Bio::Command is a collection of useful methods for execution of external commands or web applications. Any wrapper class for applications shall use this class.
Library internal use only. Users should not directly use it.
Executes the program. Automatically select popen for Ruby 1.9 or Windows environment and fork for the others. A block must be given. An IO object is passed to the block.
Available options:
:chdir => "path" : changes working directory to the specified path.
Arguments:
Returns |
(undefined) |
# File lib/bio/command.rb, line 196 def call_command(cmd, options = {}, &block) #:yields: io if RUBY_VERSION >= "1.9.0" then return call_command_popen(cmd, options, &block) elsif no_fork? then call_command_popen(cmd, options, &block) else begin call_command_fork(cmd, options, &block) rescue NotImplementedError # fork(2) not implemented @@no_fork = true call_command_popen(cmd, options, &block) end end end
This method is internally called from the call_command method. In normal case, use call_command, and do not call this method directly.
Executes the program via fork (by using IO.popen(“-”)) and exec. A block must be given. An IO object is passed to the block.
See the document of call_command for available options.
Note for Ruby 1.8: In Ruby 1.8, from the view point of security, this method is recommended rather than call_command_popen. However, this method might have problems with multi-threads.
Note for Ruby 1.9: In Ruby 1.9, this method can not be used, because Thread.critical is removed. In Ruby 1.9, call_command_popen is safe and robust enough, and is the recommended way, because IO.popen is improved to get a command-line as an array without calling shell.
Arguments:
Returns |
(undefined) |
# File lib/bio/command.rb, line 373 def call_command_fork(cmd, options = {}) dir = options[:chdir] cmd = safe_command_line_array(cmd) begin tc, Thread.critical, flag0, flag1 = Thread.critical, true, true, true IO.popen("-", "r+") do |io| if io then # parent flag0, Thread.critical, flag1 = false, tc, false yield io else # child Thread.critical = true # for safety, though already true GC.disable # chdir to options[:chdir] if available begin Dir.chdir(dir) if dir rescue Exception Process.exit!(1) end # executing the command begin Kernel.exec(*cmd) rescue Errno::ENOENT, Errno::EACCES Process.exit!(127) rescue Exception end Process.exit!(1) end end ensure # When IO.popen("-") raises error, Thread.critical will be set here. Thread.critical = tc if flag0 or flag1 #warn 'Thread.critical might have wrong value.' if flag0 != flag1 end end
Executes the program via Open3.popen3 A block must be given. IO objects are passed to the block.
You would use this method only when you really need to get stderr.
Arguments:
(required) cmd: Array containing String objects
Returns |
(undefined) |
# File lib/bio/command.rb, line 419 def call_command_open3(cmd) cmd = safe_command_line_array(cmd) Open3.popen3(*cmd) do |pin, pout, perr| yield pin, pout, perr end end
This method is internally called from the call_command method. In normal case, use call_command, and do not call this method directly.
Executes the program via IO.popen for OS which doesn’t support fork. A block must be given. An IO object is passed to the block.
See the document of call_command for available options.
Note for Ruby 1.8: In Ruby 1.8, although shell unsafe characters are escaped. If inescapable characters exists, it raises RuntimeError. So, call_command_fork is normally recommended.
Note for Ruby 1.9: In Ruby 1.9, call_command_popen is safe and robust enough, and is the recommended way, because IO.popen is improved to get a command-line as an array without calling shell.
Arguments:
Returns |
(undefined) |
# File lib/bio/command.rb, line 235 def call_command_popen(cmd, options = {}, &block) if RUBY_VERSION >= "1.9.0" then if RUBY_ENGINE == 'jruby' then _call_command_popen_jruby19(cmd, options, &block) else _call_command_popen_ruby19(cmd, options, &block) end else _call_command_popen_ruby18(cmd, options, &block) end end
Escape special characters in command line string for UNIX shells.
Arguments:
(required) str: String
Returns |
String object |
# File lib/bio/command.rb, line 110 def escape_shell_unix(str) str = str.to_s raise 'cannot escape control characters' if UNESCAPABLE_CHARS =~ str str.gsub(UNSAFE_CHARS_UNIX) { |x| "\\#{x}" } end
Escape special characters in command line string for cmd.exe on Windows.
Arguments:
(required) str: String
Returns |
String object |
# File lib/bio/command.rb, line 95 def escape_shell_windows(str) str = str.to_s raise 'cannot escape control characters' if UNESCAPABLE_CHARS =~ str if QUOTE_CHARS_WINDOWS =~ str then '"' + str.gsub(/\"/, '""') + '"' else String.new(str) end end
Same as:
http = Net::HTTP.new(...); http.post_form(path, params)
and it uses proxy if an environment variable (same as OpenURI.open_uri) is set. In addition, header can be set. (Note that Content-Type and Content-Length are automatically set by default.) uri must be a URI object, params must be a hash, and header must be a hash.
Arguments:
(required) http: Net::HTTP object or compatible object
(required) path: String
(optional) params: Hash containing parameters
(optional) header: Hash containing header strings
Returns |
(same as Net::HTTP::post_form) |
# File lib/bio/command.rb, line 775 def http_post_form(http, path, params = nil, header = {}) data = make_cgi_params(params) hash = { 'Content-Type' => 'application/x-www-form-urlencoded', 'Content-Length' => data.length.to_s } hash.update(header) http.post(path, data, hash) end
Builds parameter string for from Hash of parameters for application/x-www-form-urlencoded.
Arguments:
(required) params: Hash containing parameters
Returns |
# File lib/bio/command.rb, line 829 def make_cgi_params(params) data = "" case params when Hash data = params.map do |key, val| make_cgi_params_key_value(key, val) end.join('&') when Array case params.first when Hash data = params.map do |hash| hash.map do |key, val| make_cgi_params_key_value(key, val) end end.join('&') when Array data = params.map do |key, val| make_cgi_params_key_value(key, val) end.join('&') when String data = params.map do |str| key, val = str.split(/\=/, 2) if val then make_cgi_params_key_value(key, val) else CGI.escape(str) end end.join('&') end when String data = URI.escape(params.strip) end return data end
Builds parameter string for from a key string and a value (or values) for application/x-www-form-urlencoded.
Arguments:
Returns |
# File lib/bio/command.rb, line 872 def make_cgi_params_key_value(key, value) result = [] case value when Array value.each do |val| result << [key, val].map {|x| CGI.escape(x.to_s) }.join('=') end else result << [key, value].map {|x| CGI.escape(x.to_s) }.join('=') end return result end
Generate command line string with special characters escaped.
Arguments:
(required) ary: Array containing String objects
Returns |
String object |
# File lib/bio/command.rb, line 134 def make_command_line(ary) if windows_platform? then make_command_line_windows(ary) else make_command_line_unix(ary) end end
Backport of Dir.mktmpdir in Ruby 1.9.
Same as Dir.mktmpdir(prefix_suffix) in Ruby 1.9.
Arguments:
(optional) prefix_suffix: String (or Array, etc.)
(optional) tmpdir: String: temporary directory’s path
# File lib/bio/command.rb, line 573 def mktmpdir(prefix_suffix = nil, tmpdir = nil, &block) begin Dir.mktmpdir(prefix_suffix, tmpdir, &block) rescue NoMethodError # backported from Ruby 1.9.2-preview1. # ***** Below is excerpted from Ruby 1.9.2-preview1's lib/tmpdir.rb **** # ***** Be careful about copyright. **** case prefix_suffix when nil prefix = "d" suffix = "" when String prefix = prefix_suffix suffix = "" when Array prefix = prefix_suffix[0] suffix = prefix_suffix[1] else raise ArgumentError, "unexpected prefix_suffix: #{prefix_suffix.inspect}" end tmpdir ||= Dir.tmpdir t = Time.now.strftime("%Y%m%d") n = nil begin path = "#{tmpdir}/#{prefix}#{t}-#{$$}-#{rand(0x100000000).to_s(36)}" path << "-#{n}" if n path << suffix Dir.mkdir(path, 0700) rescue Errno::EEXIST n ||= 0 n += 1 retry end if block_given? begin yield path ensure remove_entry_secure path end else path end # ***** Above is excerpted from Ruby 1.9.2-preview1's lib/tmpdir.rb **** end end
Same as:
Net::HTTP.new(address, port)
and it uses proxy if an environment variable (same as OpenURI.open_uri) is set.
Arguments:
(required) address: String containing host name or IP address
(optional) port: port (sanme as Net::HTTP::start)
Returns |
(same as Net::HTTP.new except for proxy support) |
# File lib/bio/command.rb, line 745 def new_http(address, port = 80) uri = URI.parse("http://#{address}:#{port}") # Note: URI#find_proxy is an unofficial method defined in open-uri.rb. # If the spec of open-uri.rb would be changed, we should change below. if proxyuri = uri.find_proxy then raise 'Non-HTTP proxy' if proxyuri.class != URI::HTTP Net::HTTP.new(address, port, proxyuri.host, proxyuri.port) else Net::HTTP.new(address, port) end end
CAUTION Bio::Command INTERNAL USE ONLY. Users must NOT use the method. The method will be removed when it is not needed.
Checks if the OS does not support fork(2) system call. When not supported, it returns true. When supported or unknown, it returns false or nil.
Known issues:
It might make a mistake in minor platforms/architectures/interpreters.
Returns |
true, false or nil. |
# File lib/bio/command.rb, line 80 def no_fork? if (defined?(@@no_fork) && @@no_fork) or windows_platform? or /java/ =~ RUBY_PLATFORM then true else false end end
Same as: Net::HTTP.post_form(uri, params) and it uses proxy if an environment variable (same as OpenURI.open_uri) is set. In addition, header can be set. (Note that Content-Type and Content-Length are automatically set by default.) uri must be a URI object, params must be a hash, and header must be a hash.
Arguments:
(required) uri: URI object or String
(optional) params: Hash containing parameters
(optional) header: Hash containing header strings
Returns |
(same as Net::HTTP::post_form) |
# File lib/bio/command.rb, line 804 def post_form(uri, params = nil, header = {}) unless uri.is_a?(URI) uri = URI.parse(uri) end data = make_cgi_params(params) hash = { 'Content-Type' => 'application/x-www-form-urlencoded', 'Content-Length' => data.length.to_s } hash.update(header) start_http(uri.host, uri.port) do |http| http.post(uri.path, data, hash) end end
Executes the program with the query (String) given to the standard input, waits the program termination, and returns the output data printed to the standard output as a string.
Automatically select popen for Ruby 1.9 or Windows environment and fork for the others.
Available options:
:chdir => "path" : changes working directory to the specified path.
Arguments:
Returns |
String or nil |
# File lib/bio/command.rb, line 442 def query_command(cmd, query = nil, options = {}) if RUBY_VERSION >= "1.9.0" then return query_command_popen(cmd, query, options) elsif no_fork? then query_command_popen(cmd, query, options) else begin query_command_fork(cmd, query, options) rescue NotImplementedError # fork(2) not implemented @@no_fork = true query_command_fork(cmd, query, options) end end end
This method is internally called from the query_command method. In normal case, use query_command, and do not call this method directly.
Executes the program with the query (String) given to the standard input, waits the program termination, and returns the output data printed to the standard output as a string.
Fork (by using IO.popen(“-”)) and exec is used to execute the program.
See the document of query_command for available options.
See the document of call_command_fork for the security and Ruby version specific issues.
Arguments:
Returns |
String or nil |
# File lib/bio/command.rb, line 507 def query_command_fork(cmd, query = nil, options = {}) ret = nil call_command_fork(cmd, options) do |io| io.sync = true io.print query if query io.close_write ret = io.read end ret end
Executes the program via Open3.popen3 with the query (String) given to the stain, waits the program termination, and returns the data from stdout and stderr as an array of the strings.
You would use this method only when you really need to get stderr.
Arguments:
Returns |
Array containing 2 objects: output string (or nil) and stderr string (or nil) |
# File lib/bio/command.rb, line 529 def query_command_open3(cmd, query = nil) errorlog = nil cmd = safe_command_line_array(cmd) Open3.popen3(*cmd) do |pin, pout, perr| perr.sync = true t = Thread.start { errorlog = perr.read } begin pin.print query if query pin.close output = pout.read ensure t.join end [ output, errorlog ] end end
This method is internally called from the query_command method. In normal case, use query_command, and do not call this method directly.
Executes the program with the query (String) given to the standard input, waits the program termination, and returns the output data printed to the standard output as a string.
See the document of query_command for available options.
See the document of call_command_popen for the security and Ruby version specific issues.
Arguments:
Returns |
String or nil |
# File lib/bio/command.rb, line 476 def query_command_popen(cmd, query = nil, options = {}) ret = nil call_command_popen(cmd, options) do |io| io.sync = true io.print query if query io.close_write ret = io.read end ret end
Same as FileUtils.remove_entry_secure after Ruby 1.8.3. In Ruby 1.8.2 or previous version, it only shows warning message and does nothing.
It is strongly recommended using Ruby 1.8.5 or later.
Arguments:
(required) path: String
(optional) force: boolean
# File lib/bio/command.rb, line 555 def remove_entry_secure(path, force = false) begin FileUtils.remove_entry_secure(path, force) rescue NoMethodError warn "The temporary file or directory is not removed because of the lack of FileUtils.remove_entry_secure. Use Ruby 1.8.3 or later (1.8.5 or later is strongly recommended): #{path}" nil end end
Returns an Array of command-line command and arguments that can be safely passed to Kernel.exec etc. If the given array is already safe (or empty), returns the given array.
Arguments:
(required) ary: Array
Returns |
Array |
# File lib/bio/command.rb, line 169 def safe_command_line_array(ary) ary = ary.to_ary return ary if ary.size >= 2 or ary.empty? if ary.size != 1 then raise 'Bug: assersion of ary.size == 1 failed' end arg0 = ary[0] begin arg0 = arg0.to_ary rescue NoMethodError arg0 = [ arg0, arg0 ] end [ arg0 ] end
Same as:
Net::HTTP.start(address, port)
and it uses proxy if an environment variable (same as OpenURI.open_uri) is set.
Arguments:
(required) address: String containing host name or IP address
(optional) port: port (sanme as Net::HTTP::start)
Returns |
(same as Net::HTTP::start except for proxy support) |
# File lib/bio/command.rb, line 721 def start_http(address, port = 80, &block) uri = URI.parse("http://#{address}:#{port}") # Note: URI#find_proxy is an unofficial method defined in open-uri.rb. # If the spec of open-uri.rb would be changed, we should change below. if proxyuri = uri.find_proxy then raise 'Non-HTTP proxy' if proxyuri.class != URI::HTTP http = Net::HTTP.Proxy(proxyuri.host, proxyuri.port) else http = Net::HTTP end http.start(address, port, &block) end
CAUTION Bio::Command INTERNAL USE ONLY. Users must NOT use the method. The method will be removed when it is not needed.
Checks if the program is running on Microsoft Windows. If Windows, returns true. Otherwise, returns false. Note that Cygwin is not treated as Windows.
Known issues:
It might make a mistake in minor platforms/architectures/interpreters.
When running JRuby on Cygwin, the result is unknown.
Returns |
true or false |
# File lib/bio/command.rb, line 50 def windows_platform? case RUBY_PLATFORM when /(?:mswin|bccwin|mingw)(?:32|64)/ true when /java/ # Reference: Redmine's platform.rb # http://www.redmine.org/projects/redmine/repository/revisions/1753/entry/trunk/lib/redmine/platform.rb if /windows/ =~ (ENV['OS'] || ENV['os']).to_s then true else false end else false end end
Generated with the Darkfish Rdoc Generator 2.