X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ShellPkg%2FApplication%2FShell%2FShell.c;h=81982f135405a9ac442fcb3728e4bf981584aa63;hb=4922715d85564441d7cf16bac1a1fa67673f6877;hp=fe722e955448bd0c60d6901da4bf3f9d350e85fc;hpb=806c49db0538080ac397892c750b86d1c55d32af;p=mirror_edk2.git diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c index fe722e9554..81982f1354 100644 --- a/ShellPkg/Application/Shell/Shell.c +++ b/ShellPkg/Application/Shell/Shell.c @@ -1,7 +1,7 @@ /** @file This is THE shell (application) - Copyright (c) 2009 - 2013, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2014, Intel Corporation. All rights reserved.
Copyright (c) 2013, Hewlett-Packard Development Company, L.P. This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License @@ -71,9 +71,9 @@ STATIC CONST CHAR16 mExecutableExtensions[] = L".NSH;.EFI"; STATIC CONST CHAR16 mStartupScript[] = L"startup.nsh"; /** - Cleans off leading and trailing spaces and tabs + Cleans off leading and trailing spaces and tabs. - @param[in] String pointer to the string to trim them off + @param[in] String pointer to the string to trim them off. **/ EFI_STATUS EFIAPI @@ -91,9 +91,9 @@ TrimSpaces( } // - // Remove any spaces at the end of the (*String). + // Remove any spaces and tabs at the end of the (*String). // - while ((*String)[StrLen((*String))-1] == L' ') { + while ((StrLen (*String) > 0) && (((*String)[StrLen((*String))-1] == L' ') || ((*String)[StrLen((*String))-1] == L'\t'))) { (*String)[StrLen((*String))-1] = CHAR_NULL; } @@ -107,8 +107,7 @@ TrimSpaces( @retval A pointer to the | character in CmdLine or NULL if not present. **/ -CONST -CHAR16* +CONST CHAR16* EFIAPI FindSplit( IN CONST CHAR16 *CmdLine @@ -1068,7 +1067,7 @@ DoShellPrompt ( if (!EFI_ERROR (Status)) { CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL; Status = RunCommand(CmdLine); - } + } // // Done with this command @@ -1432,13 +1431,12 @@ RunSplitCommand( /** Take the original command line, substitute any variables, free - the original string, return the modified copy + the original string, return the modified copy. - @param[in,out] CmdLine pointer to the command line to update - @param[out]CmdName upon successful return the name of the command to be run + @param[in] CmdLine pointer to the command line to update. - @retval EFI_SUCCESS the function was successful - @retval EFI_OUT_OF_RESOURCES a memory allocation failed + @retval EFI_SUCCESS the function was successful. + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. **/ EFI_STATUS EFIAPI @@ -1458,13 +1456,12 @@ ShellSubstituteVariables( /** Take the original command line, substitute any alias in the first group of space delimited characters, free - the original string, return the modified copy + the original string, return the modified copy. - @param[in] CmdLine pointer to the command line to update - @param[out]CmdName upon successful return the name of the command to be run + @param[in] CmdLine pointer to the command line to update. - @retval EFI_SUCCESS the function was successful - @retval EFI_OUT_OF_RESOURCES a memory allocation failed + @retval EFI_SUCCESS the function was successful. + @retval EFI_OUT_OF_RESOURCES a memory allocation failed. **/ EFI_STATUS EFIAPI @@ -1530,13 +1527,13 @@ ShellSubstituteAliases( /** Takes the Argv[0] part of the command line and determine the meaning of it. - @param[in] CmdLine pointer to the command line to update + @param[in] CmdName pointer to the command line to update. - @retval INTERNAL_COMMAND The name is an internal command - @retval FILE_SYS_CHANGE the name is a file system change - @retval SCRIPT_FILE_NAME the name is a NSH script file - @retval UNKNOWN_INVALID the name is unknown - @retval EFI_APPLICATION the name is an application (.EFI) + @retval Internal_Command The name is an internal command. + @retval File_Sys_Change the name is a file system change. + @retval Script_File_Name the name is a NSH script file. + @retval Unknown_Invalid the name is unknown. + @retval Efi_Application the name is an application (.EFI). **/ SHELL_OPERATION_TYPES EFIAPI @@ -1553,7 +1550,7 @@ GetOperationType( // test for an internal command. // if (ShellCommandIsCommandOnList(CmdName)) { - return (INTERNAL_COMMAND); + return (Internal_Command); } // @@ -1561,9 +1558,9 @@ GetOperationType( // if (CmdName[(StrLen(CmdName)-1)] == L':') { if (StrStr(CmdName, L" ") != NULL) { - return (UNKNOWN_INVALID); + return (Unknown_Invalid); } - return (FILE_SYS_CHANGE); + return (File_Sys_Change); } // @@ -1578,7 +1575,7 @@ GetOperationType( TempLocation2 = mScriptExtension; if (StringNoCaseCompare((VOID*)(&TempLocation), (VOID*)(&TempLocation2)) == 0) { SHELL_FREE_NON_NULL(FileWithPath); - return (SCRIPT_FILE_NAME); + return (Script_File_Name); } } @@ -1586,14 +1583,113 @@ GetOperationType( // Was a file, but not a script. we treat this as an application. // SHELL_FREE_NON_NULL(FileWithPath); - return (EFI_APPLICATION); + return (Efi_Application); } SHELL_FREE_NON_NULL(FileWithPath); // // No clue what this is... return invalid flag... // - return (UNKNOWN_INVALID); + return (Unknown_Invalid); +} + +/** + Determine if the first item in a command line is valid. + + @param[in] CmdLine The command line to parse. + + @retval EFI_SUCCESS The item is valid. + @retval EFI_OUT_OF_RESOURCES A memory allocation failed. + @retval EFI_NOT_FOUND The operation type is unknown or invalid. +**/ +EFI_STATUS +EFIAPI +IsValidSplit( + IN CONST CHAR16 *CmdLine + ) +{ + CHAR16 *Temp; + CHAR16 *FirstParameter; + CHAR16 *TempWalker; + EFI_STATUS Status; + + Temp = NULL; + + Temp = StrnCatGrow(&Temp, NULL, CmdLine, 0); + if (Temp == NULL) { + return (EFI_OUT_OF_RESOURCES); + } + + FirstParameter = StrStr(Temp, L"|"); + if (FirstParameter != NULL) { + *FirstParameter = CHAR_NULL; + } + + FirstParameter = NULL; + + // + // Process the command line + // + Status = ProcessCommandLineToFinal(&Temp); + + if (!EFI_ERROR(Status)) { + FirstParameter = AllocateZeroPool(StrSize(CmdLine)); + if (FirstParameter == NULL) { + SHELL_FREE_NON_NULL(Temp); + return (EFI_OUT_OF_RESOURCES); + } + TempWalker = (CHAR16*)Temp; + GetNextParameter(&TempWalker, &FirstParameter); + + if (GetOperationType(FirstParameter) == Unknown_Invalid) { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); + SetLastError(SHELL_NOT_FOUND); + Status = EFI_NOT_FOUND; + } + } + + SHELL_FREE_NON_NULL(Temp); + SHELL_FREE_NON_NULL(FirstParameter); + return Status; +} + +/** + Determine if a command line contains with a split contains only valid commands. + + @param[in] CmdLine The command line to parse. + + @retval EFI_SUCCESS CmdLine has only valid commands, application, or has no split. + @retval EFI_ABORTED CmdLine has at least one invalid command or application. +**/ +EFI_STATUS +EFIAPI +VerifySplit( + IN CONST CHAR16 *CmdLine + ) +{ + CONST CHAR16 *TempSpot; + EFI_STATUS Status; + + // + // Verify up to the pipe or end character + // + Status = IsValidSplit(CmdLine); + if (EFI_ERROR(Status)) { + return (Status); + } + + // + // If this was the only item, then get out + // + if (!ContainsSplit(CmdLine)) { + return (EFI_SUCCESS); + } + + // + // recurse to verify the next item + // + TempSpot = FindSplit(CmdLine)+1; + return (VerifySplit(TempSpot)); } /** @@ -1613,6 +1709,11 @@ ProcessNewSplitCommandLine( SPLIT_LIST *Split; EFI_STATUS Status; + Status = VerifySplit(CmdLine); + if (EFI_ERROR(Status)) { + return (Status); + } + Split = NULL; // @@ -1634,11 +1735,11 @@ ProcessNewSplitCommandLine( } /** - Handle a request to change the current file system + Handle a request to change the current file system. - @param[in] CmdLine The passed in command line + @param[in] CmdLine The passed in command line. - @retval EFI_SUCCESS The operation was successful + @retval EFI_SUCCESS The operation was successful. **/ EFI_STATUS EFIAPI @@ -1721,14 +1822,14 @@ DoHelpUpdate( } /** - Function to update the shell variable "lasterror" + Function to update the shell variable "lasterror". - @param[in] ErrorCode the error code to put into lasterror + @param[in] ErrorCode the error code to put into lasterror. **/ EFI_STATUS EFIAPI SetLastError( - IN CONST UINT64 ErrorCode + IN CONST SHELL_STATUS ErrorCode ) { CHAR16 LeString[19]; @@ -1754,7 +1855,7 @@ SetLastError( **/ EFI_STATUS EFIAPI -ProcessCommandLineAliasVariable( +ProcessCommandLineToFinal( IN OUT CHAR16 **CmdLine ) { @@ -1840,8 +1941,19 @@ RunInternalCommand( // Pass thru the exitcode from the app. // if (ShellCommandGetExit()) { + // + // An Exit was requested ("exit" command), pass its value up. + // Status = CommandReturnedStatus; - } else if (CommandReturnedStatus != 0 && IsScriptOnlyCommand(FirstParameter)) { + } else if (CommandReturnedStatus != SHELL_SUCCESS && IsScriptOnlyCommand(FirstParameter)) { + // + // Always abort when a script only command fails for any reason + // + Status = EFI_ABORTED; + } else if (ShellCommandGetCurrentScriptFile() != NULL && CommandReturnedStatus == SHELL_ABORTED) { + // + // Abort when in a script and a command aborted + // Status = EFI_ABORTED; } } @@ -1853,11 +1965,17 @@ RunInternalCommand( // RestoreArgcArgv(ParamProtocol, &Argv, &Argc); - if (ShellCommandGetCurrentScriptFile() != NULL && !IsScriptOnlyCommand(FirstParameter)) { - // - // if this is NOT a scipt only command return success so the script won't quit. - // prevent killing the script - this is the only place where we know the actual command name (after alias and variable replacement...) - // + // + // If a script is running and the command is not a scipt only command, then + // change return value to success so the script won't halt (unless aborted). + // + // Script only commands have to be able halt the script since the script will + // not operate if they are failing. + // + if ( ShellCommandGetCurrentScriptFile() != NULL + && !IsScriptOnlyCommand(FirstParameter) + && Status != EFI_ABORTED + ) { Status = EFI_SUCCESS; } @@ -1894,11 +2012,11 @@ RunCommandOrFile( DevPath = NULL; switch (Type) { - case INTERNAL_COMMAND: + case Internal_Command: Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol); break; - case SCRIPT_FILE_NAME: - case EFI_APPLICATION: + case Script_File_Name: + case Efi_Application: // // Process a fully qualified path // @@ -1926,13 +2044,13 @@ RunCommandOrFile( // if (!EFI_ERROR(ShellIsDirectory(CommandWithPath))) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); - SetLastError(EFI_NOT_FOUND); + SetLastError(SHELL_NOT_FOUND); } switch (Type) { - case SCRIPT_FILE_NAME: + case Script_File_Name: Status = RunScriptFile (CommandWithPath); break; - case EFI_APPLICATION: + case Efi_Application: // // Get the device path of the application image // @@ -1958,10 +2076,20 @@ RunCommandOrFile( // // Update last error status. // - SetLastError(StatusCode); + SetLastError((SHELL_STATUS) StatusCode); + break; + default: + // + // Do nothing. + // break; } break; + default: + // + // Do nothing. + // + break; } SHELL_FREE_NON_NULL(CommandWithPath); @@ -2069,7 +2197,7 @@ RunCommand( return (EFI_SUCCESS); } - Status = ProcessCommandLineAliasVariable(&CleanOriginal); + Status = ProcessCommandLineToFinal(&CleanOriginal); if (EFI_ERROR(Status)) { SHELL_FREE_NON_NULL(CleanOriginal); return (Status); @@ -2099,12 +2227,12 @@ RunCommand( // Depending on the first parameter we change the behavior // switch (Type = GetOperationType(FirstParameter)) { - case FILE_SYS_CHANGE: + case File_Sys_Change: Status = ChangeMappedDrive(CleanOriginal); break; - case INTERNAL_COMMAND: - case SCRIPT_FILE_NAME: - case EFI_APPLICATION: + case Internal_Command: + case Script_File_Name: + case Efi_Application: Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol); break; default: @@ -2112,7 +2240,7 @@ RunCommand( // Whatever was typed, it was invalid. // ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); - SetLastError(EFI_NOT_FOUND); + SetLastError(SHELL_NOT_FOUND); break; } @@ -2234,11 +2362,13 @@ RunScriptFileHandle ( while(!ShellFileHandleEof(Handle)) { CommandLine = ShellFileHandleReturnLine(Handle, &Ascii); LineCount++; - if (CommandLine == NULL || StrLen(CommandLine) == 0) { + if (CommandLine == NULL || StrLen(CommandLine) == 0 || CommandLine[0] == '#') { + SHELL_FREE_NON_NULL(CommandLine); continue; } NewScriptFile->CurrentCommand = AllocateZeroPool(sizeof(SCRIPT_COMMAND_LIST)); if (NewScriptFile->CurrentCommand == NULL) { + SHELL_FREE_NON_NULL(CommandLine); DeleteScriptFileStruct(NewScriptFile); return (EFI_OUT_OF_RESOURCES); }