1*479ab7f0SSascha Wildner /*
2*479ab7f0SSascha Wildner * Copyright (c) 2010 The DragonFly Project. All rights reserved.
3*479ab7f0SSascha Wildner *
4*479ab7f0SSascha Wildner * This code is derived from software contributed to The DragonFly Project
5*479ab7f0SSascha Wildner * by Matthew Dillon <dillon@backplane.com>
6*479ab7f0SSascha Wildner *
7*479ab7f0SSascha Wildner * Redistribution and use in source and binary forms, with or without
8*479ab7f0SSascha Wildner * modification, are permitted provided that the following conditions
9*479ab7f0SSascha Wildner * are met:
10*479ab7f0SSascha Wildner *
11*479ab7f0SSascha Wildner * 1. Redistributions of source code must retain the above copyright
12*479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer.
13*479ab7f0SSascha Wildner * 2. Redistributions in binary form must reproduce the above copyright
14*479ab7f0SSascha Wildner * notice, this list of conditions and the following disclaimer in
15*479ab7f0SSascha Wildner * the documentation and/or other materials provided with the
16*479ab7f0SSascha Wildner * distribution.
17*479ab7f0SSascha Wildner * 3. Neither the name of The DragonFly Project nor the names of its
18*479ab7f0SSascha Wildner * contributors may be used to endorse or promote products derived
19*479ab7f0SSascha Wildner * from this software without specific, prior written permission.
20*479ab7f0SSascha Wildner *
21*479ab7f0SSascha Wildner * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22*479ab7f0SSascha Wildner * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23*479ab7f0SSascha Wildner * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24*479ab7f0SSascha Wildner * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25*479ab7f0SSascha Wildner * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26*479ab7f0SSascha Wildner * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27*479ab7f0SSascha Wildner * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28*479ab7f0SSascha Wildner * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29*479ab7f0SSascha Wildner * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30*479ab7f0SSascha Wildner * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31*479ab7f0SSascha Wildner * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32*479ab7f0SSascha Wildner * SUCH DAMAGE.
33*479ab7f0SSascha Wildner */
34*479ab7f0SSascha Wildner
35*479ab7f0SSascha Wildner #include <stand.h>
36*479ab7f0SSascha Wildner #include <string.h>
37*479ab7f0SSascha Wildner #include "bootstrap.h"
38*479ab7f0SSascha Wildner #include "dloader.h"
39*479ab7f0SSascha Wildner
40*479ab7f0SSascha Wildner static void menu_display(void);
41*479ab7f0SSascha Wildner static int menu_execute(int);
42*479ab7f0SSascha Wildner
43*479ab7f0SSascha Wildner /*
44*479ab7f0SSascha Wildner * This is called from common and must reference files to bring
45*479ab7f0SSascha Wildner * library modules into common during linking.
46*479ab7f0SSascha Wildner */
47*479ab7f0SSascha Wildner void
dloader_init_cmds(void)48*479ab7f0SSascha Wildner dloader_init_cmds(void)
49*479ab7f0SSascha Wildner {
50*479ab7f0SSascha Wildner }
51*479ab7f0SSascha Wildner
52*479ab7f0SSascha Wildner /*
53*479ab7f0SSascha Wildner * "local" intercepts assignments: lines of the form 'a=b'
54*479ab7f0SSascha Wildner */
55*479ab7f0SSascha Wildner COMMAND_SET(local, "local", "List local variables", command_local);
56*479ab7f0SSascha Wildner COMMAND_SET(lunset, "lunset", "Unset local variable", command_lunset);
57*479ab7f0SSascha Wildner COMMAND_SET(lunsetif, "lunsetif", "Unset local variable if kenv variable is true", command_lunsetif);
58*479ab7f0SSascha Wildner COMMAND_SET(loadall, "loadall", "Load kernel + modules", command_loadall);
59*479ab7f0SSascha Wildner COMMAND_SET(menuclear, "menuclear", "Clear all menus", command_menuclear);
60*479ab7f0SSascha Wildner COMMAND_SET(menuitem, "menuitem", "Add menu bullet", command_menuitem);
61*479ab7f0SSascha Wildner COMMAND_SET(menuadd, "menuadd", "Add script line for bullet", command_menuadd);
62*479ab7f0SSascha Wildner COMMAND_SET(menu, "menu", "Run menu system", command_menu);
63*479ab7f0SSascha Wildner
64*479ab7f0SSascha Wildner static int curitem;
65*479ab7f0SSascha Wildner static int curadd;
66*479ab7f0SSascha Wildner
67*479ab7f0SSascha Wildner static char *kenv_vars[] = {
68*479ab7f0SSascha Wildner "LINES",
69*479ab7f0SSascha Wildner "acpi_load",
70*479ab7f0SSascha Wildner "autoboot_delay",
71*479ab7f0SSascha Wildner "boot_askname",
72*479ab7f0SSascha Wildner "boot_cdrom",
73*479ab7f0SSascha Wildner "boot_ddb",
74*479ab7f0SSascha Wildner "boot_gdb",
75*479ab7f0SSascha Wildner "boot_serial",
76*479ab7f0SSascha Wildner "boot_single",
77*479ab7f0SSascha Wildner "boot_verbose",
78*479ab7f0SSascha Wildner "boot_vidcons",
79*479ab7f0SSascha Wildner "bootfile",
80*479ab7f0SSascha Wildner "console",
81*479ab7f0SSascha Wildner "currdev",
82*479ab7f0SSascha Wildner "default_kernel",
83*479ab7f0SSascha Wildner "dumpdev",
84*479ab7f0SSascha Wildner "ehci_load",
85*479ab7f0SSascha Wildner "interpret",
86*479ab7f0SSascha Wildner "init_chroot",
87*479ab7f0SSascha Wildner "init_path",
88*479ab7f0SSascha Wildner "kernel_options",
89*479ab7f0SSascha Wildner "kernelname",
90*479ab7f0SSascha Wildner "loaddev",
91*479ab7f0SSascha Wildner "local_modules",
92*479ab7f0SSascha Wildner "module_path",
93*479ab7f0SSascha Wildner "num_ide_disks",
94*479ab7f0SSascha Wildner "prompt",
95*479ab7f0SSascha Wildner "rootdev",
96*479ab7f0SSascha Wildner "root_disk_unit",
97*479ab7f0SSascha Wildner "xhci_load",
98*479ab7f0SSascha Wildner NULL
99*479ab7f0SSascha Wildner };
100*479ab7f0SSascha Wildner
101*479ab7f0SSascha Wildner /*
102*479ab7f0SSascha Wildner * List or set local variable. Sniff assignment of kenv_vars[] and
103*479ab7f0SSascha Wildner * loader tunables (recognized by '.' in name).
104*479ab7f0SSascha Wildner *
105*479ab7f0SSascha Wildner * format for av[0]:
106*479ab7f0SSascha Wildner * - List: local
107*479ab7f0SSascha Wildner * - Set: var=val
108*479ab7f0SSascha Wildner */
109*479ab7f0SSascha Wildner static int
command_local(int ac,char ** av)110*479ab7f0SSascha Wildner command_local(int ac, char **av)
111*479ab7f0SSascha Wildner {
112*479ab7f0SSascha Wildner char *name;
113*479ab7f0SSascha Wildner char *data;
114*479ab7f0SSascha Wildner dvar_t dvar;
115*479ab7f0SSascha Wildner int i;
116*479ab7f0SSascha Wildner int j;
117*479ab7f0SSascha Wildner
118*479ab7f0SSascha Wildner /*
119*479ab7f0SSascha Wildner * local command executed directly.
120*479ab7f0SSascha Wildner */
121*479ab7f0SSascha Wildner if (strcmp(av[0], "local") == 0) {
122*479ab7f0SSascha Wildner pager_open();
123*479ab7f0SSascha Wildner for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
124*479ab7f0SSascha Wildner for (j = 1; j < ac; ++j) {
125*479ab7f0SSascha Wildner if (!strncmp(dvar->name, av[j], strlen(av[j])))
126*479ab7f0SSascha Wildner break;
127*479ab7f0SSascha Wildner }
128*479ab7f0SSascha Wildner if (ac > 1 && j == ac)
129*479ab7f0SSascha Wildner continue;
130*479ab7f0SSascha Wildner
131*479ab7f0SSascha Wildner pager_output(dvar->name);
132*479ab7f0SSascha Wildner pager_output("=");
133*479ab7f0SSascha Wildner for (i = 0; i < dvar->count; ++i) {
134*479ab7f0SSascha Wildner if (i)
135*479ab7f0SSascha Wildner pager_output(",");
136*479ab7f0SSascha Wildner pager_output("\"");
137*479ab7f0SSascha Wildner pager_output(dvar->data[i]);
138*479ab7f0SSascha Wildner pager_output("\"");
139*479ab7f0SSascha Wildner }
140*479ab7f0SSascha Wildner pager_output("\n");
141*479ab7f0SSascha Wildner }
142*479ab7f0SSascha Wildner pager_close();
143*479ab7f0SSascha Wildner return(CMD_OK);
144*479ab7f0SSascha Wildner }
145*479ab7f0SSascha Wildner
146*479ab7f0SSascha Wildner /*
147*479ab7f0SSascha Wildner * local command intercept for 'var=val'
148*479ab7f0SSascha Wildner */
149*479ab7f0SSascha Wildner name = av[0];
150*479ab7f0SSascha Wildner data = strchr(name, '=');
151*479ab7f0SSascha Wildner if (data == NULL) {
152*479ab7f0SSascha Wildner sprintf(command_errbuf, "Bad variable syntax");
153*479ab7f0SSascha Wildner return (CMD_ERROR);
154*479ab7f0SSascha Wildner }
155*479ab7f0SSascha Wildner *data++ = 0;
156*479ab7f0SSascha Wildner
157*479ab7f0SSascha Wildner if (*data)
158*479ab7f0SSascha Wildner dvar_set(name, &data, 1);
159*479ab7f0SSascha Wildner else
160*479ab7f0SSascha Wildner dvar_unset(name);
161*479ab7f0SSascha Wildner
162*479ab7f0SSascha Wildner /*
163*479ab7f0SSascha Wildner * Take care of loader tunables and several other variables,
164*479ab7f0SSascha Wildner * all of which have to mirror to kenv because libstand or
165*479ab7f0SSascha Wildner * other consumers may have hooks into them.
166*479ab7f0SSascha Wildner */
167*479ab7f0SSascha Wildner if (strchr(name, '.')) {
168*479ab7f0SSascha Wildner setenv(name, data, 1);
169*479ab7f0SSascha Wildner } else {
170*479ab7f0SSascha Wildner for (i = 0; kenv_vars[i] != NULL; i++) {
171*479ab7f0SSascha Wildner if (strcmp(name, kenv_vars[i]) == 0) {
172*479ab7f0SSascha Wildner setenv(name, data, 1);
173*479ab7f0SSascha Wildner return(CMD_OK);
174*479ab7f0SSascha Wildner }
175*479ab7f0SSascha Wildner }
176*479ab7f0SSascha Wildner }
177*479ab7f0SSascha Wildner return(CMD_OK);
178*479ab7f0SSascha Wildner }
179*479ab7f0SSascha Wildner
180*479ab7f0SSascha Wildner /*
181*479ab7f0SSascha Wildner * Unset local variables
182*479ab7f0SSascha Wildner */
183*479ab7f0SSascha Wildner static int
command_lunset(int ac,char ** av)184*479ab7f0SSascha Wildner command_lunset(int ac, char **av)
185*479ab7f0SSascha Wildner {
186*479ab7f0SSascha Wildner int i;
187*479ab7f0SSascha Wildner
188*479ab7f0SSascha Wildner for (i = 1; i < ac; ++i)
189*479ab7f0SSascha Wildner dvar_unset(av[i]);
190*479ab7f0SSascha Wildner return(0);
191*479ab7f0SSascha Wildner }
192*479ab7f0SSascha Wildner
193*479ab7f0SSascha Wildner static int
command_lunsetif(int ac,char ** av)194*479ab7f0SSascha Wildner command_lunsetif(int ac, char **av)
195*479ab7f0SSascha Wildner {
196*479ab7f0SSascha Wildner char *envdata;
197*479ab7f0SSascha Wildner
198*479ab7f0SSascha Wildner if (ac != 3) {
199*479ab7f0SSascha Wildner sprintf(command_errbuf,
200*479ab7f0SSascha Wildner "syntax error use lunsetif lname envname");
201*479ab7f0SSascha Wildner return(CMD_ERROR);
202*479ab7f0SSascha Wildner }
203*479ab7f0SSascha Wildner envdata = getenv(av[2]);
204*479ab7f0SSascha Wildner if (strcmp(envdata, "yes") == 0 ||
205*479ab7f0SSascha Wildner strcmp(envdata, "YES") == 0 ||
206*479ab7f0SSascha Wildner strtol(envdata, NULL, 0)) {
207*479ab7f0SSascha Wildner dvar_unset(av[1]);
208*479ab7f0SSascha Wildner }
209*479ab7f0SSascha Wildner return (CMD_OK);
210*479ab7f0SSascha Wildner }
211*479ab7f0SSascha Wildner
212*479ab7f0SSascha Wildner /*
213*479ab7f0SSascha Wildner * Load the kernel + all modules specified with MODULE_load="YES"
214*479ab7f0SSascha Wildner */
215*479ab7f0SSascha Wildner static int
command_loadall(int ac,char ** av)216*479ab7f0SSascha Wildner command_loadall(int ac, char **av)
217*479ab7f0SSascha Wildner {
218*479ab7f0SSascha Wildner char *argv[4];
219*479ab7f0SSascha Wildner char *mod_name;
220*479ab7f0SSascha Wildner char *mod_fname;
221*479ab7f0SSascha Wildner char *mod_type;
222*479ab7f0SSascha Wildner char *tmp_str;
223*479ab7f0SSascha Wildner dvar_t dvar, dvar2;
224*479ab7f0SSascha Wildner int len;
225*479ab7f0SSascha Wildner int argc;
226*479ab7f0SSascha Wildner int res;
227*479ab7f0SSascha Wildner int tmp;
228*479ab7f0SSascha Wildner
229*479ab7f0SSascha Wildner argv[0] = "unload";
230*479ab7f0SSascha Wildner (void)perform(1, argv);
231*479ab7f0SSascha Wildner
232*479ab7f0SSascha Wildner /*
233*479ab7f0SSascha Wildner * Load kernel
234*479ab7f0SSascha Wildner */
235*479ab7f0SSascha Wildner argv[0] = "load";
236*479ab7f0SSascha Wildner argv[1] = getenv("kernelname");
237*479ab7f0SSascha Wildner argv[2] = getenv("kernel_options");
238*479ab7f0SSascha Wildner if (argv[1] == NULL)
239*479ab7f0SSascha Wildner argv[1] = strdup("kernel");
240*479ab7f0SSascha Wildner res = perform((argv[2] == NULL)?2:3, argv);
241*479ab7f0SSascha Wildner free(argv[1]);
242*479ab7f0SSascha Wildner if (argv[2])
243*479ab7f0SSascha Wildner free(argv[2]);
244*479ab7f0SSascha Wildner
245*479ab7f0SSascha Wildner if (res != CMD_OK) {
246*479ab7f0SSascha Wildner printf("Unable to load %s%s\n", DirBase, argv[1]);
247*479ab7f0SSascha Wildner return(res);
248*479ab7f0SSascha Wildner }
249*479ab7f0SSascha Wildner
250*479ab7f0SSascha Wildner /*
251*479ab7f0SSascha Wildner * Load modules
252*479ab7f0SSascha Wildner */
253*479ab7f0SSascha Wildner for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
254*479ab7f0SSascha Wildner len = strlen(dvar->name);
255*479ab7f0SSascha Wildner if (len <= 5 || strcmp(dvar->name + len - 5, "_load"))
256*479ab7f0SSascha Wildner continue;
257*479ab7f0SSascha Wildner if (strcmp(dvar->data[0], "yes") != 0 &&
258*479ab7f0SSascha Wildner strcmp(dvar->data[0], "YES") != 0) {
259*479ab7f0SSascha Wildner continue;
260*479ab7f0SSascha Wildner }
261*479ab7f0SSascha Wildner
262*479ab7f0SSascha Wildner mod_name = strdup(dvar->name);
263*479ab7f0SSascha Wildner mod_name[len - 5] = 0;
264*479ab7f0SSascha Wildner mod_type = NULL;
265*479ab7f0SSascha Wildner mod_fname = NULL;
266*479ab7f0SSascha Wildner
267*479ab7f0SSascha Wildner /* Check if there's a matching foo_type */
268*479ab7f0SSascha Wildner for (dvar2 = dvar_first();
269*479ab7f0SSascha Wildner dvar2 && (mod_type == NULL);
270*479ab7f0SSascha Wildner dvar2 = dvar_next(dvar2)) {
271*479ab7f0SSascha Wildner len = strlen(dvar2->name);
272*479ab7f0SSascha Wildner if (len <= 5 || strcmp(dvar2->name + len - 5, "_type"))
273*479ab7f0SSascha Wildner continue;
274*479ab7f0SSascha Wildner tmp_str = strdup(dvar2->name);
275*479ab7f0SSascha Wildner tmp_str[len - 5] = 0;
276*479ab7f0SSascha Wildner if (strcmp(tmp_str, mod_name) == 0)
277*479ab7f0SSascha Wildner mod_type = dvar2->data[0];
278*479ab7f0SSascha Wildner
279*479ab7f0SSascha Wildner free(tmp_str);
280*479ab7f0SSascha Wildner }
281*479ab7f0SSascha Wildner
282*479ab7f0SSascha Wildner /* Check if there's a matching foo_name */
283*479ab7f0SSascha Wildner for (dvar2 = dvar_first();
284*479ab7f0SSascha Wildner dvar2 && (mod_fname == NULL);
285*479ab7f0SSascha Wildner dvar2 = dvar_next(dvar2)) {
286*479ab7f0SSascha Wildner len = strlen(dvar2->name);
287*479ab7f0SSascha Wildner if (len <= 5 || strcmp(dvar2->name + len - 5, "_name"))
288*479ab7f0SSascha Wildner continue;
289*479ab7f0SSascha Wildner tmp_str = strdup(dvar2->name);
290*479ab7f0SSascha Wildner tmp_str[len - 5] = 0;
291*479ab7f0SSascha Wildner if (strcmp(tmp_str, mod_name) == 0) {
292*479ab7f0SSascha Wildner mod_fname = dvar2->data[0];
293*479ab7f0SSascha Wildner free(mod_name);
294*479ab7f0SSascha Wildner mod_name = strdup(mod_fname);
295*479ab7f0SSascha Wildner }
296*479ab7f0SSascha Wildner
297*479ab7f0SSascha Wildner free(tmp_str);
298*479ab7f0SSascha Wildner }
299*479ab7f0SSascha Wildner
300*479ab7f0SSascha Wildner argv[0] = "load";
301*479ab7f0SSascha Wildner if (mod_type) {
302*479ab7f0SSascha Wildner argc = 4;
303*479ab7f0SSascha Wildner argv[1] = "-t";
304*479ab7f0SSascha Wildner argv[2] = mod_type;
305*479ab7f0SSascha Wildner argv[3] = mod_name;
306*479ab7f0SSascha Wildner } else {
307*479ab7f0SSascha Wildner argc = 2;
308*479ab7f0SSascha Wildner argv[1] = mod_name;
309*479ab7f0SSascha Wildner }
310*479ab7f0SSascha Wildner tmp = perform(argc, argv);
311*479ab7f0SSascha Wildner if (tmp != CMD_OK) {
312*479ab7f0SSascha Wildner time_t t = time(NULL);
313*479ab7f0SSascha Wildner printf("Unable to load %s%s\n", DirBase, mod_name);
314*479ab7f0SSascha Wildner while (time(NULL) == t)
315*479ab7f0SSascha Wildner ;
316*479ab7f0SSascha Wildner /* don't kill the boot sequence */
317*479ab7f0SSascha Wildner /* res = tmp; */
318*479ab7f0SSascha Wildner }
319*479ab7f0SSascha Wildner free(mod_name);
320*479ab7f0SSascha Wildner }
321*479ab7f0SSascha Wildner return(res);
322*479ab7f0SSascha Wildner }
323*479ab7f0SSascha Wildner
324*479ab7f0SSascha Wildner /*
325*479ab7f0SSascha Wildner * Clear all menus
326*479ab7f0SSascha Wildner */
327*479ab7f0SSascha Wildner static int
command_menuclear(int ac,char ** av)328*479ab7f0SSascha Wildner command_menuclear(int ac, char **av)
329*479ab7f0SSascha Wildner {
330*479ab7f0SSascha Wildner dvar_unset("menu_*");
331*479ab7f0SSascha Wildner dvar_unset("item_*");
332*479ab7f0SSascha Wildner curitem = 0;
333*479ab7f0SSascha Wildner curadd = 0;
334*479ab7f0SSascha Wildner return(0);
335*479ab7f0SSascha Wildner }
336*479ab7f0SSascha Wildner
337*479ab7f0SSascha Wildner /*
338*479ab7f0SSascha Wildner * Add menu bullet
339*479ab7f0SSascha Wildner */
340*479ab7f0SSascha Wildner static int
command_menuitem(int ac,char ** av)341*479ab7f0SSascha Wildner command_menuitem(int ac, char **av)
342*479ab7f0SSascha Wildner {
343*479ab7f0SSascha Wildner char namebuf[32];
344*479ab7f0SSascha Wildner
345*479ab7f0SSascha Wildner if (ac != 3) {
346*479ab7f0SSascha Wildner sprintf(command_errbuf, "Bad menuitem syntax");
347*479ab7f0SSascha Wildner return (CMD_ERROR);
348*479ab7f0SSascha Wildner }
349*479ab7f0SSascha Wildner curitem = (unsigned char)av[1][0];
350*479ab7f0SSascha Wildner if (curitem == 0) {
351*479ab7f0SSascha Wildner sprintf(command_errbuf, "Bad menuitem syntax");
352*479ab7f0SSascha Wildner return (CMD_ERROR);
353*479ab7f0SSascha Wildner }
354*479ab7f0SSascha Wildner snprintf(namebuf, sizeof(namebuf), "menu_%c", curitem);
355*479ab7f0SSascha Wildner dvar_set(namebuf, &av[2], 1);
356*479ab7f0SSascha Wildner curadd = 0;
357*479ab7f0SSascha Wildner
358*479ab7f0SSascha Wildner return(CMD_OK);
359*479ab7f0SSascha Wildner }
360*479ab7f0SSascha Wildner
361*479ab7f0SSascha Wildner /*
362*479ab7f0SSascha Wildner * Add execution item
363*479ab7f0SSascha Wildner */
364*479ab7f0SSascha Wildner static int
command_menuadd(int ac,char ** av)365*479ab7f0SSascha Wildner command_menuadd(int ac, char **av)
366*479ab7f0SSascha Wildner {
367*479ab7f0SSascha Wildner char namebuf[32];
368*479ab7f0SSascha Wildner
369*479ab7f0SSascha Wildner if (ac == 1)
370*479ab7f0SSascha Wildner return(CMD_OK);
371*479ab7f0SSascha Wildner if (curitem == 0) {
372*479ab7f0SSascha Wildner sprintf(command_errbuf, "Missing menuitem for menuadd");
373*479ab7f0SSascha Wildner return(CMD_ERROR);
374*479ab7f0SSascha Wildner }
375*479ab7f0SSascha Wildner snprintf(namebuf, sizeof(namebuf), "item_%c_%d", curitem, curadd);
376*479ab7f0SSascha Wildner dvar_set(namebuf, &av[1], ac - 1);
377*479ab7f0SSascha Wildner ++curadd;
378*479ab7f0SSascha Wildner return (CMD_OK);
379*479ab7f0SSascha Wildner }
380*479ab7f0SSascha Wildner
381*479ab7f0SSascha Wildner /*
382*479ab7f0SSascha Wildner * Execute menu system
383*479ab7f0SSascha Wildner */
384*479ab7f0SSascha Wildner static int
command_menu(int ac,char ** av)385*479ab7f0SSascha Wildner command_menu(int ac, char **av)
386*479ab7f0SSascha Wildner {
387*479ab7f0SSascha Wildner int timeout = -1;
388*479ab7f0SSascha Wildner time_t time_target;
389*479ab7f0SSascha Wildner time_t time_last;
390*479ab7f0SSascha Wildner time_t t;
391*479ab7f0SSascha Wildner char *cp;
392*479ab7f0SSascha Wildner int c;
393*479ab7f0SSascha Wildner int res;
394*479ab7f0SSascha Wildner int counting = 1;
395*479ab7f0SSascha Wildner
396*479ab7f0SSascha Wildner menu_display();
397*479ab7f0SSascha Wildner if ((cp = getenv("autoboot_delay")) != NULL)
398*479ab7f0SSascha Wildner timeout = strtol(cp, NULL, 0);
399*479ab7f0SSascha Wildner if (timeout <= 0)
400*479ab7f0SSascha Wildner timeout = 10;
401*479ab7f0SSascha Wildner if (timeout > 24 * 60 * 60)
402*479ab7f0SSascha Wildner timeout = 24 * 60 * 60;
403*479ab7f0SSascha Wildner
404*479ab7f0SSascha Wildner time_target = time(NULL) + timeout;
405*479ab7f0SSascha Wildner time_last = 0;
406*479ab7f0SSascha Wildner c = '1';
407*479ab7f0SSascha Wildner for (;;) {
408*479ab7f0SSascha Wildner if (ischar()) {
409*479ab7f0SSascha Wildner c = getchar();
410*479ab7f0SSascha Wildner if (c == '\r' || c == '\n') {
411*479ab7f0SSascha Wildner c = '1';
412*479ab7f0SSascha Wildner break;
413*479ab7f0SSascha Wildner }
414*479ab7f0SSascha Wildner if (c == ' ') {
415*479ab7f0SSascha Wildner if (counting) {
416*479ab7f0SSascha Wildner printf("\rCountdown halted by "
417*479ab7f0SSascha Wildner "space ");
418*479ab7f0SSascha Wildner }
419*479ab7f0SSascha Wildner counting = 0;
420*479ab7f0SSascha Wildner continue;
421*479ab7f0SSascha Wildner }
422*479ab7f0SSascha Wildner if (c == 0x1b) {
423*479ab7f0SSascha Wildner setenv("autoboot_delay", "NO", 1);
424*479ab7f0SSascha Wildner return(CMD_OK);
425*479ab7f0SSascha Wildner }
426*479ab7f0SSascha Wildner res = menu_execute(c);
427*479ab7f0SSascha Wildner if (res >= 0) {
428*479ab7f0SSascha Wildner setenv("autoboot_delay", "NO", 1);
429*479ab7f0SSascha Wildner return(CMD_OK);
430*479ab7f0SSascha Wildner }
431*479ab7f0SSascha Wildner /* else ignore char */
432*479ab7f0SSascha Wildner }
433*479ab7f0SSascha Wildner if (counting) {
434*479ab7f0SSascha Wildner t = time(NULL);
435*479ab7f0SSascha Wildner if (time_last == t)
436*479ab7f0SSascha Wildner continue;
437*479ab7f0SSascha Wildner time_last = t;
438*479ab7f0SSascha Wildner printf("\rBooting in %d second%s... ",
439*479ab7f0SSascha Wildner (int)(time_target - t),
440*479ab7f0SSascha Wildner ((time_target - t) == 1 ? "" : "s"));
441*479ab7f0SSascha Wildner if ((int)(time_target - t) <= 0) {
442*479ab7f0SSascha Wildner c = '1';
443*479ab7f0SSascha Wildner break;
444*479ab7f0SSascha Wildner }
445*479ab7f0SSascha Wildner }
446*479ab7f0SSascha Wildner }
447*479ab7f0SSascha Wildner res = menu_execute(c);
448*479ab7f0SSascha Wildner if (res != CMD_OK)
449*479ab7f0SSascha Wildner setenv("autoboot_delay", "NO", 1);
450*479ab7f0SSascha Wildner return (res);
451*479ab7f0SSascha Wildner }
452*479ab7f0SSascha Wildner
453*479ab7f0SSascha Wildner #define LOGO_LINES 16
454*479ab7f0SSascha Wildner #define FRED_LEFT 0
455*479ab7f0SSascha Wildner #define FRED_RIGHT 1
456*479ab7f0SSascha Wildner static char *logo_blank_line = " ";
457*479ab7f0SSascha Wildner
458*479ab7f0SSascha Wildner static char *logo_color[LOGO_LINES] = {
459*479ab7f0SSascha Wildner "[31;1m ,--, ,--, [0m",
460*479ab7f0SSascha Wildner "[31;1m | `-, [33;1m_[31m:[33;1m_[31;1m ,-' | [0m",
461*479ab7f0SSascha Wildner "[31;1m `, `-, [33;1m([31m/ \\[33;1m)[31;1m ,-' ,' [0m",
462*479ab7f0SSascha Wildner "[31;1m `-, `-,[31m/ \\[31;1m,-' ,-' [0m",
463*479ab7f0SSascha Wildner "[31;1m `------[31m{ }[31;1m------' [0m",
464*479ab7f0SSascha Wildner "[31;1m ,----------[31m{ }[31;1m----------, [0m",
465*479ab7f0SSascha Wildner "[31;1m | _,-[31m{ }[31;1m-,_ | [0m",
466*479ab7f0SSascha Wildner "[31;1m `-,__,-' [31m\\ /[31;1m `-,__,-' [0m",
467*479ab7f0SSascha Wildner "[31m | | [0m",
468*479ab7f0SSascha Wildner "[31m | | [0m",
469*479ab7f0SSascha Wildner "[31m | | [0m",
470*479ab7f0SSascha Wildner "[31m | | [0m",
471*479ab7f0SSascha Wildner "[31m | | [0m",
472*479ab7f0SSascha Wildner "[31m | | [0m",
473*479ab7f0SSascha Wildner "[31m `,' [0m",
474*479ab7f0SSascha Wildner " " };
475*479ab7f0SSascha Wildner
476*479ab7f0SSascha Wildner static char *logo_indigo[LOGO_LINES] = {
477*479ab7f0SSascha Wildner "[36m ,--, ,--[36;1m, [0m",
478*479ab7f0SSascha Wildner "[36m | `-, [34;1m_[34m:[34;1m_[36m ,-' [36;1m| [0m",
479*479ab7f0SSascha Wildner "[36m `, `-, [34;1m([34m/ \\[34;1m)[36m ,-' [36;1m,' [0m",
480*479ab7f0SSascha Wildner "[36m `-, `-,[34m/ \\[36m,-' [36;1m,-' [0m",
481*479ab7f0SSascha Wildner "[36m `------[34m{ }[36m------[36;1m' [0m",
482*479ab7f0SSascha Wildner "[36m ,----------[34m{ }[36m----------[36;1m, [0m",
483*479ab7f0SSascha Wildner "[36m | [36;1m_,-[34m{ }[36m-,_ [36;1m| [0m",
484*479ab7f0SSascha Wildner "[36m `-,__[36;1m,-' [34m\\ /[36m `-,__[36;1m,-' [0m",
485*479ab7f0SSascha Wildner "[34m | | [0m",
486*479ab7f0SSascha Wildner "[34m | | [0m",
487*479ab7f0SSascha Wildner "[34m | | [0m",
488*479ab7f0SSascha Wildner "[34m | | [0m",
489*479ab7f0SSascha Wildner "[34m | | [0m",
490*479ab7f0SSascha Wildner "[34m | | [0m",
491*479ab7f0SSascha Wildner "[34m `,' [0m",
492*479ab7f0SSascha Wildner " " };
493*479ab7f0SSascha Wildner
494*479ab7f0SSascha Wildner static char *logo_mono[LOGO_LINES] = {
495*479ab7f0SSascha Wildner " ,--, ,--, ",
496*479ab7f0SSascha Wildner " | `-, _:_ ,-' | ",
497*479ab7f0SSascha Wildner " `, `-, (/ \\) ,-' ,' ",
498*479ab7f0SSascha Wildner " `-, `-,/ \\,-' ,-' ",
499*479ab7f0SSascha Wildner " `------{ }------' ",
500*479ab7f0SSascha Wildner " ,----------{ }----------, ",
501*479ab7f0SSascha Wildner " | _,-{ }-,_ | ",
502*479ab7f0SSascha Wildner " `-,__,-' \\ / `-,__,-' ",
503*479ab7f0SSascha Wildner " | | ",
504*479ab7f0SSascha Wildner " | | ",
505*479ab7f0SSascha Wildner " | | ",
506*479ab7f0SSascha Wildner " | | ",
507*479ab7f0SSascha Wildner " | | ",
508*479ab7f0SSascha Wildner " | | ",
509*479ab7f0SSascha Wildner " `,' ",
510*479ab7f0SSascha Wildner " " };
511*479ab7f0SSascha Wildner
512*479ab7f0SSascha Wildner static void
logo_display(char ** logo,int line,int orientation,int barrier)513*479ab7f0SSascha Wildner logo_display(char **logo, int line, int orientation, int barrier)
514*479ab7f0SSascha Wildner {
515*479ab7f0SSascha Wildner const char *fmt;
516*479ab7f0SSascha Wildner
517*479ab7f0SSascha Wildner if (orientation == FRED_LEFT)
518*479ab7f0SSascha Wildner fmt = barrier ? "%s | " : " %s ";
519*479ab7f0SSascha Wildner else
520*479ab7f0SSascha Wildner fmt = barrier ? " | %s" : " %s ";
521*479ab7f0SSascha Wildner
522*479ab7f0SSascha Wildner if (logo != NULL) {
523*479ab7f0SSascha Wildner if (line < LOGO_LINES)
524*479ab7f0SSascha Wildner printf(fmt, logo[line]);
525*479ab7f0SSascha Wildner else
526*479ab7f0SSascha Wildner printf(fmt, logo_blank_line);
527*479ab7f0SSascha Wildner }
528*479ab7f0SSascha Wildner }
529*479ab7f0SSascha Wildner
530*479ab7f0SSascha Wildner static void
menu_display(void)531*479ab7f0SSascha Wildner menu_display(void)
532*479ab7f0SSascha Wildner {
533*479ab7f0SSascha Wildner dvar_t dvar;
534*479ab7f0SSascha Wildner int i;
535*479ab7f0SSascha Wildner int logo_left = 0; /* default to fred on right */
536*479ab7f0SSascha Wildner int separated = 0; /* default blue fred without line */
537*479ab7f0SSascha Wildner char **logo = logo_indigo;
538*479ab7f0SSascha Wildner char *console_val = getenv("console");
539*479ab7f0SSascha Wildner
540*479ab7f0SSascha Wildner if (dvar_istrue(dvar_get("fred_is_red")))
541*479ab7f0SSascha Wildner logo = logo_color;
542*479ab7f0SSascha Wildner
543*479ab7f0SSascha Wildner if (dvar_istrue(dvar_get("loader_plain")))
544*479ab7f0SSascha Wildner logo = logo_mono;
545*479ab7f0SSascha Wildner
546*479ab7f0SSascha Wildner if (strcmp(console_val, "comconsole") == 0)
547*479ab7f0SSascha Wildner logo = logo_mono;
548*479ab7f0SSascha Wildner
549*479ab7f0SSascha Wildner if (dvar_istrue(dvar_get("fred_disable")))
550*479ab7f0SSascha Wildner logo = NULL;
551*479ab7f0SSascha Wildner
552*479ab7f0SSascha Wildner if (dvar_istrue(dvar_get("fred_on_left")))
553*479ab7f0SSascha Wildner logo_left = 1;
554*479ab7f0SSascha Wildner
555*479ab7f0SSascha Wildner if (dvar_istrue(dvar_get("fred_separated")))
556*479ab7f0SSascha Wildner separated = 1;
557*479ab7f0SSascha Wildner
558*479ab7f0SSascha Wildner dvar = dvar_first();
559*479ab7f0SSascha Wildner i = 0;
560*479ab7f0SSascha Wildner
561*479ab7f0SSascha Wildner if (logo != NULL) {
562*479ab7f0SSascha Wildner if (logo_left)
563*479ab7f0SSascha Wildner printf(separated ? "%35s|%43s\n" : "%35s %43s\n",
564*479ab7f0SSascha Wildner " ", " ");
565*479ab7f0SSascha Wildner else
566*479ab7f0SSascha Wildner printf(separated ? "%43s|%35s\n" : "%43s %35s\n",
567*479ab7f0SSascha Wildner " ", " ");
568*479ab7f0SSascha Wildner }
569*479ab7f0SSascha Wildner
570*479ab7f0SSascha Wildner while (dvar || i < LOGO_LINES) {
571*479ab7f0SSascha Wildner if (logo_left)
572*479ab7f0SSascha Wildner logo_display(logo, i, FRED_LEFT, separated);
573*479ab7f0SSascha Wildner
574*479ab7f0SSascha Wildner while (dvar) {
575*479ab7f0SSascha Wildner if (strncmp(dvar->name, "menu_", 5) == 0) {
576*479ab7f0SSascha Wildner printf(" %c. %-38.38s",
577*479ab7f0SSascha Wildner dvar->name[5], dvar->data[0]);
578*479ab7f0SSascha Wildner dvar = dvar_next(dvar);
579*479ab7f0SSascha Wildner break;
580*479ab7f0SSascha Wildner }
581*479ab7f0SSascha Wildner dvar = dvar_next(dvar);
582*479ab7f0SSascha Wildner }
583*479ab7f0SSascha Wildner /*
584*479ab7f0SSascha Wildner * Pad when the number of menu entries is less than
585*479ab7f0SSascha Wildner * LOGO_LINES.
586*479ab7f0SSascha Wildner */
587*479ab7f0SSascha Wildner if (dvar == NULL)
588*479ab7f0SSascha Wildner printf(" %38.38s", " ");
589*479ab7f0SSascha Wildner
590*479ab7f0SSascha Wildner if (!logo_left)
591*479ab7f0SSascha Wildner logo_display(logo, i, FRED_RIGHT, separated);
592*479ab7f0SSascha Wildner printf("\n");
593*479ab7f0SSascha Wildner i++;
594*479ab7f0SSascha Wildner }
595*479ab7f0SSascha Wildner }
596*479ab7f0SSascha Wildner
597*479ab7f0SSascha Wildner static int
menu_execute(int c)598*479ab7f0SSascha Wildner menu_execute(int c)
599*479ab7f0SSascha Wildner {
600*479ab7f0SSascha Wildner dvar_t dvar;
601*479ab7f0SSascha Wildner dvar_t dvar_exec = NULL;
602*479ab7f0SSascha Wildner dvar_t *dvar_execp = &dvar_exec;
603*479ab7f0SSascha Wildner char namebuf[32];
604*479ab7f0SSascha Wildner int res;
605*479ab7f0SSascha Wildner
606*479ab7f0SSascha Wildner snprintf(namebuf, sizeof(namebuf), "item_%c_0", c);
607*479ab7f0SSascha Wildner
608*479ab7f0SSascha Wildner /*
609*479ab7f0SSascha Wildner * Does this menu option exist?
610*479ab7f0SSascha Wildner */
611*479ab7f0SSascha Wildner if (dvar_get(namebuf) == NULL)
612*479ab7f0SSascha Wildner return(-1);
613*479ab7f0SSascha Wildner
614*479ab7f0SSascha Wildner snprintf(namebuf, sizeof(namebuf), "item_%c", c);
615*479ab7f0SSascha Wildner res = CMD_OK;
616*479ab7f0SSascha Wildner printf("\n");
617*479ab7f0SSascha Wildner
618*479ab7f0SSascha Wildner /*
619*479ab7f0SSascha Wildner * Copy the items to execute (the act of execution may modify our
620*479ab7f0SSascha Wildner * local variables so we need to copy).
621*479ab7f0SSascha Wildner */
622*479ab7f0SSascha Wildner for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
623*479ab7f0SSascha Wildner if (strncmp(dvar->name, namebuf, 6) == 0) {
624*479ab7f0SSascha Wildner *dvar_execp = dvar_copy(dvar);
625*479ab7f0SSascha Wildner dvar_execp = &(*dvar_execp)->next;
626*479ab7f0SSascha Wildner }
627*479ab7f0SSascha Wildner }
628*479ab7f0SSascha Wildner
629*479ab7f0SSascha Wildner /*
630*479ab7f0SSascha Wildner * Execute items
631*479ab7f0SSascha Wildner */
632*479ab7f0SSascha Wildner for (dvar = dvar_exec; dvar; dvar = dvar->next) {
633*479ab7f0SSascha Wildner res = perform(dvar->count, dvar->data);
634*479ab7f0SSascha Wildner if (res != CMD_OK) {
635*479ab7f0SSascha Wildner printf("%s: %s\n",
636*479ab7f0SSascha Wildner dvar->data[0], command_errmsg);
637*479ab7f0SSascha Wildner setenv("autoboot_delay", "NO", 1);
638*479ab7f0SSascha Wildner break;
639*479ab7f0SSascha Wildner }
640*479ab7f0SSascha Wildner }
641*479ab7f0SSascha Wildner
642*479ab7f0SSascha Wildner /*
643*479ab7f0SSascha Wildner * Free items
644*479ab7f0SSascha Wildner */
645*479ab7f0SSascha Wildner while (dvar_exec)
646*479ab7f0SSascha Wildner dvar_free(&dvar_exec);
647*479ab7f0SSascha Wildner
648*479ab7f0SSascha Wildner return(res);
649*479ab7f0SSascha Wildner }
650