Home | Info | Community | Development | myReactOS | Contact Us
ReactOS Development > Doxygeninternal.c
Go to the documentation of this file.
00001 /* 00002 * INTERNAL.C - command.com internal commands. 00003 * 00004 * 00005 * History: 00006 * 00007 * 17/08/94 (Tim Norman) 00008 * started. 00009 * 00010 * 08/08/95 (Matt Rains) 00011 * i have cleaned up the source code. changes now bring this source into 00012 * guidelines for recommended programming practice. 00013 * 00014 * cd() 00015 * started. 00016 * 00017 * dir() 00018 * i have added support for file attributes to the DIR() function. the 00019 * routine adds "d" (directory) and "r" (read only) output. files with the 00020 * system attribute have the filename converted to lowercase. files with 00021 * the hidden attribute are not displayed. 00022 * 00023 * i have added support for directorys. now if the directory attribute is 00024 * detected the file size if replaced with the string "<dir>". 00025 * 00026 * ver() 00027 * started. 00028 * 00029 * md() 00030 * started. 00031 * 00032 * rd() 00033 * started. 00034 * 00035 * del() 00036 * started. 00037 * 00038 * does not support wildcard selection. 00039 * 00040 * todo: add delete directory support. 00041 * add recursive directory delete support. 00042 * 00043 * ren() 00044 * started. 00045 * 00046 * does not support wildcard selection. 00047 * 00048 * todo: add rename directory support. 00049 * 00050 * a general structure has been used for the cd, rd and md commands. this 00051 * will be better in the long run. it is too hard to maintain such diverse 00052 * functions when you are involved in a group project like this. 00053 * 00054 * 12/14/95 (Tim Norman) 00055 * fixed DIR so that it will stick \*.* if a directory is specified and 00056 * that it will stick on .* if a file with no extension is specified or 00057 * *.* if it ends in a \ 00058 * 00059 * 1/6/96 (Tim Norman) 00060 * added an isatty call to DIR so it won't prompt for keypresses unless 00061 * stdin and stdout are the console. 00062 * 00063 * changed parameters to be mutually consistent to make calling the 00064 * functions easier 00065 * 00066 * rem() 00067 * started. 00068 * 00069 * doskey() 00070 * started. 00071 * 00072 * 01/22/96 (Oliver Mueller) 00073 * error messages are now handled by perror. 00074 * 00075 * 02/05/96 (Tim Norman) 00076 * converted all functions to accept first/rest parameters 00077 * 00078 * 07/26/96 (Tim Norman) 00079 * changed return values to int instead of void 00080 * 00081 * path() started. 00082 * 00083 * 12/23/96 (Aaron Kaufman) 00084 * rewrote dir() to mimic MS-DOS's dir 00085 * 00086 * 01/28/97 (Tim Norman) 00087 * cleaned up Aaron's DIR code 00088 * 00089 * 06/13/97 (Tim Norman) 00090 * moved DIR code to dir.c 00091 * re-implemented Aaron's DIR code 00092 * 00093 * 06/14/97 (Steffan Kaiser) 00094 * ctrl-break handling 00095 * bug fixes 00096 * 00097 * 27-Jul-1998 (John P Price <linux-guru@gcfl.net>) 00098 * added config.h include 00099 * 00100 * 03-Dec-1998 (Eric Kohl) 00101 * Replaced DOS calls by Win32 calls. 00102 * 00103 * 08-Dec-1998 (Eric Kohl) 00104 * Added help texts ("/?"). 00105 * 00106 * 18-Dec-1998 (Eric Kohl) 00107 * Added support for quoted arguments (cd "program files"). 00108 * 00109 * 07-Jan-1999 (Eric Kohl) 00110 * Clean up. 00111 * 00112 * 26-Jan-1999 (Eric Kohl) 00113 * Replaced remaining CRT io functions by Win32 io functions. 00114 * Unicode safe! 00115 * 00116 * 30-Jan-1999 (Eric Kohl) 00117 * Added "cd -" feature. Changes to the previous directory. 00118 * 00119 * 15-Mar-1999 (Eric Kohl) 00120 * Fixed bug in "cd -" feature. If the previous directory was a root 00121 * directory, it was ignored. 00122 * 00123 * 23-Feb-2001 (Carl Nettelblad <cnettel@hem.passagen.se>) 00124 * Improved chdir/cd command. 00125 * 00126 * 02-Apr-2004 (Magnus Olsen <magnus@greatlord.com>) 00127 * Remove all hard code string so they can be 00128 * translate to other langues. 00129 * 00130 * 19-Jul-2005 (Brandon Turner <turnerb7@msu.edu>) 00131 * Rewrite the CD, it working as Windows 2000 CMD 00132 * 00133 * 19-Jul-2005 (Magnus Olsen <magnus@greatlord.com>) 00134 * Add SetRootPath and GetRootPath 00135 * 00136 * 14-Jul-2007 (Pierre Schweitzer <heis_spiter@hotmail.com>) 00137 * Added commands help display to help command (ex. : "help cmd") 00138 */ 00139 00140 #include <precomp.h> 00141 00142 #ifdef INCLUDE_CMD_CHDIR 00143 00144 /* help functions for getting current path from drive 00145 without changing drive. Return code 0 = ok, 1 = fail. 00146 INT GetRootPath("C:",outbuffer,chater size of outbuffer); 00147 the first param can have any size, if the the two frist 00148 letter are not a drive with : it will get Currentpath on 00149 current drive exacly as GetCurrentDirectory does. 00150 */ 00151 00152 INT GetRootPath(TCHAR *InPath,TCHAR *OutPath,INT size) 00153 { 00154 if (InPath[0] && InPath[1] == _T(':')) 00155 { 00156 INT t=0; 00157 00158 if ((InPath[0] >= _T('0')) && (InPath[0] <= _T('9'))) 00159 { 00160 t = (InPath[0] - _T('0')) +28; 00161 } 00162 00163 if ((InPath[0] >= _T('a')) && (InPath[0] <= _T('z'))) 00164 { 00165 t = (InPath[0] - _T('a')) +1; 00166 InPath[0] = t + _T('A') - 1; 00167 } 00168 00169 if ((InPath[0] >= _T('A')) && (InPath[0] <= _T('Z'))) 00170 { 00171 t = (InPath[0] - _T('A')) +1; 00172 } 00173 00174 return _tgetdcwd(t,OutPath,size) == NULL; 00175 } 00176 00177 /* Get current directory */ 00178 return !GetCurrentDirectory(size,OutPath); 00179 } 00180 00181 00182 BOOL SetRootPath(TCHAR *oldpath, TCHAR *InPath) 00183 { 00184 TCHAR OutPath[MAX_PATH]; 00185 TCHAR OutPathTemp[MAX_PATH]; 00186 00187 /* The use of both of these together will correct the case of a path 00188 where as one alone or GetFullPath will not. Exameple: 00189 c:\windows\SYSTEM32 => C:\WINDOWS\system32 */ 00190 if (GetFullPathName(InPath, MAX_PATH, OutPathTemp, NULL)) 00191 { 00192 GetPathCase(OutPathTemp, OutPath); 00193 00194 /* Use _tchdir, since unlike SetCurrentDirectory it updates 00195 * the current-directory-on-drive environment variables. */ 00196 if (_tchdir(OutPath) != 0) 00197 { 00198 ConErrFormatMessage(GetLastError()); 00199 nErrorLevel = 1; 00200 return FALSE; 00201 } 00202 00203 /* Keep original drive in ordinary CD/CHDIR (without /D switch). */ 00204 if (oldpath != NULL && _tcsncicmp(OutPath, oldpath, 2) != 0) 00205 SetCurrentDirectory(oldpath); 00206 } 00207 00208 return TRUE; 00209 } 00210 00211 00212 /* 00213 * CD / CHDIR 00214 * 00215 */ 00216 INT cmd_chdir (LPTSTR param) 00217 { 00218 TCHAR szCurrent[MAX_PATH]; 00219 BOOL bChangeDrive = FALSE; 00220 00221 /* Filter out special cases first */ 00222 00223 /* Print Help */ 00224 if (!_tcsncmp(param, _T("/?"), 2)) 00225 { 00226 ConOutResPaging(TRUE,STRING_CD_HELP); 00227 return 0; 00228 } 00229 00230 /* Remove " */ 00231 StripQuotes(param); 00232 00233 /* Set Error Level to Success */ 00234 nErrorLevel = 0; 00235 00236 /* Print Current Directory on a disk */ 00237 if (_tcslen(param) == 2 && param[1] == _T(':')) 00238 { 00239 if (GetRootPath(param, szCurrent, MAX_PATH)) 00240 { 00241 error_invalid_drive(); 00242 return 1; 00243 } 00244 ConOutPuts(szCurrent); 00245 return 0; 00246 } 00247 00248 /* Get Current Directory */ 00249 GetCurrentDirectory(MAX_PATH, szCurrent); 00250 if (param[0] == _T('\0')) 00251 { 00252 ConOutPuts(szCurrent); 00253 return 0; 00254 } 00255 00256 /* Input String Contains /D Switch */ 00257 if (!_tcsncicmp(param, _T("/D"), 2)) 00258 { 00259 bChangeDrive = TRUE; 00260 param += 2; 00261 while (_istspace(*param)) 00262 param++; 00263 } 00264 00265 if (!SetRootPath(bChangeDrive ? NULL : szCurrent, param)) 00266 return 1; 00267 00268 return 0; 00269 } 00270 00271 #endif 00272 00273 00274 00275 #ifdef INCLUDE_CMD_MKDIR 00276 00277 /* Helper funtion for mkdir to make directories in a path. 00278 Dont use the api to decrease depence on libs */ 00279 BOOL 00280 MakeFullPath(TCHAR * DirPath) 00281 { 00282 TCHAR path[MAX_PATH]; 00283 TCHAR *p = DirPath; 00284 INT_PTR n; 00285 00286 if (CreateDirectory(DirPath, NULL)) 00287 return TRUE; 00288 else if (GetLastError() != ERROR_PATH_NOT_FOUND) 00289 return FALSE; 00290 00291 /* got ERROR_PATH_NOT_FOUND, so try building it up one component at a time */ 00292 if (p[0] && p[1] == _T(':')) 00293 p += 2; 00294 while (*p == _T('\\')) 00295 p++; /* skip drive root */ 00296 do 00297 { 00298 p = _tcschr(p, _T('\\')); 00299 n = p ? p++ - DirPath : _tcslen(DirPath); 00300 _tcsncpy(path, DirPath, n); 00301 path[n] = _T('\0'); 00302 if( !CreateDirectory(path, NULL) && 00303 (GetLastError() != ERROR_ALREADY_EXISTS)) 00304 return FALSE; 00305 } while (p != NULL); 00306 00307 return TRUE; 00308 } 00309 00310 /* 00311 * MD / MKDIR 00312 * 00313 */ 00314 INT cmd_mkdir (LPTSTR param) 00315 { 00316 LPTSTR *p; 00317 INT argc, i; 00318 if (!_tcsncmp (param, _T("/?"), 2)) 00319 { 00320 ConOutResPaging(TRUE,STRING_MKDIR_HELP); 00321 return 0; 00322 } 00323 00324 p = split (param, &argc, FALSE, FALSE); 00325 if (argc == 0) 00326 { 00327 ConErrResPuts(STRING_ERROR_REQ_PARAM_MISSING); 00328 nErrorLevel = 1; 00329 freep(p); 00330 return 1; 00331 } 00332 00333 nErrorLevel = 0; 00334 for (i = 0; i < argc; i++) 00335 { 00336 if (!MakeFullPath(p[i])) 00337 { 00338 if(GetLastError() == ERROR_PATH_NOT_FOUND) 00339 { 00340 ConErrResPuts(STRING_MD_ERROR2); 00341 } 00342 else 00343 { 00344 ErrorMessage (GetLastError(), _T("MD")); 00345 } 00346 nErrorLevel = 1; 00347 } 00348 } 00349 00350 freep (p); 00351 return nErrorLevel; 00352 } 00353 #endif 00354 00355 00356 #ifdef INCLUDE_CMD_RMDIR 00357 /* 00358 * RD / RMDIR 00359 * 00360 */ 00361 BOOL DeleteFolder(LPTSTR FileName) 00362 { 00363 TCHAR Base[MAX_PATH]; 00364 TCHAR TempFileName[MAX_PATH]; 00365 HANDLE hFile; 00366 WIN32_FIND_DATA f; 00367 _tcscpy(Base,FileName); 00368 _tcscat(Base,_T("\\*")); 00369 hFile = FindFirstFile(Base, &f); 00370 Base[_tcslen(Base) - 1] = _T('\0'); 00371 if (hFile != INVALID_HANDLE_VALUE) 00372 { 00373 do 00374 { 00375 if (!_tcscmp(f.cFileName, _T(".")) || 00376 !_tcscmp(f.cFileName, _T(".."))) 00377 continue; 00378 _tcscpy(TempFileName,Base); 00379 _tcscat(TempFileName,f.cFileName); 00380 00381 if(f.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) 00382 DeleteFolder(TempFileName); 00383 else 00384 { 00385 SetFileAttributes(TempFileName,FILE_ATTRIBUTE_NORMAL); 00386 if(!DeleteFile(TempFileName)) 00387 return 0; 00388 } 00389 00390 }while (FindNextFile (hFile, &f)); 00391 FindClose (hFile); 00392 } 00393 return RemoveDirectory(FileName); 00394 } 00395 INT cmd_rmdir (LPTSTR param) 00396 { 00397 TCHAR ch; 00398 INT args; 00399 INT dirCount; 00400 LPTSTR *arg; 00401 INT i; 00402 BOOL RD_SUB = FALSE; 00403 BOOL RD_QUIET = FALSE; 00404 INT res; 00405 INT nError = 0; 00406 TCHAR szFullPath[MAX_PATH]; 00407 00408 if (!_tcsncmp (param, _T("/?"), 2)) 00409 { 00410 ConOutResPaging(TRUE,STRING_RMDIR_HELP); 00411 return 0; 00412 } 00413 00414 arg = split (param, &args, FALSE, FALSE); 00415 dirCount = 0; 00416 00417 /* check for options anywhere in command line */ 00418 for (i = 0; i < args; i++) 00419 { 00420 if (*arg[i] == _T('/')) 00421 { 00422 /*found a command, but check to make sure it has something after it*/ 00423 if (_tcslen (arg[i]) == 2) 00424 { 00425 ch = _totupper (arg[i][1]); 00426 00427 if (ch == _T('S')) 00428 { 00429 RD_SUB = TRUE; 00430 } 00431 else if (ch == _T('Q')) 00432 { 00433 RD_QUIET = TRUE; 00434 } 00435 } 00436 } 00437 else 00438 { 00439 dirCount++; 00440 } 00441 } 00442 00443 if (dirCount == 0) 00444 { 00445 /* No folder to remove */ 00446 error_req_param_missing(); 00447 freep(arg); 00448 return 1; 00449 } 00450 00451 for (i = 0; i < args; i++) 00452 { 00453 if (*arg[i] == _T('/')) 00454 continue; 00455 00456 if (RD_SUB) 00457 { 00458 /* ask if they want to delete evrything in the folder */ 00459 if (!RD_QUIET) 00460 { 00461 res = FilePromptYNA (STRING_DEL_HELP2); 00462 if (res == PROMPT_NO || res == PROMPT_BREAK) 00463 { 00464 nError = 1; 00465 continue; 00466 } 00467 if (res == PROMPT_ALL) 00468 RD_QUIET = TRUE; 00469 } 00470 /* get the folder name */ 00471 GetFullPathName(arg[i],MAX_PATH,szFullPath,NULL); 00472 00473 /* remove trailing \ if any, but ONLY if dir is not the root dir */ 00474 if (_tcslen (szFullPath) >= 2 && szFullPath[_tcslen (szFullPath) - 1] == _T('\\')) 00475 szFullPath[_tcslen(szFullPath) - 1] = _T('\0'); 00476 00477 res = DeleteFolder(szFullPath); 00478 } 00479 else 00480 { 00481 res = RemoveDirectory(arg[i]); 00482 } 00483 00484 if (!res) 00485 { 00486 /* Couldn't delete the folder, print out the error */ 00487 nError = GetLastError(); 00488 ErrorMessage(nError, _T("RD")); 00489 } 00490 } 00491 00492 freep (arg); 00493 return nError; 00494 } 00495 #endif 00496 00497 00498 /* 00499 * set the exitflag to true 00500 * 00501 */ 00502 INT CommandExit (LPTSTR param) 00503 { 00504 if (!_tcsncmp (param, _T("/?"), 2)) 00505 { 00506 ConOutResPaging(TRUE,STRING_EXIT_HELP); 00507 /* Just make sure */ 00508 bExit = FALSE; 00509 /* Dont exit */ 00510 return 0; 00511 } 00512 00513 if (bc != NULL && _tcsnicmp(param,_T("/b"),2) == 0) 00514 { 00515 param += 2; 00516 while (_istspace (*param)) 00517 param++; 00518 if (_istdigit(*param)) 00519 nErrorLevel = _ttoi(param); 00520 ExitBatch(); 00521 } 00522 00523 else 00524 bExit = TRUE; 00525 00526 00527 return 0; 00528 00529 } 00530 00531 #ifdef INCLUDE_CMD_REM 00532 /* 00533 * does nothing 00534 * 00535 */ 00536 INT CommandRem (LPTSTR param) 00537 { 00538 if (!_tcsncmp (param, _T("/?"), 2)) 00539 { 00540 ConOutResPaging(TRUE,STRING_REM_HELP); 00541 } 00542 00543 return 0; 00544 } 00545 #endif /* INCLUDE_CMD_REM */ 00546 00547 00548 INT CommandShowCommands (LPTSTR param) 00549 { 00550 PrintCommandList (); 00551 return 0; 00552 } 00553 00554 INT CommandShowCommandsDetail (LPTSTR param) 00555 { 00556 /* If a param was send, display help of correspondent command */ 00557 if (_tcslen(param)) 00558 { 00559 DoCommand(param, _T("/?"), NULL); 00560 } 00561 /* Else, display detailed commands list */ 00562 else 00563 { 00564 PrintCommandListDetail (); 00565 } 00566 return 0; 00567 } 00568 00569 /* EOF */ Generated on Sat May 26 2012 04:17:03 for ReactOS by
1.7.6.1
|