diff options
-rw-r--r-- | internal/io.h | 1 | ||||
-rw-r--r-- | io.c | 24 | ||||
-rw-r--r-- | ruby.c | 19 |
3 files changed, 37 insertions, 7 deletions
diff --git a/internal/io.h b/internal/io.h index a08601faea..6578d0b683 100644 --- a/internal/io.h +++ b/internal/io.h @@ -23,6 +23,7 @@ void rb_io_fptr_finalize_internal(void *ptr); # undef rb_io_fptr_finalize #endif #define rb_io_fptr_finalize rb_io_fptr_finalize_internal +VALUE rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt); RUBY_SYMBOL_EXPORT_BEGIN /* io.c (export) */ @@ -6868,6 +6868,8 @@ pipe_close(VALUE io) return Qnil; } +static VALUE popen_finish(VALUE port, VALUE klass); + /* * call-seq: * IO.popen([env,] cmd, mode="r" [, opt]) -> io @@ -6957,10 +6959,7 @@ pipe_close(VALUE io) static VALUE rb_io_s_popen(int argc, VALUE *argv, VALUE klass) { - const char *modestr; - VALUE pname, pmode = Qnil, port, tmp, opt = Qnil, env = Qnil, execarg_obj = Qnil; - int oflags, fmode; - convconfig_t convconfig; + VALUE pname, pmode = Qnil, opt = Qnil, env = Qnil; if (argc > 1 && !NIL_P(opt = rb_check_hash_type(argv[argc-1]))) --argc; if (argc > 1 && !NIL_P(env = rb_check_hash_type(argv[0]))) --argc, ++argv; @@ -6976,6 +6975,16 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass) rb_error_arity(argc + ex, 1 + ex, 2 + ex); } } + return popen_finish(rb_io_popen(pname, pmode, env, opt), klass); +} + +VALUE +rb_io_popen(VALUE pname, VALUE pmode, VALUE env, VALUE opt) +{ + const char *modestr; + VALUE tmp, execarg_obj = Qnil; + int oflags, fmode; + convconfig_t convconfig; tmp = rb_check_array_type(pname); if (!NIL_P(tmp)) { @@ -7003,7 +7012,12 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass) rb_io_extract_modeenc(&pmode, 0, opt, &oflags, &fmode, &convconfig); modestr = rb_io_oflags_modestr(oflags); - port = pipe_open(execarg_obj, modestr, fmode, &convconfig); + return pipe_open(execarg_obj, modestr, fmode, &convconfig); +} + +static VALUE +popen_finish(VALUE port, VALUE klass) +{ if (NIL_P(port)) { /* child */ if (rb_block_given_p()) { @@ -1606,12 +1606,12 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) (argc > 0 && argv && argv[0] ? argv[0] : origarg.argc > 0 && origarg.argv && origarg.argv[0] ? origarg.argv[0] : ruby_engine); -#ifdef HAVE_WORKING_FORK if (opt->dump & DUMP_BIT(help)) { const char *pager_env = getenv("RUBY_PAGER"); if (!pager_env) pager_env = getenv("PAGER"); if (pager_env && *pager_env && isatty(0) && isatty(1)) { VALUE pager = rb_str_new_cstr(pager_env); +#ifdef HAVE_WORKING_FORK int fds[2]; if (rb_pipe(fds) == 0) { rb_pid_t pid = fork(); @@ -1632,9 +1632,24 @@ process_options(int argc, char **argv, ruby_cmdline_options_t *opt) rb_waitpid(pid, 0, 0); } } +#else + VALUE port = rb_io_popen(pager, rb_str_new_lit("w"), Qnil, Qnil); + if (!NIL_P(port)) { + int oldout = dup(1); + int olderr = dup(2); + int fd = RFILE(port)->fptr->fd; + dup2(fd, 1); + dup2(fd, 2); + usage(progname, 1); + fflush(stdout); + dup2(oldout, 1); + dup2(olderr, 2); + rb_io_close(port); + return Qtrue; + } +#endif } } -#endif usage(progname, (opt->dump & DUMP_BIT(help))); return Qtrue; } |