Annotation of src/distrib/utils/sysinst/main.c, Revision 1.45
1.45 ! christos 1: /* $NetBSD: main.c,v 1.44 2004/06/05 21:18:59 dsl Exp $ */
1.1 phil 2:
3: /*
4: * Copyright 1997 Piermont Information Systems Inc.
5: * All rights reserved.
6: *
7: * Written by Philip A. Nelson for Piermont Information Systems Inc.
8: *
9: * Redistribution and use in source and binary forms, with or without
10: * modification, are permitted provided that the following conditions
11: * are met:
12: * 1. Redistributions of source code must retain the above copyright
13: * notice, this list of conditions and the following disclaimer.
14: * 2. Redistributions in binary form must reproduce the above copyright
15: * notice, this list of conditions and the following disclaimer in the
16: * documentation and/or other materials provided with the distribution.
17: * 3. All advertising materials mentioning features or use of this software
18: * must display the following acknowledgement:
1.17 cgd 19: * This product includes software developed for the NetBSD Project by
1.1 phil 20: * Piermont Information Systems Inc.
21: * 4. The name of Piermont Information Systems Inc. may not be used to endorse
22: * or promote products derived from this software without specific prior
23: * written permission.
24: *
25: * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
26: * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28: * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
29: * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
30: * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
31: * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
32: * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
33: * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
34: * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
35: * THE POSSIBILITY OF SUCH DAMAGE.
36: *
37: */
38:
39: /* main sysinst program. */
40:
1.10 phil 41: #include <sys/types.h>
42: #include <sys/stat.h>
43: #include <sys/uio.h>
1.1 phil 44: #include <stdio.h>
1.5 simonb 45: #include <signal.h>
1.1 phil 46: #include <curses.h>
1.3 phil 47: #include <unistd.h>
1.10 phil 48: #include <fcntl.h>
1.36 dsl 49: #include <dirent.h>
1.1 phil 50:
51: #include "defs.h"
52: #include "md.h"
53: #include "msg_defs.h"
54: #include "menu_defs.h"
1.10 phil 55: #include "txtwalk.h"
1.1 phil 56:
1.34 dsl 57: int main(int, char **);
1.45 ! christos 58: static void init(void);
1.36 dsl 59: static void select_language(void);
1.34 dsl 60: static void usage(void);
61: static void miscsighandler(int);
62: static void ttysighandler(int);
63: static void cleanup(void);
64: static void process_f_flag(char *);
1.8 simonb 65:
66: static int exit_cleanly = 0; /* Did we finish nicely? */
1.11 garbled 67: int logging; /* are we logging everything? */
68: int scripting; /* are we building a script? */
1.29 fvdl 69: FILE *logfp; /* log file */
1.11 garbled 70: FILE *script; /* script file */
1.1 phil 71:
1.12 fvdl 72: #ifdef DEBUG
1.34 dsl 73: extern int log_flip(void);
1.12 fvdl 74: #endif
75:
1.45 ! christos 76: static void
! 77: init(void)
! 78: {
! 79: (void)strlcpy(rel, REL, SSTRSIZE);
! 80: (void)strlcpy(machine, MACH, SSTRSIZE);
! 81: sizemult = 1;
! 82: ramsize = 0;
! 83: rammb = 0;
! 84: (void)strlcpy(diskdev, "", SSTRSIZE);
! 85: disktype = "unknown";
! 86: tmp_mfs_size = 0;
! 87: (void)strlcpy(bsddiskname, "mydisk", DISKNAME_SIZE);
! 88: doessf = "";
! 89: (void)strlcpy(dist_dir, "/usr/INSTALL", STRSIZE);
! 90: clean_dist_dir = 0;
! 91: (void)strlcpy(ext_dir, "", STRSIZE);
! 92: (void)strlcpy(set_dir, "/" MACH "/binary/sets", STRSIZE);
! 93: (void)strlcpy(ftp_host, SYSINST_FTP_HOST, STRSIZE);
! 94: (void)strlcpy(ftp_dir, SYSINST_FTP_DIR, STRSIZE);
! 95: (void)strlcpy(ftp_user, "ftp", SSTRSIZE);
! 96: (void)strlcpy(ftp_pass, "", STRSIZE);
! 97: (void)strlcpy(ftp_proxy, "", STRSIZE);
! 98: (void)strlcpy(nfs_host, "", STRSIZE);
! 99: (void)strlcpy(nfs_dir, "/bsd/release", STRSIZE);
! 100: (void)strlcpy(cdrom_dev, "cd0a", SSTRSIZE);
! 101: (void)strlcpy(localfs_dev, "sd0a", SSTRSIZE);
! 102: (void)strlcpy(localfs_fs, "ffs", SSTRSIZE);
! 103: (void)strlcpy(localfs_dir, "release", STRSIZE);
! 104: (void)strlcpy(targetroot_mnt, "/targetroot", SSTRSIZE);
! 105: (void)strlcpy(distfs_mnt, "/mnt2", SSTRSIZE);
! 106: mnt2_mounted = 0;
! 107: (void)strlcpy(dist_postfix, ".tgz", SSTRSIZE);
! 108: }
! 109:
1.9 mrg 110: int
1.34 dsl 111: main(int argc, char **argv)
1.1 phil 112: {
113: WINDOW *win;
1.3 phil 114: int ch;
1.2 phil 115:
1.11 garbled 116: logging = 0; /* shut them off unless turned on by the user */
1.45 ! christos 117: init();
1.12 fvdl 118: #ifdef DEBUG
119: log_flip();
120: #endif
1.11 garbled 121: scripting = 0;
122:
1.2 phil 123: /* Check for TERM ... */
124: if (!getenv("TERM")) {
1.9 mrg 125: (void)fprintf(stderr,
1.34 dsl 126: "sysinst: environment variable TERM not set.\n");
1.2 phil 127: exit(1);
128: }
1.1 phil 129:
1.3 phil 130: /* argv processing */
1.35 dsl 131: while ((ch = getopt(argc, argv, "Dr:f:")) != -1)
1.3 phil 132: switch(ch) {
1.35 dsl 133: case 'D': /* set to get past certain errors in testing */
134: debug = 1;
135: break;
1.3 phil 136: case 'r':
137: /* Release name other than compiled in release. */
1.9 mrg 138: strncpy(rel, optarg, SSTRSIZE);
1.3 phil 139: break;
1.10 phil 140: case 'f':
141: /* Definition file to read. */
1.34 dsl 142: process_f_flag(optarg);
1.10 phil 143: break;
1.3 phil 144: case '?':
145: default:
146: usage();
147: }
1.21 fvdl 148:
149: md_init();
1.3 phil 150:
1.1 phil 151: /* initialize message window */
1.15 cgd 152: if (menu_init()) {
153: __menu_initerror();
154: exit(1);
155: }
1.26 perry 156:
1.15 cgd 157: /*
158: * XXX the following is bogus. if screen is too small, message
159: * XXX window will be overwritten by menus.
160: */
161: win = newwin(getmaxy(stdscr) - 2, getmaxx(stdscr) - 2, 1, 1);
1.32 dsl 162: if (win == NULL) {
163: (void)fprintf(stderr,
164: "sysinst: screen too small\n");
165: exit(1);
166: }
1.26 perry 167: if (has_colors()) {
168: /*
169: * XXX This color trick should be done so much better,
170: * but is it worth it?
171: */
172: wbkgd(win, COLOR_PAIR(1));
173: wattrset(win, COLOR_PAIR(1));
1.16 garbled 174: }
1.33 dsl 175: msg_window(win);
1.1 phil 176:
1.18 cgd 177: /* Watch for signals and clean up */
1.9 mrg 178: (void)atexit(cleanup);
1.18 cgd 179: (void)signal(SIGINT, ttysighandler);
180: (void)signal(SIGQUIT, ttysighandler);
181: (void)signal(SIGHUP, miscsighandler);
1.28 grant 182:
183: /* redraw screen */
184: touchwin(stdscr);
185: refresh();
1.38 dsl 186:
187: /* Ensure we have mountpoint for target filesystems */
188: mkdir(targetroot_mnt, S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
1.5 simonb 189:
1.36 dsl 190: select_language();
191:
1.1 phil 192: /* Menu processing */
1.31 dsl 193: process_menu(MENU_netbsd, NULL);
1.1 phil 194:
1.8 simonb 195: exit_cleanly = 1;
1.34 dsl 196: return 0;
1.1 phil 197: }
1.36 dsl 198:
199: static int
1.40 dsl 200: set_language(menudesc *m, void *arg)
1.36 dsl 201: {
202: char **fnames = arg;
203:
1.40 dsl 204: msg_file(fnames[m->cursel]);
1.36 dsl 205: return 1;
206: }
207:
208: static void
209: select_language(void)
210: {
211: DIR *dir;
212: struct dirent *dirent;
213: char **lang_msg, **fnames;
214: int max_lang = 16, num_lang = 0;
215: const char *cp;
216: menu_ent *opt = 0;
217: int lang_menu = -1;
218: int lang;
219:
220: dir = opendir(".");
221: if (!dir)
222: return;
223:
224: lang_msg = malloc(max_lang * sizeof *lang_msg);
225: fnames = malloc(max_lang * sizeof *fnames);
226: if (!lang_msg || !fnames)
227: goto done;
228:
229: lang_msg[0] = strdup(msg_string(MSG_sysinst_message_language));
230: fnames[0] = 0;
231: num_lang = 1;
232:
233: while ((dirent = readdir(dir)) != 0) {
234: if (memcmp(dirent->d_name, "sysinstmsgs.", 12))
235: continue;
236: if (msg_file(dirent->d_name))
237: continue;
238: cp = msg_string(MSG_sysinst_message_language);
239: if (!strcmp(cp, lang_msg[0]))
240: continue;
241: if (num_lang == max_lang) {
242: char **new;
243: max_lang *= 2;
244: new = realloc(lang_msg, max_lang * sizeof *lang_msg);
245: if (!new)
246: break;
247: lang_msg = new;
248: new = realloc(fnames, max_lang * sizeof *fnames);
249: if (!new)
250: break;
251: fnames = new;
252: }
253: fnames[num_lang] = strdup(dirent->d_name);
254: lang_msg[num_lang++] = strdup(cp);
255: }
256: msg_file(0);
257: closedir(dir);
258: dir = 0;
259:
260: if (num_lang == 1)
261: goto done;
262:
263: opt = calloc(num_lang, sizeof *opt);
264: if (!opt)
265: goto done;
266:
267: for (lang = 0; lang < num_lang; lang++) {
268: opt[lang].opt_name = lang_msg[lang];
269: opt[lang].opt_menu = OPT_NOMENU;
270: opt[lang].opt_action = set_language;
271: }
272:
273: lang_menu = new_menu(NULL, opt, num_lang, -1, 12, 0, 0, MC_NOEXITOPT,
1.37 dsl 274: NULL, NULL, NULL, NULL, NULL);
1.36 dsl 275:
276: if (lang_menu != -1) {
277: msg_display(MSG_hello);
278: process_menu(lang_menu, fnames);
279: }
280:
281: done:
282: if (dir)
283: closedir(dir);
284: if (lang_menu != -1)
285: free_menu(lang_menu);
286: free(opt);
287: while (num_lang) {
288: free(lang_msg[--num_lang]);
289: free(fnames[num_lang]);
290: }
291: free(lang_msg);
292: free(fnames);
293: }
1.7 jonathan 294:
295: /* toplevel menu handler ... */
1.9 mrg 296: void
1.34 dsl 297: toplevel(void)
1.7 jonathan 298: {
1.9 mrg 299:
1.20 hubertf 300: /* Display banner message in (english, francais, deutsch..) */
1.9 mrg 301: msg_display(MSG_hello);
1.23 minoura 302: msg_display_add(MSG_md_hello);
303: msg_display_add(MSG_thanks);
1.7 jonathan 304:
305: /*
306: * Undo any stateful side-effects of previous menu choices.
307: * XXX must be idempotent, since we get run each time the main
308: * menu is displayed.
309: */
310: unwind_mounts();
311: /* ... */
312: }
313:
1.3 phil 314:
315: /* The usage ... */
316:
1.8 simonb 317: static void
1.34 dsl 318: usage(void)
1.3 phil 319: {
1.9 mrg 320:
321: (void)fprintf(stderr, msg_string(MSG_usage));
1.5 simonb 322: exit(1);
323: }
324:
325: /* ARGSUSED */
1.8 simonb 326: static void
1.34 dsl 327: miscsighandler(int signo)
1.5 simonb 328: {
1.18 cgd 329:
330: /*
331: * we need to cleanup(), but it was already scheduled with atexit(),
332: * so it'll be invoked on exit().
333: */
334: exit(1);
335: }
336:
337: static void
1.34 dsl 338: ttysighandler(int signo)
1.18 cgd 339: {
340:
341: /*
342: * if we want to ignore a TTY signal (SIGINT or SIGQUIT), then we
343: * just return. If we want to forward a TTY signal, we forward it
344: * to the specified process group.
345: *
346: * This functionality is used when setting up and displaying child
347: * output so that the child gets the signal and presumably dies,
348: * but sysinst continues. We use this rather than actually ignoring
349: * the signals, because that will be be passed on to a child
350: * through fork/exec, whereas special handlers get reset on exec..
351: */
352: if (ttysig_ignore)
353: return;
354: if (ttysig_forward) {
355: killpg(ttysig_forward, signo);
356: return;
357: }
1.9 mrg 358:
1.14 cgd 359: /*
360: * we need to cleanup(), but it was already scheduled with atexit(),
361: * so it'll be invoked on exit().
362: */
1.8 simonb 363: exit(1);
364: }
365:
366: static void
1.34 dsl 367: cleanup(void)
1.8 simonb 368: {
1.11 garbled 369: time_t tloc;
1.9 mrg 370:
1.11 garbled 371: (void)time(&tloc);
1.39 dsl 372:
1.43 dsl 373: #if 0
1.39 dsl 374: restore_etc();
1.43 dsl 375: #endif
1.41 dsl 376: /* Ensure we aren't inside the target tree */
377: chdir(getenv("HOME"));
1.11 garbled 378: unwind_mounts();
1.42 dsl 379: umount_mnt2();
1.39 dsl 380:
1.5 simonb 381: endwin();
1.39 dsl 382:
1.11 garbled 383: if (logging) {
1.29 fvdl 384: fprintf(logfp, "Log ended at: %s\n", asctime(localtime(&tloc)));
385: fflush(logfp);
386: fclose(logfp);
1.11 garbled 387: }
388: if (scripting) {
1.34 dsl 389: fprintf(script, "# Script ended at: %s\n",
390: asctime(localtime(&tloc)));
1.11 garbled 391: fflush(script);
392: fclose(script);
393: }
394:
1.8 simonb 395: if (!exit_cleanly)
1.14 cgd 396: fprintf(stderr, "\n\nsysinst terminated.\n");
1.27 lukem 397: }
398:
1.10 phil 399:
400: /* Stuff for processing the -f file argument. */
401:
402: /* Data definitions ... */
403:
404: static char *rel_ptr = rel;
405: static char *machine_ptr = machine;
406: static char *dist_dir_ptr = dist_dir;
407: static char *ext_dir_ptr = ext_dir;
408: static char *ftp_host_ptr = ftp_host;
409: static char *ftp_dir_ptr = ftp_dir;
1.44 dsl 410: static char *set_dir_ptr = set_dir;
1.10 phil 411: static char *ftp_user_ptr = ftp_user;
412: static char *ftp_pass_ptr = ftp_pass;
1.25 scottr 413: static char *ftp_proxy_ptr = ftp_proxy;
1.10 phil 414: static char *nfs_host_ptr = nfs_host;
415: static char *nfs_dir_ptr = nfs_dir;
416: static char *cdrom_dev_ptr = cdrom_dev;
417: static char *localfs_dev_ptr = localfs_dev;
418: static char *localfs_fs_ptr = localfs_fs;
419: static char *localfs_dir_ptr = localfs_dir;
420: static char *targetroot_mnt_ptr = targetroot_mnt;
421: static char *distfs_mnt_ptr = distfs_mnt;
422: static char *dist_postfix_ptr = dist_postfix;
423:
424: struct lookfor fflagopts[] = {
425: {"release", "release = %s", "a $0", &rel_ptr, 1, SSTRSIZE, NULL},
426: {"machine", "machine = %s", "a $0", &machine_ptr, 1, SSTRSIZE, NULL},
427: {"dist dir", "dist dir = %s", "a $0", &dist_dir_ptr, 1, STRSIZE, NULL},
428: {"ext dir", "ext dir = %s", "a $0", &ext_dir_ptr, 1, STRSIZE, NULL},
429: {"ftp host", "ftp host = %s", "a $0", &ftp_host_ptr, 1, STRSIZE, NULL},
430: {"ftp dir", "ftp dir = %s", "a $0", &ftp_dir_ptr, 1, STRSIZE, NULL},
1.44 dsl 431: {"ftp prefix", "set dir = %s", "a $0", &set_dir_ptr, 1, STRSIZE, NULL},
1.10 phil 432: {"ftp user", "ftp user = %s", "a $0", &ftp_user_ptr, 1, STRSIZE, NULL},
433: {"ftp pass", "ftp pass = %s", "a $0", &ftp_pass_ptr, 1, STRSIZE, NULL},
1.25 scottr 434: {"ftp proxy", "ftp proxy = %s", "a $0", &ftp_proxy_ptr, 1, STRSIZE,
435: NULL},
1.10 phil 436: {"nfs host", "nfs host = %s", "a $0", &nfs_host_ptr, 1, STRSIZE, NULL},
437: {"nfs dir", "ftp dir = %s", "a $0", &nfs_dir_ptr, 1, STRSIZE, NULL},
438: {"cd dev", "cd dev = %s", "a $0", &cdrom_dev_ptr, 1, STRSIZE, NULL},
439: {"local dev", "local dev = %s", "a $0", &localfs_dev_ptr, 1, STRSIZE,
440: NULL},
441: {"local fs", "local fs = %s", "a $0", &localfs_fs_ptr, 1, STRSIZE,
442: NULL},
443: {"local dir", "local dir = %s", "a $0", &localfs_dir_ptr, 1, STRSIZE,
444: NULL},
445: {"targetroot mount", "targetroot mount = %s", "a $0",
446: &targetroot_mnt_ptr, 1, STRSIZE, NULL},
447: {"distfs mount", "distfs mount = %s", "a $0", &distfs_mnt_ptr, 1,
448: STRSIZE, NULL},
449: {"dist postfix", "dist postfix = %s", "a $0", &dist_postfix_ptr, 1,
450: STRSIZE, NULL},
451: };
452:
453: /* process function ... */
454:
1.34 dsl 455: void
456: process_f_flag(char *f_name)
1.10 phil 457: {
1.34 dsl 458: char *buffer;
459: struct stat statinfo;
460: int fd;
461:
462: /* stat the file (error reported) */
463:
464: if (stat(f_name, &statinfo) < 0) {
465: perror(f_name); /* XXX -- better message? */
466: exit(1);
467: }
468:
469: if ((statinfo.st_mode & S_IFMT) != S_IFREG) {
470: fprintf(stderr, msg_string(MSG_not_regular_file), f_name);
471: exit(1);
472: }
473:
474: /* allocate buffer (error reported) */
475: buffer = malloc((size_t)statinfo.st_size + 1);
476: if (buffer == NULL) {
477: fprintf(stderr, msg_string(MSG_out_of_memory));
478: exit(1);
479: }
480:
481: /* open the file */
482: fd = open(f_name, O_RDONLY, 0);
483: if (fd < 0) {
484: fprintf(stderr, msg_string(MSG_config_open_error), f_name);
485: exit(1);
486: }
487:
488: /* read the file */
489: if (read(fd,buffer, (size_t)statinfo.st_size)
490: != (size_t)statinfo.st_size) {
491: fprintf(stderr, msg_string(MSG_config_read_error), f_name);
492: exit(1);
493: }
494: buffer[(size_t)statinfo.st_size] = 0;
495:
496: /* close the file */
497: close(fd);
498:
499: /* Walk the buffer */
500: walk(buffer, (size_t)statinfo.st_size, fflagopts,
501: sizeof(fflagopts)/sizeof(struct lookfor));
1.10 phil 502:
1.34 dsl 503: /* free the buffer */
504: free(buffer);
1.3 phil 505: }
CVSweb <webmaster@jp.NetBSD.org>