summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
authorksss <[email protected]>2016-08-07 15:58:39 +0900
committerksss <[email protected]>2016-08-07 21:21:01 +0900
commitb462ef450665141a38978d5b31b5550a60db4e6b (patch)
treeaee07c67b90f27d02d40d1a61329664eb44bf188
parent93d481d4b49829e37b1f501c7307663c6327dfab (diff)
downloadmruby-b462ef450665141a38978d5b31b5550a60db4e6b.tar.gz
mruby-b462ef450665141a38978d5b31b5550a60db4e6b.zip
Enable option :in, :out, :err
-rw-r--r--mrblib/io.rb4
-rw-r--r--src/io.c13
-rw-r--r--test/io.rb37
3 files changed, 52 insertions, 2 deletions
diff --git a/mrblib/io.rb b/mrblib/io.rb
index 9644c2396..7e6ed9b1d 100644
--- a/mrblib/io.rb
+++ b/mrblib/io.rb
@@ -26,11 +26,11 @@ class IO
end
end
- def self.popen(command, mode = 'r', &block)
+ def self.popen(command, mode = 'r', opts={}, &block)
if !self.respond_to?(:_popen)
raise NotImplementedError, "popen is not supported on this platform"
end
- io = self._popen(command, mode)
+ io = self._popen(command, mode, opts)
return io unless block
begin
diff --git a/src/io.c b/src/io.c
index 42e9a93a8..f842ceb85 100644
--- a/src/io.c
+++ b/src/io.c
@@ -270,6 +270,7 @@ 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;
@@ -315,6 +316,18 @@ 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 (!mrb_nil_p(opt_out)) {
+ dup2(mrb_fixnum(mrb_io_fileno(mrb, opt_out)), 1);
+ }
+ if (!mrb_nil_p(opt_err)) {
+ dup2(mrb_fixnum(mrb_io_fileno(mrb, opt_err)), 2);
+ }
if (flags & FMODE_READABLE) {
close(pr[0]);
if (pr[1] != 1) {
diff --git a/test/io.rb b/test/io.rb
index f0f30e3ce..6e1bcb247 100644
--- a/test/io.rb
+++ b/test/io.rb
@@ -393,6 +393,43 @@ assert('IO.popen') do
end
end
+assert('IO.popen with in option') do
+ begin
+ IO.pipe do |r, w|
+ w.write 'hello'
+ w.close
+ assert_equal "hello", IO.popen("cat", "r", in: r) { |i| i.read }
+ assert_equal "", r.read
+ end
+ rescue NotImplementedError => e
+ skip e.message
+ end
+end
+
+assert('IO.popen with out option') do
+ begin
+ IO.pipe do |r, w|
+ IO.popen("echo 'hello'", "w", out: w) {}
+ w.close
+ assert_equal "hello\n", r.read
+ end
+ rescue NotImplementedError => e
+ skip e.message
+ end
+end
+
+assert('IO.popen with err option') do
+ begin
+ IO.pipe do |r, w|
+ assert_equal "", IO.popen("echo 'hello' 1>&2", "r", err: w) { |i| i.read }
+ w.close
+ assert_equal "hello\n", r.read
+ end
+ rescue NotImplementedError => e
+ skip e.message
+ end
+end
+
assert('IO.read') do
# empty file
fd = IO.sysopen $mrbtest_io_wfname, "w"