/usr/lib/ruby/vendor_ruby/specinfra/backend/exec.rb is in ruby-specinfra 2.66.0-1.
This file is owned by root:root, with mode 0o644.
The actual contents of the file can be viewed below.
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 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 | require 'singleton'
require 'fileutils'
require 'shellwords'
module Specinfra
module Backend
class Exec < Base
def run_command(cmd, opts={})
cmd = build_command(cmd)
cmd = add_pre_command(cmd)
stdout, stderr, exit_status = with_env do
spawn_command(cmd)
end
if @example
@example.metadata[:command] = cmd
@example.metadata[:stdout] = stdout
end
CommandResult.new :stdout => stdout, :stderr => stderr, :exit_status => exit_status
end
def send_file(from, to)
FileUtils.cp(from, to)
end
def send_directory(from, to)
FileUtils.cp_r(from, to)
end
def build_command(cmd)
shell = get_config(:shell) || '/bin/sh'
cmd = cmd.shelljoin if cmd.is_a?(Array)
shell = shell.shellescape
if get_config(:interactive_shell)
shell << " -i"
end
if get_config(:login_shell)
shell << " -l"
end
cmd = "#{shell} -c #{cmd.to_s.shellescape}"
path = get_config(:path)
if path
cmd = %Q{env PATH="#{path}" #{cmd}}
end
cmd
end
private
def spawn_command(cmd)
stdout, stderr = '', ''
begin
quit_r, quit_w = IO.pipe
out_r, out_w = IO.pipe
err_r, err_w = IO.pipe
th = Thread.new do
output = {
quit_r => "",
out_r => "",
err_r => ""
}
handlers = {
quit_r => nil,
out_r => @stdout_handler,
err_r => @stderr_handler
}
begin
loop do
readable_ios, = IO.select(output.keys)
readable_ios.each do |fd|
loop do
begin
out = fd.read_nonblock(4096)
output[fd] << out
handlers[fd].call(out) if handlers[fd]
rescue Errno::EAGAIN
# Ruby 2.2 has more specific exception class IO::EAGAINWaitReadable
break
end
end
end
break unless output[quit_r].empty?
end
rescue EOFError
ensure
# Consume remained stdout and stderr from buffer
output.keys.each do |fd|
loop do
begin
out = fd.read_nonblock(4096)
output[fd] << out
handlers[fd].call(out) if handlers[fd]
rescue Errno::EAGAIN, EOFError
# Ruby 2.2 has more specific exception class IO::EAGAINWaitReadable
break
end
end
end
stdout = output[out_r]
stderr = output[err_r]
quit_r.close unless quit_r.closed?
out_r.close unless out_r.closed?
err_r.close unless err_r.closed?
end
end
th.abort_on_exception = true
pid = spawn(cmd, :out => out_w, :err => err_w)
pid, stats = Process.waitpid2(pid)
out_w.close
err_w.close
begin
quit_w.syswrite 1
rescue Errno::EPIPE
end
th.value # wait
ensure
quit_w.close unless quit_w.closed?
end
return stdout, stderr, stats.exitstatus
end
def with_env
keys = %w[BUNDLER_EDITOR BUNDLE_BIN_PATH BUNDLE_GEMFILE
RUBYOPT GEM_HOME GEM_PATH GEM_CACHE]
keys.each { |key| ENV["_SPECINFRA_#{key}"] = ENV[key] ; ENV.delete(key) }
env = get_config(:env) || {}
env[:LANG] ||= 'C'
env.each do |key, value|
key = key.to_s
ENV["_SPECINFRA_#{key}"] = ENV[key];
ENV[key] = value
end
yield
ensure
keys.each { |key| ENV[key] = ENV.delete("_SPECINFRA_#{key}") }
env.each do |key, value|
key = key.to_s
ENV[key] = ENV.delete("_SPECINFRA_#{key}");
end
end
def add_pre_command(cmd)
if get_config(:pre_command)
pre_cmd = build_command(get_config(:pre_command))
"#{pre_cmd} && #{cmd}"
else
cmd
end
end
end
end
end
|