#ident "lib/libsk/cmd/pmenu_cmd.c: $Revision: 1.85 $" /* * PROM (not shared with sash) Menu code * * The menu mechanics are in lib/menu.c, this file defines the contents * and implementation of the menu. * */ #if !IP19 && !IP20 && !IP21 && !IP22 && !IP26 /* no tpsc or tape install in standalone */ #define _NO_TAPE_INSTALL 1 #endif #ifdef _NO_TAPE_INSTALL #define NDEVICES 2 #define DEV_REMDIR 0 #define DEV_CDROM 1 #define DEV_TAPE 100 #define DEV_REMTAPE 101 #else #define NDEVICES 4 #define DEV_REMTAPE 0 #define DEV_REMDIR 1 #define DEV_CDROM 2 #define DEV_TAPE 3 #endif #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include /* icons for gui_sa_getsource() */ #if defined(IP24) #include #include #include #include #elif defined(IP22) || defined(IP26) || defined(IP28) #include #include #ifndef _NO_TAPE_INSTALL #include #include #endif #elif defined(IP30) #include #include #else #include #include #ifndef _NO_TAPE_INSTALL #include #include #endif #endif #if !IP20 && !EVEREST /* all new machines have PC keyboards */ #define KBD_SELECTOR /* PC keyboards do not auto-select */ #endif #include /* icons for prom menu */ #include #include #include #include #ifdef KBD_SELECTOR #include #endif #ifdef KBD_SELECTOR #define KBD_MENU_ITEM 1 #else #define KBD_MENU_ITEM 0 #endif #define EXTRA_MENU_ITEMS 0 #define ITEMS_IN_MENU (5 + KBD_MENU_ITEM + EXTRA_MENU_ITEMS) #if _MIPS_SIM == _ABI64 #define SASHNAME "sash64" #else /* _MIPS_SIM */ #define SASHNAME "sashARCS" #endif int menu_boot_sys(void); int menu_doinstall(void); int menu_boot_ide(void); int menu_manualmode(void); int menu_recovery(void); #ifdef KBD_SELECTOR int menu_kbdlayout(void); #endif static int gui_sa_getsource(char *, char *, char *); #ifndef SN0 extern char *fixupname(COMPONENT *); #else extern char *kl_fixupname(COMPONENT *); extern void sn0_dev2eng(COMPONENT *, char *) ; #endif static int sa_getsource(char *); static void appendComponentList(COMPONENT **list, COMPONENT *c); static void giveup(char *,unsigned long); static void returnmsg(void); static int menu_boot(char *, char *, char *, char *); static void showlist(COMPONENT *root, CONFIGTYPE type, struct radioList *list, int gui); static void boot_failed(int rc, char *path, char *type); static int instsrc; static int tapedevset; int needsa; static void bhandler(struct Button *b, __scunsigned_t value); static int pressed; /* * prom menu's items */ static mitem_t prom_menu_items[ITEMS_IN_MENU]; /* * prom menu */ menu_t prom_menu = { prom_menu_items, 1, "System Maintenance Menu", "Option?", "", ITEMS_IN_MENU }; /* Cannot initialize prom_menu_items[] during definition because we need to modify the flags field. if prom_menu_items[] was initialized during definition, it would be put into the prom and could not be changed during run time */ void init_prom_menu(void) { int i = 0; /* 1 */ prom_menu_items[i].prompt = "Start System"; prom_menu_items[i].service = menu_boot_sys; prom_menu_items[i].bits = &sysstart; i++; /* 2 */ prom_menu_items[i].prompt = "Install System Software"; prom_menu_items[i].service = menu_doinstall; prom_menu_items[i].bits = &install; prom_menu.item[i].flags |= M_PASSWD; i++; /* 3 */ prom_menu_items[i].prompt = "Run Diagnostics"; prom_menu_items[i].service = menu_boot_ide; prom_menu_items[i].bits = &diags; prom_menu.item[i].flags |= M_PASSWD; i++; /* 4 */ prom_menu_items[i].prompt = "Recover System"; prom_menu_items[i].service = menu_recovery; prom_menu_items[i].bits = &recover; prom_menu.item[i].flags |= M_PASSWD; i++; /* 5 */ prom_menu_items[i].prompt = "Enter Command Monitor"; prom_menu_items[i].service = menu_manualmode; prom_menu_items[i].bits = &console; prom_menu.item[i].flags |= M_PASSWD; i++; #ifdef KBD_SELECTOR /* -6 or -7 */ prom_menu_items[i].prompt = "Select Keyboard Layout"; prom_menu_items[i].service = menu_kbdlayout; prom_menu_items[i].bits = &kbdlay; prom_menu_items[i].flags |= M_GUIONLY; i++; #endif /* ** to strain software loading/ custom boot features ** through password validation, nuke out "dangerous" ** automatic entries, ie install software/ recover system */ } /* * Start system menu option implementation * */ int menu_boot_sys(void) { extern int Verbose; if (!Verbose && doGui()) { setGuiMode(1,0); } else { p_panelmode(); p_clear(); } if (autoboot(0, 0, 0) != ESUCCESS) giveup("Autoboot failed",0); return 0; } /* * Install System Software menu option implementation * * Run sash with the -m option. The idea is to * keep all the mini-root swill out of the prom. * */ int menu_doinstall(void) { char sash_path[128]; int rc; if (doGui()) { if (gui_sa_getsource(sash_path,"Install System Software", "Install")) return 0; } else { p_panelmode(); p_clear(); p_center(); p_printf("\n\nInstalling System Software...\n\n"); returnmsg(); if (sa_getsource(sash_path)) return 0; } Signal(SIGINT,SIGDefault); /* calls EnterInteractiveMode() */ rc = menu_boot(sash_path, "installation tools", "OSLoadOptions=mini", 0); boot_failed(rc, sash_path, "Installation"); return 0; } /* * Boot the standalone diagnostics * * The diagnostic is in the volume header along with sash. A * boot command, for a diskfull machine, is formed by replacing * the word "ide" to the SystemPartition variable, and for a * diskless machine, the last component in the SystemPartition variable, * is replaced with "stand/ide". */ #define MAXIDEPATHLEN 64 int menu_boot_ide(void) { char *p, *oboot, idepath[MAXIDEPATHLEN]; char *diag_arg = getenv("diagmode"); /* pass to ide script */ char *diskless; COMPONENT *c; ULONG fd; int rc; Signal(SIGINT,SIGDefault); (void)ioctl(0,TIOCINTRCHAR,(long)"\003\033"); /* add */ p_panelmode(); p_clear(); p_center(); #ifdef SN p_printf("\n\nDiagnostic program not supported in this configuration.\n\n"); return 0; #else p_printf("\n\nStarting diagnostic program...\n\n"); returnmsg(); /* If CD-ROM drive is present and sashARCS (or sash64 on 64 bit * PROMS) exists in part(8), try and boot it. */ if (c = find_type(GetChild(NULL),CDROMController)) { p = getpath(c); p_center(); p_printf("Checking for Distribution CD-ROM on %s.\n",p); strcpy(idepath,p); strcat(p,"part(8)" SASHNAME); if (Open(p,OpenReadOnly,&fd) == ESUCCESS) { Close(fd); p_center(); p_printf("Booting IDE from Distribution CD-ROM.\n\n"); strcat(idepath,"part(7)/stand/ide."); strcat(idepath,inv_findcpu()); rc = menu_boot(p,0,idepath,diag_arg); goto boot_done; } p_center(); p_printf("\nDistribution CD-ROM not found." " Booting installed IDE.\n"); } /* Try local disk, or /stand/ide on diskless. */ if ( (oboot = getenv("SystemPartition")) == 0 || *oboot == '\0' ) { giveup ("No SystemPartition set", 0); return 0; } else strcpy(idepath,oboot); if ( (p = rindex(idepath,')')) == 0 ) { giveup ("SystemPartition is not set correctly", 0); return 0; } diskless = getenv ("diskless"); if (diskless && (*diskless == '1')) { char *pp; if (pp = index(p, ':')) p = pp; if (pp = rindex(p, '/')) p = pp; strcpy(p+1,"stand/ide"); } else { strcpy(p+1,"ide"); diskless = 0; } rc = menu_boot(idepath, 0, 0, diag_arg); /* ide from the volume header failed. If not diskless try * to pick it up from /stand or /usr/stand (on unified disk). */ if (rc && !diskless) { strcpy(idepath,oboot); strcat(idepath,"sash"); rc = menu_boot(idepath,0,"stand/ide",diag_arg); if (rc) rc = menu_boot(idepath,0,"usr/stand/ide",diag_arg); } boot_done: instsrc = NDEVICES; /* Make sure don't get remote message */ boot_failed(rc, idepath, "Diagnostics"); return 0; #endif /* SN */ } /* * Give the user what they ask for, the old ">> " * */ int menu_manualmode(void) { extern void EnterInteractiveMode(); setTpButtonAction(EnterInteractiveMode,TPBDONE,WBONCHANGE); p_textmode(); p_clear(); printf("Command Monitor. Type \"exit\" %sto return to the menu.\n", isgraphic(StandardOut) ? "or click on \"done\" " : ""); return 1; } /* * Boot the mini-root in crash recovery mode * */ int menu_recovery(void) { static char *msg = "System Recovery"; char sash_path[128]; int rc; if (doGui()) { if (gui_sa_getsource(sash_path,msg,"Accept")) return 0; } else { p_panelmode(); p_clear(); p_center(); p_printf("\n\n%s...\n\n",msg); returnmsg(); if (sa_getsource(sash_path)) return 0; } rc = menu_boot (sash_path, "recovery tools", "OSLoadOptions=mini", "initstate=3"); boot_failed(rc, sash_path, "Recovery"); return 0; } #ifdef KBD_SELECTOR #define CUSTOM 15 char *kbdlayout[] = { "BE", "DE", "de_CH", "DK", "ES", "FI", "FR", "fr_CH", "GB", "IT", "JP", "NO", "PT", "SE", "US", "Custom", 0 }; #define KBDLMARGIN (DIALOGBDW+DIALOGMARGIN+40) #define KBDLW 595 #define KBDLH 260 /* * Put put selector box to pick keyboard map from supported maps. Systems * with PC keyboards cannot auto-select so let the user select with the * mouse. */ int menu_kbdlayout(void) { static char *title = "Keyboard Layout"; struct _radioButton *radio; int basex, i, ch, x,y, ty; struct radioList *list; struct Canvas *canvas; struct Button *accept; struct Button *cancel; __psint_t fnd; char *keybd; pressed = 0; keybd = getenv("keybd"); if (!keybd) keybd = "US"; setGuiMode(1,GUI_NOLOGO); canvas = createCanvas(KBDLW,KBDLH); moveObject(guiobj(canvas),canvas->gui.x1,((gfxHeight() - KBDLH)/3)*2); textSize(title,&x,&y,ncenB18); x = (gfxWidth()-x)>>1; y = ty = canvas->gui.y2 - DIALOGBDW - DIALOGMARGIN - y; moveTextPoint(x,y); (void)createText(title,ncenB18); x = canvas->gui.x1 + KBDLMARGIN; y = canvas->gui.y1 + DIALOGBDW + 2*DIALOGMARGIN + TEXTBUTH + 30; list = createRadioList(x,y,KBDLW-2*KBDLMARGIN,500); list->gui.y2 = ty - DIALOGMARGIN - 20; list->gui.parent = &canvas->gui; for (fnd=i=ch=0; kbdlayout[i]; i++) { ch = 0; if (!fnd && (!strcmp(keybd,kbdlayout[i]) || (kbdlayout[i+1] == 0))) { fnd = i+1; ch = 1; } radio = appendRadioList(list,kbdlayout[i],ch); if (radio) radio->userdata = (void *)(__psint_t)i; if (!i) { x = basex = radio->button.gui.x1; y = radio->button.gui.y1; } else if (i%4 != 0) { x += 140; moveObject(guiobj(&(radio->button)),x,y); } else { x = basex; y -= 30; moveObject(guiobj(&(radio->button)),x,y); } } /* If not already custom, need to use setenv */ if (fnd != (CUSTOM+1)) invalidateButton((struct Button *)&radio->button,1); x = canvas->gui.x2 - DIALOGBDW - DIALOGMARGIN - TEXTBUTW; y = canvas->gui.y1+DIALOGBDW + DIALOGMARGIN; accept = createButton(x,y,TEXTBUTW,TEXTBUTH); addButtonText(accept,"Apply"); addButtonCallBack(accept,bhandler,50); setDefaultButton(accept,1); x = accept->gui.x1 - (TEXTBUTW + BUTTONGAP); cancel = createButton(x,y,TEXTBUTW,TEXTBUTH); addButtonText(cancel,"Cancel"); addButtonCallBack(cancel,bhandler,51); guiRefresh(); while(1) { if (GetReadStatus(0) == ESUCCESS) { ch = getchar() & 0xff; if (ch == '\033') pressed = 51; else if ((ch == '\n') || (ch == '\r')) pressed = 50; else if ((ch >= 'a') && (ch <= 'z')) { struct _radioButton *old;/* item select */ int sel = ch - 'a'; old = setRadioListSelection(list,sel); if (old) { drawObject(guiobj(&(old->button))); drawObject(guiobj(&(list->selected->button))); } } } if (pressed) { if (pressed == 50) { /* Apply */ struct _radioButton *item; item = getRadioListSelection(list); if (!item) break; fnd = (__psint_t)item->userdata; /* save new value in nvram and re-map kbd */ if (fnd != CUSTOM) { setenv("keybd",kbdlayout[fnd]); pckm_setupmap(); } break; } if (pressed == 51) /* Cancel */ break; pressed = 0; } } return(0); } #endif static void boot_failed(int rc, char *path, char *type) { char errbuf[256]; switch (rc) { case ENOENT: if (instsrc == DEV_REMTAPE || instsrc == DEV_REMDIR) sprintf(errbuf,"%s tools not found at %s:%s\n", type, getenv("netinsthost"), getenv("netinstfile")); else sprintf(errbuf,"%s tools not found\n",type); break; case EADDRNOTAVAIL: case ETIMEDOUT: case ECONNABORTED: sprintf(errbuf, "Network error while loading %s tools",type); break; case ENXIO: if (instsrc == DEV_REMTAPE || instsrc == DEV_REMDIR) { sprintf(errbuf,"Unable to reach server %s",getenv("netinsthost")); break; } /*FALLSTHROUGH*/ default: sprintf(errbuf,"Cannot load %s -- %s.\n",path, arcs_strerror(rc)); break; } giveup(errbuf,0); } /* * Called when some kind of fatal error occurs */ static void giveup(char *string, unsigned long arg) { static int buttons[] = {DIALOGCONTINUE,DIALOGPREVDEF,-1}; char buff[256]; /* > LINESIZE */ if (!tapedevset) setenv("tapedevice",""); if (isGuiMode()) { setGuiMode(1,GUI_NOLOGO); /* clear screen */ sprintf(buff,string,arg); popupDialog(buff,buttons,DIALOGWARNING,DIALOGCENTER); return; } p_curson (); printf(string,arg); setTpButtonAction(EnterInteractiveMode,TPBRETURN,WBNOW); printf("\nUnable to continue; press to return to the menu: "); gets(buff); EnterInteractiveMode(); /* doesn't return from here */ } static int ndevs; static void dev2eng(COMPONENT *c, char *buf) { static char *ctrlmsg = " on controller %d"; char *host = getenv("netinsthost"); char *file = getenv("netinstfile"); COMPONENT *parent; char nbuf[32]; #ifndef SN0 parent = GetParent(c); #else parent = NULL ; #endif switch (c->Type) { case CDROMController: #ifdef SN0 panic("dev2eng: GetParent does not workfor CDROM on SN0\n") ; #endif sprintf(buf,"Local %sCD-ROM drive %d", (parent->Type == SCSIAdapter) ? "SCSI " : "", c->Key); if (parent->Key) { sprintf(nbuf,ctrlmsg,parent->Key); strcat(buf,nbuf); } break; case NetworkController: sprintf(nbuf,"on network %d",c->Key); if (instsrc == DEV_REMTAPE) { char *tmp,*l,*r; if (strcmp(file,"/dev/tape")) { l = " ["; tmp = file; r = "]"; } else l = r = tmp = ""; sprintf(buf,"Remote tape%s%s%s on server %s%s.", l,tmp,r,host,(ndevs > 1) ? nbuf : ""); } else sprintf(buf,"Remote directory %s from server %s%s.", file,host,(ndevs > 1) ? nbuf : ""); break; case TapeController: #ifdef SN0 panic("dev2eng: GetParent does not workfor TAPE on SN0\n") ; #endif sprintf(buf,"Local %sTape drive %d", (parent->Type == SCSIAdapter) ? "SCSI " : "", c->Key); if (parent->Key) { sprintf(nbuf,ctrlmsg,parent->Key); strcat(buf,nbuf); } break; } } static int insertpostop(char *source, COMPONENT *c, struct radioList *l); static int netpreop(struct radioList *l, int which); #define DEVBUTW 80 #define DEVBUTGAP 16 static struct devices { char *place; char *name; CONFIGTYPE type; int (*preop)(struct radioList *, int which); int (*postop)(char *, COMPONENT *, struct radioList *); struct pcbm *map; } devices[] = { #ifdef _NO_TAPE_INSTALL "Remote","Directory",NetworkController,netpreop,0,&instrdir, "Local","CD-ROM",CDROMController,0,insertpostop,&instcd, #else "Remote","Tape",NetworkController,netpreop,insertpostop,&instrtape, "Remote","Directory",NetworkController,netpreop,0,&instrdir, "Local","CD-ROM",CDROMController,0,insertpostop,&instcd, "Local","Tape", TapeController,0,insertpostop,&insttape #endif }; static int devcnt[NDEVICES]; static int netpreop(struct radioList *l, int which) { extern char netaddr_default[]; static char *ipprompt = "Enter your IP address:"; static char *hostprompt = "Enter the name of the remote host:"; static char *tapeprompt = "Enter the remote tape device:"; static char *dirprompt = "Enter the remote directory:"; static char *netinsthost = "netinsthost"; static char *netinstfile = "netinstfile"; static char *netaddr = "netaddr"; static int lastwhich; char *prompt,*cp; char buf[LINESIZE]; char tok[LINESIZE]; int rc; /* reset netinstfile if switching between tape and directory */ if (which != lastwhich) setenv(netinstfile,""); lastwhich = which; /* make sure we have a valid IP address */ check_IP_address: cp = getenv(netaddr); if (!cp || !strcmp(cp, netaddr_default)) { if (l) { rc = popupGets(ipprompt,&l->gui,0,buf,LINESIZE); if (rc == 1) /* cancel button */ return(0); } else { printf("%s ",ipprompt); gets(buf); } if ((token(buf,tok) == 1) && (inet_addr(tok).s_addr != (unsigned)-1)) setenv(netaddr,tok); goto check_IP_address; /* recheck for default */ } /* get hostname of remote system */ enter_hostname: cp = getenv(netinsthost); if (l) { rc = popupGets(hostprompt,&l->gui,cp,buf,LINESIZE); if (rc == 1) /* cancel button */ return(0); } else { printf("%s ", hostprompt); if (cp) printf("[%s] ",cp); gets(buf); if (cp && (buf[0] == '\0')) strcpy(buf,cp); } if (token(buf,tok) != 1) goto enter_hostname; /* if we are given a file take it! */ if (cp=index(tok,':')) { *cp = '\0'; setenv(netinsthost,tok); setenv(netinstfile,cp+1); goto done; /* skip remote file */ } setenv(netinsthost,buf); /* Get the remote filename */ enter_file: cp = getenv(netinstfile); if ((which == DEV_REMTAPE) && !cp) cp = "/dev/tape"; prompt = (which == DEV_REMTAPE) ? tapeprompt : dirprompt; if (l) { rc = popupGets(prompt, &l->gui,cp,buf,LINESIZE); if (rc == 1) return(0); } else { printf("%s ", prompt); if (cp) printf("[%s] ",cp); gets(buf); if (cp && (buf[0] == '\0')) strcpy(buf,cp); } if (token(buf,tok) != 1) goto enter_file; setenv(netinstfile,tok); done: needsa = (which != DEV_REMTAPE); /* no sa for tapes */ return(1); } /*ARGSUSED*/ static int insertpostop(char *source, COMPONENT *c, struct radioList *l) { static int buttons[] = {DIALOGCONTINUE,DIALOGPREVDEF, DIALOGCANCEL,DIALOGPREVESC, -1}; char buf[80]; int rc; sprintf(buf,"Insert the installation %s%s", (c->Type == CDROMController) ? "CD-ROM" : "tape", l ? " now." : ", then press : "); rc = popupAlignDialog(buf,&l->gui,buttons,DIALOGQUESTION,0); /* popupDialog return 1 -> cancel, 0 -> continue */ return((rc == 1) ? 0 : 1); } /*ARGSUSED*/ static void bhandler(struct Button *b, __scunsigned_t value) { pressed = (int)value; } static int gui_sa_getsource(char *source, char *title, char *doit) { #define GS_WIDTH 700 #define GS_SMHEIGHT 380 #define GS_HEIGHT 600 char *tapedevice = getenv("tapedevice"); struct Button *buttons[NDEVICES]; struct Button *cancel, *accept; int seldev, lastn, maxdevs; struct radioList *list; struct Canvas *canvas; int gs_width = 700; int i,x,y,ch; seldev = lastn = maxdevs = pressed = 0; setGuiMode(1,GUI_NOLOGO); for (i=0 ; i < NDEVICES; i++) { #ifdef SN0 devcnt[i] = kl_count_type(devices[i].type); #else devcnt[i] = count_type(GetChild(NULL),devices[i].type); #endif if (devcnt[i] > maxdevs) maxdevs = devcnt[i]; } y = (maxdevs <= 5) ? GS_SMHEIGHT : GS_HEIGHT; /* XXX - clip point on text string to prevent overflow? */ /* Squish window to fit in low resolution */ i = gfxWidth(); if (i < gs_width) gs_width = i; i = gfxHeight(); if (i < y) y = i; canvas = createCanvas(gs_width,y); /* put small window at 2/3 y if not shrunk */ if ((y == GS_SMHEIGHT) && (gs_width == GS_WIDTH)) moveObject(guiobj(canvas),canvas->gui.x1, ((gfxHeight() - y)/3)*2); textSize(title,&x,&y,ncenB18); x = (gfxWidth()-x)>>1; y = canvas->gui.y2 - DIALOGBDW - DIALOGMARGIN - y; moveTextPoint(x,y); (void)createText(title,ncenB18); x = canvas->gui.x1 + ((gs_width - (NDEVICES*DEVBUTW) - ((NDEVICES-1)*DEVBUTGAP))>>1); y -= (DEVBUTW+FORMVERTMARGIN); for (i=0 ; i < NDEVICES; i++) { struct Button *b; struct Text *t; b = createButton(x,y,DEVBUTW,DEVBUTW); addButtonCallBack(b,bhandler,i+1); addButtonImage(b,devices[i].map); if (devcnt[i] == 0) { invalidateButton(b,1); } else if ((i == DEV_CDROM) || (i == DEV_TAPE && !pressed)) /* default to local cd, or tape if present */ pressed = i+1; buttons[i] = b; t = createText(devices[i].place,helvR10); centerObject(guiobj(t),(struct gui_obj*)b); moveObject(guiobj(t),t->gui.x1,y-15); t = createText(devices[i].name,helvR10); centerObject(guiobj(t),guiobj(b)); moveObject(guiobj(t),t->gui.x1,y-15-fontHeight(helvR10)-1); x += DEVBUTW + DEVBUTGAP; } y -= 15+fontHeight(helvR10)-1; /* text labels */ x = canvas->gui.x1+DIALOGBDW+DIALOGMARGIN+30; y -= FORMVERTMARGIN; i = y-canvas->gui.y1-DIALOGBDW-DIALOGMARGIN-TEXTBUTH-FORMVERTMARGIN; list = createRadioList(x,y-i,gs_width-2*(DIALOGBDW+DIALOGMARGIN+30),i); list->gui.parent = &canvas->gui; x = canvas->gui.x2 - DIALOGBDW - DIALOGMARGIN - TEXTBUTW; y = canvas->gui.y1+DIALOGBDW + DIALOGMARGIN; accept = createButton(x,y,TEXTBUTW,TEXTBUTH); addButtonText(accept,doit); addButtonCallBack(accept,bhandler,20); setDefaultButton(accept,1); invalidateButton(accept,1); x = accept->gui.x1 - (TEXTBUTW + BUTTONGAP); cancel = createButton(x,y,TEXTBUTW,TEXTBUTH); addButtonText(cancel,"Cancel"); addButtonCallBack(cancel,bhandler,21); /* If tapedevice is set, show that promptly, and cancel possible * local device default. */ if (tapedevice) { appendRadioList(list,tapedevice,1); invalidateButton(accept,0); pressed = 0; } guiRefresh(); for(;;) { if (GetReadStatus(0) == ESUCCESS) { ch = getchar() & 0xff; /* convert keypress into button action */ if ((ch == '\n') || (ch == '\r')) pressed = 20; /* Accept */ else if ((ch >= '1') && (ch <= (char)('0'+NDEVICES))) pressed = ch - '0'; /* select device */ else if ((ch >= 'a') && (ch <= 'z')) { struct _radioButton *old;/* item select */ int sel = ch - 'a'; old = setRadioListSelection(list,sel); if (old) { drawObject(guiobj(&(old->button))); drawObject(guiobj(&(list->selected->button))); } } else if (ch == '\033') pressed = 21; /* Cancel */ } if (pressed) { if (pressed <= NDEVICES) { seldev = pressed - 1; for (i=0; i < NDEVICES; i++) { stickButton(buttons[i],i==seldev); drawObject(guiobj(buttons[i])); } resetRadioList(list); needsa = 0; /* reset */ if (devices[seldev].preop) { i = (*devices[seldev].preop)(list, pressed-1); resetRadioList(list); if (i == 0) { stickButton(buttons[seldev],0); drawObject(guiobj(buttons[seldev])); goto reset; } } instsrc = seldev; ndevs = devcnt[seldev]; #ifdef SN0 kl_showlist(NULL, devices[seldev].type,list,1); #else showlist(GetChild(NULL), devices[seldev].type,list,1); #endif if (tapedevice) appendRadioList(list,tapedevice,0); drawObject(guiobj(list)); } else if (pressed == 20) { /* Accept */ struct _radioButton *item; int iscdrom; if ((accept->gui.flags & _INVALID) != 0) goto reset; item = getRadioListSelection(list); if (!item) goto cancel; if (item->userdata) { iscdrom = (((COMPONENT *) item->userdata)->Type == CDROMController); tapedevset = 0; #ifdef SN0 strcpy(source,kl_fixupname((COMPONENT *) item->userdata)); #else strcpy(source,fixupname((COMPONENT *) item->userdata)); #endif } else { /* tapedevice */ tapedevset = 1; needsa = iscdrom = 0; strcpy(source,item->text); } resetRadioList(list); /* If selected other than $tapedevice run * the postop for the type selected. */ if (item->userdata && devices[seldev].postop) { if (!(*devices[seldev].postop)(source, (COMPONENT *)item->userdata, list)) { drawObject(guiobj(list)); stickButton(buttons[seldev],0); drawObject(guiobj(buttons[seldev])); goto reset; } } if (needsa) strcat(source,"/sa"); setenv("tapedevice",source); if (iscdrom) strcat(source,SASHNAME); else strcat(source,"(" SASHNAME ")"); setGuiMode(1,GUI_NOLOGO); /* free gui */ return(0); } else if (pressed == 21) { /* Cancel */ cancel: setGuiMode(1,GUI_NOLOGO); /* free gui */ return(EAGAIN); } reset: /* Turn on/off accept button depending on the list. */ if (list->curitems != lastn) { invalidateButton(accept,(list->curitems == 0)); drawObject(guiobj(accept)); } lastn = list->curitems; ch = pressed = 0; } } /*NOTREACHED*/ return 0; } static SIGNALHANDLER oldhand; /* need to be global for stand longjmp() */ static char *oldintr; static jmp_buf sags_jb; static void sags_esc(void) { longjmp(sags_jb,1); } /* tty version */ #define MAXLIST 26 /* a-z */ static int sa_getsource(char *source) { char *tapedevice = getenv("tapedevice"); int seldev, curitems, curitem; COMPONENT *list[MAXLIST+1]; int devflags[NDEVICES]; #define SA_INVALID 0x01 char buf[LINESIZE]; char tok[LINESIZE]; int i,ch; /* system menu code will reset signal stuff */ oldhand = Signal(SIGINT,(SIGNALHANDLER)sags_esc); oldintr = (char *)ioctl(0,TIOCINTRCHAR,(long)"\003\033"); if (setjmp(sags_jb)) { ioctl(0,TIOCINTRCHAR,(long)oldintr); Signal(SIGINT,oldhand); return(EAGAIN); } ch = curitem = curitems = 0; seldev = -1; bzero(list,sizeof(list)); for (i=0; i < NDEVICES; i++) { devflags[i] = 0; #if defined(SN0) if (kl_find_type(devices[i].type, NULL) == 0) { #else if (find_type(GetChild(NULL),devices[i].type) == 0) { #endif devflags[i] |= SA_INVALID; } else if ((i==DEV_CDROM || (i == DEV_TAPE && !ch))) /* default to local cd, or tape if present */ ch = '1' + i; } /* If tapedevice is set, show that promptly, and cancel possible * local device default. */ if (tapedevice) { appendComponentList(list,(COMPONENT *)(__psint_t)1); curitem = ch = 0; curitems =1; } for (;;) { if ((ch == '\n') || (ch == '\r')) { int iscdrom; if (list[curitem] == 0) { printf("\nno source selected.\n"); goto printlist; } if ((long)list[curitem] == 1) { strcpy(source,tapedevice); needsa = iscdrom = 0; tapedevset = 1; } else { #ifndef SN0 strcpy(source,fixupname(list[curitem])); #else strcpy(source,kl_fixupname(list[curitem])); #endif iscdrom=(list[curitem]->Type==CDROMController); tapedevset = 0; if (devices[seldev].postop) { printf("\n\n"); if (!(*devices[seldev].postop)( source,list[curitem],0)) goto printlist; } } bzero(list,sizeof(list)); if (needsa) strcat(source,"/sa"); setenv("tapedevice",source); if (iscdrom) strcat(source, SASHNAME); else strcat(source,"(" SASHNAME ")"); printf("\n\n"); ioctl(0,TIOCINTRCHAR,(long)oldintr); Signal(SIGINT,oldhand); return(0); } else if ((ch >= '1') && (ch <= (char)('0'+NDEVICES))) { int newseldev = ch - '1'; if (devflags[newseldev] & SA_INVALID) { printf("\n%s %s not available.\n", devices[newseldev].place, devices[newseldev].name); goto printlist; } seldev = newseldev; bzero(list,sizeof(list)); needsa = 0; /* reset */ if (devices[seldev].preop) { printf("\n\n"); i = (*devices[seldev].preop)(0,seldev); bzero(list,sizeof(list)); if (i == 0) { seldev = -1; goto printlist; } } instsrc = seldev; ndevs = devcnt[seldev]; #if defined(SN0) kl_showlist((void *)NULL, devices[seldev].type, (void *)list,0); #else showlist(GetChild(NULL),devices[seldev].type, (struct radioList *)list,0); #endif if (tapedevice) appendComponentList(list, (COMPONENT *)(__psint_t)1); for (curitems=0; list[curitems] != 0; curitems++) ; curitem = 0; } else if ((ch >= 'a') && (ch <= 'z')) { int sel = ch - 'a'; if (sel < curitems && curitems) curitem = sel; else { printf("\ndevice '%c' not available\n",ch); goto printlist; } } else if (ch) printf("\ninvalid input: '%c'\n",ch); /* print list */ printlist: printf("\n\n"); for (i=0; i < NDEVICES; i++) { if (devflags[i] & SA_INVALID) printf("X"); else printf("%d",i+1); printf( (i == seldev) ? ")[%s %s] " : ") %s %s ", devices[i].place, devices[i].name); } printf("\n"); for (i=0; list[i] != 0; i++ ) { char buf[100]; char *name; printf(" %c%c) ", (i == curitem) ? '*' : ' ','a'+i); if ((long)list[i] != 1) { #ifdef SN0 sn0_dev2eng(list[i],buf); #else dev2eng(list[i],buf); #endif name = buf; } else name = tapedevice; printf("%s\n",name); } printf("\nEnter 1-%c to select source type, ", '0' + NDEVICES); if (i != 0) { printf((i==1)?"a":"a-%c",'a'+i-1); printf(" to select the source, "); } printf(" to quit,\nor to start: "); gets(buf); if (buf[0] == '\0') ch = '\n'; else { token(buf,tok); /* skip blanks */ ch = tok[0]; } } /*NOTREACHED*/ return 0; } static void showlist(COMPONENT *c, CONFIGTYPE type, struct radioList *list, int gui) { char buf[100]; if (c == NULL) return; if (c->Type == type) { if (gui) { struct _radioButton *b; dev2eng(c,buf); b = appendRadioList(list,buf,0); if (b) b->userdata = (void *)c; } else { appendComponentList((COMPONENT **)list,c); } } showlist(GetChild(c), type, list, gui); showlist(GetPeer(c), type, list, gui); return; } static void appendComponentList(COMPONENT **list, COMPONENT *c) { int i; for (i=0 ; i < MAXLIST; i++) if (list[i] == 0) { list[i] = c; break; } } static int menu_boot(char *path, char *msg, char *a1, char *a2) { struct string_list newargv; char *errstring = "No memory for argument %d (%s)\n"; init_str(&newargv); if (new_str1(path, &newargv)) { printf(errstring, 0, path); return(ENOMEM); } if (a1 && new_str1(a1, &newargv)) { printf(errstring, 1, a1); return(ENOMEM); } if (a2 && new_str1(a2, &newargv)) { printf(errstring, 2, a2); return(ENOMEM); } if (msg && isGuiMode()) { struct Dialog *d; char buf[128]; /* popup booting message since it can take a while... */ if (instsrc == DEV_REMTAPE || instsrc == DEV_REMDIR) sprintf(buf,"Obtaining %s from %s:%s",msg, getenv("netinsthost"),getenv("netinstfile")); else sprintf(buf,"Obtaining %s",msg); d = _popupDialog(buf,0,DIALOGPROGRESS,DIALOGCENTER); drawObject(guiobj(d)); } #if 0 { int i ; printf("pmenu_cmd: Execute %s, %d\n", path, newargv.strcnt) ; printf("-------------\n") ; for(i=0; newargv.strptrs[i]; i++) printf("%s\n", newargv.strptrs[i]) ; printf("-------------\n") ; printenv_cmd(1, NULL, NULL, NULL) ; } #endif return((int)Execute ((CHAR *)path, (LONG)newargv.strcnt, (CHAR **)newargv.strptrs, (CHAR **)environ)); } static void returnmsg(void) { extern int m_graphics; /* XXX - when GUI is complete graphics case is un-needed */ if (m_graphics) p_printf("Press \001 Esc \006 to return to the menu.\n\n"); else p_printf("Press to return to the menu.\n\n"); }