📄 cmd.c
字号:
#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 )
free ( *ret );
*ret = (LPTSTR)malloc ( *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)
{
LPTSTR tmp;
if ( !GrowIfNecessary ( MAX_PATH, &ret, &retlen ) )
return NULL;
size = GetDateFormat(LOCALE_USER_DEFAULT, 0, NULL, _T("ddd"), ret, retlen );
/* TODO FIXME - test whether GetDateFormat() can return a value indicating the buffer wasn't big enough */
if ( !size )
return NULL;
tmp = ret + _tcslen(ret);
*tmp++ = _T(' ');
size = GetDateFormat(LOCALE_USER_DEFAULT, DATE_SHORTDATE, NULL, NULL, tmp, retlen-(tmp-ret));
/* TODO FIXME - test whether GetDateFormat() can return a value indicating the buffer wasn't big enough */
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'):
if ((tmp = FindArg (*varName - _T('0'))))
{
if ( varNameLen )
*varNameLen = 2;
if ( !*tmp )
return _T("");
if ( !GrowIfNecessary ( _tcslen(tmp)+1, &ret, &retlen ) )
return NULL;
_tcscpy ( ret, tmp );
return ret;
}
if ( !GrowIfNecessary ( 3, &ret, &retlen ) )
return NULL;
ret[0] = _T('%');
ret[1] = *varName;
ret[2] = 0;
if ( varNameLen )
*varNameLen = 2;
return ret;
case _T('*'):
if(bc == NULL)
{
//
// No batch file to see here, move along
//
if ( !GrowIfNecessary ( 3, &ret, &retlen ) )
return NULL;
ret[0] = _T('%');
ret[1] = _T('*');
ret[2] = 0;
if ( varNameLen )
*varNameLen = 2;
return ret;
}
//
// Copy over the raw params(not including the batch file name
//
if ( !GrowIfNecessary ( _tcslen(bc->raw_params)+1, &ret, &retlen ) )
return NULL;
if ( varNameLen )
*varNameLen = 2;
_tcscpy ( ret, bc->raw_params );
return ret;
case _T('%'):
if ( !GrowIfNecessary ( 2, &ret, &retlen ) )
return NULL;
ret[0] = _T('%');
ret[1] = 0;
if ( varNameLen )
*varNameLen = 2;
return ret;
case _T('?'):
/* TODO FIXME 10 is only max size for 32-bit */
if ( !GrowIfNecessary ( 11, &ret, &retlen ) )
return NULL;
_sntprintf ( ret, retlen, _T("%u"), nErrorLevel);
ret[retlen-1] = 0;
if ( varNameLen )
*varNameLen = 2;
return ret;
}
if ( ModeSetA )
{
/* HACK for set/a */
if ( !GrowIfNecessary ( 2, &ret, &retlen ) )
return NULL;
ret[0] = _T('%');
ret[1] = 0;
if ( varNameLen )
*varNameLen = 1;
return ret;
}
p = _tcschr ( varName, _T('%') );
if ( !p )
{
SetLastError ( ERROR_INVALID_PARAMETER );
return NULL;
}
size = p-varName;
if ( varNameLen )
*varNameLen = size + 2;
p = alloca ( (size+1) * sizeof(TCHAR) );
memmove ( p, varName, size * sizeof(TCHAR) );
p[size] = 0;
varName = p;
return GetEnvVarOrSpecial ( varName );
}
/*
* do the prompt/input/process loop
*
*/
static INT
ProcessInput (BOOL bFlag)
{
TCHAR commandline[CMDLINE_LENGTH];
TCHAR readline[CMDLINE_LENGTH];
LPTSTR ip;
LPTSTR cp;
LPCTSTR tmp;
BOOL bEchoThisLine;
BOOL bModeSetA;
BOOL bIsBatch;
do
{
/* if no batch input then... */
if (!(ip = ReadBatchLine (&bEchoThisLine)))
{
if (bFlag)
return nErrorLevel;
ReadCommand (readline, CMDLINE_LENGTH);
ip = readline;
bEchoThisLine = FALSE;
bIsBatch = FALSE;
}
else
{
bIsBatch = TRUE;
}
/* skip leading blanks */
while ( _istspace(*ip) )
++ip;
cp = commandline;
bModeSetA = FALSE;
while (*ip)
{
if ( *ip == _T('%') )
{
UINT envNameLen;
LPCTSTR envVal = GetParsedEnvVar ( ip, &envNameLen, bModeSetA );
if ( envVal )
{
ip += envNameLen;
cp = _stpcpy ( cp, envVal );
}
}
if (_istcntrl (*ip))
*ip = _T(' ');
*cp++ = *ip++;
/* HACK HACK HACK check whether bModeSetA needs to be toggled */
*cp = 0;
tmp = commandline;
tmp += _tcsspn(tmp,_T(" \t"));
/* first we find and skip and pre-redirections... */
while (( tmp ) &&
( _tcschr(_T("<>"),*tmp)
|| !_tcsncmp(tmp,_T("1>"),2)
|| !_tcsncmp(tmp,_T("2>"),2) ))
{
if ( _istdigit(*tmp) )
tmp += 2;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -