X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ShellPkg%2FApplication%2FShell%2FShell.c;h=7eaccb747cccb65088eb6e9243039fa3ffe0129f;hb=14030c5c854ea40487a853344fc763d808c1a88b;hp=4abeafcd44474f08a9c45e05ff263bf4ada4d3f0;hpb=0c41d28e598356f083c308f359d435e63a6e0ef9;p=mirror_edk2.git diff --git a/ShellPkg/Application/Shell/Shell.c b/ShellPkg/Application/Shell/Shell.c index 4abeafcd44..7eaccb747c 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 - 2014, Intel Corporation. All rights reserved.
+ Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.
(C) Copyright 2013-2014, 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 @@ -100,6 +100,95 @@ TrimSpaces( return (EFI_SUCCESS); } +/** + Parse for the next instance of one string within another string. Can optionally make sure that + the string was not escaped (^ character) per the shell specification. + + @param[in] SourceString The string to search within + @param[in] FindString The string to look for + @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances +**/ +CHAR16* +EFIAPI +FindNextInstance( + IN CONST CHAR16 *SourceString, + IN CONST CHAR16 *FindString, + IN CONST BOOLEAN CheckForEscapeCharacter + ) +{ + CHAR16 *Temp; + if (SourceString == NULL) { + return (NULL); + } + Temp = StrStr(SourceString, FindString); + + // + // If nothing found, or we dont care about escape characters + // + if (Temp == NULL || !CheckForEscapeCharacter) { + return (Temp); + } + + // + // If we found an escaped character, try again on the remainder of the string + // + if ((Temp > (SourceString)) && *(Temp-1) == L'^') { + return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter); + } + + // + // we found the right character + // + return (Temp); +} + +/** + Check whether the string between a pair of % is a valid envifronment variable name. + + @param[in] BeginPercent pointer to the first percent. + @param[in] EndPercent pointer to the last percent. + + @retval TRUE is a valid environment variable name. + @retval FALSE is NOT a valid environment variable name. +**/ +BOOLEAN +IsValidEnvironmentVariableName( + IN CONST CHAR16 *BeginPercent, + IN CONST CHAR16 *EndPercent + ) +{ + CONST CHAR16 *Walker; + + Walker = NULL; + + ASSERT (BeginPercent != NULL); + ASSERT (EndPercent != NULL); + ASSERT (BeginPercent < EndPercent); + + if ((BeginPercent + 1) == EndPercent) { + return FALSE; + } + + for (Walker = BeginPercent + 1; Walker < EndPercent; Walker++) { + if ( + (*Walker >= L'0' && *Walker <= L'9') || + (*Walker >= L'A' && *Walker <= L'Z') || + (*Walker >= L'a' && *Walker <= L'z') || + (*Walker == L'_') + ) { + if (Walker == BeginPercent + 1 && (*Walker >= L'0' && *Walker <= L'9')) { + return FALSE; + } else { + continue; + } + } else { + return FALSE; + } + } + + return TRUE; +} + /** Find a command line contains a split operation @@ -142,7 +231,39 @@ ContainsSplit( ) { CONST CHAR16 *TempSpot; - TempSpot = FindSplit(CmdLine); + CONST CHAR16 *FirstQuote; + CONST CHAR16 *SecondQuote; + + FirstQuote = FindNextInstance (CmdLine, L"\"", TRUE); + SecondQuote = NULL; + TempSpot = FindSplit(CmdLine); + + if (FirstQuote == NULL || + TempSpot == NULL || + TempSpot == CHAR_NULL || + FirstQuote > TempSpot + ) { + return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)); + } + + while ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)) { + if (FirstQuote == NULL || FirstQuote > TempSpot) { + break; + } + SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE); + if (SecondQuote == NULL) { + break; + } + if (SecondQuote < TempSpot) { + FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE); + continue; + } else { + FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE); + TempSpot = FindSplit(TempSpot + 1); + continue; + } + } + return (BOOLEAN) ((TempSpot != NULL) && (*TempSpot != CHAR_NULL)); } @@ -244,9 +365,6 @@ UefiMain ( UINTN Size; EFI_HANDLE ConInHandle; EFI_SIMPLE_TEXT_INPUT_PROTOCOL *OldConIn; - UINTN ExitDataSize; - CHAR16 *ExitData; - SHELL_STATUS ExitStatus; if (PcdGet8(PcdShellSupportLevel) > 3) { return (EFI_UNSUPPORTED); @@ -300,12 +418,6 @@ UefiMain ( // install our console logger. This will keep a log of the output for back-browsing // Status = ConsoleLoggerInstall(ShellInfoObject.LogScreenCount, &ShellInfoObject.ConsoleInfo); - if(EFI_ERROR (Status)) { - ExitStatus = (SHELL_STATUS) (Status & (~MAX_BIT)); - } else { - ExitStatus = SHELL_SUCCESS; - } - if (!EFI_ERROR(Status)) { // // Enable the cursor to be visible @@ -419,7 +531,7 @@ UefiMain ( // Display the mapping // if (PcdGet8(PcdShellSupportLevel) >= 2 && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoMap) { - Status = RunCommand(L"map", NULL); + Status = RunCommand(L"map"); ASSERT_EFI_ERROR(Status); } @@ -485,11 +597,7 @@ UefiMain ( // // process the startup script or launch the called app. // - Status = DoStartupScript( - ShellInfoObject.ImageDevPath, - ShellInfoObject.FileDevPath, - &ExitStatus - ); + Status = DoStartupScript(ShellInfoObject.ImageDevPath, ShellInfoObject.FileDevPath); } if (!ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit && !ShellCommandGetExit() && (PcdGet8(PcdShellSupportLevel) >= 3 || PcdGetBool(PcdShellForceConsole)) && !EFI_ERROR(Status) && !ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoConsoleIn) { @@ -509,6 +617,7 @@ UefiMain ( // Reset page break back to default. // ShellInfoObject.PageBreakEnabled = PcdGetBool(PcdShellPageBreakDefault); + ASSERT (ShellInfoObject.ConsoleInfo != NULL); ShellInfoObject.ConsoleInfo->Enabled = TRUE; ShellInfoObject.ConsoleInfo->RowCounter = 0; @@ -522,7 +631,6 @@ UefiMain ( // Status = DoShellPrompt(); } while (!ShellCommandGetExit()); - ExitStatus = (SHELL_STATUS) ShellCommandGetExitCode(); } if (OldConIn != NULL && ConInHandle != NULL) { CloseSimpleTextInOnFile (gST->ConIn); @@ -594,33 +702,10 @@ FreeResources: DEBUG_CODE(ShellInfoObject.ConsoleInfo = NULL;); } - if (!EFI_ERROR (Status)) { - // If the command exited with an error, we pass this error out in the ExitData - // so that it can be retrieved by the EfiShellExecute function (which may - // start the shell with gBS->StartImage) - if (ExitStatus != SHELL_SUCCESS) { - // Allocate a buffer for exit data to pass to gBS->Exit(). - // This buffer will contain the empty string immediately followed by - // the shell's exit status. (The empty string is required by the UEFI spec) - ExitDataSize = (sizeof (CHAR16) + sizeof (SHELL_STATUS)); - ExitData = AllocatePool (ExitDataSize); - if (ExitData == NULL) { - return EFI_OUT_OF_RESOURCES; - } - ExitData[0] = '\0'; - // Use CopyMem to avoid alignment faults - CopyMem ((ExitData + 1), &ExitStatus, sizeof (ExitStatus)); - - gBS->Exit (ImageHandle, EFI_ABORTED, ExitDataSize, ExitData); - - ASSERT (FALSE); - return EFI_SUCCESS; - } else { - return EFI_SUCCESS; - } - } else { - return Status; + if (ShellCommandGetExit()) { + return ((EFI_STATUS)ShellCommandGetExitCode()); } + return (Status); } /** @@ -936,7 +1021,7 @@ ProcessCommandLine( continue; } - ShellInfoObject.ShellInitSettings.FileName = AllocateZeroPool(StrSize(CurrentArg)); + ShellInfoObject.ShellInitSettings.FileName = AllocateCopyPool(StrSize(CurrentArg), CurrentArg); if (ShellInfoObject.ShellInitSettings.FileName == NULL) { return (EFI_OUT_OF_RESOURCES); } @@ -944,8 +1029,6 @@ ProcessCommandLine( // We found `file-name`. // ShellInfoObject.ShellInitSettings.BitUnion.Bits.NoStartup = 1; - - StrCpy (ShellInfoObject.ShellInitSettings.FileName, CurrentArg); LoopVar++; // Add `file-name-options` @@ -987,16 +1070,13 @@ ProcessCommandLine( @param ImagePath the path to the image for shell. first place to look for the startup script @param FilePath the path to the file for shell. second place to look for the startup script. - @param[out] ExitStatus The exit code of the script. Ignored if NULL. - @retval EFI_SUCCESS the variable is initialized. **/ EFI_STATUS EFIAPI DoStartupScript( - IN EFI_DEVICE_PATH_PROTOCOL *ImagePath, - IN EFI_DEVICE_PATH_PROTOCOL *FilePath, - OUT SHELL_STATUS *ExitStatus + IN EFI_DEVICE_PATH_PROTOCOL *ImagePath, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath ) { EFI_STATUS Status; @@ -1026,12 +1106,12 @@ DoStartupScript( if (FileStringPath == NULL) { return (EFI_OUT_OF_RESOURCES); } - StrCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName); + StrnCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName, NewSize/sizeof(CHAR16) -1); if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) { - StrCat(FileStringPath, L" "); - StrCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions); + StrnCat(FileStringPath, L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1); + StrnCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1); } - Status = RunCommand(FileStringPath, ExitStatus); + Status = RunCommand(FileStringPath); FreePool(FileStringPath); return (Status); @@ -1108,13 +1188,7 @@ DoStartupScript( // If we got a file, run it // if (!EFI_ERROR(Status) && FileHandle != NULL) { - Status = RunScriptFile ( - mStartupScript, - FileHandle, - L"", - ShellInfoObject.NewShellParametersProtocol, - ExitStatus - ); + Status = RunScriptFile (mStartupScript, FileHandle, L"", ShellInfoObject.NewShellParametersProtocol); ShellInfoObject.NewEfiShellProtocol->CloseFile(FileHandle); } else { FileStringPath = ShellFindFilePath(mStartupScript); @@ -1125,13 +1199,7 @@ DoStartupScript( Status = EFI_SUCCESS; ASSERT(FileHandle == NULL); } else { - Status = RunScriptFile( - FileStringPath, - NULL, - L"", - ShellInfoObject.NewShellParametersProtocol, - ExitStatus - ); + Status = RunScriptFile(FileStringPath, NULL, L"", ShellInfoObject.NewShellParametersProtocol); FreePool(FileStringPath); } } @@ -1196,7 +1264,7 @@ DoShellPrompt ( // if (!EFI_ERROR (Status)) { CmdLine[BufferSize / sizeof (CHAR16)] = CHAR_NULL; - Status = RunCommand(CmdLine, NULL); + Status = RunCommand(CmdLine); } // @@ -1246,9 +1314,8 @@ AddLineToCommandHistory( Node = AllocateZeroPool(sizeof(BUFFER_LIST)); ASSERT(Node != NULL); - Node->Buffer = AllocateZeroPool(StrSize(Buffer)); + Node->Buffer = AllocateCopyPool(StrSize(Buffer), Buffer); ASSERT(Node->Buffer != NULL); - StrCpy(Node->Buffer, Buffer); InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link); } @@ -1279,56 +1346,13 @@ ShellConvertAlias( return (EFI_SUCCESS); } FreePool(*CommandString); - *CommandString = AllocateZeroPool(StrSize(NewString)); + *CommandString = AllocateCopyPool(StrSize(NewString), NewString); if (*CommandString == NULL) { return (EFI_OUT_OF_RESOURCES); } - StrCpy(*CommandString, NewString); return (EFI_SUCCESS); } -/** - Parse for the next instance of one string within another string. Can optionally make sure that - the string was not escaped (^ character) per the shell specification. - - @param[in] SourceString The string to search within - @param[in] FindString The string to look for - @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances -**/ -CHAR16* -EFIAPI -FindNextInstance( - IN CONST CHAR16 *SourceString, - IN CONST CHAR16 *FindString, - IN CONST BOOLEAN CheckForEscapeCharacter - ) -{ - CHAR16 *Temp; - if (SourceString == NULL) { - return (NULL); - } - Temp = StrStr(SourceString, FindString); - - // - // If nothing found, or we dont care about escape characters - // - if (Temp == NULL || !CheckForEscapeCharacter) { - return (Temp); - } - - // - // If we found an escaped character, try again on the remainder of the string - // - if ((Temp > (SourceString)) && *(Temp-1) == L'^') { - return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter); - } - - // - // we found the right character - // - return (Temp); -} - /** This function will eliminate unreplaced (and therefore non-found) environment variables. @@ -1357,8 +1381,8 @@ StripUnreplacedEnvironmentVariables( break; } - if (FirstQuote < FirstPercent) { - SecondQuote = FirstQuote!= NULL?FindNextInstance(FirstQuote+1, L"\"", TRUE):NULL; + if (FirstQuote!= NULL && FirstQuote < FirstPercent) { + SecondQuote = FindNextInstance(FirstQuote+1, L"\"", TRUE); // // Quote is first found // @@ -1376,19 +1400,21 @@ StripUnreplacedEnvironmentVariables( } continue; } - ASSERT(FirstPercent < FirstQuote); - if (SecondPercent < FirstQuote) { - FirstPercent[0] = L'\"'; - SecondPercent[0] = L'\"'; - - // - // We need to remove from FirstPercent to SecondPercent - // - CopyMem(FirstPercent + 1, SecondPercent, StrSize(SecondPercent)); - CurrentLocator = FirstPercent + 2; + + if (FirstQuote == NULL || SecondPercent < FirstQuote) { + if (IsValidEnvironmentVariableName(FirstPercent, SecondPercent)) { + // + // We need to remove from FirstPercent to SecondPercent + // + CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1)); + // + // dont need to update the locator. both % characters are gone. + // + } else { + CurrentLocator = SecondPercent + 1; + } continue; } - ASSERT(FirstQuote < SecondPercent); CurrentLocator = FirstQuote; } return (EFI_SUCCESS); @@ -1476,7 +1502,7 @@ ShellConvertVariables ( // // now do the replacements... // - NewCommandLine1 = AllocateZeroPool(NewSize); + NewCommandLine1 = AllocateCopyPool(NewSize, OriginalCommandLine); NewCommandLine2 = AllocateZeroPool(NewSize); ItemTemp = AllocateZeroPool(ItemSize+(2*sizeof(CHAR16))); if (NewCommandLine1 == NULL || NewCommandLine2 == NULL || ItemTemp == NULL) { @@ -1485,16 +1511,15 @@ ShellConvertVariables ( SHELL_FREE_NON_NULL(ItemTemp); return (NULL); } - StrCpy(NewCommandLine1, OriginalCommandLine); for (MasterEnvList = EfiShellGetEnv(NULL) - ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL //&& *(MasterEnvList+1) != CHAR_NULL + ; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL ; MasterEnvList += StrLen(MasterEnvList) + 1 ){ - StrCpy(ItemTemp, L"%"); - StrCat(ItemTemp, MasterEnvList); - StrCat(ItemTemp, L"%"); + StrnCpy(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1); + StrnCat(ItemTemp, MasterEnvList, ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp)); + StrnCat(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp)); ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE); - StrCpy(NewCommandLine1, NewCommandLine2); + StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1); } if (CurrentScriptFile != NULL) { for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList) @@ -1502,20 +1527,20 @@ ShellConvertVariables ( ; AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link) ){ ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE); - StrCpy(NewCommandLine1, NewCommandLine2); + StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1); } - - // - // Remove non-existant environment variables in scripts only - // - StripUnreplacedEnvironmentVariables(NewCommandLine1); } + // + // Remove non-existant environment variables + // + StripUnreplacedEnvironmentVariables(NewCommandLine1); + // // Now cleanup any straggler intentionally ignored "%" characters // ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE); - StrCpy(NewCommandLine1, NewCommandLine2); + StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1); FreePool(NewCommandLine2); FreePool(ItemTemp); @@ -1530,9 +1555,6 @@ ShellConvertVariables ( @param[in] StdIn The pointer to the Standard input. @param[in] StdOut The pointer to the Standard output. - @param[out] ExitStatus The exit code of the last command in the pipeline. - Ignored if NULL. - @retval EFI_SUCCESS The split command is executed successfully. @retval other Some error occurs when executing the split command. **/ @@ -1541,8 +1563,7 @@ EFIAPI RunSplitCommand( IN CONST CHAR16 *CmdLine, IN SHELL_FILE_HANDLE *StdIn, - IN SHELL_FILE_HANDLE *StdOut, - OUT SHELL_STATUS *ExitStatus + IN SHELL_FILE_HANDLE *StdOut ) { EFI_STATUS Status; @@ -1596,7 +1617,7 @@ RunSplitCommand( ASSERT(Split->SplitStdOut != NULL); InsertHeadList(&ShellInfoObject.SplitList.Link, &Split->Link); - Status = RunCommand(OurCommandLine, NULL); + Status = RunCommand(OurCommandLine); // // move the output from the first to the in to the second. @@ -1611,7 +1632,7 @@ RunSplitCommand( ShellInfoObject.NewEfiShellProtocol->SetFilePosition(ConvertShellHandleToEfiFileProtocol(Split->SplitStdIn), 0); if (!EFI_ERROR(Status)) { - Status = RunCommand(NextCommandLine, ExitStatus); + Status = RunCommand(NextCommandLine); } // @@ -1849,12 +1870,12 @@ IsValidSplit( 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; + if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine)))) { + 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; + } } } @@ -1905,9 +1926,7 @@ VerifySplit( /** Process a split based operation. - @param[in] CmdLine Pointer to the command line to process - @param[out] ExitStatus The exit status of the command. Ignored if NULL. - Invalid if this function returns an error. + @param[in] CmdLine pointer to the command line to process @retval EFI_SUCCESS The operation was successful @return an error occured. @@ -1915,8 +1934,7 @@ VerifySplit( EFI_STATUS EFIAPI ProcessNewSplitCommandLine( - IN CONST CHAR16 *CmdLine, - OUT SHELL_STATUS *ExitStatus + IN CONST CHAR16 *CmdLine ) { SPLIT_LIST *Split; @@ -1937,14 +1955,9 @@ ProcessNewSplitCommandLine( } if (Split == NULL) { - Status = RunSplitCommand(CmdLine, NULL, NULL, ExitStatus); + Status = RunSplitCommand(CmdLine, NULL, NULL); } else { - Status = RunSplitCommand( - CmdLine, - Split->SplitStdIn, - Split->SplitStdOut, - ExitStatus - ); + Status = RunSplitCommand(CmdLine, Split->SplitStdIn, Split->SplitStdOut); } if (EFI_ERROR(Status)) { ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_INVALID_SPLIT), ShellInfoObject.HiiHandle, CmdLine); @@ -2017,20 +2030,25 @@ DoHelpUpdate( Walker = *CmdLine; while(Walker != NULL && *Walker != CHAR_NULL) { LastWalker = Walker; - GetNextParameter(&Walker, &CurrentParameter); - if (StrStr(CurrentParameter, L"-?") == CurrentParameter) { - LastWalker[0] = L' '; - LastWalker[1] = L' '; - NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine)); - if (NewCommandLine == NULL) { - Status = EFI_OUT_OF_RESOURCES; + if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine)))) { + if (StrStr(CurrentParameter, L"-?") == CurrentParameter) { + LastWalker[0] = L' '; + LastWalker[1] = L' '; + NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine)); + if (NewCommandLine == NULL) { + Status = EFI_OUT_OF_RESOURCES; + break; + } + + // + // We know the space is sufficient since we just calculated it. + // + StrnCpy(NewCommandLine, L"help ", 5); + StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine)); + SHELL_FREE_NON_NULL(*CmdLine); + *CmdLine = NewCommandLine; break; } - StrCpy(NewCommandLine, L"help "); - StrCat(NewCommandLine, *CmdLine); - SHELL_FREE_NON_NULL(*CmdLine); - *CmdLine = NewCommandLine; - break; } } @@ -2091,6 +2109,7 @@ ProcessCommandLineToFinal( if (EFI_ERROR(Status)) { return (Status); } + ASSERT (*CmdLine != NULL); TrimSpaces(CmdLine); @@ -2119,8 +2138,6 @@ ProcessCommandLineToFinal( @param[in] FirstParameter the first parameter on the command line @param[in] ParamProtocol the shell parameters protocol pointer - @param[out] ExitStatus The exit code of the command. Ignored if NULL. - @retval EFI_SUCCESS The command was completed. @retval EFI_ABORTED The command's operation was aborted. **/ @@ -2129,8 +2146,7 @@ EFIAPI RunInternalCommand( IN CONST CHAR16 *CmdLine, IN CHAR16 *FirstParameter, - IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, - OUT SHELL_STATUS *ExitStatus OPTIONAL + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol ) { EFI_STATUS Status; @@ -2138,11 +2154,24 @@ RunInternalCommand( CHAR16 **Argv; SHELL_STATUS CommandReturnedStatus; BOOLEAN LastError; + CHAR16 *Walker; + CHAR16 *NewCmdLine; + + NewCmdLine = AllocateCopyPool (StrSize (CmdLine), CmdLine); + if (NewCmdLine == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for (Walker = NewCmdLine; Walker != NULL && *Walker != CHAR_NULL ; Walker++) { + if (*Walker == L'^' && *(Walker+1) == L'#') { + CopyMem(Walker, Walker+1, StrSize(Walker) - sizeof(Walker[0])); + } + } // // get the argc and argv updated for internal commands // - Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc); + Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, &Argv, &Argc); if (!EFI_ERROR(Status)) { // // Run the internal command. @@ -2157,9 +2186,6 @@ RunInternalCommand( if (LastError) { SetLastError(CommandReturnedStatus); } - if (ExitStatus != NULL) { - *ExitStatus = CommandReturnedStatus; - } // // Pass thru the exitcode from the app. @@ -2203,6 +2229,7 @@ RunInternalCommand( Status = EFI_SUCCESS; } + FreePool (NewCmdLine); return (Status); } @@ -2214,9 +2241,6 @@ RunInternalCommand( @param[in] FirstParameter the first parameter on the command line @param[in] ParamProtocol the shell parameters protocol pointer - @param[out] ExitStatus The exit code of the command or file. - Ignored if NULL. - @retval EFI_SUCCESS The command was completed. @retval EFI_ABORTED The command's operation was aborted. **/ @@ -2226,8 +2250,7 @@ RunCommandOrFile( IN SHELL_OPERATION_TYPES Type, IN CONST CHAR16 *CmdLine, IN CHAR16 *FirstParameter, - IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, - OUT SHELL_STATUS *ExitStatus + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol ) { EFI_STATUS Status; @@ -2243,12 +2266,7 @@ RunCommandOrFile( switch (Type) { case Internal_Command: - Status = RunInternalCommand( - CmdLine, - FirstParameter, - ParamProtocol, - &CalleeExitStatus - ); + Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol); break; case Script_File_Name: case Efi_Application: @@ -2283,13 +2301,7 @@ RunCommandOrFile( } switch (Type) { case Script_File_Name: - Status = RunScriptFile ( - CommandWithPath, - NULL, - CmdLine, - ParamProtocol, - &CalleeExitStatus - ); + Status = RunScriptFile (CommandWithPath, NULL, CmdLine, ParamProtocol); break; case Efi_Application: // @@ -2309,9 +2321,7 @@ RunCommandOrFile( DevPath, CmdLine, NULL, - &StartStatus, - NULL, - NULL + &StartStatus ); SHELL_FREE_NON_NULL(DevPath); @@ -2344,10 +2354,6 @@ RunCommandOrFile( SHELL_FREE_NON_NULL(CommandWithPath); - if (ExitStatus != NULL) { - *ExitStatus = CalleeExitStatus; - } - return (Status); } @@ -2359,20 +2365,16 @@ RunCommandOrFile( @param[in] FirstParameter the first parameter on the command line. @param[in] ParamProtocol the shell parameters protocol pointer - @param[out] ExitStatus The exit code of the command or file. - Ignored if NULL. - @retval EFI_SUCCESS The command was completed. @retval EFI_ABORTED The command's operation was aborted. **/ EFI_STATUS EFIAPI SetupAndRunCommandOrFile( - IN SHELL_OPERATION_TYPES Type, - IN CHAR16 *CmdLine, - IN CHAR16 *FirstParameter, - IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, - OUT SHELL_STATUS *ExitStatus + IN SHELL_OPERATION_TYPES Type, + IN CHAR16 *CmdLine, + IN CHAR16 *FirstParameter, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol ) { EFI_STATUS Status; @@ -2391,13 +2393,8 @@ SetupAndRunCommandOrFile( // Now run the command, script, or application // if (!EFI_ERROR(Status)) { - Status = RunCommandOrFile( - Type, - CmdLine, - FirstParameter, - ParamProtocol, - ExitStatus - ); + TrimSpaces(&CmdLine); + Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol); } // @@ -2422,7 +2419,6 @@ SetupAndRunCommandOrFile( command or dispatch an external application. @param[in] CmdLine The command line to parse. - @param[out] ExitStatus The exit code of the command. Ignored if NULL. @retval EFI_SUCCESS The command was completed. @retval EFI_ABORTED The command's operation was aborted. @@ -2430,8 +2426,7 @@ SetupAndRunCommandOrFile( EFI_STATUS EFIAPI RunCommand( - IN CONST CHAR16 *CmdLine, - OUT SHELL_STATUS *ExitStatus + IN CONST CHAR16 *CmdLine ) { EFI_STATUS Status; @@ -2455,6 +2450,24 @@ RunCommand( TrimSpaces(&CleanOriginal); + // + // NULL out comments (leveraged from RunScriptFileHandle() ). + // The # character on a line is used to denote that all characters on the same line + // and to the right of the # are to be ignored by the shell. + // Afterward, again remove spaces, in case any were between the last command-parameter and '#'. + // + for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) { + if (*TempWalker == L'^') { + if (*(TempWalker + 1) == L'#') { + TempWalker++; + } + } else if (*TempWalker == L'#') { + *TempWalker = CHAR_NULL; + } + } + + TrimSpaces(&CleanOriginal); + // // Handle case that passed in command line is just 1 or more " " characters. // @@ -2473,7 +2486,7 @@ RunCommand( // We dont do normal processing with a split command line (output from one command input to another) // if (ContainsSplit(CleanOriginal)) { - Status = ProcessNewSplitCommandLine(CleanOriginal, ExitStatus); + Status = ProcessNewSplitCommandLine(CleanOriginal); SHELL_FREE_NON_NULL(CleanOriginal); return (Status); } @@ -2487,33 +2500,30 @@ RunCommand( return (EFI_OUT_OF_RESOURCES); } TempWalker = CleanOriginal; - GetNextParameter(&TempWalker, &FirstParameter); - - // - // Depending on the first parameter we change the behavior - // - switch (Type = GetOperationType(FirstParameter)) { - case File_Sys_Change: - Status = ChangeMappedDrive (FirstParameter); - break; - case Internal_Command: - case Script_File_Name: - case Efi_Application: - Status = SetupAndRunCommandOrFile( - Type, - CleanOriginal, - FirstParameter, - ShellInfoObject.NewShellParametersProtocol, - ExitStatus - ); - break; - default: - // - // Whatever was typed, it was invalid. - // - ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); - SetLastError(SHELL_NOT_FOUND); - break; + if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal)))) { + // + // Depending on the first parameter we change the behavior + // + switch (Type = GetOperationType(FirstParameter)) { + case File_Sys_Change: + Status = ChangeMappedDrive (FirstParameter); + break; + case Internal_Command: + case Script_File_Name: + case Efi_Application: + Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol); + break; + default: + // + // Whatever was typed, it was invalid. + // + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); + SetLastError(SHELL_NOT_FOUND); + break; + } + } else { + ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); + SetLastError(SHELL_NOT_FOUND); } SHELL_FREE_NON_NULL(CleanOriginal); @@ -2560,16 +2570,13 @@ IsValidCommandName( @param[in] Handle The handle to the already opened file. @param[in] Name The name of the script file. - @param[out] ExitStatus The exit code of the script. Ignored if NULL. - @retval EFI_SUCCESS the script completed sucessfully **/ EFI_STATUS EFIAPI RunScriptFileHandle ( - IN SHELL_FILE_HANDLE Handle, - IN CONST CHAR16 *Name, - OUT SHELL_STATUS *ExitStatus + IN SHELL_FILE_HANDLE Handle, + IN CONST CHAR16 *Name ) { EFI_STATUS Status; @@ -2585,11 +2592,8 @@ RunScriptFileHandle ( CONST CHAR16 *CurDir; UINTN LineCount; CHAR16 LeString[50]; - SHELL_STATUS CalleeExitStatus; ASSERT(!ShellCommandGetScriptExit()); - - CalleeExitStatus = SHELL_SUCCESS; PreScriptEchoState = ShellCommandGetEchoState(); @@ -2683,15 +2687,17 @@ RunScriptFileHandle ( ; // conditional increment in the body of the loop ){ ASSERT(CommandLine2 != NULL); - StrCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl); + StrnCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1); // // NULL out comments // for (CommandLine3 = CommandLine2 ; CommandLine3 != NULL && *CommandLine3 != CHAR_NULL ; CommandLine3++) { if (*CommandLine3 == L'^') { - if (*(CommandLine3+1) == L'#' || *(CommandLine3+1) == L':') { + if ( *(CommandLine3+1) == L':') { CopyMem(CommandLine3, CommandLine3+1, StrSize(CommandLine3) - sizeof(CommandLine3[0])); + } else if (*(CommandLine3+1) == L'#') { + CommandLine3++; } } else if (*CommandLine3 == L'#') { *CommandLine3 = CHAR_NULL; @@ -2702,7 +2708,7 @@ RunScriptFileHandle ( // // Due to variability in starting the find and replace action we need to have both buffers the same. // - StrCpy(CommandLine, CommandLine2); + StrnCpy(CommandLine, CommandLine2, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1); // // Remove the %0 to %9 from the command line (if we have some arguments) @@ -2710,34 +2716,34 @@ RunScriptFileHandle ( if (NewScriptFile->Argv != NULL) { switch (NewScriptFile->Argc) { default: - Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 9: - Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 8: - Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 7: - Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 6: - Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 5: - Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 4: - Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 3: - Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 2: - Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, FALSE); ASSERT_EFI_ERROR(Status); case 1: - Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, TRUE); + Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, FALSE); ASSERT_EFI_ERROR(Status); break; case 0: @@ -2754,7 +2760,7 @@ RunScriptFileHandle ( Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", L"\"\"", FALSE, FALSE); Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", L"\"\"", FALSE, FALSE); - StrCpy(CommandLine2, CommandLine); + StrnCpy(CommandLine2, CommandLine, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1); LastCommand = NewScriptFile->CurrentCommand; @@ -2773,7 +2779,7 @@ RunScriptFileHandle ( // PreCommandEchoState = ShellCommandGetEchoState(); ShellCommandSetEchoState(FALSE); - Status = RunCommand(CommandLine3+1, NULL); + Status = RunCommand(CommandLine3+1); // // If command was "@echo -off" or "@echo -on" then don't restore echo state @@ -2795,7 +2801,7 @@ RunScriptFileHandle ( } ShellPrintEx(-1, -1, L"%s\r\n", CommandLine2); } - Status = RunCommand(CommandLine3, NULL); + Status = RunCommand(CommandLine3); } } @@ -2803,8 +2809,7 @@ RunScriptFileHandle ( // // ShellCommandGetExitCode() always returns a UINT64 // - CalleeExitStatus = (SHELL_STATUS) ShellCommandGetExitCode(); - UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", CalleeExitStatus); + UnicodeSPrint(LeString, sizeof(LeString), L"0x%Lx", ShellCommandGetExitCode()); DEBUG_CODE(InternalEfiShellSetEnv(L"debuglasterror", LeString, TRUE);); InternalEfiShellSetEnv(L"lasterror", LeString, TRUE); @@ -2816,11 +2821,9 @@ RunScriptFileHandle ( break; } if (EFI_ERROR(Status)) { - CalleeExitStatus = (SHELL_STATUS) Status; break; } if (ShellCommandGetExit()) { - CalleeExitStatus = (SHELL_STATUS) ShellCommandGetExitCode(); break; } } @@ -2852,11 +2855,6 @@ RunScriptFileHandle ( if (ShellCommandGetCurrentScriptFile()==NULL) { ShellCommandSetEchoState(PreScriptEchoState); } - - if (ExitStatus != NULL) { - *ExitStatus = CalleeExitStatus; - } - return (EFI_SUCCESS); } @@ -2868,18 +2866,15 @@ RunScriptFileHandle ( @param[in] CmdLine the command line to run. @param[in] ParamProtocol the shell parameters protocol pointer - @param[out] ExitStatus The exit code of the script. Ignored if NULL. - @retval EFI_SUCCESS the script completed sucessfully **/ EFI_STATUS EFIAPI RunScriptFile ( - IN CONST CHAR16 *ScriptPath, - IN SHELL_FILE_HANDLE Handle OPTIONAL, - IN CONST CHAR16 *CmdLine, - IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol, - OUT SHELL_STATUS *ExitStatus + IN CONST CHAR16 *ScriptPath, + IN SHELL_FILE_HANDLE Handle OPTIONAL, + IN CONST CHAR16 *CmdLine, + IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol ) { EFI_STATUS Status; @@ -2906,7 +2901,7 @@ RunScriptFile ( // // run it // - Status = RunScriptFileHandle(FileHandle, ScriptPath, ExitStatus); + Status = RunScriptFileHandle(FileHandle, ScriptPath); // // now close the file @@ -2914,7 +2909,7 @@ RunScriptFile ( ShellCloseFile(&FileHandle); } } else { - Status = RunScriptFileHandle(Handle, ScriptPath, ExitStatus); + Status = RunScriptFileHandle(Handle, ScriptPath); } }