wopen3 0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (2) hide show
  1. data/lib/wopen3.rb +89 -0
  2. metadata +46 -0
data/lib/wopen3.rb ADDED
@@ -0,0 +1,89 @@
1
+ # Copyright 2007 Wincent Colaiuta
2
+ # $Id$
3
+
4
+ # Wopen3 is a replacement for Open3.
5
+ #
6
+ # Unlike Open3, Wopen3 does not throw away the exit code of the executed (grandchild) process.
7
+ # Only a child process is spawned and the exit status is returned in $? as normal.
8
+ #
9
+ # Usage example:
10
+ #
11
+ # result, errors = '', ''
12
+ # Wopen3.popen3('svn', 'log') do |stdin, stdout, stderr|
13
+ # threads = []
14
+ # threads << Thread.new(stdout) do |out|
15
+ # out.each { |line| result << line }
16
+ # end
17
+ # threads << Thread.new(stderr) do |err|
18
+ # err.each { |line| errors << line }
19
+ # end
20
+ # threads.each { |thread| thread.join }
21
+ # end
22
+ # status = $?.exitstatus
23
+ # raise "Non-zero exit status #{status}" if status != 0
24
+ #
25
+ #
26
+ module Wopen3
27
+
28
+ class Opener
29
+
30
+ READ = 0
31
+ WRITE = 1
32
+
33
+ def initialize(*cmd)
34
+
35
+ write_pipe = IO::pipe
36
+ read_pipe = IO::pipe
37
+ error_pipe = IO::pipe
38
+
39
+ pid = fork do
40
+
41
+ # in child
42
+ write_pipe[WRITE].close
43
+ STDIN.reopen(write_pipe[READ]) # file descriptor duplicated here
44
+ write_pipe[READ].close # must close in order for parent to see EOF
45
+
46
+ read_pipe[READ].close
47
+ STDOUT.reopen(read_pipe[WRITE])
48
+ read_pipe[WRITE].close
49
+
50
+ error_pipe[READ].close
51
+ STDERR.reopen(error_pipe[WRITE])
52
+ error_pipe[WRITE].close
53
+
54
+ exec(*cmd) # will raise SystemCallError if command can't be executed (eg Errno::NOENT)
55
+ exit! # should never get here
56
+
57
+ end
58
+
59
+ # in parent
60
+ write_pipe[READ].close
61
+ read_pipe[WRITE].close
62
+ error_pipe[WRITE].close
63
+
64
+ pipes = [write_pipe[WRITE], read_pipe[READ], error_pipe[READ]]
65
+ write_pipe[WRITE].sync = true
66
+
67
+ if defined? yield
68
+ begin
69
+ result = yield(*pipes)
70
+ Process.waitpid(pid) # global $? gets set here
71
+ return result
72
+ ensure
73
+ pipes.each { |pipe| pipe.close unless pipe.closed? }
74
+ end
75
+ end
76
+
77
+ # can't wait immediately (will hang); wait once garbage collection destroys/finalizes this instance
78
+ ObjectSpace.define_finalizer(self, proc { Process.waitpid(pid) })
79
+ pipes
80
+
81
+ end
82
+
83
+ end
84
+
85
+ def self.popen3(*cmd, &block)
86
+ Opener.new(*cmd, &block)
87
+ end
88
+
89
+ end # module Wopen3
metadata ADDED
@@ -0,0 +1,46 @@
1
+ --- !ruby/object:Gem::Specification
2
+ rubygems_version: 0.9.2
3
+ specification_version: 1
4
+ name: wopen3
5
+ version: !ruby/object:Gem::Version
6
+ version: "0.1"
7
+ date: 2007-04-12 00:00:00 +02:00
8
+ summary: Wopen3 is a simple replacement for Open3.
9
+ require_paths:
10
+ - lib
11
+ email: win@wincent.com
12
+ homepage: http://wincent.com/a/products/walrus/wopen3/
13
+ rubyforge_project:
14
+ description: Unlike Open3, Wopen3 does not throw away the exit code of the executed (grandchild) process. Only a child process is spawned and the exit status is returned in $? as normal.
15
+ autorequire: wopen3
16
+ default_executable:
17
+ bindir: bin
18
+ has_rdoc: false
19
+ required_ruby_version: !ruby/object:Gem::Version::Requirement
20
+ requirements:
21
+ - - ">"
22
+ - !ruby/object:Gem::Version
23
+ version: 0.0.0
24
+ version:
25
+ platform: ruby
26
+ signing_key:
27
+ cert_chain:
28
+ post_install_message:
29
+ authors:
30
+ - Wincent Colaiuta
31
+ files:
32
+ - lib/wopen3.rb
33
+ test_files: []
34
+
35
+ rdoc_options: []
36
+
37
+ extra_rdoc_files: []
38
+
39
+ executables: []
40
+
41
+ extensions: []
42
+
43
+ requirements: []
44
+
45
+ dependencies: []
46
+