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