X-Git-Url: https://git.kernel.dk/?p=fio.git;a=blobdiff_plain;f=parse.c;h=f838a1f625e111f6aa55a5bdf221a4f6352319a4;hp=b9466901eebeddbe7c7b2b634bf5d504a3abfff8;hb=814452bd47e0f2bb4825b8042b664f32de0aff8d;hpb=3b8b7135602a4d3a7132fee10da9c1203ab643ad diff --git a/parse.c b/parse.c index b9466901..f838a1f6 100644 --- a/parse.c +++ b/parse.c @@ -8,6 +8,7 @@ #include #include #include +#include #include "parse.h" #include "debug.h" @@ -235,7 +236,7 @@ static int __handle_option(struct fio_option *o, const char *ptr, void *data, dprint(FD_PARSE, "__handle_option=%s, type=%d, ptr=%s\n", o->name, o->type, ptr); - if (!ptr && o->type != FIO_OPT_STR_SET) { + if (!ptr && o->type != FIO_OPT_STR_SET && o->type != FIO_OPT_STR) { fprintf(stderr, "Option %s requires an argument\n", o->name); return 1; } @@ -473,6 +474,7 @@ static struct fio_option *get_option(const char *opt, *ret = '\0'; ret = (char *) opt; (*post)++; + strip_blank_end(ret); o = find_option(options, ret); } else { o = find_option(options, opt); @@ -486,22 +488,23 @@ static int opt_cmp(const void *p1, const void *p2) { struct fio_option *o1, *o2; char *s1, *s2, *foo; - int ret; + int prio1, prio2; s1 = strdup(*((char **) p1)); s2 = strdup(*((char **) p2)); o1 = get_option(s1, fio_options, &foo); o2 = get_option(s2, fio_options, &foo); - - if ((!o1 && o2) || (o1 && !o2)) - ret = 0; - else - ret = o2->prio - o1->prio; + + prio1 = prio2 = 0; + if (o1) + prio1 = o1->prio; + if (o2) + prio2 = o2->prio; free(s1); free(s2); - return ret; + return prio2 - prio1; } void sort_options(char **opts, struct fio_option *options, int num_opts) @@ -518,7 +521,7 @@ int parse_cmd_option(const char *opt, const char *val, o = find_option(options, opt); if (!o) { - fprintf(stderr, "Bad option %s\n", opt); + fprintf(stderr, "Bad option <%s>\n", opt); return 1; } @@ -529,16 +532,65 @@ 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) { - fprintf(stderr, "Bad option %s\n", tmp); + fprintf(stderr, "Bad option <%s>\n", tmp); free(tmp); return 1; }