Annotation of src/distrib/utils/sysinst/util.c, Revision 1.97
1.97 ! dsl 1: /* $NetBSD: util.c,v 1.96 2003/06/11 11:00:39 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.42 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: /* util.c -- routines that don't really fit anywhere else... */
40:
41: #include <stdio.h>
1.10 jonathan 42: #include <stdarg.h>
1.1 phil 43: #include <unistd.h>
1.5 phil 44: #include <sys/types.h>
1.4 phil 45: #include <sys/param.h>
46: #include <sys/sysctl.h>
1.5 phil 47: #include <sys/stat.h>
1.2 phil 48: #include <curses.h>
1.37 bouyer 49: #include <errno.h>
1.52 hubertf 50: #include <fts.h>
1.64 mrg 51: #include <util.h>
1.1 phil 52: #include "defs.h"
1.5 phil 53: #include "md.h"
1.1 phil 54: #include "msg_defs.h"
55: #include "menu_defs.h"
1.4 phil 56:
1.97 ! dsl 57: distinfo dist_list[] = {
! 58: #ifdef SET_KERNEL_1_NAME
! 59: {SET_KERNEL_1_NAME, SET_KERNEL_1, MSG_set_kernel_1},
! 60: #endif
! 61: #ifdef SET_KERNEL_2_NAME
! 62: {SET_KERNEL_2_NAME, SET_KERNEL_2, MSG_set_kernel_2},
! 63: #endif
! 64: #ifdef SET_KERNEL_3_NAME
! 65: {SET_KERNEL_3_NAME, SET_KERNEL_3, MSG_set_kernel_3},
! 66: #endif
! 67: #ifdef SET_KERNEL_4_NAME
! 68: {SET_KERNEL_4_NAME, SET_KERNEL_4, MSG_set_kernel_4},
! 69: #endif
! 70: #ifdef SET_KERNEL_5_NAME
! 71: {SET_KERNEL_5_NAME, SET_KERNEL_5, MSG_set_kernel_5},
! 72: #endif
! 73: #ifdef SET_KERNEL_6_NAME
! 74: {SET_KERNEL_6_NAME, SET_KERNEL_6, MSG_set_kernel_6},
! 75: #endif
! 76: #ifdef SET_KERNEL_7_NAME
! 77: {SET_KERNEL_7_NAME, SET_KERNEL_7, MSG_set_kernel_7},
! 78: #endif
! 79: #ifdef SET_KERNEL_8_NAME
! 80: {SET_KERNEL_8_NAME, SET_KERNEL_8, MSG_set_kernel_8},
! 81: #endif
! 82: {"base", SET_BASE, MSG_set_base},
! 83: {"etc", SET_ETC, MSG_set_system},
! 84: {"comp", SET_COMPILER, MSG_set_compiler},
! 85: {"games", SET_GAMES, MSG_set_games},
! 86: {"man", SET_MAN_PAGES, MSG_set_man_pages},
! 87: {"misc", SET_MISC, MSG_set_misc},
! 88: {"text", SET_TEXT_TOOLS, MSG_set_text_tools},
! 89: {NULL, SET_X11, MSG_set_X11},
! 90: {"xbase", SET_X11_BASE, MSG_set_X11_base},
! 91: {"xfont", SET_X11_FONTS, MSG_set_X11_fonts},
! 92: {"xserver", SET_X11_SERVERS, MSG_set_X11_servers},
! 93: {"xcontrib", SET_X_CONTRIB, MSG_set_X_contrib},
! 94: {"xcomp", SET_X11_PROG, MSG_set_X11_prog},
! 95: {"xmisc", SET_X11_MISC, MSG_set_X11_misc},
! 96: #ifdef SET_MD_1_NAME
! 97: {SET_MD_1_NAME, SET_MD_1, MSG_set_md_1},
! 98: #endif
! 99: #ifdef SET_MD_2_NAME
! 100: {SET_MD_2_NAME, SET_MD_2, MSG_set_md_2},
! 101: #endif
! 102: #ifdef SET_MD_3_NAME
! 103: {SET_MD_3_NAME, SET_MD_3, MSG_set_md_3},
! 104: #endif
! 105: #ifdef SET_MD_4_NAME
! 106: {SET_MD_4_NAME, SET_MD_4, MSG_set_md_4},
! 107: #endif
! 108: {NULL, 0, NULL},
! 109: };
! 110:
1.14 jonathan 111: /*
112: * local prototypes
113: */
1.29 mrg 114: struct tarstats {
1.22 jonathan 115: int nselected;
116: int nfound;
117: int nnotfound;
118: int nerror;
119: int nsuccess;
1.44 cgd 120: int nskipped;
1.22 jonathan 121: } tarstats;
122:
1.61 mrg 123: int extract_file (char *path);
124: int extract_dist (void);
125: int distribution_sets_exist_p (const char *path);
126: static int check_for (unsigned int mode, const char *pathname);
1.4 phil 127:
1.97 ! dsl 128: #ifndef MD_SETS_SELECTED
! 129: #define MD_SETS_SELECTED (SET_KERNEL_1 | SET_SYSTEM | SET_X11 | SET_MD)
! 130: #endif
! 131: #ifndef MD_SETS_VALID
! 132: #define MD_SETS_VALID (SET_KERNEL | SET_SYSTEM | SET_X11 | SET_MD)
! 133: #endif
! 134:
! 135: unsigned int sets_valid = MD_SETS_VALID;
! 136: unsigned int sets_selected = (MD_SETS_SELECTED) & (MD_SETS_VALID);
! 137:
! 138:
1.29 mrg 139: int
1.96 dsl 140: dir_exists_p(const char *path)
1.22 jonathan 141: {
1.96 dsl 142:
1.54 fvdl 143: return file_mode_match(path, S_IFDIR);
144: }
1.29 mrg 145:
1.54 fvdl 146: int
1.96 dsl 147: file_exists_p(const char *path)
1.54 fvdl 148: {
1.96 dsl 149:
1.54 fvdl 150: return file_mode_match(path, S_IFREG);
1.22 jonathan 151: }
152:
1.29 mrg 153: int
1.96 dsl 154: file_mode_match(const char *path, unsigned int mode)
1.22 jonathan 155: {
1.54 fvdl 156: struct stat st;
1.29 mrg 157:
1.54 fvdl 158: return (stat(path, &st) == 0 && (st.st_mode & mode) != 0);
1.22 jonathan 159: }
160:
1.29 mrg 161: int
1.96 dsl 162: distribution_sets_exist_p(const char *path)
1.22 jonathan 163: {
164: char buf[STRSIZE];
165: int result;
166:
167: result = 1;
1.92 dsl 168: snprintf(buf, sizeof buf, "%s/%s", path, "etc.tgz");
1.59 hubertf 169: result = result && file_exists_p(buf);
170:
1.92 dsl 171: snprintf(buf, sizeof buf, "%s/%s", path, "base.tgz");
1.62 jdc 172: result = result && file_exists_p(buf);
173:
1.22 jonathan 174: return(result);
175: }
176:
177:
1.29 mrg 178: void
1.96 dsl 179: get_ramsize(void)
1.4 phil 180: {
1.78 christos 181: size_t len = sizeof(ramsize);
1.4 phil 182: int mib[2] = {CTL_HW, HW_PHYSMEM};
183:
1.78 christos 184: sysctl(mib, 2, &ramsize, &len, NULL, 0);
1.4 phil 185:
186: /* Find out how many Megs ... round up. */
1.78 christos 187: rammb = (unsigned int)((ramsize + MEG - 1) / MEG);
1.4 phil 188: }
189:
1.1 phil 190: static int asked = 0;
191:
1.29 mrg 192: void
1.96 dsl 193: ask_sizemult(int cylsize)
1.1 phil 194: {
1.96 dsl 195:
1.50 fvdl 196: current_cylsize = cylsize; /* XXX */
1.29 mrg 197:
1.1 phil 198: if (!asked) {
1.50 fvdl 199: msg_display(MSG_sizechoice);
1.94 dsl 200: process_menu(MENU_sizechoice, NULL);
1.1 phil 201: }
202: asked = 1;
1.9 phil 203: }
204:
1.29 mrg 205: void
1.96 dsl 206: reask_sizemult(int cylsize)
1.9 phil 207: {
1.29 mrg 208:
1.9 phil 209: asked = 0;
1.50 fvdl 210: ask_sizemult(cylsize);
1.1 phil 211: }
212:
1.29 mrg 213: void
1.96 dsl 214: run_makedev(void)
1.3 phil 215: {
1.22 jonathan 216: char *owd;
217:
1.39 bouyer 218: wclear(stdscr);
219: wrefresh(stdscr);
1.29 mrg 220: msg_display(MSG_makedev);
1.5 phil 221: sleep (1);
1.14 jonathan 222:
1.78 christos 223: owd = getcwd(NULL, 0);
1.22 jonathan 224:
1.14 jonathan 225: /* make /dev, in case the user didn't extract it. */
226: make_target_dir("/dev");
1.10 jonathan 227: target_chdir_or_die("/dev");
1.56 fvdl 228: run_prog(0, NULL, "/bin/sh MAKEDEV all");
1.22 jonathan 229:
230: chdir(owd);
231: free(owd);
1.5 phil 232: }
233:
234:
1.29 mrg 235: /*
236: * Load files from floppy. Requires a /mnt2 directory for mounting them.
237: */
238: int
1.96 dsl 239: get_via_floppy(void)
1.5 phil 240: {
241: char distname[STRSIZE];
242: char fddev[STRSIZE] = "/dev/fd0a";
243: char fname[STRSIZE];
1.78 christos 244: char full_name[STRSIZE];
1.34 garbled 245: char catcmd[STRSIZE];
1.7 phil 246: distinfo *list;
1.5 phil 247: char post[4];
248: int mounted = 0;
1.8 phil 249: int first;
1.5 phil 250: struct stat sb;
251:
1.29 mrg 252: cd_dist_dir("unloading from floppy");
1.7 phil 253:
1.29 mrg 254: msg_prompt_add(MSG_fddev, fddev, fddev, STRSIZE);
1.5 phil 255:
256: list = dist_list;
1.97 ! dsl 257: while (list->desc) {
! 258: if (list->name == NULL) {
! 259: list++;
! 260: continue;
! 261: }
1.29 mrg 262: strcpy(post, ".aa");
1.92 dsl 263: snprintf(distname, sizeof distname, "%s%s",
264: list->name, dist_postfix);
1.97 ! dsl 265: while (sets_selected & list->set) {
1.92 dsl 266: snprintf(fname, sizeof fname, "%s%s", list->name, post);
267: snprintf(full_name, sizeof full_name, "/mnt2/%s",
268: fname);
1.8 phil 269: first = 1;
1.78 christos 270: while (!mounted || stat(full_name, &sb)) {
1.8 phil 271: if (mounted)
1.56 fvdl 272: run_prog(0, NULL, "/sbin/umount /mnt2");
1.8 phil 273: if (first)
1.29 mrg 274: msg_display(MSG_fdmount, fname);
1.8 phil 275: else
1.29 mrg 276: msg_display(MSG_fdnotfound, fname);
1.94 dsl 277: process_menu(MENU_fdok, NULL);
1.8 phil 278: if (!yesno)
279: return 0;
1.89 jmmv 280: else if (yesno == 2)
281: return 1;
1.56 fvdl 282: while (run_prog(0, NULL,
1.35 bouyer 283: "/sbin/mount -r -t %s %s /mnt2",
1.29 mrg 284: fdtype, fddev)) {
285: msg_display(MSG_fdremount, fname);
1.94 dsl 286: process_menu(MENU_fdremount, NULL);
1.5 phil 287: if (!yesno)
288: return 0;
1.89 jmmv 289: else if (yesno == 2)
290: return 1;
1.5 phil 291: }
292: mounted = 1;
1.8 phil 293: first = 0;
1.5 phil 294: }
1.34 garbled 295: sprintf(catcmd, "/bin/cat %s >> %s",
1.78 christos 296: full_name, distname);
1.34 garbled 297: if (logging)
1.76 fvdl 298: (void)fprintf(logfp, "%s\n", catcmd);
1.34 garbled 299: if (scripting)
300: (void)fprintf(script, "%s\n", catcmd);
301: do_system(catcmd);
1.8 phil 302: if (post[2] < 'z')
303: post[2]++;
1.5 phil 304: else
1.29 mrg 305: post[2] = 'a', post[1]++;
1.5 phil 306: }
1.56 fvdl 307: run_prog(0, NULL, "/sbin/umount /mnt2");
1.5 phil 308: mounted = 0;
309: list++;
310: }
311: #ifndef DEBUG
1.10 jonathan 312: chdir("/"); /* back to current real root */
1.5 phil 313: #endif
1.6 phil 314: return 1;
315: }
316:
1.29 mrg 317: /*
318: * Get from a CDROM distribution.
319: */
1.6 phil 320: int
1.96 dsl 321: get_via_cdrom(void)
1.6 phil 322: {
1.22 jonathan 323: char tmpdir[STRSIZE];
1.82 jmc 324: int retries = 0;
1.28 fvdl 325:
326: /* Get CD-rom device name and path within CD-rom */
1.94 dsl 327: process_menu(MENU_cdromsource, NULL);
1.6 phil 328:
1.22 jonathan 329: again:
1.56 fvdl 330: run_prog(0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 331:
1.6 phil 332: /* Mount it */
1.93 dsl 333: if (run_prog(0, NULL, "/sbin/mount -rt cd9660 /dev/%s%c /mnt2",
334: cdrom_dev, 'a' + getrawpartition())) {
1.82 jmc 335: if (retries++ < 5) {
336: sleep(1);
337: goto again;
338: }
1.22 jonathan 339: msg_display(MSG_badsetdir, cdrom_dev);
1.94 dsl 340: process_menu(MENU_cdrombadmount, NULL);
1.6 phil 341: if (!yesno)
342: return 0;
1.22 jonathan 343: if (!ignorerror)
344: goto again;
345: }
346:
1.92 dsl 347: snprintf(tmpdir, sizeof tmpdir, "%s/%s", "/mnt2", cdrom_dir);
1.22 jonathan 348:
349: /* Verify distribution files exist. */
350: if (distribution_sets_exist_p(tmpdir) == 0) {
351: msg_display(MSG_badsetdir, tmpdir);
1.94 dsl 352: process_menu(MENU_cdrombadmount, NULL);
1.22 jonathan 353: if (!yesno)
354: return (0);
355: if (!ignorerror)
356: goto again;
1.6 phil 357: }
358:
359: /* return location, don't clean... */
1.92 dsl 360: strlcpy(ext_dir, tmpdir, STRSIZE);
1.6 phil 361: clean_dist_dir = 0;
362: mnt2_mounted = 1;
1.5 phil 363: return 1;
1.7 phil 364: }
365:
1.22 jonathan 366:
367: /*
368: * Get from a pathname inside an unmounted local filesystem
369: * (e.g., where sets were preloaded onto a local DOS partition)
370: */
1.29 mrg 371: int
1.96 dsl 372: get_via_localfs(void)
1.16 mhitch 373: {
1.22 jonathan 374: char tmpdir[STRSIZE];
375:
1.16 mhitch 376: /* Get device, filesystem, and filepath */
1.94 dsl 377: process_menu (MENU_localfssource, NULL);
1.16 mhitch 378:
1.22 jonathan 379: again:
1.56 fvdl 380: run_prog(0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 381:
1.16 mhitch 382: /* Mount it */
1.56 fvdl 383: if (run_prog(0, NULL, "/sbin/mount -rt %s /dev/%s /mnt2",
1.35 bouyer 384: localfs_fs, localfs_dev)) {
1.22 jonathan 385:
1.29 mrg 386: msg_display(MSG_localfsbadmount, localfs_dir, localfs_dev);
1.94 dsl 387: process_menu(MENU_localfsbadmount, NULL);
1.16 mhitch 388: if (!yesno)
389: return 0;
1.22 jonathan 390: if (!ignorerror)
1.29 mrg 391: goto again;
1.22 jonathan 392: }
393:
1.92 dsl 394: snprintf(tmpdir, sizeof tmpdir, "%s/%s", "/mnt2", localfs_dir);
1.22 jonathan 395:
396: /* Verify distribution files exist. */
397: if (distribution_sets_exist_p(tmpdir) == 0) {
398: msg_display(MSG_badsetdir, tmpdir);
1.94 dsl 399: process_menu(MENU_localfsbadmount, NULL);
1.22 jonathan 400: if (!yesno)
401: return 0;
402: if (!ignorerror)
403: goto again;
1.16 mhitch 404: }
405:
406: /* return location, don't clean... */
1.92 dsl 407: strlcpy(ext_dir, tmpdir, STRSIZE);
1.16 mhitch 408: clean_dist_dir = 0;
409: mnt2_mounted = 1;
410: return 1;
411: }
1.7 phil 412:
1.29 mrg 413: /*
414: * Get from an already-mounted pathname.
415: */
1.22 jonathan 416:
417: int get_via_localdir(void)
418: {
419:
420: /* Get device, filesystem, and filepath */
1.94 dsl 421: process_menu(MENU_localdirsource, NULL);
1.22 jonathan 422:
423: again:
424: /* Complain if not a directory */
425: if (dir_exists_p(localfs_dir) == 0) {
426:
1.29 mrg 427: msg_display(MSG_badlocalsetdir, localfs_dir);
1.94 dsl 428: process_menu(MENU_localdirbad, NULL);
1.22 jonathan 429: if (!yesno)
430: return (0);
431: if (!ignorerror)
432: goto again;
433: }
434:
435: /* Verify distribution files exist. */
436: if (distribution_sets_exist_p(localfs_dir) == 0) {
437: msg_display(MSG_badsetdir, localfs_dir);
1.94 dsl 438: process_menu(MENU_localdirbad, NULL);
1.22 jonathan 439: if (!yesno)
440: return (0);
441: if (!ignorerror)
442: goto again;
443: }
444:
445: /* return location, don't clean... */
1.92 dsl 446: strlcpy(ext_dir, localfs_dir, STRSIZE);
1.22 jonathan 447: clean_dist_dir = 0;
448: mnt2_mounted = 0;
449: return 1;
450: }
451:
452:
1.29 mrg 453: void
1.96 dsl 454: cd_dist_dir(char *forwhat)
1.7 phil 455: {
1.19 phil 456: char *cwd;
457:
1.10 jonathan 458: /* ask user for the mountpoint. */
1.29 mrg 459: msg_prompt(MSG_distdir, dist_dir, dist_dir, STRSIZE, forwhat);
1.10 jonathan 460:
461: /* make sure the directory exists. */
462: make_target_dir(dist_dir);
1.7 phil 463:
464: clean_dist_dir = 1;
1.10 jonathan 465: target_chdir_or_die(dist_dir);
1.19 phil 466:
467: /* Set ext_dir for absolute path. */
1.29 mrg 468: cwd = getcwd(NULL,0);
1.92 dsl 469: strlcpy(ext_dir, cwd, STRSIZE);
1.19 phil 470: free (cwd);
1.7 phil 471: }
472:
1.10 jonathan 473:
1.29 mrg 474: /*
475: * Support for custom distribution fetches / unpacks.
476: */
1.97 ! dsl 477:
! 478: typedef struct {
! 479: distinfo *dist;
! 480: unsigned int sets;
! 481: struct info {
! 482: unsigned int set;
! 483: char label[44];
! 484: } i[32];
! 485: } set_menu_info_t;
! 486:
! 487: static int
! 488: set_toggle(menudesc *menu, menu_ent *ent, void *arg)
! 489: {
! 490: set_menu_info_t *i = arg;
! 491: int set = i->i[ent - menu->opts].set;
! 492:
! 493: if (set & SET_KERNEL)
! 494: /* only one kernel set is allowed */
! 495: sets_selected &= ~SET_KERNEL;
! 496: sets_selected ^= set;
! 497: return 0;
! 498: }
! 499:
! 500: static int
! 501: set_all(menudesc *menu, menu_ent *ent, void *arg)
! 502: {
! 503: set_menu_info_t *i = arg;
! 504:
! 505: sets_selected |= i->sets;
! 506: return 0;
! 507: }
! 508:
! 509: static int
! 510: set_none(menudesc *menu, menu_ent *ent, void *arg)
1.29 mrg 511: {
1.97 ! dsl 512: set_menu_info_t *i = arg;
1.7 phil 513:
1.97 ! dsl 514: sets_selected &= ~i->sets;
! 515: return 0;
1.7 phil 516: }
517:
1.97 ! dsl 518: static int set_sublist(menudesc *menu, menu_ent *ent, void *arg);
! 519:
! 520: static void
! 521: set_selected_sets(menudesc *menu, void *arg)
1.7 phil 522: {
523: distinfo *list;
1.97 ! dsl 524: static const char *yes, *no, *all, *some, *none;
! 525: const char *selected;
! 526: menu_ent *m;
! 527: set_menu_info_t *menu_info = arg;
! 528: struct info *i = menu_info->i;
! 529: unsigned int set;
! 530:
! 531: if (yes == NULL) {
! 532: yes = msg_string(MSG_yes);
! 533: no = msg_string(MSG_no);
! 534: all = msg_string(MSG_all);
! 535: some = msg_string(MSG_some);
! 536: none = msg_string(MSG_none);
! 537: }
1.7 phil 538:
1.29 mrg 539: msg_display(MSG_cur_distsets);
1.48 cgd 540: msg_table_add(MSG_cur_distsets_header);
1.97 ! dsl 541:
! 542: m = menu->opts;
! 543: for (list = menu_info->dist; list->desc; list++) {
! 544: if (!(menu_info->sets & list->set))
! 545: break;
! 546: if (!(sets_valid & list->set))
! 547: continue;
! 548: i->set = list->set;
! 549: m->opt_menu = OPT_NOMENU;
! 550: m->opt_flags = 0;
! 551: m->opt_name = i->label;
! 552: m->opt_action = set_toggle;
! 553: if (list->set & (list->set - 1)) {
! 554: /* multiple bits possible */
! 555: set = list->set & sets_valid;
! 556: selected = (set & sets_selected) == 0 ? none :
! 557: (set & sets_selected) == set ? all : some;
! 558: } else {
! 559: selected = list->set & sets_selected ? yes : no;;
! 560: }
! 561: snprintf(i->label, sizeof i->label,
! 562: msg_string(MSG_cur_distsets_row),
! 563: msg_string(list->desc), selected);
! 564: m++;
! 565: i++;
! 566: if (list->name != NULL)
! 567: continue;
! 568: m[-1].opt_action = set_sublist;
! 569: /* collapsed sublist */
! 570: set = list->set;
! 571: while (list[1].set & set)
! 572: list++;
! 573: }
! 574:
! 575: if (menu_info->sets == ~0u)
! 576: return;
! 577:
! 578: m->opt_menu = OPT_NOMENU;
! 579: m->opt_flags = 0;
! 580: m->opt_name = MSG_select_all;
! 581: m->opt_action = set_all;
! 582: m++;
! 583: m->opt_menu = OPT_NOMENU;
! 584: m->opt_flags = 0;
! 585: m->opt_name = MSG_select_none;
! 586: m->opt_action = set_none;
! 587: }
! 588:
! 589: static int
! 590: set_sublist(menudesc *menu, menu_ent *ent, void *arg)
! 591: {
! 592: distinfo *list;
! 593: menu_ent me[32];
! 594: set_menu_info_t set_menu_info;
! 595: int sets;
! 596: int menu_no;
! 597: unsigned int set;
! 598: set_menu_info_t *i = arg;
! 599:
! 600: set = i->i[ent - menu->opts].set;
! 601: set_menu_info.sets = set;
! 602:
! 603: /* Count number of entries we require */
! 604: for (list = dist_list; list->set != set; list++)
! 605: if (list->desc == NULL)
! 606: return 0;
! 607: set_menu_info.dist = ++list;
! 608: for (sets = 2; list->set & set; list++)
! 609: if (sets_valid & list->set)
! 610: sets++;
! 611:
! 612: if (sets > nelem(me)) {
! 613: /* panic badly */
! 614: return 0;
! 615: }
! 616:
! 617: menu_no = new_menu(NULL, me, sets, 20, 10, 0, 44,
! 618: MC_SCROLL | MC_DFLTEXIT,
! 619: set_selected_sets, NULL, NULL, MSG_install_selected_sets);
! 620:
! 621: if (menu_no == -1)
! 622: return 0;
! 623:
! 624: process_menu(menu_no, &set_menu_info);
! 625: free_menu(menu_no);
! 626:
! 627: return 0;
! 628: }
! 629:
! 630: void
! 631: customise_sets(void)
! 632: {
! 633: distinfo *list;
! 634: menu_ent me[32];
! 635: set_menu_info_t set_menu_info;
! 636: int sets;
! 637: int menu_no;
! 638: unsigned int set, valid = 0;
! 639:
! 640: /* Count number of entries we require */
! 641: for (sets = 0, list = dist_list; list->desc != NULL; list++) {
! 642: if (!(sets_valid & list->set))
! 643: continue;
! 644: sets++;
! 645: if (list->name != NULL) {
! 646: valid |= list->set;
! 647: continue;
! 648: }
! 649: /* collapsed sublist */
! 650: set = list->set;
! 651: while (list[1].set & set) {
! 652: valid |= list[1].set;
! 653: list++;
! 654: }
1.7 phil 655: }
1.97 ! dsl 656: if (sets > nelem(me)) {
! 657: /* panic badly */
! 658: return;
! 659: }
! 660:
! 661: /* Static initialisation is lazy, fix it now */
! 662: sets_valid &= valid;
! 663: sets_selected &= valid;
! 664:
! 665: menu_no = new_menu(NULL, me, sets, 0, 5, 0, 44,
! 666: MC_SCROLL | MC_NOBOX | MC_DFLTEXIT | MC_NOCLEAR,
! 667: set_selected_sets, NULL, NULL, MSG_install_selected_sets);
! 668:
! 669: if (menu_no == -1)
! 670: return;
! 671:
! 672: set_menu_info.dist = dist_list;
! 673: set_menu_info.sets = ~0u;
! 674: process_menu(menu_no, &set_menu_info);
! 675: free_menu(menu_no);
1.1 phil 676: }
1.10 jonathan 677:
1.12 phil 678: /* Do we want a verbose extract? */
679: static int verbose = -1;
680:
681: void
1.96 dsl 682: ask_verbose_dist(void)
1.12 phil 683: {
1.29 mrg 684:
1.12 phil 685: if (verbose < 0) {
1.29 mrg 686: msg_display(MSG_verboseextract);
1.94 dsl 687: process_menu(MENU_extract, NULL);
1.12 phil 688: verbose = yesno;
1.36 bouyer 689: wclear(stdscr);
690: wrefresh(stdscr);
1.12 phil 691: }
692: }
693:
1.44 cgd 694: int
1.96 dsl 695: extract_file(char *path)
1.12 phil 696: {
697: char *owd;
1.44 cgd 698: int tarexit, rv;
1.12 phil 699:
700: owd = getcwd (NULL,0);
701:
1.22 jonathan 702: /* check tarfile exists */
703: if (!file_exists_p(path)) {
704: tarstats.nnotfound++;
1.44 cgd 705:
706: msg_display(MSG_notarfile, path);
1.94 dsl 707: process_menu(MENU_noyes, NULL);
1.44 cgd 708: return (yesno == 0);
1.22 jonathan 709: }
710:
711: tarstats.nfound++;
1.14 jonathan 712: /* cd to the target root. */
1.12 phil 713: target_chdir_or_die("/");
714:
1.14 jonathan 715: /* now extract set files files into "./". */
1.81 jhawk 716: if (verbose==1)
717: tarexit = run_prog(RUN_DISPLAY, NULL,
1.84 grant 718: "progress -zf %s tar -xepf -", path);
1.81 jhawk 719: else if (verbose==2)
720: tarexit = run_prog(RUN_DISPLAY, NULL,
1.85 grant 721: "tar -zxvepf %s", path);
1.81 jhawk 722: else
723: tarexit = run_prog(RUN_DISPLAY, NULL,
1.85 grant 724: "tar -zxepf %s", path);
1.22 jonathan 725:
1.17 phil 726: /* Check tarexit for errors and give warning. */
1.22 jonathan 727: if (tarexit) {
728: tarstats.nerror++;
1.44 cgd 729:
730: msg_display(MSG_tarerror, path);
1.94 dsl 731: process_menu(MENU_noyes, NULL);
1.44 cgd 732: rv = (yesno == 0);
1.22 jonathan 733: } else {
734: tarstats.nsuccess++;
1.44 cgd 735: rv = 0;
1.22 jonathan 736: }
737:
1.29 mrg 738: chdir(owd);
739: free(owd);
1.44 cgd 740:
741: return (rv);
1.12 phil 742: }
743:
1.19 phil 744:
1.29 mrg 745: /*
1.37 bouyer 746: * Extract_dist **REQUIRES** an absolute path in ext_dir. Any code
1.19 phil 747: * that sets up dist_dir for use by extract_dist needs to put in the
748: * full path name to the directory.
749: */
750:
1.22 jonathan 751: int
1.96 dsl 752: extract_dist(void)
1.12 phil 753: {
754: char distname[STRSIZE];
755: char fname[STRSIZE];
756: distinfo *list;
1.44 cgd 757: int punt;
1.12 phil 758:
1.22 jonathan 759: /* reset failure/success counters */
1.31 perry 760: memset(&tarstats, 0, sizeof(tarstats));
1.22 jonathan 761:
1.32 garbled 762: /*endwin();*/
1.97 ! dsl 763: for (punt = 0, list = dist_list; list->desc != NULL; list++) {
! 764: if (list->name == NULL)
! 765: continue;
! 766: if (sets_selected & list->set) {
1.22 jonathan 767: tarstats.nselected++;
1.44 cgd 768: if (punt) {
769: tarstats.nskipped++;
770: continue;
771: }
1.90 lukem 772: #if 0
1.37 bouyer 773: if (cleanup_dist(list->name) == 0) {
774: msg_display(MSG_cleanup_warn);
1.94 dsl 775: process_menu(MENU_ok, NULL);
1.37 bouyer 776: }
1.90 lukem 777: #endif
1.92 dsl 778: (void)snprintf(distname, sizeof distname, "%s%s",
779: list->name, dist_postfix);
780: (void)snprintf(fname, sizeof fname, "%s/%s",
781: ext_dir, distname);
1.44 cgd 782:
783: /* if extraction failed and user aborted, punt. */
784: punt = extract_file(fname);
1.15 phil 785: }
1.12 phil 786: }
1.22 jonathan 787:
1.63 jdc 788: wrefresh(curscr);
1.60 jdc 789: wmove(stdscr, 0, 0);
1.43 cgd 790: wclear(stdscr);
1.17 phil 791: wrefresh(stdscr);
1.22 jonathan 792:
793: if (tarstats.nerror == 0 && tarstats.nsuccess == tarstats.nselected) {
1.29 mrg 794: msg_display(MSG_endtarok);
1.94 dsl 795: process_menu(MENU_ok, NULL);
1.22 jonathan 796: return 0;
797: } else {
798: /* We encountered errors. Let the user know. */
799: msg_display(MSG_endtar,
1.44 cgd 800: tarstats.nselected, tarstats.nnotfound, tarstats.nskipped,
1.22 jonathan 801: tarstats.nfound, tarstats.nsuccess, tarstats.nerror);
1.94 dsl 802: process_menu(MENU_ok, NULL);
1.22 jonathan 803: return 1;
804: }
1.12 phil 805: }
806:
1.90 lukem 807: #if 0 /* { NOMORE */
808:
1.11 jonathan 809: /*
1.37 bouyer 810: * Do pre-extract cleanup for set 'name':
1.88 lukem 811: * open a file named '/var/db/obsolete/<name>', which contain a list of
1.37 bouyer 812: * files to kill from the target. For each file, test if it is present on
813: * the target. Then display the list of files which will be removed,
814: * ask user for confirmation, and process.
1.62 jdc 815: * Non-empty directories will be renamed to <directory.old>.
1.37 bouyer 816: */
817:
818: /* definition for a list of files. */
819: struct filelist {
820: struct filelist *next;
821: char name[MAXPATHLEN];
822: mode_t type;
823: };
824:
825: int
1.96 dsl 826: cleanup_dist(const char *name)
1.37 bouyer 827: {
828: char file_path[MAXPATHLEN];
829: char file_name[MAXPATHLEN];
1.87 lukem 830: const char *file_prefix;
1.37 bouyer 831: FILE *list_file;
832: struct filelist *head = NULL;
833: struct filelist *current;
834: int saved_errno;
835: struct stat st;
836: int retval = 1;
837: int needok = 0;
838:
1.88 lukem 839: snprintf(file_path, MAXPATHLEN, "/var/db/obsolete/%s", name);
1.37 bouyer 840: list_file = fopen(file_path, "r");
841: if (list_file == NULL) {
842: saved_errno = errno;
843: if (logging)
1.76 fvdl 844: fprintf(logfp, "Open of %s failed: %s\n", file_path,
1.37 bouyer 845: strerror(saved_errno));
846: if (saved_errno == ENOENT)
847: return 1;
848: msg_display_add(MSG_openfail, name, strerror(saved_errno));
1.94 dsl 849: process_menu(MENU_ok, NULL);
1.37 bouyer 850: return 0;
851: }
1.86 lukem 852: file_prefix = target_prefix();
1.37 bouyer 853: while (fgets(file_name, MAXPATHLEN, list_file)) {
854: /* Remove trailing \n if any */
855: if (file_name[strlen(file_name)-1] == '\n')
856: file_name[strlen(file_name)-1] = '\0';
1.86 lukem 857: snprintf(file_path, MAXPATHLEN, "%s/%s", file_prefix,
1.37 bouyer 858: file_name);
859: if (lstat(file_path, &st) != 0) {
860: saved_errno = errno;
861: if (logging)
1.76 fvdl 862: fprintf(logfp, "stat() of %s failed: %s\n",
1.37 bouyer 863: file_path, strerror(saved_errno));
864: if (saved_errno == ENOENT)
865: continue;
866: msg_display_add(MSG_statfail, file_path,
867: strerror(saved_errno));
1.94 dsl 868: process_menu(MENU_ok, NULL);
1.37 bouyer 869: return 0;
870: }
871: if (head == NULL) {
872: head = current = malloc(sizeof(struct filelist));
873: if (head == NULL) {
874: fprintf(stderr, "out of memory\n");
875: exit(1);
876: }
877: } else {
878: current->next = malloc(sizeof(struct filelist));
1.72 scottr 879: if (current->next == NULL) {
1.37 bouyer 880: fprintf(stderr, "out of memory\n");
881: exit(1);
882: }
883: current = current->next;
884: }
885: current->next = NULL;
886: snprintf(current->name, MAXPATHLEN, "%s", file_path);
887: current->type = st.st_mode & S_IFMT;
888: if (logging)
1.76 fvdl 889: fprintf(logfp, "Adding file %s, type %d to list of "
1.37 bouyer 890: "obsolete file\n", current->name, current->type);
891: }
1.62 jdc 892: fclose(list_file);
1.37 bouyer 893: if (head == NULL)
1.38 bouyer 894: return 1;
1.37 bouyer 895: #if 0
896: /* XXX doesn't work, too many files printed ! */
897: msg_display(MSG_deleting_files);
898: for (current = head; current != NULL; current = current->next) {
1.49 cgd 899: if (current->type != S_IFDIR) {
900: /* XXX msg_printf_add going/gone away */
1.37 bouyer 901: msg_printf_add("%s ", current->name);
1.49 cgd 902: }
1.37 bouyer 903: }
904: msg_display_add(MSG_deleting_dirs);
905: for (current = head; current != NULL; current = current->next) {
1.49 cgd 906: if (current->type == S_IFDIR) {
907: /* XXX msg_printf_add going/gone away */
1.37 bouyer 908: msg_printf_add("%s ", current->name);
1.49 cgd 909: }
1.37 bouyer 910: }
1.94 dsl 911: process_menu(MENU_ok, NULL);
1.37 bouyer 912: #endif
913: /* first remove files */
914: for (current = head; current != NULL; current = current->next) {
915: if (current->type == S_IFDIR)
916: continue;
917: if (scripting)
918: (void)fprintf(script, "rm %s\n", current->name);
919: if (unlink(current->name) != 0) {
920: saved_errno = errno;
1.51 hubertf 921: if (saved_errno == ENOENT)
922: continue; /* don't worry about
923: non-existing files */
1.37 bouyer 924: if (logging)
1.76 fvdl 925: fprintf(logfp, "rm %s failed: %s\n",
1.37 bouyer 926: current->name, strerror(saved_errno));
927: msg_display_add(MSG_unlink_fail, current->name,
928: strerror(saved_errno));
929: retval = 0;
930: needok = 1;
931: }
932:
933: }
934: /* now dirs */
935: for (current = head; current != NULL; current = current->next) {
936: if (current->type != S_IFDIR)
937: continue;
938: if (rmdir(current->name) == 0) {
939: if (scripting)
940: (void)fprintf(script, "rmdir %s\n",
941: current->name);
942: continue;
943: }
944: saved_errno = errno;
945: if (saved_errno == ENOTEMPTY) {
946: if (logging)
1.76 fvdl 947: fprintf(logfp, "dir %s not empty, "
1.37 bouyer 948: "trying to rename to %s.old\n",
949: current->name, current->name);
950: snprintf(file_path, MAXPATHLEN,
951: "%s.old", current->name);
952: if (scripting)
953: (void)fprintf(script, "mv %s %s\n",
954: current->name, file_path);
955: needok = 1;
956: if (rename(current->name, file_path) != 0) {
957: saved_errno = errno;
958: if (logging)
1.76 fvdl 959: fprintf(logfp, "mv %s %s failed: %s\n",
1.37 bouyer 960: current->name, file_path,
961: strerror(saved_errno));
962: msg_display_add(MSG_rename_fail, current->name,
963: file_path, strerror(errno));
964: retval = 0;
965: }
966: msg_display_add(MSG_renamed_dir, current->name,
967: file_path);
968: } else { /* rmdir error */
1.55 fvdl 969: /*
970: * Don't worry about non-existing directories.
971: */
972: if (saved_errno == ENOENT)
973: continue;
1.37 bouyer 974: if (logging)
1.76 fvdl 975: fprintf(logfp, "rm %s failed: %s\n",
1.37 bouyer 976: current->name, strerror(saved_errno));
977: msg_display_add(MSG_unlink_fail, current->name,
978: strerror(saved_errno));
979: retval = 0;
980: needok = 1;
981: }
982: }
983: if (needok)
1.94 dsl 984: process_menu(MENU_ok, NULL);
1.37 bouyer 985: return retval;
986: }
1.90 lukem 987: #endif /* } NOMORE */
1.37 bouyer 988:
989: /*
1.29 mrg 990: * Get and unpack the distribution.
991: * show success_msg if installation completes. Otherwise,,
992: * show failure_msg and wait for the user to ack it before continuing.
1.11 jonathan 993: * success_msg and failure_msg must both be 0-adic messages.
994: */
1.45 cgd 995: int
1.96 dsl 996: get_and_unpack_sets(msg success_msg, msg failure_msg)
1.11 jonathan 997: {
1.29 mrg 998:
1.20 jonathan 999: /* Ensure mountpoint for distribution files exists in current root. */
1.32 garbled 1000: (void) mkdir("/mnt2", S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
1001: if (scripting)
1002: (void)fprintf(script, "mkdir /mnt2\nchmod 755 /mnt2\n");
1.20 jonathan 1003:
1.26 phil 1004: /* Find out which files to "get" if we get files. */
1.37 bouyer 1005: wclear(stdscr);
1006: wrefresh(stdscr);
1.26 phil 1007:
1.37 bouyer 1008: /* ask user whether to do normal or verbose extraction */
1009: ask_verbose_dist();
1010:
1.11 jonathan 1011: /* Get the distribution files */
1.46 cgd 1012: do {
1013: got_dist = 0;
1.94 dsl 1014: process_menu(MENU_distmedium, NULL);
1.46 cgd 1015: } while (got_dist == -1);
1.26 phil 1016:
1.11 jonathan 1017: if (nodist)
1.45 cgd 1018: return 1;
1.20 jonathan 1019:
1.22 jonathan 1020: if (got_dist) {
1.11 jonathan 1021:
1.22 jonathan 1022: /* Extract the distribution, abort on errors. */
1.45 cgd 1023: if (extract_dist())
1024: return 1;
1.11 jonathan 1025:
1026: /* Configure the system */
1.29 mrg 1027: run_makedev();
1.11 jonathan 1028:
1029: /* Other configuration. */
1030: mnt_net_config();
1031:
1.19 phil 1032: /* Clean up dist dir (use absolute path name) */
1.11 jonathan 1033: if (clean_dist_dir)
1.56 fvdl 1034: run_prog(0, NULL, "/bin/rm -rf %s", ext_dir);
1.11 jonathan 1035:
1036: /* Mounted dist dir? */
1037: if (mnt2_mounted)
1.56 fvdl 1038: run_prog(0, NULL, "/sbin/umount /mnt2");
1.14 jonathan 1039:
1.29 mrg 1040: /* Install/Upgrade complete ... reboot or exit to script */
1041: msg_display(success_msg);
1.94 dsl 1042: process_menu(MENU_ok, NULL);
1.45 cgd 1043: return 0;
1.22 jonathan 1044: }
1045:
1.29 mrg 1046: msg_display(failure_msg);
1.94 dsl 1047: process_menu(MENU_ok, NULL);
1.45 cgd 1048: return 1;
1.14 jonathan 1049: }
1.22 jonathan 1050:
1051:
1.14 jonathan 1052:
1053: /*
1054: * Do a quick sanity check that the target can reboot.
1055: * return 1 if everything OK, 0 if there is a problem.
1056: * Uses a table of files we expect to find after a base install/upgrade.
1057: */
1058:
1059: /* test flag and pathname to check for after unpacking. */
1.54 fvdl 1060: struct check_table { unsigned int mode; const char *path;} checks[] = {
1061: { S_IFREG, "/netbsd" },
1062: { S_IFDIR, "/etc" },
1063: { S_IFREG, "/etc/fstab" },
1064: { S_IFREG, "/sbin/init" },
1065: { S_IFREG, "/bin/sh" },
1066: { S_IFREG, "/etc/rc" },
1067: { S_IFREG, "/etc/rc.subr" },
1068: { S_IFREG, "/etc/rc.conf" },
1069: { S_IFDIR, "/dev" },
1070: { S_IFCHR, "/dev/console" },
1.14 jonathan 1071: /* XXX check for rootdev in target /dev? */
1.54 fvdl 1072: { S_IFREG, "/etc/fstab" },
1073: { S_IFREG, "/sbin/fsck" },
1074: { S_IFREG, "/sbin/fsck_ffs" },
1075: { S_IFREG, "/sbin/mount" },
1076: { S_IFREG, "/sbin/mount_ffs" },
1077: { S_IFREG, "/sbin/mount_nfs" },
1.20 jonathan 1078: #if defined(DEBUG) || defined(DEBUG_CHECK)
1.54 fvdl 1079: { S_IFREG, "/foo/bar" }, /* bad entry to exercise warning */
1.14 jonathan 1080: #endif
1081: { 0, 0 }
1082:
1083: };
1084:
1085: /*
1086: * Check target for a single file.
1087: */
1.29 mrg 1088: static int
1.96 dsl 1089: check_for(unsigned int mode, const char *pathname)
1.14 jonathan 1090: {
1.18 jonathan 1091: int found;
1.14 jonathan 1092:
1.54 fvdl 1093: found = (target_test(mode, pathname) == 0);
1.18 jonathan 1094: if (found == 0)
1.14 jonathan 1095: msg_display(MSG_rootmissing, pathname);
1.18 jonathan 1096: return found;
1.14 jonathan 1097: }
1098:
1.25 jonathan 1099: /*
1100: * Check that all the files in check_table are present in the
1101: * target root. Warn if not found.
1102: */
1.14 jonathan 1103: int
1.96 dsl 1104: sanity_check(void)
1.14 jonathan 1105: {
1106: int target_ok = 1;
1107: struct check_table *p;
1108:
1109: for (p = checks; p->path; p++) {
1.54 fvdl 1110: target_ok = target_ok && check_for(p->mode, p->path);
1.14 jonathan 1111: }
1112: if (target_ok)
1113: return 0;
1114:
1115: /* Uh, oh. Something's missing. */
1116: msg_display(MSG_badroot);
1.94 dsl 1117: process_menu(MENU_ok, NULL);
1.14 jonathan 1118: return 1;
1.11 jonathan 1119: }
1.32 garbled 1120:
1.78 christos 1121: #ifdef notdef
1.32 garbled 1122: /* set reverse to 1 to default to no */
1123: int askyesno(int reverse)
1124: {
1125: WINDOW *yesnowin;
1126: int c, found;
1127:
1.40 simonb 1128: yesnowin = subwin(stdscr, 5, 20, getmaxy(stdscr)/2 - 2, getmaxx(stdscr)/2 - 10);
1.41 garbled 1129: if (yesnowin == NULL) {
1130: fprintf(stderr, "sysinst: failed to allocate yes/no box\n");
1131: exit(1);
1132: }
1.32 garbled 1133: box(yesnowin, '*', '*');
1134: wmove(yesnowin, 2,2);
1135:
1136: if (reverse)
1137: waddstr(yesnowin, "Yes or No: [N]");
1138: else
1139: waddstr(yesnowin, "Yes or No: [Y]");
1140:
1141: wrefresh(yesnowin);
1.78 christos 1142: while ((c = getchar()) != 0) {
1.32 garbled 1143: if (c == 'y' || c == 'Y') {
1144: found = 1;
1145: break;
1146: } else if (c == 'n' || c == 'N' ) {
1147: found = 0;
1148: break;
1149: } else if (c == '\n' || c == '\r') {
1150: if (reverse)
1151: found = 0;
1152: else
1153: found = 1;
1154: break;
1155: }
1156: }
1157: wclear(yesnowin);
1158: wrefresh(yesnowin);
1159: delwin(yesnowin);
1160: refresh();
1161: return(found);
1.52 hubertf 1162: }
1.78 christos 1163: #endif
1.52 hubertf 1164:
1165: /*
1166: * Some globals to pass things back from callbacks
1167: */
1168: static char zoneinfo_dir[STRSIZE];
1.91 dsl 1169: static const char *tz_selected; /* timezonename (relative to share/zoneinfo */
1170: static const char *tz_default; /* UTC, or whatever /etc/localtime points to */
1.52 hubertf 1171: static char tz_env[STRSIZE];
1172:
1173: /*
1174: * Callback from timezone menu
1175: */
1176: static int
1.94 dsl 1177: set_timezone_select(menudesc *m, menu_ent *opt, void *arg)
1.52 hubertf 1178: {
1179: time_t t;
1180:
1181: if (m)
1182: tz_selected = m->opts[m->cursel].opt_name;
1.92 dsl 1183: snprintf(tz_env, sizeof(tz_env), "%s/%s", zoneinfo_dir, tz_selected);
1.52 hubertf 1184: setenv("TZ", tz_env, 1);
1185: t = time(NULL);
1186: msg_display(MSG_choose_timezone,
1187: tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone);
1188: return 0;
1189: }
1190:
1191: /*
1192: * Alarm-handler to update example-display
1193: */
1194: static void
1.78 christos 1195: /*ARGSUSED*/
1.52 hubertf 1196: timezone_sig(int sig)
1197: {
1.96 dsl 1198:
1.94 dsl 1199: set_timezone_select(NULL, NULL, NULL);
1.74 grant 1200: alarm(60);
1.52 hubertf 1201: }
1202:
1203: /*
1204: * Choose from the files in usr/share/zoneinfo and set etc/localtime
1205: */
1206: int
1.96 dsl 1207: set_timezone(void)
1.52 hubertf 1208: {
1209: char localtime_link[STRSIZE];
1210: char localtime_target[STRSIZE];
1211: int rc;
1212: time_t t;
1213: FTS *tree;
1214: FTSENT *entry;
1215: char *argv[2];
1216: int skip;
1217: struct stat sb;
1.92 dsl 1218: int nfiles, maxfiles;
1.52 hubertf 1219: int menu_no;
1.92 dsl 1220: menu_ent *tz_menu, *tz_menu1;
1221: char **tz_titles, **tz_titles1;
1.52 hubertf 1222:
1.78 christos 1223: signal(SIGALRM, timezone_sig);
1.52 hubertf 1224: alarm(1);
1225:
1.92 dsl 1226: strlcpy(zoneinfo_dir, target_expand("/usr/share/zoneinfo"), STRSIZE);
1227: strlcpy(localtime_link, target_expand("/etc/localtime"),
1228: sizeof localtime_link);
1.52 hubertf 1229:
1230: /* Add sanity check that /mnt/usr/share/zoneinfo contains
1231: * something useful */
1232:
1233: rc = readlink(localtime_link, localtime_target,
1.75 provos 1234: sizeof(localtime_target) - 1);
1.52 hubertf 1235: if (rc < 0) {
1.53 hubertf 1236: /* error, default to UTC */
1237: tz_default = "UTC";
1238: } else {
1239: localtime_target[rc] = '\0';
1.92 dsl 1240: tz_default = strchr(strstr(localtime_target, "zoneinfo"), '/') + 1;
1.52 hubertf 1241: }
1242:
1.92 dsl 1243: tz_selected = tz_default;
1244: snprintf(tz_env, sizeof(tz_env), "%s/%s", zoneinfo_dir, tz_selected);
1.52 hubertf 1245: setenv("TZ", tz_env, 1);
1246: t = time(NULL);
1247: msg_display(MSG_choose_timezone,
1248: tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone);
1249:
1250: skip = strlen(zoneinfo_dir);
1251: argv[0] = zoneinfo_dir;
1252: argv[1] = NULL;
1253:
1.92 dsl 1254: nfiles = 0;
1255: maxfiles = 32;
1256: tz_menu = malloc(maxfiles * sizeof *tz_menu);
1257: tz_titles = malloc(maxfiles * sizeof *tz_titles);
1258: if (tz_menu == NULL || tz_titles == NULL)
1259: goto done; /* error - skip timezone setting */
1.52 hubertf 1260:
1.92 dsl 1261: if (!(tree = fts_open(argv, FTS_LOGICAL, NULL)))
1262: goto done; /* error - skip timezone setting */
1263:
1.78 christos 1264: for (; (entry = fts_read(tree)) != NULL; ) {
1.92 dsl 1265: if (stat(entry->fts_accpath, &sb) == -1)
1266: continue;
1267: if (!S_ISREG(sb.st_mode))
1268: continue;
1269: if (nfiles >= maxfiles) {
1270: maxfiles *= 2;
1271: tz_menu1 = realloc(tz_menu, maxfiles * sizeof *tz_menu);
1272: tz_titles1 = realloc(tz_titles,
1273: maxfiles * sizeof *tz_titles);
1274: if (tz_menu1 == NULL || tz_titles1 == NULL)
1275: break;
1276: tz_menu = tz_menu1;
1277: tz_titles = tz_titles1;
1278: }
1279: tz_titles[nfiles] = strdup(entry->fts_accpath + skip + 1);
1280: if (tz_titles[nfiles] == NULL)
1281: break;
1282: tz_menu[nfiles].opt_name = tz_titles[nfiles];
1283: tz_menu[nfiles].opt_menu = OPT_NOMENU;
1284: tz_menu[nfiles].opt_flags = 0;
1285: tz_menu[nfiles].opt_action = set_timezone_select;
1.52 hubertf 1286:
1.92 dsl 1287: nfiles++;
1.52 hubertf 1288: }
1289: (void)fts_close(tree);
1290:
1291: menu_no = new_menu(NULL, tz_menu, nfiles, 23, 9,
1292: 12, 32, MC_SCROLL|MC_NOSHORTCUT, NULL, NULL,
1.95 dsl 1293: "\nPlease consult the install documents.", NULL);
1.92 dsl 1294: if (menu_no < 0)
1295: goto done; /* error - skip timezone setting */
1296:
1.94 dsl 1297: process_menu(menu_no, NULL);
1.52 hubertf 1298:
1299: free_menu(menu_no);
1300:
1301: signal(SIGALRM, SIG_IGN);
1302:
1303: snprintf(localtime_target, sizeof(localtime_target),
1304: "/usr/share/zoneinfo/%s", tz_selected);
1305: unlink(localtime_link);
1306: symlink(localtime_target, localtime_link);
1307:
1.92 dsl 1308: done:
1309: while (nfiles > 0)
1310: free(tz_titles[--nfiles]);
1311: if (tz_titles != NULL)
1312: free(tz_titles);
1313: if (tz_menu != NULL)
1314: free(tz_menu);
1.52 hubertf 1315: return 1;
1.66 ad 1316: }
1317:
1318: int
1319: set_crypt_type(void)
1320: {
1321: FILE *pwc;
1322: char *fn;
1323:
1324: msg_display(MSG_choose_crypt);
1.94 dsl 1325: process_menu(MENU_crypttype, NULL);
1.66 ad 1326: fn = strdup(target_expand("/etc/passwd.conf"));
1.80 christos 1327: if (fn == NULL)
1328: return -1;
1.66 ad 1329:
1.68 itojun 1330: switch (yesno) {
1.69 itojun 1331: case 0:
1332: break;
1333: case 1: /* DES */
1334: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1335: pwc = fopen(fn, "w");
1336: fprintf(pwc,
1337: "default:\n"
1.70 enami 1338: " localcipher = old\n"
1339: " ypcipher = old\n");
1.69 itojun 1340: fclose(pwc);
1341: break;
1342: case 2: /* MD5 */
1343: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1.66 ad 1344: pwc = fopen(fn, "w");
1345: fprintf(pwc,
1346: "default:\n"
1347: " localcipher = md5\n"
1348: " ypcipher = md5\n");
1349: fclose(pwc);
1.68 itojun 1350: break;
1.69 itojun 1351: case 3: /* blowfish 2^7 */
1352: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1.68 itojun 1353: pwc = fopen(fn, "w");
1354: fprintf(pwc,
1355: "default:\n"
1356: " localcipher = blowfish,7\n"
1357: " ypcipher = blowfish,7\n");
1358: fclose(pwc);
1359: break;
1.66 ad 1360: }
1361:
1.67 ad 1362: free(fn);
1.66 ad 1363: return (0);
1.56 fvdl 1364: }
1365:
1366: int
1.96 dsl 1367: set_root_password(void)
1.56 fvdl 1368: {
1.96 dsl 1369:
1.56 fvdl 1370: msg_display(MSG_rootpw);
1.94 dsl 1371: process_menu(MENU_yesno, NULL);
1.56 fvdl 1372: if (yesno)
1373: run_prog(RUN_DISPLAY|RUN_CHROOT, NULL, "passwd -l root");
1.73 grant 1374: return 0;
1375: }
1376:
1377: int
1.96 dsl 1378: set_root_shell(void)
1.73 grant 1379: {
1.96 dsl 1380:
1.73 grant 1381: msg_display(MSG_rootsh);
1.94 dsl 1382: process_menu(MENU_rootsh, NULL);
1.73 grant 1383: run_prog(RUN_DISPLAY|RUN_CHROOT, NULL, "chpass -s %s root", shellpath);
1.56 fvdl 1384: return 0;
1.64 mrg 1385: }
1386:
1387: void
1388: scripting_vfprintf(FILE *f, const char *fmt, va_list ap)
1389: {
1.96 dsl 1390:
1.64 mrg 1391: if (f)
1392: (void)vfprintf(f, fmt, ap);
1393: if (scripting)
1394: (void)vfprintf(script, fmt, ap);
1395: }
1396:
1397: void
1398: scripting_fprintf(FILE *f, const char *fmt, ...)
1399: {
1400: va_list ap;
1401:
1402: va_start(ap, fmt);
1403: scripting_vfprintf(f, fmt, ap);
1404: va_end(ap);
1405: }
1406:
1407: void
1408: add_rc_conf(const char *fmt, ...)
1409: {
1410: FILE *f;
1411: va_list ap;
1412:
1413: va_start(ap, fmt);
1414: f = target_fopen("/etc/rc.conf", "a");
1415: if (f != 0) {
1416: scripting_fprintf(NULL, "cat <<EOF >>%s/etc/rc.conf\n",
1417: target_prefix());
1418: scripting_vfprintf(f, fmt, ap);
1419: fclose(f);
1420: scripting_fprintf(NULL, "EOF\n");
1421: }
1422: va_end(ap);
1423: }
1424:
1425: int
1.96 dsl 1426: check_lfs_progs(void)
1.64 mrg 1427: {
1428:
1429: return (access("/sbin/dump_lfs", X_OK) == 0 &&
1430: access("/sbin/fsck_lfs", X_OK) == 0 &&
1431: access("/sbin/mount_lfs", X_OK) == 0 &&
1432: access("/sbin/newfs_lfs", X_OK) == 0);
1.32 garbled 1433: }
CVSweb <webmaster@jp.NetBSD.org>