Annotation of 43BSDTahoe/new/kermit/ckutio.c, revision 1.1.1.1

1.1       root        1: char *ckxv = "Unix tty I/O, 4C(037), 31 Jul 85";
                      2: 
                      3: /*  C K U T I O  */
                      4: 
                      5: /* C-Kermit interrupt, terminal control & i/o functions for Unix systems */
                      6: 
                      7: /*
                      8:  Author: Frank da Cruz (SY.FDC@CU20B),
                      9:  Columbia University Center for Computing Activities, January 1985.
                     10:  Copyright (C) 1985, Trustees of Columbia University in the City of New York.
                     11:  Permission is granted to any individual or institution to use, copy, or
                     12:  redistribute this software so long as it is not sold for profit, provided this
                     13:  copyright notice is retained. 
                     14: */
                     15: /* Includes for all Unixes (conditional includes come later) */
                     16: 
                     17: #include <sys/types.h>                 /* Types */
                     18: #include <sys/dir.h>                   /* Directory */
                     19: #include <ctype.h>                     /* Character types */
                     20: #include <stdio.h>                     /* Unix Standard i/o */
                     21: #include <signal.h>                    /* Interrupts */
                     22: #include <setjmp.h>                    /* Longjumps */
                     23: #include "ckcdeb.h"                    /* Typedefs, formats for debug() */
                     24: 
                     25: /* Maximum length for the name of a tty device */
                     26: 
                     27: #ifndef DEVNAMLEN
                     28: #define DEVNAMLEN 25
                     29: #endif
                     30: 
                     31: /* 4.1 BSD support added by Charles E. Brooks, EDN-VAX */
                     32: /* Fortune 16:32 For:Pro 1.7 support mostly like 4.1, added by J-P Dumas */
                     33: 
                     34: #ifdef BSD4
                     35: #define ANYBSD
                     36: #undef DIRSIZ
                     37: #define DIRSIZ (sizeof(struct direct))
                     38: #ifdef MAXNAMLEN
                     39: #define BSD42
                     40: char *ckxsys = " 4.2 BSD";
                     41: #else
                     42: #ifdef FT17
                     43: #define BSD41
                     44: char *ckxsys = " For:Pro Fortune 1.7";
                     45: #else
                     46: #define BSD41
                     47: #ifndef C70
                     48: char *ckxsys = " 4.1 BSD";
                     49: #endif
                     50: #endif
                     51: #endif
                     52: #endif
                     53: 
                     54: /* 2.9bsd support contributed by Bradley Smith, UCLA */
                     55: #ifdef BSD29
                     56: #define ANYBSD
                     57: char *ckxsys = " 2.9 BSD";
                     58: #endif
                     59: 
                     60: /*
                     61:  Version 7 UNIX support contributed by Gregg Wonderly,
                     62:  Oklahoma State University:  [email protected]
                     63: */
                     64: #ifdef V7
                     65: char *ckxsys = " Version 7 UNIX (tm)";
                     66: #endif V7
                     67: 
                     68: /* BBN C70 support from Frank Wancho, WANCHO@SIMTEL20 */
                     69: #ifdef C70
                     70: char *ckxsys = " BBN C/70";
                     71: #endif
                     72: 
                     73: /* Amdahl UTS 2.4 (v7 derivative) for IBM 370 series compatible mainframes */
                     74: /* Contributed by Garard Gaye, Jean-Pierre Dumas, DUMAS@SUMEX-AIM. */
                     75: #ifdef UTS24
                     76: char *ckxsys = " Amdahl UTS 2.4";
                     77: #endif
                     78: 
                     79: /* Pro/Venix Version 1.x support from Columbia U. */
                     80: #ifdef PROVX1
                     81: char *ckxsys = " Pro-3xx Venix v1";
                     82: #endif
                     83: 
                     84: /* Tower support contributed by John Bray, Auburn, Alabama */
                     85: #ifdef TOWER1
                     86: char *ckxsys = " NCR Tower 1632, OS 1.02";
                     87: #endif
                     88: 
                     89: /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */
                     90: #ifdef UXIII
                     91: #ifdef XENIX
                     92: char *ckxsys = " Xenix/286";
                     93: #else
                     94: #ifdef PCIX
                     95: char *ckxsys = " PC/IX";
                     96: #else
                     97: #ifdef ISIII
                     98: char *ckxsys = " Interactive Systems Corp System III";
                     99: #else
                    100: char *ckxsys = " AT&T System III/System V";
                    101: #endif
                    102: #endif
                    103: #endif
                    104: #endif
                    105: 
                    106: /* Features... */
                    107: 
                    108: /* Do own buffering, using unbuffered read() calls... */
                    109: #ifdef UXIII
                    110: #define MYREAD
                    111: #endif
                    112: 
                    113: #ifdef BSD42
                    114: #define MYREAD
                    115: #endif
                    116: 
                    117: /*
                    118:  Note - KERLD is the Berkeley Unix Berknet line driver, modified to pass
                    119:  through all 8  bits, and to allow an arbitrary break character to be set.
                    120:  Don't define this symbol unless you have made this modification to your
                    121:  4.2BSD kernel!
                    122: */
                    123: #ifdef BSD4
                    124: /* #define KERLD */  /* <-- note, commented out */
                    125: #endif
                    126: 
                    127: /*
                    128:  Variables available to outside world:
                    129: 
                    130:    dftty  -- Pointer to default tty name string, like "/dev/tty".
                    131:    dfloc  -- 0 if dftty is console, 1 if external line.
                    132:    dfprty -- Default parity
                    133:    dfflow -- Default flow control
                    134:    ckxech -- Flag for who echoes console typein:
                    135:      1 - The program (system echo is turned off)
                    136:      0 - The system (or front end, or terminal).
                    137:    functions that want to do their own echoing should check this flag
                    138:    before doing so.
                    139: 
                    140:    flfnam -- Name of lock file, including its path, e.g.,
                    141:                "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
                    142:    hasLock -- Flag set if this kermit established a uucp lock.
                    143:    inbufc -- number of tty line rawmode unread characters 
                    144:                (system III/V unixes)
                    145:    backgrd -- Flag indicating program executing in background ( & on 
                    146:                end of shell command). Used to ignore INT and QUIT signals.
                    147: 
                    148:  Functions for assigned communication line (either external or console tty):
                    149: 
                    150:    sysinit()               -- System dependent program initialization
                    151:    ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access.
                    152:    ttclos()                -- Close & reset the tty, releasing any access lock.
                    153:    ttpkt(speed,flow)       -- Put the tty in packet mode and set the speed.
                    154:    ttvt(speed,flow)        -- Put the tty in virtual terminal mode.
                    155:                                or in DIALING or CONNECTED modem control state.
                    156:    ttinl(dest,max,timo)    -- Timed read line from the tty.
                    157:    ttinc(timo)             -- Timed read character from tty.
                    158:    myread()               -- System 3 raw mode bulk buffer read, gives
                    159:                           --   subsequent chars one at a time and simulates
                    160:                           --   FIONREAD!
                    161:    myunrd(c)              -- Places c back in buffer to be read (one only)
                    162:    ttchk()                 -- See how many characters in tty input buffer.
                    163:    ttxin(n,buf)            -- Read n characters from tty (untimed).
                    164:    ttol(string,length)     -- Write a string to the tty.
                    165:    ttoc(c)                 -- Write a character to the tty.
                    166:    ttflui()                -- Flush tty input buffer.
                    167: 
                    168:    ttlock(ttname)         -- Lock against uucp collisions (Sys III)
                    169:    ttunlck()              -- Unlock "       "     "
                    170:    look4lk(ttname)        -- Check if a lock file exists
                    171: */
                    172: 
                    173: /*
                    174: Functions for console terminal:
                    175: 
                    176:    congm()   -- Get console terminal modes.
                    177:    concb(esc) -- Put the console in single-character wakeup mode with no echo.
                    178:    conbin(esc) -- Put the console in binary (raw) mode.
                    179:    conres()  -- Restore the console to mode obtained by congm().
                    180:    conoc(c)  -- Unbuffered output, one character to console.
                    181:    conol(s)  -- Unbuffered output, null-terminated string to the console.
                    182:    conola(s) -- Unbuffered output, array of strings to the console.
                    183:    conxo(n,s) -- Unbuffered output, n characters to the console.
                    184:    conchk()  -- Check if characters available at console (bsd 4.2).
                    185:                Check if escape char (^\) typed at console (System III/V).
                    186:    coninc(timo)  -- Timed get a character from the console.
                    187:    conint()  -- Enable terminal interrupts on the console if not background.
                    188:    connoi()  -- Disable terminal interrupts on the console if not background.
                    189: 
                    190: Time functions
                    191: 
                    192:    msleep(m) -- Millisecond sleep
                    193:    ztime(&s) -- Return pointer to date/time string
                    194:    rtimer() --  Reset timer
                    195:    gtimer()  -- Get elapsed time since last call to rtimer()
                    196: */
                    197: 
                    198: /* Conditional Includes */
                    199: 
                    200: #ifdef FT17
                    201: #include <sys/file.h>                  /* File information */
                    202: #endif
                    203: 
                    204: #ifndef PROVX1
                    205: #include <sys/file.h>                  /* File information */
                    206: #endif
                    207: 
                    208: /* System III, System V */
                    209: 
                    210: #ifdef UXIII
                    211: #include <termio.h>
                    212: #include <sys/ioctl.h>
                    213: #include <fcntl.h>                     /* directory reading for locking */
                    214: #include <errno.h>                     /* error numbers for system returns */
                    215: #endif
                    216: 
                    217: /* Not Sys III/V */
                    218: 
                    219: #ifndef UXIII
                    220: #include <sgtty.h>                     /* Set/Get tty modes */
                    221: #ifndef PROVX1
                    222: #ifndef V7
                    223: #ifndef BSD41
                    224: #include <sys/time.h>                  /* Clock info (for break generation) */
                    225: #endif
                    226: #endif
                    227: #endif
                    228: #endif
                    229: 
                    230: #ifdef BSD41
                    231: #include <sys/timeb.h>                 /* BSD 4.1 ... ceb */
                    232: #endif
                    233: 
                    234: #ifdef TOWER1
                    235: #include <sys/timeb.h>                 /* Clock info for NCR Tower */
                    236: #endif
                    237: 
                    238: /* Declarations */
                    239: 
                    240: long time();                           /* All Unixes should have this... */
                    241: extern int errno;                      /* System call error return */
                    242: 
                    243: /* Special stuff for V7 input buffer peeking */
                    244: 
                    245: #ifdef V7
                    246: int kmem[2] = { -1, -1};
                    247: char *initrawq(), *qaddr[2]={0,0};
                    248: #define CON 0
                    249: #define TTY 1
                    250: #endif
                    251: 
                    252: /* dftty is the device name of the default device for file transfer */
                    253: /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
                    254: 
                    255: #ifdef PROVX1
                    256:     char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
                    257:     int dfloc = 1;                 /* that goes in local mode by default */
                    258: #else
                    259:     char *dftty = CTTNAM;              /* Remote by default, use normal */
                    260:     int dfloc = 0;                     /* controlling terminal name. */
                    261: #endif
                    262: 
                    263:     int dfprty = 0;                    /* Parity (0 = none) */
                    264:     int dfflow = 1;                    /* Xon/Xoff flow control */
                    265:     int backgrd = 0;                   /* Assume in foreground (no '&' ) */
                    266: 
                    267: int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
                    268: 
                    269: /* Declarations of variables global within this module */
                    270: 
                    271: static long tcount;                    /* Elapsed time counter */
                    272: 
                    273: static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */
                    274: 
                    275: static jmp_buf sjbuf, jjbuf;           /* Longjump buffer */
                    276: static int lkf = 0,                    /* Line lock flag */
                    277:     conif = 0,                         /* Console interrupts on/off flag */
                    278:     cgmf = 0,                          /* Flag that console modes saved */
                    279:     xlocal = 0,                                /* Flag for tty local or remote */
                    280:     ttyfd = -1;                                /* TTY file descriptor */
                    281: static char escchr;                    /* Escape or attn character */
                    282: 
                    283: /* Special line discipline, 4.2bsd only, and only with kernel mods... */
                    284: #ifdef KERLD
                    285:     static int kerld = 1;              /* Special Kermit line discipline... */
                    286:     struct tchars oldc, newc;          /* Special characters */
                    287:     int ld = NETLDISC;                 /* Really a hack to "Berknet" l.d. */
                    288:     int oldld;                         /* Old discipline */
                    289: #else
                    290:     static int kerld = 0;              /* Not selected, no special l.d. */
                    291: #endif
                    292: 
                    293: #ifdef BSD42
                    294:     static struct timeval tv;          /* For getting time, from sys/time.h */
                    295:     static struct timezone tz;
                    296: #endif
                    297: 
                    298: #ifdef BSD29
                    299:     static struct timeval tv;          /* For getting time, from sys/time.h */
                    300:     static struct timezone tz;         /* Same as 4.2 */
                    301: #endif
                    302: 
                    303: #ifdef BSD41
                    304:     static long clock;                 /* For getting time from sys/time.h */
                    305:     static struct timeb ftp;           /* And from sys/timeb.h */
                    306: #endif
                    307: 
                    308: #ifdef TOWER1
                    309: static long clock;                     /* For getting time from sys/time.h */
                    310: static struct timeb ftp;               /* And from sys/timeb.h */
                    311: #endif
                    312: 
                    313: #ifdef V7
                    314: static long clock;
                    315: #endif
                    316: 
                    317: #ifdef UXIII
                    318:   static struct termio                         /* sgtty info... */
                    319:     ttold, ttraw, tttvt,               /* for communication line */
                    320:     ccold, ccraw, cccbrk;              /* and for console */
                    321: #else
                    322:   static struct sgttyb                         /* sgtty info... */
                    323:     ttold, ttraw, tttvt, ttbuf,                /* for communication line */
                    324:     ccold, ccraw, cccbrk;              /* and for console */
                    325: #endif
                    326: 
                    327: static char flfnam[80];                        /* uucp lock file path name */
                    328: static int hasLock = 0;                        /* =1 if this kermit locked uucp */
                    329: static int inbufc = 0;                 /* stuff for efficient SIII raw line */
                    330: static int ungotn = -1;                        /* pushback to unread character */
                    331: static int conesc = 0;                 /* set to 1 if esc char (^\) typed */
                    332: 
                    333: static int ttlock();                   /* definition of ttlock subprocedure */
                    334: static int ttunlck();                  /* and unlock subprocedure */
                    335: static char ttnmsv[DEVNAMLEN];         /* copy of open path for tthang */
                    336: 
                    337: /*  S Y S I N I T  --  System-dependent program initialization.  */
                    338: 
                    339: sysinit() {
                    340: 
                    341: /* for now, nothing... */
                    342: 
                    343: }
                    344: 
                    345: /*  T T O P E N  --  Open a tty for exclusive access.  */
                    346: 
                    347: /*  Returns 0 on success, -1 on failure.  */
                    348: /*
                    349:   If called with lcl < 0, sets value of lcl as follows:
                    350:   0: the terminal named by ttname is the job's controlling terminal.
                    351:   1: the terminal named by ttname is not the job's controlling terminal.
                    352:   But watch out: if a line is already open, or if requested line can't
                    353:   be opened, then lcl remains (and is returned as) -1.
                    354: */
                    355: ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; {
                    356: 
                    357: #ifdef UXIII
                    358:     char *ctermid();                   /* Wish they all had this! */
                    359: #endif
                    360:     char *x; extern char* ttyname();
                    361:     char cname[DEVNAMLEN];
                    362: 
                    363:     if (ttyfd > -1) return(0);         /* If already open, ignore this call */
                    364:     xlocal = *lcl;                     /* Make this available to other fns */
                    365: 
                    366: #ifndef UXIII
                    367:     ttyfd = open(ttname,2);            /* Try to open for read/write */
                    368: #else
                    369:     /* if modem connection, don't wait for carrier */
                    370:     ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) );
                    371: #endif
                    372: 
                    373:     if (ttyfd < 0) {                   /* If couldn't open, fail. */
                    374:        return(-1);
                    375:     }
                    376:     strncpy(ttnmsv,ttname,DEVNAMLEN);  /* Open, keep copy of name locally. */
                    377: 
                    378: /* Caller wants us to figure out if line is controlling tty */
                    379: 
                    380:     debug(F111,"ttopen",ttname,*lcl);
                    381:     if (*lcl == -1) {
                    382:        if (strcmp(ttname,CTTNAM) == 0) {   /* "/dev/tty" always remote */
                    383:            debug(F110," Same as CTTNAM",ttname,0);
                    384:            xlocal = 0;
                    385:        } else if (isatty(0)) {         /* Else, if stdin not redirected */
                    386:            x = ttyname(0);             /* then compare its device name */
                    387:            strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */
                    388:            debug(F110," ttyname(0)",x,0);
                    389:            x = ttyname(ttyfd);         /* ...with real name of ttname. */
                    390:            xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
                    391:            debug(F111," ttyname",x,xlocal);
                    392:        } else {                        /* Else, if stdin redirected... */
                    393: #ifdef UXIII
                    394: /* Sys III/V provides nice ctermid() function to get name of controlling tty */
                    395:            ctermid(cname);             /* Get name of controlling terminal */
                    396:            debug(F110," ctermid",cname,0);
                    397:            x = ttyname(ttyfd);         /* Compare with name of comm line. */
                    398:            xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1;
                    399:            debug(F111," ttyname",x,xlocal);
                    400: #else
                    401: /* Just assume local, so "set speed" and similar commands will work */
                    402: /* If not really local, how could it work anyway?... */
                    403:            xlocal = 1;
                    404:            debug(F101," redirected stdin","",xlocal);
                    405: #endif
                    406:         }
                    407:     }    
                    408: 
                    409: /* Now check if line is locked -- if so fail, else lock for ourselves */
                    410: 
                    411:     lkf = 0;                           /* Check lock */
                    412:     if (xlocal > 0) {
                    413:        if (ttlock(ttname) < 0) {
                    414:            fprintf(stderr,"Exclusive access to %s denied\n",ttname);
                    415:            close(ttyfd); ttyfd = -1;
                    416:            debug(F110," Access denied by lock",ttname,0);
                    417:            return(-1);                 /* Not if already locked */
                    418:        } else lkf = 1;
                    419:     }
                    420: 
                    421: /* Got the line, now set the desired value for local. */
                    422: 
                    423:     if (*lcl < 0) *lcl = xlocal;
                    424: 
                    425: /* Some special stuff for v7... */
                    426: 
                    427: #ifdef V7
                    428:        if (kmem[TTY] < 0) {    /*  If open, then skip this.  */
                    429:                qaddr[TTY] = initrawq(ttyfd);   /* Init the queue. */
                    430:                if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
                    431:                        fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
                    432:                        perror("/dev/kmem");
                    433:                        exit(1);
                    434:                }
                    435:        }
                    436: #endif V7
                    437: 
                    438: /* Request exclusive access on systems that allow it. */
                    439: 
                    440: #ifndef XENIX
                    441: /* Xenix exclusive access prevents open(close(...)) from working... */
                    442: #ifdef TIOCEXCL
                    443:        if (ioctl(ttyfd,TIOCEXCL, NULL) < 0)
                    444:            fprintf(stderr,"Warning, problem getting exclusive access\n");
                    445: #endif
                    446: #endif
                    447: 
                    448: /* Get tty device settings */
                    449: 
                    450: #ifndef UXIII
                    451:     gtty(ttyfd,&ttold);                        /* Get sgtty info */
                    452:     gtty(ttyfd,&ttraw);                        /* And a copy of it for packets*/
                    453:     gtty(ttyfd,&tttvt);                        /* And one for virtual tty service */
                    454: #else
                    455:     ioctl(ttyfd,TCGETA,&ttold);                /* Same deal for Sys III, Sys V */
                    456:     ioctl(ttyfd,TCGETA,&ttraw);
                    457:     ioctl(ttyfd,TCGETA,&tttvt);
                    458: #endif
                    459:     debug(F101,"ttopen, ttyfd","",ttyfd);
                    460:     debug(F101," lcl","",*lcl);
                    461:     debug(F111," lock file",flfnam,lkf);
                    462:     return(0);
                    463: }
                    464: 
                    465: /*  T T C L O S  --  Close the TTY, releasing any lock.  */
                    466: 
                    467: ttclos() {
                    468:     if (ttyfd < 0) return(0);          /* Wasn't open. */
                    469:     if (xlocal) {
                    470:        if (tthang())                   /* Hang up phone line */
                    471:            fprintf(stderr,"Warning, problem hanging up the phone\n");
                    472:        if (ttunlck())                  /* Release uucp-style lock */
                    473:            fprintf(stderr,"Warning, problem releasing lock\n");
                    474:     }
                    475:     ttres();                           /* Reset modes. */
                    476: /* Relinquish exclusive access if we might have had it... */
                    477: #ifndef XENIX
                    478: #ifdef TIOCEXCL
                    479: #ifdef TIOCNXCL
                    480:     if (ioctl(ttyfd, TIOCNXCL, NULL) < 0)
                    481:        fprintf(stderr,"Warning, problem relinquishing exclusive access\n");
                    482: #endif
                    483: #endif
                    484: #endif
                    485:     close(ttyfd);                      /* Close it. */
                    486:     ttyfd = -1;                                /* Mark it as closed. */
                    487:     return(0);
                    488: }
                    489: 
                    490: /*  T T H A N G -- Hangup phone line */
                    491: 
                    492: tthang() {
                    493: #ifdef UXIII
                    494:     unsigned short ttc_save;
                    495: #endif
                    496: 
                    497:     if (ttyfd < 0) return(0);          /* Not open. */
                    498: #ifdef ANYBSD
                    499:     ioctl(ttyfd,TIOCCDTR,0);           /* Clear DTR */
                    500:     msleep(500);                       /* Let things settle */
                    501:     ioctl(ttyfd,TIOCSDTR,0);           /* Restore DTR */
                    502: #endif
                    503: #ifdef UXIII
                    504:     ttc_save = ttraw.c_cflag;
                    505:     ttraw.c_cflag &= ~CBAUD;           /* swa: set baud rate to 0 to hangup */
                    506:     if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */
                    507:     msleep(100);                       /* let things settle */
                    508:     ttraw.c_cflag = ttc_save;
                    509: #ifndef XENIX          /* xenix cannot do close/open when carrier drops */
                    510:                                /* following corrects a PC/IX defficiency */
                    511:     ttc_save = fcntl(ttyfd,F_GETFL,0);
                    512:     close(ttyfd);              /* close/reopen file descriptor */
                    513:     if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1);
                    514: #endif
                    515:     if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */
                    516: #endif
                    517:     return (0);
                    518: }
                    519: 
                    520: 
                    521: /*  T T R E S  --  Restore terminal to "normal" mode.  */
                    522: 
                    523: ttres() {                              /* Restore the tty to normal. */
                    524:     if (ttyfd < 0) return(-1);         /* Not open. */
                    525: #ifndef UXIII                          /* except for sIII, */
                    526:     sleep(1);                          /* Wait for pending i/o to finish. */
                    527: #endif                                 /*   (sIII does wait in ioctls) */
                    528: #ifdef KERLD
                    529:     if (kerld) ioctl(ttyfd,TIOCSETD,&oldld); /* Restore old line discipline. */
                    530: #endif
                    531: #ifdef UXIII
                    532:     if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */
                    533: #else
                    534:     if (stty(ttyfd,&ttold) < 0) return(-1); /* Restore sgtty stuff */
                    535: #endif
                    536: #ifdef KERLD
                    537:     if (kerld) ioctl(ttyfd,TIOCSETC,&oldc); /* Restore old special chars. */
                    538: #endif
                    539: 
                    540:     return(0);
                    541: }
                    542: 
                    543: /* Exclusive uucp file locking control */
                    544: /*
                    545:  by H. Fischer, creative non-Bell coding !
                    546:  copyright rights for lock modules assigned to Columbia University
                    547: */
                    548: static char *
                    549: xxlast(s,c) char *s; char c; {         /* Equivalent to strrchr() */
                    550:     int i;
                    551:     for (i = strlen(s); i > 0; i--)
                    552:        if ( s[i-1] == c ) return( s + (i - 1) );
                    553:     return(NULL);          
                    554: }
                    555: static
                    556: look4lk(ttname) char *ttname; {
                    557:     extern char *strcat(), *strcpy();
                    558:     char *device, *devname;
                    559:     char lockfil[DIRSIZ+1];
                    560: 
                    561: #ifdef ISIII
                    562:     char *lockdir = "/etc/locks";
                    563: #else
                    564: #ifdef ATT3BX
                    565:     char *lockdir = "/usr/spool/locks";
                    566: #else
                    567:     char *lockdir = "/usr/spool/uucp";
                    568: #endif
                    569: #endif
                    570: 
                    571:     device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
                    572: 
                    573: #ifdef ISIII
                    574:     (void) strcpy( lockfil, device );
                    575: #else
                    576:     strcat( strcpy( lockfil, "LCK.." ), device );
                    577: #endif
                    578: 
                    579:     if (access( lockdir, 04 ) < 0) {   /* read access denied on lock dir */
                    580:        fprintf(stderr,"Warning, read access to lock directory denied\n");
                    581:        return( 1 );                    /* cannot check or set lock file */
                    582:     }
                    583:        
                    584:     strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil);
                    585:     debug(F110,"look4lk",flfnam,0);
                    586: 
                    587:     if ( ! access( flfnam, 00 ) ) {    /* print out lock file entry */
                    588:        char lckcmd[40] ;
                    589:        strcat( strcpy(lckcmd, "ls -l ") , flfnam);
                    590:        system(lckcmd);
                    591:        if (access(flfnam,02) == 0)
                    592:            printf("(You may type \"! rm %s\" to remove this file)\n",flfnam);
                    593:        return( -1 );
                    594:     }
                    595:     if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */
                    596:        fprintf(stderr,"Warning, write access to lock directory denied\n");
                    597:        return( 1 );
                    598:     }
                    599:     return( 0 );                       /* okay to go ahead and lock */
                    600: }
                    601: 
                    602: /*  T T L O C K  */
                    603: 
                    604: 
                    605: static
                    606: ttlock(ttyfd) char *ttyfd; {           /* lock uucp if possible */
                    607: #ifdef ATT3BX
                    608:     FILE *lck_fild;
                    609: #endif
                    610:     int lck_fil, l4l;
                    611:     int pid_buf = getpid();            /* pid to save in lock file */
                    612:        
                    613:     hasLock = 0;                       /* not locked yet */
                    614:     l4l = look4lk(ttyfd);
                    615:     if (l4l < 0) return (-1);          /* already locked */
                    616:     if (l4l == 1) return (0);          /* can't read/write lock directory */
                    617:     lck_fil = creat(flfnam, 0444);     /* create lock file ... */
                    618:     if (lck_fil < 0) return (-1);      /* create of lockfile failed */
                    619:                /* creat leaves file handle open for writing -- hf */
                    620: #ifdef ATT3BX
                    621:     fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf);
                    622:     fflush(lck_fild);
                    623: #else
                    624:     write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */
                    625: #endif
                    626:     close (lck_fil);
                    627:     hasLock = 1;                       /* now is locked */
                    628:     return(0);
                    629: }
                    630: 
                    631: /*  T T U N L O C K  */
                    632: 
                    633: static
                    634: ttunlck() {                            /* kill uucp lock if possible */
                    635:     if (hasLock) return( unlink( flfnam ) );
                    636: }
                    637: 
                    638: /*  T T P K T  --  Condition the communication line for packets. */
                    639: /*             or for modem dialing */
                    640: 
                    641: #define DIALING        4               /* flags (via flow) for modem handling */
                    642: #define CONNECT 5
                    643: 
                    644: /*  If called with speed > -1, also set the speed.  */
                    645: 
                    646: /*  Returns 0 on success, -1 on failure.  */
                    647: 
                    648: ttpkt(speed,flow) int speed, flow; {
                    649:     int s;
                    650:     if (ttyfd < 0) return(-1);         /* Not open. */
                    651: 
                    652: #ifdef KERLD
                    653: /* Note, KERLD ignores the TANDEM, ECHO, and CRMOD bits */
                    654:     if (kerld) {
                    655:        ioctl(ttyfd,TIOCGETD,&oldld);   /* Get line discipline */
                    656:        ioctl(ttyfd,TIOCGETC,&oldc);    /* Get special chars */
                    657:        newc = oldc;                    /* Copy special chars */
                    658:        newc.t_brkc = '\r';             /* Set CR to be break character */
                    659:        if(ioctl(ttyfd,TIOCSETC,&newc) < 0) return(-1);
                    660:     }
                    661: #endif
                    662: 
                    663:     s = ttsspd(speed);                 /* Check the speed */
                    664: 
                    665: #ifndef UXIII
                    666:     if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */
                    667:     if (flow == 0) ttraw.sg_flags &= ~TANDEM;
                    668:     ttraw.sg_flags |= RAW;             /* Go into raw mode */
                    669:     ttraw.sg_flags &= ~(ECHO|CRMOD);   /* Use CR for break character */
                    670: #ifdef TOWER1
                    671:     ttraw.sg_flags &= ~ANYP;           /* Must tell Tower no parityr */
                    672: #endif
                    673:     if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */
                    674:     if (stty(ttyfd,&ttraw) < 0) return(-1);    /* Set the new modes. */
                    675: 
                    676: #ifdef MYREAD
                    677: #ifdef BSD4
                    678: /* Try to make reads nonblocking */
                    679:     if (kerld == 0) {
                    680:        if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1)
                    681:            return(-1);
                    682:        else return(0);
                    683:     }
                    684: #endif
                    685: #endif
                    686: #endif
                    687: 
                    688: #ifdef UXIII
                    689:     if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF);
                    690:     if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF);
                    691: 
                    692:     if (flow == DIALING)  ttraw.c_cflag |= CLOCAL|HUPCL;
                    693:     if (flow == CONNECT)  ttraw.c_cflag &= ~CLOCAL;
                    694: 
                    695:     ttraw.c_lflag &= ~(ICANON|ECHO);
                    696:     ttraw.c_lflag |= ISIG;             /* do check for interrupt */
                    697:     ttraw.c_iflag |= (BRKINT|IGNPAR);
                    698:     ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
                    699:     ttraw.c_oflag &= ~OPOST;
                    700:     ttraw.c_cflag &= ~(CSIZE|PARENB);
                    701:     ttraw.c_cflag |= (CS8|CREAD);
                    702:     ttraw.c_cc[4] = 1;
                    703:     ttraw.c_cc[5] = 0;
                    704: 
                    705:     if (s > -1) ttraw.c_cflag &= ~CBAUD, ttraw.c_cflag |= s; /* set speed */
                    706: 
                    707:     if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1);  /* set new modes . */
                    708:     if (flow == DIALING) {
                    709:        if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
                    710:                return(-1);
                    711:        close( open(ttnmsv,2) );        /* magic to force mode change!!! */
                    712:        }
                    713: #endif
                    714: 
                    715: #ifdef KERLD
                    716:     if (kerld) {
                    717:        if (ioctl(ttyfd,TIOCSETD,&ld) < 0)
                    718:            return(-1); /* Set line discpline. */
                    719:     }
                    720: #endif
                    721: 
                    722:     ttflui();                          /* Flush any pending input */
                    723:     return(0);
                    724: }
                    725: 
                    726: /*  T T V T -- Condition communication line for use as virtual terminal  */
                    727: 
                    728: ttvt(speed,flow) int speed, flow; {
                    729:     int s;
                    730:     if (ttyfd < 0) return(-1);         /* Not open. */
                    731: 
                    732:     s = ttsspd(speed);                 /* Check the speed */
                    733: 
                    734: #ifndef UXIII
                    735:     if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */
                    736:     if (flow == 0) tttvt.sg_flags &= ~TANDEM;
                    737:     tttvt.sg_flags |= RAW;             /* Raw mode */
                    738: #ifdef TOWER1
                    739:     tttvt.sg_flags &= ~(ECHO|ANYP);    /* No echo or system III ??? parity */
                    740: #else
                    741:     tttvt.sg_flags &= ~ECHO;           /* No echo */
                    742: #endif    
                    743:     if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */
                    744:     if (stty(ttyfd,&tttvt) < 0) return(-1);
                    745: #ifdef MYREAD
                    746: #ifdef BSD4
                    747: /* Make reads nonblocking */
                    748:     if (kerld == 0) {
                    749:        if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & FNDELAY) == -1)
                    750:            return(-1);
                    751:        else return(0);
                    752:     }
                    753: #endif
                    754: #endif
                    755: 
                    756: #else
                    757:     if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF);
                    758:     if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF);
                    759: 
                    760:     if (flow == DIALING)  tttvt.c_cflag |= CLOCAL|HUPCL;
                    761:     if (flow == CONNECT)  tttvt.c_cflag &= ~CLOCAL;
                    762: 
                    763:     tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
                    764:     tttvt.c_iflag |= (IGNBRK|IGNPAR);
                    765:     tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY);
                    766:     tttvt.c_oflag &= ~OPOST;
                    767:     tttvt.c_cflag &= ~(CSIZE|PARENB);
                    768:     tttvt.c_cflag |= (CS8|CREAD);
                    769:     tttvt.c_cc[4] = 1;
                    770:     tttvt.c_cc[5] = 0;
                    771: 
                    772:     if (s > -1) tttvt.c_cflag &= ~CBAUD, tttvt.c_cflag |= s; /* set speed */
                    773: 
                    774:     if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1);  /* set new modes . */
                    775:     if (flow == DIALING) {
                    776:        if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 )
                    777:                return(-1);
                    778:        close( open(ttnmsv,2) );        /* magic to force mode change!!! */
                    779:        }
                    780:     return(0);
                    781: #endif
                    782: }
                    783: 
                    784: /*  T T S S P D  --  Return the internal baud rate code for 'speed'.  */
                    785: 
                    786: ttsspd(speed) {
                    787:     int s, spdok;
                    788: 
                    789:     if (speed < 0) return(-1);
                    790:        spdok = 1;                      /* Assume arg ok */
                    791:        switch (speed) {
                    792:            case 0:    s = B0;    break;        /* Just the common ones. */
                    793:            case 110:  s = B110;  break;        /* The others from ttydev.h */
                    794:            case 150:  s = B150;  break;        /* could also be included if */
                    795:            case 300:  s = B300;  break;        /* necessary... */
                    796:            case 600:  s = B600;  break;
                    797:            case 1200: s = B1200; break;
                    798:            case 1800: s = B1800; break;
                    799:            case 2400: s = B2400; break;
                    800:            case 4800: s = B4800; break;
                    801:            case 9600: s = B9600; break;
                    802: #ifdef PLEXUS
                    803:            case 19200: s = EXTA; break;
                    804: #endif
                    805:            default:
                    806:                spdok = 0;
                    807:                fprintf(stderr,"Unsupported line speed - %d\n",speed);
                    808:                fprintf(stderr,"Current speed not changed\n");
                    809:                break;
                    810:        }           
                    811:        if (spdok) return(s); else return(-1);
                    812:  }
                    813: 
                    814: 
                    815: 
                    816: /*  T T F L U I  --  Flush tty input buffer */
                    817: 
                    818: ttflui() {
                    819: 
                    820: #ifndef UXIII
                    821:     long n;
                    822: #endif
                    823:     if (ttyfd < 0) return(-1);         /* Not open. */
                    824: 
                    825:     ungotn = -1;                       /* Initialize myread() stuff */
                    826:     inbufc = 0;
                    827: 
                    828: #ifdef UXIII
                    829:     if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed");
                    830: #else
                    831: #ifdef TIOCFLUSH
                    832: #ifdef ANYBSD
                    833:     n = FREAD;                         /* Specify read queue */
                    834:     if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed");
                    835: #else
                    836:     if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed");
                    837: #endif
                    838: #endif
                    839: #endif
                    840:     return(0);
                    841: }
                    842: 
                    843: /* Interrupt Functions */
                    844: 
                    845: 
                    846: /* Timeout handler for communication line input functions */
                    847: 
                    848: timerh() {
                    849:     longjmp(sjbuf,1);
                    850: }
                    851: 
                    852:  
                    853: /* Set up terminal interrupts on console terminal */
                    854: 
                    855: #ifdef UXIII
                    856: esctrp() {                             /* trap console escapes (^\) */
                    857:     conesc = 1;
                    858:     signal(SIGQUIT,SIG_IGN);           /* ignore until trapped */
                    859: }
                    860: #endif
                    861: 
                    862: #ifdef V7
                    863: esctrp() {                             /* trap console escapes (^\) */
                    864:     conesc = 1;
                    865:     signal(SIGQUIT,SIG_IGN);           /* ignore until trapped */
                    866: }
                    867: #endif
                    868: 
                    869: #ifdef C70
                    870: esctrp() {                             /* trap console escapes (^\) */
                    871:     conesc = 1;
                    872:     signal(SIGQUIT,SIG_IGN);           /* ignore until trapped */
                    873: }
                    874: #endif
                    875: 
                    876: /*  C O N I N T  --  Console Interrupt setter  */
                    877: 
                    878: conint(f) int (*f)(); {                        /* Set an interrupt trap. */
                    879: 
                    880:     if (backgrd) return;               /* must ignore signals in bkgrd */
                    881: 
                    882: /*
                    883:  Except for special cases below, ignore keyboard quit signal.
                    884:  ^\ too easily confused with connect escape, and besides, we don't want
                    885:  to leave lock files around.  (Frank Prindle)
                    886: */
                    887:     signal(SIGQUIT,SIG_IGN);
                    888: 
                    889: #ifdef UXIII
                    890:     signal(SIGQUIT,esctrp);            /* console escape in pkt modes */
                    891:     if (conesc) {                      /* clear out pending escapes */
                    892:        conesc = 0;
                    893:     }
                    894: #endif
                    895: 
                    896: #ifdef V7
                    897:     signal(SIGQUIT,esctrp);            /* console escape in pkt modes */
                    898:     if (conesc) {                      /* clear out pending escapes */
                    899:        conesc = 0;
                    900:     }
                    901: #endif
                    902: 
                    903:     if (conif) return;                 /* Nothing to do if already on. */
                    904: 
                    905: /* check if invoked in background -- if so signals set to be ignored */
                    906: 
                    907:     if (signal(SIGINT,SIG_IGN) == SIG_IGN) {
                    908:        backgrd = 1;                    /*   means running in background */
                    909: #ifdef UXIII
                    910:        signal(SIGQUIT,SIG_IGN);        /*   must leave signals ignored */
                    911: #endif
                    912: #ifdef V7
                    913:        signal(SIGQUIT,SIG_IGN);        /*   must leave signals ignored */
                    914: #endif
                    915:        return;
                    916:     }
                    917:     signal(SIGINT,f);                  /* Function to trap to on interrupt. */
                    918:     signal(SIGHUP,f);                  /* Or hangup, so lock file cleared. */
                    919:     conif = 1;                         /* Flag console interrupts on. */
                    920: }
                    921: 
                    922: 
                    923: /*  C O N N O I  --  Reset console terminal interrupts */
                    924: 
                    925: connoi() {                             /* Console-no-interrupts */
                    926: 
                    927:     if (backgrd) return;               /* Ignore signals in background */
                    928: 
                    929:     signal(SIGINT,SIG_DFL);
                    930:     signal(SIGHUP,SIG_DFL);
                    931:     signal(SIGQUIT,SIG_DFL);
                    932:     conif = 0;                         /* Flag interrupt trapping off */
                    933: }
                    934: 
                    935: /*  myread() -- For use by systems that can do nonblocking read() calls  */
                    936: /*
                    937:  Returns:
                    938:   -1  if no characters available,
                    939:   -2  upon error (such as disconnect),
                    940:   otherwise value of character (0 or greater)
                    941: */
                    942: myread() {
                    943:     static int inbuf_item;
                    944:     static CHAR inbuf[257];
                    945:     CHAR readit;
                    946:     
                    947:     if (ungotn >= 0) {
                    948:        readit = ungotn;
                    949:     } else {
                    950:         if (inbufc > 0) {
                    951:            readit = inbuf[++inbuf_item];
                    952:         } else {
                    953:            if ((inbufc = read(ttyfd,inbuf,256)) == 0) {  /* end of file */
                    954:                        /* means carrier dropped on modem connection */
                    955:                errno = 9999;           /* magic number for no carrier */
                    956:                return(-2);             /* end of file has no errno */
                    957:                }
                    958:            if (inbufc < 0) return(-2);
                    959:            readit = inbuf[inbuf_item = 0];
                    960:        }
                    961:         inbufc--;      
                    962:     }
                    963:     ungotn = -1;
                    964:     return(readit);
                    965: }
                    966: 
                    967: myunrd(ch) CHAR ch; {                  /* push back up to one character */
                    968:     ungotn = ch;
                    969: }
                    970: 
                    971: /*  I N I T R A W Q  --  Set up to read /DEV/KMEM for character count.  */
                    972: 
                    973: #ifdef V7
                    974: /*
                    975:  Used in Version 7 to simulate Berkeley's FIONREAD ioctl call.  This
                    976:  eliminates blocking on a read, because we can read /dev/kmem to get the
                    977:  number of characters available for raw input.  If your system can't
                    978:  or you won't let it read /dev/kmem (the world that is) then you must
                    979:  figure out a different way to do the counting of characters available,
                    980:  or else replace this by a dummy function that always returns 0.
                    981: */
                    982: /*
                    983:  * Call this routine as: initrawq(tty)
                    984:  * where tty is the file descriptor of a terminal.  It will return
                    985:  * (as a char *) the kernel-mode memory address of the rawq character
                    986:  * count, which may then be read.  It has the side-effect of flushing
                    987:  * input on the terminal.
                    988:  */
                    989: /*
                    990:  * John Mackin, Physiology Dept., University of Sydney (Australia)
                    991:  * ...!decvax!mulga!physiol.su.oz!john
                    992:  *
                    993:  * Permission is hereby granted to do anything with this code, as
                    994:  * long as this comment is retained unmodified and no commercial
                    995:  * advantage is gained.
                    996:  */
                    997: #include <a.out.h>
                    998: #include <sys/proc.h>
                    999: 
                   1000: char *initrawq(tty) int tty; {
                   1001: #ifdef UTS24
                   1002:     return(0);
                   1003: #else
                   1004: #ifdef BSD29
                   1005:     return(0);
                   1006: #else
                   1007:     long lseek();
                   1008:     static struct nlist nl[] = {
                   1009:        {PROCNAME},
                   1010:        {NPROCNAME},
                   1011:        {""}
                   1012:     };
                   1013:     static struct proc *pp;
                   1014:     char *malloc(), *qaddr, *p, c;
                   1015:     int m, pid, me;
                   1016:     NPTYPE xproc;                      /* Its type is defined in makefile. */
                   1017:     int catch();
                   1018: 
                   1019:     me = getpid();
                   1020:     if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
                   1021:     nlist(BOOTNAME, nl);
                   1022:     if (nl[0].n_type == 0) err("proc array");
                   1023:  
                   1024:     if (nl[1].n_type == 0) err("nproc");
                   1025: 
                   1026:     lseek(m, (long)(nl[1].n_value), 0);
                   1027:     read (m, &xproc, sizeof(xproc));
                   1028:     signal(SIGALRM, catch);
                   1029:     if ((pid = fork()) == 0) {
                   1030:        while(1)
                   1031:            read(tty, &c, 1);
                   1032:     }
                   1033:     alarm(2);
                   1034:  
                   1035:     if(setjmp(jjbuf) == 0) {
                   1036:        while(1)
                   1037:            read(tty, &c, 1);
                   1038:     }
                   1039:     signal(SIGALRM, SIG_DFL);
                   1040: 
                   1041: #ifdef DIRECT
                   1042:     pp = (struct proc *) nl[0].n_value;
                   1043: #else 
                   1044:     if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
                   1045:     if (read(m, &pp, sizeof(pp)) != sizeof(pp))  err("no read of proc ptr");
                   1046: #endif
                   1047:     lseek(m, (long)(nl[1].n_value), 0);
                   1048:     read(m, &xproc, sizeof(xproc));
                   1049: 
                   1050:     if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
                   1051:     if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
                   1052:     if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
                   1053:        err("read proc table");
                   1054:     for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
                   1055:        if (pp -> p_pid == (short) pid) goto iout;
                   1056:     }
                   1057:     err("no such proc");
                   1058:  
                   1059: iout:
                   1060:     close(m);
                   1061:     qaddr = (char *)(pp -> p_wchan);
                   1062:     free (p);
                   1063:     kill(pid, SIGKILL);
                   1064:     wait((int *)0);            /* Destroy the ZOMBIEs! */
                   1065:     return (qaddr);
                   1066: #endif
                   1067: #endif
                   1068: }
                   1069: 
                   1070: /*  More V7-support functions...  */
                   1071: 
                   1072: static
                   1073: err(s) char *s; {
                   1074:     char buf[200];
                   1075: 
                   1076:     sprintf(buf, "fatal error in initrawq: %s", s);
                   1077:     perror(buf);
                   1078:     doexit(1);
                   1079: }
                   1080: 
                   1081: static
                   1082: catch() {
                   1083:     longjmp(jjbuf, -1);
                   1084: }
                   1085: 
                   1086: 
                   1087: /*  G E N B R K  --  Simulate a modem break.  */
                   1088: 
                   1089: #define        BSPEED  B150
                   1090: 
                   1091: genbrk(fn) int fn; {
                   1092:     struct sgttyb ttbuf;
                   1093:     int ret, sospeed;
                   1094: 
                   1095:     ret = ioctl(fn, TIOCGETP, &ttbuf);
                   1096:     sospeed = ttbuf.sg_ospeed;
                   1097:     ttbuf.sg_ospeed = BSPEED;
                   1098:     ret = ioctl(fn, TIOCSETP, &ttbuf);
                   1099:     ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8);
                   1100:     ttbuf.sg_ospeed = sospeed;
                   1101:     ret = ioctl(fn, TIOCSETP, &ttbuf);
                   1102:     ret = write(fn, "@", 1);
                   1103:     return;
                   1104: }
                   1105: #endif V7
                   1106: 
                   1107: /*  T T C H K  --  Tell how many characters are waiting in tty input buffer  */
                   1108: 
                   1109: ttchk() {
                   1110:     int x; long n;
                   1111: #ifdef FIONREAD
                   1112:     x = ioctl(ttyfd, FIONREAD, &n);    /* Berkeley and maybe some others */
                   1113:     debug(F101,"ttchk","",n);
                   1114:     return((x < 0) ? 0 : n);
                   1115: #else
                   1116: #ifdef V7
                   1117:     lseek(kmem[TTY], (long) qaddr[TTY], 0);
                   1118:     x = read(kmem[TTY], &n, sizeof(int));
                   1119:     return((x == sizeof(int))? n: 0);
                   1120: #else  V7
                   1121: #ifdef UXIII
                   1122:     return(inbufc + (ungotn >= 0) );   
                   1123: #else
                   1124: #ifdef C70
                   1125:     return(inbufc + (ungotn >= 0) );
                   1126: #else
                   1127: #ifdef PROVX1
                   1128:     x = ioctl(ttyfd, TIOCQCNT, &ttbuf);
                   1129:     n = ttbuf.sg_ispeed & 0377;
                   1130:     return((x < 0) ? 0 : n);
                   1131: #else
                   1132:     return(0);
                   1133: #endif
                   1134: #endif
                   1135: #endif
                   1136: #endif
                   1137: #endif
                   1138: }
                   1139: 
                   1140: 
                   1141: /*  T T X I N  --  Get n characters from tty input buffer  */
                   1142: 
                   1143: /*  Returns number of characters actually gotten, or -1 on failure  */
                   1144: 
                   1145: /*  Intended for use only when it is known that n characters are actually */
                   1146: /*  Available in the input buffer.  */
                   1147: 
                   1148: ttxin(n,buf) int n; char *buf; {
                   1149:     int x;
                   1150:     CHAR c;
                   1151: 
                   1152: #ifdef MYREAD
                   1153:     for( x = 0; (x > -1) && (x < n); buf[x++] = myread() );
                   1154: #else
                   1155:     debug(F101,"ttxin: n","",n);
                   1156:     x = read(ttyfd,buf,n);
                   1157:     debug(F101," x","",x);
                   1158: #endif
                   1159:     if (x > 0) buf[x] = '\0';
                   1160:     if (x < 0) x = -1;
                   1161:     return(x);
                   1162: }
                   1163: 
                   1164: /*  T T O L  --  Similar to "ttinl", but for writing.  */
                   1165: 
                   1166: ttol(s,n) int n; char *s; {
                   1167:     int x;
                   1168:     if (ttyfd < 0) return(-1);         /* Not open. */
                   1169:     x = write(ttyfd,s,n);
                   1170:     debug(F111,"ttol",s,n);
                   1171:     if (x < 0) debug(F101,"ttol failed","",x);
                   1172:     return(x);
                   1173: }
                   1174: 
                   1175: 
                   1176: /*  T T O C  --  Output a character to the communication line  */
                   1177: 
                   1178: ttoc(c) char c; {
                   1179:     if (ttyfd < 0) return(-1);         /* Not open. */
                   1180:     return(write(ttyfd,&c,1));
                   1181: }
                   1182: 
                   1183: /*  T T I N L  --  Read a record (up to break character) from comm line.  */
                   1184: /*
                   1185:   If no break character encountered within "max", return "max" characters,
                   1186:   with disposition of any remaining characters undefined.  Otherwise, return
                   1187:   the characters that were read, including the break character, in "dest" and
                   1188:   the number of characters read as the value of function, or 0 upon end of
                   1189:   file, or -1 if an error occurred.  Times out & returns error if not completed
                   1190:   within "timo" seconds.
                   1191: */
                   1192: 
                   1193: ttinl(dest,max,timo,eol) int max,timo; char *dest; char eol; {
                   1194:     int x, y;
                   1195:     CHAR c;
                   1196: 
                   1197:     if (ttyfd < 0) return(-1);         /* Not open. */
                   1198:     if (timo <= 0) {                   /* Untimed read... */
                   1199: 
                   1200: #ifdef MYREAD
                   1201:        for (x = y = 0; (x < max) && (c != eol); x++) {
                   1202:             while ((y = myread()) == -1) ;
                   1203:             if (y == -2) return(-1);
                   1204:             dest[x] = y & 0377;
                   1205:        }
                   1206: #else
                   1207:        x = read(ttyfd,dest,max);       /* Try to read. */
                   1208: #endif
                   1209:        return(x);                      /* Return the count. */
                   1210:     }
                   1211: 
                   1212: /* Timed read... */
                   1213: 
                   1214:     signal(SIGALRM,timerh);            /* Set up timeout action. */
                   1215:     alarm(timo);                       /* Set the timer. */
                   1216:     if (setjmp(sjbuf))                 /* Do this if timer went off. */
                   1217:        x = -1;
                   1218:     else if (kerld) {                  /* Efficient Kermit line discipline */
                   1219:        x = read(ttyfd,dest,max);       /* for 4.2bsd only... */
                   1220:     } else {                           /* Normal case... */
                   1221:        for (x = c = y = 0; (x < max) && (c != eol); x++) {
                   1222: #ifdef MYREAD
                   1223:            while ((y = myread()) == -1) /* Use own buffering if we can */
                   1224:                ;
                   1225:            if (y == -2) y++;
                   1226:            c = y & 0377;
                   1227: #else
                   1228:            while ((y = read(ttyfd,&c,1)) == 0) /* Else call system */
                   1229:                ;                       /* ...for each character. */
                   1230: #endif
                   1231:            if (y < 0) {
                   1232:                alarm(0);               /* Error, turn off timer, */
                   1233:                signal(SIGALRM,SIG_DFL); /* and associated interrupt. */
                   1234:                return(y);              /* Return the error indication. */
                   1235:            }
                   1236:            dest[x] = c;
                   1237:        }
                   1238:        x++;
                   1239:     }
                   1240:     alarm(0);                          /* Success, turn off timer, */
                   1241:     signal(SIGALRM,SIG_DFL);           /* and associated interrupt. */
                   1242:     return(x);                         /* Return the count. */
                   1243: }
                   1244: 
                   1245: /*  T T I N C --  Read a character from the communication line  */
                   1246: 
                   1247: ttinc(timo) int timo; {
                   1248:     int n = 0;
                   1249:     CHAR ch = 0;
                   1250: 
                   1251:     if (ttyfd < 0) return(-1);         /* Not open. */
                   1252:     if (timo <= 0) {                   /* Untimed. */
                   1253: #ifdef MYREAD
                   1254:        /* comm line failure returns -1 thru myread, so no &= 0377 */
                   1255:        while ((n = myread()) == -1) ;  /* Wait for a character... */
                   1256:        if (n == -2) n++;
                   1257:        return( n );
                   1258: #else
                   1259:        while ((n = read(ttyfd,&ch,1)) == 0) ; /* Wait for a character. */
                   1260:        return( (n > 0) ? (ch & 0377) : n );
                   1261: #endif
                   1262:     }
                   1263: 
                   1264:     signal(SIGALRM,timerh);            /* Timed, set up timer. */
                   1265:     alarm(timo);
                   1266:     if (setjmp(sjbuf)) {
                   1267:        n = -1;
                   1268:     } else {
                   1269: #ifdef MYREAD
                   1270:        while ((n = myread()) == -1) ;  /* If managing own buffer... */
                   1271:        if (n == -2) {
                   1272:            n++;
                   1273:        } else {
                   1274:            ch = n;
                   1275:            n = 1;      
                   1276:        }
                   1277: #else
                   1278:        n = read(ttyfd,&ch,1);          /* Otherwise call the system. */
                   1279: #endif
                   1280:     }
                   1281:     alarm(0);                          /* Turn off timer, */
                   1282:     signal(SIGALRM,SIG_DFL);           /* and interrupt. */
                   1283:     return( (n > 0) ? (ch & 0377) : n ); /* Return char or -1. */
                   1284: }
                   1285: 
                   1286: /*  T T S N D B  --  Send a BREAK signal  */
                   1287: 
                   1288: ttsndb() {
                   1289:     int x; long n; char spd;
                   1290: 
                   1291:     if (ttyfd < 0) return(-1);         /* Not open. */
                   1292: 
                   1293: #ifdef PROVX1
                   1294:     gtty(ttyfd,&ttbuf);                        /* Get current tty flags */
                   1295:     spd = ttbuf.sg_ospeed;             /* Save speed */
                   1296:     ttbuf.sg_ospeed = B50;             /* Change to 50 baud */
                   1297:     stty(ttyfd,&ttbuf);                        /*  ... */
                   1298:     write(ttyfd,brnuls,3);             /* Send 3 nulls */
                   1299:     ttbuf.sg_ospeed = spd;             /* Restore speed */
                   1300:     stty(ttyfd,&ttbuf);                        /*  ... */
                   1301:     return(0);
                   1302: #else
                   1303: #ifdef UXIII
                   1304:     if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) {   /* Send a BREAK */
                   1305:        perror("Can't send BREAK");
                   1306:        return(-1);
                   1307:     }
                   1308:     return(0);
                   1309: #else
                   1310: #ifdef ANYBSD
                   1311:     n = FWRITE;                                /* Flush output queue. */
                   1312:     ioctl(ttyfd,TIOCFLUSH,&n);                 /* Ignore any errors.. */
                   1313:     if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
                   1314:        perror("Can't send BREAK");
                   1315:        return(-1);
                   1316:     }
                   1317:     x = msleep(275);                   /* Sleep for so many milliseconds */
                   1318:     if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
                   1319:        perror("BREAK stuck!!!");
                   1320:        doexit(1);                      /* Get out, closing the line. */
                   1321:                                        /*   with exit status = 1 */
                   1322:     }
                   1323:     return(x);
                   1324: #else
                   1325: #ifdef V7
                   1326:     genbrk(ttyfd);                     /* Simulate a BREAK */
                   1327:     return(x);
                   1328: #endif
                   1329: #endif
                   1330: #endif
                   1331: #endif
                   1332: }
                   1333: 
                   1334: /*  M S L E E P  --  Millisecond version of sleep().  */
                   1335: 
                   1336: /*
                   1337:  Intended only for small intervals.  For big ones, just use sleep().
                   1338: */
                   1339: 
                   1340: msleep(m) int m; {
                   1341: 
                   1342: #ifdef PROVX1
                   1343:     sleep(-((m * 60 + 500) / 1000));
                   1344:     return(0);
                   1345: #endif
                   1346: 
                   1347: #ifdef ANYBSD
                   1348:     int t1, t3, t4;
                   1349: #ifdef BSD41
                   1350:     if (ftime(&ftp) < 0) return(-1);   /* Get current time. */
                   1351:     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
                   1352:     while (1) {
                   1353:        ftime(&ftp);                    /* new time */
                   1354:        t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
                   1355:        if (t3 > m) return (t3);
                   1356:     }
                   1357: #else
                   1358: /* 2.9 and 4.1 BSD do it this way */
                   1359:     if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */
                   1360:     t1 = tv.tv_sec;                    /* Seconds */
                   1361: 
                   1362:     tv.tv_sec = 0;                     /* Use select() */
                   1363:     tv.tv_usec = m * 1000;
                   1364:     return(select( 0, (int *)0, (int *)0, (int *)0, &tv) );
                   1365: #endif
                   1366: #endif
                   1367: 
                   1368: #ifdef UXIII
                   1369: #ifdef XENIX
                   1370: #define CLOCK_TICK 50                  /* millisecs per clock tick */
                   1371: #else
                   1372: #define CLOCK_TICK 17                  /* 1/60 sec */
                   1373: #endif
                   1374:     extern long times();
                   1375:     long t1, t2, tarray[4];
                   1376:     int t3;
                   1377: 
                   1378:     if ((t1 = times(tarray)) < 0) return(-1);
                   1379:     while (1) {
                   1380:        if ((t2 = times(tarray)) < 0) return(-1);
                   1381:        t3 = ((int)(t2 - t1)) * CLOCK_TICK;
                   1382:        if (t3 > m) return(t3);
                   1383:     }
                   1384: #endif
                   1385: 
                   1386: #ifdef TOWER1
                   1387:     int t1, t3;
                   1388:     if (ftime(&ftp) < 0) return(-1);           /* Get current time. */
                   1389:     t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
                   1390:     while (1) {
                   1391:        ftime(&ftp);                            /* new time */
                   1392:        t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
                   1393:        if (t3 > m) return (t3);
                   1394:     }
                   1395: #endif
                   1396: }
                   1397: 
                   1398: /*  R T I M E R --  Reset elapsed time counter  */
                   1399: 
                   1400: rtimer() {
                   1401:     tcount = time( (long *) 0 );
                   1402: }
                   1403: 
                   1404: 
                   1405: /*  G T I M E R --  Get current value of elapsed time counter in seconds  */
                   1406: 
                   1407: gtimer() {
                   1408:     int x;
                   1409:     x = (int) (time( (long *) 0 ) - tcount);
                   1410:     rtimer();
                   1411:     return( (x < 0) ? 0 : x );
                   1412: }
                   1413: 
                   1414: 
                   1415: /*  Z T I M E  --  Return date/time string  */
                   1416: 
                   1417: ztime(s) char **s; {
                   1418: 
                   1419: #ifdef UXIII
                   1420:     extern long time();                        /* Sys III/V way to do it */
                   1421:     char *ctime();
                   1422:     long clock_storage;
                   1423: 
                   1424:     clock_storage = time( (long *) 0 );
                   1425:     *s = ctime( &clock_storage );
                   1426: #endif
                   1427: 
                   1428: #ifdef PROVX1
                   1429:     int utime[2];                      /* Venix way */
                   1430:     time(utime);
                   1431:     *s = ctime(utime);
                   1432: #endif
                   1433: 
                   1434: #ifdef ANYBSD
                   1435:     char *asctime();                   /* Berkeley way */
                   1436:     struct tm *localtime();
                   1437:     struct tm *tp;
                   1438: #ifndef BSD41
                   1439:     gettimeofday(&tv, &tz);            /* BSD 2.9, 4.2 ... */
                   1440:     time(&tv.tv_sec);
                   1441:     tp = localtime(&tv.tv_sec);
                   1442: #else
                   1443:     time(&clock);                      /* BSD 4.1 ... ceb */
                   1444:     tp = localtime(&clock);
                   1445: #endif
                   1446:     *s = asctime(tp);
                   1447: #endif
                   1448: 
                   1449: #ifdef TOWER1
                   1450:     char *asctime();                   /* Tower way */
                   1451:     struct tm *localtime();
                   1452:     struct tm *tp;
                   1453: 
                   1454:     time(&clock);
                   1455:     tp = localtime(&clock);
                   1456:     *s = asctime(tp);
                   1457: #endif
                   1458: #ifdef V7
                   1459:     char *asctime();                   /* V7 way */
                   1460:     struct tm *localtime();
                   1461:     struct tm *tp;
                   1462: 
                   1463:     time(&clock);
                   1464:     tp = localtime(&clock);
                   1465:     *s = asctime(tp);
                   1466: #endif
                   1467: }
                   1468: 
                   1469: /*  C O N G M  --  Get console terminal modes.  */
                   1470: 
                   1471: /*
                   1472:  Saves current console mode, and establishes variables for switching between 
                   1473:  current (presumably normal) mode and other modes.
                   1474: */
                   1475: 
                   1476: congm() {
                   1477: #ifndef UXIII
                   1478:      gtty(0,&ccold);                   /* Structure for restoring */
                   1479:      gtty(0,&cccbrk);                  /* For setting CBREAK mode */
                   1480:      gtty(0,&ccraw);                   /* For setting RAW mode */
                   1481: #else
                   1482:      ioctl(0,TCGETA,&ccold);
                   1483:      ioctl(0,TCGETA,&cccbrk);
                   1484:      ioctl(0,TCGETA,&ccraw);
                   1485: #endif
                   1486:      cgmf = 1;                         /* Flag that we got them. */
                   1487: }
                   1488: 
                   1489: 
                   1490: /*  C O N C B --  Put console in cbreak mode.  */
                   1491: 
                   1492: /*  Returns 0 if ok, -1 if not  */
                   1493: 
                   1494: concb(esc) char esc; {
                   1495:     int x;
                   1496:     if (cgmf == 0) congm();            /* Get modes if necessary. */
                   1497:     escchr = esc;                      /* Make this available to other fns */
                   1498:     ckxech = 1;                                /* Program can echo characters */
                   1499: #ifndef UXIII
                   1500:     cccbrk.sg_flags |= CBREAK;         /* Set to character wakeup, */
                   1501:     cccbrk.sg_flags &= ~ECHO;          /* no echo. */
                   1502:     x = stty(0,&cccbrk);
                   1503: #else
                   1504:     cccbrk.c_lflag &= ~(ICANON|ECHO);
                   1505:     cccbrk.c_cc[0] = 003;              /* interrupt char is control-c */
                   1506:     cccbrk.c_cc[1] = escchr;           /* escape during packet modes */
                   1507:     cccbrk.c_cc[4] = 1;
                   1508:     cccbrk.c_cc[5] = 1;
                   1509:     x = ioctl(0,TCSETAW,&cccbrk);      /* set new modes . */
                   1510: #endif
                   1511:     if (x > -1) setbuf(stdout,NULL);   /* Make console unbuffered. */
                   1512: #ifdef V7
                   1513:     if (kmem[CON] < 0) {
                   1514:        qaddr[CON] = initrawq(0);
                   1515:        if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
                   1516:            fprintf(stderr, "Can't read /dev/kmem in concb.\n");
                   1517:            perror("/dev/kmem");
                   1518:            exit(1);
                   1519:        }
                   1520:     }
                   1521: #endif V7
                   1522:     return(x);
                   1523: }
                   1524: 
                   1525: /*  C O N B I N  --  Put console in binary mode  */
                   1526: 
                   1527: /*  Returns 0 if ok, -1 if not  */
                   1528: 
                   1529: conbin(esc) char esc; {
                   1530:     if (cgmf == 0) congm();            /* Get modes if necessary. */
                   1531:     escchr = esc;                      /* Make this available to other fns */
                   1532:     ckxech = 1;                                /* Program can echo characters */
                   1533: #ifndef UXIII
                   1534:     ccraw.sg_flags |= (RAW|TANDEM);    /* Set rawmode, XON/XOFF */
                   1535:     ccraw.sg_flags &= ~(ECHO|CRMOD);   /* Set char wakeup, no echo */
                   1536:     return(stty(0,&ccraw));
                   1537: #else
                   1538:     ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
                   1539:     ccraw.c_iflag |= (BRKINT|IGNPAR);
                   1540:     ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
                   1541:                        |INPCK|ISTRIP);
                   1542:     ccraw.c_oflag &= ~OPOST;
                   1543: 
                   1544: /*** Kermit used to put the console in 8-bit raw mode, but some users have
                   1545:  *** pointed out that this should not be done, since some sites actually
                   1546:  *** use terminals with parity settings on their Unix systems, and if we
                   1547:  *** override the current settings and stop doing parity, then their terminals
                   1548:  *** will display blotches for characters whose parity is wrong.  Therefore,
                   1549:  *** the following two lines are commented out (Larry Afrin, Clemson U):
                   1550:  ***
                   1551:  ***   ccraw.c_cflag &= ~(PARENB|CSIZE);
                   1552:  ***   ccraw.c_cflag |= (CS8|CREAD);
                   1553:  ***
                   1554:  *** Sys III/V sites that have trouble with this can restore these lines.
                   1555:  ***/
                   1556:     ccraw.c_cc[4] = 1;
                   1557:     ccraw.c_cc[5] = 1;
                   1558:     return(ioctl(0,TCSETAW,&ccraw) );          /* set new modes . */
                   1559: #endif
                   1560: }
                   1561: 
                   1562: 
                   1563: /*  C O N R E S  --  Restore the console terminal  */
                   1564: 
                   1565: conres() {
                   1566:     if (cgmf == 0) return(0);          /* Don't do anything if modes */
                   1567: #ifndef UXIII                          /* except for sIII, */
                   1568:     sleep(1);                          /*  not known! */
                   1569: #endif                                 /*   (sIII does wait in ioctls) */
                   1570:     ckxech = 0;                                /* System should echo chars */
                   1571: #ifndef UXIII
                   1572:     return(stty(0,&ccold));            /* Restore controlling tty */
                   1573: #else
                   1574:     return(ioctl(0,TCSETAW,&ccold));
                   1575: #endif
                   1576: }
                   1577: 
                   1578: /*  C O N O C  --  Output a character to the console terminal  */
                   1579: 
                   1580: conoc(c) char c; {
                   1581:     write(1,&c,1);
                   1582: }
                   1583: 
                   1584: /*  C O N X O  --  Write x characters to the console terminal  */
                   1585: 
                   1586: conxo(x,s) char *s; int x; {
                   1587:     write(1,s,x);
                   1588: }
                   1589: 
                   1590: /*  C O N O L  --  Write a line to the console terminal  */
                   1591: 
                   1592: conol(s) char *s; {
                   1593:     int len;
                   1594:     len = strlen(s);
                   1595:     write(1,s,len);
                   1596: }
                   1597: 
                   1598: /*  C O N O L A  --  Write an array of lines to the console terminal */
                   1599: 
                   1600: conola(s) char *s[]; {
                   1601:     int i;
                   1602:     for (i=0 ; *s[i] ; i++) conol(s[i]);
                   1603: }
                   1604: 
                   1605: /*  C O N O L L  --  Output a string followed by CRLF  */
                   1606: 
                   1607: conoll(s) char *s; {
                   1608:     conol(s);
                   1609:     write(1,"\r\n",2);
                   1610: }
                   1611: 
                   1612: /*  C O N C H K  --  Return how many characters available at console  */
                   1613: 
                   1614: conchk() {
                   1615:     int x; long n;
                   1616: 
                   1617: #ifdef PROVX1 
                   1618:     x = ioctl(0, TIOCQCNT, &ttbuf);
                   1619:     n = ttbuf.sg_ispeed & 0377;
                   1620:     return((x < 0) ? 0 : n);
                   1621: #else
                   1622: #ifdef V7
                   1623:     lseek(kmem[CON], (long) qaddr[CON], 0);
                   1624:     x = read(kmem[CON], &n, sizeof(int));
                   1625:     return((x == sizeof(int))? n: 0);
                   1626: #else
                   1627: #ifdef UXIII
                   1628:     if (conesc) {                      /* Escape typed */
                   1629:        conesc = 0;
                   1630:        signal(SIGQUIT,esctrp);         /* Restore escape */
                   1631:        return(1);
                   1632:     }
                   1633:     return(0);
                   1634: #else
                   1635: #ifdef C70
                   1636:     if (conesc) {                      /* Escape typed */
                   1637:        conesc = 0;
                   1638:        signal(SIGQUIT,esctrp);         /* Restore escape */
                   1639:        return(1);
                   1640:     }
                   1641:     return(0);
                   1642: #else
                   1643: #ifdef FIONREAD
                   1644:     x = ioctl(0, FIONREAD, &n);                /* BSD and maybe some others */
                   1645:     return((x < 0) ? 0 : n);
                   1646: #else
                   1647:     return(0);                         /* Others can't do. */
                   1648: #endif
                   1649: #endif
                   1650: #endif
                   1651: #endif
                   1652: #endif
                   1653: }
                   1654: 
                   1655: /*  C O N I N C  --  Get a character from the console  */
                   1656: 
                   1657: coninc(timo) int timo; {
                   1658:     int n = 0; char ch;
                   1659:     if (timo <= 0 ) {                  /* untimed */
                   1660:        n = read(0, &ch, 1);            /* Read a character. */
                   1661:        ch &= 0377;
                   1662:        if (n > 0) return(ch);          /* Return the char if read */
                   1663:        else 
                   1664: #ifdef UXIII
                   1665:            if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */
                   1666:                return(escchr);          /* user entered escape character */
                   1667:            else                    /* couldnt be ^c, sigint never returns */
                   1668: #endif
                   1669:                return(-1);             /* Return the char, or -1. */
                   1670:        }
                   1671:     signal(SIGALRM,timerh);            /* Timed read, so set up timer */
                   1672:     alarm(timo);
                   1673:     if (setjmp(sjbuf)) n = -2;
                   1674:     else {
                   1675:        n = read(0, &ch, 1);
                   1676:        ch &= 0377;
                   1677:     }
                   1678:     alarm(0);                          /* Stop timing, we got our character */
                   1679:     signal(SIGALRM,SIG_DFL);
                   1680:     if (n > 0) return(ch);  
                   1681:     else
                   1682: #ifdef UXIII
                   1683:         if (n == -1 && errno == EINTR)  /* If read interrupted by QUIT, */
                   1684:            return(escchr);             /* user entered escape character, */
                   1685:         else                           /* can't be ^c, sigint never returns */
                   1686: #endif
                   1687:        return(-1);
                   1688: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.