|
|
1.1 ! root 1: char *ckxv = "Unix tty I/O, 4E(047), 27 Jan 88"; ! 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, 1988, Trustees of Columbia University in the City of New ! 11: York. 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: ! 19: #include <sys/dir.h> /* Directory */ ! 20: #include <ctype.h> /* Character types */ ! 21: #ifdef NULL ! 22: #undef NULL ! 23: #endif /* NULL */ ! 24: #include <stdio.h> /* Unix Standard i/o */ ! 25: #include <signal.h> /* Interrupts */ ! 26: ! 27: #ifndef ZILOG ! 28: #include <setjmp.h> /* Longjumps */ ! 29: #else ! 30: #include <setret.h> ! 31: #endif ! 32: ! 33: #include "ckcdeb.h" /* Typedefs, formats for debug() */ ! 34: ! 35: /* Maximum length for the name of a tty device */ ! 36: ! 37: #ifndef DEVNAMLEN ! 38: #define DEVNAMLEN 25 ! 39: #endif ! 40: ! 41: /* 4.1 BSD support added by Charles E. Brooks, EDN-VAX */ ! 42: /* Fortune 32:16 Pro:For 1.8 support mostly like 4.1, added by J-P Dumas */ ! 43: ! 44: #ifdef BSD4 ! 45: #define ANYBSD ! 46: #ifdef MAXNAMLEN ! 47: #define BSD42 ! 48: #ifdef aegis ! 49: char *ckxsys = " Apollo DOMAIN/IX 4.2 BSD"; ! 50: #else ! 51: char *ckxsys = " 4.2 BSD"; ! 52: #endif /* aegis */ ! 53: #else ! 54: #ifdef FT18 ! 55: #define BSD41 ! 56: char *ckxsys = " Fortune For:Pro 1.8"; ! 57: #else ! 58: #define BSD41 ! 59: #ifndef C70 ! 60: char *ckxsys = " 4.1 BSD"; ! 61: #endif /* not c70 */ ! 62: #endif /* ft18 */ ! 63: #endif /* maxnamlen */ ! 64: #endif /* bsd4 */ ! 65: ! 66: /* 2.9bsd support contributed by Bradley Smith, UCLA */ ! 67: #ifdef BSD29 ! 68: #define ANYBSD ! 69: char *ckxsys = " 2.9 BSD"; ! 70: #endif /* bsd29 */ ! 71: ! 72: /* ! 73: Version 7 UNIX support contributed by Gregg Wonderly, ! 74: Oklahoma State University: [email protected] ! 75: */ ! 76: #ifdef V7 ! 77: char *ckxsys = " Version 7 UNIX (tm)"; ! 78: #endif /* v7 */ ! 79: ! 80: /* ! 81: Version 9 UNIX support contributed by Paul Glick, ! 82: AT&T Bell Laboratories: [email protected] ! 83: */ ! 84: #ifdef V9 ! 85: char *ckxsys = " Version 9 UNIX (tm)"; ! 86: #endif /* v9 */ ! 87: ! 88: /* BBN C70 support from Frank Wancho, WANCHO@SIMTEL20 */ ! 89: #ifdef C70 ! 90: char *ckxsys = " BBN C/70"; ! 91: #endif /* c70 */ ! 92: ! 93: /* IBM 370 IX/370 support from Wayne Van Pelt, GE/CRD, Schenectedy, NY */ ! 94: #ifdef IX370 ! 95: char *ckxsys = " IBM IX/370"; ! 96: #endif /* ix370 */ ! 97: ! 98: /* Amdahl UTS 2.4 (v7 derivative) for IBM 370 series compatible mainframes */ ! 99: /* Contributed by Garard Gaye, Jean-Pierre Dumas, DUMAS@SUMEX-AIM. */ ! 100: #ifdef UTS24 ! 101: char *ckxsys = " Amdahl UTS 2.4"; ! 102: #endif /* uts24 */ ! 103: ! 104: /* Pro/Venix Version 1.x support from Columbia U. */ ! 105: #ifdef PROVX1 ! 106: char *ckxsys = " Pro-3xx Venix v1"; ! 107: #endif /* provx1 */ ! 108: ! 109: /* Tower support contributed by John Bray, Auburn, Alabama */ ! 110: #ifdef TOWER1 ! 111: char *ckxsys = " NCR Tower 1632, OS 1.02"; ! 112: #endif /* tower1 */ ! 113: ! 114: /* Sys III/V, Xenix, PC/IX support by Herm Fischer, Encino, CA */ ! 115: #ifdef UXIII ! 116: #ifdef XENIX ! 117: char *ckxsys = " Xenix/286"; ! 118: #else ! 119: #ifdef PCIX ! 120: char *ckxsys = " PC/IX"; ! 121: #else ! 122: #ifdef ISIII ! 123: char *ckxsys = " Interactive Systems Corp System III"; ! 124: #else ! 125: #ifdef hpux ! 126: /* HP 9000 Series changes contributed by Bill Coalson */ ! 127: char *ckxsys = " HP 9000 Series HP-UX"; ! 128: #else ! 129: #ifdef aegis ! 130: /* Apollo Aegis support from SAS Institute, Cary, NC */ ! 131: char *ckxsys = " Apollo DOMAIN/IX System V"; ! 132: #else ! 133: #ifdef ZILOG ! 134: char *ckxsys = " Zilog S8000 Zeus 3.21+"; ! 135: #else ! 136: #ifdef VXVE ! 137: /* Control Data Corp VX/VE 5.2.1 System V support by */ ! 138: /* S.O. Lidie, Lehigh University, [email protected] */ ! 139: char *ckxsys = " CDC VX/VE 5.2.1 System V"; ! 140: #else ! 141: char *ckxsys = " AT&T System III/System V"; ! 142: #endif /* vxve */ ! 143: #endif /* zilog */ ! 144: #endif /* aegis */ ! 145: #endif /* hpux */ ! 146: #endif /* isiii */ ! 147: #endif /* pcix */ ! 148: #endif /* xenix */ ! 149: #endif /* uxiii */ ! 150: ! 151: /* Features... */ ! 152: ! 153: /* Do own buffering, using unbuffered read() calls... */ ! 154: #ifdef UXIII ! 155: #define MYREAD ! 156: #endif /* uxiii */ ! 157: ! 158: #ifdef BSD42 ! 159: #undef MYREAD ! 160: #include <errno.h> ! 161: #endif /* bsd42 */ ! 162: ! 163: /* ! 164: Variables available to outside world: ! 165: ! 166: dftty -- Pointer to default tty name string, like "/dev/tty". ! 167: dfloc -- 0 if dftty is console, 1 if external line. ! 168: dfprty -- Default parity ! 169: dfflow -- Default flow control ! 170: ckxech -- Flag for who echoes console typein: ! 171: 1 - The program (system echo is turned off) ! 172: 0 - The system (or front end, or terminal). ! 173: functions that want to do their own echoing should check this flag ! 174: before doing so. ! 175: ! 176: flfnam -- Name of lock file, including its path, e.g., ! 177: "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77" ! 178: hasLock -- Flag set if this kermit established a uucp lock. ! 179: inbufc -- number of tty line rawmode unread characters ! 180: (system III/V unixes) ! 181: backgrd -- Flag indicating program executing in background ( & on ! 182: end of shell command). Used to ignore INT and QUIT signals. ! 183: ! 184: Functions for assigned communication line (either external or console tty): ! 185: ! 186: sysinit() -- System dependent program initialization ! 187: syscleanup() -- System dependent program shutdown ! 188: ttopen(ttname,local,mdmtyp) -- Open the named tty for exclusive access. ! 189: ttclos() -- Close & reset the tty, releasing any access lock. ! 190: ttpkt(speed,flow) -- Put the tty in packet mode and set the speed. ! 191: ttvt(speed,flow) -- Put the tty in virtual terminal mode. ! 192: or in DIALING or CONNECTED modem control state. ! 193: ttinl(dest,max,timo) -- Timed read line from the tty. ! 194: ttinc(timo) -- Timed read character from tty. ! 195: myread() -- System 3 raw mode bulk buffer read, gives ! 196: -- subsequent chars one at a time and simulates ! 197: -- FIONREAD! ! 198: myunrd(c) -- Places c back in buffer to be read (one only) ! 199: ttchk() -- See how many characters in tty input buffer. ! 200: ttxin(n,buf) -- Read n characters from tty (untimed). ! 201: ttol(string,length) -- Write a string to the tty. ! 202: ttoc(c) -- Write a character to the tty. ! 203: ttflui() -- Flush tty input buffer. ! 204: ! 205: ttlock(ttname) -- Lock against uucp collisions (Sys III) ! 206: ttunlck() -- Unlock " " " ! 207: look4lk(ttname) -- Check if a lock file exists ! 208: */ ! 209: ! 210: /* ! 211: Functions for console terminal: ! 212: ! 213: congm() -- Get console terminal modes. ! 214: concb(esc) -- Put the console in single-character wakeup mode with no echo. ! 215: conbin(esc) -- Put the console in binary (raw) mode. ! 216: conres() -- Restore the console to mode obtained by congm(). ! 217: conoc(c) -- Unbuffered output, one character to console. ! 218: conol(s) -- Unbuffered output, null-terminated string to the console. ! 219: conola(s) -- Unbuffered output, array of strings to the console. ! 220: conxo(n,s) -- Unbuffered output, n characters to the console. ! 221: conchk() -- Check if characters available at console (bsd 4.2). ! 222: Check if escape char (^\) typed at console (System III/V). ! 223: coninc(timo) -- Timed get a character from the console. ! 224: conint() -- Enable terminal interrupts on the console if not background. ! 225: connoi() -- Disable terminal interrupts on the console if not background. ! 226: ! 227: Time functions ! 228: ! 229: msleep(m) -- Millisecond sleep ! 230: ztime(&s) -- Return pointer to date/time string ! 231: rtimer() -- Reset timer ! 232: gtimer() -- Get elapsed time since last call to rtimer() ! 233: */ ! 234: ! 235: /* Conditional Includes */ ! 236: ! 237: #ifdef FT18 ! 238: #include <sys/file.h> /* File information */ ! 239: #endif /* ft18 */ ! 240: ! 241: /* Whether to #include <sys/file.h>... */ ! 242: #ifndef PROVX1 ! 243: #ifndef aegis ! 244: #ifndef XENIX ! 245: #include <sys/file.h> /* File information */ ! 246: #endif /* xenix */ ! 247: #endif /* aegis */ ! 248: #endif /* provx1 */ ! 249: ! 250: #ifdef aegis ! 251: #ifdef BSD4 ! 252: #include <sys/file.h> ! 253: #include <fcntl.h> ! 254: #endif /* bsd4 */ ! 255: #endif /* aegis */ ! 256: ! 257: /* System III, System V */ ! 258: ! 259: #ifdef UXIII ! 260: #include <termio.h> ! 261: #include <sys/ioctl.h> ! 262: #include <fcntl.h> /* directory reading for locking */ ! 263: #include <errno.h> /* error numbers for system returns */ ! 264: #endif /* uxiii */ ! 265: ! 266: #ifdef HPUX ! 267: #include <sys/modem.h> ! 268: #endif ! 269: ! 270: /* Not Sys III/V */ ! 271: ! 272: #ifdef V9 ! 273: #include <sys/filio.h> ! 274: #include <sys/ttyio.h> ! 275: ! 276: extern int tty_ld; ! 277: #endif ! 278: #ifndef UXIII ! 279: #ifndef V9 ! 280: #include <sgtty.h> /* Set/Get tty modes */ ! 281: #ifndef PROVX1 ! 282: #ifndef V7 ! 283: #ifndef BSD41 ! 284: #include <sys/time.h> /* Clock info (for break generation) */ ! 285: #endif /* not bsd41 */ ! 286: #endif /* not v7 */ ! 287: #endif /* not provx1 */ ! 288: #endif /* not v9 */ ! 289: #endif /* not uxiii */ ! 290: ! 291: #ifdef BSD41 ! 292: #include <sys/timeb.h> /* BSD 4.1 ... ceb */ ! 293: #endif /* bsd41 */ ! 294: ! 295: #ifdef BSD29 ! 296: #include <sys/timeb.h> /* BSD 2.9 (Vic Abell, Purdue) */ ! 297: #endif /* bsd29 */ ! 298: ! 299: #ifdef TOWER1 ! 300: #include <sys/timeb.h> /* Clock info for NCR Tower */ ! 301: #endif /* tower1 */ ! 302: ! 303: #ifdef aegis ! 304: #include "/sys/ins/base.ins.c" ! 305: #include "/sys/ins/error.ins.c" ! 306: #include "/sys/ins/ios.ins.c" ! 307: #include "/sys/ins/sio.ins.c" ! 308: #include "/sys/ins/pad.ins.c" ! 309: #include "/sys/ins/time.ins.c" ! 310: #include "/sys/ins/pfm.ins.c" ! 311: #include "/sys/ins/pgm.ins.c" ! 312: #include "/sys/ins/ec2.ins.c" ! 313: #include "/sys/ins/type_uids.ins.c" ! 314: #include <default_acl.h> ! 315: #undef TIOCEXCL ! 316: #undef FIONREAD ! 317: #endif ! 318: ! 319: /* The following two conditional #defines are catch-alls for those systems */ ! 320: /* that didn't have or couldn't find <file.h>... */ ! 321: ! 322: #ifndef FREAD ! 323: #define FREAD 0x01 ! 324: #endif ! 325: ! 326: #ifndef FWRITE ! 327: #define FWRITE 0x10 ! 328: #endif ! 329: ! 330: /* Declarations */ ! 331: ! 332: long time(); /* All Unixes should have this... */ ! 333: extern int errno; /* System call error code. */ ! 334: ! 335: /* Special stuff for V7 input buffer peeking */ ! 336: ! 337: #ifdef V7 ! 338: int kmem[2] = { -1, -1}; ! 339: char *initrawq(), *qaddr[2]={0,0}; ! 340: #define CON 0 ! 341: #define TTY 1 ! 342: #endif /* v7 */ ! 343: ! 344: /* dftty is the device name of the default device for file transfer */ ! 345: /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ ! 346: ! 347: #ifdef PROVX1 ! 348: char *dftty = "/dev/com1.dout"; /* Only example so far of a system */ ! 349: int dfloc = 1; /* that goes in local mode by default */ ! 350: #else ! 351: char *dftty = CTTNAM; /* Remote by default, use normal */ ! 352: int dfloc = 0; /* controlling terminal name. */ ! 353: #endif /* provx1 */ ! 354: ! 355: int dfprty = 0; /* Default parity (0 = none) */ ! 356: int ttprty = 0; /* Parity in use. */ ! 357: int ttmdm = 0; /* Modem in use. */ ! 358: int dfflow = 1; /* Xon/Xoff flow control */ ! 359: int backgrd = 0; /* Assume in foreground (no '&' ) */ ! 360: ! 361: int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ ! 362: ! 363: /* Declarations of variables global within this module */ ! 364: ! 365: static long tcount; /* Elapsed time counter */ ! 366: ! 367: static char *brnuls = "\0\0\0\0\0\0\0"; /* A string of nulls */ ! 368: ! 369: static jmp_buf sjbuf, jjbuf; /* Longjump buffer */ ! 370: static int lkf = 0, /* Line lock flag */ ! 371: conif = 0, /* Console interrupts on/off flag */ ! 372: cgmf = 0, /* Flag that console modes saved */ ! 373: xlocal = 0, /* Flag for tty local or remote */ ! 374: ttyfd = -1; /* TTY file descriptor */ ! 375: static char escchr; /* Escape or attn character */ ! 376: ! 377: #ifdef BSD42 ! 378: static struct timeval tv; /* For getting time, from sys/time.h */ ! 379: static struct timezone tz; ! 380: #endif /* bsd42 */ ! 381: ! 382: #ifdef BSD29 ! 383: static long clock; /* For getting time from sys/time.h */ ! 384: static struct timeb ftp; /* And from sys/timeb.h */ ! 385: #endif /* bsd29 */ ! 386: ! 387: #ifdef BSD41 ! 388: static long clock; /* For getting time from sys/time.h */ ! 389: static struct timeb ftp; /* And from sys/timeb.h */ ! 390: #endif /* bsd41 */ ! 391: ! 392: #ifdef TOWER1 ! 393: static long clock; /* For getting time from sys/time.h */ ! 394: static struct timeb ftp; /* And from sys/timeb.h */ ! 395: #endif /* tower1 */ ! 396: ! 397: #ifdef V7 ! 398: static long clock; ! 399: #endif /* v7 */ ! 400: ! 401: #ifdef V9 ! 402: static long clock; ! 403: #endif ! 404: ! 405: /* sgtty/termio information... */ ! 406: ! 407: #ifdef UXIII ! 408: static struct termio ttold = {0}; /* Init'd for word alignment, */ ! 409: static struct termio ttraw = {0}; /* which is important for some */ ! 410: static struct termio tttvt = {0}; /* systems, like Zilog... */ ! 411: static struct termio ccold = {0}; ! 412: static struct termio ccraw = {0}; ! 413: static struct termio cccbrk = {0}; ! 414: #else ! 415: static struct sgttyb /* sgtty info... */ ! 416: ttold, ttraw, tttvt, ttbuf, /* for communication line */ ! 417: ccold, ccraw, cccbrk; /* and for console */ ! 418: #endif /* uxiii */ ! 419: ! 420: static char flfnam[80]; /* uucp lock file path name */ ! 421: static int hasLock = 0; /* =1 if this kermit locked uucp */ ! 422: static int inbufc = 0; /* stuff for efficient SIII raw line */ ! 423: static int ungotn = -1; /* pushback to unread character */ ! 424: static int conesc = 0; /* set to 1 if esc char (^\) typed */ ! 425: ! 426: static int ttlock(); /* definition of ttlock subprocedure */ ! 427: static int ttunlck(); /* and unlock subprocedure */ ! 428: static char ttnmsv[DEVNAMLEN]; /* copy of open path for tthang */ ! 429: ! 430: #ifdef aegis ! 431: static status_$t st; /* error status return value */ ! 432: static short concrp = 0; /* true if console is CRP pad */ ! 433: #define CONBUFSIZ 10 ! 434: static char conbuf[CONBUFSIZ]; /* console readahead buffer */ ! 435: static int conbufn = 0; /* # chars in readahead buffer */ ! 436: static char *conbufp; /* next char in readahead buffer */ ! 437: static uid_$t ttyuid; /* tty type uid */ ! 438: static uid_$t conuid; /* stdout type uid */ ! 439: ! 440: /* APOLLO Aegis main() ! 441: * establish acl usage and cleanup handling ! 442: * this makes sure that CRP pads ! 443: * get restored to a usable mode ! 444: */ ! 445: main(argc,argv) int argc; char **argv; { ! 446: status_$t status; ! 447: pfm_$cleanup_rec dirty; ! 448: ! 449: int pid = getpid(); ! 450: ! 451: /* acl usage according to invoking environment */ ! 452: default_acl(USE_DEFENV); ! 453: ! 454: /* establish a cleanup continuation */ ! 455: status = pfm_$cleanup(dirty); ! 456: if (status.all != pfm_$cleanup_set) ! 457: { ! 458: /* only handle faults for the original process */ ! 459: if (pid == getpid() && status.all > pgm_$max_severity) ! 460: { /* blew up in main process */ ! 461: status_$t quo; ! 462: pfm_$cleanup_rec clean; ! 463: ! 464: /* restore the console in any case */ ! 465: conres(); ! 466: ! 467: /* attempt a clean exit */ ! 468: debug(F101, "cleanup fault status", "", status.all); ! 469: ! 470: /* doexit(), then send status to continuation */ ! 471: quo = pfm_$cleanup(clean); ! 472: if (quo.all == pfm_$cleanup_set) ! 473: doexit(pgm_$program_faulted); ! 474: else if (quo.all > pgm_$max_severity) ! 475: pfm_$signal(quo); /* blew up in doexit() */ ! 476: } ! 477: /* send to the original continuation */ ! 478: pfm_$signal(status); ! 479: /*NOTREACHED*/ ! 480: } ! 481: return(ckcmai(argc, argv)); ! 482: } ! 483: #endif /* aegis */ ! 484: ! 485: /* S Y S I N I T -- System-dependent program initialization. */ ! 486: ! 487: sysinit() { ! 488: ! 489: /* for now, nothing... */ ! 490: return(0); ! 491: } ! 492: ! 493: /* S Y S C L E A N U P -- System-dependent program cleanup. */ ! 494: ! 495: syscleanup() { ! 496: ! 497: /* for now, nothing... */ ! 498: return(0); ! 499: } ! 500: ! 501: /* T T O P E N -- Open a tty for exclusive access. */ ! 502: ! 503: /* Returns 0 on success, -1 on failure. */ ! 504: /* ! 505: If called with lcl < 0, sets value of lcl as follows: ! 506: 0: the terminal named by ttname is the job's controlling terminal. ! 507: 1: the terminal named by ttname is not the job's controlling terminal. ! 508: But watch out: if a line is already open, or if requested line can't ! 509: be opened, then lcl remains (and is returned as) -1. ! 510: */ ! 511: ttopen(ttname,lcl,modem) char *ttname; int *lcl, modem; { ! 512: ! 513: #ifdef UXIII ! 514: #ifndef CIE ! 515: char *ctermid(); /* Wish they all had this! */ ! 516: #endif /* not cie */ ! 517: #endif /* uxiii */ ! 518: ! 519: #ifdef CIE /* CIE Regulus doesn't... */ ! 520: #define ctermid(x) strcpy(x,"") ! 521: #endif ! 522: ! 523: char *x; extern char* ttyname(); ! 524: char cname[DEVNAMLEN+4]; ! 525: ! 526: if (ttyfd > -1) return(0); /* If already open, ignore this call */ ! 527: ttmdm = modem; /* Make this available to other fns */ ! 528: xlocal = *lcl; /* Make this available to other fns */ ! 529: #ifdef NEWUUCP ! 530: acucntrl("disable",ttname); /* Open getty on line (4.3BSD) */ ! 531: #endif /* newuucp */ ! 532: #ifdef UXIII ! 533: /* if modem connection, don't wait for carrier */ ! 534: ttyfd = open(ttname,O_RDWR | (modem ? O_NDELAY : 0) ); ! 535: #else ! 536: #ifdef V9 ! 537: if (strncmp(ttname, "/cs", 3) == 0) { ! 538: if ((ttyfd = ipcopen(ttname, "")) >= 0) ! 539: if ( ioctl(ttyfd, FIOPUSHLD, &tty_ld) == -1 ) ! 540: fprintf(stderr, "ioctl error - FIOPUSHLD\n"); ! 541: } else ! 542: #endif /* V9 */ ! 543: ttyfd = open(ttname,2); /* Try to open for read/write */ ! 544: #endif /* uxiii */ ! 545: ! 546: if (ttyfd < 0) { /* If couldn't open, fail. */ ! 547: perror(ttname); ! 548: return(-1); ! 549: } ! 550: #ifdef aegis ! 551: /* Apollo C runtime claims that console pads are tty devices, which ! 552: * is reasonable, but they aren't any good for packet transfer. */ ! 553: ios_$inq_type_uid((short)ttyfd, ttyuid, st); ! 554: if (st.all != status_$ok) { ! 555: fprintf(stderr, "problem getting tty object type: "); ! 556: error_$print(st); ! 557: } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */ ! 558: close(ttyfd); ttyfd = -1; ! 559: errno = ENOTTY; perror(ttname); ! 560: return(-1); ! 561: } ! 562: #endif /* aegis */ ! 563: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Open, keep copy of name locally. */ ! 564: ! 565: /* Caller wants us to figure out if line is controlling tty */ ! 566: ! 567: debug(F111,"ttopen ok",ttname,*lcl); ! 568: if (*lcl == -1) { ! 569: if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */ ! 570: debug(F110," Same as CTTNAM",ttname,0); ! 571: xlocal = 0; ! 572: } else if (isatty(0)) { /* Else, if stdin not redirected */ ! 573: x = ttyname(0); /* then compare its device name */ ! 574: strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */ ! 575: debug(F110," ttyname(0)",x,0); ! 576: x = ttyname(ttyfd); /* ...with real name of ttname. */ ! 577: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; ! 578: debug(F111," ttyname",x,xlocal); ! 579: } else { /* Else, if stdin redirected... */ ! 580: #ifdef UXIII ! 581: /* Sys III/V provides nice ctermid() function to get name of controlling tty */ ! 582: ctermid(cname); /* Get name of controlling terminal */ ! 583: debug(F110," ctermid",cname,0); ! 584: x = ttyname(ttyfd); /* Compare with name of comm line. */ ! 585: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; ! 586: debug(F111," ttyname",x,xlocal); ! 587: #else ! 588: /* Just assume local, so "set speed" and similar commands will work */ ! 589: /* If not really local, how could it work anyway?... */ ! 590: xlocal = 1; ! 591: debug(F101," redirected stdin","",xlocal); ! 592: #endif /* uxiii */ ! 593: } ! 594: } ! 595: ! 596: /* Now check if line is locked -- if so fail, else lock for ourselves */ ! 597: ! 598: lkf = 0; /* Check lock */ ! 599: if (xlocal > 0) { ! 600: if (ttlock(ttname) < 0) { ! 601: fprintf(stderr,"Exclusive access to %s denied\n",ttname); ! 602: close(ttyfd); ttyfd = -1; ! 603: debug(F110," Access denied by lock",ttname,0); ! 604: return(-1); /* Not if already locked */ ! 605: } else lkf = 1; ! 606: } ! 607: ! 608: /* Got the line, now set the desired value for local. */ ! 609: ! 610: if (*lcl < 0) *lcl = xlocal; ! 611: ! 612: /* Some special stuff for v7... */ ! 613: ! 614: #ifdef V7 ! 615: if (kmem[TTY] < 0) { /* If open, then skip this. */ ! 616: qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */ ! 617: if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) { ! 618: fprintf(stderr, "Can't read /dev/kmem in ttopen.\n"); ! 619: perror("/dev/kmem"); ! 620: exit(1); ! 621: } ! 622: } ! 623: #endif /* v7 */ ! 624: ! 625: /* Request exclusive access on systems that allow it. */ ! 626: ! 627: #ifndef XENIX ! 628: /* Xenix exclusive access prevents open(close(...)) from working... */ ! 629: #ifdef TIOCEXCL ! 630: if (ioctl(ttyfd,TIOCEXCL, NULL) < 0) ! 631: fprintf(stderr,"Warning, problem getting exclusive access\n"); ! 632: #endif /* tiocexcl */ ! 633: #endif /* xenix */ ! 634: ! 635: /* Get tty device settings */ ! 636: ! 637: #ifndef UXIII ! 638: #ifdef V9 ! 639: ioctl(ttyfd,TIOCGETP,&ttold); /* Same deal for Sys III, Sys V */ ! 640: ioctl(ttyfd,TIOCGETP,&ttraw); ! 641: ioctl(ttyfd,TIOCGETP,&tttvt); ! 642: #else ! 643: gtty(ttyfd,&ttold); /* Get sgtty info */ ! 644: #ifdef aegis ! 645: sio_$control((short)ttyfd, sio_$raw_nl, false, st); ! 646: if (xlocal) { /* ignore breaks from local line */ ! 647: sio_$control((short)ttyfd, sio_$int_enable, false, st); ! 648: sio_$control((short)ttyfd, sio_$quit_enable, false, st); ! 649: } ! 650: #endif /* aegis */ ! 651: gtty(ttyfd,&ttraw); /* And a copy of it for packets*/ ! 652: gtty(ttyfd,&tttvt); /* And one for virtual tty service */ ! 653: #endif /* v9 */ ! 654: #else ! 655: ioctl(ttyfd,TCGETA,&ttold); /* Same deal for Sys III, Sys V */ ! 656: #ifdef aegis ! 657: sio_$control((short)ttyfd, sio_$raw_nl, false, st); ! 658: if (xlocal) { /* ignore breaks from local line */ ! 659: sio_$control((short)ttyfd, sio_$int_enable, false, st); ! 660: sio_$control((short)ttyfd, sio_$quit_enable, false, st); ! 661: } ! 662: #endif /* aegis */ ! 663: ioctl(ttyfd,TCGETA,&ttraw); ! 664: ioctl(ttyfd,TCGETA,&tttvt); ! 665: #endif /* not uxiii */ ! 666: ! 667: #ifdef VXVE ! 668: ttraw.c_line = 0; /* STTY line 0 for VX/VE */ ! 669: ioctl(ttyfd,TCSETA,&ttraw); ! 670: tttvt.c_line = 0; /* STTY line 0 for VX/VE */ ! 671: ioctl(ttyfd,TCSETA,&tttvt); ! 672: #endif /* vxve */ ! 673: ! 674: debug(F101,"ttopen, ttyfd","",ttyfd); ! 675: debug(F101," lcl","",*lcl); ! 676: debug(F111," lock file",flfnam,lkf); ! 677: return(0); ! 678: } ! 679: ! 680: /* T T C L O S -- Close the TTY, releasing any lock. */ ! 681: ! 682: ttclos() { ! 683: if (ttyfd < 0) return(0); /* Wasn't open. */ ! 684: if (xlocal) { ! 685: if (tthang()) /* Hang up phone line */ ! 686: fprintf(stderr,"Warning, problem hanging up the phone\n"); ! 687: if (ttunlck()) /* Release uucp-style lock */ ! 688: fprintf(stderr,"Warning, problem releasing lock\n"); ! 689: } ! 690: ttres(); /* Reset modes. */ ! 691: /* Relinquish exclusive access if we might have had it... */ ! 692: #ifndef XENIX ! 693: #ifdef TIOCEXCL ! 694: #ifdef TIOCNXCL ! 695: if (ioctl(ttyfd, TIOCNXCL, NULL) < 0) ! 696: fprintf(stderr,"Warning, problem relinquishing exclusive access\n"); ! 697: #endif /* tiocnxcl */ ! 698: #endif /* tiocexcl */ ! 699: #endif /* not xenix */ ! 700: close(ttyfd); /* Close it. */ ! 701: #ifdef NEWUUCP ! 702: acucntrl("enable",flfnam); /* Close getty on line. */ ! 703: #endif /* newuucp */ ! 704: ttyfd = -1; /* Mark it as closed. */ ! 705: return(0); ! 706: } ! 707: ! 708: /* T T H A N G -- Hangup phone line */ ! 709: ! 710: tthang() { ! 711: #ifdef UXIII ! 712: #ifdef HPUX ! 713: unsigned long dtr_down = 00000000000, ! 714: modem_rtn; ! 715: #else ! 716: unsigned short ttc_save; ! 717: #endif /* hpux */ ! 718: #endif /* uxiii */ ! 719: ! 720: if (ttyfd < 0) return(0); /* Not open. */ ! 721: #ifdef aegis ! 722: sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */ ! 723: msleep(500); /* pause */ ! 724: sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */ ! 725: #else ! 726: #ifdef ANYBSD ! 727: ioctl(ttyfd,TIOCCDTR,0); /* Clear DTR */ ! 728: msleep(500); /* Let things settle */ ! 729: ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */ ! 730: #endif /* anybsd */ ! 731: #ifdef UXIII ! 732: #ifdef HPUX /* Hewlett Packard way of modem control */ ! 733: if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) return(-1); /* lower DTR */ ! 734: msleep(500); ! 735: if (ioctl(ttyfd,MCGETA,&modem_rtn) < 0) return(-1); /* get line status */ ! 736: if ((modem_rtn & MDCD) != 0) return(-1); /* check if DCD is low */ ! 737: modem_rtn = MRTS | MDTR; /* bits for RTS & DTR */ ! 738: if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) return(-1); /* set lines */ ! 739: #else ! 740: ttc_save = ttraw.c_cflag; ! 741: ttraw.c_cflag &= ~CBAUD; /* swa: set baud rate to 0 to hangup */ ! 742: if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* do it */ ! 743: msleep(100); /* let things settle */ ! 744: ttraw.c_cflag = ttc_save; ! 745: ! 746: /* NOTE - The following #ifndef...#endif can be removed for SCO Xenix 2.1.3 */ ! 747: /* or later, but must keep for earlier versions, which can't do close/open. */ ! 748: ! 749: #ifndef XENIX /* xenix cannot do close/open when carrier drops */ ! 750: /* following corrects a PC/IX defficiency */ ! 751: ttc_save = fcntl(ttyfd,F_GETFL,0); ! 752: close(ttyfd); /* close/reopen file descriptor */ ! 753: if ((ttyfd = open(ttnmsv, ttc_save)) < 0) return(-1); ! 754: #endif /* not xenix */ ! 755: if (ioctl(ttyfd,TCSETAF,&ttraw) < 0) return(-1); /* un-do it */ ! 756: #endif /* uxiii */ ! 757: #endif /* hpux */ ! 758: #endif /* aegis */ ! 759: return (0); ! 760: } ! 761: ! 762: ! 763: /* T T R E S -- Restore terminal to "normal" mode. */ ! 764: ! 765: ttres() { /* Restore the tty to normal. */ ! 766: int x; ! 767: ! 768: if (ttyfd < 0) return(-1); /* Not open. */ ! 769: #ifndef UXIII /* except for sIII, */ ! 770: sleep(1); /* Wait for pending i/o to finish. */ ! 771: #endif /* uxiii */ /* (sIII does wait in ioctls) */ ! 772: ! 773: #ifdef UXIII ! 774: if (ioctl(ttyfd,TCSETAW,&ttold) < 0) return(-1); /* restore termio stuff */ ! 775: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) ! 776: return(-1); ! 777: #else /* not uxiii */ ! 778: #ifdef V9 ! 779: if (ioctl(ttyfd, TIOCSETP, &ttold) < 0) return(-1); /* Restore sgttyb stuff */ ! 780: #else ! 781: #ifdef FIONBIO ! 782: x = 0; ! 783: x = ioctl(ttyfd,FIONBIO,&x); ! 784: if (x < 0) { ! 785: perror("ttres ioctl"); ! 786: debug(F101,"ttres ioctl","",x); ! 787: } ! 788: #else /* not fionbio */ ! 789: #ifdef FNDELAY ! 790: x = (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) & ~FNDELAY) == -1); ! 791: debug(F101,"ttres fcntl","",x); ! 792: if (x < 0) perror("fcntl"); ! 793: #endif /* fndelay */ ! 794: #endif /* fionbio */ ! 795: x = stty(ttyfd,&ttold); /* Restore sgtty stuff */ ! 796: debug(F101,"ttres stty","",x); ! 797: if (x < 0) perror("stty"); ! 798: #endif /* v9 */ ! 799: #endif /* uxiii */ ! 800: return(x); ! 801: } ! 802: ! 803: /* Exclusive uucp file locking control */ ! 804: /* ! 805: by H. Fischer, creative non-Bell coding ! ! 806: copyright rights for lock modules assigned to Columbia University ! 807: */ ! 808: static char * ! 809: xxlast(s,c) char *s; char c; { /* Equivalent to strrchr() */ ! 810: int i; ! 811: for (i = strlen(s); i > 0; i--) ! 812: if ( s[i-1] == c ) return( s + (i - 1) ); ! 813: return(NULL); ! 814: } ! 815: static ! 816: look4lk(ttname) char *ttname; { ! 817: extern char *strcat(), *strcpy(); ! 818: char *device, *devname; ! 819: char lockfil[50]; /* Max length for lock file name */ ! 820: ! 821: #ifdef ISIII ! 822: char *lockdir = "/etc/locks"; ! 823: #else ! 824: #ifdef ATT3BX ! 825: char *lockdir = "/usr/spool/locks"; ! 826: #else ! 827: #ifdef NEWUUCP ! 828: char *lockdir = "/usr/spool/uucp/LCK"; ! 829: #else ! 830: char *lockdir = "/usr/spool/uucp"; ! 831: #endif /* newuucp */ ! 832: #endif /* att3bx */ ! 833: #endif /* isiii */ ! 834: ! 835: device = ( (devname=xxlast(ttname,'/')) != NULL ? devname+1 : ttname); ! 836: ! 837: #ifdef ISIII ! 838: (void) strcpy( lockfil, device ); ! 839: #else ! 840: strcat( strcpy( lockfil, "LCK.." ), device ); ! 841: #endif /* isiii */ ! 842: ! 843: if (access( lockdir, 04 ) < 0) { /* read access denied on lock dir */ ! 844: fprintf(stderr,"Warning, read access to lock directory denied\n"); ! 845: return( 1 ); /* cannot check or set lock file */ ! 846: } ! 847: ! 848: strcat(strcat(strcpy(flfnam,lockdir),"/"), lockfil); ! 849: debug(F110,"look4lk",flfnam,0); ! 850: ! 851: if ( ! access( flfnam, 00 ) ) { /* print out lock file entry */ ! 852: char lckcmd[40] ; ! 853: strcat( strcpy(lckcmd, "ls -l ") , flfnam); ! 854: system(lckcmd); ! 855: if (access(flfnam,02) == 0) ! 856: printf("(You may type \"! rm %s\" to remove this file)\n",flfnam); ! 857: return( -1 ); ! 858: } ! 859: if ( access( lockdir, 02 ) < 0 ) { /* lock file cannot be written */ ! 860: fprintf(stderr,"Warning, write access to lock directory denied\n"); ! 861: return( 1 ); ! 862: } ! 863: return( 0 ); /* okay to go ahead and lock */ ! 864: } ! 865: ! 866: /* T T L O C K */ ! 867: ! 868: static ! 869: ttlock(ttfd) char *ttfd; { /* lock uucp if possible */ ! 870: #ifndef aegis ! 871: #ifdef ATT3BX ! 872: FILE *lck_fild; ! 873: #endif /* att3bx */ ! 874: int lck_fil, l4l; ! 875: int pid_buf = getpid(); /* pid to save in lock file */ ! 876: ! 877: hasLock = 0; /* not locked yet */ ! 878: l4l = look4lk(ttfd); ! 879: if (l4l < 0) return (-1); /* already locked */ ! 880: if (l4l == 1) return (0); /* can't read/write lock directory */ ! 881: lck_fil = creat(flfnam, 0444); /* create lock file ... */ ! 882: if (lck_fil < 0) return (-1); /* create of lockfile failed */ ! 883: /* creat leaves file handle open for writing -- hf */ ! 884: #ifdef ATT3BX ! 885: fprintf((lck_fild = fdopen(lck_fil, "w")), "%10d\n", pid_buf); ! 886: fflush(lck_fild); ! 887: #else ! 888: write (lck_fil, &pid_buf, sizeof(pid_buf) ); /* uucp expects int in file */ ! 889: #endif /* att3bx */ ! 890: close (lck_fil); ! 891: hasLock = 1; /* now is locked */ ! 892: #endif /* not aegis */ ! 893: return(0); ! 894: } ! 895: ! 896: /* T T U N L O C K */ ! 897: ! 898: static ! 899: ttunlck() { /* kill uucp lock if possible */ ! 900: if (hasLock) return( unlink( flfnam ) ); ! 901: return(0); ! 902: } ! 903: ! 904: /* New-style (4.3BSD) UUCP line direction control (Stan Barber, Rice U) */ ! 905: ! 906: #ifdef NEWUUCP ! 907: acucntrl(flag,ttname) char *flag, *ttname; { ! 908: char x[DEVNAMLEN+32], *device, *devname; ! 909: ! 910: if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */ ! 911: return; /* just return. */ ! 912: device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname); ! 913: if (strncmp(device,"LCK..",4) == 0) device += 5; ! 914: sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device); ! 915: debug(F000,"called ",x,0); ! 916: system(x); ! 917: } ! 918: #endif /* newuucp */ ! 919: ! 920: /* T T P K T -- Condition the communication line for packets. */ ! 921: /* or for modem dialing */ ! 922: ! 923: #define DIALING 4 /* flags (via flow) for modem handling */ ! 924: #define CONNECT 5 ! 925: ! 926: /* If called with speed > -1, also set the speed. */ ! 927: ! 928: /* Returns 0 on success, -1 on failure. */ ! 929: ! 930: ttpkt(speed,flow,parity) int speed, flow, parity; { ! 931: int s, x; ! 932: ! 933: if (ttyfd < 0) return(-1); /* Not open. */ ! 934: ttprty = parity; /* Let other tt functions see this. */ ! 935: debug(F101,"ttpkt setting ttprty","",ttprty); ! 936: s = ttsspd(speed); /* Check the speed */ ! 937: ! 938: #ifndef UXIII ! 939: if (flow == 1) ttraw.sg_flags |= TANDEM; /* Use XON/XOFF if selected */ ! 940: if (flow == 0) ttraw.sg_flags &= ~TANDEM; ! 941: ttraw.sg_flags |= RAW; /* Go into raw mode */ ! 942: ttraw.sg_flags &= ~(ECHO|CRMOD); /* Use CR for break character */ ! 943: #ifdef TOWER1 ! 944: ttraw.sg_flags &= ~ANYP; /* Must tell Tower no parity */ ! 945: #endif /* tower1 */ ! 946: if (s > -1) ttraw.sg_ispeed = ttraw.sg_ospeed = s; /* Do the speed */ ! 947: #ifdef V9 ! 948: if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) return(-1); /* Set the new modes. */ ! 949: #else ! 950: if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */ ! 951: #endif /* v9 */ ! 952: ! 953: #ifdef MYREAD ! 954: #ifdef BSD4 ! 955: /* Try to make reads nonblocking */ ! 956: #ifdef aegis ! 957: return(0); ! 958: #endif /* aegis */ ! 959: #ifdef FIONBIO ! 960: x = 1; ! 961: if (ioctl(ttyfd,FIONBIO,&x) < 0) { ! 962: perror("ttpkt ioctl"); ! 963: return(-1); ! 964: } ! 965: #else /* fionbio */ ! 966: #ifdef FNDELAY ! 967: if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) | FNDELAY) == -1) { ! 968: return(-1); ! 969: } ! 970: #endif /* fndelay */ ! 971: #endif /* bsd4 */ ! 972: ttflui(); /* Flush any pending input */ ! 973: return(0); ! 974: #endif /* bsd4 */ ! 975: #else /* myread */ ! 976: ttflui(); /* Flush any pending input */ ! 977: return(0); ! 978: #endif /* myread */ ! 979: #endif /* not uxiii */ ! 980: ! 981: #ifdef UXIII ! 982: if (flow == 1) ttraw.c_iflag |= (IXON|IXOFF); ! 983: if (flow == 0) ttraw.c_iflag &= ~(IXON|IXOFF); ! 984: ! 985: if (flow == DIALING) ttraw.c_cflag |= CLOCAL|HUPCL; ! 986: if (flow == CONNECT) ttraw.c_cflag &= ~CLOCAL; ! 987: ! 988: ttraw.c_lflag &= ~(ICANON|ECHO); ! 989: ttraw.c_lflag |= ISIG; /* do check for interrupt */ ! 990: ttraw.c_iflag |= (BRKINT|IGNPAR); ! 991: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY); ! 992: ttraw.c_oflag &= ~OPOST; ! 993: ttraw.c_cflag &= ~(CSIZE|PARENB); ! 994: ttraw.c_cflag |= (CS8|CREAD); ! 995: #ifdef IX370 ! 996: ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */ ! 997: ttraw.c_cc[5] = 1; ! 998: #else ! 999: #ifdef VXVE ! 1000: ttraw.c_cc[4] = 1; /* [VMIN] for CDC VX/VE */ ! 1001: ttraw.c_cc[5] = 0; /* [VTIME] for CDC VX/VE */ ! 1002: #else ! 1003: #ifdef MYREAD ! 1004: ttraw.c_cc[4] = 200; /* return max of this many characters */ ! 1005: ttraw.c_cc[5] = 1; /* or when this many secs/10 expire w/no input */ ! 1006: #else ! 1007: ttraw.c_cc[4] = 1; /* [VMIN] Maybe should be bigger for all Sys V? */ ! 1008: ttraw.c_cc[5] = 0; /* [VTIME] Should be set high enough to ignore */ ! 1009: /* intercharacter spacing? */ ! 1010: /* But then we have to distinguish between Sys III and Sys V.. */ ! 1011: #endif ! 1012: #endif ! 1013: #endif ! 1014: if (s > -1) { /* set speed */ ! 1015: ttraw.c_cflag &= ~CBAUD; ! 1016: ttraw.c_cflag |= s; ! 1017: } ! 1018: if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */ ! 1019: if (flow == DIALING) { ! 1020: #ifndef aegis ! 1021: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) ! 1022: return(-1); ! 1023: #endif /* not aegis */ ! 1024: close( open(ttnmsv,2) ); /* magic to force mode change!!! */ ! 1025: } ! 1026: ttflui(); ! 1027: return(0); ! 1028: #endif /* uxiii */ ! 1029: } ! 1030: ! 1031: /* T T V T -- Condition communication line for use as virtual terminal */ ! 1032: ! 1033: ttvt(speed,flow) int speed, flow; { ! 1034: int s; ! 1035: if (ttyfd < 0) return(-1); /* Not open. */ ! 1036: ! 1037: s = ttsspd(speed); /* Check the speed */ ! 1038: ! 1039: #ifndef UXIII ! 1040: if (flow == 1) tttvt.sg_flags |= TANDEM; /* XON/XOFF if selected */ ! 1041: if (flow == 0) tttvt.sg_flags &= ~TANDEM; ! 1042: tttvt.sg_flags |= RAW; /* Raw mode */ ! 1043: #ifdef TOWER1 ! 1044: tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or system III ??? parity */ ! 1045: #else ! 1046: tttvt.sg_flags &= ~ECHO; /* No echo */ ! 1047: #endif ! 1048: if (s > -1) tttvt.sg_ispeed = tttvt.sg_ospeed = s; /* Do the speed */ ! 1049: #ifdef V9 ! 1050: if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) return(-1); ! 1051: #else ! 1052: if (stty(ttyfd,&tttvt) < 0) return(-1); ! 1053: #endif ! 1054: ! 1055: #ifdef MYREAD ! 1056: #ifdef BSD4 ! 1057: /* Make reads nonblocking */ ! 1058: #ifdef aegis ! 1059: return(0); ! 1060: #endif ! 1061: if (fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL,0) | FNDELAY) == -1) ! 1062: return(-1); ! 1063: else return(0); ! 1064: #endif /* bsd4 */ ! 1065: #endif /* myread */ ! 1066: ! 1067: #else /* uxiii */ ! 1068: if (flow == 1) tttvt.c_iflag |= (IXON|IXOFF); ! 1069: if (flow == 0) tttvt.c_iflag &= ~(IXON|IXOFF); ! 1070: ! 1071: if (flow == DIALING) tttvt.c_cflag |= CLOCAL|HUPCL; ! 1072: if (flow == CONNECT) tttvt.c_cflag &= ~CLOCAL; ! 1073: ! 1074: tttvt.c_lflag &= ~(ISIG|ICANON|ECHO); ! 1075: tttvt.c_iflag |= (IGNBRK|IGNPAR); ! 1076: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY); ! 1077: tttvt.c_oflag &= ~OPOST; ! 1078: tttvt.c_cflag &= ~(CSIZE|PARENB); ! 1079: tttvt.c_cflag |= (CS8|CREAD); ! 1080: tttvt.c_cc[4] = 1; ! 1081: tttvt.c_cc[5] = 0; ! 1082: ! 1083: if (s > -1) { /* set speed */ ! 1084: tttvt.c_cflag &= ~CBAUD; ! 1085: tttvt.c_cflag |= s; ! 1086: } ! 1087: if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */ ! 1088: ! 1089: if (flow == DIALING) { ! 1090: #ifndef aegis ! 1091: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) ! 1092: return(-1); ! 1093: #endif ! 1094: close( open(ttnmsv,2) ); /* magic to force mode change!!! */ ! 1095: } ! 1096: #endif ! 1097: return(0); ! 1098: } ! 1099: ! 1100: /* T T S S P D -- Return the internal baud rate code for 'speed'. */ ! 1101: ! 1102: ttsspd(speed) { ! 1103: int s, spdok; ! 1104: ! 1105: if (speed < 0) return(-1); ! 1106: spdok = 1; /* Assume arg ok */ ! 1107: switch (speed) { ! 1108: case 0: s = B0; break; /* Just the common ones. */ ! 1109: case 110: s = B110; break; /* The others from ttydev.h */ ! 1110: case 150: s = B150; break; /* could also be included if */ ! 1111: case 300: s = B300; break; /* necessary... */ ! 1112: case 600: s = B600; break; ! 1113: case 1200: s = B1200; break; ! 1114: case 1800: s = B1800; break; ! 1115: case 2400: s = B2400; break; ! 1116: case 4800: s = B4800; break; ! 1117: case 9600: s = B9600; break; ! 1118: #ifdef PLEXUS ! 1119: case 19200: s = EXTA; break; ! 1120: #endif ! 1121: #ifdef aegis ! 1122: case 19200: s = EXTA; break; ! 1123: #endif ! 1124: default: ! 1125: spdok = 0; ! 1126: fprintf(stderr,"Unsupported line speed - %d\n",speed); ! 1127: fprintf(stderr,"Current speed not changed\n"); ! 1128: break; ! 1129: } ! 1130: if (spdok) return(s); else return(-1); ! 1131: } ! 1132: ! 1133: /* T T F L U I -- Flush tty input buffer */ ! 1134: ! 1135: ttflui() { ! 1136: ! 1137: #ifndef UXIII ! 1138: long n; ! 1139: #endif ! 1140: if (ttyfd < 0) return(-1); /* Not open. */ ! 1141: ! 1142: ungotn = -1; /* Initialize myread() stuff */ ! 1143: inbufc = 0; ! 1144: ! 1145: #ifdef aegis ! 1146: sio_$control((short)ttyfd, sio_$flush_in, true, st); ! 1147: if (st.all != status_$ok) ! 1148: { fprintf(stderr, "flush failed: "); error_$print(st); } ! 1149: else { /* sometimes the flush doesn't work */ ! 1150: for (;;) ! 1151: { char buf[256]; ! 1152: /* eat all the characters that shouldn't be available */ ! 1153: (void)ios_$get((short)ttyfd, ios_$cond_opt, buf, 256L, st); ! 1154: if (st.all == ios_$get_conditional_failed) break; ! 1155: fprintf(stderr, "flush failed(2): "); error_$print(st); ! 1156: } ! 1157: } ! 1158: #else ! 1159: #ifdef UXIII ! 1160: #ifndef VXVE ! 1161: if (ioctl(ttyfd,TCFLSH,0) < 0) perror("flush failed"); ! 1162: #endif /* vxve */ ! 1163: #else ! 1164: #ifdef TIOCFLUSH ! 1165: #ifdef ANYBSD ! 1166: n = FREAD; /* Specify read queue */ ! 1167: if (ioctl(ttyfd,TIOCFLUSH,&n) < 0) perror("flush failed"); ! 1168: #else ! 1169: if (ioctl(ttyfd,TIOCFLUSH,0) < 0) perror("flush failed"); ! 1170: #endif ! 1171: #endif ! 1172: #endif ! 1173: #endif ! 1174: return(0); ! 1175: } ! 1176: ! 1177: /* Interrupt Functions */ ! 1178: ! 1179: ! 1180: /* Timeout handler for communication line input functions */ ! 1181: ! 1182: timerh() { ! 1183: longjmp(sjbuf,1); ! 1184: } ! 1185: ! 1186: ! 1187: /* Set up terminal interrupts on console terminal */ ! 1188: ! 1189: #ifdef UXIII ! 1190: esctrp() { /* trap console escapes (^\) */ ! 1191: conesc = 1; ! 1192: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ ! 1193: } ! 1194: #endif ! 1195: ! 1196: #ifdef V7 ! 1197: esctrp() { /* trap console escapes (^\) */ ! 1198: conesc = 1; ! 1199: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ ! 1200: } ! 1201: #endif ! 1202: ! 1203: #ifdef V9 ! 1204: esctrp() { /* trap console escapes (^\) */ ! 1205: conesc = 1; ! 1206: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ ! 1207: } ! 1208: #endif ! 1209: ! 1210: #ifdef C70 ! 1211: esctrp() { /* trap console escapes (^\) */ ! 1212: conesc = 1; ! 1213: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ ! 1214: } ! 1215: #endif ! 1216: ! 1217: /* C O N I N T -- Console Interrupt setter */ ! 1218: ! 1219: conint(f) int (*f)(); { /* Set an interrupt trap. */ ! 1220: int x, y; ! 1221: #ifdef SIGTSTP ! 1222: int stptrap(); /* Suspend trap */ ! 1223: #endif ! 1224: ! 1225: /* Check for background operation, even if not running on real tty, so that */ ! 1226: /* background flag can be set correctly. */ ! 1227: ! 1228: #ifdef BSD4 ! 1229: int mypgrp; /* In BSD, we can check whether */ ! 1230: int ctpgrp; /* this process's group is the */ ! 1231: /* same as the controlling */ ! 1232: mypgrp = getpgrp(0); /* terminal's process group. */ ! 1233: ioctl (1, TIOCGPGRP, &ctpgrp); ! 1234: x = (mypgrp != ctpgrp); /* If they differ, then background. */ ! 1235: debug(F101,"conint process group test","",x); ! 1236: #else ! 1237: x = (signal(SIGINT,SIG_IGN) == SIG_IGN); ! 1238: debug(F101,"conint signal test","",x); ! 1239: #endif ! 1240: y = isatty(0); ! 1241: debug(F101,"conint isatty test","",y); ! 1242: #ifdef BSD29 ! 1243: /* For some reason the signal() test doesn't work under 2.9 BSD... */ ! 1244: backgrd = !y; ! 1245: #else ! 1246: backgrd = (x || !y); ! 1247: #endif ! 1248: debug(F101,"conint backgrd","",backgrd); ! 1249: ! 1250: signal(SIGHUP,f); /* Ensure lockfile cleared on hangup */ ! 1251: signal(SIGTERM,f); /* or soft kill. */ ! 1252: ! 1253: /* check if invoked in background -- if so signals set to be ignored */ ! 1254: ! 1255: if (backgrd) { /* In background, ignore signals */ ! 1256: #ifdef SIGTSTP ! 1257: signal(SIGTSTP,SIG_IGN); /* Keyboard stop */ ! 1258: #endif ! 1259: signal(SIGQUIT,SIG_IGN); /* Keyboard quit */ ! 1260: signal(SIGINT,SIG_IGN); /* Keyboard interrupt */ ! 1261: } else { ! 1262: signal(SIGINT,f); /* Catch terminal interrupt */ ! 1263: #ifdef SIGTSTP ! 1264: signal(SIGTSTP,stptrap); /* Keyboard stop */ ! 1265: #endif ! 1266: #ifdef UXIII ! 1267: signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */ ! 1268: if (conesc) conesc = 0; /* Clear out pending escapes */ ! 1269: #else ! 1270: #ifdef V7 ! 1271: signal(SIGQUIT,esctrp); /* V7 like Sys III/V */ ! 1272: if (conesc) conesc = 0; ! 1273: #else ! 1274: #ifdef V9 ! 1275: signal(SIGQUIT,esctrp); /* V7 like Sys III/V */ ! 1276: if (conesc) conesc = 0; ! 1277: #else ! 1278: #ifdef aegis ! 1279: signal(SIGQUIT,f); /* Apollo, catch it like others. */ ! 1280: #else ! 1281: signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */ ! 1282: #endif ! 1283: #endif ! 1284: #endif ! 1285: #endif ! 1286: conif = 1; /* Flag console interrupts on. */ ! 1287: } ! 1288: return; ! 1289: } ! 1290: ! 1291: ! 1292: /* C O N N O I -- Reset console terminal interrupts */ ! 1293: ! 1294: connoi() { /* Console-no-interrupts */ ! 1295: ! 1296: #ifdef SIGTSTP ! 1297: signal(SIGTSTP,SIG_DFL); ! 1298: #endif ! 1299: signal(SIGINT,SIG_DFL); ! 1300: signal(SIGHUP,SIG_DFL); ! 1301: signal(SIGQUIT,SIG_DFL); ! 1302: signal(SIGTERM,SIG_DFL); ! 1303: conif = 0; /* Flag interrupt trapping off */ ! 1304: } ! 1305: ! 1306: /* myread() -- For use by systems that can do nonblocking read() calls */ ! 1307: /* ! 1308: Returns: ! 1309: -1 if no characters available, timer expired ! 1310: -2 upon error (such as disconnect), ! 1311: otherwise value of character (0 or greater) ! 1312: */ ! 1313: myread() { ! 1314: static int inbuf_item; ! 1315: static CHAR inbuf[257]; ! 1316: CHAR readit; ! 1317: ! 1318: if (ungotn >= 0) { ! 1319: readit = ungotn; ! 1320: ungotn = -1; ! 1321: } else { ! 1322: if (inbufc > 0) { ! 1323: readit = inbuf[++inbuf_item]; ! 1324: } else { ! 1325: #ifdef aegis ! 1326: /* myread() returns -1 when no input is available. All the users of */ ! 1327: /* myread() explicitly loop until it returns a character or error. */ ! 1328: /* The Apollo code waits for input to be available. */ ! 1329: ! 1330: /* read in characters */ ! 1331: inbufc = ios_$get((short)ttyfd, ios_$cond_opt, inbuf, 256L, st); ! 1332: errno = EIO; ! 1333: if (st.all == ios_$get_conditional_failed) /* get at least one */ ! 1334: inbufc = ios_$get((short)ttyfd, 0, inbuf, 1L, st); ! 1335: if (st.all == ios_$end_of_file) inbufc = 0; ! 1336: else if (st.all != status_$ok) ! 1337: { inbufc = -1; errno = EIO; } ! 1338: #else ! 1339: inbufc = read(ttyfd,inbuf,256); ! 1340: if (inbufc > 0) { ! 1341: inbuf[inbufc] = '\0'; ! 1342: debug(F101,"myread read","",inbufc); ! 1343: } ! 1344: #endif /* aegis */ ! 1345: if (inbufc == 0) { ! 1346: if (ttmdm) { ! 1347: debug(F101,"myread read=0, ttmdm","",ttmdm); ! 1348: errno = 9999; /* magic number for no carrier */ ! 1349: return(-2); /* end of file has no errno */ ! 1350: } else return(-1); /* in sys 5 means no data available */ ! 1351: } ! 1352: if (inbufc < 0) { /* Real error */ ! 1353: #ifdef EWOULDBLOCK ! 1354: if (errno == EWOULDBLOCK) return(-1); else return(-2); ! 1355: #else ! 1356: return(-2); ! 1357: #endif /* ewouldblock */ ! 1358: } ! 1359: readit = inbuf[inbuf_item = 0]; ! 1360: } ! 1361: inbufc--; ! 1362: } ! 1363: return(((int) readit) & 255); ! 1364: } ! 1365: ! 1366: myunrd(ch) CHAR ch; { /* push back up to one character */ ! 1367: ungotn = ch; ! 1368: } ! 1369: ! 1370: /* I N I T R A W Q -- Set up to read /DEV/KMEM for character count. */ ! 1371: ! 1372: #ifdef V7 ! 1373: /* ! 1374: Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This ! 1375: eliminates blocking on a read, because we can read /dev/kmem to get the ! 1376: number of characters available for raw input. If your system can't ! 1377: or you won't let it read /dev/kmem (the world that is) then you must ! 1378: figure out a different way to do the counting of characters available, ! 1379: or else replace this by a dummy function that always returns 0. ! 1380: */ ! 1381: /* ! 1382: * Call this routine as: initrawq(tty) ! 1383: * where tty is the file descriptor of a terminal. It will return ! 1384: * (as a char *) the kernel-mode memory address of the rawq character ! 1385: * count, which may then be read. It has the side-effect of flushing ! 1386: * input on the terminal. ! 1387: */ ! 1388: /* ! 1389: * John Mackin, Physiology Dept., University of Sydney (Australia) ! 1390: * ...!decvax!mulga!physiol.su.oz!john ! 1391: * ! 1392: * Permission is hereby granted to do anything with this code, as ! 1393: * long as this comment is retained unmodified and no commercial ! 1394: * advantage is gained. ! 1395: */ ! 1396: #include <a.out.h> ! 1397: #include <sys/proc.h> ! 1398: ! 1399: char *initrawq(tty) int tty; { ! 1400: #ifdef UTS24 ! 1401: return(0); ! 1402: #else ! 1403: #ifdef BSD29 ! 1404: return(0); ! 1405: #else ! 1406: long lseek(); ! 1407: static struct nlist nl[] = { ! 1408: {PROCNAME}, ! 1409: {NPROCNAME}, ! 1410: {""} ! 1411: }; ! 1412: static struct proc *pp; ! 1413: char *malloc(), *qaddr, *p, c; ! 1414: int m, pid, me; ! 1415: NPTYPE xproc; /* Its type is defined in makefile. */ ! 1416: int catch(); ! 1417: ! 1418: me = getpid(); ! 1419: if ((m = open("/dev/kmem", 0)) < 0) err("kmem"); ! 1420: nlist(BOOTNAME, nl); ! 1421: if (nl[0].n_type == 0) err("proc array"); ! 1422: ! 1423: if (nl[1].n_type == 0) err("nproc"); ! 1424: ! 1425: lseek(m, (long)(nl[1].n_value), 0); ! 1426: read (m, &xproc, sizeof(xproc)); ! 1427: signal(SIGALRM, catch); ! 1428: if ((pid = fork()) == 0) { ! 1429: while(1) ! 1430: read(tty, &c, 1); ! 1431: } ! 1432: alarm(2); ! 1433: ! 1434: if(setjmp(jjbuf) == 0) { ! 1435: while(1) ! 1436: read(tty, &c, 1); ! 1437: } ! 1438: signal(SIGALRM, SIG_DFL); ! 1439: ! 1440: #ifdef DIRECT ! 1441: pp = (struct proc *) nl[0].n_value; ! 1442: #else ! 1443: if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek"); ! 1444: if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr"); ! 1445: #endif ! 1446: lseek(m, (long)(nl[1].n_value), 0); ! 1447: read(m, &xproc, sizeof(xproc)); ! 1448: ! 1449: if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc"); ! 1450: if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc"); ! 1451: if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc)) ! 1452: err("read proc table"); ! 1453: for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) { ! 1454: if (pp -> p_pid == (short) pid) goto iout; ! 1455: } ! 1456: err("no such proc"); ! 1457: ! 1458: iout: ! 1459: close(m); ! 1460: qaddr = (char *)(pp -> p_wchan); ! 1461: free (p); ! 1462: kill(pid, SIGKILL); ! 1463: wait((int *)0); /* Destroy the ZOMBIEs! */ ! 1464: return (qaddr); ! 1465: #endif ! 1466: #endif ! 1467: } ! 1468: ! 1469: /* More V7-support functions... */ ! 1470: ! 1471: static ! 1472: err(s) char *s; { ! 1473: char buf[200]; ! 1474: ! 1475: sprintf(buf, "fatal error in initrawq: %s", s); ! 1476: perror(buf); ! 1477: doexit(1); ! 1478: } ! 1479: ! 1480: static ! 1481: catch() { ! 1482: longjmp(jjbuf, -1); ! 1483: } ! 1484: ! 1485: ! 1486: /* G E N B R K -- Simulate a modem break. */ ! 1487: ! 1488: #define BSPEED B150 ! 1489: ! 1490: genbrk(fn) int fn; { ! 1491: struct sgttyb ttbuf; ! 1492: int ret, sospeed; ! 1493: ! 1494: ret = ioctl(fn, TIOCGETP, &ttbuf); ! 1495: sospeed = ttbuf.sg_ospeed; ! 1496: ttbuf.sg_ospeed = BSPEED; ! 1497: ret = ioctl(fn, TIOCSETP, &ttbuf); ! 1498: ret = write(fn, "\0\0\0\0\0\0\0\0\0\0\0\0", 8); ! 1499: ttbuf.sg_ospeed = sospeed; ! 1500: ret = ioctl(fn, TIOCSETP, &ttbuf); ! 1501: ret = write(fn, "@", 1); ! 1502: return; ! 1503: } ! 1504: #endif ! 1505: ! 1506: /* T T C H K -- Tell how many characters are waiting in tty input buffer */ ! 1507: ! 1508: ttchk() { ! 1509: int x; long n; ! 1510: #ifdef FIONREAD ! 1511: x = ioctl(ttyfd, FIONREAD, &n); /* Berkeley and maybe some others */ ! 1512: debug(F101,"ttchk","",n); ! 1513: return((x < 0) ? 0 : n); ! 1514: #else ! 1515: #ifdef V7 ! 1516: lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */ ! 1517: x = read(kmem[TTY], &n, sizeof(int)); ! 1518: return((x == sizeof(int))? n: 0); ! 1519: #else ! 1520: #ifdef UXIII ! 1521: return(inbufc + (ungotn >= 0) ); /* Sys III, Sys V */ ! 1522: #else ! 1523: #ifdef PROVX1 ! 1524: x = ioctl(ttyfd, TIOCQCNT, &ttbuf); /* Pro/3xx Venix V.1 */ ! 1525: n = ttbuf.sg_ispeed & 0377; ! 1526: return((x < 0) ? 0 : n); ! 1527: #else ! 1528: #ifdef aegis ! 1529: return(inbufc + (ungotn >= 0) ); /* Apollo Aegis */ ! 1530: #else ! 1531: #ifdef C70 ! 1532: return(inbufc + (ungotn >= 0) ); /* etc... */ ! 1533: #else ! 1534: return(0); ! 1535: #endif ! 1536: #endif ! 1537: #endif ! 1538: #endif ! 1539: #endif ! 1540: #endif ! 1541: } ! 1542: ! 1543: ! 1544: /* T T X I N -- Get n characters from tty input buffer */ ! 1545: ! 1546: /* Returns number of characters actually gotten, or -1 on failure */ ! 1547: ! 1548: /* Intended for use only when it is known that n characters are actually */ ! 1549: /* Available in the input buffer. */ ! 1550: ! 1551: ttxin(n,buf) int n; char *buf; { ! 1552: int x; ! 1553: ! 1554: #ifdef MYREAD ! 1555: for( x = 0; (x > -1) && (x < n); buf[x++] = myread() ); ! 1556: #else ! 1557: debug(F101,"ttxin: n","",n); ! 1558: x = read(ttyfd,buf,n); ! 1559: debug(F101," x","",x); ! 1560: #endif ! 1561: if (x > 0) buf[x] = '\0'; ! 1562: if (x < 0) x = -1; ! 1563: return(x); ! 1564: } ! 1565: ! 1566: /* T T O L -- Similar to "ttinl", but for writing. */ ! 1567: ! 1568: ttol(s,n) int n; char *s; { ! 1569: int x; ! 1570: if (ttyfd < 0) return(-1); /* Not open. */ ! 1571: x = write(ttyfd,s,n); ! 1572: debug(F111,"ttol",s,n); ! 1573: if (x < 0) debug(F101,"ttol failed","",x); ! 1574: return(x); ! 1575: } ! 1576: ! 1577: ! 1578: /* T T O C -- Output a character to the communication line */ ! 1579: ! 1580: ttoc(c) char c; { ! 1581: if (ttyfd < 0) return(-1); /* Not open. */ ! 1582: return(write(ttyfd,&c,1)); ! 1583: } ! 1584: ! 1585: /* T T I N L -- Read a record (up to break character) from comm line. */ ! 1586: /* ! 1587: If no break character encountered within "max", return "max" characters, ! 1588: with disposition of any remaining characters undefined. Otherwise, return ! 1589: the characters that were read, including the break character, in "dest" and ! 1590: the number of characters read as the value of the function, or 0 upon end of ! 1591: file, or -1 if an error occurred. Times out & returns error if not completed ! 1592: within "timo" seconds. ! 1593: */ ! 1594: #define CTRLC '\03' ! 1595: ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol; { ! 1596: int x = 0, ccn = 0, c, i, j, m, n; /* local variables */ ! 1597: ! 1598: if (ttyfd < 0) return(-1); /* Not open. */ ! 1599: ! 1600: m = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */ ! 1601: *dest = '\0'; /* Clear destination buffer */ ! 1602: if (timo) signal(SIGALRM,timerh); /* Enable timer interrupt */ ! 1603: alarm(timo); /* Set it. */ ! 1604: if (setjmp(sjbuf)) { /* Timer went off? */ ! 1605: x = -1; ! 1606: } else { ! 1607: i = 0; /* Next char to process */ ! 1608: j = 0; /* Buffer position */ ! 1609: while (1) { ! 1610: if ((n = ttchk()) > 0) { /* See how many chars have arrived */ ! 1611: if (n > (max - j)) n = max - j; ! 1612: if ((n = ttxin(n,dest+i)) < 0) { /* Get them all at once */ ! 1613: x = -1; ! 1614: break; ! 1615: } ! 1616: } else { /* Or else... */ ! 1617: n = 1; /* just wait for a char */ ! 1618: if ((c = ttinc(0)) == -1) { ! 1619: x = -1; ! 1620: break; ! 1621: } ! 1622: dest[i] = c; /* Got one. */ ! 1623: } ! 1624: j = i + n; /* Remember next buffer position. */ ! 1625: if (j >= max) { ! 1626: debug(F101,"ttinl buffer overflow","",j); ! 1627: x = -1; ! 1628: break; ! 1629: } ! 1630: for (i; i < j; i++) { /* Go thru all chars we just got */ ! 1631: dest[i] &= m; /* Strip any parity */ ! 1632: if (dest[i] == eol) { /* Got eol? */ ! 1633: dest[++i] = '\0'; /* Yes, tie off string, */ ! 1634: alarm(0); /* turn off timers, etc, */ ! 1635: if (timo) signal(SIGALRM,SIG_DFL); /* and return length. */ ! 1636: return(i); ! 1637: } else if ((dest[i] & 0177) == CTRLC) { /* Check for ^C^C */ ! 1638: if (++ccn > 1) { /* If we got 2 in a row, clean up */ ! 1639: alarm(0); /* and exit. */ ! 1640: signal(SIGALRM,SIG_DFL); ! 1641: fprintf(stderr,"^C..."); ! 1642: ttres(); ! 1643: fprintf(stderr,"\n"); ! 1644: return(-2); ! 1645: } ! 1646: } else ccn = 0; /* Not ^C, so reset ^C counter, */ ! 1647: } ! 1648: } ! 1649: } ! 1650: debug(F100,"ttinl timout","",0); /* Get here on timeout. */ ! 1651: debug(F111," with",dest,i); ! 1652: alarm(0); /* Turn off timer */ ! 1653: signal(SIGALRM,SIG_DFL); /* and interrupt, */ ! 1654: return(x); /* and return error code. */ ! 1655: } ! 1656: ! 1657: /* T T I N C -- Read a character from the communication line */ ! 1658: ! 1659: ttinc(timo) int timo; { ! 1660: int m, n = 0; ! 1661: CHAR ch = 0; ! 1662: ! 1663: m = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */ ! 1664: if (ttyfd < 0) return(-1); /* Not open. */ ! 1665: if (timo <= 0) { /* Untimed. */ ! 1666: #ifdef MYREAD ! 1667: /* comm line failure returns -1 thru myread, so no &= 0377 */ ! 1668: while ((n = myread()) == -1) ; /* Wait for a character... */ ! 1669: if (n == -2) n++; ! 1670: return( (n < 0) ? -1 : n & m ); ! 1671: #else ! 1672: while ((n = read(ttyfd,&ch,1)) == 0) ; /* Wait for a character. */ ! 1673: return( (n < 0) ? -1 : (ch & 0377) ); ! 1674: #endif ! 1675: } ! 1676: signal(SIGALRM,timerh); /* Timed, set up timer. */ ! 1677: alarm(timo); ! 1678: if (setjmp(sjbuf)) { ! 1679: n = -1; ! 1680: } else { ! 1681: #ifdef MYREAD ! 1682: while ((n = myread()) == -1) ; /* If managing own buffer... */ ! 1683: if (n == -2) { ! 1684: n++; ! 1685: } else { ! 1686: ch = n; ! 1687: n = 1; ! 1688: } ! 1689: #else ! 1690: n = read(ttyfd,&ch,1); /* Otherwise call the system. */ ! 1691: #endif ! 1692: } ! 1693: alarm(0); /* Turn off timer, */ ! 1694: signal(SIGALRM,SIG_DFL); /* and interrupt. */ ! 1695: return( (n < 0) ? -1 : (ch & m) ); /* Return char or -1. */ ! 1696: } ! 1697: ! 1698: /* T T S N D B -- Send a BREAK signal */ ! 1699: ! 1700: ttsndb() { ! 1701: int x; long n; char spd; ! 1702: ! 1703: if (ttyfd < 0) return(-1); /* Not open. */ ! 1704: ! 1705: #ifdef PROVX1 ! 1706: gtty(ttyfd,&ttbuf); /* Get current tty flags */ ! 1707: spd = ttbuf.sg_ospeed; /* Save speed */ ! 1708: ttbuf.sg_ospeed = B50; /* Change to 50 baud */ ! 1709: stty(ttyfd,&ttbuf); /* ... */ ! 1710: write(ttyfd,brnuls,3); /* Send 3 nulls */ ! 1711: ttbuf.sg_ospeed = spd; /* Restore speed */ ! 1712: stty(ttyfd,&ttbuf); /* ... */ ! 1713: return(0); ! 1714: #else ! 1715: #ifdef aegis ! 1716: sio_$control((short)ttyfd, sio_$send_break, 250, st); ! 1717: return(0); ! 1718: #else ! 1719: #ifdef UXIII ! 1720: if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) { /* Send a BREAK */ ! 1721: perror("Can't send BREAK"); ! 1722: return(-1); ! 1723: } ! 1724: return(0); ! 1725: #else ! 1726: #ifdef ANYBSD ! 1727: n = FWRITE; /* Flush output queue. */ ! 1728: ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */ ! 1729: if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */ ! 1730: perror("Can't send BREAK"); ! 1731: return(-1); ! 1732: } ! 1733: x = msleep(275); /* Sleep for so many milliseconds */ ! 1734: if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */ ! 1735: perror("BREAK stuck!!!"); ! 1736: doexit(1); /* Get out, closing the line. */ ! 1737: /* with exit status = 1 */ ! 1738: } ! 1739: return(x); ! 1740: #else ! 1741: #ifdef V7 ! 1742: genbrk(ttyfd); /* Simulate a BREAK */ ! 1743: return(x); ! 1744: #endif ! 1745: #endif ! 1746: #endif ! 1747: #endif ! 1748: #endif ! 1749: } ! 1750: ! 1751: /* M S L E E P -- Millisecond version of sleep(). */ ! 1752: ! 1753: /* ! 1754: Intended only for small intervals. For big ones, just use sleep(). ! 1755: */ ! 1756: ! 1757: msleep(m) int m; { ! 1758: ! 1759: #ifdef aegis ! 1760: time_$clock_t dur; ! 1761: ! 1762: dur.c2.high16 = 0; ! 1763: dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */ ! 1764: time_$wait(time_$relative, dur, st); ! 1765: return(0); ! 1766: #else ! 1767: #ifdef PROVX1 ! 1768: if (m <= 0) return(0); ! 1769: sleep(-((m * 60 + 500) / 1000)); ! 1770: return(0); ! 1771: #endif ! 1772: ! 1773: #ifdef ANYBSD ! 1774: int t1, t3, t4; ! 1775: if (m <= 0) return(0); ! 1776: #ifndef BSD42 ! 1777: /* 2.9 and 4.1 BSD do it this way */ ! 1778: if (ftime(&ftp) < 0) return(-1); /* Get current time. */ ! 1779: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; ! 1780: while (1) { ! 1781: ftime(&ftp); /* new time */ ! 1782: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; ! 1783: if (t3 > m) return(t3); ! 1784: } ! 1785: #else ! 1786: /* 4.2 & above can do it with select()... */ ! 1787: if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */ ! 1788: t1 = tv.tv_sec; /* Seconds */ ! 1789: ! 1790: tv.tv_sec = 0; /* Use select() */ ! 1791: tv.tv_usec = m * 1000; ! 1792: return(select( 0, (int *)0, (int *)0, (int *)0, &tv) ); ! 1793: #endif ! 1794: #endif ! 1795: ! 1796: /* The clock-tick business is a pain. Wm. E. Davidsen suggested: */ ! 1797: /* #include <sys/param.h> */ ! 1798: /* #define CLOCK_TICK 1000/HZ */ ! 1799: /* But I don't see the symbol HZ in this file on my VAX. */ ! 1800: /* Maybe just for XENIX. */ ! 1801: ! 1802: #ifdef UXIII ! 1803: #ifdef XENIX ! 1804: /* Actually, watch out. It's 50 on the AT, 20 on older PCs... */ ! 1805: #define CLOCK_TICK 50 /* millisecs per clock tick */ ! 1806: #else ! 1807: #ifndef XENIX ! 1808: #define CLOCK_TICK 17 /* 1/60 sec */ ! 1809: #endif ! 1810: #endif ! 1811: ! 1812: extern long times(); ! 1813: long t1, t2, tarray[4]; ! 1814: int t3; ! 1815: ! 1816: /* In SCO Xenix 2.1.3 or later, you can use nap((long)m) to do this. */ ! 1817: ! 1818: if (m <= 0) return(0); ! 1819: if ((t1 = times(tarray)) < 0) return(-1); ! 1820: while (1) { ! 1821: if ((t2 = times(tarray)) < 0) return(-1); ! 1822: t3 = ((int)(t2 - t1)) * CLOCK_TICK; ! 1823: if (t3 > m) return(t3); ! 1824: } ! 1825: #endif ! 1826: ! 1827: #ifdef TOWER1 ! 1828: int t1, t3; ! 1829: if (m <= 0) return(0); ! 1830: if (ftime(&ftp) < 0) return(-1); /* Get current time. */ ! 1831: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; ! 1832: while (1) { ! 1833: ftime(&ftp); /* new time */ ! 1834: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; ! 1835: if (t3 > m) return (t3); ! 1836: } ! 1837: #endif ! 1838: #endif ! 1839: } ! 1840: ! 1841: /* R T I M E R -- Reset elapsed time counter */ ! 1842: ! 1843: rtimer() { ! 1844: tcount = time( (long *) 0 ); ! 1845: } ! 1846: ! 1847: ! 1848: /* G T I M E R -- Get current value of elapsed time counter in seconds */ ! 1849: ! 1850: gtimer() { ! 1851: int x; ! 1852: x = (int) (time( (long *) 0 ) - tcount); ! 1853: rtimer(); ! 1854: return( (x < 0) ? 0 : x ); ! 1855: } ! 1856: ! 1857: ! 1858: /* Z T I M E -- Return date/time string */ ! 1859: ! 1860: ztime(s) char **s; { ! 1861: ! 1862: #ifdef UXIII ! 1863: extern long time(); /* Sys III/V way to do it */ ! 1864: char *ctime(); ! 1865: long clock_storage; ! 1866: ! 1867: clock_storage = time( (long *) 0 ); ! 1868: *s = ctime( &clock_storage ); ! 1869: #endif ! 1870: ! 1871: #ifdef PROVX1 ! 1872: int utime[2]; /* Venix way */ ! 1873: time(utime); ! 1874: *s = ctime(utime); ! 1875: #endif ! 1876: ! 1877: #ifdef ANYBSD ! 1878: char *asctime(); /* Berkeley way */ ! 1879: struct tm *localtime(); ! 1880: struct tm *tp; ! 1881: #ifdef BSD42 ! 1882: gettimeofday(&tv, &tz); /* BSD 4.2 */ ! 1883: time(&tv.tv_sec); ! 1884: tp = localtime(&tv.tv_sec); ! 1885: #else ! 1886: time(&clock); /* BSD 4.1, 2.9 ... ceb */ ! 1887: tp = localtime(&clock); ! 1888: #endif ! 1889: *s = asctime(tp); ! 1890: #endif ! 1891: ! 1892: #ifdef TOWER1 ! 1893: char *asctime(); /* Tower way */ ! 1894: struct tm *localtime(); ! 1895: struct tm *tp; ! 1896: ! 1897: time(&clock); ! 1898: tp = localtime(&clock); ! 1899: *s = asctime(tp); ! 1900: #endif ! 1901: #ifdef V7 ! 1902: char *asctime(); /* V7 way */ ! 1903: struct tm *localtime(); ! 1904: struct tm *tp; ! 1905: ! 1906: time(&clock); ! 1907: tp = localtime(&clock); ! 1908: *s = asctime(tp); ! 1909: #endif ! 1910: } ! 1911: ! 1912: /* C O N G M -- Get console terminal modes. */ ! 1913: ! 1914: /* ! 1915: Saves current console mode, and establishes variables for switching between ! 1916: current (presumably normal) mode and other modes. ! 1917: */ ! 1918: ! 1919: congm() { ! 1920: if (!isatty(0)) return(0); /* only for real ttys */ ! 1921: #ifdef aegis ! 1922: ios_$inq_type_uid(ios_$stdin, conuid, st); ! 1923: if (st.all != status_$ok) ! 1924: { fprintf(stderr, "problem getting stdin objtype: "); error_$print(st); } ! 1925: concrp = (conuid == mbx_$uid); ! 1926: conbufn = 0; ! 1927: #endif ! 1928: #ifndef UXIII ! 1929: #ifdef V9 ! 1930: if (ioctl(0,TIOCGETP,&ccold) < 0) { ! 1931: perror("ckutio:congm:ioctl(...ccold)"); ! 1932: return(-1); ! 1933: } ! 1934: if (ioctl(0,TIOCGETP,&cccbrk) < 0) { ! 1935: perror("ckutio:congm:ioctl(...cccbrk)"); ! 1936: return(-1); ! 1937: } ! 1938: if (ioctl(0,TIOCGETP,&ccraw) < 0) { ! 1939: perror("ckutio:congm:ioctl(...ccraw)"); ! 1940: return(-1); ! 1941: } ! 1942: #else ! 1943: gtty(0,&ccold); /* Structure for restoring */ ! 1944: gtty(0,&cccbrk); /* For setting CBREAK mode */ ! 1945: gtty(0,&ccraw); /* For setting RAW mode */ ! 1946: #endif ! 1947: #else ! 1948: ioctl(0,TCGETA,&ccold); ! 1949: ioctl(0,TCGETA,&cccbrk); ! 1950: ioctl(0,TCGETA,&ccraw); ! 1951: #endif ! 1952: #ifdef VXVE ! 1953: cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */ ! 1954: ioctl(0,TCSETA,&cccbrk); ! 1955: ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */ ! 1956: ioctl(0,TCSETA,&ccraw); ! 1957: #endif /* vxve */ ! 1958: cgmf = 1; /* Flag that we got them. */ ! 1959: return(0); ! 1960: } ! 1961: ! 1962: ! 1963: /* C O N C B -- Put console in cbreak mode. */ ! 1964: ! 1965: /* Returns 0 if ok, -1 if not */ ! 1966: ! 1967: concb(esc) char esc; { ! 1968: int x; ! 1969: if (!isatty(0)) return(0); /* only for real ttys */ ! 1970: if (cgmf == 0) congm(); /* Get modes if necessary. */ ! 1971: escchr = esc; /* Make this available to other fns */ ! 1972: ckxech = 1; /* Program can echo characters */ ! 1973: #ifdef aegis ! 1974: conbufn = 0; ! 1975: if (concrp) return(write(1, "\035\002", 2)); ! 1976: if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);} ! 1977: #endif ! 1978: #ifndef UXIII ! 1979: cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */ ! 1980: cccbrk.sg_flags &= ~ECHO; /* no echo. */ ! 1981: #ifdef V9 ! 1982: x = ioctl(0,TIOCSETP,&cccbrk); /* set new modes . */ ! 1983: #else ! 1984: x = stty(0,&cccbrk); ! 1985: #endif ! 1986: #else ! 1987: cccbrk.c_lflag &= ~(ICANON|ECHO); ! 1988: cccbrk.c_cc[0] = 003; /* interrupt char is control-c */ ! 1989: cccbrk.c_cc[1] = escchr; /* escape during packet modes */ ! 1990: cccbrk.c_cc[4] = 1; ! 1991: #ifdef ZILOG ! 1992: cccbrk.c_cc[5] = 0; ! 1993: #else ! 1994: cccbrk.c_cc[5] = 1; ! 1995: #endif /* zilog */ ! 1996: x = ioctl(0,TCSETAW,&cccbrk); /* set new modes . */ ! 1997: #endif ! 1998: ! 1999: #ifndef aegis ! 2000: if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */ ! 2001: #endif ! 2002: #ifdef V7 ! 2003: if (kmem[CON] < 0) { ! 2004: qaddr[CON] = initrawq(0); ! 2005: if((kmem[CON] = open("/dev/kmem", 0)) < 0) { ! 2006: fprintf(stderr, "Can't read /dev/kmem in concb.\n"); ! 2007: perror("/dev/kmem"); ! 2008: exit(1); ! 2009: } ! 2010: } ! 2011: #endif ! 2012: return(x); ! 2013: } ! 2014: ! 2015: /* C O N B I N -- Put console in binary mode */ ! 2016: ! 2017: /* Returns 0 if ok, -1 if not */ ! 2018: ! 2019: conbin(esc) char esc; { ! 2020: if (!isatty(0)) return(0); /* only for real ttys */ ! 2021: if (cgmf == 0) congm(); /* Get modes if necessary. */ ! 2022: escchr = esc; /* Make this available to other fns */ ! 2023: ckxech = 1; /* Program can echo characters */ ! 2024: #ifdef aegis ! 2025: conbufn = 0; if (concrp) return(write(1, "\035\002", 2)); ! 2026: if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);} ! 2027: #endif ! 2028: #ifndef UXIII ! 2029: ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF */ ! 2030: ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */ ! 2031: #ifdef V9 ! 2032: return(ioctl(0,TIOCSETP,&ccraw)); ! 2033: #else ! 2034: return(stty(0,&ccraw)); ! 2035: #endif ! 2036: #else ! 2037: ccraw.c_lflag &= ~(ISIG|ICANON|ECHO); ! 2038: ccraw.c_iflag |= (BRKINT|IGNPAR); ! 2039: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF ! 2040: |INPCK|ISTRIP); ! 2041: ccraw.c_oflag &= ~OPOST; ! 2042: ! 2043: /*** Kermit used to put the console in 8-bit raw mode, but some users have ! 2044: *** pointed out that this should not be done, since some sites actually ! 2045: *** use terminals with parity settings on their Unix systems, and if we ! 2046: *** override the current settings and stop doing parity, then their terminals ! 2047: *** will display blotches for characters whose parity is wrong. Therefore, ! 2048: *** the following two lines are commented out (Larry Afrin, Clemson U): ! 2049: *** ! 2050: *** ccraw.c_cflag &= ~(PARENB|CSIZE); ! 2051: *** ccraw.c_cflag |= (CS8|CREAD); ! 2052: *** ! 2053: *** Sys III/V sites that have trouble with this can restore these lines. ! 2054: ***/ ! 2055: ccraw.c_cc[4] = 1; ! 2056: ccraw.c_cc[5] = 1; ! 2057: return(ioctl(0,TCSETAW,&ccraw) ); /* set new modes . */ ! 2058: #endif ! 2059: } ! 2060: ! 2061: ! 2062: /* C O N R E S -- Restore the console terminal */ ! 2063: ! 2064: conres() { ! 2065: if (cgmf == 0) return(0); /* Don't do anything if modes */ ! 2066: if (!isatty(0)) return(0); /* only for real ttys */ ! 2067: #ifndef UXIII /* except for sIII, */ ! 2068: sleep(1); /* not known! */ ! 2069: #endif /* (sIII does wait in ioctls) */ ! 2070: ckxech = 0; /* System should echo chars */ ! 2071: #ifdef aegis ! 2072: conbufn = 0; if (concrp) return(write(1, "\035\001", 2)); ! 2073: if (conuid == input_pad_$uid) {pad_$cooked(ios_$stdin, st); return(0);} ! 2074: #endif ! 2075: #ifndef UXIII ! 2076: #ifdef V9 ! 2077: return(ioctl(0,TIOCSETP,&ccold)); ! 2078: #else ! 2079: return(stty(0,&ccold)); /* Restore controlling tty */ ! 2080: #endif ! 2081: #else ! 2082: return(ioctl(0,TCSETAW,&ccold)); ! 2083: #endif ! 2084: } ! 2085: ! 2086: /* C O N O C -- Output a character to the console terminal */ ! 2087: ! 2088: conoc(c) char c; { ! 2089: write(1,&c,1); ! 2090: } ! 2091: ! 2092: /* C O N X O -- Write x characters to the console terminal */ ! 2093: ! 2094: conxo(x,s) char *s; int x; { ! 2095: write(1,s,x); ! 2096: } ! 2097: ! 2098: /* C O N O L -- Write a line to the console terminal */ ! 2099: ! 2100: conol(s) char *s; { ! 2101: int len; ! 2102: len = strlen(s); ! 2103: write(1,s,len); ! 2104: } ! 2105: ! 2106: /* C O N O L A -- Write an array of lines to the console terminal */ ! 2107: ! 2108: conola(s) char *s[]; { ! 2109: int i; ! 2110: for (i=0 ; *s[i] ; i++) conol(s[i]); ! 2111: } ! 2112: ! 2113: /* C O N O L L -- Output a string followed by CRLF */ ! 2114: ! 2115: conoll(s) char *s; { ! 2116: conol(s); ! 2117: write(1,"\r\n",2); ! 2118: } ! 2119: ! 2120: /* C O N C H K -- Return how many characters available at console */ ! 2121: ! 2122: conchk() { ! 2123: int x; long n; ! 2124: ! 2125: #ifdef PROVX1 ! 2126: x = ioctl(0, TIOCQCNT, &ttbuf); ! 2127: n = ttbuf.sg_ispeed & 0377; ! 2128: return((x < 0) ? 0 : n); ! 2129: #else ! 2130: #ifdef aegis ! 2131: if (conbufn > 0) return(conbufn); /* use old count if nonzero */ ! 2132: ! 2133: /* read in more characters */ ! 2134: conbufn = ios_$get(ios_$stdin, ! 2135: ios_$cond_opt, conbuf, (long)sizeof(conbuf), st); ! 2136: if (st.all != status_$ok) conbufn = 0; ! 2137: conbufp = conbuf; ! 2138: return(conbufn); ! 2139: #else ! 2140: #ifdef V7 ! 2141: lseek(kmem[CON], (long) qaddr[CON], 0); ! 2142: x = read(kmem[CON], &n, sizeof(int)); ! 2143: return((x == sizeof(int))? n: 0); ! 2144: #else ! 2145: #ifdef UXIII ! 2146: if (conesc) { /* Escape typed */ ! 2147: conesc = 0; ! 2148: signal(SIGQUIT,esctrp); /* Restore escape */ ! 2149: return(1); ! 2150: } ! 2151: return(0); ! 2152: #else ! 2153: #ifdef C70 ! 2154: if (conesc) { /* Escape typed */ ! 2155: conesc = 0; ! 2156: signal(SIGQUIT,esctrp); /* Restore escape */ ! 2157: return(1); ! 2158: } ! 2159: return(0); ! 2160: #else ! 2161: #ifdef FIONREAD ! 2162: x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */ ! 2163: return((x < 0) ? 0 : n); ! 2164: #else ! 2165: return(0); /* Others can't do. */ ! 2166: #endif ! 2167: #endif ! 2168: #endif ! 2169: #endif ! 2170: #endif ! 2171: #endif ! 2172: } ! 2173: ! 2174: /* C O N I N C -- Get a character from the console */ ! 2175: ! 2176: coninc(timo) int timo; { ! 2177: int n = 0; char ch; ! 2178: #ifdef aegis ! 2179: fflush(stdout); ! 2180: if (conchk() > 0) ! 2181: { --conbufn; return(*conbufp++ & 0377); } ! 2182: #endif ! 2183: if (timo <= 0 ) { /* untimed */ ! 2184: n = read(0, &ch, 1); /* Read a character. */ ! 2185: ch &= 0377; ! 2186: if (n > 0) return(ch); /* Return the char if read */ ! 2187: else ! 2188: #ifdef UXIII ! 2189: #ifndef CIE /* CIE Regulus has no such symbol */ ! 2190: if (n < 0 && errno == EINTR) /* if read was interrupted by QUIT */ ! 2191: return(escchr); /* user entered escape character */ ! 2192: else /* couldnt be ^c, sigint never returns */ ! 2193: #endif ! 2194: #endif ! 2195: return(-1); /* Return the char, or -1. */ ! 2196: } ! 2197: signal(SIGALRM,timerh); /* Timed read, so set up timer */ ! 2198: alarm(timo); ! 2199: if (setjmp(sjbuf)) n = -2; ! 2200: else { ! 2201: n = read(0, &ch, 1); ! 2202: ch &= 0377; ! 2203: } ! 2204: alarm(0); /* Stop timing, we got our character */ ! 2205: signal(SIGALRM,SIG_DFL); ! 2206: if (n > 0) return(ch); ! 2207: else ! 2208: #ifdef UXIII ! 2209: #ifndef CIE /* CIE Regulus has no such symbol */ ! 2210: if (n == -1 && errno == EINTR) /* If read interrupted by QUIT, */ ! 2211: return(escchr); /* user entered escape character, */ ! 2212: else /* can't be ^c, sigint never returns */ ! 2213: #endif ! 2214: #endif ! 2215: return(-1); ! 2216: } ! 2217: ! 2218: #ifdef ATT7300 ! 2219: #include <sys/phone.h> ! 2220: #include <dial.h> ! 2221: #define ATT7300 4 /* REH */ ! 2222: CALL tcfig; ! 2223: struct termio ctermio = {0}; ! 2224: struct updata ph; ! 2225: static int att7300 = 0; /* REH */ ! 2226: ! 2227: /* A T T D I A L -- Dial up the remote system */ ! 2228: ! 2229: /* Purpose: to open and dial a number on the internal modem available on the ! 2230: * ATT7300 UNIX PC. Richard E. Hill, Dickinson, TX. ! 2231: */ ! 2232: ! 2233: attdial(ttname,speed,telnbr) char *ttname,*telnbr; int speed; { ! 2234: int err; ! 2235: ! 2236: if (ttyfd > 0) { ! 2237: ioctl(ttyfd,TCGETA,&ctermio); /* save current settings */ ! 2238: err=ttclos(); /* close port */ ! 2239: } else ioctl(0,TCGETA,&ctermio); /* get standard settings */ ! 2240: ! 2241: /* Open line, check availability & data mode, turn on speaker, close port. */ ! 2242: ! 2243: ttyfd = open (ttname,O_RDWR | O_NDELAY); ! 2244: if (err=ioctl(ttyfd,PIOCOFFHOOK,&ph)) { ! 2245: printf("Phone line for %s not available:%d %d %d\n", ! 2246: ttname,ttyfd,err,errno); ! 2247: close(ttyfd); ! 2248: ttyfd = -1; ! 2249: return(-1); ! 2250: } ! 2251: ioctl(ttyfd,PIOCGETP,&ph); /* set phone parameters */ ! 2252: if (ph.c_lineparam & VOICE) { ! 2253: printf("Phone line %s not in data mode. Switch to data & redial\n", ! 2254: ttname); ! 2255: ioctl(ttyfd,PIOCDISC,&ph); ! 2256: close(ttyfd); ! 2257: ttyfd = -1; ! 2258: return(-1); ! 2259: } ! 2260: ph.c_feedback |= (SPEAKERON | RINGON | NORMSPK); ! 2261: ioctl(ttyfd,PIOCSETP,&ph); /* set phone parameters */ ! 2262: ioctl(ttyfd,PIOCDISC,&ph); /* release phone resources for dial */ ! 2263: close(ttyfd); ! 2264: /* ! 2265: fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \ ! 2266: line_status:%o feedback:%o\n", ! 2267: ph.c_lineparam, ph.c_waitdialtone, ph.c_linestatus,ph.c_feedback); ! 2268: */ ! 2269: ! 2270: /* Close line so that it can be reopened using system routine "dial". */ ! 2271: /* Set terminal configuration parameters. */ ! 2272: ! 2273: ctermio.c_iflag |= (BRKINT|IGNPAR|IXON|IXOFF); ! 2274: ctermio.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP| IXANY); ! 2275: ctermio.c_oflag &= ~OPOST; ! 2276: ctermio.c_cflag = (B1200 | CS8 | CREAD | CLOCAL | HUPCL); ! 2277: ctermio.c_lflag &= ~(ICANON|ECHO); ! 2278: ctermio.c_cc[4] = 1; ! 2279: ctermio.c_cc[5] = 0; ! 2280: tcfig.attr = &ctermio; ! 2281: tcfig.baud = speed <= 1200 ? speed : 1200; ! 2282: tcfig.speed = speed <= 300 ? 300 : 1200; ! 2283: tcfig.line = ttname; ! 2284: tcfig.telno = telnbr; ! 2285: tcfig.modem = 0; ! 2286: fprintf (stderr,"dialing:%s on line:%s at %d baud, speed:%d\n", ! 2287: tcfig.telno,tcfig.line,tcfig.baud,tcfig.speed); ! 2288: if ((ttyfd = dial(tcfig)) > 0) { ! 2289: att7300 = 1; ! 2290: /* ! 2291: ioctl(ttyfd,TCGETA,&ctermio); ! 2292: fprintf(stderr,"after dial:iflag:%o, oflag:%o, cflag:%o, lflag:%o,\ ! 2293: line:%o\n", ctermio.c_iflag,ctermio.c_oflag,ctermio.c_cflag, ! 2294: ctermio.c_lflag, ctermio.c_line); ! 2295: */ ! 2296: return(0); ! 2297: } ! 2298: printf("Sorry, connection not made. Error status: %d\n",ttyfd); ! 2299: return(-2); ! 2300: } ! 2301: #endif /* ATT7300 */ ! 2302:
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.