Class: SystemUniversal

### Home Classes Methods

### In Files

- lib/systemu.rb

### Parent

Object

### Namespace

- CLASS SystemUniversal::StreamReader

### Methods

- ::description
- ::new
- ::quote
- ::ruby
- ::version
- #child_program
- #child_setup
- #getopts
- #new_thread
- #quietly
- #quote
- #relay
- #slug_for
- #systemu
- #tmpdir
- #version

### Class/Module Index

Quicksearch

- SystemUniversal
- SystemUniversal::StreamReader
- Object

No matching classes.

# SystemUniversal

### Constants

VERSION

### Public Class Methods

description() click to toggle source

    # File lib/systemu.rb, line 19
    def SystemUniversal.description
      "universal capture of stdout and stderr and handling of child process pid for windows, *nix, etc."
    end

new(argv, opts = {}) click to toggle source

instance methods

    # File lib/systemu.rb, line 56
    def initialize argv, opts = {}, &block
      getopt = getopts opts

      @argv = argv
      @block = block

      @stdin = getopt[ ['stdin', 'in', '0', 0] ]
      @stdout = getopt[ ['stdout', 'out', '1', 1] ]
      @stderr = getopt[ ['stderr', 'err', '2', 2] ]
      @env = getopt[ 'env' ]
      @cwd = getopt[ 'cwd' ]

      @host = getopt[ 'host', self.class.host ]
      @ppid = getopt[ 'ppid', self.class.ppid ]
      @pid = getopt[ 'pid', self.class.pid ]
      @ruby = getopt[ 'ruby', self.class.ruby ]
    end

quote(*words) click to toggle source

    # File lib/systemu.rb, line 47
    def quote(*words)
      words.map{|word| word.inspect}.join(' ')
    end

ruby() click to toggle source

    # File lib/systemu.rb, line 32
    def self.ruby
      return @ruby if @ruby

      c = begin; ::RbConfig::CONFIG; rescue NameError; ::Config::CONFIG; end
      ruby = File.join(c['bindir'], c['ruby_install_name']) << c['EXEEXT']
      @ruby = if system('%s -e 42' % ruby)
        ruby
      else
        system('%s -e 42' % 'ruby') ? 'ruby' : warn('no ruby in PATH/CONFIG')
      end
    end

version() click to toggle source

    # File lib/systemu.rb, line 17
    def SystemUniversal.version() SystemUniversal::VERSION end

### Public Instance Methods

child_program(config) click to toggle source

    # File lib/systemu.rb, line 180
    def child_program config
            # encoding: utf-8      PIPE = STDOUT.dup      begin        config = Marshal.load(IO.read('#{ config }',:mode=>"rb"))        argv = config['argv']        env = config['env']        cwd = config['cwd']        stdin = config['stdin']        stdout = config['stdout']        stderr = config['stderr']        Dir.chdir cwd if cwd        env.each{|k,v| ENV[k.to_s] = v.to_s} if env        STDIN.reopen stdin        STDOUT.reopen stdout        STDERR.reopen stderr        PIPE.puts "pid: \#{ Process.pid }"        PIPE.flush                        ### the process is ready yo!        PIPE.close        exec *argv      rescue Exception => e        PIPE.write Marshal.dump(e) rescue nil        exit 42      end
    end

child_setup(tmp) click to toggle source

    # File lib/systemu.rb, line 142
    def child_setup tmp
      stdin = File.expand_path(File.join(tmp, 'stdin'))
      stdout = File.expand_path(File.join(tmp, 'stdout'))
      stderr = File.expand_path(File.join(tmp, 'stderr'))
      program = File.expand_path(File.join(tmp, 'program'))
      config = File.expand_path(File.join(tmp, 'config'))

      if @stdin
        open(stdin, 'wb'){|f| relay @stdin => f}
      else
        FileUtils.touch stdin
      end
      FileUtils.touch stdout
      FileUtils.touch stderr

      c = {}
      c['argv'] = @argv
      c['env'] = @env
      c['cwd'] = @cwd
      c['stdin'] = stdin
      c['stdout'] = stdout
      c['stderr'] = stderr
      c['program'] = program
      open(config, 'wb'){|f| Marshal.dump(c, f)}

      open(program, 'wb'){|f| f.write child_program(config)}

      c
    end

getopts(opts = {}) click to toggle source

    # File lib/systemu.rb, line 264
    def getopts opts = {}
      lambda do |*args|
        keys, default, _ = args
        catch(:opt) do
          [keys].flatten.each do |key|
            [key, key.to_s, key.to_s.intern].each do |k|
              throw :opt, opts[k] if opts.has_key?(k)
            end
          end
          default
        end
      end
    end

new_thread(child_pid, block) click to toggle source

    # File lib/systemu.rb, line 131
    def new_thread child_pid, block
      q = Queue.new
      Thread.new(child_pid) do |cid|
        current = Thread.current
        current.abort_on_exception = true
        q.push current
        block.call cid
      end
      q.pop
    end

quietly() click to toggle source

    # File lib/systemu.rb, line 172
    def quietly
      v = $VERBOSE
      $VERBOSE = nil
      yield
    ensure
      $VERBOSE = v
    end

quote(*args, &block) click to toggle source

    # File lib/systemu.rb, line 127
    def quote *args, &block
      SystemUniversal.quote(*args, &block)
    end

relay(srcdst) click to toggle source

    # File lib/systemu.rb, line 214
    def relay srcdst
      src, dst, _ = srcdst.to_a.first
      if src.respond_to? 'read'
        while((buffer = src.read(8192))); dst << buffer; end
      else
        if src.respond_to?(:each_line)
          src.each_line{|buf| dst << buf}
        else
          src.each{|buf| dst << buf}
        end
      end
    end

slug_for(*args) click to toggle source

    # File lib/systemu.rb, line 227
    def slug_for(*args)
      options = args.last.is_a?(Hash) ? args.pop : {}
      join = (options[:join] || options['join'] || '_').to_s
      string = args.flatten.compact.join(join)
      words = string.to_s.scan(%[/\w]+|)
      words.map!{|word| word.gsub %[^/0-9a-zA-Z_-]|, ''}
      words.delete_if{|word| word.nil? or word.strip.empty?}
      words.join(join).downcase.gsub('/', (join * 2))
    end

systemu() click to toggle source

    # File lib/systemu.rb, line 74
    def systemu
      tmpdir do |tmp|
        c = child_setup tmp
        status = nil

        begin
          thread = nil

          quietly{
            IO.popen "#{ quote(@ruby) } #{ quote(c['program']) }", 'rb+' do |pipe|
              line = pipe.gets
              case line
                when /^pid: \d+$/
                  cid = Integer line[/\d+/]
                else
                  begin
                    buf = pipe.read
                    buf = "#{ line }#{ buf }"
                    e = Marshal.load buf
                    raise unless Exception === e
                    raise e
                  rescue
                    raise "systemu: Error - process interrupted!\n#{ buf }\n"
                  end
              end
              thread = new_thread cid, @block if @block
              pipe.read rescue nil
            end
          }
          status = $?
        ensure
          if thread
            begin
              class << status
                attr 'thread'
              end
              status.instance_eval{ @thread = thread }
            rescue
              42
            end
          end
        end

        if @stdout or @stderr
          open(c['stdout'], 'rb'){|f| relay f => @stdout} if @stdout
          open(c['stderr'], 'rb'){|f| relay f => @stderr} if @stderr
          status
        else
          [status, open(c['stdout'], 'rb'){|f| f.read}, open(c['stderr'], 'rb'){|f| f.read}]
        end
      end
    end

tmpdir(d = Dir.tmpdir, max = 42, &b) click to toggle source

    # File lib/systemu.rb, line 237
    def tmpdir d = Dir.tmpdir, max = 42, &b
      i = -1 and loop{
        i += 1

        tmp = File.join(d, slug_for("systemu_#{ @host }_#{ @ppid }_#{ @pid }_#{ rand }_#{ i += 1 }"))

        begin
          Dir.mkdir tmp
        rescue Errno::EEXIST
          raise if i >= max
          next
        end

        break(
          if b
            begin
              b.call tmp
            ensure
              FileUtils.rm_rf tmp unless SystemU.turd
            end
          else
            tmp
          end
        )
      }
    end

version() click to toggle source

    # File lib/systemu.rb, line 18
    def version() SystemUniversal::VERSION end

[Validate]

Generated with the Darkfish Rdoc Generator 2.