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