]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/lua/config.lua
stand/lua: Address some nits
[FreeBSD/FreeBSD.git] / stand / lua / config.lua
1 --
2 -- Copyright (c) 2015 Pedro Souza <pedrosouza@freebsd.org>
3 -- All rights reserved.
4 --
5 -- Redistribution and use in source and binary forms, with or without
6 -- modification, are permitted provided that the following conditions
7 -- are met:
8 -- 1. Redistributions of source code must retain the above copyright
9 --    notice, this list of conditions and the following disclaimer.
10 -- 2. Redistributions in binary form must reproduce the above copyright
11 --    notice, this list of conditions and the following disclaimer in the
12 --    documentation and/or other materials provided with the distribution.
13 --
14 -- THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
15 -- ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
16 -- IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
17 -- ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
18 -- FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
19 -- DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
20 -- OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
21 -- HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
22 -- LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
23 -- OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
24 -- SUCH DAMAGE.
25 --
26 -- $FreeBSD$
27 --
28
29 local config = {};
30
31 local modules = {};
32
33 function config.setKey(k, n, v)
34         if modules[k] == nil then
35                 modules[k] = {};
36         end
37         modules[k][n] = v;
38 end
39
40 function config.dumpModules()
41         print("== Dumping modules");
42         for k, v in pairs(modules) do
43                 print(k, v.load);
44         end
45         print("== Dump ended");
46 end
47
48 local pattern_table = {
49         [1] = {
50                 str = "^%s*(#.*)",
51                 process = function(k, v)  end
52         },
53         --  module_load="value"
54         [2] = {
55                 str = "^%s*([%w_]+)_load%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
56                 process = function(k, v)
57                         if modules[k] == nil then
58                                 modules[k] = {};
59                         end
60                         modules[k].load = v:upper();
61                 end
62         },
63         --  module_name="value"
64         [3] = {
65                 str = "^%s*([%w_]+)_name%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
66                 process = function(k, v)
67                         config.setKey(k, "name", v);
68                 end
69         },
70         --  module_type="value"
71         [4] = {
72                 str = "^%s*([%w_]+)_type%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
73                 process = function(k, v)
74                         config.setKey(k, "type", v);
75                 end
76         },
77         --  module_flags="value"
78         [5] = {
79                 str = "^%s*([%w_]+)_flags%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
80                 process = function(k, v)
81                         config.setKey(k, "flags", v);
82                 end
83         },
84         --  module_before="value"
85         [6] = {
86                 str = "^%s*([%w_]+)_before%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
87                 process = function(k, v)
88                         config.setKey(k, "before", v);
89                 end
90         },
91         --  module_after="value"
92         [7] = {
93                 str = "^%s*([%w_]+)_after%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
94                 process = function(k, v)
95                         config.setKey(k, "after", v);
96                 end
97         },
98         --  module_error="value"
99         [8] = {
100                 str = "^%s*([%w_]+)_error%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
101                 process = function(k, v)
102                         config.setKey(k, "error", v);
103                 end
104         },
105         --  exec="command"
106         [9] = {
107                 str = "^%s*exec%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
108                 process = function(k, v)
109                         if loader.perform(k) ~= 0 then
110                                 print("Failed to exec '"..k.."'");
111                         end
112                 end
113         },
114         --  env_var="value"
115         [10] = {
116                 str = "^%s*([%w%p]+)%s*=%s*\"([%w%s%p]-)\"%s*(.*)",
117                 process = function(k, v)
118                         if loader.setenv(k, v) ~= 0 then
119                                 print("Failed to set '"..k.."' with value: "..v.."");
120                         end
121                 end
122         },
123         --  env_var=num
124         [11] = {
125                 str = "^%s*([%w%p]+)%s*=%s*(%d+)%s*(.*)",
126                 process = function(k, v)
127                         if loader.setenv(k, v) ~= 0 then
128                                 print("Failed to set '"..k.."' with value: "..v.."");
129                         end
130                 end
131         }
132 };
133
134 function config.isValidComment(c)
135         if c ~= nil then
136                 local s = c:match("^%s*#.*");
137                 if s == nil then
138                         s = c:match("^%s*$");
139                 end
140                 if s == nil then
141                         return false;
142                 end
143         end
144         return true;
145 end
146
147 function config.loadmod(mod, silent)
148         local status = true;
149         for k, v in pairs(mod) do
150                 if v.load == "YES" then
151                         local str = "load ";
152                         if v.flags ~= nil then
153                                 str = str .. v.flags .. " ";
154                         end
155                         if v.type ~= nil then
156                                 str = str .. "-t " .. v.type .. " ";
157                         end
158                         if v.name ~= nil then
159                                 str = str .. v.name;
160                         else
161                                 str = str .. k;
162                         end
163
164                         if v.before ~= nil then
165                                 if loader.perform(v.before) ~= 0 then
166                                         if not silent then
167                                                 print("Failed to execute '"..v.before.."' before loading '"..k.."'");
168                                         end
169                                         status = false;
170                                 end
171                         end
172
173                         if loader.perform(str) ~= 0 then
174                                 if not silent then
175                                         print("Failed to execute '" .. str .. "'");
176                                 end
177                                 if v.error ~= nil then
178                                         loader.perform(v.error);
179                                 end
180                                 status = false;
181                         end
182
183                         if v.after ~= nil then
184                                 if loader.perform(v.after) ~= 0 then
185                                         if not silent then
186                                                 print("Failed to execute '"..v.after.."' after loading '"..k.."'");
187                                         end
188                                         status = false;
189                                 end
190                         end
191
192                 else
193                         --if not silent then print("Skiping module '".. k .. "'"); end
194                 end
195         end
196
197         return status;
198 end
199
200 function config.parse(name, silent)
201         local f = io.open(name);
202         if f == nil then
203                 if not silent then
204                         print("Failed to open config: '" .. name.."'");
205                 end
206                 return false;
207         end
208
209         local text;
210         local r;
211
212         text, r = io.read(f);
213
214         if text == nil then
215                 if not silent then
216                         print("Failed to read config: '" .. name.."'");
217                 end
218                 return false;
219         end
220
221         local n = 1;
222         local status = true;
223
224         for line in text:gmatch("([^\n]+)") do
225
226                 if line:match("^%s*$") == nil then
227                         local found = false;
228
229                         for i, val in ipairs(pattern_table) do
230                                 local k, v, c = line:match(val.str);
231                                 if k ~= nil then
232                                         found = true;
233
234                                         if config.isValidComment(c) then
235                                                 val.process(k, v);
236                                         else
237                                                 print("Malformed line ("..n.."):\n\t'"..line.."'");
238                                                 status = false;
239                                         end
240
241                                         break;
242                                 end
243                         end
244
245                         if found == false then
246                                 print("Malformed line ("..n.."):\n\t'"..line.."'");
247                                 status = false;
248                         end
249                 end
250                 n = n + 1;
251         end
252
253         return status;
254 end
255
256 function config.loadkernel()
257         local flags = loader.getenv("kernel_options") or "";
258         local kernel = loader.getenv("kernel");
259
260         local try_load = function (names)
261                 for name in names:gmatch("([^;]+)%s*;?") do
262                         r = loader.perform("load "..flags.." "..name);
263                         if r == 0 then
264                                 return name;
265                         end
266                 end
267                 return nil;
268         end;
269
270         local load_bootfile = function()
271                 local bootfile = loader.getenv("bootfile");
272
273                 -- append default kernel name
274                 if not bootfile then
275                         bootfile = "kernel";
276                 else
277                         bootfile = bootfile..";kernel";
278                 end
279
280                 return try_load(bootfile);
281         end;
282
283         -- kernel not set, try load from default module_path
284         if kernel == nil then
285                 local res = load_bootfile();
286
287                 if res ~= nil then
288                         return true;
289                 else
290                         print("No kernel set, failed to load from module_path");
291                         return false;
292                 end
293         else
294                 local module_path = loader.getenv("module_path");
295                 local res = nil;
296
297                 -- first try load kernel with module_path = /boot/${kernel}
298                 -- then try load with module_path=${kernel}
299                 local paths = {"/boot/"..kernel, kernel};
300
301                 for k,v in pairs(paths) do
302
303                         loader.setenv("module_path", v);
304                         res = load_bootfile();
305
306                         -- succeeded add path to module_path
307                         if res ~= nil then
308                                 if module_path == nil then
309                                         loader.setenv("module_path", v..";"..
310                                             module_path);
311                                 end
312                                 return true;
313                         end
314                 end
315
316                 -- failed to load with ${kernel} as a directory
317                 -- try as a file
318                 res = try_load(kernel);
319                 if res ~= nil then
320                         return true;
321                 else
322                         print("Failed to load kernel '"..kernel.."'");
323                         return false;
324                 end
325         end
326 end
327
328
329 function config.load(file)
330
331         if not file then
332                 file = "/boot/defaults/loader.conf";
333         end
334
335         if not config.parse(file) then
336 --              print("Failed to parse configuration: '"..file.."'");
337         end
338
339         local f = loader.getenv("loader_conf_files");
340         if f ~= nil then
341                 for name in f:gmatch("([%w%p]+)%s*") do
342                         if not config.parse(name) then
343 --                              print("Failed to parse configuration: '"..name.."'");
344                         end
345                 end
346         end
347
348         print("Loading kernel...");
349         config.loadkernel();
350
351         print("Loading configured modules...");
352         if not config.loadmod(modules) then
353                 print("Could not load one or more modules!");
354         end
355 end
356
357 function config.reload(kernel)
358         local res = 1;
359
360         -- unload all modules
361         print("Unloading modules...");
362         loader.perform("unload");
363
364         if kernel ~= nil then
365                 res = loader.perform("load "..kernel);
366                 if res == 0 then
367                         print("Kernel '"..kernel.."' loaded!");
368                 end
369         end
370
371         -- failed to load kernel or it is nil
372         -- then load default
373         if res == 1 then
374                 print("Loading default kernel...");
375                 config.loadkernel();
376         end
377
378         -- load modules
379         config.loadmod(modules);
380 end
381
382 return config