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

1.170.2.2! yamt        1: /*     $NetBSD: util.c,v 1.170.2.1 2012/04/17 00:02:51 yamt 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.
1.169     mbalmer    17:  * 3. The name of Piermont Information Systems Inc. may not be used to endorse
1.1       phil       18:  *    or promote products derived from this software without specific prior
                     19:  *    written permission.
                     20:  *
                     21:  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
                     22:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     23:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
1.169     mbalmer    24:  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
                     25:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     26:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
1.1       phil       27:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     28:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     29:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
1.169     mbalmer    30:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
1.1       phil       31:  * THE POSSIBILITY OF SUCH DAMAGE.
                     32:  *
                     33:  */
                     34:
                     35: /* util.c -- routines that don't really fit anywhere else... */
                     36:
                     37: #include <stdio.h>
1.10      jonathan   38: #include <stdarg.h>
1.164     martin     39: #include <string.h>
1.1       phil       40: #include <unistd.h>
1.168     martin     41: #include <sys/mount.h>
1.164     martin     42: #include <sys/disklabel.h>
                     43: #include <sys/dkio.h>
                     44: #include <sys/ioctl.h>
1.5       phil       45: #include <sys/types.h>
1.4       phil       46: #include <sys/param.h>
                     47: #include <sys/sysctl.h>
1.5       phil       48: #include <sys/stat.h>
1.153     ad         49: #include <sys/statvfs.h>
1.164     martin     50: #include <isofs/cd9660/iso.h>
1.2       phil       51: #include <curses.h>
1.163     jmmv       52: #include <err.h>
1.37      bouyer     53: #include <errno.h>
1.101     dsl        54: #include <dirent.h>
1.64      mrg        55: #include <util.h>
1.1       phil       56: #include "defs.h"
1.5       phil       57: #include "md.h"
1.1       phil       58: #include "msg_defs.h"
                     59: #include "menu_defs.h"
1.4       phil       60:
1.138     dsl        61: #ifndef MD_SETS_SELECTED
                     62: #define MD_SETS_SELECTED SET_KERNEL_1, SET_SYSTEM, SET_X11, SET_MD
                     63: #endif
1.145     hubertf    64: #ifndef MD_SETS_SELECTED_MINIMAL
                     65: #define MD_SETS_SELECTED_MINIMAL SET_KERNEL_1, SET_CORE
                     66: #endif
1.167     joerg      67: #ifndef MD_SETS_SELECTED_NOX
                     68: #define MD_SETS_SELECTED_NOX SET_KERNEL_1, SET_SYSTEM, SET_MD
                     69: #endif
1.138     dsl        70: #ifndef MD_SETS_VALID
1.170.2.1  yamt       71: #define MD_SETS_VALID SET_KERNEL, SET_SYSTEM, SET_X11, SET_MD, SET_SOURCE
1.138     dsl        72: #endif
                     73:
1.164     martin     74: #define MAX_CD_DEVS    256     /* how many cd drives do we expect to attach */
                     75: #define ISO_BLKSIZE    ISO_DEFAULT_BLOCK_SIZE
                     76:
1.138     dsl        77: static const char *msg_yes, *msg_no, *msg_all, *msg_some, *msg_none;
                     78: static const char *msg_cur_distsets_row;
                     79: static int select_menu_width;
                     80:
                     81: static uint8_t set_status[SET_GROUP_END];
                     82: #define SET_VALID      0x01
                     83: #define SET_SELECTED   0x02
                     84: #define SET_SKIPPED    0x04
                     85: #define SET_INSTALLED  0x08
                     86:
                     87: struct  tarstats {
                     88:        int nselected;
                     89:        int nfound;
                     90:        int nnotfound;
                     91:        int nerror;
                     92:        int nsuccess;
                     93:        int nskipped;
                     94: } tarstats;
                     95:
1.97      dsl        96: distinfo dist_list[] = {
                     97: #ifdef SET_KERNEL_1_NAME
1.146     he         98:        {SET_KERNEL_1_NAME,     SET_KERNEL_1,           MSG_set_kernel_1, NULL},
1.97      dsl        99: #endif
                    100: #ifdef SET_KERNEL_2_NAME
1.146     he        101:        {SET_KERNEL_2_NAME,     SET_KERNEL_2,           MSG_set_kernel_2, NULL},
1.97      dsl       102: #endif
                    103: #ifdef SET_KERNEL_3_NAME
1.146     he        104:        {SET_KERNEL_3_NAME,     SET_KERNEL_3,           MSG_set_kernel_3, NULL},
1.97      dsl       105: #endif
                    106: #ifdef SET_KERNEL_4_NAME
1.146     he        107:        {SET_KERNEL_4_NAME,     SET_KERNEL_4,           MSG_set_kernel_4, NULL},
1.97      dsl       108: #endif
                    109: #ifdef SET_KERNEL_5_NAME
1.146     he        110:        {SET_KERNEL_5_NAME,     SET_KERNEL_5,           MSG_set_kernel_5, NULL},
1.97      dsl       111: #endif
                    112: #ifdef SET_KERNEL_6_NAME
1.146     he        113:        {SET_KERNEL_6_NAME,     SET_KERNEL_6,           MSG_set_kernel_6, NULL},
1.97      dsl       114: #endif
                    115: #ifdef SET_KERNEL_7_NAME
1.146     he        116:        {SET_KERNEL_7_NAME,     SET_KERNEL_7,           MSG_set_kernel_7, NULL},
1.97      dsl       117: #endif
                    118: #ifdef SET_KERNEL_8_NAME
1.146     he        119:        {SET_KERNEL_8_NAME,     SET_KERNEL_8,           MSG_set_kernel_8, NULL},
1.97      dsl       120: #endif
1.138     dsl       121:
1.159     jnemeth   122:        {"modules",             SET_MODULES,            MSG_set_modules, NULL},
1.146     he        123:        {"base",                SET_BASE,               MSG_set_base, NULL},
                    124:        {"etc",                 SET_ETC,                MSG_set_system, NULL},
                    125:        {"comp",                SET_COMPILER,           MSG_set_compiler, NULL},
                    126:        {"games",               SET_GAMES,              MSG_set_games, NULL},
                    127:        {"man",                 SET_MAN_PAGES,          MSG_set_man_pages, NULL},
                    128:        {"misc",                SET_MISC,               MSG_set_misc, NULL},
1.149     jmmv      129:        {"tests",               SET_TESTS,              MSG_set_tests, NULL},
1.146     he        130:        {"text",                SET_TEXT_TOOLS,         MSG_set_text_tools, NULL},
                    131:
                    132:        {NULL,                  SET_GROUP,              MSG_set_X11, NULL},
                    133:        {"xbase",               SET_X11_BASE,           MSG_set_X11_base, NULL},
                    134:        {"xcomp",               SET_X11_PROG,           MSG_set_X11_prog, NULL},
                    135:        {"xetc",                SET_X11_ETC,            MSG_set_X11_etc, NULL},
                    136:        {"xfont",               SET_X11_FONTS,          MSG_set_X11_fonts, NULL},
                    137:        {"xserver",             SET_X11_SERVERS,        MSG_set_X11_servers, NULL},
                    138:        {NULL,                  SET_GROUP_END,          NULL, NULL},
1.138     dsl       139:
1.97      dsl       140: #ifdef SET_MD_1_NAME
1.146     he        141:        {SET_MD_1_NAME,         SET_MD_1,               MSG_set_md_1, NULL},
1.97      dsl       142: #endif
                    143: #ifdef SET_MD_2_NAME
1.146     he        144:        {SET_MD_2_NAME,         SET_MD_2,               MSG_set_md_2, NULL},
1.97      dsl       145: #endif
                    146: #ifdef SET_MD_3_NAME
1.146     he        147:        {SET_MD_3_NAME,         SET_MD_3,               MSG_set_md_3, NULL},
1.97      dsl       148: #endif
                    149: #ifdef SET_MD_4_NAME
1.146     he        150:        {SET_MD_4_NAME,         SET_MD_4,               MSG_set_md_4, NULL},
1.97      dsl       151: #endif
1.138     dsl       152:
1.170.2.1  yamt      153:        {NULL,                  SET_GROUP,              MSG_set_source, NULL},
                    154:        {"syssrc",              SET_SYSSRC,             MSG_set_syssrc, NULL},
                    155:        {"src",                 SET_SRC,                MSG_set_src, NULL},
                    156:        {"sharesrc",            SET_SHARESRC,           MSG_set_sharesrc, NULL},
                    157:        {"gnusrc",              SET_GNUSRC,             MSG_set_gnusrc, NULL},
                    158:        {"xsrc",                SET_XSRC,               MSG_set_xsrc, NULL},
                    159:        {NULL,                  SET_GROUP_END,          NULL, NULL},
                    160:
1.146     he        161:        {NULL,                  SET_LAST,               NULL, NULL},
1.97      dsl       162: };
                    163:
1.164     martin    164: #define MAX_CD_INFOS   16      /* how many media can be found? */
                    165: struct cd_info {
                    166:        char device_name[16];
                    167:        char menu[100];
                    168: };
                    169: static struct cd_info cds[MAX_CD_INFOS];
                    170:
1.14      jonathan  171: /*
1.169     mbalmer   172:  * local prototypes
1.14      jonathan  173:  */
1.22      jonathan  174:
1.104     dsl       175: static int check_for(unsigned int mode, const char *pathname);
1.164     martin    176: static int get_iso9660_volname(int dev, int sess, char *volname);
                    177: static int get_available_cds(void);
1.4       phil      178:
1.140     dsl       179: void
1.167     joerg     180: init_set_status(int flags)
1.138     dsl       181: {
1.146     he        182:        static const uint8_t sets_valid[] = {MD_SETS_VALID};
                    183:        static const uint8_t sets_selected_full[] = {MD_SETS_SELECTED};
                    184:        static const uint8_t sets_selected_minimal[] = {MD_SETS_SELECTED_MINIMAL};
1.167     joerg     185:        static const uint8_t sets_selected_nox[] = {MD_SETS_SELECTED_NOX};
1.146     he        186:        static const uint8_t *sets_selected;
1.162     dsl       187:        unsigned int nelem_selected;
1.138     dsl       188:        unsigned int i, len;
                    189:        const char *longest;
                    190:
1.167     joerg     191:        if (flags & SFLAG_MINIMAL) {
1.145     hubertf   192:                sets_selected = sets_selected_minimal;
1.147     hubertf   193:                nelem_selected = nelem(sets_selected_minimal);
1.167     joerg     194:        } else if (flags & SFLAG_NOX) {
                    195:                sets_selected = sets_selected_nox;
                    196:                nelem_selected = nelem(sets_selected_nox);
1.147     hubertf   197:        } else {
1.145     hubertf   198:                sets_selected = sets_selected_full;
1.147     hubertf   199:                nelem_selected = nelem(sets_selected_full);
                    200:        }
1.145     hubertf   201:
1.138     dsl       202:        for (i = 0; i < nelem(sets_valid); i++)
                    203:                set_status[sets_valid[i]] = SET_VALID;
1.147     hubertf   204:        for (i = 0; i < nelem_selected; i++)
1.138     dsl       205:                set_status[sets_selected[i]] |= SET_SELECTED;
                    206:
                    207:        set_status[SET_GROUP] = SET_VALID;
                    208:
                    209:        /* Lookup some strings we need lots of times */
                    210:        msg_yes = msg_string(MSG_Yes);
                    211:        msg_no = msg_string(MSG_No);
                    212:        msg_all = msg_string(MSG_All);
                    213:        msg_some = msg_string(MSG_Some);
                    214:        msg_none = msg_string(MSG_None);
                    215:        msg_cur_distsets_row = msg_string(MSG_cur_distsets_row);
                    216:
                    217:        /* Find longest and use it to determine width of selection menu */
                    218:        len = strlen(msg_no); longest = msg_no;
                    219:        i = strlen(msg_yes); if (i > len) {len = i; longest = msg_yes; }
                    220:        i = strlen(msg_all); if (i > len) {len = i; longest = msg_all; }
                    221:        i = strlen(msg_some); if (i > len) {len = i; longest = msg_some; }
                    222:        i = strlen(msg_none); if (i > len) {len = i; longest = msg_none; }
                    223:        select_menu_width = snprintf(NULL, 0, msg_cur_distsets_row, "",longest);
1.150     rumble    224:
                    225:        /* Give the md code a chance to choose the right kernel, etc. */
1.167     joerg     226:        md_init_set_status(flags);
1.138     dsl       227: }
1.97      dsl       228:
1.29      mrg       229: int
1.96      dsl       230: dir_exists_p(const char *path)
1.22      jonathan  231: {
1.96      dsl       232:
1.54      fvdl      233:        return file_mode_match(path, S_IFDIR);
                    234: }
1.29      mrg       235:
1.54      fvdl      236: int
1.96      dsl       237: file_exists_p(const char *path)
1.54      fvdl      238: {
1.96      dsl       239:
1.54      fvdl      240:        return file_mode_match(path, S_IFREG);
1.22      jonathan  241: }
                    242:
1.29      mrg       243: int
1.96      dsl       244: file_mode_match(const char *path, unsigned int mode)
1.22      jonathan  245: {
1.54      fvdl      246:        struct stat st;
1.29      mrg       247:
1.138     dsl       248:        return (stat(path, &st) == 0 && (st.st_mode & S_IFMT) == mode);
1.22      jonathan  249: }
                    250:
1.125     dsl       251: uint
1.96      dsl       252: get_ramsize(void)
1.4       phil      253: {
1.125     dsl       254:        uint64_t ramsize;
                    255:        size_t len = sizeof ramsize;
                    256:        int mib[2] = {CTL_HW, HW_PHYSMEM64};
1.169     mbalmer   257:
1.78      christos  258:        sysctl(mib, 2, &ramsize, &len, NULL, 0);
1.4       phil      259:
                    260:        /* Find out how many Megs ... round up. */
1.125     dsl       261:        return (ramsize + MEG - 1) / MEG;
1.4       phil      262: }
                    263:
1.29      mrg       264: void
1.96      dsl       265: run_makedev(void)
1.3       phil      266: {
1.22      jonathan  267:        char *owd;
                    268:
1.128     dsl       269:        msg_display_add("\n\n");
1.127     dsl       270:        msg_display_add(MSG_makedev);
1.14      jonathan  271:
1.78      christos  272:        owd = getcwd(NULL, 0);
1.22      jonathan  273:
1.14      jonathan  274:        /* make /dev, in case the user  didn't extract it. */
                    275:        make_target_dir("/dev");
1.10      jonathan  276:        target_chdir_or_die("/dev");
1.115     dsl       277:        run_program(0, "/bin/sh MAKEDEV all");
1.22      jonathan  278:
                    279:        chdir(owd);
                    280:        free(owd);
1.5       phil      281: }
                    282:
1.163     jmmv      283: /*
                    284:  * Performs in-place replacement of a set of patterns in a file that lives
                    285:  * inside the installed system.  The patterns must be separated by a semicolon.
                    286:  * For example:
                    287:  *
                    288:  * replace("/etc/some-file.conf", "s/prop1=NO/prop1=YES/;s/foo/bar/");
                    289:  */
                    290: void
                    291: replace(const char *path, const char *patterns, ...)
                    292: {
                    293:        char *spatterns;
                    294:        va_list ap;
                    295:
                    296:        va_start(ap, patterns);
                    297:        vasprintf(&spatterns, patterns, ap);
                    298:        va_end(ap);
                    299:        if (spatterns == NULL)
                    300:                err(1, "vasprintf(&spatterns, \"%s\", ...)", patterns);
                    301:
                    302:        run_program(RUN_CHROOT, "sed -an -e '%s;H;$!d;g;w %s' %s", spatterns,
                    303:            path, path);
                    304:
                    305:        free(spatterns);
                    306: }
                    307:
1.138     dsl       308: static int
                    309: floppy_fetch(const char *set_name)
                    310: {
                    311:        char post[4];
1.143     dsl       312:        msg errmsg;
1.138     dsl       313:        int menu;
                    314:        int status;
1.143     dsl       315:        const char *write_mode = ">";
1.138     dsl       316:
                    317:        strcpy(post, "aa");
                    318:
1.143     dsl       319:        errmsg = "";
1.138     dsl       320:        menu = MENU_fdok;
                    321:        for (;;) {
                    322:                umount_mnt2();
1.143     dsl       323:                msg_display(errmsg);
                    324:                msg_display_add(MSG_fdmount, set_name, post);
1.138     dsl       325:                process_menu(menu, &status);
                    326:                if (status != SET_CONTINUE)
                    327:                        return status;
                    328:                menu = MENU_fdremount;
1.143     dsl       329:                errmsg = MSG_fdremount;
1.138     dsl       330:                if (run_program(0, "/sbin/mount -r -t %s %s /mnt2",
1.143     dsl       331:                                                        fd_type, fd_dev))
1.138     dsl       332:                        continue;
                    333:                mnt2_mounted = 1;
1.143     dsl       334:                errmsg = MSG_fdnotfound;
1.138     dsl       335:
                    336:                /* Display this because it might take a while.... */
                    337:                if (run_program(RUN_DISPLAY,
                    338:                            "sh -c '/bin/cat /mnt2/%s.%s %s %s/%s/%s%s'",
1.143     dsl       339:                            set_name, post, write_mode,
1.138     dsl       340:                            target_prefix(), xfer_dir, set_name, dist_postfix))
                    341:                        /* XXX: a read error will give a corrupt file! */
                    342:                        continue;
                    343:
                    344:                /* We got that file, advance to next fragment */
                    345:                if (post[1] < 'z')
                    346:                        post[1]++;
                    347:                else
                    348:                        post[1] = 'a', post[0]++;
1.143     dsl       349:                write_mode = ">>";
                    350:                errmsg = "";
1.138     dsl       351:                menu = MENU_fdok;
                    352:        }
                    353: }
1.5       phil      354:
1.29      mrg       355: /*
                    356:  * Load files from floppy.  Requires a /mnt2 directory for mounting them.
                    357:  */
                    358: int
1.96      dsl       359: get_via_floppy(void)
1.5       phil      360: {
                    361:
1.142     dsl       362:        process_menu(MENU_floppysource, NULL);
1.7       phil      363:
1.138     dsl       364:        fetch_fn = floppy_fetch;
1.142     dsl       365:
                    366:        /* Set ext_dir for absolute path. */
1.170.2.1  yamt      367:        snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s", target_prefix(), xfer_dir);
                    368:        snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s", target_prefix(), xfer_dir);
1.5       phil      369:
1.138     dsl       370:        return SET_OK;
1.6       phil      371: }
                    372:
1.29      mrg       373: /*
1.164     martin    374:  * Get the volume name of a ISO9660 file system
                    375:  */
                    376: static int
                    377: get_iso9660_volname(int dev, int sess, char *volname)
                    378: {
                    379:        int blkno, error, last;
                    380:        char buf[ISO_BLKSIZE];
                    381:        struct iso_volume_descriptor *vd = NULL;
                    382:        struct iso_primary_descriptor *pd = NULL;
                    383:
                    384:        for (blkno = sess+16; blkno < sess+16+100; blkno++) {
                    385:                error = pread(dev, buf, ISO_BLKSIZE, blkno*ISO_BLKSIZE);
                    386:                if (error == -1)
                    387:                        return -1;
                    388:                vd = (struct iso_volume_descriptor *)&buf;
                    389:                if (memcmp(vd->id, ISO_STANDARD_ID, sizeof(vd->id)) != 0)
                    390:                        return -1;
                    391:                if (isonum_711((const unsigned char *)&vd->type)
                    392:                     == ISO_VD_PRIMARY) {
                    393:                        pd = (struct iso_primary_descriptor*)buf;
                    394:                        strncpy(volname, pd->volume_id, sizeof pd->volume_id);
                    395:                        last = sizeof pd->volume_id-1;
1.169     mbalmer   396:                        while (last >= 0
1.164     martin    397:                            && (volname[last] == ' ' || volname[last] == 0))
                    398:                                last--;
                    399:                        volname[last+1] = 0;
                    400:                        return 0;
                    401:                }
                    402:        }
                    403:        return -1;
                    404: }
                    405:
                    406: /*
                    407:  * Get a list of all available CD media (not drives!), return
                    408:  * the number of entries collected.
                    409:  */
                    410: static int
1.170.2.1  yamt      411: get_available_cds(void)
1.164     martin    412: {
                    413:        char dname[16], volname[80];
                    414:        struct cd_info *info = cds;
                    415:        struct disklabel label;
                    416:        int i, part, dev, error, sess, ready, count = 0;
                    417:
                    418:        for (i = 0; i < MAX_CD_DEVS; i++) {
                    419:                sprintf(dname, "/dev/rcd%d%c", i, 'a'+RAW_PART);
                    420:                dev = open(dname, O_RDONLY, 0);
                    421:                if (dev == -1)
                    422:                        break;
                    423:                ready = 0;
                    424:                error = ioctl(dev, DIOCTUR, &ready);
                    425:                if (error != 0 || ready == 0) {
                    426:                        close(dev);
                    427:                        continue;
                    428:                }
                    429:                error = ioctl(dev, DIOCGDINFO, &label);
                    430:                close(dev);
                    431:                if (error == 0) {
                    432:                        for (part = 0; part < label.d_npartitions; part++) {
                    433:                                if (label.d_partitions[part].p_fstype
1.170.2.2! yamt      434:                                        == FS_UNUSED
        !           435:                                    || label.d_partitions[part].p_size == 0)
1.164     martin    436:                                        continue;
                    437:                                if (label.d_partitions[part].p_fstype
                    438:                                    == FS_ISO9660) {
                    439:                                        sess = label.d_partitions[part]
                    440:                                            .p_cdsession;
                    441:                                        sprintf(dname, "/dev/rcd%d%c", i,
                    442:                                            'a'+part);
                    443:                                        dev = open(dname, O_RDONLY, 0);
                    444:                                        if (dev == -1)
                    445:                                                continue;
                    446:                                        error = get_iso9660_volname(dev, sess,
                    447:                                            volname);
                    448:                                        close(dev);
                    449:                                        if (error) continue;
                    450:                                        sprintf(info->device_name, "cd%d%c",
                    451:                                                i, 'a'+part);
                    452:                                        sprintf(info->menu, "%s (%s)",
                    453:                                                info->device_name,
                    454:                                                volname);
                    455:                                } else {
                    456:                                        /*
                    457:                                         * All install CDs use partition
                    458:                                         * a for the sets.
                    459:                                         */
                    460:                                        if (part > 0)
                    461:                                                continue;
                    462:                                        sprintf(info->device_name, "cd%d%c",
                    463:                                                i, 'a'+part);
                    464:                                        strcpy(info->menu, info->device_name);
                    465:                                }
                    466:                                info++;
                    467:                                if (++count >= MAX_CD_INFOS)
                    468:                                        break;
                    469:                        }
                    470:                }
                    471:        }
                    472:        return count;
                    473: }
                    474:
                    475: static int
                    476: cd_has_sets(void)
                    477: {
                    478:        /* Mount it */
                    479:        if (run_program(RUN_SILENT, "/sbin/mount -rt cd9660 /dev/%s /mnt2",
                    480:            cdrom_dev) != 0)
                    481:                return 0;
                    482:
                    483:        mnt2_mounted = 1;
                    484:
1.170.2.1  yamt      485:        snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s", "/mnt2", set_dir_bin);
                    486:        snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s", "/mnt2", set_dir_src);
                    487:        return dir_exists_p(ext_dir_bin);
1.164     martin    488: }
                    489:
                    490:
                    491: static int
                    492: set_cd_select(menudesc *m, void *arg)
                    493: {
                    494:        *(int *)arg = m->cursel;
                    495:        return 1;
                    496: }
                    497:
                    498: /*
1.170     mbalmer   499:  * Check whether we can remove the boot media.
1.168     martin    500:  * If it is not a local filesystem, return -1.
                    501:  * If we can not decide for sure (can not tell MD content from plain ffs
                    502:  * on hard disk, for example), return 0.
                    503:  * If it is a CD/DVD, return 1.
                    504:  */
                    505: int
                    506: boot_media_still_needed(void)
                    507: {
                    508:        struct statvfs sb;
                    509:
                    510:        if (statvfs("/", &sb) == 0) {
                    511:                if (!(sb.f_flag & ST_LOCAL))
                    512:                        return -1;
                    513:                if (strcmp(sb.f_fstypename, MOUNT_CD9660) == 0
                    514:                           || strcmp(sb.f_fstypename, MOUNT_UDF) == 0)
                    515:                        return 1;
                    516:        }
                    517:
                    518:        return 0;
                    519: }
                    520:
                    521: /*
1.29      mrg       522:  * Get from a CDROM distribution.
                    523:  */
1.6       phil      524: int
1.96      dsl       525: get_via_cdrom(void)
1.6       phil      526: {
1.164     martin    527:        menu_ent cd_menu[MAX_CD_INFOS];
1.153     ad        528:        struct statvfs sb;
1.164     martin    529:        int num_cds, menu_cd, i, selected_cd = 0;
                    530:        bool silent = false;
1.153     ad        531:
                    532:        /* If root is a CD-ROM and we have sets, skip this step. */
1.170.2.1  yamt      533:        if (statvfs(set_dir_bin, &sb) == 0 &&
1.168     martin    534:            (strcmp(sb.f_fstypename, MOUNT_CD9660) == 0
                    535:                    || strcmp(sb.f_fstypename, MOUNT_UDF) == 0)) {
1.170.2.1  yamt      536:                strlcpy(ext_dir_bin, set_dir_bin, sizeof ext_dir_bin);
                    537:                strlcpy(ext_dir_src, set_dir_src, sizeof ext_dir_src);
1.153     ad        538:                return SET_OK;
                    539:        }
1.28      fvdl      540:
1.164     martin    541:        num_cds = get_available_cds();
                    542:        if (num_cds <= 0) {
                    543:                silent = true;
                    544:        } else if (num_cds == 1) {
                    545:                /* single CD found, check for sets on it */
                    546:                strcpy(cdrom_dev, cds[0].device_name);
                    547:                if (cd_has_sets())
                    548:                        return SET_OK;
                    549:        } else {
                    550:                for (i = 0; i< num_cds; i++) {
                    551:                        cd_menu[i].opt_name = cds[i].menu;
                    552:                        cd_menu[i].opt_menu = OPT_NOMENU;
                    553:                        cd_menu[i].opt_flags = OPT_EXIT;
                    554:                        cd_menu[i].opt_action = set_cd_select;
                    555:                }
                    556:                /* create a menu offering available choices */
                    557:                menu_cd = new_menu(MSG_Available_cds,
                    558:                        cd_menu, num_cds, -1, 4, 0, 0,
                    559:                        MC_SCROLL | MC_NOEXITOPT,
                    560:                        NULL, NULL, NULL, NULL, NULL);
                    561:                if (menu_cd == -1)
                    562:                        return SET_RETRY;
                    563:                msg_display(MSG_ask_cd);
                    564:                process_menu(menu_cd, &selected_cd);
                    565:                free_menu(menu_cd);
                    566:                strcpy(cdrom_dev, cds[selected_cd].device_name);
                    567:                if (cd_has_sets())
                    568:                        return SET_OK;
                    569:        }
1.6       phil      570:
1.164     martin    571:        if (silent)
                    572:                msg_display("");
                    573:        else {
                    574:                umount_mnt2();
                    575:                msg_display(MSG_cd_path_not_found);
1.170.2.1  yamt      576:                process_menu(MENU_ok, NULL);
1.164     martin    577:        }
1.22      jonathan  578:
1.164     martin    579:        /* ask for paths on the CD */
                    580:        process_menu(MENU_cdromsource, NULL);
1.22      jonathan  581:
1.164     martin    582:        if (cd_has_sets())
                    583:                return SET_OK;
1.22      jonathan  584:
1.164     martin    585:        return SET_RETRY;
1.7       phil      586: }
                    587:
1.22      jonathan  588:
                    589: /*
                    590:  * Get from a pathname inside an unmounted local filesystem
1.169     mbalmer   591:  * (e.g., where sets were preloaded onto a local DOS partition)
1.22      jonathan  592:  */
1.29      mrg       593: int
1.96      dsl       594: get_via_localfs(void)
1.16      mhitch    595: {
1.22      jonathan  596:
1.16      mhitch    597:        /* Get device, filesystem, and filepath */
1.94      dsl       598:        process_menu (MENU_localfssource, NULL);
1.16      mhitch    599:
                    600:        /* Mount it */
1.115     dsl       601:        if (run_program(0, "/sbin/mount -rt %s /dev/%s /mnt2",
1.138     dsl       602:            localfs_fs, localfs_dev))
                    603:                return SET_RETRY;
1.22      jonathan  604:
1.112     dsl       605:        mnt2_mounted = 1;
1.22      jonathan  606:
1.170.2.1  yamt      607:        snprintf(ext_dir_bin, sizeof ext_dir_bin, "%s/%s/%s",
                    608:                "/mnt2", localfs_dir, set_dir_bin);
                    609:        snprintf(ext_dir_src, sizeof ext_dir_src, "%s/%s/%s",
                    610:                "/mnt2", localfs_dir, set_dir_src);
1.22      jonathan  611:
1.138     dsl       612:        return SET_OK;
1.16      mhitch    613: }
1.7       phil      614:
1.29      mrg       615: /*
                    616:  * Get from an already-mounted pathname.
                    617:  */
1.22      jonathan  618:
1.99      dsl       619: int
                    620: get_via_localdir(void)
1.22      jonathan  621: {
                    622:
1.120     dsl       623:        /* Get filepath */
1.94      dsl       624:        process_menu(MENU_localdirsource, NULL);
1.22      jonathan  625:
1.120     dsl       626:        /*
                    627:         * We have to have an absolute path ('cos pax runs in a
                    628:         * different directory), make it so.
                    629:         */
1.170.2.1  yamt      630:        snprintf(ext_dir_bin, sizeof ext_dir_bin, "/%s/%s", localfs_dir, set_dir_bin);
                    631:        snprintf(ext_dir_src, sizeof ext_dir_src, "/%s/%s", localfs_dir, set_dir_src);
1.120     dsl       632:
1.138     dsl       633:        return SET_OK;
1.22      jonathan  634: }
                    635:
                    636:
1.29      mrg       637: /*
                    638:  * Support for custom distribution fetches / unpacks.
                    639:  */
1.97      dsl       640:
1.138     dsl       641: unsigned int
                    642: set_X11_selected(void)
                    643: {
                    644:        int i;
                    645:
                    646:        for (i = SET_X11_FIRST; ++i < SET_X11_LAST;)
                    647:                if (set_status[i] & SET_SELECTED)
                    648:                        return 1;
                    649:        return 0;
                    650: }
                    651:
                    652: unsigned int
                    653: get_kernel_set(void)
                    654: {
                    655:        int i;
                    656:
                    657:        for (i = SET_KERNEL_FIRST; ++i < SET_KERNEL_LAST;)
                    658:                if (set_status[i] & SET_SELECTED)
                    659:                        return i;
                    660:        return SET_NONE;
                    661: }
                    662:
                    663: void
                    664: set_kernel_set(unsigned int kernel_set)
                    665: {
                    666:        int i;
                    667:
                    668:        /* only one kernel set is allowed */
                    669:        for (i = SET_KERNEL_FIRST; ++i < SET_KERNEL_LAST;)
                    670:                set_status[i] &= ~SET_SELECTED;
                    671:        set_status[kernel_set] |= SET_SELECTED;
                    672: }
1.97      dsl       673:
                    674: static int
1.108     dsl       675: set_toggle(menudesc *menu, void *arg)
1.97      dsl       676: {
1.138     dsl       677:        distinfo **distp = arg;
                    678:        int set = distp[menu->cursel]->set;
                    679:
                    680:        if (set > SET_KERNEL_FIRST && set < SET_KERNEL_LAST &&
                    681:            !(set_status[set] & SET_SELECTED))
                    682:                set_kernel_set(set);
                    683:        else
                    684:                set_status[set] ^= SET_SELECTED;
                    685:        return 0;
                    686: }
1.97      dsl       687:
1.138     dsl       688: static int
                    689: set_all_none(menudesc *menu, void *arg, int set, int clr)
                    690: {
                    691:        distinfo **distp = arg;
                    692:        distinfo *dist = *distp;
                    693:        int nested;
                    694:
                    695:        for (nested = 0; dist->set != SET_GROUP_END || nested--; dist++) {
                    696:                if (dist->set == SET_GROUP) {
                    697:                        nested++;
                    698:                        continue;
                    699:                }
                    700:                set_status[dist->set] = (set_status[dist->set] & ~clr) | set;
                    701:        }
1.97      dsl       702:        return 0;
                    703: }
                    704:
                    705: static int
1.108     dsl       706: set_all(menudesc *menu, void *arg)
1.97      dsl       707: {
1.138     dsl       708:        return set_all_none(menu, arg, SET_SELECTED, 0);
1.97      dsl       709: }
                    710:
                    711: static int
1.108     dsl       712: set_none(menudesc *menu, void *arg)
1.29      mrg       713: {
1.138     dsl       714:        return set_all_none(menu, arg, 0, SET_SELECTED);
                    715: }
                    716:
                    717: static void
                    718: set_label(menudesc *menu, int opt, void *arg)
                    719: {
                    720:        distinfo **distp = arg;
                    721:        distinfo *dist = distp[opt];
                    722:        const char *selected;
                    723:        const char *desc;
                    724:        int nested;
                    725:
                    726:        desc = dist->desc;
1.7       phil      727:
1.138     dsl       728:        if (dist->set != SET_GROUP)
                    729:                selected = set_status[dist->set] & SET_SELECTED ? msg_yes : msg_no;
                    730:        else {
                    731:                /* sub menu - display None/Some/All */
                    732:                nested = 0;
                    733:                selected = "unknown";
                    734:                while ((++dist)->set != SET_GROUP_END || nested--) {
                    735:                        if (dist->set == SET_GROUP) {
                    736:                                nested++;
                    737:                                continue;
                    738:                        }
                    739:                        if (!(set_status[dist->set] & SET_VALID))
                    740:                                continue;
                    741:                        if (set_status[dist->set] & SET_SELECTED) {
                    742:                                if (selected == msg_none) {
                    743:                                        selected = msg_some;
                    744:                                        break;
                    745:                                }
                    746:                                selected = msg_all;
                    747:                        } else {
                    748:                                if (selected == msg_all) {
                    749:                                        selected = msg_some;
                    750:                                        break;
                    751:                                }
                    752:                                selected = msg_none;
                    753:                        }
                    754:                }
                    755:        }
                    756:
                    757:        wprintw(menu->mw, msg_cur_distsets_row, msg_string(desc), selected);
1.7       phil      758: }
                    759:
1.108     dsl       760: static int set_sublist(menudesc *menu, void *arg);
1.97      dsl       761:
1.138     dsl       762: static int
                    763: initialise_set_menu(distinfo *dist, menu_ent *me, distinfo **de, int all_none)
1.7       phil      764: {
1.138     dsl       765:        int set;
                    766:        int sets;
                    767:        int nested;
                    768:
                    769:        for (sets = 0; ; dist++) {
                    770:                set = dist->set;
                    771:                if (set == SET_LAST || set == SET_GROUP_END)
1.97      dsl       772:                        break;
1.138     dsl       773:                if (!(set_status[set] & SET_VALID))
1.97      dsl       774:                        continue;
1.138     dsl       775:                *de = dist;
                    776:                me->opt_menu = OPT_NOMENU;
                    777:                me->opt_flags = 0;
                    778:                me->opt_name = NULL;
                    779:                if (set != SET_GROUP)
                    780:                        me->opt_action = set_toggle;
                    781:                else {
                    782:                        /* Collapse sublist */
                    783:                        nested = 0;
                    784:                        while ((++dist)->set != SET_GROUP_END || nested--) {
                    785:                                if (dist->set == SET_GROUP)
                    786:                                        nested++;
                    787:                        }
                    788:                        me->opt_action = set_sublist;
1.97      dsl       789:                }
1.138     dsl       790:                sets++;
                    791:                de++;
                    792:                me++;
1.97      dsl       793:        }
                    794:
1.138     dsl       795:        if (all_none) {
                    796:                me->opt_menu = OPT_NOMENU;
                    797:                me->opt_flags = 0;
                    798:                me->opt_name = MSG_select_all;
                    799:                me->opt_action = set_all;
                    800:                me++;
                    801:                me->opt_menu = OPT_NOMENU;
                    802:                me->opt_flags = 0;
                    803:                me->opt_name = MSG_select_none;
                    804:                me->opt_action = set_none;
                    805:                sets += 2;
                    806:        }
1.97      dsl       807:
1.138     dsl       808:        return sets;
1.97      dsl       809: }
                    810:
                    811: static int
1.108     dsl       812: set_sublist(menudesc *menu, void *arg)
1.97      dsl       813: {
1.138     dsl       814:        distinfo *de[SET_LAST];
                    815:        menu_ent me[SET_LAST];
                    816:        distinfo **dist = arg;
                    817:        int menu_no;
1.97      dsl       818:        int sets;
                    819:
1.138     dsl       820:        sets = initialise_set_menu(dist[menu->cursel] + 1, me, de, 1);
1.97      dsl       821:
1.138     dsl       822:        menu_no = new_menu(NULL, me, sets, 20, 10, 0, select_menu_width,
1.127     dsl       823:                MC_SUBMENU | MC_SCROLL | MC_DFLTEXIT,
1.138     dsl       824:                NULL, set_label, NULL, NULL,
                    825:                MSG_install_selected_sets);
1.97      dsl       826:
1.138     dsl       827:        process_menu(menu_no, de);
1.97      dsl       828:        free_menu(menu_no);
                    829:
                    830:        return 0;
                    831: }
                    832:
                    833: void
                    834: customise_sets(void)
                    835: {
1.138     dsl       836:        distinfo *de[SET_LAST];
                    837:        menu_ent me[SET_LAST];
1.97      dsl       838:        int sets;
                    839:        int menu_no;
                    840:
1.138     dsl       841:        msg_display(MSG_cur_distsets);
                    842:        msg_table_add(MSG_cur_distsets_header);
1.97      dsl       843:
1.138     dsl       844:        sets = initialise_set_menu(dist_list, me, de, 0);
1.97      dsl       845:
1.138     dsl       846:        menu_no = new_menu(NULL, me, sets, 0, 5, 0, select_menu_width,
                    847:                MC_SCROLL | MC_NOBOX | MC_DFLTEXIT | MC_NOCLEAR,
                    848:                NULL, set_label, NULL, NULL,
                    849:                MSG_install_selected_sets);
1.137     dsl       850:
1.138     dsl       851:        process_menu(menu_no, de);
1.97      dsl       852:        free_menu(menu_no);
1.1       phil      853: }
1.10      jonathan  854:
1.142     dsl       855: /*
                    856:  * Extract_file **REQUIRES** an absolute path in ext_dir.  Any code
                    857:  * that sets up xfer_dir for use by extract_file needs to put in the
1.169     mbalmer   858:  * full path name to the directory.
1.142     dsl       859:  */
                    860:
1.170.2.1  yamt      861: int
1.158     jmcneill  862: extract_file(distinfo *dist, int update)
1.12      phil      863: {
1.142     dsl       864:        char path[STRSIZE];
1.12      phil      865:        char *owd;
1.138     dsl       866:        int   rval;
1.142     dsl       867:
                    868:        /* If we might need to tidy up, ensure directory exists */
                    869:        if (fetch_fn != NULL)
                    870:                make_target_dir(xfer_dir);
                    871:
                    872:        (void)snprintf(path, sizeof path, "%s/%s%s",
1.170.2.1  yamt      873:            ext_dir_for_set(dist->name), dist->name, dist_postfix);
1.169     mbalmer   874:
1.104     dsl       875:        owd = getcwd(NULL, 0);
1.12      phil      876:
1.138     dsl       877:        /* Do we need to fetch the file now? */
                    878:        if (fetch_fn != NULL) {
                    879:                rval = fetch_fn(dist->name);
                    880:                if (rval != SET_OK)
                    881:                        return rval;
                    882:        }
                    883:
1.22      jonathan  884:        /* check tarfile exists */
                    885:        if (!file_exists_p(path)) {
1.154     abs       886:
                    887: #ifdef SUPPORT_8_3_SOURCE_FILESYSTEM
                    888:        /*
1.170.2.1  yamt      889:         * Update path to use dist->name truncated to the first eight
1.169     mbalmer   890:         * characters and check again
1.154     abs       891:         */
1.155     abs       892:        (void)snprintf(path, sizeof path, "%s/%.8s%.4s", /* 4 as includes '.' */
1.170.2.1  yamt      893:            ext_dir_for_set(dist->name), dist->name, dist_postfix);
1.154     abs       894:                if (!file_exists_p(path)) {
                    895: #endif /* SUPPORT_8_3_SOURCE_FILESYSTEM */
                    896:
1.22      jonathan  897:                tarstats.nnotfound++;
1.44      cgd       898:
                    899:                msg_display(MSG_notarfile, path);
1.138     dsl       900:                process_menu(MENU_ok, NULL);
                    901:                return SET_RETRY;
1.22      jonathan  902:        }
1.154     abs       903: #ifdef SUPPORT_8_3_SOURCE_FILESYSTEM
                    904:        }
                    905: #endif /* SUPPORT_8_3_SOURCE_FILESYSTEM */
1.22      jonathan  906:
1.169     mbalmer   907:        tarstats.nfound++;
1.14      jonathan  908:        /* cd to the target root. */
1.161     snj       909:        if (update && (dist->set == SET_ETC || dist->set == SET_X11_ETC)) {
1.119     dsl       910:                make_target_dir("/.sysinst");
                    911:                target_chdir_or_die("/.sysinst");
1.170.2.1  yamt      912:        } else if (dist->set == SET_PKGSRC)
                    913:                target_chdir_or_die("/usr");
                    914:        else
1.119     dsl       915:                target_chdir_or_die("/");
1.12      phil      916:
1.160     snj       917:        /*
                    918:         * /usr/X11R7/lib/X11/xkb/symbols/pc was a directory in 5.0
                    919:         * but is a file in 5.1 and beyond, so on upgrades we need to
                    920:         * delete it before extracting the xbase set.
                    921:         */
                    922:        if (update && dist->set == SET_X11_BASE)
                    923:                run_program(0, "rm -rf usr/X11R7/lib/X11/xkb/symbols/pc");
                    924:
1.132     dsl       925:        /* now extract set files into "./". */
1.169     mbalmer   926:        rval = run_program(RUN_DISPLAY | RUN_PROGRESS,
1.158     jmcneill  927:                        "progress -zf %s tar --chroot -xhepf -", path);
1.22      jonathan  928:
1.112     dsl       929:        chdir(owd);
                    930:        free(owd);
                    931:
1.138     dsl       932:        /* Check rval for errors and give warning. */
                    933:        if (rval != 0) {
1.22      jonathan  934:                tarstats.nerror++;
1.44      cgd       935:                msg_display(MSG_tarerror, path);
1.138     dsl       936:                process_menu(MENU_ok, NULL);
                    937:                return SET_RETRY;
1.22      jonathan  938:        }
1.44      cgd       939:
1.142     dsl       940:        if (fetch_fn != NULL && clean_xfer_dir) {
                    941:                run_program(0, "rm %s", path);
                    942:                /* Plausibly we should unlink an empty xfer_dir as well */
                    943:        }
                    944:
1.138     dsl       945:        set_status[dist->set] |= SET_INSTALLED;
1.112     dsl       946:        tarstats.nsuccess++;
1.138     dsl       947:        return SET_OK;
1.12      phil      948: }
                    949:
1.138     dsl       950: static void
                    951: skip_set(distinfo *dist, int skip_type)
                    952: {
                    953:        int nested;
                    954:        int set;
1.22      jonathan  955:
1.138     dsl       956:        nested = 0;
                    957:        while ((++dist)->set != SET_GROUP_END || nested--) {
                    958:                set = dist->set;
                    959:                if (set == SET_GROUP) {
                    960:                        nested++;
                    961:                        continue;
                    962:                }
                    963:                if (set == SET_LAST)
                    964:                        break;
                    965:                if (set_status[set] == (SET_SELECTED | SET_VALID))
                    966:                        set_status[set] |= SET_SKIPPED;
                    967:                tarstats.nskipped++;
1.22      jonathan  968:        }
1.12      phil      969: }
                    970:
1.37      bouyer    971: /*
1.29      mrg       972:  * Get and unpack the distribution.
1.112     dsl       973:  * Show success_msg if installation completes.
                    974:  * Otherwise show failure_msg and wait for the user to ack it before continuing.
1.11      jonathan  975:  * success_msg and failure_msg must both be 0-adic messages.
                    976:  */
1.45      cgd       977: int
1.120     dsl       978: get_and_unpack_sets(int update, msg setupdone_msg, msg success_msg, msg failure_msg)
1.11      jonathan  979: {
1.138     dsl       980:        distinfo *dist;
                    981:        int status;
                    982:        int set;
1.29      mrg       983:
1.20      jonathan  984:        /* Ensure mountpoint for distribution files exists in current root. */
1.112     dsl       985:        (void)mkdir("/mnt2", S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
1.170.2.1  yamt      986:        if (script)
1.138     dsl       987:                (void)fprintf(script, "mkdir -m 755 /mnt2\n");
                    988:
                    989:        /* reset failure/success counters */
                    990:        memset(&tarstats, 0, sizeof(tarstats));
1.20      jonathan  991:
1.26      phil      992:        /* Find out which files to "get" if we get files. */
                    993:
1.140     dsl       994:        /* Accurately count selected sets */
                    995:        for (dist = dist_list; (set = dist->set) != SET_LAST; dist++) {
                    996:                if ((set_status[set] & (SET_VALID | SET_SELECTED))
                    997:                    == (SET_VALID | SET_SELECTED))
                    998:                        tarstats.nselected++;
                    999:        }
                   1000:
1.138     dsl      1001:        status = SET_RETRY;
1.140     dsl      1002:        for (dist = dist_list; ; dist++) {
1.138     dsl      1003:                set = dist->set;
                   1004:                if (set == SET_LAST)
                   1005:                        break;
                   1006:                if (dist->name == NULL)
                   1007:                        continue;
                   1008:                if (set_status[set] != (SET_VALID | SET_SELECTED))
                   1009:                        continue;
1.26      phil     1010:
1.138     dsl      1011:                if (status != SET_OK) {
                   1012:                        /* This might force a redraw.... */
                   1013:                        clearok(curscr, 1);
                   1014:                        touchwin(stdscr);
                   1015:                        wrefresh(stdscr);
                   1016:                        /* Sort out the location of the set files */
                   1017:                        do {
1.140     dsl      1018:                                umount_mnt2();
                   1019:                                msg_display(MSG_distmedium, tarstats.nselected,
                   1020:                                    tarstats.nsuccess + tarstats.nskipped,
                   1021:                                    dist->name);
1.138     dsl      1022:                                fetch_fn = NULL;
                   1023:                                process_menu(MENU_distmedium, &status);
                   1024:                        } while (status == SET_RETRY);
                   1025:
                   1026:                        if (status == SET_SKIP) {
                   1027:                                set_status[set] |= SET_SKIPPED;
                   1028:                                tarstats.nskipped++;
                   1029:                                continue;
                   1030:                        }
                   1031:                        if (status == SET_SKIP_GROUP) {
                   1032:                                skip_set(dist, status);
                   1033:                                continue;
                   1034:                        }
                   1035:                        if (status != SET_OK) {
                   1036:                                msg_display(failure_msg);
                   1037:                                process_menu(MENU_ok, NULL);
                   1038:                                return 1;
                   1039:                        }
                   1040:                }
1.20      jonathan 1041:
1.142     dsl      1042:                /* Try to extract this set */
1.158     jmcneill 1043:                status = extract_file(dist, update);
1.140     dsl      1044:                if (status == SET_RETRY)
                   1045:                        dist--;
1.138     dsl      1046:        }
                   1047:
                   1048:        if (tarstats.nerror == 0 && tarstats.nsuccess == tarstats.nselected) {
                   1049:                msg_display(MSG_endtarok);
                   1050:                /* Give user a chance to see the success message */
                   1051:                sleep(1);
                   1052:        } else {
                   1053:                /* We encountered errors. Let the user know. */
                   1054:                msg_display(MSG_endtar,
                   1055:                    tarstats.nselected, tarstats.nnotfound, tarstats.nskipped,
                   1056:                    tarstats.nfound, tarstats.nsuccess, tarstats.nerror);
1.112     dsl      1057:                process_menu(MENU_ok, NULL);
1.138     dsl      1058:                msg_clear();
1.112     dsl      1059:        }
1.11      jonathan 1060:
1.161     snj      1061:        /*
                   1062:         * postinstall needs to be run after extracting all sets, because
                   1063:         * otherwise /var/db/obsolete will only have current information
                   1064:         * from the base, comp, and etc sets.
                   1065:         */
                   1066:        if (update && (set_status[SET_ETC] & SET_INSTALLED)) {
                   1067:                int oldsendmail;
                   1068:                oldsendmail = run_program(RUN_DISPLAY | RUN_CHROOT |
                   1069:                                          RUN_ERROR_OK | RUN_PROGRESS,
                   1070:                                          "/usr/sbin/postinstall -s /.sysinst -d / check mailerconf");
                   1071:                if (oldsendmail == 1) {
                   1072:                        msg_display(MSG_oldsendmail);
                   1073:                        process_menu(MENU_yesno, NULL);
                   1074:                        if (yesno) {
                   1075:                                run_program(RUN_DISPLAY | RUN_CHROOT,
                   1076:                                            "/usr/sbin/postinstall -s /.sysinst -d / fix mailerconf");
                   1077:                        }
                   1078:                }
                   1079:                run_program(RUN_DISPLAY | RUN_CHROOT,
                   1080:                        "/usr/sbin/postinstall -s /.sysinst -d / fix");
                   1081:        }
                   1082:
1.112     dsl      1083:        /* Configure the system */
1.138     dsl      1084:        if (set_status[SET_BASE] & SET_INSTALLED)
1.112     dsl      1085:                run_makedev();
1.11      jonathan 1086:
1.170.2.1  yamt     1087:        if (!update) {
                   1088:                /* Save keybard type */
                   1089:                save_kb_encoding();
1.122     dsl      1090:
1.170.2.1  yamt     1091:                /* Other configuration. */
                   1092:                mnt_net_config();
                   1093:        }
1.138     dsl      1094:
1.112     dsl      1095:        /* Mounted dist dir? */
                   1096:        umount_mnt2();
1.22      jonathan 1097:
1.112     dsl      1098:        /* Install/Upgrade complete ... reboot or exit to script */
                   1099:        msg_display(success_msg);
1.94      dsl      1100:        process_menu(MENU_ok, NULL);
1.112     dsl      1101:        return 0;
1.14      jonathan 1102: }
1.22      jonathan 1103:
1.112     dsl      1104: void
                   1105: umount_mnt2(void)
                   1106: {
                   1107:        if (!mnt2_mounted)
                   1108:                return;
1.115     dsl      1109:        run_program(RUN_SILENT, "/sbin/umount /mnt2");
1.112     dsl      1110:        mnt2_mounted = 0;
                   1111: }
1.22      jonathan 1112:
1.14      jonathan 1113:
                   1114: /*
                   1115:  * Do a quick sanity check that  the target can reboot.
                   1116:  * return 1 if everything OK, 0 if there is a problem.
                   1117:  * Uses a table of files we expect to find after a base install/upgrade.
                   1118:  */
                   1119:
                   1120: /* test flag and pathname to check for after unpacking. */
1.54      fvdl     1121: struct check_table { unsigned int mode; const char *path;} checks[] = {
                   1122:   { S_IFREG, "/netbsd" },
                   1123:   { S_IFDIR, "/etc" },
                   1124:   { S_IFREG, "/etc/fstab" },
                   1125:   { S_IFREG, "/sbin/init" },
                   1126:   { S_IFREG, "/bin/sh" },
                   1127:   { S_IFREG, "/etc/rc" },
                   1128:   { S_IFREG, "/etc/rc.subr" },
                   1129:   { S_IFREG, "/etc/rc.conf" },
                   1130:   { S_IFDIR, "/dev" },
                   1131:   { S_IFCHR, "/dev/console" },
1.14      jonathan 1132: /* XXX check for rootdev in target /dev? */
1.54      fvdl     1133:   { S_IFREG, "/etc/fstab" },
                   1134:   { S_IFREG, "/sbin/fsck" },
                   1135:   { S_IFREG, "/sbin/fsck_ffs" },
                   1136:   { S_IFREG, "/sbin/mount" },
                   1137:   { S_IFREG, "/sbin/mount_ffs" },
                   1138:   { S_IFREG, "/sbin/mount_nfs" },
1.20      jonathan 1139: #if defined(DEBUG) || defined(DEBUG_CHECK)
1.54      fvdl     1140:   { S_IFREG, "/foo/bar" },             /* bad entry to exercise warning */
1.14      jonathan 1141: #endif
                   1142:   { 0, 0 }
1.169     mbalmer  1143:
1.14      jonathan 1144: };
                   1145:
                   1146: /*
                   1147:  * Check target for a single file.
                   1148:  */
1.29      mrg      1149: static int
1.96      dsl      1150: check_for(unsigned int mode, const char *pathname)
1.14      jonathan 1151: {
1.169     mbalmer  1152:        int found;
1.14      jonathan 1153:
1.54      fvdl     1154:        found = (target_test(mode, pathname) == 0);
1.169     mbalmer  1155:        if (found == 0)
1.14      jonathan 1156:                msg_display(MSG_rootmissing, pathname);
1.18      jonathan 1157:        return found;
1.14      jonathan 1158: }
                   1159:
1.25      jonathan 1160: /*
                   1161:  * Check that all the files in check_table are present in the
                   1162:  * target root. Warn if not found.
                   1163:  */
1.14      jonathan 1164: int
1.96      dsl      1165: sanity_check(void)
1.14      jonathan 1166: {
                   1167:        int target_ok = 1;
                   1168:        struct check_table *p;
                   1169:
                   1170:        for (p = checks; p->path; p++) {
1.54      fvdl     1171:                target_ok = target_ok && check_for(p->mode, p->path);
1.14      jonathan 1172:        }
                   1173:        if (target_ok)
1.169     mbalmer  1174:                return 0;
1.14      jonathan 1175:
                   1176:        /* Uh, oh. Something's missing. */
                   1177:        msg_display(MSG_badroot);
1.94      dsl      1178:        process_menu(MENU_ok, NULL);
1.14      jonathan 1179:        return 1;
1.11      jonathan 1180: }
1.32      garbled  1181:
1.52      hubertf  1182: /*
                   1183:  * Some globals to pass things back from callbacks
                   1184:  */
                   1185: static char zoneinfo_dir[STRSIZE];
1.101     dsl      1186: static int zonerootlen;
                   1187: static char *tz_selected;      /* timezonename (relative to share/zoneinfo */
1.170.2.1  yamt     1188: const char *tz_default;                /* UTC, or whatever /etc/localtime points to */
1.52      hubertf  1189: static char tz_env[STRSIZE];
1.101     dsl      1190: static int save_cursel, save_topline;
1.52      hubertf  1191:
                   1192: /*
                   1193:  * Callback from timezone menu
                   1194:  */
                   1195: static int
1.108     dsl      1196: set_tz_select(menudesc *m, void *arg)
1.52      hubertf  1197: {
                   1198:        time_t t;
1.101     dsl      1199:        char *new;
1.52      hubertf  1200:
1.110     dsl      1201:        if (m && strcmp(tz_selected, m->opts[m->cursel].opt_name) != 0) {
1.126     dsl      1202:                /* Change the displayed timezone */
1.101     dsl      1203:                new = strdup(m->opts[m->cursel].opt_name);
                   1204:                if (new == NULL)
                   1205:                        return 0;
                   1206:                free(tz_selected);
                   1207:                tz_selected = new;
1.110     dsl      1208:                snprintf(tz_env, sizeof tz_env, "%.*s%s",
                   1209:                         zonerootlen, zoneinfo_dir, tz_selected);
                   1210:                setenv("TZ", tz_env, 1);
1.101     dsl      1211:        }
1.126     dsl      1212:        if (m)
                   1213:                /* Warp curser to 'Exit' line on menu */
                   1214:                m->cursel = -1;
                   1215:
                   1216:        /* Update displayed time */
1.52      hubertf  1217:        t = time(NULL);
1.169     mbalmer  1218:        msg_display(MSG_choose_timezone,
1.52      hubertf  1219:                    tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone);
                   1220:        return 0;
                   1221: }
                   1222:
1.101     dsl      1223: static int
1.108     dsl      1224: set_tz_back(menudesc *m, void *arg)
1.101     dsl      1225: {
                   1226:
                   1227:        zoneinfo_dir[zonerootlen] = 0;
                   1228:        m->cursel = save_cursel;
                   1229:        m->topline = save_topline;
                   1230:        return 0;
                   1231: }
                   1232:
                   1233: static int
1.108     dsl      1234: set_tz_dir(menudesc *m, void *arg)
1.101     dsl      1235: {
                   1236:
                   1237:        strlcpy(zoneinfo_dir + zonerootlen, m->opts[m->cursel].opt_name,
                   1238:                sizeof zoneinfo_dir - zonerootlen);
                   1239:        save_cursel = m->cursel;
                   1240:        save_topline = m->topline;
                   1241:        m->cursel = 0;
                   1242:        m->topline = 0;
                   1243:        return 0;
                   1244: }
                   1245:
1.52      hubertf  1246: /*
                   1247:  * Alarm-handler to update example-display
                   1248:  */
                   1249: static void
1.78      christos 1250: /*ARGSUSED*/
1.52      hubertf  1251: timezone_sig(int sig)
                   1252: {
1.96      dsl      1253:
1.108     dsl      1254:        set_tz_select(NULL, NULL);
1.74      grant    1255:        alarm(60);
1.52      hubertf  1256: }
                   1257:
1.101     dsl      1258: static int
                   1259: tz_sort(const void *a, const void *b)
                   1260: {
1.107     dsl      1261:        return strcmp(((const menu_ent *)a)->opt_name, ((const menu_ent *)b)->opt_name);
1.101     dsl      1262: }
                   1263:
                   1264: static void
                   1265: tzm_set_names(menudesc *m, void *arg)
                   1266: {
                   1267:        DIR *dir;
                   1268:        struct dirent *dp;
                   1269:        static int nfiles;
                   1270:        static int maxfiles = 32;
                   1271:        static menu_ent *tz_menu;
                   1272:        static char **tz_names;
                   1273:        void *p;
                   1274:        int maxfname;
                   1275:        char *fp;
                   1276:        struct stat sb;
                   1277:
                   1278:        if (tz_menu == NULL)
                   1279:                tz_menu = malloc(maxfiles * sizeof *tz_menu);
                   1280:        if (tz_names == NULL)
                   1281:                tz_names = malloc(maxfiles * sizeof *tz_names);
                   1282:        if (tz_menu == NULL || tz_names == NULL)
                   1283:                return; /* error - skip timezone setting */
                   1284:        while (nfiles > 0)
                   1285:                free(tz_names[--nfiles]);
1.169     mbalmer  1286:
1.101     dsl      1287:        dir = opendir(zoneinfo_dir);
                   1288:        fp = strchr(zoneinfo_dir, 0);
                   1289:        if (fp != zoneinfo_dir + zonerootlen) {
                   1290:                tz_names[0] = 0;
1.102     dsl      1291:                tz_menu[0].opt_name = msg_string(MSG_tz_back);
1.101     dsl      1292:                tz_menu[0].opt_menu = OPT_NOMENU;
                   1293:                tz_menu[0].opt_flags = 0;
                   1294:                tz_menu[0].opt_action = set_tz_back;
                   1295:                nfiles = 1;
                   1296:        }
                   1297:        maxfname = zoneinfo_dir + sizeof zoneinfo_dir - fp - 1;
                   1298:        if (dir != NULL) {
                   1299:                while ((dp = readdir(dir)) != NULL) {
                   1300:                        if (dp->d_namlen > maxfname || dp->d_name[0] == '.')
                   1301:                                continue;
                   1302:                        strlcpy(fp, dp->d_name, maxfname);
                   1303:                        if (stat(zoneinfo_dir, &sb) == -1)
                   1304:                                continue;
                   1305:                        if (nfiles >= maxfiles) {
                   1306:                                p = realloc(tz_menu, 2 * maxfiles * sizeof *tz_menu);
                   1307:                                if (p == NULL)
                   1308:                                        break;
                   1309:                                tz_menu = p;
                   1310:                                p = realloc(tz_names, 2 * maxfiles * sizeof *tz_names);
                   1311:                                if (p == NULL)
                   1312:                                        break;
                   1313:                                tz_names = p;
                   1314:                                maxfiles *= 2;
                   1315:                        }
                   1316:                        if (S_ISREG(sb.st_mode))
                   1317:                                tz_menu[nfiles].opt_action = set_tz_select;
                   1318:                        else if (S_ISDIR(sb.st_mode)) {
                   1319:                                tz_menu[nfiles].opt_action = set_tz_dir;
1.111     itojun   1320:                                strlcat(fp, "/",
                   1321:                                    sizeof(zoneinfo_dir) - (fp - zoneinfo_dir));
1.101     dsl      1322:                        } else
                   1323:                                continue;
                   1324:                        tz_names[nfiles] = strdup(zoneinfo_dir + zonerootlen);
                   1325:                        tz_menu[nfiles].opt_name = tz_names[nfiles];
                   1326:                        tz_menu[nfiles].opt_menu = OPT_NOMENU;
                   1327:                        tz_menu[nfiles].opt_flags = 0;
                   1328:                        nfiles++;
                   1329:                }
                   1330:                closedir(dir);
                   1331:        }
                   1332:        *fp = 0;
                   1333:
                   1334:        m->opts = tz_menu;
                   1335:        m->numopts = nfiles;
                   1336:        qsort(tz_menu, nfiles, sizeof *tz_menu, tz_sort);
                   1337: }
                   1338:
1.170.2.1  yamt     1339: void
                   1340: get_tz_default(void)
1.52      hubertf  1341: {
                   1342:        char localtime_link[STRSIZE];
1.170.2.1  yamt     1343:        static char localtime_target[STRSIZE];
1.52      hubertf  1344:        int rc;
1.169     mbalmer  1345:
1.92      dsl      1346:        strlcpy(localtime_link, target_expand("/etc/localtime"),
                   1347:            sizeof localtime_link);
1.52      hubertf  1348:
                   1349:        /* Add sanity check that /mnt/usr/share/zoneinfo contains
1.101     dsl      1350:         * something useful
                   1351:         */
1.52      hubertf  1352:
                   1353:        rc = readlink(localtime_link, localtime_target,
1.75      provos   1354:                      sizeof(localtime_target) - 1);
1.52      hubertf  1355:        if (rc < 0) {
1.53      hubertf  1356:                /* error, default to UTC */
                   1357:                tz_default = "UTC";
                   1358:        } else {
                   1359:                localtime_target[rc] = '\0';
1.92      dsl      1360:                tz_default = strchr(strstr(localtime_target, "zoneinfo"), '/') + 1;
1.52      hubertf  1361:        }
1.170.2.1  yamt     1362: }
                   1363:
                   1364: /*
                   1365:  * Choose from the files in usr/share/zoneinfo and set etc/localtime
                   1366:  */
                   1367: int
                   1368: set_timezone(void)
                   1369: {
                   1370:        char localtime_link[STRSIZE];
                   1371:        char localtime_target[STRSIZE];
                   1372:        time_t t;
                   1373:        int menu_no;
                   1374:
                   1375:        strlcpy(zoneinfo_dir, target_expand("/usr/share/zoneinfo/"),
                   1376:            sizeof zoneinfo_dir - 1);
                   1377:        zonerootlen = strlen(zoneinfo_dir);
                   1378:
                   1379:        get_tz_default();
1.52      hubertf  1380:
1.101     dsl      1381:        tz_selected = strdup(tz_default);
                   1382:        snprintf(tz_env, sizeof(tz_env), "%s%s", zoneinfo_dir, tz_selected);
1.52      hubertf  1383:        setenv("TZ", tz_env, 1);
                   1384:        t = time(NULL);
1.169     mbalmer  1385:        msg_display(MSG_choose_timezone,
1.52      hubertf  1386:                    tz_default, tz_selected, ctime(&t), localtime(&t)->tm_zone);
                   1387:
1.101     dsl      1388:        signal(SIGALRM, timezone_sig);
                   1389:        alarm(60);
1.169     mbalmer  1390:
1.101     dsl      1391:        menu_no = new_menu(NULL, NULL, 14, 23, 9,
1.112     dsl      1392:                           12, 32, MC_ALWAYS_SCROLL | MC_NOSHORTCUT,
1.101     dsl      1393:                           tzm_set_names, NULL, NULL,
1.95      dsl      1394:                           "\nPlease consult the install documents.", NULL);
1.92      dsl      1395:        if (menu_no < 0)
                   1396:                goto done;      /* error - skip timezone setting */
1.169     mbalmer  1397:
1.94      dsl      1398:        process_menu(menu_no, NULL);
1.52      hubertf  1399:
                   1400:        free_menu(menu_no);
                   1401:
                   1402:        signal(SIGALRM, SIG_IGN);
                   1403:
                   1404:        snprintf(localtime_target, sizeof(localtime_target),
                   1405:                 "/usr/share/zoneinfo/%s", tz_selected);
1.170.2.1  yamt     1406:        strlcpy(localtime_link, target_expand("/etc/localtime"),
                   1407:            sizeof localtime_link);
1.52      hubertf  1408:        unlink(localtime_link);
                   1409:        symlink(localtime_target, localtime_link);
1.169     mbalmer  1410:
1.92      dsl      1411: done:
1.52      hubertf  1412:        return 1;
1.66      ad       1413: }
                   1414:
1.64      mrg      1415: void
                   1416: scripting_vfprintf(FILE *f, const char *fmt, va_list ap)
                   1417: {
1.96      dsl      1418:
1.64      mrg      1419:        if (f)
                   1420:                (void)vfprintf(f, fmt, ap);
1.170.2.1  yamt     1421:        if (script)
1.64      mrg      1422:                (void)vfprintf(script, fmt, ap);
                   1423: }
                   1424:
                   1425: void
                   1426: scripting_fprintf(FILE *f, const char *fmt, ...)
                   1427: {
                   1428:        va_list ap;
                   1429:
                   1430:        va_start(ap, fmt);
                   1431:        scripting_vfprintf(f, fmt, ap);
                   1432:        va_end(ap);
                   1433: }
                   1434:
                   1435: void
                   1436: add_rc_conf(const char *fmt, ...)
                   1437: {
                   1438:        FILE *f;
                   1439:        va_list ap;
                   1440:
                   1441:        va_start(ap, fmt);
                   1442:        f = target_fopen("/etc/rc.conf", "a");
                   1443:        if (f != 0) {
                   1444:                scripting_fprintf(NULL, "cat <<EOF >>%s/etc/rc.conf\n",
                   1445:                    target_prefix());
                   1446:                scripting_vfprintf(f, fmt, ap);
                   1447:                fclose(f);
                   1448:                scripting_fprintf(NULL, "EOF\n");
                   1449:        }
                   1450:        va_end(ap);
1.112     dsl      1451: }
                   1452:
1.170.2.1  yamt     1453: int
                   1454: del_rc_conf(const char *value)
                   1455: {
                   1456:        FILE *fp, *nfp;
                   1457:        char buf[4096]; /* Ridiculously high, but should be enough in any way */
                   1458:        char *rcconf, *tempname, *bakname;
                   1459:        char *cp;
                   1460:        int done = 0;
                   1461:        int fd;
                   1462:        int retval = 0;
                   1463:
                   1464:        /* The paths might seem strange, but using /tmp would require copy instead
                   1465:         * of rename operations. */
                   1466:        if (asprintf(&rcconf, "%s", target_expand("/etc/rc.conf")) < 0
                   1467:                        || asprintf(&tempname, "%s", target_expand("/etc/rc.conf.tmp.XXXXXX")) < 0
                   1468:                        || asprintf(&bakname, "%s", target_expand("/etc/rc.conf.bak.XXXXXX")) < 0) {
                   1469:                if (rcconf)
                   1470:                        free(rcconf);
                   1471:                if (tempname)
                   1472:                        free(tempname);
                   1473:                msg_display(MSG_rcconf_delete_failed, value);
                   1474:                process_menu(MENU_ok, NULL);
                   1475:                return -1;
                   1476:        }
                   1477:
                   1478:        if ((fd = mkstemp(bakname)) < 0) {
                   1479:                msg_display(MSG_rcconf_delete_failed, value);
                   1480:                process_menu(MENU_ok, NULL);
                   1481:                return -1;
                   1482:        }
                   1483:        close(fd);
                   1484:
                   1485:        if (!(fp = fopen(rcconf, "r+")) || (fd = mkstemp(tempname)) < 0) {
                   1486:                if (fp)
                   1487:                        fclose(fp);
                   1488:                msg_display(MSG_rcconf_delete_failed, value);
                   1489:                process_menu(MENU_ok, NULL);
                   1490:                return -1;
                   1491:        }
                   1492:
                   1493:        nfp = fdopen(fd, "w");
                   1494:        if (!nfp) {
                   1495:                fclose(fp);
                   1496:                close(fd);
                   1497:                msg_display(MSG_rcconf_delete_failed, value);
                   1498:                process_menu(MENU_ok, NULL);
                   1499:                return -1;
                   1500:        }
                   1501:
                   1502:        while (fgets(buf, sizeof buf, fp) != NULL) {
                   1503:
                   1504:                cp = buf + strspn(buf, " \t"); /* Skip initial spaces */
                   1505:                if (strncmp(cp, value, strlen(value)) == 0) {
                   1506:                        cp += strlen(value);
                   1507:                        if (*cp != '=')
                   1508:                                scripting_fprintf(nfp, "%s", buf);
                   1509:                        else
                   1510:                                done = 1;
                   1511:                } else {
                   1512:                        scripting_fprintf(nfp, "%s", buf);
                   1513:                }
                   1514:        }
                   1515:        fclose(fp);
                   1516:        fclose(nfp);
                   1517:
                   1518:        if (done) {
                   1519:                if (rename(rcconf, bakname)) {
                   1520:                        msg_display(MSG_rcconf_backup_failed);
                   1521:                        process_menu(MENU_noyes, NULL);
                   1522:                        if (!yesno) {
                   1523:                                retval = -1;
                   1524:                                goto done;
                   1525:                        }
                   1526:                }
                   1527:
                   1528:                if (rename(tempname, rcconf)) {
                   1529:                        if (rename(bakname, rcconf)) {
                   1530:                                msg_display(MSG_rcconf_restore_failed);
                   1531:                                process_menu(MENU_ok, NULL);
                   1532:                        } else {
                   1533:                                msg_display(MSG_rcconf_delete_failed, value);
                   1534:                                process_menu(MENU_ok, NULL);
                   1535:                        }
                   1536:                } else {
                   1537:                        (void)unlink(bakname);
                   1538:                }
                   1539:        }
                   1540:
                   1541: done:
                   1542:        (void)unlink(tempname);
                   1543:        free(rcconf);
                   1544:        free(tempname);
                   1545:        free(bakname);
                   1546:        return retval;
                   1547: }
                   1548:
1.112     dsl      1549: void
1.152     christos 1550: add_sysctl_conf(const char *fmt, ...)
                   1551: {
                   1552:        FILE *f;
                   1553:        va_list ap;
                   1554:
                   1555:        va_start(ap, fmt);
                   1556:        f = target_fopen("/etc/sysctl.conf", "a");
                   1557:        if (f != 0) {
                   1558:                scripting_fprintf(NULL, "cat <<EOF >>%s/etc/sysctl.conf\n",
                   1559:                    target_prefix());
                   1560:                scripting_vfprintf(f, fmt, ap);
                   1561:                fclose(f);
                   1562:                scripting_fprintf(NULL, "EOF\n");
                   1563:        }
                   1564:        va_end(ap);
                   1565: }
                   1566:
                   1567: void
1.112     dsl      1568: enable_rc_conf(void)
                   1569: {
1.163     jmmv     1570:
                   1571:        replace("/etc/rc.conf", "s/^rc_configured=NO/rc_configured=YES/");
1.64      mrg      1572: }
                   1573:
                   1574: int
1.96      dsl      1575: check_lfs_progs(void)
1.64      mrg      1576: {
                   1577:
1.165     martin   1578: #ifndef NO_LFS
1.141     dsl      1579:        return (access("/sbin/fsck_lfs", X_OK) == 0 &&
1.64      mrg      1580:                access("/sbin/mount_lfs", X_OK) == 0 &&
                   1581:                access("/sbin/newfs_lfs", X_OK) == 0);
1.165     martin   1582: #else
                   1583:        return 0;
                   1584: #endif
1.32      garbled  1585: }
1.170.2.1  yamt     1586:
                   1587: int
                   1588: set_is_source(const char *set_name) {
                   1589:        int len = strlen(set_name);
                   1590:        return len >= 3 && memcmp(set_name + len - 3, "src", 3) == 0;
                   1591: }
                   1592:
                   1593: const char *
                   1594: set_dir_for_set(const char *set_name) {
                   1595:        if (strcmp(set_name, "pkgsrc") == 0)
                   1596:                return pkgsrc_dir;
                   1597:        return set_is_source(set_name) ? set_dir_src : set_dir_bin;
                   1598: }
                   1599:
                   1600: const char *
                   1601: ext_dir_for_set(const char *set_name) {
                   1602:        if (strcmp(set_name, "pkgsrc") == 0)
                   1603:                return ext_dir_pkgsrc;
                   1604:        return set_is_source(set_name) ? ext_dir_src : ext_dir_bin;
                   1605: }
                   1606:

CVSweb <webmaster@jp.NetBSD.org>