- Implement CMD /D, /Q, and /R switches

- Do %envvar% expansions in CMD /C or /K commands
- Make SETLOCAL recognize ENABLEEXTENSIONS and DISABLEEXTENSIONS, although it doesn't do anything yet
- Make VERIFY set the errorlevel (documented in SETLOCAL /?). Also make it recognize when ON/OFF is followed by space
- Make ECHOSERR actually print to stderr, not stdout
- Make echoed display of ( ... ) blocks look nicer (Bug 4022)
- Fix some other minor display bugs

svn path=/trunk/; revision=40244
This commit is contained in:
Jeffrey Morlan 2009-03-26 01:14:25 +00:00
parent 65d9fbc726
commit db8815a497
9 changed files with 139 additions and 106 deletions

View file

@ -293,8 +293,9 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd
/* JPP 19980807 */ /* JPP 19980807 */
/* Echo batch file line */ /* Echo batch file line */
if (bEcho && Cmd->Type != C_QUIET) if (bEcho && !bDisableBatchEcho && Cmd->Type != C_QUIET)
{ {
if (!bIgnoreEcho)
ConOutChar(_T('\n')); ConOutChar(_T('\n'));
PrintPrompt(); PrintPrompt();
EchoCommand(Cmd); EchoCommand(Cmd);

View file

@ -157,6 +157,7 @@ BOOL bCtrlBreak = FALSE; /* Ctrl-Break or Ctrl-C hit */
BOOL bIgnoreEcho = FALSE; /* Set this to TRUE to prevent a newline, when executing a command */ BOOL bIgnoreEcho = FALSE; /* Set this to TRUE to prevent a newline, when executing a command */
INT nErrorLevel = 0; /* Errorlevel of last launched external program */ INT nErrorLevel = 0; /* Errorlevel of last launched external program */
BOOL bChildProcessRunning = FALSE; BOOL bChildProcessRunning = FALSE;
BOOL bDisableBatchEcho = FALSE;
BOOL bDelayedExpansion = FALSE; BOOL bDelayedExpansion = FALSE;
DWORD dwChildProcessId = 0; DWORD dwChildProcessId = 0;
OSVERSIONINFO osvi; OSVERSIONINFO osvi;
@ -1509,8 +1510,12 @@ ReadLine (TCHAR *commandline, BOOL bMore)
{ {
/* JPP 19980807 - if echo off, don't print prompt */ /* JPP 19980807 - if echo off, don't print prompt */
if (bEcho) if (bEcho)
{
if (!bIgnoreEcho)
ConOutChar('\n');
PrintPrompt(); PrintPrompt();
} }
}
ReadCommand (readline, CMDLINE_LENGTH - 1); ReadCommand (readline, CMDLINE_LENGTH - 1);
if (CheckCtrlBreak(BREAK_INPUT)) if (CheckCtrlBreak(BREAK_INPUT))
@ -1542,10 +1547,7 @@ ProcessInput()
continue; continue;
ExecuteCommand(Cmd); ExecuteCommand(Cmd);
if (bEcho && !bIgnoreEcho)
ConOutChar ('\n');
FreeCommand(Cmd); FreeCommand(Cmd);
bIgnoreEcho = FALSE;
} }
while (!bCanExit || !bExit); while (!bCanExit || !bExit);
@ -1676,7 +1678,8 @@ ExecuteAutoRunFile (VOID)
(LPBYTE)autorun, (LPBYTE)autorun,
&len) == ERROR_SUCCESS) &len) == ERROR_SUCCESS)
{ {
ParseCommandLine (autorun); if (*autorun)
ParseCommandLine(autorun);
} }
} }
@ -1748,9 +1751,9 @@ Initialize()
TCHAR lpBuffer[2]; TCHAR lpBuffer[2];
//INT len; //INT len;
TCHAR *ptr, *cmdLine; TCHAR *ptr, *cmdLine, option = 0;
BOOL AlwaysStrip = FALSE; BOOL AlwaysStrip = FALSE;
BOOL ShowVersion = TRUE; BOOL AutoRun = TRUE;
/* get version information */ /* get version information */
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO); osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@ -1793,12 +1796,13 @@ Initialize()
{ {
if (*ptr == _T('/')) if (*ptr == _T('/'))
{ {
if (ptr[1] == _T('?')) option = _totupper(ptr[1]);
if (option == _T('?'))
{ {
ConOutResPaging(TRUE,STRING_CMD_HELP8); ConOutResPaging(TRUE,STRING_CMD_HELP8);
cmd_exit(0); cmd_exit(0);
} }
else if (_totlower(ptr[1]) == _T('p')) else if (option == _T('P'))
{ {
if (!IsExistingFile (_T("\\autoexec.bat"))) if (!IsExistingFile (_T("\\autoexec.bat")))
{ {
@ -1815,27 +1819,25 @@ Initialize()
} }
bCanExit = FALSE; bCanExit = FALSE;
} }
else if (_totlower(ptr[1]) == _T('c')) else if (option == _T('C') || option == _T('K') || option == _T('R'))
{ {
/* This just runs a program and exits */ /* Remainder of command line is a command to be run */
GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
ParseCommandLine(commandline);
cmd_exit(nErrorLevel);
}
else if (_totlower(ptr[1]) == _T('k'))
{
/* This just runs a program and remains */
GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
ParseCommandLine(commandline);
ShowVersion = FALSE;
break; break;
} }
else if (_totlower(ptr[1]) == _T('s')) else if (option == _T('D'))
{
AutoRun = FALSE;
}
else if (option == _T('Q'))
{
bDisableBatchEcho = TRUE;
}
else if (option == _T('S'))
{ {
AlwaysStrip = TRUE; AlwaysStrip = TRUE;
} }
#ifdef INCLUDE_CMD_COLOR #ifdef INCLUDE_CMD_COLOR
else if (!_tcsnicmp(ptr, _T("/t:"), 3)) else if (!_tcsnicmp(ptr, _T("/T:"), 3))
{ {
/* process /t (color) argument */ /* process /t (color) argument */
wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16); wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
@ -1843,25 +1845,22 @@ Initialize()
SetScreenColor (wColor, TRUE); SetScreenColor (wColor, TRUE);
} }
#endif #endif
else if (_totlower(ptr[1]) == _T('v')) else if (option == _T('V'))
{ {
bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":off"), 4); bDelayedExpansion = _tcsnicmp(&ptr[2], _T(":OFF"), 4);
} }
} }
} }
if (ShowVersion) if (!*ptr)
{ {
/* Display a simple version string */ /* If neither /C or /K was given, display a simple version string */
ConOutResPrintf(STRING_REACTOS_VERSION, ConOutResPrintf(STRING_REACTOS_VERSION,
_T(KERNEL_RELEASE_STR), _T(KERNEL_RELEASE_STR),
_T(KERNEL_VERSION_BUILD_STR)); _T(KERNEL_VERSION_BUILD_STR));
ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team."));
ConOutPuts (_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
} }
ExecuteAutoRunFile ();
#ifdef FEATURE_DIR_STACK #ifdef FEATURE_DIR_STACK
/* initialize directory stack */ /* initialize directory stack */
InitDirectoryStack (); InitDirectoryStack ();
@ -1882,6 +1881,18 @@ Initialize()
/* add ctrl break handler */ /* add ctrl break handler */
AddBreakHandler (); AddBreakHandler ();
if (AutoRun)
ExecuteAutoRunFile();
if (*ptr)
{
/* Do the /C or /K command */
GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
ParseCommandLine(commandline);
if (option != _T('K'))
cmd_exit(nErrorLevel);
}
} }

View file

@ -60,6 +60,7 @@ extern WORD wDefColor;
extern BOOL bCtrlBreak; extern BOOL bCtrlBreak;
extern BOOL bIgnoreEcho; extern BOOL bIgnoreEcho;
extern BOOL bExit; extern BOOL bExit;
extern BOOL bDisableBatchEcho;
extern BOOL bDelayedExpansion; extern BOOL bDelayedExpansion;
extern INT nErrorLevel; extern INT nErrorLevel;
extern SHORT maxx; extern SHORT maxx;
@ -211,6 +212,7 @@ INT CommandDirs (LPTSTR);
/* Prototypes for ECHO.C */ /* Prototypes for ECHO.C */
BOOL OnOffCommand(LPTSTR param, LPBOOL flag, INT message);
INT CommandEcho (LPTSTR); INT CommandEcho (LPTSTR);
INT CommandEchos (LPTSTR); INT CommandEchos (LPTSTR);
INT CommandEchoerr (LPTSTR); INT CommandEchoerr (LPTSTR);

View file

@ -28,10 +28,43 @@
#include <precomp.h> #include <precomp.h>
BOOL
OnOffCommand(LPTSTR param, LPBOOL flag, INT message)
{
TCHAR *p2;
if (_tcsnicmp(param, D_OFF, sizeof(D_OFF)/sizeof(TCHAR) - 1) == 0)
{
p2 = param + sizeof(D_OFF)/sizeof(TCHAR) - 1;
while (_istspace(*p2))
p2++;
if (*p2 == _T('\0'))
{
*flag = FALSE;
return TRUE;
}
}
else if (_tcsnicmp(param, D_ON, sizeof(D_ON)/sizeof(TCHAR) - 1) == 0)
{
p2 = param + sizeof(D_ON)/sizeof(TCHAR) - 1;
while (_istspace(*p2))
p2++;
if (*p2 == _T('\0'))
{
*flag = TRUE;
return TRUE;
}
}
else if (*param == _T('\0'))
{
ConOutResPrintf(message, *flag ? D_ON : D_OFF);
return TRUE;
}
return FALSE;
}
INT CommandEcho (LPTSTR param) INT CommandEcho (LPTSTR param)
{ {
LPTSTR p1, p2; LPTSTR p1;
TRACE ("CommandEcho: '%s'\n", debugstr_aw(param)); TRACE ("CommandEcho: '%s'\n", debugstr_aw(param));
@ -46,45 +79,16 @@ INT CommandEcho (LPTSTR param)
return 0; return 0;
} }
if (_tcsnicmp (p1, D_OFF, sizeof(D_OFF)/sizeof(TCHAR) - 1) == 0) if (!OnOffCommand(p1, &bEcho, STRING_ECHO_HELP5))
{
p2 = p1 + sizeof(D_OFF)/sizeof(TCHAR) - 1;
while (_istspace(*p2))
p2++;
if (*p2 == _T('\0'))
{
bEcho = FALSE;
return 0;
}
}
else if (_tcsnicmp (p1, D_ON, sizeof(D_ON)/sizeof(TCHAR) - 1) == 0)
{
p2 = p1 + sizeof(D_ON)/sizeof(TCHAR) - 1;
while (_istspace(*p2))
p2++;
if (*p2 == _T('\0'))
{
bEcho = TRUE;
return 0;
}
}
if (*p1 != _T('\0'))
{ {
/* skip the first character */ /* skip the first character */
ConOutPuts(param + 1); ConOutPuts(param + 1);
} }
else
{
ConOutResPrintf(STRING_ECHO_HELP5, bEcho ? D_ON : D_OFF);
}
return 0; return 0;
} }
INT CommandEchos (LPTSTR param) INT CommandEchos (LPTSTR param)
{ {
TRACE ("CommandEchos: '%s'\n", debugstr_aw(param)); TRACE ("CommandEchos: '%s'\n", debugstr_aw(param));
if (!_tcsncmp (param, _T("/?"), 2)) if (!_tcsncmp (param, _T("/?"), 2))
@ -93,16 +97,13 @@ INT CommandEchos (LPTSTR param)
return 0; return 0;
} }
if (*param)
ConOutPrintf (_T("%s"), param); ConOutPrintf (_T("%s"), param);
return 0; return 0;
} }
INT CommandEchoerr (LPTSTR param) INT CommandEchoerr (LPTSTR param)
{ {
TRACE ("CommandEchoerr: '%s'\n", debugstr_aw(param)); TRACE ("CommandEchoerr: '%s'\n", debugstr_aw(param));
if (!_tcsncmp (param, _T("/?"), 2)) if (!_tcsncmp (param, _T("/?"), 2))
@ -112,14 +113,12 @@ INT CommandEchoerr (LPTSTR param)
} }
ConErrPuts (param); ConErrPuts (param);
return 0; return 0;
} }
INT CommandEchoserr (LPTSTR param) INT CommandEchoserr (LPTSTR param)
{ {
TRACE ("CommandEchoserr: '%s'\n", debugstr_aw(param)); TRACE ("CommandEchoserr: '%s'\n", debugstr_aw(param));
if (!_tcsncmp (param, _T("/?"), 2)) if (!_tcsncmp (param, _T("/?"), 2))
@ -128,9 +127,7 @@ INT CommandEchoserr (LPTSTR param)
return 0; return 0;
} }
if (*param) ConErrPrintf (_T("%s"), param);
ConOutPrintf (_T("%s"), param);
return 0; return 0;
} }

View file

@ -141,7 +141,7 @@ VOID error_out_of_memory (VOID)
VOID error_invalid_parameter_format (LPTSTR s) VOID error_invalid_parameter_format (LPTSTR s)
{ {
ConErrResPuts(STRING_ERROR_INVALID_PARAM_FORMAT); ConErrResPrintf(STRING_ERROR_INVALID_PARAM_FORMAT, s);
nErrorLevel = 1; nErrorLevel = 1;
} }

View file

@ -71,8 +71,9 @@ static BOOL GetNextElement(TCHAR **pStart, TCHAR **pEnd)
/* Execute a single instance of a FOR command */ /* Execute a single instance of a FOR command */
static void RunInstance(PARSED_COMMAND *Cmd) static void RunInstance(PARSED_COMMAND *Cmd)
{ {
if (bEcho && Cmd->Subcommands->Type != C_QUIET) if (bEcho && !bDisableBatchEcho && Cmd->Subcommands->Type != C_QUIET)
{ {
if (!bIgnoreEcho)
ConOutChar(_T('\n')); ConOutChar(_T('\n'));
PrintPrompt(); PrintPrompt();
EchoCommand(Cmd->Subcommands); EchoCommand(Cmd->Subcommands);

View file

@ -701,7 +701,8 @@ ParseCommand(LPTSTR Line)
if (Line) if (Line)
{ {
_tcscpy(ParseLine, Line); if (!SubstituteVars(Line, ParseLine, _T('%')))
return NULL;
bLineContinuations = FALSE; bLineContinuations = FALSE;
} }
else else
@ -724,6 +725,11 @@ ParseCommand(LPTSTR Line)
FreeCommand(Cmd); FreeCommand(Cmd);
Cmd = NULL; Cmd = NULL;
} }
bIgnoreEcho = FALSE;
}
else
{
bIgnoreEcho = TRUE;
} }
return Cmd; return Cmd;
} }
@ -748,10 +754,22 @@ EchoCommand(PARSED_COMMAND *Cmd)
return; return;
case C_BLOCK: case C_BLOCK:
ConOutChar(_T('(')); ConOutChar(_T('('));
for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next) Sub = Cmd->Subcommands;
if (Sub && !Sub->Next)
{
/* Single-command block: display all on one line */
EchoCommand(Sub);
}
else if (Sub)
{
/* Multi-command block: display parenthesis on separate lines */
ConOutChar(_T('\n'));
do
{ {
EchoCommand(Sub); EchoCommand(Sub);
ConOutChar(_T('\n')); ConOutChar(_T('\n'));
Sub = Sub->Next;
} while (Sub);
} }
ConOutChar(_T(')')); ConOutChar(_T(')'));
break; break;

View file

@ -35,6 +35,8 @@ DuplicateEnvironment(VOID)
INT cmd_setlocal(LPTSTR param) INT cmd_setlocal(LPTSTR param)
{ {
SETLOCAL *Saved; SETLOCAL *Saved;
LPTSTR *arg;
INT argc, i;
/* SETLOCAL only works inside a batch file */ /* SETLOCAL only works inside a batch file */
if (!bc) if (!bc)
@ -59,14 +61,24 @@ INT cmd_setlocal(LPTSTR param)
nErrorLevel = 0; nErrorLevel = 0;
if (*param == _T('\0')) arg = splitspace(param, &argc);
/* nothing */; for (i = 0; i < argc; i++)
else if (!_tcsicmp(param, _T("enabledelayedexpansion"))) {
if (!_tcsicmp(arg[i], _T("enableextensions")))
/* not implemented, ignore */;
else if (!_tcsicmp(arg[i], _T("disableextensions")))
/* not implemented, ignore */;
else if (!_tcsicmp(arg[i], _T("enabledelayedexpansion")))
bDelayedExpansion = TRUE; bDelayedExpansion = TRUE;
else if (!_tcsicmp(param, _T("disabledelayedexpansion"))) else if (!_tcsicmp(arg[i], _T("disabledelayedexpansion")))
bDelayedExpansion = FALSE; bDelayedExpansion = FALSE;
else else
error_invalid_parameter_format(param); {
error_invalid_parameter_format(arg[i]);
break;
}
}
freep(arg);
return nErrorLevel; return nErrorLevel;
} }

View file

@ -35,22 +35,13 @@ INT cmd_verify (LPTSTR param)
return 0; return 0;
} }
nErrorLevel = 0; if (!OnOffCommand(param, &bVerify, STRING_VERIFY_HELP2))
if (!*param)
{ {
ConOutResPrintf(STRING_VERIFY_HELP2, bVerify ? D_ON : D_OFF); ConErrResPuts(STRING_VERIFY_HELP3);
} return nErrorLevel = 1;
else if (_tcsicmp (param, D_OFF) == 0)
bVerify = FALSE;
else if (_tcsicmp (param, D_ON) == 0)
bVerify = TRUE;
else
{
ConOutResPuts(STRING_VERIFY_HELP3);
} }
return 0; return nErrorLevel = 0;
} }
#endif #endif