PageRenderTime 24ms CodeModel.GetById 24ms RepoModel.GetById 0ms app.codeStats 0ms

/lib/babushka/popen.rb

https://github.com/ravibhure/babushka
Ruby | 40 lines | 33 code | 7 blank | 0 comment | 4 complexity | b3e7592e4656e8d936427753c5efa790 MD5 | raw file
  1. module Babushka
  2. class Open3
  3. def self.popen3 cmd, opts = {}, &block
  4. pipes = { :in => IO::pipe, :out => IO::pipe, :err => IO::pipe }
  5. near = { :in => pipes[:in][1], :out => pipes[:out][0], :err => pipes[:err][0] }
  6. far = { :in => pipes[:in][0], :out => pipes[:out][1], :err => pipes[:err][1] }
  7. pid = fork {
  8. reopen_pipe_for :read, pipes[:in], STDIN
  9. reopen_pipe_for :write, pipes[:out], STDOUT
  10. reopen_pipe_for :write, pipes[:err], STDERR
  11. Dir.chdir opts[:chdir] if opts[:chdir]
  12. ENV.update opts[:env] if opts[:env]
  13. exec(*cmd)
  14. }
  15. far.values.each(&:close)
  16. near.values.each {|p| p.sync = true }
  17. begin
  18. yield near[:in], near[:out], near[:err]
  19. Process.waitpid2(pid).last.exitstatus
  20. ensure
  21. near.values.each {|p| p.close unless p.closed? }
  22. end
  23. end
  24. private
  25. def self.reopen_pipe_for task, pipe, io
  26. to_close = pipe[task == :read ? 1 : 0]
  27. to_reopen = pipe[task == :read ? 0 : 1]
  28. to_close.close
  29. io.reopen to_reopen
  30. to_reopen.close
  31. end
  32. end
  33. end