summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--internal/io.h1
-rw-r--r--io.c24
-rw-r--r--ruby.c19
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) */
diff --git a/io.c b/io.c
index 2cdfd80610..4be5f05d2f 100644
--- a/io.c
+++ b/io.c
@@ -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()) {
diff --git a/ruby.c b/ruby.c
index a3d67d3f46..79cd595806 100644
--- a/ruby.c
+++ b/ruby.c
@@ -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;
}