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);
}