system.c revision 8665
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.25 1995/05/20 23:33:14 phk 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(stdout, 0);
78	setbuf(stderr, 0);
79    }
80
81    for(i = 0; i < 256; i++)
82	default_scrnmap[i] = i;
83
84    if (set_termcap() == -1) {
85	printf("Can't find terminal entry\n");
86	exit(-1);
87    }
88
89    /* XXX - libdialog has particularly bad return value checking */
90    init_dialog();
91    /* If we haven't crashed I guess dialog is running ! */
92    DialogActive = TRUE;
93
94    signal(SIGINT, handle_intr);
95}
96
97/* Close down and prepare to exit */
98void
99systemShutdown(void)
100{
101    if (DialogActive) {
102	end_dialog();
103	DialogActive = FALSE;
104    }
105    /* REALLY exit! */
106    if (getpid() == 1)
107	reboot(RB_HALT);
108    else
109	exit(1);
110}
111
112/* Run some general command */
113int
114systemExecute(char *command)
115{
116    int status;
117
118    dialog_clear();
119    dialog_update();
120    end_dialog();
121    DialogActive = FALSE;
122    status = system(command);
123    DialogActive = TRUE;
124    dialog_clear();
125    dialog_update();
126    return status;
127}
128
129/* Find and execute a shell */
130int
131systemShellEscape(void)
132{
133    char *sh = NULL;
134
135    if (file_executable("/bin/sh"))
136	sh = "/bin/sh";
137    else if (file_executable("/stand/sh"))
138	sh = "/stand/sh";
139    else {
140	msgWarn("No shell available, sorry!");
141	return 1;
142    }
143    setenv("PS1", "freebsd% ", 1);
144    dialog_clear();
145    dialog_update();
146    move(0, 0);
147    standout();
148    addstr("Type `exit' to leave this shell and continue installation");
149    standend();
150    refresh();
151    end_dialog();
152    DialogActive = FALSE;
153    if (fork() == 0)
154	execlp(sh, "-sh", 0);
155    else
156	wait(NULL);
157    dialog_clear();
158    DialogActive = TRUE;
159    return 0;
160}
161
162/* Display a file in a filebox */
163int
164systemDisplayFile(char *file)
165{
166    char *fname = NULL;
167    char buf[FILENAME_MAX];
168    WINDOW *w;
169
170    fname = systemHelpFile(file, buf);
171    if (!fname) {
172	snprintf(buf, FILENAME_MAX, "The %s file is not provided on this particular floppy image.", file);
173	use_helpfile(NULL);
174	use_helpline(NULL);
175	w = dupwin(newscr);
176	dialog_mesgbox("Sorry!", buf, -1, -1);
177	touchwin(w);
178	wrefresh(w);
179	delwin(w);
180	return 1;
181    }
182    else {
183	use_helpfile(NULL);
184	use_helpline(NULL);
185	w = dupwin(newscr);
186	dialog_textbox(file, fname, LINES, COLS);
187	touchwin(w);
188	wrefresh(w);
189	delwin(w);
190    }
191    return 0;
192}
193
194char *
195systemHelpFile(char *file, char *buf)
196{
197    char *cp, *fname = NULL;
198
199    if (!file)
200	return NULL;
201
202    if ((cp = getenv("LANG")) != NULL) {
203	snprintf(buf, FILENAME_MAX, "help/%s/%s", cp, file);
204	if (file_readable(buf))
205	    fname = buf;
206	else {
207	    snprintf(buf, FILENAME_MAX, "/stand/help/%s/%s", cp, file);
208	    if (file_readable(buf))
209		fname = buf;
210	}
211    }
212    if (!fname) {
213	snprintf(buf, FILENAME_MAX, "help/en_US.ISO8859-1/%s", file);
214	if (file_readable(buf))
215	    fname = buf;
216	else {
217	    snprintf(buf, FILENAME_MAX, "/stand/help/en_US.ISO8859-1/%s",
218		     file);
219	    if (file_readable(buf))
220		fname = buf;
221	}
222    }
223    return fname;
224}
225
226void
227systemChangeFont(const u_char font[])
228{
229    if (OnVTY && ColorDisplay) {
230	if (ioctl(0, PIO_FONT8x16, font) < 0)
231	    msgConfirm("Sorry!  Unable to load font for %s", getenv("LANG"));
232    }
233}
234
235void
236systemChangeLang(char *lang)
237{
238    variable_set2("LANG", lang);
239}
240
241void
242systemChangeTerminal(char *color, const u_char c_term[],
243		     char *mono, const u_char m_term[])
244{
245    extern void init_acs(void);
246
247    if (OnVTY) {
248	if (ColorDisplay) {
249	    setenv("TERM", color, 1);
250	    setenv("TERMCAP", c_term, 1);
251	    reset_shell_mode();
252	    setterm(color);
253	    init_acs();
254	    cbreak(); noecho();
255	    dialog_clear();
256	}
257	else {
258	    setenv("TERM", mono, 1);
259	    setenv("TERMCAP", m_term, 1);
260	    reset_shell_mode();
261	    setterm(mono);
262	    init_acs();
263	    cbreak(); noecho();
264	    dialog_clear();
265	}
266    }
267}
268
269void
270systemChangeScreenmap(const u_char newmap[])
271{
272    if (OnVTY) {
273	if (ioctl(0, PIO_SCRNMAP, newmap) < 0)
274	    msgConfirm("Sorry!  Unable to load the screenmap for %s",
275		       getenv("LANG"));
276	dialog_clear();
277    }
278}
279int
280vsystem(char *fmt, ...)
281{
282    va_list args;
283    union wait pstat;
284    pid_t pid;
285    int omask;
286    sig_t intsave, quitsave;
287    char *cmd,*p;
288    int i,magic=0;
289
290    cmd = (char *)malloc(FILENAME_MAX);
291    cmd[0] = '\0';
292    va_start(args, fmt);
293    vsnprintf(cmd, FILENAME_MAX, fmt, args);
294    va_end(args);
295    /* Find out if this command needs the wizardry of the shell */
296    for (p="<>|'`=\"()" ; *p; p++)
297	    if (strchr(cmd,*p))	magic++;
298    omask = sigblock(sigmask(SIGCHLD));
299    msgDebug("Executing command `%s' (Magic=%d)\n", cmd, magic);
300    switch(pid = fork()) {
301    case -1:			/* error */
302	(void)sigsetmask(omask);
303	i = 127;
304
305    case 0:				/* child */
306	(void)sigsetmask(omask);
307	if (DebugFD != -1) {
308	    if (OnVTY)
309		msgInfo("Command output is on debugging screen - type ALT-F2 to see it");
310	    dup2(DebugFD, 0);
311	    dup2(DebugFD, 1);
312	    dup2(DebugFD, 2);
313	}
314#ifdef CRUNCHED_BINARY
315	if (magic) {
316		char *argv[100];
317		i = 0;
318		argv[i++] = "crunch";
319		argv[i++] = "sh";
320		argv[i++] = "-c";
321		argv[i++] = cmd;
322		argv[i] = 0;
323		exit(crunched_main(i,argv));
324	} else {
325		char *argv[100];
326		i = 0;
327		argv[i++] = "crunch";
328		while (cmd && *cmd) {
329			argv[i] = strsep(&cmd," \t");
330			if (*argv[i])
331				i++;
332		}
333		argv[i] = 0;
334		if (crunched_here(argv[1]))
335			exit(crunched_main(i,argv));
336		else
337			execvp(argv[1],argv+1);
338		kill(getpid(),9);
339	}
340#else /* !CRUNCHED_BINARY */
341	execl("/stand/sh", "sh", "-c", cmd, (char *)NULL);
342	kill(getpid(),9);
343#endif /* CRUNCHED_BINARY */
344    }
345    intsave = signal(SIGINT, SIG_IGN);
346    quitsave = signal(SIGQUIT, SIG_IGN);
347    pid = waitpid(pid, (int *)&pstat, 0);
348    (void)sigsetmask(omask);
349    (void)signal(SIGINT, intsave);
350    (void)signal(SIGQUIT, quitsave);
351    i = (pid == -1) ? -1 : pstat.w_status;
352    msgDebug("Command `%s' returns status of %d\n", cmd, i);
353    free(cmd);
354    return i;
355}
356