| #ifdef aegis |
| char *ckxv = "Aegis Communications support, 8.0.303, 17 Apr 2004"; |
| #else |
| #ifdef Plan9 |
| char *ckxv = "Plan 9 Communications support, 8.0.303, 17 Apr 2004"; |
| #else |
| char *ckxv = "UNIX Communications support, 8.0.303, 17 Apr 2004"; |
| #endif /* Plan9 */ |
| #endif /* aegis */ |
| |
| /* C K U T I O */ |
| |
| /* C-Kermit interrupt, communications control and I/O functions for UNIX */ |
| |
| /* |
| Author: Frank da Cruz (fdc@columbia.edu), |
| Columbia University Academic Information Systems, New York City. |
| |
| Copyright (C) 1985, 2004, |
| Trustees of Columbia University in the City of New York. |
| All rights reserved. See the C-Kermit COPYING.TXT file or the |
| copyright text in the ckcmai.c module for disclaimer and permissions. |
| */ |
| |
| /* |
| NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be |
| compatible with C preprocessors that support only #ifdef, #else, #endif, |
| #define, and #undef. Please do not use #if, logical operators, or other |
| preprocessor features in any of the portable C-Kermit modules. You can, |
| of course, use these constructions in platform-specific modules when they |
| are supported by all compilers/preprocessors that could be used on that |
| platform. |
| */ |
| |
| extern int nettype; /* Defined in ckcmai.c */ |
| |
| /* Includes */ |
| |
| #include "ckcsym.h" /* This must go first */ |
| #include "ckcdeb.h" /* This must go second */ |
| |
| #ifdef OSF13 |
| #ifdef CK_ANSIC |
| #ifdef _NO_PROTO |
| #undef _NO_PROTO |
| #endif /* _NO_PROTO */ |
| #endif /* CK_ANSIC */ |
| #endif /* OSF13 */ |
| |
| #include <errno.h> /* System error numbers */ |
| |
| #ifdef __386BSD__ |
| #define ENOTCONN 57 |
| #else |
| #ifdef __bsdi__ |
| #define ENOTCONN 57 |
| #else |
| #ifdef __FreeBSD__ |
| #define ENOTCONN 57 |
| #endif /* __FreeBSD__ */ |
| #endif /* __bsdi__ */ |
| #endif /* __386BSD__ */ |
| |
| #ifdef SCO_OSR504 |
| #define NBBY 8 |
| #endif /* SCO_OSR504 */ |
| |
| #ifdef Plan9 |
| #define SELECT |
| #include <sys/time.h> |
| #include <select.h> |
| #define FD_SETSIZE (3 * sizeof(long) * 8) |
| static struct timeval tv; |
| #endif /* Plan9 */ |
| |
| #ifdef CLIX |
| #include <sys/time.h> |
| #endif /* CLIX */ |
| |
| #include "ckcnet.h" /* Symbols for network types. */ |
| #ifdef CK_SSL |
| #include "ck_ssl.h" |
| #endif /* CK_SSL */ |
| |
| /* |
| The directory-related includes are here because we need to test some |
| file-system-related symbols to find out which system we're being compiled |
| under. For example, MAXNAMLEN is defined in BSD4.2 but not 4.1. |
| */ |
| #ifdef SDIRENT /* Directory bits... */ |
| #define DIRENT |
| #endif /* SDIRENT */ |
| |
| #ifdef XNDIR |
| #include <sys/ndir.h> |
| #else /* !XNDIR */ |
| #ifdef NDIR |
| #include <ndir.h> |
| #else /* !NDIR, !XNDIR */ |
| #ifdef RTU |
| #include "/usr/lib/ndir.h" |
| #else /* !RTU, !NDIR, !XNDIR */ |
| #ifdef DIRENT |
| #ifdef SDIRENT |
| #include <sys/dirent.h> |
| #else |
| #include <dirent.h> |
| #endif /* SDIRENT */ |
| #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */ |
| #include <sys/dir.h> |
| #endif /* DIRENT */ |
| #endif /* RTU */ |
| #endif /* NDIR */ |
| #endif /* XNDIR */ |
| |
| #ifdef QNX |
| #include <sys/dev.h> |
| #endif /* QNX */ |
| |
| #ifdef HPUX5 |
| #ifndef TCPSOCKET |
| /* I don't know why this is needed here since we never reference bzero(). */ |
| /* But without it C-Kermit won't link in an HP-UX 5.xx non-TCP build. */ |
| void |
| bzero(s,n) char *s; int n; { |
| extern char * memset(); |
| memset(s,0,n); |
| } |
| #endif /* TCPSOCKET */ |
| #endif /* HPUX5 */ |
| |
| /* Definition of HZ, used in msleep() */ |
| |
| #ifdef MIPS |
| #define HZ ( 1000 / CLOCK_TICK ) |
| #else /* MIPS */ |
| #ifdef ATTSV |
| #ifndef NAP |
| #ifdef TRS16 |
| #define HZ ( 1000 / CLOCK_TICK ) |
| #endif /* TRS16 */ |
| #ifdef NAPHACK |
| #define nap(x) (void)syscall(3112, (x)) |
| #define NAP |
| #endif /* NAPHACK */ |
| #endif /* NAP */ |
| #endif /* ATTSV */ |
| #endif /* MIPS */ |
| |
| #ifdef M_UNIX |
| #undef NGROUPS_MAX /* Prevent multiple definition warnings */ |
| #endif /* M_UNIX */ |
| |
| /* |
| NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding |
| library routine, so _poll comes up undefined at link time. |
| */ |
| #ifdef CK_POLL |
| #ifndef AIXRS /* IBM AIX needs special handling */ |
| #include <poll.h> /* "standard" (SVID) i/o multiplexing, etc */ |
| #else /* AIXRS */ |
| #ifdef SVR4 /* AIX 3.2 is like SVID... */ |
| #include <poll.h> |
| #else /* But AIX 3.1 is not ... */ |
| #include <sys/poll.h> /* The include file is in include/sys */ |
| #define events reqevents /* And it does not map IBM-specific member */ |
| #define revents rtnevents /* names to the System V equivalents */ |
| #endif /* SVR4 */ |
| #endif /* AIXRS */ |
| #endif /* CK_POLL */ |
| |
| #include <signal.h> /* Signals */ |
| |
| /* For setjmp and longjmp */ |
| |
| #ifndef ZILOG |
| #include <setjmp.h> |
| #else |
| #include <setret.h> |
| #endif /* ZILOG */ |
| |
| /* |
| The following test differentiates between 4.1 BSD and 4.2 & later. |
| If you have a 4.1BSD system with the DIRENT library, this test could |
| mistakenly diagnose 4.2BSD and then later enable the use of system calls |
| that aren't defined. If indeed there are such systems, we can use some |
| other way of testing for 4.1BSD, or add yet another compile-time switch. |
| */ |
| #ifdef BSD4 |
| #ifdef MAXNAMLEN |
| #ifndef FT21 /* Except for Fortune. */ |
| #ifndef FT18 |
| #ifndef BELLV10 /* And Bell Labs Research UNIX V10 */ |
| #define BSD42 |
| #endif /* BELLV10 */ |
| #endif /* FT18 */ |
| #endif /* FT21 */ |
| #endif /* MAXNAMLEN */ |
| #endif /* BSD4 */ |
| /* |
| Minix 2.0 support added by Terry McConnell, |
| Syracuse University <tmc@barnyard.syr.edu> |
| No more sgtty interface, posix compliant. |
| */ |
| #ifdef MINIX2 |
| #define _MINIX /* Needed for some Minix header files */ |
| #undef MINIX /* Old minix 1.0: used sgtty interface */ |
| #define BSD44ORPOSIX |
| #define SVORPOSIX |
| #define DCLTIMEVAL |
| #define NOFILEH |
| #include <sys/types.h> |
| #include <sys/ioctl.h> |
| #include <termios.h> |
| #include <limits.h> |
| #undef TIOCGETC /* defined in sys/ioctl.h, but not really supported */ |
| #define TANDEM 0 |
| #endif /* MINIX2 */ |
| |
| /* |
| MINIX 1.0 support added by Charles Hedrick, |
| Rutgers University <hedrick@aramis.rutgers.edu>. |
| MINIX also has V7 enabled. |
| */ |
| #ifdef MINIX |
| #define TANDEM 0 |
| #define MYREAD |
| #define NOSYSIOCTLH |
| #include <limits.h> |
| #endif /* MINIX */ |
| |
| #ifdef CK_REDIR /* <sys/wait.h> needed only for REDIRECT command. */ |
| /* |
| If anybody can figure out how to make this work with NeXTSTEP, be |
| my guest! (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS) |
| */ |
| #ifndef CK_WAIT_H /* If wait.h not already included... */ |
| #ifdef OSF /* force OSF to select POSIX wait */ |
| #ifdef _BSD /* instead of BSD (see ckcdeb.h) */ |
| #define CK_OSF_BSD |
| #undef _BSD |
| #endif /* _BSD */ |
| #endif /* OSF */ |
| #include <sys/wait.h> /* Include it */ |
| #ifdef OSF |
| #ifdef CK_OSF_BSD |
| #define _BSD /* Restore it */ |
| #undef CK_OSF_BSD |
| #endif /* CK_OSF_BSD */ |
| #endif /* OSF */ |
| #endif /* CK_WAIT_H */ |
| #endif /* CK_REDIR */ |
| |
| #include "ckuver.h" /* Version herald */ |
| char *ckxsys = HERALD; |
| |
| #ifdef CK_UTSNAME |
| #include <sys/utsname.h> |
| |
| #ifdef TRU64 /* Tru64 UNIX 4.0 and later */ |
| /* Verified on Tru64 4.0F - might break on 4.0E or earlier */ |
| #include <sys/sysinfo.h> /* (don't know about OSF/1 or DU) */ |
| #include <machine/hal_sysinfo.h> |
| #endif /* TRU64 */ |
| |
| #ifdef SOLARIS25 /* Solaris 2.5 and later */ |
| #include <sys/systeminfo.h> /* (don't know about earlier ones) */ |
| #endif /* SOLARIS25 */ |
| |
| #ifdef UW7 |
| #ifndef SYS_NMLN |
| #define SYS_NMLN 257 |
| #endif /* NMLN */ |
| #endif /* UW7 */ |
| #ifdef HPUX9PLUS |
| static int hpis800 = 0; |
| #endif /* HPUX9PLUS */ |
| #ifdef SYS_NMLN |
| #define CK_SYSNMLN SYS_NMLN |
| #else |
| #ifdef _SYS_NMLN |
| #define CK_SYSNMLN _SYS_NMLN |
| #else |
| #ifdef UTSLEN |
| #define CK_SYSNMLN UTSLEN |
| #else |
| #define CK_SYSNMLN 31 |
| #endif /* UTSLEN */ |
| #endif /* _SYS_NMLN */ |
| #endif /* SYS_NMLN */ |
| char unm_mch[CK_SYSNMLN+1] = { '\0', '\0' }; |
| char unm_mod[CK_SYSNMLN+1] = { '\0', '\0' }; |
| char unm_nam[CK_SYSNMLN+1] = { '\0', '\0' }; |
| char unm_rel[CK_SYSNMLN+1] = { '\0', '\0' }; |
| char unm_ver[CK_SYSNMLN+1] = { '\0', '\0' }; |
| #endif /* CK_UTSNAME */ |
| |
| #ifdef CIE |
| #include <stat.h> /* For chasing symlinks, etc. */ |
| #else |
| #include <sys/stat.h> |
| #endif /* CIE */ |
| |
| /* UUCP lockfile material... */ |
| |
| #ifndef NOUUCP |
| #ifdef USETTYLOCK |
| #ifdef HAVE_BAUDBOY /* Red Hat baudboy/lockdev */ |
| #include <baudboy.h> |
| #else |
| #ifdef USE_UU_LOCK |
| #ifdef __FreeBSD__ |
| #include <libutil.h> /* FreeBSD */ |
| #else |
| #include <util.h> /* OpenBSD */ |
| #endif /* HAVE_BAUDBOY */ |
| #endif /* __FreeBSD */ |
| #endif /* USE_UU_LOCK */ |
| #else /* USETTYLOCK */ |
| |
| /* Name of UUCP tty device lockfile */ |
| |
| #ifdef LINUXFSSTND |
| #ifndef HDBUUCP |
| #define HDBUUCP |
| #endif /* HDBUUCP */ |
| #endif /* LINUXFSSTND */ |
| |
| #ifdef ACUCNTRL |
| #define LCKDIR |
| #endif /* ACUCNTRL */ |
| |
| /* |
| PIDSTRING means use ASCII string to represent pid in lockfile. |
| */ |
| #ifndef PIDSTRING |
| #ifdef HDBUUCP |
| #define PIDSTRING |
| #else |
| #ifdef BSD44 |
| #define PIDSTRING |
| #else |
| #ifdef RTAIX |
| #define PIDSTRING |
| #else |
| #ifdef AIXRS |
| #define PIDSTRING |
| #else |
| #ifdef COHERENT |
| #define PIDSTRING |
| #endif /* COHERENT */ |
| #endif /* AIXRS */ |
| #endif /* RTAIX */ |
| #endif /* BSD44 */ |
| #endif /* HDBUUCP */ |
| #endif /* PIDSTRING */ |
| |
| /* Now the PIDSTRING exceptions... */ |
| |
| #ifdef PIDSTRING |
| #ifdef HPUX |
| #undef PIDSTRING |
| #endif /* HPUX */ |
| #endif /* PIDSTRING */ |
| |
| #ifdef __bsdi__ /* BSDI (at least thru 1.1) */ |
| #ifdef PIDSTRING |
| #undef PIDSTRING |
| #endif /* PIDSTRING */ |
| #endif /* __bsdi__ */ |
| |
| #ifdef OSF32 /* Digital UNIX (OSF/1) 3.2 */ |
| #ifdef PIDSTRING |
| #undef PIDSTRING |
| #endif /* PIDSTRING */ |
| #endif /* OSF32 */ |
| |
| /* |
| LOCK_DIR is the name of the lockfile directory. |
| If LOCK_DIR is already defined (e.g. on command line), we don't change it. |
| */ |
| |
| #ifndef LOCK_DIR |
| #ifdef MACOSX |
| #define LOCK_DIR "/var/spool/lock" |
| #endif /* MACOSX */ |
| #endif/* LOCK_DIR */ |
| |
| #ifndef LOCK_DIR |
| #ifdef BSD44 |
| #ifdef __386BSD__ |
| #define LOCK_DIR "/var/spool/lock" |
| #else |
| #ifdef __FreeBSD__ |
| #define LOCK_DIR "/var/spool/lock" |
| #else |
| #ifdef __NetBSD__ |
| #define LOCK_DIR "/var/spool/lock" |
| #else |
| #ifdef __OpenBSD__ |
| #define LOCK_DIR "/var/spool/lock" |
| #else |
| /* So which ones is this for? */ |
| /* Probably original 4.4BSD on Vangogh */ |
| /* Plus who knows about Mac OS X... It doesn't even have a cu program */ |
| #define LOCK_DIR "/var/spool/uucp" |
| #endif /* __OpenBSD__ */ |
| #endif /* __NetBSD__ */ |
| #endif /* __FreeBSD__ */ |
| #endif /* __386BSD__ */ |
| #else |
| #ifdef DGUX430 |
| #define LOCK_DIR "/var/spool/locks" |
| #else |
| #ifdef HPUX10 |
| #define LOCK_DIR "/var/spool/locks" |
| #else |
| #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */ |
| #define LOCK_DIR "/etc/locks" |
| #else |
| #ifdef AIXRS |
| #define LOCK_DIR "/etc/locks" |
| #else |
| #ifdef ISIII |
| #define LOCK_DIR "/etc/locks" |
| #else |
| #ifdef HDBUUCP |
| #ifdef M_SYS5 |
| #define LOCK_DIR "/usr/spool/uucp" |
| #else |
| #ifdef M_UNIX |
| #define LOCK_DIR "/usr/spool/uucp" |
| #else |
| #ifdef SVR4 |
| #define LOCK_DIR "/var/spool/locks" |
| #else |
| #ifdef SUNOS4 |
| #define LOCK_DIR "/var/spool/locks" |
| #else |
| #ifdef LINUXFSSTND |
| #define LOCK_DIR "/var/lock"; |
| #else |
| #define LOCK_DIR "/usr/spool/locks" |
| #endif /* LINUXFSSTND */ |
| #endif /* SUNOS4 */ |
| #endif /* SVR4 */ |
| #endif /* M_UNIX */ |
| #endif /* M_SYS5 */ |
| #else |
| #ifdef LCKDIR |
| #define LOCK_DIR "/usr/spool/uucp/LCK" |
| #else |
| #ifdef COHERENT |
| #define LOCK_DIR "/usr/spool/uucp" |
| #else |
| #define LOCK_DIR "/usr/spool/uucp" |
| #endif /* COHERENT */ |
| #endif /* LCKDIR */ |
| #endif /* HDBUUCP */ |
| #endif /* ISIII */ |
| #endif /* AIXRS */ |
| #endif /* RTAIX */ |
| #endif /* HPUX10 */ |
| #endif /* DGUX430 */ |
| #endif /* BSD44 */ |
| #endif /* !LOCK_DIR (outside ifndef) */ |
| |
| #ifdef OSF2 /* OSF/1 2.0 or later */ |
| #ifdef LOCK_DIR /* (maybe 1.x too, who knows...) */ |
| #undef LOCK_DIR |
| #define LOCK_DIR "/var/spool/locks" |
| #endif /* LOCK_DIR */ |
| #endif /* OSF2 */ |
| |
| #ifdef COMMENT |
| /* Sorry no more lockf() -- we lock first and THEN open the device. */ |
| #ifdef SVR4 |
| #ifndef BSD44 |
| #ifndef LOCKF |
| #define LOCKF /* Use lockf() on tty device in SVR4 */ |
| #endif /* LOCKF */ |
| #endif /* BSD44 */ |
| #endif /* SVR4 */ |
| #endif /* COMMENT */ |
| |
| #ifdef NOLOCKF /* But NOLOCKF cancels LOCKF */ |
| #ifdef LOCKF |
| #undef LOCKF |
| #endif /* LOCKF */ |
| #endif /* NOLOCKF */ |
| |
| /* More about this below... */ |
| |
| #endif /* USETTYLOCK */ |
| #endif /* NOUUCP */ |
| |
| /* |
| MYREAD means use our internally defined nonblocking buffered read routine. |
| */ |
| #ifdef ATTSV |
| #define MYREAD |
| #endif /* ATTSV */ |
| |
| #ifdef ATT7300 |
| #ifndef MYREAD |
| #define MYREAD |
| #endif /* MYREAD */ |
| /* bits for attmodem: internal modem in use, restart getty */ |
| #define ISMODEM 1 |
| #define DOGETY 512 |
| #endif /* ATT7300 */ |
| |
| #ifdef BSD42 |
| #define MYREAD |
| #endif /* BSD42 */ |
| |
| #ifdef POSIX |
| #define MYREAD |
| #endif /* POSIX */ |
| #ifdef __bsdi__ |
| #ifndef O_NDELAY |
| #define O_NDELAY O_NONBLOCK |
| #endif /* O_NDELAY */ |
| #endif /* __bsdi__ */ |
| |
| /* |
| Variables available to outside world: |
| |
| dftty -- Pointer to default tty name string, like "/dev/tty". |
| dfloc -- 0 if dftty is console, 1 if external line. |
| dfprty -- Default parity |
| dfflow -- Default flow control |
| ckxech -- Flag for who echoes console typein: |
| 1 - The program (system echo is turned off) |
| 0 - The system (or front end, or terminal). |
| functions that want to do their own echoing should check this flag |
| before doing so. |
| |
| flfnam -- Name of lock file, including its path, e.g., |
| "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77" |
| lkflfn -- Name of link to lock file, including its paths |
| haslock -- Flag set if this kermit established a uucp lock. |
| lockpid -- PID of other process that has desired line open, as string. |
| backgrd -- Flag indicating program executing in background ( & on |
| end of shell command). Used to ignore INT and QUIT signals. |
| rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle |
| SIGTSTP) |
| |
| Functions for assigned communication line (either external or console tty): |
| |
| sysinit() -- System dependent program initialization |
| syscleanup() -- System dependent program shutdown |
| ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access. |
| ttclos() -- Close & reset the tty, releasing any access lock. |
| ttsspd(cps) -- Set the transmission speed of the tty. |
| ttgspd() -- Get (read) the the transmission speed of the tty. |
| ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed. |
| ttvt(speed,flow) -- Put the tty in virtual terminal mode. |
| or in DIALING or CONNECTED modem control state. |
| ttres() -- Restore original tty modes. |
| ttscarr(carrier) -- Set carrier control mode, on/off/auto. |
| ttinl(dest,max,timo) -- Timed read line from the tty. |
| ttinc(timo) -- Timed read character from tty. |
| myread() -- Raw mode bulk buffer read, gives subsequent |
| chars one at a time and simulates FIONREAD. |
| myunrd(c) -- Places c back in buffer to be read (one only) |
| ttchk() -- See how many characters in tty input buffer. |
| ttxin(n,buf) -- Read n characters from tty (untimed). |
| ttol(string,length) -- Write a string to the tty. |
| ttoc(c) -- Write a character to the tty. |
| ttflui() -- Flush tty input buffer. |
| ttsndb() -- Send BREAK signal. |
| ttsndlb() -- Send Long BREAK signal. |
| |
| ttlock(ttname) -- "Lock" tty device against uucp collisions. |
| ttunlck() -- Unlock tty device. |
| |
| For ATT7300/Unix PC, System V: |
| attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem |
| offgetty(ttname) -- Turns off getty(1m) for comms line |
| ongetty(ttname) -- Restores getty() to comms line |
| */ |
| |
| /* |
| Functions for console terminal: |
| |
| congm() -- Get console terminal modes. |
| concb(esc) -- Put the console in single-character wakeup mode with no echo. |
| conbin(esc) -- Put the console in binary (raw) mode. |
| conres() -- Restore the console to mode obtained by congm(). |
| conoc(c) -- Unbuffered output, one character to console. |
| conol(s) -- Unbuffered output, null-terminated string to the console. |
| conola(s) -- Unbuffered output, array of strings to the console. |
| conxo(n,s) -- Unbuffered output, n characters to the console. |
| conchk() -- Check if characters available at console (bsd 4.2). |
| Check if escape char (^\) typed at console (System III/V). |
| coninc(timo) -- Timed get a character from the console. |
| congks(timo) -- Timed get keyboard scan code. |
| conint() -- Enable terminal interrupts on the console if not background. |
| connoi() -- Disable terminal interrupts on the console if not background. |
| |
| Time functions |
| |
| msleep(m) -- Millisecond sleep |
| ztime(&s) -- Return pointer to date/time string |
| rtimer() -- Reset timer |
| gtimer() -- Get elapsed time since last call to rtimer() |
| */ |
| |
| /* Conditional Includes */ |
| |
| /* Whether to include <sys/file.h> */ |
| |
| #ifdef RTU /* RTU doesn't */ |
| #define NOFILEH |
| #endif /* RTU */ |
| |
| #ifdef CIE /* CIE does. */ |
| #undef NOFILEH |
| #endif /* CIE */ |
| |
| #ifdef BSD41 /* 4.1 BSD doesn't */ |
| #define NOFILEH |
| #endif /* BSD41 */ |
| |
| #ifdef is68k /* Integrated Solutions 68000 UNIX */ |
| #define NOFILEH /* e.g. on Plexux P60 and Sun-1 */ |
| #endif /* is68k */ |
| |
| #ifdef MINIX /* MINIX */ |
| #define NOFILEH |
| #endif /* MINIX */ |
| |
| #ifdef COHERENT /* Coherent */ |
| #define NOFILEH |
| #endif /* COHERENT */ |
| |
| #ifndef NOFILEH /* Now include if selected. */ |
| #include <sys/file.h> |
| #endif /* NOFILEH */ |
| |
| /* POSIX */ |
| |
| #ifdef BSD44ORPOSIX /* POSIX uses termios.h */ |
| #define TERMIOS |
| #ifdef __bsdi__ |
| #ifdef POSIX |
| #undef _POSIX_SOURCE /* Get extra stuff from termios.h */ |
| #endif /* POSIX */ |
| #endif /* __bsdi__ */ |
| #include <termios.h> |
| #ifdef LINUX |
| #include <sys/ioctl.h> |
| #endif /* LINUX */ |
| #ifdef QNX16 |
| #include <ioctl.h> |
| #else |
| #ifdef QNX6 |
| #include <ioctl.h> |
| #endif /* QNX6 */ |
| #endif /* QNX16 */ |
| #ifdef __bsdi__ |
| #ifdef POSIX |
| #define _POSIX_SOURCE |
| #endif /* POSIX */ |
| #endif /* __bsdi__ */ |
| #ifndef BSD44 /* Really POSIX */ |
| #ifndef CK_QNX32 /* was CK_QNX32 */ |
| #define NOSYSIOCTLH /* No ioctl's allowed. */ |
| #undef ultrix /* Turn off any ultrix features. */ |
| #endif /* CK_QNX32 */ |
| #endif /* BSD44 */ |
| #endif /* POSIX */ |
| |
| /* System III, System V */ |
| |
| #ifdef ATTSV |
| #ifndef BSD44 |
| #ifndef POSIX |
| #include <termio.h> |
| #endif /* POSIX */ |
| #endif /* BSD44 */ |
| #ifdef TERMIOX |
| /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */ |
| #include <termiox.h> |
| struct termiox rctsx; |
| #else |
| #ifdef STERMIOX |
| #ifdef SCO_OSR504 |
| /* Sorry, this is truly disgusting but it's SCO's fault. */ |
| #ifndef _SVID3 |
| #define _CK_SVID3_X |
| #define _SVID3 |
| #endif /* _SVID3 */ |
| #endif /* SCO_OSR504 */ |
| #include <sys/termiox.h> |
| struct termiox rctsx; |
| #ifdef CK_SVID3_X |
| #undef _SVID3 |
| #undef CK_SVID3_X |
| #endif /* CK_SVID3_X */ |
| #endif /* STERMIOX */ |
| #endif /* TERMIOX */ |
| #endif /* ATTSV */ |
| |
| #ifdef COHERENT /* Use termio.h, not sgtty.h for Coherent */ |
| #include <termio.h> |
| #endif /* COHERENT */ |
| |
| #ifdef MINIX /* MINIX uses ioctl's */ |
| #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */ |
| #endif /* MINIX */ |
| |
| /* Others */ |
| |
| #ifndef NOSYSIOCTLH /* Others use ioctl() */ |
| #ifdef SUN4S5 |
| /* |
| This is to get rid of cpp warning messages that occur because all of |
| these symbols are defined by both termios.h and ioctl.h on the SUN. |
| */ |
| #undef ECHO |
| #undef NL0 |
| #undef NL1 |
| #undef TAB0 |
| #undef TAB1 |
| #undef TAB2 |
| #undef XTABS |
| #undef CR0 |
| #undef CR1 |
| #undef CR2 |
| #undef CR3 |
| #undef FF0 |
| #undef FF1 |
| #undef BS0 |
| #undef BS1 |
| #undef TOSTOP |
| #undef FLUSHO |
| #undef PENDIN |
| #undef NOFLSH |
| #endif /* SUN4S5 */ |
| #include <sys/ioctl.h> |
| #endif /* NOSYSIOCTLH */ |
| /* |
| We really, really, REALLY want FIONREAD, because it is the only way to find |
| out not just *if* stuff is waiting to be read, but how much, which is |
| critical to our sliding-window and streaming procedures, not to mention |
| efficiency of CONNECT, etc. |
| */ |
| #ifdef BELLV10 |
| #include <sys/filio.h> /* For FIONREAD */ |
| #ifdef FIONREAD |
| #define MYREAD |
| #endif /* MYREAD */ |
| #endif /* BELLV10 */ |
| |
| #ifndef FIONREAD |
| /* It wasn't found in ioctl.h or term*.h - try these places: */ |
| #ifdef UNIXWARE |
| #include <sys/filio.h> |
| #else |
| #ifdef SOLARIS |
| #include <sys/filio.h> |
| #endif /* SOLARIS */ |
| #endif /* UNIXWARE */ |
| #endif /* FIONREAD */ |
| |
| #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */ |
| /* |
| <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as |
| something. Due to this, in_chk() uses the FIONREAD instead of RDCHK |
| and the hot keys during file transfer (X to cancel file etc) do not |
| work because FIONREAD doesn't work even though it is defined. |
| |
| NOTE: This might also be true elsewhere. |
| */ |
| #ifdef FIONREAD |
| #undef FIONREAD |
| #endif /* FIONREAD */ |
| #endif /* XENIX */ |
| |
| #ifdef CK_SCOV5 /* Ditto for SCO OpenServer 5.0 */ |
| #ifdef FIONREAD |
| #undef FIONREAD |
| #endif /* FIONREAD */ |
| #endif /* XENIX */ |
| |
| /* Whether to include <fcntl.h> */ |
| |
| #ifndef is68k /* Only a few don't have this one. */ |
| #ifndef BSD41 |
| #ifndef FT21 |
| #ifndef FT18 |
| #ifndef COHERENT |
| #include <fcntl.h> |
| #endif /* COHERENT */ |
| #endif /* FT18 */ |
| #endif /* FT21 */ |
| #endif /* BSD41 */ |
| #endif /* not is68k */ |
| |
| #ifdef COHERENT |
| #ifdef _I386 |
| #include <fcntl.h> |
| #else |
| #include <sys/fcntl.h> |
| #endif /* _I386 */ |
| #endif /* COHERENT */ |
| |
| #ifdef ATT7300 /* Unix PC, internal modem dialer */ |
| #include <sys/phone.h> |
| #endif /* ATT7300 */ |
| |
| #ifdef HPUX /* HP-UX variations. */ |
| #define HPUXJOBCTL |
| #include <sys/modem.h> /* HP-UX modem signals */ |
| #ifdef hp9000s500 /* Model 500 */ |
| #undef HPUXJOBCTL |
| #endif /* hp9000s500 */ |
| #ifdef HPUXPRE65 |
| #undef HPUXJOBCTL |
| typedef long mflag; |
| #endif /* HPUXPRE65 */ |
| #ifdef HPUXJOBCTL |
| #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */ |
| #endif /* HPUXJOBCTL */ |
| #endif /* HPUX */ |
| |
| /* |
| Which time.h files to include... See ckcdeb.h for defaults. |
| Note that 0, 1, 2, or all 3 of these can be included according to |
| the symbol definitions. |
| */ |
| #ifndef NOTIMEH |
| #ifdef TIMEH |
| #include <time.h> |
| #endif /* TIMEH */ |
| #endif /* NOTIMEH */ |
| |
| #ifndef NOSYSTIMEH |
| #ifdef SYSTIMEH |
| #include <sys/time.h> |
| #endif /* SYSTIMEH */ |
| #endif /* NOSYSTIMEH */ |
| |
| #ifndef NOSYSTIMEBH |
| #ifdef SYSTIMEBH |
| #include <sys/timeb.h> |
| #endif /* SYSTIMEBH */ |
| #endif /* NOSYSTIMEBH */ |
| |
| #ifndef NODCLTIMEVAL |
| #ifdef DCLTIMEVAL |
| /* |
| In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to |
| define the structs we need to access the higher speeds, so we have to |
| do it ourselves. |
| */ |
| struct timeval { |
| long tv_sec; |
| long tv_usec; |
| }; |
| struct timezone { |
| int tz_minuteswest; |
| int tz_dsttime; |
| }; |
| #endif /* DCLTIMEVAL */ |
| #endif /* NODCLTIMEVAL */ |
| |
| #ifdef __linux__ |
| /* THIS IS OBSOLETE since about Linux 0.92 */ |
| #ifdef OLINUXHISPEED |
| #include <linux/serial.h> |
| #endif /* OLINUXHISPEED */ |
| #ifdef __alpha__ /* Linux on DEC Alpha */ |
| #ifndef __GLIBC__ /* But not with glibc */ |
| #include <asm/termios.h> |
| #endif /* __GLIBC__ */ |
| #endif /* __alpha__ */ |
| #endif /* __linux__ */ |
| |
| #ifdef NOIEXTEN /* This is broken on some systems */ |
| #undef IEXTEN /* like Convex/OS 9.1 */ |
| #endif /* NOIEXTEN */ |
| #ifndef IEXTEN /* Turn off ^O/^V processing. */ |
| #define IEXTEN 0 /* Needed, at least, on BSDI. */ |
| #endif /* IEXTEN */ |
| /* |
| Pick up definitions needed for select() if we don't have them already. |
| Normally they come from <sys/types.h> but some systems get them from |
| <sys/select.h>... Rather than hardwire all of them into the source, we |
| include it if SELECT_H is defined in compile-time CFLAGS. |
| */ |
| #ifndef SCO_OSR504 |
| #ifdef SELECT_H |
| #include <sys/select.h> |
| #endif /* SELECT_H */ |
| #endif /* SCO_OSR504 */ |
| |
| #ifdef aegis |
| #include "/sys/ins/base.ins.c" |
| #include "/sys/ins/error.ins.c" |
| #include "/sys/ins/ios.ins.c" |
| #include "/sys/ins/sio.ins.c" |
| #include "/sys/ins/pad.ins.c" |
| #include "/sys/ins/time.ins.c" |
| #include "/sys/ins/pfm.ins.c" |
| #include "/sys/ins/pgm.ins.c" |
| #include "/sys/ins/ec2.ins.c" |
| #include "/sys/ins/type_uids.ins.c" |
| #include <default_acl.h> |
| #undef TIOCEXCL |
| #undef FIONREAD |
| #endif /* aegis */ |
| |
| #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */ |
| #undef FIONREAD |
| #endif /* sxaE50 */ |
| |
| /* The following #defines are catch-alls for those systems */ |
| /* that didn't have or couldn't find <file.h>... */ |
| |
| #ifndef FREAD |
| #define FREAD 0x01 |
| #endif /* FREAD */ |
| |
| #ifndef FWRITE |
| #define FWRITE 0x10 |
| #endif /* FWRITE */ |
| |
| #ifndef O_RDONLY |
| #define O_RDONLY 000 |
| #endif /* O_RDONLY */ |
| |
| #ifdef SVORPOSIX |
| /* |
| Modem signals are also forbidden in the POSIX world. But some POSIX-based |
| platforms let us at them anyway if we know where to look. |
| */ |
| #ifndef NEEDMDMDEFS |
| /* Doesn't work for Linux */ |
| #ifdef UNIXWARE7 |
| #define NEEDMDMDEFS |
| #endif /* UNIXWARE7 */ |
| #endif /* NEEDMDMDEFS */ |
| |
| #ifdef NEEDMDMDEFS |
| #ifndef TIOCMGET |
| #define TIOCMGET (('t'<<8)|29) |
| #endif /* TIOCMGET */ |
| |
| #ifndef TIOCM_DTR |
| #define TIOCM_DTR 0x0002 |
| #endif /* TIOCM_DTR */ |
| #ifndef TIOCM_RTS |
| #define TIOCM_RTS 0x0004 |
| #endif /* TIOCM_RTS */ |
| #ifndef TIOCM_CTS |
| #define TIOCM_CTS 0x0020 |
| #endif /* TIOCM_CTS */ |
| #ifndef TIOCM_CAR |
| #define TIOCM_CAR 0x0040 |
| #endif /* TIOCM_CAR */ |
| #ifndef TIOCM_RNG |
| #define TIOCM_RNG 0x0080 |
| #endif /* TIOCM_RNG */ |
| #ifndef TIOCM_DSR |
| #define TIOCM_DSR 0x0100 |
| #endif /* TIOCM_DSR */ |
| #endif /* NEEDMDMDEFS */ |
| #endif /* SVORPOSIX */ |
| |
| /* Declarations */ |
| |
| #ifdef OXOS |
| #undef TCGETA |
| #undef TCSETA |
| #undef TCSETAW |
| #undef TCSETAF |
| #define TCGETA TCGETS |
| #define TCSETA TCSETS |
| #define TCSETAW TCSETSW |
| #define TCSETAF TCSETSF |
| #define termio termios |
| #endif /* OXOS */ |
| |
| #ifdef SVORPOSIX /* AT&T Sys V or POSIX */ |
| #ifdef UNIXWAREPOSIX /* UnixWare 7 POSIX build */ |
| /* |
| In Unixware POSIX builds, <[sys/]time.h> refuses to define the |
| structs we need to access the higher speeds, so we have to do it |
| ourselves. |
| */ |
| struct timeval { |
| long tv_sec; |
| long tv_usec; |
| }; |
| struct timezone { |
| int tz_minuteswest; |
| int tz_dsttime; |
| }; |
| #endif /* UNIXWAREPOSIX */ |
| #endif /* SVORPOSIX */ |
| |
| #ifdef __GNUC__ |
| #ifdef XENIX |
| /* |
| Because Xenix <time.h> doesn't declare time() if we're using gcc. |
| */ |
| time_t time(); |
| #endif /* XENIX */ |
| #endif /* __GNUC__ */ |
| |
| /* Special stuff for V7 input buffer peeking */ |
| |
| #ifdef V7 |
| int kmem[2] = { -1, -1}; |
| char *initrawq(), *qaddr[2]={0,0}; |
| #define CON 0 |
| #define TTY 1 |
| #endif /* V7 */ |
| |
| /* dftty is the device name of the default device for file transfer */ |
| /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */ |
| |
| #ifdef BEOS |
| char * dftty = NULL; |
| char * dfmdm = "none"; |
| int dfloc = 0; /* that goes in local mode by default */ |
| #else |
| #ifndef DFTTY |
| #ifdef PROVX1 |
| char *dftty = "/dev/com1.dout"; /* Only example so far of a system */ |
| char *dfmdm = "none"; |
| int dfloc = 1; /* that goes in local mode by default */ |
| #else |
| char *dftty = CTTNAM; /* Remote by default, use normal */ |
| char *dfmdm = "none"; |
| int dfloc = 0; /* controlling terminal name. */ |
| #endif /* PROVX1 */ |
| #else |
| char *dftty = DFTTY; /* Default location specified on */ |
| char *dfmdm = "none"; /* command line. */ |
| int dfloc = 1; /* controlling terminal name. */ |
| #endif /* DFTTY */ |
| #endif /* BEOS */ |
| |
| #define CON_RES 0 /* Console state is "reset" */ |
| #define CON_CB 1 /* Console state is CBREAK */ |
| #define CON_BIN 2 /* Console state is binary */ |
| static int constate = CON_RES; |
| |
| #define CONI_RES 0 /* Console interrupts are "reset" */ |
| #define CONI_INT 1 /* Console intterupts are set */ |
| #define CONI_NOI 2 /* Console intterupts are disabled */ |
| static int conistate = CONI_RES; |
| |
| #ifdef CK_SMALL |
| #define CONBUFSIZ 15 |
| #else |
| #define CONBUFSIZ 255 |
| #endif /* CK_SMALL */ |
| static char conbuf[CONBUFSIZ]; /* Console readahead buffer */ |
| static int conbufn = 0; /* Chars in readahead buffer */ |
| static char *conbufp = conbuf; /* Next char in readahead buffer */ |
| |
| char cttnam[DEVNAMLEN+1] = { '\0', '\0' }; /* Determined at runtime */ |
| |
| #ifdef RTU |
| int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */ |
| #endif /* RTU */ |
| |
| int dfprty = DEFPAR; /* Default parity (0 = none) */ |
| int ttprty = 0; /* The parity that is in use. */ |
| static int ttpmsk = 0xff; /* Parity stripping mask. */ |
| int ttmdm = 0; /* Modem in use. */ |
| int ttcarr = CAR_AUT; /* Carrier handling mode. */ |
| int dfflow = FLO_NONE; /* Default flow control is NONE */ |
| int backgrd = 0; /* Assume in foreground (no '&' ) */ |
| #ifdef F_SETFL |
| int iniflags = -1; /* fcntl flags for ttyfd */ |
| #endif /* F_SETFL */ |
| int fdflag = 0; /* Flag for redirected stdio */ |
| int ttfdflg = 0; /* Open File descriptor was given */ |
| int tvtflg = 0; /* Flag that ttvt has been called */ |
| long ttspeed = -1L; /* For saving speed */ |
| int ttflow = -9; /* For saving flow */ |
| int ttld = -1; /* Line discipline */ |
| |
| #ifdef sony_news |
| static int km_con = -1; /* Kanji mode for console tty */ |
| static int km_ext = -1; /* Kanji mode for external device */ |
| #endif /* sony_news */ |
| |
| #ifdef PARSENSE |
| static int needpchk = 1; /* Need parity check */ |
| #else |
| static int needpchk = 0; |
| #endif /* PARSENSE */ |
| |
| extern int stopbits; /* Stop bits */ |
| #ifdef HWPARITY |
| /* |
| Unfortunately we must do this with global variables rather than through the |
| tt...() APIs to avoid changing the APIs and the many modules that use them. |
| If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data |
| bits + parity or 8 data bits and no parity, and overrides the regular parity |
| variable, which is communicated to this module thru ttpkt(), and represented |
| locally by the ttprty variable. |
| */ |
| extern int hwparity; /* Hardware parity */ |
| #endif /* HWPARITY */ |
| |
| #ifdef TCPSOCKET |
| #ifdef TCP_NODELAY |
| static int nodelay_sav = -1; |
| #endif /* TCP_NODELAY */ |
| #endif /* TCPSOCKET */ |
| |
| static int sigint_ign = 0; /* SIGINT is ignored */ |
| |
| /* |
| Having this module rely on external globals is bad, but fixing this |
| requires overhaul of the ck*tio.c modules for all the different operating |
| systems supported by C-Kermit. Left for a future release. |
| */ |
| extern int ttnproto; /* Defined in ckcnet.c */ |
| extern int ttnet; /* Defined in ckcnet.c */ |
| extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */ |
| extern int xsuspend, wasclosed; |
| extern int inserver, local; |
| |
| int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */ |
| |
| int ckmaxfiles = 0; /* Max number of open files */ |
| |
| #ifdef CK_ENCRYPTION /* Kerberos */ |
| #include "ckuath.h" |
| extern int me_encrypt, u_encrypt; |
| #endif /* CK_ENCRYPTION */ |
| |
| /* Declarations of variables global within this module */ |
| |
| #ifdef TTLEBUF /* See ckcnet.h */ |
| int ttpush = -1; |
| #define LEBUFSIZ 4096 |
| static CHAR le_buf[LEBUFSIZ]; |
| static int le_start = 0, le_end = 0, le_data = 0; |
| #endif /* TTLEBUF */ |
| |
| static int gotsigs = 0; |
| |
| static time_t tcount = (time_t)0; /* Elapsed time counter */ |
| |
| static SIGTYP (*saval)() = NULL; /* For saving alarm() handler */ |
| static SIGTYP (*savquit)() = NULL; /* and other signal handlers */ |
| #ifdef SIGUSR1 |
| static SIGTYP (*savusr1)() = NULL; |
| #endif /* SIGUSR1 */ |
| #ifdef SIGUSR2 |
| static SIGTYP (*savusr2)() = NULL; |
| #endif /* SIGUSR2 */ |
| #ifdef SIGPIPE |
| static SIGTYP (*savpipe)() = NULL; |
| #endif /* SIGPIPE */ |
| #ifdef SIGDANGER |
| static SIGTYP (*savdanger)() = NULL; |
| #endif /* SIGDANGER */ |
| |
| #ifndef NOJC |
| static SIGTYP (*jchdlr)() = NULL; /* For checking suspend handler */ |
| #endif /* NOJC */ |
| static int jcshell = -1; /* And flag for result */ |
| |
| /* |
| BREAKNULS is defined for systems that simulate sending a BREAK signal |
| by sending a bunch of NUL characters at low speed. |
| */ |
| #ifdef PROVX1 |
| #ifndef BREAKNULS |
| #define BREAKNULS |
| #endif /* BREAKNULS */ |
| #endif /* PROVX1 */ |
| |
| #ifdef V7 |
| #ifndef BREAKNULS |
| #define BREAKNULS |
| #endif /* BREAKNULS */ |
| #endif /* V7 */ |
| |
| #ifdef BREAKNULS |
| static char /* A string of nulls */ |
| *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"; |
| #endif /* BREAKNULS */ |
| |
| #ifdef CK_POSIX_SIG /* Longjump buffers */ |
| static sigjmp_buf sjbuf; /* POSIX signal handling */ |
| #else |
| static jmp_buf sjbuf; |
| #endif /* CK_POSIX_SIG */ |
| |
| #ifdef V7 |
| static jmp_buf jjbuf; |
| #endif /* V7 */ |
| |
| /* static */ /* (Not static any more) */ |
| int ttyfd = -1; /* TTY file descriptor */ |
| |
| int ttpipe = 0; /* NETCMD: Use pipe instead of ttyfd */ |
| int ttpty = 0; /* NETPTY: Use pty instead of ttfyd */ |
| |
| #ifdef NETCMD |
| #ifdef NETCONN |
| static int pipe0[2], pipe1[2]; /* Pipes for net i/o */ |
| #endif /* NETCONN */ |
| static PID_T ttpid = 0; /* Process ID for fork */ |
| static int fdin, fdout; /* File descriptors for pipe */ |
| static FILE * ttout = NULL; /* File pointer for output pipe */ |
| #ifdef DCLFDOPEN |
| /* fdopen() needs declaring because it's not declared in <stdio.h> */ |
| _PROTOTYP( FILE * fdopen, (int, char *) ); |
| #endif /* DCLFDOPEN */ |
| #endif /* NETCMD */ |
| |
| extern int pexitstat, quiet; |
| |
| #ifdef Plan9 |
| int ttyctlfd = -1; /* TTY control channel - What? UNIX doesn't have one? */ |
| int consctlfd = -1; /* Console control channel */ |
| int noisefd = -1; /* tone channel */ |
| static int ttylastspeed = -1; /* So we can lie about the speed */ |
| #endif /* Plan9 */ |
| |
| int telnetfd = 0; /* File descriptor is for telnet */ |
| #ifdef NETCONN |
| int x25fd = 0; /* File descriptor is for X.25 */ |
| #endif /* NETCONN */ |
| |
| char lockpid[16] = { '\0', '\0' }; /* PID stored in lockfile, as string */ |
| |
| static int lkf = 0, /* Line lock flag */ |
| cgmf = 0, /* Flag that console modes saved */ |
| xlocal = 0, /* Flag for tty local or remote */ |
| curcarr = 0; /* Carrier mode: require/ignore. */ |
| |
| static int netconn = 0; /* 1 if network connection active */ |
| |
| static char escchr; /* Escape or attn character */ |
| |
| #ifdef CK_SCO32V4 |
| #include <sys/time.h> |
| #endif /* CK_SCO32V4 */ |
| |
| #ifdef HAVE_TV |
| static struct timeval tv; /* For getting time, from sys/time.h */ |
| #endif /* HAVE_TV */ |
| #ifdef HAVE_TZ |
| static struct timezone tz; |
| #endif /* HAVE_TZ */ |
| |
| #ifdef OSF |
| static struct timeb ftp; /* And from sys/timeb.h */ |
| #endif /* OSF */ |
| |
| #ifdef BSD29 |
| static long xclock; /* For getting time from sys/time.h */ |
| static struct timeb ftp; /* And from sys/timeb.h */ |
| #endif /* BSD29 */ |
| |
| #ifdef BSD41 |
| static long xclock; /* For getting time from sys/time.h */ |
| static struct timeb ftp; /* And from sys/timeb.h */ |
| #endif /* BSD41 */ |
| |
| #ifdef BELLV10 |
| static long xclock; /* For getting time from sys/time.h */ |
| static struct timeb ftp; /* And from sys/timeb.h */ |
| #endif /* BELLV10 */ |
| |
| #ifdef FT21 |
| static long xclock; /* For getting time from sys/time.h */ |
| static struct timeb ftp; /* And from sys/timeb.h */ |
| #endif /* FT21 */ |
| |
| #ifdef TOWER1 |
| static long xclock; /* For getting time from sys/time.h */ |
| static struct timeb ftp; /* And from sys/timeb.h */ |
| #endif /* TOWER1 */ |
| |
| #ifdef COHERENT |
| static long xclock; /* For getting time from sys/time.h */ |
| static struct timeb ftp; /* And from sys/timeb.h */ |
| #endif /* COHERENT */ |
| |
| #ifdef V7 |
| static long xclock; |
| #endif /* V7 */ |
| |
| /* sgtty/termio information... */ |
| |
| #ifdef BSD44ORPOSIX /* POSIX or BSD44 */ |
| static struct termios |
| ttold, ttraw, tttvt, ttcur, |
| ccold, ccraw, cccbrk; |
| #else /* BSD, V7, etc */ |
| |
| #ifdef COHERENT /* Hack alert... */ |
| #define ATTSV |
| #endif /* COHERENT */ |
| |
| #ifdef ATTSV |
| static struct termio ttold = {0}; /* Init'd for word alignment, */ |
| static struct termio ttraw = {0}; /* which is important for some */ |
| static struct termio tttvt = {0}; /* systems, like Zilog... */ |
| static struct termio ttcur = {0}; |
| static struct termio ccold = {0}; |
| static struct termio ccraw = {0}; |
| static struct termio cccbrk = {0}; |
| #else |
| static struct sgttyb /* sgtty info... */ |
| ttold, ttraw, tttvt, ttcur, /* for communication line */ |
| ccold, ccraw, cccbrk; /* and for console */ |
| #ifdef BELLV10 |
| static struct ttydevb /* Device info... */ |
| tdold, tdcur; /* for communication device */ |
| #endif /* BELLV10 */ |
| #ifdef TIOCGETC |
| static struct tchars tchold, tchnoi; |
| |
| static int tcharf; |
| #endif /* TIOCGETC */ |
| #ifdef TIOCGLTC |
| static struct ltchars ltchold, ltchnoi; |
| static int ltcharf; |
| #endif /* TIOCGLTC */ |
| int lmodef = 0; /* Local modes */ |
| int lmode = 0; |
| #endif /* ATTSV */ |
| #endif /* BSD44ORPOSIX */ |
| |
| #ifdef COMMENT |
| /* It picks up the speeds but they don't work */ |
| #ifdef UNIXWARE /* For higher serial speeds */ |
| #ifdef UW7 /* in Unixware 7.0 */ |
| #include <sys/asyc.h> /* This picks up 57600 and 115200 */ |
| #endif /* UW7 */ |
| #endif /* UNIXWARE */ |
| #endif /* COMMENT */ |
| |
| #ifdef PROVX1 |
| static struct sgttyb ttbuf; |
| #endif /* PROVX1 */ |
| |
| #ifdef ultrix |
| /* do we really need this? */ |
| static struct sgttyb vanilla; |
| #endif /* ultrix */ |
| |
| #ifdef ATT7300 |
| static int attmodem = 0; /* ATT7300 internal-modem status */ |
| struct updata dialer = {0}; /* Condition dialer for data call */ |
| #endif /* ATT7300 */ |
| |
| #ifndef NOUUCP |
| #define FLFNAML 128 |
| #ifndef USETTYLOCK |
| #ifdef RTAIX |
| char lkflfn[FLFNAML] = { '\0', '\0' }; /* and possible link to it */ |
| #endif /* RTAIX */ |
| char lock2[FLFNAML] = { '\0', '\0' }; /* Name of second lockfile */ |
| #endif /* USETTYLOCK */ |
| #else |
| #define FLFNAML 7 |
| #endif /* NOUUCP */ |
| char flfnam[FLFNAML+1] = { '\0', '\0' }; /* UUCP lock file path name */ |
| |
| int haslock = 0; /* =1 if this kermit locked uucp */ |
| |
| #ifndef OXOS |
| #ifdef SVORPOSIX |
| static int conesc = 0; /* set to 1 if esc char (^\) typed */ |
| #else |
| #ifdef V7 |
| static int conesc = 0; |
| #else |
| #ifdef C70 |
| static int conesc = 0; |
| #endif /* C70 */ |
| #endif /* V7 */ |
| #endif /* SVORPOSIX */ |
| #endif /* OXOS */ |
| |
| /* Local copy of comm device name or network host */ |
| static char ttnmsv[DEVNAMLEN+1] = { '\0', '\0' }; |
| #ifdef USETTYLOCK |
| static char lockname[DEVNAMLEN+1]; /* Ditto, the part after "/dev/". */ |
| #endif /* USETTYLOCK */ |
| |
| #ifdef aegis |
| static status_$t st; /* error status return value */ |
| static short concrp = 0; /* true if console is CRP pad */ |
| static uid_$t ttyuid; /* tty type uid */ |
| static uid_$t conuid; /* stdout type uid */ |
| |
| /* APOLLO Aegis main() |
| * establish acl usage and cleanup handling |
| * this makes sure that CRP pads |
| * get restored to a usable mode |
| */ |
| main(argc,argv) int argc; char **argv; { |
| status_$t status; |
| pfm_$cleanup_rec dirty; |
| |
| PID_T pid = getpid(); |
| |
| /* acl usage according to invoking environment */ |
| default_acl(USE_DEFENV); |
| |
| /* establish a cleanup continuation */ |
| status = pfm_$cleanup(dirty); |
| if (status.all != pfm_$cleanup_set) { |
| /* only handle faults for the original process */ |
| if (pid == getpid() && status.all > pgm_$max_severity) { |
| /* blew up in main process */ |
| status_$t quo; |
| pfm_$cleanup_rec clean; |
| |
| /* restore the console in any case */ |
| conres(); |
| |
| /* attempt a clean exit */ |
| debug(F101, "cleanup fault status", "", status.all); |
| |
| /* doexit(), then send status to continuation */ |
| quo = pfm_$cleanup(clean); |
| if (quo.all == pfm_$cleanup_set) |
| doexit(pgm_$program_faulted,-1); |
| else if (quo.all > pgm_$max_severity) |
| pfm_$signal(quo); /* blew up in doexit() */ |
| } |
| /* send to the original continuation */ |
| pfm_$signal(status); |
| /*NOTREACHED*/ |
| } |
| return(ckcmai(argc, argv)); |
| } |
| #endif /* aegis */ |
| |
| /* ANSI-style prototypes for internal functions. */ |
| /* Functions used outside this module are prototyped in ckcker.h. */ |
| |
| #ifdef apollo |
| _PROTOTYP( SIGTYP timerh, () ); |
| _PROTOTYP( SIGTYP cctrap, () ); |
| _PROTOTYP( SIGTYP esctrp, () ); |
| _PROTOTYP( SIGTYP sig_ign, () ); |
| #else |
| _PROTOTYP( SIGTYP timerh, (int) ); |
| _PROTOTYP( SIGTYP cctrap, (int) ); |
| _PROTOTYP( SIGTYP esctrp, (int) ); |
| #endif /* apollo */ |
| _PROTOTYP( int do_open, (char *) ); |
| _PROTOTYP( static int in_chk, (int, int) ); |
| _PROTOTYP( static int ttrpid, (char *) ); |
| _PROTOTYP( static int ttchkpid, (char *) ); |
| _PROTOTYP( static int ttlock, (char *) ); |
| _PROTOTYP( static int ttunlck, (void) ); |
| _PROTOTYP( int mygetbuf, (void) ); |
| _PROTOTYP( int myfillbuf, (void) ); |
| _PROTOTYP( VOID conbgt, (int) ); |
| #ifdef ACUCNTRL |
| _PROTOTYP( VOID acucntrl, (char *, char *) ); |
| #endif /* ACUCNTRL */ |
| |
| #ifdef BSD44ORPOSIX |
| _PROTOTYP( int carrctl, (struct termios *, int) ); |
| #else |
| #ifdef ATTSV |
| _PROTOTYP( int carrctl, (struct termio *, int) ); |
| #else |
| _PROTOTYP( int carrctl, (struct sgttyb *, int) ); |
| #endif /* ATTSV */ |
| #endif /* BSD44ORPOSIX */ |
| |
| #ifdef ATT7300 |
| _PROTOTYP( int attdial, (char *, long, char *) ); |
| _PROTOTYP( int offgetty, (char *) ); |
| _PROTOTYP( int ongetty, (char *) ); |
| #endif /* ATT7300 */ |
| |
| #ifdef BEOSORBEBOX |
| #ifdef SELECT |
| /* BeOS is not capable of using SELECT on anything but sockets */ |
| #undef SELECT |
| #endif /* SELECT */ |
| #include <kernel/OS.h> |
| /* #ifdef BE_DR_7 */ |
| static double time_started = 0.0; |
| struct ALARM_STRUCT { |
| thread_id thread; |
| int time; |
| }; |
| static thread_id alarm_thread = -1; |
| static struct ALARM_STRUCT alarm_struct; |
| _PROTOTYP( long do_alarm, (void *) ); |
| _PROTOTYP( unsigned int alarm, (unsigned int) ); |
| _PROTOTYP( void alarm_expired, (void) ); |
| /* #endif */ /* BE_DR_7 */ |
| #endif /* BEOSORBEBOX */ |
| |
| #ifndef xunchar |
| #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */ |
| #endif /* xunchar */ |
| |
| #ifdef CK_ANSIC |
| static char * |
| xxlast(char *s, char c) |
| #else |
| static char * |
| xxlast(s,c) char *s; char c; |
| #endif /* CK_ANSIC */ |
| /* xxlast */ { /* Last occurrence of character c in string s. */ |
| int i; |
| for (i = (int)strlen(s); i > 0; i--) |
| if (s[i-1] == c ) return(s + (i - 1)); |
| return(NULL); |
| } |
| |
| /* Timeout handler for communication line input functions */ |
| |
| /*ARGSUSED*/ |
| SIGTYP |
| timerh(foo) int foo; { |
| ttimoff(); |
| #ifdef BEOSORBEBOX |
| /* #ifdef BE_DR_7 */ |
| alarm_expired(); |
| /* #endif */ /* BE_DR_7 */ |
| #endif /* BEOSORBEBOX */ |
| #ifdef CK_POSIX_SIG |
| siglongjmp(sjbuf,1); |
| #else |
| longjmp(sjbuf,1); |
| #endif /* CK_POSIX_SIG */ |
| } |
| |
| /*ARGSUSED*/ |
| SIGTYP |
| xtimerh(foo) int foo; { /* Like timerh() but does */ |
| #ifdef BEOSORBEBOX /* not reset the timer itslef */ |
| /* #ifdef BE_DR_7 */ |
| alarm_expired(); |
| /* #endif */ /* BE_DR_7 */ |
| #endif /* BEOSORBEBOX */ |
| #ifdef CK_POSIX_SIG |
| siglongjmp(sjbuf,1); |
| #else |
| longjmp(sjbuf,1); |
| #endif /* CK_POSIX_SIG */ |
| } |
| |
| |
| /* Control-C trap for communication line input functions */ |
| |
| int cc_int; /* Flag */ |
| SIGTYP (* occt)(); /* For saving old SIGINT handler */ |
| |
| /*ARGSUSED*/ |
| SIGTYP |
| cctrap(foo) int foo; { /* Needs arg for ANSI C */ |
| cc_int = 1; /* signal() prototype. */ |
| return; |
| } |
| |
| /* S Y S I N I T -- System-dependent program initialization. */ |
| |
| /* |
| * ttgwsiz() returns: |
| * 1 tt_rows and tt_cols are known, both altered, both > 0 |
| * 0 tt_rows and/or tt_cols are known, both altered, one or both <= 0 |
| * -1 tt_rows and tt_cols are unknown and unaltered |
| */ |
| |
| extern int tt_rows, tt_cols; |
| |
| static int |
| xttgwsiz() { |
| char *p; |
| int rows = 0, cols = 0; |
| p = getenv("LINES"); |
| debug(F110,"xttgwsiz LINES",p,0); |
| if (p) { |
| rows = atol(p); |
| if (rows > 0) { |
| p = getenv("COLUMNS"); |
| debug(F110,"xttgwsiz COLUMNS",p,0); |
| if (p) { |
| cols = atol(p); |
| if (cols > 0) { |
| tt_rows = rows; |
| tt_cols = cols; |
| return(1); |
| } |
| return(0); |
| } |
| } |
| } |
| return(-1); |
| } |
| |
| #ifdef TTLEBUF |
| VOID |
| le_init() { /* LocalEchoInit() */ |
| int i; |
| for (i = 0; i < LEBUFSIZ; i++) |
| le_buf[i] = '\0'; |
| le_start = 0; |
| le_end = 0; |
| le_data = 0; |
| } |
| |
| VOID |
| le_clean() { /* LocalEchoCleanup() */ |
| le_init(); |
| return; |
| } |
| |
| int |
| le_inbuf() { |
| int rc = 0; |
| if (le_start != le_end) { |
| rc = (le_end - |
| le_start + |
| LEBUFSIZ) % LEBUFSIZ; |
| } |
| debug(F111,"le_inbuf","chars waiting",rc); |
| return(rc); |
| } |
| |
| int |
| #ifdef CK_ANSIC |
| le_putchar(CHAR ch) |
| #else |
| le_putchar(ch) CHAR ch; |
| #endif /* CK_ANSIC */ |
| /* le_putchar */ { |
| #ifdef COMMENT |
| /* In UNIX we do not have another thread taking chars out of the buffer */ |
| while ((le_start - le_end == 1) || |
| (le_start == 0 && le_end == LEBUFSIZ - 1)) { |
| /* Buffer is full */ |
| debug(F111,"le_putchar","Buffer is Full",ch); |
| ReleaseLocalEchoMutex() ; |
| msleep(250); |
| RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ; |
| } |
| #else |
| if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) { |
| debug(F110,"le_putchar","buffer is full",0); |
| return(-1); |
| } |
| #endif /* COMMENT */ |
| le_buf[le_end++] = ch; |
| if (le_end == LEBUFSIZ) |
| le_end = 0; |
| le_data = 1; |
| return(0); |
| } |
| |
| int |
| #ifdef CK_ANSIC |
| le_puts(CHAR * s, int n) |
| #else |
| le_puts(s,n) CHAR * s; int n; |
| #endif /* CK_ANSIC */ |
| /* le_puts */ { |
| int rc = 0; |
| int i = 0; |
| CHAR * p = (CHAR *)"le_puts"; |
| hexdump(p,s,n); |
| for (i = 0; i < n; i++) |
| rc = le_putchar((char)s[i]); |
| debug(F101,"le_puts","",rc); |
| return(rc); |
| } |
| |
| int |
| #ifdef CK_ANSIC |
| le_putstr(CHAR * s) |
| #else |
| le_putstr(s) CHAR * s; |
| #endif /* CK_ANSIC */ |
| /* le_puts */ { |
| CHAR * p; |
| int rc = 0; |
| p = (CHAR *)"le_putstr"; |
| hexdump(p,s,(int)strlen((char *)s)); |
| for (p = s; *p && !rc; p++) |
| rc = le_putchar(*p); |
| return(rc); |
| } |
| |
| int |
| #ifdef CK_ANSIC |
| le_getchar(CHAR * pch) |
| #else /* CK_ANSIC */ |
| le_getchar(pch) CHAR * pch; |
| #endif /* CK_ANSIC */ |
| /* le_gatchar */ { |
| int rc = 0; |
| if (le_start != le_end) { |
| *pch = le_buf[le_start]; |
| le_buf[le_start] = 0; |
| le_start++; |
| |
| if (le_start == LEBUFSIZ) |
| le_start = 0; |
| |
| if (le_start == le_end) { |
| le_data = 0; |
| } |
| rc++; |
| } else { |
| *pch = 0; |
| } |
| return(rc); |
| } |
| #endif /* TTLEBUF */ |
| |
| #ifdef COMMENT |
| /* |
| Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ. |
| But as far as I know, whenever TIOCGSIZE is defined, it is |
| equated to TIOCGWINSZ. For cases where this is not done, try this: |
| */ |
| #ifndef TIOCGWINSZ |
| #ifdef TIOCGSIZE |
| #define TIOCGWINSZ TIOCGSIZE |
| #endif /* TIOCGSIZE */ |
| #endif /* TIOCGWINSZ */ |
| #endif /* COMMENT */ |
| |
| static int tt_xpixel = 0, tt_ypixel = 0; |
| |
| int |
| ttgwsiz() { |
| int x = 0; |
| #ifndef NONAWS |
| #ifdef QNX |
| /* |
| NOTE: TIOCGWSIZ works here too, but only in the 32-bit version. |
| This code works for both the 16- and 32-bit versions. |
| */ |
| extern int dev_size(int, int, int, int *, int *); |
| int r, c; |
| |
| if (dev_size(0, -1, -1, &r, &c) == 0) { |
| debug(F101,"ttgwsiz QNX r","",r); |
| debug(F101,"ttgwsiz QNX c","",c); |
| tt_rows = r; |
| tt_cols = c; |
| return ((r > 0 && c > 0) ? 1 : 0); |
| } else return(xttgwsiz()); |
| #else /* QNX */ |
| #ifdef TIOCGWINSZ |
| |
| /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */ |
| #ifdef XENIX /* SCO UNIX 3.2v4.0 */ |
| #include <sys/stream.h> /* typedef mblk_t needed by ptem.h */ |
| #include <sys/ptem.h> /* for ttgwsiz() */ |
| #endif /* XENIX */ |
| |
| #ifdef I386IX /* Ditto for Interactive */ |
| #include <sys/stream.h> |
| #include <sys/ptem.h> |
| #endif /* I386IX */ |
| |
| /* Note, the above might be needed for some other older SVR3 Intel makes... */ |
| |
| struct winsize w; |
| tt_xpixel = 0; |
| tt_ypixel = 0; |
| |
| #ifdef IKSD |
| if (inserver) |
| return(xttgwsiz()); |
| #endif /* IKSD */ |
| x = ioctl(0, (int)TIOCGWINSZ, (char *)&w); |
| debug(F101,"ttgwsiz TIOCGWINSZ","",x); |
| if (x < 0) { |
| return(xttgwsiz()); |
| } else if (w.ws_row > 0 && w.ws_col > 0) { |
| tt_rows = w.ws_row; |
| tt_cols = w.ws_col; |
| tt_xpixel = w.ws_xpixel; |
| tt_ypixel = w.ws_ypixel; |
| debug(F101,"ttgwsiz tt_rows","",tt_rows); |
| debug(F101,"ttgwsiz tt_cols","",tt_cols); |
| return(1); |
| } else { |
| debug(F100,"ttgwsiz TIOCGWINSZ 00","",0); |
| return(xttgwsiz()); |
| } |
| #else |
| return(xttgwsiz()); |
| #endif /* TIOCGWINSZ */ |
| #endif /* QNX */ |
| #endif /* NONAWS */ |
| } |
| |
| |
| #ifndef NOSIGWINCH |
| #ifdef SIGWINCH |
| SIGTYP |
| winchh(foo) int foo; { /* SIGWINCH handler */ |
| int x = 0; |
| #ifdef NETPTY |
| extern int pty_fork_pid; |
| #endif /* NETPTY */ |
| #ifdef CK_TTYFD |
| #ifndef VMS |
| extern int ttyfd; |
| #endif /* VMS */ |
| #endif /* CK_TTYFD */ |
| extern int tt_rows, tt_cols, cmd_rows, cmd_cols; |
| #ifdef DEBUG |
| if (deblog) { |
| debug(F100,"***************","",0); |
| debug(F100,"SIGWINCH caught","",0); |
| debug(F100,"***************","",0); |
| #ifdef NETPTY |
| debug(F101,"SIGWINCH pty_fork_pid","",pty_fork_pid); |
| #endif /* NETPTY */ |
| } |
| #endif /* DEUB */ |
| signal(SIGWINCH,winchh); /* Re-arm the signal */ |
| x = ttgwsiz(); /* Get new window size */ |
| cmd_rows = tt_rows; /* Adjust command screen too */ |
| cmd_cols = tt_cols; |
| |
| #ifdef CK_TTYFD |
| if /* If we don't have a connection */ |
| #ifdef VMS /* we're done. */ |
| (vmsttyfd() == -1) |
| #else |
| (ttyfd == -1) |
| #endif /* VMS */ |
| #else |
| (!local) |
| #endif /* CK_TTYFD */ |
| return; |
| |
| #ifdef NETPTY |
| if (pty_fork_pid > -1) { /* "set host" to a PTY? */ |
| int x; |
| |
| #ifdef TIOCSWINSZ |
| struct winsize w; /* Resize the PTY */ |
| errno = 0; |
| w.ws_col = tt_cols; |
| w.ws_row = tt_rows; |
| w.ws_xpixel = tt_xpixel; |
| w.ws_ypixel = tt_ypixel; |
| x = ioctl(ttyfd,TIOCSWINSZ,&w); |
| debug(F101,"winchh TIOCSWINSZ","",x); |
| debug(F101,"winchh TIOCSWINSZ errno","",errno); |
| #endif /* TIOCSWINSZ */ |
| |
| errno = 0; |
| x = kill(pty_fork_pid,SIGWINCH); |
| debug(F101,"winchh kill","",x); |
| debug(F101,"winchh kill errno","",errno); |
| } |
| #endif /* NETPTY */ |
| |
| /* |
| This should be OK. It might seem that sending this from |
| interrupt level could interfere with another TELNET IAC string |
| that was in the process of being sent. But we always send |
| TELNET strings with a single write(), which should prevent mixups. |
| blah_snaws() should protect themselves from being called on the |
| wrong kind of connection. |
| */ |
| #ifdef TCPSOCKET |
| #ifndef NOTTGWSIZ |
| if (x > 0 && tt_rows > 0 && tt_cols > 0) { |
| tn_snaws(); |
| #ifdef RLOGCODE |
| rlog_naws(); |
| #endif /* RLOGCODE */ |
| } |
| #endif /* NOTTGWSIZ */ |
| #endif /* TCPSOCKET */ |
| SIGRETURN; |
| } |
| #endif /* SIGWINCH */ |
| #endif /* NOSIGWINCH */ |
| |
| SIGTYP |
| sighup(foo) int foo; { /* SIGHUP handler */ |
| backgrd = 1; |
| debug(F100,"***************","",0); |
| debug(F100,"SIGHUP received","",0); |
| debug(F100,"***************","",0); |
| doexit(BAD_EXIT,-1); |
| /*NOTREACHED*/ |
| SIGRETURN; /* Shut picky compilers up... */ |
| } |
| |
| #ifdef CK_SCO32V4 |
| /* Exists but there is no prototype in the header files */ |
| _PROTOTYP( char * ttyname, (int) ); |
| #else |
| #ifdef SV68R3V6 |
| _PROTOTYP( char * ttyname, (int) ); |
| #else |
| #ifdef ultrix |
| _PROTOTYP( char * ttyname, (int) ); |
| #else |
| #ifdef HPUX6 |
| _PROTOTYP( char * ttyname, (int) ); |
| #else |
| #ifdef HPUX5 |
| _PROTOTYP( char * ttyname, (int) ); |
| #else |
| #ifdef PS2AIX10 |
| _PROTOTYP( char * ttyname, (int) ); |
| #else |
| #ifdef BSD42 |
| _PROTOTYP( char * ttyname, (int) ); |
| #endif /* BSD42 */ |
| #endif /* PS2AIX10 */ |
| #endif /* HPUX5 */ |
| #endif /* HPUX6 */ |
| #endif /* ultrix */ |
| #endif /* SV68R3V6 */ |
| #endif /* CK_SCO32V4 */ |
| |
| #ifndef SIGUSR1 /* User-defined signals */ |
| #define SIGUSR1 30 |
| #endif /* SIGUSR1 */ |
| |
| #ifndef SIGUSR2 |
| #define SIGUSR2 31 |
| #endif /* SIGUSR2 */ |
| |
| /* |
| ignorsigs() sets certain signals to SIG_IGN. But when a signal is |
| ignored, it remains ignored across exec(), so we have to restore these |
| signals before exec(), which is the purpose of restorsigs(). |
| */ |
| static VOID |
| ignorsigs() { /* Ignore these signals */ |
| savquit = signal(SIGQUIT,SIG_IGN); /* Ignore Quit signal */ |
| |
| #ifdef SIGDANGER /* Ignore danger signals */ |
| /* |
| This signal is sent when the system is low on swap space. Processes |
| that don't handle it are candidates for termination. If swap space doesn't |
| clear out enough, we still might be terminated via kill() -- nothing we can |
| do about that! Conceivably, this could be improved by installing a real |
| signal handler that warns the user, but that would be pretty complicated, |
| since we are not always in control of the screen -- e.g. during remote-mode |
| file transfer. |
| */ |
| savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */ |
| #endif /* SIGDANGER */ |
| #ifdef SIGPIPE |
| /* |
| This one comes when a TCP/IP connection is broken by the remote. |
| We prefer to catch this situation by examining error codes from write(). |
| */ |
| savpipe = signal(SIGPIPE,SIG_IGN); |
| #endif /* SIGPIPE */ |
| savusr1 = signal(SIGUSR1,SIG_IGN); /* Ignore user-defined signals */ |
| savusr2 = signal(SIGUSR2,SIG_IGN); |
| } |
| |
| VOID |
| restorsigs() { /* Restore these signals */ |
| (VOID) signal(SIGQUIT,savquit); /* (used in ckufio.c) */ |
| #ifdef SIGDANGER |
| (VOID) signal(SIGDANGER,savdanger); |
| #endif /* SIGDANGER */ |
| #ifdef SIGPIPE |
| (VOID) signal(SIGPIPE,savpipe); |
| #endif /* SIGPIPE */ |
| (VOID) signal(SIGUSR1,savusr1); |
| (VOID) signal(SIGUSR2,savusr2); |
| } |
| |
| int |
| sysinit() { |
| int x; |
| char * s; |
| #ifdef CK_UTSNAME |
| struct utsname name; |
| #endif /* CK_UTSNAME */ |
| |
| extern char startupdir[]; |
| /* |
| BEFORE ANYTHING ELSE: Initialize the setuid package. |
| Change to the user's real user and group ID. |
| If this can't be done, don't run at all. |
| */ |
| x = priv_ini(); |
| #ifdef SUIDDEBUG |
| fprintf(stderr,"PRIV_INI=%d\n",x); |
| #endif /* SUIDDEBUG */ |
| if (x) { |
| if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n"); |
| if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n"); |
| if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n"); |
| exit(1); |
| } |
| signal(SIGINT,SIG_IGN); /* Ignore interrupts at first */ |
| signal(SIGFPE,SIG_IGN); /* Ignore floating-point exceptions */ |
| signal(SIGHUP,sighup); /* Catch SIGHUP */ |
| #ifndef NOSIGWINCH |
| #ifdef SIGWINCH |
| signal(SIGWINCH,winchh); /* Catch window-size change */ |
| #endif /* SIGWINCH */ |
| #endif /* NOSIGWINCH */ |
| |
| #ifndef NOJC |
| /* |
| Get the initial job control state. |
| If it is SIG_IGN, that means the shell does not support job control, |
| and so we'd better not suspend ourselves. |
| */ |
| #ifdef SIGTSTP |
| jchdlr = signal(SIGTSTP,SIG_IGN); |
| if (jchdlr == SIG_IGN) { |
| jcshell = 0; |
| debug(F100,"sysinit jchdlr: SIG_IGN","",0); |
| } else if (jchdlr == SIG_DFL) { |
| debug(F100,"sysinit jchdlr: SIG_DFL","",0); |
| jcshell = 1; |
| } else { |
| debug(F100,"sysinit jchdlr: other","",0); |
| jcshell = 3; |
| } |
| (VOID) signal(SIGTSTP,jchdlr); /* Put it back... */ |
| #endif /* SIGTSTP */ |
| #endif /* NOJC */ |
| |
| conbgt(0); /* See if we're in the background */ |
| congm(); /* Get console modes */ |
| |
| (VOID) signal(SIGALRM,SIG_IGN); /* Ignore alarms */ |
| |
| ignorsigs(); /* Ignore some other signals */ |
| |
| #ifdef F_SETFL |
| iniflags = fcntl(0,F_GETFL,0); /* Get stdin flags */ |
| #endif /* F_SETFL */ |
| |
| #ifdef ultrix |
| gtty(0,&vanilla); /* Get sgtty info */ |
| #else |
| #ifdef AUX |
| set42sig(); /* Don't ask! (hakanson@cs.orst.edu) */ |
| #endif /* AUX */ |
| #endif /* ultrix */ |
| /* |
| Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but |
| never closes it. If it is called often enough, we run out of file |
| descriptors and subsequent open()'s of other devices or files can fail. |
| */ |
| s = NULL; |
| #ifndef MINIX |
| if (isatty(0)) /* Name of controlling terminal */ |
| s = ttyname(0); |
| else if (isatty(1)) |
| s = ttyname(1); |
| else if (isatty(2)) |
| s = ttyname(2); |
| debug(F110,"sysinit ttyname(0)",s,0); |
| #endif /* MINIX */ |
| |
| #ifdef BEOS |
| if (!dftty) |
| makestr(&dftty,s); |
| #endif /* BEOS */ |
| |
| if (s) |
| ckstrncpy((char *)cttnam,s,DEVNAMLEN+1); |
| #ifdef SVORPOSIX |
| if (!cttnam[0]) |
| ctermid(cttnam); |
| #endif /* SVORPOSIX */ |
| if (!cttnam[0]) |
| ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1); |
| debug(F110,"sysinit CTTNAM",CTTNAM,0); |
| debug(F110,"sysinit cttnam",cttnam,0); |
| |
| ttgwsiz(); /* Get window (screen) dimensions. */ |
| |
| #ifndef NOSYSCONF |
| #ifdef _SC_OPEN_MAX |
| ckmaxfiles = sysconf(_SC_OPEN_MAX); |
| #endif /* _SC_OPEN_MAX */ |
| #endif /* NOSYSCONF */ |
| |
| #ifdef Plan9 |
| if (!backgrd) { |
| consctlfd = open("/dev/consctl", O_WRONLY); |
| /*noisefd = open("/dev/noise", O_WRONLY)*/ |
| } |
| ckxech = 1; |
| #endif /* Plan9 */ |
| |
| #ifdef CK_UTSNAME |
| if (uname(&name) > -1) { |
| ckstrncpy(unm_mch,name.machine,CK_SYSNMLN); |
| ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN); |
| ckstrncpy(unm_rel,name.release,CK_SYSNMLN); |
| ckstrncpy(unm_ver,name.version,CK_SYSNMLN); |
| #ifdef DEBUG |
| if (deblog) { |
| debug(F110,"sysinit uname machine",unm_mch,0); |
| debug(F110,"sysinit uname sysname",unm_nam,0); |
| debug(F110,"sysinit uname release",unm_rel,0); |
| debug(F110,"sysinit uname version",unm_ver,0); |
| } |
| #endif /* DEBUG */ |
| |
| #ifdef HPUX9PLUS |
| if (name.machine[5] == '8') |
| hpis800 = 1; |
| else |
| hpis800 = 0; |
| debug(F101,"sysinit hpis800","",hpis800); |
| #endif /* HPUX9PLUS */ |
| #ifdef TRU64 |
| getsysinfo(GSI_PLATFORM_NAME, unm_mod, CK_SYSNMLN, 0, 0); |
| debug(F110,"sysinit getsysinfo model",unm_mod,0); |
| #endif /* TRU64 */ |
| #ifdef SOLARIS25 |
| sysinfo(SI_PLATFORM, unm_mod, CK_SYSNMLN); |
| debug(F110,"sysinit sysinfo model",unm_mod,0); |
| #endif /* SOLARIS25 */ |
| } |
| #endif /* CK_UTSNAME */ |
| |
| #ifdef CK_ENVIRONMENT |
| { |
| #ifdef TNCODE |
| extern char tn_env_acct[], tn_env_disp[], tn_env_job[], |
| tn_env_prnt[], tn_env_sys[]; |
| #endif /* TNCODE */ |
| extern char uidbuf[]; |
| extern char * whoami(); |
| char *p; |
| #ifdef CKSENDUID |
| uidbuf[0] = '\0'; |
| #ifdef IKSD |
| if (!inserver) { |
| #endif /* IKSD */ |
| p = getenv("USER"); |
| debug(F110,"sysinit uidbuf from USER",uidbuf,0); |
| if (!p) p = ""; |
| if (!*p) { |
| p = getenv("LOGNAME"); |
| debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0); |
| } |
| if (!p) p = ""; |
| if (!*p) { |
| p = whoami(); |
| debug(F110,"sysinit uidbuf from whoami()",uidbuf,0); |
| } |
| if (!p) p = ""; |
| ckstrncpy(uidbuf, *p ? p : "UNKNOWN", UIDBUFLEN); |
| #ifdef IKSD |
| } |
| #endif /* IKSD */ |
| debug(F110,"sysinit final uidbuf",uidbuf,0); |
| #endif /* CKSENDUID */ |
| |
| #ifdef TNCODE |
| if ((p = getenv("JOB"))) ckstrncpy(tn_env_job,p,63); |
| if ((p = getenv("ACCT"))) ckstrncpy(tn_env_acct,p,63); |
| if ((p = getenv("PRINTER"))) ckstrncpy(tn_env_prnt,p,63); |
| if ((p = getenv("DISPLAY"))) ckstrncpy(tn_env_disp,p,63); |
| #ifdef aegis |
| ckstrncpy(tn_env_sys,"Aegis",64); |
| #else |
| #ifdef Plan9 |
| ckstrncpy(tn_env_sys,"Plan9",64); |
| #else |
| ckstrncpy(tn_env_sys,"UNIX",64); |
| #endif /* Plan9 */ |
| #endif /* aegis */ |
| #endif /* TNCODE */ |
| } |
| #endif /* CK_ENVIRONMENT */ |
| #ifdef CK_SNDLOC |
| { |
| extern char * tn_loc; |
| char *p; |
| if (p = getenv("LOCATION")) |
| if (tn_loc = (char *)malloc((int)strlen(p)+1)) |
| strcpy(tn_loc,p); /* safe */ |
| } |
| #endif /* CK_SNDLOC */ |
| |
| ckstrncpy(startupdir, zgtdir(), CKMAXPATH); |
| startupdir[CKMAXPATH] = '\0'; |
| x = strlen(startupdir); |
| if (x <= 0) { |
| startupdir[0] = '/'; |
| startupdir[1] = '\0'; |
| } else if (startupdir[x-1] != '/') { |
| startupdir[x] = '/'; |
| startupdir[x+1] = '\0'; |
| } |
| debug(F110,"sysinit startupdir",startupdir,0); |
| #ifdef TTLEBUF |
| le_init(); |
| #endif /* TTLEBUF */ |
| #ifdef BSD44ORPOSIX |
| /* This should catch the ncurses platforms */ |
| /* Some platforms don't have putenv(), like NeXTSTEP */ |
| putenv("NCURSES_NO_SETBUF=1"); |
| #endif /* BSD44ORPOSIX */ |
| return(0); |
| } |
| |
| /* S Y S C L E A N U P -- System-dependent program cleanup. */ |
| |
| int |
| syscleanup() { |
| #ifdef F_SETFL |
| if (iniflags > -1) |
| fcntl(0,F_SETFL,iniflags); /* Restore stdin flags */ |
| #endif /* F_SETFL */ |
| #ifdef ultrix |
| stty(0,&vanilla); /* Get sgtty info */ |
| #endif /* ultrix */ |
| #ifdef NETCMD |
| if (ttpid) kill(ttpid,9); |
| #endif /* NETCMD */ |
| return(0); |
| } |
| |
| /* T T O P E N -- Open a tty for exclusive access. */ |
| |
| /* |
| Call with: |
| ttname: character string - device name or network host name. |
| lcl: |
| If called with lcl < 0, sets value of lcl as follows: |
| 0: the terminal named by ttname is the job's controlling terminal. |
| 1: the terminal named by ttname is not the job's controlling terminal. |
| But watch out: if a line is already open, or if requested line can't |
| be opened, then lcl remains (and is returned as) -1. |
| modem: |
| Less than zero: ttname is a network host name. |
| Zero or greater: ttname is a terminal device name. |
| Zero means a local connection (don't use modem signals). |
| Positive means use modem signals. |
| timo: |
| 0 = no timer. |
| nonzero = number of seconds to wait for open() to return before timing out. |
| |
| Returns: |
| 0 on success |
| -5 if device is in use |
| -4 if access to device is denied |
| -3 if access to lock directory denied |
| -2 upon timeout waiting for device to open |
| -1 on other error |
| */ |
| static int ttotmo = 0; /* Timeout flag */ |
| /* Flag kept here to avoid being clobbered by longjmp. */ |
| |
| int |
| ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; { |
| |
| #ifdef BSD44 |
| #define ctermid(x) strcpy(x,"") |
| #else |
| #ifdef SVORPOSIX |
| #ifndef CIE |
| extern char *ctermid(); /* Wish they all had this! */ |
| #else /* CIE Regulus */ |
| #define ctermid(x) strcpy(x,"") |
| #endif /* CIE */ |
| #endif /* SVORPOSIX */ |
| #endif /* BSD44 */ |
| |
| #ifdef ultrix |
| int temp = 0; |
| #endif /* ultrix */ |
| |
| #ifndef OPENFIRST |
| char fullname[DEVNAMLEN+1]; |
| #endif /* OPENFIRST */ |
| |
| char * fnam; /* Full name after expansion */ |
| |
| int y; |
| |
| #ifndef pdp11 |
| #define NAMEFD /* Feature to allow name to be an open file descriptor */ |
| #endif /* pdp11 */ |
| |
| #ifdef NAMEFD |
| char *p; |
| debug(F101,"ttopen telnetfd","",telnetfd); |
| #endif /* NAMEFD */ |
| |
| debug(F110,"ttopen ttname",ttname,0); |
| debug(F110,"ttopen ttnmsv",ttnmsv,0); |
| debug(F101,"ttopen modem","",modem); |
| debug(F101,"ttopen netconn","",netconn); |
| debug(F101,"ttopen ttyfd","",ttyfd); |
| debug(F101,"ttopen *lcl","",*lcl); |
| debug(F101,"ttopen ttmdm","",ttmdm); |
| debug(F101,"ttopen ttnet","",ttnet); |
| |
| ttpmsk = 0xff; |
| lockpid[0] = '\0'; |
| |
| if (ttyfd > -1) { /* If device already opened */ |
| if (!strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */ |
| return(0); /* Yes, nothing to do - just return */ |
| ttnmsv[0] = '\0'; /* No, clear out old name */ |
| ttclos(ttyfd); /* close old connection. */ |
| } |
| wasclosed = 0; /* New connection, not closed yet. */ |
| ttpipe = 0; /* Assume it's not a pipe */ |
| ttpty = 0; /* or a pty... */ |
| |
| #ifdef NETCONN |
| /* |
| This is a bit tricky... Suppose that previously Kermit had dialed a telnet |
| modem server ("set host xxx:2001, set modem type usr, dial ..."). Then the |
| connection was closed (ttyfd = -1), and then a REDIAL command was given. At |
| this point we've obliterated the negative modem type hack, and so would |
| treat the IP hostname as a device name, and would then fail because of "No |
| such device or directory". But the previous connection has left behind some |
| clues, so let's use them... |
| */ |
| if (ttyfd < 0) { /* Connection is not open */ |
| if (!strcmp(ttname,ttnmsv)) { /* Old and new names the same? */ |
| if (((netconn > 0) && (ttmdm < 0)) || |
| ((ttnet > 0) && |
| (!ckstrchr(ttname,'/')) && (ckstrchr(ttname,':'))) |
| ) { |
| int x, rc; |
| x = (ttmdm < 0) ? -ttmdm : ttnet; |
| rc = netopen(ttname, lcl, x); |
| debug(F111,"ttopen REOPEN netopen",ttname,rc); |
| if (rc > -1) { |
| netconn = 1; |
| xlocal = *lcl = 1; |
| } else { |
| netconn = 0; |
| } |
| gotsigs = 0; |
| return(rc); |
| } |
| } |
| } |
| #endif /* NETCONN */ |
| |
| #ifdef MAXNAMLEN |
| debug(F100,"ttopen MAXNAMLEN defined","",0); |
| #else |
| debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0); |
| #endif |
| |
| #ifdef BSD4 |
| debug(F100,"ttopen BSD4 defined","",0); |
| #else |
| debug(F100,"ttopen BSD4 *NOT* defined","",0); |
| #endif /* BSD4 */ |
| |
| #ifdef BSD42 |
| debug(F100,"ttopen BSD42 defined","",0); |
| #else |
| debug(F100,"ttopen BSD42 *NOT* defined","",0); |
| #endif /* BSD42 */ |
| |
| #ifdef MYREAD |
| debug(F100,"ttopen MYREAD defined","",0); |
| #else |
| debug(F100,"ttopen MYREAD *NOT* defined","",0); |
| #endif /* MYREAD */ |
| |
| #ifdef NETCONN |
| if (modem < 0) { /* modem < 0 = code for network */ |
| int x; |
| ttmdm = modem; |
| modem = -modem; /* Positive network type number */ |
| fdflag = 0; /* Stdio not redirected. */ |
| netconn = 1; /* And it's a network connection */ |
| debug(F111,"ttopen net",ttname,modem); |
| #ifdef NAMEFD |
| for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */ |
| if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */ |
| ttyfd = atoi(ttname); /* Is there a way to test it's open? */ |
| ttfdflg = 1; /* We got an open file descriptor */ |
| debug(F111,"ttopen net ttfdflg",ttname,ttfdflg); |
| debug(F101,"ttopen net ttyfd","",ttyfd); |
| ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */ |
| x = 1; /* Return code is "good". */ |
| if (telnetfd) { |
| ttnet = NET_TCPB; |
| if (ttnproto != NP_TCPRAW) |
| ttnproto = NP_TELNET; |
| #ifdef SUNX25 |
| } else if (x25fd) { |
| ttnet = NET_SX25; |
| ttnproto = NP_NONE; |
| #endif /* SUNX25 */ |
| } |
| } else { /* Host name or address given */ |
| #ifdef NETPTY |
| if (modem == NET_PTY) { |
| int x; |
| if (nopush) { |
| debug(F100,"ttopen PTY: nopush","",0); |
| return(-1); |
| } |
| ttnet = NET_PTY; |
| ttnproto = NP_NONE; |
| netconn = 1; /* but we don't use network i/o */ |
| ttpty = 1; |
| debug(F110,"ttopen PTY",ttname,0); |
| x = do_pty(ttname); |
| if (x > -1) { |
| ckstrncpy(ttnmsv,ttname,DEVNAMLEN); |
| xlocal = *lcl = 1; /* It's local */ |
| } else { |
| ttpty = 0; |
| netconn = 0; |
| } |
| gotsigs = 0; |
| return(x); |
| } |
| #endif /* NETPTY */ |
| #ifdef NETCMD |
| /* |
| dup2() is not available on older System V platforms like AT&T 3Bx. For |
| those systems we punt by not defining NETCMD, but we might be able to do |
| better -- see workarounds for this problem in ckufio.c (search for dup2). |
| */ |
| if (modem == NET_CMD) { |
| if (nopush) { |
| debug(F100,"ttopen pipe: nopush","",0); |
| return(-1); |
| } |
| if (pipe(pipe0) || pipe(pipe1)) { |
| perror("Pipe error"); |
| return(-1); |
| } |
| ttpid = fork(); /* Make a fork */ |
| |
| switch (ttpid) { |
| case -1: /* Error making fork */ |
| close(pipe0[0]); |
| close(pipe0[1]); |
| close(pipe1[0]); |
| close(pipe1[1]); |
| perror("Fork error"); |
| return(-1); |
| case 0: /* Child. */ |
| close(pipe0[0]); |
| close(pipe1[1]); |
| dup2(pipe0[1], 1); |
| close(pipe0[1]); |
| dup2(pipe1[0], 0); |
| close(pipe1[0]); |
| system(ttname); |
| _exit(0); |
| default: /* Parent */ |
| close(pipe0[1]); |
| close(pipe1[0]); |
| fdin = pipe0[0]; /* Read from pipe */ |
| fdout = pipe1[1]; /* Write to pipe */ |
| ttout = fdopen(fdout,"w"); /* Get stream so we can */ |
| if (!ttout) { /* make it unbuffered. */ |
| perror("fdopen failure"); |
| return(-1); |
| } |
| setbuf(ttout,NULL); |
| ckstrncpy(ttnmsv,ttname,DEVNAMLEN); |
| xlocal = *lcl = 1; /* It's local */ |
| netconn = 1; /* Call it a network connection */ |
| ttmdm = modem; /* Remember network type */ |
| ttyfd = fdin; |
| ttpipe = 1; |
| gotsigs = 0; |
| return(0); |
| } |
| } |
| #endif /* NETCMD */ |
| #endif /* NAMEFD */ |
| x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */ |
| if (x > -1) { |
| ckstrncpy(ttnmsv,ttname,DEVNAMLEN); |
| } else netconn = 0; |
| #ifdef NAMEFD |
| } |
| #endif /* NAMEFD */ |
| |
| #ifdef sony_news /* Sony NEWS */ |
| if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */ |
| perror("ttopen error getting Kanji mode (network)"); |
| debug(F111,"ttopen error getting Kanji mode","network",0); |
| km_ext = -1; /* Make sure this stays undefined. */ |
| } |
| #endif /* sony_news */ |
| |
| xlocal = *lcl = 1; /* Network connections are local. */ |
| debug(F101,"ttopen net x","",x); |
| #ifdef COMMENT |
| /* Let netopen() do this */ |
| if (x > -1 && !x25fd) |
| x = tn_ini(); /* Initialize TELNET protocol */ |
| #endif /* COMMENT */ |
| gotsigs = 0; |
| return(x); |
| } else { /* Terminal device */ |
| #endif /* NETCONN */ |
| |
| #ifdef NAMEFD |
| /* |
| This code lets you give Kermit an open file descriptor for a serial |
| communication device, rather than a device name. Kermit assumes that the |
| line is already open, locked, conditioned with the right parameters, etc. |
| */ |
| for (p = ttname; isdigit(*p); p++) ; /* Check for all-digits */ |
| if (*p == '\0') { |
| ttyfd = atoi(ttname); /* Is there a way to test it's open? */ |
| debug(F111,"ttopen got open fd",ttname,ttyfd); |
| ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */ |
| if (ttyfd >= 0 && ttyfd < 3) /* If it's stdio... */ |
| xlocal = *lcl = 0; /* we're in remote mode */ |
| else /* otherwise */ |
| xlocal = *lcl = 1; /* local mode. */ |
| netconn = 0; /* Assume it's not a network. */ |
| tvtflg = 0; /* Might need to initialize modes. */ |
| ttmdm = modem; /* Remember modem type. */ |
| fdflag = 0; /* Stdio not redirected. */ |
| ttfdflg = 1; /* Flag we were opened this way. */ |
| debug(F111,"ttopen non-net ttfdflg",ttname,ttfdflg); |
| debug(F101,"ttopen non-net ttyfd","",ttyfd); |
| |
| #ifdef sony_news /* Sony NEWS */ |
| /* Get device Kanji mode */ |
| if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { |
| perror("ttopen error getting Kanji mode"); |
| debug(F101,"ttopen error getting Kanji mode","",0); |
| km_ext = -1; /* Make sure this stays undefined. */ |
| } |
| #endif /* sony_news */ |
| gotsigs = 0; |
| return(0); /* Return success */ |
| } |
| #endif /* NAMEFD */ |
| #ifdef NETCONN |
| } |
| #endif /* NETCONN */ |
| |
| /* Here we have to open a serial device of the given name. */ |
| |
| netconn = 0; /* So it's not a network connection */ |
| occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */ |
| sigint_ign = 0; |
| |
| tvtflg = 0; /* Flag for use by ttvt(). */ |
| /* 0 = ttvt not called yet for this device */ |
| |
| fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */ |
| debug(F101,"ttopen fdflag","",fdflag); |
| |
| ttmdm = modem; /* Make this available to other fns */ |
| xlocal = *lcl; /* Make this available to other fns */ |
| |
| /* Code for handling bidirectional tty lines goes here. */ |
| /* Use specified method for turning off logins and suppressing getty. */ |
| |
| #ifdef ACUCNTRL |
| /* Should put call to priv_on() here, but that would be very risky! */ |
| acucntrl("disable",ttname); /* acucntrl() program. */ |
| /* and priv_off() here... */ |
| #else |
| #ifdef ATT7300 |
| if ((attmodem & DOGETY) == 0) /* offgetty() program. */ |
| attmodem |= offgetty(ttname); /* Remember response. */ |
| #endif /* ATT7300 */ |
| #endif /* ACUCNTRL */ |
| |
| #ifdef OPENFIRST |
| /* |
| 1985-2001: opens device first then gets lock; reason: |
| Kermit usually has to run setuid or setgid in order to create a lockfile. |
| If you give a SET LINE command for a device that happens to be your job's |
| controlling terminal, Kermit doesn't have to create a lockfile, and in fact |
| should not create one, and would fail if it tried to if it did not have the |
| required privileges. But you can't find out if two tty device names are |
| equivalent until you have a file descriptor that you can give to ttyname(). |
| But this can cause a race condition between Kermit and [m]getty. So see |
| the [#]else part... |
| */ |
| |
| /* |
| In the following section, we open the tty device for read/write. |
| If a modem has been specified via "set modem" prior to "set line" |
| then the O_NDELAY parameter is used in the open, provided this symbol |
| is defined (e.g. in fcntl.h), so that the program does not hang waiting |
| for carrier (which in most cases won't be present because a connection |
| has not been dialed yet). O_NDELAY is removed later on in ttopen(). It |
| would make more sense to first determine if the line is local before |
| doing this, but because ttyname() requires a file descriptor, we have |
| to open it first. See do_open(). |
| |
| Now open the device using the desired treatment of carrier. |
| If carrier is REQUIRED, then open could hang forever, so an optional |
| timer is provided. If carrier is not required, the timer should never |
| go off, and should do no harm... |
| */ |
| ttotmo = 0; /* Flag no timeout */ |
| debug(F101,"ttopen timo","",timo); |
| debug(F101,"ttopen xlocal","",xlocal); |
| if (timo > 0) { |
| int xx; |
| saval = signal(SIGALRM,timerh); /* Timed, set up timer. */ |
| xx = alarm(timo); /* Timed open() */ |
| debug(F101,"ttopen alarm","",xx); |
| if ( |
| #ifdef CK_POSIX_SIG |
| sigsetjmp(sjbuf,1) |
| #else |
| setjmp(sjbuf) |
| #endif /* CK_POSIX_SIG */ |
| ) { |
| ttotmo = 1; /* Flag timeout. */ |
| } else ttyfd = do_open(ttname); |
| ttimoff(); |
| debug(F111,"ttopen","modem",modem); |
| debug(F101,"ttopen ttyfd","",ttyfd); |
| debug(F101,"ttopen alarm return","",ttotmo); |
| } else { |
| errno = 0; |
| ttyfd = do_open(ttname); |
| } |
| debug(F111,"ttopen ttyfd",ttname,ttyfd); |
| if (ttyfd < 0) { /* If couldn't open, fail. */ |
| debug(F101,"ttopen errno","",errno); |
| if (errno > 0 && !quiet) |
| perror(ttname); /* Print message */ |
| |
| #ifdef ATT7300 |
| if (attmodem & DOGETY) /* was getty(1m) running before us? */ |
| ongetty(ttnmsv); /* yes, restart on tty line */ |
| attmodem &= ~DOGETY; /* no phone in use, getty restored */ |
| #else |
| #ifdef ACUCNTRL |
| /* Should put call to priv_on() here, but that would be risky! */ |
| acucntrl("enable",ttname); /* acucntrl() program. */ |
| /* and priv_off() here... */ |
| #endif /* ACUNTRL */ |
| #endif /* ATT7300 */ |
| |
| signal(SIGINT,occt); /* Put old Ctrl-C trap back. */ |
| if (errno == EACCES) { /* Device is protected against user */ |
| debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */ |
| return(-4); |
| } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */ |
| } |
| |
| #ifdef QNX |
| { |
| extern int qnxportlock; |
| x = qnxopencount(); |
| debug(F101,"ttopen qnxopencount","",x); |
| debug(F101,"ttopen qnxportlock","",qnxportlock); |
| if (x < 0 && qnxportlock) { |
| ttclos(0); |
| printf("?Can't get port open count\n"); |
| printf("(Try again with SET QNX-PORT-LOCK OFF)\n"); |
| return(-1); /* Indicate device is in use */ |
| } |
| if (x > 1) { /* 1 == me */ |
| if (qnxportlock) |
| ttclos(0); |
| return(-2); /* Indicate device is in use */ |
| else if (!quiet) |
| printf("WARNING: \"%s\" looks busy...\n",ttdev); |
| } |
| } |
| #endif /* QNX */ |
| |
| #ifdef Plan9 |
| /* take this opportunity to open the control channel */ |
| if (p9openttyctl(ttname) < 0) |
| #else |
| /* Make sure it's a real tty. */ |
| if (!ttfdflg && !isatty(ttyfd) && strcmp(ttname,"/dev/null")) |
| #endif /* Plan9 */ |
| { |
| fprintf(stderr,"%s is not a terminal device\n",ttname); |
| debug(F111,"ttopen not a tty",ttname,errno); |
| close(ttyfd); |
| ttyfd = -1; |
| wasclosed = 1; |
| signal(SIGINT,occt); |
| return(-1); |
| } |
| |
| #ifdef aegis |
| /* Apollo C runtime claims that console pads are tty devices, which |
| * is reasonable, but they aren't any good for packet transfer. */ |
| ios_$inq_type_uid((short)ttyfd, ttyuid, st); |
| if (st.all != status_$ok) { |
| fprintf(stderr, "problem getting tty object type: "); |
| error_$print(st); |
| } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */ |
| close(ttyfd); ttyfd = -1; |
| wasclosed = 1; |
| errno = ENOTTY; perror(ttname); |
| signal(SIGINT,occt); |
| return(-1); |
| } |
| #endif /* aegis */ |
| |
| sigint_ign = (occt == SIG_IGN) ? 1 : 0; |
| |
| ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */ |
| |
| /* Caller wants us to figure out if line is controlling tty */ |
| |
| if (*lcl < 0) { |
| if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */ |
| xlocal = 0; |
| debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal); |
| } else if (strcmp(ttname,cttnam) == 0) { |
| xlocal = 0; |
| debug(F111,"ttopen ttname=cttnam",ttname,xlocal); |
| } else if (cttnam[0]) { |
| #ifdef BEBOX_DR7 |
| x = ttnmsv; /* ttyname() is broken */ |
| #else |
| x = ttyname(ttyfd); /* Get real name of ttname. */ |
| #endif /* BEBOX_DR7 */ |
| if (!x) x = ""; |
| if (*x) |
| xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1); |
| else |
| xlocal = 1; |
| debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal); |
| } |
| } |
| |
| #ifndef NOFDZERO |
| /* Note, the following code was added so that Unix "idle-line" snoopers */ |
| /* would not think Kermit was idle when it was transferring files, and */ |
| /* maybe log people out. */ |
| if (xlocal == 0) { /* Remote mode */ |
| if (fdflag == 0) { /* Standard i/o is not redirected */ |
| debug(F100,"ttopen setting ttyfd = 0","",0); |
| #ifdef LYNXOS |
| /* On Lynx OS, fd 0 is open for read only. */ |
| dup2(ttyfd,0); |
| #endif /* LYNXOS */ |
| close(ttyfd); /* Use file descriptor 0 */ |
| ttyfd = 0; |
| } else { /* Standard i/o is redirected */ |
| debug(F101,"ttopen stdio redirected","",ttyfd); |
| } |
| } |
| #endif /* NOFDZERO */ |
| |
| /* Now check if line is locked -- if so fail, else lock for ourselves */ |
| /* Note: After having done this, don't forget to delete the lock if you */ |
| /* leave ttopen() with an error condition. */ |
| |
| lkf = 0; /* Check lock */ |
| if (xlocal > 0) { |
| int xx; int xpid; |
| if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */ |
| debug(F111,"ttopen ttlock fails",ttname,xx); |
| /* WARNING - This close() can hang if tty is an empty socket... */ |
| close(ttyfd); /* Close the device. */ |
| ttyfd = -1; /* Erase its file descriptor. */ |
| wasclosed = 1; |
| signal(SIGINT,occt); /* Put old SIGINT back. */ |
| sigint_ign = (occt == SIG_IGN) ? 1 : 0; |
| if (xx == -2) { /* If lockfile says device in use, */ |
| #ifndef NOUUCP |
| debug(F111,"ttopen reading lockfile pid",flfnam,xx); |
| xpid = ttrpid(flfnam); /* Try to read pid from lockfile */ |
| if (xpid > -1) { /* If we got a pid */ |
| if (!quiet) |
| printf("Locked by process %d\n",xpid); /* tell them. */ |
| sprintf(lockpid,"%d",xpid); /* Record it too */ |
| debug(F110,"ttopen lockpid",lockpid,0); |
| } else if (*flfnam) { |
| extern char *DIRCMD; |
| char *p = NULL; |
| int x; |
| x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2; |
| p = malloc(x); /* Print a directory listing. */ |
| /* |
| Note: priv_on() won't help here, because we do not pass privs along to |
| to inferior processes, in this case ls. So if the real user does not have |
| directory-listing access to the lockfile directory, this will result in |
| something like "not found". That's why we try this only as a last resort. |
| */ |
| if (p) { /* If we got the space... */ |
| ckmakmsg(p,x,DIRCMD," ",flfnam,NULL); |
| zsyscmd(p); /* Get listing. */ |
| if (p) { /* free the space */ |
| free(p); |
| p = NULL; |
| } |
| } |
| } |
| #endif /* NOUUCP */ |
| return(-5); /* Code for device in use */ |
| } else return(-3); /* Access denied */ |
| } else lkf = 1; |
| } |
| #else /* OPENFIRST */ |
| |
| /* |
| 27 Oct 2001: New simpler code that gets the lock first and then opens the |
| device, which eliminates the race condition. The downside is you can no |
| longer say "set line /dev/ttyp0" or whatever, where /dev/ttyp0 is your login |
| terminal, without trying to create a lockfile, which fails if C-Kermit lacks |
| privs, and if it succeeds, it has created a lockfile where it didn't create |
| one before. |
| */ |
| xlocal = *lcl; /* Is the device my login terminal? */ |
| debug(F111,"ttopen xlocal","A",xlocal); |
| fnam = ttname; |
| if (strcmp(ttname,CTTNAM) && netconn == 0) { |
| if (zfnqfp(ttname,DEVNAMLEN+1,fullname)) { |
| if ((int)strlen(fullname) > 0) |
| fnam = fullname; |
| } |
| } |
| debug(F110,"ttopen fnam",fnam,0); |
| if (xlocal < 0) { |
| xlocal = (strcmp(fnam,CTTNAM) != 0); |
| } |
| debug(F111,"ttopen xlocal","B",xlocal); |
| |
| lkf = 0; /* No lock yet */ |
| if (xlocal > 0) { /* If not... */ |
| int xx; int xpid; |
| xx = ttlock(fnam); /* Try to lock it. */ |
| debug(F101,"ttopen ttlock","",xx); |
| if (xx < 0) { /* Can't lock it. */ |
| debug(F111,"ttopen ttlock fails",fnam,xx); |
| if (xx == -2) { /* If lockfile says device in use, */ |
| #ifndef NOUUCP |
| debug(F111,"ttopen reading lockfile pid",flfnam,xx); |
| xpid = ttrpid(flfnam); /* Try to read pid from lockfile */ |
| if (xpid > -1) { /* If we got a pid */ |
| if (!quiet) |
| printf("Locked by process %d\n",xpid); /* tell them. */ |
| ckstrncpy(lockpid,ckitoa(xpid),16); |
| debug(F110,"ttopen lockpid",lockpid,0); |
| #ifndef NOPUSH |
| } else if (flfnam[0] && !nopush) { |
| extern char *DIRCMD; |
| char *p = NULL; |
| int x; |
| x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2; |
| p = malloc(x); /* Print a directory listing. */ |
| /* |
| Note: priv_on() won't help here, because we do not pass privs along to |
| to inferior processes, in this case ls. So if the real user does not have |
| directory-listing access to the lockfile directory, this will result in |
| something like "not found". That's why we try this only as a last resort. |
| */ |
| if (p) { /* If we got the space... */ |
| ckmakmsg(p,x,DIRCMD," ",flfnam,NULL); |
| zsyscmd(p); /* Get listing. */ |
| if (p) { /* free the space */ |
| free(p); |
| p = NULL; |
| } |
| } |
| #endif /* NOPUSH */ |
| } |
| #endif /* NOUUCP */ |
| return(-5); /* Code for device in use */ |
| } else return(-3); /* Access denied */ |
| } else lkf = 1; |
| } |
| /* Have lock -- now it's safe to open the device */ |
| |
| debug(F101,"ttopen lkf","",lkf); |
| debug(F101,"ttopen timo","",timo); |
| |
| ttotmo = 0; /* Flag no timeout */ |
| if (timo > 0) { |
| int xx; |
| saval = signal(SIGALRM,timerh); /* Timed, set up timer. */ |
| xx = alarm(timo); /* Timed open() */ |
| debug(F101,"ttopen alarm","",xx); |
| if ( |
| #ifdef CK_POSIX_SIG |
| sigsetjmp(sjbuf,1) |
| #else |
| setjmp(sjbuf) |
| #endif /* CK_POSIX_SIG */ |
| ) { |
| ttotmo = 1; /* Flag timeout. */ |
| } else { |
| ttyfd = do_open(fnam); |
| } |
| ttimoff(); |
| debug(F111,"ttopen timed ttyfd",fnam,ttyfd); |
| } else { |
| errno = 0; |
| ttyfd = do_open(fnam); |
| debug(F111,"ttopen untimed ttyfd",fnam,ttyfd); |
| } |
| if (ttyfd < 0) { /* If couldn't open, fail. */ |
| debug(F111,"ttopen errno",fnam,errno); |
| debug(F111,"ttopen xlocal","C",xlocal); |
| if (xlocal == 0) { |
| debug(F100,"ttopen substituting 0","",0); |
| ttyfd = 0; |
| } else { |
| if (errno > 0 && !quiet) { |
| debug(F111,"ttopen perror",fnam,errno); |
| perror(fnam); /* Print message */ |
| } |
| if (ttunlck()) /* Release the lock file */ |
| fprintf(stderr,"Warning, problem releasing lock\r\n"); |
| } |
| } |
| |
| if (ttyfd < 0) { /* ttyfd is still < 0? */ |
| #ifdef ATT7300 |
| if (attmodem & DOGETY) /* was getty(1m) running before us? */ |
| ongetty(ttnmsv); /* yes, restart on tty line */ |
| attmodem &= ~DOGETY; /* no phone in use, getty restored */ |
| #else |
| #ifdef ACUCNTRL |
| /* Should put call to priv_on() here, but that would be risky! */ |
| acucntrl("enable",fnam); /* acucntrl() program. */ |
| /* and priv_off() here... */ |
| #endif /* ACUNTRL */ |
| #endif /* ATT7300 */ |
| |
| signal(SIGINT,occt); /* Put old Ctrl-C trap back. */ |
| if (errno == EACCES) { /* Device is protected against user */ |
| debug(F110,"ttopen EACCESS",fnam,0); /* Return -4 */ |
| return(-4); |
| } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */ |
| } |
| |
| /* Make sure it's a real tty. */ |
| |
| #ifdef Plan9 |
| /* take this opportunity to open the control channel */ |
| if (p9openttyctl(fnam) < 0) |
| #else |
| if (!ttfdflg && !isatty(ttyfd) && strcmp(fnam,"/dev/null")) |
| #endif /* Plan9 */ |
| { |
| fprintf(stderr,"%s is not a terminal device\n",fnam); |
| debug(F111,"ttopen not a tty",fnam,errno); |
| if (ttunlck()) /* Release the lock file */ |
| fprintf(stderr,"Warning, problem releasing lock\r\n"); |
| close(ttyfd); |
| ttyfd = -1; |
| wasclosed = 1; |
| signal(SIGINT,occt); |
| return(-1); |
| } |
| |
| #ifdef aegis |
| /* |
| Apollo C runtime claims that console pads are tty devices, which |
| is reasonable, but they aren't any good for packet transfer. |
| */ |
| ios_$inq_type_uid((short)ttyfd, ttyuid, st); |
| if (st.all != status_$ok) { |
| fprintf(stderr, "problem getting tty object type: "); |
| error_$print(st); |
| } else if (ttyuid != sio_$uid) { /* Reject non-SIO lines */ |
| close(ttyfd); ttyfd = -1; |
| wasclosed = 1; |
| errno = ENOTTY; perror(fnam); |
| signal(SIGINT,occt); |
| return(-1); |
| } |
| #endif /* aegis */ |
| |
| sigint_ign = (occt == SIG_IGN) ? 1 : 0; |
| |
| ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */ |
| |
| /* Caller wants us to figure out if line is controlling tty */ |
| |
| if (*lcl < 0) { |
| char * s; |
| if (strcmp(fnam,CTTNAM) == 0) { /* "/dev/tty" always remote */ |
| xlocal = 0; |
| debug(F111,"ttopen fnam=CTTNAM",fnam,xlocal); |
| } else if (strcmp(fnam,cttnam) == 0) { |
| xlocal = 0; |
| debug(F111,"ttopen fnam=cttnam",fnam,xlocal); |
| } else if (cttnam[0]) { |
| #ifdef BEBOX_DR7 |
| s = ttnmsv; /* ttyname() is broken */ |
| #else |
| s = ttyname(ttyfd); /* Get real name of ttname. */ |
| #endif /* BEBOX_DR7 */ |
| if (!s) s = ""; |
| if (*s) |
| xlocal = ((strncmp(s,cttnam,DEVNAMLEN) == 0) ? 0 : 1); |
| else |
| xlocal = 1; |
| debug(F111,"ttopen ttyname(ttyfd) xlocal",s,xlocal); |
| } |
| } |
| |
| #ifndef NOFDZERO |
| /* Note, the following code was added so that Unix "idle-line" snoopers */ |
| /* would not think Kermit was idle when it was transferring files, and */ |
| /* maybe log people out. */ |
| if (xlocal == 0) { /* Remote mode */ |
| if (fdflag == 0) { /* Standard i/o is not redirected */ |
| debug(F100,"ttopen setting ttyfd = 0","",0); |
| #ifdef LYNXOS |
| /* On Lynx OS, fd 0 is open for read only. */ |
| dup2(ttyfd,0); |
| #endif /* LYNXOS */ |
| close(ttyfd); /* Use file descriptor 0 */ |
| ttyfd = 0; |
| } else { /* Standard i/o is redirected */ |
| debug(F101,"ttopen stdio redirected","",ttyfd); |
| } |
| } |
| #endif /* NOFDZERO */ |
| #endif /* OPENFIRST */ |
| |
| /* Got the line, now set the desired value for local. */ |
| |
| if (*lcl != 0) *lcl = xlocal; |
| |
| /* Some special stuff for v7... */ |
| |
| #ifdef V7 |
| #ifndef MINIX |
| if (kmem[TTY] < 0) { /* If open, then skip this. */ |
| qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */ |
| if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) { |
| fprintf(stderr, "Can't read /dev/kmem in ttopen.\n"); |
| perror("/dev/kmem"); |
| exit(1); |
| } |
| } |
| #endif /* !MINIX */ |
| #endif /* V7 */ |
| |
| /* No failure returns after this point */ |
| |
| #ifdef ultrix |
| ioctl(ttyfd, TIOCMODEM, &temp); |
| #ifdef TIOCSINUSE |
| if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) { |
| if (!quiet) |
| perror(fnam); |
| } |
| #endif /* TIOCSINUSE */ |
| #endif /* ultrix */ |
| |
| /* Get tty device settings */ |
| |
| #ifdef BSD44ORPOSIX /* POSIX */ |
| tcgetattr(ttyfd,&ttold); |
| debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag); |
| tcgetattr(ttyfd,&ttraw); |
| debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag); |
| tcgetattr(ttyfd,&tttvt); |
| debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag); |
| #else /* BSD, V7, and all others */ |
| #ifdef ATTSV /* AT&T UNIX */ |
| ioctl(ttyfd,TCGETA,&ttold); |
| debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag); |
| ioctl(ttyfd,TCGETA,&ttraw); |
| ioctl(ttyfd,TCGETA,&tttvt); |
| #else |
| #ifdef BELLV10 |
| ioctl(ttyfd,TIOCGETP,&ttold); |
| debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags); |
| ioctl(ttyfd,TIOCGDEV,&tdold); |
| debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags); |
| #else |
| gtty(ttyfd,&ttold); |
| debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags); |
| #endif /* BELLV10 */ |
| |
| #ifdef sony_news /* Sony NEWS */ |
| if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */ |
| perror("ttopen error getting Kanji mode"); |
| debug(F101,"ttopen error getting Kanji mode","",0); |
| km_ext = -1; /* Make sure this stays undefined. */ |
| } |
| #endif /* sony_news */ |
| |
| #ifdef TIOCGETC |
| debug(F100,"ttopen TIOCGETC","",0); |
| tcharf = 0; /* In remote mode, also get */ |
| if (xlocal == 0) { /* special characters */ |
| if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) { |
| debug(F100,"ttopen TIOCGETC failed","",0); |
| } else { |
| tcharf = 1; /* It worked. */ |
| ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */ |
| debug(F100,"ttopen TIOCGETC ok","",0); |
| } |
| } |
| #else |
| debug(F100,"ttopen TIOCGETC not defined","",0); |
| #endif /* TIOCGETC */ |
| |
| #ifdef TIOCGLTC |
| debug(F100,"ttopen TIOCGLTC","",0); |
| ltcharf = 0; /* In remote mode, also get */ |
| if (xlocal == 0) { /* local special characters */ |
| if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) { |
| debug(F100,"ttopen TIOCGLTC failed","",0); |
| } else { |
| ltcharf = 1; /* It worked. */ |
| ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */ |
| debug(F100,"ttopen TIOCGLTC ok","",0); |
| } |
| } |
| #else |
| debug(F100,"ttopen TIOCGLTC not defined","",0); |
| #endif /* TIOCGLTC */ |
| |
| #ifdef TIOCLGET |
| debug(F100,"ttopen TIOCLGET","",0); |
| lmodef = 0; |
| if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) { |
| debug(F100,"ttopen TIOCLGET failed","",0); |
| } else { |
| lmodef = 1; |
| debug(F100,"ttopen TIOCLGET ok","",0); |
| } |
| #endif /* TIOCLGET */ |
| |
| #ifdef BELLV10 |
| ioctl(ttyfd,TIOCGETP,&ttraw); |
| ioctl(ttyfd,TIOCGETP,&tttvt); |
| #else |
| gtty(ttyfd,&ttraw); /* And a copy of it for packets*/ |
| gtty(ttyfd,&tttvt); /* And one for virtual tty service */ |
| #endif /* BELLV10 */ |
| |
| #endif /* ATTSV */ |
| #endif /* BSD44ORPOSIX */ |
| |
| /* Section for changing line discipline. It's restored in ttres(). */ |
| |
| #ifdef AIXRS |
| #ifndef AIX41 |
| { union txname ld_name; int ld_idx = 0; |
| ttld = 0; |
| do { |
| ld_name.tx_which = ld_idx++; |
| ioctl(ttyfd, TXGETCD, &ld_name); |
| if (!strncmp(ld_name.tx_name, "rts", 3)) |
| ttld |= 1; |
| } while (*ld_name.tx_name); |
| debug(F101,"AIX line discipline","",ttld); |
| } |
| #endif /* AIX41 */ |
| #endif /* AIXRS */ |
| |
| #ifdef BSD41 |
| /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */ |
| { int k; |
| ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */ |
| debug(F101,"4.1bsd line discipline","",ttld); |
| k = OTTYDISC; /* Switch to "old" discipline */ |
| k = ioctl(ttyfd, TIOCSETD, &k); |
| debug(F101,"4.1bsd tiocsetd","",k); |
| } |
| #endif /* BSD41 */ |
| |
| #ifdef aegis |
| /* This was previously done before the last two TCGETA or gtty above, |
| * in both the ATTSV and not-ATTSV case. If it is not okay to have only |
| * one copy if it here instead, give us a shout! |
| */ |
| sio_$control((short)ttyfd, sio_$raw_nl, false, st); |
| if (xlocal) { /* ignore breaks from local line */ |
| sio_$control((short)ttyfd, sio_$int_enable, false, st); |
| sio_$control((short)ttyfd, sio_$quit_enable, false, st); |
| } |
| #endif /* aegis */ |
| |
| #ifdef VXVE |
| ttraw.c_line = 0; /* STTY line 0 for VX/VE */ |
| tttvt.c_line = 0; /* STTY line 0 for VX/VE */ |
| ioctl(ttyfd,TCSETA,&ttraw); |
| #endif /* vxve */ |
| |
| /* If O_NDELAY was used during open(), then remove it now. */ |
| |
| #ifdef O_NDELAY |
| debug(F100,"ttopen O_NDELAY","",0); |
| if (xlocal > 0) { |
| if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) { |
| debug(F100,"ttopen fcntl O_NDELAY","",0); |
| #ifndef aegis |
| if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) { |
| debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0); |
| perror("Can't unset O_NDELAY"); |
| } |
| #endif /* aegis */ |
| /* Some systems, notably Xenix (don't know how common this is in |
| * other systems), need special treatment to get rid of the O_NDELAY |
| * behaviour on read() with respect to carrier presence (i.e. read() |
| * returning 0 when carrier absent), even though the above fcntl() |
| * is enough to make read() wait for input when carrier is present. |
| * This magic, in turn, requires CLOCAL for working when the carrier |
| * is absent. But if xlocal == 0, presumably you already have CLOCAL |
| * or you have a carrier, otherwise you wouldn't be running this. |
| */ |
| debug(F101,"ttopen xlocal","",xlocal); |
| #ifdef ATTSV |
| #ifdef BSD44ORPOSIX |
| #ifdef COMMENT /* 12 Aug 1997 */ |
| #ifdef __bsdi__ |
| if (xlocal) |
| ttraw.c_cflag |= CLOCAL; |
| #else |
| #ifdef __FreeBSD__ |
| if (xlocal) |
| ttraw.c_cflag |= CLOCAL; |
| #endif /* __FreeBSD__ */ |
| #endif /* __bsdi__ */ |
| #else /* Not COMMENT */ |
| #ifdef CLOCAL |
| if (xlocal) |