[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.97

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

CVSweb <webmaster@jp.NetBSD.org>