* 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
This commit is contained in:
akr 2012-06-03 14:53:13 +00:00
Родитель d70af743bf
Коммит 9ee4575ea4
3 изменённых файлов: 119 добавлений и 96 удалений

Просмотреть файл

@ -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]

Просмотреть файл

@ -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;
};

194
process.c
Просмотреть файл

@ -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