sources:
MinShell2.cpp (8.1k)


binaries:
Release/minshell2.exe (5.0k)
Release/script.txt (45 bytes)


website:
more info here


screenshot:
studies/betriebssysteme/Betriebssysteme-Code3/MinShell2.cpp
download file

  1 ///////////////////////////////////////////////////////////
  2 // Betriebssysteme I - Windows 2000
  3 // Assignment 3.3: An extended command shell
  4 //
  5 // author: Stephan Brumme
  6 // last changes: November 27, 2001
  7
  8 #include <windows.h>
  9 #include <stdio.h>
 10
 11
 12 ////////////////////////////////////////////////////////////////////
 13 // read a single command
 14 BOOL ReadLine(const HANDLE hFile, char* buffer)
 15 {
 16     // FALSE, if error
 17     BOOL bRead;
 18     // determines end of line
 19     BOOL bCRLF = FALSE;
 20     // number of read bytes per read access (only 0 or 1 !)
 21     unsigned long nRead  = 0;
 22     // total amount of read bytes
 23     unsigned long nIndex = 0;
 24
 25     // read in command byte by byte
 26     do     {
 27         // read a single byte
 28         bRead = ReadFile(hFile, &buffer[nIndex], 1, &nRead, NULL);
 29         // strip EOL
 30         if (buffer[nIndex] == 0x0D)
 31             nIndex--;
 32         if (buffer[nIndex] == 0x0A)
 33             bCRLF = TRUE;
 34
 35         // next byte
 36         nIndex++;
 37     }
 38     while (nRead == 1 && bCRLF == FALSE);
 39
 40     // terminate string, we moved one too far
 41     buffer[nIndex-1] = 0;
 42
 43     // return last status
 44     return bRead;
 45 }
 46
 47
 48 ////////////////////////////////////////////////////////////////////
 49 // parse a string and looks for a given command
 50 // return a pointer to the parameter list
 51 // or NULL if command not found
 52 char* SearchCommand(const char* command, const char* text)
 53 {
 54     // look for command
 55     char* pReturn = strstr(text, command);
 56     // must be at the beginning of the line
 57     if (pReturn != text)
 58         return NULL;
 59
 60     // jump to parameter list
 61     pReturn += strlen(command);
 62
 63     // remove whitespaces
 64     while (*pReturn == ' ')
 65         pReturn++;
 66
 67     return pReturn;
 68 }
 69
 70
 71 ////////////////////////////////////////////////////////////////////
 72 const MAX_HANDLES = 255;
 73 HANDLE arHandles[MAX_HANDLES];
 74
 75 ////////////////////////////////////////////////////////////////////
 76 // add handle to internal list
 77 // no checking !
 78 void AddHandle(HANDLE handle)
 79 {
 80     for (int i=0; i<MAX_HANDLES; i++)
 81         if (arHandles[i] == 0)
 82         {
 83             arHandles[i] = handle;
 84             break;
 85         }
 86 }
 87
 88
 89 ////////////////////////////////////////////////////////////////////
 90 // remove handle from internal list
 91 // no checking !
 92 void RemoveHandle(HANDLE handle)
 93 {
 94     for (int i=0; i<MAX_HANDLES; i++)
 95         if (arHandles[i] == handle)
 96         {
 97             arHandles[i] = 0;
 98             break;
 99         }
100 }
101
102
103 ////////////////////////////////////////////////////////////////////
104 // change directory
105 // return TRUE if successful
106 BOOL ChangeDirectory(const char* dir)
107 {
108     return SetCurrentDirectory(dir);
109 }
110
111
112 ////////////////////////////////////////////////////////////////////
113 // wait for a single process
114 // return TRUE if successful
115 BOOL Wait(HANDLE hProcess)
116 {
117     printf("... waiting for %d ...\n", hProcess);
118
119     // wait for Godot
120     DWORD dwResult = WaitForSingleObject(hProcess, INFINITE);
121     CloseHandle(hProcess);
122
123     // remove handle from list
124     RemoveHandle(hProcess);
125
126     return (dwResult != WAIT_FAILED);
127 }
128
129
130 ////////////////////////////////////////////////////////////////////
131 // create a new process
132 BOOL NewProcess(char* name, BOOL bWait = TRUE)
133 {
134     // fill in start-up info values
135     STARTUPINFO StartupInfo;
136     ZeroMemory(&StartupInfo, sizeof StartupInfo);
137     StartupInfo.cb = sizeof StartupInfo;
138
139     // CreateProcess returns some process information
140     PROCESS_INFORMATION ProcessInfo;
141     ZeroMemory(&ProcessInfo, sizeof ProcessInfo);
142
143     if (CreateProcess(NULL,     // application name is first token of the command line
144                       name,     // contains application name, too
145                       NULL,     // default process security settings
146                       NULL,     // default thread security settings
147                       FALSE,    // process DOES NOT inherit from minshell.exe
148                       0,        // child has no access to minshell.exe
149                       NULL,     // no special environment
150                       NULL,     // same directory
151                       &StartupInfo,
152                       &ProcessInfo)
== 0)

153     {
154         // error handling
155         const int MAX_ERROR_LEN = 255;
156         char strError[MAX_ERROR_LEN+1];
157
158         DWORD nError = GetLastError();
159         FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
160                       NULL,
161                       nError,
162                       0,
163                       strError,
164                       MAX_ERROR_LEN,
165                       NULL)
;
166
167         printf("Failed to create \"%s===>\<===": (%d) %s\n", name, nError, strError);
168
169         return FALSE;
170     }
171
172     printf("\"%s===>\<===" (PID: %d, handle: %d) started ", name, ProcessInfo.dwProcessId,
173                                                           ProcessInfo.hProcess)
;
174
175     // wait until process terminates and clean up
176     if (bWait == TRUE)
177     {
178         printf("synchronously\n");
179
180         // wait
181         WaitForSingleObject(ProcessInfo.hProcess, INFINITE);
182
183         CloseHandle(ProcessInfo.hProcess);
184         CloseHandle(ProcessInfo.hThread);
185     }
186     else     {
187         printf("asynchronously\n");
188         CloseHandle(ProcessInfo.hThread);
189
190         // store handle
191         AddHandle(ProcessInfo.hProcess);
192     }
193
194     return TRUE;
195 }
196
197
198
199 ////////////////////////////////////////////////////////////////////
200 ////////////////////////////////////////////////////////////////////
201 ////////////////////////////////////////////////////////////////////
202 // here we go !
203
204 int main(int argc, char* argv[])
205 {
206     // a shell command file must be supplied
207     if (argc > 2)
208     {
209         printf("usage: \"MinShell ShellCommands.txt===>\<==="\n");
210         printf("or just \"MinShell===>\<===" if you want to type in the commands.\n");
211
212         // wrong parameter count
213         return 1;
214     }
215     printf("Please remember that this extremely cool shell is case sensitive.\n"    ===>\<===
216            "Available internal commands:\n\n"                                        ===>\<===
217            "\"cd===>\<===" Directory change current directory\n"                    ===>\<===
218            "\"wait===>\<===" Handle|\"all===>\<===" wait for a single process / all processes\n"    ===>\<===
219            "\"exit===>\<===" quit shell\n\n"                                ===>\<===
220            "or just enter a program (+parameters) that is available through %%PATH%% !\n\n")
;
221  
222     // file handle to access the shell commands
223     HANDLE hFile;
224
225     if (argc == 2)
226     {
227         // open file (read shared !)
228         hFile = CreateFile(argv[1], GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL);
229         if (hFile == INVALID_HANDLE_VALUE)
230         {
231             printf("Cannot find %s.\n", argv[1]);
232             // failed
233             return 2;
234         }
235     }
236     else         // read from console
237         hFile = GetStdHandle(STD_INPUT_HANDLE);
238
239     // clear HANDLE list
240     ZeroMemory(&arHandles, sizeof arHandles);
241
242
243     //
244     // DA MAIN LOOP
245     //
246
247     // read and execute shell commands
248     for (;;)
249     {
250         // at most 512 characters per line
251         const int MAX_LINE_LENGTH = 512;
252         char  cmdLine[MAX_LINE_LENGTH+1];
253
254         // prompt
255         printf("MinShell:");
256         // show current directoy
257         static char strDirectory[MAX_LINE_LENGTH];
258         if (GetCurrentDirectory(sizeof strDirectory, strDirectory))
259             printf(strDirectory);
260         printf("$ ");
261
262
263         // read the command
264         BOOL bDone = ReadLine(hFile, cmdLine);
265
266         // error or exit ?
267         if (cmdLine[0] == 0 || SearchCommand("exit", cmdLine))
268         {
269             printf("\n... winke, winke, Lala !\n");
270             return 0;
271         }
272
273         // show shell command (if not typed in from console)
274         if (hFile != GetStdHandle(STD_INPUT_HANDLE))
275             printf("%s\n", cmdLine);
276
277         //
278         // now the internal commands
279         // "exit" was already handled
280         //
281
282         // "cd [directory]"
283         if (char* directory = SearchCommand("cd", cmdLine))
284         {
285             if (!ChangeDirectory(directory))
286                 printf("Unable to change directory to \"%s===>\<===".\n", directory);
287             // read next command
288             continue;
289         }
290
291         // "wait"
292         if (char* strHandle = SearchCommand("wait", cmdLine))
293         {
294             // wait for all ?
295             if (strstr(strHandle, "all"))
296             {
297                 // take a look at each handle
298                 for (int i=0; i<MAX_HANDLES; i++)
299                     if (arHandles[i] != 0)
300                         // wait and remove from list
301                         Wait(arHandles[i]);
302             }
303             else             {
304                 // get numerical value
305                 HANDLE dwHandle = (HANDLE) atoi(strHandle);
306                 // wait and wait and wait ...
307                 if (!Wait(dwHandle))
308                     printf("Unable to use handle %d (converted from %s).\n", dwHandle, strHandle);
309             }
310            
311             // read next command
312             continue;
313         }
314
315            
316         //
317         // no internal command found ? let's try to launch new process !
318         //
319         if (cmdLine[strlen(cmdLine)-1] == '&')
320         {
321             // remove ampersand
322             cmdLine[strlen(cmdLine)-1] = 0;
323             // launch synchronously
324             NewProcess(cmdLine, FALSE);
325         }
326         else             // launch asynchronously
327             NewProcess(cmdLine, TRUE);
328     }
329
330     CloseHandle(hFile);
331
332     // successful
333     return 0;
334 }
335