Annotation of src/distrib/utils/sysinst/util.c, Revision 1.130
1.130 ! dsl 1: /* $NetBSD: util.c,v 1.129 2004/08/17 17:12:26 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.101 dsl 50: #include <dirent.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},
1.116 lukem 91: {"xcomp", SET_X11_PROG, MSG_set_X11_prog},
1.117 lukem 92: {"xetc", SET_X11_ETC, MSG_set_X11_etc},
1.97 dsl 93: {"xfont", SET_X11_FONTS, MSG_set_X11_fonts},
94: {"xserver", SET_X11_SERVERS, MSG_set_X11_servers},
95: #ifdef SET_MD_1_NAME
96: {SET_MD_1_NAME, SET_MD_1, MSG_set_md_1},
97: #endif
98: #ifdef SET_MD_2_NAME
99: {SET_MD_2_NAME, SET_MD_2, MSG_set_md_2},
100: #endif
101: #ifdef SET_MD_3_NAME
102: {SET_MD_3_NAME, SET_MD_3, MSG_set_md_3},
103: #endif
104: #ifdef SET_MD_4_NAME
105: {SET_MD_4_NAME, SET_MD_4, MSG_set_md_4},
106: #endif
107: {NULL, 0, NULL},
108: };
109:
1.14 jonathan 110: /*
111: * local prototypes
112: */
1.29 mrg 113: struct tarstats {
1.22 jonathan 114: int nselected;
115: int nfound;
116: int nnotfound;
117: int nerror;
118: int nsuccess;
1.44 cgd 119: int nskipped;
1.22 jonathan 120: } tarstats;
121:
1.124 dsl 122: static int extract_file(int, int, int, char *path);
123: static int extract_dist(int, int);
1.104 dsl 124: int distribution_sets_exist_p(const char *path);
125: static int check_for(unsigned int mode, const char *pathname);
1.4 phil 126:
1.97 dsl 127: #ifndef MD_SETS_SELECTED
128: #define MD_SETS_SELECTED (SET_KERNEL_1 | SET_SYSTEM | SET_X11 | SET_MD)
129: #endif
130: #ifndef MD_SETS_VALID
131: #define MD_SETS_VALID (SET_KERNEL | SET_SYSTEM | SET_X11 | SET_MD)
132: #endif
133:
134: unsigned int sets_valid = MD_SETS_VALID;
135: unsigned int sets_selected = (MD_SETS_SELECTED) & (MD_SETS_VALID);
1.104 dsl 136: unsigned int sets_installed = 0;
1.97 dsl 137:
1.29 mrg 138: int
1.96 dsl 139: dir_exists_p(const char *path)
1.22 jonathan 140: {
1.96 dsl 141:
1.54 fvdl 142: return file_mode_match(path, S_IFDIR);
143: }
1.29 mrg 144:
1.54 fvdl 145: int
1.96 dsl 146: file_exists_p(const char *path)
1.54 fvdl 147: {
1.96 dsl 148:
1.54 fvdl 149: return file_mode_match(path, S_IFREG);
1.22 jonathan 150: }
151:
1.29 mrg 152: int
1.96 dsl 153: file_mode_match(const char *path, unsigned int mode)
1.22 jonathan 154: {
1.54 fvdl 155: struct stat st;
1.29 mrg 156:
1.54 fvdl 157: return (stat(path, &st) == 0 && (st.st_mode & mode) != 0);
1.22 jonathan 158: }
159:
1.29 mrg 160: int
1.96 dsl 161: distribution_sets_exist_p(const char *path)
1.22 jonathan 162: {
163: char buf[STRSIZE];
164: int result;
165:
166: result = 1;
1.92 dsl 167: snprintf(buf, sizeof buf, "%s/%s", path, "etc.tgz");
1.59 hubertf 168: result = result && file_exists_p(buf);
169:
1.92 dsl 170: snprintf(buf, sizeof buf, "%s/%s", path, "base.tgz");
1.62 jdc 171: result = result && file_exists_p(buf);
172:
1.120 dsl 173: if (result == 0) {
174: msg_display(MSG_badsetdir, path);
175: process_menu(MENU_ok, NULL);
176: }
177:
178: return result;
1.22 jonathan 179: }
180:
181:
1.125 dsl 182: uint
1.96 dsl 183: get_ramsize(void)
1.4 phil 184: {
1.125 dsl 185: uint64_t ramsize;
186: size_t len = sizeof ramsize;
187: int mib[2] = {CTL_HW, HW_PHYSMEM64};
1.4 phil 188:
1.78 christos 189: sysctl(mib, 2, &ramsize, &len, NULL, 0);
1.4 phil 190:
191: /* Find out how many Megs ... round up. */
1.125 dsl 192: return (ramsize + MEG - 1) / MEG;
1.4 phil 193: }
194:
1.29 mrg 195: void
1.96 dsl 196: run_makedev(void)
1.3 phil 197: {
1.22 jonathan 198: char *owd;
199:
1.128 dsl 200: msg_display_add("\n\n");
1.127 dsl 201: msg_display_add(MSG_makedev);
1.14 jonathan 202:
1.78 christos 203: owd = getcwd(NULL, 0);
1.22 jonathan 204:
1.14 jonathan 205: /* make /dev, in case the user didn't extract it. */
206: make_target_dir("/dev");
1.10 jonathan 207: target_chdir_or_die("/dev");
1.115 dsl 208: run_program(0, "/bin/sh MAKEDEV all");
1.22 jonathan 209:
210: chdir(owd);
211: free(owd);
1.5 phil 212: }
213:
214:
1.29 mrg 215: /*
216: * Load files from floppy. Requires a /mnt2 directory for mounting them.
217: */
218: int
1.96 dsl 219: get_via_floppy(void)
1.5 phil 220: {
1.121 christos 221: char fddev[STRSIZE];
1.5 phil 222: char fname[STRSIZE];
1.78 christos 223: char full_name[STRSIZE];
1.34 garbled 224: char catcmd[STRSIZE];
1.7 phil 225: distinfo *list;
1.5 phil 226: char post[4];
1.8 phil 227: int first;
1.5 phil 228: struct stat sb;
229:
1.121 christos 230: (void)strlcpy(fddev, "/dev/fd0a", STRSIZE);
1.29 mrg 231: cd_dist_dir("unloading from floppy");
1.7 phil 232:
1.29 mrg 233: msg_prompt_add(MSG_fddev, fddev, fddev, STRSIZE);
1.5 phil 234:
235: list = dist_list;
1.97 dsl 236: while (list->desc) {
237: if (list->name == NULL) {
238: list++;
239: continue;
240: }
1.29 mrg 241: strcpy(post, ".aa");
1.97 dsl 242: while (sets_selected & list->set) {
1.92 dsl 243: snprintf(fname, sizeof fname, "%s%s", list->name, post);
244: snprintf(full_name, sizeof full_name, "/mnt2/%s",
245: fname);
1.8 phil 246: first = 1;
1.112 dsl 247: while (!mnt2_mounted || stat(full_name, &sb)) {
248: umount_mnt2();
1.8 phil 249: if (first)
1.29 mrg 250: msg_display(MSG_fdmount, fname);
1.8 phil 251: else
1.29 mrg 252: msg_display(MSG_fdnotfound, fname);
1.94 dsl 253: process_menu(MENU_fdok, NULL);
1.8 phil 254: if (!yesno)
255: return 0;
1.89 jmmv 256: else if (yesno == 2)
257: return 1;
1.115 dsl 258: while (run_program(0,
1.35 bouyer 259: "/sbin/mount -r -t %s %s /mnt2",
1.29 mrg 260: fdtype, fddev)) {
261: msg_display(MSG_fdremount, fname);
1.94 dsl 262: process_menu(MENU_fdremount, NULL);
1.5 phil 263: if (!yesno)
264: return 0;
1.112 dsl 265: if (yesno == 2)
1.89 jmmv 266: return 1;
1.5 phil 267: }
1.112 dsl 268: mnt2_mounted = 1;
1.8 phil 269: first = 0;
1.5 phil 270: }
1.111 itojun 271: snprintf(catcmd, sizeof(catcmd), "/bin/cat %s >> %s%s",
1.104 dsl 272: full_name, list->name, dist_postfix);
1.34 garbled 273: if (logging)
1.76 fvdl 274: (void)fprintf(logfp, "%s\n", catcmd);
1.34 garbled 275: if (scripting)
276: (void)fprintf(script, "%s\n", catcmd);
277: do_system(catcmd);
1.8 phil 278: if (post[2] < 'z')
279: post[2]++;
1.5 phil 280: else
1.29 mrg 281: post[2] = 'a', post[1]++;
1.5 phil 282: }
1.112 dsl 283: umount_mnt2();
1.5 phil 284: list++;
285: }
286: #ifndef DEBUG
1.10 jonathan 287: chdir("/"); /* back to current real root */
1.5 phil 288: #endif
1.6 phil 289: return 1;
290: }
291:
1.29 mrg 292: /*
293: * Get from a CDROM distribution.
294: */
1.6 phil 295: int
1.96 dsl 296: get_via_cdrom(void)
1.6 phil 297: {
1.28 fvdl 298:
299: /* Get CD-rom device name and path within CD-rom */
1.94 dsl 300: process_menu(MENU_cdromsource, NULL);
1.6 phil 301:
1.112 dsl 302: umount_mnt2();
1.22 jonathan 303:
1.6 phil 304: /* Mount it */
1.120 dsl 305: for (;;) {
306: if (run_program(0, "/sbin/mount -rt cd9660 /dev/%s /mnt2",
307: cdrom_dev) == 0)
1.112 dsl 308: break;
1.94 dsl 309: process_menu(MENU_cdrombadmount, NULL);
1.6 phil 310: if (!yesno)
1.120 dsl 311: return -1;
1.22 jonathan 312: }
1.112 dsl 313: mnt2_mounted = 1;
1.22 jonathan 314:
1.120 dsl 315: snprintf(ext_dir, sizeof ext_dir, "%s/%s", "/mnt2", set_dir);
1.22 jonathan 316:
317: /* Verify distribution files exist. */
1.120 dsl 318: if (distribution_sets_exist_p(ext_dir) == 0)
319: return -1;
1.6 phil 320:
321: /* return location, don't clean... */
322: clean_dist_dir = 0;
1.5 phil 323: return 1;
1.7 phil 324: }
325:
1.22 jonathan 326:
327: /*
328: * Get from a pathname inside an unmounted local filesystem
329: * (e.g., where sets were preloaded onto a local DOS partition)
330: */
1.29 mrg 331: int
1.96 dsl 332: get_via_localfs(void)
1.16 mhitch 333: {
1.22 jonathan 334:
1.16 mhitch 335: /* Get device, filesystem, and filepath */
1.94 dsl 336: process_menu (MENU_localfssource, NULL);
1.16 mhitch 337:
1.22 jonathan 338: again:
1.112 dsl 339: umount_mnt2();
1.22 jonathan 340:
1.16 mhitch 341: /* Mount it */
1.115 dsl 342: if (run_program(0, "/sbin/mount -rt %s /dev/%s /mnt2",
1.35 bouyer 343: localfs_fs, localfs_dev)) {
1.22 jonathan 344:
1.29 mrg 345: msg_display(MSG_localfsbadmount, localfs_dir, localfs_dev);
1.94 dsl 346: process_menu(MENU_localfsbadmount, NULL);
1.16 mhitch 347: if (!yesno)
348: return 0;
1.22 jonathan 349: if (!ignorerror)
1.29 mrg 350: goto again;
1.22 jonathan 351: }
1.112 dsl 352: mnt2_mounted = 1;
1.22 jonathan 353:
1.120 dsl 354: snprintf(ext_dir, sizeof ext_dir, "%s/%s/%s",
355: "/mnt2", localfs_dir, set_dir);
1.22 jonathan 356:
357: /* Verify distribution files exist. */
1.120 dsl 358: if (distribution_sets_exist_p(ext_dir) == 0)
359: return -1;
1.16 mhitch 360:
361: /* return location, don't clean... */
362: clean_dist_dir = 0;
363: return 1;
364: }
1.7 phil 365:
1.29 mrg 366: /*
367: * Get from an already-mounted pathname.
368: */
1.22 jonathan 369:
1.99 dsl 370: int
371: get_via_localdir(void)
1.22 jonathan 372: {
373:
1.120 dsl 374: /* Get filepath */
1.94 dsl 375: process_menu(MENU_localdirsource, NULL);
1.22 jonathan 376:
1.120 dsl 377: /*
378: * We have to have an absolute path ('cos pax runs in a
379: * different directory), make it so.
380: */
381: snprintf(ext_dir, sizeof ext_dir, "/%s/%s", localfs_dir, set_dir);
382:
383: if (distribution_sets_exist_p(ext_dir) == 0)
384: return -1;
1.22 jonathan 385:
386: /* return location, don't clean... */
387: clean_dist_dir = 0;
388: return 1;
389: }
390:
391:
1.29 mrg 392: void
1.107 dsl 393: cd_dist_dir(const char *forwhat)
1.7 phil 394: {
1.19 phil 395:
1.10 jonathan 396: /* ask user for the mountpoint. */
1.29 mrg 397: msg_prompt(MSG_distdir, dist_dir, dist_dir, STRSIZE, forwhat);
1.10 jonathan 398:
399: /* make sure the directory exists. */
400: make_target_dir(dist_dir);
1.7 phil 401:
402: clean_dist_dir = 1;
1.10 jonathan 403: target_chdir_or_die(dist_dir);
1.19 phil 404:
405: /* Set ext_dir for absolute path. */
1.103 dsl 406: getcwd(ext_dir, sizeof ext_dir);
1.7 phil 407: }
408:
1.10 jonathan 409:
1.29 mrg 410: /*
411: * Support for custom distribution fetches / unpacks.
412: */
1.97 dsl 413:
414: typedef struct {
415: distinfo *dist;
416: unsigned int sets;
417: struct info {
418: unsigned int set;
419: char label[44];
420: } i[32];
421: } set_menu_info_t;
422:
423: static int
1.108 dsl 424: set_toggle(menudesc *menu, void *arg)
1.97 dsl 425: {
426: set_menu_info_t *i = arg;
1.108 dsl 427: int set = i->i[menu->cursel].set;
1.97 dsl 428:
429: if (set & SET_KERNEL)
430: /* only one kernel set is allowed */
1.101 dsl 431: sets_selected &= ~SET_KERNEL | set;
1.97 dsl 432: sets_selected ^= set;
433: return 0;
434: }
435:
436: static int
1.108 dsl 437: set_all(menudesc *menu, void *arg)
1.97 dsl 438: {
439: set_menu_info_t *i = arg;
440:
441: sets_selected |= i->sets;
1.101 dsl 442: return 1;
1.97 dsl 443: }
444:
445: static int
1.108 dsl 446: set_none(menudesc *menu, void *arg)
1.29 mrg 447: {
1.97 dsl 448: set_menu_info_t *i = arg;
1.7 phil 449:
1.97 dsl 450: sets_selected &= ~i->sets;
1.101 dsl 451: return 1;
1.7 phil 452: }
453:
1.108 dsl 454: static int set_sublist(menudesc *menu, void *arg);
1.97 dsl 455:
456: static void
457: set_selected_sets(menudesc *menu, void *arg)
1.7 phil 458: {
459: distinfo *list;
1.97 dsl 460: static const char *yes, *no, *all, *some, *none;
461: const char *selected;
462: menu_ent *m;
463: set_menu_info_t *menu_info = arg;
464: struct info *i = menu_info->i;
465: unsigned int set;
466:
467: if (yes == NULL) {
1.100 dsl 468: yes = msg_string(MSG_Yes);
469: no = msg_string(MSG_No);
470: all = msg_string(MSG_All);
471: some = msg_string(MSG_Some);
472: none = msg_string(MSG_None);
1.97 dsl 473: }
1.7 phil 474:
1.29 mrg 475: msg_display(MSG_cur_distsets);
1.48 cgd 476: msg_table_add(MSG_cur_distsets_header);
1.97 dsl 477:
478: m = menu->opts;
479: for (list = menu_info->dist; list->desc; list++) {
480: if (!(menu_info->sets & list->set))
481: break;
482: if (!(sets_valid & list->set))
483: continue;
484: i->set = list->set;
485: m->opt_menu = OPT_NOMENU;
486: m->opt_flags = 0;
487: m->opt_name = i->label;
488: m->opt_action = set_toggle;
489: if (list->set & (list->set - 1)) {
490: /* multiple bits possible */
491: set = list->set & sets_valid;
492: selected = (set & sets_selected) == 0 ? none :
493: (set & sets_selected) == set ? all : some;
494: } else {
495: selected = list->set & sets_selected ? yes : no;;
496: }
497: snprintf(i->label, sizeof i->label,
498: msg_string(MSG_cur_distsets_row),
499: msg_string(list->desc), selected);
500: m++;
501: i++;
502: if (list->name != NULL)
503: continue;
504: m[-1].opt_action = set_sublist;
505: /* collapsed sublist */
506: set = list->set;
507: while (list[1].set & set)
508: list++;
509: }
510:
511: if (menu_info->sets == ~0u)
512: return;
513:
514: m->opt_menu = OPT_NOMENU;
515: m->opt_flags = 0;
516: m->opt_name = MSG_select_all;
517: m->opt_action = set_all;
518: m++;
519: m->opt_menu = OPT_NOMENU;
520: m->opt_flags = 0;
521: m->opt_name = MSG_select_none;
522: m->opt_action = set_none;
523: }
524:
525: static int
1.108 dsl 526: set_sublist(menudesc *menu, void *arg)
1.97 dsl 527: {
528: distinfo *list;
529: menu_ent me[32];
530: set_menu_info_t set_menu_info;
531: int sets;
532: int menu_no;
533: unsigned int set;
534: set_menu_info_t *i = arg;
535:
1.108 dsl 536: set = i->i[menu->cursel].set;
1.97 dsl 537: set_menu_info.sets = set;
538:
539: /* Count number of entries we require */
540: for (list = dist_list; list->set != set; list++)
541: if (list->desc == NULL)
542: return 0;
543: set_menu_info.dist = ++list;
544: for (sets = 2; list->set & set; list++)
545: if (sets_valid & list->set)
546: sets++;
547:
548: if (sets > nelem(me)) {
549: /* panic badly */
550: return 0;
551: }
552:
553: menu_no = new_menu(NULL, me, sets, 20, 10, 0, 44,
1.127 dsl 554: MC_SUBMENU | MC_SCROLL | MC_DFLTEXIT,
1.101 dsl 555: set_selected_sets, NULL, NULL, NULL, MSG_install_selected_sets);
1.97 dsl 556:
557: if (menu_no == -1)
558: return 0;
559:
560: process_menu(menu_no, &set_menu_info);
561: free_menu(menu_no);
562:
563: return 0;
564: }
565:
566: void
567: customise_sets(void)
568: {
569: distinfo *list;
570: menu_ent me[32];
571: set_menu_info_t set_menu_info;
572: int sets;
573: int menu_no;
574: unsigned int set, valid = 0;
575:
576: /* Count number of entries we require */
577: for (sets = 0, list = dist_list; list->desc != NULL; list++) {
578: if (!(sets_valid & list->set))
579: continue;
580: sets++;
581: if (list->name != NULL) {
582: valid |= list->set;
583: continue;
584: }
585: /* collapsed sublist */
586: set = list->set;
587: while (list[1].set & set) {
588: valid |= list[1].set;
589: list++;
590: }
1.7 phil 591: }
1.97 dsl 592: if (sets > nelem(me)) {
593: /* panic badly */
594: return;
595: }
596:
597: /* Static initialisation is lazy, fix it now */
598: sets_valid &= valid;
599: sets_selected &= valid;
600:
601: menu_no = new_menu(NULL, me, sets, 0, 5, 0, 44,
602: MC_SCROLL | MC_NOBOX | MC_DFLTEXIT | MC_NOCLEAR,
1.101 dsl 603: set_selected_sets, NULL, NULL, NULL, MSG_install_selected_sets);
1.97 dsl 604:
605: if (menu_no == -1)
606: return;
607:
608: set_menu_info.dist = dist_list;
609: set_menu_info.sets = ~0u;
610: process_menu(menu_no, &set_menu_info);
611: free_menu(menu_no);
1.1 phil 612: }
1.10 jonathan 613:
1.124 dsl 614: static int
1.120 dsl 615: ask_verbose_dist(msg setup_done)
1.12 phil 616: {
1.124 dsl 617: int verbose = 0;
1.29 mrg 618:
1.120 dsl 619: wclear(stdscr);
620: wrefresh(stdscr);
621: if (setup_done != NULL)
622: msg_display(setup_done);
623: msg_display_add(MSG_verboseextract);
624: process_menu(MENU_extract, &verbose);
625: wclear(stdscr);
626: wrefresh(stdscr);
1.124 dsl 627:
628: return verbose;
1.12 phil 629: }
630:
1.112 dsl 631: static int
1.124 dsl 632: extract_file(int set, int update, int verbose, char *path)
1.12 phil 633: {
634: char *owd;
1.112 dsl 635: int tarexit;
1.12 phil 636:
1.104 dsl 637: owd = getcwd(NULL, 0);
1.12 phil 638:
1.22 jonathan 639: /* check tarfile exists */
640: if (!file_exists_p(path)) {
641: tarstats.nnotfound++;
1.44 cgd 642:
643: msg_display(MSG_notarfile, path);
1.120 dsl 644: process_menu(MENU_noyes, deconst(MSG_notarfile_ok));
1.112 dsl 645: return yesno;
1.22 jonathan 646: }
647:
648: tarstats.nfound++;
1.14 jonathan 649: /* cd to the target root. */
1.119 dsl 650: if (update && set == SET_ETC) {
651: make_target_dir("/.sysinst");
652: target_chdir_or_die("/.sysinst");
653: } else
654: target_chdir_or_die("/");
1.12 phil 655:
1.14 jonathan 656: /* now extract set files files into "./". */
1.120 dsl 657: if (verbose == 0)
1.115 dsl 658: tarexit = run_program(RUN_DISPLAY | RUN_PROGRESS,
1.104 dsl 659: "progress -zf %s tar -xepf -", path);
1.120 dsl 660: else if (verbose == 1)
1.124 dsl 661: tarexit = run_program(RUN_DISPLAY,
662: "tar -zxepf %s", path);
663: else
1.115 dsl 664: tarexit = run_program(RUN_DISPLAY | RUN_PROGRESS,
1.104 dsl 665: "tar -zxvepf %s", path);
1.22 jonathan 666:
1.112 dsl 667: chdir(owd);
668: free(owd);
669:
1.17 phil 670: /* Check tarexit for errors and give warning. */
1.22 jonathan 671: if (tarexit) {
672: tarstats.nerror++;
1.44 cgd 673: msg_display(MSG_tarerror, path);
1.94 dsl 674: process_menu(MENU_noyes, NULL);
1.112 dsl 675: return yesno;
1.22 jonathan 676: }
1.44 cgd 677:
1.119 dsl 678: if (update && set == SET_ETC) {
679: run_program(RUN_DISPLAY | RUN_CHROOT,
1.130 ! dsl 680: "/.sysinst/etc/postinstall -s /.sysinst -d / fix");
1.119 dsl 681: }
682:
1.112 dsl 683: tarstats.nsuccess++;
684: return 2;
1.12 phil 685: }
686:
1.19 phil 687:
1.29 mrg 688: /*
1.37 bouyer 689: * Extract_dist **REQUIRES** an absolute path in ext_dir. Any code
1.19 phil 690: * that sets up dist_dir for use by extract_dist needs to put in the
691: * full path name to the directory.
692: */
693:
1.112 dsl 694: static int
1.124 dsl 695: extract_dist(int update, int verbose)
1.12 phil 696: {
697: char fname[STRSIZE];
698: distinfo *list;
1.112 dsl 699: int extracted;
1.12 phil 700:
1.22 jonathan 701: /* reset failure/success counters */
1.31 perry 702: memset(&tarstats, 0, sizeof(tarstats));
1.22 jonathan 703:
1.32 garbled 704: /*endwin();*/
1.112 dsl 705: for (extracted = 2, list = dist_list; list->desc != NULL; list++) {
1.97 dsl 706: if (list->name == NULL)
707: continue;
1.112 dsl 708: if (!(sets_selected & list->set))
709: continue;
710: tarstats.nselected++;
711: if (extracted == 0) {
712: tarstats.nskipped++;
713: continue;
714: }
715: (void)snprintf(fname, sizeof fname, "%s/%s%s",
716: ext_dir, list->name, dist_postfix);
1.44 cgd 717:
1.112 dsl 718: /* if extraction failed and user aborted, punt. */
1.124 dsl 719: extracted = extract_file(list->set, update, verbose, fname);
1.112 dsl 720: if (extracted == 2)
721: sets_installed |= list->set;
1.12 phil 722: }
1.22 jonathan 723:
1.63 jdc 724: wrefresh(curscr);
1.60 jdc 725: wmove(stdscr, 0, 0);
1.43 cgd 726: wclear(stdscr);
1.17 phil 727: wrefresh(stdscr);
1.22 jonathan 728:
729: if (tarstats.nerror == 0 && tarstats.nsuccess == tarstats.nselected) {
1.29 mrg 730: msg_display(MSG_endtarok);
1.127 dsl 731: /* Give user a chance to see the success message */
732: sleep(1);
1.22 jonathan 733: return 0;
734: }
1.112 dsl 735: /* We encountered errors. Let the user know. */
736: msg_display(MSG_endtar,
737: tarstats.nselected, tarstats.nnotfound, tarstats.nskipped,
738: tarstats.nfound, tarstats.nsuccess, tarstats.nerror);
739: process_menu(MENU_ok, NULL);
1.127 dsl 740: msg_clear();
1.112 dsl 741: return extracted == 0;
1.12 phil 742: }
743:
1.37 bouyer 744: /*
1.29 mrg 745: * Get and unpack the distribution.
1.112 dsl 746: * Show success_msg if installation completes.
747: * Otherwise show failure_msg and wait for the user to ack it before continuing.
1.11 jonathan 748: * success_msg and failure_msg must both be 0-adic messages.
749: */
1.45 cgd 750: int
1.120 dsl 751: get_and_unpack_sets(int update, msg setupdone_msg, msg success_msg, msg failure_msg)
1.11 jonathan 752: {
1.112 dsl 753: int got_dist;
1.124 dsl 754: int verbose;
1.29 mrg 755:
1.20 jonathan 756: /* Ensure mountpoint for distribution files exists in current root. */
1.112 dsl 757: (void)mkdir("/mnt2", S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
1.32 garbled 758: if (scripting)
759: (void)fprintf(script, "mkdir /mnt2\nchmod 755 /mnt2\n");
1.20 jonathan 760:
1.26 phil 761: /* Find out which files to "get" if we get files. */
762:
1.37 bouyer 763: /* ask user whether to do normal or verbose extraction */
1.124 dsl 764: verbose = ask_verbose_dist(setupdone_msg);
1.37 bouyer 765:
1.120 dsl 766: again:
1.11 jonathan 767: /* Get the distribution files */
1.46 cgd 768: do {
1.112 dsl 769: process_menu(MENU_distmedium, &got_dist);
1.46 cgd 770: } while (got_dist == -1);
1.26 phil 771:
1.112 dsl 772: if (got_dist == -2)
1.45 cgd 773: return 1;
1.20 jonathan 774:
1.112 dsl 775: if (got_dist != 1) {
776: msg_display(failure_msg);
777: process_menu(MENU_ok, NULL);
778: return 1;
779: }
1.11 jonathan 780:
1.120 dsl 781: /* Extract the distribution, retry from top on errors. */
1.124 dsl 782: if (extract_dist(update, verbose))
1.120 dsl 783: goto again;
1.11 jonathan 784:
1.112 dsl 785: /* Configure the system */
1.127 dsl 786: if (sets_installed & SET_BASE)
1.112 dsl 787: run_makedev();
1.11 jonathan 788:
1.122 dsl 789: /* Save keybard type */
790: save_kb_encoding();
791:
1.112 dsl 792: /* Other configuration. */
793: mnt_net_config();
794:
795: /* Clean up dist dir (use absolute path name) */
796: if (clean_dist_dir && ext_dir[0] == '/' && ext_dir[1] != 0) {
797: msg_display(MSG_delete_dist_files,
798: ext_dir + strlen(target_prefix()));
799: process_menu(MENU_yesno, NULL);
800: if (yesno)
1.115 dsl 801: run_program(0, "/bin/rm -rf %s", ext_dir);
1.112 dsl 802: }
1.14 jonathan 803:
1.112 dsl 804: /* Mounted dist dir? */
805: umount_mnt2();
1.22 jonathan 806:
1.112 dsl 807: /* Install/Upgrade complete ... reboot or exit to script */
808: msg_display(success_msg);
1.94 dsl 809: process_menu(MENU_ok, NULL);
1.112 dsl 810: return 0;
1.14 jonathan 811: }
1.22 jonathan 812:
1.112 dsl 813: void
814: umount_mnt2(void)
815: {
816: if (!mnt2_mounted)
817: return;
1.115 dsl 818: run_program(RUN_SILENT, "/sbin/umount /mnt2");
1.112 dsl 819: mnt2_mounted = 0;
820: }
1.22 jonathan 821:
1.14 jonathan 822:
823: /*
824: * Do a quick sanity check that the target can reboot.
825: * return 1 if everything OK, 0 if there is a problem.
826: * Uses a table of files we expect to find after a base install/upgrade.
827: */
828:
829: /* test flag and pathname to check for after unpacking. */
1.54 fvdl 830: struct check_table { unsigned int mode; const char *path;} checks[] = {
831: { S_IFREG, "/netbsd" },
832: { S_IFDIR, "/etc" },
833: { S_IFREG, "/etc/fstab" },
834: { S_IFREG, "/sbin/init" },
835: { S_IFREG, "/bin/sh" },
836: { S_IFREG, "/etc/rc" },
837: { S_IFREG, "/etc/rc.subr" },
838: { S_IFREG, "/etc/rc.conf" },
839: { S_IFDIR, "/dev" },
840: { S_IFCHR, "/dev/console" },
1.14 jonathan 841: /* XXX check for rootdev in target /dev? */
1.54 fvdl 842: { S_IFREG, "/etc/fstab" },
843: { S_IFREG, "/sbin/fsck" },
844: { S_IFREG, "/sbin/fsck_ffs" },
845: { S_IFREG, "/sbin/mount" },
846: { S_IFREG, "/sbin/mount_ffs" },
847: { S_IFREG, "/sbin/mount_nfs" },
1.20 jonathan 848: #if defined(DEBUG) || defined(DEBUG_CHECK)
1.54 fvdl 849: { S_IFREG, "/foo/bar" }, /* bad entry to exercise warning */
1.14 jonathan 850: #endif
851: { 0, 0 }
852:
853: };
854:
855: /*
856: * Check target for a single file.
857: */
1.29 mrg 858: static int
1.96 dsl 859: check_for(unsigned int mode, const char *pathname)
1.14 jonathan 860: {
1.18 jonathan 861: int found;
1.14 jonathan 862:
1.54 fvdl 863: found = (target_test(mode, pathname) == 0);
1.18 jonathan 864: if (found == 0)
1.14 jonathan 865: msg_display(MSG_rootmissing, pathname);
1.18 jonathan 866: return found;
1.14 jonathan 867: }
868:
1.25 jonathan 869: /*
870: * Check that all the files in check_table are present in the
871: * target root. Warn if not found.
872: */
1.14 jonathan 873: int
1.96 dsl 874: sanity_check(void)
1.14 jonathan 875: {
876: int target_ok = 1;
877: struct check_table *p;
878:
879: for (p = checks; p->path; p++) {
1.54 fvdl 880: target_ok = target_ok && check_for(p->mode, p->path);
1.14 jonathan 881: }
882: if (target_ok)
883: return 0;
884:
885: /* Uh, oh. Something's missing. */
886: msg_display(MSG_badroot);
1.94 dsl 887: process_menu(MENU_ok, NULL);
1.14 jonathan 888: return 1;
1.11 jonathan 889: }
1.32 garbled 890:
1.52 hubertf 891: /*
892: * Some globals to pass things back from callbacks
893: */
894: static char zoneinfo_dir[STRSIZE];
1.101 dsl 895: static int zonerootlen;
896: static char *tz_selected; /* timezonename (relative to share/zoneinfo */
1.91 dsl 897: static const char *tz_default; /* UTC, or whatever /etc/localtime points to */
1.52 hubertf 898: static char tz_env[STRSIZE];
1.101 dsl 899: static int save_cursel, save_topline;
1.52 hubertf 900:
901: /*
902: * Callback from timezone menu
903: */
904: static int
1.108 dsl 905: set_tz_select(menudesc *m, void *arg)
1.52 hubertf 906: {
907: time_t t;
1.101 dsl 908: char *new;
1.52 hubertf 909:
1.110 dsl 910: if (m && strcmp(tz_selected, m->opts[m->cursel].opt_name) != 0) {
1.126 dsl 911: /* Change the displayed timezone */
1.101 dsl 912: new = strdup(m->opts[m->cursel].opt_name);
913: if (new == NULL)
914: return 0;
915: free(tz_selected);
916: tz_selected = new;
1.110 dsl 917: snprintf(tz_env, sizeof tz_env, "%.*s%s",
918: zonerootlen, zoneinfo_dir, tz_selected);
919: setenv("TZ", tz_env, 1);
1.101 dsl 920: }
1.126 dsl 921: if (m)
922: /* Warp curser to 'Exit' line on menu */
923: m->cursel = -1;
924:
925: /* Update displayed time */
1.52 hubertf 926: t = time(NULL);
927: msg_display(MSG_choose_timezone,
928: tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone);
929: return 0;
930: }
931:
1.101 dsl 932: static int
1.108 dsl 933: set_tz_back(menudesc *m, void *arg)
1.101 dsl 934: {
935:
936: zoneinfo_dir[zonerootlen] = 0;
937: m->cursel = save_cursel;
938: m->topline = save_topline;
939: return 0;
940: }
941:
942: static int
1.108 dsl 943: set_tz_dir(menudesc *m, void *arg)
1.101 dsl 944: {
945:
946: strlcpy(zoneinfo_dir + zonerootlen, m->opts[m->cursel].opt_name,
947: sizeof zoneinfo_dir - zonerootlen);
948: save_cursel = m->cursel;
949: save_topline = m->topline;
950: m->cursel = 0;
951: m->topline = 0;
952: return 0;
953: }
954:
1.52 hubertf 955: /*
956: * Alarm-handler to update example-display
957: */
958: static void
1.78 christos 959: /*ARGSUSED*/
1.52 hubertf 960: timezone_sig(int sig)
961: {
1.96 dsl 962:
1.108 dsl 963: set_tz_select(NULL, NULL);
1.74 grant 964: alarm(60);
1.52 hubertf 965: }
966:
1.101 dsl 967: static int
968: tz_sort(const void *a, const void *b)
969: {
1.107 dsl 970: return strcmp(((const menu_ent *)a)->opt_name, ((const menu_ent *)b)->opt_name);
1.101 dsl 971: }
972:
973: static void
974: tzm_set_names(menudesc *m, void *arg)
975: {
976: DIR *dir;
977: struct dirent *dp;
978: static int nfiles;
979: static int maxfiles = 32;
980: static menu_ent *tz_menu;
981: static char **tz_names;
982: void *p;
983: int maxfname;
984: char *fp;
985: struct stat sb;
986:
987: if (tz_menu == NULL)
988: tz_menu = malloc(maxfiles * sizeof *tz_menu);
989: if (tz_names == NULL)
990: tz_names = malloc(maxfiles * sizeof *tz_names);
991: if (tz_menu == NULL || tz_names == NULL)
992: return; /* error - skip timezone setting */
993: while (nfiles > 0)
994: free(tz_names[--nfiles]);
995:
996: dir = opendir(zoneinfo_dir);
997: fp = strchr(zoneinfo_dir, 0);
998: if (fp != zoneinfo_dir + zonerootlen) {
999: tz_names[0] = 0;
1.102 dsl 1000: tz_menu[0].opt_name = msg_string(MSG_tz_back);
1.101 dsl 1001: tz_menu[0].opt_menu = OPT_NOMENU;
1002: tz_menu[0].opt_flags = 0;
1003: tz_menu[0].opt_action = set_tz_back;
1004: nfiles = 1;
1005: }
1006: maxfname = zoneinfo_dir + sizeof zoneinfo_dir - fp - 1;
1007: if (dir != NULL) {
1008: while ((dp = readdir(dir)) != NULL) {
1009: if (dp->d_namlen > maxfname || dp->d_name[0] == '.')
1010: continue;
1011: strlcpy(fp, dp->d_name, maxfname);
1012: if (stat(zoneinfo_dir, &sb) == -1)
1013: continue;
1014: if (nfiles >= maxfiles) {
1015: p = realloc(tz_menu, 2 * maxfiles * sizeof *tz_menu);
1016: if (p == NULL)
1017: break;
1018: tz_menu = p;
1019: p = realloc(tz_names, 2 * maxfiles * sizeof *tz_names);
1020: if (p == NULL)
1021: break;
1022: tz_names = p;
1023: maxfiles *= 2;
1024: }
1025: if (S_ISREG(sb.st_mode))
1026: tz_menu[nfiles].opt_action = set_tz_select;
1027: else if (S_ISDIR(sb.st_mode)) {
1028: tz_menu[nfiles].opt_action = set_tz_dir;
1.111 itojun 1029: strlcat(fp, "/",
1030: sizeof(zoneinfo_dir) - (fp - zoneinfo_dir));
1.101 dsl 1031: } else
1032: continue;
1033: tz_names[nfiles] = strdup(zoneinfo_dir + zonerootlen);
1034: tz_menu[nfiles].opt_name = tz_names[nfiles];
1035: tz_menu[nfiles].opt_menu = OPT_NOMENU;
1036: tz_menu[nfiles].opt_flags = 0;
1037: nfiles++;
1038: }
1039: closedir(dir);
1040: }
1041: *fp = 0;
1042:
1043: m->opts = tz_menu;
1044: m->numopts = nfiles;
1045: qsort(tz_menu, nfiles, sizeof *tz_menu, tz_sort);
1046: }
1047:
1.52 hubertf 1048: /*
1049: * Choose from the files in usr/share/zoneinfo and set etc/localtime
1050: */
1051: int
1.96 dsl 1052: set_timezone(void)
1.52 hubertf 1053: {
1054: char localtime_link[STRSIZE];
1055: char localtime_target[STRSIZE];
1056: int rc;
1057: time_t t;
1058: int menu_no;
1059:
1.101 dsl 1060: strlcpy(zoneinfo_dir, target_expand("/usr/share/zoneinfo/"),
1061: sizeof zoneinfo_dir - 1);
1062: zonerootlen = strlen(zoneinfo_dir);
1.92 dsl 1063: strlcpy(localtime_link, target_expand("/etc/localtime"),
1064: sizeof localtime_link);
1.52 hubertf 1065:
1066: /* Add sanity check that /mnt/usr/share/zoneinfo contains
1.101 dsl 1067: * something useful
1068: */
1.52 hubertf 1069:
1070: rc = readlink(localtime_link, localtime_target,
1.75 provos 1071: sizeof(localtime_target) - 1);
1.52 hubertf 1072: if (rc < 0) {
1.53 hubertf 1073: /* error, default to UTC */
1074: tz_default = "UTC";
1075: } else {
1076: localtime_target[rc] = '\0';
1.92 dsl 1077: tz_default = strchr(strstr(localtime_target, "zoneinfo"), '/') + 1;
1.52 hubertf 1078: }
1079:
1.101 dsl 1080: tz_selected = strdup(tz_default);
1081: snprintf(tz_env, sizeof(tz_env), "%s%s", zoneinfo_dir, tz_selected);
1.52 hubertf 1082: setenv("TZ", tz_env, 1);
1083: t = time(NULL);
1084: msg_display(MSG_choose_timezone,
1085: tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone);
1086:
1.101 dsl 1087: signal(SIGALRM, timezone_sig);
1088: alarm(60);
1.52 hubertf 1089:
1.101 dsl 1090: menu_no = new_menu(NULL, NULL, 14, 23, 9,
1.112 dsl 1091: 12, 32, MC_ALWAYS_SCROLL | MC_NOSHORTCUT,
1.101 dsl 1092: tzm_set_names, NULL, NULL,
1.95 dsl 1093: "\nPlease consult the install documents.", NULL);
1.92 dsl 1094: if (menu_no < 0)
1095: goto done; /* error - skip timezone setting */
1.101 dsl 1096:
1.94 dsl 1097: process_menu(menu_no, NULL);
1.52 hubertf 1098:
1099: free_menu(menu_no);
1100:
1101: signal(SIGALRM, SIG_IGN);
1102:
1103: snprintf(localtime_target, sizeof(localtime_target),
1104: "/usr/share/zoneinfo/%s", tz_selected);
1105: unlink(localtime_link);
1106: symlink(localtime_target, localtime_link);
1107:
1.92 dsl 1108: done:
1.52 hubertf 1109: return 1;
1.66 ad 1110: }
1111:
1112: int
1113: set_crypt_type(void)
1114: {
1115: FILE *pwc;
1116: char *fn;
1117:
1118: msg_display(MSG_choose_crypt);
1.94 dsl 1119: process_menu(MENU_crypttype, NULL);
1.66 ad 1120: fn = strdup(target_expand("/etc/passwd.conf"));
1.80 christos 1121: if (fn == NULL)
1122: return -1;
1.66 ad 1123:
1.68 itojun 1124: switch (yesno) {
1.69 itojun 1125: case 0:
1126: break;
1127: case 1: /* DES */
1128: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1129: pwc = fopen(fn, "w");
1130: fprintf(pwc,
1131: "default:\n"
1.70 enami 1132: " localcipher = old\n"
1133: " ypcipher = old\n");
1.69 itojun 1134: fclose(pwc);
1135: break;
1136: case 2: /* MD5 */
1137: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1.66 ad 1138: pwc = fopen(fn, "w");
1139: fprintf(pwc,
1140: "default:\n"
1141: " localcipher = md5\n"
1142: " ypcipher = md5\n");
1143: fclose(pwc);
1.68 itojun 1144: break;
1.69 itojun 1145: case 3: /* blowfish 2^7 */
1146: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1.68 itojun 1147: pwc = fopen(fn, "w");
1148: fprintf(pwc,
1149: "default:\n"
1150: " localcipher = blowfish,7\n"
1151: " ypcipher = blowfish,7\n");
1152: fclose(pwc);
1153: break;
1.66 ad 1154: }
1155:
1.67 ad 1156: free(fn);
1.66 ad 1157: return (0);
1.56 fvdl 1158: }
1159:
1160: int
1.96 dsl 1161: set_root_password(void)
1.56 fvdl 1162: {
1.96 dsl 1163:
1.56 fvdl 1164: msg_display(MSG_rootpw);
1.94 dsl 1165: process_menu(MENU_yesno, NULL);
1.56 fvdl 1166: if (yesno)
1.129 dsl 1167: run_program(RUN_DISPLAY | RUN_PROGRESS | RUN_CHROOT,
1168: "passwd -l root");
1.73 grant 1169: return 0;
1170: }
1171:
1172: int
1.96 dsl 1173: set_root_shell(void)
1.73 grant 1174: {
1.96 dsl 1175:
1.73 grant 1176: msg_display(MSG_rootsh);
1.94 dsl 1177: process_menu(MENU_rootsh, NULL);
1.129 dsl 1178: run_program(RUN_DISPLAY | RUN_CHROOT, "chpass -s %s root", shellpath);
1.56 fvdl 1179: return 0;
1.64 mrg 1180: }
1181:
1182: void
1183: scripting_vfprintf(FILE *f, const char *fmt, va_list ap)
1184: {
1.96 dsl 1185:
1.64 mrg 1186: if (f)
1187: (void)vfprintf(f, fmt, ap);
1188: if (scripting)
1189: (void)vfprintf(script, fmt, ap);
1190: }
1191:
1192: void
1193: scripting_fprintf(FILE *f, const char *fmt, ...)
1194: {
1195: va_list ap;
1196:
1197: va_start(ap, fmt);
1198: scripting_vfprintf(f, fmt, ap);
1199: va_end(ap);
1200: }
1201:
1202: void
1203: add_rc_conf(const char *fmt, ...)
1204: {
1205: FILE *f;
1206: va_list ap;
1207:
1208: va_start(ap, fmt);
1209: f = target_fopen("/etc/rc.conf", "a");
1210: if (f != 0) {
1211: scripting_fprintf(NULL, "cat <<EOF >>%s/etc/rc.conf\n",
1212: target_prefix());
1213: scripting_vfprintf(f, fmt, ap);
1214: fclose(f);
1215: scripting_fprintf(NULL, "EOF\n");
1216: }
1217: va_end(ap);
1.112 dsl 1218: }
1219:
1220: void
1221: enable_rc_conf(void)
1222: {
1223: const char *tp = target_prefix();
1224:
1.115 dsl 1225: run_program(0, "sed -an -e 's/^rc_configured=NO/rc_configured=YES/;"
1.112 dsl 1226: "H;$!d;g;w %s/etc/rc.conf' %s/etc/rc.conf",
1227: tp, tp);
1.64 mrg 1228: }
1229:
1230: int
1.96 dsl 1231: check_lfs_progs(void)
1.64 mrg 1232: {
1233:
1234: return (access("/sbin/dump_lfs", X_OK) == 0 &&
1235: access("/sbin/fsck_lfs", X_OK) == 0 &&
1236: access("/sbin/mount_lfs", X_OK) == 0 &&
1237: access("/sbin/newfs_lfs", X_OK) == 0);
1.32 garbled 1238: }
CVSweb <webmaster@jp.NetBSD.org>