import less(1)
[unleashed/tickless.git] / usr / src / psm / stand / bootlst / common / bootlst.c
blob328329ab802fede1704c1d000d92f7d8e0ac1022
1 /*
2 * CDDL HEADER START
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
19 * CDDL HEADER END
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
25 #pragma ident "%Z%%M% %I% %E% SMI"
27 #include <sys/promif.h>
28 #include <sys/salib.h>
30 #define MAX_CMDLINE 1600 /* from GRUB source */
32 char **titles;
33 char **datasets;
35 int menu_entry_count;
36 int menu_table_size;
38 int in_menu_entry;
40 #define ENTRY_ALLOC_COUNT 10
42 extern void set_default_fs(char *fsw_name);
43 extern int mountroot(char *str);
45 void
46 init_table(void)
49 menu_entry_count = 0;
50 titles = (char **)calloc(ENTRY_ALLOC_COUNT, sizeof (char *));
51 datasets = (char **)calloc(ENTRY_ALLOC_COUNT, sizeof (char *));
52 if (titles == NULL || datasets == NULL)
53 prom_panic("out of mem");
54 menu_table_size = ENTRY_ALLOC_COUNT;
55 in_menu_entry = 0;
58 void
59 add_title_entry(char *title_str)
62 /* skip leading white space */
63 while (isspace(*title_str))
64 title_str++;
66 if (menu_entry_count == menu_table_size) {
67 printf("Reallocating at count %d\n", menu_table_size);
68 titles = (char **)reallocarray(titles, ENTRY_ALLOC_COUNT,
69 sizeof (char *));
70 datasets = reallocarray(datasets, ENTRY_ALLOC_COUNT,
71 sizeof(char *));
72 if (titles == NULL || datasets == NULL)
73 prom_panic("out of mem");
74 menu_table_size += ENTRY_ALLOC_COUNT;
77 if (in_menu_entry)
78 free(titles[menu_entry_count]);
79 if ((titles[menu_entry_count] = strdup(title_str)) == NULL)
80 prom_panic("out of mem");
81 in_menu_entry = 1;
84 void
85 add_dataset_entry(char *dataset_str)
87 char *cp;
89 /* skip leading white space */
90 while (isspace(*dataset_str))
91 dataset_str++;
93 /* if there is still any white space in the line, it's invalid */
94 for (cp = dataset_str; *cp; cp++)
95 if (isspace(*cp))
96 break;
97 if (*cp)
98 return; /* dataset name was invalid */
100 if (!in_menu_entry)
101 return; /* dataset line was not preceded by a title */
103 if ((datasets[menu_entry_count] = strdup(dataset_str)) == NULL)
104 prom_panic("out of mem");
105 menu_entry_count++;
106 in_menu_entry = 0;
110 char *
111 trim_white_space(char *cp)
113 char *ep;
115 /* skip leading white space */
116 while (isspace(*cp))
117 cp++;
120 * if the string contained nothing but white space, return a
121 * null string.
123 if (*cp == '\0')
124 return (cp);
126 /* truncate trailing white space */
127 for (ep = cp + strlen(cp) - 1; isspace(*ep); ep--)
129 ep++;
130 *ep = '\0';
131 return (cp);
134 char *cons_gets(char *, int);
136 void
137 main(void *cif)
139 char linebuf[MAX_CMDLINE];
140 FILE *file;
141 char *cp, *ep;
142 int n;
143 unsigned long choice;
145 prom_init("bootlst", cif);
146 set_default_fs("promfs");
147 if (mountroot("bootfs") != 0)
148 prom_panic("can't mount root");
150 if ((file = fopen("/boot/menu.lst", "r")) == NULL)
151 prom_panic("can't open menu.lst");
152 init_table();
154 while (fgets(linebuf, MAX_CMDLINE, file)) {
155 cp = trim_white_space(linebuf);
157 /* skip comments and blank lines */
158 if (*cp == '#' || *cp == '\0')
159 continue;
161 /* find end of first keyword on line */
162 for (ep = cp; !isspace(*ep) && *ep; ep++)
165 /* if at the end of the line, the line had no arguments */
166 if (*ep == '\0')
167 continue;
169 *ep = '\0';
171 if (strcmp(cp, "title") == 0) {
172 add_title_entry(ep + 1);
173 continue;
176 if (strcmp(cp, "bootfs") == 0) {
177 add_dataset_entry(ep + 1);
178 continue;
182 if (menu_entry_count == 0)
183 prom_panic("no menu entries found");
185 for (n = 0; n < menu_entry_count; n++) {
186 printf("%d %s\n", n + 1, titles[n]);
189 printf("Select environment to boot: [ 1 - %d ]: ", menu_entry_count);
191 while (cons_gets(linebuf, MAX_CMDLINE)) {
192 /* cut off leading and trailing white space */
193 cp = trim_white_space(linebuf);
194 choice = strtoul(cp, NULL, 0);
197 * If the input is totally invalid, the return value of
198 * strtoul() will be 0 or ULONG_MAX. Either way, it's
199 * of the acceptable range.
201 if (choice == 0 || choice > menu_entry_count) {
202 printf("Invalid entry.\n");
203 continue;
205 /* XXX here is the result */
206 printf("\nTo boot the selected entry, invoke:\n");
207 printf("boot [<root-device>] -Z %s\n\n", datasets[choice - 1]);
208 prom_exit_to_mon();