~rootmos/lua-hack

5738bb34b4a302a6182bd538173396ab03f7e6f4 — Gustav Behm 1 year, 1 month ago d5e8863
Extend os.execute and io.popen
4 files changed, 84 insertions(+), 21 deletions(-)

M README.md
M base64.lua
A execute.lua
M hex.lua
M README.md => README.md +1 -0
@@ 8,6 8,7 @@ A set of Lua modules guaranteed to be public domain.
- [bits](bits.lua): utility module to determine the current Lua interpreter's integer bitwidth
- [char](char.lua): ASCII character utilities (e.g. `is_printable`)
- [deep](deep/init.lua): deep equality and copy operations
- [execute](execute.lua): extend os.execute and io.popen to safely quote arguments, set environment variables and change directory
- [hex](hex.lua): [hexadecimal binary encoding](https://en.wikipedia.org/wiki/Hexadecimal#Base16_(transfer_encoding))
- [lamport](lamport.lua): implementation of the [Lamport signature scheme](https://en.wikipedia.org/wiki/Lamport_signature)
- [random.prng](random/prng.lua): Pseudorandom number generators (e.g. [xorshift32](https://en.wikipedia.org/wiki/Xorshift))

M base64.lua => base64.lua +15 -14
@@ 31,49 31,50 @@ end
function M.encode(bs)
    local alph = M.alphabeth
    local i = 1
    local s = ""
    local t = {}
    while i <= #bs do
        local a, b, c = bs:byte(i, i+2)
        s = s .. alph[a>>2]
        table.insert(t, alph[a>>2])
        if b == nil then
            s = s .. alph[(a&3)<<4] .. alph.pad .. alph.pad
            table.insert(t, alph[(a&3)<<4] .. alph.pad .. alph.pad)
        else
            s = s .. alph[(a&3)<<4 | b>>4]
            table.insert(t, alph[(a&3)<<4 | b>>4])
            if c == nil then
                s = s .. alph[(b&15)<<2] .. alph.pad
                table.insert(t, alph[(b&15)<<2] .. alph.pad)
            else
                s = s .. alph[(b&15)<<2 | c>>6] .. alph[c&63]
                table.insert(t, alph[(b&15)<<2 | c>>6] .. alph[c&63])
            end
        end
        i = i + 3
    end
    return s
    return table.concat(t)
end

function M.decode(s, L)
    local i = 1
    local bs = ""
    local t = {}
    local pad = M.alphabeth.pad:byte()
    local inv = M.alphabeth_inv
    while i <= #s do
        local a, b, c, d = s:byte(i, i+3)
        if b == pad then
            bs = bs .. string.char(inv[a]<<2) .. "\0\0"
            table.insert(t, string.char(inv[a]<<2) .. "\0\0")
        else
            bs = bs .. string.char(inv[a]<<2 | inv[b]>>4)
            table.insert(t, string.char(inv[a]<<2 | inv[b]>>4))
            if c == pad then
                bs = bs .. string.char((inv[b]&15)<<4) .. "\0"
                table.insert(t, string.char((inv[b]&15)<<4) .. "\0")
            else
                bs = bs .. string.char((inv[b]&15)<<4 | inv[c]>>2)
                table.insert(t, string.char((inv[b]&15)<<4 | inv[c]>>2))
                if d == pad then
                    bs = bs .. string.char((inv[c]&3)<<6)
                    table.insert(t, string.char((inv[c]&3)<<6))
                else
                    bs = bs .. string.char((inv[c]&3)<<6 | inv[d])
                    table.insert(t, string.char((inv[c]&3)<<6 | inv[d]))
                end
            end
        end
        i = i + 4
    end
    local bs = table.concat(t)
    return bs:sub(1, L or #bs)
end


A execute.lua => execute.lua +61 -0
@@ 0,0 1,61 @@
local M = {}

local os, io = require("os"), require("io")
local execute, popen = os.execute, io.popen

local b64 = require("base64")
local H = require("hex")

local function mk_cmd(o)
    local t = {"env"}

    local function q(s)
        return H(s):gsub("(%w%w)", "\\x%1")
    end

    if o.cwd then
        table.insert(t, "-C")
        table.insert(t, string.format('"$(echo -ne "%s")"', q(o.cwd)))
    end

    for k, v in pairs(o.env or {}) do
        table.insert(t, string.format('"$(echo -ne "%s")=$(echo -ne "%s")"', q(k), q(v)))
    end

    for _, a in ipairs(o) do
        table.insert(t, string.format('"$(echo -ne "%s")"', q(a)))
    end

    return table.concat(t, " ")
end

function M.execute(o)
    if type(o) == "string" then
        return execute(o)
    elseif type(o) ~= "table" then
        error("argument of unexpected type: " .. type(o))
    end

    return execute(mk_cmd(o))
end

function M.popen(o, mode)
    if type(o) == "string" then
        return popen(o, mode)
    elseif type(o) ~= "table" then
        error("argument of unexpected type: " .. type(o))
    end

    return popen(mk_cmd(o), mode or o.mode)
end

function M.extend()
    os.execute = M.execute
    io.popen = M.popen
end

return setmetatable(M, {
    __call = function(N, o)
        return N.execute(o)
    end,
})

M hex.lua => hex.lua +7 -7
@@ 26,26 26,26 @@ end
function M.encode(bs)
    local alph = M.alphabeth
    local i = 1
    local s = ""
    local t = {}
    while i <= #bs do
        local b = bs:byte(i)
        s = s .. alph[b >> 4]
        s = s .. alph[b & 0x0f]
        table.insert(t, alph[b >> 4])
        table.insert(t, alph[b & 0x0f])
        i = i + 1
    end
    return s
    return table.concat(t)
end

function M.decode(s)
    local inv = M.alphabeth_inv
    local bs = ""
    local t = {}
    local i = 1
    while i <= #s do
        local u, l = s:byte(i, i+2)
        bs = bs .. string.char((inv[u]<<4) + inv[l])
        table.insert(t, string.char((inv[u]<<4) + inv[l]))
        i = i + 2
    end
    return bs
    return table.concat(t)
end

return M