#include "cmd.h" #pragma hdrstop #include "ctable.h" #define MSG_USE_DEFAULT -1 /* M031 */ struct envdata CmdEnv ; /* Holds info need to manipulate Cmd's environment */ extern TCHAR PathChar ; extern TCHAR CurDrvDir[] ; #define DAYLENGTH 3 extern TCHAR TmpBuf[], Delimiters[] ; /* M020 */ extern TCHAR SwitChar ; extern int Ctrlc; // // flag if control-c was seen // extern BOOL CtrlCSeen; extern int ExtCtrlc; /* @@4 */ extern TCHAR CrLf[] ; extern TCHAR Fmt19[]; extern unsigned flgwd ; unsigned int DosErr = 0 ; unsigned long OHTbl[3] = {0,0,0} ; extern BOOLEAN fPrintCtrlC; extern int CurBat ; unsigned int cbTitleCurPrefix; extern BOOLEAN fTitleChanged; extern TCHAR ShortMondayName[]; extern TCHAR ShortTuesdayName[]; extern TCHAR ShortWednesdayName[]; extern TCHAR ShortThursdayName[]; extern TCHAR ShortFridayName[]; extern TCHAR ShortSaturdayName[]; extern TCHAR ShortSundayName[]; // // Set of /c switch on command line set. // extern BOOLEAN fSingleCmdLine; // // Used to set and reset ctlcseen flag // VOID SetCtrlC(); VOID ResetCtrlC(); // // console mode at program startup time. Used to reset mode // after running another process. // extern DWORD dwCurInputConMode; extern DWORD dwCurOutputConMode; // // BUGBUG temp till i sync // // #define CONTROL_C_EXIT 0x00F00F00 unsigned msglen; /* @@@@@@@@@@@@@@ */ struct msentry { /* M027 */ unsigned errnum ; unsigned msnum ; } ; struct msentry mstabl[] = { {(unsigned)ERROR_INVALID_FUNCTION, (unsigned)MSG_USE_DEFAULT }, /* 1 */ {ERROR_FILE_NOT_FOUND, ERROR_FILE_NOT_FOUND }, /* 2 */ {ERROR_PATH_NOT_FOUND, ERROR_PATH_NOT_FOUND }, /* 3 */ {ERROR_TOO_MANY_OPEN_FILES, ERROR_TOO_MANY_OPEN_FILES }, /* 4 */ {ERROR_ACCESS_DENIED, ERROR_ACCESS_DENIED }, /* 5 */ {ERROR_INVALID_HANDLE, ERROR_INVALID_HANDLE }, /* 6 */ {ERROR_NOT_ENOUGH_MEMORY, ERROR_NOT_ENOUGH_MEMORY }, /* 8 */ {(unsigned)ERROR_INVALID_ACCESS, (unsigned)MSG_USE_DEFAULT }, /* 12 */ {ERROR_NO_MORE_FILES, ERROR_FILE_NOT_FOUND }, /* 18 */ {ERROR_SECTOR_NOT_FOUND, ERROR_SECTOR_NOT_FOUND }, /* 27 */ {ERROR_SHARING_VIOLATION, ERROR_SHARING_VIOLATION }, /* 32 */ {ERROR_LOCK_VIOLATION, ERROR_LOCK_VIOLATION }, /* 33 */ {ERROR_FILE_EXISTS, ERROR_FILE_EXISTS }, /* 80 */ {ERROR_CANNOT_MAKE, ERROR_CANNOT_MAKE }, /* 82 */ {(unsigned)ERROR_INVALID_PARAMETER, (unsigned)MSG_USE_DEFAULT }, /* 87 */ {ERROR_OPEN_FAILED, ERROR_OPEN_FAILED }, /* 110 */ {ERROR_DISK_FULL, ERROR_DISK_FULL }, /* 112 */ {0,0} /* End of Table */ } ; /*** OnOffCheck - check an argument string for "ON" or "OFF" * * Purpose: * To check str for the word "ON" or the word "OFF". If flag is nonzero, * an error message will be printed if str contains anything other than * just "ON", "OFF", or an empty string. * * int OnOffCheck(TCHAR *str, int flag) * * Args: * str - the string to check * flag - nonzero if error checking is to be done * * Returns: * OOC_EMPTY if str was empty. * OOC_ON if just "ON" was found. * OOC_OFF if just "OFF" was found. * OOC_OTHER if anything else was found. * */ int OnOffCheck(str, flag) TCHAR *str ; int flag ; { TCHAR *tas ; /* Tokenized arg string */ int retval = OOC_OTHER ; /* Return value */ TCHAR control[2]; control[0] = 12; /* ^L */ control[1] = NULLC; if (*(tas = TokStr(str, control, TS_NWSPACE )) == NULLC) return(OOC_EMPTY) ; if (_tcsicmp(tas,TEXT("on")) == 0) /* M015 */ retval = OOC_ON ; else if (_tcsicmp(tas,TEXT("off")) == 0) /* M015 */ retval = OOC_OFF ; if (retval == OOC_OTHER || *(tas+mystrlen(tas)+1)) { if (flag) /* M020 */ PutStdErr(MSG_BAD_PARM1, NOARGS); return(OOC_OTHER) ; } ; return(retval) ; } /*** ChangeDrive - change Command's current drive * * Purpose: * To change Command's default drive. * * ChangeDrive(int drvnum) * * Args: * drvnum - the drive number to change to (M010 - 1 == A, etc.) * */ void ChangeDrive(drvnum) int drvnum ; { TCHAR denvname[ 4 ]; TCHAR denvvalue[ MAX_PATH ]; TCHAR *s; BOOLEAN fSet; UINT OldErrorMode; denvname[ 0 ] = EQ; denvname[ 1 ] = (TEXT('A') + (drvnum-1)); denvname[ 2 ] = COLON; denvname[ 3 ] = NULLC; fSet = FALSE; s = NULL; if (s = GetEnvVar( denvname )) { fSet = (BOOLEAN)SetCurrentDirectory( s ); } // // if the drive was not at current position then // reset. If it was a mapped drive then it may have // been disconnected and then reconnected and so // we should reset to root. // if (!fSet) { // // In the case where the drive letter was not in the environment // ans so did not do the first SetCurrentDirectory then do not // turn off error pop-up // if (s != NULL) { OldErrorMode = SetErrorMode( SEM_FAILCRITICALERRORS ); } denvvalue[ 0 ] = denvname[ 1 ]; denvvalue[ 1 ] = denvname[ 2 ]; denvvalue[ 2 ] = PathChar; denvvalue[ 3 ] = NULLC; SetEnvVar(denvname,denvvalue,&CmdEnv); if (!SetCurrentDirectory( denvvalue )) { // // Could not set the drive at all give an error // PutStdErr(ERROR_INVALID_DRIVE, NOARGS); } if (s != NULL) { SetErrorMode( OldErrorMode ); } } GetDir(CurDrvDir, GD_DEFAULT) ; } /*** PutStdOut - Print a message to STDOUT * * Purpose: * Calls PutMsg sending STDOUT as the handle to which the message * will be written. * * int PutStdOut(unsigned MsgNum, unsigned NumOfArgs, ...) * * Args: * MsgNum - the number of the message to print * NumOfArgs - the number of total arguments * ... - the additional arguments for the message * * Returns: * Return value from PutMsg() M026 * */ PutStdOut(unsigned int MsgNum, unsigned int NumOfArgs, ...) { int Result; va_list arglist; va_start(arglist, NumOfArgs); Result = PutMsg(MsgNum, STDOUT, NumOfArgs, &arglist); va_end(arglist); return Result; } /*** PutStdErr - Print a message to STDERR * * Purpose: * Calls PutMsg sending STDERR as the handle to which the message * will be written. * * int PutStdErr(unsigned MsgNum, unsigned NumOfArgs, ...) * * Args: * MsgNum - the number of the message to print * NumOfArgs - the number of total arguments * ... - the additonal arguments for the message * * Returns: * Return value from PutMsg() M026 * */ int PutStdErr(unsigned int MsgNum, unsigned int NumOfArgs, ...) { int Result; va_list arglist; va_start(arglist, NumOfArgs); Result = PutMsg(MsgNum, STDERR, NumOfArgs, &arglist); va_end(arglist); return Result; } int FindMsg(unsigned MsgNum, PTCHAR NullArg, unsigned NumOfArgs, va_list *arglist) { unsigned msglen; DWORD msgsource; TCHAR *Inserts[ 2 ]; extern HANDLE NtDllHandle; CHAR numbuf[ 32 ]; #ifdef UNICODE TCHAR wnumbuf[ 32 ]; #endif #if DBG int error; #endif // // find message without doing argument substitution // if (MsgNum == ERROR_MR_MID_NOT_FOUND) { msglen = 0; } else { msgsource = MsgNum >= MSG_RESPONSE_DATA ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM; msglen = FormatMessage(msgsource | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, MsgNum, 0, MsgBuf, sizeof(MsgBuf) / sizeof(TCHAR), NULL ); if (msglen == 0) { #if DBG error = GetLastError(); DEBUG((CTGRP, COLVL, "FindMsg: FormatMessage #1 error %d",error)) ; #endif if (NtDllHandle == NULL) { NtDllHandle = GetModuleHandle( TEXT("NTDLL") ); } msgsource = FORMAT_MESSAGE_FROM_HMODULE; msglen = FormatMessage(msgsource | FORMAT_MESSAGE_IGNORE_INSERTS, (LPVOID)NtDllHandle, MsgNum, 0, MsgBuf, sizeof(MsgBuf) / sizeof(TCHAR), NULL ); } } if (msglen == 0) { #if DBG error = GetLastError(); DEBUG((CTGRP, COLVL, "FindMsg: FormatMessage #2 error %d",error)) ; #endif // // didn't find message // msgsource = FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_ARGUMENT_ARRAY; _ultoa( MsgNum, numbuf, 16 ); #ifdef UNICODE MultiByteToWideChar(CP_ACP, MB_PRECOMPOSED, numbuf, -1, wnumbuf, 32); Inserts[ 0 ]= wnumbuf; #else Inserts[ 0 ]= numbuf; #endif Inserts[ 1 ]= (MsgNum >= MSG_RESPONSE_DATA ? TEXT("Application") : TEXT("System")); MsgNum = ERROR_MR_MID_NOT_FOUND; msglen = FormatMessage(msgsource, NULL, MsgNum, 0, MsgBuf, sizeof(MsgBuf) / sizeof(TCHAR), (va_list *)Inserts ); #if DBG if (msglen == 0) { error = GetLastError(); DEBUG((CTGRP, COLVL, "FindMsg: FormatMessage #3 error %d",error)) ; } #endif } else { // see how many arguments are expected and make sure we have enough PTCHAR tmp; ULONG count; tmp=MsgBuf; count = 0; while (tmp = mystrchr(tmp, PERCENT)) { tmp++; if (*tmp >= TEXT('1') && *tmp <= TEXT('9')) { count += 1; } else if (*tmp == PERCENT) { tmp++; } } if (count > NumOfArgs) { PTCHAR *LocalArgList; ULONG i; LocalArgList = (PTCHAR*)HeapAlloc(GetProcessHeap(), 0, sizeof(PTCHAR) * count); for (i=0; i 2) || /* Flags invalid? */ ((flags & O_WRONLY) && (flags & O_APPEND))) { DEBUG((CTGRP, COLVL, "COPEN: Bad flags issued %04x",flags)) ; return(BADHANDLE) ; } ; /* M024 - Altered so that the only sharing restriction is to deny * others write permission if this open is for writing. Any other * sharing is allowed. */ if(flags & (O_WRONLY | O_RDWR)) { /* If Writing, set... */ fAccess = GENERIC_WRITE; /* * deny write only if it is not console */ if (_tcsicmp(fn, TEXT("con"))) { fShareMode = FILE_SHARE_READ; } fCreate = CREATE_ALWAYS;/* ...open if exists, else create */ } else { fAccess = GENERIC_READ; fCreate = OPEN_EXISTING; } if (flags == OP_APPEN) { if ((handle = CreateFile(fn, fAccess|GENERIC_READ, fShareMode, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { if ((handle = CreateFile(fn, fAccess, fShareMode, &sa, fCreate, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { DosErr = GetLastError(); DEBUG((CTGRP,COLVL, "COPEN: CreateFile ret'd %d",DosErr)) ; if ( DosErr == ERROR_OPEN_FAILED ){ DosErr = ERROR_FILE_NOT_FOUND; } /* endif */ return(BADHANDLE) ; } } } else if ((handle = CreateFile(fn, fAccess, fShareMode, &sa, fCreate, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { DosErr = GetLastError(); DEBUG((CTGRP,COLVL, "COPEN: CreateFile ret'd %d",DosErr)) ; if ( DosErr == ERROR_OPEN_FAILED ){ DosErr = ERROR_FILE_NOT_FOUND; } /* endif */ return(BADHANDLE) ; } fh = _open_osfhandle((long)handle, _O_APPEND); if ((flags & O_APPEND) && !FileIsDevice(fh) && GetFileSize(handle,NULL) != 0){ c = NULLC ; high = -1; fCreate = SetFilePointer(handle, -1L, &high, FILE_END) ; if (fCreate == 0xffffffff && (DosErr = GetLastError()) != NO_ERROR) { DEBUG((CTGRP,COLVL,"COPEN: SetFilePointer error %d",DosErr)) ; // should close CRT handle, not OS handle if (fh != BADHANDLE) { _close(fh); } return BADHANDLE; } fCreate = ReadFile(handle, &c, 1, &cb, NULL) ; if (fCreate == 0) { high = 0; SetFilePointer(handle, 0L, &high, FILE_END) ; /* ...back up 1 */ DEBUG((CTGRP,COLVL,"COPEN: ReadFile error %d",GetLastError())) ; } DEBUG((CTGRP,COLVL, "COPEN: Moving file ptr")) ; if (c == CTRLZ) { /* If end=^Z... */ high = -1; SetFilePointer(handle, -1L, &high, FILE_END) ; /* ...back up 1 */ } } ; SetList(fh) ; return(fh) ; } CRTHANDLE Copen(fn, flags) TCHAR *fn ; unsigned int flags ; { return( Copen_Work(fn, flags, FILE_SHARE_READ | FILE_SHARE_WRITE ) ); /* deny nothing */ } /*** InSetList - Determine if handle is in signal cleanup table * * Purpose: * To determine if the input handle exsists in the cleanup table. * * int InSetList(unsigned int fh) * * Args: * fh = File handle to check. * * Returns: * TRUE: if handle is in table. * FALSE: if handle is not in table. * * Notes: * - Signal cleanup table does not include STDIN, STDOUT or STDERR. * */ unsigned long InSetList( IN CRTHANDLE fh ) { int cnt = 0 ; if (fh > STDERR && fh < 95) { while (fh > 31) { fh -= 32 ; ++cnt ; } ; return( (OHTbl[cnt]) & ((unsigned long)1 << fh) ); } ; return( FALSE ); } /*** Cdup - CMD.EXE dup function (M014) * * Purpose: * Duplicates the supplied handle and saves the new handle for * possible signal cleanup. * * int Cdup(unsigned int fh) * * Args: * fh = Handle to be duplicated * * Returns: * The handle returned by the C runtime dup function * * Notes: * Signal cleanup table does not include STDIN, STDOUT or STDERR. * */ CRTHANDLE Cdup( CRTHANDLE fh ) { CRTHANDLE NewHandle ; if((int)(NewHandle = _dup(fh)) != BADHANDLE) if ( InSetList( fh ) ) SetList(NewHandle) ; return(NewHandle) ; } /*** Cdup2 - CMD.EXE dup2 function (M014) * * Purpose: * Duplicates the supplied handle and saves the new handle for * possible signal cleanup. * * HANDLE Cdup2(unsigned int fh1, unsigned int fh2) * * Args: * fh = Handle to be duplicated * * Returns: * The handle returned by the C runtime dup2 function * * Notes: * Signal cleanup table does not include STDIN, STDOUT or STDERR. * */ CRTHANDLE Cdup2( CRTHANDLE fh1, CRTHANDLE fh2) { unsigned int retcode ; int cnt = 0 ; unsigned int fuse ; if((int)(retcode = (unsigned)_dup2(fh1,fh2)) != -1) { if ((fuse = fh2) > STDERR && fuse < 95) { while (fuse > 31) { fuse -= 32 ; ++cnt ; } OHTbl[cnt] &= ~((unsigned long)1 << fuse) ; } if ( InSetList( fh1 ) ) SetList(fh2) ; } return(retcode) ; } /*** Cclose - CMD.EXE close handle function (M014) * * Purpose: * Closes an open file or device and removes the handle from the * signal cleanup table. * * int Cclose(unsigned int fh) * * Args: * fh = File handle to be closed. * * Returns: * return code from C runtime close * * Notes: * - Signal cleanup table does not include STDIN, STDOUT or STDERR. * - M023 * Revised to use bit map instead of malloc'd space. * */ Cclose(fh) CRTHANDLE fh ; { int cnt = 0 ; unsigned int fuse ; int ret_val; if (fh == BADHANDLE) return(0); if ((fuse = fh) > STDERR && fuse < 95) { while (fuse > 31) { fuse -= 32 ; ++cnt ; } OHTbl[cnt] &= ~((unsigned long)1 << fuse) ; } ret_val = _close(fh); /* Delete file handle */ return(ret_val); } /*** SetList - Place open handle in signal cleanup list (M014) * * Purpose: * Places a handle number in the signal cleanup table for use * during signal's closing of files. * * int SetList(unsigned int fh) * * Args: * fh = File handle to install. * * Returns: * nothing * * Notes: * - Signal cleanup table does not include STDIN, STDOUT or STDERR. * - M023 * Revised to use bit map instead of malloc'd space. * */ void SetList( IN CRTHANDLE fh ) { int cnt = 0 ; if (fh > STDERR && fh < 95) { while (fh > 31) { fh -= 32 ; ++cnt ; } ; OHTbl[cnt] |= ((unsigned long)1 << fh) ; } ; } /*** GetFuncPtr - return the i-th function pointer in JumpTable (M015) * * int (*GetFuncPtr(int i))() * * Args: * i - the index of the JumpTable entry containing the function pointer * to be returned * * Returns: * The i-th function pointer in JumpTable. * * Notes: * It is assumed that i is valid. * */ int (*GetFuncPtr(i))(struct cmdnode *) int i ; { return(JumpTable[i].func) ; } /*** FindCmd - search JumpTable for a particular command (M015) * * Purpose: * Check the command name string pointers in each of the JumpTable * entries for one which matches the name in the string supplied by * the caller. * * int FindCmd(int entries, TCHAR *sname, TCHAR *sflags) * * Args: * entries - M009 - This value is highest entry to be checked. One * must be added for this to become a count of entries to * check. * sname - pointer to the command name to search for * sflags - if the command is found, store the command's flags here * * Returns: * If the entry is found, the entry's JumpTable index. * Otherwise, -1. * */ int FindCmd(entries, sname, sflags) int entries ; TCHAR *sname ; TCHAR *sflags ; { int i ; for (i=0 ; i <= entries ; i++) /* search through all entries */ { if (_tcsicmp(sname,JumpTable[i].name) == 0) /* test for cmd in table @inx */ { /* */ if (!(JumpTable[i].flags & EXTENSCMD) || fEnableExtensions) { *sflags = JumpTable[i].flags; /* M017 */ cmdfound = i; /* @@5 save current cmd index */ return(i); /* return not found index */ } } /* */ } /* */ cmdfound = -1; /* @@5 save not found index */ return(-1) ; /* return not found index */ } /********************* START OF SPECIFICATION **************************/ /* */ /* SUBROUTINE NAME: KillProc */ /* */ /* DESCRIPTIVE NAME: Kill process and wait for it to die */ /* */ /* FUNCTION: This routine kills a specified process during signal */ /* handling. */ /* */ /* NOTES: If the process is started by DosExecPgm, DosKillProcess */ /* is called to kill the process and all its child processes.*/ /* WaitProc is also called to wait for the termination of */ /* the process and child processes. */ /* If the process is started by DosStartSession, */ /* DosStopSession is called to stop the specified session and*/ /* its child sessions. WaitTermQProc is also called to wait */ /* for the termination of the session. */ /* */ /* All of CMD's kills are done on the entire subtree and that */ /* is assumed by this function. For single PID kills, use */ /* DOSKILLPROCESS direct. */ /* */ /* */ /* ENTRY POINT: KillProc */ /* LINKAGE: NEAR */ /* */ /* INPUT: Process ID / Session ID - to kill */ /* Wait - indicates if we should wait here or not */ /* */ /* OUTPUT: None */ /* */ /* EXIT-NORMAL: No error return code from WaitProc or WaitTermQProc */ /* */ /* */ /* EXIT-ERROR: Error return code from DosKillProcess or */ /* DosStopSession. Or error code from WaitProc or */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* WaitProc - wait for the termination of the specified process, */ /* its child process, and related pipelined */ /* processes. */ /* */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* DOSKILLPROCESS - Kill the process and its child processes */ /* DOSSTOPSESSION - Stop the session and its child sessions */ /* WINCHANGESWITCHENTRY - Change switch list entry */ /* */ /********************** END OF SPECIFICATION **************************/ KillProc(pid, wait) unsigned pid ; int wait; { unsigned i = 0; DEBUG((CTGRP,COLVL, "KillProc: Entered PID = %d", pid)) ; if (!TerminateProcess((HANDLE)pid, 1)) { DosErr = GetLastError(); } if (wait) { i = WaitProc(pid) ; /* wait for the related process to end */ } return( i ); } /*** WaitProc - Wait for a command subtree to terminate (M019) * * Purpose: * Provides a means of waiting for a process and all of its * children to terminate. * * int WaitProc(unsigned pid) * * Args: * pid - The process ID to be waited on * * Returns: * Retcode of the head process of the subtree * * Notes: * All of CMD's waits are done on the entire subtree and CMD * will always wait until someone terminates. That is assumed * by this function. For single PID waits, use DOSCWAIT direct. * */ WaitProc(pid) unsigned pid ; { unsigned FinalRCode; /* Return value from this function */ DEBUG((CTGRP,COLVL, "WaitProc: Entered PID = %d", pid)) ; // // Do not allow printint of ctrl-c in ctrl-c thread while // waiting for another process. The main loop will handle // this if the process exits due to ctrl-c. // fPrintCtrlC = FALSE; WaitForSingleObject( (HANDLE)pid, INFINITE ); GetExitCodeProcess( (HANDLE)pid, (LPDWORD)&FinalRCode ); //if (CtrlCSeen & (FinalRCode == CONTROL_C_EXIT)) { // how do we ever get here??? if (FinalRCode == CONTROL_C_EXIT) { SetCtrlC(); fprintf( stderr, "^C" ); fflush( stderr ); } fPrintCtrlC = TRUE; DEBUG((CTGRP, COLVL, "WaitProc: Returned handle %d, FinalRCode %d", pid, FinalRCode)); CloseHandle( (HANDLE)pid ); DEBUG((CTGRP,COLVL,"WaitProc:Complete and returning %d", FinalRCode)) ; return(FinalRCode) ; } /*** ParseLabel - Parse a batch file label statement (M020) * * Purpose: * Simulates the lexer's handling of labels in GOTO arguments. * * int ParseLabel(TCHAR *lab, TCHAR buf[],unsigned flag) * * Args: * lab - The batch file label to parse * buf - The buffer to hold the parsed label * flag - TRUE if this is a source label (already parsed once) * - FALSE if this is a test target label. * * Returns: * Nothing useful * * Notes: * Note that source labels (those in the GOTO statement itself), * have already been parsed by the normal method with ESCHAR's * and other operator tokens presumably processed. Such char's * still in the label can be assumed to have been ESC'd already, * and therefore, we ignore them. Target labels, however, are * raw strings and we must simulate the parser's actions. * */ void ParseLabel( TCHAR *lab, TCHAR buf[], ULONG cbBufMax, BOOLEAN flag ) { ULONG i ; TCHAR c ; lab = EatWS(lab,NULL) ; /* Strip normal whitespace */ if ((c = *lab) == COLON || c == PLUS) /* Eat first : or + ... */ ++lab ; /* ...only */ if (!flag) /* If target strip... */ lab = EatWS(lab,NULL) ; /* ... any add'l WS */ for (i = 0, c = *lab ; i < cbBufMax ; c = *(++lab)) { DEBUG((CTGRP,COLVL,"ParseLabel: Current Char = %04x", *lab)) ; if ((flag && mystrchr(Delimiters, c)) || //mystrchr("+:\n\r\x20", c)) { mystrchr( TEXT("+:\n\r\t "), c)) { //change from \x20 to space bug // mips compiler DEBUG((CTGRP,COLVL,"ParseLabel: Found terminating delim.")) ; break ; } ; if (!flag) { if (mystrchr(TEXT("&<|>"), c)) { DEBUG((CTGRP,COLVL, "ParseLabel: Found operator in target!")) ; break ; } ; if (c == ESCHAR) { DEBUG((CTGRP,COLVL, "ParseLabel: Found '^' adding %04x", *(lab+1))) ; buf[i++] = *(++lab) ; continue ; } ; } ; DEBUG((CTGRP,COLVL,"ParseLabel: Adding %02x",c)) ; buf[i++] = c ; } ; buf[i] = NULLC ; DEBUG((CTGRP,COLVL,"ParseLabel: Exitted with label %ws", buf)) ; } /*** EatWS - Strip leading whitespace and other special chars (M020) * * Purpose: * Remove leading whitespace and any special chars from the string. * * TCHAR *EatWS(TCHAR *str, TCHAR *spec) * * Args: * str - The string to eat from * spec - Additional delimiters to eat * * Returns: * Updated character pointer * * Notes: * */ PTCHAR EatWS(str,spec) TCHAR *str ; TCHAR *spec ; { TCHAR c ; if (str != NULL) { while ((_istspace(c = *str) && c != NLN) || (mystrchr(Delimiters, c) && c) || (spec && mystrchr(spec,c) && c)) ++str ; } return(str) ; } /*** IsValidDrv - Check drive validity * * Purpose: * Check validity of passed drive letter. * * int IsValidDrv(TCHAR drv) * * Args: * drv - The letter of the drive to check * * Returns: * TRUE if drive is valid * FALSE if not * * Notes: * */ IsValidDrv(TCHAR drv) { TCHAR temp[4]; temp[ 0 ] = drv; temp[ 1 ] = COLON; temp[ 2 ] = PathChar; temp[ 3 ] = NULLC; // // return of 0 or 1 mean can't determine or root // does not exists. // if (GetDriveType(temp) <= 1) return( FALSE ); else { return( TRUE ); } } /*** IsDriveLocked - Check For Drive Locked Condition * * Purpose: * The real purpose is to check for a drive locked, but since this * could be the first time that the disk get hit we will just return * the Dos Error Code * * int IsDriveLocked(TCHAR drv) * * Args: * drv - The letter of the drive to check * * Returns: * 0 if no errors * Dos Error number if failure * * Notes: * */ IsDriveLocked( TCHAR drv ) { DWORD Vsn[2]; TCHAR szVolName[MAX_PATH]; TCHAR szVolRoot[5]; DWORD rc; szVolRoot[ 0 ] = drv; szVolRoot[ 1 ] = COLON; szVolRoot[ 2 ] = PathChar; szVolRoot[ 3 ] = NULLC; // // If floppy and locked will get this. // if ( (rc = GetDriveType(szVolRoot)) <= 1) { return( TRUE ); } // // If removable check if access to vol. info allowed. // if not then assume it is locked. // if ((rc != DRIVE_REMOVABLE) && (rc != DRIVE_CDROM)) { if (!GetVolumeInformation(szVolRoot, szVolName, MAX_PATH, Vsn, NULL, NULL, NULL, 0)) { if ( GetLastError() == ERROR_ACCESS_DENIED) { return( TRUE ); } } } return( FALSE ); } /*** PtrErr - Print Error resulting from last recorded system call * * Purpose: * Prints appropriate error message resulting from last system * call whose return code is saved in DosErr variable. * * int PtrErr(unsigned msgnum) * * Args: * msgnum = Default message to print if no match * * Returns: * Nothing * * Notes: * msgnum can be passed in as NULL if no msg is to be printed as a * default. * */ void PrtErr(msgnum) unsigned msgnum ; { unsigned i, /* Temp counter */ tabmsg = (unsigned)MSG_USE_DEFAULT ; /* Table message found */ for (i = 0 ; mstabl[i].errnum != 0 ; ++i) { if (DosErr == mstabl[i].errnum) { tabmsg = mstabl[i].msnum ; break ; } } if (tabmsg != (unsigned)MSG_USE_DEFAULT) msgnum = tabmsg ; if (msgnum) PutStdErr(msgnum, NOARGS) ; /* @@ */ } /*** GetMsg - Get a message ***/ int GetMsg(unsigned MsgNum, unsigned NumOfArgs, ...) { va_list arglist; va_start(arglist, NumOfArgs); msglen = FormatMessage(MsgNum >= MSG_RESPONSE_DATA ? FORMAT_MESSAGE_FROM_HMODULE : FORMAT_MESSAGE_FROM_SYSTEM, NULL, MsgNum, 0, MsgBuf, sizeof(MsgBuf) / sizeof(TCHAR), &arglist ); va_end(arglist); if (msglen) { return( NO_ERROR ); } else { return( GetLastError() ); } } /**** dayptr - return pointer to day of the week * * Purpose: * To return a pointer to the string representing the current day of * the week. * * Args: * dow - number representing the day of the week. * */ TCHAR *dayptr( dow ) unsigned dow; { switch( dow ) { case 0: return ShortSundayName; case 1: return ShortMondayName; case 2: return ShortTuesdayName; case 3: return ShortWednesdayName; case 4: return ShortThursdayName; case 5: return ShortFridayName; default: return ShortSaturdayName; } } /********************** START OF SPECIFICATIONS **********************/ /* SUBROUTINE NAME: Copen_Work2 */ /* */ /* DESCRIPTIVE NAME: Worker routine to open a file. */ /* */ /* FUNCTION: Opens a file or device and saves the handle for */ /* possible later signal cleanup. Set the extended */ /* attribute information from the file being opened. */ /* */ /* NOTES: Signal cleanup table does not include STDIN, STDOUT or */ /* STDERR. M017 - Extensively rewritten to use CreateFile */ /* rather than runtime open(). */ /* */ /* ENTRY POINT: Copen_Work2 */ /* LINKAGE: Copen_Work2(fn, flags, fShareMode, eaop, FSwitch) */ /* */ /* INPUT: (PARAMETERS) */ /* */ /* filename = ASCIZ filename to open */ /* flags = Flags controlling type of open to make */ /* fShareMode = Flags for callers sharing mode */ /* eaop = Extended attribute buffer pointer. */ /* FSwitch = Fail if EAs can't be copied */ /* */ /* EXIT-NORMAL: */ /* Return file handle value like C runtime open */ /* */ /* EXIT-ERROR: */ /* Return -1 if open failed */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* FileIsDevice - test for file or device via DOSQHANDTYPE */ /* SetList - add handle from open to cleanup list */ /* varb:DosErr - global error return variable */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* CreateFile - open a file with ability for EA processing */ /* */ /*********************** END OF SPECIFICATIONS ***********************/ CRTHANDLE Copen_Work2(fn, flags, fShareMode, FSwitch) TCHAR *fn ; /* filename */ unsigned int flags, fShareMode, FSwitch ; /* flags and special case flags */ { HANDLE handl ; /* Handle ret'd */ CRTHANDLE rcode; /* return code */ DWORD fAccess; DWORD fCreate; SECURITY_ATTRIBUTES sa; sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof(SECURITY_ATTRIBUTES); /***************************************************************************/ /* Note that O_RDONLY being a value of 0, cannot be tested for */ /* conflicts with any of the write type flags. */ /***************************************************************************/ DBG_UNREFERENCED_PARAMETER( FSwitch); if (((flags & (O_WRONLY | O_RDWR)) > 2) || /* Flags invalid? */ ((flags & O_WRONLY) && /* */ (flags & O_APPEND))) { /* */ DEBUG((CTGRP, COLVL, "COPEN: Bad flags issued %04x",flags)) ; rcode = BADHANDLE; /* set bad handle */ } else { /***************************************************************************/ /* M024 - Altered so that the only sharing restriction is to deny */ /* others write permission if this open is for writing. Any other */ /* sharing is allowed. */ /***************************************************************************/ if(flags & (O_WRONLY | O_RDWR)) { /* If Writing, set... */ fAccess = GENERIC_WRITE; if (flags & O_RDWR) fAccess |= GENERIC_READ; /* * deny write only if it is not console */ if (_tcsicmp(fn, TEXT("con"))) { fShareMode = FILE_SHARE_READ; } fCreate = CREATE_ALWAYS;/* ...open if exists, else create */ } else { fAccess = GENERIC_READ; fCreate = OPEN_EXISTING; if (!_tcsicmp(fn,TEXT("con"))) { fShareMode = FILE_SHARE_READ; } } fn = stripit(fn); if (fCreate == CREATE_ALWAYS && (handl=CreateFile(fn, fAccess, fShareMode, &sa, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL)) != INVALID_HANDLE_VALUE) { rcode = _open_osfhandle((long)handl, _O_APPEND); } else if ((handl = CreateFile(fn, fAccess, fShareMode, &sa, fCreate, FILE_ATTRIBUTE_NORMAL, NULL)) == INVALID_HANDLE_VALUE) { DosErr = GetLastError(); DEBUG((CTGRP,COLVL, "COPEN: CreateFile ret'd %d",DosErr)) ; if (DosErr==ERROR_OPEN_FAILED) { DosErr=ERROR_FILE_NOT_FOUND; /* change to another error */ } rcode = BADHANDLE; } else { rcode = _open_osfhandle((long)handl, _O_APPEND); } /* */ } /* */ return(rcode ) ; /* return handle to caller */ } /********************** START OF SPECIFICATIONS **********************/ /* SUBROUTINE NAME: Copen2 */ /* */ /* DESCRIPTIVE NAME: Open a destination file with extended attributes*/ /* */ /* FUNCTION: Call a worker routine to open a destination file or */ /* device and set the extended attribute information */ /* from the source file if this is the first file */ /* and/or only file and there are extended attributes */ /* available. */ /* */ /* NOTES: */ /* */ /* ENTRY POINT: Copen2 */ /* LINKAGE: Copen2(fn, flags, FSwitch) */ /* */ /* INPUT: (PARAMETERS) */ /* */ /* fn = ASCIZ filename to open */ /* flags = Flags controlling type of open to make */ /* */ /* */ /* EXIT-NORMAL: */ /* Return file handle value like C runtime open */ /* */ /* EXIT-ERROR: */ /* Return -1 if open failed */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* Copen_Work2 - worker routine for performing CreateFile */ /* varb: first_fflag-TRUE = first file FALSE = not first file */ /* */ /* */ /*********************** END OF SPECIFICATIONS ***********************/ CRTHANDLE Copen2(fn, flags, FSwitch) TCHAR *fn ; /* file name */ unsigned int flags ; /* open flags */ unsigned FSwitch; { return(Copen_Work2(fn, flags, FILE_SHARE_READ | FILE_SHARE_WRITE, FSwitch)); } /********************** START OF SPECIFICATIONS **********************/ /* SUBROUTINE NAME: Copen_Copy2 */ /* */ /* DESCRIPTIVE NAME: Open a source file with extended attributes. */ /* */ /* FUNCTION: Call a worker routine to open a source file or device */ /* and get the extended attribute information from the */ /* file if ffirst2 or fnext2 says this is a EA file. */ /* */ /* NOTES: */ /* */ /* ENTRY POINT: Copen_Copy2 */ /* LINKAGE: Copen2(fn, flags) */ /* */ /* INPUT: (PARAMETERS) */ /* */ /* fn = ASCIZ filename to open */ /* flags = Flags controlling type of open to make */ /* */ /* EXIT-NORMAL: */ /* Return file handle value like C runtime open */ /* */ /* EXIT-ERROR: */ /* Return -1 if open failed */ /* */ /* EFFECTS: None. */ /* */ /* INTERNAL REFERENCES: */ /* ROUTINES: */ /* Copen_Work2 - worker routine for performing CreateFile */ /* Cclose - close a handle file/device handle opened */ /* and remove handle from handles to free */ /* varb: first_file- TRUE = first file FALSE = not first file */ /* */ /* */ /* */ /* EXTERNAL REFERENCES: */ /* ROUTINES: */ /* DOSALLOCSEG - request an amount of ram memory */ /* DOSFREESEG - free a DOSALLOCSEG segment of ram memory */ /* DOSQFILEINFO - request EA info for a file using level 2 */ /* */ /*********************** END OF SPECIFICATIONS ***********************/ CRTHANDLE Copen_Copy2(fn, flags) TCHAR *fn; /* file name */ unsigned int flags ; /* open flags */ { return(Copen_Work2(fn, flags, FILE_SHARE_READ | FILE_SHARE_WRITE, TRUE)); } CRTHANDLE Copen_Copy3(fn) TCHAR *fn; /* file name */ { HANDLE handl ; /* Handle ret'd */ CRTHANDLE rcode; /* return code */ SECURITY_ATTRIBUTES sa; sa.bInheritHandle = TRUE; sa.lpSecurityDescriptor = NULL; sa.nLength = sizeof(SECURITY_ATTRIBUTES); fn = stripit(fn); handl = CreateFile(fn, GENERIC_WRITE, 0, &sa, TRUNCATE_EXISTING, FILE_ATTRIBUTE_NORMAL, NULL); if (handl == INVALID_HANDLE_VALUE) { DosErr = GetLastError(); DEBUG((CTGRP,COLVL, "COPEN: CreateFile ret'd %d",DosErr)) ; if (DosErr==ERROR_OPEN_FAILED) { DosErr=ERROR_FILE_NOT_FOUND; /* change to another error */ } rcode = BADHANDLE; } else { rcode = _open_osfhandle((long)handl, _O_APPEND); } /* */ return(rcode ) ; /* return handle to caller */ } TCHAR * stripit(TCHAR *wrkstr ) { int i,j,slen; static TCHAR tempstr[MAXTOKLEN]; if ( mystrchr(wrkstr,QUOTE) ) { mytcsnset(tempstr, NULLC, MAXTOKLEN); slen= mystrlen(wrkstr); j=0; for (i=0;icmdline)*sizeof(TCHAR)+mystrlen(pcmdnode->argptr)*sizeof(TCHAR)+3*sizeof(TCHAR)))) return(NULL) ; /* The command line is the concatenation of the command head and tail */ mystrcpy(argptr,pcmdnode->cmdline); tptr = argptr+mystrlen(argptr); if (mystrlen(pcmdnode->argptr)) { if (*pcmdnode->argptr != SPACE) { //DbgPrint("GetTitle: first arg char not space %s\n",pcmdnode->argptr); *tptr++ = SPACE; } mystrcpy(tptr,pcmdnode->argptr); tptr[mystrlen(tptr)+1] = NULLC; /* Add extra null byte */ } tptr = argptr; return( tptr ); } VOID SetConTitle( IN PTCHAR pszTitle ) { ULONG cbNewTitle, cbTitle; PTCHAR pszNewTitle; if (pszTitle == NULL) { return; } if ((!CurBat) && (!fSingleCmdLine)) { if ((pszNewTitle = (PTCHAR)HeapAlloc(GetProcessHeap(), 0, (MAX_PATH+2)*sizeof(TCHAR))) == NULL) { return; } cbNewTitle = GetConsoleTitle( pszNewTitle, MAX_PATH ); if (!cbNewTitle) { return; } cbTitle = mystrlen(pszTitle); pszNewTitle = (PTCHAR)HeapReAlloc(GetProcessHeap(), 0, pszNewTitle, (cbNewTitle+cbTitle+cbTitleCurPrefix+10)*sizeof(TCHAR)); if (pszNewTitle == NULL) { return; } if (fTitleChanged) { _tcscpy( pszNewTitle + cbTitleCurPrefix, pszTitle ); } else { _tcscat( pszNewTitle, TEXT(" - ") ); cbTitleCurPrefix = _tcslen( pszNewTitle ); _tcscat( pszNewTitle, pszTitle ); fTitleChanged = TRUE; } SetConsoleTitle(pszNewTitle); HeapFree(GetProcessHeap(), 0, pszNewTitle); } } VOID ResetConTitle( IN PTCHAR pszTitle ) { if (pszTitle == NULL) { return; } if ((!CurBat) && (fTitleChanged)) { SetConsoleTitle(pszTitle); cbTitleCurPrefix = 0; fTitleChanged = FALSE; } } /*** *void ResetConsoleMode( void ) - make sure correct mode bits are set * *Purpose: * Called after each external command or ^C in case they hosed out modes. * *Entry: *Exit: * *Exceptions: * *******************************************************************************/ void ResetConsoleMode( void ) { DWORD dwDesiredOutputMode = ENABLE_PROCESSED_OUTPUT | ENABLE_WRAP_AT_EOL_OUTPUT; DWORD dwDesiredInputMode = ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT; SetConsoleMode(CRTTONT(STDOUT), dwCurOutputConMode); if (GetConsoleMode(CRTTONT(STDOUT), &dwCurOutputConMode)) { if ((dwCurOutputConMode & dwDesiredOutputMode) != dwDesiredOutputMode) { dwCurOutputConMode |= dwDesiredOutputMode; SetConsoleMode(CRTTONT(STDOUT), dwCurOutputConMode); } } if (GetConsoleMode(CRTTONT(STDIN),&dwCurInputConMode)) { if ((dwCurInputConMode & dwDesiredInputMode) != dwDesiredInputMode || dwCurInputConMode & ENABLE_MOUSE_INPUT ) { dwCurInputConMode &= ~ENABLE_MOUSE_INPUT; dwCurInputConMode |= dwDesiredInputMode; SetConsoleMode(CRTTONT(STDIN), dwCurInputConMode); } } } /*** *void mytcsnset(string, val, count) - set count characters to val * *Purpose: * Sets the first count characters of string the character value. * *Entry: * tchar_t *string - string to set characters in * tchar_t val - character to fill with * size_t count - count of characters to fill * *Exit: * returns string, now filled with count copies of val. * *Exceptions: * *******************************************************************************/ void mytcsnset ( PTCHAR string, TCHAR val, int count ) { while (count--) *string++ = val; return; }