/*++ Copyright (c) 1988-1999 Microsoft Corporation Module Name: cinit.c Abstract: Initialization --*/ #include "cmd.h" #if CMD_DEBUG_ENABLE unsigned DebGroup=0; unsigned DebLevel=0; #endif TCHAR CurDrvDir[MAX_PATH] ; /* Current drive and directory */ BOOL SingleBatchInvocation = FALSE ; BOOL SingleCommandInvocation = FALSE; BOOLEAN fDisableUNCCheck = FALSE; int cmdfound = -1; /* @@5 - command found index */ int cpyfirst = TRUE; /* @@5 - flag to ctrl DOSQFILEMODE calls */ int cpydflag = FALSE; /* @@5 - flag save dirflag from las DQFMDE*/ int cpydest = FALSE; /* @@6 - flag to not display bad dev msg */ int cdevfail = FALSE; /* @@7 - flag to not display extra emsg */ #ifdef UNICODE BOOLEAN fOutputUnicode = FALSE;/* Unicode/Ansi output */ #endif // UNICODE BOOLEAN fEnableExtensions = FALSE; BOOLEAN fDefaultExtensions = TRUE; BOOLEAN fDelayedExpansion = FALSE; BOOLEAN ReportDelayLoadErrors = TRUE; unsigned tywild = 0; /* flag to tell if wild type args @@5 @J1 */ int array_size = 0 ; /* original array size is zero */ CPINFO CurrentCPInfo; UINT CurrentCP; WORD wDefaultColor = 0; // default is whatever console currently has // but default can be overriden by the registry. TCHAR chCompletionCtrl = SPACE; // Default is no completion (must be Ctrl character) TCHAR chPathCompletionCtrl = SPACE; VOID InitLocale( VOID ); extern TCHAR ComSpec[], ComSpecStr[] ; /* M021 */ extern TCHAR PathStr[], PCSwitch, SCSwitch, PromptStr[] ; extern TCHAR PathExtStr[], PathExtDefaultStr[]; extern TCHAR BCSwitch ; /* @@ */ extern TCHAR QCSwitch ; /* @@dv */ extern TCHAR UCSwitch; extern TCHAR ACSwitch; extern TCHAR XCSwitch; extern TCHAR YCSwitch; extern TCHAR DevNul[], VolSrch[] ; /* M021 - To set PathChar */ extern TCHAR SwitChar, PathChar ; /* M000 - Made non-settable */ extern int Necho ; /* @@dv - true if /Q for no echo */ extern TCHAR MsgBuf[]; extern struct envdata CmdEnv; extern struct envdata * penvOrig; struct envdata OrigEnv; extern TCHAR TmpBuf[] ; /* M034 */ extern TCHAR ComSpec[]; TCHAR *CmdSpec = &ComSpec[1]; /* M033 */ extern unsigned DosErr ; /* D64 */ // // TRUE if the ctrl-c thread has been run. // BOOL CtrlCSeen; // // Set TRUE when it is ok the print a control-c. // If we are waiting for another process this will be // FALSE BOOLEAN fPrintCtrlC = TRUE; // // console mode at program startup time. Used to reset mode // after running another process. // DWORD dwCurInputConMode; DWORD dwCurOutputConMode; // // Initial Title. Used for restoration on abort etc. // MAX_PATH was arbitrary // PTCHAR pszTitleCur; PTCHAR pszTitleOrg; BOOLEAN fTitleChanged = FALSE; // title has been changed and needs to be reset // // used to gate access to ctrlcseen flag between ctrl-c thread // and main thread // CRITICAL_SECTION CtrlCSection; LPCRITICAL_SECTION lpcritCtrlC; // // Used to set and reset ctlcseen flag // VOID SetCtrlC(); VOID ResetCtrlC(); Handler( IN ULONG CtrlType ) { if ( (CtrlType == CTRL_C_EVENT) || (CtrlType == CTRL_BREAK_EVENT) ) { // // Note that we had a ^C event // SetCtrlC(); // // Display the ^C if we are enabled and if we're not in a batch file // if (fPrintCtrlC && CurrentBatchFile != NULL) { fprintf( stderr, "^C" ); fflush( stderr ); } return TRUE; } else { return FALSE; } } /********************* START OF SPECIFICATION **************************/ /* */ /* SUBROUTINE NAME: Init */ /* */ /* DESCRIPTIVE NAME: CMD.EXE Initialization Process */ /* */ /* FUNCTION: Initialization of CMD.EXE. */ /* */ /* NOTES: */ /* */ /* ENTRY POINT: Init */ /* */ /* INPUT: None. */ /* */ /* OUTPUT: None. */ /* */ /* EXIT-NORMAL: */ /* Return the pointer to command line. */ /* */ /* EXIT-ERROR: */ /* Return NULL string. */ /* */ /* EFFECTS: None. */ /* */ /********************** END OF SPECIFICATION **************************/ /*** Init - initialize Command * * Purpose: * Save current SIGINTR response (SIGIGN or SIGDEF) and set SIGIGN. * If debugging * Set DebGroup & DebLevel * Get Environment and init CmdEnv structure (M034) * Check for any switches. * Make a version check. * If version out of range * Print error message. * If Permanent Command * Loop forever * Else * Exit. * Save the current drive and directory. * Check for other command line arguments. * Set up the environment. * Always print a bannner if MSDOS version of Command. * Return any "comline" value found. * * TCHAR *Init() * * Args: * * Returns: * Comline (it's NULL if NOT in single command mode). * * Notes: * See CSIG.C for a description of the way ^Cs and INT24s are handled * during initialization. * M024 - Brought functionality for checking non-specific args into * init from routines CheckOtherArgs and ChangeComSpec which have * been eliminated. * */ BOOL Init( TCHAR *InitialCmds[] ) { #if 0 /* Set debug group and level words */ int fh; PTCHAR nptr; nptr = TmpBuf; nptr = EatWS(nptr, NULL); nptr = mystrchr(nptr, TEXT(' ')); nptr = EatWS(nptr, NULL); // // Assume a non-zero debugging group // DebGroup = hstoi(nptr) ; /* 1st debug arg */ if (DebGroup) { for (fh=0 ; fh < 2 ; fh++) { if (fh == 1) DebLevel = hstoi(nptr) ; /* 2nd debug arg */ while(*nptr && !_istspace(*nptr)) { /* Index past it */ ++nptr ; } nptr = EatWS(nptr, NULL) ; } } DEBUG((INGRP, RSLVL, "INIT: Debug GRP=%04x LVL=%04x", DebGroup, DebLevel)) ; mystrcpy(TmpBuf, nptr) ; /* Elim from cmdline */ #endif // // Initialize Critical Section to handle access to // flag for control C handling // lpcritCtrlC = &CtrlCSection; InitializeCriticalSection(lpcritCtrlC); ResetCtrlC(); SetConsoleCtrlHandler(Handler,TRUE); // // Make sure we have the correct console modes. // ResetConsoleMode(); #ifndef UNICODE setbuf(stdout, NULL); /* Don't buffer output @@5 */ setbuf(stderr, NULL); /* @@5 */ _setmode(1, O_BINARY); /* Set output to text mode @@5 */ _setmode(2, O_BINARY); /* @@5 */ #endif CmdEnv.handle = GetEnvironmentStrings(); GetRegistryValues(InitialCmds); mystrcpy(TmpBuf, GetCommandLine()); LexCopy( TmpBuf, TmpBuf, mystrlen( TmpBuf ) ); /* convert dbcs spaces */ GetDir(CurDrvDir, GD_DEFAULT) ; SetUpEnvironment() ; /* Check cmdline switches */ CheckSwitches(InitialCmds, TmpBuf); if (CurDrvDir[0] == BSLASH && CurDrvDir[1] == BSLASH) { #if 0 if (fEnableExtensions) { struct cmdnode *n ; PutStdErr(MSG_SIM_UNC_CURDIR, ONEARG, CurDrvDir); n = mkstr(sizeof(*n)); n->argptr = mkstr((_tcslen(CurDrvDir)+1) * sizeof(TCHAR)); _tcscpy(n->argptr, CurDrvDir); GetWindowsDirectory(CurDrvDir, sizeof(CurDrvDir)/sizeof(TCHAR)); ChangeDir2(CurDrvDir, TRUE); ePushDir(n); } else #endif if (!fDisableUNCCheck) { PutStdErr(MSG_NO_UNC_INITDIR, ONEARG, CurDrvDir); GetWindowsDirectory(CurDrvDir, sizeof(CurDrvDir)/sizeof(TCHAR)); ChangeDir2(CurDrvDir, TRUE); } } // // Get current CodePage Info. We need this to decide whether // or not to use half-width characters. This is actually here // in the init code for safety - the Dir command calls it before // each dir is executed, because chcp may have been executed. // GetCPInfo((CurrentCP=GetConsoleOutputCP()), &CurrentCPInfo); InitLocale(); pszTitleCur = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(TCHAR) + 2*sizeof(TCHAR)); pszTitleOrg = HeapAlloc(GetProcessHeap(), 0, MAX_PATH*sizeof(TCHAR) + 2*sizeof(TCHAR)); if ((pszTitleCur != NULL) && (pszTitleOrg != NULL)) { if (GetConsoleTitle(pszTitleOrg, MAX_PATH)) { mystrcpy(pszTitleCur, pszTitleOrg); } else { *pszTitleCur = 0; *pszTitleOrg = 0; } } if (!SingleCommandInvocation) { if (FileIsConsole(STDOUT)) { #ifndef WIN95_CMD CONSOLE_SCREEN_BUFFER_INFO csbi; if (!wDefaultColor) { if (GetConsoleScreenBufferInfo( GetStdHandle(STD_OUTPUT_HANDLE), &csbi)) { wDefaultColor = csbi.wAttributes; } } #endif // WIN95_CMD if (wDefaultColor) { SetColor( wDefaultColor ); } } } /* Print banner if no command string on command line */ if (!InitialCmds[2]) { TCHAR VersionFormat[32]; GetVersionString( VersionFormat, sizeof( VersionFormat ) / sizeof( VersionFormat[0] )); PutStdOut( MSG_MS_DOS_VERSION, ONEARG, VersionFormat ); cmd_printf( CrLf ); PutStdOut( MSG_COPYRIGHT, NOARGS ) ; if (fDefaultExtensions) { // // DaveC says say nothing to user here. // // PutStdOut(MSG_EXT_ENABLED_BY_DEFAULT, NOARGS); } else if (fEnableExtensions) { PutStdOut(MSG_EXT_ENABLED, NOARGS) ; } } DEBUG((INGRP, RSLVL, "INIT: Returning now.")) ; #ifndef WIN95_CMD { hKernel32 = GetModuleHandle( TEXT("KERNEL32.DLL") ); lpCopyFileExW = (LPCOPYFILEEX_ROUTINE) GetProcAddress( hKernel32, "CopyFileExW" ); lpIsDebuggerPresent = (LPISDEBUGGERPRESENT_ROUTINE) GetProcAddress( hKernel32, "IsDebuggerPresent" ); lpSetConsoleInputExeName = (LPSETCONSOLEINPUTEXENAME_ROUTINE) GetProcAddress( hKernel32, "SetConsoleInputExeNameW" ); } #endif // WIN95_CMD return(InitialCmds[0] != NULL || InitialCmds[1] != NULL || InitialCmds[2] != NULL); } void GetRegistryValues( TCHAR *InitialCmds[] ) { long rc; HKEY hKey; ULONG ValueBuffer[ 1024 ]; LPBYTE lpData; DWORD cbData; DWORD dwType; DWORD cchSrc, cchDst; PTCHAR s; int i; HKEY PredefinedKeys[2] = {HKEY_LOCAL_MACHINE, HKEY_CURRENT_USER}; if (fDefaultExtensions) { fEnableExtensions = TRUE; } for (i=0; i<2; i++) { rc = RegOpenKey(PredefinedKeys[i], TEXT("Software\\Microsoft\\Command Processor"), &hKey); if (rc) { continue; } dwType = REG_NONE; lpData = (LPBYTE)ValueBuffer; cbData = sizeof(ValueBuffer); rc = RegQueryValueEx(hKey, TEXT("DisableUNCCheck"), NULL, &dwType, lpData, &cbData); if (!rc) { if (dwType == REG_DWORD) { fDisableUNCCheck = (BOOLEAN)(*(PULONG)lpData != 0); } else if (dwType == REG_SZ) { fDisableUNCCheck = (BOOLEAN)(_wtol((PWSTR)lpData) == 1); } } cbData = sizeof(ValueBuffer); rc = RegQueryValueEx(hKey, TEXT("EnableExtensions"), NULL, &dwType, lpData, &cbData); if (!rc) { if (dwType == REG_DWORD) { fEnableExtensions = (BOOLEAN)(*(PULONG)lpData != 0); } else if (dwType == REG_SZ) { fEnableExtensions = (BOOLEAN)(_wtol((PWSTR)lpData) == 1); } } cbData = sizeof(ValueBuffer); rc = RegQueryValueEx(hKey, TEXT("DelayedExpansion"), NULL, &dwType, lpData, &cbData); if (!rc) { if (dwType == REG_DWORD) { fDelayedExpansion = (BOOLEAN)(*(PULONG)lpData != 0); } else if (dwType == REG_SZ) { fDelayedExpansion = (BOOLEAN)(_wtol((PWSTR)lpData) == 1); } } cbData = sizeof(ValueBuffer); rc = RegQueryValueEx(hKey, TEXT("DefaultColor"), NULL, &dwType, lpData, &cbData); if (!rc) { if (dwType == REG_DWORD) { wDefaultColor = (WORD) *(PULONG)lpData; } else if (dwType == REG_SZ) { wDefaultColor = (WORD)_tcstol((PTCHAR)lpData, NULL, 0); } } cbData = sizeof(ValueBuffer); rc = RegQueryValueEx(hKey, TEXT("CompletionChar"), NULL, &dwType, lpData, &cbData); if (!rc) { if (dwType == REG_DWORD) { chCompletionCtrl = (TCHAR)*(PULONG)lpData; } else if (dwType == REG_SZ) { chCompletionCtrl = (TCHAR)_tcstol((PTCHAR)lpData, NULL, 0); } if (chCompletionCtrl == 0 || chCompletionCtrl == 0x0d || chCompletionCtrl > SPACE) { chCompletionCtrl = SPACE; } } cbData = sizeof(ValueBuffer); rc = RegQueryValueEx(hKey, TEXT("PathCompletionChar"), NULL, &dwType, lpData, &cbData); if (!rc) { if (dwType == REG_DWORD) { chPathCompletionCtrl = (TCHAR)*(PULONG)lpData; } else if (dwType == REG_SZ) { chPathCompletionCtrl = (TCHAR)_tcstol((PTCHAR)lpData, NULL, 0); } if (chPathCompletionCtrl == 0 || chPathCompletionCtrl == 0x0d || chPathCompletionCtrl > SPACE) { chPathCompletionCtrl = SPACE; } } if (chCompletionCtrl == SPACE && chPathCompletionCtrl < SPACE) { chCompletionCtrl = chPathCompletionCtrl; } else if (chPathCompletionCtrl == SPACE && chCompletionCtrl < SPACE) { chPathCompletionCtrl = chCompletionCtrl; } cbData = sizeof(ValueBuffer); rc = RegQueryValueEx(hKey, TEXT("AutoRun"), NULL, &dwType, lpData, &cbData); if (!rc) { s = (TCHAR *)lpData; if (dwType == REG_EXPAND_SZ) { cchSrc = cbData / sizeof( TCHAR ); cchDst = (sizeof( ValueBuffer ) - cbData) / sizeof( TCHAR ); if (ExpandEnvironmentStrings( s, &s[ cchSrc+2 ], cchDst ) ) _tcscpy( s, &s[ cchSrc+2 ] ); else *s = NULLC; } if (*s) InitialCmds[i] = mystrcpy( mkstr( (_tcslen(s)+1) * sizeof( TCHAR ) ), s ); } RegCloseKey(hKey); } // // Initialize for %RANDOM% // srand( (unsigned)time( NULL ) ); return; } /*** CheckSwitches - process Command's switches * * Purpose: * Check to see if Command was passed any switches and take appropriate * action. The switches are: * /P - Permanent Command. Set permanent CMD flag. * /C - Single command. Build a command line out of the rest of * the args and pass it back to Init. * @@ /K - Same as /C but also set BatCom flag. * /Q - No echo * /A - Output in ANSI * /U - Output in UNICODE * * All other switches are ignored. * * TCHAR *CheckSwitches(TCHAR *nptr) * * Args: * nptr = Ptr to cmdline to check for switches * * Returns: * Comline (it's NULL if NOT in single command mode). * * Notes: * M034 - This function revised to use the raw cmdline * from the passed environment. * */ void CheckSwitches( TCHAR *InitialCmds[], TCHAR *nptr ) { TCHAR a, /* Holds switch value */ *comline = NULL , /* Ptr to command line if /c found */ store, *ptr, /* A temporary pointers */ *ptr_b, *ptr_e; BOOLEAN fAutoGen = FALSE; // On if "/S" in cmdline meaning cmdline was parsed by CMD.EXE previously BOOLEAN fOrigEnableExt; struct cmdnode cmd_node; // need for SearchForExecutable() TCHAR cmdline [MAX_PATH]; TCHAR argptr [MAX_PATH]; TCHAR CmdBuf [MAXTOKLEN+3]; int retc; memset( &cmd_node, 0, sizeof( cmd_node )); fOrigEnableExt = fEnableExtensions; DEBUG((INGRP, ACLVL, "CHKSW: entered.")) ; while (nptr = mystrchr(nptr, SwitChar)) { a = (TCHAR) _totlower(nptr[1]) ; if (a == NULLC) break; if (a == QMARK) { #define CTRLCBREAK if (CtrlCSeen) break BeginHelpPause(); do { CTRLCBREAK; PutStdOut(MSG_HELP_CMD, NOARGS); CTRLCBREAK; PutStdOut(MSG_HELP_CMD1, NOARGS); if (!fOrigEnableExt && !fEnableExtensions) break; CTRLCBREAK; PutStdOut(MSG_HELP_CMD_EXTENSIONS, NOARGS); CTRLCBREAK; PutStdOut(MSG_HELP_CMD_EXTENSIONS1, NOARGS); CTRLCBREAK; PutStdOut(MSG_HELP_CMD_COMPLETION1, NOARGS); CTRLCBREAK; PutStdOut(MSG_HELP_CMD_COMPLETION2, NOARGS); } while ( FALSE ); EndHelpPause(); CMDexit(1); } else if (a == QCSwitch) { /* Quiet cmd switch */ Necho = TRUE ; mystrcpy(nptr, nptr+2) ; } else if ((a == SCSwitch) || (a == BCSwitch) || a == TEXT('r')) { DEBUG((INGRP, ACLVL, "CHKSW: Single command switch")) ; if ( a == BCSwitch ) { SingleBatchInvocation = TRUE; // /K specified } else { SingleCommandInvocation = TRUE; // /C or /R specified } if (!(comline = mkstr(mystrlen(nptr+2)*sizeof(TCHAR)+2*sizeof(TCHAR)))) { PutStdErr(ERROR_NOT_ENOUGH_MEMORY, NOARGS); CMDexit(1) ; } ; mystrcpy(comline, nptr+2) ; /* Make comline */ *nptr = NULLC ; /* Invalidate this arg */ comline = SkipWhiteSpace( comline ); //--------------------------------------------------------------------------------------------------------- // CMD.EXE uses quotes by two reasons: // 1. to embed command symbols "&", "<", ">", "|", "&&", "||" into command arguments, e.g. // cmd /c " dir | more " // 2. to embed spaces into filename, e.g. // cmd /c " my batfile with spaces.cmd" // Note that the caret "^" has no effect when used in between quotes in the current implementation (941221). // Also, CMD.EXE binds the quote with the next one. // // I see a problem here: the commands like // cmd /c "findstr " | " | find "smth" " OR // cmd /c "ls | " my filterbat with spaces.cmd" | more" // WON'T WORK unless we all decide to change CMD's syntax to better handle quotes! // // There is more to it: when CMD.EXE parses pipes,CMD creates process with the command argument like this: // /S /C" " // so we've got spaces inside the quotes. // // I hope I am not missing anything else... // // With given design restrictions, I will at least solve simple but most wide-spread problem: // using filenames with spaces by trying this: // IF ( (there is no /S switch ) AND // it is not the result of prev. parsing // (there are exactly 2 quotes) AND // the existing design problem with multiple quotes // (there is no special chars between quotes) AND // don't break command symbols parsing // (there is a whitespace between quotes) AND // otherwise it is not filename with spaces // (the token between quotes is a valid executable) )// otherwise we can't help anyway // THEN // Preserve quotes // Assume it is a filename with spaces // ELSE // Exec. old logic // Strip first and last quotes // // Ugly, but what options do I have? Only to patch existing logic or change syntax. //----------------------------------------------------------------------------------------------------------- if (fAutoGen) // seen /S switch goto old_way; if (*comline == QUOTE) { ptr_b = comline + 1; ptr_e = mystrchr (ptr_b, QUOTE); if (ptr_e) { // at least 2 quotes ptr_b = ptr_e + 1; ptr_e = mystrchr (ptr_b, QUOTE); if (ptr_e) { // more than 2 quotes goto old_way; } } else { // only 1 quote goto old_way; } // exactly 2 quotes store = *ptr_b; *ptr_b = NULLC; if ( (mystrchr (comline, ANDOP) ) || (mystrchr (comline, INOP) ) || (mystrchr (comline, OUTOP) ) || (mystrchr (comline, LPOP) ) || (mystrchr (comline, RPOP) ) || (mystrchr (comline, SILOP) ) || (mystrchr (comline, ESCHAR)) || (mystrchr (comline, PIPOP) ) ) { *ptr_b = store; // special chars between quotes goto old_way; } if ( ! mystrchr (comline, TEXT(' ')) ) { *ptr_b = store; // no spaces between quotes goto old_way; } // the last check is for valid executable cmd_node.type = CMDTYP ; cmd_node.cmdline = cmdline; cmd_node.argptr = argptr; cmd_node.rio = NULL; mystrcpy (cmdline, comline); // get token between quotes mystrcpy (argptr, TEXT (" ") ); *ptr_b = store; // restore comline retc = SearchForExecutable (&cmd_node, CmdBuf); if ( ( retc == SFE_NOTFND) || ( retc == SFE_FAIL) ) goto old_way; goto new_way; // assume filename and DO NOT strip quotes. } old_way: if (*comline == QUOTE) { ++comline ; ptr = mystrrchr(comline, QUOTE); if ( ptr ) { *ptr = NULLC; ++ptr; mystrcat(comline,ptr); } } new_way: *(comline+mystrlen(comline)) = NLN ; DEBUG((INGRP, ACLVL, "CHKSW: Single command line = `%ws'", comline)) ; InitialCmds[2] = comline; break ; /* Once /K or /C found, no more args exist */ } else if (a == UCSwitch) { /* Unicode output switch */ #ifdef UNICODE fOutputUnicode = TRUE; mystrcpy(nptr, nptr+2) ; #else PutStdErr(MSG_UNICODE_NOT_SUPPORTED, NOARGS); #endif // UNICODE } else if (a == ACSwitch) { /* Ansi output switch */ #ifdef UNICODE fOutputUnicode = FALSE; #endif // UNICODE mystrcpy(nptr, nptr+2) ; // // Old style of enabling extensions with /X // } else if (a == XCSwitch) { /* Enable extensions switch */ fEnableExtensions = TRUE; mystrcpy(nptr, nptr+2) ; // // Old style of disabling extensions with /Y // } else if (a == YCSwitch) { /* Disable extensions switch */ fEnableExtensions = FALSE; mystrcpy(nptr, nptr+2) ; // // Enable/Disable command extensions. /E or /E:ON to enable // and /E:OFF to disable. // } else if (a == TEXT('e')) { mystrcpy(nptr, nptr+2) ; if (*nptr == COLON && !_tcsnicmp(nptr+1, TEXT("OFF"), 3)) { fEnableExtensions = FALSE; mystrcpy(nptr, nptr+4) ; } else { fEnableExtensions = TRUE; if (!_tcsnicmp(nptr, TEXT(":ON"), 3)) { mystrcpy(nptr, nptr+3) ; } } // // Disable AutoRun from Registry if /D specified. // } else if (a == TEXT('d')) { mystrcpy(nptr, nptr+2) ; InitialCmds[0] = NULL; InitialCmds[1] = NULL; // // Enable/Disable file and directory name completion. /F or /F:ON to // enable and /F:OFF to disable. // } else if (a == TEXT('f')) { mystrcpy(nptr, nptr+2) ; if (*nptr == COLON && !_tcsnicmp(nptr+1, TEXT("OFF"), 3)) { chCompletionCtrl = SPACE; chPathCompletionCtrl = SPACE; mystrcpy(nptr, nptr+4) ; } else { chCompletionCtrl = 0x6; // Ctrl-F chPathCompletionCtrl = 0x4; // Ctrl-D if (!_tcsnicmp(nptr, TEXT(":ON"), 3)) { mystrcpy(nptr, nptr+3) ; } } // // Enable/Disable delayed variable expansion inside FOR loops. /V or /V:ON to // enable and /V:OFF to disable. // } else if (a == TEXT('v')) { mystrcpy(nptr, nptr+2) ; if (*nptr == COLON && !_tcsnicmp(nptr+1, TEXT("OFF"), 3)) { fDelayedExpansion = FALSE; mystrcpy(nptr, nptr+4) ; } else { fDelayedExpansion = TRUE; if (!_tcsnicmp(nptr, TEXT(":ON"), 3)) { mystrcpy(nptr, nptr+3) ; } } // // Set the foreground/background screen coler // enable and /F:OFF to disable. // } else if (fEnableExtensions && a == TEXT('t')) { /* Define start color */ if (*(nptr+2) == __TEXT(':') && _istxdigit(*(nptr+3)) && _istxdigit(*(nptr+4)) && !_istxdigit(*(nptr+5))) { wDefaultColor = (WORD) (_istdigit(*(nptr+3)) ? (WORD)*(nptr+3) - (WORD)TEXT('0') : (WORD)_totlower(*(nptr+3)) - (WORD)TEXT('W')) ; wDefaultColor <<= 4; wDefaultColor |= (WORD) (_istdigit(*(nptr+4)) ? (WORD)*(nptr+4) - (WORD)TEXT('0') : (WORD)_totlower(*(nptr+4)) - (WORD)TEXT('W')) ; mystrcpy(nptr+2, nptr+5 ); } mystrcpy(nptr, nptr+2) ; } else if (a == TEXT('s') ) { /* CMD inserts when parsing pipes */ fAutoGen = TRUE ; mystrcpy(nptr, nptr+2) ; } else { mystrcpy(nptr, nptr+2) ; /* Remove any other switches */ } ; } ; return; } /*** SetUpEnvironment - initialize Command's environment * * Purpose: * Take the environment pointer received earlier and initialize it * with respect with respect to size and maxsize. Initialize the * PATH and COMSPEC variables as necessary. * * SetUpEnvironment() * */ extern TCHAR KeysStr[]; /* @@5 */ extern int KeysFlag; /* @@5 */ void SetUpEnvironment(void) { TCHAR *cds ; // Command directory string TCHAR *nptr ; // Temp cmd name ptr TCHAR *eptr ; // Temp cmd name ptr MEMORY_BASIC_INFORMATION MemInfo; eptr = CmdEnv.handle; CmdEnv.cursize = GetEnvCb( eptr ); VirtualQuery( CmdEnv.handle, &MemInfo, sizeof( MemInfo )); CmdEnv.maxsize = (UINT)MemInfo.RegionSize; if (!(cds = mkstr(MAX_PATH*sizeof(TCHAR)))) { PutStdErr(ERROR_NOT_ENOUGH_MEMORY, NOARGS); CMDexit(1) ; } GetModuleFileName( NULL, cds, MAX_PATH ); // // If the PATH variable is not set, it must be added as a NULL. This is // so that DOS apps inherit the current directory path. // if (!GetEnvVar(PathStr)) { SetEnvVar(PathStr, TEXT(""), &CmdEnv); } // // If the PATHEXT variable is not set, and extensions are enabled, set it to // the default list of extensions that will be searched. // if (!GetEnvVar(PathExtStr)) { SetEnvVar(PathExtStr, PathExtDefaultStr, &CmdEnv); } // // If the PROMPT variable is not set, it must be added as $P$G. This is // special cased, since we do not allow users to add NULLs. // if (!GetEnvVar(PromptStr)) { SetEnvVar(PromptStr, TEXT("$P$G"), &CmdEnv); } if (!GetEnvVar(ComSpecStr)) { DEBUG((INGRP, EILVL, "SETENV: No COMSPEC var")) ; if(!mystrchr(cds,DOT)) { /* If no fname, use default */ _tcsupr(CmdSpec); if((cds+mystrlen(cds)-1) != mystrrchr(cds,PathChar)) { mystrcat(cds,ComSpec) ; } else { mystrcat(cds,&ComSpec[1]) ; } } SetEnvVar(ComSpecStr, cds, &CmdEnv) ; } if ( (nptr = GetEnvVar(KeysStr)) && (!_tcsicmp(nptr, TEXT("ON"))) ) { KeysFlag = 1; } ChangeDir(CurDrvDir); penvOrig = CopyEnv(); if (penvOrig) { OrigEnv = *penvOrig; penvOrig = &OrigEnv; } } VOID ResetCtrlC() { EnterCriticalSection(lpcritCtrlC); CtrlCSeen = FALSE; LeaveCriticalSection(lpcritCtrlC); } VOID SetCtrlC() { EnterCriticalSection(lpcritCtrlC); CtrlCSeen = TRUE; LeaveCriticalSection(lpcritCtrlC); } void CMDexit(int rc) { while (ePopDir(NULL) == SUCCESS) ; exit(rc); } // // Get the current OS version and put it into the common version format // VOID GetVersionString( IN OUT PTCHAR VersionString, IN ULONG Length ) { ULONG vrs = GetVersion(); // // Version format is [Major.Minor(2).Build(4)] // _sntprintf( VersionString, Length, TEXT( "%d.%d.%04d" ), vrs & 0xFF, (vrs >> 8) & 0xFF, (vrs >> 16) & 0x3FFF ); }