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