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