[BACK]Return to util.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / distrib / utils / sysinst

Annotation of src/distrib/utils/sysinst/util.c, Revision 1.56

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

CVSweb <webmaster@jp.NetBSD.org>