1 /*
2 * CDDL HEADER START
3 *
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.
7 *
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.
12 *
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]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * This file contains routines relating to running the menus.
28 */
29 #include <string.h>
30 #include "global.h"
31 #include "menu.h"
32 #include "misc.h"
33
34 static int (*find_enabled_menu_item(struct menu_item *, int))(void);
35
36 static char cur_title[MAXPATHLEN];
37
38 /*
39 * This routine takes a menu struct and concatenates the
40 * command names into an array of strings describing the menu.
41 * All menus have a 'quit' command at the bottom to exit the menu.
42 */
43 char **
create_menu_list(struct menu_item * menu)44 create_menu_list(struct menu_item *menu)
45 {
46 struct menu_item *mptr;
47 char **cpptr;
48 char **list;
49 int nitems;
50
51 /*
52 * A minimum list consists of the quit command, followed
53 * by a terminating null.
54 */
55 nitems = 2;
56 /*
57 * Count the number of active commands in the menu and allocate
58 * space for the array of pointers.
59 */
60 for (mptr = menu; mptr->menu_cmd != NULL; mptr++) {
61 if ((*mptr->menu_state)())
62 nitems++;
63 }
64 list = (char **)zalloc(nitems * sizeof (char *));
65 cpptr = list;
66 /*
67 * Fill in the array with the names of the menu commands.
68 */
69 for (mptr = menu; mptr->menu_cmd != NULL; mptr++) {
70 if ((*mptr->menu_state)()) {
71 *cpptr++ = mptr->menu_cmd;
72 }
73 }
74 /*
75 * Add the 'quit' command to the end.
76 */
77 *cpptr = "quit";
78 return (list);
79 }
80
81 /*
82 * This routine takes a menu list created by the above routine and
83 * prints it nicely on the screen.
84 */
85 void
display_menu_list(char ** list)86 display_menu_list(char **list)
87 {
88 char **str;
89
90 for (str = list; *str != NULL; str++)
91 fmt_print(" %s\n", *str);
92 }
93
94 /*
95 * Find the "i"th enabled menu in a menu list. This depends
96 * on menu_state() returning the same status as when the
97 * original list of enabled commands was constructed.
98 */
99 static int (*
find_enabled_menu_item(struct menu_item * menu,int item)100 find_enabled_menu_item(struct menu_item *menu, int item))(void)
101 {
102 struct menu_item *mp;
103
104 for (mp = menu; mp->menu_cmd != NULL; mp++) {
105 if ((*mp->menu_state)()) {
106 if (item-- == 0) {
107 return (mp->menu_func);
108 }
109 }
110 }
111
112 return (NULL);
113 }
114
115 /*
116 * This routine 'runs' a menu. It repeatedly requests a command and
117 * executes the command chosen. It exits when the 'quit' command is
118 * executed.
119 */
120 /*ARGSUSED*/
121 void
run_menu(struct menu_item * menu,char * title,char * prompt,int display_flag)122 run_menu(struct menu_item *menu, char *title, char *prompt, int display_flag)
123 {
124 char **list;
125 int i;
126 struct env env;
127 u_ioparam_t ioparam;
128 int (*f)();
129
130
131 /*
132 * Create the menu list and display it.
133 */
134 list = create_menu_list(menu);
135 (void) strcpy(cur_title, title);
136 fmt_print("\n\n%s MENU:\n", title);
137 display_menu_list(list);
138 /*
139 * Save the environment so a ctrl-C out of a command lands here.
140 */
141 saveenv(env);
142 for (;;) {
143 /*
144 * Ask the user which command they want to run.
145 */
146 ioparam.io_charlist = list;
147 i = input(FIO_MSTR, prompt, '>', &ioparam, NULL, CMD_INPUT);
148 /*
149 * If they choose 'quit', the party's over.
150 */
151 if ((f = find_enabled_menu_item(menu, i)) == NULL)
152 break;
153
154 /*
155 * Mark the saved environment active so the user can now
156 * do a ctrl-C to get out of the command.
157 */
158 useenv();
159 /*
160 * Run the command. If it returns an error and we are
161 * running out of a command file, the party's really over.
162 */
163 if ((*f)() && option_f)
164 fullabort();
165 /*
166 * Mark the saved environment inactive so ctrl-C doesn't
167 * work at the menu itself.
168 */
169 unuseenv();
170 /*
171 * Since menu items are dynamic, some commands
172 * cause changes to occur. Destroy the old menu,
173 * and rebuild it, so we're always up-to-date.
174 */
175 destroy_data((char *)list);
176 list = create_menu_list(menu);
177 /*
178 * Redisplay menu, if we're returning to this one.
179 */
180 if (cur_menu != last_menu) {
181 last_menu = cur_menu;
182 (void) strcpy(cur_title, title);
183 fmt_print("\n\n%s MENU:\n", title);
184 display_menu_list(list);
185 }
186 }
187 /*
188 * Clean up the environment stack and throw away the menu list.
189 */
190 clearenv();
191 destroy_data((char *)list);
192 }
193
194 /*
195 * re-display the screen after exiting from shell escape
196 *
197 */
198 void
redisplay_menu_list(char ** list)199 redisplay_menu_list(char **list)
200 {
201 fmt_print("\n\n%s MENU:\n", cur_title);
202 display_menu_list(list);
203 }
204
205
206 /*
207 * Glue to always return true. Used for menu items which
208 * are always enabled.
209 */
210 int
211 true(void)
212 {
213 return (1);
214 }
215
216 /*
217 * Note: The following functions are used to enable the inclusion
218 * of device specific options (see init_menus.c). But when we are
219 * running non interactively with commands taken from a script file,
220 * current disk (cur_disk, cur_type, cur_ctype) may not be defined.
221 * They get defined when the script selects a disk using "disk" option
222 * in the main menu. However, in the normal interactive mode, the disk
223 * selection happens before entering the main menu.
224 */
225 /*
226 * Return true for menu items enabled only for embedded SCSI controllers
227 */
228 int
embedded_scsi(void)229 embedded_scsi(void)
230 {
231 if (cur_ctype == NULL && option_f)
232 return (0);
233 return (EMBEDDED_SCSI);
234 }
235
236 /*
237 * Return false for menu items disabled only for embedded SCSI controllers
238 */
239 int
not_embedded_scsi(void)240 not_embedded_scsi(void)
241 {
242 if (cur_ctype == NULL && option_f)
243 return (0);
244 return (!EMBEDDED_SCSI);
245 }
246
247 /*
248 * Return false for menu items disabled for scsi controllers
249 */
250 int
not_scsi(void)251 not_scsi(void)
252 {
253 if (cur_ctype == NULL && option_f)
254 return (0);
255 return (!SCSI);
256 }
257
258 /*
259 * Return false for menu items disabled for efi labels
260 */
261 int
not_efi(void)262 not_efi(void)
263 {
264 if ((cur_disk == NULL) && option_f)
265 return (0);
266 if (cur_disk->label_type == L_TYPE_EFI)
267 return (0);
268 return (1);
269 }
270
271 int
disp_expert_change_expert_efi(void)272 disp_expert_change_expert_efi(void)
273 {
274 if ((cur_disk == NULL) && option_f)
275 return (0);
276 if ((cur_disk->label_type == L_TYPE_EFI) && expert_mode)
277 return (1);
278 if (cur_disk->label_type != L_TYPE_EFI)
279 return (1);
280 return (0);
281 }
282
283 int
disp_expand_efi(void)284 disp_expand_efi(void)
285 {
286 if ((cur_disk == NULL) && option_f)
287 return (0);
288 if (cur_disk->label_type != L_TYPE_EFI)
289 return (0);
290 if (cur_parts == NULL)
291 return (0);
292 return (1);
293 }
294
295 int
disp_all_change_expert_efi(void)296 disp_all_change_expert_efi(void)
297 {
298 if ((cur_disk == NULL) && option_f)
299 return (0);
300 if ((cur_disk->label_type != L_TYPE_EFI) || (!expert_mode))
301 return (0);
302 return (1);
303 }
304
305 /*
306 * Return true for menu items enabled scsi controllers
307 */
308 int
scsi(void)309 scsi(void)
310 {
311 if (cur_ctype == NULL && option_f)
312 return (0);
313 return (SCSI);
314 }
315
316
317 /*
318 * Return true for menu items enabled if expert mode is enabled
319 */
320 int
scsi_expert(void)321 scsi_expert(void)
322 {
323 if (cur_ctype == NULL && option_f)
324 return (0);
325 return (SCSI && expert_mode);
326 }
327
328 #if defined(i386)
329 /*
330 * Return true for menu items enabled if expert mode is enabled
331 */
332 int
expert(void)333 expert(void)
334 {
335 return (expert_mode);
336 }
337 #endif /* defined(i386) */
338
339 /*
340 * Return true for menu items enabled if developer mode is enabled
341 */
342 int
developer(void)343 developer(void)
344 {
345 return (dev_expert);
346 }
347
348 /*
349 * For x86, always return true for menu items enabled
350 * since fdisk is already supported on these two platforms.
351 * For Sparc, only return true for menu items enabled
352 * if a PCATA disk is selected.
353 */
354 int
support_fdisk_on_sparc(void)355 support_fdisk_on_sparc(void)
356 {
357 #if defined(sparc)
358 /*
359 * If it's a SCSI disk then we don't support fdisk and we
360 * don't need to know the type cause we can ask the disk,
361 * therefore we return true only if we *KNOW* it's an ATA
362 * disk.
363 */
364 if (cur_ctype && cur_ctype->ctype_ctype == DKC_PCMCIA_ATA) {
365 return (1);
366 } else {
367 return (0);
368 }
369 #elif defined(i386)
370 return (1);
371 #else
372 #error No Platform defined
373 #endif /* defined(sparc) */
374
375 }
376