freebsd-dev/usr.sbin/sade/system.c
Alexander Leidinger 2e14ff0f41 Say welcome to 'sade', the SysAdmins Disk Editor. It's the fdisk and disklabel part
of sysinstall. So sysinstall may retire now, we have the important non-install part
of it covered.

ATM it doesn't understand GEOM stuff (like mirror, stripe, raid, ...), but patches
to change this and to clean it up internally are more than welcome.

Submitted by:	mami@nyitolap.hu
2006-08-07 23:35:49 +00:00

337 lines
7.4 KiB
C

/*
* $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 "sade.h"
#include <signal.h>
#include <termios.h>
#include <sys/param.h>
#include <sys/reboot.h>
#include <sys/consio.h>
#include <sys/fcntl.h>
#include <sys/ioctl.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/sysctl.h>
#include <ufs/ufs/ufsmount.h>
/* Where we stick our temporary expanded doc file */
#define DOC_TMP_DIR "/tmp/.doc"
#define DOC_TMP_FILE "/tmp/.doc/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 int
intr_continue(dialogMenuItem *self)
{
return DITEM_LEAVE_MENU;
}
static int
intr_restart(dialogMenuItem *self)
{
int ret, fd, fdmax;
free_variables();
fdmax = getdtablesize();
for (fd = 3; fd < fdmax; fd++)
close(fd);
ret = execl(StartName, StartName, "-restart", (char *)NULL);
msgDebug("execl failed (%s)\n", strerror(errno));
/* NOTREACHED */
return -1;
}
static dialogMenuItem intrmenu[] = {
{ "Restart", "Restart the program", NULL, intr_restart },
{ "Continue", "Continue without restarting", NULL, intr_continue },
};
static void
handle_intr(int sig)
{
WINDOW *save = savescr();
use_helpline(NULL);
use_helpfile(NULL);
if (OnVTY) {
ioctl(0, VT_ACTIVATE, 1); /* Switch back */
msgInfo(NULL);
}
(void)dialog_menu("Installation interrupt",
"Do you want to abort the installation?",
-1, -1, 2, -2, intrmenu, NULL, NULL, NULL);
restorescr(save);
}
/* Expand a file into a convenient location, nuking it each time */
static char *
expand(char *fname)
{
char *gunzip = "/usr/bin/gunzip";
if (!directory_exists(DOC_TMP_DIR)) {
Mkdir(DOC_TMP_DIR);
if (chown(DOC_TMP_DIR, 0, 0) < 0)
return NULL;
if (chmod(DOC_TMP_DIR, S_IRWXU) < 0)
return NULL;
}
else
unlink(DOC_TMP_FILE);
if (!file_readable(fname) || vsystem("%s < %s > %s", gunzip, fname, DOC_TMP_FILE))
return NULL;
return DOC_TMP_FILE;
}
/* Initialize system defaults */
void
systemInitialize(int argc, char **argv)
{
size_t i;
int boothowto;
sigset_t signalset;
signal(SIGINT, SIG_IGN);
globalsInit();
i = sizeof(boothowto);
if (!sysctlbyname("debug.boothowto", &boothowto, &i, NULL, 0) &&
(i == sizeof(boothowto)) && (boothowto & RB_VERBOSE))
variable_set2(VAR_DEBUG, "YES", 0);
char hname[256];
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 */
signal(SIGINT, handle_intr);
/*
* Make sure we can be interrupted even if we were re-executed
* from an interrupt.
*/
sigemptyset(&signalset);
sigaddset(&signalset, SIGINT);
sigprocmask(SIG_UNBLOCK, &signalset, NULL);
(void)vsystem("rm -rf %s", DOC_TMP_DIR);
}
/* Run some general command */
int
systemExecute(char *command)
{
int status;
struct termios foo;
WINDOW *w = savescr();
dialog_clear();
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;
restorescr(w);
return status;
}
/* suspend/resume libdialog/curses screen */
static WINDOW *oldW;
void
systemSuspendDialog(void)
{
oldW = savescr();
dialog_clear();
dialog_update();
end_dialog();
DialogActive = FALSE;
}
void
systemResumeDialog(void)
{
DialogActive = TRUE;
restorescr(oldW);
}
/* Display a help file in a filebox */
int
systemDisplayHelp(char *file)
{
char *fname = NULL;
char buf[FILENAME_MAX];
int ret = 0;
WINDOW *w = savescr();
printf("zzz");
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);
}
restorescr(w);
return ret;
}
char *
systemHelpFile(char *file, char *buf)
{
if (!file)
return NULL;
if (file[0] == '/')
return file;
snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp.gz", file);
if (file_readable(buf))
return expand(buf);
snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp", file);
if (file_readable(buf))
return expand(buf);
snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT.gz", file);
if (file_readable(buf))
return expand(buf);
snprintf(buf, FILENAME_MAX, "/stand/help/%s.TXT", file);
if (file_readable(buf))
return expand(buf);
snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/sade/help/%s.hlp", file);
if (file_readable(buf))
return buf;
snprintf(buf, FILENAME_MAX, "/usr/src/usr.sbin/sade/help/%s.TXT", 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[])
{
if (OnVTY) {
int setupterm(char *color, int, int *);
if (ColorDisplay) {
setenv("TERM", color, 1);
setenv("TERMCAP", c_term, 1);
reset_shell_mode();
setterm(color);
cbreak(); noecho();
}
else {
setenv("TERM", mono, 1);
setenv("TERMCAP", m_term, 1);
reset_shell_mode();
setterm(mono);
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;
struct stat sb;
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 (stat("/stand/sh", &sb) == 0)
execl("/stand/sh", "/stand/sh", "-c", cmd, (char *)NULL);
else
execl("/bin/sh", "/bin/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;
}