diff --git a/lib/open3.rb b/lib/open3.rb index 2aec1fd..6781a03 100644 --- a/lib/open3.rb +++ b/lib/open3.rb @@ -490,12 +490,12 @@ class << self # # - Creates a child process, by calling Open3.popen3 with the given arguments # (except for certain entries in hash +options+; see below). - # - Returns as strings +stdout+ and +stderr+ the standard output + # - Returns as strings +stdout_s+ and +stderr_s+ the standard output # and standard error of the child process. # - Returns as +status+ a Process::Status object # that represents the exit status of the child process. # - # Returns the array [stdin_s, stdout_s, status]: + # Returns the array [stdout_s, stderr_s, status]: # # stdout_s, stderr_s, status = Open3.capture3('echo "Foo"') # # => ["Foo\n", "", #] @@ -612,11 +612,11 @@ def capture3(*cmd) # # - Creates a child process, by calling Open3.popen3 with the given arguments # (except for certain entries in hash +options+; see below). - # - Returns as string +stdout+ the standard output of the child process. + # - Returns as string +stdout_s+ the standard output of the child process. # - Returns as +status+ a Process::Status object # that represents the exit status of the child process. # - # Returns the array [stdin_s, status]: + # Returns the array [stdout_s, status]: # # stdout_s, status = Open3.capture2('echo "Foo"') # # => ["Foo\n", #] @@ -638,6 +638,7 @@ def capture3(*cmd) # and its string value is sent to the command's standard input: # # Open3.capture2('tee', stdin_data: 'Foo') + # # # => ["Foo", #] # # the internal streams are set to binary mode. @@ -724,21 +725,94 @@ def capture2(*cmd) end module_function :capture2 - # Open3.capture2e captures the standard output and the standard error of a command. + # :call-seq: + # Open3.capture2e([env, ] command_line, options = {}) -> [stdout_and_stderr_s, status] + # Open3.capture2e([env, ] exe_path, *args, options = {}) -> [stdout_and_stderr_s, status] + # + # Basically a wrapper for Open3.popen3 that: + # + # - Creates a child process, by calling Open3.popen3 with the given arguments + # (except for certain entries in hash +options+; see below). + # - Returns as string +stdout_and_stderr_s+ the merged standard output + # and standard error of the child process. + # - Returns as +status+ a Process::Status object + # that represents the exit status of the child process. + # + # Returns the array [stdout_and_stderr_s, status]: + # + # stdout_and_stderr_s, status = Open3.capture2e('echo "Foo"') + # # => ["Foo\n", #] + # + # Like Process.spawn, this method has potential security vulnerabilities + # if called with untrusted input; + # see {Command Injection}[rdoc-ref:command_injection.rdoc]. # - # stdout_and_stderr_str, status = Open3.capture2e([env,] cmd... [, opts]) + # Unlike Process.spawn, this method waits for the child process to exit + # before returning, so the caller need not do so. # - # The arguments env, cmd and opts are passed to Open3.popen3 except - # opts[:stdin_data] and opts[:binmode]. See Process.spawn. + # Argument +options+ is a hash of options for the new process; + # see {Execution Options}[rdoc-ref:Process@Execution+Options]. # - # If opts[:stdin_data] is specified, it is sent to the command's standard input. + # The hash +options+ is passed to method Open3.popen3; + # two options have local effect in method Open3.capture2e: # - # If opts[:binmode] is true, internal pipes are set to binary mode. + # - If entry options[:stdin_data] exists, the entry is removed + # and its string value is sent to the command's standard input: + # + # Open3.capture2e('tee', stdin_data: 'Foo') + # # => ["Foo", #] + # + # the internal streams are set to binary mode. + # + # The single required argument is one of the following: + # + # - +command_line+ if it is a string, + # and if it begins with a shell reserved word or special built-in, + # or if it contains one or more metacharacters. + # - +exe_path+ otherwise. + # + # Argument +command_line+ + # + # \String argument +command_line+ is a command line to be passed to a shell; + # it must begin with a shell reserved word, begin with a special built-in, + # or contain meta characters: + # + # Open3.capture2e('if true; then echo "Foo"; fi') # Shell reserved word. + # # => ["Foo\n", #] + # Open3.capture2e('echo') # Built-in. + # # => ["\n", #] + # Open3.capture2e('date > date.tmp') # Contains meta character. + # # => ["", #] + # + # The command line may also contain arguments and options for the command: + # + # Open3.capture2e('echo "Foo"') + # # => ["Foo\n", #] + # + # Argument +exe_path+ + # + # Argument +exe_path+ is one of the following: + # + # - The string path to an executable to be called. + # - A 2-element array containing the path to an executable + # and the string to be used as the name of the executing process. # # Example: # - # # capture make log - # make_log, s = Open3.capture2e("make") + # Open3.capture2e('/usr/bin/date') + # # => ["Sat Sep 30 09:01:46 AM CDT 2023\n", #] + # + # Ruby invokes the executable directly, with no shell and no shell expansion: + # + # Open3.capture2e('doesnt_exist') # Raises Errno::ENOENT + # + # If one or more +args+ is given, each is an argument or option + # to be passed to the executable: + # + # Open3.capture2e('echo', 'C #') + # # => ["C #\n", #] + # Open3.capture2e('echo', 'hello', 'world') + # # => ["hello world\n", #] # def capture2e(*cmd) if Hash === cmd.last