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:  gregg@okstate.csnet
  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: }

Defined functions

catch defined in line 1081; used 2 times
conbin defined in line 1529; used 1 times
concb defined in line 1494; used 4 times
conchk defined in line 1614; used 2 times
congm defined in line 1476; used 3 times
conint defined in line 878; used 1 times
connoi defined in line 925; used 2 times
conol defined in line 1592; used 25 times
conola defined in line 1600; used 2 times
conres defined in line 1565; used 5 times
conxo defined in line 1586; used 1 times
err defined in line 1072; used 9 times
esctrp defined in line 870; used 4 times
genbrk defined in line 1091; used 1 times
gtimer defined in line 1407; never used
initrawq defined in line 1000; used 3 times
look4lk defined in line 555; used 1 times
msleep defined in line 1340; used 7 times
myread defined in line 942; used 5 times
myunrd defined in line 967; never used
rtimer defined in line 1400; used 1 times
sysinit defined in line 339; used 1 times
timerh defined in line 848; used 3 times
ttchk defined in line 1109; used 3 times
tthang defined in line 492; used 3 times
ttinl defined in line 1193; used 1 times
ttlock defined in line 605; used 2 times
ttpkt defined in line 648; used 2 times
ttres defined in line 523; used 1 times
ttsndb defined in line 1288; used 2 times
ttsspd defined in line 786; used 2 times
ttunlck defined in line 633; used 2 times
ttvt defined in line 728; used 2 times
ttxin defined in line 1148; used 1 times
xxlast defined in line 548; used 1 times
ztime defined in line 1417; used 5 times

Defined variables

backgrd defined in line 265; used 4 times
brnuls defined in line 273; used 1 times
cccbrk defined in line 324; used 11 times
ccold defined in line 324; used 4 times
ccraw defined in line 324; used 12 times
ckxech defined in line 267; used 8 times
ckxsys defined in line 100; used 4 times
ckxv defined in line 1; used 1 times
clock defined in line 314; used 6 times
conesc defined in line 331; used 11 times
dfflow defined in line 264; used 1 times
dfprty defined in line 263; used 1 times
escchr defined in line 281; used 5 times
flfnam defined in line 327; used 9 times
ftp defined in line 310; used 12 times
hasLock defined in line 328; used 3 times
inbufc defined in line 329; used 7 times
jjbuf defined in line 275; used 2 times
kerld defined in line 290; used 7 times
kmem defined in line 246; used 8 times
ld defined in line 287; used 1 times
lkf defined in line 276; used 3 times
newc defined in line 286; used 3 times
oldc defined in line 286; used 3 times
oldld defined in line 288; used 2 times
qaddr defined in line 247; used 7 times
sjbuf defined in line 275; used 4 times
tcount defined in line 271; used 2 times
ttbuf defined in line 323; used 17 times
ttnmsv defined in line 335; used 4 times
ttold defined in line 323; used 4 times
ttraw defined in line 323; used 31 times
tttvt defined in line 323; used 25 times
tv defined in line 299; used 8 times
tz defined in line 300; used 2 times
ungotn defined in line 330; used 7 times

Defined macros

ANYBSD defined in line 56; used 5 times
BSD41 defined in line 46; used 5 times
BSD42 defined in line 39; used 2 times
BSPEED defined in line 1089; used 1 times
CLOCK_TICK defined in line 1372; used 1 times
CON defined in line 248; used 6 times
CONNECT defined in line 642; used 2 times
DEVNAMLEN defined in line 28; used 7 times
DIALING defined in line 641; used 4 times
DIRSIZ defined in line 37; used 2 times
MYREAD defined in line 114; used 7 times
TTY defined in line 249; used 6 times
Last modified: 1985-08-14
Generated: 2016-12-26
Generated by src2html V0.67
page hit count: 5878
Valid CSS Valid XHTML 1.0 Strict