This is THE shell (application)\r
\r
Copyright (c) 2009 - 2015, Intel Corporation. All rights reserved.<BR>\r
- (C) Copyright 2013-2014, Hewlett-Packard Development Company, L.P.\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
}\r
\r
/**\r
- Check whether the string between a pair of % is a valid envifronment variable name.\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
+ @param[in] FindString The string to look for\r
+ @param[in] CheckForEscapeCharacter TRUE to skip escaped instances of FinfString, otherwise will return even escaped instances\r
+**/\r
+CHAR16*\r
+EFIAPI\r
+FindNextInstance(\r
+ IN CONST CHAR16 *SourceString,\r
+ IN CONST CHAR16 *FindString,\r
+ IN CONST BOOLEAN CheckForEscapeCharacter\r
+ )\r
+{\r
+ CHAR16 *Temp;\r
+ if (SourceString == NULL) {\r
+ return (NULL);\r
+ }\r
+ Temp = StrStr(SourceString, FindString);\r
+\r
+ //\r
+ // If nothing found, or we don't care about escape characters\r
+ //\r
+ if (Temp == NULL || !CheckForEscapeCharacter) {\r
+ return (Temp);\r
+ }\r
+\r
+ //\r
+ // If we found an escaped character, try again on the remainder of the string\r
+ //\r
+ if ((Temp > (SourceString)) && *(Temp-1) == L'^') {\r
+ return FindNextInstance(Temp+1, FindString, CheckForEscapeCharacter);\r
+ }\r
+\r
+ //\r
+ // we found the right character\r
+ //\r
+ return (Temp);\r
+}\r
+\r
+/**\r
+ Check whether the string between a pair of % is a valid environment variable name.\r
\r
@param[in] BeginPercent pointer to the first percent.\r
@param[in] EndPercent pointer to the last percent.\r
CONST CHAR16 *FirstQuote;\r
CONST CHAR16 *SecondQuote;\r
\r
- FirstQuote = FindFirstCharacter (CmdLine, L"\"", L'^');\r
+ FirstQuote = FindNextInstance (CmdLine, L"\"", TRUE);\r
SecondQuote = NULL;\r
TempSpot = FindFirstCharacter(CmdLine, L"|", L'^');\r
\r
if (FirstQuote == NULL || FirstQuote > TempSpot) {\r
break;\r
} \r
- SecondQuote = FindFirstCharacter (FirstQuote + 1, L"\"", L'^');\r
+ SecondQuote = FindNextInstance (FirstQuote + 1, L"\"", TRUE);\r
if (SecondQuote == NULL) {\r
break;\r
}\r
if (SecondQuote < TempSpot) {\r
- FirstQuote = FindFirstCharacter (SecondQuote + 1, L"\"", L'^');\r
+ FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);\r
continue;\r
} else {\r
- FirstQuote = FindFirstCharacter (SecondQuote + 1, L"\"", L'^');\r
+ FirstQuote = FindNextInstance (SecondQuote + 1, L"\"", TRUE);\r
TempSpot = FindFirstCharacter(TempSpot + 1, L"|", L'^');\r
continue;\r
} \r
feature's enabled state was not known when the shell initially launched.\r
\r
@retval EFI_SUCCESS The feature is enabled.\r
- @retval EFI_OUT_OF_RESOURCES There is not enough mnemory available.\r
+ @retval EFI_OUT_OF_RESOURCES There is not enough memory available.\r
**/\r
EFI_STATUS\r
EFIAPI\r
/**\r
Sets all the alias' that were registered with the ShellCommandLib library.\r
\r
- @retval EFI_SUCCESS all init commands were run sucessfully.\r
+ @retval EFI_SUCCESS all init commands were run successfully.\r
**/\r
EFI_STATUS\r
EFIAPI\r
loaded image protocol installed on it. The FilePath will point to the device path\r
for the file that was loaded.\r
\r
- @param[in, out] DevPath On a sucessful return the device path to the loaded image.\r
- @param[in, out] FilePath On a sucessful return the device path to the file.\r
+ @param[in, out] DevPath On a successful return the device path to the loaded image.\r
+ @param[in, out] FilePath On a successful return the device path to the file.\r
\r
- @retval EFI_SUCCESS The 2 device paths were sucessfully returned.\r
+ @retval EFI_SUCCESS The 2 device paths were successfully returned.\r
@retval other A error from gBS->HandleProtocol.\r
\r
@sa HandleProtocol\r
) == 0) {\r
ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit = TRUE;\r
} else if (StrnCmp (L"-", CurrentArg, 1) == 0) {\r
- // Unrecognised option\r
+ // Unrecognized option\r
ShellPrintHiiEx(-1, -1, NULL,\r
STRING_TOKEN (STR_GEN_PROBLEM),\r
ShellInfoObject.HiiHandle,\r
)\r
{\r
EFI_STATUS Status;\r
+ EFI_STATUS CalleeStatus;\r
UINTN Delay;\r
EFI_INPUT_KEY Key;\r
SHELL_FILE_HANDLE FileHandle;\r
if (FileStringPath == NULL) {\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
- StrnCpy(FileStringPath, ShellInfoObject.ShellInitSettings.FileName, NewSize/sizeof(CHAR16) -1);\r
+ StrCpyS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileName);\r
if (ShellInfoObject.ShellInitSettings.FileOptions != NULL) {\r
- StrnCat(FileStringPath, L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
- StrnCat(FileStringPath, ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
+ StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), L" ", NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
+ StrnCatS(FileStringPath, NewSize/sizeof(CHAR16), ShellInfoObject.ShellInitSettings.FileOptions, NewSize/sizeof(CHAR16) - StrLen(FileStringPath) -1);\r
+ }\r
+ Status = RunShellCommand(FileStringPath, &CalleeStatus);\r
+ if (ShellInfoObject.ShellInitSettings.BitUnion.Bits.Exit == TRUE) {\r
+ ShellCommandRegisterExit(gEfiShellProtocol->BatchIsActive(), (UINT64)CalleeStatus);\r
}\r
- Status = RunCommand(FileStringPath);\r
FreePool(FileStringPath);\r
return (Status);\r
\r
FileStringPath = ShellFindFilePath(mStartupScript);\r
if (FileStringPath == NULL) {\r
//\r
- // we return success since we dont need to have a startup script\r
+ // we return success since we don't need to have a startup script\r
//\r
Status = EFI_SUCCESS;\r
ASSERT(FileHandle == NULL);\r
CONST CHAR16 *CurDir;\r
UINTN BufferSize;\r
EFI_STATUS Status;\r
+ LIST_ENTRY OldBufferList;\r
\r
CurDir = NULL;\r
\r
return EFI_OUT_OF_RESOURCES;\r
}\r
\r
+ SaveBufferList(&OldBufferList);\r
CurDir = ShellInfoObject.NewEfiShellProtocol->GetEnv(L"cwd");\r
\r
//\r
//\r
// Done with this command\r
//\r
+ RestoreBufferList(&OldBufferList);\r
FreePool (CmdLine);\r
return Status;\r
}\r
return (Buffer);\r
}\r
\r
+\r
+/**\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
+VOID\r
+SaveBufferList (\r
+ OUT LIST_ENTRY *OldBufferList\r
+ )\r
+{\r
+ CopyMem (OldBufferList, &ShellInfoObject.BufferToFreeList.Link, sizeof (LIST_ENTRY));\r
+ InitializeListHead (&ShellInfoObject.BufferToFreeList.Link);\r
+}\r
+\r
+/**\r
+ Restore previous nodes into BufferToFreeList .\r
+\r
+ @param OldBufferList The temporary list head used to store the nodes in BufferToFreeList.\r
+**/\r
+VOID\r
+RestoreBufferList (\r
+ IN OUT LIST_ENTRY *OldBufferList\r
+ )\r
+{\r
+ FreeBufferList (&ShellInfoObject.BufferToFreeList);\r
+ CopyMem (&ShellInfoObject.BufferToFreeList.Link, OldBufferList, sizeof (LIST_ENTRY));\r
+}\r
+\r
+\r
/**\r
Add a buffer to the Line History List\r
\r
)\r
{\r
BUFFER_LIST *Node;\r
+ BUFFER_LIST *Walker;\r
+ UINT16 MaxHistoryCmdCount;\r
+ UINT16 Count;\r
+ \r
+ Count = 0;\r
+ MaxHistoryCmdCount = PcdGet16(PcdShellMaxHistoryCommandCount);\r
+ \r
+ if (MaxHistoryCmdCount == 0) {\r
+ return ;\r
+ }\r
+\r
\r
Node = AllocateZeroPool(sizeof(BUFFER_LIST));\r
ASSERT(Node != NULL);\r
Node->Buffer = AllocateCopyPool(StrSize(Buffer), Buffer);\r
ASSERT(Node->Buffer != NULL);\r
\r
- InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);\r
+ for ( Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link)\r
+ ; !IsNull(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)\r
+ ; Walker = (BUFFER_LIST*)GetNextNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Walker->Link)\r
+ ){\r
+ Count++;\r
+ }\r
+ if (Count < MaxHistoryCmdCount){\r
+ InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);\r
+ } else {\r
+ Walker = (BUFFER_LIST*)GetFirstNode(&ShellInfoObject.ViewingSettings.CommandHistory.Link);\r
+ RemoveEntryList(&Walker->Link);\r
+ if (Walker->Buffer != NULL) {\r
+ FreePool(Walker->Buffer);\r
+ }\r
+ FreePool(Walker);\r
+ InsertTailList(&ShellInfoObject.ViewingSettings.CommandHistory.Link, &Node->Link);\r
+ }\r
}\r
\r
/**\r
CHAR16 *CurrentLocator;\r
\r
for (CurrentLocator = CmdLine ; CurrentLocator != NULL ; ) {\r
- FirstQuote = FindFirstCharacter(CurrentLocator, L"\"", L'^');\r
- FirstPercent = FindFirstCharacter(CurrentLocator, L"%", L'^');\r
- SecondPercent = FirstPercent!=NULL?FindFirstCharacter(FirstPercent+1, L"%", L'^'):NULL;\r
+ FirstQuote = FindNextInstance(CurrentLocator, L"\"", TRUE);\r
+ FirstPercent = FindNextInstance(CurrentLocator, L"%", TRUE);\r
+ SecondPercent = FirstPercent!=NULL?FindNextInstance(FirstPercent+1, L"%", TRUE):NULL;\r
if (FirstPercent == NULL || SecondPercent == NULL) {\r
//\r
- // If we ever dont have 2 % we are done.\r
+ // If we ever don't have 2 % we are done.\r
//\r
break;\r
}\r
\r
if (FirstQuote!= NULL && FirstQuote < FirstPercent) {\r
- SecondQuote = FindFirstCharacter(FirstQuote+1, L"\"", L'^');\r
+ SecondQuote = FindNextInstance(FirstQuote+1, L"\"", TRUE);\r
//\r
// Quote is first found\r
//\r
+\r
if (SecondQuote < FirstPercent) {\r
//\r
// restart after the pair of "\r
//\r
CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent + 1));\r
//\r
- // dont need to update the locator. both % characters are gone.\r
+ // don't need to update the locator. both % characters are gone.\r
//\r
} else {\r
CurrentLocator = SecondPercent + 1;\r
\r
@param[in] OriginalCommandLine The original command line\r
\r
- @retval NULL An error ocurred.\r
+ @retval NULL An error occurred.\r
@return The new command line with no environment variables present.\r
**/\r
CHAR16*\r
; Temp = StrStr(Temp+1, AliasListNode->Alias)\r
){\r
//\r
- // we need a preceeding and if there is space no ^ preceeding (if no space ignore)\r
+ // we need a preceding and if there is space no ^ preceding (if no space ignore)\r
//\r
if ((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2)) {\r
NewSize += StrSize(AliasListNode->CommandString);\r
; Temp = StrStr(Temp+1, MasterEnvList)\r
){\r
//\r
- // we need a preceeding and following % and if there is space no ^ preceeding (if no space ignore)\r
+ // we need a preceding and following % and if there is space no ^ preceding (if no space ignore)\r
//\r
if (*(Temp-1) == L'%' && *(Temp+StrLen(MasterEnvList)) == L'%' &&\r
((((Temp-OriginalCommandLine)>2) && *(Temp-2) != L'^') || ((Temp-OriginalCommandLine)<=2))) {\r
; MasterEnvList != NULL && *MasterEnvList != CHAR_NULL\r
; MasterEnvList += StrLen(MasterEnvList) + 1\r
){\r
- StrnCpy(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1);\r
- StrnCat(ItemTemp, MasterEnvList, ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp));\r
- StrnCat(ItemTemp, L"%", ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16))-1 - StrLen(ItemTemp));\r
+ StrCpyS( ItemTemp, \r
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+ L"%"\r
+ );\r
+ StrCatS( ItemTemp, \r
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+ MasterEnvList\r
+ );\r
+ StrCatS( ItemTemp, \r
+ ((ItemSize+(2*sizeof(CHAR16)))/sizeof(CHAR16)), \r
+ L"%"\r
+ );\r
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, ItemTemp, EfiShellGetEnv(MasterEnvList), TRUE, FALSE);\r
- StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);\r
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
}\r
if (CurrentScriptFile != NULL) {\r
for (AliasListNode = (ALIAS_LIST*)GetFirstNode(&CurrentScriptFile->SubstList)\r
; AliasListNode = (ALIAS_LIST*)GetNextNode(&CurrentScriptFile->SubstList, &AliasListNode->Link)\r
){\r
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, AliasListNode->Alias, AliasListNode->CommandString, TRUE, FALSE);\r
- StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);\r
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
}\r
}\r
\r
//\r
- // Remove non-existant environment variables\r
+ // Remove non-existent environment variables\r
//\r
StripUnreplacedEnvironmentVariables(NewCommandLine1);\r
\r
// Now cleanup any straggler intentionally ignored "%" characters\r
//\r
ShellCopySearchAndReplace(NewCommandLine1, NewCommandLine2, NewSize, L"^%", L"%", TRUE, FALSE);\r
- StrnCpy(NewCommandLine1, NewCommandLine2, NewSize/sizeof(CHAR16)-1);\r
+ StrCpyS(NewCommandLine1, NewSize/sizeof(CHAR16), NewCommandLine2);\r
\r
FreePool(NewCommandLine2);\r
FreePool(ItemTemp);\r
SHELL_FREE_NON_NULL(OurCommandLine);\r
SHELL_FREE_NON_NULL(NextCommandLine);\r
return (EFI_INVALID_PARAMETER);\r
- } else if (NextCommandLine[0] != CHAR_NULL &&\r
- NextCommandLine[0] == L'a' &&\r
- NextCommandLine[1] == L' '\r
- ){\r
+ } else if (NextCommandLine[0] == L'a' &&\r
+ (NextCommandLine[1] == L' ' || NextCommandLine[1] == CHAR_NULL)\r
+ ){\r
CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));\r
+ while (NextCommandLine[0] == L' ') {\r
+ CopyMem(NextCommandLine, NextCommandLine+1, StrSize(NextCommandLine) - sizeof(NextCommandLine[0]));\r
+ }\r
+ if (NextCommandLine[0] == CHAR_NULL) {\r
+ SHELL_FREE_NON_NULL(OurCommandLine);\r
+ SHELL_FREE_NON_NULL(NextCommandLine);\r
+ return (EFI_INVALID_PARAMETER);\r
+ }\r
Unicode = FALSE;\r
} else {\r
Unicode = TRUE;\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
TempWalker = (CHAR16*)Temp;\r
- if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine)))) {\r
+ if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine), TRUE))) {\r
if (GetOperationType(FirstParameter) == Unknown_Invalid) {\r
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);\r
SetLastError(SHELL_NOT_FOUND);\r
EFI_STATUS Status;\r
\r
//\r
- // Verify up to the pipe or end character\r
+ // If this was the only item, then get out\r
//\r
- Status = IsValidSplit(CmdLine);\r
- if (EFI_ERROR(Status)) {\r
- return (Status);\r
+ if (!ContainsSplit(CmdLine)) {\r
+ return (EFI_SUCCESS);\r
}\r
\r
//\r
- // If this was the only item, then get out\r
+ // Verify up to the pipe or end character\r
//\r
- if (!ContainsSplit(CmdLine)) {\r
- return (EFI_SUCCESS);\r
+ Status = IsValidSplit(CmdLine);\r
+ if (EFI_ERROR(Status)) {\r
+ return (Status);\r
}\r
\r
//\r
// recurse to verify the next item\r
//\r
TempSpot = FindFirstCharacter(CmdLine, L"|", L'^') + 1;\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
return (VerifySplit(TempSpot));\r
}\r
\r
@param[in] CmdLine pointer to the command line to process\r
\r
@retval EFI_SUCCESS The operation was successful\r
- @return an error occured.\r
+ @return an error occurred.\r
**/\r
EFI_STATUS\r
EFIAPI\r
{\r
CHAR16 *CurrentParameter;\r
CHAR16 *Walker;\r
- CHAR16 *LastWalker;\r
CHAR16 *NewCommandLine;\r
EFI_STATUS Status;\r
+ UINTN NewCmdLineSize;\r
\r
Status = EFI_SUCCESS;\r
\r
\r
Walker = *CmdLine;\r
while(Walker != NULL && *Walker != CHAR_NULL) {\r
- LastWalker = Walker;\r
- if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine)))) {\r
+ if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine), TRUE))) {\r
if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {\r
- LastWalker[0] = L' ';\r
- LastWalker[1] = L' ';\r
- NewCommandLine = AllocateZeroPool(StrSize(L"help ") + StrSize(*CmdLine));\r
+ CurrentParameter[0] = L' ';\r
+ CurrentParameter[1] = L' ';\r
+ NewCmdLineSize = StrSize(L"help ") + StrSize(*CmdLine);\r
+ NewCommandLine = AllocateZeroPool(NewCmdLineSize);\r
if (NewCommandLine == NULL) {\r
Status = EFI_OUT_OF_RESOURCES;\r
break;\r
//\r
// We know the space is sufficient since we just calculated it.\r
//\r
- StrnCpy(NewCommandLine, L"help ", 5);\r
- StrnCat(NewCommandLine, *CmdLine, StrLen(*CmdLine));\r
+ StrnCpyS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), L"help ", 5);\r
+ StrnCatS(NewCommandLine, NewCmdLineSize/sizeof(CHAR16), *CmdLine, StrLen(*CmdLine));\r
SHELL_FREE_NON_NULL(*CmdLine);\r
*CmdLine = NewCommandLine;\r
break;\r
\r
@retval EFI_SUCCESS The operation was successful\r
@retval EFI_OUT_OF_RESOURCES A memory allocation failed.\r
- @return some other error occured\r
+ @return some other error occurred\r
**/\r
EFI_STATUS\r
EFIAPI\r
/**\r
Run an internal shell command.\r
\r
- This API will upadate the shell's environment since these commands are libraries.\r
+ This API will update the shell's environment since these commands are libraries.\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
+ @param[out] CommandStatus the status from the command line.\r
\r
@retval EFI_SUCCESS The command was completed.\r
@retval EFI_ABORTED The command's operation was aborted.\r
RunInternalCommand(\r
IN CONST CHAR16 *CmdLine,\r
IN CHAR16 *FirstParameter,\r
- IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,\r
+ OUT EFI_STATUS *CommandStatus\r
)\r
{\r
EFI_STATUS Status;\r
//\r
// get the argc and argv updated for internal commands\r
//\r
- Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, &Argv, &Argc);\r
+ Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, Internal_Command, &Argv, &Argc);\r
if (!EFI_ERROR(Status)) {\r
//\r
// Run the internal command.\r
Status = ShellCommandRunCommandHandler(FirstParameter, &CommandReturnedStatus, &LastError);\r
\r
if (!EFI_ERROR(Status)) {\r
+ if (CommandStatus != NULL) {\r
+ if (CommandReturnedStatus != SHELL_SUCCESS) {\r
+ *CommandStatus = (EFI_STATUS)(CommandReturnedStatus | MAX_BIT);\r
+ } else {\r
+ *CommandStatus = EFI_SUCCESS;\r
+ }\r
+ }\r
+\r
//\r
// Update last error status.\r
// some commands do not update last error.\r
}\r
\r
//\r
- // This is guarenteed to be called after UpdateArgcArgv no matter what else happened.\r
+ // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.\r
// This is safe even if the update API failed. In this case, it may be a no-op.\r
//\r
RestoreArgcArgv(ParamProtocol, &Argv, &Argc);\r
\r
//\r
- // If a script is running and the command is not a scipt only command, then\r
+ // If a script is running and the command is not a script only command, then\r
// change return value to success so the script won't halt (unless aborted).\r
//\r
// Script only commands have to be able halt the script since the script will\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
+ @param[out] CommandStatus the status from the command line.\r
\r
@retval EFI_SUCCESS The command was completed.\r
@retval EFI_ABORTED The command's operation was aborted.\r
IN SHELL_OPERATION_TYPES Type,\r
IN CONST CHAR16 *CmdLine,\r
IN CHAR16 *FirstParameter,\r
- IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,\r
+ OUT EFI_STATUS *CommandStatus\r
)\r
{\r
EFI_STATUS Status;\r
\r
switch (Type) {\r
case Internal_Command:\r
- Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol);\r
+ Status = RunInternalCommand(CmdLine, FirstParameter, ParamProtocol, CommandStatus);\r
break;\r
case Script_File_Name:\r
case Efi_Application:\r
CalleeExitStatus = (SHELL_STATUS) StartStatus;\r
}\r
\r
+ if (CommandStatus != NULL) {\r
+ *CommandStatus = CalleeExitStatus;\r
+ }\r
+\r
//\r
// Update last error status.\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
+ @param[out] CommandStatus the status from the command line.\r
\r
@retval EFI_SUCCESS The command was completed.\r
@retval EFI_ABORTED The command's operation was aborted.\r
EFI_STATUS\r
EFIAPI\r
SetupAndRunCommandOrFile(\r
- IN SHELL_OPERATION_TYPES Type,\r
- IN CHAR16 *CmdLine,\r
- IN CHAR16 *FirstParameter,\r
- IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol\r
+ IN SHELL_OPERATION_TYPES Type,\r
+ IN CHAR16 *CmdLine,\r
+ IN CHAR16 *FirstParameter,\r
+ IN EFI_SHELL_PARAMETERS_PROTOCOL *ParamProtocol,\r
+ OUT EFI_STATUS *CommandStatus\r
)\r
{\r
EFI_STATUS Status;\r
//\r
if (!EFI_ERROR(Status)) {\r
TrimSpaces(&CmdLine);\r
- Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol);\r
+ Status = RunCommandOrFile(Type, CmdLine, FirstParameter, ParamProtocol, CommandStatus);\r
}\r
\r
//\r
command or dispatch an external application.\r
\r
@param[in] CmdLine The command line to parse.\r
+ @param[out] CommandStatus The status from the command line.\r
\r
@retval EFI_SUCCESS The command was completed.\r
@retval EFI_ABORTED The command's operation was aborted.\r
**/\r
EFI_STATUS\r
EFIAPI\r
-RunCommand(\r
- IN CONST CHAR16 *CmdLine\r
+RunShellCommand(\r
+ IN CONST CHAR16 *CmdLine,\r
+ OUT EFI_STATUS *CommandStatus\r
)\r
{\r
EFI_STATUS Status;\r
// NULL out comments (leveraged from RunScriptFileHandle() ).\r
// The # character on a line is used to denote that all characters on the same line\r
// and to the right of the # are to be ignored by the shell.\r
- // Afterward, again remove spaces, in case any were between the last command-parameter and '#'.\r
+ // Afterwards, again remove spaces, in case any were between the last command-parameter and '#'.\r
//\r
for (TempWalker = CleanOriginal; TempWalker != NULL && *TempWalker != CHAR_NULL; TempWalker++) {\r
if (*TempWalker == L'^') {\r
}\r
\r
//\r
- // We dont do normal processing with a split command line (output from one command input to another)\r
+ // We don't do normal processing with a split command line (output from one command input to another)\r
//\r
if (ContainsSplit(CleanOriginal)) {\r
Status = ProcessNewSplitCommandLine(CleanOriginal);\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
TempWalker = CleanOriginal;\r
- if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal)))) {\r
+ if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal), TRUE))) {\r
//\r
// Depending on the first parameter we change the behavior\r
//\r
case Internal_Command:\r
case Script_File_Name:\r
case Efi_Application:\r
- Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol);\r
+ Status = SetupAndRunCommandOrFile(Type, CleanOriginal, FirstParameter, ShellInfoObject.NewShellParametersProtocol, CommandStatus);\r
break;\r
default:\r
//\r
return (Status);\r
}\r
\r
+/**\r
+ Function will process and run a command line.\r
+\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
+\r
+ @retval EFI_SUCCESS The command was completed.\r
+ @retval EFI_ABORTED The command's operation was aborted.\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+RunCommand(\r
+ IN CONST CHAR16 *CmdLine\r
+ )\r
+{\r
+ return (RunShellCommand(CmdLine, NULL));\r
+}\r
+\r
+\r
STATIC CONST UINT16 InvalidChars[] = {L'*', L'?', L'<', L'>', L'\\', L'/', L'\"', 0x0001, 0x0002};\r
/**\r
- Function determins if the CommandName COULD be a valid command. It does not determine whether\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
@param[in] Handle The handle to the already opened file.\r
@param[in] Name The name of the script file.\r
\r
- @retval EFI_SUCCESS the script completed sucessfully\r
+ @retval EFI_SUCCESS the script completed successfully\r
**/\r
EFI_STATUS\r
EFIAPI\r
EFI_STATUS Status;\r
SCRIPT_FILE *NewScriptFile;\r
UINTN LoopVar;\r
+ UINTN PrintBuffSize;\r
CHAR16 *CommandLine;\r
CHAR16 *CommandLine2;\r
CHAR16 *CommandLine3;\r
CONST CHAR16 *CurDir;\r
UINTN LineCount;\r
CHAR16 LeString[50];\r
+ LIST_ENTRY OldBufferList;\r
\r
ASSERT(!ShellCommandGetScriptExit());\r
\r
PreScriptEchoState = ShellCommandGetEchoState();\r
+ PrintBuffSize = PcdGet16(PcdShellPrintBufferSize);\r
\r
NewScriptFile = (SCRIPT_FILE*)AllocateZeroPool(sizeof(SCRIPT_FILE));\r
if (NewScriptFile == NULL) {\r
//\r
// Now enumerate through the commands and run each one.\r
//\r
- CommandLine = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
+ CommandLine = AllocateZeroPool(PrintBuffSize);\r
if (CommandLine == NULL) {\r
DeleteScriptFileStruct(NewScriptFile);\r
return (EFI_OUT_OF_RESOURCES);\r
}\r
- CommandLine2 = AllocateZeroPool(PcdGet16(PcdShellPrintBufferSize));\r
+ CommandLine2 = AllocateZeroPool(PrintBuffSize);\r
if (CommandLine2 == NULL) {\r
FreePool(CommandLine);\r
DeleteScriptFileStruct(NewScriptFile);\r
; // conditional increment in the body of the loop\r
){\r
ASSERT(CommandLine2 != NULL);\r
- StrnCpy(CommandLine2, NewScriptFile->CurrentCommand->Cl, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);\r
+ StrnCpyS( CommandLine2, \r
+ PrintBuffSize/sizeof(CHAR16), \r
+ NewScriptFile->CurrentCommand->Cl,\r
+ PrintBuffSize/sizeof(CHAR16) - 1\r
+ );\r
+\r
+ SaveBufferList(&OldBufferList);\r
\r
//\r
// NULL out comments\r
//\r
// Due to variability in starting the find and replace action we need to have both buffers the same.\r
//\r
- StrnCpy(CommandLine, CommandLine2, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);\r
+ StrnCpyS( CommandLine, \r
+ PrintBuffSize/sizeof(CHAR16), \r
+ CommandLine2,\r
+ PrintBuffSize/sizeof(CHAR16) - 1\r
+ );\r
\r
//\r
// Remove the %0 to %9 from the command line (if we have some arguments)\r
if (NewScriptFile->Argv != NULL) {\r
switch (NewScriptFile->Argc) {\r
default:\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", NewScriptFile->Argv[9], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 9:\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", NewScriptFile->Argv[8], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 8:\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", NewScriptFile->Argv[7], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 7:\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", NewScriptFile->Argv[6], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 6:\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", NewScriptFile->Argv[5], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 5:\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", NewScriptFile->Argv[4], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 4:\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", NewScriptFile->Argv[3], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 3:\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", NewScriptFile->Argv[2], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 2:\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", NewScriptFile->Argv[1], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
case 1:\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%0", NewScriptFile->Argv[0], FALSE, TRUE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE);\r
ASSERT_EFI_ERROR(Status);\r
break;\r
case 0:\r
break;\r
}\r
}\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%1", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%2", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%3", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%4", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%5", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%6", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%7", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PcdGet16 (PcdShellPrintBufferSize), L"%8", L"\"\"", FALSE, FALSE);\r
- Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PcdGet16 (PcdShellPrintBufferSize), L"%9", L"\"\"", FALSE, FALSE);\r
-\r
- StrnCpy(CommandLine2, CommandLine, PcdGet16(PcdShellPrintBufferSize)/sizeof(CHAR16)-1);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", L"\"\"", FALSE, FALSE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", L"\"\"", FALSE, FALSE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", L"\"\"", FALSE, FALSE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", L"\"\"", FALSE, FALSE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", L"\"\"", FALSE, FALSE);\r
+ Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", L"\"\"", FALSE, FALSE);\r
+ Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", L"\"\"", FALSE, FALSE);\r
+ 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
+ CommandLine,\r
+ PrintBuffSize/sizeof(CHAR16) - 1\r
+ );\r
\r
LastCommand = NewScriptFile->CurrentCommand;\r
\r
\r
ShellCommandRegisterExit(FALSE, 0);\r
Status = EFI_SUCCESS;\r
+ RestoreBufferList(&OldBufferList);\r
break;\r
}\r
if (ShellGetExecutionBreakFlag()) {\r
+ RestoreBufferList(&OldBufferList);\r
break;\r
}\r
if (EFI_ERROR(Status)) {\r
+ RestoreBufferList(&OldBufferList);\r
break;\r
}\r
if (ShellCommandGetExit()) {\r
+ RestoreBufferList(&OldBufferList);\r
break;\r
}\r
}\r
NewScriptFile->CurrentCommand->Reset = TRUE;\r
}\r
}\r
+ RestoreBufferList(&OldBufferList);\r
}\r
\r
\r
@param[in] CmdLine the command line to run.\r
@param[in] ParamProtocol the shell parameters protocol pointer\r
\r
- @retval EFI_SUCCESS the script completed sucessfully\r
+ @retval EFI_SUCCESS the script completed successfully\r
**/\r
EFI_STATUS\r
EFIAPI\r
//\r
// get the argc and argv updated for scripts\r
//\r
- Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc);\r
+ Status = UpdateArgcArgv(ParamProtocol, CmdLine, Script_File_Name, &Argv, &Argc);\r
if (!EFI_ERROR(Status)) {\r
\r
if (Handle == NULL) {\r
}\r
\r
//\r
- // This is guarenteed to be called after UpdateArgcArgv no matter what else happened.\r
+ // This is guaranteed to be called after UpdateArgcArgv no matter what else happened.\r
// This is safe even if the update API failed. In this case, it may be a no-op.\r
//\r
RestoreArgcArgv(ParamProtocol, &Argv, &Argc);\r
}\r
\r
/**\r
- Return the pointer to the first occurance of any character from a list of characters.\r
+ Return the pointer to the first occurrence of any character from a list of characters.\r
\r
@param[in] String the string to parse\r
@param[in] CharacterList the list of character to look for\r
}\r
}\r
return (String + StrLen(String));\r
-}
\ No newline at end of file
+}\r