Annotation of coherent/e/bin/ckermit/ckutio.c, revision 1.1

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

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.