1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79
|
# stolen directly from Open3::open3.rb!
#
# open4.rb: Spawn a program like popen, but with stderr, and pid, too. You might
# also want to use this if you want to bypass the shell. (By passing multiple
# args, which IO#popen does not allow)
#
# Usage:
# require "open4"
#
# stdin, stdout, stderr, pid = Open4.popen4('nroff -man')
# or
# include Open4
# stdin, stdout, stderr, pid = popen4('nroff -man')
module Open4
#--{{{
#[stdin, stdout, stderr, pid] = popen4(command);
def popen4(*cmd)
#--{{{
pw = IO::pipe # pipe[0] for read, pipe[1] for write
pr = IO::pipe
pe = IO::pipe
verbose = $VERBOSE
begin
$VERBOSE = nil # shut up warning about forking in threads, world writable
# dirs, etc
cid =
fork{
# child
pw[1].close
STDIN.reopen(pw[0])
pw[0].close
pr[0].close
STDOUT.reopen(pr[1])
pr[1].close
pe[0].close
STDERR.reopen(pe[1])
pe[1].close
STDOUT.sync = true
STDERR.sync = true
exec(*cmd)
}
ensure
$VERBOSE = verbose
end
pw[0].close
pr[1].close
pe[1].close
pi = [pw[1], pr[0], pe[0]]
pw[1].sync = true
if defined? yield
begin
yield(cid, *pi)
return(Process::waitpid2(cid).last)
ensure
pi.each{|p| p.close unless p.closed?}
end
end
[cid, pw[1], pr[0], pe[0]]
#--}}}
end
alias open4 popen4
module_function :popen4
module_function :open4
#--}}}
end
if $0 == __FILE__
status = Open4::popen4('sh'){|cid,i,o,e|i.puts 'echo 42';i.close; puts o.read;}
p [status]
p status.exitstatus
p status == 0
end
|