Annotation of coherent/e/bin/cku179/ckutio.c, revision 1.1.1.1

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

unix.superglobalmegacorp.com

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