public inbox for devel@edk2.groups.io
 help / color / mirror / Atom feed
From: "Gao, Zhichao" <zhichao.gao@intel.com>
To: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>,
	"Ni, Ray" <ray.ni@intel.com>,
	"devel@edk2.groups.io" <devel@edk2.groups.io>
Subject: Re: [edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested variables substitution from cmd line
Date: Mon, 13 Jan 2020 03:06:33 +0000	[thread overview]
Message-ID: <b40b9d6021d145b3932cbbfdcd7c7c7d@intel.com> (raw)
In-Reply-To: <2d6b2d376dfef281c2ec66b35d0735f8@mail.gmail.com>

Hi Vladimir,

> -----Original Message-----
> From: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> Sent: Saturday, January 11, 2020 12:33 AM
> To: Ni, Ray <ray.ni@intel.com>; devel@edk2.groups.io; Gao, Zhichao
> <zhichao.gao@intel.com>
> Subject: RE: [edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested
> variables substitution from cmd line
> 
> Hi Ray,
> 
> As an example, let's say that you have multiple variants of serverips - each
> interface has its own, and each interface has a property as say interface no
> (eth_no).
> It is logical to address a serverip for an interface as %serverip%eth_no%%, and
> in the end get the contents of variable serverip0 (say for eth_no containing value
> 0).
> In fact, Linux bash allows doing that easily.
> We are doing most of our upgrade/configuration stuff via Shell scripts which is
> very flexible, easy and efficient.
> To support boot redundancy, we support multiple slots for kernel/dtbs, etc,
> which are addressed as %update_type_%upd_type%% where upd_type can be
> dtb, kernel, etc.
> The spec says " Environment variables can be used on the command-line by
> using %variable-name% where variable-name is the environment variable's
> name. Variable substitution is not recursive."
> I treat it as an extension to %var% case; %var case is not touched. What do you
> think?

"Variable substitution is not recursive" means the enviornment variable doesn't support nested. If you want to push the change, you should change the spec first. And there is one variable substitution flow figure, it should be update as well.

Thanks,
Zhichao

> 
> Regarding unit tests.
> I verified variables substitutions using %var% and %var%var1%%
> and %%var1%var% to make sure there would be no regression.
> Our scripts use variables extensively, and no issues were encountered.
> Please let me know if you need the scripts we are using, and I will send them to
> you.
> 
> Which unit tests are available?
> 
> Thank you,
> Vladimir
> 
> -----Original Message-----
> From: Ni, Ray <ray.ni@intel.com>
> Sent: Thursday, January 9, 2020 10:03 PM
> To: devel@edk2.groups.io; vladimir.olovyannikov@broadcom.com; Gao,
> Zhichao <zhichao.gao@intel.com>
> Subject: RE: [edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested
> variables substitution from cmd line
> 
> Vladimir,
> Is this enhancement an extension to Shell spec or violation of Shell spec?
> If it's an extension, I am happy to have such feature implemented.
> Otherwise, we may need to discuss in uefi.org.
> 
> Can you list the unit tests you have done?
> 
> Thanks,
> Ray
> 
> > -----Original Message-----
> > From: devel@edk2.groups.io <devel@edk2.groups.io> On Behalf Of
> > Vladimir Olovyannikov via Groups.Io
> > Sent: Friday, January 10, 2020 6:07 AM
> > To: devel@edk2.groups.io; Ni, Ray <ray.ni@intel.com>; Gao, Zhichao
> > <zhichao.gao@intel.com>
> > Cc: Vladimir Olovyannikov <vladimir.olovyannikov@broadcom.com>
> > Subject: [edk2-devel] [PATCH 1/1] ShellPkg/Application: Support nested
> > variables substitution from cmd line
> >
> > The current implementation of ShellSubstituteVariables() does not
> > allow substitution of variables names containing another variable
> > name(s) between %...%
> >
> > Example: %text%var_name%% where var_name variable contains 0.
> > Here the variable value which should be returned on substitution would
> > be contents of text0 variable.
> > The current implementation would return nothing as %text0% would be
> > eliminated by StripUnreplacedEnvironmentVariables().
> >
> > Modify the code so that StripUnreplacedEnvironmentVariables checks if
> > variable between %...% really exists. If it does not, delete %...%.
> > If it exists, preserve it and tell the caller that another run of
> > ShellConvertVariables() is needed. This way, any nested variable
> > between %...% can be easily retrieved.
> > REF:https://bugzilla.tianocore.org/show_bug.cgi?id=2452
> >
> > Signed-off-by: Vladimir Olovyannikov
> > <vladimir.olovyannikov@broadcom.com>
> > Contributed-under: TianoCore Contribution Agreement 1.1
> > ---
> >  ShellPkg/Application/Shell/Shell.c | 71
> > ++++++++++++++++++++++++------
> >  1 file changed, 57 insertions(+), 14 deletions(-)
> >
> > diff --git a/ShellPkg/Application/Shell/Shell.c
> > b/ShellPkg/Application/Shell/Shell.c
> > index d16adae0ea30..3756a71794d1 100644
> > --- a/ShellPkg/Application/Shell/Shell.c
> > +++ b/ShellPkg/Application/Shell/Shell.c
> > @@ -1510,12 +1510,16 @@ ShellConvertAlias(
> >
> >  /**
> >    This function will eliminate unreplaced (and therefore non-found)
> environment variables.
> > -
> > +  If a variable exists between %...%, it will be preserved, and
> > + VarExists  would be TRUE.
> >    @param[in,out] CmdLine   The command line to update.
> > +  @param[out] VarExists    A pointer to the BOOLEAN which is set if
> > +                           a Shell variable between %...% exists.
> >  **/
> >  EFI_STATUS
> >  StripUnreplacedEnvironmentVariables(
> > -  IN OUT CHAR16 *CmdLine
> > +  IN OUT CHAR16 *CmdLine,
> > +  OUT BOOLEAN   *VarExists
> >    )
> >  {
> >    CHAR16 *FirstPercent;
> > @@ -1558,12 +1562,38 @@ StripUnreplacedEnvironmentVariables(
> >      if (FirstQuote == NULL || SecondPercent < FirstQuote) {
> >        if (IsValidEnvironmentVariableName(FirstPercent,
> > SecondPercent))
> {
> >          //
> > -        // We need to remove from FirstPercent to SecondPercent
> > -        //
> > -        CopyMem(FirstPercent, SecondPercent + 1, StrSize(SecondPercent
> + 1));
> > -        //
> > -        // don't need to update the locator.  both % characters are
> gone.
> > +        // If this Shell variable exists, consider that another run
> > + is
> needed.
> > +        // For example, consider a variable %var%var2%% when var2 is 0.
> > +        // After the first run, it becomes %var0%, and after the
> > + second
> run
> > +        // it contains the value of var0 variable.
> > +        // Eliminate variable if it does not exist.
> >          //
> > +        CHAR16 *VarName;
> > +
> > +        // Consider NULL terminator as well
> > +        VarName = (CHAR16 *)AllocateZeroPool((SecondPercent -
> FirstPercent) *
> > +                                             sizeof(CHAR16));
> > +        if (VarName) {
> > +          CopyMem(VarName, FirstPercent + 1,
> > +                  (SecondPercent - FirstPercent - 1) * sizeof(CHAR16));
> > +        }
> > +
> > +        if (!VarName || !ShellGetEnvironmentVariable(VarName)) {
> > +          //
> > +          // We need to remove from FirstPercent to SecondPercent.
> > +          //
> > +          CopyMem(FirstPercent, SecondPercent + 1,
> StrSize(SecondPercent + 1));
> > +          //
> > +          // don't need to update the locator.  both % characters are
> gone.
> > +          //
> > +        } else {
> > +          *VarExists = TRUE;
> > +          //
> > +          // In this case, locator needs to be updated as %
> > + characters
> present.
> > +          //
> > +          CurrentLocator = SecondPercent + 1;
> > +        }
> > +        SHELL_FREE_NON_NULL(VarName);
> >        } else {
> >          CurrentLocator = SecondPercent + 1;
> >        }
> > @@ -1581,13 +1611,18 @@ StripUnreplacedEnvironmentVariables(
> >    If the return value is not NULL the memory must be caller freed.
> >
> >    @param[in] OriginalCommandLine    The original command line
> > +  @param[out] NeedExtraRun          Indication that the caller needs to
> repeat
> > +                                    this call to convert variables as
> there are
> > +                                    existing variable(s) between %..%
> > +                                    present after the call.
> >
> >    @retval NULL                      An error occurred.
> >    @return                           The new command line with no
> environment variables present.
> >  **/
> >  CHAR16*
> >  ShellConvertVariables (
> > -  IN CONST CHAR16 *OriginalCommandLine
> > +  IN CONST CHAR16 *OriginalCommandLine,
> > +  OUT BOOLEAN     *NeedExtraRun
> >    )
> >  {
> >    CONST CHAR16        *MasterEnvList;
> > @@ -1601,11 +1636,13 @@ ShellConvertVariables (
> >    ALIAS_LIST          *AliasListNode;
> >
> >    ASSERT(OriginalCommandLine != NULL);
> > +  ASSERT(NeedExtraRun != NULL);
> >
> >    ItemSize          = 0;
> >    NewSize           = StrSize(OriginalCommandLine);
> >    CurrentScriptFile = ShellCommandGetCurrentScriptFile();
> >    Temp              = NULL;
> > +  *NeedExtraRun     = FALSE;
> >
> >    ///@todo update this to handle the %0 - %9 for scripting only
> > (borrow
> from line 1256 area) ? ? ?
> >
> > @@ -1698,7 +1735,7 @@ ShellConvertVariables (
> >    //
> >    // Remove non-existent environment variables
> >    //
> > -  StripUnreplacedEnvironmentVariables(NewCommandLine1);
> > +  StripUnreplacedEnvironmentVariables(NewCommandLine1, NeedExtraRun);
> >
> >    //
> >    // Now cleanup any straggler intentionally ignored "%" characters
> > @@ -1845,12 +1882,18 @@ ShellSubstituteVariables(
> >    )
> >  {
> >    CHAR16      *NewCmdLine;
> > -  NewCmdLine = ShellConvertVariables(*CmdLine);
> > -  SHELL_FREE_NON_NULL(*CmdLine);
> > -  if (NewCmdLine == NULL) {
> > -    return (EFI_OUT_OF_RESOURCES);
> > +  BOOLEAN     NeedExtraRun;
> > +
> > +  NeedExtraRun = TRUE;
> > +  while (NeedExtraRun) {
> > +    NewCmdLine = ShellConvertVariables(*CmdLine, &NeedExtraRun);
> > +    SHELL_FREE_NON_NULL(*CmdLine);
> > +    if (NewCmdLine == NULL) {
> > +      return (EFI_OUT_OF_RESOURCES);
> > +    }
> > +    *CmdLine = NewCmdLine;
> >    }
> > -  *CmdLine = NewCmdLine;
> > +
> >    return (EFI_SUCCESS);
> >  }
> >
> > --
> > 2.17.1
> >
> >
> > 

  reply	other threads:[~2020-01-13  3:06 UTC|newest]

Thread overview: 6+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-01-09 22:06 [PATCH 1/1] ShellPkg/Application: Support nested variables substitution from cmd line Vladimir Olovyannikov
2020-01-10  6:02 ` [edk2-devel] " Ni, Ray
2020-01-10 16:32   ` Vladimir Olovyannikov
2020-01-13  3:06     ` Gao, Zhichao [this message]
2020-01-14 17:33       ` Vladimir Olovyannikov
2020-01-13  0:49 ` Liming Gao

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-list from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=b40b9d6021d145b3932cbbfdcd7c7c7d@intel.com \
    --to=devel@edk2.groups.io \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox