ShellPkg: Don't strip positional parameters of quotation marks.

Per Shell SPEC 2.1 'Double-quotation marks that surround arguments are not stripped in positional parameters'. This patch makes Shell implementation to follow SPEC.

Contributed-under: TianoCore Contribution Agreement 1.0
Signed-off-by: Qiu Shumin <shumin.qiu@intel.com>
Reviewed-by: Jaben Carsey <jaben.carsey@intel.com>

git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@18742 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
Qiu Shumin
2015-11-09 02:29:31 +00:00
committed by shenshushi
parent 3ec97ca490
commit d1c275c651
5 changed files with 80 additions and 48 deletions

View File

@@ -1863,7 +1863,7 @@ IsValidSplit(
return (EFI_OUT_OF_RESOURCES); return (EFI_OUT_OF_RESOURCES);
} }
TempWalker = (CHAR16*)Temp; TempWalker = (CHAR16*)Temp;
if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine)))) { if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CmdLine), TRUE))) {
if (GetOperationType(FirstParameter) == Unknown_Invalid) { if (GetOperationType(FirstParameter) == Unknown_Invalid) {
ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter); ShellPrintHiiEx(-1, -1, NULL, STRING_TOKEN (STR_SHELL_NOT_FOUND), ShellInfoObject.HiiHandle, FirstParameter);
SetLastError(SHELL_NOT_FOUND); SetLastError(SHELL_NOT_FOUND);
@@ -2029,7 +2029,7 @@ DoHelpUpdate(
Walker = *CmdLine; Walker = *CmdLine;
while(Walker != NULL && *Walker != CHAR_NULL) { while(Walker != NULL && *Walker != CHAR_NULL) {
if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine)))) { if (!EFI_ERROR(GetNextParameter(&Walker, &CurrentParameter, StrSize(*CmdLine), TRUE))) {
if (StrStr(CurrentParameter, L"-?") == CurrentParameter) { if (StrStr(CurrentParameter, L"-?") == CurrentParameter) {
CurrentParameter[0] = L' '; CurrentParameter[0] = L' ';
CurrentParameter[1] = L' '; CurrentParameter[1] = L' ';
@@ -2173,7 +2173,7 @@ RunInternalCommand(
// //
// get the argc and argv updated for internal commands // get the argc and argv updated for internal commands
// //
Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, &Argv, &Argc); Status = UpdateArgcArgv(ParamProtocol, NewCmdLine, Internal_Command, &Argv, &Argc);
if (!EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
// //
// Run the internal command. // Run the internal command.
@@ -2520,7 +2520,7 @@ RunShellCommand(
return (EFI_OUT_OF_RESOURCES); return (EFI_OUT_OF_RESOURCES);
} }
TempWalker = CleanOriginal; TempWalker = CleanOriginal;
if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal)))) { if (!EFI_ERROR(GetNextParameter(&TempWalker, &FirstParameter, StrSize(CleanOriginal), TRUE))) {
// //
// Depending on the first parameter we change the behavior // Depending on the first parameter we change the behavior
// //
@@ -2767,34 +2767,34 @@ RunScriptFileHandle (
if (NewScriptFile->Argv != NULL) { if (NewScriptFile->Argv != NULL) {
switch (NewScriptFile->Argc) { switch (NewScriptFile->Argc) {
default: default:
Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%9", NewScriptFile->Argv[9], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 9: case 9:
Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%8", NewScriptFile->Argv[8], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 8: case 8:
Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%7", NewScriptFile->Argv[7], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 7: case 7:
Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%6", NewScriptFile->Argv[6], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 6: case 6:
Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%5", NewScriptFile->Argv[5], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 5: case 5:
Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%4", NewScriptFile->Argv[4], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 4: case 4:
Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%3", NewScriptFile->Argv[3], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 3: case 3:
Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%2", NewScriptFile->Argv[2], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 2: case 2:
Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine2, CommandLine, PrintBuffSize, L"%1", NewScriptFile->Argv[1], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
case 1: case 1:
Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, TRUE); Status = ShellCopySearchAndReplace(CommandLine, CommandLine2, PrintBuffSize, L"%0", NewScriptFile->Argv[0], FALSE, FALSE);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
break; break;
case 0: case 0:
@@ -2944,7 +2944,7 @@ RunScriptFile (
// //
// get the argc and argv updated for scripts // get the argc and argv updated for scripts
// //
Status = UpdateArgcArgv(ParamProtocol, CmdLine, &Argv, &Argc); Status = UpdateArgcArgv(ParamProtocol, CmdLine, Script_File_Name, &Argv, &Argc);
if (!EFI_ERROR(Status)) { if (!EFI_ERROR(Status)) {
if (Handle == NULL) { if (Handle == NULL) {

View File

@@ -124,14 +124,6 @@ typedef struct {
extern SHELL_INFO ShellInfoObject; extern SHELL_INFO ShellInfoObject;
typedef enum {
Internal_Command,
Script_File_Name,
Efi_Application,
File_Sys_Change,
Unknown_Invalid
} SHELL_OPERATION_TYPES;
/** /**
Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec. Converts the command line to it's post-processed form. this replaces variables and alias' per UEFI Shell spec.

View File

@@ -74,10 +74,12 @@ FindEndOfParameter(
This will also remove all remaining ^ characters after processing. This will also remove all remaining ^ characters after processing.
@param[in, out] Walker pointer to string of command line. Adjusted to @param[in, out] Walker pointer to string of command line. Adjusted to
reminaing command line on return reminaing command line on return
@param[in, out] TempParameter pointer to string of command line item extracted. @param[in, out] TempParameter pointer to string of command line item extracted.
@param[in] Length buffer size of TempParameter. @param[in] Length buffer size of TempParameter.
@param[in] StripQuotation if TRUE then strip the quotation marks surrounding
the parameters.
@return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string. @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string.
@return EFI_NOT_FOUND A closing " could not be found on the specified string @return EFI_NOT_FOUND A closing " could not be found on the specified string
@@ -87,7 +89,8 @@ EFIAPI
GetNextParameter( GetNextParameter(
IN OUT CHAR16 **Walker, IN OUT CHAR16 **Walker,
IN OUT CHAR16 **TempParameter, IN OUT CHAR16 **TempParameter,
IN CONST UINTN Length IN CONST UINTN Length,
IN BOOLEAN StripQuotation
) )
{ {
CONST CHAR16 *NextDelim; CONST CHAR16 *NextDelim;
@@ -161,7 +164,11 @@ DEBUG_CODE_END();
// //
// eliminate the unescaped quote // eliminate the unescaped quote
// //
CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1)); if (StripQuotation) {
CopyMem ((CHAR16*)NextDelim, NextDelim + 1, StrSize (NextDelim + 1));
} else{
NextDelim++;
}
} }
} }
@@ -178,9 +185,11 @@ DEBUG_CODE_END();
All special character processing (alias, environment variable, redirection, All special character processing (alias, environment variable, redirection,
etc... must be complete before calling this API. etc... must be complete before calling this API.
@param[in] CommandLine String of command line to parse @param[in] CommandLine String of command line to parse
@param[in, out] Argv pointer to array of strings; one for each parameter @param[in] StripQuotation if TRUE then strip the quotation marks surrounding
@param[in, out] Argc pointer to number of strings in Argv array the parameters.
@param[in, out] Argv pointer to array of strings; one for each parameter
@param[in, out] Argc pointer to number of strings in Argv array
@return EFI_SUCCESS the operation was sucessful @return EFI_SUCCESS the operation was sucessful
@return EFI_OUT_OF_RESOURCES a memory allocation failed. @return EFI_OUT_OF_RESOURCES a memory allocation failed.
@@ -189,8 +198,9 @@ EFI_STATUS
EFIAPI EFIAPI
ParseCommandLineToArgs( ParseCommandLineToArgs(
IN CONST CHAR16 *CommandLine, IN CONST CHAR16 *CommandLine,
IN OUT CHAR16 ***Argv, IN BOOLEAN StripQuotation,
IN OUT UINTN *Argc IN OUT CHAR16 ***Argv,
IN OUT UINTN *Argc
) )
{ {
UINTN Count; UINTN Count;
@@ -228,7 +238,7 @@ ParseCommandLineToArgs(
; Walker != NULL && *Walker != CHAR_NULL ; Walker != NULL && *Walker != CHAR_NULL
; Count++ ; Count++
) { ) {
if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) { if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, TRUE))) {
break; break;
} }
} }
@@ -246,7 +256,7 @@ ParseCommandLineToArgs(
Walker = (CHAR16*)NewCommandLine; Walker = (CHAR16*)NewCommandLine;
while(Walker != NULL && *Walker != CHAR_NULL) { while(Walker != NULL && *Walker != CHAR_NULL) {
SetMem16(TempParameter, Size, CHAR_NULL); SetMem16(TempParameter, Size, CHAR_NULL);
if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size))) { if (EFI_ERROR(GetNextParameter(&Walker, &TempParameter, Size, StripQuotation))) {
Status = EFI_INVALID_PARAMETER; Status = EFI_INVALID_PARAMETER;
goto Done; goto Done;
} }
@@ -375,6 +385,7 @@ CreatePopulateInstallShellParametersProtocol (
// Populate Argc and Argv // Populate Argc and Argv
// //
Status = ParseCommandLineToArgs(FullCommandLine, Status = ParseCommandLineToArgs(FullCommandLine,
TRUE,
&(*NewShellParameters)->Argv, &(*NewShellParameters)->Argv,
&(*NewShellParameters)->Argc); &(*NewShellParameters)->Argc);
@@ -1369,6 +1380,7 @@ RestoreStdInStdOutStdErr (
@param[in, out] ShellParameters Pointer to parameter structure to modify. @param[in, out] ShellParameters Pointer to parameter structure to modify.
@param[in] NewCommandLine The new command line to parse and use. @param[in] NewCommandLine The new command line to parse and use.
@param[in] Type The type of operation.
@param[out] OldArgv Pointer to old list of parameters. @param[out] OldArgv Pointer to old list of parameters.
@param[out] OldArgc Pointer to old number of items in Argv list. @param[out] OldArgc Pointer to old number of items in Argv list.
@@ -1380,11 +1392,15 @@ EFIAPI
UpdateArgcArgv( UpdateArgcArgv(
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
IN CONST CHAR16 *NewCommandLine, IN CONST CHAR16 *NewCommandLine,
IN SHELL_OPERATION_TYPES Type,
OUT CHAR16 ***OldArgv OPTIONAL, OUT CHAR16 ***OldArgv OPTIONAL,
OUT UINTN *OldArgc OPTIONAL OUT UINTN *OldArgc OPTIONAL
) )
{ {
BOOLEAN StripParamQuotation;
ASSERT(ShellParameters != NULL); ASSERT(ShellParameters != NULL);
StripParamQuotation = TRUE;
if (OldArgc != NULL) { if (OldArgc != NULL) {
*OldArgc = ShellParameters->Argc; *OldArgc = ShellParameters->Argc;
@@ -1393,7 +1409,15 @@ UpdateArgcArgv(
*OldArgv = ShellParameters->Argv; *OldArgv = ShellParameters->Argv;
} }
return (ParseCommandLineToArgs(NewCommandLine, &(ShellParameters->Argv), &(ShellParameters->Argc))); if (Type == Script_File_Name) {
StripParamQuotation = FALSE;
}
return ParseCommandLineToArgs( NewCommandLine,
StripParamQuotation,
&(ShellParameters->Argv),
&(ShellParameters->Argc)
);
} }
/** /**

View File

@@ -18,6 +18,14 @@
#include "Shell.h" #include "Shell.h"
typedef enum {
Internal_Command,
Script_File_Name,
Efi_Application,
File_Sys_Change,
Unknown_Invalid
} SHELL_OPERATION_TYPES;
/** /**
creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then creates a new EFI_SHELL_PARAMETERS_PROTOCOL instance and populates it and then
installs it on our handle and if there is an existing version of the protocol installs it on our handle and if there is an existing version of the protocol
@@ -66,6 +74,7 @@ CleanUpShellParametersProtocol (
@param[in, out] ShellParameters pointer to parameter structure to modify @param[in, out] ShellParameters pointer to parameter structure to modify
@param[in] NewCommandLine the new command line to parse and use @param[in] NewCommandLine the new command line to parse and use
@param[in] Type the type of operation.
@param[out] OldArgv pointer to old list of parameters @param[out] OldArgv pointer to old list of parameters
@param[out] OldArgc pointer to old number of items in Argv list @param[out] OldArgc pointer to old number of items in Argv list
@@ -77,6 +86,7 @@ EFIAPI
UpdateArgcArgv( UpdateArgcArgv(
IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters, IN OUT EFI_SHELL_PARAMETERS_PROTOCOL *ShellParameters,
IN CONST CHAR16 *NewCommandLine, IN CONST CHAR16 *NewCommandLine,
IN SHELL_OPERATION_TYPES Type,
OUT CHAR16 ***OldArgv, OUT CHAR16 ***OldArgv,
OUT UINTN *OldArgc OUT UINTN *OldArgc
); );
@@ -162,9 +172,11 @@ RestoreStdInStdOutStdErr (
parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space parameters for inclusion in EFI_SHELL_PARAMETERS_PROTOCOL. this supports space
delimited and quote surrounded parameter definition. delimited and quote surrounded parameter definition.
@param[in] CommandLine String of command line to parse @param[in] CommandLine String of command line to parse
@param[in, out] Argv pointer to array of strings; one for each parameter @param[in] StripQuotation if TRUE then strip the quotation marks surrounding
@param[in, out] Argc pointer to number of strings in Argv array the parameters.
@param[in, out] Argv pointer to array of strings; one for each parameter
@param[in, out] Argc pointer to number of strings in Argv array
@return EFI_SUCCESS the operation was sucessful @return EFI_SUCCESS the operation was sucessful
@return EFI_OUT_OF_RESOURCES a memory allocation failed. @return EFI_OUT_OF_RESOURCES a memory allocation failed.
@@ -173,8 +185,9 @@ EFI_STATUS
EFIAPI EFIAPI
ParseCommandLineToArgs( ParseCommandLineToArgs(
IN CONST CHAR16 *CommandLine, IN CONST CHAR16 *CommandLine,
IN OUT CHAR16 ***Argv, IN BOOLEAN StripQuotation,
IN OUT UINTN *Argc IN OUT CHAR16 ***Argv,
IN OUT UINTN *Argc
); );
/** /**
@@ -187,10 +200,12 @@ ParseCommandLineToArgs(
Temp Parameter must be large enough to hold the parameter before calling this Temp Parameter must be large enough to hold the parameter before calling this
function. function.
@param[in, out] Walker pointer to string of command line. Adjusted to @param[in, out] Walker pointer to string of command line. Adjusted to
reminaing command line on return reminaing command line on return
@param[in, out] TempParameter pointer to string of command line item extracted. @param[in, out] TempParameter pointer to string of command line item extracted.
@param[in] Length Length of (*TempParameter) in bytes @param[in] Length Length of (*TempParameter) in bytes
@param[in] StripQuotation if TRUE then strip the quotation marks surrounding
the parameters.
@return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string. @return EFI_INALID_PARAMETER A required parameter was NULL or pointed to a NULL or empty string.
@return EFI_NOT_FOUND A closing " could not be found on the specified string @return EFI_NOT_FOUND A closing " could not be found on the specified string
@@ -200,7 +215,8 @@ EFIAPI
GetNextParameter( GetNextParameter(
IN OUT CHAR16 **Walker, IN OUT CHAR16 **Walker,
IN OUT CHAR16 **TempParameter, IN OUT CHAR16 **TempParameter,
IN CONST UINTN Length IN CONST UINTN Length,
IN BOOLEAN StripQuotation
); );
#endif //_SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_ #endif //_SHELL_PARAMETERS_PROTOCOL_PROVIDER_HEADER_

View File

@@ -1501,7 +1501,7 @@ InternalShellExecuteDevicePath(
ShellParamsProtocol.StdIn = ShellInfoObject.NewShellParametersProtocol->StdIn; ShellParamsProtocol.StdIn = ShellInfoObject.NewShellParametersProtocol->StdIn;
ShellParamsProtocol.StdOut = ShellInfoObject.NewShellParametersProtocol->StdOut; ShellParamsProtocol.StdOut = ShellInfoObject.NewShellParametersProtocol->StdOut;
ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr; ShellParamsProtocol.StdErr = ShellInfoObject.NewShellParametersProtocol->StdErr;
Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, NULL, NULL); Status = UpdateArgcArgv(&ShellParamsProtocol, NewCmdLine, Efi_Application, NULL, NULL);
ASSERT_EFI_ERROR(Status); ASSERT_EFI_ERROR(Status);
// //
// Replace Argv[0] with the full path of the binary we're executing: // Replace Argv[0] with the full path of the binary we're executing: