diff options
Diffstat (limited to 'polygLua.lua')
| -rwxr-xr-x | polygLua.lua | 518 |
1 files changed, 518 insertions, 0 deletions
diff --git a/polygLua.lua b/polygLua.lua new file mode 100755 index 0000000..008011e --- /dev/null +++ b/polygLua.lua | |||
| @@ -0,0 +1,518 @@ | |||
| 1 | #!/usr/bin/env luajit | ||
| 2 | |||
| 3 | --- polygLua, gluing things onto Lua, making it a polyglot language. | ||
| 4 | -- I can write Lua in any language. B-) | ||
| 5 | -- Also includes some other little useful bits I commonly use, most of which is used in support of its main function. | ||
| 6 | -- @module polygLua | ||
| 7 | -- @alias _ | ||
| 8 | |||
| 9 | local _ = {} | ||
| 10 | --- version number and string | ||
| 11 | _.version = '0.0 crap' | ||
| 12 | |||
| 13 | |||
| 14 | _.verbosity = 4 | ||
| 15 | local log = function( v, -- verbosity | ||
| 16 | t, -- level | ||
| 17 | s -- message | ||
| 18 | ) | ||
| 19 | if nil == s then s = 'nil' end | ||
| 20 | if v <= _.verbosity then | ||
| 21 | if 3 <= _.verbosity then t = os.date('!%F %T') .. ' ' .. t end | ||
| 22 | if 4 == v then t = '' else t = t .. ': ' end | ||
| 23 | if 3 <= v then | ||
| 24 | io.stdout:write(t .. s .. '\n') | ||
| 25 | io.stdout:flush() | ||
| 26 | else | ||
| 27 | io.stderr:write(t .. s .. '\n') | ||
| 28 | io.stderr:flush() | ||
| 29 | end | ||
| 30 | end | ||
| 31 | end | ||
| 32 | -- This sets the global values, here and in the caller. | ||
| 33 | --- log DEBUG level string | ||
| 34 | D = function(s) log(5, 'DEBUG ', s) end | ||
| 35 | --- log PRINT level string | ||
| 36 | P = function(s) log(4, 'PRINT ', s) end | ||
| 37 | --- log INFO level string | ||
| 38 | I = function(s) log(3, 'INFO ', s) end | ||
| 39 | --- log TIMEOUT level string | ||
| 40 | T = function(s) log(2, 'TIMEOUT ', s) end | ||
| 41 | --- log WARNING level string | ||
| 42 | W = function(s) log(1, 'WARNING ', s) end | ||
| 43 | --- log ERROR level string | ||
| 44 | E = function(s) log(0, 'ERROR ', s) end | ||
| 45 | --- log CRITICAL level string | ||
| 46 | C = function(s) log(-1, 'CRITICAL ', s) end | ||
| 47 | |||
| 48 | --- common options | ||
| 49 | local optionsCommon = | ||
| 50 | { | ||
| 51 | help = {help = 'Print the help text.', | ||
| 52 | func = function(self, options, a, args, i, name) | ||
| 53 | for i,v in ipairs{'/usr/share/doc/' .. name, '/usr/local/share/doc/' .. name, './'} do | ||
| 54 | local p = v .. 'README.md' | ||
| 55 | local h = io.open(p, 'r') | ||
| 56 | if nil ~= h then | ||
| 57 | D('Found README file '.. p) | ||
| 58 | Help = h:read('*a') -- NOTE Lua 5.3 doesn't use the *, but ignores it if it's there, earlier versions need it. | ||
| 59 | h:close() | ||
| 60 | end | ||
| 61 | end | ||
| 62 | |||
| 63 | P(Help) | ||
| 64 | _.usage(args, options, true) | ||
| 65 | os.exit(0) | ||
| 66 | end | ||
| 67 | }, | ||
| 68 | version = {help = 'Print the version details.', | ||
| 69 | func = function(self, options, a, args, i) | ||
| 70 | P('This is version ' ..Version .. ' of ' .. args[0]) | ||
| 71 | os.exit(0) | ||
| 72 | end | ||
| 73 | }, | ||
| 74 | ['-q'] = {help = 'Decrease verbosity level.', | ||
| 75 | func = function(self, options, a, args, i) | ||
| 76 | if _.verbosity > -1 then _.verbosity = _.verbosity - 1 end | ||
| 77 | I('New verbosity level is ' .. _.verbosity) | ||
| 78 | end | ||
| 79 | }, | ||
| 80 | ['-v'] = {help = 'Increase verbosity level.', | ||
| 81 | func = function(self, options, a, args, i) | ||
| 82 | if _.verbosity < 4 then _.verbosity = _.verbosity + 1 end | ||
| 83 | I('New verbosity level is ' .. _.verbosity) | ||
| 84 | end | ||
| 85 | }, | ||
| 86 | ['--maximum-verbosity'] = {help = 'Increase verbosity level to maximum.', | ||
| 87 | func = function(self, options, a, args, i) | ||
| 88 | _.verbosity = 4 | ||
| 89 | I('New verbosity level is ' .. _.verbosity) | ||
| 90 | end | ||
| 91 | }, | ||
| 92 | } | ||
| 93 | |||
| 94 | --- print usage info | ||
| 95 | _.usage = function( args, -- command line arguments that where passed to the script, including the name | ||
| 96 | options, -- describes all the command line options | ||
| 97 | all -- print the lot | ||
| 98 | ) | ||
| 99 | local h = '' | ||
| 100 | for k, v in pairs(options) do | ||
| 101 | if 'table' == type(v) then h = h .. k .. ' | ' end | ||
| 102 | end | ||
| 103 | for k, v in pairs(optionsCommon) do | ||
| 104 | if 'table' == type(v) then h = h .. k .. ' | ' end | ||
| 105 | end | ||
| 106 | P('Usage: ' .. args[0] .. ' {' .. h:sub(1, -2) .. '}') | ||
| 107 | if true == all then | ||
| 108 | for k, v in pairs(options) do | ||
| 109 | if 'table' == type(v) then | ||
| 110 | if nil ~= v.help then P(k .. '\t\t' .. v.help) end | ||
| 111 | end | ||
| 112 | end | ||
| 113 | for k, v in pairs(optionsCommon) do | ||
| 114 | if 'table' == type(v) then | ||
| 115 | if nil ~= v.help then P(k .. '\t\t' .. v.help) end | ||
| 116 | end | ||
| 117 | end | ||
| 118 | end | ||
| 119 | end | ||
| 120 | |||
| 121 | --- parse command line options | ||
| 122 | _.parse = function( args, -- command line arguments that where passed to the script | ||
| 123 | options, -- describes all the command line options | ||
| 124 | name -- name to use for finding config file | ||
| 125 | ) | ||
| 126 | local o = nil | ||
| 127 | |||
| 128 | local doIt = function(name, val, a, args, i) | ||
| 129 | local o = options[name] | ||
| 130 | if nil == o then o = optionsCommon[name] end | ||
| 131 | if nil ~= o then | ||
| 132 | if nil ~= val then o.value = val; D(name .. ' = ' .. tostring(val)) end | ||
| 133 | if nil ~= o.func then o:func(options, a, args, i, name) end | ||
| 134 | end | ||
| 135 | return o | ||
| 136 | end | ||
| 137 | |||
| 138 | if nil ~= name then | ||
| 139 | for i,v in ipairs{'/etc/', '~/.', './.'} do | ||
| 140 | local p = v .. name .. '.conf.lua' | ||
| 141 | local h = io.open(p, 'r') | ||
| 142 | if nil ~= h then | ||
| 143 | D('Found configuration file '.. p) | ||
| 144 | h:close() | ||
| 145 | local ar = dofile(p) | ||
| 146 | for k, w in pairs(ar) do | ||
| 147 | if nil == doIt(k, w, k .. '=' .. tostring(w), args, i) then W('config variable not found ' .. k .. ' = ' .. tostring(w)) end | ||
| 148 | end | ||
| 149 | end | ||
| 150 | end | ||
| 151 | end | ||
| 152 | |||
| 153 | if (0 == #args) and (nil ~= options['']) then table.insert(args, '') end | ||
| 154 | if 0 ~= #args then | ||
| 155 | for i,a in ipairs(args) do | ||
| 156 | D('Argument ' .. i .. ' = ' .. a) | ||
| 157 | local ds = 0 | ||
| 158 | if ('-' == a:sub(1, 1)) and ('-' ~= a:sub(2, 2)) then ds = 1 end | ||
| 159 | if '--' == a:sub(1, 2) then ds = 2; a = a:sub(3, -1) end | ||
| 160 | local s, e = a:find('=', 1, true) | ||
| 161 | local k , v | ||
| 162 | if not s then | ||
| 163 | e = 0 | ||
| 164 | v = nil | ||
| 165 | else | ||
| 166 | v = a:sub(e + 1, -1) | ||
| 167 | end | ||
| 168 | k = a:sub(1, e - 1) | ||
| 169 | if 1 == ds then | ||
| 170 | for j = 2, #k do | ||
| 171 | o = doIt('-' .. k:sub(j, j), v, a, args, i) | ||
| 172 | end | ||
| 173 | else | ||
| 174 | o = doIt(k, v, a, args, i) | ||
| 175 | end | ||
| 176 | end | ||
| 177 | end | ||
| 178 | |||
| 179 | if nil == o then | ||
| 180 | _.usage(args, options) | ||
| 181 | os.exit(0) | ||
| 182 | end | ||
| 183 | end | ||
| 184 | |||
| 185 | |||
| 186 | --- run a shell command, return the output in a table | ||
| 187 | _.readCmd = function(cmd) | ||
| 188 | local result = {} | ||
| 189 | --[[ | ||
| 190 | io.popen gives us a read file handle for 'r' and a write one for 'w' | ||
| 191 | os.execute gives us some sort of status code, plus other things in other Lua versions, but no in or out. | ||
| 192 | ]] | ||
| 193 | local output = io.popen(cmd, 'r') | ||
| 194 | if nil ~= output then | ||
| 195 | for l in output:lines() do | ||
| 196 | table.insert(result, l) | ||
| 197 | end | ||
| 198 | end | ||
| 199 | output:close() | ||
| 200 | return result | ||
| 201 | end | ||
| 202 | |||
| 203 | |||
| 204 | |||
| 205 | --- funky executable wrapper, might even call it a class | ||
| 206 | -- @alias exe | ||
| 207 | __ = function(c -- main command, or commands in a multiline string, or list of commands in a table, or a #! script | ||
| 208 | ) | ||
| 209 | local exe = {status = 0, lines = {}, logging = false, showing = false, cmd = '', command = c, isScript = false, script = ''} | ||
| 210 | local n = 0 | ||
| 211 | |||
| 212 | exe.cmd = '{ ' | ||
| 213 | if 'table' == type(c) then | ||
| 214 | for i, l in ipairs(c) do | ||
| 215 | n = n + 1 | ||
| 216 | exe.cmd = exe.cmd .. l .. ' ; ' | ||
| 217 | end | ||
| 218 | elseif 'string' == type(c) then | ||
| 219 | exe.isScript = (n == 0) and ('#!' == c:sub(1,2)) | ||
| 220 | for l in c:gmatch('\n*([^\n]+)\n*') do | ||
| 221 | if '' ~= l then | ||
| 222 | if exe.isScript then | ||
| 223 | if '' == exe.script then | ||
| 224 | exe.scriptFile = os.tmpname() | ||
| 225 | D('Creating temporary script file at ' .. exe.scriptFile) | ||
| 226 | exe.cmd = exe.cmd .. l:sub(3) .. ' ' .. exe.scriptFile .. ' ; ' | ||
| 227 | -- PHP wants this to be executable. | ||
| 228 | __('chmod u+x ' .. exe.scriptFile) | ||
| 229 | end | ||
| 230 | exe.script = exe.script .. l .. '\n' | ||
| 231 | else | ||
| 232 | n = n + 1 | ||
| 233 | exe.cmd = exe.cmd .. l .. ' ; ' | ||
| 234 | end | ||
| 235 | end | ||
| 236 | end | ||
| 237 | end | ||
| 238 | if exe.isScript then | ||
| 239 | local a, e = io.open(exe.scriptFile, 'w') | ||
| 240 | if nil == a then E('Could not open ' .. exe.scriptFile .. ' - ' .. e) else | ||
| 241 | a:write(exe.script) | ||
| 242 | a:close() | ||
| 243 | end | ||
| 244 | -- exe.cmd = exe.cmd .. 'rm ' .. exe.scriptFile .. ' ; ' | ||
| 245 | end | ||
| 246 | exe.cmd = exe.cmd .. ' } ' | ||
| 247 | if 1 == n then exe.cmd = c end | ||
| 248 | |||
| 249 | |||
| 250 | --- run this command under ionice and nice | ||
| 251 | function exe:Nice(c) | ||
| 252 | if nil == c then | ||
| 253 | self.cmd = 'ionice -c3 nice -n 19 ' .. self.cmd | ||
| 254 | else | ||
| 255 | self.cmd = self.cmd .. ' ionice -c3 nice -n 19 ' .. c .. ' ' | ||
| 256 | end | ||
| 257 | return self | ||
| 258 | end | ||
| 259 | |||
| 260 | --- run this command under timeout | ||
| 261 | function exe:timeout(c) | ||
| 262 | if nil == c then | ||
| 263 | -- timeout returns a status of - command status if --preserve-status; "128+9" (actually 137) if --kill-after ends up being done; 124 if it had to TERM; command status if all went well. | ||
| 264 | -- --kill-after means "send KILL after TERM fails". | ||
| 265 | self.cmd = 'timeout --kill-after=10.0 --foreground 42.0s ' .. self.cmd | ||
| 266 | else | ||
| 267 | self.cmd = 'timeout --kill-after=10.0 --foreground ' .. c .. ' ' .. self.cmd | ||
| 268 | end | ||
| 269 | return self | ||
| 270 | end | ||
| 271 | |||
| 272 | --- enable logging the command line | ||
| 273 | function exe:log() self.logging = true return self end | ||
| 274 | --- enable showing the command output | ||
| 275 | function exe:show() self.showing = true return self end | ||
| 276 | --- run this command after the last one runs | ||
| 277 | function exe:Then(c) if nil == c then c = '' else c = ' ' .. c end self.cmd = self.cmd .. '; ' .. c .. ' ' return self end | ||
| 278 | --- run this command after the last one runs, if it worked | ||
| 279 | function exe:And(c) if nil == c then c = '' else c = ' ' .. c end self.cmd = self.cmd .. ' && ' .. c .. ' ' return self end | ||
| 280 | --- run this command after the last one runs, if it failed | ||
| 281 | function exe:Or(c) if nil == c then c = '' else c = ' ' .. c end self.cmd = self.cmd .. ' || ' .. c .. ' ' return self end | ||
| 282 | --- discard stderr | ||
| 283 | function exe:noErr() self.cmd = self.cmd .. ' 2>/dev/null ' return self end | ||
| 284 | --- discard stdout | ||
| 285 | function exe:noOut() self.cmd = self.cmd .. ' 1>/dev/null ' return self end | ||
| 286 | --- if the command worked, touch the w file, which is being waited on elsewhere, maybe | ||
| 287 | function exe:wait(w) self.cmd = self.cmd .. ' && touch ' .. w .. ' ' return self end | ||
| 288 | |||
| 289 | --- actually run the command. | ||
| 290 | function exe:Do() | ||
| 291 | --[[ "The condition expression of a control structure can return any | ||
| 292 | value. Both false and nil are considered false. All values different | ||
| 293 | from nil and false are considered true (in particular, the number 0 | ||
| 294 | and the empty string are also true)." | ||
| 295 | says the docs, I beg to differ.]] | ||
| 296 | if true == self.logging then D(' executing - ' .. self.cmd) end | ||
| 297 | self.lines = _.readCmd(self.cmd .. '; echo "$?"', 'r') | ||
| 298 | -- The last line will be the command's returned status, fish that out and collect everything else in lines. | ||
| 299 | self.status = tonumber(self.lines[#self.lines]) | ||
| 300 | self.lines[#self.lines] = nil | ||
| 301 | if true == self.showing then for i, l in ipairs(self.lines) do I(l) end end | ||
| 302 | |||
| 303 | if (nil == self.status) then D('STATUS |' .. 'NIL' .. '| ' .. self.command) | ||
| 304 | elseif (137 == self.status) or (124 == self.status) then T('timeout killed ' .. self.status .. ' ' .. self.command) | ||
| 305 | elseif (0 ~= self.status) then D('STATUS |' .. self.status .. '| ' .. self.command) | ||
| 306 | end | ||
| 307 | |||
| 308 | if nil ~= exe.scriptFile then os.execute('rm ' .. exe.scriptFile) end | ||
| 309 | |||
| 310 | return self | ||
| 311 | end | ||
| 312 | |||
| 313 | -- TODO - currently after is a string that is run after the command. Could be a Lua function to call. | ||
| 314 | |||
| 315 | --- fork the command | ||
| 316 | function exe:fork(after, host) | ||
| 317 | if nil == after then after = '' end | ||
| 318 | if '' ~= after then after = ' ; ' .. after end | ||
| 319 | -- The host part is from apt-panopticon, likely needed there, but makes no sense here. | ||
| 320 | -- if nil ~= host then self.cmd = self.cmd .. '; r=$?; if [ $r -ge 124 ]; then echo "$r ' .. host .. ' failed forked command ' .. self.cmd:gsub(, '"', "'") .. '"; fi' end | ||
| 321 | self.cmd = '{ ' .. self.cmd .. after .. ' ; } & ' | ||
| 322 | if true == self.logging then D(' forking - ' .. self.cmd) end | ||
| 323 | os.execute(self.cmd) | ||
| 324 | return self | ||
| 325 | end | ||
| 326 | |||
| 327 | --- fork the command, unless it's already running | ||
| 328 | function exe:forkOnce() | ||
| 329 | if _.running(self.command) then | ||
| 330 | D('Already running ' .. self.command) | ||
| 331 | else | ||
| 332 | self:fork() | ||
| 333 | end | ||
| 334 | end | ||
| 335 | |||
| 336 | return exe | ||
| 337 | end | ||
| 338 | |||
| 339 | |||
| 340 | |||
| 341 | --- dereference an array | ||
| 342 | -- A simple table.subtable = subtable wont work, you end up with a reference so that changes to the later get applied to the former. | ||
| 343 | -- On the other hand, this isn't going deep, only the top layer if there is sub tables. | ||
| 344 | _.derefiTable = function(t) | ||
| 345 | local argh = {} | ||
| 346 | for l, y in ipairs(t) do if (l ~= y.name) then table.insert(argh, y) end end | ||
| 347 | return argh | ||
| 348 | end | ||
| 349 | --- dereference a table | ||
| 350 | _.derefTable = function(t) | ||
| 351 | local argh = {} | ||
| 352 | for l, y in pairs(t) do argh[l] = y end | ||
| 353 | return argh | ||
| 354 | end | ||
| 355 | |||
| 356 | --- Does this file exist? | ||
| 357 | _.exists = function(f) | ||
| 358 | local h = io.open(f, 'r') | ||
| 359 | if nil == h then return false else h:close(); return true end | ||
| 360 | end | ||
| 361 | --- Is this command runnable? | ||
| 362 | _.runnable = function(c) return ( 0 == __('which ' .. c):Do().status ) end | ||
| 363 | --- Is this command running? | ||
| 364 | _.running = function(c) return ( 1 ~= tonumber(__('pgrep -u $USER -cf ' .. c):Do().lines[1]) ) end | ||
| 365 | --- pkill all | ||
| 366 | _.killEmAll = function(all -- table of command names to pkill | ||
| 367 | ) | ||
| 368 | for i,l in ipairs(all) do | ||
| 369 | local c = 0 | ||
| 370 | while 0 ~= tonumber(__('pgrep -u $USER -xc ' .. l):Do().lines[1]) do | ||
| 371 | local s = 'TERM' | ||
| 372 | if c > 1 then s = 'KILL'; __('sleep ' .. c):Do() end | ||
| 373 | __('pkill -' .. s .. ' -u $USER -x ' .. l):log():Do() | ||
| 374 | c = c + 1 | ||
| 375 | end | ||
| 376 | end | ||
| 377 | end | ||
| 378 | |||
| 379 | --- execute whoami and return the result | ||
| 380 | _.who = __[[whoami]]:noErr():Do().lines[1] | ||
| 381 | --- execute pwd and return the result | ||
| 382 | _.dir = __[[pwd]]:noErr():Do().lines[1] | ||
| 383 | |||
| 384 | --- write a string to a file | ||
| 385 | _.string2file = function(s, f) | ||
| 386 | local a, e = io.open(f, 'w') | ||
| 387 | if nil == a then E('Could not open ' .. f .. ' - ' .. e) else | ||
| 388 | a:write(s) | ||
| 389 | a:close() | ||
| 390 | end | ||
| 391 | end | ||
| 392 | |||
| 393 | --- dump a table to a pretty string | ||
| 394 | _.table2string = function (table, -- table to dump | ||
| 395 | name, -- name of table | ||
| 396 | space -- Optional, used internally for sub tables. | ||
| 397 | ) | ||
| 398 | if nil == space then space = '' end | ||
| 399 | local r = space | ||
| 400 | if '' == space then r = r .. name .. ' =\n' else r = r .. '[' .. name .. '] =\n' end | ||
| 401 | r = r .. space .. '{\n' .. _.table2stringSub(table, space .. ' ') .. space .. '}' | ||
| 402 | if '' ~= space then r = r .. ',' end | ||
| 403 | return r .. '\n' | ||
| 404 | end | ||
| 405 | _.table2stringSub = function (table, space) | ||
| 406 | local r = '' | ||
| 407 | for k, v in pairs(table) do | ||
| 408 | if type(k) == 'string' then k = "'" .. k .. "'" end | ||
| 409 | if type(v) == 'table' then r = r .. _.table2string(v, k, space) | ||
| 410 | elseif type(v) == 'string' then | ||
| 411 | local bq, eq = "'", "'" | ||
| 412 | if nil ~= v:find(bq, 1, true) then | ||
| 413 | bq, eq = '[=[', ']=]' | ||
| 414 | end | ||
| 415 | if nil ~= v:find(bq, 1, true) then | ||
| 416 | bq, eq = '[==[', ']==]' | ||
| 417 | if nil ~= v:find(bq, 1, true) then | ||
| 418 | bq, eq = '[===[', ']===]' | ||
| 419 | mbq, meq = '%[%[', '%]%]' | ||
| 420 | while (nil ~= v:match(mbq)) or (nil ~= v:match(meq)) do | ||
| 421 | bq = '[' .. '=' .. bq:sub(2, -1) | ||
| 422 | eq = ']' .. '=' .. eq:sub(2, -1) | ||
| 423 | mbq = '%[' .. '=' .. bq:sub(3, -1) | ||
| 424 | meq = '%]' .. '=' .. eq:sub(3, -1) | ||
| 425 | end | ||
| 426 | end | ||
| 427 | end | ||
| 428 | r = r .. space .. '[' .. k .. '] = ' .. bq .. v .. eq .. ';\n' | ||
| 429 | elseif type(v) == 'function' then r = r .. space .. '[' .. k .. '] = function ();\n' | ||
| 430 | elseif type(v) == 'userdata' then r = r .. space .. 'userdata ' .. '[' .. k .. '];\n' | ||
| 431 | elseif type(v) == 'boolean' then | ||
| 432 | if (v) then r = r .. space .. '[' .. k .. '] = true;\n' | ||
| 433 | else r = r .. space .. '[' .. k .. '] = false;\n' | ||
| 434 | end | ||
| 435 | else r = r .. space .. '[' .. k .. '] = ' .. v .. ';\n' | ||
| 436 | end | ||
| 437 | end | ||
| 438 | return r | ||
| 439 | end | ||
| 440 | |||
| 441 | |||
| 442 | |||
| 443 | -- Deal with being called directly. | ||
| 444 | if (arg[0] == './polygLua.lua') or (arg[0] == 'polygLua.lua') then | ||
| 445 | local function goAway(txt) | ||
| 446 | local luas = __'ls -d1 /usr/share/lua/*':noErr():Do() | ||
| 447 | for i,l in ipairs(luas.lines) do | ||
| 448 | local lua = '/usr/local/share/lua/' .. l:sub(16) .. '/polygLua.lua' | ||
| 449 | if _.exists(lua) then | ||
| 450 | if 'root' == _.who then | ||
| 451 | I(txt .. ' ' .. lua) | ||
| 452 | __('rm ' .. lua):Do() | ||
| 453 | end | ||
| 454 | end | ||
| 455 | end | ||
| 456 | end | ||
| 457 | |||
| 458 | local options = | ||
| 459 | { | ||
| 460 | install = | ||
| 461 | { | ||
| 462 | help = 'Command to install polygLua.lua', | ||
| 463 | func = function(self, options, a, args, i) | ||
| 464 | if 'root' ~= _.who then | ||
| 465 | E'Need to be root user to install.' | ||
| 466 | else | ||
| 467 | I'INSTALLING polygLua.lua!!!' | ||
| 468 | |||
| 469 | local luas = __'ls -d1 /usr/share/lua/*':noErr():Do() | ||
| 470 | for i,l in ipairs(luas.lines) do | ||
| 471 | local lua = '/usr/local/share/lua/' .. l:sub(16) .. '/polygLua.lua' | ||
| 472 | if _.exists(lua) then | ||
| 473 | P(lua .. ' installed') | ||
| 474 | else | ||
| 475 | if 'root' == _.who then | ||
| 476 | P('Installing ' .. lua) | ||
| 477 | __('mkdir -p /usr/local/share/lua/' .. l:sub(16) .. ' ; ln -s ' .. _.dir .. '/polygLua.lua ' .. lua):Do() | ||
| 478 | else | ||
| 479 | P(lua .. ' NOT installed') | ||
| 480 | end | ||
| 481 | end | ||
| 482 | end | ||
| 483 | |||
| 484 | end | ||
| 485 | end | ||
| 486 | }, | ||
| 487 | uninstall = | ||
| 488 | { | ||
| 489 | help = 'Command to uninstall polygLua.lua', | ||
| 490 | func = function(self, options, a, args, i) | ||
| 491 | if 'root' ~= _.who then | ||
| 492 | E'Need to be root user to uninstall.' | ||
| 493 | else | ||
| 494 | P'UNINSTALLING polygLua.lua!!!' | ||
| 495 | goAway('Uninstalling') | ||
| 496 | end | ||
| 497 | end | ||
| 498 | }, | ||
| 499 | purge = | ||
| 500 | { | ||
| 501 | help = 'Command to purge polygLua.lua', | ||
| 502 | func = function(self, options, a, args, i) | ||
| 503 | if 'root' ~= _.who then | ||
| 504 | E'Need to be root user to purge.' | ||
| 505 | else | ||
| 506 | P'PURGING polygLua.lua!!!' | ||
| 507 | goAway('Purging') | ||
| 508 | end | ||
| 509 | end | ||
| 510 | }, | ||
| 511 | } | ||
| 512 | |||
| 513 | _.parse(arg, options) | ||
| 514 | end | ||
| 515 | |||
| 516 | |||
| 517 | |||
| 518 | return _ | ||
