#! /usr/bin/env lua local p = require("posix") local port = 54321 local short = "hp:" local long = { {"help", "none", 'h'}, {"port", "required", 'p'}, } local rules = {} for opt, optarg, optind, longind in p.getopt(arg, short, long) do if opt == '?' then print("Unrecognized option") os.exit(1) elseif opt == 'h' then print("Usage: ruld [-h|-p PORT]") os.exit(0) elseif opt == 'p' then port = optarg end end function eval(exp, env) local f local value = "return " .. exp if env then f = load(value, nil, nil, env) else f = load(value) end return f and f() end function test(env) local rsp = "" for index = #rules, 1, -1 do local entry = rules[index] if eval(entry[1], env) then local delay, duration if entry[3] then delay = entry[3].delay duration = entry[3].duration if delay and delay > 0 then entry[3].delay = delay - 1 end if ((not delay) or delay == 0) and duration and duration > 0 then entry[3].duration = duration - 1 end end if (((not delay) or delay == 0) and ((not duration) or duration > 0)) then if #rsp > 0 then rsp = rsp .. " " .. entry[2] else rsp = entry[2] end end if duration and duration <= 1 then table.remove(rules, index) end end end return rsp end local fd = p.socket(p.AF_INET, p.SOCK_STREAM, 0) p.setsockopt(fd, p.SOL_SOCKET, p.SO_REUSEADDR, 1) p.bind(fd, {family=p.AF_INET, addr="127.0.0.1", port=port}) p.listen(fd, p.SOMAXCONN) local running = true while running do ret_fd = p.accept(fd) if ret_fd then local msg = p.recv(ret_fd, p.BUFSIZ) if msg then local cmd, data = nil sep = msg:find(" ") if sep then cmd = msg:sub(1, sep - 1) data = msg:sub(sep + 1) else cmd = msg end if cmd == "test" then local env = eval(data) if env then rsp = test(env) p.send(ret_fd, rsp) end elseif cmd == "add" then local value = eval(data) if value then table.insert(rules, value) end elseif cmd == "remove" then if data == "tail" then table.remove(rules, #rules) elseif data == "head" then table.remove(rules, 1) else for index = #rules, 1, -1 do if rules[index][1]:find(data) then table.remove(rules, index) end end end elseif cmd == "quit" then running = false elseif cmd == "list" then local rsp = "" for index, entry in pairs(rules) do rsp = rsp .. string.format("%s => %s", entry[1], entry[2]) if entry[3] then if entry[3].delay then rsp = rsp .. string.format(" @%i", entry[3].delay) end if entry[3].duration then rsp = rsp .. string.format(" +%i", entry[3].duration) end end if index < #rules then rsp = rsp .. "\n" end end p.send(ret_fd, rsp) end end p.close(ret_fd) end end p.close(fd)