freebsd-nq/usr.sbin/sysinstall/system.c
Jordan K. Hubbard 5214787fd5 OK, I've got two ideas to file in the "really seemed like a good idea
at the time, but on further reflection..." bucket with these changes.

1. Checking the media before frobbing the disks was a fine idea, and
   I wish it could have worked, but that leads to a rather difficult
   situation when you need to mount the media someplace and you're about
   to:

	a) Chroot away from your present root.
	b) Newfs the root to be.

   You're basically screwed since there's no place to stick the mount
   point where it will be found following the newfs/chroot (and eliminating
   the chroot in favor of just using the "root bias" feature would work
   great for the distributions but not the pkg_add calls done by the
   package installer).

2. Automatic timeout handling.  I don't know why, but alarm() frequently
   returns no residual even when the alarm didn't go off, which defies
   the man page but hey, since when was that so unusual?  Take out timeouts
   but retain the code which temporarily replaces the SIGINT handler in
   favor of a more media-specific handler.  This way, at least, if it's hanging
   you can at least whap it.  I think the timeout code would have been losing
   over *really slow* links anyway, so it's probably best that it go.

This should fix NFS, tape & CDROM installs again (serves me right for getting
complacent and using just the FTP installs in my testing).
1997-01-24 19:24:51 +00:00

353 lines
7.7 KiB
C

/*
* The new sysinstall program.
*
* This is probably the last program in the `sysinstall' line - the next
* generation being essentially a complete rewrite.
*
* $FreeBSD$
*
* Jordan Hubbard
*
* My contributions are in the public domain.
*
* Parts of this file are also blatently stolen from Poul-Henning Kamp's
* previous version of sysinstall, and as such fall under his "BEERWARE license"
* so buy him a beer if you like it! Buy him a beer for me, too!
* Heck, get him completely drunk and send me pictures! :-)
*/
#include "sysinstall.h"
#include <signal.h>
#include <sys/reboot.h>
#include <machine/console.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/wait.h>
/* Where we stick our temporary expanded doc file */
#define DOC_TMP_DIR "/tmp"
#define DOC_TMP_FILE "/tmp/doc.tmp"
static pid_t ehs_pid;
/*
* Handle interrupt signals - this probably won't work in all cases
* due to our having bogotified the internal state of dialog or curses,
* but we'll give it a try.
*/
static void
handle_intr(int sig)
{
WINDOW *save = savescr();
if (!msgYesNo("Are you sure you want to abort the installation?"))
systemShutdown(-1);
else
restorescr(save);
}
/* Expand a file into a convenient location, nuking it each time */
static char *
expand(char *fname)
{
Mkdir(DOC_TMP_DIR);
unlink(DOC_TMP_FILE);
if (!file_readable(fname) || vsystem("gzip -c -d %s > %s", fname, DOC_TMP_FILE))
return NULL;
return DOC_TMP_FILE;
}
/* Initialize system defaults */
void
systemInitialize(int argc, char **argv)
{
int i;
signal(SIGINT, SIG_IGN);
globalsInit();
/* Are we running as init? */
if (getpid() == 1) {
setsid();
close(0);
if (open("/dev/ttyv0", O_RDWR) < 0)
open("/dev/console", O_RDWR);
else
OnVTY = TRUE;
close(1); dup(0);
close(2); dup(0);
printf("%s running as init\n", argv[0]);
RunningAsInit = 1;
i = ioctl(0, TIOCSCTTY, (char *)NULL);
setlogin("root");
setenv("PATH", "/stand:/bin:/sbin:/usr/sbin:/usr/bin:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin:/usr/X11R6/bin", 1);
setbuf(stdin, 0);
setbuf(stderr, 0);
}
else {
char hname[256];
/* Initalize various things for a multi-user environment */
if (!gethostname(hname, sizeof hname))
variable_set2(VAR_HOSTNAME, hname);
}
if (set_termcap() == -1) {
printf("Can't find terminal entry\n");
exit(-1);
}
/* XXX - libdialog has particularly bad return value checking */
init_dialog();
/* If we haven't crashed I guess dialog is running ! */
DialogActive = TRUE;
/* Make sure HOME is set for those utilities that need it */
if (!getenv("HOME"))
setenv("HOME", "/", 1);
signal(SIGINT, handle_intr);
}
/* Close down and prepare to exit */
void
systemShutdown(int status)
{
/* If some media is open, close it down */
if (status >=0 && mediaDevice)
mediaDevice->shutdown(mediaDevice);
/* Shut down the dialog library */
if (DialogActive) {
end_dialog();
DialogActive = FALSE;
}
/* Shut down curses */
endwin();
/* If we have a temporary doc file lying around, nuke it */
unlink(DOC_TMP_FILE);
/* REALLY exit! */
if (RunningAsInit) {
/* Put the console back */
ioctl(0, VT_ACTIVATE, 2);
reboot(0);
}
else
exit(status);
}
/* Run some general command */
int
systemExecute(char *command)
{
int status;
struct termios foo;
dialog_update();
end_dialog();
DialogActive = FALSE;
if (tcgetattr(0, &foo) != -1) {
foo.c_cc[VERASE] = '\010';
tcsetattr(0, TCSANOW, &foo);
}
if (!Fake)
status = system(command);
else {
status = 0;
msgDebug("systemExecute: Faked execution of `%s'\n", command);
}
DialogActive = TRUE;
return status;
}
/* Display a help file in a filebox */
int
systemDisplayHelp(char *file)
{
char *fname = NULL;
char buf[FILENAME_MAX];
int ret = 0;
fname = systemHelpFile(file, buf);
if (!fname) {
snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file);
use_helpfile(NULL);
use_helpline(NULL);
dialog_mesgbox("Sorry!", buf, -1, -1);
ret = 1;
}
else {
use_helpfile(NULL);
use_helpline(NULL);
dialog_textbox(file, fname, LINES, COLS);
}
return ret;
}
char *
systemHelpFile(char *file, char *buf)
{
if (!file)
return NULL;
snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp.gz", file);
if (file_readable(buf))
return expand(buf);
snprintf(buf, FILENAME_MAX, "/usr/src/release/sysinstall/help/%s.hlp", file);
if (file_readable(buf))
return buf;
return NULL;
}
void
systemChangeTerminal(char *color, const u_char c_term[],
char *mono, const u_char m_term[])
{
extern void init_acs(void);
if (OnVTY) {
if (ColorDisplay) {
setenv("TERM", color, 1);
setenv("TERMCAP", c_term, 1);
reset_shell_mode();
setterm(color);
init_acs();
cbreak(); noecho();
}
else {
setenv("TERM", mono, 1);
setenv("TERMCAP", m_term, 1);
reset_shell_mode();
setterm(mono);
init_acs();
cbreak(); noecho();
}
}
clear();
refresh();
dialog_clear();
}
int
vsystem(char *fmt, ...)
{
va_list args;
int pstat;
pid_t pid;
int omask;
sig_t intsave, quitsave;
char *cmd;
int i;
cmd = (char *)alloca(FILENAME_MAX);
cmd[0] = '\0';
va_start(args, fmt);
vsnprintf(cmd, FILENAME_MAX, fmt, args);
va_end(args);
omask = sigblock(sigmask(SIGCHLD));
if (Fake) {
msgDebug("vsystem: Faked execution of `%s'\n", cmd);
return 0;
}
if (isDebug())
msgDebug("Executing command `%s'\n", cmd);
pid = fork();
if (pid == -1) {
(void)sigsetmask(omask);
i = 127;
}
else if (!pid) { /* Junior */
(void)sigsetmask(omask);
if (DebugFD != -1) {
dup2(DebugFD, 0);
dup2(DebugFD, 1);
dup2(DebugFD, 2);
}
else {
close(1); open("/dev/null", O_WRONLY);
dup2(1, 2);
}
if (!RunningAsInit)
execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL);
else
execl("/stand/sh", "/stand/sh", "-c", cmd, (char *)NULL);
exit(1);
}
else {
intsave = signal(SIGINT, SIG_IGN);
quitsave = signal(SIGQUIT, SIG_IGN);
pid = waitpid(pid, &pstat, 0);
(void)sigsetmask(omask);
(void)signal(SIGINT, intsave);
(void)signal(SIGQUIT, quitsave);
i = (pid == -1) ? -1 : WEXITSTATUS(pstat);
if (isDebug())
msgDebug("Command `%s' returns status of %d\n", cmd, i);
}
return i;
}
void
systemCreateHoloshell(void)
{
if (OnVTY && RunningAsInit) {
if (ehs_pid != 0) {
int pstat;
if (kill(ehs_pid, 0) == 0) {
if (msgYesNo("There seems to be an emergency holographic shell\n"
"already running von VTY 4.\n"
"Kill it and start a new one?"))
return;
/* try cleaning up as much as possible */
(void) kill(ehs_pid, SIGHUP);
sleep(1);
(void) kill(ehs_pid, SIGKILL);
}
/* avoid too many zombies */
(void) waitpid(ehs_pid, &pstat, WNOHANG);
}
if ((ehs_pid = fork()) == 0) {
int i, fd;
struct termios foo;
extern int login_tty(int);
ioctl(0, TIOCNOTTY, NULL);
for (i = getdtablesize(); i >= 0; --i)
close(i);
fd = open("/dev/ttyv3", O_RDWR);
ioctl(0, TIOCSCTTY, &fd);
dup2(0, 1);
dup2(0, 2);
DebugFD = 2;
if (login_tty(fd) == -1)
msgDebug("Doctor: I can't set the controlling terminal.\n");
signal(SIGTTOU, SIG_IGN);
if (tcgetattr(fd, &foo) != -1) {
foo.c_cc[VERASE] = '\010';
if (tcsetattr(fd, TCSANOW, &foo) == -1)
msgDebug("Doctor: I'm unable to set the erase character.\n");
}
else
msgDebug("Doctor: I'm unable to get the terminal attributes!\n");
execlp("sh", "-sh", 0);
msgDebug("Was unable to execute sh for Holographic shell!\n");
exit(1);
}
else {
msgNotify("Starting an emergency holographic shell on VTY4");
sleep(2);
}
}
}