|
|
#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<count; i++) { if (i < NumOfArgs) { LocalArgList[i] = (PTCHAR)va_arg( *arglist, ULONG ); } else { LocalArgList[i] = NullArg; } } msglen = FormatMessage(msgsource | FORMAT_MESSAGE_ARGUMENT_ARRAY, NULL, MsgNum, 0, MsgBuf, sizeof(MsgBuf) / sizeof(TCHAR), (va_list *)LocalArgList ); HeapFree(GetProcessHeap(), 0, LocalArgList); } else { msglen = FormatMessage(msgsource, NULL, MsgNum, 0, MsgBuf, sizeof(MsgBuf) / sizeof(TCHAR), arglist ); } #if DBG
if (msglen == 0) { error = GetLastError(); DEBUG((CTGRP, COLVL, "FindMsg: FormatMessage error %d",error)) ; } #endif
} return msglen; }
/*** PutMsg - Print a message to a handle
* * Purpose: * PutMsg is the work routine which interfaces command.com with the * DOS message retriever. This routine is called by PutStdOut and * PutStdErr. * * int PutMsg(unsigned MsgNum, unsigned Handle, unsigned NumOfArgs, ...) * * Args: * MsgNum - the number of the message to print * NumOfArgs - the number of total arguments * Handle - the handle to print to * Arg1 [Arg2...] - the additonal arguments for the message * * Returns: * Return value from DOSPUTMESSAGE M026 * * Notes: * - PutMsg builds an argument table which is passed to DOSGETMESSAGE; * this table contains the variable information which the DOS routine * inserts into the message. * - If more than one Arg is sent into PutMsg, it (or they) are taken * from the stack in the first for loop. * - M020 MsgBuf is a static array of 2K length. It is temporary and * will be replaced by a more efficient method when decided upon. * */
int PutMsg(unsigned int MsgNum, CRTHANDLE Handle, unsigned int NumOfArgs, va_list *arglist) { unsigned msglen,writelen; unsigned rc; PTCHAR msgptr; PTCHAR NullArg = TEXT(" "); DWORD cb;
rc = 0; /* live with */ msglen = FindMsg(MsgNum,NullArg,NumOfArgs,arglist);
msgptr = MsgBuf; writelen = msglen; for (msgptr=MsgBuf ; msglen!=0 ; msgptr+=writelen,msglen-=writelen) { if (FileIsConsole(Handle)) { //
// write a maximum of MAXTOWRITE chars at a time so ctrl-s works
//
writelen = min(MAXTOWRITE,msglen); if (!WriteConsole(CRTTONT(Handle), msgptr, writelen, &rc, NULL)) { #if DBG
fprintf(stderr, "PutMsg - WriteConsole error %d, tried to write %d, only got\n", GetLastError(), writelen, rc); #endif
rc = GetLastError(); } else { rc = 0; continue; } } if (MyWriteFile(Handle, msgptr, writelen*sizeof(TCHAR), &cb) == 0 || cb != writelen*sizeof(TCHAR)) { rc = GetLastError(); #if DBG
fprintf(stderr, "PutMsg - WriteFile error %d\n", rc); #endif
break; } else { rc = 0; } }
if ( rc ) { //
// If you can not even display a message, then you */
// might as well just give up */
//
Abort();
} return NO_ERROR; }
/*** argstr1/argstr2 - Create formatted message in memory
* * Purpose: * Uses sprintf to create a formatted text string in memory to * use in message output. * * TCHAR *argstr1/argstr2(TCHAR *format, unsigned long arg) * * Args: * Format - the format string * arg - the arguments for the message * * Returns: * Pointer to the formatted message text * * Notes: * - M020 argstr1 and argstr2 use TmpBuf[128-191] and TmpBuf[192-256] * respectively to build their print strings. This limits any * two args to 64 bytes each and a single arg to 128 bytes. It * is doubtful if we would want to build arguments larger than * this, BUT IT MUST BE CHECKED WHEN THESE TWO ARE CALLED!!!!! * */
PTCHAR argstr1(format, arg) TCHAR *format; unsigned long arg; { wsprintf(&TmpBuf[MAX_PATH], format, arg); /* M020 */ return(&TmpBuf[MAX_PATH]); }
TCHAR * argstr2(format, arg) TCHAR *format; unsigned long arg; { wsprintf(&TmpBuf[MAX_PATH*2], format, arg); /* M020 */ return(&TmpBuf[MAX_PATH*2]); }
/*** Copen - CMD.EXE open function (M014)
* * Purpose: * Opens a file or device and saves the handle for possible later * signal cleanup. * * int Copen(TCHAR *fn, int flags) * * Args: * fn = ASCIZ filename to open * flags = Flags controlling type of open to make * fShareMode = Flags for callers sharing mode * * Returns: * Return value from C runtime open * * Notes: * Signal cleanup table does not include STDIN, STDOUT or STDERR. * M017 - Extensively rewritten to use CreateFile rather than * runtime open(). * */
CRTHANDLE Copen_Work(fn, flags, fShareMode) TCHAR *fn ; unsigned int flags, fShareMode; { TCHAR c; DWORD fAccess; DWORD fCreate; HANDLE handle ; DWORD cb; LONG high; CRTHANDLE fh; 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. */ if (((flags & (O_WRONLY | O_RDWR)) > 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;i<slen;i++) { if ( wrkstr[i] != QUOTE ) tempstr[j++] = wrkstr[i];
} tempstr[j] = NULLC; return(tempstr); } else return(wrkstr); }
BOOLEAN GotValidResponses; TCHAR chY_Char; TCHAR chN_Char;
BOOLEAN PromptUser ( IN PTCHAR szArg, IN ULONG msgId )
/*++
Routine Description:
Prompts user for Y or N answer to a question. The prompt can be a message plus an optional single argument.
Arguments:
pszTok - list of attributes
Return Value:
TRUE if user answered yes. FALSE otherwise
Return: the user response
--*/
{
BOOLEAN fFirst; TCHAR chT; TCHAR chAnsw = NULLC; ULONG dwOutputModeOld; ULONG dwOutputModeCur; ULONG dwInputModeOld; ULONG dwInputModeCur; BOOLEAN fOutputModeSet = FALSE; BOOLEAN fInputModeSet = FALSE; HANDLE hndStdOut = NULL; HANDLE hndStdIn = NULL; DWORD cb;
if (!GotValidResponses) { //
// Get yes and no message strings
//
if ((GetMsg(MSG_RESPONSE_DATA,0) == 0 )) { chY_Char = _totupper(MsgBuf[0]); chN_Char = _totupper(MsgBuf[2]); } else { chY_Char = TEXT('Y'); chN_Char = TEXT('N'); }
GotValidResponses = TRUE; }
hndStdOut = GetStdHandle(STD_OUTPUT_HANDLE); if (GetConsoleMode( hndStdOut, &dwOutputModeOld) ) {
// make sure CRLF is processed correctly
dwOutputModeCur = dwOutputModeOld | ENABLE_PROCESSED_OUTPUT; fOutputModeSet = TRUE; SetConsoleMode(hndStdOut,dwOutputModeCur); GetLastError();
}
hndStdIn = GetStdHandle(STD_INPUT_HANDLE); if (GetConsoleMode( hndStdIn, &dwInputModeOld) ) {
// make sure input is processed correctly
dwInputModeCur = dwInputModeOld | ENABLE_LINE_INPUT | ENABLE_ECHO_INPUT | ENABLE_PROCESSED_INPUT; fInputModeSet = TRUE; SetConsoleMode(hndStdIn,dwInputModeCur); GetLastError();
}
//
// Loop till the user answer with a valid character
//
while (chAnsw != chY_Char && chAnsw != chN_Char) {
chT = NULLC; fFirst = TRUE ; if (szArg) { PutStdOut(msgId, ONEARG, szArg ); } else { PutStdOut(msgId, NOARGS); }
//
// Flush keyboard before asking for response
//
if (FileIsDevice(STDIN)) { FlushConsoleInputBuffer( GetStdHandle(STD_INPUT_HANDLE) ); }
//
// Read till EOL
//
while (chT != NLN) {
if (ReadBufFromInput( GetStdHandle(STD_INPUT_HANDLE), (TCHAR*)&chT, 1, &cb) == 0 || cb != 1) {
chAnsw = chN_Char ; cmd_printf(CrLf) ; break; }
if (fFirst) { chAnsw = _totupper(chT) ; fFirst = FALSE ; }
if (!FileIsDevice(STDIN) || !(flgwd & 1)) { cmd_printf(Fmt19,chT) ; } } } if (fOutputModeSet) { SetConsoleMode( hndStdOut, dwOutputModeOld ); } if (fInputModeSet) { SetConsoleMode( hndStdIn, dwInputModeOld ); } return((BOOLEAN)(chAnsw == chY_Char)); }
ULONG LastMsgNo;
int eSpecialHelp( IN struct cmdnode *pcmdnode ) { TCHAR szHelpStr[] = TEXT("/\0?");
if (LastMsgNo == MSG_HELP_FOR) CheckHelpSwitch(FORTYP, szHelpStr); else if (LastMsgNo == MSG_HELP_IF) CheckHelpSwitch(IFTYP, szHelpStr); else if (LastMsgNo == MSG_HELP_REM) CheckHelpSwitch(REMTYP, szHelpStr); else PutStdOut( LastMsgNo, NOARGS );
return SUCCESS; }
BOOLEAN CheckHelp ( IN ULONG jmptblidx, IN PTCHAR pszTok, IN BOOL fDisplay )
{ ULONG msgno = JumpTable[jmptblidx].msgno; ULONG extmsgno = JumpTable[jmptblidx].extmsgno; ULONG extmsgno1 =JumpTable[jmptblidx].extmsgno1;
while (*pszTok) { if (*pszTok == SwitChar) { //
// Check for /?. Ignore /? if ? not followed by delimeter and IF command
// This allows if ./?. == ..
//
if (*(pszTok + 2) == QMARK && (jmptblidx != IFTYP || *(pszTok + 3) == NULLC) ) {
if (msgno == 0 && fEnableExtensions) { msgno = extmsgno; extmsgno = 0; }
if (msgno == 0) { msgno = MSG_SYNERR_GENL; extmsgno = 0; extmsgno1 = 0; }
if ( fDisplay ) { //
// Display help now
//
PutStdOut(msgno, NOARGS); if (fEnableExtensions) { if (extmsgno != 0) PutStdOut(extmsgno, NOARGS); if (extmsgno1 != 0) PutStdOut(extmsgno1, NOARGS); } } else { //
// Remember the message, somebody will display it later.
// extmsgno will always be zero here
//
LastMsgNo = msgno; } return( TRUE );
} //
// move over SwitChar, switch value and 2 0's
//
pszTok += mystrlen(pszTok) + 1; if (*pszTok) { pszTok += mystrlen(pszTok) + 1; }
} else if (jmptblidx == ECHTYP) { //
// ECHO only supports /? as first token. Allows you echo a string
// with /? in it (e.g. ECHO Update /?).
//
break; } else {
//
// move over param. and 1 0's
//
pszTok += mystrlen(pszTok) + 1; } }
return( FALSE );
}
BOOLEAN TokBufCheckHelp( IN PTCHAR pszTokBuf, IN ULONG jmptblidx )
{
TCHAR szT[10]; PTCHAR pszTok;
//
// Tokensize the command line (special delimeters are tokens)
//
szT[0] = SwitChar ; szT[1] = NULLC ;
pszTok = TokStr(pszTokBuf, szT, TS_SDTOKENS); return CheckHelp(jmptblidx, pszTok, FALSE); }
BOOLEAN CheckHelpSwitch ( IN ULONG jmptblidx, IN PTCHAR pszTok )
{ return CheckHelp( jmptblidx, pszTok, TRUE ) ; }
PTCHAR GetTitle( IN struct cmdnode *pcmdnode )
{ PTCHAR tptr, argptr; /* Allocate string space for command line */ /* Command_Head + Optional_Space + Command_Tail + Null + Null */
if (!(argptr = mkstr(mystrlen(pcmdnode->cmdline)*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; }
|