mirror of
https://github.com/reactos/reactos.git
synced 2025-07-27 20:32:18 +00:00
Make command parsing in DoCommand/Execute more compatible with Windows
svn path=/trunk/; revision=40280
This commit is contained in:
parent
47bc28fa47
commit
ad25b56ea8
5 changed files with 120 additions and 249 deletions
|
@ -37,7 +37,9 @@
|
||||||
|
|
||||||
INT cmd_call (LPTSTR param)
|
INT cmd_call (LPTSTR param)
|
||||||
{
|
{
|
||||||
TCHAR line[CMDLINE_LENGTH];
|
TCHAR line[CMDLINE_LENGTH + 1];
|
||||||
|
TCHAR *first;
|
||||||
|
BOOL bInQuote = FALSE;
|
||||||
|
|
||||||
TRACE ("cmd_call: (\'%s\')\n", debugstr_aw(param));
|
TRACE ("cmd_call: (\'%s\')\n", debugstr_aw(param));
|
||||||
if (!_tcsncmp (param, _T("/?"), 2))
|
if (!_tcsncmp (param, _T("/?"), 2))
|
||||||
|
@ -50,26 +52,31 @@ INT cmd_call (LPTSTR param)
|
||||||
if (!SubstituteVars(param, line, _T('%')))
|
if (!SubstituteVars(param, line, _T('%')))
|
||||||
return nErrorLevel = 1;
|
return nErrorLevel = 1;
|
||||||
|
|
||||||
param = line;
|
/* Find start and end of first word */
|
||||||
while (_istspace(*param))
|
first = line;
|
||||||
param++;
|
while (_istspace(*first))
|
||||||
if (*param == _T(':') && (bc))
|
first++;
|
||||||
|
|
||||||
|
for (param = first; *param; param++)
|
||||||
|
{
|
||||||
|
if (!bInQuote && (_istspace(*param) || _tcschr(_T(",;="), *param)))
|
||||||
|
break;
|
||||||
|
bInQuote ^= (*param == _T('"'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Separate first word from rest of line */
|
||||||
|
memmove(param + 1, param, (_tcslen(param) + 1) * sizeof(TCHAR));
|
||||||
|
*param++ = _T('\0');
|
||||||
|
|
||||||
|
if (*first == _T(':') && (bc))
|
||||||
{
|
{
|
||||||
/* CALL :label - call a subroutine of the current batch file */
|
/* CALL :label - call a subroutine of the current batch file */
|
||||||
TCHAR *first = param;
|
while (*param == _T(' '))
|
||||||
while (*param && !_istspace(*param))
|
|
||||||
param++;
|
param++;
|
||||||
if (*param)
|
|
||||||
{
|
|
||||||
/* Separate label and arguments */
|
|
||||||
*param++ = _T('\0');
|
|
||||||
while (_istspace(*param))
|
|
||||||
param++;
|
|
||||||
}
|
|
||||||
return !Batch(bc->BatchFilePath, first, param, NULL);
|
return !Batch(bc->BatchFilePath, first, param, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
return !DoCommand(param, NULL);
|
return !DoCommand(first, param, NULL);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* EOF */
|
/* EOF */
|
||||||
|
|
|
@ -213,15 +213,6 @@ ConvertULargeInteger(ULONGLONG num, LPTSTR des, INT len, BOOL bPutSeperator)
|
||||||
return n;
|
return n;
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
|
||||||
* is character a delimeter when used on first word?
|
|
||||||
*
|
|
||||||
*/
|
|
||||||
static BOOL IsDelimiter (TCHAR c)
|
|
||||||
{
|
|
||||||
return (c == _T('/') || c == _T('=') || c == _T('\0') || _istspace (c));
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Is a process a console process?
|
* Is a process a console process?
|
||||||
*/
|
*/
|
||||||
|
@ -313,7 +304,7 @@ HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
|
||||||
/*
|
/*
|
||||||
* This command (in first) was not found in the command table
|
* This command (in first) was not found in the command table
|
||||||
*
|
*
|
||||||
* Full - whole command line
|
* Full - buffer to hold whole command line
|
||||||
* First - first word on command line
|
* First - first word on command line
|
||||||
* Rest - rest of command line
|
* Rest - rest of command line
|
||||||
*/
|
*/
|
||||||
|
@ -321,104 +312,42 @@ HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
|
||||||
static BOOL
|
static BOOL
|
||||||
Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
{
|
{
|
||||||
TCHAR *szFullName=NULL;
|
TCHAR szFullName[MAX_PATH];
|
||||||
TCHAR *first = NULL;
|
TCHAR *first, *rest, *dot;
|
||||||
TCHAR *rest = NULL;
|
|
||||||
TCHAR *full = NULL;
|
|
||||||
TCHAR *dot = NULL;
|
|
||||||
TCHAR szWindowTitle[MAX_PATH];
|
TCHAR szWindowTitle[MAX_PATH];
|
||||||
DWORD dwExitCode = 0;
|
DWORD dwExitCode = 0;
|
||||||
|
TCHAR *FirstEnd;
|
||||||
|
|
||||||
TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(first), debugstr_aw(rest));
|
TRACE ("Execute: \'%s\' \'%s\'\n", debugstr_aw(First), debugstr_aw(Rest));
|
||||||
|
|
||||||
/* we need biger buffer that First, Rest, Full are already
|
|
||||||
need rewrite some code to use cmd_realloc when it need instead
|
|
||||||
of add 512bytes extra */
|
|
||||||
|
|
||||||
first = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
|
|
||||||
if (first == NULL)
|
|
||||||
{
|
|
||||||
error_out_of_memory();
|
|
||||||
nErrorLevel = 1;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
rest = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
|
|
||||||
if (rest == NULL)
|
|
||||||
{
|
|
||||||
cmd_free (first);
|
|
||||||
error_out_of_memory();
|
|
||||||
nErrorLevel = 1;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
full = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
|
|
||||||
if (full == NULL)
|
|
||||||
{
|
|
||||||
cmd_free (first);
|
|
||||||
cmd_free (rest);
|
|
||||||
error_out_of_memory();
|
|
||||||
nErrorLevel = 1;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
szFullName = cmd_alloc ( (_tcslen(Full) + 512) * sizeof(TCHAR));
|
|
||||||
if (full == NULL)
|
|
||||||
{
|
|
||||||
cmd_free (first);
|
|
||||||
cmd_free (rest);
|
|
||||||
cmd_free (full);
|
|
||||||
error_out_of_memory();
|
|
||||||
nErrorLevel = 1;
|
|
||||||
return FALSE;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
/* Though it was already parsed once, we have a different set of rules
|
/* Though it was already parsed once, we have a different set of rules
|
||||||
for parsing before we pass to CreateProccess */
|
for parsing before we pass to CreateProccess */
|
||||||
if(!_tcschr(Full,_T('\"')))
|
if (First[0] == _T('/') || (First[0] && First[1] == _T(':')))
|
||||||
{
|
{
|
||||||
_tcscpy(first,First);
|
/* Use the entire first word as the program name (no change) */
|
||||||
_tcscpy(rest,Rest);
|
FirstEnd = First + _tcslen(First);
|
||||||
_tcscpy(full,Full);
|
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
UINT i = 0;
|
/* If present in the first word, spaces and ,;=/ end the program
|
||||||
|
* name and become the beginning of its parameters. */
|
||||||
BOOL bInside = FALSE;
|
BOOL bInside = FALSE;
|
||||||
rest[0] = _T('\0');
|
for (FirstEnd = First; *FirstEnd; FirstEnd++)
|
||||||
full[0] = _T('\0');
|
|
||||||
first[0] = _T('\0');
|
|
||||||
_tcscpy(first,Full);
|
|
||||||
/* find the end of the command and start of the args */
|
|
||||||
for(i = 0; i < _tcslen(first); i++)
|
|
||||||
{
|
{
|
||||||
if(!_tcsncmp(&first[i], _T("\""), 1))
|
if (!bInside && (_istspace(*FirstEnd) || _tcschr(_T(",;=/"), *FirstEnd)))
|
||||||
bInside = !bInside;
|
|
||||||
if(!_tcsncmp(&first[i], _T(" "), 1) && !bInside)
|
|
||||||
{
|
|
||||||
_tcscpy(rest,&first[i]);
|
|
||||||
first[i] = _T('\0');
|
|
||||||
break;
|
break;
|
||||||
}
|
bInside ^= *FirstEnd == _T('"');
|
||||||
|
|
||||||
}
|
}
|
||||||
i = 0;
|
|
||||||
/* remove any slashes */
|
|
||||||
while(i < _tcslen(first))
|
|
||||||
{
|
|
||||||
if(first[i] == _T('\"'))
|
|
||||||
memmove(&first[i],&first[i + 1], _tcslen(&first[i]) * sizeof(TCHAR));
|
|
||||||
else
|
|
||||||
i++;
|
|
||||||
}
|
|
||||||
/* Drop quotes around it just in case there is a space */
|
|
||||||
_tcscpy(full,_T("\""));
|
|
||||||
_tcscat(full,first);
|
|
||||||
_tcscat(full,_T("\" "));
|
|
||||||
_tcscat(full,rest);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* Copy the new first/rest into the buffer */
|
||||||
|
first = Full;
|
||||||
|
rest = &Full[FirstEnd - First + 1];
|
||||||
|
_tcscpy(rest, FirstEnd);
|
||||||
|
_tcscat(rest, Rest);
|
||||||
|
*FirstEnd = _T('\0');
|
||||||
|
_tcscpy(first, First);
|
||||||
|
|
||||||
/* check for a drive change */
|
/* check for a drive change */
|
||||||
if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
|
if ((_istalpha (first[0])) && (!_tcscmp (first + 1, _T(":"))))
|
||||||
{
|
{
|
||||||
|
@ -435,27 +364,16 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!working) ConErrResPuts (STRING_FREE_ERROR1);
|
if (!working) ConErrResPuts (STRING_FREE_ERROR1);
|
||||||
|
|
||||||
cmd_free (first);
|
|
||||||
cmd_free (rest);
|
|
||||||
cmd_free (full);
|
|
||||||
cmd_free (szFullName);
|
|
||||||
nErrorLevel = 1;
|
|
||||||
return working;
|
return working;
|
||||||
}
|
}
|
||||||
|
|
||||||
/* get the PATH environment variable and parse it */
|
/* get the PATH environment variable and parse it */
|
||||||
/* search the PATH environment variable for the binary */
|
/* search the PATH environment variable for the binary */
|
||||||
if (!SearchForExecutable (first, szFullName))
|
StripQuotes(First);
|
||||||
|
if (!SearchForExecutable(First, szFullName))
|
||||||
{
|
{
|
||||||
error_bad_command (first);
|
error_bad_command(first);
|
||||||
cmd_free (first);
|
return FALSE;
|
||||||
cmd_free (rest);
|
|
||||||
cmd_free (full);
|
|
||||||
cmd_free (szFullName);
|
|
||||||
nErrorLevel = 1;
|
|
||||||
return FALSE;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
GetConsoleTitle (szWindowTitle, MAX_PATH);
|
GetConsoleTitle (szWindowTitle, MAX_PATH);
|
||||||
|
@ -464,6 +382,8 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
dot = _tcsrchr (szFullName, _T('.'));
|
dot = _tcsrchr (szFullName, _T('.'));
|
||||||
if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
|
if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
|
||||||
{
|
{
|
||||||
|
while (*rest == _T(' '))
|
||||||
|
rest++;
|
||||||
TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
|
TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
|
||||||
Batch (szFullName, first, rest, Cmd);
|
Batch (szFullName, first, rest, Cmd);
|
||||||
}
|
}
|
||||||
|
@ -473,8 +393,11 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
PROCESS_INFORMATION prci;
|
PROCESS_INFORMATION prci;
|
||||||
STARTUPINFO stui;
|
STARTUPINFO stui;
|
||||||
|
|
||||||
TRACE ("[EXEC: %s %s]\n", debugstr_aw(full), debugstr_aw(rest));
|
/* build command line for CreateProcess(): first + " " + rest */
|
||||||
/* build command line for CreateProcess() */
|
if (*rest)
|
||||||
|
rest[-1] = _T(' ');
|
||||||
|
|
||||||
|
TRACE ("[EXEC: %s]\n", debugstr_aw(Full));
|
||||||
|
|
||||||
/* fill startup info */
|
/* fill startup info */
|
||||||
memset (&stui, 0, sizeof (STARTUPINFO));
|
memset (&stui, 0, sizeof (STARTUPINFO));
|
||||||
|
@ -487,7 +410,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
|
ENABLE_LINE_INPUT | ENABLE_PROCESSED_INPUT | ENABLE_ECHO_INPUT );
|
||||||
|
|
||||||
if (CreateProcess (szFullName,
|
if (CreateProcess (szFullName,
|
||||||
full,
|
Full,
|
||||||
NULL,
|
NULL,
|
||||||
NULL,
|
NULL,
|
||||||
TRUE,
|
TRUE,
|
||||||
|
@ -534,7 +457,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(full));
|
TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
|
||||||
error_bad_command (first);
|
error_bad_command (first);
|
||||||
nErrorLevel = 1;
|
nErrorLevel = 1;
|
||||||
}
|
}
|
||||||
|
@ -550,10 +473,6 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
OutputCodePage = GetConsoleOutputCP();
|
OutputCodePage = GetConsoleOutputCP();
|
||||||
SetConsoleTitle (szWindowTitle);
|
SetConsoleTitle (szWindowTitle);
|
||||||
|
|
||||||
cmd_free(first);
|
|
||||||
cmd_free(rest);
|
|
||||||
cmd_free(full);
|
|
||||||
cmd_free (szFullName);
|
|
||||||
return nErrorLevel == 0;
|
return nErrorLevel == 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -563,120 +482,60 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
|
||||||
* command is one of them. If it is, call the command. If not, call
|
* command is one of them. If it is, call the command. If not, call
|
||||||
* execute to run it as an external program.
|
* execute to run it as an external program.
|
||||||
*
|
*
|
||||||
* line - the command line of the program to run
|
* first - first word on command line
|
||||||
*
|
* rest - rest of command line
|
||||||
*/
|
*/
|
||||||
|
|
||||||
BOOL
|
BOOL
|
||||||
DoCommand (LPTSTR line, PARSED_COMMAND *Cmd)
|
DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
|
||||||
{
|
{
|
||||||
TCHAR *com = NULL; /* the first word in the command */
|
TCHAR com[_tcslen(first) + _tcslen(rest) + 2]; /* full command line */
|
||||||
TCHAR *cp = NULL;
|
TCHAR *cp;
|
||||||
LPTSTR cstart;
|
LPTSTR param; /* pointer to command's parameters */
|
||||||
LPTSTR rest; /* pointer to the rest of the command line */
|
|
||||||
INT cl;
|
INT cl;
|
||||||
LPCOMMAND cmdptr;
|
LPCOMMAND cmdptr;
|
||||||
BOOL ret = TRUE;
|
BOOL nointernal = FALSE;
|
||||||
|
|
||||||
TRACE ("DoCommand: (\'%s\')\n", debugstr_aw(line));
|
TRACE ("DoCommand: (\'%s\' \'%s\')\n", debugstr_aw(first), debugstr_aw(rest));
|
||||||
|
|
||||||
com = cmd_alloc( (_tcslen(line) +512)*sizeof(TCHAR) );
|
/* If present in the first word, these characters end the name of an
|
||||||
if (com == NULL)
|
* internal command and become the beginning of its parameters. */
|
||||||
|
cp = first + _tcscspn(first, _T("\t +,/;=[]"));
|
||||||
|
|
||||||
|
for (cl = 0; cl < (cp - first); cl++)
|
||||||
{
|
{
|
||||||
error_out_of_memory();
|
/* These characters do it too, but if one of them is present,
|
||||||
return FALSE;
|
* then we check to see if the word is a file name and skip
|
||||||
|
* checking for internal commands if so.
|
||||||
|
* This allows running programs with names like "echo.exe" */
|
||||||
|
if (_tcschr(_T(".:\\"), first[cl]))
|
||||||
|
{
|
||||||
|
TCHAR tmp = *cp;
|
||||||
|
*cp = _T('\0');
|
||||||
|
nointernal = IsExistingFile(first);
|
||||||
|
*cp = tmp;
|
||||||
|
break;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
cp = com;
|
/* Scan internal command table */
|
||||||
/* Skip over initial white space */
|
for (cmdptr = cmds; !nointernal && cmdptr->name; cmdptr++)
|
||||||
while (_istspace (*line))
|
|
||||||
line++;
|
|
||||||
rest = line;
|
|
||||||
|
|
||||||
cstart = rest;
|
|
||||||
|
|
||||||
/* Anything to do ? */
|
|
||||||
if (*rest)
|
|
||||||
{
|
{
|
||||||
if (*rest == _T('"'))
|
if (!_tcsnicmp(first, cmdptr->name, cl) && cmdptr->name[cl] == _T('\0'))
|
||||||
{
|
{
|
||||||
/* treat quoted words specially */
|
_tcscpy(com, first);
|
||||||
|
_tcscat(com, rest);
|
||||||
|
param = &com[cl];
|
||||||
|
|
||||||
rest++;
|
/* Skip over whitespace to rest of line, exclude 'echo' command */
|
||||||
|
if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
|
||||||
while(*rest != _T('\0') && *rest != _T('"'))
|
while (_istspace(*param))
|
||||||
*cp++ = _totlower (*rest++);
|
param++;
|
||||||
if (*rest == _T('"'))
|
return !cmdptr->func(param);
|
||||||
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)
|
|
||||||
{
|
|
||||||
ret = Execute (line, com, rest, Cmd);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!_tcscmp (com, cmdptr->name))
|
|
||||||
{
|
|
||||||
cmdptr->func (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...*/
|
|
||||||
|
|
||||||
/* Call with new rest */
|
|
||||||
cmdptr->func (cstart + cl);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
cmd_free(com);
|
|
||||||
return ret;
|
return Execute(com, first, rest, Cmd);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -825,7 +684,7 @@ BOOL
|
||||||
ExecuteCommand(PARSED_COMMAND *Cmd)
|
ExecuteCommand(PARSED_COMMAND *Cmd)
|
||||||
{
|
{
|
||||||
PARSED_COMMAND *Sub;
|
PARSED_COMMAND *Sub;
|
||||||
LPTSTR ExpandedLine;
|
LPTSTR First, Rest;
|
||||||
BOOL Success = TRUE;
|
BOOL Success = TRUE;
|
||||||
|
|
||||||
if (!PerformRedirection(Cmd->Redirections))
|
if (!PerformRedirection(Cmd->Redirections))
|
||||||
|
@ -834,14 +693,18 @@ ExecuteCommand(PARSED_COMMAND *Cmd)
|
||||||
switch (Cmd->Type)
|
switch (Cmd->Type)
|
||||||
{
|
{
|
||||||
case C_COMMAND:
|
case C_COMMAND:
|
||||||
ExpandedLine = DoDelayedExpansion(Cmd->Command.CommandLine);
|
Success = FALSE;
|
||||||
if (!ExpandedLine)
|
First = DoDelayedExpansion(Cmd->Command.First);
|
||||||
|
if (First)
|
||||||
{
|
{
|
||||||
Success = FALSE;
|
Rest = DoDelayedExpansion(Cmd->Command.Rest);
|
||||||
break;
|
if (Rest)
|
||||||
|
{
|
||||||
|
Success = DoCommand(First, Rest, Cmd);
|
||||||
|
cmd_free(Rest);
|
||||||
|
}
|
||||||
|
cmd_free(First);
|
||||||
}
|
}
|
||||||
Success = DoCommand(ExpandedLine, Cmd);
|
|
||||||
cmd_free(ExpandedLine);
|
|
||||||
break;
|
break;
|
||||||
case C_QUIET:
|
case C_QUIET:
|
||||||
case C_BLOCK:
|
case C_BLOCK:
|
||||||
|
|
|
@ -112,7 +112,7 @@ VOID RemoveBreakHandler (VOID);
|
||||||
BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim);
|
BOOL SubstituteVars(TCHAR *Src, TCHAR *Dest, TCHAR Delim);
|
||||||
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest);
|
BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest);
|
||||||
LPTSTR DoDelayedExpansion(LPTSTR Line);
|
LPTSTR DoDelayedExpansion(LPTSTR Line);
|
||||||
BOOL DoCommand (LPTSTR line, struct _PARSED_COMMAND *Cmd);
|
BOOL DoCommand(LPTSTR first, LPTSTR rest, struct _PARSED_COMMAND *Cmd);
|
||||||
BOOL ReadLine(TCHAR *commandline, BOOL bMore);
|
BOOL ReadLine(TCHAR *commandline, BOOL bMore);
|
||||||
int cmd_main (int argc, const TCHAR *argv[]);
|
int cmd_main (int argc, const TCHAR *argv[]);
|
||||||
|
|
||||||
|
@ -375,8 +375,8 @@ typedef struct _PARSED_COMMAND
|
||||||
{
|
{
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
TCHAR *Tail;
|
TCHAR *Rest;
|
||||||
TCHAR CommandLine[];
|
TCHAR First[];
|
||||||
} Command;
|
} Command;
|
||||||
struct
|
struct
|
||||||
{
|
{
|
||||||
|
|
|
@ -704,11 +704,7 @@ INT CommandShowCommandsDetail (LPTSTR param)
|
||||||
/* If a param was send, display help of correspondent command */
|
/* If a param was send, display help of correspondent command */
|
||||||
if (_tcslen(param))
|
if (_tcslen(param))
|
||||||
{
|
{
|
||||||
LPTSTR NewCommand = cmd_alloc((_tcslen(param)+4)*sizeof(TCHAR));
|
DoCommand(param, _T("/?"), NULL);
|
||||||
_tcscpy(NewCommand, param);
|
|
||||||
_tcscat(NewCommand, _T(" /?"));
|
|
||||||
DoCommand(NewCommand, NULL);
|
|
||||||
cmd_free(NewCommand);
|
|
||||||
}
|
}
|
||||||
/* Else, display detailed commands list */
|
/* Else, display detailed commands list */
|
||||||
else
|
else
|
||||||
|
|
|
@ -576,7 +576,7 @@ static PARSED_COMMAND *ParseCommandPart(void)
|
||||||
Type = ParseToken(_T('('), STANDARD_SEPS);
|
Type = ParseToken(_T('('), STANDARD_SEPS);
|
||||||
if (Type == TOK_NORMAL)
|
if (Type == TOK_NORMAL)
|
||||||
{
|
{
|
||||||
Pos = _stpcpy(ParsedLine, CurrentToken);
|
Pos = _stpcpy(ParsedLine, CurrentToken) + 1;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
else if (Type == TOK_REDIRECTION)
|
else if (Type == TOK_REDIRECTION)
|
||||||
|
@ -645,14 +645,15 @@ static PARSED_COMMAND *ParseCommandPart(void)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
*Pos++ = _T('\0');
|
||||||
|
|
||||||
Cmd = cmd_alloc(FIELD_OFFSET(PARSED_COMMAND, Command.CommandLine[Pos + 1 - ParsedLine]));
|
Cmd = cmd_alloc(FIELD_OFFSET(PARSED_COMMAND, Command.First[Pos - ParsedLine]));
|
||||||
Cmd->Type = C_COMMAND;
|
Cmd->Type = C_COMMAND;
|
||||||
Cmd->Next = NULL;
|
Cmd->Next = NULL;
|
||||||
Cmd->Subcommands = NULL;
|
Cmd->Subcommands = NULL;
|
||||||
Cmd->Redirections = RedirList;
|
Cmd->Redirections = RedirList;
|
||||||
_tcscpy(Cmd->Command.CommandLine, ParsedLine);
|
memcpy(Cmd->Command.First, ParsedLine, (Pos - ParsedLine) * sizeof(TCHAR));
|
||||||
Cmd->Command.Tail = Cmd->Command.CommandLine + TailOffset;
|
Cmd->Command.Rest = Cmd->Command.First + TailOffset;
|
||||||
return Cmd;
|
return Cmd;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -747,7 +748,9 @@ EchoCommand(PARSED_COMMAND *Cmd)
|
||||||
switch (Cmd->Type)
|
switch (Cmd->Type)
|
||||||
{
|
{
|
||||||
case C_COMMAND:
|
case C_COMMAND:
|
||||||
if (SubstituteForVars(Cmd->Command.CommandLine, Buf))
|
if (SubstituteForVars(Cmd->Command.First, Buf))
|
||||||
|
ConOutPrintf(_T("%s"), Buf);
|
||||||
|
if (SubstituteForVars(Cmd->Command.Rest, Buf))
|
||||||
ConOutPrintf(_T("%s"), Buf);
|
ConOutPrintf(_T("%s"), Buf);
|
||||||
break;
|
break;
|
||||||
case C_QUIET:
|
case C_QUIET:
|
||||||
|
@ -852,10 +855,12 @@ Unparse(PARSED_COMMAND *Cmd, TCHAR *Out, TCHAR *OutEnd)
|
||||||
switch (Cmd->Type)
|
switch (Cmd->Type)
|
||||||
{
|
{
|
||||||
case C_COMMAND:
|
case C_COMMAND:
|
||||||
if (!SubstituteForVars(Cmd->Command.CommandLine, Buf)) return NULL;
|
|
||||||
/* This is fragile since there could be special characters, but
|
/* This is fragile since there could be special characters, but
|
||||||
* Windows doesn't bother escaping them, so for compatibility
|
* Windows doesn't bother escaping them, so for compatibility
|
||||||
* we probably shouldn't do it either */
|
* we probably shouldn't do it either */
|
||||||
|
if (!SubstituteForVars(Cmd->Command.First, Buf)) return NULL;
|
||||||
|
STRING(Buf)
|
||||||
|
if (!SubstituteForVars(Cmd->Command.Rest, Buf)) return NULL;
|
||||||
STRING(Buf)
|
STRING(Buf)
|
||||||
break;
|
break;
|
||||||
case C_QUIET:
|
case C_QUIET:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue