Annotation of coherent/e/bin/ckermit/ckutio.c, revision 1.1.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.