Add environment-variable substitution to config options
authorAaron Carroll <aaronc@gelato.unsw.edu.au>
Tue, 7 Oct 2008 09:25:20 +0000 (11:25 +0200)
committerJens Axboe <jens.axboe@oracle.com>
Tue, 7 Oct 2008 09:25:20 +0000 (11:25 +0200)
Strings of the form ${VARNAME} in config option strings are substituted with
the value of the environment variable VARNAME.  Only the right hand side of
an option assignment undergoes substitution.  If VARNAME is empty or
undefined, the empty string is substituted.

Signed-off-by: Aaron Carroll <aaronc@gelato.unsw.edu.au>
Signed-off-by: Jens Axboe <jens.axboe@oracle.com>
parse.c
parse.h

diff --git a/parse.c b/parse.c
index b9466901eebeddbe7c7b2b634bf5d504a3abfff8..456e3bafb54f91c19c060bf42c1e152e21448467 100644 (file)
--- a/parse.c
+++ b/parse.c
@@ -8,6 +8,7 @@
 #include <string.h>
 #include <errno.h>
 #include <limits.h>
+#include <stdlib.h>
 
 #include "parse.h"
 #include "debug.h"
@@ -529,12 +530,61 @@ int parse_cmd_option(const char *opt, const char *val,
        return 1;
 }
 
+/*
+ * Return a copy of the input string with substrings of the form ${VARNAME}
+ * substituted with the value of the environment variable VARNAME.  The
+ * substitution always occurs, even if VARNAME is empty or the corresponding
+ * environment variable undefined.
+ */
+static char *option_dup_subs(const char *opt)
+{
+       char out[OPT_LEN_MAX+1];
+       char in[OPT_LEN_MAX+1];
+       char *outptr = out;
+       char *inptr = in;
+       char *ch1, *ch2, *env;
+       ssize_t nchr = OPT_LEN_MAX;
+       size_t envlen;
+
+       in[OPT_LEN_MAX] = '\0';
+       strncpy(in, opt, OPT_LEN_MAX);
+
+       while (*inptr && nchr > 0) {
+               if (inptr[0] == '$' && inptr[1] == '{') {
+                       ch2 = strchr(inptr, '}');
+                       if (ch2 && inptr+1 < ch2) {
+                               ch1 = inptr+2;
+                               inptr = ch2+1;
+                               *ch2 = '\0';
+
+                               env = getenv(ch1);
+                               if (env) {
+                                       envlen = strlen(env);
+                                       if (envlen <= nchr) {
+                                               memcpy(outptr, env, envlen);
+                                               outptr += envlen;
+                                               nchr -= envlen;
+                                       }
+                               }
+
+                               continue;
+                       }
+               }
+
+               *outptr++ = *inptr++;
+               --nchr;
+       }
+
+       *outptr = '\0';
+       return strdup(out);
+}
+
 int parse_option(const char *opt, struct fio_option *options, void *data)
 {
        struct fio_option *o;
        char *post, *tmp;
 
-       tmp = strdup(opt);
+       tmp = option_dup_subs(opt);
 
        o = get_option(tmp, options, &post);
        if (!o) {
diff --git a/parse.h b/parse.h
index 4f3f94d0f7f8f97fef15ead4adc12e7af199db3d..45462596ca4246dd6a7b4eac7600a2936c241b81 100644 (file)
--- a/parse.h
+++ b/parse.h
@@ -26,6 +26,7 @@ struct value_pair {
        const char *help;               /* help text for sub option */
 };
 
+#define OPT_LEN_MAX    1024
 #define PARSE_MAX_VP   16
 
 /*