diff options
author | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-06-03 14:53:13 +0000 |
---|---|---|
committer | akr <akr@b2dd03c8-39d4-4d8f-98ff-823fe69b080e> | 2012-06-03 14:53:13 +0000 |
commit | 9ee4575ea418992d3a03eb7065d31159bb51fb72 (patch) | |
tree | 2fe4d3fc7942c03145b167f4775e97fcd7708106 | |
parent | d70af743bf5d9d3a83d1b1a3ddfc0eb88ec93487 (diff) | |
download | ruby-9ee4575ea418992d3a03eb7065d31159bb51fb72.tar.gz |
* include/ruby/intern.h (rb_exec_arg): remove argc and argv fields.
add use_shell, argv_str and argv_buf fields.
* process.c (rb_proc_exec_e): don't split shell command line arguments
here to avoid memory allocation in a child process.
(rb_exec_fillarg): split shell command line arguments here.
(proc_exec_v): takes argv_str argument instead of argv.
(rb_proc_exec_ne): removed.
(rb_proc_exec_n): removed.
(rb_run_exec_options_err): don't initialize the removed fields.
(rb_exec_err): don't initialize the removed fields.
call proc_exec_v directly instead of rb_proc_exec_ne.
(rb_spawn_process): use use_shell field.
git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@35889 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
-rw-r--r-- | ChangeLog | 16 | ||||
-rw-r--r-- | include/ruby/intern.h | 5 | ||||
-rw-r--r-- | process.c | 194 |
3 files changed, 119 insertions, 96 deletions
@@ -1,3 +1,19 @@ +Sun Jun 3 23:47:30 2012 Tanaka Akira <akr@fsij.org> + + * include/ruby/intern.h (rb_exec_arg): remove argc and argv fields. + add use_shell, argv_str and argv_buf fields. + + * process.c (rb_proc_exec_e): don't split shell command line arguments + here to avoid memory allocation in a child process. + (rb_exec_fillarg): split shell command line arguments here. + (proc_exec_v): takes argv_str argument instead of argv. + (rb_proc_exec_ne): removed. + (rb_proc_exec_n): removed. + (rb_run_exec_options_err): don't initialize the removed fields. + (rb_exec_err): don't initialize the removed fields. + call proc_exec_v directly instead of rb_proc_exec_ne. + (rb_spawn_process): use use_shell field. + Sun Jun 3 21:53:00 2012 NARUSE, Yui <naruse@ruby-lang.org> * GPL: update text of GPLv2. [ruby-core:44488] [Bug #6328] diff --git a/include/ruby/intern.h b/include/ruby/intern.h index 693e52b5bd..e963d99b06 100644 --- a/include/ruby/intern.h +++ b/include/ruby/intern.h @@ -592,12 +592,13 @@ VALUE rb_sym_all_symbols(void); void rb_last_status_set(int status, rb_pid_t pid); VALUE rb_last_status_get(void); struct rb_exec_arg { - int argc; - VALUE *argv; const char *prog; VALUE options; VALUE redirect_fds; VALUE progname; + int use_shell; + VALUE argv_str; + VALUE argv_buf; VALUE envp_str; VALUE envp_buf; }; @@ -1068,19 +1068,22 @@ exec_with_sh(const char *prog, char **argv) #ifdef __native_client__ static int -proc_exec_v(char **argv, const char *prog, VALUE envp_str) +proc_exec_v(const char *prog, VALUE argv_str, VALUE envp_str) { rb_notimplement(); } #else static int -proc_exec_v(char **argv, const char *prog, VALUE envp_str) +proc_exec_v(const char *prog, VALUE argv_str, VALUE envp_str) { + char **argv; char fbuf[MAXPATHLEN]; # if defined(__EMX__) || defined(OS2) char **new_argv = NULL; # endif + argv = (char **)RSTRING_PTR(argv_str); + if (!prog) prog = argv[0]; prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf)); @@ -1133,32 +1136,6 @@ proc_exec_v(char **argv, const char *prog, VALUE envp_str) } #endif -static int -rb_proc_exec_ne(int argc, VALUE *argv, const char *prog, VALUE envp_str) -{ - char **args; - int i; - int ret = -1; - VALUE v; - - args = ALLOC_ARGV(argc+1, v); - for (i=0; i<argc; i++) { - args[i] = RSTRING_PTR(argv[i]); - } - args[i] = 0; - if (args[0]) { - ret = proc_exec_v(args, prog, envp_str); - } - ALLOCV_END(v); - return ret; -} - -int -rb_proc_exec_n(int argc, VALUE *argv, const char *prog) -{ - return rb_proc_exec_ne(argc, argv, prog, Qfalse); -} - #ifdef __native_client__ static int rb_proc_exec_e(const char *str, VALUE envp_str) @@ -1169,73 +1146,43 @@ rb_proc_exec_e(const char *str, VALUE envp_str) static int rb_proc_exec_e(const char *str, VALUE envp_str) { -#ifndef _WIN32 - const char *s = str; - char *ss, *t; - char **argv, **a; - VALUE v; - int ret = -1; -#endif - while (*str && ISSPACE(*str)) str++; + if (!*str) { + errno = ENOENT; + return -1; + } + #ifdef _WIN32 before_exec(); rb_w32_spawn(P_OVERLAY, (char *)str, 0); after_exec(); return -1; #else - for (s=str; *s; s++) { - if (ISSPACE(*s)) { - const char *p, *nl = NULL; - for (p = s; ISSPACE(*p); p++) { - if (*p == '\n') nl = p; - } - if (!*p) break; - if (nl) s = nl; - } - if (*s != ' ' && !ISALPHA(*s) && strchr("*?{}[]<>()~&|\\$;'`\"\n",*s)) { #if defined(__CYGWIN32__) || defined(__EMX__) - char fbuf[MAXPATHLEN]; - char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf)); - int status = -1; - before_exec(); - if (shell) - execl(shell, "sh", "-c", str, (char *) NULL); - else - status = system(str); - after_exec(); - if (status != -1) - exit(status); + { + char fbuf[MAXPATHLEN]; + char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf)); + int status = -1; + before_exec(); + if (shell) + execl(shell, "sh", "-c", str, (char *) NULL); + else + status = system(str); + after_exec(); + if (status != -1) + exit(status); + } #else - before_exec(); - if (envp_str) - execle("/bin/sh", "sh", "-c", str, (char *)NULL, (char **)RSTRING_PTR(envp_str)); - else - execl("/bin/sh", "sh", "-c", str, (char *)NULL); - preserving_errno(after_exec()); + before_exec(); + if (envp_str) + execle("/bin/sh", "sh", "-c", str, (char *)NULL, (char **)RSTRING_PTR(envp_str)); + else + execl("/bin/sh", "sh", "-c", str, (char *)NULL); + preserving_errno(after_exec()); #endif - return -1; - } - } - a = argv = ALLOC_ARGV_WITH_STR((s-str)/2+2, v, ss, s-str+1); - memcpy(ss, str, s-str); - ss[s-str] = '\0'; - if ((*a++ = strtok(ss, " \t")) != 0) { - while ((t = strtok(NULL, " \t")) != 0) { - *a++ = t; - } - *a = NULL; - } - if (argv[0]) { - ret = proc_exec_v(argv, NULL, envp_str); - } - else { - errno = ENOENT; - } - ALLOCV_END(v); - return ret; + return -1; #endif /* _WIN32 */ } #endif @@ -1857,10 +1804,73 @@ rb_exec_fillarg(VALUE prog, int argc, VALUE *argv, VALUE env, VALUE opthash, str rb_ary_store(options, EXEC_OPTION_ENV, env); } - e->argc = argc; - e->argv = argv; + e->use_shell = argc == 0; e->prog = prog ? RSTRING_PTR(prog) : 0; e->progname = prog; + +#ifndef _WIN32 + if (e->use_shell) { + char *p; + int has_meta = 0; + int has_nonspace = 0; + for (p = RSTRING_PTR(prog); *p; p++) { + if (*p != ' ' && *p != '\t') + has_nonspace = 1; + if (strchr("*?{}[]<>()~&|\\$;'`\"\n", *p)) + has_meta = 1; + } + if (has_nonspace && !has_meta) { + /* avoid shell since no shell meta charactor found. */ + e->use_shell = 0; + } + if (!e->use_shell) { + VALUE argv_buf; + argv_buf = hide_obj(rb_str_buf_new(0)); + p = RSTRING_PTR(prog); + while (*p) { + while (*p == ' ' || *p == '\t') + p++; + if (*p) { + char *w = p; + while (*p && *p != ' ' && *p != '\t') + p++; + rb_str_buf_cat(argv_buf, w, p-w); + rb_str_buf_cat(argv_buf, "", 1); /* append '\0' */ + } + } + e->argv_buf = argv_buf; + e->progname = hide_obj(rb_str_new_cstr(RSTRING_PTR(argv_buf))); + e->prog = RSTRING_PTR(e->progname); + } + } +#endif + + if (!e->use_shell && !e->argv_buf) { + int i; + VALUE argv_buf; + argv_buf = rb_str_buf_new(0); + hide_obj(argv_buf); + for (i = 0; i < argc; i++) { + rb_str_buf_cat2(argv_buf, StringValueCStr(argv[i])); + rb_str_buf_cat(argv_buf, "", 1); /* append '\0' */ + } + e->argv_buf = argv_buf; + } + + if (e->argv_buf) { + char *p, *ep; + VALUE argv_str; + argv_str = hide_obj(rb_str_buf_new(sizeof(char*) * (argc + 1))); + p = RSTRING_PTR(e->argv_buf); + ep = p + RSTRING_LEN(e->argv_buf); + while (p < ep) { + rb_str_buf_cat(argv_str, (char *)&p, sizeof(p)); + p += strlen(p) + 1; + } + p = NULL; + rb_str_buf_cat(argv_str, (char *)&p, sizeof(p)); + e->argv_str = argv_str; + } } VALUE @@ -2433,8 +2443,6 @@ rb_run_exec_options_err(const struct rb_exec_arg *e, struct rb_exec_arg *s, char return 0; if (s) { - s->argc = 0; - s->argv = NULL; s->prog = NULL; s->options = soptions = hide_obj(rb_ary_new()); s->redirect_fds = Qnil; @@ -2527,19 +2535,17 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s) int rb_exec_err(const struct rb_exec_arg *e, char *errmsg, size_t errmsg_buflen) { - int argc = e->argc; - VALUE *argv = e->argv; const char *prog = e->prog; if (rb_run_exec_options_err(e, NULL, errmsg, errmsg_buflen) < 0) { return -1; } - if (argc == 0) { + if (e->use_shell) { rb_proc_exec_e(prog, e->envp_str); } else { - rb_proc_exec_ne(argc, argv, prog, e->envp_str); + proc_exec_v(prog, e->argv_str, e->envp_str); } return -1; } @@ -3090,9 +3096,9 @@ rb_spawn_process(struct rb_exec_arg *earg, VALUE prog, char *errmsg, size_t errm argc = earg->argc; argv = earg->argv; - if (prog && argc) argv[0] = prog; + if (prog && !earg->use_shell) argv[0] = prog; # if defined HAVE_SPAWNV - if (!argc) { + if (earg->use_shell) { pid = proc_spawn(RSTRING_PTR(prog)); } else { @@ -3103,7 +3109,7 @@ rb_spawn_process(struct rb_exec_arg *earg, VALUE prog, char *errmsg, size_t errm rb_last_status_set(0x7f << 8, 0); # endif # else - if (argc) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" ")); + if (!earg->use_shell) prog = rb_ary_join(rb_ary_new4(argc, argv), rb_str_new2(" ")); status = system(StringValuePtr(prog)); rb_last_status_set((status & 0xff) << 8, 0); # endif |