[ruby/open3] [DOC] RDoc for Open3

This commit is contained in:
Peter Zhu 2023-09-28 14:37:44 -04:00
parent 56cf1633a2
commit cc6ffceeec

View file

@ -151,6 +151,8 @@ module Open3
# when the unread buffer fills. # when the unread buffer fills.
# To avoid that, +stdout+ and +stderr+ should be read simultaneously # To avoid that, +stdout+ and +stderr+ should be read simultaneously
# (using threads or IO.select). # (using threads or IO.select).
#
# Related: Open3.popen2, Open3.popen2e.
def popen3(*cmd, &block) def popen3(*cmd, &block)
if Hash === cmd.last if Hash === cmd.last
opts = cmd.pop.dup opts = cmd.pop.dup
@ -172,46 +174,117 @@ module Open3
end end
module_function :popen3 module_function :popen3
# Open3.popen2 is similar to Open3.popen3 except that it doesn't create a pipe for # :call-seq:
# the standard error stream. # Open3.popen2([env, ] command_line, options = {}) -> [stdin, stdout, wait_thread]
# Open3.popen2([env, ] exe_path, *args, options = {}) -> [stdin, stdout, wait_thread]
# Open3.popen2([env, ] command_line, options = {}) {|stdin, stdout, wait_thread| ... } -> object
# Open3.popen2([env, ] exe_path, *args, options = {}) {|stdin, stdout, wait_thread| ... } -> object
# #
# Block form: # Basically a wrapper for Process.spawn that:
# #
# Open3.popen2([env,] cmd... [, opts]) {|stdin, stdout, wait_thr| # - Creates a child process, by calling Process.spawn with the given arguments.
# pid = wait_thr.pid # pid of the started process. # - Creates streams +stdin+ and +stdout+,
# ... # which are the standard input and standard output streams
# exit_status = wait_thr.value # Process::Status object returned. # in the child process.
# } # - Creates thread +wait_thread+ that waits for the child process to exit;
# the thread has method +pid+, which returns the process ID
# of the child process.
# #
# Non-block form: # With no block given, returns the array
# <tt>[stdin, stdout, wait_thread]</tt>.
# The caller should close each of the two returned streams.
# #
# stdin, stdout, wait_thr = Open3.popen2([env,] cmd... [, opts]) # stdin, stdout, wait_thread = Open3.popen2('echo')
# ... # # => [#<IO:fd 6>, #<IO:fd 7>, #<Process::Waiter:0x00007f58d52dbe98 run>]
# stdin.close # stdin and stdout should be closed explicitly in this form. # stdin.close
# stdout.close # stdout.close
# wait_thread.pid # => 2263572
# wait_thread.value # => #<Process::Status: pid 2263572 exit 0>
# #
# See Process.spawn for the optional hash arguments _env_ and _opts_. # With a block given, calls the block with the three variables
# (two streams and the wait thread)
# and returns the block's return value.
# The caller need not close the streams:
#
# Open3.popen2('echo') do |stdin, stdout, wait_thread|
# p stdin
# p stdout
# p wait_thread
# p wait_thread.pid
# p wait_thread.value
# end
#
# Output:
#
# #<IO:fd 6>
# #<IO:fd 7>
# #<Process::Waiter:0x00007f58d59a34b0 sleep>
# 2263636
# #<Process::Status: pid 2263636 exit 0>
#
# Like Process.spawn, this method has potential security vulnerabilities
# if called with untrusted input;
# see {Command Injection}[rdoc-ref:command_injection.rdoc].
#
# Unlike Process.spawn, this method waits for the child process to exit
# before returning, so the caller need not do so.
#
# Argument +options+ is a hash of options for the new process;
# see {Execution Options}[rdoc-ref:Process@Execution+Options].
#
# 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.
#
# <b>Argument +command_line+</b>
#
# \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.popen2('if true; then echo "Foo"; fi') {|*args| p args } # Shell reserved word.
# Open3.popen2('echo') {|*args| p args } # Built-in.
# Open3.popen2('date > date.tmp') {|*args| p args } # Contains meta character.
#
# Output (for each call above):
#
# # => [#<IO:(closed)>, #<IO:(closed)>, #<Process::Waiter:0x00007f7577dfe410 dead>]
#
# The command line may also contain arguments and options for the command:
#
# Open3.popen2('echo "Foo"') { |i, o, t| o.gets }
# "Foo\n"
#
# <b>Argument +exe_path+</b>
#
# 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: # Example:
# #
# Open3.popen2("wc -c") {|i,o,t| # Open3.popen2('/usr/bin/date') { |i, o, t| o.gets }
# i.print "answer to life the universe and everything" # # => "Thu Sep 28 09:41:06 AM CDT 2023\n"
# i.close
# p o.gets #=> "42\n"
# }
# #
# Open3.popen2("bc -q") {|i,o,t| # Ruby invokes the executable directly, with no shell and no shell expansion:
# i.puts "obase=13"
# i.puts "6 * 9"
# p o.gets #=> "42\n"
# }
# #
# Open3.popen2("dc") {|i,o,t| # Open3.popen2('doesnt_exist') { |i, o, t| o.gets } # Raises Errno::ENOENT
# i.print "42P"
# i.close
# p o.read #=> "*"
# }
# #
# If one or more +args+ is given, each is an argument or option
# to be passed to the executable:
#
# Open3.popen2('echo', 'C #') { |i, o, t| o.gets }
# # => "C #\n"
# Open3.popen2('echo', 'hello', 'world') { |i, o, t| o.gets }
# # => "hello world\n"
#
#
# Related: Open3.popen3, Open3.popen2e.
def popen2(*cmd, &block) def popen2(*cmd, &block)
if Hash === cmd.last if Hash === cmd.last
opts = cmd.pop.dup opts = cmd.pop.dup