📄 cmd.c
字号:
*cp++ = _totlower (*rest++);
if (*rest == _T('"'))
rest++;
}
else
{
while (!IsDelimiter (*rest))
*cp++ = _totlower (*rest++);
}
/* Terminate first word */
*cp = _T('\0');
/* Do not limit commands to MAX_PATH */
/*
if(_tcslen(com) > MAX_PATH)
{
error_bad_command();
cmd_free(com);
return;
}
*/
/* Skip over whitespace to rest of line, exclude 'echo' command */
if (_tcsicmp (com, _T("echo")))
{
while (_istspace (*rest))
rest++;
}
/* Scan internal command table */
for (cmdptr = cmds;; cmdptr++)
{
/* If end of table execute ext cmd */
if (cmdptr->name == NULL)
{
Execute (line, com, rest);
break;
}
if (!_tcscmp (com, cmdptr->name))
{
cmdptr->func (com, rest);
break;
}
/* The following code handles the case of commands like CD which
* are recognised even when the command name and parameter are
* not space separated.
*
* e.g dir..
* cd\freda
*/
/* Get length of command name */
cl = _tcslen (cmdptr->name);
if ((cmdptr->flags & CMD_SPECIAL) &&
(!_tcsncmp (cmdptr->name, com, cl)) &&
(_tcschr (_T("\\.-"), *(com + cl))))
{
/* OK its one of the specials...*/
/* Terminate first word properly */
com[cl] = _T('\0');
/* Call with new rest */
cmdptr->func (com, cstart + cl);
break;
}
}
}
cmd_free(com);
}
/*
* process the command line and execute the appropriate functions
* full input/output redirection and piping are supported
*/
VOID ParseCommandLine (LPTSTR cmd)
{
TCHAR szMsg[RC_STRING_MAX_SIZE];
TCHAR cmdline[CMDLINE_LENGTH];
LPTSTR s;
#ifdef FEATURE_REDIRECTION
TCHAR in[CMDLINE_LENGTH] = _T("");
TCHAR out[CMDLINE_LENGTH] = _T("");
TCHAR err[CMDLINE_LENGTH] = _T("");
TCHAR szTempPath[MAX_PATH] = _T(".\\");
TCHAR szFileName[2][MAX_PATH] = {_T(""), _T("")};
HANDLE hFile[2] = {INVALID_HANDLE_VALUE, INVALID_HANDLE_VALUE};
LPTSTR t = NULL;
INT num = 0;
INT nRedirFlags = 0;
INT Length;
UINT Attributes;
BOOL bNewBatch = TRUE;
HANDLE hOldConIn;
HANDLE hOldConOut;
HANDLE hOldConErr;
#endif /* FEATURE_REDIRECTION */
_tcscpy (cmdline, cmd);
s = &cmdline[0];
#ifdef _DEBUG
DebugPrintf (_T("ParseCommandLine: (\'%s\')\n"), s);
#endif /* DEBUG */
#ifdef FEATURE_ALIASES
/* expand all aliases */
ExpandAlias (s, CMDLINE_LENGTH);
#endif /* FEATURE_ALIAS */
#ifdef FEATURE_REDIRECTION
/* find the temp path to store temporary files */
Length = GetTempPath (MAX_PATH, szTempPath);
if (Length > 0 && Length < MAX_PATH)
{
Attributes = GetFileAttributes(szTempPath);
if (Attributes == 0xffffffff ||
!(Attributes & FILE_ATTRIBUTE_DIRECTORY))
{
Length = 0;
}
}
if (Length == 0 || Length >= MAX_PATH)
{
_tcscpy(szTempPath, _T(".\\"));
}
if (szTempPath[_tcslen (szTempPath) - 1] != _T('\\'))
_tcscat (szTempPath, _T("\\"));
/* get the redirections from the command line */
num = GetRedirection (s, in, out, err, &nRedirFlags);
/* more efficient, but do we really need to do this? */
for (t = in; _istspace (*t); t++)
;
_tcscpy (in, t);
for (t = out; _istspace (*t); t++)
;
_tcscpy (out, t);
for (t = err; _istspace (*t); t++)
;
_tcscpy (err, t);
if(bc && !_tcslen (in) && _tcslen (bc->In))
_tcscpy(in, bc->In);
if(bc && !out[0] && _tcslen(bc->Out))
{
nRedirFlags |= OUTPUT_APPEND;
_tcscpy(out, bc->Out);
}
if(bc && !_tcslen (err) && _tcslen (bc->Err))
{
nRedirFlags |= ERROR_APPEND;
_tcscpy(err, bc->Err);
}
/* Set up the initial conditions ... */
/* preserve STDIN, STDOUT and STDERR handles */
hOldConIn = GetStdHandle (STD_INPUT_HANDLE);
hOldConOut = GetStdHandle (STD_OUTPUT_HANDLE);
hOldConErr = GetStdHandle (STD_ERROR_HANDLE);
/* redirect STDIN */
if (in[0])
{
HANDLE hFile;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
/* we need make sure the LastError msg is zero before calling CreateFile */
SetLastError(0);
/* Set up pipe for the standard input handler */
hFile = CreateFile (in, GENERIC_READ, FILE_SHARE_READ, &sa, OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, in);
return;
}
if (!SetStdHandle (STD_INPUT_HANDLE, hFile))
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR1, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, in);
return;
}
#ifdef _DEBUG
DebugPrintf (_T("Input redirected from: %s\n"), in);
#endif
}
/* Now do all but the last pipe command */
*szFileName[0] = _T('\0');
hFile[0] = INVALID_HANDLE_VALUE;
while (num-- > 1)
{
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
/* Create unique temporary file name */
GetTempFileName (szTempPath, _T("CMD"), 0, szFileName[1]);
/* we need make sure the LastError msg is zero before calling CreateFile */
SetLastError(0);
/* Set current stdout to temporary file */
hFile[1] = CreateFile (szFileName[1], GENERIC_WRITE, 0, &sa,
TRUNCATE_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
if (hFile[1] == INVALID_HANDLE_VALUE)
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR2, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg);
return;
}
SetStdHandle (STD_OUTPUT_HANDLE, hFile[1]);
DoCommand (s);
/* close stdout file */
SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
if ((hFile[1] != INVALID_HANDLE_VALUE) && (hFile[1] != hOldConOut))
{
CloseHandle (hFile[1]);
hFile[1] = INVALID_HANDLE_VALUE;
}
/* close old stdin file */
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
if ((hFile[0] != INVALID_HANDLE_VALUE) && (hFile[0] != hOldConIn))
{
/* delete old stdin file, if it is a real file */
CloseHandle (hFile[0]);
hFile[0] = INVALID_HANDLE_VALUE;
DeleteFile (szFileName[0]);
*szFileName[0] = _T('\0');
}
/* copy stdout file name to stdin file name */
_tcscpy (szFileName[0], szFileName[1]);
*szFileName[1] = _T('\0');
/* we need make sure the LastError msg is zero before calling CreateFile */
SetLastError(0);
/* open new stdin file */
hFile[0] = CreateFile (szFileName[0], GENERIC_READ, 0, &sa,
OPEN_EXISTING, FILE_ATTRIBUTE_TEMPORARY, NULL);
SetStdHandle (STD_INPUT_HANDLE, hFile[0]);
s = s + _tcslen (s) + 1;
}
/* Now set up the end conditions... */
/* redirect STDOUT */
if (out[0])
{
/* Final output to here */
HANDLE hFile;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
/* we need make sure the LastError msg is zero before calling CreateFile */
SetLastError(0);
hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
(nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
INT size = _tcslen(out)-1;
if (out[size] != _T(':'))
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, out);
return;
}
out[size]=_T('\0');
hFile = CreateFile (out, GENERIC_WRITE, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, &sa,
(nRedirFlags & OUTPUT_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH, NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, out);
return;
}
}
if (!SetStdHandle (STD_OUTPUT_HANDLE, hFile))
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, out);
return;
}
if (nRedirFlags & OUTPUT_APPEND)
{
LONG lHighPos = 0;
if (GetFileType (hFile) == FILE_TYPE_DISK)
SetFilePointer (hFile, 0, &lHighPos, FILE_END);
}
#ifdef _DEBUG
DebugPrintf (_T("Output redirected to: %s\n"), out);
#endif
}
else if (hOldConOut != INVALID_HANDLE_VALUE)
{
/* Restore original stdout */
HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
if (hOldConOut != hOut)
CloseHandle (hOut);
hOldConOut = INVALID_HANDLE_VALUE;
}
/* redirect STDERR */
if (err[0])
{
/* Final output to here */
HANDLE hFile;
SECURITY_ATTRIBUTES sa = {sizeof(SECURITY_ATTRIBUTES), NULL, TRUE};
if (!_tcscmp (err, out))
{
#ifdef _DEBUG
DebugPrintf (_T("Stdout and stderr will use the same file!!\n"));
#endif
DuplicateHandle (GetCurrentProcess (),
GetStdHandle (STD_OUTPUT_HANDLE),
GetCurrentProcess (),
&hFile, 0, TRUE, DUPLICATE_SAME_ACCESS);
}
else
{
hFile = CreateFile (err,
GENERIC_WRITE,
FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE,
&sa,
(nRedirFlags & ERROR_APPEND) ? OPEN_ALWAYS : CREATE_ALWAYS,
FILE_ATTRIBUTE_NORMAL | FILE_FLAG_WRITE_THROUGH,
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, err);
return;
}
}
if (!SetStdHandle (STD_ERROR_HANDLE, hFile))
{
LoadString(CMD_ModuleHandle, STRING_CMD_ERROR3, szMsg, RC_STRING_MAX_SIZE);
ConErrPrintf(szMsg, err);
return;
}
if (nRedirFlags & ERROR_APPEND)
{
LONG lHighPos = 0;
if (GetFileType (hFile) == FILE_TYPE_DISK)
SetFilePointer (hFile, 0, &lHighPos, FILE_END);
}
#ifdef _DEBUG
DebugPrintf (_T("Error redirected to: %s\n"), err);
#endif
}
else if (hOldConErr != INVALID_HANDLE_VALUE)
{
/* Restore original stderr */
HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
if (hOldConErr != hErr)
CloseHandle (hErr);
hOldConErr = INVALID_HANDLE_VALUE;
}
if(bc)
bNewBatch = FALSE;
#endif
/* process final command */
DoCommand (s);
#ifdef FEATURE_REDIRECTION
if(bNewBatch && bc)
AddBatchRedirection(in, out, err);
/* close old stdin file */
#if 0 /* buggy implementation */
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
if ((hFile[0] != INVALID_HANDLE_VALUE) &&
(hFile[0] != hOldConIn))
{
/* delete old stdin file, if it is a real file */
CloseHandle (hFile[0]);
hFile[0] = INVALID_HANDLE_VALUE;
DeleteFile (szFileName[0]);
*szFileName[0] = _T('\0');
}
/* Restore original STDIN */
if (hOldConIn != INVALID_HANDLE_VALUE)
{
HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
if (hOldConIn != hIn)
CloseHandle (hIn);
hOldConIn = INVALID_HANDLE_VALUE;
}
else
{
#ifdef _DEBUG
DebugPrintf (_T("Can't restore STDIN! Is invalid!!\n"), out);
#endif
}
#endif /* buggy implementation */
if (hOldConIn != INVALID_HANDLE_VALUE)
{
HANDLE hIn = GetStdHandle (STD_INPUT_HANDLE);
SetStdHandle (STD_INPUT_HANDLE, hOldConIn);
if (hIn == INVALID_HANDLE_VALUE)
{
#ifdef _DEBUG
DebugPrintf (_T("Previous STDIN is invalid!!\n"));
#endif
}
else
{
if (GetFileType (hIn) == FILE_TYPE_DISK)
{
if (hFile[0] == hIn)
{
CloseHandle (hFile[0]);
hFile[0] = INVALID_HANDLE_VALUE;
DeleteFile (szFileName[0]);
*szFileName[0] = _T('\0');
}
else
{
#ifdef _DEBUG
DebugPrintf (_T("hFile[0] and hIn dont match!!!\n"));
#endif
}
}
}
}
/* Restore original STDOUT */
if (hOldConOut != INVALID_HANDLE_VALUE)
{
HANDLE hOut = GetStdHandle (STD_OUTPUT_HANDLE);
SetStdHandle (STD_OUTPUT_HANDLE, hOldConOut);
if (hOldConOut != hOut)
CloseHandle (hOut);
hOldConOut = INVALID_HANDLE_VALUE;
}
/* Restore original STDERR */
if (hOldConErr != INVALID_HANDLE_VALUE)
{
HANDLE hErr = GetStdHandle (STD_ERROR_HANDLE);
SetStdHandle (STD_ERROR_HANDLE, hOldConErr);
if (hOldConErr != hErr)
CloseHandle (hErr);
hOldConErr = INVALID_HANDLE_VALUE;
}
#endif /* FEATURE_REDIRECTION */
}
BOOL
GrowIfNecessary ( UINT needed, LPTSTR* ret, UINT* retlen )
{
if ( *ret && needed < *retlen )
return TRUE;
*retlen = needed;
if ( *ret )
cmd_free ( *ret );
*ret = (LPTSTR)cmd_alloc ( *retlen * sizeof(TCHAR) );
if ( !*ret )
SetLastError ( ERROR_OUTOFMEMORY );
return *ret != NULL;
}
LPCTSTR
GetEnvVarOrSpecial ( LPCTSTR varName )
{
static LPTSTR ret = NULL;
static UINT retlen = 0;
UINT size;
size = GetEnvironmentVariable ( varName, ret, retlen );
if ( size > retlen )
{
if ( !GrowIfNecessary ( size, &ret, &retlen ) )
return NULL;
size = GetEnvironmentVariable ( varName, ret, retlen );
}
if ( size )
return ret;
/* env var doesn't exist, look for a "special" one */
/* %CD% */
if (_tcsicmp(varName,_T("cd")) ==0)
{
size = GetCurrentDirectory ( retlen, ret );
if ( size > retlen )
{
if ( !GrowIfNecessary ( size, &ret, &retlen ) )
return NULL;
size = GetCurrentDirectory ( retlen, ret );
}
if ( !size )
return NULL;
return ret;
}
/* %TIME% */
else if (_tcsicmp(varName,_T("time")) ==0)
{
SYSTEMTIME t;
if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
return NULL;
GetSystemTime(&t);
_sntprintf ( ret, retlen, _T("%02d%c%02d%c%02d%c%02d"),
t.wHour, cTimeSeparator, t.wMinute, cTimeSeparator,
t.wSecond, cDecimalSeparator, t.wMilliseconds / 10);
return ret;
}
/* %DATE% */
else if (_tcsicmp(varName,_T("date")) ==0)
{
if ( !GrowIfNecessary ( GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, NULL, 0), &ret, &retlen ) )
return NULL;
size = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, ret, retlen);
if ( !size )
return NULL;
return ret;
}
/* %RANDOM% */
else if (_tcsicmp(varName,_T("random")) ==0)
{
if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
return NULL;
/* Get random number */
_itot(rand(),ret,10);
return ret;
}
/* %CMDCMDLINE% */
else if (_tcsicmp(varName,_T("cmdcmdline")) ==0)
{
return GetCommandLine();
}
/* %CMDEXTVERSION% */
else if (_tcsicmp(varName,_T("cmdextversion")) ==0)
{
if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
return NULL;
/* Set version number to 2 */
_itot(2,ret,10);
return ret;
}
/* %ERRORLEVEL% */
else if (_tcsicmp(varName,_T("errorlevel")) ==0)
{
if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
return NULL;
_itot(nErrorLevel,ret,10);
return ret;
}
GrowIfNecessary(_tcslen(varName) + 2, &ret, &retlen);
_stprintf(ret,_T("%%%s%%"),varName);
return ret; /* not found - return orginal string */
}
LPCTSTR
GetParsedEnvVar ( LPCTSTR varName, UINT* varNameLen, BOOL ModeSetA )
{
static LPTSTR ret = NULL;
static UINT retlen = 0;
LPTSTR p, tmp;
UINT size;
if ( varNameLen )
*varNameLen = 0;
SetLastError(0);
if ( *varName++ != '%' )
return NULL;
switch ( *varName )
{
case _T('0'):
case _T('1'):
case _T('2'):
case _T('3'):
case _T('4'):
case _T('5'):
case _T('6'):
case _T('7'):
case _T('8'):
case _T('9'):
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -