Module: PatchELF::CLI
Overview
For command line interface to parsing arguments.
Constant Summary collapse
- SCRIPT_NAME =
Name of binary.
'patchelf.rb'- USAGE =
CLI usage string.
format('Usage: %s [OPTIONS] INPUT_FILE [OUTPUT_FILE]', SCRIPT_NAME).freeze
Class Method Summary collapse
- .option_parser ⇒ OptionParser
-
.parse?(argv) ⇒ Boolean
Parse options and capture the input and optional output paths.
-
.patch_requests ⇒ void
Apply all requested ELF mutations to the patcher.
- .patcher ⇒ PatchELF::Patcher
-
.readonly ⇒ void
Print the requested ELF metadata.
-
.work(argv) ⇒ Integer
Main method of CLI.
Class Method Details
.option_parser ⇒ OptionParser
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 |
# File 'lib/patchelf/cli.rb', line 105 def option_parser @option_parser ||= OptionParser.new do |opts| opts. = USAGE opts.on('--print-interpreter', '--pi', 'Show interpreter\'s name.') do @options[:print] << :interpreter end opts.on('--print-needed', '--pn', 'Show needed libraries specified in DT_NEEDED.') do @options[:print] << :needed end opts.on('--print-runpath', '--pr', 'Show the path specified in DT_RUNPATH.') do @options[:print] << :runpath end opts.on('--print-soname', '--ps', 'Show soname specified in DT_SONAME.') do @options[:print] << :soname end opts.on('--set-interpreter INTERP', '--interp INTERP', 'Set interpreter\'s name.') do |interp| @options[:set][:interpreter] = interp end opts.on('--set-needed LIB1,LIB2,LIB3', '--needed LIB1,LIB2,LIB3', Array, 'Set needed libraries, this will remove all existent needed libraries.') do |needs| @options[:set][:needed] = needs end opts.on('--add-needed LIB', 'Append a new needed library.') do |lib| @options[:needed] << [:add, lib] end opts.on('--remove-needed LIB', 'Remove a needed library.') do |lib| @options[:needed] << [:remove, lib] end opts.on('--replace-needed LIB1,LIB2', Array, 'Replace needed library LIB1 as LIB2.') do |libs| @options[:needed] << [:replace, libs] end opts.on('--set-runpath PATH', '--runpath PATH', 'Set the path of runpath.') do |path| @options[:set][:runpath] = path end opts.on( '--force-rpath', 'According to the ld.so docs, DT_RPATH is obsolete,', "#{SCRIPT_NAME} will always try to get/set DT_RUNPATH first.", 'Use this option to force every operations related to runpath (e.g. --runpath)', 'to consider \'DT_RPATH\' instead of \'DT_RUNPATH\'.' ) do @options[:force_rpath] = true end opts.on('--set-soname SONAME', '--so SONAME', 'Set name of a shared library.') do |soname| @options[:set][:soname] = soname end opts.on('-h', '--help', 'Show this help.') do @options[:action] = :help end opts.on('--version', 'Show current gem\'s version.') do @options[:action] = :version end end end |
.parse?(argv) ⇒ Boolean
Parse options and capture the input and optional output paths.
93 94 95 96 97 98 99 100 101 102 |
# File 'lib/patchelf/cli.rb', line 93 def parse?(argv) remain = option_parser.permute(argv) return true if @options[:action] return false if remain.first.nil? raise OptionParser::InvalidArgument, 'too many positional arguments' if remain.length > 2 @options[:in_file] = remain.first @options[:out_file] = remain[1] # can be nil true end |
.patch_requests ⇒ void
This method returns an undefined value.
Apply all requested ELF mutations to the patcher.
80 81 82 83 84 85 86 87 88 |
# File 'lib/patchelf/cli.rb', line 80 def patch_requests @options[:set].each do |sym, val| patcher.__send__(:"#{sym}=", val) end @options[:needed].each do |type, val| patcher.__send__(:"#{type}_needed", *val) end end |
.patcher ⇒ PatchELF::Patcher
62 63 64 |
# File 'lib/patchelf/cli.rb', line 62 def patcher @patcher end |
.readonly ⇒ void
This method returns an undefined value.
Print the requested ELF metadata.
68 69 70 71 72 73 74 75 76 |
# File 'lib/patchelf/cli.rb', line 68 def readonly @options[:print].uniq.each do |s| content = patcher.__send__(s) next if content.nil? s = :rpath if @options[:force_rpath] && s == :runpath $stdout.puts "#{s}: #{Array(content).join(' ')}" end end |
.work(argv) ⇒ Integer
Main method of CLI.
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 |
# File 'lib/patchelf/cli.rb', line 27 def work(argv) @options = { set: {}, print: [], needed: [] } unless parse?(argv) $stdout.puts option_parser return 1 end case @options[:action] when :version $stdout.puts "PatchELF Version #{PatchELF::VERSION}" return 0 when :help $stdout.puts option_parser return 0 end # Now the options are (hopefully) valid, let's process the ELF file. @patcher = PatchELF::Patcher.new(@options[:in_file]) patcher.use_rpath! if @options[:force_rpath] readonly patch_requests patcher.save(@options[:out_file]) 0 rescue OptionParser::ParseError, ELFTools::ELFError, SystemCallError, NotImplementedError => e PatchELF::Logger.error(e.) 1 end |