ahoward-open4 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
@@ -0,0 +1,365 @@
1
+ URIS
2
+
3
+ http://rubyforge.org/projects/codeforpeople/
4
+ http://www.codeforpeople.com/lib/ruby/
5
+
6
+ SYNOPSIS
7
+
8
+ open child process with handles on pid, stdin, stdout, and stderr: manage
9
+ child processes and their io handles easily.
10
+
11
+ INSTALL
12
+
13
+ ~> gem install open4
14
+
15
+ SAMPLES
16
+
17
+ ----------------------------------------------------------------------------
18
+ simple usage
19
+ ----------------------------------------------------------------------------
20
+
21
+ harp: > cat sample/simple.rb
22
+ require "open4"
23
+
24
+ pid, stdin, stdout, stderr = Open4::popen4 "sh"
25
+
26
+ stdin.puts "echo 42.out"
27
+ stdin.puts "echo 42.err 1>&2"
28
+ stdin.close
29
+
30
+ ignored, status = Process::waitpid2 pid
31
+
32
+ puts "pid : #{ pid }"
33
+ puts "stdout : #{ stdout.read.strip }"
34
+ puts "stderr : #{ stderr.read.strip }"
35
+ puts "status : #{ status.inspect }"
36
+ puts "exitstatus : #{ status.exitstatus }"
37
+
38
+
39
+ harp: > ruby sample/simple.rb
40
+ pid : 17273
41
+ stdout : 42.out
42
+ stderr : 42.err
43
+ status : #<Process::Status: pid=17273,exited(0)>
44
+ exitstatus : 0
45
+
46
+
47
+ ----------------------------------------------------------------------------
48
+ in block form - the child process is automatically waited for
49
+ ----------------------------------------------------------------------------
50
+
51
+ harp: > cat sample/block.rb
52
+ require 'open4'
53
+
54
+ status =
55
+ Open4::popen4("sh") do |pid, stdin, stdout, stderr|
56
+ stdin.puts "echo 42.out"
57
+ stdin.puts "echo 42.err 1>&2"
58
+ stdin.close
59
+
60
+ puts "pid : #{ pid }"
61
+ puts "stdout : #{ stdout.read.strip }"
62
+ puts "stderr : #{ stderr.read.strip }"
63
+ end
64
+
65
+ puts "status : #{ status.inspect }"
66
+ puts "exitstatus : #{ status.exitstatus }"
67
+
68
+
69
+ harp: > ruby sample/block.rb
70
+ pid : 17295
71
+ stdout : 42.out
72
+ stderr : 42.err
73
+ status : #<Process::Status: pid=17295,exited(0)>
74
+ exitstatus : 0
75
+
76
+ ----------------------------------------------------------------------------
77
+ exceptions are marshaled from child to parent if fork/exec fails
78
+ ----------------------------------------------------------------------------
79
+
80
+ harp: > cat sample/exception.rb
81
+ require "open4"
82
+ Open4::popen4 "noexist"
83
+
84
+
85
+ harp: > ruby sample/exception.rb
86
+ /dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/open4.rb:100:in `popen4': No such file or directory - noexist (Errno::ENOENT)
87
+ from sample/exception.rb:3
88
+
89
+ ----------------------------------------------------------------------------
90
+ the spawn method provides and even more convenient method of running a
91
+ process, allowing any object that supports 'each', 'read', or 'to_s' to be
92
+ given as stdin and any objects that support '<<' to be given as
93
+ stdout/stderr. an exception is thrown if the exec'd cmd fails (nonzero
94
+ exitstatus) unless the option 'raise'=>false is given
95
+ ----------------------------------------------------------------------------
96
+
97
+ harp: > cat sample/spawn.rb
98
+ require 'open4'
99
+ include Open4
100
+
101
+ cat = ' ruby -e" ARGF.each{|line| STDOUT << line} " '
102
+
103
+ stdout, stderr = '', ''
104
+ status = spawn cat, 'stdin' => '42', 'stdout' => stdout, 'stderr' => stderr
105
+ p status
106
+ p stdout
107
+ p stderr
108
+
109
+ stdout, stderr = '', ''
110
+ status = spawn cat, 0=>'42', 1=>stdout, 2=>stderr
111
+ p status
112
+ p stdout
113
+ p stderr
114
+
115
+
116
+ harp: > RUBYLIB=lib ruby sample/spawn.rb
117
+ 0
118
+ "42"
119
+ ""
120
+ 0
121
+ "42"
122
+ ""
123
+
124
+
125
+ ----------------------------------------------------------------------------
126
+ the bg/background method is similar to spawn, but the process is
127
+ automatically set running in a thread. the returned thread has several
128
+ methods added dynamically which return the pid and blocking calls to the
129
+ exitstatus.
130
+ ----------------------------------------------------------------------------
131
+
132
+ harp: > cat sample/bg.rb
133
+ require 'yaml'
134
+ require 'open4'
135
+ include Open4
136
+
137
+ stdin = '42'
138
+ stdout = ''
139
+ stderr = ''
140
+
141
+ t = bg 'ruby -e"sleep 4; puts ARGF.read"', 0=>stdin, 1=>stdout, 2=>stderr
142
+
143
+ waiter = Thread.new{ y t.pid => t.exitstatus } # t.exitstatus is a blocking call!
144
+
145
+ while((status = t.status))
146
+ y "status" => status
147
+ sleep 1
148
+ end
149
+
150
+ waiter.join
151
+
152
+ y "stdout" => stdout
153
+
154
+
155
+ harp: > ruby sample/bg.rb
156
+ ---
157
+ status: run
158
+ ---
159
+ status: sleep
160
+ ---
161
+ status: sleep
162
+ ---
163
+ status: sleep
164
+ ---
165
+ 21357: 0
166
+ ---
167
+ stdout: "42\n"
168
+
169
+ ----------------------------------------------------------------------------
170
+ the timeout methods can be used to ensure execution is preceding at the
171
+ desired interval. note also how to setup a 'pipeline'
172
+ ----------------------------------------------------------------------------
173
+
174
+ harp: > cat sample/stdin_timeout.rb
175
+ require 'open4'
176
+
177
+ producer = 'ruby -e" STDOUT.sync = true; loop{sleep(rand+rand) and puts 42} "'
178
+
179
+ consumer = 'ruby -e" STDOUT.sync = true; STDIN.each{|line| puts line} "'
180
+
181
+ open4(producer) do |pid, i, o, e|
182
+
183
+ open4.spawn consumer, :stdin=>o, :stdout=>STDOUT, :stdin_timeout => 1.4
184
+
185
+ end
186
+
187
+
188
+ harp: > ruby sample/stdin_timeout.rb
189
+ 42
190
+ 42
191
+ 42
192
+ 42
193
+ 42
194
+ /dmsp/reference/ruby-1.8.1//lib/ruby/1.8/timeout.rb:42:in `relay': execution expired (Timeout::Error)
195
+
196
+ HISTORY
197
+ 1.0.0
198
+ - added ability for spawn to take a proc (respond_to?(:call))
199
+
200
+ cmd = ' ruby -e" 42.times{ puts 0b101010 } " '
201
+ include Open4
202
+ spawn cmd, :stdout => lambda{|buf| puts buf}
203
+
204
+
205
+ 0.9.5:
206
+ - another patch from Corey Jewett, this time dealing with ruby's handling
207
+ of chdir and threads. basically the 'cwd' keyword to open4 cannot work
208
+ with multiple threads (aka background) because ruby cannot cause green
209
+ threads to have an actuall different working dir. the moral is that the
210
+ :cwd/'cwd' keyword to spawn will work with 0 or 1 threads in effect.
211
+
212
+ 0.9.4:
213
+ - patch to #background from Corey Jewett
214
+
215
+
216
+ 0.9.3:
217
+ - removed some debugging output accidentally left in 0.9.2. arggh!
218
+
219
+ 0.9.2:
220
+ - fixed a descriptor leak. thanks Andre Nathan.
221
+
222
+ 0.9.1:
223
+ - fixed warning with '-w' : @cid not initialized. thanks blaise tarr.
224
+
225
+ 0.9.0:
226
+ - added the ability for open4.spawn to take either an array of arguments
227
+ or multiple arguments in order to specify the argv for the command run.
228
+ for example
229
+
230
+ open4.spawn ['touch', 'difficult to "quote"'], :stdout=>STDOUT
231
+
232
+ same thing
233
+
234
+ open4.spawn 'touch', 'difficult to "quote"', :stdout=>STDOUT
235
+
236
+ thanks to jordan breeding for this suggestion
237
+
238
+
239
+ - added 'cwd'/:cwd keyword. usage is pretty obivous
240
+
241
+ open4.spawn 'pwd', 1=>STDOUT, :cwd=>'/tmp' #=> /tmp
242
+
243
+ this one also from jordan
244
+
245
+ 0.8.0:
246
+
247
+ - fixed a critical bug whereby a process producing tons of stdout, but for
248
+ which the stdout was not handled, would cause the child process to
249
+ become blocked/hung writing to the pipe. eg, this command would cause a
250
+ hang
251
+
252
+ include Open4
253
+
254
+ spawn 'ruby -e" puts Array.new(65536){ 42 } "'
255
+
256
+ whereas this one would not
257
+
258
+ include Open4
259
+
260
+ spawn 'ruby -e" puts Array.new(65536){ 42 } "', :stdout=>StringIO.new
261
+
262
+ this version handles the former by spawning a 'null' thread which reads,
263
+ but does not process stdout/stderr. that way commands which generate
264
+ tons of output will never become blocked.
265
+
266
+ 0.7.0:
267
+ - merged functionality of exitstatus/status keywords:
268
+
269
+ include Open4
270
+
271
+ spawn 'ruby -e "exit 42"' # raises
272
+ spawn 'ruby -e "exit 42"', :status=>true # ok, returns status
273
+ spawn 'ruby -e "exit 42"', :status=>42 # raises if status != 42
274
+ spawn 'ruby -e "exit 42"', :status=>0,42 # raises if status != 0||42
275
+
276
+ - the 0.6.0 was broken on rubyforge... this release fixes that (somehow!?)
277
+
278
+ 0.6.0:
279
+ - added feature for exitstatus to be list of acceptable exit statuses
280
+
281
+ Open4.spawn 'ruby -e "exit 42"' # raises
282
+ Open4.spawn 'ruby -e "exit 42"', :exitstatus=>[0,42] # ok
283
+
284
+ - added :status switch, which will always simply return the status (no
285
+ error thrown for failure)
286
+
287
+ Open4.spawn 'ruby -e "exit 42"' # raises
288
+ status = Open4.spawn 'ruby -e "exit 42"', :status=>true # ok
289
+
290
+ note, however, that any SpawnError does in fact contain the failed
291
+ status so, even when they are thrown, error status can be retrieved:
292
+
293
+ include Open4
294
+
295
+ status =
296
+ begin
297
+ spawn 'ruby -e "exit 42"'
298
+ rescue SpawnError => e
299
+ warn{ e }
300
+ e.status
301
+ end
302
+
303
+ 0.5.1:
304
+ - fixes a __critical__ but in ThreadEnsemble class that had a race
305
+ condition that could cause thread deadlock. sorry bout that folks.
306
+
307
+ 0.5.0:
308
+ - on the suggestion of tim pease (thanks tim!), i added timeout features
309
+ to open4. the command run may have an overall timeout and individual
310
+ timeouts set for each of the io handles. for example
311
+
312
+ cmd = 'command_that_produce_out_at_one_second_intervals'
313
+
314
+ open4.spawn cmd, :stdout_timeout => 2
315
+
316
+ or
317
+
318
+ cmd = 'command_that_should_complete_in_about_one_minute'
319
+
320
+ open4.spawn cmd, :timeout => 60
321
+
322
+ or
323
+
324
+ cmd = 'consumes_input_at_one_line_per_second_rate'
325
+
326
+ input = %w( 42 forty-two 42.0 )
327
+
328
+ open4.spawn cmd, :stdin=>input, :stdin_timeout=>1
329
+
330
+ - added 'open4' alias so one can write
331
+
332
+ open4.spawn vs Open4.spawn
333
+
334
+ or even
335
+
336
+ open4(cmd) do |pid,i,o,e|
337
+ end
338
+
339
+ - added signal info to SpawnError
340
+
341
+ 0.4.0:
342
+ - improved error handling contributed by jordan breeding.
343
+ - introduction of background/bg method
344
+
345
+ 0.3.0 :
346
+ - bug fix from jordan breeding. general clean up. added spawn method.
347
+
348
+ 0.2.0 :
349
+ - added exception marshaled from child -> parent when exec fails. thanks
350
+ to jordan breeding for a patch (yay!) and paul brannan for this most
351
+ excellent idea.
352
+
353
+ 0.1.0 :
354
+ - fixed docs to correctly show return value of popen4 (pid first not last).
355
+ thanks Stefanie Tellex <stefie10@alum.mit.edu> for catching this.
356
+ 0.0.0 :
357
+ - initial version
358
+
359
+ AUTHOR
360
+
361
+ ara.t.howard@gmail.com
362
+
363
+ LICENSE
364
+
365
+ ruby's
data/README.erb ADDED
@@ -0,0 +1,365 @@
1
+ URIS
2
+
3
+ http://rubyforge.org/projects/codeforpeople/
4
+ http://www.codeforpeople.com/lib/ruby/
5
+
6
+ SYNOPSIS
7
+
8
+ open child process with handles on pid, stdin, stdout, and stderr: manage
9
+ child processes and their io handles easily.
10
+
11
+ INSTALL
12
+
13
+ ~> gem install open4
14
+
15
+ SAMPLES
16
+
17
+ ----------------------------------------------------------------------------
18
+ simple usage
19
+ ----------------------------------------------------------------------------
20
+
21
+ harp: > cat sample/simple.rb
22
+ require "open4"
23
+
24
+ pid, stdin, stdout, stderr = Open4::popen4 "sh"
25
+
26
+ stdin.puts "echo 42.out"
27
+ stdin.puts "echo 42.err 1>&2"
28
+ stdin.close
29
+
30
+ ignored, status = Process::waitpid2 pid
31
+
32
+ puts "pid : #{ pid }"
33
+ puts "stdout : #{ stdout.read.strip }"
34
+ puts "stderr : #{ stderr.read.strip }"
35
+ puts "status : #{ status.inspect }"
36
+ puts "exitstatus : #{ status.exitstatus }"
37
+
38
+
39
+ harp: > ruby sample/simple.rb
40
+ pid : 17273
41
+ stdout : 42.out
42
+ stderr : 42.err
43
+ status : #<Process::Status: pid=17273,exited(0)>
44
+ exitstatus : 0
45
+
46
+
47
+ ----------------------------------------------------------------------------
48
+ in block form - the child process is automatically waited for
49
+ ----------------------------------------------------------------------------
50
+
51
+ harp: > cat sample/block.rb
52
+ require 'open4'
53
+
54
+ status =
55
+ Open4::popen4("sh") do |pid, stdin, stdout, stderr|
56
+ stdin.puts "echo 42.out"
57
+ stdin.puts "echo 42.err 1>&2"
58
+ stdin.close
59
+
60
+ puts "pid : #{ pid }"
61
+ puts "stdout : #{ stdout.read.strip }"
62
+ puts "stderr : #{ stderr.read.strip }"
63
+ end
64
+
65
+ puts "status : #{ status.inspect }"
66
+ puts "exitstatus : #{ status.exitstatus }"
67
+
68
+
69
+ harp: > ruby sample/block.rb
70
+ pid : 17295
71
+ stdout : 42.out
72
+ stderr : 42.err
73
+ status : #<Process::Status: pid=17295,exited(0)>
74
+ exitstatus : 0
75
+
76
+ ----------------------------------------------------------------------------
77
+ exceptions are marshaled from child to parent if fork/exec fails
78
+ ----------------------------------------------------------------------------
79
+
80
+ harp: > cat sample/exception.rb
81
+ require "open4"
82
+ Open4::popen4 "noexist"
83
+
84
+
85
+ harp: > ruby sample/exception.rb
86
+ /dmsp/reference/ruby-1.8.1//lib/ruby/site_ruby/open4.rb:100:in `popen4': No such file or directory - noexist (Errno::ENOENT)
87
+ from sample/exception.rb:3
88
+
89
+ ----------------------------------------------------------------------------
90
+ the spawn method provides and even more convenient method of running a
91
+ process, allowing any object that supports 'each', 'read', or 'to_s' to be
92
+ given as stdin and any objects that support '<<' to be given as
93
+ stdout/stderr. an exception is thrown if the exec'd cmd fails (nonzero
94
+ exitstatus) unless the option 'raise'=>false is given
95
+ ----------------------------------------------------------------------------
96
+
97
+ harp: > cat sample/spawn.rb
98
+ require 'open4'
99
+ include Open4
100
+
101
+ cat = ' ruby -e" ARGF.each{|line| STDOUT << line} " '
102
+
103
+ stdout, stderr = '', ''
104
+ status = spawn cat, 'stdin' => '42', 'stdout' => stdout, 'stderr' => stderr
105
+ p status
106
+ p stdout
107
+ p stderr
108
+
109
+ stdout, stderr = '', ''
110
+ status = spawn cat, 0=>'42', 1=>stdout, 2=>stderr
111
+ p status
112
+ p stdout
113
+ p stderr
114
+
115
+
116
+ harp: > RUBYLIB=lib ruby sample/spawn.rb
117
+ 0
118
+ "42"
119
+ ""
120
+ 0
121
+ "42"
122
+ ""
123
+
124
+
125
+ ----------------------------------------------------------------------------
126
+ the bg/background method is similar to spawn, but the process is
127
+ automatically set running in a thread. the returned thread has several
128
+ methods added dynamically which return the pid and blocking calls to the
129
+ exitstatus.
130
+ ----------------------------------------------------------------------------
131
+
132
+ harp: > cat sample/bg.rb
133
+ require 'yaml'
134
+ require 'open4'
135
+ include Open4
136
+
137
+ stdin = '42'
138
+ stdout = ''
139
+ stderr = ''
140
+
141
+ t = bg 'ruby -e"sleep 4; puts ARGF.read"', 0=>stdin, 1=>stdout, 2=>stderr
142
+
143
+ waiter = Thread.new{ y t.pid => t.exitstatus } # t.exitstatus is a blocking call!
144
+
145
+ while((status = t.status))
146
+ y "status" => status
147
+ sleep 1
148
+ end
149
+
150
+ waiter.join
151
+
152
+ y "stdout" => stdout
153
+
154
+
155
+ harp: > ruby sample/bg.rb
156
+ ---
157
+ status: run
158
+ ---
159
+ status: sleep
160
+ ---
161
+ status: sleep
162
+ ---
163
+ status: sleep
164
+ ---
165
+ 21357: 0
166
+ ---
167
+ stdout: "42\n"
168
+
169
+ ----------------------------------------------------------------------------
170
+ the timeout methods can be used to ensure execution is preceding at the
171
+ desired interval. note also how to setup a 'pipeline'
172
+ ----------------------------------------------------------------------------
173
+
174
+ harp: > cat sample/stdin_timeout.rb
175
+ require 'open4'
176
+
177
+ producer = 'ruby -e" STDOUT.sync = true; loop{sleep(rand+rand) and puts 42} "'
178
+
179
+ consumer = 'ruby -e" STDOUT.sync = true; STDIN.each{|line| puts line} "'
180
+
181
+ open4(producer) do |pid, i, o, e|
182
+
183
+ open4.spawn consumer, :stdin=>o, :stdout=>STDOUT, :stdin_timeout => 1.4
184
+
185
+ end
186
+
187
+
188
+ harp: > ruby sample/stdin_timeout.rb
189
+ 42
190
+ 42
191
+ 42
192
+ 42
193
+ 42
194
+ /dmsp/reference/ruby-1.8.1//lib/ruby/1.8/timeout.rb:42:in `relay': execution expired (Timeout::Error)
195
+
196
+ HISTORY
197
+ 1.0.0
198
+ - added ability for spawn to take a proc (respond_to?(:call))
199
+
200
+ cmd = ' ruby -e" 42.times{ puts 0b101010 } " '
201
+ include Open4
202
+ spawn cmd, :stdout => lambda{|buf| puts buf}
203
+
204
+
205
+ 0.9.5:
206
+ - another patch from Corey Jewett, this time dealing with ruby's handling
207
+ of chdir and threads. basically the 'cwd' keyword to open4 cannot work
208
+ with multiple threads (aka background) because ruby cannot cause green
209
+ threads to have an actuall different working dir. the moral is that the
210
+ :cwd/'cwd' keyword to spawn will work with 0 or 1 threads in effect.
211
+
212
+ 0.9.4:
213
+ - patch to #background from Corey Jewett
214
+
215
+
216
+ 0.9.3:
217
+ - removed some debugging output accidentally left in 0.9.2. arggh!
218
+
219
+ 0.9.2:
220
+ - fixed a descriptor leak. thanks Andre Nathan.
221
+
222
+ 0.9.1:
223
+ - fixed warning with '-w' : @cid not initialized. thanks blaise tarr.
224
+
225
+ 0.9.0:
226
+ - added the ability for open4.spawn to take either an array of arguments
227
+ or multiple arguments in order to specify the argv for the command run.
228
+ for example
229
+
230
+ open4.spawn ['touch', 'difficult to "quote"'], :stdout=>STDOUT
231
+
232
+ same thing
233
+
234
+ open4.spawn 'touch', 'difficult to "quote"', :stdout=>STDOUT
235
+
236
+ thanks to jordan breeding for this suggestion
237
+
238
+
239
+ - added 'cwd'/:cwd keyword. usage is pretty obivous
240
+
241
+ open4.spawn 'pwd', 1=>STDOUT, :cwd=>'/tmp' #=> /tmp
242
+
243
+ this one also from jordan
244
+
245
+ 0.8.0:
246
+
247
+ - fixed a critical bug whereby a process producing tons of stdout, but for
248
+ which the stdout was not handled, would cause the child process to
249
+ become blocked/hung writing to the pipe. eg, this command would cause a
250
+ hang
251
+
252
+ include Open4
253
+
254
+ spawn 'ruby -e" puts Array.new(65536){ 42 } "'
255
+
256
+ whereas this one would not
257
+
258
+ include Open4
259
+
260
+ spawn 'ruby -e" puts Array.new(65536){ 42 } "', :stdout=>StringIO.new
261
+
262
+ this version handles the former by spawning a 'null' thread which reads,
263
+ but does not process stdout/stderr. that way commands which generate
264
+ tons of output will never become blocked.
265
+
266
+ 0.7.0:
267
+ - merged functionality of exitstatus/status keywords:
268
+
269
+ include Open4
270
+
271
+ spawn 'ruby -e "exit 42"' # raises
272
+ spawn 'ruby -e "exit 42"', :status=>true # ok, returns status
273
+ spawn 'ruby -e "exit 42"', :status=>42 # raises if status != 42
274
+ spawn 'ruby -e "exit 42"', :status=>0,42 # raises if status != 0||42
275
+
276
+ - the 0.6.0 was broken on rubyforge... this release fixes that (somehow!?)
277
+
278
+ 0.6.0:
279
+ - added feature for exitstatus to be list of acceptable exit statuses
280
+
281
+ Open4.spawn 'ruby -e "exit 42"' # raises
282
+ Open4.spawn 'ruby -e "exit 42"', :exitstatus=>[0,42] # ok
283
+
284
+ - added :status switch, which will always simply return the status (no
285
+ error thrown for failure)
286
+
287
+ Open4.spawn 'ruby -e "exit 42"' # raises
288
+ status = Open4.spawn 'ruby -e "exit 42"', :status=>true # ok
289
+
290
+ note, however, that any SpawnError does in fact contain the failed
291
+ status so, even when they are thrown, error status can be retrieved:
292
+
293
+ include Open4
294
+
295
+ status =
296
+ begin
297
+ spawn 'ruby -e "exit 42"'
298
+ rescue SpawnError => e
299
+ warn{ e }
300
+ e.status
301
+ end
302
+
303
+ 0.5.1:
304
+ - fixes a __critical__ but in ThreadEnsemble class that had a race
305
+ condition that could cause thread deadlock. sorry bout that folks.
306
+
307
+ 0.5.0:
308
+ - on the suggestion of tim pease (thanks tim!), i added timeout features
309
+ to open4. the command run may have an overall timeout and individual
310
+ timeouts set for each of the io handles. for example
311
+
312
+ cmd = 'command_that_produce_out_at_one_second_intervals'
313
+
314
+ open4.spawn cmd, :stdout_timeout => 2
315
+
316
+ or
317
+
318
+ cmd = 'command_that_should_complete_in_about_one_minute'
319
+
320
+ open4.spawn cmd, :timeout => 60
321
+
322
+ or
323
+
324
+ cmd = 'consumes_input_at_one_line_per_second_rate'
325
+
326
+ input = %w( 42 forty-two 42.0 )
327
+
328
+ open4.spawn cmd, :stdin=>input, :stdin_timeout=>1
329
+
330
+ - added 'open4' alias so one can write
331
+
332
+ open4.spawn vs Open4.spawn
333
+
334
+ or even
335
+
336
+ open4(cmd) do |pid,i,o,e|
337
+ end
338
+
339
+ - added signal info to SpawnError
340
+
341
+ 0.4.0:
342
+ - improved error handling contributed by jordan breeding.
343
+ - introduction of background/bg method
344
+
345
+ 0.3.0 :
346
+ - bug fix from jordan breeding. general clean up. added spawn method.
347
+
348
+ 0.2.0 :
349
+ - added exception marshaled from child -> parent when exec fails. thanks
350
+ to jordan breeding for a patch (yay!) and paul brannan for this most
351
+ excellent idea.
352
+
353
+ 0.1.0 :
354
+ - fixed docs to correctly show return value of popen4 (pid first not last).
355
+ thanks Stefanie Tellex <stefie10@alum.mit.edu> for catching this.
356
+ 0.0.0 :
357
+ - initial version
358
+
359
+ AUTHOR
360
+
361
+ ara.t.howard@gmail.com
362
+
363
+ LICENSE
364
+
365
+ ruby's