diff options
Diffstat (limited to 'libs/lucid/luasrc/lucid.lua')
-rw-r--r-- | libs/lucid/luasrc/lucid.lua | 348 |
1 files changed, 0 insertions, 348 deletions
diff --git a/libs/lucid/luasrc/lucid.lua b/libs/lucid/luasrc/lucid.lua deleted file mode 100644 index 38b34fde96..0000000000 --- a/libs/lucid/luasrc/lucid.lua +++ /dev/null @@ -1,348 +0,0 @@ ---[[ -LuCI - Lua Development Framework - -Copyright 2009 Steven Barth <steven@midlink.org> - -Licensed under the Apache License, Version 2.0 (the "License"); -you may not use this file except in compliance with the License. -You may obtain a copy of the License at - -http://www.apache.org/licenses/LICENSE-2.0 - -$Id$ -]] - -local nixio = require "nixio" -local table = require "table" -local uci = require "luci.model.uci" -local os = require "os" -local io = require "io" - -local pairs, require, pcall, assert, type = pairs, require, pcall, assert, type -local ipairs, tonumber, collectgarbage = ipairs, tonumber, collectgarbage - - -module "luci.lucid" - -local slaves = {} -local pollt = {} -local tickt = {} -local tpids = {} -local tcount = 0 -local ifaddrs = nixio.getifaddrs() - -cursor = uci.cursor() -state = uci.cursor_state() -UCINAME = "lucid" - -local cursor = cursor -local state = state -local UCINAME = UCINAME -local SSTATE = "/tmp/.lucid_store" - - ---- Starts a new LuCId superprocess. -function start() - state:revert(UCINAME, "main") - - prepare() - - local detach = cursor:get(UCINAME, "main", "daemonize") - if detach == "1" then - local stat, code, msg = daemonize() - if not stat then - nixio.syslog("crit", "Unable to detach process: " .. msg .. "\n") - ox.exit(2) - end - end - - state:set(UCINAME, "main", "pid", nixio.getpid()) - state:save(UCINAME) - - run() -end - ---- Returns the PID of the currently active LuCId process. -function running() - local pid = tonumber(state:get(UCINAME, "main", "pid")) - return pid and nixio.kill(pid, 0) and pid -end - ---- Stops any running LuCId superprocess. -function stop() - local pid = tonumber(state:get(UCINAME, "main", "pid")) - if pid then - return nixio.kill(pid, nixio.const.SIGTERM) - end - return false -end - ---- Prepares the slaves, daemons and publishers, allocate resources. -function prepare() - local debug = tonumber((cursor:get(UCINAME, "main", "debug"))) - - nixio.openlog("lucid", "pid", "perror") - if debug ~= 1 then - nixio.setlogmask("warning") - end - - cursor:foreach(UCINAME, "daemon", function(config) - if config.enabled ~= "1" then - return - end - - local key = config[".name"] - if not config.slave then - nixio.syslog("crit", "Daemon "..key.." is missing a slave\n") - os.exit(1) - else - nixio.syslog("info", "Initializing daemon " .. key) - end - - state:revert(UCINAME, key) - - local daemon, code, err = prepare_daemon(config) - if daemon then - state:set(UCINAME, key, "status", "started") - nixio.syslog("info", "Prepared daemon " .. key) - else - state:set(UCINAME, key, "status", "error") - state:set(UCINAME, key, "error", err) - nixio.syslog("err", "Failed to initialize daemon "..key..": ".. - err .. "\n") - end - end) -end - ---- Run the superprocess if prepared before. --- This main function of LuCId will wait for events on given file descriptors. -function run() - local pollint = tonumber((cursor:get(UCINAME, "main", "pollinterval"))) - local threadlimit = tonumber((cursor:get(UCINAME, "main", "threadlimit"))) - - while true do - local stat, code = nixio.poll(pollt, pollint) - - if stat and stat > 0 then - local ok = false - for _, polle in ipairs(pollt) do - if polle.revents ~= 0 and polle.handler then - ok = ok or polle.handler(polle) - end - end - if not ok then - -- Avoid high CPU usage if thread limit is reached - nixio.nanosleep(0, 100000000) - end - elseif stat == 0 then - ifaddrs = nixio.getifaddrs() - end - - for _, cb in ipairs(tickt) do - cb() - end - - local pid, stat, code = nixio.wait(-1, "nohang") - while pid and pid > 0 do - nixio.syslog("info", "Buried thread: " .. pid) - if tpids[pid] then - tcount = tcount - 1 - if tpids[pid] ~= true then - tpids[pid](pid, stat, code) - end - tpids[pid] = nil - end - pid, stat, code = nixio.wait(-1, "nohang") - end - end -end - ---- Add a file descriptor for the main loop and associate handler functions. --- @param polle Table containing: {fd = FILE DESCRIPTOR, events = POLL EVENTS, --- handler = EVENT HANDLER CALLBACK} --- @see unregister_pollfd --- @return boolean status -function register_pollfd(polle) - pollt[#pollt+1] = polle - return true -end - ---- Unregister a file desciptor and associate handler from the main loop. --- @param polle Poll descriptor --- @see register_pollfd --- @return boolean status -function unregister_pollfd(polle) - for k, v in ipairs(pollt) do - if v == polle then - table.remove(pollt, k) - return true - end - end - return false -end - ---- Close all registered file descriptors from main loop. --- This is useful for forked child processes. -function close_pollfds() - for k, v in ipairs(pollt) do - if v.fd and v.fd.close then - v.fd:close() - end - end -end - ---- Register a tick function that will be called at each cycle of the main loop. --- @param cb Callback --- @see unregister_tick --- @return boolean status -function register_tick(cb) - tickt[#tickt+1] = cb - return true -end - ---- Unregister a tick function from the main loop. --- @param cb Callback --- @see register_tick --- @return boolean status -function unregister_tick(cb) - for k, v in ipairs(tickt) do - if v == cb then - table.remove(tickt, k) - return true - end - end - return false -end - ---- Tests whether a given number of processes can be created. --- @oaram num Processes to be created --- @return boolean status -function try_process(num) - local threadlimit = tonumber((cursor:get(UCINAME, "main", "threadlimit"))) - return not threadlimit or (threadlimit - tcount) >= (num or 1) -end - ---- Create a new child process from a Lua function and assign a destructor. --- @param threadcb main function of the new process --- @param waitcb destructor callback --- @return process identifier or nil, error code, error message -function create_process(threadcb, waitcb) - local threadlimit = tonumber(cursor:get(UCINAME, "main", "threadlimit")) - if threadlimit and tcount >= threadlimit then - nixio.syslog("warning", "Cannot create thread: process limit reached") - return nil - else - collectgarbage("collect") - end - local pid, code, err = nixio.fork() - if pid and pid ~= 0 then - nixio.syslog("info", "Created thread: " .. pid) - tpids[pid] = waitcb or true - tcount = tcount + 1 - elseif pid == 0 then - local code = threadcb() - os.exit(code) - else - nixio.syslog("err", "Unable to fork(): " .. err) - end - return pid, code, err -end - ---- Prepare a daemon from a given configuration table. --- @param config Configuration data. --- @return boolean status or nil, error code, error message -function prepare_daemon(config) - nixio.syslog("info", "Preparing daemon " .. config[".name"]) - local modname = cursor:get(UCINAME, config.slave) - if not modname then - return nil, -1, "invalid slave" - end - - local stat, module = pcall(require, _NAME .. "." .. modname) - if not stat or not module.prepare_daemon then - return nil, -2, "slave type not supported" - end - - config.slave = prepare_slave(config.slave) - - return module.prepare_daemon(config, _M) -end - ---- Prepare a slave. --- @param name slave name --- @return table containing slave module and configuration or nil, error message -function prepare_slave(name) - local slave = slaves[name] - if not slave then - local config = cursor:get_all(UCINAME, name) - - local stat, module = pcall(require, config and config.entrypoint) - if stat then - slave = {module = module, config = config} - end - end - - if slave then - return slave - else - return nil, module - end -end - ---- Return a list of available network interfaces on the host. --- @return table returned by nixio.getifaddrs() -function get_interfaces() - return ifaddrs -end - ---- Revoke process privileges. --- @param user new user name or uid --- @param group new group name or gid --- @return boolean status or nil, error code, error message -function revoke_privileges(user, group) - if nixio.getuid() == 0 then - return nixio.setgid(group) and nixio.setuid(user) - end -end - ---- Return a secure UCI cursor. --- @return UCI cursor -function securestate() - local stat = nixio.fs.stat(SSTATE) or {} - local uid = nixio.getuid() - if stat.type ~= "dir" or (stat.modedec % 100) ~= 0 or stat.uid ~= uid then - nixio.fs.remover(SSTATE) - if not nixio.fs.mkdir(SSTATE, 700) then - local errno = nixio.errno() - nixio.syslog("err", "Integrity check on secure state failed!") - return nil, errno, nixio.perror(errno) - end - end - - return uci.cursor(nil, SSTATE) -end - ---- Daemonize the process. --- @return boolean status or nil, error code, error message -function daemonize() - if nixio.getppid() == 1 then - return - end - - local pid, code, msg = nixio.fork() - if not pid then - return nil, code, msg - elseif pid > 0 then - os.exit(0) - end - - nixio.setsid() - nixio.chdir("/") - - local devnull = nixio.open("/dev/null", nixio.open_flags("rdwr")) - nixio.dup(devnull, nixio.stdin) - nixio.dup(devnull, nixio.stdout) - nixio.dup(devnull, nixio.stderr) - - return true -end |