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