- Implement CMD /D, /Q, and /R switches
authorJeffrey Morlan <mrnobo1024@yahoo.com>
Thu, 26 Mar 2009 01:14:25 +0000 (01:14 +0000)
committerJeffrey Morlan <mrnobo1024@yahoo.com>
Thu, 26 Mar 2009 01:14:25 +0000 (01:14 +0000)
- 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

reactos/base/shell/cmd/batch.c
reactos/base/shell/cmd/cmd.c
reactos/base/shell/cmd/cmd.h
reactos/base/shell/cmd/echo.c
reactos/base/shell/cmd/error.c
reactos/base/shell/cmd/for.c
reactos/base/shell/cmd/parser.c
reactos/base/shell/cmd/setlocal.c
reactos/base/shell/cmd/verify.c

index e8c2b07..aab0b67 100644 (file)
@@ -293,9 +293,10 @@ 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)
                {
-                       ConOutChar(_T('\n'));
+                       if (!bIgnoreEcho)
+                               ConOutChar(_T('\n'));
                        PrintPrompt();
                        EchoCommand(Cmd);
                        ConOutChar(_T('\n'));
index a7e0e53..5a4f3d4 100644 (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,7 +1510,11 @@ 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);
@@ -1542,10 +1547,7 @@ ProcessInput()
                        continue;
 
                ExecuteCommand(Cmd);
-               if (bEcho && !bIgnoreEcho)
-                       ConOutChar ('\n');
                FreeCommand(Cmd);
-               bIgnoreEcho = FALSE;
        }
        while (!bCanExit || !bExit);
 
@@ -1676,7 +1678,8 @@ ExecuteAutoRunFile (VOID)
                            (LPBYTE)autorun, 
                            &len) == ERROR_SUCCESS)
            {
-                   ParseCommandLine (autorun);
+                       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);
+                               /* Remainder of command line is a command to be run */
+                               break;
                        }
-                       else if (_totlower(ptr[1]) == _T('k'))
+                       else if (option == _T('D'))
                        {
-                               /* This just runs a program and remains */
-                               GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
-                               ParseCommandLine(commandline);
-                               ShowVersion = FALSE;
-                               break;
+                               AutoRun = FALSE;
                        }
-                       else if (_totlower(ptr[1]) == _T('s'))
+                       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,24 +1845,21 @@ 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)
-    {
-        /* Display a simple version string */
+       if (!*ptr)
+       {
+               /* 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"));
-    }
-
-    ExecuteAutoRunFile ();
+                       _T(KERNEL_RELEASE_STR),
+                       _T(KERNEL_VERSION_BUILD_STR));
+               ConOutPuts(_T("(C) Copyright 1998-") _T(COPYRIGHT_YEAR) _T(" ReactOS Team."));
+       }
 
 #ifdef FEATURE_DIR_STACK
        /* initialize directory stack */
@@ -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);
+       }
 }
 
 
index f0ae1a3..fc21bbb 100644 (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);
index e6ea2d1..324facd 100644 (file)
 
 #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'))
-               {
-                       /* skip the first character */
-                       ConOutPuts(param + 1);
-               }
-               else
-               {
-                       ConOutResPrintf(STRING_ECHO_HELP5, bEcho ? D_ON : D_OFF);
-               }
-
+       if (!OnOffCommand(p1, &bEcho, STRING_ECHO_HELP5))
+       {
+               /* skip the first character */
+               ConOutPuts(param + 1);
+       }
        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);
-
+       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;
 }
 
index 35e4ec5..aa7eae4 100644 (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;
 }
 
index 84cf68f..4488d6a 100644 (file)
@@ -71,9 +71,10 @@ 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)
        {
-               ConOutChar(_T('\n'));
+               if (!bIgnoreEcho)
+                       ConOutChar(_T('\n'));
                PrintPrompt();
                EchoCommand(Cmd->Subcommands);
                ConOutChar(_T('\n'));
index a0a09f8..c2f41bd 100644 (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;
index ed6fb69..51284c9 100644 (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")))
-               bDelayedExpansion = TRUE;
-       else if (!_tcsicmp(param, _T("disabledelayedexpansion")))
-               bDelayedExpansion = FALSE;
-       else
-               error_invalid_parameter_format(param);
+       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(arg[i], _T("disabledelayedexpansion")))
+                       bDelayedExpansion = FALSE;
+               else
+               {
+                       error_invalid_parameter_format(arg[i]);
+                       break;
+               }
+       }
+       freep(arg);
 
        return nErrorLevel;
 }
index dba702e..e184891 100644 (file)
@@ -35,22 +35,13 @@ INT cmd_verify (LPTSTR param)
                return 0;
        }
 
-  nErrorLevel = 0;
-
-       if (!*param)
-       {
-               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
+       if (!OnOffCommand(param, &bVerify, STRING_VERIFY_HELP2))
        {
-               ConOutResPuts(STRING_VERIFY_HELP3);
+               ConErrResPuts(STRING_VERIFY_HELP3);
+               return nErrorLevel = 1;
        }
 
-       return 0;
+       return nErrorLevel = 0;
 }
 
 #endif