popen4 0.1.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (7) hide show
  1. data/CHANGES +7 -0
  2. data/LICENSE +71 -0
  3. data/README.rdoc +50 -0
  4. data/Rakefile +131 -0
  5. data/lib/popen4.rb +100 -0
  6. data/tests/popen4_test.rb +79 -0
  7. metadata +80 -0
data/CHANGES ADDED
@@ -0,0 +1,7 @@
1
+ == 0.1.1 - 12-Jun-2006
2
+ * Fixed Bug 4742
3
+ - open3.so Open4 fails to return Process::Status on Windows 2000.
4
+ - Thanks to Park Heesob!
5
+
6
+ == 0.1.0 - 10-Jun-2006
7
+ * Initial release
data/LICENSE ADDED
@@ -0,0 +1,71 @@
1
+ == POpen4 License
2
+
3
+ POpen4 is copyright John-Mason P. Shackelford (john-mason@shackelford.org)
4
+ and made available under the terms of Ruby's license, included below for your
5
+ convenience.
6
+
7
+ == win32-open3 License
8
+
9
+ The the win32-open3 library may be included in this distribution of POpen4. If
10
+ so, POpen4 users must also comply with the terms of its license. Park Heesob and
11
+ Daniel Berger hold the copyright on most of the win32-open3 code which also
12
+ happens to be licensed under the same terms as Ruby.
13
+
14
+ == Ruby's License
15
+
16
+ Ruby is copyrighted free software by Yukihiro Matsumoto <matz@netlab.jp>.
17
+ You can redistribute it and/or modify it under either the terms of the GPL
18
+ (see the file GPL), or the conditions below:
19
+
20
+ 1. You may make and give away verbatim copies of the source form of the
21
+ software without restriction, provided that you duplicate all of the
22
+ original copyright notices and associated disclaimers.
23
+
24
+ 2. You may modify your copy of the software in any way, provided that
25
+ you do at least ONE of the following:
26
+
27
+ a) place your modifications in the Public Domain or otherwise
28
+ make them Freely Available, such as by posting said
29
+ modifications to Usenet or an equivalent medium, or by allowing
30
+ the author to include your modifications in the software.
31
+
32
+ b) use the modified software only within your corporation or
33
+ organization.
34
+
35
+ c) give non-standard binaries non-standard names, with
36
+ instructions on where to get the original software distribution.
37
+
38
+ d) make other distribution arrangements with the author.
39
+
40
+ 3. You may distribute the software in object code or binary form,
41
+ provided that you do at least ONE of the following:
42
+
43
+ a) distribute the binaries and library files of the software,
44
+ together with instructions (in the manual page or equivalent)
45
+ on where to get the original distribution.
46
+
47
+ b) accompany the distribution with the machine-readable source of
48
+ the software.
49
+
50
+ c) give non-standard binaries non-standard names, with
51
+ instructions on where to get the original software distribution.
52
+
53
+ d) make other distribution arrangements with the author.
54
+
55
+ 4. You may modify and include the part of the software into any other
56
+ software (possibly commercial). But some files in the distribution
57
+ are not written by the author, so that they are not under these terms.
58
+
59
+ For the list of those files and their copying conditions, see the
60
+ file LEGAL.
61
+
62
+ 5. The scripts and library files supplied as input to or produced as
63
+ output from the software do not automatically fall under the
64
+ copyright of the software, but belong to whomever generated them,
65
+ and may be sold commercially, and may be aggregated with this
66
+ software.
67
+
68
+ 6. THIS SOFTWARE IS PROVIDED "AS IS" AND WITHOUT ANY EXPRESS OR
69
+ IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED
70
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
71
+ PURPOSE.
@@ -0,0 +1,50 @@
1
+ == Description
2
+ POpen4 provides the Rubyist a single API across platforms for executing a
3
+ command in a child process with handles on stdout, stderr, stdin streams as well
4
+ as access to the process ID and exit status. It does very little other than to
5
+ provide an easy way to use either Ara Howard's Open4 library or the win32-popen3
6
+ library by Park Heesob and Daniel Berger depending on your platform and without
7
+ having to code around the slight differences in their APIs.
8
+
9
+ Consider this my first attempt at a response to
10
+ {Daniel's request}[http://groups.google.com/group/comp.lang.ruby/msg/44ba016610fa8878]
11
+ for a consensus on the API back in 2005.
12
+
13
+ It is my hope that this project will be shortly absorbed or replaced with a
14
+ better solution. POpen4 offers very little in the way of features or
15
+ flexibility, but it does work across platforms without extra coding.
16
+ == Notes
17
+ Rather than adopting either Open4's API or win32-open3's (they differ in several
18
+ respects, but most obviously in the order in which streams are passed to the
19
+ block) I am proposing a third API for couple of reasons. First, Open4 passes the
20
+ PID first and win32-open3 passes stdin neither of which seem to me to be the
21
+ streams we are most likely to use when we don't need all four. POpen4 passes
22
+ stdout and stderr first so that when the others are not required we can omit
23
+ them from the block. Second, I thought it best to break everybody's code rather
24
+ than to be a drop in replacement on one platform and be a surprise on another.
25
+ No surprises--it's a new API on either platform.
26
+
27
+ == Installation
28
+
29
+ $ gem install --remote --include-dependencies POpen4
30
+
31
+ Presently POpen4 ships in four platform specific gems:
32
+
33
+ POpen4-0.1.0-unix.gem
34
+ POpen4-0.1.0-win32-1.8.2-VC7.gem
35
+ POpen4-0.1.0-win32-1.8.4-VC6.gem
36
+ POpen4-0.1.0-win32-source.gem
37
+
38
+ Users of Linux, Unix, BSD, etc., will want the unix package. Ara's Open4 gem
39
+ is a dependency. Users of the Ruby One-Click Installer (OCI) will want to select
40
+ the gem appropriate their version of Ruby. The real issue here is compiler
41
+ version. The wrong version will SEGFAULT due to some incompatibility somewhere
42
+ in the VC++ compiler or libraries (which I really wish we could resolve,
43
+ but oh well). Others using a Windows platform but not the OCI will want to
44
+ compile from source using last of these gems. Be sure to have your environment
45
+ set up for doing a build before running <tt>gem install POpen4</tt>.
46
+
47
+ == Acknowledgements
48
+ Ara Howard, Park Heesob, Daniel Berger and others have done the real work. Many
49
+ thanks to them for the many hours they have poured into sharing their work with
50
+ the Ruby community at large.
@@ -0,0 +1,131 @@
1
+ require 'rubygems'
2
+ require 'rubygems/user_interaction'
3
+ require 'rake/gempackagetask'
4
+ require 'rake/testtask'
5
+ require 'rake/rdoctask'
6
+
7
+ PROJECT_VERSION = "0.1.1"
8
+
9
+ task :default => [:test]
10
+
11
+ # Test --------------------------------------------------------------------
12
+
13
+ desc "Run the unit tests"
14
+ task :test do
15
+ Rake::TestTask.new("test") do |t|
16
+ t.libs << "tests"
17
+ t.pattern = 'tests/*_test.rb'
18
+ t.verbose = true
19
+ end
20
+ end
21
+
22
+ # Documentation -----------------------------------------------------------
23
+ desc "Generate RDoc"
24
+ rd = Rake::RDocTask.new("rdoc") { |rdoc|
25
+ rdoc.rdoc_dir = 'rdoc'
26
+ rdoc.title = "POpen4 -- Open4 cross-platform"
27
+ rdoc.options << '--main' << 'README'
28
+ rdoc.rdoc_files.include('README', 'LICENSE', 'CHANGES')
29
+ rdoc.rdoc_files.include('lib/**/*.rb', 'doc/**/*.rdoc').exclude('lib/open3.rb')
30
+ }
31
+
32
+ # GEM Packaging -----------------------------------------------------------
33
+
34
+ POPEN4_GENERIC = FileList["{tests,lib}/popen4*.rb"].add('*').to_a
35
+
36
+ # -- WIN32 1.8.2 ----------------
37
+
38
+ spec = Gem::Specification.new do |s|
39
+ s.name = "POpen4"
40
+ s.version = PROJECT_VERSION
41
+ s.author = "John-Mason P. Shackelford"
42
+ s.email = "john-mason@shackelford.org"
43
+ s.platform = 'win32-1.8.2-VC7'
44
+ s.summary = "Open4 cross-platform"
45
+ s.files = POPEN4_GENERIC + FileList['lib/1.8.2*/*', 'lib/open3.rb'].to_a
46
+ s.require_path = "lib"
47
+ s.autorequire = "popen4.rb"
48
+ s.has_rdoc = true
49
+ s.add_dependency("Platform", ">= 0.4.0")
50
+ end
51
+
52
+ task :package => [:test]
53
+ Rake::GemPackageTask.new( spec ) do |pkg|
54
+ pkg.gem_spec = spec
55
+ pkg.need_zip = false
56
+ pkg.need_tar = false
57
+ end
58
+
59
+ # -- WIN32 1.8.4 ----------------
60
+
61
+ spec = Gem::Specification.new do |s|
62
+ s.name = "POpen4"
63
+ s.version = PROJECT_VERSION
64
+ s.author = "John-Mason P. Shackelford"
65
+ s.email = "john-mason@shackelford.org"
66
+ s.platform = 'win32-1.8.4-VC6'
67
+ s.summary = "Open4 cross-platform"
68
+ s.files = POPEN4_GENERIC + FileList['lib/1.8.4*/*', 'lib/open3.rb'].to_a
69
+ s.require_path = "lib"
70
+ s.autorequire = "popen4.rb"
71
+ s.has_rdoc = true
72
+ s.add_dependency("Platform", ">= 0.4.0")
73
+ end
74
+
75
+ task :package => [:test]
76
+ Rake::GemPackageTask.new( spec ) do |pkg|
77
+ pkg.gem_spec = spec
78
+ pkg.need_zip = false
79
+ pkg.need_tar = false
80
+ end
81
+
82
+ # -- WIN32 src-only ----------------
83
+
84
+ spec = Gem::Specification.new do |s|
85
+ s.name = "POpen4"
86
+ s.version = PROJECT_VERSION
87
+ s.author = "John-Mason P. Shackelford"
88
+ s.email = "john-mason@shackelford.org"
89
+ s.platform = 'win32-source'
90
+ s.summary = "Open4 cross-platform"
91
+ s.files = POPEN4_GENERIC + FileList['{ext}/**/*','lib/open3.rb'].to_a
92
+ s.require_path = "lib"
93
+ s.autorequire = "popen4.rb"
94
+ s.has_rdoc = true
95
+ s.add_dependency("Platform", ">= 0.4.0")
96
+ s.extensions << 'ext/win32-open3/extconf.rb'
97
+ end
98
+
99
+ task :package => [:test]
100
+ Rake::GemPackageTask.new( spec ) do |pkg|
101
+ pkg.gem_spec = spec
102
+ pkg.need_zip = false
103
+ pkg.need_tar = false
104
+ end
105
+
106
+ # -- Unix / OS X / BSD / Linux ----------------
107
+
108
+ spec = Gem::Specification.new do |s|
109
+ s.name = "POpen4"
110
+ s.version = PROJECT_VERSION
111
+ s.author = "John-Mason P. Shackelford"
112
+ s.email = "john-mason@shackelford.org"
113
+ s.platform = 'unix'
114
+ s.summary = "Open4 cross-platform"
115
+ s.files = POPEN4_GENERIC
116
+ s.require_path = "lib"
117
+ s.autorequire = "popen4.rb"
118
+ s.has_rdoc = true
119
+ s.add_dependency("Platform", ">= 0.4.0")
120
+ s.add_dependency("open4", ">= 0.4.0")
121
+ end
122
+
123
+ task :package => [:test]
124
+ Rake::GemPackageTask.new( spec ) do |pkg|
125
+ pkg.gem_spec = spec
126
+ pkg.need_zip = false
127
+ pkg.need_tar = false
128
+ end
129
+
130
+
131
+
@@ -0,0 +1,100 @@
1
+ require 'rubygems'
2
+ require 'platform'
3
+ #require_gem 'Platform', '>= 0.4.0'
4
+
5
+ case Platform::OS
6
+
7
+ # win32/popen4 yields stdin, stdout, stderr and pid, respectively
8
+ when :win32
9
+
10
+ require File.join( File.dirname( __FILE__ ), 'open3')
11
+
12
+ # POpen4 provides the Rubyist a single API across platforms for executing a
13
+ # command in a child process with handles on stdout, stderr, and stdin streams
14
+ # as well as access to the process ID and exit status.
15
+ #
16
+ # Consider the following example (borrowed from Open4):
17
+ #
18
+ # require 'rubygems'
19
+ # require 'popen4'
20
+ #
21
+ # status =
22
+ # POpen4::popen4("cmd") do |stdout, stderr, stdin, pid|
23
+ # stdin.puts "echo hello world!"
24
+ # stdin.puts "echo ERROR! 1>&2"
25
+ # stdin.puts "exit"
26
+ # stdin.close
27
+ #
28
+ # puts "pid : #{ pid }"
29
+ # puts "stdout : #{ stdout.read.strip }"
30
+ # puts "stderr : #{ stderr.read.strip }"
31
+ # end
32
+ #
33
+ # puts "status : #{ status.inspect }"
34
+ # puts "exitstatus : #{ status.exitstatus }"
35
+ #
36
+ module POpen4
37
+ # Starts a new process and hands IO objects representing the subprocess
38
+ # stdout, stderr, stdin streams and the pid (respectively) to the block
39
+ # supplied. If the command could not be started, return nil.
40
+ #
41
+ # The mode argument may be set to t[ext] or b[inary] and is used only on
42
+ # Windows platforms.
43
+ #
44
+ # The stdin stream and/or pid may be omitted from the block parameter list
45
+ # if they are not required.
46
+ def self.popen4(command, mode = "t") # :yields: stdout, stderr, stdin, pid
47
+
48
+ err_output = nil
49
+ status = Open4.popen4(command, mode) do |stdin,stdout,stderr,pid|
50
+ yield stdout, stderr, stdin, pid
51
+
52
+ # On windows we will always get an exit status of 3 unless
53
+ # we read to the end of the streams so we do this on all platforms
54
+ # so that our behavior is always the same.
55
+ stdout.read unless stdout.eof?
56
+
57
+ # On windows executing a non existent command does not raise an error
58
+ # (as in unix) so on unix we return nil instead of a status object and
59
+ # on windows we try to determine if we couldn't start the command and
60
+ # return nil instead of the Process::Status object.
61
+ stderr.rewind
62
+ err_output = stderr.read
63
+ end
64
+
65
+ if status.exitstatus == 1 &&
66
+ err_output.match(/is not recognized as an internal or external command/)
67
+ return nil
68
+ end
69
+
70
+ return status
71
+ end # def
72
+ end # module
73
+
74
+
75
+ else # unix popen4 yields pid, stdin, stdout and stderr, respectively
76
+ # :enddoc:
77
+ require 'open4'
78
+ module POpen4
79
+ def self.popen4(command, mode = "t")
80
+ begin
81
+ return status = Open4.popen4(command) do |pid,stdin,stdout,stderr|
82
+ yield stdout, stderr, stdin, pid
83
+ # On windows we will always get an exit status of 3 unless
84
+ # we read to the end of the streams so we do this on all platforms
85
+ # so that our behavior is always the same.
86
+ stdout.read unless stdout.eof?
87
+ stderr.read unless stderr.eof?
88
+ end
89
+ rescue Errno::ENOENT => e
90
+ # On windows executing a non existent command does not raise an error
91
+ # (as in unix) so on unix we return nil instead of a status object and
92
+ # on windows we try to determine if we couldn't start the command and
93
+ # return nil instead of the Process::Status object.
94
+ return nil
95
+ end
96
+ end #def
97
+ end #module
98
+
99
+ end
100
+
@@ -0,0 +1,79 @@
1
+ $: << File.join( File.dirname( __FILE__ ), '../lib/')
2
+
3
+ require 'test/unit'
4
+ require 'popen4'
5
+
6
+ require 'rubygems'
7
+ require_gem 'Platform', '>= 0.4.0'
8
+
9
+ class POpen4Test < Test::Unit::TestCase
10
+
11
+ case Platform::OS
12
+ when :win32
13
+ CMD_SHELL = "cmd"
14
+ CMD_STDERR = "ruby -e \"$stderr.puts 'ruby'\""
15
+ CMD_EXIT = "ruby -e \"$stdout.puts 'ruby'; exit 1\""
16
+ else # unix
17
+ CMD_SHELL = "sh"
18
+ CMD_STDERR = "ruby -e '$stderr.puts \"ruby\"'"
19
+ CMD_EXIT = "ruby -e '$stdout.puts \"ruby\"; exit 1'"
20
+ end
21
+ CMD_GOOD = "ruby --version"
22
+ CMD_BAD = CMD_GOOD.reverse
23
+
24
+ def test_popen4_block_good_cmd
25
+ assert_nothing_raised do
26
+ POpen4.popen4(CMD_GOOD){ |pout, perr, pin, pid| }
27
+ end
28
+ end
29
+
30
+ def test_popen4_block_bad_cmd
31
+ status = nil
32
+ assert_nothing_raised do
33
+ status = POpen4.popen4(CMD_BAD){ |pout, perr, pin, pid| }
34
+ end
35
+ assert_nil status
36
+ end
37
+
38
+ def test_popen4_block_status
39
+ status = POpen4.popen4(CMD_GOOD) do |pout, perr, pin, pid|
40
+ assert_kind_of(IO, pin)
41
+ assert_kind_of(IO, pout)
42
+ assert_kind_of(IO, perr)
43
+ assert_kind_of(Fixnum, pid)
44
+ end
45
+ assert_kind_of Process::Status, status
46
+ end
47
+
48
+ def test_open4_block_read_stdout
49
+ status = POpen4.popen4(CMD_GOOD) do |pout, perr|
50
+ assert_match(/ruby \d\.\d\.\d/, pout.gets)
51
+ end
52
+ assert_equal 0, status.exitstatus
53
+ end
54
+
55
+ def test_open4_block_read_stderr
56
+ status = POpen4.popen4(CMD_STDERR) do |pout, perr|
57
+ assert_match "ruby", perr.gets
58
+ end
59
+ assert_equal 0, status.exitstatus
60
+ end
61
+
62
+ def test_open4_block_exitstatus
63
+ status = POpen4.popen4(CMD_EXIT) do |pout, perr|
64
+ assert_match "ruby", pout.gets
65
+ end
66
+ assert_kind_of Process::Status, status
67
+ assert_equal 1, status.exitstatus
68
+ end
69
+
70
+ def test_open4_block_write_stdin
71
+ status = POpen4.popen4(CMD_SHELL) do |pout, perr, pin|
72
+ pin.puts CMD_GOOD
73
+ pin.puts "exit"
74
+ pin.close
75
+ assert_match(/ruby \d\.\d\.\d/, pout.readlines.join)
76
+ end
77
+ assert_equal 0, status.exitstatus
78
+ end
79
+ end
metadata ADDED
@@ -0,0 +1,80 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: popen4
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.2
5
+ platform: ruby
6
+ authors:
7
+ - John-Mason P. Shackelford
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-01-03 00:00:00 -05:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: Platform
17
+ type: :runtime
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 0.4.0
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: open4
27
+ type: :runtime
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.0
34
+ version:
35
+ description: POpen4 provides the Rubyist a single API across platforms for executing a command in a child process with handles on stdout, stderr, stdin streams as well as access to the process ID and exit status.
36
+ email: john-mason@shackelford.org
37
+ executables: []
38
+
39
+ extensions: []
40
+
41
+ extra_rdoc_files:
42
+ - CHANGES
43
+ - LICENSE
44
+ - README.rdoc
45
+ files:
46
+ - Rakefile
47
+ - lib/popen4.rb
48
+ - CHANGES
49
+ - LICENSE
50
+ - README.rdoc
51
+ has_rdoc: true
52
+ homepage: http://github.com/shairontoledo/popen4
53
+ licenses: []
54
+
55
+ post_install_message:
56
+ rdoc_options: []
57
+
58
+ require_paths:
59
+ - lib
60
+ required_ruby_version: !ruby/object:Gem::Requirement
61
+ requirements:
62
+ - - ">="
63
+ - !ruby/object:Gem::Version
64
+ version: "0"
65
+ version:
66
+ required_rubygems_version: !ruby/object:Gem::Requirement
67
+ requirements:
68
+ - - ">="
69
+ - !ruby/object:Gem::Version
70
+ version: "0"
71
+ version:
72
+ requirements: []
73
+
74
+ rubyforge_project:
75
+ rubygems_version: 1.3.4
76
+ signing_key:
77
+ specification_version: 3
78
+ summary: Open4 cross-platform
79
+ test_files:
80
+ - tests/popen4_test.rb