=begin COMMANDSERVER RUBY LIBRARY REFERENCE MANUAL COMMANDSERVER NAME CommandServer SYNOPSIS c = CommandServer.new(cmd) DESCRIPTION CommandServer is a class to control a child process with standard IOs. A CommandServer object behaves as a readable and writable IO. The stderr of the child is always bufferd in an Array and can be obtain by err.shift. Note that child process maybe have internal buffer to output, so, gets might cause block. A solution to avoid blocking is making stdout of CommandServer tty, e.g., child = CommandServer.new(cmd) STDOUT.reopen(child.stdout) but this maybe mix child's stdout and parent's. CLASS METHODS CommandServer.new() create new process. METHODS alive? returns true if process is alive. err returns stderr buffer as an Array. gets gets one line from stdout of command. kill(signal) sends signal to command (child process). See also Process::kill. print arg1, arg2, ... prints to stdin of command. << arg puts to stdin of command and returns stdin IO object. pid returns pid of command. stdout returns stdout of command. AUTHORS gotoken@notwork.org =end class CommandServer def initialize(cmd) cin = IO::pipe cout = IO::pipe cerr = IO::pipe @errbuf = [] parent = fork if parent [cin[0],cout[1],cerr[1]].each{|fd| fd.close} @in, @out, @err = cin[1], cout[0], cerr[0] @alive = true; Thread.start{ sleep 1; Process::waitpid(@pid, nil); @alive = false } @pid = parent @gone = false err_reader = Thread.start{ while TRUE if line = @err.gets @errbuf.push line end end } else [cin[1],cout[0],cerr[0]].each{|fd| fd.close} $stdin, $stdout, $stderr = cin[0], cout[1], cerr[1] exec(cmd) raise Abort.new("#{cmd}: cannot exec") end end def gets @out.gets end def print(*args) if alive? @in.print(*args) @in.flush else $stdout.print "No Process: input is ignored\n" end end def <<(arg) if alive? @in << arg @in.flush else $stdout.print "No Process: input is ignored\n" end end def pid @pid end def err @errbuf end def stdout @out end def stdin @in end def alive? @alive end def kill(signal) Process::kill(signal, @pid) end end if __FILE__ == $0 cmd = ARGV[0] || "scat" cat = CommandServer.new(cmd) Thread.start{ while TRUE if err = cat.err.shift print "| ", err end end } while $_ = $stdin.gets cat << $_ end end