[BACK]Return to fep_main.c CVS log [TXT][DIR] Up to [local] / OpenXM_contrib2 / fep

Annotation of OpenXM_contrib2/fep/fep_main.c, Revision 1.5

1.1       noro        1: /*     Copyright (c) 1987, 1988 by Software Research Associates, Inc.  */
                      2:
                      3: #ifndef lint
                      4: static char rcsid[]=
                      5: "$Id: fep_main.c,v 4.11 1993/06/10 02:51:28 utashiro Exp $ (SRA)";
                      6: #endif /* lint */
                      7:
                      8: #include <stdio.h>
                      9: #include <signal.h>
                     10: #include <sys/types.h>
                     11: #include <sys/stat.h>
                     12: #include <sys/ioctl.h>
1.3       noro       13: #if defined(sun)
                     14: #include <sys/fcntl.h>
                     15: #include <sys/ttold.h>
                     16: #endif
1.1       noro       17: #ifdef TERMIOS
                     18: #include <termios.h>
                     19: #if defined(__linux__) || defined(__CYGWIN__)
                     20: #ifndef _POSIX_VDISABLE
                     21: #define _POSIX_VDISABLE '\0'
                     22: #endif
                     23: #endif
                     24: #else
                     25: #include <sgtty.h>
                     26: #endif
                     27: #include <sys/file.h>
                     28: #include <sys/time.h>
                     29: #include <sys/resource.h>
                     30: #include <sys/errno.h>
                     31:
                     32: #include "fep_defs.h"
                     33: #include "fep_glob.h"
                     34: #include "fep_funcs.h"
                     35: #ifdef STAT
                     36: #include "fep_stat.h"
                     37: #endif
                     38:
                     39: #ifndef lint
                     40:   static char fep_defsrc[] = FEP_DEFS;
                     41:   static char fep_globrc[] = FEP_GLOB;
                     42:   static char fep_funcsrc[] = FEP_FUNCS;
                     43: #ifdef STAT
                     44:   static char fep_statrc[] = FEP_STAT;
                     45: #endif
                     46: #endif /* lint */
                     47:
                     48: char   *myself;                        /* the command name */
                     49: char   *prompt = "";                   /* prompt string */
                     50: char   *delimiters = DEFAULT_DELIMITERS;
                     51:                                        /* delimiter characters */
                     52: int    master;                         /* file discriptor for pty master */
                     53: int    slave;                          /* file discriptor for pty slave */
                     54: fd_set mastermask;                     /* 1<<master */
                     55: fd_set stdinmask;                      /* 1<<fileno(stdin) */
                     56: fd_set selectmask;                     /* stdinmask | mastermask */
                     57: int    selectnfds;                     /* max (fileno(stdin), master) + 1*/
                     58: int    child_pid;                      /* child pid */
                     59: int    ptyflag = ON;                   /* flag to use pty or not */
                     60: int    histlen = -1;                   /* history length */
                     61: int    debug = OFF;                    /* debug switch */
                     62: int    auto_tty_fix = ON;              /* fix tty mode automaticaly */
                     63: FILE   *script_fp = NULL;              /* script file pointer */
1.3       noro       64: #if defined(sun)
                     65: void   catchsig (int);         /* function take care SIGCHILD */
                     66: #else
1.1       noro       67: void   catchsig __P((int));            /* function take care SIGCHILD */
1.3       noro       68: #endif
1.1       noro       69:
                     70: #ifdef TERMIOS
                     71: #define ttystruct termios
                     72: #elif defined(TIOCSETN)
                     73: #define ttystruct sgttyb
                     74: #endif
                     75: struct ttystruct initial_ttymode;              /* initial tty mode */
                     76: struct ttystruct master_ttymode;               /* master tty mode */
                     77: struct ttystruct slave_ttymode;                /* slave tty mode */
                     78:
                     79: int    lines;                          /* terminal line size */
                     80: int    columns;                        /* terminal coulumn size */
                     81: char   *term_clear;                    /* terminal clear code */
                     82:
1.3       noro       83: #if defined(sun)
                     84: void   (*sighup)(int), (*sigchld)(int), (*sigtstp)(int);
                     85: #else
1.1       noro       86: void   (*sighup) __P((int)), (*sigchld) __P((int)), (*sigtstp) __P((int));
1.3       noro       87: #endif
1.1       noro       88:                                        /* function buffer for signal */
                     89:
                     90: #ifdef TIOCSETN
                     91: struct tchars tchars_buf;              /* tty characters */
                     92: struct ltchars ltchars_buf;            /* tty characters */
                     93: #endif
                     94: int    lmode_buf;                      /* local mode */
                     95: int    line_desc;                      /* line descipline */
                     96: #ifdef KANJI
                     97: struct jtchars jtchars_buf;            /* kanji tty characters */
                     98: int    kmode_buf;                      /* kanji mode */
                     99: #endif /* KANJI */
                    100:
                    101: char   master_tty[16];                 /* master tty name */
                    102: char   slave_tty[16];                  /* slave tty name */
                    103:
                    104: BUFFER iobuffer;                       /* buffer self */
                    105: BUFFER *output_buffer = &iobuffer;     /* buffer pointer */
                    106:
                    107: struct cmdinfo {
                    108:        char *command;
                    109:        char *prompt;
                    110:        char *delimiters;
                    111: } cmdinfo_tab [] = {
                    112:        {"/bin/sh",             "$ ",           " \t()<>{};&|='\""},
                    113:        {"sh",                  "$ ",           " \t()<>{};&|='\""},
                    114:        {"jsh",                 "$ ",           " \t()<>{};&|='\""},
                    115:        {"/bin/csh",            "% ",           " \t()<>{};&|='\""},
                    116:        {"csh",                 "% ",           " \t()<>{};&|='\""},
                    117:        {"jcsh",                "% ",           " \t()<>{};&|='\""},
                    118:        {"/usr/ucb/dbx",        "(dbx) ",       " \t>"},
                    119:        {"dbx",                 "(dbx) ",       " \t>"},
                    120:        {"/etc/lpc",            "lpc> ",        " \t"},
                    121:        {"lpc",                 "lpc> ",        " \t"},
                    122:        {"/usr/ucb/mail",       "& ",           " \t"},
                    123:        {"mail",                "& ",           " \t"},
                    124:        {"/usr/lib/sendmail",   "> ",           " \t"},
                    125:        {"sendmail",            "> ",           " \t"},
                    126:        {"/usr/sra/calc",       "CALC: ",       " \t"},
                    127:        {"calc",                "CALC: ",       " \t"},
                    128:        {0,                     0}
                    129: };
                    130:
                    131: main(argc, argv)
                    132:     int argc;
                    133:     char *argv[];
                    134: {
                    135:     int     i;
                    136:     char    *cp;
                    137:     char    *getenv();
                    138:     char    **commandv;
                    139:     char    *allocAndCopyThere();
                    140:
                    141:     myself = argv[0];
                    142:
                    143:     setvbuf(stdin, NULL, _IONBF, 0);
                    144:     setvbuf(stdout, NULL, _IONBF, 0);
                    145:     setvbuf(stderr, NULL, _IONBF, 0);
                    146:
                    147:     /*
                    148:      * Initialize binding table
                    149:      */
                    150:     init_bind_table ();
                    151:
                    152:     /*
                    153:      * Set default variables before process arguments.
                    154:      */
                    155:     set_default_vars ();
                    156:
                    157:
                    158:     /*
                    159:      * Look environment variable first.
                    160:      */
                    161:     /* EDITMODE */
                    162:     if ((cp=getenv("EDITMODE")) && (eq(cp,"emacs")||eq(cp,"vi")))
                    163:        set_only_var ("editmode", cp);
                    164:     /* USER */
                    165:     if (cp=getenv("USER"))
                    166:        set_only_var ("user", cp);
                    167:     /* HOME */
                    168:     if (cp=getenv("HOME"))
                    169:        set_only_var ("home", cp);
                    170:     /* TERM */
                    171:     if (cp=getenv("TERM"))
                    172:        set_only_var ("term", cp);
                    173:     /* SHELL */
                    174:     if (cp=getenv("SHELL"))
                    175:        set_only_var ("shell", cp);
                    176:
                    177:     /*
                    178:      * Check arguments.
                    179:      */
                    180:     while (argv[1] && argv[1][0] == '-') {
                    181:        switch (argv[1][1]) {
                    182:
                    183:            case '\0': /* - */
                    184:                ptyflag = 0;
                    185:                break;
                    186:
                    187:            case 'd':  /* -d */
                    188:                debug = ON;
                    189:                break;
                    190:
                    191:            case 'e': /* -emacs */
                    192:                if (strcmp (argv[1], "-emacs") == 0)
                    193:                    set_only_var ("editmode", "emacs");
                    194:                else
                    195:                    goto DEFAULT;
                    196:                break;
                    197:
                    198:            case 'h': /* -h */
                    199:                if (argv[1][2] == '\0') {
                    200:                    argv++;
                    201:                    argc--;
                    202:                    if (argc == 1)
                    203:                        usageAndExit ();
                    204:                    histlen = atoi (argv[1]);
                    205:                }
                    206:                else {
                    207:                    histlen = atoi (&argv[1] + 2);
                    208:                }
                    209:                break;
                    210:
                    211:            case 'p': /* -p */
                    212:                if (argv[1][2] == '\0') {
                    213:                    argv++;
                    214:                    argc--;
                    215:                    if (argc == 1)
                    216:                        usageAndExit ();
                    217:                    prompt = allocAndCopyThere (argv[1]);
                    218:                }
                    219:                else {
                    220:                    prompt = allocAndCopyThere (argv[1] + 2);
                    221:                }
                    222:                break;
                    223:
                    224:            case 'v': /* -vi */
                    225:                if (strcmp (argv[1], "-vi") == 0)
                    226:                    set_only_var ("editmode", "vi");
                    227:                else
                    228:                    goto DEFAULT;
                    229:                break;
                    230: DEFAULT:
                    231:            default:
                    232:                printf ("Unknown option \"%s\"\n", argv[1]);
                    233:        }
                    234:        argv++;
                    235:        argc--;
                    236:     }
                    237:     fflush (stdout);
                    238:
                    239:     if (argc < 2 && ptyflag) {
                    240:        usageAndExit ();
                    241:     }
                    242:
                    243:     look_cmdinfo (argv[1]);
                    244:
                    245:     /*
                    246:      * Set variable of command name.
                    247:      */
                    248:     {
                    249:        char *cp = argv[1], *rindex();
                    250:
                    251:        if (any ('/', cp))
                    252:            cp = rindex (cp, '/') + 1;
                    253:        set_var (cp, "1");
                    254:        set_var ("command", cp);
                    255:     }
                    256:
                    257:     commandv = &argv[1];
                    258:
                    259:     if (! isatty (0)) {
1.5     ! ohara     260: #if defined(__INTERIX)
        !           261:        execvp (*commandv, commandv);
        !           262: #else
1.1       noro      263:        execvp (*commandv, commandv, 0);
1.5     ! ohara     264: #endif
1.1       noro      265:        perror (*commandv);
                    266:        exit (1);
                    267:     }
                    268:
                    269:     get_pty_master ();
                    270:     fix_tty ();
                    271:
                    272:     if (histlen < 0) {
                    273:        if (getenv ("HISTLEN"))
                    274:            histlen = atoi (getenv ("HISTLEN"));
                    275:        else
                    276:            histlen = DFL_HISTLEN;
                    277:     }
                    278:
                    279:     init_hist (histlen);
                    280:     init_edit_params ();
                    281:
                    282:     /*
                    283:      * Initialize output buffer.
                    284:      */
                    285:     if (!output_buffer->b_buf) {
                    286:        int size;
                    287:
                    288:        if ((size = atoi (look_var ("buffer"))) <= 0)
                    289:            size = 5120;
                    290:        if (!set_buffer (output_buffer, size)) {
                    291:            fprintf (stderr, "Can't allocate enough momory\n");
                    292:            kill_process ();
                    293:            exit (1);
                    294:        }
                    295:     }
                    296:
                    297:     if (ptyflag) {
                    298:        child_pid = fork ();
                    299:        if (child_pid < 0) {
                    300:            perror ("fork");
                    301:            kill_process ();
                    302:            exit (1);
                    303:        }
                    304:        if (child_pid == 0)
                    305:            exec_to_command (commandv);
                    306:     }
                    307:     fix_signal ();
                    308:
                    309:     input_handler ();
                    310: }
                    311:
                    312: fix_signal ()
                    313: {
                    314: #ifdef SIGWINCH
1.3       noro      315: #if defined(sun)
                    316:     void sigwinch (int);
                    317: #else
1.1       noro      318:     void sigwinch __P((int));
                    319: #endif
1.3       noro      320: #endif
1.1       noro      321:
                    322:     sighup = signal (SIGHUP, terminate);
                    323:     sigchld = signal (SIGCHLD, catchsig);
                    324:     sigtstp = signal (SIGTSTP, SIG_IGN);
                    325:     signal (SIGINT, (void(*)())send_int_sig);
                    326: #ifdef SIGWINCH
                    327:     (void) signal(SIGWINCH, sigwinch);
                    328: #endif
                    329: }
                    330:
                    331: recover_signal ()
                    332: {
                    333:
                    334:     (void) signal (SIGHUP, sighup);
                    335:     (void) signal (SIGCHLD, sigchld);
                    336:     (void) signal (SIGTSTP, sigtstp);
                    337: }
                    338:
                    339: input_handler()
                    340: {
                    341:     char   *inputline;
                    342:     char   *getline ();
                    343:
                    344:     /*
                    345:      * Get slave tty descriptor for auto-tty-fix
                    346:      */
                    347:     if ((slave = open (slave_tty, O_RDONLY)) < 0)
                    348:        perror ("open");
                    349:
                    350:     while (inputline = getline ()) {
                    351:        /*
                    352:         * XXX: nbyte should be greater than 0 only for ^@ input in emacs.
                    353:         * This solution is very ugly.. but it will takes a half day
                    354:         * to fix this problem in more right way.  I will fix this problem
                    355:         * in future release.
                    356:         */
                    357:        register int nbyte = max (strlen (inputline), 1);
                    358:
                    359:        /*
                    360:         * Write to master pty
                    361:         */
                    362:        write (master, inputline, nbyte);
                    363:
                    364:        /*
                    365:         * NOTE:
                    366:         * Saving command line to output buffer is done in getline().
                    367:         * Because inputline here is converted by alias.
                    368:         */
                    369:
                    370: #ifdef STAT
                    371:        stat_ibyte += nbyte;
                    372: #endif
                    373:
                    374:        /*
                    375:         * Write to script file.
                    376:         */
                    377:        if (Through == OFF && Transparency == OFF && script_fp)
                    378:            fwrite (inputline, sizeof(CHAR), strlen (inputline), script_fp);
                    379:     }
                    380:     terminate (0);
                    381: }
                    382:
                    383: #define INPUT_BUFFER_SIZE 1024
                    384:
                    385: #ifdef USE_TIMEOUT
                    386: /*
                    387:  * NOTE:
                    388:  * Now these time mechanism is not used.
                    389:  * Terminal status is get at every input from stdin.
                    390:  */
                    391: struct timeval timeout_0s      = {0L, 0L};
                    392: struct timeval timeout_500ms   = {0L, 500000L};
                    393: struct timeval timeout_1s      = {1L, 0L};
                    394: struct timeval timeout_5s      = {5L, 0L};
                    395: struct timeval timeout_10s     = {10L, 0L};
                    396: struct timeval timeout_60s     = {60L, 0L};
                    397:
                    398: #define TIMEOUT_IMMID          &timeout_500ms
                    399: #define TIMEOUT_SOON           &timeout_1s
                    400: #define TIMEOUT_SHORT          &timeout_5s
                    401: #define TIMEOUT_MID            &timeout_10s
                    402: #define TIMEOUT_LONG           &timeout_60s
                    403: #define TIMEOUT_FOREVER                (struct timeval *)0
                    404: #define TIMEOUT_NOBLOCK                &timeout_0s
                    405:
                    406: struct timeval *timeout_list[] = {
                    407:        TIMEOUT_IMMID,
                    408:        TIMEOUT_SOON,
                    409:        TIMEOUT_SHORT,
                    410:        TIMEOUT_MID,
                    411:        TIMEOUT_LONG,
                    412:        TIMEOUT_FOREVER
                    413: };
                    414: #else
                    415: struct timeval timeout_0s      = {0L, 0L};
                    416: #define TIMEOUT_FOREVER                (struct timeval *)0
                    417: #define TIMEOUT_NOBLOCK                &timeout_0s
                    418: #endif
                    419:
                    420: struct timeval *notimeout[] = {
                    421:        TIMEOUT_FOREVER
                    422: };
                    423:
                    424: getcharacter()
                    425: {
                    426:     char c;
                    427:     int n;
                    428:     int nfound;
                    429:     fd_set readfd, writefd, exceptfd;
                    430: #ifdef USE_TIMEOUT
                    431:     struct timeval **timeout = auto_tty_fix ? timeout_list : notimeout;
                    432: #else
                    433:     struct timeval **timeout = notimeout;
                    434: #endif
                    435:     extern int errno;
                    436:
                    437:
                    438:     /*
                    439:      * Sorry, this cording depends to an implementation of getc().
                    440:      */
                    441:     FD_ZERO(&writefd);
                    442:     FD_ZERO(&exceptfd);
                    443:
                    444: RETRY:
                    445:     readfd = selectmask;
                    446:
                    447: #ifdef STAT
                    448:     stat_nselect++;
                    449: #endif
                    450:     while ((nfound = select (selectnfds, &readfd, 0, 0, *timeout)) < 0)
                    451:        if (errno != EINTR) {
                    452:                perror ("select");
                    453:                terminate(0);
                    454:        }
                    455:
                    456:     /*
                    457:      * Found output from pty.
                    458:      */
                    459:     if (FD_ISSET(master, &readfd)) {
                    460:        int nbyte;
                    461:
                    462:        /*
                    463:         * Read from pty.
                    464:         */
                    465:        nbyte = buf_read (master, output_buffer);
                    466:
                    467:        if (nbyte > 0) {
                    468:            /*
                    469:             * Write to stdout
                    470:             */
                    471:            write (1, output_buffer->b_lastbuf, nbyte);
                    472:
                    473:            /*
                    474:             * Write to script file
                    475:             */
                    476:            if (script_fp)
                    477:                fwrite (output_buffer->b_lastbuf,
                    478:                        sizeof(CHAR), nbyte, script_fp);
                    479:
                    480: #ifdef STAT
                    481:            stat_obyte += nbyte;
                    482: #endif
                    483:        }
                    484:        else if (nbyte < 0) {
                    485:            perror ("read");
                    486: #ifdef STAT
                    487:            stat_rerror++;
                    488: #endif
                    489:        }
                    490:     }
                    491:
                    492:     /*
                    493:      * Found input from terminal
                    494:      */
                    495:     if (FD_ISSET(fileno(stdin), &readfd)) {
                    496:
                    497: #ifndef USE_TIMEOUT
                    498:        /*
                    499:         * Look slave tty mode before every input.
                    500:         * This will be done only before real input from stdin, because
                    501:         * if character remained in FILE buffer, control goes to RETURNCHAR
                    502:         * label.
                    503:         */
                    504:        if (Through == OFF && auto_tty_fix)
                    505:            (void) fix_transparency ();
                    506: #endif
                    507:
                    508:        RETURNCHAR:
                    509:        if ((c = getc (stdin)) == EOF) {
                    510:            if (debug)
                    511:                printf ("EOF chatched\n");
                    512:            terminate (0);
                    513:        }
                    514:        else
                    515:            return (c & CHARMASK);
                    516:     }
                    517:
                    518: #ifdef USE_TIMEOUT
                    519:     /*
                    520:      * In the case of timeout.
                    521:      */
                    522:     if (nfound == 0) {
                    523:
                    524:        /*
                    525:         * Only to make sure
                    526:         */
                    527:        if (!auto_tty_fix) {
                    528:            printf ("Timeout should not happen!!\n");
                    529:            timeout = notimeout;
                    530:            goto RETRY;
                    531:        }
                    532:
                    533:        (void) fix_transparency ();
                    534:        ++timeout;
                    535:
                    536:        if (debug)
                    537:            errorBell();
                    538:     }
                    539: #endif
                    540:
                    541:     goto RETRY;
                    542: }
                    543:
                    544: int set_buffer (bp, size)
                    545:     BUFFER *bp;
                    546:     int size;
                    547: {
                    548:     char *newbuf, *malloc(), *realloc();
                    549:
                    550:     if (bp->b_buf)
                    551:        newbuf = (char *) realloc (bp->b_buf, size);
                    552:     else {
                    553:        newbuf = (char *) malloc (size);
                    554:        bp->b_count = bp->b_next = 0;
                    555:     }
                    556:
                    557:     if (newbuf == 0)
                    558:        return (0);
                    559:
                    560:     bp->b_buf = newbuf;
                    561:     bp->b_max = size;
                    562:     bp->b_hiwater = size * 4 / 5;
                    563:
                    564:     if (bp->b_next > bp->b_hiwater) {
                    565:        bp->b_count = bp->b_next;
                    566:        bp->b_next = 0;
                    567:     }
                    568:     return (1);
                    569: }
                    570:
                    571: int buf_read (fd, bp)
                    572:     int fd;                    /* file discriptor */
                    573:     BUFFER *bp;                        /* buffer pointer */
                    574: {
                    575:     int nbyte;
                    576:
                    577:     /*
                    578:      * save previous next pointer
                    579:      */
                    580:     bp->b_lastbuf = bp->b_buf + bp->b_next;
                    581:
                    582:     /*
                    583:      * read from fd as possible
                    584:      */
                    585:     nbyte = read (fd, bp->b_buf + bp->b_next, bp->b_max - bp->b_next);
                    586:
                    587:     /*
                    588:      * move next read pointer
                    589:      */
                    590:     bp->b_next += nbyte;
                    591:
                    592:     /*
                    593:      * If count has not reached high-water mark, increment count
                    594:      * by read count.
                    595:      */
                    596:     if (bp->b_count < bp->b_hiwater)
                    597:        bp->b_count += nbyte;
                    598:
                    599:     /*
                    600:      * If next pointer goes further than high-water mark, discard contents
                    601:      * after next pointer, and move next pointer to buffer top.
                    602:      */
                    603:     if (bp->b_next > bp->b_hiwater) {
                    604:        bp->b_count = bp->b_next;
                    605:        bp->b_next = 0;
                    606:     }
                    607:
                    608:     return (nbyte);
                    609: }
                    610:
                    611: buf_put (bp, s)
                    612:     BUFFER *bp;                        /* buffer pointer */
                    613:     char *s;                   /* string pointer */
                    614: {
                    615:     int nbyte;
                    616:     int slen;
                    617:
                    618:     nbyte = strlen (s);
                    619:
                    620:     while (nbyte > 0) {
                    621:
                    622:        slen = min (bp->b_max - bp->b_next, nbyte);
                    623:        strncpy (bp->b_buf + bp->b_next, s, slen);
                    624:        s += slen;
                    625:        nbyte -= slen;
                    626:        bp->b_next += slen;
                    627:
                    628:        if (bp->b_count < bp->b_hiwater)
                    629:            bp->b_count += slen;
                    630:
                    631:        if (bp->b_next > bp->b_hiwater) {
                    632:            bp->b_count = bp->b_next;
                    633:            bp->b_next = 0;
                    634:        }
                    635:     }
                    636: }
                    637:
                    638: swallow_output()
                    639: {
                    640:     fd_set readfd = mastermask;
                    641:     int r;
                    642:     int nbyte;
                    643:     int ncount = 10;
                    644:
                    645:     while (
                    646:        ncount-- &&
                    647:        select (selectnfds, &readfd, 0, 0, TIMEOUT_NOBLOCK) > 0 &&
                    648:        FD_ISSET(master, &mastermask)
                    649:     ) {
                    650:        nbyte = buf_read (master, output_buffer);
                    651:        if (nbyte > 0) {
                    652:            write (1, output_buffer->b_lastbuf, nbyte);
                    653: #ifdef STAT
                    654:            stat_obyte += nbyte;
                    655:            stat_nselect++;
                    656: #endif
                    657:
                    658:            /*
                    659:             * Write to script file
                    660:             */
                    661:            if (script_fp)
                    662:                fwrite (output_buffer->b_lastbuf,
                    663:                        sizeof(CHAR), nbyte, script_fp);
                    664:        }
                    665:        else if (nbyte < 0) {
                    666:            perror ("read");
                    667: #ifdef STAT
                    668:            stat_rerror++;
                    669: #endif
                    670:        }
                    671:     }
                    672:     return;
                    673: }
                    674:
                    675: #include <sys/wait.h>
                    676: #ifdef AIX
                    677: #include <sys/m_wait.h>
                    678: #endif
                    679:
1.5     ! ohara     680: #if defined(__INTERIX)
        !           681: #define wait3(s,opt,rp)   (waitpid((-1),(s),(opt)))
        !           682: #endif
        !           683:
1.1       noro      684: void
                    685: catchsig(n)
                    686:     int n;
                    687: {
                    688:     int status;
                    689:     struct rusage   ru;
                    690:
                    691:     if (wait3 (&status, WNOHANG | WUNTRACED, &ru) != child_pid)
                    692:        return;
                    693:     if (WIFSTOPPED (status) /* || WIFSIGNALED (status) */) {
                    694:        if (debug) {
                    695:            message ("Child has sttoped!!\n");
                    696:        }
                    697:        suspend ();
                    698:        return;
                    699:     }
                    700:     terminate (0);
                    701: }
                    702:
                    703: exec_to_command(argv)
                    704:     char *argv[];
                    705: {
                    706:     int t;
                    707:
                    708:     /*
                    709:      * Disconnect control terminal
                    710:      */
                    711:     t = open ("/dev/tty", 2);
                    712:     if (t >= 0) {
1.5     ! ohara     713: #if !defined(__CYGWIN32__) && !defined(__INTERIX)
1.1       noro      714:        ioctl (t, TIOCNOTTY, (char *) 0);
                    715: #endif
                    716:        (void) close (t);
                    717:     }
                    718:
                    719:     get_pty_slave ();
                    720:
                    721:     (void) close (master);
                    722:     dup2 (slave, 0);
                    723:     dup2 (slave, 1);
                    724:     dup2 (slave, 2);
                    725:     (void) close (slave);
                    726:
                    727: #ifdef TERMIOS
                    728:     tcsetattr(0, TCSANOW, &slave_ttymode);
                    729: #elif defined(TIOCSETN)
                    730:     ioctl (0, TIOCSETN, (char *) & slave_ttymode);
                    731: #endif
1.5     ! ohara     732: #if defined(__INTERIX)
        !           733:     execvp (*argv, argv);
        !           734: #else
1.1       noro      735:     execvp (*argv, argv, 0);
1.5     ! ohara     736: #endif
1.1       noro      737:     perror (*argv);
                    738:     exit (1);
                    739: }
                    740:
                    741: #ifdef TERMIOS
                    742: fix_tty()
                    743: {
                    744:     int i;
                    745:     master_ttymode = initial_ttymode;
                    746:     slave_ttymode = initial_ttymode;
                    747:     master_ttymode.c_lflag &= ~(ECHO|ECHOE|ECHOK|ICANON);
                    748:
                    749:     for (i = 0; i < NCCS; i++)
                    750:        master_ttymode.c_cc[i] = _POSIX_VDISABLE;
                    751:
                    752:     master_ttymode.c_cc[VMIN] = 1;
                    753:     master_ttymode.c_cc[VTIME] = 0;
                    754:     slave_ttymode.c_lflag &= ~(ECHO|ECHOE|ECHOK);
                    755:     slave_ttymode.c_iflag &= ~(ICRNL);
                    756:     slave_ttymode.c_oflag &= ~(ONLCR);
                    757:     tcsetattr(0, TCSANOW, &master_ttymode);
                    758: }
                    759:
                    760: #elif defined(TIOCSETN)
                    761:
                    762: fix_tty()
                    763: {
                    764:     struct tchars tcbuf;
                    765:     struct ltchars lcbuf;
                    766:
                    767:     master_ttymode = initial_ttymode;
                    768:     slave_ttymode = initial_ttymode;
                    769:     tcbuf = tchars_buf;
                    770:     lcbuf = ltchars_buf;
                    771:
                    772:     master_ttymode.sg_flags |= CBREAK;
                    773:     master_ttymode.sg_flags &= ~ECHO;
                    774:
                    775:     slave_ttymode.sg_erase = -1;
                    776:     slave_ttymode.sg_kill = -1;
                    777:     slave_ttymode.sg_flags &= ~(ECHO|CRMOD);
                    778:
                    779:     tcbuf.t_intrc = -1;
                    780:     tcbuf.t_quitc = -1;
                    781: #ifdef AIX
                    782:     tcbuf.t_eofc = 0;
                    783: #else
                    784:     tcbuf.t_eofc = -1;
                    785: #endif
                    786:     tcbuf.t_brkc = -1;
                    787:
                    788:     lcbuf.t_suspc = -1;
                    789:     lcbuf.t_dsuspc = -1;
                    790:     lcbuf.t_rprntc = -1;
                    791:     lcbuf.t_flushc = -1;
                    792:     lcbuf.t_werasc = -1;
                    793:     lcbuf.t_lnextc = -1;
                    794:
                    795:     ioctl (0, TIOCSETN, (char *) & master_ttymode);
                    796:     ioctl (0, TIOCSETC, (char *) & tcbuf);
                    797:     ioctl (0, TIOCSLTC, (char *) & lcbuf);
                    798: }
                    799: #endif
                    800:
                    801: kill_process()
                    802: {
                    803:
                    804:     if (child_pid)
                    805:        (void) killpg (child_pid, SIGTERM);
                    806: }
                    807:
                    808: void
                    809: terminate(n)
                    810:     int n;
                    811: {
                    812:     extern int errno;
                    813:
                    814:     /*
                    815:      * Save history if 'history-file' is set
                    816:      */
                    817:     {
                    818:        char *cp, *mk_home_relative(), *look_var();
                    819:        char buf [256];
                    820:        int num;
                    821:
                    822:        if (look_var ("savehist") && (cp = look_var ("history-file"))) {
                    823:
                    824:            num = lookd_var ("savehist");
                    825:            strcpy (buf, mk_home_relative (cp));
                    826:            save_history (buf, num);
                    827:        }
                    828:     }
                    829:
                    830:     /*
                    831:      * If scripting, close script file.
                    832:      */
                    833:     if (script_fp)
                    834:        fclose (script_fp);
                    835:
                    836:     (void) signal (SIGCHLD, SIG_IGN);
                    837:     if (killpg (child_pid, SIGTERM) < 0 && errno != ESRCH)
                    838:        if (killpg (child_pid, SIGHUP) < 0)
                    839:            if (killpg (child_pid, SIGKILL) < 0)
                    840:                perror ("kill");
                    841:
                    842: #ifdef TERMIOS
                    843:     tcsetattr(0, TCSANOW, &initial_ttymode);
                    844: #elif defined(TIOCSETN)
                    845:     ioctl (0, TIOCSETN, (char *) & initial_ttymode);
                    846:     ioctl (0, TIOCSETC, (char *) & tchars_buf);
                    847:     ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
                    848: #endif
                    849:     exit (0);
                    850: }
                    851:
                    852: send_int_sig() {
                    853: #ifndef __CYGWIN__
                    854:     kill(child_pid,SIGINT);
                    855: #endif
                    856:        return 0;
                    857: }
                    858:
                    859: get_pty_master()
                    860: {
                    861:     char    c;
                    862:     struct stat stb;
                    863:     int     i;
                    864:
                    865:     if (ptyflag == 0) {
                    866:        master = 1;
                    867:        return;
                    868:     }
                    869: #ifdef __CYGWIN32__
1.2       noro      870:     sprintf (master_tty, "/dev/ptmx");
                    871:     master = open (master_tty, O_RDWR);
                    872:     if (master >= 0) {
                    873:        char *name;
                    874:        name = (char *)ptsname(master);
                    875:        if ( name != 0 ) {
                    876:            strcpy(slave_tty, name);
1.1       noro      877:            goto FOUND;
                    878:        }
                    879:     }
                    880: #else
                    881:     for (c = 'p'; c <= 's'; c++) {
                    882:        for (i = 0; i < 16; i++) {
                    883:            sprintf (master_tty, "/dev/pty%c%x", c, i);
                    884:            master = open (master_tty, O_RDWR);
                    885:            if (master >= 0) {
                    886:                sprintf (slave_tty, "/dev/tty%c%x", c, i);
                    887:                goto FOUND;
                    888:            }
                    889:        }
                    890:     }
                    891: #endif
                    892:     /*
                    893:      * Can't get master tty
                    894:      */
                    895:     if (master < 0) {
                    896:        fprintf (stderr, "Couldn't open pseudo tty\n");
                    897:        kill_process ();
                    898:        exit (1);
                    899:     }
                    900:
                    901:  FOUND:
                    902: #ifdef TERMIOS
                    903:     tcgetattr(0, &initial_ttymode);
                    904: #elif defined(TIOCSETN)
                    905:     ioctl (0, TIOCGETP, (char *) &initial_ttymode);
                    906:     ioctl (0, TIOCGETC, (char *) &tchars_buf);
                    907:     ioctl (0, TIOCGETD, (char *) &line_desc);
                    908:     ioctl (0, TIOCGLTC, (char *) &ltchars_buf);
                    909:     ioctl (0, TIOCLGET, (char *) &lmode_buf);
                    910: #endif
                    911:
                    912: #ifdef TIOCGWINSZ
                    913:     {
                    914:        struct winsize win;
                    915:
                    916:        if (ioctl (0, TIOCGWINSZ, &win) >= 0) {
                    917:            lines = win.ws_row;
                    918:            columns = win.ws_col;
                    919:        }
                    920:     }
                    921: #endif
                    922:
                    923: #ifdef KANJI
                    924: # if defined(TIOCKGET) && defined(TIOCKSET)
                    925:     ioctl (0, TIOCKGET, (char *) &kmode_buf);
                    926: # endif
                    927: # if defined(TIOCKGETC) && defined(TIOCKSETC)
                    928:     ioctl (0, TIOCKGETC, (char *) &jtchars_buf);
                    929: # endif
                    930: #endif /* KANJI */
                    931:
                    932:     FD_ZERO(&stdinmask);
                    933:     FD_ZERO(&mastermask);
                    934:     FD_ZERO(&selectmask);
                    935:     FD_SET(fileno(stdin), &stdinmask);
                    936:     FD_SET(master, &mastermask);
                    937:     FD_SET(fileno(stdin), &selectmask);
                    938:     FD_SET(master, &selectmask);
                    939:     selectnfds = max (fileno(stdin), master) + 1;
                    940:
                    941:     return;
                    942: }
                    943:
                    944: get_pty_slave()
                    945: {
                    946:
                    947:     slave = open (slave_tty, 2);
                    948:     if (slave < 0) {
                    949:        perror (slave_tty);
                    950:        exit (1);
                    951:     }
                    952: #ifdef TERMIOS
                    953:     tcsetattr(slave, TCSANOW, &initial_ttymode);
                    954: #elif defined(TIOCSETN)
                    955:     ioctl (slave, TIOCSETN, (char *) &initial_ttymode);
                    956:     ioctl (slave, TIOCSETC, (char *) &tchars_buf);
                    957:     ioctl (slave, TIOCSLTC, (char *) &ltchars_buf);
                    958:     ioctl (slave, TIOCLSET, (char *) &lmode_buf);
                    959:     ioctl (slave, TIOCSETD, (char *) &line_desc);
                    960: #endif
                    961:
                    962: #ifdef KANJI
                    963: # if defined(TIOCKGET) && defined(TIOCKSET)
                    964:     ioctl (slave, TIOCKSET, (char *) &kmode_buf);
                    965: # endif
                    966: # if defined(TIOCKGETC) && defined(TIOCKSETC)
                    967:     ioctl (slave, TIOCKSETC, (char *) &jtchars_buf);
                    968: # endif
                    969: #endif /* KANJI */
                    970:
                    971: #ifdef TIOCSWINSZ
                    972:     {
                    973:        struct winsize win;
                    974:
                    975:        win.ws_row = lines;
                    976:        win.ws_col = columns;
                    977:        (void) ioctl (slave, TIOCSWINSZ, &win);
                    978:     }
                    979: #endif
                    980: }
                    981:
                    982: recover_tty()
                    983: {
                    984: #ifdef TERMIOS
                    985:     tcsetattr(0, TCSANOW, &initial_ttymode);
                    986: #elif defined(TIOCSETN)
                    987:     ioctl (0, TIOCSETN, (char *) & initial_ttymode);
                    988:     ioctl (0, TIOCSETC, (char *) & tchars_buf);
                    989:     ioctl (0, TIOCSLTC, (char *) & ltchars_buf);
                    990: #endif
                    991: }
                    992:
                    993: suspend()
                    994: {
                    995:     long       pid;
1.3       noro      996: #if defined(sun)
                    997:     void       (*func) (int);
                    998: #else
1.1       noro      999:     void       (*func) __P((int));
1.3       noro     1000: #endif
1.1       noro     1001: #ifndef __CYGWIN32__
                   1002:     int                omask;
                   1003: #endif
                   1004:     extern int errno;
                   1005:
                   1006:     pid = getpid ();
                   1007:  /* reset signal handler so kill below stops us */
                   1008:     func = signal (SIGCHLD, SIG_IGN);
                   1009:     signal (SIGTSTP, SIG_DFL);
                   1010:     recover_tty();
                   1011: #define        mask(s) (1 << ((s)-1))
1.3       noro     1012: #if !defined(__CYGWIN32__) && !defined(sun)
1.1       noro     1013:     omask = sigsetmask (sigblock (0) & ~mask (SIGTSTP));
                   1014: #endif
                   1015:     kill (0, SIGTSTP);
                   1016:
                   1017:     if (kill (child_pid, SIGCONT) < 0 && errno == ESRCH) {
                   1018:        printf ("Where my child has gone?!\n");
                   1019:        terminate (0);
                   1020:     }
                   1021:     killpg (child_pid, SIGCONT);
                   1022:     kill (0, SIGCONT);
                   1023:     signal (SIGCHLD, func);
                   1024:     signal (SIGTSTP, SIG_IGN);
1.3       noro     1025: #if !defined(__CYGWIN32__) && !defined(sun)
1.1       noro     1026:     sigblock (mask (SIGTSTP));
                   1027: #endif
                   1028:     fix_tty ();
                   1029:     if (look_var ("auto-repaint"))
                   1030:        fep_repaint(0);
                   1031: }
                   1032:
                   1033: look_cmdinfo (command)
                   1034:     char *command;
                   1035: {
                   1036:     struct cmdinfo *p;
                   1037:     char *allocAndCopyThere();
                   1038:
                   1039:     if (strcmp (prompt, "") != 0)
                   1040:        return;
                   1041:
                   1042:     for (p = cmdinfo_tab; p->command; p++) {
                   1043:        if (strcmp (command, p->command) == 0) {
                   1044:            prompt = allocAndCopyThere (p->prompt);
                   1045:            set_var ("prompt", p->prompt);
                   1046:            set_var ("delimiters", p->delimiters);
                   1047:            break;
                   1048:        }
                   1049:     }
                   1050: }
                   1051:
                   1052:
                   1053: usageAndExit()
                   1054: {
                   1055:
                   1056:     printf ("Usage: %s [-emacs|-vi] command\n", myself);
                   1057:     exit (1);
                   1058: }
                   1059:
                   1060: #ifdef SIGWINCH
                   1061: /*
                   1062:  * Propagate window size changes to the slave tty.
                   1063:  */
1.4       ohara    1064: void sigwinch(int dummy)
1.1       noro     1065: {
                   1066: #ifdef TIOCGWINSZ                      /* 4.3BSD */
                   1067:     struct winsize win;
                   1068:
                   1069:     if (ioctl (0, TIOCGWINSZ, (char *)&win) >= 0) {
                   1070:        (void) ioctl (slave, TIOCSWINSZ, (char *)&win);
                   1071:        set_var ("crt", itoa (win.ws_row));
                   1072:        set_var ("showhist", itoa (win.ws_row - 1));
                   1073:     }
                   1074: #else
                   1075: #ifdef TIOCGSIZE                       /* SONY NEWS OS2.2 */
                   1076:     struct ttysize win;
                   1077:
                   1078:     if (ioctl(0, TIOCGSIZE, (char *)&win) >= 0) {
                   1079:        (void) ioctl(slave, TIOCSSIZE, (char *)&win);
                   1080:        set_var ("crt", itoa (win.ts_lines));
                   1081:        set_var ("showhist", itoa (win.ts_lines - 1));
                   1082:     }
                   1083: #endif /* TIOCGWINSZ */
                   1084: #endif /* TIOCGSIZE */
                   1085: }
                   1086: #endif /* SIGWINCH */

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>