- 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 */
/* Echo batch file line */
if (bEcho && Cmd->Type != C_QUIET)
if (bEcho && !bDisableBatchEcho && Cmd->Type != C_QUIET)
{
if (!bIgnoreEcho)
ConOutChar(_T('\n'));
PrintPrompt();
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 */
INT nErrorLevel = 0; /* Errorlevel of last launched external program */
BOOL bChildProcessRunning = FALSE;
BOOL bDisableBatchEcho = FALSE;
BOOL bDelayedExpansion = FALSE;
DWORD dwChildProcessId = 0;
OSVERSIONINFO osvi;
@ -1509,8 +1510,12 @@ ReadLine (TCHAR *commandline, BOOL bMore)
{
/* JPP 19980807 - if echo off, don't print prompt */
if (bEcho)
{
if (!bIgnoreEcho)
ConOutChar('\n');
PrintPrompt();
}
}
ReadCommand (readline, CMDLINE_LENGTH - 1);
if (CheckCtrlBreak(BREAK_INPUT))
@ -1542,10 +1547,7 @@ ProcessInput()
continue;
ExecuteCommand(Cmd);
if (bEcho && !bIgnoreEcho)
ConOutChar ('\n');
FreeCommand(Cmd);
bIgnoreEcho = FALSE;
}
while (!bCanExit || !bExit);
@ -1676,6 +1678,7 @@ ExecuteAutoRunFile (VOID)
(LPBYTE)autorun,
&len) == ERROR_SUCCESS)
{
if (*autorun)
ParseCommandLine(autorun);
}
}
@ -1748,9 +1751,9 @@ Initialize()
TCHAR lpBuffer[2];
//INT len;
TCHAR *ptr, *cmdLine;
TCHAR *ptr, *cmdLine, option = 0;
BOOL AlwaysStrip = FALSE;
BOOL ShowVersion = TRUE;
BOOL AutoRun = TRUE;
/* get version information */
osvi.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
@ -1793,12 +1796,13 @@ Initialize()
{
if (*ptr == _T('/'))
{
if (ptr[1] == _T('?'))
option = _totupper(ptr[1]);
if (option == _T('?'))
{
ConOutResPaging(TRUE,STRING_CMD_HELP8);
cmd_exit(0);
}
else if (_totlower(ptr[1]) == _T('p'))
else if (option == _T('P'))
{
if (!IsExistingFile (_T("\\autoexec.bat")))
{
@ -1815,27 +1819,25 @@ Initialize()
}
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 */
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;
/* Remainder of command line is a command to be run */
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;
}
#ifdef INCLUDE_CMD_COLOR
else if (!_tcsnicmp(ptr, _T("/t:"), 3))
else if (!_tcsnicmp(ptr, _T("/T:"), 3))
{
/* process /t (color) argument */
wDefColor = (WORD)_tcstoul(&ptr[3], &ptr, 16);
@ -1843,25 +1845,22 @@ Initialize()
SetScreenColor (wColor, TRUE);
}
#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,
_T(KERNEL_RELEASE_STR),
_T(KERNEL_VERSION_BUILD_STR));
ConOutPuts (_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team.\n"));
ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team."));
}
ExecuteAutoRunFile ();
#ifdef FEATURE_DIR_STACK
/* initialize directory stack */
InitDirectoryStack ();
@ -1882,6 +1881,18 @@ Initialize()
/* add ctrl break handler */
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 bIgnoreEcho;
extern BOOL bExit;
extern BOOL bDisableBatchEcho;
extern BOOL bDelayedExpansion;
extern INT nErrorLevel;
extern SHORT maxx;
@ -211,6 +212,7 @@ INT CommandDirs (LPTSTR);
/* Prototypes for ECHO.C */
BOOL OnOffCommand(LPTSTR param, LPBOOL flag, INT message);
INT CommandEcho (LPTSTR);
INT CommandEchos (LPTSTR);
INT CommandEchoerr (LPTSTR);

View file

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

View file

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

View file

@ -71,8 +71,9 @@ static BOOL GetNextElement(TCHAR **pStart, TCHAR **pEnd)
/* Execute a single instance of a FOR command */
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'));
PrintPrompt();
EchoCommand(Cmd->Subcommands);

View file

@ -701,7 +701,8 @@ ParseCommand(LPTSTR Line)
if (Line)
{
_tcscpy(ParseLine, Line);
if (!SubstituteVars(Line, ParseLine, _T('%')))
return NULL;
bLineContinuations = FALSE;
}
else
@ -724,6 +725,11 @@ ParseCommand(LPTSTR Line)
FreeCommand(Cmd);
Cmd = NULL;
}
bIgnoreEcho = FALSE;
}
else
{
bIgnoreEcho = TRUE;
}
return Cmd;
}
@ -748,10 +754,22 @@ EchoCommand(PARSED_COMMAND *Cmd)
return;
case C_BLOCK:
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);
ConOutChar(_T('\n'));
Sub = Sub->Next;
} while (Sub);
}
ConOutChar(_T(')'));
break;

View file

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

View file

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