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