Annotation of src/distrib/utils/sysinst/util.c, Revision 1.67.2.8
1.67.2.8! jmc 1: /* $NetBSD$ */
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.14 jonathan 57: /*
58: * local prototypes
59: */
1.29 mrg 60: struct tarstats {
1.22 jonathan 61: int nselected;
62: int nfound;
63: int nnotfound;
64: int nerror;
65: int nsuccess;
1.44 cgd 66: int nskipped;
1.22 jonathan 67: } tarstats;
68:
1.61 mrg 69: int extract_file (char *path);
70: int extract_dist (void);
71: int cleanup_dist (const char *path);
72: int distribution_sets_exist_p (const char *path);
73: static int check_for (unsigned int mode, const char *pathname);
1.4 phil 74:
1.29 mrg 75: int
76: dir_exists_p(path)
77: const char *path;
1.22 jonathan 78: {
1.54 fvdl 79: return file_mode_match(path, S_IFDIR);
80: }
1.29 mrg 81:
1.54 fvdl 82: int
83: file_exists_p(path)
84: const char *path;
85: {
86: return file_mode_match(path, S_IFREG);
1.22 jonathan 87: }
88:
1.29 mrg 89: int
1.54 fvdl 90: file_mode_match(path, mode)
1.29 mrg 91: const char *path;
1.54 fvdl 92: unsigned int mode;
1.22 jonathan 93: {
1.54 fvdl 94: struct stat st;
1.29 mrg 95:
1.54 fvdl 96: return (stat(path, &st) == 0 && (st.st_mode & mode) != 0);
1.22 jonathan 97: }
98:
1.29 mrg 99: int
100: distribution_sets_exist_p(path)
101: const char *path;
1.22 jonathan 102: {
103: char buf[STRSIZE];
104: int result;
105:
106: result = 1;
107: snprintf(buf, STRSIZE, "%s/%s", path, "etc.tgz");
1.59 hubertf 108: result = result && file_exists_p(buf);
109:
1.62 jdc 110: snprintf(buf, STRSIZE, "%s/%s", path, "base.tgz");
111: result = result && file_exists_p(buf);
112:
1.22 jonathan 113: return(result);
114: }
115:
116:
1.29 mrg 117: void
118: get_ramsize()
1.4 phil 119: {
1.29 mrg 120: long len = sizeof(long);
1.4 phil 121: int mib[2] = {CTL_HW, HW_PHYSMEM};
122:
123: sysctl(mib, 2, (void *)&ramsize, (size_t *)&len, NULL, 0);
124:
125: /* Find out how many Megs ... round up. */
126: rammb = (ramsize + MEG - 1) / MEG;
127: }
128:
1.1 phil 129: static int asked = 0;
130:
1.29 mrg 131: void
1.50 fvdl 132: ask_sizemult(cylsize)
133: int cylsize;
1.1 phil 134: {
1.50 fvdl 135: current_cylsize = cylsize; /* XXX */
1.29 mrg 136:
1.1 phil 137: if (!asked) {
1.50 fvdl 138: msg_display(MSG_sizechoice);
1.29 mrg 139: process_menu(MENU_sizechoice);
1.1 phil 140: }
141: asked = 1;
1.9 phil 142: }
143:
1.29 mrg 144: void
1.50 fvdl 145: reask_sizemult(cylsize)
146: int cylsize;
1.9 phil 147: {
1.29 mrg 148:
1.9 phil 149: asked = 0;
1.50 fvdl 150: ask_sizemult(cylsize);
1.1 phil 151: }
152:
1.29 mrg 153: void
154: run_makedev()
1.3 phil 155: {
1.22 jonathan 156: char *owd;
157:
1.39 bouyer 158: wclear(stdscr);
159: wrefresh(stdscr);
1.29 mrg 160: msg_display(MSG_makedev);
1.5 phil 161: sleep (1);
1.14 jonathan 162:
1.29 mrg 163: owd = getcwd(NULL,0);
1.22 jonathan 164:
1.14 jonathan 165: /* make /dev, in case the user didn't extract it. */
166: make_target_dir("/dev");
1.10 jonathan 167: target_chdir_or_die("/dev");
1.56 fvdl 168: run_prog(0, NULL, "/bin/sh MAKEDEV all");
1.22 jonathan 169:
170: chdir(owd);
171: free(owd);
1.5 phil 172: }
173:
174:
1.29 mrg 175: /*
176: * Load files from floppy. Requires a /mnt2 directory for mounting them.
177: */
178: int
179: get_via_floppy()
1.5 phil 180: {
181: char distname[STRSIZE];
182: char fddev[STRSIZE] = "/dev/fd0a";
183: char fname[STRSIZE];
184: char fullname[STRSIZE];
1.34 garbled 185: char catcmd[STRSIZE];
1.7 phil 186: distinfo *list;
1.5 phil 187: char post[4];
188: int mounted = 0;
1.8 phil 189: int first;
1.5 phil 190: struct stat sb;
191:
1.29 mrg 192: cd_dist_dir("unloading from floppy");
1.7 phil 193:
1.29 mrg 194: msg_prompt_add(MSG_fddev, fddev, fddev, STRSIZE);
1.5 phil 195:
196: list = dist_list;
1.7 phil 197: while (list->name) {
1.29 mrg 198: strcpy(post, ".aa");
199: snprintf(distname, STRSIZE, "%s%s", list->name, dist_postfix);
1.8 phil 200: while (list->getit && strcmp(&post[1],list->fdlast) <= 0) {
1.29 mrg 201: snprintf(fname, STRSIZE, "%s%s", list->name, post);
202: snprintf(fullname, STRSIZE, "/mnt2/%s", fname);
1.8 phil 203: first = 1;
1.5 phil 204: while (!mounted || stat(fullname, &sb)) {
1.8 phil 205: if (mounted)
1.56 fvdl 206: run_prog(0, NULL, "/sbin/umount /mnt2");
1.8 phil 207: if (first)
1.29 mrg 208: msg_display(MSG_fdmount, fname);
1.8 phil 209: else
1.29 mrg 210: msg_display(MSG_fdnotfound, fname);
211: process_menu(MENU_fdok);
1.8 phil 212: if (!yesno)
213: return 0;
1.56 fvdl 214: while (run_prog(0, NULL,
1.35 bouyer 215: "/sbin/mount -r -t %s %s /mnt2",
1.29 mrg 216: fdtype, fddev)) {
217: msg_display(MSG_fdremount, fname);
218: process_menu(MENU_fdremount);
1.5 phil 219: if (!yesno)
220: return 0;
221: }
222: mounted = 1;
1.8 phil 223: first = 0;
1.5 phil 224: }
1.34 garbled 225: sprintf(catcmd, "/bin/cat %s >> %s",
226: fullname, distname);
227: if (logging)
228: (void)fprintf(log, "%s\n", catcmd);
229: if (scripting)
230: (void)fprintf(script, "%s\n", catcmd);
231: do_system(catcmd);
1.8 phil 232: if (post[2] < 'z')
233: post[2]++;
1.5 phil 234: else
1.29 mrg 235: post[2] = 'a', post[1]++;
1.5 phil 236: }
1.56 fvdl 237: run_prog(0, NULL, "/sbin/umount /mnt2");
1.5 phil 238: mounted = 0;
239: list++;
240: }
241: #ifndef DEBUG
1.10 jonathan 242: chdir("/"); /* back to current real root */
1.5 phil 243: #endif
1.6 phil 244: return 1;
245: }
246:
1.29 mrg 247: /*
248: * Get from a CDROM distribution.
249: */
1.6 phil 250: int
1.29 mrg 251: get_via_cdrom()
1.6 phil 252: {
1.22 jonathan 253: char tmpdir[STRSIZE];
1.28 fvdl 254:
255: /* Get CD-rom device name and path within CD-rom */
1.29 mrg 256: process_menu(MENU_cdromsource);
1.6 phil 257:
1.22 jonathan 258: again:
1.56 fvdl 259: run_prog(0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 260:
1.6 phil 261: /* Mount it */
1.56 fvdl 262: if (run_prog(0, NULL,
1.35 bouyer 263: "/sbin/mount -rt cd9660 /dev/%sa /mnt2", cdrom_dev)) {
1.22 jonathan 264: msg_display(MSG_badsetdir, cdrom_dev);
1.29 mrg 265: process_menu(MENU_cdrombadmount);
1.6 phil 266: if (!yesno)
267: return 0;
1.22 jonathan 268: if (!ignorerror)
269: goto again;
270: }
271:
272: snprintf(tmpdir, STRSIZE, "%s/%s", "/mnt2", cdrom_dir);
273:
274: /* Verify distribution files exist. */
275: if (distribution_sets_exist_p(tmpdir) == 0) {
276: msg_display(MSG_badsetdir, tmpdir);
1.29 mrg 277: process_menu(MENU_cdrombadmount);
1.22 jonathan 278: if (!yesno)
279: return (0);
280: if (!ignorerror)
281: goto again;
1.6 phil 282: }
283:
284: /* return location, don't clean... */
1.22 jonathan 285: strncpy(ext_dir, tmpdir, STRSIZE);
1.6 phil 286: clean_dist_dir = 0;
287: mnt2_mounted = 1;
1.5 phil 288: return 1;
1.7 phil 289: }
290:
1.22 jonathan 291:
292: /*
293: * Get from a pathname inside an unmounted local filesystem
294: * (e.g., where sets were preloaded onto a local DOS partition)
295: */
1.29 mrg 296: int
297: get_via_localfs()
1.16 mhitch 298: {
1.22 jonathan 299: char tmpdir[STRSIZE];
300:
1.16 mhitch 301: /* Get device, filesystem, and filepath */
302: process_menu (MENU_localfssource);
303:
1.22 jonathan 304: again:
1.56 fvdl 305: run_prog(0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 306:
1.16 mhitch 307: /* Mount it */
1.56 fvdl 308: if (run_prog(0, NULL, "/sbin/mount -rt %s /dev/%s /mnt2",
1.35 bouyer 309: localfs_fs, localfs_dev)) {
1.22 jonathan 310:
1.29 mrg 311: msg_display(MSG_localfsbadmount, localfs_dir, localfs_dev);
312: process_menu(MENU_localfsbadmount);
1.16 mhitch 313: if (!yesno)
314: return 0;
1.22 jonathan 315: if (!ignorerror)
1.29 mrg 316: goto again;
1.22 jonathan 317: }
318:
319: snprintf(tmpdir, STRSIZE, "%s/%s", "/mnt2", localfs_dir);
320:
321: /* Verify distribution files exist. */
322: if (distribution_sets_exist_p(tmpdir) == 0) {
323: msg_display(MSG_badsetdir, tmpdir);
1.29 mrg 324: process_menu(MENU_localfsbadmount);
1.22 jonathan 325: if (!yesno)
326: return 0;
327: if (!ignorerror)
328: goto again;
1.16 mhitch 329: }
330:
331: /* return location, don't clean... */
1.22 jonathan 332: strncpy(ext_dir, tmpdir, STRSIZE);
1.16 mhitch 333: clean_dist_dir = 0;
334: mnt2_mounted = 1;
335: return 1;
336: }
1.7 phil 337:
1.29 mrg 338: /*
339: * Get from an already-mounted pathname.
340: */
1.22 jonathan 341:
342: int get_via_localdir(void)
343: {
344:
345: /* Get device, filesystem, and filepath */
1.29 mrg 346: process_menu(MENU_localdirsource);
1.22 jonathan 347:
348: again:
349: /* Complain if not a directory */
350: if (dir_exists_p(localfs_dir) == 0) {
351:
1.29 mrg 352: msg_display(MSG_badlocalsetdir, localfs_dir);
353: process_menu(MENU_localdirbad);
1.22 jonathan 354: if (!yesno)
355: return (0);
356: if (!ignorerror)
357: goto again;
358: }
359:
360: /* Verify distribution files exist. */
361: if (distribution_sets_exist_p(localfs_dir) == 0) {
362: msg_display(MSG_badsetdir, localfs_dir);
1.29 mrg 363: process_menu(MENU_localdirbad);
1.22 jonathan 364: if (!yesno)
365: return (0);
366: if (!ignorerror)
367: goto again;
368: }
369:
370: /* return location, don't clean... */
1.29 mrg 371: strncpy(ext_dir, localfs_dir, STRSIZE);
1.22 jonathan 372: clean_dist_dir = 0;
373: mnt2_mounted = 0;
374: return 1;
375: }
376:
377:
1.29 mrg 378: void
379: cd_dist_dir(forwhat)
380: char *forwhat;
1.7 phil 381: {
1.19 phil 382: char *cwd;
383:
1.10 jonathan 384: /* ask user for the mountpoint. */
1.29 mrg 385: msg_prompt(MSG_distdir, dist_dir, dist_dir, STRSIZE, forwhat);
1.10 jonathan 386:
387: /* make sure the directory exists. */
388: make_target_dir(dist_dir);
1.7 phil 389:
390: clean_dist_dir = 1;
1.10 jonathan 391: target_chdir_or_die(dist_dir);
1.19 phil 392:
393: /* Set ext_dir for absolute path. */
1.29 mrg 394: cwd = getcwd(NULL,0);
395: strncpy(ext_dir, cwd, STRSIZE);
1.19 phil 396: free (cwd);
1.7 phil 397: }
398:
1.10 jonathan 399:
1.29 mrg 400: /*
401: * Support for custom distribution fetches / unpacks.
402: */
403: void
404: toggle_getit(num)
405: int num;
406: {
1.7 phil 407:
408: dist_list[num].getit ^= 1;
409: }
410:
1.29 mrg 411: void
412: show_cur_distsets()
1.7 phil 413: {
414: distinfo *list;
415:
1.29 mrg 416: msg_display(MSG_cur_distsets);
1.48 cgd 417: msg_table_add(MSG_cur_distsets_header);
1.7 phil 418: list = dist_list;
419: while (list->name) {
1.48 cgd 420: msg_table_add(MSG_cur_distsets_row, list->desc,
1.29 mrg 421: list->getit ? msg_string(MSG_yes) : msg_string(MSG_no));
1.7 phil 422: list++;
423: }
1.1 phil 424: }
1.10 jonathan 425:
1.12 phil 426: /* Do we want a verbose extract? */
427: static int verbose = -1;
428:
429: void
1.29 mrg 430: ask_verbose_dist()
1.12 phil 431: {
1.29 mrg 432:
1.12 phil 433: if (verbose < 0) {
1.29 mrg 434: msg_display(MSG_verboseextract);
435: process_menu(MENU_noyes);
1.12 phil 436: verbose = yesno;
1.36 bouyer 437: wclear(stdscr);
438: wrefresh(stdscr);
1.12 phil 439: }
440: }
441:
1.44 cgd 442: int
1.29 mrg 443: extract_file(path)
444: char *path;
1.12 phil 445: {
446: char *owd;
1.44 cgd 447: int tarexit, rv;
1.12 phil 448:
449: owd = getcwd (NULL,0);
450:
1.22 jonathan 451: /* check tarfile exists */
452: if (!file_exists_p(path)) {
453: tarstats.nnotfound++;
1.44 cgd 454:
455: msg_display(MSG_notarfile, path);
456: process_menu(MENU_noyes);
457: return (yesno == 0);
1.22 jonathan 458: }
459:
460: tarstats.nfound++;
1.14 jonathan 461: /* cd to the target root. */
1.12 phil 462: target_chdir_or_die("/");
463:
1.14 jonathan 464: /* now extract set files files into "./". */
1.56 fvdl 465: tarexit = run_prog(RUN_DISPLAY, NULL,
1.67.2.8! jmc 466: "pax -zr%spe -O -f %s", verbose ? "v" : "", path);
1.22 jonathan 467:
1.17 phil 468: /* Check tarexit for errors and give warning. */
1.22 jonathan 469: if (tarexit) {
470: tarstats.nerror++;
1.44 cgd 471:
472: msg_display(MSG_tarerror, path);
473: process_menu(MENU_noyes);
474: rv = (yesno == 0);
1.22 jonathan 475: } else {
476: tarstats.nsuccess++;
1.44 cgd 477: rv = 0;
1.22 jonathan 478: }
479:
1.29 mrg 480: chdir(owd);
481: free(owd);
1.44 cgd 482:
483: return (rv);
1.12 phil 484: }
485:
1.19 phil 486:
1.29 mrg 487: /*
1.37 bouyer 488: * Extract_dist **REQUIRES** an absolute path in ext_dir. Any code
1.19 phil 489: * that sets up dist_dir for use by extract_dist needs to put in the
490: * full path name to the directory.
491: */
492:
1.22 jonathan 493: int
1.29 mrg 494: extract_dist()
1.12 phil 495: {
496: char distname[STRSIZE];
497: char fname[STRSIZE];
498: distinfo *list;
1.44 cgd 499: int punt;
1.12 phil 500:
1.22 jonathan 501: /* reset failure/success counters */
1.31 perry 502: memset(&tarstats, 0, sizeof(tarstats));
1.22 jonathan 503:
1.32 garbled 504: /*endwin();*/
1.44 cgd 505: for (punt = 0, list = dist_list; list->name != NULL; list++) {
1.15 phil 506: if (list->getit) {
1.22 jonathan 507: tarstats.nselected++;
1.44 cgd 508: if (punt) {
509: tarstats.nskipped++;
510: continue;
511: }
1.37 bouyer 512: if (cleanup_dist(list->name) == 0) {
513: msg_display(MSG_cleanup_warn);
514: process_menu(MENU_ok);
515: }
1.29 mrg 516: (void)snprintf(distname, STRSIZE, "%s%s", list->name,
517: dist_postfix);
518: (void)snprintf(fname, STRSIZE, "%s/%s", ext_dir,
519: distname);
1.44 cgd 520:
521: /* if extraction failed and user aborted, punt. */
522: punt = extract_file(fname);
1.15 phil 523: }
1.12 phil 524: }
1.22 jonathan 525:
1.63 jdc 526: wrefresh(curscr);
1.60 jdc 527: wmove(stdscr, 0, 0);
1.43 cgd 528: wclear(stdscr);
1.17 phil 529: wrefresh(stdscr);
1.22 jonathan 530:
531: if (tarstats.nerror == 0 && tarstats.nsuccess == tarstats.nselected) {
1.29 mrg 532: msg_display(MSG_endtarok);
533: process_menu(MENU_ok);
1.22 jonathan 534: return 0;
535: } else {
536: /* We encountered errors. Let the user know. */
537: msg_display(MSG_endtar,
1.44 cgd 538: tarstats.nselected, tarstats.nnotfound, tarstats.nskipped,
1.22 jonathan 539: tarstats.nfound, tarstats.nsuccess, tarstats.nerror);
1.29 mrg 540: process_menu(MENU_ok);
1.22 jonathan 541: return 1;
542: }
1.12 phil 543: }
544:
1.11 jonathan 545: /*
1.37 bouyer 546: * Do pre-extract cleanup for set 'name':
547: * open a file named '/dist/<name>_obsolete file', which contain a list of
548: * files to kill from the target. For each file, test if it is present on
549: * the target. Then display the list of files which will be removed,
550: * ask user for confirmation, and process.
1.62 jdc 551: * Non-empty directories will be renamed to <directory.old>.
1.37 bouyer 552: */
553:
554: /* definition for a list of files. */
555: struct filelist {
556: struct filelist *next;
557: char name[MAXPATHLEN];
558: mode_t type;
559: };
560:
561: int
562: cleanup_dist(name)
563: const char *name;
564: {
565: char file_path[MAXPATHLEN];
566: char file_name[MAXPATHLEN];
567: FILE *list_file;
568: struct filelist *head = NULL;
569: struct filelist *current;
570: int saved_errno;
571: struct stat st;
572: int retval = 1;
573: int needok = 0;
574:
575: snprintf(file_path, MAXPATHLEN, "/dist/%s_obsolete", name);
576: list_file = fopen(file_path, "r");
577: if (list_file == NULL) {
578: saved_errno = errno;
579: if (logging)
580: fprintf(log, "Open of %s failed: %s\n", file_path,
581: strerror(saved_errno));
582: if (saved_errno == ENOENT)
583: return 1;
584: msg_display_add(MSG_openfail, name, strerror(saved_errno));
585: process_menu(MENU_ok);
586: return 0;
587: }
588: while (fgets(file_name, MAXPATHLEN, list_file)) {
589: /* ignore lines that don't begin with '/' */
590: if (file_name[0] != '/')
591: continue;
592: /* Remove trailing \n if any */
593: if (file_name[strlen(file_name)-1] == '\n')
594: file_name[strlen(file_name)-1] = '\0';
595: snprintf(file_path, MAXPATHLEN, "%s%s", target_prefix(),
596: file_name);
597: if (lstat(file_path, &st) != 0) {
598: saved_errno = errno;
599: if (logging)
600: fprintf(log, "stat() of %s failed: %s\n",
601: file_path, strerror(saved_errno));
602: if (saved_errno == ENOENT)
603: continue;
604: msg_display_add(MSG_statfail, file_path,
605: strerror(saved_errno));
606: process_menu(MENU_ok);
607: return 0;
608: }
609: if (head == NULL) {
610: head = current = malloc(sizeof(struct filelist));
611: if (head == NULL) {
612: fprintf(stderr, "out of memory\n");
613: exit(1);
614: }
615: } else {
616: current->next = malloc(sizeof(struct filelist));
1.67.2.3 lukem 617: if (current->next == NULL) {
1.37 bouyer 618: fprintf(stderr, "out of memory\n");
619: exit(1);
620: }
621: current = current->next;
622: }
623: current->next = NULL;
624: snprintf(current->name, MAXPATHLEN, "%s", file_path);
625: current->type = st.st_mode & S_IFMT;
626: if (logging)
627: fprintf(log, "Adding file %s, type %d to list of "
628: "obsolete file\n", current->name, current->type);
629: }
1.62 jdc 630: fclose(list_file);
1.37 bouyer 631: if (head == NULL)
1.38 bouyer 632: return 1;
1.37 bouyer 633: #if 0
634: /* XXX doesn't work, too many files printed ! */
635: msg_display(MSG_deleting_files);
636: for (current = head; current != NULL; current = current->next) {
1.49 cgd 637: if (current->type != S_IFDIR) {
638: /* XXX msg_printf_add going/gone away */
1.37 bouyer 639: msg_printf_add("%s ", current->name);
1.49 cgd 640: }
1.37 bouyer 641: }
642: msg_display_add(MSG_deleting_dirs);
643: for (current = head; current != NULL; current = current->next) {
1.49 cgd 644: if (current->type == S_IFDIR) {
645: /* XXX msg_printf_add going/gone away */
1.37 bouyer 646: msg_printf_add("%s ", current->name);
1.49 cgd 647: }
1.37 bouyer 648: }
649: process_menu(MENU_ok);
650: #endif
651: /* first remove files */
652: for (current = head; current != NULL; current = current->next) {
653: if (current->type == S_IFDIR)
654: continue;
655: if (scripting)
656: (void)fprintf(script, "rm %s\n", current->name);
657: if (unlink(current->name) != 0) {
658: saved_errno = errno;
1.51 hubertf 659: if (saved_errno == ENOENT)
660: continue; /* don't worry about
661: non-existing files */
1.37 bouyer 662: if (logging)
663: fprintf(log, "rm %s failed: %s\n",
664: current->name, strerror(saved_errno));
665: msg_display_add(MSG_unlink_fail, current->name,
666: strerror(saved_errno));
667: retval = 0;
668: needok = 1;
669: }
670:
671: }
672: /* now dirs */
673: for (current = head; current != NULL; current = current->next) {
674: if (current->type != S_IFDIR)
675: continue;
676: if (rmdir(current->name) == 0) {
677: if (scripting)
678: (void)fprintf(script, "rmdir %s\n",
679: current->name);
680: continue;
681: }
682: saved_errno = errno;
683: if (saved_errno == ENOTEMPTY) {
684: if (logging)
685: fprintf(log, "dir %s not empty, "
686: "trying to rename to %s.old\n",
687: current->name, current->name);
688: snprintf(file_path, MAXPATHLEN,
689: "%s.old", current->name);
690: if (scripting)
691: (void)fprintf(script, "mv %s %s\n",
692: current->name, file_path);
693: needok = 1;
694: if (rename(current->name, file_path) != 0) {
695: saved_errno = errno;
696: if (logging)
697: fprintf(log, "mv %s %s failed: %s\n",
698: current->name, file_path,
699: strerror(saved_errno));
700: msg_display_add(MSG_rename_fail, current->name,
701: file_path, strerror(errno));
702: retval = 0;
703: }
704: msg_display_add(MSG_renamed_dir, current->name,
705: file_path);
706: } else { /* rmdir error */
1.55 fvdl 707: /*
708: * Don't worry about non-existing directories.
709: */
710: if (saved_errno == ENOENT)
711: continue;
1.37 bouyer 712: if (logging)
713: fprintf(log, "rm %s failed: %s\n",
714: current->name, strerror(saved_errno));
715: msg_display_add(MSG_unlink_fail, current->name,
716: strerror(saved_errno));
717: retval = 0;
718: needok = 1;
719: }
720: }
721: if (needok)
722: process_menu(MENU_ok);
723: return retval;
724: }
725:
726: /*
1.29 mrg 727: * Get and unpack the distribution.
728: * show success_msg if installation completes. Otherwise,,
729: * show failure_msg and wait for the user to ack it before continuing.
1.11 jonathan 730: * success_msg and failure_msg must both be 0-adic messages.
731: */
1.45 cgd 732: int
1.29 mrg 733: get_and_unpack_sets(success_msg, failure_msg)
1.47 cgd 734: msg success_msg;
735: msg failure_msg;
1.11 jonathan 736: {
1.29 mrg 737:
1.20 jonathan 738: /* Ensure mountpoint for distribution files exists in current root. */
1.32 garbled 739: (void) mkdir("/mnt2", S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
740: if (scripting)
741: (void)fprintf(script, "mkdir /mnt2\nchmod 755 /mnt2\n");
1.20 jonathan 742:
1.26 phil 743: /* Find out which files to "get" if we get files. */
1.37 bouyer 744: wclear(stdscr);
745: wrefresh(stdscr);
1.29 mrg 746: process_menu(MENU_distset);
1.26 phil 747:
1.37 bouyer 748: /* ask user whether to do normal or verbose extraction */
749: ask_verbose_dist();
750:
1.11 jonathan 751: /* Get the distribution files */
1.46 cgd 752: do {
753: got_dist = 0;
754: process_menu(MENU_distmedium);
755: } while (got_dist == -1);
1.26 phil 756:
1.11 jonathan 757: if (nodist)
1.45 cgd 758: return 1;
1.20 jonathan 759:
1.22 jonathan 760: if (got_dist) {
1.11 jonathan 761:
1.22 jonathan 762: /* Extract the distribution, abort on errors. */
1.45 cgd 763: if (extract_dist())
764: return 1;
1.11 jonathan 765:
766: /* Configure the system */
1.29 mrg 767: run_makedev();
1.11 jonathan 768:
769: /* Other configuration. */
770: mnt_net_config();
771:
1.19 phil 772: /* Clean up dist dir (use absolute path name) */
1.11 jonathan 773: if (clean_dist_dir)
1.56 fvdl 774: run_prog(0, NULL, "/bin/rm -rf %s", ext_dir);
1.11 jonathan 775:
776: /* Mounted dist dir? */
777: if (mnt2_mounted)
1.56 fvdl 778: run_prog(0, NULL, "/sbin/umount /mnt2");
1.14 jonathan 779:
1.29 mrg 780: /* Install/Upgrade complete ... reboot or exit to script */
781: msg_display(success_msg);
782: process_menu(MENU_ok);
1.45 cgd 783: return 0;
1.22 jonathan 784: }
785:
1.29 mrg 786: msg_display(failure_msg);
787: process_menu(MENU_ok);
1.45 cgd 788: return 1;
1.14 jonathan 789: }
1.22 jonathan 790:
791:
1.14 jonathan 792:
793: /*
794: * Do a quick sanity check that the target can reboot.
795: * return 1 if everything OK, 0 if there is a problem.
796: * Uses a table of files we expect to find after a base install/upgrade.
797: */
798:
799: /* test flag and pathname to check for after unpacking. */
1.54 fvdl 800: struct check_table { unsigned int mode; const char *path;} checks[] = {
801: { S_IFREG, "/netbsd" },
802: { S_IFDIR, "/etc" },
803: { S_IFREG, "/etc/fstab" },
804: { S_IFREG, "/sbin/init" },
805: { S_IFREG, "/bin/sh" },
806: { S_IFREG, "/etc/rc" },
807: { S_IFREG, "/etc/rc.subr" },
808: { S_IFREG, "/etc/rc.conf" },
809: { S_IFDIR, "/dev" },
810: { S_IFCHR, "/dev/console" },
1.14 jonathan 811: /* XXX check for rootdev in target /dev? */
1.54 fvdl 812: { S_IFREG, "/etc/fstab" },
813: { S_IFREG, "/sbin/fsck" },
814: { S_IFREG, "/sbin/fsck_ffs" },
815: { S_IFREG, "/sbin/mount" },
816: { S_IFREG, "/sbin/mount_ffs" },
817: { S_IFREG, "/sbin/mount_nfs" },
1.20 jonathan 818: #if defined(DEBUG) || defined(DEBUG_CHECK)
1.54 fvdl 819: { S_IFREG, "/foo/bar" }, /* bad entry to exercise warning */
1.14 jonathan 820: #endif
821: { 0, 0 }
822:
823: };
824:
825: /*
826: * Check target for a single file.
827: */
1.29 mrg 828: static int
1.54 fvdl 829: check_for(mode, pathname)
830: unsigned int mode;
1.29 mrg 831: const char *pathname;
1.14 jonathan 832: {
1.18 jonathan 833: int found;
1.14 jonathan 834:
1.54 fvdl 835: found = (target_test(mode, pathname) == 0);
1.18 jonathan 836: if (found == 0)
1.14 jonathan 837: msg_display(MSG_rootmissing, pathname);
1.18 jonathan 838: return found;
1.14 jonathan 839: }
840:
1.25 jonathan 841: /*
842: * Check that all the files in check_table are present in the
843: * target root. Warn if not found.
844: */
1.14 jonathan 845: int
846: sanity_check()
847: {
848: int target_ok = 1;
849: struct check_table *p;
850:
851: for (p = checks; p->path; p++) {
1.54 fvdl 852: target_ok = target_ok && check_for(p->mode, p->path);
1.14 jonathan 853: }
854: if (target_ok)
855: return 0;
856:
857: /* Uh, oh. Something's missing. */
858: msg_display(MSG_badroot);
859: process_menu(MENU_ok);
860: return 1;
1.11 jonathan 861: }
1.32 garbled 862:
863: /* set reverse to 1 to default to no */
864: int askyesno(int reverse)
865: {
866: WINDOW *yesnowin;
867: int c, found;
868:
1.40 simonb 869: yesnowin = subwin(stdscr, 5, 20, getmaxy(stdscr)/2 - 2, getmaxx(stdscr)/2 - 10);
1.41 garbled 870: if (yesnowin == NULL) {
871: fprintf(stderr, "sysinst: failed to allocate yes/no box\n");
872: exit(1);
873: }
1.32 garbled 874: box(yesnowin, '*', '*');
875: wmove(yesnowin, 2,2);
876:
877: if (reverse)
878: waddstr(yesnowin, "Yes or No: [N]");
879: else
880: waddstr(yesnowin, "Yes or No: [Y]");
881:
882: wrefresh(yesnowin);
883: while ((c = getchar())) {
884: if (c == 'y' || c == 'Y') {
885: found = 1;
886: break;
887: } else if (c == 'n' || c == 'N' ) {
888: found = 0;
889: break;
890: } else if (c == '\n' || c == '\r') {
891: if (reverse)
892: found = 0;
893: else
894: found = 1;
895: break;
896: }
897: }
898: wclear(yesnowin);
899: wrefresh(yesnowin);
900: delwin(yesnowin);
901: refresh();
902: return(found);
1.52 hubertf 903: }
904:
905: /*
906: * Some globals to pass things back from callbacks
907: */
908: static char zoneinfo_dir[STRSIZE];
909: static char *tz_selected; /* timezonename (relative to share/zoneinfo */
910: static char *tz_default; /* UTC, or whatever /etc/localtime points to */
911: static char tz_env[STRSIZE];
912:
913: /*
914: * Callback from timezone menu
915: */
916: static int
917: set_timezone_select(menudesc *m)
918: {
919: time_t t;
920:
921: if (m)
922: tz_selected = m->opts[m->cursel].opt_name;
923: snprintf(tz_env, sizeof(tz_env), "%s/%s",
924: zoneinfo_dir, tz_selected);
925: setenv("TZ", tz_env, 1);
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:
932: /*
933: * Alarm-handler to update example-display
934: */
935: static void
936: timezone_sig(int sig)
937: {
938: set_timezone_select(NULL);
1.67.2.7 lukem 939: alarm(60);
1.52 hubertf 940: }
941:
942: /*
943: * Choose from the files in usr/share/zoneinfo and set etc/localtime
944: */
945: int
946: set_timezone()
947: {
948: char localtime_link[STRSIZE];
949: char localtime_target[STRSIZE];
950: int rc;
951: time_t t;
952: sig_t oldalrm;
953: FTS *tree;
954: FTSENT *entry;
955: int rval;
956: char *argv[2];
957: int skip;
958: struct stat sb;
959: int nfiles, n;
960: int menu_no;
961: menu_ent *tz_menu;
962:
1.64 mrg 963: oldalrm = signal(SIGALRM, timezone_sig);
1.52 hubertf 964: alarm(1);
965:
966: strncpy(zoneinfo_dir, target_expand("/usr/share/zoneinfo"), STRSIZE);
967: strncpy(localtime_link, target_expand("/etc/localtime"), STRSIZE);
968:
969: /* Add sanity check that /mnt/usr/share/zoneinfo contains
970: * something useful */
971:
972: rc = readlink(localtime_link, localtime_target,
973: sizeof(localtime_target));
974: if (rc < 0) {
1.53 hubertf 975: /* error, default to UTC */
976: tz_default = "UTC";
977: } else {
978: localtime_target[rc] = '\0';
979: tz_default = strchr(strstr(localtime_target, "zoneinfo"), '/')+1;
1.52 hubertf 980: }
981:
982: tz_selected=tz_default;
983: snprintf(tz_env, sizeof(tz_env), "%s/%s",
984: zoneinfo_dir, tz_selected);
985: setenv("TZ", tz_env, 1);
986: t = time(NULL);
987: msg_display(MSG_choose_timezone,
988: tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone);
989:
990: skip = strlen(zoneinfo_dir);
991: argv[0] = zoneinfo_dir;
992: argv[1] = NULL;
993: if (!(tree = fts_open(argv, FTS_LOGICAL, NULL))) {
1.53 hubertf 994: return 1; /* error - skip timezone setting */
1.52 hubertf 995: }
996: for (nfiles = 0; (entry = fts_read(tree)) != NULL;) {
997: stat(entry->fts_accpath, &sb);
998: if (S_ISREG(sb.st_mode))
999: nfiles++;
1000: }
1001: if (errno) {
1.53 hubertf 1002: return 1; /* error - skip timezone setting */
1.52 hubertf 1003: }
1004: (void)fts_close(tree);
1005:
1006: tz_menu = malloc(nfiles * sizeof(struct menu_ent));
1007: if (tz_menu == NULL) {
1.53 hubertf 1008: return 1; /* error - skip timezone setting */
1.52 hubertf 1009: }
1010:
1011: if (!(tree = fts_open(argv, FTS_LOGICAL, NULL))) {
1.53 hubertf 1012: return 1; /* error - skip timezone setting */
1.52 hubertf 1013: }
1.64 mrg 1014: n = 0;
1015: for (rval = 0; (entry = fts_read(tree)) != NULL; ) {
1.52 hubertf 1016: stat(entry->fts_accpath, &sb);
1017: if (S_ISREG(sb.st_mode)) {
1018: tz_menu[n].opt_name = strdup(entry->fts_accpath+skip+1);
1019: tz_menu[n].opt_menu = OPT_NOMENU;
1020: tz_menu[n].opt_flags = 0;
1021: tz_menu[n].opt_action = set_timezone_select;
1022:
1023: n++;
1024: }
1025: }
1026: if (errno) {
1.53 hubertf 1027: return 1; /* error - skip timezone setting */
1.52 hubertf 1028: }
1029: (void)fts_close(tree);
1030:
1031: menu_no = new_menu(NULL, tz_menu, nfiles, 23, 9,
1032: 12, 32, MC_SCROLL|MC_NOSHORTCUT, NULL, NULL,
1033: "\nPlease consult the install documents.");
1034: if (menu_no < 0) {
1.53 hubertf 1035: return 1; /* error - skip timezone setting */
1.52 hubertf 1036: }
1037: process_menu(menu_no);
1038:
1039: free_menu(menu_no);
1040: for(n=0; n < nfiles; n++)
1041: free(tz_menu[n].opt_name);
1042: free(tz_menu);
1043:
1044: signal(SIGALRM, SIG_IGN);
1045:
1046: snprintf(localtime_target, sizeof(localtime_target),
1047: "/usr/share/zoneinfo/%s", tz_selected);
1048: unlink(localtime_link);
1049: symlink(localtime_target, localtime_link);
1050:
1051: return 1;
1.66 ad 1052: }
1053:
1054: int
1055: set_crypt_type(void)
1056: {
1057: FILE *pwc;
1058: char *fn;
1059:
1060: msg_display(MSG_choose_crypt);
1061: process_menu(MENU_crypttype);
1062: fn = strdup(target_expand("/etc/passwd.conf"));
1063:
1.67.2.2 lukem 1064: switch (yesno) {
1065: case 0:
1066: break;
1067: case 1: /* DES */
1068: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1069: pwc = fopen(fn, "w");
1070: fprintf(pwc,
1071: "default:\n"
1072: " localcipher = old\n"
1073: " ypcipher = old\n");
1074: fclose(pwc);
1075: break;
1076: case 2: /* MD5 */
1077: rename(fn, target_expand("/etc/passwd.conf.pre-sysinst"));
1.66 ad 1078: pwc = fopen(fn, "w");
1079: fprintf(pwc,
1080: "default:\n"
1081: " localcipher = md5\n"
1082: " ypcipher = md5\n");
1083: fclose(pwc);
1.67.2.2 lukem 1084: break;
1.66 ad 1085: }
1086:
1.67 ad 1087: free(fn);
1.66 ad 1088: return (0);
1.56 fvdl 1089: }
1090:
1091: int
1092: set_root_password()
1093: {
1094: msg_display(MSG_rootpw);
1095: process_menu(MENU_yesno);
1096: if (yesno)
1097: run_prog(RUN_DISPLAY|RUN_CHROOT, NULL, "passwd -l root");
1098: return 0;
1.64 mrg 1099: }
1100:
1101: void
1102: scripting_vfprintf(FILE *f, const char *fmt, va_list ap)
1103: {
1104: if (f)
1105: (void)vfprintf(f, fmt, ap);
1106: if (scripting)
1107: (void)vfprintf(script, fmt, ap);
1108: }
1109:
1110: void
1111: scripting_fprintf(FILE *f, const char *fmt, ...)
1112: {
1113: va_list ap;
1114:
1115: va_start(ap, fmt);
1116: scripting_vfprintf(f, fmt, ap);
1117: va_end(ap);
1118: }
1119:
1120: void
1121: add_rc_conf(const char *fmt, ...)
1122: {
1123: FILE *f;
1124: va_list ap;
1125:
1126: va_start(ap, fmt);
1127: f = target_fopen("/etc/rc.conf", "a");
1128: if (f != 0) {
1129: scripting_fprintf(NULL, "cat <<EOF >>%s/etc/rc.conf\n",
1130: target_prefix());
1131: scripting_vfprintf(f, fmt, ap);
1132: fclose(f);
1133: scripting_fprintf(NULL, "EOF\n");
1134: }
1135: va_end(ap);
1136: }
1137:
1138: /*
1139: * check that there is at least a / somewhere.
1140: */
1141: int
1142: check_partitions()
1143: {
1144: int i;
1145:
1146: for (i = 0; i < getmaxpartitions(); i++)
1147: if (PI_ISBSDFS(&bsdlabel[i]) &&
1148: fsmount[i][0] == '/' && fsmount[i][1] == '\0')
1149: return 1;
1150: msg_display(MSG_no_root_fs);
1151: getchar();
1152: return 0;
1153: }
1154:
1155: void
1156: set_sizemultname_cyl()
1157: {
1158:
1159: sizemult = dlcylsize;
1160: multname = msg_string(MSG_cylname);
1161: }
1162:
1163: void
1164: set_sizemultname_meg()
1165: {
1166:
1167: sizemult = MEG / sectorsize;
1168: multname = msg_string(MSG_megname);
1169: }
1170:
1171: int
1172: check_lfs_progs()
1173: {
1174:
1175: return (access("/sbin/dump_lfs", X_OK) == 0 &&
1176: access("/sbin/fsck_lfs", X_OK) == 0 &&
1177: access("/sbin/mount_lfs", X_OK) == 0 &&
1178: access("/sbin/newfs_lfs", X_OK) == 0);
1.32 garbled 1179: }
CVSweb <webmaster@jp.NetBSD.org>