system.c revision 16975
1/*
2 * The new sysinstall program.
3 *
4 * This is probably the last program in the `sysinstall' line - the next
5 * generation being essentially a complete rewrite.
6 *
7 * $Id: system.c,v 1.59 1996/05/16 11:47:46 jkh Exp $
8 *
9 * Jordan Hubbard
10 *
11 * My contributions are in the public domain.
12 *
13 * Parts of this file are also blatently 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! :-)
17 */
18
19#include "sysinstall.h"
20#include <signal.h>
21#include <sys/reboot.h>
22#include <machine/console.h>
23#include <sys/fcntl.h>
24#include <sys/ioctl.h>
25#include <sys/wait.h>
26
27
28/* Where we stick our temporary expanded doc file */
29#define	DOC_TMP_FILE	"/tmp/doc.tmp"
30
31/*
32 * Handle interrupt signals - this probably won't work in all cases
33 * due to our having bogotified the internal state of dialog or curses,
34 * but we'll give it a try.
35 */
36static void
37handle_intr(int sig)
38{
39    if (!msgYesNo("Are you sure you want to abort the installation?"))
40	systemShutdown(1);
41}
42
43/* Expand a file into a convenient location, nuking it each time */
44static char *
45expand(char *fname)
46{
47    unlink(DOC_TMP_FILE);
48    if (vsystem("gzip -c -d %s > %s", fname, DOC_TMP_FILE))
49	return NULL;
50    return DOC_TMP_FILE;
51}
52
53/* Initialize system defaults */
54void
55systemInitialize(int argc, char **argv)
56{
57    int i;
58
59    signal(SIGINT, SIG_IGN);
60    globalsInit();
61
62    /* Are we running as init? */
63    if (getpid() == 1) {
64	setsid();
65	close(0); open("/dev/ttyv0", O_RDWR);
66	close(1); dup(0);
67	close(2); dup(0);
68	printf("%s running as init\n", argv[0]);
69	RunningAsInit = 1;
70	i = ioctl(0, TIOCSCTTY, (char *)NULL);
71	setlogin("root");
72	setenv("PATH", "/stand:/bin:/sbin:/usr/sbin:/usr/bin:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin:/usr/X11R6/bin", 1);
73	setbuf(stdin, 0);
74	setbuf(stderr, 0);
75    }
76
77    if (set_termcap() == -1) {
78	printf("Can't find terminal entry\n");
79	exit(-1);
80    }
81
82    /* XXX - libdialog has particularly bad return value checking */
83    init_dialog();
84
85    /* If we haven't crashed I guess dialog is running ! */
86    DialogActive = TRUE;
87
88    /* Make sure HOME is set for those utilities that need it */
89    if (!getenv("HOME"))
90	setenv("HOME", "/", 1);
91    signal(SIGINT, handle_intr);
92}
93
94/* Close down and prepare to exit */
95void
96systemShutdown(int status)
97{
98    /* If some media is open, close it down */
99    if (mediaDevice)
100	mediaDevice->shutdown(mediaDevice);
101
102    /* Shut down the dialog library */
103    if (DialogActive) {
104	end_dialog();
105	DialogActive = FALSE;
106    }
107
108    /* Shut down curses */
109    endwin();
110
111    /* If we have a temporary doc file lying around, nuke it */
112    unlink(DOC_TMP_FILE);
113
114    /* REALLY exit! */
115    if (RunningAsInit) {
116	/* Put the console back */
117	ioctl(0, VT_ACTIVATE, 2);
118	reboot(0);
119    }
120    else
121	exit(status);
122}
123
124/* Run some general command */
125int
126systemExecute(char *command)
127{
128    int status;
129    struct termios foo;
130
131    dialog_update();
132    end_dialog();
133    DialogActive = FALSE;
134    if (tcgetattr(0, &foo) != -1) {
135	foo.c_cc[VERASE] = '\010';
136	tcsetattr(0, TCSANOW, &foo);
137    }
138    if (!Fake)
139	status = system(command);
140    else {
141	status = 0;
142	msgDebug("systemExecute:  Faked execution of `%s'\n", command);
143    }
144    DialogActive = TRUE;
145    return status;
146}
147
148/* Display a help file in a filebox */
149int
150systemDisplayHelp(char *file)
151{
152    char *fname = NULL;
153    char buf[FILENAME_MAX];
154    WINDOW *old = savescr();
155    int ret = 0;
156
157    fname = systemHelpFile(file, buf);
158    if (!fname) {
159	snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file);
160	use_helpfile(NULL);
161	use_helpline(NULL);
162	dialog_mesgbox("Sorry!", buf, -1, -1);
163	ret = 1;
164    }
165    else {
166	use_helpfile(NULL);
167	use_helpline(NULL);
168	dialog_textbox(file, fname, LINES, COLS);
169    }
170    restorescr(old);
171    return ret;
172}
173
174char *
175systemHelpFile(char *file, char *buf)
176{
177    if (!file)
178	return NULL;
179
180    snprintf(buf, FILENAME_MAX, "/stand/help/%s.hlp.gz", file);
181    if (file_readable(buf))
182	return expand(buf);
183    snprintf(buf, FILENAME_MAX, "/usr/src/release/sysinstall/help/%s.hlp", file);
184    if (file_readable(buf))
185	return buf;
186    return NULL;
187}
188
189void
190systemChangeTerminal(char *color, const u_char c_term[],
191		     char *mono, const u_char m_term[])
192{
193    extern void init_acs(void);
194
195    if (OnVTY) {
196	if (ColorDisplay) {
197	    setenv("TERM", color, 1);
198	    setenv("TERMCAP", c_term, 1);
199	    reset_shell_mode();
200	    setterm(color);
201	    init_acs();
202	    cbreak(); noecho();
203	}
204	else {
205	    setenv("TERM", mono, 1);
206	    setenv("TERMCAP", m_term, 1);
207	    reset_shell_mode();
208	    setterm(mono);
209	    init_acs();
210	    cbreak(); noecho();
211	}
212    }
213    clear();
214    refresh();
215    dialog_clear();
216}
217
218int
219vsystem(char *fmt, ...)
220{
221    va_list args;
222    int pstat;
223    pid_t pid;
224    int omask;
225    sig_t intsave, quitsave;
226    char *cmd;
227    int i;
228
229    cmd = (char *)alloca(FILENAME_MAX);
230    cmd[0] = '\0';
231    va_start(args, fmt);
232    vsnprintf(cmd, FILENAME_MAX, fmt, args);
233    va_end(args);
234
235    omask = sigblock(sigmask(SIGCHLD));
236    if (Fake) {
237	msgDebug("vsystem:  Faked execution of `%s'\n", cmd);
238	return 0;
239    }
240    if (isDebug())
241	msgDebug("Executing command `%s'\n", cmd);
242    pid = fork();
243    if (pid == -1) {
244	(void)sigsetmask(omask);
245	i = 127;
246    }
247    else if (!pid) {	/* Junior */
248	(void)sigsetmask(omask);
249	if (DebugFD != -1) {
250	    if (OnVTY && isDebug() && RunningAsInit)
251		msgInfo("Command output is on VTY2 - type ALT-F2 to see it");
252	    dup2(DebugFD, 0);
253	    dup2(DebugFD, 1);
254	    dup2(DebugFD, 2);
255	}
256	else {
257	    close(1); open("/dev/null", O_WRONLY);
258	    dup2(1, 2);
259	}
260	if (!RunningAsInit)
261	    execl("/bin/sh", "/bin/sh", "-c", cmd, (char *)NULL);
262	else
263	    execl("/stand/sh", "/stand/sh", "-c", cmd, (char *)NULL);
264	exit(1);
265    }
266    else {
267	intsave = signal(SIGINT, SIG_IGN);
268	quitsave = signal(SIGQUIT, SIG_IGN);
269	pid = waitpid(pid, &pstat, 0);
270	(void)sigsetmask(omask);
271	(void)signal(SIGINT, intsave);
272	(void)signal(SIGQUIT, quitsave);
273	i = (pid == -1) ? -1 : WEXITSTATUS(pstat);
274	if (isDebug())
275	    msgDebug("Command `%s' returns status of %d\n", cmd, i);
276    }
277    return i;
278}
279
280void
281systemCreateHoloshell(void)
282{
283    if (OnVTY && RunningAsInit) {
284	if (!fork()) {
285	    int i, fd;
286	    struct termios foo;
287	    extern int login_tty(int);
288
289	    for (i = 0; i < 64; i++)
290		close(i);
291	    DebugFD = fd = open("/dev/ttyv3", O_RDWR);
292	    ioctl(0, TIOCSCTTY, &fd);
293	    dup2(0, 1);
294	    dup2(0, 2);
295	    if (login_tty(fd) == -1)
296		msgDebug("Doctor: I can't set the controlling terminal.\n");
297	    signal(SIGTTOU, SIG_IGN);
298	    if (tcgetattr(fd, &foo) != -1) {
299		foo.c_cc[VERASE] = '\010';
300		if (tcsetattr(fd, TCSANOW, &foo) == -1)
301		    msgDebug("Doctor: I'm unable to set the erase character.\n");
302	    }
303	    else
304		msgDebug("Doctor: I'm unable to get the terminal attributes!\n");
305	    execlp("sh", "-sh", 0);
306	    msgDebug("Was unable to execute sh for Holographic shell!\n");
307	    exit(1);
308	}
309	else {
310	    msgNotify("Starting an emergency holographic shell on VTY4");
311	    sleep(2);
312	}
313    }
314}
315