popen: shell commands with envvar
* io.c (is_popen_fork): check if fork and raise NotImplementedError if unavailable. * io.c (rb_io_s_popen): allow shell commands with modified environment variables. git-svn-id: svn+ssh://ci.ruby-lang.org/ruby/trunk@36213 b2dd03c8-39d4-4d8f-98ff-823fe69b080e
This commit is contained in:
parent
0e8395d6cb
commit
0f0f0f4441
@ -1,3 +1,11 @@
|
|||||||
|
Mon Jun 25 15:42:00 2012 Nobuyoshi Nakada <nobu@ruby-lang.org>
|
||||||
|
|
||||||
|
* io.c (is_popen_fork): check if fork and raise NotImplementedError if
|
||||||
|
unavailable.
|
||||||
|
|
||||||
|
* io.c (rb_io_s_popen): allow shell commands with modified environment
|
||||||
|
variables.
|
||||||
|
|
||||||
Mon Jun 25 11:34:45 2012 NAKAMURA Usaku <usa@ruby-lang.org>
|
Mon Jun 25 11:34:45 2012 NAKAMURA Usaku <usa@ruby-lang.org>
|
||||||
|
|
||||||
* internal.h: use rb_pid_t instead of pid_t because of there is no
|
* internal.h: use rb_pid_t instead of pid_t because of there is no
|
||||||
|
44
io.c
44
io.c
@ -5692,35 +5692,30 @@ pipe_open(VALUE execarg_obj, const char *modestr, int fmode, convconfig_t *convc
|
|||||||
return port;
|
return port;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static int
|
||||||
pipe_open_v(int argc, VALUE *argv, const char *modestr, int fmode, convconfig_t *convconfig)
|
is_popen_fork(VALUE prog)
|
||||||
{
|
{
|
||||||
VALUE execarg_obj, ret;
|
if (RSTRING_LEN(prog) == 1 && RSTRING_PTR(prog)[0] == '-') {
|
||||||
execarg_obj = rb_execarg_new(argc, argv, FALSE);
|
#if !defined(HAVE_FORK)
|
||||||
ret = pipe_open(execarg_obj, modestr, fmode, convconfig);
|
rb_raise(rb_eNotImpError,
|
||||||
return ret;
|
"fork() function is unimplemented on this machine");
|
||||||
|
#else
|
||||||
|
return TRUE;
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
return FALSE;
|
||||||
}
|
}
|
||||||
|
|
||||||
static VALUE
|
static VALUE
|
||||||
pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
|
pipe_open_s(VALUE prog, const char *modestr, int fmode, convconfig_t *convconfig)
|
||||||
{
|
{
|
||||||
const char *cmd = RSTRING_PTR(prog);
|
|
||||||
int argc = 1;
|
int argc = 1;
|
||||||
VALUE *argv = &prog;
|
VALUE *argv = &prog;
|
||||||
VALUE execarg_obj, ret;
|
VALUE execarg_obj = Qnil;
|
||||||
|
|
||||||
if (RSTRING_LEN(prog) == 1 && cmd[0] == '-') {
|
if (!is_popen_fork(prog))
|
||||||
#if !defined(HAVE_FORK)
|
execarg_obj = rb_execarg_new(argc, argv, TRUE);
|
||||||
rb_raise(rb_eNotImpError,
|
return pipe_open(execarg_obj, modestr, fmode, convconfig);
|
||||||
"fork() function is unimplemented on this machine");
|
|
||||||
#else
|
|
||||||
return pipe_open(Qnil, modestr, fmode, convconfig);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
execarg_obj = rb_execarg_new(argc, argv, TRUE);
|
|
||||||
ret = pipe_open(execarg_obj, modestr, fmode, convconfig);
|
|
||||||
return ret;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
@ -5810,7 +5805,7 @@ static VALUE
|
|||||||
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
|
rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
|
||||||
{
|
{
|
||||||
const char *modestr;
|
const char *modestr;
|
||||||
VALUE pname, pmode, port, tmp, opt;
|
VALUE pname, pmode, port, tmp, opt, execarg_obj;
|
||||||
int oflags, fmode;
|
int oflags, fmode;
|
||||||
convconfig_t convconfig;
|
convconfig_t convconfig;
|
||||||
|
|
||||||
@ -5829,13 +5824,16 @@ rb_io_s_popen(int argc, VALUE *argv, VALUE klass)
|
|||||||
#endif
|
#endif
|
||||||
tmp = rb_ary_dup(tmp);
|
tmp = rb_ary_dup(tmp);
|
||||||
RBASIC(tmp)->klass = 0;
|
RBASIC(tmp)->klass = 0;
|
||||||
port = pipe_open_v((int)len, RARRAY_PTR(tmp), modestr, fmode, &convconfig);
|
execarg_obj = rb_execarg_new((int)len, RARRAY_PTR(tmp), TRUE);
|
||||||
rb_ary_clear(tmp);
|
rb_ary_clear(tmp);
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
SafeStringValue(pname);
|
SafeStringValue(pname);
|
||||||
port = pipe_open_s(pname, modestr, fmode, &convconfig);
|
execarg_obj = Qnil;
|
||||||
|
if (!is_popen_fork(pname))
|
||||||
|
execarg_obj = rb_execarg_new(1, &pname, TRUE);
|
||||||
}
|
}
|
||||||
|
port = pipe_open(execarg_obj, modestr, fmode, &convconfig);
|
||||||
if (NIL_P(port)) {
|
if (NIL_P(port)) {
|
||||||
/* child */
|
/* child */
|
||||||
if (rb_block_given_p()) {
|
if (rb_block_given_p()) {
|
||||||
|
@ -275,34 +275,53 @@ class TestProcess < Test::Unit::TestCase
|
|||||||
assert_equal("PATH\n", io.read)
|
assert_equal("PATH\n", io.read)
|
||||||
}
|
}
|
||||||
|
|
||||||
IO.popen([{"FOO"=>"BAR"}, *ENVCOMMAND]) {|io|
|
|
||||||
assert_match(/^FOO=BAR$/, io.read)
|
|
||||||
}
|
|
||||||
|
|
||||||
with_tmpchdir {|d|
|
with_tmpchdir {|d|
|
||||||
system({"fofo"=>"haha"}, *ENVCOMMAND, STDOUT=>"out")
|
system({"fofo"=>"haha"}, *ENVCOMMAND, STDOUT=>"out")
|
||||||
assert_match(/^fofo=haha$/, File.read("out").chomp)
|
assert_match(/^fofo=haha$/, File.read("out").chomp, message)
|
||||||
|
}
|
||||||
|
end
|
||||||
|
|
||||||
|
def _test_execopts_env_popen(cmd)
|
||||||
|
message = cmd.inspect
|
||||||
|
IO.popen([{"FOO"=>"BAR"}, *cmd]) {|io|
|
||||||
|
assert_match(/^FOO=BAR$/, io.read, message)
|
||||||
}
|
}
|
||||||
|
|
||||||
old = ENV["hmm"]
|
old = ENV["hmm"]
|
||||||
begin
|
begin
|
||||||
ENV["hmm"] = "fufu"
|
ENV["hmm"] = "fufu"
|
||||||
IO.popen(ENVCOMMAND) {|io| assert_match(/^hmm=fufu$/, io.read) }
|
IO.popen(cmd) {|io| assert_match(/^hmm=fufu$/, io.read, message)}
|
||||||
IO.popen([{"hmm"=>""}, *ENVCOMMAND]) {|io| assert_match(/^hmm=$/, io.read) }
|
IO.popen([{"hmm"=>""}, *cmd]) {|io| assert_match(/^hmm=$/, io.read, message)}
|
||||||
IO.popen([{"hmm"=>nil}, *ENVCOMMAND]) {|io| assert_not_match(/^hmm=/, io.read) }
|
IO.popen([{"hmm"=>nil}, *cmd]) {|io| assert_not_match(/^hmm=/, io.read, message)}
|
||||||
ENV["hmm"] = ""
|
ENV["hmm"] = ""
|
||||||
IO.popen(ENVCOMMAND) {|io| assert_match(/^hmm=$/, io.read) }
|
IO.popen(cmd) {|io| assert_match(/^hmm=$/, io.read, message)}
|
||||||
IO.popen([{"hmm"=>""}, *ENVCOMMAND]) {|io| assert_match(/^hmm=$/, io.read) }
|
IO.popen([{"hmm"=>""}, *cmd]) {|io| assert_match(/^hmm=$/, io.read, message)}
|
||||||
IO.popen([{"hmm"=>nil}, *ENVCOMMAND]) {|io| assert_not_match(/^hmm=/, io.read) }
|
IO.popen([{"hmm"=>nil}, *cmd]) {|io| assert_not_match(/^hmm=/, io.read, message)}
|
||||||
ENV["hmm"] = nil
|
ENV["hmm"] = nil
|
||||||
IO.popen(ENVCOMMAND) {|io| assert_not_match(/^hmm=/, io.read) }
|
IO.popen(cmd) {|io| assert_not_match(/^hmm=/, io.read, message)}
|
||||||
IO.popen([{"hmm"=>""}, *ENVCOMMAND]) {|io| assert_match(/^hmm=$/, io.read) }
|
IO.popen([{"hmm"=>""}, *cmd]) {|io| assert_match(/^hmm=$/, io.read, message)}
|
||||||
IO.popen([{"hmm"=>nil}, *ENVCOMMAND]) {|io| assert_not_match(/^hmm=/, io.read) }
|
IO.popen([{"hmm"=>nil}, *cmd]) {|io| assert_not_match(/^hmm=/, io.read, message)}
|
||||||
ensure
|
ensure
|
||||||
ENV["hmm"] = old
|
ENV["hmm"] = old
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def test_execopts_env_popen_vector
|
||||||
|
_test_execopts_env_popen(ENVCOMMAND)
|
||||||
|
end
|
||||||
|
|
||||||
|
def test_execopts_env_popen_string
|
||||||
|
with_tmpchdir do |d|
|
||||||
|
open('test-script', 'w') do |f|
|
||||||
|
ENVCOMMAND.each_with_index do |cmd, i|
|
||||||
|
next if i.zero? or cmd == "-e"
|
||||||
|
f.puts cmd
|
||||||
|
end
|
||||||
|
end
|
||||||
|
_test_execopts_env_popen("#{RUBY} test-script")
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
def test_execopts_preserve_env_on_exec_failure
|
def test_execopts_preserve_env_on_exec_failure
|
||||||
with_tmpchdir {|d|
|
with_tmpchdir {|d|
|
||||||
write_file 's', <<-"End"
|
write_file 's', <<-"End"
|
||||||
@ -603,7 +622,7 @@ class TestProcess < Test::Unit::TestCase
|
|||||||
def test_execopts_popen
|
def test_execopts_popen
|
||||||
with_tmpchdir {|d|
|
with_tmpchdir {|d|
|
||||||
IO.popen("#{RUBY} -e 'puts :foo'") {|io| assert_equal("foo\n", io.read) }
|
IO.popen("#{RUBY} -e 'puts :foo'") {|io| assert_equal("foo\n", io.read) }
|
||||||
assert_raise(Errno::ENOENT) { IO.popen(["echo bar"]) {} } # assuming "echo bar" command not exist.
|
IO.popen(["echo bar"]) {|io| assert_equal("bar\n", io.read) }
|
||||||
IO.popen(ECHO["baz"]) {|io| assert_equal("baz\n", io.read) }
|
IO.popen(ECHO["baz"]) {|io| assert_equal("baz\n", io.read) }
|
||||||
assert_raise(ArgumentError) {
|
assert_raise(ArgumentError) {
|
||||||
IO.popen([*ECHO["qux"], STDOUT=>STDOUT]) {|io| }
|
IO.popen([*ECHO["qux"], STDOUT=>STDOUT]) {|io| }
|
||||||
|
Loading…
x
Reference in New Issue
Block a user