4 char *ckxv = "Aegis Communications support, 9.0.326, 20 August 2011";
7 char *ckxv = "Plan 9 Communications support, 9.0.326, 20 August 2011";
9 char *ckxv = "UNIX Communications support, 9.0.326, 20 August 2011";
15 /* C-Kermit interrupt, communications control and I/O functions for UNIX */
18 Author: Frank da Cruz (fdc@columbia.edu),
19 Columbia University Academic Information Systems, New York City.
21 Copyright (C) 1985, 2011,
22 Trustees of Columbia University in the City of New York.
23 All rights reserved. See the C-Kermit COPYING.TXT file or the
24 copyright text in the ckcmai.c module for disclaimer and permissions.
28 NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be
29 compatible with C preprocessors that support only #ifdef, #else, #endif,
30 #define, and #undef. Please do not use #if, logical operators, or other
31 preprocessor features in any of the portable C-Kermit modules. You can,
32 of course, use these constructions in platform-specific modules when they
33 are supported by all compilers/preprocessors that could be used on that
37 extern int nettype; /* Defined in ckcmai.c */
42 #include "ckcsym.h" /* This must go first */
43 #include "ckcdeb.h" /* This must go second */
49 #endif /* _NO_PROTO */
54 #include <errno.h> /* Error number symbols */
56 #ifndef ERRNO_INCLUDED
57 #include <errno.h> /* Error number symbols */
58 #endif /* ERRNO_INCLUDED */
59 #endif /* HPUXPRE65 */
69 #endif /* __FreeBSD__ */
71 #endif /* __386BSD__ */
75 #endif /* SCO_OSR504 */
81 #define FD_SETSIZE (3 * sizeof(long) * 8)
82 static struct timeval tv;
89 #include "ckcnet.h" /* Symbols for network types. */
95 The directory-related includes are here because we need to test some
96 file-system-related symbols to find out which system we're being compiled
97 under. For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
99 #ifdef SDIRENT /* Directory bits... */
104 #include <sys/ndir.h>
108 #else /* !NDIR, !XNDIR */
110 #include "/usr/lib/ndir.h"
111 #else /* !RTU, !NDIR, !XNDIR */
114 #include <sys/dirent.h>
118 #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
131 /* I don't know why this is needed here since we never reference bzero(). */
132 /* But without it C-Kermit won't link in an HP-UX 5.xx non-TCP build. */
134 bzero(s,n) char *s; int n; {
135 extern char * memset();
138 #endif /* TCPSOCKET */
141 /* Definition of HZ, used in msleep() */
144 #define HZ ( 1000 / CLOCK_TICK )
149 #define HZ ( 1000 / CLOCK_TICK )
152 #define nap(x) (void)syscall(3112, (x))
160 #undef NGROUPS_MAX /* Prevent multiple definition warnings */
164 NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding
165 library routine, so _poll comes up undefined at link time.
168 #ifndef AIXRS /* IBM AIX needs special handling */
169 #include <poll.h> /* "standard" (SVID) i/o multiplexing, etc */
171 #ifdef SVR4 /* AIX 3.2 is like SVID... */
173 #else /* But AIX 3.1 is not ... */
174 #include <sys/poll.h> /* The include file is in include/sys */
175 #define events reqevents /* And it does not map IBM-specific member */
176 #define revents rtnevents /* names to the System V equivalents */
181 #include <signal.h> /* Signals */
183 /* For setjmp and longjmp */
192 The following test differentiates between 4.1 BSD and 4.2 & later.
193 If you have a 4.1BSD system with the DIRENT library, this test could
194 mistakenly diagnose 4.2BSD and then later enable the use of system calls
195 that aren't defined. If indeed there are such systems, we can use some
196 other way of testing for 4.1BSD, or add yet another compile-time switch.
200 #ifndef FT21 /* Except for Fortune. */
202 #ifndef BELLV10 /* And Bell Labs Research UNIX V10 */
207 #endif /* MAXNAMLEN */
210 #ifdef SUNOS41 /* From Christian Corti */
211 #define BSD44ORPOSIX /* Uni Stuttgart */
212 #define SVORPOSIX /* February 2010 */
214 #include <sys/ioctl.h>
220 #include <sys/filio.h> /* 299 for FIONREAD */
224 Minix 2.0 support added by Terry McConnell,
225 Syracuse University <tmc@barnyard.syr.edu>
226 No more sgtty interface, posix compliant.
229 #define _MINIX /* Needed for some Minix header files */
236 #include <sys/types.h>
237 #include <sys/ioctl.h>
240 #undef TIOCGETC /* defined in sys/ioctl.h, but not really supported */
245 MINIX 1.0 support added by Charles Hedrick,
246 Rutgers University <hedrick@aramis.rutgers.edu>.
247 MINIX also has V7 enabled.
256 #ifdef CK_REDIR /* <sys/wait.h> needed only for REDIRECT command. */
258 If anybody can figure out how to make this work with NeXTSTEP, be
259 my guest! (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS)
261 #ifndef CK_WAIT_H /* If wait.h not already included... */
262 #ifdef OSF /* force OSF to select POSIX wait */
263 #ifdef _BSD /* instead of BSD (see ckcdeb.h) */
268 #include <sys/wait.h> /* Include it */
271 #define _BSD /* Restore it */
273 #endif /* CK_OSF_BSD */
275 #endif /* CK_WAIT_H */
276 #endif /* CK_REDIR */
278 #include "ckuver.h" /* Version herald */
279 char *ckxsys = HERALD;
282 #include <sys/utsname.h>
284 #ifdef TRU64 /* Tru64 UNIX 4.0 and later */
285 /* Verified on Tru64 4.0F - might break on 4.0E or earlier */
286 #include <sys/sysinfo.h> /* (don't know about OSF/1 or DU) */
287 #include <machine/hal_sysinfo.h>
290 #ifdef SOLARIS25 /* Solaris 2.5 and later */
291 #include <sys/systeminfo.h> /* (don't know about earlier ones) */
292 #endif /* SOLARIS25 */
300 static int hpis800 = 0;
301 #endif /* HPUX9PLUS */
303 #define CK_SYSNMLN SYS_NMLN
306 #define CK_SYSNMLN _SYS_NMLN
309 #define CK_SYSNMLN UTSLEN
311 #define CK_SYSNMLN 31
313 #endif /* _SYS_NMLN */
314 #endif /* SYS_NMLN */
315 char unm_mch[CK_SYSNMLN+1] = { '\0', '\0' };
316 char unm_mod[CK_SYSNMLN+1] = { '\0', '\0' };
317 char unm_nam[CK_SYSNMLN+1] = { '\0', '\0' };
318 char unm_rel[CK_SYSNMLN+1] = { '\0', '\0' };
319 char unm_ver[CK_SYSNMLN+1] = { '\0', '\0' };
320 #endif /* CK_UTSNAME */
323 #include <stat.h> /* For chasing symlinks, etc. */
325 #include <sys/stat.h>
334 /* UUCP lockfile material... */
338 #ifdef HAVE_LOCKDEV /* Red Hat baudboy/lockdev */
340 Watch out: baudboy.h references open() without making sure it has been
341 declared, resulting in warnings on at least Red Hat 7.3. It's declared in
342 fcntl.h, but we don't include that until later. In this case only, we
343 include it here, and then the second include is harmless because in Red Hat
344 Linux (the only place where you find baudboy.h) fcntl.h is protected from
345 multiple inclusion by _FCNTL_H. - fdc, 10 May 2004.
347 NOTE: Although Linux /usr/sbin/lockdev obviates the need for setuid or
348 setgid bits to access the lockfile, C-Kermit will still need them to access
349 the serial port itself unless the port is open for world read/write.
350 Normally setgid uucp does the trick.
352 Extra: HAVE_LOCKDEV has been added als openSuSE >= 11.3 doesn't use baudboy
353 but ttylock. - jb, 26 Jul 2010
355 #include <fcntl.h> /* This has to come before baudboy */
356 #ifdef HAVE_BAUDBOY /* Red Hat baudboy/lockdev */
358 #else /* !HAVE_BAUDBOY */ /* openSuSE lock via ttylock */
360 #endif /* HAVE_BAUDBOY */
361 #define LOCK_DIR "/var/lock" /* (even though we don't care) */
363 #else /* !HAVE_LOCKDEV */
367 #include <libutil.h> /* FreeBSD */
369 #include <util.h> /* OpenBSD */
370 #endif /* HAVE_LOCKDEV */
371 #endif /* __FreeBSD */
372 #endif /* USE_UU_LOCK */
373 #else /* USETTYLOCK */
375 /* Name of UUCP tty device lockfile */
381 #endif /* LINUXFSSTND */
385 #endif /* ACUCNTRL */
388 PIDSTRING means use ASCII string to represent pid in lockfile.
405 #endif /* COHERENT */
410 #endif /* PIDSTRING */
412 /* Now the PIDSTRING exceptions... */
418 #endif /* PIDSTRING */
420 #ifdef __bsdi__ /* BSDI (at least thru 1.1) */
423 #endif /* PIDSTRING */
424 #endif /* __bsdi__ */
426 #ifdef OSF32 /* Digital UNIX (OSF/1) 3.2 */
429 #endif /* PIDSTRING */
433 LOCK_DIR is the name of the lockfile directory.
434 If LOCK_DIR is already defined (e.g. on command line), we don't change it.
439 #define LOCK_DIR "/var/spool/lock"
446 #define LOCK_DIR "/var/spool/lock"
449 #define LOCK_DIR "/var/spool/lock"
452 #define LOCK_DIR "/var/spool/lock"
455 #define LOCK_DIR "/var/spool/lock"
457 /* So which ones is this for? */
458 /* Probably original 4.4BSD on Vangogh */
459 /* Plus who knows about Mac OS X... It doesn't even have a cu program */
460 #define LOCK_DIR "/var/spool/uucp"
461 #endif /* __OpenBSD__ */
462 #endif /* __NetBSD__ */
463 #endif /* __FreeBSD__ */
464 #endif /* __386BSD__ */
467 #define LOCK_DIR "/var/spool/locks"
470 #define LOCK_DIR "/var/spool/locks"
472 #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */
473 #define LOCK_DIR "/etc/locks"
476 #define LOCK_DIR "/etc/locks"
479 #define LOCK_DIR "/etc/locks"
483 #define LOCK_DIR "/usr/spool/uucp"
486 #define LOCK_DIR "/usr/spool/uucp"
489 #define LOCK_DIR "/var/spool/locks"
492 #define LOCK_DIR "/var/spool/locks"
495 #define LOCK_DIR "/var/lock";
497 #define LOCK_DIR "/usr/spool/locks"
498 #endif /* LINUXFSSTND */
505 #define LOCK_DIR "/usr/spool/uucp/LCK"
508 #define LOCK_DIR "/usr/spool/uucp"
510 #define LOCK_DIR "/usr/spool/uucp"
511 #endif /* COHERENT */
520 #endif /* !LOCK_DIR (outside ifndef) */
522 #ifdef OSF2 /* OSF/1 2.0 or later */
523 #ifdef LOCK_DIR /* (maybe 1.x too, who knows...) */
525 #define LOCK_DIR "/var/spool/locks"
526 #endif /* LOCK_DIR */
530 /* Sorry no more lockf() -- we lock first and THEN open the device. */
534 #define LOCKF /* Use lockf() on tty device in SVR4 */
540 #ifdef NOLOCKF /* But NOLOCKF cancels LOCKF */
546 /* More about this below... */
548 #endif /* USETTYLOCK */
552 MYREAD means use our internally defined nonblocking buffered read routine.
562 /* bits for attmodem: internal modem in use, restart getty */
576 #define O_NDELAY O_NONBLOCK
577 #endif /* O_NDELAY */
578 #endif /* __bsdi__ */
581 Variables available to outside world:
583 dftty -- Pointer to default tty name string, like "/dev/tty".
584 dfloc -- 0 if dftty is console, 1 if external line.
585 dfprty -- Default parity
586 dfflow -- Default flow control
587 ckxech -- Flag for who echoes console typein:
588 1 - The program (system echo is turned off)
589 0 - The system (or front end, or terminal).
590 functions that want to do their own echoing should check this flag
593 flfnam -- Name of lock file, including its path, e.g.,
594 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
595 lkflfn -- Name of link to lock file, including its paths
596 haslock -- Flag set if this kermit established a uucp lock.
597 lockpid -- PID of other process that has desired line open, as string.
598 backgrd -- Flag indicating program executing in background ( & on
599 end of shell command). Used to ignore INT and QUIT signals.
600 rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle
603 Functions for assigned communication line (either external or console tty):
605 sysinit() -- System dependent program initialization
606 syscleanup() -- System dependent program shutdown
607 ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
608 ttclos() -- Close & reset the tty, releasing any access lock.
609 ttsspd(cps) -- Set the transmission speed of the tty.
610 ttgspd() -- Get (read) the the transmission speed of the tty.
611 ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
612 ttvt(speed,flow) -- Put the tty in virtual terminal mode.
613 or in DIALING or CONNECTED modem control state.
614 ttres() -- Restore original tty modes.
615 ttscarr(carrier) -- Set carrier control mode, on/off/auto.
616 ttinl(dest,max,timo) -- Timed read line from the tty.
617 ttinc(timo) -- Timed read character from tty.
618 myread() -- Raw mode bulk buffer read, gives subsequent
619 chars one at a time and simulates FIONREAD.
620 myunrd(c) -- Places c back in buffer to be read (one only)
621 ttchk() -- See how many characters in tty input buffer.
622 ttxin(n,buf) -- Read n characters from tty (untimed).
623 ttol(string,length) -- Write a string to the tty.
624 ttoc(c) -- Write a character to the tty.
625 ttflui() -- Flush tty input buffer.
626 ttsndb() -- Send BREAK signal.
627 ttsndlb() -- Send Long BREAK signal.
629 ttlock(ttname) -- "Lock" tty device against uucp collisions.
630 ttunlck() -- Unlock tty device.
632 For ATT7300/Unix PC, System V:
633 attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
634 offgetty(ttname) -- Turns off getty(1m) for comms line
635 ongetty(ttname) -- Restores getty() to comms line
639 Functions for console terminal:
641 congm() -- Get console terminal modes.
642 concb(esc) -- Put the console in single-character wakeup mode with no echo.
643 conbin(esc) -- Put the console in binary (raw) mode.
644 conres() -- Restore the console to mode obtained by congm().
645 conoc(c) -- Unbuffered output, one character to console.
646 conol(s) -- Unbuffered output, null-terminated string to the console.
647 conola(s) -- Unbuffered output, array of strings to the console.
648 conxo(n,s) -- Unbuffered output, n characters to the console.
649 conchk() -- Check if characters available at console (bsd 4.2).
650 Check if escape char (^\) typed at console (System III/V).
651 coninc(timo) -- Timed get a character from the console.
652 congks(timo) -- Timed get keyboard scan code.
653 conint() -- Enable terminal interrupts on the console if not background.
654 connoi() -- Disable terminal interrupts on the console if not background.
658 msleep(m) -- Millisecond sleep
659 ztime(&s) -- Return pointer to date/time string
660 rtimer() -- Reset timer
661 gtimer() -- Get elapsed time since last call to rtimer()
664 /* Conditional Includes */
666 /* Whether to include <sys/file.h> */
668 #ifdef RTU /* RTU doesn't */
672 #ifdef CIE /* CIE does. */
676 #ifdef BSD41 /* 4.1 BSD doesn't */
680 #ifdef is68k /* Integrated Solutions 68000 UNIX */
681 #define NOFILEH /* e.g. on Plexux P60 and Sun-1 */
684 #ifdef MINIX /* MINIX */
688 #ifdef COHERENT /* Coherent */
690 #endif /* COHERENT */
692 #ifndef NOFILEH /* Now include if selected. */
693 #include <sys/file.h>
698 #ifdef BSD44ORPOSIX /* POSIX uses termios.h */
702 #undef _POSIX_SOURCE /* Get extra stuff from termios.h */
704 #endif /* __bsdi__ */
707 #include <sys/ioctl.h>
718 #define _POSIX_SOURCE
720 #endif /* __bsdi__ */
721 #ifndef BSD44 /* Really POSIX */
722 #ifndef CK_QNX32 /* was CK_QNX32 */
723 #define NOSYSIOCTLH /* No ioctl's allowed. */
724 #undef ultrix /* Turn off any ultrix features. */
725 #endif /* CK_QNX32 */
729 /* System III, System V */
738 /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
740 struct termiox rctsx;
744 /* Sorry, this is truly disgusting but it's SCO's fault. */
749 #endif /* SCO_OSR504 */
750 #include <sys/termiox.h>
751 struct termiox rctsx;
755 #endif /* CK_SVID3_X */
756 #endif /* STERMIOX */
760 #ifdef COHERENT /* Use termio.h, not sgtty.h for Coherent */
762 #endif /* COHERENT */
764 #ifdef MINIX /* MINIX uses ioctl's */
765 #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */
770 #ifndef NOSYSIOCTLH /* Others use ioctl() */
773 This is to get rid of cpp warning messages that occur because all of
774 these symbols are defined by both termios.h and ioctl.h on the SUN.
796 #include <sys/ioctl.h>
797 #endif /* NOSYSIOCTLH */
799 We really, really, REALLY want FIONREAD, because it is the only way to find
800 out not just *if* stuff is waiting to be read, but how much, which is
801 critical to our sliding-window and streaming procedures, not to mention
802 efficiency of CONNECT, etc.
805 #include <sys/filio.h> /* For FIONREAD */
812 /* It wasn't found in ioctl.h or term*.h - try these places: */
814 #include <sys/filio.h>
817 #include <sys/filio.h>
819 #endif /* UNIXWARE */
820 #endif /* FIONREAD */
822 #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */
824 <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as
825 something. Due to this, in_chk() uses the FIONREAD instead of RDCHK
826 and the hot keys during file transfer (X to cancel file etc) do not
827 work because FIONREAD doesn't work even though it is defined.
829 NOTE: This might also be true elsewhere.
833 #endif /* FIONREAD */
836 #ifdef CK_SCOV5 /* Ditto for SCO OpenServer 5.0 */
837 #ifndef SCO_OSR507 /* 299 */
840 #endif /* FIONREAD */
841 #endif /* SCO_OSR507 */
842 #endif /* CK_SCOV5 */
844 #ifdef SCO_OSR507 /* 299 */
848 #endif /* SCO_OSR507 */
850 /* Whether to include <fcntl.h> */
852 #ifndef is68k /* Only a few don't have this one. */
858 #endif /* COHERENT */
862 #endif /* not is68k */
868 #include <sys/fcntl.h>
870 #endif /* COHERENT */
872 #ifdef ATT7300 /* Unix PC, internal modem dialer */
873 #include <sys/phone.h>
876 #ifdef HPUX /* HP-UX variations. */
878 #include <sys/modem.h> /* HP-UX modem signals */
879 #ifdef hp9000s500 /* Model 500 */
881 #endif /* hp9000s500 */
885 #endif /* HPUXPRE65 */
887 #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */
888 #endif /* HPUXJOBCTL */
892 Which time.h files to include... See ckcdeb.h for defaults.
893 Note that 0, 1, 2, or all 3 of these can be included according to
894 the symbol definitions.
904 #include <sys/time.h>
905 #endif /* SYSTIMEH */
906 #endif /* NOSYSTIMEH */
910 #include <sys/timeb.h>
911 #endif /* SYSTIMEBH */
912 #endif /* NOSYSTIMEBH */
917 In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to
918 define the structs we need to access the higher speeds, so we have to
929 #endif /* DCLTIMEVAL */
930 #endif /* NODCLTIMEVAL */
933 /* THIS IS OBSOLETE since about Linux 0.92 */
935 #include <linux/serial.h>
936 #endif /* OLINUXHISPEED */
937 #ifdef __alpha__ /* Linux on DEC Alpha */
938 #ifndef __GLIBC__ /* But not with glibc */
939 #include <asm/termios.h>
940 #endif /* __GLIBC__ */
941 #endif /* __alpha__ */
942 #endif /* __linux__ */
944 #ifdef NOIEXTEN /* This is broken on some systems */
945 #undef IEXTEN /* like Convex/OS 9.1 */
946 #endif /* NOIEXTEN */
947 #ifndef IEXTEN /* Turn off ^O/^V processing. */
948 #define IEXTEN 0 /* Needed, at least, on BSDI. */
951 Pick up definitions needed for select() if we don't have them already.
952 Normally they come from <sys/types.h> but some systems get them from
953 <sys/select.h>... Rather than hardwire all of them into the source, we
954 include it if SELECT_H is defined in compile-time CFLAGS.
958 #include <sys/select.h>
959 #endif /* SELECT_H */
960 #endif /* SCO_OSR504 */
963 #include "/sys/ins/base.ins.c"
964 #include "/sys/ins/error.ins.c"
965 #include "/sys/ins/ios.ins.c"
966 #include "/sys/ins/sio.ins.c"
967 #include "/sys/ins/pad.ins.c"
968 #include "/sys/ins/time.ins.c"
969 #include "/sys/ins/pfm.ins.c"
970 #include "/sys/ins/pgm.ins.c"
971 #include "/sys/ins/ec2.ins.c"
972 #include "/sys/ins/type_uids.ins.c"
973 #include <default_acl.h>
978 #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */
982 /* The following #defines are catch-alls for those systems */
983 /* that didn't have or couldn't find <file.h>... */
995 #endif /* O_RDONLY */
997 /* This is for ancient Unixes that don't have these tty symbols defined. */
1000 #define PENDIN ICANON
1003 #define FLUSHO ICANON
1006 #define EXTPROC ICANON
1007 #endif /* EXTPROC */
1011 Modem signals are also forbidden in the POSIX world. But some POSIX-based
1012 platforms let us at them anyway if we know where to look.
1015 /* Doesn't work for Linux */
1018 #endif /* UNIXWARE7 */
1019 #endif /* NEEDMDMDEFS */
1023 #define TIOCMGET (('t'<<8)|29)
1024 #endif /* TIOCMGET */
1027 #define TIOCM_DTR 0x0002
1028 #endif /* TIOCM_DTR */
1030 #define TIOCM_RTS 0x0004
1031 #endif /* TIOCM_RTS */
1033 #define TIOCM_CTS 0x0020
1034 #endif /* TIOCM_CTS */
1036 #define TIOCM_CAR 0x0040
1037 #endif /* TIOCM_CAR */
1039 #define TIOCM_RNG 0x0080
1040 #endif /* TIOCM_RNG */
1042 #define TIOCM_DSR 0x0100
1043 #endif /* TIOCM_DSR */
1044 #endif /* NEEDMDMDEFS */
1045 #endif /* SVORPOSIX */
1054 #define TCGETA TCGETS
1055 #define TCSETA TCSETS
1056 #define TCSETAW TCSETSW
1057 #define TCSETAF TCSETSF
1058 #define termio termios
1061 #ifdef SVORPOSIX /* AT&T Sys V or POSIX */
1062 #ifdef UNIXWAREPOSIX /* UnixWare 7 POSIX build */
1064 In Unixware POSIX builds, <[sys/]time.h> refuses to define the
1065 structs we need to access the higher speeds, so we have to do it
1076 #endif /* UNIXWAREPOSIX */
1077 #endif /* SVORPOSIX */
1082 Because Xenix <time.h> doesn't declare time() if we're using gcc.
1086 #endif /* __GNUC__ */
1088 /* Special stuff for V7 input buffer peeking */
1091 int kmem[2] = { -1, -1};
1092 char *initrawq(), *qaddr[2]={0,0};
1097 /* dftty is the device name of the default device for file transfer */
1098 /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
1101 char * dftty = NULL;
1102 char * dfmdm = "none";
1103 int dfloc = 0; /* that goes in local mode by default */
1107 char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
1108 char *dfmdm = "none";
1109 int dfloc = 1; /* that goes in local mode by default */
1111 char *dftty = CTTNAM; /* Remote by default, use normal */
1112 char *dfmdm = "none";
1113 int dfloc = 0; /* controlling terminal name. */
1116 char *dftty = DFTTY; /* Default location specified on */
1117 char *dfmdm = "none"; /* command line. */
1118 int dfloc = 1; /* controlling terminal name. */
1122 #define CON_RES 0 /* Console state is "reset" */
1123 #define CON_CB 1 /* Console state is CBREAK */
1124 #define CON_BIN 2 /* Console state is binary */
1125 static int constate = CON_RES;
1127 #define CONI_RES 0 /* Console interrupts are "reset" */
1128 #define CONI_INT 1 /* Console intterupts are set */
1129 #define CONI_NOI 2 /* Console intterupts are disabled */
1130 static int conistate = CONI_RES;
1133 #define CONBUFSIZ 15
1135 #define CONBUFSIZ 255
1136 #endif /* CK_SMALL */
1137 static char conbuf[CONBUFSIZ]; /* Console readahead buffer */
1138 static int conbufn = 0; /* Chars in readahead buffer */
1139 static char *conbufp = conbuf; /* Next char in readahead buffer */
1141 char cttnam[DEVNAMLEN+1] = { '\0', '\0' }; /* Determined at runtime */
1144 int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */
1147 int dfprty = DEFPAR; /* Default parity (0 = none) */
1148 int ttprty = 0; /* The parity that is in use. */
1149 static int ttpmsk = 0xff; /* Parity stripping mask. */
1150 int ttmdm = 0; /* Modem in use. */
1151 int ttcarr = CAR_AUT; /* Carrier handling mode. */
1152 int dfflow = FLO_NONE; /* Default flow control is NONE */
1153 int backgrd = 0; /* Assume in foreground (no '&' ) */
1155 int iniflags = -1; /* fcntl flags for ttyfd */
1156 #endif /* F_SETFL */
1157 int fdflag = 0; /* Flag for redirected stdio */
1158 int ttfdflg = 0; /* Open File descriptor was given */
1159 int tvtflg = 0; /* Flag that ttvt has been called */
1160 long ttspeed = -1L; /* For saving speed */
1161 int ttflow = -9; /* For saving flow */
1162 int ttld = -1; /* Line discipline */
1165 static int km_con = -1; /* Kanji mode for console tty */
1166 static int km_ext = -1; /* Kanji mode for external device */
1167 #endif /* sony_news */
1170 static int needpchk = 1; /* Need parity check */
1172 static int needpchk = 0;
1173 #endif /* PARSENSE */
1175 extern int stopbits; /* Stop bits */
1178 Unfortunately we must do this with global variables rather than through the
1179 tt...() APIs to avoid changing the APIs and the many modules that use them.
1180 If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
1181 bits + parity or 8 data bits and no parity, and overrides the regular parity
1182 variable, which is communicated to this module thru ttpkt(), and represented
1183 locally by the ttprty variable.
1185 extern int hwparity; /* Hardware parity */
1186 #endif /* HWPARITY */
1190 static int nodelay_sav = -1;
1191 #endif /* TCP_NODELAY */
1192 #endif /* TCPSOCKET */
1194 static int sigint_ign = 0; /* SIGINT is ignored */
1197 Having this module rely on external globals is bad, but fixing this
1198 requires overhaul of the ck*tio.c modules for all the different operating
1199 systems supported by C-Kermit. Left for a future release.
1201 extern int ttnproto; /* Defined in ckcnet.c */
1202 extern int ttnet; /* Defined in ckcnet.c */
1203 extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */
1204 extern int xsuspend, wasclosed;
1205 extern int inserver, local;
1207 int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
1209 int ckmaxfiles = 0; /* Max number of open files */
1211 #ifdef CK_ENCRYPTION /* Kerberos */
1213 extern int me_encrypt, u_encrypt;
1214 #endif /* CK_ENCRYPTION */
1216 /* Declarations of variables global within this module */
1218 #ifdef TTLEBUF /* See ckcnet.h */
1220 #define LEBUFSIZ 4096
1221 static CHAR le_buf[LEBUFSIZ];
1222 static int le_start = 0, le_end = 0, le_data = 0;
1223 #endif /* TTLEBUF */
1225 #define MSGBUF_SIZE 1024 /* For debugging */
1226 static char msgbuf[MSGBUF_SIZE];
1228 static int gotsigs = 0;
1230 static time_t tcount = (time_t)0; /* Elapsed time counter */
1232 static SIGTYP (*saval)() = NULL; /* For saving alarm() handler */
1233 static SIGTYP (*savquit)() = NULL; /* and other signal handlers */
1235 static SIGTYP (*savusr1)() = NULL;
1236 #endif /* SIGUSR1 */
1238 static SIGTYP (*savusr2)() = NULL;
1239 #endif /* SIGUSR2 */
1241 static SIGTYP (*savpipe)() = NULL;
1242 #endif /* SIGPIPE */
1244 static SIGTYP (*savdanger)() = NULL;
1245 #endif /* SIGDANGER */
1248 static SIGTYP (*jchdlr)() = NULL; /* For checking suspend handler */
1250 static int jcshell = -1; /* And flag for result */
1253 BREAKNULS is defined for systems that simulate sending a BREAK signal
1254 by sending a bunch of NUL characters at low speed.
1259 #endif /* BREAKNULS */
1265 #endif /* BREAKNULS */
1269 static char /* A string of nulls */
1270 *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";
1271 #endif /* BREAKNULS */
1273 #ifdef CK_POSIX_SIG /* Longjump buffers */
1274 static sigjmp_buf sjbuf; /* POSIX signal handling */
1276 static jmp_buf sjbuf;
1277 #endif /* CK_POSIX_SIG */
1280 static jmp_buf jjbuf;
1283 /* static */ /* (Not static any more) */
1284 int ttyfd = -1; /* TTY file descriptor */
1286 int ttpipe = 0; /* NETCMD: Use pipe instead of ttyfd */
1287 int ttpty = 0; /* NETPTY: Use pty instead of ttfyd */
1289 #ifdef NETPTY /* These are in ckupty.c */
1290 extern PID_T pty_fork_pid;
1291 extern int pty_master_fd, pty_slave_fd;
1296 static int pipe0[2], pipe1[2]; /* Pipes for net i/o */
1297 #endif /* NETCONN */
1298 static PID_T ttpid = 0; /* Process ID for fork */
1299 static int fdin, fdout; /* File descriptors for pipe */
1300 static FILE * ttout = NULL; /* File pointer for output pipe */
1302 /* fdopen() needs declaring because it's not declared in <stdio.h> */
1303 _PROTOTYP( FILE * fdopen, (int, char *) );
1304 #endif /* DCLFDOPEN */
1307 extern int pexitstat, quiet;
1310 int ttyctlfd = -1; /* TTY control channel - What? UNIX doesn't have one? */
1311 int consctlfd = -1; /* Console control channel */
1312 int noisefd = -1; /* tone channel */
1313 static int ttylastspeed = -1; /* So we can lie about the speed */
1316 int telnetfd = 0; /* File descriptor is for telnet */
1318 int x25fd = 0; /* File descriptor is for X.25 */
1319 #endif /* NETCONN */
1321 char lockpid[16] = { '\0', '\0' }; /* PID stored in lockfile, as string */
1323 static int lkf = 0, /* Line lock flag */
1324 cgmf = 0, /* Flag that console modes saved */
1325 xlocal = 0, /* Flag for tty local or remote */
1326 curcarr = 0; /* Carrier mode: require/ignore. */
1328 static int netconn = 0; /* 1 if network connection active */
1330 static char escchr; /* Escape or attn character */
1333 #include <sys/time.h>
1334 #endif /* CK_SCO32V4 */
1337 static struct timeval tv; /* For getting time, from sys/time.h */
1338 #endif /* HAVE_TV */
1340 static struct timezone tz;
1341 #endif /* HAVE_TZ */
1344 static struct timeb ftp; /* And from sys/timeb.h */
1348 static long xclock; /* For getting time from sys/time.h */
1349 static struct timeb ftp; /* And from sys/timeb.h */
1353 static long xclock; /* For getting time from sys/time.h */
1354 static struct timeb ftp; /* And from sys/timeb.h */
1358 static long xclock; /* For getting time from sys/time.h */
1359 static struct timeb ftp; /* And from sys/timeb.h */
1360 #endif /* BELLV10 */
1363 static long xclock; /* For getting time from sys/time.h */
1364 static struct timeb ftp; /* And from sys/timeb.h */
1368 static long xclock; /* For getting time from sys/time.h */
1369 static struct timeb ftp; /* And from sys/timeb.h */
1373 static long xclock; /* For getting time from sys/time.h */
1374 static struct timeb ftp; /* And from sys/timeb.h */
1375 #endif /* COHERENT */
1381 /* sgtty/termio information... */
1383 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
1384 static struct termios
1385 ttold, ttraw, tttvt, ttcur,
1386 ccold, ccraw, cccbrk;
1387 #else /* BSD, V7, etc */
1389 #ifdef COHERENT /* Hack alert... */
1391 #endif /* COHERENT */
1394 static struct termio ttold = {0}; /* Init'd for word alignment, */
1395 static struct termio ttraw = {0}; /* which is important for some */
1396 static struct termio tttvt = {0}; /* systems, like Zilog... */
1397 static struct termio ttcur = {0};
1398 static struct termio ccold = {0};
1399 static struct termio ccraw = {0};
1400 static struct termio cccbrk = {0};
1402 static struct sgttyb /* sgtty info... */
1403 ttold, ttraw, tttvt, ttcur, /* for communication line */
1404 ccold, ccraw, cccbrk; /* and for console */
1406 static struct ttydevb /* Device info... */
1407 tdold, tdcur; /* for communication device */
1408 #endif /* BELLV10 */
1410 static struct tchars tchold, tchnoi;
1413 #endif /* TIOCGETC */
1415 static struct ltchars ltchold, ltchnoi;
1417 #endif /* TIOCGLTC */
1418 int lmodef = 0; /* Local modes */
1421 #endif /* BSD44ORPOSIX */
1424 /* It picks up the speeds but they don't work */
1425 #ifdef UNIXWARE /* For higher serial speeds */
1426 #ifdef UW7 /* in Unixware 7.0 */
1427 #include <sys/asyc.h> /* This picks up 57600 and 115200 */
1429 #endif /* UNIXWARE */
1430 #endif /* COMMENT */
1433 static struct sgttyb ttbuf;
1437 /* do we really need this? */
1438 static struct sgttyb vanilla;
1442 static int attmodem = 0; /* ATT7300 internal-modem status */
1443 struct updata dialer = {0}; /* Condition dialer for data call */
1444 #endif /* ATT7300 */
1450 char lkflfn[FLFNAML] = { '\0', '\0' }; /* and possible link to it */
1452 char lock2[FLFNAML] = { '\0', '\0' }; /* Name of second lockfile */
1453 #endif /* USETTYLOCK */
1457 char flfnam[FLFNAML+1] = { '\0', '\0' }; /* UUCP lock file path name */
1459 int haslock = 0; /* =1 if this kermit locked uucp */
1463 static int conesc = 0; /* set to 1 if esc char (^\) typed */
1466 static int conesc = 0;
1469 static int conesc = 0;
1472 #endif /* SVORPOSIX */
1475 /* Local copy of comm device name or network host */
1476 static char ttnmsv[DEVNAMLEN+1] = { '\0', '\0' };
1478 static char lockname[DEVNAMLEN+1]; /* Ditto, the part after "/dev/". */
1479 #endif /* USETTYLOCK */
1482 static status_$t st; /* error status return value */
1483 static short concrp = 0; /* true if console is CRP pad */
1484 static uid_$t ttyuid; /* tty type uid */
1485 static uid_$t conuid; /* stdout type uid */
1487 /* APOLLO Aegis main()
1488 * establish acl usage and cleanup handling
1489 * this makes sure that CRP pads
1490 * get restored to a usable mode
1492 main(argc,argv) int argc; char **argv; {
1494 pfm_$cleanup_rec dirty;
1496 PID_T pid = getpid();
1498 /* acl usage according to invoking environment */
1499 default_acl(USE_DEFENV);
1501 /* establish a cleanup continuation */
1502 status = pfm_$cleanup(dirty);
1503 if (status.all != pfm_$cleanup_set) {
1504 /* only handle faults for the original process */
1505 if (pid == getpid() && status.all > pgm_$max_severity) {
1506 /* blew up in main process */
1508 pfm_$cleanup_rec clean;
1510 /* restore the console in any case */
1513 /* attempt a clean exit */
1514 debug(F101, "cleanup fault status", "", status.all);
1516 /* doexit(), then send status to continuation */
1517 quo = pfm_$cleanup(clean);
1518 if (quo.all == pfm_$cleanup_set)
1519 doexit(pgm_$program_faulted,-1);
1520 else if (quo.all > pgm_$max_severity)
1521 pfm_$signal(quo); /* blew up in doexit() */
1523 /* send to the original continuation */
1524 pfm_$signal(status);
1527 return(ckcmai(argc, argv));
1531 /* ANSI-style prototypes for internal functions. */
1532 /* Functions used outside this module are prototyped in ckcker.h. */
1535 _PROTOTYP( SIGTYP timerh, () );
1536 _PROTOTYP( SIGTYP cctrap, () );
1537 _PROTOTYP( SIGTYP esctrp, () );
1538 _PROTOTYP( SIGTYP sig_ign, () );
1540 _PROTOTYP( SIGTYP timerh, (int) );
1541 _PROTOTYP( SIGTYP cctrap, (int) );
1542 _PROTOTYP( SIGTYP esctrp, (int) );
1544 _PROTOTYP( int do_open, (char *) );
1545 _PROTOTYP( static int in_chk, (int, int) );
1546 _PROTOTYP( static int ttrpid, (char *) );
1547 _PROTOTYP( static int ttchkpid, (char *) );
1548 _PROTOTYP( static int ttlock, (char *) );
1549 _PROTOTYP( static int ttunlck, (void) );
1550 _PROTOTYP( static VOID sigchld_handler, (int) );
1551 _PROTOTYP( int mygetbuf, (void) );
1552 _PROTOTYP( int myfillbuf, (void) );
1553 _PROTOTYP( VOID conbgt, (int) );
1555 _PROTOTYP( VOID acucntrl, (char *, char *) );
1556 #endif /* ACUCNTRL */
1559 _PROTOTYP( int carrctl, (struct termios *, int) );
1562 _PROTOTYP( int carrctl, (struct termio *, int) );
1564 _PROTOTYP( int carrctl, (struct sgttyb *, int) );
1566 #endif /* BSD44ORPOSIX */
1569 _PROTOTYP( int attdial, (char *, long, char *) );
1570 _PROTOTYP( int offgetty, (char *) );
1571 _PROTOTYP( int ongetty, (char *) );
1572 #endif /* ATT7300 */
1576 /* BeOS is not capable of using SELECT on anything but sockets */
1579 #include <kernel/OS.h>
1580 /* #ifdef BE_DR_7 */
1581 static double time_started = 0.0;
1582 struct ALARM_STRUCT {
1586 static thread_id alarm_thread = -1;
1587 static struct ALARM_STRUCT alarm_struct;
1588 _PROTOTYP( long do_alarm, (void *) );
1589 _PROTOTYP( unsigned int alarm, (unsigned int) );
1590 _PROTOTYP( void alarm_expired, (void) );
1591 /* #endif */ /* BE_DR_7 */
1592 #endif /* BEOSORBEBOX */
1595 #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
1596 #endif /* xunchar */
1600 xxlast(char *s, char c)
1603 xxlast(s,c) char *s; char c;
1604 #endif /* CK_ANSIC */
1605 /* xxlast */ { /* Last occurrence of character c in string s. */
1607 for (i = (int)strlen(s); i > 0; i--)
1608 if (s[i-1] == c ) return(s + (i - 1));
1612 /* Timeout handler for communication line input functions */
1616 timerh(foo) int foo; {
1619 /* #ifdef BE_DR_7 */
1621 /* #endif */ /* BE_DR_7 */
1622 #endif /* BEOSORBEBOX */
1624 siglongjmp(sjbuf,1);
1627 #endif /* CK_POSIX_SIG */
1632 xtimerh(foo) int foo; { /* Like timerh() but does */
1633 #ifdef BEOSORBEBOX /* not reset the timer itself */
1634 /* #ifdef BE_DR_7 */
1636 /* #endif */ /* BE_DR_7 */
1637 #endif /* BEOSORBEBOX */
1639 siglongjmp(sjbuf,1);
1642 #endif /* CK_POSIX_SIG */
1646 /* Control-C trap for communication line input functions */
1648 int cc_int; /* Flag */
1649 SIGTYP (* occt)(); /* For saving old SIGINT handler */
1653 cctrap(foo) int foo; { /* Needs arg for ANSI C */
1654 cc_int = 1; /* signal() prototype. */
1658 /* S Y S I N I T -- System-dependent program initialization. */
1661 * ttgwsiz() returns:
1662 * 1 tt_rows and tt_cols are known, both altered, both > 0
1663 * 0 tt_rows and/or tt_cols are known, both altered, one or both <= 0
1664 * -1 tt_rows and tt_cols are unknown and unaltered
1667 extern int tt_rows, tt_cols;
1672 int rows = 0, cols = 0;
1673 p = getenv("LINES");
1674 debug(F110,"xttgwsiz LINES",p,0);
1678 p = getenv("COLUMNS");
1679 debug(F110,"xttgwsiz COLUMNS",p,0);
1696 le_init() { /* LocalEchoInit() */
1698 for (i = 0; i < LEBUFSIZ; i++)
1706 le_clean() { /* LocalEchoCleanup() */
1714 if (le_start != le_end) {
1717 LEBUFSIZ) % LEBUFSIZ;
1719 debug(F111,"le_inbuf","chars waiting",rc);
1727 le_putchar(ch) CHAR ch;
1728 #endif /* CK_ANSIC */
1731 /* In UNIX we do not have another thread taking chars out of the buffer */
1732 while ((le_start - le_end == 1) ||
1733 (le_start == 0 && le_end == LEBUFSIZ - 1)) {
1734 /* Buffer is full */
1735 debug(F111,"le_putchar","Buffer is Full",ch);
1736 ReleaseLocalEchoMutex() ;
1738 RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
1741 if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
1742 debug(F110,"le_putchar","buffer is full",0);
1745 #endif /* COMMENT */
1746 le_buf[le_end++] = ch;
1747 if (le_end == LEBUFSIZ)
1755 le_puts(CHAR * s, int n)
1757 le_puts(s,n) CHAR * s; int n;
1758 #endif /* CK_ANSIC */
1762 CHAR * p = (CHAR *)"le_puts";
1764 for (i = 0; i < n; i++)
1765 rc = le_putchar((char)s[i]);
1766 debug(F101,"le_puts","",rc);
1774 le_putstr(s) CHAR * s;
1775 #endif /* CK_ANSIC */
1779 p = (CHAR *)"le_putstr";
1780 ckhexdump(p,s,(int)strlen((char *)s));
1781 for (p = s; *p && !rc; p++)
1782 rc = le_putchar(*p);
1788 le_getchar(CHAR * pch)
1789 #else /* CK_ANSIC */
1790 le_getchar(pch) CHAR * pch;
1791 #endif /* CK_ANSIC */
1794 if (le_start != le_end) {
1795 *pch = le_buf[le_start];
1796 le_buf[le_start] = 0;
1799 if (le_start == LEBUFSIZ)
1802 if (le_start == le_end) {
1811 #endif /* TTLEBUF */
1815 Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ.
1816 But as far as I know, whenever TIOCGSIZE is defined, it is
1817 equated to TIOCGWINSZ. For cases where this is not done, try this:
1821 #define TIOCGWINSZ TIOCGSIZE
1822 #endif /* TIOCGSIZE */
1823 #endif /* TIOCGWINSZ */
1824 #endif /* COMMENT */
1826 static int tt_xpixel = 0, tt_ypixel = 0;
1834 NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
1835 This code works for both the 16- and 32-bit versions.
1837 extern int dev_size(int, int, int, int *, int *);
1840 if (dev_size(0, -1, -1, &r, &c) == 0) {
1841 debug(F101,"ttgwsiz QNX r","",r);
1842 debug(F101,"ttgwsiz QNX c","",c);
1845 return ((r > 0 && c > 0) ? 1 : 0);
1846 } else return(xttgwsiz());
1850 /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
1851 #ifdef XENIX /* SCO UNIX 3.2v4.0 */
1852 #include <sys/stream.h> /* typedef mblk_t needed by ptem.h */
1853 #include <sys/ptem.h> /* for ttgwsiz() */
1856 #ifdef I386IX /* Ditto for Interactive */
1857 #include <sys/stream.h>
1858 #include <sys/ptem.h>
1861 /* Note, the above might be needed for some other older SVR3 Intel makes... */
1871 x = ioctl(0, (int)TIOCGWINSZ, (char *)&w);
1872 debug(F101,"ttgwsiz TIOCGWINSZ","",x);
1875 } else if (w.ws_row > 0 && w.ws_col > 0) {
1878 tt_xpixel = w.ws_xpixel;
1879 tt_ypixel = w.ws_ypixel;
1880 debug(F101,"ttgwsiz tt_rows","",tt_rows);
1881 debug(F101,"ttgwsiz tt_cols","",tt_cols);
1884 debug(F100,"ttgwsiz TIOCGWINSZ 00","",0);
1889 #endif /* TIOCGWINSZ */
1896 _PROTOTYP( int rlog_naws, (void) );
1897 #endif /* RLOGCODE */
1902 winchh(foo) int foo; { /* SIGWINCH handler */
1908 #endif /* CK_TTYFD */
1909 extern int tt_rows, tt_cols, cmd_rows, cmd_cols;
1912 debug(F100,"***************","",0);
1913 debug(F100,"SIGWINCH caught","",0);
1914 debug(F100,"***************","",0);
1916 debug(F101,"SIGWINCH pty_fork_pid","",pty_fork_pid);
1920 signal(SIGWINCH,winchh); /* Re-arm the signal */
1921 x = ttgwsiz(); /* Get new window size */
1922 cmd_rows = tt_rows; /* Adjust command screen too */
1926 if /* If we don't have a connection */
1927 #ifdef VMS /* we're done. */
1934 #endif /* CK_TTYFD */
1938 if (pty_fork_pid > -1) { /* "set host" to a PTY? */
1942 struct winsize w; /* Resize the PTY */
1946 w.ws_xpixel = tt_xpixel;
1947 w.ws_ypixel = tt_ypixel;
1948 x = ioctl(ttyfd,TIOCSWINSZ,&w);
1949 debug(F101,"winchh TIOCSWINSZ","",x);
1950 debug(F101,"winchh TIOCSWINSZ errno","",errno);
1951 #endif /* TIOCSWINSZ */
1954 x = kill(pty_fork_pid,SIGWINCH);
1955 debug(F101,"winchh kill","",x);
1956 debug(F101,"winchh kill errno","",errno);
1961 This should be OK. It might seem that sending this from
1962 interrupt level could interfere with another TELNET IAC string
1963 that was in the process of being sent. But we always send
1964 TELNET strings with a single write(), which should prevent mixups.
1965 blah_snaws() should protect themselves from being called on the
1966 wrong kind of connection.
1970 if (x > 0 && tt_rows > 0 && tt_cols > 0) {
1974 #endif /* RLOGCODE */
1976 #endif /* NOTTGWSIZ */
1977 #endif /* TCPSOCKET */
1980 #endif /* SIGWINCH */
1981 #endif /* NOSIGWINCH */
1984 sighup(foo) int foo; { /* SIGHUP handler */
1986 debug(F100,"***************","",0);
1987 debug(F100,"SIGHUP received","",0);
1988 debug(F100,"***************","",0);
1989 doexit(BAD_EXIT,-1);
1991 SIGRETURN; /* Shut picky compilers up... */
1995 /* Exists but there is no prototype in the header files */
1996 _PROTOTYP( char * ttyname, (int) );
1999 _PROTOTYP( char * ttyname, (int) );
2002 _PROTOTYP( char * ttyname, (int) );
2005 _PROTOTYP( char * ttyname, (int) );
2008 _PROTOTYP( char * ttyname, (int) );
2011 _PROTOTYP( char * ttyname, (int) );
2014 _PROTOTYP( char * ttyname, (int) );
2016 #endif /* PS2AIX10 */
2020 #endif /* SV68R3V6 */
2021 #endif /* CK_SCO32V4 */
2023 #ifndef SIGUSR1 /* User-defined signals */
2025 #endif /* SIGUSR1 */
2029 #endif /* SIGUSR2 */
2032 ignorsigs() sets certain signals to SIG_IGN. But when a signal is
2033 ignored, it remains ignored across exec(), so we have to restore these
2034 signals before exec(), which is the purpose of restorsigs().
2037 ignorsigs() { /* Ignore these signals */
2038 savquit = signal(SIGQUIT,SIG_IGN); /* Ignore Quit signal */
2040 #ifdef SIGDANGER /* Ignore danger signals */
2042 This signal is sent when the system is low on swap space. Processes
2043 that don't handle it are candidates for termination. If swap space doesn't
2044 clear out enough, we still might be terminated via kill() -- nothing we can
2045 do about that! Conceivably, this could be improved by installing a real
2046 signal handler that warns the user, but that would be pretty complicated,
2047 since we are not always in control of the screen -- e.g. during remote-mode
2050 savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */
2051 #endif /* SIGDANGER */
2054 This one comes when a TCP/IP connection is broken by the remote.
2055 We prefer to catch this situation by examining error codes from write().
2057 savpipe = signal(SIGPIPE,SIG_IGN);
2058 #endif /* SIGPIPE */
2059 savusr1 = signal(SIGUSR1,SIG_IGN); /* Ignore user-defined signals */
2060 savusr2 = signal(SIGUSR2,SIG_IGN);
2064 restorsigs() { /* Restore these signals */
2065 (VOID) signal(SIGQUIT,savquit); /* (used in ckufio.c) */
2067 (VOID) signal(SIGDANGER,savdanger);
2068 #endif /* SIGDANGER */
2070 (VOID) signal(SIGPIPE,savpipe);
2071 #endif /* SIGPIPE */
2072 (VOID) signal(SIGUSR1,savusr1);
2073 (VOID) signal(SIGUSR2,savusr2);
2081 struct utsname name;
2082 #endif /* CK_UTSNAME */
2084 extern char startupdir[];
2086 BEFORE ANYTHING ELSE: Initialize the setuid package.
2087 Change to the user's real user and group ID.
2088 If this can't be done, don't run at all.
2092 fprintf(stderr,"PRIV_INI=%d\n",x);
2093 #endif /* SUIDDEBUG */
2095 if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
2096 if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
2097 if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
2100 signal(SIGINT,SIG_IGN); /* Ignore interrupts at first */
2101 signal(SIGFPE,SIG_IGN); /* Ignore floating-point exceptions */
2102 signal(SIGHUP,sighup); /* Catch SIGHUP */
2105 signal(SIGWINCH,winchh); /* Catch window-size change */
2106 #endif /* SIGWINCH */
2107 #endif /* NOSIGWINCH */
2110 signal(SIGXFSZ,SIG_IGN); /* Ignore writing past file limit */
2111 #endif /* SIGXFSZ */
2115 Get the initial job control state.
2116 If it is SIG_IGN, that means the shell does not support job control,
2117 and so we'd better not suspend ourselves.
2120 jchdlr = signal(SIGTSTP,SIG_IGN);
2121 if (jchdlr == SIG_IGN) {
2123 debug(F100,"sysinit jchdlr: SIG_IGN","",0);
2124 } else if (jchdlr == SIG_DFL) {
2125 debug(F100,"sysinit jchdlr: SIG_DFL","",0);
2128 debug(F100,"sysinit jchdlr: other","",0);
2131 (VOID) signal(SIGTSTP,jchdlr); /* Put it back... */
2132 #endif /* SIGTSTP */
2135 conbgt(0); /* See if we're in the background */
2136 congm(); /* Get console modes */
2138 (VOID) signal(SIGALRM,SIG_IGN); /* Ignore alarms */
2140 ignorsigs(); /* Ignore some other signals */
2143 iniflags = fcntl(0,F_GETFL,0); /* Get stdin flags */
2144 #endif /* F_SETFL */
2147 gtty(0,&vanilla); /* Get sgtty info */
2150 set42sig(); /* Don't ask! (hakanson@cs.orst.edu) */
2154 Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
2155 never closes it. If it is called often enough, we run out of file
2156 descriptors and subsequent open()'s of other devices or files can fail.
2160 if (isatty(0)) /* Name of controlling terminal */
2166 debug(F110,"sysinit ttyname(0)",s,0);
2175 ckstrncpy((char *)cttnam,s,DEVNAMLEN+1);
2179 #endif /* SVORPOSIX */
2181 ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1);
2182 debug(F110,"sysinit CTTNAM",CTTNAM,0);
2183 debug(F110,"sysinit cttnam",cttnam,0);
2185 ttgwsiz(); /* Get window (screen) dimensions. */
2189 ckmaxfiles = sysconf(_SC_OPEN_MAX);
2190 #endif /* _SC_OPEN_MAX */
2191 #endif /* NOSYSCONF */
2195 consctlfd = open("/dev/consctl", O_WRONLY);
2196 /*noisefd = open("/dev/noise", O_WRONLY)*/
2202 if (uname(&name) > -1) {
2203 ckstrncpy(unm_mch,name.machine,CK_SYSNMLN);
2204 ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN);
2205 ckstrncpy(unm_rel,name.release,CK_SYSNMLN);
2206 ckstrncpy(unm_ver,name.version,CK_SYSNMLN);
2209 debug(F110,"sysinit uname machine",unm_mch,0);
2210 debug(F110,"sysinit uname sysname",unm_nam,0);
2211 debug(F110,"sysinit uname release",unm_rel,0);
2212 debug(F110,"sysinit uname version",unm_ver,0);
2217 if (name.machine[5] == '8')
2221 debug(F101,"sysinit hpis800","",hpis800);
2222 #endif /* HPUX9PLUS */
2224 getsysinfo(GSI_PLATFORM_NAME, unm_mod, CK_SYSNMLN, 0, 0);
2225 debug(F110,"sysinit getsysinfo model",unm_mod,0);
2228 sysinfo(SI_PLATFORM, unm_mod, CK_SYSNMLN);
2229 debug(F110,"sysinit sysinfo model",unm_mod,0);
2230 #endif /* SOLARIS25 */
2232 #endif /* CK_UTSNAME */
2234 #ifdef CK_ENVIRONMENT
2237 extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
2238 tn_env_prnt[], tn_env_sys[];
2240 extern char uidbuf[];
2241 extern char * whoami();
2249 debug(F110,"sysinit uidbuf from USER",uidbuf,0);
2252 p = getenv("LOGNAME");
2253 debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0);
2258 debug(F110,"sysinit uidbuf from whoami()",uidbuf,0);
2261 ckstrncpy(uidbuf, *p ? p : "UNKNOWN", UIDBUFLEN);
2265 debug(F110,"sysinit final uidbuf",uidbuf,0);
2266 #endif /* CKSENDUID */
2269 if ((p = getenv("JOB"))) ckstrncpy(tn_env_job,p,63);
2270 if ((p = getenv("ACCT"))) ckstrncpy(tn_env_acct,p,63);
2271 if ((p = getenv("PRINTER"))) ckstrncpy(tn_env_prnt,p,63);
2272 if ((p = getenv("DISPLAY"))) ckstrncpy(tn_env_disp,p,63);
2274 ckstrncpy(tn_env_sys,"Aegis",64);
2277 ckstrncpy(tn_env_sys,"Plan9",64);
2279 ckstrncpy(tn_env_sys,"UNIX",64);
2284 #endif /* CK_ENVIRONMENT */
2287 extern char * tn_loc;
2289 if (p = getenv("LOCATION"))
2290 if (tn_loc = (char *)malloc((int)strlen(p)+1))
2291 strcpy(tn_loc,p); /* safe */
2293 #endif /* CK_SNDLOC */
2295 ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
2296 startupdir[CKMAXPATH] = '\0';
2297 x = strlen(startupdir);
2299 startupdir[0] = '/';
2300 startupdir[1] = '\0';
2301 } else if (startupdir[x-1] != '/') {
2302 startupdir[x] = '/';
2303 startupdir[x+1] = '\0';
2305 debug(F110,"sysinit startupdir",startupdir,0);
2308 #endif /* TTLEBUF */
2310 /* This should catch the ncurses platforms */
2311 /* Some platforms don't have putenv(), like NeXTSTEP */
2312 putenv("NCURSES_NO_SETBUF=1");
2313 #endif /* BSD44ORPOSIX */
2317 /* S Y S C L E A N U P -- System-dependent program cleanup. */
2323 fcntl(0,F_SETFL,iniflags); /* Restore stdin flags */
2324 #endif /* F_SETFL */
2326 stty(0,&vanilla); /* Get sgtty info */
2329 if (ttpid) kill(ttpid,9);
2334 /* T T O P E N -- Open a tty for exclusive access. */
2338 ttname: character string - device name or network host name.
2340 If called with lcl < 0, sets value of lcl as follows:
2341 0: the terminal named by ttname is the job's controlling terminal.
2342 1: the terminal named by ttname is not the job's controlling terminal.
2343 But watch out: if a line is already open, or if requested line can't
2344 be opened, then lcl remains (and is returned as) -1.
2346 Less than zero: ttname is a network host name.
2347 Zero or greater: ttname is a terminal device name.
2348 Zero means a local connection (don't use modem signals).
2349 Positive means use modem signals.
2352 nonzero = number of seconds to wait for open() to return before timing out.
2356 -5 if device is in use
2357 -4 if access to device is denied
2358 -3 if access to lock directory denied
2359 -2 upon timeout waiting for device to open
2362 static int ttotmo = 0; /* Timeout flag */
2363 /* Flag kept here to avoid being clobbered by longjmp. */
2366 ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
2369 #define ctermid(x) strcpy(x,"")
2373 extern char *ctermid(); /* Wish they all had this! */
2374 #else /* CIE Regulus */
2375 #define ctermid(x) strcpy(x,"")
2377 #endif /* SVORPOSIX */
2385 char fullname[DEVNAMLEN+1];
2386 #endif /* OPENFIRST */
2388 char * fnam; /* Full name after expansion */
2393 #define NAMEFD /* Feature to allow name to be an open file descriptor */
2398 debug(F101,"ttopen telnetfd","",telnetfd);
2401 debug(F110,"ttopen ttname",ttname,0);
2402 debug(F110,"ttopen ttnmsv",ttnmsv,0);
2403 debug(F101,"ttopen modem","",modem);
2404 debug(F101,"ttopen netconn","",netconn);
2405 debug(F101,"ttopen ttyfd","",ttyfd);
2406 debug(F101,"ttopen *lcl","",*lcl);
2407 debug(F101,"ttopen ttmdm","",ttmdm);
2408 debug(F101,"ttopen ttnet","",ttnet);
2413 if (ttyfd > -1) { /* If device already opened */
2414 if (!strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
2415 return(0); /* Yes, nothing to do - just return */
2416 ttnmsv[0] = '\0'; /* No, clear out old name */
2417 ttclos(ttyfd); /* close old connection. */
2419 wasclosed = 0; /* New connection, not closed yet. */
2420 ttpipe = 0; /* Assume it's not a pipe */
2421 ttpty = 0; /* or a pty... */
2425 This is a bit tricky... Suppose that previously Kermit had dialed a telnet
2426 modem server ("set host xxx:2001, set modem type usr, dial ..."). Then the
2427 connection was closed (ttyfd = -1), and then a REDIAL command was given. At
2428 this point we've obliterated the negative modem type hack, and so would
2429 treat the IP hostname as a device name, and would then fail because of "No
2430 such device or directory". But the previous connection has left behind some
2431 clues, so let's use them...
2433 if (ttyfd < 0) { /* Connection is not open */
2434 if (!strcmp(ttname,ttnmsv)) { /* Old and new names the same? */
2435 if (((netconn > 0) && (ttmdm < 0)) ||
2437 (!ckstrchr(ttname,'/')) && (ckstrchr(ttname,':')))
2440 x = (ttmdm < 0) ? -ttmdm : ttnet;
2441 rc = netopen(ttname, lcl, x);
2442 debug(F111,"ttopen REOPEN netopen",ttname,rc);
2454 #endif /* NETCONN */
2457 debug(F100,"ttopen MAXNAMLEN defined","",0);
2459 debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
2463 debug(F100,"ttopen BSD4 defined","",0);
2465 debug(F100,"ttopen BSD4 *NOT* defined","",0);
2469 debug(F100,"ttopen BSD42 defined","",0);
2471 debug(F100,"ttopen BSD42 *NOT* defined","",0);
2475 debug(F100,"ttopen MYREAD defined","",0);
2477 debug(F100,"ttopen MYREAD *NOT* defined","",0);
2481 if (modem < 0) { /* modem < 0 = code for network */
2484 modem = -modem; /* Positive network type number */
2485 fdflag = 0; /* Stdio not redirected. */
2486 netconn = 1; /* And it's a network connection */
2487 debug(F111,"ttopen net",ttname,modem);
2489 for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
2490 if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
2491 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2492 ttfdflg = 1; /* We got an open file descriptor */
2493 debug(F111,"ttopen net ttfdflg",ttname,ttfdflg);
2494 debug(F101,"ttopen net ttyfd","",ttyfd);
2495 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2496 x = 1; /* Return code is "good". */
2499 if (ttnproto != NP_TCPRAW)
2500 ttnproto = NP_TELNET;
2507 } else { /* Host name or address given */
2509 if (modem == NET_PTY) {
2512 debug(F100,"ttopen PTY: nopush","",0);
2517 netconn = 1; /* but we don't use network i/o */
2519 debug(F110,"ttopen PTY",ttname,0);
2520 x = do_pty(&ttyfd,ttname,0);
2522 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2523 xlocal = *lcl = 1; /* It's local */
2534 dup2() is not available on older System V platforms like AT&T 3Bx. For
2535 those systems we punt by not defining NETCMD, but we might be able to do
2536 better -- see workarounds for this problem in ckufio.c (search for dup2).
2538 if (modem == NET_CMD) {
2540 debug(F100,"ttopen pipe: nopush","",0);
2543 if (pipe(pipe0) || pipe(pipe1)) {
2544 perror("Pipe error");
2547 ttpid = fork(); /* Make a fork */
2550 case -1: /* Error making fork */
2555 perror("Fork error");
2557 case 0: /* Child. */
2566 default: /* Parent */
2569 fdin = pipe0[0]; /* Read from pipe */
2570 fdout = pipe1[1]; /* Write to pipe */
2571 ttout = fdopen(fdout,"w"); /* Get stream so we can */
2572 if (!ttout) { /* make it unbuffered. */
2573 perror("fdopen failure");
2577 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2578 xlocal = *lcl = 1; /* It's local */
2579 netconn = 1; /* Call it a network connection */
2580 ttmdm = modem; /* Remember network type */
2589 x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
2591 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2597 #ifdef sony_news /* Sony NEWS */
2598 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
2599 perror("ttopen error getting Kanji mode (network)");
2600 debug(F111,"ttopen error getting Kanji mode","network",0);
2601 km_ext = -1; /* Make sure this stays undefined. */
2603 #endif /* sony_news */
2605 xlocal = *lcl = 1; /* Network connections are local. */
2606 debug(F101,"ttopen net x","",x);
2608 /* Let netopen() do this */
2609 if (x > -1 && !x25fd)
2610 x = tn_ini(); /* Initialize TELNET protocol */
2611 #endif /* COMMENT */
2614 } else { /* Terminal device */
2615 #endif /* NETCONN */
2619 This code lets you give Kermit an open file descriptor for a serial
2620 communication device, rather than a device name. Kermit assumes that the
2621 line is already open, locked, conditioned with the right parameters, etc.
2623 for (p = ttname; isdigit(*p); p++) ; /* Check for all-digits */
2625 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2626 debug(F111,"ttopen got open fd",ttname,ttyfd);
2627 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2628 if (ttyfd >= 0 && ttyfd < 3) /* If it's stdio... */
2629 xlocal = *lcl = 0; /* we're in remote mode */
2630 else /* otherwise */
2631 xlocal = *lcl = 1; /* local mode. */
2632 netconn = 0; /* Assume it's not a network. */
2633 tvtflg = 0; /* Might need to initialize modes. */
2634 ttmdm = modem; /* Remember modem type. */
2635 fdflag = 0; /* Stdio not redirected. */
2636 ttfdflg = 1; /* Flag we were opened this way. */
2637 debug(F111,"ttopen non-net ttfdflg",ttname,ttfdflg);
2638 debug(F101,"ttopen non-net ttyfd","",ttyfd);
2640 #ifdef sony_news /* Sony NEWS */
2641 /* Get device Kanji mode */
2642 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
2643 perror("ttopen error getting Kanji mode");
2644 debug(F101,"ttopen error getting Kanji mode","",0);
2645 km_ext = -1; /* Make sure this stays undefined. */
2647 #endif /* sony_news */
2649 return(0); /* Return success */
2654 #endif /* NETCONN */
2656 /* Here we have to open a serial device of the given name. */
2658 netconn = 0; /* So it's not a network connection */
2659 occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */
2662 tvtflg = 0; /* Flag for use by ttvt(). */
2663 /* 0 = ttvt not called yet for this device */
2665 fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
2666 debug(F101,"ttopen fdflag","",fdflag);
2668 ttmdm = modem; /* Make this available to other fns */
2669 xlocal = *lcl; /* Make this available to other fns */
2671 /* Code for handling bidirectional tty lines goes here. */
2672 /* Use specified method for turning off logins and suppressing getty. */
2675 /* Should put call to priv_on() here, but that would be very risky! */
2676 acucntrl("disable",ttname); /* acucntrl() program. */
2677 /* and priv_off() here... */
2680 if ((attmodem & DOGETY) == 0) /* offgetty() program. */
2681 attmodem |= offgetty(ttname); /* Remember response. */
2682 #endif /* ATT7300 */
2683 #endif /* ACUCNTRL */
2687 1985-2001: opens device first then gets lock; reason:
2688 Kermit usually has to run setuid or setgid in order to create a lockfile.
2689 If you give a SET LINE command for a device that happens to be your job's
2690 controlling terminal, Kermit doesn't have to create a lockfile, and in fact
2691 should not create one, and would fail if it tried to if it did not have the
2692 required privileges. But you can't find out if two tty device names are
2693 equivalent until you have a file descriptor that you can give to ttyname().
2694 But this can cause a race condition between Kermit and [m]getty. So see
2699 In the following section, we open the tty device for read/write.
2700 If a modem has been specified via "set modem" prior to "set line"
2701 then the O_NDELAY parameter is used in the open, provided this symbol
2702 is defined (e.g. in fcntl.h), so that the program does not hang waiting
2703 for carrier (which in most cases won't be present because a connection
2704 has not been dialed yet). O_NDELAY is removed later on in ttopen(). It
2705 would make more sense to first determine if the line is local before
2706 doing this, but because ttyname() requires a file descriptor, we have
2707 to open it first. See do_open().
2709 Now open the device using the desired treatment of carrier.
2710 If carrier is REQUIRED, then open could hang forever, so an optional
2711 timer is provided. If carrier is not required, the timer should never
2712 go off, and should do no harm...
2714 ttotmo = 0; /* Flag no timeout */
2715 debug(F101,"ttopen timo","",timo);
2716 debug(F101,"ttopen xlocal","",xlocal);
2719 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2720 xx = alarm(timo); /* Timed open() */
2721 debug(F101,"ttopen alarm","",xx);
2727 #endif /* CK_POSIX_SIG */
2729 ttotmo = 1; /* Flag timeout. */
2730 } else ttyfd = do_open(ttname);
2732 debug(F111,"ttopen","modem",modem);
2733 debug(F101,"ttopen ttyfd","",ttyfd);
2734 debug(F101,"ttopen alarm return","",ttotmo);
2737 ttyfd = do_open(ttname);
2739 debug(F111,"ttopen ttyfd",ttname,ttyfd);
2740 if (ttyfd < 0) { /* If couldn't open, fail. */
2741 debug(F101,"ttopen errno","",errno);
2742 if (errno > 0 && !quiet)
2743 perror(ttname); /* Print message */
2746 if (attmodem & DOGETY) /* was getty(1m) running before us? */
2747 ongetty(ttnmsv); /* yes, restart on tty line */
2748 attmodem &= ~DOGETY; /* no phone in use, getty restored */
2751 /* Should put call to priv_on() here, but that would be risky! */
2752 acucntrl("enable",ttname); /* acucntrl() program. */
2753 /* and priv_off() here... */
2754 #endif /* ACUNTRL */
2755 #endif /* ATT7300 */
2757 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
2758 if (errno == EACCES) { /* Device is protected against user */
2759 debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */
2761 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
2766 extern int qnxportlock;
2768 debug(F101,"ttopen qnxopencount","",x);
2769 debug(F101,"ttopen qnxportlock","",qnxportlock);
2770 if (x < 0 && qnxportlock) {
2772 printf("?Can't get port open count\n");
2773 printf("(Try again with SET QNX-PORT-LOCK OFF)\n");
2774 return(-1); /* Indicate device is in use */
2776 if (x > 1) { /* 1 == me */
2779 return(-2); /* Indicate device is in use */
2781 printf("WARNING: \"%s\" looks busy...\n",ttdev);
2787 /* take this opportunity to open the control channel */
2788 if (p9openttyctl(ttname) < 0)
2790 /* Make sure it's a real tty. */
2791 if (!ttfdflg && !isatty(ttyfd) && strcmp(ttname,"/dev/null"))
2794 fprintf(stderr,"%s is not a terminal device\n",ttname);
2795 debug(F111,"ttopen not a tty",ttname,errno);
2799 signal(SIGINT,occt);
2804 /* Apollo C runtime claims that console pads are tty devices, which
2805 * is reasonable, but they aren't any good for packet transfer. */
2806 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
2807 if (st.all != status_$ok) {
2808 fprintf(stderr, "problem getting tty object type: ");
2810 } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
2811 close(ttyfd); ttyfd = -1;
2813 errno = ENOTTY; perror(ttname);
2814 signal(SIGINT,occt);
2819 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2821 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
2823 /* Caller wants us to figure out if line is controlling tty */
2826 if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
2828 debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal);
2829 } else if (strcmp(ttname,cttnam) == 0) {
2831 debug(F111,"ttopen ttname=cttnam",ttname,xlocal);
2832 } else if (cttnam[0]) {
2834 x = ttnmsv; /* ttyname() is broken */
2836 x = ttyname(ttyfd); /* Get real name of ttname. */
2837 #endif /* BEBOX_DR7 */
2840 xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
2843 debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal);
2848 /* Note, the following code was added so that Unix "idle-line" snoopers */
2849 /* would not think Kermit was idle when it was transferring files, and */
2850 /* maybe log people out. */
2851 if (xlocal == 0) { /* Remote mode */
2852 if (fdflag == 0) { /* Standard i/o is not redirected */
2853 debug(F100,"ttopen setting ttyfd = 0","",0);
2855 /* On Lynx OS, fd 0 is open for read only. */
2858 close(ttyfd); /* Use file descriptor 0 */
2860 } else { /* Standard i/o is redirected */
2861 debug(F101,"ttopen stdio redirected","",ttyfd);
2864 #endif /* NOFDZERO */
2866 /* Now check if line is locked -- if so fail, else lock for ourselves */
2867 /* Note: After having done this, don't forget to delete the lock if you */
2868 /* leave ttopen() with an error condition. */
2870 lkf = 0; /* Check lock */
2873 if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
2874 debug(F111,"ttopen ttlock fails",ttname,xx);
2875 /* WARNING - This close() can hang if tty is an empty socket... */
2876 close(ttyfd); /* Close the device. */
2877 ttyfd = -1; /* Erase its file descriptor. */
2879 signal(SIGINT,occt); /* Put old SIGINT back. */
2880 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2881 if (xx == -2) { /* If lockfile says device in use, */
2883 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2884 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2885 if (xpid > -1) { /* If we got a pid */
2887 printf("Locked by process %d\n",xpid); /* tell them. */
2888 sprintf(lockpid,"%d",xpid); /* Record it too */
2889 debug(F110,"ttopen lockpid",lockpid,0);
2890 } else if (*flfnam) {
2891 extern char *DIRCMD;
2894 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2895 p = malloc(x); /* Print a directory listing. */
2897 Note: priv_on() won't help here, because we do not pass privs along to
2898 to inferior processes, in this case ls. So if the real user does not have
2899 directory-listing access to the lockfile directory, this will result in
2900 something like "not found". That's why we try this only as a last resort.
2902 if (p) { /* If we got the space... */
2903 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2904 zsyscmd(p); /* Get listing. */
2905 if (p) { /* free the space */
2912 return(-5); /* Code for device in use */
2913 } else return(-3); /* Access denied */
2916 #else /* OPENFIRST */
2919 27 Oct 2001: New simpler code that gets the lock first and then opens the
2920 device, which eliminates the race condition. The downside is you can no
2921 longer say "set line /dev/ttyp0" or whatever, where /dev/ttyp0 is your login
2922 terminal, without trying to create a lockfile, which fails if C-Kermit lacks
2923 privs, and if it succeeds, it has created a lockfile where it didn't create
2926 xlocal = *lcl; /* Is the device my login terminal? */
2927 debug(F111,"ttopen xlocal","A",xlocal);
2929 if (strcmp(ttname,CTTNAM) && netconn == 0) {
2930 if (zfnqfp(ttname,DEVNAMLEN+1,fullname)) {
2931 if ((int)strlen(fullname) > 0)
2935 debug(F110,"ttopen fnam",fnam,0);
2937 xlocal = (strcmp(fnam,CTTNAM) != 0);
2939 debug(F111,"ttopen xlocal","B",xlocal);
2941 lkf = 0; /* No lock yet */
2942 if (xlocal > 0) { /* If not... */
2944 xx = ttlock(fnam); /* Try to lock it. */
2945 debug(F101,"ttopen ttlock","",xx);
2946 if (xx < 0) { /* Can't lock it. */
2947 debug(F111,"ttopen ttlock fails",fnam,xx);
2948 if (xx == -2) { /* If lockfile says device in use, */
2950 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2951 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2952 if (xpid > -1) { /* If we got a pid */
2954 printf("Locked by process %d\n",xpid); /* tell them. */
2955 ckstrncpy(lockpid,ckitoa(xpid),16);
2956 debug(F110,"ttopen lockpid",lockpid,0);
2958 } else if (flfnam[0] && !nopush) {
2959 extern char *DIRCMD;
2962 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2963 p = malloc(x); /* Print a directory listing. */
2965 Note: priv_on() won't help here, because we do not pass privs along to
2966 to inferior processes, in this case ls. So if the real user does not have
2967 directory-listing access to the lockfile directory, this will result in
2968 something like "not found". That's why we try this only as a last resort.
2970 if (p) { /* If we got the space... */
2971 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2972 zsyscmd(p); /* Get listing. */
2973 if (p) { /* free the space */
2981 return(-5); /* Code for device in use */
2982 } else return(-3); /* Access denied */
2985 /* Have lock -- now it's safe to open the device */
2987 debug(F101,"ttopen lkf","",lkf);
2988 debug(F101,"ttopen timo","",timo);
2990 ttotmo = 0; /* Flag no timeout */
2993 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2994 xx = alarm(timo); /* Timed open() */
2995 debug(F101,"ttopen alarm","",xx);
3001 #endif /* CK_POSIX_SIG */
3003 ttotmo = 1; /* Flag timeout. */
3005 ttyfd = do_open(fnam);
3008 debug(F111,"ttopen timed ttyfd",fnam,ttyfd);
3011 ttyfd = do_open(fnam);
3012 debug(F111,"ttopen untimed ttyfd",fnam,ttyfd);
3014 if (ttyfd < 0) { /* If couldn't open, fail. */
3015 debug(F111,"ttopen errno",fnam,errno);
3016 debug(F111,"ttopen xlocal","C",xlocal);
3018 debug(F100,"ttopen substituting 0","",0);
3021 if (errno > 0 && !quiet) {
3022 debug(F111,"ttopen perror",fnam,errno);
3023 perror(fnam); /* Print message */
3025 if (ttunlck()) /* Release the lock file */
3026 fprintf(stderr,"Warning, problem releasing lock\r\n");
3030 if (ttyfd < 0) { /* ttyfd is still < 0? */
3032 if (attmodem & DOGETY) /* was getty(1m) running before us? */
3033 ongetty(ttnmsv); /* yes, restart on tty line */
3034 attmodem &= ~DOGETY; /* no phone in use, getty restored */
3037 /* Should put call to priv_on() here, but that would be risky! */
3038 acucntrl("enable",fnam); /* acucntrl() program. */
3039 /* and priv_off() here... */
3040 #endif /* ACUNTRL */
3041 #endif /* ATT7300 */
3043 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
3044 if (errno == EACCES) { /* Device is protected against user */
3045 debug(F110,"ttopen EACCESS",fnam,0); /* Return -4 */
3047 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
3050 /* Make sure it's a real tty. */
3053 /* take this opportunity to open the control channel */
3054 if (p9openttyctl(fnam) < 0)
3056 if (!ttfdflg && !isatty(ttyfd) && strcmp(fnam,"/dev/null"))
3059 fprintf(stderr,"%s is not a terminal device\n",fnam);
3060 debug(F111,"ttopen not a tty",fnam,errno);
3061 if (ttunlck()) /* Release the lock file */
3062 fprintf(stderr,"Warning, problem releasing lock\r\n");
3066 signal(SIGINT,occt);
3072 Apollo C runtime claims that console pads are tty devices, which
3073 is reasonable, but they aren't any good for packet transfer.
3075 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
3076 if (st.all != status_$ok) {
3077 fprintf(stderr, "problem getting tty object type: ");
3079 } else if (ttyuid != sio_$uid) { /* Reject non-SIO lines */
3080 close(ttyfd); ttyfd = -1;
3082 errno = ENOTTY; perror(fnam);
3083 signal(SIGINT,occt);
3088 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3090 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
3092 /* Caller wants us to figure out if line is controlling tty */
3096 if (strcmp(fnam,CTTNAM) == 0) { /* "/dev/tty" always remote */
3098 debug(F111,"ttopen fnam=CTTNAM",fnam,xlocal);
3099 } else if (strcmp(fnam,cttnam) == 0) {
3101 debug(F111,"ttopen fnam=cttnam",fnam,xlocal);
3102 } else if (cttnam[0]) {
3104 s = ttnmsv; /* ttyname() is broken */
3106 s = ttyname(ttyfd); /* Get real name of ttname. */
3107 #endif /* BEBOX_DR7 */
3110 xlocal = ((strncmp(s,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
3113 debug(F111,"ttopen ttyname(ttyfd) xlocal",s,xlocal);
3118 /* Note, the following code was added so that Unix "idle-line" snoopers */
3119 /* would not think Kermit was idle when it was transferring files, and */
3120 /* maybe log people out. */
3121 if (xlocal == 0) { /* Remote mode */
3122 if (fdflag == 0) { /* Standard i/o is not redirected */
3123 debug(F100,"ttopen setting ttyfd = 0","",0);
3125 /* On Lynx OS, fd 0 is open for read only. */
3128 close(ttyfd); /* Use file descriptor 0 */
3130 } else { /* Standard i/o is redirected */
3131 debug(F101,"ttopen stdio redirected","",ttyfd);
3134 #endif /* NOFDZERO */
3135 #endif /* OPENFIRST */
3137 /* Got the line, now set the desired value for local. */
3139 if (*lcl != 0) *lcl = xlocal;
3141 /* Some special stuff for v7... */
3145 if (kmem[TTY] < 0) { /* If open, then skip this. */
3146 qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
3147 if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
3148 fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
3149 perror("/dev/kmem");
3156 /* No failure returns after this point */
3159 ioctl(ttyfd, TIOCMODEM, &temp);
3161 if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
3165 #endif /* TIOCSINUSE */
3168 /* Get tty device settings */
3170 #ifdef BSD44ORPOSIX /* POSIX */
3171 tcgetattr(ttyfd,&ttold);
3172 debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
3173 tcgetattr(ttyfd,&ttraw);
3174 debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag);
3175 tcgetattr(ttyfd,&tttvt);
3176 debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag);
3177 #else /* BSD, V7, and all others */
3178 #ifdef ATTSV /* AT&T UNIX */
3179 ioctl(ttyfd,TCGETA,&ttold);
3180 debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
3181 ioctl(ttyfd,TCGETA,&ttraw);
3182 ioctl(ttyfd,TCGETA,&tttvt);
3185 ioctl(ttyfd,TIOCGETP,&ttold);
3186 debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
3187 ioctl(ttyfd,TIOCGDEV,&tdold);
3188 debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
3191 debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
3192 #endif /* BELLV10 */
3194 #ifdef sony_news /* Sony NEWS */
3195 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
3196 perror("ttopen error getting Kanji mode");
3197 debug(F101,"ttopen error getting Kanji mode","",0);
3198 km_ext = -1; /* Make sure this stays undefined. */
3200 #endif /* sony_news */
3203 debug(F100,"ttopen TIOCGETC","",0);
3204 tcharf = 0; /* In remote mode, also get */
3205 if (xlocal == 0) { /* special characters */
3206 if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
3207 debug(F100,"ttopen TIOCGETC failed","",0);
3209 tcharf = 1; /* It worked. */
3210 ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
3211 debug(F100,"ttopen TIOCGETC ok","",0);
3215 debug(F100,"ttopen TIOCGETC not defined","",0);
3216 #endif /* TIOCGETC */
3219 debug(F100,"ttopen TIOCGLTC","",0);
3220 ltcharf = 0; /* In remote mode, also get */
3221 if (xlocal == 0) { /* local special characters */
3222 if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
3223 debug(F100,"ttopen TIOCGLTC failed","",0);
3225 ltcharf = 1; /* It worked. */
3226 ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
3227 debug(F100,"ttopen TIOCGLTC ok","",0);
3231 debug(F100,"ttopen TIOCGLTC not defined","",0);
3232 #endif /* TIOCGLTC */
3235 debug(F100,"ttopen TIOCLGET","",0);
3237 if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
3238 debug(F100,"ttopen TIOCLGET failed","",0);
3241 debug(F100,"ttopen TIOCLGET ok","",0);
3243 #endif /* TIOCLGET */
3246 ioctl(ttyfd,TIOCGETP,&ttraw);
3247 ioctl(ttyfd,TIOCGETP,&tttvt);
3249 gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
3250 gtty(ttyfd,&tttvt); /* And one for virtual tty service */
3251 #endif /* BELLV10 */
3254 #endif /* BSD44ORPOSIX */
3256 /* Section for changing line discipline. It's restored in ttres(). */
3260 { union txname ld_name; int ld_idx = 0;
3263 ld_name.tx_which = ld_idx++;
3264 ioctl(ttyfd, TXGETCD, &ld_name);
3265 if (!strncmp(ld_name.tx_name, "rts", 3))
3267 } while (*ld_name.tx_name);
3268 debug(F101,"AIX line discipline","",ttld);
3274 /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
3276 ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */
3277 debug(F101,"4.1bsd line discipline","",ttld);
3278 k = OTTYDISC; /* Switch to "old" discipline */
3279 k = ioctl(ttyfd, TIOCSETD, &k);
3280 debug(F101,"4.1bsd tiocsetd","",k);
3285 /* This was previously done before the last two TCGETA or gtty above,
3286 * in both the ATTSV and not-ATTSV case. If it is not okay to have only
3287 * one copy if it here instead, give us a shout!
3289 sio_$control((short)ttyfd, sio_$raw_nl, false, st);
3290 if (xlocal) { /* ignore breaks from local line */
3291 sio_$control((short)ttyfd, sio_$int_enable, false, st);
3292 sio_$control((short)ttyfd, sio_$quit_enable, false, st);
3297 ttraw.c_line = 0; /* STTY line 0 for VX/VE */
3298 tttvt.c_line = 0; /* STTY line 0 for VX/VE */
3299 ioctl(ttyfd,TCSETA,&ttraw);
3302 /* If O_NDELAY was used during open(), then remove it now. */
3305 debug(F100,"ttopen O_NDELAY","",0);
3307 if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
3308 debug(F100,"ttopen fcntl O_NDELAY","",0);
3310 if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) {
3311 debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0);
3312 perror("Can't unset O_NDELAY");
3315 /* Some systems, notably Xenix (don't know how common this is in
3316 * other systems), need special treatment to get rid of the O_NDELAY
3317 * behaviour on read() with respect to carrier presence (i.e. read()
3318 * returning 0 when carrier absent), even though the above fcntl()
3319 * is enough to make read() wait for input when carrier is present.
3320 * This magic, in turn, requires CLOCAL for working when the carrier
3321 * is absent. But if xlocal == 0, presumably you already have CLOCAL
3322 * or you have a carrier, otherwise you wouldn't be running this.
3324 debug(F101,"ttopen xlocal","",xlocal);
3327 #ifdef COMMENT /* 12 Aug 1997 */
3330 ttraw.c_cflag |= CLOCAL;
3334 ttraw.c_cflag |= CLOCAL;
3335 #endif /* __FreeBSD__ */
3336 #endif /* __bsdi__ */
3337 #else /* Not COMMENT */
3339 if (xlocal) /* Unset this if it's defined. */
3340 ttraw.c_cflag |= CLOCAL;
3342 #endif /* COMMENT */
3343 debug(F101,"ttopen BSD44ORPOSIX calling tcsetattr","",TCSADRAIN);
3344 if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0) {
3345 debug(F100,"ttopen POSIX tcseattr fails","",0);
3346 perror("tcsetattr");
3348 #else /* !BSD44ORPOSIX */
3350 ttraw.c_cflag |= CLOCAL;
3351 debug(F100,"ttopen calling ioctl(TCSETA)","",0);
3353 if (ioctl(ttyfd, TCSETA, &ttraw) < 0) {
3354 debug(F101,"ttopen ioctl(TCSETA) fails","",errno);
3355 perror("ioctl(TCSETA)");
3358 #endif /* BSD44ORPOSIX */
3360 #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
3361 /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
3362 debug(F100,"ttopen executing close/open","",0);
3363 close( priv_opn(fnam, O_RDWR) ); /* Magic to force change. */
3364 #endif /* NOCOTFMC */
3367 #endif /* O_NDELAY */
3369 /* Instruct the system how to treat the carrier, and set a few other tty
3372 * This also undoes the temporary setting of CLOCAL that may have been done
3373 * for the close(open()) above (except in Xenix). Also throw in ~ECHO, to
3374 * prevent the other end of the line from sitting there talking to itself,
3375 * producing garbage when the user performs a connect.
3377 * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
3378 * Now it thinks CLOCAL is always on. It seems the only real solution for
3379 * Xenix is to switch between the lower and upper case device names.
3381 * This section may at some future time expand into setting a complete
3382 * collection of tty parameters, or call a function shared with ttpkt()/
3383 * ttvt() that does so. On the other hand, the initial parameters are not
3384 * that important, since ttpkt() or ttvt() should always fix that before
3385 * any communication is done. Well, we'll see...
3389 debug(F100,"ttopen calling carrctl","",0);
3390 carrctl(&ttraw, ttcarr == CAR_ON);
3391 debug(F100,"ttopen carrctl ok","",0);
3395 #endif /* COHERENT */
3398 ttraw.c_lflag &= ~ECHO;
3399 ttold.c_lflag &= ~ECHO;
3401 y = tcsetattr(ttyfd, TCSADRAIN, &ttraw);
3402 debug(F101,"ttopen tcsetattr","",y);
3404 y = ioctl(ttyfd, TCSETA, &ttraw);
3405 debug(F100,"ttopen ioctl","",y);
3406 #endif /* BSD44ORPOSIX */
3408 #else /* BSD, etc */
3409 ttraw.sg_flags &= ~ECHO;
3410 ttold.sg_flags &= ~ECHO;
3412 y = ioctl(ttyfd,TIOCSETP,&ttraw);
3413 debug(F100,"ttopen ioctl","",y);
3415 y = stty(ttyfd,&ttraw);
3416 debug(F100,"ttopen stty","",y);
3417 #endif /* BELLV10 */
3418 #endif /* SVORPOSIX */
3422 #endif /* COHERENT */
3424 /* ttflui(); */ /* This fails for some reason. */
3427 /* Get current speed */
3434 debug(F101,"ttopen ttspeed","",ttspeed);
3436 /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
3438 debug(F101,"ttopen ttyfd","",ttyfd);
3439 debug(F101,"ttopen *lcl","",*lcl);
3440 debug(F111,"ttopen lock file",flfnam,lkf);
3441 signal(SIGINT,occt);
3442 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3448 /* D O _ O P E N -- Do the right kind of open() call for the tty. */
3451 do_open(ttname) char *ttname; {
3455 /* O_NONBLOCK on /dev/tty makes open() fail */
3456 return(priv_opn(ttname, O_RDWR |
3458 ((int)strcmp(ttname,"/dev/tty") == 0) ?
3460 (ttcarr != CAR_ON) ? O_NONBLOCK : 0)
3465 #ifndef O_NDELAY /* O_NDELAY not defined */
3466 return(priv_opn(ttname,2));
3467 #else /* O_NDELAY defined */
3471 Open comms line without waiting for carrier so initial call does not hang
3472 because state of "modem" is likely unknown at the initial call -jrd.
3473 If this is needed for the getty stuff to work, and the open would not work
3474 without O_NDELAY when getty is still on, then this special case is ok.
3475 Otherwise, get rid of it. -ske
3477 return(priv_opn(ttname, O_RDWR | O_NDELAY));
3479 #else /* !ATT7300 */
3481 /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
3483 debug(F101,"do_open xlocal","",xlocal);
3484 debug(F111,"do_open flags A",ttname,flags);
3485 if (xlocal && (ttcarr != CAR_ON))
3487 debug(F111,"do_open flags B",ttname,flags);
3488 return(priv_opn(ttname, flags));
3489 #endif /* !ATT7300 */
3490 #endif /* O_NDELAY */
3494 /* T T C L O S -- Close the TTY, releasing any lock. */
3496 static int ttc_state = 0; /* ttclose() state */
3497 static char * ttc_nam[] = { "setup", "hangup", "reset", "close" };
3500 ttclos(foo) int foo; { /* Arg req'd for signal() prototype */
3502 extern int exithangup;
3504 debug(F101,"ttclos ttyfd","",ttyfd);
3505 debug(F101,"ttclos netconn","",netconn);
3506 debug(F101,"ttclos xlocal","",xlocal);
3508 debug(F100,"ttclos NOFDZERO","",0);
3509 #endif /* NOFDZERO */
3513 le_init(); /* No need for any of this */
3514 #endif /* TTLEBUF */
3515 #endif /* COMMENT */
3517 if (ttyfd < 0) /* Wasn't open. */
3520 if (ttfdflg) /* If we inherited ttyfd from */
3521 return(0); /* another process, don't close it. */
3523 tvtflg = 0; /* (some day get rid of this...) */
3529 tn_push(); /* Place any waiting data into input*/
3530 tn_sopt(DO,TELOPT_LOGOUT); /* Send LOGOUT option before close */
3531 TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
3532 tn_reset(); /* The Reset Telnet Option table. */
3535 if (ssl_active_flag) {
3537 BIO_printf(bio_err,"calling SSL_shutdown(ssl)\n");
3538 SSL_shutdown(ssl_con);
3541 ssl_active_flag = 0;
3543 if (tls_active_flag) {
3545 BIO_printf(bio_err,"calling SSL_shutdown(tls)\n");
3546 SSL_shutdown(tls_con);
3549 tls_active_flag = 0;
3555 if (ttpipe) { /* We've been using a pipe */
3560 close(fdin); /* Close these. */
3563 kill(ttpid,1); /* Kill fork with SIGHUP */
3565 wstat = wait(&statusp);
3566 if (wstat == ttpid || wstat == -1)
3568 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
3582 #endif /* NODOPTY */
3593 if (netconn) { /* If it's a network connection. */
3594 debug(F100,"ttclos closing net","",0);
3595 netclos(); /* Let the network module close it. */
3596 netconn = 0; /* No more network connection. */
3597 debug(F101,"ttclos ttyfd after netclos","",ttyfd); /* Should be -1 */
3600 #endif /* NETCONN */
3602 if (xlocal) { /* We're closing a SET LINE device */
3603 #ifdef FT21 /* Fortune 2.1-specific items ... */
3604 ioctl(ttyfd,TIOCHPCL, NULL);
3606 #ifdef ultrix /* Ultrix-specific items ... */
3608 /* Unset the INUSE flag that we set in ttopen() */
3609 ioctl(ttyfd, TIOCSINUSE, NULL);
3610 #endif /* TIOCSINUSE */
3611 ioctl(ttyfd, TIOCNMODEM, &x);
3613 /* What was this? */
3614 ioctl(ttyfd, TIOCNCAR, NULL);
3615 #endif /* COMMENT */
3619 /* This is to prevent us from sticking in tthang() or close(). */
3623 if (ttyfd > 0) { /* But skip it on stdin. */
3624 debug(F100,"ttclos setting O_NDELAY","",0);
3625 x = fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL, 0)|O_NDELAY);
3627 if (deblog && x == -1) {
3628 perror("Warning - Can't set O_NDELAY");
3629 debug(F101,"ttclos fcntl failure to set O_NDELAY","",x);
3634 #endif /* O_NDELAY */
3641 #endif /* NOFDZERO */
3643 saval = signal(SIGALRM,xtimerh); /* Enable timer interrupt. */
3644 xx = alarm(8); /* Allow 8 seconds. */
3645 debug(F101,"ttclos alarm","",xx);
3651 #endif /* CK_POSIX_SIG */
3652 ) { /* Timer went off? */
3655 debug(F111,"ttclos ALARM TRAP errno",ckitoa(ttc_state),errno);
3656 printf("ttclos() timeout: %s\n", ttc_nam[ttc_state]);
3659 /* Hang up the device (drop DTR) */
3662 debug(F111,"ttclos A",ckitoa(x),ttc_state);
3663 if (ttc_state < 1) {
3665 debug(F101,"ttclos exithangup","",exithangup);
3667 alarm(8); /* Re-arm the timer */
3668 debug(F101,"ttclos calling tthang()","",x);
3669 x = tthang(); /* Hang up first, then... */
3670 debug(F101,"ttclos tthang()","",x);
3674 Oct 2006 - Leave DTR on if SET EXIT HANGUP OFF.
3675 Suggested by Soewono Effendi.
3679 ttold.c_cflag &= ~HUPCL; /* Let's see how this travels */
3681 tcsetattr(ttyfd,TCSANOW,&ttold);
3682 #else /* !BSD44ORPOSIX */
3684 ioctl(ttyfd,TCSETAW,&ttold);
3688 #endif /* BSD44ORPOSIX */
3691 #endif /* CK_NOHUPCL */
3693 /* Put back device modes as we found them */
3696 debug(F111,"ttclos B",ckitoa(x),ttc_state);
3697 if (ttc_state < 2) {
3699 /* Don't try to mess with tty modes if tthang failed() */
3700 /* since it probably won't work. */
3702 debug(F101,"ttclos calling ttres()","",x);
3703 signal(SIGALRM,xtimerh); /* Re-enable the alarm. */
3704 alarm(8); /* Re-arm the timer */
3705 x = ttres(); /* Reset device modes. */
3706 debug(F101,"ttclos ttres()","",x);
3710 /* Close the device */
3713 debug(F101,"ttclos C","",ttc_state);
3714 if (ttc_state < 3) {
3717 debug(F101,"ttclos calling close","",x);
3718 signal(SIGALRM,xtimerh); /* Re-enable alarm. */
3719 alarm(8); /* Re-arm the timer */
3720 x = close(ttyfd); /* Close the device. */
3721 debug(F101,"ttclos close()","",x);
3725 debug(F101,"ttclos D","",ttc_state);
3726 ttimoff(); /* Turn off timer. */
3728 printf("?WARNING - close failed: %s\n",ttnmsv);
3731 printf("errno = %d\n", errno);
3732 debug(F101,"ttclos failed","",errno);
3736 /* Unlock after closing but before any getty mumbo jumbo */
3738 debug(F100,"ttclos about to call ttunlck","",0);
3739 if (ttunlck()) /* Release uucp-style lock */
3740 fprintf(stderr,"Warning, problem releasing lock\r\n");
3743 /* For bidirectional lines, restore getty if it was there before. */
3745 #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */
3747 debug(F100,"ttclos ACUCNTRL","",0);
3748 acucntrl("enable",ttnmsv); /* Enable getty on the device. */
3751 #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */
3753 debug(F100,"ttclos ATT7300 ongetty","",0);
3754 if (attmodem & DOGETY) /* Was getty(1m) running before us? */
3755 ongetty(ttnmsv); /* Yes, restart getty on tty line */
3756 attmodem &= ~DOGETY; /* No phone in use, getty restored */
3758 #endif /* ATT7300 */
3759 #endif /* System-dependent getty-restoring methods */
3762 km_ext = -1; /* Invalidate device's Kanji-mode */
3763 #endif /* sony_news */
3765 ttyfd = -1; /* Invalidate the file descriptor. */
3767 debug(F100,"ttclos done","",0);
3771 /* T T H A N G -- Hangup phone line or network connection. */
3774 0 if it does nothing.
3775 1 if it believes that it hung up successfully.
3776 -1 if it believes that the hangup attempt failed.
3779 #define HUPTIME 500 /* Milliseconds for hangup */
3782 /* The following didn't work but TIOCSDTR does work */
3784 /* Define HUP_POSIX to force non-POSIX builds to use the POSIX hangup method */
3785 #ifndef POSIX /* Such as Unixware 1.x, 2.x */
3788 #endif /* HUP_POSIX */
3790 #endif /* UNIXWARE */
3791 #endif /* COMMENT */
3793 #ifndef USE_TIOCSDTR
3795 /* Because the POSIX method (set output speed to 0) doesn't work in NetBSD */
3798 #define USE_TIOCSDTR
3799 #endif /* TIOCCDTR */
3800 #endif /* TIOCSDTR */
3801 #endif /* __NetBSD__ */
3802 #endif /* USE_TIOCSDTR */
3804 #ifndef HUP_CLOSE_POSIX
3806 #define HUP_CLOSE_POSIX
3809 #define HUP_CLOSE_POSIX
3810 #endif /* CK_SCOV5 */
3812 #endif /* HUP_CLOSE_POSIX */
3814 #ifdef NO_HUP_CLOSE_POSIX
3815 #ifdef HUP_CLOSE_POSIX
3816 #undef HUP_CLOSE_POSIX
3817 #endif /* HUP_CLOSE_POSIX */
3818 #endif /* NO_HUP_CLOSE_POSIX */
3825 int x = 0; /* Sometimes used as return code. */
3832 #endif /* COHERENT */
3834 #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */
3835 int spdsav; /* for saving speed */
3841 #endif /* BSD44ORPOSIX */
3842 #endif /* HUP_POSIX */
3845 Early versions of HP-UX omitted the mflag typedef. If you get complaints
3846 about it, just change it to long (or better still, unsigned long).
3849 dtr_down = 00000000000,
3852 char modem_state[64];
3854 int flags; /* fcntl flags */
3855 unsigned short ttc_save;
3856 #endif /* SVORPOSIX */
3858 if (ttyfd < 0) return(0); /* Don't do this if not open */
3859 if (xlocal < 1) return(0); /* Don't do this if not local */
3863 return((ttclos(0) < 0) ? -1 : 1);
3867 return((ttclos(0) < 0) ? -1 : 1);
3870 if (netconn) { /* Network connection. */
3872 if (istncomport()) {
3873 int rc = tnc_set_dtr_state(0);
3876 rc = tnc_set_dtr_state(1);
3878 return(rc >= 0 ? 1 : -1);
3880 #endif /* TN_COMPORT */
3881 return((netclos() < 0) ? -1 : 1); /* Just close it. */
3883 #endif /* NETCONN */
3885 /* From here down, we handle real tty devices. */
3888 e.g. for Unixware 2, where we don't have a full POSIX build, we
3889 still have to use POSIX-style hangup. Thus the duplication of this
3890 and the next case, the only difference being we use a local termios
3891 struct here, since a different model is used elsewhere.
3893 NO LONGER USED as of C-Kermit 8.0 -- it turns out that this method,
3894 even though it compiles and executes without error, doesn't actually
3895 work (i.e. DTR does not drop), whereas the TIOCSDTR method works just fine,
3898 struct termios ttcur;
3900 debug(F100,"tthang HUP_POSIX style","",0);
3901 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3902 debug(F111,"tthang tcgetattr",ckitoa(errno),x);
3903 if (x < 0) return(-1);
3904 spdsav = cfgetospeed(&ttcur); /* Get current speed */
3905 debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
3906 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
3907 debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
3908 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
3909 debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
3910 if (x < 0) return(-1);
3911 x = cfsetispeed(&ttcur,B0);
3912 debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
3913 if (x < 0) return(-1);
3914 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3915 debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
3916 if (x < 0) return(-1);
3917 msleep(HUPTIME); /* Sleep 0.5 sec */
3918 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
3919 if (x < 0) return(-1);
3920 debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
3921 x = cfsetispeed(&ttcur,spdsavi);
3922 debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
3923 if (x < 0) return(-1);
3924 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3925 debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
3926 if (x < 0) return(-1);
3934 x = tcdropline(ttyfd,500);
3935 debug(F101,"tthang QNX tcdropline","",x);
3936 ttcur.c_cflag |= CLOCAL;
3937 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3938 debug(F101,"tthang QNX tcsetattr restore","",x);
3940 debug(F101,"tthang QNX tcsetattr restore errno","",errno);
3943 /* Fix flags - ensure O_NONBLOCK is off */
3946 debug(F101,"tthang QNX iniflags","",iniflags);
3947 if (fcntl(ttyfd, F_SETFL, iniflags) == -1) {
3948 debug(F101,"tthang QNX F_SETFL errno","",errno);
3957 debug(F100,"tthang BSD44ORPOSIX USE_TIOCSDTR","",0);
3959 x = ioctl(ttyfd, TIOCCDTR, NULL);
3960 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCCDTR",ckitoa(errno),x);
3961 if (x < 0) return(-1);
3962 msleep(HUPTIME); /* Sleep 0.5 sec */
3964 x = ioctl(ttyfd, TIOCSDTR, NULL);
3965 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCSDTR",ckitoa(errno),x);
3966 if (x < 0) return(-1);
3967 #else /* USE_TIOCSDTR */
3969 #ifdef HUP_CLOSE_POSIX
3971 In OSR5 versions where TIOCSDTR is not defined (up to and including at
3972 least 5.0.6a) the POSIX APIs in the "#else" part below are available but
3973 don't work, and no other APIs are available that do work. In this case
3974 we have to drop DTR by brute force: close and reopen the port. This
3975 code actually works, but all the steps are crucial: setting CLOCAL, the
3976 O_NDELAY manipulations, etc.
3978 debug(F100,"tthang HUP_CLOSE_POSIX close/open","",0);
3979 debug(F101,"tthang HUP_CLOSE_POSIX O_NONBLOCK","",O_NONBLOCK);
3980 debug(F101,"tthang HUP_CLOSE_POSIX O_NDELAY","",O_NDELAY);
3982 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3983 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr","",x);
3985 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr errno","",errno);
3990 x = close(ttyfd); /* Close without releasing lock */
3992 debug(F101,"tthang HUP_CLOSE_POSIX close errno","",errno);
3996 x = msleep(500); /* Pause half a second */
3997 if (x < 0) { /* Or if that doesn't work, 1 sec */
3998 debug(F101,"tthang HUP_CLOSE_POSIX msleep errno","",errno);
4002 ttyfd = priv_opn(ttnmsv, (O_RDWR|O_NDELAY)); /* Reopen the device */
4003 debug(F111,"tthang HUP_CLOSE_POSIX reopen",ttnmsv,ttyfd);
4005 debug(F101,"tthang HUP_CLOSE_POSIX reopen errno","",errno);
4008 debug(F101,"tthang HUP_CLOSE_POSIX re-ttopen ttyfd","",ttyfd);
4010 /* Restore previous attributes */
4014 ttcur.c_cflag |= CLOCAL;
4015 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4016 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore","",x);
4018 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore errno",
4022 /* Fix flags - ensure O_NDELAY and O_NONBLOCK are off */
4025 if ((x = fcntl(ttyfd, F_GETFL, 0)) == -1) {
4026 debug(F101,"tthang HUP_CLOSE_POSIX F_GETFL errno","",errno);
4029 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4031 x &= ~(O_NONBLOCK|O_NDELAY);
4032 debug(F101,"tthang HUP_CLOSE_POSIX flags to set","",x);
4033 debug(F101,"tthang HUP_CLOSE_POSIX iniflags","",iniflags);
4034 if (fcntl(ttyfd, F_SETFL, x) == -1) {
4035 debug(F101,"tthang HUP_CLOSE_POSIX F_SETFL errno","",errno);
4040 if ((x = fcntl(ttyfd, F_GETFL, 0)) > -1) {
4041 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4042 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NONBLOCK",
4044 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NDELAY",
4050 #else /* HUP_CLOSE_POSIX */
4052 /* General BSD44ORPOSIX case (Linux, BSDI, FreeBSD, etc) */
4054 debug(F100,"tthang BSD44ORPOSIX B0","",0);
4055 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
4056 debug(F111,"tthang BSD44ORPOSIX tcgetattr",ckitoa(errno),x);
4057 if (x < 0) return(-1);
4058 spdsav = cfgetospeed(&ttcur); /* Get current speed */
4059 debug(F111,"tthang BSD44ORPOSIX cfgetospeed",ckitoa(errno),spdsav);
4060 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
4061 debug(F111,"tthang BSD44ORPOSIX cfgetispeed",ckitoa(errno),spdsavi);
4062 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
4063 debug(F111,"tthang BSD44ORPOSIX cfsetospeed",ckitoa(errno),x);
4064 if (x < 0) return(-1);
4065 x = cfsetispeed(&ttcur,B0);
4066 debug(F111,"tthang BSD44ORPOSIX cfsetispeed",ckitoa(errno),x);
4067 if (x < 0) return(-1);
4068 /* This gets EINVAL on NetBSD 1.4.1 because of B0... */
4069 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4070 debug(F111,"tthang BSD44ORPOSIX tcsetattr B0",ckitoa(errno),x);
4071 if (x < 0) return(-1);
4072 msleep(HUPTIME); /* Sleep 0.5 sec */
4073 debug(F101,"tthang BSD44ORPOSIX restore output speed","",spdsav);
4074 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
4075 debug(F111,"tthang BSD44ORPOSIX cfsetospeed prev",ckitoa(errno),x);
4076 if (x < 0) return(-1);
4077 debug(F101,"tthang BSD44ORPOSIX restore input speed","",spdsavi);
4078 x = cfsetispeed(&ttcur,spdsavi);
4079 debug(F111,"tthang BSD44ORPOSIX cfsetispeed prev",ckitoa(errno),x);
4080 if (x < 0) return(-1);
4081 ttcur.c_cflag |= CLOCAL; /* Don't expect CD after hangup */
4082 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4083 debug(F111,"tthang BSD44ORPOSIX tcsetattr restore",ckitoa(errno),x);
4084 if (x < 0) return(-1);
4086 #endif /* HUP_CLOSE_POSIX */
4087 #endif /* USE_TIOCSDTR */
4093 #else /* BSD44ORPOSIX */
4095 #ifdef aegis /* Apollo Aegis */
4096 sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */
4097 msleep(HUPTIME); /* pause */
4098 sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */
4102 #ifdef ANYBSD /* Any BSD version. */
4103 #ifdef TIOCCDTR /* Except those that don't have this */
4104 debug(F100,"tthang BSD style","",0);
4105 if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */
4106 debug(F101,"tthang TIOCCDTR fails","",errno);
4109 msleep(HUPTIME); /* For about 1/2 sec */
4111 x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
4114 For some reason, this tends to fail with "no such device or address"
4115 but the operation still works, probably because of the close/open
4116 later on. So let's not scare the user unnecessarily here.
4118 debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
4119 x = 1; /* Pretend we succeeded */
4120 } else if (x == 0) x = 1; /* Success */
4123 ioctl(ttyfd, TIOCSAVEMODES, 0);
4124 ioctl(ttyfd, TIOCHPCL, 0);
4125 close(ttyfd); /* Yes, must do this twice */
4126 if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */
4127 return(-1); /* (but why?) */
4130 #endif /* COMMENT */
4131 #endif /* TIOCCDTR */
4132 close(do_open(ttnmsv)); /* Clear i/o error condition */
4135 /* This is definitely dangerous. Why was it here? */
4136 z = ttvt(ttspeed,ttflow); /* Restore modes. */
4137 debug(F101,"tthang ttvt returns","",z);
4138 return(z < 0 ? -1 : 1);
4141 #endif /* COMMENT */
4145 /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
4148 /* Hewlett Packard allows explicit manipulation of modem signals. */
4152 debug(F100,"tthang HP-UX style","",0);
4153 if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) /* lower DTR */
4154 return(-1); /* oops, can't. */
4155 msleep(HUPTIME); /* Pause half a second. */
4156 x = 1; /* Set return code */
4157 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4158 if ((modem_rtn & MDCD) != 0) /* Check if CD is low. */
4159 x = -1; /* CD didn't drop, fail. */
4162 /* Even if above calls fail, RTS & DTR should be turned back on. */
4163 modem_rtn = MRTS | MDTR;
4164 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
4167 /* New way, from Hellmuth Michaelis */
4168 debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
4169 if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
4170 debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
4173 sprintf(modem_state,"%#lx",modem_rtn);
4174 debug(F110,"tthang HP-UX: modem lines = ",modem_state,0);
4175 modem_sav = modem_rtn; /* Save current modem signals */
4176 modem_rtn &= ~MDTR; /* Turn DTR bit off */
4177 sprintf(modem_state,"%#lx",modem_rtn);
4178 debug(F110,"tthang HP-UX: DTR down = ",modem_state,0);
4179 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
4180 debug(F100,"tthang HP-UX: can't lower DTR!","",0);
4181 return(-1); /* oops, can't. */
4183 msleep(HUPTIME); /* Pause half a second. */
4184 x = 1; /* Set return code */
4185 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4186 sprintf(modem_state,"%#lx",modem_rtn);
4187 debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
4188 if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */
4189 debug(F100,"tthang HP-UX: DCD not down","",0);
4190 x = -1; /* CD didn't drop, fail. */
4192 debug(F100,"tthang HP-UX: DCD down","",0);
4196 debug(F100,"tthang HP-UX: can't get DCD status !","",0);
4199 /* Even if above calls fail, DTR should be turned back on. */
4202 if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
4204 debug(F100,"tthang HP-UX: can't set saved state","",0);
4206 sprintf(modem_state,"%#lx",modem_sav);
4207 debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
4210 #endif /* COMMENT */
4212 #else /* AT&T but not HP-UX */
4214 /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
4215 /* It is not known how many, if any, systems actually implement them, */
4216 /* so we include them here in ifdef's. */
4219 Unixware has the TIOCMxxx symbols defined, but calling ioctl() with them
4220 gives error 22 (invalid argument).
4224 No modem-signal twiddling for IBM RT PC or RS/6000.
4225 In AIX 3.1 and earlier, the ioctl() call is broken.
4226 This code could be activated for AIX 3.1 with PTF 2006 or later
4227 (e.g. AIX 3.2), but close/open does the job too, so why bother.
4229 #ifdef TIOCMBIS /* Bit Set */
4230 #ifdef TIOCMBIC /* Bit Clear */
4231 #ifdef TIOCM_DTR /* DTR */
4233 /* Clear DTR, sleep 300 msec, turn it back on. */
4234 /* If any of the ioctl's return failure, go on to the next section. */
4236 z = TIOCM_DTR; /* Code for DTR. */
4239 This was the cause of the troubles with the Solaris Port Monitor.
4240 The problem is: RTS never comes back on. Moral: Don't do it!
4241 (But why doesn't it come back on? See the TIOCMBIS call...)
4243 #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */
4245 #endif /* TIOCM_RTS */
4246 #endif /* COMMENT */
4248 debug(F101,"tthang TIOCM signal mask","",z);
4249 if (ioctl(ttyfd,TIOCMBIC,&z) > -1) { /* Try to lower DTR. */
4250 debug(F100,"tthang TIOCMBIC ok","",0);
4251 msleep(HUPTIME); /* Pause half a second. */
4252 if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
4253 debug(F100,"tthang TIOCMBIS ok","",0);
4255 return(1); /* Success, done. */
4257 } else { /* Couldn't raise, continue. */
4258 debug(F101,"tthang TIOCMBIS errno","",errno);
4260 } else { /* Couldn't lower, continue. */
4261 debug(F101,"tthang TIOCMBIC errno","",errno);
4263 #endif /* TIOCM_DTR */
4264 #endif /* TIOCMBIC */
4265 #endif /* TIOCMBIS */
4269 General AT&T UNIX case, not HPUX. The following code is highly suspect. No
4270 two AT&T-based systems seem to do this the same way. The object is simply
4271 to turn off DTR and then turn it back on. SVID says the universal method
4272 for turning off DTR is to set the speed to zero, and this does seem to do
4273 the trick in all cases. But neither SVID nor any known man pages say how to
4274 turn DTR back on again. Some variants, like most Xenix implementations,
4275 raise DTR again when the speed is restored to a nonzero value. Others
4276 require the device to be closed and opened again, but this is risky because
4277 getty could seize the device during the instant it is closed.
4280 /* Return code for ioctl failures... */
4282 x = 1; /* ATT6300 doesn't want to fail... */
4285 #endif /* ATT6300 */
4287 debug(F100,"tthang get settings","",0);
4288 if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
4289 return(x); /* Fail if this doesn't work. */
4290 if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
4292 ttc_save = ttcur.c_cflag; /* Remember current speed. */
4293 spdsav = ttc_save & CBAUD;
4294 debug(F101,"tthang speed","",spdsav);
4297 debug(F100,"tthang turning O_NDELAY on","",0);
4298 fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
4299 #endif /* O_NDELAY */
4301 #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
4302 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4305 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4306 #else /* This way really works but may be dangerous */
4308 ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */
4309 /* (CLOCAL must be OFF) */
4311 #ifdef SCO3R2 /* SCO UNIX 3.2 */
4313 This is complete nonsense, but an SCO user claimed this change made
4314 hanging up work. Comments from other SCO UNIX 3.2 users would be
4317 ttcur.c_cflag = CBAUD|B0;
4319 #ifdef AIXRS /* AIX on RS/6000 */
4321 Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
4322 even though you can do it on the built-in port and the 8- and 16-port
4323 adapters. (Untested on 128-port adapter.)
4325 ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
4326 #else /* None of the above */
4328 Set everything, including the speed, to zero, except for the CLOCAL
4331 ttcur.c_cflag = CLOCAL|HUPCL;
4336 #endif /* ATT7300 */
4339 /* and if none of those work, try one of these... */
4341 ttcur.c_cflag = CLOCAL;
4342 ttcur.c_cflag &= ~(CBAUD|HUPCL);
4343 ttcur.c_cflag &= ~(CBAUD|CREAD);
4344 ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
4345 /* or other combinations */
4346 #endif /* COMMENT */
4349 debug(F100,"tthang TCXONC","",0);
4350 if (ioctl(ttyfd, TCXONC, 1) < 0) {
4351 debug(F101,"tthang TCXONC failed","",errno);
4356 debug(F100,"tthang TIOCSTART","",0);
4357 if (ioctl(ttyfd, TIOCSTART, 0) < 0) {
4358 debug(F101,"tthang TIOCSTART failed","",errno);
4360 #endif /* TIOCSTART */
4362 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
4363 debug(F101,"tthang TCSETAF failed","",errno);
4364 fcntl(ttyfd, F_SETFL, flags); /* Restore flags */
4365 return(-1); /* before returning. */
4367 msleep(300); /* Give modem time to notice. */
4371 /* Now, even though it doesn't say this in SVID or any man page, we have */
4372 /* to close and reopen the device. This is not necessary for all systems, */
4373 /* but it's impossible to predict which ones need it and which ones don't. */
4377 Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
4378 related ioctl's for their internal modems. attmodem has getty status and
4379 modem-in-use bit. Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
4380 but also ruins the file descriptor, and no other phone(7) ioctl call can fix
4381 it. Whatever it does, it seems to escape detection with PIOCGETA and TCGETA.
4382 The only way to undo the damage is to close the fd and then reopen it.
4384 if (attmodem & ISMODEM) {
4385 debug(F100,"tthang attmodem close/open","",0);
4386 ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
4387 ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */
4388 close(ttyfd); /* Close and reopen the fd. */
4389 ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
4390 attmodem &= ~ISMODEM; /* Phone no longer in use. */
4392 #else /* !ATT7300 */
4393 /* It seems we have to close and open the device for other AT&T systems */
4394 /* too, and this is the place to do it. The following code does the */
4395 /* famous close(open(...)) magic by default. If that doesn't work for you, */
4396 /* then try uncommenting the following statement or putting -DCLSOPN in */
4397 /* the makefile CFLAGS. */
4399 /* #define CLSOPN */
4401 #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
4404 #define OPENFLGS O_RDWR | O_NDELAY
4406 #define OPENFLGS O_RDWR
4410 /* This method is used by default, i.e. unless CLSOPN is defined. */
4411 /* It is thought to be safer because there is no window where getty */
4412 /* can seize control of the device. The drawback is that it might not work. */
4414 debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
4415 close(priv_opn(ttnmsv, OPENFLGS));
4418 /* This method is used if you #define CLSOPN. It is more likely to work */
4419 /* than the previous method, but it's also more dangerous. */
4421 debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
4424 ttyfd = priv_opn(ttnmsv, OPENFLGS); /* Open it again */
4429 #endif /* ATT7300 */
4431 #endif /* NOCOTFMC */
4433 /* Now put all flags & modes back the way we found them. */
4434 /* (Does the order of ioctl & fcntl matter ? ) */
4436 debug(F100,"tthang restore settings","",0);
4437 ttcur.c_cflag = ttc_save; /* Get old speed back. */
4438 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
4442 This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
4443 After closing a modem line, the modem will probably not be asserting
4444 carrier any more, so we should not require carrier any more. If this
4445 causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
4448 flags &= ~O_NDELAY; /* Don't require carrier on reopen */
4449 #endif /* O_NDELAY */
4450 if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */
4454 #endif /* not HPUX */
4456 #endif /* BSD44ORPOSIX */
4457 #endif /* HUP_POSIX */
4458 #endif /* NOLOCAL */
4462 Major change in 5A(174). We used to use LPASS8, if it was defined, to
4463 allow 8-bit data and Xon/Xoff flow control at the same time. But this
4464 LPASS8 business seems to have been causing trouble for everybody but me!
4465 For example, Annex terminal servers, commonly used with Encore computers,
4466 do not support LPASS8 even though the Encore itself does. Ditto for many
4467 other terminal servers, TELNET connections, rlogin connections, etc etc.
4468 Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
4469 serial lines, even though LPASS8 is a feature of 4.3BSD. So let's turn it
4470 off for everybody. That means we goes back to using raw mode, with no
4471 flow control. Phooey.
4473 NOTE: This must be done before the first reference to LPASS8 in this file,
4474 and after the last #include statment.
4480 /* T T R E S -- Restore terminal to "normal" mode. */
4482 /* ske@pkmab.se: There are two choices for what this function should do.
4483 * (1) Restore the tty to current "normal" mode, with carrier treatment
4484 * according to ttcarr, to be used after every kermit command. (2) Restore
4485 * the tty to the state it was in before kermit opened it. These choices
4486 * conflict, since ttold can't hold both choices of tty parameters. ttres()
4487 * is currently being called as in choice (1), but ttold basically holds
4488 * the initial parameters, as in (2), and the description at the beginning
4489 * of this file says (2).
4491 * I don't think restoring tty parameters after all kermit commands makes
4492 * much of a difference. Restoring them upon exit from kermit may be of
4493 * some use in some cases (when the line is not restored automatically on
4494 * close, by the operating system).
4496 * I can't choose which one it should be, so I haven't changed it. It
4497 * probably works as it is, too. It would probably even work even with
4498 * ttres() entirely deleted...
4500 * (from fdc: Actually, this function operates in remote mode too, so
4501 * it restores the console (command) terminal to whatever mode it was
4502 * in before packet operations began, so that commands work right again.)
4505 ttres() { /* Restore the tty to normal. */
4508 if (ttyfd < 0) return(-1); /* Not open. */
4510 if (ttfdflg) return(0); /* Don't mess with terminal modes if */
4511 /* we got ttyfd from another process */
4513 if (netconn) { /* Network connection */
4518 extern int tcp_nodelay; /* Just put this back if necessary */
4519 if (ttnet == NET_TCPB) {
4520 if (nodelay_sav > -1) {
4521 no_delay(ttyfd,nodelay_sav);
4526 #endif /* TCP_NODELAY */
4528 if (istncomport()) {
4530 if ((rc = tnsetflow(ttflow)) < 0)
4533 ttspeed = tnc_get_baud();
4534 else if ((rc = tnc_set_baud(ttspeed)) < 0)
4536 tnc_set_datasize(8);
4537 tnc_set_stopsize(stopbits);
4542 case 'e': /* Even */
4543 debug(F100,"ttres 8 bits + even parity","",0);
4547 debug(F100,"ttres 8 bits + odd parity","",0);
4550 case 'm': /* Mark */
4551 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
4554 case 's': /* Space */
4555 debug(F100,"ttres 8 bits + invalid parity: space","",0);
4560 #endif /* HWPARITY */
4562 tnc_set_parity(1); /* None */
4567 #endif /* TN_COMPORT */
4568 #endif /* TCPSOCKET */
4571 #endif /* NETCONN */
4573 if (ttpipe) return(0);
4576 if (ttpty) return(0);
4579 /* Real terminal device, so restore its original modes */
4581 #ifdef BSD44ORPOSIX /* For POSIX like this */
4582 debug(F100,"ttres BSD44ORPOSIX","",0);
4583 x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
4584 #else /* For all others... */
4585 #ifdef ATTSV /* For AT&T versions... */
4586 debug(F100,"ttres ATTSV","",0);
4587 x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */
4589 /* Here we restore the modes for BSD */
4591 #ifdef LPASS8 /* Undo "pass8" if it were done */
4593 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4594 debug(F100,"ttres TIOCLSET failed","",0);
4596 debug(F100,"ttres TIOCLSET ok","",0);
4600 #ifdef CK_DTRCTS /* Undo hardware flow if it were done */
4602 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4603 debug(F100,"ttres TIOCLSET failed","",0);
4605 debug(F100,"ttres TIOCLSET ok","",0);
4607 #endif /* CK_DTRCTS */
4609 #ifdef TIOCGETC /* Put back special characters */
4610 if (tcharf && (xlocal == 0)) {
4611 if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
4612 debug(F100,"ttres TIOCSETC failed","",0);
4614 debug(F100,"ttres TIOCSETC ok","",0);
4616 #endif /* TIOCGETC */
4618 #ifdef TIOCGLTC /* Put back local special characters */
4619 if (ltcharf && (xlocal == 0)) {
4620 if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
4621 debug(F100,"ttres TIOCSLTC failed","",0);
4623 debug(F100,"ttres TIOCSLTC ok","",0);
4625 #endif /* TIOCGLTC */
4628 debug(F100,"ttres BELLV10","",0);
4629 x = ioctl(ttyfd,TIOCSETP,&ttold); /* Restore both structs */
4630 x = ioctl(ttyfd,TIOCSDEV,&tdold);
4632 debug(F100,"ttres stty","",0);
4633 x = stty(ttyfd,&ttold); /* Restore tty modes the old way. */
4634 #endif /* BELLV10 */
4637 msleep(100); /* This replaces sleep(1)... */
4638 /* Put back sleep(1) if tty is */
4639 /* messed up after close. */
4641 #endif /* BSD44ORPOSIX */
4643 debug(F101,"ttres result","",x);
4645 if (x < 0) debug(F101,"ttres errno","",errno);
4650 x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
4651 debug(F101,"ttres AIX line discipline rts restore","",x);
4656 if (ttld > -1) { /* Put back line discipline */
4657 x = ioctl(ttyfd, TIOCSETD, &ttld);
4658 debug(F101,"ttres BSD41 line discipline restore","",x);
4659 if (x < 0) debug(F101,"...ioctl errno","",errno);
4665 x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */
4666 if (x != -1) { /* Make sure we know original modes. */
4667 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
4668 perror("ttres can't set Kanji mode");
4669 debug(F101,"ttres error setting Kanji mode","",x);
4673 debug(F100,"ttres set Kanji mode ok","",0);
4674 #endif /* sony_news */
4676 tvtflg = 0; /* Invalidate terminal mode settings */
4677 debug(F101,"ttres return code","",x);
4683 /* T T C H K P I D -- Check lockfile pid */
4685 Read pid from lockfile named f, check that it's still valid.
4687 On failure to read pid, return 1.
4688 Otherwise, try to delete lockfile f and return 0 if successful, else 1.
4691 ttchkpid(f) char *f; {
4693 pid = ttrpid(f); /* Read pid from file. */
4694 if (pid > -1) { /* If we were able to read the pid.. */
4695 debug(F101,"ttchkpid lock pid","",pid);
4696 errno = 0; /* See if process still exists. */
4697 mypid = (int)getpid(); /* Get my own pid. */
4698 debug(F101,"ttchkpid my pid","",mypid);
4699 if (pid == mypid) { /* It's me! */
4700 x = -1; /* So I can delete it */
4701 errno = ESRCH; /* pretend it's invalid */
4702 } else { /* It's not me */
4703 x = kill((PID_T)pid, 0); /* See if it's a live process */
4704 debug(F101,"ttchkpid kill errno","",errno);
4706 debug(F101,"ttchkpid pid test","",x);
4707 if (x < 0 && errno == ESRCH) { /* pid is invalid */
4708 debug(F111,"removing stale lock",f,pid);
4710 printf("Removing stale lock %s (pid %d terminated)\n", f, pid);
4712 x = unlink(f); /* Remove the lockfile. */
4714 debug(F111,"ttchkpid unlink",f,x);
4716 return(0); /* Device is not locked after all */
4722 return(1); /* Failure to read pid */
4727 /* Aliases (different drivers) for HP-UX dialout devices: */
4729 static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "cuad", "culd", "" };
4730 static int ttydexists = 0;
4734 /* T T R P I D -- Read pid from lockfile "name" */
4737 ttrpid(name) char *name; {
4743 debug(F110,"ttrpid",name,0);
4744 if (!name) return(-1);
4745 if (!*name) return(-1);
4747 len = zchki(name); /* Get file length */
4749 debug(F101,"ttrpid zchki","",len);
4755 fd = open(name,O_RDONLY); /* Try to open lockfile. */
4757 debug(F101,"ttrpid fd","",fd);
4761 Here we try to be flexible and allow for all different binary and string
4762 formats at runtime, rather than a specific format for each configuration
4763 hardwired at compile time.
4768 COHERENT uses a string PID but without leading spaces or 0's, so there is
4769 no way to tell from the file's length whether it contains a string or binary
4770 pid. So for COHERENT only, we only allow string pids. For all others, we
4771 decide based on the size of the lockfile.
4773 if (len > 4) { /* If file > 4 bytes it's a string */
4774 #endif /* COHERENT */
4775 x = read(fd,buf,(int)len);
4776 debug(F111,"ttrpid string read",buf,x);
4781 x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */
4784 } else if (len == 4) { /* 4 bytes so binary */
4785 x = read(fd, (char *)&pid, 4); /* Read the bytes into an int */
4786 debug(F101,"ttrpid integer read","",x);
4789 } else if (len == 2) { /* 2 bytes binary */
4790 x = read(fd, (char *)&spid, 2); /* Read the bytes into a short */
4791 debug(F101,"ttrpid short read","",x);
4798 #endif /* COHERENT */
4799 close(fd); /* Close the lockfile */
4800 debug(F101,"ttrpid pid","",pid);
4808 This function attempts to coordinate use of the communication device with
4809 other copies of Kermit and any other program that follows the UUCP
4810 device-locking conventions, which, unfortunately, vary among different UNIX
4811 implementations. The idea is to look for a file of a certain name, the
4812 "lockfile", in a certain directory. If such a file is found, then the line
4813 is presumed to be in use, and Kermit should not use it. If no such file is
4814 found, Kermit attempts to create one so that other programs will not use the
4815 same line at the same time. Because the lockfile and/or the directory it's
4816 in might lack write permission for the person running Kermit, Kermit could
4817 find itself running setuid to uucp or other user that does have the
4818 necessary permissions. At startup, Kermit has changed its effective uid to
4819 the user's real uid, and so ttlock() must switch back to the original
4820 effective uid in order to create the lockfile, and then back again to the
4821 real uid to prevent unauthorized access to other directories or files owned
4822 by the user the program is setuid to.
4824 Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
4825 based on suggestions from Warren Tucker. Call with pointer to name of
4826 tty device. Returns:
4831 Note: Once privileges are turned on using priv_on(), it is essential that
4832 they are turned off again before this function returns.
4834 #ifdef SVR4 /* Lockfile uses device numbers. */
4836 Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
4837 it is the behavior of the "reference version" of SVR4, i.e. the Intel
4838 port from UNIX Systems Laboratories, then called Univel UnixWare,
4839 then called Novell UnixWare, then called SCO Unixware, then called Caldera
4840 Open UNIX... It also makes much more sense than device-name-based lockfiles
4841 since there can be multiple names for the same device, symlinks, etc.
4844 #ifndef LFDEVNO /* Define this for SVR4 */
4845 #ifndef AIXRS /* But not for RS/6000 AIX 3.2, etc. */
4846 #ifndef BSD44 /* If anybody else needs it... */
4850 #ifndef IRIX51 /* SGI IRIX 5.1 or later */
4851 #ifndef CK_SCOV5 /* SCO Open Server 5.0 */
4853 #endif /* CK_SCOV5 */
4856 #endif /* __FreeBSD__ */
4857 #endif /* __386BSD__ */
4860 #endif /* LFDEVNO */ /* ... define it here or on CC */
4861 #endif /* NOLFDEVNO */
4862 #endif /* SVR4 */ /* command line. */
4866 #endif /* COHERENT */
4869 For platforms where the lockfile name is made from device/major/minor
4870 device number, as in SVR4. Which, if we must have lockfiles at all, is
4871 by far the best format, since it eliminates all the confusion that stems
4872 from multiple names (or drivers) for the same port, not to mention
4873 symlinks. It might even be a good idea to start using this form even
4874 on platforms where it's not supported, alongside the normal forms for those
4875 platforms, in order to get people used to it...
4878 #ifndef major /* If we didn't find it */
4879 #ifdef SVR4 /* then for Sys V R4 */
4880 #include <sys/mkdev.h> /* look here */
4881 #else /* or for SunOS versions */
4882 #ifdef SUNOS4 /* ... */
4883 #include <sys/sysmacros.h> /* look here */
4884 #else /* Otherwise take a chance: */
4885 #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
4886 #define minor(dev) ( (int) ( (dev) & 0xff))
4890 #endif /* LFDEVNO */
4892 /* No advisory locks if F_TLOCK and F_ULOCK are not defined at this point */
4899 #endif /* NOLOCKF */
4900 #endif /* F_TLOCK */
4908 #endif /* NOLOCKF */
4909 #endif /* F_ULOCK */
4912 static char linkto[DEVNAMLEN+1];
4913 static char * linkdev = NULL;
4918 char * uucplockdir = LOCK_DIR;
4920 char * uucplockdir = "";
4921 #endif /* LOCK_DIR */
4924 char * uucplockdir = LOCK_DIR;
4926 char * uucplockdir = "";
4927 #endif /* LOCK_DIR */
4928 #endif /* USETTYLOCK */
4930 char * uucplockdir = "";
4933 #ifdef QNX /* Only for QNX4 */
4934 int /* Visible to outside world */
4935 qnxopencount() { /* Get QNX device open count */
4936 struct _dev_info_entry info;
4939 x = -1; /* Unknown */
4941 if (!dev_info(ttyfd, &info)) {
4942 debug(F101,"ttlock QNX open_count","",info.open_count);
4943 x = info.open_count;
4951 ttglckdir() { /* Get Lockfile directory name */
4953 return("/var/spool/lock");
4954 #else /* __OpenBSD__ */
4956 return("/var/spool/lock");
4957 #else /* __FreeBSD__ */
4959 char * s = LOCK_DIR;
4960 #endif /* LOCK_DIR */
4966 #else /* LOCK_DIR */
4968 #endif /* LOCK_DIR */
4970 #endif /* __FreeBSD__ */
4971 #endif /* __OpenBSD__ */
4975 ttlock(ttdev) char *ttdev; {
4981 #endif /* __FreeBSD__ */
4984 debug(F100,"ttlock NOUUCP","",0);
4985 ckstrncpy(flfnam,"NOLOCK",FLFNAML);
4991 haslock = 0; /* Not locked yet. */
4992 *flfnam = '\0'; /* Lockfile name is empty. */
4994 if ((devname = xxlast(ttdev,'/')) != NULL)
4996 ckstrncat(lockname,devname+1,DEVNAMLEN-ckstrncpy(lockname,"pts",4));
4998 ckstrncpy(lockname,devname+1,DEVNAMLEN);
4999 #endif /* FREEBSD8 */
5001 if (!strncmp(ttdev,"/dev/",5) && ttdev[5])
5002 ckstrncpy(lockname,ttdev+5,DEVNAMLEN);
5003 #endif /* __FreeBSD__ */
5005 ckstrncpy(lockname,ttdev,DEVNAMLEN);
5007 This might be overkill, but it's not clear from the man pages whether
5008 ttylock() can be called without calling ttylocked() first, since the doc
5009 says that ttylocked() removes any stale lockfiles, but it does not say this
5010 about ttylock(). Also the docs don't say what ttylocked() returns in the
5011 case when it finds and removes a stale lockfile. So one or both calls to
5012 to ttylocked() might be superfluous, but they should do no harm. Also I'm
5013 assuming that we have to do all the same ID swapping, etc, with these
5014 routines as we do without them. Thus the priv_on/off() sandwich.
5017 priv_on(); /* Turn on privs */
5018 x = uu_lock(lockname); /* Try to set the lock */
5019 priv_off(); /* Turn privs off */
5020 debug(F111,"ttlock uu_lock",lockname,x);
5026 ckmakmsg(flfnam,FLFNAML,"/var/spool/lock/LCK..",lockname,NULL,NULL);
5033 #else /* USE_UU_LOCK */
5034 priv_on(); /* Turn on privs */
5035 if (ttylocked(lockname)) { /* This should remove any stale lock */
5036 if (ttylocked(lockname)) { /* so check again. */
5038 return(-5); /* Still locked, fail. */
5041 x = ttylock(lockname); /* Lock it. */
5042 priv_off(); /* Turn off privs */
5044 debug(F111,"ttlock lockname",lockname,x);
5047 We don't really know the name of the lockfile, but
5048 this is what the man page says it is. In USETTYLOCK
5049 builds, it is used only for display by SHOW COMM.
5051 ckmakmsg(flfnam,FLFNAML,"/etc/locks/LCK..",lockname,NULL,NULL);
5055 #endif /* USE_UU_LOCK */
5056 #else /* Systems that don't have ttylock()... */
5060 int lockfd; /* File descriptor for lock file. */
5061 PID_T pid; /* Process id of this process. */
5062 int tries; /* How many times we've tried... */
5063 struct stat devbuf; /* For device numbers (SVR4). */
5066 char pid_str[32]; /* My pid in string format. */
5067 #endif /* PIDSTRING */
5069 char *device, *devname;
5071 #define LFNAML 256 /* Max length for lock file name. */
5072 char lockfil[LFNAML]; /* Lock file name */
5074 char lklockf[LFNAML]; /* Name for link to lock file */
5077 char symlock[LFNAML]; /* Name for symlink lockfile name */
5078 #endif /* CKSYMLINK */
5079 char tmpnam[LFNAML+30]; /* Temporary lockfile name. */
5080 char *lockdir = LOCK_DIR; /* Defined near top of this file, */
5081 /* or on cc command line. */
5082 haslock = 0; /* Not locked yet. */
5083 *flfnam = '\0'; /* Lockfile name is empty. */
5084 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5085 pid = getpid(); /* Get id of this process. */
5087 /* Construct name of lockfile and temporary file */
5089 /* device = name of tty device without the path, e.g. "ttyh8" */
5090 /* lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
5092 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5094 if (stat(ttdev,&devbuf) < 0)
5098 islink = 1; /* Assume it's a symlink */
5099 linkto[0] = '\0'; /* But we don't know to what */
5102 This is undependable. If it worked it would save the readlink call if
5103 we knew the device name was not a link.
5106 islink = S_ISLNK(devbuf.st_mode);
5107 debug(F101,"ttlock stat S_ISLNK","",islink);
5108 #endif /* S_ISLNK */
5109 #endif /* COMMENT */
5111 n = readlink(ttdev,linkto,DEVNAMLEN); /* See if it's a link */
5112 debug(F111,"ttlock readlink",ttdev,n);
5113 if (n > -1) /* It is */
5117 debug(F111,"ttlock link",linkto,islink);
5120 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5121 debug(F110,"ttlock linkdev",linkdev,0);
5123 #endif /* CKSYMLINK */
5126 On SCO platforms, if we don't have a symlink, then let's pretend the
5127 name given for the device is a symlink, because later we will change
5128 the name if it contains any uppercase characters.
5130 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5133 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5134 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5135 debug(F110,"ttlock linkdev",linkdev,0);
5138 #ifdef M_XENIX /* SCO Xenix or UNIX */
5141 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5142 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5143 debug(F110,"ttlock linkdev",linkdev,0);
5145 #endif /* M_XENIX */
5146 #endif /* CK_SCOV5 */
5148 #ifdef ISIII /* Interactive System III, PC/IX */
5149 ckstrncpy(lockfil, device, DEVNAMLEN);
5150 #else /* not ISIII */
5151 #ifdef LFDEVNO /* Lockfilename has device numbers. */
5153 sprintf(lockfil,"LCK..%d.%d", /* SAFE */
5154 major(devbuf.st_rdev), /* major device number */
5155 0x1f & minor(devbuf.st_rdev)); /* minor device number */
5157 /* Note: %d changed to %u in 8.0 -- %u is part of SVID for SVR4 */
5158 /* Lockfile name format verified to agree with Solaris cu, Dec 2001 */
5159 sprintf(lockfil,"LK.%03u.%03u.%03u", /* SAFE */
5160 major(devbuf.st_dev), /* device */
5161 major(devbuf.st_rdev), /* major device number */
5162 minor(devbuf.st_rdev)); /* minor device number */
5163 #endif /* COHERENT */
5164 #else /* Not LFDEVNO */
5165 #ifdef PTX /* Dynix PTX */
5166 if ((device != &ttdev[5]) && (strncmp(ttdev,"/dev/",5) == 0)) {
5167 if ((int)strlen(device) + 8 < LFNAML)
5168 sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
5170 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5173 if ((int)strlen(device) + 5 < LFNAML)
5174 sprintf(lockfil,"LCK..%s", device);
5176 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5178 ckstrncpy(lklockf,device,DEVNAMLEN);
5183 ckmakmsg(symlock,LFNAML, "LCK..", linkdev, NULL, NULL);
5184 #endif /* CKSYMLINK */
5185 #endif /* LFDEVNO */
5188 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5190 /* Lowercase the entire filename. */
5191 /* SCO says we must do this in V5.0 and later. */
5192 /* BUT... watch out for devices -- like Digiboard Portserver */
5193 /* That can have hundreds of ports... */
5194 char *p = (char *)(lockfil + 5);
5195 while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
5198 if (islink) { /* If no change */
5199 if (!strcmp(lockfil,symlock)) { /* then no second lockfile needed */
5204 #endif /* CKSYMLINK */
5206 #ifdef M_XENIX /* SCO Xenix or UNIX */
5209 x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */
5210 if (x > 0) { /* If it's uppercase, lower it. */
5212 if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
5217 if (!strcmp(lockfil,symlock)) { /* No change */
5218 islink = 0; /* so no second lockfile */
5222 #endif /* CKSYMLINK */
5223 #endif /* M_XENIX */
5224 #endif /* CK_SCOV5 */
5226 /* flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
5227 /* tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
5229 ckmakmsg(flfnam,LFNAML,lockdir,"/",lockfil,NULL);
5232 ckmakmsg(lkflfn,FLFNAML,lockdir,"/",lklockf,NULL);
5237 /* If it's a link then also make a lockfile for the real name */
5238 debug(F111,"ttlock link symlock",symlock,islink);
5239 if (islink && symlock[0]) {
5240 /* But only if the lockfile names would be different. */
5241 /* WARNING: They won't be, e.g. for /dev/ttyd2 => /hw/ttys/ttyd2 */
5242 ckmakmsg(lock2,FLFNAML,lockdir,"/",symlock,NULL);
5243 debug(F110,"ttlock lock2",lock2,0);
5244 if (!strcmp(lock2,flfnam)) { /* Are lockfile names the same? */
5245 debug(F100,"ttlock lock2 cleared","",0);
5246 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5249 #endif /* CKSYMLINK */
5250 #endif /* LFDEVNO */
5252 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* safe */
5253 debug(F110,"ttlock flfnam",flfnam,0);
5254 debug(F110,"ttlock tmpnam",tmpnam,0);
5256 priv_on(); /* Turn on privileges if possible. */
5257 lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */
5258 if (lockfd < 0) { /* Create failed. */
5259 debug(F111,"ttlock creat failed",tmpnam,errno);
5260 if (errno == ENOENT) {
5262 printf("UUCP not installed or Kermit misconfigured\n");
5266 unlink(tmpnam); /* Get rid of the temporary file. */
5268 priv_off(); /* Turn off privileges!!! */
5269 return(-1); /* Return failure code. */
5271 /* Now write the pid into the temp lockfile in the appropriate format */
5273 #ifdef PIDSTRING /* For Honey DanBer UUCP, */
5274 sprintf( /* write PID as decimal string */
5276 #ifdef LINUXFSSTND /* The "Linux File System Standard" */
5277 #ifdef FSSTND10 /* Version 1.0 calls for */
5278 "%010d\n", /* leading zeros */
5279 #else /* while version 1.2 calls for */
5280 "%10d\n", /* leading spaces */
5281 #endif /* FSSTND10 */
5284 "%d\n", /* with leading nothing */
5286 "%10d\n", /* with leading blanks */
5287 #endif /* COHERENT */
5288 #endif /* LINUXFSSTND */
5291 write(lockfd, pid_str, 11);
5292 debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
5294 #else /* Not PIDSTRING, use integer PID */
5296 write(lockfd, (char *)&pid, sizeof(pid) );
5297 debug(F101,"ttlock pid","",(int) pid);
5299 #endif /* PIDSTRING */
5301 /* Now try to rename the temp file to the real lock file name. */
5302 /* This will fail if a lock file of that name already exists. */
5304 close(lockfd); /* Close the temp lockfile. */
5305 chmod(tmpnam,0444); /* Permission for a valid lock. */
5307 while (!haslock && tries++ < 2) {
5308 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5309 if (haslock) { /* If we got the lockfile */
5311 link(flfnam,lkflfn);
5315 if (islink && lock2[0])
5317 #endif /* LFDEVNO */
5318 #endif /* CKSYMLINK */
5321 /* Can't do this any more because device is not open yet so no ttyfd. */
5324 Advisory file locking works on SVR4, so we use it. In fact, it is
5325 necessary in some cases, e.g. when SLIP is involved. But it still doesn't
5326 seem to prevent multiple users accessing the same device by different names.
5328 while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
5329 debug(F111, "ttlock lockf returns errno", "", errno);
5330 if ((++tries >= 3) || (errno != EAGAIN)) {
5331 x = unlink(flfnam); /* remove the lockfile */
5333 unlink(lkflfn); /* And any links to it... */
5337 if (islink && lock2[0])
5338 unlink(lock2); /* ditto... */
5339 #endif /* LFDEVNO */
5340 #endif /* CKSYMLINK */
5341 debug(F111,"ttlock unlink",flfnam,x);
5347 if (haslock) /* If we got an advisory lock */
5349 #endif /* COMMENT */
5350 break; /* We're done. */
5352 } else { /* We didn't create a new lockfile. */
5354 if (ttchkpid(flfnam)) { /* Check existing lockfile */
5355 priv_on(); /* cause ttchkpid turns priv_off... */
5356 unlink(tmpnam); /* Delete the tempfile */
5357 debug(F100,"ttlock found tty locked","",0);
5358 priv_off(); /* Turn off privs */
5359 return(-2); /* Code for device is in use. */
5364 unlink(tmpnam); /* Unlink (remove) the temp file. */
5365 priv_off(); /* Turn off privs */
5366 return(haslock ? 0 : -1); /* Return link's return code. */
5371 HP-UX gets its own copy of this routine, modeled after the observed behavior
5372 of the HP-UX 'cu' program. HP-UX serial device names consist of a base name
5373 such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
5374 designator which is a string of digits, possibly containing an imbedded
5375 letter "p". Examples (for base name "tty"):
5377 /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
5379 According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
5380 used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
5381 on other models. In HP-UX 10.00, "0p0" notation was adopted for all models.
5382 However, we make and enforce no such distinctions; either notation is
5383 accepted on any model or HP-UX version as a valid unit designator.
5385 If a valid unit is specified (as opposed to a designer name or symlink), we
5386 check for all aliases of the given unit according to the devprefix[] array.
5387 If no lockfiles are found for the given unit, we can have the device; we
5388 create a lockfile LCK..name in the lockfile directory appropriate for the
5389 HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
5390 9.xx and earlier). If it is a "cua" or "cul" device, a second lockfile is
5391 created with the "ttyd" prefix. This is exactly what cu does.
5393 If the "set line" device does not have a valid unit designator, then it is
5394 used literally and no synomyms are searched for and only one lockfile is
5399 #define LFNAML 80 /* Max length for lock file name. */
5401 int lockfd; /* File descriptor for lock file. */
5402 PID_T pid; /* Process ID of this process. */
5403 int fpid; /* pid found in existing lockfile. */
5404 int tries; /* How many times we've tried... */
5405 int i, k; /* Workers */
5407 char *device, *devname; /* "/dev/xxx", "xxx" */
5408 char *unit, *p; /* <instance>p<port> part of xxx */
5410 char lockfil[LFNAML]; /* Lockfile name (no path) */
5411 char tmpnam[LFNAML]; /* Temporary lockfile name. */
5413 #ifdef HPUX10 /* Lockfile directory */
5414 char *lockdir = "/var/spool/locks"; /* Always this for 10.00 and higher */
5415 #else /* HP-UX 9.xx and below */
5417 char *lockdir = LOCK_DIR; /* Defined near top of this file */
5419 char *lockdir = "/usr/spool/uucp"; /* or not... */
5420 #endif /* LOCK_DIR */
5423 haslock = 0; /* Not locked yet. */
5424 *flfnam = '\0'; /* Lockfile name is empty. */
5425 lock2[0] = '\0'; /* Second one too. */
5426 pid = getpid(); /* Get my process ID */
5428 Construct name of lockfile and temporary file...
5429 device = name of tty device without the path, e.g. "tty0p0"
5430 lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
5432 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5433 debug(F110,"TTLOCK device",device,0);
5434 ckmakmsg(lockfil,LFNAML,"LCK..",device,NULL,NULL);
5436 k = 0; /* Assume device is not locked */
5437 n = 0; /* Digit counter */
5438 unit = device; /* Unit = <instance>p<port> */
5439 while (*unit && !isdigit(*unit)) /* Search for digit... */
5441 p = unit; /* Verify <num>p<num> format... */
5442 debug(F110,"TTLOCK unit 1",unit,0);
5444 The unit number is recognized as:
5445 (a) any sequence of digits that runs to the end of the string.
5446 (b) any (a) that includes one and only one letter "p", with at least
5447 one digit before and after it.
5449 while (isdigit(*p)) p++, n++; /* Get a run of digits */
5450 if (*p && n > 0) { /* Have a "p"? */
5451 if (*p == 'p' && isdigit(*(p+1))) {
5454 while (isdigit(*p)) p++, n++;
5457 if (n == 0 || *p) unit = "";
5458 debug(F110,"TTLOCK unit 2",unit,0);
5460 if (*unit) { /* Device name has unit number. */
5461 /* The following loop not only searches for the various lockfile */
5462 /* synonyms, but also removes all -- not just one -- stale lockfile */
5463 /* for the device, should there be more than one. See ttchkpid(). */
5465 for (i = 0; *devprefix[i]; i++) { /* For each driver... */
5466 /* Make device name */
5467 ckmakmsg(lock2,FLFNAML,"/dev/",devprefix[i],unit,NULL);
5468 priv_on(); /* Privs on */
5469 k = zchki(lock2) != -1; /* See if device exists */
5470 priv_off(); /* Privs off */
5471 debug(F111,"TTLOCK exist",lock2,k);
5473 if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
5475 /* Make lockfile name */
5476 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",devprefix[i],unit);
5477 debug(F110,"TTLOCK checking",lock2,0);
5478 priv_on(); /* Privs on */
5479 k = zchki(lock2) != -1; /* See if lockfile exists */
5480 priv_off(); /* Privs off */
5481 debug(F111,"TTLOCK check for lock A",lock2,k);
5482 if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
5483 ckstrncpy(flfnam,lock2,FLFNAML);
5488 } else { /* Some other device-name format */
5489 /* This takes care of symbolic links, etc... */
5490 /* But does not chase them down! */
5491 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",device,NULL);
5493 k = zchki(lock2) != -1; /* Check for existing lockfile */
5495 debug(F111,"TTLOCK check for lock B",lock2,k);
5496 if (k) if (ttchkpid(lock2)) { /* Check pid from lockfile */
5497 ckstrncpy(flfnam,lock2,FLFNAML);
5498 debug(F110,"TTLOCK in use",device,0);
5499 debug(F101,"TTLOCK returns","",-2);
5504 Get here only if there is no (more) lockfile, so now we make one (or two)...
5505 flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
5506 tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
5508 ckmakmsg(flfnam,FLFNAML,lockdir,"/",lockfil,NULL); /* SET LINE device */
5510 /* If dialout device, also make one for corresponding dialin device */
5512 if (!strncmp(device,"cu",2) && *unit && ttydexists)
5513 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..ttyd",unit,NULL);
5515 if ((int)strlen(lockdir)+12 < LFNAML)
5516 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temp name */
5519 debug(F110,"TTLOCK flfnam",flfnam,0);
5520 debug(F110,"TTLOCK lock2",lock2,0);
5521 debug(F110,"TTLOCK tmpnam",tmpnam,0);
5525 Lockfile permissions...
5526 444 is standard, HP-UX 10.00 uses 664. It doesn't matter.
5527 Kermit uses 444; the difference lets us tell whether Kermit created
5530 priv_on(); /* Turn on privileges. */
5531 lockfd = creat(tmpnam, 0444); /* Try to create temporary file. */
5532 if (lockfd < 0) { /* Create failed. */
5533 debug(F111,"TTLOCK creat failed",tmpnam,errno);
5534 if (errno == ENOENT) {
5536 printf("UUCP not installed or Kermit misconfigured\n");
5540 unlink(tmpnam); /* Get rid of the temporary file. */
5542 priv_off(); /* Turn off privileges!!! */
5543 debug(F101,"TTLOCK returns","",-1);
5544 return(-1); /* Return failure code. */
5546 debug(F110,"TTLOCK temp ok",tmpnam,0);
5548 /* Now write our pid into the temp lockfile in integer format. */
5550 i = write(lockfd, (char *)&pid, sizeof(pid));
5554 debug(F101,"TTLOCK pid","",pid);
5555 debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
5556 debug(F101,"TTLOCK write pid returns","",i);
5561 Now try to rename the temporary file to the real lockfile name.
5562 This will fail if a lock file of that name already exists, which
5563 will catch race conditions with other users.
5565 close(lockfd); /* Close the temp lockfile. */
5569 while (!haslock && tries++ < 2) {
5570 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5571 debug(F101,"TTLOCK link","",haslock);
5572 if (haslock) { /* If we made the lockfile... */
5575 /* We can't do this any more because we don't have a file descriptor yet. */
5576 #ifdef LOCKF /* Can be canceled with -DNOLOCKF */
5578 Create an advisory lock on the device through its file descriptor.
5579 This code actually seems to work. If it is executed, and then another
5580 process tries to open the same device under a different name to circumvent
5581 the lockfile, they get a "device busy" error.
5583 debug(F100,"TTLOCK LOCKF code...","",0);
5584 while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
5585 debug(F111, "TTLOCK lockf error", "", errno);
5586 if ((++tries >= 3) || (errno != EAGAIN)) {
5587 x = unlink(flfnam); /* Remove the lockfile */
5588 if (errno == EACCES && !quiet)
5589 printf("Device already locked by another process\n");
5596 #endif /* COMMENT */
5598 if (haslock) { /* If we made the lockfile ... */
5599 if (lock2[0]) { /* if there is to be a 2nd lockfile */
5600 lockfd = creat(lock2, 0444); /* Create it */
5601 debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
5602 if (lockfd > -1) { /* Created OK, write pid. */
5603 write(lockfd, (char *)&pid, sizeof(pid) );
5604 close(lockfd); /* Close and */
5605 chmod(lock2, 0444); /* set permissions. */
5606 } else { /* Not OK, but don't fail. */
5607 lock2[0] = '\0'; /* Just remember it's not there. */
5610 break; /* and we're done. */
5614 unlink(tmpnam); /* Unlink (remove) the temp file. */
5615 priv_off(); /* Turn off privs */
5616 i = haslock ? 0 : -1; /* Our return value */
5617 debug(F101,"TTLOCK returns","",i);
5620 #endif /* USETTYLOCK */
5621 #endif /* !NOUUCP */
5624 /* T T U N L O C K */
5627 ttunlck() { /* Remove UUCP lockfile(s). */
5631 debug(F111,"ttunlck",flfnam,haslock);
5635 if (haslock && *flfnam) {
5637 priv_on(); /* Turn on privs */
5639 x = uu_unlock(lockname);
5640 #else /* USE_UU_LOCK */
5641 x = ttyunlock(lockname); /* Try to unlock */
5642 #endif /* USE_UU_LOCK */
5643 priv_off(); /* Turn off privs */
5644 if (x < 0 && !quiet)
5645 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5647 *flfnam = '\0'; /* Erase the name. */
5652 #else /* No ttylock()... */
5654 if (haslock && *flfnam) {
5655 /* Don't remove lockfile if we didn't make it ourselves */
5656 if ((x = ttrpid(flfnam)) != (int)getpid()) {
5657 debug(F111,"ttunlck lockfile seized",flfnam,x);
5658 printf("Warning - Lockfile %s seized by pid %d\n",
5664 priv_on(); /* Turn privileges on. */
5666 x = unlink(flfnam); /* Remove the lockfile. */
5667 debug(F111,"ttunlck unlink",flfnam,x);
5669 if (errno && !quiet)
5671 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5674 *flfnam = '\0'; /* Erase the name. */
5678 x = unlink(lkflfn); /* Remove link to lockfile */
5679 debug(F111,"ttunlck AIX link unlink",lkflfn,x);
5681 if (errno && !quiet)
5683 printf("Warning - Can't remove link to lockfile: %s\n", lkflfn);
5687 if (lock2[0]) { /* If there is a second lockfile, */
5689 x = unlink(lock2); /* remove it too. */
5690 debug(F111,"ttunlck lock2 unlink",lock2,x);
5692 if (errno && !quiet)
5694 printf("Warning - Can't remove secondary lockfile: %s\n",
5698 lock2[0] = '\0'; /* Forget its name. */
5704 (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
5706 #endif /* COMMENT */
5708 priv_off(); /* Turn privileges off. */
5710 #endif /* USETTYLOCK */
5711 #endif /* !NOUUCP */
5716 4.3BSD-style UUCP line direction control.
5717 (Stan Barber, Rice U, 1980-something...)
5722 acucntrl(flag,ttname) char *flag, *ttname; {
5723 char x[DEVNAMLEN+32], *device, *devname;
5725 if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
5726 return; /* just return. */
5727 device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
5728 if (strncmp(device,"LCK..",4) == 0) device += 5;
5729 ckmakmsg(x,DEVNAMLEN+32,"/usr/lib/uucp/acucntrl ",flag," ",device);
5730 debug(F110,"called ",x,0);
5733 #endif /* ACUCNTRL */
5737 T T H F L O W -- Set or Reset hardware flow control.
5739 This is an attempt to collect all hardware-flow-control related code
5740 into a single module. Thanks to Rick Sladkey and John Kohl for lots of
5741 help here. Overview:
5743 Hardware flow control is not supported in many UNIX implementions. Even
5744 when it is supported, there is no (ha ha) "standard" for the programming
5745 interface. In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
5746 SunOS, AIX, etc, have totally different methods. (And, not strictly
5747 relevant here, the programming interface often brings one only to a no-op
5748 in the device driver!)
5750 Among all these, we have two major types of APIs: those in which hardware
5751 flow control is determined by bits in the same termio/termios/sgtty mode
5752 word(s) that are used for controlling such items as CBREAK vs RAW mode, and
5753 which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
5754 for changing terminal modes. And those that use entirely different
5757 In the first category, it is important that any change in the mode bits be
5758 reflected in the relevant termio(s)/sgtty structure, so that subsequent
5759 changes to that structure do not wipe out the effects of this routine. That
5760 is why a pointer, attrs, to the appropriate structure is passed as a
5761 parameter to this routine.
5763 The second category should give us no worries, since any changes to hardware
5764 flow control accomplished by this routine should not affect the termio(s)/
5765 sgtty structures, and therefore will not be undone by later changes to them.
5767 The second argument, status, means to turn on hardware flow control if
5768 nonzero, and to turn it off if zero.
5770 Returns: 0 on apparent success, -1 on probable failure.
5774 The following business is for BSDI, where it was discovered that two
5775 separate bits, CCTS_OFLOW and CRTS_IFLOW, are used in hardware flow control,
5776 but CTRSCTS is defined (in <termios.h>) to be just CCTS_OFLOW rather both
5777 bits, so hwfc only works in one direction if you use CRTSCTS to control it.
5778 Other 4.4BSD-based Unixes such as FreeBSD 4.1, which use these two bits,
5779 define CRTSCTS correctly.
5786 #define CRTSCTS (CRTS_IFLOW|CCTS_OFLOW)
5787 #endif /* CRTS_IFLOW */
5788 #endif /* CCTS_OFLOW */
5789 #endif /* CRTSCTS */
5790 #endif /* FIXCRTSCTS */
5793 tthflow(flow, status, attrs)
5794 int flow, /* Type of flow control (ckcdeb.h) */
5795 status; /* Nonzero = turn it on */
5796 /* Zero = turn it off */
5797 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
5798 struct termios *attrs;
5799 #else /* System V */
5803 /* AT&T UNIX 3.51m can set but not test for hardware flow control */
5804 #define RTSFLOW CTSCD
5805 #define CTSFLOW CTSCD
5806 #endif /* ATT7300 */
5807 #endif /* UNIX351M */
5808 struct termio *attrs;
5809 #else /* BSD, V7, etc */
5810 struct sgttyb *attrs; /* sgtty info... */
5812 #endif /* BSD44ORPOSIX */
5815 int x = 0; /* tthflow() return code */
5818 return p9tthflow(flow, status);
5821 #ifndef OXOS /* NOT Olivetti X/OS... */
5823 For SunOS 4.0 and later in the BSD environment ...
5825 The declarations are copied and interpreted from the System V header files,
5826 so we don't actually have to pull in all the System V junk when building
5827 C-Kermit for SunOS in the BSD environment, which would be dangerous because
5828 having those symbols defined would cause us to take the wrong paths through
5829 the code. The code in this section is used in both the BSD and Sys V SunOS
5834 In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
5835 because GNU CC uses different formats for the _IOxxx macros than regular CC;
5836 the POSIX forms work for both. But the POSIX calls are not available in
5839 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5840 #define TCSANOW 0 /* Do it now */
5843 unsigned long c_iflag; /* Input modes */
5844 unsigned long c_oflag; /* Output modes */
5845 unsigned long c_cflag; /* Control modes */
5846 unsigned long c_lflag; /* Line discipline modes */
5850 struct termios temp;
5852 _PROTOTYP( int tcgetattr, (int, struct termios *) );
5853 _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
5855 When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
5856 asserted. So we don't set CRTSCTS unless CD is up. This should be OK,
5857 since we don't need RTS/CTS during dialing, and after dialing is complete,
5858 we should have CD. If not, we still communicate, but without RTS/CTS.
5860 int mflags; /* Modem signal flags */
5863 if (ttpipe) return(0);
5866 if (ttpty) return(0);
5869 debug(F101,"tthflow SUNOS41 entry status","",status);
5870 if (!status) { /* Turn hard flow off */
5871 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5872 (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5873 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5874 x = tcsetattr(ttyfd,TCSANOW,&temp);
5876 } else { /* Turn hard flow on */
5877 if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
5878 (mflags & TIOCM_CAR)) { /* Check for CD */
5879 debug(F100,"tthflow SunOS has CD","",0);
5880 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5881 !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5882 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5883 x = tcsetattr(ttyfd,TCSANOW,&temp);
5887 debug(F100,"tthflow SunOS no CD","",0);
5892 struct termios temp;
5894 if (ttpipe) return(0);
5897 if (ttpty) return(0);
5899 debug(F101,"tthflow QNX entry status","",status);
5900 if (tcgetattr(ttyfd, &temp) > -1) { /* Get device attributes */
5901 if (!status) { /* Turn hard flow off */
5902 if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
5903 temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
5904 attrs->c_cflag &= ~(IHFLOW|OHFLOW);
5905 x = tcsetattr(ttyfd,TCSANOW,&temp);
5907 } else { /* Turn hard flow on */
5908 if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
5909 temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
5910 temp.c_iflag &= ~(IXON|IXOFF); /* Bye to IXON/IXOFF */
5911 ttraw.c_lflag |= IEXTEN; /* Must be on */
5912 x = tcsetattr(ttyfd,TCSANOW,&temp);
5913 attrs->c_cflag |= (IHFLOW|OHFLOW);
5914 attrs->c_iflag &= ~(IXON|IXOFF);
5919 debug(F100, "tthflow QNX getattr fails", "", 0);
5922 #ifdef POSIX_CRTSCTS
5924 POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
5925 Note: Do not assume CRTSCTS is a one-bit field!
5927 struct termios temp;
5929 if (ttpipe) return(0);
5932 if (ttpty) return(0);
5934 debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
5936 x = tcgetattr(ttyfd, &temp);
5937 debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
5942 if (!status) { /* Turn hard flow off */
5945 /* This can fail because of sign extension */
5946 /* e.g. in Linux where it's Bit 31 */
5947 (temp.c_cflag & CRTSCTS) == CRTSCTS
5949 (temp.c_cflag & CRTSCTS) != 0
5950 #endif /* COMMENT */
5952 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5953 attrs->c_cflag &= ~CRTSCTS;
5954 x = tcsetattr(ttyfd,TCSANOW,&temp);
5955 debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
5957 } else { /* John Dunlap 2010-01-26 */
5959 "tthflow before forcing off attrs CRTSCTS",
5961 attrs->c_cflag&CRTSCTS
5963 attrs->c_cflag &= ~CRTSCTS; /* force it off if !status */
5965 "tthflow after forcing off attrs CRTSCTS",
5967 attrs->c_cflag&CRTSCTS
5970 } else { /* Turn hard flow on */
5973 /* This can fail because of sign extension */
5974 (temp.c_cflag & CRTSCTS) != CRTSCTS
5976 (temp.c_cflag & CRTSCTS) == 0
5977 #endif /* COMMENT */
5979 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5980 temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
5981 x = tcsetattr(ttyfd,TCSANOW,&temp);
5982 debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
5984 attrs->c_cflag |= CRTSCTS;
5985 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
5992 SunOS 4.0 (and maybe earlier?). This code is dangerous because it
5993 prevents compilation with GNU gcc, which uses different formats for the
5994 _IORxxx macros than regular cc. SunOS 4.1 and later can use the POSIX
5995 routines above, which work for both cc and gcc.
5997 #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
5998 #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
5999 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
6002 unsigned long c_iflag; /* Input modes */
6003 unsigned long c_oflag; /* Output modes */
6004 unsigned long c_cflag; /* Control modes */
6005 unsigned long c_lflag; /* Line discipline modes */
6009 struct termios temp;
6011 if (ttpipe) return(0);
6014 if (ttpty) return(0);
6016 debug(F101,"tthflow entry status","",status);
6017 if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
6018 if (status) { /* Turn hard flow on */
6019 temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */
6020 x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
6021 attrs->c_cflag |= CRTSCTS; /* Add to global info. */
6022 } else { /* Turn hard flow off */
6023 temp.c_cflag &= ~CRTSCTS;
6024 x = ioctl(ttyfd,TCSETS,&temp);
6025 attrs->c_cflag &= ~CRTSCTS;
6028 #else /* Not SunOS 4.0 or later */
6029 #ifdef AIXRS /* IBM AIX RS/6000 */
6030 #ifndef AIX41 /* But only pre-4.x == SVR4 */
6032 if (ttpipe) return(0);
6035 if (ttpty) return(0);
6038 if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
6039 debug(F100,"hardflow TXADDCD (rts) error", "", 0);
6041 if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
6042 debug(F100,"hardflow TXDELCD (rts) error", "", 0);
6045 #else /* Not AIX RS/6000 */
6047 #ifdef ATTSV /* System V... */
6049 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
6052 #ifdef M_UNIX /* SCO UNIX 3.2v4.x or earlier */
6055 #endif /* CK_SCOV5 */
6057 #ifdef SCO_FORCE_RTSXOFF
6058 #ifdef CK_SCOUNIX /* But not SCO OpenServer 5.0.4 */
6059 #ifdef SCO_OSR504 /* or later... */
6061 #endif /* SCO_OSR504 */
6062 #endif /* CK_SCOUNIX */
6063 #endif /* SCO_FORCE_RTSXOFF */
6067 struct termios temp;
6069 if (ttpipe) return(0);
6072 if (ttpty) return(0);
6074 debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
6076 x = tcgetattr(ttyfd, &temp);
6077 debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
6081 if (ttpipe) return(0);
6084 if (ttpty) return(0);
6086 debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
6087 x = ioctl(ttyfd, TCGETA, &temp);
6088 debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
6091 This is not really POSIX, since POSIX does not deal with hardware flow
6092 control, but we are using the POSIX APIs. In fact, RTSFLOW and CTSFLOW
6093 are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif. So
6094 let's try forcing their definitions here.
6097 #define CTSFLOW 0020000
6098 debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
6100 debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
6101 #endif /* CTSFLOW */
6103 #define RTSFLOW 0040000
6104 debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
6106 debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
6107 #endif /* RTSFLOW */
6109 #define ORTSFL 0100000
6110 debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
6112 debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
6116 if (status) { /* Turn it ON */
6117 temp.c_cflag |= RTSFLOW|CTSFLOW;
6118 attrs->c_cflag |= RTSFLOW|CTSFLOW;
6120 temp.c_cflag &= ~ORTSFL;
6121 attrs->c_cflag &= ~ORTSFL;
6123 temp.c_iflag &= ~(IXON|IXOFF|IXANY);
6124 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
6125 } else { /* Turn it OFF */
6127 temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6128 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6130 temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
6131 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
6135 x = tcsetattr(ttyfd, TCSADRAIN, &temp);
6137 x = ioctl(ttyfd, TCSETA, &temp);
6139 debug(F101,"tthflow SCO set modes","",x);
6141 #else /* Not SCO UNIX */
6143 if (ttpipe) return(0);
6146 if (ttpty) return(0);
6148 if (!status) { /* Turn it OFF */
6150 debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
6151 rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
6153 x = ioctl(ttyfd,TCSETX,&rctsx);
6154 debug(F101,"tthflow ATTSV TCSETX OFF","",x);
6157 debug(F100,"tthflow TCSETX not defined","",0);
6160 debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
6161 #endif /* RTSXOFF */
6163 debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
6164 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6165 x = ioctl(ttyfd,TCSETX,&rctsx);
6166 debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
6168 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6169 #endif /* DTRXOFF */
6170 } else { /* Turn it ON. */
6171 if (flow == FLO_RTSC) { /* RTS/CTS Flow control... */
6172 debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
6174 /* This is the preferred way, according to SVID3 */
6176 x = ioctl(ttyfd,TCGETX,&rctsx);
6177 debug(F101,"tthflow TCGETX","",x);
6179 rctsx.x_hflag |= RTSXOFF | CTSXON;
6180 x = ioctl(ttyfd,TCSETX,&rctsx);
6181 debug(F100,"tthflow ATTSV ioctl","",x);
6184 debug(F100,"tthflow TCGETX not defined","",0);
6188 debug(F100,"tthflow RTSXOFF not defined","",0);
6190 #endif /* RTSXOFF */
6191 } else if (flow == FLO_DTRC) { /* DTR/CD Flow control... */
6192 debug(F100,"tthflow ATTSV DTR/CD ON","",0);
6194 /* This is straight out of SVID R4 */
6195 if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
6196 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6197 x = ioctl(ttyfd,TCSETX,&rctsx);
6200 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6202 #endif /* DTRXOFF */
6205 #endif /* CK_SCOUNIX */
6207 #else /* not System V... */
6213 if (ttpipe) return(0);
6216 if (ttpty) return(0);
6218 x = LDODTR | LDOCTS; /* Found only on UTEK? */
6219 if (flow == FLO_DTRT && status) { /* Use hardware flow control */
6221 x = ioctl(ttyfd,TIOCLBIS,&x);
6223 debug(F100,"hardflow TIOCLBIS error","",0);
6226 debug(F100,"hardflow TIOCLBIS ok","",0);
6231 x = ioctl(ttyfd,TIOCLBIC,&x);
6233 debug(F100,"hardflow TIOCLBIC error","",0);
6236 debug(F100,"hardflow TIOCLBIC ok","",0);
6242 #endif /* CK_DTRCTS */
6247 #endif /* POSIX_CRTSCTS */
6248 #endif /* SUNOS41 */
6252 struct termios temp; /* Olivetti X/OS ... */
6255 if (ttpipe) return(0);
6258 if (ttpty) return(0);
6260 x = ioctl(ttyfd,TCGETS,&temp);
6262 temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
6265 case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
6267 case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
6271 x = ioctl(ttyfd,TCSETS,&temp);
6279 /* T T P K T -- Condition the communication line for packets */
6280 /* or for modem dialing */
6283 If called with speed > -1, also set the speed.
6284 Returns 0 on success, -1 on failure.
6286 NOTE: the "xflow" parameter is supposed to be the currently selected
6287 type of flow control, but for historical reasons, this parameter is also
6288 used to indicate that we are dialing. Therefore, when the true flow
6289 control setting is needed, we access the external variable "flow", rather
6290 than trusting our "xflow" argument.
6294 ttpkt(long speed, int xflow, int parity)
6296 ttpkt(speed,xflow,parity) long speed; int xflow, parity;
6297 #endif /* CK_ANSIC */
6302 #endif /* NOLOCAL */
6304 extern int flow; /* REAL flow-control setting */
6306 if (ttyfd < 0) return(-1); /* Not open. */
6308 debug(F101,"ttpkt parity","",parity);
6309 debug(F101,"ttpkt xflow","",xflow);
6310 debug(F101,"ttpkt speed","",(int) speed);
6312 ttprty = parity; /* Let other tt functions see these. */
6313 ttspeed = speed; /* Make global copy for this module */
6314 ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
6316 needpchk = ttprty ? 0 : 1; /* Parity check needed? */
6319 #endif /* PARSENSE */
6321 debug(F101,"ttpkt ttpmsk","",ttpmsk);
6322 debug(F101,"ttpkt netconn","",netconn);
6324 #ifdef NETCONN /* No mode-changing for telnet */
6328 if (ttnet == NET_TCPB) { /* But turn off Nagle */
6329 extern int tcp_nodelay;
6330 nodelay_sav = tcp_nodelay;
6333 #endif /* TCP_NODELAY */
6335 if (istncomport()) {
6337 if (tvtflg == 0 && speed == ttspeed && flow == ttflow
6338 /* && ttcarr == curcarr */ ) {
6339 debug(F100,"ttpkt modes already set, skipping...","",0);
6340 return(0); /* Already been called. */
6342 if (flow != ttflow) {
6343 if ((rc = tnsetflow(flow)) < 0)
6347 if (speed != ttspeed) {
6349 speed = tnc_get_baud();
6350 else if ((rc = tnc_set_baud(speed)) < 0)
6354 tnc_set_datasize(8);
6355 tnc_set_stopsize(stopbits);
6360 case 'e': /* Even */
6361 debug(F100,"ttres 8 bits + even parity","",0);
6365 debug(F100,"ttres 8 bits + odd parity","",0);
6368 case 'm': /* Mark */
6369 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
6372 case 's': /* Space */
6373 debug(F100,"ttres 8 bits + invalid parity: space","",0);
6378 #endif /* HWPARITY */
6380 tnc_set_parity(1); /* None */
6385 #endif /* TN_COMPORT */
6386 #endif /* TCPSOCKET */
6390 #endif /* NETCONN */
6392 if (ttpipe) return(0);
6395 if (ttpty) return(0);
6399 if (ttfdflg && !isatty(ttyfd)) return(0);
6404 #endif /* COHERENT */
6406 #ifndef SVORPOSIX /* Berkeley, V7, etc. */
6409 For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
6410 after having previously set it to NONE without closing and reopening the
6411 device. Unless there's something I overlooked below...
6413 if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
6414 debug(F101,"ttpkt executing horrible flow kludge","",0);
6415 ttclos(0); /* Close it */
6417 ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
6420 #endif /* SVORPOSIX */
6422 #ifdef COHERENT /* This must be vestigial since we */
6423 #undef SVORPOSIX /* reverse it a few lines below... */
6424 #endif /* COHERENT */
6426 if (xflow != FLO_DIAL && xflow != FLO_DIAX)
6427 ttflow = xflow; /* Now make this available too. */
6431 s2 = (int) (speed / 10L); /* Convert bps to cps */
6432 debug(F101,"ttpkt calling ttsspd","",s2);
6433 s = ttsspd(s2); /* Check and set the speed */
6434 debug(F101,"ttpkt ttsspd result","",s);
6435 carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
6436 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
6437 tvtflg = 0; /* So ttvt() will work next time */
6439 #endif /* NOLOCAL */
6443 #endif /* COHERENT */
6445 #ifndef SVORPOSIX /* BSD section */
6446 if (flow == FLO_RTSC || /* Hardware flow control */
6449 tthflow(flow, 1, &ttraw);
6450 debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
6451 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6452 ttraw.sg_flags |= RAW; /* Enter raw mode */
6453 } else if (flow == FLO_NONE) { /* No flow control */
6454 debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
6455 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6456 tthflow(flow, 0, &ttraw); /* Turn off any hardware f/c too */
6457 ttraw.sg_flags |= RAW; /* Enter raw mode */
6458 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
6459 debug(F100,"ttpkt keeping original TANDEM","",0);
6460 ttraw.sg_flags &= ~TANDEM;
6461 ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
6462 /* NOTE: We should also handle hardware flow control here! */
6465 /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
6467 if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
6468 debug(F100,"ttpkt turning on TANDEM","",0);
6469 ttraw.sg_flags |= TANDEM; /* So ask for it. */
6471 #ifdef LPASS8 /* Can pass 8-bit data through? */
6472 /* If the LPASS8 local mode is available, then flow control can always */
6473 /* be used, even if parity is none and we are transferring 8-bit data. */
6474 /* But we only need to do all this if Xon/Xoff is requested. */
6475 /* BUT... this tends not to work through IP or LAT connections, terminal */
6476 /* servers, telnet, rlogin, etc, so it is currently disabled. */
6477 x = LPASS8; /* If LPASS8 defined, then */
6478 debug(F100,"ttpkt executing LPASS8 code","",0);
6479 if (lmodef) { /* TIOCLBIS must be too. */
6480 x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
6482 debug(F100,"ttpkt TIOCLBIS error","",0);
6485 debug(F100,"ttpkt TIOCLBIS ok","",0);
6489 But if we use LPASS8 mode, we must explicitly turn off
6490 terminal interrupts of all kinds.
6492 #ifdef TIOCGETC /* Not rawmode, */
6493 if (tcharf && (xlocal == 0)) { /* must turn off */
6494 tchnoi.t_intrc = -1; /* interrupt character */
6495 tchnoi.t_quitc = -1; /* and quit character. */
6496 tchnoi.t_startc = 17; /* Make sure xon */
6497 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6499 tchnoi.t_eofc = -1; /* eof character. */
6500 tchnoi.t_brkc = -1; /* brk character. */
6502 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6503 debug(F100,"ttpkt TIOCSETC failed","",0);
6506 debug(F100,"ttpkt TIOCSETC ok","",0);
6509 /* only for paranoid debugging */
6513 ioctl(0,TIOCGETC,&foo);
6515 "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
6516 foo.t_intrc, foo.t_quitc, foo.t_startc,
6517 foo.t_stopc, foo.t_eofc, foo.t_brkc);
6518 debug(F110,"ttpkt chars",tchbuf,0);
6520 #endif /* COMMENT */
6522 ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
6523 #endif /* TIOCGETC */
6525 /* Prevent suspend during packet mode */
6526 #ifdef TIOCGLTC /* Not rawmode, */
6527 if (ltcharf && (xlocal == 0)) { /* must turn off */
6528 ltchnoi.t_suspc = -1; /* suspend character */
6529 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6530 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6531 debug(F100,"ttpkt TIOCSLTC failed","",0);
6534 debug(F100,"ttpkt TIOCSLTC ok","",0);
6537 #endif /* TIOCGLTC */
6539 #else /* LPASS8 not defined */
6541 /* Previously, BSD-based implementations always */
6542 /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */
6543 /* This allows the flow control requested above to actually work, but only */
6544 /* if the user asks for parity (which also means they get 8th-bit quoting). */
6546 if (parity) { /* If parity, */
6547 ttraw.sg_flags &= ~RAW; /* use cooked mode */
6551 #endif /* COMMENT */
6552 ttraw.sg_flags |= CBREAK;
6553 debug(F101,"ttpkt cooked, cbreak, parity","",parity);
6554 #ifdef TIOCGETC /* Not rawmode, */
6555 if (tcharf && (xlocal == 0)) { /* must turn off */
6556 tchnoi.t_intrc = -1; /* interrupt character */
6557 tchnoi.t_quitc = -1; /* and quit character. */
6558 tchnoi.t_startc = 17; /* Make sure xon */
6559 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6561 tchnoi.t_eofc = -1; /* eof character. */
6562 tchnoi.t_brkc = -1; /* brk character. */
6564 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6565 debug(F100,"ttpkt TIOCSETC failed","",0);
6568 debug(F100,"ttpkt TIOCSETC ok","",0);
6571 #endif /* TIOCGETC */
6572 #ifdef TIOCGLTC /* Not rawmode, */
6573 /* Prevent suspend during packet mode */
6574 if (ltcharf && (xlocal == 0)) { /* must turn off */
6575 ltchnoi.t_suspc = -1; /* suspend character */
6576 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6577 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6578 debug(F100,"ttpkt TIOCSLTC failed","",0);
6581 debug(F100,"ttpkt TIOCSLTC ok","",0);
6584 #endif /* TIOCGLTC */
6585 } else { /* If no parity, */
6586 ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
6587 debug(F101,"ttpkt setting rawmode, parity","",parity);
6590 } /* End of Xon/Xoff section */
6592 /* Don't echo, don't map CR to CRLF on output, don't fool with case */
6594 ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
6596 ttraw.sg_flags &= ~(ECHO|CRMOD);
6600 ttraw.sg_flags &= ~ANYP; /* Must set this on old Towers */
6604 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
6608 if (stty(ttyfd,&ttraw) < 0) { /* Set the new modes. */
6609 debug(F101,"ttpkt stty failed","",errno);
6612 #endif /* BELLV10 */
6613 debug(F100,"ttpkt stty ok","",0);
6616 x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
6617 if (x != -1) { /* Make sure we know original modes. */
6620 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
6621 perror("ttpkt can't set ASCII mode");
6622 debug(F101,"ttpkt error setting ASCII mode","",x);
6626 debug(F100,"ttpkt set ASCII mode ok","",0);
6627 #endif /* sony_news */
6629 if (xlocal == 0) { /* Turn this off so we can read */
6630 signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
6633 tvtflg = 0; /* So ttvt() will work next time */
6634 debug(F100,"ttpkt success","",0);
6637 #endif /* Not ATTSV or POSIX */
6639 /* AT&T UNIX and POSIX */
6643 #endif /* COHERENT */
6646 if (flow == FLO_XONX) { /* Xon/Xoff */
6647 ttraw.c_iflag |= (IXON|IXOFF);
6648 tthflow(flow, 0, &ttraw);
6649 } else if (flow == FLO_NONE) { /* None */
6650 /* NOTE: We should also turn off hardware flow control here! */
6651 ttraw.c_iflag &= ~(IXON|IXOFF);
6652 tthflow(flow, 0, &ttraw);
6653 } else if (flow == FLO_KEEP) { /* Keep */
6654 ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
6655 ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
6656 /* NOTE: We should also handle hardware flow control here! */
6657 #ifdef POSIX_CRTSCTS
6658 /* In Linux case, we do this, which is unlikely to be portable */
6659 ttraw.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
6660 ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
6661 #endif /* POSIX_CRTSCTS */
6662 } else if (flow == FLO_RTSC || /* Hardware */
6665 ttraw.c_iflag &= ~(IXON|IXOFF); /* (190) */
6666 tthflow(flow, 1, &ttraw);
6668 ttraw.c_lflag &= ~(ICANON|ECHO);
6669 ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
6673 if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
6676 ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */
6677 #endif /* COHERENT */
6679 ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
6681 ttraw.c_lflag |= NOFLSH; /* Don't flush */
6682 ttraw.c_iflag |= IGNPAR; /* Ignore parity errors */
6685 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
6687 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
6690 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
6692 ttraw.c_oflag &= ~OPOST;
6693 ttraw.c_cflag &= ~(CSIZE);
6694 ttraw.c_cflag |= (CS8|CREAD|HUPCL);
6698 if (stopbits == 2) {
6699 ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
6700 debug(F100,"ttpkt 2 stopbits","",0);
6701 } else if (stopbits == 1) {
6702 ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
6703 debug(F100,"ttpkt 1 stopbit","",0);
6709 if (hwparity && xlocal) { /* Hardware parity */
6710 ttraw.c_cflag |= PARENB; /* Enable parity */
6712 /* Uncomment this only if needed -- I don't think it is */
6713 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
6714 ttraw.c_cflag |= CS8; /* And set it to 8 */
6715 #endif /* COMMENT */
6717 ttraw.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
6718 debug(F100,"ttpkt IGNPAR","",0); /* that have parity errors */
6721 case 'e': /* Even */
6722 ttraw.c_cflag &= ~(PARODD);
6723 debug(F100,"ttpkt 8 bits + even parity","",0);
6726 ttraw.c_cflag |= PARODD;
6727 debug(F100,"ttpkt 8 bits + odd parity","",0);
6729 case 'm': /* Mark */
6730 case 's': /* Space */
6731 /* PAREXT is mentioned in SVID but the details are not given. */
6732 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
6733 debug(F100,"ttpkt 8 bits + invalid parity","",0);
6736 } else { /* We handle parity ourselves */
6737 #endif /* HWPARITY */
6738 ttraw.c_cflag &= ~(PARENB); /* Don't enable parity */
6741 #endif /* HWPARITY */
6744 ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
6747 #ifndef VEOF /* for DGUX this is VEOF, not VMIN */
6748 ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */
6752 ttraw.c_cc[VMIN] = 1;
6758 #ifndef VEOL /* for DGUX this is VEOL, not VTIME */
6759 ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */
6763 ttraw.c_cc[VTIME] = 0;
6771 #ifdef VINTR /* Turn off interrupt character */
6772 if (xlocal == 0) /* so ^C^C can break us out of */
6773 ttraw.c_cc[VINTR] = 0; /* packet mode. */
6777 if (p9ttyparity('n') < 0)
6783 ttraw.c_cc[VMIN] = 0; /* DR7 can only poll. */
6784 #endif /* BEOSORBEBOX */
6789 debug(F100,"ttpkt TESTING234 rawmode","",0);
6792 ttraw.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
6793 ttraw.c_iflag &= ~(INPCK|IGNPAR|IXON|IXOFF);
6794 ttraw.c_iflag |= IGNBRK;
6796 ttraw.c_iflag &= ~IMAXBEL;
6797 #endif /* IMAXBEL */
6799 ttraw.c_iflag &= ~IXANY;
6802 ttraw.c_iflag &= ~IUCLC;
6806 ttraw.c_oflag &= ~OPOST;
6808 ttraw.c_oflag &= ~OXTABS;
6811 ttraw.c_oflag &= ~ONOCR;
6814 ttraw.c_oflag &= ~ONLRET;
6817 ttraw.c_oflag &= ~ONLCR;
6821 ttraw.c_lflag &= ~ECHO;
6823 ttraw.c_lflag &= ~ECHOE;
6826 ttraw.c_lflag &= ~ECHONL;
6829 ttraw.c_lflag &= ~ECHOPRT;
6830 #endif /* ECHOPRT */
6832 ttraw.c_lflag &= ~ECHOKE;
6835 ttraw.c_lflag &= ~ECHOCTL;
6836 #endif /* ECHOCTL */
6838 ttraw.c_lflag &= ~ALTWERASE;
6839 #endif /* ALTWERASE */
6841 ttraw.c_lflag &= ~EXTPROC;
6842 #endif /* EXTPROC */
6843 ttraw.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
6845 ttraw.c_lflag |= NOKERNINFO;
6846 #endif /* NOKERNINFO */
6847 /* ttraw.c_lflag |= NOFLSH; */
6848 ttraw.c_lflag &= ~NOFLSH;
6851 ttraw.c_cflag &= ~(CSIZE|PARENB|PARODD);
6852 ttraw.c_cflag |= CS8|CREAD;
6854 ttraw.c_cc[VMIN] = 1; /* Supposedly needed for AIX */
6858 #endif /* TESTING234 */
6860 debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
6861 x = tcsetattr(ttyfd,TCSADRAIN,&ttraw);
6862 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr","",x);
6864 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr errno","",errno);
6867 #else /* BSD44ORPOSIX */
6868 x = ioctl(ttyfd,TCSETAW,&ttraw);
6869 debug(F101,"ttpkt ATTSV ioctl TCSETAW","",x);
6870 if (x < 0) { /* set new modes . */
6871 debug(F101,"ttpkt ATTSV ioctl TCSETAW errno","",errno);
6874 #endif /* BSD44ORPOSIX */
6877 debug(F100,"ttpkt ok","",0);
6883 #endif /* COHERENT */
6887 /* T T S E T F L O W -- Set flow control immediately. */
6891 #endif /* COHERENT */
6894 ttsetflow(flow) int flow; {
6895 if (ttyfd < 0) /* A channel must be open */
6898 debug(F101,"ttsetflow flow","",flow);
6901 if (netconn && istncomport()) {
6902 debug(F101,"ttsetflow net modem","",ttmdm);
6903 return(tnsetflow(flow));
6905 #endif /* TN_COMPORT */
6907 if (ttpipe) return(0);
6910 if (ttpty) return(0);
6914 /* This seems to hurt... */
6915 if (flow == FLO_KEEP)
6917 #endif /* COMMENT */
6919 if (flow == FLO_RTSC || /* Hardware flow control... */
6922 tthflow(flow, 1, &ttraw);
6924 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6926 ttraw.c_iflag &= ~(IXON|IXOFF);
6927 #endif /* SVORPOSIX */
6929 } else if (flow == FLO_XONX) { /* Xon/Xoff... */
6932 ttraw.sg_flags |= TANDEM;
6934 ttraw.c_iflag |= (IXON|IXOFF);
6935 #endif /* SVORPOSIX */
6936 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off hardware flow control */
6938 } else if (flow == FLO_NONE) { /* No flow control */
6941 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6943 ttraw.c_iflag &= ~(IXON|IXOFF);
6944 #endif /* SVORPOSIX */
6945 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off any hardware f/c too */
6948 /* Set the new modes... */
6950 #ifndef SVORPOSIX /* BSD and friends */
6952 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
6956 if (stty(ttyfd,&ttraw) < 0)
6959 #endif /* BELLV10 */
6961 #ifdef BSD44ORPOSIX /* POSIX */
6962 if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
6964 #else /* System V */
6965 if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
6967 #endif /* BSD44ORPOSIX */
6968 #endif /* SVORPOSIX */
6973 #endif /* COHERENT */
6975 /* T T V T -- Condition communication device for use as virtual terminal. */
6979 ttvt(long speed, int flow)
6981 ttvt(speed,flow) long speed; int flow;
6982 #endif /* CK_ANSIC */
6986 debug(F101,"ttvt ttyfd","",ttyfd);
6987 debug(F101,"ttvt tvtflg","",tvtflg);
6988 debug(F111,"ttvt speed",ckitoa(ttspeed),speed);
6989 debug(F111,"ttvt flow",ckitoa(ttflow),flow);
6990 debug(F111,"ttvt curcarr",ckitoa(ttcarr),curcarr);
6992 /* Note: NetBSD and maybe other BSD44s have cfmakeraw() */
6993 /* Maybe it would be simpler to use it... */
6997 return(conbin((char)escchr));
6999 if (ttyfd < 0) { /* Not open. */
7002 else /* But maybe something buffered. */
7006 if (ttpipe) return(0);
7009 if (ttpty) return(0);
7016 extern int tcp_nodelay;
7017 if (ttnet == NET_TCPB) {
7018 if (nodelay_sav > -1) {
7019 no_delay(ttyfd,nodelay_sav);
7024 #endif /* TCP_NODELAY */
7026 if (istncomport()) {
7028 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7029 /* && ttcarr == curcarr */ ) {
7030 debug(F100,"ttvt modes already set, skipping...","",0);
7031 return(0); /* Already been called. */
7033 if (flow != ttflow) {
7034 if ((rc = tnsetflow(flow)) < 0)
7038 if (speed != ttspeed) {
7040 speed = tnc_get_baud();
7041 else if ((rc = tnc_set_baud(speed)) < 0)
7045 tnc_set_datasize(8);
7046 tnc_set_stopsize(stopbits);
7051 case 'e': /* Even */
7052 debug(F100,"ttres 8 bits + even parity","",0);
7056 debug(F100,"ttres 8 bits + odd parity","",0);
7059 case 'm': /* Mark */
7060 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
7063 case 's': /* Space */
7064 debug(F100,"ttres 8 bits + invalid parity: space","",0);
7069 #endif /* HWPARITY */
7071 tnc_set_parity(1); /* None */
7076 #endif /* TN_COMPORT */
7077 #endif /* TCPSOCKET */
7078 tvtflg = 1; /* Network connections... */
7079 debug(F100,"ttvt network connection, skipping...","",0);
7080 return(0); /* ... require no special setup */
7082 #endif /* NETCONN */
7084 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7085 /* && ttcarr == curcarr */ )
7087 debug(F100,"ttvt modes already set, skipping...","",0);
7088 return(0); /* Already been called. */
7096 debug(F100,"ttvt using external fd, skipping...","",0);
7100 debug(F100,"ttvt setting modes...","",0);
7102 if (xlocal) { /* For external lines... */
7103 s2 = (int) (speed / 10L);
7104 s = ttsspd(s2); /* Check/set the speed */
7105 carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
7106 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
7112 #endif /* COHERENT */
7115 /* Berkeley, V7, etc */
7116 if (flow == FLO_RTSC || /* Hardware flow control */
7119 tthflow(flow, 1, &tttvt);
7120 debug(F100,"ttvt hard flow, TANDEM off","",0);
7121 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7122 } else if (flow == FLO_XONX) { /* Xon/Xoff flow control */
7123 debug(F100,"ttvt TANDEM on","",0);
7124 tttvt.sg_flags |= TANDEM; /* Ask for it. */
7125 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7126 } else if (flow == FLO_NONE) {
7127 debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
7128 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7129 tthflow(flow, 0, &tttvt); /* Turn off any hardware f/c too */
7130 tttvt.sg_flags |= RAW; /* Enter raw mode */
7131 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
7132 debug(F100,"ttvt keeping original TANDEM","",0);
7133 tttvt.sg_flags &= ~TANDEM;
7134 tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
7135 /* NOTE: We should also handle hardware flow control here! */
7137 tttvt.sg_flags |= RAW; /* Raw mode in all cases */
7139 tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */
7141 tttvt.sg_flags &= ~ECHO; /* No echo */
7145 if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
7148 if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */
7150 #endif /* BELLV10 */
7152 #else /* It is ATTSV or POSIX */
7154 if (flow == FLO_XONX) { /* Software flow control */
7155 tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */
7156 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7157 debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
7158 } else if (flow == FLO_NONE) { /* NONE */
7159 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff */
7160 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7161 debug(F100,"ttvt SVORPOSIX flow NONE","",0);
7162 } else if (flow == FLO_KEEP) {
7163 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
7164 tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
7165 #ifdef POSIX_CRTSCTS
7166 tttvt.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
7167 tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
7168 #endif /* POSIX_CRTSCTS */
7169 debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
7170 } else if (flow == FLO_RTSC || /* Hardware flow control */
7173 tttvt.c_iflag &= ~(IXON|IXOFF); /* (196) */
7174 tthflow(flow, 1, &tttvt);
7175 debug(F100,"ttvt SVORPOSIX flow HARD","",0);
7179 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7181 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
7182 #endif /* COHERENT */
7184 /* Needed for hwfc */
7185 if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
7186 tttvt.c_lflag |= IEXTEN;
7189 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7190 tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
7193 tttvt.c_iflag |= (IGNBRK|IGNPAR);
7199 if (stopbits == 2) {
7200 tttvt.c_cflag |= CSTOPB; /* 2 stop bits */
7201 debug(F100,"ttvt 2 stopbits","",0);
7202 } else if (stopbits == 1) {
7203 tttvt.c_cflag &= ~(CSTOPB); /* 1 stop bit */
7204 debug(F100,"ttvt 1 stopbit","",0);
7212 if (hwparity && xlocal) { /* Hardware parity */
7214 /* Uncomment this only if needed -- I don't think it is */
7215 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
7216 ttraw.c_cflag |= CS8; /* And set it to 8 */
7217 #endif /* COMMENT */
7219 debug(F101,"ttvt hwparity IGNPAR","",IGNPAR);
7220 tttvt.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
7222 tttvt.c_cflag |= PARENB; /* Enable parity */
7225 case 'e': /* Even */
7226 tttvt.c_cflag &= ~(PARODD);
7227 debug(F100,"ttvt 8 bits + even parity","",0);
7230 tttvt.c_cflag |= PARODD;
7231 debug(F100,"ttvt 8 bits + odd parity","",0);
7233 case 'm': /* Mark */
7234 case 's': /* Space */
7235 /* PAREXT is mentioned in SVID but the details are not given. */
7236 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
7237 debug(F100,"ttvt 8 bits + invalid parity","",0);
7240 } else { /* We handle parity ourselves */
7241 #endif /* HWPARITY */
7242 tttvt.c_cflag &= ~(PARENB); /* Don't enable parity */
7245 #endif /* HWPARITY */
7249 /* Things not to do... */
7250 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
7252 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
7255 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
7257 tttvt.c_cflag &= ~(CSIZE); /* Zero out the char size field */
7258 tttvt.c_cflag |= (CS8|CREAD|HUPCL); /* Char size 8, enable receiver, hup */
7259 tttvt.c_oflag &= ~OPOST; /* Don't postprocess output */
7260 #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
7265 tttvt.c_cc[VMIN] = 1;
7271 #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */
7276 tttvt.c_cc[VTIME] = 0;
7284 if (p9ttyparity('n') < 0)
7290 tttvt.c_cc[VMIN] = 0; /* DR7 can only poll. */
7291 #endif /* BEOSORBEBOX */
7293 x = tcsetattr(ttyfd,TCSADRAIN,&tttvt);
7294 debug(F101,"ttvt BSD44ORPOSIX tcsetattr","",x);
7296 debug(F101,"ttvt BSD44ORPOSIX tcsetattr errno","",errno);
7300 x = ioctl(ttyfd,TCSETAW,&tttvt);
7301 debug(F101,"ttvt ATTSV ioctl TCSETAW","",x);
7302 if (x < 0) { /* set new modes . */
7303 debug(F101,"ttvt ATTSV ioctl TCSETAW errno","",errno);
7306 #endif /* BSD44ORPOSIX */
7310 ttspeed = speed; /* Done, remember how we were */
7311 ttflow = flow; /* called, so we can decide how to */
7312 tvtflg = 1; /* respond next time. */
7313 debug(F100,"ttvt ok","",0);
7318 #endif /* COHERENT */
7320 #endif /* NOLOCAL */
7325 /* Serial speed department . . . */
7328 SCO OSR5.0.x might or might not support high speeds. Sometimes they are not
7329 defined in the header files but they are supported (e.g. when building with
7330 UDK compiler rather than /bin/cc), sometimes vice versa. Even though 5.0.4
7331 was the first release that came with high serial speeds standard, releases
7332 back to 5.0.0 could use them if certain patches (or "supplements") were
7333 applied to the SIO driver. Plus a lot of SCO installations run third-party
7338 #define B38400 0000017
7341 #define B57600 0000021
7344 #define B76800 0000022
7347 #define B115200 0000023
7348 #endif /* B115200 */
7350 #define B230400 0000024
7351 #endif /* B230400 */
7353 #define B460800 0000025
7354 #endif /* B460800 */
7356 #define B921600 0000026
7357 #endif /* B921600 */
7358 #endif /* CK_SCOV5 */
7360 Plan 9's native speed setting interface lets you set anything you like,
7361 but will fail if the hardware doesn't like it, so we allow all the common
7399 #define B14400 14400
7402 #define B19200 19200
7405 #define B28800 28800
7408 #define B38400 38400
7411 #define B57600 57600
7414 #define B76800 76800
7417 #define B115200 115200
7418 #endif /* B115200 */
7420 #define B230400 230400
7421 #endif /* B230400 */
7423 #define B460800 460800
7424 #endif /* B460800 */
7426 #define B921600 921600
7427 #endif /* B921600 */
7430 /* T T S S P D -- Checks and sets transmission rate. */
7432 /* Call with speed in characters (not bits!) per second. */
7433 /* Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
7435 #ifdef USETCSETSPEED
7437 The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
7438 to be used as a speed to be set, rather than forcing a choice from a
7439 predefined list. It seems to be peculiar to UnixWare 7.
7441 These are the function codes to be passed to tc[gs]etspeed(),
7442 but for some reason they don't seem to be picked up from termios.h.
7446 #endif /* TCS_ALL */
7452 #endif /* TCS_OUT */
7453 #endif /* USETCSETSPEED */
7456 ttsspd(cps) int cps; {
7459 /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
7465 int ok = 1; /* Speed check result, assume ok */
7467 #ifdef OLINUXHISPEED
7468 unsigned int spd_flags = 0;
7469 struct serial_struct serinfo;
7470 #endif /* OLINUXHISPEED */
7472 debug(F101,"ttsspd cps","",cps);
7473 debug(F101,"ttsspd ttyfd","",ttyfd);
7474 debug(F101,"ttsspd xlocal","",xlocal);
7476 if (ttyfd < 0 || xlocal == 0) /* Don't set speed on console */
7483 return(tnc_set_baud(cps * 10));
7485 #endif /* TN_COMPORT */
7488 #endif /* NETCONN */
7490 if (ttpipe) return(0);
7493 if (ttpty) return(0);
7496 if (cps < 0) return(-1);
7497 s = s2 = 0; /* NB: s and s2 might be unsigned */
7499 #ifdef USETCSETSPEED
7503 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7504 debug(F101,"ttsspd tcgetattr","",x);
7507 debug(F101,"ttsspd TCSETSPEED speed","",s);
7510 if (s == 8880L) { /* 75/1200 split speed requested */
7511 tcsetspeed(TCS_IN, &ttcur, 1200L);
7512 tcsetspeed(TCS_OUT, &ttcur, 75L);
7514 tcsetspeed(TCS_ALL, &ttcur, s); /* Put new speed in structs */
7516 if (errno & deblog) {
7517 debug(F101,"ttsspd TCSETSPEED errno","",errno);
7522 tcsetspeed(TCS_ALL, &ttraw, s);
7523 tcsetspeed(TCS_ALL, &tttvt, s);
7524 tcsetspeed(TCS_ALL, &ttold, s);
7526 if (s == 8880L) { /* 75/1200 split speed requested */
7527 tcsetspeed(TCS_IN, &ttraw, 1200L);
7528 tcsetspeed(TCS_OUT, &ttraw, 75L);
7529 tcsetspeed(TCS_IN, &tttvt, 1200L);
7530 tcsetspeed(TCS_OUT, &tttvt, 75L);
7531 tcsetspeed(TCS_IN, &ttold, 1200L);
7532 tcsetspeed(TCS_OUT, &ttold, 75L);
7534 tcsetspeed(TCS_ALL, &ttraw, s);
7535 tcsetspeed(TCS_ALL, &tttvt, s);
7536 tcsetspeed(TCS_ALL, &ttold, s);
7538 #endif /* COMMENT */
7540 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
7541 debug(F101,"ttsspd tcsetattr","",x);
7545 #else /* Not USETCSETSPEED */
7547 /* First check that the given speed is valid. */
7551 case 0: s = B0; break;
7552 case 5: s = B50; break;
7553 case 7: s = B75; break;
7555 case 11: s = B110; break;
7557 case 13: s = B134; break;
7558 case 15: s = B150; break;
7559 case 20: s = B200; break;
7561 case 30: s = B300; break;
7563 case 60: s = B600; break;
7565 case 120: s = B1200; break;
7567 case 180: s = B1800; break;
7569 case 240: s = B2400; break;
7570 case 480: s = B4800; break;
7572 case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
7575 case 720: s = B7200; break;
7577 case 960: s = B9600; break;
7579 case 1440: s = B14400; break;
7582 case 1920: s = B19200; break;
7585 case 1920: s = EXTA; break;
7589 case 2880: s = B28800; break;
7592 case 3840: s = B38400;
7593 #ifdef OLINUXHISPEED
7594 spd_flags = ~ASYNC_SPD_MASK; /* Nonzero, but zero flags */
7595 #endif /* OLINUXHISPEED */
7597 #else /* B38400 not defined... */
7599 case 3840: s = EXTB; break;
7605 case 5760: s = _B57600; break;
7606 #endif /* _B57600 */
7608 case 11520: s = _B115200; break;
7609 #endif /* _B115200 */
7611 #ifdef OLINUXHISPEED
7613 This bit from <carlo@sg.tn.tudelft.nl>:
7614 "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
7615 setting the speed to 38400 will set the custom speed (and ttgspd returns
7616 38400), but speeds 57600 and 115200 won't work any more because I didn't
7617 want to mess up the speed flags when someone is doing sophisticated stuff
7618 like custom speeds..."
7620 case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
7621 case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
7624 case 5760: s = B57600; break;
7627 case 7680: s = B76800; break;
7630 case 11520: s = B115200; break;
7631 #endif /* B115200 */
7632 #endif /* OLINUXHISPEED */
7634 case 15360: s = B153600; break;
7635 #endif /* B153600 */
7637 case 23040: s = B230400; break;
7638 #endif /* B230400 */
7640 case 30720: s = B307200; break;
7641 #endif /* B307200 */
7643 case 46080: s = B460800; break;
7646 case 92160: s = B921600; break;
7647 #endif /* B921600 */
7650 ok = 0; /* Good speed not found, so not ok */
7653 debug(F101,"ttsspd ok","",ok);
7654 debug(F101,"ttsspd s","",s);
7657 debug(F100,"ttsspd fails","",0);
7660 if (!s2) s2 = s; /* Set input speed */
7662 if (p9ttsspd(cps) < 0)
7666 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7667 debug(F101,"ttsspd tcgetattr","",x);
7670 #ifdef OLINUXHISPEED
7671 debug(F101,"ttsspd spd_flags","",spd_flags);
7672 if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
7673 if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
7674 debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
7676 } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
7677 serinfo.flags &= ~ASYNC_SPD_MASK;
7678 serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
7679 if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
7682 #endif /* OLINUXHISPEED */
7683 cfsetospeed(&ttcur,s);
7684 cfsetispeed(&ttcur,s2);
7685 cfsetospeed(&ttraw,s);
7686 cfsetispeed(&ttraw,s2);
7687 cfsetospeed(&tttvt,s);
7688 cfsetispeed(&tttvt,s2);
7689 cfsetospeed(&ttold,s);
7690 cfsetispeed(&ttold,s2);
7691 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
7692 debug(F101,"ttsspd tcsetattr","",x);
7693 if (x < 0) return(-1);
7696 if (cps == 888) return(-1); /* No split speeds, sorry. */
7697 x = ioctl(ttyfd,TCGETA,&ttcur);
7698 debug(F101,"ttsspd TCGETA ioctl","",x);
7699 if (x < 0) return(-1);
7700 ttcur.c_cflag &= ~CBAUD;
7702 tttvt.c_cflag &= ~CBAUD;
7704 ttraw.c_cflag &= ~CBAUD;
7706 ttold.c_cflag &= ~CBAUD;
7708 x = ioctl(ttyfd,TCSETAW,&ttcur);
7709 debug(F101,"ttsspd TCSETAW ioctl","",x);
7710 if (x < 0) return(-1);
7713 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
7714 debug(F101,"ttsspd TIOCGDEV ioctl","",x);
7715 if (x < 0) return(-1);
7719 ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
7720 debug(F101,"ttsspd BELLV10 ioctl","",ok);
7723 debug(F101,"ttsspd BELLV10 errno","",ok);
7727 x = gtty(ttyfd,&ttcur);
7728 debug(F101,"ttsspd gtty","",x);
7729 if (x < 0) return(-1);
7730 ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
7731 tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
7732 ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
7733 ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
7734 x = stty(ttyfd,&ttcur);
7735 debug(F101,"ttsspd stty","",x);
7736 if (x < 0) return(-1);
7737 #endif /* BELLV10 */
7739 #endif /* BSD44ORPOSIX */
7742 return(1); /* Return 1 = success. */
7743 #endif /* USETCSETSPEED */
7746 #endif /* NOLOCAL */
7748 /* C O N G S P D - Get speed of console terminal */
7753 This is a disgusting hack. The right way to do this would be to pass an
7754 argument to ttgspd(), but then we'd need to change the Kermit API and
7755 all of the ck?tio.c modules. (Currently used only for rlogin.)
7762 #endif /* NETCONN */
7766 debug(F101,"congspd","",spd);
7769 #endif /* NETCONN */
7774 /* T T S P D L I S T -- Get list of serial speeds allowed on this platform */
7777 static long spdlist[NSPDLIST];
7779 As written, this picks up the speeds known at compile time, and thus
7780 apply to the system where C-Kermit was built, rather than to the one where
7781 it is running. Suggestions for improvement are always welcome.
7786 for (i = 0; i < NSPDLIST; i++) /* Initialize the list */
7790 #ifdef USETCSETSPEED /* No way to find out what's legal */
7791 debug(F100,"ttspdlist USETCSETSPEED","",0);
7796 spdlist[i++] = 110L;
7798 spdlist[i++] = 134L;
7800 spdlist[i++] = 150L;
7801 spdlist[i++] = 200L;
7802 spdlist[i++] = 300L;
7803 spdlist[i++] = 600L;
7804 spdlist[i++] = 1200L;
7805 spdlist[i++] = 1800L;
7806 spdlist[i++] = 2400L;
7807 spdlist[i++] = 4800L;
7808 spdlist[i++] = 8880L;
7809 spdlist[i++] = 9600L;
7810 spdlist[i++] = 14400L;
7811 spdlist[i++] = 19200L;
7812 spdlist[i++] = 28800L;
7814 spdlist[i++] = 33600L;
7816 spdlist[i++] = 38400L;
7817 spdlist[i++] = 57600L;
7818 spdlist[i++] = 76800L;
7819 spdlist[i++] = 115200L;
7821 spdlist[i++] = 153600L;
7822 spdlist[i++] = 230400L;
7823 spdlist[i++] = 307200L;
7824 spdlist[i++] = 460800L;
7825 spdlist[i++] = 921600L;
7828 #else /* USETCSETSPEED */
7830 debug(F100,"ttspdlist no USETCSETSPEED","",0);
7833 debug(F101,"ttspdlist B50","",B50);
7837 debug(F101,"ttspdlist B75","",B75);
7841 debug(F101,"ttspdlist B110","",B110);
7842 spdlist[i++] = 110L;
7845 debug(F101,"ttspdlist B134","",B134);
7846 spdlist[i++] = 134L;
7849 debug(F101,"ttspdlist B150","",B150);
7850 spdlist[i++] = 150L;
7853 debug(F101,"ttspdlist B200","",B200);
7854 spdlist[i++] = 200L;
7857 debug(F101,"ttspdlist B300","",B300);
7858 spdlist[i++] = 300L;
7861 debug(F101,"ttspdlist B600","",B600);
7862 spdlist[i++] = 600L;
7865 debug(F101,"ttspdlist B1200","",B1200);
7866 spdlist[i++] = 1200L;
7869 debug(F101,"ttspdlist B1800","",B1800);
7870 spdlist[i++] = 1800L;
7873 debug(F101,"ttspdlist B2400","",B2400);
7874 spdlist[i++] = 2400L;
7877 debug(F101,"ttspdlist B4800","",B4800);
7878 spdlist[i++] = 4800L;
7881 debug(F101,"ttspdlist B9600","",B9600);
7882 spdlist[i++] = 9600L;
7885 debug(F101,"ttspdlist B14400","",B14400);
7886 spdlist[i++] = 14400L;
7889 debug(F101,"ttspdlist B19200","",B19200);
7890 spdlist[i++] = 19200L;
7893 debug(F101,"ttspdlist EXTA","",EXTA);
7894 spdlist[i++] = 19200L;
7898 debug(F101,"ttspdlist B28800","",B28800);
7899 spdlist[i++] = 28800L;
7902 debug(F101,"ttspdlist B33600","",B33600);
7903 spdlist[i++] = 33600L;
7906 debug(F101,"ttspdlist B38400","",B38400);
7907 spdlist[i++] = 38400L;
7910 debug(F101,"ttspdlist EXTB","",EXTB);
7911 spdlist[i++] = 38400L;
7915 debug(F101,"ttspdlist _B57600","",_B57600);
7916 spdlist[i++] = 57600L;
7919 debug(F101,"ttspdlist B57600","",B57600);
7920 spdlist[i++] = 57600L;
7922 #endif /* _B57600 */
7924 debug(F101,"ttspdlist B76800","",B76800);
7925 spdlist[i++] = 76800L;
7928 debug(F101,"ttspdlist _B115200","",_B115200);
7929 spdlist[i++] = 115200L;
7932 debug(F101,"ttspdlist B115200","",B115200);
7933 spdlist[i++] = 115200L;
7934 #endif /* B115200 */
7935 #endif /* _B115200 */
7937 debug(F101,"ttspdlist B153600","",B153600);
7938 spdlist[i++] = 153600L;
7939 #endif /* B153600 */
7941 debug(F101,"ttspdlist B230400","",B230400);
7942 spdlist[i++] = 230400L;
7943 #endif /* B230400 */
7945 debug(F101,"ttspdlist B307200","",B307200);
7946 spdlist[i++] = 307200L;
7947 #endif /* B307200 */
7949 debug(F101,"ttspdlist B460800","",B460800);
7950 spdlist[i++] = 460800L;
7951 #endif /* B460800 */
7953 debug(F101,"ttspdlist B921600","",B921600);
7954 spdlist[i++] = 921600L;
7955 #endif /* B921600 */
7956 #endif /* USETCSETSPEED */
7957 spdlist[0] = i - 1; /* Return count in 0th element */
7958 debug(F111,"ttspdlist spdlist","0",spdlist[0]);
7959 return((long *)spdlist);
7962 /* T T G S P D - Get speed of currently selected tty line */
7965 Unreliable. After SET LINE, it returns an actual speed, but not necessarily
7966 the real speed. On some systems, it returns the line's nominal speed, from
7967 /etc/ttytab. Even if you SET SPEED to something else, this function might
7971 ttgspd() { /* Get current serial device speed */
7976 speed_t /* Should be unsigned */
7978 int /* Isn't unsigned */
7983 #ifdef OLINUXHISPEED
7984 unsigned int spd_flags = 0;
7985 struct serial_struct serinfo;
7986 #endif /* OLINUXHISPEED */
7992 return(tnc_get_baud());
7994 #endif /* TN_COMPORT */
7995 return(-1); /* -1 if network connection */
7997 #endif /* NETCONN */
7999 if (ttpipe) return(-1);
8002 if (ttpty) return(-1);
8005 debug(F101,"ttgspd ttyfd","",ttyfd);
8007 #ifdef USETCSETSPEED
8009 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
8010 debug(F101,"ttgspd tcgetattr","",x);
8014 s = tcgetspeed(TCS_ALL, &ttcur);
8015 debug(F101,"ttsspd TCGETSPEED speed","",s);
8018 s1 = tcgetspeed(TCS_IN, &ttcur);
8019 s2 = tcgetspeed(TCS_OUT, &ttcur);
8020 if (s1 == 1200L && s2 == 75L)
8024 if (errno & deblog) {
8025 debug(F101,"ttsspd TCGETSPEED errno","",errno);
8030 #else /* Not USETCSETSPEED */
8038 #ifdef OLINUXHISPEED
8039 debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
8040 #endif /* OLINUXHISPEED */
8044 s = cfgetospeed(&ccold);
8045 debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
8048 s = ccold.c_cflag & CBAUD;
8049 debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
8051 s = ccold.sg_ospeed; /* (obtained by congm()) */
8052 debug(F101,"ttgspd sg_ospeed 1","",s);
8054 #endif /* BSD44POSIX */
8058 if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
8059 s = cfgetospeed(&ttcur);
8060 debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
8061 #ifdef OLINUXHISPEED
8062 if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
8063 spd_flags = serinfo.flags & ASYNC_SPD_MASK;
8064 debug(F101,"ttgspd spd_flags","",spd_flags);
8065 #endif /* OLINUXHISPEED */
8068 x = ioctl(ttyfd,TCGETA,&ttcur);
8069 debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
8070 debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
8071 if (x < 0) return(-1);
8072 s = ttcur.c_cflag & CBAUD;
8073 debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
8076 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
8077 debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
8078 if (x < 0) return(-1);
8080 debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
8082 x = gtty(ttyfd,&ttcur);
8083 debug(F101,"ttgspd gtty 2 x","",x);
8084 debug(F101,"ttgspd gtty 2 errno","",errno);
8085 if (x < 0) return(-1);
8086 s = ttcur.sg_ospeed;
8087 debug(F101,"ttgspd gtty 2 speed","",s);
8088 #endif /* BELLV10 */
8090 #endif /* BSD44ORPOSIX */
8092 debug(F101,"ttgspd code","",s);
8093 #ifdef OLINUXHISPEED
8094 debug(F101,"ttgspd spd_flags","",spd_flags);
8095 #endif /* OLINUXHISPEED */
8098 case B0: ss = 0L; break;
8103 MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
8104 etc, making for many "duplicate case in switch" errors, which are fatal.
8107 case B50: ss = 50L; break;
8110 case B75: ss = 75L; break;
8115 case B110: ss = 110L; break;
8120 case B134: ss = 134L; break;
8123 case B150: ss = 150L; break;
8128 case B200: ss = 200L; break;
8132 case B300: ss = 300L; break;
8136 case B600: ss = 600L; break;
8140 case B1200: ss = 1200L; break;
8144 case B1800: ss = 1800L; break;
8148 case B2400: ss = 2400L; break;
8152 case B4800: ss = 4800L; break;
8156 case B7200: ss = 7200L; break;
8160 case B9600: ss = 9600L; break;
8164 case B19200: ss = 19200L; break;
8167 case EXTA: ss = 19200L; break;
8175 #ifdef OLINUXHISPEED
8177 case ASYNC_SPD_HI: ss = 57600L; break;
8178 case ASYNC_SPD_VHI: ss = 115200L; break;
8180 #endif /* OLINUXHISPEED */
8184 case EXTB: ss = 38400L; break;
8191 case _B57600: ss = 57600L; break;
8192 #endif /* _B57600 */
8194 case _B115200: ss = 115200L; break;
8195 #endif /* _B115200 */
8198 case B57600: ss = 57600L; break;
8201 case B76800: ss = 76800L; break;
8204 case B115200: ss = 115200L; break;
8205 #endif /* B115200 */
8207 case B153600: ss = 153600L; break;
8208 #endif /* B153600 */
8210 case B230400: ss = 230400L; break;
8211 #endif /* B230400 */
8213 case B307200: ss = 307200L; break;
8214 #endif /* B307200 */
8216 case B460800: ss = 460800L; break;
8217 #endif /* B460800 */
8220 case B921600: ss = 921600L; break;
8221 #endif /* B921600 */
8226 debug(F101,"ttgspd speed","",ss);
8229 #endif /* USETCSETSPEED */
8230 #endif /* NOLOCAL */
8232 #ifdef MINIX2 /* Another hack alert */
8237 FIONREAD data type... This has been defined as "long" for many, many
8238 years, and it worked OK until 64-bit platforms appeared. Thus we use
8239 int for 64-bit platforms, but keep long for the others. If we changed
8240 the default PEEKTYPE to int, this would probably break 16-bit builds
8241 (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
8242 of which we have no way of testing any more. Therefore, do not change
8243 the default definition of PEEKTYPE -- only add exceptions to it as needed.
8248 #endif /* FIONREAD */
8249 /* #define FIONREAD TIOCQUERY */
8250 /* #define PEEKTYPE int */
8251 #else /* Not COHERENT... */
8253 #ifdef OSF32 /* Digital UNIX 3.2 or higher */
8254 #define PEEKTYPE int
8256 #define PEEKTYPE long /* Elsewhere (see notes above) */
8258 #endif /* COHERENT */
8260 /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
8264 /* Private buffer for myread() and its companions. Not for use by anything
8265 * else. ttflui() is allowed to reset them to initial values. ttchk() is
8266 * allowed to read my_count.
8268 * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
8270 * A global parity mask variable could be useful too. We could use it to
8271 * let myread() strip the parity on its own, instead of stripping sign
8272 * bits as it does now.
8275 #define MYBUFLEN 32768
8278 #define MYBUFLEN 256
8280 #define MYBUFLEN 1024
8282 #endif /* BIGBUFOK */
8286 #define MYBUFLEN 256
8288 On X.25 connections, there is an extra control byte at the beginning.
8290 static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */
8291 static CHAR *mybuf = x25buf+1;
8293 static CHAR mybuf[MYBUFLEN];
8296 static int my_count = 0; /* Number of chars still in mybuf */
8297 static int my_item = -1; /* Last index read from mybuf[] */
8299 /* T T P E E K -- Peek into our internal communications input buffers. */
8302 NOTE: This routine is peculiar to UNIX, and is used only by the
8303 select()-based CONNECT module, ckucns.c. It need not be replicated in
8304 the ck?tio.c of other platforms.
8316 #endif /* TTLEBUF */
8325 /* myread() -- Efficient read of one character from communications line.
8327 * NOTE: myread() and its helpers mygetbuf() and myfillbuf() return raw
8328 * bytes from connection, so when the connection is encrypted, these bytes
8329 * must be decrypted.
8331 * Uses a private buffer to minimize the number of expensive read() system
8332 * calls. Essentially performs the equivalent of read() of 1 character, which
8333 * is then returned. By reading all available input from the system buffers
8334 * to the private buffer in one chunk, and then working from this buffer, the
8335 * number of system calls is reduced in any case where more than one character
8336 * arrives during the processing of the previous chunk, for instance high
8337 * baud rates or network type connections where input arrives in packets.
8338 * If the time needed for a read() system call approaches the time for more
8339 * than one character to arrive, then this mechanism automatically compensates
8340 * for that by performing bigger read()s less frequently. If the system load
8341 * is high, the same mechanism compensates for that too.
8343 * myread() is a macro that returns the next character from the buffer. If the
8344 * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
8347 * This should be efficient enough for any one-character-at-a-time loops.
8348 * For even better efficiency you might use memcpy()/bcopy() or such between
8349 * buffers (since they are often better optimized for copying), but it may not
8350 * be worth it if you have to take an extra pass over the buffer to strip
8351 * parity and check for CTRL-C anyway.
8353 * Note that if you have been using myread() from another program module, you
8354 * may have some trouble accessing this macro version and the private variables
8355 * it uses. In that case, just add a function in this module, that invokes the
8358 #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
8360 /* Specification: Push back up to one character onto myread()'s queue.
8362 * This implementation: Push back characters into mybuf. At least one character
8363 * must have been read through myread() before myunrd() may be used. After
8364 * EOF or read error, again, myunrd() can not be used. Sometimes more than
8365 * one character can be pushed back, but only one character is guaranteed.
8366 * Since a previous myread() must have read its character out of mybuf[],
8367 * that guarantees that there is space for at least one character. If push
8368 * back was really needed after EOF, a small addition could provide that.
8370 * As of 02/2007 myunrd() is used by ttinl().
8377 #endif /* CK_ANSIC */
8380 mybuf[my_item--] = ch;
8385 /* T T P U S H B A C K -- Put n bytes back into the myread buffer */
8387 static CHAR * pushbuf = NULL;
8388 /* static int pushed = 0; */
8391 ttpushback(s,n) CHAR * s; int n; {
8392 debug(F101,"ttpushback n","",n);
8393 if (pushbuf || n > MYBUFLEN || n < 1)
8395 debug(F101,"ttpushback my_count","",my_count);
8397 if (!(pushbuf = (CHAR *)malloc(n+1)))
8399 memcpy(pushbuf,mybuf,my_count);
8400 /* pushed = my_count; */ /* (set but never used) */
8408 /* mygetbuf() -- Fill buffer for myread() and return first character.
8410 * This function is what myread() uses when it can't get the next character
8411 * directly from its buffer. First, it calls a system dependent myfillbuf()
8412 * to read at least one new character into the buffer, and then it returns
8413 * the first character just as myread() would have done. This function also
8414 * is responsible for all error conditions that myread() can indicate.
8416 * Returns: When OK => a positive character, 0 or greater.
8418 * When error => -3, error code in errno.
8420 * Older myread()s additionally returned -1 to indicate that there was nothing
8421 * to read, upon which the caller would call myread() again until it got
8422 * something. The new myread()/mygetbuf() always gets something. If it
8423 * doesn't, then make it do so! Any program that actually depends on the old
8424 * behaviour will break.
8426 * The older version also used to return -2 both for EOF and other errors,
8427 * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
8428 * other errors now return different results, although Kermit currently never
8429 * checks to see which it was. It just disconnects in both cases.
8431 * Kermit lets the user use the quit key to perform some special commands
8432 * during file transfer. This causes read(), and thus also mygetbuf(), to
8433 * finish without reading anything and return the EINTR error. This should
8434 * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
8435 * but if there is nothing to read, this could delay Kermit's reaction to
8436 * the command, and make Kermit appear unresponsive.
8438 * The debug() call should be removed for optimum performance.
8445 if (deblog && my_count > 0)
8446 debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
8449 my_count = myfillbuf();
8453 if (deblog) debug(F101, "mygetbuf read", "", my_count);
8455 ckhexdump("mygetbuf read", mybuf, my_count);
8456 #endif /* COMMENT */
8459 if (my_count <= 0) {
8462 debug(F101,"mygetbuf errno","",errno);
8464 if (netconn && ttnet == NET_TCPB && errno != 0) {
8465 if (errno != EINTR) {
8466 debug(F101,"mygetbuf TCP error","",errno);
8467 ttclos(0); /* Close the connection. */
8471 #endif /* TCPSOCKET */
8472 if (!netconn && xlocal && errno) {
8473 if (errno != EINTR) {
8474 debug(F101,"mygetbuf SERIAL error","",errno);
8476 ttclos(0); /* Close the connection. */
8479 return((x < 0) ? -3 : -2);
8482 return((unsigned)(0xff & mybuf[my_item = 0]));
8486 * System-dependent read() into mybuf[], as many characters as possible.
8488 * Returns: OK => number of characters read, always more than zero.
8490 * Error => -1, error code in errno.
8492 * If there is input available in the system's buffers, all of it should be
8493 * read into mybuf[] and the function return immediately. If no input is
8494 * available, it should wait for a character to arrive, and return with that
8495 * one in mybuf[] as soon as possible. It may wait somewhat past the first
8496 * character, but be aware that any such delay lengthens the packet turnaround
8497 * time during kermit file transfers. Should never return with zero characters
8498 * unless EOF or irrecoverable read error.
8500 * Correct functioning depends on the correct tty parameters being used.
8501 * Better control of current parameters is required than may have been the
8502 * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
8503 * no longer be sometimes off and sometimes on like it used to, unless a
8504 * special myfillbuf() is written to handle that. Otherwise the ordinary
8505 * myfillbuf()s may think they have come to EOF.
8507 * If your system has a facility to directly perform the functioning of
8508 * myfillbuf(), then use it. If the system can tell you how many characters
8509 * are available in its buffers, then read that amount (but not less than 1).
8510 * If the system can return a special indication when you try to read without
8511 * anything to read, while allowing you to read all there is when there is
8512 * something, you may loop until there is something to read, but probably that
8513 * is not good for the system load.
8517 /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
8518 * and CLOCAL set any way you like. This way, read() will do exactly
8519 * what is required by myfillbuf(): If there is data in the buffers
8520 * of the O.S., all available data is read into mybuf, up to the size
8521 * of mybuf. If there is none, the first character to arrive is
8522 * awaited and returned.
8535 /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */
8536 /* necessary for the sxa E50, but it is. */
8537 return read(fd, mybuf, 255);
8543 n = netxin(sizeof(mybuf), (char *)mybuf);
8544 debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
8547 #endif /* NETCONN */
8548 n = read(fd, mybuf, sizeof(mybuf));
8549 debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
8554 #else /* BEOSORBEBOX */
8556 /* debug(F101,"SVORPOSIX myfillbuf calling read() fd","",fd); */
8558 if (netconn && (nettype == NET_IX25)) {
8559 /* can't use sizeof because mybuf is a pointer, and not an array! */
8560 n = x25xin( MYBUFLEN, mybuf );
8565 if (ssl_active_flag || tls_active_flag) {
8567 debug(F100,"myfillbuf calling SSL_read() fd","",0);
8569 if (ssl_active_flag)
8570 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8571 else if (tls_active_flag)
8572 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8575 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8576 case SSL_ERROR_NONE:
8583 case SSL_ERROR_WANT_WRITE:
8584 case SSL_ERROR_WANT_READ:
8586 case SSL_ERROR_SYSCALL:
8589 case SSL_ERROR_WANT_X509_LOOKUP:
8591 case SSL_ERROR_ZERO_RETURN:
8602 if (ttnproto == NP_EK4LOGIN) {
8603 debug(F101,"myfillbuf calling krb4_des_read() fd","",ttyfd);
8604 if ((n = krb4_des_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8609 #endif /* RLOGCODE */
8613 if (ttnproto == NP_EK5LOGIN) {
8614 debug(F101,"myfillbuf calling krb5_des_read() fd","",ttyfd);
8615 if ((n = krb5_des_read(ttyfd,(char *)mybuf,sizeof(mybuf),0)) < 0)
8620 #endif /* RLOGCODE */
8622 if (ttnproto == NP_K5U2U) {
8623 debug(F101,"myfillbuf calling krb5_u2u_read() fd","",ttyfd);
8624 if ((n = krb5_u2u_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8629 #endif /* KRB5_U2U */
8631 #endif /* CK_KERBEROS */
8635 /* Special handling for HP-UX pty i/o */
8637 if (ttpty && pty_trap_pending(ttyfd) > 0) {
8638 debug(F101,"myfillbuf calling pty_trap_handler() fd","",ttyfd);
8639 if (pty_trap_handler(ttyfd) > 0) {
8644 #endif /* HAVE_PTYTRAP */
8646 debug(F101,"myfillbuf calling read() fd","",ttyfd);
8647 n = read(fd, mybuf, sizeof(mybuf));
8648 debug(F101,"SVORPOSIX myfillbuf read","",n);
8649 debug(F101,"SVORPOSIX myfillbuf errno","",errno);
8650 debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
8654 /* When we have a PTY trap in place the connection cannot */
8655 /* be closed until the trap receives a close indication. */
8656 if (n == 0 && ttpty)
8658 #endif /* HAVE_PTYTRAP */
8663 #endif /* BEOSORBEBOX */
8667 #else /* not AT&T or POSIX */
8670 /* This is quoted from the old myread(). The semantics seem to be
8671 * alright, but maybe errno would not need to be set even when
8672 * there is no error? I don't know aegis.
8684 count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
8686 if (st.all == ios_$get_conditional_failed) /* get at least one */
8687 count = ios_$get((short)fd, 0, mybuf, 1L, st);
8688 if (st.all == ios_$end_of_file)
8690 else if (st.all != status_$ok) {
8694 return(count > 0 ? count : -3);
8699 /* This is for systems with FIONREAD. FIONREAD returns the number
8700 * of characters available for reading. If none are available, wait
8701 * until something arrives, otherwise return all there is.
8716 SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
8717 Depends on SunOS having FIONREAD, not because we use it, but just so this
8718 code is grouped correctly within the #ifdefs. Let's hope Solaris keeps it.
8720 We call x25xin() instead of read() so that Q-Bit packets, which contain
8721 X.25 service-level information (e.g. PAD parameter changes), can be processed
8722 transparently to the upper-level code. This is a blocking read, and so
8723 we depend on higher-level code (such as ttinc()) to set any necessary alarms.
8726 if (netconn && nettype == NET_SX25) {
8727 while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
8728 return(x - 1); /* "-1" compensates for extra status byte */
8733 if (ssl_active_flag || tls_active_flag) {
8736 if (ssl_active_flag)
8737 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8739 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8740 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8741 case SSL_ERROR_NONE:
8748 case SSL_ERROR_WANT_WRITE:
8749 case SSL_ERROR_WANT_READ:
8751 case SSL_ERROR_SYSCALL:
8754 case SSL_ERROR_WANT_X509_LOOKUP:
8756 case SSL_ERROR_ZERO_RETURN:
8767 if (ttnproto == NP_EK4LOGIN) {
8768 if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8773 #endif /* RLOGCODE */
8777 if (ttnproto == NP_EK5LOGIN) {
8778 if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8783 #endif /* RLOGCODE */
8785 if (ttnproto == NP_K5U2U) {
8786 if ((x = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8791 #endif /* KRB5_U2U */
8793 #endif /* CK_KERBEROS */
8796 debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
8797 x = ioctl(fd, FIONREAD, &avail);
8800 debug(F101,"myfillbuf FIONREAD","",x);
8801 debug(F101,"myfillbuf FIONREAD avail","",avail);
8802 debug(F101,"myfillbuf FIONREAD errno","",errno);
8805 if (x < 0 || avail == 0)
8808 if (avail > MYBUFLEN)
8813 x = read(fd, mybuf, (int) avail);
8816 debug(F101,"myfillbuf avail","",avail);
8817 debug(F101,"myfillbuf read","",x);
8818 debug(F101,"myfillbuf read errno","",errno);
8820 ckhexdump("myfillbuf mybuf",mybuf,x);
8823 if (x < 1) x = -3; /* read 0 == connection loss */
8827 #else /* !FIONREAD */
8828 /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
8829 /* When there is no other possibility, read 1 character at a time. */
8835 if (ssl_active_flag || tls_active_flag) {
8838 if (ssl_active_flag)
8839 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8841 count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8842 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8843 case SSL_ERROR_NONE:
8850 case SSL_ERROR_WANT_WRITE:
8851 case SSL_ERROR_WANT_READ:
8853 case SSL_ERROR_SYSCALL:
8856 case SSL_ERROR_WANT_X509_LOOKUP:
8858 case SSL_ERROR_ZERO_RETURN:
8869 if (ttnproto == NP_EK4LOGIN) {
8870 if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8875 #endif /* RLOGCODE */
8879 if (ttnproto == NP_EK5LOGIN) {
8880 if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8885 #endif /* RLOGCODE */
8887 if (ttnproto == NP_K5U2U) {
8888 if ((len = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8893 #endif /* KRB5_U2U */
8895 #endif /* CK_KERBEROS */
8903 x = read(fd, mybuf, 1);
8904 return(x > 0 ? x : -3);
8907 #endif /* !FIONREAD */
8913 /* T T _ T N O P T -- Handle Telnet negotions in incoming data */
8915 Call with the IAC that was encountered.
8917 -3: If connection has dropped or gone bad.
8918 -2: On Telnet protocol error resulting in inconsistent states.
8919 0: If negotiation OK and caller has nothing to do.
8920 1: If packet start character has changed (new value is in global stchr).
8921 255: If there was a quoted IAC as data.
8922 or: Not at all if we got a legitimate Telnet Logout request.
8926 tt_tnopt(n) int n; { /* Handle Telnet options */
8927 /* In case caller did not already check these conditions... */
8929 ((xlocal && netconn && IS_TELNET()) ||
8930 (!xlocal && sstelnet))) {
8933 debug(F100,"ttinl calling tn_doop()","",0);
8934 tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
8935 debug(F111,"ttinl tn_doop() returned","tx",tx);
8939 case -1: /* I/O error */
8940 ttimoff(); /* Turn off timer */
8942 case -2: /* Connection failed. */
8944 ttimoff(); /* Turn off timer */
8947 case 1: /* ECHO change */
8950 case 2: /* ECHO change */
8953 case 3: /* Quoted IAC */
8955 return((unsigned)255);
8958 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
8962 ) { /* Remote in Server mode */
8963 ttimoff(); /* Turn off timer */
8964 debug(F100,"u_start and !inserver","",0);
8965 return(-2); /* End server mode */
8966 } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
8968 ) { /* I'm no longer in Server Mode */
8969 debug(F100,"me_start and server","",0);
8975 case 5: { /* Start character change */
8976 /* extern CHAR stchr; */
8977 /* start = stchr; */
8980 #endif /* IKS_OPTION */
8981 case 6: /* Remote Logout */
8985 if (inserver && !local)
8986 doexit(GOOD_EXIT,0);
8996 #endif /* TCPSOCKET */
8998 /* T T F L U I -- Flush tty input buffer */
9001 ttflux() { /* But first... */
9004 Flush internal MYREAD buffer.
9008 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
9009 (!xlocal && sstelnet)));
9010 #endif /* TCPSOCKET */
9011 debug(F101,"ttflux my_count","",my_count);
9015 while (my_count > 0) {
9017 #ifdef CK_ENCRYPTION
9018 if (TELOPT_U(TELOPT_ENCRYPTION))
9019 ck_tn_decrypt((char *)&ch,1);
9020 #endif /* CK_ENCRYPTION */
9025 #endif /* TCPSOCKET */
9027 #ifdef CK_ENCRYPTION
9028 if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
9029 ck_tn_decrypt(&mybuf[my_item+1],my_count);
9030 #endif /* CK_ENCRYPTION */
9031 #endif /* COMMENT */
9032 my_count = 0; /* Reset count to zero */
9033 my_item = -1; /* And buffer index to -1 */
9042 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
9043 (!xlocal && sstelnet)));
9044 #endif /* TCPSOCKET */
9054 ttpush = -1; /* Clear the peek-ahead char */
9055 while (le_data && (le_inbuf() > 0)) {
9057 if (le_getchar(&ch) > 0) { /* Clear any more... */
9058 debug(F101,"ttflui le_inbuf ch","",ch);
9061 #endif /* TTLEBUF */
9062 debug(F101,"ttflui ttpipe","",ttpipe);
9066 Flush internal MYREAD buffer *NEXT*, in all cases.
9072 /* Network flush is done specially, in the network support module. */
9073 if ((netconn || sstelnet) && !ttpipe && !ttpty) {
9074 debug(F100,"ttflui netflui","",0);
9078 tnc_send_purge_data(TNC_PURGE_RECEIVE);
9079 #endif /* TN_COMPORT */
9080 #endif /* COMMENT */
9083 #endif /* NETCONN */
9085 debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
9090 sio_$control((short)yfd, sio_$flush_in, true, st);
9091 if (st.all != status_$ok) {
9092 fprintf(stderr, "flush failed: "); error_$print(st);
9093 } else { /* sometimes the flush doesn't work */
9096 /* eat all the characters that shouldn't be available */
9097 ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
9098 if (st.all == ios_$get_conditional_failed) break;
9099 fprintf(stderr, "flush failed(2): "); error_$print(st);
9103 #ifdef BSD44 /* 4.4 BSD */
9104 n = FREAD; /* Specify read queue */
9105 debug(F100,"ttflui BSD44","",0);
9106 ioctl(fd,TIOCFLUSH,&n);
9109 #undef POSIX /* Uh oh... */
9111 #ifdef POSIX /* POSIX */
9112 debug(F100,"ttflui POSIX","",0);
9113 tcflush(fd,TCIFLUSH);
9115 #ifdef ATTSV /* System V */
9117 debug(F100,"ttflui ATTSV","",0);
9120 #else /* Not BSD44, POSIX, or Sys V */
9121 #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */
9122 #ifdef ANYBSD /* Berkeley */
9123 n = FREAD; /* Specify read queue */
9124 debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
9125 ioctl(fd,TIOCFLUSH,&n);
9126 #else /* Others (V7, etc) */
9127 debug(F100,"ttflui TIOCFLUSH","",0);
9128 ioctl(fd,TIOCFLUSH,0);
9130 #else /* All others... */
9132 No system call (that we know about) for input buffer flushing.
9133 So see how many there are and read them in a loop, using ttinc().
9134 ttinc() is buffered, so we're not getting charged with a system call
9135 per character, just a function call.
9137 if ((n = ttchk()) > 0) {
9138 debug(F101,"ttflui read loop","",n);
9139 while ((n--) && ttinc(0) > 0) ;
9141 #endif /* TIOCFLUSH */
9153 ttfluo() { /* Flush output buffer */
9166 return(tcflush(fd,TCOFLUSH));
9169 return(ioctl(fd,TCFLSH,1));
9171 return(0); /* All others, nothing */
9177 /* Interrupt Functions */
9179 /* Set up terminal interrupts on console terminal */
9181 #ifndef FIONREAD /* We don't need esctrp() */
9182 #ifndef SELECT /* if we have any of these... */
9189 esctrp(foo) int foo; { /* trap console escapes (^\) */
9190 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9192 debug(F101,"esctrp caught SIGQUIT","",conesc);
9194 #endif /* SVORPOSIX */
9200 esctrp(foo) int foo; { /* trap console escapes (^\) */
9201 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9203 debug(F101,"esctrp caught SIGQUIT","",conesc);
9210 esctrp(foo) int foo; { /* trap console escapes (^\) */
9212 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9217 #endif /* CK_POLL */
9219 #endif /* FIONREAD */
9221 /* C O N B G T -- Background Test */
9223 static int jc = 0; /* 0 = no job control */
9226 Call with flag == 1 to prevent signal test, which can not be expected
9227 to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
9229 Call with flag == 0 to use the signal test, but only if the process-group
9230 test fails, as it does on some UNIX systems, where getpgrp() is buggy,
9231 requires an argument when the man page says it doesn't, or vice versa.
9233 If flag == 0 and the process-group test fails, then we determine background
9234 status simply (but not necessarily reliably) from isatty().
9236 conbgt() sets the global backgrd = 1 if we appear to be in the background,
9237 and to 0 if we seem to be in the foreground. conbgt() is highly prone to
9241 conbgt(flag) int flag; {
9242 int x = -1, /* process group or SIGINT test */
9243 y = 0; /* isatty() test */
9245 Check for background operation, even if not running on real tty, so that
9246 background flag can be set correctly. If background status is detected,
9247 then Kermit will not issue its interactive prompt or most messages.
9248 If your prompt goes away, you can blame (and fix?) this function.
9251 /* Use process-group test if possible. */
9253 #ifdef POSIX /* We can do it in POSIX */
9256 #ifdef BSD4 /* and in BSD 4.x. */
9259 #ifdef HPUXJOBCTL /* and in most HP-UX's */
9262 #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
9264 #endif /* TIOCGPGRP */
9265 #endif /* HPUXJOBCTL */
9269 #ifdef MIPS /* Except if it doesn't work... */
9279 Semi-reliable process-group test. Check whether this process's group is
9280 the same as the controlling terminal's process group. This works if the
9281 getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
9283 PID_T mypgrp = (PID_T)0; /* Kermit's process group */
9284 PID_T ctpgrp = (PID_T)0; /* The terminal's process group */
9285 #ifndef _POSIX_SOURCE
9287 The getpgrp() prototype is obtained from system header files for POSIX
9288 and Sys V R4 compilations. Other systems, who knows. Some complain about
9289 a duplicate declaration here, others don't, so it's safer to leave it in
9290 if we don't know for certain.
9295 extern PID_T getpgrp();
9297 #endif /* PS2AIX10 */
9299 #endif /* _POSIX_SOURCE */
9301 /* Get my process group. */
9303 #ifdef SVR3 /* Maybe this should be ATTSV? */
9304 /* This function is not described in SVID R2 */
9306 /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
9310 /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
9314 /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
9318 /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
9320 #ifdef OSF32 /* (was OSF40) */
9322 /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
9323 #else /* BSD, V7, etc */
9327 mypgrp = getpgrp(0);
9329 /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
9337 /* MINIX does not support job control so Kermit is always in foreground */
9340 #else /* Not MINIX */
9342 /* Now get controlling tty's process group */
9344 ctpgrp = tcgetpgrp(1); /* The POSIX way */
9345 /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
9347 ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
9348 /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
9349 #endif /* BSD44ORPOSIX */
9351 if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
9352 x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
9353 else x = -1; /* If error, remember. */
9354 debug(F101,"conbgt process group test","",x);
9355 #endif /* PGROUP_T */
9358 /* Try to see if job control is available */
9360 #ifdef NOJC /* User override */
9361 jc = 0; /* No job control allowed */
9362 debug(F111,"NOJC","jc",jc);
9367 #ifdef SVR4ORPOSIX /* POSIX actually tells us */
9368 debug(F100,"SVR4ORPOSIX jc test...","",0);
9369 #ifdef _SC_JOB_CONTROL
9376 jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
9378 debug(F101,"sysconf fails, jcshell","",jcshell);
9379 jc = (jchdlr == SIG_DFL) ? 1 : 0;
9381 debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
9382 #endif /* __386BSD__ */
9383 #endif /* __bsdi__ */
9385 #ifdef _POSIX_JOB_CONTROL
9386 jc = 1; /* By definition */
9387 debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
9389 jc = 0; /* Assume job control not allowed */
9390 debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
9391 #endif /* _POSIX_JOB_CONTROL */
9392 #endif /* _SC_JOB_CONTROL */
9395 jc = 1; /* Job control allowed */
9396 debug(F111,"BSD job control","jc",jc);
9399 jc = 1; /* JC allowed */
9400 debug(F111,"SVR3 job control","jc",jc);
9403 jc = 1; /* JC allowed */
9404 debug(F111,"X/OS job control","jc",jc);
9407 jc = 1; /* JC allowed */
9408 debug(F111,"HP-UX 9.0 job control","jc",jc);
9411 jc = 1; /* JC allowed */
9412 debug(F111,"HP-UX 10.0 job control","jc",jc);
9414 jc = 0; /* JC not allowed */
9415 debug(F111,"job control catch-all","jc",jc);
9421 #endif /* SVR4ORPOSIX */
9424 debug(F101,"conbgt jc","",jc);
9426 debug(F101,"conbgt jcshell","",jcshell);
9428 At this point, if jc == 1 but jcshell == 0, it means that the OS supports
9429 job control, but the shell or other process we are running under does not
9430 (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
9431 will come of it. So...
9434 if (jc > 0 && jcshell == 0) jc = 0;
9438 Another background test.
9439 Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
9440 which is done by the shell (sh) if the program is started with '&'.
9441 Unfortunately, this is NOT done by csh or ksh so watch out!
9442 Note, it's safe to set SIGINT to SIG_IGN here, because further down
9443 we always set it to something else.
9444 Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
9447 if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
9449 SIGTYP (*osigint)();
9451 osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
9453 x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
9454 /* debug(F101,"conbgt osigint","",osigint); */
9455 /* debug(F101,"conbgt signal test","",x); */
9458 /* Also check to see if we're running with redirected stdio. */
9459 /* This is not really background operation, but we want to act as though */
9463 if (inserver) { /* Internet Kermit Server */
9464 backgrd = 0; /* is not in the background */
9469 y = (isatty(0) && isatty(1)) ? 1 : 0;
9470 debug(F101,"conbgt isatty test","",y);
9473 /* The process group and/or signal test doesn't work under these... */
9486 backgrd = (x || !y) ? 1 : 0;
9492 debug(F101,"conbgt backgrd","",backgrd);
9495 /* C O N I N T -- Console Interrupt setter */
9498 First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
9499 Second arg is pointer to function to handle SIGTSTP (suspend).
9502 VOID /* Set terminal interrupt traps. */
9505 conint(f,s) SIGTYP (*f)(), (*s)();
9507 conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
9510 conint(f,s) SIGTYP (*f)(), (*s)();
9511 #endif /* CK_ANSIC */
9514 debug(F101,"conint conistate","",conistate);
9516 conbgt(0); /* Do background test. */
9518 /* Set the desired handlers for hangup and software termination. */
9521 signal(SIGTERM,f); /* Software termination */
9522 #endif /* SIGTERM */
9525 Prior to July 1999 we used to call sighup() here but now it's called in
9526 sysinit() so SIGHUP can be caught during execution of the init file or
9530 /* Now handle keyboard stop, quit, and interrupt signals. */
9531 /* Check if invoked in background -- if so signals set to be ignored. */
9532 /* However, if running under a job control shell, don't ignore them. */
9533 /* We won't be getting any, as we aren't in the terminal's process group. */
9535 debug(F101,"conint backgrd","",backgrd);
9536 debug(F101,"conint jc","",jc);
9538 if (backgrd && !jc) { /* In background, ignore signals */
9539 debug(F101,"conint background ignoring signals, jc","",jc);
9541 signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
9542 #endif /* SIGTSTP */
9543 signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
9544 signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
9546 conistate = CONI_NOI;
9547 } else { /* Else in foreground or suspended */
9548 debug(F101,"conint foreground catching signals, jc","",jc);
9549 signal(SIGINT,f); /* Catch terminal interrupt */
9550 sigint_ign = (f == SIG_IGN) ? 1 : 0;
9552 #ifdef SIGTSTP /* Keyboard stop (suspend) */
9553 /* debug(F101,"conint SIGSTSTP","",s); */
9554 if (s == NULL) s = SIG_DFL;
9555 #ifdef NOJC /* No job control allowed. */
9556 signal(SIGTSTP,SIG_IGN);
9557 #else /* Job control allowed */
9558 if (jc) /* if available. */
9561 signal(SIGTSTP,SIG_IGN);
9563 #endif /* SIGTSTP */
9567 #ifndef FIONREAD /* Watch out, we don't know this... */
9571 signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
9573 #endif /* CK_POLL */
9575 #endif /* FIONREAD */
9576 if (conesc) conesc = 0; /* Clear out pending escapes */
9579 signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
9580 if (conesc) conesc = 0;
9583 signal(SIGQUIT,f); /* Apollo, catch it like others. */
9585 signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
9588 #endif /* SVORPOSIX */
9590 conistate = CONI_INT;
9595 /* C O N N O I -- Reset console terminal interrupts */
9598 connoi() { /* Console-no-interrupts */
9600 debug(F101,"connoi conistate","",conistate);
9602 signal(SIGTSTP,SIG_IGN); /* Suspend */
9603 #endif /* SIGTSTP */
9604 conint(SIG_IGN,SIG_IGN); /* Interrupt */
9605 sigint_ign = 1; /* Remember we did this ourselves */
9607 signal(SIGQUIT,SIG_IGN); /* Quit */
9608 #endif /* SIGQUIT */
9610 signal(SIGTERM,SIG_IGN); /* Term */
9611 #endif /* SIGTERM */
9612 conistate = CONI_NOI;
9615 /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */
9619 Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
9620 eliminates blocking on a read, because we can read /dev/kmem to get the
9621 number of characters available for raw input. If your system can't
9622 or you won't let the world read /dev/kmem then you must figure out a
9623 different way to do the counting of characters available, or else replace
9624 this by a dummy function that always returns 0.
9627 * Call this routine as: initrawq(tty)
9628 * where tty is the file descriptor of a terminal. It will return
9629 * (as a char *) the kernel-mode memory address of the rawq character
9630 * count, which may then be read. It has the side-effect of flushing
9631 * input on the terminal.
9634 * John Mackin, Physiology Dept., University of Sydney (Australia)
9635 * ...!decvax!mulga!physiol.su.oz!john
9637 * Permission is hereby granted to do anything with this code, as
9638 * long as this comment is retained unmodified and no commercial
9639 * advantage is gained.
9645 #include <sys/proc.h>
9646 #endif /* COHERENT */
9652 #include <sys/proc.h>
9653 #endif /* COHERENT */
9656 initrawq(tty) int tty; {
9670 static struct nlist nl[] = {
9675 static struct proc *pp;
9679 NPTYPE xproc; /* Its type is defined in makefile. */
9683 if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
9684 nlist(BOOTNAME, nl);
9685 if (nl[0].n_type == 0) err("proc array");
9687 if (nl[1].n_type == 0) err("nproc");
9689 lseek(m, (long)(nl[1].n_value), 0);
9690 read (m, &xproc, sizeof(xproc));
9691 saval = signal(SIGALRM, catch);
9692 if ((pid = fork()) == 0) {
9698 if(setjmp(jjbuf) == 0) {
9702 signal(SIGALRM, SIG_DFL);
9705 pp = (struct proc *) nl[0].n_value;
9707 if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
9708 if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
9710 lseek(m, (long)(nl[1].n_value), 0);
9711 read(m, &xproc, sizeof(xproc));
9713 if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
9714 if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
9715 if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
9716 err("read proc table");
9717 for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
9718 if (pp -> p_pid == (short) pid) goto iout;
9720 err("no such proc");
9724 qaddr = (char *)(pp -> p_wchan);
9735 /* More V7-support functions... */
9741 ckmakmsg(buf,200,"fatal error in initrawq: ", s, NULL, NULL);
9747 catch(foo) int foo; {
9752 /* G E N B R K -- Simulate a modem break. */
9766 genbrk(fn,msec) int fn, msec; {
9767 struct sgttyb ttbuf;
9768 int ret, sospeed, x, y;
9770 ret = ioctl(fn, TIOCGETP, &ttbuf);
9771 sospeed = ttbuf.sg_ospeed;
9772 ttbuf.sg_ospeed = BSPEED;
9773 ret = ioctl(fn, TIOCSETP, &ttbuf);
9774 y = (int)strlen(brnuls);
9775 x = ( BSPEED * 100 ) / msec;
9777 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9778 ttbuf.sg_ospeed = sospeed;
9779 ret = ioctl(fn, TIOCSETP, &ttbuf);
9780 ret = write(fn, "@", 1);
9787 genbrk(fn,msec) int fn, msec; {
9788 struct termios ttbuf;
9792 ret = tcgetattr(fn, &ttbuf);
9793 sospeed = ttbuf.c_ospeed;
9794 ttbuf.c_ospeed = BSPEED;
9795 ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
9796 y = (int)strlen(brnuls);
9797 x = ( BSPEED * 100 ) / msec;
9799 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9800 ttbuf.c_ospeed = sospeed;
9801 ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
9802 ret = write(fn, "@", 1);
9809 I N C H K -- Check if chars waiting to be read on given file descriptor.
9811 This routine is a merger of ttchk() and conchk().
9813 channel == 0 to check console.
9814 channel == 1 to check communications connection.
9816 fd = file descriptor.
9818 >= 0: number of characters waiting, 0 or greater,
9819 -1: on any kind of error,
9820 -2: if there is (definitely) no connection.
9821 Note: In UNIX we don't have to call nettchk() because a socket
9822 file descriptor works just like in serial i/o, ioctls and all.
9823 (But this will change if we add non-file-descriptor channels,
9824 such as IBM X.25 for AIX...)
9827 in_chk(channel, fd) int channel, fd; {
9828 int x, n = 0; /* Workers, n = return value */
9829 extern int clsondisc; /* Close on disconnect */
9831 The first section checks to make sure we have a connection,
9832 but only if we're in local mode.
9836 debug(F111,"in_chk entry",ckitoa(fd),channel);
9837 debug(F101,"in_chk ttyfd","",ttyfd);
9838 debug(F101,"in_chk ttpty","",ttpty);
9842 But don't say connection is gone if we have any buffered-stuff.
9845 debug(F101,"in_chk ttpush","",ttpush);
9853 #endif /* TTLEBUF */
9857 /* Special handling for HP-UX pty i/o */
9858 if (ttpty && pty_trap_pending(ttyfd) > 0) {
9859 if (pty_trap_handler(ttyfd) > 0) {
9864 #endif /* HAVE_PTYTRAP */
9867 if (channel) { /* Checking communications channel */
9868 if (ttyfd < 0) { /* No connection */
9869 return(-2); /* That's what this means */
9870 } else if (xlocal && /* In local mode */
9871 (!netconn /* Serial connection or */
9873 || istncomport() /* Telnet Com Port */
9874 #endif /* TN_COMPORT */
9875 ) && ttcarr != CAR_OFF /* with CARRIER WATCH ON (or AUTO) */
9879 Seems like this would be a good idea but it prevents C-Kermit from
9880 popping back to the prompt automatically when carrier drops. However,
9881 commenting this out prevents us from seeing the NO CARRIER message.
9884 && my_count < 1 /* Nothing in our internal buffer */
9886 #endif /* COMMENT */
9889 x = ttgmdm(); /* So get modem signals */
9890 debug(F101,"in_chk close-on-disconnect","",clsondisc);
9891 if (x > -1) { /* Check for carrier */
9892 if (!(x & BM_DCD)) { /* No carrier */
9893 debug(F101,"in_chk carrier lost","",x);
9894 if (clsondisc) /* If "close-on-disconnect" */
9895 ttclos(0); /* close device & release lock. */
9896 return(-2); /* This means "disconnected" */
9898 /* In case I/O to device after CD dropped always fails */
9899 /* as in Debian Linux 2.1 and Unixware 2.1... */
9901 debug(F101,"in_chk ttgmdm I/O error","",errno);
9902 debug(F101,"in_chk ttgmdm gotsigs","",gotsigs);
9903 if (gotsigs) { /* If we got signals before... */
9904 if (errno == 5 || errno == 6) { /* I/O error etc */
9905 if (clsondisc) /* like when modem hangs up */
9910 /* If we never got modem signals successfully on this */
9911 /* connection before, we can't conclude that THIS failure */
9912 /* means the connection was lost. */
9918 /* We seem to have a connection so now see if any bytes are waiting on it */
9921 if (ssl_active_flag || tls_active_flag) {
9922 n += SSL_pending(ssl_active_flag?ssl_con:tls_con);
9923 debug(F101,"in_chk SSL_pending","",n);
9934 /* It is not safe to read any data when using encrypted Klogin */
9935 if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
9937 if (ttnproto == NP_EK4LOGIN) {
9938 n += krb4_des_avail(ttyfd);
9939 debug(F101,"in_chk krb4_des_avail","",n);
9943 if (ttnproto == NP_EK5LOGIN) {
9944 n += krb5_des_avail(ttyfd);
9945 debug(F101,"in_chk krb5_des_avail","",n);
9948 if (ttnproto == NP_K5U2U) {
9949 n += krb5_u2u_avail(ttyfd);
9950 debug(F101,"in_chk krb5_des_avail","",n);
9952 #endif /* KRB5_U2U */
9954 if (n < 0) /* Is this right? */
9959 #endif /* CK_KERBEROS */
9960 #endif /* RLOGCODE */
9962 errno = 0; /* Reset this so we log good info */
9964 x = ioctl(fd, FIONREAD, &n); /* BSD and lots of others */
9965 #ifdef DEBUG /* (the more the better) */
9967 debug(F101,"in_chk FIONREAD return code","",x);
9968 debug(F101,"in_chk FIONREAD count","",n);
9969 debug(F101,"in_chk FIONREAD errno","",errno);
9972 #else /* FIONREAD not defined */
9974 Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
9975 with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
9976 portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
9977 that I looked at, but it is needed to prevent the call from blocking), and
9978 the msghdr struct differs from place to place, so we would need another
9979 avalanche of ifdefs. Still, when FIONREAD is not available, this is the
9980 only other known method of asking the OS for the *number* of characters
9981 available for reading.
9983 #ifdef V7 /* UNIX V7: look in kernel memory */
9985 n = 0; /* But not in MINIX */
9990 lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
9991 x = read(kmem[TTY], &n, sizeof(int));
9992 if (x != sizeof(int))
9998 x = ioctl(fd, TIOCQCNT, &ttbuf); /* DEC Pro/3xx Venix V.1 */
9999 n = ttbuf.sg_ispeed & 0377; /* Circa 1984 */
10004 Here we skip all the undependable and expensive calls below if we
10005 already have something in our internal buffer. This tends to work quite
10006 nicely, so the only really bad case remaining is the one in which neither
10007 FIONREAD or MYREAD are defined, which is increasingly rare these days.
10009 if (channel != 0 && my_count > 0) {
10010 debug(F101,"in_chk buf my_count","",my_count);
10011 n = my_count; /* n was 0 before we got here */
10014 #endif /* MYREAD */
10016 rdchk(), select(), and poll() tell us *if* data is available to be read, but
10017 not how much, so these should be used only as a final resort. Especially
10018 since these calls tend to add a lot overhead.
10020 #ifdef RDCHK /* This mostly SCO-specific */
10022 debug(F101,"in_chk rdchk","",n);
10023 #else /* No RDCHK */
10026 /* Only allows select on the console ... don't ask */
10030 fd_set rfds; /* Read file descriptors */
10032 FD_ZERO(rfds); /* Initialize them */
10033 FD_SET(fd,rfds); /* We want to look at this fd */
10035 FD_ZERO(&rfds); /* Initialize them */
10036 FD_SET(fd,&rfds); /* We want to look at this fd */
10037 tv.tv_sec = tv.tv_usec = 0L; /* A 0-valued timeval structure */
10038 #endif /* BELLV10 */
10040 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10041 debug(F101,"in_chk Plan 9 select","",n);
10044 n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
10045 debug(F101,"in_chk BELLV10 select","",n);
10048 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10049 debug(F101,"in_chk BSD44 select","",n);
10052 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10053 debug(F101,"in_chk BSD43 select","",n);
10056 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10057 debug(F101,"in_chk SOLARIS select","",n);
10060 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10061 debug(F101,"in_chk QNX6 select","",n);
10064 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10065 debug(F101,"in_chk QNX select","",n);
10068 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10069 debug(F101,"in_chk COHERENT select","",n);
10072 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10073 debug(F101,"in_chk SVR4 select","",n);
10076 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10077 debug(F101,"in_chk LINUX select","",n);
10079 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10080 debug(F101,"in_chk OSF select","",n);
10082 n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
10083 debug(F101,"in_chk catchall select","",n);
10085 #endif /* __linux__ */
10087 #endif /* COHERENT */
10090 #endif /* SOLARIS */
10093 #endif /* BELLV10 */
10096 #else /* Not SELECT */
10102 pfd.events = POLLIN;
10104 n = poll(&pfd, 1, 0);
10105 debug(F101,"in_chk poll","",n);
10106 if ((n > 0) && (pfd.revents & POLLIN))
10109 #endif /* CK_POLL */
10110 #endif /* SELECT */
10112 #endif /* PROVX1 */
10114 #endif /* FIONREAD */
10116 /* From here down, treat console and communication device differently... */
10118 if (channel == 0) { /* Console */
10126 This is the hideous hack used in System V and POSIX systems that don't
10127 support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
10128 CONNECT-mode escape character is attached to SIGQUIT. Used, obviously,
10129 only on the console.
10131 if (conesc) { /* Escape character typed == SIGQUIT */
10132 debug(F100,"in_chk conesc","",conesc);
10134 signal(SIGQUIT,esctrp); /* Restore signal */
10138 #endif /* CK_POLL */
10139 #endif /* SELECT */
10140 #endif /* FIONREAD */
10141 #endif /* SVORPOSIX */
10143 return(n); /* Done with console */
10146 if (channel != 0) { /* Communications connection */
10151 select() or rdchk(), etc, has told us that something is waiting, but we
10152 don't know how much. So we do a read to get it and then we know. Note:
10153 This read is NOT nonblocking if nothing is there (because of VMIN=1), but
10154 it should be safe in this case since the OS tells us at least one byte is
10155 waiting to be read, and MYREAD reads return as much as is there without
10156 waiting for any more. Controlled tests on Solaris and Unixware (with
10157 FIONREAD deliberately undefined) show this to be true.
10159 debug(F101,"in_chk read my_count","",my_count);
10160 debug(F101,"in_chk read n","",n);
10161 if (n > 0 && my_count == 0) {
10162 /* This also catches disconnects etc */
10163 /* Do what mygetbuf does except don't grab a character */
10164 my_count = myfillbuf();
10165 my_item = -1; /* ^^^ */
10166 debug(F101,"in_chk myfillbuf my_count","",my_count);
10170 n = 0; /* NB: n is replaced by my_count */
10172 #endif /* FIONREAD */
10174 Here we add whatever we think is unread to what is still in our
10175 our internal buffer. Thus the importance of setting n to 0 just above.
10177 debug(F101,"in_chk my_count","",my_count);
10178 debug(F101,"in_chk n","",n);
10181 #endif /* MYREAD */
10183 debug(F101,"in_chk result","",n);
10185 /* Errors here don't prove the connection has dropped so just say 0 */
10187 return(n < 0 ? 0 : n);
10191 /* T T C H K -- Tell how many characters are waiting in tty input buffer */
10200 #endif /* NETCMD */
10202 return(in_chk(1,fd));
10205 /* T T X I N -- Get n characters from tty input buffer */
10207 /* Returns number of characters actually gotten, or -1 on failure */
10209 /* Intended for use only when it is known that n characters are actually */
10210 /* Available in the input buffer. */
10213 ttxin(n,buf) int n; CHAR *buf; {
10214 register int x = 0, c = -2;
10216 register int i = 0;
10217 #endif /* TTLEBUF */
10220 if (n < 1) /* Nothing to do */
10225 buf[0] = ttpush; /* Put pushed char in buffer*/
10226 ttpush = -1; /* Clear the push buffer */
10228 return(ttxin(n-1, &buf[1]) + 1);
10233 while (le_inbuf() > 0) {
10234 if (le_getchar(&buf[i])) {
10240 return(ttxin(n,&buf[i])+i);
10244 #endif /* TTLEBUF */
10250 #endif /* NETCMD */
10254 if (netconn && (ttnet == NET_SX25)) /* X.25 connection */
10255 return(x25xin(n,buf));
10256 #endif /* SUNX25 */
10259 /* riehm: possibly not needed. Test worked with normal reads and writes */
10260 if (netconn && (ttnet == NET_IX25)) { /* X.25 connection */
10262 if (x > 0) buf[x] = '\0';
10265 #endif /* IBMX25 */
10268 debug(F101,"ttxin MYREAD","",n);
10272 debug(F101,"ttxin myread returns","",c);
10273 if (c == -3) x = -1;
10276 buf[x++] = c & ttpmsk;
10279 /* It is impossible to know how many characters are waiting */
10280 /* to be read when you are using Encrypted Rlogin or SSL */
10281 /* as the transport since the number of real data bytes */
10282 /* can be greater or less than the number of bytes on the */
10283 /* wire which is what ttchk() returns. */
10284 if (netconn && (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN))
10287 #endif /* CK_KERBEROS */
10288 #endif /* RLOGCODE */
10290 if (ssl_active_flag || tls_active_flag)
10293 #endif /* CK_SSL */
10296 debug(F101,"ttxin READ","",n);
10297 x = read(fd,buf,n);
10298 for (c = 0; c < n; c++) /* Strip any parity */
10300 #endif /* MYREAD */
10302 debug(F101,"ttxin x","",x); /* Done */
10303 if (x > 0) buf[x] = '\0';
10308 /* T T O L -- Write string s, length n, to communication device. */
10311 >= 0 on success, number of characters actually written.
10314 #ifdef CK_ENCRYPTION
10315 CHAR * xpacket = NULL;
10317 #endif /* CK_ENCRYPTION */
10321 ttol(s,n) int n; CHAR *s; {
10322 int x, len, tries, fd;
10324 extern int dblflag; /* For SET SEND DOUBLE-CHARACTER */
10325 extern short dblt[];
10326 CHAR *p = NULL, *p2, *s2, c;
10328 #endif /* CKXXCHAR */
10330 if (ttyfd < 0) /* Not open? */
10334 /* debug(F101,"ttol ttyfd","",ttyfd); */
10335 ckhexdump("ttol s",s,n);
10343 #endif /* NETCMD */
10347 /* Double any characters that must be doubled. */
10348 debug(F101,"ttol dblflag","",dblflag);
10350 p = (CHAR *) malloc(n + n + 1);
10359 if (dblt[(unsigned) c] & 2) {
10369 ckhexdump("ttol doubled s",s,n);
10372 #endif /* CKXXCHAR */
10374 tries = TTOLMAXT; /* Allow up to this many tries */
10375 len = n; /* Remember original length */
10377 #ifdef CK_ENCRYPTION
10379 This is to avoid encrypting a packet that is already encrypted, e.g.
10380 when we resend a packet directly out of the packet buffer, and also to
10381 avoid encrypting a constant (literal) string, which can cause a memory
10384 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
10386 if (nxpacket < n) {
10392 x = n > 10240 ? n : 10240;
10393 xpacket = (CHAR *)malloc(x);
10395 fprintf(stderr,"ttol malloc failure\n");
10400 memcpy((char *)xpacket,(char *)s,n);
10402 ck_tn_encrypt((char *)s,n);
10404 #endif /* CK_ENCRYPTION */
10408 #ifdef CK_ENCRYPTION
10409 /* keep trying if we are encrypting */
10410 || TELOPT_ME(TELOPT_ENCRYPTION)
10411 #endif /* CK_ENCRYPTION */
10412 )) { /* Be persistent */
10413 debug(F101,"ttol try","",TTOLMAXT - tries);
10415 if (netconn && !ttpipe && !ttpty)
10416 x = nettol((char *)s,n); /* Write string to device */
10418 #endif /* BEOSORBEBOX */
10420 if (ttnet == NET_IX25)
10422 * this is a more controlled way of writing to X25
10423 * STREAMS, however write should also work!
10425 x = x25write(ttyfd, s, n);
10427 #endif /* IBMX25 */
10429 if (ssl_active_flag || tls_active_flag) {
10431 /* Write using SSL */
10433 if (ssl_active_flag)
10434 x = SSL_write(ssl_con, s, n);
10436 x = SSL_write(tls_con, s, n);
10437 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
10438 case SSL_ERROR_NONE:
10444 case SSL_ERROR_WANT_WRITE:
10445 case SSL_ERROR_WANT_READ:
10448 case SSL_ERROR_SYSCALL:
10451 case SSL_ERROR_WANT_X509_LOOKUP:
10452 case SSL_ERROR_SSL:
10453 case SSL_ERROR_ZERO_RETURN:
10459 #endif /* CK_SSL */
10463 if (ttnproto == NP_EK4LOGIN) {
10464 return(krb4_des_write(ttyfd,s,n));
10466 #endif /* RLOGCODE */
10470 if (ttnproto == NP_EK5LOGIN) {
10471 return(krb5_des_write(ttyfd,(char *)s,n,0));
10473 #endif /* RLOGCODE */
10475 if (ttnproto == NP_K5U2U) {
10476 return(krb5_u2u_write(ttyfd,(char *)s,n));
10478 #endif /* KRB5_U2U */
10480 #endif /* CK_KERBEROS */
10481 x = write(fd,s,n); /* Write string to device */
10483 if (x == n) { /* Worked? */
10484 debug(F101,"ttol ok","",x); /* OK */
10487 #endif /* CKXXCHAR */
10488 return(len); /* Done */
10489 } else if (x < 0) { /* No, got error? */
10490 debug(F101,"ttol write error","",errno);
10492 if (errno == EWOULDBLOCK) {
10496 #endif /* EWOULDBLOCK */
10498 if (netconn && ttnet == NET_TCPB) {
10499 debug(F101,"ttol TCP error","",errno);
10500 ttclos(0); /* Close the connection. */
10503 #endif /* TCPSOCKET */
10506 #endif /* CKXXCHAR */
10508 } else { /* No error, so partial success */
10509 debug(F101,"ttol partial","",x); /* This never happens */
10510 s += x; /* Point to part not written yet */
10511 n -= x; /* Adjust length */
10512 if (x > 0) msleep(10); /* Wait 10 msec */
10513 } /* Go back and try again */
10517 #endif /* CKXXCHAR */
10518 return(n < 1 ? len : -1); /* Return the results */
10521 /* T T O C -- Output a character to the communication line */
10524 This function should only be used for interactive, character-mode operations,
10525 like terminal connection, script execution, dialer i/o, where the overhead
10526 of the signals and alarms does not create a bottleneck.
10533 #endif /* CK_ANSIC */
10535 #define TTOC_TMO 15 /* Timeout in case we get stuck */
10538 if (ttyfd < 0) /* Check for not open. */
10545 #endif /* NETCMD */
10549 /* debug(F101,"ttoc","",(CHAR) c); */
10550 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10551 xx = alarm(TTOC_TMO); /* for this many seconds. */
10552 if (xx < 0) xx = 0; /* Save old alarm value. */
10553 /* debug(F101,"ttoc alarm","",xx); */
10555 #ifdef CK_POSIX_SIG
10559 #endif /* CK_POSIX_SIG */
10560 ) { /* Timer went off? */
10561 ttimoff(); /* Yes, cancel this alarm. */
10562 if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
10563 /* debug(F100,"ttoc timeout","",0); */
10566 #endif /* NETCONN */
10567 debug(F101,"ttoc timeout","",c);
10568 if (ttflow == FLO_XONX) {
10569 debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
10572 /* POSIX way to unstick. */
10573 debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
10575 #ifdef BSD4 /* Berkeley way to do it. */
10577 /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);". Who knows? */
10580 debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
10582 #endif /* TIOCSTART */
10584 /* Is there a Sys V way to do this? */
10590 #endif /* NETCONN */
10591 return(-1); /* Return failure code. */
10596 if (netconn && !ttpipe && !ttpty)
10599 #endif /* BEOSORBEBOX */
10600 #endif /* NETCONN */
10601 #ifdef CK_ENCRYPTION
10602 if (TELOPT_ME(TELOPT_ENCRYPTION))
10603 ck_tn_encrypt(&c,1);
10604 #endif /* CK_ENCRYPTION */
10606 /* riehm: maybe this isn't necessary after all. Test program
10607 * worked fine with data being sent and retrieved with normal
10608 * read's and writes!
10610 if (ttnet == NET_IX25)
10611 rc = x25write(ttyfd,&c,1); /* as above for X25 streams */
10613 #endif /* IBMX25 */
10615 if (ssl_active_flag || tls_active_flag) {
10617 /* Write using SSL */
10618 if (ssl_active_flag)
10619 rc = SSL_write(ssl_con, &c, 1);
10621 rc = SSL_write(tls_con, &c, 1);
10622 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)){
10623 case SSL_ERROR_NONE:
10625 case SSL_ERROR_WANT_WRITE:
10626 case SSL_ERROR_WANT_READ:
10629 case SSL_ERROR_SYSCALL:
10632 case SSL_ERROR_WANT_X509_LOOKUP:
10633 case SSL_ERROR_SSL:
10634 case SSL_ERROR_ZERO_RETURN:
10640 #endif /* CK_SSL */
10644 if (ttnproto == NP_EK4LOGIN) {
10645 rc = (krb4_des_write(ttyfd,(char *)&c,1) == 1);
10647 #endif /* RLOGCODE */
10651 if (ttnproto == NP_EK5LOGIN) {
10652 rc = (krb5_des_write(ttyfd,&c,1,0) == 1);
10654 #endif /* RLOGCODE */
10656 if (ttnproto == NP_K5U2U) {
10657 rc = (krb5_u2u_write(ttyfd,&c,1) == 1);
10659 #endif /* KRB5_U2U */
10661 #endif /* CK_KERBEROS */
10662 rc = write(fd,&c,1); /* Try to write the character. */
10663 if (rc < 1) { /* Failed */
10664 ttimoff(); /* Turn off the alarm. */
10665 alarm(xx); /* Restore previous alarm. */
10666 debug(F101,"ttoc errno","",errno); /* Log the error, */
10667 return(-1); /* and return the error code. */
10670 ttimoff(); /* Success, turn off the alarm. */
10671 alarm(xx); /* Restore previous alarm. */
10672 return(0); /* Return good code. */
10675 /* T T I N L -- Read a record (up to break character) from comm line. */
10677 Reads up to "max" characters from the connection, terminating on:
10678 (a) the packet length field if the "turn" argument is zero, or
10679 (b) on the packet-end character (eol) if the "turn" argument is nonzero
10680 (c) a certain number of Ctrl-C's in a row
10683 >= 0, the number of characters read upon success;
10684 -1 if "max" exceeded, timeout, or other correctable error;
10685 -2 on user interruption (c);
10686 -3 on fatal error like connection lost.
10688 The name of this routine dates from the early days when Kermit packets
10689 were, indeed, always lines of text. That was before control-character
10690 unprefixing and length-driven packet framing were introduced, which this
10691 version handle. NB: this routine is ONLY for reading incoming Kermit
10692 packets, nothing else. To read other kinds of incoming material, use
10693 ttinc() or ttxin().
10695 The bytes that were input are copied into "dest" with their parity bits
10696 stripped if parity was selected. Returns the number of bytes read.
10697 Bytes after the eol are available upon the next call to this function.
10699 The idea is to minimize the number of system calls per packet, and also to
10700 minimize timeouts. This function is the inner loop of the protocol and must
10701 be as efficient as possible. The current strategy is to use myread(), a
10702 macro to manage buffered (and generally nonblocking) reads.
10704 WARNING: This function calls parchk(), which is defined in another module.
10705 Normally, ckutio.c does not depend on code from any other module, but there
10706 is an exception in this case because all the other ck?tio.c modules also
10707 need to call parchk(), so it's better to have it defined in a common place.
10712 #define CTRLC '\03'
10714 We have four different declarations here because:
10715 (a) to allow Kermit to be built without the automatic parity sensing feature
10716 (b) one of each type for ANSI C, one for non-ANSI.
10720 static int pushedback = 0;
10725 ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
10727 ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
10728 #endif /* CK_ANSIC */
10729 #else /* not PARSENSE */
10731 ttinl(CHAR *dest, int max,int timo, CHAR eol)
10733 ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
10734 #endif /* CK_ANSIC */
10735 #endif /* PARSENSE */
10740 #endif /* MYREAD */
10745 #endif /* PARSENSE */
10747 int sopmask = 0xff; /* Start-Of-Packet mask */
10749 extern short dblt[]; /* Ignore-character table */
10750 extern int ignflag;
10751 #endif /* CKXXCHAR */
10754 #endif /* TCPSOCKET */
10757 extern int streaming;
10759 #endif /* STREAMING */
10761 if (ttyfd < 0) return(-3); /* Not open. */
10763 In February 2007 I fixed ttinl() to work better under the truly awful
10764 conditions encountered by the AM-APEX oceanographic floats that gather
10765 hurricane data and phone home using Iridium satellite modems, which under
10766 certain conditions, can send two packets back to back after a long pause.
10767 In this case the second packet would be ignored because the SOH was skipped
10768 due to the ttflui() call. But the reworked lookahead/pushback logic broke
10769 Kermit transfers on encrypted connections. This was fixed 12-13 August
10770 2007. All of this happened after 8.0.212 Dev.27 was released and before
10771 Dev.28, so no harm done other than the delay.
10773 debug(F101,"ttinl max","",max);
10774 debug(F101,"ttinl timo","",timo);
10780 #endif /* NETCMD */
10784 if (xlocal && conchk() > 0) /* Allow for console interruptions */
10786 #endif /* COMMENT */
10788 *dest = '\0'; /* Clear destination buffer */
10789 if (timo < 0) timo = 0; /* Safety */
10790 if (timo) { /* Don't time out if timo == 0 */
10792 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10793 xx = alarm(timo); /* Set it. */
10794 debug(F101,"ttinl alarm","",xx);
10797 #ifdef CK_POSIX_SIG
10801 #endif /* CK_POSIX_SIG */
10802 ) { /* Timer went off? */
10803 debug(F100,"ttinl timout","",0); /* Get here on timeout. */
10804 /* debug(F110," with",(char *) dest,0); */
10805 ttimoff(); /* Turn off timer */
10806 return(-1); /* and return error code. */
10808 register int i, n = -1; /* local variables */
10811 register int flag = 0;
10812 debug(F000,"ttinl start","",start);
10813 #endif /* PARSENSE */
10815 ttpmsk = ttprty ? 0177 : 0377; /* Set parity stripping mask. */
10816 sopmask = needpchk ? 0177 : ttpmsk; /* And SOP matching mask. */
10818 /* Now read into destination, stripping parity and looking for the */
10819 /* the packet terminator, and also for several Ctrl-C's typed in a row. */
10821 i = 0; /* Destination index */
10822 debug(F101,"ttinl eol","",eol);
10824 while (i < max-1) {
10827 /* On encrypted connections myread returns encrypted bytes */
10829 debug(F000,"TTINL myread char","",n);
10830 if (n < 0) { /* Timeout or i/o error? */
10833 debug(F101,"ttinl myread failure, n","",n);
10834 debug(F101,"ttinl myread errno","",errno);
10837 /* Don't let EINTR break packets. */
10839 if (errno == EINTR && i > 0) {
10840 debug(F111,"ttinl EINTR myread i","continuing",i);
10843 debug(F110,"ttinl non-EINTR -3","closing",0);
10845 ttimoff(); /* Turn off timer */
10849 } else if (n == -2 && netconn /* && timo == 0 */ ) {
10850 /* Here we try to catch broken network connections */
10851 /* even when ioctl() and read() do not catch them */
10852 debug(F111,"ttinl network myread failure","closing",n);
10859 /* Streaming and no data to read */
10860 else if (n == 0 && streaming && sndtyp == 'D')
10862 #endif /* STREAMING */
10863 break; /* Break out of while loop */
10866 #else /* not MYREAD (is this code used anywhere any more?) */
10868 The non-MYREAD code dates from the 1980s and was needed on certain platforms
10869 where there were no nonblocking reads. -fdc, 2007/02/22.
10871 if ((n = read(fd, &n, 1)) < 1)
10872 break; /* Error - break out of while loop */
10874 #endif /* MYREAD */
10876 /* Get here with char in n */
10878 #ifdef CK_ENCRYPTION
10879 if (TELOPT_U(TELOPT_ENCRYPTION) && !pushedback) {
10881 ck_tn_decrypt((char *)&ch,1);
10883 debug(F000,"TTINL decryp char","",n);
10886 #endif /* CK_ENCRYPTION */
10889 if (n == IAC && /* Handle Telnet options */
10890 ((xlocal && netconn && IS_TELNET()) ||
10891 (!xlocal && sstelnet))) {
10898 #endif /* NOPARSEN */
10899 if (n != 255) /* No data - go back for next char */
10901 } /* Quoted IAC - keep going */
10902 #endif /* TCPSOCKET */
10906 if (dblt[(unsigned) n] & 1) /* Character to ignore? */
10908 #endif /* CKXXCHAR */
10910 Use parity mask, rather than always stripping parity, to check for
10911 cancellation. Otherwise, runs like \x03\x83\x03 in a packet could cancel
10912 the transfer when parity is NONE. (Note that \x03\x03\x03 is extremely
10913 unlikely due to run-length encoding.)
10915 /* Check cancellation */
10916 if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
10917 if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
10918 if (timo) { /* Clear timer. */
10922 printf("^%c...\r\n",(char)(xfrchr+64));
10924 printf("Canceled...\r\n");
10927 } else ccn = 0; /* No cancellation, reset counter, */
10931 Restructured code allows for a new packet to appear somewhere in the
10932 middle of a previous one. -fdc, 24 Feb 2007.
10934 if ((n & sopmask) == start) { /* Start of Packet */
10935 debug(F101,"ttinl SOP i","",i);
10936 flag = 1; /* Flag that we are in a packet */
10937 havelen = 0; /* Invalidate previous length */
10938 pktlen = -1; /* (if any) in case we were */
10939 lplen = 0; /* alread processand a packet */
10940 i = 0; /* and reset the dest buffer pointer */
10942 if (flag == 0) { /* No SOP yet... */
10943 debug(F000,"ttinl skipping","",n);
10946 dest[i++] = n & ttpmsk;
10948 If we have not been instructed to wait for a turnaround character, we can go
10949 by the packet length field. If turn != 0, we must wait for the end of line
10950 (eol) character before returning. This is an egregious violation of all
10951 principles of layering... (Less egregious in C-Kermit 9.0, in which we go
10952 by the length field but also look for the eol in case it arrives early,
10953 e.g. if the length field was corrupted upwards.)
10957 if ((dest[1] & 0x7f) < 32) /* Garbage in length field */
10958 return(-1); /* fdc - 13 Apr 2010 */
10959 pktlen = xunchar(dest[1] & 0x7f);
10960 if (pktlen > 94) /* Rubout in length field */
10961 return(-1); /* fdc - 13 Apr 2010 */
10964 debug(F101,"ttinl pktlen value","",pktlen);
10966 } else if (i == 5 && pktlen == 0) {
10967 lplen = xunchar(dest[4] & 0x7f);
10968 } else if (i == 6 && pktlen == 0) {
10969 pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
10971 debug(F101,"ttinl extended length","",pktlen);
10976 Suppose we looked at the sequence number here and found it was out of
10977 range? This would mean either (a) incoming packets had SOP unprefixed
10978 and we are out of sync, or (b) the packet is damaged. Since (a) is bad
10979 practice, let's ignore it. So what should we do here if we know the
10982 1. Nothing -- keep trying to read the packet till we find what we think
10983 is the end, or we time out, and let the upper layer decide what to
10984 do. But since either the packet is corrupt or we are out of sync,
10985 our criterion for finding the end does not apply and we are likely
10986 to time out (or swallow a piece of the next packet) if our assumed
10987 length is too long. (This was the behavior prior to version 7.0.)
10989 2. set flag = 0 and continue? This would force us to wait for the
10990 next packet to come in, and therefore (in the nonwindowing case),
10991 would force a timeout in the other Kermit.
10993 3. set flag = 0 and continue, but only if the window size is > 1 and
10994 the window is not blocked? Talk about cheating!
10996 4. Return a failure code and let the upper layer decide what to do.
10997 This should be equivalent to 3, but without the cheating. So let's
10998 do it that way... But note that we must ignore the parity bit
10999 in case this is the first packet and we have not yet run parchk().
11001 if (i == 3) { /* Peek at sequence number */
11002 x = xunchar((dest[i-1] & 0x7f)); /* If it's not in range... */
11003 if (x < 0 || x > 63) {
11004 debug(F111,"ttinl bad seq",dest,x);
11005 if (timo) ttimoff();
11006 return(-1); /* return a nonfatal error */
11010 #else /* PARSENSE */
11011 dest[i++] = n & ttpmsk;
11012 #endif /* PARSENSE */
11014 /* Check for end of packet */
11017 ((n & ttpmsk) == eol) /* Always break on the eol char */
11019 || /* fdc - see notes of 13 Apr 2010 */
11021 Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
11022 This allows packet terminators and handshake characters to appear
11023 literally inside a packet data field.
11025 (havelen && (i > pktlen+1) &&
11026 (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
11028 #endif /* PARSENSE */
11031 Here we have either read the last byte of the packet based on its length
11032 field, or else we have read the packet terminator (eol) or the half-duplex
11033 line-turnaround char (turn).
11036 debug(F101,"ttinl got eol","",eol); /* (or turn) */
11037 dest[i] = '\0'; /* Yes, terminate the string, */
11038 /* debug(F101,"ttinl i","",i); */
11040 #else /* PARSENSE */
11044 if ((n & ttpmsk) != eol) {
11045 debug(F101,"ttinl EOP length","",pktlen);
11046 debug(F000,"ttinl EOP current char","",n);
11047 debug(F101,"ttinl EOP packet buf index","",i);
11048 } else debug(F101,"ttinl got eol","",eol);
11054 The packet was read based on its length. This leaves the packet terminator
11055 unread, and so ttchk() will always return at least 1 because of this,
11056 possibly giving a false positive to the "is there another packet waiting?"
11057 test. But if we know the terminator (or any other interpacket junk) is
11058 there, we can safely get rid of it.
11060 NOTE: This code reworked to (a) execute even if the debug log isn't active;
11061 and (b) actually work. -fdc, 2007/02/22. And again 2007/08/12-13 to also
11062 work on encrypted connections.
11064 debug(F101,"TTINL my_count","",my_count);
11065 if ((n & ttpmsk) != eol) { /* Not the packet terminator */
11067 while (my_count > 0) {
11068 x = myread(); /* (was ttinc(0) */
11069 debug(F000,"TTINL lkread char","",x);
11070 #ifdef CK_ENCRYPTION
11071 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11073 ck_tn_decrypt((char *)&ch,1);
11075 debug(F000,"TTINL lkdecr char","",x);
11077 #endif /* CK_ENCRYPTION */
11079 Note: while it might seem more elegant to simply
11080 push back the encrypted byte, that desynchronizes
11081 the decryption stream; the flag is necessary so we
11082 don't try to decrypt the same byte twice.
11084 if ((x & ttpmsk) == start) { /* Start of next packet */
11085 myunrd(x); /* Push back the decrypted byte */
11086 pushedback = 1; /* And set flag */
11087 debug(F000,"TTINL lkpush char","",x);
11092 #endif /* MYREAD */
11094 dest[i] = '\0'; /* Terminate the string, */
11095 if (needpchk) { /* Parity checked yet? */
11096 if (ttprty == 0) { /* No, check. */
11097 if ((ttprty = parchk(dest,start,i)) > 0) {
11099 debug(F101,"ttinl senses parity","",ttprty);
11100 debug(F110,"ttinl packet before",dest,0);
11102 for (j = 0; j < i; j++)
11103 dest[j] &= 0x7f; /* Strip parity from packet */
11104 debug(F110,"ttinl packet after ",dest,0);
11105 } else ttprty = 0; /* Restore if parchk error */
11110 #endif /* PARSENSE */
11112 if (timo) /* Turn off timer if it was on */
11114 ckhexdump("ttinl got",dest,i);
11117 /* ttinl() was called because there was non-packet */
11118 /* data sitting in the back channel. Ignore it. */
11119 if (streaming && sndtyp == 'D')
11121 #endif /* STREAMING */
11124 } /* End of while() */
11129 #endif /* NOXFER */
11131 /* T T I N C -- Read a character from the communication line */
11133 On success, returns the character that was read, >= 0.
11134 On failure, returns -1 or other negative myread error code,
11135 or -2 if connection is broken or ttyfd < 0.
11136 or -3 if session limit has expired,
11137 or -4 if something or other...
11138 NOTE: The API does not provide for ttinc() returning a special code
11139 upon timeout, but we need it. So for this we have a global variable,
11142 static int ttinctimo = 0; /* Yuk */
11145 ttinc(timo) int timo; {
11153 if (ttyfd < 0) return(-2); /* Not open. */
11155 is_tn = (xlocal && netconn && IS_TELNET()) ||
11156 (!xlocal && sstelnet);
11160 debug(F111,"ttinc","ttpush",ttpush);
11166 if (le_getchar(&ch) > 0) {
11167 debug(F111,"ttinc le_getchar","ch",ch);
11171 #endif /* TTLEBUF */
11177 #endif /* NETCMD */
11180 if ((timo <= 0) /* Untimed. */
11182 || (my_count > 0) /* Buffered char already waiting. */
11183 #endif /* MYREAD */
11186 /* Comm line failure returns -1 thru myread, so no &= 0377 */
11187 n = myread(); /* Wait for a character... */
11188 /* debug(F000,"ttinc MYREAD n","",n); */
11189 #ifdef CK_ENCRYPTION
11190 /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
11191 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11193 ck_tn_decrypt((char *)&ch,1);
11196 #endif /* CK_ENCRYPTION */
11199 if (ttpty && n < 0) {
11200 debug(F101,"ttinc error on pty","",n);
11204 #endif /* NETPTY */
11207 if ((n > -1) && is_tn)
11208 return((unsigned)(n & 0xff));
11210 #endif /* TNCODE */
11211 return(n < 0 ? n : (unsigned)(n & ttpmsk));
11215 while ((n = read(fd,&ch,1)) == 0) /* Wait for a character. */
11216 /* Shouldn't have to loop in ver 5A. */
11218 if (netconn) { /* Special handling for net */
11219 netclos(); /* If read() returns 0 it means */
11220 netconn = 0; /* the connection has dropped. */
11224 #endif /* NETCONN */
11226 /* debug(F101,"ttinc","",ch); */
11228 if ((n > 0) && is_tn) {
11229 #ifdef CK_ENCRYPTION
11230 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11231 ck_tn_decrypt(&ch,1);
11234 #endif /* CK_ENCRYPTION */
11235 return((unsigned)(ch & 0xff));
11237 #endif /* TNCODE */
11238 return((n < 0) ? -4 : ((n == 0) ? -1 : (unsigned)(ch & ttpmsk)));
11239 #endif /* MYREAD */
11241 } else { /* Timed read */
11244 saval = signal(SIGALRM,timerh); /* Set up handler, save old one. */
11245 oldalarm = alarm(timo); /* Set alarm, save old one. */
11247 #ifdef CK_POSIX_SIG
11251 #endif /* CK_POSIX_SIG */
11252 ) { /* Timer expired */
11254 n = -1; /* set flag */
11257 n = myread(); /* If managing own buffer... */
11258 debug(F101,"ttinc myread","",n);
11261 n = read(fd,&ch,1); /* Otherwise call the system. */
11262 if (n == 0) n = -1;
11263 debug(F101,"ttinc read","",n);
11264 #endif /* MYREAD */
11266 #ifdef CK_ENCRYPTION
11267 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11268 ck_tn_decrypt((char *)&ch,1);
11270 #endif /* CK_ENCRYPTION */
11272 n = (unsigned) (ch & 0xff);
11274 n = (n < 0) ? -4 : -2; /* Special return codes. */
11276 ttimoff(); /* Turn off the timer */
11277 if (oldalarm > 0) {
11278 if (n == -1) /* and restore any previous alarm */
11280 if (oldalarm < 0) /* adjusted by our timeout interval */
11283 debug(F101,"ttinc restoring oldalarm","",oldalarm);
11289 if (n == -2) { /* read() returns 0 */
11290 netclos(); /* on network read failure */
11295 #endif /* NETCONN */
11297 if ((n > -1) && is_tn)
11298 return((unsigned)(n & 0xff));
11300 #endif /* TNCODE */
11301 /* Return masked char or neg. */
11302 return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
11306 /* S N D B R K -- Send a BREAK signal of the given duration */
11310 sndbrk(int msec) { /* Argument is milliseconds */
11312 sndbrk(msec) int msec; {
11313 #endif /* CK_ANSIC */
11324 #endif /* ANYBSD */
11333 #endif /* BSDBREAK */
11334 #endif /* COHERENT */
11339 #endif /* BSDBREAK */
11340 #endif /* BELLV10 */
11344 #endif /* PROVX1 */
11346 debug(F101,"ttsndb ttyfd","",ttyfd);
11347 if (ttyfd < 0) return(-1); /* Not open. */
11350 return p9sndbrk(msec);
11354 if (ttpipe) /* Pipe */
11355 return(ttoc('\0'));
11356 #endif /* NETCMD */
11359 return(ttoc('\0'));
11360 #endif /* NETPTY */
11361 if (netconn) /* Send network BREAK */
11362 return(netbreak());
11363 #endif /* NETCONN */
11365 if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
11367 #ifdef POSIX /* Easy in POSIX */
11370 debug(F111,"sndbrk POSIX",ckitoa(msec),(msec/375));
11372 x = tcsendbreak(ttyfd,msec / 375);
11373 debug(F111,"sndbrk tcsendbreak",ckitoa(errno),x);
11378 gtty(ttyfd,&ttbuf); /* Get current tty flags */
11379 spd = ttbuf.sg_ospeed; /* Save speed */
11380 ttbuf.sg_ospeed = B50; /* Change to 50 baud */
11381 stty(ttyfd,&ttbuf); /* ... */
11382 n = (int)strlen(brnuls); /* Send the right number of nulls */
11385 write(ttyfd,brnuls,n);
11386 ttbuf.sg_ospeed = spd; /* Restore speed */
11387 stty(ttyfd,&ttbuf); /* ... */
11391 sio_$control((short)ttyfd, sio_$send_break, msec, st);
11395 n = FWRITE; /* Flush output queue. */
11396 /* Watch out for int vs long problems in &n arg! */
11397 debug(F101,"sndbrk BSDBREAK","",msec);
11398 ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
11399 if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
11400 perror("Can't send BREAK");
11403 x = msleep(msec); /* Sleep for so many milliseconds */
11404 if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
11405 perror("BREAK stuck!!!");
11406 doexit(BAD_EXIT,-1); /* Get out, closing the line. */
11407 /* with bad exit status */
11413 No way to send a long BREAK in Sys V, so send a bunch of regular ones.
11414 (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
11415 but there's no way for this code to know for sure.)
11417 debug(F101,"sndbrk ATTSV","",msec);
11419 for (n = 0; n < x; n++) {
11420 /* Reportedly the cast breaks this function on some systems */
11421 /* But then why was it here in the first place? */
11422 if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
11423 perror("Can't send BREAK");
11430 debug(F101,"sndbrk V7","",msec);
11431 return(genbrk(ttyfd,250)); /* Simulate a BREAK */
11433 debug(F101,"sndbrk catchall","",msec);
11434 ttoc(0);ttoc(0);ttoc(0);ttoc(0);
11437 #endif /* BSDBREAK */
11440 #endif /* PROVX1 */
11445 /* T T S N D B -- Send a BREAK signal */
11450 if (netconn && istncomport())
11451 return((tnsndb(275L) >= 0) ? 0 : -1);
11453 #endif /* TN_COMPORT */
11454 return(sndbrk(275));
11457 /* T T S N D L B -- Send a Long BREAK signal */
11462 if (netconn && istncomport())
11463 return((tnsndb(1800L) >= 0) ? 0 : -1);
11465 #endif /* TN_COMPORT */
11466 return(sndbrk(1500));
11469 /* M S L E E P -- Millisecond version of sleep(). */
11472 Call with number of milliseconds (thousandths of seconds) to sleep.
11473 Intended only for small intervals. For big ones, just use sleep().
11474 Highly system-dependent.
11475 Returns 0 always, even if it didn't work.
11478 /* Define MSLFTIME for systems that must use an ftime() loop. */
11479 #ifdef ANYBSD /* For pre-4.2 BSD versions */
11483 #endif /* ANYBSD */
11485 #ifdef TOWER1 /* NCR Tower OS 1.0 */
11487 #endif /* TOWER1 */
11489 #ifdef COHERENT /* Coherent... */
11490 #ifndef _I386 /* Maybe Coherent/386 should get this, too */
11491 #define MSLFTIME /* Opinions are divided */
11493 #endif /* COHERENT */
11498 /* Millisecond timer */
11500 static long msecbase = 0L; /* Unsigned long not portable */
11503 getmsec() { /* Milliseconds since base time */
11505 struct timezone xz;
11512 gettimeofday(&tv, NULL)
11514 gettimeofday(&tv, &tz)
11516 #endif /* GTODONEARG */
11519 if (msecbase == 0L) { /* First call, set base time. */
11520 msecbase = tv.tv_sec;
11521 debug(F101,"getmsec base","",msecbase);
11523 return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
11525 #endif /* GETMSEC */
11526 #endif /* COMMENT */
11530 ttwait(fd, secs) int fd, secs; {
11538 if ((x = select(FD_SETSIZE,
11544 #endif /* HPUX1000 */
11548 debug(F101,"ttwait select errno","",errno);
11551 debug(F101,"ttwait OK","",errno);
11552 x = FD_ISSET(fd, &rfds);
11553 debug(F101,"ttwait select x","",x);
11557 #endif /* SELECT */
11562 Other possibilities here are:
11563 nanosleep(), reportedly defined in POSIX.4.
11564 sginap(), IRIX only (back to what IRIX version I don't know).
11571 #else /* BEOSORBEBOX */
11574 debug(F101,"msleep SELECT 1","",m);
11575 if (m <= 0) return(0);
11576 if (m >= 1000) { /* Catch big arguments. */
11579 if (m < 10) return(0);
11581 debug(F101,"msleep SELECT 2","",m);
11583 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
11584 debug(F101,"msleep BELLV10 select","",x);
11585 #else /* BELLV10 */
11587 gettimeofday(&tv, &tz);
11592 if (gettimeofday(&tv) < 0)
11595 if (gettimeofday(&tv,NULL) < 0)
11598 if (gettimeofday(&tv, NULL) < 0) /* wonder what this does... */
11600 if (gettimeofday(&tv, &tz) < 0)
11601 #endif /* NOTIMEZONE */
11603 #endif /* GTODONEARG */
11605 t1 = tv.tv_sec; /* Seconds */
11606 #endif /* COHERENT */
11608 tv.tv_sec = 0; /* Use select() */
11609 tv.tv_usec = m * 1000L;
11611 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11612 debug(F101,"msleep BSD44 select","",x);
11615 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11616 debug(F101,"msleep __linux__ select","",x);
11617 #else /* __linux__ */
11619 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11620 debug(F101,"msleep BSD43 select","",x);
11623 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11624 debug(F101,"msleep QNX6 select","",x);
11627 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11628 debug(F101,"msleep QNX select","",x);
11631 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11632 debug(F101,"msleep COHERENT select","",x);
11633 #else /* COHERENT */
11634 #ifdef HPUX1000 /* 10.00 only, not 10.10 or later */
11635 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11636 debug(F101,"msleep HP-UX 10.00 select","",x);
11637 #else /* HPUX1000 */
11639 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11640 debug(F101,"msleep SVR4 select","",x);
11643 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11644 debug(F101,"msleep OSF40 select","",x);
11647 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11648 debug(F101,"msleep OSF40 select","",x);
11650 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11651 debug(F101,"msleep catch-all select","",x);
11654 #endif /* HP1000 */
11656 #endif /* COHERENT */
11660 #endif /* __linux__ */
11662 #endif /* BELLV10 */
11665 #else /* Not SELECT */
11666 #ifdef CK_POLL /* We have poll() */
11667 struct pollfd pfd; /* Supply a valid address for poll() */
11669 #ifdef ODT30 /* But in SCO ODT 3.0 */
11670 #ifdef NAP /* we should use nap() instead */
11671 debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
11672 nap((long)m); /* seems to break dialing. */
11675 debug(F101,"msleep ODT 3.0 POLL","",m);
11680 debug(F101,"msleep POLL","",m);
11686 We could handle the above more cleanly by just letting nap() always
11687 take precedence over poll() in this routine, but there is no way to know
11688 whether that would break something else.
11691 #else /* Not POLL */
11694 "This routine is implemented using setitimer(2); it requires eight
11695 system calls...". In other words, it might take 5 minutes to sleep
11698 debug(F101,"msleep USLEEP","",m);
11699 if (m >= 1000) { /* Catch big arguments. */
11702 if (m < 10) return(0);
11704 usleep((unsigned int)(m * 1000));
11709 debug(F101,"msleep aegis","",m);
11711 dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */
11712 time_$wait(time_$relative, dur, st);
11716 debug(F101,"msleep Venix","",m);
11717 if (m <= 0) return(0);
11718 sleep(-((m * 60 + 500) / 1000));
11722 debug(F101,"msleep NAP","",m);
11728 extern long times(); /* Or #include <times.h> ? */
11730 long t1, t2, tarray[4];
11732 char *cp = getenv("HZ");
11736 if (cp && (hertz = atoi(cp))) {
11737 CLOCK_TICK = 1000 / hertz;
11738 } else { /* probably single user mode */
11740 CLOCK_TICK = 1000 / HZ;
11743 /* HZ always exists in, for instance, SCO Xenix, so you don't have to
11744 * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
11745 * have Xenix, you have should have nap(), so the best is to use -DNAP
11746 * in the makefile. Most systems have HZ.
11748 CLOCK_TICK = 17; /* 1/60 sec */
11750 printf("warning: environment variable HZ bad... using HZ=%d\r\n",
11751 1000 / CLOCK_TICK);
11756 debug(F101,"msleep ATTSV","",m);
11757 if (m <= 0) return(0);
11758 if (m >= 1000) { /* Catch big arguments. */
11761 if (m < 10) return(0);
11763 if ((t1 = times(tarray)) < 0) return(-1);
11765 if ((t2 = times(tarray)) < 0) return(-1);
11766 t3 = ((int)(t2 - t1)) * CLOCK_TICK;
11767 if (t3 > m) return(t3);
11769 #else /* Not ATTSV */
11770 #ifdef MSLFTIME /* Use ftime() loop... */
11772 debug(F101,"msleep MSLFTIME","",m);
11773 if (m <= 0) return(0);
11774 if (m >= 1000) { /* Catch big arguments. */
11777 if (m < 10) return(0);
11780 ftime(&ftp); /* void ftime() in QNX */
11782 if (ftime(&ftp) < 0) return(-1); /* Get base time. */
11784 t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
11786 ftime(&ftp); /* Get current time and compare. */
11787 t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
11788 if (t3 > m) return(0);
11791 /* This includes true POSIX, which has no way to do this. */
11792 debug(F101,"msleep busy loop","",m);
11793 if (m >= 1000) { /* Catch big arguments. */
11796 if (m < 10) return(0);
11798 if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */
11800 #endif /* MSLFTIME */
11803 #endif /* PROVX1 */
11805 #endif /* CK_POLL */
11806 #endif /* SELECT */
11807 #endif /* BEOSORBEBOX */
11808 #endif /* USLEEP */
11812 /* R T I M E R -- Reset elapsed time counter */
11816 tcount = time( (time_t *) 0 );
11820 /* G T I M E R -- Get current value of elapsed time counter in seconds */
11825 x = (int) (time( (time_t *) 0 ) - tcount);
11826 debug(F101,"gtimer","",x);
11827 return( (x < 0) ? 0 : x );
11832 Floating-point timers. Require not only floating point support, but
11833 also gettimeofday().
11835 static struct timeval tzero;
11839 #ifdef GTODONEARG /* Account for Mot's definition */
11840 (VOID) gettimeofday(&tzero);
11842 (VOID) gettimeofday(&tzero, (struct timezone *)0);
11843 #endif /* GTODONEARG */
11848 struct timeval tnow, tdelta;
11853 #ifdef GTODONEARG /* Account for Mot's definition */
11854 (VOID) gettimeofday(&tnow);
11856 (VOID) gettimeofday(&tnow, (struct timezone *)0);
11857 #endif /* GTODONEARG */
11859 tdelta.tv_sec = tnow.tv_sec - tzero.tv_sec;
11860 tdelta.tv_usec = tnow.tv_usec - tzero.tv_usec;
11862 if (tdelta.tv_usec < 0) {
11864 tdelta.tv_usec += 1000000;
11866 s = (CKFLOAT) tdelta.tv_sec + ((CKFLOAT) tdelta.tv_usec / 1000000.0);
11871 sprintf(fpbuf,"%f",s);
11872 debug(F110,"gftimer",fpbuf,0);
11877 #endif /* GFTIMER */
11879 /* Z T I M E -- Return asctime()-format date/time string */
11881 NOTE: as a side effect of calling this routine, we can also set the
11882 following two variables, giving the micro- and milliseconds (fractions of
11883 seconds) of the clock time. Currently this is done only in BSD-based builds
11884 that use gettimeofday(). When these variables are not filled in, they are
11885 left with a value of -1L.
11887 static char asctmbuf[64];
11890 ztime(s) char **s; {
11894 The gettimeofday() method, which also sets ztmsec and ztusec, works for
11895 all GFTIMER builds. NOTE: ztmsec and ztusec are defined in ckcmai.c,
11896 and extern declarations for them are in ckcdeb.h; thus they are
11897 declared in this file by inclusion of ckcdeb.h.
11900 struct tm *localtime();
11906 debug(F100,"ztime s==NULL","",0);
11909 /* No 2nd arg in Motorola SV88 and some others */
11910 if (gettimeofday(&tv) > -1)
11914 if (gettimeofday(&tv,NULL) > -1)
11917 if (gettimeofday(&tv, NULL) > -1) /* wonder what this does... */
11919 if (gettimeofday(&tv, &tz) > -1)
11920 #endif /* NOTIMEZONE */
11922 #endif /* COHERENT */
11923 #endif /* GTODONEARG */
11924 { /* Fill in tm struct */
11925 ztusec = tv.tv_usec; /* Microseconds */
11926 ztmsec = ztusec / 1000L; /* Milliseconds */
11931 tp = localtime(&zz); /* Convert to local time */
11938 tp = localtime(&zz);
11942 { /* avoid unaligned access trap on 64-bit platforms */
11945 tp = localtime(&zz);
11949 tp = localtime((time_t *)&tv.tv_sec); /* Convert to local time */
11951 tp = localtime(&tv.tv_sec);
11952 #endif /* MACOSX */
11954 #endif /* HPUX1000 */
11958 s2 = asctime(tp); /* Convert result to ASCII string */
11959 asctmbuf[0] = '\0';
11960 if (s2) ckstrncpy(asctmbuf,s2,64);
11962 debug(F111,"ztime GFTIMER gettimeofday",*s,ztusec);
11965 #else /* Not GFTIMER */
11967 #undef ZTIMEV7 /* Which systems need to use */
11968 #ifdef COHERENT /* old UNIX Version 7 way... */
11970 #endif /* COHERENT */
11973 #endif /* TOWER1 */
11978 #endif /* ANYBSD */
11990 Prototypes are in <time.h>, included above.
11992 time_t clock_storage;
11993 clock_storage = time((void *) 0);
11995 *s = ctime(&clock_storage);
11996 debug(F110,"ztime: HPUX 10.20",*s,0);
11999 #ifdef ATTSV /* AT&T way */
12000 /* extern long time(); */ /* Theoretically these should */
12001 char *ctime(); /* already been dcl'd in <time.h> */
12002 time_t clock_storage;
12003 clock_storage = time(
12012 #endif /* IRIX60 */
12015 *s = ctime( &clock_storage );
12016 debug(F110,"ztime: ATTSV",*s,0);
12019 #ifdef PROVX1 /* Venix 1.0 way */
12024 debug(F110,"ztime: PROVX1",*s,0);
12027 #ifdef BSD42 /* 4.2BSD way */
12029 struct tm *localtime();
12031 gettimeofday(&tv, &tz);
12032 ztusec = tv.tv_usec;
12033 ztmsec = tv.tv_usec / 1000L;
12034 tp = localtime(&tv.tv_sec);
12037 debug(F111,"ztime: BSD42",*s,ztusec);
12040 #ifdef MINIX /* MINIX way */
12042 extern long time(); /* Already got these from <time.h> */
12043 extern char *ctime();
12044 #endif /* COMMENT */
12049 debug(F110,"ztime: MINIX",*s,0);
12052 #ifdef ZTIMEV7 /* The regular way */
12054 struct tm *localtime();
12056 long xclock; /* or unsigned long for BeBox? */
12058 tp = localtime(&xclock);
12061 debug(F110,"ztime: ZTIMEV7",*s,0);
12063 #else /* Catch-all for others... */
12065 *s = "Day Mon 00 00:00:00 0000\n"; /* Dummy in asctime() format */
12066 debug(F110,"ztime: catch-all",*s,0);
12068 #endif /* ZTIMEV7 */
12071 #endif /* PROVX1 */
12073 #endif /* HPUX1020 */
12074 #endif /* GFTIMER */
12077 /* C O N G M -- Get console terminal modes. */
12080 Saves initial console mode, and establishes variables for switching
12081 between current (presumably normal) mode and other modes.
12082 Should be called when program starts, but only after establishing
12083 whether program is in the foreground or background.
12084 Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
12089 if (backgrd || !isatty(0)) { /* If in background. */
12090 cgmf = -1; /* Don't bother, modes are garbage. */
12093 if (cgmf > 0) return(0); /* Already did this. */
12094 debug(F100,"congm getting modes","",0); /* Need to do it. */
12096 ios_$inq_type_uid(ios_$stdin, conuid, st);
12097 if (st.all != status_$ok) {
12098 fprintf(stderr, "problem getting stdin objtype: ");
12101 concrp = (conuid == mbx_$uid);
12106 if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */
12108 fprintf(stderr,"Error opening %s\n", CTTNAM);
12113 #endif /* COMMENT */
12117 #endif /* !BEBOX */
12118 #ifdef BSD44ORPOSIX
12119 if (tcgetattr(fd,&ccold) < 0) return(-1);
12120 if (tcgetattr(fd,&cccbrk) < 0) return(-1);
12121 if (tcgetattr(fd,&ccraw) < 0) return(-1);
12124 if (ioctl(fd,TCGETA,&ccold) < 0) return(-1);
12125 if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
12126 if (ioctl(fd,TCGETA,&ccraw) < 0) return(-1);
12128 cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
12129 if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
12130 ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
12131 if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
12135 if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
12136 if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
12137 if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
12138 debug(F101,"cccbrk.sg_flags orig","", cccbrk.sg_flags);
12140 if (gtty(fd,&ccold) < 0) return(-1);
12141 if (gtty(fd,&cccbrk) < 0) return(-1);
12142 if (gtty(fd,&ccraw) < 0) return(-1);
12143 #endif /* BELLV10 */
12145 #endif /* BSD44ORPOSIX */
12146 #ifdef sony_news /* Sony NEWS */
12147 if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
12148 perror("congm error getting Kanji mode");
12149 debug(F101,"congm error getting Kanji mode","",0);
12150 km_con = -1; /* Make sure this stays undefined. */
12153 #endif /* sony_news */
12156 cgmf = 1; /* Flag that we got them. */
12162 congetbuf(x) int x; {
12164 n = CONBUFSIZ - (conbufp - conbuf); /* How much room left in buffer? */
12166 debug(F101,"congetbuf char loss","",x-n);
12169 x = read(0,conbufp,x);
12171 debug(F111,"congetbuf readahead",conbuf,x);
12175 /* C O N C B -- Put console in cbreak mode. */
12177 /* Returns 0 if ok, -1 if not */
12183 concb(esc) char esc;
12184 #endif /* CK_ANSIC */
12187 debug(F101,"concb constate","",constate);
12188 debug(F101,"concb cgmf","",cgmf);
12189 debug(F101,"concb backgrd","",backgrd);
12191 if (constate == CON_CB)
12194 if (cgmf < 1) /* Did we get console modes yet? */
12195 if (!backgrd) /* No, in background? */
12196 congm(); /* No, try to get them now. */
12197 if (cgmf < 1) /* Still don't have them? */
12198 return(0); /* Give up. */
12199 debug(F101,"concb ttyfd","",ttyfd);
12200 debug(F101,"concb ttfdflg","",ttfdflg);
12202 /* This breaks returning to prompt after protocol with "-l 0" */
12203 /* Commented out July 1998 */
12204 if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
12206 #endif /* COMMENT */
12208 debug(F101,"concb isatty","",x);
12209 if (!x) return(0); /* Only when running on real ttys */
12210 debug(F101,"concb xsuspend","",xsuspend);
12211 if (backgrd) /* Do nothing if in background. */
12213 escchr = esc; /* Make this available to other fns */
12214 ckxech = 1; /* Program can echo characters */
12217 if (concrp) return(write(1, "\035\002", 2));
12218 if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
12223 #endif /* COHERENT */
12228 #ifndef SVORPOSIX /* BSD, V7, etc */
12229 debug(F101,"cccbrk.sg_flags concb 1","", cccbrk.sg_flags);
12230 debug(F101,"concb stty CBREAK","",0);
12231 cccbrk.sg_flags |= (CBREAK|CRMOD); /* Set to character wakeup, */
12232 cccbrk.sg_flags &= ~ECHO; /* no echo. */
12233 debug(F101,"cccbrk.sg_flags concb 2","", cccbrk.sg_flags);
12236 BSD stty() clears the console buffer. So if anything is waiting in it,
12237 we have to read it now to avoid losing it.
12244 x = ioctl(0,TIOCSETP,&cccbrk);
12246 x = stty(0,&cccbrk);
12247 debug(F101,"cccbrk.sg_flags concb x","", x);
12248 #endif /* BELLV10 */
12249 #else /* Sys V and POSIX */
12251 debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
12253 /* Don't mess with IEXTEN */
12254 cccbrk.c_lflag &= ~(ICANON|ECHO);
12257 cccbrk.c_lflag &= ~(ICANON|ECHO);
12259 cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
12260 #endif /* COHERENT */
12262 cccbrk.c_lflag |= ISIG; /* Allow signals in command mode. */
12263 cccbrk.c_iflag |= IGNBRK; /* But ignore BREAK signal */
12264 cccbrk.c_iflag &= ~BRKINT;
12267 debug(F100,"concb OXOS is defined","",0);
12268 cccbrk.c_lflag &= ~(ICANON|ECHO);
12269 cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
12273 Believe it or not, in SCO UNIX, VSUSP is greater than NCC, and so this
12274 array reference is out of bounds. It's only a debug() call so who needs it.
12277 debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
12279 #endif /* COMMENT */
12281 debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
12282 cccbrk.c_cc[0] = 003; /* Interrupt char is Control-C */
12284 debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
12285 cccbrk.c_cc[VINTR] = 003;
12288 cccbrk.c_cc[1] = escchr; /* escape during packet modes */
12290 cccbrk.c_cc[VQUIT] = escchr;
12293 cccbrk.c_cc[4] = 1;
12297 cccbrk.c_cc[VMIN] = 1;
12304 cccbrk.c_cc[5] = 0;
12307 cccbrk.c_cc[5] = 1;
12311 cccbrk.c_cc[VTIME] = 1;
12319 #ifdef BSD44ORPOSIX /* Set new modes */
12320 x = tcsetattr(0,TCSADRAIN,&cccbrk);
12321 #else /* ATTSV */ /* or the POSIX way */
12322 x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */
12323 #endif /* BSD44ORPOSIX */
12324 #endif /* SVORPOSIX */
12328 #endif /* COHERENT */
12330 debug(F101,"concb x","",x);
12331 debug(F101,"concb errno","",errno);
12335 if (kmem[CON] < 0) {
12336 qaddr[CON] = initrawq(0);
12337 if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
12338 fprintf(stderr, "Can't read /dev/kmem in concb.\n");
12339 perror("/dev/kmem");
12350 debug(F101,"concb returns","",x);
12354 /* C O N B I N -- Put console in binary mode */
12356 /* Returns 0 if ok, -1 if not */
12362 conbin(esc) char esc;
12363 #endif /* CK_ANSIC */
12368 debug(F101,"conbin constate","",constate);
12370 if (constate == CON_BIN)
12373 if (!isatty(0)) return(0); /* only for real ttys */
12374 congm(); /* Get modes if necessary. */
12375 debug(F100,"conbin","",0);
12376 escchr = esc; /* Make this available to other fns */
12377 ckxech = 1; /* Program can echo characters */
12380 if (concrp) return(write(1, "\035\002", 2));
12381 if (conuid == input_pad_$uid) {
12382 pad_$raw(ios_$stdin, st);
12389 #endif /* COHERENT */
12397 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12400 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12402 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
12403 #endif /* COHERENT */
12406 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12407 ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
12409 ccraw.c_iflag |= IGNPAR;
12411 Note that for terminal sessions we disable Xon/Xoff flow control to allow
12412 the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
12413 transfers to work when C-Kermit is in the middle, etc. Hardware flow
12414 control, if in use, is not affected.
12418 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
12421 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
12425 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
12427 ccraw.c_oflag &= ~OPOST;
12430 WHAT THE HECK WAS THIS FOR?
12431 The B9600 setting (obviously) prevents CONNECT from working at any
12432 speed other than 9600 when you are logged in to the 7300 on a serial
12433 line. Maybe some of the other flags are necessary -- if so, put back
12434 the ones that are needed. This code is supposed to work the same, no
12435 matter whether you are logged in to the 7300 on the real console device,
12436 or through a serial port.
12439 ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
12440 #endif /* ATT7300 */
12441 #endif /* COMMENT */
12443 /*** Kermit used to put the console in 8-bit raw mode, but some users have
12444 *** pointed out that this should not be done, since some sites actually
12445 *** use terminals with parity settings on their Unix systems, and if we
12446 *** override the current settings and stop doing parity, then their terminals
12447 *** will display blotches for characters whose parity is wrong. Therefore,
12448 *** the following two lines are commented out (Larry Afrin, Clemson U):
12450 *** ccraw.c_cflag &= ~(PARENB|CSIZE);
12451 *** ccraw.c_cflag |= (CS8|CREAD);
12453 *** Sys III/V sites that have trouble with this can restore these lines.
12456 ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */
12458 ccraw.c_cc[VINTR] = 003;
12461 ccraw.c_cc[1] = escchr; /* Escape during packet mode */
12463 ccraw.c_cc[VQUIT] = escchr;
12470 ccraw.c_cc[VMIN] = 1;
12485 ccraw.c_cc[VTIME] = 1;
12493 #ifdef BSD44ORPOSIX
12494 x = tcsetattr(0,TCSADRAIN,&ccraw); /* Set new modes. */
12496 x = ioctl(0,TCSETAW,&ccraw);
12497 #endif /* BSD44ORPOSIX */
12498 #else /* Berkeley, etc. */
12499 x = conchk(); /* Because stty() is destructive */
12502 ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF (ha) */
12503 ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
12505 x = ioctl(0,TIOCSETP,&ccraw);
12507 x = stty(0,&ccraw);
12508 #endif /* BELLV10 */
12509 #endif /* SVORPOSIX */
12513 constate = CON_BIN;
12515 debug(F101,"conbin returns","",x);
12520 #endif /* COHERENT */
12525 /* C O N R E S -- Restore the console terminal */
12530 debug(F101,"conres cgmf","",cgmf);
12531 debug(F101,"conres constate","",constate);
12533 if (cgmf < 1) /* Do nothing if modes unchanged */
12535 if (constate == CON_RES)
12538 if (!isatty(0)) return(0); /* only for real ttys */
12539 debug(F100,"conres isatty ok","",0);
12540 ckxech = 0; /* System should echo chars */
12544 if (concrp) return(write(1, "\035\001", 2));
12545 if (conuid == input_pad_$uid) {
12546 pad_$cooked(ios_$stdin, st);
12547 constate = CON_RES;
12555 #ifdef BSD44ORPOSIX
12556 debug(F100,"conres restoring tcsetattr","",0);
12557 x = tcsetattr(0,TCSADRAIN,&ccold);
12560 debug(F100,"conres restoring ioctl","",0);
12561 x = ioctl(0,TCSETAW,&ccold);
12562 #else /* BSD, V7, and friends */
12563 #ifdef sony_news /* Sony NEWS */
12565 ioctl(0,TIOCKSET,&km_con); /* Restore console Kanji mode */
12566 #endif /* sony_news */
12568 debug(F100,"conres restoring stty","",0);
12569 x = conchk(); /* Because stty() is destructive */
12573 x = ioctl(0,TIOCSETP,&ccold);
12575 x = stty(0,&ccold);
12576 #endif /* BELLV10 */
12578 #endif /* BSD44ORPOSIX */
12581 constate = CON_RES;
12583 debug(F101,"conres returns","",x);
12587 /* C O N O C -- Output a character to the console terminal */
12594 #endif /* CK_ANSIC */
12598 if (inserver && !local)
12601 #ifdef CK_ENCRYPTION
12602 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12603 ck_tn_encrypt(&c,1);
12604 #endif /* CK_ENCRYPTION */
12608 return conwrite(&c,1);
12610 return(write(1,&c,1));
12614 /* C O N X O -- Write x characters to the console terminal */
12617 conxo(x,s) int x; char *s; {
12620 if (inserver && !local)
12621 return(ttol((CHAR *)s,x));
12623 #ifdef CK_ENCRYPTION
12624 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12625 ck_tn_encrypt(s,x);
12626 #endif /* CK_ENCRYPTION */
12630 return(conwrite(s,x));
12632 return(write(1,s,x));
12636 /* C O N O L -- Write a line to the console terminal */
12639 conol(s) char *s; {
12641 if (!s) s = ""; /* Always do this! */
12647 if (inserver && !local)
12648 return(ttol((CHAR *)s,len));
12650 #ifdef CK_ENCRYPTION
12651 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION)) {
12652 if (nxpacket < len) {
12658 len = len > 10240 ? len : 10240;
12659 xpacket = (CHAR *)malloc(len);
12661 fprintf(stderr,"ttol malloc failure\n");
12666 memcpy(xpacket,s,len);
12667 s = (char *)xpacket;
12668 ck_tn_encrypt(s,len);
12670 #endif /* CK_ENCRYPTION */
12674 return(conwrite(s,len));
12676 return(write(1,s,len));
12680 /* C O N O L A -- Write an array of lines to the console terminal */
12683 conola(s) char *s[]; {
12689 for (i = 0; ; i++) {
12691 if (!p) p = ""; /* Let's not dump core shall we? */
12695 if (inserver && !local)
12696 x = ttol((CHAR *)p,(int)strlen(p));
12706 /* C O N O L L -- Output a string followed by CRLF */
12709 conoll(s) char *s; {
12717 if (inserver && !local) {
12718 if (*s) ttol((CHAR *)s,(int)strlen(s));
12719 return(ttol(buf,2));
12725 #ifdef CK_ENCRYPTION
12726 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12727 ck_tn_encrypt((char *)buf,2);
12728 #endif /* CK_ENCRYPTION */
12732 return(conwrite(buf, 2));
12734 return(write(1,buf,2));
12738 /* C O N C H K -- Return how many characters available at console */
12740 We could also use select() here to cover a few more systems that are not
12741 covered by any of the following, e.g. HP-UX 9.0x on the model 800.
12745 static int contyp = 0; /* +1 for isatty, -1 otherwise */
12747 if (contyp == 0) /* This prevents unnecessary */
12748 contyp = (isatty(0) ? 1 : -1); /* duplicated calls to isatty() */
12749 debug(F101,"conchk contyp","",contyp);
12750 if (backgrd || (contyp < 0))
12754 if (conbufn > 0) return(conbufn); /* use old count if nonzero */
12756 /* read in more characters */
12757 conbufn = ios_$get(ios_$stdin,
12758 ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
12759 if (st.all != status_$ok) conbufn = 0;
12764 if (inserver && !local)
12765 return(in_chk(1,ttyfd));
12768 return(in_chk(0,0));
12772 /* C O N I N C -- Get a character from the console */
12774 Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
12775 read. Upon success, returns the character. Upon failure, returns -1.
12776 A timed read that does not complete within the timeout period returns -2.
12779 coninc(timo) int timo; {
12780 int n = 0; CHAR ch;
12783 if (conbufn > 0) { /* If something already buffered */
12785 return((unsigned)(*conbufp++ & 0xff));
12788 errno = 0; /* Clear this */
12790 if (inserver && !local) {
12793 return(ttinctimo ? -2 : -1);
12799 #ifdef aegis /* Apollo Aegis only... */
12800 debug(F101,"coninc timo","",timo);
12802 if (conchk() > 0) {
12804 return((unsigned)(*conbufp++ & 0xff));
12816 debug(F111,"ttinc","ttpush",ttpush);
12822 if (le_getchar(&ch) > 0) {
12823 debug(F111,"ttinc LocalEchoInBuf","ch",ch);
12828 #endif /* TTLEBUF */
12830 if (timo <= 0) { /* Untimed, blocking read. */
12831 while (1) { /* Keep trying till we get one. */
12832 n = read(0, &ch, 1); /* Read a character. */
12833 if (n == 0) continue; /* Shouldn't happen. */
12834 if (n > 0) { /* If read was successful, */
12836 #ifdef CK_ENCRYPTION
12837 debug(F100,"coninc decrypt 1","",0);
12838 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12839 ck_tn_decrypt((char *)&ch,1);
12840 #endif /* CK_ENCRYPTION */
12842 return((unsigned)(ch & 0xff)); /* return the character. */
12845 /* Come here if read() returned an error. */
12847 debug(F101, "coninc(0) errno","",errno); /* Log the error. */
12850 #ifdef CIE /* CIE Regulus has no EINTR symbol? */
12856 This routine is used for several different purposes. In CONNECT mode, it is
12857 used to do an untimed, blocking read from the keyboard in the lower CONNECT
12858 fork. During local-mode file transfer, it reads a character from the
12859 console to interrupt the file transfer (like A for a status report, X to
12860 cancel a file, etc). Obviously, we don't want the reads in the latter case
12861 to be blocking, or the file transfer would stop until the user typed
12862 something. Unfortunately, System V does not allow the console device input
12863 buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
12864 used instead. During local-mode file transfer, the SIGQUIT signal is armed
12865 and trapped by esctrp(), and this routine pretends to have read the quit
12866 character from the keyboard normally. But, kludge or no kludge, the read()
12867 issued by this command, under System V only, can fail if a signal -- ANY
12868 signal -- is caught while the read is pending. This can occur not only when
12869 the user types the quit character, but also during telnet negotiations, when
12870 the lower CONNECT fork signals the upper one about an echoing mode change.
12871 When this happens, we have to post the read() again. This is apparently not
12872 a problem in BSD-based UNIX versions.
12874 if (errno == EINTR) /* Read interrupted. */
12875 if (conesc) { /* If by SIGQUIT, */
12876 conesc = 0; /* the conesc variable is set, */
12877 return(escchr); /* so return the escape character. */
12878 } else continue; /* By other signal, try again. */
12881 This might be dangerous, but let's do this on non-System V versions too,
12882 since at least one SunOS 4.1.2 user complains of immediate disconnections
12883 upon first making a TELNET connection.
12885 if (errno == EINTR) /* Read interrupted. */
12887 #endif /* SVORPOSIX */
12889 if (errno == EINTR) /* Read interrupted. */
12892 return(-1); /* Error */
12896 if (deblog && timo <= 0) {
12897 debug(F100,"coninc timeout logic error","",0);
12902 /* Timed read... */
12904 saval = signal(SIGALRM,timerh); /* Set up timeout handler. */
12905 xx = alarm(timo); /* Set the alarm. */
12906 debug(F101,"coninc alarm set","",timo);
12908 #ifdef CK_POSIX_SIG
12912 #endif /* CK_POSIX_SIG */
12913 ) /* The read() timed out. */
12914 n = -2; /* Code for timeout. */
12916 n = read(0, &ch, 1);
12917 ttimoff(); /* Turn off timer */
12918 if (n > 0) { /* Got character OK. */
12920 #ifdef CK_ENCRYPTION
12921 debug(F100,"coninc decrypt 2","",0);
12922 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12923 ck_tn_decrypt((char *)&ch,1);
12924 #endif /* CK_ENCRYPTION */
12926 return((unsigned)(ch & 0xff)); /* Return it. */
12929 read() returned an error. Same deal as above, but without the loop.
12931 debug(F101, "coninc(timo) n","",n);
12932 debug(F101, "coninc(timo) errno","",errno);
12935 if (n == -1 && errno == EINTR && conesc != 0) {
12937 return(escchr); /* User entered escape character. */
12939 #endif /* SVORPOSIX */
12940 if (n == 0 && errno > 0) { /* It's an error */
12943 #endif /* ! OXOS */
12947 /* C O N G K S -- Console Get Keyboard Scancode */
12951 This function needs to be filled in with the various system-dependent
12952 system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
12953 keyboard scan code. Unfortunately there aren't any.
12956 congks(timo) int timo; {
12959 if (inserver && !local)
12960 return(ttinc(timo));
12963 return(coninc(timo));
12965 #endif /* congks */
12969 /* A T T D I A L -- Dial up the remote system using internal modem
12970 * Purpose: to open and dial a number on the internal modem available on the
12971 * ATT7300 UNIX PC. Written by Joe Doupnik. Superceeds version written by
12972 * Richard E. Hill, Dickinson, TX. which employed dial(3c).
12973 * Uses information in <sys/phone.h> and our status int attmodem.
12975 attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
12978 attmodem &= ~ISMODEM; /* modem not in use yet */
12979 /* Ensure O_NDELAY is set, else i/o traffic hangs */
12980 /* We turn this flag off once the dial is complete */
12981 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
12983 /* Condition line, check availability & DATA mode, turn on speaker */
12984 if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
12985 printf("cannot access phone\n");
12989 ioctl(ttyfd,PIOCGETP,&dialer); /* get phone dialer parameters */
12991 if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */
12992 printf(" Should not dial with modem in VOICE mode.\n");
12993 printf(" Exit Kermit, switch to DATA and retry call.\n");
12997 #ifdef ATTTONED /* Old way, tone dialing only. */
12998 dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */
12999 dialer.c_lineparam &= ~PULSE; /* not with pulses. */
13001 /* Leave current pulse/tone state alone. */
13002 /* But what about DATA? Add it back if you have trouble. */
13003 /* sys/phone says you get DATA automatically by opening device RDWR */
13005 dialer.c_waitdialtone = 5; /* wait 5 sec for dialtone */
13007 dialer.c_feedback = SPEAKERON|NORMSPK|RINGON; /* control speaker */
13009 /* sys/phone says RINGON used only for incoming voice calls */
13010 dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
13011 dialer.c_feedback |= SPEAKERON|NORMSPK;
13013 dialer.c_waitflash = 500; /* 0.5 sec flash hook */
13014 if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) { /* set phone parameters */
13015 printf("Cannot set modem characteristics\n");
13019 ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */
13022 fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
13023 line_status:%o feedback:%o\n",
13024 dialer.c_lineparam, dialer.c_waitdialtone,
13025 dialer.c_linestatus, dialer.c_feedback);
13028 attmodem |= ISMODEM; /* modem is now in-use */
13030 for (telnum = telnbr; *telnum != '\0'; telnum++) /* dial number */
13032 /* Tone dialing only */
13033 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13034 perror("Error in dialing");
13038 #else /* Allow Pulse or Tone dialing */
13040 case 't': case 'T': case '%': /* Tone dialing requested */
13041 dialer.c_lineparam |= DTMF;
13042 dialer.c_lineparam &= ~PULSE;
13043 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13044 printf("Cannot set modem to tone dialing\n");
13049 case 'd': case 'D': case 'p': case 'P': case '^':
13050 dialer.c_lineparam |= PULSE;
13051 dialer.c_lineparam &= ~DTMF;
13052 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13053 printf("Cannot set modem to pulse dialing\n");
13059 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13060 perror("Dialing error");
13068 ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */
13069 do { /* wait for modems to Connect */
13070 if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */
13071 perror("Cannot get modems to connect");
13075 } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
13076 /* Turn off O_NDELAY flag now. */
13077 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
13078 signal(SIGHUP, sighup); /* hangup on loss of carrier */
13079 return(0); /* return success */
13083 Offgetty, ongetty functions. These function get the 'getty(1m)' off
13084 and restore it to the indicated line. Shell's return codes are:
13085 0: Can't do it. Probably a user logged on.
13086 1: No need. No getty on that line.
13087 2: Done, you should restore the getty when you're done.
13088 DOGETY System(3), however, returns them as 0, 256, 512, respectively.
13089 Thanks to Kevin O'Gorman, Anarm Software Systems.
13091 getoff.sh looks like: geton.sh looks like:
13092 setgetty $1 0 setgetty $1 1
13098 /* O F F G E T T Y -- Turn off getty(1m) for the communications tty line
13099 * and get status so it can be restarted after the line is hung up.
13102 offgetty(ttname) char *ttname; {
13104 while (*ttname != '\0') ttname++; /* seek terminator of path */
13105 ttname -= 3; /* get last 3 chars of name */
13106 sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
13107 return(zsyscmd(temp));
13110 /* O N G E T T Y -- Turn on getty(1m) for the communications tty line */
13113 ongetty(ttname) char *ttname; {
13115 while (*ttname != '\0') ttname++; /* comms tty path name */
13117 sprintf(temp,"/usr/bin/geton.sh %s",ttname);
13118 return(zsyscmd(temp));
13120 #endif /* ATT7300 */
13122 /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
13124 * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
13125 * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
13126 * 2 = Auto: For "modem direct": The same as "Off".
13127 * For real modem types: Heed carrier during connect, but ignore
13128 * it anytime else. Compatible with pre-5A C-Kermit versions.
13130 * As you can see, this setting does not affect dialing, which always ignores
13131 * carrier (unless there is some special exception for some modem type). It
13132 * does affect ttopen() if it is set before ttopen() is used. This setting
13133 * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
13134 * (or should be) always called before any communications is tried, which
13135 * means that, practically speaking, the effect is immediate.
13137 * Of course, nothing of this applies to remote mode (xlocal = 0).
13139 * Someone has yet to uncover how to manipulate the carrier in the BSD
13140 * environment (or any non-termio using environment). Until that time, this
13141 * will simply be a no-op for BSD.
13143 * Note that in previous versions, the carrier was most often left unchanged
13144 * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX. This
13145 * has changed. Now it is controlled by ttcarr in conjunction with these
13149 ttscarr(carrier) int carrier; {
13151 debug(F101, "ttscarr","",ttcarr);
13155 /* C A R R C T L -- Set tty modes for carrier treatment.
13157 * Sets the appropriate bits in a termio or sgttyb struct for carrier control
13158 * (actually, there are no bits in sgttyb for that), or performs any other
13159 * operations needed to control this on the current system. The function does
13160 * not do the actual TCSETA or stty, since often we want to set other bits too
13161 * first. Don't call this function when xlocal is 0, or the tty is not opened.
13163 * We don't know how to do anything like carrier control on non-ATTSV systems,
13164 * except, apparently, ultrix. See above. It is also known that this doesn't
13165 * have much effect on a Xenix system. For Xenix, one should switch back and
13166 * forth between the upper and lower case device files. Maybe later.
13167 * Presently, Xenix will stick to the mode it was opened with.
13169 * carrier: 0 = ignore carrier, 1 = require carrier.
13170 * The current state is saved in curcarr, and checked to save labour.
13174 #ifdef BSD44ORPOSIX
13175 carrctl(ttpar, carrier) struct termios *ttpar; int carrier;
13177 carrctl(ttpar, carrier) struct termio *ttpar; int carrier;
13178 #endif /* BSD44ORPOSIX */
13180 debug(F101, "carrctl","",carrier);
13182 ttpar->c_cflag &= ~CLOCAL;
13184 ttpar->c_cflag |= CLOCAL;
13187 #else /* Berkeley, V7, et al... */
13189 carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
13190 debug(F101, "carrctl","",carrier);
13191 if (carrier == curcarr)
13197 Old code from somebody at DEC that tends to get stuck, time out, etc.
13200 ioctl(ttyfd, TIOCMODEM, &temp);
13201 ioctl(ttyfd, TIOCHPCL, 0);
13203 /* (According to the manuals, TIOCNCAR should be preferred */
13204 /* over TIOCNMODEM...) */
13205 ioctl(ttyfd, TIOCNMODEM, &temp);
13209 New code from Jamie Watson that, he says, eliminates the problems.
13212 ioctl(ttyfd, TIOCCAR);
13213 ioctl(ttyfd, TIOCHPCL);
13215 ioctl(ttyfd, TIOCNCAR);
13217 #endif /* COMMENT */
13218 #endif /* ultrix */
13221 #endif /* SVORPOSIX */
13224 /* T T G M D M -- Get modem signals */
13226 Looks for RS-232 modem signals, and returns those that are on in as its
13227 return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
13230 -2 if the communication device does not have modem control (e.g. telnet)
13232 >= 0 on success, with a bit mask containing the modem signals that are on.
13236 Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
13237 modem control, namely the TIOCMGET ioctl.
13246 #endif /* SUNOS4 */
13249 SCO OpenServer R5.0.4. The TIOCMGET definition is hardwired in because it
13250 is skipped in termio.h when _POSIX_SOURCE is defined. But _POSIX_SOURCE
13251 must be defined in order to get the high serial speeds that are new to
13252 5.0.4. However, the regular SCO drivers do not implement TIOCMGET, so the
13253 ioctl() returns -1 with errno 22 (invalid function). But third-party
13254 drivers, e.g. for Digiboard, do implement it, and so it should work on ports
13255 driven by those drivers.
13259 #define TIOCMGET (('t'<<8)|29)
13260 #endif /* TIOCMGET */
13261 #endif /* SCO_OSR504 */
13264 /* Because POSIX strictness in <sys/termio.h> won't let us see these. */
13266 #define TIOCM_DTR 0x0002 /* data terminal ready */
13267 #define TIOCM_RTS 0x0004 /* request to send */
13268 #define TIOCM_CTS 0x0020 /* clear to send */
13269 #define TIOCM_CAR 0x0040 /* carrier detect */
13270 #define TIOCM_RNG 0x0080 /* ring */
13271 #define TIOCM_DSR 0x0100 /* data set ready */
13272 #define TIOCM_CD TIOCM_CAR
13273 #define TIOCM_RI TIOCM_RNG
13274 #endif /* TIOCM_DTR */
13275 #endif /* CK_SCOV5 */
13282 #endif /* TIOCMGET */
13285 "A serial communication program that can't read modem signals
13286 is like a car without windows."
13292 #include <sys/qioctl.h>
13294 unsigned long y, mdmbits[2];
13297 if (xlocal && ttyfd < 0)
13301 if (netconn) { /* Network connection */
13303 if (istncomport()) {
13307 #endif /* TN_COMPORT */
13308 return(-2); /* No modem signals */
13310 #endif /* NETCONN */
13313 if (ttpipe) return(-2);
13314 #endif /* NETCMD */
13316 if (ttpty) return(-2);
13317 #endif /* NETPTY */
13322 * From <sys/qioctl.h>:
13324 * SERIAL devices (all Dev.ser versions)
13325 * 0 : DTR 8 = Data Bits 0 16 - reserved 24 - reserved
13326 * 1 : RTS 9 = Data Bits 1 17 - reserved 25 - reserved
13327 * 2 = Out 1 10 = Stop Bits 18 - reserved 26 - reserved
13328 * 3 = Int Enable 11 = Par Enable 19 - reserved 27 - reserved
13329 * 4 = Loop 12 = Par Even 20 = CTS 28 - reserved
13330 * 5 - reserved 13 = Par Stick 21 = DSR 29 - reserved
13331 * 6 - reserved 14 : Break 22 = RI 30 - reserved
13332 * 7 - reserved 15 = 0 23 = CD 31 - reserved
13335 x = qnx_ioctl(ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4);
13336 debug(F101,"ttgmdm qnx_ioctl","",x);
13337 debug(F101,"ttgmdm qnx_ioctl errno","",errno);
13339 debug(F101,"ttgmdm qnx_ioctl mdmbits[0]","",mdmbits[0]);
13340 debug(F101,"ttgmdm qnx_ioctl mdmbits[1]","",mdmbits[1]);
13342 if (y & 0x000001L) z |= BM_DTR; /* Bit 0 */
13343 if (y & 0x000002L) z |= BM_RTS; /* Bit 1 */
13344 if (y & 0x100000L) z |= BM_CTS; /* Bit 20 */
13345 if (y & 0x200000L) z |= BM_DSR; /* Bit 21 */
13346 if (y & 0x400000L) z |= BM_RNG; /* Bit 22 */
13347 if (y & 0x800000L) z |= BM_DCD; /* Bit 23 */
13348 debug(F101,"ttgmdm qnx result","",z);
13349 debug(F110,"ttgmdm qnx CD = ",(z & BM_DCD) ? "On" : "Off", 0);
13354 #ifdef HPUX /* HPUX has its own way */
13357 #ifdef HPUX10 /* Modem flag word */
13358 mflag y; /* mflag typedef'd in <sys/modem.h> */
13366 unsigned long y; /* Not sure about pre-8.0... */
13369 #endif /* HPUX10 */
13371 if (xlocal && ttyfd < 0)
13375 if (netconn) { /* Network connection */
13377 if (istncomport()) {
13381 #endif /* TN_COMPORT */
13382 return(-2); /* No modem signals */
13384 #endif /* NETCONN */
13387 if (ttpipe) return(-2);
13388 #endif /* NETCMD */
13390 if (ttpty) return(-2);
13391 #endif /* NETPTY */
13393 if (xlocal) /* Get modem signals */
13394 x = ioctl(ttyfd,MCGETA,&y);
13396 x = ioctl(0,MCGETA,&y);
13397 if (x < 0) return(-1);
13398 debug(F101,"ttgmdm","",y);
13400 z = 0; /* Initialize return value */
13402 /* Now set bits for each modem signal that is reported to be on. */
13405 /* Clear To Send */
13406 debug(F101,"ttgmdm HPUX CTS","",y & MCTS);
13407 if (y & MCTS) z |= BM_CTS;
13410 /* Data Set Ready */
13411 debug(F101,"ttgmdm HPUX DSR","",y & MDSR);
13412 if (y & MDSR) z |= BM_DSR;
13416 debug(F101,"ttgmdm HPUX DCD","",y & MDCD);
13417 if (y & MDCD) z |= BM_DCD;
13420 /* Ring Indicate */
13421 debug(F101,"ttgmdm HPUX RI","",y & MRI);
13422 if (y & MRI) z |= BM_RNG;
13425 /* Data Terminal Ready */
13426 debug(F101,"ttgmdm HPUX DTR","",y & MDTR);
13427 if (y & MDTR) z |= BM_DTR;
13430 /* Request To Send */
13431 debug(F101,"ttgmdm HPUX RTS","",y & MRTS);
13432 if (y & MRTS) z |= BM_RTS;
13441 Note, TIOCMGET might already have been defined in <sys/ioctl.h> or elsewhere.
13442 If not, we try including <sys/ttycom.h> -- if this blows up then more ifdefs
13446 #include <sys/ttycom.h>
13447 #endif /* TIOCMGET */
13451 debug(F100,"ttgmdm K_MDMCTL defined","",0);
13454 if (netconn) { /* Network connection */
13456 if (istncomport()) {
13460 #endif /* TN_COMPORT */
13461 return(-2); /* No modem signals */
13463 #endif /* NETCONN */
13466 if (ttpipe) return(-2);
13467 #endif /* NETCMD */
13469 if (ttpty) return(-2);
13470 #endif /* NETPTY */
13472 if (xlocal && ttyfd < 0)
13476 x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */
13478 x = ioctl(0,TIOCMGET,&y);
13479 debug(F101,"ttgmdm TIOCMGET ioctl","",x);
13481 debug(F101,"ttgmdm errno","",errno);
13484 debug(F101,"ttgmdm bits","",y);
13486 z = 0; /* Initialize return value. */
13488 /* Clear To Send */
13489 if (y & TIOCM_CTS) z |= BM_CTS;
13490 debug(F101,"ttgmdm TIOCM_CTS defined","",TIOCM_CTS);
13492 debug(F100,"ttgmdm TIOCM_CTS not defined","",0);
13495 /* Data Set Ready */
13496 if (y & TIOCM_DSR) z |= BM_DSR;
13497 debug(F101,"ttgmdm TIOCM_DSR defined","",TIOCM_DSR);
13499 debug(F100,"ttgmdm TIOCM_DSR not defined","",0);
13503 if (y & TIOCM_CAR) z |= BM_DCD;
13504 debug(F101,"ttgmdm TIOCM_CAR defined","",TIOCM_CAR);
13506 debug(F100,"ttgmdm TIOCM_CAR not defined","",0);
13509 /* Ring Indicate */
13510 if (y & TIOCM_RNG) z |= BM_RNG;
13511 debug(F101,"ttgmdm TIOCM_RNG defined","",TIOCM_RNG);
13513 debug(F100,"ttgmdm TIOCM_RNG not defined","",0);
13516 /* Data Terminal Ready */
13517 if (y & TIOCM_DTR) z |= BM_DTR;
13518 debug(F101,"ttgmdm TIOCM_DTR defined","",TIOCM_DTR);
13520 debug(F100,"ttgmdm TIOCM_DTR not defined","",0);
13523 /* Request To Send */
13524 if (y & TIOCM_RTS) z |= BM_RTS;
13525 debug(F101,"ttgmdm TIOCM_RTS defined","",TIOCM_RTS);
13527 debug(F100,"ttgmdm TIOCM_RTS not defined","",0);
13532 #else /* !K_MDMCTL catch-All */
13534 debug(F100,"ttgmdm K_MDMCTL not defined","",0);
13536 debug(F100,"ttgmdm TIOCMGET defined","",0);
13538 debug(F100,"ttgmdm TIOCMGET not defined","",0);
13539 #endif /* TIOCMGET */
13541 debug(F100,"ttgmdm _SVID3 defined","",0);
13543 debug(F100,"ttgmdm _SVID3 not defined","",0);
13544 #endif /* _SVID3 */
13547 if (netconn) { /* Network connection */
13549 if (istncomport()) {
13553 #endif /* TN_COMPORT */
13554 return(-2); /* No modem signals */
13556 #endif /* NETCONN */
13559 if (ttpipe) return(-2);
13560 #endif /* NETCMD */
13562 if (ttpty) return(-2);
13563 #endif /* NETPTY */
13565 return(-3); /* Sorry, I don't know how... */
13567 #endif /* K_MDMCTL */
13572 /* P S U S P E N D -- Put this process in the background. */
13575 Call with flag nonzero if suspending is allowed, zero if not allowed.
13576 Returns 0 on apparent success, -1 on failure (flag was zero, or
13577 kill() returned an error code.
13580 psuspend(flag) int flag; {
13583 extern int rtu_bug;
13586 if (flag == 0) return(-1);
13593 The big question here is whether job control is *really* supported.
13594 There's no way Kermit can know for sure. The fact that SIGTSTP is
13595 defined does not guarantee the Unix kernel supports it, and the fact
13596 that the Unix kernel supports it doesn't guarantee that the user's
13597 shell (or other process that invoked Kermit) supports it.
13602 if (kill(0,SIGSTOP) < 0
13604 /* Let's try this for MIPS too. */
13605 && kill(getpid(),SIGSTOP) < 0
13607 ) { /* If job control, suspend the job */
13609 debug(F101,"psuspend error","",errno);
13612 debug(F100,"psuspend ok","",0);
13616 #endif /* SIGTSTP */
13621 setuid package, by Kristoffer Eriksson, with contributions from Dean
13625 /* The following is for SCO when CK_ANSILIBS is defined... */
13628 #ifndef NOGETID_PROTOS
13629 #define NOGETID_PROTOS
13630 #endif /* NOGETID_PROTOS */
13631 #endif /* CK_ANSILIBS */
13632 #endif /* M_UNIX */
13634 #ifndef _POSIX_SOURCE
13642 #ifndef NOGETID_PROTOS
13643 _PROTOTYP( UID_T getuid, (void) );
13644 _PROTOTYP( UID_T geteuid, (void) );
13645 _PROTOTYP( UID_T getreuid, (void) );
13646 _PROTOTYP( UID_T getgid, (void) );
13647 _PROTOTYP( UID_T getegid, (void) );
13648 _PROTOTYP( UID_T getregid, (void) );
13649 #endif /* NOGETID_PROTOS */
13651 _PROTOTYP( UID_T getreuid, (void) );
13652 _PROTOTYP( UID_T getregid, (void) );
13653 #endif /* COHERENT */
13654 #endif /* HPUX10 */
13656 #endif /* sequent */
13657 #endif /* PS2AIX10 */
13659 #endif /* SUNOS4 */
13660 #endif /* _POSIX_SOURCE */
13663 Subject: Set-user-id
13664 To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
13665 Date: Sat, 21 Apr 90 4:48:25 MES
13666 From: Kristoffer Eriksson <ske@pkmab.se>
13668 This is a set of functions to be used in programs that may be run set-user-id
13669 and/or set-group-id. They handle both the case where the program is not run
13670 with such privileges (nothing special happens then), and the case where one
13671 or both of these set-id modes are used. The program is made to run with the
13672 user's real user and group ids most of the time, except for when more
13673 privileges are needed. Don't set-user-id to "root".
13675 This works on System V and POSIX. In BSD, it depends on the
13676 "saved-set-user-id" feature.
13679 #define UID_ROOT 0 /* Root user and group ids */
13683 The following code defines the symbol SETEUID for UNIX systems based
13684 on BSD4.4 (either -Encumbered or -Lite). This program will then use
13685 seteuid() and setegid() instead of setuid() and setgid(), which still
13686 don't allow arbitrary switching. It also avoids setreuid() and
13687 setregid(), which are included in BSD4.4 for compatibility only, are
13688 insecure, and print warnings to stderr under at least one system (NetBSD
13689 1.0). Note that POSIX systems should still use setuid() and setgid();
13690 the seteuid() and setegid() functions are BSD4.4 extensions to the
13691 POSIX model. Mike Long <mike.long@analog.com>, 8/94.
13698 The following construction automatically defines the symbol SETREUID for
13699 UNIX versions based on Berkeley Unix 4.2 and 4.3. If this symbol is
13700 defined, then this program will use getreuid() and getregid() calls in
13701 preference to getuid() and getgid(), which in Berkeley-based Unixes do
13702 not allow arbitrary switching back and forth of real & effective uid.
13703 This construction also allows -DSETREUID to be put on the cc command line
13704 for any system that has and wants to use setre[ug]id(). It also prevents
13705 automatic definition of SETREUID if -DNOSETREU is included on the cc
13706 command line (or otherwise defined).
13708 #ifdef FT18 /* None of this for Fortune. */
13719 #endif /* SETEUID */
13720 #endif /* NOSETREU */
13721 #endif /* SETREUID */
13722 #endif /* !BSD41 */
13723 #endif /* !BSD29 */
13724 #endif /* ANYBSD */
13726 /* Variables for user and group IDs. */
13728 static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
13729 static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
13732 /* P R I V _ I N I -- Initialize privileges package */
13734 /* Called as early as possible in a set-uid or set-gid program to store the
13735 * set-to uid and/or gid and step down to the users real uid and gid. The
13736 * stored id's can be temporarily restored (allowed in System V) during
13737 * operations that require the privilege. Most of the time, the program
13738 * should execute in unpriviliged state, to not impose any security threat.
13740 * Note: Don't forget that access() always uses the real id:s to determine
13741 * file access, even with privileges restored.
13743 * Returns an error mask, with error values or:ed together:
13744 * 1 if setuid() fails,
13745 * 2 if setgid() fails, and
13746 * 4 if the program is set-user-id to "root", which can't be handled.
13748 * Only the return value 0 indicates real success. In case of failure,
13749 * those privileges that could be reduced have been, at least, but the
13750 * program should be aborted none-the-less.
13752 * Also note that these functions do not expect the uid or gid to change
13753 * without their knowing. It may work if it is only done temporarily, but
13754 * you're on your own.
13760 #ifndef HAVE_LOCKDEV
13762 /* Save real ID:s. */
13763 realuid = getuid();
13764 realgid = getgid();
13766 /* Save current effective ID:s, those set to at program exec. */
13767 privuid = geteuid();
13768 privgid = getegid();
13770 /* If running set-uid, go down to real uid, otherwise remember that
13771 * no privileged uid is available.
13775 * 1) If the real uid is already "root" and the set-uid uid (the
13776 * initial effective uid) is not "root", then we would have trouble
13777 * if we went "down" to "root" here, and then temporarily back to the
13778 * set-uid uid (not "root") and then again tried to become "root". I
13779 * think the "saved set-uid" is lost when changing uid from effective
13780 * uid "root", which changes all uid, not only the effective uid. But
13781 * in this situation, we can simply go to "root" and stay there all
13782 * the time. That should give sufficient privilege (understatement!),
13783 * and give the right uids for subprocesses.
13785 * 2) If the set-uid (the initial effective uid) is "root", and we
13786 * change uid to the real uid, we can't change it back to "root" when
13787 * we need the privilege, for the same reason as in 1). Thus, we can't
13788 * handle programs that are set-user-id to "root" at all. The program
13789 * should be stopped. Use some other uid. "root" is probably too
13790 * privileged for such things, anyway. (The uid is reverted to the
13791 * real uid until termination.)
13793 * These two exceptions have the effect that the "root" uid will never
13794 * be one of the two uids that are being switched between, which also
13795 * means we don't have to check for such cases in the switching
13798 * Note that exception 1) is handled by these routines (by constantly
13799 * running with uid "root", while exception 2) is a serious error, and
13800 * is not provided for at all in the switching functions.
13802 if (realuid == privuid)
13803 privuid = (UID_T) -1; /* Not running set-user-id. */
13805 /* If running set-gid, go down to real gid, otherwise remember that
13806 * no privileged gid is available.
13808 * There are no exception like there is for the user id, since there
13809 * is no group id that is privileged in the manner of uid "root".
13810 * There could be equivalent problems for group changing if the
13811 * program sometimes ran with uid "root" and sometimes not, but
13812 * that is already avoided as explained above.
13814 * Thus we can expect always to be able to switch to the "saved set-
13815 * gid" when we want, and back to the real gid again. You may also
13816 * draw the conclusion that set-gid provides for fewer hassles than
13821 fprintf(stderr,"UID_ROOT=%d\n",UID_ROOT);
13822 fprintf(stderr,"realuid=%d\n",realuid);
13823 fprintf(stderr,"privuid=%d\n",privuid);
13824 #endif /* SUIDDEBUG */
13826 if (realgid == privgid) /* If not running set-user-id, */
13827 privgid = (GID_T) -1; /* remember it this way. */
13829 err = priv_off(); /* Turn off setuid privilege. */
13831 if (privuid == UID_ROOT) /* If setuid to root, */
13832 err |= 4; /* return this error. */
13834 if (realuid == UID_ROOT) { /* If real id is root, */
13835 privuid = (UID_T) -1; /* stay root at all times. */
13837 /* If Kermit installed SUID uucp and user is running as root */
13838 err &= ~1; /* System V R0 does not save UID */
13839 #endif /* ATT7300 */
13841 #endif /* HAVE_LOCKDEV */
13846 /* Macros for hiding the differences in UID/GID setting between various Unix
13847 * systems. These macros should always be called with both the privileged ID
13848 * and the non-privileged ID. The one in the second argument, will become the
13849 * effective ID. The one in the first argument will be retained for later
13854 /* On BSD systems with the saved-UID feature, we just juggle the effective
13855 * UID back and forth, and leave the real UID at its true value. The kernel
13856 * allows switching to both the current real UID, the effective UID, and the
13857 * UID which the program is set-UID to. The saved set-UID always holds the
13858 * privileged UID for us, and the real UID will always be the non-privileged,
13859 * and we can freely choose one of them for the effective UID at any time.
13861 #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
13862 #define switchgid(hidden,active) setregid( (GID_T) -1, active)
13864 #else /* SETREUID,!SAVEDUID */
13866 /* On systems with setreXid() but without the saved-UID feature, notably
13867 * BSD 4.2, we swap the real and effective UIDs each time. It's
13868 * the effective UID that we are interested in, but we have to retain the
13869 * unused UID somewhere to enable us to restore it later, and we do this
13870 * in the real UID. The kernel only allows switching to either the current
13871 * real or the effective UID, unless you're "root".
13873 #define switchuid(hidden,active) setreuid(hidden,active)
13874 #define switchgid(hidden,active) setregid(hidden,active)
13877 #else /* !SETREUID, !SAVEDUID */
13881 BSD 4.4 works similarly to System V and POSIX (see below), but uses
13882 seteXid() instead of setXid() to change effective IDs. In addition, the
13883 seteXid() functions work the same for "root" as for other users.
13885 #define switchuid(hidden,active) seteuid(active)
13886 #define switchgid(hidden,active) setegid(active)
13888 #else /* !SETEUID */
13890 /* On System V and POSIX, the only thing we can change is the effective UID
13891 * (unless the current effective UID is "root", but initsuid() avoids that for
13892 * us). The kernel allows switching to the current real UID or to the saved
13893 * set-UID. These are always set to the non-privileged UID and the privileged
13894 * UID, respectively, and we only change the effective UID. This breaks if
13895 * the current effective UID is "root", though, because for "root" setuid/gid
13896 * becomes more powerful, which is why initsuid() treats "root" specially.
13897 * Note: That special treatment maybe could be ignored for BSD? Note: For
13898 * systems that don't fit any of these four cases, we simply can't support
13901 #define switchuid(hidden,active) setuid(active)
13902 #define switchgid(hidden,active) setgid(active)
13904 #endif /* SETEUID */
13905 #endif /* SETREUID */
13908 /* P R I V _ O N -- Turn on the setuid and/or setgid */
13910 /* Go to the privileged uid (gid) that the program is set-user-id
13911 * (set-group-id) to, unless the program is running unprivileged.
13912 * If setuid() fails, return value will be 1. If getuid() fails it
13913 * will be 2. Return immediately after first failure, and the function
13914 * tries to restore any partial work done. Returns 0 on success.
13915 * Group id is changed first, since it is less serious than user id.
13919 #ifndef HAVE_LOCKDEV
13920 if (privgid != (GID_T) -1)
13921 if (switchgid(realgid,privgid))
13924 if (privuid != (UID_T) -1)
13925 if (switchuid(realuid,privuid)) {
13926 if (privgid != (GID_T) -1)
13927 switchgid(privgid,realgid);
13930 #endif /* HAVE_LOCKDEV */
13934 /* P R I V _ O F F -- Turn on the real uid and gid */
13936 /* Return to the unprivileged uid (gid) after an temporary visit to
13937 * privileged status, unless the program is running without set-user-id
13938 * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
13939 * in setgid() or:ed together. The functions tries to return both uid
13940 * and gid to unprivileged state, regardless of errors. Returns 0 on
13946 #ifndef HAVE_LOCKDEV
13947 if (privuid != (UID_T) -1)
13948 if (switchuid(privuid,realuid))
13951 if (privgid != (GID_T) -1)
13952 if (switchgid(privgid,realgid))
13954 #endif /* HAVE_LOCKDEV */
13958 /* Turn off privilege permanently. No going back. This is necessary before
13959 * a fork() on BSD43 machines that don't save the setUID or setGID, because
13960 * we swap the real and effective ids, and we don't want to let the forked
13961 * process swap them again and get the privilege back. It will work on other
13962 * machines too, such that you can rely on its effect always being the same,
13963 * for instance, even when you're in priv_on() state when this is called.
13964 * (Well, that part about "permanent" is on System V only true if you follow
13965 * this with a call to exec(), but that's what we want it for anyway.)
13966 * Added by Dean Long -- dlong@midgard.ucsc.edu
13970 #ifndef HAVE_LOCKDEV
13973 if (privuid != (UID_T) -1)
13974 if (setreuid(realuid,realuid))
13977 if (privgid != (GID_T) -1)
13978 if (setregid(realgid,realgid))
13986 if (privuid != (UID_T) -1)
13987 if (setuid(realuid)) {
13988 debug(F101,"setuid failed","",errno);
13990 debug(F101,"ruid","",getuid());
13991 debug(F101,"euid","",geteuid());
13993 debug(F101,"setuid","",realuid);
13994 if (privgid != (GID_T) -1)
13995 if (setgid(realgid)) {
13996 debug(F101,"setgid failed","",errno);
13998 debug(F101,"rgid","",getgid());
13999 debug(F101,"egid","",getegid());
14001 debug(F101,"setgid","",realgid);
14004 /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
14005 return(priv_off());
14006 #endif /* SETEUID */
14007 #endif /* SETREUID */
14010 #endif /* HAVE_LOCKDEV */
14013 /* P R I V _ O P N -- For opening protected files or devices. */
14016 priv_opn(name, modes) char *name; int modes; {
14018 priv_on(); /* Turn privileges on */
14019 debug(F111,"priv_opn",name,modes);
14021 x = open(name, modes); /* Try to open the device */
14022 debug(F101,"priv_opn result","",x);
14023 debug(F101,"priv_opn errno","",errno);
14024 priv_off(); /* Turn privileges off */
14025 return(x); /* Return open's return code */
14028 /* P R I V _ C H K -- Check privileges. */
14030 /* Try to turn them off. If turning them off did not succeed, cancel them */
14035 x = priv_off(); /* Turn off privs. */
14036 if (x != 0 || getuid() == privuid || geteuid() == privuid)
14038 if (x != 0 || getgid() == privgid || getegid() == privgid)
14039 y = y | priv_can();
14049 ttimoff() { /* Turn off any timer interrupts */
14052 As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
14053 SIG_DFL (to catch alarms, or if there is no handler, to exit). This is to
14054 cure (mask, really) a deeper problem with stray alarms that occurs on some
14055 systems, possibly having to do with sleep(), that caused core dumps. It
14056 should be OK to do this, because no code in this module uses nested alarms.
14057 (But we still have to watch out for SCRIPT and DIAL...)
14059 /* xx = */ alarm(0);
14060 /* debug(F101,"ttimoff alarm","",xx); */
14061 if (saval) { /* Restore any previous */
14062 signal(SIGALRM,saval); /* alarm handler. */
14063 /* debug(F101,"ttimoff alarm restoring saval","",saval); */
14066 signal(SIGALRM,SIG_IGN); /* Used to be SIG_DFL */
14067 /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
14073 tt_is_secure() { /* Tells whether the current connection is secure */
14081 #endif /* SSHBUILTIN */
14082 #ifdef CK_ENCRYPTION
14083 || ck_tn_encrypting() && ck_tn_decrypting()
14084 #endif /* CK_ENCRYPTION */
14086 || tls_active_flag || ssl_active_flag
14087 #endif /* CK_SSL */
14090 #ifdef CK_ENCRYPTION
14091 || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
14092 #endif /* CK_ENCRYPTION */
14093 #endif /* CK_KERBEROS */
14094 #endif /* RLOGCODE */
14102 /* External protocol handler parameters from ckuus3.c */
14103 extern int exp_handler, exp_stderr, exp_timo;
14108 /* The right size is 24576 */
14110 #ifndef PTY_PBUF_SIZE /* Size of buffer to read from pty */
14111 #define PTY_PBUF_SIZE 24576 /* and write to net. */
14112 #endif /* PTY_PBUF_SIZE */
14114 #ifndef PTY_TBUF_SIZE /* Size of buffer to read from net */
14115 #define PTY_TBUF_SIZE 24576 /* and write to pty. */
14116 #endif /* PTY_TBUF_SIZE */
14118 #ifdef O_NDELAY /* Whether to use nonblocking */
14119 #ifndef PTY_NO_NDELAY /* reads on the pseudoterminal */
14120 #ifndef PTY_USE_NDELAY
14121 #define PTY_USE_NDELAY
14122 #endif /* PTY_USE_NDELAY */
14123 #endif /* PTY_NO_NDELAY */
14124 #endif /* O_NDELAY */
14126 #ifndef HAVE_OPENPTY
14127 #ifndef USE_CKUPTY_C
14128 #define USE_CKUPTY_C
14129 #endif /* USE_CKUPTY_C */
14130 #endif /* HAVE_OPENPTY */
14133 pty_make_raw(fd) int fd; {
14136 #ifdef BSD44ORPOSIX /* POSIX */
14139 #ifdef ATTSV /* AT&T UNIX */
14141 struct termio tp = {0};
14144 #endif /* CK_ANSIC */
14146 struct sgttyb tp; /* Traditional */
14148 #endif /* BSD44ORPOSIX */
14150 debug(F101,"pty_make_raw fd","",fd);
14153 #ifdef BSD44ORPOSIX /* POSIX */
14154 x = tcgetattr(fd,&tp);
14155 debug(F101,"pty_make_raw tcgetattr","",x);
14157 #ifdef ATTSV /* AT&T UNIX */
14158 x = ioctl(fd,TCGETA,&tp);
14159 debug(F101,"pty_make_raw TCGETA ioctl","",x);
14162 debug(F101,"pty_make_raw ttty","",x);
14164 #endif /* BSD44ORPOSIX */
14165 debug(F101,"pty_make_raw GET errno","",errno);
14167 #ifdef USE_CFMAKERAW
14170 debug(F101,"pty_make_raw cfmakeraw errno","",errno);
14171 #else /* USE_CFMAKERAW */
14175 /* This very simple version recommended by Serg Iakolev doesn't work */
14177 tp.c_lflag &= ~(ECHO|ICANON|IEXTEN|ISIG);
14178 tp.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
14179 tp.c_cflag &= ~(CSIZE|PARENB);
14181 tp.c_oflag &= ~(OPOST);
14183 tp.c_cc[VTIME] = 0;
14185 debug(F101,"pty_make_raw 1 c_cc[] NCCS","",NCCS);
14186 debug(F101,"pty_make_raw 1 iflags","",tp.c_iflag);
14187 debug(F101,"pty_make_raw 1 oflags","",tp.c_oflag);
14188 debug(F101,"pty_make_raw 1 lflags","",tp.c_lflag);
14189 debug(F101,"pty_make_raw 1 cflags","",tp.c_cflag);
14194 In this version we unset everything and then set only the
14195 bits we know we need.
14199 tp.c_iflag |= IGNBRK;
14201 tp.c_iflag |= IMAXBEL;
14202 #endif /* IMAXBEL */
14210 tp.c_lflag |= NOKERNINFO;
14211 #endif /* NOKERNINFO */
14215 tp.c_cflag |= CS8|CREAD;
14217 for (i = 0; i < NCCS; i++) { /* No special characters */
14221 tp.c_cc[VMIN] = 1; /* But always wait for input */
14223 debug(F101,"pty_make_raw 2 c_cc[] NCCS","",NCCS);
14224 debug(F101,"pty_make_raw 2 iflags","",tp.c_iflag);
14225 debug(F101,"pty_make_raw 2 oflags","",tp.c_oflag);
14226 debug(F101,"pty_make_raw 2 lflags","",tp.c_lflag);
14227 debug(F101,"pty_make_raw 2 cflags","",tp.c_cflag);
14229 #else /* COMMENT */
14231 In this version we set or unset every single flag explicitly. It works a
14232 bit better than the simple version just above, but it's still far from
14236 tp.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
14237 tp.c_iflag &= ~(INPCK|IGNPAR|IXANY|IXON|IXOFF);
14238 tp.c_iflag |= IGNBRK;
14241 tp.c_iflag |= IMAXBEL;
14243 tp.c_iflag &= ~IMAXBEL;
14244 #endif /* COMMENT */
14245 #endif /* IMAXBEL */
14247 tp.c_iflag &= ~IUCLC;
14252 tp.c_oflag &= ~BSDLY;
14255 tp.c_oflag &= ~CRDLY;
14258 tp.c_oflag &= ~FFDLY;
14261 tp.c_oflag &= ~NLDLY;
14264 tp.c_oflag &= ~TABDLY;
14265 #endif /* TABDLY */
14267 tp.c_oflag &= ~VTDLY;
14270 tp.c_oflag &= ~OFDEL;
14273 tp.c_oflag &= ~OFILL;
14276 tp.c_oflag &= ~OLCUC;
14279 tp.c_oflag &= ~CMSPAR;
14280 #endif /* CMSPAR */
14281 tp.c_oflag &= ~OPOST;
14283 tp.c_oflag &= ~OXTABS;
14284 #endif /* OXTABS */
14287 tp.c_oflag &= ~ONOCR; /* Maybe should be |=? */
14288 tp.c_oflag |= ONOCR; /* makes no difference either way */
14290 #endif /* COMMENT */
14292 tp.c_oflag &= ~ONOEOT;
14293 #endif /* ONOEOT */
14295 tp.c_oflag &= ~ONLRET;
14296 #endif /* ONLRET */
14298 tp.c_oflag &= ~ONLCR;
14301 tp.c_oflag &= ~OCRNL;
14305 tp.c_lflag &= ~ECHO;
14307 tp.c_lflag &= ~ECHOE;
14310 tp.c_lflag &= ~ECHONL;
14311 #endif /* ECHONL */
14313 tp.c_lflag &= ~ECHOPRT;
14314 #endif /* ECHOPRT */
14316 tp.c_lflag &= ~ECHOKE;
14317 #endif /* ECHOKE */
14319 tp.c_lflag &= ~ECHOCTL;
14320 #endif /* ECHOCTL */
14322 tp.c_lflag &= ~XCASE;
14325 tp.c_lflag &= ~ALTWERASE;
14326 #endif /* ALTWERASE */
14328 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN|EXTPROC);
14330 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
14331 #endif /* EXTPROC */
14333 tp.c_lflag |= NOKERNINFO;
14334 #endif /* NOKERNINFO */
14336 tp.c_lflag &= ~NOFLSH; /* TRY IT THE OTHER WAY? */
14338 tp.c_lflag |= NOFLSH; /* No, this way is worse */
14339 #endif /* COMMENT */
14342 tp.c_cflag &= ~(CSIZE|PARENB|PARODD);
14343 tp.c_cflag |= CS8|CREAD;
14346 tp.c_cflag &= ~(MDMBUF);
14349 tp.c_cflag &= ~(CCAR_OFLOW); /* two names for the same thing */
14350 #endif /* CCAR_OFLOW */
14351 #endif /* MDMBUF */
14354 tp.c_cflag &= ~(CCTS_OFLOW);
14355 #endif /* CCTS_OFLOW */
14357 tp.c_cflag &= ~(CDSR_OFLOW);
14358 #endif /* CDSR_OFLOW */
14360 tp.c_cflag &= ~(CDTR_IFLOW);
14361 #endif /* CDTR_IFLOW */
14363 tp.c_cflag &= ~(CRTS_IFLOW);
14364 #endif /* CRTS_IFLOW */
14366 tp.c_cflag &= ~(CRTSXOFF);
14367 #endif /* CRTSXOFF */
14369 tp.c_cflag &= ~(CRTSCTS);
14370 #endif /* CRTSCTS */
14372 tp.c_cflag &= ~(CLOCAL);
14373 #endif /* CLOCAL */
14375 tp.c_cflag &= ~(CSTOPB);
14376 #endif /* CSTOPB */
14378 tp.c_cflag &= ~(HUPCL);
14381 for (i = 0; i < NCCS; i++) { /* No special characters */
14385 tp.c_cc[VMIN] = 1; /* But always wait for input */
14387 debug(F101,"pty_make_raw 3 c_cc[] NCCS","",NCCS);
14388 debug(F101,"pty_make_raw 3 iflags","",tp.c_iflag);
14389 debug(F101,"pty_make_raw 3 oflags","",tp.c_oflag);
14390 debug(F101,"pty_make_raw 3 lflags","",tp.c_lflag);
14391 debug(F101,"pty_make_raw 3 cflags","",tp.c_cflag);
14392 #endif /* COMMENT */
14393 #endif /* COMMENT */
14396 #ifdef BSD44ORPOSIX /* POSIX */
14397 x = tcsetattr(fd,TCSANOW,&tp);
14398 debug(F101,"pty_make_raw tcsetattr","",x);
14400 #ifdef ATTSV /* AT&T UNIX */
14401 x = ioctl(fd,TCSETA,&tp);
14402 debug(F101,"pty_make_raw ioctl","",x);
14404 x = stty(fd,&tp); /* Traditional */
14405 debug(F101,"pty_make_raw stty","",x);
14407 #endif /* BSD44ORPOSIX */
14408 debug(F101,"pty_make_raw errno","",errno);
14410 #endif /* __NetBSD__ */
14414 pty_chk(fd) int fd; {
14418 x = ioctl(fd, FIONREAD, &n); /* BSD and most others */
14419 ckmakmsg(msgbuf,500,
14420 "pty_chk ioctl FIONREAD errno=",
14424 debug(F100,msgbuf,"",0);
14428 debug(F101,"pty_chk rdchk","",n);
14432 #endif /* FIONREAD */
14433 return((n > -1) ? n : 0);
14437 pty_get_status(fd,pid) int fd; PID_T pid; {
14438 int x, status = -1;
14441 debug(F101,"pty_get_status fd","",fd);
14442 debug(F101,"pty_get_status pid","",pid);
14444 if (pexitstat > -1)
14448 /* Not only unnecessary but harmful */
14450 x = kill(pty_fork_pid,0);
14451 debug(F101,"pty_get_status kill value","",x);
14452 debug(F101,"pty_get_status kill errno","",errno);
14453 if (x > -1 && errno != ESRCH)
14454 return(-1); /* Fork still there */
14455 /* Fork seems to be gone */
14456 #endif /* COMMENT */
14459 x = waitpid(pty_fork_pid,&status,WNOHANG);
14460 debug(F111,"pty_get_status waitpid",ckitoa(errno),x);
14461 if (x <= 0 && errno == 0) {
14462 debug(F101,"pty_get_status waitpid return","",-1);
14466 if (x != pty_fork_pid)
14468 "pty_get_status waitpid pid doesn't match","",pty_fork_pid);
14469 debug(F101,"pty_get_status waitpid status","",status);
14470 debug(F101,"pty_get_status waitpid errno","",errno);
14471 if (WIFEXITED(status)) {
14472 debug(F100,"pty_get_status WIFEXITED","",0);
14473 status = WEXITSTATUS(status);
14474 debug(F101,"pty_get_status fork exit status","",status);
14477 #endif /* COMMENT */
14479 pexitstat = status;
14481 debug(F100,"pty_get_status waitpid unexpected status","",0);
14484 debug(F101,"pty_get_status return status","",status);
14488 /* t t p t y c m d -- Run command on pty and forward to net */
14491 Needed for running external protocols on secure connections.
14492 For example, if C-Kermit has made an SSL/TLS or Kerberos Telnet
14493 connection, and then needs to transfer a file with Zmodem, which is
14494 an external program, this routine reads Zmodem's output, encrypts it,
14495 and then forwards it out the connection, and reads the encrypted data
14496 stream coming in from the connection, decrypts it, and forwards it to
14499 Works like a TCP/IP port forwarder except one end is a pty rather
14500 than a socket, which introduces some complications:
14502 . On most platforms, select() always indicates the output side of
14503 the pty has characters waiting to be read, even when it doesn't,
14504 even when the pty process has already exited.
14506 . Nonblocking reads must be used on the pty, because there is no
14507 way on certain platforms (e.g. NetBSD) to find out how many characters
14508 are available to be read (the FIONREAD ioctl always says 0). The code
14509 also allows for blocking reads (if O_NDELAY and O_NONBLOCK are not
14510 defined, or if PTY_NO_NDELAY is defined), but on some platforms this can
14511 result in single-byte reads and writes (NetBSD again).
14513 . Testing for "EOF" on the pty is problematic. select() never gives
14514 any indication. After the pty process has exited and the fork has
14515 disappeared, read() can still return with 0 bytes read but without an
14516 error (NetBSD); no known test on the pty file descriptor will indicate
14517 that it is no longer valid. The process ID of the pty fork can be
14518 tested on some platforms (NetBSD, luckily) but not others (Solaris,
14521 On the network side, we use ttinc() and ttoc(), which, for network
14522 connections, handle any active security methods.
14524 Call with s = command.
14525 Returns 0 on failure, 1 on success.
14526 fdc - December 2006 - August 2007.
14528 NOTE: This code defaults to nonblocking reads if O_NDELAY or O_NONBLOCK are
14529 defined in the header files, which should be true of every recent Unix
14530 platform. If this causes trouble somewhere, define PTY_NO_NDELAY, e.g. when
14534 make platformname KFLAGS=-DPTY_NO_NODELAY
14536 static int have_pty = 0; /* Do we have a pty? */
14538 static SIGTYP (*save_sigchld)() = NULL; /* For catching SIGCHLD */
14541 sigchld_handler(sig) int sig; {
14542 have_pty = 0; /* We don't have a pty */
14544 if (save_sigchld) {
14545 (VOID) signal(SIGCHLD,save_sigchld);
14546 save_sigchld = NULL;
14549 debug(F100,"**************","",0);
14550 debug(F100,"SIGCHLD caught","",0);
14551 debug(F100,"**************","",0);
14559 ttptycmd(s) char *s; {
14560 CHAR tbuf[PTY_TBUF_SIZE]; /* Read from net, write to pty */
14561 int tbuf_avail = 0; /* Pointers for tbuf */
14562 int tbuf_written = 0;
14563 static int in_state = 0; /* For TELNET IAC and NVT in */
14564 static int out_prev = 0; /* Simpler scheme for out */
14566 CHAR pbuf[PTY_PBUF_SIZE]; /* Read from pty, write to net */
14567 CHAR dbuf[PTY_PBUF_SIZE + PTY_PBUF_SIZE + 1]; /* Double-size buffer */
14568 int pbuf_avail = 0; /* Pointers for pbuf */
14569 int pbuf_written = 0;
14571 int ptyfd = -1; /* Pty file descriptor */
14572 int have_net = 0; /* We have a network connection */
14573 int pty_err = 0; /* Got error on pty */
14574 int net_err = 0; /* Got error on net */
14575 int status = -1; /* Pty process exit status */
14576 int rc = 0; /* Our return code */
14578 int x1 = 0, x2 = 0; /* Workers... */
14579 int c, n, m, t, x; /* Workers */
14581 long seconds_to_wait = 0L; /* select() timeout */
14582 struct timeval tv, *tv2; /* For select() */
14584 int in, out, err; /* For select() */
14586 fd_set in, out, err;
14587 #endif /* INTSELECT */
14588 int nfds = 0; /* For select() */
14590 int pset = 0, tset = 0, pnotset = 0, tnotset = 0; /* stats/debuggin only */
14591 int read_net_bytes = 0; /* Stats */
14592 int write_net_bytes = 0; /* Stats */
14593 int read_pty_bytes = 0; /* Stats */
14594 int write_pty_bytes = 0; /* Stats */
14595 int is_tn = 0; /* TELNET protocol is active */
14599 #ifndef USE_CKUPTY_C
14600 struct termios term;
14601 struct winsize twin;
14602 struct stringarray * q;
14603 char ** args = NULL;
14604 #endif /* USE_CKUPTY_C */
14606 in_state = 0; /* No previous character yet */
14609 printf("?Sorry, communication channel is not open\n");
14615 debug(F100,"ttptycmd fail: nopush","",0);
14618 if (!s) s = ""; /* Defense de bogus arguments */
14619 if (!*s) return(0);
14620 pexitstat = -1; /* Fork process exit status */
14623 is_tn = (xlocal && netconn && IS_TELNET()) || /* Telnet protocol active */
14624 (!xlocal && sstelnet);
14625 #endif /* TNCODE */
14627 debug(F110,"ttptycmd command",s,0);
14628 debug(F101,"ttptycmd ttyfd","",ttyfd);
14629 debug(F101,"ttptycmd is_tn","",is_tn);
14630 debug(F101,"ttptycmd ckermit pid","",getpid());
14632 #ifdef USE_CKUPTY_C
14633 /* Call ckupty.c module to get and set up the pty fork */
14634 /* fc 1 == "run an external protocol" */
14635 debug(F100,"ttptycmd using ckupty.c","",0);
14636 if (do_pty(&ptyfd,s,1) < 0) { /* Start the command on a pty */
14637 debug(F100,"ttptycmd do_pty fails","",0);
14641 pty_master_fd = ptyfd;
14643 slavefd = pty_slave_fd; /* This is not visible to us */
14644 #endif /* COMMENT */
14645 debug(F111,"ttptycmd ptyfd","USE_CKUPTY_C",ptyfd);
14646 debug(F111,"ttptycmd masterfd","USE_CKUPTY_C",masterfd);
14647 debug(F111,"ttptycmd fork pid","USE_CKUPTY_C",pty_fork_pid);
14649 /* "ioctl inappropriate on device" for pty master */
14650 pty_make_raw(masterfd);
14651 #endif /* SOLARIS */
14653 #else /* USE_CKUPTY_C */
14655 debug(F100,"ttptycmd OPENPTY","",0);
14656 if (tcgetattr(0, &term) == -1) { /* Get controlling terminal's modes */
14657 perror("tcgetattr");
14660 if (ioctl(0, TIOCGWINSZ, (char *) &twin) == -1) { /* and window size */
14661 perror("ioctl TIOCGWINSZ");
14664 if (openpty(&masterfd, &slavefd, NULL, NULL, NULL) == -1) {
14665 debug(F101,"ttptycmd openpty failed errno","",errno);
14669 debug(F101,"ttptycmd openpty masterfd","",masterfd);
14670 debug(F101,"ttptycmd openpty slavefd","",slavefd);
14671 pty_master_fd = masterfd;
14672 pty_slave_fd = slavefd;
14673 debug(F101,"ttptycmd openpty pty_master_fd","",pty_master_fd);
14675 /* Put pty master in raw mode but let forked app control the slave */
14676 pty_make_raw(masterfd);
14680 /* TIOCREMOTE,0 = disable all termio processing */
14681 x = ioctl(masterfd, TIOCREMOTE, 1);
14682 debug(F111,"ttptycmd ioctl TIOCREMOTE",ckitoa(x),errno);
14683 #endif /* TIOCREMOTE */
14685 /* TIOCTTY,0 = disable all termio processing */
14686 x = ioctl(masterfd, TIOCTTY, 0);
14687 debug(F111,"ttptycmd ioctl TIOCTTY",ckitoa(x),errno);
14688 #endif /* TIOCTTY */
14689 #endif /* COMMENT */
14691 have_pty = 1; /* We have an open pty */
14692 save_sigchld = signal(SIGCHLD, sigchld_handler); /* Catch fork quit */
14694 pty_fork_pid = fork(); /* Make fork for external protocol */
14695 debug(F101,"ttptycmd pty_fork_pid","",pty_fork_pid);
14696 if (pty_fork_pid == -1) {
14699 } else if (pty_fork_pid == 0) { /* In new fork */
14701 debug(F101,"ttptycmd new fork pid","",getpid());
14702 close(masterfd); /* Slave quarters no masters allowed */
14704 debug(F101,"ttptycmd new fork setsid","",x);
14706 perror("ttptycmd setsid");
14709 signal(SIGINT,SIG_IGN); /* Let upper fork catch this */
14713 /* Make pty the controlling terminal for the process */
14714 /* THIS CAUSES AN INFINITE SIGWINCH INTERRUPT LOOP */
14715 x = ioctl(slavefd, TIOCSCTTY, NULL);
14716 debug(F101,"ttptycmd TIOCSCTTY","",x);
14717 #endif /* TIOCSCTTY */
14718 #endif /* COMMENT */
14720 /* Initialize slave pty modes and size to those of our terminal */
14721 if (tcsetattr(slavefd, TCSANOW, &term) == -1) {
14722 perror("ttptycmd tcsetattr");
14725 if (ioctl(slavefd, TIOCSWINSZ, &twin) == -1) {
14726 perror("ttptycmd ioctl");
14731 /* Disassociate this process from its terminal */
14732 /* THIS HAS NO EFFECT */
14733 x = ioctl(slavefd, TIOCNOTTY, NULL);
14734 debug(F101,"ttptycmd TIOCNOTTY","",x);
14735 #endif /* TIOCNOTTY */
14736 #endif /* COMMENT */
14740 /* Ignore terminal output interrupts */
14741 /* THIS HAS NO EFFECT */
14742 debug(F100,"ttptycmd ignoring SIGTTOU","",0);
14743 signal(SIGTTOU, SIG_IGN);
14744 #endif /* SIGTTOU */
14746 /* Ignore terminal output interrupts */
14747 /* THIS HAS NO EFFECT */
14748 debug(F100,"ttptycmd ignoring SIGTSTP","",0);
14749 signal(SIGTSTP, SIG_IGN);
14750 #endif /* SIGTSTP */
14751 #endif /* COMMENT */
14753 pty_make_raw(slavefd); /* Put it in rawmode */
14756 if (dup2(slavefd, STDIN_FILENO) != STDIN_FILENO ||
14757 dup2(slavefd, STDOUT_FILENO) != STDOUT_FILENO) {
14758 debug(F101,"ttptycmd new fork dup2 error","",errno);
14759 perror("ttptycmd dup2");
14762 debug(F100,"ttptycmd new fork dup2 ok","",0);
14764 /* Parse external protocol command line */
14765 q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0);
14767 debug(F100,"ttptycmd cksplit failed","",0);
14771 debug(F100,"ttptycmd cksplit ok","",0);
14773 args = q->a_head + 1;
14774 for (i = 0; i <= n; i++) {
14778 /* sometimes cksplit() doesn't terminate the list */
14779 if ((i == n) && args[i]) {
14780 if ((int)strlen(args[i]) == 0)
14781 makestr(&(args[i]),NULL);
14788 Putting the slave pty in rawmode should not be necessary because the
14789 external protocol program is supposed to do that itself. Yet doing this
14790 here cuts down on Zmodem binary-file transmission errors by 30-50% but
14791 still doesn't eliminate them.
14793 pty_make_raw(STDIN_FILENO);
14794 pty_make_raw(STDOUT_FILENO);
14795 #endif /* COMMENT */
14797 debug(F100,"ttptycmd execvp'ing external protocol","",0);
14798 execvp(args[0],args);
14799 perror("execvp failed");
14800 debug(F101,"ttptycmd execvp failed","",errno);
14804 /* (there are better ways to do this...) */
14805 msleep(1000); /* Make parent wait for child to be ready */
14806 ptyfd = masterfd; /* We talk to the master */
14808 #endif /* USE_CKUPTY_C */
14810 debug(F101,"ttptycmd ptyfd","",ptyfd);
14812 printf("?Failure to get pty\n");
14815 have_pty = 1; /* We have an open pty or we wouldn't he here */
14817 debug(F101,"ttptycmd PTY_PBUF_SIZE","",PTY_PBUF_SIZE);
14818 debug(F101,"ttptycmd PTY_TBUF_SIZE","",PTY_TBUF_SIZE);
14820 #ifdef PTY_USE_NDELAY
14822 NOTE: If select() and ioctl(ptyfd,FIONREAD,&n) return true indications
14823 on the pty, we don't need nonblocking reads. Performance of either
14824 method seems to be about the same, so use whatever works.
14827 x = fcntl(ptyfd,F_SETFL,fcntl(ptyfd,F_GETFL, 0)|O_NDELAY);
14828 ckmakmsg(msgbuf,500,
14829 "ttptycmd set O_NDELAY errno=",
14833 debug(F100,msgbuf,"",0);
14834 #endif /* PTY_USE_NDELAY */
14837 /* Not necessary, the protocol module already did this */
14839 #ifdef USE_CFMAKERAW
14840 if (tcgetattr(ttyfd, &term) > -1) {
14842 debug(F101,"ttptycmd net cfmakeraw errno","",errno);
14843 x tcsetattr(ttyfd, TCSANOW, &term);
14844 debug(F101,"ttptycmd net tcsetattr","",x);
14845 debug(F101,"ttptycmd net tcsetattr","",errno);
14848 if (local) /* Put network connection in */
14849 ttpkt(ttspeed,ttflow,ttprty); /* "packet mode". */
14851 conbin((char)escchr); /* OR... pty_make_raw(0) */
14852 #endif /* USE_CFMAKERAW */
14853 #endif /* COMMENT */
14857 debug(F101,"<<< ttptycmd TELOPT_ME_BINARY","",TELOPT_ME(TELOPT_BINARY));
14858 debug(F101,"<<< ttptycmd TELOPT_U_BINARY","",TELOPT_U(TELOPT_BINARY));
14860 #endif /* TNCODE */
14862 debug(F101,"ttptycmd entering loop - seconds_to_wait","",seconds_to_wait);
14864 while (have_pty || have_net) {
14865 FD_ZERO(&in); /* Initialize select() structs */
14867 FD_ZERO(&err); /* (not used because useless) */
14870 debug(F101,"ttptycmd loop top have_pty","",have_pty);
14871 debug(F101,"ttptycmd loop top have_net","",have_net);
14873 /* Pty is open and we have room to read from it? */
14874 if (have_pty && pbuf_avail < PTY_PBUF_SIZE) {
14875 debug(F100,"ttptycmd FD_SET ptyfd in","",0);
14876 FD_SET(ptyfd, &in);
14879 /* Network is open and we have room to read from it? */
14880 if (have_net && have_pty && tbuf_avail < PTY_TBUF_SIZE) {
14881 debug(F100,"ttptycmd FD_SET ttyfd in","",0);
14882 FD_SET(ttyfd, &in);
14883 if (ttyfd > nfds) nfds = ttyfd;
14885 /* Pty is open and we have stuff to write to it? */
14886 if (have_pty && tbuf_avail - tbuf_written > 0) {
14887 debug(F100,"ttptycmd FD_SET ptyfd out","",0);
14888 FD_SET (ptyfd, &out);
14889 if (ptyfd > nfds) nfds = ptyfd;
14891 /* Net is open and we have stuff to write to it? */
14892 debug(F101,"ttptycmd pbuf_avail-pbuf_written","",
14893 pbuf_avail - pbuf_written);
14894 if (have_net && pbuf_avail - pbuf_written > 0) {
14895 debug(F100,"ttptycmd FD_SET ttyfd out","",0);
14896 FD_SET (ttyfd, &out);
14897 if (ttyfd > nfds) nfds = ttyfd;
14899 /* We don't use err because it's not really for errors, */
14900 /* but for out of band data on the TCP socket, which, if it is */
14901 /* to be handled at all, is handled in the tt*() routines */
14903 nfds++; /* 0-based to 1-based */
14904 debug(F101,"ttptycmd nfds","",nfds);
14906 debug(F100,"ttptycmd NO FDs set for select","",0);
14908 /* This is not right -- sleeping won't accomplish anything */
14909 debug(F101,"ttptycmd msleep","",100);
14912 debug(F100,"ttptycmd no pty - quitting loop","",0);
14918 if (seconds_to_wait > 0L) { /* Timeout in case nothing happens */
14919 tv.tv_sec = seconds_to_wait; /* for a long time */
14925 x = select(nfds, &in, &out, NULL, tv2);
14926 debug(F101,"ttptycmd select","",x);
14928 if (errno == EINTR)
14930 debug(F101,"ttptycmd select error","",errno);
14934 debug(F101,"ttptycmd +++ select timeout","",seconds_to_wait);
14936 status = pty_get_status(ptyfd,pty_fork_pid);
14937 debug(F101,"ttptycmd pty_get_status A","",status);
14938 if (status > -1) pexitstat = status;
14943 /* We want to handle any pending writes first to make room */
14944 /* for new incoming. */
14946 if (FD_ISSET(ttyfd, &out)) { /* Can write to net? */
14948 s = pbuf + pbuf_written; /* Current spot for sending */
14950 if (is_tn) { /* ttol() doesn't double IACs */
14951 CHAR c; /* Rewrite string with IACs doubled */
14953 s = pbuf + pbuf_written; /* Source */
14955 for (i = 0; i < pbuf_avail - pbuf_written; i++) {
14956 c = s[i]; /* Next character */
14957 if (c == IAC) { /* If it's IAC */
14958 dbuf[x++] = c; /* put another one */
14959 debug(F000,">>> QUOTED IAC","",c);
14960 } else if (c != 0x0a && out_prev == 0x0d) { /* Bare CR */
14961 if (!TELOPT_ME(TELOPT_BINARY)) { /* NVT rule */
14964 debug(F000,">>> CR-NUL","",c);
14967 dbuf[x++] = c; /* Copy and count it */
14968 debug(F000,">>> char",ckitoa(in_state),c);
14971 s = dbuf; /* New source */
14973 #endif /* TNCODE */
14974 x = pbuf_avail - pbuf_written; /* How much to send */
14976 debug(F101,"ttptycmd bytes to send","",x);
14978 debug(F101,">>> ttol","",x);
14981 debug(F111,"ttptycmd ttol error",ckitoa(x),errno);
14984 write_net_bytes += x;
14987 if (FD_ISSET(ptyfd, &out)) { /* Can write to pty? */
14988 debug(F100,"ttptycmd FD_ISSET ptyfd out","",0);
14991 x = write(ptyfd,tbuf + tbuf_written,tbuf_avail - tbuf_written);
14993 /* Byte loop to rule out data overruns in the pty */
14994 /* (it makes no difference) */
14996 char *p = tbuf+tbuf_written;
14997 int n = tbuf_avail - tbuf_written;
14998 for (x = 0; x < n; x++) {
15000 if (write(ptyfd,&(p[x]),1) < 0)
15004 #endif /* COMMENT */
15005 debug(F111,"ttptycmd ptyfd write",ckitoa(errno),x);
15008 write_pty_bytes += x;
15012 if (pexitstat < 0) {
15013 status = pty_get_status(ptyfd,pty_fork_pid);
15014 debug(F101,"ttptycmd pty_get_status B","",status);
15015 if (status > -1) pexitstat = status;
15018 debug(F100,"ttptycmd +++ ptyfd write error","",0);
15021 if (FD_ISSET(ttyfd, &in)) { /* Can read from net? */
15023 debug(F100,"ttptycmd FD_ISSET ttyfd in","",0);
15024 n = in_chk(1,ttyfd);
15025 debug(F101,"ttptycmd in_chk(ttyfd)","",n);
15026 if (n < 0 || ttyfd == -1) {
15027 debug(F101,"ttptycmd +++ ttyfd errno","",errno);
15029 } else if (n > 0) {
15030 if (n > PTY_TBUF_SIZE - tbuf_avail)
15031 n = PTY_TBUF_SIZE - tbuf_avail;
15032 debug(F101,"ttptycmd net read size adjusted","",n);
15033 if (xlocal && netconn) {
15035 We have to use a byte loop here because ttxin()
15036 does not decrypt or, for that matter, handle Telnet.
15040 p = tbuf + tbuf_avail;
15041 for (x = 0; x < n; x++) {
15042 if ((c = ttinc(0)) < 0)
15044 if (!is_tn) { /* Not Telnet - keep all bytes */
15046 debug(F000,"<<< char","",c);
15048 } else { /* Telnet - must handle IAC and NVT */
15049 debug(F000,"<<< char",ckitoa(in_state),c);
15051 case 0x00: /* NUL */
15052 if (in_state == HAVE_CR) {
15053 debug(F000,"<<< SKIP","",c);
15056 debug(F000,"<<< Keep","",c);
15060 case 0x0d: /* CR */
15061 if (!TELOPT_U(TELOPT_BINARY))
15062 in_state = HAVE_CR;
15064 debug(F000,"<<< Keep","",c);
15067 case 0x0f: /* Ctrl-O */
15068 case 0x16: /* Ctrl-V */
15071 debug(F000,"<<< QUOT","",c);
15073 #endif /* COMMENT */
15074 case 0xff: /* IAC */
15075 if (in_state == HAVE_IAC) {
15076 debug(F000,"<<< KEEP","",c);
15080 debug(F000,"<<< SKIP","",c);
15081 in_state = HAVE_IAC;
15084 default: /* All others */
15085 if (in_state == HAVE_IAC) {
15088 tn_doop() will consume an unknown number of bytes and we'll overshoot
15089 the for-loop. The only Telnet command I've ever seen arrive here is
15090 a Data Mark, which comes when the remote protocol exits and the remote
15091 job returns to its shell prompt. On the assumption it's a 1-byte command,
15092 we don't write out the IAC or the command, and we clear the state. If
15093 we called tn_doop() we'd have no way of knowing how many bytes it took
15094 from the input stream.
15097 xx = tn_doop((CHAR)c,duplex,ttinc);
15098 debug(F111,"<<< DOOP",ckctoa(c),xx);
15100 debug(F101,"<<< DOOP","",c);
15101 #endif /* COMMENT */
15105 debug(F000,"<<< keep","",c);
15109 #endif /* TNCODE */
15112 ckmakmsg(msgbuf,500,
15113 "ttptycmd read net [ttinc loop] errno=",
15117 debug(F100,msgbuf,"",0);
15119 x = ttxin(n,tbuf+tbuf_avail);
15120 debug(F101,"ttptycmd ttxin x","",x);
15124 debug(F101,"ttptycmd read net error","",x);
15128 read_net_bytes += x;
15134 if (FD_ISSET(ptyfd, &in)) { /* Read from pty? */
15136 debug(F100,"ttptycmd FD_ISSET ptyfd in","",0);
15137 #ifdef PTY_USE_NDELAY
15141 This does not work on nonblocking channels
15142 on certain platforms such as NetBSD.
15144 n = pty_chk(ptyfd);
15145 #endif /* PTY_USE_NDELAY */
15146 debug(F101,"ttptycmd pty_chk() n","",n);
15151 if (n > PTY_PBUF_SIZE - pbuf_avail)
15152 n = PTY_PBUF_SIZE - pbuf_avail;
15153 debug(F101,"ttptycmd pty read size adjusted","",n);
15155 x = read(ptyfd,pbuf+pbuf_avail,n);
15158 ckmakmsg(msgbuf,500,
15159 "ttptycmd read pty errno=",
15163 debug(F100,msgbuf,"",0);
15167 if (x < 0 && errno == EAGAIN)
15170 if (x < 0) { /* This works on Solaris and Linux */
15171 pty_err++; /* but not NetBSD */
15172 debug(F100,"TERMINATION TEST A","",0);
15176 #endif /* COMMENT */
15177 if (pexitstat < 0) {
15178 status = pty_get_status(ptyfd,pty_fork_pid);
15179 debug(F101,"ttptycmd pty_get_status C","",status);
15180 if (status > -1) pexitstat = status;
15185 if (x == 0 && !pty_err) { /* This works on NetBSD but */
15186 debug(F100,"TERMINATION TEST B","",0);
15187 status = pexitstat > -1 ? pexitstat :
15188 pty_get_status(ptyfd,pty_fork_pid);
15189 debug(F101,"ttptycmd pty_get_status D","",status);
15191 pexitstat = status;
15194 } else { /* Select() lied */
15195 pty_err = 0; /* pty still there but has nothing */
15196 msleep(100); /* sleep a bit */
15200 /* Hopefully the next two are no longer needed... */
15202 #ifndef PTY_USE_NDELAY
15205 errno != 0 && errno != EAGAIN
15206 #endif /* PTY_USE_NDELAY */
15208 debug(F100,"TERMINATION TEST C","",0);
15210 debug(F101,"ttptycmd SET pty_err","",pty_err);
15211 if (errno == EIO) /* errno == EIO is like EOF */
15219 pbuf[pbuf_avail + x] = '\0';
15220 debug(F111,"ttptycmd added to pty buffer",
15221 pbuf+pbuf_avail,x);
15224 #endif /* COMMENT */
15226 read_pty_bytes += x;
15227 } else { /* n == 0 with blocking reads */
15229 "PTY READ RETURNED ZERO BYTES - SHOULD NOT HAPPEN",
15235 /* If writes have caught up to reads, reset the buffers */
15237 if (pbuf_written == pbuf_avail)
15238 pbuf_written = pbuf_avail = 0;
15239 if (tbuf_written == tbuf_avail)
15240 tbuf_written = tbuf_avail = 0;
15242 /* See if we can exit */
15244 x1 = pbuf_avail - pbuf_written;
15245 x2 = tbuf_avail - tbuf_written;
15247 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pty_err","",pty_err);
15248 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x1 [write to net]","",x1);
15249 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x2 [write to pty]","",x2);
15250 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc","",rc);
15251 debug(F101,"ttptycmd pty_err LOOP EXIT TEST status","",status);
15252 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pexitstat","",pexitstat);
15254 if (net_err) { /* Net error? */
15255 debug(F101,"ttptycmd net_err LOOP EXIT TEST net_err","",net_err);
15259 printf("?Connection closed\n");
15263 debug(F101,"ttptycmd net_err LOOP EXIT TEST x1","",x1);
15267 if (pty_err) { /* Pty error? */
15269 if (pexitstat < 0) {
15270 status = pty_get_status(ptyfd,pty_fork_pid);
15271 debug(F101,"ttptycmd pty_get_status E","",status);
15272 if (status > -1) pexitstat = status;
15276 if (x1 == 0 && x2 == 0) { /* If buffers are caught up */
15277 rc = 1; /* set preliminary return to success */
15278 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc 2","",rc);
15279 break; /* and exit the loop */
15283 debug(F101,"ttptycmd +++ have_pty","",have_pty);
15284 if (have_pty) { /* In case select() failed */
15285 #ifdef USE_CKUPTY_C
15291 #endif /* USE_CKUPTY_C */
15293 pty_master_fd = -1;
15294 debug(F101,"ttptycmd +++ pexitstat","",pexitstat);
15295 if (pexitstat < 0) { /* Try one last time to get status */
15296 status = pty_get_status(ptyfd,pty_fork_pid);
15297 debug(F101,"ttptycmd pty_get_status F","",status);
15298 if (status > -1) pexitstat = status;
15300 debug(F101,"ttptycmd +++ final pexitstat","",pexitstat);
15301 if (deblog) { /* Stats for debug log */
15302 debug(F101,"ttptycmd +++ pset ","",pset);
15303 debug(F101,"ttptycmd +++ pnotset","",pnotset);
15304 debug(F101,"ttptycmd +++ tset ","",tset);
15305 debug(F101,"ttptycmd +++ tnotset","",tnotset);
15307 debug(F101,"ttptycmd +++ read_pty_bytes","",read_pty_bytes);
15308 debug(F101,"ttptycmd +++ write_net_bytes","",write_net_bytes);
15309 debug(F101,"ttptycmd +++ read_net_bytes","",read_net_bytes);
15310 debug(F101,"ttptycmd +++ write_pty_bytes","",write_pty_bytes);
15313 If we got the external protocol's exit status from waitpid(), we use that
15314 to set our return code. If not, we fall back on whatever rc was previously
15315 set to, namely 1 (success) if the pty fork seemed to terminate, 0 otherwise.
15317 if (save_sigchld) { /* Restore this if we changed it */
15318 (VOID) signal(SIGCHLD,save_sigchld);
15319 save_sigchld = NULL;
15322 x = kill(pty_fork_pid,SIGHUP); /* In case it's still there */
15324 debug(F101,"ttptycmd fork kill SIGHUP","",x);
15325 if (pexitstat > -1)
15326 rc = (pexitstat == 0 ? 1 : 0);
15327 debug(F101,"ttptycmd +++ rc","",rc);
15328 if (!local) { /* If in remote mode */
15329 conres(); /* restore console to CBREAK mode */
15330 concb((char)escchr);
15334 #endif /* NETPTY */
15335 #endif /* SELECT */
15337 /* T T R U N C M D -- Redirect an external command over the connection. */
15340 TTRUNCMD is the routine that was originally used for running external
15341 protocols. It is very simple and works fine provided (a) the connection
15342 is not encrypted, and (b) the external protocol uses standard i/o
15343 (file descriptors 0 and 1) for file transfer.
15347 ttruncmd(s) char *s; {
15348 PID_T pid; /* pid of lower fork */
15349 int wstat; /* for wait() */
15354 printf("?Sorry, device is not open\n");
15358 debug(F100,"ttruncmd fail: nopush","",0);
15364 It might also be necessary to use the pty routine for other reasons,
15365 e.g. because the external program does not use stdio.
15369 If we have a network connection we use a different routine because
15370 (a) if the connection is encrypted, the mechanism used here can't deal
15371 with it; and (b) it won't handle any network protocols either, e.g.
15372 Telnet, Rlogin, K5 U-to-U, etc. However, this routine works much
15373 better (faster, more transparent) on serial connections and when
15374 C-Kermit is in remote mode (i.e. is on the far end).
15376 /* For testing always use this */
15378 return(ttptycmd(s));
15379 #endif /* NETCONN */
15383 if (tt_is_secure()) {
15385 external protocols over secure connections not supported in this OS.\n"
15389 #endif /* NETPTY */
15391 conres(); /* Make console normal */
15393 if ((pid = fork()) == 0) { /* Make a child fork */
15394 if (priv_can()) /* Child: turn off privs. */
15396 dup2(ttyfd, 0); /* Give stdin/out to the line */
15399 debug(F101,"ttruncmd system",s,x);
15400 _exit(x ? BAD_EXIT : 0);
15402 SIGTYP (*istat)(), (*qstat)();
15403 if (pid == (PID_T) -1) /* fork() failed? */
15405 istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
15406 qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
15409 while (((wstat = wait(&statusp)) != pid) && (wstat != -1)) ;
15410 #else /* Not COMMENT */
15412 wstat = wait(&statusp);
15413 debug(F101,"ttruncmd wait","",wstat);
15414 if (wstat == pid || wstat == -1)
15417 #endif /* COMMENT */
15419 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
15420 debug(F101,"ttruncmd wait statusp","",statusp);
15421 debug(F101,"ttruncmd wait pexitstat","",pexitstat);
15422 signal(SIGINT,istat); /* Restore interrupts */
15423 signal(SIGQUIT,qstat);
15425 concb((char)escchr); /* Restore console to CBREAK mode */
15426 return(statusp == 0 ? 1 : 0);
15428 #endif /* CK_REDIR */
15432 cmdate2tm(char * date, int gmt) /* date as "yyyymmdd hh:mm:ss" */
15434 cmdate2tm(date,gmt) char * date; int gmt;
15437 /* date as "yyyymmdd hh:mm:ss" */
15438 static struct tm _tm;
15441 if (strlen(date) != 17 ||
15449 _tm = *gmtime(&now);
15451 _tm = *localtime(&now);
15452 _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
15453 (date[2]-'0')*10 + (date[3]-'0')-1900;
15454 _tm.tm_mon = (date[4]-'0')*10 + (date[5]-'0')-1;
15455 _tm.tm_mday = (date[6]-'0')*10 + (date[7]-'0');
15456 _tm.tm_hour = (date[9]-'0')*10 + (date[10]-'0');
15457 _tm.tm_min = (date[12]-'0')*10 + (date[13]-'0');
15458 _tm.tm_sec = (date[15]-'0')*10 + (date[16]-'0');
15460 /* Should we set _tm.tm_isdst to -1 here? */
15474 priv_kill(pid, sig) int pid, sig; {
15478 debug(F100,"priv_kill priv_on failed","",0);
15479 i = kill(pid, sig);
15481 debug(F100,"priv_kill priv_off failed","",0);
15487 /* #ifdef BE_DR_7 */
15489 alarm() function not supplied with Be OS DR7 - this one contributed by
15494 This should mimic the UNIX/POSIX alarm() function well enough, with the
15495 caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
15496 and wait for the alarm thread to finish.
15499 alarm(unsigned int seconds) {
15500 long time_left = 0;
15502 /* If an alarm is active, turn it off, saving the unused time */
15503 if (alarm_thread != -1) {
15504 /* We'll be generous and count partial seconds as whole seconds. */
15505 time_left = alarm_struct.time -
15506 ((system_time() - time_started) / 1000000.0);
15508 /* Kill the alarm thread */
15509 kill_thread (alarm_thread);
15511 /* We need to clean up as though the alarm occured. */
15513 alarm_struct.thread = -1;
15514 alarm_struct.time = 0;
15518 /* Set a new alarm clock, if requested. */
15520 alarm_struct.thread = find_thread(NULL);
15521 alarm_struct.time = seconds;
15522 time_started = system_time();
15523 alarm_thread = spawn_thread (do_alarm,
15526 (void *) &alarm_struct
15528 resume_thread (alarm_thread);
15531 /* Now return [unused time | 0] */
15532 return ((unsigned int) time_left);
15536 This function is the departure from UNIX/POSIX alarm handling. In the case
15537 of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
15538 handler. When Be implements alarm(), this function call can be eliminated
15539 from user's SIGALRM signal handlers.
15543 alarm_expired(void) {
15546 if (alarm_thread != -1) {
15547 wait_for_thread (alarm_thread, &ret_val);
15553 This is the function that snoozes the requisite number of seconds and then
15554 SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
15555 uses thread_id; currently they are both typdef'ed as long, but I'll do the
15556 cast anyway. This function is run in a separate thread.
15560 do_alarm (void *alarm_struct) {
15561 snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
15562 kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
15564 ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
15565 ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
15567 /* #endif */ /* BE_DR_7 */
15568 #endif /* BEOSORBEBOX */
15573 p9ttyctl(char letter, int num, int param) {
15582 len = sprintf(cmd + 1, "%d", param) + 1;
15587 if (write(ttyctlfd, cmd, len) == len) {
15589 /* fprintf(stdout, "wrote '%s'\n", cmd); */
15596 p9ttyparity(char l) {
15597 return p9ttyctl('p', 0, l);
15601 p9tthflow(int flow, int status) {
15602 return p9ttyctl('m', 1, status);
15606 p9ttsspd(int cps) {
15607 if (p9ttyctl('b', 1, cps * 10) < 0)
15609 ttylastspeed = cps * 10;
15614 p9openttyctl(char *ttname) {
15617 if (ttyctlfd >= 0) {
15622 sprintf(name, "%sctl", ttname);
15623 ttyctlfd = open(name, 1);
15629 if (consctlfd >= 0) {
15630 if (write(consctlfd, "rawon", 5) == 5)
15643 if (consctlfd >= 0) {
15644 if (write(consctlfd, "rawoff", 6) == 6)
15651 p9sndbrk(int msec) {
15652 if (ttyctlfd >= 0) {
15654 int i = sprintf(cmd, "k%d", msec);
15655 if (write(ttyctlfd, cmd, i) == i)
15662 conwrite(char *buf, int n) {
15664 static int length = 0;
15665 static int holdingcr = 0;
15667 for (x = 0; x < n; x++) {
15671 write(1, buf + (x - normal), normal);
15675 /* write(noisefd, "1000 300", 8); */
15677 } else if (c == '\r') {
15679 write(1, buf + (x - normal), normal);
15684 } else if (c == '\n') {
15685 write(1, buf + (x - normal), normal + 1);
15689 } else if (c == '\b') {
15691 write(1, buf + (x - normal), normal);
15703 while (length-- > 0)
15705 length = 0; /* compiler bug */
15712 write(1, buf + (x - normal), normal);
15719 conprint(char *fmt, ...) {
15720 static char buf[1000]; /* not safe if on the stack */
15726 i = vsprintf(buf, fmt, ap);
15731 /* fprintf, printf, perror replacements... */
15733 /* f p r i n t f */
15737 #include <stdarg.h>
15738 #else /* CK_ANSIC */
15740 #include <stdarg.h>
15742 #include <varargs.h>
15743 #endif /* __GNUC__ */
15744 #endif /* CK_ANSIC */
15747 static char str1[4096];
15748 static char str2[4096];
15751 ckxfprintf(FILE * file, const char * format, ...)
15752 #else /* CK_ANSIC */
15753 ckxfprintf(va_alist) va_dcl
15754 #endif /* CK_ANSIC */
15756 int i, j, len, got_cr;
15761 va_start(args, format);
15762 #else /* CK_ANSIC */
15766 file = va_arg(args,FILE *);
15767 format = va_arg(args,char *);
15768 #endif /* CK_ANSIC */
15770 if (!inserver || (file != stdout && file != stderr && file != stdin)) {
15771 rc = vfprintf(file,format,args);
15774 rc = vsprintf(str1, format, args);
15775 len = strlen(str1);
15776 if (len >= sizeof(str1)) {
15777 debug(F101,"ckxfprintf() buffer overflow","",len);
15778 doexit(BAD_EXIT,1);
15780 for (i = 0, j = 0, got_cr = 0;
15781 i < len && j < sizeof(str1)-2;
15783 /* We can't use 255 as a case label because of signed chars */
15784 c = (unsigned)(str1[i] & 0xff);
15787 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15793 #endif /* TNCODE */
15798 && !TELOPT_ME(TELOPT_BINARY)
15799 #endif /* TNCODE */
15814 && !TELOPT_ME(TELOPT_BINARY)
15815 #endif /* TNCODE */
15824 && !TELOPT_ME(TELOPT_BINARY)
15825 #endif /* TNCODE */
15828 #ifdef CK_ENCRYPTION
15830 if (TELOPT_ME(TELOPT_ENCRYPTION))
15831 ck_tn_encrypt(str2,j);
15832 #endif /* TNCODE */
15833 #endif /* CK_ENCRYPTION */
15835 if (inserver && (ssl_active_flag || tls_active_flag)) {
15836 /* Write using SSL */
15839 if (ssl_active_flag)
15840 rc = SSL_write(ssl_con, p, j);
15842 rc = SSL_write(tls_con, p, j);
15843 debug(F111,"ckxfprintf","SSL_write",rc);
15844 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
15845 case SSL_ERROR_NONE:
15851 case SSL_ERROR_WANT_WRITE:
15852 case SSL_ERROR_WANT_READ:
15853 case SSL_ERROR_SYSCALL:
15856 case SSL_ERROR_WANT_X509_LOOKUP:
15857 case SSL_ERROR_SSL:
15858 case SSL_ERROR_ZERO_RETURN:
15863 #endif /* CK_SSL */
15864 fwrite(str2,sizeof(char),j,stdout);
15869 #endif /* fprintf */
15877 ckxprintf(const char * format, ...)
15878 #else /* CK_ANSIC */
15879 ckxprintf(va_alist) va_dcl
15880 #endif /* CK_ANSIC */
15882 int i, j, len, got_cr;
15887 va_start(args, format);
15888 #else /* CK_ANSIC */
15891 format = va_arg(args,char *);
15892 #endif /* CK_ANSIC */
15895 rc = vprintf(format, args);
15898 rc = vsprintf(str1, format, args);
15899 len = strlen(str1);
15900 if (len >= sizeof(str1)) {
15901 debug(F101,"ckxprintf() buffer overflow","",len);
15902 doexit(BAD_EXIT,1);
15904 for (i = 0, j = 0, got_cr=0;
15905 i < len && j < sizeof(str1)-2;
15907 c = (unsigned)(str1[i] & 0xff);
15910 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15916 #endif /* TNCODE */
15921 && !TELOPT_ME(TELOPT_BINARY)
15922 #endif /* TNCODE */
15937 && !TELOPT_ME(TELOPT_BINARY)
15938 #endif /* TNCODE */
15948 && !TELOPT_ME(TELOPT_BINARY)
15949 #endif /* TNCODE */
15952 #ifdef CK_ENCRYPTION
15954 if (TELOPT_ME(TELOPT_ENCRYPTION))
15955 ck_tn_encrypt(str2,j);
15956 #endif /* TNCODE */
15957 #endif /* CK_ENCRYPTION */
15959 if (inserver && (ssl_active_flag || tls_active_flag)) {
15961 /* Write using SSL */
15963 if (ssl_active_flag)
15964 rc = SSL_write(ssl_con, p, j);
15966 rc = SSL_write(tls_con, p, j);
15967 debug(F111,"ckxprintf","SSL_write",rc);
15968 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
15969 case SSL_ERROR_NONE:
15975 case SSL_ERROR_WANT_WRITE:
15976 case SSL_ERROR_WANT_READ:
15977 case SSL_ERROR_SYSCALL:
15980 case SSL_ERROR_WANT_X509_LOOKUP:
15981 case SSL_ERROR_SSL:
15982 case SSL_ERROR_ZERO_RETURN:
15987 #endif /* CK_SSL */
15988 rc = fwrite(str2,sizeof(char),j,stdout);
15993 #endif /* printf */
15999 _PROTOTYP(char * ck_errstr,(VOID));
16007 #endif /* CK_SCOV5 */
16010 ckxperror(const char * str)
16011 #else /* CK_ANSIC */
16012 ckxperror(str) char * str;
16013 #endif /* CK_ANSIC */
16015 char * errstr = ck_errstr();
16019 #endif /* CK_SCOV5 */
16021 ckxprintf("%s%s %s\n",str,*errstr?":":"",errstr);
16023 #endif /* perror */
16028 /* Minix doesn't have a gettimeofday call (but MINIX3 does).
16029 * We fake one here using time(2)
16034 gettimeofday(struct timeval *tp, struct timezone *tzp) {
16035 tp->tv_usec = 0L; /* Close enough for horseshoes */
16036 if(time(&(tp->tv_sec))==-1)
16040 #endif /* MINIX3 */
16044 readlink(const char *path, void *buf, size_t bufsiz) {
16048 #endif /* MINIX3 */
16050 #endif /* MINIX2 */