227134a7e8bc0c620796718a7fb417232766f291
[reactos.git] / reactos / apps / utils / shell / shell.c
1 #include <ddk/ntddk.h>
2 #include <windows.h>
3 #include <stdarg.h>
4 #include <string.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <ctype.h>
8
9
10 HANDLE InputHandle, OutputHandle;
11 BOOL bCanExit = TRUE;
12
13
14 void debug_printf(char* fmt, ...)
15 {
16 va_list args;
17 char buffer[255];
18
19 va_start(args,fmt);
20 vsprintf(buffer,fmt,args);
21 va_end(args);
22 WriteConsoleA(OutputHandle, buffer, strlen(buffer), NULL, NULL);
23 }
24
25
26 void ExecuteVer(void)
27 {
28 debug_printf(
29 "Reactos Simple Shell\n(compiled on %s, at %s)\n",
30 __DATE__,
31 __TIME__
32 );
33 }
34
35 void ExecuteCd(char* cmdline)
36 {
37 if (!SetCurrentDirectoryA(cmdline))
38 {
39 debug_printf("Invalid directory\n");
40 }
41 }
42
43 void ExecuteDir(char* cmdline)
44 {
45 HANDLE shandle;
46 WIN32_FIND_DATA FindData;
47 int nFile=0, nRep=0;
48 FILETIME fTime;
49 SYSTEMTIME sTime;
50
51 shandle = FindFirstFile("*",&FindData);
52
53 if (shandle==INVALID_HANDLE_VALUE)
54 {
55 debug_printf("Invalid directory\n");
56 return;
57 }
58 do
59 {
60 debug_printf("%-15.15s",FindData.cAlternateFileName);
61 if(FindData.dwFileAttributes &FILE_ATTRIBUTE_DIRECTORY)
62 debug_printf("<DIR> "),nRep++;
63 else
64 debug_printf(" %10d ",FindData.nFileSizeLow),nFile++;
65
66 FileTimeToLocalFileTime(&FindData.ftLastWriteTime ,&fTime);
67 FileTimeToSystemTime(&fTime, &sTime);
68 debug_printf("%02d/%02d/%04d %02d:%02d:%02d "
69 ,sTime.wMonth,sTime.wDay,sTime.wYear
70 ,sTime.wHour,sTime.wMinute,sTime.wSecond);
71
72 debug_printf("%s\n",FindData.cFileName);
73 } while(FindNextFile(shandle,&FindData));
74 debug_printf("\n %d files\n %d directories\n\n",nFile,nRep);
75 FindClose(shandle);
76 }
77
78
79 void ExecuteReboot(char* cmdline)
80 {
81 NtShutdownSystem (ShutdownReboot);
82 }
83
84
85 void ExecuteType(char* cmdline)
86 {
87 HANDLE FileHandle;
88 char c;
89 DWORD Result;
90
91 FileHandle = CreateFile(cmdline,
92 FILE_GENERIC_READ,
93 0,
94 NULL,
95 OPEN_EXISTING,
96 0,
97 NULL);
98 if (FileHandle == NULL)
99 {
100 debug_printf("Unknown file\n");
101 return;
102 }
103 while (ReadFile(FileHandle,
104 &c,
105 1,
106 &Result,
107 NULL))
108 {
109 debug_printf("%c",c);
110 c = 0;
111 }
112 CloseHandle(FileHandle);
113 }
114
115 int ExecuteProcess(char* name, char* cmdline, BOOL detached)
116 {
117 PROCESS_INFORMATION ProcessInformation;
118 STARTUPINFO StartupInfo;
119 BOOL ret;
120
121 memset(&StartupInfo, 0, sizeof(StartupInfo));
122 StartupInfo.cb = sizeof (STARTUPINFO);
123 StartupInfo.lpTitle = name;
124
125 ret = CreateProcessA(name,
126 cmdline,
127 NULL,
128 NULL,
129 FALSE,
130 ((TRUE == detached)
131 ? DETACHED_PROCESS
132 : CREATE_NEW_CONSOLE
133 ),
134 NULL,
135 NULL,
136 & StartupInfo,
137 & ProcessInformation
138 );
139 if (TRUE == detached)
140 {
141 if (ret)
142 {
143 debug_printf("%s detached:\n"
144 "\thProcess = %08X\n"
145 "\thThread = %08X\n"
146 "\tPID = %d\n"
147 "\tTID = %d\n\n",
148 name,
149 ProcessInformation.hProcess,
150 ProcessInformation.hThread,
151 ProcessInformation.dwProcessId,
152 ProcessInformation.dwThreadId);
153 CloseHandle(ProcessInformation.hProcess);
154 CloseHandle(ProcessInformation.hThread);
155 }
156 else
157 {
158 debug_printf("Could not detach %s\n", name);
159 }
160 }
161 else
162 {
163 if (ret)
164 {
165 debug_printf("ProcessInformation.hThread %x\n",
166 ProcessInformation.hThread);
167 WaitForSingleObject(ProcessInformation.hProcess, INFINITE);
168 CloseHandle(ProcessInformation.hProcess);
169 debug_printf("Thandle %x\n", ProcessInformation.hThread);
170 CloseHandle(ProcessInformation.hThread);
171 }
172 }
173 return(ret);
174 }
175
176 void ExecuteStart(char* CommandLine)
177 {
178 char *ImageName = CommandLine;
179
180 for ( ;
181 ( (*CommandLine)
182 && (*CommandLine != ' ')
183 && (*CommandLine != '\t')
184 );
185 CommandLine++
186 );
187 *CommandLine++ = '\0';
188 while ( (*CommandLine)
189 && ( (*CommandLine == ' ')
190 || (*CommandLine == '\t')
191 )
192 );
193 ExecuteProcess(
194 ImageName,
195 CommandLine,
196 TRUE
197 );
198 return;
199 }
200
201 void
202 ExecuteKill(char * lpPid)
203 {
204 HANDLE hProcess;
205 DWORD dwProcessId;
206
207 dwProcessId = (DWORD) atol(lpPid);
208 debug_printf("dwProcessId %d\n",dwProcessId);
209 hProcess = OpenProcess(
210 PROCESS_TERMINATE,
211 FALSE,
212 dwProcessId
213 );
214 if (NULL == hProcess)
215 {
216 debug_printf(
217 "Could not open the process with PID = %d\n",
218 dwProcessId
219 );
220 return;
221 }
222 if (FALSE == TerminateProcess(
223 hProcess,
224 0
225 )
226 ) {
227 debug_printf(
228 "Could not terminate the process with PID = %d\n",
229 dwProcessId
230 );
231 }
232 CloseHandle(hProcess);
233 return;
234 }
235
236 void ExecuteCommand(char* line)
237 {
238 char* cmd;
239 char* tail;
240
241 if (isalpha(line[0]) && line[1] == ':' && line[2] == 0)
242 {
243 //#if 0
244 char szPath[MAX_PATH];
245 char szVar[5];
246
247 /* save curent directory in environment variable */
248 GetCurrentDirectory (MAX_PATH, szPath);
249
250 strcpy (szVar, "=A:");
251 szVar[1] = toupper (szPath[0]);
252 SetEnvironmentVariable (szVar, szPath);
253
254 /* check for current directory of new drive */
255 strcpy (szVar, "=A:");
256 szVar[1] = toupper (line[0]);
257 if (GetEnvironmentVariable (szVar, szPath, MAX_PATH) == 0)
258 {
259 /* no environment variable found */
260 strcpy (szPath, "A:\\");
261 szPath[0] = toupper (line[0]);
262 }
263
264 /* set new current directory */
265 SetCurrentDirectory (szPath);
266 GetCurrentDirectory (MAX_PATH, szPath);
267 if (szPath[0] != (char)toupper (line[0]))
268 debug_printf("Invalid drive\n");
269 //#endif
270 #if 0
271 line[0] = toupper (line[0]);
272 line[2] = '\\';
273 line[3] = 0;
274 if (SetCurrentDirectoryA(line) == FALSE)
275 debug_printf("Invalid drive\n");
276 #endif
277
278 return;
279 }
280
281 tail = line;
282 while ((*tail)!=' ' && (*tail)!=0)
283 {
284 tail++;
285 }
286 if ((*tail)==' ')
287 {
288 *tail = 0;
289 tail++;
290 }
291 cmd = line;
292
293
294 if (cmd==NULL || *cmd == '\0' )
295 {
296 return;
297 }
298 if (strcmp(cmd,"cd")==0)
299 {
300 ExecuteCd(tail);
301 return;
302 }
303 if (strcmp(cmd,"dir")==0)
304 {
305 ExecuteDir(tail);
306 return;
307 }
308 if (strcmp(cmd,"kill")==0)
309 {
310 ExecuteKill(tail);
311 return;
312 }
313 if (strcmp(cmd,"reboot")==0)
314 {
315 ExecuteReboot(tail);
316 return;
317 }
318 if (strcmp(cmd,"type")==0)
319 {
320 ExecuteType(tail);
321 return;
322 }
323 if (strcmp(cmd,"ver")==0)
324 {
325 ExecuteVer();
326 return;
327 }
328 if (strcmp(cmd,"validate")==0)
329 {
330 debug_printf("Validating heap...");
331 if (HeapValidate(GetProcessHeap(),0,NULL))
332 {
333 debug_printf("succeeded\n");
334 }
335 else
336 {
337 debug_printf("failed\n");
338 }
339 return;
340 }
341 if (strcmp(cmd,"start") == 0)
342 {
343 ExecuteStart(tail);
344 return;
345 }
346 if (strcmp(cmd,"exit")==0)
347 {
348 if (bCanExit == TRUE)
349 {
350 ExitProcess(0);
351 }
352 return;
353 }
354 if (ExecuteProcess(cmd,tail,FALSE))
355 {
356 return;
357 }
358 debug_printf("Unknown command\n");
359 }
360
361 void ReadLine(char* line)
362 {
363 DWORD Result;
364 UCHAR CurrentDir[255];
365 char ch;
366 int length = 0;
367
368 GetCurrentDirectoryA(255,CurrentDir);
369 debug_printf("%s>", CurrentDir);
370
371 do
372 {
373 if (!ReadConsoleA(InputHandle,
374 &ch,
375 1,
376 &Result,
377 NULL))
378 {
379 debug_printf("Failed to read from console\n");
380 for(;;);
381 }
382 switch (ch)
383 {
384 case '\b':
385 if (length > 0)
386 {
387 debug_printf("\b \b");
388 line--;
389 length--;
390 }
391 break;
392
393 default:
394 debug_printf("%c", ch);
395 *line = ch;
396 line++;
397 length++;
398 }
399 } while (ch != '\n');
400 line--;
401 *line = 0;
402 }
403
404 void ParseCommandLine (void)
405 {
406 char *pszCommandLine;
407
408 pszCommandLine = GetCommandLineA ();
409 _strupr (pszCommandLine);
410 if (strstr (pszCommandLine, "/P") != NULL)
411 {
412 debug_printf("Permanent shell\n");
413 bCanExit = FALSE;
414 }
415 }
416
417 int main(void)
418 {
419 static char line[255];
420
421 AllocConsole();
422 InputHandle = GetStdHandle(STD_INPUT_HANDLE);
423 OutputHandle = GetStdHandle(STD_OUTPUT_HANDLE);
424
425 debug_printf("Shell Starting...\n");
426
427 ParseCommandLine ();
428 // SetCurrentDirectoryA("C:\\");
429
430 for(;;)
431 {
432 ReadLine(line);
433 ExecuteCommand(line);
434 }
435
436 return 0;
437 }
438