systemu_j 1.2.1

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.
@@ -0,0 +1,2 @@
1
+ .DS_Store
2
+ *.gem
data/README ADDED
@@ -0,0 +1,160 @@
1
+ NAME
2
+
3
+ systemu
4
+
5
+ SYNOPSIS
6
+
7
+ univeral capture of stdout and stderr and handling of child process pid for windows, *nix, etc.
8
+
9
+ URIS
10
+
11
+ http://rubyforge.org/projects/codeforpeople/
12
+ http://codeforpeople.com/lib/ruby/
13
+ http://codeforpeople.rubyforge.org/svn/
14
+
15
+ INSTALL
16
+
17
+ gem install systemu
18
+
19
+ HISTORY
20
+
21
+ 1.2.0
22
+
23
+ - fixed handling of background thread management - needed
24
+ Thread.current.abort_on_exception = true
25
+
26
+ - fixed reporting of child pid, it was reported as the parent's pid before
27
+
28
+ SAMPLES
29
+
30
+ <========< samples/a.rb >========>
31
+
32
+ ~ > cat samples/a.rb
33
+
34
+ #
35
+ # systemu can be used on any platform to return status, stdout, and stderr of
36
+ # any command. unlike other methods like open3/popen4 there is zero danger of
37
+ # full pipes or threading issues hanging your process or subprocess.
38
+ #
39
+ require 'systemu'
40
+
41
+ date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
42
+
43
+ status, stdout, stderr = systemu date
44
+ p [ status, stdout, stderr ]
45
+
46
+ ~ > ruby samples/a.rb
47
+
48
+ [#<Process::Status: pid=987,exited(0)>, "Thu Dec 06 16:01:59 -0700 2007\n", "Thu Dec 06 16:01:59 -0700 2007\n"]
49
+
50
+
51
+ <========< samples/b.rb >========>
52
+
53
+ ~ > cat samples/b.rb
54
+
55
+ #
56
+ # quite a few keys can be passed to the command to alter it's behaviour. if
57
+ # either stdout or stderr is supplied those objects should respond_to? '<<'
58
+ # and only status will be returned
59
+ #
60
+ require 'systemu'
61
+
62
+ date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
63
+
64
+ stdout, stderr = '', ''
65
+ status = systemu date, 'stdout' => stdout, 'stderr' => stderr
66
+ p [ status, stdout, stderr ]
67
+
68
+ ~ > ruby samples/b.rb
69
+
70
+ [#<Process::Status: pid=992,exited(0)>, "Thu Dec 06 16:01:59 -0700 2007\n", "Thu Dec 06 16:01:59 -0700 2007\n"]
71
+
72
+
73
+ <========< samples/c.rb >========>
74
+
75
+ ~ > cat samples/c.rb
76
+
77
+ #
78
+ # of course stdin can be supplied too. synonyms for 'stdin' include '0' and
79
+ # 0. the other stdio streams have similar shortcuts
80
+ #
81
+ require 'systemu'
82
+
83
+ cat = %q( ruby -e" ARGF.each{|line| puts line} " )
84
+
85
+ status = systemu cat, 0=>'the stdin for cat', 1=>stdout=''
86
+ puts stdout
87
+
88
+ ~ > ruby samples/c.rb
89
+
90
+ the stdin for cat
91
+
92
+
93
+ <========< samples/d.rb >========>
94
+
95
+ ~ > cat samples/d.rb
96
+
97
+ #
98
+ # the cwd can be supplied
99
+ #
100
+ require 'systemu'
101
+ require 'tmpdir'
102
+
103
+ pwd = %q( ruby -e" STDERR.puts Dir.pwd " )
104
+
105
+ status = systemu pwd, 2=>(stderr=''), :cwd=>Dir.tmpdir
106
+ puts stderr
107
+
108
+
109
+ ~ > ruby samples/d.rb
110
+
111
+ /private/tmp
112
+
113
+
114
+ <========< samples/e.rb >========>
115
+
116
+ ~ > cat samples/e.rb
117
+
118
+ #
119
+ # any environment vars specified are merged into the child's environment
120
+ #
121
+ require 'systemu'
122
+
123
+ env = %q( ruby -r yaml -e" puts ENV[ 'answer' ] " )
124
+
125
+ status = systemu env, 1=>stdout='', 'env'=>{ 'answer' => 0b101010 }
126
+ puts stdout
127
+
128
+ ~ > ruby samples/e.rb
129
+
130
+ 42
131
+
132
+
133
+ <========< samples/f.rb >========>
134
+
135
+ ~ > cat samples/f.rb
136
+
137
+ #
138
+ # if a block is specified then it is passed the child pid and run in a
139
+ # background thread. note that this thread will __not__ be blocked during the
140
+ # execution of the command so it may do useful work such as killing the child
141
+ # if execution time passes a certain threshold
142
+ #
143
+ require 'systemu'
144
+
145
+ looper = %q( ruby -e" loop{ STDERR.puts Time.now.to_i; sleep 1 } " )
146
+
147
+ status, stdout, stderr =
148
+ systemu looper do |cid|
149
+ sleep 3
150
+ Process.kill 9, cid
151
+ end
152
+
153
+ p status
154
+ p stderr
155
+
156
+ ~ > ruby samples/f.rb
157
+
158
+ #<Process::Status: pid=1012,signaled(SIGKILL=9)>
159
+ "1196982119\n1196982120\n1196982121\n"
160
+
@@ -0,0 +1,30 @@
1
+ NAME
2
+
3
+ systemu
4
+
5
+ SYNOPSIS
6
+
7
+ univeral capture of stdout and stderr and handling of child process pid for windows, *nix, etc.
8
+
9
+ URIS
10
+
11
+ http://rubyforge.org/projects/codeforpeople/
12
+ http://codeforpeople.com/lib/ruby/
13
+ http://codeforpeople.rubyforge.org/svn/
14
+
15
+ INSTALL
16
+
17
+ gem install systemu
18
+
19
+ HISTORY
20
+
21
+ 1.2.0
22
+
23
+ - fixed handling of background thread management - needed
24
+ Thread.current.abort_on_exception = true
25
+
26
+ - fixed reporting of child pid, it was reported as the parent's pid before
27
+
28
+ SAMPLES
29
+
30
+ @samples
@@ -0,0 +1,15 @@
1
+ begin
2
+ require 'jeweler'
3
+ Jeweler::Tasks.new do |gemspec|
4
+ gemspec.name = "systemu_j"
5
+ gemspec.summary = "System Universal"
6
+ gemspec.description = "Univeral capture of stdout and stderr and handling of child process pid for windows, *nix, etc."
7
+ gemspec.email = "hahn@netseven.it"
8
+ gemspec.homepage = "http://codeforpeople.com/lib/ruby/systemu"
9
+ gemspec.description = "Special version for JRuby compatibility"
10
+ gemspec.authors = ["Ara T. Howard (ara.t.howard@noaa.gov)", "Daniel Hahn (JRuby modifications)"]
11
+ end
12
+ Jeweler::GemcutterTasks.new
13
+ rescue LoadError
14
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
15
+ end
@@ -0,0 +1,4 @@
1
+ ---
2
+ :major: 1
3
+ :minor: 2
4
+ :patch: 1
data/a.rb ADDED
@@ -0,0 +1,6 @@
1
+ require 'systemu'
2
+
3
+
4
+ systemu 'date' do |cid|
5
+ p cid
6
+ end
@@ -0,0 +1,32 @@
1
+ require 'pathname'
2
+
3
+ $VERBOSE=nil
4
+
5
+ def indent s, n = 2
6
+ ws = ' ' * n
7
+ s.gsub %r/^/, ws
8
+ end
9
+
10
+ template = IO::read 'README.tmpl'
11
+
12
+ samples = ''
13
+ prompt = '~ > '
14
+
15
+ Dir['sample*/*'].sort.each do |sample|
16
+ samples << "\n" << " <========< #{ sample } >========>" << "\n\n"
17
+
18
+ cmd = "cat #{ sample }"
19
+ samples << indent(prompt + cmd, 2) << "\n\n"
20
+ samples << indent(`#{ cmd }`, 4) << "\n"
21
+
22
+ cmd = "ruby #{ sample }"
23
+ samples << indent(prompt + cmd, 2) << "\n\n"
24
+
25
+ cmd = "ruby -W0 -Ilib #{ sample }"
26
+ samples << indent(`#{ cmd } 2>&1`, 4) << "\n"
27
+ end
28
+
29
+ #samples.gsub! %r/^/, ' '
30
+
31
+ readme = template.gsub %r/^\s*@samples\s*$/, samples
32
+ print readme
@@ -0,0 +1,206 @@
1
+ #!/usr/bin/env ruby
2
+ require 'rbconfig'
3
+ require 'find'
4
+ require 'ftools'
5
+ require 'tempfile'
6
+ include Config
7
+
8
+ LIBDIR = "lib"
9
+ LIBDIR_MODE = 0644
10
+
11
+ BINDIR = "bin"
12
+ BINDIR_MODE = 0755
13
+
14
+
15
+ $srcdir = CONFIG["srcdir"]
16
+ $version = CONFIG["MAJOR"]+"."+CONFIG["MINOR"]
17
+ $libdir = File.join(CONFIG["libdir"], "ruby", $version)
18
+ $archdir = File.join($libdir, CONFIG["arch"])
19
+ $site_libdir = $:.find {|x| x =~ /site_ruby$/}
20
+ $bindir = CONFIG["bindir"] || CONFIG['BINDIR']
21
+ $ruby_install_name = CONFIG['ruby_install_name'] || CONFIG['RUBY_INSTALL_NAME'] || 'ruby'
22
+ $ruby_ext = CONFIG['EXEEXT'] || ''
23
+ $ruby = File.join($bindir, ($ruby_install_name + $ruby_ext))
24
+
25
+ if !$site_libdir
26
+ $site_libdir = File.join($libdir, "site_ruby")
27
+ elsif $site_libdir !~ %r/#{Regexp.quote($version)}/
28
+ $site_libdir = File.join($site_libdir, $version)
29
+ end
30
+
31
+ def install_rb(srcdir=nil, destdir=nil, mode=nil, bin=nil)
32
+ #{{{
33
+ path = []
34
+ dir = []
35
+ Find.find(srcdir) do |f|
36
+ next unless FileTest.file?(f)
37
+ next if (f = f[srcdir.length+1..-1]) == nil
38
+ next if (/CVS$/ =~ File.dirname(f))
39
+ next if f =~ %r/\.lnk/
40
+ path.push f
41
+ dir |= [File.dirname(f)]
42
+ end
43
+ for f in dir
44
+ next if f == "."
45
+ next if f == "CVS"
46
+ File::makedirs(File.join(destdir, f))
47
+ end
48
+ for f in path
49
+ next if (/\~$/ =~ f)
50
+ next if (/^\./ =~ File.basename(f))
51
+ unless bin
52
+ File::install(File.join(srcdir, f), File.join(destdir, f), mode, true)
53
+ else
54
+ from = File.join(srcdir, f)
55
+ to = File.join(destdir, f)
56
+ shebangify(from) do |sf|
57
+ $deferr.print from, " -> ", File::catname(from, to), "\n"
58
+ $deferr.printf "chmod %04o %s\n", mode, to
59
+ File::install(sf, to, mode, false)
60
+ end
61
+ end
62
+ end
63
+ #}}}
64
+ end
65
+ def shebangify f
66
+ #{{{
67
+ open(f) do |fd|
68
+ buf = fd.read 42
69
+ if buf =~ %r/^\s*#\s*!.*ruby/o
70
+ ftmp = Tempfile::new("#{ $$ }_#{ File::basename(f) }")
71
+ begin
72
+ fd.rewind
73
+ ftmp.puts "#!#{ $ruby }"
74
+ while((buf = fd.read(8192)))
75
+ ftmp.write buf
76
+ end
77
+ ftmp.close
78
+ yield ftmp.path
79
+ ensure
80
+ ftmp.close!
81
+ end
82
+ else
83
+ yield f
84
+ end
85
+ end
86
+ #}}}
87
+ end
88
+ def ARGV.switch
89
+ #{{{
90
+ return nil if self.empty?
91
+ arg = self.shift
92
+ return nil if arg == '--'
93
+ if arg =~ /^-(.)(.*)/
94
+ return arg if $1 == '-'
95
+ raise 'unknown switch "-"' if $2.index('-')
96
+ self.unshift "-#{$2}" if $2.size > 0
97
+ "-#{$1}"
98
+ else
99
+ self.unshift arg
100
+ nil
101
+ end
102
+ #}}}
103
+ end
104
+ def ARGV.req_arg
105
+ #{{{
106
+ self.shift || raise('missing argument')
107
+ #}}}
108
+ end
109
+ def linkify d, linked = []
110
+ #--{{{
111
+ if test ?d, d
112
+ versioned = Dir[ File::join(d, "*-[0-9].[0-9].[0-9].rb") ]
113
+ versioned.each do |v|
114
+ src, dst = v, v.gsub(%r/\-[\d\.]+\.rb$/, '.rb')
115
+ lnk = nil
116
+ begin
117
+ if test ?l, dst
118
+ lnk = "#{ dst }.lnk"
119
+ puts "#{ dst } -> #{ lnk }"
120
+ File::rename dst, lnk
121
+ end
122
+ unless test ?e, dst
123
+ puts "#{ src } -> #{ dst }"
124
+ File::copy src, dst
125
+ linked << dst
126
+ end
127
+ ensure
128
+ if lnk
129
+ at_exit do
130
+ puts "#{ lnk } -> #{ dst }"
131
+ File::rename lnk, dst
132
+ end
133
+ end
134
+ end
135
+ end
136
+ end
137
+ linked
138
+ #--}}}
139
+ end
140
+
141
+
142
+ #
143
+ # main program
144
+ #
145
+
146
+ libdir = $site_libdir
147
+ bindir = $bindir
148
+ no_linkify = false
149
+ linked = nil
150
+ help = false
151
+
152
+ usage = <<-usage
153
+ #{ File::basename $0 }
154
+ -d, --destdir <destdir>
155
+ -l, --libdir <libdir>
156
+ -b, --bindir <bindir>
157
+ -r, --ruby <ruby>
158
+ -n, --no_linkify
159
+ -s, --sudo
160
+ -h, --help
161
+ usage
162
+
163
+ begin
164
+ while switch = ARGV.switch
165
+ case switch
166
+ when '-d', '--destdir'
167
+ libdir = ARGV.req_arg
168
+ when '-l', '--libdir'
169
+ libdir = ARGV.req_arg
170
+ when '-b', '--bindir'
171
+ bindir = ARGV.req_arg
172
+ when '-r', '--ruby'
173
+ $ruby = ARGV.req_arg
174
+ when '-n', '--no_linkify'
175
+ no_linkify = true
176
+ when '-s', '--sudo'
177
+ sudo = 'sudo'
178
+ when '-h', '--help'
179
+ help = true
180
+ else
181
+ raise "unknown switch #{switch.dump}"
182
+ end
183
+ end
184
+ rescue
185
+ STDERR.puts $!.to_s
186
+ STDERR.puts usage
187
+ exit 1
188
+ end
189
+
190
+ if help
191
+ STDOUT.puts usage
192
+ exit
193
+ end
194
+
195
+ unless no_linkify
196
+ linked = linkify('lib') + linkify('bin')
197
+ end
198
+
199
+ system "#{ $ruby } extconf.rb && make && #{ sudo } make install" if test(?s, 'extconf.rb')
200
+
201
+ install_rb(LIBDIR, libdir, LIBDIR_MODE)
202
+ install_rb(BINDIR, bindir, BINDIR_MODE, bin=true)
203
+
204
+ if linked
205
+ linked.each{|path| File::rm_f path}
206
+ end
@@ -0,0 +1,328 @@
1
+ # vim: ts=2:sw=2:sts=2:et:fdm=marker
2
+ require 'tmpdir'
3
+ require 'socket'
4
+ require 'fileutils'
5
+ require 'rbconfig'
6
+ require 'thread'
7
+ require 'yaml'
8
+
9
+ class Object
10
+ def systemu(*a, &b) SystemUniversal.new(*a, &b).systemu end
11
+ end
12
+
13
+ class SystemUniversal
14
+ #
15
+ # constants
16
+ #
17
+ SystemUniversal::VERSION = '1.2.0' unless defined? SystemUniversal::VERSION
18
+ def version() SystemUniversal::VERSION end
19
+ #
20
+ # class methods
21
+ #
22
+
23
+ @host = Socket.gethostname
24
+ begin
25
+ @ppid = Process.ppid
26
+ rescue Exception
27
+ STDERR.puts "WARNING: Seems that this platform doesn't support Process.ppid"
28
+ @ppid = 0
29
+ end
30
+ @pid = Process.pid
31
+ @turd = ENV['SYSTEMU_TURD']
32
+
33
+ c = ::Config::CONFIG
34
+ ruby = File.join(c['bindir'], c['ruby_install_name']) << c['EXEEXT']
35
+ @ruby = if system('%s -e 42' % ruby)
36
+ ruby
37
+ else
38
+ system('%s -e 42' % 'ruby') ? 'ruby' : warn('no ruby in PATH/CONFIG')
39
+ end
40
+
41
+ class << self
42
+ %w( host ppid pid ruby turd ).each{|a| attr_accessor a}
43
+ end
44
+
45
+ #
46
+ # instance methods
47
+ #
48
+
49
+ def initialize argv, opts = {}, &block
50
+ getopt = getopts opts
51
+
52
+ @argv = argv
53
+ @block = block
54
+
55
+ @stdin = getopt[ ['stdin', 'in', '0', 0] ]
56
+ @stdout = getopt[ ['stdout', 'out', '1', 1] ]
57
+ @stderr = getopt[ ['stderr', 'err', '2', 2] ]
58
+ @env = getopt[ 'env' ]
59
+ @cwd = getopt[ 'cwd' ]
60
+
61
+ @host = getopt[ 'host', self.class.host ]
62
+ @ppid = getopt[ 'ppid', self.class.ppid ]
63
+ @pid = getopt[ 'pid', self.class.pid ]
64
+ @ruby = getopt[ 'ruby', self.class.ruby ]
65
+ end
66
+
67
+ def systemu
68
+ tmpdir do |tmp|
69
+ c = child_setup tmp
70
+ status = nil
71
+
72
+ begin
73
+ thread = nil
74
+
75
+ quietly{
76
+ IO.popen "#{ @ruby } #{ c['program'] }", 'r+' do |pipe|
77
+ line = pipe.gets
78
+ case line
79
+ when %r/^pid: \d+$/
80
+ cid = Integer line[%r/\d+/]
81
+ else
82
+ begin
83
+ buf = pipe.read
84
+ buf = "#{ line }#{ buf }"
85
+ e = Marshal.load buf
86
+ raise unless Exception === e
87
+ raise e
88
+ rescue
89
+ raise "wtf?\n#{ buf }\n"
90
+ end
91
+ end
92
+ thread = new_thread cid, @block if @block
93
+ pipe.read rescue nil
94
+ end
95
+ }
96
+ status = $?
97
+ ensure
98
+ if thread
99
+ begin
100
+ class << status
101
+ attr 'thread'
102
+ end
103
+ status.instance_eval{ @thread = thread }
104
+ rescue
105
+ 42
106
+ end
107
+ end
108
+ end
109
+
110
+ if @stdout or @stderr
111
+ open(c['stdout']){|f| relay f => @stdout} if @stdout
112
+ open(c['stderr']){|f| relay f => @stderr} if @stderr
113
+ status
114
+ else
115
+ [status, IO.read(c['stdout']), IO.read(c['stderr'])]
116
+ end
117
+ end
118
+ end
119
+
120
+ def new_thread cid, block
121
+ q = Queue.new
122
+ Thread.new(cid) do |cid|
123
+ current = Thread.current
124
+ current.abort_on_exception = true
125
+ q.push current
126
+ block.call cid
127
+ end
128
+ q.pop
129
+ end
130
+
131
+ def child_setup tmp
132
+ stdin = File.expand_path(File.join(tmp, 'stdin'))
133
+ stdout = File.expand_path(File.join(tmp, 'stdout'))
134
+ stderr = File.expand_path(File.join(tmp, 'stderr'))
135
+ program = File.expand_path(File.join(tmp, 'program'))
136
+ config = File.expand_path(File.join(tmp, 'config'))
137
+
138
+ if @stdin
139
+ open(stdin, 'w'){|f| relay @stdin => f}
140
+ else
141
+ FileUtils.touch stdin
142
+ end
143
+ FileUtils.touch stdout
144
+ FileUtils.touch stderr
145
+
146
+ c = {}
147
+ c['argv'] = @argv
148
+ c['env'] = @env
149
+ c['cwd'] = @cwd
150
+ c['stdin'] = stdin
151
+ c['stdout'] = stdout
152
+ c['stderr'] = stderr
153
+ c['program'] = program
154
+ open(config, 'w'){|f| YAML.dump c, f}
155
+
156
+ open(program, 'w'){|f| f.write child_program(config)}
157
+
158
+ c
159
+ end
160
+
161
+ def quietly
162
+ v = $VERBOSE
163
+ $VERBOSE = nil
164
+ yield
165
+ ensure
166
+ $VERBOSE = v
167
+ end
168
+
169
+ def child_program config
170
+ <<-program
171
+ require 'rbconfig'
172
+ is_jruby = (::Config::CONFIG['RUBY_INSTALL_NAME'] =~ /jruby/) != nil
173
+
174
+ PIPE = STDOUT.dup
175
+ begin
176
+ if(is_jruby)
177
+ require 'java'
178
+
179
+ include_class 'java.io.PrintStream'
180
+ include_class 'java.io.ByteArrayOutputStream'
181
+ include_class 'java.io.FileOutputStream'
182
+ include_class 'java.io.FileInputStream'
183
+ include_class 'java.io.BufferedOutputStream'
184
+ include_class 'java.io.BufferedInputStream'
185
+ include_class 'java.lang.System'
186
+ end
187
+
188
+ require 'yaml'
189
+
190
+ config = YAML.load(IO.read('#{ config }'))
191
+
192
+ argv = config['argv']
193
+ env = config['env']
194
+ cwd = config['cwd']
195
+ stdin = config['stdin']
196
+ stdout = config['stdout']
197
+ stderr = config['stderr']
198
+
199
+ Dir.chdir cwd if cwd
200
+ env.each{|k,v| ENV[k.to_s] = v.to_s} if env
201
+
202
+ if(is_jruby)
203
+ file_in = BufferedInputStream.new(FileInputStream.new(stdin))
204
+ System.setIn(file_in)
205
+ file_out = PrintStream.new(BufferedOutputStream.new(FileOutputStream.new(stdout)))
206
+ System.setOut(file_out)
207
+ file_err = PrintStream.new(BufferedOutputStream.new(FileOutputStream.new(stderr)))
208
+ System.setErr(file_err)
209
+ else
210
+ STDIN.reopen stdin
211
+ STDOUT.reopen stdout
212
+ STDERR.reopen stderr
213
+ end
214
+
215
+ PIPE.puts "pid: \#{ Process.pid }"
216
+ PIPE.flush ### the process is ready yo!
217
+ PIPE.close unless(is_jruby)
218
+
219
+ exec *argv
220
+ rescue Exception => e
221
+ PIPE.write Marshal.dump(e) rescue nil
222
+ exit 42
223
+ end
224
+ program
225
+ end
226
+
227
+ def relay srcdst
228
+ src, dst, ignored = srcdst.to_a.first
229
+ if src.respond_to? 'read'
230
+ while((buf = src.read(8192))); dst << buf; end
231
+ else
232
+ src.each{|buf| dst << buf}
233
+ end
234
+ end
235
+
236
+ def tmpdir d = Dir.tmpdir, max = 42, &b
237
+ i = -1 and loop{
238
+ i += 1
239
+
240
+ tmp = File.join d, "systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }"
241
+
242
+ begin
243
+ Dir.mkdir tmp
244
+ rescue Errno::EEXIST
245
+ raise if i >= max
246
+ next
247
+ end
248
+
249
+ break(
250
+ if b
251
+ begin
252
+ b.call tmp
253
+ ensure
254
+ FileUtils.rm_rf tmp unless SystemU.turd
255
+ end
256
+ else
257
+ tmp
258
+ end
259
+ )
260
+ }
261
+ end
262
+
263
+ def getopts opts = {}
264
+ lambda do |*args|
265
+ keys, default, ignored = args
266
+ catch('opt') do
267
+ [keys].flatten.each do |key|
268
+ [key, key.to_s, key.to_s.intern].each do |key|
269
+ throw 'opt', opts[key] if opts.has_key?(key)
270
+ end
271
+ end
272
+ default
273
+ end
274
+ end
275
+ end
276
+ end
277
+
278
+ SystemU = SystemUniversal unless defined? SystemU
279
+
280
+
281
+
282
+
283
+
284
+
285
+
286
+
287
+
288
+
289
+
290
+
291
+
292
+ if $0 == __FILE__
293
+ #
294
+ # date
295
+ #
296
+ date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
297
+
298
+ status, stdout, stderr = systemu date
299
+ p [status, stdout, stderr]
300
+
301
+ status = systemu date, 1=>(stdout = '')
302
+ p [status, stdout]
303
+
304
+ status = systemu date, 2=>(stderr = '')
305
+ p [status, stderr]
306
+ #
307
+ # sleep
308
+ #
309
+ sleep = %q( ruby -e" p(sleep(1)) " )
310
+ status, stdout, stderr = systemu sleep
311
+ p [status, stdout, stderr]
312
+
313
+ sleep = %q( ruby -e" p(sleep(42)) " )
314
+ status, stdout, stderr = systemu(sleep){|cid| Process.kill 9, cid}
315
+ p [status, stdout, stderr]
316
+ #
317
+ # env
318
+ #
319
+ env = %q( ruby -e" p ENV['A'] " )
320
+ status, stdout, stderr = systemu env, :env => {'A' => 42}
321
+ p [status, stdout, stderr]
322
+ #
323
+ # cwd
324
+ #
325
+ env = %q( ruby -e" p Dir.pwd " )
326
+ status, stdout, stderr = systemu env, :cwd => Dir.tmpdir
327
+ p [status, stdout, stderr]
328
+ end
@@ -0,0 +1,11 @@
1
+ #
2
+ # systemu can be used on any platform to return status, stdout, and stderr of
3
+ # any command. unlike other methods like open3/popen4 there is zero danger of
4
+ # full pipes or threading issues hanging your process or subprocess.
5
+ #
6
+ require 'systemu'
7
+
8
+ date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
9
+
10
+ status, stdout, stderr = systemu date
11
+ p [ status, stdout, stderr ]
@@ -0,0 +1,12 @@
1
+ #
2
+ # quite a few keys can be passed to the command to alter it's behaviour. if
3
+ # either stdout or stderr is supplied those objects should respond_to? '<<'
4
+ # and only status will be returned
5
+ #
6
+ require 'systemu'
7
+
8
+ date = %q( ruby -e" t = Time.now; STDOUT.puts t; STDERR.puts t " )
9
+
10
+ stdout, stderr = '', ''
11
+ status = systemu date, 'stdout' => stdout, 'stderr' => stderr
12
+ p [ status, stdout, stderr ]
@@ -0,0 +1,10 @@
1
+ #
2
+ # of course stdin can be supplied too. synonyms for 'stdin' include '0' and
3
+ # 0. the other stdio streams have similar shortcuts
4
+ #
5
+ require 'systemu'
6
+
7
+ cat = %q( ruby -e" ARGF.each{|line| puts line} " )
8
+
9
+ status = systemu cat, 0=>'the stdin for cat', 1=>stdout=''
10
+ puts stdout
@@ -0,0 +1,11 @@
1
+ #
2
+ # the cwd can be supplied
3
+ #
4
+ require 'systemu'
5
+ require 'tmpdir'
6
+
7
+ pwd = %q( ruby -e" STDERR.puts Dir.pwd " )
8
+
9
+ status = systemu pwd, 2=>(stderr=''), :cwd=>Dir.tmpdir
10
+ puts stderr
11
+
@@ -0,0 +1,9 @@
1
+ #
2
+ # any environment vars specified are merged into the child's environment
3
+ #
4
+ require 'systemu'
5
+
6
+ env = %q( ruby -r yaml -e" puts ENV[ 'answer' ] " )
7
+
8
+ status = systemu env, 1=>stdout='', 'env'=>{ 'answer' => 0b101010 }
9
+ puts stdout
@@ -0,0 +1,18 @@
1
+ #
2
+ # if a block is specified then it is passed the child pid and run in a
3
+ # background thread. note that this thread will __not__ be blocked during the
4
+ # execution of the command so it may do useful work such as killing the child
5
+ # if execution time passes a certain threshold
6
+ #
7
+ require 'systemu'
8
+
9
+ looper = %q( ruby -e" loop{ STDERR.puts Time.now.to_i; sleep 1 } " )
10
+
11
+ status, stdout, stderr =
12
+ systemu looper do |cid|
13
+ sleep 3
14
+ Process.kill 9, cid
15
+ end
16
+
17
+ p status
18
+ p stderr
@@ -0,0 +1,30 @@
1
+ # -*- encoding: utf-8 -*-
2
+
3
+ Gem::Specification.new do |s|
4
+ s.name = %q{systemu}
5
+ s.version = "1.2.0"
6
+
7
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
+ s.authors = ["Ara T. Howard (ara.t.howard@noaa.gov)", "Daniel Hahn (JRuby modifications)"]
9
+ s.date = %q{2009-09-11}
10
+ s.description = %q{Special version for JRuby compatibility}
11
+ s.email = %q{hahn@netseven.it}
12
+ s.extra_rdoc_files = ["README", "README.tmpl"]
13
+ s.files = ["README.tmpl", "VERSION.yml", "lib/systemu.rb", "README"]
14
+ s.has_rdoc = true
15
+ s.homepage = %q{http://codeforpeople.com/lib/ruby/systemu}
16
+ s.rdoc_options = ["--inline-source", "--charset=UTF-8"]
17
+ s.require_paths = ["lib"]
18
+ s.rubygems_version = %q{1.3.1}
19
+ s.summary = %q{System Universal}
20
+
21
+ if s.respond_to? :specification_version then
22
+ current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
23
+ s.specification_version = 2
24
+
25
+ if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
26
+ else
27
+ end
28
+ else
29
+ end
30
+ end
metadata ADDED
@@ -0,0 +1,72 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: systemu_j
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.2.1
5
+ platform: ruby
6
+ authors:
7
+ - Ara T. Howard (ara.t.howard@noaa.gov)
8
+ - Daniel Hahn (JRuby modifications)
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+
13
+ date: 2009-12-15 00:00:00 +01:00
14
+ default_executable:
15
+ dependencies: []
16
+
17
+ description: Special version for JRuby compatibility
18
+ email: hahn@netseven.it
19
+ executables: []
20
+
21
+ extensions: []
22
+
23
+ extra_rdoc_files:
24
+ - README
25
+ - README.tmpl
26
+ files:
27
+ - .gitignore
28
+ - README
29
+ - README.tmpl
30
+ - Rakefile
31
+ - VERSION.yml
32
+ - a.rb
33
+ - gen_readme.rb
34
+ - install.rb
35
+ - lib/systemu.rb
36
+ - samples/a.rb
37
+ - samples/b.rb
38
+ - samples/c.rb
39
+ - samples/d.rb
40
+ - samples/e.rb
41
+ - samples/f.rb
42
+ - systemu.gemspec
43
+ has_rdoc: true
44
+ homepage: http://codeforpeople.com/lib/ruby/systemu
45
+ licenses: []
46
+
47
+ post_install_message:
48
+ rdoc_options:
49
+ - --charset=UTF-8
50
+ require_paths:
51
+ - lib
52
+ required_ruby_version: !ruby/object:Gem::Requirement
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ version: "0"
57
+ version:
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ version: "0"
63
+ version:
64
+ requirements: []
65
+
66
+ rubyforge_project:
67
+ rubygems_version: 1.3.5
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: System Universal
71
+ test_files: []
72
+