ruby-changes:23998
From: nobu <ko1@a...>
Date: Wed, 13 Jun 2012 09:56:39 +0900 (JST)
Subject: [ruby-changes:23998] nobu:r36049 (trunk): process.c: use shell for reserved or special built-in
nobu 2012-06-13 09:56:31 +0900 (Wed, 13 Jun 2012) New Revision: 36049 http://svn.ruby-lang.org/cgi-bin/viewvc.cgi?view=rev&revision=36049 Log: process.c: use shell for reserved or special built-in * process.c (rb_exec_fillarg): use shell if the first word is reserved or special built-in name. http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html Modified files: trunk/ChangeLog trunk/process.c Index: ChangeLog =================================================================== --- ChangeLog (revision 36048) +++ ChangeLog (revision 36049) @@ -1,5 +1,9 @@ -Wed Jun 13 09:55:29 2012 Nobuyoshi Nakada <nobu@r...> +Wed Jun 13 09:56:29 2012 Nobuyoshi Nakada <nobu@r...> + * process.c (rb_exec_fillarg): use shell if the first word is reserved + or special built-in name. + http://pubs.opengroup.org/onlinepubs/009695399/utilities/xcu_chap02.html + * process.c (rb_exec_fillarg): treat '=' only in the first word. if the first word does not contain '=', it is the command name and environment assignments cannot be anymore. Index: process.c =================================================================== --- process.c (revision 36048) +++ process.c (revision 36049) @@ -79,6 +79,8 @@ #include <grp.h> #endif +#define numberof(array) (int)(sizeof(array)/sizeof((array)[0])) + #if defined(HAVE_TIMES) || defined(_WIN32) static VALUE rb_cProcessTms; #endif @@ -1824,6 +1826,20 @@ return prog; } +struct string_part { + const char *ptr; + size_t len; +}; + +static int +compare_posix_sh(const void *key, const void *el) +{ + const struct string_part *word = key; + int ret = strncmp(word->ptr, el, word->len); + if (!ret && ((const char *)el)[word->len]) ret = -1; + return ret; +} + static void rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, struct rb_exec_arg *e) { @@ -1850,10 +1866,40 @@ #ifndef _WIN32 if (e->use_shell) { + static const char posix_sh_cmds[][8] = { + "!", /* reserved */ + ".", /* special built-in */ + "break", /* special built-in */ + "case", /* reserved */ + "colon", /* special built-in */ + "continue", /* special built-in */ + "do", /* reserved */ + "done", /* reserved */ + "elif", /* reserved */ + "else", /* reserved */ + "esac", /* reserved */ + "eval", /* special built-in */ + "exec", /* special built-in */ + "exit", /* special built-in */ + "export", /* special built-in */ + "fi", /* reserved */ + "for", /* reserved */ + "if", /* reserved */ + "in", /* reserved */ + "readonly", /* special built-in */ + "return", /* special built-in */ + "set", /* special built-in */ + "shift", /* special built-in */ + "then", /* reserved */ + "times", /* special built-in */ + "trap", /* special built-in */ + "unset", /* special built-in */ + "until", /* reserved */ + "while", /* reserved */ + }; const char *p; - int first = 1; + struct string_part first = {0, 0}; int has_meta = 0; - int has_nonspace = 0; /* * meta characters: * @@ -1879,18 +1925,32 @@ * % (used in Parameter Expansion) */ for (p = RSTRING_PTR(prog); *p; p++) { - if (!has_nonspace && *p != ' ' && *p != '\t') - has_nonspace = 1; - if (has_nonspace && (*p == ' ' || *p == '\t')) - first = 0; + if (*p == ' ' || *p == '\t') { + if (first.ptr && !first.len) first.len = p - first.ptr; + } + else { + if (!first.ptr) first.ptr = p; + } if (!has_meta && strchr("*?{}[]<>()~&|\\$;'`\"\n#", *p)) has_meta = 1; - if (first && *p == '=') - has_meta = 1; - if (has_nonspace && has_meta) + if (!first.len) { + if (*p == '=') { + has_meta = 1; + } + else if (*p == '/') { + first.len = SIZE_T_MAX; /* longer than any posix_sh_cmds */ + } + } + if (has_meta) break; } - if (has_nonspace && !has_meta) { + if (!has_meta && first.ptr) { + if (!first.len) first.len = p - first.ptr; + if (first.len > 0 && first.len <= sizeof(posix_sh_cmds[0]) && + bsearch(&first, posix_sh_cmds, numberof(posix_sh_cmds), sizeof(posix_sh_cmds[0]), compare_posix_sh)) + has_meta = 1; + } + if (!has_meta) { /* avoid shell since no shell meta charactor found. */ e->use_shell = 0; } -- ML: ruby-changes@q... Info: http://www.atdot.net/~ko1/quickml/