/////////////////////////////////////////////////////////// // Betriebssysteme I - Windows 2000 // Assignment 3.3: An extended command shell // // author: Stephan Brumme // last changes: November 27, 2001 #include #include //////////////////////////////////////////////////////////////////// // read a single command BOOL ReadLine(const HANDLE hFile, char* buffer) { // FALSE, if error BOOL bRead; // determines end of line BOOL bCRLF = FALSE; // number of read bytes per read access (only 0 or 1 !) unsigned long nRead = 0; // total amount of read bytes unsigned long nIndex = 0; // read in command byte by byte do { // read a single byte bRead = ReadFile(hFile, &buffer[nIndex], 1, &nRead, NULL); // strip EOL if (buffer[nIndex] == 0x0D) nIndex--; if (buffer[nIndex] == 0x0A) bCRLF = TRUE; // next byte nIndex++; } while (nRead == 1 && bCRLF == FALSE); // terminate string, we moved one too far buffer[nIndex-1] = 0; // return last status return bRead; } //////////////////////////////////////////////////////////////////// // parse a string and looks for a given command // return a pointer to the parameter list // or NULL if command not found char* SearchCommand(const char* command, const char* text) { // look for command char* pReturn = strstr(text, command); // must be at the beginning of the line if (pReturn != text) return NULL; // jump to parameter list pReturn += strlen(command); // remove whitespaces while (*pReturn == ' ') pReturn++; return pReturn; } //////////////////////////////////////////////////////////////////// const MAX_HANDLES = 255; HANDLE arHandles[MAX_HANDLES]; //////////////////////////////////////////////////////////////////// // add handle to internal list // no checking ! void AddHandle(HANDLE handle) { for (int i=0; i 2) { printf("usage: \"MinShell ShellCommands.txt\"\n"); printf("or just \"MinShell\" if you want to type in the commands.\n"); // wrong parameter count return 1; } printf("Please remember that this extremely cool shell is case sensitive.\n" \ "Available internal commands:\n\n" \ "\"cd\" Directory change current directory\n" \ "\"wait\" Handle|\"all\" wait for a single process / all processes\n" \ "\"exit\" quit shell\n\n" \ "or just enter a program (+parameters) that is available through %%PATH%% !\n\n"); // file handle to access the shell commands HANDLE hFile; if (argc == 2) { // open file (read shared !) hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (hFile == INVALID_HANDLE_VALUE) { printf("Cannot find %s.\n", argv[1]); // failed return 2; } } else // read from console hFile = GetStdHandle(STD_INPUT_HANDLE); // clear HANDLE list ZeroMemory(&arHandles, sizeof arHandles); // // DA MAIN LOOP // // read and execute shell commands for (;;) { // at most 512 characters per line const int MAX_LINE_LENGTH = 512; char cmdLine[MAX_LINE_LENGTH+1]; // prompt printf("MinShell:"); // show current directoy static char strDirectory[MAX_LINE_LENGTH]; if (GetCurrentDirectory(sizeof strDirectory, strDirectory)) printf(strDirectory); printf("$ "); // read the command BOOL bDone = ReadLine(hFile, cmdLine); // error or exit ? if (cmdLine[0] == 0 || SearchCommand("exit", cmdLine)) { printf("\n... winke, winke, Lala !\n"); return 0; } // show shell command (if not typed in from console) if (hFile != GetStdHandle(STD_INPUT_HANDLE)) printf("%s\n", cmdLine); // // now the internal commands // "exit" was already handled // // "cd [directory]" if (char* directory = SearchCommand("cd", cmdLine)) { if (!ChangeDirectory(directory)) printf("Unable to change directory to \"%s\".\n", directory); // read next command continue; } // "wait" if (char* strHandle = SearchCommand("wait", cmdLine)) { // wait for all ? if (strstr(strHandle, "all")) { // take a look at each handle for (int i=0; i