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

Annotation of src/distrib/utils/sysinst/main.c, Revision 1.45

1.45    ! christos    1: /*     $NetBSD: main.c,v 1.44 2004/06/05 21:18:59 dsl Exp $    */
1.1       phil        2:
                      3: /*
                      4:  * Copyright 1997 Piermont Information Systems Inc.
                      5:  * All rights reserved.
                      6:  *
                      7:  * Written by Philip A. Nelson for Piermont Information Systems Inc.
                      8:  *
                      9:  * Redistribution and use in source and binary forms, with or without
                     10:  * modification, are permitted provided that the following conditions
                     11:  * are met:
                     12:  * 1. Redistributions of source code must retain the above copyright
                     13:  *    notice, this list of conditions and the following disclaimer.
                     14:  * 2. Redistributions in binary form must reproduce the above copyright
                     15:  *    notice, this list of conditions and the following disclaimer in the
                     16:  *    documentation and/or other materials provided with the distribution.
                     17:  * 3. All advertising materials mentioning features or use of this software
                     18:  *    must display the following acknowledgement:
1.17      cgd        19:  *      This product includes software developed for the NetBSD Project by
1.1       phil       20:  *      Piermont Information Systems Inc.
                     21:  * 4. The name of Piermont Information Systems Inc. may not be used to endorse
                     22:  *    or promote products derived from this software without specific prior
                     23:  *    written permission.
                     24:  *
                     25:  * THIS SOFTWARE IS PROVIDED BY PIERMONT INFORMATION SYSTEMS INC. ``AS IS''
                     26:  * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     27:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     28:  * ARE DISCLAIMED. IN NO EVENT SHALL PIERMONT INFORMATION SYSTEMS INC. BE
                     29:  * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     30:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     31:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     32:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     33:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     34:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
                     35:  * THE POSSIBILITY OF SUCH DAMAGE.
                     36:  *
                     37:  */
                     38:
                     39: /* main sysinst program. */
                     40:
1.10      phil       41: #include <sys/types.h>
                     42: #include <sys/stat.h>
                     43: #include <sys/uio.h>
1.1       phil       44: #include <stdio.h>
1.5       simonb     45: #include <signal.h>
1.1       phil       46: #include <curses.h>
1.3       phil       47: #include <unistd.h>
1.10      phil       48: #include <fcntl.h>
1.36      dsl        49: #include <dirent.h>
1.1       phil       50:
                     51: #include "defs.h"
                     52: #include "md.h"
                     53: #include "msg_defs.h"
                     54: #include "menu_defs.h"
1.10      phil       55: #include "txtwalk.h"
1.1       phil       56:
1.34      dsl        57: int main(int, char **);
1.45    ! christos   58: static void init(void);
1.36      dsl        59: static void select_language(void);
1.34      dsl        60: static void usage(void);
                     61: static void miscsighandler(int);
                     62: static void ttysighandler(int);
                     63: static void cleanup(void);
                     64: static void process_f_flag(char *);
1.8       simonb     65:
                     66: static int exit_cleanly = 0;   /* Did we finish nicely? */
1.11      garbled    67: int logging;                   /* are we logging everything? */
                     68: int scripting;                 /* are we building a script? */
1.29      fvdl       69: FILE *logfp;                   /* log file */
1.11      garbled    70: FILE *script;                  /* script file */
1.1       phil       71:
1.12      fvdl       72: #ifdef DEBUG
1.34      dsl        73: extern int log_flip(void);
1.12      fvdl       74: #endif
                     75:
1.45    ! christos   76: static void
        !            77: init(void)
        !            78: {
        !            79:        (void)strlcpy(rel, REL, SSTRSIZE);
        !            80:        (void)strlcpy(machine, MACH, SSTRSIZE);
        !            81:        sizemult = 1;
        !            82:        ramsize = 0;
        !            83:        rammb = 0;
        !            84:        (void)strlcpy(diskdev, "", SSTRSIZE);
        !            85:        disktype = "unknown";
        !            86:        tmp_mfs_size = 0;
        !            87:        (void)strlcpy(bsddiskname, "mydisk", DISKNAME_SIZE);
        !            88:        doessf = "";
        !            89:        (void)strlcpy(dist_dir, "/usr/INSTALL", STRSIZE);
        !            90:        clean_dist_dir = 0;
        !            91:        (void)strlcpy(ext_dir, "", STRSIZE);
        !            92:        (void)strlcpy(set_dir, "/" MACH "/binary/sets", STRSIZE);
        !            93:        (void)strlcpy(ftp_host, SYSINST_FTP_HOST, STRSIZE);
        !            94:        (void)strlcpy(ftp_dir, SYSINST_FTP_DIR, STRSIZE);
        !            95:        (void)strlcpy(ftp_user, "ftp", SSTRSIZE);
        !            96:        (void)strlcpy(ftp_pass, "", STRSIZE);
        !            97:        (void)strlcpy(ftp_proxy, "", STRSIZE);
        !            98:        (void)strlcpy(nfs_host, "", STRSIZE);
        !            99:        (void)strlcpy(nfs_dir, "/bsd/release", STRSIZE);
        !           100:        (void)strlcpy(cdrom_dev, "cd0a", SSTRSIZE);
        !           101:        (void)strlcpy(localfs_dev, "sd0a", SSTRSIZE);
        !           102:        (void)strlcpy(localfs_fs, "ffs", SSTRSIZE);
        !           103:        (void)strlcpy(localfs_dir, "release", STRSIZE);
        !           104:        (void)strlcpy(targetroot_mnt, "/targetroot", SSTRSIZE);
        !           105:        (void)strlcpy(distfs_mnt, "/mnt2", SSTRSIZE);
        !           106:        mnt2_mounted = 0;
        !           107:        (void)strlcpy(dist_postfix, ".tgz", SSTRSIZE);
        !           108: }
        !           109:
1.9       mrg       110: int
1.34      dsl       111: main(int argc, char **argv)
1.1       phil      112: {
                    113:        WINDOW *win;
1.3       phil      114:        int ch;
1.2       phil      115:
1.11      garbled   116:        logging = 0; /* shut them off unless turned on by the user */
1.45    ! christos  117:        init();
1.12      fvdl      118: #ifdef DEBUG
                    119:        log_flip();
                    120: #endif
1.11      garbled   121:        scripting = 0;
                    122:
1.2       phil      123:        /* Check for TERM ... */
                    124:        if (!getenv("TERM")) {
1.9       mrg       125:                (void)fprintf(stderr,
1.34      dsl       126:                         "sysinst: environment variable TERM not set.\n");
1.2       phil      127:                exit(1);
                    128:        }
1.1       phil      129:
1.3       phil      130:        /* argv processing */
1.35      dsl       131:        while ((ch = getopt(argc, argv, "Dr:f:")) != -1)
1.3       phil      132:                switch(ch) {
1.35      dsl       133:                case 'D':       /* set to get past certain errors in testing */
                    134:                        debug = 1;
                    135:                        break;
1.3       phil      136:                case 'r':
                    137:                        /* Release name other than compiled in release. */
1.9       mrg       138:                        strncpy(rel, optarg, SSTRSIZE);
1.3       phil      139:                        break;
1.10      phil      140:                case 'f':
                    141:                        /* Definition file to read. */
1.34      dsl       142:                        process_f_flag(optarg);
1.10      phil      143:                        break;
1.3       phil      144:                case '?':
                    145:                default:
                    146:                        usage();
                    147:                }
1.21      fvdl      148:
                    149:        md_init();
1.3       phil      150:
1.1       phil      151:        /* initialize message window */
1.15      cgd       152:        if (menu_init()) {
                    153:                __menu_initerror();
                    154:                exit(1);
                    155:        }
1.26      perry     156:
1.15      cgd       157:        /*
                    158:         * XXX the following is bogus.  if screen is too small, message
                    159:         * XXX window will be overwritten by menus.
                    160:         */
                    161:        win = newwin(getmaxy(stdscr) - 2, getmaxx(stdscr) - 2, 1, 1);
1.32      dsl       162:        if (win == NULL) {
                    163:                (void)fprintf(stderr,
                    164:                         "sysinst: screen too small\n");
                    165:                exit(1);
                    166:        }
1.26      perry     167:        if (has_colors()) {
                    168:                /*
                    169:                 * XXX This color trick should be done so much better,
                    170:                 * but is it worth it?
                    171:                 */
                    172:                wbkgd(win, COLOR_PAIR(1));
                    173:                wattrset(win, COLOR_PAIR(1));
1.16      garbled   174:        }
1.33      dsl       175:        msg_window(win);
1.1       phil      176:
1.18      cgd       177:        /* Watch for signals and clean up */
1.9       mrg       178:        (void)atexit(cleanup);
1.18      cgd       179:        (void)signal(SIGINT, ttysighandler);
                    180:        (void)signal(SIGQUIT, ttysighandler);
                    181:        (void)signal(SIGHUP, miscsighandler);
1.28      grant     182:
                    183:        /* redraw screen */
                    184:        touchwin(stdscr);
                    185:        refresh();
1.38      dsl       186:
                    187:        /* Ensure we have mountpoint for target filesystems */
                    188:        mkdir(targetroot_mnt, S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
1.5       simonb    189:
1.36      dsl       190:        select_language();
                    191:
1.1       phil      192:        /* Menu processing */
1.31      dsl       193:        process_menu(MENU_netbsd, NULL);
1.1       phil      194:
1.8       simonb    195:        exit_cleanly = 1;
1.34      dsl       196:        return 0;
1.1       phil      197: }
1.36      dsl       198:
                    199: static int
1.40      dsl       200: set_language(menudesc *m, void *arg)
1.36      dsl       201: {
                    202:        char **fnames = arg;
                    203:
1.40      dsl       204:        msg_file(fnames[m->cursel]);
1.36      dsl       205:        return 1;
                    206: }
                    207:
                    208: static void
                    209: select_language(void)
                    210: {
                    211:        DIR *dir;
                    212:        struct dirent *dirent;
                    213:        char **lang_msg, **fnames;
                    214:        int max_lang = 16, num_lang = 0;
                    215:        const char *cp;
                    216:        menu_ent *opt = 0;
                    217:        int lang_menu = -1;
                    218:        int lang;
                    219:
                    220:        dir = opendir(".");
                    221:        if (!dir)
                    222:                return;
                    223:
                    224:        lang_msg = malloc(max_lang * sizeof *lang_msg);
                    225:        fnames = malloc(max_lang * sizeof *fnames);
                    226:        if (!lang_msg || !fnames)
                    227:                goto done;
                    228:
                    229:        lang_msg[0] = strdup(msg_string(MSG_sysinst_message_language));
                    230:        fnames[0] = 0;
                    231:        num_lang = 1;
                    232:
                    233:        while ((dirent = readdir(dir)) != 0) {
                    234:                if (memcmp(dirent->d_name, "sysinstmsgs.", 12))
                    235:                        continue;
                    236:                if (msg_file(dirent->d_name))
                    237:                        continue;
                    238:                cp = msg_string(MSG_sysinst_message_language);
                    239:                if (!strcmp(cp, lang_msg[0]))
                    240:                        continue;
                    241:                if (num_lang == max_lang) {
                    242:                        char **new;
                    243:                        max_lang *= 2;
                    244:                        new = realloc(lang_msg, max_lang * sizeof *lang_msg);
                    245:                        if (!new)
                    246:                                break;
                    247:                        lang_msg = new;
                    248:                        new = realloc(fnames, max_lang * sizeof *fnames);
                    249:                        if (!new)
                    250:                                break;
                    251:                        fnames = new;
                    252:                }
                    253:                fnames[num_lang] = strdup(dirent->d_name);
                    254:                lang_msg[num_lang++] = strdup(cp);
                    255:        }
                    256:        msg_file(0);
                    257:        closedir(dir);
                    258:        dir = 0;
                    259:
                    260:        if (num_lang == 1)
                    261:                goto done;
                    262:
                    263:        opt = calloc(num_lang, sizeof *opt);
                    264:        if (!opt)
                    265:                goto done;
                    266:
                    267:        for (lang = 0; lang < num_lang; lang++) {
                    268:                opt[lang].opt_name = lang_msg[lang];
                    269:                opt[lang].opt_menu = OPT_NOMENU;
                    270:                opt[lang].opt_action = set_language;
                    271:        }
                    272:
                    273:        lang_menu = new_menu(NULL, opt, num_lang, -1, 12, 0, 0, MC_NOEXITOPT,
1.37      dsl       274:                NULL, NULL, NULL, NULL, NULL);
1.36      dsl       275:
                    276:        if (lang_menu != -1) {
                    277:                msg_display(MSG_hello);
                    278:                process_menu(lang_menu, fnames);
                    279:        }
                    280:
                    281:     done:
                    282:        if (dir)
                    283:                closedir(dir);
                    284:        if (lang_menu != -1)
                    285:                free_menu(lang_menu);
                    286:        free(opt);
                    287:        while (num_lang) {
                    288:                free(lang_msg[--num_lang]);
                    289:                free(fnames[num_lang]);
                    290:        }
                    291:        free(lang_msg);
                    292:        free(fnames);
                    293: }
1.7       jonathan  294:
                    295: /* toplevel menu handler ... */
1.9       mrg       296: void
1.34      dsl       297: toplevel(void)
1.7       jonathan  298: {
1.9       mrg       299:
1.20      hubertf   300:        /* Display banner message in (english, francais, deutsch..) */
1.9       mrg       301:        msg_display(MSG_hello);
1.23      minoura   302:        msg_display_add(MSG_md_hello);
                    303:        msg_display_add(MSG_thanks);
1.7       jonathan  304:
                    305:        /*
                    306:         * Undo any stateful side-effects of previous menu choices.
                    307:         * XXX must be idempotent, since we get run each time the main
                    308:         *     menu is displayed.
                    309:         */
                    310:        unwind_mounts();
                    311:        /* ... */
                    312: }
                    313:
1.3       phil      314:
                    315: /* The usage ... */
                    316:
1.8       simonb    317: static void
1.34      dsl       318: usage(void)
1.3       phil      319: {
1.9       mrg       320:
                    321:        (void)fprintf(stderr, msg_string(MSG_usage));
1.5       simonb    322:        exit(1);
                    323: }
                    324:
                    325: /* ARGSUSED */
1.8       simonb    326: static void
1.34      dsl       327: miscsighandler(int signo)
1.5       simonb    328: {
1.18      cgd       329:
                    330:        /*
                    331:         * we need to cleanup(), but it was already scheduled with atexit(),
                    332:         * so it'll be invoked on exit().
                    333:         */
                    334:        exit(1);
                    335: }
                    336:
                    337: static void
1.34      dsl       338: ttysighandler(int signo)
1.18      cgd       339: {
                    340:
                    341:        /*
                    342:         * if we want to ignore a TTY signal (SIGINT or SIGQUIT), then we
                    343:         * just return.  If we want to forward a TTY signal, we forward it
                    344:         * to the specified process group.
                    345:         *
                    346:         * This functionality is used when setting up and displaying child
                    347:         * output so that the child gets the signal and presumably dies,
                    348:         * but sysinst continues.  We use this rather than actually ignoring
                    349:         * the signals, because that will be be passed on to a child
                    350:         * through fork/exec, whereas special handlers get reset on exec..
                    351:         */
                    352:        if (ttysig_ignore)
                    353:                return;
                    354:        if (ttysig_forward) {
                    355:                killpg(ttysig_forward, signo);
                    356:                return;
                    357:        }
1.9       mrg       358:
1.14      cgd       359:        /*
                    360:         * we need to cleanup(), but it was already scheduled with atexit(),
                    361:         * so it'll be invoked on exit().
                    362:         */
1.8       simonb    363:        exit(1);
                    364: }
                    365:
                    366: static void
1.34      dsl       367: cleanup(void)
1.8       simonb    368: {
1.11      garbled   369:        time_t tloc;
1.9       mrg       370:
1.11      garbled   371:        (void)time(&tloc);
1.39      dsl       372:
1.43      dsl       373: #if 0
1.39      dsl       374:        restore_etc();
1.43      dsl       375: #endif
1.41      dsl       376:        /* Ensure we aren't inside the target tree */
                    377:        chdir(getenv("HOME"));
1.11      garbled   378:        unwind_mounts();
1.42      dsl       379:        umount_mnt2();
1.39      dsl       380:
1.5       simonb    381:        endwin();
1.39      dsl       382:
1.11      garbled   383:        if (logging) {
1.29      fvdl      384:                fprintf(logfp, "Log ended at: %s\n", asctime(localtime(&tloc)));
                    385:                fflush(logfp);
                    386:                fclose(logfp);
1.11      garbled   387:        }
                    388:        if (scripting) {
1.34      dsl       389:                fprintf(script, "# Script ended at: %s\n",
                    390:                    asctime(localtime(&tloc)));
1.11      garbled   391:                fflush(script);
                    392:                fclose(script);
                    393:        }
                    394:
1.8       simonb    395:        if (!exit_cleanly)
1.14      cgd       396:                fprintf(stderr, "\n\nsysinst terminated.\n");
1.27      lukem     397: }
                    398:
1.10      phil      399:
                    400: /* Stuff for processing the -f file argument. */
                    401:
                    402: /* Data definitions ... */
                    403:
                    404: static char *rel_ptr = rel;
                    405: static char *machine_ptr = machine;
                    406: static char *dist_dir_ptr = dist_dir;
                    407: static char *ext_dir_ptr = ext_dir;
                    408: static char *ftp_host_ptr = ftp_host;
                    409: static char *ftp_dir_ptr = ftp_dir;
1.44      dsl       410: static char *set_dir_ptr = set_dir;
1.10      phil      411: static char *ftp_user_ptr = ftp_user;
                    412: static char *ftp_pass_ptr = ftp_pass;
1.25      scottr    413: static char *ftp_proxy_ptr = ftp_proxy;
1.10      phil      414: static char *nfs_host_ptr = nfs_host;
                    415: static char *nfs_dir_ptr = nfs_dir;
                    416: static char *cdrom_dev_ptr = cdrom_dev;
                    417: static char *localfs_dev_ptr = localfs_dev;
                    418: static char *localfs_fs_ptr = localfs_fs;
                    419: static char *localfs_dir_ptr = localfs_dir;
                    420: static char *targetroot_mnt_ptr = targetroot_mnt;
                    421: static char *distfs_mnt_ptr = distfs_mnt;
                    422: static char *dist_postfix_ptr = dist_postfix;
                    423:
                    424: struct lookfor fflagopts[] = {
                    425:        {"release", "release = %s", "a $0", &rel_ptr, 1, SSTRSIZE, NULL},
                    426:        {"machine", "machine = %s", "a $0", &machine_ptr, 1, SSTRSIZE, NULL},
                    427:        {"dist dir", "dist dir = %s", "a $0", &dist_dir_ptr, 1, STRSIZE, NULL},
                    428:        {"ext dir", "ext dir = %s", "a $0", &ext_dir_ptr, 1, STRSIZE, NULL},
                    429:        {"ftp host", "ftp host = %s", "a $0", &ftp_host_ptr, 1, STRSIZE, NULL},
                    430:        {"ftp dir", "ftp dir = %s", "a $0", &ftp_dir_ptr, 1, STRSIZE, NULL},
1.44      dsl       431:        {"ftp prefix", "set dir = %s", "a $0", &set_dir_ptr, 1, STRSIZE, NULL},
1.10      phil      432:        {"ftp user", "ftp user = %s", "a $0", &ftp_user_ptr, 1, STRSIZE, NULL},
                    433:        {"ftp pass", "ftp pass = %s", "a $0", &ftp_pass_ptr, 1, STRSIZE, NULL},
1.25      scottr    434:        {"ftp proxy", "ftp proxy = %s", "a $0", &ftp_proxy_ptr, 1, STRSIZE,
                    435:                NULL},
1.10      phil      436:        {"nfs host", "nfs host = %s", "a $0", &nfs_host_ptr, 1, STRSIZE, NULL},
                    437:        {"nfs dir", "ftp dir = %s", "a $0", &nfs_dir_ptr, 1, STRSIZE, NULL},
                    438:        {"cd dev", "cd dev = %s", "a $0", &cdrom_dev_ptr, 1, STRSIZE, NULL},
                    439:        {"local dev", "local dev = %s", "a $0", &localfs_dev_ptr, 1, STRSIZE,
                    440:                NULL},
                    441:        {"local fs", "local fs = %s", "a $0", &localfs_fs_ptr, 1, STRSIZE,
                    442:                NULL},
                    443:        {"local dir", "local dir = %s", "a $0", &localfs_dir_ptr, 1, STRSIZE,
                    444:                NULL},
                    445:        {"targetroot mount", "targetroot mount = %s", "a $0",
                    446:                &targetroot_mnt_ptr, 1, STRSIZE, NULL},
                    447:        {"distfs mount", "distfs mount = %s", "a $0", &distfs_mnt_ptr, 1,
                    448:                STRSIZE, NULL},
                    449:        {"dist postfix", "dist postfix = %s", "a $0", &dist_postfix_ptr, 1,
                    450:                STRSIZE, NULL},
                    451: };
                    452:
                    453: /* process function ... */
                    454:
1.34      dsl       455: void
                    456: process_f_flag(char *f_name)
1.10      phil      457: {
1.34      dsl       458:        char *buffer;
                    459:        struct stat statinfo;
                    460:        int fd;
                    461:
                    462:        /* stat the file (error reported) */
                    463:
                    464:        if (stat(f_name, &statinfo) < 0) {
                    465:                perror(f_name);                 /* XXX -- better message? */
                    466:                exit(1);
                    467:        }
                    468:
                    469:        if ((statinfo.st_mode & S_IFMT) != S_IFREG) {
                    470:                fprintf(stderr, msg_string(MSG_not_regular_file), f_name);
                    471:                exit(1);
                    472:        }
                    473:
                    474:        /* allocate buffer (error reported) */
                    475:        buffer = malloc((size_t)statinfo.st_size + 1);
                    476:        if (buffer == NULL) {
                    477:                fprintf(stderr, msg_string(MSG_out_of_memory));
                    478:                exit(1);
                    479:        }
                    480:
                    481:        /* open the file */
                    482:        fd = open(f_name, O_RDONLY, 0);
                    483:        if (fd < 0) {
                    484:                fprintf(stderr, msg_string(MSG_config_open_error), f_name);
                    485:                exit(1);
                    486:        }
                    487:
                    488:        /* read the file */
                    489:        if (read(fd,buffer, (size_t)statinfo.st_size)
                    490:                                                != (size_t)statinfo.st_size) {
                    491:                fprintf(stderr, msg_string(MSG_config_read_error), f_name);
                    492:                exit(1);
                    493:        }
                    494:        buffer[(size_t)statinfo.st_size] = 0;
                    495:
                    496:        /* close the file */
                    497:        close(fd);
                    498:
                    499:        /* Walk the buffer */
                    500:        walk(buffer, (size_t)statinfo.st_size, fflagopts,
                    501:            sizeof(fflagopts)/sizeof(struct lookfor));
1.10      phil      502:
1.34      dsl       503:        /* free the buffer */
                    504:        free(buffer);
1.3       phil      505: }

CVSweb <webmaster@jp.NetBSD.org>