18097Sjkh/* 28097Sjkh * The new sysinstall program. 38097Sjkh * 48097Sjkh * This is probably the last attempt in the `sysinstall' line, the next 58097Sjkh * generation being slated for what's essentially a complete rewrite. 68097Sjkh * 750479Speter * $FreeBSD$ 88097Sjkh * 98097Sjkh * Copyright (c) 1995 108097Sjkh * Jordan Hubbard. All rights reserved. 118097Sjkh * 128097Sjkh * Redistribution and use in source and binary forms, with or without 138097Sjkh * modification, are permitted provided that the following conditions 148097Sjkh * are met: 158097Sjkh * 1. Redistributions of source code must retain the above copyright 168881Srgrimes * notice, this list of conditions and the following disclaimer, 178881Srgrimes * verbatim and that no modifications are made prior to this 188097Sjkh * point in the file. 198097Sjkh * 2. Redistributions in binary form must reproduce the above copyright 208097Sjkh * notice, this list of conditions and the following disclaimer in the 218097Sjkh * documentation and/or other materials provided with the distribution. 228097Sjkh * 238097Sjkh * THIS SOFTWARE IS PROVIDED BY JORDAN HUBBARD ``AS IS'' AND 248097Sjkh * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 258097Sjkh * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 268097Sjkh * ARE DISCLAIMED. IN NO EVENT SHALL JORDAN HUBBARD OR HIS PETS BE LIABLE 278097Sjkh * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 288097Sjkh * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 298097Sjkh * OR SERVICES; LOSS OF USE, DATA, LIFE OR PROFITS; OR BUSINESS INTERRUPTION) 308097Sjkh * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 318097Sjkh * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 328097Sjkh * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 338097Sjkh * SUCH DAMAGE. 348097Sjkh * 358097Sjkh */ 368097Sjkh 378097Sjkh#include "sysinstall.h" 38156118Sjhb#include <sys/param.h> 3919573Sjoerg#include <errno.h> 408097Sjkh 4112661Speter#define MAX_MENU 15 428097Sjkh 4315416Sjkhstatic Boolean exited; 4415091Sjkh 4515091Sjkhint 4615091SjkhdmenuDisplayFile(dialogMenuItem *tmp) 4715091Sjkh{ 4815091Sjkh systemDisplayHelp((char *)tmp->data); 4954587Sjkh return DITEM_SUCCESS; 5015091Sjkh} 5115091Sjkh 5215091Sjkhint 5315091SjkhdmenuSubmenu(dialogMenuItem *tmp) 5415091Sjkh{ 5554587Sjkh return (dmenuOpenSimple((DMenu *)(tmp->data), FALSE) ? DITEM_SUCCESS : DITEM_FAILURE); 5615091Sjkh} 5715091Sjkh 5815091Sjkhint 5915355SjkhdmenuSystemCommand(dialogMenuItem *self) 6015091Sjkh{ 6115355Sjkh WINDOW *w = NULL; /* Keep lint happy */ 6215091Sjkh 6315355Sjkh /* If aux is set, the command is known not to produce any screen-spoiling output */ 6415355Sjkh if (!self->aux) 6515355Sjkh w = savescr(); 6615355Sjkh systemExecute((char *)self->data); 6715355Sjkh if (!self->aux) 6815355Sjkh restorescr(w); 6915242Sjkh return DITEM_SUCCESS; 7015091Sjkh} 7115091Sjkh 7215091Sjkhint 7315091SjkhdmenuSystemCommandBox(dialogMenuItem *tmp) 7415091Sjkh{ 7554587Sjkh WINDOW *w = savescr(); 7654587Sjkh 7715091Sjkh use_helpfile(NULL); 7815091Sjkh use_helpline("Select OK to dismiss this dialog"); 7915091Sjkh dialog_prgbox(tmp->title, (char *)tmp->data, 22, 76, 1, 1); 8054587Sjkh restorescr(w); 8154587Sjkh return DITEM_SUCCESS; 8215091Sjkh} 8315091Sjkh 8415091Sjkhint 8515416SjkhdmenuExit(dialogMenuItem *tmp) 8615091Sjkh{ 8715416Sjkh exited = TRUE; 8815242Sjkh return DITEM_LEAVE_MENU; 8915091Sjkh} 9015091Sjkh 9115091Sjkhint 9215091SjkhdmenuSetVariable(dialogMenuItem *tmp) 9315091Sjkh{ 9443707Sjkh variable_set((char *)tmp->data, *((char *)tmp->data) != '_'); 9515242Sjkh return DITEM_SUCCESS; 9615091Sjkh} 9715091Sjkh 9815091Sjkhint 9919488SjkhdmenuSetVariables(dialogMenuItem *tmp) 10019488Sjkh{ 10119488Sjkh char *cp1, *cp2; 10219488Sjkh char *copy = strdup((char *)tmp->data); 10319488Sjkh 10419488Sjkh for (cp1 = copy; cp1 != NULL;) { 10519488Sjkh cp2 = index(cp1, ','); 10619488Sjkh if (cp2 != NULL) *cp2++ = '\0'; 10743688Sjkh variable_set(cp1, *cp1 != '_'); 10819488Sjkh cp1 = cp2; 10919488Sjkh } 11019488Sjkh free(copy); 11119488Sjkh return DITEM_SUCCESS; 11219488Sjkh} 11319488Sjkh 11419488Sjkhint 115156118SjhbdmenuSetCountryVariable(dialogMenuItem *tmp) 116156118Sjhb{ 117156118Sjhb variable_set((char *)tmp->data, FALSE); 118156118Sjhb#ifdef WITH_SYSCONS 119156118Sjhb /* Don't prompt the user for a keymap if they're using the default locale. */ 120156118Sjhb if (!strcmp(variable_get(VAR_COUNTRY), DEFAULT_COUNTRY)) 121156118Sjhb return DITEM_SUCCESS; 122156118Sjhb 123156118Sjhb return keymapMenuSelect(tmp); 124156118Sjhb#else 125156118Sjhb return DITEM_SUCCESS; 126156118Sjhb#endif 127156118Sjhb} 128156118Sjhb 129156118Sjhbint 13019573SjoergdmenuSetKmapVariable(dialogMenuItem *tmp) 13119573Sjoerg{ 13219573Sjoerg char *lang; 13319573Sjoerg int err; 13419573Sjoerg 13557502Sjkh variable_set((char *)tmp->data, TRUE); 13629539Spst lang = variable_get(VAR_KEYMAP); 13719573Sjoerg if (lang != NULL) 13819573Sjoerg { 13919573Sjoerg err = loadKeymap(lang); 14019573Sjoerg if (err == -1) 14119573Sjoerg msgConfirm("No appropriate keyboard map found, sorry."); 14219573Sjoerg else if (err == -2) 14319573Sjoerg msgConfirm("Error installing keyboard map, errno = %d.", errno); 14419573Sjoerg } 14519573Sjoerg return DITEM_SUCCESS; 14619573Sjoerg} 14719573Sjoerg 14819573Sjoergint 14916326SjkhdmenuToggleVariable(dialogMenuItem *tmp) 15016326Sjkh{ 15157825Sjkh char *var, *cp; 15257502Sjkh int status; 15334472Sjkh 15457825Sjkh if (!(var = strdup((char *)tmp->data))) { 15534472Sjkh msgConfirm("Incorrect data field for `%s'!", tmp->title); 15634472Sjkh return DITEM_FAILURE; 15734472Sjkh } 15857825Sjkh if (!(cp = index(var, '='))) { 15957825Sjkh msgConfirm("Data field for %s is not in var=value format!", tmp->title); 16057825Sjkh return DITEM_FAILURE; 16157825Sjkh } 16257502Sjkh status = variable_check(var); 16357825Sjkh *cp = '\0'; 16457502Sjkh variable_set2(var, status ? "NO" : "YES", *var != '_'); 16557825Sjkh free(var); 16616326Sjkh return DITEM_SUCCESS; 16716326Sjkh} 16816326Sjkh 16916326Sjkhint 17030414SjkhdmenuISetVariable(dialogMenuItem *tmp) 17130414Sjkh{ 172173172Skensmith char *ans, *p, *var; 17330414Sjkh 174173172Skensmith if (!(var = strdup((char *)tmp->data))) { 17530414Sjkh msgConfirm("Incorrect data field for `%s'!", tmp->title); 17630414Sjkh return DITEM_FAILURE; 17730414Sjkh } 178173172Skensmith if ((p = index(var, '=')) != NULL) 179173172Skensmith *p = '\0'; 18043685Sjkh ans = msgGetInput(variable_get(var), tmp->title, 1); 181173172Skensmith if (!ans) { 182173172Skensmith free(var); 18330414Sjkh return DITEM_FAILURE; 184173172Skensmith } else if (!*ans) 18530414Sjkh variable_unset(var); 18630414Sjkh else 18743688Sjkh variable_set2(var, ans, *var != '_'); 188173172Skensmith free(var); 18930414Sjkh return DITEM_SUCCESS; 19030414Sjkh} 19130414Sjkh 19230414Sjkhint 19315091SjkhdmenuSetFlag(dialogMenuItem *tmp) 19415091Sjkh{ 19515242Sjkh if (*((unsigned int *)tmp->data) & tmp->aux) 19615242Sjkh *((unsigned int *)tmp->data) &= ~tmp->aux; 19715242Sjkh else 19815242Sjkh *((unsigned int *)tmp->data) |= tmp->aux; 19915242Sjkh return DITEM_SUCCESS; 20015091Sjkh} 20115091Sjkh 20215091Sjkhint 20315091SjkhdmenuSetValue(dialogMenuItem *tmp) 20415091Sjkh{ 20515091Sjkh *((unsigned int *)tmp->data) = tmp->aux; 20615242Sjkh return DITEM_SUCCESS; 20715091Sjkh} 20815091Sjkh 2098549Sjkh/* Traverse menu but give user no control over positioning */ 2109202SrgrimesBoolean 21116887SjkhdmenuOpenSimple(DMenu *menu, Boolean buttons) 2128549Sjkh{ 2138549Sjkh int choice, scroll, curr, max; 2148549Sjkh 2158549Sjkh choice = scroll = curr = max = 0; 21616887Sjkh return dmenuOpen(menu, &choice, &scroll, &curr, &max, buttons); 2178549Sjkh} 2188549Sjkh 2199202Srgrimes/* Work functions for the state hook */ 22015091Sjkhint 22115091SjkhdmenuFlagCheck(dialogMenuItem *item) 2229202Srgrimes{ 22315091Sjkh return (*((unsigned int *)item->data) & item->aux); 2249202Srgrimes} 2259202Srgrimes 22615091Sjkhint 22715091SjkhdmenuVarCheck(dialogMenuItem *item) 2289202Srgrimes{ 22926610Sjkh char *w; 2309202Srgrimes 23115091Sjkh w = (char *)item->aux; 23212661Speter if (!w) 23315091Sjkh w = (char *)item->data; 23426610Sjkh return variable_check(w); 23526610Sjkh} 23626610Sjkh 23726610Sjkhint 23826610SjkhdmenuVarsCheck(dialogMenuItem *item) 23926610Sjkh{ 24026610Sjkh int res, init; 24126610Sjkh char *w, *cp1, *cp2; 24226610Sjkh char *copy; 24326610Sjkh 24426610Sjkh w = (char *)item->aux; 24526610Sjkh if (!w) 24626610Sjkh w = (char *)item->data; 24726610Sjkh if (!w) 24826610Sjkh return FALSE; 24926610Sjkh 25026610Sjkh copy = strdup(w); 25126610Sjkh res = TRUE; 25226610Sjkh init = FALSE; 25326610Sjkh for (cp1 = copy; cp1 != NULL;) { 25426610Sjkh init = TRUE; 25526610Sjkh cp2 = index(cp1, ','); 25626610Sjkh if (cp2 != NULL) 25726610Sjkh *cp2++ = '\0'; 25826610Sjkh res = res && variable_check(cp1); 25926610Sjkh cp1 = cp2; 2609202Srgrimes } 26126610Sjkh free(copy); 26226610Sjkh return res && init; 2639202Srgrimes} 2649202Srgrimes 26515091Sjkhint 26615091SjkhdmenuRadioCheck(dialogMenuItem *item) 2679202Srgrimes{ 268156123Sjhb return (*((int *)item->data) == item->aux); 2699202Srgrimes} 2709202Srgrimes 27112661Speterstatic int 27212661Spetermenu_height(DMenu *menu, int n) 27312661Speter{ 27412661Speter int max; 27512661Speter char *t; 27612661Speter 27717375Sjkh max = MAX_MENU; 27817375Sjkh if (StatusLine > 24) 27917375Sjkh max += StatusLine - 24; 28017375Sjkh for (t = menu->prompt; *t; t++) { 28112661Speter if (*t == '\n') 28212661Speter --max; 28312661Speter } 28412661Speter return n > max ? max : n; 28512661Speter} 28612661Speter 287156118Sjhb/* Find a menu item that matches any field. */ 288156118Sjhbint 289156118SjhbdmenuFindItem(DMenu *menu, const char *prompt, const char *title, void *data) 290156118Sjhb{ 291156118Sjhb dialogMenuItem *items = menu->items; 292156118Sjhb int i; 293156118Sjhb 294156118Sjhb for (i = 0; items[i].prompt; ++i) 295156118Sjhb if ((prompt && !strcmp(items[i].prompt, prompt)) || 296156118Sjhb (title && !strcmp(items[i].title, title)) || 297156118Sjhb (data && items[i].data == data)) 298156118Sjhb return i; 299156118Sjhb 300156118Sjhb return -1; 301156118Sjhb} 302156118Sjhb 303156118Sjhb/* Set the default item for a menu by index and scroll to it. */ 304156118Sjhbvoid 305156118SjhbdmenuSetDefaultIndex(DMenu *menu, int *choice, int *scroll, int *curr, int *max) 306156118Sjhb{ 307156118Sjhb int nitem; 308156118Sjhb int height; 309156118Sjhb 310156118Sjhb *curr = *max = 0; 311156118Sjhb 312156118Sjhb for (nitem = 0; menu->items[nitem].prompt; ++nitem); 313156118Sjhb 314156118Sjhb height = menu_height(menu, nitem); 315156118Sjhb if (*choice > height) 316156118Sjhb { 317156118Sjhb *scroll = MIN(nitem - height, *choice); 318156118Sjhb *choice = *choice - *scroll; 319156118Sjhb } 320156118Sjhb else 321156118Sjhb *scroll = 0; 322156118Sjhb} 323156118Sjhb 324156118Sjhb/* Set the default menu item that matches any field and scroll to it. */ 325156118SjhbBoolean 326156118SjhbdmenuSetDefaultItem(DMenu *menu, const char *prompt, const char *title, void *data, 327156118Sjhb int *choice, int *scroll, int *curr, int *max) 328156118Sjhb{ 329156118Sjhb if ((*choice = dmenuFindItem(menu, prompt, title, data)) != -1) 330156118Sjhb { 331156118Sjhb dmenuSetDefaultIndex(menu, choice, scroll, curr, max); 332156118Sjhb return TRUE; 333156118Sjhb } 334156118Sjhb else 335156118Sjhb { 336156118Sjhb *choice = *scroll = *curr = *max = 0; 337156118Sjhb return FALSE; 338156118Sjhb } 339156118Sjhb} 340156118Sjhb 3418097Sjkh/* Traverse over an internal menu */ 3429202SrgrimesBoolean 34316887SjkhdmenuOpen(DMenu *menu, int *choice, int *scroll, int *curr, int *max, Boolean buttons) 3448097Sjkh{ 34515091Sjkh int n, rval = 0; 34616887Sjkh dialogMenuItem *items; 3478097Sjkh 34816887Sjkh items = menu->items; 34916887Sjkh if (buttons) 35016887Sjkh items += 2; 35115091Sjkh /* Count up all the items */ 35216887Sjkh for (n = 0; items[n].title; n++); 3538097Sjkh 3548174Sjkh while (1) { 3558208Sjkh char buf[FILENAME_MAX]; 35654587Sjkh WINDOW *w = savescr(); 3578208Sjkh 3588174Sjkh /* Any helpful hints, put 'em up! */ 3598208Sjkh use_helpline(menu->helpline); 3608208Sjkh use_helpfile(systemHelpFile(menu->helpfile, buf)); 36154587Sjkh dialog_clear_norefresh(); 3628097Sjkh /* Pop up that dialog! */ 36315242Sjkh if (menu->type & DMENU_NORMAL_TYPE) 364120147Smarcel rval = dialog_menu((u_char *)menu->title, (u_char *)menu->prompt, 365120147Smarcel -1, -1, menu_height(menu, n), -n, items, 366120147Smarcel (char *)(uintptr_t)buttons, choice, scroll); 36712661Speter 36815242Sjkh else if (menu->type & DMENU_RADIO_TYPE) 369120147Smarcel rval = dialog_radiolist((u_char *)menu->title, 370120147Smarcel (u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n, 371120147Smarcel items, (char *)(uintptr_t)buttons); 37212661Speter 37315242Sjkh else if (menu->type & DMENU_CHECKLIST_TYPE) 374120147Smarcel rval = dialog_checklist((u_char *)menu->title, 375120147Smarcel (u_char *)menu->prompt, -1, -1, menu_height(menu, n), -n, 376120147Smarcel items, (char *)(uintptr_t)buttons); 37715242Sjkh else 37815242Sjkh msgFatal("Menu: `%s' is of an unknown type\n", menu->title); 37915416Sjkh if (exited) { 38015416Sjkh exited = FALSE; 38154587Sjkh restorescr(w); 38215416Sjkh return TRUE; 38315416Sjkh } 38454587Sjkh else if (rval) { 38554587Sjkh restorescr(w); 3869202Srgrimes return FALSE; 38754587Sjkh } 38854587Sjkh else if (menu->type & DMENU_SELECTION_RETURNS) { 38954587Sjkh restorescr(w); 39015091Sjkh return TRUE; 39154587Sjkh } 3928097Sjkh } 3938097Sjkh} 394