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

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

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