1 1.33 martin /* $NetBSD: main.c,v 1.34 2025/07/25 17:28:50 martin Exp $ */ 2 1.1 dholland 3 1.1 dholland /* 4 1.1 dholland * Copyright 1997 Piermont Information Systems Inc. 5 1.1 dholland * All rights reserved. 6 1.1 dholland * 7 1.1 dholland * Written by Philip A. Nelson for Piermont Information Systems Inc. 8 1.1 dholland * 9 1.1 dholland * Redistribution and use in source and binary forms, with or without 10 1.1 dholland * modification, are permitted provided that the following conditions 11 1.1 dholland * are met: 12 1.1 dholland * 1. Redistributions of source code must retain the above copyright 13 1.1 dholland * notice, this list of conditions and the following disclaimer. 14 1.1 dholland * 2. Redistributions in binary form must reproduce the above copyright 15 1.1 dholland * notice, this list of conditions and the following disclaimer in the 16 1.1 dholland * documentation and/or other materials provided with the distribution. 17 1.1 dholland * 3. The name of Piermont Information Systems Inc. may not be used to endorse 18 1.1 dholland * or promote products derived from this software without specific prior 19 1.1 dholland * written permission. 20 1.1 dholland * 21 1.1 dholland * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS'' 22 1.1 dholland * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23 1.1 dholland * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24 1.1 dholland * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE 25 1.1 dholland * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 1.1 dholland * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 1.1 dholland * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 1.1 dholland * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 1.1 dholland * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 1.1 dholland * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF 31 1.1 dholland * THE POSSIBILITY OF SUCH DAMAGE. 32 1.1 dholland * 33 1.1 dholland */ 34 1.1 dholland 35 1.1 dholland /* main sysinst program. */ 36 1.1 dholland 37 1.1 dholland #include <sys/types.h> 38 1.1 dholland #include <sys/stat.h> 39 1.3 martin #include <sys/syslimits.h> 40 1.1 dholland #include <sys/uio.h> 41 1.1 dholland #include <stdio.h> 42 1.1 dholland #include <signal.h> 43 1.1 dholland #include <curses.h> 44 1.1 dholland #include <unistd.h> 45 1.1 dholland #include <fcntl.h> 46 1.1 dholland #include <dirent.h> 47 1.1 dholland #include <locale.h> 48 1.1 dholland 49 1.1 dholland #include "defs.h" 50 1.1 dholland #include "md.h" 51 1.1 dholland #include "msg_defs.h" 52 1.1 dholland #include "menu_defs.h" 53 1.1 dholland #include "txtwalk.h" 54 1.1 dholland 55 1.24 joerg int debug; 56 1.24 joerg char machine[SSTRSIZE]; 57 1.24 joerg int ignorerror; 58 1.24 joerg int ttysig_ignore; 59 1.24 joerg pid_t ttysig_forward; 60 1.24 joerg uint sizemult; 61 1.24 joerg int partman_go; 62 1.24 joerg FILE *logfp; 63 1.24 joerg FILE *script; 64 1.24 joerg daddr_t root_limit; 65 1.24 joerg struct pm_head_t pm_head; 66 1.24 joerg struct pm_devs *pm; 67 1.24 joerg struct pm_devs *pm_new; 68 1.24 joerg char xfer_dir[STRSIZE]; 69 1.24 joerg int clean_xfer_dir; 70 1.24 joerg char ext_dir_bin[STRSIZE]; 71 1.24 joerg char ext_dir_src[STRSIZE]; 72 1.24 joerg char ext_dir_pkgsrc[STRSIZE]; 73 1.24 joerg char set_dir_bin[STRSIZE]; 74 1.24 joerg char set_dir_src[STRSIZE]; 75 1.24 joerg char pkg_dir[STRSIZE]; 76 1.24 joerg char pkgsrc_dir[STRSIZE]; 77 1.24 joerg const char *ushell; 78 1.24 joerg struct ftpinfo ftp, pkg, pkgsrc; 79 1.24 joerg int (*fetch_fn)(const char *); 80 1.24 joerg char nfs_host[STRSIZE]; 81 1.24 joerg char nfs_dir[STRSIZE]; 82 1.24 joerg char cdrom_dev[SSTRSIZE]; 83 1.24 joerg char fd_dev[SSTRSIZE]; 84 1.24 joerg const char *fd_type; 85 1.24 joerg char localfs_dev[SSTRSIZE]; 86 1.24 joerg char localfs_fs[SSTRSIZE]; 87 1.24 joerg char localfs_dir[STRSIZE]; 88 1.24 joerg char targetroot_mnt[SSTRSIZE]; 89 1.24 joerg int mnt2_mounted; 90 1.24 joerg char dist_postfix[SSTRSIZE]; 91 1.24 joerg char dist_tgz_postfix[SSTRSIZE]; 92 1.24 joerg WINDOW *mainwin; 93 1.24 joerg 94 1.28 martin static void select_language(const char*); 95 1.1 dholland __dead static void usage(void); 96 1.1 dholland __dead static void miscsighandler(int); 97 1.1 dholland static void ttysighandler(int); 98 1.1 dholland static void cleanup(void); 99 1.1 dholland static void process_f_flag(char *); 100 1.31 martin static bool no_openssl_trust_anchors_available(void); 101 1.1 dholland 102 1.1 dholland static int exit_cleanly = 0; /* Did we finish nicely? */ 103 1.1 dholland FILE *logfp; /* log file */ 104 1.1 dholland FILE *script; /* script file */ 105 1.1 dholland 106 1.16 martin const char *multname; 107 1.16 martin const char *err_outofmem; 108 1.16 martin 109 1.1 dholland #ifdef DEBUG 110 1.1 dholland extern int log_flip(void); 111 1.1 dholland #endif 112 1.1 dholland 113 1.2 martin /* Definion for colors */ 114 1.2 martin 115 1.2 martin struct { 116 1.2 martin unsigned int bg; 117 1.2 martin unsigned int fg; 118 1.2 martin } clr_arg; 119 1.2 martin 120 1.1 dholland /* String defaults and stuff for processing the -f file argument. */ 121 1.1 dholland 122 1.1 dholland struct f_arg { 123 1.1 dholland const char *name; 124 1.1 dholland const char *dflt; 125 1.1 dholland char *var; 126 1.1 dholland int size; 127 1.1 dholland }; 128 1.1 dholland 129 1.1 dholland static const struct f_arg fflagopts[] = { 130 1.22 martin {"release", REL, NULL, 0}, 131 1.1 dholland {"machine", MACH, machine, sizeof machine}, 132 1.15 martin {"xfer dir", "/usr/INSTALL", xfer_dir, sizeof xfer_dir}, 133 1.1 dholland {"ext dir", "", ext_dir_bin, sizeof ext_dir_bin}, 134 1.1 dholland {"ext src dir", "", ext_dir_src, sizeof ext_dir_src}, 135 1.32 martin {"ftp host", SYSINST_FTP_HOST, ftp.xfer_host[XFER_HOST(XFER_FTP)], sizeof ftp.xfer_host[XFER_HOST(XFER_FTP)]}, 136 1.32 martin {"http host", SYSINST_HTTP_HOST, ftp.xfer_host[XFER_HOST(XFER_HTTP)], sizeof ftp.xfer_host[XFER_HOST(XFER_HTTP)]}, 137 1.1 dholland {"ftp dir", SYSINST_FTP_DIR, ftp.dir, sizeof ftp.dir}, 138 1.14 martin {"ftp prefix", "/" ARCH_SUBDIR "/binary/sets", set_dir_bin, sizeof set_dir_bin}, 139 1.1 dholland {"ftp src prefix", "/source/sets", set_dir_src, sizeof set_dir_src}, 140 1.1 dholland {"ftp user", "ftp", ftp.user, sizeof ftp.user}, 141 1.1 dholland {"ftp pass", "", ftp.pass, sizeof ftp.pass}, 142 1.1 dholland {"ftp proxy", "", ftp.proxy, sizeof ftp.proxy}, 143 1.1 dholland {"nfs host", "", nfs_host, sizeof nfs_host}, 144 1.1 dholland {"nfs dir", "/bsd/release", nfs_dir, sizeof nfs_dir}, 145 1.1 dholland {"cd dev", 0, cdrom_dev, sizeof cdrom_dev}, /* default filled in init */ 146 1.1 dholland {"fd dev", "/dev/fd0a", fd_dev, sizeof fd_dev}, 147 1.1 dholland {"local dev", "", localfs_dev, sizeof localfs_dev}, 148 1.1 dholland {"local fs", "ffs", localfs_fs, sizeof localfs_fs}, 149 1.1 dholland {"local dir", "release", localfs_dir, sizeof localfs_dir}, 150 1.1 dholland {"targetroot mount", "/targetroot", targetroot_mnt, sizeof targetroot_mnt}, 151 1.11 martin {"dist postfix", "." SETS_TAR_SUFF, dist_postfix, sizeof dist_postfix}, 152 1.11 martin {"dist tgz postfix", ".tgz", dist_tgz_postfix, sizeof dist_tgz_postfix}, 153 1.32 martin {"pkg host", SYSINST_PKG_HOST, pkg.xfer_host[XFER_HOST(XFER_FTP)], sizeof pkg.xfer_host[XFER_HOST(XFER_FTP)]}, 154 1.32 martin {"pkg http host", SYSINST_PKG_HTTP_HOST, pkg.xfer_host[XFER_HOST(XFER_HTTP)], sizeof pkg.xfer_host[XFER_HOST(XFER_HTTP)]}, 155 1.1 dholland {"pkg dir", SYSINST_PKG_DIR, pkg.dir, sizeof pkg.dir}, 156 1.14 martin {"pkg prefix", "/" PKG_ARCH_SUBDIR "/" PKG_SUBDIR "/All", pkg_dir, sizeof pkg_dir}, 157 1.1 dholland {"pkg user", "ftp", pkg.user, sizeof pkg.user}, 158 1.1 dholland {"pkg pass", "", pkg.pass, sizeof pkg.pass}, 159 1.1 dholland {"pkg proxy", "", pkg.proxy, sizeof pkg.proxy}, 160 1.32 martin {"pkgsrc host", SYSINST_PKGSRC_HOST, pkgsrc.xfer_host[XFER_HOST(XFER_FTP)], sizeof pkgsrc.xfer_host[XFER_HOST(XFER_FTP)]}, 161 1.32 martin {"pkgsrc http host", SYSINST_PKGSRC_HTTP_HOST, pkgsrc.xfer_host[XFER_HOST(XFER_HTTP)], sizeof pkgsrc.xfer_host[XFER_HOST(XFER_HTTP)]}, 162 1.1 dholland {"pkgsrc dir", "", pkgsrc.dir, sizeof pkgsrc.dir}, 163 1.1 dholland {"pkgsrc prefix", "pub/pkgsrc/stable", pkgsrc_dir, sizeof pkgsrc_dir}, 164 1.1 dholland {"pkgsrc user", "ftp", pkgsrc.user, sizeof pkgsrc.user}, 165 1.1 dholland {"pkgsrc pass", "", pkgsrc.pass, sizeof pkgsrc.pass}, 166 1.1 dholland {"pkgsrc proxy", "", pkgsrc.proxy, sizeof pkgsrc.proxy}, 167 1.1 dholland 168 1.1 dholland {NULL, NULL, NULL, 0} 169 1.1 dholland }; 170 1.1 dholland 171 1.1 dholland static void 172 1.1 dholland init(void) 173 1.1 dholland { 174 1.1 dholland const struct f_arg *arg; 175 1.27 rillig 176 1.1 dholland sizemult = 1; 177 1.1 dholland clean_xfer_dir = 0; 178 1.1 dholland mnt2_mounted = 0; 179 1.1 dholland fd_type = "msdos"; 180 1.2 martin 181 1.2 martin pm_head = (struct pm_head_t) SLIST_HEAD_INITIALIZER(pm_head); 182 1.2 martin SLIST_INIT(&pm_head); 183 1.16 martin pm_new = malloc(sizeof (struct pm_devs)); 184 1.2 martin memset(pm_new, 0, sizeof *pm_new); 185 1.1 dholland 186 1.1 dholland for (arg = fflagopts; arg->name != NULL; arg++) { 187 1.23 martin if (arg->var == NULL) 188 1.23 martin continue; 189 1.1 dholland if (arg->var == cdrom_dev) 190 1.13 martin get_default_cdrom(arg->var, arg->size); 191 1.1 dholland else 192 1.1 dholland strlcpy(arg->var, arg->dflt, arg->size); 193 1.1 dholland } 194 1.32 martin ftp.xfer = pkg.xfer = pkgsrc.xfer = XFER_HTTPS; 195 1.27 rillig 196 1.2 martin clr_arg.bg=COLOR_BLUE; 197 1.2 martin clr_arg.fg=COLOR_WHITE; 198 1.1 dholland } 199 1.1 dholland 200 1.16 martin static void 201 1.16 martin init_lang(void) 202 1.27 rillig { 203 1.16 martin sizemult = 1; 204 1.16 martin err_outofmem = msg_string(MSG_out_of_memory); 205 1.16 martin multname = msg_string(MSG_secname); 206 1.16 martin } 207 1.16 martin 208 1.1 dholland int 209 1.1 dholland main(int argc, char **argv) 210 1.1 dholland { 211 1.34 martin int ch, no_https = 0; 212 1.28 martin const char *msg_cat_dir = NULL; 213 1.1 dholland 214 1.1 dholland init(); 215 1.16 martin 216 1.1 dholland #ifdef DEBUG 217 1.1 dholland log_flip(); 218 1.1 dholland #endif 219 1.2 martin 220 1.1 dholland /* Check for TERM ... */ 221 1.1 dholland if (!getenv("TERM")) { 222 1.1 dholland (void)fprintf(stderr, 223 1.1 dholland "sysinst: environment variable TERM not set.\n"); 224 1.1 dholland exit(4); 225 1.1 dholland } 226 1.1 dholland 227 1.1 dholland /* argv processing */ 228 1.28 martin while ((ch = getopt(argc, argv, "Dr:f:C:m:" 229 1.10 rin #ifndef NO_PARTMAN 230 1.10 rin "p" 231 1.10 rin #endif 232 1.10 rin )) != -1) 233 1.1 dholland switch(ch) { 234 1.1 dholland case 'D': /* set to get past certain errors in testing */ 235 1.1 dholland debug = 1; 236 1.1 dholland break; 237 1.1 dholland case 'r': 238 1.22 martin /* Release name - ignore for compatibility with older versions */ 239 1.1 dholland break; 240 1.1 dholland case 'f': 241 1.1 dholland /* Definition file to read. */ 242 1.1 dholland process_f_flag(optarg); 243 1.1 dholland break; 244 1.2 martin case 'C': 245 1.2 martin /* Define colors */ 246 1.2 martin sscanf(optarg, "%u:%u", &clr_arg.bg, &clr_arg.fg); 247 1.2 martin break; 248 1.28 martin case 'm': 249 1.28 martin /* set message catalog directory */ 250 1.28 martin msg_cat_dir = optarg; 251 1.28 martin break; 252 1.10 rin #ifndef NO_PARTMAN 253 1.2 martin case 'p': 254 1.2 martin /* Partition tool */ 255 1.2 martin partman_go = 1; 256 1.2 martin break; 257 1.10 rin #endif 258 1.1 dholland case '?': 259 1.1 dholland default: 260 1.1 dholland usage(); 261 1.1 dholland } 262 1.1 dholland 263 1.1 dholland md_init(); 264 1.1 dholland 265 1.16 martin /* Initialize the partitioning subsystem */ 266 1.16 martin partitions_init(); 267 1.16 martin 268 1.31 martin /* do we need to tell ftp(1) to avoid checking certificate chains? */ 269 1.34 martin if (no_openssl_trust_anchors_available()) { 270 1.31 martin setenv("FTPSSLNOVERIFY", "1", 1); 271 1.34 martin no_https = 1; 272 1.34 martin } 273 1.31 martin 274 1.1 dholland /* initialize message window */ 275 1.1 dholland if (menu_init()) { 276 1.1 dholland __menu_initerror(); 277 1.1 dholland exit(4); 278 1.1 dholland } 279 1.1 dholland 280 1.1 dholland /* 281 1.1 dholland * Put 'messages' in a window that has a one-character border 282 1.1 dholland * on the real screen. 283 1.1 dholland */ 284 1.2 martin mainwin = newwin(getmaxy(stdscr) - 2, getmaxx(stdscr) - 2, 1, 1); 285 1.2 martin if (mainwin == NULL) { 286 1.1 dholland (void)fprintf(stderr, 287 1.1 dholland "sysinst: screen too small\n"); 288 1.1 dholland exit(1); 289 1.1 dholland } 290 1.1 dholland if (has_colors()) { 291 1.2 martin start_color(); 292 1.2 martin do_coloring(clr_arg.fg,clr_arg.bg); 293 1.1 dholland } 294 1.2 martin msg_window(mainwin); 295 1.1 dholland 296 1.1 dholland /* Watch for signals and clean up */ 297 1.1 dholland (void)atexit(cleanup); 298 1.1 dholland (void)signal(SIGINT, ttysighandler); 299 1.1 dholland (void)signal(SIGQUIT, ttysighandler); 300 1.1 dholland (void)signal(SIGHUP, miscsighandler); 301 1.1 dholland 302 1.1 dholland /* redraw screen */ 303 1.1 dholland touchwin(stdscr); 304 1.1 dholland refresh(); 305 1.1 dholland 306 1.1 dholland /* Ensure we have mountpoint for target filesystems */ 307 1.27 rillig mkdir(targetroot_mnt, S_IRWXU | S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH); 308 1.1 dholland 309 1.28 martin select_language(msg_cat_dir); 310 1.1 dholland get_kb_encoding(); 311 1.16 martin init_lang(); 312 1.1 dholland 313 1.33 martin /* remove some invalid menu entries */ 314 1.33 martin if (!has_colors()) 315 1.33 martin remove_color_options(); 316 1.34 martin if (no_https) 317 1.34 martin remove_https_options(); 318 1.33 martin 319 1.1 dholland /* Menu processing */ 320 1.2 martin if (partman_go) 321 1.30 martin partman(NULL); 322 1.2 martin else 323 1.2 martin process_menu(MENU_netbsd, NULL); 324 1.1 dholland 325 1.16 martin #ifndef NO_PARTMAN 326 1.16 martin /* clean up internal storage */ 327 1.16 martin pm_destroy_all(); 328 1.16 martin #endif 329 1.16 martin 330 1.18 martin partitions_cleanup(); 331 1.18 martin 332 1.1 dholland exit_cleanly = 1; 333 1.1 dholland return 0; 334 1.1 dholland } 335 1.1 dholland 336 1.1 dholland static int 337 1.1 dholland set_language(menudesc *m, void *arg) 338 1.1 dholland { 339 1.1 dholland char **fnames = arg; 340 1.1 dholland 341 1.1 dholland msg_file(fnames[m->cursel]); 342 1.1 dholland return 1; 343 1.1 dholland } 344 1.1 dholland 345 1.28 martin /* 346 1.28 martin * Search for sysinstmsg.* files in the given dir, collect 347 1.28 martin * their names and return the number of files found. 348 1.28 martin * fnames[0] is preallocated and duplicates are ignored. 349 1.28 martin */ 350 1.28 martin struct found_msgs { 351 1.28 martin char **lang_msg, **fnames; 352 1.28 martin int max_lang, num_lang; 353 1.28 martin 354 1.28 martin }; 355 1.1 dholland static void 356 1.28 martin find_language_files(const char *path, struct found_msgs *res) 357 1.1 dholland { 358 1.1 dholland DIR *dir; 359 1.1 dholland struct dirent *dirent; 360 1.28 martin char fname[PATH_MAX]; 361 1.1 dholland const char *cp; 362 1.1 dholland 363 1.28 martin res->num_lang = 0; 364 1.28 martin dir = opendir(path); 365 1.1 dholland if (!dir) 366 1.1 dholland return; 367 1.1 dholland 368 1.1 dholland while ((dirent = readdir(dir)) != 0) { 369 1.1 dholland if (memcmp(dirent->d_name, "sysinstmsgs.", 12)) 370 1.1 dholland continue; 371 1.28 martin 372 1.28 martin if (res->num_lang == 0) 373 1.28 martin res->num_lang = 1; 374 1.28 martin strcpy(fname, path); 375 1.28 martin strcat(fname, "/"); 376 1.3 martin strcat(fname, dirent->d_name); 377 1.3 martin if (msg_file(fname)) 378 1.1 dholland continue; 379 1.1 dholland cp = msg_string(MSG_sysinst_message_language); 380 1.28 martin if (!strcmp(cp, res->lang_msg[0])) 381 1.1 dholland continue; 382 1.28 martin if (res->num_lang == res->max_lang) { 383 1.1 dholland char **new; 384 1.28 martin res->max_lang *= 2; 385 1.28 martin new = realloc(res->lang_msg, 386 1.28 martin res->max_lang * sizeof *res->lang_msg); 387 1.1 dholland if (!new) 388 1.1 dholland break; 389 1.28 martin res->lang_msg = new; 390 1.28 martin new = realloc(res->fnames, 391 1.28 martin res->max_lang * sizeof *res->fnames); 392 1.1 dholland if (!new) 393 1.1 dholland break; 394 1.28 martin res->fnames = new; 395 1.1 dholland } 396 1.28 martin res->fnames[res->num_lang] = strdup(fname); 397 1.28 martin res->lang_msg[res->num_lang++] = strdup(cp); 398 1.1 dholland } 399 1.28 martin 400 1.28 martin closedir(dir); 401 1.28 martin } 402 1.28 martin 403 1.28 martin static void 404 1.28 martin select_language(const char *msg_cat_path) 405 1.28 martin { 406 1.28 martin struct found_msgs found; 407 1.28 martin menu_ent *opt = 0; 408 1.28 martin const char *cp; 409 1.28 martin int lang_menu = -1; 410 1.28 martin int lang; 411 1.28 martin 412 1.28 martin found.max_lang = 16; 413 1.28 martin found.num_lang = 0; 414 1.28 martin found.lang_msg = malloc(found.max_lang * sizeof *found.lang_msg); 415 1.28 martin found.fnames = malloc(found.max_lang * sizeof *found.fnames); 416 1.28 martin if (!found.lang_msg || !found.fnames) 417 1.28 martin goto done; 418 1.28 martin found.lang_msg[0] = strdup(msg_string(MSG_sysinst_message_language)); 419 1.28 martin found.fnames[0] = NULL; 420 1.28 martin 421 1.28 martin if (msg_cat_path != NULL) 422 1.28 martin find_language_files(msg_cat_path, &found); 423 1.28 martin if (found.num_lang == 0) 424 1.28 martin find_language_files(".", &found); 425 1.28 martin #ifdef CATALOG_DIR 426 1.28 martin if (found.num_lang == 0) 427 1.28 martin find_language_files(CATALOG_DIR, &found); 428 1.28 martin #endif 429 1.28 martin 430 1.1 dholland msg_file(0); 431 1.1 dholland 432 1.28 martin if (found.num_lang <= 1) 433 1.1 dholland goto done; 434 1.1 dholland 435 1.28 martin opt = calloc(found.num_lang, sizeof *opt); 436 1.1 dholland if (!opt) 437 1.1 dholland goto done; 438 1.1 dholland 439 1.28 martin for (lang = 0; lang < found.num_lang; lang++) { 440 1.28 martin opt[lang].opt_name = found.lang_msg[lang]; 441 1.1 dholland opt[lang].opt_action = set_language; 442 1.1 dholland } 443 1.1 dholland 444 1.28 martin lang_menu = new_menu(NULL, opt, found.num_lang, -1, 12, 0, 0, 445 1.28 martin MC_NOEXITOPT, NULL, NULL, NULL, NULL, NULL); 446 1.1 dholland 447 1.1 dholland if (lang_menu != -1) { 448 1.1 dholland msg_display(MSG_hello); 449 1.28 martin process_menu(lang_menu, found.fnames); 450 1.1 dholland } 451 1.1 dholland 452 1.1 dholland done: 453 1.1 dholland if (lang_menu != -1) 454 1.1 dholland free_menu(lang_menu); 455 1.1 dholland free(opt); 456 1.28 martin for (int i = 0; i < found.num_lang; i++) { 457 1.28 martin free(found.lang_msg[i]); 458 1.28 martin free(found.fnames[i]); 459 1.1 dholland } 460 1.28 martin free(found.lang_msg); 461 1.28 martin free(found.fnames); 462 1.1 dholland 463 1.1 dholland /* set locale according to selected language */ 464 1.1 dholland cp = msg_string(MSG_sysinst_message_locale); 465 1.1 dholland if (cp) { 466 1.1 dholland setlocale(LC_CTYPE, cp); 467 1.1 dholland setenv("LC_CTYPE", cp, 1); 468 1.1 dholland } 469 1.1 dholland } 470 1.1 dholland 471 1.1 dholland #ifndef md_may_remove_boot_medium 472 1.1 dholland #define md_may_remove_boot_medium() (boot_media_still_needed()<=0) 473 1.1 dholland #endif 474 1.1 dholland 475 1.1 dholland /* toplevel menu handler ... */ 476 1.1 dholland void 477 1.1 dholland toplevel(void) 478 1.1 dholland { 479 1.2 martin /* 480 1.2 martin * Undo any stateful side-effects of previous menu choices. 481 1.2 martin * XXX must be idempotent, since we get run each time the main 482 1.2 martin * menu is displayed. 483 1.2 martin */ 484 1.4 martin char *home = getenv("HOME"); 485 1.4 martin if (home != NULL) 486 1.5 martin if (chdir(home) != 0) 487 1.5 martin (void)chdir("/"); 488 1.2 martin unwind_mounts(); 489 1.25 martin clear_swap(); 490 1.1 dholland 491 1.1 dholland /* Display banner message in (english, francais, deutsch..) */ 492 1.1 dholland msg_display(MSG_hello); 493 1.1 dholland msg_display_add(MSG_md_hello); 494 1.1 dholland if (md_may_remove_boot_medium()) 495 1.1 dholland msg_display_add(MSG_md_may_remove_boot_medium); 496 1.1 dholland msg_display_add(MSG_thanks); 497 1.1 dholland } 498 1.1 dholland 499 1.1 dholland 500 1.1 dholland /* The usage ... */ 501 1.1 dholland 502 1.1 dholland static void 503 1.1 dholland usage(void) 504 1.1 dholland { 505 1.1 dholland 506 1.29 wiz (void)fprintf(stderr, "usage: sysinst [-C bg:fg] [-D" 507 1.12 martin #ifndef NO_PARTMAN 508 1.29 wiz "p" 509 1.12 martin #endif 510 1.29 wiz "] [-f definition_file] " 511 1.29 wiz "[-m message_catalog_dir]" 512 1.12 martin "\n" 513 1.12 martin "where:\n" 514 1.29 wiz "\t-C bg:fg\n\t\tuse different color scheme\n" 515 1.12 martin "\t-D\n\t\trun in debug mode\n" 516 1.12 martin "\t-f definition_file\n\t\toverride built-in defaults from file\n" 517 1.28 martin "\t-m msg_catalog_dir\n\t\tuse translation files from msg_catalog_dir\n" 518 1.12 martin #ifndef NO_PARTMAN 519 1.12 martin "\t-p\n\t\tonly run the partition editor, no installation\n" 520 1.12 martin #endif 521 1.12 martin ); 522 1.12 martin 523 1.1 dholland exit(1); 524 1.1 dholland } 525 1.1 dholland 526 1.1 dholland /* ARGSUSED */ 527 1.1 dholland static void 528 1.1 dholland miscsighandler(int signo) 529 1.1 dholland { 530 1.1 dholland 531 1.1 dholland /* 532 1.1 dholland * we need to cleanup(), but it was already scheduled with atexit(), 533 1.1 dholland * so it'll be invoked on exit(). 534 1.1 dholland */ 535 1.1 dholland exit(1); 536 1.1 dholland } 537 1.1 dholland 538 1.1 dholland static void 539 1.1 dholland ttysighandler(int signo) 540 1.1 dholland { 541 1.1 dholland 542 1.1 dholland /* 543 1.1 dholland * if we want to ignore a TTY signal (SIGINT or SIGQUIT), then we 544 1.1 dholland * just return. If we want to forward a TTY signal, we forward it 545 1.1 dholland * to the specified process group. 546 1.1 dholland * 547 1.1 dholland * This functionality is used when setting up and displaying child 548 1.1 dholland * output so that the child gets the signal and presumably dies, 549 1.1 dholland * but sysinst continues. We use this rather than actually ignoring 550 1.26 msaitoh * the signals, because that will be passed on to a child 551 1.1 dholland * through fork/exec, whereas special handlers get reset on exec.. 552 1.1 dholland */ 553 1.1 dholland if (ttysig_ignore) 554 1.1 dholland return; 555 1.1 dholland if (ttysig_forward) { 556 1.1 dholland killpg(ttysig_forward, signo); 557 1.1 dholland return; 558 1.1 dholland } 559 1.1 dholland 560 1.1 dholland /* 561 1.1 dholland * we need to cleanup(), but it was already scheduled with atexit(), 562 1.1 dholland * so it'll be invoked on exit(). 563 1.1 dholland */ 564 1.1 dholland exit(1); 565 1.1 dholland } 566 1.1 dholland 567 1.1 dholland static void 568 1.1 dholland cleanup(void) 569 1.1 dholland { 570 1.1 dholland time_t tloc; 571 1.1 dholland 572 1.1 dholland (void)time(&tloc); 573 1.1 dholland 574 1.1 dholland #if 0 575 1.1 dholland restore_etc(); 576 1.1 dholland #endif 577 1.1 dholland /* Ensure we aren't inside the target tree */ 578 1.1 dholland chdir(getenv("HOME")); 579 1.1 dholland unwind_mounts(); 580 1.1 dholland umount_mnt2(); 581 1.25 martin clear_swap(); 582 1.1 dholland 583 1.1 dholland endwin(); 584 1.1 dholland 585 1.1 dholland if (logfp) { 586 1.6 christos fprintf(logfp, "Log ended at: %s\n", safectime(&tloc)); 587 1.1 dholland fflush(logfp); 588 1.1 dholland fclose(logfp); 589 1.1 dholland logfp = NULL; 590 1.1 dholland } 591 1.1 dholland if (script) { 592 1.6 christos fprintf(script, "# Script ended at: %s\n", safectime(&tloc)); 593 1.1 dholland fflush(script); 594 1.1 dholland fclose(script); 595 1.1 dholland script = NULL; 596 1.1 dholland } 597 1.1 dholland 598 1.1 dholland if (!exit_cleanly) 599 1.1 dholland fprintf(stderr, "\n\nsysinst terminated.\n"); 600 1.1 dholland } 601 1.1 dholland 602 1.1 dholland 603 1.1 dholland /* process function ... */ 604 1.1 dholland 605 1.1 dholland void 606 1.1 dholland process_f_flag(char *f_name) 607 1.1 dholland { 608 1.1 dholland char buffer[STRSIZE]; 609 1.1 dholland int len; 610 1.1 dholland const struct f_arg *arg; 611 1.1 dholland FILE *fp; 612 1.16 martin char *cp, *cp1, *err; 613 1.1 dholland 614 1.1 dholland /* open the file */ 615 1.1 dholland fp = fopen(f_name, "r"); 616 1.1 dholland if (fp == NULL) { 617 1.16 martin const char *args[] = { f_name }; 618 1.16 martin err = str_arg_subst(msg_string(MSG_config_open_error), 619 1.16 martin __arraycount(args), args); 620 1.16 martin fprintf(stderr, "%s\n", err); 621 1.16 martin free(err); 622 1.1 dholland exit(1); 623 1.1 dholland } 624 1.1 dholland 625 1.1 dholland while (fgets(buffer, sizeof buffer, fp) != NULL) { 626 1.1 dholland cp = buffer + strspn(buffer, " \t"); 627 1.1 dholland if (strchr("#\r\n", *cp) != NULL) 628 1.1 dholland continue; 629 1.1 dholland for (arg = fflagopts; arg->name != NULL; arg++) { 630 1.1 dholland len = strlen(arg->name); 631 1.1 dholland if (memcmp(cp, arg->name, len) != 0) 632 1.1 dholland continue; 633 1.22 martin if (arg->var == NULL || arg->size == 0) 634 1.22 martin continue; 635 1.1 dholland cp1 = cp + len; 636 1.1 dholland cp1 += strspn(cp1, " \t"); 637 1.1 dholland if (*cp1++ != '=') 638 1.1 dholland continue; 639 1.1 dholland cp1 += strspn(cp1, " \t"); 640 1.1 dholland len = strcspn(cp1, " \n\r\t"); 641 1.1 dholland cp1[len] = 0; 642 1.1 dholland strlcpy(arg->var, cp1, arg->size); 643 1.1 dholland break; 644 1.1 dholland } 645 1.1 dholland } 646 1.1 dholland 647 1.1 dholland fclose(fp); 648 1.1 dholland } 649 1.31 martin 650 1.31 martin /* 651 1.31 martin * return true if we do not have any root certificates installed, 652 1.31 martin * so can not verify any trust chain. 653 1.31 martin * We rely on /etc/openssl being the OPENSSLDIR and test the 654 1.31 martin * "all in one" /etc/openssl/cert.pem first, if that is not found 655 1.31 martin * check if there are multiple regular files or symlinks in 656 1.31 martin * /etc/openssl/certs/. 657 1.31 martin */ 658 1.31 martin static bool 659 1.31 martin no_openssl_trust_anchors_available(void) 660 1.31 martin { 661 1.31 martin struct stat sb; 662 1.31 martin DIR *dir; 663 1.31 martin struct dirent *ent; 664 1.31 martin size_t cnt; 665 1.31 martin 666 1.31 martin /* check the omnibus single file variant first */ 667 1.31 martin if (stat("/etc/openssl/cert.pem", &sb) == 0 && 668 1.31 martin S_ISREG(sb.st_mode) && sb.st_size > 0) 669 1.31 martin return false; /* exists and is a non-empty file */ 670 1.31 martin 671 1.31 martin /* look for files/symlinks in the certs subdirectory */ 672 1.31 martin dir = opendir("/etc/openssl/certs"); 673 1.31 martin if (dir == NULL) 674 1.31 martin return true; 675 1.31 martin for (cnt = 0; cnt < 2; ) { 676 1.31 martin ent = readdir(dir); 677 1.31 martin if (ent == NULL) 678 1.31 martin break; 679 1.31 martin switch (ent->d_type) { 680 1.31 martin case DT_REG: 681 1.31 martin case DT_LNK: 682 1.31 martin cnt++; 683 1.31 martin break; 684 1.31 martin default: 685 1.31 martin break; 686 1.31 martin } 687 1.31 martin } 688 1.31 martin closedir(dir); 689 1.31 martin 690 1.31 martin return cnt < 2; 691 1.31 martin } 692