From: Simon Strandgaard <0bz63fz3m1qt3001@...> Date: 2003-05-15T21:14:00+09:00 Subject: Re: RCR for child execution On Thu, 15 May 2003 18:29:50 +0900, ts wrote: >>>>>> "S" == Simon Strandgaard <0bz63fz3m1qt3001@sneakemail.com> writes: > > S> I think my proprosal a minor patch and I think its possible. > > Well, it's easy : #system is > > rb_define_global_function("system", rb_f_system, -1); > > If you don't like it, you write your own version and then you call > rb_define_global_function() to change the definition of #system > > Then you do the same with fork, and backquote OK.. I have now replaced 'system' with a system which can redirect output elsewhere. I use pipes + threads so that stdout/stderr can go to a string. BTW: people said that this was *impossible* :-) I don't think my code here will interfere with the output of C/C++. Still I need to overload Kernel#fork, Kernel#backquote and stdin is not yet supported. What should I change on my version of 'system' so that it gets same behavier as rubys 'system'.. arguments/return value ??? > cat b.rb require 'stringio' require 'singleton' class Redir include Singleton def initialize @out = $stdout @error = $stderr end def set_out(elsewhere) @out = elsewhere end def set_error(elsewhere) @error = elsewhere end def write_out(msg) msg = msg + "_" @out.write(msg) end def write_error(msg) msg = msg + "." @error.write(msg) end end def system(command) # todo: stdin r1, w1 = IO.pipe # stdout r2, w2 = IO.pipe # stderr thread1 = Thread.new do # redirect stdout loop do s = r1.read(1) # TODO: can I make this buffered? Redir.instance.write_out(s) end end thread2 = Thread.new do # redirect stderr loop do s = r2.read(1) # TODO: can I make this buffered? Redir.instance.write_error(s) end end if (pid = fork) == nil r1.close; r2.close $defout = w1; $stdout = w1; $stderr = w2 #puts "system: enter: #{command}" exec(command) end w1.close; w2.close Process.waitpid(pid) r1.close; r2.close thread1.kill; thread2.kill #puts "system.leave" end redir = Redir.instance s = "" buf = StringIO.new(s, "w") redir.set_out(buf) redir.set_error(buf) system("ls main.cpp nonexist") puts "1" puts s.split(/\n/).collect { |msg| "OK: "+msg }.join("\n") puts "2" > Output looks like this: > ruby b.rb 1 OK: l.s.:. .n.o.n.e.x.i.s.t.:. .N.o. .s.u.c.h. .f.i.l.e. .o.r. .d.i.r.e.c.t.o.r.y. OK: .m_a_i_n_._c_p_p_ OK: _ 2 > -- Simon Strandgaard