Handle quotes in a CMD /C or CMD /K argument properly.

svn path=/trunk/; revision=39795
This commit is contained in:
Jeffrey Morlan 2009-02-27 18:09:33 +00:00
parent 83f58a9337
commit 9ed19ef909

View file

@ -1529,23 +1529,73 @@ ExecuteAutoRunFile (VOID)
RegCloseKey(hkey);
}
/* Get the command that comes after a /C or /K switch */
static VOID
GetCmdLineCommand(TCHAR *commandline, TCHAR *ptr, BOOL AlwaysStrip)
{
TCHAR *LastQuote;
while (_istspace(*ptr))
ptr++;
/* Remove leading quote, find final quote */
if (*ptr == _T('"') &&
(LastQuote = _tcsrchr(++ptr, _T('"'))) != NULL)
{
TCHAR *Space;
/* Under certain circumstances, all quotes are preserved.
* CMD /? documents these conditions as follows:
* 1. No /S switch
* 2. Exactly two quotes
* 3. No "special characters" between the quotes
* (CMD /? says &<>()@^| but parentheses did not
* trigger this rule when I tested them.)
* 4. Whitespace exists between the quotes
* 5. Enclosed string is an executable filename
*/
*LastQuote = _T('\0');
for (Space = ptr + 1; Space < LastQuote; Space++)
{
if (_istspace(*Space)) /* Rule 4 */
{
if (!AlwaysStrip && /* Rule 1 */
!_tcspbrk(ptr, _T("\"&<>@^|")) && /* Rules 2, 3 */
SearchForExecutable(ptr, commandline)) /* Rule 5 */
{
/* All conditions met: preserve both the quotes */
*LastQuote = _T('"');
_tcscpy(commandline, ptr - 1);
return;
}
break;
}
}
/* The conditions were not met: remove both the
* leading quote and the last quote */
_tcscpy(commandline, ptr);
_tcscpy(&commandline[LastQuote - ptr], LastQuote + 1);
return;
}
/* No quotes; just copy */
_tcscpy(commandline, ptr);
}
/*
* set up global initializations and process parameters
*
* argc - number of parameters to command.com
* argv - command-line parameters
*
*/
static VOID
Initialize (int argc, const TCHAR* argv[])
Initialize()
{
TCHAR commandline[CMDLINE_LENGTH];
TCHAR ModuleName[_MAX_PATH + 1];
INT i;
TCHAR lpBuffer[2];
//INT len;
//TCHAR *ptr, *cmdLine;
TCHAR *ptr, *cmdLine;
BOOL AlwaysStrip = FALSE;
BOOL ShowVersion = TRUE;
/* get version information */
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@ -1572,13 +1622,8 @@ Initialize (int argc, const TCHAR* argv[])
NtReadVirtualMemoryPtr = (NtReadVirtualMemoryProc)GetProcAddress(NtDllModule, "NtReadVirtualMemory");
}
TRACE ("[command args:\n");
for (i = 0; i < argc; i++)
{
TRACE ("%d. %s\n", i, debugstr_aw(argv[i]));
}
TRACE ("]\n");
cmdLine = GetCommandLine();
TRACE ("[command args: %s]\n", debugstr_aw(cmdLine));
InitLocale ();
@ -1594,22 +1639,22 @@ Initialize (int argc, const TCHAR* argv[])
SetEnvironmentVariable (_T("PROMPT"), _T("$P$G"));
if (argc >= 2 && !_tcsncmp (argv[1], _T("/?"), 2))
{
ConOutResPaging(TRUE,STRING_CMD_HELP8);
cmd_exit(0);
}
SetConsoleMode (hIn, ENABLE_PROCESSED_INPUT);
#ifdef INCLUDE_CMD_CHDIR
InitLastPath ();
#endif
if (argc >= 2)
for (ptr = cmdLine; *ptr; ptr++)
{
for (i = 1; i < argc; i++)
if (*ptr == _T('/'))
{
if (!_tcsicmp (argv[i], _T("/p")))
if (ptr[1] == _T('?'))
{
ConOutResPaging(TRUE,STRING_CMD_HELP8);
cmd_exit(0);
}
else if (_totlower(ptr[1]) == _T('p'))
{
if (!IsExistingFile (_T("\\autoexec.bat")))
{
@ -1626,56 +1671,38 @@ Initialize (int argc, const TCHAR* argv[])
}
bCanExit = FALSE;
}
else if (!_tcsicmp (argv[i], _T("/c")))
else if (_totlower(ptr[1]) == _T('c'))
{
/* This just runs a program and exits */
++i;
if (i < argc)
{
_tcscpy (commandline, argv[i]);
while (++i < argc)
{
_tcscat (commandline, _T(" "));
_tcscat (commandline, argv[i]);
}
ParseCommandLine(commandline);
cmd_exit (ProcessInput (TRUE));
}
else
{
cmd_exit (0);
}
GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
ParseCommandLine(commandline);
cmd_exit (ProcessInput (TRUE));
}
else if (!_tcsicmp (argv[i], _T("/k")))
else if (_totlower(ptr[1]) == _T('k'))
{
/* This just runs a program and remains */
++i;
if (i < argc)
{
_tcscpy (commandline, _T("\""));
_tcscat (commandline, argv[i]);
_tcscat (commandline, _T("\""));
while (++i < argc)
{
_tcscat (commandline, _T(" "));
_tcscat (commandline, argv[i]);
}
ParseCommandLine(commandline);
}
GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
ParseCommandLine(commandline);
ShowVersion = FALSE;
break;
}
else if (_totlower(ptr[1]) == _T('s'))
{
AlwaysStrip = TRUE;
}
#ifdef INCLUDE_CMD_COLOR
else if (!_tcsnicmp (argv[i], _T("/t:"), 3))
else if (!_tcsnicmp(ptr, _T("/t:"), 3))
{
/* process /t (color) argument */
wDefColor = (WORD)_tcstoul (&argv[i][3], NULL, 16);
wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
wColor = wDefColor;
SetScreenColor (wColor, TRUE);
}
#endif
}
}
else
if (ShowVersion)
{
/* Display a simple version string */
ConOutPrintf(_T("ReactOS Operating System [Version %s-%s]\n"),
@ -1710,7 +1737,7 @@ Initialize (int argc, const TCHAR* argv[])
}
static VOID Cleanup (int argc, const TCHAR *argv[])
static VOID Cleanup()
{
/* run cmdexit.bat */
if (IsExistingFile (_T("cmdexit.bat")))
@ -1782,13 +1809,13 @@ int cmd_main (int argc, const TCHAR *argv[])
CMD_ModuleHandle = GetModuleHandle(NULL);
/* check switches on command-line */
Initialize(argc, argv);
Initialize();
/* call prompt routine */
nExitCode = ProcessInput(FALSE);
/* do the cleanup */
Cleanup(argc, argv);
Cleanup();
cmd_exit(nExitCode);
return(nExitCode);