2 FFLuCI - System library
5 Utilities for interaction with the Linux system
11 Copyright 2008 Steven Barth <steven@midlink.org>
13 Licensed under the Apache License, Version 2.0 (the "License");
14 you may not use this file except in compliance with the License.
15 You may obtain a copy of the License at
17 http://www.apache.org/licenses/LICENSE-2.0
19 Unless required by applicable law or agreed to in writing, software
20 distributed under the License is distributed on an "AS IS" BASIS,
21 WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
22 See the License for the specific language governing permissions and
23 limitations under the License.
27 module("ffluci.sys", package.seeall)
29 require("ffluci.bits")
30 require("ffluci.util")
32 -- Returns whether a system is bigendian
34 local fp = io.open("/bin/sh")
36 return (fp:read(1):byte() ~= 1)
39 -- Runs "command" and returns its output
40 function exec(command)
41 local pp = io.popen(command)
42 local data = pp:read("*a")
48 -- Runs "command" and returns its output as a array of lines
49 function execl(command)
50 local pp = io.popen(command)
56 if (line == nil) then break end
57 table.insert(data, line)
64 -- Uses "ffluci-flash" to flash a new image file to the system
65 function flash(image, kpattern)
66 local cmd = "ffluci-flash "
68 cmd = cmd .. "-k '" .. kpattern:gsub("'", "") .. "' "
70 cmd = cmd .. "'" .. image:gsub("'", "") .. "' >/dev/null 2>&1"
72 return os.execute(cmd)
75 -- Returns the hostname
77 return io.lines("/proc/sys/kernel/hostname")()
80 -- Returns the contents of a documented referred by an URL
82 return exec("wget -qO- '"..url:gsub("'", "").."'")
85 -- Returns the load average
87 local loadavg = io.lines("/proc/loadavg")()
88 return loadavg:match("^(.-) (.-) (.-) (.-) (.-)$")
93 return os.execute("reboot >/dev/null 2>&1")
96 -- Returns the system type, cpu name, and installed physical memory
98 local c1 = "cat /proc/cpuinfo|grep system\\ typ|cut -d: -f2 2>/dev/null"
99 local c2 = "uname -m 2>/dev/null"
100 local c3 = "cat /proc/cpuinfo|grep model\\ name|cut -d: -f2 2>/dev/null"
101 local c4 = "cat /proc/cpuinfo|grep cpu\\ model|cut -d: -f2 2>/dev/null"
102 local c5 = "cat /proc/meminfo|grep MemTotal|cut -d: -f2 2>/dev/null"
104 local s = ffluci.util.trim(exec(c1))
109 s = ffluci.util.trim(exec(c2))
110 m = ffluci.util.trim(exec(c3))
112 m = ffluci.util.trim(exec(c4))
115 r = ffluci.util.trim(exec(c5))
122 group.getgroup = posix.getgroup
125 -- Returns the ARP-Table
126 function net.arptable()
127 return _parse_delimited_table(io.lines("/proc/net/arp"), "%s%s+")
130 -- Returns whether an IP-Adress belongs to a certain net
131 function net.belongs(ip, ipnet, prefix)
132 return (net.ip4bin(ip):sub(1, prefix) == net.ip4bin(ipnet):sub(1, prefix))
135 -- Detect the default route
136 function net.defaultroute()
137 local routes = net.routes()
140 for i, r in pairs(ffluci.sys.net.routes()) do
141 if r.Destination == "00000000" and (not route or route.Metric > r.Metric) then
149 -- Returns all available network interfaces
150 function net.devices()
152 for line in io.lines("/proc/net/dev") do
153 table.insert(devices, line:match(" *(.-):"))
158 -- Returns the MAC-Address belonging to the given IP-Address
159 function net.ip4mac(ip)
162 for i, l in ipairs(net.arptable()) do
163 if l["IP address"] == ip then
164 mac = l["HW address"]
171 -- Returns the prefix to a given netmask
172 function net.mask4prefix(mask)
173 local bin = net.ip4bin(mask)
179 return #ffluci.util.split(bin, "1")-1
182 -- Returns the kernel routing table
183 function net.routes()
184 return _parse_delimited_table(io.lines("/proc/net/route"))
187 -- Returns the numeric IP to a given hexstring
188 function net.hexip4(hex, be)
193 be = be or bigendian()
195 local hexdec = ffluci.bits.Hex2Dec
199 ip = ip .. tostring(hexdec(hex:sub(1,2))) .. "."
200 ip = ip .. tostring(hexdec(hex:sub(3,4))) .. "."
201 ip = ip .. tostring(hexdec(hex:sub(5,6))) .. "."
202 ip = ip .. tostring(hexdec(hex:sub(7,8)))
204 ip = ip .. tostring(hexdec(hex:sub(7,8))) .. "."
205 ip = ip .. tostring(hexdec(hex:sub(5,6))) .. "."
206 ip = ip .. tostring(hexdec(hex:sub(3,4))) .. "."
207 ip = ip .. tostring(hexdec(hex:sub(1,2)))
213 -- Returns the binary IP to a given IP
214 function net.ip4bin(ip)
215 local parts = ffluci.util.split(ip, '.')
220 local decbin = ffluci.bits.Dec2Bin
223 bin = bin .. decbin(parts[1], 8)
224 bin = bin .. decbin(parts[2], 8)
225 bin = bin .. decbin(parts[3], 8)
226 bin = bin .. decbin(parts[4], 8)
231 -- Tests whether a host is pingable
232 function net.pingtest(host)
233 return os.execute("ping -c1 '"..host:gsub("'", '').."' >/dev/null 2>&1")
238 process.info = posix.getpid
240 -- Sets the gid of a process
241 function process.setgroup(pid, gid)
242 return posix.setpid("g", pid, gid)
245 -- Sets the uid of a process
246 function process.setuser(pid, uid)
247 return posix.setpid("u", pid, uid)
251 -- returns user information to a given uid
252 user.getuser = posix.getpasswd
254 -- Changes the user password of given user
255 function user.setpasswd(user, pwd)
257 pwd = pwd:gsub("'", "")
261 user = user:gsub("'", "")
264 local cmd = "(echo '"..pwd.."';sleep 1;echo '"..pwd.."')|"
265 cmd = cmd .. "passwd '"..user.."' >/dev/null 2>&1"
266 return os.execute(cmd)
272 function wifi.getiwconfig()
273 local cnt = exec("/usr/sbin/iwconfig 2>/dev/null")
276 for i, l in pairs(ffluci.util.split(ffluci.util.trim(cnt), "\n\n")) do
277 local k = l:match("^(.-) ")
278 l = l:gsub("^(.-) +", "", 1)
280 iwc[k] = _parse_mixed_record(l)
287 function wifi.iwscan()
288 local cnt = exec("iwlist scan 2>/dev/null")
291 for i, l in pairs(ffluci.util.split(ffluci.util.trim(cnt), "\n\n")) do
292 local k = l:match("^(.-) ")
293 l = l:gsub("^[^\n]+", "", 1)
294 l = ffluci.util.trim(l)
297 for j, c in pairs(ffluci.util.split(l, "\n Cell")) do
298 c = c:gsub("^(.-)- ", "", 1)
299 c = ffluci.util.split(c, "\n", 7)
300 c = table.concat(c, "\n", 1)
301 table.insert(iws[k], _parse_mixed_record(c))
310 -- Internal functions
312 function _parse_delimited_table(iter, delimiter)
313 delimiter = delimiter or "%s+"
316 local trim = ffluci.util.trim
317 local split = ffluci.util.split
319 local keys = split(trim(iter()), delimiter, nil, true)
320 for i, j in pairs(keys) do
321 keys[i] = trim(keys[i])
328 for i, j in pairs(split(line, delimiter, nil, true)) do
334 table.insert(data, row)
340 function _parse_mixed_record(cnt)
343 for i, l in pairs(ffluci.util.split(ffluci.util.trim(cnt), "\n")) do
344 for j, f in pairs(ffluci.util.split(ffluci.util.trim(l), " ")) do
345 local k, x, v = f:match('([^%s][^:=]+) *([:=]*) *"*([^\n"]*)"*')
349 table.insert(data, k)