xref: /illumos-gate/usr/src/cmd/format/menu.c (revision dd72704bd9e794056c558153663c739e2012d721)
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 **
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
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 (*
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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