1 | #
|
---|
2 | # = open3.rb: Popen, but with stderr, too
|
---|
3 | #
|
---|
4 | # Author:: Yukihiro Matsumoto
|
---|
5 | # Documentation:: Konrad Meyer
|
---|
6 | #
|
---|
7 | # Open3 gives you access to stdin, stdout, and stderr when running other
|
---|
8 | # programs.
|
---|
9 | #
|
---|
10 |
|
---|
11 | #
|
---|
12 | # Open3 grants you access to stdin, stdout, and stderr when running another
|
---|
13 | # program. Example:
|
---|
14 | #
|
---|
15 | # require "open3"
|
---|
16 | # include Open3
|
---|
17 | #
|
---|
18 | # stdin, stdout, stderr = popen3('nroff -man')
|
---|
19 | #
|
---|
20 | # Open3.popen3 can also take a block which will receive stdin, stdout and
|
---|
21 | # stderr as parameters. This ensures stdin, stdout and stderr are closed
|
---|
22 | # once the block exits. Example:
|
---|
23 | #
|
---|
24 | # require "open3"
|
---|
25 | #
|
---|
26 | # Open3.popen3('nroff -man') { |stdin, stdout, stderr| ... }
|
---|
27 | #
|
---|
28 |
|
---|
29 | module Open3
|
---|
30 | #
|
---|
31 | # Open stdin, stdout, and stderr streams and start external executable.
|
---|
32 | # Non-block form:
|
---|
33 | #
|
---|
34 | # require 'open3'
|
---|
35 | #
|
---|
36 | # [stdin, stdout, stderr] = Open3.popen3(cmd)
|
---|
37 | #
|
---|
38 | # Block form:
|
---|
39 | #
|
---|
40 | # require 'open3'
|
---|
41 | #
|
---|
42 | # Open3.popen3(cmd) { |stdin, stdout, stderr| ... }
|
---|
43 | #
|
---|
44 | # The parameter +cmd+ is passed directly to Kernel#exec.
|
---|
45 | #
|
---|
46 | def popen3(*cmd)
|
---|
47 | pw = IO::pipe # pipe[0] for read, pipe[1] for write
|
---|
48 | pr = IO::pipe
|
---|
49 | pe = IO::pipe
|
---|
50 |
|
---|
51 | pid = fork{
|
---|
52 | # child
|
---|
53 | fork{
|
---|
54 | # grandchild
|
---|
55 | pw[1].close
|
---|
56 | STDIN.reopen(pw[0])
|
---|
57 | pw[0].close
|
---|
58 |
|
---|
59 | pr[0].close
|
---|
60 | STDOUT.reopen(pr[1])
|
---|
61 | pr[1].close
|
---|
62 |
|
---|
63 | pe[0].close
|
---|
64 | STDERR.reopen(pe[1])
|
---|
65 | pe[1].close
|
---|
66 |
|
---|
67 | exec(*cmd)
|
---|
68 | }
|
---|
69 | exit!(0)
|
---|
70 | }
|
---|
71 |
|
---|
72 | pw[0].close
|
---|
73 | pr[1].close
|
---|
74 | pe[1].close
|
---|
75 | Process.waitpid(pid)
|
---|
76 | pi = [pw[1], pr[0], pe[0]]
|
---|
77 | pw[1].sync = true
|
---|
78 | if defined? yield
|
---|
79 | begin
|
---|
80 | return yield(*pi)
|
---|
81 | ensure
|
---|
82 | pi.each{|p| p.close unless p.closed?}
|
---|
83 | end
|
---|
84 | end
|
---|
85 | pi
|
---|
86 | end
|
---|
87 | module_function :popen3
|
---|
88 | end
|
---|
89 |
|
---|
90 | if $0 == __FILE__
|
---|
91 | a = Open3.popen3("nroff -man")
|
---|
92 | Thread.start do
|
---|
93 | while line = gets
|
---|
94 | a[0].print line
|
---|
95 | end
|
---|
96 | a[0].close
|
---|
97 | end
|
---|
98 | while line = a[1].gets
|
---|
99 | print ":", line
|
---|
100 | end
|
---|
101 | end
|
---|