1 /* $NetBSD: main.c,v 1.53 2008/12/21 11:02:41 martin Exp $ */
4 * Copyright 1997 Piermont Information Systems Inc.
7 * Written by Philip A. Nelson for Piermont Information Systems Inc.
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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:
19 * This product includes software developed for the NetBSD Project by
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
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.
39 /* main sysinst program. */
41 #include <sys/types.h>
55 #include "menu_defs.h"
58 int main(int, char **);
59 static void select_language(void);
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 *);
66 static int exit_cleanly
= 0; /* Did we finish nicely? */
67 int logging
; /* are we logging everything? */
68 int scripting
; /* are we building a script? */
69 FILE *logfp
; /* log file */
70 FILE *script
; /* script file */
73 extern int log_flip(void);
76 /* String defaults and stuff for processing the -f file argument. */
85 static const struct f_arg fflagopts
[] = {
86 {"release", REL
, rel
, sizeof rel
},
87 {"machine", MACH
, machine
, sizeof machine
},
88 {"xfer dir", "/usr/INSTALL", xfer_dir
, sizeof xfer_dir
},
89 {"ext dir", "", ext_dir
, sizeof ext_dir
},
90 {"ftp host", SYSINST_FTP_HOST
, ftp
.host
, sizeof ftp
.host
},
91 {"ftp dir", SYSINST_FTP_DIR
, ftp
.dir
, sizeof ftp
.dir
},
92 {"ftp prefix", "/" MACH
"/binary/sets", set_dir
, sizeof set_dir
},
93 {"ftp user", "ftp", ftp
.user
, sizeof ftp
.user
},
94 {"ftp pass", "", ftp
.pass
, sizeof ftp
.pass
},
95 {"ftp proxy", "", ftp
.proxy
, sizeof ftp
.proxy
},
96 {"nfs host", "", nfs_host
, sizeof nfs_host
},
97 {"nfs dir", "/bsd/release", nfs_dir
, sizeof nfs_dir
},
98 {"cd dev", "cd0a", cdrom_dev
, sizeof cdrom_dev
},
99 {"fd dev", "/dev/fd0a", fd_dev
, sizeof fd_dev
},
100 {"local dev", "", localfs_dev
, sizeof localfs_dev
},
101 {"local fs", "ffs", localfs_fs
, sizeof localfs_fs
},
102 {"local dir", "release", localfs_dir
, sizeof localfs_dir
},
103 {"targetroot mount", "/targetroot", targetroot_mnt
, sizeof targetroot_mnt
},
104 {"dist postfix", ".tgz", dist_postfix
, sizeof dist_postfix
},
105 {"diskname", "mydisk", bsddiskname
, sizeof bsddiskname
},
107 {NULL
, NULL
, NULL
, 0}
113 const struct f_arg
*arg
;
116 disktype
= "unknown";
117 tmp_ramdisk_size
= 0;
123 for (arg
= fflagopts
; arg
->name
!= NULL
; arg
++)
124 strlcpy(arg
->var
, arg
->dflt
, arg
->size
);
128 main(int argc
, char **argv
)
133 logging
= 0; /* shut them off unless turned on by the user */
140 /* Check for TERM ... */
141 if (!getenv("TERM")) {
142 (void)fprintf(stderr
,
143 "sysinst: environment variable TERM not set.\n");
147 /* argv processing */
148 while ((ch
= getopt(argc
, argv
, "Dr:f:")) != -1)
150 case 'D': /* set to get past certain errors in testing */
154 /* Release name other than compiled in release. */
155 strncpy(rel
, optarg
, sizeof rel
);
158 /* Definition file to read. */
159 process_f_flag(optarg
);
168 /* initialize message window */
175 * Put 'messages' in a window that has a one-character border
176 * on the real screen.
178 win
= newwin(getmaxy(stdscr
) - 2, getmaxx(stdscr
) - 2, 1, 1);
180 (void)fprintf(stderr
,
181 "sysinst: screen too small\n");
186 * XXX This color trick should be done so much better,
187 * but is it worth it?
189 wbkgd(win
, COLOR_PAIR(1));
190 wattrset(win
, COLOR_PAIR(1));
194 /* Watch for signals and clean up */
195 (void)atexit(cleanup
);
196 (void)signal(SIGINT
, ttysighandler
);
197 (void)signal(SIGQUIT
, ttysighandler
);
198 (void)signal(SIGHUP
, miscsighandler
);
204 /* Ensure we have mountpoint for target filesystems */
205 mkdir(targetroot_mnt
, S_IRWXU
| S_IRGRP
|S_IXGRP
| S_IROTH
|S_IXOTH
);
210 /* Menu processing */
211 process_menu(MENU_netbsd
, NULL
);
218 set_language(menudesc
*m
, void *arg
)
222 msg_file(fnames
[m
->cursel
]);
227 select_language(void)
230 struct dirent
*dirent
;
231 char **lang_msg
, **fnames
;
232 int max_lang
= 16, num_lang
= 0;
242 lang_msg
= malloc(max_lang
* sizeof *lang_msg
);
243 fnames
= malloc(max_lang
* sizeof *fnames
);
244 if (!lang_msg
|| !fnames
)
247 lang_msg
[0] = strdup(msg_string(MSG_sysinst_message_language
));
251 while ((dirent
= readdir(dir
)) != 0) {
252 if (memcmp(dirent
->d_name
, "sysinstmsgs.", 12))
254 if (msg_file(dirent
->d_name
))
256 cp
= msg_string(MSG_sysinst_message_language
);
257 if (!strcmp(cp
, lang_msg
[0]))
259 if (num_lang
== max_lang
) {
262 new = realloc(lang_msg
, max_lang
* sizeof *lang_msg
);
266 new = realloc(fnames
, max_lang
* sizeof *fnames
);
271 fnames
[num_lang
] = strdup(dirent
->d_name
);
272 lang_msg
[num_lang
++] = strdup(cp
);
281 opt
= calloc(num_lang
, sizeof *opt
);
285 for (lang
= 0; lang
< num_lang
; lang
++) {
286 opt
[lang
].opt_name
= lang_msg
[lang
];
287 opt
[lang
].opt_menu
= OPT_NOMENU
;
288 opt
[lang
].opt_action
= set_language
;
291 lang_menu
= new_menu(NULL
, opt
, num_lang
, -1, 12, 0, 0, MC_NOEXITOPT
,
292 NULL
, NULL
, NULL
, NULL
, NULL
);
294 if (lang_menu
!= -1) {
295 msg_display(MSG_hello
);
296 process_menu(lang_menu
, fnames
);
303 free_menu(lang_menu
);
306 free(lang_msg
[--num_lang
]);
307 free(fnames
[num_lang
]);
312 /* set locale according to selected language */
313 cp
= msg_string(MSG_sysinst_message_locale
);
315 setlocale(LC_CTYPE
, cp
);
316 setenv("LC_CTYPE", cp
, 1);
320 /* toplevel menu handler ... */
325 /* Display banner message in (english, francais, deutsch..) */
326 msg_display(MSG_hello
);
327 msg_display_add(MSG_md_hello
);
328 msg_display_add(MSG_thanks
);
331 * Undo any stateful side-effects of previous menu choices.
332 * XXX must be idempotent, since we get run each time the main
346 (void)fprintf(stderr
, msg_string(MSG_usage
));
352 miscsighandler(int signo
)
356 * we need to cleanup(), but it was already scheduled with atexit(),
357 * so it'll be invoked on exit().
363 ttysighandler(int signo
)
367 * if we want to ignore a TTY signal (SIGINT or SIGQUIT), then we
368 * just return. If we want to forward a TTY signal, we forward it
369 * to the specified process group.
371 * This functionality is used when setting up and displaying child
372 * output so that the child gets the signal and presumably dies,
373 * but sysinst continues. We use this rather than actually ignoring
374 * the signals, because that will be be passed on to a child
375 * through fork/exec, whereas special handlers get reset on exec..
379 if (ttysig_forward
) {
380 killpg(ttysig_forward
, signo
);
385 * we need to cleanup(), but it was already scheduled with atexit(),
386 * so it'll be invoked on exit().
401 /* Ensure we aren't inside the target tree */
402 chdir(getenv("HOME"));
409 fprintf(logfp
, "Log ended at: %s\n", asctime(localtime(&tloc
)));
414 fprintf(script
, "# Script ended at: %s\n",
415 asctime(localtime(&tloc
)));
421 fprintf(stderr
, "\n\nsysinst terminated.\n");
425 /* process function ... */
428 process_f_flag(char *f_name
)
430 char buffer
[STRSIZE
];
432 const struct f_arg
*arg
;
437 fp
= fopen(f_name
, "r");
439 fprintf(stderr
, msg_string(MSG_config_open_error
), f_name
);
443 while (fgets(buffer
, sizeof buffer
, fp
) != NULL
) {
444 cp
= buffer
+ strspn(buffer
, " \t");
445 if (strchr("#\r\n", *cp
) != NULL
)
447 for (arg
= fflagopts
; arg
->name
!= NULL
; arg
++) {
448 len
= strlen(arg
->name
);
449 if (memcmp(cp
, arg
->name
, len
) != 0)
452 cp1
+= strspn(cp1
, " \t");
455 cp1
+= strspn(cp1
, " \t");
456 len
= strcspn(cp1
, " \n\r\t");
458 strlcpy(arg
->var
, cp1
, arg
->size
);