|
|
1.1 ! root 1: char *ckxv = "UNIX Communications support, 5A(0102), 23 Nov 92"; ! 2: ! 3: /* C K U T I O */ ! 4: ! 5: /* C-Kermit interrupt, terminal control & i/o functions for UNIX */ ! 6: ! 7: /* ! 8: Author: Frank da Cruz ([email protected], [email protected]), ! 9: Columbia University Center for Computing Activities. ! 10: First released January 1985. ! 11: Copyright (C) 1985, 1992, Trustees of Columbia University in the City of New ! 12: York. Permission is granted to any individual or institution to use this ! 13: software as long as it is not sold for profit. This copyright notice must be ! 14: retained. This software may not be included in commercial products without ! 15: written permission of Columbia University. ! 16: */ ! 17: ! 18: /* Includes */ ! 19: ! 20: #include "ckcdeb.h" /* This moved to here. */ ! 21: #include <errno.h> /* System error numbers */ ! 22: #ifdef __386BSD__ ! 23: #define ENOTCONN 57 ! 24: #endif /* __386BSD__ */ ! 25: ! 26: #include "ckcnet.h" /* Symbols for network types. */ ! 27: ! 28: /* ! 29: The directory-related includes are here because we need to test some ! 30: file-system-related symbols to find out which system we're being compiled ! 31: under. For example, MAXNAMLEN is defined in BSD4.2 but not 4.1. ! 32: */ ! 33: #ifdef SDIRENT /* Directory bits... */ ! 34: #define DIRENT ! 35: #endif /* SDIRENT */ ! 36: ! 37: #ifdef XNDIR ! 38: #include <sys/ndir.h> ! 39: #else /* !XNDIR */ ! 40: #ifdef NDIR ! 41: #include <ndir.h> ! 42: #else /* !NDIR, !XNDIR */ ! 43: #ifdef RTU ! 44: #include "/usr/lib/ndir.h" ! 45: #else /* !RTU, !NDIR, !XNDIR */ ! 46: #ifdef DIRENT ! 47: #ifdef SDIRENT ! 48: #include <sys/dirent.h> ! 49: #else ! 50: #include <dirent.h> ! 51: #endif /* SDIRENT */ ! 52: #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */ ! 53: #include <sys/dir.h> ! 54: #endif /* DIRENT */ ! 55: #endif /* RTU */ ! 56: #endif /* NDIR */ ! 57: #endif /* XNDIR */ ! 58: ! 59: /* Definition of HZ, used in msleep() */ ! 60: ! 61: #ifdef MIPS ! 62: #define HZ ( 1000 / CLOCK_TICK ) ! 63: #else ! 64: #ifdef ATTSV ! 65: #ifndef NAP ! 66: #ifndef TRS16 ! 67: #include <sys/param.h> ! 68: #else ! 69: #define HZ ( 1000 / CLOCK_TICK ) ! 70: #endif /* TRS16 */ ! 71: #ifdef NAPHACK ! 72: #define nap(x) (void)syscall(3112, (x)) ! 73: #define NAP ! 74: #endif /* NAPHACK */ ! 75: #endif /* NAP */ ! 76: #endif /* ATTSV */ ! 77: #endif /* MIPS */ ! 78: ! 79: #ifdef M_UNIX ! 80: #undef NGROUPS_MAX /* Prevent multiple definition warnings */ ! 81: #endif /* M_UNIX */ ! 82: ! 83: #include <signal.h> /* Signals */ ! 84: ! 85: /* For setjmp and longjmp */ ! 86: ! 87: #ifndef ZILOG ! 88: #include <setjmp.h> ! 89: #else ! 90: #include <setret.h> ! 91: #endif /* ZILOG */ ! 92: ! 93: /* Maximum length for the name of a tty device */ ! 94: ! 95: #ifndef DEVNAMLEN ! 96: #define DEVNAMLEN 25 ! 97: #endif ! 98: ! 99: #ifdef NETCONN ! 100: #undef DEVNAMLEN ! 101: #define DEVNAMLEN 50 /* longer field for host:service */ ! 102: #endif /* NETCONN */ ! 103: ! 104: /* ! 105: The following test differentiates between 4.1 BSD and 4.2 & later. ! 106: If you have a 4.1BSD system with the DIRENT library, this test could ! 107: mistakenly diagnose 4.2BSD and then later enable the use of system calls ! 108: that aren't defined. If indeed there are such systems, we can use some ! 109: other way of testing for 4.1BSD, or add yet another compile-time switch. ! 110: */ ! 111: #ifdef BSD4 ! 112: #ifdef MAXNAMLEN ! 113: #ifndef FT21 ! 114: #ifndef FT18 /* Except for Fortune. */ ! 115: #define BSD42 ! 116: #endif /* FT18 */ ! 117: #endif /* FT21 */ ! 118: #endif /* MAXNAMLEN */ ! 119: #endif /* BSD4 */ ! 120: /* ! 121: Minix support added by Charles Hedrick, ! 122: Rutgers University: [email protected] ! 123: Minix also has V7 enabled. ! 124: */ ! 125: #ifdef MINIX ! 126: #define TANDEM 0 ! 127: #define MYREAD ! 128: #include <limits.h> ! 129: #endif /* MINIX */ ! 130: ! 131: #include "ckuver.h" /* Version herald */ ! 132: char *ckxsys = HERALD; ! 133: ! 134: /* UUCP lock file name definition */ ! 135: ! 136: #ifndef NOUUCP ! 137: ! 138: /* Name of UUCP tty device lock file */ ! 139: ! 140: #ifdef ACUCNTRL ! 141: #define LCKDIR ! 142: #endif /* ACUCNTRL */ ! 143: /* ! 144: LOCK_DIR is the name of the lockfile directory. ! 145: If LOCK_DIR is already defined (e.g. on command line), we don't change it. ! 146: PIDSTRING means use ASCII string to represent pid in lockfile. ! 147: */ ! 148: #ifndef LOCK_DIR ! 149: #ifdef BSD44 ! 150: #define LOCK_DIR "/var/spool/uucp"; ! 151: #else ! 152: #ifdef DGUX430 ! 153: #define LOCK_DIR "/var/spool/locks"; ! 154: #else ! 155: #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */ ! 156: #define PIDSTRING ! 157: #define LOCK_DIR "/etc/locks"; ! 158: #else ! 159: #ifdef AIXRS ! 160: #define PIDSTRING ! 161: #define LOCK_DIR "/etc/locks"; ! 162: #else ! 163: #ifdef ISIII ! 164: #define LOCK_DIR "/etc/locks"; ! 165: #else ! 166: #ifdef HDBUUCP ! 167: #define PIDSTRING ! 168: #ifdef M_SYS5 /* wht@n4hgf - SCO */ ! 169: #define LOCK_DIR "/usr/spool/uucp"; ! 170: #else ! 171: #ifdef M_UNIX ! 172: #define LOCK_DIR "/usr/spool/uucp"; ! 173: #else ! 174: #ifdef SVR4 ! 175: #define LOCK_DIR "/var/spool/locks"; ! 176: #ifndef LOCKF ! 177: #define LOCKF /* Use lockf() too in SVR4 */ ! 178: #endif /* LOCKF */ ! 179: #else ! 180: #ifdef SUNOS4 ! 181: #define LOCK_DIR "/var/spool/locks"; ! 182: #else ! 183: #define LOCK_DIR "/usr/spool/locks"; ! 184: #endif /* SUNOS4 */ ! 185: #endif /* SVR4 */ ! 186: #endif /* M_UNIX */ ! 187: #endif /* M_SYS5 */ ! 188: #else ! 189: #ifdef LCKDIR ! 190: #define LOCK_DIR "/usr/spool/uucp/LCK"; ! 191: #else ! 192: #define LOCK_DIR "/usr/spool/uucp"; ! 193: #endif /* LCKDIR */ ! 194: #endif /* HDBUUCP */ ! 195: #endif /* ISIII */ ! 196: #endif /* AIXRS */ ! 197: #endif /* RTAIX */ ! 198: #endif /* DGUX430 */ ! 199: #endif /* BSD44 */ ! 200: #endif /* !LOCK_DIR (outside ifndef) */ ! 201: ! 202: #endif /* !NOUUCP */ ! 203: ! 204: #ifdef ATTSV ! 205: #define MYREAD ! 206: #endif /* ATTSV */ ! 207: ! 208: #ifdef ATT7300 ! 209: #ifndef MYREAD ! 210: #define MYREAD ! 211: #endif /* MYREAD */ ! 212: /* bits for attmodem: internal modem in use, restart getty */ ! 213: #define ISMODEM 1 ! 214: #define DOGETY 512 ! 215: #endif /* ATT7300 */ ! 216: ! 217: #ifdef BSD42 ! 218: #define MYREAD ! 219: #endif /* BSD42 */ ! 220: ! 221: #ifdef POSIX ! 222: #define MYREAD ! 223: #endif /* POSIX */ ! 224: ! 225: /* ! 226: Variables available to outside world: ! 227: ! 228: dftty -- Pointer to default tty name string, like "/dev/tty". ! 229: dfloc -- 0 if dftty is console, 1 if external line. ! 230: dfprty -- Default parity ! 231: dfflow -- Default flow control ! 232: ckxech -- Flag for who echoes console typein: ! 233: 1 - The program (system echo is turned off) ! 234: 0 - The system (or front end, or terminal). ! 235: functions that want to do their own echoing should check this flag ! 236: before doing so. ! 237: ! 238: flfnam -- Name of lock file, including its path, e.g., ! 239: "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77" ! 240: lkflfn -- Name of link to lock file, including its paths ! 241: haslock -- Flag set if this kermit established a uucp lock. ! 242: backgrd -- Flag indicating program executing in background ( & on ! 243: end of shell command). Used to ignore INT and QUIT signals. ! 244: rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle ! 245: SIGTSTP) ! 246: ! 247: Functions for assigned communication line (either external or console tty): ! 248: ! 249: sysinit() -- System dependent program initialization ! 250: syscleanup() -- System dependent program shutdown ! 251: ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access. ! 252: ttclos() -- Close & reset the tty, releasing any access lock. ! 253: ttsspd(cps) -- Set the transmission speed of the tty. ! 254: ttgspd() -- Get (read) the the transmission speed of the tty. ! 255: ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed. ! 256: ttvt(speed,flow) -- Put the tty in virtual terminal mode. ! 257: or in DIALING or CONNECTED modem control state. ! 258: ttres() -- Restore original tty modes. ! 259: ttscarr(carrier) -- Set carrier control mode, on/off/auto. ! 260: ttinl(dest,max,timo) -- Timed read line from the tty. ! 261: ttinc(timo) -- Timed read character from tty. ! 262: myread() -- Raw mode bulk buffer read, gives subsequent ! 263: chars one at a time and simulates FIONREAD. ! 264: myunrd(c) -- Places c back in buffer to be read (one only) ! 265: ttchk() -- See how many characters in tty input buffer. ! 266: ttxin(n,buf) -- Read n characters from tty (untimed). ! 267: ttol(string,length) -- Write a string to the tty. ! 268: ttoc(c) -- Write a character to the tty. ! 269: ttflui() -- Flush tty input buffer. ! 270: ttsndb() -- Send BREAK signal. ! 271: ttsndlb() -- Send Long BREAK signal. ! 272: ! 273: ttlock(ttname) -- "Lock" tty device against uucp collisions. ! 274: ttunlck() -- Unlock tty device. ! 275: ! 276: For ATT7300/Unix PC, System V: ! 277: attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem ! 278: offgetty(ttname) -- Turns off getty(1m) for comms line ! 279: ongetty(ttname) -- Restores getty() to comms line ! 280: */ ! 281: ! 282: /* ! 283: Functions for console terminal: ! 284: ! 285: congm() -- Get console terminal modes. ! 286: concb(esc) -- Put the console in single-character wakeup mode with no echo. ! 287: conbin(esc) -- Put the console in binary (raw) mode. ! 288: conres() -- Restore the console to mode obtained by congm(). ! 289: conoc(c) -- Unbuffered output, one character to console. ! 290: conol(s) -- Unbuffered output, null-terminated string to the console. ! 291: conola(s) -- Unbuffered output, array of strings to the console. ! 292: conxo(n,s) -- Unbuffered output, n characters to the console. ! 293: conchk() -- Check if characters available at console (bsd 4.2). ! 294: Check if escape char (^\) typed at console (System III/V). ! 295: coninc(timo) -- Timed get a character from the console. ! 296: congks(timo) -- Timed get keyboard scan code. ! 297: conint() -- Enable terminal interrupts on the console if not background. ! 298: connoi() -- Disable terminal interrupts on the console if not background. ! 299: ! 300: Time functions ! 301: ! 302: msleep(m) -- Millisecond sleep ! 303: ztime(&s) -- Return pointer to date/time string ! 304: rtimer() -- Reset timer ! 305: gtimer() -- Get elapsed time since last call to rtimer() ! 306: */ ! 307: ! 308: /* Conditional Includes */ ! 309: ! 310: /* Whether to include <sys/file.h> */ ! 311: ! 312: #ifdef RTU /* RTU doesn't */ ! 313: #define NOFILEH ! 314: #endif /* RTU */ ! 315: ! 316: #ifdef CIE /* CIE does. */ ! 317: #undef NOFILEH ! 318: #endif /* CIE */ ! 319: ! 320: #ifdef BSD41 /* 4.1 BSD doesn't */ ! 321: #define NOFILEH ! 322: #endif /* BSD41 */ ! 323: ! 324: #ifdef is68k /* is68k (whatever that is) */ ! 325: #define NOFILEH ! 326: #endif /* is68k */ ! 327: ! 328: #ifdef MINIX /* MINIX */ ! 329: #define NOFILEH ! 330: #endif /* MINIX */ ! 331: ! 332: #ifdef COHERENT /* Coherent */ ! 333: #define NOFILEH ! 334: #endif /* COHERENT */ ! 335: ! 336: #ifndef NOFILEH /* Now include if selected. */ ! 337: #include <sys/file.h> ! 338: #endif /* NOFILEH */ ! 339: ! 340: /* POSIX */ ! 341: ! 342: #ifdef BSD44ORPOSIX /* POSIX uses termios.h */ ! 343: #define TERMIOS ! 344: #ifdef bsdi ! 345: #ifndef NCCS ! 346: #define NCCS 20 ! 347: #endif /* NCCS */ ! 348: #endif /* bsdi */ ! 349: #include <termios.h> ! 350: #ifndef BSD44 /* Really POSIX */ ! 351: #define NOSYSIOCTLH /* No ioctl's allowed. */ ! 352: #undef ultrix /* Turn off any ultrix features. */ ! 353: #endif /* BSD44 */ ! 354: #endif /* POSIX */ ! 355: ! 356: /* System III, System V */ ! 357: ! 358: #ifdef ATTSV ! 359: #ifndef BSD44 ! 360: #include <termio.h> ! 361: #endif /* BSD44 */ ! 362: #ifdef SVR4 /* Sys V R4 and later */ ! 363: #ifdef TERMIOX ! 364: /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */ ! 365: #include <termiox.h> ! 366: struct termiox rctsx; ! 367: #else ! 368: #ifdef STERMIOX ! 369: #include <sys/termiox.h> ! 370: struct termiox rctsx; ! 371: #endif /* STERMIOX */ ! 372: #endif /* TERMIOX */ ! 373: #endif /* SVR4 */ ! 374: #endif /* ATTSV */ ! 375: ! 376: #ifdef MINIX /* MINIX uses ioctl's */ ! 377: #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */ ! 378: #endif /* MINIX */ ! 379: ! 380: /* Others */ ! 381: ! 382: #ifndef NOSYSIOCTLH /* Others use ioctl() */ ! 383: #ifdef SUN4S5 ! 384: /* ! 385: This is to get rid of cpp warning messages that occur because all of ! 386: these symbols are defined by both termios.h and ioctl.h on the SUN. ! 387: */ ! 388: #undef ECHO ! 389: #undef NL0 ! 390: #undef NL1 ! 391: #undef TAB0 ! 392: #undef TAB1 ! 393: #undef TAB2 ! 394: #undef XTABS ! 395: #undef CR0 ! 396: #undef CR1 ! 397: #undef CR2 ! 398: #undef CR3 ! 399: #undef FF0 ! 400: #undef FF1 ! 401: #undef BS0 ! 402: #undef BS1 ! 403: #undef TOSTOP ! 404: #undef FLUSHO ! 405: #undef PENDIN ! 406: #undef NOFLSH ! 407: #endif /* SUN4S5 */ ! 408: #include <sys/ioctl.h> ! 409: #endif /* NOSYSIOCTLH */ ! 410: ! 411: /* Whether to include <fcntl.h> */ ! 412: ! 413: #ifndef is68k /* Only a few don't have this one. */ ! 414: #ifndef BSD41 ! 415: #ifndef FT21 ! 416: #ifndef FT18 ! 417: #include <fcntl.h> ! 418: #endif /* FT18 */ ! 419: #endif /* FT21 */ ! 420: #endif /* BSD41 */ ! 421: #endif /* not is68k */ ! 422: ! 423: #ifdef ATT7300 /* Unix PC, internal modem dialer */ ! 424: #include <sys/phone.h> ! 425: #endif /* ATT7300 */ ! 426: ! 427: #ifdef HPUX /* HP-UX variations. */ ! 428: #define HPUXJOBCTL ! 429: #include <sys/modem.h> /* HP-UX modem signals */ ! 430: #ifdef hp9000s500 /* Model 500 */ ! 431: #undef HPUXJOBCTL ! 432: #endif /* hp9000s500 */ ! 433: #ifdef HPUXPRE65 ! 434: #undef HPUXJOBCTL ! 435: typedef int mflag; ! 436: #endif /* HPUXPRE65 */ ! 437: #ifdef HPUXJOBCTL ! 438: #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */ ! 439: #endif /* HPUXJOBCTL */ ! 440: #endif /* HPUX */ ! 441: ! 442: /* BSD, V7, Coherent, Minix, et al. */ ! 443: ! 444: #ifdef SVORPOSIX /* Sys V or POSIX */ ! 445: #ifdef BSD44 ! 446: #include <sys/time.h> ! 447: #endif /* BSD44 */ ! 448: #ifdef AIXRS ! 449: #include <sys/time.h> ! 450: #endif /* AIXRS */ ! 451: #ifdef NOIEXTEN /* This is broken on some systems */ ! 452: #undef IEXTEN /* like Convex/OS 9.1 */ ! 453: #endif /* NOIEXTEN */ ! 454: #ifndef IEXTEN /* Turn off ^O/^V processing. */ ! 455: #define IEXTEN 0 /* Needed, at least, on BSDI. */ ! 456: #endif /* IEXTEN */ ! 457: #else /* Not AT&T Sys V or POSIX */ ! 458: #include <sgtty.h> /* So we use <sgtty.h> */ ! 459: #ifndef PROVX1 /* Now <sys/time.h> ... */ ! 460: #ifndef V7 ! 461: #ifndef BSD41 ! 462: #ifndef COHERENT ! 463: #include <sys/time.h> /* Clock info (for break generation) */ ! 464: #endif /* COHERENT */ ! 465: #endif /* BSD41 */ ! 466: #endif /* V7 */ ! 467: #endif /* PROVX1 */ ! 468: #endif /* SVORPOSIX */ ! 469: ! 470: #ifdef OSF /* DEC OSF/1 1.0 */ ! 471: #include <sys/timeb.h> ! 472: #endif /* OSF */ ! 473: ! 474: #ifdef BSD41 /* BSD 4.1 */ ! 475: #include <sys/timeb.h> ! 476: #endif /* BSD41 */ ! 477: ! 478: #ifdef FT21 /* For:Pro 2.1 */ ! 479: #include <sys/timeb.h> ! 480: #endif /* FT21 */ ! 481: ! 482: #ifdef BSD29 /* BSD 2.9 */ ! 483: #include <sys/timeb.h> ! 484: #endif /* BSD29 */ ! 485: ! 486: #ifdef TOWER1 ! 487: #include <sys/timeb.h> /* Clock info for NCR Tower */ ! 488: #endif /* TOWER1 */ ! 489: ! 490: #ifdef COHERENT ! 491: #include <sys/timeb.h> /* Clock info for NCR Tower */ ! 492: #endif /* COHERENT */ ! 493: ! 494: #ifdef aegis ! 495: #include "/sys/ins/base.ins.c" ! 496: #include "/sys/ins/error.ins.c" ! 497: #include "/sys/ins/ios.ins.c" ! 498: #include "/sys/ins/sio.ins.c" ! 499: #include "/sys/ins/pad.ins.c" ! 500: #include "/sys/ins/time.ins.c" ! 501: #include "/sys/ins/pfm.ins.c" ! 502: #include "/sys/ins/pgm.ins.c" ! 503: #include "/sys/ins/ec2.ins.c" ! 504: #include "/sys/ins/type_uids.ins.c" ! 505: #include <default_acl.h> ! 506: #undef TIOCEXCL ! 507: #undef FIONREAD ! 508: #endif /* aegis */ ! 509: ! 510: #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */ ! 511: #undef FIONREAD ! 512: #endif /* sxaE50 */ ! 513: ! 514: /* The following #defines are catch-alls for those systems */ ! 515: /* that didn't have or couldn't find <file.h>... */ ! 516: ! 517: #ifndef FREAD ! 518: #define FREAD 0x01 ! 519: #endif /* FREAD */ ! 520: ! 521: #ifndef FWRITE ! 522: #define FWRITE 0x10 ! 523: #endif /* FWRITE */ ! 524: ! 525: #ifndef O_RDONLY ! 526: #define O_RDONLY 000 ! 527: #endif /* O_RDONLY */ ! 528: ! 529: /* Declarations */ ! 530: ! 531: #ifdef _POSIX_SOURCE /* This includes MINIX */ ! 532: #ifndef AIXRS ! 533: #include <time.h> ! 534: #endif /* AIXRS */ ! 535: #ifdef __GNUC__ ! 536: #ifdef XENIX ! 537: /* ! 538: Because Xenix <time.h> doesn't declare time() if we're using gcc. ! 539: */ ! 540: time_t time(); ! 541: #endif /* XENIX */ ! 542: #endif /* __GNUC__ */ ! 543: #else ! 544: time_t time(); /* All Unixes should have this... */ ! 545: #endif /* _POSIX_SOURCE */ ! 546: ! 547: /* Special stuff for V7 input buffer peeking */ ! 548: ! 549: #ifdef V7 ! 550: int kmem[2] = { -1, -1}; ! 551: char *initrawq(), *qaddr[2]={0,0}; ! 552: #define CON 0 ! 553: #define TTY 1 ! 554: #endif /* V7 */ ! 555: ! 556: /* dftty is the device name of the default device for file transfer */ ! 557: /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ ! 558: ! 559: #ifndef DFTTY ! 560: #ifdef PROVX1 ! 561: char *dftty = "/dev/com1.dout"; /* Only example so far of a system */ ! 562: char *dfmdm = "none"; ! 563: int dfloc = 1; /* that goes in local mode by default */ ! 564: #else ! 565: char *dftty = CTTNAM; /* Remote by default, use normal */ ! 566: char *dfmdm = "none"; ! 567: int dfloc = 0; /* controlling terminal name. */ ! 568: #endif /* PROVX1 */ ! 569: #else ! 570: char *dftty = DFTTY; /* Default location specified on */ ! 571: char *dfmdm = "none"; /* command line. */ ! 572: int dfloc = 1; /* controlling terminal name. */ ! 573: #endif /* DFTTY */ ! 574: ! 575: #ifdef RTU ! 576: int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */ ! 577: #endif /* RTU */ ! 578: ! 579: int dfprty = 0; /* Default parity (0 = none) */ ! 580: int ttprty = 0; /* The parity that is in use. */ ! 581: int ttpflg = 0; /* Parity not sensed yet. */ ! 582: static int ttpmsk = 0377; /* Parity stripping mask. */ ! 583: int ttmdm = 0; /* Modem in use. */ ! 584: int ttcarr = CAR_AUT; /* Carrier handling mode. */ ! 585: int dfflow = FLO_XONX; /* Default is Xon/Xoff */ ! 586: int backgrd = 0; /* Assume in foreground (no '&' ) */ ! 587: #ifdef ultrix ! 588: int iniflags = 0; /* fcntl flags for ttyfd */ ! 589: #endif /* ultrix */ ! 590: int fdflag = 0; /* Flag for redirected stdio */ ! 591: int ttfdflg = 0; /* Open File descriptor was given */ ! 592: int tvtflg = 0; /* Flag that ttvt has been called */ ! 593: long ttspeed = -1; /* For saving speed */ ! 594: int ttflow = -9; /* For saving flow */ ! 595: int ttld = -1; /* Line discipline */ ! 596: ! 597: #ifdef sony_news ! 598: static int km_con = -1; /* Kanji mode for console tty */ ! 599: static int km_ext = -1; /* Kanji mode for external device */ ! 600: #endif /* sony_news */ ! 601: ! 602: extern int ttnproto; /* Defined in ckcnet.c */ ! 603: extern int ttnet; /* Defined in ckcnet.c */ ! 604: ! 605: int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ ! 606: ! 607: /* Declarations of variables global within this module */ ! 608: ! 609: static time_t tcount; /* Elapsed time counter */ ! 610: static SIGTYP (*saval)() = NULL; /* For saving alarm() handler */ ! 611: ! 612: /* ! 613: BREAKNULS is defined for systems that simulate sending a BREAK signal ! 614: by sending a bunch of NUL characters at low speed. ! 615: */ ! 616: #ifdef PROVX1 ! 617: #ifndef BREAKNULS ! 618: #define BREAKNULS ! 619: #endif /* BREAKNULS */ ! 620: #endif /* PROVX1 */ ! 621: ! 622: #ifdef V7 ! 623: #ifndef BREAKNULS ! 624: #define BREAKNULS ! 625: #endif /* BREAKNULS */ ! 626: #endif /* V7 */ ! 627: ! 628: #ifdef BREAKNULS ! 629: static char /* A string of nulls */ ! 630: *brnuls = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; ! 631: #endif /* BREAKNULS */ ! 632: ! 633: static jmp_buf sjbuf; /* Longjump buffers */ ! 634: #ifdef V7 ! 635: static jmp_buf jjbuf; ! 636: #endif /* V7 */ ! 637: ! 638: /* static */ /* (Not static any more) */ ! 639: int ttyfd = -1; /* TTY file descriptor */ ! 640: ! 641: int telnetfd = 0; /* File descriptor is for telnet */ ! 642: int x25fd = 0; /* File descriptor is for X.25 */ ! 643: ! 644: static int lkf = 0, /* Line lock flag */ ! 645: cgmf = 0, /* Flag that console modes saved */ ! 646: xlocal = 0, /* Flag for tty local or remote */ ! 647: curcarr = 0; /* Carrier mode: require/ignore. */ ! 648: ! 649: static int netconn = 0; /* 1 if network connection active */ ! 650: ! 651: static char escchr; /* Escape or attn character */ ! 652: ! 653: #ifdef AIXRS ! 654: static struct timeval tv; /* For getting time, from sys/time.h */ ! 655: static struct timezone tz; ! 656: #else ! 657: #ifdef BSD44 ! 658: static struct timeval tv; /* For getting time, from sys/time.h */ ! 659: static struct timezone tz; ! 660: #else ! 661: #ifdef BSD42 ! 662: static struct timeval tv; /* For getting time, from sys/time.h */ ! 663: static struct timezone tz; ! 664: #ifdef OSF ! 665: static struct timeb ftp; /* And from sys/timeb.h */ ! 666: #endif /* OSF */ ! 667: #endif /* BSD42 */ ! 668: #endif /* BSD44 */ ! 669: #endif /* AIXRS */ ! 670: ! 671: #ifdef BSD29 ! 672: static long xclock; /* For getting time from sys/time.h */ ! 673: static struct timeb ftp; /* And from sys/timeb.h */ ! 674: #endif /* BSD29 */ ! 675: ! 676: #ifdef BSD41 ! 677: static long xclock; /* For getting time from sys/time.h */ ! 678: static struct timeb ftp; /* And from sys/timeb.h */ ! 679: #endif /* BSD41 */ ! 680: ! 681: #ifdef FT21 ! 682: static long xclock; /* For getting time from sys/time.h */ ! 683: static struct timeb ftp; /* And from sys/timeb.h */ ! 684: #endif /* FT21 */ ! 685: ! 686: #ifdef TOWER1 ! 687: static long xclock; /* For getting time from sys/time.h */ ! 688: static struct timeb ftp; /* And from sys/timeb.h */ ! 689: #endif /* TOWER1 */ ! 690: ! 691: #ifdef COHERENT ! 692: static long xclock; /* For getting time from sys/time.h */ ! 693: static struct timeb ftp; /* And from sys/timeb.h */ ! 694: #endif /* COHERENT */ ! 695: ! 696: #ifdef V7 ! 697: static long xclock; ! 698: #endif /* V7 */ ! 699: ! 700: /* sgtty/termio information... */ ! 701: ! 702: #ifdef BSD44ORPOSIX /* POSIX or BSD44 */ ! 703: static struct termios ! 704: ttold, ttraw, tttvt, ttcur, ! 705: ccold, ccraw, cccbrk; ! 706: #else /* BSD, V7, etc */ ! 707: #ifdef ATTSV ! 708: static struct termio ttold = {0}; /* Init'd for word alignment, */ ! 709: static struct termio ttraw = {0}; /* which is important for some */ ! 710: static struct termio tttvt = {0}; /* systems, like Zilog... */ ! 711: static struct termio ttcur = {0}; ! 712: static struct termio ccold = {0}; ! 713: static struct termio ccraw = {0}; ! 714: static struct termio cccbrk = {0}; ! 715: #else ! 716: static struct sgttyb /* sgtty info... */ ! 717: ttold, ttraw, tttvt, ttcur, /* for communication line */ ! 718: ccold, ccraw, cccbrk; /* and for console */ ! 719: #ifdef TIOCGETC ! 720: #ifdef MINIX ! 721: static struct sgttyb tchold, tchnoi; /* Special chars */ ! 722: #else ! 723: static struct tchars tchold, tchnoi; ! 724: #endif /* MINIX */ ! 725: static int tcharf; ! 726: #endif /* TIOCGETC */ ! 727: #ifdef TIOCGLTC ! 728: #ifdef MINIX ! 729: static struct sgttyb ltchold, ltchnoi; ! 730: #else ! 731: static struct ltchars ltchold, ltchnoi; ! 732: #endif /* MINIX */ ! 733: static int ltcharf; ! 734: #endif /* TIOCGLTC */ ! 735: int lmodef = 0; /* Local modes */ ! 736: int lmode = 0; ! 737: #endif /* ATTSV */ ! 738: #endif /* BSD44ORPOSIX */ ! 739: ! 740: #ifdef PROVX1 ! 741: static struct sgttyb ttbuf; ! 742: #endif /* PROVX1 */ ! 743: ! 744: #ifdef ultrix ! 745: /* do we really need this? */ ! 746: static struct sgttyb vanilla; ! 747: #endif /* ultrix */ ! 748: ! 749: #ifdef ATT7300 ! 750: static int attmodem = 0; /* ATT7300 internal-modem status */ ! 751: struct updata dialer = {0}; /* Condition dialer for data call */ ! 752: #endif /* ATT7300 */ ! 753: ! 754: char flfnam[80]; /* uucp lock file path name */ ! 755: #ifdef RTAIX ! 756: char lkflfn[80]; /* and possible link to it */ ! 757: #endif /* RTAIX */ ! 758: int haslock = 0; /* =1 if this kermit locked uucp */ ! 759: ! 760: #ifdef SVORPOSIX ! 761: static int conesc = 0; /* set to 1 if esc char (^\) typed */ ! 762: #else ! 763: #ifdef V7 ! 764: static int conesc = 0; ! 765: #else ! 766: #ifdef C70 ! 767: static int conesc = 0; ! 768: #endif /* C70 */ ! 769: #endif /* V7 */ ! 770: #endif /* ATTSV */ ! 771: ! 772: static char ttnmsv[DEVNAMLEN]; /* Copy of open path for tthang */ ! 773: ! 774: #ifdef aegis ! 775: static status_$t st; /* error status return value */ ! 776: static short concrp = 0; /* true if console is CRP pad */ ! 777: #define CONBUFSIZ 10 ! 778: static char conbuf[CONBUFSIZ]; /* console readahead buffer */ ! 779: static int conbufn = 0; /* # chars in readahead buffer */ ! 780: static char *conbufp; /* next char in readahead buffer */ ! 781: static uid_$t ttyuid; /* tty type uid */ ! 782: static uid_$t conuid; /* stdout type uid */ ! 783: ! 784: /* APOLLO Aegis main() ! 785: * establish acl usage and cleanup handling ! 786: * this makes sure that CRP pads ! 787: * get restored to a usable mode ! 788: */ ! 789: main(argc,argv) int argc; char **argv; { ! 790: status_$t status; ! 791: pfm_$cleanup_rec dirty; ! 792: ! 793: PID_T pid = getpid(); ! 794: ! 795: /* acl usage according to invoking environment */ ! 796: default_acl(USE_DEFENV); ! 797: ! 798: /* establish a cleanup continuation */ ! 799: status = pfm_$cleanup(dirty); ! 800: if (status.all != pfm_$cleanup_set) { ! 801: /* only handle faults for the original process */ ! 802: if (pid == getpid() && status.all > pgm_$max_severity) { ! 803: /* blew up in main process */ ! 804: status_$t quo; ! 805: pfm_$cleanup_rec clean; ! 806: ! 807: /* restore the console in any case */ ! 808: conres(); ! 809: ! 810: /* attempt a clean exit */ ! 811: debug(F101, "cleanup fault status", "", status.all); ! 812: ! 813: /* doexit(), then send status to continuation */ ! 814: quo = pfm_$cleanup(clean); ! 815: if (quo.all == pfm_$cleanup_set) ! 816: doexit(pgm_$program_faulted,-1); ! 817: else if (quo.all > pgm_$max_severity) ! 818: pfm_$signal(quo); /* blew up in doexit() */ ! 819: } ! 820: /* send to the original continuation */ ! 821: pfm_$signal(status); ! 822: /*NOTREACHED*/ ! 823: } ! 824: return(ckcmai(argc, argv)); ! 825: } ! 826: #endif /* aegis */ ! 827: ! 828: /* ANSI-style prototypes for internal functions. */ ! 829: /* Functions used outside this module are prototyped in ckcker.h. */ ! 830: ! 831: #ifdef apollo ! 832: _PROTOTYP( SIGTYP timerh, () ); ! 833: _PROTOTYP( SIGTYP cctrap, () ); ! 834: _PROTOTYP( SIGTYP esctrp, () ); ! 835: _PROTOTYP( SIGTYP sig_ign, () ); ! 836: #else ! 837: _PROTOTYP( SIGTYP timerh, (int) ); ! 838: _PROTOTYP( SIGTYP cctrap, (int) ); ! 839: _PROTOTYP( SIGTYP esctrp, (int) ); ! 840: #endif /* apollo */ ! 841: _PROTOTYP( int do_open, (char *) ); ! 842: _PROTOTYP( int ttrpid, (char *) ); ! 843: _PROTOTYP( static int ttlock, (char *) ); ! 844: _PROTOTYP( static int ttunlck, (void) ); ! 845: _PROTOTYP( int mygetbuf, (void) ); ! 846: _PROTOTYP( int myfillbuf, (void) ); ! 847: _PROTOTYP( VOID conbgt, (int) ); ! 848: #ifdef ACUCNTRL ! 849: _PROTOTYP( VOID acucntrl, (char *, char *) ); ! 850: #endif /* ACUCNTRL */ ! 851: ! 852: #ifdef BSD44ORPOSIX ! 853: _PROTOTYP( int carrctl, (struct termios *, int) ); ! 854: #else ! 855: #ifdef ATTSV ! 856: _PROTOTYP( int carrctl, (struct termio *, int) ); ! 857: #else ! 858: _PROTOTYP( int carrctl, (struct sgttyb *, int) ); ! 859: #endif /* ATTSV */ ! 860: #endif /* BSD44ORPOSIX */ ! 861: ! 862: #ifdef ATT7300 ! 863: _PROTOTYP( int attdial, (char *, long, char *) ); ! 864: _PROTOTYP( int offgetty, (char *) ); ! 865: _PROTOTYP( int ongetty, (char *) ); ! 866: #endif /* ATT7300 */ ! 867: ! 868: #ifdef CK_ANSIC ! 869: static char * ! 870: xxlast(char *s, char c) ! 871: #else ! 872: static char * ! 873: xxlast(s,c) char *s; char c; ! 874: #endif /* CK_ANSIC */ ! 875: /* xxlast */ { /* Last occurrence of character c in string s. */ ! 876: int i; ! 877: for (i = (int)strlen(s); i > 0; i--) ! 878: if ( s[i-1] == c ) return( s + (i - 1) ); ! 879: return(NULL); ! 880: } ! 881: ! 882: /* Timeout handler for communication line input functions */ ! 883: ! 884: SIGTYP ! 885: timerh(foo) int foo; { ! 886: ttimoff(); ! 887: longjmp(sjbuf,1); ! 888: } ! 889: ! 890: /* Control-C trap for communication line input functions */ ! 891: ! 892: int cc_int; /* Flag */ ! 893: SIGTYP (* occt)(); /* For saving old SIGINT handler */ ! 894: ! 895: SIGTYP ! 896: cctrap(foo) int foo; { /* Needs arg for ANSI C */ ! 897: cc_int = 1; /* signal() prototype. */ ! 898: return; ! 899: } ! 900: ! 901: /* S Y S I N I T -- System-dependent program initialization. */ ! 902: ! 903: int ! 904: sysinit() { ! 905: int x; ! 906: ! 907: conbgt(0); /* See if we're in the background */ ! 908: #ifndef __386BSD__ ! 909: /* ! 910: 386BSD doesn't allow opening /dev/tty if Kermit is running setuid. ! 911: */ ! 912: congm(); /* Get console modes */ ! 913: #endif /* __386BSD__ */ ! 914: signal(SIGALRM,SIG_IGN); /* Ignore alarms */ ! 915: ! 916: #ifdef ultrix ! 917: gtty(0,&vanilla); /* Get sgtty info */ ! 918: iniflags = fcntl(0,F_GETFL,0); /* Get flags */ ! 919: #else ! 920: #ifdef AUX ! 921: set42sig(); /* Don't ask! ([email protected]) */ ! 922: #endif /* AUX */ ! 923: #endif /* ultrix */ ! 924: ! 925: /* Initialize the setuid package. */ ! 926: /* Change to the user's real user and group id. */ ! 927: /* If this can't be done, don't run at all. */ ! 928: ! 929: if (x = priv_ini()) { ! 930: if (x | 1) fprintf(stderr,"Fatal: setuid failure.\n"); ! 931: if (x | 2) fprintf(stderr,"Fatal: setgid failure.\n"); ! 932: if (x | 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n"); ! 933: exit(1); ! 934: } ! 935: #ifdef __386BSD__ ! 936: /* ! 937: 386BSD... OK, now we have changed into ourselves, so can open /dev/tty. ! 938: */ ! 939: congm(); /* Get console modes */ ! 940: #endif /* __386BSD__ */ ! 941: return(0); ! 942: } ! 943: ! 944: /* S Y S C L E A N U P -- System-dependent program cleanup. */ ! 945: ! 946: int ! 947: syscleanup() { ! 948: #ifdef ultrix ! 949: stty(0,&vanilla); /* Get sgtty info */ ! 950: fcntl(0,F_SETFL,iniflags); /* Restore flags */ ! 951: #endif /* ultrix */ ! 952: /* No need to call anything in the suid package here, right? */ ! 953: return(0); ! 954: } ! 955: ! 956: /* T T O P E N -- Open a tty for exclusive access. */ ! 957: ! 958: /* ! 959: Call with: ! 960: ttname: character string - device name or network host name. ! 961: lcl: ! 962: If called with lcl < 0, sets value of lcl as follows: ! 963: 0: the terminal named by ttname is the job's controlling terminal. ! 964: 1: the terminal named by ttname is not the job's controlling terminal. ! 965: But watch out: if a line is already open, or if requested line can't ! 966: be opened, then lcl remains (and is returned as) -1. ! 967: modem: ! 968: Less than zero: ttname is a network host name. ! 969: Zero or greater: ttname is a terminal device name. ! 970: Zero means a local connection (don't use modem signals). ! 971: Positive means use modem signals. ! 972: timo: ! 973: 0 = no timer. ! 974: nonzero = number of seconds to wait for open() to return before timing out. ! 975: ! 976: Returns: ! 977: 0 on success ! 978: -5 if device is in use ! 979: -4 if access to device is denied ! 980: -3 if access to lock directory denied ! 981: -2 upon timeout waiting for device to open ! 982: -1 on other error ! 983: */ ! 984: static int ttotmo = 0; /* Timeout flag */ ! 985: /* Flag kept here to avoid being clobbered by longjmp. */ ! 986: ! 987: int ! 988: ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; { ! 989: ! 990: #ifdef BSD44 ! 991: #define ctermid(x) strcpy(x,"") ! 992: #else ! 993: #ifdef SVORPOSIX ! 994: #ifndef CIE ! 995: extern char *ctermid(); /* Wish they all had this! */ ! 996: #else /* CIE Regulus */ ! 997: #define ctermid(x) strcpy(x,"") ! 998: #endif /* CIE */ ! 999: #endif /* SVORPOSIX */ ! 1000: #endif /* BSD44 */ ! 1001: ! 1002: char *x; /* what's this ? */ ! 1003: ! 1004: #ifndef MINIX ! 1005: extern char* ttyname(); ! 1006: #endif /* MINIX */ ! 1007: char cname[DEVNAMLEN+4]; ! 1008: ! 1009: #ifndef pdp11 ! 1010: #define NAMEFD /* Feature to allow name to be an open file descriptor */ ! 1011: #endif /* pdp11 */ ! 1012: ! 1013: #ifdef NAMEFD ! 1014: char *p; ! 1015: ! 1016: debug(F101,"ttopen telnetfd","",telnetfd); ! 1017: #endif /* NAMEFD */ ! 1018: ! 1019: debug(F111,"ttopen entry modem",ttname,modem); ! 1020: debug(F101," ttyfd","",ttyfd); ! 1021: debug(F101," lcl","",*lcl); ! 1022: ! 1023: #ifdef MAXNAMLEN ! 1024: debug(F100,"ttopen MAXNAMLEN defined","",0); ! 1025: #else ! 1026: debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0); ! 1027: #endif ! 1028: ! 1029: #ifdef BSD4 ! 1030: debug(F100,"ttopen BSD4 defined","",0); ! 1031: #else ! 1032: debug(F100,"ttopen BSD4 *NOT* defined","",0); ! 1033: #endif ! 1034: ! 1035: #ifdef BSD42 ! 1036: debug(F100,"ttopen BSD42 defined","",0); ! 1037: #else ! 1038: debug(F100,"ttopen BSD42 *NOT* defined","",0); ! 1039: #endif /* BSD42 */ ! 1040: ! 1041: #ifdef MYREAD ! 1042: debug(F100,"ttopen MYREAD defined","",0); ! 1043: #else ! 1044: debug(F100,"ttopen MYREAD *NOT* defined","",0); ! 1045: #endif /* MYREAD */ ! 1046: ! 1047: ! 1048: if (ttyfd > -1) { /* if device already opened */ ! 1049: if (strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */ ! 1050: ttclos(ttyfd); /* no, close old ttname, open new */ ! 1051: else /* else same, ignore this call, */ ! 1052: return(0); /* and return. */ ! 1053: } ! 1054: ! 1055: #ifdef NETCONN ! 1056: if (modem < 0) { /* modem < 0 = special code for net */ ! 1057: int x; ! 1058: ttmdm = modem; ! 1059: modem = -modem; /* Positive network type number */ ! 1060: fdflag = 0; /* Stdio not redirected. */ ! 1061: netconn = 1; /* And it's a network connection */ ! 1062: debug(F111,"ttopen net",ttname,modem); ! 1063: #ifdef NAMEFD ! 1064: for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */ ! 1065: if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */ ! 1066: ttyfd = atoi(ttname); /* Is there a way to test it's open? */ ! 1067: ttfdflg = 1; /* We got an open file descriptor */ ! 1068: debug(F111,"ttopen got open network fd",ttname,ttyfd); ! 1069: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */ ! 1070: x = 1; /* Return code is "good". */ ! 1071: if (telnetfd) { ! 1072: ttnet = NET_TCPB; ! 1073: ttnproto = NP_TELNET; ! 1074: #ifdef SUNX25 ! 1075: } else if (x25fd) { ! 1076: ttnet = NET_SX25; ! 1077: ttnproto = NP_NONE; ! 1078: #endif /* SUNX25 */ ! 1079: } ! 1080: } else { /* Host name or address given */ ! 1081: #endif /* NAMEFD */ ! 1082: x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */ ! 1083: if (x > -1) { ! 1084: strncpy(ttnmsv,ttname,DEVNAMLEN); ! 1085: } else netconn = 0; ! 1086: #ifdef NAMEFD ! 1087: } ! 1088: #endif /* NAMEFD */ ! 1089: ! 1090: #ifdef sony_news /* Sony NEWS */ ! 1091: if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */ ! 1092: perror("ttopen error getting Kanji mode (network)"); ! 1093: debug(F111,"ttopen error getting Kanji mode","network",0); ! 1094: km_ext = -1; /* Make sure this stays undefined. */ ! 1095: } ! 1096: #endif /* sony_news */ ! 1097: ! 1098: xlocal = *lcl = 1; /* Network connections are local. */ ! 1099: debug(F101,"ttopen net x","",x); ! 1100: ! 1101: if (x > -1 && !x25fd) ! 1102: x = tn_ini(); /* Initialize TELNET protocol */ ! 1103: return(x); ! 1104: } else { /* Terminal device */ ! 1105: #endif /* NETCONN */ ! 1106: ! 1107: #ifdef NAMEFD ! 1108: /* ! 1109: This code lets you give Kermit an open file descriptor for a serial ! 1110: communication device, rather than a device name. Kermit assumes that the ! 1111: line is already open, locked, conditioned with the right parameters, etc. ! 1112: */ ! 1113: for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */ ! 1114: if (*p == '\0') { ! 1115: ttyfd = atoi(ttname); /* Is there a way to test it's open? */ ! 1116: debug(F111,"ttopen got open fd",ttname,ttyfd); ! 1117: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */ ! 1118: xlocal = *lcl = 1; /* Assume it's local. */ ! 1119: netconn = 0; /* Assume it's not a network. */ ! 1120: tvtflg = 0; /* Might need to initialize modes. */ ! 1121: ttmdm = modem; /* Remember modem type. */ ! 1122: fdflag = 0; /* Stdio not redirected. */ ! 1123: ttfdflg = 1; /* Flag we were opened this way. */ ! 1124: ! 1125: #ifdef sony_news /* Sony NEWS */ ! 1126: /* Get device Kanji mode */ ! 1127: if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { ! 1128: perror("ttopen error getting Kanji mode"); ! 1129: debug(F101,"ttopen error getting Kanji mode","",0); ! 1130: km_ext = -1; /* Make sure this stays undefined. */ ! 1131: } ! 1132: #endif /* sony_news */ ! 1133: return(0); /* Return success */ ! 1134: } ! 1135: #endif /* NAMEFD */ ! 1136: #ifdef NETCONN ! 1137: } ! 1138: #endif /* NETCONN */ ! 1139: ! 1140: /* Here we have to open a serial device of the given name. */ ! 1141: ! 1142: occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */ ! 1143: ! 1144: tvtflg = 0; /* Flag for use by ttvt(). */ ! 1145: /* 0 = ttvt not called yet for this device */ ! 1146: ! 1147: fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */ ! 1148: debug(F101,"ttopen fdflag","",fdflag); ! 1149: ! 1150: ttmdm = modem; /* Make this available to other fns */ ! 1151: xlocal = *lcl; /* Make this available to other fns */ ! 1152: ! 1153: /* Code for handling bidirectional tty lines goes here. */ ! 1154: /* Use specified method for turning off logins and suppressing getty. */ ! 1155: ! 1156: #ifdef ACUCNTRL ! 1157: /* Should put call to priv_on() here, but that would be very risky! */ ! 1158: acucntrl("disable",ttname); /* acucntrl() program. */ ! 1159: /* and priv_off() here... */ ! 1160: #else ! 1161: #ifdef ATT7300 ! 1162: if ((attmodem & DOGETY) == 0) /* offgetty() program. */ ! 1163: attmodem |= offgetty(ttname); /* Remember response. */ ! 1164: #endif /* ATT7300 */ ! 1165: #endif /* ACUCNTRL */ ! 1166: ! 1167: /* ! 1168: In the following section, we open the tty device for read/write. ! 1169: If a modem has been specified via "set modem" prior to "set line" ! 1170: then the O_NDELAY parameter is used in the open, provided this symbol ! 1171: is defined (e.g. in fcntl.h), so that the program does not hang waiting ! 1172: for carrier (which in most cases won't be present because a connection ! 1173: has not been dialed yet). O_NDELAY is removed later on in ttopen(). It ! 1174: would make more sense to first determine if the line is local before ! 1175: doing this, but because ttyname() requires a file descriptor, we have ! 1176: to open it first. See do_open(). ! 1177: ! 1178: Now open the device using the desired treatment of carrier. ! 1179: If carrier is REQUIRED, then open could hang forever, so an optional ! 1180: timer is provided. If carrier is not required, the timer should never ! 1181: go off, and should do no harm... ! 1182: */ ! 1183: ttotmo = 0; /* Flag no timeout */ ! 1184: if (timo > 0) { ! 1185: int xx; ! 1186: saval = signal(SIGALRM,timerh); /* Timed, set up timer. */ ! 1187: xx = alarm(timo); /* Timed open() */ ! 1188: debug(F101,"ttopen alarm","",xx); ! 1189: if (setjmp(sjbuf)) { ! 1190: ttotmo = 1; /* Flag timeout. */ ! 1191: } else ttyfd = do_open(ttname); ! 1192: ttimoff(); ! 1193: debug(F111,"ttopen","modem",modem); ! 1194: debug(F101," ttyfd","",ttyfd); ! 1195: debug(F101," alarm return","",ttotmo); ! 1196: } else ttyfd = do_open(ttname); ! 1197: debug(F111,"ttopen ttyfd",ttname,ttyfd); ! 1198: if (ttyfd < 0) { /* If couldn't open, fail. */ ! 1199: #ifdef ATT7300 ! 1200: if (attmodem & DOGETY) /* was getty(1m) running before us? */ ! 1201: ongetty(ttnmsv); /* yes, restart on tty line */ ! 1202: attmodem &= ~DOGETY; /* no phone in use, getty restored */ ! 1203: #else ! 1204: #if ACUCNTRL ! 1205: /* Should put call to priv_on() here, but that would be risky! */ ! 1206: acucntrl("enable",ttname); /* acucntrl() program. */ ! 1207: /* and priv_off() here... */ ! 1208: #endif /* ACUNTRL */ ! 1209: #endif /* ATT7300 */ ! 1210: ! 1211: signal(SIGINT,occt); /* Put old Ctrl-C trap back. */ ! 1212: if (errno == EACCES) { /* Device is protected against user */ ! 1213: perror(ttname); /* Print message */ ! 1214: debug(F111,"ttopen tty access denied",ttname,errno); ! 1215: return(-4); ! 1216: } else return(ttotmo ? -2 : -1); ! 1217: } ! 1218: ! 1219: /* Make sure it's a real tty. */ ! 1220: if (!isatty(ttyfd)) { ! 1221: fprintf(stderr,"%s is not a tty!\n",ttname); ! 1222: debug(F110,"ttopen not a tty",ttname,0); ! 1223: close(ttyfd); ! 1224: ttyfd = -1; ! 1225: signal(SIGINT,occt); ! 1226: return(-1); ! 1227: } ! 1228: ! 1229: #ifdef aegis ! 1230: /* Apollo C runtime claims that console pads are tty devices, which ! 1231: * is reasonable, but they aren't any good for packet transfer. */ ! 1232: ios_$inq_type_uid((short)ttyfd, ttyuid, st); ! 1233: if (st.all != status_$ok) { ! 1234: fprintf(stderr, "problem getting tty object type: "); ! 1235: error_$print(st); ! 1236: } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */ ! 1237: close(ttyfd); ttyfd = -1; ! 1238: errno = ENOTTY; perror(ttname); ! 1239: signal(SIGINT,occt); ! 1240: return(-1); ! 1241: } ! 1242: #endif /* aegis */ ! 1243: ! 1244: strncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */ ! 1245: ! 1246: /* Caller wants us to figure out if line is controlling tty */ ! 1247: ! 1248: if (*lcl < 0) { ! 1249: int x0 = 0, x1 = 0; ! 1250: if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */ ! 1251: xlocal = 0; ! 1252: debug(F111," ttname=CTTNAM",ttname,xlocal); ! 1253: ! 1254: /* If any of 0, 1, or 2 not redirected, we can use ttyname() to get */ ! 1255: /* the name of the controlling terminal... */ ! 1256: ! 1257: /* ! 1258: Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but ! 1259: never closes it. If it is called often enough, we run out of file ! 1260: descriptors and subsequent open()'s of other devices or files can fail. ! 1261: */ ! 1262: ! 1263: } else if ((x0 = isatty(0)) || (x1 = isatty(1)) || isatty(2)) { ! 1264: #ifndef MINIX ! 1265: if (x0) ! 1266: x = ttyname(0); /* and compare it with the */ ! 1267: else if (x1) /* tty device name. */ ! 1268: x = ttyname(1); ! 1269: else x = ttyname(2); ! 1270: strncpy(cname,x,DEVNAMLEN); /* (copy from internal static buf) */ ! 1271: debug(F110," cname",x,0); ! 1272: x = ttyname(ttyfd); /* Gat real name of ttname. */ ! 1273: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; /* Compare. */ ! 1274: debug(F111," ttyname",x,xlocal); ! 1275: #else ! 1276: xlocal = 1; /* Can't do this test in MINIX */ ! 1277: #endif /* MINIX */ ! 1278: } else { /* Else, if stdin redirected... */ ! 1279: #ifdef SVORPOSIX ! 1280: /* System V provides nice ctermid() function to get name of controlling tty */ ! 1281: ctermid(cname); /* Get name of controlling terminal */ ! 1282: debug(F110," ctermid",cname,0); ! 1283: x = ttyname(ttyfd); /* Compare with name of comm line. */ ! 1284: xlocal = (strncmp(x,cname,DEVNAMLEN) == 0) ? 0 : 1; ! 1285: debug(F111," ttyname",x,xlocal); ! 1286: #else ! 1287: /* Just assume local */ ! 1288: xlocal = 1; ! 1289: #endif /* SVORPOSIX */ ! 1290: debug(F101," redirected stdin","",xlocal); ! 1291: } ! 1292: } ! 1293: ! 1294: #ifndef NOFDZERO ! 1295: /* Note, the following code was added so that Unix "idle-line" snoopers */ ! 1296: /* would not think Kermit was idle when it was transferring files, and */ ! 1297: /* maybe log people out. */ ! 1298: if (xlocal == 0) { /* Remote mode */ ! 1299: if (fdflag == 0) { /* Standard i/o is not redirected */ ! 1300: debug(F100,"ttopen setting ttyfd = 0","",0); ! 1301: close(ttyfd); /* Use file descriptor 0 */ ! 1302: ttyfd = 0; ! 1303: } else { /* Standard i/o is redirected */ ! 1304: debug(F101,"ttopen stdio redirected","",ttyfd); ! 1305: } ! 1306: } ! 1307: #endif /* NOFDZERO */ ! 1308: ! 1309: /* Now check if line is locked -- if so fail, else lock for ourselves */ ! 1310: /* Note: After having done this, don't forget to delete the lock if you */ ! 1311: /* leave ttopen() with an error condition. */ ! 1312: ! 1313: lkf = 0; /* Check lock */ ! 1314: if (xlocal > 0) { ! 1315: int xx; int xpid; ! 1316: if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */ ! 1317: debug(F111,"ttopen ttlock fails",ttname,xx); ! 1318: close(ttyfd); /* Close the device. */ ! 1319: ttyfd = -1; /* Erase its file descriptor. */ ! 1320: signal(SIGINT,occt); /* Put old SIGINT back. */ ! 1321: if (xx == -2) { /* If lockfile says tty is in use, */ ! 1322: char *p = malloc(200); /* print an ls -l listing */ ! 1323: if (p) { /* if we can get space... */ ! 1324: sprintf(p,"/bin/ls -l %s",flfnam); ! 1325: zsyscmd(p); /* Get listing. */ ! 1326: free(p); /* free the space */ ! 1327: xpid = ttrpid(flfnam); /* Try to read pid from lockfile */ ! 1328: priv_off(); /* Turn privs back off. */ ! 1329: if (xpid > -1) printf("pid = %d\n",xpid); /* show pid */ ! 1330: } ! 1331: return(-5); /* Code for device in use */ ! 1332: } else return(-3); /* Access denied */ ! 1333: } else lkf = 1; ! 1334: } ! 1335: ! 1336: /* Got the line, now set the desired value for local. */ ! 1337: ! 1338: if (*lcl != 0) *lcl = xlocal; ! 1339: ! 1340: /* Some special stuff for v7... */ ! 1341: ! 1342: #ifdef V7 ! 1343: #ifndef MINIX ! 1344: if (kmem[TTY] < 0) { /* If open, then skip this. */ ! 1345: qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */ ! 1346: if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) { ! 1347: fprintf(stderr, "Can't read /dev/kmem in ttopen.\n"); ! 1348: perror("/dev/kmem"); ! 1349: exit(1); ! 1350: } ! 1351: } ! 1352: #endif /* !MINIX */ ! 1353: #endif /* V7 */ ! 1354: ! 1355: /* No failure returns after this point */ ! 1356: ! 1357: #ifdef ultrix ! 1358: #ifdef TIOCSINUSE ! 1359: if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) { ! 1360: fprintf(stderr, "Can't set in-use flag on modem.\n"); ! 1361: perror("TIOCSINUSE"); ! 1362: } ! 1363: #endif /* TIOCSINUSE */ ! 1364: #endif /* ultrix */ ! 1365: ! 1366: /* Get tty device settings */ ! 1367: ! 1368: #ifdef BSD44ORPOSIX /* POSIX */ ! 1369: tcgetattr(ttyfd,&ttold); ! 1370: debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag); ! 1371: tcgetattr(ttyfd,&ttraw); ! 1372: tcgetattr(ttyfd,&tttvt); ! 1373: #else /* BSD, V7, and all others */ ! 1374: #ifdef ATTSV /* AT&T UNIX */ ! 1375: ioctl(ttyfd,TCGETA,&ttold); ! 1376: debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag); ! 1377: ioctl(ttyfd,TCGETA,&ttraw); ! 1378: ioctl(ttyfd,TCGETA,&tttvt); ! 1379: #else ! 1380: gtty(ttyfd,&ttold); ! 1381: debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags); ! 1382: ! 1383: #ifdef sony_news /* Sony NEWS */ ! 1384: if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */ ! 1385: perror("ttopen error getting Kanji mode"); ! 1386: debug(F101,"ttopen error getting Kanji mode","",0); ! 1387: km_ext = -1; /* Make sure this stays undefined. */ ! 1388: } ! 1389: #endif /* sony_news */ ! 1390: ! 1391: #ifdef TIOCGETC ! 1392: tcharf = 0; /* In remote mode, also get */ ! 1393: if (xlocal == 0) { /* special characters */ ! 1394: if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) { ! 1395: debug(F100,"ttopen TIOCGETC failed","",0); ! 1396: } else { ! 1397: tcharf = 1; /* It worked. */ ! 1398: ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */ ! 1399: debug(F100,"ttopen TIOCGETC ok","",0); ! 1400: } ! 1401: } ! 1402: #else ! 1403: debug(F100,"ttopen TIOCGETC not defined","",0); ! 1404: #endif /* TIOCGETC */ ! 1405: ! 1406: #ifdef TIOCGLTC ! 1407: ltcharf = 0; /* In remote mode, also get */ ! 1408: if (xlocal == 0) { /* local special characters */ ! 1409: if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) { ! 1410: debug(F100,"ttopen TIOCGLTC failed","",0); ! 1411: } else { ! 1412: ltcharf = 1; /* It worked. */ ! 1413: ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */ ! 1414: debug(F100,"ttopen TIOCGLTC ok","",0); ! 1415: } ! 1416: } ! 1417: #else ! 1418: debug(F100,"ttopen TIOCGLTC not defined","",0); ! 1419: #endif /* TIOCGLTC */ ! 1420: ! 1421: #ifdef TIOCLGET ! 1422: lmodef = 0; ! 1423: if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) { ! 1424: debug(F100,"ttopen TIOCLGET failed","",0); ! 1425: } else { ! 1426: lmodef = 1; ! 1427: debug(F100,"ttopen TIOCLGET ok","",0); ! 1428: } ! 1429: #endif /* TIOCLGET */ ! 1430: ! 1431: gtty(ttyfd,&ttraw); /* And a copy of it for packets*/ ! 1432: gtty(ttyfd,&tttvt); /* And one for virtual tty service */ ! 1433: ! 1434: #endif /* ATTSV */ ! 1435: #endif /* BSD44ORPOSIX */ ! 1436: ! 1437: ! 1438: /* Section for changing line discipline. It's restored in ttres(). */ ! 1439: ! 1440: #ifdef BSD41 ! 1441: /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */ ! 1442: { int k; ! 1443: ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */ ! 1444: debug(F101,"4.1bsd line discipline","",ttld); ! 1445: k = OTTYDISC; /* Switch to "old" discipline */ ! 1446: k = ioctl(ttyfd, TIOCSETD, &k); ! 1447: debug(F101,"4.1bsd tiocsetd","",k); ! 1448: } ! 1449: #endif /* BSD41 */ ! 1450: ! 1451: #ifdef aegis ! 1452: /* This was previously done before the last two TCGETA or gtty above, ! 1453: * in both the ATTSV and not-ATTSV case. If it is not okay to have only ! 1454: * one copy if it here instead, give us a shout! ! 1455: */ ! 1456: sio_$control((short)ttyfd, sio_$raw_nl, false, st); ! 1457: if (xlocal) { /* ignore breaks from local line */ ! 1458: sio_$control((short)ttyfd, sio_$int_enable, false, st); ! 1459: sio_$control((short)ttyfd, sio_$quit_enable, false, st); ! 1460: } ! 1461: #endif /* aegis */ ! 1462: ! 1463: #ifdef VXVE ! 1464: ttraw.c_line = 0; /* STTY line 0 for VX/VE */ ! 1465: tttvt.c_line = 0; /* STTY line 0 for VX/VE */ ! 1466: ioctl(ttyfd,TCSETA,&ttraw); ! 1467: #endif /* vxve */ ! 1468: ! 1469: /* If O_NDELAY was used during open(), then remove it now. */ ! 1470: ! 1471: #ifdef O_NDELAY ! 1472: if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) { ! 1473: ! 1474: #ifndef aegis ! 1475: if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0 ) ! 1476: perror("Can't unset O_NDELAY"); ! 1477: #endif /* aegis */ ! 1478: /* Some systems, notably Xenix (don't know how common this is in ! 1479: * other systems), need special treatment to get rid of the O_NDELAY ! 1480: * behaviour on read() with respect to carrier presence (i.e. read() ! 1481: * returning 0 when carrier absent), even though the above fcntl() ! 1482: * is enough to make read() wait for input when carrier is present. ! 1483: * This magic, in turn, requires CLOCAL for working when the carrier ! 1484: * is absent. But if xlocal == 0, presumably you already have CLOCAL ! 1485: * or you have a carrier, otherwise you wouldn't be running this. ! 1486: */ ! 1487: #ifdef ATTSV ! 1488: #ifdef BSD44 ! 1489: tcsetattr(ttyfd, TCSADRAIN, &ttraw); ! 1490: #else ! 1491: if (xlocal) { ! 1492: ttraw.c_cflag |= CLOCAL; ! 1493: ioctl(ttyfd, TCSETA, &ttraw); ! 1494: } ! 1495: #endif /* BSD44 */ ! 1496: #endif /* ATTSV */ ! 1497: #ifndef SCO3R2 ! 1498: #ifndef OXOS ! 1499: /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */ ! 1500: close( priv_opn(ttname, O_RDWR) ); /* Magic to force change. */ ! 1501: #endif /* OXOS */ ! 1502: #endif /* SCO3R2 */ ! 1503: } ! 1504: #endif /* O_NDELAY */ ! 1505: ! 1506: /* Instruct the system how to treat the carrier, and set a few other tty ! 1507: * parameters. ! 1508: * ! 1509: * This also undoes the temporary setting of CLOCAL that may have been done ! 1510: * for the close(open()) above (except in Xenix). Also throw in ~ECHO, to ! 1511: * prevent the other end of the line from sitting there talking to itself, ! 1512: * producing garbage when the user performs a connect. ! 1513: * ! 1514: * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL. ! 1515: * Now it thinks CLOCAL is always on. It seems the only real solution for ! 1516: * Xenix is to switch between the lower and upper case device names. ! 1517: * ! 1518: * This section may at some future time expand into setting a complete ! 1519: * collection of tty parameters, or call a function shared with ttpkt()/ ! 1520: * ttvt() that does so. On the other hand, the initial parameters are not ! 1521: * that important, since ttpkt() or ttvt() should always fix that before ! 1522: * any communication is done. Well, we'll see... ! 1523: */ ! 1524: if (xlocal) { ! 1525: curcarr = -2; ! 1526: carrctl(&ttraw, ttcarr == CAR_ON); ! 1527: ! 1528: #ifdef SVORPOSIX ! 1529: ttraw.c_lflag &= ~ECHO; ! 1530: ttold.c_lflag &= ~ECHO; ! 1531: #ifdef BSD44ORPOSIX ! 1532: tcsetattr(ttyfd, TCSADRAIN, &ttraw); ! 1533: #else ! 1534: ioctl(ttyfd, TCSETA, &ttraw); ! 1535: #endif /* BSD44ORPOSIX */ ! 1536: ! 1537: #else /* BSD, etc */ ! 1538: ttraw.sg_flags &= ~ECHO; ! 1539: ttold.sg_flags &= ~ECHO; ! 1540: stty(ttyfd,&ttraw); ! 1541: #endif /* SVORPOSIX */ ! 1542: /* ttflui(); This fails for some reason */ ! 1543: } ! 1544: ! 1545: /* Get current speed */ ! 1546: ! 1547: ttspeed = ttgspd(); ! 1548: debug(F101,"ttopen ttspeed","",ttspeed); ! 1549: ! 1550: /* Done, make entries in debug log, restore Ctrl-C trap, and return. */ ! 1551: ! 1552: debug(F101,"ttopen, ttyfd","",ttyfd); ! 1553: debug(F101," lcl","",*lcl); ! 1554: debug(F111," lock file",flfnam,lkf); ! 1555: signal(SIGINT,occt); ! 1556: return(0); ! 1557: } ! 1558: ! 1559: ! 1560: /* D O _ O P E N -- Do the right kind of open() call for the tty. */ ! 1561: ! 1562: int ! 1563: do_open(ttname) char *ttname; { ! 1564: ! 1565: #ifndef O_NDELAY /* O_NDELAY not defined */ ! 1566: return(priv_opn(ttname,2)); ! 1567: #else /* O_NDELAY defined */ ! 1568: ! 1569: #ifdef ATT7300 ! 1570: /* ! 1571: Open comms line without waiting for carrier so initial call does not hang ! 1572: because state of "modem" is likely unknown at the initial call -jrd. ! 1573: If this is needed for the getty stuff to work, and the open would not work ! 1574: without O_NDELAY when getty is still on, then this special case is ok. ! 1575: Otherwise, get rid of it. -ske ! 1576: */ ! 1577: return(priv_opn(ttname, O_RDWR | O_NDELAY)); ! 1578: ! 1579: #else /* !ATT7300 */ ! 1580: ! 1581: /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */ ! 1582: ! 1583: return(priv_opn(ttname, O_RDWR | ((ttcarr != CAR_ON) ? O_NDELAY : 0) )); ! 1584: ! 1585: #endif /* !ATT7300 */ ! 1586: #endif /* O_NDELAY */ ! 1587: } ! 1588: ! 1589: /* T T C L O S -- Close the TTY, releasing any lock. */ ! 1590: ! 1591: int ! 1592: ttclos(foo) int foo; { /* Arg req'd for signal() prototype */ ! 1593: int x = 0; ! 1594: ! 1595: debug(F101,"ttclos ttyfd","",ttyfd); ! 1596: if (ttyfd < 0) return(0); /* Wasn't open. */ ! 1597: ! 1598: if (ttfdflg) return(0); /* If we got ttyfd from another */ ! 1599: /* process, don't close it. */ ! 1600: tvtflg = 0; ! 1601: #ifdef NETCONN ! 1602: if (netconn) { /* Network connection. */ ! 1603: debug(F100,"ttclos closing net","",0); ! 1604: netclos(); /* Close it. */ ! 1605: netconn = 0; ! 1606: return(0); ! 1607: } ! 1608: #endif /* NETCONN */ ! 1609: #ifdef FT21 ! 1610: if (xlocal) ioctl(ttyfd,TIOCHPCL, NULL); ! 1611: #endif /* FT21 */ ! 1612: #ifdef ultrix ! 1613: if (xlocal) ioctl(ttyfd, TIOCNCAR, NULL); ! 1614: #endif /* ultrix */ ! 1615: if (xlocal) { ! 1616: debug(F100,"ttclos about to call ttunlck","",0); ! 1617: if (ttunlck()) /* Release uucp-style lock */ ! 1618: fprintf(stderr,"Warning, problem releasing lock\r\n"); ! 1619: debug(F100,"ttclos about to call ttres","",0); ! 1620: } ! 1621: if (ttyfd > 0) { ! 1622: int xx; ! 1623: saval = signal(SIGALRM,timerh); /* Enable timer interrupt. */ ! 1624: xx = alarm(5); /* Allow 5 seconds for this. */ ! 1625: debug(F101,"ttclos alarm","",xx); ! 1626: if (setjmp(sjbuf)) { /* Timer went off? */ ! 1627: x = -1; ! 1628: } else { /* What we're really trying to do */ ! 1629: if (xlocal) { ! 1630: tthang(); /* Hang up first, then... */ ! 1631: ttres(); /* reset device modes. */ ! 1632: } ! 1633: debug(F101,"ttclos about to call close","",ttyfd); ! 1634: close(ttyfd); /* Close the device. */ ! 1635: x = 1; ! 1636: } ! 1637: ttimoff(); /* Turn off timer. */ ! 1638: if (x < 0) { ! 1639: fprintf(stderr,"?Timed out closing device: %s\n",ttnmsv); ! 1640: debug(F100,"ttclos timed out","",0); ! 1641: } ! 1642: } ! 1643: ttyfd = -1; /* Invalidate the file descriptor. */ ! 1644: #ifdef sony_news ! 1645: km_ext = -1; /* Invalidate device's Kanji-mode */ ! 1646: #endif /* sony_news */ ! 1647: ! 1648: /* For bidirectional lines, restore getty if it was there before. */ ! 1649: ! 1650: #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */ ! 1651: acucntrl("enable",ttnmsv); /* Enable getty on the device. */ ! 1652: #else ! 1653: #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */ ! 1654: if (attmodem & DOGETY) /* Was getty(1m) running before us? */ ! 1655: ongetty(ttnmsv); /* Yes, restart getty on tty line */ ! 1656: attmodem &= ~DOGETY; /* No phone in use, getty restored */ ! 1657: #endif /* ATT7300 */ ! 1658: #endif /* System-dependent getty-restoring methods */ ! 1659: ! 1660: debug(F100,"ttclos done","",0); ! 1661: return(0); ! 1662: } ! 1663: ! 1664: /* T T H A N G -- Hangup phone line or network connection. */ ! 1665: /* ! 1666: Returns: ! 1667: 0 if it does nothing. ! 1668: 1 if it believes that it hung up successfully. ! 1669: -1 if it believes that the hangup attempt failed. ! 1670: */ ! 1671: ! 1672: #define HUPTIME 500 /* Milliseconds for hangup */ ! 1673: ! 1674: int ! 1675: tthang() { ! 1676: int x = 0; /* Sometimes used as return code. */ ! 1677: #ifndef POSIX ! 1678: int z; /* worker */ ! 1679: #endif /* POSIX */ ! 1680: ! 1681: #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */ ! 1682: int spdsav; /* for saving speed */ ! 1683: int spdsavi; ! 1684: #ifdef HPUX ! 1685: mflag dtr_down = 00000000000, ! 1686: modem_rtn; ! 1687: mflag modem_sav; ! 1688: char modem_state[64]; ! 1689: #endif /* HPUX */ ! 1690: int flags; /* fcntl flags */ ! 1691: unsigned short ttc_save; ! 1692: #endif /* SVORPOSIX */ ! 1693: ! 1694: if (ttyfd < 0) return(0); /* Don't do this if not open */ ! 1695: if (xlocal < 1) return(0); /* Don't do this if not local */ ! 1696: ! 1697: #ifdef NETCONN ! 1698: if (netconn) /* Network connection. */ ! 1699: return((netclos() < 0) ? -1 : 1); /* Just close it. */ ! 1700: #endif /* NETCONN */ ! 1701: ! 1702: /* From here down, we handle real tty devices. */ ! 1703: ! 1704: #ifdef BSD44ORPOSIX ! 1705: /* Should add some error checking here... */ ! 1706: debug(F100,"tthang POSIX style","",0); ! 1707: spdsav = cfgetospeed(&ttcur); /* Get current speed */ ! 1708: spdsavi = cfgetispeed(&ttcur); /* Get current speed */ ! 1709: cfsetospeed(&ttcur,B0); /* Replace by 0 */ ! 1710: cfsetispeed(&ttcur,B0); ! 1711: if (tcsetattr(ttyfd,TCSADRAIN,&ttcur) == -1) ! 1712: debug(F100,"tthang tcsetattr fails","",errno); ! 1713: msleep(HUPTIME); /* Sleep */ ! 1714: cfsetospeed(&ttcur,spdsav); /* Restore previous speed */ ! 1715: cfsetispeed(&ttcur,spdsavi); ! 1716: tcsetattr(ttyfd,TCSADRAIN,&ttcur); ! 1717: return(1); ! 1718: ! 1719: #else /* BSD44ORPOSIX */ ! 1720: ! 1721: #ifdef aegis /* Apollo Aegis */ ! 1722: sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */ ! 1723: msleep(HUPTIME); /* pause */ ! 1724: sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */ ! 1725: return(1); ! 1726: #endif /* aegis */ ! 1727: ! 1728: #ifdef ANYBSD /* Any BSD version. */ ! 1729: debug(F100,"tthang BSD style","",0); ! 1730: if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */ ! 1731: debug(F101,"tthang TIOCCDTR fails","",errno); ! 1732: return(-1); ! 1733: } ! 1734: msleep(HUPTIME); /* For about 1/2 sec */ ! 1735: errno = 0; ! 1736: x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */ ! 1737: if (x < 0) { ! 1738: /* ! 1739: For some reason, this tends to fail with "no such device or address" ! 1740: but the operation still works, probably because of the close/open ! 1741: later on. So let's not scare the user unnecessarily here. ! 1742: */ ! 1743: debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */ ! 1744: x = 1; /* Pretend we succeeded */ ! 1745: } else if (x == 0) x = 1; /* Success */ ! 1746: #ifdef COMMENT ! 1747: #ifdef FT21 ! 1748: ioctl(ttyfd, TIOCSAVEMODES, 0); ! 1749: ioctl(ttyfd, TIOCHPCL, 0); ! 1750: close(ttyfd); /* Yes, must do this twice */ ! 1751: if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */ ! 1752: return(-1); /* (but why?) */ ! 1753: else x = 1; ! 1754: #endif /* FT21 */ ! 1755: #endif /* COMMENT */ ! 1756: close(do_open(ttnmsv)); /* Clear i/o error condition */ ! 1757: errno = 0; ! 1758: #ifdef COMMENT ! 1759: /* This is definitely dangerous. Why was it here? */ ! 1760: z = ttvt(ttspeed,ttflow); /* Restore modes. */ ! 1761: debug(F101,"tthang ttvt returns","",z); ! 1762: return(z < 0 ? -1 : 1); ! 1763: #else ! 1764: return(x); ! 1765: #endif /* COMMENT */ ! 1766: #endif /* ANYBSD */ ! 1767: ! 1768: #ifdef ATTSV ! 1769: /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */ ! 1770: ! 1771: #ifdef HPUX ! 1772: /* Hewlett Packard allows explicit manipulation of modem signals. */ ! 1773: ! 1774: #ifdef COMMENT ! 1775: /* Old way... */ ! 1776: debug(F100,"tthang HP-UX style","",0); ! 1777: if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) /* lower DTR */ ! 1778: return(-1); /* oops, can't. */ ! 1779: msleep(HUPTIME); /* Pause half a second. */ ! 1780: x = 1; /* Set return code */ ! 1781: if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */ ! 1782: if ((modem_rtn & MDCD) != 0) /* Check if CD is low. */ ! 1783: x = -1; /* CD didn't drop, fail. */ ! 1784: } else x = -1; ! 1785: ! 1786: /* Even if above calls fail, RTS & DTR should be turned back on. */ ! 1787: modem_rtn = MRTS | MDTR; ! 1788: if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1; ! 1789: return(x); ! 1790: #else ! 1791: /* New way, from Hellmuth Michaelis */ ! 1792: debug(F100,"tthang HP-UX style, HPUXDEBUG","",0); ! 1793: if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */ ! 1794: debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0); ! 1795: return(-1); ! 1796: } ! 1797: sprintf(modem_state,"%#lx",modem_rtn); ! 1798: debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0); ! 1799: modem_sav = modem_rtn; /* save line status */ ! 1800: modem_rtn &= ~MDTR; /* DTR bit down */ ! 1801: sprintf(modem_state,"%#lx",modem_rtn); ! 1802: debug(F110,"tthang HP-UX: modem lines lowered DTR = ",modem_state,0); ! 1803: if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */ ! 1804: debug(F100,"tthang HP-UX: can't lower DTR!","",0); ! 1805: return(-1); /* oops, can't. */ ! 1806: } ! 1807: msleep(HUPTIME); /* Pause half a second. */ ! 1808: x = 1; /* Set return code */ ! 1809: if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */ ! 1810: sprintf(modem_state,"%#lx",modem_rtn); ! 1811: debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0); ! 1812: if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */ ! 1813: debug(F100,"tthang HP-UX: DCD didn't get down!","",0); ! 1814: x = -1; /* CD didn't drop, fail. */ ! 1815: } else { ! 1816: debug(F100,"tthang HP-UX: DCD down!","",0); ! 1817: } ! 1818: } else { ! 1819: x = -1; ! 1820: debug(F100,"tthang HP-UX: can't get DCD status !","",0); ! 1821: } ! 1822: ! 1823: /* Even if above calls fail, RTS & DTR should be turned back on. */ ! 1824: ! 1825: modem_sav |= (MRTS | MDTR); ! 1826: if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) { ! 1827: x = -1; ! 1828: debug(F100,"tthang HP-UX: can't set saved state |=(RTS | DTR)","",0); ! 1829: } else { ! 1830: sprintf(modem_state,"%#lx",modem_sav); ! 1831: debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0); ! 1832: } ! 1833: return(x); ! 1834: #endif /* COMMENT */ ! 1835: ! 1836: #else /* AT&T but not HP-UX */ ! 1837: ! 1838: /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */ ! 1839: /* It is not known how many, if any, systems actually implement them, */ ! 1840: /* so we include them here in ifdef's. */ ! 1841: ! 1842: #ifndef _IBMR2 ! 1843: /* ! 1844: No modem-signal twiddling for IBM RT PC or RS/6000. ! 1845: In AIX 3.1 and earlier, the ioctl() call is broken. ! 1846: This code could be activated for AIX 3.1 with PTF 2006 or later ! 1847: (e.g. AIX 3.2), but close/open does the job too, so why bother. ! 1848: */ ! 1849: #ifdef TIOCMBIS /* Bit Set */ ! 1850: #ifdef TIOCMBIC /* Bit Clear */ ! 1851: #ifdef TIOCM_DTR /* DTR */ ! 1852: ! 1853: /* Clear DTR, sleep 300 msec, turn it back on. */ ! 1854: /* If any of the ioctl's return failure, go on to the next section. */ ! 1855: ! 1856: z = TIOCM_DTR; /* Code for DTR. */ ! 1857: #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */ ! 1858: z |= TIOCM_RTS; ! 1859: #endif /* TIOCM_RTS */ ! 1860: ! 1861: debug(F101,"tthang TIOCM signal mask","",z); ! 1862: if (ioctl(ttyfd,TIOCMBIC,&z) > -1) { /* Try to lower DTR. */ ! 1863: debug(F100,"tthang TIOCMBIC ok","",0); ! 1864: msleep(HUPTIME); /* Pause half a second. */ ! 1865: if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */ ! 1866: debug(F100,"tthang TIOCMBIS ok","",0); ! 1867: #ifndef CLSOPN ! 1868: return(1); /* Success, done. */ ! 1869: #endif /* CLSOPN */ ! 1870: } else { /* Couldn't raise, continue. */ ! 1871: debug(F101,"tthang TIOCMBIS errno","",errno); ! 1872: } ! 1873: } else { /* Couldn't lower, continue. */ ! 1874: debug(F101,"tthang TIOCMBIC errno","",errno); ! 1875: } ! 1876: #endif /* TIOCM_DTR */ ! 1877: #endif /* TIOCMBIC */ ! 1878: #endif /* TIOCMBIS */ ! 1879: #endif /* _IBMR2 */ ! 1880: /* ! 1881: General AT&T UNIX case, not HPUX. The following code is highly suspect. No ! 1882: two AT&T-based systems seem to do this the same way. The object is simply ! 1883: to turn off DTR and then turn it back on. SVID says the universal method ! 1884: for turning off DTR is to set the speed to zero, and this does seem to do ! 1885: the trick in all cases. But neither SVID nor any known man pages say how to ! 1886: turn DTR back on again. Some variants, like most Xenix implementations, ! 1887: raise DTR again when the speed is restored to a nonzero value. Others ! 1888: require the device to be closed and opened again, but this is risky because ! 1889: getty could seize the device during the instant it is closed. ! 1890: */ ! 1891: ! 1892: /* Return code for ioctl failures... */ ! 1893: #ifdef ATT6300 ! 1894: x = 1; /* ATT6300 doesn't want to fail... */ ! 1895: #else ! 1896: x = -1; ! 1897: #endif /* ATT6300 */ ! 1898: ! 1899: debug(F100,"tthang get settings","",0); ! 1900: if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */ ! 1901: return(x); /* Fail if this doesn't work. */ ! 1902: if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */ ! 1903: return(x); ! 1904: ttc_save = ttcur.c_cflag; /* Remember current speed. */ ! 1905: spdsav = ttc_save & CBAUD; ! 1906: debug(F101,"tthang speed","",spdsav); ! 1907: ! 1908: #ifdef O_NDELAY ! 1909: debug(F100,"tthang turning O_NDELAY on","",0); ! 1910: fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */ ! 1911: #endif /* O_NDELAY */ ! 1912: ! 1913: #ifdef ATT7300 /* This is the way it is SUPPOSED to work */ ! 1914: ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */ ! 1915: #else ! 1916: #ifdef RTAIX ! 1917: ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */ ! 1918: #else /* This way really works but may be dangerous */ ! 1919: #ifdef u3b2 ! 1920: ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */ ! 1921: /* (CLOCAL must be OFF) */ ! 1922: #else ! 1923: #ifdef SCO3R2 /* SCO UNIX 3.2 */ ! 1924: /* ! 1925: This is complete nonsense, but an SCO user claimed this change made ! 1926: hanging up work. Comments from other SCO UNIX 3.2 users would be ! 1927: appreciated. ! 1928: */ ! 1929: ttcur.c_cflag = CBAUD|B0; ! 1930: #else /* None of the above. */ ! 1931: ttcur.c_cflag = CLOCAL|HUPCL; /* Change all but these to zero */ ! 1932: /* (CLOCAL must be ON) */ ! 1933: #endif /* SCO3R2 */ ! 1934: #endif /* u3b2 */ ! 1935: #endif /* RTAIX */ ! 1936: #endif /* ATT7300 */ ! 1937: ! 1938: #ifdef COMMENT ! 1939: /* and if none of those work, try one of these... */ ! 1940: ttcur.c_cflag = 0; ! 1941: ttcur.c_cflag = CLOCAL; ! 1942: ttcur.c_cflag &= ~(CBAUD|HUPCL); ! 1943: ttcur.c_cflag &= ~(CBAUD|CREAD); ! 1944: ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL); ! 1945: /* or other combinations */ ! 1946: #endif /* COMMENT */ ! 1947: ! 1948: #ifdef TCXONC ! 1949: debug(F100,"tthang TCXONC","",0); ! 1950: ioctl(ttyfd, TCXONC, 1); ! 1951: #endif /* TCXONC */ ! 1952: ! 1953: #ifdef TIOCSTART ! 1954: debug(F100,"tthang TIOCSTART","",0); ! 1955: ioctl(ttyfd, TIOCSTART, 0); ! 1956: #endif /* TIOCSTART */ ! 1957: ! 1958: if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */ ! 1959: fcntl(ttyfd, F_SETFL, flags); /* Restore flags */ ! 1960: return(-1); /* before returning. */ ! 1961: } ! 1962: msleep(300); /* Give modem time to notice. */ ! 1963: ! 1964: /* Now, even though it doesn't say this in SVID or any man page, we have */ ! 1965: /* to close and reopen the device. This is not necessary for all systems, */ ! 1966: /* but it's impossible to predict which ones need it and which ones don't. */ ! 1967: ! 1968: #ifdef ATT7300 ! 1969: /* ! 1970: Special handling for ATT 7300 UNIX PC and 3B1, which have "phone" ! 1971: related ioctl's for their internal modems. attmodem has getty status and ! 1972: modem-in-use bit. Reportedly the ATT7300/3B1 PIOCDISC call is necessary, ! 1973: but also ruins the file descriptor, and no other phone(7) ioctl call can fix ! 1974: it. Whateverit does, it seems to escape detection with PIOCGETA and TCGETA. ! 1975: The only way to undo the damage is to close the fd and then reopen it. ! 1976: */ ! 1977: if (attmodem & ISMODEM) { ! 1978: debug(F100,"tthang attmodem close/open","",0); ! 1979: ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */ ! 1980: ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */ ! 1981: close(ttyfd); /* Close and reopen the fd. */ ! 1982: ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY); ! 1983: attmodem &= ~ISMODEM; /* Phone no longer in use. */ ! 1984: } ! 1985: #else /* !ATT7300 */ ! 1986: /* It seems we have to close and open the device for other AT&T systems */ ! 1987: /* too, and this is the place to do it. The following code does the */ ! 1988: /* famous close(open(...)) magic by default. If that doesn't work for you, */ ! 1989: /* then try uncommenting the following statement or putting -DCLSOPN in */ ! 1990: /* the makefile CFLAGS. */ ! 1991: ! 1992: /* #define CLSOPN */ ! 1993: ! 1994: #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */ ! 1995: ! 1996: #ifdef O_NDELAY ! 1997: #define OPENFLGS O_RDWR | O_NDELAY ! 1998: #else ! 1999: #define OPENFLGS O_RDWR ! 2000: #endif ! 2001: ! 2002: #ifndef CLSOPN ! 2003: /* This method is used by default, i.e. unless CLSOPN is defined. */ ! 2004: /* It is thought to be safer because there is no window where getty */ ! 2005: /* can seize control of the device. The drawback is that it might not work. */ ! 2006: ! 2007: debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS); ! 2008: close(priv_opn(ttnmsv, OPENFLGS)); ! 2009: ! 2010: #else ! 2011: /* This method is used if you #define CLSOPN. It is more likely to work */ ! 2012: /* than the previous method, but it's also more dangerous. */ ! 2013: ! 2014: debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS); ! 2015: close(ttyfd); ! 2016: msleep(10); ! 2017: ttyfd = priv_opn(ttnmsv, OPENFLGS); /* Open it again */ ! 2018: #endif /* CLSOPN */ ! 2019: #undef OPENFLGS ! 2020: ! 2021: #endif /* SCO32 */ ! 2022: #endif /* ATT7300 */ ! 2023: ! 2024: /* Now put all flags & modes back the way we found them. */ ! 2025: /* (Does the order of ioctl & fcntl matter ? ) */ ! 2026: ! 2027: debug(F100,"tthang restore settings","",0); ! 2028: ttcur.c_cflag = ttc_save; /* Get old speed back. */ ! 2029: if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */ ! 2030: return(-1); ! 2031: #ifdef O_NDELAY ! 2032: /* ! 2033: This is required for IBM RT and RS/6000, probably helps elsewhere too (?). ! 2034: After closing a modem line, the modem will probably not be asserting ! 2035: carrier any more, so we should not require carrier any more. If this ! 2036: causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather ! 2037: than O_NDELAY. ! 2038: */ ! 2039: flags &= ~O_NDELAY; /* Don't require carrier on reopen */ ! 2040: #endif /* O_NDELAY */ ! 2041: if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */ ! 2042: return(-1); ! 2043: ! 2044: return(1); ! 2045: #endif /* not HPUX */ ! 2046: #endif /* ATTSV */ ! 2047: #endif /* BSD44ORPOSIX */ ! 2048: } ! 2049: ! 2050: /* ! 2051: Major change in 5A(174). We used to use LPASS8, if it was defined, to ! 2052: allow 8-bit data and Xon/Xoff flow control at the same time. But this ! 2053: LPASS8 business seems to have been causing trouble for everybody but me! ! 2054: For example, Annex terminal servers, commonly used with Encore computers, ! 2055: do not support LPASS8 even though the Encore itself does. Ditto for many ! 2056: other terminal servers, TELNET connections, rlogin connections, etc etc. ! 2057: Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their ! 2058: serial lines, even though LPASS8 is a feature of 4.3BSD. So let's turn it ! 2059: off for everybody. That means we goes back to using raw mode, with no ! 2060: flow control. Phooey. ! 2061: ! 2062: NOTE: This must be done before the first reference to LPASS8 in this file, ! 2063: and after the last #include statment. ! 2064: */ ! 2065: #ifdef LPASS8 ! 2066: #undef LPASS8 ! 2067: #endif /* LPASS8 */ ! 2068: ! 2069: /* T T R E S -- Restore terminal to "normal" mode. */ ! 2070: ! 2071: /* [email protected]: There are two choices for what this function should do. ! 2072: * (1) Restore the tty to current "normal" mode, with carrier treatment ! 2073: * according to ttcarr, to be used after every kermit command. (2) Restore ! 2074: * the tty to the state it was in before kermit opened it. These choices ! 2075: * conflict, since ttold can't hold both choices of tty parameters. ttres() ! 2076: * is currently being called as in choice (1), but ttold basically holds ! 2077: * the initial parameters, as in (2), and the description at the beginning ! 2078: * of this file says (2). ! 2079: * ! 2080: * I don't think restoring tty parameters after all kermit commands makes ! 2081: * much of a difference. Restoring them upon exit from kermit may be of ! 2082: * some use in some cases (when the line is not restored automatically on ! 2083: * close, by the operating system). ! 2084: * ! 2085: * I can't choose which one it should be, so I haven't changed it. It ! 2086: * probably works as it is, too. It would probably even work even with ! 2087: * ttres() entirely deleted... ! 2088: * ! 2089: * (from fdc: Actually, this function operates in remote mode too, so ! 2090: * it restores the console (command) terminal to whatever mode it was ! 2091: * in before packet operations began, so that commands work right again.) ! 2092: */ ! 2093: int ! 2094: ttres() { /* Restore the tty to normal. */ ! 2095: int x; ! 2096: ! 2097: if (ttyfd < 0) return(-1); /* Not open. */ ! 2098: ! 2099: if (ttfdflg) return(0); /* Don't mess with terminal modes if */ ! 2100: /* we got ttyfd from another process */ ! 2101: #ifdef NETCONN ! 2102: if (netconn) return (0); /* Network connection, do nothing */ ! 2103: #endif /* NETCONN */ ! 2104: ! 2105: /* Real terminal device, so restore its original modes */ ! 2106: ! 2107: #ifdef BSD44ORPOSIX /* For POSIX like this */ ! 2108: x = tcsetattr(ttyfd,TCSADRAIN,&ttold); ! 2109: #else /* For all others... */ ! 2110: #ifdef ATTSV /* For AT&T versions... */ ! 2111: x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */ ! 2112: #else ! 2113: msleep(HUPTIME); /* This replaces sleep(1)... */ ! 2114: /* Put back sleep(1) if tty is */ ! 2115: /* messed up after close. */ ! 2116: ! 2117: /* Here we restore the modes for BSD */ ! 2118: ! 2119: #ifdef LPASS8 /* Undo "pass8" if it were done */ ! 2120: if (lmodef) { ! 2121: if (ioctl(ttyfd,TIOCLSET,&lmode) < 0) ! 2122: debug(F100,"ttres TIOCLSET failed","",0); ! 2123: else ! 2124: debug(F100,"ttres TIOCLSET ok","",0); ! 2125: } ! 2126: #endif /* LPASS8 */ ! 2127: ! 2128: #ifdef CK_DTRCTS /* Undo hardware flow if it were done */ ! 2129: if (lmodef) { ! 2130: if (ioctl(ttyfd,TIOCLSET,&lmode) < 0) ! 2131: debug(F100,"ttres TIOCLSET failed","",0); ! 2132: else ! 2133: debug(F100,"ttres TIOCLSET ok","",0); ! 2134: } ! 2135: #endif /* CK_DTRCTS */ ! 2136: ! 2137: #ifdef TIOCGETC /* Put back special characters */ ! 2138: if (tcharf && (xlocal == 0)) { ! 2139: if (ioctl(ttyfd,TIOCSETC,&tchold) < 0) ! 2140: debug(F100,"ttres TIOCSETC failed","",0); ! 2141: else ! 2142: debug(F100,"ttres TIOCSETC ok","",0); ! 2143: } ! 2144: #endif /* TIOCGETC */ ! 2145: ! 2146: #ifdef TIOCGLTC /* Put back local special characters */ ! 2147: if (ltcharf && (xlocal == 0)) { ! 2148: if (ioctl(ttyfd,TIOCSLTC,<chold) < 0) ! 2149: debug(F100,"ttres TIOCSLTC failed","",0); ! 2150: else ! 2151: debug(F100,"ttres TIOCSLTC ok","",0); ! 2152: } ! 2153: #endif /* TIOCGLTC */ ! 2154: ! 2155: x = stty(ttyfd,&ttold); /* restore tty modes the old way. */ ! 2156: ! 2157: #endif /* ATTSV */ ! 2158: #endif /* BSD44ORPOSIX */ ! 2159: ! 2160: debug(F101,"ttres tty modes restore","",x); ! 2161: if (x < 0) debug(F101,"ttres errno","",errno); ! 2162: ! 2163: #ifdef BSD41 ! 2164: if (ttld > -1) { /* Put back line discipline */ ! 2165: x = ioctl(ttyfd, TIOCSETD, &ttld); ! 2166: debug(F101,"ttres line discipline restore","",x); ! 2167: if (x < 0) debug(F101,"...ioctl errno","",errno); ! 2168: ttld = -1; ! 2169: } ! 2170: #endif /* BSD41 */ ! 2171: ! 2172: #ifdef sony_news ! 2173: x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */ ! 2174: if (x != -1) { /* Make sure we know original modes. */ ! 2175: if (ioctl(ttyfd,TIOCKSET, &x) < 0) { ! 2176: perror("ttres can't set Kanji mode"); ! 2177: debug(F101,"ttres error setting Kanji mode","",x); ! 2178: return(-1); ! 2179: } ! 2180: } ! 2181: debug(F100,"ttres set Kanji mode ok","",0); ! 2182: #endif /* sony_news */ ! 2183: ! 2184: tvtflg = 0; /* Invalidate terminal mode settings */ ! 2185: return(x); ! 2186: } ! 2187: ! 2188: /* T T R P I D -- Read pid from lockfile "name" (used by ttlock) */ ! 2189: ! 2190: int ! 2191: ttrpid(name) char *name; { ! 2192: int x, fd, pid; ! 2193: ! 2194: fd = open(name,O_RDONLY); /* Try to open lockfile. */ ! 2195: if (fd > 0) { ! 2196: ! 2197: #ifdef PIDSTRING ! 2198: char buf[12]; ! 2199: x = read(fd, buf, 11); /* For HDP UUCP, read pid string */ ! 2200: if (x < 0) return(-1); ! 2201: buf[11] = '\0'; ! 2202: if (x == 11) ! 2203: x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */ ! 2204: #else ! 2205: x = read(fd, (char *)&pid, sizeof(pid)); /* Else read integer pid */ ! 2206: #endif /* PIDSTRING */ ! 2207: ! 2208: if (x < 0) pid = -1; /* Return any errors. */ ! 2209: close(fd); /* Close the lockfile. */ ! 2210: } else pid = -1; ! 2211: return(pid); ! 2212: } ! 2213: ! 2214: /* T T L O C K */ ! 2215: ! 2216: /* ! 2217: This function attempts to coordinate use of the communication device with ! 2218: other copies of Kermit and any other program that follows the UUCP ! 2219: device-locking conventions, which, unfortunately, vary among different UNIX ! 2220: implementations. The idea is to look for a file of a certain name, the ! 2221: "lockfile", in a certain directory. If such a file is found, then the line ! 2222: is presumed to be in use, and Kermit should not use it. If no such file is ! 2223: found, Kermit attempts to create one so that other programs will not use the ! 2224: same line at the same time. Because the lockfile and/or the directory it's ! 2225: in might lack write permission for the person running Kermit, Kermit could ! 2226: find itself running setuid to uucp or other user that does have the ! 2227: necessary permissions. At startup, Kermit has changed its effective uid to ! 2228: the user's real uid, and so ttlock() must switch back to the original ! 2229: effective uid in order to create the lockfile, and then back again to the ! 2230: real uid to prevent unauthorized access to other directories or files owned ! 2231: by the user the program is setuid to. ! 2232: ! 2233: Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability, ! 2234: based on suggestions from Warren Tucker. Call with pointer to name of ! 2235: tty device. Returns: ! 2236: ! 2237: 0 on success ! 2238: -1 on failure ! 2239: ! 2240: Note: Once privileges are turned on using priv_on(), it is essential that ! 2241: they are turned off again before this function returns. ! 2242: */ ! 2243: #ifdef SVR4 /* Lockfile uses device numbers. */ ! 2244: #ifndef LFDEVNO /* Define this for SVR4 */ ! 2245: #ifndef AIXRS /* But not for RS/6000 AIX 3.2 */ ! 2246: #define LFDEVNO /* If anybody else needs it, */ ! 2247: #endif /* AIXRS */ ! 2248: #endif /* LFDEVNO */ /* define it here or on CC */ ! 2249: #endif /* SVR4 */ /* command line. */ ! 2250: ! 2251: #ifdef LFDEVNO ! 2252: #include <sys/stat.h> /* For major() & minor() macros. */ ! 2253: /* Should be in <sys/types.h>. */ ! 2254: #ifndef major /* If we didn't find it */ ! 2255: #ifdef SVR4 /* then for Sys V R4 */ ! 2256: #include <sys/mkdev.h> /* look here */ ! 2257: #else /* or for Sunos versions */ ! 2258: #ifdef SUNOS4 /* ... */ ! 2259: #include <sys/sysmacros.h> /* look here */ ! 2260: #else /* Otherwise take a chance: */ ! 2261: #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff)) ! 2262: #define minor(dev) ( (int) ( (dev) & 0xff)) ! 2263: #endif /* SUNOS4 */ ! 2264: #endif /* SVR4 */ ! 2265: #endif /* major */ ! 2266: #endif /* LFDEVNO */ ! 2267: /* ! 2268: Note for RS/6000: routines ttylock(devicename), ttyunlock(devicename), ! 2269: and ttylocked(devicename) from the standard library (libc.a) could be ! 2270: used here instead. It's not clear whether there is any advantage in this. ! 2271: */ ! 2272: static int ! 2273: ttlock(ttdev) char *ttdev; { ! 2274: int x; ! 2275: ! 2276: #ifdef MINIX ! 2277: char *buf; ! 2278: #endif /* MINIX */ ! 2279: ! 2280: #ifdef NOUUCP ! 2281: strcpy(flfnam,"NOLOCK"); ! 2282: haslock = 1; ! 2283: return(0); ! 2284: #else /* !NOUUCP */ ! 2285: int lockfd; /* File descriptor for lock file. */ ! 2286: PID_T pid; /* Process id of this process. */ ! 2287: int fpid; /* pid found in existing lockfile. */ ! 2288: int tries; /* How many times we've tried... */ ! 2289: #ifdef LFDEVNO ! 2290: struct stat devbuf; /* For device numbers (SVR4). */ ! 2291: #endif /* LFDEVNO */ ! 2292: ! 2293: #ifdef PIDSTRING ! 2294: char pid_str[12]; /* My pid in string format. */ ! 2295: #endif /* PIDSTRING */ ! 2296: ! 2297: char *device, *devname; ! 2298: ! 2299: #define LFNAML 50 /* Max length for lock file name. */ ! 2300: char lockfil[LFNAML]; /* Lock file name */ ! 2301: #ifdef RTAIX ! 2302: char lklockf[LFNAML]; /* Name for link to lock file */ ! 2303: #endif /* RTAIX */ ! 2304: char tmpnam[LFNAML+30]; /* Temporary lockfile name. */ ! 2305: char *lockdir = LOCK_DIR; /* Defined near top of this file, */ ! 2306: /* or on cc command line. */ ! 2307: ! 2308: haslock = 0; /* Not locked yet. */ ! 2309: *flfnam = '\0'; /* Lockfile name is empty. */ ! 2310: pid = getpid(); /* Get id of this process. */ ! 2311: ! 2312: /* Construct name of lockfile and temporary file */ ! 2313: ! 2314: /* device = name of tty device without the path, e.g. "ttyh8" */ ! 2315: /* lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */ ! 2316: ! 2317: device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev); ! 2318: ! 2319: #ifdef ISIII /* Interactive System III, PC/IX */ ! 2320: strcpy(lockfil, device); ! 2321: #else ! 2322: #ifdef LFDEVNO /* Lockfilename has device numbers. */ ! 2323: if (stat(ttdev,&devbuf) < 0) ! 2324: return(-1); ! 2325: sprintf(lockfil,"LK.%03d.%03d.%03d", ! 2326: major(devbuf.st_dev), /* inode */ ! 2327: major(devbuf.st_rdev), /* major device number */ ! 2328: minor(devbuf.st_rdev)); /* minor device number */ ! 2329: ! 2330: #else /* Others... */ ! 2331: #ifdef PTX /* Dynix PTX */ ! 2332: if (device != &ttdev[5] && strncmp(ttdev,"/dev/",5)==0) { ! 2333: sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device); ! 2334: } else ! 2335: #endif /* PTX */ ! 2336: sprintf(lockfil,"LCK..%s", device); ! 2337: #ifdef M_XENIX /* SCO Xenix */ ! 2338: { int x; char c; ! 2339: x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */ ! 2340: if (x > 0) { /* If it's uppercase, lower it. */ ! 2341: c = lockfil[x]; ! 2342: if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A'); ! 2343: } ! 2344: } ! 2345: #endif /* M_XENIX */ ! 2346: #ifdef RTAIX ! 2347: strcpy(lklockf,device); ! 2348: #endif /* RTAIX */ ! 2349: #endif /* LFDEVNO */ ! 2350: #endif /* ISIII */ ! 2351: ! 2352: /* flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */ ! 2353: /* tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */ ! 2354: ! 2355: sprintf(flfnam,"%s/%s",lockdir,lockfil); ! 2356: #ifdef RTAIX ! 2357: sprintf(lkflfn,"%s/%s",lockdir,lklockf); ! 2358: #endif /* RTAIX */ ! 2359: sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); ! 2360: debug(F110,"ttlock flfnam",flfnam,0); ! 2361: debug(F110,"ttlock tmpnam",tmpnam,0); ! 2362: ! 2363: priv_on(); /* Turn on privileges if possible. */ ! 2364: lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */ ! 2365: if (lockfd < 0) { /* Create failed. */ ! 2366: debug(F111,"ttlock creat failed",tmpnam,errno); ! 2367: if (errno == ENOENT) { ! 2368: perror(lockdir); ! 2369: printf("UUCP not installed or Kermit misconfigured\n"); ! 2370: } else { ! 2371: perror(lockdir); ! 2372: unlink(tmpnam); /* Get rid of the temporary file. */ ! 2373: } ! 2374: priv_off(); /* Turn off privileges!!! */ ! 2375: return(-1); /* Return failure code. */ ! 2376: } ! 2377: /* Now write the pid into the temp lockfile in the appropriate format */ ! 2378: ! 2379: #ifdef PIDSTRING /* For Honey DanBer UUCP, */ ! 2380: sprintf(pid_str,"%10d\n", (int) pid); /* Write pid as decimal string. */ ! 2381: write(lockfd, pid_str, 11); ! 2382: debug(F111,"ttlock hdb pid string",pid_str,(int) pid); ! 2383: #else /* Others use integer pid */ ! 2384: write(lockfd, (char *)&pid, sizeof(pid) ); ! 2385: debug(F111,"ttlock pid","",(int) pid); ! 2386: #endif /* PIDSTRING */ ! 2387: ! 2388: /* Now try to rename the temp file to the real lock file name. */ ! 2389: /* This will fail if a lock file of that name already exists. */ ! 2390: ! 2391: close(lockfd); /* Close the temp lockfile. */ ! 2392: chmod(tmpnam,0444); /* Permission for a valid lock. */ ! 2393: tries = 0; ! 2394: while (!haslock && tries++ < 2) { ! 2395: haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */ ! 2396: if (haslock) { /* If we got the lockfile */ ! 2397: #ifdef RTAIX ! 2398: link(flfnam,lkflfn); ! 2399: #endif /* RTAIX */ ! 2400: #ifdef LOCKF ! 2401: /* ! 2402: Advisory file locking works on SVR4, so we use it. In fact, it is ! 2403: necessary in some cases, e.g. when SLIP is involved. ! 2404: */ ! 2405: while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) { ! 2406: debug(F111, "ttlock: lockf returns errno", "", errno); ! 2407: if ( (++tries >= 3) || (errno != EAGAIN) ) { ! 2408: x = unlink(flfnam); /* remove the lockfile */ ! 2409: debug(F111,"ttlock unlink",flfnam,x); ! 2410: haslock = 0; ! 2411: break; ! 2412: } ! 2413: sleep(2); ! 2414: } ! 2415: if (haslock) /* If we got an advisory lock */ ! 2416: #endif /* LOCKF */ ! 2417: break; /* We're done. */ ! 2418: ! 2419: } else { /* We didn't create a new lockfile. */ ! 2420: if ((fpid = ttrpid(flfnam)) > -1) { /* Read pid from old one. */ ! 2421: if (fpid > 0) { ! 2422: debug(F101,"ttlock fpid","",fpid); ! 2423: errno = 0; /* See if process still exists. */ ! 2424: x = kill((PID_T) fpid,0); ! 2425: debug(F101,"ttlock kill","",x); ! 2426: debug(F101,"ttlock kill errno","",errno); ! 2427: if (x < 0 && errno == ESRCH) { /* pid is invalid */ ! 2428: debug(F111,"ttlock removing stale lock",flfnam, ! 2429: fpid); ! 2430: if (!backgrd) ! 2431: printf( ! 2432: "Removing stale lock %s (pid %d terminated)\n", ! 2433: flfnam,fpid); ! 2434: x = unlink(flfnam); /* remove the lockfile. */ ! 2435: debug(F111,"ttlock unlink",flfnam,x); ! 2436: continue; /* and go back and try again. */ ! 2437: } else if ((x < 0 && errno == EPERM) || x == 0) { ! 2438: unlink(tmpnam); /* Delete the tempfile */ ! 2439: debug(F101,"ttlock found tty locked","",fpid); ! 2440: priv_off(); /* Turn off privs */ ! 2441: return(-2); /* Code for device is in use. */ ! 2442: } ! 2443: } else { ! 2444: debug(F101,"ttlock can't get fpid","",fpid); ! 2445: break; ! 2446: } ! 2447: } else break; /* Couldn't read pid from old file */ ! 2448: } ! 2449: } ! 2450: unlink(tmpnam); /* Unlink (remove) the temp file. */ ! 2451: priv_off(); /* Turn off privs */ ! 2452: return(haslock ? 0 : -1); /* Return link's return code. */ ! 2453: #endif /* !NOUUCP */ ! 2454: } ! 2455: ! 2456: /* T T U N L O C K */ ! 2457: ! 2458: static int ! 2459: ttunlck() { /* Remove UUCP lockfile. */ ! 2460: #ifndef NOUUCP ! 2461: if (haslock && *flfnam) { ! 2462: priv_on(); /* Turn privileges on. */ ! 2463: unlink(flfnam); /* Remove the lockfile. */ ! 2464: #ifdef RTAIX ! 2465: unlink(lkflfn); /* Remove other lockfile */ ! 2466: #endif /* RTAIX */ ! 2467: #ifdef LOCKF ! 2468: (void) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */ ! 2469: #endif /* LOCKF */ ! 2470: *flfnam = '\0'; /* Erase the name. */ ! 2471: priv_off(); /* Turn privileges off. */ ! 2472: } ! 2473: #endif /* !NOUUCP */ ! 2474: return(0); ! 2475: } ! 2476: ! 2477: /* 4.3BSD-style UUCP line direction control (Stan Barber, Rice U) */ ! 2478: ! 2479: #ifdef ACUCNTRL ! 2480: VOID ! 2481: acucntrl(flag,ttname) char *flag, *ttname; { ! 2482: char x[DEVNAMLEN+32], *device, *devname; ! 2483: ! 2484: if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */ ! 2485: return; /* just return. */ ! 2486: device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname); ! 2487: if (strncmp(device,"LCK..",4) == 0) device += 5; ! 2488: sprintf(x,"/usr/lib/uucp/acucntrl %s %s",flag,device); ! 2489: debug(F110,"called ",x,0); ! 2490: zsyscmd(x); ! 2491: } ! 2492: #endif /* ACUCNTRL */ ! 2493: ! 2494: /* ! 2495: T T H F L O W -- Set hardware flow control. ! 2496: */ ! 2497: static int ! 2498: tthflow(flow) int flow; { ! 2499: int x = 0; /* Return code */ ! 2500: ! 2501: /* There is no hardware flow control in POSIX. */ ! 2502: ! 2503: /* ! 2504: For SunOS 4.0 and later in the BSD environment ... ! 2505: ! 2506: The declarations are copied and interpreted from the System V header files, ! 2507: so we don't actually have to pull in all the System V junk when building ! 2508: C-Kermit for SunOS in the BSD environment, which would be dangerous because ! 2509: having those symbols defined would cause us to take the wrong paths through ! 2510: the code. The code in this section is used in both the BSD and Sys V SunOS ! 2511: versions. ! 2512: */ ! 2513: #ifdef SUNOS41 ! 2514: /* ! 2515: In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls ! 2516: because GNU CC uses different formats for the _IOxxx macros than regular CC; ! 2517: the POSIX forms work for both. But the POSIX calls are not available in ! 2518: SunOS 4.0. ! 2519: */ ! 2520: #define CRTSCTS 0x80000000 /* RTS/CTS flow control */ ! 2521: #define TCSANOW 0 /* Do it now */ ! 2522: ! 2523: struct termios { ! 2524: unsigned long c_iflag; /* Input modes */ ! 2525: unsigned long c_oflag; /* Output modes */ ! 2526: unsigned long c_cflag; /* Control modes */ ! 2527: unsigned long c_lflag; /* Line discipline modes */ ! 2528: char c_line; ! 2529: CHAR c_cc[17]; ! 2530: }; ! 2531: struct termios temp; ! 2532: ! 2533: _PROTOTYP( int tcgetattr, (int, struct termios *) ); ! 2534: _PROTOTYP( int tcsetattr, (int, int, struct termios *) ); ! 2535: ! 2536: /* ! 2537: When CRTSCTS is set, SunOS won't do output unless both CTS and CD are ! 2538: asserted. So we don't set CRTSCTS unless CD is up. This should be OK, ! 2539: since we don't need RTS/CTS during dialing, and after dialing is complete, ! 2540: we should have CD. If not, we still communicate, but without RTS/CTS. ! 2541: */ ! 2542: int mflags; /* Modem signal flags */ ! 2543: if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */ ! 2544: (mflags & TIOCM_CAR)) { /* Check for CD */ ! 2545: debug(F100,"tthflow SunOS has CD","",0); ! 2546: if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */ ! 2547: !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */ ! 2548: temp.c_cflag |= CRTSCTS; /* Not there, add it */ ! 2549: x = tcsetattr(ttyfd,TCSANOW,&temp); ! 2550: } ! 2551: } else debug(F100,"tthflow SunOS no CD","",0); ! 2552: #else ! 2553: #ifdef SUNOS4 ! 2554: /* ! 2555: SunOS 4.0 (and maybe earlier?). This code is dangerous because it ! 2556: prevents compilation with GNU gcc, which uses different formats for the ! 2557: _IORxxx macros than regular cc. SunOS 4.1 and later can use the POSIX ! 2558: routines in the #else part of this clause, which work for both cc and gcc. ! 2559: */ ! 2560: #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */ ! 2561: #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */ ! 2562: #define CRTSCTS 0x80000000 /* RTS/CTS flow control */ ! 2563: ! 2564: struct termios { ! 2565: unsigned long c_iflag; /* Input modes */ ! 2566: unsigned long c_oflag; /* Output modes */ ! 2567: unsigned long c_cflag; /* Control modes */ ! 2568: unsigned long c_lflag; /* Line discipline modes */ ! 2569: char c_line; ! 2570: CHAR c_cc[17]; ! 2571: }; ! 2572: struct termios temp; ! 2573: ! 2574: if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get current terminal modes. */ ! 2575: temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */ ! 2576: x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */ ! 2577: } ! 2578: #else /* Not SunOS 4.0 or later */ ! 2579: #ifdef ATTSV ! 2580: if (flow == FLO_RTSC) { ! 2581: /* RTS/CTS Flow control... */ ! 2582: #ifdef RTSXOFF ! 2583: /* This is the preferred way, according to SVID R4 */ ! 2584: if (ioctl(ttyfd,TCGETX,&rctsx) > -1) { ! 2585: rctsx.x_hflag |= RTSXOFF | CTSXON; ! 2586: x = ioctl(ttyfd,TCSETX,&rctsx); ! 2587: } ! 2588: #endif /* RTSXOFF */ ! 2589: } ! 2590: if (flow == FLO_DTRC) { ! 2591: /* DTR/CD Flow control... */ ! 2592: #ifdef DTRXOFF ! 2593: /* This is straight out of SVID R4 */ ! 2594: if (ioctl(ttyfd,TCGETX,&rctsx) > -1) { ! 2595: rctsx.x_hflag |= DTRXOFF | CDXON; ! 2596: x = ioctl(ttyfd,TCSETX,&rctsx); ! 2597: } ! 2598: #endif /* DTRXOFF */ ! 2599: } ! 2600: #else /* not System V */ ! 2601: #ifdef CK_DTRCTS ! 2602: x = LDODTR | LDOCTS; /* Found only on UTEK? */ ! 2603: if (flow == FLO_DTRT) { /* Use hardware flow control */ ! 2604: if (lmodef) { ! 2605: x = ioctl(ttyfd,TIOCLBIS,&x); ! 2606: if (x < 0) { ! 2607: debug(F100,"hardflow TIOCLBIS error","",0); ! 2608: } else { ! 2609: lmodef++; ! 2610: debug(F100,"hardflow TIOCLBIS ok","",0); ! 2611: } ! 2612: } ! 2613: } else { ! 2614: if (lmodef) { ! 2615: x = ioctl(ttyfd,TIOCLBIC,&x); ! 2616: if (x < 0) { ! 2617: debug(F100,"hardflow TIOCLBIC error","",0); ! 2618: } else { ! 2619: lmodef++; ! 2620: debug(F100,"hardflow TIOCLBIC ok","",0); ! 2621: } ! 2622: } ! 2623: } ! 2624: #endif /* CK_DTRCTS */ ! 2625: #endif /* ATTSV */ ! 2626: #endif /* SUNOS4 */ ! 2627: #endif /* SUNOS41 */ ! 2628: return(x); ! 2629: } ! 2630: ! 2631: /* T T P K T -- Condition the communication line for packets */ ! 2632: /* or for modem dialing */ ! 2633: ! 2634: /* ! 2635: If called with speed > -1, also set the speed. ! 2636: Returns 0 on success, -1 on failure. ! 2637: ! 2638: NOTE: the "xflow" parameter is supposed to be the currently selected ! 2639: type of flow control, but for historical reasons, this parameter is also ! 2640: used to indicate that we are dialing. Therefore, when the true flow ! 2641: control setting is needed, we access the external variable "flow", rather ! 2642: than trusting our "xflow" argument. ! 2643: */ ! 2644: int ! 2645: #ifdef CK_ANSIC ! 2646: ttpkt(long speed, int xflow, int parity) ! 2647: #else ! 2648: ttpkt(speed,xflow,parity) long speed; int xflow, parity; ! 2649: #endif /* CK_ANSIC */ ! 2650: /* ttpkt */ { ! 2651: int s2; ! 2652: int s = -1; ! 2653: #ifndef SVORPOSIX ! 2654: int x; ! 2655: #endif /* SVORPOSIX */ ! 2656: extern int flow; /* REAL flow-control setting */ ! 2657: ! 2658: if (ttyfd < 0) return(-1); /* Not open. */ ! 2659: ! 2660: debug(F101,"ttpkt parity","",parity); ! 2661: debug(F101,"ttpkt xflow","",xflow); ! 2662: debug(F101,"ttpkt speed","",(int) speed); ! 2663: ! 2664: ttprty = parity; /* Let other tt functions see these. */ ! 2665: ttpflg = 0; /* Parity not sensed yet */ ! 2666: ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */ ! 2667: ttspeed = speed; /* Make global copy for this module */ ! 2668: ! 2669: #ifdef NETCONN /* Nothing to do for telnet */ ! 2670: if (netconn) return (0); ! 2671: #endif /* NETCONN */ ! 2672: ! 2673: if (ttfdflg && !isatty(ttyfd)) return(0); ! 2674: ! 2675: #ifndef SVORPOSIX /* Berkeley, V7, etc. */ ! 2676: #ifdef LPASS8 ! 2677: /* ! 2678: For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF ! 2679: after having previously set it to NONE without closing and reopening the ! 2680: device. Unless there's something I overlooked below... ! 2681: */ ! 2682: if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) { ! 2683: debug(F101,"ttpkt executing horrible flow kludge","",0); ! 2684: ttclos(0); /* Close it */ ! 2685: x = 0; ! 2686: ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */ ! 2687: } ! 2688: #endif /* LPASS8 */ ! 2689: #endif /* SVORPOSIX */ ! 2690: ! 2691: if (xflow != FLO_DIAL && xflow != FLO_DIAX) ! 2692: ttflow = xflow; /* Now make this available too. */ ! 2693: ! 2694: if (xlocal) { ! 2695: s2 = (int) (speed / 10L); /* Convert bps to cps */ ! 2696: s = ttsspd(s2); /* Check and set the speed */ ! 2697: debug(F101,"ttpkt carrier","",xflow); ! 2698: carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */ ! 2699: && (ttcarr == CAR_ON)); ! 2700: tvtflg = 0; /* So ttvt() will work next time */ ! 2701: } ! 2702: ! 2703: #ifndef SVORPOSIX /* BSD section */ ! 2704: if (flow == FLO_RTSC || /* Hardware flow control */ ! 2705: flow == FLO_DTRC || ! 2706: flow == FLO_DTRT) { ! 2707: tthflow(flow); ! 2708: debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0); ! 2709: ttraw.sg_flags &= ~TANDEM; /* Don't ask for it. */ ! 2710: ttraw.sg_flags |= RAW; ! 2711: } else if (flow == FLO_NONE) { /* No Xon/Xoff flow control */ ! 2712: debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0); ! 2713: ttraw.sg_flags &= ~TANDEM; /* Don't ask for it. */ ! 2714: ttraw.sg_flags |= RAW; ! 2715: /* NOTE: We should also turn off hardware flow control here! */ ! 2716: } else if (flow == FLO_KEEP) { /* Keep device's original setting */ ! 2717: debug(F100,"ttpkt keeping original TANDEM","",0); ! 2718: ttraw.sg_flags &= ~TANDEM; ! 2719: ttraw.sg_flags |= (ttold.sg_flags & TANDEM); ! 2720: /* NOTE: We should also handle hardware flow control here! */ ! 2721: } ! 2722: ! 2723: /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */ ! 2724: ! 2725: if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) { ! 2726: debug(F100,"ttpkt turning on TANDEM","",0); ! 2727: ttraw.sg_flags |= TANDEM; /* So ask for it. */ ! 2728: ! 2729: #ifdef LPASS8 /* Can pass 8-bit data through? */ ! 2730: /* If the LPASS8 local mode is available, then flow control can always */ ! 2731: /* be used, even if parity is none and we are transferring 8-bit data. */ ! 2732: /* But we only need to do all this if Xon/Xoff is requested. */ ! 2733: /* BUT... this tends not to work through IP or LAT connections, terminal */ ! 2734: /* servers, telnet, rlogin, etc, so it is currently disabled. */ ! 2735: x = LPASS8; /* If LPASS8 defined, then */ ! 2736: debug(F100,"ttpkt executing LPASS8 code","",0); ! 2737: if (lmodef) { /* TIOCLBIS must be too. */ ! 2738: x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */ ! 2739: if (x < 0) { ! 2740: debug(F100,"ttpkt TIOCLBIS error","",0); ! 2741: } else { ! 2742: lmodef++; ! 2743: debug(F100,"ttpkt TIOCLBIS ok","",0); ! 2744: } ! 2745: } ! 2746: /* ! 2747: But if we use LPASS8 mode, we must explicitly turn off ! 2748: terminal interrupts of all kinds. ! 2749: */ ! 2750: #ifdef TIOCGETC /* Not rawmode, */ ! 2751: if (tcharf && (xlocal == 0)) { /* must turn off */ ! 2752: tchnoi.t_intrc = -1; /* interrupt character */ ! 2753: tchnoi.t_quitc = -1; /* and quit character. */ ! 2754: tchnoi.t_startc = 17; /* Make sure xon */ ! 2755: tchnoi.t_stopc = 19; /* and xoff not ignored. */ ! 2756: #ifndef NOBRKC ! 2757: tchnoi.t_eofc = -1; /* eof character. */ ! 2758: tchnoi.t_brkc = -1; /* brk character. */ ! 2759: #endif /* NOBRKC */ ! 2760: if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) { ! 2761: debug(F100,"ttpkt TIOCSETC failed","",0); ! 2762: } else { ! 2763: tcharf = 1; ! 2764: debug(F100,"ttpkt TIOCSETC ok","",0); ! 2765: } ! 2766: #ifdef COMMENT ! 2767: /* only for paranoid debugging */ ! 2768: if (tcharf) { ! 2769: struct tchars foo; ! 2770: char tchbuf[100]; ! 2771: ioctl(0,TIOCGETC,&foo); ! 2772: sprintf(tchbuf, ! 2773: "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d", ! 2774: foo.t_intrc, foo.t_quitc, foo.t_startc, ! 2775: foo.t_stopc, foo.t_eofc, foo.t_brkc); ! 2776: debug(F110,"ttpkt chars",tchbuf,0); ! 2777: } ! 2778: #endif /* COMMENT */ ! 2779: } ! 2780: ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */ ! 2781: #endif /* TIOCGETC */ ! 2782: ! 2783: /* Prevent suspend during packet mode */ ! 2784: #ifdef TIOCGLTC /* Not rawmode, */ ! 2785: if (ltcharf && (xlocal == 0)) { /* must turn off */ ! 2786: ltchnoi.t_suspc = -1; /* suspend character */ ! 2787: ltchnoi.t_dsuspc = -1; /* and delayed suspend character */ ! 2788: if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) { ! 2789: debug(F100,"ttpkt TIOCSLTC failed","",0); ! 2790: } else { ! 2791: ltcharf = 1; ! 2792: debug(F100,"ttpkt TIOCSLTC ok","",0); ! 2793: } ! 2794: } ! 2795: #endif /* TIOCGLTC */ ! 2796: ! 2797: #else /* LPASS8 not defined */ ! 2798: ! 2799: /* Previously, BSD-based implementations always */ ! 2800: /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */ ! 2801: /* This allows the flow control requested above to actually work, but only */ ! 2802: /* if the user asks for parity (which also means they get 8th-bit quoting). */ ! 2803: ! 2804: if (parity) { /* If parity, */ ! 2805: ttraw.sg_flags &= ~RAW; /* use cooked mode */ ! 2806: #ifdef COMMENT ! 2807: /* WHY??? */ ! 2808: if (xlocal) ! 2809: #endif /* COMMENT */ ! 2810: ttraw.sg_flags |= CBREAK; ! 2811: debug(F101,"ttpkt cooked, cbreak, parity","",parity); ! 2812: #ifdef TIOCGETC /* Not rawmode, */ ! 2813: if (tcharf && (xlocal == 0)) { /* must turn off */ ! 2814: tchnoi.t_intrc = -1; /* interrupt character */ ! 2815: tchnoi.t_quitc = -1; /* and quit character. */ ! 2816: tchnoi.t_startc = 17; /* Make sure xon */ ! 2817: tchnoi.t_stopc = 19; /* and xoff not ignored. */ ! 2818: #ifndef NOBRKC ! 2819: tchnoi.t_eofc = -1; /* eof character. */ ! 2820: tchnoi.t_brkc = -1; /* brk character. */ ! 2821: #endif /* NOBRKC */ ! 2822: if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) { ! 2823: debug(F100,"ttpkt TIOCSETC failed","",0); ! 2824: } else { ! 2825: tcharf = 1; ! 2826: debug(F100,"ttpkt TIOCSETC ok","",0); ! 2827: } ! 2828: } ! 2829: #endif /* TIOCGETC */ ! 2830: #ifdef TIOCGLTC /* Not rawmode, */ ! 2831: /* Prevent suspend during packet mode */ ! 2832: if (ltcharf && (xlocal == 0)) { /* must turn off */ ! 2833: ltchnoi.t_suspc = -1; /* suspend character */ ! 2834: ltchnoi.t_dsuspc = -1; /* and delayed suspend character */ ! 2835: if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) { ! 2836: debug(F100,"ttpkt TIOCSLTC failed","",0); ! 2837: } else { ! 2838: ltcharf = 1; ! 2839: debug(F100,"ttpkt TIOCSLTC ok","",0); ! 2840: } ! 2841: } ! 2842: #endif /* TIOCGLTC */ ! 2843: } else { /* If no parity, */ ! 2844: ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */ ! 2845: debug(F101,"ttpkt setting rawmode, parity","",parity); ! 2846: } ! 2847: #endif /* LPASS8 */ ! 2848: } /* End of Xon/Xoff section */ ! 2849: ! 2850: /* Don't echo, don't map CR to CRLF on output, don't fool with case */ ! 2851: #ifdef LCASE ! 2852: ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE); ! 2853: #else ! 2854: ttraw.sg_flags &= ~(ECHO|CRMOD); ! 2855: #endif /* LCASE */ ! 2856: ! 2857: #ifdef TOWER1 ! 2858: ttraw.sg_flags &= ~ANYP; /* Must set this on old Towers */ ! 2859: #endif /* TOWER1 */ ! 2860: ! 2861: if (stty(ttyfd,&ttraw) < 0) return(-1); /* Set the new modes. */ ! 2862: debug(F100,"ttpkt stty ok","",0); ! 2863: ! 2864: #ifdef sony_news ! 2865: x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */ ! 2866: if (x != -1) { /* Make sure we know original modes. */ ! 2867: x &= ~KM_TTYPE; ! 2868: x |= KM_ASCII; ! 2869: if (ioctl(ttyfd,TIOCKSET, &x) < 0) { ! 2870: perror("ttpkt can't set ASCII mode"); ! 2871: debug(F101,"ttpkt error setting ASCII mode","",x); ! 2872: return(-1); ! 2873: } ! 2874: } ! 2875: debug(F100,"ttpkt set ASCII mode ok","",0); ! 2876: #endif /* sony_news */ ! 2877: ! 2878: if (xlocal == 0) /* Turn this off so we can read */ ! 2879: signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */ ! 2880: ! 2881: tvtflg = 0; /* So ttvt() will work next time */ ! 2882: return(0); ! 2883: ! 2884: #endif /* Not ATTSV or POSIX */ ! 2885: ! 2886: /* AT&T UNIX and POSIX */ ! 2887: ! 2888: #ifdef SVORPOSIX ! 2889: if (flow == FLO_XONX) /* Xon/Xoff */ ! 2890: ttraw.c_iflag |= (IXON|IXOFF); ! 2891: else if (flow == FLO_NONE) /* None */ ! 2892: /* NOTE: We should also turn off hardware flow control here! */ ! 2893: ttraw.c_iflag &= ~(IXON|IXOFF); ! 2894: else if (flow == FLO_KEEP) { /* Keep */ ! 2895: ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */ ! 2896: ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */ ! 2897: /* NOTE: We should also handle hardware flow control here! */ ! 2898: } else if (flow == FLO_RTSC || /* Hardware */ ! 2899: flow == FLO_DTRC || ! 2900: flow == FLO_DTRT) ! 2901: tthflow(flow); ! 2902: ! 2903: ttraw.c_lflag &= ~(ICANON|ECHO); ! 2904: ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */ ! 2905: ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */ ! 2906: ttraw.c_lflag |= NOFLSH; /* Don't flush */ ! 2907: ttraw.c_iflag |= (BRKINT|IGNPAR); ! 2908: #ifdef ATTSV ! 2909: #ifdef BSD44 ! 2910: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY); ! 2911: #else ! 2912: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY); ! 2913: #endif /* BSD44 */ ! 2914: #else /* POSIX */ ! 2915: ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP); ! 2916: #endif /* ATTSV */ ! 2917: ttraw.c_oflag &= ~OPOST; ! 2918: ttraw.c_cflag &= ~(CSIZE|PARENB); ! 2919: ttraw.c_cflag |= (CS8|CREAD|HUPCL); ! 2920: #ifdef IX370 ! 2921: ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */ ! 2922: ttraw.c_cc[5] = 1; ! 2923: #else ! 2924: #ifndef VEOF /* for DGUX this is VEOF, not VMIN */ ! 2925: ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */ ! 2926: #else ! 2927: #ifdef VMIN ! 2928: ttraw.c_cc[VMIN] = 1; ! 2929: #endif /* VMIN */ ! 2930: #endif /* VEOF */ ! 2931: #ifndef VEOL /* for DGUX this is VEOL, not VTIME */ ! 2932: ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */ ! 2933: #else ! 2934: #ifdef VTIME ! 2935: ttraw.c_cc[VTIME] = 0; ! 2936: #endif /* VTIME */ ! 2937: #endif /* VEOL */ ! 2938: #endif /* IX370 */ ! 2939: ! 2940: #ifdef VINTR /* Turn off interrupt character */ ! 2941: if (xlocal == 0) /* so ^C^C can break us out of */ ! 2942: ttraw.c_cc[VINTR] = 0; /* packet mode. */ ! 2943: #endif /* VINTR */ ! 2944: ! 2945: #ifdef BSD44ORPOSIX ! 2946: if (xlocal && (s > 0)) { ! 2947: cfsetispeed(&ttraw,s); ! 2948: cfsetospeed(&ttraw,s); ! 2949: } ! 2950: if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0) return(-1); ! 2951: #else /* ATTSV */ ! 2952: if (xlocal && (s > 0)) { /* set speed */ ! 2953: ttraw.c_cflag &= ~CBAUD; ! 2954: ttraw.c_cflag |= s; ! 2955: } ! 2956: if (ioctl(ttyfd,TCSETAW,&ttraw) < 0) return(-1); /* set new modes . */ ! 2957: #endif /* BSD44ORPOSIX */ ! 2958: tvtflg = 0; ! 2959: return(0); ! 2960: #endif /* ATTSV */ ! 2961: } ! 2962: ! 2963: /* T T V T -- Condition communication line for use as virtual terminal */ ! 2964: ! 2965: int ! 2966: #ifdef CK_ANSIC ! 2967: ttvt(long speed, int flow) ! 2968: #else ! 2969: ttvt(speed,flow) long speed; int flow; ! 2970: #endif /* CK_ANSIC */ ! 2971: /* ttvt */ { ! 2972: int s, s2; ! 2973: ! 2974: debug(F101,"ttvt ttyfd","",ttyfd); ! 2975: debug(F101,"ttvt tvtflg","",tvtflg); ! 2976: debug(F101,"ttvt speed","",speed); ! 2977: if (ttyfd < 0) return(-1); /* Not open. */ ! 2978: #ifdef NETCONN ! 2979: if (netconn) { ! 2980: tvtflg = 1; /* Network connections */ ! 2981: return(0); /* require no special setup */ ! 2982: } ! 2983: #endif /* NETCONN */ ! 2984: ! 2985: if (tvtflg != 0 && speed == ttspeed && flow == ttflow && ttcarr == curcarr) ! 2986: return(0); /* Already been called. */ ! 2987: ! 2988: if (ttfdflg && !isatty(ttyfd)) return(0); ! 2989: ! 2990: if (xlocal) { /* For external lines... */ ! 2991: s2 = (int) (speed / 10L); ! 2992: s = ttsspd(s2); /* Check/set the speed */ ! 2993: carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */ ! 2994: && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0))); ! 2995: } else s = s2 = -1; ! 2996: ! 2997: #ifndef SVORPOSIX ! 2998: /* Berkeley, V7, etc */ ! 2999: if (flow == FLO_RTSC || /* Hardware flow control */ ! 3000: flow == FLO_DTRC || ! 3001: flow == FLO_DTRT) ! 3002: tthflow(flow); ! 3003: if (flow == FLO_XONX) { /* No Xon/Xoff flow control */ ! 3004: tttvt.sg_flags |= TANDEM; /* Ask for it. */ ! 3005: } else if (flow == FLO_KEEP) { ! 3006: tttvt.sg_flags &= ~TANDEM; ! 3007: tttvt.sg_flags |= (ttold.sg_flags & TANDEM); ! 3008: /* NOTE: We should also handle hardware flow control here! */ ! 3009: } else if (flow == FLO_NONE) { ! 3010: tttvt.sg_flags &= ~TANDEM; /* Don't ask for it. */ ! 3011: /* NOTE: We should also turn off hardware flow control here! */ ! 3012: } ! 3013: tttvt.sg_flags |= RAW; /* Raw mode in all cases */ ! 3014: #ifdef TOWER1 ! 3015: tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */ ! 3016: #else ! 3017: tttvt.sg_flags &= ~ECHO; /* No echo */ ! 3018: #endif /* TOWER1 */ ! 3019: ! 3020: if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */ ! 3021: return(-1); ! 3022: ! 3023: #else /* It is ATTSV or POSIX */ ! 3024: ! 3025: if (flow == FLO_RTSC || /* Hardware flow control */ ! 3026: flow == FLO_DTRC || ! 3027: flow == FLO_DTRT) ! 3028: tthflow(flow); ! 3029: else if (flow == FLO_XONX) /* Software flow control */ ! 3030: tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */ ! 3031: else if (flow == FLO_KEEP) { ! 3032: tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */ ! 3033: tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */ ! 3034: /* NOTE: We should also handle hardware flow control here! */ ! 3035: } else if (flow == FLO_NONE) /* Off if NONE or hardware */ ! 3036: tttvt.c_iflag &= ~(IXON|IXOFF); /* requested. */ ! 3037: ! 3038: tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN); ! 3039: tttvt.c_iflag |= (IGNBRK|IGNPAR); ! 3040: #ifdef ATTSV ! 3041: #ifdef BSD44 ! 3042: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|BRKINT|INPCK|ISTRIP|IXANY); ! 3043: #else ! 3044: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|BRKINT|INPCK|ISTRIP|IXANY); ! 3045: #endif /* BSD44 */ ! 3046: #else /* POSIX */ ! 3047: tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|BRKINT|INPCK|ISTRIP); ! 3048: #endif /* ATTSV */ ! 3049: tttvt.c_oflag &= ~OPOST; ! 3050: tttvt.c_cflag &= ~(CSIZE|PARENB); ! 3051: tttvt.c_cflag |= (CS8|CREAD|HUPCL); ! 3052: #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */ ! 3053: tttvt.c_cc[4] = 1; ! 3054: #else ! 3055: #ifdef VMIN ! 3056: tttvt.c_cc[VMIN] = 1; ! 3057: #endif /* VMIN */ ! 3058: #endif /* VEOF */ ! 3059: #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */ ! 3060: tttvt.c_cc[5] = 0; ! 3061: #else ! 3062: #ifdef VTIME ! 3063: tttvt.c_cc[VTIME] = 0; ! 3064: #endif /* VTIME */ ! 3065: #endif /* VEOL */ ! 3066: ! 3067: #ifdef BSD44ORPOSIX ! 3068: if (xlocal && (s > 0)) { ! 3069: cfsetispeed(&tttvt,s); ! 3070: cfsetospeed(&tttvt,s); ! 3071: } ! 3072: if (tcsetattr(ttyfd,TCSADRAIN,&tttvt) < 0) return(-1); ! 3073: #else /* ATTSV */ ! 3074: if (s > 0) { /* Set speed */ ! 3075: tttvt.c_cflag &= ~CBAUD; ! 3076: tttvt.c_cflag |= s; ! 3077: } ! 3078: if (ioctl(ttyfd,TCSETAW,&tttvt) < 0) return(-1); /* set new modes . */ ! 3079: #endif /* BSD44ORPOSIX */ ! 3080: #endif /* ATTSV */ ! 3081: ! 3082: ttspeed = speed; /* Done, remember how we were */ ! 3083: ttflow = flow; /* called, so we can decide how to */ ! 3084: tvtflg = 1; /* respond next time. */ ! 3085: ! 3086: debug(F101,"ttvt done","",tvtflg); ! 3087: return(0); ! 3088: } ! 3089: ! 3090: /* T T S S P D -- Checks and sets transmission rate. */ ! 3091: ! 3092: /* Call with speed in characters (not bits!) per second. */ ! 3093: /* Returns internal speed code if successful, -1 otherwise. */ ! 3094: ! 3095: int ! 3096: ttsspd(cps) int cps; { ! 3097: int s, s2; ! 3098: ! 3099: debug(F101,"ttsspd","",cps); ! 3100: ! 3101: #ifdef NETCONN ! 3102: if (netconn) return (0); ! 3103: #endif /* NETCONN */ ! 3104: ! 3105: if (cps < 0) return(-1); ! 3106: s = s2 = -1; ! 3107: ! 3108: /* First check that the given speed is valid. */ ! 3109: ! 3110: switch (cps) { ! 3111: #ifndef MINIX ! 3112: case 0: s = B0; break; ! 3113: case 5: s = B50; break; ! 3114: case 7: s = B75; break; ! 3115: #endif ! 3116: case 11: s = B110; break; ! 3117: #ifndef MINIX ! 3118: case 15: s = B150; break; ! 3119: case 20: s = B200; break; ! 3120: #endif ! 3121: case 30: s = B300; break; ! 3122: #ifndef MINIX ! 3123: case 60: s = B600; break; ! 3124: #endif ! 3125: case 120: s = B1200; break; ! 3126: #ifndef MINIX ! 3127: case 180: s = B1800; break; ! 3128: #endif ! 3129: case 240: s = B2400; break; ! 3130: case 480: s = B4800; break; ! 3131: #ifndef MINIX ! 3132: case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */ ! 3133: #endif ! 3134: case 960: s = B9600; break; ! 3135: #ifdef B19200 ! 3136: case 1920: s = B19200; break; ! 3137: #else ! 3138: #ifdef EXTA ! 3139: case 1920: s = EXTA; break; ! 3140: #endif ! 3141: #endif ! 3142: #ifdef B38400 ! 3143: case 3840: s = B38400; break; ! 3144: #else ! 3145: #ifdef EXTB ! 3146: case 3840: s = EXTB; break; ! 3147: #endif ! 3148: #endif ! 3149: default: ! 3150: return(-1); ! 3151: } ! 3152: /* Actually set the speed */ ! 3153: ! 3154: if (ttyfd > -1 && s > -1 && xlocal != 0) { ! 3155: if (s2 == -1) s2 = s; ! 3156: ! 3157: #ifdef BSD44ORPOSIX ! 3158: if (tcgetattr(ttyfd,&ttcur) < 0) return(-1); ! 3159: cfsetospeed(&ttcur,s); ! 3160: cfsetispeed(&ttcur,s2); ! 3161: cfsetospeed(&ttraw,s); ! 3162: cfsetispeed(&ttraw,s2); ! 3163: cfsetospeed(&tttvt,s); ! 3164: cfsetispeed(&tttvt,s2); ! 3165: cfsetospeed(&ttold,s); ! 3166: cfsetispeed(&ttold,s2); ! 3167: if (tcsetattr(ttyfd,TCSADRAIN,&ttcur) < 0) return(-1); ! 3168: #else ! 3169: #ifdef ATTSV ! 3170: if (cps == 888) return(-1); /* No split speeds, sorry. */ ! 3171: if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1); ! 3172: ttcur.c_cflag &= ~CBAUD; ! 3173: ttcur.c_cflag |= s; ! 3174: tttvt.c_cflag &= ~CBAUD; ! 3175: tttvt.c_cflag |= s; ! 3176: ttraw.c_cflag &= ~CBAUD; ! 3177: ttraw.c_cflag |= s; ! 3178: ttold.c_cflag &= ~CBAUD; ! 3179: ttold.c_cflag |= s; ! 3180: if (ioctl(ttyfd,TCSETAW,&ttcur) < 0) return(-1); ! 3181: #else ! 3182: if (gtty(ttyfd,&ttcur) < 0) return(-1); ! 3183: ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2; ! 3184: tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2; ! 3185: ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2; ! 3186: ttold.sg_ospeed = s; ttold.sg_ispeed = s2; ! 3187: if (stty(ttyfd,&ttcur) < 0) return(-1); ! 3188: #endif /* ATTSV */ ! 3189: #endif /* BSD44ORPOSIX */ ! 3190: } ! 3191: return(s); ! 3192: } ! 3193: ! 3194: /* T T G S P D - Get speed of currently selected tty line */ ! 3195: ! 3196: /* ! 3197: Unreliable. After SET LINE, it returns an actual speed, but not the real ! 3198: speed. Apparently it always returns the line's nominal speed, from ! 3199: /etc/ttytab. Even if you SET SPEED to something else, this function might ! 3200: not notice. ! 3201: */ ! 3202: long ! 3203: ttgspd() { /* Get current tty speed */ ! 3204: int s; long ss; ! 3205: char temp[12]; ! 3206: ! 3207: #ifdef NETCONN ! 3208: if (netconn) return(-1); /* -1 if network connection */ ! 3209: #endif /* NETCONN */ ! 3210: ! 3211: if (ttyfd < 0) { ! 3212: #ifdef BSD44ORPOSIX ! 3213: s = cfgetospeed(&ccold); ! 3214: #else ! 3215: #ifdef ATTSV ! 3216: s = ccold.c_cflag & CBAUD; ! 3217: #else ! 3218: s = ccold.sg_ospeed; /* (obtained by congm()) */ ! 3219: #endif /* ATTSV */ ! 3220: #endif /* BSD44ORPOSIX */ ! 3221: ! 3222: } else { ! 3223: #ifdef BSD44ORPOSIX ! 3224: if (tcgetattr(ttyfd,&ttcur) < 0) return(-1); ! 3225: s = cfgetospeed(&ttcur); ! 3226: #else ! 3227: #ifdef ATTSV ! 3228: if (ioctl(ttyfd,TCGETA,&ttcur) < 0) return(-1); ! 3229: s = ttcur.c_cflag & CBAUD; ! 3230: #else ! 3231: if (gtty(ttyfd,&ttcur) < 0) return(-1); ! 3232: s = ttcur.sg_ospeed; ! 3233: #endif /* ATTSV */ ! 3234: #endif /* BSD44ORPOSIX */ ! 3235: } ! 3236: debug(F101,"ttgspd ttyfd","",ttyfd); ! 3237: debug(F101,"ttgspd code","",s); ! 3238: switch (s) { ! 3239: #ifdef B0 ! 3240: case B0: ss = 0L; break; ! 3241: #endif /* B0 */ ! 3242: ! 3243: #ifndef MINIX ! 3244: /* ! 3245: MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150, ! 3246: etc, making for many "duplicate case in switch" errors, which are fatal. ! 3247: */ ! 3248: #ifdef B50 ! 3249: case B50: ss = 50L; break; ! 3250: #endif ! 3251: #ifdef B75 ! 3252: case B75: ss = 75L; break; ! 3253: #endif ! 3254: #endif /* MINIX */ ! 3255: ! 3256: #ifdef B110 ! 3257: case B110: ss = 110L; break; ! 3258: #endif ! 3259: ! 3260: #ifndef MINIX ! 3261: #ifdef B134 ! 3262: case B134: ss = 134L; break; ! 3263: #endif ! 3264: #ifdef B150 ! 3265: case B150: ss = 150L; break; ! 3266: #endif ! 3267: #endif /* MINIX */ ! 3268: ! 3269: #ifdef B200 ! 3270: case B200: ss = 200L; break; ! 3271: #endif ! 3272: ! 3273: #ifdef B300 ! 3274: case B300: ss = 300L; break; ! 3275: #endif ! 3276: #ifdef B600 ! 3277: case B600: ss = 600L; break; ! 3278: #endif ! 3279: #ifdef B1200 ! 3280: case B1200: ss = 1200L; break; ! 3281: #endif ! 3282: #ifdef B1800 ! 3283: case B1800: ss = 1800L; break; ! 3284: #endif ! 3285: #ifdef B2400 ! 3286: case B2400: ss = 2400L; break; ! 3287: #endif ! 3288: #ifdef B4800 ! 3289: case B4800: ss = 4800L; break; ! 3290: #endif ! 3291: #ifdef B9600 ! 3292: case B9600: ss = 9600L; break; ! 3293: #endif ! 3294: #ifdef B19200 ! 3295: case B19200: ss = 19200L; break; ! 3296: #else ! 3297: #ifdef EXTA ! 3298: case EXTA: ss = 19200L; break; ! 3299: #endif ! 3300: #endif ! 3301: ! 3302: #ifndef MINIX ! 3303: #ifdef B38400 ! 3304: case B38400: ss = 38400L; break; ! 3305: #else ! 3306: #ifdef EXTB ! 3307: case EXTB: ss = 38400L; break; ! 3308: #endif ! 3309: #endif ! 3310: #endif /* MINIX */ ! 3311: ! 3312: default: ! 3313: ss = -1; break; ! 3314: } ! 3315: sprintf(temp,"%ld",ss); ! 3316: debug(F110,"speed",temp,0); ! 3317: return(ss); ! 3318: } ! 3319: ! 3320: /* ckumyr.c by Kristoffer Eriksson, [email protected], 15 Mar 1990. */ ! 3321: ! 3322: #ifdef COHERENT ! 3323: #ifdef FIONREAD ! 3324: #undef FIONREAD ! 3325: #endif ! 3326: #define FIONREAD TIOCQUERY ! 3327: #define PEEKTYPE int ! 3328: #else ! 3329: #define PEEKTYPE long ! 3330: #endif /* COHERENT */ ! 3331: ! 3332: #ifdef MYREAD ! 3333: ! 3334: /* Private buffer for myread() and its companions. Not for use by anything ! 3335: * else. ttflui() is allowed to reset them to initial values. ttchk() is ! 3336: * allowed to read my_count. ! 3337: * ! 3338: * my_item is an index into mybuf[]. Increment it *before* reading mybuf[]. ! 3339: * ! 3340: * A global parity mask variable could be useful too. We could use it to ! 3341: * let myread() strip the parity on its own, instead of stripping sign ! 3342: * bits as it does now. ! 3343: */ ! 3344: #define MYBUFLEN 256 ! 3345: #ifdef SUNX25 ! 3346: /* ! 3347: On X.25 connections, there is an extra control byte at the beginning. ! 3348: */ ! 3349: static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */ ! 3350: static CHAR *mybuf = x25buf+1; ! 3351: #else ! 3352: static CHAR mybuf[MYBUFLEN]; ! 3353: #endif /* SUNX25 */ ! 3354: ! 3355: static int my_count = 0; /* Number of chars still in mybuf */ ! 3356: static int my_item = -1; /* Last index read from mybuf[] */ ! 3357: ! 3358: /* myread() -- Efficient read of one character from communications line. ! 3359: * ! 3360: * Uses a private buffer to minimize the number of expensive read() system ! 3361: * calls. Essentially performs the equivalent of read() of 1 character, which ! 3362: * is then returned. By reading all available input from the system buffers ! 3363: * to the private buffer in one chunk, and then working from this buffer, the ! 3364: * number of system calls is reduced in any case where more than one character ! 3365: * arrives during the processing of the previous chunk, for instance high ! 3366: * baud rates or network type connections where input arrives in packets. ! 3367: * If the time needed for a read() system call approaches the time for more ! 3368: * than one character to arrive, then this mechanism automatically compensates ! 3369: * for that by performing bigger read()s less frequently. If the system load ! 3370: * is high, the same mechanism compensates for that too. ! 3371: * ! 3372: * myread() is a macro that returns the next character from the buffer. If the ! 3373: * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error ! 3374: * returns. ! 3375: * ! 3376: * This should be efficient enough for any one-character-at-a-time loops. ! 3377: * For even better efficiency you might use memcpy()/bcopy() or such between ! 3378: * buffers (since they are often better optimized for copying), but it may not ! 3379: * be worth it if you have to take an extra pass over the buffer to strip ! 3380: * parity and check for CTRL-C anyway. ! 3381: * ! 3382: * Note that if you have been using myread() from another program module, you ! 3383: * may have some trouble accessing this macro version and the private variables ! 3384: * it uses. In that case, just add a function in this module, that invokes the ! 3385: * macro. ! 3386: */ ! 3387: #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item]) ! 3388: ! 3389: /* Specification: Push back up to one character onto myread()'s queue. ! 3390: * ! 3391: * This implementation: Push back characters into mybuf. At least one character ! 3392: * must have been read through myread() before myunrd() may be used. After ! 3393: * EOF or read error, again, myunrd() can not be used. Sometimes more than ! 3394: * one character can be pushed back, but only one character is guaranteed. ! 3395: * Since a previous myread() must have read its character out of mybuf[], ! 3396: * that guarantees that there is space for at least one character. If push ! 3397: * back was really needed after EOF, a small addition could provide that. ! 3398: * ! 3399: * myunrd() is currently not called from anywhere inside kermit... ! 3400: */ ! 3401: #ifdef NOTUSED ! 3402: myunrd(ch) CHAR ch; { ! 3403: if (my_item >= 0) { ! 3404: mybuf[my_item--] = ch; ! 3405: ++my_count; ! 3406: } ! 3407: } ! 3408: #endif ! 3409: ! 3410: /* mygetbuf() -- Fill buffer for myread() and return first character. ! 3411: * ! 3412: * This function is what myread() uses when it can't get the next character ! 3413: * directly from its buffer. First, it calls a system dependent myfillbuf() ! 3414: * to read at least one new character into the buffer, and then it returns ! 3415: * the first character just as myread() would have done. This function also ! 3416: * is responsible for all error conditions that myread() can indicate. ! 3417: * ! 3418: * Returns: When OK => a positive character, 0 or greater. ! 3419: * When EOF => -2. ! 3420: * When error => -3, error code in errno. ! 3421: * ! 3422: * Older myread()s additionally returned -1 to indicate that there was nothing ! 3423: * to read, upon which the caller would call myread() again until it got ! 3424: * something. The new myread()/mygetbuf() always gets something. If it ! 3425: * doesn't, then make it do so! Any program that actually depends on the old ! 3426: * behaviour will break. ! 3427: * ! 3428: * The older version also used to return -2 both for EOF and other errors, ! 3429: * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and ! 3430: * other errors now return different results, although Kermit currently never ! 3431: * checks to see which it was. It just disconnects in both cases. ! 3432: * ! 3433: * Kermit lets the user use the quit key to perform some special commands ! 3434: * during file transfer. This causes read(), and thus also mygetbuf(), to ! 3435: * finish without reading anything and return the EINTR error. This should ! 3436: * be checked by the caller. Mygetbuf() could retry the read() on EINTR, ! 3437: * but if there is nothing to read, this could delay Kermit's reaction to ! 3438: * the command, and make Kermit appear unresponsive. ! 3439: * ! 3440: * The debug() call should be removed for optimum performance. ! 3441: */ ! 3442: int ! 3443: mygetbuf() { ! 3444: my_count = myfillbuf(); ! 3445: debug(F101, "myfillbuf read", "", my_count); ! 3446: if (my_count <= 0) ! 3447: return(my_count < 0 ? -3 : -2); ! 3448: --my_count; ! 3449: return(255 & (int)mybuf[my_item = 0]); ! 3450: } ! 3451: ! 3452: /* myfillbuf(): ! 3453: * System-dependent read() into mybuf[], as many characters as possible. ! 3454: * ! 3455: * Returns: OK => number of characters read, always more than zero. ! 3456: * EOF => 0 ! 3457: * Error => -1, error code in errno. ! 3458: * ! 3459: * If there is input available in the system's buffers, all of it should be ! 3460: * read into mybuf[] and the function return immediately. If no input is ! 3461: * available, it should wait for a character to arrive, and return with that ! 3462: * one in mybuf[] as soon as possible. It may wait somewhat past the first ! 3463: * character, but be aware that any such delay lengthens the packet turnaround ! 3464: * time during kermit file transfers. Should never return with zero characters ! 3465: * unless EOF or irrecoverable read error. ! 3466: * ! 3467: * Correct functioning depends on the correct tty parameters being used. ! 3468: * Better control of current parameters is required than may have been the ! 3469: * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can ! 3470: * no longer be sometimes off and sometimes on like it used to, unless a ! 3471: * special myfillbuf() is written to handle that. Otherwise the ordinary ! 3472: * myfillbuf()s may think they have come to EOF. ! 3473: * ! 3474: * If your system has a facility to directly perform the functioning of ! 3475: * myfillbuf(), then use it. If the system can tell you how many characters ! 3476: * are available in its buffers, then read that amount (but not less than 1). ! 3477: * If the system can return a special indication when you try to read without ! 3478: * anything to read, while allowing you to read all there is when there is ! 3479: * something, you may loop until there is something to read, but probably that ! 3480: * is not good for the system load. ! 3481: */ ! 3482: ! 3483: #ifdef SVORPOSIX ! 3484: /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off, ! 3485: * and CLOCAL set any way you like. This way, read() will do exactly ! 3486: * what is required by myfillbuf(): If there is data in the buffers ! 3487: * of the O.S., all available data is read into mybuf, up to the size ! 3488: * of mybuf. If there is none, the first character to arrive is ! 3489: * awaited and returned. ! 3490: */ ! 3491: int ! 3492: myfillbuf() { ! 3493: #ifdef sxaE50 ! 3494: /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */ ! 3495: /* necessary for the sxa E50, but it is. */ ! 3496: return read(ttyfd, mybuf, 255); ! 3497: #else ! 3498: /* sizeof(mybuf) should be MYBUFL == 256 */ ! 3499: return read(ttyfd, mybuf, sizeof(mybuf)); ! 3500: #endif /* sxaE50 */ ! 3501: } ! 3502: ! 3503: #else /* not AT&T or POSIX */ ! 3504: ! 3505: #ifdef aegis ! 3506: /* This is quoted from the old myread(). The semantics seem to be ! 3507: * alright, but maybe errno would not need to be set even when ! 3508: * there is no error? I don't know aegis. ! 3509: */ ! 3510: int ! 3511: myfillbuf() { ! 3512: int count; ! 3513: ! 3514: count = ios_$get((short)ttyfd, ios_$cond_opt, mybuf, 256L, st); ! 3515: errno = EIO; ! 3516: if (st.all == ios_$get_conditional_failed) /* get at least one */ ! 3517: inbufc = ios_$get((short)ttyfd, 0, mybuf, 1L, st); ! 3518: if (st.all == ios_$end_of_file) ! 3519: return(0); ! 3520: else if (st.all != status_$ok) { ! 3521: errno = EIO; ! 3522: return(-1); ! 3523: } ! 3524: return(count); ! 3525: } ! 3526: #else /* !aegis */ ! 3527: ! 3528: #ifdef FIONREAD ! 3529: /* This is for systems with FIONREAD. FIONREAD returns the number ! 3530: * of characters available for reading. If none are available, wait ! 3531: * until something arrives, otherwise return all there is. ! 3532: */ ! 3533: int ! 3534: myfillbuf() { ! 3535: PEEKTYPE avail; ! 3536: int x; ! 3537: ! 3538: #ifdef SUNX25 ! 3539: /* ! 3540: SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC). ! 3541: Depends on SunOS having FIONREAD, not because we use it, but just so this ! 3542: code is grouped correctly within the #ifdefs. Let's hope Solaris keeps it. ! 3543: ! 3544: We call x25xin() instead of read() so that Q-Bit packets, which contain ! 3545: X.25 service-level information (e.g. PAD parameter changes), can be processed ! 3546: transparently to the upper-level code. This is a blocking read, and so ! 3547: we depend on higher-level code (such as ttinc()) to set any necessary alarms. ! 3548: */ ! 3549: extern int nettype; ! 3550: if (netconn && nettype == NET_SX25) { ! 3551: while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ; ! 3552: return(x - 1); /* "-1" compensates for extra status byte */ ! 3553: } ! 3554: #endif /* SUNX25 */ ! 3555: ! 3556: x = ioctl(ttyfd, FIONREAD, &avail); ! 3557: if (x < 0) { ! 3558: debug(F101,"myfillbuf FIONREAD","",x); ! 3559: debug(F101,"myfillbuf errno","",errno); ! 3560: } ! 3561: if (x < 0 || avail == 0) ! 3562: avail = 1; ! 3563: ! 3564: if (avail > MYBUFLEN) ! 3565: avail = MYBUFLEN; ! 3566: ! 3567: return(read(ttyfd, mybuf, (int) avail)); ! 3568: } ! 3569: ! 3570: #else /* !FIONREAD */ ! 3571: /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */ ! 3572: /* When there is no other possibility, read 1 character at a time. */ ! 3573: int ! 3574: myfillbuf() { ! 3575: return read(ttyfd, mybuf, 1); ! 3576: } ! 3577: ! 3578: #endif /* !FIONREAD */ ! 3579: #endif /* !aegis */ ! 3580: #endif /* !ATTSV */ ! 3581: ! 3582: #endif /* MYREAD */ ! 3583: ! 3584: /* T T F L U I -- Flush tty input buffer */ ! 3585: ! 3586: int ! 3587: ttflui() { ! 3588: #ifdef BSD44 ! 3589: int n; ! 3590: #endif /* BSD44 */ ! 3591: #ifndef SVORPOSIX ! 3592: int n; ! 3593: #endif /* SVORPOSIX */ ! 3594: ! 3595: #ifdef MYREAD ! 3596: /* ! 3597: Flush internal MYREAD buffer *FIRST*, in all cases. ! 3598: */ ! 3599: my_count = 0; /* Reset count to zero */ ! 3600: my_item = -1; /* And buffer index to -1 */ ! 3601: #endif /* MYREAD */ ! 3602: ! 3603: #ifdef NETCONN ! 3604: /* ! 3605: Network flush is done specially, in the network support module. ! 3606: */ ! 3607: if (netconn) return(netflui()); ! 3608: #endif /* NETCONN */ ! 3609: ! 3610: debug(F101,"ttflui ttyfd","",ttyfd); ! 3611: if (ttyfd < 0) return(-1); ! 3612: ! 3613: #ifdef aegis ! 3614: sio_$control((short)ttyfd, sio_$flush_in, true, st); ! 3615: if (st.all != status_$ok) { ! 3616: fprintf(stderr, "flush failed: "); error_$print(st); ! 3617: } else { /* sometimes the flush doesn't work */ ! 3618: for (;;) { ! 3619: char buf[256]; ! 3620: /* eat all the characters that shouldn't be available */ ! 3621: ios_$get((short)ttyfd, ios_$cond_opt, buf, 256L, st); /* (void) */ ! 3622: if (st.all == ios_$get_conditional_failed) break; ! 3623: fprintf(stderr, "flush failed(2): "); error_$print(st); ! 3624: } ! 3625: } ! 3626: #else ! 3627: #ifdef BSD44 /* 4.4 BSD */ ! 3628: n = FREAD; /* Specify read queue */ ! 3629: debug(F101,"ttflui BSD44 flush","",ttyfd); ! 3630: ioctl(ttyfd,TIOCFLUSH,&n); ! 3631: ioctl(ttyfd,TCSAFLUSH,&n); ! 3632: #else ! 3633: #ifdef POSIX /* POSIX */ ! 3634: tcflush(ttyfd,TCIFLUSH); ! 3635: #else ! 3636: #ifdef ATTSV /* System V */ ! 3637: #ifndef VXVE ! 3638: ioctl(ttyfd,TCFLSH,0); ! 3639: #endif /* VXVE */ ! 3640: #else /* Not BSD44, POSIX, or Sys V */ ! 3641: #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */ ! 3642: #ifdef ANYBSD /* Berkeley */ ! 3643: n = FREAD; /* Specify read queue */ ! 3644: debug(F101,"ttflui anybsd flush","",ttyfd); ! 3645: ioctl(ttyfd,TIOCFLUSH,&n); ! 3646: #else /* Others (V7, etc) */ ! 3647: ioctl(ttyfd,TIOCFLUSH,0); ! 3648: #endif /* ANYBSD */ ! 3649: #else /* All others... */ ! 3650: /* ! 3651: No system call (that we know about) for input buffer flushing. ! 3652: So see how many there are and read them in a loop, using ttinc(). ! 3653: ttinc() is buffered, so we're not getting charged with a system call ! 3654: per character, just a function call. ! 3655: */ ! 3656: if ((n = ttchk()) > 0) { ! 3657: debug(F101,"ttflui reading","",n); ! 3658: while ((n--) && ttinc(0) > 1) ; ! 3659: } ! 3660: #endif /* TIOCFLUSH */ ! 3661: #endif /* ATTSV */ ! 3662: #endif /* POSIX */ ! 3663: #endif /* BSD44 */ ! 3664: #endif /* aegis */ ! 3665: return(0); ! 3666: } ! 3667: ! 3668: int ! 3669: ttfluo() { /* Flush output buffer */ ! 3670: #ifdef POSIX ! 3671: return(tcflush(ttyfd,TCOFLUSH)); ! 3672: #else ! 3673: return(0); /* (dummy for now) */ ! 3674: #endif /* POSIX */ ! 3675: ! 3676: } ! 3677: ! 3678: /* Interrupt Functions */ ! 3679: ! 3680: /* Set up terminal interrupts on console terminal */ ! 3681: ! 3682: #ifdef SVORPOSIX ! 3683: SIGTYP ! 3684: esctrp(foo) int foo; { /* trap console escapes (^\) */ ! 3685: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ ! 3686: conesc = 1; ! 3687: debug(F101,"esctrp caught SIGQUIT","",conesc); ! 3688: } ! 3689: #endif /* SVORPOSIX */ ! 3690: ! 3691: #ifdef V7 ! 3692: SIGTYP ! 3693: esctrp(foo) int foo; { /* trap console escapes (^\) */ ! 3694: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ ! 3695: conesc = 1; ! 3696: debug(F101,"esctrp caught SIGQUIT","",conesc); ! 3697: } ! 3698: #endif ! 3699: ! 3700: #ifdef C70 ! 3701: SIGTYP ! 3702: esctrp(foo) int foo; { /* trap console escapes (^\) */ ! 3703: conesc = 1; ! 3704: signal(SIGQUIT,SIG_IGN); /* ignore until trapped */ ! 3705: } ! 3706: #endif ! 3707: ! 3708: /* C O N B G T -- Background Test */ ! 3709: ! 3710: static int jc = 0; /* 0 = no job control */ ! 3711: ! 3712: /* ! 3713: Call with flag == 1 to prevent signal test, which can not be expected ! 3714: to work during file transfer, when SIGINT probably *is* set to SIG_IGN. ! 3715: ! 3716: Call with flag == 0 to use the signal test, but only if the process-group ! 3717: test fails, as it does on some UNIX systems, where getpgrp() is buggy, ! 3718: requires an argument when the man page says it doesn't, or vice versa. ! 3719: ! 3720: If flag == 0 and the process-group test fails, then we determine background ! 3721: status simply (but not necessarily reliably) from isatty(). ! 3722: ! 3723: conbgt() sets the global backgrd = 1 if we appear to be in the background, ! 3724: and to 0 if we seem to be in the foreground. conbgt() is highly prone to ! 3725: misbehavior. ! 3726: */ ! 3727: VOID ! 3728: conbgt(flag) int flag; { ! 3729: int x = -1, /* process group or SIGINT test */ ! 3730: y = 0; /* isatty() test */ ! 3731: /* ! 3732: Check for background operation, even if not running on real tty, so that ! 3733: background flag can be set correctly. If background status is detected, ! 3734: then Kermit will not issue its interactive prompt or most messages. ! 3735: If your prompt goes away, you can blame (and fix?) this function. ! 3736: */ ! 3737: ! 3738: /* Use process-group test if possible. */ ! 3739: ! 3740: #ifdef POSIX /* We can do it in POSIX */ ! 3741: #define PGROUP_T ! 3742: #else ! 3743: #ifdef BSD4 /* and in BSD 4.x. */ ! 3744: #define PGROUP_T ! 3745: #else ! 3746: #ifdef HPUXJOBCTL /* and in most HP-UX's */ ! 3747: #define PGROUP_T ! 3748: #else ! 3749: #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */ ! 3750: #define PGROUP_T ! 3751: #endif /* TIOCGPGRP */ ! 3752: #endif /* HPUXJOBCTL */ ! 3753: #endif /* BSD4 */ ! 3754: #endif /* POSIX */ ! 3755: ! 3756: #ifdef MIPS /* Except if it doesn't work... */ ! 3757: #undef PGROUP_T ! 3758: #endif /* MIPS */ ! 3759: ! 3760: #ifdef PGROUP_T ! 3761: /* ! 3762: Semi-reliable process-group test. Check whether this process's group is ! 3763: the same as the controlling terminal's process group. This works if the ! 3764: getpgrp() call doesn't lie (as it does in the SUNOS System V environment). ! 3765: */ ! 3766: PID_T mypgrp = (PID_T)0; /* Kermit's process group */ ! 3767: PID_T ctpgrp = (PID_T)0; /* The terminal's process group */ ! 3768: #ifndef _POSIX_SOURCE ! 3769: /* ! 3770: The getpgrp() prototype is obtained from system header files for POSIX ! 3771: and Sys V R4 compilations. Other systems, who knows. Some complain about ! 3772: a duplicate declaration here, others don't, so it's safer to leave it in ! 3773: if we don't know for certain. ! 3774: */ ! 3775: #ifndef SVR4 ! 3776: #ifndef PS2AIX10 ! 3777: extern PID_T getpgrp(); ! 3778: #endif /* PS2AIX10 */ ! 3779: #endif /* SVR4 */ ! 3780: #endif /* _POSIX_SOURCE */ ! 3781: ! 3782: /* Get my process group. */ ! 3783: ! 3784: #ifdef SVR3 /* Maybe this should be ATTSV? */ ! 3785: /* This function is not described in SVID R2 */ ! 3786: mypgrp = getpgrp(); ! 3787: debug(F101,"ATTSV conbgt process group","",(int) mypgrp); ! 3788: #else ! 3789: #ifdef POSIX ! 3790: mypgrp = getpgrp(); ! 3791: debug(F101,"POSIX conbgt process group","",(int) mypgrp); ! 3792: #else /* BSD, V7, etc */ ! 3793: mypgrp = getpgrp(0); ! 3794: debug(F101,"BSD conbgt process group","",(int) mypgrp); ! 3795: #endif /* POSIX */ ! 3796: #endif /* SVR3 */ ! 3797: ! 3798: /* Now get controlling tty's process group */ ! 3799: #ifdef BSD44ORPOSIX ! 3800: ctpgrp = tcgetpgrp(1); /* The POSIX way */ ! 3801: debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); ! 3802: #else ! 3803: ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */ ! 3804: debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); ! 3805: #endif /* BSD44ORPOSIX */ ! 3806: ! 3807: if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0)) ! 3808: x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */ ! 3809: else x = -1; /* If error, remember. */ ! 3810: debug(F101,"conbgt process group test","",x); ! 3811: #endif /* PGROUP_T */ ! 3812: ! 3813: /* Try to see if job control is available */ ! 3814: ! 3815: #ifdef NOJC /* User override */ ! 3816: jc = 0; /* No job control allowed */ ! 3817: debug(F111,"NOJC","jc",jc); ! 3818: #else ! 3819: #ifdef BSD44 ! 3820: jc = 1; ! 3821: #else ! 3822: #ifdef SVR4ORPOSIX /* POSIX actually tells us */ ! 3823: debug(F100,"SVR4ORPOSIX jc test...","",0); ! 3824: #ifdef _SC_JOB_CONTROL ! 3825: #ifdef bsdi ! 3826: jc = 1; ! 3827: #else ! 3828: #ifdef __386BSD__ ! 3829: jc = 1; ! 3830: #else ! 3831: jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */ ! 3832: debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc); ! 3833: #endif /* __386BSD__ */ ! 3834: #endif /* bsdi */ ! 3835: #else ! 3836: #ifdef _POSIX_JOB_CONTROL ! 3837: jc = 1; /* By definition */ ! 3838: debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc); ! 3839: #else ! 3840: jc = 0; /* Assume job control not allowed */ ! 3841: debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc); ! 3842: #endif /* _POSIX_JOB_CONTROL */ ! 3843: #endif /* _SC_JOB_CONTROL */ ! 3844: #else ! 3845: #ifdef BSD4 ! 3846: jc = 1; /* Job control allowed */ ! 3847: debug(F111,"BSD job control","jc",jc); ! 3848: #else ! 3849: #ifdef SVR3JC ! 3850: jc = 1; /* JC allowed */ ! 3851: debug(F111,"SVR3 job control","jc",jc); ! 3852: #else ! 3853: jc = 0; /* JC not allowed */ ! 3854: debug(F111,"job control catch-all","jc",jc); ! 3855: #endif /* SVR3JC */ ! 3856: #endif /* BSD4 */ ! 3857: #endif /* SVR4ORPOSIX */ ! 3858: #endif /* BSD44 */ ! 3859: #endif /* NOJC */ ! 3860: debug(F101,"conbgt jc","",jc); ! 3861: ! 3862: /* ! 3863: Another background test. ! 3864: Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore), ! 3865: which is done by the shell (sh) if the program is started with '&'. ! 3866: Unfortunately, this is NOT done by csh or ksh so watch out! ! 3867: Note, it's safe to set SIGINT to SIG_IGN here, because further down ! 3868: we always set it to something else. ! 3869: */ ! 3870: if (x < 0 && !flag) { /* Didn't get good results above... */ ! 3871: ! 3872: SIGTYP (*osigint)(); ! 3873: ! 3874: osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */ ! 3875: x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */ ! 3876: debug(F101,"conbgt osigint","",(int) osigint); ! 3877: debug(F101,"conbgt signal test","",x); ! 3878: } ! 3879: ! 3880: /* Also check to see if we're running with redirected stdio. */ ! 3881: /* This is not really background operation, but we want to act as though */ ! 3882: /* it were. */ ! 3883: ! 3884: y = (isatty(0) && isatty(1)) ? 1 : 0; ! 3885: debug(F101,"conbgt isatty test","",y); ! 3886: ! 3887: #ifdef BSD29 ! 3888: /* The process group and/or signal test doesn't work under these... */ ! 3889: backgrd = !y; ! 3890: #else ! 3891: #ifdef sxaE50 ! 3892: backgrd = !y; ! 3893: #else ! 3894: #ifdef MINIX ! 3895: backgrd = !y; ! 3896: #else ! 3897: if (x > -1) ! 3898: backgrd = (x || !y) ? 1 : 0; ! 3899: else backgrd = !y; ! 3900: #endif /* BSD29 */ ! 3901: #endif /* sxaE50 */ ! 3902: #endif /* MINIX */ ! 3903: debug(F101,"conbgt backgrd","",backgrd); ! 3904: } ! 3905: ! 3906: /* C O N I N T -- Console Interrupt setter */ ! 3907: ! 3908: /* ! 3909: First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C). ! 3910: Second arg is pointer to function to handle SIGTSTP (suspend). ! 3911: */ ! 3912: ! 3913: VOID /* Set terminal interrupt traps. */ ! 3914: #ifdef CK_ANSIC ! 3915: #ifdef apollo ! 3916: conint(f,s) SIGTYP (*f)(), (*s)(); ! 3917: #else ! 3918: conint(SIGTYP (*f)(int), SIGTYP (*s)(int)) ! 3919: #endif /* apollo */ ! 3920: #else ! 3921: conint(f,s) SIGTYP (*f)(), (*s)(); ! 3922: #endif /* CK_ANSIC */ ! 3923: /* conint */ { ! 3924: ! 3925: conbgt(0); /* Do background test. */ ! 3926: ! 3927: /* Set the desired handlers for hangup and software termination. */ ! 3928: ! 3929: signal(SIGTERM,f); /* Software termination */ ! 3930: ! 3931: #ifdef COMMENT ! 3932: /* ! 3933: Prior to edit 184, we used to trap SIGHUP here. That is clearly wrong; ! 3934: on some systems, it would leave the user's process on the terminal after ! 3935: the phone hung up. But the trap was here for a reason: most likely some ! 3936: UNIX systems (init, getty, or login) fail to properly restore the terminal ! 3937: modes after regaining control of a hung-up-upon login terminal. Therefore ! 3938: removing this trap is likely to cause problems too. A more sensible ! 3939: approach would be to use a special handler for HANGUP, which would restore ! 3940: the terminal modes and then exit(). But that could leave zombie processes ! 3941: around (like the lower CONNECT fork, or any fork started by zxcmd()), but ! 3942: there is probably no clean, portable, reliable way for Kermit to kill all ! 3943: its forks. So we just exit() and hope that UNIX fixes the terminal modes ! 3944: before the next person tries to log in. ! 3945: */ ! 3946: signal(SIGHUP,f); /* Hangup */ ! 3947: #endif /* COMMENT */ ! 3948: ! 3949: /* Now handle keyboard stop, quit, and interrupt signals. */ ! 3950: /* Check if invoked in background -- if so signals set to be ignored. */ ! 3951: /* However, if running under a job control shell, don't ignore them. */ ! 3952: /* We won't be getting any, as we aren't in the terminal's process group. */ ! 3953: ! 3954: debug(F101,"conint backgrd","",backgrd); ! 3955: debug(F101,"conint jc","",jc); ! 3956: ! 3957: if (backgrd && !jc) { /* In background, ignore signals */ ! 3958: debug(F101,"conint background ignoring signals, jc","",jc); ! 3959: #ifdef SIGTSTP ! 3960: signal(SIGTSTP,SIG_IGN); /* Keyboard stop */ ! 3961: #endif /* SIGTSTP */ ! 3962: signal(SIGQUIT,SIG_IGN); /* Keyboard quit */ ! 3963: signal(SIGINT,SIG_IGN); /* Keyboard interrupt */ ! 3964: } else { /* Else in foreground or suspended */ ! 3965: debug(F101,"conint foreground catching signals, jc","",jc); ! 3966: signal(SIGINT,f); /* Catch terminal interrupt */ ! 3967: ! 3968: #ifdef SIGTSTP /* Keyboard stop (suspend) */ ! 3969: debug(F101,"conint SIGSTSTP","",(int) s); ! 3970: if (s == NULL) s = SIG_DFL; ! 3971: #ifdef NOJC /* No job control allowed. */ ! 3972: signal(SIGTSTP,SIG_IGN); ! 3973: #else /* Job control allowed */ ! 3974: if (jc) /* if available. */ ! 3975: signal(SIGTSTP,s); ! 3976: else ! 3977: signal(SIGTSTP,SIG_IGN); ! 3978: #endif /* NOJC */ ! 3979: #endif /* SIGTSTP */ ! 3980: ! 3981: #ifdef SVORPOSIX ! 3982: signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */ ! 3983: if (conesc) conesc = 0; /* Clear out pending escapes */ ! 3984: #else ! 3985: #ifdef V7 ! 3986: signal(SIGQUIT,esctrp); /* V7 like Sys III/V */ ! 3987: if (conesc) conesc = 0; ! 3988: #else ! 3989: #ifdef aegis ! 3990: signal(SIGQUIT,f); /* Apollo, catch it like others. */ ! 3991: #else ! 3992: signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */ ! 3993: #endif /* aegis */ ! 3994: #endif /* V7 */ ! 3995: #endif /* SVORPOSIX */ ! 3996: } ! 3997: } ! 3998: ! 3999: ! 4000: /* C O N N O I -- Reset console terminal interrupts */ ! 4001: ! 4002: SIGTYP /* Dummy function to ignore signals */ ! 4003: #ifdef CK_ANSIC ! 4004: sig_ign(int foo) ! 4005: #else ! 4006: sig_ign(foo) int foo; ! 4007: #endif /* CK_ANSIC */ ! 4008: /* sig_IGN */ { /* Just like the real one, but has */ ! 4009: } /* different address. */ ! 4010: ! 4011: VOID ! 4012: connoi() { /* Console-no-interrupts */ ! 4013: ! 4014: debug(F100,"connoi","",0); ! 4015: #ifdef SIGTSTP ! 4016: signal(SIGTSTP,SIG_DFL); ! 4017: #endif /* SIGTSTP */ ! 4018: /* Note the locally defined replacement for SIG_IGN that is used here */ ! 4019: /* for the SIGINT setting. This is done so that the Sys V background */ ! 4020: /* test -- (signal(SIGINT,SIG_IGN) == SIG_IGN) -- can work. If we use */ ! 4021: /* the real SIG_IGN here, then conint will always decide that this */ ! 4022: /* program is running in the background! */ ! 4023: ! 4024: signal(SIGINT,sig_ign); /* <--- note! */ ! 4025: ! 4026: signal(SIGHUP,SIG_DFL); ! 4027: signal(SIGQUIT,SIG_IGN); ! 4028: signal(SIGTERM,SIG_IGN); ! 4029: } ! 4030: ! 4031: /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */ ! 4032: ! 4033: #ifdef V7 ! 4034: /* ! 4035: Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This ! 4036: eliminates blocking on a read, because we can read /dev/kmem to get the ! 4037: number of characters available for raw input. If your system can't ! 4038: or you won't let the world read /dev/kmem then you must figure out a ! 4039: different way to do the counting of characters available, or else replace ! 4040: this by a dummy function that always returns 0. ! 4041: */ ! 4042: /* ! 4043: * Call this routine as: initrawq(tty) ! 4044: * where tty is the file descriptor of a terminal. It will return ! 4045: * (as a char *) the kernel-mode memory address of the rawq character ! 4046: * count, which may then be read. It has the side-effect of flushing ! 4047: * input on the terminal. ! 4048: */ ! 4049: /* ! 4050: * John Mackin, Physiology Dept., University of Sydney (Australia) ! 4051: * ...!decvax!mulga!physiol.su.oz!john ! 4052: * ! 4053: * Permission is hereby granted to do anything with this code, as ! 4054: * long as this comment is retained unmodified and no commercial ! 4055: * advantage is gained. ! 4056: */ ! 4057: #ifndef MINIX ! 4058: #ifndef COHERENT ! 4059: #include <a.out.h> ! 4060: #include <sys/proc.h> ! 4061: #endif /* COHERENT */ ! 4062: #endif /* MINIX */ ! 4063: ! 4064: #ifdef COHERENT ! 4065: #include <l.out.h> ! 4066: #include <sys/proc.h> ! 4067: #endif /* COHERENT */ ! 4068: ! 4069: char * ! 4070: initrawq(tty) int tty; { ! 4071: #ifdef MINIX ! 4072: return(0); ! 4073: #else ! 4074: #ifdef UTS24 ! 4075: return(0); ! 4076: #else ! 4077: #ifdef BSD29 ! 4078: return(0); ! 4079: #else ! 4080: long lseek(); ! 4081: static struct nlist nl[] = { ! 4082: {PROCNAME}, ! 4083: {NPROCNAME}, ! 4084: {""} ! 4085: }; ! 4086: static struct proc *pp; ! 4087: char *qaddr, *p, c; ! 4088: int m; ! 4089: PID_T pid, me; ! 4090: NPTYPE xproc; /* Its type is defined in makefile. */ ! 4091: int catch(); ! 4092: ! 4093: me = getpid(); ! 4094: if ((m = open("/dev/kmem", 0)) < 0) err("kmem"); ! 4095: nlist(BOOTNAME, nl); ! 4096: if (nl[0].n_type == 0) err("proc array"); ! 4097: ! 4098: if (nl[1].n_type == 0) err("nproc"); ! 4099: ! 4100: lseek(m, (long)(nl[1].n_value), 0); ! 4101: read (m, &xproc, sizeof(xproc)); ! 4102: saval = signal(SIGALRM, catch); ! 4103: if ((pid = fork()) == 0) { ! 4104: while(1) ! 4105: read(tty, &c, 1); ! 4106: } ! 4107: alarm(2); ! 4108: ! 4109: if(setjmp(jjbuf) == 0) { ! 4110: while(1) ! 4111: read(tty, &c, 1); ! 4112: } ! 4113: signal(SIGALRM, SIG_DFL); ! 4114: ! 4115: #ifdef DIRECT ! 4116: pp = (struct proc *) nl[0].n_value; ! 4117: #else ! 4118: if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek"); ! 4119: if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr"); ! 4120: #endif ! 4121: lseek(m, (long)(nl[1].n_value), 0); ! 4122: read(m, &xproc, sizeof(xproc)); ! 4123: ! 4124: if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc"); ! 4125: if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc"); ! 4126: if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc)) ! 4127: err("read proc table"); ! 4128: for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) { ! 4129: if (pp -> p_pid == (short) pid) goto iout; ! 4130: } ! 4131: err("no such proc"); ! 4132: ! 4133: iout: ! 4134: close(m); ! 4135: qaddr = (char *)(pp -> p_wchan); ! 4136: free (p); ! 4137: kill(pid, SIGKILL); ! 4138: wait((WAIT_T)0); /* Destroy the ZOMBIEs! */ ! 4139: return (qaddr); ! 4140: #endif ! 4141: #endif ! 4142: #endif ! 4143: } ! 4144: ! 4145: /* More V7-support functions... */ ! 4146: ! 4147: static VOID ! 4148: err(s) char *s; { ! 4149: char buf[200]; ! 4150: ! 4151: sprintf(buf, "fatal error in initrawq: %s", s); ! 4152: perror(buf); ! 4153: doexit(1,-1); ! 4154: } ! 4155: ! 4156: static VOID ! 4157: catch(foo) int foo; { ! 4158: longjmp(jjbuf, -1); ! 4159: } ! 4160: ! 4161: ! 4162: /* G E N B R K -- Simulate a modem break. */ ! 4163: ! 4164: #ifdef MINIX ! 4165: #define BSPEED B110 ! 4166: #else ! 4167: #define BSPEED B150 ! 4168: #endif /* MINIX */ ! 4169: ! 4170: VOID ! 4171: genbrk(fn,msec) int fn, msec; { ! 4172: struct sgttyb ttbuf; ! 4173: int ret, sospeed, x, y; ! 4174: ! 4175: ret = ioctl(fn, TIOCGETP, &ttbuf); ! 4176: sospeed = ttbuf.sg_ospeed; ! 4177: ttbuf.sg_ospeed = BSPEED; ! 4178: ret = ioctl(fn, TIOCSETP, &ttbuf); ! 4179: y = (int)strlen(brnuls); ! 4180: x = ( BSPEED * 100 ) / msec; ! 4181: if (x > y) x = y; ! 4182: ret = write(fn, brnuls, (( BSPEED * 100 ) / msec )); ! 4183: ttbuf.sg_ospeed = sospeed; ! 4184: ret = ioctl(fn, TIOCSETP, &ttbuf); ! 4185: ret = write(fn, "@", 1); ! 4186: return; ! 4187: } ! 4188: #endif /* V7 */ ! 4189: ! 4190: /* T T C H K -- Tell how many characters are waiting in tty input buffer */ ! 4191: ! 4192: /* Some callers of this want to know whether there is something to read ! 4193: * either in the system buffers or in our private buffers (and mostly don't ! 4194: * care how many characters, just whether it's more than zero or not), while ! 4195: * some others would be better off with the number of characters in our ! 4196: * private buffers only. ! 4197: * ! 4198: * Some systems can say how many characters there are in the system buffers. ! 4199: * Others can not. For those that can't, the number in the private buffers ! 4200: * will have to do (or should we put the tty into O_NDELAY-mode and try to ! 4201: * read one character?). If the system can tell whether there is zero or ! 4202: * more than zero characters, we can return 1 in the latter case even if the ! 4203: * private buffer is empty. (That is good for sliding windows.) ! 4204: */ ! 4205: int ! 4206: ttchk() { ! 4207: int x; ! 4208: PEEKTYPE n = 0; ! 4209: ! 4210: #ifdef COMMENT ! 4211: /* ! 4212: This was REALLY slowing TELNET connections down! Just do the regular ! 4213: ttyfd-based stuff here. Let the VMS version call nettchk if it has to... ! 4214: FIONREAD definitely works for TELNET, at least on the NeXT and SUNOS. ! 4215: */ ! 4216: #ifdef NETCONN ! 4217: if (netconn) return(nettchk()); ! 4218: #endif /* NETCONN */ ! 4219: #endif /* COMMENT */ ! 4220: ! 4221: #ifdef FIONREAD ! 4222: x = ioctl(ttyfd, FIONREAD, &n); /* Berkeley and maybe some others */ ! 4223: debug(F101,"ttchk FIONREAD return code","",x); ! 4224: debug(F101,"ttchk FIONREAD count","",n); ! 4225: if (x < 0) n = 0; ! 4226: #else ! 4227: #ifdef V7 ! 4228: #ifdef MINIX ! 4229: return(0); ! 4230: #else ! 4231: lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */ ! 4232: x = read(kmem[TTY], &n, sizeof(int)); ! 4233: if (x != sizeof(int)) n = 0; ! 4234: #endif /* MINIX */ ! 4235: #else ! 4236: #ifdef PROVX1 ! 4237: x = ioctl(ttyfd, TIOCQCNT, &ttbuf); /* Pro/3xx Venix V.1 */ ! 4238: n = ttbuf.sg_ispeed & 0377; ! 4239: if (x < 0) n = 0; ! 4240: #else ! 4241: #ifdef RDCHK ! 4242: /* ! 4243: Last resort for systems without FIONREAD or equivalent, but with ! 4244: something like rdchk(), like XENIX. ! 4245: */ ! 4246: if (my_count == 0 && rdchk(ttyfd) > 0) n = 1; ! 4247: debug(F101,"ttchk rdchk","",n); ! 4248: #endif /* RDCHK */ ! 4249: #endif /* PROVX1 */ ! 4250: #endif /* V7 */ ! 4251: #endif /* FIONREAD */ ! 4252: ! 4253: #ifdef MYREAD ! 4254: /* ! 4255: For myread() users, add the contents of myread()'s private buffer. ! 4256: Sometimes, this is all there is to construct a result of ttchk() on. ! 4257: */ ! 4258: if (my_count > 0) ! 4259: n += my_count; ! 4260: #endif /* MYREAD */ ! 4261: ! 4262: debug(F101,"ttchk returns","",n); ! 4263: return(n); ! 4264: } ! 4265: ! 4266: /* T T X I N -- Get n characters from tty input buffer */ ! 4267: ! 4268: /* Returns number of characters actually gotten, or -1 on failure */ ! 4269: ! 4270: /* Intended for use only when it is known that n characters are actually */ ! 4271: /* Available in the input buffer. */ ! 4272: ! 4273: int ! 4274: ttxin(n,buf) int n; CHAR *buf; { ! 4275: register int x, c; ! 4276: ! 4277: debug(F101,"ttxin n","",n); ! 4278: if (n < 1) return(0); ! 4279: ttpmsk = (ttprty) ? 0177 : 0377; /* Parity stripping mask. */ ! 4280: ! 4281: #ifdef SUNX25 ! 4282: if (netconn && (ttnet == NET_SX25)) /* X.25 connection */ ! 4283: return(x25xin(n,buf)); ! 4284: #endif /* SUNX25 */ ! 4285: ! 4286: #ifdef MYREAD ! 4287: debug(F101,"ttxin MYREAD","",0); ! 4288: c = -2; ! 4289: for( x = 0; (x > -1) && (x < n) && (c = myread()) >= 0; ) ! 4290: buf[x++] = c & ttpmsk; ! 4291: if (c < 0) { ! 4292: debug(F101,"ttxin myread returns","",c); ! 4293: if (c == -3) x = -1; ! 4294: } ! 4295: #else ! 4296: x = read(ttyfd,buf,n); ! 4297: for (c = 0; c < n; c++) buf[c] &= ttpmsk; ! 4298: debug(F101," x","",x); ! 4299: #endif /* MYREAD */ ! 4300: if (x > 0) buf[x] = '\0'; ! 4301: if (x < 0) x = -1; ! 4302: return(x); ! 4303: } ! 4304: ! 4305: /* T T O L -- Write string s, length n, to communication device. */ ! 4306: /* ! 4307: Returns: ! 4308: >= 0 on success, number of characters actually written. ! 4309: -1 on failure. ! 4310: */ ! 4311: #define TTOLMAXT 5 ! 4312: int ! 4313: ttol(s,n) int n; CHAR *s; { ! 4314: int x, len, tries; ! 4315: ! 4316: if (ttyfd < 0) return(-1); /* Not open? */ ! 4317: debug(F101,"ttol n","",n); ! 4318: tries = TTOLMAXT; /* Allow up to this many tries */ ! 4319: len = n; /* Remember original length */ ! 4320: ! 4321: while (n > 0 && tries-- > 0) { /* Be persistent */ ! 4322: debug(F101,"ttol try","",TTOLMAXT - tries); ! 4323: x = write(ttyfd,s,n); /* Write string to device */ ! 4324: if (x == n) { /* Worked? */ ! 4325: debug(F101,"ttol ok","",x); /* OK */ ! 4326: return(len); /* Done */ ! 4327: } else if (x < 0) { /* No, got error? */ ! 4328: debug(F101,"ttol failed","",errno); ! 4329: return(-1); ! 4330: } else { /* No error, so partial success */ ! 4331: debug(F101,"ttol partial","",x); ! 4332: s += x; /* Point to part not written yet */ ! 4333: n -= x; /* Adjust length */ ! 4334: if (x > 0) msleep(100); /* Wait 100 msec */ ! 4335: } /* Go back and try again */ ! 4336: } ! 4337: return(n < 1 ? len : -1); /* Too many tries */ ! 4338: } ! 4339: ! 4340: ! 4341: ! 4342: /* T T O C -- Output a character to the communication line */ ! 4343: ! 4344: /* ! 4345: This function should only be used for interactive, character-mode operations, ! 4346: like terminal connection, script execution, dialer i/o, where the overhead ! 4347: of the signals and alarms does not create a bottleneck. ! 4348: */ ! 4349: int ! 4350: #ifdef CK_ANSIC ! 4351: ttoc(char c) ! 4352: #else ! 4353: ttoc(c) char c; ! 4354: #endif /* CK_ANSIC */ ! 4355: /* ttoc */ { ! 4356: #define TTOC_TMO 15 /* Timeout in case we get stuck */ ! 4357: int xx; ! 4358: c &= 0xff; ! 4359: /* debug(F101,"ttoc","",(CHAR) c); */ ! 4360: if (ttyfd < 0) return(-1); /* Check for not open. */ ! 4361: saval = signal(SIGALRM,timerh); /* Enable timer interrupt */ ! 4362: xx = alarm(TTOC_TMO); /* for this many seconds. */ ! 4363: if (xx < 0) xx = 0; /* Save old alarm value. */ ! 4364: /* debug(F101,"ttoc alarm","",xx); */ ! 4365: if (setjmp(sjbuf)) { /* Timer went off? */ ! 4366: ttimoff(); /* Yes, cancel this alarm. */ ! 4367: if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */ ! 4368: /* debug(F100,"ttoc timeout","",0); */ ! 4369: #ifdef NETCONN ! 4370: if (!netconn) { ! 4371: #endif /* NETCONN */ ! 4372: debug(F101,"ttoc timeout","",c); ! 4373: if (ttflow == FLO_XONX) { ! 4374: int x = 0, y; ! 4375: debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */ ! 4376: #ifdef POSIX ! 4377: y = tcflow(ttyfd,TCOON); /* POSIX way to unstick. */ ! 4378: debug(F100,"ttoc tcflow","",y); ! 4379: #else ! 4380: #ifdef BSD4 /* Berkeley way to do it. */ ! 4381: #ifdef TIOCSTART ! 4382: /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);". Who knows? */ ! 4383: y = ioctl(ttyfd, TIOCSTART, &x); ! 4384: debug(F101,"ttoc TIOCSTART","",y); ! 4385: #endif /* TIOCSTART */ ! 4386: #endif /* BSD4 */ ! 4387: /* Is there a Sys V way to do this? */ ! 4388: #endif /* POSIX */ ! 4389: } ! 4390: #ifdef NETCONN ! 4391: } ! 4392: #endif /* NETCONN */ ! 4393: return(-1); /* Return failure code. */ ! 4394: } else { ! 4395: if (write(ttyfd,&c,1) < 1) { /* Try to write the character. */ ! 4396: ttimoff(); /* Failed, turn off the alarm. */ ! 4397: alarm(xx); /* Restore previous alarm. */ ! 4398: debug(F101,"ttoc error","",errno); /* Log the error, */ ! 4399: return(-1); /* and return the error code. */ ! 4400: } ! 4401: } ! 4402: ttimoff(); /* Success, turn off the alarm. */ ! 4403: alarm(xx); /* Restore previous alarm. */ ! 4404: return(0); /* Return good code. */ ! 4405: } ! 4406: ! 4407: /* T T I N L -- Read a record (up to break character) from comm line. */ ! 4408: /* ! 4409: Reads up to "max" characters from the communication line, terminating on: ! 4410: ! 4411: (a) the packet length field if the "turn" argument is zero, or ! 4412: (b) on the packet-end character (eol) if the "turn" argument is nonzero ! 4413: (c) two Ctrl-C's in a row ! 4414: ! 4415: and returns the number of characters read upon success, or if "max" was ! 4416: exceeded or the timeout interval expired before (a) or (b), returns -1. ! 4417: ! 4418: The characters that were input are copied into "dest" with their parity bits ! 4419: stripped if parity was selected. Returns the number of characters read. ! 4420: Characters after the eol are available upon the next call to this function. ! 4421: ! 4422: The idea is to minimize the number of system calls per packet, and also to ! 4423: minimize timeouts. This function is the inner loop of the program and must ! 4424: be as efficient as possible. The current strategy is to use myread(). ! 4425: ! 4426: WARNING: this function calls parchk(), which is defined in another module. ! 4427: Normally, ckutio.c does not depend on code from any other module, but there ! 4428: is an exception in this case because all the other ck?tio.c modules also ! 4429: need to call parchk(), so it's better to have it defined in a common place. ! 4430: ! 4431: Since this function has grown to have its fingers so deeply into the ! 4432: protocol, it is slated for removal: rpack() will take care of everything. ! 4433: */ ! 4434: #ifdef CTRLC ! 4435: #undef CTRLC ! 4436: #endif /* CTRLC */ ! 4437: #define CTRLC '\03' ! 4438: /* ! 4439: We have four different declarations here because: ! 4440: (a) to allow Kermit to be built without the automatic parity sensing feature ! 4441: (b) one of each type for ANSI C, one for non-ANSI. ! 4442: */ ! 4443: int ! 4444: #ifdef PARSENSE ! 4445: #ifdef CK_ANSIC ! 4446: ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn) ! 4447: #else ! 4448: ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start; ! 4449: #endif /* CK_ANSIC */ ! 4450: #else /* not PARSENSE */ ! 4451: #ifdef CK_ANSIC ! 4452: ttinl(CHAR *dest, int max,int timo, CHAR eol) ! 4453: #else ! 4454: ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol; ! 4455: #endif /* __SDTC__ */ ! 4456: #endif /* PARSENSE */ ! 4457: /* ttinl */ { ! 4458: ! 4459: #ifndef MYREAD ! 4460: CHAR ch; ! 4461: #endif /* MYREAD */ ! 4462: #ifdef PARSENSE ! 4463: int pktlen = -1; ! 4464: int lplen = 0; ! 4465: int havelen = 0; ! 4466: #endif /* PARSENSE */ ! 4467: ! 4468: if (ttyfd < 0) return(-1); /* Not open. */ ! 4469: ! 4470: debug(F101,"ttinl max","",max); ! 4471: debug(F101,"ttinl timo","",timo); ! 4472: ! 4473: *dest = '\0'; /* Clear destination buffer */ ! 4474: if (timo < 0) timo = 0; /* Safety */ ! 4475: if (timo) { /* Don't time out if timo == 0 */ ! 4476: int xx; ! 4477: saval = signal(SIGALRM,timerh); /* Enable timer interrupt */ ! 4478: xx = alarm(timo); /* Set it. */ ! 4479: debug(F101,"ttinl alarm","",xx); ! 4480: } ! 4481: if (setjmp(sjbuf)) { /* Timer went off? */ ! 4482: debug(F100,"ttinl timout","",0); /* Get here on timeout. */ ! 4483: /* debug(F110," with",(char *) dest,0); */ ! 4484: ttimoff(); /* Turn off timer */ ! 4485: return(-1); /* and return error code. */ ! 4486: } else { ! 4487: register int i, m, n; /* local variables */ ! 4488: int ccn = 0; ! 4489: #ifdef PARSENSE ! 4490: int flag = 0; ! 4491: ! 4492: debug(F000,"ttinl start","",start); ! 4493: flag = 0; /* Start of packet flag */ ! 4494: #endif /* PARSENSE */ ! 4495: ! 4496: ttpmsk = m = (ttprty) ? 0177 : 0377; /* Set parity stripping mask. */ ! 4497: ! 4498: #ifdef COMMENT ! 4499: /* ! 4500: No longer needed. ! 4501: */ ! 4502: #ifdef SUNX25 ! 4503: if (netconn && (ttnet == NET_SX25)) ! 4504: #ifdef PARSENSE ! 4505: return(x25inl(dest,max,timo,eol,start)); ! 4506: #else ! 4507: return(x25inl(dest,max,timo,eol)); ! 4508: #endif /* PARSENSE */ ! 4509: #endif /* SUNX25 */ ! 4510: #endif /* COMMENT */ ! 4511: ! 4512: /* Now read into destination, stripping parity and looking for the */ ! 4513: /* the packet terminator, and also for two Ctrl-C's typed in a row. */ ! 4514: ! 4515: i = 0; /* Destination index */ ! 4516: debug(F101,"ttinl eol","",eol); ! 4517: ! 4518: #ifdef MYREAD ! 4519: while (i < max-1) { ! 4520: /* debug(F101,"ttinl i","",i); */ ! 4521: if ((n = myread()) < 0) { ! 4522: debug(F101,"ttinl myread failure, n","",n); ! 4523: debug(F101,"ttinl myread errno,","",errno); ! 4524: /* Don't let EINTR break packets. */ ! 4525: if (n == -3 && errno == EINTR && i > 0) { ! 4526: debug(F101,"ttinl myread i","",i); ! 4527: continue; ! 4528: } ! 4529: break; ! 4530: } ! 4531: #else ! 4532: while ((i < max-1) && (n = read(ttyfd, &ch, 1)) > 0) { ! 4533: n = ch; ! 4534: #endif /* MYREAD */ ! 4535: ! 4536: /* debug(F101,"ttinl char","", (n & ttpmsk)); */ ! 4537: ! 4538: #ifdef PARSENSE ! 4539: /* ! 4540: Figure out what the length is supposed to be in case the packet ! 4541: has no terminator (as with Honeywell GCOS-8 Kermit). ! 4542: */ ! 4543: #ifndef xunchar ! 4544: #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */ ! 4545: #endif /* xunchar */ ! 4546: if ((flag == 0) && ((n & 0x7f) == start)) flag = 1; ! 4547: if (flag) dest[i++] = n & ttpmsk; ! 4548: /* ! 4549: If we have not been instructed to wait for a turnaround character, we ! 4550: can go by the packet length field. If turn != 0, we must wait for the ! 4551: end of line (eol) character before returning. ! 4552: */ ! 4553: if (i == 2) { ! 4554: pktlen = xunchar(dest[1]); ! 4555: havelen = (pktlen > 1); ! 4556: debug(F101,"ttinl length","",pktlen); ! 4557: } else if (i == 5 && pktlen == 0) { ! 4558: lplen = xunchar(dest[4]); ! 4559: } else if (i == 6 && pktlen == 0) { ! 4560: pktlen = lplen * 95 + xunchar(dest[5]) + 5; ! 4561: havelen = 1; ! 4562: debug(F101,"ttinl length","",pktlen); ! 4563: } ! 4564: #else ! 4565: dest[i++] = n & ttpmsk; ! 4566: #endif /* PARSENSE */ ! 4567: if ((n & 0x7f) == CTRLC) { /* Check for ^C^C */ ! 4568: if (++ccn > 1) { /* If we got 2 in a row, bail out. */ ! 4569: if (timo) { /* Clear timer. */ ! 4570: ttimoff(); ! 4571: } ! 4572: fprintf(stderr,"^C...\r\n"); /* Echo Ctrl-C */ ! 4573: return(-2); ! 4574: } ! 4575: } else ccn = 0; /* Not ^C, so reset ^C counter, */ ! 4576: ! 4577: #ifdef PARSENSE ! 4578: if (flag == 0) { ! 4579: debug(F101,"ttinl skipping","",n); ! 4580: continue; ! 4581: } ! 4582: #endif /* PARSENSE */ ! 4583: ! 4584: /* Check for end of packet */ ! 4585: ! 4586: if (((n & 0x7f) == eol) ! 4587: #ifdef PARSENSE ! 4588: || (!turn && havelen && (i > pktlen+1)) ! 4589: #endif /* PARSENSE */ ! 4590: ) { ! 4591: #ifndef PARSENSE ! 4592: debug(F101,"ttinl got eol","",eol); ! 4593: dest[i] = '\0'; /* Yes, terminate the string, */ ! 4594: /* debug(F101,"ttinl i","",i); */ ! 4595: #else ! 4596: if ((n & 0x7f) != eol) { ! 4597: debug(F101,"ttinl EOP length","",pktlen); ! 4598: debug(F101,"ttinl i","",i); ! 4599: } else debug(F101,"ttinl got eol","",eol); ! 4600: dest[i] = '\0'; /* Terminate the string, */ ! 4601: /* Parity checked yet? */ ! 4602: if (ttpflg++ == 0 && ttprty == 0) { ! 4603: if ((ttprty = parchk(dest,start,i)) > 0) { /* No, check. */ ! 4604: int j; ! 4605: debug(F101,"ttinl senses parity","",ttprty); ! 4606: debug(F110,"ttinl packet before",dest,0); ! 4607: ttpmsk = 0x7f; ! 4608: for (j = 0; j < i; j++) ! 4609: dest[j] &= 0x7f; /* Strip parity from packet */ ! 4610: debug(F110,"ttinl packet after ",dest,0); ! 4611: } else ttprty = 0; /* restore if parchk error */ ! 4612: } ! 4613: #endif /* PARSENSE */ ! 4614: if (timo) { /* Turn off timer. */ ! 4615: ttimoff(); ! 4616: } ! 4617: debug(F111,"ttinl got", dest,i); ! 4618: return(i); ! 4619: } ! 4620: } /* end of while() */ ! 4621: ttimoff(); ! 4622: return(-1); ! 4623: } ! 4624: } ! 4625: ! 4626: /* T T I N C -- Read a character from the communication line */ ! 4627: /* ! 4628: On success, returns the character that was read, >= 0. ! 4629: On failure, returns -1 or other negative myread error code. ! 4630: */ ! 4631: int ! 4632: ttinc(timo) int timo; { ! 4633: ! 4634: int n = 0; ! 4635: #ifndef MYREAD ! 4636: CHAR ch = 0; ! 4637: #endif /* MYREAD */ ! 4638: ! 4639: if (ttyfd < 0) return(-1); /* Not open. */ ! 4640: if (timo <= 0) { /* Untimed. */ ! 4641: #ifdef MYREAD ! 4642: /* comm line failure returns -1 thru myread, so no &= 0377 */ ! 4643: n = myread(); /* Wait for a character... */ ! 4644: /* debug(F101,"ttinc MYREAD n","",n); */ ! 4645: return(n < 0 ? n : n & ttpmsk); ! 4646: #else ! 4647: while ((n = read(ttyfd,&ch,1)) == 0) /* Wait for a character. */ ! 4648: /* Shouldn't have to loop in ver 5A. */ ! 4649: #ifdef NETCONN ! 4650: if (netconn) { /* Special handling for net */ ! 4651: netclos(); /* If read() returns 0 it means */ ! 4652: netconn = 0; /* the connection has dropped. */ ! 4653: errno = ENOTCONN; ! 4654: return(-2); ! 4655: } ! 4656: #endif /* NETCONN */ ! 4657: ; ! 4658: /* debug(F000,"ttinc","",ch); */ ! 4659: return( (n < 1) ? -3 : (ch & ttpmsk) ); ! 4660: #endif /* MYREAD */ ! 4661: } else { /* Timed read */ ! 4662: int xx; ! 4663: saval = signal(SIGALRM,timerh); /* Set up handler, save old one. */ ! 4664: xx = alarm(timo); /* Set alarm, save old one. */ ! 4665: /* debug(F101,"ttinc alarm","",xx); */ ! 4666: if (setjmp(sjbuf)) { /* Timer expired */ ! 4667: n = -1; /* set flag */ ! 4668: } else { ! 4669: #ifdef MYREAD ! 4670: n = myread(); /* If managing own buffer... */ ! 4671: /* debug(F101,"ttinc myread","",n); */ ! 4672: #else ! 4673: n = read(ttyfd,&ch,1); /* Otherwise call the system. */ ! 4674: /* debug(F101,"ttinc read","",n); */ ! 4675: if (n > 0) ! 4676: n = ch & 255; ! 4677: else ! 4678: n = (n < 0) ? -3 : -2; /* Special return codes. */ ! 4679: #endif /* MYREAD */ ! 4680: } ! 4681: ttimoff(); /* Turn off the timer */ ! 4682: /* #ifdef COMMENT */ ! 4683: if (n == -1) xx -= timo; /* and restore any previous alarm */ ! 4684: if (xx < 0) xx = 0; /* adjusted by timeout interval */ ! 4685: alarm(xx); /* if timer expired. */ ! 4686: /* #endif */ /* COMMENT */ ! 4687: #ifdef NETCONN ! 4688: if (netconn) { ! 4689: if (n == -2) { /* read() returns 0 */ ! 4690: netclos(); /* on network read failure */ ! 4691: netconn = 0; ! 4692: errno = ENOTCONN; ! 4693: } ! 4694: } ! 4695: #endif /* NETCONN */ ! 4696: return( (n < 0) ? n : (n & ttpmsk) ); /* Return masked char or neg. */ ! 4697: } ! 4698: } ! 4699: ! 4700: /* S N D B R K -- Send a BREAK signal of the given duration */ ! 4701: ! 4702: static int ! 4703: #ifdef CK_ANSIC ! 4704: sndbrk(int msec) { /* Argument is milliseconds */ ! 4705: #else ! 4706: sndbrk(msec) int msec; { ! 4707: #endif /* CK_ANSIC */ ! 4708: #ifndef POSIX ! 4709: int x, n; ! 4710: #endif /* POSIX */ ! 4711: ! 4712: #ifdef ANYBSD ! 4713: #define BSDBREAK ! 4714: #endif /* ANYBSD */ ! 4715: ! 4716: #ifdef BSD44 ! 4717: #define BSDBREAK ! 4718: #endif /* BSD44 */ ! 4719: ! 4720: #ifdef COHERENT ! 4721: #define BSDBREAK ! 4722: #endif /* COHERENT */ ! 4723: ! 4724: #ifdef PROVX1 ! 4725: char spd; ! 4726: #endif /* PROVX1 */ ! 4727: ! 4728: debug(F101,"ttsndb ttyfd","",ttyfd); ! 4729: if (ttyfd < 0) return(-1); /* Not open. */ ! 4730: ! 4731: #ifdef NETCONN ! 4732: if (netconn) /* Send network BREAK */ ! 4733: return(netbreak()); ! 4734: #endif /* NETCONN */ ! 4735: ! 4736: if (msec < 1 || msec > 5000) return(-1); /* Bad argument */ ! 4737: ! 4738: #ifdef POSIX /* Easy in POSIX */ ! 4739: return(tcsendbreak(ttyfd,msec / 375)); ! 4740: #else ! 4741: #ifdef PROVX1 ! 4742: gtty(ttyfd,&ttbuf); /* Get current tty flags */ ! 4743: spd = ttbuf.sg_ospeed; /* Save speed */ ! 4744: ttbuf.sg_ospeed = B50; /* Change to 50 baud */ ! 4745: stty(ttyfd,&ttbuf); /* ... */ ! 4746: n = (int)strlen(brnuls); /* Send the right number of nulls */ ! 4747: x = msec / 91; ! 4748: if (x > n) x = n; ! 4749: write(ttyfd,brnuls,n); ! 4750: ttbuf.sg_ospeed = spd; /* Restore speed */ ! 4751: stty(ttyfd,&ttbuf); /* ... */ ! 4752: return(0); ! 4753: #else ! 4754: #ifdef aegis ! 4755: sio_$control((short)ttyfd, sio_$send_break, msec, st); ! 4756: return(0); ! 4757: #else ! 4758: #ifdef BSDBREAK ! 4759: n = FWRITE; /* Flush output queue. */ ! 4760: /* Watch out for int vs long problems in &n arg! */ ! 4761: ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */ ! 4762: if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */ ! 4763: perror("Can't send BREAK"); ! 4764: return(-1); ! 4765: } ! 4766: x = msleep(msec); /* Sleep for so many milliseconds */ ! 4767: if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */ ! 4768: perror("BREAK stuck!!!"); ! 4769: doexit(BAD_EXIT,-1); /* Get out, closing the line. */ ! 4770: /* with bad exit status */ ! 4771: } ! 4772: return(x); ! 4773: #else ! 4774: #ifdef ATTSV ! 4775: /* ! 4776: No way to send a long BREAK in Sys V, so send a bunch of regular ones. ! 4777: (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function, ! 4778: but there's no way for this code to know for sure.) ! 4779: */ ! 4780: x = msec / 275; ! 4781: for (n = 0; n < x; n++) { ! 4782: if (ioctl(ttyfd,TCSBRK,(char *)0) < 0) { ! 4783: perror("Can't send BREAK"); ! 4784: return(-1); ! 4785: } ! 4786: } ! 4787: return(0); ! 4788: #else ! 4789: #ifdef V7 ! 4790: return(genbrk(ttyfd,250)); /* Simulate a BREAK */ ! 4791: #endif /* V7 */ ! 4792: #endif /* BSDBREAK */ ! 4793: #endif /* ATTSV */ ! 4794: #endif /* aegis */ ! 4795: #endif /* PROVX1 */ ! 4796: #endif /* POSIX */ ! 4797: } ! 4798: ! 4799: /* T T S N D B -- Send a BREAK signal */ ! 4800: ! 4801: int ! 4802: ttsndb() { ! 4803: return(sndbrk(275)); ! 4804: } ! 4805: ! 4806: /* T T S N D L B -- Send a Long BREAK signal */ ! 4807: ! 4808: int ! 4809: ttsndlb() { ! 4810: return(sndbrk(1500)); ! 4811: } ! 4812: ! 4813: /* M S L E E P -- Millisecond version of sleep(). */ ! 4814: ! 4815: /* ! 4816: Call with number of milliseconds (thousandths of seconds) to sleep. ! 4817: Intended only for small intervals. For big ones, just use sleep(). ! 4818: Highly system-dependent. ! 4819: Returns 0 always, even if it didn't work. ! 4820: */ ! 4821: ! 4822: /* Define MSLFTIME for systems that must use an ftime() loop. */ ! 4823: #ifdef ANYBSD /* For pre-4.2 BSD versions */ ! 4824: #ifndef BSD4 ! 4825: #define MSLFTIME ! 4826: #endif /* BSD4 */ ! 4827: #endif /* ANYBSD */ ! 4828: ! 4829: #ifdef TOWER1 /* NCR Tower OS 1.0 */ ! 4830: #define MSLFTIME ! 4831: #endif /* TOWER1 */ ! 4832: ! 4833: #ifdef COHERENT /* Coherent */ ! 4834: #ifndef _I386 ! 4835: #define MSLFTIME ! 4836: #endif /* _I386 */ ! 4837: #endif /* COHERENT */ ! 4838: ! 4839: int ! 4840: msleep(m) int m; { ! 4841: ! 4842: #ifndef USLEEP ! 4843: #ifdef SUNOS4 /* Systems that have usleep() */ ! 4844: #define USLEEP ! 4845: #endif /* SUNOS4 */ ! 4846: #ifdef SUN4S5 ! 4847: #define USLEEP ! 4848: #endif /* SUN4S5 */ ! 4849: #ifdef NEXT ! 4850: #define USLEEP ! 4851: #endif /* NEXT*/ ! 4852: #endif /* USLEEP */ ! 4853: ! 4854: #ifdef AIXRS /* RS/6000 can do select() */ ! 4855: #define BSD42 ! 4856: #endif /* AIXRS */ ! 4857: ! 4858: #ifndef SELECT ! 4859: #ifdef BSD44 ! 4860: #define SELECT ! 4861: #endif /* BSD44 */ ! 4862: #ifdef BSD42 ! 4863: #define SELECT ! 4864: #endif /* BSD42 */ ! 4865: #endif /* SELECT */ ! 4866: ! 4867: #ifdef SELECT ! 4868: /* BSD 4.2 & above can do it with select()... */ ! 4869: int t1; ! 4870: if (m <= 0) return(0); ! 4871: if (m >= 1000) { /* Catch big arguments. */ ! 4872: sleep(m/1000); ! 4873: m = m % 1000; ! 4874: if (m < 10) return(0); ! 4875: } ! 4876: if (gettimeofday(&tv, &tz) < 0) return(-1); /* Get current time. */ ! 4877: t1 = tv.tv_sec; /* Seconds */ ! 4878: tv.tv_sec = 0; /* Use select() */ ! 4879: tv.tv_usec = m * 1000L; ! 4880: #ifdef BSD44 ! 4881: select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv ); ! 4882: #else ! 4883: #ifdef BSD43 ! 4884: select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv ); ! 4885: #else ! 4886: select( 0, (int *)0, (int *)0, (int *)0, &tv ); ! 4887: #endif /* BSD43 */ ! 4888: #endif /* BSD44 */ ! 4889: return(0); ! 4890: ! 4891: #else /* Not SELECT */ ! 4892: ! 4893: #ifdef USLEEP ! 4894: /* ! 4895: "This routine is implemented using setitimer(2); it requires eight ! 4896: system calls...". In other words, it might take 5 minutes to sleep ! 4897: for 100 milliseconds... ! 4898: */ ! 4899: if (m >= 1000) { /* Catch big arguments. */ ! 4900: sleep(m/1000); ! 4901: m = m % 1000; ! 4902: if (m < 10) return(0); ! 4903: } ! 4904: usleep((unsigned int)(m * 1000)); ! 4905: return(0); ! 4906: #else ! 4907: #ifdef aegis ! 4908: time_$clock_t dur; ! 4909: ! 4910: dur.c2.high16 = 0; ! 4911: dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */ ! 4912: time_$wait(time_$relative, dur, st); ! 4913: return(0); ! 4914: #else ! 4915: #ifdef PROVX1 ! 4916: if (m <= 0) return(0); ! 4917: sleep(-((m * 60 + 500) / 1000)); ! 4918: return(0); ! 4919: #else ! 4920: #ifdef NAP ! 4921: nap((long)m); ! 4922: return(0); ! 4923: #else ! 4924: #ifdef ATTSV ! 4925: #ifndef BSD44 ! 4926: extern long times(); /* Or #include <times.h> ? */ ! 4927: #endif /* BSD44 */ ! 4928: long t1, t2, tarray[4]; ! 4929: int t3; ! 4930: ! 4931: #ifdef COMMENT ! 4932: /* This better be picked up in ckcdeb.h... */ ! 4933: char *getenv(); ! 4934: #endif /* COMMENT */ ! 4935: char *cp = getenv("HZ"); ! 4936: int CLOCK_TICK; ! 4937: int hertz; ! 4938: ! 4939: if (cp && (hertz = atoi(cp))) { ! 4940: CLOCK_TICK = 1000 / hertz; ! 4941: } else { /* probably single user mode */ ! 4942: #ifdef HZ ! 4943: CLOCK_TICK = 1000 / HZ; ! 4944: #else ! 4945: static warned = 0; ! 4946: /* HZ always exists in, for instance, SCO Xenix, so you don't have to ! 4947: * make special #ifdefs for XENIX here, like in ver 4F. Also, if you ! 4948: * have Xenix, you have should have nap(), so the best is to use -DNAP ! 4949: * in the makefile. Most systems have HZ. ! 4950: */ ! 4951: CLOCK_TICK = 17; /* 1/60 sec */ ! 4952: if (!warned) { ! 4953: printf("warning: environment variable HZ bad... using HZ=%d\r\n", ! 4954: 1000 / CLOCK_TICK); ! 4955: warned = 1; ! 4956: } ! 4957: #endif /* !HZ */ ! 4958: } ! 4959: ! 4960: if (m <= 0) return(0); ! 4961: if (m >= 1000) { /* Catch big arguments. */ ! 4962: sleep(m/1000); ! 4963: m = m % 1000; ! 4964: if (m < 10) return(0); ! 4965: } ! 4966: if ((t1 = times(tarray)) < 0) return(-1); ! 4967: while (1) { ! 4968: if ((t2 = times(tarray)) < 0) return(-1); ! 4969: t3 = ((int)(t2 - t1)) * CLOCK_TICK; ! 4970: if (t3 > m) return(t3); ! 4971: } ! 4972: #else /* Not ATTSV */ ! 4973: #ifdef MSLFTIME /* Use ftime() loop... */ ! 4974: int t1, t3 = 0; ! 4975: if (m <= 0) return(0); ! 4976: if (m >= 1000) { /* Catch big arguments. */ ! 4977: sleep(m/1000); ! 4978: m = m % 1000; ! 4979: if (m < 10) return(0); ! 4980: } ! 4981: if (ftime(&ftp) < 0) return(-1); /* Get base time. */ ! 4982: t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm; ! 4983: while (1) { ! 4984: ftime(&ftp); /* Get current time and compare. */ ! 4985: t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1; ! 4986: if (t3 > m) return(0); ! 4987: } ! 4988: #else ! 4989: /* This includes true POSIX, which has no way to do this. */ ! 4990: if (m >= 1000) { /* Catch big arguments. */ ! 4991: sleep(m/1000); ! 4992: m = m % 1000; ! 4993: if (m < 10) return(0); ! 4994: } ! 4995: if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */ ! 4996: return(0); ! 4997: #endif /* MSLFTIME */ ! 4998: #endif /* ATTSV */ ! 4999: #endif /* NAP */ ! 5000: #endif /* PROVX1 */ ! 5001: #endif /* aegis */ ! 5002: #endif /* SELECT */ ! 5003: #endif /* USLEEP */ ! 5004: } ! 5005: ! 5006: /* R T I M E R -- Reset elapsed time counter */ ! 5007: ! 5008: VOID ! 5009: rtimer() { ! 5010: tcount = time( (time_t *) 0 ); ! 5011: } ! 5012: ! 5013: ! 5014: /* G T I M E R -- Get current value of elapsed time counter in seconds */ ! 5015: ! 5016: int ! 5017: gtimer() { ! 5018: int x; ! 5019: x = (int) (time( (time_t *) 0 ) - tcount); ! 5020: debug(F101,"gtimer","",x); ! 5021: return( (x < 0) ? 0 : x ); ! 5022: } ! 5023: ! 5024: ! 5025: /* Z T I M E -- Return date/time string */ ! 5026: ! 5027: VOID ! 5028: ztime(s) char **s; { ! 5029: ! 5030: #undef ZTIMEV7 /* Which systems need to use */ ! 5031: #ifdef COHERENT /* old UNIX Version 7 way... */ ! 5032: #define ZTIMEV7 ! 5033: #endif /* COHERENT */ ! 5034: #ifdef TOWER1 ! 5035: #define ZTIMEV7 ! 5036: #endif /* TOWER1 */ ! 5037: #ifdef ANYBSD ! 5038: #ifndef BSD42 ! 5039: #define ZTIMEV7 ! 5040: #endif /* BSD42 */ ! 5041: #endif /* ANYBSD */ ! 5042: #ifdef V7 ! 5043: #ifndef MINIX ! 5044: #define ZTIMEV7 ! 5045: #endif /* MINIX */ ! 5046: #endif /* V7 */ ! 5047: #ifdef POSIX ! 5048: #define ZTIMEV7 ! 5049: #endif /* POSIX */ ! 5050: ! 5051: #ifdef ATTSV /* AT&T way */ ! 5052: /* extern long time(); */ /* Theoretically these should */ ! 5053: char *ctime(); /* already been dcl'd in <time.h> */ ! 5054: long clock_storage; ! 5055: clock_storage = time( (long *) 0 ); ! 5056: *s = ctime( &clock_storage ); ! 5057: #else ! 5058: #ifdef PROVX1 /* Venix 1.0 way */ ! 5059: int utime[2]; ! 5060: time(utime); ! 5061: *s = ctime(utime); ! 5062: #else ! 5063: #ifdef BSD42 /* 4.2BSD way */ ! 5064: char *asctime(); ! 5065: struct tm *localtime(); ! 5066: struct tm *tp; ! 5067: gettimeofday(&tv, &tz); ! 5068: time(&tv.tv_sec); ! 5069: tp = localtime(&tv.tv_sec); ! 5070: *s = asctime(tp); ! 5071: #else ! 5072: #ifdef MINIX /* MINIX way */ ! 5073: #ifdef COMMENT ! 5074: extern long time(); /* Already got these from <time.h> */ ! 5075: extern char *ctime(); ! 5076: #endif /* COMMENT */ ! 5077: time_t utime[2]; ! 5078: time(utime); ! 5079: *s = ctime(utime); ! 5080: #else ! 5081: #ifdef ZTIMEV7 /* The regular way */ ! 5082: char *asctime(); ! 5083: struct tm *localtime(); ! 5084: struct tm *tp; ! 5085: long xclock; ! 5086: time(&xclock); ! 5087: tp = localtime(&xclock); ! 5088: *s = asctime(tp); ! 5089: #else /* Catch-all for others... */ ! 5090: *s = "Ddd Mmm 00 00:00:00 0000\n" /* Return dummy in asctime() format */ ! 5091: #endif /* ZTIMEV7 */ ! 5092: #endif /* MINIX */ ! 5093: #endif /* BSD42 */ ! 5094: #endif /* PROVX1 */ ! 5095: #endif /* SVORPOSIX */ ! 5096: } ! 5097: ! 5098: /* C O N G M -- Get console terminal modes. */ ! 5099: ! 5100: /* ! 5101: Saves initial console mode, and establishes variables for switching ! 5102: between current (presumably normal) mode and other modes. ! 5103: Should be called when program starts, but only after establishing ! 5104: whether program is in the foreground or background. ! 5105: Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error. ! 5106: */ ! 5107: int ! 5108: congm() { ! 5109: int fd; ! 5110: if (backgrd || !isatty(0)) { /* If in background. */ ! 5111: cgmf = -1; /* Don't bother, modes are garbage. */ ! 5112: return(-1); ! 5113: } ! 5114: if (cgmf > 0) return(0); /* Already did this. */ ! 5115: debug(F100,"congm getting modes","",0); /* Need to do it. */ ! 5116: #ifdef aegis ! 5117: ios_$inq_type_uid(ios_$stdin, conuid, st); ! 5118: if (st.all != status_$ok) { ! 5119: fprintf(stderr, "problem getting stdin objtype: "); ! 5120: error_$print(st); ! 5121: } ! 5122: concrp = (conuid == mbx_$uid); ! 5123: conbufn = 0; ! 5124: #endif /* aegis */ ! 5125: ! 5126: if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */ ! 5127: fprintf(stderr,"Error opening %s\n", CTTNAM); ! 5128: perror("congm"); ! 5129: return(-1); ! 5130: } ! 5131: #ifdef BSD44ORPOSIX ! 5132: if (tcgetattr(fd,&ccold) < 0) return(-1); ! 5133: if (tcgetattr(fd,&cccbrk) < 0) return(-1); ! 5134: if (tcgetattr(fd,&ccraw) < 0) return(-1); ! 5135: #else ! 5136: #ifdef ATTSV ! 5137: if (ioctl(fd,TCGETA,&ccold) < 0) return(-1); ! 5138: if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1); ! 5139: if (ioctl(fd,TCGETA,&ccraw) < 0) return(-1); ! 5140: #ifdef VXVE ! 5141: cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */ ! 5142: if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1); ! 5143: ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */ ! 5144: if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1); ! 5145: #endif /* VXVE */ ! 5146: #else ! 5147: if (gtty(fd,&ccold) < 0) return(-1); ! 5148: if (gtty(fd,&cccbrk) < 0) return(-1); ! 5149: if (gtty(fd,&ccraw) < 0) return(-1); ! 5150: #endif /* ATTSV */ ! 5151: #endif /* BSD44ORPOSIX */ ! 5152: #ifdef sony_news /* Sony NEWS */ ! 5153: if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */ ! 5154: perror("congm error getting Kanji mode"); ! 5155: debug(F101,"congm error getting Kanji mode","",0); ! 5156: km_con = -1; /* Make sure this stays undefined. */ ! 5157: return(-1); ! 5158: } ! 5159: #endif /* sony_news */ ! 5160: close(fd); ! 5161: cgmf = 1; /* Flag that we got them. */ ! 5162: return(1); ! 5163: } ! 5164: ! 5165: ! 5166: /* C O N C B -- Put console in cbreak mode. */ ! 5167: ! 5168: /* Returns 0 if ok, -1 if not */ ! 5169: ! 5170: int ! 5171: #ifdef CK_ANSIC ! 5172: concb(char esc) ! 5173: #else ! 5174: concb(esc) char esc; ! 5175: #endif /* CK_ANSIC */ ! 5176: /* concb */ { ! 5177: int x; ! 5178: if (cgmf < 1) return(0); /* Console modes not available yet */ ! 5179: if (ttfdflg && ttyfd >= 0 && ttyfd < 3) ! 5180: return(0); ! 5181: debug(F101,"concb backgrd","",backgrd); ! 5182: if (!isatty(0)) return(0); /* Only for real ttys */ ! 5183: debug(F100,"concb isatty","",0); ! 5184: if (backgrd) return(0); /* Do nothing if in background. */ ! 5185: escchr = esc; /* Make this available to other fns */ ! 5186: ckxech = 1; /* Program can echo characters */ ! 5187: #ifdef aegis ! 5188: conbufn = 0; ! 5189: if (concrp) return(write(1, "\035\002", 2)); ! 5190: if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);} ! 5191: #endif ! 5192: #ifndef SVORPOSIX /* BSD, V7, etc */ ! 5193: cccbrk.sg_flags |= CBREAK; /* Set to character wakeup, */ ! 5194: cccbrk.sg_flags &= ~ECHO; /* no echo. */ ! 5195: x = stty(0,&cccbrk); ! 5196: #else /* Sys V and POSIX */ ! 5197: cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN); ! 5198: #ifndef VINTR ! 5199: cccbrk.c_cc[0] = 003; /* interrupt char is control-c */ ! 5200: #else ! 5201: cccbrk.c_cc[VINTR] = 003; ! 5202: #endif /* VINTR */ ! 5203: #ifndef VQUIT ! 5204: cccbrk.c_cc[1] = escchr; /* escape during packet modes */ ! 5205: #else ! 5206: cccbrk.c_cc[VQUIT] = escchr; ! 5207: #endif /* VQUIT */ ! 5208: #ifndef VEOF ! 5209: cccbrk.c_cc[4] = 1; ! 5210: #else ! 5211: #ifdef VMIN ! 5212: cccbrk.c_cc[VMIN] = 1; ! 5213: #endif /* VMIN */ ! 5214: #endif /* VEOF */ ! 5215: #ifdef ZILOG ! 5216: cccbrk.c_cc[5] = 0; ! 5217: #else ! 5218: #ifndef VEOL ! 5219: cccbrk.c_cc[5] = 1; ! 5220: #else ! 5221: #ifdef VTIME ! 5222: cccbrk.c_cc[VTIME] = 1; ! 5223: #endif /* VTIME */ ! 5224: #endif /* VEOL */ ! 5225: #endif /* ZILOG */ ! 5226: #ifdef BSD44ORPOSIX /* Set new modes */ ! 5227: x = tcsetattr(0,TCSADRAIN,&cccbrk); ! 5228: #else /* ATTSV */ /* or the POSIX way */ ! 5229: x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */ ! 5230: #endif /* BSD44ORPOSIX */ ! 5231: #endif /* SVORPOSIX */ ! 5232: ! 5233: #ifndef aegis ! 5234: #ifndef NOSETBUF ! 5235: if (x > -1) setbuf(stdout,NULL); /* Make console unbuffered. */ ! 5236: #endif /* NOSETBUF */ ! 5237: #endif /* aegis */ ! 5238: ! 5239: #ifdef V7 ! 5240: #ifndef MINIX ! 5241: if (kmem[CON] < 0) { ! 5242: qaddr[CON] = initrawq(0); ! 5243: if((kmem[CON] = open("/dev/kmem", 0)) < 0) { ! 5244: fprintf(stderr, "Can't read /dev/kmem in concb.\n"); ! 5245: perror("/dev/kmem"); ! 5246: exit(1); ! 5247: } ! 5248: } ! 5249: #endif /* MINIX */ ! 5250: #endif /* V7 */ ! 5251: debug(F101,"concb returns","",x); ! 5252: return(x); ! 5253: } ! 5254: ! 5255: /* C O N B I N -- Put console in binary mode */ ! 5256: ! 5257: /* Returns 0 if ok, -1 if not */ ! 5258: ! 5259: int ! 5260: #ifdef CK_ANSIC ! 5261: conbin(char esc) ! 5262: #else ! 5263: conbin(esc) char esc; ! 5264: #endif /* CK_ANSIC */ ! 5265: /* conbin */ { ! 5266: if (!isatty(0)) return(0); /* only for real ttys */ ! 5267: congm(); /* Get modes if necessary. */ ! 5268: debug(F100,"conbin","",0); ! 5269: escchr = esc; /* Make this available to other fns */ ! 5270: ckxech = 1; /* Program can echo characters */ ! 5271: #ifdef aegis ! 5272: conbufn = 0; ! 5273: if (concrp) return(write(1, "\035\002", 2)); ! 5274: if (conuid == input_pad_$uid) ! 5275: pad_$raw(ios_$stdin, st); ! 5276: return(0) ! 5277: #endif /* aegis */ ! 5278: ! 5279: #ifdef SVORPOSIX ! 5280: ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN); ! 5281: ccraw.c_iflag |= (BRKINT|IGNPAR); ! 5282: #ifdef ATTSV ! 5283: #ifdef BSD44 ! 5284: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF ! 5285: |INPCK|ISTRIP); ! 5286: #else ! 5287: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF ! 5288: |INPCK|ISTRIP); ! 5289: #endif /* BSD44 */ ! 5290: #else /* POSIX */ ! 5291: ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP); ! 5292: #endif /* ATTSV */ ! 5293: ccraw.c_oflag &= ~OPOST; ! 5294: #ifdef ATT7300 ! 5295: ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL; ! 5296: #endif /* ATT7300 */ ! 5297: /*** Kermit used to put the console in 8-bit raw mode, but some users have ! 5298: *** pointed out that this should not be done, since some sites actually ! 5299: *** use terminals with parity settings on their Unix systems, and if we ! 5300: *** override the current settings and stop doing parity, then their terminals ! 5301: *** will display blotches for characters whose parity is wrong. Therefore, ! 5302: *** the following two lines are commented out (Larry Afrin, Clemson U): ! 5303: *** ! 5304: *** ccraw.c_cflag &= ~(PARENB|CSIZE); ! 5305: *** ccraw.c_cflag |= (CS8|CREAD); ! 5306: *** ! 5307: *** Sys III/V sites that have trouble with this can restore these lines. ! 5308: ***/ ! 5309: #ifndef VINTR ! 5310: ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */ ! 5311: #else ! 5312: ccraw.c_cc[VINTR] = 003; ! 5313: #endif /* VINTR */ ! 5314: #ifndef VQUIT ! 5315: ccraw.c_cc[1] = escchr; /* Escape during packet mode */ ! 5316: #else ! 5317: ccraw.c_cc[VQUIT] = escchr; ! 5318: #endif /* VQUIT */ ! 5319: #ifndef VEOF ! 5320: ccraw.c_cc[4] = 1; ! 5321: #else ! 5322: #ifdef VMIN ! 5323: ccraw.c_cc[VMIN] = 1; ! 5324: #endif ! 5325: #endif /* VEOF */ ! 5326: ! 5327: #ifdef ZILOG ! 5328: ccraw.c_cc[5] = 0; ! 5329: #else ! 5330: #ifndef VEOL ! 5331: ccraw.c_cc[5] = 1; ! 5332: #else ! 5333: #ifdef VTIME ! 5334: ccraw.c_cc[VTIME] = 1; ! 5335: #endif /* VTIME */ ! 5336: #endif /* VEOL */ ! 5337: #endif /* ZILOG */ ! 5338: ! 5339: #ifdef BSD44ORPOSIX ! 5340: return(tcsetattr(0,TCSADRAIN,&ccraw)); ! 5341: #else ! 5342: return(ioctl(0,TCSETAW,&ccraw)); /* Set new modes. */ ! 5343: #endif /* BSD44ORPOSIX */ ! 5344: ! 5345: #else /* Berkeley, etc. */ ! 5346: ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF (ha) */ ! 5347: ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */ ! 5348: return(stty(0,&ccraw)); ! 5349: #endif /* SVORPOSIX */ ! 5350: } ! 5351: ! 5352: ! 5353: /* C O N R E S -- Restore the console terminal */ ! 5354: ! 5355: int ! 5356: conres() { ! 5357: debug(F101,"conres cgmf","",cgmf); ! 5358: if (cgmf < 1) return(0); /* Do nothing if modes unchanged */ ! 5359: if (!isatty(0)) return(0); /* only for real ttys */ ! 5360: debug(F100,"conres isatty ok","",0); ! 5361: ckxech = 0; /* System should echo chars */ ! 5362: ! 5363: #ifdef aegis ! 5364: conbufn = 0; ! 5365: if (concrp) return(write(1, "\035\001", 2)); ! 5366: if (conuid == input_pad_$uid) ! 5367: pad_$cooked(ios_$stdin, st); ! 5368: return(0); ! 5369: #endif /* aegis */ ! 5370: ! 5371: #ifdef BSD44ORPOSIX ! 5372: debug(F100,"conres restoring tcsetattr","",0); ! 5373: return(tcsetattr(0,TCSADRAIN,&ccold)); ! 5374: #else ! 5375: #ifdef ATTSV ! 5376: debug(F100,"conres restoring ioctl","",0); ! 5377: return(ioctl(0,TCSETAW,&ccold)); ! 5378: #else /* BSD, V7, and friends */ ! 5379: #ifdef sony_news /* Sony NEWS */ ! 5380: if (km_con != -1) ! 5381: ioctl(0,TIOCKSET,&km_con); /* Restore console Kanji mode */ ! 5382: #endif /* sony_news */ ! 5383: msleep(300); ! 5384: debug(F100,"conres restoring stty","",0); ! 5385: return(stty(0,&ccold)); ! 5386: #endif /* ATTSV */ ! 5387: #endif /* BSD44ORPOSIX */ ! 5388: } ! 5389: ! 5390: /* C O N O C -- Output a character to the console terminal */ ! 5391: ! 5392: int ! 5393: #ifdef CK_ANSIC ! 5394: conoc(char c) ! 5395: #else ! 5396: conoc(c) char c; ! 5397: #endif /* CK_ANSIC */ ! 5398: /* conoc */ { ! 5399: return(write(1,&c,1)); ! 5400: } ! 5401: ! 5402: /* C O N X O -- Write x characters to the console terminal */ ! 5403: ! 5404: int ! 5405: conxo(x,s) int x; char *s; { ! 5406: return(write(1,s,x)); ! 5407: } ! 5408: ! 5409: /* C O N O L -- Write a line to the console terminal */ ! 5410: ! 5411: int ! 5412: conol(s) char *s; { ! 5413: int len; ! 5414: len = (int)strlen(s); ! 5415: return(write(1,s,len)); ! 5416: } ! 5417: ! 5418: /* C O N O L A -- Write an array of lines to the console terminal */ ! 5419: ! 5420: int ! 5421: conola(s) char *s[]; { ! 5422: int i; ! 5423: for (i=0 ; *s[i] ; i++) if (conol(s[i]) < 0) return(-1);; ! 5424: return(0); ! 5425: } ! 5426: ! 5427: /* C O N O L L -- Output a string followed by CRLF */ ! 5428: ! 5429: int ! 5430: conoll(s) char *s; { ! 5431: conol(s); ! 5432: return(write(1,"\r\n",2)); ! 5433: } ! 5434: ! 5435: /* C O N C H K -- Return how many characters available at console */ ! 5436: ! 5437: int ! 5438: conchk() { ! 5439: int x; PEEKTYPE n; ! 5440: ! 5441: if (backgrd || !isatty(0)) return(0); ! 5442: #ifdef PROVX1 ! 5443: x = ioctl(0, TIOCQCNT, &ttbuf); ! 5444: n = ttbuf.sg_ispeed & 0377; ! 5445: return((x < 0) ? 0 : n); ! 5446: #else ! 5447: #ifdef aegis ! 5448: if (conbufn > 0) return(conbufn); /* use old count if nonzero */ ! 5449: ! 5450: /* read in more characters */ ! 5451: conbufn = ios_$get(ios_$stdin, ! 5452: ios_$cond_opt, conbuf, (long)sizeof(conbuf), st); ! 5453: if (st.all != status_$ok) conbufn = 0; ! 5454: conbufp = conbuf; ! 5455: return(conbufn); ! 5456: #else ! 5457: #ifdef V7 ! 5458: #ifdef MINIX ! 5459: return(0); ! 5460: #else ! 5461: lseek(kmem[CON], (long) qaddr[CON], 0); ! 5462: x = read(kmem[CON], &n, sizeof(int)); ! 5463: return((x == sizeof(int))? n: 0); ! 5464: #endif /* MINIX */ ! 5465: #else ! 5466: #ifdef SVORPOSIX ! 5467: if (conesc) { /* Escape typed */ ! 5468: debug(F100,"conchk returns conesc","",conesc); ! 5469: conesc = 0; ! 5470: signal(SIGQUIT,esctrp); /* Restore escape */ ! 5471: return(1); ! 5472: } ! 5473: return(0); ! 5474: #else ! 5475: #ifdef C70 ! 5476: if (conesc) { /* Escape typed */ ! 5477: conesc = 0; ! 5478: signal(SIGQUIT,esctrp); /* Restore escape */ ! 5479: return(1); ! 5480: } ! 5481: return(0); ! 5482: #else ! 5483: #ifdef FIONREAD ! 5484: /* ! 5485: Reportedly, this can cause C-Kermit to be suspended on certain OS's, ! 5486: such as Olivetti X/OS, when called if Kermit is really in the background. ! 5487: Hence the change at the top of this routine to return 0 if the backgrd ! 5488: flag is set. ! 5489: */ ! 5490: x = ioctl(0, FIONREAD, &n); /* BSD and maybe some others */ ! 5491: debug(F101,"conchk","",n); ! 5492: return((x < 0) ? 0 : n); ! 5493: #else ! 5494: return(0); /* Others can't do. */ ! 5495: #endif ! 5496: #endif ! 5497: #endif ! 5498: #endif ! 5499: #endif ! 5500: #endif ! 5501: } ! 5502: ! 5503: /* C O N I N C -- Get a character from the console */ ! 5504: /* ! 5505: Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking ! 5506: read. Upon success, returns the character. Upon failure, returns -1. ! 5507: A timed read that does not complete within the timeout period returns -1. ! 5508: */ ! 5509: int ! 5510: coninc(timo) int timo; { ! 5511: int n = 0; CHAR ch; ! 5512: int xx; ! 5513: #ifdef aegis /* Apollo Aegis only... */ ! 5514: debug(F101,"coninc timo","",timo); ! 5515: fflush(stdout); ! 5516: if (conchk() > 0) { ! 5517: --conbufn; ! 5518: return(*conbufp++ & 0377); ! 5519: } ! 5520: #endif /* aegis */ ! 5521: ! 5522: if (timo <= 0 ) { /* Untimed, blocking read. */ ! 5523: while (1) { /* Keep trying till we get one. */ ! 5524: n = read(0, &ch, 1); /* Read a character. */ ! 5525: if (n == 0) continue; /* Shouldn't happen. */ ! 5526: if (n > 0) /* If read was successful, */ ! 5527: return(ch & 0377); /* return the character. */ ! 5528: ! 5529: /* Come here if read() returned an error. */ ! 5530: ! 5531: debug(F101, "coninc(0) errno","",errno); /* Log the error. */ ! 5532: #ifdef SVORPOSIX ! 5533: #ifdef CIE /* CIE Regulus has no EINTR symbol? */ ! 5534: #ifndef EINTR ! 5535: #define EINTR 4 ! 5536: #endif /* EINTR */ ! 5537: #endif /* CIE */ ! 5538: /* ! 5539: This routine is used for several different purposes. In CONNECT mode, it is ! 5540: used to do an untimed, blocking read from the keyboard in the lower CONNECT ! 5541: fork. During local-mode file transfer, it reads a character from the ! 5542: console to interrupt the file transfer (like A for a status report, X to ! 5543: cancel a file, etc). Obviously, we don't want the reads in the latter case ! 5544: to be blocking, or the file transfer would stop until the user typed ! 5545: something. Unfortunately, System V does not allow the console device input ! 5546: buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is ! 5547: used instead. During local-mode file transfer, the SIGQUIT signal is armed ! 5548: and trapped by esctrp(), and this routine pretends to have read the quit ! 5549: character from the keyboard normally. But, kludge or no kludge, the read() ! 5550: issued by this command, under System V only, can fail if a signal -- ANY ! 5551: signal -- is caught while the read is pending. This can occur not only when ! 5552: the user types the quit character, but also during telnet negotiations, when ! 5553: the lower CONNECT fork signals the upper one about an echoing mode change. ! 5554: When this happens, we have to post the read() again. This is apparently not ! 5555: a problem in BSD-based UNIX versions. ! 5556: */ ! 5557: if (errno == EINTR) /* Read interrupted. */ ! 5558: if (conesc) { /* If by SIGQUIT, */ ! 5559: conesc = 0; /* the conesc variable is set, */ ! 5560: return(escchr); /* so return the escape character. */ ! 5561: } else continue; /* By other signal, try again. */ ! 5562: #else ! 5563: /* ! 5564: This might be dangerous, but let's do this on non-System V versions too, ! 5565: since at least one SunOS 4.1.2 user complains of immediate disconnections ! 5566: upon first making a TELNET connection. ! 5567: */ ! 5568: if (errno == EINTR) /* Read interrupted. */ ! 5569: continue; ! 5570: #endif /* SVORPOSIX */ ! 5571: return(-1); /* Error */ ! 5572: } ! 5573: } ! 5574: ! 5575: if (timo <= 0) ! 5576: /* This should never happen */ ! 5577: debug(F100,"coninc HORRIBLE ERROR","",0); ! 5578: ! 5579: /* Timed read... */ ! 5580: ! 5581: saval = signal(SIGALRM,timerh); /* Set up timeout handler. */ ! 5582: xx = alarm(timo); /* Set the alarm. */ ! 5583: debug(F101,"coninc alarm","",xx); ! 5584: if (setjmp(sjbuf)) /* The read() timed out. */ ! 5585: n = -2; /* Code for timeout. */ ! 5586: else ! 5587: n = read(0, &ch, 1); ! 5588: ttimoff(); /* Turn off timer */ ! 5589: if (n > 0) /* Got character OK. */ ! 5590: return(ch & 0377); /* Return it. */ ! 5591: ! 5592: /* ! 5593: Read returned an error. Same deal as above, but without the loop. ! 5594: */ ! 5595: debug(F101, "coninc(timo) n","",n); ! 5596: debug(F101, "coninc(timo) errno","",errno); ! 5597: #ifdef SVORPOSIX ! 5598: if (n == -1 && errno == EINTR && conesc != 0) { ! 5599: conesc = 0; ! 5600: return(escchr); /* User entered escape character. */ ! 5601: } else /* n == 0 shouldn't happen. */ ! 5602: #endif /* SVORPOSIX */ ! 5603: return(-1); ! 5604: } ! 5605: ! 5606: /* C O N G K S -- Console Get Keyboard Scancode */ ! 5607: ! 5608: #ifndef congks ! 5609: /* ! 5610: This function needs to be filled in with the various system-dependent ! 5611: system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full ! 5612: keyboard scan code. For now, it's a dummy. ! 5613: */ ! 5614: int ! 5615: congks(timo) int timo; { ! 5616: return(coninc(timo)); ! 5617: } ! 5618: #endif /* congks */ ! 5619: ! 5620: #ifdef ATT7300 ! 5621: ! 5622: /* A T T D I A L -- Dial up the remote system using internal modem ! 5623: * Purpose: to open and dial a number on the internal modem available on the ! 5624: * ATT7300 UNIX PC. Written by Joe Doupnik. Superceeds version written by ! 5625: * Richard E. Hill, Dickinson, TX. which employed dial(3c). ! 5626: * Uses information in <sys/phone.h> and our status int attmodem. ! 5627: */ ! 5628: attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; { ! 5629: char *telnum; ! 5630: int ttclos(); ! 5631: ! 5632: attmodem &= ~ISMODEM; /* modem not in use yet */ ! 5633: /* Ensure O_NDELAY is set, else i/o traffic hangs */ ! 5634: /* We turn this flag off once the dial is complete */ ! 5635: fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY); ! 5636: ! 5637: /* Condition line, check availability & DATA mode, turn on speaker */ ! 5638: if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) { ! 5639: printf("cannot access phone\n"); ! 5640: ttclos(0); ! 5641: return (-2); ! 5642: } ! 5643: ioctl(ttyfd,PIOCGETP,&dialer); /* get phone dialer parameters */ ! 5644: ! 5645: if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */ ! 5646: printf(" Should not dial with modem in VOICE mode.\n"); ! 5647: printf(" Exit Kermit, switch to DATA and retry call.\n"); ! 5648: ttclos(0); ! 5649: return (-2); ! 5650: } ! 5651: #ifdef ATTTONED /* Old way, tone dialing only. */ ! 5652: dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */ ! 5653: dialer.c_lineparam &= ~PULSE; /* not with pulses. */ ! 5654: #else ! 5655: /* Leave current pulse/tone state alone. */ ! 5656: /* But what about DATA? Add it back if you have trouble. */ ! 5657: /* sys/phone says you get DATA automatically by opening device RDWR */ ! 5658: #endif ! 5659: dialer.c_waitdialtone = 5; /* wait 5 sec for dialtone */ ! 5660: #ifdef COMMENT ! 5661: dialer.c_feedback = SPEAKERON|NORMSPK|RINGON; /* control speaker */ ! 5662: #else ! 5663: /* sys/phone says RINGON used only for incoming voice calls */ ! 5664: dialer.c_feedback &= ~(SOFTSPK|LOUDSPK); ! 5665: dialer.c_feedback |= SPEAKERON|NORMSPK; ! 5666: #endif ! 5667: dialer.c_waitflash = 500; /* 0.5 sec flash hook */ ! 5668: if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) { /* set phone parameters */ ! 5669: printf("Cannot set modem characteristics\n"); ! 5670: ttclos(0); ! 5671: return (-2); ! 5672: } ! 5673: ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */ ! 5674: ! 5675: #ifdef COMMENT ! 5676: fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \ ! 5677: line_status:%o feedback:%o\n", ! 5678: dialer.c_lineparam, dialer.c_waitdialtone, ! 5679: dialer.c_linestatus, dialer.c_feedback); ! 5680: #endif ! 5681: ! 5682: attmodem |= ISMODEM; /* modem is now in-use */ ! 5683: sleep(1); ! 5684: for (telnum = telnbr; *telnum != '\0'; telnum++) /* dial number */ ! 5685: #ifdef ATTTONED ! 5686: /* Tone dialing only */ ! 5687: if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) { ! 5688: perror("Error in dialing"); ! 5689: ttclos(0); ! 5690: return(-2); ! 5691: } ! 5692: #else /* Allow Pulse or Tone dialing */ ! 5693: switch (*telnum) { ! 5694: case 't': case 'T': case '%': /* Tone dialing requested */ ! 5695: dialer.c_lineparam |= DTMF; ! 5696: dialer.c_lineparam &= ~PULSE; ! 5697: if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) { ! 5698: printf("Cannot set modem to tone dialing\n"); ! 5699: ttclos(0); ! 5700: return(-2); ! 5701: } ! 5702: break; ! 5703: case 'd': case 'D': case 'p': case 'P': case '^': ! 5704: dialer.c_lineparam |= PULSE; ! 5705: dialer.c_lineparam &= ~DTMF; ! 5706: if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) { ! 5707: printf("Cannot set modem to pulse dialing\n"); ! 5708: ttclos(0); ! 5709: return(-2); ! 5710: } ! 5711: break; ! 5712: default: ! 5713: if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) { ! 5714: perror("Dialing error"); ! 5715: ttclos(0); ! 5716: return(-2); ! 5717: } ! 5718: break; ! 5719: } ! 5720: #endif ! 5721: ! 5722: ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */ ! 5723: do { /* wait for modems to Connect */ ! 5724: if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */ ! 5725: perror("Cannot get modems to connect"); ! 5726: ttclos(0); ! 5727: return(-2); ! 5728: } ! 5729: } while ((dialer.c_linestatus & MODEMCONNECTED) == 0); ! 5730: /* Turn off O_NDELAY flag now. */ ! 5731: fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY); ! 5732: signal(SIGHUP, ttclos); /* hangup on loss of carrier */ ! 5733: return(0); /* return success */ ! 5734: } ! 5735: ! 5736: /* ! 5737: Offgetty, ongetty functions. These function get the 'getty(1m)' off ! 5738: and restore it to the indicated line. Shell's return codes are: ! 5739: 0: Can't do it. Probably a user logged on. ! 5740: 1: No need. No getty on that line. ! 5741: 2: Done, you should restore the getty when you're done. ! 5742: DOGETY System(3), however, returns them as 0, 256, 512, respectively. ! 5743: Thanks to Kevin O'Gorman, Anarm Software Systems. ! 5744: ! 5745: getoff.sh looks like: geton.sh looks like: ! 5746: setgetty $1 0 setgetty $1 1 ! 5747: err=$? exit $? ! 5748: sleep 2 ! 5749: exit $err ! 5750: */ ! 5751: ! 5752: /* O F F G E T T Y -- Turn off getty(1m) for the communications tty line ! 5753: * and get status so it can be restarted after the line is hung up. ! 5754: */ ! 5755: int ! 5756: offgetty(ttname) char *ttname; { ! 5757: char temp[30]; ! 5758: while (*ttname != '\0') ttname++; /* seek terminator of path */ ! 5759: ttname -= 3; /* get last 3 chars of name */ ! 5760: sprintf(temp,"/usr/bin/getoff.sh %s",ttname); ! 5761: return(zsyscmd(temp)); ! 5762: } ! 5763: ! 5764: /* O N G E T T Y -- Turn on getty(1m) for the communications tty line */ ! 5765: ! 5766: int ! 5767: ongetty(ttname) char *ttname; { ! 5768: char temp[30]; ! 5769: while (*ttname != '\0') ttname++; /* comms tty path name */ ! 5770: ttname -= 3; ! 5771: sprintf(temp,"/usr/bin/geton.sh %s",ttname); ! 5772: return(zsyscmd(temp)); ! 5773: } ! 5774: #endif /* ATT7300 */ ! 5775: ! 5776: /* T T S C A R R -- Set ttcarr variable, controlling carrier handling. ! 5777: * ! 5778: * 0 = Off: Always ignore carrier. E.g. you can connect without carrier. ! 5779: * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect. ! 5780: * 2 = Auto: For "modem direct": The same as "Off". ! 5781: * For real modem types: Heed carrier during connect, but ignore ! 5782: * it anytime else. Compatible with pre-5A C-Kermit versions. ! 5783: * ! 5784: * As you can see, this setting does not affect dialing, which always ignores ! 5785: * carrier (unless there is some special exception for some modem type). It ! 5786: * does affect ttopen() if it is set before ttopen() is used. This setting ! 5787: * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are ! 5788: * (or should be) always called before any communications is tried, which ! 5789: * means that, practically speaking, the effect is immediate. ! 5790: * ! 5791: * Of course, nothing of this applies to remote mode (xlocal = 0). ! 5792: * ! 5793: * Someone has yet to uncover how to manipulate the carrier in the BSD ! 5794: * environment (or any non-termio using environment). Until that time, this ! 5795: * will simply be a no-op for BSD. ! 5796: * ! 5797: * Note that in previous versions, the carrier was most often left unchanged ! 5798: * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX. This ! 5799: * has changed. Now it is controlled by ttcarr in conjunction with these ! 5800: * modes. ! 5801: */ ! 5802: int ! 5803: ttscarr(carrier) int carrier; { ! 5804: ttcarr = carrier; ! 5805: debug(F101, "ttscarr","",ttcarr); ! 5806: return(ttcarr); ! 5807: } ! 5808: ! 5809: /* C A R R C T L -- Set tty modes for carrier treatment. ! 5810: * ! 5811: * Sets the appropriate bits in a termio or sgttyb struct for carrier control ! 5812: * (actually, there are no bits in sgttyb for that), or performs any other ! 5813: * operations needed to control this on the current system. The function does ! 5814: * not do the actual TCSETA or stty, since often we want to set other bits too ! 5815: * first. Don't call this function when xlocal is 0, or the tty is not opened. ! 5816: * ! 5817: * We don't know how to do anything like carrier control on non-ATTSV systems, ! 5818: * except, apparently, ultrix. See above. It is also known that this doesn't ! 5819: * have much effect on a Xenix system. For Xenix, one should switch back and ! 5820: * forth between the upper and lower case device files. Maybe later. ! 5821: * Presently, Xenix will stick to the mode it was opened with. ! 5822: * ! 5823: * carrier: 0 = ignore carrier, 1 = require carrier. ! 5824: * The current state is saved in curcarr, and checked to save labour. ! 5825: */ ! 5826: #ifdef SVORPOSIX ! 5827: int ! 5828: #ifdef BSD44ORPOSIX ! 5829: carrctl(ttpar, carrier) struct termios *ttpar; int carrier; ! 5830: #else /* ATTSV */ ! 5831: carrctl(ttpar, carrier) struct termio *ttpar; int carrier; ! 5832: #endif /* BSD44ORPOSIX */ ! 5833: /* carrctl */ { ! 5834: debug(F101, "carrctl","",carrier); ! 5835: if (carrier) ! 5836: ttpar->c_cflag &= ~CLOCAL; ! 5837: else ! 5838: ttpar->c_cflag |= CLOCAL; ! 5839: return(0); ! 5840: } ! 5841: #else /* Berkeley, V7, et al... */ ! 5842: int ! 5843: carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; { ! 5844: #ifdef ultrix ! 5845: int temp = 0; ! 5846: #endif /* ultrix */ ! 5847: #ifdef OXOS ! 5848: int modem_status, lnohang = LNOHANG; ! 5849: #endif /* OXOS */ ! 5850: debug(F101, "carrctl","",carrier); ! 5851: if (carrier == curcarr) ! 5852: return(0); ! 5853: curcarr = carrier; ! 5854: #ifdef ultrix ! 5855: if (carrier) { ! 5856: ioctl(ttyfd, TIOCMODEM, &temp); ! 5857: ioctl(ttyfd, TIOCHPCL, 0); ! 5858: } else { ! 5859: /* (According to the manuals, TIOCNCAR should be preferred */ ! 5860: /* over TIOCNMODEM...) */ ! 5861: ioctl(ttyfd, TIOCNMODEM, &temp); ! 5862: } ! 5863: #endif /* ultrix */ ! 5864: #ifdef OXOS ! 5865: /* ! 5866: From Fulvio Marino at Olivetti. This code allows CONNECT to work even ! 5867: if DCD/RTS are down, if "carrier" is set appropriately. ! 5868: */ ! 5869: if (ioctl(ttyfd, TIOCMODG, &modem_status) == 0) { ! 5870: if (carrier) { ! 5871: /* enable carrier detect */ ! 5872: modem_status |= TIOCM_CAR; ! 5873: } else { ! 5874: /* disable carrier detect */ ! 5875: modem_status &= ~TIOCM_CAR; ! 5876: } ! 5877: (void)ioctl(ttyfd, TIOCMODS, &modem_status); ! 5878: } ! 5879: if (carrier) { ! 5880: /* Send hangup when carrier drops */ ! 5881: (void)ioctl(ttyfd, TIOCLBIC, &lnohang); ! 5882: /* hang up the phone */ ! 5883: (void)ioctl(ttyfd, TIOCHPCL, NULL); ! 5884: } else { ! 5885: /* Don't send hangup when carrier drops */ ! 5886: (void)ioctl(ttyfd, TIOCLBIS, &lnohang); ! 5887: } ! 5888: #endif /* OXOS */ ! 5889: return(0); ! 5890: } ! 5891: #endif /* SVORPOSIX */ ! 5892: ! 5893: ! 5894: /* T T G M D M -- Get modem signals */ ! 5895: /* ! 5896: Looks for RS-232 modem signals, and returns those that are on in as its ! 5897: return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h. ! 5898: Returns: ! 5899: -3 Not implemented ! 5900: -2 if the communication device does not have modem control (e.g. telnet) ! 5901: -1 on error. ! 5902: >= 0 on success, with a bit mask containing the modem signals that are on. ! 5903: */ ! 5904: ! 5905: /* ! 5906: Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style ! 5907: modem control, namely the TIOCMGET ioctl. ! 5908: */ ! 5909: ! 5910: #ifdef BSD43 ! 5911: #define K_MDMCTL ! 5912: #endif ! 5913: ! 5914: #ifdef SUNOS4 ! 5915: #define K_MDMCTL ! 5916: #endif ! 5917: ! 5918: #ifdef TIOCMGET ! 5919: #define K_MDMCTL ! 5920: #endif ! 5921: ! 5922: int ! 5923: ttgmdm() { ! 5924: ! 5925: #ifdef HPUX /* HPUX has its own way */ ! 5926: ! 5927: /* ! 5928: NOTE: I don't have an HPUX man page, and so I'm only guessing at the ! 5929: right names for these symbols. Somebody with HPUX please let me know ! 5930: what corrections are needed. ! 5931: */ ! 5932: ! 5933: int x, y, z; ! 5934: ! 5935: if (netconn) return(-2); /* No modem signals for network */ ! 5936: if (xlocal) /* Get modem signals */ ! 5937: x = ioctl(ttyfd,MCGETA,&y); ! 5938: else ! 5939: x = ioctl(0,MCGETA,&y); ! 5940: if (x < 0) return(-1); ! 5941: debug(F101,"ttgmdm","",y); ! 5942: ! 5943: z = 0; /* Initialize return value */ ! 5944: ! 5945: /* Now set bits for each modem signal that is reported to be on. */ ! 5946: ! 5947: #ifdef MCTS ! 5948: /* Clear To Send */ ! 5949: if (y & MCTS) z |= BM_CTS; ! 5950: #endif ! 5951: #ifdef MDSR ! 5952: /* Data Set Ready */ ! 5953: if (y & MDSR) z |= BM_DSR; ! 5954: #endif ! 5955: #ifdef MDCD ! 5956: /* Carrier */ ! 5957: if (y & MDCD) z |= BM_DCD; ! 5958: #endif ! 5959: #ifdef MRNG ! 5960: /* Ring Indicate */ ! 5961: if (y & MRNG) z |= BM_RNG; ! 5962: #endif ! 5963: #ifdef MDTR ! 5964: /* Data Terminal Ready */ ! 5965: if (y & MDTR) z |= BM_DTR; ! 5966: #endif ! 5967: #ifdef MRTS ! 5968: /* Request To Send */ ! 5969: if (y & MRTS) z |= BM_RTS; ! 5970: #endif ! 5971: return(z); ! 5972: ! 5973: #else /* ! HPUX */ ! 5974: ! 5975: #ifdef K_MDMCTL ! 5976: /* ! 5977: Note, <sys/ttycom> might have already been included by by <sys/ioctl.h>. ! 5978: Hence the following ifndef on a symbol which is defined there. ! 5979: */ ! 5980: #ifndef TIOCMGET ! 5981: #include <sys/ttycom.h> ! 5982: #endif /* TIOCMGET */ ! 5983: ! 5984: int x, y, z; ! 5985: ! 5986: if (netconn) return(-2); /* Network, no modem signals. */ ! 5987: if (xlocal) ! 5988: x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */ ! 5989: else ! 5990: x = ioctl(0,TIOCMGET,&y); ! 5991: if (x < 0) return(-1); ! 5992: debug(F101,"ttgmdm","",y); ! 5993: ! 5994: z = 0; /* Initialize return value. */ ! 5995: #ifdef TIOCM_CTS ! 5996: /* Clear To Send */ ! 5997: if (y & TIOCM_CTS) z |= BM_CTS; ! 5998: #endif ! 5999: #ifdef TIOCM_DSR ! 6000: /* Data Set Ready */ ! 6001: if (y & TIOCM_DSR) z |= BM_DSR; ! 6002: #endif ! 6003: #ifdef TIOCM_CAR ! 6004: /* Carrier */ ! 6005: if (y & TIOCM_CAR) z |= BM_DCD; ! 6006: #endif ! 6007: #ifdef TIOCM_RNG ! 6008: /* Ring Indicate */ ! 6009: if (y & TIOCM_RNG) z |= BM_RNG; ! 6010: #endif ! 6011: #ifdef TIOCM_DTR ! 6012: /* Data Terminal Ready */ ! 6013: if (y & TIOCM_DTR) z |= BM_DTR; ! 6014: #endif ! 6015: #ifdef TIOCM_RTS ! 6016: /* Request To Send */ ! 6017: if (y & TIOCM_RTS) z |= BM_RTS; ! 6018: #endif ! 6019: return(z); ! 6020: #else ! 6021: if (netconn) return(-2); ! 6022: return(-3); ! 6023: ! 6024: #endif /* K_MDMCTL */ ! 6025: #endif /* HPUX */ ! 6026: } ! 6027: ! 6028: /* P S U S P E N D -- Put this process in the background. */ ! 6029: ! 6030: /* ! 6031: Call with flag nonzero if suspending is allowed, zero if not allowed. ! 6032: Returns 0 on apparent success, -1 on failure (flag was zero, or ! 6033: kill() returned an error code. ! 6034: */ ! 6035: int ! 6036: psuspend(flag) int flag; { ! 6037: ! 6038: #ifdef RTU ! 6039: extern int rtu_bug; ! 6040: #endif /* RTU */ ! 6041: ! 6042: if (flag == 0) return(-1); ! 6043: ! 6044: #ifdef NOJC ! 6045: return(-1); ! 6046: #else ! 6047: #ifdef SIGTSTP ! 6048: /* ! 6049: The big question here is whether job control is *really* supported. ! 6050: There's no way Kermit can know for sure. The fact that SIGTSTP is ! 6051: defined does not guarantee the Unix kernel supports it, and the fact ! 6052: that the Unix kernel supports it doesn't guarantee that the user's ! 6053: shell (or other process that invoked Kermit) supports it. ! 6054: */ ! 6055: #ifdef RTU ! 6056: rtu_bug = 1; ! 6057: #endif /* RTU */ ! 6058: if (kill(0,SIGSTOP) < 0 ! 6059: #ifdef OXOS ! 6060: /* ! 6061: Because "kill(myself,SIGSTOP)" can't be caught, blocked, or ignored..." ! 6062: */ ! 6063: && kill(getpid(),SIGSTOP) < 0 ! 6064: #else ! 6065: #ifdef MIPS ! 6066: /* Let's try this for MIPS too. */ ! 6067: && kill(getpid(),SIGSTOP) < 0 ! 6068: #endif /* MIPS */ ! 6069: #endif /* OXOS */ ! 6070: ) { /* If job control, suspend the job */ ! 6071: perror("suspend"); ! 6072: debug(F101,"psuspend error","",errno); ! 6073: return(-1); ! 6074: } ! 6075: debug(F100,"psuspend ok","",0); ! 6076: return(0); ! 6077: #else ! 6078: return(-1); ! 6079: #endif /* SIGTSTP */ ! 6080: #endif /* NOJC */ ! 6081: } ! 6082: ! 6083: /* ! 6084: setuid package, by Kristoffer Eriksson, with contributions from Dean ! 6085: Long and fdc. ! 6086: */ ! 6087: ! 6088: #ifndef _POSIX_SOURCE ! 6089: #ifndef SUNOS4 ! 6090: #ifndef NEXT ! 6091: #ifndef PS2AIX10 ! 6092: extern UID_T getuid(), geteuid(), getreuid(); ! 6093: extern GID_T getgid(), getegid(), getregid(); ! 6094: #endif /* PS2AIX10 */ ! 6095: #endif /* NEXT */ ! 6096: #endif /* SUNOS4 */ ! 6097: #endif /* _POSIX_SOURCE */ ! 6098: ! 6099: /* ! 6100: Subject: Set-user-id ! 6101: To: [email protected] (Frank da Cruz) ! 6102: Date: Sat, 21 Apr 90 4:48:25 MES ! 6103: From: Kristoffer Eriksson <[email protected]> ! 6104: ! 6105: This is a set of functions to be used in programs that may be run set-user-id ! 6106: and/or set-group-id. They handle both the case where the program is not run ! 6107: with such privileges (nothing special happens then), and the case where one ! 6108: or both of these set-id modes are used. The program is made to run with the ! 6109: user's real user and group ids most of the time, except for when more ! 6110: privileges are needed. Don't set-user-id to "root". ! 6111: ! 6112: This works on System V and POSIX. In BSD, it depends on the ! 6113: "saved-set-user-id" feature. ! 6114: */ ! 6115: ! 6116: #define UID_ROOT 0 /* Root user and group ids */ ! 6117: #define GID_ROOT 0 ! 6118: ! 6119: /* ! 6120: The following construction automatically defines the symbol SETREUID for ! 6121: Unix versions based on Berkeley Unix 4.2 or later. If this symbol is ! 6122: defined, then this program will use getreuid() and getregid() calls in ! 6123: preference to getuid() and getgid(), which in Berkeley-based Unixes do ! 6124: not allow arbitrary switching back and forth of real & effective uid. ! 6125: This construction also allows -DSETREUID to be put on the cc command line ! 6126: for any system that has and wants to use setre[ug]id(). It also prevents ! 6127: automatic definition of SETREUID if -DNOSETREU is included on the cc ! 6128: command line (or otherwise defined). ! 6129: */ ! 6130: #ifdef FT18 /* None of this for Fortune. */ ! 6131: #define NOSETREU ! 6132: #endif /* FT18 */ ! 6133: ! 6134: #ifdef ANYBSD ! 6135: #ifndef BSD29 ! 6136: #ifndef BSD41 ! 6137: #ifndef SETREUID ! 6138: #ifndef NOSETREU ! 6139: #define SETREUID ! 6140: #endif /* NOSETREU */ ! 6141: #endif /* SETREUID */ ! 6142: #endif /* !BSD41 */ ! 6143: #endif /* !BSD29 */ ! 6144: #endif /* ANYBSD */ ! 6145: ! 6146: /* Variables for user and group IDs. */ ! 6147: ! 6148: static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1; ! 6149: static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1; ! 6150: ! 6151: ! 6152: /* P R I V _ I N I -- Initialize privileges package */ ! 6153: ! 6154: /* Called as early as possible in a set-uid or set-gid program to store the ! 6155: * set-to uid and/or gid and step down to the users real uid and gid. The ! 6156: * stored id's can be temporarily restored (allowed in System V) during ! 6157: * operations that require the privilege. Most of the time, the program ! 6158: * should execute in unpriviliged state, to not impose any security threat. ! 6159: * ! 6160: * Note: Don't forget that access() always uses the real id:s to determine ! 6161: * file access, even with privileges restored. ! 6162: * ! 6163: * Returns an error mask, with error values or:ed together: ! 6164: * 1 if setuid() fails, ! 6165: * 2 if setgid() fails, and ! 6166: * 4 if the program is set-user-id to "root", which can't be handled. ! 6167: * ! 6168: * Only the return value 0 indicates real success. In case of failure, ! 6169: * those privileges that could be reduced have been, at least, but the ! 6170: * program should be aborted none-the-less. ! 6171: * ! 6172: * Also note that these functions do not expect the uid or gid to change ! 6173: * without their knowing. It may work if it is only done temporarily, but ! 6174: * you're on your own. ! 6175: */ ! 6176: int ! 6177: priv_ini() { ! 6178: int err = 0; ! 6179: ! 6180: /* Save real ID:s. */ ! 6181: realuid = getuid(); ! 6182: realgid = getgid(); ! 6183: ! 6184: /* Save current effective ID:s, those set to at program exec. */ ! 6185: privuid = geteuid(); ! 6186: privgid = getegid(); ! 6187: ! 6188: /* If running set-uid, go down to real uid, otherwise remember that ! 6189: * no privileged uid is available. ! 6190: * ! 6191: * Exceptions: ! 6192: * ! 6193: * 1) If the real uid is already "root" and the set-uid uid (the ! 6194: * initial effective uid) is not "root", then we would have trouble ! 6195: * if we went "down" to "root" here, and then temporarily back to the ! 6196: * set-uid uid (not "root") and then again tried to become "root". I ! 6197: * think the "saved set-uid" is lost when changing uid from effective ! 6198: * uid "root", which changes all uid, not only the effective uid. But ! 6199: * in this situation, we can simply go to "root" and stay there all ! 6200: * the time. That should give sufficient privilege (understatement!), ! 6201: * and give the right uids for subprocesses. ! 6202: * ! 6203: * 2) If the set-uid (the initial effective uid) is "root", and we ! 6204: * change uid to the real uid, we can't change it back to "root" when ! 6205: * we need the privilege, for the same reason as in 1). Thus, we can't ! 6206: * handle programs that are set-user-id to "root" at all. The program ! 6207: * should be aborted. Use some other uid. "root" is probably to ! 6208: * privileged for such things, anyway. (The uid is reverted to the ! 6209: * real uid until abortion.) ! 6210: * ! 6211: * These two exceptions have the effect that the "root" uid will never ! 6212: * be one of the two uids that are being switched between, which also ! 6213: * means we don't have to check for such cases in the switching ! 6214: * functions. ! 6215: * ! 6216: * Note that exception 1) is handled by these routines (by constantly ! 6217: * running with uid "root", while exception 2) is a serious error, and ! 6218: * is not provided for at all in the switching functions. ! 6219: */ ! 6220: if (realuid == privuid) ! 6221: privuid = (UID_T) -1; /* Not running set-user-id. */ ! 6222: ! 6223: /* If running set-gid, go down to real gid, otherwise remember that ! 6224: * no privileged gid is available. ! 6225: * ! 6226: * There are no exception like there is for the user id, since there ! 6227: * is no group id that is privileged in the manner of uid "root". ! 6228: * There could be equivalent problems for group changing if the ! 6229: * program sometimes ran with uid "root" and sometimes not, but ! 6230: * that is already avoided as explained above. ! 6231: * ! 6232: * Thus we can expect always to be able to switch to the "saved set- ! 6233: * gid" when we want, and back to the real gid again. You may also ! 6234: * draw the conclusion that set-gid provides for fewer hassles than ! 6235: * set-uid. ! 6236: */ ! 6237: ! 6238: if (realgid == privgid) /* If not running set-user-id, */ ! 6239: privgid = (GID_T) -1; /* remember it this way. */ ! 6240: ! 6241: err = priv_off(); /* Turn off setuid privilege. */ ! 6242: ! 6243: if (privuid == UID_ROOT) /* If setuid to root, */ ! 6244: err |= 4; /* return this error. */ ! 6245: ! 6246: if (realuid == UID_ROOT) /* If real id is root, */ ! 6247: privuid = (UID_T) -1; /* stay root at all times. */ ! 6248: ! 6249: return(err); ! 6250: } ! 6251: ! 6252: ! 6253: /* Macros for hiding the differences in UID/GID setting between various Unix ! 6254: * systems. These macros should always be called with both the privileged ID ! 6255: * and the non-privileged ID. The one in the second argument, will become the ! 6256: * effective ID. The one in the first argument will be retained for later ! 6257: * retrieval. ! 6258: */ ! 6259: #ifdef SETREUID ! 6260: #ifdef SAVEDUID ! 6261: /* On BSD systems with the saved-UID feature, we just juggle the effective ! 6262: * UID back and forth, and leave the real UID at its true value. The kernel ! 6263: * allows switching to both the current real UID, the effective UID, and the ! 6264: * UID which the program is set-UID to. The saved set-UID always holds the ! 6265: * privileged UID for us, and the real UID will always be the non-privileged, ! 6266: * and we can freely choose one of them for the effective UID at any time. ! 6267: */ ! 6268: #define switchuid(hidden,active) setreuid( (UID_T) -1, active) ! 6269: #define switchgid(hidden,active) setregid( (GID_T) -1, active) ! 6270: ! 6271: #else /* SETREUID,!SAVEDUID */ ! 6272: ! 6273: /* On systems with setreXid() but without the saved-UID feature, notably ! 6274: * BSD 4.2, we swap the real and effective UIDs each time. It's ! 6275: * the effective UID that we are interrested in, but we have to retain the ! 6276: * unused UID somewhere to enable us to restore it later, and that we do this ! 6277: * in the real UID. The kernel only allows switching to either the current ! 6278: * real or the effective UID, unless you're "root". ! 6279: */ ! 6280: #define switchuid(hidden,active) setreuid(hidden,active) ! 6281: #define switchgid(hidden,active) setregid(hidden,active) ! 6282: #endif ! 6283: ! 6284: #else /* !SETREUID, !SAVEDUID */ ! 6285: ! 6286: /* On System V and POSIX, the only thing we can change is the effective UID ! 6287: * (unless the current effective UID is "root", but initsuid() avoids that for ! 6288: * us). The kernel allows switching to the current real UID or to the saved ! 6289: * set-UID. These are always set to the non-privileged UID and the privileged ! 6290: * UID, respectively, and we only change the effective UID. This breaks if ! 6291: * the current effective UID is "root", though, because for "root" setuid/gid ! 6292: * becomes more powerful, which is why initsuid() treats "root" specially. ! 6293: * Note: That special treatment maybe could be ignored for BSD? Note: For ! 6294: * systems that don't fit any of these three cases, we simply can't support ! 6295: * set-UID. ! 6296: */ ! 6297: #define switchuid(hidden,active) setuid(active) ! 6298: #define switchgid(hidden,active) setgid(active) ! 6299: #endif /* SETREUID */ ! 6300: ! 6301: ! 6302: /* P R I V _ O N -- Turn on the setuid and/or setgid */ ! 6303: ! 6304: /* Go to the privileged uid (gid) that the program is set-user-id ! 6305: * (set-group-id) to, unless the program is running unprivileged. ! 6306: * If setuid() fails, return value will be 1. If getuid() fails it ! 6307: * will be 2. Return immediately after first failure, and the function ! 6308: * tries to restore any partial work done. Returns 0 on success. ! 6309: * Group id is changed first, since it is less serious than user id. ! 6310: */ ! 6311: int ! 6312: priv_on() { ! 6313: if (privgid != (GID_T) -1) ! 6314: if (switchgid(realgid,privgid)) ! 6315: return(2); ! 6316: ! 6317: if (privuid != (UID_T) -1) ! 6318: if (switchuid(realuid,privuid)) { ! 6319: if (privgid != (GID_T) -1) ! 6320: switchgid(privgid,realgid); ! 6321: return(1); ! 6322: } ! 6323: return(0); ! 6324: } ! 6325: ! 6326: /* P R I V _ O F F -- Turn on the real uid and gid */ ! 6327: ! 6328: /* Return to the unprivileged uid (gid) after an temporary visit to ! 6329: * privileged status, unless the program is running without set-user-id ! 6330: * (set-group-id). Returns 1 for failure in setuid() and 2 for failure ! 6331: * in setgid() or:ed together. The functions tries to return both uid ! 6332: * and gid to unprivileged state, regardless of errors. Returns 0 on ! 6333: * success. ! 6334: */ ! 6335: int ! 6336: priv_off() { ! 6337: int err = 0; ! 6338: ! 6339: if (privuid != (UID_T) -1) ! 6340: if (switchuid(privuid,realuid)) ! 6341: err |= 1; ! 6342: ! 6343: if (privgid != (GID_T) -1) ! 6344: if (switchgid(privgid,realgid)) ! 6345: err |= 2; ! 6346: ! 6347: return(err); ! 6348: } ! 6349: ! 6350: /* Turn off privilege permanently. No going back. This is necessary before ! 6351: * a fork() on BSD43 machines that don't save the setUID or setGID, because ! 6352: * we swap the real and effective ids, and we don't want to let the forked ! 6353: * process swap them again and get the privilege back. It will work on other ! 6354: * machines too, such that you can rely on its effect always being the same, ! 6355: * for instance, even when you're in priv_on() state when this is called. ! 6356: * (Well, that part about "permanent" is on System V only true if you follow ! 6357: * this with a call to exec(), but that's what we want it for anyway.) ! 6358: * Added by Dean Long -- [email protected] ! 6359: */ ! 6360: int ! 6361: priv_can() { ! 6362: ! 6363: #ifdef SETREUID ! 6364: int err = 0; ! 6365: if (privuid != (UID_T) -1) ! 6366: if (setreuid(realuid,realuid)) ! 6367: err |= 1; ! 6368: ! 6369: if (privgid != (GID_T) -1) ! 6370: if (setregid(realgid,realgid)) ! 6371: err |= 2; ! 6372: ! 6373: return(err); ! 6374: ! 6375: #else ! 6376: /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/ ! 6377: return(priv_off()); ! 6378: ! 6379: #endif /* SETREUID */ ! 6380: } ! 6381: ! 6382: /* P R I V _ O P N -- For opening protected files or devices. */ ! 6383: ! 6384: int ! 6385: priv_opn(name, modes) char *name; int modes; { ! 6386: int x; ! 6387: priv_on(); /* Turn privileges on */ ! 6388: x = open(name, modes); /* Try to open the device */ ! 6389: priv_off(); /* Turn privileges off */ ! 6390: return(x); /* Return open's return code */ ! 6391: } ! 6392: ! 6393: /* P R I V _ C H K -- Check privileges. */ ! 6394: ! 6395: /* Try to turn them off. If turning them off did not succeed, cancel them */ ! 6396: ! 6397: int ! 6398: priv_chk() { ! 6399: int x, y = 0; ! 6400: x = priv_off(); /* Turn off privs. */ ! 6401: if (x != 0 || getuid() == privuid || geteuid() == privuid) ! 6402: y = priv_can(); ! 6403: if (x != 0 || getgid() == privgid || getegid() == privgid) ! 6404: y = y | priv_can(); ! 6405: return(y); ! 6406: } ! 6407: ! 6408: UID_T ! 6409: real_uid() { ! 6410: return(realuid); ! 6411: } ! 6412: ! 6413: VOID ! 6414: ttimoff() { /* Turn off any timer interrupts */ ! 6415: int xx; ! 6416: /* ! 6417: As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to ! 6418: SIG_DFL (to catch alarms, or if there is no handler, to exit). This is to ! 6419: cure (mask, really) a deeper problem with stray alarms that occurs on some ! 6420: systems, possibly having to do with sleep(), that caused core dumps. It ! 6421: should be OK to do this, because no code in this module uses nested alarms. ! 6422: (But we still have to watch out for SCRIPT and DIAL...) ! 6423: */ ! 6424: xx = alarm(0); ! 6425: /* debug(F101,"ttimoff alarm","",xx); */ ! 6426: if (saval) { /* Restore any previous */ ! 6427: signal(SIGALRM,saval); /* alarm handler. */ ! 6428: /* debug(F101,"ttimoff alarm restoring saval","",saval); */ ! 6429: saval = NULL; ! 6430: } else { ! 6431: signal(SIGALRM,SIG_IGN); /* Used to be SIG_DFL */ ! 6432: /* debug(F100,"ttimoff alarm SIG_IGN","",0); */ ! 6433: } ! 6434: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.