* luci/libs/core: add inline documentation to luci.sys

This commit is contained in:
Jo-Philipp Wich 2008-07-22 03:43:33 +00:00
parent a037bfd207
commit c8e99f87b1

View file

@ -12,9 +12,9 @@ Copyright 2008 Steven Barth <steven@midlink.org>
Licensed under the Apache License, Version 2.0 (the "License"); Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License. you may not use this file except in compliance with the License.
You may obtain a copy of the License at You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0 http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS, distributed under the License is distributed on an "AS IS" BASIS,
@ -24,13 +24,15 @@ limitations under the License.
]]-- ]]--
--- LuCI system utilities.
module("luci.sys", package.seeall) module("luci.sys", package.seeall)
require("posix") require("posix")
require("luci.bits") require("luci.bits")
require("luci.util") require("luci.util")
require("luci.fs") require("luci.fs")
-- Returns whether a system is bigendian --- Test wheather the current system is operating in big endian mode.
-- @return Boolean value indicating wheather system is big endian
function bigendian() function bigendian()
local fp = io.open("/bin/sh") local fp = io.open("/bin/sh")
fp:seek("set", 5) fp:seek("set", 5)
@ -39,72 +41,105 @@ function bigendian()
return be return be
end end
-- Runs "command" and returns its output --- Execute given commandline and gather stdout.
-- @param command String containing command to execute
-- @return String containing the command's stdout
function exec(command) function exec(command)
local pp = io.popen(command) local pp = io.popen(command)
local data = pp:read("*a") local data = pp:read("*a")
pp:close() pp:close()
return data return data
end end
-- Runs "command" and returns its output as a array of lines --- Execute given commandline and gather stdout.
-- @param command String containing the command to execute
-- @return Table containing the command's stdout splitted up in lines
function execl(command) function execl(command)
local pp = io.popen(command) local pp = io.popen(command)
local line = "" local line = ""
local data = {} local data = {}
while true do while true do
line = pp:read() line = pp:read()
if (line == nil) then break end if (line == nil) then break end
table.insert(data, line) table.insert(data, line)
end end
pp:close() pp:close()
return data return data
end end
-- Uses "luci-flash" to flash a new image file to the system --- Invoke the luci-flash executable to write an image to the flash memory.
-- @param kpattern kpattern (ToDo: clearify this)
-- @return Return value of os.execute()
function flash(image, kpattern) function flash(image, kpattern)
local cmd = "luci-flash " local cmd = "luci-flash "
if kpattern then if kpattern then
cmd = cmd .. "-k '" .. kpattern:gsub("'", "") .. "' " cmd = cmd .. "-k '" .. kpattern:gsub("'", "") .. "' "
end end
cmd = cmd .. "'" .. image:gsub("'", "") .. "' >/dev/null 2>&1" cmd = cmd .. "'" .. image:gsub("'", "") .. "' >/dev/null 2>&1"
return os.execute(cmd) return os.execute(cmd)
end end
-- Returns the enivornment --- 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
-- exists.
-- @class function
-- @name getenv
-- @param var Name of the environment variable to retrieve (optional)
-- @return String containg the value of the specified variable
-- @return Table containing all variables if no variable name is given
getenv = posix.getenv getenv = posix.getenv
-- Returns the hostname --- Determine the current hostname.
-- @return String containing the system hostname
function hostname() function hostname()
return io.lines("/proc/sys/kernel/hostname")() return io.lines("/proc/sys/kernel/hostname")()
end end
-- Returns the contents of a documented referred by an URL --- Returns the contents of a documented referred by an URL.
-- @param url The URL to retrieve
-- @return String containing the contents of given the URL
function httpget(url) function httpget(url)
return exec("wget -qO- '"..url:gsub("'", "").."'") return exec("wget -qO- '"..url:gsub("'", "").."'")
end end
-- Returns the FFLuci-Basedir --- Returns the absolute path to LuCI base directory.
-- @return String containing the directory path
function libpath() function libpath()
return luci.fs.dirname(require("luci.debug").__file__) return luci.fs.dirname(require("luci.debug").__file__)
end end
-- Returns the load average --- Returns the system load average values.
-- @return String containing the average load value 1 minute ago
-- @return String containing the average load value 5 minutes ago
-- @return String containing the average load value 15 minutes ago
-- @return String containing the active and total number of processes
-- @return String containing the last used pid
function loadavg() function loadavg()
local loadavg = io.lines("/proc/loadavg")() local loadavg = io.lines("/proc/loadavg")()
return loadavg:match("^(.-) (.-) (.-) (.-) (.-)$") return loadavg:match("^(.-) (.-) (.-) (.-) (.-)$")
end end
-- Reboots the system --- Initiate a system reboot.
-- @return Return value of os.execute()
function reboot() function reboot()
return os.execute("reboot >/dev/null 2>&1") return os.execute("reboot >/dev/null 2>&1")
end end
-- Returns the system type, cpu name, and installed physical memory --- Returns the system type, cpu name and installed physical memory.
-- @return String containing the system or platform identifier
-- @return String containing hardware model information
-- @return String containing the total memory amount in kB
-- @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() function sysinfo()
local c1 = "cat /proc/cpuinfo|grep system\\ typ|cut -d: -f2 2>/dev/null" local c1 = "cat /proc/cpuinfo|grep system\\ typ|cut -d: -f2 2>/dev/null"
local c2 = "uname -m 2>/dev/null" local c2 = "uname -m 2>/dev/null"
@ -114,9 +149,9 @@ function sysinfo()
local c6 = "cat /proc/meminfo|grep ^Cached|awk {' print $2 '} 2>/dev/null" local c6 = "cat /proc/meminfo|grep ^Cached|awk {' print $2 '} 2>/dev/null"
local c7 = "cat /proc/meminfo|grep MemFree|awk {' print $2 '} 2>/dev/null" local c7 = "cat /proc/meminfo|grep MemFree|awk {' print $2 '} 2>/dev/null"
local c8 = "cat /proc/meminfo|grep Buffers|awk {' print $2 '} 2>/dev/null" local c8 = "cat /proc/meminfo|grep Buffers|awk {' print $2 '} 2>/dev/null"
local system = luci.util.trim(exec(c1)) local system = luci.util.trim(exec(c1))
local model = "" local model = ""
local memtotal = luci.util.trim(exec(c5)) local memtotal = luci.util.trim(exec(c5))
local memcached = luci.util.trim(exec(c6)) local memcached = luci.util.trim(exec(c6))
local memfree = luci.util.trim(exec(c7)) local memfree = luci.util.trim(exec(c7))
@ -135,65 +170,86 @@ function sysinfo()
return system, model, memtotal, memcached, membuffers, memfree, perc_memfree, perc_membuffers, perc_memcached return system, model, memtotal, memcached, membuffers, memfree, perc_memfree, perc_membuffers, perc_memcached
end end
-- Reads the syslog --- Retrieves the output of the "logread" command.
-- @return String containing the current log buffer
function syslog() function syslog()
return exec("logread") return exec("logread")
end end
--- Generates a random id with specified length.
-- Generates a random key of length BYTES -- @param bytes Number of bytes for the unique id
-- @return String containing hex encoded id
function uniqueid(bytes) function uniqueid(bytes)
local fp = io.open("/dev/urandom") local fp = io.open("/dev/urandom")
local chunk = { fp:read(bytes):byte(1, bytes) } local chunk = { fp:read(bytes):byte(1, bytes) }
fp:close() fp:close()
local hex = "" local hex = ""
local pattern = "%02X" local pattern = "%02X"
for i, byte in ipairs(chunk) do for i, byte in ipairs(chunk) do
hex = hex .. pattern:format(byte) hex = hex .. pattern:format(byte)
end end
return hex return hex
end end
--- Returns the current system uptime stats.
-- Returns uptime stats -- @return String containing total uptime in seconds
-- @return String containing idle time in seconds
function uptime() function uptime()
local loadavg = io.lines("/proc/uptime")() local loadavg = io.lines("/proc/uptime")()
return loadavg:match("^(.-) (.-)$") return loadavg:match("^(.-) (.-)$")
end end
--- Get group information
-- @return Group (ToDo: clearify)
group = {} group = {}
group.getgroup = posix.getgroup group.getgroup = posix.getgroup
--- LuCI system utilities / network related functions.
-- @class module
-- @name luci.sys.net
net = {} net = {}
-- Returns the ARP-Table
--- Returns the current arp-table entries as two-dimensional table.
-- @return Table of table containing the current arp entries.
-- The following fields are defined for arp entry objects:
-- { "IP address", "HW address", "HW type", "Flags", "Mask", "Device" }
function net.arptable() function net.arptable()
return _parse_delimited_table(io.lines("/proc/net/arp"), "%s%s+") return _parse_delimited_table(io.lines("/proc/net/arp"), "%s%s+")
end end
-- Returns whether an IP-Adress belongs to a certain net --- Test whether an IP-Adress belongs to a certain net.
-- @param ip IPv4 address to test
-- @param ipnet IPv4 network address of the net range to compare against
-- @param prefix Network prefix of the net range to compare against
-- @return Boolean indicating wheather the ip is within the range
function net.belongs(ip, ipnet, prefix) function net.belongs(ip, ipnet, prefix)
return (net.ip4bin(ip):sub(1, prefix) == net.ip4bin(ipnet):sub(1, prefix)) return (net.ip4bin(ip):sub(1, prefix) == net.ip4bin(ipnet):sub(1, prefix))
end end
-- Detect the default route --- Determine the current default route.
-- @return Table with the properties of the current default route.
-- The following fields are defined:
-- { "Mask", "RefCnt", "Iface", "Flags", "Window", "IRTT",
-- "MTU", "Gateway", "Destination", "Metric", "Use" }
function net.defaultroute() function net.defaultroute()
local routes = net.routes() local routes = net.routes()
local route = nil local route = nil
for i, r in pairs(luci.sys.net.routes()) do for i, r in pairs(luci.sys.net.routes()) do
if r.Destination == "00000000" and (not route or route.Metric > r.Metric) then if r.Destination == "00000000" and (not route or route.Metric > r.Metric) then
route = r route = r
end end
end end
return route return route
end end
-- Returns all available network interfaces --- Determine the names of available network interfaces.
-- @return Table containing all current interface names
function net.devices() function net.devices()
local devices = {} local devices = {}
for line in io.lines("/proc/net/dev") do for line in io.lines("/proc/net/dev") do
@ -202,45 +258,56 @@ function net.devices()
return devices return devices
end end
-- Returns the MAC-Address belonging to the given IP-Address -- 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
function net.ip4mac(ip) function net.ip4mac(ip)
local mac = nil local mac = nil
for i, l in ipairs(net.arptable()) do for i, l in ipairs(net.arptable()) do
if l["IP address"] == ip then if l["IP address"] == ip then
mac = l["HW address"] mac = l["HW address"]
end end
end end
return mac return mac
end end
-- Returns the prefix to a given netmask --- Calculate the prefix from a given netmask.
-- @param mask IPv4 net mask
-- @return Number containing the corresponding numerical prefix
function net.mask4prefix(mask) function net.mask4prefix(mask)
local bin = net.ip4bin(mask) local bin = net.ip4bin(mask)
if not bin then if not bin then
return nil return nil
end end
return #luci.util.split(bin, "1")-1 return #luci.util.split(bin, "1")-1
end end
-- Returns the kernel routing table --- Returns the current kernel routing table entries.
-- @return Table of tables with properties of the corresponding routes.
-- The following fields are defined for route entry tables:
-- { "Mask", "RefCnt", "Iface", "Flags", "Window", "IRTT",
-- "MTU", "Gateway", "Destination", "Metric", "Use" }
function net.routes() function net.routes()
return _parse_delimited_table(io.lines("/proc/net/route")) return _parse_delimited_table(io.lines("/proc/net/route"))
end end
-- Returns the numeric IP to a given hexstring --- Convert hexadecimal 32 bit value to IPv4 address.
-- @param hex String containing the hexadecimal value
-- @param be Boolean indicating wheather the given value is big endian
-- @return String containing the corresponding IP4 address
function net.hexip4(hex, be) function net.hexip4(hex, be)
if #hex ~= 8 then if #hex ~= 8 then
return nil return nil
end end
be = be or bigendian() be = be or bigendian()
local hexdec = luci.bits.Hex2Dec local hexdec = luci.bits.Hex2Dec
local ip = "" local ip = ""
if be then if be then
ip = ip .. tostring(hexdec(hex:sub(1,2))) .. "." ip = ip .. tostring(hexdec(hex:sub(1,2))) .. "."
@ -253,55 +320,88 @@ function net.hexip4(hex, be)
ip = ip .. tostring(hexdec(hex:sub(3,4))) .. "." ip = ip .. tostring(hexdec(hex:sub(3,4))) .. "."
ip = ip .. tostring(hexdec(hex:sub(1,2))) ip = ip .. tostring(hexdec(hex:sub(1,2)))
end end
return ip return ip
end end
-- Returns the binary IP to a given IP --- Convert given IPv4 address to binary value.
-- @param ip String containing a IPv4 address
-- @return String containing corresponding binary value
function net.ip4bin(ip) function net.ip4bin(ip)
local parts = luci.util.split(ip, '.') local parts = luci.util.split(ip, '.')
if #parts ~= 4 then if #parts ~= 4 then
return nil return nil
end end
local decbin = luci.bits.Dec2Bin local decbin = luci.bits.Dec2Bin
local bin = "" local bin = ""
bin = bin .. decbin(parts[1], 8) bin = bin .. decbin(parts[1], 8)
bin = bin .. decbin(parts[2], 8) bin = bin .. decbin(parts[2], 8)
bin = bin .. decbin(parts[3], 8) bin = bin .. decbin(parts[3], 8)
bin = bin .. decbin(parts[4], 8) bin = bin .. decbin(parts[4], 8)
return bin return bin
end end
-- Tests whether a host is pingable --- Tests whether the given host responds to ping probes.
-- @param host String containing a hostname or IPv4 address
-- @return Number containing 0 on success and >= 1 on error
function net.pingtest(host) function net.pingtest(host)
return os.execute("ping -c1 '"..host:gsub("'", '').."' >/dev/null 2>&1") return os.execute("ping -c1 '"..host:gsub("'", '').."' >/dev/null 2>&1")
end end
--- LuCI system utilities / process related functions.
-- @class module
-- @name luci.sys.process
process = {} process = {}
process.info = posix.getpid
-- Sets the gid of a process --- Get the current process id.
-- @return Number containing the current pid
process.info = posix.getpid
--- 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
-- @return Boolean indicating successful operation
-- @return String containing the error message if failed
-- @return Number containing the error code if failed
function process.setgroup(pid, gid) function process.setgroup(pid, gid)
return posix.setpid("g", pid, gid) return posix.setpid("g", pid, gid)
end end
-- Sets the uid of a process --- Set the uid of a process identified by given pid.
-- @param pid Number containing the process id
-- @param uid Number containing the Unix user id
-- @return Boolean indicating successful operation
-- @return String containing the error message if failed
-- @return Number containing the error code if failed
function process.setuser(pid, uid) function process.setuser(pid, uid)
return posix.setpid("u", pid, uid) return posix.setpid("u", pid, uid)
end end
--- LuCI system utilities / user related functions.
-- @class module
-- @name luci.sys.user
user = {} user = {}
-- returns user information to a given uid
--- Retrieve user informations for given uid.
-- @class function
-- @name getuser
-- @param uid Number containing the Unix user id
-- @return Table containing the following fields:
-- { "uid", "gid", "name", "passwd", "dir", "shell", "gecos" }
user.getuser = posix.getpasswd user.getuser = posix.getpasswd
-- checks whether a string matches the password of a certain system user --- Test whether given string matches the password of a given system user.
-- @param username String containing the Unix user name
-- @param password String containing the password to compare
-- @return Boolean indicating wheather the passwords are equal
function user.checkpasswd(username, password) function user.checkpasswd(username, password)
local account = user.getuser(username) local account = user.getuser(username)
-- FIXME: detect testing environment -- FIXME: detect testing environment
if luci.fs.stat("/etc/shadow") and not luci.fs.access("/etc/shadow", "r") then if luci.fs.stat("/etc/shadow") and not luci.fs.access("/etc/shadow", "r") then
return true return true
@ -313,29 +413,37 @@ function user.checkpasswd(username, password)
end end
end end
end end
-- Changes the user password of given user --- Change the password of given user.
function user.setpasswd(user, pwd) -- @param username String containing the Unix user name
if pwd then -- @param password String containing the password to compare
pwd = pwd:gsub("'", "") -- @return Number containing 0 on success and >= 1 on error
function user.setpasswd(username, password)
if password then
password = password:gsub("'", "")
end end
if user then if username then
user = user:gsub("'", "") username = username:gsub("'", "")
end end
local cmd = "(echo '"..pwd.."';sleep 1;echo '"..pwd.."')|" local cmd = "(echo '"..password.."';sleep 1;echo '"..password.."')|"
cmd = cmd .. "passwd '"..user.."' >/dev/null 2>&1" cmd = cmd .. "passwd '"..username.."' >/dev/null 2>&1"
return os.execute(cmd) return os.execute(cmd)
end end
--- LuCI system utilities / wifi related functions.
-- @class module
-- @name luci.sys.wifi
wifi = {} wifi = {}
--- Get iwconfig output for all wireless devices.
-- @return Table of tables containing the iwconfing output for each wifi device
function wifi.getiwconfig() function wifi.getiwconfig()
local cnt = exec("/usr/sbin/iwconfig 2>/dev/null") local cnt = exec("/usr/sbin/iwconfig 2>/dev/null")
local iwc = {} local iwc = {}
for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do
local k = l:match("^(.-) ") local k = l:match("^(.-) ")
l = l:gsub("^(.-) +", "", 1) l = l:gsub("^(.-) +", "", 1)
@ -343,14 +451,16 @@ function wifi.getiwconfig()
iwc[k] = _parse_mixed_record(l) iwc[k] = _parse_mixed_record(l)
end end
end end
return iwc return iwc
end end
--- Get iwlist scan output from all wireless devices.
-- @return Table of tables contaiing all scan results
function wifi.iwscan() function wifi.iwscan()
local cnt = exec("iwlist scan 2>/dev/null") local cnt = exec("iwlist scan 2>/dev/null")
local iws = {} local iws = {}
for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n\n")) do
local k = l:match("^(.-) ") local k = l:match("^(.-) ")
l = l:gsub("^[^\n]+", "", 1) l = l:gsub("^[^\n]+", "", 1)
@ -365,8 +475,8 @@ function wifi.iwscan()
end end
end end
end end
return iws return iws
end end
@ -374,16 +484,16 @@ end
function _parse_delimited_table(iter, delimiter) function _parse_delimited_table(iter, delimiter)
delimiter = delimiter or "%s+" delimiter = delimiter or "%s+"
local data = {} local data = {}
local trim = luci.util.trim local trim = luci.util.trim
local split = luci.util.split local split = luci.util.split
local keys = split(trim(iter()), delimiter, nil, true) local keys = split(trim(iter()), delimiter, nil, true)
for i, j in pairs(keys) do for i, j in pairs(keys) do
keys[i] = trim(keys[i]) keys[i] = trim(keys[i])
end end
for line in iter do for line in iter do
local row = {} local row = {}
line = trim(line) line = trim(line)
@ -396,26 +506,26 @@ function _parse_delimited_table(iter, delimiter)
end end
table.insert(data, row) table.insert(data, row)
end end
return data return data
end end
function _parse_mixed_record(cnt) function _parse_mixed_record(cnt)
local data = {} local data = {}
for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n")) do for i, l in pairs(luci.util.split(luci.util.trim(cnt), "\n")) do
for j, f in pairs(luci.util.split(luci.util.trim(l), " ")) do for j, f in pairs(luci.util.split(luci.util.trim(l), " ")) do
local k, x, v = f:match('([^%s][^:=]+) *([:=]*) *"*([^\n"]*)"*') local k, x, v = f:match('([^%s][^:=]+) *([:=]*) *"*([^\n"]*)"*')
if k then if k then
if x == "" then if x == "" then
table.insert(data, k) table.insert(data, k)
else else
data[k] = v data[k] = v
end end
end end
end end
end end
return data return data
end end