Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
freebsd
GitHub Repository: freebsd/freebsd-src
Path: blob/main/stand/lua/cli.lua
34680 views
1
--
2
-- SPDX-License-Identifier: BSD-2-Clause
3
--
4
-- Copyright (c) 2018 Kyle Evans <[email protected]>
5
--
6
-- Redistribution and use in source and binary forms, with or without
7
-- modification, are permitted provided that the following conditions
8
-- are met:
9
-- 1. Redistributions of source code must retain the above copyright
10
-- notice, this list of conditions and the following disclaimer.
11
-- 2. Redistributions in binary form must reproduce the above copyright
12
-- notice, this list of conditions and the following disclaimer in the
13
-- documentation and/or other materials provided with the distribution.
14
--
15
-- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
16
-- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
17
-- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
18
-- ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
19
-- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
20
-- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
21
-- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
22
-- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
23
-- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
24
-- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
25
-- SUCH DAMAGE.
26
--
27
28
local config = require("config")
29
local core = require("core")
30
31
local cli = {}
32
33
if not pager then
34
-- shim for the pager module that just doesn't do it.
35
-- XXX Remove after 12.2 goes EoL.
36
pager = {
37
open = function() end,
38
close = function() end,
39
output = function(str)
40
printc(str)
41
end,
42
}
43
end
44
45
-- Internal function
46
-- Parses arguments to boot and returns two values: kernel_name, argstr
47
-- Defaults to nil and "" respectively.
48
-- This will also parse arguments to autoboot, but the with_kernel argument
49
-- will need to be explicitly overwritten to false
50
local function parseBootArgs(argv, with_kernel)
51
if with_kernel == nil then
52
with_kernel = true
53
end
54
if #argv == 0 then
55
if with_kernel then
56
return nil, ""
57
else
58
return ""
59
end
60
end
61
local kernel_name
62
local argstr = ""
63
64
for _, v in ipairs(argv) do
65
if with_kernel and v:sub(1,1) ~= "-" then
66
kernel_name = v
67
else
68
argstr = argstr .. " " .. v
69
end
70
end
71
if with_kernel then
72
return kernel_name, argstr
73
else
74
return argstr
75
end
76
end
77
78
local function setModule(module, loading)
79
if loading and config.enableModule(module) then
80
print(module .. " will be loaded")
81
elseif not loading and config.disableModule(module) then
82
print(module .. " will not be loaded")
83
end
84
end
85
86
-- Declares a global function cli_execute that attempts to dispatch the
87
-- arguments passed as a lua function. This gives lua a chance to intercept
88
-- builtin CLI commands like "boot"
89
-- This function intentionally does not follow our general naming guideline for
90
-- functions. This is global pollution, but the clearly separated 'cli' looks
91
-- more like a module indicator to serve as a hint of where to look for the
92
-- corresponding definition.
93
function cli_execute(...)
94
local argv = {...}
95
-- Just in case...
96
if #argv == 0 then
97
return loader.command(...)
98
end
99
100
local cmd_name = argv[1]
101
local cmd = cli[cmd_name]
102
if cmd ~= nil and type(cmd) == "function" then
103
-- Pass argv wholesale into cmd. We could omit argv[0] since the
104
-- traditional reasons for including it don't necessarily apply,
105
-- it may not be totally redundant if we want to have one global
106
-- handling multiple commands
107
return cmd(...)
108
else
109
return loader.command(...)
110
end
111
112
end
113
114
function cli_execute_unparsed(str)
115
return cli_execute(loader.parse(str))
116
end
117
118
-- Module exports
119
120
function cli.boot(...)
121
local _, argv = cli.arguments(...)
122
local kernel, argstr = parseBootArgs(argv)
123
if kernel ~= nil then
124
loader.perform("unload")
125
config.selectKernel(kernel)
126
end
127
core.boot(argstr)
128
end
129
130
function cli.autoboot(...)
131
local _, argv = cli.arguments(...)
132
local argstr = parseBootArgs(argv, false)
133
core.autoboot(argstr)
134
end
135
136
cli['boot-conf'] = function(...)
137
local _, argv = cli.arguments(...)
138
local kernel, argstr = parseBootArgs(argv)
139
if kernel ~= nil then
140
loader.perform("unload")
141
config.selectKernel(kernel)
142
end
143
core.autoboot(argstr)
144
end
145
146
cli['read-conf'] = function(...)
147
local _, argv = cli.arguments(...)
148
config.readConf(assert(core.popFrontTable(argv)))
149
end
150
151
cli['reload-conf'] = function()
152
config.reload()
153
end
154
155
cli["enable-module"] = function(...)
156
local _, argv = cli.arguments(...)
157
if #argv == 0 then
158
print("usage error: enable-module module")
159
return
160
end
161
162
setModule(argv[1], true)
163
end
164
165
cli["disable-module"] = function(...)
166
local _, argv = cli.arguments(...)
167
if #argv == 0 then
168
print("usage error: disable-module module")
169
return
170
end
171
172
setModule(argv[1], false)
173
end
174
175
cli["toggle-module"] = function(...)
176
local _, argv = cli.arguments(...)
177
if #argv == 0 then
178
print("usage error: toggle-module module")
179
return
180
end
181
182
local module = argv[1]
183
setModule(module, not config.isModuleEnabled(module))
184
end
185
186
cli["show-module-options"] = function()
187
local module_info = config.getModuleInfo()
188
local modules = module_info['modules']
189
local blacklist = module_info['blacklist']
190
local lines = {}
191
192
for module, info in pairs(modules) do
193
if #lines > 0 then
194
lines[#lines + 1] = ""
195
end
196
197
lines[#lines + 1] = "Name: " .. module
198
if info.name then
199
lines[#lines + 1] = "Path: " .. info.name
200
end
201
202
if info.type then
203
lines[#lines + 1] = "Type: " .. info.type
204
end
205
206
if info.flags then
207
lines[#lines + 1] = "Flags: " .. info.flags
208
end
209
210
if info.before then
211
lines[#lines + 1] = "Before load: " .. info.before
212
end
213
214
if info.after then
215
lines[#lines + 1] = "After load: " .. info.after
216
end
217
218
if info.error then
219
lines[#lines + 1] = "Error: " .. info.error
220
end
221
222
local status
223
if blacklist[module] and not info.force then
224
status = "Blacklisted"
225
elseif info.load == "YES" then
226
status = "Load"
227
else
228
status = "Don't load"
229
end
230
231
lines[#lines + 1] = "Status: " .. status
232
end
233
234
pager.open()
235
for _, v in ipairs(lines) do
236
pager.output(v .. "\n")
237
end
238
pager.close()
239
end
240
241
cli["disable-device"] = function(...)
242
local _, argv = cli.arguments(...)
243
local d, u
244
245
if #argv == 0 then
246
print("usage error: disable-device device")
247
return
248
end
249
250
d, u = string.match(argv[1], "(%w*%a)(%d+)")
251
if d ~= nil then
252
loader.setenv("hint." .. d .. "." .. u .. ".disabled", "1")
253
end
254
end
255
256
-- Used for splitting cli varargs into cmd_name and the rest of argv
257
function cli.arguments(...)
258
local argv = {...}
259
local cmd_name
260
cmd_name, argv = core.popFrontTable(argv)
261
return cmd_name, argv
262
end
263
264
return cli
265
266