diff mbox series

[ovs-dev,v1] command-line.c: Support parsing ctl options via env variable

Message ID 20191016015234.10388-1-amginwal@gmail.com
State Superseded
Headers show
Series [ovs-dev,v1] command-line.c: Support parsing ctl options via env variable | expand

Commit Message

aginwala aginwala Oct. 16, 2019, 1:52 a.m. UTC
From: Aliasgar Ginwala <aginwala@ebay.com>

Signed-off-by: Aliasgar Ginwala <aginwala@ebay.com>
---
 lib/command-line.c | 50 ++++++++++++++++++++++++++++++++++++++++++++++
 lib/command-line.h |  3 +++
 2 files changed, 53 insertions(+)

Comments

Ben Pfaff Oct. 25, 2019, 1:14 a.m. UTC | #1
On Tue, Oct 15, 2019 at 06:52:34PM -0700, amginwal@gmail.com wrote:
> From: Aliasgar Ginwala <aginwala@ebay.com>
> 
> Signed-off-by: Aliasgar Ginwala <aginwala@ebay.com>

I'm pretty sure this code doesn't work properly because it tries to
parse the same string twice with strtok_r(), which is going to truncate
it after the first option.  Did you try it with more than one
space-separated option in the environment variable?

lib/svec.[ch] would make it easier to write this.
Li,Rongqing via dev Oct. 25, 2019, 5:44 a.m. UTC | #2
Thanks Ben for the review:

Yes you are right,  current patch is buggy as using same string twice with strtok_r() was always using first option instead of n options. Thanks for pointing out about svec.[ch]. I sent v2 https://patchwork.ozlabs.org/patch/1183774/  to address the same. PTAL.


Ali
diff mbox series

Patch

diff --git a/lib/command-line.c b/lib/command-line.c
index 9e000bd28..64a84efa8 100644
--- a/lib/command-line.c
+++ b/lib/command-line.c
@@ -77,6 +77,56 @@  find_option_by_value(const struct option *options, int value)
     return NULL;
 }
 
+/* Parses options set using environment variable.  The caller specifies the
+ * supported options in environment variable.  On success, adds the parsed
+ * env variables in 'argv', the number of options in 'argc', and returns argv.
+ *  */
+char **
+ovs_cmdl_env_parse_all(int *argcp, char *argv_[],
+                       char *env_options)
+{
+    char *str1, *token, *saveptr1;
+    char **argv = NULL;
+    int i, j, total_args, argc;
+    int env_argc = 0;
+
+    argc = *argcp;
+    if (!env_options) {
+        /* Copy args for parsing as is from argv_ */
+        argv = xcalloc(argc + 1, sizeof( *argv_) + 1 );
+        for (i = 0; i < argc; i++) {
+            argv[i] = xstrdup(argv_[i]);
+        }
+        return argv;
+    }
+    /* Count number of options passed via environment variable */
+    for (j = 1, str1 = env_options; ; j++, str1 = NULL) {
+            token = strtok_r(str1, " ", &saveptr1);
+            if (token == NULL) {
+                break;
+            }
+            env_argc++;
+    }
+    total_args = argc + env_argc + 1;
+    argv = xcalloc(total_args, sizeof( *argv_) + env_argc + 1);
+
+    /* Construct argv with command line + environment options. */
+    for (i = 0, j = 0; i < argc; i++, j++) {
+        if (j == 1) {
+            for (j = 1, str1 = env_options; ; j++, str1 = NULL) {
+                token = strtok_r(str1, " ", &saveptr1);
+                if (token == NULL) {
+                    break;
+                }
+                argv[j] = token;
+            }
+        }
+        argv[j] = xstrdup(argv_[i]);
+    }
+    *argcp = j;
+    return argv;
+}
+
 /* Parses the command-line options in 'argc' and 'argv'.  The caller specifies
  * the supported options in 'options'.  On success, stores the parsed options
  * in '*pop', the number of options in '*n_pop', and returns NULL.  On failure,
diff --git a/lib/command-line.h b/lib/command-line.h
index 9d62dc250..4b8f76da7 100644
--- a/lib/command-line.h
+++ b/lib/command-line.h
@@ -54,6 +54,9 @@  char *ovs_cmdl_parse_all(int argc, char *argv[], const struct option *,
                          struct ovs_cmdl_parsed_option **, size_t *)
     OVS_WARN_UNUSED_RESULT;
 
+char **ovs_cmdl_env_parse_all(int *argcp, char *argv_[],
+                              char *env_options);
+
 void ovs_cmdl_print_options(const struct option *options);
 void ovs_cmdl_print_commands(const struct ovs_cmdl_command *commands);