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

Annotation of src/distrib/utils/sysinst/run.c, Revision 1.7

1.7     ! garbled     1: /*     $NetBSD: run.c,v 1.6 1998/08/10 02:23:45 perry 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:
                     19:  *      This product includes software develooped for the NetBSD Project by
                     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: /* run.c -- routines to interact with other programs. */
                     40:
1.7     ! garbled    41: /* XXX write return codes ignored. XXX */
        !            42:
        !            43: #include <errno.h>
1.1       phil       44: #include <stdio.h>
                     45: #include <stdarg.h>
                     46: #include <stdlib.h>
1.7     ! garbled    47: #include <unistd.h>
        !            48: #include <fcntl.h>
        !            49: #include <curses.h>
        !            50: #include <termios.h>
        !            51: #include <util.h>
        !            52: #include <err.h>
        !            53: #include <sys/ioctl.h>
1.1       phil       54: #include <sys/types.h>
1.7     ! garbled    55: #include <sys/wait.h>
1.1       phil       56: #include <sys/stat.h>
                     57: #include "defs.h"
                     58:
1.7     ! garbled    59: #include "menu_defs.h"
1.3       jonathan   60: #include "msg_defs.h"
                     61:
1.7     ! garbled    62: #define MAXBUF 256
        !            63:
1.1       phil       64: #ifdef DEBUG
1.2       phil       65: #define Xsystem(y) printf ("%s\n", y), 0
1.1       phil       66: #else
                     67: #define Xsystem(y) system(y)
                     68: #endif
                     69:
1.7     ! garbled    70: extern int errno;
        !            71:
1.3       jonathan   72: /*
                     73:  * local prototypes
                     74:  */
1.5       mrg        75: int do_system __P((const char *cmdstr));
                     76: char* va_prog_cmdstr __P((char *cmd, va_list ap));
1.7     ! garbled    77: int launch_subwin __P((WINDOW *actionwin, char **args, struct winsize win, int display));
        !            78: int log_flip __P((void));
        !            79: int script_flip __P((void));
        !            80:
        !            81: #define BUFSIZE 4096
        !            82:
        !            83: char log_text[2][30] = {"Logging: Off", "Scripting: Off"};
        !            84:
        !            85: menu_ent logmenu [2] = {
        !            86:        { log_text[0], OPT_NOMENU, 0, log_flip},
        !            87:        { log_text[1], OPT_NOMENU, 0, script_flip} };
        !            88:
        !            89:
        !            90: void
        !            91: do_logging(void)
        !            92: {
        !            93:        int menu_no;
        !            94:
        !            95:        menu_no = new_menu (" Logging Functions ", logmenu, 2, 13, 12,
        !            96:                0, 55, MC_SCROLL, NULL, NULL, "Pick an option to turn on or off.\n");
        !            97:
        !            98:        if (menu_no < 0) {
        !            99:                (void)fprintf(stderr, "Dynamic menu creation failed.\n");
        !           100:                if (logging)
        !           101:                        (void)fprintf(log, "Dynamic menu creation failed.\n");
        !           102:                exit(EXIT_FAILURE);
        !           103:        }
        !           104:        process_menu(menu_no);
        !           105:        free_menu(menu_no);
        !           106: }
        !           107:
        !           108: int
        !           109: log_flip(void)
        !           110: {
        !           111:        time_t tloc;
        !           112:
        !           113:        (void)time(&tloc);
        !           114:        if (logging == 1) {
        !           115:                sprintf(log_text[0], "Logging: Off");
        !           116:                logging = 0;
        !           117:                fprintf(log, "Log ended at: %s\n", asctime(localtime(&tloc)));
        !           118:                fflush(log);
        !           119:                fclose(log);
        !           120:        } else {
        !           121:                sprintf(log_text[0], "Logging: On");
        !           122:                logging = 1;
        !           123:                log = fopen("sysinst.log", "a");
        !           124:                fprintf(log, "Log started at: %s\n", asctime(localtime(&tloc)));
        !           125:                fflush(log);
        !           126:        }
        !           127:        return(0);
        !           128: }
1.3       jonathan  129:
1.7     ! garbled   130: int
        !           131: script_flip(void)
        !           132: {
        !           133:        time_t tloc;
1.3       jonathan  134:
1.7     ! garbled   135:        (void)time(&tloc);
        !           136:        if (scripting == 1) {
        !           137:                sprintf(log_text[1], "Scripting: Off");
        !           138:                scripting = 0;
        !           139:                fprintf(script, "# Script ended at: %s\n", asctime(localtime(&tloc)));
        !           140:                fflush(script);
        !           141:                fclose(script);
        !           142:        } else {
        !           143:                sprintf(log_text[1], "Scripting: On");
        !           144:                scripting = 1;
        !           145:                script = fopen("sysinst.sh", "w");
        !           146:                fprintf(script, "#!/bin/sh\n");
        !           147:                fprintf(script, "# Script started at: %s\n", asctime(localtime(&tloc)));
        !           148:                fflush(script);
        !           149:        }
        !           150:        return(0);
        !           151: }
1.1       phil      152:
                    153: int
1.5       mrg       154: collect(int kind, char **buffer, const char *name, ...)
1.1       phil      155: {
                    156:        size_t nbytes;          /* Number of bytes in buffer. */
                    157:        size_t fbytes;          /* Number of bytes in file. */
                    158:        struct stat st;         /* stat information. */
                    159:        int ch;
                    160:        FILE *f;
                    161:        char fileorcmd [STRSIZE];
                    162:        va_list ap;
                    163:
1.5       mrg       164:        va_start(ap, name);
                    165:        vsnprintf(fileorcmd, STRSIZE, name, ap);
                    166:        va_end(ap);
1.1       phil      167:
                    168:        if (kind == T_FILE) {
                    169:                /* Get the file information. */
1.5       mrg       170:                if (stat(fileorcmd, &st)) {
1.1       phil      171:                        *buffer = NULL;
                    172:                        return -1;
                    173:                }
                    174:                fbytes = (size_t)st.st_size;
                    175:
                    176:                /* Open the file. */
1.5       mrg       177:                f = fopen(fileorcmd, "r");
1.1       phil      178:                if (f == NULL) {
                    179:                        *buffer = NULL;
                    180:                        return -1;
                    181:                }
                    182:        } else {
                    183:                /* Open the program. */
1.5       mrg       184:                f = popen(fileorcmd, "r");
1.1       phil      185:                if (f == NULL) {
                    186:                        *buffer = NULL;
                    187:                        return -1;
                    188:                }
                    189:                fbytes = BUFSIZE;
                    190:        }
                    191:
                    192:        if (fbytes == 0)
                    193:                fbytes = BUFSIZE;
                    194:
                    195:        /* Allocate the buffer size. */
1.5       mrg       196:        *buffer = (char *)malloc(fbytes + 1);
1.1       phil      197:        if (!*buffer)
                    198:                return -1;
                    199:
                    200:        /* Read the buffer. */
                    201:        nbytes = 0;
                    202:        while (nbytes < fbytes && (ch = fgetc(f)) != EOF)
                    203:                (*buffer)[nbytes++] = ch;
                    204:
                    205:        (*buffer)[nbytes] = 0;
                    206:
                    207:        if (kind == T_FILE)
                    208:                fclose(f);
                    209:        else
                    210:                pclose(f);
                    211:
                    212:        return nbytes;
                    213: }
                    214:
                    215:
1.3       jonathan  216: /*
                    217:  * system(3), but with a debug wrapper.
1.7     ! garbled   218:  * use only for curses sub-applications.
1.3       jonathan  219:  */
1.5       mrg       220: int
                    221: do_system(execstr)
                    222:        const char *execstr;
1.3       jonathan  223: {
                    224:        register int ret;
                    225:
1.5       mrg       226:        /*
                    227:         * The following may be more than one function call.  Can't just
                    228:         * "return Xsystem (command);"
                    229:         */
1.3       jonathan  230:
1.5       mrg       231:        ret = Xsystem(execstr);
                    232:        return (ret);
1.3       jonathan  233:
                    234: }
                    235:
                    236: /*
                    237:  *  build command tring for do_system() from anonymous args.
                    238:  *  XXX return result is in a static buffer.
                    239:  */
1.5       mrg       240: char *
                    241: va_prog_cmdstr(char *cmd, va_list ap)
1.3       jonathan  242: {
1.5       mrg       243:        static char command[STRSIZE];
1.3       jonathan  244:
1.6       perry     245:        memset(command, 0, STRSIZE);
1.5       mrg       246:        (void)vsnprintf(command, STRSIZE, cmd, ap);
                    247:        return (command);
1.3       jonathan  248: }
1.7     ! garbled   249:
1.3       jonathan  250:
1.5       mrg       251: /*
1.7     ! garbled   252:  * launch a program inside a subwindow, and report it's return status when done
1.5       mrg       253:  */
1.7     ! garbled   254:
1.5       mrg       255: int
1.7     ! garbled   256: launch_subwin(actionwin, args, win, display)
        !           257:        WINDOW *actionwin;
        !           258:        char **args;
        !           259:        struct winsize win;
        !           260:        int display;
1.1       phil      261: {
1.7     ! garbled   262:        int xcor,ycor;
        !           263:        int n, i, j;
        !           264:        int status, master, slave;
        !           265:        fd_set active_fd_set, read_fd_set;
        !           266:        int dataflow[2];
        !           267:        pid_t child, subchild, pid;
        !           268:        char ibuf[MAXBUF], obuf[MAXBUF];
        !           269:        char *command, *p, *argzero, **origargs;
        !           270:        struct termios rtt;
        !           271:        struct termios tt;
        !           272:
        !           273:        pipe(dataflow);
        !           274:
        !           275:        argzero = *args;
        !           276:        origargs = args;
        !           277:
        !           278:        command = (char *)malloc(MAXBUF * sizeof(char));
        !           279:        for (p = *args; p != NULL; p = *++args) {
        !           280:                strcat(command, p);
        !           281:                strcat(command, " ");
        !           282:        }
        !           283:        (void)tcgetattr(STDIN_FILENO, &tt);
        !           284:        if (openpty(&master, &slave, NULL, &tt, &win) == -1)
        !           285:                return(1);
        !           286:        rtt = tt;
        !           287:        rtt.c_lflag &= ~ECHO;
        !           288:        (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &rtt);
1.1       phil      289:
1.7     ! garbled   290:        switch(child=fork()) {
        !           291:        case -1:
        !           292:                return -1;
        !           293:                break;
        !           294:        case 0: {
        !           295:                (void)close(STDIN_FILENO);
        !           296:                subchild = fork();
        !           297:                if (subchild == 0) {
        !           298:                        close(dataflow[0]);
        !           299:                        for (;;) {
        !           300:                                n = read(master, obuf, sizeof(obuf));
        !           301:                                if (n <= 0)
        !           302:                                        break;
        !           303:                                write(dataflow[1], obuf, n);
        !           304:                        } /* while spinning */
        !           305:                        nonl();
        !           306:                        _exit(EXIT_SUCCESS);
        !           307:                } /* subchild, child forks */
        !           308:                (void)close(master);
        !           309:                close(dataflow[1]);
        !           310:                close(dataflow[0]);
        !           311:                login_tty(slave);
        !           312:                if (logging) {
        !           313:                        fprintf(log, "executing: %s\n", command);
        !           314:                        fflush(log);
        !           315:                        fclose(log);
        !           316:                }
        !           317:                if (scripting) {
        !           318:                        fprintf(script, "%s\n", command);
        !           319:                        fflush(script);
        !           320:                        fclose(script);
        !           321:                }
        !           322:                execvp(argzero, origargs);
        !           323:        } break; /* end of child */
        !           324:        default: break;
        !           325:        }
        !           326:        close(dataflow[1]);
        !           327:        FD_ZERO(&active_fd_set);
        !           328:        FD_SET(dataflow[0], &active_fd_set);
        !           329:        FD_SET(STDIN_FILENO, &active_fd_set);
        !           330:
        !           331:        pid = wait4(child, &status, WNOHANG, 0);
        !           332:        for (;;) {
        !           333:                read_fd_set = active_fd_set;
        !           334:                if (select(FD_SETSIZE, &read_fd_set, NULL, NULL, NULL) < 0) {
        !           335:                        perror("select");
        !           336:                        if (logging)
        !           337:                                (void)fprintf(log, "select failure: %s\n", strerror(errno));
        !           338:                        exit(EXIT_FAILURE);
        !           339:                }
        !           340:                for (i = 0; i < FD_SETSIZE; ++i)
        !           341:                        if (FD_ISSET (i, &read_fd_set)) {
        !           342:                                n = read(i, ibuf, MAXBUF);
        !           343:                                if (i == STDIN_FILENO)
        !           344:                                        (void)write(master, ibuf, n);
        !           345:                                for (j=0; j < n; j++) {
        !           346:                                        if (display) {
        !           347:                                                if (ibuf[j] == '\n' || ibuf[j] == '\r') {
        !           348:                                                        if (ibuf[j] == '\n') {
        !           349:                                                                getyx(actionwin, ycor, xcor);
        !           350:                                                                if (ycor + 1 >= actionwin->maxy) {
        !           351:                                                                        scroll(actionwin);
        !           352:                                                                        wmove(actionwin, actionwin->maxy - 1, 1);
        !           353:                                                                } else
        !           354:                                                                        wmove(actionwin, ycor + 1, 1);
        !           355:                                                                if (logging)
        !           356:                                                                        fprintf(log, "\n");
        !           357:                                                        }
        !           358:                                                } else {
        !           359:                                                        getyx(actionwin, ycor, xcor);
        !           360:                                                        if (xcor == 0)
        !           361:                                                        wmove(actionwin, ycor, xcor + 1);
        !           362:                                                        waddch(actionwin, ibuf[j]);
        !           363:                                                        wrefresh(actionwin);
        !           364:                                                        if (logging) {
        !           365:                                                                putc(ibuf[j], log);
        !           366:                                                                fflush(log);
        !           367:                                                        }
        !           368:                                                }
        !           369:                                        } else {  /* display is off */
        !           370:                                                if (logging) {
        !           371:                                                        putc(ibuf[j], log);
        !           372:                                                        fflush(log);
        !           373:                                                }
        !           374:                                        }
        !           375:                                }
        !           376:                        }
        !           377:                pid = wait4(child, &status, WNOHANG, 0);
        !           378:                if (pid == child && (WIFEXITED(status) || WIFSIGNALED(status)))
        !           379:                        break;
        !           380:        }
        !           381:        close(dataflow[0]); /* clean up our leaks */
        !           382:        close(master);
        !           383:        close(slave);
        !           384:        if (logging)
        !           385:                fflush(log);
        !           386:
        !           387:        (void)tcsetattr(STDIN_FILENO, TCSAFLUSH, &tt);
        !           388:        if (WIFEXITED(status))
        !           389:                return(WEXITSTATUS(status));
        !           390:        else if (WIFSIGNALED(status))
        !           391:                return(WTERMSIG(status));
        !           392:        else
        !           393:                return(0);
1.3       jonathan  394: }
                    395:
                    396: /*
1.7     ! garbled   397:  * generic program runner.  fatal and display can be set to
        !           398:  * 1 if you wish the output to be displayed, or an error to be
        !           399:  * fatal.
1.3       jonathan  400:  */
1.7     ! garbled   401:
1.5       mrg       402: int
1.7     ! garbled   403: run_prog(int fatal, int display, char *cmd, ...)
1.3       jonathan  404: {
                    405:        va_list ap;
1.7     ! garbled   406:        struct winsize win;
1.3       jonathan  407:        int ret;
1.7     ! garbled   408:        WINDOW *actionwin, *statuswin, *boxwin;
        !           409:        char buf2[MAXBUF];
        !           410:        char *command, *p, *args[51], **aps;
        !           411:
        !           412:        va_start(ap,cmd);
        !           413:        sprintf(buf2,"%s",va_prog_cmdstr(cmd,ap));
        !           414:        p = buf2;
        !           415:        command = strdup(buf2);
        !           416:
        !           417:        /* 51 strings and it's blown! */
        !           418:        for (aps = args; (*aps = strsep(&p, " ")) != NULL;)
        !           419:                if (**aps != '\0')
        !           420:                        ++aps;
        !           421:
        !           422:        (void)ioctl(STDIN_FILENO, TIOCGWINSZ, &win);
        !           423:        if (display) {
        !           424:                statuswin = subwin(stdscr, win.ws_row, win.ws_col, 0, 0);
        !           425:                boxwin = subwin(statuswin, win.ws_row - 3, win.ws_col, 3, 0);
        !           426:                actionwin = subwin(statuswin, win.ws_row - 5, win.ws_col - 3, 4, 1);
        !           427:                scrollok(actionwin, TRUE);
        !           428:
        !           429:                win.ws_col -= 3;
        !           430:                win.ws_row -= 5;
        !           431:
        !           432:                wclear(statuswin);
        !           433:                wrefresh(statuswin);
        !           434:
        !           435:                wclear(boxwin);
        !           436:                box(boxwin, 124, 45);
        !           437:                wrefresh(boxwin);
        !           438:
        !           439:                wclear(actionwin);
        !           440:                wrefresh(actionwin);
        !           441:
        !           442:                wmove(statuswin, 0 , 5);
        !           443:                waddstr(statuswin, "Status: ");
        !           444:                wstandout(statuswin);
        !           445:                waddstr(statuswin, "Running");
        !           446:                wstandend(statuswin);
        !           447:
        !           448:                wmove(statuswin, 1, 4);
        !           449:                waddstr(statuswin, "Command: ");
        !           450:                wstandout(statuswin);
        !           451:                waddstr(statuswin, command);
        !           452:                wstandend(statuswin);
        !           453:                wrefresh(statuswin);
        !           454:
        !           455:                ret = launch_subwin(actionwin, args, win, 1);
        !           456:
        !           457:                wmove(statuswin, 0, 13);
        !           458:                waddstr(statuswin, "          ");
        !           459:                wmove(statuswin, 0, 13);
        !           460:                wstandout(statuswin);
        !           461:                if (ret != 0)
        !           462:                        waddstr(statuswin, "Failed");
        !           463:                else
        !           464:                        waddstr(statuswin, "Finished");
        !           465:                wstandend(statuswin);
        !           466:                wmove(statuswin, 2, 5);
        !           467:                waddstr(statuswin, "Press any key to continue");
        !           468:                wrefresh(statuswin);
        !           469:                (void)getchar();
        !           470:
        !           471:                /* clean things up */
        !           472:                wclear(actionwin);
        !           473:                wrefresh(actionwin);
        !           474:                delwin(actionwin);
        !           475:                wclear(boxwin);
        !           476:                wrefresh(boxwin);
        !           477:                delwin(boxwin);
        !           478:                wclear(statuswin);
        !           479:                wrefresh(statuswin);
        !           480:                delwin(statuswin);
        !           481:                refresh();
        !           482:        } else { /* display */
        !           483:                ret = launch_subwin(NULL, args, win, 0);
        !           484:        }
1.5       mrg       485:        va_end(ap);
1.7     ! garbled   486:        if (fatal)
1.5       mrg       487:                exit(ret);
1.7     ! garbled   488:        else
        !           489:                return(ret);
1.3       jonathan  490: }

CVSweb <webmaster@jp.NetBSD.org>