This file is indexed.

/usr/share/ettercap/lua/third-party/getopt.lua is in ettercap-common 1:0.8.2-10build4.

This file is owned by root:root, with mode 0o644.

The actual contents of the file can be viewed below.

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 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
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
102
103
104
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
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
--- Simplified getopt, based on Svenne Panne's Haskell GetOpt.<br>
-- Usage:
-- <ul>
-- <li><code>prog = {<
--     name = <progname>,
--     [usage = <usage line>,]
--     [options = {
--        {{<name>[, ...]}, <desc>, [<type> [, <var>]]},
--        ...
--     },]
--     [banner = <banner string>,]
--     [purpose = <purpose string>,]
--     [notes = <additional notes>]
-- }</code></li>
-- <li>The <code>type</code> of option argument is one of <code>Req</code>(uired),
-- <code>Opt</code>(ional)</li>
-- <li>The <code>var</code>is a descriptive name for the option argument.</li>
-- <li><code>getopt.processArgs (prog)</code></li>
-- <li>Options take a single dash, but may have a double dash.</li>
-- <li>Arguments may be given as <code>-opt=arg</code> or <code>-opt arg</code>.</li>
-- <li>If an option taking an argument is given multiple times, only the
-- last value is returned; missing arguments are returned as 1.</li>
-- </ul>
-- getOpt, usageInfo and usage can be called directly (see
-- below, and the example at the end). Set _DEBUG.std to a non-nil
-- value to run the example.
-- <ul>
-- <li>TODO: Wrap all messages; do all wrapping in processArgs, not
-- usageInfo; use sdoc-like library (see string.format todos).</li>
-- <li>TODO: Don't require name to be repeated in banner.</li>
-- <li>TODO: Store version separately (construct banner?).</li>
-- </ul>

require "base"
local list = require "list"
require "string_ext"
local Object = require "object"

local M = {
  opt = {},
}


--- Perform argument processing
-- @param argIn list of command-line args
-- @param options options table
-- @param stop_at_nonopt if true, stop option processing at first non-option
-- @return table of remaining non-options
-- @return table of option key-value list pairs
-- @return table of error messages
local function getOpt (argIn, options, stop_at_nonopt)
  local noProcess = nil
  local argOut, optOut, errors = {[0] = argIn[0]}, {}, {}
  -- get an argument for option opt
  local function getArg (o, opt, arg, oldarg)
    if o.type == nil then
      if arg ~= nil then
        table.insert (errors, "option `" .. opt .. "' doesn't take an argument")
      end
    else
      if arg == nil and argIn[1] and
        string.sub (argIn[1], 1, 1) ~= "-" then
        arg = argIn[1]
        table.remove (argIn, 1)
      end
      if arg == nil and o.type == "Req" then
        table.insert (errors,  "option `" .. opt ..
                      "' requires an argument `" .. o.var .. "'")
        return nil
      end
    end
    return arg or 1 -- make sure arg has a value
  end

  local function parseOpt (opt, arg)
    local o = options.name[opt]
    if o ~= nil then
      o = o or {name = {opt}}
      optOut[o.name[1]] = optOut[o.name[1]] or {}
      table.insert (optOut[o.name[1]], getArg (o, opt, arg, optOut[o.name[1]]))
    else
      table.insert (errors, "unrecognized option `-" .. opt .. "'")
    end
  end
  while argIn[1] do
    local v = argIn[1]
    table.remove (argIn, 1)
    local _, _, dash, opt = string.find (v, "^(%-%-?)([^=-][^=]*)")
    local _, _, arg = string.find (v, "=(.*)$")
    if not dash and stop_at_nonopt then
      noProcess = true
    end
    if v == "--" then
      noProcess = true
    elseif not dash or noProcess then -- non-option
      table.insert (argOut, v)
    else -- option
      parseOpt (opt, arg)
    end
  end
  return argOut, optOut, errors
end


-- Object that defines a single Option entry.
local Option = Object {_init = {"name", "desc", "type", "var"}}

--- Options table constructor: adds lookup tables for the option names
local function makeOptions (t)
  local options, name = {}, {}
  local function appendOpt (v, nodupes)
    local dupe = false
    v = Option (v)
    for s in list.elems (v.name) do
      if name[s] then
	dupe = true
      end
      name[s] = v
    end
    if not dupe or nodupes ~= true then
      if dupe then warn ("duplicate option '%s'", s) end
      for s in list.elems (v.name) do name[s] = v end
      options = list.concat (options, {v})
    end
  end
  for v in list.elems (t or {}) do
    appendOpt (v)
  end
  -- Unless they were supplied already, add version and help options
  appendOpt ({{"version", "V"}, "print version information, then exit"},
             true)
  appendOpt ({{"help", "h"}, "print this help, then exit"}, true)
  options.name = name
  return options
end


--- Produce usage info for the given options
-- @param header header string
-- @param optDesc option descriptors
-- @param pageWidth width to format to [78]
-- @return formatted string
local function usageInfo (header, optDesc, pageWidth)
  pageWidth = pageWidth or 78
  -- Format the usage info for a single option
  -- @param opt the option table
  -- @return options
  -- @return description
  local function fmtOpt (opt)
    local function fmtName (o)
      return (#o > 1 and "--" or "-") .. o
    end
    local function fmtArg ()
      if opt.type == nil then
        return ""
      elseif opt.type == "Req" then
        return "=" .. opt.var
      else
        return "[=" .. opt.var .. "]"
      end
    end
    local textName = list.reverse (list.map (fmtName, opt.name))
    textName[#textName] = textName[#textName] .. fmtArg ()
    local indent = ""
    if #opt.name == 1 and #opt.name[1] > 1 then
      indent = "    "
    end
    return {indent .. table.concat ({table.concat (textName, ", ")}, ", "),
      opt.desc}
  end
  local function sameLen (xs)
    local n = math.max (unpack (list.map (string.len, xs)))
    for i, v in pairs (xs) do
      xs[i] = string.sub (v .. string.rep (" ", n), 1, n)
    end
    return xs, n
  end
  local function paste (x, y)
    return "  " .. x .. "  " .. y
  end
  local function wrapper (w, i)
    return function (s)
             return string.wrap (s, w, i, 0)
           end
  end
  local optText = ""
  if #optDesc > 0 then
    local cols = list.transpose (list.map (fmtOpt, optDesc))
    local width
    cols[1], width = sameLen (cols[1])
    cols[2] = list.map (wrapper (pageWidth, width + 4), cols[2])
    optText = "\n\n" ..
      table.concat (list.mapWith (paste,
                                  list.transpose ({sameLen (cols[1]),
                                                    cols[2]})),
                    "\n")
  end
  return header .. optText
end

--- Emit a usage message.
-- @param prog table of named parameters
local function usage (prog)
  local usage = "[OPTION]... [FILE]..."
  local purpose, description, notes = "", "", ""
  if prog.usage then
    usage = prog.usage
  end
  usage = "Usage: " .. prog.name .. " " .. usage
  if prog.purpose then
      purpose = "\n\n" .. prog.purpose
  end
  if prog.description then
    for para in list.elems (string.split (prog.description, "\n")) do
      description = description .. "\n\n" .. string.wrap (para)
    end
  end
  if prog.notes then
    notes = "\n\n"
    if not string.find (prog.notes, "\n") then
      notes = notes .. string.wrap (prog.notes)
    else
      notes = notes .. prog.notes
    end
  end
  local header = usage .. purpose .. description
  io.writelines (usageInfo (header, prog.options) .. notes)
end


local function version (prog)
  local version = prog.version or prog.name or "unknown version!"
  if prog.copyright then
    version = version .. "\n\n" .. prog.copyright
  end
  io.writelines (version)
end



--- Simple getOpt wrapper.
-- If the caller didn't supply their own already,
-- adds <code>--version</code>/<code>-V</code> and
-- <code>--help</code>/<code>-h</code> options automatically;
-- stops program if there was an error, or if <code>--help</code> or
-- <code>--version</code> was used.
-- @param prog table of named parameters
-- @param ... extra arguments for getOpt
local function processArgs (prog, ...)
  local totArgs = #_G.arg
  local errors
  prog.options = makeOptions (prog.options)
  _G.arg, M.opt, errors = getOpt (_G.arg, prog.options, ...)
  local opt = M.opt
  if (opt.version or opt.help) and prog.banner then
    io.writelines (prog.banner)
  end
  if #errors > 0 then
    local name = prog.name
    prog.name = nil
    if #errors > 0 then
      warn (name .. ": " .. table.concat (errors, "\n"))
      warn (name .. ": Try '" .. (arg[0] or name) .. " --help' for more help")
    end
    if #errors > 0 then
      error ()
    end
  elseif opt.version then
    version (prog)
  elseif opt.help then
    usage (prog)
  end
  if opt.version or opt.help then
    os.exit ()
  end
end


-- Public interface
return table.merge (M, {
  getOpt      = getOpt,
  processArgs = processArgs,
  usage       = usage,
  usageInfo   = usageInfo,
})