summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--lib/mixlib/shellout.rb1
-rw-r--r--lib/mixlib/shellout/unix.rb35
-rw-r--r--spec/mixlib/shellout/shellout_spec.rb13
3 files changed, 40 insertions, 9 deletions
diff --git a/lib/mixlib/shellout.rb b/lib/mixlib/shellout.rb
index 2082f41..8e8b7ea 100644
--- a/lib/mixlib/shellout.rb
+++ b/lib/mixlib/shellout.rb
@@ -256,7 +256,6 @@ module Mixlib
private
- # FIXME: This can be done better
def parse_options(opts)
opts.each do |option, setting|
case option.to_s
diff --git a/lib/mixlib/shellout/unix.rb b/lib/mixlib/shellout/unix.rb
index fe307b5..aa62272 100644
--- a/lib/mixlib/shellout/unix.rb
+++ b/lib/mixlib/shellout/unix.rb
@@ -40,6 +40,8 @@ module Mixlib
@result = nil
@execution_time = 0
+ write_to_child_stdin
+
# Ruby 1.8.7 and 1.8.6 from mid 2009 try to allocate objects during GC
# when calling IO.select and IO#read. Some OS Vendors are not interested
# in updating their ruby packages (Apple, *cough*) and we *have to*
@@ -114,10 +116,14 @@ module Mixlib
end
def initialize_ipc
- @stdout_pipe, @stderr_pipe, @process_status_pipe = IO.pipe, IO.pipe, IO.pipe
+ @stdin_pipe, @stdout_pipe, @stderr_pipe, @process_status_pipe = IO.pipe, IO.pipe, IO.pipe, IO.pipe
@process_status_pipe.last.fcntl(Fcntl::F_SETFD, Fcntl::FD_CLOEXEC)
end
+ def child_stdin
+ @stdin_pipe[1]
+ end
+
def child_stdout
@stdout_pipe[0]
end
@@ -131,23 +137,25 @@ module Mixlib
end
def close_all_pipes
+ child_stdin.close unless child_stdin.closed?
child_stdout.close unless child_stdout.closed?
child_stderr.close unless child_stderr.closed?
child_process_status.close unless child_process_status.closed?
end
- # replace stdout, and stderr with pipes to the parent, and close the
- # reader side of the error marshaling side channel. Close STDIN so when we
- # exec, the new program will know it's never getting input ever.
+ # Replace stdout, and stderr with pipes to the parent, and close the
+ # reader side of the error marshaling side channel.
+ #
+ # If there is no input, close STDIN so when we exec,
+ # the new program will know it's never getting input ever.
def configure_subprocess_file_descriptors
process_status_pipe.first.close
# HACK: for some reason, just STDIN.close isn't good enough when running
# under ruby 1.9.2, so make it good enough:
- stdin_reader, stdin_writer = IO.pipe
- stdin_writer.close
- STDIN.reopen stdin_reader
- stdin_reader.close
+ stdin_pipe.last.close
+ STDIN.reopen stdin_pipe.first
+ stdin_pipe.first.close unless input
stdout_pipe.first.close
STDOUT.reopen stdout_pipe.last
@@ -158,14 +166,18 @@ module Mixlib
stderr_pipe.last.close
STDOUT.sync = STDERR.sync = true
+ STDIN.sync = true if input
end
def configure_parent_process_file_descriptors
# Close the sides of the pipes we don't care about
+ stdin_pipe.first.close
+ stdin_pipe.last.close unless input
stdout_pipe.last.close
stderr_pipe.last.close
process_status_pipe.last.close
# Get output as it happens rather than buffered
+ child_stdin.sync = true if input
child_stdout.sync = true
child_stderr.sync = true
@@ -178,6 +190,13 @@ module Mixlib
@open_pipes ||= [child_stdout, child_stderr]
end
+ # Keep this unbuffered for now
+ def write_to_child_stdin
+ return unless input
+ child_stdin << input
+ child_stdin.close # Kick things off
+ end
+
def read_stdout_to_buffer
while chunk = child_stdout.read_nonblock(READ_SIZE)
@stdout << chunk
diff --git a/spec/mixlib/shellout/shellout_spec.rb b/spec/mixlib/shellout/shellout_spec.rb
index 59afce0..81f58d6 100644
--- a/spec/mixlib/shellout/shellout_spec.rb
+++ b/spec/mixlib/shellout/shellout_spec.rb
@@ -365,6 +365,19 @@ describe Mixlib::ShellOut do
end
end
+ # FIXME: Add Windows support
+ context "with an input", :unix_only => true do
+ subject { stdout }
+
+ let(:input) { 'hello' }
+ let(:ruby_code) { 'STDIN.sync = true; STDOUT.sync = true; puts gets' }
+ let(:options) { { :input => input } }
+
+ it "should copy the input to the child's stdin" do
+ should eql("hello#{LINE_ENDING}")
+ end
+ end
+
context "when running different types of command" do
context 'with spaces in the path' do
subject { chomped_stdout }