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

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

CVSweb <webmaster@jp.NetBSD.org>