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

Defined functions

SIGTYP defined in line 3930; never used
acucntrl defined in line 2492; used 4 times
attdial defined in line 5640; used 2 times
carrctl defined in line 5854; used 6 times
catch defined in line 4168; used 2 times
cctrap defined in line 907; used 3 times
conbgt defined in line 3739; used 4 times
congks defined in line 5626; never used
congm defined in line 5119; used 3 times
do_open defined in line 1574; used 4 times
err defined in line 4159; used 21 times
esctrp defined in line 3713; used 6 times
genbrk defined in line 4182; used 1 times
initrawq defined in line 4081; used 3 times
main defined in line 801; never used
myfillbuf defined in line 3585; used 2 times
mygetbuf defined in line 3454; used 2 times
myunrd defined in line 3414; never used
offgetty defined in line 5767; used 2 times
ongetty defined in line 5778; used 3 times
priv_can defined in line 6372; used 7 times
priv_chk defined in line 6409; used 9 times
priv_ini defined in line 6188; used 1 times
priv_off defined in line 6347; used 9 times
priv_on defined in line 6323; used 5 times
priv_opn defined in line 6396; used 7 times
psuspend defined in line 6047; used 1 times
real_uid defined in line 6420; used 4 times
rtimer defined in line 5020; used 1 times
sig_ign defined in line 4014; used 2 times
sndbrk defined in line 4714; used 2 times
syscleanup defined in line 958; used 1 times
sysinit defined in line 915; used 1 times
timerh defined in line 896; used 8 times
ttfluo defined in line 3680; never used
tthflow defined in line 2509; used 4 times
ttinl defined in line 4464; used 5 times
ttlock defined in line 2284; used 2 times
ttres defined in line 2105; used 2 times
ttrpid defined in line 2202; used 3 times
ttscarr defined in line 5814; used 1 times
ttunlck defined in line 2470; used 2 times
xxlast defined in line 881; used 2 times

Defined variables

UID_T defined in line 6420; never used
VOID defined in line 6425; never used
attmodem defined in line 762; used 10 times
cc_int defined in line 904; used 1 times
cccbrk defined in line 730; used 21 times
ccold defined in line 730; used 10 times
ccraw defined in line 730; used 27 times
ckxech defined in line 617; used 15 times
ckxv defined in line 1; used 2 times
conbuf defined in line 790; used 3 times
conbufn defined in line 791; used 10 times
conbufp defined in line 792; used 2 times
concrp defined in line 788; used 4 times
conesc defined in line 779; used 18 times
dfflow defined in line 597; used 1 times
dfmdm defined in line 583; never used
dfprty defined in line 591; used 1 times
dialer defined in line 763; used 25 times
fdflag defined in line 602; used 5 times
flfnam defined in line 766; used 21 times
haslock defined in line 770; used 10 times
iniflags defined in line 600; used 2 times
jc defined in line 3722; used 23 times
km_con defined in line 610; used 6 times
km_ext defined in line 611; used 9 times
kmem defined in line 556; used 8 times
lkflfn defined in line 768; used 3 times
lmode defined in line 748; used 3 times
lmodef defined in line 747; used 10 times
ltcharf defined in line 745; used 7 times
ltchnoi defined in line 743; used 5 times
ltchold defined in line 743; used 2 times
my_count defined in line 3367; used 11 times
my_item defined in line 3368; used 5 times
mybuf defined in line 3364; used 10 times
qaddr defined in line 557; used 7 times
rctsx defined in line 370; used 6 times
rtu_bug defined in line 588; used 2 times
tcharf defined in line 737; used 8 times
tchnoi defined in line 735; used 17 times
tchold defined in line 735; used 2 times
tcount defined in line 621; used 2 times
ttbuf defined in line 753; used 17 times
ttcarr defined in line 596; used 9 times
ttcur defined in line 729; used 42 times
ttfdflg defined in line 603; used 7 times
ttflow defined in line 606; used 7 times
ttld defined in line 607; used 5 times
ttmdm defined in line 595; used 5 times
ttnmsv defined in line 784; used 15 times
ttold defined in line 729; used 23 times
ttotmo defined in line 996; used 4 times
ttpflg defined in line 593; used 2 times
ttpmsk defined in line 594; used 11 times
ttprty defined in line 592; used 10 times
ttraw defined in line 729; used 66 times
ttspeed defined in line 605; used 6 times
tttvt defined in line 729; used 42 times
tvtflg defined in line 604; used 12 times
vanilla defined in line 758; used 2 times
x25buf defined in line 3361; used 3 times

Defined struct's

termios defined in line 2576; used 12 times

Defined typedef's

mflag defined in line 441; used 2 times

Defined macros

BREAKNULS defined in line 636; used 3 times
BSD42 defined in line 4867; used 6 times
BSDBREAK defined in line 4733; used 1 times
BSPEED defined in line 4179; used 3 times
CON defined in line 558; used 6 times
CONBUFSIZ defined in line 789; used 1 times
CRTSCTS defined in line 2574; used 3 times
CTRLC defined in line 4449; used 3 times
DEVNAMLEN defined in line 101; used 13 times
DIRENT defined in line 34; used 1 times
  • in line 46
DOGETY defined in line 214; used 5 times
EINTR defined in line 5547; used 5 times
ENOTCONN defined in line 23; used 2 times
FIONREAD defined in line 3338; used 10 times
FREAD defined in line 524; used 3 times
FWRITE defined in line 528; used 2 times
GID_ROOT defined in line 6129; never used
HPUXJOBCTL defined in line 434; used 4 times
HUPTIME defined in line 1684; used 7 times
HZ defined in line 69; used 2 times
IEXTEN defined in line 461; used 6 times
ISMODEM defined in line 213; used 4 times
K_MDMCTL defined in line 5931; used 1 times
LCKDIR defined in line 141; used 1 times
LFDEVNO defined in line 2258; used 4 times
LFNAML defined in line 2311; used 3 times
LOCKF defined in line 177; used 3 times
LOCK_DIR defined in line 192; used 2 times
MSLFTIME defined in line 4847; used 1 times
MYBUFLEN defined in line 3356; used 4 times
MYREAD defined in line 222; used 11 times
NAMEFD defined in line 1022; used 4 times
NAP defined in line 73; used 2 times
NCCS defined in line 346; used 1 times
NOFILEH defined in line 333; used 2 times
NOSETREU defined in line 6143; used 1 times
NOSYSIOCTLH defined in line 377; used 1 times
OPENFLGS defined in line 2011; used 5 times
O_RDONLY defined in line 532; used 2 times
PEEKTYPE defined in line 3341; used 3 times
PGROUP_T defined in line 3762; used 2 times
PIDSTRING defined in line 167; used 3 times
SELECT defined in line 4875; used 2 times
SETREUID defined in line 6151; used 3 times
TANDEM defined in line 126; used 11 times
TCGETS defined in line 2572; used 1 times
TCSANOW defined in line 2533; used 1 times
TCSETS defined in line 2573; used 1 ti