18097Sjkh/* 28097Sjkh * The new sysinstall program. 38097Sjkh * 48097Sjkh * This is probably the last program in the `sysinstall' line - the next 58097Sjkh * generation being essentially a complete rewrite. 68097Sjkh * 750479Speter * $FreeBSD$ 88097Sjkh * 98097Sjkh * Jordan Hubbard 108097Sjkh * 118097Sjkh * My contributions are in the public domain. 128097Sjkh * 13155347Sceri * Parts of this file are also blatantly stolen from Poul-Henning Kamp's 148629Sjkh * previous version of sysinstall, and as such fall under his "BEERWARE license" 158629Sjkh * so buy him a beer if you like it! Buy him a beer for me, too! 168629Sjkh * Heck, get him completely drunk and send me pictures! :-) 178097Sjkh */ 188097Sjkh 198097Sjkh#include "sysinstall.h" 208097Sjkh#include <signal.h> 2150917Sjkh#include <termios.h> 22123686Sjhb#include <sys/param.h> 238097Sjkh#include <sys/reboot.h> 2466834Sphk#include <sys/consio.h> 258097Sjkh#include <sys/fcntl.h> 268097Sjkh#include <sys/ioctl.h> 27123686Sjhb#include <sys/mount.h> 2842392Sjkh#include <sys/stat.h> 2958547Sjhb#include <sys/sysctl.h> 30123686Sjhb#include <ufs/ufs/ufsmount.h> 318097Sjkh 3216975Sjkh 3316975Sjkh/* Where we stick our temporary expanded doc file */ 3442392Sjkh#define DOC_TMP_DIR "/tmp/.doc" 3542392Sjkh#define DOC_TMP_FILE "/tmp/.doc/doc.tmp" 3616975Sjkh 3721010Sjkhstatic pid_t ehs_pid; 3821010Sjkh 398302Sjkh/* 408302Sjkh * Handle interrupt signals - this probably won't work in all cases 418302Sjkh * due to our having bogotified the internal state of dialog or curses, 428302Sjkh * but we'll give it a try. 438302Sjkh */ 4467862Seivindstatic int 4567862Seivindintr_continue(dialogMenuItem *self) 4667862Seivind{ 4783440Smurray return DITEM_LEAVE_MENU; 4867862Seivind} 4967862Seivind 5067862Seivindstatic int 5167862Seivindintr_reboot(dialogMenuItem *self) 5267862Seivind{ 5383440Smurray systemShutdown(-1); 5483440Smurray /* NOTREACHED */ 5583440Smurray return 0; 5667862Seivind} 5767862Seivind 5867862Seivindstatic int 5967862Seivindintr_restart(dialogMenuItem *self) 6067862Seivind{ 6184152Smurray int ret, fd, fdmax; 62211417Sbrucec char *arg; 6384152Smurray 6484152Smurray mediaClose(); 6583820Smurray free_variables(); 6684152Smurray fdmax = getdtablesize(); 6784152Smurray for (fd = 3; fd < fdmax; fd++) 6884152Smurray close(fd); 69211417Sbrucec 70211417Sbrucec if (RunningAsInit) 71211417Sbrucec arg = "-restart -fakeInit"; 72211417Sbrucec else 73211417Sbrucec arg = "-restart"; 74211417Sbrucec 75211417Sbrucec ret = execl(StartName, StartName, arg, NULL); 7683820Smurray msgDebug("execl failed (%s)\n", strerror(errno)); 7783440Smurray /* NOTREACHED */ 7883440Smurray return -1; 7967862Seivind} 8067862Seivind 8167862Seivindstatic dialogMenuItem intrmenu[] = { 8283440Smurray { "Abort", "Abort the installation", NULL, intr_reboot }, 8383440Smurray { "Restart", "Restart the installation program", NULL, intr_restart }, 8483440Smurray { "Continue", "Continue the installation", NULL, intr_continue }, 8567862Seivind}; 8667862Seivind 8767862Seivind 888097Sjkhstatic void 898097Sjkhhandle_intr(int sig) 908097Sjkh{ 9118619Sjkh WINDOW *save = savescr(); 9218619Sjkh 9367862Seivind use_helpline(NULL); 9467862Seivind use_helpfile(NULL); 9567862Seivind if (OnVTY) { 9667862Seivind ioctl(0, VT_ACTIVATE, 1); /* Switch back */ 9767862Seivind msgInfo(NULL); 9867862Seivind } 9967862Seivind (void)dialog_menu("Installation interrupt", 10067862Seivind "Do you want to abort the installation?", 10167862Seivind -1, -1, 3, -3, intrmenu, NULL, NULL, NULL); 10267862Seivind restorescr(save); 1038097Sjkh} 1048097Sjkh 105156119Sjhb#if 0 10683142Smurray/* 10783142Smurray * Harvest children if we are init. 10883142Smurray */ 10983142Smurraystatic void 11083142Smurrayreap_children(int sig) 11183142Smurray{ 11283142Smurray int errbak = errno; 11383440Smurray 11483440Smurray while (waitpid(-1, NULL, WNOHANG) > 0) 11583142Smurray ; 11683142Smurray errno = errbak; 11783142Smurray} 118156119Sjhb#endif 11983142Smurray 12016975Sjkh/* Expand a file into a convenient location, nuking it each time */ 12116975Sjkhstatic char * 12216975Sjkhexpand(char *fname) 12316975Sjkh{ 124174473Sobrien char *unzipper = RunningAsInit ? "/stand/" UNZIPPER : "/usr/bin/" UNZIPPER; 12539814Sjkh 12642392Sjkh if (!directory_exists(DOC_TMP_DIR)) { 12742392Sjkh Mkdir(DOC_TMP_DIR); 12842392Sjkh if (chown(DOC_TMP_DIR, 0, 0) < 0) 12942392Sjkh return NULL; 13042392Sjkh if (chmod(DOC_TMP_DIR, S_IRWXU) < 0) 13142392Sjkh return NULL; 13242392Sjkh } 13342392Sjkh else 13442392Sjkh unlink(DOC_TMP_FILE); 135174473Sobrien if (!file_readable(fname) || vsystem("%s < %s > %s", unzipper, fname, 136174473Sobrien DOC_TMP_FILE)) 13716975Sjkh return NULL; 13816975Sjkh return DOC_TMP_FILE; 13916975Sjkh} 14016975Sjkh 1418097Sjkh/* Initialize system defaults */ 1428097Sjkhvoid 1438097SjkhsystemInitialize(int argc, char **argv) 1448097Sjkh{ 14583843Smurray size_t i; 14683843Smurray int boothowto; 14767862Seivind sigset_t signalset; 14848929Sjkh 1498097Sjkh signal(SIGINT, SIG_IGN); 1508097Sjkh globalsInit(); 1518097Sjkh 15257490Sjkh i = sizeof(boothowto); 153126844Sbde if (!sysctlbyname("debug.boothowto", &boothowto, &i, NULL, 0) && 15457490Sjkh (i == sizeof(boothowto)) && (boothowto & RB_VERBOSE)) 15557490Sjkh variable_set2(VAR_DEBUG, "YES", 0); 15657490Sjkh 1578097Sjkh /* Are we running as init? */ 158211417Sbrucec if (RunningAsInit) { 159123686Sjhb struct ufs_args ufs_args; 16085366Sjhb int fd; 16127798Sjkh 1628097Sjkh setsid(); 16318502Spst close(0); 16427798Sjkh fd = open("/dev/ttyv0", O_RDWR); 16568012Sjkh if (fd == -1) { 16627798Sjkh fd = open("/dev/console", O_RDWR); /* fallback */ 16768012Sjkh variable_set2(VAR_FIXIT_TTY, "serial", 0); /* give fixit a hint */ 16868012Sjkh } else 16918502Spst OnVTY = TRUE; 17027798Sjkh /* 17127798Sjkh * To make _sure_ we're on a VTY and don't have /dev/console switched 17227798Sjkh * away to a serial port or something, attempt to set the cursor appearance. 17327798Sjkh */ 17427798Sjkh if (OnVTY) { 17585366Sjhb int fd2, type; 17627798Sjkh 17785366Sjhb type = 0; /* normal */ 17827798Sjkh if ((fd2 = open("/dev/console", O_RDWR)) != -1) { 17927798Sjkh if (ioctl(fd2, CONS_CURSORTYPE, &type) == -1) { 18027798Sjkh OnVTY = FALSE; 18168012Sjkh variable_set2(VAR_FIXIT_TTY, "serial", 0); /* Tell Fixit 18268012Sjkh the console 18368012Sjkh type */ 18427798Sjkh close(fd); close(fd2); 18527798Sjkh open("/dev/console", O_RDWR); 18627798Sjkh } 18727798Sjkh else 18827798Sjkh close(fd2); 18927798Sjkh } 19027798Sjkh } 1919202Srgrimes close(1); dup(0); 1929202Srgrimes close(2); dup(0); 19327798Sjkh printf("%s running as init on %s\n", argv[0], OnVTY ? "vty0" : "serial console"); 19450780Sjkh ioctl(0, TIOCSCTTY, (char *)NULL); 1958097Sjkh setlogin("root"); 196186152Skensmith setenv("PATH", "/stand:/bin:/sbin:/usr/sbin:/usr/bin:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin", 1); 1978097Sjkh setbuf(stdin, 0); 1988097Sjkh setbuf(stderr, 0); 19985847Sjkh#if 0 20083142Smurray signal(SIGCHLD, reap_children); 20185847Sjkh#endif 202123686Sjhb memset(&ufs_args, 0, sizeof(ufs_args)); 203123686Sjhb mount("ufs", "/", MNT_UPDATE, &ufs_args); 2048097Sjkh } 20520335Sjkh else { 20620335Sjkh char hname[256]; 2078097Sjkh 20820335Sjkh /* Initalize various things for a multi-user environment */ 20920335Sjkh if (!gethostname(hname, sizeof hname)) 21044017Sjkh variable_set2(VAR_HOSTNAME, hname, 0); 21120335Sjkh } 21220335Sjkh 2138418Sjkh if (set_termcap() == -1) { 2148418Sjkh printf("Can't find terminal entry\n"); 2158418Sjkh exit(-1); 2168418Sjkh } 2178097Sjkh 2188097Sjkh /* XXX - libdialog has particularly bad return value checking */ 2198097Sjkh init_dialog(); 22015383Sjkh 2218097Sjkh /* If we haven't crashed I guess dialog is running ! */ 2228097Sjkh DialogActive = TRUE; 2238097Sjkh 22412661Speter /* Make sure HOME is set for those utilities that need it */ 22512661Speter if (!getenv("HOME")) 22612661Speter setenv("HOME", "/", 1); 2278097Sjkh signal(SIGINT, handle_intr); 22867862Seivind /* 22967862Seivind * Make sure we can be interrupted even if we were re-executed 23067862Seivind * from an interrupt. 23167862Seivind */ 23267862Seivind sigemptyset(&signalset); 23367862Seivind sigaddset(&signalset, SIGINT); 23467862Seivind sigprocmask(SIG_UNBLOCK, &signalset, NULL); 23567862Seivind 23642392Sjkh (void)vsystem("rm -rf %s", DOC_TMP_DIR); 2378097Sjkh} 2388097Sjkh 2398097Sjkh/* Close down and prepare to exit */ 2408097Sjkhvoid 24115788SjkhsystemShutdown(int status) 2428097Sjkh{ 24315788Sjkh /* If some media is open, close it down */ 244186131Skensmith if (status >=0) { 245186131Skensmith if (mediaDevice != NULL && mediaDevice->type == DEVICE_TYPE_CDROM) { 246186131Skensmith mediaClose(); 247186131Skensmith msgConfirm("Be sure to remove the media from the drive."); 248186131Skensmith } else 249186131Skensmith mediaClose(); 250186131Skensmith } 25115788Sjkh 25225251Sjkh /* write out any changes to rc.conf .. */ 25343811Sjkh configRC_conf(); 25422549Sjkh 25515788Sjkh /* Shut down the dialog library */ 2568097Sjkh if (DialogActive) { 2578097Sjkh end_dialog(); 2588097Sjkh DialogActive = FALSE; 2598097Sjkh } 26015788Sjkh 26115788Sjkh /* Shut down curses */ 26215788Sjkh endwin(); 26315788Sjkh 26442392Sjkh /* If we have a temporary doc dir lying around, nuke it */ 26542392Sjkh (void)vsystem("rm -rf %s", DOC_TMP_DIR); 26616975Sjkh 2678097Sjkh /* REALLY exit! */ 2688774Sjkh if (RunningAsInit) { 2698774Sjkh /* Put the console back */ 2709202Srgrimes ioctl(0, VT_ACTIVATE, 2); 271186075Skensmith#if defined(__sparc64__) 27242386Sjkh reboot(RB_HALT); 27342386Sjkh#else 274166927Sceri reboot(RB_AUTOBOOT); 27542386Sjkh#endif 2768774Sjkh } 2778174Sjkh else 27815788Sjkh exit(status); 2798097Sjkh} 2808097Sjkh 2818174Sjkh/* Run some general command */ 2828097Sjkhint 2838097SjkhsystemExecute(char *command) 2848097Sjkh{ 2858097Sjkh int status; 28612661Speter struct termios foo; 28754587Sjkh WINDOW *w = savescr(); 2888097Sjkh 28954587Sjkh dialog_clear(); 2908097Sjkh dialog_update(); 2918097Sjkh end_dialog(); 2928097Sjkh DialogActive = FALSE; 29312661Speter if (tcgetattr(0, &foo) != -1) { 29412661Speter foo.c_cc[VERASE] = '\010'; 29512661Speter tcsetattr(0, TCSANOW, &foo); 29612661Speter } 29715439Sjkh if (!Fake) 29815439Sjkh status = system(command); 29915439Sjkh else { 30015439Sjkh status = 0; 30115439Sjkh msgDebug("systemExecute: Faked execution of `%s'\n", command); 30215439Sjkh } 3038097Sjkh DialogActive = TRUE; 30454587Sjkh restorescr(w); 3058097Sjkh return status; 3068097Sjkh} 3078097Sjkh 30863404Sobrien/* suspend/resume libdialog/curses screen */ 30963404Sobrienstatic WINDOW *oldW; 31063404Sobrien 31163404Sobrienvoid 31263404SobriensystemSuspendDialog(void) 31363404Sobrien{ 31463404Sobrien 31563404Sobrien oldW = savescr(); 31663404Sobrien dialog_clear(); 31763404Sobrien dialog_update(); 31863404Sobrien end_dialog(); 31963404Sobrien DialogActive = FALSE; 32063404Sobrien} 32163404Sobrien 32263404Sobrienvoid 32363404SobriensystemResumeDialog(void) 32463404Sobrien{ 32563404Sobrien 32663404Sobrien DialogActive = TRUE; 32763404Sobrien restorescr(oldW); 32863404Sobrien} 32963404Sobrien 33012661Speter/* Display a help file in a filebox */ 3318174Sjkhint 33212661SpetersystemDisplayHelp(char *file) 3338174Sjkh{ 3348208Sjkh char *fname = NULL; 3358208Sjkh char buf[FILENAME_MAX]; 33615393Sjkh int ret = 0; 33754587Sjkh WINDOW *w = savescr(); 33854587Sjkh 3398208Sjkh fname = systemHelpFile(file, buf); 3408174Sjkh if (!fname) { 3418174Sjkh snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file); 3428208Sjkh use_helpfile(NULL); 3438208Sjkh use_helpline(NULL); 3448208Sjkh dialog_mesgbox("Sorry!", buf, -1, -1); 34515393Sjkh ret = 1; 3468174Sjkh } 3478174Sjkh else { 3488208Sjkh use_helpfile(NULL); 3498208Sjkh use_helpline(NULL); 3508174Sjkh dialog_textbox(file, fname, LINES, COLS); 3518174Sjkh } 35254587Sjkh restorescr(w); 35315393Sjkh return ret; 3548174Sjkh} 3558208Sjkh 3568208Sjkhchar * 3578208SjkhsystemHelpFile(char *file, char *buf) 3588208Sjkh{ 3598208Sjkh if (!file) 3608208Sjkh return NULL; 36157490Sjkh if (file[0] == '/') 36257490Sjkh return file; 36316975Sjkh snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp.gz", file); 36410882Speter if (file_readable(buf)) 36516975Sjkh return expand(buf); 366101562Sjhay snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp", file); 367101562Sjhay if (file_readable(buf)) 368101562Sjhay return expand(buf); 36940841Sjkh snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT.gz", file); 37040841Sjkh if (file_readable(buf)) 37140841Sjkh return expand(buf); 372101562Sjhay snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT", file); 373101562Sjhay if (file_readable(buf)) 374101562Sjhay return expand(buf); 375178946Sobrien snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/%s/help/%s.hlp", ProgName, 376178941Sobrien file); 37715788Sjkh if (file_readable(buf)) 37815788Sjkh return buf; 379178946Sobrien snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/%s/help/%s.TXT", ProgName, 380178941Sobrien file); 38140841Sjkh if (file_readable(buf)) 38240841Sjkh return buf; 3838829Sphk return NULL; 3848208Sjkh} 3858278Sjkh 3868278Sjkhvoid 3878302SjkhsystemChangeTerminal(char *color, const u_char c_term[], 3888302Sjkh char *mono, const u_char m_term[]) 3898278Sjkh{ 3908601Sjkh if (OnVTY) { 39154473Sjkh int setupterm(char *color, int, int *); 39254473Sjkh 3938302Sjkh if (ColorDisplay) { 3948302Sjkh setenv("TERM", color, 1); 3958302Sjkh setenv("TERMCAP", c_term, 1); 3968601Sjkh reset_shell_mode(); 3978601Sjkh setterm(color); 3988601Sjkh cbreak(); noecho(); 3998302Sjkh } 4008302Sjkh else { 4018302Sjkh setenv("TERM", mono, 1); 4028302Sjkh setenv("TERMCAP", m_term, 1); 4038601Sjkh reset_shell_mode(); 4048601Sjkh setterm(mono); 4058601Sjkh cbreak(); noecho(); 4068302Sjkh } 4078302Sjkh } 4089202Srgrimes clear(); 4099202Srgrimes refresh(); 4109202Srgrimes dialog_clear(); 4118278Sjkh} 4128278Sjkh 4138658Sphkint 4148658Sphkvsystem(char *fmt, ...) 4158658Sphk{ 4168658Sphk va_list args; 4178768Sjkh int pstat; 4188658Sphk pid_t pid; 4198658Sphk int omask; 4208658Sphk sig_t intsave, quitsave; 42112661Speter char *cmd; 42212661Speter int i; 423148734Skensmith struct stat sb; 4248629Sjkh 42515417Sjkh cmd = (char *)alloca(FILENAME_MAX); 4268658Sphk cmd[0] = '\0'; 4278658Sphk va_start(args, fmt); 4288658Sphk vsnprintf(cmd, FILENAME_MAX, fmt, args); 4298658Sphk va_end(args); 4308837Sjkh 4318658Sphk omask = sigblock(sigmask(SIGCHLD)); 43215439Sjkh if (Fake) { 43315439Sjkh msgDebug("vsystem: Faked execution of `%s'\n", cmd); 43415439Sjkh return 0; 43515439Sjkh } 4368837Sjkh if (isDebug()) 43712661Speter msgDebug("Executing command `%s'\n", cmd); 43812661Speter pid = fork(); 43912661Speter if (pid == -1) { 4408658Sphk (void)sigsetmask(omask); 4418658Sphk i = 127; 44212661Speter } 44312661Speter else if (!pid) { /* Junior */ 4448658Sphk (void)sigsetmask(omask); 4458658Sphk if (DebugFD != -1) { 4468658Sphk dup2(DebugFD, 0); 4478658Sphk dup2(DebugFD, 1); 4488658Sphk dup2(DebugFD, 2); 4498658Sphk } 45015419Sjkh else { 45115419Sjkh close(1); open("/dev/null", O_WRONLY); 45215419Sjkh dup2(1, 2); 45315419Sjkh } 454148734Skensmith if (stat("/stand/sh", &sb) == 0) 455137883Sobrien execl("/stand/sh", "/stand/sh", "-c", cmd, (char *)NULL); 456137883Sobrien else 45715419Sjkh execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL); 45812661Speter exit(1); 45912661Speter } 46012661Speter else { 46112661Speter intsave = signal(SIGINT, SIG_IGN); 46212661Speter quitsave = signal(SIGQUIT, SIG_IGN); 46312661Speter pid = waitpid(pid, &pstat, 0); 46412661Speter (void)sigsetmask(omask); 46512661Speter (void)signal(SIGINT, intsave); 46612661Speter (void)signal(SIGQUIT, quitsave); 46712661Speter i = (pid == -1) ? -1 : WEXITSTATUS(pstat); 46812661Speter if (isDebug()) 46912661Speter msgDebug("Command `%s' returns status of %d\n", cmd, i); 47012661Speter } 47112661Speter return i; 47212661Speter} 47312661Speter 47412661Spetervoid 47512661SpetersystemCreateHoloshell(void) 47612661Speter{ 47763404Sobrien int waitstatus; 47821010Sjkh 47963404Sobrien if ((FixItMode || OnVTY) && RunningAsInit) { 48063404Sobrien 48121010Sjkh if (ehs_pid != 0) { 48221010Sjkh int pstat; 48321010Sjkh 48421010Sjkh if (kill(ehs_pid, 0) == 0) { 48521010Sjkh 48670005Sjkh if (msgNoYes("There seems to be an emergency holographic shell\n" 48750780Sjkh "already running on VTY 4.\n\n" 48821010Sjkh "Kill it and start a new one?")) 48921010Sjkh return; 49021010Sjkh 49121010Sjkh /* try cleaning up as much as possible */ 49221010Sjkh (void) kill(ehs_pid, SIGHUP); 49321010Sjkh sleep(1); 49421010Sjkh (void) kill(ehs_pid, SIGKILL); 49521010Sjkh } 49621010Sjkh 49721010Sjkh /* avoid too many zombies */ 49821010Sjkh (void) waitpid(ehs_pid, &pstat, WNOHANG); 49921010Sjkh } 50021010Sjkh 50168012Sjkh if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) 50263404Sobrien systemSuspendDialog(); /* must be before the fork() */ 50321010Sjkh if ((ehs_pid = fork()) == 0) { 50412661Speter int i, fd; 50512661Speter struct termios foo; 50612661Speter extern int login_tty(int); 50712661Speter 50820335Sjkh ioctl(0, TIOCNOTTY, NULL); 50920354Sjkh for (i = getdtablesize(); i >= 0; --i) 51012661Speter close(i); 51168012Sjkh if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) 51268012Sjkh fd = open("/dev/console", O_RDWR); 51368012Sjkh else 51463404Sobrien fd = open("/dev/ttyv3", O_RDWR); 51512661Speter ioctl(0, TIOCSCTTY, &fd); 51612661Speter dup2(0, 1); 51712661Speter dup2(0, 2); 51820335Sjkh DebugFD = 2; 51912661Speter if (login_tty(fd) == -1) 52012661Speter msgDebug("Doctor: I can't set the controlling terminal.\n"); 52112661Speter signal(SIGTTOU, SIG_IGN); 52212661Speter if (tcgetattr(fd, &foo) != -1) { 52312661Speter foo.c_cc[VERASE] = '\010'; 52412661Speter if (tcsetattr(fd, TCSANOW, &foo) == -1) 52512661Speter msgDebug("Doctor: I'm unable to set the erase character.\n"); 5268837Sjkh } 5278837Sjkh else 52812661Speter msgDebug("Doctor: I'm unable to get the terminal attributes!\n"); 52968012Sjkh if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) { 53063404Sobrien printf("Type ``exit'' in this fixit shell to resume sysinstall.\n\n"); 53163404Sobrien fflush(stdout); 53263404Sobrien } 533209069Srandi execlp("sh", "-sh", NULL); 53412661Speter msgDebug("Was unable to execute sh for Holographic shell!\n"); 53512661Speter exit(1); 5368589Sjkh } 53715458Sjkh else { 53868012Sjkh if (strcmp(variable_get(VAR_FIXIT_TTY), "standard") == 0) { 53963404Sobrien WINDOW *w = savescr(); 54054722Sjkh 54163404Sobrien msgNotify("Starting an emergency holographic shell on VTY4"); 54263404Sobrien sleep(2); 54363404Sobrien restorescr(w); 54463404Sobrien } 54568012Sjkh else { 54668012Sjkh (void)waitpid(ehs_pid, &waitstatus, 0); /* we only wait for 54768012Sjkh shell to finish 548171027Sphilip in serial mode 54968012Sjkh since there is no 55068012Sjkh virtual console */ 55163404Sobrien systemResumeDialog(); 55263404Sobrien } 55315458Sjkh } 5548584Sjkh } 5558307Sjkh} 556