Rework batch-file processing so that 'call file.bat' doesn't return until the file...
authorJeffrey Morlan <mrnobo1024@yahoo.com>
Tue, 3 Mar 2009 20:06:54 +0000 (20:06 +0000)
committerJeffrey Morlan <mrnobo1024@yahoo.com>
Tue, 3 Mar 2009 20:06:54 +0000 (20:06 +0000)
svn path=/trunk/; revision=39858

reactos/base/shell/cmd/batch.c
reactos/base/shell/cmd/batch.h
reactos/base/shell/cmd/call.c
reactos/base/shell/cmd/cmd.c
reactos/base/shell/cmd/cmd.h
reactos/base/shell/cmd/internal.c

index ffcd1a9..30cdbae 100644 (file)
@@ -171,8 +171,6 @@ VOID ExitBatch (LPTSTR msg)
 
        if (bc != NULL)
        {
-               LPBATCH_CONTEXT t = bc;
-
                if (bc->hBatchFile)
                {
                        CloseHandle (bc->hBatchFile);
@@ -192,7 +190,6 @@ VOID ExitBatch (LPTSTR msg)
                bEcho = bc->bEcho;
 
                bc = bc->prev;
-               cmd_free(t);
        }
 
        if (msg && *msg)
@@ -207,8 +204,10 @@ VOID ExitBatch (LPTSTR msg)
  *
  */
 
-BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, BOOL forcenew)
+BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, PARSED_COMMAND *Cmd)
 {
+       BATCH_CONTEXT new;
+
        HANDLE hFile;
        SetLastError(0);
        hFile = CreateFile (fullname, GENERIC_READ, FILE_SHARE_WRITE | FILE_SHARE_READ | FILE_SHARE_DELETE, NULL,
@@ -227,22 +226,7 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, BOOL forcenew)
        /* Kill any and all FOR contexts */
        fc = NULL;
 
-       if (bc == NULL || forcenew)
-       {
-               /* No curent batch file, create a new context */
-               LPBATCH_CONTEXT n = (LPBATCH_CONTEXT)cmd_alloc (sizeof(BATCH_CONTEXT));
-
-               if (n == NULL)
-               {
-                       error_out_of_memory ();
-                       return FALSE;
-               }
-
-               n->prev = bc;
-               bc = n;
-               bc->RedirList = NULL;
-       }
-       else if (bc->hBatchFile != INVALID_HANDLE_VALUE)
+       if (bc != NULL && Cmd == bc->current)
        {
                /* Then we are transferring to another batch */
                CloseHandle (bc->hBatchFile);
@@ -251,6 +235,20 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, BOOL forcenew)
                        cmd_free (bc->params);
                if (bc->raw_params)
                        cmd_free (bc->raw_params);
+               AddBatchRedirection(&Cmd->Redirections);
+       }
+       else
+       {
+               /* If a batch file runs another batch file as part of a compound command
+                * (e.g. "x.bat & somethingelse") then the first file gets terminated. */
+               if (Cmd != NULL)
+                       ExitBatch(NULL);
+
+               /* Create a new context. This function will not
+                * return until this context has been exited */
+               new.prev = bc;
+               bc = &new;
+               bc->RedirList = NULL;
        }
 
        GetFullPathName(fullname, sizeof(bc->BatchFilePath) / sizeof(TCHAR), bc->BatchFilePath, NULL);
@@ -264,17 +262,42 @@ BOOL Batch (LPTSTR fullname, LPTSTR firstword, LPTSTR param, BOOL forcenew)
     //
     // Allocate enough memory to hold the params and copy them over without modifications
     //
-    bc->raw_params = (TCHAR*) cmd_alloc((_tcslen(param)+1) * sizeof(TCHAR));
-    if (bc->raw_params != NULL)
-    {
-        _tcscpy(bc->raw_params,param);
-    }
-    else
+    bc->raw_params = cmd_dup(param);
+    if (bc->raw_params == NULL)
     {
         error_out_of_memory();
         return FALSE;
     }
 
+       /* Check if this is a "CALL :label" */
+       if (*firstword == _T(':'))
+               cmd_goto(firstword);
+
+       /* If we have created a new context, don't return
+        * until this batch file has completed. */
+       while (bc == &new && !bExit)
+       {
+               Cmd = ParseCommand(NULL);
+               if (!Cmd)
+                       continue;
+
+               /* JPP 19980807 */
+               /* Echo batch file line */
+               if (bEcho && Cmd->Type != C_QUIET)
+               {
+                       PrintPrompt();
+                       EchoCommand(Cmd);
+                       ConOutChar(_T('\n'));
+               }
+
+               bc->current = Cmd;
+               ExecuteCommand(Cmd);
+               if (bEcho && !bIgnoreEcho && Cmd->Type != C_QUIET)
+                       ConOutChar(_T('\n'));
+               FreeCommand(Cmd);
+               bIgnoreEcho = FALSE;
+       }
+
     /* Don't print a newline for this command */
     bIgnoreEcho = TRUE;
 
@@ -313,50 +336,34 @@ VOID AddBatchRedirection(REDIRECTION **RedirList)
 
 LPTSTR ReadBatchLine ()
 {
-       LPTSTR first;
-
        /* No batch */
        if (bc == NULL)
                return NULL;
 
        TRACE ("ReadBatchLine ()\n");
 
-       while (1)
+       /* User halt */
+       if (CheckCtrlBreak (BREAK_BATCHFILE))
        {
-               /* User halt */
-               if (CheckCtrlBreak (BREAK_BATCHFILE))
-               {
-                       while (bc)
-                               ExitBatch (NULL);
-                       return NULL;
-               }
-
-               /* No batch */
-               if (bc == NULL)
-                       return NULL;
-
-               if (!FileGetString (bc->hBatchFile, textline, sizeof (textline) / sizeof (textline[0]) - 1))
-               {
-                       TRACE ("ReadBatchLine(): Reached EOF!\n");
-                       /* End of file.... */
+               while (bc)
                        ExitBatch (NULL);
+               return NULL;
+       }
 
-                       if (bc == NULL)
-                               return NULL;
-
-                       continue;
-               }
-               TRACE ("ReadBatchLine(): textline: \'%s\'\n", debugstr_aw(textline));
-
-               if (textline[_tcslen(textline) - 1] != _T('\n'))
-                       _tcscat(textline, _T("\n"));
+       if (!FileGetString (bc->hBatchFile, textline, sizeof (textline) / sizeof (textline[0]) - 1))
+       {
+               TRACE ("ReadBatchLine(): Reached EOF!\n");
+               /* End of file.... */
+               ExitBatch (NULL);
+               return NULL;
+       }
 
-               first = textline;
+       TRACE ("ReadBatchLine(): textline: \'%s\'\n", debugstr_aw(textline));
 
-               break;
-       }
+       if (textline[_tcslen(textline) - 1] != _T('\n'))
+               _tcscat(textline, _T("\n"));
 
-       return first;
+       return textline;
 }
 
 /* EOF */
index 28022b1..7f4d503 100644 (file)
@@ -17,6 +17,7 @@ typedef struct tagBATCHCONTEXT
        INT    shiftlevel;
        BOOL   bEcho;        /* Preserve echo flag across batch calls */
        REDIRECTION *RedirList;
+       PARSED_COMMAND *current; 
 } BATCH_CONTEXT, *LPBATCH_CONTEXT;
 
 typedef struct tagFORCONTEXT
@@ -45,7 +46,7 @@ extern TCHAR textline[BATCH_BUFFSIZE]; /* Buffer for reading Batch file lines */
 LPTSTR FindArg (INT);
 LPTSTR BatchParams (LPTSTR, LPTSTR);
 VOID   ExitBatch (LPTSTR);
-BOOL   Batch (LPTSTR, LPTSTR, LPTSTR, BOOL);
+BOOL   Batch (LPTSTR, LPTSTR, LPTSTR, PARSED_COMMAND *);
 LPTSTR ReadBatchLine();
 VOID AddBatchRedirection(REDIRECTION **);
 
index 3418ccd..4577ee3 100644 (file)
@@ -42,8 +42,6 @@
 
 INT cmd_call (LPTSTR param)
 {
-       LPBATCH_CONTEXT n = NULL;
-
        TRACE ("cmd_call: (\'%s\')\n", debugstr_aw(param));
        if (!_tcsncmp (param, _T("/?"), 2))
        {
@@ -62,39 +60,10 @@ INT cmd_call (LPTSTR param)
                        while (_istspace(*param))
                                param++;
                }
-               if (!Batch(bc->BatchFilePath, first, param, TRUE))
-                       return 1;
-               return cmd_goto(first);
-       }
-
-    nErrorLevel = 0;
-
-       n = (LPBATCH_CONTEXT)cmd_alloc (sizeof (BATCH_CONTEXT));
-
-       if (n == NULL)
-       {
-               error_out_of_memory ();
-               return 1;
-       }
-
-       n->prev = bc;
-       bc = n;
-
-       bc->hBatchFile = INVALID_HANDLE_VALUE;
-       bc->params = NULL;
-       bc->shiftlevel = 0;
-       bc->RedirList = NULL;
-       ParseCommandLine (param);
-
-
-       /* Wasn't a batch file so remove conext */
-       if (bc->hBatchFile == INVALID_HANDLE_VALUE)
-       {
-               bc = bc->prev;
-               cmd_free (n);
+               return !Batch(bc->BatchFilePath, first, param, NULL);
        }
 
-       return 0;
+       return !DoCommand(param, NULL);
 }
 
 /* EOF */
index 280deb5..3c7f4a7 100644 (file)
@@ -324,7 +324,7 @@ static BOOL RunFile(LPTSTR filename)
  */
 
 static BOOL
-Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
+Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest, PARSED_COMMAND *Cmd)
 {
        TCHAR *szFullName=NULL;
        TCHAR *first = NULL;
@@ -470,7 +470,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
        if (dot && (!_tcsicmp (dot, _T(".bat")) || !_tcsicmp (dot, _T(".cmd"))))
        {
                TRACE ("[BATCH: %s %s]\n", debugstr_aw(szFullName), debugstr_aw(rest));
-               Batch (szFullName, first, rest, FALSE);
+               Batch (szFullName, first, rest, Cmd);
        }
        else
        {
@@ -568,7 +568,7 @@ Execute (LPTSTR Full, LPTSTR First, LPTSTR Rest)
  */
 
 BOOL
-DoCommand (LPTSTR line)
+DoCommand (LPTSTR line, PARSED_COMMAND *Cmd)
 {
        TCHAR *com = NULL;  /* the first word in the command */
        TCHAR *cp = NULL;
@@ -642,7 +642,7 @@ DoCommand (LPTSTR line)
                        /* If end of table execute ext cmd */
                        if (cmdptr->name == NULL)
                        {
-                               ret = Execute (line, com, rest);
+                               ret = Execute (line, com, rest, Cmd);
                                break;
                        }
 
@@ -866,7 +866,6 @@ ExecutePipeline(PARSED_COMMAND *Cmd)
 BOOL
 ExecuteCommand(PARSED_COMMAND *Cmd)
 {
-       BOOL bNewBatch = TRUE;
        PARSED_COMMAND *Sub;
        LPTSTR ExpandedLine;
        BOOL Success = TRUE;
@@ -877,20 +876,14 @@ ExecuteCommand(PARSED_COMMAND *Cmd)
        switch (Cmd->Type)
        {
        case C_COMMAND:
-               if(bc)
-                       bNewBatch = FALSE;
-
                ExpandedLine = DoDelayedExpansion(Cmd->Command.CommandLine);
                if (!ExpandedLine)
                {
                        Success = FALSE;
                        break;
                }
-               Success = DoCommand(ExpandedLine);
+               Success = DoCommand(ExpandedLine, Cmd);
                cmd_free(ExpandedLine);
-
-               if(bNewBatch && bc)
-                       AddBatchRedirection(&Cmd->Redirections);
                break;
        case C_QUIET:
        case C_BLOCK:
@@ -1330,7 +1323,7 @@ ReadLine (TCHAR *commandline, BOOL bMore)
        LPTSTR ip;
 
        /* if no batch input then... */
-       if (!(ip = ReadBatchLine()))
+       if (bc == NULL)
        {
                if (bNoInteractive)
                {
@@ -1360,6 +1353,9 @@ ReadLine (TCHAR *commandline, BOOL bMore)
        }
        else
        {
+               ip = ReadBatchLine();
+               if (!ip)
+                       return FALSE;
                bIsBatch = TRUE;
        }
 
@@ -1378,17 +1374,8 @@ ProcessInput (BOOL bFlag)
                if (!Cmd)
                        continue;
 
-               /* JPP 19980807 */
-               /* Echo batch file line */
-               if (bIsBatch && bEcho && Cmd->Type != C_QUIET)
-               {
-                       PrintPrompt ();
-                       EchoCommand(Cmd);
-                       ConOutChar(_T('\n'));
-               }
-
                ExecuteCommand(Cmd);
-               if (bEcho && !bIgnoreEcho && (!bIsBatch || Cmd->Type != C_QUIET))
+               if (bEcho && !bIgnoreEcho)
                        ConOutChar ('\n');
                FreeCommand(Cmd);
                bIgnoreEcho = FALSE;
index 5944eb1..b35bf75 100644 (file)
@@ -104,7 +104,7 @@ VOID AddBreakHandler (VOID);
 VOID RemoveBreakHandler (VOID);
 BOOL SubstituteForVars(TCHAR *Src, TCHAR *Dest);
 LPTSTR DoDelayedExpansion(LPTSTR Line);
-BOOL DoCommand (LPTSTR line);
+BOOL DoCommand (LPTSTR line, struct _PARSED_COMMAND *Cmd);
 BOOL ReadLine(TCHAR *commandline, BOOL bMore);
 int cmd_main (int argc, const TCHAR *argv[]);
 
index 2bb5924..75836db 100644 (file)
@@ -707,7 +707,7 @@ INT CommandShowCommandsDetail (LPTSTR param)
                LPTSTR NewCommand = cmd_alloc((_tcslen(param)+4)*sizeof(TCHAR));
                _tcscpy(NewCommand, param);
                _tcscat(NewCommand, _T(" /?"));
-               DoCommand(NewCommand);
+               DoCommand(NewCommand, NULL);
                cmd_free(NewCommand);
        }
        /* Else, display detailed commands list */