replacement for 'Kernel#system' which captures all output.
This is the *almost* final version.. this may have others interest :-)
Warning: 'stdin' is not yet supported.

Suggestions for improvements is welcome.


def system(command, *args)
    #todo: stdin
    r1, w1 = IO.pipe # stdout
    r2, w2 = IO.pipe # stderr
    fdes = [r1, r2]
    thread = Thread.new do
        loop do
            #puts "waiting"
            res = select(fdes, nil, nil, nil)[0]
            #p res
            if res.include?(r1)
                #puts "r1"
                unless r1.eof
                    Redir.instance.write_out r1.read
                else
                    #puts "kill r1"
                    fdes.delete r1
                    thread.kill if fdes == []
                end
            end
            if res.include?(r2)
                #puts "r2"
                unless r2.eof
                    Redir.instance.write_error r2.read
                else
                    #puts "kill r2"
                    fdes.delete r2
                    thread.kill if fdes == []
                end
            end
        end
    end
    pid = Kernel.fork do
        r1.close; r2.close
        $defout.reopen(w1); $stdout.reopen(w1); $stderr.reopen(w2)
        exec(command, *args)
        # todo: should I care closing w1+w2 correctly?
    end
    w1.close; w2.close
    status = Process.waitpid2(pid, 0)
    # wait until EOF on both pipes (r1+r2)
    thread.join
    r1.close; r2.close

    #$? = status[1]  # not possible
    (status[1] == 0) ? true : false
end




There is also some unittesting of this 'Kernel#system' replacement:
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/metaeditor/experiments/cpp_embed_ruby/test/output/testall.rb

Code for the sandbox:
http://cvs.sourceforge.net/cgi-bin/viewcvs.cgi/metaeditor/experiments/cpp_embed_ruby/test/output/b.rb

--
Simon Strandgaard