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