From d2c1f4d10b29040aad3fbf38b2b27fe46e145e63 Mon Sep 17 00:00:00 2001 From: ksss Date: Sun, 7 Aug 2016 22:18:08 +0900 Subject: Enable Fixnum option --- src/io.c | 40 ++++++++++++++++++++++++++++++---------- 1 file changed, 30 insertions(+), 10 deletions(-) (limited to 'src') diff --git a/src/io.c b/src/io.c index f842ceb85..264ded8ad 100644 --- a/src/io.c +++ b/src/io.c @@ -264,13 +264,32 @@ mrb_io_alloc(mrb_state *mrb) #endif #ifndef _WIN32 +static int +option_to_fd(mrb_state *mrb, mrb_value obj, const char *key) +{ + mrb_value opt = mrb_funcall(mrb, obj, "[]", 1, mrb_symbol_value(mrb_intern_static(mrb, key, strlen(key)))); + if (mrb_nil_p(opt)) { + return -1; + } + + switch (mrb_type(opt)) { + case MRB_TT_DATA: /* IO */ + return mrb_fixnum(mrb_io_fileno(mrb, opt)); + case MRB_TT_FIXNUM: + return mrb_fixnum(opt); + default: + mrb_raise(mrb, E_ARGUMENT_ERROR, "wrong exec redirect action"); + break; + } + return -1; /* never reached */ +} + mrb_value mrb_io_s_popen(mrb_state *mrb, mrb_value klass) { mrb_value cmd, io, result; mrb_value mode = mrb_str_new_cstr(mrb, "r"); mrb_value opt = mrb_hash_new(mrb); - mrb_value opt_in, opt_out, opt_err; struct mrb_io *fptr; const char *pname; @@ -279,6 +298,7 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass) int pw[2] = { -1, -1 }; int doexec; int saved_errno; + int opt_in, opt_out, opt_err; mrb_get_args(mrb, "S|SH", &cmd, &mode, &opt); io = mrb_obj_value(mrb_data_object_alloc(mrb, mrb_class_ptr(klass), NULL, &mrb_io_type)); @@ -287,6 +307,9 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass) flags = mrb_io_modestr_to_flags(mrb, mrb_string_value_cstr(mrb, &mode)); doexec = (strcmp("-", pname) != 0); + opt_in = option_to_fd(mrb, opt, "in"); + opt_out = option_to_fd(mrb, opt, "out"); + opt_err = option_to_fd(mrb, opt, "err"); if (flags & FMODE_READABLE) { if (pipe(pr) == -1) { @@ -316,17 +339,14 @@ mrb_io_s_popen(mrb_state *mrb, mrb_value klass) result = mrb_nil_value(); switch (pid = fork()) { case 0: /* child */ - opt_in = mrb_funcall(mrb, opt, "[]", 1, mrb_symbol_value(mrb_intern_lit(mrb, "in"))); - opt_out = mrb_funcall(mrb, opt, "[]", 1, mrb_symbol_value(mrb_intern_lit(mrb, "out"))); - opt_err = mrb_funcall(mrb, opt, "[]", 1, mrb_symbol_value(mrb_intern_lit(mrb, "err"))); - if (!mrb_nil_p(opt_in)) { - dup2(mrb_fixnum(mrb_io_fileno(mrb, opt_in)), 0); + if (opt_in != -1) { + dup2(opt_in, 0); } - if (!mrb_nil_p(opt_out)) { - dup2(mrb_fixnum(mrb_io_fileno(mrb, opt_out)), 1); + if (opt_out != -1) { + dup2(opt_out, 1); } - if (!mrb_nil_p(opt_err)) { - dup2(mrb_fixnum(mrb_io_fileno(mrb, opt_err)), 2); + if (opt_err != -1) { + dup2(opt_err, 2); } if (flags & FMODE_READABLE) { close(pr[0]); -- cgit v1.2.3