systemu_j 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -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
+