used in cases where no proper argument vector is passed to env
an example are shebangs:
"#!/usr/bin/env -S executable -o"
this will pass 3 arguments to env: the env executable,
"-S executable -o" as one string and filename.
"-S executable -o" willobe split and "executable -o" will be separate
arguments in the argument vector
---
 coreutils/env.c | 39 ++++++++++++++++++++++++++++++++++++++-
 1 file changed, 38 insertions(+), 1 deletion(-)

diff --git a/coreutils/env.c b/coreutils/env.c
index 9ca1fad2d..22cc916be 100644
--- a/coreutils/env.c
+++ b/coreutils/env.c
@@ -48,6 +48,7 @@
 //usage:     "\n       -, -i   Start with empty environment"
 //usage:     "\n       -0      NUL terminated output"
 //usage:     "\n       -u NAME Remove variable from environment"
+//usage:     "\n       -S ARGS split into separate arguments, only useful in 
shebang or similar"
 
 #include "libbb.h"
 #include <getopt.h>
@@ -56,10 +57,11 @@ static struct option const long_options[] = {
        {"ignore-environment", no_argument,       0,  'i' },
        {"null",               no_argument,       0,  '0' },
        {"unset",              required_argument, 0,  'u' },
+       {"split",              required_argument, 0,  'S' },
        {0,                    0,                 0,  0 }
 };
 
-static char const short_options[] = "+iu:0";
+static char const short_options[] = "+iS:u:0";
 
 static char const **unset_vars;
 static int num_unset_vars;
@@ -70,6 +72,38 @@ static void add_unset_var (char const *var)
        unset_vars[num_unset_vars++] = var;
 }
 
+// inspired by GNU core utilities env.c
+static void split_string (char const *str, int *optind, int *argc, char 
***argv)
+{
+       // remember the amount of extra arguments after the string to split
+       int extra_argc = *argc - *optind;
+       // 1 is reserved for the executable name of env
+       int new_argc = extra_argc + 1;
+       int new_ind = new_argc - extra_argc;
+       char **new_argv = NULL;
+       char *arg, *tokstate;
+
+       // keep it simple, assume arguments are split by spaces
+       arg = strtok_r (str, " ", &tokstate);
+       while (arg != NULL) {
+               // increase size of new_argv
+               new_argv = xrealloc(new_argv, ++new_argc * sizeof(char *));
+               // copy the current argument to new_argv
+               new_argv[new_ind++] = xstrdup(arg);
+               arg = strtok_r (NULL, " ", &tokstate);
+       }
+       // keep executable name
+       *new_argv = (*argv)[0];
+
+       // copy remaining arguments
+       memcpy(new_argv + new_ind, *argv + *optind, (extra_argc + 1) * 
sizeof(char *));
+
+       // write back values to argc and argv
+       *argc = new_argc;
+       *argv = new_argv;
+       *optind = 0;
+}
+
 int env_main(int argc, char **argv) MAIN_EXTERNALLY_VISIBLE;
 int env_main(int argc, char **argv)
 {
@@ -90,6 +124,9 @@ int env_main(int argc, char **argv)
                case '0':
                        null_terminate_output = true;
                        break;
+               case 'S':
+                       split_string(optarg, &optind, &argc, &argv);
+                       break;
                default:
                        exit(EXIT_FAILURE);
                }
-- 
2.30.2

_______________________________________________
busybox mailing list
[email protected]
https://lists.busybox.net/mailman/listinfo/busybox

Reply via email to