Please explain what problem you try to solve. Bash doesn't do anything of
the kind. Why should we? Looks like a solution without a problem

Regards
Vladimir 'phcoder' Serbinenko

Le lun. 26 mai 2025, 20:34, Jiří 'bindiff' Wolker via Grub-devel <
grub-devel@gnu.org> a écrit :

> This adds new options ‘-g’ and ‘-u’ to the ‘export’ command.
>
> By default, the ‘export’ command exports the variables to
> lower environment context nesting levels, but not to the upper levels.
> This behavior is left unchanged from the original version.
>
> Using of the ‘-g’ option allows exporting of the given variable(s)
> even to the upper levels.
>
> The ‘-u’ option complements the default behavior of ‘export’ command:
> It causes the variable to become local, i.e., un-exported.
> ---
>   grub-core/kern/env.c       | 11 ++++--
>   grub-core/normal/context.c | 70 ++++++++++++++++++++++++++++++--------
>   include/grub/env.h         | 11 +++++-
>   3 files changed, 75 insertions(+), 17 deletions(-)
>
> diff --git a/grub-core/kern/env.c b/grub-core/kern/env.c
> index 764068896..6b60c71de 100644
> --- a/grub-core/kern/env.c
> +++ b/grub-core/kern/env.c
> @@ -231,7 +231,8 @@ grub_register_variable_hook (const char *name,
>   }
>    grub_err_t
> -grub_env_export (const char *name)
> +grub_env_set_export_mode (const char *name,
> +                         enum grub_env_var_export mode)
>   {
>     struct grub_env_var *var;
>   @@ -245,7 +246,13 @@ grub_env_export (const char *name)
>         return err;
>         var = grub_env_find (name);
>       }
> -  var->global = 1;
> +  var->global = mode;
>      return GRUB_ERR_NONE;
>   }
> +
> +grub_err_t
> +grub_env_export (const char *name)
> +{
> +  return grub_env_set_export_mode (name, grub_env_var_exported);
> +}
> diff --git a/grub-core/normal/context.c b/grub-core/normal/context.c
> index ba185e915..8abe5065c 100644
> --- a/grub-core/normal/context.c
> +++ b/grub-core/normal/context.c
> @@ -22,6 +22,7 @@
>   #include <grub/misc.h>
>   #include <grub/mm.h>
>   #include <grub/command.h>
> +#include <grub/extcmd.h>
>   #include <grub/normal.h>
>   #include <grub/i18n.h>
>   @@ -88,7 +89,7 @@ grub_env_new_context (int export_all)
>                 grub_env_context_close ();
>                 return grub_errno;
>               }
> -           grub_env_export (var->name);
> +           grub_env_set_export_mode (var->name, var->global);
>             grub_register_variable_hook (var->name, var->read_hook,
> var->write_hook);
>           }
>       }
> @@ -115,31 +116,52 @@ grub_err_t
>   grub_env_context_close (void)
>   {
>     struct grub_env_context *context;
> +  struct grub_env_context *original_context;
>     int i;
>     struct menu_pointer *menu;
> +  grub_err_t last_err = GRUB_ERR_NONE;
>      if (! grub_current_context->prev)
>       return grub_error (GRUB_ERR_BAD_ARGUMENT,
>                        "cannot close the initial context");
>   -  /* Free the variables associated with this context.  */
> +  /* Restore the previous context.  */
> +  original_context = grub_current_context;
> +  context = grub_current_context->prev;
> +  grub_current_context = context;
> +
> +  /* Re-export global variables to the upper context. */
> +
>     for (i = 0; i < HASHSZ; i++)
>       {
>         struct grub_env_var *p, *q;
>   -      for (p = grub_current_context->vars[i]; p; p = q)
> +      for (p = original_context->vars[i]; p; p = q)
>         {
>           q = p->next;
> +
> +         /* Copy global variables to the upper context. */
> +         if (p->global == grub_env_var_global) {
> +           if (grub_env_set (p->name, p->value) != GRUB_ERR_NONE)
> +             {
> +               last_err = grub_errno;
> +             }
> +           else
> +             {
> +               grub_env_set_export_mode (p->name, p->global);
> +               grub_register_variable_hook (p->name, p->read_hook,
> p->write_hook);
> +             }
> +         }
> +
> +         /* Free the variables associated with this context.  */
>             grub_free (p->name);
>           grub_free (p->value);
>           grub_free (p);
>         }
>       }
>   -  /* Restore the previous context.  */
> -  context = grub_current_context->prev;
> -  grub_free (grub_current_context);
> -  grub_current_context = context;
> +  /* Free the previous context. */
> +  grub_free (original_context);
>      menu = current_menu->prev;
>     if (current_menu->menu)
> @@ -181,34 +203,54 @@ grub_env_extractor_close (int source)
>     return err;
>   }
>   -static grub_command_t export_cmd;
> +static grub_extcmd_t export_cmd;
>    static grub_err_t
> -grub_cmd_export (struct grub_command *cmd __attribute__ ((unused)),
> +grub_cmd_export (grub_extcmd_context_t ctxt,
>                  int argc, char **args)
>   {
> +  struct grub_arg_list *state = ctxt->state;
>     int i;
>   +  enum grub_env_var_export mode = grub_env_var_exported;
> +  if (state[0].set)
> +    mode = grub_env_var_local;
> +  if (state[1].set)
> +    mode = grub_env_var_global;
> +  if (state[0].set && state[1].set)
> +    return grub_error (GRUB_ERR_BAD_ARGUMENT,
> +                      N_("canot use both -u and -a at once"));
> +
>     if (argc < 1)
>       return grub_error (GRUB_ERR_BAD_ARGUMENT,
>                        N_("one argument expected"));
>      for (i = 0; i < argc; i++)
> -    grub_env_export (args[i]);
> +    grub_env_set_export_mode (args[i], mode);
>      return 0;
>   }
>   +static const struct grub_arg_option export_options[] =
> +  {
> +    {"unexport", 'u', 0, N_("Undo exporting the variable."), 0, 0},
> +    {"global", 'g', 0, N_("Export also to parent contexts."), 0, 0},
> +    {0, 0, 0, 0, 0, 0}
> +  };
> +
>   void
>   grub_context_init (void)
>   {
> -  export_cmd = grub_register_command ("export", grub_cmd_export,
> -                                     N_("ENVVAR [ENVVAR] ..."),
> -                                     N_("Export variables."));
> +  export_cmd = grub_register_extcmd ("export", grub_cmd_export,
> +                                    GRUB_COMMAND_ACCEPT_DASH
> +                                    | GRUB_COMMAND_OPTIONS_AT_START,
> +                                    N_("[-u|-g] ENVVAR [ENVVAR] ..."),
> +                                    N_("Export variables."),
> +                                    export_options);
>   }
>    void
>   grub_context_fini (void)
>   {
> -  grub_unregister_command (export_cmd);
> +  grub_unregister_extcmd (export_cmd);
>   }
> diff --git a/include/grub/env.h b/include/grub/env.h
> index 6b9379a30..4634c09d3 100644
> --- a/include/grub/env.h
> +++ b/include/grub/env.h
> @@ -31,6 +31,13 @@ typedef const char *(*grub_env_read_hook_t) (struct
> grub_env_var *var,
>   typedef char *(*grub_env_write_hook_t) (struct grub_env_var *var,
>                                         const char *val);
>   +enum grub_env_var_export
> +{
> +  grub_env_var_local    = 0,
> +  grub_env_var_exported = 1,
> +  grub_env_var_global   = 2,
> +};
> +
>   struct grub_env_var
>   {
>     char *name;
> @@ -40,7 +47,7 @@ struct grub_env_var
>     struct grub_env_var *next;
>     struct grub_env_var **prevp;
>     struct grub_env_var *sorted_next;
> -  int global;
> +  enum grub_env_var_export global;
>   };
>    grub_err_t EXPORT_FUNC(grub_env_set) (const char *name, const char
> *val);
> @@ -58,6 +65,8 @@ grub_err_t EXPORT_FUNC(grub_register_variable_hook)
> (const char *name,
>   grub_err_t grub_env_context_open (void);
>   grub_err_t grub_env_context_close (void);
>   grub_err_t EXPORT_FUNC(grub_env_export) (const char *name);
> +grub_err_t EXPORT_FUNC(grub_env_set_export_mode) (const char *name,
> +                                                 enum grub_env_var_export
> mode);
>    void grub_env_unset_menu (void);
>   grub_menu_t grub_env_get_menu (void);
> --
> 2.45.3
>
>
> _______________________________________________
> Grub-devel mailing list
> Grub-devel@gnu.org
> https://lists.gnu.org/mailman/listinfo/grub-devel
>
_______________________________________________
Grub-devel mailing list
Grub-devel@gnu.org
https://lists.gnu.org/mailman/listinfo/grub-devel

Reply via email to