Various fixes to the way cmd handles errorlevel and the "return values" of commands:
[reactos.git] / reactos / base / shell / cmd / cmd.c
index 11a30d3..0ec4d67 100644 (file)
@@ -308,7 +308,7 @@ HANDLE RunFile(DWORD flags, LPTSTR filename, LPTSTR params,
  * Rest  - rest of command line
  */
 
-static BOOL
+static INT
 Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
 {
        TCHAR szFullName[MAX_PATH];
@@ -363,7 +363,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
                }
 
                if (!working) ConErrResPuts (STRING_FREE_ERROR1);
-               return working;
+               return !working;
        }
 
        /* get the PATH environment variable and parse it */
@@ -372,7 +372,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
        if (!SearchForExecutable(First, szFullName))
        {
                error_bad_command(first);
-               return FALSE;
+               return 1;
        }
 
        GetConsoleTitle (szWindowTitle, MAX_PATH);
@@ -384,7 +384,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
                while (*rest == _T(' '))
                        rest++;
                TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
-               Batch (szFullName, first, rest, Cmd);
+               dwExitCode = Batch(szFullName, first, rest, Cmd);
        }
        else
        {
@@ -448,17 +448,13 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
                                GetExitCodeProcess (prci.hProcess, &dwExitCode);
                                nErrorLevel = (INT)dwExitCode;
                        }
-                        else
-                        {
-                            nErrorLevel = 0;
-                        }
                        CloseHandle (prci.hProcess);
                }
                else
                {
                        TRACE ("[ShellExecute failed!: %s]\n", debugstr_aw(Full));
                        error_bad_command (first);
-                       nErrorLevel = 1;
+                       dwExitCode = 1;
                }
 
                // restore console mode
@@ -472,7 +468,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
        OutputCodePage = GetConsoleOutputCP();
        SetConsoleTitle (szWindowTitle);
 
-       return nErrorLevel == 0;
+       return dwExitCode;
 }
 
 
@@ -485,7 +481,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
  * rest  - rest of command line
  */
 
-BOOL
+INT
 DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
 {
        TCHAR com[_tcslen(first) + _tcslen(rest) + 2];  /* full command line */
@@ -530,7 +526,7 @@ DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
                        if (_tcsicmp(cmdptr->name, _T("echo")) != 0)
                                while (_istspace(*param))
                                        param++;
-                       return !cmdptr->func(param);
+                       return cmdptr->func(param);
                }
        }
 
@@ -543,14 +539,16 @@ DoCommand(LPTSTR first, LPTSTR rest, PARSED_COMMAND *Cmd)
  * full input/output redirection and piping are supported
  */
 
-VOID ParseCommandLine (LPTSTR cmd)
+INT ParseCommandLine (LPTSTR cmd)
 {
+       INT Ret = 0;
        PARSED_COMMAND *Cmd = ParseCommand(cmd);
        if (Cmd)
        {
-               ExecuteCommand(Cmd);
+               Ret = ExecuteCommand(Cmd);
                FreeCommand(Cmd);
        }
+       return Ret;
 }
 
 /* Execute a command without waiting for it to finish. If it's an internal
@@ -679,27 +677,27 @@ failed:
 #endif
 }
 
-BOOL
+INT
 ExecuteCommand(PARSED_COMMAND *Cmd)
 {
        PARSED_COMMAND *Sub;
        LPTSTR First, Rest;
-       BOOL Success = TRUE;
+       INT Ret = 0;
 
        if (!PerformRedirection(Cmd->Redirections))
-               return FALSE;
+               return 1;
 
        switch (Cmd->Type)
        {
        case C_COMMAND:
-               Success = FALSE;
+               Ret = 1;
                First = DoDelayedExpansion(Cmd->Command.First);
                if (First)
                {
                        Rest = DoDelayedExpansion(Cmd->Command.Rest);
                        if (Rest)
                        {
-                               Success = DoCommand(First, Rest, Cmd);
+                               Ret = DoCommand(First, Rest, Cmd);
                                cmd_free(Rest);
                        }
                        cmd_free(First);
@@ -709,31 +707,36 @@ ExecuteCommand(PARSED_COMMAND *Cmd)
        case C_BLOCK:
        case C_MULTI:
                for (Sub = Cmd->Subcommands; Sub; Sub = Sub->Next)
-                       Success = ExecuteCommand(Sub);
+                       Ret = ExecuteCommand(Sub);
                break;
        case C_IFFAILURE:
-       case C_IFSUCCESS:
                Sub = Cmd->Subcommands;
-               Success = ExecuteCommand(Sub);
-               if (Success == (Cmd->Type - C_IFFAILURE))
+               Ret = ExecuteCommand(Sub);
+               if (Ret != 0)
                {
-                       Sub = Sub->Next;
-                       Success = ExecuteCommand(Sub);
+                       nErrorLevel = Ret;
+                       Ret = ExecuteCommand(Sub->Next);
                }
                break;
+       case C_IFSUCCESS:
+               Sub = Cmd->Subcommands;
+               Ret = ExecuteCommand(Sub);
+               if (Ret == 0)
+                       Ret = ExecuteCommand(Sub->Next);
+               break;
        case C_PIPE:
                ExecutePipeline(Cmd);
                break;
        case C_IF:
-               Success = ExecuteIf(Cmd);
+               Ret = ExecuteIf(Cmd);
                break;
        case C_FOR:
-               Success = ExecuteFor(Cmd);
+               Ret = ExecuteFor(Cmd);
                break;
        }
 
        UndoRedirection(Cmd->Redirections, NULL);
-       return Success;
+       return Ret;
 }
 
 BOOL
@@ -1402,7 +1405,7 @@ ReadLine (TCHAR *commandline, BOOL bMore)
        return SubstituteVars(ip, commandline, _T('%'));
 }
 
-static INT
+static VOID
 ProcessInput()
 {
        PARSED_COMMAND *Cmd;
@@ -1416,8 +1419,6 @@ ProcessInput()
                ExecuteCommand(Cmd);
                FreeCommand(Cmd);
        }
-
-       return nErrorLevel;
 }
 
 
@@ -1614,6 +1615,7 @@ Initialize()
        TCHAR commandline[CMDLINE_LENGTH];
        TCHAR ModuleName[_MAX_PATH + 1];
        TCHAR lpBuffer[2];
+       INT nExitCode;
 
        //INT len;
        TCHAR *ptr, *cmdLine, option = 0;
@@ -1760,9 +1762,12 @@ Initialize()
        {
                /* Do the /C or /K command */
                GetCmdLineCommand(commandline, &ptr[2], AlwaysStrip);
-               ParseCommandLine(commandline);
+               nExitCode = ParseCommandLine(commandline);
                if (option != _T('K'))
+               {
+                       nErrorLevel = nExitCode;
                        bExit = TRUE;
+               }
        }
 }
 
@@ -1806,7 +1811,6 @@ int cmd_main (int argc, const TCHAR *argv[])
        HANDLE hConsole;
        TCHAR startPath[MAX_PATH];
        CONSOLE_SCREEN_BUFFER_INFO Info;
-       INT nExitCode;
 
        lpOriginalEnvironment = DuplicateEnvironment();
 
@@ -1839,15 +1843,15 @@ int cmd_main (int argc, const TCHAR *argv[])
        Initialize();
 
        /* call prompt routine */
-       nExitCode = ProcessInput();
+       ProcessInput();
 
        /* do the cleanup */
        Cleanup();
 
        cmd_free(lpOriginalEnvironment);
 
-       cmd_exit(nExitCode);
-       return(nExitCode);
+       cmd_exit(nErrorLevel);
+       return(nErrorLevel);
 }
 
 /* EOF */