/*
* call-seq:
* IO.popen(cmd_string, mode="r" ) => io
* IO.popen(cmd_string, mode="r" ) {|io| block } => obj
*
* Runs the specified command string as a subprocess; the subprocess's
* standard input and output will be connected to the returned
* <code>IO</code> object. If <i>cmd_string</i> starts with a
* ``<code>-</code>'', then a new instance of Ruby is started as the
* subprocess. The default mode for the new file object is ``r'', but
* <i>mode</i> may be set to any of the modes listed in the description
* for class IO.
*
* If a block is given, Ruby will run the command as a child connected
* to Ruby with a pipe. Ruby's end of the pipe will be passed as a
* parameter to the block.
* At the end of block, Ruby close the pipe and sets <code>$?</code>.
* In this case <code>IO::popen</code> returns
* the value of the block.
*
* If a block is given with a <i>cmd_string</i> of ``<code>-</code>'',
* the block will be run in two separate processes: once in the parent,
* and once in a child. The parent process will be passed the pipe
* object as a parameter to the block, the child version of the block
* will be passed <code>nil</code>, and the child's standard in and
* standard out will be connected to the parent through the pipe. Not
* available on all platforms.
*
* f = IO.popen("uname")
* p f.readlines
* puts "Parent is #{Process.pid}"
* IO.popen ("date") { |f| puts f.gets }
* IO.popen("-") {|f| $stderr.puts "#{Process.pid} is here, f is #{f}"}
* p $?
*
* <em>produces:</em>
*
* ["Linux\n"]
* Parent is 26166
* Wed Apr 9 08:53:52 CDT 2003
* 26169 is here, f is
* 26166 is here, f is #<IO:0x401b3d44>
* #<Process::Status: pid=26166,exited(0)>
*/
static VALUE
rb_io_s_popen(argc, argv, klass)
int argc;
VALUE *argv;
VALUE klass;
{
char *mode;
VALUE pname, pmode, port;
if (rb_scan_args(argc, argv, "11", &pname, &pmode) == 1) {
mode = "r";
}
else if (FIXNUM_P(pmode)) {
mode = rb_io_modenum_mode(FIX2INT(pmode));
}
else {
mode = rb_io_flags_mode(rb_io_mode_flags(StringValueCStr(pmode)));
}
SafeStringValue(pname);
port = pipe_open(pname, 0, mode);
if (NIL_P(port)) {
/* child */
if (rb_block_given_p()) {
rb_yield(Qnil);
fflush(stdout);
fflush(stderr);
_exit(0);
}
return Qnil;
}
RBASIC(port)->klass = klass;
if (rb_block_given_p()) {
return rb_ensure(rb_yield, port, io_close, port);
}
return port;
}