]> CyberLeo.Net >> Repos - FreeBSD/FreeBSD.git/blob - stand/lua/config.lua
stand/lua: Style pass
[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 -- other_kernel is optionally the name of a kernel to load, if not the default
257 -- or autoloaded default from the module_path
258 function config.loadkernel(other_kernel)
259         local flags = loader.getenv("kernel_options") or "";
260         local kernel = other_kernel or loader.getenv("kernel");
261
262         local try_load = function (names)
263                 for name in names:gmatch("([^;]+)%s*;?") do
264                         r = loader.perform("load "..flags.." "..name);
265                         if r == 0 then
266                                 return name;
267                         end
268                 end
269                 return nil;
270         end
271
272         local load_bootfile = function()
273                 local bootfile = loader.getenv("bootfile");
274
275                 -- append default kernel name
276                 if not bootfile then
277                         bootfile = "kernel";
278                 else
279                         bootfile = bootfile..";kernel";
280                 end
281
282                 return try_load(bootfile);
283         end
284
285         -- kernel not set, try load from default module_path
286         if kernel == nil then
287                 local res = load_bootfile();
288
289                 if res ~= nil then
290                         return true;
291                 else
292                         print("No kernel set, failed to load from module_path");
293                         return false;
294                 end
295         else
296                 local module_path = loader.getenv("module_path");
297                 local res = nil;
298
299                 if other_kern ~= nil then
300                         kernel = other_kern;
301                 end
302                 -- first try load kernel with module_path = /boot/${kernel}
303                 -- then try load with module_path=${kernel}
304                 local paths = {"/boot/"..kernel, kernel};
305
306                 for k,v in pairs(paths) do
307
308                         loader.setenv("module_path", v);
309                         res = load_bootfile();
310
311                         -- succeeded add path to module_path
312                         if res ~= nil then
313                                 if module_path ~= nil then
314                                         loader.setenv("module_path", v..";"..
315                                             module_path);
316                                 end
317                                 return true;
318                         end
319                 end
320
321                 -- failed to load with ${kernel} as a directory
322                 -- try as a file
323                 res = try_load(kernel);
324                 if res ~= nil then
325                         return true;
326                 else
327                         print("Failed to load kernel '"..kernel.."'");
328                         return false;
329                 end
330         end
331 end
332
333
334 function config.load(file)
335
336         if not file then
337                 file = "/boot/defaults/loader.conf";
338         end
339
340         if not config.parse(file) then
341 --              print("Failed to parse configuration: '"..file.."'");
342         end
343
344         local f = loader.getenv("loader_conf_files");
345         if f ~= nil then
346                 for name in f:gmatch("([%w%p]+)%s*") do
347                         if not config.parse(name) then
348 --                              print("Failed to parse configuration: '"..name.."'");
349                         end
350                 end
351         end
352
353         print("Loading kernel...");
354         config.loadkernel();
355
356         print("Loading configured modules...");
357         if not config.loadmod(modules) then
358                 print("Could not load one or more modules!");
359         end
360 end
361
362 function config.reload(kernel)
363         local kernel_loaded = false;
364
365         -- unload all modules
366         print("Unloading modules...");
367         loader.perform("unload");
368
369         if (kernel ~= nil) then
370                 print("Trying to load '" .. kernel .. "'")
371                 kernel_loaded = config.loadkernel(kernel);
372                 if (kernel_loaded) then
373                         print("Kernel '"..kernel.."' loaded!");
374                 end
375         end
376
377         -- failed to load kernel or it is nil
378         -- then load default
379         if (not kernel_loaded) then
380                 print("Loading default kernel...");
381                 config.loadkernel();
382         end
383
384         -- load modules
385         config.loadmod(modules);
386 end
387
388 return config