2 * The new sysinstall program.
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
11 * My contributions are in the public domain.
13 * Parts of this file are also blatantly stolen from Poul-Henning Kamp's
14 * previous version of sysinstall, and as such fall under his "BEERWARE license"
15 * so buy him a beer if you like it! Buy him a beer for me, too!
16 * Heck, get him completely drunk and send me pictures! :-)
19 #include "sysinstall.h"
22 #include <sys/param.h>
23 #include <sys/reboot.h>
24 #include <sys/consio.h>
25 #include <sys/fcntl.h>
26 #include <sys/ioctl.h>
27 #include <sys/mount.h>
29 #include <sys/sysctl.h>
30 #include <ufs/ufs/ufsmount.h>
33 /* Where we stick our temporary expanded doc file */
34 #define DOC_TMP_DIR "/tmp/.doc"
35 #define DOC_TMP_FILE "/tmp/.doc/doc.tmp"
40 * Handle interrupt signals - this probably won't work in all cases
41 * due to our having bogotified the internal state of dialog or curses,
42 * but we'll give it a try.
45 intr_continue(dialogMenuItem *self)
47 return DITEM_LEAVE_MENU;
51 intr_reboot(dialogMenuItem *self)
59 intr_restart(dialogMenuItem *self)
65 fdmax = getdtablesize();
66 for (fd = 3; fd < fdmax; fd++)
68 ret = execl(StartName, StartName, "-restart", (char *)NULL);
69 msgDebug("execl failed (%s)\n", strerror(errno));
74 static dialogMenuItem intrmenu[] = {
75 { "Abort", "Abort the installation", NULL, intr_reboot },
76 { "Restart", "Restart the installation program", NULL, intr_restart },
77 { "Continue", "Continue the installation", NULL, intr_continue },
84 WINDOW *save = savescr();
89 ioctl(0, VT_ACTIVATE, 1); /* Switch back */
92 (void)dialog_menu("Installation interrupt",
93 "Do you want to abort the installation?",
94 -1, -1, 3, -3, intrmenu, NULL, NULL, NULL);
100 * Harvest children if we are init.
103 reap_children(int sig)
107 while (waitpid(-1, NULL, WNOHANG) > 0)
113 /* Expand a file into a convenient location, nuking it each time */
117 char *gunzip = RunningAsInit ? "/stand/gunzip" : "/usr/bin/gunzip";
119 if (!directory_exists(DOC_TMP_DIR)) {
121 if (chown(DOC_TMP_DIR, 0, 0) < 0)
123 if (chmod(DOC_TMP_DIR, S_IRWXU) < 0)
127 unlink(DOC_TMP_FILE);
128 if (!file_readable(fname) || vsystem("%s < %s > %s", gunzip, fname, DOC_TMP_FILE))
133 /* Initialize system defaults */
135 systemInitialize(int argc, char **argv)
141 signal(SIGINT, SIG_IGN);
144 i = sizeof(boothowto);
145 if (!sysctlbyname("debug.boothowto", &boothowto, &i, NULL, 0) &&
146 (i == sizeof(boothowto)) && (boothowto & RB_VERBOSE))
147 variable_set2(VAR_DEBUG, "YES", 0);
149 /* Are we running as init? */
151 struct ufs_args ufs_args;
157 fd = open("/dev/ttyv0", O_RDWR);
159 fd = open("/dev/console", O_RDWR); /* fallback */
160 variable_set2(VAR_FIXIT_TTY, "serial", 0); /* give fixit a hint */
164 * To make _sure_ we're on a VTY and don't have /dev/console switched
165 * away to a serial port or something, attempt to set the cursor appearance.
170 type = 0; /* normal */
171 if ((fd2 = open("/dev/console", O_RDWR)) != -1) {
172 if (ioctl(fd2, CONS_CURSORTYPE, &type) == -1) {
174 variable_set2(VAR_FIXIT_TTY, "serial", 0); /* Tell Fixit
177 close(fd); close(fd2);
178 open("/dev/console", O_RDWR);
186 printf("%s running as init on %s\n", argv[0], OnVTY ? "vty0" : "serial console");
187 ioctl(0, TIOCSCTTY, (char *)NULL);
189 setenv("PATH", "/stand:/bin:/sbin:/usr/sbin:/usr/bin:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin:/usr/X11R6/bin", 1);
194 sysctlbyname("machdep.unaligned_print", NULL, 0, &i, sizeof(i));
197 signal(SIGCHLD, reap_children);
199 memset(&ufs_args, 0, sizeof(ufs_args));
200 mount("ufs", "/", MNT_UPDATE, &ufs_args);
205 /* Initalize various things for a multi-user environment */
206 if (!gethostname(hname, sizeof hname))
207 variable_set2(VAR_HOSTNAME, hname, 0);
210 if (set_termcap() == -1) {
211 printf("Can't find terminal entry\n");
215 /* XXX - libdialog has particularly bad return value checking */
218 /* If we haven't crashed I guess dialog is running ! */
221 /* Make sure HOME is set for those utilities that need it */
223 setenv("HOME", "/", 1);
224 signal(SIGINT, handle_intr);
226 * Make sure we can be interrupted even if we were re-executed
229 sigemptyset(&signalset);
230 sigaddset(&signalset, SIGINT);
231 sigprocmask(SIG_UNBLOCK, &signalset, NULL);
233 (void)vsystem("rm -rf %s", DOC_TMP_DIR);
236 /* Close down and prepare to exit */
238 systemShutdown(int status)
240 /* If some media is open, close it down */
244 /* write out any changes to rc.conf .. */
247 /* Shut down the dialog library */
250 DialogActive = FALSE;
253 /* Shut down curses */
256 /* If we have a temporary doc dir lying around, nuke it */
257 (void)vsystem("rm -rf %s", DOC_TMP_DIR);
261 /* Put the console back */
262 ioctl(0, VT_ACTIVATE, 2);
263 #if defined(__alpha__) || defined(__sparc64__)
273 /* Run some general command */
275 systemExecute(char *command)
279 WINDOW *w = savescr();
284 DialogActive = FALSE;
285 if (tcgetattr(0, &foo) != -1) {
286 foo.c_cc[VERASE] = '\010';
287 tcsetattr(0, TCSANOW, &foo);
290 status = system(command);
293 msgDebug("systemExecute: Faked execution of `%s'\n", command);
300 /* suspend/resume libdialog/curses screen */
304 systemSuspendDialog(void)
311 DialogActive = FALSE;
315 systemResumeDialog(void)
322 /* Display a help file in a filebox */
324 systemDisplayHelp(char *file)
327 char buf[FILENAME_MAX];
329 WINDOW *w = savescr();
331 fname = systemHelpFile(file, buf);
333 snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file);
336 dialog_mesgbox("Sorry!", buf, -1, -1);
342 dialog_textbox(file, fname, LINES, COLS);
349 systemHelpFile(char *file, char *buf)
355 snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp.gz", file);
356 if (file_readable(buf))
358 snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp", file);
359 if (file_readable(buf))
361 snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT.gz", file);
362 if (file_readable(buf))
364 snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT", file);
365 if (file_readable(buf))
367 snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/sysinstall/help/%s.hlp", file);
368 if (file_readable(buf))
370 snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/sysinstall/help/%s.TXT", file);
371 if (file_readable(buf))
377 systemChangeTerminal(char *color, const u_char c_term[],
378 char *mono, const u_char m_term[])
381 int setupterm(char *color, int, int *);
384 setenv("TERM", color, 1);
385 setenv("TERMCAP", c_term, 1);
391 setenv("TERM", mono, 1);
392 setenv("TERMCAP", m_term, 1);
404 vsystem(char *fmt, ...)
410 sig_t intsave, quitsave;
415 cmd = (char *)alloca(FILENAME_MAX);
418 vsnprintf(cmd, FILENAME_MAX, fmt, args);
421 omask = sigblock(sigmask(SIGCHLD));
423 msgDebug("vsystem: Faked execution of `%s'\n", cmd);
427 msgDebug("Executing command `%s'\n", cmd);
430 (void)sigsetmask(omask);
433 else if (!pid) { /* Junior */
434 (void)sigsetmask(omask);
441 close(1); open("/dev/null", O_WRONLY);
444 if (stat("/stand/sh", &sb) == 0)
445 execl("/stand/sh", "/stand/sh", "-c", cmd, (char *)NULL);
447 execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL);
451 intsave = signal(SIGINT, SIG_IGN);
452 quitsave = signal(SIGQUIT, SIG_IGN);
453 pid = waitpid(pid, &pstat, 0);
454 (void)sigsetmask(omask);
455 (void)signal(SIGINT, intsave);
456 (void)signal(SIGQUIT, quitsave);
457 i = (pid == -1) ? -1 : WEXITSTATUS(pstat);
459 msgDebug("Command `%s' returns status of %d\n", cmd, i);
465 systemCreateHoloshell(void)
469 if ((FixItMode || OnVTY) && RunningAsInit) {
474 if (kill(ehs_pid, 0) == 0) {
476 if (msgNoYes("There seems to be an emergency holographic shell\n"
477 "already running on VTY 4.\n\n"
478 "Kill it and start a new one?"))
481 /* try cleaning up as much as possible */
482 (void) kill(ehs_pid, SIGHUP);
484 (void) kill(ehs_pid, SIGKILL);
487 /* avoid too many zombies */
488 (void) waitpid(ehs_pid, &pstat, WNOHANG);
491 if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0)
492 systemSuspendDialog(); /* must be before the fork() */
493 if ((ehs_pid = fork()) == 0) {
496 extern int login_tty(int);
498 ioctl(0, TIOCNOTTY, NULL);
499 for (i = getdtablesize(); i >= 0; --i)
501 if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0)
502 fd = open("/dev/console", O_RDWR);
504 fd = open("/dev/ttyv3", O_RDWR);
505 ioctl(0, TIOCSCTTY, &fd);
509 if (login_tty(fd) == -1)
510 msgDebug("Doctor: I can't set the controlling terminal.\n");
511 signal(SIGTTOU, SIG_IGN);
512 if (tcgetattr(fd, &foo) != -1) {
513 foo.c_cc[VERASE] = '\010';
514 if (tcsetattr(fd, TCSANOW, &foo) == -1)
515 msgDebug("Doctor: I'm unable to set the erase character.\n");
518 msgDebug("Doctor: I'm unable to get the terminal attributes!\n");
519 if (strcmp(variable_get(VAR_FIXIT_TTY), "serial") == 0) {
520 printf("Type ``exit'' in this fixit shell to resume sysinstall.\n\n");
523 execlp("sh", "-sh", 0);
524 msgDebug("Was unable to execute sh for Holographic shell!\n");
528 if (strcmp(variable_get(VAR_FIXIT_TTY), "standard") == 0) {
529 WINDOW *w = savescr();
531 msgNotify("Starting an emergency holographic shell on VTY4");
536 (void)waitpid(ehs_pid, &waitstatus, 0); /* we only wait for
541 systemResumeDialog();