4 char *ckxv = "Aegis Communications support, 9.0.324, 20 June 2011";
7 char *ckxv = "Plan 9 Communications support, 9.0.324, 20 June 2011";
9 char *ckxv = "UNIX Communications support, 9.0.324, 20 June 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 */
53 #include <errno.h> /* System error numbers */
63 #endif /* __FreeBSD__ */
65 #endif /* __386BSD__ */
69 #endif /* SCO_OSR504 */
75 #define FD_SETSIZE (3 * sizeof(long) * 8)
76 static struct timeval tv;
83 #include "ckcnet.h" /* Symbols for network types. */
89 The directory-related includes are here because we need to test some
90 file-system-related symbols to find out which system we're being compiled
91 under. For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
93 #ifdef SDIRENT /* Directory bits... */
102 #else /* !NDIR, !XNDIR */
104 #include "/usr/lib/ndir.h"
105 #else /* !RTU, !NDIR, !XNDIR */
108 #include <sys/dirent.h>
112 #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
125 /* I don't know why this is needed here since we never reference bzero(). */
126 /* But without it C-Kermit won't link in an HP-UX 5.xx non-TCP build. */
128 bzero(s,n) char *s; int n; {
129 extern char * memset();
132 #endif /* TCPSOCKET */
135 /* Definition of HZ, used in msleep() */
138 #define HZ ( 1000 / CLOCK_TICK )
143 #define HZ ( 1000 / CLOCK_TICK )
146 #define nap(x) (void)syscall(3112, (x))
154 #undef NGROUPS_MAX /* Prevent multiple definition warnings */
158 NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding
159 library routine, so _poll comes up undefined at link time.
162 #ifndef AIXRS /* IBM AIX needs special handling */
163 #include <poll.h> /* "standard" (SVID) i/o multiplexing, etc */
165 #ifdef SVR4 /* AIX 3.2 is like SVID... */
167 #else /* But AIX 3.1 is not ... */
168 #include <sys/poll.h> /* The include file is in include/sys */
169 #define events reqevents /* And it does not map IBM-specific member */
170 #define revents rtnevents /* names to the System V equivalents */
175 #include <signal.h> /* Signals */
177 /* For setjmp and longjmp */
186 The following test differentiates between 4.1 BSD and 4.2 & later.
187 If you have a 4.1BSD system with the DIRENT library, this test could
188 mistakenly diagnose 4.2BSD and then later enable the use of system calls
189 that aren't defined. If indeed there are such systems, we can use some
190 other way of testing for 4.1BSD, or add yet another compile-time switch.
194 #ifndef FT21 /* Except for Fortune. */
196 #ifndef BELLV10 /* And Bell Labs Research UNIX V10 */
201 #endif /* MAXNAMLEN */
204 #ifdef SUNOS41 /* From Christian Corti */
205 #define BSD44ORPOSIX /* Uni Stuttgart */
206 #define SVORPOSIX /* February 2010 */
208 #include <sys/ioctl.h>
214 #include <sys/filio.h> /* 299 for FIONREAD */
218 Minix 2.0 support added by Terry McConnell,
219 Syracuse University <tmc@barnyard.syr.edu>
220 No more sgtty interface, posix compliant.
223 #define _MINIX /* Needed for some Minix header files */
230 #include <sys/types.h>
231 #include <sys/ioctl.h>
234 #undef TIOCGETC /* defined in sys/ioctl.h, but not really supported */
239 MINIX 1.0 support added by Charles Hedrick,
240 Rutgers University <hedrick@aramis.rutgers.edu>.
241 MINIX also has V7 enabled.
250 #ifdef CK_REDIR /* <sys/wait.h> needed only for REDIRECT command. */
252 If anybody can figure out how to make this work with NeXTSTEP, be
253 my guest! (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS)
255 #ifndef CK_WAIT_H /* If wait.h not already included... */
256 #ifdef OSF /* force OSF to select POSIX wait */
257 #ifdef _BSD /* instead of BSD (see ckcdeb.h) */
262 #include <sys/wait.h> /* Include it */
265 #define _BSD /* Restore it */
267 #endif /* CK_OSF_BSD */
269 #endif /* CK_WAIT_H */
270 #endif /* CK_REDIR */
272 #include "ckuver.h" /* Version herald */
273 char *ckxsys = HERALD;
276 #include <sys/utsname.h>
278 #ifdef TRU64 /* Tru64 UNIX 4.0 and later */
279 /* Verified on Tru64 4.0F - might break on 4.0E or earlier */
280 #include <sys/sysinfo.h> /* (don't know about OSF/1 or DU) */
281 #include <machine/hal_sysinfo.h>
284 #ifdef SOLARIS25 /* Solaris 2.5 and later */
285 #include <sys/systeminfo.h> /* (don't know about earlier ones) */
286 #endif /* SOLARIS25 */
294 static int hpis800 = 0;
295 #endif /* HPUX9PLUS */
297 #define CK_SYSNMLN SYS_NMLN
300 #define CK_SYSNMLN _SYS_NMLN
303 #define CK_SYSNMLN UTSLEN
305 #define CK_SYSNMLN 31
307 #endif /* _SYS_NMLN */
308 #endif /* SYS_NMLN */
309 char unm_mch[CK_SYSNMLN+1] = { '\0', '\0' };
310 char unm_mod[CK_SYSNMLN+1] = { '\0', '\0' };
311 char unm_nam[CK_SYSNMLN+1] = { '\0', '\0' };
312 char unm_rel[CK_SYSNMLN+1] = { '\0', '\0' };
313 char unm_ver[CK_SYSNMLN+1] = { '\0', '\0' };
314 #endif /* CK_UTSNAME */
317 #include <stat.h> /* For chasing symlinks, etc. */
319 #include <sys/stat.h>
328 /* UUCP lockfile material... */
332 #ifdef HAVE_LOCKDEV /* Red Hat baudboy/lockdev */
334 Watch out: baudboy.h references open() without making sure it has been
335 declared, resulting in warnings on at least Red Hat 7.3. It's declared in
336 fcntl.h, but we don't include that until later. In this case only, we
337 include it here, and then the second include is harmless because in Red Hat
338 Linux (the only place where you find baudboy.h) fcntl.h is protected from
339 multiple inclusion by _FCNTL_H. - fdc, 10 May 2004.
341 NOTE: Although Linux /usr/sbin/lockdev obviates the need for setuid or
342 setgid bits to access the lockfile, C-Kermit will still need them to access
343 the serial port itself unless the port is open for world read/write.
344 Normally setgid uucp does the trick.
346 Extra: HAVE_LOCKDEV has been added als openSuSE >= 11.3 doesn't use baudboy
347 but ttylock. - jb, 26 Jul 2010
349 #include <fcntl.h> /* This has to come before baudboy */
350 #ifdef HAVE_BAUDBOY /* Red Hat baudboy/lockdev */
352 #else /* !HAVE_BAUDBOY */ /* openSuSE lock via ttylock */
354 #endif /* HAVE_BAUDBOY */
355 #define LOCK_DIR "/var/lock" /* (even though we don't care) */
357 #else /* !HAVE_LOCKDEV */
361 #include <libutil.h> /* FreeBSD */
363 #include <util.h> /* OpenBSD */
364 #endif /* HAVE_LOCKDEV */
365 #endif /* __FreeBSD */
366 #endif /* USE_UU_LOCK */
367 #else /* USETTYLOCK */
369 /* Name of UUCP tty device lockfile */
375 #endif /* LINUXFSSTND */
379 #endif /* ACUCNTRL */
382 PIDSTRING means use ASCII string to represent pid in lockfile.
399 #endif /* COHERENT */
404 #endif /* PIDSTRING */
406 /* Now the PIDSTRING exceptions... */
412 #endif /* PIDSTRING */
414 #ifdef __bsdi__ /* BSDI (at least thru 1.1) */
417 #endif /* PIDSTRING */
418 #endif /* __bsdi__ */
420 #ifdef OSF32 /* Digital UNIX (OSF/1) 3.2 */
423 #endif /* PIDSTRING */
427 LOCK_DIR is the name of the lockfile directory.
428 If LOCK_DIR is already defined (e.g. on command line), we don't change it.
433 #define LOCK_DIR "/var/spool/lock"
440 #define LOCK_DIR "/var/spool/lock"
443 #define LOCK_DIR "/var/spool/lock"
446 #define LOCK_DIR "/var/spool/lock"
449 #define LOCK_DIR "/var/spool/lock"
451 /* So which ones is this for? */
452 /* Probably original 4.4BSD on Vangogh */
453 /* Plus who knows about Mac OS X... It doesn't even have a cu program */
454 #define LOCK_DIR "/var/spool/uucp"
455 #endif /* __OpenBSD__ */
456 #endif /* __NetBSD__ */
457 #endif /* __FreeBSD__ */
458 #endif /* __386BSD__ */
461 #define LOCK_DIR "/var/spool/locks"
464 #define LOCK_DIR "/var/spool/locks"
466 #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */
467 #define LOCK_DIR "/etc/locks"
470 #define LOCK_DIR "/etc/locks"
473 #define LOCK_DIR "/etc/locks"
477 #define LOCK_DIR "/usr/spool/uucp"
480 #define LOCK_DIR "/usr/spool/uucp"
483 #define LOCK_DIR "/var/spool/locks"
486 #define LOCK_DIR "/var/spool/locks"
489 #define LOCK_DIR "/var/lock";
491 #define LOCK_DIR "/usr/spool/locks"
492 #endif /* LINUXFSSTND */
499 #define LOCK_DIR "/usr/spool/uucp/LCK"
502 #define LOCK_DIR "/usr/spool/uucp"
504 #define LOCK_DIR "/usr/spool/uucp"
505 #endif /* COHERENT */
514 #endif /* !LOCK_DIR (outside ifndef) */
516 #ifdef OSF2 /* OSF/1 2.0 or later */
517 #ifdef LOCK_DIR /* (maybe 1.x too, who knows...) */
519 #define LOCK_DIR "/var/spool/locks"
520 #endif /* LOCK_DIR */
524 /* Sorry no more lockf() -- we lock first and THEN open the device. */
528 #define LOCKF /* Use lockf() on tty device in SVR4 */
534 #ifdef NOLOCKF /* But NOLOCKF cancels LOCKF */
540 /* More about this below... */
542 #endif /* USETTYLOCK */
546 MYREAD means use our internally defined nonblocking buffered read routine.
556 /* bits for attmodem: internal modem in use, restart getty */
570 #define O_NDELAY O_NONBLOCK
571 #endif /* O_NDELAY */
572 #endif /* __bsdi__ */
575 Variables available to outside world:
577 dftty -- Pointer to default tty name string, like "/dev/tty".
578 dfloc -- 0 if dftty is console, 1 if external line.
579 dfprty -- Default parity
580 dfflow -- Default flow control
581 ckxech -- Flag for who echoes console typein:
582 1 - The program (system echo is turned off)
583 0 - The system (or front end, or terminal).
584 functions that want to do their own echoing should check this flag
587 flfnam -- Name of lock file, including its path, e.g.,
588 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
589 lkflfn -- Name of link to lock file, including its paths
590 haslock -- Flag set if this kermit established a uucp lock.
591 lockpid -- PID of other process that has desired line open, as string.
592 backgrd -- Flag indicating program executing in background ( & on
593 end of shell command). Used to ignore INT and QUIT signals.
594 rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle
597 Functions for assigned communication line (either external or console tty):
599 sysinit() -- System dependent program initialization
600 syscleanup() -- System dependent program shutdown
601 ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
602 ttclos() -- Close & reset the tty, releasing any access lock.
603 ttsspd(cps) -- Set the transmission speed of the tty.
604 ttgspd() -- Get (read) the the transmission speed of the tty.
605 ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
606 ttvt(speed,flow) -- Put the tty in virtual terminal mode.
607 or in DIALING or CONNECTED modem control state.
608 ttres() -- Restore original tty modes.
609 ttscarr(carrier) -- Set carrier control mode, on/off/auto.
610 ttinl(dest,max,timo) -- Timed read line from the tty.
611 ttinc(timo) -- Timed read character from tty.
612 myread() -- Raw mode bulk buffer read, gives subsequent
613 chars one at a time and simulates FIONREAD.
614 myunrd(c) -- Places c back in buffer to be read (one only)
615 ttchk() -- See how many characters in tty input buffer.
616 ttxin(n,buf) -- Read n characters from tty (untimed).
617 ttol(string,length) -- Write a string to the tty.
618 ttoc(c) -- Write a character to the tty.
619 ttflui() -- Flush tty input buffer.
620 ttsndb() -- Send BREAK signal.
621 ttsndlb() -- Send Long BREAK signal.
623 ttlock(ttname) -- "Lock" tty device against uucp collisions.
624 ttunlck() -- Unlock tty device.
626 For ATT7300/Unix PC, System V:
627 attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
628 offgetty(ttname) -- Turns off getty(1m) for comms line
629 ongetty(ttname) -- Restores getty() to comms line
633 Functions for console terminal:
635 congm() -- Get console terminal modes.
636 concb(esc) -- Put the console in single-character wakeup mode with no echo.
637 conbin(esc) -- Put the console in binary (raw) mode.
638 conres() -- Restore the console to mode obtained by congm().
639 conoc(c) -- Unbuffered output, one character to console.
640 conol(s) -- Unbuffered output, null-terminated string to the console.
641 conola(s) -- Unbuffered output, array of strings to the console.
642 conxo(n,s) -- Unbuffered output, n characters to the console.
643 conchk() -- Check if characters available at console (bsd 4.2).
644 Check if escape char (^\) typed at console (System III/V).
645 coninc(timo) -- Timed get a character from the console.
646 congks(timo) -- Timed get keyboard scan code.
647 conint() -- Enable terminal interrupts on the console if not background.
648 connoi() -- Disable terminal interrupts on the console if not background.
652 msleep(m) -- Millisecond sleep
653 ztime(&s) -- Return pointer to date/time string
654 rtimer() -- Reset timer
655 gtimer() -- Get elapsed time since last call to rtimer()
658 /* Conditional Includes */
660 /* Whether to include <sys/file.h> */
662 #ifdef RTU /* RTU doesn't */
666 #ifdef CIE /* CIE does. */
670 #ifdef BSD41 /* 4.1 BSD doesn't */
674 #ifdef is68k /* Integrated Solutions 68000 UNIX */
675 #define NOFILEH /* e.g. on Plexux P60 and Sun-1 */
678 #ifdef MINIX /* MINIX */
682 #ifdef COHERENT /* Coherent */
684 #endif /* COHERENT */
686 #ifndef NOFILEH /* Now include if selected. */
687 #include <sys/file.h>
692 #ifdef BSD44ORPOSIX /* POSIX uses termios.h */
696 #undef _POSIX_SOURCE /* Get extra stuff from termios.h */
698 #endif /* __bsdi__ */
701 #include <sys/ioctl.h>
712 #define _POSIX_SOURCE
714 #endif /* __bsdi__ */
715 #ifndef BSD44 /* Really POSIX */
716 #ifndef CK_QNX32 /* was CK_QNX32 */
717 #define NOSYSIOCTLH /* No ioctl's allowed. */
718 #undef ultrix /* Turn off any ultrix features. */
719 #endif /* CK_QNX32 */
723 /* System III, System V */
732 /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
734 struct termiox rctsx;
738 /* Sorry, this is truly disgusting but it's SCO's fault. */
743 #endif /* SCO_OSR504 */
744 #include <sys/termiox.h>
745 struct termiox rctsx;
749 #endif /* CK_SVID3_X */
750 #endif /* STERMIOX */
754 #ifdef COHERENT /* Use termio.h, not sgtty.h for Coherent */
756 #endif /* COHERENT */
758 #ifdef MINIX /* MINIX uses ioctl's */
759 #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */
764 #ifndef NOSYSIOCTLH /* Others use ioctl() */
767 This is to get rid of cpp warning messages that occur because all of
768 these symbols are defined by both termios.h and ioctl.h on the SUN.
790 #include <sys/ioctl.h>
791 #endif /* NOSYSIOCTLH */
793 We really, really, REALLY want FIONREAD, because it is the only way to find
794 out not just *if* stuff is waiting to be read, but how much, which is
795 critical to our sliding-window and streaming procedures, not to mention
796 efficiency of CONNECT, etc.
799 #include <sys/filio.h> /* For FIONREAD */
806 /* It wasn't found in ioctl.h or term*.h - try these places: */
808 #include <sys/filio.h>
811 #include <sys/filio.h>
813 #endif /* UNIXWARE */
814 #endif /* FIONREAD */
816 #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */
818 <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as
819 something. Due to this, in_chk() uses the FIONREAD instead of RDCHK
820 and the hot keys during file transfer (X to cancel file etc) do not
821 work because FIONREAD doesn't work even though it is defined.
823 NOTE: This might also be true elsewhere.
827 #endif /* FIONREAD */
830 #ifdef CK_SCOV5 /* Ditto for SCO OpenServer 5.0 */
831 #ifndef SCO_OSR507 /* 299 */
834 #endif /* FIONREAD */
835 #endif /* SCO_OSR507 */
836 #endif /* CK_SCOV5 */
838 #ifdef SCO_OSR507 /* 299 */
842 #endif /* SCO_OSR507 */
844 /* Whether to include <fcntl.h> */
846 #ifndef is68k /* Only a few don't have this one. */
852 #endif /* COHERENT */
856 #endif /* not is68k */
862 #include <sys/fcntl.h>
864 #endif /* COHERENT */
866 #ifdef ATT7300 /* Unix PC, internal modem dialer */
867 #include <sys/phone.h>
870 #ifdef HPUX /* HP-UX variations. */
872 #include <sys/modem.h> /* HP-UX modem signals */
873 #ifdef hp9000s500 /* Model 500 */
875 #endif /* hp9000s500 */
879 #endif /* HPUXPRE65 */
881 #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */
882 #endif /* HPUXJOBCTL */
886 Which time.h files to include... See ckcdeb.h for defaults.
887 Note that 0, 1, 2, or all 3 of these can be included according to
888 the symbol definitions.
898 #include <sys/time.h>
899 #endif /* SYSTIMEH */
900 #endif /* NOSYSTIMEH */
904 #include <sys/timeb.h>
905 #endif /* SYSTIMEBH */
906 #endif /* NOSYSTIMEBH */
911 In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to
912 define the structs we need to access the higher speeds, so we have to
923 #endif /* DCLTIMEVAL */
924 #endif /* NODCLTIMEVAL */
927 /* THIS IS OBSOLETE since about Linux 0.92 */
929 #include <linux/serial.h>
930 #endif /* OLINUXHISPEED */
931 #ifdef __alpha__ /* Linux on DEC Alpha */
932 #ifndef __GLIBC__ /* But not with glibc */
933 #include <asm/termios.h>
934 #endif /* __GLIBC__ */
935 #endif /* __alpha__ */
936 #endif /* __linux__ */
938 #ifdef NOIEXTEN /* This is broken on some systems */
939 #undef IEXTEN /* like Convex/OS 9.1 */
940 #endif /* NOIEXTEN */
941 #ifndef IEXTEN /* Turn off ^O/^V processing. */
942 #define IEXTEN 0 /* Needed, at least, on BSDI. */
945 Pick up definitions needed for select() if we don't have them already.
946 Normally they come from <sys/types.h> but some systems get them from
947 <sys/select.h>... Rather than hardwire all of them into the source, we
948 include it if SELECT_H is defined in compile-time CFLAGS.
952 #include <sys/select.h>
953 #endif /* SELECT_H */
954 #endif /* SCO_OSR504 */
957 #include "/sys/ins/base.ins.c"
958 #include "/sys/ins/error.ins.c"
959 #include "/sys/ins/ios.ins.c"
960 #include "/sys/ins/sio.ins.c"
961 #include "/sys/ins/pad.ins.c"
962 #include "/sys/ins/time.ins.c"
963 #include "/sys/ins/pfm.ins.c"
964 #include "/sys/ins/pgm.ins.c"
965 #include "/sys/ins/ec2.ins.c"
966 #include "/sys/ins/type_uids.ins.c"
967 #include <default_acl.h>
972 #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */
976 /* The following #defines are catch-alls for those systems */
977 /* that didn't have or couldn't find <file.h>... */
989 #endif /* O_RDONLY */
991 /* This is for ancient Unixes that don't have these tty symbols defined. */
994 #define PENDIN ICANON
997 #define FLUSHO ICANON
1000 #define EXTPROC ICANON
1001 #endif /* EXTPROC */
1005 Modem signals are also forbidden in the POSIX world. But some POSIX-based
1006 platforms let us at them anyway if we know where to look.
1009 /* Doesn't work for Linux */
1012 #endif /* UNIXWARE7 */
1013 #endif /* NEEDMDMDEFS */
1017 #define TIOCMGET (('t'<<8)|29)
1018 #endif /* TIOCMGET */
1021 #define TIOCM_DTR 0x0002
1022 #endif /* TIOCM_DTR */
1024 #define TIOCM_RTS 0x0004
1025 #endif /* TIOCM_RTS */
1027 #define TIOCM_CTS 0x0020
1028 #endif /* TIOCM_CTS */
1030 #define TIOCM_CAR 0x0040
1031 #endif /* TIOCM_CAR */
1033 #define TIOCM_RNG 0x0080
1034 #endif /* TIOCM_RNG */
1036 #define TIOCM_DSR 0x0100
1037 #endif /* TIOCM_DSR */
1038 #endif /* NEEDMDMDEFS */
1039 #endif /* SVORPOSIX */
1048 #define TCGETA TCGETS
1049 #define TCSETA TCSETS
1050 #define TCSETAW TCSETSW
1051 #define TCSETAF TCSETSF
1052 #define termio termios
1055 #ifdef SVORPOSIX /* AT&T Sys V or POSIX */
1056 #ifdef UNIXWAREPOSIX /* UnixWare 7 POSIX build */
1058 In Unixware POSIX builds, <[sys/]time.h> refuses to define the
1059 structs we need to access the higher speeds, so we have to do it
1070 #endif /* UNIXWAREPOSIX */
1071 #endif /* SVORPOSIX */
1076 Because Xenix <time.h> doesn't declare time() if we're using gcc.
1080 #endif /* __GNUC__ */
1082 /* Special stuff for V7 input buffer peeking */
1085 int kmem[2] = { -1, -1};
1086 char *initrawq(), *qaddr[2]={0,0};
1091 /* dftty is the device name of the default device for file transfer */
1092 /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
1095 char * dftty = NULL;
1096 char * dfmdm = "none";
1097 int dfloc = 0; /* that goes in local mode by default */
1101 char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
1102 char *dfmdm = "none";
1103 int dfloc = 1; /* that goes in local mode by default */
1105 char *dftty = CTTNAM; /* Remote by default, use normal */
1106 char *dfmdm = "none";
1107 int dfloc = 0; /* controlling terminal name. */
1110 char *dftty = DFTTY; /* Default location specified on */
1111 char *dfmdm = "none"; /* command line. */
1112 int dfloc = 1; /* controlling terminal name. */
1116 #define CON_RES 0 /* Console state is "reset" */
1117 #define CON_CB 1 /* Console state is CBREAK */
1118 #define CON_BIN 2 /* Console state is binary */
1119 static int constate = CON_RES;
1121 #define CONI_RES 0 /* Console interrupts are "reset" */
1122 #define CONI_INT 1 /* Console intterupts are set */
1123 #define CONI_NOI 2 /* Console intterupts are disabled */
1124 static int conistate = CONI_RES;
1127 #define CONBUFSIZ 15
1129 #define CONBUFSIZ 255
1130 #endif /* CK_SMALL */
1131 static char conbuf[CONBUFSIZ]; /* Console readahead buffer */
1132 static int conbufn = 0; /* Chars in readahead buffer */
1133 static char *conbufp = conbuf; /* Next char in readahead buffer */
1135 char cttnam[DEVNAMLEN+1] = { '\0', '\0' }; /* Determined at runtime */
1138 int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */
1141 int dfprty = DEFPAR; /* Default parity (0 = none) */
1142 int ttprty = 0; /* The parity that is in use. */
1143 static int ttpmsk = 0xff; /* Parity stripping mask. */
1144 int ttmdm = 0; /* Modem in use. */
1145 int ttcarr = CAR_AUT; /* Carrier handling mode. */
1146 int dfflow = FLO_NONE; /* Default flow control is NONE */
1147 int backgrd = 0; /* Assume in foreground (no '&' ) */
1149 int iniflags = -1; /* fcntl flags for ttyfd */
1150 #endif /* F_SETFL */
1151 int fdflag = 0; /* Flag for redirected stdio */
1152 int ttfdflg = 0; /* Open File descriptor was given */
1153 int tvtflg = 0; /* Flag that ttvt has been called */
1154 long ttspeed = -1L; /* For saving speed */
1155 int ttflow = -9; /* For saving flow */
1156 int ttld = -1; /* Line discipline */
1159 static int km_con = -1; /* Kanji mode for console tty */
1160 static int km_ext = -1; /* Kanji mode for external device */
1161 #endif /* sony_news */
1164 static int needpchk = 1; /* Need parity check */
1166 static int needpchk = 0;
1167 #endif /* PARSENSE */
1169 extern int stopbits; /* Stop bits */
1172 Unfortunately we must do this with global variables rather than through the
1173 tt...() APIs to avoid changing the APIs and the many modules that use them.
1174 If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
1175 bits + parity or 8 data bits and no parity, and overrides the regular parity
1176 variable, which is communicated to this module thru ttpkt(), and represented
1177 locally by the ttprty variable.
1179 extern int hwparity; /* Hardware parity */
1180 #endif /* HWPARITY */
1184 static int nodelay_sav = -1;
1185 #endif /* TCP_NODELAY */
1186 #endif /* TCPSOCKET */
1188 static int sigint_ign = 0; /* SIGINT is ignored */
1191 Having this module rely on external globals is bad, but fixing this
1192 requires overhaul of the ck*tio.c modules for all the different operating
1193 systems supported by C-Kermit. Left for a future release.
1195 extern int ttnproto; /* Defined in ckcnet.c */
1196 extern int ttnet; /* Defined in ckcnet.c */
1197 extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */
1198 extern int xsuspend, wasclosed;
1199 extern int inserver, local;
1201 int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
1203 int ckmaxfiles = 0; /* Max number of open files */
1205 #ifdef CK_ENCRYPTION /* Kerberos */
1207 extern int me_encrypt, u_encrypt;
1208 #endif /* CK_ENCRYPTION */
1210 /* Declarations of variables global within this module */
1212 #ifdef TTLEBUF /* See ckcnet.h */
1214 #define LEBUFSIZ 4096
1215 static CHAR le_buf[LEBUFSIZ];
1216 static int le_start = 0, le_end = 0, le_data = 0;
1217 #endif /* TTLEBUF */
1219 #define MSGBUF_SIZE 1024 /* For debugging */
1220 static char msgbuf[MSGBUF_SIZE];
1222 static int gotsigs = 0;
1224 static time_t tcount = (time_t)0; /* Elapsed time counter */
1226 static SIGTYP (*saval)() = NULL; /* For saving alarm() handler */
1227 static SIGTYP (*savquit)() = NULL; /* and other signal handlers */
1229 static SIGTYP (*savusr1)() = NULL;
1230 #endif /* SIGUSR1 */
1232 static SIGTYP (*savusr2)() = NULL;
1233 #endif /* SIGUSR2 */
1235 static SIGTYP (*savpipe)() = NULL;
1236 #endif /* SIGPIPE */
1238 static SIGTYP (*savdanger)() = NULL;
1239 #endif /* SIGDANGER */
1242 static SIGTYP (*jchdlr)() = NULL; /* For checking suspend handler */
1244 static int jcshell = -1; /* And flag for result */
1247 BREAKNULS is defined for systems that simulate sending a BREAK signal
1248 by sending a bunch of NUL characters at low speed.
1253 #endif /* BREAKNULS */
1259 #endif /* BREAKNULS */
1263 static char /* A string of nulls */
1264 *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";
1265 #endif /* BREAKNULS */
1267 #ifdef CK_POSIX_SIG /* Longjump buffers */
1268 static sigjmp_buf sjbuf; /* POSIX signal handling */
1270 static jmp_buf sjbuf;
1271 #endif /* CK_POSIX_SIG */
1274 static jmp_buf jjbuf;
1277 /* static */ /* (Not static any more) */
1278 int ttyfd = -1; /* TTY file descriptor */
1280 int ttpipe = 0; /* NETCMD: Use pipe instead of ttyfd */
1281 int ttpty = 0; /* NETPTY: Use pty instead of ttfyd */
1283 #ifdef NETPTY /* These are in ckupty.c */
1284 extern PID_T pty_fork_pid;
1285 extern int pty_master_fd, pty_slave_fd;
1290 static int pipe0[2], pipe1[2]; /* Pipes for net i/o */
1291 #endif /* NETCONN */
1292 static PID_T ttpid = 0; /* Process ID for fork */
1293 static int fdin, fdout; /* File descriptors for pipe */
1294 static FILE * ttout = NULL; /* File pointer for output pipe */
1296 /* fdopen() needs declaring because it's not declared in <stdio.h> */
1297 _PROTOTYP( FILE * fdopen, (int, char *) );
1298 #endif /* DCLFDOPEN */
1301 extern int pexitstat, quiet;
1304 int ttyctlfd = -1; /* TTY control channel - What? UNIX doesn't have one? */
1305 int consctlfd = -1; /* Console control channel */
1306 int noisefd = -1; /* tone channel */
1307 static int ttylastspeed = -1; /* So we can lie about the speed */
1310 int telnetfd = 0; /* File descriptor is for telnet */
1312 int x25fd = 0; /* File descriptor is for X.25 */
1313 #endif /* NETCONN */
1315 char lockpid[16] = { '\0', '\0' }; /* PID stored in lockfile, as string */
1317 static int lkf = 0, /* Line lock flag */
1318 cgmf = 0, /* Flag that console modes saved */
1319 xlocal = 0, /* Flag for tty local or remote */
1320 curcarr = 0; /* Carrier mode: require/ignore. */
1322 static int netconn = 0; /* 1 if network connection active */
1324 static char escchr; /* Escape or attn character */
1327 #include <sys/time.h>
1328 #endif /* CK_SCO32V4 */
1331 static struct timeval tv; /* For getting time, from sys/time.h */
1332 #endif /* HAVE_TV */
1334 static struct timezone tz;
1335 #endif /* HAVE_TZ */
1338 static struct timeb ftp; /* And from sys/timeb.h */
1342 static long xclock; /* For getting time from sys/time.h */
1343 static struct timeb ftp; /* And from sys/timeb.h */
1347 static long xclock; /* For getting time from sys/time.h */
1348 static struct timeb ftp; /* And from sys/timeb.h */
1352 static long xclock; /* For getting time from sys/time.h */
1353 static struct timeb ftp; /* And from sys/timeb.h */
1354 #endif /* BELLV10 */
1357 static long xclock; /* For getting time from sys/time.h */
1358 static struct timeb ftp; /* And from sys/timeb.h */
1362 static long xclock; /* For getting time from sys/time.h */
1363 static struct timeb ftp; /* And from sys/timeb.h */
1367 static long xclock; /* For getting time from sys/time.h */
1368 static struct timeb ftp; /* And from sys/timeb.h */
1369 #endif /* COHERENT */
1375 /* sgtty/termio information... */
1377 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
1378 static struct termios
1379 ttold, ttraw, tttvt, ttcur,
1380 ccold, ccraw, cccbrk;
1381 #else /* BSD, V7, etc */
1383 #ifdef COHERENT /* Hack alert... */
1385 #endif /* COHERENT */
1388 static struct termio ttold = {0}; /* Init'd for word alignment, */
1389 static struct termio ttraw = {0}; /* which is important for some */
1390 static struct termio tttvt = {0}; /* systems, like Zilog... */
1391 static struct termio ttcur = {0};
1392 static struct termio ccold = {0};
1393 static struct termio ccraw = {0};
1394 static struct termio cccbrk = {0};
1396 static struct sgttyb /* sgtty info... */
1397 ttold, ttraw, tttvt, ttcur, /* for communication line */
1398 ccold, ccraw, cccbrk; /* and for console */
1400 static struct ttydevb /* Device info... */
1401 tdold, tdcur; /* for communication device */
1402 #endif /* BELLV10 */
1404 static struct tchars tchold, tchnoi;
1407 #endif /* TIOCGETC */
1409 static struct ltchars ltchold, ltchnoi;
1411 #endif /* TIOCGLTC */
1412 int lmodef = 0; /* Local modes */
1415 #endif /* BSD44ORPOSIX */
1418 /* It picks up the speeds but they don't work */
1419 #ifdef UNIXWARE /* For higher serial speeds */
1420 #ifdef UW7 /* in Unixware 7.0 */
1421 #include <sys/asyc.h> /* This picks up 57600 and 115200 */
1423 #endif /* UNIXWARE */
1424 #endif /* COMMENT */
1427 static struct sgttyb ttbuf;
1431 /* do we really need this? */
1432 static struct sgttyb vanilla;
1436 static int attmodem = 0; /* ATT7300 internal-modem status */
1437 struct updata dialer = {0}; /* Condition dialer for data call */
1438 #endif /* ATT7300 */
1444 char lkflfn[FLFNAML] = { '\0', '\0' }; /* and possible link to it */
1446 char lock2[FLFNAML] = { '\0', '\0' }; /* Name of second lockfile */
1447 #endif /* USETTYLOCK */
1451 char flfnam[FLFNAML+1] = { '\0', '\0' }; /* UUCP lock file path name */
1453 int haslock = 0; /* =1 if this kermit locked uucp */
1457 static int conesc = 0; /* set to 1 if esc char (^\) typed */
1460 static int conesc = 0;
1463 static int conesc = 0;
1466 #endif /* SVORPOSIX */
1469 /* Local copy of comm device name or network host */
1470 static char ttnmsv[DEVNAMLEN+1] = { '\0', '\0' };
1472 static char lockname[DEVNAMLEN+1]; /* Ditto, the part after "/dev/". */
1473 #endif /* USETTYLOCK */
1476 static status_$t st; /* error status return value */
1477 static short concrp = 0; /* true if console is CRP pad */
1478 static uid_$t ttyuid; /* tty type uid */
1479 static uid_$t conuid; /* stdout type uid */
1481 /* APOLLO Aegis main()
1482 * establish acl usage and cleanup handling
1483 * this makes sure that CRP pads
1484 * get restored to a usable mode
1486 main(argc,argv) int argc; char **argv; {
1488 pfm_$cleanup_rec dirty;
1490 PID_T pid = getpid();
1492 /* acl usage according to invoking environment */
1493 default_acl(USE_DEFENV);
1495 /* establish a cleanup continuation */
1496 status = pfm_$cleanup(dirty);
1497 if (status.all != pfm_$cleanup_set) {
1498 /* only handle faults for the original process */
1499 if (pid == getpid() && status.all > pgm_$max_severity) {
1500 /* blew up in main process */
1502 pfm_$cleanup_rec clean;
1504 /* restore the console in any case */
1507 /* attempt a clean exit */
1508 debug(F101, "cleanup fault status", "", status.all);
1510 /* doexit(), then send status to continuation */
1511 quo = pfm_$cleanup(clean);
1512 if (quo.all == pfm_$cleanup_set)
1513 doexit(pgm_$program_faulted,-1);
1514 else if (quo.all > pgm_$max_severity)
1515 pfm_$signal(quo); /* blew up in doexit() */
1517 /* send to the original continuation */
1518 pfm_$signal(status);
1521 return(ckcmai(argc, argv));
1525 /* ANSI-style prototypes for internal functions. */
1526 /* Functions used outside this module are prototyped in ckcker.h. */
1529 _PROTOTYP( SIGTYP timerh, () );
1530 _PROTOTYP( SIGTYP cctrap, () );
1531 _PROTOTYP( SIGTYP esctrp, () );
1532 _PROTOTYP( SIGTYP sig_ign, () );
1534 _PROTOTYP( SIGTYP timerh, (int) );
1535 _PROTOTYP( SIGTYP cctrap, (int) );
1536 _PROTOTYP( SIGTYP esctrp, (int) );
1538 _PROTOTYP( int do_open, (char *) );
1539 _PROTOTYP( static int in_chk, (int, int) );
1540 _PROTOTYP( static int ttrpid, (char *) );
1541 _PROTOTYP( static int ttchkpid, (char *) );
1542 _PROTOTYP( static int ttlock, (char *) );
1543 _PROTOTYP( static int ttunlck, (void) );
1544 _PROTOTYP( static VOID sigchld_handler, (int) );
1545 _PROTOTYP( int mygetbuf, (void) );
1546 _PROTOTYP( int myfillbuf, (void) );
1547 _PROTOTYP( VOID conbgt, (int) );
1549 _PROTOTYP( VOID acucntrl, (char *, char *) );
1550 #endif /* ACUCNTRL */
1553 _PROTOTYP( int carrctl, (struct termios *, int) );
1556 _PROTOTYP( int carrctl, (struct termio *, int) );
1558 _PROTOTYP( int carrctl, (struct sgttyb *, int) );
1560 #endif /* BSD44ORPOSIX */
1563 _PROTOTYP( int attdial, (char *, long, char *) );
1564 _PROTOTYP( int offgetty, (char *) );
1565 _PROTOTYP( int ongetty, (char *) );
1566 #endif /* ATT7300 */
1570 /* BeOS is not capable of using SELECT on anything but sockets */
1573 #include <kernel/OS.h>
1574 /* #ifdef BE_DR_7 */
1575 static double time_started = 0.0;
1576 struct ALARM_STRUCT {
1580 static thread_id alarm_thread = -1;
1581 static struct ALARM_STRUCT alarm_struct;
1582 _PROTOTYP( long do_alarm, (void *) );
1583 _PROTOTYP( unsigned int alarm, (unsigned int) );
1584 _PROTOTYP( void alarm_expired, (void) );
1585 /* #endif */ /* BE_DR_7 */
1586 #endif /* BEOSORBEBOX */
1589 #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
1590 #endif /* xunchar */
1594 xxlast(char *s, char c)
1597 xxlast(s,c) char *s; char c;
1598 #endif /* CK_ANSIC */
1599 /* xxlast */ { /* Last occurrence of character c in string s. */
1601 for (i = (int)strlen(s); i > 0; i--)
1602 if (s[i-1] == c ) return(s + (i - 1));
1606 /* Timeout handler for communication line input functions */
1610 timerh(foo) int foo; {
1613 /* #ifdef BE_DR_7 */
1615 /* #endif */ /* BE_DR_7 */
1616 #endif /* BEOSORBEBOX */
1618 siglongjmp(sjbuf,1);
1621 #endif /* CK_POSIX_SIG */
1626 xtimerh(foo) int foo; { /* Like timerh() but does */
1627 #ifdef BEOSORBEBOX /* not reset the timer itself */
1628 /* #ifdef BE_DR_7 */
1630 /* #endif */ /* BE_DR_7 */
1631 #endif /* BEOSORBEBOX */
1633 siglongjmp(sjbuf,1);
1636 #endif /* CK_POSIX_SIG */
1640 /* Control-C trap for communication line input functions */
1642 int cc_int; /* Flag */
1643 SIGTYP (* occt)(); /* For saving old SIGINT handler */
1647 cctrap(foo) int foo; { /* Needs arg for ANSI C */
1648 cc_int = 1; /* signal() prototype. */
1652 /* S Y S I N I T -- System-dependent program initialization. */
1655 * ttgwsiz() returns:
1656 * 1 tt_rows and tt_cols are known, both altered, both > 0
1657 * 0 tt_rows and/or tt_cols are known, both altered, one or both <= 0
1658 * -1 tt_rows and tt_cols are unknown and unaltered
1661 extern int tt_rows, tt_cols;
1666 int rows = 0, cols = 0;
1667 p = getenv("LINES");
1668 debug(F110,"xttgwsiz LINES",p,0);
1672 p = getenv("COLUMNS");
1673 debug(F110,"xttgwsiz COLUMNS",p,0);
1690 le_init() { /* LocalEchoInit() */
1692 for (i = 0; i < LEBUFSIZ; i++)
1700 le_clean() { /* LocalEchoCleanup() */
1708 if (le_start != le_end) {
1711 LEBUFSIZ) % LEBUFSIZ;
1713 debug(F111,"le_inbuf","chars waiting",rc);
1721 le_putchar(ch) CHAR ch;
1722 #endif /* CK_ANSIC */
1725 /* In UNIX we do not have another thread taking chars out of the buffer */
1726 while ((le_start - le_end == 1) ||
1727 (le_start == 0 && le_end == LEBUFSIZ - 1)) {
1728 /* Buffer is full */
1729 debug(F111,"le_putchar","Buffer is Full",ch);
1730 ReleaseLocalEchoMutex() ;
1732 RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
1735 if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
1736 debug(F110,"le_putchar","buffer is full",0);
1739 #endif /* COMMENT */
1740 le_buf[le_end++] = ch;
1741 if (le_end == LEBUFSIZ)
1749 le_puts(CHAR * s, int n)
1751 le_puts(s,n) CHAR * s; int n;
1752 #endif /* CK_ANSIC */
1756 CHAR * p = (CHAR *)"le_puts";
1758 for (i = 0; i < n; i++)
1759 rc = le_putchar((char)s[i]);
1760 debug(F101,"le_puts","",rc);
1768 le_putstr(s) CHAR * s;
1769 #endif /* CK_ANSIC */
1773 p = (CHAR *)"le_putstr";
1774 ckhexdump(p,s,(int)strlen((char *)s));
1775 for (p = s; *p && !rc; p++)
1776 rc = le_putchar(*p);
1782 le_getchar(CHAR * pch)
1783 #else /* CK_ANSIC */
1784 le_getchar(pch) CHAR * pch;
1785 #endif /* CK_ANSIC */
1788 if (le_start != le_end) {
1789 *pch = le_buf[le_start];
1790 le_buf[le_start] = 0;
1793 if (le_start == LEBUFSIZ)
1796 if (le_start == le_end) {
1805 #endif /* TTLEBUF */
1809 Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ.
1810 But as far as I know, whenever TIOCGSIZE is defined, it is
1811 equated to TIOCGWINSZ. For cases where this is not done, try this:
1815 #define TIOCGWINSZ TIOCGSIZE
1816 #endif /* TIOCGSIZE */
1817 #endif /* TIOCGWINSZ */
1818 #endif /* COMMENT */
1820 static int tt_xpixel = 0, tt_ypixel = 0;
1828 NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
1829 This code works for both the 16- and 32-bit versions.
1831 extern int dev_size(int, int, int, int *, int *);
1834 if (dev_size(0, -1, -1, &r, &c) == 0) {
1835 debug(F101,"ttgwsiz QNX r","",r);
1836 debug(F101,"ttgwsiz QNX c","",c);
1839 return ((r > 0 && c > 0) ? 1 : 0);
1840 } else return(xttgwsiz());
1844 /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
1845 #ifdef XENIX /* SCO UNIX 3.2v4.0 */
1846 #include <sys/stream.h> /* typedef mblk_t needed by ptem.h */
1847 #include <sys/ptem.h> /* for ttgwsiz() */
1850 #ifdef I386IX /* Ditto for Interactive */
1851 #include <sys/stream.h>
1852 #include <sys/ptem.h>
1855 /* Note, the above might be needed for some other older SVR3 Intel makes... */
1865 x = ioctl(0, (int)TIOCGWINSZ, (char *)&w);
1866 debug(F101,"ttgwsiz TIOCGWINSZ","",x);
1869 } else if (w.ws_row > 0 && w.ws_col > 0) {
1872 tt_xpixel = w.ws_xpixel;
1873 tt_ypixel = w.ws_ypixel;
1874 debug(F101,"ttgwsiz tt_rows","",tt_rows);
1875 debug(F101,"ttgwsiz tt_cols","",tt_cols);
1878 debug(F100,"ttgwsiz TIOCGWINSZ 00","",0);
1883 #endif /* TIOCGWINSZ */
1890 _PROTOTYP( int rlog_naws, (void) );
1891 #endif /* RLOGCODE */
1896 winchh(foo) int foo; { /* SIGWINCH handler */
1902 #endif /* CK_TTYFD */
1903 extern int tt_rows, tt_cols, cmd_rows, cmd_cols;
1906 debug(F100,"***************","",0);
1907 debug(F100,"SIGWINCH caught","",0);
1908 debug(F100,"***************","",0);
1910 debug(F101,"SIGWINCH pty_fork_pid","",pty_fork_pid);
1914 signal(SIGWINCH,winchh); /* Re-arm the signal */
1915 x = ttgwsiz(); /* Get new window size */
1916 cmd_rows = tt_rows; /* Adjust command screen too */
1920 if /* If we don't have a connection */
1921 #ifdef VMS /* we're done. */
1928 #endif /* CK_TTYFD */
1932 if (pty_fork_pid > -1) { /* "set host" to a PTY? */
1936 struct winsize w; /* Resize the PTY */
1940 w.ws_xpixel = tt_xpixel;
1941 w.ws_ypixel = tt_ypixel;
1942 x = ioctl(ttyfd,TIOCSWINSZ,&w);
1943 debug(F101,"winchh TIOCSWINSZ","",x);
1944 debug(F101,"winchh TIOCSWINSZ errno","",errno);
1945 #endif /* TIOCSWINSZ */
1948 x = kill(pty_fork_pid,SIGWINCH);
1949 debug(F101,"winchh kill","",x);
1950 debug(F101,"winchh kill errno","",errno);
1955 This should be OK. It might seem that sending this from
1956 interrupt level could interfere with another TELNET IAC string
1957 that was in the process of being sent. But we always send
1958 TELNET strings with a single write(), which should prevent mixups.
1959 blah_snaws() should protect themselves from being called on the
1960 wrong kind of connection.
1964 if (x > 0 && tt_rows > 0 && tt_cols > 0) {
1968 #endif /* RLOGCODE */
1970 #endif /* NOTTGWSIZ */
1971 #endif /* TCPSOCKET */
1974 #endif /* SIGWINCH */
1975 #endif /* NOSIGWINCH */
1978 sighup(foo) int foo; { /* SIGHUP handler */
1980 debug(F100,"***************","",0);
1981 debug(F100,"SIGHUP received","",0);
1982 debug(F100,"***************","",0);
1983 doexit(BAD_EXIT,-1);
1985 SIGRETURN; /* Shut picky compilers up... */
1989 /* Exists but there is no prototype in the header files */
1990 _PROTOTYP( char * ttyname, (int) );
1993 _PROTOTYP( char * ttyname, (int) );
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) );
2010 #endif /* PS2AIX10 */
2014 #endif /* SV68R3V6 */
2015 #endif /* CK_SCO32V4 */
2017 #ifndef SIGUSR1 /* User-defined signals */
2019 #endif /* SIGUSR1 */
2023 #endif /* SIGUSR2 */
2026 ignorsigs() sets certain signals to SIG_IGN. But when a signal is
2027 ignored, it remains ignored across exec(), so we have to restore these
2028 signals before exec(), which is the purpose of restorsigs().
2031 ignorsigs() { /* Ignore these signals */
2032 savquit = signal(SIGQUIT,SIG_IGN); /* Ignore Quit signal */
2034 #ifdef SIGDANGER /* Ignore danger signals */
2036 This signal is sent when the system is low on swap space. Processes
2037 that don't handle it are candidates for termination. If swap space doesn't
2038 clear out enough, we still might be terminated via kill() -- nothing we can
2039 do about that! Conceivably, this could be improved by installing a real
2040 signal handler that warns the user, but that would be pretty complicated,
2041 since we are not always in control of the screen -- e.g. during remote-mode
2044 savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */
2045 #endif /* SIGDANGER */
2048 This one comes when a TCP/IP connection is broken by the remote.
2049 We prefer to catch this situation by examining error codes from write().
2051 savpipe = signal(SIGPIPE,SIG_IGN);
2052 #endif /* SIGPIPE */
2053 savusr1 = signal(SIGUSR1,SIG_IGN); /* Ignore user-defined signals */
2054 savusr2 = signal(SIGUSR2,SIG_IGN);
2058 restorsigs() { /* Restore these signals */
2059 (VOID) signal(SIGQUIT,savquit); /* (used in ckufio.c) */
2061 (VOID) signal(SIGDANGER,savdanger);
2062 #endif /* SIGDANGER */
2064 (VOID) signal(SIGPIPE,savpipe);
2065 #endif /* SIGPIPE */
2066 (VOID) signal(SIGUSR1,savusr1);
2067 (VOID) signal(SIGUSR2,savusr2);
2075 struct utsname name;
2076 #endif /* CK_UTSNAME */
2078 extern char startupdir[];
2080 BEFORE ANYTHING ELSE: Initialize the setuid package.
2081 Change to the user's real user and group ID.
2082 If this can't be done, don't run at all.
2086 fprintf(stderr,"PRIV_INI=%d\n",x);
2087 #endif /* SUIDDEBUG */
2089 if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
2090 if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
2091 if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
2094 signal(SIGINT,SIG_IGN); /* Ignore interrupts at first */
2095 signal(SIGFPE,SIG_IGN); /* Ignore floating-point exceptions */
2096 signal(SIGHUP,sighup); /* Catch SIGHUP */
2099 signal(SIGWINCH,winchh); /* Catch window-size change */
2100 #endif /* SIGWINCH */
2101 #endif /* NOSIGWINCH */
2104 signal(SIGXFSZ,SIG_IGN); /* Ignore writing past file limit */
2105 #endif /* SIGXFSZ */
2109 Get the initial job control state.
2110 If it is SIG_IGN, that means the shell does not support job control,
2111 and so we'd better not suspend ourselves.
2114 jchdlr = signal(SIGTSTP,SIG_IGN);
2115 if (jchdlr == SIG_IGN) {
2117 debug(F100,"sysinit jchdlr: SIG_IGN","",0);
2118 } else if (jchdlr == SIG_DFL) {
2119 debug(F100,"sysinit jchdlr: SIG_DFL","",0);
2122 debug(F100,"sysinit jchdlr: other","",0);
2125 (VOID) signal(SIGTSTP,jchdlr); /* Put it back... */
2126 #endif /* SIGTSTP */
2129 conbgt(0); /* See if we're in the background */
2130 congm(); /* Get console modes */
2132 (VOID) signal(SIGALRM,SIG_IGN); /* Ignore alarms */
2134 ignorsigs(); /* Ignore some other signals */
2137 iniflags = fcntl(0,F_GETFL,0); /* Get stdin flags */
2138 #endif /* F_SETFL */
2141 gtty(0,&vanilla); /* Get sgtty info */
2144 set42sig(); /* Don't ask! (hakanson@cs.orst.edu) */
2148 Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
2149 never closes it. If it is called often enough, we run out of file
2150 descriptors and subsequent open()'s of other devices or files can fail.
2154 if (isatty(0)) /* Name of controlling terminal */
2160 debug(F110,"sysinit ttyname(0)",s,0);
2169 ckstrncpy((char *)cttnam,s,DEVNAMLEN+1);
2173 #endif /* SVORPOSIX */
2175 ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1);
2176 debug(F110,"sysinit CTTNAM",CTTNAM,0);
2177 debug(F110,"sysinit cttnam",cttnam,0);
2179 ttgwsiz(); /* Get window (screen) dimensions. */
2183 ckmaxfiles = sysconf(_SC_OPEN_MAX);
2184 #endif /* _SC_OPEN_MAX */
2185 #endif /* NOSYSCONF */
2189 consctlfd = open("/dev/consctl", O_WRONLY);
2190 /*noisefd = open("/dev/noise", O_WRONLY)*/
2196 if (uname(&name) > -1) {
2197 ckstrncpy(unm_mch,name.machine,CK_SYSNMLN);
2198 ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN);
2199 ckstrncpy(unm_rel,name.release,CK_SYSNMLN);
2200 ckstrncpy(unm_ver,name.version,CK_SYSNMLN);
2203 debug(F110,"sysinit uname machine",unm_mch,0);
2204 debug(F110,"sysinit uname sysname",unm_nam,0);
2205 debug(F110,"sysinit uname release",unm_rel,0);
2206 debug(F110,"sysinit uname version",unm_ver,0);
2211 if (name.machine[5] == '8')
2215 debug(F101,"sysinit hpis800","",hpis800);
2216 #endif /* HPUX9PLUS */
2218 getsysinfo(GSI_PLATFORM_NAME, unm_mod, CK_SYSNMLN, 0, 0);
2219 debug(F110,"sysinit getsysinfo model",unm_mod,0);
2222 sysinfo(SI_PLATFORM, unm_mod, CK_SYSNMLN);
2223 debug(F110,"sysinit sysinfo model",unm_mod,0);
2224 #endif /* SOLARIS25 */
2226 #endif /* CK_UTSNAME */
2228 #ifdef CK_ENVIRONMENT
2231 extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
2232 tn_env_prnt[], tn_env_sys[];
2234 extern char uidbuf[];
2235 extern char * whoami();
2243 debug(F110,"sysinit uidbuf from USER",uidbuf,0);
2246 p = getenv("LOGNAME");
2247 debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0);
2252 debug(F110,"sysinit uidbuf from whoami()",uidbuf,0);
2255 ckstrncpy(uidbuf, *p ? p : "UNKNOWN", UIDBUFLEN);
2259 debug(F110,"sysinit final uidbuf",uidbuf,0);
2260 #endif /* CKSENDUID */
2263 if ((p = getenv("JOB"))) ckstrncpy(tn_env_job,p,63);
2264 if ((p = getenv("ACCT"))) ckstrncpy(tn_env_acct,p,63);
2265 if ((p = getenv("PRINTER"))) ckstrncpy(tn_env_prnt,p,63);
2266 if ((p = getenv("DISPLAY"))) ckstrncpy(tn_env_disp,p,63);
2268 ckstrncpy(tn_env_sys,"Aegis",64);
2271 ckstrncpy(tn_env_sys,"Plan9",64);
2273 ckstrncpy(tn_env_sys,"UNIX",64);
2278 #endif /* CK_ENVIRONMENT */
2281 extern char * tn_loc;
2283 if (p = getenv("LOCATION"))
2284 if (tn_loc = (char *)malloc((int)strlen(p)+1))
2285 strcpy(tn_loc,p); /* safe */
2287 #endif /* CK_SNDLOC */
2289 ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
2290 startupdir[CKMAXPATH] = '\0';
2291 x = strlen(startupdir);
2293 startupdir[0] = '/';
2294 startupdir[1] = '\0';
2295 } else if (startupdir[x-1] != '/') {
2296 startupdir[x] = '/';
2297 startupdir[x+1] = '\0';
2299 debug(F110,"sysinit startupdir",startupdir,0);
2302 #endif /* TTLEBUF */
2304 /* This should catch the ncurses platforms */
2305 /* Some platforms don't have putenv(), like NeXTSTEP */
2306 putenv("NCURSES_NO_SETBUF=1");
2307 #endif /* BSD44ORPOSIX */
2311 /* S Y S C L E A N U P -- System-dependent program cleanup. */
2317 fcntl(0,F_SETFL,iniflags); /* Restore stdin flags */
2318 #endif /* F_SETFL */
2320 stty(0,&vanilla); /* Get sgtty info */
2323 if (ttpid) kill(ttpid,9);
2328 /* T T O P E N -- Open a tty for exclusive access. */
2332 ttname: character string - device name or network host name.
2334 If called with lcl < 0, sets value of lcl as follows:
2335 0: the terminal named by ttname is the job's controlling terminal.
2336 1: the terminal named by ttname is not the job's controlling terminal.
2337 But watch out: if a line is already open, or if requested line can't
2338 be opened, then lcl remains (and is returned as) -1.
2340 Less than zero: ttname is a network host name.
2341 Zero or greater: ttname is a terminal device name.
2342 Zero means a local connection (don't use modem signals).
2343 Positive means use modem signals.
2346 nonzero = number of seconds to wait for open() to return before timing out.
2350 -5 if device is in use
2351 -4 if access to device is denied
2352 -3 if access to lock directory denied
2353 -2 upon timeout waiting for device to open
2356 static int ttotmo = 0; /* Timeout flag */
2357 /* Flag kept here to avoid being clobbered by longjmp. */
2360 ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
2363 #define ctermid(x) strcpy(x,"")
2367 extern char *ctermid(); /* Wish they all had this! */
2368 #else /* CIE Regulus */
2369 #define ctermid(x) strcpy(x,"")
2371 #endif /* SVORPOSIX */
2379 char fullname[DEVNAMLEN+1];
2380 #endif /* OPENFIRST */
2382 char * fnam; /* Full name after expansion */
2387 #define NAMEFD /* Feature to allow name to be an open file descriptor */
2392 debug(F101,"ttopen telnetfd","",telnetfd);
2395 debug(F110,"ttopen ttname",ttname,0);
2396 debug(F110,"ttopen ttnmsv",ttnmsv,0);
2397 debug(F101,"ttopen modem","",modem);
2398 debug(F101,"ttopen netconn","",netconn);
2399 debug(F101,"ttopen ttyfd","",ttyfd);
2400 debug(F101,"ttopen *lcl","",*lcl);
2401 debug(F101,"ttopen ttmdm","",ttmdm);
2402 debug(F101,"ttopen ttnet","",ttnet);
2407 if (ttyfd > -1) { /* If device already opened */
2408 if (!strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
2409 return(0); /* Yes, nothing to do - just return */
2410 ttnmsv[0] = '\0'; /* No, clear out old name */
2411 ttclos(ttyfd); /* close old connection. */
2413 wasclosed = 0; /* New connection, not closed yet. */
2414 ttpipe = 0; /* Assume it's not a pipe */
2415 ttpty = 0; /* or a pty... */
2419 This is a bit tricky... Suppose that previously Kermit had dialed a telnet
2420 modem server ("set host xxx:2001, set modem type usr, dial ..."). Then the
2421 connection was closed (ttyfd = -1), and then a REDIAL command was given. At
2422 this point we've obliterated the negative modem type hack, and so would
2423 treat the IP hostname as a device name, and would then fail because of "No
2424 such device or directory". But the previous connection has left behind some
2425 clues, so let's use them...
2427 if (ttyfd < 0) { /* Connection is not open */
2428 if (!strcmp(ttname,ttnmsv)) { /* Old and new names the same? */
2429 if (((netconn > 0) && (ttmdm < 0)) ||
2431 (!ckstrchr(ttname,'/')) && (ckstrchr(ttname,':')))
2434 x = (ttmdm < 0) ? -ttmdm : ttnet;
2435 rc = netopen(ttname, lcl, x);
2436 debug(F111,"ttopen REOPEN netopen",ttname,rc);
2448 #endif /* NETCONN */
2451 debug(F100,"ttopen MAXNAMLEN defined","",0);
2453 debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
2457 debug(F100,"ttopen BSD4 defined","",0);
2459 debug(F100,"ttopen BSD4 *NOT* defined","",0);
2463 debug(F100,"ttopen BSD42 defined","",0);
2465 debug(F100,"ttopen BSD42 *NOT* defined","",0);
2469 debug(F100,"ttopen MYREAD defined","",0);
2471 debug(F100,"ttopen MYREAD *NOT* defined","",0);
2475 if (modem < 0) { /* modem < 0 = code for network */
2478 modem = -modem; /* Positive network type number */
2479 fdflag = 0; /* Stdio not redirected. */
2480 netconn = 1; /* And it's a network connection */
2481 debug(F111,"ttopen net",ttname,modem);
2483 for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
2484 if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
2485 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2486 ttfdflg = 1; /* We got an open file descriptor */
2487 debug(F111,"ttopen net ttfdflg",ttname,ttfdflg);
2488 debug(F101,"ttopen net ttyfd","",ttyfd);
2489 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2490 x = 1; /* Return code is "good". */
2493 if (ttnproto != NP_TCPRAW)
2494 ttnproto = NP_TELNET;
2501 } else { /* Host name or address given */
2503 if (modem == NET_PTY) {
2506 debug(F100,"ttopen PTY: nopush","",0);
2511 netconn = 1; /* but we don't use network i/o */
2513 debug(F110,"ttopen PTY",ttname,0);
2514 x = do_pty(&ttyfd,ttname,0);
2516 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2517 xlocal = *lcl = 1; /* It's local */
2528 dup2() is not available on older System V platforms like AT&T 3Bx. For
2529 those systems we punt by not defining NETCMD, but we might be able to do
2530 better -- see workarounds for this problem in ckufio.c (search for dup2).
2532 if (modem == NET_CMD) {
2534 debug(F100,"ttopen pipe: nopush","",0);
2537 if (pipe(pipe0) || pipe(pipe1)) {
2538 perror("Pipe error");
2541 ttpid = fork(); /* Make a fork */
2544 case -1: /* Error making fork */
2549 perror("Fork error");
2551 case 0: /* Child. */
2560 default: /* Parent */
2563 fdin = pipe0[0]; /* Read from pipe */
2564 fdout = pipe1[1]; /* Write to pipe */
2565 ttout = fdopen(fdout,"w"); /* Get stream so we can */
2566 if (!ttout) { /* make it unbuffered. */
2567 perror("fdopen failure");
2571 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2572 xlocal = *lcl = 1; /* It's local */
2573 netconn = 1; /* Call it a network connection */
2574 ttmdm = modem; /* Remember network type */
2583 x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
2585 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2591 #ifdef sony_news /* Sony NEWS */
2592 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
2593 perror("ttopen error getting Kanji mode (network)");
2594 debug(F111,"ttopen error getting Kanji mode","network",0);
2595 km_ext = -1; /* Make sure this stays undefined. */
2597 #endif /* sony_news */
2599 xlocal = *lcl = 1; /* Network connections are local. */
2600 debug(F101,"ttopen net x","",x);
2602 /* Let netopen() do this */
2603 if (x > -1 && !x25fd)
2604 x = tn_ini(); /* Initialize TELNET protocol */
2605 #endif /* COMMENT */
2608 } else { /* Terminal device */
2609 #endif /* NETCONN */
2613 This code lets you give Kermit an open file descriptor for a serial
2614 communication device, rather than a device name. Kermit assumes that the
2615 line is already open, locked, conditioned with the right parameters, etc.
2617 for (p = ttname; isdigit(*p); p++) ; /* Check for all-digits */
2619 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2620 debug(F111,"ttopen got open fd",ttname,ttyfd);
2621 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2622 if (ttyfd >= 0 && ttyfd < 3) /* If it's stdio... */
2623 xlocal = *lcl = 0; /* we're in remote mode */
2624 else /* otherwise */
2625 xlocal = *lcl = 1; /* local mode. */
2626 netconn = 0; /* Assume it's not a network. */
2627 tvtflg = 0; /* Might need to initialize modes. */
2628 ttmdm = modem; /* Remember modem type. */
2629 fdflag = 0; /* Stdio not redirected. */
2630 ttfdflg = 1; /* Flag we were opened this way. */
2631 debug(F111,"ttopen non-net ttfdflg",ttname,ttfdflg);
2632 debug(F101,"ttopen non-net ttyfd","",ttyfd);
2634 #ifdef sony_news /* Sony NEWS */
2635 /* Get device Kanji mode */
2636 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
2637 perror("ttopen error getting Kanji mode");
2638 debug(F101,"ttopen error getting Kanji mode","",0);
2639 km_ext = -1; /* Make sure this stays undefined. */
2641 #endif /* sony_news */
2643 return(0); /* Return success */
2648 #endif /* NETCONN */
2650 /* Here we have to open a serial device of the given name. */
2652 netconn = 0; /* So it's not a network connection */
2653 occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */
2656 tvtflg = 0; /* Flag for use by ttvt(). */
2657 /* 0 = ttvt not called yet for this device */
2659 fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
2660 debug(F101,"ttopen fdflag","",fdflag);
2662 ttmdm = modem; /* Make this available to other fns */
2663 xlocal = *lcl; /* Make this available to other fns */
2665 /* Code for handling bidirectional tty lines goes here. */
2666 /* Use specified method for turning off logins and suppressing getty. */
2669 /* Should put call to priv_on() here, but that would be very risky! */
2670 acucntrl("disable",ttname); /* acucntrl() program. */
2671 /* and priv_off() here... */
2674 if ((attmodem & DOGETY) == 0) /* offgetty() program. */
2675 attmodem |= offgetty(ttname); /* Remember response. */
2676 #endif /* ATT7300 */
2677 #endif /* ACUCNTRL */
2681 1985-2001: opens device first then gets lock; reason:
2682 Kermit usually has to run setuid or setgid in order to create a lockfile.
2683 If you give a SET LINE command for a device that happens to be your job's
2684 controlling terminal, Kermit doesn't have to create a lockfile, and in fact
2685 should not create one, and would fail if it tried to if it did not have the
2686 required privileges. But you can't find out if two tty device names are
2687 equivalent until you have a file descriptor that you can give to ttyname().
2688 But this can cause a race condition between Kermit and [m]getty. So see
2693 In the following section, we open the tty device for read/write.
2694 If a modem has been specified via "set modem" prior to "set line"
2695 then the O_NDELAY parameter is used in the open, provided this symbol
2696 is defined (e.g. in fcntl.h), so that the program does not hang waiting
2697 for carrier (which in most cases won't be present because a connection
2698 has not been dialed yet). O_NDELAY is removed later on in ttopen(). It
2699 would make more sense to first determine if the line is local before
2700 doing this, but because ttyname() requires a file descriptor, we have
2701 to open it first. See do_open().
2703 Now open the device using the desired treatment of carrier.
2704 If carrier is REQUIRED, then open could hang forever, so an optional
2705 timer is provided. If carrier is not required, the timer should never
2706 go off, and should do no harm...
2708 ttotmo = 0; /* Flag no timeout */
2709 debug(F101,"ttopen timo","",timo);
2710 debug(F101,"ttopen xlocal","",xlocal);
2713 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2714 xx = alarm(timo); /* Timed open() */
2715 debug(F101,"ttopen alarm","",xx);
2721 #endif /* CK_POSIX_SIG */
2723 ttotmo = 1; /* Flag timeout. */
2724 } else ttyfd = do_open(ttname);
2726 debug(F111,"ttopen","modem",modem);
2727 debug(F101,"ttopen ttyfd","",ttyfd);
2728 debug(F101,"ttopen alarm return","",ttotmo);
2731 ttyfd = do_open(ttname);
2733 debug(F111,"ttopen ttyfd",ttname,ttyfd);
2734 if (ttyfd < 0) { /* If couldn't open, fail. */
2735 debug(F101,"ttopen errno","",errno);
2736 if (errno > 0 && !quiet)
2737 perror(ttname); /* Print message */
2740 if (attmodem & DOGETY) /* was getty(1m) running before us? */
2741 ongetty(ttnmsv); /* yes, restart on tty line */
2742 attmodem &= ~DOGETY; /* no phone in use, getty restored */
2745 /* Should put call to priv_on() here, but that would be risky! */
2746 acucntrl("enable",ttname); /* acucntrl() program. */
2747 /* and priv_off() here... */
2748 #endif /* ACUNTRL */
2749 #endif /* ATT7300 */
2751 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
2752 if (errno == EACCES) { /* Device is protected against user */
2753 debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */
2755 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
2760 extern int qnxportlock;
2762 debug(F101,"ttopen qnxopencount","",x);
2763 debug(F101,"ttopen qnxportlock","",qnxportlock);
2764 if (x < 0 && qnxportlock) {
2766 printf("?Can't get port open count\n");
2767 printf("(Try again with SET QNX-PORT-LOCK OFF)\n");
2768 return(-1); /* Indicate device is in use */
2770 if (x > 1) { /* 1 == me */
2773 return(-2); /* Indicate device is in use */
2775 printf("WARNING: \"%s\" looks busy...\n",ttdev);
2781 /* take this opportunity to open the control channel */
2782 if (p9openttyctl(ttname) < 0)
2784 /* Make sure it's a real tty. */
2785 if (!ttfdflg && !isatty(ttyfd) && strcmp(ttname,"/dev/null"))
2788 fprintf(stderr,"%s is not a terminal device\n",ttname);
2789 debug(F111,"ttopen not a tty",ttname,errno);
2793 signal(SIGINT,occt);
2798 /* Apollo C runtime claims that console pads are tty devices, which
2799 * is reasonable, but they aren't any good for packet transfer. */
2800 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
2801 if (st.all != status_$ok) {
2802 fprintf(stderr, "problem getting tty object type: ");
2804 } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
2805 close(ttyfd); ttyfd = -1;
2807 errno = ENOTTY; perror(ttname);
2808 signal(SIGINT,occt);
2813 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2815 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
2817 /* Caller wants us to figure out if line is controlling tty */
2820 if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
2822 debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal);
2823 } else if (strcmp(ttname,cttnam) == 0) {
2825 debug(F111,"ttopen ttname=cttnam",ttname,xlocal);
2826 } else if (cttnam[0]) {
2828 x = ttnmsv; /* ttyname() is broken */
2830 x = ttyname(ttyfd); /* Get real name of ttname. */
2831 #endif /* BEBOX_DR7 */
2834 xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
2837 debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal);
2842 /* Note, the following code was added so that Unix "idle-line" snoopers */
2843 /* would not think Kermit was idle when it was transferring files, and */
2844 /* maybe log people out. */
2845 if (xlocal == 0) { /* Remote mode */
2846 if (fdflag == 0) { /* Standard i/o is not redirected */
2847 debug(F100,"ttopen setting ttyfd = 0","",0);
2849 /* On Lynx OS, fd 0 is open for read only. */
2852 close(ttyfd); /* Use file descriptor 0 */
2854 } else { /* Standard i/o is redirected */
2855 debug(F101,"ttopen stdio redirected","",ttyfd);
2858 #endif /* NOFDZERO */
2860 /* Now check if line is locked -- if so fail, else lock for ourselves */
2861 /* Note: After having done this, don't forget to delete the lock if you */
2862 /* leave ttopen() with an error condition. */
2864 lkf = 0; /* Check lock */
2867 if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
2868 debug(F111,"ttopen ttlock fails",ttname,xx);
2869 /* WARNING - This close() can hang if tty is an empty socket... */
2870 close(ttyfd); /* Close the device. */
2871 ttyfd = -1; /* Erase its file descriptor. */
2873 signal(SIGINT,occt); /* Put old SIGINT back. */
2874 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2875 if (xx == -2) { /* If lockfile says device in use, */
2877 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2878 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2879 if (xpid > -1) { /* If we got a pid */
2881 printf("Locked by process %d\n",xpid); /* tell them. */
2882 sprintf(lockpid,"%d",xpid); /* Record it too */
2883 debug(F110,"ttopen lockpid",lockpid,0);
2884 } else if (*flfnam) {
2885 extern char *DIRCMD;
2888 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2889 p = malloc(x); /* Print a directory listing. */
2891 Note: priv_on() won't help here, because we do not pass privs along to
2892 to inferior processes, in this case ls. So if the real user does not have
2893 directory-listing access to the lockfile directory, this will result in
2894 something like "not found". That's why we try this only as a last resort.
2896 if (p) { /* If we got the space... */
2897 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2898 zsyscmd(p); /* Get listing. */
2899 if (p) { /* free the space */
2906 return(-5); /* Code for device in use */
2907 } else return(-3); /* Access denied */
2910 #else /* OPENFIRST */
2913 27 Oct 2001: New simpler code that gets the lock first and then opens the
2914 device, which eliminates the race condition. The downside is you can no
2915 longer say "set line /dev/ttyp0" or whatever, where /dev/ttyp0 is your login
2916 terminal, without trying to create a lockfile, which fails if C-Kermit lacks
2917 privs, and if it succeeds, it has created a lockfile where it didn't create
2920 xlocal = *lcl; /* Is the device my login terminal? */
2921 debug(F111,"ttopen xlocal","A",xlocal);
2923 if (strcmp(ttname,CTTNAM) && netconn == 0) {
2924 if (zfnqfp(ttname,DEVNAMLEN+1,fullname)) {
2925 if ((int)strlen(fullname) > 0)
2929 debug(F110,"ttopen fnam",fnam,0);
2931 xlocal = (strcmp(fnam,CTTNAM) != 0);
2933 debug(F111,"ttopen xlocal","B",xlocal);
2935 lkf = 0; /* No lock yet */
2936 if (xlocal > 0) { /* If not... */
2938 xx = ttlock(fnam); /* Try to lock it. */
2939 debug(F101,"ttopen ttlock","",xx);
2940 if (xx < 0) { /* Can't lock it. */
2941 debug(F111,"ttopen ttlock fails",fnam,xx);
2942 if (xx == -2) { /* If lockfile says device in use, */
2944 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2945 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2946 if (xpid > -1) { /* If we got a pid */
2948 printf("Locked by process %d\n",xpid); /* tell them. */
2949 ckstrncpy(lockpid,ckitoa(xpid),16);
2950 debug(F110,"ttopen lockpid",lockpid,0);
2952 } else if (flfnam[0] && !nopush) {
2953 extern char *DIRCMD;
2956 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2957 p = malloc(x); /* Print a directory listing. */
2959 Note: priv_on() won't help here, because we do not pass privs along to
2960 to inferior processes, in this case ls. So if the real user does not have
2961 directory-listing access to the lockfile directory, this will result in
2962 something like "not found". That's why we try this only as a last resort.
2964 if (p) { /* If we got the space... */
2965 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2966 zsyscmd(p); /* Get listing. */
2967 if (p) { /* free the space */
2975 return(-5); /* Code for device in use */
2976 } else return(-3); /* Access denied */
2979 /* Have lock -- now it's safe to open the device */
2981 debug(F101,"ttopen lkf","",lkf);
2982 debug(F101,"ttopen timo","",timo);
2984 ttotmo = 0; /* Flag no timeout */
2987 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2988 xx = alarm(timo); /* Timed open() */
2989 debug(F101,"ttopen alarm","",xx);
2995 #endif /* CK_POSIX_SIG */
2997 ttotmo = 1; /* Flag timeout. */
2999 ttyfd = do_open(fnam);
3002 debug(F111,"ttopen timed ttyfd",fnam,ttyfd);
3005 ttyfd = do_open(fnam);
3006 debug(F111,"ttopen untimed ttyfd",fnam,ttyfd);
3008 if (ttyfd < 0) { /* If couldn't open, fail. */
3009 debug(F111,"ttopen errno",fnam,errno);
3010 debug(F111,"ttopen xlocal","C",xlocal);
3012 debug(F100,"ttopen substituting 0","",0);
3015 if (errno > 0 && !quiet) {
3016 debug(F111,"ttopen perror",fnam,errno);
3017 perror(fnam); /* Print message */
3019 if (ttunlck()) /* Release the lock file */
3020 fprintf(stderr,"Warning, problem releasing lock\r\n");
3024 if (ttyfd < 0) { /* ttyfd is still < 0? */
3026 if (attmodem & DOGETY) /* was getty(1m) running before us? */
3027 ongetty(ttnmsv); /* yes, restart on tty line */
3028 attmodem &= ~DOGETY; /* no phone in use, getty restored */
3031 /* Should put call to priv_on() here, but that would be risky! */
3032 acucntrl("enable",fnam); /* acucntrl() program. */
3033 /* and priv_off() here... */
3034 #endif /* ACUNTRL */
3035 #endif /* ATT7300 */
3037 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
3038 if (errno == EACCES) { /* Device is protected against user */
3039 debug(F110,"ttopen EACCESS",fnam,0); /* Return -4 */
3041 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
3044 /* Make sure it's a real tty. */
3047 /* take this opportunity to open the control channel */
3048 if (p9openttyctl(fnam) < 0)
3050 if (!ttfdflg && !isatty(ttyfd) && strcmp(fnam,"/dev/null"))
3053 fprintf(stderr,"%s is not a terminal device\n",fnam);
3054 debug(F111,"ttopen not a tty",fnam,errno);
3055 if (ttunlck()) /* Release the lock file */
3056 fprintf(stderr,"Warning, problem releasing lock\r\n");
3060 signal(SIGINT,occt);
3066 Apollo C runtime claims that console pads are tty devices, which
3067 is reasonable, but they aren't any good for packet transfer.
3069 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
3070 if (st.all != status_$ok) {
3071 fprintf(stderr, "problem getting tty object type: ");
3073 } else if (ttyuid != sio_$uid) { /* Reject non-SIO lines */
3074 close(ttyfd); ttyfd = -1;
3076 errno = ENOTTY; perror(fnam);
3077 signal(SIGINT,occt);
3082 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3084 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
3086 /* Caller wants us to figure out if line is controlling tty */
3090 if (strcmp(fnam,CTTNAM) == 0) { /* "/dev/tty" always remote */
3092 debug(F111,"ttopen fnam=CTTNAM",fnam,xlocal);
3093 } else if (strcmp(fnam,cttnam) == 0) {
3095 debug(F111,"ttopen fnam=cttnam",fnam,xlocal);
3096 } else if (cttnam[0]) {
3098 s = ttnmsv; /* ttyname() is broken */
3100 s = ttyname(ttyfd); /* Get real name of ttname. */
3101 #endif /* BEBOX_DR7 */
3104 xlocal = ((strncmp(s,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
3107 debug(F111,"ttopen ttyname(ttyfd) xlocal",s,xlocal);
3112 /* Note, the following code was added so that Unix "idle-line" snoopers */
3113 /* would not think Kermit was idle when it was transferring files, and */
3114 /* maybe log people out. */
3115 if (xlocal == 0) { /* Remote mode */
3116 if (fdflag == 0) { /* Standard i/o is not redirected */
3117 debug(F100,"ttopen setting ttyfd = 0","",0);
3119 /* On Lynx OS, fd 0 is open for read only. */
3122 close(ttyfd); /* Use file descriptor 0 */
3124 } else { /* Standard i/o is redirected */
3125 debug(F101,"ttopen stdio redirected","",ttyfd);
3128 #endif /* NOFDZERO */
3129 #endif /* OPENFIRST */
3131 /* Got the line, now set the desired value for local. */
3133 if (*lcl != 0) *lcl = xlocal;
3135 /* Some special stuff for v7... */
3139 if (kmem[TTY] < 0) { /* If open, then skip this. */
3140 qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
3141 if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
3142 fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
3143 perror("/dev/kmem");
3150 /* No failure returns after this point */
3153 ioctl(ttyfd, TIOCMODEM, &temp);
3155 if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
3159 #endif /* TIOCSINUSE */
3162 /* Get tty device settings */
3164 #ifdef BSD44ORPOSIX /* POSIX */
3165 tcgetattr(ttyfd,&ttold);
3166 debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
3167 tcgetattr(ttyfd,&ttraw);
3168 debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag);
3169 tcgetattr(ttyfd,&tttvt);
3170 debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag);
3171 #else /* BSD, V7, and all others */
3172 #ifdef ATTSV /* AT&T UNIX */
3173 ioctl(ttyfd,TCGETA,&ttold);
3174 debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
3175 ioctl(ttyfd,TCGETA,&ttraw);
3176 ioctl(ttyfd,TCGETA,&tttvt);
3179 ioctl(ttyfd,TIOCGETP,&ttold);
3180 debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
3181 ioctl(ttyfd,TIOCGDEV,&tdold);
3182 debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
3185 debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
3186 #endif /* BELLV10 */
3188 #ifdef sony_news /* Sony NEWS */
3189 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
3190 perror("ttopen error getting Kanji mode");
3191 debug(F101,"ttopen error getting Kanji mode","",0);
3192 km_ext = -1; /* Make sure this stays undefined. */
3194 #endif /* sony_news */
3197 debug(F100,"ttopen TIOCGETC","",0);
3198 tcharf = 0; /* In remote mode, also get */
3199 if (xlocal == 0) { /* special characters */
3200 if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
3201 debug(F100,"ttopen TIOCGETC failed","",0);
3203 tcharf = 1; /* It worked. */
3204 ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
3205 debug(F100,"ttopen TIOCGETC ok","",0);
3209 debug(F100,"ttopen TIOCGETC not defined","",0);
3210 #endif /* TIOCGETC */
3213 debug(F100,"ttopen TIOCGLTC","",0);
3214 ltcharf = 0; /* In remote mode, also get */
3215 if (xlocal == 0) { /* local special characters */
3216 if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
3217 debug(F100,"ttopen TIOCGLTC failed","",0);
3219 ltcharf = 1; /* It worked. */
3220 ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
3221 debug(F100,"ttopen TIOCGLTC ok","",0);
3225 debug(F100,"ttopen TIOCGLTC not defined","",0);
3226 #endif /* TIOCGLTC */
3229 debug(F100,"ttopen TIOCLGET","",0);
3231 if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
3232 debug(F100,"ttopen TIOCLGET failed","",0);
3235 debug(F100,"ttopen TIOCLGET ok","",0);
3237 #endif /* TIOCLGET */
3240 ioctl(ttyfd,TIOCGETP,&ttraw);
3241 ioctl(ttyfd,TIOCGETP,&tttvt);
3243 gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
3244 gtty(ttyfd,&tttvt); /* And one for virtual tty service */
3245 #endif /* BELLV10 */
3248 #endif /* BSD44ORPOSIX */
3250 /* Section for changing line discipline. It's restored in ttres(). */
3254 { union txname ld_name; int ld_idx = 0;
3257 ld_name.tx_which = ld_idx++;
3258 ioctl(ttyfd, TXGETCD, &ld_name);
3259 if (!strncmp(ld_name.tx_name, "rts", 3))
3261 } while (*ld_name.tx_name);
3262 debug(F101,"AIX line discipline","",ttld);
3268 /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
3270 ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */
3271 debug(F101,"4.1bsd line discipline","",ttld);
3272 k = OTTYDISC; /* Switch to "old" discipline */
3273 k = ioctl(ttyfd, TIOCSETD, &k);
3274 debug(F101,"4.1bsd tiocsetd","",k);
3279 /* This was previously done before the last two TCGETA or gtty above,
3280 * in both the ATTSV and not-ATTSV case. If it is not okay to have only
3281 * one copy if it here instead, give us a shout!
3283 sio_$control((short)ttyfd, sio_$raw_nl, false, st);
3284 if (xlocal) { /* ignore breaks from local line */
3285 sio_$control((short)ttyfd, sio_$int_enable, false, st);
3286 sio_$control((short)ttyfd, sio_$quit_enable, false, st);
3291 ttraw.c_line = 0; /* STTY line 0 for VX/VE */
3292 tttvt.c_line = 0; /* STTY line 0 for VX/VE */
3293 ioctl(ttyfd,TCSETA,&ttraw);
3296 /* If O_NDELAY was used during open(), then remove it now. */
3299 debug(F100,"ttopen O_NDELAY","",0);
3301 if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
3302 debug(F100,"ttopen fcntl O_NDELAY","",0);
3304 if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) {
3305 debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0);
3306 perror("Can't unset O_NDELAY");
3309 /* Some systems, notably Xenix (don't know how common this is in
3310 * other systems), need special treatment to get rid of the O_NDELAY
3311 * behaviour on read() with respect to carrier presence (i.e. read()
3312 * returning 0 when carrier absent), even though the above fcntl()
3313 * is enough to make read() wait for input when carrier is present.
3314 * This magic, in turn, requires CLOCAL for working when the carrier
3315 * is absent. But if xlocal == 0, presumably you already have CLOCAL
3316 * or you have a carrier, otherwise you wouldn't be running this.
3318 debug(F101,"ttopen xlocal","",xlocal);
3321 #ifdef COMMENT /* 12 Aug 1997 */
3324 ttraw.c_cflag |= CLOCAL;
3328 ttraw.c_cflag |= CLOCAL;
3329 #endif /* __FreeBSD__ */
3330 #endif /* __bsdi__ */
3331 #else /* Not COMMENT */
3333 if (xlocal) /* Unset this if it's defined. */
3334 ttraw.c_cflag |= CLOCAL;
3336 #endif /* COMMENT */
3337 debug(F101,"ttopen BSD44ORPOSIX calling tcsetattr","",TCSADRAIN);
3338 if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0) {
3339 debug(F100,"ttopen POSIX tcseattr fails","",0);
3340 perror("tcsetattr");
3342 #else /* !BSD44ORPOSIX */
3344 ttraw.c_cflag |= CLOCAL;
3345 debug(F100,"ttopen calling ioctl(TCSETA)","",0);
3347 if (ioctl(ttyfd, TCSETA, &ttraw) < 0) {
3348 debug(F101,"ttopen ioctl(TCSETA) fails","",errno);
3349 perror("ioctl(TCSETA)");
3352 #endif /* BSD44ORPOSIX */
3354 #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
3355 /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
3356 debug(F100,"ttopen executing close/open","",0);
3357 close( priv_opn(fnam, O_RDWR) ); /* Magic to force change. */
3358 #endif /* NOCOTFMC */
3361 #endif /* O_NDELAY */
3363 /* Instruct the system how to treat the carrier, and set a few other tty
3366 * This also undoes the temporary setting of CLOCAL that may have been done
3367 * for the close(open()) above (except in Xenix). Also throw in ~ECHO, to
3368 * prevent the other end of the line from sitting there talking to itself,
3369 * producing garbage when the user performs a connect.
3371 * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
3372 * Now it thinks CLOCAL is always on. It seems the only real solution for
3373 * Xenix is to switch between the lower and upper case device names.
3375 * This section may at some future time expand into setting a complete
3376 * collection of tty parameters, or call a function shared with ttpkt()/
3377 * ttvt() that does so. On the other hand, the initial parameters are not
3378 * that important, since ttpkt() or ttvt() should always fix that before
3379 * any communication is done. Well, we'll see...
3383 debug(F100,"ttopen calling carrctl","",0);
3384 carrctl(&ttraw, ttcarr == CAR_ON);
3385 debug(F100,"ttopen carrctl ok","",0);
3389 #endif /* COHERENT */
3392 ttraw.c_lflag &= ~ECHO;
3393 ttold.c_lflag &= ~ECHO;
3395 y = tcsetattr(ttyfd, TCSADRAIN, &ttraw);
3396 debug(F101,"ttopen tcsetattr","",y);
3398 y = ioctl(ttyfd, TCSETA, &ttraw);
3399 debug(F100,"ttopen ioctl","",y);
3400 #endif /* BSD44ORPOSIX */
3402 #else /* BSD, etc */
3403 ttraw.sg_flags &= ~ECHO;
3404 ttold.sg_flags &= ~ECHO;
3406 y = ioctl(ttyfd,TIOCSETP,&ttraw);
3407 debug(F100,"ttopen ioctl","",y);
3409 y = stty(ttyfd,&ttraw);
3410 debug(F100,"ttopen stty","",y);
3411 #endif /* BELLV10 */
3412 #endif /* SVORPOSIX */
3416 #endif /* COHERENT */
3418 /* ttflui(); */ /* This fails for some reason. */
3421 /* Get current speed */
3428 debug(F101,"ttopen ttspeed","",ttspeed);
3430 /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
3432 debug(F101,"ttopen ttyfd","",ttyfd);
3433 debug(F101,"ttopen *lcl","",*lcl);
3434 debug(F111,"ttopen lock file",flfnam,lkf);
3435 signal(SIGINT,occt);
3436 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3442 /* D O _ O P E N -- Do the right kind of open() call for the tty. */
3445 do_open(ttname) char *ttname; {
3449 /* O_NONBLOCK on /dev/tty makes open() fail */
3450 return(priv_opn(ttname, O_RDWR |
3452 ((int)strcmp(ttname,"/dev/tty") == 0) ?
3454 (ttcarr != CAR_ON) ? O_NONBLOCK : 0)
3459 #ifndef O_NDELAY /* O_NDELAY not defined */
3460 return(priv_opn(ttname,2));
3461 #else /* O_NDELAY defined */
3465 Open comms line without waiting for carrier so initial call does not hang
3466 because state of "modem" is likely unknown at the initial call -jrd.
3467 If this is needed for the getty stuff to work, and the open would not work
3468 without O_NDELAY when getty is still on, then this special case is ok.
3469 Otherwise, get rid of it. -ske
3471 return(priv_opn(ttname, O_RDWR | O_NDELAY));
3473 #else /* !ATT7300 */
3475 /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
3477 debug(F101,"do_open xlocal","",xlocal);
3478 debug(F111,"do_open flags A",ttname,flags);
3479 if (xlocal && (ttcarr != CAR_ON))
3481 debug(F111,"do_open flags B",ttname,flags);
3482 return(priv_opn(ttname, flags));
3483 #endif /* !ATT7300 */
3484 #endif /* O_NDELAY */
3488 /* T T C L O S -- Close the TTY, releasing any lock. */
3490 static int ttc_state = 0; /* ttclose() state */
3491 static char * ttc_nam[] = { "setup", "hangup", "reset", "close" };
3494 ttclos(foo) int foo; { /* Arg req'd for signal() prototype */
3496 extern int exithangup;
3498 debug(F101,"ttclos ttyfd","",ttyfd);
3499 debug(F101,"ttclos netconn","",netconn);
3500 debug(F101,"ttclos xlocal","",xlocal);
3502 debug(F100,"ttclos NOFDZERO","",0);
3503 #endif /* NOFDZERO */
3507 le_init(); /* No need for any of this */
3508 #endif /* TTLEBUF */
3509 #endif /* COMMENT */
3511 if (ttyfd < 0) /* Wasn't open. */
3514 if (ttfdflg) /* If we inherited ttyfd from */
3515 return(0); /* another process, don't close it. */
3517 tvtflg = 0; /* (some day get rid of this...) */
3523 tn_push(); /* Place any waiting data into input*/
3524 tn_sopt(DO,TELOPT_LOGOUT); /* Send LOGOUT option before close */
3525 TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
3526 tn_reset(); /* The Reset Telnet Option table. */
3529 if (ssl_active_flag) {
3531 BIO_printf(bio_err,"calling SSL_shutdown(ssl)\n");
3532 SSL_shutdown(ssl_con);
3535 ssl_active_flag = 0;
3537 if (tls_active_flag) {
3539 BIO_printf(bio_err,"calling SSL_shutdown(tls)\n");
3540 SSL_shutdown(tls_con);
3543 tls_active_flag = 0;
3549 if (ttpipe) { /* We've been using a pipe */
3554 close(fdin); /* Close these. */
3557 kill(ttpid,1); /* Kill fork with SIGHUP */
3559 wstat = wait(&statusp);
3560 if (wstat == ttpid || wstat == -1)
3562 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
3576 #endif /* NODOPTY */
3587 if (netconn) { /* If it's a network connection. */
3588 debug(F100,"ttclos closing net","",0);
3589 netclos(); /* Let the network module close it. */
3590 netconn = 0; /* No more network connection. */
3591 debug(F101,"ttclos ttyfd after netclos","",ttyfd); /* Should be -1 */
3594 #endif /* NETCONN */
3596 if (xlocal) { /* We're closing a SET LINE device */
3597 #ifdef FT21 /* Fortune 2.1-specific items ... */
3598 ioctl(ttyfd,TIOCHPCL, NULL);
3600 #ifdef ultrix /* Ultrix-specific items ... */
3602 /* Unset the INUSE flag that we set in ttopen() */
3603 ioctl(ttyfd, TIOCSINUSE, NULL);
3604 #endif /* TIOCSINUSE */
3605 ioctl(ttyfd, TIOCNMODEM, &x);
3607 /* What was this? */
3608 ioctl(ttyfd, TIOCNCAR, NULL);
3609 #endif /* COMMENT */
3613 /* This is to prevent us from sticking in tthang() or close(). */
3617 if (ttyfd > 0) { /* But skip it on stdin. */
3618 debug(F100,"ttclos setting O_NDELAY","",0);
3619 x = fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL, 0)|O_NDELAY);
3621 if (deblog && x == -1) {
3622 perror("Warning - Can't set O_NDELAY");
3623 debug(F101,"ttclos fcntl failure to set O_NDELAY","",x);
3628 #endif /* O_NDELAY */
3635 #endif /* NOFDZERO */
3637 saval = signal(SIGALRM,xtimerh); /* Enable timer interrupt. */
3638 xx = alarm(8); /* Allow 8 seconds. */
3639 debug(F101,"ttclos alarm","",xx);
3645 #endif /* CK_POSIX_SIG */
3646 ) { /* Timer went off? */
3649 debug(F111,"ttclos ALARM TRAP errno",ckitoa(ttc_state),errno);
3650 printf("ttclos() timeout: %s\n", ttc_nam[ttc_state]);
3653 /* Hang up the device (drop DTR) */
3656 debug(F111,"ttclos A",ckitoa(x),ttc_state);
3657 if (ttc_state < 1) {
3659 debug(F101,"ttclos exithangup","",exithangup);
3661 alarm(8); /* Re-arm the timer */
3662 debug(F101,"ttclos calling tthang()","",x);
3663 x = tthang(); /* Hang up first, then... */
3664 debug(F101,"ttclos tthang()","",x);
3668 Oct 2006 - Leave DTR on if SET EXIT HANGUP OFF.
3669 Suggested by Soewono Effendi.
3673 ttold.c_cflag &= ~HUPCL; /* Let's see how this travels */
3675 tcsetattr(ttyfd,TCSANOW,&ttold);
3676 #else /* !BSD44ORPOSIX */
3678 ioctl(ttyfd,TCSETAW,&ttold);
3682 #endif /* BSD44ORPOSIX */
3685 #endif /* CK_NOHUPCL */
3687 /* Put back device modes as we found them */
3690 debug(F111,"ttclos B",ckitoa(x),ttc_state);
3691 if (ttc_state < 2) {
3693 /* Don't try to mess with tty modes if tthang failed() */
3694 /* since it probably won't work. */
3696 debug(F101,"ttclos calling ttres()","",x);
3697 signal(SIGALRM,xtimerh); /* Re-enable the alarm. */
3698 alarm(8); /* Re-arm the timer */
3699 x = ttres(); /* Reset device modes. */
3700 debug(F101,"ttclos ttres()","",x);
3704 /* Close the device */
3707 debug(F101,"ttclos C","",ttc_state);
3708 if (ttc_state < 3) {
3711 debug(F101,"ttclos calling close","",x);
3712 signal(SIGALRM,xtimerh); /* Re-enable alarm. */
3713 alarm(8); /* Re-arm the timer */
3714 x = close(ttyfd); /* Close the device. */
3715 debug(F101,"ttclos close()","",x);
3719 debug(F101,"ttclos D","",ttc_state);
3720 ttimoff(); /* Turn off timer. */
3722 printf("?WARNING - close failed: %s\n",ttnmsv);
3725 printf("errno = %d\n", errno);
3726 debug(F101,"ttclos failed","",errno);
3730 /* Unlock after closing but before any getty mumbo jumbo */
3732 debug(F100,"ttclos about to call ttunlck","",0);
3733 if (ttunlck()) /* Release uucp-style lock */
3734 fprintf(stderr,"Warning, problem releasing lock\r\n");
3737 /* For bidirectional lines, restore getty if it was there before. */
3739 #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */
3741 debug(F100,"ttclos ACUCNTRL","",0);
3742 acucntrl("enable",ttnmsv); /* Enable getty on the device. */
3745 #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */
3747 debug(F100,"ttclos ATT7300 ongetty","",0);
3748 if (attmodem & DOGETY) /* Was getty(1m) running before us? */
3749 ongetty(ttnmsv); /* Yes, restart getty on tty line */
3750 attmodem &= ~DOGETY; /* No phone in use, getty restored */
3752 #endif /* ATT7300 */
3753 #endif /* System-dependent getty-restoring methods */
3756 km_ext = -1; /* Invalidate device's Kanji-mode */
3757 #endif /* sony_news */
3759 ttyfd = -1; /* Invalidate the file descriptor. */
3761 debug(F100,"ttclos done","",0);
3765 /* T T H A N G -- Hangup phone line or network connection. */
3768 0 if it does nothing.
3769 1 if it believes that it hung up successfully.
3770 -1 if it believes that the hangup attempt failed.
3773 #define HUPTIME 500 /* Milliseconds for hangup */
3776 /* The following didn't work but TIOCSDTR does work */
3778 /* Define HUP_POSIX to force non-POSIX builds to use the POSIX hangup method */
3779 #ifndef POSIX /* Such as Unixware 1.x, 2.x */
3782 #endif /* HUP_POSIX */
3784 #endif /* UNIXWARE */
3785 #endif /* COMMENT */
3787 #ifndef USE_TIOCSDTR
3789 /* Because the POSIX method (set output speed to 0) doesn't work in NetBSD */
3792 #define USE_TIOCSDTR
3793 #endif /* TIOCCDTR */
3794 #endif /* TIOCSDTR */
3795 #endif /* __NetBSD__ */
3796 #endif /* USE_TIOCSDTR */
3798 #ifndef HUP_CLOSE_POSIX
3800 #define HUP_CLOSE_POSIX
3803 #define HUP_CLOSE_POSIX
3804 #endif /* CK_SCOV5 */
3806 #endif /* HUP_CLOSE_POSIX */
3808 #ifdef NO_HUP_CLOSE_POSIX
3809 #ifdef HUP_CLOSE_POSIX
3810 #undef HUP_CLOSE_POSIX
3811 #endif /* HUP_CLOSE_POSIX */
3812 #endif /* NO_HUP_CLOSE_POSIX */
3819 int x = 0; /* Sometimes used as return code. */
3826 #endif /* COHERENT */
3828 #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */
3829 int spdsav; /* for saving speed */
3835 #endif /* BSD44ORPOSIX */
3836 #endif /* HUP_POSIX */
3839 Early versions of HP-UX omitted the mflag typedef. If you get complaints
3840 about it, just change it to long (or better still, unsigned long).
3843 dtr_down = 00000000000,
3846 char modem_state[64];
3848 int flags; /* fcntl flags */
3849 unsigned short ttc_save;
3850 #endif /* SVORPOSIX */
3852 if (ttyfd < 0) return(0); /* Don't do this if not open */
3853 if (xlocal < 1) return(0); /* Don't do this if not local */
3857 return((ttclos(0) < 0) ? -1 : 1);
3861 return((ttclos(0) < 0) ? -1 : 1);
3864 if (netconn) { /* Network connection. */
3866 if (istncomport()) {
3867 int rc = tnc_set_dtr_state(0);
3870 rc = tnc_set_dtr_state(1);
3872 return(rc >= 0 ? 1 : -1);
3874 #endif /* TN_COMPORT */
3875 return((netclos() < 0) ? -1 : 1); /* Just close it. */
3877 #endif /* NETCONN */
3879 /* From here down, we handle real tty devices. */
3882 e.g. for Unixware 2, where we don't have a full POSIX build, we
3883 still have to use POSIX-style hangup. Thus the duplication of this
3884 and the next case, the only difference being we use a local termios
3885 struct here, since a different model is used elsewhere.
3887 NO LONGER USED as of C-Kermit 8.0 -- it turns out that this method,
3888 even though it compiles and executes without error, doesn't actually
3889 work (i.e. DTR does not drop), whereas the TIOCSDTR method works just fine,
3892 struct termios ttcur;
3894 debug(F100,"tthang HUP_POSIX style","",0);
3895 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3896 debug(F111,"tthang tcgetattr",ckitoa(errno),x);
3897 if (x < 0) return(-1);
3898 spdsav = cfgetospeed(&ttcur); /* Get current speed */
3899 debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
3900 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
3901 debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
3902 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
3903 debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
3904 if (x < 0) return(-1);
3905 x = cfsetispeed(&ttcur,B0);
3906 debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
3907 if (x < 0) return(-1);
3908 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3909 debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
3910 if (x < 0) return(-1);
3911 msleep(HUPTIME); /* Sleep 0.5 sec */
3912 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
3913 if (x < 0) return(-1);
3914 debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
3915 x = cfsetispeed(&ttcur,spdsavi);
3916 debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
3917 if (x < 0) return(-1);
3918 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3919 debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
3920 if (x < 0) return(-1);
3928 x = tcdropline(ttyfd,500);
3929 debug(F101,"tthang QNX tcdropline","",x);
3930 ttcur.c_cflag |= CLOCAL;
3931 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3932 debug(F101,"tthang QNX tcsetattr restore","",x);
3934 debug(F101,"tthang QNX tcsetattr restore errno","",errno);
3937 /* Fix flags - ensure O_NONBLOCK is off */
3940 debug(F101,"tthang QNX iniflags","",iniflags);
3941 if (fcntl(ttyfd, F_SETFL, iniflags) == -1) {
3942 debug(F101,"tthang QNX F_SETFL errno","",errno);
3951 debug(F100,"tthang BSD44ORPOSIX USE_TIOCSDTR","",0);
3953 x = ioctl(ttyfd, TIOCCDTR, NULL);
3954 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCCDTR",ckitoa(errno),x);
3955 if (x < 0) return(-1);
3956 msleep(HUPTIME); /* Sleep 0.5 sec */
3958 x = ioctl(ttyfd, TIOCSDTR, NULL);
3959 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCSDTR",ckitoa(errno),x);
3960 if (x < 0) return(-1);
3961 #else /* USE_TIOCSDTR */
3963 #ifdef HUP_CLOSE_POSIX
3965 In OSR5 versions where TIOCSDTR is not defined (up to and including at
3966 least 5.0.6a) the POSIX APIs in the "#else" part below are available but
3967 don't work, and no other APIs are available that do work. In this case
3968 we have to drop DTR by brute force: close and reopen the port. This
3969 code actually works, but all the steps are crucial: setting CLOCAL, the
3970 O_NDELAY manipulations, etc.
3972 debug(F100,"tthang HUP_CLOSE_POSIX close/open","",0);
3973 debug(F101,"tthang HUP_CLOSE_POSIX O_NONBLOCK","",O_NONBLOCK);
3974 debug(F101,"tthang HUP_CLOSE_POSIX O_NDELAY","",O_NDELAY);
3976 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3977 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr","",x);
3979 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr errno","",errno);
3984 x = close(ttyfd); /* Close without releasing lock */
3986 debug(F101,"tthang HUP_CLOSE_POSIX close errno","",errno);
3990 x = msleep(500); /* Pause half a second */
3991 if (x < 0) { /* Or if that doesn't work, 1 sec */
3992 debug(F101,"tthang HUP_CLOSE_POSIX msleep errno","",errno);
3996 ttyfd = priv_opn(ttnmsv, (O_RDWR|O_NDELAY)); /* Reopen the device */
3997 debug(F111,"tthang HUP_CLOSE_POSIX reopen",ttnmsv,ttyfd);
3999 debug(F101,"tthang HUP_CLOSE_POSIX reopen errno","",errno);
4002 debug(F101,"tthang HUP_CLOSE_POSIX re-ttopen ttyfd","",ttyfd);
4004 /* Restore previous attributes */
4008 ttcur.c_cflag |= CLOCAL;
4009 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4010 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore","",x);
4012 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore errno",
4016 /* Fix flags - ensure O_NDELAY and O_NONBLOCK are off */
4019 if ((x = fcntl(ttyfd, F_GETFL, 0)) == -1) {
4020 debug(F101,"tthang HUP_CLOSE_POSIX F_GETFL errno","",errno);
4023 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4025 x &= ~(O_NONBLOCK|O_NDELAY);
4026 debug(F101,"tthang HUP_CLOSE_POSIX flags to set","",x);
4027 debug(F101,"tthang HUP_CLOSE_POSIX iniflags","",iniflags);
4028 if (fcntl(ttyfd, F_SETFL, x) == -1) {
4029 debug(F101,"tthang HUP_CLOSE_POSIX F_SETFL errno","",errno);
4034 if ((x = fcntl(ttyfd, F_GETFL, 0)) > -1) {
4035 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4036 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NONBLOCK",
4038 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NDELAY",
4044 #else /* HUP_CLOSE_POSIX */
4046 /* General BSD44ORPOSIX case (Linux, BSDI, FreeBSD, etc) */
4048 debug(F100,"tthang BSD44ORPOSIX B0","",0);
4049 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
4050 debug(F111,"tthang BSD44ORPOSIX tcgetattr",ckitoa(errno),x);
4051 if (x < 0) return(-1);
4052 spdsav = cfgetospeed(&ttcur); /* Get current speed */
4053 debug(F111,"tthang BSD44ORPOSIX cfgetospeed",ckitoa(errno),spdsav);
4054 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
4055 debug(F111,"tthang BSD44ORPOSIX cfgetispeed",ckitoa(errno),spdsavi);
4056 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
4057 debug(F111,"tthang BSD44ORPOSIX cfsetospeed",ckitoa(errno),x);
4058 if (x < 0) return(-1);
4059 x = cfsetispeed(&ttcur,B0);
4060 debug(F111,"tthang BSD44ORPOSIX cfsetispeed",ckitoa(errno),x);
4061 if (x < 0) return(-1);
4062 /* This gets EINVAL on NetBSD 1.4.1 because of B0... */
4063 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4064 debug(F111,"tthang BSD44ORPOSIX tcsetattr B0",ckitoa(errno),x);
4065 if (x < 0) return(-1);
4066 msleep(HUPTIME); /* Sleep 0.5 sec */
4067 debug(F101,"tthang BSD44ORPOSIX restore output speed","",spdsav);
4068 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
4069 debug(F111,"tthang BSD44ORPOSIX cfsetospeed prev",ckitoa(errno),x);
4070 if (x < 0) return(-1);
4071 debug(F101,"tthang BSD44ORPOSIX restore input speed","",spdsavi);
4072 x = cfsetispeed(&ttcur,spdsavi);
4073 debug(F111,"tthang BSD44ORPOSIX cfsetispeed prev",ckitoa(errno),x);
4074 if (x < 0) return(-1);
4075 ttcur.c_cflag |= CLOCAL; /* Don't expect CD after hangup */
4076 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4077 debug(F111,"tthang BSD44ORPOSIX tcsetattr restore",ckitoa(errno),x);
4078 if (x < 0) return(-1);
4080 #endif /* HUP_CLOSE_POSIX */
4081 #endif /* USE_TIOCSDTR */
4087 #else /* BSD44ORPOSIX */
4089 #ifdef aegis /* Apollo Aegis */
4090 sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */
4091 msleep(HUPTIME); /* pause */
4092 sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */
4096 #ifdef ANYBSD /* Any BSD version. */
4097 #ifdef TIOCCDTR /* Except those that don't have this */
4098 debug(F100,"tthang BSD style","",0);
4099 if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */
4100 debug(F101,"tthang TIOCCDTR fails","",errno);
4103 msleep(HUPTIME); /* For about 1/2 sec */
4105 x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
4108 For some reason, this tends to fail with "no such device or address"
4109 but the operation still works, probably because of the close/open
4110 later on. So let's not scare the user unnecessarily here.
4112 debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
4113 x = 1; /* Pretend we succeeded */
4114 } else if (x == 0) x = 1; /* Success */
4117 ioctl(ttyfd, TIOCSAVEMODES, 0);
4118 ioctl(ttyfd, TIOCHPCL, 0);
4119 close(ttyfd); /* Yes, must do this twice */
4120 if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */
4121 return(-1); /* (but why?) */
4124 #endif /* COMMENT */
4125 #endif /* TIOCCDTR */
4126 close(do_open(ttnmsv)); /* Clear i/o error condition */
4129 /* This is definitely dangerous. Why was it here? */
4130 z = ttvt(ttspeed,ttflow); /* Restore modes. */
4131 debug(F101,"tthang ttvt returns","",z);
4132 return(z < 0 ? -1 : 1);
4135 #endif /* COMMENT */
4139 /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
4142 /* Hewlett Packard allows explicit manipulation of modem signals. */
4146 debug(F100,"tthang HP-UX style","",0);
4147 if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) /* lower DTR */
4148 return(-1); /* oops, can't. */
4149 msleep(HUPTIME); /* Pause half a second. */
4150 x = 1; /* Set return code */
4151 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4152 if ((modem_rtn & MDCD) != 0) /* Check if CD is low. */
4153 x = -1; /* CD didn't drop, fail. */
4156 /* Even if above calls fail, RTS & DTR should be turned back on. */
4157 modem_rtn = MRTS | MDTR;
4158 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
4161 /* New way, from Hellmuth Michaelis */
4162 debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
4163 if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
4164 debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
4167 sprintf(modem_state,"%#lx",modem_rtn);
4168 debug(F110,"tthang HP-UX: modem lines = ",modem_state,0);
4169 modem_sav = modem_rtn; /* Save current modem signals */
4170 modem_rtn &= ~MDTR; /* Turn DTR bit off */
4171 sprintf(modem_state,"%#lx",modem_rtn);
4172 debug(F110,"tthang HP-UX: DTR down = ",modem_state,0);
4173 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
4174 debug(F100,"tthang HP-UX: can't lower DTR!","",0);
4175 return(-1); /* oops, can't. */
4177 msleep(HUPTIME); /* Pause half a second. */
4178 x = 1; /* Set return code */
4179 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4180 sprintf(modem_state,"%#lx",modem_rtn);
4181 debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
4182 if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */
4183 debug(F100,"tthang HP-UX: DCD not down","",0);
4184 x = -1; /* CD didn't drop, fail. */
4186 debug(F100,"tthang HP-UX: DCD down","",0);
4190 debug(F100,"tthang HP-UX: can't get DCD status !","",0);
4193 /* Even if above calls fail, DTR should be turned back on. */
4196 if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
4198 debug(F100,"tthang HP-UX: can't set saved state","",0);
4200 sprintf(modem_state,"%#lx",modem_sav);
4201 debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
4204 #endif /* COMMENT */
4206 #else /* AT&T but not HP-UX */
4208 /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
4209 /* It is not known how many, if any, systems actually implement them, */
4210 /* so we include them here in ifdef's. */
4213 Unixware has the TIOCMxxx symbols defined, but calling ioctl() with them
4214 gives error 22 (invalid argument).
4218 No modem-signal twiddling for IBM RT PC or RS/6000.
4219 In AIX 3.1 and earlier, the ioctl() call is broken.
4220 This code could be activated for AIX 3.1 with PTF 2006 or later
4221 (e.g. AIX 3.2), but close/open does the job too, so why bother.
4223 #ifdef TIOCMBIS /* Bit Set */
4224 #ifdef TIOCMBIC /* Bit Clear */
4225 #ifdef TIOCM_DTR /* DTR */
4227 /* Clear DTR, sleep 300 msec, turn it back on. */
4228 /* If any of the ioctl's return failure, go on to the next section. */
4230 z = TIOCM_DTR; /* Code for DTR. */
4233 This was the cause of the troubles with the Solaris Port Monitor.
4234 The problem is: RTS never comes back on. Moral: Don't do it!
4235 (But why doesn't it come back on? See the TIOCMBIS call...)
4237 #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */
4239 #endif /* TIOCM_RTS */
4240 #endif /* COMMENT */
4242 debug(F101,"tthang TIOCM signal mask","",z);
4243 if (ioctl(ttyfd,TIOCMBIC,&z) > -1) { /* Try to lower DTR. */
4244 debug(F100,"tthang TIOCMBIC ok","",0);
4245 msleep(HUPTIME); /* Pause half a second. */
4246 if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
4247 debug(F100,"tthang TIOCMBIS ok","",0);
4249 return(1); /* Success, done. */
4251 } else { /* Couldn't raise, continue. */
4252 debug(F101,"tthang TIOCMBIS errno","",errno);
4254 } else { /* Couldn't lower, continue. */
4255 debug(F101,"tthang TIOCMBIC errno","",errno);
4257 #endif /* TIOCM_DTR */
4258 #endif /* TIOCMBIC */
4259 #endif /* TIOCMBIS */
4263 General AT&T UNIX case, not HPUX. The following code is highly suspect. No
4264 two AT&T-based systems seem to do this the same way. The object is simply
4265 to turn off DTR and then turn it back on. SVID says the universal method
4266 for turning off DTR is to set the speed to zero, and this does seem to do
4267 the trick in all cases. But neither SVID nor any known man pages say how to
4268 turn DTR back on again. Some variants, like most Xenix implementations,
4269 raise DTR again when the speed is restored to a nonzero value. Others
4270 require the device to be closed and opened again, but this is risky because
4271 getty could seize the device during the instant it is closed.
4274 /* Return code for ioctl failures... */
4276 x = 1; /* ATT6300 doesn't want to fail... */
4279 #endif /* ATT6300 */
4281 debug(F100,"tthang get settings","",0);
4282 if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
4283 return(x); /* Fail if this doesn't work. */
4284 if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
4286 ttc_save = ttcur.c_cflag; /* Remember current speed. */
4287 spdsav = ttc_save & CBAUD;
4288 debug(F101,"tthang speed","",spdsav);
4291 debug(F100,"tthang turning O_NDELAY on","",0);
4292 fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
4293 #endif /* O_NDELAY */
4295 #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
4296 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4299 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4300 #else /* This way really works but may be dangerous */
4302 ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */
4303 /* (CLOCAL must be OFF) */
4305 #ifdef SCO3R2 /* SCO UNIX 3.2 */
4307 This is complete nonsense, but an SCO user claimed this change made
4308 hanging up work. Comments from other SCO UNIX 3.2 users would be
4311 ttcur.c_cflag = CBAUD|B0;
4313 #ifdef AIXRS /* AIX on RS/6000 */
4315 Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
4316 even though you can do it on the built-in port and the 8- and 16-port
4317 adapters. (Untested on 128-port adapter.)
4319 ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
4320 #else /* None of the above */
4322 Set everything, including the speed, to zero, except for the CLOCAL
4325 ttcur.c_cflag = CLOCAL|HUPCL;
4330 #endif /* ATT7300 */
4333 /* and if none of those work, try one of these... */
4335 ttcur.c_cflag = CLOCAL;
4336 ttcur.c_cflag &= ~(CBAUD|HUPCL);
4337 ttcur.c_cflag &= ~(CBAUD|CREAD);
4338 ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
4339 /* or other combinations */
4340 #endif /* COMMENT */
4343 debug(F100,"tthang TCXONC","",0);
4344 if (ioctl(ttyfd, TCXONC, 1) < 0) {
4345 debug(F101,"tthang TCXONC failed","",errno);
4350 debug(F100,"tthang TIOCSTART","",0);
4351 if (ioctl(ttyfd, TIOCSTART, 0) < 0) {
4352 debug(F101,"tthang TIOCSTART failed","",errno);
4354 #endif /* TIOCSTART */
4356 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
4357 debug(F101,"tthang TCSETAF failed","",errno);
4358 fcntl(ttyfd, F_SETFL, flags); /* Restore flags */
4359 return(-1); /* before returning. */
4361 msleep(300); /* Give modem time to notice. */
4365 /* Now, even though it doesn't say this in SVID or any man page, we have */
4366 /* to close and reopen the device. This is not necessary for all systems, */
4367 /* but it's impossible to predict which ones need it and which ones don't. */
4371 Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
4372 related ioctl's for their internal modems. attmodem has getty status and
4373 modem-in-use bit. Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
4374 but also ruins the file descriptor, and no other phone(7) ioctl call can fix
4375 it. Whatever it does, it seems to escape detection with PIOCGETA and TCGETA.
4376 The only way to undo the damage is to close the fd and then reopen it.
4378 if (attmodem & ISMODEM) {
4379 debug(F100,"tthang attmodem close/open","",0);
4380 ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
4381 ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */
4382 close(ttyfd); /* Close and reopen the fd. */
4383 ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
4384 attmodem &= ~ISMODEM; /* Phone no longer in use. */
4386 #else /* !ATT7300 */
4387 /* It seems we have to close and open the device for other AT&T systems */
4388 /* too, and this is the place to do it. The following code does the */
4389 /* famous close(open(...)) magic by default. If that doesn't work for you, */
4390 /* then try uncommenting the following statement or putting -DCLSOPN in */
4391 /* the makefile CFLAGS. */
4393 /* #define CLSOPN */
4395 #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
4398 #define OPENFLGS O_RDWR | O_NDELAY
4400 #define OPENFLGS O_RDWR
4404 /* This method is used by default, i.e. unless CLSOPN is defined. */
4405 /* It is thought to be safer because there is no window where getty */
4406 /* can seize control of the device. The drawback is that it might not work. */
4408 debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
4409 close(priv_opn(ttnmsv, OPENFLGS));
4412 /* This method is used if you #define CLSOPN. It is more likely to work */
4413 /* than the previous method, but it's also more dangerous. */
4415 debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
4418 ttyfd = priv_opn(ttnmsv, OPENFLGS); /* Open it again */
4423 #endif /* ATT7300 */
4425 #endif /* NOCOTFMC */
4427 /* Now put all flags & modes back the way we found them. */
4428 /* (Does the order of ioctl & fcntl matter ? ) */
4430 debug(F100,"tthang restore settings","",0);
4431 ttcur.c_cflag = ttc_save; /* Get old speed back. */
4432 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
4436 This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
4437 After closing a modem line, the modem will probably not be asserting
4438 carrier any more, so we should not require carrier any more. If this
4439 causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
4442 flags &= ~O_NDELAY; /* Don't require carrier on reopen */
4443 #endif /* O_NDELAY */
4444 if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */
4448 #endif /* not HPUX */
4450 #endif /* BSD44ORPOSIX */
4451 #endif /* HUP_POSIX */
4452 #endif /* NOLOCAL */
4456 Major change in 5A(174). We used to use LPASS8, if it was defined, to
4457 allow 8-bit data and Xon/Xoff flow control at the same time. But this
4458 LPASS8 business seems to have been causing trouble for everybody but me!
4459 For example, Annex terminal servers, commonly used with Encore computers,
4460 do not support LPASS8 even though the Encore itself does. Ditto for many
4461 other terminal servers, TELNET connections, rlogin connections, etc etc.
4462 Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
4463 serial lines, even though LPASS8 is a feature of 4.3BSD. So let's turn it
4464 off for everybody. That means we goes back to using raw mode, with no
4465 flow control. Phooey.
4467 NOTE: This must be done before the first reference to LPASS8 in this file,
4468 and after the last #include statment.
4474 /* T T R E S -- Restore terminal to "normal" mode. */
4476 /* ske@pkmab.se: There are two choices for what this function should do.
4477 * (1) Restore the tty to current "normal" mode, with carrier treatment
4478 * according to ttcarr, to be used after every kermit command. (2) Restore
4479 * the tty to the state it was in before kermit opened it. These choices
4480 * conflict, since ttold can't hold both choices of tty parameters. ttres()
4481 * is currently being called as in choice (1), but ttold basically holds
4482 * the initial parameters, as in (2), and the description at the beginning
4483 * of this file says (2).
4485 * I don't think restoring tty parameters after all kermit commands makes
4486 * much of a difference. Restoring them upon exit from kermit may be of
4487 * some use in some cases (when the line is not restored automatically on
4488 * close, by the operating system).
4490 * I can't choose which one it should be, so I haven't changed it. It
4491 * probably works as it is, too. It would probably even work even with
4492 * ttres() entirely deleted...
4494 * (from fdc: Actually, this function operates in remote mode too, so
4495 * it restores the console (command) terminal to whatever mode it was
4496 * in before packet operations began, so that commands work right again.)
4499 ttres() { /* Restore the tty to normal. */
4502 if (ttyfd < 0) return(-1); /* Not open. */
4504 if (ttfdflg) return(0); /* Don't mess with terminal modes if */
4505 /* we got ttyfd from another process */
4507 if (netconn) { /* Network connection */
4512 extern int tcp_nodelay; /* Just put this back if necessary */
4513 if (ttnet == NET_TCPB) {
4514 if (nodelay_sav > -1) {
4515 no_delay(ttyfd,nodelay_sav);
4520 #endif /* TCP_NODELAY */
4522 if (istncomport()) {
4524 if ((rc = tnsetflow(ttflow)) < 0)
4527 ttspeed = tnc_get_baud();
4528 else if ((rc = tnc_set_baud(ttspeed)) < 0)
4530 tnc_set_datasize(8);
4531 tnc_set_stopsize(stopbits);
4536 case 'e': /* Even */
4537 debug(F100,"ttres 8 bits + even parity","",0);
4541 debug(F100,"ttres 8 bits + odd parity","",0);
4544 case 'm': /* Mark */
4545 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
4548 case 's': /* Space */
4549 debug(F100,"ttres 8 bits + invalid parity: space","",0);
4554 #endif /* HWPARITY */
4556 tnc_set_parity(1); /* None */
4561 #endif /* TN_COMPORT */
4562 #endif /* TCPSOCKET */
4565 #endif /* NETCONN */
4567 if (ttpipe) return(0);
4570 if (ttpty) return(0);
4573 /* Real terminal device, so restore its original modes */
4575 #ifdef BSD44ORPOSIX /* For POSIX like this */
4576 debug(F100,"ttres BSD44ORPOSIX","",0);
4577 x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
4578 #else /* For all others... */
4579 #ifdef ATTSV /* For AT&T versions... */
4580 debug(F100,"ttres ATTSV","",0);
4581 x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */
4583 /* Here we restore the modes for BSD */
4585 #ifdef LPASS8 /* Undo "pass8" if it were done */
4587 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4588 debug(F100,"ttres TIOCLSET failed","",0);
4590 debug(F100,"ttres TIOCLSET ok","",0);
4594 #ifdef CK_DTRCTS /* Undo hardware flow if it were done */
4596 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4597 debug(F100,"ttres TIOCLSET failed","",0);
4599 debug(F100,"ttres TIOCLSET ok","",0);
4601 #endif /* CK_DTRCTS */
4603 #ifdef TIOCGETC /* Put back special characters */
4604 if (tcharf && (xlocal == 0)) {
4605 if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
4606 debug(F100,"ttres TIOCSETC failed","",0);
4608 debug(F100,"ttres TIOCSETC ok","",0);
4610 #endif /* TIOCGETC */
4612 #ifdef TIOCGLTC /* Put back local special characters */
4613 if (ltcharf && (xlocal == 0)) {
4614 if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
4615 debug(F100,"ttres TIOCSLTC failed","",0);
4617 debug(F100,"ttres TIOCSLTC ok","",0);
4619 #endif /* TIOCGLTC */
4622 debug(F100,"ttres BELLV10","",0);
4623 x = ioctl(ttyfd,TIOCSETP,&ttold); /* Restore both structs */
4624 x = ioctl(ttyfd,TIOCSDEV,&tdold);
4626 debug(F100,"ttres stty","",0);
4627 x = stty(ttyfd,&ttold); /* Restore tty modes the old way. */
4628 #endif /* BELLV10 */
4631 msleep(100); /* This replaces sleep(1)... */
4632 /* Put back sleep(1) if tty is */
4633 /* messed up after close. */
4635 #endif /* BSD44ORPOSIX */
4637 debug(F101,"ttres result","",x);
4639 if (x < 0) debug(F101,"ttres errno","",errno);
4644 x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
4645 debug(F101,"ttres AIX line discipline rts restore","",x);
4650 if (ttld > -1) { /* Put back line discipline */
4651 x = ioctl(ttyfd, TIOCSETD, &ttld);
4652 debug(F101,"ttres BSD41 line discipline restore","",x);
4653 if (x < 0) debug(F101,"...ioctl errno","",errno);
4659 x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */
4660 if (x != -1) { /* Make sure we know original modes. */
4661 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
4662 perror("ttres can't set Kanji mode");
4663 debug(F101,"ttres error setting Kanji mode","",x);
4667 debug(F100,"ttres set Kanji mode ok","",0);
4668 #endif /* sony_news */
4670 tvtflg = 0; /* Invalidate terminal mode settings */
4671 debug(F101,"ttres return code","",x);
4677 /* T T C H K P I D -- Check lockfile pid */
4679 Read pid from lockfile named f, check that it's still valid.
4681 On failure to read pid, return 1.
4682 Otherwise, try to delete lockfile f and return 0 if successful, else 1.
4685 ttchkpid(f) char *f; {
4687 pid = ttrpid(f); /* Read pid from file. */
4688 if (pid > -1) { /* If we were able to read the pid.. */
4689 debug(F101,"ttchkpid lock pid","",pid);
4690 errno = 0; /* See if process still exists. */
4691 mypid = (int)getpid(); /* Get my own pid. */
4692 debug(F101,"ttchkpid my pid","",mypid);
4693 if (pid == mypid) { /* It's me! */
4694 x = -1; /* So I can delete it */
4695 errno = ESRCH; /* pretend it's invalid */
4696 } else { /* It's not me */
4697 x = kill((PID_T)pid, 0); /* See if it's a live process */
4698 debug(F101,"ttchkpid kill errno","",errno);
4700 debug(F101,"ttchkpid pid test","",x);
4701 if (x < 0 && errno == ESRCH) { /* pid is invalid */
4702 debug(F111,"removing stale lock",f,pid);
4704 printf("Removing stale lock %s (pid %d terminated)\n", f, pid);
4706 x = unlink(f); /* Remove the lockfile. */
4708 debug(F111,"ttchkpid unlink",f,x);
4710 return(0); /* Device is not locked after all */
4716 return(1); /* Failure to read pid */
4721 /* Aliases (different drivers) for HP-UX dialout devices: */
4723 static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "cuad", "culd", "" };
4724 static int ttydexists = 0;
4728 /* T T R P I D -- Read pid from lockfile "name" */
4731 ttrpid(name) char *name; {
4737 debug(F110,"ttrpid",name,0);
4738 if (!name) return(-1);
4739 if (!*name) return(-1);
4741 len = zchki(name); /* Get file length */
4743 debug(F101,"ttrpid zchki","",len);
4749 fd = open(name,O_RDONLY); /* Try to open lockfile. */
4751 debug(F101,"ttrpid fd","",fd);
4755 Here we try to be flexible and allow for all different binary and string
4756 formats at runtime, rather than a specific format for each configuration
4757 hardwired at compile time.
4762 COHERENT uses a string PID but without leading spaces or 0's, so there is
4763 no way to tell from the file's length whether it contains a string or binary
4764 pid. So for COHERENT only, we only allow string pids. For all others, we
4765 decide based on the size of the lockfile.
4767 if (len > 4) { /* If file > 4 bytes it's a string */
4768 #endif /* COHERENT */
4769 x = read(fd,buf,(int)len);
4770 debug(F111,"ttrpid string read",buf,x);
4775 x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */
4778 } else if (len == 4) { /* 4 bytes so binary */
4779 x = read(fd, (char *)&pid, 4); /* Read the bytes into an int */
4780 debug(F101,"ttrpid integer read","",x);
4783 } else if (len == 2) { /* 2 bytes binary */
4784 x = read(fd, (char *)&spid, 2); /* Read the bytes into a short */
4785 debug(F101,"ttrpid short read","",x);
4792 #endif /* COHERENT */
4793 close(fd); /* Close the lockfile */
4794 debug(F101,"ttrpid pid","",pid);
4802 This function attempts to coordinate use of the communication device with
4803 other copies of Kermit and any other program that follows the UUCP
4804 device-locking conventions, which, unfortunately, vary among different UNIX
4805 implementations. The idea is to look for a file of a certain name, the
4806 "lockfile", in a certain directory. If such a file is found, then the line
4807 is presumed to be in use, and Kermit should not use it. If no such file is
4808 found, Kermit attempts to create one so that other programs will not use the
4809 same line at the same time. Because the lockfile and/or the directory it's
4810 in might lack write permission for the person running Kermit, Kermit could
4811 find itself running setuid to uucp or other user that does have the
4812 necessary permissions. At startup, Kermit has changed its effective uid to
4813 the user's real uid, and so ttlock() must switch back to the original
4814 effective uid in order to create the lockfile, and then back again to the
4815 real uid to prevent unauthorized access to other directories or files owned
4816 by the user the program is setuid to.
4818 Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
4819 based on suggestions from Warren Tucker. Call with pointer to name of
4820 tty device. Returns:
4825 Note: Once privileges are turned on using priv_on(), it is essential that
4826 they are turned off again before this function returns.
4828 #ifdef SVR4 /* Lockfile uses device numbers. */
4830 Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
4831 it is the behavior of the "reference version" of SVR4, i.e. the Intel
4832 port from UNIX Systems Laboratories, then called Univel UnixWare,
4833 then called Novell UnixWare, then called SCO Unixware, then called Caldera
4834 Open UNIX... It also makes much more sense than device-name-based lockfiles
4835 since there can be multiple names for the same device, symlinks, etc.
4838 #ifndef LFDEVNO /* Define this for SVR4 */
4839 #ifndef AIXRS /* But not for RS/6000 AIX 3.2, etc. */
4840 #ifndef BSD44 /* If anybody else needs it... */
4844 #ifndef IRIX51 /* SGI IRIX 5.1 or later */
4845 #ifndef CK_SCOV5 /* SCO Open Server 5.0 */
4847 #endif /* CK_SCOV5 */
4850 #endif /* __FreeBSD__ */
4851 #endif /* __386BSD__ */
4854 #endif /* LFDEVNO */ /* ... define it here or on CC */
4855 #endif /* NOLFDEVNO */
4856 #endif /* SVR4 */ /* command line. */
4860 #endif /* COHERENT */
4863 For platforms where the lockfile name is made from device/major/minor
4864 device number, as in SVR4. Which, if we must have lockfiles at all, is
4865 by far the best format, since it eliminates all the confusion that stems
4866 from multiple names (or drivers) for the same port, not to mention
4867 symlinks. It might even be a good idea to start using this form even
4868 on platforms where it's not supported, alongside the normal forms for those
4869 platforms, in order to get people used to it...
4872 #ifndef major /* If we didn't find it */
4873 #ifdef SVR4 /* then for Sys V R4 */
4874 #include <sys/mkdev.h> /* look here */
4875 #else /* or for SunOS versions */
4876 #ifdef SUNOS4 /* ... */
4877 #include <sys/sysmacros.h> /* look here */
4878 #else /* Otherwise take a chance: */
4879 #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
4880 #define minor(dev) ( (int) ( (dev) & 0xff))
4884 #endif /* LFDEVNO */
4886 /* No advisory locks if F_TLOCK and F_ULOCK are not defined at this point */
4893 #endif /* NOLOCKF */
4894 #endif /* F_TLOCK */
4902 #endif /* NOLOCKF */
4903 #endif /* F_ULOCK */
4906 static char linkto[DEVNAMLEN+1];
4907 static char * linkdev = NULL;
4912 char * uucplockdir = LOCK_DIR;
4914 char * uucplockdir = "";
4915 #endif /* LOCK_DIR */
4918 char * uucplockdir = LOCK_DIR;
4920 char * uucplockdir = "";
4921 #endif /* LOCK_DIR */
4922 #endif /* USETTYLOCK */
4924 char * uucplockdir = "";
4927 #ifdef QNX /* Only for QNX4 */
4928 int /* Visible to outside world */
4929 qnxopencount() { /* Get QNX device open count */
4930 struct _dev_info_entry info;
4933 x = -1; /* Unknown */
4935 if (!dev_info(ttyfd, &info)) {
4936 debug(F101,"ttlock QNX open_count","",info.open_count);
4937 x = info.open_count;
4945 ttglckdir() { /* Get Lockfile directory name */
4947 return("/var/spool/lock");
4948 #else /* __OpenBSD__ */
4950 return("/var/spool/lock");
4951 #else /* __FreeBSD__ */
4953 char * s = LOCK_DIR;
4954 #endif /* LOCK_DIR */
4960 #else /* LOCK_DIR */
4962 #endif /* LOCK_DIR */
4964 #endif /* __FreeBSD__ */
4965 #endif /* __OpenBSD__ */
4969 ttlock(ttdev) char *ttdev; {
4975 debug(F100,"ttlock NOUUCP","",0);
4976 ckstrncpy(flfnam,"NOLOCK",FLFNAML);
4982 haslock = 0; /* Not locked yet. */
4983 *flfnam = '\0'; /* Lockfile name is empty. */
4984 if (!strncmp(ttdev,"/dev/",5) && ttdev[5])
4985 ckstrncpy(lockname,ttdev+5,DEVNAMLEN);
4987 ckstrncpy(lockname,ttdev,DEVNAMLEN);
4989 This might be overkill, but it's not clear from the man pages whether
4990 ttylock() can be called without calling ttylocked() first, since the doc
4991 says that ttylocked() removes any stale lockfiles, but it does not say this
4992 about ttylock(). Also the docs don't say what ttylocked() returns in the
4993 case when it finds and removes a stale lockfile. So one or both calls to
4994 to ttylocked() might be superfluous, but they should do no harm. Also I'm
4995 assuming that we have to do all the same ID swapping, etc, with these
4996 routines as we do without them. Thus the priv_on/off() sandwich.
4999 priv_on(); /* Turn on privs */
5000 x = uu_lock(lockname); /* Try to set the lock */
5001 priv_off(); /* Turn privs off */
5002 debug(F111,"ttlock uu_lock",lockname,x);
5008 ckmakmsg(flfnam,FLFNAML,"/var/spool/lock/LCK..",lockname,NULL,NULL);
5015 #else /* USE_UU_LOCK */
5016 priv_on(); /* Turn on privs */
5017 if (ttylocked(lockname)) { /* This should remove any stale lock */
5018 if (ttylocked(lockname)) { /* so check again. */
5020 return(-5); /* Still locked, fail. */
5023 x = ttylock(lockname); /* Lock it. */
5024 priv_off(); /* Turn off privs */
5026 debug(F111,"ttlock lockname",lockname,x);
5029 We don't really know the name of the lockfile, but
5030 this is what the man page says it is. In USETTYLOCK
5031 builds, it is used only for display by SHOW COMM.
5033 ckmakmsg(flfnam,FLFNAML,"/etc/locks/LCK..",lockname,NULL,NULL);
5037 #endif /* USE_UU_LOCK */
5038 #else /* Systems that don't have ttylock()... */
5042 int lockfd; /* File descriptor for lock file. */
5043 PID_T pid; /* Process id of this process. */
5044 int tries; /* How many times we've tried... */
5045 struct stat devbuf; /* For device numbers (SVR4). */
5048 char pid_str[32]; /* My pid in string format. */
5049 #endif /* PIDSTRING */
5051 char *device, *devname;
5053 #define LFNAML 256 /* Max length for lock file name. */
5054 char lockfil[LFNAML]; /* Lock file name */
5056 char lklockf[LFNAML]; /* Name for link to lock file */
5059 char symlock[LFNAML]; /* Name for symlink lockfile name */
5060 #endif /* CKSYMLINK */
5061 char tmpnam[LFNAML+30]; /* Temporary lockfile name. */
5062 char *lockdir = LOCK_DIR; /* Defined near top of this file, */
5063 /* or on cc command line. */
5064 haslock = 0; /* Not locked yet. */
5065 *flfnam = '\0'; /* Lockfile name is empty. */
5066 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5067 pid = getpid(); /* Get id of this process. */
5069 /* Construct name of lockfile and temporary file */
5071 /* device = name of tty device without the path, e.g. "ttyh8" */
5072 /* lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
5074 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5076 if (stat(ttdev,&devbuf) < 0)
5080 islink = 1; /* Assume it's a symlink */
5081 linkto[0] = '\0'; /* But we don't know to what */
5084 This is undependable. If it worked it would save the readlink call if
5085 we knew the device name was not a link.
5088 islink = S_ISLNK(devbuf.st_mode);
5089 debug(F101,"ttlock stat S_ISLNK","",islink);
5090 #endif /* S_ISLNK */
5091 #endif /* COMMENT */
5093 n = readlink(ttdev,linkto,DEVNAMLEN); /* See if it's a link */
5094 debug(F111,"ttlock readlink",ttdev,n);
5095 if (n > -1) /* It is */
5099 debug(F111,"ttlock link",linkto,islink);
5102 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5103 debug(F110,"ttlock linkdev",linkdev,0);
5105 #endif /* CKSYMLINK */
5108 On SCO platforms, if we don't have a symlink, then let's pretend the
5109 name given for the device is a symlink, because later we will change
5110 the name if it contains any uppercase characters.
5112 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5115 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5116 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5117 debug(F110,"ttlock linkdev",linkdev,0);
5120 #ifdef M_XENIX /* SCO Xenix or UNIX */
5123 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5124 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5125 debug(F110,"ttlock linkdev",linkdev,0);
5127 #endif /* M_XENIX */
5128 #endif /* CK_SCOV5 */
5130 #ifdef ISIII /* Interactive System III, PC/IX */
5131 ckstrncpy(lockfil, device, DEVNAMLEN);
5132 #else /* not ISIII */
5133 #ifdef LFDEVNO /* Lockfilename has device numbers. */
5135 sprintf(lockfil,"LCK..%d.%d", /* SAFE */
5136 major(devbuf.st_rdev), /* major device number */
5137 0x1f & minor(devbuf.st_rdev)); /* minor device number */
5139 /* Note: %d changed to %u in 8.0 -- %u is part of SVID for SVR4 */
5140 /* Lockfile name format verified to agree with Solaris cu, Dec 2001 */
5141 sprintf(lockfil,"LK.%03u.%03u.%03u", /* SAFE */
5142 major(devbuf.st_dev), /* device */
5143 major(devbuf.st_rdev), /* major device number */
5144 minor(devbuf.st_rdev)); /* minor device number */
5145 #endif /* COHERENT */
5146 #else /* Not LFDEVNO */
5147 #ifdef PTX /* Dynix PTX */
5148 if ((device != &ttdev[5]) && (strncmp(ttdev,"/dev/",5) == 0)) {
5149 if ((int)strlen(device) + 8 < LFNAML)
5150 sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
5152 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5155 if ((int)strlen(device) + 5 < LFNAML)
5156 sprintf(lockfil,"LCK..%s", device);
5158 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5160 ckstrncpy(lklockf,device,DEVNAMLEN);
5165 ckmakmsg(symlock,LFNAML, "LCK..", linkdev, NULL, NULL);
5166 #endif /* CKSYMLINK */
5167 #endif /* LFDEVNO */
5170 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5172 /* Lowercase the entire filename. */
5173 /* SCO says we must do this in V5.0 and later. */
5174 /* BUT... watch out for devices -- like Digiboard Portserver */
5175 /* That can have hundreds of ports... */
5176 char *p = (char *)(lockfil + 5);
5177 while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
5180 if (islink) { /* If no change */
5181 if (!strcmp(lockfil,symlock)) { /* then no second lockfile needed */
5186 #endif /* CKSYMLINK */
5188 #ifdef M_XENIX /* SCO Xenix or UNIX */
5191 x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */
5192 if (x > 0) { /* If it's uppercase, lower it. */
5194 if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
5199 if (!strcmp(lockfil,symlock)) { /* No change */
5200 islink = 0; /* so no second lockfile */
5204 #endif /* CKSYMLINK */
5205 #endif /* M_XENIX */
5206 #endif /* CK_SCOV5 */
5208 /* flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
5209 /* tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
5211 ckmakmsg(flfnam,LFNAML,lockdir,"/",lockfil,NULL);
5214 ckmakmsg(lkflfn,FLFNAML,lockdir,"/",lklockf,NULL);
5219 /* If it's a link then also make a lockfile for the real name */
5220 debug(F111,"ttlock link symlock",symlock,islink);
5221 if (islink && symlock[0]) {
5222 /* But only if the lockfile names would be different. */
5223 /* WARNING: They won't be, e.g. for /dev/ttyd2 => /hw/ttys/ttyd2 */
5224 ckmakmsg(lock2,FLFNAML,lockdir,"/",symlock,NULL);
5225 debug(F110,"ttlock lock2",lock2,0);
5226 if (!strcmp(lock2,flfnam)) { /* Are lockfile names the same? */
5227 debug(F100,"ttlock lock2 cleared","",0);
5228 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5231 #endif /* CKSYMLINK */
5232 #endif /* LFDEVNO */
5234 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* safe */
5235 debug(F110,"ttlock flfnam",flfnam,0);
5236 debug(F110,"ttlock tmpnam",tmpnam,0);
5238 priv_on(); /* Turn on privileges if possible. */
5239 lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */
5240 if (lockfd < 0) { /* Create failed. */
5241 debug(F111,"ttlock creat failed",tmpnam,errno);
5242 if (errno == ENOENT) {
5244 printf("UUCP not installed or Kermit misconfigured\n");
5248 unlink(tmpnam); /* Get rid of the temporary file. */
5250 priv_off(); /* Turn off privileges!!! */
5251 return(-1); /* Return failure code. */
5253 /* Now write the pid into the temp lockfile in the appropriate format */
5255 #ifdef PIDSTRING /* For Honey DanBer UUCP, */
5256 sprintf( /* write PID as decimal string */
5258 #ifdef LINUXFSSTND /* The "Linux File System Standard" */
5259 #ifdef FSSTND10 /* Version 1.0 calls for */
5260 "%010d\n", /* leading zeros */
5261 #else /* while version 1.2 calls for */
5262 "%10d\n", /* leading spaces */
5263 #endif /* FSSTND10 */
5266 "%d\n", /* with leading nothing */
5268 "%10d\n", /* with leading blanks */
5269 #endif /* COHERENT */
5270 #endif /* LINUXFSSTND */
5273 write(lockfd, pid_str, 11);
5274 debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
5276 #else /* Not PIDSTRING, use integer PID */
5278 write(lockfd, (char *)&pid, sizeof(pid) );
5279 debug(F101,"ttlock pid","",(int) pid);
5281 #endif /* PIDSTRING */
5283 /* Now try to rename the temp file to the real lock file name. */
5284 /* This will fail if a lock file of that name already exists. */
5286 close(lockfd); /* Close the temp lockfile. */
5287 chmod(tmpnam,0444); /* Permission for a valid lock. */
5289 while (!haslock && tries++ < 2) {
5290 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5291 if (haslock) { /* If we got the lockfile */
5293 link(flfnam,lkflfn);
5297 if (islink && lock2[0])
5299 #endif /* LFDEVNO */
5300 #endif /* CKSYMLINK */
5303 /* Can't do this any more because device is not open yet so no ttyfd. */
5306 Advisory file locking works on SVR4, so we use it. In fact, it is
5307 necessary in some cases, e.g. when SLIP is involved. But it still doesn't
5308 seem to prevent multiple users accessing the same device by different names.
5310 while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
5311 debug(F111, "ttlock lockf returns errno", "", errno);
5312 if ((++tries >= 3) || (errno != EAGAIN)) {
5313 x = unlink(flfnam); /* remove the lockfile */
5315 unlink(lkflfn); /* And any links to it... */
5319 if (islink && lock2[0])
5320 unlink(lock2); /* ditto... */
5321 #endif /* LFDEVNO */
5322 #endif /* CKSYMLINK */
5323 debug(F111,"ttlock unlink",flfnam,x);
5329 if (haslock) /* If we got an advisory lock */
5331 #endif /* COMMENT */
5332 break; /* We're done. */
5334 } else { /* We didn't create a new lockfile. */
5336 if (ttchkpid(flfnam)) { /* Check existing lockfile */
5337 priv_on(); /* cause ttchkpid turns priv_off... */
5338 unlink(tmpnam); /* Delete the tempfile */
5339 debug(F100,"ttlock found tty locked","",0);
5340 priv_off(); /* Turn off privs */
5341 return(-2); /* Code for device is in use. */
5346 unlink(tmpnam); /* Unlink (remove) the temp file. */
5347 priv_off(); /* Turn off privs */
5348 return(haslock ? 0 : -1); /* Return link's return code. */
5353 HP-UX gets its own copy of this routine, modeled after the observed behavior
5354 of the HP-UX 'cu' program. HP-UX serial device names consist of a base name
5355 such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
5356 designator which is a string of digits, possibly containing an imbedded
5357 letter "p". Examples (for base name "tty"):
5359 /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
5361 According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
5362 used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
5363 on other models. In HP-UX 10.00, "0p0" notation was adopted for all models.
5364 However, we make and enforce no such distinctions; either notation is
5365 accepted on any model or HP-UX version as a valid unit designator.
5367 If a valid unit is specified (as opposed to a designer name or symlink), we
5368 check for all aliases of the given unit according to the devprefix[] array.
5369 If no lockfiles are found for the given unit, we can have the device; we
5370 create a lockfile LCK..name in the lockfile directory appropriate for the
5371 HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
5372 9.xx and earlier). If it is a "cua" or "cul" device, a second lockfile is
5373 created with the "ttyd" prefix. This is exactly what cu does.
5375 If the "set line" device does not have a valid unit designator, then it is
5376 used literally and no synomyms are searched for and only one lockfile is
5381 #define LFNAML 80 /* Max length for lock file name. */
5383 int lockfd; /* File descriptor for lock file. */
5384 PID_T pid; /* Process ID of this process. */
5385 int fpid; /* pid found in existing lockfile. */
5386 int tries; /* How many times we've tried... */
5387 int i, k; /* Workers */
5389 char *device, *devname; /* "/dev/xxx", "xxx" */
5390 char *unit, *p; /* <instance>p<port> part of xxx */
5392 char lockfil[LFNAML]; /* Lockfile name (no path) */
5393 char tmpnam[LFNAML]; /* Temporary lockfile name. */
5395 #ifdef HPUX10 /* Lockfile directory */
5396 char *lockdir = "/var/spool/locks"; /* Always this for 10.00 and higher */
5397 #else /* HP-UX 9.xx and below */
5399 char *lockdir = LOCK_DIR; /* Defined near top of this file */
5401 char *lockdir = "/usr/spool/uucp"; /* or not... */
5402 #endif /* LOCK_DIR */
5405 haslock = 0; /* Not locked yet. */
5406 *flfnam = '\0'; /* Lockfile name is empty. */
5407 lock2[0] = '\0'; /* Second one too. */
5408 pid = getpid(); /* Get my process ID */
5410 Construct name of lockfile and temporary file...
5411 device = name of tty device without the path, e.g. "tty0p0"
5412 lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
5414 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5415 debug(F110,"TTLOCK device",device,0);
5416 ckmakmsg(lockfil,LFNAML,"LCK..",device,NULL,NULL);
5418 k = 0; /* Assume device is not locked */
5419 n = 0; /* Digit counter */
5420 unit = device; /* Unit = <instance>p<port> */
5421 while (*unit && !isdigit(*unit)) /* Search for digit... */
5423 p = unit; /* Verify <num>p<num> format... */
5424 debug(F110,"TTLOCK unit 1",unit,0);
5426 The unit number is recognized as:
5427 (a) any sequence of digits that runs to the end of the string.
5428 (b) any (a) that includes one and only one letter "p", with at least
5429 one digit before and after it.
5431 while (isdigit(*p)) p++, n++; /* Get a run of digits */
5432 if (*p && n > 0) { /* Have a "p"? */
5433 if (*p == 'p' && isdigit(*(p+1))) {
5436 while (isdigit(*p)) p++, n++;
5439 if (n == 0 || *p) unit = "";
5440 debug(F110,"TTLOCK unit 2",unit,0);
5442 if (*unit) { /* Device name has unit number. */
5443 /* The following loop not only searches for the various lockfile */
5444 /* synonyms, but also removes all -- not just one -- stale lockfile */
5445 /* for the device, should there be more than one. See ttchkpid(). */
5447 for (i = 0; *devprefix[i]; i++) { /* For each driver... */
5448 /* Make device name */
5449 ckmakmsg(lock2,FLFNAML,"/dev/",devprefix[i],unit,NULL);
5450 priv_on(); /* Privs on */
5451 k = zchki(lock2) != -1; /* See if device exists */
5452 priv_off(); /* Privs off */
5453 debug(F111,"TTLOCK exist",lock2,k);
5455 if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
5457 /* Make lockfile name */
5458 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",devprefix[i],unit);
5459 debug(F110,"TTLOCK checking",lock2,0);
5460 priv_on(); /* Privs on */
5461 k = zchki(lock2) != -1; /* See if lockfile exists */
5462 priv_off(); /* Privs off */
5463 debug(F111,"TTLOCK check for lock A",lock2,k);
5464 if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
5465 ckstrncpy(flfnam,lock2,FLFNAML);
5470 } else { /* Some other device-name format */
5471 /* This takes care of symbolic links, etc... */
5472 /* But does not chase them down! */
5473 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",device,NULL);
5475 k = zchki(lock2) != -1; /* Check for existing lockfile */
5477 debug(F111,"TTLOCK check for lock B",lock2,k);
5478 if (k) if (ttchkpid(lock2)) { /* Check pid from lockfile */
5479 ckstrncpy(flfnam,lock2,FLFNAML);
5480 debug(F110,"TTLOCK in use",device,0);
5481 debug(F101,"TTLOCK returns","",-2);
5486 Get here only if there is no (more) lockfile, so now we make one (or two)...
5487 flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
5488 tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
5490 ckmakmsg(flfnam,FLFNAML,lockdir,"/",lockfil,NULL); /* SET LINE device */
5492 /* If dialout device, also make one for corresponding dialin device */
5494 if (!strncmp(device,"cu",2) && *unit && ttydexists)
5495 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..ttyd",unit,NULL);
5497 if ((int)strlen(lockdir)+12 < LFNAML)
5498 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temp name */
5501 debug(F110,"TTLOCK flfnam",flfnam,0);
5502 debug(F110,"TTLOCK lock2",lock2,0);
5503 debug(F110,"TTLOCK tmpnam",tmpnam,0);
5507 Lockfile permissions...
5508 444 is standard, HP-UX 10.00 uses 664. It doesn't matter.
5509 Kermit uses 444; the difference lets us tell whether Kermit created
5512 priv_on(); /* Turn on privileges. */
5513 lockfd = creat(tmpnam, 0444); /* Try to create temporary file. */
5514 if (lockfd < 0) { /* Create failed. */
5515 debug(F111,"TTLOCK creat failed",tmpnam,errno);
5516 if (errno == ENOENT) {
5518 printf("UUCP not installed or Kermit misconfigured\n");
5522 unlink(tmpnam); /* Get rid of the temporary file. */
5524 priv_off(); /* Turn off privileges!!! */
5525 debug(F101,"TTLOCK returns","",-1);
5526 return(-1); /* Return failure code. */
5528 debug(F110,"TTLOCK temp ok",tmpnam,0);
5530 /* Now write our pid into the temp lockfile in integer format. */
5532 i = write(lockfd, (char *)&pid, sizeof(pid));
5536 debug(F101,"TTLOCK pid","",pid);
5537 debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
5538 debug(F101,"TTLOCK write pid returns","",i);
5543 Now try to rename the temporary file to the real lockfile name.
5544 This will fail if a lock file of that name already exists, which
5545 will catch race conditions with other users.
5547 close(lockfd); /* Close the temp lockfile. */
5551 while (!haslock && tries++ < 2) {
5552 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5553 debug(F101,"TTLOCK link","",haslock);
5554 if (haslock) { /* If we made the lockfile... */
5557 /* We can't do this any more because we don't have a file descriptor yet. */
5558 #ifdef LOCKF /* Can be canceled with -DNOLOCKF */
5560 Create an advisory lock on the device through its file descriptor.
5561 This code actually seems to work. If it is executed, and then another
5562 process tries to open the same device under a different name to circumvent
5563 the lockfile, they get a "device busy" error.
5565 debug(F100,"TTLOCK LOCKF code...","",0);
5566 while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
5567 debug(F111, "TTLOCK lockf error", "", errno);
5568 if ((++tries >= 3) || (errno != EAGAIN)) {
5569 x = unlink(flfnam); /* Remove the lockfile */
5570 if (errno == EACCES && !quiet)
5571 printf("Device already locked by another process\n");
5578 #endif /* COMMENT */
5580 if (haslock) { /* If we made the lockfile ... */
5581 if (lock2[0]) { /* if there is to be a 2nd lockfile */
5582 lockfd = creat(lock2, 0444); /* Create it */
5583 debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
5584 if (lockfd > -1) { /* Created OK, write pid. */
5585 write(lockfd, (char *)&pid, sizeof(pid) );
5586 close(lockfd); /* Close and */
5587 chmod(lock2, 0444); /* set permissions. */
5588 } else { /* Not OK, but don't fail. */
5589 lock2[0] = '\0'; /* Just remember it's not there. */
5592 break; /* and we're done. */
5596 unlink(tmpnam); /* Unlink (remove) the temp file. */
5597 priv_off(); /* Turn off privs */
5598 i = haslock ? 0 : -1; /* Our return value */
5599 debug(F101,"TTLOCK returns","",i);
5602 #endif /* USETTYLOCK */
5603 #endif /* !NOUUCP */
5606 /* T T U N L O C K */
5609 ttunlck() { /* Remove UUCP lockfile(s). */
5613 debug(F111,"ttunlck",flfnam,haslock);
5617 if (haslock && *flfnam) {
5619 priv_on(); /* Turn on privs */
5621 x = uu_unlock(lockname);
5622 #else /* USE_UU_LOCK */
5623 x = ttyunlock(lockname); /* Try to unlock */
5624 #endif /* USE_UU_LOCK */
5625 priv_off(); /* Turn off privs */
5626 if (x < 0 && !quiet)
5627 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5629 *flfnam = '\0'; /* Erase the name. */
5634 #else /* No ttylock()... */
5636 if (haslock && *flfnam) {
5637 /* Don't remove lockfile if we didn't make it ourselves */
5638 if ((x = ttrpid(flfnam)) != (int)getpid()) {
5639 debug(F111,"ttunlck lockfile seized",flfnam,x);
5640 printf("Warning - Lockfile %s seized by pid %d\n",
5646 priv_on(); /* Turn privileges on. */
5648 x = unlink(flfnam); /* Remove the lockfile. */
5649 debug(F111,"ttunlck unlink",flfnam,x);
5651 if (errno && !quiet)
5653 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5656 *flfnam = '\0'; /* Erase the name. */
5660 x = unlink(lkflfn); /* Remove link to lockfile */
5661 debug(F111,"ttunlck AIX link unlink",lkflfn,x);
5663 if (errno && !quiet)
5665 printf("Warning - Can't remove link to lockfile: %s\n", lkflfn);
5669 if (lock2[0]) { /* If there is a second lockfile, */
5671 x = unlink(lock2); /* remove it too. */
5672 debug(F111,"ttunlck lock2 unlink",lock2,x);
5674 if (errno && !quiet)
5676 printf("Warning - Can't remove secondary lockfile: %s\n",
5680 lock2[0] = '\0'; /* Forget its name. */
5686 (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
5688 #endif /* COMMENT */
5690 priv_off(); /* Turn privileges off. */
5692 #endif /* USETTYLOCK */
5693 #endif /* !NOUUCP */
5698 4.3BSD-style UUCP line direction control.
5699 (Stan Barber, Rice U, 1980-something...)
5704 acucntrl(flag,ttname) char *flag, *ttname; {
5705 char x[DEVNAMLEN+32], *device, *devname;
5707 if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
5708 return; /* just return. */
5709 device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
5710 if (strncmp(device,"LCK..",4) == 0) device += 5;
5711 ckmakmsg(x,DEVNAMLEN+32,"/usr/lib/uucp/acucntrl ",flag," ",device);
5712 debug(F110,"called ",x,0);
5715 #endif /* ACUCNTRL */
5719 T T H F L O W -- Set or Reset hardware flow control.
5721 This is an attempt to collect all hardware-flow-control related code
5722 into a single module. Thanks to Rick Sladkey and John Kohl for lots of
5723 help here. Overview:
5725 Hardware flow control is not supported in many UNIX implementions. Even
5726 when it is supported, there is no (ha ha) "standard" for the programming
5727 interface. In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
5728 SunOS, AIX, etc, have totally different methods. (And, not strictly
5729 relevant here, the programming interface often brings one only to a no-op
5730 in the device driver!)
5732 Among all these, we have two major types of APIs: those in which hardware
5733 flow control is determined by bits in the same termio/termios/sgtty mode
5734 word(s) that are used for controlling such items as CBREAK vs RAW mode, and
5735 which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
5736 for changing terminal modes. And those that use entirely different
5739 In the first category, it is important that any change in the mode bits be
5740 reflected in the relevant termio(s)/sgtty structure, so that subsequent
5741 changes to that structure do not wipe out the effects of this routine. That
5742 is why a pointer, attrs, to the appropriate structure is passed as a
5743 parameter to this routine.
5745 The second category should give us no worries, since any changes to hardware
5746 flow control accomplished by this routine should not affect the termio(s)/
5747 sgtty structures, and therefore will not be undone by later changes to them.
5749 The second argument, status, means to turn on hardware flow control if
5750 nonzero, and to turn it off if zero.
5752 Returns: 0 on apparent success, -1 on probable failure.
5756 The following business is for BSDI, where it was discovered that two
5757 separate bits, CCTS_OFLOW and CRTS_IFLOW, are used in hardware flow control,
5758 but CTRSCTS is defined (in <termios.h>) to be just CCTS_OFLOW rather both
5759 bits, so hwfc only works in one direction if you use CRTSCTS to control it.
5760 Other 4.4BSD-based Unixes such as FreeBSD 4.1, which use these two bits,
5761 define CRTSCTS correctly.
5768 #define CRTSCTS (CRTS_IFLOW|CCTS_OFLOW)
5769 #endif /* CRTS_IFLOW */
5770 #endif /* CCTS_OFLOW */
5771 #endif /* CRTSCTS */
5772 #endif /* FIXCRTSCTS */
5775 tthflow(flow, status, attrs)
5776 int flow, /* Type of flow control (ckcdeb.h) */
5777 status; /* Nonzero = turn it on */
5778 /* Zero = turn it off */
5779 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
5780 struct termios *attrs;
5781 #else /* System V */
5785 /* AT&T UNIX 3.51m can set but not test for hardware flow control */
5786 #define RTSFLOW CTSCD
5787 #define CTSFLOW CTSCD
5788 #endif /* ATT7300 */
5789 #endif /* UNIX351M */
5790 struct termio *attrs;
5791 #else /* BSD, V7, etc */
5792 struct sgttyb *attrs; /* sgtty info... */
5794 #endif /* BSD44ORPOSIX */
5797 int x = 0; /* tthflow() return code */
5800 return p9tthflow(flow, status);
5803 #ifndef OXOS /* NOT Olivetti X/OS... */
5805 For SunOS 4.0 and later in the BSD environment ...
5807 The declarations are copied and interpreted from the System V header files,
5808 so we don't actually have to pull in all the System V junk when building
5809 C-Kermit for SunOS in the BSD environment, which would be dangerous because
5810 having those symbols defined would cause us to take the wrong paths through
5811 the code. The code in this section is used in both the BSD and Sys V SunOS
5816 In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
5817 because GNU CC uses different formats for the _IOxxx macros than regular CC;
5818 the POSIX forms work for both. But the POSIX calls are not available in
5821 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5822 #define TCSANOW 0 /* Do it now */
5825 unsigned long c_iflag; /* Input modes */
5826 unsigned long c_oflag; /* Output modes */
5827 unsigned long c_cflag; /* Control modes */
5828 unsigned long c_lflag; /* Line discipline modes */
5832 struct termios temp;
5834 _PROTOTYP( int tcgetattr, (int, struct termios *) );
5835 _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
5837 When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
5838 asserted. So we don't set CRTSCTS unless CD is up. This should be OK,
5839 since we don't need RTS/CTS during dialing, and after dialing is complete,
5840 we should have CD. If not, we still communicate, but without RTS/CTS.
5842 int mflags; /* Modem signal flags */
5845 if (ttpipe) return(0);
5848 if (ttpty) return(0);
5851 debug(F101,"tthflow SUNOS41 entry status","",status);
5852 if (!status) { /* Turn hard flow off */
5853 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5854 (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5855 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5856 x = tcsetattr(ttyfd,TCSANOW,&temp);
5858 } else { /* Turn hard flow on */
5859 if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
5860 (mflags & TIOCM_CAR)) { /* Check for CD */
5861 debug(F100,"tthflow SunOS has CD","",0);
5862 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5863 !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5864 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5865 x = tcsetattr(ttyfd,TCSANOW,&temp);
5869 debug(F100,"tthflow SunOS no CD","",0);
5874 struct termios temp;
5876 if (ttpipe) return(0);
5879 if (ttpty) return(0);
5881 debug(F101,"tthflow QNX entry status","",status);
5882 if (tcgetattr(ttyfd, &temp) > -1) { /* Get device attributes */
5883 if (!status) { /* Turn hard flow off */
5884 if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
5885 temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
5886 attrs->c_cflag &= ~(IHFLOW|OHFLOW);
5887 x = tcsetattr(ttyfd,TCSANOW,&temp);
5889 } else { /* Turn hard flow on */
5890 if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
5891 temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
5892 temp.c_iflag &= ~(IXON|IXOFF); /* Bye to IXON/IXOFF */
5893 ttraw.c_lflag |= IEXTEN; /* Must be on */
5894 x = tcsetattr(ttyfd,TCSANOW,&temp);
5895 attrs->c_cflag |= (IHFLOW|OHFLOW);
5896 attrs->c_iflag &= ~(IXON|IXOFF);
5901 debug(F100, "tthflow QNX getattr fails", "", 0);
5904 #ifdef POSIX_CRTSCTS
5906 POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
5907 Note: Do not assume CRTSCTS is a one-bit field!
5909 struct termios temp;
5911 if (ttpipe) return(0);
5914 if (ttpty) return(0);
5916 debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
5918 x = tcgetattr(ttyfd, &temp);
5919 debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
5924 if (!status) { /* Turn hard flow off */
5927 /* This can fail because of sign extension */
5928 /* e.g. in Linux where it's Bit 31 */
5929 (temp.c_cflag & CRTSCTS) == CRTSCTS
5931 (temp.c_cflag & CRTSCTS) != 0
5932 #endif /* COMMENT */
5934 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5935 attrs->c_cflag &= ~CRTSCTS;
5936 x = tcsetattr(ttyfd,TCSANOW,&temp);
5937 debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
5939 } else { /* John Dunlap 2010-01-26 */
5941 "tthflow before forcing off attrs CRTSCTS",
5943 attrs->c_cflag&CRTSCTS
5945 attrs->c_cflag &= ~CRTSCTS; /* force it off if !status */
5947 "tthflow after forcing off attrs CRTSCTS",
5949 attrs->c_cflag&CRTSCTS
5952 } else { /* Turn hard flow on */
5955 /* This can fail because of sign extension */
5956 (temp.c_cflag & CRTSCTS) != CRTSCTS
5958 (temp.c_cflag & CRTSCTS) == 0
5959 #endif /* COMMENT */
5961 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5962 temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
5963 x = tcsetattr(ttyfd,TCSANOW,&temp);
5964 debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
5966 attrs->c_cflag |= CRTSCTS;
5967 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
5974 SunOS 4.0 (and maybe earlier?). This code is dangerous because it
5975 prevents compilation with GNU gcc, which uses different formats for the
5976 _IORxxx macros than regular cc. SunOS 4.1 and later can use the POSIX
5977 routines above, which work for both cc and gcc.
5979 #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
5980 #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
5981 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5984 unsigned long c_iflag; /* Input modes */
5985 unsigned long c_oflag; /* Output modes */
5986 unsigned long c_cflag; /* Control modes */
5987 unsigned long c_lflag; /* Line discipline modes */
5991 struct termios temp;
5993 if (ttpipe) return(0);
5996 if (ttpty) return(0);
5998 debug(F101,"tthflow entry status","",status);
5999 if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
6000 if (status) { /* Turn hard flow on */
6001 temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */
6002 x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
6003 attrs->c_cflag |= CRTSCTS; /* Add to global info. */
6004 } else { /* Turn hard flow off */
6005 temp.c_cflag &= ~CRTSCTS;
6006 x = ioctl(ttyfd,TCSETS,&temp);
6007 attrs->c_cflag &= ~CRTSCTS;
6010 #else /* Not SunOS 4.0 or later */
6011 #ifdef AIXRS /* IBM AIX RS/6000 */
6012 #ifndef AIX41 /* But only pre-4.x == SVR4 */
6014 if (ttpipe) return(0);
6017 if (ttpty) return(0);
6020 if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
6021 debug(F100,"hardflow TXADDCD (rts) error", "", 0);
6023 if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
6024 debug(F100,"hardflow TXDELCD (rts) error", "", 0);
6027 #else /* Not AIX RS/6000 */
6029 #ifdef ATTSV /* System V... */
6031 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
6034 #ifdef M_UNIX /* SCO UNIX 3.2v4.x or earlier */
6037 #endif /* CK_SCOV5 */
6039 #ifdef SCO_FORCE_RTSXOFF
6040 #ifdef CK_SCOUNIX /* But not SCO OpenServer 5.0.4 */
6041 #ifdef SCO_OSR504 /* or later... */
6043 #endif /* SCO_OSR504 */
6044 #endif /* CK_SCOUNIX */
6045 #endif /* SCO_FORCE_RTSXOFF */
6049 struct termios temp;
6051 if (ttpipe) return(0);
6054 if (ttpty) return(0);
6056 debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
6058 x = tcgetattr(ttyfd, &temp);
6059 debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
6063 if (ttpipe) return(0);
6066 if (ttpty) return(0);
6068 debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
6069 x = ioctl(ttyfd, TCGETA, &temp);
6070 debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
6073 This is not really POSIX, since POSIX does not deal with hardware flow
6074 control, but we are using the POSIX APIs. In fact, RTSFLOW and CTSFLOW
6075 are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif. So
6076 let's try forcing their definitions here.
6079 #define CTSFLOW 0020000
6080 debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
6082 debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
6083 #endif /* CTSFLOW */
6085 #define RTSFLOW 0040000
6086 debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
6088 debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
6089 #endif /* RTSFLOW */
6091 #define ORTSFL 0100000
6092 debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
6094 debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
6098 if (status) { /* Turn it ON */
6099 temp.c_cflag |= RTSFLOW|CTSFLOW;
6100 attrs->c_cflag |= RTSFLOW|CTSFLOW;
6102 temp.c_cflag &= ~ORTSFL;
6103 attrs->c_cflag &= ~ORTSFL;
6105 temp.c_iflag &= ~(IXON|IXOFF|IXANY);
6106 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
6107 } else { /* Turn it OFF */
6109 temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6110 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6112 temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
6113 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
6117 x = tcsetattr(ttyfd, TCSADRAIN, &temp);
6119 x = ioctl(ttyfd, TCSETA, &temp);
6121 debug(F101,"tthflow SCO set modes","",x);
6123 #else /* Not SCO UNIX */
6125 if (ttpipe) return(0);
6128 if (ttpty) return(0);
6130 if (!status) { /* Turn it OFF */
6132 debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
6133 rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
6135 x = ioctl(ttyfd,TCSETX,&rctsx);
6136 debug(F101,"tthflow ATTSV TCSETX OFF","",x);
6139 debug(F100,"tthflow TCSETX not defined","",0);
6142 debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
6143 #endif /* RTSXOFF */
6145 debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
6146 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6147 x = ioctl(ttyfd,TCSETX,&rctsx);
6148 debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
6150 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6151 #endif /* DTRXOFF */
6152 } else { /* Turn it ON. */
6153 if (flow == FLO_RTSC) { /* RTS/CTS Flow control... */
6154 debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
6156 /* This is the preferred way, according to SVID3 */
6158 x = ioctl(ttyfd,TCGETX,&rctsx);
6159 debug(F101,"tthflow TCGETX","",x);
6161 rctsx.x_hflag |= RTSXOFF | CTSXON;
6162 x = ioctl(ttyfd,TCSETX,&rctsx);
6163 debug(F100,"tthflow ATTSV ioctl","",x);
6166 debug(F100,"tthflow TCGETX not defined","",0);
6170 debug(F100,"tthflow RTSXOFF not defined","",0);
6172 #endif /* RTSXOFF */
6173 } else if (flow == FLO_DTRC) { /* DTR/CD Flow control... */
6174 debug(F100,"tthflow ATTSV DTR/CD ON","",0);
6176 /* This is straight out of SVID R4 */
6177 if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
6178 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6179 x = ioctl(ttyfd,TCSETX,&rctsx);
6182 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6184 #endif /* DTRXOFF */
6187 #endif /* CK_SCOUNIX */
6189 #else /* not System V... */
6195 if (ttpipe) return(0);
6198 if (ttpty) return(0);
6200 x = LDODTR | LDOCTS; /* Found only on UTEK? */
6201 if (flow == FLO_DTRT && status) { /* Use hardware flow control */
6203 x = ioctl(ttyfd,TIOCLBIS,&x);
6205 debug(F100,"hardflow TIOCLBIS error","",0);
6208 debug(F100,"hardflow TIOCLBIS ok","",0);
6213 x = ioctl(ttyfd,TIOCLBIC,&x);
6215 debug(F100,"hardflow TIOCLBIC error","",0);
6218 debug(F100,"hardflow TIOCLBIC ok","",0);
6224 #endif /* CK_DTRCTS */
6229 #endif /* POSIX_CRTSCTS */
6230 #endif /* SUNOS41 */
6234 struct termios temp; /* Olivetti X/OS ... */
6237 if (ttpipe) return(0);
6240 if (ttpty) return(0);
6242 x = ioctl(ttyfd,TCGETS,&temp);
6244 temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
6247 case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
6249 case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
6253 x = ioctl(ttyfd,TCSETS,&temp);
6261 /* T T P K T -- Condition the communication line for packets */
6262 /* or for modem dialing */
6265 If called with speed > -1, also set the speed.
6266 Returns 0 on success, -1 on failure.
6268 NOTE: the "xflow" parameter is supposed to be the currently selected
6269 type of flow control, but for historical reasons, this parameter is also
6270 used to indicate that we are dialing. Therefore, when the true flow
6271 control setting is needed, we access the external variable "flow", rather
6272 than trusting our "xflow" argument.
6276 ttpkt(long speed, int xflow, int parity)
6278 ttpkt(speed,xflow,parity) long speed; int xflow, parity;
6279 #endif /* CK_ANSIC */
6284 #endif /* NOLOCAL */
6286 extern int flow; /* REAL flow-control setting */
6288 if (ttyfd < 0) return(-1); /* Not open. */
6290 debug(F101,"ttpkt parity","",parity);
6291 debug(F101,"ttpkt xflow","",xflow);
6292 debug(F101,"ttpkt speed","",(int) speed);
6294 ttprty = parity; /* Let other tt functions see these. */
6295 ttspeed = speed; /* Make global copy for this module */
6296 ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
6298 needpchk = ttprty ? 0 : 1; /* Parity check needed? */
6301 #endif /* PARSENSE */
6303 debug(F101,"ttpkt ttpmsk","",ttpmsk);
6304 debug(F101,"ttpkt netconn","",netconn);
6306 #ifdef NETCONN /* No mode-changing for telnet */
6310 if (ttnet == NET_TCPB) { /* But turn off Nagle */
6311 extern int tcp_nodelay;
6312 nodelay_sav = tcp_nodelay;
6315 #endif /* TCP_NODELAY */
6317 if (istncomport()) {
6319 if (tvtflg == 0 && speed == ttspeed && flow == ttflow
6320 /* && ttcarr == curcarr */ ) {
6321 debug(F100,"ttpkt modes already set, skipping...","",0);
6322 return(0); /* Already been called. */
6324 if (flow != ttflow) {
6325 if ((rc = tnsetflow(flow)) < 0)
6329 if (speed != ttspeed) {
6331 speed = tnc_get_baud();
6332 else if ((rc = tnc_set_baud(speed)) < 0)
6336 tnc_set_datasize(8);
6337 tnc_set_stopsize(stopbits);
6342 case 'e': /* Even */
6343 debug(F100,"ttres 8 bits + even parity","",0);
6347 debug(F100,"ttres 8 bits + odd parity","",0);
6350 case 'm': /* Mark */
6351 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
6354 case 's': /* Space */
6355 debug(F100,"ttres 8 bits + invalid parity: space","",0);
6360 #endif /* HWPARITY */
6362 tnc_set_parity(1); /* None */
6367 #endif /* TN_COMPORT */
6368 #endif /* TCPSOCKET */
6372 #endif /* NETCONN */
6374 if (ttpipe) return(0);
6377 if (ttpty) return(0);
6381 if (ttfdflg && !isatty(ttyfd)) return(0);
6386 #endif /* COHERENT */
6388 #ifndef SVORPOSIX /* Berkeley, V7, etc. */
6391 For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
6392 after having previously set it to NONE without closing and reopening the
6393 device. Unless there's something I overlooked below...
6395 if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
6396 debug(F101,"ttpkt executing horrible flow kludge","",0);
6397 ttclos(0); /* Close it */
6399 ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
6402 #endif /* SVORPOSIX */
6404 #ifdef COHERENT /* This must be vestigial since we */
6405 #undef SVORPOSIX /* reverse it a few lines below... */
6406 #endif /* COHERENT */
6408 if (xflow != FLO_DIAL && xflow != FLO_DIAX)
6409 ttflow = xflow; /* Now make this available too. */
6413 s2 = (int) (speed / 10L); /* Convert bps to cps */
6414 debug(F101,"ttpkt calling ttsspd","",s2);
6415 s = ttsspd(s2); /* Check and set the speed */
6416 debug(F101,"ttpkt ttsspd result","",s);
6417 carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
6418 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
6419 tvtflg = 0; /* So ttvt() will work next time */
6421 #endif /* NOLOCAL */
6425 #endif /* COHERENT */
6427 #ifndef SVORPOSIX /* BSD section */
6428 if (flow == FLO_RTSC || /* Hardware flow control */
6431 tthflow(flow, 1, &ttraw);
6432 debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
6433 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6434 ttraw.sg_flags |= RAW; /* Enter raw mode */
6435 } else if (flow == FLO_NONE) { /* No flow control */
6436 debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
6437 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6438 tthflow(flow, 0, &ttraw); /* Turn off any hardware f/c too */
6439 ttraw.sg_flags |= RAW; /* Enter raw mode */
6440 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
6441 debug(F100,"ttpkt keeping original TANDEM","",0);
6442 ttraw.sg_flags &= ~TANDEM;
6443 ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
6444 /* NOTE: We should also handle hardware flow control here! */
6447 /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
6449 if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
6450 debug(F100,"ttpkt turning on TANDEM","",0);
6451 ttraw.sg_flags |= TANDEM; /* So ask for it. */
6453 #ifdef LPASS8 /* Can pass 8-bit data through? */
6454 /* If the LPASS8 local mode is available, then flow control can always */
6455 /* be used, even if parity is none and we are transferring 8-bit data. */
6456 /* But we only need to do all this if Xon/Xoff is requested. */
6457 /* BUT... this tends not to work through IP or LAT connections, terminal */
6458 /* servers, telnet, rlogin, etc, so it is currently disabled. */
6459 x = LPASS8; /* If LPASS8 defined, then */
6460 debug(F100,"ttpkt executing LPASS8 code","",0);
6461 if (lmodef) { /* TIOCLBIS must be too. */
6462 x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
6464 debug(F100,"ttpkt TIOCLBIS error","",0);
6467 debug(F100,"ttpkt TIOCLBIS ok","",0);
6471 But if we use LPASS8 mode, we must explicitly turn off
6472 terminal interrupts of all kinds.
6474 #ifdef TIOCGETC /* Not rawmode, */
6475 if (tcharf && (xlocal == 0)) { /* must turn off */
6476 tchnoi.t_intrc = -1; /* interrupt character */
6477 tchnoi.t_quitc = -1; /* and quit character. */
6478 tchnoi.t_startc = 17; /* Make sure xon */
6479 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6481 tchnoi.t_eofc = -1; /* eof character. */
6482 tchnoi.t_brkc = -1; /* brk character. */
6484 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6485 debug(F100,"ttpkt TIOCSETC failed","",0);
6488 debug(F100,"ttpkt TIOCSETC ok","",0);
6491 /* only for paranoid debugging */
6495 ioctl(0,TIOCGETC,&foo);
6497 "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
6498 foo.t_intrc, foo.t_quitc, foo.t_startc,
6499 foo.t_stopc, foo.t_eofc, foo.t_brkc);
6500 debug(F110,"ttpkt chars",tchbuf,0);
6502 #endif /* COMMENT */
6504 ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
6505 #endif /* TIOCGETC */
6507 /* Prevent suspend during packet mode */
6508 #ifdef TIOCGLTC /* Not rawmode, */
6509 if (ltcharf && (xlocal == 0)) { /* must turn off */
6510 ltchnoi.t_suspc = -1; /* suspend character */
6511 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6512 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6513 debug(F100,"ttpkt TIOCSLTC failed","",0);
6516 debug(F100,"ttpkt TIOCSLTC ok","",0);
6519 #endif /* TIOCGLTC */
6521 #else /* LPASS8 not defined */
6523 /* Previously, BSD-based implementations always */
6524 /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */
6525 /* This allows the flow control requested above to actually work, but only */
6526 /* if the user asks for parity (which also means they get 8th-bit quoting). */
6528 if (parity) { /* If parity, */
6529 ttraw.sg_flags &= ~RAW; /* use cooked mode */
6533 #endif /* COMMENT */
6534 ttraw.sg_flags |= CBREAK;
6535 debug(F101,"ttpkt cooked, cbreak, parity","",parity);
6536 #ifdef TIOCGETC /* Not rawmode, */
6537 if (tcharf && (xlocal == 0)) { /* must turn off */
6538 tchnoi.t_intrc = -1; /* interrupt character */
6539 tchnoi.t_quitc = -1; /* and quit character. */
6540 tchnoi.t_startc = 17; /* Make sure xon */
6541 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6543 tchnoi.t_eofc = -1; /* eof character. */
6544 tchnoi.t_brkc = -1; /* brk character. */
6546 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6547 debug(F100,"ttpkt TIOCSETC failed","",0);
6550 debug(F100,"ttpkt TIOCSETC ok","",0);
6553 #endif /* TIOCGETC */
6554 #ifdef TIOCGLTC /* Not rawmode, */
6555 /* Prevent suspend during packet mode */
6556 if (ltcharf && (xlocal == 0)) { /* must turn off */
6557 ltchnoi.t_suspc = -1; /* suspend character */
6558 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6559 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6560 debug(F100,"ttpkt TIOCSLTC failed","",0);
6563 debug(F100,"ttpkt TIOCSLTC ok","",0);
6566 #endif /* TIOCGLTC */
6567 } else { /* If no parity, */
6568 ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
6569 debug(F101,"ttpkt setting rawmode, parity","",parity);
6572 } /* End of Xon/Xoff section */
6574 /* Don't echo, don't map CR to CRLF on output, don't fool with case */
6576 ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
6578 ttraw.sg_flags &= ~(ECHO|CRMOD);
6582 ttraw.sg_flags &= ~ANYP; /* Must set this on old Towers */
6586 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
6590 if (stty(ttyfd,&ttraw) < 0) { /* Set the new modes. */
6591 debug(F101,"ttpkt stty failed","",errno);
6594 #endif /* BELLV10 */
6595 debug(F100,"ttpkt stty ok","",0);
6598 x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
6599 if (x != -1) { /* Make sure we know original modes. */
6602 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
6603 perror("ttpkt can't set ASCII mode");
6604 debug(F101,"ttpkt error setting ASCII mode","",x);
6608 debug(F100,"ttpkt set ASCII mode ok","",0);
6609 #endif /* sony_news */
6611 if (xlocal == 0) { /* Turn this off so we can read */
6612 signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
6615 tvtflg = 0; /* So ttvt() will work next time */
6616 debug(F100,"ttpkt success","",0);
6619 #endif /* Not ATTSV or POSIX */
6621 /* AT&T UNIX and POSIX */
6625 #endif /* COHERENT */
6628 if (flow == FLO_XONX) { /* Xon/Xoff */
6629 ttraw.c_iflag |= (IXON|IXOFF);
6630 tthflow(flow, 0, &ttraw);
6631 } else if (flow == FLO_NONE) { /* None */
6632 /* NOTE: We should also turn off hardware flow control here! */
6633 ttraw.c_iflag &= ~(IXON|IXOFF);
6634 tthflow(flow, 0, &ttraw);
6635 } else if (flow == FLO_KEEP) { /* Keep */
6636 ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
6637 ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
6638 /* NOTE: We should also handle hardware flow control here! */
6639 #ifdef POSIX_CRTSCTS
6640 /* In Linux case, we do this, which is unlikely to be portable */
6641 ttraw.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
6642 ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
6643 #endif /* POSIX_CRTSCTS */
6644 } else if (flow == FLO_RTSC || /* Hardware */
6647 ttraw.c_iflag &= ~(IXON|IXOFF); /* (190) */
6648 tthflow(flow, 1, &ttraw);
6650 ttraw.c_lflag &= ~(ICANON|ECHO);
6651 ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
6655 if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
6658 ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */
6659 #endif /* COHERENT */
6661 ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
6663 ttraw.c_lflag |= NOFLSH; /* Don't flush */
6664 ttraw.c_iflag |= IGNPAR; /* Ignore parity errors */
6667 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
6669 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
6672 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
6674 ttraw.c_oflag &= ~OPOST;
6675 ttraw.c_cflag &= ~(CSIZE);
6676 ttraw.c_cflag |= (CS8|CREAD|HUPCL);
6680 if (stopbits == 2) {
6681 ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
6682 debug(F100,"ttpkt 2 stopbits","",0);
6683 } else if (stopbits == 1) {
6684 ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
6685 debug(F100,"ttpkt 1 stopbit","",0);
6691 if (hwparity && xlocal) { /* Hardware parity */
6692 ttraw.c_cflag |= PARENB; /* Enable parity */
6694 /* Uncomment this only if needed -- I don't think it is */
6695 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
6696 ttraw.c_cflag |= CS8; /* And set it to 8 */
6697 #endif /* COMMENT */
6699 ttraw.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
6700 debug(F100,"ttpkt IGNPAR","",0); /* that have parity errors */
6703 case 'e': /* Even */
6704 ttraw.c_cflag &= ~(PARODD);
6705 debug(F100,"ttpkt 8 bits + even parity","",0);
6708 ttraw.c_cflag |= PARODD;
6709 debug(F100,"ttpkt 8 bits + odd parity","",0);
6711 case 'm': /* Mark */
6712 case 's': /* Space */
6713 /* PAREXT is mentioned in SVID but the details are not given. */
6714 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
6715 debug(F100,"ttpkt 8 bits + invalid parity","",0);
6718 } else { /* We handle parity ourselves */
6719 #endif /* HWPARITY */
6720 ttraw.c_cflag &= ~(PARENB); /* Don't enable parity */
6723 #endif /* HWPARITY */
6726 ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
6729 #ifndef VEOF /* for DGUX this is VEOF, not VMIN */
6730 ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */
6734 ttraw.c_cc[VMIN] = 1;
6740 #ifndef VEOL /* for DGUX this is VEOL, not VTIME */
6741 ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */
6745 ttraw.c_cc[VTIME] = 0;
6753 #ifdef VINTR /* Turn off interrupt character */
6754 if (xlocal == 0) /* so ^C^C can break us out of */
6755 ttraw.c_cc[VINTR] = 0; /* packet mode. */
6759 if (p9ttyparity('n') < 0)
6765 ttraw.c_cc[VMIN] = 0; /* DR7 can only poll. */
6766 #endif /* BEOSORBEBOX */
6771 debug(F100,"ttpkt TESTING234 rawmode","",0);
6774 ttraw.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
6775 ttraw.c_iflag &= ~(INPCK|IGNPAR|IXON|IXOFF);
6776 ttraw.c_iflag |= IGNBRK;
6778 ttraw.c_iflag &= ~IMAXBEL;
6779 #endif /* IMAXBEL */
6781 ttraw.c_iflag &= ~IXANY;
6784 ttraw.c_iflag &= ~IUCLC;
6788 ttraw.c_oflag &= ~OPOST;
6790 ttraw.c_oflag &= ~OXTABS;
6793 ttraw.c_oflag &= ~ONOCR;
6796 ttraw.c_oflag &= ~ONLRET;
6799 ttraw.c_oflag &= ~ONLCR;
6803 ttraw.c_lflag &= ~ECHO;
6805 ttraw.c_lflag &= ~ECHOE;
6808 ttraw.c_lflag &= ~ECHONL;
6811 ttraw.c_lflag &= ~ECHOPRT;
6812 #endif /* ECHOPRT */
6814 ttraw.c_lflag &= ~ECHOKE;
6817 ttraw.c_lflag &= ~ECHOCTL;
6818 #endif /* ECHOCTL */
6820 ttraw.c_lflag &= ~ALTWERASE;
6821 #endif /* ALTWERASE */
6823 ttraw.c_lflag &= ~EXTPROC;
6824 #endif /* EXTPROC */
6825 ttraw.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
6827 ttraw.c_lflag |= NOKERNINFO;
6828 #endif /* NOKERNINFO */
6829 /* ttraw.c_lflag |= NOFLSH; */
6830 ttraw.c_lflag &= ~NOFLSH;
6833 ttraw.c_cflag &= ~(CSIZE|PARENB|PARODD);
6834 ttraw.c_cflag |= CS8|CREAD;
6836 ttraw.c_cc[VMIN] = 1; /* Supposedly needed for AIX */
6840 #endif /* TESTING234 */
6842 debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
6843 x = tcsetattr(ttyfd,TCSADRAIN,&ttraw);
6844 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr","",x);
6846 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr errno","",errno);
6849 #else /* BSD44ORPOSIX */
6850 x = ioctl(ttyfd,TCSETAW,&ttraw);
6851 debug(F101,"ttpkt ATTSV ioctl TCSETAW","",x);
6852 if (x < 0) { /* set new modes . */
6853 debug(F101,"ttpkt ATTSV ioctl TCSETAW errno","",errno);
6856 #endif /* BSD44ORPOSIX */
6859 debug(F100,"ttpkt ok","",0);
6865 #endif /* COHERENT */
6869 /* T T S E T F L O W -- Set flow control immediately. */
6873 #endif /* COHERENT */
6876 ttsetflow(flow) int flow; {
6877 if (ttyfd < 0) /* A channel must be open */
6880 debug(F101,"ttsetflow flow","",flow);
6883 if (netconn && istncomport()) {
6884 debug(F101,"ttsetflow net modem","",ttmdm);
6885 return(tnsetflow(flow));
6887 #endif /* TN_COMPORT */
6889 if (ttpipe) return(0);
6892 if (ttpty) return(0);
6896 /* This seems to hurt... */
6897 if (flow == FLO_KEEP)
6899 #endif /* COMMENT */
6901 if (flow == FLO_RTSC || /* Hardware flow control... */
6904 tthflow(flow, 1, &ttraw);
6906 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6908 ttraw.c_iflag &= ~(IXON|IXOFF);
6909 #endif /* SVORPOSIX */
6911 } else if (flow == FLO_XONX) { /* Xon/Xoff... */
6914 ttraw.sg_flags |= TANDEM;
6916 ttraw.c_iflag |= (IXON|IXOFF);
6917 #endif /* SVORPOSIX */
6918 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off hardware flow control */
6920 } else if (flow == FLO_NONE) { /* No flow control */
6923 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6925 ttraw.c_iflag &= ~(IXON|IXOFF);
6926 #endif /* SVORPOSIX */
6927 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off any hardware f/c too */
6930 /* Set the new modes... */
6932 #ifndef SVORPOSIX /* BSD and friends */
6934 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
6938 if (stty(ttyfd,&ttraw) < 0)
6941 #endif /* BELLV10 */
6943 #ifdef BSD44ORPOSIX /* POSIX */
6944 if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
6946 #else /* System V */
6947 if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
6949 #endif /* BSD44ORPOSIX */
6950 #endif /* SVORPOSIX */
6955 #endif /* COHERENT */
6957 /* T T V T -- Condition communication device for use as virtual terminal. */
6961 ttvt(long speed, int flow)
6963 ttvt(speed,flow) long speed; int flow;
6964 #endif /* CK_ANSIC */
6968 debug(F101,"ttvt ttyfd","",ttyfd);
6969 debug(F101,"ttvt tvtflg","",tvtflg);
6970 debug(F111,"ttvt speed",ckitoa(ttspeed),speed);
6971 debug(F111,"ttvt flow",ckitoa(ttflow),flow);
6972 debug(F111,"ttvt curcarr",ckitoa(ttcarr),curcarr);
6974 /* Note: NetBSD and maybe other BSD44s have cfmakeraw() */
6975 /* Maybe it would be simpler to use it... */
6979 return(conbin((char)escchr));
6981 if (ttyfd < 0) { /* Not open. */
6984 else /* But maybe something buffered. */
6988 if (ttpipe) return(0);
6991 if (ttpty) return(0);
6998 extern int tcp_nodelay;
6999 if (ttnet == NET_TCPB) {
7000 if (nodelay_sav > -1) {
7001 no_delay(ttyfd,nodelay_sav);
7006 #endif /* TCP_NODELAY */
7008 if (istncomport()) {
7010 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7011 /* && ttcarr == curcarr */ ) {
7012 debug(F100,"ttvt modes already set, skipping...","",0);
7013 return(0); /* Already been called. */
7015 if (flow != ttflow) {
7016 if ((rc = tnsetflow(flow)) < 0)
7020 if (speed != ttspeed) {
7022 speed = tnc_get_baud();
7023 else if ((rc = tnc_set_baud(speed)) < 0)
7027 tnc_set_datasize(8);
7028 tnc_set_stopsize(stopbits);
7033 case 'e': /* Even */
7034 debug(F100,"ttres 8 bits + even parity","",0);
7038 debug(F100,"ttres 8 bits + odd parity","",0);
7041 case 'm': /* Mark */
7042 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
7045 case 's': /* Space */
7046 debug(F100,"ttres 8 bits + invalid parity: space","",0);
7051 #endif /* HWPARITY */
7053 tnc_set_parity(1); /* None */
7058 #endif /* TN_COMPORT */
7059 #endif /* TCPSOCKET */
7060 tvtflg = 1; /* Network connections... */
7061 debug(F100,"ttvt network connection, skipping...","",0);
7062 return(0); /* ... require no special setup */
7064 #endif /* NETCONN */
7066 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7067 /* && ttcarr == curcarr */ )
7069 debug(F100,"ttvt modes already set, skipping...","",0);
7070 return(0); /* Already been called. */
7078 debug(F100,"ttvt using external fd, skipping...","",0);
7082 debug(F100,"ttvt setting modes...","",0);
7084 if (xlocal) { /* For external lines... */
7085 s2 = (int) (speed / 10L);
7086 s = ttsspd(s2); /* Check/set the speed */
7087 carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
7088 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
7094 #endif /* COHERENT */
7097 /* Berkeley, V7, etc */
7098 if (flow == FLO_RTSC || /* Hardware flow control */
7101 tthflow(flow, 1, &tttvt);
7102 debug(F100,"ttvt hard flow, TANDEM off","",0);
7103 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7104 } else if (flow == FLO_XONX) { /* Xon/Xoff flow control */
7105 debug(F100,"ttvt TANDEM on","",0);
7106 tttvt.sg_flags |= TANDEM; /* Ask for it. */
7107 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7108 } else if (flow == FLO_NONE) {
7109 debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
7110 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7111 tthflow(flow, 0, &tttvt); /* Turn off any hardware f/c too */
7112 tttvt.sg_flags |= RAW; /* Enter raw mode */
7113 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
7114 debug(F100,"ttvt keeping original TANDEM","",0);
7115 tttvt.sg_flags &= ~TANDEM;
7116 tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
7117 /* NOTE: We should also handle hardware flow control here! */
7119 tttvt.sg_flags |= RAW; /* Raw mode in all cases */
7121 tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */
7123 tttvt.sg_flags &= ~ECHO; /* No echo */
7127 if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
7130 if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */
7132 #endif /* BELLV10 */
7134 #else /* It is ATTSV or POSIX */
7136 if (flow == FLO_XONX) { /* Software flow control */
7137 tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */
7138 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7139 debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
7140 } else if (flow == FLO_NONE) { /* NONE */
7141 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff */
7142 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7143 debug(F100,"ttvt SVORPOSIX flow NONE","",0);
7144 } else if (flow == FLO_KEEP) {
7145 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
7146 tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
7147 #ifdef POSIX_CRTSCTS
7148 tttvt.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
7149 tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
7150 #endif /* POSIX_CRTSCTS */
7151 debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
7152 } else if (flow == FLO_RTSC || /* Hardware flow control */
7155 tttvt.c_iflag &= ~(IXON|IXOFF); /* (196) */
7156 tthflow(flow, 1, &tttvt);
7157 debug(F100,"ttvt SVORPOSIX flow HARD","",0);
7161 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7163 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
7164 #endif /* COHERENT */
7166 /* Needed for hwfc */
7167 if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
7168 tttvt.c_lflag |= IEXTEN;
7171 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7172 tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
7175 tttvt.c_iflag |= (IGNBRK|IGNPAR);
7181 if (stopbits == 2) {
7182 tttvt.c_cflag |= CSTOPB; /* 2 stop bits */
7183 debug(F100,"ttvt 2 stopbits","",0);
7184 } else if (stopbits == 1) {
7185 tttvt.c_cflag &= ~(CSTOPB); /* 1 stop bit */
7186 debug(F100,"ttvt 1 stopbit","",0);
7194 if (hwparity && xlocal) { /* Hardware parity */
7196 /* Uncomment this only if needed -- I don't think it is */
7197 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
7198 ttraw.c_cflag |= CS8; /* And set it to 8 */
7199 #endif /* COMMENT */
7201 debug(F101,"ttvt hwparity IGNPAR","",IGNPAR);
7202 tttvt.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
7204 tttvt.c_cflag |= PARENB; /* Enable parity */
7207 case 'e': /* Even */
7208 tttvt.c_cflag &= ~(PARODD);
7209 debug(F100,"ttvt 8 bits + even parity","",0);
7212 tttvt.c_cflag |= PARODD;
7213 debug(F100,"ttvt 8 bits + odd parity","",0);
7215 case 'm': /* Mark */
7216 case 's': /* Space */
7217 /* PAREXT is mentioned in SVID but the details are not given. */
7218 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
7219 debug(F100,"ttvt 8 bits + invalid parity","",0);
7222 } else { /* We handle parity ourselves */
7223 #endif /* HWPARITY */
7224 tttvt.c_cflag &= ~(PARENB); /* Don't enable parity */
7227 #endif /* HWPARITY */
7231 /* Things not to do... */
7232 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
7234 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
7237 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
7239 tttvt.c_cflag &= ~(CSIZE); /* Zero out the char size field */
7240 tttvt.c_cflag |= (CS8|CREAD|HUPCL); /* Char size 8, enable receiver, hup */
7241 tttvt.c_oflag &= ~OPOST; /* Don't postprocess output */
7242 #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
7247 tttvt.c_cc[VMIN] = 1;
7253 #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */
7258 tttvt.c_cc[VTIME] = 0;
7266 if (p9ttyparity('n') < 0)
7272 tttvt.c_cc[VMIN] = 0; /* DR7 can only poll. */
7273 #endif /* BEOSORBEBOX */
7275 x = tcsetattr(ttyfd,TCSADRAIN,&tttvt);
7276 debug(F101,"ttvt BSD44ORPOSIX tcsetattr","",x);
7278 debug(F101,"ttvt BSD44ORPOSIX tcsetattr errno","",errno);
7282 x = ioctl(ttyfd,TCSETAW,&tttvt);
7283 debug(F101,"ttvt ATTSV ioctl TCSETAW","",x);
7284 if (x < 0) { /* set new modes . */
7285 debug(F101,"ttvt ATTSV ioctl TCSETAW errno","",errno);
7288 #endif /* BSD44ORPOSIX */
7292 ttspeed = speed; /* Done, remember how we were */
7293 ttflow = flow; /* called, so we can decide how to */
7294 tvtflg = 1; /* respond next time. */
7295 debug(F100,"ttvt ok","",0);
7300 #endif /* COHERENT */
7302 #endif /* NOLOCAL */
7307 /* Serial speed department . . . */
7310 SCO OSR5.0.x might or might not support high speeds. Sometimes they are not
7311 defined in the header files but they are supported (e.g. when building with
7312 UDK compiler rather than /bin/cc), sometimes vice versa. Even though 5.0.4
7313 was the first release that came with high serial speeds standard, releases
7314 back to 5.0.0 could use them if certain patches (or "supplements") were
7315 applied to the SIO driver. Plus a lot of SCO installations run third-party
7320 #define B38400 0000017
7323 #define B57600 0000021
7326 #define B76800 0000022
7329 #define B115200 0000023
7330 #endif /* B115200 */
7332 #define B230400 0000024
7333 #endif /* B230400 */
7335 #define B460800 0000025
7336 #endif /* B460800 */
7338 #define B921600 0000026
7339 #endif /* B921600 */
7340 #endif /* CK_SCOV5 */
7342 Plan 9's native speed setting interface lets you set anything you like,
7343 but will fail if the hardware doesn't like it, so we allow all the common
7381 #define B14400 14400
7384 #define B19200 19200
7387 #define B28800 28800
7390 #define B38400 38400
7393 #define B57600 57600
7396 #define B76800 76800
7399 #define B115200 115200
7400 #endif /* B115200 */
7402 #define B230400 230400
7403 #endif /* B230400 */
7405 #define B460800 460800
7406 #endif /* B460800 */
7408 #define B921600 921600
7409 #endif /* B921600 */
7412 /* T T S S P D -- Checks and sets transmission rate. */
7414 /* Call with speed in characters (not bits!) per second. */
7415 /* Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
7417 #ifdef USETCSETSPEED
7419 The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
7420 to be used as a speed to be set, rather than forcing a choice from a
7421 predefined list. It seems to be peculiar to UnixWare 7.
7423 These are the function codes to be passed to tc[gs]etspeed(),
7424 but for some reason they don't seem to be picked up from termios.h.
7428 #endif /* TCS_ALL */
7434 #endif /* TCS_OUT */
7435 #endif /* USETCSETSPEED */
7438 ttsspd(cps) int cps; {
7441 /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
7447 int ok = 1; /* Speed check result, assume ok */
7449 #ifdef OLINUXHISPEED
7450 unsigned int spd_flags = 0;
7451 struct serial_struct serinfo;
7452 #endif /* OLINUXHISPEED */
7454 debug(F101,"ttsspd cps","",cps);
7455 debug(F101,"ttsspd ttyfd","",ttyfd);
7456 debug(F101,"ttsspd xlocal","",xlocal);
7458 if (ttyfd < 0 || xlocal == 0) /* Don't set speed on console */
7465 return(tnc_set_baud(cps * 10));
7467 #endif /* TN_COMPORT */
7470 #endif /* NETCONN */
7472 if (ttpipe) return(0);
7475 if (ttpty) return(0);
7478 if (cps < 0) return(-1);
7479 s = s2 = 0; /* NB: s and s2 might be unsigned */
7481 #ifdef USETCSETSPEED
7485 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7486 debug(F101,"ttsspd tcgetattr","",x);
7489 debug(F101,"ttsspd TCSETSPEED speed","",s);
7492 if (s == 8880L) { /* 75/1200 split speed requested */
7493 tcsetspeed(TCS_IN, &ttcur, 1200L);
7494 tcsetspeed(TCS_OUT, &ttcur, 75L);
7496 tcsetspeed(TCS_ALL, &ttcur, s); /* Put new speed in structs */
7498 if (errno & deblog) {
7499 debug(F101,"ttsspd TCSETSPEED errno","",errno);
7504 tcsetspeed(TCS_ALL, &ttraw, s);
7505 tcsetspeed(TCS_ALL, &tttvt, s);
7506 tcsetspeed(TCS_ALL, &ttold, s);
7508 if (s == 8880L) { /* 75/1200 split speed requested */
7509 tcsetspeed(TCS_IN, &ttraw, 1200L);
7510 tcsetspeed(TCS_OUT, &ttraw, 75L);
7511 tcsetspeed(TCS_IN, &tttvt, 1200L);
7512 tcsetspeed(TCS_OUT, &tttvt, 75L);
7513 tcsetspeed(TCS_IN, &ttold, 1200L);
7514 tcsetspeed(TCS_OUT, &ttold, 75L);
7516 tcsetspeed(TCS_ALL, &ttraw, s);
7517 tcsetspeed(TCS_ALL, &tttvt, s);
7518 tcsetspeed(TCS_ALL, &ttold, s);
7520 #endif /* COMMENT */
7522 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
7523 debug(F101,"ttsspd tcsetattr","",x);
7527 #else /* Not USETCSETSPEED */
7529 /* First check that the given speed is valid. */
7533 case 0: s = B0; break;
7534 case 5: s = B50; break;
7535 case 7: s = B75; break;
7537 case 11: s = B110; break;
7539 case 13: s = B134; break;
7540 case 15: s = B150; break;
7541 case 20: s = B200; break;
7543 case 30: s = B300; break;
7545 case 60: s = B600; break;
7547 case 120: s = B1200; break;
7549 case 180: s = B1800; break;
7551 case 240: s = B2400; break;
7552 case 480: s = B4800; break;
7554 case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
7557 case 720: s = B7200; break;
7559 case 960: s = B9600; break;
7561 case 1440: s = B14400; break;
7564 case 1920: s = B19200; break;
7567 case 1920: s = EXTA; break;
7571 case 2880: s = B28800; break;
7574 case 3840: s = B38400;
7575 #ifdef OLINUXHISPEED
7576 spd_flags = ~ASYNC_SPD_MASK; /* Nonzero, but zero flags */
7577 #endif /* OLINUXHISPEED */
7579 #else /* B38400 not defined... */
7581 case 3840: s = EXTB; break;
7587 case 5760: s = _B57600; break;
7588 #endif /* _B57600 */
7590 case 11520: s = _B115200; break;
7591 #endif /* _B115200 */
7593 #ifdef OLINUXHISPEED
7595 This bit from <carlo@sg.tn.tudelft.nl>:
7596 "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
7597 setting the speed to 38400 will set the custom speed (and ttgspd returns
7598 38400), but speeds 57600 and 115200 won't work any more because I didn't
7599 want to mess up the speed flags when someone is doing sophisticated stuff
7600 like custom speeds..."
7602 case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
7603 case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
7606 case 5760: s = B57600; break;
7609 case 7680: s = B76800; break;
7612 case 11520: s = B115200; break;
7613 #endif /* B115200 */
7614 #endif /* OLINUXHISPEED */
7616 case 15360: s = B153600; break;
7617 #endif /* B153600 */
7619 case 23040: s = B230400; break;
7620 #endif /* B230400 */
7622 case 30720: s = B307200; break;
7623 #endif /* B307200 */
7625 case 46080: s = B460800; break;
7628 case 92160: s = B921600; break;
7629 #endif /* B921600 */
7632 ok = 0; /* Good speed not found, so not ok */
7635 debug(F101,"ttsspd ok","",ok);
7636 debug(F101,"ttsspd s","",s);
7639 debug(F100,"ttsspd fails","",0);
7642 if (!s2) s2 = s; /* Set input speed */
7644 if (p9ttsspd(cps) < 0)
7648 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7649 debug(F101,"ttsspd tcgetattr","",x);
7652 #ifdef OLINUXHISPEED
7653 debug(F101,"ttsspd spd_flags","",spd_flags);
7654 if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
7655 if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
7656 debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
7658 } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
7659 serinfo.flags &= ~ASYNC_SPD_MASK;
7660 serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
7661 if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
7664 #endif /* OLINUXHISPEED */
7665 cfsetospeed(&ttcur,s);
7666 cfsetispeed(&ttcur,s2);
7667 cfsetospeed(&ttraw,s);
7668 cfsetispeed(&ttraw,s2);
7669 cfsetospeed(&tttvt,s);
7670 cfsetispeed(&tttvt,s2);
7671 cfsetospeed(&ttold,s);
7672 cfsetispeed(&ttold,s2);
7673 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
7674 debug(F101,"ttsspd tcsetattr","",x);
7675 if (x < 0) return(-1);
7678 if (cps == 888) return(-1); /* No split speeds, sorry. */
7679 x = ioctl(ttyfd,TCGETA,&ttcur);
7680 debug(F101,"ttsspd TCGETA ioctl","",x);
7681 if (x < 0) return(-1);
7682 ttcur.c_cflag &= ~CBAUD;
7684 tttvt.c_cflag &= ~CBAUD;
7686 ttraw.c_cflag &= ~CBAUD;
7688 ttold.c_cflag &= ~CBAUD;
7690 x = ioctl(ttyfd,TCSETAW,&ttcur);
7691 debug(F101,"ttsspd TCSETAW ioctl","",x);
7692 if (x < 0) return(-1);
7695 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
7696 debug(F101,"ttsspd TIOCGDEV ioctl","",x);
7697 if (x < 0) return(-1);
7701 ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
7702 debug(F101,"ttsspd BELLV10 ioctl","",ok);
7705 debug(F101,"ttsspd BELLV10 errno","",ok);
7709 x = gtty(ttyfd,&ttcur);
7710 debug(F101,"ttsspd gtty","",x);
7711 if (x < 0) return(-1);
7712 ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
7713 tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
7714 ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
7715 ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
7716 x = stty(ttyfd,&ttcur);
7717 debug(F101,"ttsspd stty","",x);
7718 if (x < 0) return(-1);
7719 #endif /* BELLV10 */
7721 #endif /* BSD44ORPOSIX */
7724 return(1); /* Return 1 = success. */
7725 #endif /* USETCSETSPEED */
7728 #endif /* NOLOCAL */
7730 /* C O N G S P D - Get speed of console terminal */
7735 This is a disgusting hack. The right way to do this would be to pass an
7736 argument to ttgspd(), but then we'd need to change the Kermit API and
7737 all of the ck?tio.c modules. (Currently used only for rlogin.)
7744 #endif /* NETCONN */
7748 debug(F101,"congspd","",spd);
7751 #endif /* NETCONN */
7756 /* T T S P D L I S T -- Get list of serial speeds allowed on this platform */
7759 static long spdlist[NSPDLIST];
7761 As written, this picks up the speeds known at compile time, and thus
7762 apply to the system where C-Kermit was built, rather than to the one where
7763 it is running. Suggestions for improvement are always welcome.
7768 for (i = 0; i < NSPDLIST; i++) /* Initialize the list */
7772 #ifdef USETCSETSPEED /* No way to find out what's legal */
7773 debug(F100,"ttspdlist USETCSETSPEED","",0);
7778 spdlist[i++] = 110L;
7780 spdlist[i++] = 134L;
7782 spdlist[i++] = 150L;
7783 spdlist[i++] = 200L;
7784 spdlist[i++] = 300L;
7785 spdlist[i++] = 600L;
7786 spdlist[i++] = 1200L;
7787 spdlist[i++] = 1800L;
7788 spdlist[i++] = 2400L;
7789 spdlist[i++] = 4800L;
7790 spdlist[i++] = 8880L;
7791 spdlist[i++] = 9600L;
7792 spdlist[i++] = 14400L;
7793 spdlist[i++] = 19200L;
7794 spdlist[i++] = 28800L;
7796 spdlist[i++] = 33600L;
7798 spdlist[i++] = 38400L;
7799 spdlist[i++] = 57600L;
7800 spdlist[i++] = 76800L;
7801 spdlist[i++] = 115200L;
7803 spdlist[i++] = 153600L;
7804 spdlist[i++] = 230400L;
7805 spdlist[i++] = 307200L;
7806 spdlist[i++] = 460800L;
7807 spdlist[i++] = 921600L;
7810 #else /* USETCSETSPEED */
7812 debug(F100,"ttspdlist no USETCSETSPEED","",0);
7815 debug(F101,"ttspdlist B50","",B50);
7819 debug(F101,"ttspdlist B75","",B75);
7823 debug(F101,"ttspdlist B110","",B110);
7824 spdlist[i++] = 110L;
7827 debug(F101,"ttspdlist B134","",B134);
7828 spdlist[i++] = 134L;
7831 debug(F101,"ttspdlist B150","",B150);
7832 spdlist[i++] = 150L;
7835 debug(F101,"ttspdlist B200","",B200);
7836 spdlist[i++] = 200L;
7839 debug(F101,"ttspdlist B300","",B300);
7840 spdlist[i++] = 300L;
7843 debug(F101,"ttspdlist B600","",B600);
7844 spdlist[i++] = 600L;
7847 debug(F101,"ttspdlist B1200","",B1200);
7848 spdlist[i++] = 1200L;
7851 debug(F101,"ttspdlist B1800","",B1800);
7852 spdlist[i++] = 1800L;
7855 debug(F101,"ttspdlist B2400","",B2400);
7856 spdlist[i++] = 2400L;
7859 debug(F101,"ttspdlist B4800","",B4800);
7860 spdlist[i++] = 4800L;
7863 debug(F101,"ttspdlist B9600","",B9600);
7864 spdlist[i++] = 9600L;
7867 debug(F101,"ttspdlist B14400","",B14400);
7868 spdlist[i++] = 14400L;
7871 debug(F101,"ttspdlist B19200","",B19200);
7872 spdlist[i++] = 19200L;
7875 debug(F101,"ttspdlist EXTA","",EXTA);
7876 spdlist[i++] = 19200L;
7880 debug(F101,"ttspdlist B28800","",B28800);
7881 spdlist[i++] = 28800L;
7884 debug(F101,"ttspdlist B33600","",B33600);
7885 spdlist[i++] = 33600L;
7888 debug(F101,"ttspdlist B38400","",B38400);
7889 spdlist[i++] = 38400L;
7892 debug(F101,"ttspdlist EXTB","",EXTB);
7893 spdlist[i++] = 38400L;
7897 debug(F101,"ttspdlist _B57600","",_B57600);
7898 spdlist[i++] = 57600L;
7901 debug(F101,"ttspdlist B57600","",B57600);
7902 spdlist[i++] = 57600L;
7904 #endif /* _B57600 */
7906 debug(F101,"ttspdlist B76800","",B76800);
7907 spdlist[i++] = 76800L;
7910 debug(F101,"ttspdlist _B115200","",_B115200);
7911 spdlist[i++] = 115200L;
7914 debug(F101,"ttspdlist B115200","",B115200);
7915 spdlist[i++] = 115200L;
7916 #endif /* B115200 */
7917 #endif /* _B115200 */
7919 debug(F101,"ttspdlist B153600","",B153600);
7920 spdlist[i++] = 153600L;
7921 #endif /* B153600 */
7923 debug(F101,"ttspdlist B230400","",B230400);
7924 spdlist[i++] = 230400L;
7925 #endif /* B230400 */
7927 debug(F101,"ttspdlist B307200","",B307200);
7928 spdlist[i++] = 307200L;
7929 #endif /* B307200 */
7931 debug(F101,"ttspdlist B460800","",B460800);
7932 spdlist[i++] = 460800L;
7933 #endif /* B460800 */
7935 debug(F101,"ttspdlist B921600","",B921600);
7936 spdlist[i++] = 921600L;
7937 #endif /* B921600 */
7938 #endif /* USETCSETSPEED */
7939 spdlist[0] = i - 1; /* Return count in 0th element */
7940 debug(F111,"ttspdlist spdlist","0",spdlist[0]);
7941 return((long *)spdlist);
7944 /* T T G S P D - Get speed of currently selected tty line */
7947 Unreliable. After SET LINE, it returns an actual speed, but not necessarily
7948 the real speed. On some systems, it returns the line's nominal speed, from
7949 /etc/ttytab. Even if you SET SPEED to something else, this function might
7953 ttgspd() { /* Get current serial device speed */
7958 speed_t /* Should be unsigned */
7960 int /* Isn't unsigned */
7965 #ifdef OLINUXHISPEED
7966 unsigned int spd_flags = 0;
7967 struct serial_struct serinfo;
7968 #endif /* OLINUXHISPEED */
7974 return(tnc_get_baud());
7976 #endif /* TN_COMPORT */
7977 return(-1); /* -1 if network connection */
7979 #endif /* NETCONN */
7981 if (ttpipe) return(-1);
7984 if (ttpty) return(-1);
7987 debug(F101,"ttgspd ttyfd","",ttyfd);
7989 #ifdef USETCSETSPEED
7991 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7992 debug(F101,"ttgspd tcgetattr","",x);
7996 s = tcgetspeed(TCS_ALL, &ttcur);
7997 debug(F101,"ttsspd TCGETSPEED speed","",s);
8000 s1 = tcgetspeed(TCS_IN, &ttcur);
8001 s2 = tcgetspeed(TCS_OUT, &ttcur);
8002 if (s1 == 1200L && s2 == 75L)
8006 if (errno & deblog) {
8007 debug(F101,"ttsspd TCGETSPEED errno","",errno);
8012 #else /* Not USETCSETSPEED */
8020 #ifdef OLINUXHISPEED
8021 debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
8022 #endif /* OLINUXHISPEED */
8026 s = cfgetospeed(&ccold);
8027 debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
8030 s = ccold.c_cflag & CBAUD;
8031 debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
8033 s = ccold.sg_ospeed; /* (obtained by congm()) */
8034 debug(F101,"ttgspd sg_ospeed 1","",s);
8036 #endif /* BSD44POSIX */
8040 if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
8041 s = cfgetospeed(&ttcur);
8042 debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
8043 #ifdef OLINUXHISPEED
8044 if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
8045 spd_flags = serinfo.flags & ASYNC_SPD_MASK;
8046 debug(F101,"ttgspd spd_flags","",spd_flags);
8047 #endif /* OLINUXHISPEED */
8050 x = ioctl(ttyfd,TCGETA,&ttcur);
8051 debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
8052 debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
8053 if (x < 0) return(-1);
8054 s = ttcur.c_cflag & CBAUD;
8055 debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
8058 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
8059 debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
8060 if (x < 0) return(-1);
8062 debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
8064 x = gtty(ttyfd,&ttcur);
8065 debug(F101,"ttgspd gtty 2 x","",x);
8066 debug(F101,"ttgspd gtty 2 errno","",errno);
8067 if (x < 0) return(-1);
8068 s = ttcur.sg_ospeed;
8069 debug(F101,"ttgspd gtty 2 speed","",s);
8070 #endif /* BELLV10 */
8072 #endif /* BSD44ORPOSIX */
8074 debug(F101,"ttgspd code","",s);
8075 #ifdef OLINUXHISPEED
8076 debug(F101,"ttgspd spd_flags","",spd_flags);
8077 #endif /* OLINUXHISPEED */
8080 case B0: ss = 0L; break;
8085 MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
8086 etc, making for many "duplicate case in switch" errors, which are fatal.
8089 case B50: ss = 50L; break;
8092 case B75: ss = 75L; break;
8097 case B110: ss = 110L; break;
8102 case B134: ss = 134L; break;
8105 case B150: ss = 150L; break;
8110 case B200: ss = 200L; break;
8114 case B300: ss = 300L; break;
8118 case B600: ss = 600L; break;
8122 case B1200: ss = 1200L; break;
8126 case B1800: ss = 1800L; break;
8130 case B2400: ss = 2400L; break;
8134 case B4800: ss = 4800L; break;
8138 case B7200: ss = 7200L; break;
8142 case B9600: ss = 9600L; break;
8146 case B19200: ss = 19200L; break;
8149 case EXTA: ss = 19200L; break;
8157 #ifdef OLINUXHISPEED
8159 case ASYNC_SPD_HI: ss = 57600L; break;
8160 case ASYNC_SPD_VHI: ss = 115200L; break;
8162 #endif /* OLINUXHISPEED */
8166 case EXTB: ss = 38400L; break;
8173 case _B57600: ss = 57600L; break;
8174 #endif /* _B57600 */
8176 case _B115200: ss = 115200L; break;
8177 #endif /* _B115200 */
8180 case B57600: ss = 57600L; break;
8183 case B76800: ss = 76800L; break;
8186 case B115200: ss = 115200L; break;
8187 #endif /* B115200 */
8189 case B153600: ss = 153600L; break;
8190 #endif /* B153600 */
8192 case B230400: ss = 230400L; break;
8193 #endif /* B230400 */
8195 case B307200: ss = 307200L; break;
8196 #endif /* B307200 */
8198 case B460800: ss = 460800L; break;
8199 #endif /* B460800 */
8202 case B921600: ss = 921600L; break;
8203 #endif /* B921600 */
8208 debug(F101,"ttgspd speed","",ss);
8211 #endif /* USETCSETSPEED */
8212 #endif /* NOLOCAL */
8214 #ifdef MINIX2 /* Another hack alert */
8219 FIONREAD data type... This has been defined as "long" for many, many
8220 years, and it worked OK until 64-bit platforms appeared. Thus we use
8221 int for 64-bit platforms, but keep long for the others. If we changed
8222 the default PEEKTYPE to int, this would probably break 16-bit builds
8223 (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
8224 of which we have no way of testing any more. Therefore, do not change
8225 the default definition of PEEKTYPE -- only add exceptions to it as needed.
8230 #endif /* FIONREAD */
8231 /* #define FIONREAD TIOCQUERY */
8232 /* #define PEEKTYPE int */
8233 #else /* Not COHERENT... */
8235 #ifdef OSF32 /* Digital UNIX 3.2 or higher */
8236 #define PEEKTYPE int
8238 #define PEEKTYPE long /* Elsewhere (see notes above) */
8240 #endif /* COHERENT */
8242 /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
8246 /* Private buffer for myread() and its companions. Not for use by anything
8247 * else. ttflui() is allowed to reset them to initial values. ttchk() is
8248 * allowed to read my_count.
8250 * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
8252 * A global parity mask variable could be useful too. We could use it to
8253 * let myread() strip the parity on its own, instead of stripping sign
8254 * bits as it does now.
8257 #define MYBUFLEN 32768
8260 #define MYBUFLEN 256
8262 #define MYBUFLEN 1024
8264 #endif /* BIGBUFOK */
8268 #define MYBUFLEN 256
8270 On X.25 connections, there is an extra control byte at the beginning.
8272 static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */
8273 static CHAR *mybuf = x25buf+1;
8275 static CHAR mybuf[MYBUFLEN];
8278 static int my_count = 0; /* Number of chars still in mybuf */
8279 static int my_item = -1; /* Last index read from mybuf[] */
8281 /* T T P E E K -- Peek into our internal communications input buffers. */
8284 NOTE: This routine is peculiar to UNIX, and is used only by the
8285 select()-based CONNECT module, ckucns.c. It need not be replicated in
8286 the ck?tio.c of other platforms.
8298 #endif /* TTLEBUF */
8307 /* myread() -- Efficient read of one character from communications line.
8309 * NOTE: myread() and its helpers mygetbuf() and myfillbuf() return raw
8310 * bytes from connection, so when the connection is encrypted, these bytes
8311 * must be decrypted.
8313 * Uses a private buffer to minimize the number of expensive read() system
8314 * calls. Essentially performs the equivalent of read() of 1 character, which
8315 * is then returned. By reading all available input from the system buffers
8316 * to the private buffer in one chunk, and then working from this buffer, the
8317 * number of system calls is reduced in any case where more than one character
8318 * arrives during the processing of the previous chunk, for instance high
8319 * baud rates or network type connections where input arrives in packets.
8320 * If the time needed for a read() system call approaches the time for more
8321 * than one character to arrive, then this mechanism automatically compensates
8322 * for that by performing bigger read()s less frequently. If the system load
8323 * is high, the same mechanism compensates for that too.
8325 * myread() is a macro that returns the next character from the buffer. If the
8326 * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
8329 * This should be efficient enough for any one-character-at-a-time loops.
8330 * For even better efficiency you might use memcpy()/bcopy() or such between
8331 * buffers (since they are often better optimized for copying), but it may not
8332 * be worth it if you have to take an extra pass over the buffer to strip
8333 * parity and check for CTRL-C anyway.
8335 * Note that if you have been using myread() from another program module, you
8336 * may have some trouble accessing this macro version and the private variables
8337 * it uses. In that case, just add a function in this module, that invokes the
8340 #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
8342 /* Specification: Push back up to one character onto myread()'s queue.
8344 * This implementation: Push back characters into mybuf. At least one character
8345 * must have been read through myread() before myunrd() may be used. After
8346 * EOF or read error, again, myunrd() can not be used. Sometimes more than
8347 * one character can be pushed back, but only one character is guaranteed.
8348 * Since a previous myread() must have read its character out of mybuf[],
8349 * that guarantees that there is space for at least one character. If push
8350 * back was really needed after EOF, a small addition could provide that.
8352 * As of 02/2007 myunrd() is used by ttinl().
8359 #endif /* CK_ANSIC */
8362 mybuf[my_item--] = ch;
8367 /* T T P U S H B A C K -- Put n bytes back into the myread buffer */
8369 static CHAR * pushbuf = NULL;
8370 /* static int pushed = 0; */
8373 ttpushback(s,n) CHAR * s; int n; {
8374 debug(F101,"ttpushback n","",n);
8375 if (pushbuf || n > MYBUFLEN || n < 1)
8377 debug(F101,"ttpushback my_count","",my_count);
8379 if (!(pushbuf = (CHAR *)malloc(n+1)))
8381 memcpy(pushbuf,mybuf,my_count);
8382 /* pushed = my_count; */ /* (set but never used) */
8390 /* mygetbuf() -- Fill buffer for myread() and return first character.
8392 * This function is what myread() uses when it can't get the next character
8393 * directly from its buffer. First, it calls a system dependent myfillbuf()
8394 * to read at least one new character into the buffer, and then it returns
8395 * the first character just as myread() would have done. This function also
8396 * is responsible for all error conditions that myread() can indicate.
8398 * Returns: When OK => a positive character, 0 or greater.
8400 * When error => -3, error code in errno.
8402 * Older myread()s additionally returned -1 to indicate that there was nothing
8403 * to read, upon which the caller would call myread() again until it got
8404 * something. The new myread()/mygetbuf() always gets something. If it
8405 * doesn't, then make it do so! Any program that actually depends on the old
8406 * behaviour will break.
8408 * The older version also used to return -2 both for EOF and other errors,
8409 * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
8410 * other errors now return different results, although Kermit currently never
8411 * checks to see which it was. It just disconnects in both cases.
8413 * Kermit lets the user use the quit key to perform some special commands
8414 * during file transfer. This causes read(), and thus also mygetbuf(), to
8415 * finish without reading anything and return the EINTR error. This should
8416 * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
8417 * but if there is nothing to read, this could delay Kermit's reaction to
8418 * the command, and make Kermit appear unresponsive.
8420 * The debug() call should be removed for optimum performance.
8427 if (deblog && my_count > 0)
8428 debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
8431 my_count = myfillbuf();
8435 if (deblog) debug(F101, "mygetbuf read", "", my_count);
8437 ckhexdump("mygetbuf read", mybuf, my_count);
8438 #endif /* COMMENT */
8441 if (my_count <= 0) {
8444 debug(F101,"mygetbuf errno","",errno);
8446 if (netconn && ttnet == NET_TCPB && errno != 0) {
8447 if (errno != EINTR) {
8448 debug(F101,"mygetbuf TCP error","",errno);
8449 ttclos(0); /* Close the connection. */
8453 #endif /* TCPSOCKET */
8454 if (!netconn && xlocal && errno) {
8455 if (errno != EINTR) {
8456 debug(F101,"mygetbuf SERIAL error","",errno);
8458 ttclos(0); /* Close the connection. */
8461 return((x < 0) ? -3 : -2);
8464 return((unsigned)(0xff & mybuf[my_item = 0]));
8468 * System-dependent read() into mybuf[], as many characters as possible.
8470 * Returns: OK => number of characters read, always more than zero.
8472 * Error => -1, error code in errno.
8474 * If there is input available in the system's buffers, all of it should be
8475 * read into mybuf[] and the function return immediately. If no input is
8476 * available, it should wait for a character to arrive, and return with that
8477 * one in mybuf[] as soon as possible. It may wait somewhat past the first
8478 * character, but be aware that any such delay lengthens the packet turnaround
8479 * time during kermit file transfers. Should never return with zero characters
8480 * unless EOF or irrecoverable read error.
8482 * Correct functioning depends on the correct tty parameters being used.
8483 * Better control of current parameters is required than may have been the
8484 * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
8485 * no longer be sometimes off and sometimes on like it used to, unless a
8486 * special myfillbuf() is written to handle that. Otherwise the ordinary
8487 * myfillbuf()s may think they have come to EOF.
8489 * If your system has a facility to directly perform the functioning of
8490 * myfillbuf(), then use it. If the system can tell you how many characters
8491 * are available in its buffers, then read that amount (but not less than 1).
8492 * If the system can return a special indication when you try to read without
8493 * anything to read, while allowing you to read all there is when there is
8494 * something, you may loop until there is something to read, but probably that
8495 * is not good for the system load.
8499 /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
8500 * and CLOCAL set any way you like. This way, read() will do exactly
8501 * what is required by myfillbuf(): If there is data in the buffers
8502 * of the O.S., all available data is read into mybuf, up to the size
8503 * of mybuf. If there is none, the first character to arrive is
8504 * awaited and returned.
8517 /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */
8518 /* necessary for the sxa E50, but it is. */
8519 return read(fd, mybuf, 255);
8525 n = netxin(sizeof(mybuf), (char *)mybuf);
8526 debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
8529 #endif /* NETCONN */
8530 n = read(fd, mybuf, sizeof(mybuf));
8531 debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
8536 #else /* BEOSORBEBOX */
8538 /* debug(F101,"SVORPOSIX myfillbuf calling read() fd","",fd); */
8540 if (netconn && (nettype == NET_IX25)) {
8541 /* can't use sizeof because mybuf is a pointer, and not an array! */
8542 n = x25xin( MYBUFLEN, mybuf );
8547 if (ssl_active_flag || tls_active_flag) {
8549 debug(F100,"myfillbuf calling SSL_read() fd","",0);
8551 if (ssl_active_flag)
8552 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8553 else if (tls_active_flag)
8554 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8557 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8558 case SSL_ERROR_NONE:
8565 case SSL_ERROR_WANT_WRITE:
8566 case SSL_ERROR_WANT_READ:
8568 case SSL_ERROR_SYSCALL:
8571 case SSL_ERROR_WANT_X509_LOOKUP:
8573 case SSL_ERROR_ZERO_RETURN:
8584 if (ttnproto == NP_EK4LOGIN) {
8585 debug(F101,"myfillbuf calling krb4_des_read() fd","",ttyfd);
8586 if ((n = krb4_des_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8591 #endif /* RLOGCODE */
8595 if (ttnproto == NP_EK5LOGIN) {
8596 debug(F101,"myfillbuf calling krb5_des_read() fd","",ttyfd);
8597 if ((n = krb5_des_read(ttyfd,(char *)mybuf,sizeof(mybuf),0)) < 0)
8602 #endif /* RLOGCODE */
8604 if (ttnproto == NP_K5U2U) {
8605 debug(F101,"myfillbuf calling krb5_u2u_read() fd","",ttyfd);
8606 if ((n = krb5_u2u_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8611 #endif /* KRB5_U2U */
8613 #endif /* CK_KERBEROS */
8617 /* Special handling for HP-UX pty i/o */
8619 if (ttpty && pty_trap_pending(ttyfd) > 0) {
8620 debug(F101,"myfillbuf calling pty_trap_handler() fd","",ttyfd);
8621 if (pty_trap_handler(ttyfd) > 0) {
8626 #endif /* HAVE_PTYTRAP */
8628 debug(F101,"myfillbuf calling read() fd","",ttyfd);
8629 n = read(fd, mybuf, sizeof(mybuf));
8630 debug(F101,"SVORPOSIX myfillbuf read","",n);
8631 debug(F101,"SVORPOSIX myfillbuf errno","",errno);
8632 debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
8636 /* When we have a PTY trap in place the connection cannot */
8637 /* be closed until the trap receives a close indication. */
8638 if (n == 0 && ttpty)
8640 #endif /* HAVE_PTYTRAP */
8645 #endif /* BEOSORBEBOX */
8649 #else /* not AT&T or POSIX */
8652 /* This is quoted from the old myread(). The semantics seem to be
8653 * alright, but maybe errno would not need to be set even when
8654 * there is no error? I don't know aegis.
8666 count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
8668 if (st.all == ios_$get_conditional_failed) /* get at least one */
8669 count = ios_$get((short)fd, 0, mybuf, 1L, st);
8670 if (st.all == ios_$end_of_file)
8672 else if (st.all != status_$ok) {
8676 return(count > 0 ? count : -3);
8681 /* This is for systems with FIONREAD. FIONREAD returns the number
8682 * of characters available for reading. If none are available, wait
8683 * until something arrives, otherwise return all there is.
8698 SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
8699 Depends on SunOS having FIONREAD, not because we use it, but just so this
8700 code is grouped correctly within the #ifdefs. Let's hope Solaris keeps it.
8702 We call x25xin() instead of read() so that Q-Bit packets, which contain
8703 X.25 service-level information (e.g. PAD parameter changes), can be processed
8704 transparently to the upper-level code. This is a blocking read, and so
8705 we depend on higher-level code (such as ttinc()) to set any necessary alarms.
8708 if (netconn && nettype == NET_SX25) {
8709 while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
8710 return(x - 1); /* "-1" compensates for extra status byte */
8715 if (ssl_active_flag || tls_active_flag) {
8718 if (ssl_active_flag)
8719 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8721 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8722 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8723 case SSL_ERROR_NONE:
8730 case SSL_ERROR_WANT_WRITE:
8731 case SSL_ERROR_WANT_READ:
8733 case SSL_ERROR_SYSCALL:
8736 case SSL_ERROR_WANT_X509_LOOKUP:
8738 case SSL_ERROR_ZERO_RETURN:
8749 if (ttnproto == NP_EK4LOGIN) {
8750 if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8755 #endif /* RLOGCODE */
8759 if (ttnproto == NP_EK5LOGIN) {
8760 if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8765 #endif /* RLOGCODE */
8767 if (ttnproto == NP_K5U2U) {
8768 if ((x = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8773 #endif /* KRB5_U2U */
8775 #endif /* CK_KERBEROS */
8778 debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
8779 x = ioctl(fd, FIONREAD, &avail);
8782 debug(F101,"myfillbuf FIONREAD","",x);
8783 debug(F101,"myfillbuf FIONREAD avail","",avail);
8784 debug(F101,"myfillbuf FIONREAD errno","",errno);
8787 if (x < 0 || avail == 0)
8790 if (avail > MYBUFLEN)
8795 x = read(fd, mybuf, (int) avail);
8798 debug(F101,"myfillbuf avail","",avail);
8799 debug(F101,"myfillbuf read","",x);
8800 debug(F101,"myfillbuf read errno","",errno);
8802 ckhexdump("myfillbuf mybuf",mybuf,x);
8805 if (x < 1) x = -3; /* read 0 == connection loss */
8809 #else /* !FIONREAD */
8810 /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
8811 /* When there is no other possibility, read 1 character at a time. */
8817 if (ssl_active_flag || tls_active_flag) {
8820 if (ssl_active_flag)
8821 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8823 count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8824 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8825 case SSL_ERROR_NONE:
8832 case SSL_ERROR_WANT_WRITE:
8833 case SSL_ERROR_WANT_READ:
8835 case SSL_ERROR_SYSCALL:
8838 case SSL_ERROR_WANT_X509_LOOKUP:
8840 case SSL_ERROR_ZERO_RETURN:
8851 if (ttnproto == NP_EK4LOGIN) {
8852 if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8857 #endif /* RLOGCODE */
8861 if (ttnproto == NP_EK5LOGIN) {
8862 if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8867 #endif /* RLOGCODE */
8869 if (ttnproto == NP_K5U2U) {
8870 if ((len = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8875 #endif /* KRB5_U2U */
8877 #endif /* CK_KERBEROS */
8885 x = read(fd, mybuf, 1);
8886 return(x > 0 ? x : -3);
8889 #endif /* !FIONREAD */
8895 /* T T _ T N O P T -- Handle Telnet negotions in incoming data */
8897 Call with the IAC that was encountered.
8899 -3: If connection has dropped or gone bad.
8900 -2: On Telnet protocol error resulting in inconsistent states.
8901 0: If negotiation OK and caller has nothing to do.
8902 1: If packet start character has changed (new value is in global stchr).
8903 255: If there was a quoted IAC as data.
8904 or: Not at all if we got a legitimate Telnet Logout request.
8908 tt_tnopt(n) int n; { /* Handle Telnet options */
8909 /* In case caller did not already check these conditions... */
8911 ((xlocal && netconn && IS_TELNET()) ||
8912 (!xlocal && sstelnet))) {
8915 debug(F100,"ttinl calling tn_doop()","",0);
8916 tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
8917 debug(F111,"ttinl tn_doop() returned","tx",tx);
8921 case -1: /* I/O error */
8922 ttimoff(); /* Turn off timer */
8924 case -2: /* Connection failed. */
8926 ttimoff(); /* Turn off timer */
8929 case 1: /* ECHO change */
8932 case 2: /* ECHO change */
8935 case 3: /* Quoted IAC */
8937 return((unsigned)255);
8940 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
8944 ) { /* Remote in Server mode */
8945 ttimoff(); /* Turn off timer */
8946 debug(F100,"u_start and !inserver","",0);
8947 return(-2); /* End server mode */
8948 } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
8950 ) { /* I'm no longer in Server Mode */
8951 debug(F100,"me_start and server","",0);
8957 case 5: { /* Start character change */
8958 /* extern CHAR stchr; */
8959 /* start = stchr; */
8962 #endif /* IKS_OPTION */
8963 case 6: /* Remote Logout */
8967 if (inserver && !local)
8968 doexit(GOOD_EXIT,0);
8978 #endif /* TCPSOCKET */
8980 /* T T F L U I -- Flush tty input buffer */
8983 ttflux() { /* But first... */
8986 Flush internal MYREAD buffer.
8990 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
8991 (!xlocal && sstelnet)));
8992 #endif /* TCPSOCKET */
8993 debug(F101,"ttflux my_count","",my_count);
8997 while (my_count > 0) {
8999 #ifdef CK_ENCRYPTION
9000 if (TELOPT_U(TELOPT_ENCRYPTION))
9001 ck_tn_decrypt((char *)&ch,1);
9002 #endif /* CK_ENCRYPTION */
9007 #endif /* TCPSOCKET */
9009 #ifdef CK_ENCRYPTION
9010 if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
9011 ck_tn_decrypt(&mybuf[my_item+1],my_count);
9012 #endif /* CK_ENCRYPTION */
9013 #endif /* COMMENT */
9014 my_count = 0; /* Reset count to zero */
9015 my_item = -1; /* And buffer index to -1 */
9024 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
9025 (!xlocal && sstelnet)));
9026 #endif /* TCPSOCKET */
9036 ttpush = -1; /* Clear the peek-ahead char */
9037 while (le_data && (le_inbuf() > 0)) {
9039 if (le_getchar(&ch) > 0) { /* Clear any more... */
9040 debug(F101,"ttflui le_inbuf ch","",ch);
9043 #endif /* TTLEBUF */
9044 debug(F101,"ttflui ttpipe","",ttpipe);
9048 Flush internal MYREAD buffer *NEXT*, in all cases.
9054 /* Network flush is done specially, in the network support module. */
9055 if ((netconn || sstelnet) && !ttpipe && !ttpty) {
9056 debug(F100,"ttflui netflui","",0);
9060 tnc_send_purge_data(TNC_PURGE_RECEIVE);
9061 #endif /* TN_COMPORT */
9062 #endif /* COMMENT */
9065 #endif /* NETCONN */
9067 debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
9072 sio_$control((short)yfd, sio_$flush_in, true, st);
9073 if (st.all != status_$ok) {
9074 fprintf(stderr, "flush failed: "); error_$print(st);
9075 } else { /* sometimes the flush doesn't work */
9078 /* eat all the characters that shouldn't be available */
9079 ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
9080 if (st.all == ios_$get_conditional_failed) break;
9081 fprintf(stderr, "flush failed(2): "); error_$print(st);
9085 #ifdef BSD44 /* 4.4 BSD */
9086 n = FREAD; /* Specify read queue */
9087 debug(F100,"ttflui BSD44","",0);
9088 ioctl(fd,TIOCFLUSH,&n);
9091 #undef POSIX /* Uh oh... */
9093 #ifdef POSIX /* POSIX */
9094 debug(F100,"ttflui POSIX","",0);
9095 tcflush(fd,TCIFLUSH);
9097 #ifdef ATTSV /* System V */
9099 debug(F100,"ttflui ATTSV","",0);
9102 #else /* Not BSD44, POSIX, or Sys V */
9103 #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */
9104 #ifdef ANYBSD /* Berkeley */
9105 n = FREAD; /* Specify read queue */
9106 debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
9107 ioctl(fd,TIOCFLUSH,&n);
9108 #else /* Others (V7, etc) */
9109 debug(F100,"ttflui TIOCFLUSH","",0);
9110 ioctl(fd,TIOCFLUSH,0);
9112 #else /* All others... */
9114 No system call (that we know about) for input buffer flushing.
9115 So see how many there are and read them in a loop, using ttinc().
9116 ttinc() is buffered, so we're not getting charged with a system call
9117 per character, just a function call.
9119 if ((n = ttchk()) > 0) {
9120 debug(F101,"ttflui read loop","",n);
9121 while ((n--) && ttinc(0) > 0) ;
9123 #endif /* TIOCFLUSH */
9135 ttfluo() { /* Flush output buffer */
9148 return(tcflush(fd,TCOFLUSH));
9151 return(ioctl(fd,TCFLSH,1));
9153 return(0); /* All others, nothing */
9159 /* Interrupt Functions */
9161 /* Set up terminal interrupts on console terminal */
9163 #ifndef FIONREAD /* We don't need esctrp() */
9164 #ifndef SELECT /* if we have any of these... */
9171 esctrp(foo) int foo; { /* trap console escapes (^\) */
9172 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9174 debug(F101,"esctrp caught SIGQUIT","",conesc);
9176 #endif /* SVORPOSIX */
9182 esctrp(foo) int foo; { /* trap console escapes (^\) */
9183 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9185 debug(F101,"esctrp caught SIGQUIT","",conesc);
9192 esctrp(foo) int foo; { /* trap console escapes (^\) */
9194 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9199 #endif /* CK_POLL */
9201 #endif /* FIONREAD */
9203 /* C O N B G T -- Background Test */
9205 static int jc = 0; /* 0 = no job control */
9208 Call with flag == 1 to prevent signal test, which can not be expected
9209 to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
9211 Call with flag == 0 to use the signal test, but only if the process-group
9212 test fails, as it does on some UNIX systems, where getpgrp() is buggy,
9213 requires an argument when the man page says it doesn't, or vice versa.
9215 If flag == 0 and the process-group test fails, then we determine background
9216 status simply (but not necessarily reliably) from isatty().
9218 conbgt() sets the global backgrd = 1 if we appear to be in the background,
9219 and to 0 if we seem to be in the foreground. conbgt() is highly prone to
9223 conbgt(flag) int flag; {
9224 int x = -1, /* process group or SIGINT test */
9225 y = 0; /* isatty() test */
9227 Check for background operation, even if not running on real tty, so that
9228 background flag can be set correctly. If background status is detected,
9229 then Kermit will not issue its interactive prompt or most messages.
9230 If your prompt goes away, you can blame (and fix?) this function.
9233 /* Use process-group test if possible. */
9235 #ifdef POSIX /* We can do it in POSIX */
9238 #ifdef BSD4 /* and in BSD 4.x. */
9241 #ifdef HPUXJOBCTL /* and in most HP-UX's */
9244 #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
9246 #endif /* TIOCGPGRP */
9247 #endif /* HPUXJOBCTL */
9251 #ifdef MIPS /* Except if it doesn't work... */
9261 Semi-reliable process-group test. Check whether this process's group is
9262 the same as the controlling terminal's process group. This works if the
9263 getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
9265 PID_T mypgrp = (PID_T)0; /* Kermit's process group */
9266 PID_T ctpgrp = (PID_T)0; /* The terminal's process group */
9267 #ifndef _POSIX_SOURCE
9269 The getpgrp() prototype is obtained from system header files for POSIX
9270 and Sys V R4 compilations. Other systems, who knows. Some complain about
9271 a duplicate declaration here, others don't, so it's safer to leave it in
9272 if we don't know for certain.
9277 extern PID_T getpgrp();
9279 #endif /* PS2AIX10 */
9281 #endif /* _POSIX_SOURCE */
9283 /* Get my process group. */
9285 #ifdef SVR3 /* Maybe this should be ATTSV? */
9286 /* This function is not described in SVID R2 */
9288 /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
9292 /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
9296 /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
9300 /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
9302 #ifdef OSF32 /* (was OSF40) */
9304 /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
9305 #else /* BSD, V7, etc */
9309 mypgrp = getpgrp(0);
9311 /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
9319 /* MINIX does not support job control so Kermit is always in foreground */
9322 #else /* Not MINIX */
9324 /* Now get controlling tty's process group */
9326 ctpgrp = tcgetpgrp(1); /* The POSIX way */
9327 /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
9329 ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
9330 /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
9331 #endif /* BSD44ORPOSIX */
9333 if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
9334 x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
9335 else x = -1; /* If error, remember. */
9336 debug(F101,"conbgt process group test","",x);
9337 #endif /* PGROUP_T */
9340 /* Try to see if job control is available */
9342 #ifdef NOJC /* User override */
9343 jc = 0; /* No job control allowed */
9344 debug(F111,"NOJC","jc",jc);
9349 #ifdef SVR4ORPOSIX /* POSIX actually tells us */
9350 debug(F100,"SVR4ORPOSIX jc test...","",0);
9351 #ifdef _SC_JOB_CONTROL
9358 jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
9360 debug(F101,"sysconf fails, jcshell","",jcshell);
9361 jc = (jchdlr == SIG_DFL) ? 1 : 0;
9363 debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
9364 #endif /* __386BSD__ */
9365 #endif /* __bsdi__ */
9367 #ifdef _POSIX_JOB_CONTROL
9368 jc = 1; /* By definition */
9369 debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
9371 jc = 0; /* Assume job control not allowed */
9372 debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
9373 #endif /* _POSIX_JOB_CONTROL */
9374 #endif /* _SC_JOB_CONTROL */
9377 jc = 1; /* Job control allowed */
9378 debug(F111,"BSD job control","jc",jc);
9381 jc = 1; /* JC allowed */
9382 debug(F111,"SVR3 job control","jc",jc);
9385 jc = 1; /* JC allowed */
9386 debug(F111,"X/OS job control","jc",jc);
9389 jc = 1; /* JC allowed */
9390 debug(F111,"HP-UX 9.0 job control","jc",jc);
9393 jc = 1; /* JC allowed */
9394 debug(F111,"HP-UX 10.0 job control","jc",jc);
9396 jc = 0; /* JC not allowed */
9397 debug(F111,"job control catch-all","jc",jc);
9403 #endif /* SVR4ORPOSIX */
9406 debug(F101,"conbgt jc","",jc);
9408 debug(F101,"conbgt jcshell","",jcshell);
9410 At this point, if jc == 1 but jcshell == 0, it means that the OS supports
9411 job control, but the shell or other process we are running under does not
9412 (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
9413 will come of it. So...
9416 if (jc > 0 && jcshell == 0) jc = 0;
9420 Another background test.
9421 Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
9422 which is done by the shell (sh) if the program is started with '&'.
9423 Unfortunately, this is NOT done by csh or ksh so watch out!
9424 Note, it's safe to set SIGINT to SIG_IGN here, because further down
9425 we always set it to something else.
9426 Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
9429 if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
9431 SIGTYP (*osigint)();
9433 osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
9435 x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
9436 /* debug(F101,"conbgt osigint","",osigint); */
9437 /* debug(F101,"conbgt signal test","",x); */
9440 /* Also check to see if we're running with redirected stdio. */
9441 /* This is not really background operation, but we want to act as though */
9445 if (inserver) { /* Internet Kermit Server */
9446 backgrd = 0; /* is not in the background */
9451 y = (isatty(0) && isatty(1)) ? 1 : 0;
9452 debug(F101,"conbgt isatty test","",y);
9455 /* The process group and/or signal test doesn't work under these... */
9468 backgrd = (x || !y) ? 1 : 0;
9474 debug(F101,"conbgt backgrd","",backgrd);
9477 /* C O N I N T -- Console Interrupt setter */
9480 First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
9481 Second arg is pointer to function to handle SIGTSTP (suspend).
9484 VOID /* Set terminal interrupt traps. */
9487 conint(f,s) SIGTYP (*f)(), (*s)();
9489 conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
9492 conint(f,s) SIGTYP (*f)(), (*s)();
9493 #endif /* CK_ANSIC */
9496 debug(F101,"conint conistate","",conistate);
9498 conbgt(0); /* Do background test. */
9500 /* Set the desired handlers for hangup and software termination. */
9503 signal(SIGTERM,f); /* Software termination */
9504 #endif /* SIGTERM */
9507 Prior to July 1999 we used to call sighup() here but now it's called in
9508 sysinit() so SIGHUP can be caught during execution of the init file or
9512 /* Now handle keyboard stop, quit, and interrupt signals. */
9513 /* Check if invoked in background -- if so signals set to be ignored. */
9514 /* However, if running under a job control shell, don't ignore them. */
9515 /* We won't be getting any, as we aren't in the terminal's process group. */
9517 debug(F101,"conint backgrd","",backgrd);
9518 debug(F101,"conint jc","",jc);
9520 if (backgrd && !jc) { /* In background, ignore signals */
9521 debug(F101,"conint background ignoring signals, jc","",jc);
9523 signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
9524 #endif /* SIGTSTP */
9525 signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
9526 signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
9528 conistate = CONI_NOI;
9529 } else { /* Else in foreground or suspended */
9530 debug(F101,"conint foreground catching signals, jc","",jc);
9531 signal(SIGINT,f); /* Catch terminal interrupt */
9532 sigint_ign = (f == SIG_IGN) ? 1 : 0;
9534 #ifdef SIGTSTP /* Keyboard stop (suspend) */
9535 /* debug(F101,"conint SIGSTSTP","",s); */
9536 if (s == NULL) s = SIG_DFL;
9537 #ifdef NOJC /* No job control allowed. */
9538 signal(SIGTSTP,SIG_IGN);
9539 #else /* Job control allowed */
9540 if (jc) /* if available. */
9543 signal(SIGTSTP,SIG_IGN);
9545 #endif /* SIGTSTP */
9549 #ifndef FIONREAD /* Watch out, we don't know this... */
9553 signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
9555 #endif /* CK_POLL */
9557 #endif /* FIONREAD */
9558 if (conesc) conesc = 0; /* Clear out pending escapes */
9561 signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
9562 if (conesc) conesc = 0;
9565 signal(SIGQUIT,f); /* Apollo, catch it like others. */
9567 signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
9570 #endif /* SVORPOSIX */
9572 conistate = CONI_INT;
9577 /* C O N N O I -- Reset console terminal interrupts */
9580 connoi() { /* Console-no-interrupts */
9582 debug(F101,"connoi conistate","",conistate);
9584 signal(SIGTSTP,SIG_IGN); /* Suspend */
9585 #endif /* SIGTSTP */
9586 conint(SIG_IGN,SIG_IGN); /* Interrupt */
9587 sigint_ign = 1; /* Remember we did this ourselves */
9589 signal(SIGQUIT,SIG_IGN); /* Quit */
9590 #endif /* SIGQUIT */
9592 signal(SIGTERM,SIG_IGN); /* Term */
9593 #endif /* SIGTERM */
9594 conistate = CONI_NOI;
9597 /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */
9601 Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
9602 eliminates blocking on a read, because we can read /dev/kmem to get the
9603 number of characters available for raw input. If your system can't
9604 or you won't let the world read /dev/kmem then you must figure out a
9605 different way to do the counting of characters available, or else replace
9606 this by a dummy function that always returns 0.
9609 * Call this routine as: initrawq(tty)
9610 * where tty is the file descriptor of a terminal. It will return
9611 * (as a char *) the kernel-mode memory address of the rawq character
9612 * count, which may then be read. It has the side-effect of flushing
9613 * input on the terminal.
9616 * John Mackin, Physiology Dept., University of Sydney (Australia)
9617 * ...!decvax!mulga!physiol.su.oz!john
9619 * Permission is hereby granted to do anything with this code, as
9620 * long as this comment is retained unmodified and no commercial
9621 * advantage is gained.
9627 #include <sys/proc.h>
9628 #endif /* COHERENT */
9634 #include <sys/proc.h>
9635 #endif /* COHERENT */
9638 initrawq(tty) int tty; {
9652 static struct nlist nl[] = {
9657 static struct proc *pp;
9661 NPTYPE xproc; /* Its type is defined in makefile. */
9665 if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
9666 nlist(BOOTNAME, nl);
9667 if (nl[0].n_type == 0) err("proc array");
9669 if (nl[1].n_type == 0) err("nproc");
9671 lseek(m, (long)(nl[1].n_value), 0);
9672 read (m, &xproc, sizeof(xproc));
9673 saval = signal(SIGALRM, catch);
9674 if ((pid = fork()) == 0) {
9680 if(setjmp(jjbuf) == 0) {
9684 signal(SIGALRM, SIG_DFL);
9687 pp = (struct proc *) nl[0].n_value;
9689 if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
9690 if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
9692 lseek(m, (long)(nl[1].n_value), 0);
9693 read(m, &xproc, sizeof(xproc));
9695 if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
9696 if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
9697 if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
9698 err("read proc table");
9699 for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
9700 if (pp -> p_pid == (short) pid) goto iout;
9702 err("no such proc");
9706 qaddr = (char *)(pp -> p_wchan);
9717 /* More V7-support functions... */
9723 ckmakmsg(buf,200,"fatal error in initrawq: ", s, NULL, NULL);
9729 catch(foo) int foo; {
9734 /* G E N B R K -- Simulate a modem break. */
9748 genbrk(fn,msec) int fn, msec; {
9749 struct sgttyb ttbuf;
9750 int ret, sospeed, x, y;
9752 ret = ioctl(fn, TIOCGETP, &ttbuf);
9753 sospeed = ttbuf.sg_ospeed;
9754 ttbuf.sg_ospeed = BSPEED;
9755 ret = ioctl(fn, TIOCSETP, &ttbuf);
9756 y = (int)strlen(brnuls);
9757 x = ( BSPEED * 100 ) / msec;
9759 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9760 ttbuf.sg_ospeed = sospeed;
9761 ret = ioctl(fn, TIOCSETP, &ttbuf);
9762 ret = write(fn, "@", 1);
9769 genbrk(fn,msec) int fn, msec; {
9770 struct termios ttbuf;
9774 ret = tcgetattr(fn, &ttbuf);
9775 sospeed = ttbuf.c_ospeed;
9776 ttbuf.c_ospeed = BSPEED;
9777 ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
9778 y = (int)strlen(brnuls);
9779 x = ( BSPEED * 100 ) / msec;
9781 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9782 ttbuf.c_ospeed = sospeed;
9783 ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
9784 ret = write(fn, "@", 1);
9791 I N C H K -- Check if chars waiting to be read on given file descriptor.
9793 This routine is a merger of ttchk() and conchk().
9795 channel == 0 to check console.
9796 channel == 1 to check communications connection.
9798 fd = file descriptor.
9800 >= 0: number of characters waiting, 0 or greater,
9801 -1: on any kind of error,
9802 -2: if there is (definitely) no connection.
9803 Note: In UNIX we don't have to call nettchk() because a socket
9804 file descriptor works just like in serial i/o, ioctls and all.
9805 (But this will change if we add non-file-descriptor channels,
9806 such as IBM X.25 for AIX...)
9809 in_chk(channel, fd) int channel, fd; {
9810 int x, n = 0; /* Workers, n = return value */
9811 extern int clsondisc; /* Close on disconnect */
9813 The first section checks to make sure we have a connection,
9814 but only if we're in local mode.
9818 debug(F111,"in_chk entry",ckitoa(fd),channel);
9819 debug(F101,"in_chk ttyfd","",ttyfd);
9820 debug(F101,"in_chk ttpty","",ttpty);
9824 But don't say connection is gone if we have any buffered-stuff.
9827 debug(F101,"in_chk ttpush","",ttpush);
9835 #endif /* TTLEBUF */
9839 /* Special handling for HP-UX pty i/o */
9840 if (ttpty && pty_trap_pending(ttyfd) > 0) {
9841 if (pty_trap_handler(ttyfd) > 0) {
9846 #endif /* HAVE_PTYTRAP */
9849 if (channel) { /* Checking communications channel */
9850 if (ttyfd < 0) { /* No connection */
9851 return(-2); /* That's what this means */
9852 } else if (xlocal && /* In local mode */
9853 (!netconn /* Serial connection or */
9855 || istncomport() /* Telnet Com Port */
9856 #endif /* TN_COMPORT */
9857 ) && ttcarr != CAR_OFF /* with CARRIER WATCH ON (or AUTO) */
9861 Seems like this would be a good idea but it prevents C-Kermit from
9862 popping back to the prompt automatically when carrier drops. However,
9863 commenting this out prevents us from seeing the NO CARRIER message.
9866 && my_count < 1 /* Nothing in our internal buffer */
9868 #endif /* COMMENT */
9871 x = ttgmdm(); /* So get modem signals */
9872 debug(F101,"in_chk close-on-disconnect","",clsondisc);
9873 if (x > -1) { /* Check for carrier */
9874 if (!(x & BM_DCD)) { /* No carrier */
9875 debug(F101,"in_chk carrier lost","",x);
9876 if (clsondisc) /* If "close-on-disconnect" */
9877 ttclos(0); /* close device & release lock. */
9878 return(-2); /* This means "disconnected" */
9880 /* In case I/O to device after CD dropped always fails */
9881 /* as in Debian Linux 2.1 and Unixware 2.1... */
9883 debug(F101,"in_chk ttgmdm I/O error","",errno);
9884 debug(F101,"in_chk ttgmdm gotsigs","",gotsigs);
9885 if (gotsigs) { /* If we got signals before... */
9886 if (errno == 5 || errno == 6) { /* I/O error etc */
9887 if (clsondisc) /* like when modem hangs up */
9892 /* If we never got modem signals successfully on this */
9893 /* connection before, we can't conclude that THIS failure */
9894 /* means the connection was lost. */
9900 /* We seem to have a connection so now see if any bytes are waiting on it */
9903 if (ssl_active_flag || tls_active_flag) {
9904 n += SSL_pending(ssl_active_flag?ssl_con:tls_con);
9905 debug(F101,"in_chk SSL_pending","",n);
9916 /* It is not safe to read any data when using encrypted Klogin */
9917 if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
9919 if (ttnproto == NP_EK4LOGIN) {
9920 n += krb4_des_avail(ttyfd);
9921 debug(F101,"in_chk krb4_des_avail","",n);
9925 if (ttnproto == NP_EK5LOGIN) {
9926 n += krb5_des_avail(ttyfd);
9927 debug(F101,"in_chk krb5_des_avail","",n);
9930 if (ttnproto == NP_K5U2U) {
9931 n += krb5_u2u_avail(ttyfd);
9932 debug(F101,"in_chk krb5_des_avail","",n);
9934 #endif /* KRB5_U2U */
9936 if (n < 0) /* Is this right? */
9941 #endif /* CK_KERBEROS */
9942 #endif /* RLOGCODE */
9944 errno = 0; /* Reset this so we log good info */
9946 x = ioctl(fd, FIONREAD, &n); /* BSD and lots of others */
9947 #ifdef DEBUG /* (the more the better) */
9949 debug(F101,"in_chk FIONREAD return code","",x);
9950 debug(F101,"in_chk FIONREAD count","",n);
9951 debug(F101,"in_chk FIONREAD errno","",errno);
9954 #else /* FIONREAD not defined */
9956 Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
9957 with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
9958 portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
9959 that I looked at, but it is needed to prevent the call from blocking), and
9960 the msghdr struct differs from place to place, so we would need another
9961 avalanche of ifdefs. Still, when FIONREAD is not available, this is the
9962 only other known method of asking the OS for the *number* of characters
9963 available for reading.
9965 #ifdef V7 /* UNIX V7: look in kernel memory */
9967 n = 0; /* But not in MINIX */
9972 lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
9973 x = read(kmem[TTY], &n, sizeof(int));
9974 if (x != sizeof(int))
9980 x = ioctl(fd, TIOCQCNT, &ttbuf); /* DEC Pro/3xx Venix V.1 */
9981 n = ttbuf.sg_ispeed & 0377; /* Circa 1984 */
9986 Here we skip all the undependable and expensive calls below if we
9987 already have something in our internal buffer. This tends to work quite
9988 nicely, so the only really bad case remaining is the one in which neither
9989 FIONREAD or MYREAD are defined, which is increasingly rare these days.
9991 if (channel != 0 && my_count > 0) {
9992 debug(F101,"in_chk buf my_count","",my_count);
9993 n = my_count; /* n was 0 before we got here */
9998 rdchk(), select(), and poll() tell us *if* data is available to be read, but
9999 not how much, so these should be used only as a final resort. Especially
10000 since these calls tend to add a lot overhead.
10002 #ifdef RDCHK /* This mostly SCO-specific */
10004 debug(F101,"in_chk rdchk","",n);
10005 #else /* No RDCHK */
10008 /* Only allows select on the console ... don't ask */
10012 fd_set rfds; /* Read file descriptors */
10014 FD_ZERO(rfds); /* Initialize them */
10015 FD_SET(fd,rfds); /* We want to look at this fd */
10017 FD_ZERO(&rfds); /* Initialize them */
10018 FD_SET(fd,&rfds); /* We want to look at this fd */
10019 tv.tv_sec = tv.tv_usec = 0L; /* A 0-valued timeval structure */
10020 #endif /* BELLV10 */
10022 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10023 debug(F101,"in_chk Plan 9 select","",n);
10026 n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
10027 debug(F101,"in_chk BELLV10 select","",n);
10030 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10031 debug(F101,"in_chk BSD44 select","",n);
10034 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10035 debug(F101,"in_chk BSD43 select","",n);
10038 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10039 debug(F101,"in_chk SOLARIS select","",n);
10042 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10043 debug(F101,"in_chk QNX6 select","",n);
10046 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10047 debug(F101,"in_chk QNX select","",n);
10050 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10051 debug(F101,"in_chk COHERENT select","",n);
10054 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10055 debug(F101,"in_chk SVR4 select","",n);
10058 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10059 debug(F101,"in_chk LINUX select","",n);
10061 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10062 debug(F101,"in_chk OSF select","",n);
10064 n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
10065 debug(F101,"in_chk catchall select","",n);
10067 #endif /* __linux__ */
10069 #endif /* COHERENT */
10072 #endif /* SOLARIS */
10075 #endif /* BELLV10 */
10078 #else /* Not SELECT */
10084 pfd.events = POLLIN;
10086 n = poll(&pfd, 1, 0);
10087 debug(F101,"in_chk poll","",n);
10088 if ((n > 0) && (pfd.revents & POLLIN))
10091 #endif /* CK_POLL */
10092 #endif /* SELECT */
10094 #endif /* PROVX1 */
10096 #endif /* FIONREAD */
10098 /* From here down, treat console and communication device differently... */
10100 if (channel == 0) { /* Console */
10108 This is the hideous hack used in System V and POSIX systems that don't
10109 support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
10110 CONNECT-mode escape character is attached to SIGQUIT. Used, obviously,
10111 only on the console.
10113 if (conesc) { /* Escape character typed == SIGQUIT */
10114 debug(F100,"in_chk conesc","",conesc);
10116 signal(SIGQUIT,esctrp); /* Restore signal */
10120 #endif /* CK_POLL */
10121 #endif /* SELECT */
10122 #endif /* FIONREAD */
10123 #endif /* SVORPOSIX */
10125 return(n); /* Done with console */
10128 if (channel != 0) { /* Communications connection */
10133 select() or rdchk(), etc, has told us that something is waiting, but we
10134 don't know how much. So we do a read to get it and then we know. Note:
10135 This read is NOT nonblocking if nothing is there (because of VMIN=1), but
10136 it should be safe in this case since the OS tells us at least one byte is
10137 waiting to be read, and MYREAD reads return as much as is there without
10138 waiting for any more. Controlled tests on Solaris and Unixware (with
10139 FIONREAD deliberately undefined) show this to be true.
10141 debug(F101,"in_chk read my_count","",my_count);
10142 debug(F101,"in_chk read n","",n);
10143 if (n > 0 && my_count == 0) {
10144 /* This also catches disconnects etc */
10145 /* Do what mygetbuf does except don't grab a character */
10146 my_count = myfillbuf();
10147 my_item = -1; /* ^^^ */
10148 debug(F101,"in_chk myfillbuf my_count","",my_count);
10152 n = 0; /* NB: n is replaced by my_count */
10154 #endif /* FIONREAD */
10156 Here we add whatever we think is unread to what is still in our
10157 our internal buffer. Thus the importance of setting n to 0 just above.
10159 debug(F101,"in_chk my_count","",my_count);
10160 debug(F101,"in_chk n","",n);
10163 #endif /* MYREAD */
10165 debug(F101,"in_chk result","",n);
10167 /* Errors here don't prove the connection has dropped so just say 0 */
10169 return(n < 0 ? 0 : n);
10173 /* T T C H K -- Tell how many characters are waiting in tty input buffer */
10182 #endif /* NETCMD */
10184 return(in_chk(1,fd));
10187 /* T T X I N -- Get n characters from tty input buffer */
10189 /* Returns number of characters actually gotten, or -1 on failure */
10191 /* Intended for use only when it is known that n characters are actually */
10192 /* Available in the input buffer. */
10195 ttxin(n,buf) int n; CHAR *buf; {
10196 register int x = 0, c = -2;
10198 register int i = 0;
10199 #endif /* TTLEBUF */
10202 if (n < 1) /* Nothing to do */
10207 buf[0] = ttpush; /* Put pushed char in buffer*/
10208 ttpush = -1; /* Clear the push buffer */
10210 return(ttxin(n-1, &buf[1]) + 1);
10215 while (le_inbuf() > 0) {
10216 if (le_getchar(&buf[i])) {
10222 return(ttxin(n,&buf[i])+i);
10226 #endif /* TTLEBUF */
10232 #endif /* NETCMD */
10236 if (netconn && (ttnet == NET_SX25)) /* X.25 connection */
10237 return(x25xin(n,buf));
10238 #endif /* SUNX25 */
10241 /* riehm: possibly not needed. Test worked with normal reads and writes */
10242 if (netconn && (ttnet == NET_IX25)) { /* X.25 connection */
10244 if (x > 0) buf[x] = '\0';
10247 #endif /* IBMX25 */
10250 debug(F101,"ttxin MYREAD","",n);
10254 debug(F101,"ttxin myread returns","",c);
10255 if (c == -3) x = -1;
10258 buf[x++] = c & ttpmsk;
10261 /* It is impossible to know how many characters are waiting */
10262 /* to be read when you are using Encrypted Rlogin or SSL */
10263 /* as the transport since the number of real data bytes */
10264 /* can be greater or less than the number of bytes on the */
10265 /* wire which is what ttchk() returns. */
10266 if (netconn && (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN))
10269 #endif /* CK_KERBEROS */
10270 #endif /* RLOGCODE */
10272 if (ssl_active_flag || tls_active_flag)
10275 #endif /* CK_SSL */
10278 debug(F101,"ttxin READ","",n);
10279 x = read(fd,buf,n);
10280 for (c = 0; c < n; c++) /* Strip any parity */
10282 #endif /* MYREAD */
10284 debug(F101,"ttxin x","",x); /* Done */
10285 if (x > 0) buf[x] = '\0';
10290 /* T T O L -- Write string s, length n, to communication device. */
10293 >= 0 on success, number of characters actually written.
10296 #ifdef CK_ENCRYPTION
10297 CHAR * xpacket = NULL;
10299 #endif /* CK_ENCRYPTION */
10303 ttol(s,n) int n; CHAR *s; {
10304 int x, len, tries, fd;
10306 extern int dblflag; /* For SET SEND DOUBLE-CHARACTER */
10307 extern short dblt[];
10308 CHAR *p = NULL, *p2, *s2, c;
10310 #endif /* CKXXCHAR */
10312 if (ttyfd < 0) /* Not open? */
10316 /* debug(F101,"ttol ttyfd","",ttyfd); */
10317 ckhexdump("ttol s",s,n);
10325 #endif /* NETCMD */
10329 /* Double any characters that must be doubled. */
10330 debug(F101,"ttol dblflag","",dblflag);
10332 p = (CHAR *) malloc(n + n + 1);
10341 if (dblt[(unsigned) c] & 2) {
10351 ckhexdump("ttol doubled s",s,n);
10354 #endif /* CKXXCHAR */
10356 tries = TTOLMAXT; /* Allow up to this many tries */
10357 len = n; /* Remember original length */
10359 #ifdef CK_ENCRYPTION
10361 This is to avoid encrypting a packet that is already encrypted, e.g.
10362 when we resend a packet directly out of the packet buffer, and also to
10363 avoid encrypting a constant (literal) string, which can cause a memory
10366 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
10368 if (nxpacket < n) {
10374 x = n > 10240 ? n : 10240;
10375 xpacket = (CHAR *)malloc(x);
10377 fprintf(stderr,"ttol malloc failure\n");
10382 memcpy((char *)xpacket,(char *)s,n);
10384 ck_tn_encrypt((char *)s,n);
10386 #endif /* CK_ENCRYPTION */
10390 #ifdef CK_ENCRYPTION
10391 /* keep trying if we are encrypting */
10392 || TELOPT_ME(TELOPT_ENCRYPTION)
10393 #endif /* CK_ENCRYPTION */
10394 )) { /* Be persistent */
10395 debug(F101,"ttol try","",TTOLMAXT - tries);
10397 if (netconn && !ttpipe && !ttpty)
10398 x = nettol((char *)s,n); /* Write string to device */
10400 #endif /* BEOSORBEBOX */
10402 if (ttnet == NET_IX25)
10404 * this is a more controlled way of writing to X25
10405 * STREAMS, however write should also work!
10407 x = x25write(ttyfd, s, n);
10409 #endif /* IBMX25 */
10411 if (ssl_active_flag || tls_active_flag) {
10413 /* Write using SSL */
10415 if (ssl_active_flag)
10416 x = SSL_write(ssl_con, s, n);
10418 x = SSL_write(tls_con, s, n);
10419 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
10420 case SSL_ERROR_NONE:
10426 case SSL_ERROR_WANT_WRITE:
10427 case SSL_ERROR_WANT_READ:
10430 case SSL_ERROR_SYSCALL:
10433 case SSL_ERROR_WANT_X509_LOOKUP:
10434 case SSL_ERROR_SSL:
10435 case SSL_ERROR_ZERO_RETURN:
10441 #endif /* CK_SSL */
10445 if (ttnproto == NP_EK4LOGIN) {
10446 return(krb4_des_write(ttyfd,s,n));
10448 #endif /* RLOGCODE */
10452 if (ttnproto == NP_EK5LOGIN) {
10453 return(krb5_des_write(ttyfd,(char *)s,n,0));
10455 #endif /* RLOGCODE */
10457 if (ttnproto == NP_K5U2U) {
10458 return(krb5_u2u_write(ttyfd,(char *)s,n));
10460 #endif /* KRB5_U2U */
10462 #endif /* CK_KERBEROS */
10463 x = write(fd,s,n); /* Write string to device */
10465 if (x == n) { /* Worked? */
10466 debug(F101,"ttol ok","",x); /* OK */
10469 #endif /* CKXXCHAR */
10470 return(len); /* Done */
10471 } else if (x < 0) { /* No, got error? */
10472 debug(F101,"ttol write error","",errno);
10474 if (errno == EWOULDBLOCK) {
10478 #endif /* EWOULDBLOCK */
10480 if (netconn && ttnet == NET_TCPB) {
10481 debug(F101,"ttol TCP error","",errno);
10482 ttclos(0); /* Close the connection. */
10485 #endif /* TCPSOCKET */
10488 #endif /* CKXXCHAR */
10490 } else { /* No error, so partial success */
10491 debug(F101,"ttol partial","",x); /* This never happens */
10492 s += x; /* Point to part not written yet */
10493 n -= x; /* Adjust length */
10494 if (x > 0) msleep(10); /* Wait 10 msec */
10495 } /* Go back and try again */
10499 #endif /* CKXXCHAR */
10500 return(n < 1 ? len : -1); /* Return the results */
10503 /* T T O C -- Output a character to the communication line */
10506 This function should only be used for interactive, character-mode operations,
10507 like terminal connection, script execution, dialer i/o, where the overhead
10508 of the signals and alarms does not create a bottleneck.
10515 #endif /* CK_ANSIC */
10517 #define TTOC_TMO 15 /* Timeout in case we get stuck */
10520 if (ttyfd < 0) /* Check for not open. */
10527 #endif /* NETCMD */
10531 /* debug(F101,"ttoc","",(CHAR) c); */
10532 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10533 xx = alarm(TTOC_TMO); /* for this many seconds. */
10534 if (xx < 0) xx = 0; /* Save old alarm value. */
10535 /* debug(F101,"ttoc alarm","",xx); */
10537 #ifdef CK_POSIX_SIG
10541 #endif /* CK_POSIX_SIG */
10542 ) { /* Timer went off? */
10543 ttimoff(); /* Yes, cancel this alarm. */
10544 if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
10545 /* debug(F100,"ttoc timeout","",0); */
10548 #endif /* NETCONN */
10549 debug(F101,"ttoc timeout","",c);
10550 if (ttflow == FLO_XONX) {
10551 debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
10554 /* POSIX way to unstick. */
10555 debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
10557 #ifdef BSD4 /* Berkeley way to do it. */
10559 /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);". Who knows? */
10562 debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
10564 #endif /* TIOCSTART */
10566 /* Is there a Sys V way to do this? */
10572 #endif /* NETCONN */
10573 return(-1); /* Return failure code. */
10578 if (netconn && !ttpipe && !ttpty)
10581 #endif /* BEOSORBEBOX */
10582 #endif /* NETCONN */
10583 #ifdef CK_ENCRYPTION
10584 if (TELOPT_ME(TELOPT_ENCRYPTION))
10585 ck_tn_encrypt(&c,1);
10586 #endif /* CK_ENCRYPTION */
10588 /* riehm: maybe this isn't necessary after all. Test program
10589 * worked fine with data being sent and retrieved with normal
10590 * read's and writes!
10592 if (ttnet == NET_IX25)
10593 rc = x25write(ttyfd,&c,1); /* as above for X25 streams */
10595 #endif /* IBMX25 */
10597 if (ssl_active_flag || tls_active_flag) {
10599 /* Write using SSL */
10600 if (ssl_active_flag)
10601 rc = SSL_write(ssl_con, &c, 1);
10603 rc = SSL_write(tls_con, &c, 1);
10604 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)){
10605 case SSL_ERROR_NONE:
10607 case SSL_ERROR_WANT_WRITE:
10608 case SSL_ERROR_WANT_READ:
10611 case SSL_ERROR_SYSCALL:
10614 case SSL_ERROR_WANT_X509_LOOKUP:
10615 case SSL_ERROR_SSL:
10616 case SSL_ERROR_ZERO_RETURN:
10622 #endif /* CK_SSL */
10626 if (ttnproto == NP_EK4LOGIN) {
10627 rc = (krb4_des_write(ttyfd,(char *)&c,1) == 1);
10629 #endif /* RLOGCODE */
10633 if (ttnproto == NP_EK5LOGIN) {
10634 rc = (krb5_des_write(ttyfd,&c,1,0) == 1);
10636 #endif /* RLOGCODE */
10638 if (ttnproto == NP_K5U2U) {
10639 rc = (krb5_u2u_write(ttyfd,&c,1) == 1);
10641 #endif /* KRB5_U2U */
10643 #endif /* CK_KERBEROS */
10644 rc = write(fd,&c,1); /* Try to write the character. */
10645 if (rc < 1) { /* Failed */
10646 ttimoff(); /* Turn off the alarm. */
10647 alarm(xx); /* Restore previous alarm. */
10648 debug(F101,"ttoc errno","",errno); /* Log the error, */
10649 return(-1); /* and return the error code. */
10652 ttimoff(); /* Success, turn off the alarm. */
10653 alarm(xx); /* Restore previous alarm. */
10654 return(0); /* Return good code. */
10657 /* T T I N L -- Read a record (up to break character) from comm line. */
10659 Reads up to "max" characters from the connection, terminating on:
10660 (a) the packet length field if the "turn" argument is zero, or
10661 (b) on the packet-end character (eol) if the "turn" argument is nonzero
10662 (c) a certain number of Ctrl-C's in a row
10665 >= 0, the number of characters read upon success;
10666 -1 if "max" exceeded, timeout, or other correctable error;
10667 -2 on user interruption (c);
10668 -3 on fatal error like connection lost.
10670 The name of this routine dates from the early days when Kermit packets
10671 were, indeed, always lines of text. That was before control-character
10672 unprefixing and length-driven packet framing were introduced, which this
10673 version handle. NB: this routine is ONLY for reading incoming Kermit
10674 packets, nothing else. To read other kinds of incoming material, use
10675 ttinc() or ttxin().
10677 The bytes that were input are copied into "dest" with their parity bits
10678 stripped if parity was selected. Returns the number of bytes read.
10679 Bytes after the eol are available upon the next call to this function.
10681 The idea is to minimize the number of system calls per packet, and also to
10682 minimize timeouts. This function is the inner loop of the protocol and must
10683 be as efficient as possible. The current strategy is to use myread(), a
10684 macro to manage buffered (and generally nonblocking) reads.
10686 WARNING: This function calls parchk(), which is defined in another module.
10687 Normally, ckutio.c does not depend on code from any other module, but there
10688 is an exception in this case because all the other ck?tio.c modules also
10689 need to call parchk(), so it's better to have it defined in a common place.
10694 #define CTRLC '\03'
10696 We have four different declarations here because:
10697 (a) to allow Kermit to be built without the automatic parity sensing feature
10698 (b) one of each type for ANSI C, one for non-ANSI.
10702 static int pushedback = 0;
10707 ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
10709 ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
10710 #endif /* CK_ANSIC */
10711 #else /* not PARSENSE */
10713 ttinl(CHAR *dest, int max,int timo, CHAR eol)
10715 ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
10716 #endif /* CK_ANSIC */
10717 #endif /* PARSENSE */
10722 #endif /* MYREAD */
10727 #endif /* PARSENSE */
10729 int sopmask = 0xff; /* Start-Of-Packet mask */
10731 extern short dblt[]; /* Ignore-character table */
10732 extern int ignflag;
10733 #endif /* CKXXCHAR */
10736 #endif /* TCPSOCKET */
10739 extern int streaming;
10741 #endif /* STREAMING */
10743 if (ttyfd < 0) return(-3); /* Not open. */
10745 In February 2007 I fixed ttinl() to work better under the truly awful
10746 conditions encountered by the AM-APEX oceanographic floats that gather
10747 hurricane data and phone home using Iridium satellite modems, which under
10748 certain conditions, can send two packets back to back after a long pause.
10749 In this case the second packet would be ignored because the SOH was skipped
10750 due to the ttflui() call. But the reworked lookahead/pushback logic broke
10751 Kermit transfers on encrypted connections. This was fixed 12-13 August
10752 2007. All of this happened after 8.0.212 Dev.27 was released and before
10753 Dev.28, so no harm done other than the delay.
10755 debug(F101,"ttinl max","",max);
10756 debug(F101,"ttinl timo","",timo);
10762 #endif /* NETCMD */
10766 if (xlocal && conchk() > 0) /* Allow for console interruptions */
10768 #endif /* COMMENT */
10770 *dest = '\0'; /* Clear destination buffer */
10771 if (timo < 0) timo = 0; /* Safety */
10772 if (timo) { /* Don't time out if timo == 0 */
10774 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10775 xx = alarm(timo); /* Set it. */
10776 debug(F101,"ttinl alarm","",xx);
10779 #ifdef CK_POSIX_SIG
10783 #endif /* CK_POSIX_SIG */
10784 ) { /* Timer went off? */
10785 debug(F100,"ttinl timout","",0); /* Get here on timeout. */
10786 /* debug(F110," with",(char *) dest,0); */
10787 ttimoff(); /* Turn off timer */
10788 return(-1); /* and return error code. */
10790 register int i, n = -1; /* local variables */
10793 register int flag = 0;
10794 debug(F000,"ttinl start","",start);
10795 #endif /* PARSENSE */
10797 ttpmsk = ttprty ? 0177 : 0377; /* Set parity stripping mask. */
10798 sopmask = needpchk ? 0177 : ttpmsk; /* And SOP matching mask. */
10800 /* Now read into destination, stripping parity and looking for the */
10801 /* the packet terminator, and also for several Ctrl-C's typed in a row. */
10803 i = 0; /* Destination index */
10804 debug(F101,"ttinl eol","",eol);
10806 while (i < max-1) {
10809 /* On encrypted connections myread returns encrypted bytes */
10811 debug(F000,"TTINL myread char","",n);
10812 if (n < 0) { /* Timeout or i/o error? */
10815 debug(F101,"ttinl myread failure, n","",n);
10816 debug(F101,"ttinl myread errno","",errno);
10819 /* Don't let EINTR break packets. */
10821 if (errno == EINTR && i > 0) {
10822 debug(F111,"ttinl EINTR myread i","continuing",i);
10825 debug(F110,"ttinl non-EINTR -3","closing",0);
10827 ttimoff(); /* Turn off timer */
10831 } else if (n == -2 && netconn /* && timo == 0 */ ) {
10832 /* Here we try to catch broken network connections */
10833 /* even when ioctl() and read() do not catch them */
10834 debug(F111,"ttinl network myread failure","closing",n);
10841 /* Streaming and no data to read */
10842 else if (n == 0 && streaming && sndtyp == 'D')
10844 #endif /* STREAMING */
10845 break; /* Break out of while loop */
10848 #else /* not MYREAD (is this code used anywhere any more?) */
10850 The non-MYREAD code dates from the 1980s and was needed on certain platforms
10851 where there were no nonblocking reads. -fdc, 2007/02/22.
10853 if ((n = read(fd, &n, 1)) < 1)
10854 break; /* Error - break out of while loop */
10856 #endif /* MYREAD */
10858 /* Get here with char in n */
10860 #ifdef CK_ENCRYPTION
10861 if (TELOPT_U(TELOPT_ENCRYPTION) && !pushedback) {
10863 ck_tn_decrypt((char *)&ch,1);
10865 debug(F000,"TTINL decryp char","",n);
10868 #endif /* CK_ENCRYPTION */
10871 if (n == IAC && /* Handle Telnet options */
10872 ((xlocal && netconn && IS_TELNET()) ||
10873 (!xlocal && sstelnet))) {
10880 #endif /* NOPARSEN */
10881 if (n != 255) /* No data - go back for next char */
10883 } /* Quoted IAC - keep going */
10884 #endif /* TCPSOCKET */
10888 if (dblt[(unsigned) n] & 1) /* Character to ignore? */
10890 #endif /* CKXXCHAR */
10892 Use parity mask, rather than always stripping parity, to check for
10893 cancellation. Otherwise, runs like \x03\x83\x03 in a packet could cancel
10894 the transfer when parity is NONE. (Note that \x03\x03\x03 is extremely
10895 unlikely due to run-length encoding.)
10897 /* Check cancellation */
10898 if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
10899 if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
10900 if (timo) { /* Clear timer. */
10904 printf("^%c...\r\n",(char)(xfrchr+64));
10906 printf("Canceled...\r\n");
10909 } else ccn = 0; /* No cancellation, reset counter, */
10913 Restructured code allows for a new packet to appear somewhere in the
10914 middle of a previous one. -fdc, 24 Feb 2007.
10916 if ((n & sopmask) == start) { /* Start of Packet */
10917 debug(F101,"ttinl SOP i","",i);
10918 flag = 1; /* Flag that we are in a packet */
10919 havelen = 0; /* Invalidate previous length */
10920 pktlen = -1; /* (if any) in case we were */
10921 lplen = 0; /* alread processand a packet */
10922 i = 0; /* and reset the dest buffer pointer */
10924 if (flag == 0) { /* No SOP yet... */
10925 debug(F000,"ttinl skipping","",n);
10928 dest[i++] = n & ttpmsk;
10930 If we have not been instructed to wait for a turnaround character, we can go
10931 by the packet length field. If turn != 0, we must wait for the end of line
10932 (eol) character before returning. This is an egregious violation of all
10933 principles of layering... (Less egregious in C-Kermit 9.0, in which we go
10934 by the length field but also look for the eol in case it arrives early,
10935 e.g. if the length field was corrupted upwards.)
10939 if ((dest[1] & 0x7f) < 32) /* Garbage in length field */
10940 return(-1); /* fdc - 13 Apr 2010 */
10941 pktlen = xunchar(dest[1] & 0x7f);
10942 if (pktlen > 94) /* Rubout in length field */
10943 return(-1); /* fdc - 13 Apr 2010 */
10946 debug(F101,"ttinl pktlen value","",pktlen);
10948 } else if (i == 5 && pktlen == 0) {
10949 lplen = xunchar(dest[4] & 0x7f);
10950 } else if (i == 6 && pktlen == 0) {
10951 pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
10953 debug(F101,"ttinl extended length","",pktlen);
10958 Suppose we looked at the sequence number here and found it was out of
10959 range? This would mean either (a) incoming packets had SOP unprefixed
10960 and we are out of sync, or (b) the packet is damaged. Since (a) is bad
10961 practice, let's ignore it. So what should we do here if we know the
10964 1. Nothing -- keep trying to read the packet till we find what we think
10965 is the end, or we time out, and let the upper layer decide what to
10966 do. But since either the packet is corrupt or we are out of sync,
10967 our criterion for finding the end does not apply and we are likely
10968 to time out (or swallow a piece of the next packet) if our assumed
10969 length is too long. (This was the behavior prior to version 7.0.)
10971 2. set flag = 0 and continue? This would force us to wait for the
10972 next packet to come in, and therefore (in the nonwindowing case),
10973 would force a timeout in the other Kermit.
10975 3. set flag = 0 and continue, but only if the window size is > 1 and
10976 the window is not blocked? Talk about cheating!
10978 4. Return a failure code and let the upper layer decide what to do.
10979 This should be equivalent to 3, but without the cheating. So let's
10980 do it that way... But note that we must ignore the parity bit
10981 in case this is the first packet and we have not yet run parchk().
10983 if (i == 3) { /* Peek at sequence number */
10984 x = xunchar((dest[i-1] & 0x7f)); /* If it's not in range... */
10985 if (x < 0 || x > 63) {
10986 debug(F111,"ttinl bad seq",dest,x);
10987 if (timo) ttimoff();
10988 return(-1); /* return a nonfatal error */
10992 #else /* PARSENSE */
10993 dest[i++] = n & ttpmsk;
10994 #endif /* PARSENSE */
10996 /* Check for end of packet */
10999 ((n & ttpmsk) == eol) /* Always break on the eol char */
11001 || /* fdc - see notes of 13 Apr 2010 */
11003 Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
11004 This allows packet terminators and handshake characters to appear
11005 literally inside a packet data field.
11007 (havelen && (i > pktlen+1) &&
11008 (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
11010 #endif /* PARSENSE */
11013 Here we have either read the last byte of the packet based on its length
11014 field, or else we have read the packet terminator (eol) or the half-duplex
11015 line-turnaround char (turn).
11018 debug(F101,"ttinl got eol","",eol); /* (or turn) */
11019 dest[i] = '\0'; /* Yes, terminate the string, */
11020 /* debug(F101,"ttinl i","",i); */
11022 #else /* PARSENSE */
11026 if ((n & ttpmsk) != eol) {
11027 debug(F101,"ttinl EOP length","",pktlen);
11028 debug(F000,"ttinl EOP current char","",n);
11029 debug(F101,"ttinl EOP packet buf index","",i);
11030 } else debug(F101,"ttinl got eol","",eol);
11036 The packet was read based on its length. This leaves the packet terminator
11037 unread, and so ttchk() will always return at least 1 because of this,
11038 possibly giving a false positive to the "is there another packet waiting?"
11039 test. But if we know the terminator (or any other interpacket junk) is
11040 there, we can safely get rid of it.
11042 NOTE: This code reworked to (a) execute even if the debug log isn't active;
11043 and (b) actually work. -fdc, 2007/02/22. And again 2007/08/12-13 to also
11044 work on encrypted connections.
11046 debug(F101,"TTINL my_count","",my_count);
11047 if ((n & ttpmsk) != eol) { /* Not the packet terminator */
11049 while (my_count > 0) {
11050 x = myread(); /* (was ttinc(0) */
11051 debug(F000,"TTINL lkread char","",x);
11052 #ifdef CK_ENCRYPTION
11053 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11055 ck_tn_decrypt((char *)&ch,1);
11057 debug(F000,"TTINL lkdecr char","",x);
11059 #endif /* CK_ENCRYPTION */
11061 Note: while it might seem more elegant to simply
11062 push back the encrypted byte, that desynchronizes
11063 the decryption stream; the flag is necessary so we
11064 don't try to decrypt the same byte twice.
11066 if ((x & ttpmsk) == start) { /* Start of next packet */
11067 myunrd(x); /* Push back the decrypted byte */
11068 pushedback = 1; /* And set flag */
11069 debug(F000,"TTINL lkpush char","",x);
11074 #endif /* MYREAD */
11076 dest[i] = '\0'; /* Terminate the string, */
11077 if (needpchk) { /* Parity checked yet? */
11078 if (ttprty == 0) { /* No, check. */
11079 if ((ttprty = parchk(dest,start,i)) > 0) {
11081 debug(F101,"ttinl senses parity","",ttprty);
11082 debug(F110,"ttinl packet before",dest,0);
11084 for (j = 0; j < i; j++)
11085 dest[j] &= 0x7f; /* Strip parity from packet */
11086 debug(F110,"ttinl packet after ",dest,0);
11087 } else ttprty = 0; /* Restore if parchk error */
11092 #endif /* PARSENSE */
11094 if (timo) /* Turn off timer if it was on */
11096 ckhexdump("ttinl got",dest,i);
11099 /* ttinl() was called because there was non-packet */
11100 /* data sitting in the back channel. Ignore it. */
11101 if (streaming && sndtyp == 'D')
11103 #endif /* STREAMING */
11106 } /* End of while() */
11111 #endif /* NOXFER */
11113 /* T T I N C -- Read a character from the communication line */
11115 On success, returns the character that was read, >= 0.
11116 On failure, returns -1 or other negative myread error code,
11117 or -2 if connection is broken or ttyfd < 0.
11118 or -3 if session limit has expired,
11119 or -4 if something or other...
11120 NOTE: The API does not provide for ttinc() returning a special code
11121 upon timeout, but we need it. So for this we have a global variable,
11124 static int ttinctimo = 0; /* Yuk */
11127 ttinc(timo) int timo; {
11135 if (ttyfd < 0) return(-2); /* Not open. */
11137 is_tn = (xlocal && netconn && IS_TELNET()) ||
11138 (!xlocal && sstelnet);
11142 debug(F111,"ttinc","ttpush",ttpush);
11148 if (le_getchar(&ch) > 0) {
11149 debug(F111,"ttinc le_getchar","ch",ch);
11153 #endif /* TTLEBUF */
11159 #endif /* NETCMD */
11162 if ((timo <= 0) /* Untimed. */
11164 || (my_count > 0) /* Buffered char already waiting. */
11165 #endif /* MYREAD */
11168 /* Comm line failure returns -1 thru myread, so no &= 0377 */
11169 n = myread(); /* Wait for a character... */
11170 /* debug(F000,"ttinc MYREAD n","",n); */
11171 #ifdef CK_ENCRYPTION
11172 /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
11173 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11175 ck_tn_decrypt((char *)&ch,1);
11178 #endif /* CK_ENCRYPTION */
11181 if (ttpty && n < 0) {
11182 debug(F101,"ttinc error on pty","",n);
11186 #endif /* NETPTY */
11189 if ((n > -1) && is_tn)
11190 return((unsigned)(n & 0xff));
11192 #endif /* TNCODE */
11193 return(n < 0 ? n : (unsigned)(n & ttpmsk));
11197 while ((n = read(fd,&ch,1)) == 0) /* Wait for a character. */
11198 /* Shouldn't have to loop in ver 5A. */
11200 if (netconn) { /* Special handling for net */
11201 netclos(); /* If read() returns 0 it means */
11202 netconn = 0; /* the connection has dropped. */
11206 #endif /* NETCONN */
11208 /* debug(F101,"ttinc","",ch); */
11210 if ((n > 0) && is_tn) {
11211 #ifdef CK_ENCRYPTION
11212 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11213 ck_tn_decrypt(&ch,1);
11216 #endif /* CK_ENCRYPTION */
11217 return((unsigned)(ch & 0xff));
11219 #endif /* TNCODE */
11220 return((n < 0) ? -4 : ((n == 0) ? -1 : (unsigned)(ch & ttpmsk)));
11221 #endif /* MYREAD */
11223 } else { /* Timed read */
11226 saval = signal(SIGALRM,timerh); /* Set up handler, save old one. */
11227 oldalarm = alarm(timo); /* Set alarm, save old one. */
11229 #ifdef CK_POSIX_SIG
11233 #endif /* CK_POSIX_SIG */
11234 ) { /* Timer expired */
11236 n = -1; /* set flag */
11239 n = myread(); /* If managing own buffer... */
11240 debug(F101,"ttinc myread","",n);
11243 n = read(fd,&ch,1); /* Otherwise call the system. */
11244 if (n == 0) n = -1;
11245 debug(F101,"ttinc read","",n);
11246 #endif /* MYREAD */
11248 #ifdef CK_ENCRYPTION
11249 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11250 ck_tn_decrypt((char *)&ch,1);
11252 #endif /* CK_ENCRYPTION */
11254 n = (unsigned) (ch & 0xff);
11256 n = (n < 0) ? -4 : -2; /* Special return codes. */
11258 ttimoff(); /* Turn off the timer */
11259 if (oldalarm > 0) {
11260 if (n == -1) /* and restore any previous alarm */
11262 if (oldalarm < 0) /* adjusted by our timeout interval */
11265 debug(F101,"ttinc restoring oldalarm","",oldalarm);
11271 if (n == -2) { /* read() returns 0 */
11272 netclos(); /* on network read failure */
11277 #endif /* NETCONN */
11279 if ((n > -1) && is_tn)
11280 return((unsigned)(n & 0xff));
11282 #endif /* TNCODE */
11283 /* Return masked char or neg. */
11284 return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
11288 /* S N D B R K -- Send a BREAK signal of the given duration */
11292 sndbrk(int msec) { /* Argument is milliseconds */
11294 sndbrk(msec) int msec; {
11295 #endif /* CK_ANSIC */
11306 #endif /* ANYBSD */
11315 #endif /* BSDBREAK */
11316 #endif /* COHERENT */
11321 #endif /* BSDBREAK */
11322 #endif /* BELLV10 */
11326 #endif /* PROVX1 */
11328 debug(F101,"ttsndb ttyfd","",ttyfd);
11329 if (ttyfd < 0) return(-1); /* Not open. */
11332 return p9sndbrk(msec);
11336 if (ttpipe) /* Pipe */
11337 return(ttoc('\0'));
11338 #endif /* NETCMD */
11341 return(ttoc('\0'));
11342 #endif /* NETPTY */
11343 if (netconn) /* Send network BREAK */
11344 return(netbreak());
11345 #endif /* NETCONN */
11347 if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
11349 #ifdef POSIX /* Easy in POSIX */
11352 debug(F111,"sndbrk POSIX",ckitoa(msec),(msec/375));
11354 x = tcsendbreak(ttyfd,msec / 375);
11355 debug(F111,"sndbrk tcsendbreak",ckitoa(errno),x);
11360 gtty(ttyfd,&ttbuf); /* Get current tty flags */
11361 spd = ttbuf.sg_ospeed; /* Save speed */
11362 ttbuf.sg_ospeed = B50; /* Change to 50 baud */
11363 stty(ttyfd,&ttbuf); /* ... */
11364 n = (int)strlen(brnuls); /* Send the right number of nulls */
11367 write(ttyfd,brnuls,n);
11368 ttbuf.sg_ospeed = spd; /* Restore speed */
11369 stty(ttyfd,&ttbuf); /* ... */
11373 sio_$control((short)ttyfd, sio_$send_break, msec, st);
11377 n = FWRITE; /* Flush output queue. */
11378 /* Watch out for int vs long problems in &n arg! */
11379 debug(F101,"sndbrk BSDBREAK","",msec);
11380 ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
11381 if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
11382 perror("Can't send BREAK");
11385 x = msleep(msec); /* Sleep for so many milliseconds */
11386 if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
11387 perror("BREAK stuck!!!");
11388 doexit(BAD_EXIT,-1); /* Get out, closing the line. */
11389 /* with bad exit status */
11395 No way to send a long BREAK in Sys V, so send a bunch of regular ones.
11396 (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
11397 but there's no way for this code to know for sure.)
11399 debug(F101,"sndbrk ATTSV","",msec);
11401 for (n = 0; n < x; n++) {
11402 /* Reportedly the cast breaks this function on some systems */
11403 /* But then why was it here in the first place? */
11404 if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
11405 perror("Can't send BREAK");
11412 debug(F101,"sndbrk V7","",msec);
11413 return(genbrk(ttyfd,250)); /* Simulate a BREAK */
11415 debug(F101,"sndbrk catchall","",msec);
11416 ttoc(0);ttoc(0);ttoc(0);ttoc(0);
11419 #endif /* BSDBREAK */
11422 #endif /* PROVX1 */
11427 /* T T S N D B -- Send a BREAK signal */
11432 if (netconn && istncomport())
11433 return((tnsndb(275L) >= 0) ? 0 : -1);
11435 #endif /* TN_COMPORT */
11436 return(sndbrk(275));
11439 /* T T S N D L B -- Send a Long BREAK signal */
11444 if (netconn && istncomport())
11445 return((tnsndb(1800L) >= 0) ? 0 : -1);
11447 #endif /* TN_COMPORT */
11448 return(sndbrk(1500));
11451 /* M S L E E P -- Millisecond version of sleep(). */
11454 Call with number of milliseconds (thousandths of seconds) to sleep.
11455 Intended only for small intervals. For big ones, just use sleep().
11456 Highly system-dependent.
11457 Returns 0 always, even if it didn't work.
11460 /* Define MSLFTIME for systems that must use an ftime() loop. */
11461 #ifdef ANYBSD /* For pre-4.2 BSD versions */
11465 #endif /* ANYBSD */
11467 #ifdef TOWER1 /* NCR Tower OS 1.0 */
11469 #endif /* TOWER1 */
11471 #ifdef COHERENT /* Coherent... */
11472 #ifndef _I386 /* Maybe Coherent/386 should get this, too */
11473 #define MSLFTIME /* Opinions are divided */
11475 #endif /* COHERENT */
11480 /* Millisecond timer */
11482 static long msecbase = 0L; /* Unsigned long not portable */
11485 getmsec() { /* Milliseconds since base time */
11487 struct timezone xz;
11494 gettimeofday(&tv, NULL)
11496 gettimeofday(&tv, &tz)
11498 #endif /* GTODONEARG */
11501 if (msecbase == 0L) { /* First call, set base time. */
11502 msecbase = tv.tv_sec;
11503 debug(F101,"getmsec base","",msecbase);
11505 return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
11507 #endif /* GETMSEC */
11508 #endif /* COMMENT */
11512 ttwait(fd, secs) int fd, secs; {
11520 if ((x = select(FD_SETSIZE,
11526 #endif /* HPUX1000 */
11530 debug(F101,"ttwait select errno","",errno);
11533 debug(F101,"ttwait OK","",errno);
11534 x = FD_ISSET(fd, &rfds);
11535 debug(F101,"ttwait select x","",x);
11539 #endif /* SELECT */
11544 Other possibilities here are:
11545 nanosleep(), reportedly defined in POSIX.4.
11546 sginap(), IRIX only (back to what IRIX version I don't know).
11553 #else /* BEOSORBEBOX */
11556 debug(F101,"msleep SELECT 1","",m);
11557 if (m <= 0) return(0);
11558 if (m >= 1000) { /* Catch big arguments. */
11561 if (m < 10) return(0);
11563 debug(F101,"msleep SELECT 2","",m);
11565 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
11566 debug(F101,"msleep BELLV10 select","",x);
11567 #else /* BELLV10 */
11569 gettimeofday(&tv, &tz);
11574 if (gettimeofday(&tv) < 0)
11577 if (gettimeofday(&tv,NULL) < 0)
11580 if (gettimeofday(&tv, NULL) < 0) /* wonder what this does... */
11582 if (gettimeofday(&tv, &tz) < 0)
11583 #endif /* NOTIMEZONE */
11585 #endif /* GTODONEARG */
11587 t1 = tv.tv_sec; /* Seconds */
11588 #endif /* COHERENT */
11590 tv.tv_sec = 0; /* Use select() */
11591 tv.tv_usec = m * 1000L;
11593 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11594 debug(F101,"msleep BSD44 select","",x);
11597 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11598 debug(F101,"msleep __linux__ select","",x);
11599 #else /* __linux__ */
11601 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11602 debug(F101,"msleep BSD43 select","",x);
11605 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11606 debug(F101,"msleep QNX6 select","",x);
11609 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11610 debug(F101,"msleep QNX select","",x);
11613 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11614 debug(F101,"msleep COHERENT select","",x);
11615 #else /* COHERENT */
11616 #ifdef HPUX1000 /* 10.00 only, not 10.10 or later */
11617 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11618 debug(F101,"msleep HP-UX 10.00 select","",x);
11619 #else /* HPUX1000 */
11621 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11622 debug(F101,"msleep SVR4 select","",x);
11625 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11626 debug(F101,"msleep OSF40 select","",x);
11629 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11630 debug(F101,"msleep OSF40 select","",x);
11632 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11633 debug(F101,"msleep catch-all select","",x);
11636 #endif /* HP1000 */
11638 #endif /* COHERENT */
11642 #endif /* __linux__ */
11644 #endif /* BELLV10 */
11647 #else /* Not SELECT */
11648 #ifdef CK_POLL /* We have poll() */
11649 struct pollfd pfd; /* Supply a valid address for poll() */
11651 #ifdef ODT30 /* But in SCO ODT 3.0 */
11652 #ifdef NAP /* we should use nap() instead */
11653 debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
11654 nap((long)m); /* seems to break dialing. */
11657 debug(F101,"msleep ODT 3.0 POLL","",m);
11662 debug(F101,"msleep POLL","",m);
11668 We could handle the above more cleanly by just letting nap() always
11669 take precedence over poll() in this routine, but there is no way to know
11670 whether that would break something else.
11673 #else /* Not POLL */
11676 "This routine is implemented using setitimer(2); it requires eight
11677 system calls...". In other words, it might take 5 minutes to sleep
11680 debug(F101,"msleep USLEEP","",m);
11681 if (m >= 1000) { /* Catch big arguments. */
11684 if (m < 10) return(0);
11686 usleep((unsigned int)(m * 1000));
11691 debug(F101,"msleep aegis","",m);
11693 dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */
11694 time_$wait(time_$relative, dur, st);
11698 debug(F101,"msleep Venix","",m);
11699 if (m <= 0) return(0);
11700 sleep(-((m * 60 + 500) / 1000));
11704 debug(F101,"msleep NAP","",m);
11710 extern long times(); /* Or #include <times.h> ? */
11712 long t1, t2, tarray[4];
11714 char *cp = getenv("HZ");
11718 if (cp && (hertz = atoi(cp))) {
11719 CLOCK_TICK = 1000 / hertz;
11720 } else { /* probably single user mode */
11722 CLOCK_TICK = 1000 / HZ;
11725 /* HZ always exists in, for instance, SCO Xenix, so you don't have to
11726 * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
11727 * have Xenix, you have should have nap(), so the best is to use -DNAP
11728 * in the makefile. Most systems have HZ.
11730 CLOCK_TICK = 17; /* 1/60 sec */
11732 printf("warning: environment variable HZ bad... using HZ=%d\r\n",
11733 1000 / CLOCK_TICK);
11738 debug(F101,"msleep ATTSV","",m);
11739 if (m <= 0) return(0);
11740 if (m >= 1000) { /* Catch big arguments. */
11743 if (m < 10) return(0);
11745 if ((t1 = times(tarray)) < 0) return(-1);
11747 if ((t2 = times(tarray)) < 0) return(-1);
11748 t3 = ((int)(t2 - t1)) * CLOCK_TICK;
11749 if (t3 > m) return(t3);
11751 #else /* Not ATTSV */
11752 #ifdef MSLFTIME /* Use ftime() loop... */
11754 debug(F101,"msleep MSLFTIME","",m);
11755 if (m <= 0) return(0);
11756 if (m >= 1000) { /* Catch big arguments. */
11759 if (m < 10) return(0);
11762 ftime(&ftp); /* void ftime() in QNX */
11764 if (ftime(&ftp) < 0) return(-1); /* Get base time. */
11766 t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
11768 ftime(&ftp); /* Get current time and compare. */
11769 t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
11770 if (t3 > m) return(0);
11773 /* This includes true POSIX, which has no way to do this. */
11774 debug(F101,"msleep busy loop","",m);
11775 if (m >= 1000) { /* Catch big arguments. */
11778 if (m < 10) return(0);
11780 if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */
11782 #endif /* MSLFTIME */
11785 #endif /* PROVX1 */
11787 #endif /* CK_POLL */
11788 #endif /* SELECT */
11789 #endif /* BEOSORBEBOX */
11790 #endif /* USLEEP */
11794 /* R T I M E R -- Reset elapsed time counter */
11798 tcount = time( (time_t *) 0 );
11802 /* G T I M E R -- Get current value of elapsed time counter in seconds */
11807 x = (int) (time( (time_t *) 0 ) - tcount);
11808 debug(F101,"gtimer","",x);
11809 return( (x < 0) ? 0 : x );
11814 Floating-point timers. Require not only floating point support, but
11815 also gettimeofday().
11817 static struct timeval tzero;
11821 #ifdef GTODONEARG /* Account for Mot's definition */
11822 (VOID) gettimeofday(&tzero);
11824 (VOID) gettimeofday(&tzero, (struct timezone *)0);
11825 #endif /* GTODONEARG */
11830 struct timeval tnow, tdelta;
11835 #ifdef GTODONEARG /* Account for Mot's definition */
11836 (VOID) gettimeofday(&tnow);
11838 (VOID) gettimeofday(&tnow, (struct timezone *)0);
11839 #endif /* GTODONEARG */
11841 tdelta.tv_sec = tnow.tv_sec - tzero.tv_sec;
11842 tdelta.tv_usec = tnow.tv_usec - tzero.tv_usec;
11844 if (tdelta.tv_usec < 0) {
11846 tdelta.tv_usec += 1000000;
11848 s = (CKFLOAT) tdelta.tv_sec + ((CKFLOAT) tdelta.tv_usec / 1000000.0);
11853 sprintf(fpbuf,"%f",s);
11854 debug(F110,"gftimer",fpbuf,0);
11859 #endif /* GFTIMER */
11861 /* Z T I M E -- Return asctime()-format date/time string */
11863 NOTE: as a side effect of calling this routine, we can also set the
11864 following two variables, giving the micro- and milliseconds (fractions of
11865 seconds) of the clock time. Currently this is done only in BSD-based builds
11866 that use gettimeofday(). When these variables are not filled in, they are
11867 left with a value of -1L.
11869 static char asctmbuf[64];
11872 ztime(s) char **s; {
11876 The gettimeofday() method, which also sets ztmsec and ztusec, works for
11877 all GFTIMER builds. NOTE: ztmsec and ztusec are defined in ckcmai.c,
11878 and extern declarations for them are in ckcdeb.h; thus they are
11879 declared in this file by inclusion of ckcdeb.h.
11882 struct tm *localtime();
11888 debug(F100,"ztime s==NULL","",0);
11891 /* No 2nd arg in Motorola SV88 and some others */
11892 if (gettimeofday(&tv) > -1)
11896 if (gettimeofday(&tv,NULL) > -1)
11899 if (gettimeofday(&tv, NULL) > -1) /* wonder what this does... */
11901 if (gettimeofday(&tv, &tz) > -1)
11902 #endif /* NOTIMEZONE */
11904 #endif /* COHERENT */
11905 #endif /* GTODONEARG */
11906 { /* Fill in tm struct */
11907 ztusec = tv.tv_usec; /* Microseconds */
11908 ztmsec = ztusec / 1000L; /* Milliseconds */
11913 tp = localtime(&zz); /* Convert to local time */
11920 tp = localtime(&zz);
11924 { /* avoid unaligned access trap on 64-bit platforms */
11927 tp = localtime(&zz);
11931 tp = localtime((time_t *)&tv.tv_sec); /* Convert to local time */
11933 tp = localtime(&tv.tv_sec);
11934 #endif /* MACOSX */
11936 #endif /* HPUX1000 */
11940 s2 = asctime(tp); /* Convert result to ASCII string */
11941 asctmbuf[0] = '\0';
11942 if (s2) ckstrncpy(asctmbuf,s2,64);
11944 debug(F111,"ztime GFTIMER gettimeofday",*s,ztusec);
11947 #else /* Not GFTIMER */
11949 #undef ZTIMEV7 /* Which systems need to use */
11950 #ifdef COHERENT /* old UNIX Version 7 way... */
11952 #endif /* COHERENT */
11955 #endif /* TOWER1 */
11960 #endif /* ANYBSD */
11972 Prototypes are in <time.h>, included above.
11974 time_t clock_storage;
11975 clock_storage = time((void *) 0);
11977 *s = ctime(&clock_storage);
11978 debug(F110,"ztime: HPUX 10.20",*s,0);
11981 #ifdef ATTSV /* AT&T way */
11982 /* extern long time(); */ /* Theoretically these should */
11983 char *ctime(); /* already been dcl'd in <time.h> */
11984 time_t clock_storage;
11985 clock_storage = time(
11994 #endif /* IRIX60 */
11997 *s = ctime( &clock_storage );
11998 debug(F110,"ztime: ATTSV",*s,0);
12001 #ifdef PROVX1 /* Venix 1.0 way */
12006 debug(F110,"ztime: PROVX1",*s,0);
12009 #ifdef BSD42 /* 4.2BSD way */
12011 struct tm *localtime();
12013 gettimeofday(&tv, &tz);
12014 ztusec = tv.tv_usec;
12015 ztmsec = tv.tv_usec / 1000L;
12016 tp = localtime(&tv.tv_sec);
12019 debug(F111,"ztime: BSD42",*s,ztusec);
12022 #ifdef MINIX /* MINIX way */
12024 extern long time(); /* Already got these from <time.h> */
12025 extern char *ctime();
12026 #endif /* COMMENT */
12031 debug(F110,"ztime: MINIX",*s,0);
12034 #ifdef ZTIMEV7 /* The regular way */
12036 struct tm *localtime();
12038 long xclock; /* or unsigned long for BeBox? */
12040 tp = localtime(&xclock);
12043 debug(F110,"ztime: ZTIMEV7",*s,0);
12045 #else /* Catch-all for others... */
12047 *s = "Day Mon 00 00:00:00 0000\n"; /* Dummy in asctime() format */
12048 debug(F110,"ztime: catch-all",*s,0);
12050 #endif /* ZTIMEV7 */
12053 #endif /* PROVX1 */
12055 #endif /* HPUX1020 */
12056 #endif /* GFTIMER */
12059 /* C O N G M -- Get console terminal modes. */
12062 Saves initial console mode, and establishes variables for switching
12063 between current (presumably normal) mode and other modes.
12064 Should be called when program starts, but only after establishing
12065 whether program is in the foreground or background.
12066 Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
12071 if (backgrd || !isatty(0)) { /* If in background. */
12072 cgmf = -1; /* Don't bother, modes are garbage. */
12075 if (cgmf > 0) return(0); /* Already did this. */
12076 debug(F100,"congm getting modes","",0); /* Need to do it. */
12078 ios_$inq_type_uid(ios_$stdin, conuid, st);
12079 if (st.all != status_$ok) {
12080 fprintf(stderr, "problem getting stdin objtype: ");
12083 concrp = (conuid == mbx_$uid);
12088 if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */
12090 fprintf(stderr,"Error opening %s\n", CTTNAM);
12095 #endif /* COMMENT */
12099 #endif /* !BEBOX */
12100 #ifdef BSD44ORPOSIX
12101 if (tcgetattr(fd,&ccold) < 0) return(-1);
12102 if (tcgetattr(fd,&cccbrk) < 0) return(-1);
12103 if (tcgetattr(fd,&ccraw) < 0) return(-1);
12106 if (ioctl(fd,TCGETA,&ccold) < 0) return(-1);
12107 if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
12108 if (ioctl(fd,TCGETA,&ccraw) < 0) return(-1);
12110 cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
12111 if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
12112 ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
12113 if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
12117 if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
12118 if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
12119 if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
12120 debug(F101,"cccbrk.sg_flags orig","", cccbrk.sg_flags);
12122 if (gtty(fd,&ccold) < 0) return(-1);
12123 if (gtty(fd,&cccbrk) < 0) return(-1);
12124 if (gtty(fd,&ccraw) < 0) return(-1);
12125 #endif /* BELLV10 */
12127 #endif /* BSD44ORPOSIX */
12128 #ifdef sony_news /* Sony NEWS */
12129 if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
12130 perror("congm error getting Kanji mode");
12131 debug(F101,"congm error getting Kanji mode","",0);
12132 km_con = -1; /* Make sure this stays undefined. */
12135 #endif /* sony_news */
12138 cgmf = 1; /* Flag that we got them. */
12144 congetbuf(x) int x; {
12146 n = CONBUFSIZ - (conbufp - conbuf); /* How much room left in buffer? */
12148 debug(F101,"congetbuf char loss","",x-n);
12151 x = read(0,conbufp,x);
12153 debug(F111,"congetbuf readahead",conbuf,x);
12157 /* C O N C B -- Put console in cbreak mode. */
12159 /* Returns 0 if ok, -1 if not */
12165 concb(esc) char esc;
12166 #endif /* CK_ANSIC */
12169 debug(F101,"concb constate","",constate);
12170 debug(F101,"concb cgmf","",cgmf);
12171 debug(F101,"concb backgrd","",backgrd);
12173 if (constate == CON_CB)
12176 if (cgmf < 1) /* Did we get console modes yet? */
12177 if (!backgrd) /* No, in background? */
12178 congm(); /* No, try to get them now. */
12179 if (cgmf < 1) /* Still don't have them? */
12180 return(0); /* Give up. */
12181 debug(F101,"concb ttyfd","",ttyfd);
12182 debug(F101,"concb ttfdflg","",ttfdflg);
12184 /* This breaks returning to prompt after protocol with "-l 0" */
12185 /* Commented out July 1998 */
12186 if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
12188 #endif /* COMMENT */
12190 debug(F101,"concb isatty","",x);
12191 if (!x) return(0); /* Only when running on real ttys */
12192 debug(F101,"concb xsuspend","",xsuspend);
12193 if (backgrd) /* Do nothing if in background. */
12195 escchr = esc; /* Make this available to other fns */
12196 ckxech = 1; /* Program can echo characters */
12199 if (concrp) return(write(1, "\035\002", 2));
12200 if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
12205 #endif /* COHERENT */
12210 #ifndef SVORPOSIX /* BSD, V7, etc */
12211 debug(F101,"cccbrk.sg_flags concb 1","", cccbrk.sg_flags);
12212 debug(F101,"concb stty CBREAK","",0);
12213 cccbrk.sg_flags |= (CBREAK|CRMOD); /* Set to character wakeup, */
12214 cccbrk.sg_flags &= ~ECHO; /* no echo. */
12215 debug(F101,"cccbrk.sg_flags concb 2","", cccbrk.sg_flags);
12218 BSD stty() clears the console buffer. So if anything is waiting in it,
12219 we have to read it now to avoid losing it.
12226 x = ioctl(0,TIOCSETP,&cccbrk);
12228 x = stty(0,&cccbrk);
12229 debug(F101,"cccbrk.sg_flags concb x","", x);
12230 #endif /* BELLV10 */
12231 #else /* Sys V and POSIX */
12233 debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
12235 /* Don't mess with IEXTEN */
12236 cccbrk.c_lflag &= ~(ICANON|ECHO);
12239 cccbrk.c_lflag &= ~(ICANON|ECHO);
12241 cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
12242 #endif /* COHERENT */
12244 cccbrk.c_lflag |= ISIG; /* Allow signals in command mode. */
12245 cccbrk.c_iflag |= IGNBRK; /* But ignore BREAK signal */
12246 cccbrk.c_iflag &= ~BRKINT;
12249 debug(F100,"concb OXOS is defined","",0);
12250 cccbrk.c_lflag &= ~(ICANON|ECHO);
12251 cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
12255 Believe it or not, in SCO UNIX, VSUSP is greater than NCC, and so this
12256 array reference is out of bounds. It's only a debug() call so who needs it.
12259 debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
12261 #endif /* COMMENT */
12263 debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
12264 cccbrk.c_cc[0] = 003; /* Interrupt char is Control-C */
12266 debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
12267 cccbrk.c_cc[VINTR] = 003;
12270 cccbrk.c_cc[1] = escchr; /* escape during packet modes */
12272 cccbrk.c_cc[VQUIT] = escchr;
12275 cccbrk.c_cc[4] = 1;
12279 cccbrk.c_cc[VMIN] = 1;
12286 cccbrk.c_cc[5] = 0;
12289 cccbrk.c_cc[5] = 1;
12293 cccbrk.c_cc[VTIME] = 1;
12301 #ifdef BSD44ORPOSIX /* Set new modes */
12302 x = tcsetattr(0,TCSADRAIN,&cccbrk);
12303 #else /* ATTSV */ /* or the POSIX way */
12304 x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */
12305 #endif /* BSD44ORPOSIX */
12306 #endif /* SVORPOSIX */
12310 #endif /* COHERENT */
12312 debug(F101,"concb x","",x);
12313 debug(F101,"concb errno","",errno);
12317 if (kmem[CON] < 0) {
12318 qaddr[CON] = initrawq(0);
12319 if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
12320 fprintf(stderr, "Can't read /dev/kmem in concb.\n");
12321 perror("/dev/kmem");
12332 debug(F101,"concb returns","",x);
12336 /* C O N B I N -- Put console in binary mode */
12338 /* Returns 0 if ok, -1 if not */
12344 conbin(esc) char esc;
12345 #endif /* CK_ANSIC */
12350 debug(F101,"conbin constate","",constate);
12352 if (constate == CON_BIN)
12355 if (!isatty(0)) return(0); /* only for real ttys */
12356 congm(); /* Get modes if necessary. */
12357 debug(F100,"conbin","",0);
12358 escchr = esc; /* Make this available to other fns */
12359 ckxech = 1; /* Program can echo characters */
12362 if (concrp) return(write(1, "\035\002", 2));
12363 if (conuid == input_pad_$uid) {
12364 pad_$raw(ios_$stdin, st);
12371 #endif /* COHERENT */
12379 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12382 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12384 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
12385 #endif /* COHERENT */
12388 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12389 ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
12391 ccraw.c_iflag |= IGNPAR;
12393 Note that for terminal sessions we disable Xon/Xoff flow control to allow
12394 the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
12395 transfers to work when C-Kermit is in the middle, etc. Hardware flow
12396 control, if in use, is not affected.
12400 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
12403 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
12407 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
12409 ccraw.c_oflag &= ~OPOST;
12412 WHAT THE HECK WAS THIS FOR?
12413 The B9600 setting (obviously) prevents CONNECT from working at any
12414 speed other than 9600 when you are logged in to the 7300 on a serial
12415 line. Maybe some of the other flags are necessary -- if so, put back
12416 the ones that are needed. This code is supposed to work the same, no
12417 matter whether you are logged in to the 7300 on the real console device,
12418 or through a serial port.
12421 ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
12422 #endif /* ATT7300 */
12423 #endif /* COMMENT */
12425 /*** Kermit used to put the console in 8-bit raw mode, but some users have
12426 *** pointed out that this should not be done, since some sites actually
12427 *** use terminals with parity settings on their Unix systems, and if we
12428 *** override the current settings and stop doing parity, then their terminals
12429 *** will display blotches for characters whose parity is wrong. Therefore,
12430 *** the following two lines are commented out (Larry Afrin, Clemson U):
12432 *** ccraw.c_cflag &= ~(PARENB|CSIZE);
12433 *** ccraw.c_cflag |= (CS8|CREAD);
12435 *** Sys III/V sites that have trouble with this can restore these lines.
12438 ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */
12440 ccraw.c_cc[VINTR] = 003;
12443 ccraw.c_cc[1] = escchr; /* Escape during packet mode */
12445 ccraw.c_cc[VQUIT] = escchr;
12452 ccraw.c_cc[VMIN] = 1;
12467 ccraw.c_cc[VTIME] = 1;
12475 #ifdef BSD44ORPOSIX
12476 x = tcsetattr(0,TCSADRAIN,&ccraw); /* Set new modes. */
12478 x = ioctl(0,TCSETAW,&ccraw);
12479 #endif /* BSD44ORPOSIX */
12480 #else /* Berkeley, etc. */
12481 x = conchk(); /* Because stty() is destructive */
12484 ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF (ha) */
12485 ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
12487 x = ioctl(0,TIOCSETP,&ccraw);
12489 x = stty(0,&ccraw);
12490 #endif /* BELLV10 */
12491 #endif /* SVORPOSIX */
12495 constate = CON_BIN;
12497 debug(F101,"conbin returns","",x);
12502 #endif /* COHERENT */
12507 /* C O N R E S -- Restore the console terminal */
12512 debug(F101,"conres cgmf","",cgmf);
12513 debug(F101,"conres constate","",constate);
12515 if (cgmf < 1) /* Do nothing if modes unchanged */
12517 if (constate == CON_RES)
12520 if (!isatty(0)) return(0); /* only for real ttys */
12521 debug(F100,"conres isatty ok","",0);
12522 ckxech = 0; /* System should echo chars */
12526 if (concrp) return(write(1, "\035\001", 2));
12527 if (conuid == input_pad_$uid) {
12528 pad_$cooked(ios_$stdin, st);
12529 constate = CON_RES;
12537 #ifdef BSD44ORPOSIX
12538 debug(F100,"conres restoring tcsetattr","",0);
12539 x = tcsetattr(0,TCSADRAIN,&ccold);
12542 debug(F100,"conres restoring ioctl","",0);
12543 x = ioctl(0,TCSETAW,&ccold);
12544 #else /* BSD, V7, and friends */
12545 #ifdef sony_news /* Sony NEWS */
12547 ioctl(0,TIOCKSET,&km_con); /* Restore console Kanji mode */
12548 #endif /* sony_news */
12550 debug(F100,"conres restoring stty","",0);
12551 x = conchk(); /* Because stty() is destructive */
12555 x = ioctl(0,TIOCSETP,&ccold);
12557 x = stty(0,&ccold);
12558 #endif /* BELLV10 */
12560 #endif /* BSD44ORPOSIX */
12563 constate = CON_RES;
12565 debug(F101,"conres returns","",x);
12569 /* C O N O C -- Output a character to the console terminal */
12576 #endif /* CK_ANSIC */
12580 if (inserver && !local)
12583 #ifdef CK_ENCRYPTION
12584 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12585 ck_tn_encrypt(&c,1);
12586 #endif /* CK_ENCRYPTION */
12590 return conwrite(&c,1);
12592 return(write(1,&c,1));
12596 /* C O N X O -- Write x characters to the console terminal */
12599 conxo(x,s) int x; char *s; {
12602 if (inserver && !local)
12603 return(ttol((CHAR *)s,x));
12605 #ifdef CK_ENCRYPTION
12606 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12607 ck_tn_encrypt(s,x);
12608 #endif /* CK_ENCRYPTION */
12612 return(conwrite(s,x));
12614 return(write(1,s,x));
12618 /* C O N O L -- Write a line to the console terminal */
12621 conol(s) char *s; {
12623 if (!s) s = ""; /* Always do this! */
12629 if (inserver && !local)
12630 return(ttol((CHAR *)s,len));
12632 #ifdef CK_ENCRYPTION
12633 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION)) {
12634 if (nxpacket < len) {
12640 len = len > 10240 ? len : 10240;
12641 xpacket = (CHAR *)malloc(len);
12643 fprintf(stderr,"ttol malloc failure\n");
12648 memcpy(xpacket,s,len);
12649 s = (char *)xpacket;
12650 ck_tn_encrypt(s,len);
12652 #endif /* CK_ENCRYPTION */
12656 return(conwrite(s,len));
12658 return(write(1,s,len));
12662 /* C O N O L A -- Write an array of lines to the console terminal */
12665 conola(s) char *s[]; {
12671 for (i = 0; ; i++) {
12673 if (!p) p = ""; /* Let's not dump core shall we? */
12677 if (inserver && !local)
12678 x = ttol((CHAR *)p,(int)strlen(p));
12688 /* C O N O L L -- Output a string followed by CRLF */
12691 conoll(s) char *s; {
12699 if (inserver && !local) {
12700 if (*s) ttol((CHAR *)s,(int)strlen(s));
12701 return(ttol(buf,2));
12707 #ifdef CK_ENCRYPTION
12708 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12709 ck_tn_encrypt((char *)buf,2);
12710 #endif /* CK_ENCRYPTION */
12714 return(conwrite(buf, 2));
12716 return(write(1,buf,2));
12720 /* C O N C H K -- Return how many characters available at console */
12722 We could also use select() here to cover a few more systems that are not
12723 covered by any of the following, e.g. HP-UX 9.0x on the model 800.
12727 static int contyp = 0; /* +1 for isatty, -1 otherwise */
12729 if (contyp == 0) /* This prevents unnecessary */
12730 contyp = (isatty(0) ? 1 : -1); /* duplicated calls to isatty() */
12731 debug(F101,"conchk contyp","",contyp);
12732 if (backgrd || (contyp < 0))
12736 if (conbufn > 0) return(conbufn); /* use old count if nonzero */
12738 /* read in more characters */
12739 conbufn = ios_$get(ios_$stdin,
12740 ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
12741 if (st.all != status_$ok) conbufn = 0;
12746 if (inserver && !local)
12747 return(in_chk(1,ttyfd));
12750 return(in_chk(0,0));
12754 /* C O N I N C -- Get a character from the console */
12756 Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
12757 read. Upon success, returns the character. Upon failure, returns -1.
12758 A timed read that does not complete within the timeout period returns -2.
12761 coninc(timo) int timo; {
12762 int n = 0; CHAR ch;
12765 if (conbufn > 0) { /* If something already buffered */
12767 return((unsigned)(*conbufp++ & 0xff));
12770 errno = 0; /* Clear this */
12772 if (inserver && !local) {
12775 return(ttinctimo ? -2 : -1);
12781 #ifdef aegis /* Apollo Aegis only... */
12782 debug(F101,"coninc timo","",timo);
12784 if (conchk() > 0) {
12786 return((unsigned)(*conbufp++ & 0xff));
12798 debug(F111,"ttinc","ttpush",ttpush);
12804 if (le_getchar(&ch) > 0) {
12805 debug(F111,"ttinc LocalEchoInBuf","ch",ch);
12810 #endif /* TTLEBUF */
12812 if (timo <= 0) { /* Untimed, blocking read. */
12813 while (1) { /* Keep trying till we get one. */
12814 n = read(0, &ch, 1); /* Read a character. */
12815 if (n == 0) continue; /* Shouldn't happen. */
12816 if (n > 0) { /* If read was successful, */
12818 #ifdef CK_ENCRYPTION
12819 debug(F100,"coninc decrypt 1","",0);
12820 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12821 ck_tn_decrypt((char *)&ch,1);
12822 #endif /* CK_ENCRYPTION */
12824 return((unsigned)(ch & 0xff)); /* return the character. */
12827 /* Come here if read() returned an error. */
12829 debug(F101, "coninc(0) errno","",errno); /* Log the error. */
12832 #ifdef CIE /* CIE Regulus has no EINTR symbol? */
12838 This routine is used for several different purposes. In CONNECT mode, it is
12839 used to do an untimed, blocking read from the keyboard in the lower CONNECT
12840 fork. During local-mode file transfer, it reads a character from the
12841 console to interrupt the file transfer (like A for a status report, X to
12842 cancel a file, etc). Obviously, we don't want the reads in the latter case
12843 to be blocking, or the file transfer would stop until the user typed
12844 something. Unfortunately, System V does not allow the console device input
12845 buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
12846 used instead. During local-mode file transfer, the SIGQUIT signal is armed
12847 and trapped by esctrp(), and this routine pretends to have read the quit
12848 character from the keyboard normally. But, kludge or no kludge, the read()
12849 issued by this command, under System V only, can fail if a signal -- ANY
12850 signal -- is caught while the read is pending. This can occur not only when
12851 the user types the quit character, but also during telnet negotiations, when
12852 the lower CONNECT fork signals the upper one about an echoing mode change.
12853 When this happens, we have to post the read() again. This is apparently not
12854 a problem in BSD-based UNIX versions.
12856 if (errno == EINTR) /* Read interrupted. */
12857 if (conesc) { /* If by SIGQUIT, */
12858 conesc = 0; /* the conesc variable is set, */
12859 return(escchr); /* so return the escape character. */
12860 } else continue; /* By other signal, try again. */
12863 This might be dangerous, but let's do this on non-System V versions too,
12864 since at least one SunOS 4.1.2 user complains of immediate disconnections
12865 upon first making a TELNET connection.
12867 if (errno == EINTR) /* Read interrupted. */
12869 #endif /* SVORPOSIX */
12871 if (errno == EINTR) /* Read interrupted. */
12874 return(-1); /* Error */
12878 if (deblog && timo <= 0) {
12879 debug(F100,"coninc timeout logic error","",0);
12884 /* Timed read... */
12886 saval = signal(SIGALRM,timerh); /* Set up timeout handler. */
12887 xx = alarm(timo); /* Set the alarm. */
12888 debug(F101,"coninc alarm set","",timo);
12890 #ifdef CK_POSIX_SIG
12894 #endif /* CK_POSIX_SIG */
12895 ) /* The read() timed out. */
12896 n = -2; /* Code for timeout. */
12898 n = read(0, &ch, 1);
12899 ttimoff(); /* Turn off timer */
12900 if (n > 0) { /* Got character OK. */
12902 #ifdef CK_ENCRYPTION
12903 debug(F100,"coninc decrypt 2","",0);
12904 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12905 ck_tn_decrypt((char *)&ch,1);
12906 #endif /* CK_ENCRYPTION */
12908 return((unsigned)(ch & 0xff)); /* Return it. */
12911 read() returned an error. Same deal as above, but without the loop.
12913 debug(F101, "coninc(timo) n","",n);
12914 debug(F101, "coninc(timo) errno","",errno);
12917 if (n == -1 && errno == EINTR && conesc != 0) {
12919 return(escchr); /* User entered escape character. */
12921 #endif /* SVORPOSIX */
12922 if (n == 0 && errno > 0) { /* It's an error */
12925 #endif /* ! OXOS */
12929 /* C O N G K S -- Console Get Keyboard Scancode */
12933 This function needs to be filled in with the various system-dependent
12934 system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
12935 keyboard scan code. Unfortunately there aren't any.
12938 congks(timo) int timo; {
12941 if (inserver && !local)
12942 return(ttinc(timo));
12945 return(coninc(timo));
12947 #endif /* congks */
12951 /* A T T D I A L -- Dial up the remote system using internal modem
12952 * Purpose: to open and dial a number on the internal modem available on the
12953 * ATT7300 UNIX PC. Written by Joe Doupnik. Superceeds version written by
12954 * Richard E. Hill, Dickinson, TX. which employed dial(3c).
12955 * Uses information in <sys/phone.h> and our status int attmodem.
12957 attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
12960 attmodem &= ~ISMODEM; /* modem not in use yet */
12961 /* Ensure O_NDELAY is set, else i/o traffic hangs */
12962 /* We turn this flag off once the dial is complete */
12963 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
12965 /* Condition line, check availability & DATA mode, turn on speaker */
12966 if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
12967 printf("cannot access phone\n");
12971 ioctl(ttyfd,PIOCGETP,&dialer); /* get phone dialer parameters */
12973 if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */
12974 printf(" Should not dial with modem in VOICE mode.\n");
12975 printf(" Exit Kermit, switch to DATA and retry call.\n");
12979 #ifdef ATTTONED /* Old way, tone dialing only. */
12980 dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */
12981 dialer.c_lineparam &= ~PULSE; /* not with pulses. */
12983 /* Leave current pulse/tone state alone. */
12984 /* But what about DATA? Add it back if you have trouble. */
12985 /* sys/phone says you get DATA automatically by opening device RDWR */
12987 dialer.c_waitdialtone = 5; /* wait 5 sec for dialtone */
12989 dialer.c_feedback = SPEAKERON|NORMSPK|RINGON; /* control speaker */
12991 /* sys/phone says RINGON used only for incoming voice calls */
12992 dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
12993 dialer.c_feedback |= SPEAKERON|NORMSPK;
12995 dialer.c_waitflash = 500; /* 0.5 sec flash hook */
12996 if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) { /* set phone parameters */
12997 printf("Cannot set modem characteristics\n");
13001 ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */
13004 fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
13005 line_status:%o feedback:%o\n",
13006 dialer.c_lineparam, dialer.c_waitdialtone,
13007 dialer.c_linestatus, dialer.c_feedback);
13010 attmodem |= ISMODEM; /* modem is now in-use */
13012 for (telnum = telnbr; *telnum != '\0'; telnum++) /* dial number */
13014 /* Tone dialing only */
13015 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13016 perror("Error in dialing");
13020 #else /* Allow Pulse or Tone dialing */
13022 case 't': case 'T': case '%': /* Tone dialing requested */
13023 dialer.c_lineparam |= DTMF;
13024 dialer.c_lineparam &= ~PULSE;
13025 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13026 printf("Cannot set modem to tone dialing\n");
13031 case 'd': case 'D': case 'p': case 'P': case '^':
13032 dialer.c_lineparam |= PULSE;
13033 dialer.c_lineparam &= ~DTMF;
13034 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13035 printf("Cannot set modem to pulse dialing\n");
13041 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13042 perror("Dialing error");
13050 ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */
13051 do { /* wait for modems to Connect */
13052 if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */
13053 perror("Cannot get modems to connect");
13057 } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
13058 /* Turn off O_NDELAY flag now. */
13059 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
13060 signal(SIGHUP, sighup); /* hangup on loss of carrier */
13061 return(0); /* return success */
13065 Offgetty, ongetty functions. These function get the 'getty(1m)' off
13066 and restore it to the indicated line. Shell's return codes are:
13067 0: Can't do it. Probably a user logged on.
13068 1: No need. No getty on that line.
13069 2: Done, you should restore the getty when you're done.
13070 DOGETY System(3), however, returns them as 0, 256, 512, respectively.
13071 Thanks to Kevin O'Gorman, Anarm Software Systems.
13073 getoff.sh looks like: geton.sh looks like:
13074 setgetty $1 0 setgetty $1 1
13080 /* O F F G E T T Y -- Turn off getty(1m) for the communications tty line
13081 * and get status so it can be restarted after the line is hung up.
13084 offgetty(ttname) char *ttname; {
13086 while (*ttname != '\0') ttname++; /* seek terminator of path */
13087 ttname -= 3; /* get last 3 chars of name */
13088 sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
13089 return(zsyscmd(temp));
13092 /* O N G E T T Y -- Turn on getty(1m) for the communications tty line */
13095 ongetty(ttname) char *ttname; {
13097 while (*ttname != '\0') ttname++; /* comms tty path name */
13099 sprintf(temp,"/usr/bin/geton.sh %s",ttname);
13100 return(zsyscmd(temp));
13102 #endif /* ATT7300 */
13104 /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
13106 * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
13107 * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
13108 * 2 = Auto: For "modem direct": The same as "Off".
13109 * For real modem types: Heed carrier during connect, but ignore
13110 * it anytime else. Compatible with pre-5A C-Kermit versions.
13112 * As you can see, this setting does not affect dialing, which always ignores
13113 * carrier (unless there is some special exception for some modem type). It
13114 * does affect ttopen() if it is set before ttopen() is used. This setting
13115 * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
13116 * (or should be) always called before any communications is tried, which
13117 * means that, practically speaking, the effect is immediate.
13119 * Of course, nothing of this applies to remote mode (xlocal = 0).
13121 * Someone has yet to uncover how to manipulate the carrier in the BSD
13122 * environment (or any non-termio using environment). Until that time, this
13123 * will simply be a no-op for BSD.
13125 * Note that in previous versions, the carrier was most often left unchanged
13126 * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX. This
13127 * has changed. Now it is controlled by ttcarr in conjunction with these
13131 ttscarr(carrier) int carrier; {
13133 debug(F101, "ttscarr","",ttcarr);
13137 /* C A R R C T L -- Set tty modes for carrier treatment.
13139 * Sets the appropriate bits in a termio or sgttyb struct for carrier control
13140 * (actually, there are no bits in sgttyb for that), or performs any other
13141 * operations needed to control this on the current system. The function does
13142 * not do the actual TCSETA or stty, since often we want to set other bits too
13143 * first. Don't call this function when xlocal is 0, or the tty is not opened.
13145 * We don't know how to do anything like carrier control on non-ATTSV systems,
13146 * except, apparently, ultrix. See above. It is also known that this doesn't
13147 * have much effect on a Xenix system. For Xenix, one should switch back and
13148 * forth between the upper and lower case device files. Maybe later.
13149 * Presently, Xenix will stick to the mode it was opened with.
13151 * carrier: 0 = ignore carrier, 1 = require carrier.
13152 * The current state is saved in curcarr, and checked to save labour.
13156 #ifdef BSD44ORPOSIX
13157 carrctl(ttpar, carrier) struct termios *ttpar; int carrier;
13159 carrctl(ttpar, carrier) struct termio *ttpar; int carrier;
13160 #endif /* BSD44ORPOSIX */
13162 debug(F101, "carrctl","",carrier);
13164 ttpar->c_cflag &= ~CLOCAL;
13166 ttpar->c_cflag |= CLOCAL;
13169 #else /* Berkeley, V7, et al... */
13171 carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
13172 debug(F101, "carrctl","",carrier);
13173 if (carrier == curcarr)
13179 Old code from somebody at DEC that tends to get stuck, time out, etc.
13182 ioctl(ttyfd, TIOCMODEM, &temp);
13183 ioctl(ttyfd, TIOCHPCL, 0);
13185 /* (According to the manuals, TIOCNCAR should be preferred */
13186 /* over TIOCNMODEM...) */
13187 ioctl(ttyfd, TIOCNMODEM, &temp);
13191 New code from Jamie Watson that, he says, eliminates the problems.
13194 ioctl(ttyfd, TIOCCAR);
13195 ioctl(ttyfd, TIOCHPCL);
13197 ioctl(ttyfd, TIOCNCAR);
13199 #endif /* COMMENT */
13200 #endif /* ultrix */
13203 #endif /* SVORPOSIX */
13206 /* T T G M D M -- Get modem signals */
13208 Looks for RS-232 modem signals, and returns those that are on in as its
13209 return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
13212 -2 if the communication device does not have modem control (e.g. telnet)
13214 >= 0 on success, with a bit mask containing the modem signals that are on.
13218 Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
13219 modem control, namely the TIOCMGET ioctl.
13228 #endif /* SUNOS4 */
13231 SCO OpenServer R5.0.4. The TIOCMGET definition is hardwired in because it
13232 is skipped in termio.h when _POSIX_SOURCE is defined. But _POSIX_SOURCE
13233 must be defined in order to get the high serial speeds that are new to
13234 5.0.4. However, the regular SCO drivers do not implement TIOCMGET, so the
13235 ioctl() returns -1 with errno 22 (invalid function). But third-party
13236 drivers, e.g. for Digiboard, do implement it, and so it should work on ports
13237 driven by those drivers.
13241 #define TIOCMGET (('t'<<8)|29)
13242 #endif /* TIOCMGET */
13243 #endif /* SCO_OSR504 */
13246 /* Because POSIX strictness in <sys/termio.h> won't let us see these. */
13248 #define TIOCM_DTR 0x0002 /* data terminal ready */
13249 #define TIOCM_RTS 0x0004 /* request to send */
13250 #define TIOCM_CTS 0x0020 /* clear to send */
13251 #define TIOCM_CAR 0x0040 /* carrier detect */
13252 #define TIOCM_RNG 0x0080 /* ring */
13253 #define TIOCM_DSR 0x0100 /* data set ready */
13254 #define TIOCM_CD TIOCM_CAR
13255 #define TIOCM_RI TIOCM_RNG
13256 #endif /* TIOCM_DTR */
13257 #endif /* CK_SCOV5 */
13264 #endif /* TIOCMGET */
13267 "A serial communication program that can't read modem signals
13268 is like a car without windows."
13274 #include <sys/qioctl.h>
13276 unsigned long y, mdmbits[2];
13279 if (xlocal && ttyfd < 0)
13283 if (netconn) { /* Network connection */
13285 if (istncomport()) {
13289 #endif /* TN_COMPORT */
13290 return(-2); /* No modem signals */
13292 #endif /* NETCONN */
13295 if (ttpipe) return(-2);
13296 #endif /* NETCMD */
13298 if (ttpty) return(-2);
13299 #endif /* NETPTY */
13304 * From <sys/qioctl.h>:
13306 * SERIAL devices (all Dev.ser versions)
13307 * 0 : DTR 8 = Data Bits 0 16 - reserved 24 - reserved
13308 * 1 : RTS 9 = Data Bits 1 17 - reserved 25 - reserved
13309 * 2 = Out 1 10 = Stop Bits 18 - reserved 26 - reserved
13310 * 3 = Int Enable 11 = Par Enable 19 - reserved 27 - reserved
13311 * 4 = Loop 12 = Par Even 20 = CTS 28 - reserved
13312 * 5 - reserved 13 = Par Stick 21 = DSR 29 - reserved
13313 * 6 - reserved 14 : Break 22 = RI 30 - reserved
13314 * 7 - reserved 15 = 0 23 = CD 31 - reserved
13317 x = qnx_ioctl(ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4);
13318 debug(F101,"ttgmdm qnx_ioctl","",x);
13319 debug(F101,"ttgmdm qnx_ioctl errno","",errno);
13321 debug(F101,"ttgmdm qnx_ioctl mdmbits[0]","",mdmbits[0]);
13322 debug(F101,"ttgmdm qnx_ioctl mdmbits[1]","",mdmbits[1]);
13324 if (y & 0x000001L) z |= BM_DTR; /* Bit 0 */
13325 if (y & 0x000002L) z |= BM_RTS; /* Bit 1 */
13326 if (y & 0x100000L) z |= BM_CTS; /* Bit 20 */
13327 if (y & 0x200000L) z |= BM_DSR; /* Bit 21 */
13328 if (y & 0x400000L) z |= BM_RNG; /* Bit 22 */
13329 if (y & 0x800000L) z |= BM_DCD; /* Bit 23 */
13330 debug(F101,"ttgmdm qnx result","",z);
13331 debug(F110,"ttgmdm qnx CD = ",(z & BM_DCD) ? "On" : "Off", 0);
13336 #ifdef HPUX /* HPUX has its own way */
13339 #ifdef HPUX10 /* Modem flag word */
13340 mflag y; /* mflag typedef'd in <sys/modem.h> */
13348 unsigned long y; /* Not sure about pre-8.0... */
13351 #endif /* HPUX10 */
13353 if (xlocal && ttyfd < 0)
13357 if (netconn) { /* Network connection */
13359 if (istncomport()) {
13363 #endif /* TN_COMPORT */
13364 return(-2); /* No modem signals */
13366 #endif /* NETCONN */
13369 if (ttpipe) return(-2);
13370 #endif /* NETCMD */
13372 if (ttpty) return(-2);
13373 #endif /* NETPTY */
13375 if (xlocal) /* Get modem signals */
13376 x = ioctl(ttyfd,MCGETA,&y);
13378 x = ioctl(0,MCGETA,&y);
13379 if (x < 0) return(-1);
13380 debug(F101,"ttgmdm","",y);
13382 z = 0; /* Initialize return value */
13384 /* Now set bits for each modem signal that is reported to be on. */
13387 /* Clear To Send */
13388 debug(F101,"ttgmdm HPUX CTS","",y & MCTS);
13389 if (y & MCTS) z |= BM_CTS;
13392 /* Data Set Ready */
13393 debug(F101,"ttgmdm HPUX DSR","",y & MDSR);
13394 if (y & MDSR) z |= BM_DSR;
13398 debug(F101,"ttgmdm HPUX DCD","",y & MDCD);
13399 if (y & MDCD) z |= BM_DCD;
13402 /* Ring Indicate */
13403 debug(F101,"ttgmdm HPUX RI","",y & MRI);
13404 if (y & MRI) z |= BM_RNG;
13407 /* Data Terminal Ready */
13408 debug(F101,"ttgmdm HPUX DTR","",y & MDTR);
13409 if (y & MDTR) z |= BM_DTR;
13412 /* Request To Send */
13413 debug(F101,"ttgmdm HPUX RTS","",y & MRTS);
13414 if (y & MRTS) z |= BM_RTS;
13423 Note, TIOCMGET might already have been defined in <sys/ioctl.h> or elsewhere.
13424 If not, we try including <sys/ttycom.h> -- if this blows up then more ifdefs
13428 #include <sys/ttycom.h>
13429 #endif /* TIOCMGET */
13433 debug(F100,"ttgmdm K_MDMCTL defined","",0);
13436 if (netconn) { /* Network connection */
13438 if (istncomport()) {
13442 #endif /* TN_COMPORT */
13443 return(-2); /* No modem signals */
13445 #endif /* NETCONN */
13448 if (ttpipe) return(-2);
13449 #endif /* NETCMD */
13451 if (ttpty) return(-2);
13452 #endif /* NETPTY */
13454 if (xlocal && ttyfd < 0)
13458 x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */
13460 x = ioctl(0,TIOCMGET,&y);
13461 debug(F101,"ttgmdm TIOCMGET ioctl","",x);
13463 debug(F101,"ttgmdm errno","",errno);
13466 debug(F101,"ttgmdm bits","",y);
13468 z = 0; /* Initialize return value. */
13470 /* Clear To Send */
13471 if (y & TIOCM_CTS) z |= BM_CTS;
13472 debug(F101,"ttgmdm TIOCM_CTS defined","",TIOCM_CTS);
13474 debug(F100,"ttgmdm TIOCM_CTS not defined","",0);
13477 /* Data Set Ready */
13478 if (y & TIOCM_DSR) z |= BM_DSR;
13479 debug(F101,"ttgmdm TIOCM_DSR defined","",TIOCM_DSR);
13481 debug(F100,"ttgmdm TIOCM_DSR not defined","",0);
13485 if (y & TIOCM_CAR) z |= BM_DCD;
13486 debug(F101,"ttgmdm TIOCM_CAR defined","",TIOCM_CAR);
13488 debug(F100,"ttgmdm TIOCM_CAR not defined","",0);
13491 /* Ring Indicate */
13492 if (y & TIOCM_RNG) z |= BM_RNG;
13493 debug(F101,"ttgmdm TIOCM_RNG defined","",TIOCM_RNG);
13495 debug(F100,"ttgmdm TIOCM_RNG not defined","",0);
13498 /* Data Terminal Ready */
13499 if (y & TIOCM_DTR) z |= BM_DTR;
13500 debug(F101,"ttgmdm TIOCM_DTR defined","",TIOCM_DTR);
13502 debug(F100,"ttgmdm TIOCM_DTR not defined","",0);
13505 /* Request To Send */
13506 if (y & TIOCM_RTS) z |= BM_RTS;
13507 debug(F101,"ttgmdm TIOCM_RTS defined","",TIOCM_RTS);
13509 debug(F100,"ttgmdm TIOCM_RTS not defined","",0);
13514 #else /* !K_MDMCTL catch-All */
13516 debug(F100,"ttgmdm K_MDMCTL not defined","",0);
13518 debug(F100,"ttgmdm TIOCMGET defined","",0);
13520 debug(F100,"ttgmdm TIOCMGET not defined","",0);
13521 #endif /* TIOCMGET */
13523 debug(F100,"ttgmdm _SVID3 defined","",0);
13525 debug(F100,"ttgmdm _SVID3 not defined","",0);
13526 #endif /* _SVID3 */
13529 if (netconn) { /* Network connection */
13531 if (istncomport()) {
13535 #endif /* TN_COMPORT */
13536 return(-2); /* No modem signals */
13538 #endif /* NETCONN */
13541 if (ttpipe) return(-2);
13542 #endif /* NETCMD */
13544 if (ttpty) return(-2);
13545 #endif /* NETPTY */
13547 return(-3); /* Sorry, I don't know how... */
13549 #endif /* K_MDMCTL */
13554 /* P S U S P E N D -- Put this process in the background. */
13557 Call with flag nonzero if suspending is allowed, zero if not allowed.
13558 Returns 0 on apparent success, -1 on failure (flag was zero, or
13559 kill() returned an error code.
13562 psuspend(flag) int flag; {
13565 extern int rtu_bug;
13568 if (flag == 0) return(-1);
13575 The big question here is whether job control is *really* supported.
13576 There's no way Kermit can know for sure. The fact that SIGTSTP is
13577 defined does not guarantee the Unix kernel supports it, and the fact
13578 that the Unix kernel supports it doesn't guarantee that the user's
13579 shell (or other process that invoked Kermit) supports it.
13584 if (kill(0,SIGSTOP) < 0
13586 /* Let's try this for MIPS too. */
13587 && kill(getpid(),SIGSTOP) < 0
13589 ) { /* If job control, suspend the job */
13591 debug(F101,"psuspend error","",errno);
13594 debug(F100,"psuspend ok","",0);
13598 #endif /* SIGTSTP */
13603 setuid package, by Kristoffer Eriksson, with contributions from Dean
13607 /* The following is for SCO when CK_ANSILIBS is defined... */
13610 #ifndef NOGETID_PROTOS
13611 #define NOGETID_PROTOS
13612 #endif /* NOGETID_PROTOS */
13613 #endif /* CK_ANSILIBS */
13614 #endif /* M_UNIX */
13616 #ifndef _POSIX_SOURCE
13624 #ifndef NOGETID_PROTOS
13625 _PROTOTYP( UID_T getuid, (void) );
13626 _PROTOTYP( UID_T geteuid, (void) );
13627 _PROTOTYP( UID_T getreuid, (void) );
13628 _PROTOTYP( UID_T getgid, (void) );
13629 _PROTOTYP( UID_T getegid, (void) );
13630 _PROTOTYP( UID_T getregid, (void) );
13631 #endif /* NOGETID_PROTOS */
13633 _PROTOTYP( UID_T getreuid, (void) );
13634 _PROTOTYP( UID_T getregid, (void) );
13635 #endif /* COHERENT */
13636 #endif /* HPUX10 */
13638 #endif /* sequent */
13639 #endif /* PS2AIX10 */
13641 #endif /* SUNOS4 */
13642 #endif /* _POSIX_SOURCE */
13645 Subject: Set-user-id
13646 To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
13647 Date: Sat, 21 Apr 90 4:48:25 MES
13648 From: Kristoffer Eriksson <ske@pkmab.se>
13650 This is a set of functions to be used in programs that may be run set-user-id
13651 and/or set-group-id. They handle both the case where the program is not run
13652 with such privileges (nothing special happens then), and the case where one
13653 or both of these set-id modes are used. The program is made to run with the
13654 user's real user and group ids most of the time, except for when more
13655 privileges are needed. Don't set-user-id to "root".
13657 This works on System V and POSIX. In BSD, it depends on the
13658 "saved-set-user-id" feature.
13661 #define UID_ROOT 0 /* Root user and group ids */
13665 The following code defines the symbol SETEUID for UNIX systems based
13666 on BSD4.4 (either -Encumbered or -Lite). This program will then use
13667 seteuid() and setegid() instead of setuid() and setgid(), which still
13668 don't allow arbitrary switching. It also avoids setreuid() and
13669 setregid(), which are included in BSD4.4 for compatibility only, are
13670 insecure, and print warnings to stderr under at least one system (NetBSD
13671 1.0). Note that POSIX systems should still use setuid() and setgid();
13672 the seteuid() and setegid() functions are BSD4.4 extensions to the
13673 POSIX model. Mike Long <mike.long@analog.com>, 8/94.
13680 The following construction automatically defines the symbol SETREUID for
13681 UNIX versions based on Berkeley Unix 4.2 and 4.3. If this symbol is
13682 defined, then this program will use getreuid() and getregid() calls in
13683 preference to getuid() and getgid(), which in Berkeley-based Unixes do
13684 not allow arbitrary switching back and forth of real & effective uid.
13685 This construction also allows -DSETREUID to be put on the cc command line
13686 for any system that has and wants to use setre[ug]id(). It also prevents
13687 automatic definition of SETREUID if -DNOSETREU is included on the cc
13688 command line (or otherwise defined).
13690 #ifdef FT18 /* None of this for Fortune. */
13701 #endif /* SETEUID */
13702 #endif /* NOSETREU */
13703 #endif /* SETREUID */
13704 #endif /* !BSD41 */
13705 #endif /* !BSD29 */
13706 #endif /* ANYBSD */
13708 /* Variables for user and group IDs. */
13710 static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
13711 static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
13714 /* P R I V _ I N I -- Initialize privileges package */
13716 /* Called as early as possible in a set-uid or set-gid program to store the
13717 * set-to uid and/or gid and step down to the users real uid and gid. The
13718 * stored id's can be temporarily restored (allowed in System V) during
13719 * operations that require the privilege. Most of the time, the program
13720 * should execute in unpriviliged state, to not impose any security threat.
13722 * Note: Don't forget that access() always uses the real id:s to determine
13723 * file access, even with privileges restored.
13725 * Returns an error mask, with error values or:ed together:
13726 * 1 if setuid() fails,
13727 * 2 if setgid() fails, and
13728 * 4 if the program is set-user-id to "root", which can't be handled.
13730 * Only the return value 0 indicates real success. In case of failure,
13731 * those privileges that could be reduced have been, at least, but the
13732 * program should be aborted none-the-less.
13734 * Also note that these functions do not expect the uid or gid to change
13735 * without their knowing. It may work if it is only done temporarily, but
13736 * you're on your own.
13742 #ifndef HAVE_LOCKDEV
13744 /* Save real ID:s. */
13745 realuid = getuid();
13746 realgid = getgid();
13748 /* Save current effective ID:s, those set to at program exec. */
13749 privuid = geteuid();
13750 privgid = getegid();
13752 /* If running set-uid, go down to real uid, otherwise remember that
13753 * no privileged uid is available.
13757 * 1) If the real uid is already "root" and the set-uid uid (the
13758 * initial effective uid) is not "root", then we would have trouble
13759 * if we went "down" to "root" here, and then temporarily back to the
13760 * set-uid uid (not "root") and then again tried to become "root". I
13761 * think the "saved set-uid" is lost when changing uid from effective
13762 * uid "root", which changes all uid, not only the effective uid. But
13763 * in this situation, we can simply go to "root" and stay there all
13764 * the time. That should give sufficient privilege (understatement!),
13765 * and give the right uids for subprocesses.
13767 * 2) If the set-uid (the initial effective uid) is "root", and we
13768 * change uid to the real uid, we can't change it back to "root" when
13769 * we need the privilege, for the same reason as in 1). Thus, we can't
13770 * handle programs that are set-user-id to "root" at all. The program
13771 * should be stopped. Use some other uid. "root" is probably too
13772 * privileged for such things, anyway. (The uid is reverted to the
13773 * real uid until termination.)
13775 * These two exceptions have the effect that the "root" uid will never
13776 * be one of the two uids that are being switched between, which also
13777 * means we don't have to check for such cases in the switching
13780 * Note that exception 1) is handled by these routines (by constantly
13781 * running with uid "root", while exception 2) is a serious error, and
13782 * is not provided for at all in the switching functions.
13784 if (realuid == privuid)
13785 privuid = (UID_T) -1; /* Not running set-user-id. */
13787 /* If running set-gid, go down to real gid, otherwise remember that
13788 * no privileged gid is available.
13790 * There are no exception like there is for the user id, since there
13791 * is no group id that is privileged in the manner of uid "root".
13792 * There could be equivalent problems for group changing if the
13793 * program sometimes ran with uid "root" and sometimes not, but
13794 * that is already avoided as explained above.
13796 * Thus we can expect always to be able to switch to the "saved set-
13797 * gid" when we want, and back to the real gid again. You may also
13798 * draw the conclusion that set-gid provides for fewer hassles than
13803 fprintf(stderr,"UID_ROOT=%d\n",UID_ROOT);
13804 fprintf(stderr,"realuid=%d\n",realuid);
13805 fprintf(stderr,"privuid=%d\n",privuid);
13806 #endif /* SUIDDEBUG */
13808 if (realgid == privgid) /* If not running set-user-id, */
13809 privgid = (GID_T) -1; /* remember it this way. */
13811 err = priv_off(); /* Turn off setuid privilege. */
13813 if (privuid == UID_ROOT) /* If setuid to root, */
13814 err |= 4; /* return this error. */
13816 if (realuid == UID_ROOT) { /* If real id is root, */
13817 privuid = (UID_T) -1; /* stay root at all times. */
13819 /* If Kermit installed SUID uucp and user is running as root */
13820 err &= ~1; /* System V R0 does not save UID */
13821 #endif /* ATT7300 */
13823 #endif /* HAVE_LOCKDEV */
13828 /* Macros for hiding the differences in UID/GID setting between various Unix
13829 * systems. These macros should always be called with both the privileged ID
13830 * and the non-privileged ID. The one in the second argument, will become the
13831 * effective ID. The one in the first argument will be retained for later
13836 /* On BSD systems with the saved-UID feature, we just juggle the effective
13837 * UID back and forth, and leave the real UID at its true value. The kernel
13838 * allows switching to both the current real UID, the effective UID, and the
13839 * UID which the program is set-UID to. The saved set-UID always holds the
13840 * privileged UID for us, and the real UID will always be the non-privileged,
13841 * and we can freely choose one of them for the effective UID at any time.
13843 #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
13844 #define switchgid(hidden,active) setregid( (GID_T) -1, active)
13846 #else /* SETREUID,!SAVEDUID */
13848 /* On systems with setreXid() but without the saved-UID feature, notably
13849 * BSD 4.2, we swap the real and effective UIDs each time. It's
13850 * the effective UID that we are interested in, but we have to retain the
13851 * unused UID somewhere to enable us to restore it later, and we do this
13852 * in the real UID. The kernel only allows switching to either the current
13853 * real or the effective UID, unless you're "root".
13855 #define switchuid(hidden,active) setreuid(hidden,active)
13856 #define switchgid(hidden,active) setregid(hidden,active)
13859 #else /* !SETREUID, !SAVEDUID */
13863 BSD 4.4 works similarly to System V and POSIX (see below), but uses
13864 seteXid() instead of setXid() to change effective IDs. In addition, the
13865 seteXid() functions work the same for "root" as for other users.
13867 #define switchuid(hidden,active) seteuid(active)
13868 #define switchgid(hidden,active) setegid(active)
13870 #else /* !SETEUID */
13872 /* On System V and POSIX, the only thing we can change is the effective UID
13873 * (unless the current effective UID is "root", but initsuid() avoids that for
13874 * us). The kernel allows switching to the current real UID or to the saved
13875 * set-UID. These are always set to the non-privileged UID and the privileged
13876 * UID, respectively, and we only change the effective UID. This breaks if
13877 * the current effective UID is "root", though, because for "root" setuid/gid
13878 * becomes more powerful, which is why initsuid() treats "root" specially.
13879 * Note: That special treatment maybe could be ignored for BSD? Note: For
13880 * systems that don't fit any of these four cases, we simply can't support
13883 #define switchuid(hidden,active) setuid(active)
13884 #define switchgid(hidden,active) setgid(active)
13886 #endif /* SETEUID */
13887 #endif /* SETREUID */
13890 /* P R I V _ O N -- Turn on the setuid and/or setgid */
13892 /* Go to the privileged uid (gid) that the program is set-user-id
13893 * (set-group-id) to, unless the program is running unprivileged.
13894 * If setuid() fails, return value will be 1. If getuid() fails it
13895 * will be 2. Return immediately after first failure, and the function
13896 * tries to restore any partial work done. Returns 0 on success.
13897 * Group id is changed first, since it is less serious than user id.
13901 #ifndef HAVE_LOCKDEV
13902 if (privgid != (GID_T) -1)
13903 if (switchgid(realgid,privgid))
13906 if (privuid != (UID_T) -1)
13907 if (switchuid(realuid,privuid)) {
13908 if (privgid != (GID_T) -1)
13909 switchgid(privgid,realgid);
13912 #endif /* HAVE_LOCKDEV */
13916 /* P R I V _ O F F -- Turn on the real uid and gid */
13918 /* Return to the unprivileged uid (gid) after an temporary visit to
13919 * privileged status, unless the program is running without set-user-id
13920 * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
13921 * in setgid() or:ed together. The functions tries to return both uid
13922 * and gid to unprivileged state, regardless of errors. Returns 0 on
13928 #ifndef HAVE_LOCKDEV
13929 if (privuid != (UID_T) -1)
13930 if (switchuid(privuid,realuid))
13933 if (privgid != (GID_T) -1)
13934 if (switchgid(privgid,realgid))
13936 #endif /* HAVE_LOCKDEV */
13940 /* Turn off privilege permanently. No going back. This is necessary before
13941 * a fork() on BSD43 machines that don't save the setUID or setGID, because
13942 * we swap the real and effective ids, and we don't want to let the forked
13943 * process swap them again and get the privilege back. It will work on other
13944 * machines too, such that you can rely on its effect always being the same,
13945 * for instance, even when you're in priv_on() state when this is called.
13946 * (Well, that part about "permanent" is on System V only true if you follow
13947 * this with a call to exec(), but that's what we want it for anyway.)
13948 * Added by Dean Long -- dlong@midgard.ucsc.edu
13952 #ifndef HAVE_LOCKDEV
13955 if (privuid != (UID_T) -1)
13956 if (setreuid(realuid,realuid))
13959 if (privgid != (GID_T) -1)
13960 if (setregid(realgid,realgid))
13968 if (privuid != (UID_T) -1)
13969 if (setuid(realuid)) {
13970 debug(F101,"setuid failed","",errno);
13972 debug(F101,"ruid","",getuid());
13973 debug(F101,"euid","",geteuid());
13975 debug(F101,"setuid","",realuid);
13976 if (privgid != (GID_T) -1)
13977 if (setgid(realgid)) {
13978 debug(F101,"setgid failed","",errno);
13980 debug(F101,"rgid","",getgid());
13981 debug(F101,"egid","",getegid());
13983 debug(F101,"setgid","",realgid);
13986 /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
13987 return(priv_off());
13988 #endif /* SETEUID */
13989 #endif /* SETREUID */
13992 #endif /* HAVE_LOCKDEV */
13995 /* P R I V _ O P N -- For opening protected files or devices. */
13998 priv_opn(name, modes) char *name; int modes; {
14000 priv_on(); /* Turn privileges on */
14001 debug(F111,"priv_opn",name,modes);
14003 x = open(name, modes); /* Try to open the device */
14004 debug(F101,"priv_opn result","",x);
14005 debug(F101,"priv_opn errno","",errno);
14006 priv_off(); /* Turn privileges off */
14007 return(x); /* Return open's return code */
14010 /* P R I V _ C H K -- Check privileges. */
14012 /* Try to turn them off. If turning them off did not succeed, cancel them */
14017 x = priv_off(); /* Turn off privs. */
14018 if (x != 0 || getuid() == privuid || geteuid() == privuid)
14020 if (x != 0 || getgid() == privgid || getegid() == privgid)
14021 y = y | priv_can();
14031 ttimoff() { /* Turn off any timer interrupts */
14034 As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
14035 SIG_DFL (to catch alarms, or if there is no handler, to exit). This is to
14036 cure (mask, really) a deeper problem with stray alarms that occurs on some
14037 systems, possibly having to do with sleep(), that caused core dumps. It
14038 should be OK to do this, because no code in this module uses nested alarms.
14039 (But we still have to watch out for SCRIPT and DIAL...)
14041 /* xx = */ alarm(0);
14042 /* debug(F101,"ttimoff alarm","",xx); */
14043 if (saval) { /* Restore any previous */
14044 signal(SIGALRM,saval); /* alarm handler. */
14045 /* debug(F101,"ttimoff alarm restoring saval","",saval); */
14048 signal(SIGALRM,SIG_IGN); /* Used to be SIG_DFL */
14049 /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
14055 tt_is_secure() { /* Tells whether the current connection is secure */
14063 #endif /* SSHBUILTIN */
14064 #ifdef CK_ENCRYPTION
14065 || ck_tn_encrypting() && ck_tn_decrypting()
14066 #endif /* CK_ENCRYPTION */
14068 || tls_active_flag || ssl_active_flag
14069 #endif /* CK_SSL */
14072 #ifdef CK_ENCRYPTION
14073 || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
14074 #endif /* CK_ENCRYPTION */
14075 #endif /* CK_KERBEROS */
14076 #endif /* RLOGCODE */
14084 /* External protocol handler parameters from ckuus3.c */
14085 extern int exp_handler, exp_stderr, exp_timo;
14090 /* The right size is 24576 */
14092 #ifndef PTY_PBUF_SIZE /* Size of buffer to read from pty */
14093 #define PTY_PBUF_SIZE 24576 /* and write to net. */
14094 #endif /* PTY_PBUF_SIZE */
14096 #ifndef PTY_TBUF_SIZE /* Size of buffer to read from net */
14097 #define PTY_TBUF_SIZE 24576 /* and write to pty. */
14098 #endif /* PTY_TBUF_SIZE */
14100 #ifdef O_NDELAY /* Whether to use nonblocking */
14101 #ifndef PTY_NO_NDELAY /* reads on the pseudoterminal */
14102 #ifndef PTY_USE_NDELAY
14103 #define PTY_USE_NDELAY
14104 #endif /* PTY_USE_NDELAY */
14105 #endif /* PTY_NO_NDELAY */
14106 #endif /* O_NDELAY */
14108 #ifndef HAVE_OPENPTY
14109 #ifndef USE_CKUPTY_C
14110 #define USE_CKUPTY_C
14111 #endif /* USE_CKUPTY_C */
14112 #endif /* HAVE_OPENPTY */
14115 pty_make_raw(fd) int fd; {
14118 #ifdef BSD44ORPOSIX /* POSIX */
14121 #ifdef ATTSV /* AT&T UNIX */
14123 struct termio tp = {0};
14126 #endif /* CK_ANSIC */
14128 struct sgttyb tp; /* Traditional */
14130 #endif /* BSD44ORPOSIX */
14132 debug(F101,"pty_make_raw fd","",fd);
14135 #ifdef BSD44ORPOSIX /* POSIX */
14136 x = tcgetattr(fd,&tp);
14137 debug(F101,"pty_make_raw tcgetattr","",x);
14139 #ifdef ATTSV /* AT&T UNIX */
14140 x = ioctl(fd,TCGETA,&tp);
14141 debug(F101,"pty_make_raw TCGETA ioctl","",x);
14144 debug(F101,"pty_make_raw ttty","",x);
14146 #endif /* BSD44ORPOSIX */
14147 debug(F101,"pty_make_raw GET errno","",errno);
14149 #ifdef USE_CFMAKERAW
14152 debug(F101,"pty_make_raw cfmakeraw errno","",errno);
14153 #else /* USE_CFMAKERAW */
14157 /* This very simple version recommended by Serg Iakolev doesn't work */
14159 tp.c_lflag &= ~(ECHO|ICANON|IEXTEN|ISIG);
14160 tp.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
14161 tp.c_cflag &= ~(CSIZE|PARENB);
14163 tp.c_oflag &= ~(OPOST);
14165 tp.c_cc[VTIME] = 0;
14167 debug(F101,"pty_make_raw 1 c_cc[] NCCS","",NCCS);
14168 debug(F101,"pty_make_raw 1 iflags","",tp.c_iflag);
14169 debug(F101,"pty_make_raw 1 oflags","",tp.c_oflag);
14170 debug(F101,"pty_make_raw 1 lflags","",tp.c_lflag);
14171 debug(F101,"pty_make_raw 1 cflags","",tp.c_cflag);
14176 In this version we unset everything and then set only the
14177 bits we know we need.
14181 tp.c_iflag |= IGNBRK;
14183 tp.c_iflag |= IMAXBEL;
14184 #endif /* IMAXBEL */
14192 tp.c_lflag |= NOKERNINFO;
14193 #endif /* NOKERNINFO */
14197 tp.c_cflag |= CS8|CREAD;
14199 for (i = 0; i < NCCS; i++) { /* No special characters */
14203 tp.c_cc[VMIN] = 1; /* But always wait for input */
14205 debug(F101,"pty_make_raw 2 c_cc[] NCCS","",NCCS);
14206 debug(F101,"pty_make_raw 2 iflags","",tp.c_iflag);
14207 debug(F101,"pty_make_raw 2 oflags","",tp.c_oflag);
14208 debug(F101,"pty_make_raw 2 lflags","",tp.c_lflag);
14209 debug(F101,"pty_make_raw 2 cflags","",tp.c_cflag);
14211 #else /* COMMENT */
14213 In this version we set or unset every single flag explicitly. It works a
14214 bit better than the simple version just above, but it's still far from
14218 tp.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
14219 tp.c_iflag &= ~(INPCK|IGNPAR|IXANY|IXON|IXOFF);
14220 tp.c_iflag |= IGNBRK;
14223 tp.c_iflag |= IMAXBEL;
14225 tp.c_iflag &= ~IMAXBEL;
14226 #endif /* COMMENT */
14227 #endif /* IMAXBEL */
14229 tp.c_iflag &= ~IUCLC;
14234 tp.c_oflag &= ~BSDLY;
14237 tp.c_oflag &= ~CRDLY;
14240 tp.c_oflag &= ~FFDLY;
14243 tp.c_oflag &= ~NLDLY;
14246 tp.c_oflag &= ~TABDLY;
14247 #endif /* TABDLY */
14249 tp.c_oflag &= ~VTDLY;
14252 tp.c_oflag &= ~OFDEL;
14255 tp.c_oflag &= ~OFILL;
14258 tp.c_oflag &= ~OLCUC;
14261 tp.c_oflag &= ~CMSPAR;
14262 #endif /* CMSPAR */
14263 tp.c_oflag &= ~OPOST;
14265 tp.c_oflag &= ~OXTABS;
14266 #endif /* OXTABS */
14269 tp.c_oflag &= ~ONOCR; /* Maybe should be |=? */
14270 tp.c_oflag |= ONOCR; /* makes no difference either way */
14272 #endif /* COMMENT */
14274 tp.c_oflag &= ~ONOEOT;
14275 #endif /* ONOEOT */
14277 tp.c_oflag &= ~ONLRET;
14278 #endif /* ONLRET */
14280 tp.c_oflag &= ~ONLCR;
14283 tp.c_oflag &= ~OCRNL;
14287 tp.c_lflag &= ~ECHO;
14289 tp.c_lflag &= ~ECHOE;
14292 tp.c_lflag &= ~ECHONL;
14293 #endif /* ECHONL */
14295 tp.c_lflag &= ~ECHOPRT;
14296 #endif /* ECHOPRT */
14298 tp.c_lflag &= ~ECHOKE;
14299 #endif /* ECHOKE */
14301 tp.c_lflag &= ~ECHOCTL;
14302 #endif /* ECHOCTL */
14304 tp.c_lflag &= ~XCASE;
14307 tp.c_lflag &= ~ALTWERASE;
14308 #endif /* ALTWERASE */
14310 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN|EXTPROC);
14312 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
14313 #endif /* EXTPROC */
14315 tp.c_lflag |= NOKERNINFO;
14316 #endif /* NOKERNINFO */
14318 tp.c_lflag &= ~NOFLSH; /* TRY IT THE OTHER WAY? */
14320 tp.c_lflag |= NOFLSH; /* No, this way is worse */
14321 #endif /* COMMENT */
14324 tp.c_cflag &= ~(CSIZE|PARENB|PARODD);
14325 tp.c_cflag |= CS8|CREAD;
14328 tp.c_cflag &= ~(MDMBUF);
14331 tp.c_cflag &= ~(CCAR_OFLOW); /* two names for the same thing */
14332 #endif /* CCAR_OFLOW */
14333 #endif /* MDMBUF */
14336 tp.c_cflag &= ~(CCTS_OFLOW);
14337 #endif /* CCTS_OFLOW */
14339 tp.c_cflag &= ~(CDSR_OFLOW);
14340 #endif /* CDSR_OFLOW */
14342 tp.c_cflag &= ~(CDTR_IFLOW);
14343 #endif /* CDTR_IFLOW */
14345 tp.c_cflag &= ~(CRTS_IFLOW);
14346 #endif /* CRTS_IFLOW */
14348 tp.c_cflag &= ~(CRTSXOFF);
14349 #endif /* CRTSXOFF */
14351 tp.c_cflag &= ~(CRTSCTS);
14352 #endif /* CRTSCTS */
14354 tp.c_cflag &= ~(CLOCAL);
14355 #endif /* CLOCAL */
14357 tp.c_cflag &= ~(CSTOPB);
14358 #endif /* CSTOPB */
14360 tp.c_cflag &= ~(HUPCL);
14363 for (i = 0; i < NCCS; i++) { /* No special characters */
14367 tp.c_cc[VMIN] = 1; /* But always wait for input */
14369 debug(F101,"pty_make_raw 3 c_cc[] NCCS","",NCCS);
14370 debug(F101,"pty_make_raw 3 iflags","",tp.c_iflag);
14371 debug(F101,"pty_make_raw 3 oflags","",tp.c_oflag);
14372 debug(F101,"pty_make_raw 3 lflags","",tp.c_lflag);
14373 debug(F101,"pty_make_raw 3 cflags","",tp.c_cflag);
14374 #endif /* COMMENT */
14375 #endif /* COMMENT */
14378 #ifdef BSD44ORPOSIX /* POSIX */
14379 x = tcsetattr(fd,TCSANOW,&tp);
14380 debug(F101,"pty_make_raw tcsetattr","",x);
14382 #ifdef ATTSV /* AT&T UNIX */
14383 x = ioctl(fd,TCSETA,&tp);
14384 debug(F101,"pty_make_raw ioctl","",x);
14386 x = stty(fd,&tp); /* Traditional */
14387 debug(F101,"pty_make_raw stty","",x);
14389 #endif /* BSD44ORPOSIX */
14390 debug(F101,"pty_make_raw errno","",errno);
14392 #endif /* __NetBSD__ */
14396 pty_chk(fd) int fd; {
14400 x = ioctl(fd, FIONREAD, &n); /* BSD and most others */
14401 ckmakmsg(msgbuf,500,
14402 "pty_chk ioctl FIONREAD errno=",
14406 debug(F100,msgbuf,"",0);
14410 debug(F101,"pty_chk rdchk","",n);
14414 #endif /* FIONREAD */
14415 return((n > -1) ? n : 0);
14419 pty_get_status(fd,pid) int fd; PID_T pid; {
14420 int x, status = -1;
14423 debug(F101,"pty_get_status fd","",fd);
14424 debug(F101,"pty_get_status pid","",pid);
14426 if (pexitstat > -1)
14430 /* Not only unnecessary but harmful */
14432 x = kill(pty_fork_pid,0);
14433 debug(F101,"pty_get_status kill value","",x);
14434 debug(F101,"pty_get_status kill errno","",errno);
14435 if (x > -1 && errno != ESRCH)
14436 return(-1); /* Fork still there */
14437 /* Fork seems to be gone */
14438 #endif /* COMMENT */
14441 x = waitpid(pty_fork_pid,&status,WNOHANG);
14442 debug(F111,"pty_get_status waitpid",ckitoa(errno),x);
14443 if (x <= 0 && errno == 0) {
14444 debug(F101,"pty_get_status waitpid return","",-1);
14448 if (x != pty_fork_pid)
14450 "pty_get_status waitpid pid doesn't match","",pty_fork_pid);
14451 debug(F101,"pty_get_status waitpid status","",status);
14452 debug(F101,"pty_get_status waitpid errno","",errno);
14453 if (WIFEXITED(status)) {
14454 debug(F100,"pty_get_status WIFEXITED","",0);
14455 status = WEXITSTATUS(status);
14456 debug(F101,"pty_get_status fork exit status","",status);
14459 #endif /* COMMENT */
14461 pexitstat = status;
14463 debug(F100,"pty_get_status waitpid unexpected status","",0);
14466 debug(F101,"pty_get_status return status","",status);
14470 /* t t p t y c m d -- Run command on pty and forward to net */
14473 Needed for running external protocols on secure connections.
14474 For example, if C-Kermit has made an SSL/TLS or Kerberos Telnet
14475 connection, and then needs to transfer a file with Zmodem, which is
14476 an external program, this routine reads Zmodem's output, encrypts it,
14477 and then forwards it out the connection, and reads the encrypted data
14478 stream coming in from the connection, decrypts it, and forwards it to
14481 Works like a TCP/IP port forwarder except one end is a pty rather
14482 than a socket, which introduces some complications:
14484 . On most platforms, select() always indicates the output side of
14485 the pty has characters waiting to be read, even when it doesn't,
14486 even when the pty process has already exited.
14488 . Nonblocking reads must be used on the pty, because there is no
14489 way on certain platforms (e.g. NetBSD) to find out how many characters
14490 are available to be read (the FIONREAD ioctl always says 0). The code
14491 also allows for blocking reads (if O_NDELAY and O_NONBLOCK are not
14492 defined, or if PTY_NO_NDELAY is defined), but on some platforms this can
14493 result in single-byte reads and writes (NetBSD again).
14495 . Testing for "EOF" on the pty is problematic. select() never gives
14496 any indication. After the pty process has exited and the fork has
14497 disappeared, read() can still return with 0 bytes read but without an
14498 error (NetBSD); no known test on the pty file descriptor will indicate
14499 that it is no longer valid. The process ID of the pty fork can be
14500 tested on some platforms (NetBSD, luckily) but not others (Solaris,
14503 On the network side, we use ttinc() and ttoc(), which, for network
14504 connections, handle any active security methods.
14506 Call with s = command.
14507 Returns 0 on failure, 1 on success.
14508 fdc - December 2006 - August 2007.
14510 NOTE: This code defaults to nonblocking reads if O_NDELAY or O_NONBLOCK are
14511 defined in the header files, which should be true of every recent Unix
14512 platform. If this causes trouble somewhere, define PTY_NO_NDELAY, e.g. when
14516 make platformname KFLAGS=-DPTY_NO_NODELAY
14518 static int have_pty = 0; /* Do we have a pty? */
14520 static SIGTYP (*save_sigchld)() = NULL; /* For catching SIGCHLD */
14523 sigchld_handler(sig) int sig; {
14524 have_pty = 0; /* We don't have a pty */
14526 if (save_sigchld) {
14527 (VOID) signal(SIGCHLD,save_sigchld);
14528 save_sigchld = NULL;
14531 debug(F100,"**************","",0);
14532 debug(F100,"SIGCHLD caught","",0);
14533 debug(F100,"**************","",0);
14541 ttptycmd(s) char *s; {
14542 CHAR tbuf[PTY_TBUF_SIZE]; /* Read from net, write to pty */
14543 int tbuf_avail = 0; /* Pointers for tbuf */
14544 int tbuf_written = 0;
14545 static int in_state = 0; /* For TELNET IAC and NVT in */
14546 static int out_prev = 0; /* Simpler scheme for out */
14548 CHAR pbuf[PTY_PBUF_SIZE]; /* Read from pty, write to net */
14549 CHAR dbuf[PTY_PBUF_SIZE + PTY_PBUF_SIZE + 1]; /* Double-size buffer */
14550 int pbuf_avail = 0; /* Pointers for pbuf */
14551 int pbuf_written = 0;
14553 int ptyfd = -1; /* Pty file descriptor */
14554 int have_net = 0; /* We have a network connection */
14555 int pty_err = 0; /* Got error on pty */
14556 int net_err = 0; /* Got error on net */
14557 int status = -1; /* Pty process exit status */
14558 int rc = 0; /* Our return code */
14560 int x1 = 0, x2 = 0; /* Workers... */
14561 int c, n, m, t, x; /* Workers */
14563 long seconds_to_wait = 0L; /* select() timeout */
14564 struct timeval tv, *tv2; /* For select() */
14566 int in, out, err; /* For select() */
14568 fd_set in, out, err;
14569 #endif /* INTSELECT */
14570 int nfds = 0; /* For select() */
14572 int pset = 0, tset = 0, pnotset = 0, tnotset = 0; /* stats/debuggin only */
14573 int read_net_bytes = 0; /* Stats */
14574 int write_net_bytes = 0; /* Stats */
14575 int read_pty_bytes = 0; /* Stats */
14576 int write_pty_bytes = 0; /* Stats */
14577 int is_tn = 0; /* TELNET protocol is active */
14581 #ifndef USE_CKUPTY_C
14582 struct termios term;
14583 struct winsize twin;
14584 struct stringarray * q;
14585 char ** args = NULL;
14586 #endif /* USE_CKUPTY_C */
14588 in_state = 0; /* No previous character yet */
14591 printf("?Sorry, communication channel is not open\n");
14597 debug(F100,"ttptycmd fail: nopush","",0);
14600 if (!s) s = ""; /* Defense de bogus arguments */
14601 if (!*s) return(0);
14602 pexitstat = -1; /* Fork process exit status */
14605 is_tn = (xlocal && netconn && IS_TELNET()) || /* Telnet protocol active */
14606 (!xlocal && sstelnet);
14607 #endif /* TNCODE */
14609 debug(F110,"ttptycmd command",s,0);
14610 debug(F101,"ttptycmd ttyfd","",ttyfd);
14611 debug(F101,"ttptycmd is_tn","",is_tn);
14612 debug(F101,"ttptycmd ckermit pid","",getpid());
14614 #ifdef USE_CKUPTY_C
14615 /* Call ckupty.c module to get and set up the pty fork */
14616 /* fc 1 == "run an external protocol" */
14617 debug(F100,"ttptycmd using ckupty.c","",0);
14618 if (do_pty(&ptyfd,s,1) < 0) { /* Start the command on a pty */
14619 debug(F100,"ttptycmd do_pty fails","",0);
14623 pty_master_fd = ptyfd;
14625 slavefd = pty_slave_fd; /* This is not visible to us */
14626 #endif /* COMMENT */
14627 debug(F111,"ttptycmd ptyfd","USE_CKUPTY_C",ptyfd);
14628 debug(F111,"ttptycmd masterfd","USE_CKUPTY_C",masterfd);
14629 debug(F111,"ttptycmd fork pid","USE_CKUPTY_C",pty_fork_pid);
14631 /* "ioctl inappropriate on device" for pty master */
14632 pty_make_raw(masterfd);
14633 #endif /* SOLARIS */
14635 #else /* USE_CKUPTY_C */
14637 debug(F100,"ttptycmd OPENPTY","",0);
14638 if (tcgetattr(0, &term) == -1) { /* Get controlling terminal's modes */
14639 perror("tcgetattr");
14642 if (ioctl(0, TIOCGWINSZ, (char *) &twin) == -1) { /* and window size */
14643 perror("ioctl TIOCGWINSZ");
14646 if (openpty(&masterfd, &slavefd, NULL, NULL, NULL) == -1) {
14647 debug(F101,"ttptycmd openpty failed errno","",errno);
14651 debug(F101,"ttptycmd openpty masterfd","",masterfd);
14652 debug(F101,"ttptycmd openpty slavefd","",slavefd);
14653 pty_master_fd = masterfd;
14654 pty_slave_fd = slavefd;
14655 debug(F101,"ttptycmd openpty pty_master_fd","",pty_master_fd);
14657 /* Put pty master in raw mode but let forked app control the slave */
14658 pty_make_raw(masterfd);
14662 /* TIOCREMOTE,0 = disable all termio processing */
14663 x = ioctl(masterfd, TIOCREMOTE, 1);
14664 debug(F111,"ttptycmd ioctl TIOCREMOTE",ckitoa(x),errno);
14665 #endif /* TIOCREMOTE */
14667 /* TIOCTTY,0 = disable all termio processing */
14668 x = ioctl(masterfd, TIOCTTY, 0);
14669 debug(F111,"ttptycmd ioctl TIOCTTY",ckitoa(x),errno);
14670 #endif /* TIOCTTY */
14671 #endif /* COMMENT */
14673 have_pty = 1; /* We have an open pty */
14674 save_sigchld = signal(SIGCHLD, sigchld_handler); /* Catch fork quit */
14676 pty_fork_pid = fork(); /* Make fork for external protocol */
14677 debug(F101,"ttptycmd pty_fork_pid","",pty_fork_pid);
14678 if (pty_fork_pid == -1) {
14681 } else if (pty_fork_pid == 0) { /* In new fork */
14683 debug(F101,"ttptycmd new fork pid","",getpid());
14684 close(masterfd); /* Slave quarters no masters allowed */
14686 debug(F101,"ttptycmd new fork setsid","",x);
14688 perror("ttptycmd setsid");
14691 signal(SIGINT,SIG_IGN); /* Let upper fork catch this */
14695 /* Make pty the controlling terminal for the process */
14696 /* THIS CAUSES AN INFINITE SIGWINCH INTERRUPT LOOP */
14697 x = ioctl(slavefd, TIOCSCTTY, NULL);
14698 debug(F101,"ttptycmd TIOCSCTTY","",x);
14699 #endif /* TIOCSCTTY */
14700 #endif /* COMMENT */
14702 /* Initialize slave pty modes and size to those of our terminal */
14703 if (tcsetattr(slavefd, TCSANOW, &term) == -1) {
14704 perror("ttptycmd tcsetattr");
14707 if (ioctl(slavefd, TIOCSWINSZ, &twin) == -1) {
14708 perror("ttptycmd ioctl");
14713 /* Disassociate this process from its terminal */
14714 /* THIS HAS NO EFFECT */
14715 x = ioctl(slavefd, TIOCNOTTY, NULL);
14716 debug(F101,"ttptycmd TIOCNOTTY","",x);
14717 #endif /* TIOCNOTTY */
14718 #endif /* COMMENT */
14722 /* Ignore terminal output interrupts */
14723 /* THIS HAS NO EFFECT */
14724 debug(F100,"ttptycmd ignoring SIGTTOU","",0);
14725 signal(SIGTTOU, SIG_IGN);
14726 #endif /* SIGTTOU */
14728 /* Ignore terminal output interrupts */
14729 /* THIS HAS NO EFFECT */
14730 debug(F100,"ttptycmd ignoring SIGTSTP","",0);
14731 signal(SIGTSTP, SIG_IGN);
14732 #endif /* SIGTSTP */
14733 #endif /* COMMENT */
14735 pty_make_raw(slavefd); /* Put it in rawmode */
14738 if (dup2(slavefd, STDIN_FILENO) != STDIN_FILENO ||
14739 dup2(slavefd, STDOUT_FILENO) != STDOUT_FILENO) {
14740 debug(F101,"ttptycmd new fork dup2 error","",errno);
14741 perror("ttptycmd dup2");
14744 debug(F100,"ttptycmd new fork dup2 ok","",0);
14746 /* Parse external protocol command line */
14747 q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0);
14749 debug(F100,"ttptycmd cksplit failed","",0);
14753 debug(F100,"ttptycmd cksplit ok","",0);
14755 args = q->a_head + 1;
14756 for (i = 0; i <= n; i++) {
14760 /* sometimes cksplit() doesn't terminate the list */
14761 if ((i == n) && args[i]) {
14762 if ((int)strlen(args[i]) == 0)
14763 makestr(&(args[i]),NULL);
14770 Putting the slave pty in rawmode should not be necessary because the
14771 external protocol program is supposed to do that itself. Yet doing this
14772 here cuts down on Zmodem binary-file transmission errors by 30-50% but
14773 still doesn't eliminate them.
14775 pty_make_raw(STDIN_FILENO);
14776 pty_make_raw(STDOUT_FILENO);
14777 #endif /* COMMENT */
14779 debug(F100,"ttptycmd execvp'ing external protocol","",0);
14780 execvp(args[0],args);
14781 perror("execvp failed");
14782 debug(F101,"ttptycmd execvp failed","",errno);
14786 /* (there are better ways to do this...) */
14787 msleep(1000); /* Make parent wait for child to be ready */
14788 ptyfd = masterfd; /* We talk to the master */
14790 #endif /* USE_CKUPTY_C */
14792 debug(F101,"ttptycmd ptyfd","",ptyfd);
14794 printf("?Failure to get pty\n");
14797 have_pty = 1; /* We have an open pty or we wouldn't he here */
14799 debug(F101,"ttptycmd PTY_PBUF_SIZE","",PTY_PBUF_SIZE);
14800 debug(F101,"ttptycmd PTY_TBUF_SIZE","",PTY_TBUF_SIZE);
14802 #ifdef PTY_USE_NDELAY
14804 NOTE: If select() and ioctl(ptyfd,FIONREAD,&n) return true indications
14805 on the pty, we don't need nonblocking reads. Performance of either
14806 method seems to be about the same, so use whatever works.
14809 x = fcntl(ptyfd,F_SETFL,fcntl(ptyfd,F_GETFL, 0)|O_NDELAY);
14810 ckmakmsg(msgbuf,500,
14811 "ttptycmd set O_NDELAY errno=",
14815 debug(F100,msgbuf,"",0);
14816 #endif /* PTY_USE_NDELAY */
14819 /* Not necessary, the protocol module already did this */
14821 #ifdef USE_CFMAKERAW
14822 if (tcgetattr(ttyfd, &term) > -1) {
14824 debug(F101,"ttptycmd net cfmakeraw errno","",errno);
14825 x tcsetattr(ttyfd, TCSANOW, &term);
14826 debug(F101,"ttptycmd net tcsetattr","",x);
14827 debug(F101,"ttptycmd net tcsetattr","",errno);
14830 if (local) /* Put network connection in */
14831 ttpkt(ttspeed,ttflow,ttprty); /* "packet mode". */
14833 conbin((char)escchr); /* OR... pty_make_raw(0) */
14834 #endif /* USE_CFMAKERAW */
14835 #endif /* COMMENT */
14839 debug(F101,"<<< ttptycmd TELOPT_ME_BINARY","",TELOPT_ME(TELOPT_BINARY));
14840 debug(F101,"<<< ttptycmd TELOPT_U_BINARY","",TELOPT_U(TELOPT_BINARY));
14842 #endif /* TNCODE */
14844 debug(F101,"ttptycmd entering loop - seconds_to_wait","",seconds_to_wait);
14846 while (have_pty || have_net) {
14847 FD_ZERO(&in); /* Initialize select() structs */
14849 FD_ZERO(&err); /* (not used because useless) */
14852 debug(F101,"ttptycmd loop top have_pty","",have_pty);
14853 debug(F101,"ttptycmd loop top have_net","",have_net);
14855 /* Pty is open and we have room to read from it? */
14856 if (have_pty && pbuf_avail < PTY_PBUF_SIZE) {
14857 debug(F100,"ttptycmd FD_SET ptyfd in","",0);
14858 FD_SET(ptyfd, &in);
14861 /* Network is open and we have room to read from it? */
14862 if (have_net && have_pty && tbuf_avail < PTY_TBUF_SIZE) {
14863 debug(F100,"ttptycmd FD_SET ttyfd in","",0);
14864 FD_SET(ttyfd, &in);
14865 if (ttyfd > nfds) nfds = ttyfd;
14867 /* Pty is open and we have stuff to write to it? */
14868 if (have_pty && tbuf_avail - tbuf_written > 0) {
14869 debug(F100,"ttptycmd FD_SET ptyfd out","",0);
14870 FD_SET (ptyfd, &out);
14871 if (ptyfd > nfds) nfds = ptyfd;
14873 /* Net is open and we have stuff to write to it? */
14874 debug(F101,"ttptycmd pbuf_avail-pbuf_written","",
14875 pbuf_avail - pbuf_written);
14876 if (have_net && pbuf_avail - pbuf_written > 0) {
14877 debug(F100,"ttptycmd FD_SET ttyfd out","",0);
14878 FD_SET (ttyfd, &out);
14879 if (ttyfd > nfds) nfds = ttyfd;
14881 /* We don't use err because it's not really for errors, */
14882 /* but for out of band data on the TCP socket, which, if it is */
14883 /* to be handled at all, is handled in the tt*() routines */
14885 nfds++; /* 0-based to 1-based */
14886 debug(F101,"ttptycmd nfds","",nfds);
14888 debug(F100,"ttptycmd NO FDs set for select","",0);
14890 /* This is not right -- sleeping won't accomplish anything */
14891 debug(F101,"ttptycmd msleep","",100);
14894 debug(F100,"ttptycmd no pty - quitting loop","",0);
14900 if (seconds_to_wait > 0L) { /* Timeout in case nothing happens */
14901 tv.tv_sec = seconds_to_wait; /* for a long time */
14907 x = select(nfds, &in, &out, NULL, tv2);
14908 debug(F101,"ttptycmd select","",x);
14910 if (errno == EINTR)
14912 debug(F101,"ttptycmd select error","",errno);
14916 debug(F101,"ttptycmd +++ select timeout","",seconds_to_wait);
14918 status = pty_get_status(ptyfd,pty_fork_pid);
14919 debug(F101,"ttptycmd pty_get_status A","",status);
14920 if (status > -1) pexitstat = status;
14925 /* We want to handle any pending writes first to make room */
14926 /* for new incoming. */
14928 if (FD_ISSET(ttyfd, &out)) { /* Can write to net? */
14930 s = pbuf + pbuf_written; /* Current spot for sending */
14932 if (is_tn) { /* ttol() doesn't double IACs */
14933 CHAR c; /* Rewrite string with IACs doubled */
14935 s = pbuf + pbuf_written; /* Source */
14937 for (i = 0; i < pbuf_avail - pbuf_written; i++) {
14938 c = s[i]; /* Next character */
14939 if (c == IAC) { /* If it's IAC */
14940 dbuf[x++] = c; /* put another one */
14941 debug(F000,">>> QUOTED IAC","",c);
14942 } else if (c != 0x0a && out_prev == 0x0d) { /* Bare CR */
14943 if (!TELOPT_ME(TELOPT_BINARY)) { /* NVT rule */
14946 debug(F000,">>> CR-NUL","",c);
14949 dbuf[x++] = c; /* Copy and count it */
14950 debug(F000,">>> char",ckitoa(in_state),c);
14953 s = dbuf; /* New source */
14955 #endif /* TNCODE */
14956 x = pbuf_avail - pbuf_written; /* How much to send */
14958 debug(F101,"ttptycmd bytes to send","",x);
14960 debug(F101,">>> ttol","",x);
14963 debug(F111,"ttptycmd ttol error",ckitoa(x),errno);
14966 write_net_bytes += x;
14969 if (FD_ISSET(ptyfd, &out)) { /* Can write to pty? */
14970 debug(F100,"ttptycmd FD_ISSET ptyfd out","",0);
14973 x = write(ptyfd,tbuf + tbuf_written,tbuf_avail - tbuf_written);
14975 /* Byte loop to rule out data overruns in the pty */
14976 /* (it makes no difference) */
14978 char *p = tbuf+tbuf_written;
14979 int n = tbuf_avail - tbuf_written;
14980 for (x = 0; x < n; x++) {
14982 if (write(ptyfd,&(p[x]),1) < 0)
14986 #endif /* COMMENT */
14987 debug(F111,"ttptycmd ptyfd write",ckitoa(errno),x);
14990 write_pty_bytes += x;
14994 if (pexitstat < 0) {
14995 status = pty_get_status(ptyfd,pty_fork_pid);
14996 debug(F101,"ttptycmd pty_get_status B","",status);
14997 if (status > -1) pexitstat = status;
15000 debug(F100,"ttptycmd +++ ptyfd write error","",0);
15003 if (FD_ISSET(ttyfd, &in)) { /* Can read from net? */
15005 debug(F100,"ttptycmd FD_ISSET ttyfd in","",0);
15006 n = in_chk(1,ttyfd);
15007 debug(F101,"ttptycmd in_chk(ttyfd)","",n);
15008 if (n < 0 || ttyfd == -1) {
15009 debug(F101,"ttptycmd +++ ttyfd errno","",errno);
15011 } else if (n > 0) {
15012 if (n > PTY_TBUF_SIZE - tbuf_avail)
15013 n = PTY_TBUF_SIZE - tbuf_avail;
15014 debug(F101,"ttptycmd net read size adjusted","",n);
15015 if (xlocal && netconn) {
15017 We have to use a byte loop here because ttxin()
15018 does not decrypt or, for that matter, handle Telnet.
15022 p = tbuf + tbuf_avail;
15023 for (x = 0; x < n; x++) {
15024 if ((c = ttinc(0)) < 0)
15026 if (!is_tn) { /* Not Telnet - keep all bytes */
15028 debug(F000,"<<< char","",c);
15030 } else { /* Telnet - must handle IAC and NVT */
15031 debug(F000,"<<< char",ckitoa(in_state),c);
15033 case 0x00: /* NUL */
15034 if (in_state == HAVE_CR) {
15035 debug(F000,"<<< SKIP","",c);
15038 debug(F000,"<<< Keep","",c);
15042 case 0x0d: /* CR */
15043 if (!TELOPT_U(TELOPT_BINARY))
15044 in_state = HAVE_CR;
15046 debug(F000,"<<< Keep","",c);
15049 case 0x0f: /* Ctrl-O */
15050 case 0x16: /* Ctrl-V */
15053 debug(F000,"<<< QUOT","",c);
15055 #endif /* COMMENT */
15056 case 0xff: /* IAC */
15057 if (in_state == HAVE_IAC) {
15058 debug(F000,"<<< KEEP","",c);
15062 debug(F000,"<<< SKIP","",c);
15063 in_state = HAVE_IAC;
15066 default: /* All others */
15067 if (in_state == HAVE_IAC) {
15070 tn_doop() will consume an unknown number of bytes and we'll overshoot
15071 the for-loop. The only Telnet command I've ever seen arrive here is
15072 a Data Mark, which comes when the remote protocol exits and the remote
15073 job returns to its shell prompt. On the assumption it's a 1-byte command,
15074 we don't write out the IAC or the command, and we clear the state. If
15075 we called tn_doop() we'd have no way of knowing how many bytes it took
15076 from the input stream.
15079 xx = tn_doop((CHAR)c,duplex,ttinc);
15080 debug(F111,"<<< DOOP",ckctoa(c),xx);
15082 debug(F101,"<<< DOOP","",c);
15083 #endif /* COMMENT */
15087 debug(F000,"<<< keep","",c);
15091 #endif /* TNCODE */
15094 ckmakmsg(msgbuf,500,
15095 "ttptycmd read net [ttinc loop] errno=",
15099 debug(F100,msgbuf,"",0);
15101 x = ttxin(n,tbuf+tbuf_avail);
15102 debug(F101,"ttptycmd ttxin x","",x);
15106 debug(F101,"ttptycmd read net error","",x);
15110 read_net_bytes += x;
15116 if (FD_ISSET(ptyfd, &in)) { /* Read from pty? */
15118 debug(F100,"ttptycmd FD_ISSET ptyfd in","",0);
15119 #ifdef PTY_USE_NDELAY
15123 This does not work on nonblocking channels
15124 on certain platforms such as NetBSD.
15126 n = pty_chk(ptyfd);
15127 #endif /* PTY_USE_NDELAY */
15128 debug(F101,"ttptycmd pty_chk() n","",n);
15133 if (n > PTY_PBUF_SIZE - pbuf_avail)
15134 n = PTY_PBUF_SIZE - pbuf_avail;
15135 debug(F101,"ttptycmd pty read size adjusted","",n);
15137 x = read(ptyfd,pbuf+pbuf_avail,n);
15140 ckmakmsg(msgbuf,500,
15141 "ttptycmd read pty errno=",
15145 debug(F100,msgbuf,"",0);
15149 if (x < 0 && errno == EAGAIN)
15152 if (x < 0) { /* This works on Solaris and Linux */
15153 pty_err++; /* but not NetBSD */
15154 debug(F100,"TERMINATION TEST A","",0);
15158 #endif /* COMMENT */
15159 if (pexitstat < 0) {
15160 status = pty_get_status(ptyfd,pty_fork_pid);
15161 debug(F101,"ttptycmd pty_get_status C","",status);
15162 if (status > -1) pexitstat = status;
15167 if (x == 0 && !pty_err) { /* This works on NetBSD but */
15168 debug(F100,"TERMINATION TEST B","",0);
15169 status = pexitstat > -1 ? pexitstat :
15170 pty_get_status(ptyfd,pty_fork_pid);
15171 debug(F101,"ttptycmd pty_get_status D","",status);
15173 pexitstat = status;
15176 } else { /* Select() lied */
15177 pty_err = 0; /* pty still there but has nothing */
15178 msleep(100); /* sleep a bit */
15182 /* Hopefully the next two are no longer needed... */
15184 #ifndef PTY_USE_NDELAY
15187 errno != 0 && errno != EAGAIN
15188 #endif /* PTY_USE_NDELAY */
15190 debug(F100,"TERMINATION TEST C","",0);
15192 debug(F101,"ttptycmd SET pty_err","",pty_err);
15193 if (errno == EIO) /* errno == EIO is like EOF */
15201 pbuf[pbuf_avail + x] = '\0';
15202 debug(F111,"ttptycmd added to pty buffer",
15203 pbuf+pbuf_avail,x);
15206 #endif /* COMMENT */
15208 read_pty_bytes += x;
15209 } else { /* n == 0 with blocking reads */
15211 "PTY READ RETURNED ZERO BYTES - SHOULD NOT HAPPEN",
15217 /* If writes have caught up to reads, reset the buffers */
15219 if (pbuf_written == pbuf_avail)
15220 pbuf_written = pbuf_avail = 0;
15221 if (tbuf_written == tbuf_avail)
15222 tbuf_written = tbuf_avail = 0;
15224 /* See if we can exit */
15226 x1 = pbuf_avail - pbuf_written;
15227 x2 = tbuf_avail - tbuf_written;
15229 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pty_err","",pty_err);
15230 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x1 [write to net]","",x1);
15231 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x2 [write to pty]","",x2);
15232 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc","",rc);
15233 debug(F101,"ttptycmd pty_err LOOP EXIT TEST status","",status);
15234 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pexitstat","",pexitstat);
15236 if (net_err) { /* Net error? */
15237 debug(F101,"ttptycmd net_err LOOP EXIT TEST net_err","",net_err);
15241 printf("?Connection closed\n");
15245 debug(F101,"ttptycmd net_err LOOP EXIT TEST x1","",x1);
15249 if (pty_err) { /* Pty error? */
15251 if (pexitstat < 0) {
15252 status = pty_get_status(ptyfd,pty_fork_pid);
15253 debug(F101,"ttptycmd pty_get_status E","",status);
15254 if (status > -1) pexitstat = status;
15258 if (x1 == 0 && x2 == 0) { /* If buffers are caught up */
15259 rc = 1; /* set preliminary return to success */
15260 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc 2","",rc);
15261 break; /* and exit the loop */
15265 debug(F101,"ttptycmd +++ have_pty","",have_pty);
15266 if (have_pty) { /* In case select() failed */
15267 #ifdef USE_CKUPTY_C
15273 #endif /* USE_CKUPTY_C */
15275 pty_master_fd = -1;
15276 debug(F101,"ttptycmd +++ pexitstat","",pexitstat);
15277 if (pexitstat < 0) { /* Try one last time to get status */
15278 status = pty_get_status(ptyfd,pty_fork_pid);
15279 debug(F101,"ttptycmd pty_get_status F","",status);
15280 if (status > -1) pexitstat = status;
15282 debug(F101,"ttptycmd +++ final pexitstat","",pexitstat);
15283 if (deblog) { /* Stats for debug log */
15284 debug(F101,"ttptycmd +++ pset ","",pset);
15285 debug(F101,"ttptycmd +++ pnotset","",pnotset);
15286 debug(F101,"ttptycmd +++ tset ","",tset);
15287 debug(F101,"ttptycmd +++ tnotset","",tnotset);
15289 debug(F101,"ttptycmd +++ read_pty_bytes","",read_pty_bytes);
15290 debug(F101,"ttptycmd +++ write_net_bytes","",write_net_bytes);
15291 debug(F101,"ttptycmd +++ read_net_bytes","",read_net_bytes);
15292 debug(F101,"ttptycmd +++ write_pty_bytes","",write_pty_bytes);
15295 If we got the external protocol's exit status from waitpid(), we use that
15296 to set our return code. If not, we fall back on whatever rc was previously
15297 set to, namely 1 (success) if the pty fork seemed to terminate, 0 otherwise.
15299 if (save_sigchld) { /* Restore this if we changed it */
15300 (VOID) signal(SIGCHLD,save_sigchld);
15301 save_sigchld = NULL;
15304 x = kill(pty_fork_pid,SIGHUP); /* In case it's still there */
15306 debug(F101,"ttptycmd fork kill SIGHUP","",x);
15307 if (pexitstat > -1)
15308 rc = (pexitstat == 0 ? 1 : 0);
15309 debug(F101,"ttptycmd +++ rc","",rc);
15310 if (!local) { /* If in remote mode */
15311 conres(); /* restore console to CBREAK mode */
15312 concb((char)escchr);
15316 #endif /* NETPTY */
15317 #endif /* SELECT */
15319 /* T T R U N C M D -- Redirect an external command over the connection. */
15322 TTRUNCMD is the routine that was originally used for running external
15323 protocols. It is very simple and works fine provided (a) the connection
15324 is not encrypted, and (b) the external protocol uses standard i/o
15325 (file descriptors 0 and 1) for file transfer.
15329 ttruncmd(s) char *s; {
15330 PID_T pid; /* pid of lower fork */
15331 int wstat; /* for wait() */
15336 printf("?Sorry, device is not open\n");
15340 debug(F100,"ttruncmd fail: nopush","",0);
15346 It might also be necessary to use the pty routine for other reasons,
15347 e.g. because the external program does not use stdio.
15351 If we have a network connection we use a different routine because
15352 (a) if the connection is encrypted, the mechanism used here can't deal
15353 with it; and (b) it won't handle any network protocols either, e.g.
15354 Telnet, Rlogin, K5 U-to-U, etc. However, this routine works much
15355 better (faster, more transparent) on serial connections and when
15356 C-Kermit is in remote mode (i.e. is on the far end).
15358 /* For testing always use this */
15360 return(ttptycmd(s));
15361 #endif /* NETCONN */
15365 if (tt_is_secure()) {
15367 external protocols over secure connections not supported in this OS.\n"
15371 #endif /* NETPTY */
15373 conres(); /* Make console normal */
15375 if ((pid = fork()) == 0) { /* Make a child fork */
15376 if (priv_can()) /* Child: turn off privs. */
15378 dup2(ttyfd, 0); /* Give stdin/out to the line */
15381 debug(F101,"ttruncmd system",s,x);
15382 _exit(x ? BAD_EXIT : 0);
15384 SIGTYP (*istat)(), (*qstat)();
15385 if (pid == (PID_T) -1) /* fork() failed? */
15387 istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
15388 qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
15391 while (((wstat = wait(&statusp)) != pid) && (wstat != -1)) ;
15392 #else /* Not COMMENT */
15394 wstat = wait(&statusp);
15395 debug(F101,"ttruncmd wait","",wstat);
15396 if (wstat == pid || wstat == -1)
15399 #endif /* COMMENT */
15401 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
15402 debug(F101,"ttruncmd wait statusp","",statusp);
15403 debug(F101,"ttruncmd wait pexitstat","",pexitstat);
15404 signal(SIGINT,istat); /* Restore interrupts */
15405 signal(SIGQUIT,qstat);
15407 concb((char)escchr); /* Restore console to CBREAK mode */
15408 return(statusp == 0 ? 1 : 0);
15410 #endif /* CK_REDIR */
15414 cmdate2tm(char * date, int gmt) /* date as "yyyymmdd hh:mm:ss" */
15416 cmdate2tm(date,gmt) char * date; int gmt;
15419 /* date as "yyyymmdd hh:mm:ss" */
15420 static struct tm _tm;
15423 if (strlen(date) != 17 ||
15431 _tm = *gmtime(&now);
15433 _tm = *localtime(&now);
15434 _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
15435 (date[2]-'0')*10 + (date[3]-'0')-1900;
15436 _tm.tm_mon = (date[4]-'0')*10 + (date[5]-'0')-1;
15437 _tm.tm_mday = (date[6]-'0')*10 + (date[7]-'0');
15438 _tm.tm_hour = (date[9]-'0')*10 + (date[10]-'0');
15439 _tm.tm_min = (date[12]-'0')*10 + (date[13]-'0');
15440 _tm.tm_sec = (date[15]-'0')*10 + (date[16]-'0');
15442 /* Should we set _tm.tm_isdst to -1 here? */
15456 priv_kill(pid, sig) int pid, sig; {
15460 debug(F100,"priv_kill priv_on failed","",0);
15461 i = kill(pid, sig);
15463 debug(F100,"priv_kill priv_off failed","",0);
15469 /* #ifdef BE_DR_7 */
15471 alarm() function not supplied with Be OS DR7 - this one contributed by
15476 This should mimic the UNIX/POSIX alarm() function well enough, with the
15477 caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
15478 and wait for the alarm thread to finish.
15481 alarm(unsigned int seconds) {
15482 long time_left = 0;
15484 /* If an alarm is active, turn it off, saving the unused time */
15485 if (alarm_thread != -1) {
15486 /* We'll be generous and count partial seconds as whole seconds. */
15487 time_left = alarm_struct.time -
15488 ((system_time() - time_started) / 1000000.0);
15490 /* Kill the alarm thread */
15491 kill_thread (alarm_thread);
15493 /* We need to clean up as though the alarm occured. */
15495 alarm_struct.thread = -1;
15496 alarm_struct.time = 0;
15500 /* Set a new alarm clock, if requested. */
15502 alarm_struct.thread = find_thread(NULL);
15503 alarm_struct.time = seconds;
15504 time_started = system_time();
15505 alarm_thread = spawn_thread (do_alarm,
15508 (void *) &alarm_struct
15510 resume_thread (alarm_thread);
15513 /* Now return [unused time | 0] */
15514 return ((unsigned int) time_left);
15518 This function is the departure from UNIX/POSIX alarm handling. In the case
15519 of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
15520 handler. When Be implements alarm(), this function call can be eliminated
15521 from user's SIGALRM signal handlers.
15525 alarm_expired(void) {
15528 if (alarm_thread != -1) {
15529 wait_for_thread (alarm_thread, &ret_val);
15535 This is the function that snoozes the requisite number of seconds and then
15536 SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
15537 uses thread_id; currently they are both typdef'ed as long, but I'll do the
15538 cast anyway. This function is run in a separate thread.
15542 do_alarm (void *alarm_struct) {
15543 snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
15544 kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
15546 ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
15547 ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
15549 /* #endif */ /* BE_DR_7 */
15550 #endif /* BEOSORBEBOX */
15555 p9ttyctl(char letter, int num, int param) {
15564 len = sprintf(cmd + 1, "%d", param) + 1;
15569 if (write(ttyctlfd, cmd, len) == len) {
15571 /* fprintf(stdout, "wrote '%s'\n", cmd); */
15578 p9ttyparity(char l) {
15579 return p9ttyctl('p', 0, l);
15583 p9tthflow(int flow, int status) {
15584 return p9ttyctl('m', 1, status);
15588 p9ttsspd(int cps) {
15589 if (p9ttyctl('b', 1, cps * 10) < 0)
15591 ttylastspeed = cps * 10;
15596 p9openttyctl(char *ttname) {
15599 if (ttyctlfd >= 0) {
15604 sprintf(name, "%sctl", ttname);
15605 ttyctlfd = open(name, 1);
15611 if (consctlfd >= 0) {
15612 if (write(consctlfd, "rawon", 5) == 5)
15625 if (consctlfd >= 0) {
15626 if (write(consctlfd, "rawoff", 6) == 6)
15633 p9sndbrk(int msec) {
15634 if (ttyctlfd >= 0) {
15636 int i = sprintf(cmd, "k%d", msec);
15637 if (write(ttyctlfd, cmd, i) == i)
15644 conwrite(char *buf, int n) {
15646 static int length = 0;
15647 static int holdingcr = 0;
15649 for (x = 0; x < n; x++) {
15653 write(1, buf + (x - normal), normal);
15657 /* write(noisefd, "1000 300", 8); */
15659 } else if (c == '\r') {
15661 write(1, buf + (x - normal), normal);
15666 } else if (c == '\n') {
15667 write(1, buf + (x - normal), normal + 1);
15671 } else if (c == '\b') {
15673 write(1, buf + (x - normal), normal);
15685 while (length-- > 0)
15687 length = 0; /* compiler bug */
15694 write(1, buf + (x - normal), normal);
15701 conprint(char *fmt, ...) {
15702 static char buf[1000]; /* not safe if on the stack */
15708 i = vsprintf(buf, fmt, ap);
15713 /* fprintf, printf, perror replacements... */
15715 /* f p r i n t f */
15719 #include <stdarg.h>
15720 #else /* CK_ANSIC */
15722 #include <stdarg.h>
15724 #include <varargs.h>
15725 #endif /* __GNUC__ */
15726 #endif /* CK_ANSIC */
15729 static char str1[4096];
15730 static char str2[4096];
15733 ckxfprintf(FILE * file, const char * format, ...)
15734 #else /* CK_ANSIC */
15735 ckxfprintf(va_alist) va_dcl
15736 #endif /* CK_ANSIC */
15738 int i, j, len, got_cr;
15743 va_start(args, format);
15744 #else /* CK_ANSIC */
15748 file = va_arg(args,FILE *);
15749 format = va_arg(args,char *);
15750 #endif /* CK_ANSIC */
15752 if (!inserver || (file != stdout && file != stderr && file != stdin)) {
15753 rc = vfprintf(file,format,args);
15756 rc = vsprintf(str1, format, args);
15757 len = strlen(str1);
15758 if (len >= sizeof(str1)) {
15759 debug(F101,"ckxfprintf() buffer overflow","",len);
15760 doexit(BAD_EXIT,1);
15762 for (i = 0, j = 0, got_cr = 0;
15763 i < len && j < sizeof(str1)-2;
15765 /* We can't use 255 as a case label because of signed chars */
15766 c = (unsigned)(str1[i] & 0xff);
15769 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15775 #endif /* TNCODE */
15780 && !TELOPT_ME(TELOPT_BINARY)
15781 #endif /* TNCODE */
15796 && !TELOPT_ME(TELOPT_BINARY)
15797 #endif /* TNCODE */
15806 && !TELOPT_ME(TELOPT_BINARY)
15807 #endif /* TNCODE */
15810 #ifdef CK_ENCRYPTION
15812 if (TELOPT_ME(TELOPT_ENCRYPTION))
15813 ck_tn_encrypt(str2,j);
15814 #endif /* TNCODE */
15815 #endif /* CK_ENCRYPTION */
15817 if (inserver && (ssl_active_flag || tls_active_flag)) {
15818 /* Write using SSL */
15821 if (ssl_active_flag)
15822 rc = SSL_write(ssl_con, p, j);
15824 rc = SSL_write(tls_con, p, j);
15825 debug(F111,"ckxfprintf","SSL_write",rc);
15826 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
15827 case SSL_ERROR_NONE:
15833 case SSL_ERROR_WANT_WRITE:
15834 case SSL_ERROR_WANT_READ:
15835 case SSL_ERROR_SYSCALL:
15838 case SSL_ERROR_WANT_X509_LOOKUP:
15839 case SSL_ERROR_SSL:
15840 case SSL_ERROR_ZERO_RETURN:
15845 #endif /* CK_SSL */
15846 fwrite(str2,sizeof(char),j,stdout);
15851 #endif /* fprintf */
15859 ckxprintf(const char * format, ...)
15860 #else /* CK_ANSIC */
15861 ckxprintf(va_alist) va_dcl
15862 #endif /* CK_ANSIC */
15864 int i, j, len, got_cr;
15869 va_start(args, format);
15870 #else /* CK_ANSIC */
15873 format = va_arg(args,char *);
15874 #endif /* CK_ANSIC */
15877 rc = vprintf(format, args);
15880 rc = vsprintf(str1, format, args);
15881 len = strlen(str1);
15882 if (len >= sizeof(str1)) {
15883 debug(F101,"ckxprintf() buffer overflow","",len);
15884 doexit(BAD_EXIT,1);
15886 for (i = 0, j = 0, got_cr=0;
15887 i < len && j < sizeof(str1)-2;
15889 c = (unsigned)(str1[i] & 0xff);
15892 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15898 #endif /* TNCODE */
15903 && !TELOPT_ME(TELOPT_BINARY)
15904 #endif /* TNCODE */
15919 && !TELOPT_ME(TELOPT_BINARY)
15920 #endif /* TNCODE */
15930 && !TELOPT_ME(TELOPT_BINARY)
15931 #endif /* TNCODE */
15934 #ifdef CK_ENCRYPTION
15936 if (TELOPT_ME(TELOPT_ENCRYPTION))
15937 ck_tn_encrypt(str2,j);
15938 #endif /* TNCODE */
15939 #endif /* CK_ENCRYPTION */
15941 if (inserver && (ssl_active_flag || tls_active_flag)) {
15943 /* Write using SSL */
15945 if (ssl_active_flag)
15946 rc = SSL_write(ssl_con, p, j);
15948 rc = SSL_write(tls_con, p, j);
15949 debug(F111,"ckxprintf","SSL_write",rc);
15950 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
15951 case SSL_ERROR_NONE:
15957 case SSL_ERROR_WANT_WRITE:
15958 case SSL_ERROR_WANT_READ:
15959 case SSL_ERROR_SYSCALL:
15962 case SSL_ERROR_WANT_X509_LOOKUP:
15963 case SSL_ERROR_SSL:
15964 case SSL_ERROR_ZERO_RETURN:
15969 #endif /* CK_SSL */
15970 rc = fwrite(str2,sizeof(char),j,stdout);
15975 #endif /* printf */
15981 _PROTOTYP(char * ck_errstr,(VOID));
15989 #endif /* CK_SCOV5 */
15992 ckxperror(const char * str)
15993 #else /* CK_ANSIC */
15994 ckxperror(str) char * str;
15995 #endif /* CK_ANSIC */
15997 char * errstr = ck_errstr();
16001 #endif /* CK_SCOV5 */
16003 ckxprintf("%s%s %s\n",str,*errstr?":":"",errstr);
16005 #endif /* perror */
16010 /* Minix doesn't have a gettimeofday call (but MINIX3 does).
16011 * We fake one here using time(2)
16016 gettimeofday(struct timeval *tp, struct timezone *tzp) {
16017 tp->tv_usec = 0L; /* Close enough for horseshoes */
16018 if(time(&(tp->tv_sec))==-1)
16022 #endif /* MINIX3 */
16026 readlink(const char *path, void *buf, size_t bufsiz) {
16030 #endif /* MINIX3 */
16032 #endif /* MINIX2 */