Increase number of menu options to 20.

Add support for switching menu format between numbers and letters. Will
prefer numbers, but will automatically switch to letters if > 9 options
and timeout > 0 (i.e. need a single key press to choose).
Menu format can be explicitly set in boot.cfg file.
Add support for reading numeric choices of more than 1 digit.
This commit is contained in:
sborrill 2008-08-12 17:56:05 +00:00
parent 094d45b30f
commit c7b0526b9b

View File

@ -1,4 +1,4 @@
/* $NetBSD: boot2.c,v 1.33 2008/08/08 07:48:32 simonb Exp $ */
/* $NetBSD: boot2.c,v 1.34 2008/08/12 17:56:05 sborrill Exp $ */
/*-
* Copyright (c) 2008 The NetBSD Foundation, Inc.
@ -108,7 +108,7 @@ static const char * const names[][2] = {
#ifndef SMALL
#define BOOTCONF "boot.cfg"
#define MAXMENU 10
#define MAXMENU 20
#define MAXBANNER 12
#define COMMAND_SEPARATOR ';'
#endif /* !SMALL */
@ -151,6 +151,11 @@ const struct bootblk_command commands[] = {
};
#ifndef SMALL
#define MENUFORMAT_AUTO 0
#define MENUFORMAT_NUMBER 1
#define MENUFORMAT_LETTER 2
struct bootconf_def {
char *banner[MAXBANNER]; /* Banner text */
char *command[MAXMENU]; /* Menu commands per entry*/
@ -159,6 +164,7 @@ struct bootconf_def {
char *desc[MAXMENU]; /* Menu text per entry */
int nummenu; /* Number of menu items */
int timeout; /* Timeout in seconds */
int menuformat; /* Print letters instead of numbers? */
} bootconf;
#endif /* !SMALL */
@ -305,7 +311,7 @@ atoi(const char *in)
* (if present) and populates the global boot configuration.
*
* The file consists of a number of lines each terminated by \n
* The lines are in the format keyword=value. There should be spaces
* The lines are in the format keyword=value. There should not be spaces
* around the = sign.
*
* The recognised keywords are:
@ -314,6 +320,7 @@ atoi(const char *in)
* timeout: Timeout in seconds (overrides that set by installboot)
* default: the default menu option to use if Return is pressed
* consdev: the console device to use
* format: how menu choices are displayed: (a)utomatic, (n)umbers or (l)etters
*
* Example boot.cfg file:
* banner=Welcome to NetBSD
@ -344,6 +351,9 @@ parsebootconf(const char *conf)
/* Set timeout to configured */
bootconf.timeout = boot_params.bp_timeout;
/* automatically switch between letter and numbers on menu */
bootconf.menuformat = MENUFORMAT_AUTO;
/* don't try to open BOOTCONF if the target fs is ustarfs */
#ifdef SUPPORT_USTARFS
#if !defined(LIBSA_SINGLE_FILESYSTEM)
@ -442,10 +452,44 @@ parsebootconf(const char *conf)
bootconf.def = atoi(value) - 1;
} else if (!strncmp(key, "consdev", 7)) {
bootconf.consdev = value;
} else if (!strncmp(key, "load", 6)) {
} else if (!strncmp(key, "load", 4)) {
command_load(value);
} else if (!strncmp(key, "format", 6)) {
printf("value:%c\n", *value);
switch (*value) {
case 'a':
case 'A':
bootconf.menuformat = MENUFORMAT_AUTO;
break;
case 'n':
case 'N':
case 'd':
case 'D':
bootconf.menuformat = MENUFORMAT_NUMBER;
break;
case 'l':
case 'L':
bootconf.menuformat = MENUFORMAT_LETTER;
break;
}
}
}
switch (bootconf.menuformat) {
case MENUFORMAT_AUTO:
if (cmenu > 9 && bootconf.timeout > 0)
bootconf.menuformat = MENUFORMAT_LETTER;
else
bootconf.menuformat = MENUFORMAT_NUMBER;
break;
case MENUFORMAT_NUMBER:
if (cmenu > 9 && bootconf.timeout > 0)
cmenu = 9;
break;
}
bootconf.nummenu = cmenu;
if (bootconf.def < 0)
bootconf.def = 0;
@ -457,46 +501,74 @@ parsebootconf(const char *conf)
* doboottypemenu will render the menu and parse any user input
*/
static int getchoicefrominput(char *input, int def)
{
int choice;
choice = -1;
if (*input == '\0' || *input == '\r' || *input == '\n')
choice = def;
else if (*input >= 'A' && *input < bootconf.nummenu + 'A')
choice = (*input) - 'A';
else if (*input >= 'a' && *input < bootconf.nummenu + 'a')
choice = (*input) - 'a';
else if (isnum(*input)) {
choice = atoi(input) - 1;
if (choice < 0 || choice >= bootconf.nummenu)
choice = -1;
}
return choice;
}
void
doboottypemenu(void)
{
int choice;
char input[80], c, *ic, *oc;
char input[80], *ic, *oc;
printf("\n");
/* Display menu */
for (choice = 0; choice < bootconf.nummenu; choice++)
printf(" %d. %s\n", choice+1, bootconf.desc[choice]);
if (bootconf.menuformat == MENUFORMAT_LETTER) {
for (choice = 0; choice < bootconf.nummenu; choice++)
printf(" %c. %s\n", choice + 'A',
bootconf.desc[choice]);
} else {
/* Can't use %2d format string with libsa */
for (choice = 0; choice < bootconf.nummenu; choice++)
printf(" %s%d. %s\n",
(choice < 9) ? " " : "",
choice + 1,
bootconf.desc[choice]);
}
choice = -1;
for(;;) {
input[0] = '\0';
if (bootconf.timeout < 0) {
printf("\nOption: [%d]:", bootconf.def + 1);
if (bootconf.menuformat == MENUFORMAT_LETTER)
printf("\nOption: [%c]:",
bootconf.def + 'A');
else
printf("\nOption: [%d]:",
bootconf.def + 1);
gets(input);
if (input[0] == '\0') choice = bootconf.def;
if (input[0] >= '1' &&
input[0] <= bootconf.nummenu + '0')
choice = input[0] - '1';
choice = getchoicefrominput(input, bootconf.def);
} else if (bootconf.timeout == 0)
choice = bootconf.def;
else {
printf("\nChoose an option; RETURN for default; "
"SPACE to stop countdown.\n");
printf("Option %d will be chosen in ",
bootconf.def + 1);
c = awaitkey(bootconf.timeout, 1);
if (c >= '1' && c <= bootconf.nummenu + '0')
choice = c - '1';
else if (c == '\r' || c == '\n' || c == '\0')
/* default if timed out or Return pressed */
choice = bootconf.def;
else {
/* If any other key pressed, drop to menu */
if (bootconf.menuformat == MENUFORMAT_LETTER)
printf("Option %d will be chosen in ",
bootconf.def + 1);
printf("Option %c will be chosen in ",
bootconf.def + 'A');
input[0] = awaitkey(bootconf.timeout, 1);
input[1] = '\0';
choice = getchoicefrominput(input, bootconf.def);
/* If invalid key pressed, drop to menu */
if (choice == -1)
bootconf.timeout = -1;
choice = -1;
}
}
if (choice < 0)
continue;