X-Git-Url: https://git.archive.openwrt.org/?a=blobdiff_plain;ds=sidebyside;f=libs%2Fsys%2Fluasrc%2Fsys.lua;h=4bf294678825a5ab5aa0554b2af945fe1ffd5124;hb=a63363130730a543c1a7291f18068f027b83c9ed;hp=56beafe94446d398c6ec9d314715530b96f8463f;hpb=f9fa6d82da4f15473a49822d6d9dfda34144b85e;p=project%2Fluci.git diff --git a/libs/sys/luasrc/sys.lua b/libs/sys/luasrc/sys.lua index 56beafe94..4bf294678 100644 --- a/libs/sys/luasrc/sys.lua +++ b/libs/sys/luasrc/sys.lua @@ -24,15 +24,41 @@ limitations under the License. ]]-- + +local io = require "io" +local os = require "os" +local posix = require "posix" +local table = require "table" + +local luci = {} +luci.util = require "luci.util" +luci.fs = require "luci.fs" +luci.ip = require "luci.ip" + +local tonumber, ipairs, pairs = tonumber, ipairs, pairs + + --- LuCI Linux and POSIX system utilities. -module("luci.sys", package.seeall) -require("posix") -require("luci.bits") -require("luci.util") -require("luci.fs") -require("luci.ip") +module "luci.sys" + +--- Execute a given shell command and return the error code +-- @class function +-- @name call +-- @param ... Command to call +-- @return Error code of the command +function call(...) + return os.execute(...) / 256 +end + +--- Execute a given shell command and capture its standard output +-- @class function +-- @name exec +-- @param command Command to call +-- @return String containg the return the output of the command +exec = luci.util.exec --- Invoke the luci-flash executable to write an image to the flash memory. +-- @param image Local path or URL to image file -- @param kpattern Pattern of files to keep over flash process -- @return Return value of os.execute() function flash(image, kpattern) @@ -45,6 +71,53 @@ function flash(image, kpattern) return os.execute(cmd) end +--- Retrieve information about currently mounted file systems. +-- @return Table containing mount information +function mounts() + local data = {} + local k = {"fs", "blocks", "used", "available", "percent", "mountpoint"} + local ps = luci.util.execi("df") + + if not ps then + return + else + ps() + end + + for line in ps do + local row = {} + + local j = 1 + for value in line:gmatch("[^%s]+") do + row[k[j]] = value + j = j + 1 + end + + if row[k[1]] then + + -- this is a rather ugly workaround to cope with wrapped lines in + -- the df output: + -- + -- /dev/scsi/host0/bus0/target0/lun0/part3 + -- 114382024 93566472 15005244 86% /mnt/usb + -- + + if not row[k[2]] then + j = 2 + line = ps() + for value in line:gmatch("[^%s]+") do + row[k[j]] = value + j = j + 1 + end + end + + table.insert(data, row) + end + end + + return data +end + --- Retrieve environment variables. If no variable is given then a table -- containing the whole environment is returned otherwise this function returns -- the corresponding string value for the given name or nil if no such variable @@ -65,10 +138,16 @@ end --- Returns the contents of a documented referred by an URL. -- @param url The URL to retrieve -- @param stream Return a stream instead of a buffer +-- @param target Directly write to target file name -- @return String containing the contents of given the URL -function httpget(url, stream) - local source = stream and io.open or luci.util.exec - return source("wget -qO- '"..url:gsub("'", "").."'") +function httpget(url, stream, target) + if not target then + local source = stream and io.open or luci.util.exec + return source("wget -qO- '"..url:gsub("'", "").."'") + else + return os.execute("wget -qO '%s' '%s'" % + {target:gsub("'", ""), url:gsub("'", "")}) + end end --- Returns the system load average values. @@ -95,9 +174,6 @@ end -- @return String containing the memory used for caching in kB -- @return String containing the memory used for buffering in kB -- @return String containing the free memory amount in kB --- @return Number containing free memory in percent --- @return Number containing buffer memory in percent --- @return Number containing cache memory in percent function sysinfo() local c1 = "cat /proc/cpuinfo|grep system\\ typ|cut -d: -f2 2>/dev/null" local c2 = "uname -m 2>/dev/null" @@ -110,13 +186,10 @@ function sysinfo() local system = luci.util.trim(luci.util.exec(c1)) local model = "" - local memtotal = luci.util.trim(luci.util.exec(c5)) - local memcached = luci.util.trim(luci.util.exec(c6)) - local memfree = luci.util.trim(luci.util.exec(c7)) - local membuffers = luci.util.trim(luci.util.exec(c8)) - local perc_memfree = math.floor((memfree/memtotal)*100) - local perc_membuffers = math.floor((membuffers/memtotal)*100) - local perc_memcached = math.floor((memcached/memtotal)*100) + local memtotal = tonumber(luci.util.trim(luci.util.exec(c5))) + local memcached = tonumber(luci.util.trim(luci.util.exec(c6))) + local memfree = tonumber(luci.util.trim(luci.util.exec(c7))) + local membuffers = tonumber(luci.util.trim(luci.util.exec(c8))) if system == "" then system = luci.util.trim(luci.util.exec(c2)) @@ -125,7 +198,7 @@ function sysinfo() model = luci.util.trim(luci.util.exec(c4)) end - return system, model, memtotal, memcached, membuffers, memfree, perc_memfree, perc_membuffers, perc_memcached + return system, model, memtotal, memcached, membuffers, memfree end --- Retrieves the output of the "logread" command. @@ -166,6 +239,8 @@ end group = {} --- Returns information about a POSIX user group. +-- @class function +-- @name getgroup -- @param group Group ID or name of a system user group -- @return Table with information about the requested group group.getgroup = posix.getgroup @@ -212,6 +287,21 @@ function net.devices() return devices end + +--- Return information about available network interfaces. +-- @return Table containing all current interface names and their information +function net.deviceinfo() + local devices = {} + for line in io.lines("/proc/net/dev") do + local name, data = line:match("^ *(.-): *(.*)$") + if name and data then + devices[name] = luci.util.split(data, " +", nil, true) + end + end + return devices +end + + -- Determine the MAC address belonging to the given IP address. -- @param ip IPv4 address -- @return String containing the MAC address or nil if it cannot be found @@ -251,9 +341,51 @@ end process = {} --- Get the current process id. +-- @class function +-- @name process.info -- @return Number containing the current pid process.info = posix.getpid +--- Retrieve information about currently running processes. +-- @return Table containing process information +function process.list() + local data = {} + local k + local ps = luci.util.execi("top -bn1") + + if not ps then + return + end + + while true do + local line = ps() + if not line then + return + end + + k = luci.util.split(luci.util.trim(line), "%s+", nil, true) + if k[1] == "PID" then + break + end + end + + for line in ps do + local row = {} + + line = luci.util.trim(line) + for i, value in ipairs(luci.util.split(line, "%s+", #k-1, true)) do + row[k[i]] = value + end + + local pid = tonumber(row[k[1]]) + if pid then + data[pid] = row + end + end + + return data +end + --- Set the gid of a process identified by given pid. -- @param pid Number containing the process id -- @param gid Number containing the Unix group id @@ -274,6 +406,15 @@ function process.setuser(pid, uid) return posix.setpid("u", pid, uid) end +--- Send a signal to a process identified by given pid. +-- @class function +-- @name process.signal +-- @param pid Number containing the process id +-- @param sig Signal to send (default: 15 [SIGTERM]) +-- @return Boolean indicating successful operation +-- @return Number containing the error code if failed +process.signal = posix.kill + --- LuCI system utilities / user related functions. -- @class module @@ -296,11 +437,23 @@ function user.checkpasswd(username, password) local account = user.getuser(username) if account then - if account.passwd == "!" then + local pwd = account.passwd + if pwd == "!" then return true - else - return (account.passwd == posix.crypt(password, account.passwd)) + elseif pwd == "x" then + pwd = nil + for l in io.lines("/etc/shadow") do + pwd = l:match("^%s:([^:]+)" % username) + if pwd then + break + end + end + if not pwd then + return nil, "No shadow password for " .. username + end end + + return (pwd == posix.crypt(password, pwd)) end end @@ -347,8 +500,9 @@ end --- Get iwlist scan output from all wireless devices. -- @return Table of tables contaiing all scan results -function wifi.iwscan() - local cnt = luci.util.exec("iwlist scan 2>/dev/null") +function wifi.iwscan(iface) + local siface = iface or "" + local cnt = luci.util.exec("iwlist "..siface.." scan 2>/dev/null") local iws = {} for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do @@ -366,7 +520,7 @@ function wifi.iwscan() end end - return iws + return iface and (iws[iface] or {}) or iws end