/* * CDDL HEADER START * * The contents of this file are subject to the terms of the * Common Development and Distribution License (the "License"). * You may not use this file except in compliance with the License. * * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE * or http://www.opensolaris.org/os/licensing. * See the License for the specific language governing permissions * and limitations under the License. * * When distributing Covered Code, include this CDDL HEADER in each * file and include the License file at usr/src/OPENSOLARIS.LICENSE. * If applicable, add the following below this CDDL HEADER, with the * fields enclosed by brackets "[]" replaced with your own identifying * information: Portions Copyright [yyyy] [name of copyright owner] * * CDDL HEADER END */ /* * Copyright 2008 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. */ #pragma ident "%Z%%M% %I% %E% SMI" /* * This file contains routines relating to running the menus. */ #include #include "global.h" #include "menu.h" #include "misc.h" #ifdef __STDC__ /* Function prototypes for ANSI C Compilers */ static int (*find_enabled_menu_item())(struct menu_item *menu, int item); #else /* __STDC__ */ /* Function prototypes for non-ANSI C Compilers */ static int (*find_enabled_menu_item())(); #endif /* __STDC__ */ static char cur_title[MAXPATHLEN]; /* * This routine takes a menu struct and concatenates the * command names into an array of strings describing the menu. * All menus have a 'quit' command at the bottom to exit the menu. */ char ** create_menu_list(menu) struct menu_item *menu; { register struct menu_item *mptr; register char **cpptr; register char **list; int nitems; /* * A minimum list consists of the quit command, followed * by a terminating null. */ nitems = 2; /* * Count the number of active commands in the menu and allocate * space for the array of pointers. */ for (mptr = menu; mptr->menu_cmd != NULL; mptr++) { if ((*mptr->menu_state)()) nitems++; } list = (char **)zalloc(nitems * sizeof (char *)); cpptr = list; /* * Fill in the array with the names of the menu commands. */ for (mptr = menu; mptr->menu_cmd != NULL; mptr++) { if ((*mptr->menu_state)()) { *cpptr++ = mptr->menu_cmd; } } /* * Add the 'quit' command to the end. */ *cpptr = "quit"; return (list); } /* * This routine takes a menu list created by the above routine and * prints it nicely on the screen. */ void display_menu_list(list) char **list; { register char **str; for (str = list; *str != NULL; str++) fmt_print(" %s\n", *str); } /* * Find the "i"th enabled menu in a menu list. This depends * on menu_state() returning the same status as when the * original list of enabled commands was constructed. */ static int (* find_enabled_menu_item(menu, item))() struct menu_item *menu; int item; { struct menu_item *mp; for (mp = menu; mp->menu_cmd != NULL; mp++) { if ((*mp->menu_state)()) { if (item-- == 0) { return (mp->menu_func); } } } return (NULL); } /* * This routine 'runs' a menu. It repeatedly requests a command and * executes the command chosen. It exits when the 'quit' command is * executed. */ /*ARGSUSED*/ void run_menu(menu, title, prompt, display_flag) struct menu_item *menu; char *title; char *prompt; int display_flag; { char **list; int i; struct env env; u_ioparam_t ioparam; int (*f)(); /* * Create the menu list and display it. */ list = create_menu_list(menu); (void) strcpy(cur_title, title); fmt_print("\n\n%s MENU:\n", title); display_menu_list(list); /* * Save the environment so a ctrl-C out of a command lands here. */ saveenv(env); for (;;) { /* * Ask the user which command they want to run. */ ioparam.io_charlist = list; i = input(FIO_MSTR, prompt, '>', &ioparam, (int *)NULL, CMD_INPUT); /* * If they choose 'quit', the party's over. */ if ((f = find_enabled_menu_item(menu, i)) == NULL) break; /* * Mark the saved environment active so the user can now * do a ctrl-C to get out of the command. */ useenv(); /* * Run the command. If it returns an error and we are * running out of a command file, the party's really over. */ if ((*f)() && option_f) fullabort(); /* * Mark the saved environment inactive so ctrl-C doesn't * work at the menu itself. */ unuseenv(); /* * Since menu items are dynamic, some commands * cause changes to occur. Destroy the old menu, * and rebuild it, so we're always up-to-date. */ destroy_data((char *)list); list = create_menu_list(menu); /* * Redisplay menu, if we're returning to this one. */ if (cur_menu != last_menu) { last_menu = cur_menu; (void) strcpy(cur_title, title); fmt_print("\n\n%s MENU:\n", title); display_menu_list(list); } } /* * Clean up the environment stack and throw away the menu list. */ clearenv(); destroy_data((char *)list); } /* * re-display the screen after exiting from shell escape * */ void redisplay_menu_list(list) char **list; { fmt_print("\n\n%s MENU:\n", cur_title); display_menu_list(list); } /* * Glue to always return true. Used for menu items which * are always enabled. */ int true() { return (1); } /* * Note: The following functions are used to enable the inclusion * of device specific options (see init_menus.c). But when we are * running non interactively with commands taken from a script file, * current disk (cur_disk, cur_type, cur_ctype) may not be defined. * They get defined when the script selects a disk using "disk" option * in the main menu. However, in the normal interactive mode, the disk * selection happens before entering the main menu. */ /* * Return true for menu items enabled only for embedded SCSI controllers */ int embedded_scsi() { if (cur_ctype == NULL && option_f) return (0); return (EMBEDDED_SCSI); } /* * Return false for menu items disabled only for embedded SCSI controllers */ int not_embedded_scsi() { if (cur_ctype == NULL && option_f) return (0); return (!EMBEDDED_SCSI); } /* * Return false for menu items disabled for scsi controllers */ int not_scsi() { if (cur_ctype == NULL && option_f) return (0); return (!SCSI); } /* * Return false for menu items disabled for efi labels */ int not_efi() { if ((cur_disk == NULL) && option_f) return (0); if (cur_disk->label_type == L_TYPE_EFI) return (0); return (1); } int disp_expert_change_expert_efi() { if ((cur_disk == NULL) && option_f) return (0); if ((cur_disk->label_type == L_TYPE_EFI) && expert_mode) return (1); if (cur_disk->label_type != L_TYPE_EFI) return (1); return (0); } int disp_expand_efi() { if ((cur_disk == NULL) && option_f) return (0); if (cur_disk->label_type != L_TYPE_EFI) return (0); if (cur_parts == NULL) return (0); return (1); } int disp_all_change_expert_efi() { if ((cur_disk == NULL) && option_f) return (0); if ((cur_disk->label_type != L_TYPE_EFI) || (!expert_mode)) return (0); return (1); } /* * Return true for menu items enabled scsi controllers */ int scsi() { if (cur_ctype == NULL && option_f) return (0); return (SCSI); } /* * Return true for menu items enabled if expert mode is enabled */ int scsi_expert() { if (cur_ctype == NULL && option_f) return (0); return (SCSI && expert_mode); } #if defined(i386) /* * Return true for menu items enabled if expert mode is enabled */ int expert() { return (expert_mode); } #endif /* defined(i386) */ /* * Return true for menu items enabled if developer mode is enabled */ int developer() { return (dev_expert); } /* * For x86, always return true for menu items enabled * since fdisk is already supported on these two platforms. * For Sparc, only return true for menu items enabled * if a PCATA disk is selected. */ int support_fdisk_on_sparc() { #if defined(sparc) /* * If it's a SCSI disk then we don't support fdisk and we * don't need to know the type cause we can ask the disk, * therefore we return true only if we *KNOW* it's an ATA * disk. */ if (cur_ctype && cur_ctype->ctype_ctype == DKC_PCMCIA_ATA) { return (1); } else { return (0); } #elif defined(i386) return (1); #else #error No Platform defined #endif /* defined(sparc) */ }