2 * Copyright (c) 2010 The DragonFly Project. All rights reserved.
4 * This code is derived from software contributed to The DragonFly Project
5 * by Matthew Dillon <dillon@backplane.com>
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions
11 * 1. Redistributions of source code must retain the above copyright
12 * notice, this list of conditions and the following disclaimer.
13 * 2. Redistributions in binary form must reproduce the above copyright
14 * notice, this list of conditions and the following disclaimer in
15 * the documentation and/or other materials provided with the
17 * 3. Neither the name of The DragonFly Project nor the names of its
18 * contributors may be used to endorse or promote products derived
19 * from this software without specific, prior written permission.
21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
37 #include "bootstrap.h"
40 static void menu_display(void);
41 static int menu_execute(int);
44 * This is called from common and must reference files to bring
45 * library modules into common during linking.
48 dloader_init_cmds(void)
53 * This intercepts lines of the form 'a=b'
55 COMMAND_SET(local, "local", "List local variables", command_local);
56 COMMAND_SET(lunset, "lunset", "Unset local variables", command_lunset);
57 COMMAND_SET(lunsetif, "lunsetif", "Unset local if envvar set to 1 or YES", command_lunsetif);
58 COMMAND_SET(loadall, "loadall", "Load kernel + modules", command_loadall);
59 COMMAND_SET(menuclear, "menuclear", "Clear all menus", command_menuclear);
60 COMMAND_SET(menuitem, "menuitem", "Add menu bullet", command_menuitem);
61 COMMAND_SET(menuadd, "menuadd", "Add script line for bullet", command_menuadd);
62 COMMAND_SET(menu, "menu", "Run menu system", command_menu);
67 static char *kenv_vars[] = {
88 * Set local variable. Sniff "module_path"
90 * format a=b (one argument) - in av[0]
93 command_local(int ac, char **av)
102 * local command executed directly.
104 if (strcmp(av[0], "local") == 0) {
105 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
106 for (j = 1; j < ac; ++j) {
107 if (!strncmp(dvar->name, av[j], strlen(av[j])))
110 if (ac > 1 && j == ac)
113 printf("%s=", dvar->name);
114 for (i = 0; i < dvar->count; ++i) {
117 printf("\"%s\"", dvar->data[i]);
125 * local command intercept for blah=blah
128 data = strchr(name, '=');
130 sprintf(command_errbuf, "Bad variable syntax");
136 dvar_set(name, &data, 1);
141 * Take care of loader tunables and several other variables,
142 * all of which have to mirror to kenv because libstand or
143 * other consumers may have hooks into them.
145 if (strchr(name, '.')) {
146 setenv(name, data, 1);
148 for (i = 0; kenv_vars[i] != NULL; i++) {
149 if (strcmp(name, kenv_vars[i]) == 0) {
150 setenv(name, data, 1);
159 * Unset local variables
162 command_lunset(int ac, char **av)
166 for (i = 1; i < ac; ++i)
172 command_lunsetif(int ac, char **av)
177 sprintf(command_errbuf,
178 "syntax error use lunsetif lname envname");
181 envdata = getenv(av[2]);
182 if (strcmp(envdata, "yes") == 0 ||
183 strcmp(envdata, "YES") == 0 ||
184 strtol(envdata, NULL, 0)) {
191 * Load the kernel + all modules specified with
194 command_loadall(int ac, char **av)
204 (void)perform(1, argv);
210 argv[1] = getenv("kernelname");
212 argv[1] = strdup("kernel");
213 res = perform(2, argv);
217 printf("Unable to load %s%s\n", DirBase, argv[1]);
224 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
225 len = strlen(dvar->name);
226 if (len <= 5 || strcmp(dvar->name + len - 5, "_load"))
228 if (strcmp(dvar->data[0], "yes") != 0 &&
229 strcmp(dvar->data[0], "YES") != 0) {
233 argv[1] = strdup(dvar->name);
234 argv[1][len - 5] = 0;
235 tmp = perform(2, argv);
238 time_t t = time(NULL);
239 printf("Unable to load %s%s\n", DirBase, argv[1]);
240 while (time(NULL) == t)
242 /* don't kill the boot sequence */
254 command_menuclear(int ac, char **av)
256 dvar_unset("menu_*");
257 dvar_unset("item_*");
267 command_menuitem(int ac, char **av)
273 sprintf(command_errbuf, "Bad menuitem syntax");
276 curitem = (unsigned char)av[1][0];
278 sprintf(command_errbuf, "Bad menuitem syntax");
281 snprintf(namebuf, sizeof(namebuf), "menu_%c", curitem);
282 dvar_set(namebuf, &av[2], 1);
292 command_menuadd(int ac, char **av)
300 sprintf(command_errbuf, "Missing menuitem for menuadd");
303 snprintf(namebuf, sizeof(namebuf), "item_%c_%d", curitem, curadd);
304 dvar_set(namebuf, &av[1], ac - 1);
310 * Execute menu system
313 command_menu(int ac, char **av)
325 if ((cp = getenv("autoboot_delay")) != NULL)
326 timeout = strtol(cp, NULL, 0);
329 if (timeout > 24 * 60 * 60)
330 timeout = 24 * 60 * 60;
332 time_target = time(NULL) + timeout;
338 if (c == '\r' || c == '\n') {
344 printf("\rCountdown halted by "
351 setenv("autoboot_delay", "NO", 1);
354 res = menu_execute(c);
356 setenv("autoboot_delay", "NO", 1);
359 /* else ignore char */
366 printf("\rBooting in %d second%s... ",
367 (int)(time_target - t),
368 ((time_target - t) == 1 ? "" : "s"));
369 if ((int)(time_target - t) <= 0) {
375 res = menu_execute(c);
377 setenv("autoboot_delay", "NO", 1);
386 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
387 if (strncmp(dvar->name, "menu_", 5) == 0) {
388 printf("%c. %s\n", dvar->name[5], dvar->data[0]);
403 snprintf(namebuf, sizeof(namebuf), "item_%c_0", c);
406 * Does this menu option exist?
408 if (dvar_get(namebuf) == NULL)
411 snprintf(namebuf, sizeof(namebuf), "item_%c", c);
413 for (dvar = dvar_first(); dvar; dvar = dvar_next(dvar)) {
414 if (strncmp(dvar->name, namebuf, 6) == 0) {
415 res = perform(dvar->count, dvar->data);
418 dvar->data[0], command_errmsg);
419 setenv("autoboot_delay", "NO", 1);