]> git.proxmox.com Git - mirror_edk2.git/blobdiff - ShellPkg/Application/Shell/Shell.c
ShellPkg: Refactor change to current file system
[mirror_edk2.git] / ShellPkg / Application / Shell / Shell.c
index 1c617abff509301a48410c0b4611d56b3fc2dd63..0cf09ec76b70b07d5aa62e227514449f52984888 100644 (file)
@@ -1430,6 +1430,32 @@ RunSplitCommand(
   return (Status);\r
 }\r
 \r
+/**\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
+  @param[out]CmdName  upon successful return the name of the command to be run\r
+\r
+  @retval EFI_SUCCESS           the function was successful\r
+  @retval EFI_OUT_OF_RESOURCES  a memory allocation failed\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ShellSubstituteVariables(\r
+  IN CHAR16 **CmdLine\r
+  )\r
+{\r
+  CHAR16      *NewCmdLine;\r
+  NewCmdLine = ShellConvertVariables(*CmdLine);\r
+  SHELL_FREE_NON_NULL(*CmdLine);\r
+  if (NewCmdLine == NULL) {\r
+    return (EFI_OUT_OF_RESOURCES);\r
+  }\r
+  *CmdLine = NewCmdLine;\r
+  return (EFI_SUCCESS);\r
+}\r
+\r
 /**\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
@@ -1501,6 +1527,134 @@ ShellSubstituteAliases(
   return (EFI_SUCCESS);\r
 }\r
 \r
+/**\r
+  Takes the Argv[0] part of the command line and determine the meaning of it.\r
+**/\r
+SHELL_OPERATION_TYPES\r
+EFIAPI\r
+GetOperationType(\r
+  IN CONST CHAR16 *CmdName\r
+  )\r
+{\r
+        CHAR16* FileWithPath;\r
+  CONST CHAR16* TempLocation;\r
+  CONST CHAR16* TempLocation2;\r
+\r
+  FileWithPath = NULL;\r
+  //\r
+  // test for an internal command.\r
+  //\r
+  if (ShellCommandIsCommandOnList(CmdName)) {\r
+    return (INTERNAL_COMMAND);\r
+  }\r
+\r
+  //\r
+  // Test for file system change request.  anything ending with : and cant have spaces.\r
+  //\r
+  if (CmdName[(StrLen(CmdName)-1)] == L':') {\r
+    if (StrStr(CmdName, L" ") != NULL) {\r
+      return (UNKNOWN_INVALID);\r
+    }\r
+    return (FILE_SYS_CHANGE);\r
+  }\r
+\r
+  //\r
+  // Test for a file\r
+  //\r
+  if ((FileWithPath = ShellFindFilePathEx(CmdName, mExecutableExtensions)) != NULL) {\r
+    //\r
+    // See if that file has a script file extension\r
+    //\r
+    if (StrLen(FileWithPath) > 4) {\r
+      TempLocation = FileWithPath+StrLen(FileWithPath)-4;\r
+      TempLocation2 = mScriptExtension;\r
+      if (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0) {\r
+        SHELL_FREE_NON_NULL(FileWithPath);\r
+        return (SCRIPT_FILE_NAME);\r
+      }\r
+    }\r
+\r
+    //\r
+    // Was a file, but not a script.  we treat this as an application.\r
+    //\r
+    SHELL_FREE_NON_NULL(FileWithPath);\r
+    return (EFI_APPLICATION);\r
+  }\r
+  \r
+  SHELL_FREE_NON_NULL(FileWithPath);\r
+  //\r
+  // No clue what this is... return invalid flag...\r
+  //\r
+  return (UNKNOWN_INVALID);\r
+}\r
+\r
+/**\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ProcessNewSplitCommandLine(\r
+  IN CONST CHAR16 *CmdLine\r
+  )\r
+{\r
+  SPLIT_LIST                *Split;\r
+  EFI_STATUS                Status;\r
+\r
+  Split = NULL;\r
+\r
+  //\r
+  // are we in an existing split???\r
+  //\r
+  if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
+    Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
+  }\r
+\r
+  if (Split == NULL) {\r
+    Status = RunSplitCommand(CmdLine, NULL, NULL);\r
+  } else {\r
+    Status = RunSplitCommand(CmdLine, Split->SplitStdIn, Split->SplitStdOut);\r
+  }\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, CmdLine);\r
+  }\r
+  return (Status);\r
+}\r
+\r
+/**\r
+  Handle a request to change the current file system\r
+\r
+  @param[in] CmdLine  The passed in command line\r
+\r
+  @retval EFI_SUCCESS The operation was successful\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+ChangeMappedDrive(\r
+  IN CONST CHAR16 *CmdLine\r
+  )\r
+{\r
+  EFI_STATUS Status;\r
+  Status = EFI_SUCCESS;\r
+\r
+  //\r
+  // make sure we are the right operation\r
+  //\r
+  ASSERT(CmdLine[(StrLen(CmdLine)-1)] == L':' && StrStr(CmdLine, L" ") == NULL);\r
+  \r
+  //\r
+  // Call the protocol API to do the work\r
+  //\r
+  Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir(NULL, CmdLine);\r
+\r
+  //\r
+  // Report any errors\r
+  //\r
+  if (EFI_ERROR(Status)) {\r
+    ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, CmdLine);\r
+  }\r
+\r
+  return (Status);\r
+}\r
+\r
 /**\r
   Function will process and run a command line.\r
 \r
@@ -1526,7 +1680,6 @@ RunCommand(
   CHAR16                    **Argv;\r
   BOOLEAN                   LastError;\r
   CHAR16                    LeString[19];\r
-  CHAR16                    *PostVariableCmdLine;\r
   CHAR16                    *CommandWithPath;\r
   CONST EFI_DEVICE_PATH_PROTOCOL  *DevPath;\r
   CONST CHAR16              *TempLocation;\r
@@ -1538,7 +1691,6 @@ RunCommand(
   UINTN                     Count;\r
   UINTN                     Count2;\r
   CHAR16                    *CleanOriginal;\r
-  SPLIT_LIST                *Split;\r
 \r
   ASSERT(CmdLine != NULL);\r
   if (StrLen(CmdLine) == 0) {\r
@@ -1546,12 +1698,10 @@ RunCommand(
   }\r
 \r
   CommandName         = NULL;\r
-  PostVariableCmdLine = NULL;\r
   CommandWithPath     = NULL;\r
   DevPath             = NULL;\r
   Status              = EFI_SUCCESS;\r
   CleanOriginal       = NULL;\r
-  Split               = NULL;\r
 \r
   CleanOriginal = StrnCatGrow(&CleanOriginal, NULL, CmdLine, 0);\r
   if (CleanOriginal == NULL) {\r
@@ -1576,53 +1726,35 @@ RunCommand(
     return (Status);\r
   }\r
 \r
-  PostVariableCmdLine = ShellConvertVariables(CleanOriginal);\r
-\r
-  if (PostVariableCmdLine == NULL) {\r
-    return (EFI_OUT_OF_RESOURCES);\r
+  Status = ShellSubstituteVariables(&CleanOriginal);\r
+  if (EFI_ERROR(Status)) {\r
+    return (Status);\r
   }\r
 \r
-  TrimSpaces(&PostVariableCmdLine);\r
+  TrimSpaces(&CleanOriginal);\r
 \r
   //\r
   // We dont do normal processing with a split command line (output from one command input to another)\r
   //\r
-  if (ContainsSplit(PostVariableCmdLine)) {\r
-    //\r
-    // are we in an existing split???\r
-    //\r
-    if (!IsListEmpty(&ShellInfoObject.SplitList.Link)) {\r
-      Split = (SPLIT_LIST*)GetFirstNode(&ShellInfoObject.SplitList.Link);\r
-    }\r
-\r
-    if (Split == NULL) {\r
-      Status = RunSplitCommand(PostVariableCmdLine, NULL, NULL);\r
-    } else {\r
-      Status = RunSplitCommand(PostVariableCmdLine, Split->SplitStdIn, Split->SplitStdOut);\r
-    }\r
-    if (EFI_ERROR(Status)) {\r
-      ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, PostVariableCmdLine);\r
-    }\r
+  if (ContainsSplit(CleanOriginal)) {\r
+    Status = ProcessNewSplitCommandLine(CleanOriginal);\r
   } else {\r
-\r
     //\r
     // If this is a mapped drive change handle that...\r
     //\r
-    if (PostVariableCmdLine[(StrLen(PostVariableCmdLine)-1)] == L':' && StrStr(PostVariableCmdLine, L" ") == NULL) {\r
-      Status = ShellInfoObject.NewEfiShellProtocol->SetCurDir(NULL, PostVariableCmdLine);\r
-      if (EFI_ERROR(Status)) {\r
-        ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_MAPPING), ShellInfoObject.HiiHandle, PostVariableCmdLine);\r
-      }\r
-      FreePool(PostVariableCmdLine);\r
+    if (CleanOriginal[(StrLen(CleanOriginal)-1)] == L':' && StrStr(CleanOriginal, L" ") == NULL) {\r
+      Status = ChangeMappedDrive(CleanOriginal);\r
+      SHELL_FREE_NON_NULL(CleanOriginal);\r
       return (Status);\r
     }\r
 \r
+\r
     ///@todo update this section to divide into 3 ways - run internal command, run split (above), and run an external file...\r
     ///      We waste a lot of time doing processing like StdIn,StdOut,Argv,Argc for things that are external files...\r
 \r
 \r
 \r
-    Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);\r
+    Status = UpdateStdInStdOutStdErr(ShellInfoObject.NewShellParametersProtocol, CleanOriginal, &OriginalStdIn, &OriginalStdOut, &OriginalStdErr, &OriginalSystemTableInfo);\r
     if (EFI_ERROR(Status)) {\r
       if (Status == EFI_NOT_FOUND) {\r
         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_REDUNDA_REDIR), ShellInfoObject.HiiHandle);\r
@@ -1630,12 +1762,12 @@ RunCommand(
         ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_REDIR), ShellInfoObject.HiiHandle);\r
       }\r
     } else {\r
-      TrimSpaces(&PostVariableCmdLine);\r
+      TrimSpaces(&CleanOriginal);\r
     \r
       //\r
       // get the argc and argv updated for internal commands\r
       //\r
-      Status = UpdateArgcArgv(ShellInfoObject.NewShellParametersProtocol, PostVariableCmdLine, &Argv, &Argc);\r
+      Status = UpdateArgcArgv(ShellInfoObject.NewShellParametersProtocol, CleanOriginal, &Argv, &Argc);\r
       ASSERT_EFI_ERROR(Status);\r
 \r
       for (Count = 0 ; Count < ShellInfoObject.NewShellParametersProtocol->Argc ; Count++) {\r
@@ -1727,7 +1859,7 @@ RunCommand(
             Status = InternalShellExecuteDevicePath(\r
               &gImageHandle,\r
               DevPath,\r
-              PostVariableCmdLine,\r
+              CleanOriginal,\r
               NULL,\r
               &StatusCode\r
              );\r
@@ -1772,7 +1904,6 @@ RunCommand(
 \r
   SHELL_FREE_NON_NULL(CommandName);\r
   SHELL_FREE_NON_NULL(CommandWithPath);\r
-  SHELL_FREE_NON_NULL(PostVariableCmdLine);\r
   SHELL_FREE_NON_NULL(CleanOriginal);\r
 \r
   return (Status);\r