Annotation of src/distrib/utils/sysinst/util.c, Revision 1.41
1.41 ! garbled 1: /* $NetBSD: util.c,v 1.40 1999/04/18 04:09:27 simonb 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:
19: * This product includes software develooped for the NetBSD Project by
20: * Piermont Information Systems Inc.
21: * 4. The name of Piermont Information Systems Inc. may not be used to endorse
22: * or promote products derived from this software without specific prior
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.1 phil 50: #include "defs.h"
1.5 phil 51: #include "md.h"
1.1 phil 52: #include "msg_defs.h"
53: #include "menu_defs.h"
1.4 phil 54:
1.14 jonathan 55: /*
56: * local prototypes
57: */
1.29 mrg 58: struct tarstats {
1.22 jonathan 59: int nselected;
60: int nfound;
61: int nnotfound;
62: int nerror;
63: int nsuccess;
64: } tarstats;
65:
66: void extract_file __P((char *path));
67: int extract_dist __P((void));
1.37 bouyer 68: int cleanup_dist __P((const char *path));
1.22 jonathan 69: int distribution_sets_exist_p __P((const char *path));
1.14 jonathan 70: static int check_for __P((const char *type, const char *pathname));
1.4 phil 71:
1.29 mrg 72: /*
73: * XXX these are WAY bogus!
74: */
75: int
76: dir_exists_p(path)
77: const char *path;
1.22 jonathan 78: {
79: register int result;
1.29 mrg 80:
1.35 bouyer 81: result = (run_prog(0, 0, NULL, "test -d %s", path) == 0);
1.22 jonathan 82: return (result);
83: }
84:
1.29 mrg 85: int
86: file_exists_p(path)
87: const char *path;
1.22 jonathan 88: {
89: register int result;
1.29 mrg 90:
1.35 bouyer 91: result = (run_prog(0, 0, NULL, "test -f %s", path) == 0);
1.22 jonathan 92: return (result);
93: }
94:
1.29 mrg 95: int
96: distribution_sets_exist_p(path)
97: const char *path;
1.22 jonathan 98: {
99: char buf[STRSIZE];
100: int result;
101:
102: result = 1;
103: snprintf(buf, STRSIZE, "%s/%s", path, "kern.tgz");
104: result = result && file_exists_p(buf);
105:
106: snprintf(buf, STRSIZE, "%s/%s", path, "etc.tgz");
107: result = result && file_exists_p(buf);
108:
109: return(result);
110: }
111:
112:
1.29 mrg 113: void
114: get_ramsize()
1.4 phil 115: {
1.29 mrg 116: long len = sizeof(long);
1.4 phil 117: int mib[2] = {CTL_HW, HW_PHYSMEM};
118:
119: sysctl(mib, 2, (void *)&ramsize, (size_t *)&len, NULL, 0);
120:
121: /* Find out how many Megs ... round up. */
122: rammb = (ramsize + MEG - 1) / MEG;
123: }
124:
1.1 phil 125: static int asked = 0;
126:
1.29 mrg 127: void
128: ask_sizemult()
1.1 phil 129: {
1.29 mrg 130:
1.1 phil 131: if (!asked) {
1.29 mrg 132: msg_display(MSG_sizechoice, dlcylsize);
133: process_menu(MENU_sizechoice);
1.1 phil 134: }
135: asked = 1;
1.9 phil 136: }
137:
1.29 mrg 138: void
139: reask_sizemult()
1.9 phil 140: {
1.29 mrg 141:
1.9 phil 142: asked = 0;
1.29 mrg 143: ask_sizemult();
1.1 phil 144: }
145:
1.29 mrg 146: /*
147: * Returns 1 for "y" or "Y" and "n" otherwise. CR => default.
148: */
1.1 phil 149: int
1.29 mrg 150: ask_ynquestion(char *quest, char def, ...)
1.1 phil 151: {
152: char line[STRSIZE];
153: va_list ap;
154: char c;
155:
156: va_start(ap, def);
1.29 mrg 157: vsnprintf(line, STRSIZE, quest, ap);
1.1 phil 158: va_end(ap);
159:
1.17 phil 160: if (def)
1.29 mrg 161: printf("%s [%c]: ", line, def);
1.17 phil 162: else
1.29 mrg 163: printf("%s: ", line);
1.1 phil 164: c = getchar();
165: if (c == '\n')
166: return def == 'y';
167:
168: while (getchar() != '\n') /* eat characters */;
169:
170: return c == 'y' || c == 'Y';
171: }
172:
1.29 mrg 173: void
174: run_makedev()
1.3 phil 175: {
1.22 jonathan 176: char *owd;
177:
1.39 bouyer 178: wclear(stdscr);
179: wrefresh(stdscr);
1.29 mrg 180: msg_display(MSG_makedev);
1.5 phil 181: sleep (1);
1.14 jonathan 182:
1.29 mrg 183: owd = getcwd(NULL,0);
1.22 jonathan 184:
1.14 jonathan 185: /* make /dev, in case the user didn't extract it. */
186: make_target_dir("/dev");
1.10 jonathan 187: target_chdir_or_die("/dev");
1.35 bouyer 188: run_prog(0, 0, NULL, "/bin/sh MAKEDEV all");
1.22 jonathan 189:
190: chdir(owd);
191: free(owd);
1.5 phil 192: }
193:
194:
1.29 mrg 195: /*
196: * Load files from floppy. Requires a /mnt2 directory for mounting them.
197: */
198: int
199: get_via_floppy()
1.5 phil 200: {
201: char distname[STRSIZE];
202: char fddev[STRSIZE] = "/dev/fd0a";
203: char fname[STRSIZE];
204: char fullname[STRSIZE];
1.34 garbled 205: char catcmd[STRSIZE];
1.7 phil 206: distinfo *list;
1.5 phil 207: char post[4];
208: int mounted = 0;
1.8 phil 209: int first;
1.5 phil 210: struct stat sb;
211:
1.29 mrg 212: cd_dist_dir("unloading from floppy");
1.7 phil 213:
1.29 mrg 214: msg_prompt_add(MSG_fddev, fddev, fddev, STRSIZE);
1.5 phil 215:
216: list = dist_list;
1.7 phil 217: while (list->name) {
1.29 mrg 218: strcpy(post, ".aa");
219: snprintf(distname, STRSIZE, "%s%s", list->name, dist_postfix);
1.8 phil 220: while (list->getit && strcmp(&post[1],list->fdlast) <= 0) {
1.29 mrg 221: snprintf(fname, STRSIZE, "%s%s", list->name, post);
222: snprintf(fullname, STRSIZE, "/mnt2/%s", fname);
1.8 phil 223: first = 1;
1.5 phil 224: while (!mounted || stat(fullname, &sb)) {
1.8 phil 225: if (mounted)
1.35 bouyer 226: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.8 phil 227: if (first)
1.29 mrg 228: msg_display(MSG_fdmount, fname);
1.8 phil 229: else
1.29 mrg 230: msg_display(MSG_fdnotfound, fname);
231: process_menu(MENU_fdok);
1.8 phil 232: if (!yesno)
233: return 0;
1.35 bouyer 234: while (run_prog(0, 0, NULL,
235: "/sbin/mount -r -t %s %s /mnt2",
1.29 mrg 236: fdtype, fddev)) {
237: msg_display(MSG_fdremount, fname);
238: process_menu(MENU_fdremount);
1.5 phil 239: if (!yesno)
240: return 0;
241: }
242: mounted = 1;
1.8 phil 243: first = 0;
1.5 phil 244: }
1.34 garbled 245: sprintf(catcmd, "/bin/cat %s >> %s",
246: fullname, distname);
247: if (logging)
248: (void)fprintf(log, "%s\n", catcmd);
249: if (scripting)
250: (void)fprintf(script, "%s\n", catcmd);
251: do_system(catcmd);
1.8 phil 252: if (post[2] < 'z')
253: post[2]++;
1.5 phil 254: else
1.29 mrg 255: post[2] = 'a', post[1]++;
1.5 phil 256: }
1.35 bouyer 257: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.5 phil 258: mounted = 0;
259: list++;
260: }
261: #ifndef DEBUG
1.10 jonathan 262: chdir("/"); /* back to current real root */
1.5 phil 263: #endif
1.6 phil 264: return 1;
265: }
266:
1.29 mrg 267: /*
268: * Get from a CDROM distribution.
269: */
1.6 phil 270: int
1.29 mrg 271: get_via_cdrom()
1.6 phil 272: {
1.22 jonathan 273: char tmpdir[STRSIZE];
274:
1.29 mrg 275: /*
276: * Fill in final default path, similar to ftp path
277: * because we expect the CDROM structure to be the
278: * same as the ftp site.
279: */
280: strncat(cdrom_dir, machine, STRSIZE - strlen(cdrom_dir));
281: strncat(cdrom_dir, ftp_prefix, STRSIZE - strlen(cdrom_dir));
1.28 fvdl 282:
283: /* Get CD-rom device name and path within CD-rom */
1.29 mrg 284: process_menu(MENU_cdromsource);
1.6 phil 285:
1.22 jonathan 286: again:
1.35 bouyer 287: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 288:
1.6 phil 289: /* Mount it */
1.35 bouyer 290: if (run_prog(0, 0, NULL,
291: "/sbin/mount -rt cd9660 /dev/%sa /mnt2", cdrom_dev)) {
1.22 jonathan 292: msg_display(MSG_badsetdir, cdrom_dev);
1.29 mrg 293: process_menu(MENU_cdrombadmount);
1.6 phil 294: if (!yesno)
295: return 0;
1.22 jonathan 296: if (!ignorerror)
297: goto again;
298: }
299:
300: snprintf(tmpdir, STRSIZE, "%s/%s", "/mnt2", cdrom_dir);
301:
302: /* Verify distribution files exist. */
303: if (distribution_sets_exist_p(tmpdir) == 0) {
304: msg_display(MSG_badsetdir, tmpdir);
1.29 mrg 305: process_menu(MENU_cdrombadmount);
1.22 jonathan 306: if (!yesno)
307: return (0);
308: if (!ignorerror)
309: goto again;
1.6 phil 310: }
311:
312: /* return location, don't clean... */
1.22 jonathan 313: strncpy(ext_dir, tmpdir, STRSIZE);
1.6 phil 314: clean_dist_dir = 0;
315: mnt2_mounted = 1;
1.5 phil 316: return 1;
1.7 phil 317: }
318:
1.22 jonathan 319:
320: /*
321: * Get from a pathname inside an unmounted local filesystem
322: * (e.g., where sets were preloaded onto a local DOS partition)
323: */
1.29 mrg 324: int
325: get_via_localfs()
1.16 mhitch 326: {
1.22 jonathan 327: char tmpdir[STRSIZE];
328:
1.16 mhitch 329: /* Get device, filesystem, and filepath */
330: process_menu (MENU_localfssource);
331:
1.22 jonathan 332: again:
1.35 bouyer 333: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.22 jonathan 334:
1.16 mhitch 335: /* Mount it */
1.35 bouyer 336: if (run_prog(0, 0, NULL, "/sbin/mount -rt %s /dev/%s /mnt2",
337: localfs_fs, localfs_dev)) {
1.22 jonathan 338:
1.29 mrg 339: msg_display(MSG_localfsbadmount, localfs_dir, localfs_dev);
340: process_menu(MENU_localfsbadmount);
1.16 mhitch 341: if (!yesno)
342: return 0;
1.22 jonathan 343: if (!ignorerror)
1.29 mrg 344: goto again;
1.22 jonathan 345: }
346:
347: snprintf(tmpdir, STRSIZE, "%s/%s", "/mnt2", localfs_dir);
348:
349: /* Verify distribution files exist. */
350: if (distribution_sets_exist_p(tmpdir) == 0) {
351: msg_display(MSG_badsetdir, tmpdir);
1.29 mrg 352: process_menu(MENU_localfsbadmount);
1.22 jonathan 353: if (!yesno)
354: return 0;
355: if (!ignorerror)
356: goto again;
1.16 mhitch 357: }
358:
359: /* return location, don't clean... */
1.22 jonathan 360: strncpy(ext_dir, tmpdir, STRSIZE);
1.16 mhitch 361: clean_dist_dir = 0;
362: mnt2_mounted = 1;
363: return 1;
364: }
1.7 phil 365:
1.29 mrg 366: /*
367: * Get from an already-mounted pathname.
368: */
1.22 jonathan 369:
370: int get_via_localdir(void)
371: {
372:
373: /* Get device, filesystem, and filepath */
1.29 mrg 374: process_menu(MENU_localdirsource);
1.22 jonathan 375:
376: again:
377: /* Complain if not a directory */
378: if (dir_exists_p(localfs_dir) == 0) {
379:
1.29 mrg 380: msg_display(MSG_badlocalsetdir, localfs_dir);
381: process_menu(MENU_localdirbad);
1.22 jonathan 382: if (!yesno)
383: return (0);
384: if (!ignorerror)
385: goto again;
386: }
387:
388: /* Verify distribution files exist. */
389: if (distribution_sets_exist_p(localfs_dir) == 0) {
390: msg_display(MSG_badsetdir, localfs_dir);
1.29 mrg 391: process_menu(MENU_localdirbad);
1.22 jonathan 392: if (!yesno)
393: return (0);
394: if (!ignorerror)
395: goto again;
396: }
397:
398: /* return location, don't clean... */
1.29 mrg 399: strncpy(ext_dir, localfs_dir, STRSIZE);
1.22 jonathan 400: clean_dist_dir = 0;
401: mnt2_mounted = 0;
402: return 1;
403: }
404:
405:
1.29 mrg 406: void
407: cd_dist_dir(forwhat)
408: char *forwhat;
1.7 phil 409: {
1.19 phil 410: char *cwd;
411:
1.10 jonathan 412: /* ask user for the mountpoint. */
1.29 mrg 413: msg_prompt(MSG_distdir, dist_dir, dist_dir, STRSIZE, forwhat);
1.10 jonathan 414:
415: /* make sure the directory exists. */
416: make_target_dir(dist_dir);
1.7 phil 417:
418: clean_dist_dir = 1;
1.10 jonathan 419: target_chdir_or_die(dist_dir);
1.19 phil 420:
421: /* Set ext_dir for absolute path. */
1.29 mrg 422: cwd = getcwd(NULL,0);
423: strncpy(ext_dir, cwd, STRSIZE);
1.19 phil 424: free (cwd);
1.7 phil 425: }
426:
1.10 jonathan 427:
1.29 mrg 428: /*
429: * Support for custom distribution fetches / unpacks.
430: */
431: void
432: toggle_getit(num)
433: int num;
434: {
1.7 phil 435:
436: dist_list[num].getit ^= 1;
437: }
438:
1.29 mrg 439: void
440: show_cur_distsets()
1.7 phil 441: {
442: distinfo *list;
443:
1.29 mrg 444: msg_display(MSG_cur_distsets);
1.7 phil 445: list = dist_list;
446: while (list->name) {
1.29 mrg 447: msg_printf_add("%s%s\n", list->desc,
448: list->getit ? msg_string(MSG_yes) : msg_string(MSG_no));
1.7 phil 449: list++;
450: }
1.1 phil 451: }
1.10 jonathan 452:
1.12 phil 453: /* Do we want a verbose extract? */
454: static int verbose = -1;
455:
456: void
1.29 mrg 457: ask_verbose_dist()
1.12 phil 458: {
1.29 mrg 459:
1.12 phil 460: if (verbose < 0) {
1.29 mrg 461: msg_display(MSG_verboseextract);
462: process_menu(MENU_noyes);
1.12 phil 463: verbose = yesno;
1.36 bouyer 464: wclear(stdscr);
465: wrefresh(stdscr);
1.12 phil 466: }
467: }
468:
469: void
1.29 mrg 470: extract_file(path)
471: char *path;
1.12 phil 472: {
473: char *owd;
474: int tarexit;
475:
476: owd = getcwd (NULL,0);
477:
1.22 jonathan 478: /* check tarfile exists */
479: if (!file_exists_p(path)) {
480: tarstats.nnotfound++;
481: ask_ynquestion(msg_string(MSG_notarfile), 0, path);
482: return;
483: }
484:
485: tarstats.nfound++;
1.14 jonathan 486: /* cd to the target root. */
1.12 phil 487: target_chdir_or_die("/");
488:
1.14 jonathan 489: /* now extract set files files into "./". */
1.35 bouyer 490: tarexit = run_prog(0, 1, NULL,
491: "pax -zr%spe -f %s", verbose ? "v" : "", path);
1.22 jonathan 492:
1.17 phil 493: /* Check tarexit for errors and give warning. */
1.22 jonathan 494: if (tarexit) {
495: tarstats.nerror++;
1.29 mrg 496: ask_ynquestion(msg_string(MSG_tarerror), 0, path);
1.22 jonathan 497: sleep(3);
498: } else {
499: tarstats.nsuccess++;
500: sleep(1);
501: }
502:
1.29 mrg 503: chdir(owd);
504: free(owd);
1.12 phil 505: }
506:
1.19 phil 507:
1.29 mrg 508: /*
1.37 bouyer 509: * Extract_dist **REQUIRES** an absolute path in ext_dir. Any code
1.19 phil 510: * that sets up dist_dir for use by extract_dist needs to put in the
511: * full path name to the directory.
512: */
513:
1.22 jonathan 514: int
1.29 mrg 515: extract_dist()
1.12 phil 516: {
517: char distname[STRSIZE];
518: char fname[STRSIZE];
519: distinfo *list;
520:
1.22 jonathan 521: /* reset failure/success counters */
1.31 perry 522: memset(&tarstats, 0, sizeof(tarstats));
1.22 jonathan 523:
1.32 garbled 524: /*endwin();*/
1.12 phil 525: list = dist_list;
526: while (list->name) {
1.15 phil 527: if (list->getit) {
1.22 jonathan 528: tarstats.nselected++;
1.37 bouyer 529: if (cleanup_dist(list->name) == 0) {
530: msg_display(MSG_cleanup_warn);
531: process_menu(MENU_ok);
532: }
1.29 mrg 533: (void)snprintf(distname, STRSIZE, "%s%s", list->name,
534: dist_postfix);
535: (void)snprintf(fname, STRSIZE, "%s/%s", ext_dir,
536: distname);
537: extract_file(fname);
1.15 phil 538: }
1.12 phil 539: list++;
540: }
1.22 jonathan 541:
1.17 phil 542: puts(CL);
543: wrefresh(stdscr);
1.22 jonathan 544:
545: if (tarstats.nerror == 0 && tarstats.nsuccess == tarstats.nselected) {
1.29 mrg 546: msg_display(MSG_endtarok);
547: process_menu(MENU_ok);
1.22 jonathan 548: return 0;
549: } else {
550: /* We encountered errors. Let the user know. */
551: msg_display(MSG_endtar,
552: tarstats.nselected, tarstats.nnotfound,
553: tarstats.nfound, tarstats.nsuccess, tarstats.nerror);
1.29 mrg 554: process_menu(MENU_ok);
1.22 jonathan 555: return 1;
556: }
1.12 phil 557: }
558:
1.11 jonathan 559: /*
1.37 bouyer 560: * Do pre-extract cleanup for set 'name':
561: * open a file named '/dist/<name>_obsolete file', which contain a list of
562: * files to kill from the target. For each file, test if it is present on
563: * the target. Then display the list of files which will be removed,
564: * ask user for confirmation, and process.
565: * Non-empty directories will be renaned to <directory.old>.
566: */
567:
568: /* definition for a list of files. */
569: struct filelist {
570: struct filelist *next;
571: char name[MAXPATHLEN];
572: mode_t type;
573: };
574:
575: int
576: cleanup_dist(name)
577: const char *name;
578: {
579: char file_path[MAXPATHLEN];
580: char file_name[MAXPATHLEN];
581: FILE *list_file;
582: struct filelist *head = NULL;
583: struct filelist *current;
584: int saved_errno;
585: struct stat st;
586: int retval = 1;
587: int needok = 0;
588:
589: snprintf(file_path, MAXPATHLEN, "/dist/%s_obsolete", name);
590: list_file = fopen(file_path, "r");
591: if (list_file == NULL) {
592: saved_errno = errno;
593: if (logging)
594: fprintf(log, "Open of %s failed: %s\n", file_path,
595: strerror(saved_errno));
596: if (saved_errno == ENOENT)
597: return 1;
598: msg_display_add(MSG_openfail, name, strerror(saved_errno));
599: process_menu(MENU_ok);
600: return 0;
601: }
602: while (fgets(file_name, MAXPATHLEN, list_file)) {
603: /* ignore lines that don't begin with '/' */
604: if (file_name[0] != '/')
605: continue;
606: /* Remove trailing \n if any */
607: if (file_name[strlen(file_name)-1] == '\n')
608: file_name[strlen(file_name)-1] = '\0';
609: snprintf(file_path, MAXPATHLEN, "%s%s", target_prefix(),
610: file_name);
611: if (lstat(file_path, &st) != 0) {
612: saved_errno = errno;
613: if (logging)
614: fprintf(log, "stat() of %s failed: %s\n",
615: file_path, strerror(saved_errno));
616: if (saved_errno == ENOENT)
617: continue;
618: msg_display_add(MSG_statfail, file_path,
619: strerror(saved_errno));
620: process_menu(MENU_ok);
621: return 0;
622: }
623: if (head == NULL) {
624: head = current = malloc(sizeof(struct filelist));
625: if (head == NULL) {
626: fprintf(stderr, "out of memory\n");
627: exit(1);
628: }
629: } else {
630: current->next = malloc(sizeof(struct filelist));
631: if (head == NULL) {
632: fprintf(stderr, "out of memory\n");
633: exit(1);
634: }
635: current = current->next;
636: }
637: current->next = NULL;
638: snprintf(current->name, MAXPATHLEN, "%s", file_path);
639: current->type = st.st_mode & S_IFMT;
640: if (logging)
641: fprintf(log, "Adding file %s, type %d to list of "
642: "obsolete file\n", current->name, current->type);
643: }
644: if (head == NULL)
1.38 bouyer 645: return 1;
1.37 bouyer 646: #if 0
647: /* XXX doesn't work, too many files printed ! */
648: msg_display(MSG_deleting_files);
649: for (current = head; current != NULL; current = current->next) {
650: if (current->type != S_IFDIR)
651: msg_printf_add("%s ", current->name);
652: }
653: msg_display_add(MSG_deleting_dirs);
654: for (current = head; current != NULL; current = current->next) {
655: if (current->type == S_IFDIR)
656: msg_printf_add("%s ", current->name);
657: }
658: process_menu(MENU_ok);
659: #endif
660: /* first remove files */
661: for (current = head; current != NULL; current = current->next) {
662: if (current->type == S_IFDIR)
663: continue;
664: if (scripting)
665: (void)fprintf(script, "rm %s\n", current->name);
666: if (unlink(current->name) != 0) {
667: saved_errno = errno;
668: if (logging)
669: fprintf(log, "rm %s failed: %s\n",
670: current->name, strerror(saved_errno));
671: msg_display_add(MSG_unlink_fail, current->name,
672: strerror(saved_errno));
673: retval = 0;
674: needok = 1;
675: }
676:
677: }
678: /* now dirs */
679: for (current = head; current != NULL; current = current->next) {
680: if (current->type != S_IFDIR)
681: continue;
682: if (rmdir(current->name) == 0) {
683: if (scripting)
684: (void)fprintf(script, "rmdir %s\n",
685: current->name);
686: continue;
687: }
688: saved_errno = errno;
689: if (saved_errno == ENOTEMPTY) {
690: if (logging)
691: fprintf(log, "dir %s not empty, "
692: "trying to rename to %s.old\n",
693: current->name, current->name);
694: snprintf(file_path, MAXPATHLEN,
695: "%s.old", current->name);
696: if (scripting)
697: (void)fprintf(script, "mv %s %s\n",
698: current->name, file_path);
699: needok = 1;
700: if (rename(current->name, file_path) != 0) {
701: saved_errno = errno;
702: if (logging)
703: fprintf(log, "mv %s %s failed: %s\n",
704: current->name, file_path,
705: strerror(saved_errno));
706: msg_display_add(MSG_rename_fail, current->name,
707: file_path, strerror(errno));
708: retval = 0;
709: }
710: msg_display_add(MSG_renamed_dir, current->name,
711: file_path);
712: } else { /* rmdir error */
713: if (logging)
714: fprintf(log, "rm %s failed: %s\n",
715: current->name, strerror(saved_errno));
716: msg_display_add(MSG_unlink_fail, current->name,
717: strerror(saved_errno));
718: retval = 0;
719: needok = 1;
720: }
721: }
722: if (needok)
723: process_menu(MENU_ok);
724: return retval;
725: }
726:
727: /*
1.29 mrg 728: * Get and unpack the distribution.
729: * show success_msg if installation completes. Otherwise,,
730: * show failure_msg and wait for the user to ack it before continuing.
1.11 jonathan 731: * success_msg and failure_msg must both be 0-adic messages.
732: */
1.29 mrg 733: void
734: get_and_unpack_sets(success_msg, failure_msg)
735: int success_msg;
736: int failure_msg;
1.11 jonathan 737: {
1.29 mrg 738:
1.20 jonathan 739: /* Ensure mountpoint for distribution files exists in current root. */
1.32 garbled 740: (void) mkdir("/mnt2", S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
741: if (scripting)
742: (void)fprintf(script, "mkdir /mnt2\nchmod 755 /mnt2\n");
1.20 jonathan 743:
1.26 phil 744: /* Find out which files to "get" if we get files. */
1.37 bouyer 745: wclear(stdscr);
746: wrefresh(stdscr);
1.29 mrg 747: process_menu(MENU_distset);
1.26 phil 748:
1.37 bouyer 749: /* ask user whether to do normal or verbose extraction */
750: ask_verbose_dist();
751:
1.11 jonathan 752: /* Get the distribution files */
1.29 mrg 753: process_menu(MENU_distmedium);
1.26 phil 754:
1.11 jonathan 755: if (nodist)
756: return;
1.20 jonathan 757:
1.22 jonathan 758: if (got_dist) {
1.11 jonathan 759:
1.22 jonathan 760: /* Extract the distribution, abort on errors. */
1.29 mrg 761: if (extract_dist()) {
1.22 jonathan 762: goto bad;
763: }
1.11 jonathan 764:
765: /* Configure the system */
1.29 mrg 766: run_makedev();
1.11 jonathan 767:
768: /* Other configuration. */
769: mnt_net_config();
770:
1.19 phil 771: /* Clean up dist dir (use absolute path name) */
1.11 jonathan 772: if (clean_dist_dir)
1.35 bouyer 773: run_prog(0, 0, NULL, "/bin/rm -rf %s", ext_dir);
1.11 jonathan 774:
775: /* Mounted dist dir? */
776: if (mnt2_mounted)
1.35 bouyer 777: run_prog(0, 0, NULL, "/sbin/umount /mnt2");
1.14 jonathan 778:
1.29 mrg 779: /* Install/Upgrade complete ... reboot or exit to script */
780: msg_display(success_msg);
781: process_menu(MENU_ok);
1.22 jonathan 782: return;
783: }
784:
785: bad:
1.29 mrg 786: msg_display(failure_msg);
787: process_menu(MENU_ok);
1.14 jonathan 788: }
1.22 jonathan 789:
790:
1.14 jonathan 791:
792: /*
793: * Do a quick sanity check that the target can reboot.
794: * return 1 if everything OK, 0 if there is a problem.
795: * Uses a table of files we expect to find after a base install/upgrade.
796: */
797:
798: /* test flag and pathname to check for after unpacking. */
799: struct check_table { const char *testarg; const char *path;} checks[] = {
800: { "-f", "/netbsd" },
1.25 jonathan 801: { "-d", "/etc" },
1.14 jonathan 802: { "-f", "/etc/fstab" },
803: { "-f", "/sbin/init" },
804: { "-f", "/bin/sh" },
1.20 jonathan 805: { "-f", "/etc/rc" },
806: { "-f", "/etc/rc.subr" },
807: { "-f", "/etc/rc.conf" },
1.14 jonathan 808: { "-d" "/dev" },
809: { "-c", "/dev/console" },
810: /* XXX check for rootdev in target /dev? */
811: { "-f", "/etc/fstab" },
812: { "-f", "/sbin/fsck" },
813: { "-f", "/sbin/fsck_ffs" },
814: { "-f", "/sbin/mount" },
815: { "-f", "/sbin/mount_ffs" },
816: { "-f", "/sbin/mount_nfs" },
1.20 jonathan 817: #if defined(DEBUG) || defined(DEBUG_CHECK)
818: { "-f", "/foo/bar" }, /* bad entry to exercise warning */
1.14 jonathan 819: #endif
820: { 0, 0 }
821:
822: };
823:
824: /*
825: * Check target for a single file.
826: */
1.29 mrg 827: static int
828: check_for(type, pathname)
829: const char *type;
830: const char *pathname;
1.14 jonathan 831: {
1.18 jonathan 832: int found;
1.14 jonathan 833:
1.18 jonathan 834: found = (target_test(type, pathname) == 0);
835: if (found == 0)
1.14 jonathan 836: msg_display(MSG_rootmissing, pathname);
1.18 jonathan 837: return found;
1.14 jonathan 838: }
839:
1.25 jonathan 840: /*
841: * Check that all the files in check_table are present in the
842: * target root. Warn if not found.
843: */
1.14 jonathan 844: int
845: sanity_check()
846: {
847: int target_ok = 1;
848: struct check_table *p;
849:
850: for (p = checks; p->path; p++) {
851: target_ok = target_ok && check_for(p->testarg, p->path);
852: }
853: if (target_ok)
854: return 0;
855:
856: /* Uh, oh. Something's missing. */
857: msg_display(MSG_badroot);
858: process_menu(MENU_ok);
859: return 1;
1.11 jonathan 860: }
1.32 garbled 861:
862: /* set reverse to 1 to default to no */
863: int askyesno(int reverse)
864: {
865: WINDOW *yesnowin;
866: int c, found;
867:
1.40 simonb 868: yesnowin = subwin(stdscr, 5, 20, getmaxy(stdscr)/2 - 2, getmaxx(stdscr)/2 - 10);
1.41 ! garbled 869: if (yesnowin == NULL) {
! 870: fprintf(stderr, "sysinst: failed to allocate yes/no box\n");
! 871: exit(1);
! 872: }
1.32 garbled 873: box(yesnowin, '*', '*');
874: wmove(yesnowin, 2,2);
875:
876: if (reverse)
877: waddstr(yesnowin, "Yes or No: [N]");
878: else
879: waddstr(yesnowin, "Yes or No: [Y]");
880:
881: wrefresh(yesnowin);
882: while ((c = getchar())) {
883: if (c == 'y' || c == 'Y') {
884: found = 1;
885: break;
886: } else if (c == 'n' || c == 'N' ) {
887: found = 0;
888: break;
889: } else if (c == '\n' || c == '\r') {
890: if (reverse)
891: found = 0;
892: else
893: found = 1;
894: break;
895: }
896: }
897: wclear(yesnowin);
898: wrefresh(yesnowin);
899: delwin(yesnowin);
900: refresh();
901: return(found);
902: }
CVSweb <webmaster@jp.NetBSD.org>