diff --git a/usr.bin/rpcgen/rpc_main.c b/usr.bin/rpcgen/rpc_main.c --- a/usr.bin/rpcgen/rpc_main.c +++ b/usr.bin/rpcgen/rpc_main.c @@ -45,6 +45,7 @@ #include #include +#include #include #include #include @@ -270,20 +271,114 @@ static void prepend_cpp(void) { - int idx = 0; - const char *var; - char *dupvar, *s, *t; + int idx = 0, quoted; + const char *var, *s; + char *dupvar, *t, *word; if (CPP != NULL) insarg(idx++, CPP); else if ((var = getenv("RPCGEN_CPP")) == NULL) insarg(idx++, "/usr/bin/cpp"); else { - /* Parse command line in a rudimentary way */ - dupvar = xstrdup(var); - for (s = dupvar; (t = strsep(&s, " \t")) != NULL; ) { - if (t[0]) - insarg(idx++, t); + /* + * Parse command line like a shell (but only handle whitespace, + * quotes and backslash). + */ + dupvar = malloc(strlen(var) + 1); + quoted = 0; + word = NULL; + for (s = var, t = dupvar; *s; ++s) { + switch (quoted) { + /* Unquoted */ + case 0: + switch (*s) { + case ' ': + case '\t': + case '\n': + if (word != NULL) { + *t++ = '\0'; + insarg(idx++, word); + word = NULL; + } + break; + case '\'': + if (word == NULL) + word = t; + quoted = 1; + break; + case '"': + if (word == NULL) + word = t; + quoted = 2; + break; + case '\\': + switch (*(s + 1)) { + case '\0': + break; + case '\n': + ++s; + continue; + default: + ++s; + break; + } + /* FALLTHROUGH */ + default: + if (word == NULL) + word = t; + *t++ = *s; + break; + } + break; + + /* Single-quoted */ + case 1: + switch (*s) { + case '\'': + quoted = 0; + break; + default: + *t++ = *s; + break; + } + break; + + /* Double-quoted */ + case 2: + switch (*s) { + case '"': + quoted = 0; + break; + case '\\': + switch (*(s + 1)) { + case '\0': + break; + case '$': + case '`': + case '"': + case '\\': + ++s; + break; + case '\n': + ++s; + continue; + default: + break; + } + /* FALLTHROUGH */ + default: + *t++ = *s; + break; + } + break; + } + } + if (quoted) + errx(1, "RPCGEN_CPP: unterminated %c", + quoted == 1 ? '\'' : '"'); + if (word != NULL) { + *t++ = '\0'; + insarg(idx++, word); } free(dupvar); }