system.c revision 8738
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.31 1995/05/24 23:36:50 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 * Handle interrupt signals - this probably won't work in all cases
29 * due to our having bogotified the internal state of dialog or curses,
30 * but we'll give it a try.
31 */
32static void
33handle_intr(int sig)
34{
35    if (!msgYesNo("Are you sure you want to abort the installation?"))
36	systemShutdown();
37}
38
39/* Welcome the user to the system */
40void
41systemWelcome(void)
42{
43    printf("Installation system initializing..\n");
44}
45
46/* Initialize system defaults */
47void
48systemInitialize(int argc, char **argv)
49{
50    int i;
51
52    signal(SIGINT, SIG_IGN);
53    globalsInit();
54
55    /* Are we running as init? */
56    if (getpid() == 1) {
57	setsid();
58	if (argc > 1 && strchr(argv[1],'C')) {
59	    /* Kernel told us that we are on a CDROM root */
60	    close(0); open("/bootcd/dev/console", O_RDWR);
61	    close(1); dup(0);
62	    close(2); dup(0);
63	    CpioFD = open("/floppies/cpio.flp", O_RDONLY);
64	    OnCDROM = TRUE;
65	    chroot("/bootcd");
66	} else {
67	    close(0); open("/dev/console", O_RDWR);
68	    close(1); dup(0);
69	    close(2); dup(0);
70	}
71	printf("%s running as init\n", argv[0]);
72
73	ioctl(0, TIOCSCTTY, (char *)NULL);
74	setlogin("root");
75	setenv("PATH", "/stand:/mnt/bin:/mnt/sbin:/mnt/usr/sbin:/mnt/usr/bin", 1);
76	setbuf(stdin, 0);
77	setbuf(stderr, 0);
78    }
79
80    for(i = 0; i < 256; i++)
81	default_scrnmap[i] = i;
82
83    if (set_termcap() == -1) {
84	printf("Can't find terminal entry\n");
85	exit(-1);
86    }
87
88    /* If we're running as init, stick a shell over on the 4th VTY */
89    if (RunningAsInit && !fork()) {
90	int i;
91
92	for (i = 0; i < 64; i++)
93	    close(i);
94	open("/dev/ttyv3", O_RDWR);
95	ioctl(0, TIOCSCTTY, (char *)NULL);
96	dup2(0, 1);
97	dup2(0, 2);
98	execlp("/stand/sh", "-sh", 0);
99	exit(1);
100    }
101
102    /* XXX - libdialog has particularly bad return value checking */
103    init_dialog();
104    /* If we haven't crashed I guess dialog is running ! */
105    DialogActive = TRUE;
106
107    signal(SIGINT, handle_intr);
108}
109
110/* Close down and prepare to exit */
111void
112systemShutdown(void)
113{
114    if (DialogActive) {
115	end_dialog();
116	DialogActive = FALSE;
117    }
118    /* REALLY exit! */
119    if (getpid() == 1)
120	reboot(RB_HALT);
121    else
122	exit(1);
123}
124
125/* Run some general command */
126int
127systemExecute(char *command)
128{
129    int status;
130
131    dialog_clear();
132    dialog_update();
133    end_dialog();
134    DialogActive = FALSE;
135    status = system(command);
136    DialogActive = TRUE;
137    dialog_clear();
138    dialog_update();
139    return status;
140}
141
142/* Find and execute a shell */
143int
144systemShellEscape(void)
145{
146    char *sh = NULL;
147
148    if (file_executable("/bin/sh"))
149	sh = "/bin/sh";
150    else if (file_executable("/stand/sh"))
151	sh = "/stand/sh";
152    else {
153	msgWarn("No shell available, sorry!");
154	return 1;
155    }
156    setenv("PS1", "freebsd% ", 1);
157    dialog_clear();
158    dialog_update();
159    move(0, 0);
160    standout();
161    addstr("Type `exit' to leave this shell and continue installation");
162    standend();
163    refresh();
164    end_dialog();
165    DialogActive = FALSE;
166    if (fork() == 0)
167	execlp(sh, "-sh", 0);
168    else
169	wait(NULL);
170    dialog_clear();
171    DialogActive = TRUE;
172    return 0;
173}
174
175/* Display a file in a filebox */
176int
177systemDisplayFile(char *file)
178{
179    char *fname = NULL;
180    char buf[FILENAME_MAX];
181    WINDOW *w;
182
183    fname = systemHelpFile(file, buf);
184    if (!fname) {
185	snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file);
186	use_helpfile(NULL);
187	use_helpline(NULL);
188	w = dupwin(newscr);
189	dialog_mesgbox("Sorry!", buf, -1, -1);
190	touchwin(w);
191	wrefresh(w);
192	delwin(w);
193	return 1;
194    }
195    else {
196	use_helpfile(NULL);
197	use_helpline(NULL);
198	w = dupwin(newscr);
199	dialog_textbox(file, fname, LINES, COLS);
200	touchwin(w);
201	wrefresh(w);
202	delwin(w);
203    }
204    return 0;
205}
206
207char *
208systemHelpFile(char *file, char *buf)
209{
210    char *cp, *fname = NULL;
211
212    if (!file)
213	return NULL;
214
215    if ((cp = getenv("LANG")) != NULL) {
216	snprintf(buf, FILENAME_MAX, "help/%s/%s", cp, file);
217	if (file_readable(buf))
218	    fname = buf;
219	else {
220	    snprintf(buf, FILENAME_MAX, "/stand/help/%s/%s", cp, file);
221	    if (file_readable(buf))
222		fname = buf;
223	}
224    }
225    if (!fname) {
226	snprintf(buf, FILENAME_MAX, "help/en_US.ISO8859-1/%s", file);
227	if (file_readable(buf))
228	    fname = buf;
229	else {
230	    snprintf(buf, FILENAME_MAX, "/stand/help/en_US.ISO8859-1/%s",
231		     file);
232	    if (file_readable(buf))
233		fname = buf;
234	}
235    }
236    return fname;
237}
238
239void
240systemChangeFont(const u_char font[])
241{
242    if (OnVTY && ColorDisplay) {
243	if (ioctl(0, PIO_FONT8x16, font) < 0)
244	    msgConfirm("Sorry!  Unable to load font for %s", getenv("LANG"));
245    }
246    dialog_clear();
247}
248
249void
250systemChangeLang(char *lang)
251{
252    variable_set2("LANG", lang);
253}
254
255void
256systemChangeTerminal(char *color, const u_char c_term[],
257		     char *mono, const u_char m_term[])
258{
259    extern void init_acs(void);
260
261    if (OnVTY) {
262	if (ColorDisplay) {
263	    setenv("TERM", color, 1);
264	    setenv("TERMCAP", c_term, 1);
265	    reset_shell_mode();
266	    setterm(color);
267	    init_acs();
268	    cbreak(); noecho();
269	}
270	else {
271	    setenv("TERM", mono, 1);
272	    setenv("TERMCAP", m_term, 1);
273	    reset_shell_mode();
274	    setterm(mono);
275	    init_acs();
276	    cbreak(); noecho();
277	}
278	dialog_clear();
279    }
280}
281
282void
283systemChangeScreenmap(const u_char newmap[])
284{
285    if (OnVTY) {
286	if (ioctl(0, PIO_SCRNMAP, newmap) < 0)
287	    msgConfirm("Sorry!  Unable to load the screenmap for %s",
288		       getenv("LANG"));
289    }
290    dialog_clear();
291}
292
293int
294vsystem(char *fmt, ...)
295{
296    va_list args;
297    union wait pstat;
298    pid_t pid;
299    int omask;
300    sig_t intsave, quitsave;
301    char *cmd,*p;
302    int i,magic=0;
303
304    cmd = (char *)malloc(FILENAME_MAX);
305    cmd[0] = '\0';
306    va_start(args, fmt);
307    vsnprintf(cmd, FILENAME_MAX, fmt, args);
308    va_end(args);
309    /* Find out if this command needs the wizardry of the shell */
310    for (p="<>|'`=\"()" ; *p; p++)
311	    if (strchr(cmd,*p))	magic++;
312    omask = sigblock(sigmask(SIGCHLD));
313    msgDebug("Executing command `%s' (Magic=%d)\n", cmd, magic);
314    switch(pid = fork()) {
315    case -1:			/* error */
316	(void)sigsetmask(omask);
317	i = 127;
318
319    case 0:				/* child */
320	(void)sigsetmask(omask);
321	if (DebugFD != -1) {
322	    if (OnVTY)
323		msgInfo("Command output is on debugging screen - type ALT-F2 to see it");
324	    dup2(DebugFD, 0);
325	    dup2(DebugFD, 1);
326	    dup2(DebugFD, 2);
327	}
328#ifdef CRUNCHED_BINARY
329	if (magic) {
330		char *argv[100];
331		i = 0;
332		argv[i++] = "crunch";
333		argv[i++] = "sh";
334		argv[i++] = "-c";
335		argv[i++] = cmd;
336		argv[i] = 0;
337		exit(crunched_main(i,argv));
338	} else {
339		char *argv[100];
340		i = 0;
341		argv[i++] = "crunch";
342		while (cmd && *cmd) {
343			argv[i] = strsep(&cmd," \t");
344			if (*argv[i])
345				i++;
346		}
347		argv[i] = 0;
348		if (crunched_here(argv[1]))
349			exit(crunched_main(i,argv));
350		else
351			execvp(argv[1],argv+1);
352		kill(getpid(),9);
353	}
354#else /* !CRUNCHED_BINARY */
355	execl("/stand/sh", "sh", "-c", cmd, (char *)NULL);
356	kill(getpid(),9);
357#endif /* CRUNCHED_BINARY */
358    }
359    intsave = signal(SIGINT, SIG_IGN);
360    quitsave = signal(SIGQUIT, SIG_IGN);
361    pid = waitpid(pid, (int *)&pstat, 0);
362    (void)sigsetmask(omask);
363    (void)signal(SIGINT, intsave);
364    (void)signal(SIGQUIT, quitsave);
365    i = (pid == -1) ? -1 : pstat.w_status;
366    msgDebug("Command `%s' returns status of %d\n", cmd, i);
367    free(cmd);
368    return i;
369}
370