Module: Open4

Defined in:
lib/open4.rb

Overview

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')

Class Method Summary collapse

Class Method Details

.open4Object

stdin, stdout, stderr, pid

popen4(command);

–}}}



68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
# File 'lib/open4.rb', line 68

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

.popen4(*cmd) ⇒ Object

stdin, stdout, stderr, pid

popen4(command);



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
# File 'lib/open4.rb', line 18

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