File: popen4.rb

package info (click to toggle)
ruby-popen4 0.1.4-1
  • links: PTS, VCS
  • area: main
  • in suites: jessie, jessie-kfreebsd, wheezy
  • size: 104 kB
  • ctags: 16
  • sloc: ruby: 99; makefile: 2
file content (92 lines) | stat: -rw-r--r-- 3,225 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
require 'platform'

case Platform::OS

# win32/popen4 yields stdin, stdout, stderr and pid, respectively
when :win32

  require 'win32/open3'

  # POpen4 provides the Rubyist a single API across platforms for executing a
  # command in a child process with handles on stdout, stderr, and stdin streams
  # as well as access to the process ID and exit status.
  #
  # Consider the following example (borrowed from Open4):
  #
  #   require 'rubygems'
  #   require 'popen4'
  #
  #   status =
  #     POpen4::popen4("cmd") do |stdout, stderr, stdin, pid|
  #       stdin.puts "echo hello world!"
  #       stdin.puts "echo ERROR! 1>&2"
  #       stdin.puts "exit"
  #       stdin.close
  #
  #       puts "pid        : #{ pid }"
  #       puts "stdout     : #{ stdout.read.strip }"
  #       puts "stderr     : #{ stderr.read.strip }"
  #     end
  #
  #   puts "status     : #{ status.inspect }"
  #   puts "exitstatus : #{ status.exitstatus }"
  #
  module POpen4
    # Starts a new process and hands IO objects representing the subprocess
    # stdout, stderr, stdin streams and the pid (respectively) to the block
    # supplied. If the command could not be started, return nil.
    #
    # The mode argument may be set to t[ext] or b[inary] and is used only on
    # Windows platforms.
    #
    # The stdin stream and/or pid may be omitted from the block parameter list
    # if they are not required.
    def self.popen4(command, mode = "t") # :yields: stdout, stderr, stdin, pid

      err_output = nil
      Open4.popen4(command, mode) do |stdin,stdout,stderr,pid|
        yield stdout, stderr, stdin, pid

        # On windows we will always get an exit status of 3 unless
        # we read to the end of the streams so we do this on all platforms
        # so that our behavior is always the same.
        stdout.read unless stdout.eof?

        # On windows executing a non existent command does not raise an error
        # (as in unix) so on unix we return nil instead of a status object and
        # on windows we try to determine if we couldn't start the command and
        # return nil instead of the Process::Status object.
        stderr.rewind
        err_output = stderr.read
      end

      return $?
    end # def
  end # module


else # unix popen4 yields pid, stdin, stdout and stderr, respectively
  # :enddoc:
  require 'open4'
  module POpen4
    def self.popen4(command, mode = "t")
      begin
        return status = Open4.popen4(command) do |pid,stdin,stdout,stderr|
          yield stdout, stderr, stdin, pid
          # On windows we will always get an exit status of 3 unless
          # we read to the end of the streams so we do this on all platforms
          # so that our behavior is always the same.
          stdout.read unless stdout.eof?
          stderr.read unless stderr.eof?
        end
      rescue Errno::ENOENT => e
        # On windows executing a non existent command does not raise an error
        # (as in unix) so on unix we return nil instead of a status object and
        # on windows we try to determine if we couldn't start the command and
        # return nil instead of the Process::Status object.
        return nil
      end
    end #def
  end #module

end