1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
|
module(..., package.seeall)
require("posix")
require("fs")
require("format")
local path = "PATH=/usr/bin:/bin:/usr/sbin:/sbin "
function package_version(packagename)
local cmderrors
local f = io.popen( "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin apk_version -vs " .. format.escapespecialcharacters(packagename) .." | egrep -v 'acf' 2>/dev/null" )
local cmdresult = f:read("*l")
if (cmdresult) and (#cmdresult > 0) then
cmdresult = (string.match(cmdresult,"^%S*") or "Unknown")
else
cmderrors = "Program not installed"
end
f:close()
return cmdresult,cmderrors
end
function process_startupsequence(servicename)
local cmderrors
local f = io.popen( "/sbin/rc_status | egrep '^S' | egrep \"" .. format.escapespecialcharacters(servicename) .."\" 2>/dev/null" )
local cmdresult = f:read("*a")
if (cmdresult) and (#cmdresult > 0) then
cmdresult = "Service will autostart at next boot (at sequence '" .. string.match(cmdresult,"^%a+(%d%d)") .. "')"
else
cmderrors = "Not programmed to autostart"
end
f:close()
return cmdresult,cmderrors
end
function read_startupsequence()
local config = {}
local f = io.popen( "/sbin/rc_status 2>/dev/null" )
local cmdresult = f:read("*a") or ""
f:close()
local section = 0
for line in string.gmatch(cmdresult, "([^\n]*)\n?") do
local sequence, service = string.match(line, "(%d%d)(%S+)")
if service then
if section == 3 then -- kill section
for i,cfg in ipairs(config) do
if cfg.servicename == service then
cfg.kill = true
break
end
end
else
config[#config+1] = {servicename=service, sequence=sequence, kill=false, system=(section == 1)}
end
elseif string.match(line, "^rc.%.d:") then
section = section + 1
end
end
-- Add in any missing init.d scripts
local reverseservices = {} for i,cfg in ipairs(config) do reverseservices[cfg.servicename] = i end
local temp = {}
for name in posix.files("/etc/init.d") do
if not reverseservices[name] and not string.find(name, "^rc[KLS]$") and not string.find(name, "^..?$") then
temp[#temp+1] = {servicename=name, sequence="", kill=false, system=false}
end
end
table.sort(temp, function(a,b) return a.servicename < b.servicename end)
for i,val in ipairs(temp) do
config[#config+1] = val
end
return config
end
function add_startupsequence(servicename, sequence, kill, system)
local cmdresult,cmderrors
if not servicename then
cmderrors = "Invalid service name"
else
local cmd = {path, "rc_add"}
if kill then cmd[#cmd+1] = "-k" end
if system then cmd[#cmd+1] = "-S" end
if sequence and tonumber(sequence) then cmd[#cmd+1] = "-s "..sequence end
cmd[#cmd+1] = format.escapespecialcharacters(servicename)
cmd[#cmd+1] = "2>&1"
delete_startupsequence(servicename)
local f = io.popen(table.concat(cmd, " "))
cmdresult = f:read("*a")
f:close()
if cmdresult == "" then cmdresult = "Added sequence" end
end
return cmdresult,cmderrors
end
function delete_startupsequence(servicename)
local cmdresult,cmderrors
if not servicename then
cmderrors = "Invalid service name"
else
local f = io.popen(path.."rc_delete "..format.escapespecialcharacters(servicename))
cmdresult = f:read("*a")
f:close()
if cmdresult == "" then cmderrors = "Failed to delete sequence" end
end
return cmdresult,cmderrors
end
function daemoncontrol (process, action)
local cmdresult = ""
local cmderrors
if not process then
cmderrors = "Invalid service name"
elseif (string.lower(action) == "start") or (string.lower(action) == "stop") or (string.lower(action) == "restart") then
local file = io.popen( "PATH=/usr/local/bin:/usr/bin:/bin:/usr/local/sbin:/usr/sbin:/sbin /etc/init.d/" ..
format.escapespecialcharacters(process) .. " " .. string.lower(action) .. " 2>&1" )
if file ~= nil then
cmdresult = file:read( "*a" )
file:close()
end
posix.sleep(2) -- Wait for the process to start|stop
else
cmderrors = "Unknown command!"
end
return cmdresult,cmderrors
end
-- the following methods are available:
-- /proc/<pid>/stat the comm field (2nd) field contains name but only up
-- to 15 chars. does not resolve links
--
-- /proc/<pid>/cmdline argv[0] contains the command. However if it is a script
-- then will the interpreter show up
--
-- /proc/<pid>/exe link to exe file. this will resolv links
--
-- returns list of all pids for given exe name
--[[
-- gives lots of false positives for busybox
local function is_exe(path, name)
local f = posix.readlink(path.."/exe")
if f and (f == name or posix.basename(f) == name) then
return true
else
return false
end
end
]]--
local function is_stat(path, name)
local f = io.open(path.."/stat")
if (f) then
local line = f:read()
local p = string.gsub(line, ".*%(", "")
p = string.gsub(p, "%).*", "")
f:close()
end
if p ~= nil then
if string.len(name) <= 15 and p == name then
return true
end
end
return false
end
local function is_cmdline(path, name)
local f = io.open(path.."/cmdline")
if f == nil then
return false
end
local line = f:read()
f:close()
if line == nil then
return false
end
local arg0 = string.gsub(line, string.char(0)..".*", "")
if posix.basename(arg0) == name then
return true
end
end
local function has_pidfile(name)
local pid
local f = io.popen(path .. "find /var/run/ -name "..format.escapespecialcharacters(name)..".pid")
local file = f:read("*a")
f:close()
if file and string.find(file, "%w") then
-- check to see if there's a matching proc directory and that it was created slightly after the pid file
-- this allows us to find init scripts with differing process names and avoids the problem with
-- proc numbers wrapping
file = string.match(file, "^%s*(.*%S)")
local tmp = string.match(fs.read_file(file) or "", "%d+")
if tmp then
local dir = "/proc/" .. tmp
filetime = posix.stat(file, "ctime")
dirtime = posix.stat(dir, "ctime")
if dirtime and (tonumber(dirtime) - tonumber(filetime) < 100) then
pid = tmp
end
end
end
return pid
end
function pidof(name)
local pids = {has_pidfile(name)}
local i, j
for i,j in pairs(posix.glob("/proc/[0-9]*")) do
local pid = tonumber(posix.basename(j))
if is_stat(j, name) or is_cmdline(j, name) then
table.insert(pids, pid)
end
end
if #pids == 0 then
pids = nil
end
return pids
end
|