mirror of
https://github.com/ruby/ruby.git
synced 2022-11-09 12:17:21 -05:00
* 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:
parent
d70af743bf
commit
9ee4575ea4
3 changed files with 119 additions and 96 deletions
16
ChangeLog
16
ChangeLog
|
@ -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>
|
Sun Jun 3 21:53:00 2012 NARUSE, Yui <naruse@ruby-lang.org>
|
||||||
|
|
||||||
* GPL: update text of GPLv2. [ruby-core:44488] [Bug #6328]
|
* 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);
|
void rb_last_status_set(int status, rb_pid_t pid);
|
||||||
VALUE rb_last_status_get(void);
|
VALUE rb_last_status_get(void);
|
||||||
struct rb_exec_arg {
|
struct rb_exec_arg {
|
||||||
int argc;
|
|
||||||
VALUE *argv;
|
|
||||||
const char *prog;
|
const char *prog;
|
||||||
VALUE options;
|
VALUE options;
|
||||||
VALUE redirect_fds;
|
VALUE redirect_fds;
|
||||||
VALUE progname;
|
VALUE progname;
|
||||||
|
int use_shell;
|
||||||
|
VALUE argv_str;
|
||||||
|
VALUE argv_buf;
|
||||||
VALUE envp_str;
|
VALUE envp_str;
|
||||||
VALUE envp_buf;
|
VALUE envp_buf;
|
||||||
};
|
};
|
||||||
|
|
158
process.c
158
process.c
|
@ -1068,19 +1068,22 @@ exec_with_sh(const char *prog, char **argv)
|
||||||
|
|
||||||
#ifdef __native_client__
|
#ifdef __native_client__
|
||||||
static int
|
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();
|
rb_notimplement();
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
static int
|
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];
|
char fbuf[MAXPATHLEN];
|
||||||
# if defined(__EMX__) || defined(OS2)
|
# if defined(__EMX__) || defined(OS2)
|
||||||
char **new_argv = NULL;
|
char **new_argv = NULL;
|
||||||
# endif
|
# endif
|
||||||
|
|
||||||
|
argv = (char **)RSTRING_PTR(argv_str);
|
||||||
|
|
||||||
if (!prog)
|
if (!prog)
|
||||||
prog = argv[0];
|
prog = argv[0];
|
||||||
prog = dln_find_exe_r(prog, 0, fbuf, sizeof(fbuf));
|
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
|
#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__
|
#ifdef __native_client__
|
||||||
static int
|
static int
|
||||||
rb_proc_exec_e(const char *str, VALUE envp_str)
|
rb_proc_exec_e(const char *str, VALUE envp_str)
|
||||||
|
@ -1169,34 +1146,22 @@ rb_proc_exec_e(const char *str, VALUE envp_str)
|
||||||
static int
|
static int
|
||||||
rb_proc_exec_e(const char *str, VALUE envp_str)
|
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))
|
while (*str && ISSPACE(*str))
|
||||||
str++;
|
str++;
|
||||||
|
|
||||||
|
if (!*str) {
|
||||||
|
errno = ENOENT;
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
#ifdef _WIN32
|
#ifdef _WIN32
|
||||||
before_exec();
|
before_exec();
|
||||||
rb_w32_spawn(P_OVERLAY, (char *)str, 0);
|
rb_w32_spawn(P_OVERLAY, (char *)str, 0);
|
||||||
after_exec();
|
after_exec();
|
||||||
return -1;
|
return -1;
|
||||||
#else
|
#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__)
|
#if defined(__CYGWIN32__) || defined(__EMX__)
|
||||||
|
{
|
||||||
char fbuf[MAXPATHLEN];
|
char fbuf[MAXPATHLEN];
|
||||||
char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
|
char *shell = dln_find_exe_r("sh", 0, fbuf, sizeof(fbuf));
|
||||||
int status = -1;
|
int status = -1;
|
||||||
|
@ -1208,6 +1173,7 @@ rb_proc_exec_e(const char *str, VALUE envp_str)
|
||||||
after_exec();
|
after_exec();
|
||||||
if (status != -1)
|
if (status != -1)
|
||||||
exit(status);
|
exit(status);
|
||||||
|
}
|
||||||
#else
|
#else
|
||||||
before_exec();
|
before_exec();
|
||||||
if (envp_str)
|
if (envp_str)
|
||||||
|
@ -1217,25 +1183,6 @@ rb_proc_exec_e(const char *str, VALUE envp_str)
|
||||||
preserving_errno(after_exec());
|
preserving_errno(after_exec());
|
||||||
#endif
|
#endif
|
||||||
return -1;
|
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;
|
|
||||||
#endif /* _WIN32 */
|
#endif /* _WIN32 */
|
||||||
}
|
}
|
||||||
#endif
|
#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);
|
rb_ary_store(options, EXEC_OPTION_ENV, env);
|
||||||
}
|
}
|
||||||
|
|
||||||
e->argc = argc;
|
e->use_shell = argc == 0;
|
||||||
e->argv = argv;
|
|
||||||
e->prog = prog ? RSTRING_PTR(prog) : 0;
|
e->prog = prog ? RSTRING_PTR(prog) : 0;
|
||||||
e->progname = prog;
|
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
|
VALUE
|
||||||
|
@ -2433,8 +2443,6 @@ rb_run_exec_options_err(const struct rb_exec_arg *e, struct rb_exec_arg *s, char
|
||||||
return 0;
|
return 0;
|
||||||
|
|
||||||
if (s) {
|
if (s) {
|
||||||
s->argc = 0;
|
|
||||||
s->argv = NULL;
|
|
||||||
s->prog = NULL;
|
s->prog = NULL;
|
||||||
s->options = soptions = hide_obj(rb_ary_new());
|
s->options = soptions = hide_obj(rb_ary_new());
|
||||||
s->redirect_fds = Qnil;
|
s->redirect_fds = Qnil;
|
||||||
|
@ -2527,19 +2535,17 @@ rb_run_exec_options(const struct rb_exec_arg *e, struct rb_exec_arg *s)
|
||||||
int
|
int
|
||||||
rb_exec_err(const struct rb_exec_arg *e, char *errmsg, size_t errmsg_buflen)
|
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;
|
const char *prog = e->prog;
|
||||||
|
|
||||||
if (rb_run_exec_options_err(e, NULL, errmsg, errmsg_buflen) < 0) {
|
if (rb_run_exec_options_err(e, NULL, errmsg, errmsg_buflen) < 0) {
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (argc == 0) {
|
if (e->use_shell) {
|
||||||
rb_proc_exec_e(prog, e->envp_str);
|
rb_proc_exec_e(prog, e->envp_str);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
rb_proc_exec_ne(argc, argv, prog, e->envp_str);
|
proc_exec_v(prog, e->argv_str, e->envp_str);
|
||||||
}
|
}
|
||||||
return -1;
|
return -1;
|
||||||
}
|
}
|
||||||
|
@ -3090,9 +3096,9 @@ rb_spawn_process(struct rb_exec_arg *earg, VALUE prog, char *errmsg, size_t errm
|
||||||
|
|
||||||
argc = earg->argc;
|
argc = earg->argc;
|
||||||
argv = earg->argv;
|
argv = earg->argv;
|
||||||
if (prog && argc) argv[0] = prog;
|
if (prog && !earg->use_shell) argv[0] = prog;
|
||||||
# if defined HAVE_SPAWNV
|
# if defined HAVE_SPAWNV
|
||||||
if (!argc) {
|
if (earg->use_shell) {
|
||||||
pid = proc_spawn(RSTRING_PTR(prog));
|
pid = proc_spawn(RSTRING_PTR(prog));
|
||||||
}
|
}
|
||||||
else {
|
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);
|
rb_last_status_set(0x7f << 8, 0);
|
||||||
# endif
|
# endif
|
||||||
# else
|
# 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));
|
status = system(StringValuePtr(prog));
|
||||||
rb_last_status_set((status & 0xff) << 8, 0);
|
rb_last_status_set((status & 0xff) << 8, 0);
|
||||||
# endif
|
# endif
|
||||||
|
|
Loading…
Add table
Reference in a new issue