]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/Shell.c
SecurityPkg: Apply uncrustify changes
[mirror_edk2.git] / ShellPkg / Application / Shell / Shell.c
index fcf47b5c733d615f79c1756ebc2b5bd41901abe8..a5563070972ed1aaba020f99ef5f26751b9ae53e 100644 (file)
@@ -1,15 +1,10 @@
 /** @file\r
   This is THE shell (application)\r
 \r
-  Copyright (c) 2009 - 2017, Intel Corporation. All rights reserved.<BR>\r
+  Copyright (c) 2009 - 2019, Intel Corporation. All rights reserved.<BR>\r
   (C) Copyright 2013-2014 Hewlett-Packard Development Company, L.P.<BR>\r
-  This program and the accompanying materials\r
-  are licensed and made available under the terms and conditions of the BSD License\r
-  which accompanies this distribution.  The full text of the license may be found at\r
-  http://opensource.org/licenses/bsd-license.php\r
-\r
-  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+  Copyright 2015-2018 Dell Technologies.<BR>\r
+  SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -104,7 +99,7 @@ TrimSpaces(
 }\r
 \r
 /**\r
-  Parse for the next instance of one string within another string. Can optionally make sure that \r
+  Parse for the next instance of one string within another string. Can optionally make sure that\r
   the string was not escaped (^ character) per the shell specification.\r
 \r
   @param[in] SourceString             The string to search within\r
@@ -160,13 +155,13 @@ IsValidEnvironmentVariableName(
   )\r
 {\r
   CONST CHAR16    *Walker;\r
-  \r
+\r
   Walker = NULL;\r
 \r
   ASSERT (BeginPercent != NULL);\r
   ASSERT (EndPercent != NULL);\r
   ASSERT (BeginPercent < EndPercent);\r
-  \r
+\r
   if ((BeginPercent + 1) == EndPercent) {\r
     return FALSE;\r
   }\r
@@ -212,9 +207,9 @@ ContainsSplit(
   SecondQuote   = NULL;\r
   TempSpot      = FindFirstCharacter(CmdLine, L"|", L'^');\r
 \r
-  if (FirstQuote == NULL    || \r
-      TempSpot == NULL      || \r
-      TempSpot == CHAR_NULL || \r
+  if (FirstQuote == NULL    ||\r
+      TempSpot == NULL      ||\r
+      TempSpot == CHAR_NULL ||\r
       FirstQuote > TempSpot\r
       ) {\r
     return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
@@ -223,7 +218,7 @@ ContainsSplit(
   while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) {\r
     if (FirstQuote == NULL || FirstQuote > TempSpot) {\r
       break;\r
-    }    \r
+    }\r
     SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE);\r
     if (SecondQuote == NULL) {\r
       break;\r
@@ -235,14 +230,14 @@ ContainsSplit(
       FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);\r
       TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^');\r
       continue;\r
-    } \r
+    }\r
   }\r
-  \r
+\r
   return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL));\r
 }\r
 \r
 /**\r
-  Function to start monitoring for CTRL-S using SimpleTextInputEx.  This \r
+  Function to start monitoring for CTRL-S using SimpleTextInputEx.  This\r
   feature's enabled state was not known when the shell initially launched.\r
 \r
   @retval EFI_SUCCESS           The feature is enabled.\r
@@ -266,8 +261,8 @@ InternalEfiShellStartCtrlSMonitor(
     EFI_OPEN_PROTOCOL_GET_PROTOCOL);\r
   if (EFI_ERROR(Status)) {\r
     ShellPrintHiiEx(\r
-      -1, \r
-      -1, \r
+      -1,\r
+      -1,\r
       NULL,\r
       STRING_TOKEN (STR_SHELL_NO_IN_EX),\r
       ShellInfoObject.HiiHandle);\r
@@ -284,7 +279,7 @@ InternalEfiShellStartCtrlSMonitor(
     &KeyData,\r
     NotificationFunction,\r
     &ShellInfoObject.CtrlSNotifyHandle1);\r
-  \r
+\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
   if (!EFI_ERROR(Status)) {\r
     Status = SimpleEx->RegisterKeyNotify(\r
@@ -302,7 +297,7 @@ InternalEfiShellStartCtrlSMonitor(
       &KeyData,\r
       NotificationFunction,\r
       &ShellInfoObject.CtrlSNotifyHandle3);\r
-  }  \r
+  }\r
   KeyData.KeyState.KeyShiftState  = EFI_SHIFT_STATE_VALID|EFI_RIGHT_CONTROL_PRESSED;\r
   if (!EFI_ERROR(Status)) {\r
     Status = SimpleEx->RegisterKeyNotify(\r
@@ -620,11 +615,6 @@ UefiMain (
           ShellInfoObject.ConsoleInfo->Enabled    = TRUE;\r
           ShellInfoObject.ConsoleInfo->RowCounter = 0;\r
 \r
-          //\r
-          // Reset the CTRL-C event (yes we ignore the return values)\r
-          //\r
-          Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);\r
-\r
           //\r
           // Display Prompt\r
           //\r
@@ -726,6 +716,7 @@ FreeResources:
 **/\r
 EFI_STATUS\r
 SetBuiltInAlias(\r
+  VOID\r
   )\r
 {\r
   EFI_STATUS          Status;\r
@@ -1005,7 +996,11 @@ ProcessCommandLine(
                                  ) == 0) {\r
       ShellInfoObject.ShellInitSettings.BitUnion.Bits.Delay        = TRUE;\r
       // Check for optional delay value following "-delay"\r
-      DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1];\r
+      if ((LoopVar + 1) >= gEfiShellParametersProtocol->Argc) {\r
+        DelayValueStr = NULL;\r
+      } else {\r
+        DelayValueStr = gEfiShellParametersProtocol->Argv[LoopVar + 1];\r
+      }\r
       if (DelayValueStr != NULL){\r
         if (*DelayValueStr == L':') {\r
           DelayValueStr++;\r
@@ -1086,7 +1081,7 @@ ProcessCommandLine(
           }\r
         }\r
         //\r
-        // If an argumnent contains a space, then add double quotes before the argument\r
+        // If an argument contains a space, then add double quotes before the argument\r
         //\r
         if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {\r
           StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
@@ -1107,7 +1102,7 @@ ProcessCommandLine(
           return (EFI_OUT_OF_RESOURCES);\r
         }\r
         //\r
-        // If an argumnent contains a space, then add double quotes after the argument\r
+        // If an argument contains a space, then add double quotes after the argument\r
         //\r
         if (StrStr (gEfiShellParametersProtocol->Argv[LoopVar], L" ") != NULL) {\r
           StrnCatGrow(&ShellInfoObject.ShellInitSettings.FileOptions,\r
@@ -1133,7 +1128,7 @@ ProcessCommandLine(
 \r
 /**\r
   Function try to find location of the Startup.nsh file.\r
-  \r
+\r
   The buffer is callee allocated and should be freed by the caller.\r
 \r
   @param    ImageDevicePath       The path to the image for shell.  first place to look for the startup script\r
@@ -1160,7 +1155,7 @@ LocateStartupScript (
   // Try to find 'Startup.nsh' in the directory where the shell itself was launched.\r
   //\r
   MapName = ShellInfoObject.NewEfiShellProtocol->GetMapFromDevicePath (&ImageDevicePath);\r
-  if (MapName != NULL) {   \r
+  if (MapName != NULL) {\r
     StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, MapName, 0);\r
     if (StartupScriptPath == NULL) {\r
       //\r
@@ -1173,13 +1168,15 @@ LocateStartupScript (
       *TempSpot = CHAR_NULL;\r
     }\r
 \r
+    InternalEfiShellSetEnv(L"homefilesystem", StartupScriptPath, TRUE);\r
+\r
     StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, ((FILEPATH_DEVICE_PATH *)FileDevicePath)->PathName, 0);\r
     PathRemoveLastItem (StartupScriptPath);\r
     StartupScriptPath = StrnCatGrow (&StartupScriptPath, &Size, mStartupScript, 0);\r
   }\r
 \r
   //\r
-  // Try to find 'Startup.nsh' in the execution path defined by the envrionment variable PATH.\r
+  // Try to find 'Startup.nsh' in the execution path defined by the environment variable PATH.\r
   //\r
   if ((StartupScriptPath == NULL) || EFI_ERROR (ShellIsFile (StartupScriptPath))) {\r
     SHELL_FREE_NON_NULL (StartupScriptPath);\r
@@ -1210,6 +1207,7 @@ DoStartupScript(
   UINTN                         Delay;\r
   EFI_INPUT_KEY                 Key;\r
   CHAR16                        *FileStringPath;\r
+  CHAR16                        *FullFileStringPath;\r
   UINTN                         NewSize;\r
 \r
   Key.UnicodeChar = CHAR_NULL;\r
@@ -1277,7 +1275,13 @@ DoStartupScript(
 \r
   FileStringPath = LocateStartupScript (ImagePath, FilePath);\r
   if (FileStringPath != NULL) {\r
-    Status = RunScriptFile (FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol);\r
+    FullFileStringPath = FullyQualifyPath(FileStringPath);\r
+    if (FullFileStringPath == NULL) {\r
+      Status = RunScriptFile (FileStringPath, NULL, FileStringPath, ShellInfoObject.NewShellParametersProtocol);\r
+    } else {\r
+      Status = RunScriptFile (FullFileStringPath, NULL, FullFileStringPath, ShellInfoObject.NewShellParametersProtocol);\r
+      FreePool(FullFileStringPath);\r
+    }\r
     FreePool (FileStringPath);\r
   } else {\r
     //\r
@@ -1345,9 +1349,14 @@ DoShellPrompt (
   // Null terminate the string and parse it\r
   //\r
   if (!EFI_ERROR (Status)) {\r
+    //\r
+    // Reset the CTRL-C event just before running the command (yes we ignore the return values)\r
+    //\r
+    Status = gBS->CheckEvent (ShellInfoObject.NewEfiShellProtocol->ExecutionBreak);\r
+\r
     CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL;\r
     Status = RunCommand(CmdLine);\r
-    }\r
+  }\r
 \r
   //\r
   // Done with this command\r
@@ -1386,7 +1395,7 @@ AddBufferToFreeList (
 \r
 \r
 /**\r
-  Create a new buffer list and stores the old one to OldBufferList \r
+  Create a new buffer list and stores the old one to OldBufferList\r
 \r
   @param OldBufferList   The temporary list head used to store the nodes in BufferToFreeList.\r
 **/\r
@@ -1431,7 +1440,7 @@ AddLineToCommandHistory(
 \r
   Count = 0;\r
   MaxHistoryCmdCount = PcdGet16(PcdShellMaxHistoryCommandCount);\r
-  \r
+\r
   if (MaxHistoryCmdCount == 0) {\r
     return ;\r
   }\r
@@ -1545,7 +1554,7 @@ StripUnreplacedEnvironmentVariables(
       }\r
       continue;\r
     }\r
-    \r
+\r
     if (FirstQuote == NULL || SecondPercent < FirstQuote) {\r
       if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) {\r
         //\r
@@ -1646,7 +1655,7 @@ ShellConvertVariables (
   //\r
   // now do the replacements...\r
   //\r
-  NewCommandLine1 = AllocateCopyPool(NewSize, OriginalCommandLine);\r
+  NewCommandLine1 = AllocateZeroPool (NewSize);\r
   NewCommandLine2 = AllocateZeroPool(NewSize);\r
   ItemTemp        = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16)));\r
   if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) {\r
@@ -1655,20 +1664,22 @@ ShellConvertVariables (
     SHELL_FREE_NON_NULL(ItemTemp);\r
     return (NULL);\r
   }\r
+  CopyMem (NewCommandLine1, OriginalCommandLine, StrSize (OriginalCommandLine));\r
+\r
   for (MasterEnvList = EfiShellGetEnv(NULL)\r
     ;  MasterEnvList != NULL && *MasterEnvList != CHAR_NULL\r
     ;  MasterEnvList += StrLen(MasterEnvList) + 1\r
    ){\r
-    StrCpyS( ItemTemp, \r
-              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+    StrCpyS( ItemTemp,\r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),\r
               L"%"\r
               );\r
-    StrCatS( ItemTemp, \r
-              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+    StrCatS( ItemTemp,\r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),\r
               MasterEnvList\r
               );\r
-    StrCatS( ItemTemp, \r
-              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+    StrCatS( ItemTemp,\r
+              ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)),\r
               L"%"\r
               );\r
     ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);\r
@@ -1694,7 +1705,7 @@ ShellConvertVariables (
   //\r
   ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);\r
   StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
-  \r
+\r
   FreePool(NewCommandLine2);\r
   FreePool(ItemTemp);\r
 \r
@@ -1820,7 +1831,7 @@ RunSplitCommand(
 }\r
 \r
 /**\r
-  Take the original command line, substitute any variables, free \r
+  Take the original command line, substitute any variables, free\r
   the original string, return the modified copy.\r
 \r
   @param[in] CmdLine  pointer to the command line to update.\r
@@ -1844,7 +1855,7 @@ ShellSubstituteVariables(
 }\r
 \r
 /**\r
-  Take the original command line, substitute any alias in the first group of space delimited characters, free \r
+  Take the original command line, substitute any alias in the first group of space delimited characters, free\r
   the original string, return the modified copy.\r
 \r
   @param[in] CmdLine  pointer to the command line to update.\r
@@ -1903,7 +1914,7 @@ ShellSubstituteAliases(
 \r
   SHELL_FREE_NON_NULL(*CmdLine);\r
   SHELL_FREE_NON_NULL(CommandName);\r
\r
+\r
   //\r
   // re-assign the passed in double pointer to point to our newly allocated buffer\r
   //\r
@@ -1916,7 +1927,7 @@ ShellSubstituteAliases(
   Takes the Argv[0] part of the command line and determine the meaning of it.\r
 \r
   @param[in] CmdName  pointer to the command line to update.\r
-  \r
+\r
   @retval Internal_Command    The name is an internal command.\r
   @retval File_Sys_Change     the name is a file system change.\r
   @retval Script_File_Name    the name is a NSH script file.\r
@@ -1944,7 +1955,7 @@ GetOperationType(
   // Test for file system change request.  anything ending with first : and cant have spaces.\r
   //\r
   if (CmdName[(StrLen(CmdName)-1)] == L':') {\r
-    if ( StrStr(CmdName, L" ") != NULL \r
+    if ( StrStr(CmdName, L" ") != NULL\r
       || StrLen(StrStr(CmdName, L":")) > 1\r
       ) {\r
       return (Unknown_Invalid);\r
@@ -1974,7 +1985,7 @@ GetOperationType(
     SHELL_FREE_NON_NULL(FileWithPath);\r
     return (Efi_Application);\r
   }\r
-  \r
+\r
   SHELL_FREE_NON_NULL(FileWithPath);\r
   //\r
   // No clue what this is... return invalid flag...\r
@@ -1991,7 +2002,7 @@ GetOperationType(
   @retval EFI_OUT_OF_RESOURCES  A memory allocation failed.\r
   @retval EFI_NOT_FOUND         The operation type is unknown or invalid.\r
 **/\r
-EFI_STATUS \r
+EFI_STATUS\r
 IsValidSplit(\r
   IN CONST CHAR16 *CmdLine\r
   )\r
@@ -2076,13 +2087,13 @@ VerifySplit(
   // recurse to verify the next item\r
   //\r
   TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;\r
-  if (*TempSpot == L'a' && \r
+  if (*TempSpot == L'a' &&\r
       (*(TempSpot + 1) == L' ' || *(TempSpot + 1) == CHAR_NULL)\r
      ) {\r
     // If it's an ASCII pipe '|a'\r
     TempSpot += 1;\r
   }\r
-  \r
+\r
   return (VerifySplit(TempSpot));\r
 }\r
 \r
@@ -2146,7 +2157,7 @@ ChangeMappedDrive(
   // make sure we are the right operation\r
   //\r
   ASSERT(CmdLine[(StrLen(CmdLine)-1)] == L':' && StrStr(CmdLine, L" ") == NULL);\r
-  \r
+\r
   //\r
   // Call the protocol API to do the work\r
   //\r
@@ -2240,7 +2251,7 @@ SetLastError(
 }\r
 \r
 /**\r
-  Converts the command line to it's post-processed form.  this replaces variables and alias' per UEFI Shell spec.\r
+  Converts the command line to its post-processed form.  this replaces variables and alias' per UEFI Shell spec.\r
 \r
   @param[in,out] CmdLine        pointer to the command line to update\r
 \r
@@ -2291,7 +2302,7 @@ ProcessCommandLineToFinal(
   Run an internal shell command.\r
 \r
   This API will update the shell's environment since these commands are libraries.\r
-  \r
+\r
   @param[in] CmdLine          the command line to run.\r
   @param[in] FirstParameter   the first parameter on the command line\r
   @param[in] ParamProtocol    the shell parameters protocol pointer\r
@@ -2314,7 +2325,7 @@ RunInternalCommand(
   SHELL_STATUS              CommandReturnedStatus;\r
   BOOLEAN                   LastError;\r
   CHAR16                    *Walker;\r
-  CHAR16                    *NewCmdLine;  \r
+  CHAR16                    *NewCmdLine;\r
 \r
   NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine);\r
   if (NewCmdLine == NULL) {\r
@@ -2424,6 +2435,7 @@ RunCommandOrFile(
   EFI_STATUS                Status;\r
   EFI_STATUS                StartStatus;\r
   CHAR16                    *CommandWithPath;\r
+  CHAR16                    *FullCommandWithPath;\r
   EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   SHELL_STATUS              CalleeExitStatus;\r
 \r
@@ -2469,7 +2481,13 @@ RunCommandOrFile(
       }\r
       switch (Type) {\r
         case   Script_File_Name:\r
-          Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);\r
+          FullCommandWithPath = FullyQualifyPath(CommandWithPath);\r
+          if (FullCommandWithPath == NULL) {\r
+            Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol);\r
+          } else {\r
+            Status = RunScriptFile (FullCommandWithPath, NULL, CmdLine, ParamProtocol);\r
+            FreePool(FullCommandWithPath);\r
+          }\r
           break;\r
         case   Efi_Application:\r
           //\r
@@ -2594,7 +2612,7 @@ SetupAndRunCommandOrFile(
 /**\r
   Function will process and run a command line.\r
 \r
-  This will determine if the command line represents an internal shell \r
+  This will determine if the command line represents an internal shell\r
   command or dispatch an external application.\r
 \r
   @param[in] CmdLine      The command line to parse.\r
@@ -2614,6 +2632,7 @@ RunShellCommand(
   CHAR16                    *FirstParameter;\r
   CHAR16                    *TempWalker;\r
   SHELL_OPERATION_TYPES     Type;\r
+  CONST CHAR16              *CurDir;\r
 \r
   ASSERT(CmdLine != NULL);\r
   if (StrLen(CmdLine) == 0) {\r
@@ -2669,7 +2688,7 @@ RunShellCommand(
     Status = ProcessNewSplitCommandLine(CleanOriginal);\r
     SHELL_FREE_NON_NULL(CleanOriginal);\r
     return (Status);\r
-  } \r
+  }\r
 \r
   //\r
   // We need the first parameter information so we can determine the operation type\r
@@ -2705,7 +2724,22 @@ RunShellCommand(
     ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
     SetLastError(SHELL_NOT_FOUND);\r
   }\r
\r
+  //\r
+  // Check whether the current file system still exists. If not exist, we need update "cwd" and gShellCurMapping.\r
+  //\r
+  CurDir = EfiShellGetCurDir (NULL);\r
+  if (CurDir != NULL) {\r
+    if (EFI_ERROR(ShellFileExists (CurDir))) {\r
+      //\r
+      // EfiShellSetCurDir() cannot set current directory to NULL.\r
+      // EfiShellSetEnv() is not allowed to set the "cwd" variable.\r
+      // Only InternalEfiShellSetEnv () is allowed setting the "cwd" variable.\r
+      //\r
+      InternalEfiShellSetEnv (L"cwd", NULL, TRUE);\r
+      gShellCurMapping = NULL;\r
+    }\r
+  }\r
+\r
   SHELL_FREE_NON_NULL(CleanOriginal);\r
   SHELL_FREE_NON_NULL(FirstParameter);\r
 \r
@@ -2715,7 +2749,7 @@ RunShellCommand(
 /**\r
   Function will process and run a command line.\r
 \r
-  This will determine if the command line represents an internal shell \r
+  This will determine if the command line represents an internal shell\r
   command or dispatch an external application.\r
 \r
   @param[in] CmdLine      The command line to parse.\r
@@ -2731,38 +2765,6 @@ RunCommand(
   return (RunShellCommand(CmdLine, NULL));\r
 }\r
 \r
-\r
-STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};\r
-/**\r
-  Function determines if the CommandName COULD be a valid command.  It does not determine whether\r
-  this is a valid command.  It only checks for invalid characters.\r
-\r
-  @param[in] CommandName    The name to check\r
-\r
-  @retval TRUE              CommandName could be a command name\r
-  @retval FALSE             CommandName could not be a valid command name\r
-**/\r
-BOOLEAN\r
-IsValidCommandName(\r
-  IN CONST CHAR16     *CommandName\r
-  )\r
-{\r
-  UINTN Count;\r
-  if (CommandName == NULL) {\r
-    ASSERT(FALSE);\r
-    return (FALSE);\r
-  }\r
-  for ( Count = 0\r
-      ; Count < sizeof(InvalidChars) / sizeof(InvalidChars[0])\r
-      ; Count++\r
-     ){\r
-    if (ScanMem16(CommandName, StrSize(CommandName), InvalidChars[Count]) != NULL) {\r
-      return (FALSE);\r
-    }\r
-  }\r
-  return (TRUE);\r
-}\r
-\r
 /**\r
   Function to process a NSH script file via SHELL_FILE_HANDLE.\r
 \r
@@ -2823,7 +2825,12 @@ RunScriptFileHandle (
       DeleteScriptFileStruct(NewScriptFile);\r
       return (EFI_OUT_OF_RESOURCES);\r
     }\r
-    for (LoopVar = 0 ; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) {\r
+    //\r
+    // Put the full path of the script file into Argv[0] as required by section\r
+    // 3.6.2 of version 2.2 of the shell specification.\r
+    //\r
+    NewScriptFile->Argv[0] = StrnCatGrow(&NewScriptFile->Argv[0], NULL, NewScriptFile->ScriptName, 0);\r
+    for (LoopVar = 1 ; LoopVar < 10 && LoopVar < NewScriptFile->Argc; LoopVar++) {\r
       ASSERT(NewScriptFile->Argv[LoopVar] == NULL);\r
       NewScriptFile->Argv[LoopVar] = StrnCatGrow(&NewScriptFile->Argv[LoopVar], NULL, ShellInfoObject.NewShellParametersProtocol->Argv[LoopVar], 0);\r
       if (NewScriptFile->Argv[LoopVar] == NULL) {\r
@@ -2888,8 +2895,8 @@ RunScriptFileHandle (
       ; // conditional increment in the body of the loop\r
   ){\r
     ASSERT(CommandLine2 != NULL);\r
-    StrnCpyS( CommandLine2, \r
-              PrintBuffSize/sizeof(CHAR16), \r
+    StrnCpyS( CommandLine2,\r
+              PrintBuffSize/sizeof(CHAR16),\r
               NewScriptFile->CurrentCommand->Cl,\r
               PrintBuffSize/sizeof(CHAR16) - 1\r
               );\r
@@ -2915,8 +2922,8 @@ RunScriptFileHandle (
       //\r
       // Due to variability in starting the find and replace action we need to have both buffers the same.\r
       //\r
-      StrnCpyS( CommandLine, \r
-                PrintBuffSize/sizeof(CHAR16), \r
+      StrnCpyS( CommandLine,\r
+                PrintBuffSize/sizeof(CHAR16),\r
                 CommandLine2,\r
                 PrintBuffSize/sizeof(CHAR16) - 1\r
                 );\r
@@ -2971,8 +2978,8 @@ RunScriptFileHandle (
       Status = ShellCopySearchAndReplace(CommandLine,  CommandLine2, PrintBuffSize, L"%8", L"\"\"", FALSE, FALSE);\r
       Status = ShellCopySearchAndReplace(CommandLine2,  CommandLine, PrintBuffSize, L"%9", L"\"\"", FALSE, FALSE);\r
 \r
-      StrnCpyS( CommandLine2, \r
-                PrintBuffSize/sizeof(CHAR16), \r
+      StrnCpyS( CommandLine2,\r
+                PrintBuffSize/sizeof(CHAR16),\r
                 CommandLine,\r
                 PrintBuffSize/sizeof(CHAR16) - 1\r
                 );\r