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

1.52    ! he          1: /*     $NetBSD: main.c,v 1.51 2006/02/26 10:25:52 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.36      dsl        58: static void select_language(void);
1.34      dsl        59: static void usage(void);
                     60: static void miscsighandler(int);
                     61: static void ttysighandler(int);
                     62: static void cleanup(void);
                     63: static void process_f_flag(char *);
1.8       simonb     64:
                     65: static int exit_cleanly = 0;   /* Did we finish nicely? */
1.11      garbled    66: int logging;                   /* are we logging everything? */
                     67: int scripting;                 /* are we building a script? */
1.29      fvdl       68: FILE *logfp;                   /* log file */
1.11      garbled    69: FILE *script;                  /* script file */
1.1       phil       70:
1.12      fvdl       71: #ifdef DEBUG
1.34      dsl        72: extern int log_flip(void);
1.12      fvdl       73: #endif
                     74:
1.49      dsl        75: /* String defaults and stuff for processing the -f file argument. */
                     76:
                     77: struct f_arg {
                     78:        const char *name;
                     79:        const char *dflt;
                     80:        char *var;
                     81:        int size;
                     82: };
                     83:
                     84: static const struct f_arg fflagopts[] = {
                     85:        {"release", REL, rel, sizeof rel},
                     86:        {"machine", MACH, machine, sizeof machine},
                     87:        {"xfer dir", "/usr/INSTALL", xfer_dir, sizeof xfer_dir},
                     88:        {"ext dir", "", ext_dir, sizeof ext_dir},
                     89:        {"ftp host", SYSINST_FTP_HOST, ftp.host, sizeof ftp.host},
                     90:        {"ftp dir", SYSINST_FTP_DIR, ftp.dir, sizeof ftp.dir},
                     91:        {"ftp prefix", "/" MACH "/binary/sets", set_dir, sizeof set_dir},
                     92:        {"ftp user", "ftp", ftp.user, sizeof ftp.user},
                     93:        {"ftp pass", "", ftp.pass, sizeof ftp.pass},
                     94:        {"ftp proxy", "", ftp.proxy, sizeof ftp.proxy},
                     95:        {"nfs host", "", nfs_host, sizeof nfs_host},
                     96:        {"nfs dir", "/bsd/release", nfs_dir, sizeof nfs_dir},
                     97:        {"cd dev", "cd0a", cdrom_dev, sizeof cdrom_dev},
1.50      dsl        98:        {"fd dev", "/dev/fd0a", fd_dev, sizeof fd_dev},
1.49      dsl        99:        {"local dev", "", localfs_dev, sizeof localfs_dev},
                    100:        {"local fs", "ffs", localfs_fs, sizeof localfs_fs},
                    101:        {"local dir", "release", localfs_dir, sizeof localfs_dir},
                    102:        {"targetroot mount", "/targetroot", targetroot_mnt, sizeof targetroot_mnt},
                    103:        {"dist postfix", ".tgz", dist_postfix, sizeof dist_postfix},
                    104:        {"diskname", "mydisk", bsddiskname, sizeof bsddiskname},
                    105:
1.52    ! he        106:        {NULL, NULL, NULL, 0}
1.49      dsl       107: };
                    108:
1.45      christos  109: static void
                    110: init(void)
                    111: {
1.49      dsl       112:        const struct f_arg *arg;
                    113:
1.45      christos  114:        sizemult = 1;
                    115:        disktype = "unknown";
                    116:        tmp_mfs_size = 0;
                    117:        doessf = "";
1.49      dsl       118:        clean_xfer_dir = 0;
1.45      christos  119:        mnt2_mounted = 0;
1.51      dsl       120:        fd_type = "msdos";
1.49      dsl       121:
                    122:        for (arg = fflagopts; arg->name != NULL; arg++)
                    123:                strlcpy(arg->var, arg->dflt, arg->size);
1.45      christos  124: }
                    125:
1.9       mrg       126: int
1.34      dsl       127: main(int argc, char **argv)
1.1       phil      128: {
                    129:        WINDOW *win;
1.3       phil      130:        int ch;
1.2       phil      131:
1.11      garbled   132:        logging = 0; /* shut them off unless turned on by the user */
1.45      christos  133:        init();
1.12      fvdl      134: #ifdef DEBUG
                    135:        log_flip();
                    136: #endif
1.11      garbled   137:        scripting = 0;
                    138:
1.2       phil      139:        /* Check for TERM ... */
                    140:        if (!getenv("TERM")) {
1.9       mrg       141:                (void)fprintf(stderr,
1.34      dsl       142:                         "sysinst: environment variable TERM not set.\n");
1.2       phil      143:                exit(1);
                    144:        }
1.1       phil      145:
1.3       phil      146:        /* argv processing */
1.35      dsl       147:        while ((ch = getopt(argc, argv, "Dr:f:")) != -1)
1.3       phil      148:                switch(ch) {
1.35      dsl       149:                case 'D':       /* set to get past certain errors in testing */
                    150:                        debug = 1;
                    151:                        break;
1.3       phil      152:                case 'r':
                    153:                        /* Release name other than compiled in release. */
1.49      dsl       154:                        strncpy(rel, optarg, sizeof rel);
1.3       phil      155:                        break;
1.10      phil      156:                case 'f':
                    157:                        /* Definition file to read. */
1.34      dsl       158:                        process_f_flag(optarg);
1.10      phil      159:                        break;
1.3       phil      160:                case '?':
                    161:                default:
                    162:                        usage();
                    163:                }
1.21      fvdl      164:
                    165:        md_init();
1.3       phil      166:
1.1       phil      167:        /* initialize message window */
1.15      cgd       168:        if (menu_init()) {
                    169:                __menu_initerror();
                    170:                exit(1);
                    171:        }
1.26      perry     172:
1.15      cgd       173:        /*
1.49      dsl       174:         * Put 'messages' in a window that has a one-character border
                    175:         * on the real screen.
1.15      cgd       176:         */
                    177:        win = newwin(getmaxy(stdscr) - 2, getmaxx(stdscr) - 2, 1, 1);
1.32      dsl       178:        if (win == NULL) {
                    179:                (void)fprintf(stderr,
                    180:                         "sysinst: screen too small\n");
                    181:                exit(1);
                    182:        }
1.26      perry     183:        if (has_colors()) {
                    184:                /*
                    185:                 * XXX This color trick should be done so much better,
                    186:                 * but is it worth it?
                    187:                 */
                    188:                wbkgd(win, COLOR_PAIR(1));
                    189:                wattrset(win, COLOR_PAIR(1));
1.16      garbled   190:        }
1.33      dsl       191:        msg_window(win);
1.1       phil      192:
1.18      cgd       193:        /* Watch for signals and clean up */
1.9       mrg       194:        (void)atexit(cleanup);
1.18      cgd       195:        (void)signal(SIGINT, ttysighandler);
                    196:        (void)signal(SIGQUIT, ttysighandler);
                    197:        (void)signal(SIGHUP, miscsighandler);
1.28      grant     198:
                    199:        /* redraw screen */
                    200:        touchwin(stdscr);
                    201:        refresh();
1.38      dsl       202:
                    203:        /* Ensure we have mountpoint for target filesystems */
                    204:        mkdir(targetroot_mnt, S_IRWXU| S_IRGRP|S_IXGRP | S_IROTH|S_IXOTH);
1.5       simonb    205:
1.36      dsl       206:        select_language();
1.46      dsl       207:        get_kb_encoding();
1.36      dsl       208:
1.1       phil      209:        /* Menu processing */
1.31      dsl       210:        process_menu(MENU_netbsd, NULL);
1.1       phil      211:
1.8       simonb    212:        exit_cleanly = 1;
1.34      dsl       213:        return 0;
1.1       phil      214: }
1.36      dsl       215:
                    216: static int
1.40      dsl       217: set_language(menudesc *m, void *arg)
1.36      dsl       218: {
                    219:        char **fnames = arg;
                    220:
1.40      dsl       221:        msg_file(fnames[m->cursel]);
1.36      dsl       222:        return 1;
                    223: }
                    224:
                    225: static void
                    226: select_language(void)
                    227: {
                    228:        DIR *dir;
                    229:        struct dirent *dirent;
                    230:        char **lang_msg, **fnames;
                    231:        int max_lang = 16, num_lang = 0;
                    232:        const char *cp;
                    233:        menu_ent *opt = 0;
                    234:        int lang_menu = -1;
                    235:        int lang;
                    236:
                    237:        dir = opendir(".");
                    238:        if (!dir)
                    239:                return;
                    240:
                    241:        lang_msg = malloc(max_lang * sizeof *lang_msg);
                    242:        fnames = malloc(max_lang * sizeof *fnames);
                    243:        if (!lang_msg || !fnames)
                    244:                goto done;
                    245:
                    246:        lang_msg[0] = strdup(msg_string(MSG_sysinst_message_language));
                    247:        fnames[0] = 0;
                    248:        num_lang = 1;
                    249:
                    250:        while ((dirent = readdir(dir)) != 0) {
                    251:                if (memcmp(dirent->d_name, "sysinstmsgs.", 12))
                    252:                        continue;
                    253:                if (msg_file(dirent->d_name))
                    254:                        continue;
                    255:                cp = msg_string(MSG_sysinst_message_language);
                    256:                if (!strcmp(cp, lang_msg[0]))
                    257:                        continue;
                    258:                if (num_lang == max_lang) {
                    259:                        char **new;
                    260:                        max_lang *= 2;
                    261:                        new = realloc(lang_msg, max_lang * sizeof *lang_msg);
                    262:                        if (!new)
                    263:                                break;
                    264:                        lang_msg = new;
                    265:                        new = realloc(fnames, max_lang * sizeof *fnames);
                    266:                        if (!new)
                    267:                                break;
                    268:                        fnames = new;
                    269:                }
                    270:                fnames[num_lang] = strdup(dirent->d_name);
                    271:                lang_msg[num_lang++] = strdup(cp);
                    272:        }
                    273:        msg_file(0);
                    274:        closedir(dir);
                    275:        dir = 0;
                    276:
                    277:        if (num_lang == 1)
                    278:                goto done;
                    279:
                    280:        opt = calloc(num_lang, sizeof *opt);
                    281:        if (!opt)
                    282:                goto done;
                    283:
                    284:        for (lang = 0; lang < num_lang; lang++) {
                    285:                opt[lang].opt_name = lang_msg[lang];
                    286:                opt[lang].opt_menu = OPT_NOMENU;
                    287:                opt[lang].opt_action = set_language;
                    288:        }
                    289:
                    290:        lang_menu = new_menu(NULL, opt, num_lang, -1, 12, 0, 0, MC_NOEXITOPT,
1.37      dsl       291:                NULL, NULL, NULL, NULL, NULL);
1.36      dsl       292:
                    293:        if (lang_menu != -1) {
                    294:                msg_display(MSG_hello);
                    295:                process_menu(lang_menu, fnames);
                    296:        }
                    297:
                    298:     done:
                    299:        if (dir)
                    300:                closedir(dir);
                    301:        if (lang_menu != -1)
                    302:                free_menu(lang_menu);
                    303:        free(opt);
                    304:        while (num_lang) {
                    305:                free(lang_msg[--num_lang]);
                    306:                free(fnames[num_lang]);
                    307:        }
                    308:        free(lang_msg);
                    309:        free(fnames);
                    310: }
1.7       jonathan  311:
                    312: /* toplevel menu handler ... */
1.9       mrg       313: void
1.34      dsl       314: toplevel(void)
1.7       jonathan  315: {
1.9       mrg       316:
1.20      hubertf   317:        /* Display banner message in (english, francais, deutsch..) */
1.9       mrg       318:        msg_display(MSG_hello);
1.23      minoura   319:        msg_display_add(MSG_md_hello);
                    320:        msg_display_add(MSG_thanks);
1.7       jonathan  321:
                    322:        /*
                    323:         * Undo any stateful side-effects of previous menu choices.
                    324:         * XXX must be idempotent, since we get run each time the main
                    325:         *     menu is displayed.
                    326:         */
                    327:        unwind_mounts();
                    328:        /* ... */
                    329: }
                    330:
1.3       phil      331:
                    332: /* The usage ... */
                    333:
1.8       simonb    334: static void
1.34      dsl       335: usage(void)
1.3       phil      336: {
1.9       mrg       337:
                    338:        (void)fprintf(stderr, msg_string(MSG_usage));
1.5       simonb    339:        exit(1);
                    340: }
                    341:
                    342: /* ARGSUSED */
1.8       simonb    343: static void
1.34      dsl       344: miscsighandler(int signo)
1.5       simonb    345: {
1.18      cgd       346:
                    347:        /*
                    348:         * we need to cleanup(), but it was already scheduled with atexit(),
                    349:         * so it'll be invoked on exit().
                    350:         */
                    351:        exit(1);
                    352: }
                    353:
                    354: static void
1.34      dsl       355: ttysighandler(int signo)
1.18      cgd       356: {
                    357:
                    358:        /*
                    359:         * if we want to ignore a TTY signal (SIGINT or SIGQUIT), then we
                    360:         * just return.  If we want to forward a TTY signal, we forward it
                    361:         * to the specified process group.
                    362:         *
                    363:         * This functionality is used when setting up and displaying child
                    364:         * output so that the child gets the signal and presumably dies,
                    365:         * but sysinst continues.  We use this rather than actually ignoring
                    366:         * the signals, because that will be be passed on to a child
                    367:         * through fork/exec, whereas special handlers get reset on exec..
                    368:         */
                    369:        if (ttysig_ignore)
                    370:                return;
                    371:        if (ttysig_forward) {
                    372:                killpg(ttysig_forward, signo);
                    373:                return;
                    374:        }
1.9       mrg       375:
1.14      cgd       376:        /*
                    377:         * we need to cleanup(), but it was already scheduled with atexit(),
                    378:         * so it'll be invoked on exit().
                    379:         */
1.8       simonb    380:        exit(1);
                    381: }
                    382:
                    383: static void
1.34      dsl       384: cleanup(void)
1.8       simonb    385: {
1.11      garbled   386:        time_t tloc;
1.9       mrg       387:
1.11      garbled   388:        (void)time(&tloc);
1.39      dsl       389:
1.43      dsl       390: #if 0
1.39      dsl       391:        restore_etc();
1.43      dsl       392: #endif
1.41      dsl       393:        /* Ensure we aren't inside the target tree */
                    394:        chdir(getenv("HOME"));
1.11      garbled   395:        unwind_mounts();
1.42      dsl       396:        umount_mnt2();
1.39      dsl       397:
1.5       simonb    398:        endwin();
1.39      dsl       399:
1.11      garbled   400:        if (logging) {
1.29      fvdl      401:                fprintf(logfp, "Log ended at: %s\n", asctime(localtime(&tloc)));
                    402:                fflush(logfp);
                    403:                fclose(logfp);
1.11      garbled   404:        }
                    405:        if (scripting) {
1.34      dsl       406:                fprintf(script, "# Script ended at: %s\n",
                    407:                    asctime(localtime(&tloc)));
1.11      garbled   408:                fflush(script);
                    409:                fclose(script);
                    410:        }
                    411:
1.8       simonb    412:        if (!exit_cleanly)
1.14      cgd       413:                fprintf(stderr, "\n\nsysinst terminated.\n");
1.27      lukem     414: }
                    415:
1.10      phil      416:
                    417: /* process function ... */
                    418:
1.34      dsl       419: void
                    420: process_f_flag(char *f_name)
1.10      phil      421: {
1.49      dsl       422:        char buffer[STRSIZE];
                    423:        int len;
                    424:        const struct f_arg *arg;
                    425:        FILE *fp;
                    426:        char *cp, *cp1;
1.34      dsl       427:
1.48      dsl       428:        /* open the file */
1.49      dsl       429:        fp = fopen(f_name, "r");
                    430:        if (fp == NULL) {
1.48      dsl       431:                fprintf(stderr, msg_string(MSG_config_open_error), f_name);
1.34      dsl       432:                exit(1);
                    433:        }
                    434:
1.49      dsl       435:        while (fgets(buffer, sizeof buffer, fp) != NULL) {
                    436:                cp = buffer + strspn(buffer, " \t");
                    437:                if (strchr("#\r\n", *cp) != NULL)
                    438:                        continue;
                    439:                for (arg = fflagopts; arg->name != NULL; arg++) {
                    440:                        len = strlen(arg->name);
                    441:                        if (memcmp(cp, arg->name, len) != 0)
                    442:                                continue;
                    443:                        cp1 = cp + len;
                    444:                        cp1 += strspn(cp1, " \t");
                    445:                        if (*cp1++ != '=')
                    446:                                continue;
                    447:                        cp1 += strspn(cp1, " \t");
                    448:                        len = strcspn(cp1, " \n\r\t");
                    449:                        cp1[len] = 0;
                    450:                        strlcpy(arg->var, cp1, arg->size);
                    451:                        break;
                    452:                }
1.34      dsl       453:        }
                    454:
1.49      dsl       455:        fclose(fp);
1.3       phil      456: }

CVSweb <webmaster@jp.NetBSD.org>