4 char *ckxv = "Aegis Communications support, 9.0.323, 10 June 2011";
7 char *ckxv = "Plan 9 Communications support, 9.0.323, 10 June 2011";
9 char *ckxv = "UNIX Communications support, 9.0.323, 10 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 */
833 #endif /* FIONREAD */
836 /* Whether to include <fcntl.h> */
838 #ifndef is68k /* Only a few don't have this one. */
844 #endif /* COHERENT */
848 #endif /* not is68k */
854 #include <sys/fcntl.h>
856 #endif /* COHERENT */
858 #ifdef ATT7300 /* Unix PC, internal modem dialer */
859 #include <sys/phone.h>
862 #ifdef HPUX /* HP-UX variations. */
864 #include <sys/modem.h> /* HP-UX modem signals */
865 #ifdef hp9000s500 /* Model 500 */
867 #endif /* hp9000s500 */
871 #endif /* HPUXPRE65 */
873 #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */
874 #endif /* HPUXJOBCTL */
878 Which time.h files to include... See ckcdeb.h for defaults.
879 Note that 0, 1, 2, or all 3 of these can be included according to
880 the symbol definitions.
890 #include <sys/time.h>
891 #endif /* SYSTIMEH */
892 #endif /* NOSYSTIMEH */
896 #include <sys/timeb.h>
897 #endif /* SYSTIMEBH */
898 #endif /* NOSYSTIMEBH */
903 In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to
904 define the structs we need to access the higher speeds, so we have to
915 #endif /* DCLTIMEVAL */
916 #endif /* NODCLTIMEVAL */
919 /* THIS IS OBSOLETE since about Linux 0.92 */
921 #include <linux/serial.h>
922 #endif /* OLINUXHISPEED */
923 #ifdef __alpha__ /* Linux on DEC Alpha */
924 #ifndef __GLIBC__ /* But not with glibc */
925 #include <asm/termios.h>
926 #endif /* __GLIBC__ */
927 #endif /* __alpha__ */
928 #endif /* __linux__ */
930 #ifdef NOIEXTEN /* This is broken on some systems */
931 #undef IEXTEN /* like Convex/OS 9.1 */
932 #endif /* NOIEXTEN */
933 #ifndef IEXTEN /* Turn off ^O/^V processing. */
934 #define IEXTEN 0 /* Needed, at least, on BSDI. */
937 Pick up definitions needed for select() if we don't have them already.
938 Normally they come from <sys/types.h> but some systems get them from
939 <sys/select.h>... Rather than hardwire all of them into the source, we
940 include it if SELECT_H is defined in compile-time CFLAGS.
944 #include <sys/select.h>
945 #endif /* SELECT_H */
946 #endif /* SCO_OSR504 */
949 #include "/sys/ins/base.ins.c"
950 #include "/sys/ins/error.ins.c"
951 #include "/sys/ins/ios.ins.c"
952 #include "/sys/ins/sio.ins.c"
953 #include "/sys/ins/pad.ins.c"
954 #include "/sys/ins/time.ins.c"
955 #include "/sys/ins/pfm.ins.c"
956 #include "/sys/ins/pgm.ins.c"
957 #include "/sys/ins/ec2.ins.c"
958 #include "/sys/ins/type_uids.ins.c"
959 #include <default_acl.h>
964 #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */
968 /* The following #defines are catch-alls for those systems */
969 /* that didn't have or couldn't find <file.h>... */
981 #endif /* O_RDONLY */
983 /* This is for ancient Unixes that don't have these tty symbols defined. */
986 #define PENDIN ICANON
989 #define FLUSHO ICANON
992 #define EXTPROC ICANON
997 Modem signals are also forbidden in the POSIX world. But some POSIX-based
998 platforms let us at them anyway if we know where to look.
1001 /* Doesn't work for Linux */
1004 #endif /* UNIXWARE7 */
1005 #endif /* NEEDMDMDEFS */
1009 #define TIOCMGET (('t'<<8)|29)
1010 #endif /* TIOCMGET */
1013 #define TIOCM_DTR 0x0002
1014 #endif /* TIOCM_DTR */
1016 #define TIOCM_RTS 0x0004
1017 #endif /* TIOCM_RTS */
1019 #define TIOCM_CTS 0x0020
1020 #endif /* TIOCM_CTS */
1022 #define TIOCM_CAR 0x0040
1023 #endif /* TIOCM_CAR */
1025 #define TIOCM_RNG 0x0080
1026 #endif /* TIOCM_RNG */
1028 #define TIOCM_DSR 0x0100
1029 #endif /* TIOCM_DSR */
1030 #endif /* NEEDMDMDEFS */
1031 #endif /* SVORPOSIX */
1040 #define TCGETA TCGETS
1041 #define TCSETA TCSETS
1042 #define TCSETAW TCSETSW
1043 #define TCSETAF TCSETSF
1044 #define termio termios
1047 #ifdef SVORPOSIX /* AT&T Sys V or POSIX */
1048 #ifdef UNIXWAREPOSIX /* UnixWare 7 POSIX build */
1050 In Unixware POSIX builds, <[sys/]time.h> refuses to define the
1051 structs we need to access the higher speeds, so we have to do it
1062 #endif /* UNIXWAREPOSIX */
1063 #endif /* SVORPOSIX */
1068 Because Xenix <time.h> doesn't declare time() if we're using gcc.
1072 #endif /* __GNUC__ */
1074 /* Special stuff for V7 input buffer peeking */
1077 int kmem[2] = { -1, -1};
1078 char *initrawq(), *qaddr[2]={0,0};
1083 /* dftty is the device name of the default device for file transfer */
1084 /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
1087 char * dftty = NULL;
1088 char * dfmdm = "none";
1089 int dfloc = 0; /* that goes in local mode by default */
1093 char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
1094 char *dfmdm = "none";
1095 int dfloc = 1; /* that goes in local mode by default */
1097 char *dftty = CTTNAM; /* Remote by default, use normal */
1098 char *dfmdm = "none";
1099 int dfloc = 0; /* controlling terminal name. */
1102 char *dftty = DFTTY; /* Default location specified on */
1103 char *dfmdm = "none"; /* command line. */
1104 int dfloc = 1; /* controlling terminal name. */
1108 #define CON_RES 0 /* Console state is "reset" */
1109 #define CON_CB 1 /* Console state is CBREAK */
1110 #define CON_BIN 2 /* Console state is binary */
1111 static int constate = CON_RES;
1113 #define CONI_RES 0 /* Console interrupts are "reset" */
1114 #define CONI_INT 1 /* Console intterupts are set */
1115 #define CONI_NOI 2 /* Console intterupts are disabled */
1116 static int conistate = CONI_RES;
1119 #define CONBUFSIZ 15
1121 #define CONBUFSIZ 255
1122 #endif /* CK_SMALL */
1123 static char conbuf[CONBUFSIZ]; /* Console readahead buffer */
1124 static int conbufn = 0; /* Chars in readahead buffer */
1125 static char *conbufp = conbuf; /* Next char in readahead buffer */
1127 char cttnam[DEVNAMLEN+1] = { '\0', '\0' }; /* Determined at runtime */
1130 int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */
1133 int dfprty = DEFPAR; /* Default parity (0 = none) */
1134 int ttprty = 0; /* The parity that is in use. */
1135 static int ttpmsk = 0xff; /* Parity stripping mask. */
1136 int ttmdm = 0; /* Modem in use. */
1137 int ttcarr = CAR_AUT; /* Carrier handling mode. */
1138 int dfflow = FLO_NONE; /* Default flow control is NONE */
1139 int backgrd = 0; /* Assume in foreground (no '&' ) */
1141 int iniflags = -1; /* fcntl flags for ttyfd */
1142 #endif /* F_SETFL */
1143 int fdflag = 0; /* Flag for redirected stdio */
1144 int ttfdflg = 0; /* Open File descriptor was given */
1145 int tvtflg = 0; /* Flag that ttvt has been called */
1146 long ttspeed = -1L; /* For saving speed */
1147 int ttflow = -9; /* For saving flow */
1148 int ttld = -1; /* Line discipline */
1151 static int km_con = -1; /* Kanji mode for console tty */
1152 static int km_ext = -1; /* Kanji mode for external device */
1153 #endif /* sony_news */
1156 static int needpchk = 1; /* Need parity check */
1158 static int needpchk = 0;
1159 #endif /* PARSENSE */
1161 extern int stopbits; /* Stop bits */
1164 Unfortunately we must do this with global variables rather than through the
1165 tt...() APIs to avoid changing the APIs and the many modules that use them.
1166 If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
1167 bits + parity or 8 data bits and no parity, and overrides the regular parity
1168 variable, which is communicated to this module thru ttpkt(), and represented
1169 locally by the ttprty variable.
1171 extern int hwparity; /* Hardware parity */
1172 #endif /* HWPARITY */
1176 static int nodelay_sav = -1;
1177 #endif /* TCP_NODELAY */
1178 #endif /* TCPSOCKET */
1180 static int sigint_ign = 0; /* SIGINT is ignored */
1183 Having this module rely on external globals is bad, but fixing this
1184 requires overhaul of the ck*tio.c modules for all the different operating
1185 systems supported by C-Kermit. Left for a future release.
1187 extern int ttnproto; /* Defined in ckcnet.c */
1188 extern int ttnet; /* Defined in ckcnet.c */
1189 extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */
1190 extern int xsuspend, wasclosed;
1191 extern int inserver, local;
1193 int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
1195 int ckmaxfiles = 0; /* Max number of open files */
1197 #ifdef CK_ENCRYPTION /* Kerberos */
1199 extern int me_encrypt, u_encrypt;
1200 #endif /* CK_ENCRYPTION */
1202 /* Declarations of variables global within this module */
1204 #ifdef TTLEBUF /* See ckcnet.h */
1206 #define LEBUFSIZ 4096
1207 static CHAR le_buf[LEBUFSIZ];
1208 static int le_start = 0, le_end = 0, le_data = 0;
1209 #endif /* TTLEBUF */
1211 #define MSGBUF_SIZE 1024 /* For debugging */
1212 static char msgbuf[MSGBUF_SIZE];
1214 static int gotsigs = 0;
1216 static time_t tcount = (time_t)0; /* Elapsed time counter */
1218 static SIGTYP (*saval)() = NULL; /* For saving alarm() handler */
1219 static SIGTYP (*savquit)() = NULL; /* and other signal handlers */
1221 static SIGTYP (*savusr1)() = NULL;
1222 #endif /* SIGUSR1 */
1224 static SIGTYP (*savusr2)() = NULL;
1225 #endif /* SIGUSR2 */
1227 static SIGTYP (*savpipe)() = NULL;
1228 #endif /* SIGPIPE */
1230 static SIGTYP (*savdanger)() = NULL;
1231 #endif /* SIGDANGER */
1234 static SIGTYP (*jchdlr)() = NULL; /* For checking suspend handler */
1236 static int jcshell = -1; /* And flag for result */
1239 BREAKNULS is defined for systems that simulate sending a BREAK signal
1240 by sending a bunch of NUL characters at low speed.
1245 #endif /* BREAKNULS */
1251 #endif /* BREAKNULS */
1255 static char /* A string of nulls */
1256 *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";
1257 #endif /* BREAKNULS */
1259 #ifdef CK_POSIX_SIG /* Longjump buffers */
1260 static sigjmp_buf sjbuf; /* POSIX signal handling */
1262 static jmp_buf sjbuf;
1263 #endif /* CK_POSIX_SIG */
1266 static jmp_buf jjbuf;
1269 /* static */ /* (Not static any more) */
1270 int ttyfd = -1; /* TTY file descriptor */
1272 int ttpipe = 0; /* NETCMD: Use pipe instead of ttyfd */
1273 int ttpty = 0; /* NETPTY: Use pty instead of ttfyd */
1275 #ifdef NETPTY /* These are in ckupty.c */
1276 extern PID_T pty_fork_pid;
1277 extern int pty_master_fd, pty_slave_fd;
1282 static int pipe0[2], pipe1[2]; /* Pipes for net i/o */
1283 #endif /* NETCONN */
1284 static PID_T ttpid = 0; /* Process ID for fork */
1285 static int fdin, fdout; /* File descriptors for pipe */
1286 static FILE * ttout = NULL; /* File pointer for output pipe */
1288 /* fdopen() needs declaring because it's not declared in <stdio.h> */
1289 _PROTOTYP( FILE * fdopen, (int, char *) );
1290 #endif /* DCLFDOPEN */
1293 extern int pexitstat, quiet;
1296 int ttyctlfd = -1; /* TTY control channel - What? UNIX doesn't have one? */
1297 int consctlfd = -1; /* Console control channel */
1298 int noisefd = -1; /* tone channel */
1299 static int ttylastspeed = -1; /* So we can lie about the speed */
1302 int telnetfd = 0; /* File descriptor is for telnet */
1304 int x25fd = 0; /* File descriptor is for X.25 */
1305 #endif /* NETCONN */
1307 char lockpid[16] = { '\0', '\0' }; /* PID stored in lockfile, as string */
1309 static int lkf = 0, /* Line lock flag */
1310 cgmf = 0, /* Flag that console modes saved */
1311 xlocal = 0, /* Flag for tty local or remote */
1312 curcarr = 0; /* Carrier mode: require/ignore. */
1314 static int netconn = 0; /* 1 if network connection active */
1316 static char escchr; /* Escape or attn character */
1319 #include <sys/time.h>
1320 #endif /* CK_SCO32V4 */
1323 static struct timeval tv; /* For getting time, from sys/time.h */
1324 #endif /* HAVE_TV */
1326 static struct timezone tz;
1327 #endif /* HAVE_TZ */
1330 static struct timeb ftp; /* And from sys/timeb.h */
1334 static long xclock; /* For getting time from sys/time.h */
1335 static struct timeb ftp; /* And from sys/timeb.h */
1339 static long xclock; /* For getting time from sys/time.h */
1340 static struct timeb ftp; /* And from sys/timeb.h */
1344 static long xclock; /* For getting time from sys/time.h */
1345 static struct timeb ftp; /* And from sys/timeb.h */
1346 #endif /* BELLV10 */
1349 static long xclock; /* For getting time from sys/time.h */
1350 static struct timeb ftp; /* And from sys/timeb.h */
1354 static long xclock; /* For getting time from sys/time.h */
1355 static struct timeb ftp; /* And from sys/timeb.h */
1359 static long xclock; /* For getting time from sys/time.h */
1360 static struct timeb ftp; /* And from sys/timeb.h */
1361 #endif /* COHERENT */
1367 /* sgtty/termio information... */
1369 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
1370 static struct termios
1371 ttold, ttraw, tttvt, ttcur,
1372 ccold, ccraw, cccbrk;
1373 #else /* BSD, V7, etc */
1375 #ifdef COHERENT /* Hack alert... */
1377 #endif /* COHERENT */
1380 static struct termio ttold = {0}; /* Init'd for word alignment, */
1381 static struct termio ttraw = {0}; /* which is important for some */
1382 static struct termio tttvt = {0}; /* systems, like Zilog... */
1383 static struct termio ttcur = {0};
1384 static struct termio ccold = {0};
1385 static struct termio ccraw = {0};
1386 static struct termio cccbrk = {0};
1388 static struct sgttyb /* sgtty info... */
1389 ttold, ttraw, tttvt, ttcur, /* for communication line */
1390 ccold, ccraw, cccbrk; /* and for console */
1392 static struct ttydevb /* Device info... */
1393 tdold, tdcur; /* for communication device */
1394 #endif /* BELLV10 */
1396 static struct tchars tchold, tchnoi;
1399 #endif /* TIOCGETC */
1401 static struct ltchars ltchold, ltchnoi;
1403 #endif /* TIOCGLTC */
1404 int lmodef = 0; /* Local modes */
1407 #endif /* BSD44ORPOSIX */
1410 /* It picks up the speeds but they don't work */
1411 #ifdef UNIXWARE /* For higher serial speeds */
1412 #ifdef UW7 /* in Unixware 7.0 */
1413 #include <sys/asyc.h> /* This picks up 57600 and 115200 */
1415 #endif /* UNIXWARE */
1416 #endif /* COMMENT */
1419 static struct sgttyb ttbuf;
1423 /* do we really need this? */
1424 static struct sgttyb vanilla;
1428 static int attmodem = 0; /* ATT7300 internal-modem status */
1429 struct updata dialer = {0}; /* Condition dialer for data call */
1430 #endif /* ATT7300 */
1436 char lkflfn[FLFNAML] = { '\0', '\0' }; /* and possible link to it */
1438 char lock2[FLFNAML] = { '\0', '\0' }; /* Name of second lockfile */
1439 #endif /* USETTYLOCK */
1443 char flfnam[FLFNAML+1] = { '\0', '\0' }; /* UUCP lock file path name */
1445 int haslock = 0; /* =1 if this kermit locked uucp */
1449 static int conesc = 0; /* set to 1 if esc char (^\) typed */
1452 static int conesc = 0;
1455 static int conesc = 0;
1458 #endif /* SVORPOSIX */
1461 /* Local copy of comm device name or network host */
1462 static char ttnmsv[DEVNAMLEN+1] = { '\0', '\0' };
1464 static char lockname[DEVNAMLEN+1]; /* Ditto, the part after "/dev/". */
1465 #endif /* USETTYLOCK */
1468 static status_$t st; /* error status return value */
1469 static short concrp = 0; /* true if console is CRP pad */
1470 static uid_$t ttyuid; /* tty type uid */
1471 static uid_$t conuid; /* stdout type uid */
1473 /* APOLLO Aegis main()
1474 * establish acl usage and cleanup handling
1475 * this makes sure that CRP pads
1476 * get restored to a usable mode
1478 main(argc,argv) int argc; char **argv; {
1480 pfm_$cleanup_rec dirty;
1482 PID_T pid = getpid();
1484 /* acl usage according to invoking environment */
1485 default_acl(USE_DEFENV);
1487 /* establish a cleanup continuation */
1488 status = pfm_$cleanup(dirty);
1489 if (status.all != pfm_$cleanup_set) {
1490 /* only handle faults for the original process */
1491 if (pid == getpid() && status.all > pgm_$max_severity) {
1492 /* blew up in main process */
1494 pfm_$cleanup_rec clean;
1496 /* restore the console in any case */
1499 /* attempt a clean exit */
1500 debug(F101, "cleanup fault status", "", status.all);
1502 /* doexit(), then send status to continuation */
1503 quo = pfm_$cleanup(clean);
1504 if (quo.all == pfm_$cleanup_set)
1505 doexit(pgm_$program_faulted,-1);
1506 else if (quo.all > pgm_$max_severity)
1507 pfm_$signal(quo); /* blew up in doexit() */
1509 /* send to the original continuation */
1510 pfm_$signal(status);
1513 return(ckcmai(argc, argv));
1517 /* ANSI-style prototypes for internal functions. */
1518 /* Functions used outside this module are prototyped in ckcker.h. */
1521 _PROTOTYP( SIGTYP timerh, () );
1522 _PROTOTYP( SIGTYP cctrap, () );
1523 _PROTOTYP( SIGTYP esctrp, () );
1524 _PROTOTYP( SIGTYP sig_ign, () );
1526 _PROTOTYP( SIGTYP timerh, (int) );
1527 _PROTOTYP( SIGTYP cctrap, (int) );
1528 _PROTOTYP( SIGTYP esctrp, (int) );
1530 _PROTOTYP( int do_open, (char *) );
1531 _PROTOTYP( static int in_chk, (int, int) );
1532 _PROTOTYP( static int ttrpid, (char *) );
1533 _PROTOTYP( static int ttchkpid, (char *) );
1534 _PROTOTYP( static int ttlock, (char *) );
1535 _PROTOTYP( static int ttunlck, (void) );
1536 _PROTOTYP( static VOID sigchld_handler, (int) );
1537 _PROTOTYP( int mygetbuf, (void) );
1538 _PROTOTYP( int myfillbuf, (void) );
1539 _PROTOTYP( VOID conbgt, (int) );
1541 _PROTOTYP( VOID acucntrl, (char *, char *) );
1542 #endif /* ACUCNTRL */
1545 _PROTOTYP( int carrctl, (struct termios *, int) );
1548 _PROTOTYP( int carrctl, (struct termio *, int) );
1550 _PROTOTYP( int carrctl, (struct sgttyb *, int) );
1552 #endif /* BSD44ORPOSIX */
1555 _PROTOTYP( int attdial, (char *, long, char *) );
1556 _PROTOTYP( int offgetty, (char *) );
1557 _PROTOTYP( int ongetty, (char *) );
1558 #endif /* ATT7300 */
1562 /* BeOS is not capable of using SELECT on anything but sockets */
1565 #include <kernel/OS.h>
1566 /* #ifdef BE_DR_7 */
1567 static double time_started = 0.0;
1568 struct ALARM_STRUCT {
1572 static thread_id alarm_thread = -1;
1573 static struct ALARM_STRUCT alarm_struct;
1574 _PROTOTYP( long do_alarm, (void *) );
1575 _PROTOTYP( unsigned int alarm, (unsigned int) );
1576 _PROTOTYP( void alarm_expired, (void) );
1577 /* #endif */ /* BE_DR_7 */
1578 #endif /* BEOSORBEBOX */
1581 #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
1582 #endif /* xunchar */
1586 xxlast(char *s, char c)
1589 xxlast(s,c) char *s; char c;
1590 #endif /* CK_ANSIC */
1591 /* xxlast */ { /* Last occurrence of character c in string s. */
1593 for (i = (int)strlen(s); i > 0; i--)
1594 if (s[i-1] == c ) return(s + (i - 1));
1598 /* Timeout handler for communication line input functions */
1602 timerh(foo) int foo; {
1605 /* #ifdef BE_DR_7 */
1607 /* #endif */ /* BE_DR_7 */
1608 #endif /* BEOSORBEBOX */
1610 siglongjmp(sjbuf,1);
1613 #endif /* CK_POSIX_SIG */
1618 xtimerh(foo) int foo; { /* Like timerh() but does */
1619 #ifdef BEOSORBEBOX /* not reset the timer itself */
1620 /* #ifdef BE_DR_7 */
1622 /* #endif */ /* BE_DR_7 */
1623 #endif /* BEOSORBEBOX */
1625 siglongjmp(sjbuf,1);
1628 #endif /* CK_POSIX_SIG */
1632 /* Control-C trap for communication line input functions */
1634 int cc_int; /* Flag */
1635 SIGTYP (* occt)(); /* For saving old SIGINT handler */
1639 cctrap(foo) int foo; { /* Needs arg for ANSI C */
1640 cc_int = 1; /* signal() prototype. */
1644 /* S Y S I N I T -- System-dependent program initialization. */
1647 * ttgwsiz() returns:
1648 * 1 tt_rows and tt_cols are known, both altered, both > 0
1649 * 0 tt_rows and/or tt_cols are known, both altered, one or both <= 0
1650 * -1 tt_rows and tt_cols are unknown and unaltered
1653 extern int tt_rows, tt_cols;
1658 int rows = 0, cols = 0;
1659 p = getenv("LINES");
1660 debug(F110,"xttgwsiz LINES",p,0);
1664 p = getenv("COLUMNS");
1665 debug(F110,"xttgwsiz COLUMNS",p,0);
1682 le_init() { /* LocalEchoInit() */
1684 for (i = 0; i < LEBUFSIZ; i++)
1692 le_clean() { /* LocalEchoCleanup() */
1700 if (le_start != le_end) {
1703 LEBUFSIZ) % LEBUFSIZ;
1705 debug(F111,"le_inbuf","chars waiting",rc);
1713 le_putchar(ch) CHAR ch;
1714 #endif /* CK_ANSIC */
1717 /* In UNIX we do not have another thread taking chars out of the buffer */
1718 while ((le_start - le_end == 1) ||
1719 (le_start == 0 && le_end == LEBUFSIZ - 1)) {
1720 /* Buffer is full */
1721 debug(F111,"le_putchar","Buffer is Full",ch);
1722 ReleaseLocalEchoMutex() ;
1724 RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
1727 if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
1728 debug(F110,"le_putchar","buffer is full",0);
1731 #endif /* COMMENT */
1732 le_buf[le_end++] = ch;
1733 if (le_end == LEBUFSIZ)
1741 le_puts(CHAR * s, int n)
1743 le_puts(s,n) CHAR * s; int n;
1744 #endif /* CK_ANSIC */
1748 CHAR * p = (CHAR *)"le_puts";
1750 for (i = 0; i < n; i++)
1751 rc = le_putchar((char)s[i]);
1752 debug(F101,"le_puts","",rc);
1760 le_putstr(s) CHAR * s;
1761 #endif /* CK_ANSIC */
1765 p = (CHAR *)"le_putstr";
1766 ckhexdump(p,s,(int)strlen((char *)s));
1767 for (p = s; *p && !rc; p++)
1768 rc = le_putchar(*p);
1774 le_getchar(CHAR * pch)
1775 #else /* CK_ANSIC */
1776 le_getchar(pch) CHAR * pch;
1777 #endif /* CK_ANSIC */
1780 if (le_start != le_end) {
1781 *pch = le_buf[le_start];
1782 le_buf[le_start] = 0;
1785 if (le_start == LEBUFSIZ)
1788 if (le_start == le_end) {
1797 #endif /* TTLEBUF */
1801 Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ.
1802 But as far as I know, whenever TIOCGSIZE is defined, it is
1803 equated to TIOCGWINSZ. For cases where this is not done, try this:
1807 #define TIOCGWINSZ TIOCGSIZE
1808 #endif /* TIOCGSIZE */
1809 #endif /* TIOCGWINSZ */
1810 #endif /* COMMENT */
1812 static int tt_xpixel = 0, tt_ypixel = 0;
1820 NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
1821 This code works for both the 16- and 32-bit versions.
1823 extern int dev_size(int, int, int, int *, int *);
1826 if (dev_size(0, -1, -1, &r, &c) == 0) {
1827 debug(F101,"ttgwsiz QNX r","",r);
1828 debug(F101,"ttgwsiz QNX c","",c);
1831 return ((r > 0 && c > 0) ? 1 : 0);
1832 } else return(xttgwsiz());
1836 /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
1837 #ifdef XENIX /* SCO UNIX 3.2v4.0 */
1838 #include <sys/stream.h> /* typedef mblk_t needed by ptem.h */
1839 #include <sys/ptem.h> /* for ttgwsiz() */
1842 #ifdef I386IX /* Ditto for Interactive */
1843 #include <sys/stream.h>
1844 #include <sys/ptem.h>
1847 /* Note, the above might be needed for some other older SVR3 Intel makes... */
1857 x = ioctl(0, (int)TIOCGWINSZ, (char *)&w);
1858 debug(F101,"ttgwsiz TIOCGWINSZ","",x);
1861 } else if (w.ws_row > 0 && w.ws_col > 0) {
1864 tt_xpixel = w.ws_xpixel;
1865 tt_ypixel = w.ws_ypixel;
1866 debug(F101,"ttgwsiz tt_rows","",tt_rows);
1867 debug(F101,"ttgwsiz tt_cols","",tt_cols);
1870 debug(F100,"ttgwsiz TIOCGWINSZ 00","",0);
1875 #endif /* TIOCGWINSZ */
1882 _PROTOTYP( int rlog_naws, (void) );
1883 #endif /* RLOGCODE */
1888 winchh(foo) int foo; { /* SIGWINCH handler */
1894 #endif /* CK_TTYFD */
1895 extern int tt_rows, tt_cols, cmd_rows, cmd_cols;
1898 debug(F100,"***************","",0);
1899 debug(F100,"SIGWINCH caught","",0);
1900 debug(F100,"***************","",0);
1902 debug(F101,"SIGWINCH pty_fork_pid","",pty_fork_pid);
1906 signal(SIGWINCH,winchh); /* Re-arm the signal */
1907 x = ttgwsiz(); /* Get new window size */
1908 cmd_rows = tt_rows; /* Adjust command screen too */
1912 if /* If we don't have a connection */
1913 #ifdef VMS /* we're done. */
1920 #endif /* CK_TTYFD */
1924 if (pty_fork_pid > -1) { /* "set host" to a PTY? */
1928 struct winsize w; /* Resize the PTY */
1932 w.ws_xpixel = tt_xpixel;
1933 w.ws_ypixel = tt_ypixel;
1934 x = ioctl(ttyfd,TIOCSWINSZ,&w);
1935 debug(F101,"winchh TIOCSWINSZ","",x);
1936 debug(F101,"winchh TIOCSWINSZ errno","",errno);
1937 #endif /* TIOCSWINSZ */
1940 x = kill(pty_fork_pid,SIGWINCH);
1941 debug(F101,"winchh kill","",x);
1942 debug(F101,"winchh kill errno","",errno);
1947 This should be OK. It might seem that sending this from
1948 interrupt level could interfere with another TELNET IAC string
1949 that was in the process of being sent. But we always send
1950 TELNET strings with a single write(), which should prevent mixups.
1951 blah_snaws() should protect themselves from being called on the
1952 wrong kind of connection.
1956 if (x > 0 && tt_rows > 0 && tt_cols > 0) {
1960 #endif /* RLOGCODE */
1962 #endif /* NOTTGWSIZ */
1963 #endif /* TCPSOCKET */
1966 #endif /* SIGWINCH */
1967 #endif /* NOSIGWINCH */
1970 sighup(foo) int foo; { /* SIGHUP handler */
1972 debug(F100,"***************","",0);
1973 debug(F100,"SIGHUP received","",0);
1974 debug(F100,"***************","",0);
1975 doexit(BAD_EXIT,-1);
1977 SIGRETURN; /* Shut picky compilers up... */
1981 /* Exists but there is no prototype in the header files */
1982 _PROTOTYP( char * ttyname, (int) );
1985 _PROTOTYP( char * ttyname, (int) );
1988 _PROTOTYP( char * ttyname, (int) );
1991 _PROTOTYP( char * ttyname, (int) );
1994 _PROTOTYP( char * ttyname, (int) );
1997 _PROTOTYP( char * ttyname, (int) );
2000 _PROTOTYP( char * ttyname, (int) );
2002 #endif /* PS2AIX10 */
2006 #endif /* SV68R3V6 */
2007 #endif /* CK_SCO32V4 */
2009 #ifndef SIGUSR1 /* User-defined signals */
2011 #endif /* SIGUSR1 */
2015 #endif /* SIGUSR2 */
2018 ignorsigs() sets certain signals to SIG_IGN. But when a signal is
2019 ignored, it remains ignored across exec(), so we have to restore these
2020 signals before exec(), which is the purpose of restorsigs().
2023 ignorsigs() { /* Ignore these signals */
2024 savquit = signal(SIGQUIT,SIG_IGN); /* Ignore Quit signal */
2026 #ifdef SIGDANGER /* Ignore danger signals */
2028 This signal is sent when the system is low on swap space. Processes
2029 that don't handle it are candidates for termination. If swap space doesn't
2030 clear out enough, we still might be terminated via kill() -- nothing we can
2031 do about that! Conceivably, this could be improved by installing a real
2032 signal handler that warns the user, but that would be pretty complicated,
2033 since we are not always in control of the screen -- e.g. during remote-mode
2036 savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */
2037 #endif /* SIGDANGER */
2040 This one comes when a TCP/IP connection is broken by the remote.
2041 We prefer to catch this situation by examining error codes from write().
2043 savpipe = signal(SIGPIPE,SIG_IGN);
2044 #endif /* SIGPIPE */
2045 savusr1 = signal(SIGUSR1,SIG_IGN); /* Ignore user-defined signals */
2046 savusr2 = signal(SIGUSR2,SIG_IGN);
2050 restorsigs() { /* Restore these signals */
2051 (VOID) signal(SIGQUIT,savquit); /* (used in ckufio.c) */
2053 (VOID) signal(SIGDANGER,savdanger);
2054 #endif /* SIGDANGER */
2056 (VOID) signal(SIGPIPE,savpipe);
2057 #endif /* SIGPIPE */
2058 (VOID) signal(SIGUSR1,savusr1);
2059 (VOID) signal(SIGUSR2,savusr2);
2067 struct utsname name;
2068 #endif /* CK_UTSNAME */
2070 extern char startupdir[];
2072 BEFORE ANYTHING ELSE: Initialize the setuid package.
2073 Change to the user's real user and group ID.
2074 If this can't be done, don't run at all.
2078 fprintf(stderr,"PRIV_INI=%d\n",x);
2079 #endif /* SUIDDEBUG */
2081 if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
2082 if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
2083 if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
2086 signal(SIGINT,SIG_IGN); /* Ignore interrupts at first */
2087 signal(SIGFPE,SIG_IGN); /* Ignore floating-point exceptions */
2088 signal(SIGHUP,sighup); /* Catch SIGHUP */
2091 signal(SIGWINCH,winchh); /* Catch window-size change */
2092 #endif /* SIGWINCH */
2093 #endif /* NOSIGWINCH */
2096 signal(SIGXFSZ,SIG_IGN); /* Ignore writing past file limit */
2097 #endif /* SIGXFSZ */
2101 Get the initial job control state.
2102 If it is SIG_IGN, that means the shell does not support job control,
2103 and so we'd better not suspend ourselves.
2106 jchdlr = signal(SIGTSTP,SIG_IGN);
2107 if (jchdlr == SIG_IGN) {
2109 debug(F100,"sysinit jchdlr: SIG_IGN","",0);
2110 } else if (jchdlr == SIG_DFL) {
2111 debug(F100,"sysinit jchdlr: SIG_DFL","",0);
2114 debug(F100,"sysinit jchdlr: other","",0);
2117 (VOID) signal(SIGTSTP,jchdlr); /* Put it back... */
2118 #endif /* SIGTSTP */
2121 conbgt(0); /* See if we're in the background */
2122 congm(); /* Get console modes */
2124 (VOID) signal(SIGALRM,SIG_IGN); /* Ignore alarms */
2126 ignorsigs(); /* Ignore some other signals */
2129 iniflags = fcntl(0,F_GETFL,0); /* Get stdin flags */
2130 #endif /* F_SETFL */
2133 gtty(0,&vanilla); /* Get sgtty info */
2136 set42sig(); /* Don't ask! (hakanson@cs.orst.edu) */
2140 Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
2141 never closes it. If it is called often enough, we run out of file
2142 descriptors and subsequent open()'s of other devices or files can fail.
2146 if (isatty(0)) /* Name of controlling terminal */
2152 debug(F110,"sysinit ttyname(0)",s,0);
2161 ckstrncpy((char *)cttnam,s,DEVNAMLEN+1);
2165 #endif /* SVORPOSIX */
2167 ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1);
2168 debug(F110,"sysinit CTTNAM",CTTNAM,0);
2169 debug(F110,"sysinit cttnam",cttnam,0);
2171 ttgwsiz(); /* Get window (screen) dimensions. */
2175 ckmaxfiles = sysconf(_SC_OPEN_MAX);
2176 #endif /* _SC_OPEN_MAX */
2177 #endif /* NOSYSCONF */
2181 consctlfd = open("/dev/consctl", O_WRONLY);
2182 /*noisefd = open("/dev/noise", O_WRONLY)*/
2188 if (uname(&name) > -1) {
2189 ckstrncpy(unm_mch,name.machine,CK_SYSNMLN);
2190 ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN);
2191 ckstrncpy(unm_rel,name.release,CK_SYSNMLN);
2192 ckstrncpy(unm_ver,name.version,CK_SYSNMLN);
2195 debug(F110,"sysinit uname machine",unm_mch,0);
2196 debug(F110,"sysinit uname sysname",unm_nam,0);
2197 debug(F110,"sysinit uname release",unm_rel,0);
2198 debug(F110,"sysinit uname version",unm_ver,0);
2203 if (name.machine[5] == '8')
2207 debug(F101,"sysinit hpis800","",hpis800);
2208 #endif /* HPUX9PLUS */
2210 getsysinfo(GSI_PLATFORM_NAME, unm_mod, CK_SYSNMLN, 0, 0);
2211 debug(F110,"sysinit getsysinfo model",unm_mod,0);
2214 sysinfo(SI_PLATFORM, unm_mod, CK_SYSNMLN);
2215 debug(F110,"sysinit sysinfo model",unm_mod,0);
2216 #endif /* SOLARIS25 */
2218 #endif /* CK_UTSNAME */
2220 #ifdef CK_ENVIRONMENT
2223 extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
2224 tn_env_prnt[], tn_env_sys[];
2226 extern char uidbuf[];
2227 extern char * whoami();
2235 debug(F110,"sysinit uidbuf from USER",uidbuf,0);
2238 p = getenv("LOGNAME");
2239 debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0);
2244 debug(F110,"sysinit uidbuf from whoami()",uidbuf,0);
2247 ckstrncpy(uidbuf, *p ? p : "UNKNOWN", UIDBUFLEN);
2251 debug(F110,"sysinit final uidbuf",uidbuf,0);
2252 #endif /* CKSENDUID */
2255 if ((p = getenv("JOB"))) ckstrncpy(tn_env_job,p,63);
2256 if ((p = getenv("ACCT"))) ckstrncpy(tn_env_acct,p,63);
2257 if ((p = getenv("PRINTER"))) ckstrncpy(tn_env_prnt,p,63);
2258 if ((p = getenv("DISPLAY"))) ckstrncpy(tn_env_disp,p,63);
2260 ckstrncpy(tn_env_sys,"Aegis",64);
2263 ckstrncpy(tn_env_sys,"Plan9",64);
2265 ckstrncpy(tn_env_sys,"UNIX",64);
2270 #endif /* CK_ENVIRONMENT */
2273 extern char * tn_loc;
2275 if (p = getenv("LOCATION"))
2276 if (tn_loc = (char *)malloc((int)strlen(p)+1))
2277 strcpy(tn_loc,p); /* safe */
2279 #endif /* CK_SNDLOC */
2281 ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
2282 startupdir[CKMAXPATH] = '\0';
2283 x = strlen(startupdir);
2285 startupdir[0] = '/';
2286 startupdir[1] = '\0';
2287 } else if (startupdir[x-1] != '/') {
2288 startupdir[x] = '/';
2289 startupdir[x+1] = '\0';
2291 debug(F110,"sysinit startupdir",startupdir,0);
2294 #endif /* TTLEBUF */
2296 /* This should catch the ncurses platforms */
2297 /* Some platforms don't have putenv(), like NeXTSTEP */
2298 putenv("NCURSES_NO_SETBUF=1");
2299 #endif /* BSD44ORPOSIX */
2303 /* S Y S C L E A N U P -- System-dependent program cleanup. */
2309 fcntl(0,F_SETFL,iniflags); /* Restore stdin flags */
2310 #endif /* F_SETFL */
2312 stty(0,&vanilla); /* Get sgtty info */
2315 if (ttpid) kill(ttpid,9);
2320 /* T T O P E N -- Open a tty for exclusive access. */
2324 ttname: character string - device name or network host name.
2326 If called with lcl < 0, sets value of lcl as follows:
2327 0: the terminal named by ttname is the job's controlling terminal.
2328 1: the terminal named by ttname is not the job's controlling terminal.
2329 But watch out: if a line is already open, or if requested line can't
2330 be opened, then lcl remains (and is returned as) -1.
2332 Less than zero: ttname is a network host name.
2333 Zero or greater: ttname is a terminal device name.
2334 Zero means a local connection (don't use modem signals).
2335 Positive means use modem signals.
2338 nonzero = number of seconds to wait for open() to return before timing out.
2342 -5 if device is in use
2343 -4 if access to device is denied
2344 -3 if access to lock directory denied
2345 -2 upon timeout waiting for device to open
2348 static int ttotmo = 0; /* Timeout flag */
2349 /* Flag kept here to avoid being clobbered by longjmp. */
2352 ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
2355 #define ctermid(x) strcpy(x,"")
2359 extern char *ctermid(); /* Wish they all had this! */
2360 #else /* CIE Regulus */
2361 #define ctermid(x) strcpy(x,"")
2363 #endif /* SVORPOSIX */
2371 char fullname[DEVNAMLEN+1];
2372 #endif /* OPENFIRST */
2374 char * fnam; /* Full name after expansion */
2379 #define NAMEFD /* Feature to allow name to be an open file descriptor */
2384 debug(F101,"ttopen telnetfd","",telnetfd);
2387 debug(F110,"ttopen ttname",ttname,0);
2388 debug(F110,"ttopen ttnmsv",ttnmsv,0);
2389 debug(F101,"ttopen modem","",modem);
2390 debug(F101,"ttopen netconn","",netconn);
2391 debug(F101,"ttopen ttyfd","",ttyfd);
2392 debug(F101,"ttopen *lcl","",*lcl);
2393 debug(F101,"ttopen ttmdm","",ttmdm);
2394 debug(F101,"ttopen ttnet","",ttnet);
2399 if (ttyfd > -1) { /* If device already opened */
2400 if (!strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
2401 return(0); /* Yes, nothing to do - just return */
2402 ttnmsv[0] = '\0'; /* No, clear out old name */
2403 ttclos(ttyfd); /* close old connection. */
2405 wasclosed = 0; /* New connection, not closed yet. */
2406 ttpipe = 0; /* Assume it's not a pipe */
2407 ttpty = 0; /* or a pty... */
2411 This is a bit tricky... Suppose that previously Kermit had dialed a telnet
2412 modem server ("set host xxx:2001, set modem type usr, dial ..."). Then the
2413 connection was closed (ttyfd = -1), and then a REDIAL command was given. At
2414 this point we've obliterated the negative modem type hack, and so would
2415 treat the IP hostname as a device name, and would then fail because of "No
2416 such device or directory". But the previous connection has left behind some
2417 clues, so let's use them...
2419 if (ttyfd < 0) { /* Connection is not open */
2420 if (!strcmp(ttname,ttnmsv)) { /* Old and new names the same? */
2421 if (((netconn > 0) && (ttmdm < 0)) ||
2423 (!ckstrchr(ttname,'/')) && (ckstrchr(ttname,':')))
2426 x = (ttmdm < 0) ? -ttmdm : ttnet;
2427 rc = netopen(ttname, lcl, x);
2428 debug(F111,"ttopen REOPEN netopen",ttname,rc);
2440 #endif /* NETCONN */
2443 debug(F100,"ttopen MAXNAMLEN defined","",0);
2445 debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
2449 debug(F100,"ttopen BSD4 defined","",0);
2451 debug(F100,"ttopen BSD4 *NOT* defined","",0);
2455 debug(F100,"ttopen BSD42 defined","",0);
2457 debug(F100,"ttopen BSD42 *NOT* defined","",0);
2461 debug(F100,"ttopen MYREAD defined","",0);
2463 debug(F100,"ttopen MYREAD *NOT* defined","",0);
2467 if (modem < 0) { /* modem < 0 = code for network */
2470 modem = -modem; /* Positive network type number */
2471 fdflag = 0; /* Stdio not redirected. */
2472 netconn = 1; /* And it's a network connection */
2473 debug(F111,"ttopen net",ttname,modem);
2475 for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
2476 if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
2477 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2478 ttfdflg = 1; /* We got an open file descriptor */
2479 debug(F111,"ttopen net ttfdflg",ttname,ttfdflg);
2480 debug(F101,"ttopen net ttyfd","",ttyfd);
2481 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2482 x = 1; /* Return code is "good". */
2485 if (ttnproto != NP_TCPRAW)
2486 ttnproto = NP_TELNET;
2493 } else { /* Host name or address given */
2495 if (modem == NET_PTY) {
2498 debug(F100,"ttopen PTY: nopush","",0);
2503 netconn = 1; /* but we don't use network i/o */
2505 debug(F110,"ttopen PTY",ttname,0);
2506 x = do_pty(&ttyfd,ttname,0);
2508 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2509 xlocal = *lcl = 1; /* It's local */
2520 dup2() is not available on older System V platforms like AT&T 3Bx. For
2521 those systems we punt by not defining NETCMD, but we might be able to do
2522 better -- see workarounds for this problem in ckufio.c (search for dup2).
2524 if (modem == NET_CMD) {
2526 debug(F100,"ttopen pipe: nopush","",0);
2529 if (pipe(pipe0) || pipe(pipe1)) {
2530 perror("Pipe error");
2533 ttpid = fork(); /* Make a fork */
2536 case -1: /* Error making fork */
2541 perror("Fork error");
2543 case 0: /* Child. */
2552 default: /* Parent */
2555 fdin = pipe0[0]; /* Read from pipe */
2556 fdout = pipe1[1]; /* Write to pipe */
2557 ttout = fdopen(fdout,"w"); /* Get stream so we can */
2558 if (!ttout) { /* make it unbuffered. */
2559 perror("fdopen failure");
2563 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2564 xlocal = *lcl = 1; /* It's local */
2565 netconn = 1; /* Call it a network connection */
2566 ttmdm = modem; /* Remember network type */
2575 x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
2577 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2583 #ifdef sony_news /* Sony NEWS */
2584 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
2585 perror("ttopen error getting Kanji mode (network)");
2586 debug(F111,"ttopen error getting Kanji mode","network",0);
2587 km_ext = -1; /* Make sure this stays undefined. */
2589 #endif /* sony_news */
2591 xlocal = *lcl = 1; /* Network connections are local. */
2592 debug(F101,"ttopen net x","",x);
2594 /* Let netopen() do this */
2595 if (x > -1 && !x25fd)
2596 x = tn_ini(); /* Initialize TELNET protocol */
2597 #endif /* COMMENT */
2600 } else { /* Terminal device */
2601 #endif /* NETCONN */
2605 This code lets you give Kermit an open file descriptor for a serial
2606 communication device, rather than a device name. Kermit assumes that the
2607 line is already open, locked, conditioned with the right parameters, etc.
2609 for (p = ttname; isdigit(*p); p++) ; /* Check for all-digits */
2611 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2612 debug(F111,"ttopen got open fd",ttname,ttyfd);
2613 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2614 if (ttyfd >= 0 && ttyfd < 3) /* If it's stdio... */
2615 xlocal = *lcl = 0; /* we're in remote mode */
2616 else /* otherwise */
2617 xlocal = *lcl = 1; /* local mode. */
2618 netconn = 0; /* Assume it's not a network. */
2619 tvtflg = 0; /* Might need to initialize modes. */
2620 ttmdm = modem; /* Remember modem type. */
2621 fdflag = 0; /* Stdio not redirected. */
2622 ttfdflg = 1; /* Flag we were opened this way. */
2623 debug(F111,"ttopen non-net ttfdflg",ttname,ttfdflg);
2624 debug(F101,"ttopen non-net ttyfd","",ttyfd);
2626 #ifdef sony_news /* Sony NEWS */
2627 /* Get device Kanji mode */
2628 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
2629 perror("ttopen error getting Kanji mode");
2630 debug(F101,"ttopen error getting Kanji mode","",0);
2631 km_ext = -1; /* Make sure this stays undefined. */
2633 #endif /* sony_news */
2635 return(0); /* Return success */
2640 #endif /* NETCONN */
2642 /* Here we have to open a serial device of the given name. */
2644 netconn = 0; /* So it's not a network connection */
2645 occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */
2648 tvtflg = 0; /* Flag for use by ttvt(). */
2649 /* 0 = ttvt not called yet for this device */
2651 fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
2652 debug(F101,"ttopen fdflag","",fdflag);
2654 ttmdm = modem; /* Make this available to other fns */
2655 xlocal = *lcl; /* Make this available to other fns */
2657 /* Code for handling bidirectional tty lines goes here. */
2658 /* Use specified method for turning off logins and suppressing getty. */
2661 /* Should put call to priv_on() here, but that would be very risky! */
2662 acucntrl("disable",ttname); /* acucntrl() program. */
2663 /* and priv_off() here... */
2666 if ((attmodem & DOGETY) == 0) /* offgetty() program. */
2667 attmodem |= offgetty(ttname); /* Remember response. */
2668 #endif /* ATT7300 */
2669 #endif /* ACUCNTRL */
2673 1985-2001: opens device first then gets lock; reason:
2674 Kermit usually has to run setuid or setgid in order to create a lockfile.
2675 If you give a SET LINE command for a device that happens to be your job's
2676 controlling terminal, Kermit doesn't have to create a lockfile, and in fact
2677 should not create one, and would fail if it tried to if it did not have the
2678 required privileges. But you can't find out if two tty device names are
2679 equivalent until you have a file descriptor that you can give to ttyname().
2680 But this can cause a race condition between Kermit and [m]getty. So see
2685 In the following section, we open the tty device for read/write.
2686 If a modem has been specified via "set modem" prior to "set line"
2687 then the O_NDELAY parameter is used in the open, provided this symbol
2688 is defined (e.g. in fcntl.h), so that the program does not hang waiting
2689 for carrier (which in most cases won't be present because a connection
2690 has not been dialed yet). O_NDELAY is removed later on in ttopen(). It
2691 would make more sense to first determine if the line is local before
2692 doing this, but because ttyname() requires a file descriptor, we have
2693 to open it first. See do_open().
2695 Now open the device using the desired treatment of carrier.
2696 If carrier is REQUIRED, then open could hang forever, so an optional
2697 timer is provided. If carrier is not required, the timer should never
2698 go off, and should do no harm...
2700 ttotmo = 0; /* Flag no timeout */
2701 debug(F101,"ttopen timo","",timo);
2702 debug(F101,"ttopen xlocal","",xlocal);
2705 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2706 xx = alarm(timo); /* Timed open() */
2707 debug(F101,"ttopen alarm","",xx);
2713 #endif /* CK_POSIX_SIG */
2715 ttotmo = 1; /* Flag timeout. */
2716 } else ttyfd = do_open(ttname);
2718 debug(F111,"ttopen","modem",modem);
2719 debug(F101,"ttopen ttyfd","",ttyfd);
2720 debug(F101,"ttopen alarm return","",ttotmo);
2723 ttyfd = do_open(ttname);
2725 debug(F111,"ttopen ttyfd",ttname,ttyfd);
2726 if (ttyfd < 0) { /* If couldn't open, fail. */
2727 debug(F101,"ttopen errno","",errno);
2728 if (errno > 0 && !quiet)
2729 perror(ttname); /* Print message */
2732 if (attmodem & DOGETY) /* was getty(1m) running before us? */
2733 ongetty(ttnmsv); /* yes, restart on tty line */
2734 attmodem &= ~DOGETY; /* no phone in use, getty restored */
2737 /* Should put call to priv_on() here, but that would be risky! */
2738 acucntrl("enable",ttname); /* acucntrl() program. */
2739 /* and priv_off() here... */
2740 #endif /* ACUNTRL */
2741 #endif /* ATT7300 */
2743 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
2744 if (errno == EACCES) { /* Device is protected against user */
2745 debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */
2747 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
2752 extern int qnxportlock;
2754 debug(F101,"ttopen qnxopencount","",x);
2755 debug(F101,"ttopen qnxportlock","",qnxportlock);
2756 if (x < 0 && qnxportlock) {
2758 printf("?Can't get port open count\n");
2759 printf("(Try again with SET QNX-PORT-LOCK OFF)\n");
2760 return(-1); /* Indicate device is in use */
2762 if (x > 1) { /* 1 == me */
2765 return(-2); /* Indicate device is in use */
2767 printf("WARNING: \"%s\" looks busy...\n",ttdev);
2773 /* take this opportunity to open the control channel */
2774 if (p9openttyctl(ttname) < 0)
2776 /* Make sure it's a real tty. */
2777 if (!ttfdflg && !isatty(ttyfd) && strcmp(ttname,"/dev/null"))
2780 fprintf(stderr,"%s is not a terminal device\n",ttname);
2781 debug(F111,"ttopen not a tty",ttname,errno);
2785 signal(SIGINT,occt);
2790 /* Apollo C runtime claims that console pads are tty devices, which
2791 * is reasonable, but they aren't any good for packet transfer. */
2792 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
2793 if (st.all != status_$ok) {
2794 fprintf(stderr, "problem getting tty object type: ");
2796 } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
2797 close(ttyfd); ttyfd = -1;
2799 errno = ENOTTY; perror(ttname);
2800 signal(SIGINT,occt);
2805 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2807 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
2809 /* Caller wants us to figure out if line is controlling tty */
2812 if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
2814 debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal);
2815 } else if (strcmp(ttname,cttnam) == 0) {
2817 debug(F111,"ttopen ttname=cttnam",ttname,xlocal);
2818 } else if (cttnam[0]) {
2820 x = ttnmsv; /* ttyname() is broken */
2822 x = ttyname(ttyfd); /* Get real name of ttname. */
2823 #endif /* BEBOX_DR7 */
2826 xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
2829 debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal);
2834 /* Note, the following code was added so that Unix "idle-line" snoopers */
2835 /* would not think Kermit was idle when it was transferring files, and */
2836 /* maybe log people out. */
2837 if (xlocal == 0) { /* Remote mode */
2838 if (fdflag == 0) { /* Standard i/o is not redirected */
2839 debug(F100,"ttopen setting ttyfd = 0","",0);
2841 /* On Lynx OS, fd 0 is open for read only. */
2844 close(ttyfd); /* Use file descriptor 0 */
2846 } else { /* Standard i/o is redirected */
2847 debug(F101,"ttopen stdio redirected","",ttyfd);
2850 #endif /* NOFDZERO */
2852 /* Now check if line is locked -- if so fail, else lock for ourselves */
2853 /* Note: After having done this, don't forget to delete the lock if you */
2854 /* leave ttopen() with an error condition. */
2856 lkf = 0; /* Check lock */
2859 if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
2860 debug(F111,"ttopen ttlock fails",ttname,xx);
2861 /* WARNING - This close() can hang if tty is an empty socket... */
2862 close(ttyfd); /* Close the device. */
2863 ttyfd = -1; /* Erase its file descriptor. */
2865 signal(SIGINT,occt); /* Put old SIGINT back. */
2866 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2867 if (xx == -2) { /* If lockfile says device in use, */
2869 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2870 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2871 if (xpid > -1) { /* If we got a pid */
2873 printf("Locked by process %d\n",xpid); /* tell them. */
2874 sprintf(lockpid,"%d",xpid); /* Record it too */
2875 debug(F110,"ttopen lockpid",lockpid,0);
2876 } else if (*flfnam) {
2877 extern char *DIRCMD;
2880 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2881 p = malloc(x); /* Print a directory listing. */
2883 Note: priv_on() won't help here, because we do not pass privs along to
2884 to inferior processes, in this case ls. So if the real user does not have
2885 directory-listing access to the lockfile directory, this will result in
2886 something like "not found". That's why we try this only as a last resort.
2888 if (p) { /* If we got the space... */
2889 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2890 zsyscmd(p); /* Get listing. */
2891 if (p) { /* free the space */
2898 return(-5); /* Code for device in use */
2899 } else return(-3); /* Access denied */
2902 #else /* OPENFIRST */
2905 27 Oct 2001: New simpler code that gets the lock first and then opens the
2906 device, which eliminates the race condition. The downside is you can no
2907 longer say "set line /dev/ttyp0" or whatever, where /dev/ttyp0 is your login
2908 terminal, without trying to create a lockfile, which fails if C-Kermit lacks
2909 privs, and if it succeeds, it has created a lockfile where it didn't create
2912 xlocal = *lcl; /* Is the device my login terminal? */
2913 debug(F111,"ttopen xlocal","A",xlocal);
2915 if (strcmp(ttname,CTTNAM) && netconn == 0) {
2916 if (zfnqfp(ttname,DEVNAMLEN+1,fullname)) {
2917 if ((int)strlen(fullname) > 0)
2921 debug(F110,"ttopen fnam",fnam,0);
2923 xlocal = (strcmp(fnam,CTTNAM) != 0);
2925 debug(F111,"ttopen xlocal","B",xlocal);
2927 lkf = 0; /* No lock yet */
2928 if (xlocal > 0) { /* If not... */
2930 xx = ttlock(fnam); /* Try to lock it. */
2931 debug(F101,"ttopen ttlock","",xx);
2932 if (xx < 0) { /* Can't lock it. */
2933 debug(F111,"ttopen ttlock fails",fnam,xx);
2934 if (xx == -2) { /* If lockfile says device in use, */
2936 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2937 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2938 if (xpid > -1) { /* If we got a pid */
2940 printf("Locked by process %d\n",xpid); /* tell them. */
2941 ckstrncpy(lockpid,ckitoa(xpid),16);
2942 debug(F110,"ttopen lockpid",lockpid,0);
2944 } else if (flfnam[0] && !nopush) {
2945 extern char *DIRCMD;
2948 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2949 p = malloc(x); /* Print a directory listing. */
2951 Note: priv_on() won't help here, because we do not pass privs along to
2952 to inferior processes, in this case ls. So if the real user does not have
2953 directory-listing access to the lockfile directory, this will result in
2954 something like "not found". That's why we try this only as a last resort.
2956 if (p) { /* If we got the space... */
2957 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2958 zsyscmd(p); /* Get listing. */
2959 if (p) { /* free the space */
2967 return(-5); /* Code for device in use */
2968 } else return(-3); /* Access denied */
2971 /* Have lock -- now it's safe to open the device */
2973 debug(F101,"ttopen lkf","",lkf);
2974 debug(F101,"ttopen timo","",timo);
2976 ttotmo = 0; /* Flag no timeout */
2979 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2980 xx = alarm(timo); /* Timed open() */
2981 debug(F101,"ttopen alarm","",xx);
2987 #endif /* CK_POSIX_SIG */
2989 ttotmo = 1; /* Flag timeout. */
2991 ttyfd = do_open(fnam);
2994 debug(F111,"ttopen timed ttyfd",fnam,ttyfd);
2997 ttyfd = do_open(fnam);
2998 debug(F111,"ttopen untimed ttyfd",fnam,ttyfd);
3000 if (ttyfd < 0) { /* If couldn't open, fail. */
3001 debug(F111,"ttopen errno",fnam,errno);
3002 debug(F111,"ttopen xlocal","C",xlocal);
3004 debug(F100,"ttopen substituting 0","",0);
3007 if (errno > 0 && !quiet) {
3008 debug(F111,"ttopen perror",fnam,errno);
3009 perror(fnam); /* Print message */
3011 if (ttunlck()) /* Release the lock file */
3012 fprintf(stderr,"Warning, problem releasing lock\r\n");
3016 if (ttyfd < 0) { /* ttyfd is still < 0? */
3018 if (attmodem & DOGETY) /* was getty(1m) running before us? */
3019 ongetty(ttnmsv); /* yes, restart on tty line */
3020 attmodem &= ~DOGETY; /* no phone in use, getty restored */
3023 /* Should put call to priv_on() here, but that would be risky! */
3024 acucntrl("enable",fnam); /* acucntrl() program. */
3025 /* and priv_off() here... */
3026 #endif /* ACUNTRL */
3027 #endif /* ATT7300 */
3029 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
3030 if (errno == EACCES) { /* Device is protected against user */
3031 debug(F110,"ttopen EACCESS",fnam,0); /* Return -4 */
3033 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
3036 /* Make sure it's a real tty. */
3039 /* take this opportunity to open the control channel */
3040 if (p9openttyctl(fnam) < 0)
3042 if (!ttfdflg && !isatty(ttyfd) && strcmp(fnam,"/dev/null"))
3045 fprintf(stderr,"%s is not a terminal device\n",fnam);
3046 debug(F111,"ttopen not a tty",fnam,errno);
3047 if (ttunlck()) /* Release the lock file */
3048 fprintf(stderr,"Warning, problem releasing lock\r\n");
3052 signal(SIGINT,occt);
3058 Apollo C runtime claims that console pads are tty devices, which
3059 is reasonable, but they aren't any good for packet transfer.
3061 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
3062 if (st.all != status_$ok) {
3063 fprintf(stderr, "problem getting tty object type: ");
3065 } else if (ttyuid != sio_$uid) { /* Reject non-SIO lines */
3066 close(ttyfd); ttyfd = -1;
3068 errno = ENOTTY; perror(fnam);
3069 signal(SIGINT,occt);
3074 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3076 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
3078 /* Caller wants us to figure out if line is controlling tty */
3082 if (strcmp(fnam,CTTNAM) == 0) { /* "/dev/tty" always remote */
3084 debug(F111,"ttopen fnam=CTTNAM",fnam,xlocal);
3085 } else if (strcmp(fnam,cttnam) == 0) {
3087 debug(F111,"ttopen fnam=cttnam",fnam,xlocal);
3088 } else if (cttnam[0]) {
3090 s = ttnmsv; /* ttyname() is broken */
3092 s = ttyname(ttyfd); /* Get real name of ttname. */
3093 #endif /* BEBOX_DR7 */
3096 xlocal = ((strncmp(s,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
3099 debug(F111,"ttopen ttyname(ttyfd) xlocal",s,xlocal);
3104 /* Note, the following code was added so that Unix "idle-line" snoopers */
3105 /* would not think Kermit was idle when it was transferring files, and */
3106 /* maybe log people out. */
3107 if (xlocal == 0) { /* Remote mode */
3108 if (fdflag == 0) { /* Standard i/o is not redirected */
3109 debug(F100,"ttopen setting ttyfd = 0","",0);
3111 /* On Lynx OS, fd 0 is open for read only. */
3114 close(ttyfd); /* Use file descriptor 0 */
3116 } else { /* Standard i/o is redirected */
3117 debug(F101,"ttopen stdio redirected","",ttyfd);
3120 #endif /* NOFDZERO */
3121 #endif /* OPENFIRST */
3123 /* Got the line, now set the desired value for local. */
3125 if (*lcl != 0) *lcl = xlocal;
3127 /* Some special stuff for v7... */
3131 if (kmem[TTY] < 0) { /* If open, then skip this. */
3132 qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
3133 if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
3134 fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
3135 perror("/dev/kmem");
3142 /* No failure returns after this point */
3145 ioctl(ttyfd, TIOCMODEM, &temp);
3147 if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
3151 #endif /* TIOCSINUSE */
3154 /* Get tty device settings */
3156 #ifdef BSD44ORPOSIX /* POSIX */
3157 tcgetattr(ttyfd,&ttold);
3158 debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
3159 tcgetattr(ttyfd,&ttraw);
3160 debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag);
3161 tcgetattr(ttyfd,&tttvt);
3162 debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag);
3163 #else /* BSD, V7, and all others */
3164 #ifdef ATTSV /* AT&T UNIX */
3165 ioctl(ttyfd,TCGETA,&ttold);
3166 debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
3167 ioctl(ttyfd,TCGETA,&ttraw);
3168 ioctl(ttyfd,TCGETA,&tttvt);
3171 ioctl(ttyfd,TIOCGETP,&ttold);
3172 debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
3173 ioctl(ttyfd,TIOCGDEV,&tdold);
3174 debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
3177 debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
3178 #endif /* BELLV10 */
3180 #ifdef sony_news /* Sony NEWS */
3181 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
3182 perror("ttopen error getting Kanji mode");
3183 debug(F101,"ttopen error getting Kanji mode","",0);
3184 km_ext = -1; /* Make sure this stays undefined. */
3186 #endif /* sony_news */
3189 debug(F100,"ttopen TIOCGETC","",0);
3190 tcharf = 0; /* In remote mode, also get */
3191 if (xlocal == 0) { /* special characters */
3192 if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
3193 debug(F100,"ttopen TIOCGETC failed","",0);
3195 tcharf = 1; /* It worked. */
3196 ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
3197 debug(F100,"ttopen TIOCGETC ok","",0);
3201 debug(F100,"ttopen TIOCGETC not defined","",0);
3202 #endif /* TIOCGETC */
3205 debug(F100,"ttopen TIOCGLTC","",0);
3206 ltcharf = 0; /* In remote mode, also get */
3207 if (xlocal == 0) { /* local special characters */
3208 if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
3209 debug(F100,"ttopen TIOCGLTC failed","",0);
3211 ltcharf = 1; /* It worked. */
3212 ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
3213 debug(F100,"ttopen TIOCGLTC ok","",0);
3217 debug(F100,"ttopen TIOCGLTC not defined","",0);
3218 #endif /* TIOCGLTC */
3221 debug(F100,"ttopen TIOCLGET","",0);
3223 if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
3224 debug(F100,"ttopen TIOCLGET failed","",0);
3227 debug(F100,"ttopen TIOCLGET ok","",0);
3229 #endif /* TIOCLGET */
3232 ioctl(ttyfd,TIOCGETP,&ttraw);
3233 ioctl(ttyfd,TIOCGETP,&tttvt);
3235 gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
3236 gtty(ttyfd,&tttvt); /* And one for virtual tty service */
3237 #endif /* BELLV10 */
3240 #endif /* BSD44ORPOSIX */
3242 /* Section for changing line discipline. It's restored in ttres(). */
3246 { union txname ld_name; int ld_idx = 0;
3249 ld_name.tx_which = ld_idx++;
3250 ioctl(ttyfd, TXGETCD, &ld_name);
3251 if (!strncmp(ld_name.tx_name, "rts", 3))
3253 } while (*ld_name.tx_name);
3254 debug(F101,"AIX line discipline","",ttld);
3260 /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
3262 ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */
3263 debug(F101,"4.1bsd line discipline","",ttld);
3264 k = OTTYDISC; /* Switch to "old" discipline */
3265 k = ioctl(ttyfd, TIOCSETD, &k);
3266 debug(F101,"4.1bsd tiocsetd","",k);
3271 /* This was previously done before the last two TCGETA or gtty above,
3272 * in both the ATTSV and not-ATTSV case. If it is not okay to have only
3273 * one copy if it here instead, give us a shout!
3275 sio_$control((short)ttyfd, sio_$raw_nl, false, st);
3276 if (xlocal) { /* ignore breaks from local line */
3277 sio_$control((short)ttyfd, sio_$int_enable, false, st);
3278 sio_$control((short)ttyfd, sio_$quit_enable, false, st);
3283 ttraw.c_line = 0; /* STTY line 0 for VX/VE */
3284 tttvt.c_line = 0; /* STTY line 0 for VX/VE */
3285 ioctl(ttyfd,TCSETA,&ttraw);
3288 /* If O_NDELAY was used during open(), then remove it now. */
3291 debug(F100,"ttopen O_NDELAY","",0);
3293 if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
3294 debug(F100,"ttopen fcntl O_NDELAY","",0);
3296 if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) {
3297 debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0);
3298 perror("Can't unset O_NDELAY");
3301 /* Some systems, notably Xenix (don't know how common this is in
3302 * other systems), need special treatment to get rid of the O_NDELAY
3303 * behaviour on read() with respect to carrier presence (i.e. read()
3304 * returning 0 when carrier absent), even though the above fcntl()
3305 * is enough to make read() wait for input when carrier is present.
3306 * This magic, in turn, requires CLOCAL for working when the carrier
3307 * is absent. But if xlocal == 0, presumably you already have CLOCAL
3308 * or you have a carrier, otherwise you wouldn't be running this.
3310 debug(F101,"ttopen xlocal","",xlocal);
3313 #ifdef COMMENT /* 12 Aug 1997 */
3316 ttraw.c_cflag |= CLOCAL;
3320 ttraw.c_cflag |= CLOCAL;
3321 #endif /* __FreeBSD__ */
3322 #endif /* __bsdi__ */
3323 #else /* Not COMMENT */
3325 if (xlocal) /* Unset this if it's defined. */
3326 ttraw.c_cflag |= CLOCAL;
3328 #endif /* COMMENT */
3329 debug(F101,"ttopen BSD44ORPOSIX calling tcsetattr","",TCSADRAIN);
3330 if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0) {
3331 debug(F100,"ttopen POSIX tcseattr fails","",0);
3332 perror("tcsetattr");
3334 #else /* !BSD44ORPOSIX */
3336 ttraw.c_cflag |= CLOCAL;
3337 debug(F100,"ttopen calling ioctl(TCSETA)","",0);
3339 if (ioctl(ttyfd, TCSETA, &ttraw) < 0) {
3340 debug(F101,"ttopen ioctl(TCSETA) fails","",errno);
3341 perror("ioctl(TCSETA)");
3344 #endif /* BSD44ORPOSIX */
3346 #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
3347 /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
3348 debug(F100,"ttopen executing close/open","",0);
3349 close( priv_opn(fnam, O_RDWR) ); /* Magic to force change. */
3350 #endif /* NOCOTFMC */
3353 #endif /* O_NDELAY */
3355 /* Instruct the system how to treat the carrier, and set a few other tty
3358 * This also undoes the temporary setting of CLOCAL that may have been done
3359 * for the close(open()) above (except in Xenix). Also throw in ~ECHO, to
3360 * prevent the other end of the line from sitting there talking to itself,
3361 * producing garbage when the user performs a connect.
3363 * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
3364 * Now it thinks CLOCAL is always on. It seems the only real solution for
3365 * Xenix is to switch between the lower and upper case device names.
3367 * This section may at some future time expand into setting a complete
3368 * collection of tty parameters, or call a function shared with ttpkt()/
3369 * ttvt() that does so. On the other hand, the initial parameters are not
3370 * that important, since ttpkt() or ttvt() should always fix that before
3371 * any communication is done. Well, we'll see...
3375 debug(F100,"ttopen calling carrctl","",0);
3376 carrctl(&ttraw, ttcarr == CAR_ON);
3377 debug(F100,"ttopen carrctl ok","",0);
3381 #endif /* COHERENT */
3384 ttraw.c_lflag &= ~ECHO;
3385 ttold.c_lflag &= ~ECHO;
3387 y = tcsetattr(ttyfd, TCSADRAIN, &ttraw);
3388 debug(F101,"ttopen tcsetattr","",y);
3390 y = ioctl(ttyfd, TCSETA, &ttraw);
3391 debug(F100,"ttopen ioctl","",y);
3392 #endif /* BSD44ORPOSIX */
3394 #else /* BSD, etc */
3395 ttraw.sg_flags &= ~ECHO;
3396 ttold.sg_flags &= ~ECHO;
3398 y = ioctl(ttyfd,TIOCSETP,&ttraw);
3399 debug(F100,"ttopen ioctl","",y);
3401 y = stty(ttyfd,&ttraw);
3402 debug(F100,"ttopen stty","",y);
3403 #endif /* BELLV10 */
3404 #endif /* SVORPOSIX */
3408 #endif /* COHERENT */
3410 /* ttflui(); */ /* This fails for some reason. */
3413 /* Get current speed */
3420 debug(F101,"ttopen ttspeed","",ttspeed);
3422 /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
3424 debug(F101,"ttopen ttyfd","",ttyfd);
3425 debug(F101,"ttopen *lcl","",*lcl);
3426 debug(F111,"ttopen lock file",flfnam,lkf);
3427 signal(SIGINT,occt);
3428 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3434 /* D O _ O P E N -- Do the right kind of open() call for the tty. */
3437 do_open(ttname) char *ttname; {
3441 /* O_NONBLOCK on /dev/tty makes open() fail */
3442 return(priv_opn(ttname, O_RDWR |
3444 ((int)strcmp(ttname,"/dev/tty") == 0) ?
3446 (ttcarr != CAR_ON) ? O_NONBLOCK : 0)
3451 #ifndef O_NDELAY /* O_NDELAY not defined */
3452 return(priv_opn(ttname,2));
3453 #else /* O_NDELAY defined */
3457 Open comms line without waiting for carrier so initial call does not hang
3458 because state of "modem" is likely unknown at the initial call -jrd.
3459 If this is needed for the getty stuff to work, and the open would not work
3460 without O_NDELAY when getty is still on, then this special case is ok.
3461 Otherwise, get rid of it. -ske
3463 return(priv_opn(ttname, O_RDWR | O_NDELAY));
3465 #else /* !ATT7300 */
3467 /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
3469 debug(F101,"do_open xlocal","",xlocal);
3470 debug(F111,"do_open flags A",ttname,flags);
3471 if (xlocal && (ttcarr != CAR_ON))
3473 debug(F111,"do_open flags B",ttname,flags);
3474 return(priv_opn(ttname, flags));
3475 #endif /* !ATT7300 */
3476 #endif /* O_NDELAY */
3480 /* T T C L O S -- Close the TTY, releasing any lock. */
3482 static int ttc_state = 0; /* ttclose() state */
3483 static char * ttc_nam[] = { "setup", "hangup", "reset", "close" };
3486 ttclos(foo) int foo; { /* Arg req'd for signal() prototype */
3488 extern int exithangup;
3490 debug(F101,"ttclos ttyfd","",ttyfd);
3491 debug(F101,"ttclos netconn","",netconn);
3492 debug(F101,"ttclos xlocal","",xlocal);
3494 debug(F100,"ttclos NOFDZERO","",0);
3495 #endif /* NOFDZERO */
3499 le_init(); /* No need for any of this */
3500 #endif /* TTLEBUF */
3501 #endif /* COMMENT */
3503 if (ttyfd < 0) /* Wasn't open. */
3506 if (ttfdflg) /* If we inherited ttyfd from */
3507 return(0); /* another process, don't close it. */
3509 tvtflg = 0; /* (some day get rid of this...) */
3515 tn_push(); /* Place any waiting data into input*/
3516 tn_sopt(DO,TELOPT_LOGOUT); /* Send LOGOUT option before close */
3517 TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
3518 tn_reset(); /* The Reset Telnet Option table. */
3521 if (ssl_active_flag) {
3523 BIO_printf(bio_err,"calling SSL_shutdown(ssl)\n");
3524 SSL_shutdown(ssl_con);
3527 ssl_active_flag = 0;
3529 if (tls_active_flag) {
3531 BIO_printf(bio_err,"calling SSL_shutdown(tls)\n");
3532 SSL_shutdown(tls_con);
3535 tls_active_flag = 0;
3541 if (ttpipe) { /* We've been using a pipe */
3546 close(fdin); /* Close these. */
3549 kill(ttpid,1); /* Kill fork with SIGHUP */
3551 wstat = wait(&statusp);
3552 if (wstat == ttpid || wstat == -1)
3554 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
3568 #endif /* NODOPTY */
3579 if (netconn) { /* If it's a network connection. */
3580 debug(F100,"ttclos closing net","",0);
3581 netclos(); /* Let the network module close it. */
3582 netconn = 0; /* No more network connection. */
3583 debug(F101,"ttclos ttyfd after netclos","",ttyfd); /* Should be -1 */
3586 #endif /* NETCONN */
3588 if (xlocal) { /* We're closing a SET LINE device */
3589 #ifdef FT21 /* Fortune 2.1-specific items ... */
3590 ioctl(ttyfd,TIOCHPCL, NULL);
3592 #ifdef ultrix /* Ultrix-specific items ... */
3594 /* Unset the INUSE flag that we set in ttopen() */
3595 ioctl(ttyfd, TIOCSINUSE, NULL);
3596 #endif /* TIOCSINUSE */
3597 ioctl(ttyfd, TIOCNMODEM, &x);
3599 /* What was this? */
3600 ioctl(ttyfd, TIOCNCAR, NULL);
3601 #endif /* COMMENT */
3605 /* This is to prevent us from sticking in tthang() or close(). */
3609 if (ttyfd > 0) { /* But skip it on stdin. */
3610 debug(F100,"ttclos setting O_NDELAY","",0);
3611 x = fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL, 0)|O_NDELAY);
3613 if (deblog && x == -1) {
3614 perror("Warning - Can't set O_NDELAY");
3615 debug(F101,"ttclos fcntl failure to set O_NDELAY","",x);
3620 #endif /* O_NDELAY */
3627 #endif /* NOFDZERO */
3629 saval = signal(SIGALRM,xtimerh); /* Enable timer interrupt. */
3630 xx = alarm(8); /* Allow 8 seconds. */
3631 debug(F101,"ttclos alarm","",xx);
3637 #endif /* CK_POSIX_SIG */
3638 ) { /* Timer went off? */
3641 debug(F111,"ttclos ALARM TRAP errno",ckitoa(ttc_state),errno);
3642 printf("ttclos() timeout: %s\n", ttc_nam[ttc_state]);
3645 /* Hang up the device (drop DTR) */
3648 debug(F111,"ttclos A",ckitoa(x),ttc_state);
3649 if (ttc_state < 1) {
3651 debug(F101,"ttclos exithangup","",exithangup);
3653 alarm(8); /* Re-arm the timer */
3654 debug(F101,"ttclos calling tthang()","",x);
3655 x = tthang(); /* Hang up first, then... */
3656 debug(F101,"ttclos tthang()","",x);
3660 Oct 2006 - Leave DTR on if SET EXIT HANGUP OFF.
3661 Suggested by Soewono Effendi.
3665 ttold.c_cflag &= ~HUPCL; /* Let's see how this travels */
3667 tcsetattr(ttyfd,TCSANOW,&ttold);
3668 #else /* !BSD44ORPOSIX */
3670 ioctl(ttyfd,TCSETAW,&ttold);
3674 #endif /* BSD44ORPOSIX */
3677 #endif /* CK_NOHUPCL */
3679 /* Put back device modes as we found them */
3682 debug(F111,"ttclos B",ckitoa(x),ttc_state);
3683 if (ttc_state < 2) {
3685 /* Don't try to mess with tty modes if tthang failed() */
3686 /* since it probably won't work. */
3688 debug(F101,"ttclos calling ttres()","",x);
3689 signal(SIGALRM,xtimerh); /* Re-enable the alarm. */
3690 alarm(8); /* Re-arm the timer */
3691 x = ttres(); /* Reset device modes. */
3692 debug(F101,"ttclos ttres()","",x);
3696 /* Close the device */
3699 debug(F101,"ttclos C","",ttc_state);
3700 if (ttc_state < 3) {
3703 debug(F101,"ttclos calling close","",x);
3704 signal(SIGALRM,xtimerh); /* Re-enable alarm. */
3705 alarm(8); /* Re-arm the timer */
3706 x = close(ttyfd); /* Close the device. */
3707 debug(F101,"ttclos close()","",x);
3711 debug(F101,"ttclos D","",ttc_state);
3712 ttimoff(); /* Turn off timer. */
3714 printf("?WARNING - close failed: %s\n",ttnmsv);
3717 printf("errno = %d\n", errno);
3718 debug(F101,"ttclos failed","",errno);
3722 /* Unlock after closing but before any getty mumbo jumbo */
3724 debug(F100,"ttclos about to call ttunlck","",0);
3725 if (ttunlck()) /* Release uucp-style lock */
3726 fprintf(stderr,"Warning, problem releasing lock\r\n");
3729 /* For bidirectional lines, restore getty if it was there before. */
3731 #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */
3733 debug(F100,"ttclos ACUCNTRL","",0);
3734 acucntrl("enable",ttnmsv); /* Enable getty on the device. */
3737 #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */
3739 debug(F100,"ttclos ATT7300 ongetty","",0);
3740 if (attmodem & DOGETY) /* Was getty(1m) running before us? */
3741 ongetty(ttnmsv); /* Yes, restart getty on tty line */
3742 attmodem &= ~DOGETY; /* No phone in use, getty restored */
3744 #endif /* ATT7300 */
3745 #endif /* System-dependent getty-restoring methods */
3748 km_ext = -1; /* Invalidate device's Kanji-mode */
3749 #endif /* sony_news */
3751 ttyfd = -1; /* Invalidate the file descriptor. */
3753 debug(F100,"ttclos done","",0);
3757 /* T T H A N G -- Hangup phone line or network connection. */
3760 0 if it does nothing.
3761 1 if it believes that it hung up successfully.
3762 -1 if it believes that the hangup attempt failed.
3765 #define HUPTIME 500 /* Milliseconds for hangup */
3768 /* The following didn't work but TIOCSDTR does work */
3770 /* Define HUP_POSIX to force non-POSIX builds to use the POSIX hangup method */
3771 #ifndef POSIX /* Such as Unixware 1.x, 2.x */
3774 #endif /* HUP_POSIX */
3776 #endif /* UNIXWARE */
3777 #endif /* COMMENT */
3779 #ifndef USE_TIOCSDTR
3781 /* Because the POSIX method (set output speed to 0) doesn't work in NetBSD */
3784 #define USE_TIOCSDTR
3785 #endif /* TIOCCDTR */
3786 #endif /* TIOCSDTR */
3787 #endif /* __NetBSD__ */
3788 #endif /* USE_TIOCSDTR */
3790 #ifndef HUP_CLOSE_POSIX
3792 #define HUP_CLOSE_POSIX
3795 #define HUP_CLOSE_POSIX
3796 #endif /* CK_SCOV5 */
3798 #endif /* HUP_CLOSE_POSIX */
3800 #ifdef NO_HUP_CLOSE_POSIX
3801 #ifdef HUP_CLOSE_POSIX
3802 #undef HUP_CLOSE_POSIX
3803 #endif /* HUP_CLOSE_POSIX */
3804 #endif /* NO_HUP_CLOSE_POSIX */
3811 int x = 0; /* Sometimes used as return code. */
3818 #endif /* COHERENT */
3820 #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */
3821 int spdsav; /* for saving speed */
3827 #endif /* BSD44ORPOSIX */
3828 #endif /* HUP_POSIX */
3831 Early versions of HP-UX omitted the mflag typedef. If you get complaints
3832 about it, just change it to long (or better still, unsigned long).
3835 dtr_down = 00000000000,
3838 char modem_state[64];
3840 int flags; /* fcntl flags */
3841 unsigned short ttc_save;
3842 #endif /* SVORPOSIX */
3844 if (ttyfd < 0) return(0); /* Don't do this if not open */
3845 if (xlocal < 1) return(0); /* Don't do this if not local */
3849 return((ttclos(0) < 0) ? -1 : 1);
3853 return((ttclos(0) < 0) ? -1 : 1);
3856 if (netconn) { /* Network connection. */
3858 if (istncomport()) {
3859 int rc = tnc_set_dtr_state(0);
3862 rc = tnc_set_dtr_state(1);
3864 return(rc >= 0 ? 1 : -1);
3866 #endif /* TN_COMPORT */
3867 return((netclos() < 0) ? -1 : 1); /* Just close it. */
3869 #endif /* NETCONN */
3871 /* From here down, we handle real tty devices. */
3874 e.g. for Unixware 2, where we don't have a full POSIX build, we
3875 still have to use POSIX-style hangup. Thus the duplication of this
3876 and the next case, the only difference being we use a local termios
3877 struct here, since a different model is used elsewhere.
3879 NO LONGER USED as of C-Kermit 8.0 -- it turns out that this method,
3880 even though it compiles and executes without error, doesn't actually
3881 work (i.e. DTR does not drop), whereas the TIOCSDTR method works just fine,
3884 struct termios ttcur;
3886 debug(F100,"tthang HUP_POSIX style","",0);
3887 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3888 debug(F111,"tthang tcgetattr",ckitoa(errno),x);
3889 if (x < 0) return(-1);
3890 spdsav = cfgetospeed(&ttcur); /* Get current speed */
3891 debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
3892 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
3893 debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
3894 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
3895 debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
3896 if (x < 0) return(-1);
3897 x = cfsetispeed(&ttcur,B0);
3898 debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
3899 if (x < 0) return(-1);
3900 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3901 debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
3902 if (x < 0) return(-1);
3903 msleep(HUPTIME); /* Sleep 0.5 sec */
3904 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
3905 if (x < 0) return(-1);
3906 debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
3907 x = cfsetispeed(&ttcur,spdsavi);
3908 debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
3909 if (x < 0) return(-1);
3910 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3911 debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
3912 if (x < 0) return(-1);
3920 x = tcdropline(ttyfd,500);
3921 debug(F101,"tthang QNX tcdropline","",x);
3922 ttcur.c_cflag |= CLOCAL;
3923 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3924 debug(F101,"tthang QNX tcsetattr restore","",x);
3926 debug(F101,"tthang QNX tcsetattr restore errno","",errno);
3929 /* Fix flags - ensure O_NONBLOCK is off */
3932 debug(F101,"tthang QNX iniflags","",iniflags);
3933 if (fcntl(ttyfd, F_SETFL, iniflags) == -1) {
3934 debug(F101,"tthang QNX F_SETFL errno","",errno);
3943 debug(F100,"tthang BSD44ORPOSIX USE_TIOCSDTR","",0);
3945 x = ioctl(ttyfd, TIOCCDTR, NULL);
3946 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCCDTR",ckitoa(errno),x);
3947 if (x < 0) return(-1);
3948 msleep(HUPTIME); /* Sleep 0.5 sec */
3950 x = ioctl(ttyfd, TIOCSDTR, NULL);
3951 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCSDTR",ckitoa(errno),x);
3952 if (x < 0) return(-1);
3953 #else /* USE_TIOCSDTR */
3955 #ifdef HUP_CLOSE_POSIX
3957 In OSR5 versions where TIOCSDTR is not defined (up to and including at
3958 least 5.0.6a) the POSIX APIs in the "#else" part below are available but
3959 don't work, and no other APIs are available that do work. In this case
3960 we have to drop DTR by brute force: close and reopen the port. This
3961 code actually works, but all the steps are crucial: setting CLOCAL, the
3962 O_NDELAY manipulations, etc.
3964 debug(F100,"tthang HUP_CLOSE_POSIX close/open","",0);
3965 debug(F101,"tthang HUP_CLOSE_POSIX O_NONBLOCK","",O_NONBLOCK);
3966 debug(F101,"tthang HUP_CLOSE_POSIX O_NDELAY","",O_NDELAY);
3968 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3969 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr","",x);
3971 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr errno","",errno);
3976 x = close(ttyfd); /* Close without releasing lock */
3978 debug(F101,"tthang HUP_CLOSE_POSIX close errno","",errno);
3982 x = msleep(500); /* Pause half a second */
3983 if (x < 0) { /* Or if that doesn't work, 1 sec */
3984 debug(F101,"tthang HUP_CLOSE_POSIX msleep errno","",errno);
3988 ttyfd = priv_opn(ttnmsv, (O_RDWR|O_NDELAY)); /* Reopen the device */
3989 debug(F111,"tthang HUP_CLOSE_POSIX reopen",ttnmsv,ttyfd);
3991 debug(F101,"tthang HUP_CLOSE_POSIX reopen errno","",errno);
3994 debug(F101,"tthang HUP_CLOSE_POSIX re-ttopen ttyfd","",ttyfd);
3996 /* Restore previous attributes */
4000 ttcur.c_cflag |= CLOCAL;
4001 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4002 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore","",x);
4004 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore errno",
4008 /* Fix flags - ensure O_NDELAY and O_NONBLOCK are off */
4011 if ((x = fcntl(ttyfd, F_GETFL, 0)) == -1) {
4012 debug(F101,"tthang HUP_CLOSE_POSIX F_GETFL errno","",errno);
4015 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4017 x &= ~(O_NONBLOCK|O_NDELAY);
4018 debug(F101,"tthang HUP_CLOSE_POSIX flags to set","",x);
4019 debug(F101,"tthang HUP_CLOSE_POSIX iniflags","",iniflags);
4020 if (fcntl(ttyfd, F_SETFL, x) == -1) {
4021 debug(F101,"tthang HUP_CLOSE_POSIX F_SETFL errno","",errno);
4026 if ((x = fcntl(ttyfd, F_GETFL, 0)) > -1) {
4027 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
4028 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NONBLOCK",
4030 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NDELAY",
4036 #else /* HUP_CLOSE_POSIX */
4038 /* General BSD44ORPOSIX case (Linux, BSDI, FreeBSD, etc) */
4040 debug(F100,"tthang BSD44ORPOSIX B0","",0);
4041 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
4042 debug(F111,"tthang BSD44ORPOSIX tcgetattr",ckitoa(errno),x);
4043 if (x < 0) return(-1);
4044 spdsav = cfgetospeed(&ttcur); /* Get current speed */
4045 debug(F111,"tthang BSD44ORPOSIX cfgetospeed",ckitoa(errno),spdsav);
4046 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
4047 debug(F111,"tthang BSD44ORPOSIX cfgetispeed",ckitoa(errno),spdsavi);
4048 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
4049 debug(F111,"tthang BSD44ORPOSIX cfsetospeed",ckitoa(errno),x);
4050 if (x < 0) return(-1);
4051 x = cfsetispeed(&ttcur,B0);
4052 debug(F111,"tthang BSD44ORPOSIX cfsetispeed",ckitoa(errno),x);
4053 if (x < 0) return(-1);
4054 /* This gets EINVAL on NetBSD 1.4.1 because of B0... */
4055 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4056 debug(F111,"tthang BSD44ORPOSIX tcsetattr B0",ckitoa(errno),x);
4057 if (x < 0) return(-1);
4058 msleep(HUPTIME); /* Sleep 0.5 sec */
4059 debug(F101,"tthang BSD44ORPOSIX restore output speed","",spdsav);
4060 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
4061 debug(F111,"tthang BSD44ORPOSIX cfsetospeed prev",ckitoa(errno),x);
4062 if (x < 0) return(-1);
4063 debug(F101,"tthang BSD44ORPOSIX restore input speed","",spdsavi);
4064 x = cfsetispeed(&ttcur,spdsavi);
4065 debug(F111,"tthang BSD44ORPOSIX cfsetispeed prev",ckitoa(errno),x);
4066 if (x < 0) return(-1);
4067 ttcur.c_cflag |= CLOCAL; /* Don't expect CD after hangup */
4068 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
4069 debug(F111,"tthang BSD44ORPOSIX tcsetattr restore",ckitoa(errno),x);
4070 if (x < 0) return(-1);
4072 #endif /* HUP_CLOSE_POSIX */
4073 #endif /* USE_TIOCSDTR */
4079 #else /* BSD44ORPOSIX */
4081 #ifdef aegis /* Apollo Aegis */
4082 sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */
4083 msleep(HUPTIME); /* pause */
4084 sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */
4088 #ifdef ANYBSD /* Any BSD version. */
4089 #ifdef TIOCCDTR /* Except those that don't have this */
4090 debug(F100,"tthang BSD style","",0);
4091 if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */
4092 debug(F101,"tthang TIOCCDTR fails","",errno);
4095 msleep(HUPTIME); /* For about 1/2 sec */
4097 x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
4100 For some reason, this tends to fail with "no such device or address"
4101 but the operation still works, probably because of the close/open
4102 later on. So let's not scare the user unnecessarily here.
4104 debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
4105 x = 1; /* Pretend we succeeded */
4106 } else if (x == 0) x = 1; /* Success */
4109 ioctl(ttyfd, TIOCSAVEMODES, 0);
4110 ioctl(ttyfd, TIOCHPCL, 0);
4111 close(ttyfd); /* Yes, must do this twice */
4112 if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */
4113 return(-1); /* (but why?) */
4116 #endif /* COMMENT */
4117 #endif /* TIOCCDTR */
4118 close(do_open(ttnmsv)); /* Clear i/o error condition */
4121 /* This is definitely dangerous. Why was it here? */
4122 z = ttvt(ttspeed,ttflow); /* Restore modes. */
4123 debug(F101,"tthang ttvt returns","",z);
4124 return(z < 0 ? -1 : 1);
4127 #endif /* COMMENT */
4131 /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
4134 /* Hewlett Packard allows explicit manipulation of modem signals. */
4138 debug(F100,"tthang HP-UX style","",0);
4139 if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) /* lower DTR */
4140 return(-1); /* oops, can't. */
4141 msleep(HUPTIME); /* Pause half a second. */
4142 x = 1; /* Set return code */
4143 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4144 if ((modem_rtn & MDCD) != 0) /* Check if CD is low. */
4145 x = -1; /* CD didn't drop, fail. */
4148 /* Even if above calls fail, RTS & DTR should be turned back on. */
4149 modem_rtn = MRTS | MDTR;
4150 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
4153 /* New way, from Hellmuth Michaelis */
4154 debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
4155 if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
4156 debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
4159 sprintf(modem_state,"%#lx",modem_rtn);
4160 debug(F110,"tthang HP-UX: modem lines = ",modem_state,0);
4161 modem_sav = modem_rtn; /* Save current modem signals */
4162 modem_rtn &= ~MDTR; /* Turn DTR bit off */
4163 sprintf(modem_state,"%#lx",modem_rtn);
4164 debug(F110,"tthang HP-UX: DTR down = ",modem_state,0);
4165 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
4166 debug(F100,"tthang HP-UX: can't lower DTR!","",0);
4167 return(-1); /* oops, can't. */
4169 msleep(HUPTIME); /* Pause half a second. */
4170 x = 1; /* Set return code */
4171 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4172 sprintf(modem_state,"%#lx",modem_rtn);
4173 debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
4174 if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */
4175 debug(F100,"tthang HP-UX: DCD not down","",0);
4176 x = -1; /* CD didn't drop, fail. */
4178 debug(F100,"tthang HP-UX: DCD down","",0);
4182 debug(F100,"tthang HP-UX: can't get DCD status !","",0);
4185 /* Even if above calls fail, DTR should be turned back on. */
4188 if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
4190 debug(F100,"tthang HP-UX: can't set saved state","",0);
4192 sprintf(modem_state,"%#lx",modem_sav);
4193 debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
4196 #endif /* COMMENT */
4198 #else /* AT&T but not HP-UX */
4200 /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
4201 /* It is not known how many, if any, systems actually implement them, */
4202 /* so we include them here in ifdef's. */
4205 Unixware has the TIOCMxxx symbols defined, but calling ioctl() with them
4206 gives error 22 (invalid argument).
4210 No modem-signal twiddling for IBM RT PC or RS/6000.
4211 In AIX 3.1 and earlier, the ioctl() call is broken.
4212 This code could be activated for AIX 3.1 with PTF 2006 or later
4213 (e.g. AIX 3.2), but close/open does the job too, so why bother.
4215 #ifdef TIOCMBIS /* Bit Set */
4216 #ifdef TIOCMBIC /* Bit Clear */
4217 #ifdef TIOCM_DTR /* DTR */
4219 /* Clear DTR, sleep 300 msec, turn it back on. */
4220 /* If any of the ioctl's return failure, go on to the next section. */
4222 z = TIOCM_DTR; /* Code for DTR. */
4225 This was the cause of the troubles with the Solaris Port Monitor.
4226 The problem is: RTS never comes back on. Moral: Don't do it!
4227 (But why doesn't it come back on? See the TIOCMBIS call...)
4229 #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */
4231 #endif /* TIOCM_RTS */
4232 #endif /* COMMENT */
4234 debug(F101,"tthang TIOCM signal mask","",z);
4235 if (ioctl(ttyfd,TIOCMBIC,&z) > -1) { /* Try to lower DTR. */
4236 debug(F100,"tthang TIOCMBIC ok","",0);
4237 msleep(HUPTIME); /* Pause half a second. */
4238 if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
4239 debug(F100,"tthang TIOCMBIS ok","",0);
4241 return(1); /* Success, done. */
4243 } else { /* Couldn't raise, continue. */
4244 debug(F101,"tthang TIOCMBIS errno","",errno);
4246 } else { /* Couldn't lower, continue. */
4247 debug(F101,"tthang TIOCMBIC errno","",errno);
4249 #endif /* TIOCM_DTR */
4250 #endif /* TIOCMBIC */
4251 #endif /* TIOCMBIS */
4255 General AT&T UNIX case, not HPUX. The following code is highly suspect. No
4256 two AT&T-based systems seem to do this the same way. The object is simply
4257 to turn off DTR and then turn it back on. SVID says the universal method
4258 for turning off DTR is to set the speed to zero, and this does seem to do
4259 the trick in all cases. But neither SVID nor any known man pages say how to
4260 turn DTR back on again. Some variants, like most Xenix implementations,
4261 raise DTR again when the speed is restored to a nonzero value. Others
4262 require the device to be closed and opened again, but this is risky because
4263 getty could seize the device during the instant it is closed.
4266 /* Return code for ioctl failures... */
4268 x = 1; /* ATT6300 doesn't want to fail... */
4271 #endif /* ATT6300 */
4273 debug(F100,"tthang get settings","",0);
4274 if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
4275 return(x); /* Fail if this doesn't work. */
4276 if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
4278 ttc_save = ttcur.c_cflag; /* Remember current speed. */
4279 spdsav = ttc_save & CBAUD;
4280 debug(F101,"tthang speed","",spdsav);
4283 debug(F100,"tthang turning O_NDELAY on","",0);
4284 fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
4285 #endif /* O_NDELAY */
4287 #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
4288 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4291 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4292 #else /* This way really works but may be dangerous */
4294 ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */
4295 /* (CLOCAL must be OFF) */
4297 #ifdef SCO3R2 /* SCO UNIX 3.2 */
4299 This is complete nonsense, but an SCO user claimed this change made
4300 hanging up work. Comments from other SCO UNIX 3.2 users would be
4303 ttcur.c_cflag = CBAUD|B0;
4305 #ifdef AIXRS /* AIX on RS/6000 */
4307 Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
4308 even though you can do it on the built-in port and the 8- and 16-port
4309 adapters. (Untested on 128-port adapter.)
4311 ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
4312 #else /* None of the above */
4314 Set everything, including the speed, to zero, except for the CLOCAL
4317 ttcur.c_cflag = CLOCAL|HUPCL;
4322 #endif /* ATT7300 */
4325 /* and if none of those work, try one of these... */
4327 ttcur.c_cflag = CLOCAL;
4328 ttcur.c_cflag &= ~(CBAUD|HUPCL);
4329 ttcur.c_cflag &= ~(CBAUD|CREAD);
4330 ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
4331 /* or other combinations */
4332 #endif /* COMMENT */
4335 debug(F100,"tthang TCXONC","",0);
4336 if (ioctl(ttyfd, TCXONC, 1) < 0) {
4337 debug(F101,"tthang TCXONC failed","",errno);
4342 debug(F100,"tthang TIOCSTART","",0);
4343 if (ioctl(ttyfd, TIOCSTART, 0) < 0) {
4344 debug(F101,"tthang TIOCSTART failed","",errno);
4346 #endif /* TIOCSTART */
4348 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
4349 debug(F101,"tthang TCSETAF failed","",errno);
4350 fcntl(ttyfd, F_SETFL, flags); /* Restore flags */
4351 return(-1); /* before returning. */
4353 msleep(300); /* Give modem time to notice. */
4357 /* Now, even though it doesn't say this in SVID or any man page, we have */
4358 /* to close and reopen the device. This is not necessary for all systems, */
4359 /* but it's impossible to predict which ones need it and which ones don't. */
4363 Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
4364 related ioctl's for their internal modems. attmodem has getty status and
4365 modem-in-use bit. Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
4366 but also ruins the file descriptor, and no other phone(7) ioctl call can fix
4367 it. Whatever it does, it seems to escape detection with PIOCGETA and TCGETA.
4368 The only way to undo the damage is to close the fd and then reopen it.
4370 if (attmodem & ISMODEM) {
4371 debug(F100,"tthang attmodem close/open","",0);
4372 ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
4373 ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */
4374 close(ttyfd); /* Close and reopen the fd. */
4375 ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
4376 attmodem &= ~ISMODEM; /* Phone no longer in use. */
4378 #else /* !ATT7300 */
4379 /* It seems we have to close and open the device for other AT&T systems */
4380 /* too, and this is the place to do it. The following code does the */
4381 /* famous close(open(...)) magic by default. If that doesn't work for you, */
4382 /* then try uncommenting the following statement or putting -DCLSOPN in */
4383 /* the makefile CFLAGS. */
4385 /* #define CLSOPN */
4387 #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
4390 #define OPENFLGS O_RDWR | O_NDELAY
4392 #define OPENFLGS O_RDWR
4396 /* This method is used by default, i.e. unless CLSOPN is defined. */
4397 /* It is thought to be safer because there is no window where getty */
4398 /* can seize control of the device. The drawback is that it might not work. */
4400 debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
4401 close(priv_opn(ttnmsv, OPENFLGS));
4404 /* This method is used if you #define CLSOPN. It is more likely to work */
4405 /* than the previous method, but it's also more dangerous. */
4407 debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
4410 ttyfd = priv_opn(ttnmsv, OPENFLGS); /* Open it again */
4415 #endif /* ATT7300 */
4417 #endif /* NOCOTFMC */
4419 /* Now put all flags & modes back the way we found them. */
4420 /* (Does the order of ioctl & fcntl matter ? ) */
4422 debug(F100,"tthang restore settings","",0);
4423 ttcur.c_cflag = ttc_save; /* Get old speed back. */
4424 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
4428 This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
4429 After closing a modem line, the modem will probably not be asserting
4430 carrier any more, so we should not require carrier any more. If this
4431 causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
4434 flags &= ~O_NDELAY; /* Don't require carrier on reopen */
4435 #endif /* O_NDELAY */
4436 if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */
4440 #endif /* not HPUX */
4442 #endif /* BSD44ORPOSIX */
4443 #endif /* HUP_POSIX */
4444 #endif /* NOLOCAL */
4448 Major change in 5A(174). We used to use LPASS8, if it was defined, to
4449 allow 8-bit data and Xon/Xoff flow control at the same time. But this
4450 LPASS8 business seems to have been causing trouble for everybody but me!
4451 For example, Annex terminal servers, commonly used with Encore computers,
4452 do not support LPASS8 even though the Encore itself does. Ditto for many
4453 other terminal servers, TELNET connections, rlogin connections, etc etc.
4454 Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
4455 serial lines, even though LPASS8 is a feature of 4.3BSD. So let's turn it
4456 off for everybody. That means we goes back to using raw mode, with no
4457 flow control. Phooey.
4459 NOTE: This must be done before the first reference to LPASS8 in this file,
4460 and after the last #include statment.
4466 /* T T R E S -- Restore terminal to "normal" mode. */
4468 /* ske@pkmab.se: There are two choices for what this function should do.
4469 * (1) Restore the tty to current "normal" mode, with carrier treatment
4470 * according to ttcarr, to be used after every kermit command. (2) Restore
4471 * the tty to the state it was in before kermit opened it. These choices
4472 * conflict, since ttold can't hold both choices of tty parameters. ttres()
4473 * is currently being called as in choice (1), but ttold basically holds
4474 * the initial parameters, as in (2), and the description at the beginning
4475 * of this file says (2).
4477 * I don't think restoring tty parameters after all kermit commands makes
4478 * much of a difference. Restoring them upon exit from kermit may be of
4479 * some use in some cases (when the line is not restored automatically on
4480 * close, by the operating system).
4482 * I can't choose which one it should be, so I haven't changed it. It
4483 * probably works as it is, too. It would probably even work even with
4484 * ttres() entirely deleted...
4486 * (from fdc: Actually, this function operates in remote mode too, so
4487 * it restores the console (command) terminal to whatever mode it was
4488 * in before packet operations began, so that commands work right again.)
4491 ttres() { /* Restore the tty to normal. */
4494 if (ttyfd < 0) return(-1); /* Not open. */
4496 if (ttfdflg) return(0); /* Don't mess with terminal modes if */
4497 /* we got ttyfd from another process */
4499 if (netconn) { /* Network connection */
4504 extern int tcp_nodelay; /* Just put this back if necessary */
4505 if (ttnet == NET_TCPB) {
4506 if (nodelay_sav > -1) {
4507 no_delay(ttyfd,nodelay_sav);
4512 #endif /* TCP_NODELAY */
4514 if (istncomport()) {
4516 if ((rc = tnsetflow(ttflow)) < 0)
4519 ttspeed = tnc_get_baud();
4520 else if ((rc = tnc_set_baud(ttspeed)) < 0)
4522 tnc_set_datasize(8);
4523 tnc_set_stopsize(stopbits);
4528 case 'e': /* Even */
4529 debug(F100,"ttres 8 bits + even parity","",0);
4533 debug(F100,"ttres 8 bits + odd parity","",0);
4536 case 'm': /* Mark */
4537 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
4540 case 's': /* Space */
4541 debug(F100,"ttres 8 bits + invalid parity: space","",0);
4546 #endif /* HWPARITY */
4548 tnc_set_parity(1); /* None */
4553 #endif /* TN_COMPORT */
4554 #endif /* TCPSOCKET */
4557 #endif /* NETCONN */
4559 if (ttpipe) return(0);
4562 if (ttpty) return(0);
4565 /* Real terminal device, so restore its original modes */
4567 #ifdef BSD44ORPOSIX /* For POSIX like this */
4568 debug(F100,"ttres BSD44ORPOSIX","",0);
4569 x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
4570 #else /* For all others... */
4571 #ifdef ATTSV /* For AT&T versions... */
4572 debug(F100,"ttres ATTSV","",0);
4573 x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */
4575 /* Here we restore the modes for BSD */
4577 #ifdef LPASS8 /* Undo "pass8" if it were done */
4579 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4580 debug(F100,"ttres TIOCLSET failed","",0);
4582 debug(F100,"ttres TIOCLSET ok","",0);
4586 #ifdef CK_DTRCTS /* Undo hardware flow if it were done */
4588 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4589 debug(F100,"ttres TIOCLSET failed","",0);
4591 debug(F100,"ttres TIOCLSET ok","",0);
4593 #endif /* CK_DTRCTS */
4595 #ifdef TIOCGETC /* Put back special characters */
4596 if (tcharf && (xlocal == 0)) {
4597 if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
4598 debug(F100,"ttres TIOCSETC failed","",0);
4600 debug(F100,"ttres TIOCSETC ok","",0);
4602 #endif /* TIOCGETC */
4604 #ifdef TIOCGLTC /* Put back local special characters */
4605 if (ltcharf && (xlocal == 0)) {
4606 if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
4607 debug(F100,"ttres TIOCSLTC failed","",0);
4609 debug(F100,"ttres TIOCSLTC ok","",0);
4611 #endif /* TIOCGLTC */
4614 debug(F100,"ttres BELLV10","",0);
4615 x = ioctl(ttyfd,TIOCSETP,&ttold); /* Restore both structs */
4616 x = ioctl(ttyfd,TIOCSDEV,&tdold);
4618 debug(F100,"ttres stty","",0);
4619 x = stty(ttyfd,&ttold); /* Restore tty modes the old way. */
4620 #endif /* BELLV10 */
4623 msleep(100); /* This replaces sleep(1)... */
4624 /* Put back sleep(1) if tty is */
4625 /* messed up after close. */
4627 #endif /* BSD44ORPOSIX */
4629 debug(F101,"ttres result","",x);
4631 if (x < 0) debug(F101,"ttres errno","",errno);
4636 x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
4637 debug(F101,"ttres AIX line discipline rts restore","",x);
4642 if (ttld > -1) { /* Put back line discipline */
4643 x = ioctl(ttyfd, TIOCSETD, &ttld);
4644 debug(F101,"ttres BSD41 line discipline restore","",x);
4645 if (x < 0) debug(F101,"...ioctl errno","",errno);
4651 x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */
4652 if (x != -1) { /* Make sure we know original modes. */
4653 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
4654 perror("ttres can't set Kanji mode");
4655 debug(F101,"ttres error setting Kanji mode","",x);
4659 debug(F100,"ttres set Kanji mode ok","",0);
4660 #endif /* sony_news */
4662 tvtflg = 0; /* Invalidate terminal mode settings */
4663 debug(F101,"ttres return code","",x);
4669 /* T T C H K P I D -- Check lockfile pid */
4671 Read pid from lockfile named f, check that it's still valid.
4673 On failure to read pid, return 1.
4674 Otherwise, try to delete lockfile f and return 0 if successful, else 1.
4677 ttchkpid(f) char *f; {
4679 pid = ttrpid(f); /* Read pid from file. */
4680 if (pid > -1) { /* If we were able to read the pid.. */
4681 debug(F101,"ttchkpid lock pid","",pid);
4682 errno = 0; /* See if process still exists. */
4683 mypid = (int)getpid(); /* Get my own pid. */
4684 debug(F101,"ttchkpid my pid","",mypid);
4685 if (pid == mypid) { /* It's me! */
4686 x = -1; /* So I can delete it */
4687 errno = ESRCH; /* pretend it's invalid */
4688 } else { /* It's not me */
4689 x = kill((PID_T)pid, 0); /* See if it's a live process */
4690 debug(F101,"ttchkpid kill errno","",errno);
4692 debug(F101,"ttchkpid pid test","",x);
4693 if (x < 0 && errno == ESRCH) { /* pid is invalid */
4694 debug(F111,"removing stale lock",f,pid);
4696 printf("Removing stale lock %s (pid %d terminated)\n", f, pid);
4698 x = unlink(f); /* Remove the lockfile. */
4700 debug(F111,"ttchkpid unlink",f,x);
4702 return(0); /* Device is not locked after all */
4708 return(1); /* Failure to read pid */
4713 /* Aliases (different drivers) for HP-UX dialout devices: */
4715 static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "cuad", "culd", "" };
4716 static int ttydexists = 0;
4720 /* T T R P I D -- Read pid from lockfile "name" */
4723 ttrpid(name) char *name; {
4729 debug(F110,"ttrpid",name,0);
4730 if (!name) return(-1);
4731 if (!*name) return(-1);
4733 len = zchki(name); /* Get file length */
4735 debug(F101,"ttrpid zchki","",len);
4741 fd = open(name,O_RDONLY); /* Try to open lockfile. */
4743 debug(F101,"ttrpid fd","",fd);
4747 Here we try to be flexible and allow for all different binary and string
4748 formats at runtime, rather than a specific format for each configuration
4749 hardwired at compile time.
4754 COHERENT uses a string PID but without leading spaces or 0's, so there is
4755 no way to tell from the file's length whether it contains a string or binary
4756 pid. So for COHERENT only, we only allow string pids. For all others, we
4757 decide based on the size of the lockfile.
4759 if (len > 4) { /* If file > 4 bytes it's a string */
4760 #endif /* COHERENT */
4761 x = read(fd,buf,(int)len);
4762 debug(F111,"ttrpid string read",buf,x);
4767 x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */
4770 } else if (len == 4) { /* 4 bytes so binary */
4771 x = read(fd, (char *)&pid, 4); /* Read the bytes into an int */
4772 debug(F101,"ttrpid integer read","",x);
4775 } else if (len == 2) { /* 2 bytes binary */
4776 x = read(fd, (char *)&spid, 2); /* Read the bytes into a short */
4777 debug(F101,"ttrpid short read","",x);
4784 #endif /* COHERENT */
4785 close(fd); /* Close the lockfile */
4786 debug(F101,"ttrpid pid","",pid);
4794 This function attempts to coordinate use of the communication device with
4795 other copies of Kermit and any other program that follows the UUCP
4796 device-locking conventions, which, unfortunately, vary among different UNIX
4797 implementations. The idea is to look for a file of a certain name, the
4798 "lockfile", in a certain directory. If such a file is found, then the line
4799 is presumed to be in use, and Kermit should not use it. If no such file is
4800 found, Kermit attempts to create one so that other programs will not use the
4801 same line at the same time. Because the lockfile and/or the directory it's
4802 in might lack write permission for the person running Kermit, Kermit could
4803 find itself running setuid to uucp or other user that does have the
4804 necessary permissions. At startup, Kermit has changed its effective uid to
4805 the user's real uid, and so ttlock() must switch back to the original
4806 effective uid in order to create the lockfile, and then back again to the
4807 real uid to prevent unauthorized access to other directories or files owned
4808 by the user the program is setuid to.
4810 Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
4811 based on suggestions from Warren Tucker. Call with pointer to name of
4812 tty device. Returns:
4817 Note: Once privileges are turned on using priv_on(), it is essential that
4818 they are turned off again before this function returns.
4820 #ifdef SVR4 /* Lockfile uses device numbers. */
4822 Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
4823 it is the behavior of the "reference version" of SVR4, i.e. the Intel
4824 port from UNIX Systems Laboratories, then called Univel UnixWare,
4825 then called Novell UnixWare, then called SCO Unixware, then called Caldera
4826 Open UNIX... It also makes much more sense than device-name-based lockfiles
4827 since there can be multiple names for the same device, symlinks, etc.
4830 #ifndef LFDEVNO /* Define this for SVR4 */
4831 #ifndef AIXRS /* But not for RS/6000 AIX 3.2, etc. */
4832 #ifndef BSD44 /* If anybody else needs it... */
4836 #ifndef IRIX51 /* SGI IRIX 5.1 or later */
4837 #ifndef CK_SCOV5 /* SCO Open Server 5.0 */
4839 #endif /* CK_SCOV5 */
4842 #endif /* __FreeBSD__ */
4843 #endif /* __386BSD__ */
4846 #endif /* LFDEVNO */ /* ... define it here or on CC */
4847 #endif /* NOLFDEVNO */
4848 #endif /* SVR4 */ /* command line. */
4852 #endif /* COHERENT */
4855 For platforms where the lockfile name is made from device/major/minor
4856 device number, as in SVR4. Which, if we must have lockfiles at all, is
4857 by far the best format, since it eliminates all the confusion that stems
4858 from multiple names (or drivers) for the same port, not to mention
4859 symlinks. It might even be a good idea to start using this form even
4860 on platforms where it's not supported, alongside the normal forms for those
4861 platforms, in order to get people used to it...
4864 #ifndef major /* If we didn't find it */
4865 #ifdef SVR4 /* then for Sys V R4 */
4866 #include <sys/mkdev.h> /* look here */
4867 #else /* or for SunOS versions */
4868 #ifdef SUNOS4 /* ... */
4869 #include <sys/sysmacros.h> /* look here */
4870 #else /* Otherwise take a chance: */
4871 #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
4872 #define minor(dev) ( (int) ( (dev) & 0xff))
4876 #endif /* LFDEVNO */
4878 /* No advisory locks if F_TLOCK and F_ULOCK are not defined at this point */
4885 #endif /* NOLOCKF */
4886 #endif /* F_TLOCK */
4894 #endif /* NOLOCKF */
4895 #endif /* F_ULOCK */
4898 static char linkto[DEVNAMLEN+1];
4899 static char * linkdev = NULL;
4904 char * uucplockdir = LOCK_DIR;
4906 char * uucplockdir = "";
4907 #endif /* LOCK_DIR */
4910 char * uucplockdir = LOCK_DIR;
4912 char * uucplockdir = "";
4913 #endif /* LOCK_DIR */
4914 #endif /* USETTYLOCK */
4916 char * uucplockdir = "";
4919 #ifdef QNX /* Only for QNX4 */
4920 int /* Visible to outside world */
4921 qnxopencount() { /* Get QNX device open count */
4922 struct _dev_info_entry info;
4925 x = -1; /* Unknown */
4927 if (!dev_info(ttyfd, &info)) {
4928 debug(F101,"ttlock QNX open_count","",info.open_count);
4929 x = info.open_count;
4937 ttglckdir() { /* Get Lockfile directory name */
4939 return("/var/spool/lock");
4940 #else /* __OpenBSD__ */
4942 return("/var/spool/lock");
4943 #else /* __FreeBSD__ */
4945 char * s = LOCK_DIR;
4946 #endif /* LOCK_DIR */
4952 #else /* LOCK_DIR */
4954 #endif /* LOCK_DIR */
4956 #endif /* __FreeBSD__ */
4957 #endif /* __OpenBSD__ */
4961 ttlock(ttdev) char *ttdev; {
4967 debug(F100,"ttlock NOUUCP","",0);
4968 ckstrncpy(flfnam,"NOLOCK",FLFNAML);
4974 haslock = 0; /* Not locked yet. */
4975 *flfnam = '\0'; /* Lockfile name is empty. */
4976 if (!strncmp(ttdev,"/dev/",5) && ttdev[5])
4977 ckstrncpy(lockname,ttdev+5,DEVNAMLEN);
4979 ckstrncpy(lockname,ttdev,DEVNAMLEN);
4981 This might be overkill, but it's not clear from the man pages whether
4982 ttylock() can be called without calling ttylocked() first, since the doc
4983 says that ttylocked() removes any stale lockfiles, but it does not say this
4984 about ttylock(). Also the docs don't say what ttylocked() returns in the
4985 case when it finds and removes a stale lockfile. So one or both calls to
4986 to ttylocked() might be superfluous, but they should do no harm. Also I'm
4987 assuming that we have to do all the same ID swapping, etc, with these
4988 routines as we do without them. Thus the priv_on/off() sandwich.
4991 priv_on(); /* Turn on privs */
4992 x = uu_lock(lockname); /* Try to set the lock */
4993 priv_off(); /* Turn privs off */
4994 debug(F111,"ttlock uu_lock",lockname,x);
5000 ckmakmsg(flfnam,FLFNAML,"/var/spool/lock/LCK..",lockname,NULL,NULL);
5007 #else /* USE_UU_LOCK */
5008 priv_on(); /* Turn on privs */
5009 if (ttylocked(lockname)) { /* This should remove any stale lock */
5010 if (ttylocked(lockname)) { /* so check again. */
5012 return(-5); /* Still locked, fail. */
5015 x = ttylock(lockname); /* Lock it. */
5016 priv_off(); /* Turn off privs */
5018 debug(F111,"ttlock lockname",lockname,x);
5021 We don't really know the name of the lockfile, but
5022 this is what the man page says it is. In USETTYLOCK
5023 builds, it is used only for display by SHOW COMM.
5025 ckmakmsg(flfnam,FLFNAML,"/etc/locks/LCK..",lockname,NULL,NULL);
5029 #endif /* USE_UU_LOCK */
5030 #else /* Systems that don't have ttylock()... */
5034 int lockfd; /* File descriptor for lock file. */
5035 PID_T pid; /* Process id of this process. */
5036 int tries; /* How many times we've tried... */
5037 struct stat devbuf; /* For device numbers (SVR4). */
5040 char pid_str[32]; /* My pid in string format. */
5041 #endif /* PIDSTRING */
5043 char *device, *devname;
5045 #define LFNAML 256 /* Max length for lock file name. */
5046 char lockfil[LFNAML]; /* Lock file name */
5048 char lklockf[LFNAML]; /* Name for link to lock file */
5051 char symlock[LFNAML]; /* Name for symlink lockfile name */
5052 #endif /* CKSYMLINK */
5053 char tmpnam[LFNAML+30]; /* Temporary lockfile name. */
5054 char *lockdir = LOCK_DIR; /* Defined near top of this file, */
5055 /* or on cc command line. */
5056 haslock = 0; /* Not locked yet. */
5057 *flfnam = '\0'; /* Lockfile name is empty. */
5058 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5059 pid = getpid(); /* Get id of this process. */
5061 /* Construct name of lockfile and temporary file */
5063 /* device = name of tty device without the path, e.g. "ttyh8" */
5064 /* lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
5066 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5068 if (stat(ttdev,&devbuf) < 0)
5072 islink = 1; /* Assume it's a symlink */
5073 linkto[0] = '\0'; /* But we don't know to what */
5076 This is undependable. If it worked it would save the readlink call if
5077 we knew the device name was not a link.
5080 islink = S_ISLNK(devbuf.st_mode);
5081 debug(F101,"ttlock stat S_ISLNK","",islink);
5082 #endif /* S_ISLNK */
5083 #endif /* COMMENT */
5085 n = readlink(ttdev,linkto,DEVNAMLEN); /* See if it's a link */
5086 debug(F111,"ttlock readlink",ttdev,n);
5087 if (n > -1) /* It is */
5091 debug(F111,"ttlock link",linkto,islink);
5094 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5095 debug(F110,"ttlock linkdev",linkdev,0);
5097 #endif /* CKSYMLINK */
5100 On SCO platforms, if we don't have a symlink, then let's pretend the
5101 name given for the device is a symlink, because later we will change
5102 the name if it contains any uppercase characters.
5104 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5107 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5108 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5109 debug(F110,"ttlock linkdev",linkdev,0);
5112 #ifdef M_XENIX /* SCO Xenix or UNIX */
5115 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5116 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5117 debug(F110,"ttlock linkdev",linkdev,0);
5119 #endif /* M_XENIX */
5120 #endif /* CK_SCOV5 */
5122 #ifdef ISIII /* Interactive System III, PC/IX */
5123 ckstrncpy(lockfil, device, DEVNAMLEN);
5124 #else /* not ISIII */
5125 #ifdef LFDEVNO /* Lockfilename has device numbers. */
5127 sprintf(lockfil,"LCK..%d.%d", /* SAFE */
5128 major(devbuf.st_rdev), /* major device number */
5129 0x1f & minor(devbuf.st_rdev)); /* minor device number */
5131 /* Note: %d changed to %u in 8.0 -- %u is part of SVID for SVR4 */
5132 /* Lockfile name format verified to agree with Solaris cu, Dec 2001 */
5133 sprintf(lockfil,"LK.%03u.%03u.%03u", /* SAFE */
5134 major(devbuf.st_dev), /* device */
5135 major(devbuf.st_rdev), /* major device number */
5136 minor(devbuf.st_rdev)); /* minor device number */
5137 #endif /* COHERENT */
5138 #else /* Not LFDEVNO */
5139 #ifdef PTX /* Dynix PTX */
5140 if ((device != &ttdev[5]) && (strncmp(ttdev,"/dev/",5) == 0)) {
5141 if ((int)strlen(device) + 8 < LFNAML)
5142 sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
5144 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5147 if ((int)strlen(device) + 5 < LFNAML)
5148 sprintf(lockfil,"LCK..%s", device);
5150 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5152 ckstrncpy(lklockf,device,DEVNAMLEN);
5157 ckmakmsg(symlock,LFNAML, "LCK..", linkdev, NULL, NULL);
5158 #endif /* CKSYMLINK */
5159 #endif /* LFDEVNO */
5162 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5164 /* Lowercase the entire filename. */
5165 /* SCO says we must do this in V5.0 and later. */
5166 /* BUT... watch out for devices -- like Digiboard Portserver */
5167 /* That can have hundreds of ports... */
5168 char *p = (char *)(lockfil + 5);
5169 while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
5172 if (islink) { /* If no change */
5173 if (!strcmp(lockfil,symlock)) { /* then no second lockfile needed */
5178 #endif /* CKSYMLINK */
5180 #ifdef M_XENIX /* SCO Xenix or UNIX */
5183 x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */
5184 if (x > 0) { /* If it's uppercase, lower it. */
5186 if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
5191 if (!strcmp(lockfil,symlock)) { /* No change */
5192 islink = 0; /* so no second lockfile */
5196 #endif /* CKSYMLINK */
5197 #endif /* M_XENIX */
5198 #endif /* CK_SCOV5 */
5200 /* flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
5201 /* tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
5203 ckmakmsg(flfnam,LFNAML,lockdir,"/",lockfil,NULL);
5206 ckmakmsg(lkflfn,FLFNAML,lockdir,"/",lklockf,NULL);
5211 /* If it's a link then also make a lockfile for the real name */
5212 debug(F111,"ttlock link symlock",symlock,islink);
5213 if (islink && symlock[0]) {
5214 /* But only if the lockfile names would be different. */
5215 /* WARNING: They won't be, e.g. for /dev/ttyd2 => /hw/ttys/ttyd2 */
5216 ckmakmsg(lock2,FLFNAML,lockdir,"/",symlock,NULL);
5217 debug(F110,"ttlock lock2",lock2,0);
5218 if (!strcmp(lock2,flfnam)) { /* Are lockfile names the same? */
5219 debug(F100,"ttlock lock2 cleared","",0);
5220 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5223 #endif /* CKSYMLINK */
5224 #endif /* LFDEVNO */
5226 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* safe */
5227 debug(F110,"ttlock flfnam",flfnam,0);
5228 debug(F110,"ttlock tmpnam",tmpnam,0);
5230 priv_on(); /* Turn on privileges if possible. */
5231 lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */
5232 if (lockfd < 0) { /* Create failed. */
5233 debug(F111,"ttlock creat failed",tmpnam,errno);
5234 if (errno == ENOENT) {
5236 printf("UUCP not installed or Kermit misconfigured\n");
5240 unlink(tmpnam); /* Get rid of the temporary file. */
5242 priv_off(); /* Turn off privileges!!! */
5243 return(-1); /* Return failure code. */
5245 /* Now write the pid into the temp lockfile in the appropriate format */
5247 #ifdef PIDSTRING /* For Honey DanBer UUCP, */
5248 sprintf( /* write PID as decimal string */
5250 #ifdef LINUXFSSTND /* The "Linux File System Standard" */
5251 #ifdef FSSTND10 /* Version 1.0 calls for */
5252 "%010d\n", /* leading zeros */
5253 #else /* while version 1.2 calls for */
5254 "%10d\n", /* leading spaces */
5255 #endif /* FSSTND10 */
5258 "%d\n", /* with leading nothing */
5260 "%10d\n", /* with leading blanks */
5261 #endif /* COHERENT */
5262 #endif /* LINUXFSSTND */
5265 write(lockfd, pid_str, 11);
5266 debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
5268 #else /* Not PIDSTRING, use integer PID */
5270 write(lockfd, (char *)&pid, sizeof(pid) );
5271 debug(F101,"ttlock pid","",(int) pid);
5273 #endif /* PIDSTRING */
5275 /* Now try to rename the temp file to the real lock file name. */
5276 /* This will fail if a lock file of that name already exists. */
5278 close(lockfd); /* Close the temp lockfile. */
5279 chmod(tmpnam,0444); /* Permission for a valid lock. */
5281 while (!haslock && tries++ < 2) {
5282 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5283 if (haslock) { /* If we got the lockfile */
5285 link(flfnam,lkflfn);
5289 if (islink && lock2[0])
5291 #endif /* LFDEVNO */
5292 #endif /* CKSYMLINK */
5295 /* Can't do this any more because device is not open yet so no ttyfd. */
5298 Advisory file locking works on SVR4, so we use it. In fact, it is
5299 necessary in some cases, e.g. when SLIP is involved. But it still doesn't
5300 seem to prevent multiple users accessing the same device by different names.
5302 while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
5303 debug(F111, "ttlock lockf returns errno", "", errno);
5304 if ((++tries >= 3) || (errno != EAGAIN)) {
5305 x = unlink(flfnam); /* remove the lockfile */
5307 unlink(lkflfn); /* And any links to it... */
5311 if (islink && lock2[0])
5312 unlink(lock2); /* ditto... */
5313 #endif /* LFDEVNO */
5314 #endif /* CKSYMLINK */
5315 debug(F111,"ttlock unlink",flfnam,x);
5321 if (haslock) /* If we got an advisory lock */
5323 #endif /* COMMENT */
5324 break; /* We're done. */
5326 } else { /* We didn't create a new lockfile. */
5328 if (ttchkpid(flfnam)) { /* Check existing lockfile */
5329 priv_on(); /* cause ttchkpid turns priv_off... */
5330 unlink(tmpnam); /* Delete the tempfile */
5331 debug(F100,"ttlock found tty locked","",0);
5332 priv_off(); /* Turn off privs */
5333 return(-2); /* Code for device is in use. */
5338 unlink(tmpnam); /* Unlink (remove) the temp file. */
5339 priv_off(); /* Turn off privs */
5340 return(haslock ? 0 : -1); /* Return link's return code. */
5345 HP-UX gets its own copy of this routine, modeled after the observed behavior
5346 of the HP-UX 'cu' program. HP-UX serial device names consist of a base name
5347 such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
5348 designator which is a string of digits, possibly containing an imbedded
5349 letter "p". Examples (for base name "tty"):
5351 /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
5353 According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
5354 used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
5355 on other models. In HP-UX 10.00, "0p0" notation was adopted for all models.
5356 However, we make and enforce no such distinctions; either notation is
5357 accepted on any model or HP-UX version as a valid unit designator.
5359 If a valid unit is specified (as opposed to a designer name or symlink), we
5360 check for all aliases of the given unit according to the devprefix[] array.
5361 If no lockfiles are found for the given unit, we can have the device; we
5362 create a lockfile LCK..name in the lockfile directory appropriate for the
5363 HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
5364 9.xx and earlier). If it is a "cua" or "cul" device, a second lockfile is
5365 created with the "ttyd" prefix. This is exactly what cu does.
5367 If the "set line" device does not have a valid unit designator, then it is
5368 used literally and no synomyms are searched for and only one lockfile is
5373 #define LFNAML 80 /* Max length for lock file name. */
5375 int lockfd; /* File descriptor for lock file. */
5376 PID_T pid; /* Process ID of this process. */
5377 int fpid; /* pid found in existing lockfile. */
5378 int tries; /* How many times we've tried... */
5379 int i, k; /* Workers */
5381 char *device, *devname; /* "/dev/xxx", "xxx" */
5382 char *unit, *p; /* <instance>p<port> part of xxx */
5384 char lockfil[LFNAML]; /* Lockfile name (no path) */
5385 char tmpnam[LFNAML]; /* Temporary lockfile name. */
5387 #ifdef HPUX10 /* Lockfile directory */
5388 char *lockdir = "/var/spool/locks"; /* Always this for 10.00 and higher */
5389 #else /* HP-UX 9.xx and below */
5391 char *lockdir = LOCK_DIR; /* Defined near top of this file */
5393 char *lockdir = "/usr/spool/uucp"; /* or not... */
5394 #endif /* LOCK_DIR */
5397 haslock = 0; /* Not locked yet. */
5398 *flfnam = '\0'; /* Lockfile name is empty. */
5399 lock2[0] = '\0'; /* Second one too. */
5400 pid = getpid(); /* Get my process ID */
5402 Construct name of lockfile and temporary file...
5403 device = name of tty device without the path, e.g. "tty0p0"
5404 lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
5406 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5407 debug(F110,"TTLOCK device",device,0);
5408 ckmakmsg(lockfil,LFNAML,"LCK..",device,NULL,NULL);
5410 k = 0; /* Assume device is not locked */
5411 n = 0; /* Digit counter */
5412 unit = device; /* Unit = <instance>p<port> */
5413 while (*unit && !isdigit(*unit)) /* Search for digit... */
5415 p = unit; /* Verify <num>p<num> format... */
5416 debug(F110,"TTLOCK unit 1",unit,0);
5418 The unit number is recognized as:
5419 (a) any sequence of digits that runs to the end of the string.
5420 (b) any (a) that includes one and only one letter "p", with at least
5421 one digit before and after it.
5423 while (isdigit(*p)) p++, n++; /* Get a run of digits */
5424 if (*p && n > 0) { /* Have a "p"? */
5425 if (*p == 'p' && isdigit(*(p+1))) {
5428 while (isdigit(*p)) p++, n++;
5431 if (n == 0 || *p) unit = "";
5432 debug(F110,"TTLOCK unit 2",unit,0);
5434 if (*unit) { /* Device name has unit number. */
5435 /* The following loop not only searches for the various lockfile */
5436 /* synonyms, but also removes all -- not just one -- stale lockfile */
5437 /* for the device, should there be more than one. See ttchkpid(). */
5439 for (i = 0; *devprefix[i]; i++) { /* For each driver... */
5440 /* Make device name */
5441 ckmakmsg(lock2,FLFNAML,"/dev/",devprefix[i],unit,NULL);
5442 priv_on(); /* Privs on */
5443 k = zchki(lock2) != -1; /* See if device exists */
5444 priv_off(); /* Privs off */
5445 debug(F111,"TTLOCK exist",lock2,k);
5447 if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
5449 /* Make lockfile name */
5450 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",devprefix[i],unit);
5451 debug(F110,"TTLOCK checking",lock2,0);
5452 priv_on(); /* Privs on */
5453 k = zchki(lock2) != -1; /* See if lockfile exists */
5454 priv_off(); /* Privs off */
5455 debug(F111,"TTLOCK check for lock A",lock2,k);
5456 if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
5457 ckstrncpy(flfnam,lock2,FLFNAML);
5462 } else { /* Some other device-name format */
5463 /* This takes care of symbolic links, etc... */
5464 /* But does not chase them down! */
5465 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",device,NULL);
5467 k = zchki(lock2) != -1; /* Check for existing lockfile */
5469 debug(F111,"TTLOCK check for lock B",lock2,k);
5470 if (k) if (ttchkpid(lock2)) { /* Check pid from lockfile */
5471 ckstrncpy(flfnam,lock2,FLFNAML);
5472 debug(F110,"TTLOCK in use",device,0);
5473 debug(F101,"TTLOCK returns","",-2);
5478 Get here only if there is no (more) lockfile, so now we make one (or two)...
5479 flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
5480 tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
5482 ckmakmsg(flfnam,FLFNAML,lockdir,"/",lockfil,NULL); /* SET LINE device */
5484 /* If dialout device, also make one for corresponding dialin device */
5486 if (!strncmp(device,"cu",2) && *unit && ttydexists)
5487 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..ttyd",unit,NULL);
5489 if ((int)strlen(lockdir)+12 < LFNAML)
5490 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temp name */
5493 debug(F110,"TTLOCK flfnam",flfnam,0);
5494 debug(F110,"TTLOCK lock2",lock2,0);
5495 debug(F110,"TTLOCK tmpnam",tmpnam,0);
5499 Lockfile permissions...
5500 444 is standard, HP-UX 10.00 uses 664. It doesn't matter.
5501 Kermit uses 444; the difference lets us tell whether Kermit created
5504 priv_on(); /* Turn on privileges. */
5505 lockfd = creat(tmpnam, 0444); /* Try to create temporary file. */
5506 if (lockfd < 0) { /* Create failed. */
5507 debug(F111,"TTLOCK creat failed",tmpnam,errno);
5508 if (errno == ENOENT) {
5510 printf("UUCP not installed or Kermit misconfigured\n");
5514 unlink(tmpnam); /* Get rid of the temporary file. */
5516 priv_off(); /* Turn off privileges!!! */
5517 debug(F101,"TTLOCK returns","",-1);
5518 return(-1); /* Return failure code. */
5520 debug(F110,"TTLOCK temp ok",tmpnam,0);
5522 /* Now write our pid into the temp lockfile in integer format. */
5524 i = write(lockfd, (char *)&pid, sizeof(pid));
5528 debug(F101,"TTLOCK pid","",pid);
5529 debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
5530 debug(F101,"TTLOCK write pid returns","",i);
5535 Now try to rename the temporary file to the real lockfile name.
5536 This will fail if a lock file of that name already exists, which
5537 will catch race conditions with other users.
5539 close(lockfd); /* Close the temp lockfile. */
5543 while (!haslock && tries++ < 2) {
5544 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5545 debug(F101,"TTLOCK link","",haslock);
5546 if (haslock) { /* If we made the lockfile... */
5549 /* We can't do this any more because we don't have a file descriptor yet. */
5550 #ifdef LOCKF /* Can be canceled with -DNOLOCKF */
5552 Create an advisory lock on the device through its file descriptor.
5553 This code actually seems to work. If it is executed, and then another
5554 process tries to open the same device under a different name to circumvent
5555 the lockfile, they get a "device busy" error.
5557 debug(F100,"TTLOCK LOCKF code...","",0);
5558 while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
5559 debug(F111, "TTLOCK lockf error", "", errno);
5560 if ((++tries >= 3) || (errno != EAGAIN)) {
5561 x = unlink(flfnam); /* Remove the lockfile */
5562 if (errno == EACCES && !quiet)
5563 printf("Device already locked by another process\n");
5570 #endif /* COMMENT */
5572 if (haslock) { /* If we made the lockfile ... */
5573 if (lock2[0]) { /* if there is to be a 2nd lockfile */
5574 lockfd = creat(lock2, 0444); /* Create it */
5575 debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
5576 if (lockfd > -1) { /* Created OK, write pid. */
5577 write(lockfd, (char *)&pid, sizeof(pid) );
5578 close(lockfd); /* Close and */
5579 chmod(lock2, 0444); /* set permissions. */
5580 } else { /* Not OK, but don't fail. */
5581 lock2[0] = '\0'; /* Just remember it's not there. */
5584 break; /* and we're done. */
5588 unlink(tmpnam); /* Unlink (remove) the temp file. */
5589 priv_off(); /* Turn off privs */
5590 i = haslock ? 0 : -1; /* Our return value */
5591 debug(F101,"TTLOCK returns","",i);
5594 #endif /* USETTYLOCK */
5595 #endif /* !NOUUCP */
5598 /* T T U N L O C K */
5601 ttunlck() { /* Remove UUCP lockfile(s). */
5605 debug(F111,"ttunlck",flfnam,haslock);
5609 if (haslock && *flfnam) {
5611 priv_on(); /* Turn on privs */
5613 x = uu_unlock(lockname);
5614 #else /* USE_UU_LOCK */
5615 x = ttyunlock(lockname); /* Try to unlock */
5616 #endif /* USE_UU_LOCK */
5617 priv_off(); /* Turn off privs */
5618 if (x < 0 && !quiet)
5619 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5621 *flfnam = '\0'; /* Erase the name. */
5626 #else /* No ttylock()... */
5628 if (haslock && *flfnam) {
5629 /* Don't remove lockfile if we didn't make it ourselves */
5630 if ((x = ttrpid(flfnam)) != (int)getpid()) {
5631 debug(F111,"ttunlck lockfile seized",flfnam,x);
5632 printf("Warning - Lockfile %s seized by pid %d\n",
5638 priv_on(); /* Turn privileges on. */
5640 x = unlink(flfnam); /* Remove the lockfile. */
5641 debug(F111,"ttunlck unlink",flfnam,x);
5643 if (errno && !quiet)
5645 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5648 *flfnam = '\0'; /* Erase the name. */
5652 x = unlink(lkflfn); /* Remove link to lockfile */
5653 debug(F111,"ttunlck AIX link unlink",lkflfn,x);
5655 if (errno && !quiet)
5657 printf("Warning - Can't remove link to lockfile: %s\n", lkflfn);
5661 if (lock2[0]) { /* If there is a second lockfile, */
5663 x = unlink(lock2); /* remove it too. */
5664 debug(F111,"ttunlck lock2 unlink",lock2,x);
5666 if (errno && !quiet)
5668 printf("Warning - Can't remove secondary lockfile: %s\n",
5672 lock2[0] = '\0'; /* Forget its name. */
5678 (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
5680 #endif /* COMMENT */
5682 priv_off(); /* Turn privileges off. */
5684 #endif /* USETTYLOCK */
5685 #endif /* !NOUUCP */
5690 4.3BSD-style UUCP line direction control.
5691 (Stan Barber, Rice U, 1980-something...)
5696 acucntrl(flag,ttname) char *flag, *ttname; {
5697 char x[DEVNAMLEN+32], *device, *devname;
5699 if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
5700 return; /* just return. */
5701 device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
5702 if (strncmp(device,"LCK..",4) == 0) device += 5;
5703 ckmakmsg(x,DEVNAMLEN+32,"/usr/lib/uucp/acucntrl ",flag," ",device);
5704 debug(F110,"called ",x,0);
5707 #endif /* ACUCNTRL */
5711 T T H F L O W -- Set or Reset hardware flow control.
5713 This is an attempt to collect all hardware-flow-control related code
5714 into a single module. Thanks to Rick Sladkey and John Kohl for lots of
5715 help here. Overview:
5717 Hardware flow control is not supported in many UNIX implementions. Even
5718 when it is supported, there is no (ha ha) "standard" for the programming
5719 interface. In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
5720 SunOS, AIX, etc, have totally different methods. (And, not strictly
5721 relevant here, the programming interface often brings one only to a no-op
5722 in the device driver!)
5724 Among all these, we have two major types of APIs: those in which hardware
5725 flow control is determined by bits in the same termio/termios/sgtty mode
5726 word(s) that are used for controlling such items as CBREAK vs RAW mode, and
5727 which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
5728 for changing terminal modes. And those that use entirely different
5731 In the first category, it is important that any change in the mode bits be
5732 reflected in the relevant termio(s)/sgtty structure, so that subsequent
5733 changes to that structure do not wipe out the effects of this routine. That
5734 is why a pointer, attrs, to the appropriate structure is passed as a
5735 parameter to this routine.
5737 The second category should give us no worries, since any changes to hardware
5738 flow control accomplished by this routine should not affect the termio(s)/
5739 sgtty structures, and therefore will not be undone by later changes to them.
5741 The second argument, status, means to turn on hardware flow control if
5742 nonzero, and to turn it off if zero.
5744 Returns: 0 on apparent success, -1 on probable failure.
5748 The following business is for BSDI, where it was discovered that two
5749 separate bits, CCTS_OFLOW and CRTS_IFLOW, are used in hardware flow control,
5750 but CTRSCTS is defined (in <termios.h>) to be just CCTS_OFLOW rather both
5751 bits, so hwfc only works in one direction if you use CRTSCTS to control it.
5752 Other 4.4BSD-based Unixes such as FreeBSD 4.1, which use these two bits,
5753 define CRTSCTS correctly.
5760 #define CRTSCTS (CRTS_IFLOW|CCTS_OFLOW)
5761 #endif /* CRTS_IFLOW */
5762 #endif /* CCTS_OFLOW */
5763 #endif /* CRTSCTS */
5764 #endif /* FIXCRTSCTS */
5767 tthflow(flow, status, attrs)
5768 int flow, /* Type of flow control (ckcdeb.h) */
5769 status; /* Nonzero = turn it on */
5770 /* Zero = turn it off */
5771 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
5772 struct termios *attrs;
5773 #else /* System V */
5777 /* AT&T UNIX 3.51m can set but not test for hardware flow control */
5778 #define RTSFLOW CTSCD
5779 #define CTSFLOW CTSCD
5780 #endif /* ATT7300 */
5781 #endif /* UNIX351M */
5782 struct termio *attrs;
5783 #else /* BSD, V7, etc */
5784 struct sgttyb *attrs; /* sgtty info... */
5786 #endif /* BSD44ORPOSIX */
5789 int x = 0; /* tthflow() return code */
5792 return p9tthflow(flow, status);
5795 #ifndef OXOS /* NOT Olivetti X/OS... */
5797 For SunOS 4.0 and later in the BSD environment ...
5799 The declarations are copied and interpreted from the System V header files,
5800 so we don't actually have to pull in all the System V junk when building
5801 C-Kermit for SunOS in the BSD environment, which would be dangerous because
5802 having those symbols defined would cause us to take the wrong paths through
5803 the code. The code in this section is used in both the BSD and Sys V SunOS
5808 In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
5809 because GNU CC uses different formats for the _IOxxx macros than regular CC;
5810 the POSIX forms work for both. But the POSIX calls are not available in
5813 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5814 #define TCSANOW 0 /* Do it now */
5817 unsigned long c_iflag; /* Input modes */
5818 unsigned long c_oflag; /* Output modes */
5819 unsigned long c_cflag; /* Control modes */
5820 unsigned long c_lflag; /* Line discipline modes */
5824 struct termios temp;
5826 _PROTOTYP( int tcgetattr, (int, struct termios *) );
5827 _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
5829 When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
5830 asserted. So we don't set CRTSCTS unless CD is up. This should be OK,
5831 since we don't need RTS/CTS during dialing, and after dialing is complete,
5832 we should have CD. If not, we still communicate, but without RTS/CTS.
5834 int mflags; /* Modem signal flags */
5837 if (ttpipe) return(0);
5840 if (ttpty) return(0);
5843 debug(F101,"tthflow SUNOS41 entry status","",status);
5844 if (!status) { /* Turn hard flow off */
5845 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5846 (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5847 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5848 x = tcsetattr(ttyfd,TCSANOW,&temp);
5850 } else { /* Turn hard flow on */
5851 if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
5852 (mflags & TIOCM_CAR)) { /* Check for CD */
5853 debug(F100,"tthflow SunOS has CD","",0);
5854 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5855 !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5856 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5857 x = tcsetattr(ttyfd,TCSANOW,&temp);
5861 debug(F100,"tthflow SunOS no CD","",0);
5866 struct termios temp;
5868 if (ttpipe) return(0);
5871 if (ttpty) return(0);
5873 debug(F101,"tthflow QNX entry status","",status);
5874 if (tcgetattr(ttyfd, &temp) > -1) { /* Get device attributes */
5875 if (!status) { /* Turn hard flow off */
5876 if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
5877 temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
5878 attrs->c_cflag &= ~(IHFLOW|OHFLOW);
5879 x = tcsetattr(ttyfd,TCSANOW,&temp);
5881 } else { /* Turn hard flow on */
5882 if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
5883 temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
5884 temp.c_iflag &= ~(IXON|IXOFF); /* Bye to IXON/IXOFF */
5885 ttraw.c_lflag |= IEXTEN; /* Must be on */
5886 x = tcsetattr(ttyfd,TCSANOW,&temp);
5887 attrs->c_cflag |= (IHFLOW|OHFLOW);
5888 attrs->c_iflag &= ~(IXON|IXOFF);
5893 debug(F100, "tthflow QNX getattr fails", "", 0);
5896 #ifdef POSIX_CRTSCTS
5898 POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
5899 Note: Do not assume CRTSCTS is a one-bit field!
5901 struct termios temp;
5903 if (ttpipe) return(0);
5906 if (ttpty) return(0);
5908 debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
5910 x = tcgetattr(ttyfd, &temp);
5911 debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
5916 if (!status) { /* Turn hard flow off */
5919 /* This can fail because of sign extension */
5920 /* e.g. in Linux where it's Bit 31 */
5921 (temp.c_cflag & CRTSCTS) == CRTSCTS
5923 (temp.c_cflag & CRTSCTS) != 0
5924 #endif /* COMMENT */
5926 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5927 attrs->c_cflag &= ~CRTSCTS;
5928 x = tcsetattr(ttyfd,TCSANOW,&temp);
5929 debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
5931 } else { /* John Dunlap 2010-01-26 */
5933 "tthflow before forcing off attrs CRTSCTS",
5935 attrs->c_cflag&CRTSCTS
5937 attrs->c_cflag &= ~CRTSCTS; /* force it off if !status */
5939 "tthflow after forcing off attrs CRTSCTS",
5941 attrs->c_cflag&CRTSCTS
5944 } else { /* Turn hard flow on */
5947 /* This can fail because of sign extension */
5948 (temp.c_cflag & CRTSCTS) != CRTSCTS
5950 (temp.c_cflag & CRTSCTS) == 0
5951 #endif /* COMMENT */
5953 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5954 temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
5955 x = tcsetattr(ttyfd,TCSANOW,&temp);
5956 debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
5958 attrs->c_cflag |= CRTSCTS;
5959 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
5966 SunOS 4.0 (and maybe earlier?). This code is dangerous because it
5967 prevents compilation with GNU gcc, which uses different formats for the
5968 _IORxxx macros than regular cc. SunOS 4.1 and later can use the POSIX
5969 routines above, which work for both cc and gcc.
5971 #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
5972 #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
5973 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5976 unsigned long c_iflag; /* Input modes */
5977 unsigned long c_oflag; /* Output modes */
5978 unsigned long c_cflag; /* Control modes */
5979 unsigned long c_lflag; /* Line discipline modes */
5983 struct termios temp;
5985 if (ttpipe) return(0);
5988 if (ttpty) return(0);
5990 debug(F101,"tthflow entry status","",status);
5991 if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
5992 if (status) { /* Turn hard flow on */
5993 temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */
5994 x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
5995 attrs->c_cflag |= CRTSCTS; /* Add to global info. */
5996 } else { /* Turn hard flow off */
5997 temp.c_cflag &= ~CRTSCTS;
5998 x = ioctl(ttyfd,TCSETS,&temp);
5999 attrs->c_cflag &= ~CRTSCTS;
6002 #else /* Not SunOS 4.0 or later */
6003 #ifdef AIXRS /* IBM AIX RS/6000 */
6004 #ifndef AIX41 /* But only pre-4.x == SVR4 */
6006 if (ttpipe) return(0);
6009 if (ttpty) return(0);
6012 if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
6013 debug(F100,"hardflow TXADDCD (rts) error", "", 0);
6015 if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
6016 debug(F100,"hardflow TXDELCD (rts) error", "", 0);
6019 #else /* Not AIX RS/6000 */
6021 #ifdef ATTSV /* System V... */
6023 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
6026 #ifdef M_UNIX /* SCO UNIX 3.2v4.x or earlier */
6029 #endif /* CK_SCOV5 */
6031 #ifdef SCO_FORCE_RTSXOFF
6032 #ifdef CK_SCOUNIX /* But not SCO OpenServer 5.0.4 */
6033 #ifdef SCO_OSR504 /* or later... */
6035 #endif /* SCO_OSR504 */
6036 #endif /* CK_SCOUNIX */
6037 #endif /* SCO_FORCE_RTSXOFF */
6041 struct termios temp;
6043 if (ttpipe) return(0);
6046 if (ttpty) return(0);
6048 debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
6050 x = tcgetattr(ttyfd, &temp);
6051 debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
6055 if (ttpipe) return(0);
6058 if (ttpty) return(0);
6060 debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
6061 x = ioctl(ttyfd, TCGETA, &temp);
6062 debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
6065 This is not really POSIX, since POSIX does not deal with hardware flow
6066 control, but we are using the POSIX APIs. In fact, RTSFLOW and CTSFLOW
6067 are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif. So
6068 let's try forcing their definitions here.
6071 #define CTSFLOW 0020000
6072 debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
6074 debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
6075 #endif /* CTSFLOW */
6077 #define RTSFLOW 0040000
6078 debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
6080 debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
6081 #endif /* RTSFLOW */
6083 #define ORTSFL 0100000
6084 debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
6086 debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
6090 if (status) { /* Turn it ON */
6091 temp.c_cflag |= RTSFLOW|CTSFLOW;
6092 attrs->c_cflag |= RTSFLOW|CTSFLOW;
6094 temp.c_cflag &= ~ORTSFL;
6095 attrs->c_cflag &= ~ORTSFL;
6097 temp.c_iflag &= ~(IXON|IXOFF|IXANY);
6098 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
6099 } else { /* Turn it OFF */
6101 temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6102 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
6104 temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
6105 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
6109 x = tcsetattr(ttyfd, TCSADRAIN, &temp);
6111 x = ioctl(ttyfd, TCSETA, &temp);
6113 debug(F101,"tthflow SCO set modes","",x);
6115 #else /* Not SCO UNIX */
6117 if (ttpipe) return(0);
6120 if (ttpty) return(0);
6122 if (!status) { /* Turn it OFF */
6124 debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
6125 rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
6127 x = ioctl(ttyfd,TCSETX,&rctsx);
6128 debug(F101,"tthflow ATTSV TCSETX OFF","",x);
6131 debug(F100,"tthflow TCSETX not defined","",0);
6134 debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
6135 #endif /* RTSXOFF */
6137 debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
6138 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6139 x = ioctl(ttyfd,TCSETX,&rctsx);
6140 debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
6142 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6143 #endif /* DTRXOFF */
6144 } else { /* Turn it ON. */
6145 if (flow == FLO_RTSC) { /* RTS/CTS Flow control... */
6146 debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
6148 /* This is the preferred way, according to SVID3 */
6150 x = ioctl(ttyfd,TCGETX,&rctsx);
6151 debug(F101,"tthflow TCGETX","",x);
6153 rctsx.x_hflag |= RTSXOFF | CTSXON;
6154 x = ioctl(ttyfd,TCSETX,&rctsx);
6155 debug(F100,"tthflow ATTSV ioctl","",x);
6158 debug(F100,"tthflow TCGETX not defined","",0);
6162 debug(F100,"tthflow RTSXOFF not defined","",0);
6164 #endif /* RTSXOFF */
6165 } else if (flow == FLO_DTRC) { /* DTR/CD Flow control... */
6166 debug(F100,"tthflow ATTSV DTR/CD ON","",0);
6168 /* This is straight out of SVID R4 */
6169 if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
6170 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6171 x = ioctl(ttyfd,TCSETX,&rctsx);
6174 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6176 #endif /* DTRXOFF */
6179 #endif /* CK_SCOUNIX */
6181 #else /* not System V... */
6187 if (ttpipe) return(0);
6190 if (ttpty) return(0);
6192 x = LDODTR | LDOCTS; /* Found only on UTEK? */
6193 if (flow == FLO_DTRT && status) { /* Use hardware flow control */
6195 x = ioctl(ttyfd,TIOCLBIS,&x);
6197 debug(F100,"hardflow TIOCLBIS error","",0);
6200 debug(F100,"hardflow TIOCLBIS ok","",0);
6205 x = ioctl(ttyfd,TIOCLBIC,&x);
6207 debug(F100,"hardflow TIOCLBIC error","",0);
6210 debug(F100,"hardflow TIOCLBIC ok","",0);
6216 #endif /* CK_DTRCTS */
6221 #endif /* POSIX_CRTSCTS */
6222 #endif /* SUNOS41 */
6226 struct termios temp; /* Olivetti X/OS ... */
6229 if (ttpipe) return(0);
6232 if (ttpty) return(0);
6234 x = ioctl(ttyfd,TCGETS,&temp);
6236 temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
6239 case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
6241 case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
6245 x = ioctl(ttyfd,TCSETS,&temp);
6253 /* T T P K T -- Condition the communication line for packets */
6254 /* or for modem dialing */
6257 If called with speed > -1, also set the speed.
6258 Returns 0 on success, -1 on failure.
6260 NOTE: the "xflow" parameter is supposed to be the currently selected
6261 type of flow control, but for historical reasons, this parameter is also
6262 used to indicate that we are dialing. Therefore, when the true flow
6263 control setting is needed, we access the external variable "flow", rather
6264 than trusting our "xflow" argument.
6268 ttpkt(long speed, int xflow, int parity)
6270 ttpkt(speed,xflow,parity) long speed; int xflow, parity;
6271 #endif /* CK_ANSIC */
6276 #endif /* NOLOCAL */
6278 extern int flow; /* REAL flow-control setting */
6280 if (ttyfd < 0) return(-1); /* Not open. */
6282 debug(F101,"ttpkt parity","",parity);
6283 debug(F101,"ttpkt xflow","",xflow);
6284 debug(F101,"ttpkt speed","",(int) speed);
6286 ttprty = parity; /* Let other tt functions see these. */
6287 ttspeed = speed; /* Make global copy for this module */
6288 ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
6290 needpchk = ttprty ? 0 : 1; /* Parity check needed? */
6293 #endif /* PARSENSE */
6295 debug(F101,"ttpkt ttpmsk","",ttpmsk);
6296 debug(F101,"ttpkt netconn","",netconn);
6298 #ifdef NETCONN /* No mode-changing for telnet */
6302 if (ttnet == NET_TCPB) { /* But turn off Nagle */
6303 extern int tcp_nodelay;
6304 nodelay_sav = tcp_nodelay;
6307 #endif /* TCP_NODELAY */
6309 if (istncomport()) {
6311 if (tvtflg == 0 && speed == ttspeed && flow == ttflow
6312 /* && ttcarr == curcarr */ ) {
6313 debug(F100,"ttpkt modes already set, skipping...","",0);
6314 return(0); /* Already been called. */
6316 if (flow != ttflow) {
6317 if ((rc = tnsetflow(flow)) < 0)
6321 if (speed != ttspeed) {
6323 speed = tnc_get_baud();
6324 else if ((rc = tnc_set_baud(speed)) < 0)
6328 tnc_set_datasize(8);
6329 tnc_set_stopsize(stopbits);
6334 case 'e': /* Even */
6335 debug(F100,"ttres 8 bits + even parity","",0);
6339 debug(F100,"ttres 8 bits + odd parity","",0);
6342 case 'm': /* Mark */
6343 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
6346 case 's': /* Space */
6347 debug(F100,"ttres 8 bits + invalid parity: space","",0);
6352 #endif /* HWPARITY */
6354 tnc_set_parity(1); /* None */
6359 #endif /* TN_COMPORT */
6360 #endif /* TCPSOCKET */
6364 #endif /* NETCONN */
6366 if (ttpipe) return(0);
6369 if (ttpty) return(0);
6373 if (ttfdflg && !isatty(ttyfd)) return(0);
6378 #endif /* COHERENT */
6380 #ifndef SVORPOSIX /* Berkeley, V7, etc. */
6383 For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
6384 after having previously set it to NONE without closing and reopening the
6385 device. Unless there's something I overlooked below...
6387 if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
6388 debug(F101,"ttpkt executing horrible flow kludge","",0);
6389 ttclos(0); /* Close it */
6391 ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
6394 #endif /* SVORPOSIX */
6396 #ifdef COHERENT /* This must be vestigial since we */
6397 #undef SVORPOSIX /* reverse it a few lines below... */
6398 #endif /* COHERENT */
6400 if (xflow != FLO_DIAL && xflow != FLO_DIAX)
6401 ttflow = xflow; /* Now make this available too. */
6405 s2 = (int) (speed / 10L); /* Convert bps to cps */
6406 debug(F101,"ttpkt calling ttsspd","",s2);
6407 s = ttsspd(s2); /* Check and set the speed */
6408 debug(F101,"ttpkt ttsspd result","",s);
6409 carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
6410 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
6411 tvtflg = 0; /* So ttvt() will work next time */
6413 #endif /* NOLOCAL */
6417 #endif /* COHERENT */
6419 #ifndef SVORPOSIX /* BSD section */
6420 if (flow == FLO_RTSC || /* Hardware flow control */
6423 tthflow(flow, 1, &ttraw);
6424 debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
6425 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6426 ttraw.sg_flags |= RAW; /* Enter raw mode */
6427 } else if (flow == FLO_NONE) { /* No flow control */
6428 debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
6429 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6430 tthflow(flow, 0, &ttraw); /* Turn off any hardware f/c too */
6431 ttraw.sg_flags |= RAW; /* Enter raw mode */
6432 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
6433 debug(F100,"ttpkt keeping original TANDEM","",0);
6434 ttraw.sg_flags &= ~TANDEM;
6435 ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
6436 /* NOTE: We should also handle hardware flow control here! */
6439 /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
6441 if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
6442 debug(F100,"ttpkt turning on TANDEM","",0);
6443 ttraw.sg_flags |= TANDEM; /* So ask for it. */
6445 #ifdef LPASS8 /* Can pass 8-bit data through? */
6446 /* If the LPASS8 local mode is available, then flow control can always */
6447 /* be used, even if parity is none and we are transferring 8-bit data. */
6448 /* But we only need to do all this if Xon/Xoff is requested. */
6449 /* BUT... this tends not to work through IP or LAT connections, terminal */
6450 /* servers, telnet, rlogin, etc, so it is currently disabled. */
6451 x = LPASS8; /* If LPASS8 defined, then */
6452 debug(F100,"ttpkt executing LPASS8 code","",0);
6453 if (lmodef) { /* TIOCLBIS must be too. */
6454 x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
6456 debug(F100,"ttpkt TIOCLBIS error","",0);
6459 debug(F100,"ttpkt TIOCLBIS ok","",0);
6463 But if we use LPASS8 mode, we must explicitly turn off
6464 terminal interrupts of all kinds.
6466 #ifdef TIOCGETC /* Not rawmode, */
6467 if (tcharf && (xlocal == 0)) { /* must turn off */
6468 tchnoi.t_intrc = -1; /* interrupt character */
6469 tchnoi.t_quitc = -1; /* and quit character. */
6470 tchnoi.t_startc = 17; /* Make sure xon */
6471 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6473 tchnoi.t_eofc = -1; /* eof character. */
6474 tchnoi.t_brkc = -1; /* brk character. */
6476 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6477 debug(F100,"ttpkt TIOCSETC failed","",0);
6480 debug(F100,"ttpkt TIOCSETC ok","",0);
6483 /* only for paranoid debugging */
6487 ioctl(0,TIOCGETC,&foo);
6489 "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
6490 foo.t_intrc, foo.t_quitc, foo.t_startc,
6491 foo.t_stopc, foo.t_eofc, foo.t_brkc);
6492 debug(F110,"ttpkt chars",tchbuf,0);
6494 #endif /* COMMENT */
6496 ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
6497 #endif /* TIOCGETC */
6499 /* Prevent suspend during packet mode */
6500 #ifdef TIOCGLTC /* Not rawmode, */
6501 if (ltcharf && (xlocal == 0)) { /* must turn off */
6502 ltchnoi.t_suspc = -1; /* suspend character */
6503 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6504 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6505 debug(F100,"ttpkt TIOCSLTC failed","",0);
6508 debug(F100,"ttpkt TIOCSLTC ok","",0);
6511 #endif /* TIOCGLTC */
6513 #else /* LPASS8 not defined */
6515 /* Previously, BSD-based implementations always */
6516 /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */
6517 /* This allows the flow control requested above to actually work, but only */
6518 /* if the user asks for parity (which also means they get 8th-bit quoting). */
6520 if (parity) { /* If parity, */
6521 ttraw.sg_flags &= ~RAW; /* use cooked mode */
6525 #endif /* COMMENT */
6526 ttraw.sg_flags |= CBREAK;
6527 debug(F101,"ttpkt cooked, cbreak, parity","",parity);
6528 #ifdef TIOCGETC /* Not rawmode, */
6529 if (tcharf && (xlocal == 0)) { /* must turn off */
6530 tchnoi.t_intrc = -1; /* interrupt character */
6531 tchnoi.t_quitc = -1; /* and quit character. */
6532 tchnoi.t_startc = 17; /* Make sure xon */
6533 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6535 tchnoi.t_eofc = -1; /* eof character. */
6536 tchnoi.t_brkc = -1; /* brk character. */
6538 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6539 debug(F100,"ttpkt TIOCSETC failed","",0);
6542 debug(F100,"ttpkt TIOCSETC ok","",0);
6545 #endif /* TIOCGETC */
6546 #ifdef TIOCGLTC /* Not rawmode, */
6547 /* Prevent suspend during packet mode */
6548 if (ltcharf && (xlocal == 0)) { /* must turn off */
6549 ltchnoi.t_suspc = -1; /* suspend character */
6550 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6551 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6552 debug(F100,"ttpkt TIOCSLTC failed","",0);
6555 debug(F100,"ttpkt TIOCSLTC ok","",0);
6558 #endif /* TIOCGLTC */
6559 } else { /* If no parity, */
6560 ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
6561 debug(F101,"ttpkt setting rawmode, parity","",parity);
6564 } /* End of Xon/Xoff section */
6566 /* Don't echo, don't map CR to CRLF on output, don't fool with case */
6568 ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
6570 ttraw.sg_flags &= ~(ECHO|CRMOD);
6574 ttraw.sg_flags &= ~ANYP; /* Must set this on old Towers */
6578 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
6582 if (stty(ttyfd,&ttraw) < 0) { /* Set the new modes. */
6583 debug(F101,"ttpkt stty failed","",errno);
6586 #endif /* BELLV10 */
6587 debug(F100,"ttpkt stty ok","",0);
6590 x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
6591 if (x != -1) { /* Make sure we know original modes. */
6594 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
6595 perror("ttpkt can't set ASCII mode");
6596 debug(F101,"ttpkt error setting ASCII mode","",x);
6600 debug(F100,"ttpkt set ASCII mode ok","",0);
6601 #endif /* sony_news */
6603 if (xlocal == 0) { /* Turn this off so we can read */
6604 signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
6607 tvtflg = 0; /* So ttvt() will work next time */
6608 debug(F100,"ttpkt success","",0);
6611 #endif /* Not ATTSV or POSIX */
6613 /* AT&T UNIX and POSIX */
6617 #endif /* COHERENT */
6620 if (flow == FLO_XONX) { /* Xon/Xoff */
6621 ttraw.c_iflag |= (IXON|IXOFF);
6622 tthflow(flow, 0, &ttraw);
6623 } else if (flow == FLO_NONE) { /* None */
6624 /* NOTE: We should also turn off hardware flow control here! */
6625 ttraw.c_iflag &= ~(IXON|IXOFF);
6626 tthflow(flow, 0, &ttraw);
6627 } else if (flow == FLO_KEEP) { /* Keep */
6628 ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
6629 ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
6630 /* NOTE: We should also handle hardware flow control here! */
6631 #ifdef POSIX_CRTSCTS
6632 /* In Linux case, we do this, which is unlikely to be portable */
6633 ttraw.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
6634 ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
6635 #endif /* POSIX_CRTSCTS */
6636 } else if (flow == FLO_RTSC || /* Hardware */
6639 ttraw.c_iflag &= ~(IXON|IXOFF); /* (190) */
6640 tthflow(flow, 1, &ttraw);
6642 ttraw.c_lflag &= ~(ICANON|ECHO);
6643 ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
6647 if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
6650 ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */
6651 #endif /* COHERENT */
6653 ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
6655 ttraw.c_lflag |= NOFLSH; /* Don't flush */
6656 ttraw.c_iflag |= IGNPAR; /* Ignore parity errors */
6659 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
6661 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
6664 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
6666 ttraw.c_oflag &= ~OPOST;
6667 ttraw.c_cflag &= ~(CSIZE);
6668 ttraw.c_cflag |= (CS8|CREAD|HUPCL);
6672 if (stopbits == 2) {
6673 ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
6674 debug(F100,"ttpkt 2 stopbits","",0);
6675 } else if (stopbits == 1) {
6676 ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
6677 debug(F100,"ttpkt 1 stopbit","",0);
6683 if (hwparity && xlocal) { /* Hardware parity */
6684 ttraw.c_cflag |= PARENB; /* Enable parity */
6686 /* Uncomment this only if needed -- I don't think it is */
6687 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
6688 ttraw.c_cflag |= CS8; /* And set it to 8 */
6689 #endif /* COMMENT */
6691 ttraw.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
6692 debug(F100,"ttpkt IGNPAR","",0); /* that have parity errors */
6695 case 'e': /* Even */
6696 ttraw.c_cflag &= ~(PARODD);
6697 debug(F100,"ttpkt 8 bits + even parity","",0);
6700 ttraw.c_cflag |= PARODD;
6701 debug(F100,"ttpkt 8 bits + odd parity","",0);
6703 case 'm': /* Mark */
6704 case 's': /* Space */
6705 /* PAREXT is mentioned in SVID but the details are not given. */
6706 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
6707 debug(F100,"ttpkt 8 bits + invalid parity","",0);
6710 } else { /* We handle parity ourselves */
6711 #endif /* HWPARITY */
6712 ttraw.c_cflag &= ~(PARENB); /* Don't enable parity */
6715 #endif /* HWPARITY */
6718 ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
6721 #ifndef VEOF /* for DGUX this is VEOF, not VMIN */
6722 ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */
6726 ttraw.c_cc[VMIN] = 1;
6732 #ifndef VEOL /* for DGUX this is VEOL, not VTIME */
6733 ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */
6737 ttraw.c_cc[VTIME] = 0;
6745 #ifdef VINTR /* Turn off interrupt character */
6746 if (xlocal == 0) /* so ^C^C can break us out of */
6747 ttraw.c_cc[VINTR] = 0; /* packet mode. */
6751 if (p9ttyparity('n') < 0)
6757 ttraw.c_cc[VMIN] = 0; /* DR7 can only poll. */
6758 #endif /* BEOSORBEBOX */
6763 debug(F100,"ttpkt TESTING234 rawmode","",0);
6766 ttraw.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
6767 ttraw.c_iflag &= ~(INPCK|IGNPAR|IXON|IXOFF);
6768 ttraw.c_iflag |= IGNBRK;
6770 ttraw.c_iflag &= ~IMAXBEL;
6771 #endif /* IMAXBEL */
6773 ttraw.c_iflag &= ~IXANY;
6776 ttraw.c_iflag &= ~IUCLC;
6780 ttraw.c_oflag &= ~OPOST;
6782 ttraw.c_oflag &= ~OXTABS;
6785 ttraw.c_oflag &= ~ONOCR;
6788 ttraw.c_oflag &= ~ONLRET;
6791 ttraw.c_oflag &= ~ONLCR;
6795 ttraw.c_lflag &= ~ECHO;
6797 ttraw.c_lflag &= ~ECHOE;
6800 ttraw.c_lflag &= ~ECHONL;
6803 ttraw.c_lflag &= ~ECHOPRT;
6804 #endif /* ECHOPRT */
6806 ttraw.c_lflag &= ~ECHOKE;
6809 ttraw.c_lflag &= ~ECHOCTL;
6810 #endif /* ECHOCTL */
6812 ttraw.c_lflag &= ~ALTWERASE;
6813 #endif /* ALTWERASE */
6815 ttraw.c_lflag &= ~EXTPROC;
6816 #endif /* EXTPROC */
6817 ttraw.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
6819 ttraw.c_lflag |= NOKERNINFO;
6820 #endif /* NOKERNINFO */
6821 /* ttraw.c_lflag |= NOFLSH; */
6822 ttraw.c_lflag &= ~NOFLSH;
6825 ttraw.c_cflag &= ~(CSIZE|PARENB|PARODD);
6826 ttraw.c_cflag |= CS8|CREAD;
6828 ttraw.c_cc[VMIN] = 1; /* Supposedly needed for AIX */
6832 #endif /* TESTING234 */
6834 debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
6835 x = tcsetattr(ttyfd,TCSADRAIN,&ttraw);
6836 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr","",x);
6838 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr errno","",errno);
6841 #else /* BSD44ORPOSIX */
6842 x = ioctl(ttyfd,TCSETAW,&ttraw);
6843 debug(F101,"ttpkt ATTSV ioctl TCSETAW","",x);
6844 if (x < 0) { /* set new modes . */
6845 debug(F101,"ttpkt ATTSV ioctl TCSETAW errno","",errno);
6848 #endif /* BSD44ORPOSIX */
6851 debug(F100,"ttpkt ok","",0);
6857 #endif /* COHERENT */
6861 /* T T S E T F L O W -- Set flow control immediately. */
6865 #endif /* COHERENT */
6868 ttsetflow(flow) int flow; {
6869 if (ttyfd < 0) /* A channel must be open */
6872 debug(F101,"ttsetflow flow","",flow);
6875 if (netconn && istncomport()) {
6876 debug(F101,"ttsetflow net modem","",ttmdm);
6877 return(tnsetflow(flow));
6879 #endif /* TN_COMPORT */
6881 if (ttpipe) return(0);
6884 if (ttpty) return(0);
6888 /* This seems to hurt... */
6889 if (flow == FLO_KEEP)
6891 #endif /* COMMENT */
6893 if (flow == FLO_RTSC || /* Hardware flow control... */
6896 tthflow(flow, 1, &ttraw);
6898 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6900 ttraw.c_iflag &= ~(IXON|IXOFF);
6901 #endif /* SVORPOSIX */
6903 } else if (flow == FLO_XONX) { /* Xon/Xoff... */
6906 ttraw.sg_flags |= TANDEM;
6908 ttraw.c_iflag |= (IXON|IXOFF);
6909 #endif /* SVORPOSIX */
6910 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off hardware flow control */
6912 } else if (flow == FLO_NONE) { /* No flow control */
6915 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6917 ttraw.c_iflag &= ~(IXON|IXOFF);
6918 #endif /* SVORPOSIX */
6919 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off any hardware f/c too */
6922 /* Set the new modes... */
6924 #ifndef SVORPOSIX /* BSD and friends */
6926 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
6930 if (stty(ttyfd,&ttraw) < 0)
6933 #endif /* BELLV10 */
6935 #ifdef BSD44ORPOSIX /* POSIX */
6936 if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
6938 #else /* System V */
6939 if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
6941 #endif /* BSD44ORPOSIX */
6942 #endif /* SVORPOSIX */
6947 #endif /* COHERENT */
6949 /* T T V T -- Condition communication device for use as virtual terminal. */
6953 ttvt(long speed, int flow)
6955 ttvt(speed,flow) long speed; int flow;
6956 #endif /* CK_ANSIC */
6960 debug(F101,"ttvt ttyfd","",ttyfd);
6961 debug(F101,"ttvt tvtflg","",tvtflg);
6962 debug(F111,"ttvt speed",ckitoa(ttspeed),speed);
6963 debug(F111,"ttvt flow",ckitoa(ttflow),flow);
6964 debug(F111,"ttvt curcarr",ckitoa(ttcarr),curcarr);
6966 /* Note: NetBSD and maybe other BSD44s have cfmakeraw() */
6967 /* Maybe it would be simpler to use it... */
6971 return(conbin((char)escchr));
6973 if (ttyfd < 0) { /* Not open. */
6976 else /* But maybe something buffered. */
6980 if (ttpipe) return(0);
6983 if (ttpty) return(0);
6990 extern int tcp_nodelay;
6991 if (ttnet == NET_TCPB) {
6992 if (nodelay_sav > -1) {
6993 no_delay(ttyfd,nodelay_sav);
6998 #endif /* TCP_NODELAY */
7000 if (istncomport()) {
7002 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7003 /* && ttcarr == curcarr */ ) {
7004 debug(F100,"ttvt modes already set, skipping...","",0);
7005 return(0); /* Already been called. */
7007 if (flow != ttflow) {
7008 if ((rc = tnsetflow(flow)) < 0)
7012 if (speed != ttspeed) {
7014 speed = tnc_get_baud();
7015 else if ((rc = tnc_set_baud(speed)) < 0)
7019 tnc_set_datasize(8);
7020 tnc_set_stopsize(stopbits);
7025 case 'e': /* Even */
7026 debug(F100,"ttres 8 bits + even parity","",0);
7030 debug(F100,"ttres 8 bits + odd parity","",0);
7033 case 'm': /* Mark */
7034 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
7037 case 's': /* Space */
7038 debug(F100,"ttres 8 bits + invalid parity: space","",0);
7043 #endif /* HWPARITY */
7045 tnc_set_parity(1); /* None */
7050 #endif /* TN_COMPORT */
7051 #endif /* TCPSOCKET */
7052 tvtflg = 1; /* Network connections... */
7053 debug(F100,"ttvt network connection, skipping...","",0);
7054 return(0); /* ... require no special setup */
7056 #endif /* NETCONN */
7058 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
7059 /* && ttcarr == curcarr */ )
7061 debug(F100,"ttvt modes already set, skipping...","",0);
7062 return(0); /* Already been called. */
7070 debug(F100,"ttvt using external fd, skipping...","",0);
7074 debug(F100,"ttvt setting modes...","",0);
7076 if (xlocal) { /* For external lines... */
7077 s2 = (int) (speed / 10L);
7078 s = ttsspd(s2); /* Check/set the speed */
7079 carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
7080 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
7086 #endif /* COHERENT */
7089 /* Berkeley, V7, etc */
7090 if (flow == FLO_RTSC || /* Hardware flow control */
7093 tthflow(flow, 1, &tttvt);
7094 debug(F100,"ttvt hard flow, TANDEM off","",0);
7095 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7096 } else if (flow == FLO_XONX) { /* Xon/Xoff flow control */
7097 debug(F100,"ttvt TANDEM on","",0);
7098 tttvt.sg_flags |= TANDEM; /* Ask for it. */
7099 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7100 } else if (flow == FLO_NONE) {
7101 debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
7102 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
7103 tthflow(flow, 0, &tttvt); /* Turn off any hardware f/c too */
7104 tttvt.sg_flags |= RAW; /* Enter raw mode */
7105 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
7106 debug(F100,"ttvt keeping original TANDEM","",0);
7107 tttvt.sg_flags &= ~TANDEM;
7108 tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
7109 /* NOTE: We should also handle hardware flow control here! */
7111 tttvt.sg_flags |= RAW; /* Raw mode in all cases */
7113 tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */
7115 tttvt.sg_flags &= ~ECHO; /* No echo */
7119 if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
7122 if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */
7124 #endif /* BELLV10 */
7126 #else /* It is ATTSV or POSIX */
7128 if (flow == FLO_XONX) { /* Software flow control */
7129 tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */
7130 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7131 debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
7132 } else if (flow == FLO_NONE) { /* NONE */
7133 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff */
7134 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
7135 debug(F100,"ttvt SVORPOSIX flow NONE","",0);
7136 } else if (flow == FLO_KEEP) {
7137 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
7138 tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
7139 #ifdef POSIX_CRTSCTS
7140 tttvt.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
7141 tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
7142 #endif /* POSIX_CRTSCTS */
7143 debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
7144 } else if (flow == FLO_RTSC || /* Hardware flow control */
7147 tttvt.c_iflag &= ~(IXON|IXOFF); /* (196) */
7148 tthflow(flow, 1, &tttvt);
7149 debug(F100,"ttvt SVORPOSIX flow HARD","",0);
7153 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7155 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
7156 #endif /* COHERENT */
7158 /* Needed for hwfc */
7159 if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
7160 tttvt.c_lflag |= IEXTEN;
7163 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
7164 tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
7167 tttvt.c_iflag |= (IGNBRK|IGNPAR);
7173 if (stopbits == 2) {
7174 tttvt.c_cflag |= CSTOPB; /* 2 stop bits */
7175 debug(F100,"ttvt 2 stopbits","",0);
7176 } else if (stopbits == 1) {
7177 tttvt.c_cflag &= ~(CSTOPB); /* 1 stop bit */
7178 debug(F100,"ttvt 1 stopbit","",0);
7186 if (hwparity && xlocal) { /* Hardware parity */
7188 /* Uncomment this only if needed -- I don't think it is */
7189 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
7190 ttraw.c_cflag |= CS8; /* And set it to 8 */
7191 #endif /* COMMENT */
7193 debug(F101,"ttvt hwparity IGNPAR","",IGNPAR);
7194 tttvt.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
7196 tttvt.c_cflag |= PARENB; /* Enable parity */
7199 case 'e': /* Even */
7200 tttvt.c_cflag &= ~(PARODD);
7201 debug(F100,"ttvt 8 bits + even parity","",0);
7204 tttvt.c_cflag |= PARODD;
7205 debug(F100,"ttvt 8 bits + odd parity","",0);
7207 case 'm': /* Mark */
7208 case 's': /* Space */
7209 /* PAREXT is mentioned in SVID but the details are not given. */
7210 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
7211 debug(F100,"ttvt 8 bits + invalid parity","",0);
7214 } else { /* We handle parity ourselves */
7215 #endif /* HWPARITY */
7216 tttvt.c_cflag &= ~(PARENB); /* Don't enable parity */
7219 #endif /* HWPARITY */
7223 /* Things not to do... */
7224 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
7226 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
7229 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
7231 tttvt.c_cflag &= ~(CSIZE); /* Zero out the char size field */
7232 tttvt.c_cflag |= (CS8|CREAD|HUPCL); /* Char size 8, enable receiver, hup */
7233 tttvt.c_oflag &= ~OPOST; /* Don't postprocess output */
7234 #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
7239 tttvt.c_cc[VMIN] = 1;
7245 #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */
7250 tttvt.c_cc[VTIME] = 0;
7258 if (p9ttyparity('n') < 0)
7264 tttvt.c_cc[VMIN] = 0; /* DR7 can only poll. */
7265 #endif /* BEOSORBEBOX */
7267 x = tcsetattr(ttyfd,TCSADRAIN,&tttvt);
7268 debug(F101,"ttvt BSD44ORPOSIX tcsetattr","",x);
7270 debug(F101,"ttvt BSD44ORPOSIX tcsetattr errno","",errno);
7274 x = ioctl(ttyfd,TCSETAW,&tttvt);
7275 debug(F101,"ttvt ATTSV ioctl TCSETAW","",x);
7276 if (x < 0) { /* set new modes . */
7277 debug(F101,"ttvt ATTSV ioctl TCSETAW errno","",errno);
7280 #endif /* BSD44ORPOSIX */
7284 ttspeed = speed; /* Done, remember how we were */
7285 ttflow = flow; /* called, so we can decide how to */
7286 tvtflg = 1; /* respond next time. */
7287 debug(F100,"ttvt ok","",0);
7292 #endif /* COHERENT */
7294 #endif /* NOLOCAL */
7299 /* Serial speed department . . . */
7302 SCO OSR5.0.x might or might not support high speeds. Sometimes they are not
7303 defined in the header files but they are supported (e.g. when building with
7304 UDK compiler rather than /bin/cc), sometimes vice versa. Even though 5.0.4
7305 was the first release that came with high serial speeds standard, releases
7306 back to 5.0.0 could use them if certain patches (or "supplements") were
7307 applied to the SIO driver. Plus a lot of SCO installations run third-party
7312 #define B38400 0000017
7315 #define B57600 0000021
7318 #define B76800 0000022
7321 #define B115200 0000023
7322 #endif /* B115200 */
7324 #define B230400 0000024
7325 #endif /* B230400 */
7327 #define B460800 0000025
7328 #endif /* B460800 */
7330 #define B921600 0000026
7331 #endif /* B921600 */
7332 #endif /* CK_SCOV5 */
7334 Plan 9's native speed setting interface lets you set anything you like,
7335 but will fail if the hardware doesn't like it, so we allow all the common
7373 #define B14400 14400
7376 #define B19200 19200
7379 #define B28800 28800
7382 #define B38400 38400
7385 #define B57600 57600
7388 #define B76800 76800
7391 #define B115200 115200
7392 #endif /* B115200 */
7394 #define B230400 230400
7395 #endif /* B230400 */
7397 #define B460800 460800
7398 #endif /* B460800 */
7400 #define B921600 921600
7401 #endif /* B921600 */
7404 /* T T S S P D -- Checks and sets transmission rate. */
7406 /* Call with speed in characters (not bits!) per second. */
7407 /* Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
7409 #ifdef USETCSETSPEED
7411 The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
7412 to be used as a speed to be set, rather than forcing a choice from a
7413 predefined list. It seems to be peculiar to UnixWare 7.
7415 These are the function codes to be passed to tc[gs]etspeed(),
7416 but for some reason they don't seem to be picked up from termios.h.
7420 #endif /* TCS_ALL */
7426 #endif /* TCS_OUT */
7427 #endif /* USETCSETSPEED */
7430 ttsspd(cps) int cps; {
7433 /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
7439 int ok = 1; /* Speed check result, assume ok */
7441 #ifdef OLINUXHISPEED
7442 unsigned int spd_flags = 0;
7443 struct serial_struct serinfo;
7444 #endif /* OLINUXHISPEED */
7446 debug(F101,"ttsspd cps","",cps);
7447 debug(F101,"ttsspd ttyfd","",ttyfd);
7448 debug(F101,"ttsspd xlocal","",xlocal);
7450 if (ttyfd < 0 || xlocal == 0) /* Don't set speed on console */
7457 return(tnc_set_baud(cps * 10));
7459 #endif /* TN_COMPORT */
7462 #endif /* NETCONN */
7464 if (ttpipe) return(0);
7467 if (ttpty) return(0);
7470 if (cps < 0) return(-1);
7471 s = s2 = 0; /* NB: s and s2 might be unsigned */
7473 #ifdef USETCSETSPEED
7477 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7478 debug(F101,"ttsspd tcgetattr","",x);
7481 debug(F101,"ttsspd TCSETSPEED speed","",s);
7484 if (s == 8880L) { /* 75/1200 split speed requested */
7485 tcsetspeed(TCS_IN, &ttcur, 1200L);
7486 tcsetspeed(TCS_OUT, &ttcur, 75L);
7488 tcsetspeed(TCS_ALL, &ttcur, s); /* Put new speed in structs */
7490 if (errno & deblog) {
7491 debug(F101,"ttsspd TCSETSPEED errno","",errno);
7496 tcsetspeed(TCS_ALL, &ttraw, s);
7497 tcsetspeed(TCS_ALL, &tttvt, s);
7498 tcsetspeed(TCS_ALL, &ttold, s);
7500 if (s == 8880L) { /* 75/1200 split speed requested */
7501 tcsetspeed(TCS_IN, &ttraw, 1200L);
7502 tcsetspeed(TCS_OUT, &ttraw, 75L);
7503 tcsetspeed(TCS_IN, &tttvt, 1200L);
7504 tcsetspeed(TCS_OUT, &tttvt, 75L);
7505 tcsetspeed(TCS_IN, &ttold, 1200L);
7506 tcsetspeed(TCS_OUT, &ttold, 75L);
7508 tcsetspeed(TCS_ALL, &ttraw, s);
7509 tcsetspeed(TCS_ALL, &tttvt, s);
7510 tcsetspeed(TCS_ALL, &ttold, s);
7512 #endif /* COMMENT */
7514 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
7515 debug(F101,"ttsspd tcsetattr","",x);
7519 #else /* Not USETCSETSPEED */
7521 /* First check that the given speed is valid. */
7525 case 0: s = B0; break;
7526 case 5: s = B50; break;
7527 case 7: s = B75; break;
7529 case 11: s = B110; break;
7531 case 13: s = B134; break;
7532 case 15: s = B150; break;
7533 case 20: s = B200; break;
7535 case 30: s = B300; break;
7537 case 60: s = B600; break;
7539 case 120: s = B1200; break;
7541 case 180: s = B1800; break;
7543 case 240: s = B2400; break;
7544 case 480: s = B4800; break;
7546 case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
7549 case 720: s = B7200; break;
7551 case 960: s = B9600; break;
7553 case 1440: s = B14400; break;
7556 case 1920: s = B19200; break;
7559 case 1920: s = EXTA; break;
7563 case 2880: s = B28800; break;
7566 case 3840: s = B38400;
7567 #ifdef OLINUXHISPEED
7568 spd_flags = ~ASYNC_SPD_MASK; /* Nonzero, but zero flags */
7569 #endif /* OLINUXHISPEED */
7571 #else /* B38400 not defined... */
7573 case 3840: s = EXTB; break;
7579 case 5760: s = _B57600; break;
7580 #endif /* _B57600 */
7582 case 11520: s = _B115200; break;
7583 #endif /* _B115200 */
7585 #ifdef OLINUXHISPEED
7587 This bit from <carlo@sg.tn.tudelft.nl>:
7588 "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
7589 setting the speed to 38400 will set the custom speed (and ttgspd returns
7590 38400), but speeds 57600 and 115200 won't work any more because I didn't
7591 want to mess up the speed flags when someone is doing sophisticated stuff
7592 like custom speeds..."
7594 case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
7595 case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
7598 case 5760: s = B57600; break;
7601 case 7680: s = B76800; break;
7604 case 11520: s = B115200; break;
7605 #endif /* B115200 */
7606 #endif /* OLINUXHISPEED */
7608 case 15360: s = B153600; break;
7609 #endif /* B153600 */
7611 case 23040: s = B230400; break;
7612 #endif /* B230400 */
7614 case 30720: s = B307200; break;
7615 #endif /* B307200 */
7617 case 46080: s = B460800; break;
7620 case 92160: s = B921600; break;
7621 #endif /* B921600 */
7624 ok = 0; /* Good speed not found, so not ok */
7627 debug(F101,"ttsspd ok","",ok);
7628 debug(F101,"ttsspd s","",s);
7631 debug(F100,"ttsspd fails","",0);
7634 if (!s2) s2 = s; /* Set input speed */
7636 if (p9ttsspd(cps) < 0)
7640 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7641 debug(F101,"ttsspd tcgetattr","",x);
7644 #ifdef OLINUXHISPEED
7645 debug(F101,"ttsspd spd_flags","",spd_flags);
7646 if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
7647 if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
7648 debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
7650 } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
7651 serinfo.flags &= ~ASYNC_SPD_MASK;
7652 serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
7653 if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
7656 #endif /* OLINUXHISPEED */
7657 cfsetospeed(&ttcur,s);
7658 cfsetispeed(&ttcur,s2);
7659 cfsetospeed(&ttraw,s);
7660 cfsetispeed(&ttraw,s2);
7661 cfsetospeed(&tttvt,s);
7662 cfsetispeed(&tttvt,s2);
7663 cfsetospeed(&ttold,s);
7664 cfsetispeed(&ttold,s2);
7665 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
7666 debug(F101,"ttsspd tcsetattr","",x);
7667 if (x < 0) return(-1);
7670 if (cps == 888) return(-1); /* No split speeds, sorry. */
7671 x = ioctl(ttyfd,TCGETA,&ttcur);
7672 debug(F101,"ttsspd TCGETA ioctl","",x);
7673 if (x < 0) return(-1);
7674 ttcur.c_cflag &= ~CBAUD;
7676 tttvt.c_cflag &= ~CBAUD;
7678 ttraw.c_cflag &= ~CBAUD;
7680 ttold.c_cflag &= ~CBAUD;
7682 x = ioctl(ttyfd,TCSETAW,&ttcur);
7683 debug(F101,"ttsspd TCSETAW ioctl","",x);
7684 if (x < 0) return(-1);
7687 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
7688 debug(F101,"ttsspd TIOCGDEV ioctl","",x);
7689 if (x < 0) return(-1);
7693 ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
7694 debug(F101,"ttsspd BELLV10 ioctl","",ok);
7697 debug(F101,"ttsspd BELLV10 errno","",ok);
7701 x = gtty(ttyfd,&ttcur);
7702 debug(F101,"ttsspd gtty","",x);
7703 if (x < 0) return(-1);
7704 ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
7705 tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
7706 ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
7707 ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
7708 x = stty(ttyfd,&ttcur);
7709 debug(F101,"ttsspd stty","",x);
7710 if (x < 0) return(-1);
7711 #endif /* BELLV10 */
7713 #endif /* BSD44ORPOSIX */
7716 return(1); /* Return 1 = success. */
7717 #endif /* USETCSETSPEED */
7720 #endif /* NOLOCAL */
7722 /* C O N G S P D - Get speed of console terminal */
7727 This is a disgusting hack. The right way to do this would be to pass an
7728 argument to ttgspd(), but then we'd need to change the Kermit API and
7729 all of the ck?tio.c modules. (Currently used only for rlogin.)
7736 #endif /* NETCONN */
7740 debug(F101,"congspd","",spd);
7743 #endif /* NETCONN */
7748 /* T T S P D L I S T -- Get list of serial speeds allowed on this platform */
7751 static long spdlist[NSPDLIST];
7753 As written, this picks up the speeds known at compile time, and thus
7754 apply to the system where C-Kermit was built, rather than to the one where
7755 it is running. Suggestions for improvement are always welcome.
7760 for (i = 0; i < NSPDLIST; i++) /* Initialize the list */
7764 #ifdef USETCSETSPEED /* No way to find out what's legal */
7765 debug(F100,"ttspdlist USETCSETSPEED","",0);
7770 spdlist[i++] = 110L;
7772 spdlist[i++] = 134L;
7774 spdlist[i++] = 150L;
7775 spdlist[i++] = 200L;
7776 spdlist[i++] = 300L;
7777 spdlist[i++] = 600L;
7778 spdlist[i++] = 1200L;
7779 spdlist[i++] = 1800L;
7780 spdlist[i++] = 2400L;
7781 spdlist[i++] = 4800L;
7782 spdlist[i++] = 8880L;
7783 spdlist[i++] = 9600L;
7784 spdlist[i++] = 14400L;
7785 spdlist[i++] = 19200L;
7786 spdlist[i++] = 28800L;
7788 spdlist[i++] = 33600L;
7790 spdlist[i++] = 38400L;
7791 spdlist[i++] = 57600L;
7792 spdlist[i++] = 76800L;
7793 spdlist[i++] = 115200L;
7795 spdlist[i++] = 153600L;
7796 spdlist[i++] = 230400L;
7797 spdlist[i++] = 307200L;
7798 spdlist[i++] = 460800L;
7799 spdlist[i++] = 921600L;
7802 #else /* USETCSETSPEED */
7804 debug(F100,"ttspdlist no USETCSETSPEED","",0);
7807 debug(F101,"ttspdlist B50","",B50);
7811 debug(F101,"ttspdlist B75","",B75);
7815 debug(F101,"ttspdlist B110","",B110);
7816 spdlist[i++] = 110L;
7819 debug(F101,"ttspdlist B134","",B134);
7820 spdlist[i++] = 134L;
7823 debug(F101,"ttspdlist B150","",B150);
7824 spdlist[i++] = 150L;
7827 debug(F101,"ttspdlist B200","",B200);
7828 spdlist[i++] = 200L;
7831 debug(F101,"ttspdlist B300","",B300);
7832 spdlist[i++] = 300L;
7835 debug(F101,"ttspdlist B600","",B600);
7836 spdlist[i++] = 600L;
7839 debug(F101,"ttspdlist B1200","",B1200);
7840 spdlist[i++] = 1200L;
7843 debug(F101,"ttspdlist B1800","",B1800);
7844 spdlist[i++] = 1800L;
7847 debug(F101,"ttspdlist B2400","",B2400);
7848 spdlist[i++] = 2400L;
7851 debug(F101,"ttspdlist B4800","",B4800);
7852 spdlist[i++] = 4800L;
7855 debug(F101,"ttspdlist B9600","",B9600);
7856 spdlist[i++] = 9600L;
7859 debug(F101,"ttspdlist B14400","",B14400);
7860 spdlist[i++] = 14400L;
7863 debug(F101,"ttspdlist B19200","",B19200);
7864 spdlist[i++] = 19200L;
7867 debug(F101,"ttspdlist EXTA","",EXTA);
7868 spdlist[i++] = 19200L;
7872 debug(F101,"ttspdlist B28800","",B28800);
7873 spdlist[i++] = 28800L;
7876 debug(F101,"ttspdlist B33600","",B33600);
7877 spdlist[i++] = 33600L;
7880 debug(F101,"ttspdlist B38400","",B38400);
7881 spdlist[i++] = 38400L;
7884 debug(F101,"ttspdlist EXTB","",EXTB);
7885 spdlist[i++] = 38400L;
7889 debug(F101,"ttspdlist _B57600","",_B57600);
7890 spdlist[i++] = 57600L;
7893 debug(F101,"ttspdlist B57600","",B57600);
7894 spdlist[i++] = 57600L;
7896 #endif /* _B57600 */
7898 debug(F101,"ttspdlist B76800","",B76800);
7899 spdlist[i++] = 76800L;
7902 debug(F101,"ttspdlist _B115200","",_B115200);
7903 spdlist[i++] = 115200L;
7906 debug(F101,"ttspdlist B115200","",B115200);
7907 spdlist[i++] = 115200L;
7908 #endif /* B115200 */
7909 #endif /* _B115200 */
7911 debug(F101,"ttspdlist B153600","",B153600);
7912 spdlist[i++] = 153600L;
7913 #endif /* B153600 */
7915 debug(F101,"ttspdlist B230400","",B230400);
7916 spdlist[i++] = 230400L;
7917 #endif /* B230400 */
7919 debug(F101,"ttspdlist B307200","",B307200);
7920 spdlist[i++] = 307200L;
7921 #endif /* B307200 */
7923 debug(F101,"ttspdlist B460800","",B460800);
7924 spdlist[i++] = 460800L;
7925 #endif /* B460800 */
7927 debug(F101,"ttspdlist B921600","",B921600);
7928 spdlist[i++] = 921600L;
7929 #endif /* B921600 */
7930 #endif /* USETCSETSPEED */
7931 spdlist[0] = i - 1; /* Return count in 0th element */
7932 debug(F111,"ttspdlist spdlist","0",spdlist[0]);
7933 return((long *)spdlist);
7936 /* T T G S P D - Get speed of currently selected tty line */
7939 Unreliable. After SET LINE, it returns an actual speed, but not necessarily
7940 the real speed. On some systems, it returns the line's nominal speed, from
7941 /etc/ttytab. Even if you SET SPEED to something else, this function might
7945 ttgspd() { /* Get current serial device speed */
7950 speed_t /* Should be unsigned */
7952 int /* Isn't unsigned */
7957 #ifdef OLINUXHISPEED
7958 unsigned int spd_flags = 0;
7959 struct serial_struct serinfo;
7960 #endif /* OLINUXHISPEED */
7966 return(tnc_get_baud());
7968 #endif /* TN_COMPORT */
7969 return(-1); /* -1 if network connection */
7971 #endif /* NETCONN */
7973 if (ttpipe) return(-1);
7976 if (ttpty) return(-1);
7979 debug(F101,"ttgspd ttyfd","",ttyfd);
7981 #ifdef USETCSETSPEED
7983 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7984 debug(F101,"ttgspd tcgetattr","",x);
7988 s = tcgetspeed(TCS_ALL, &ttcur);
7989 debug(F101,"ttsspd TCGETSPEED speed","",s);
7992 s1 = tcgetspeed(TCS_IN, &ttcur);
7993 s2 = tcgetspeed(TCS_OUT, &ttcur);
7994 if (s1 == 1200L && s2 == 75L)
7998 if (errno & deblog) {
7999 debug(F101,"ttsspd TCGETSPEED errno","",errno);
8004 #else /* Not USETCSETSPEED */
8012 #ifdef OLINUXHISPEED
8013 debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
8014 #endif /* OLINUXHISPEED */
8018 s = cfgetospeed(&ccold);
8019 debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
8022 s = ccold.c_cflag & CBAUD;
8023 debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
8025 s = ccold.sg_ospeed; /* (obtained by congm()) */
8026 debug(F101,"ttgspd sg_ospeed 1","",s);
8028 #endif /* BSD44POSIX */
8032 if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
8033 s = cfgetospeed(&ttcur);
8034 debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
8035 #ifdef OLINUXHISPEED
8036 if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
8037 spd_flags = serinfo.flags & ASYNC_SPD_MASK;
8038 debug(F101,"ttgspd spd_flags","",spd_flags);
8039 #endif /* OLINUXHISPEED */
8042 x = ioctl(ttyfd,TCGETA,&ttcur);
8043 debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
8044 debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
8045 if (x < 0) return(-1);
8046 s = ttcur.c_cflag & CBAUD;
8047 debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
8050 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
8051 debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
8052 if (x < 0) return(-1);
8054 debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
8056 x = gtty(ttyfd,&ttcur);
8057 debug(F101,"ttgspd gtty 2 x","",x);
8058 debug(F101,"ttgspd gtty 2 errno","",errno);
8059 if (x < 0) return(-1);
8060 s = ttcur.sg_ospeed;
8061 debug(F101,"ttgspd gtty 2 speed","",s);
8062 #endif /* BELLV10 */
8064 #endif /* BSD44ORPOSIX */
8066 debug(F101,"ttgspd code","",s);
8067 #ifdef OLINUXHISPEED
8068 debug(F101,"ttgspd spd_flags","",spd_flags);
8069 #endif /* OLINUXHISPEED */
8072 case B0: ss = 0L; break;
8077 MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
8078 etc, making for many "duplicate case in switch" errors, which are fatal.
8081 case B50: ss = 50L; break;
8084 case B75: ss = 75L; break;
8089 case B110: ss = 110L; break;
8094 case B134: ss = 134L; break;
8097 case B150: ss = 150L; break;
8102 case B200: ss = 200L; break;
8106 case B300: ss = 300L; break;
8110 case B600: ss = 600L; break;
8114 case B1200: ss = 1200L; break;
8118 case B1800: ss = 1800L; break;
8122 case B2400: ss = 2400L; break;
8126 case B4800: ss = 4800L; break;
8130 case B7200: ss = 7200L; break;
8134 case B9600: ss = 9600L; break;
8138 case B19200: ss = 19200L; break;
8141 case EXTA: ss = 19200L; break;
8149 #ifdef OLINUXHISPEED
8151 case ASYNC_SPD_HI: ss = 57600L; break;
8152 case ASYNC_SPD_VHI: ss = 115200L; break;
8154 #endif /* OLINUXHISPEED */
8158 case EXTB: ss = 38400L; break;
8165 case _B57600: ss = 57600L; break;
8166 #endif /* _B57600 */
8168 case _B115200: ss = 115200L; break;
8169 #endif /* _B115200 */
8172 case B57600: ss = 57600L; break;
8175 case B76800: ss = 76800L; break;
8178 case B115200: ss = 115200L; break;
8179 #endif /* B115200 */
8181 case B153600: ss = 153600L; break;
8182 #endif /* B153600 */
8184 case B230400: ss = 230400L; break;
8185 #endif /* B230400 */
8187 case B307200: ss = 307200L; break;
8188 #endif /* B307200 */
8190 case B460800: ss = 460800L; break;
8191 #endif /* B460800 */
8194 case B921600: ss = 921600L; break;
8195 #endif /* B921600 */
8200 debug(F101,"ttgspd speed","",ss);
8203 #endif /* USETCSETSPEED */
8204 #endif /* NOLOCAL */
8206 #ifdef MINIX2 /* Another hack alert */
8211 FIONREAD data type... This has been defined as "long" for many, many
8212 years, and it worked OK until 64-bit platforms appeared. Thus we use
8213 int for 64-bit platforms, but keep long for the others. If we changed
8214 the default PEEKTYPE to int, this would probably break 16-bit builds
8215 (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
8216 of which we have no way of testing any more. Therefore, do not change
8217 the default definition of PEEKTYPE -- only add exceptions to it as needed.
8222 #endif /* FIONREAD */
8223 /* #define FIONREAD TIOCQUERY */
8224 /* #define PEEKTYPE int */
8225 #else /* Not COHERENT... */
8227 #ifdef OSF32 /* Digital UNIX 3.2 or higher */
8228 #define PEEKTYPE int
8230 #define PEEKTYPE long /* Elsewhere (see notes above) */
8232 #endif /* COHERENT */
8234 /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
8238 /* Private buffer for myread() and its companions. Not for use by anything
8239 * else. ttflui() is allowed to reset them to initial values. ttchk() is
8240 * allowed to read my_count.
8242 * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
8244 * A global parity mask variable could be useful too. We could use it to
8245 * let myread() strip the parity on its own, instead of stripping sign
8246 * bits as it does now.
8249 #define MYBUFLEN 32768
8252 #define MYBUFLEN 256
8254 #define MYBUFLEN 1024
8256 #endif /* BIGBUFOK */
8260 #define MYBUFLEN 256
8262 On X.25 connections, there is an extra control byte at the beginning.
8264 static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */
8265 static CHAR *mybuf = x25buf+1;
8267 static CHAR mybuf[MYBUFLEN];
8270 static int my_count = 0; /* Number of chars still in mybuf */
8271 static int my_item = -1; /* Last index read from mybuf[] */
8273 /* T T P E E K -- Peek into our internal communications input buffers. */
8276 NOTE: This routine is peculiar to UNIX, and is used only by the
8277 select()-based CONNECT module, ckucns.c. It need not be replicated in
8278 the ck?tio.c of other platforms.
8290 #endif /* TTLEBUF */
8299 /* myread() -- Efficient read of one character from communications line.
8301 * NOTE: myread() and its helpers mygetbuf() and myfillbuf() return raw
8302 * bytes from connection, so when the connection is encrypted, these bytes
8303 * must be decrypted.
8305 * Uses a private buffer to minimize the number of expensive read() system
8306 * calls. Essentially performs the equivalent of read() of 1 character, which
8307 * is then returned. By reading all available input from the system buffers
8308 * to the private buffer in one chunk, and then working from this buffer, the
8309 * number of system calls is reduced in any case where more than one character
8310 * arrives during the processing of the previous chunk, for instance high
8311 * baud rates or network type connections where input arrives in packets.
8312 * If the time needed for a read() system call approaches the time for more
8313 * than one character to arrive, then this mechanism automatically compensates
8314 * for that by performing bigger read()s less frequently. If the system load
8315 * is high, the same mechanism compensates for that too.
8317 * myread() is a macro that returns the next character from the buffer. If the
8318 * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
8321 * This should be efficient enough for any one-character-at-a-time loops.
8322 * For even better efficiency you might use memcpy()/bcopy() or such between
8323 * buffers (since they are often better optimized for copying), but it may not
8324 * be worth it if you have to take an extra pass over the buffer to strip
8325 * parity and check for CTRL-C anyway.
8327 * Note that if you have been using myread() from another program module, you
8328 * may have some trouble accessing this macro version and the private variables
8329 * it uses. In that case, just add a function in this module, that invokes the
8332 #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
8334 /* Specification: Push back up to one character onto myread()'s queue.
8336 * This implementation: Push back characters into mybuf. At least one character
8337 * must have been read through myread() before myunrd() may be used. After
8338 * EOF or read error, again, myunrd() can not be used. Sometimes more than
8339 * one character can be pushed back, but only one character is guaranteed.
8340 * Since a previous myread() must have read its character out of mybuf[],
8341 * that guarantees that there is space for at least one character. If push
8342 * back was really needed after EOF, a small addition could provide that.
8344 * As of 02/2007 myunrd() is used by ttinl().
8351 #endif /* CK_ANSIC */
8354 mybuf[my_item--] = ch;
8359 /* T T P U S H B A C K -- Put n bytes back into the myread buffer */
8361 static CHAR * pushbuf = NULL;
8362 /* static int pushed = 0; */
8365 ttpushback(s,n) CHAR * s; int n; {
8366 debug(F101,"ttpushback n","",n);
8367 if (pushbuf || n > MYBUFLEN || n < 1)
8369 debug(F101,"ttpushback my_count","",my_count);
8371 if (!(pushbuf = (CHAR *)malloc(n+1)))
8373 memcpy(pushbuf,mybuf,my_count);
8374 /* pushed = my_count; */ /* (set but never used) */
8382 /* mygetbuf() -- Fill buffer for myread() and return first character.
8384 * This function is what myread() uses when it can't get the next character
8385 * directly from its buffer. First, it calls a system dependent myfillbuf()
8386 * to read at least one new character into the buffer, and then it returns
8387 * the first character just as myread() would have done. This function also
8388 * is responsible for all error conditions that myread() can indicate.
8390 * Returns: When OK => a positive character, 0 or greater.
8392 * When error => -3, error code in errno.
8394 * Older myread()s additionally returned -1 to indicate that there was nothing
8395 * to read, upon which the caller would call myread() again until it got
8396 * something. The new myread()/mygetbuf() always gets something. If it
8397 * doesn't, then make it do so! Any program that actually depends on the old
8398 * behaviour will break.
8400 * The older version also used to return -2 both for EOF and other errors,
8401 * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
8402 * other errors now return different results, although Kermit currently never
8403 * checks to see which it was. It just disconnects in both cases.
8405 * Kermit lets the user use the quit key to perform some special commands
8406 * during file transfer. This causes read(), and thus also mygetbuf(), to
8407 * finish without reading anything and return the EINTR error. This should
8408 * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
8409 * but if there is nothing to read, this could delay Kermit's reaction to
8410 * the command, and make Kermit appear unresponsive.
8412 * The debug() call should be removed for optimum performance.
8419 if (deblog && my_count > 0)
8420 debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
8423 my_count = myfillbuf();
8427 if (deblog) debug(F101, "mygetbuf read", "", my_count);
8429 ckhexdump("mygetbuf read", mybuf, my_count);
8430 #endif /* COMMENT */
8433 if (my_count <= 0) {
8436 debug(F101,"mygetbuf errno","",errno);
8438 if (netconn && ttnet == NET_TCPB && errno != 0) {
8439 if (errno != EINTR) {
8440 debug(F101,"mygetbuf TCP error","",errno);
8441 ttclos(0); /* Close the connection. */
8445 #endif /* TCPSOCKET */
8446 if (!netconn && xlocal && errno) {
8447 if (errno != EINTR) {
8448 debug(F101,"mygetbuf SERIAL error","",errno);
8450 ttclos(0); /* Close the connection. */
8453 return((x < 0) ? -3 : -2);
8456 return((unsigned)(0xff & mybuf[my_item = 0]));
8460 * System-dependent read() into mybuf[], as many characters as possible.
8462 * Returns: OK => number of characters read, always more than zero.
8464 * Error => -1, error code in errno.
8466 * If there is input available in the system's buffers, all of it should be
8467 * read into mybuf[] and the function return immediately. If no input is
8468 * available, it should wait for a character to arrive, and return with that
8469 * one in mybuf[] as soon as possible. It may wait somewhat past the first
8470 * character, but be aware that any such delay lengthens the packet turnaround
8471 * time during kermit file transfers. Should never return with zero characters
8472 * unless EOF or irrecoverable read error.
8474 * Correct functioning depends on the correct tty parameters being used.
8475 * Better control of current parameters is required than may have been the
8476 * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
8477 * no longer be sometimes off and sometimes on like it used to, unless a
8478 * special myfillbuf() is written to handle that. Otherwise the ordinary
8479 * myfillbuf()s may think they have come to EOF.
8481 * If your system has a facility to directly perform the functioning of
8482 * myfillbuf(), then use it. If the system can tell you how many characters
8483 * are available in its buffers, then read that amount (but not less than 1).
8484 * If the system can return a special indication when you try to read without
8485 * anything to read, while allowing you to read all there is when there is
8486 * something, you may loop until there is something to read, but probably that
8487 * is not good for the system load.
8491 /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
8492 * and CLOCAL set any way you like. This way, read() will do exactly
8493 * what is required by myfillbuf(): If there is data in the buffers
8494 * of the O.S., all available data is read into mybuf, up to the size
8495 * of mybuf. If there is none, the first character to arrive is
8496 * awaited and returned.
8509 /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */
8510 /* necessary for the sxa E50, but it is. */
8511 return read(fd, mybuf, 255);
8517 n = netxin(sizeof(mybuf), (char *)mybuf);
8518 debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
8521 #endif /* NETCONN */
8522 n = read(fd, mybuf, sizeof(mybuf));
8523 debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
8528 #else /* BEOSORBEBOX */
8530 /* debug(F101,"SVORPOSIX myfillbuf calling read() fd","",fd); */
8532 if (netconn && (nettype == NET_IX25)) {
8533 /* can't use sizeof because mybuf is a pointer, and not an array! */
8534 n = x25xin( MYBUFLEN, mybuf );
8539 if (ssl_active_flag || tls_active_flag) {
8541 debug(F100,"myfillbuf calling SSL_read() fd","",0);
8543 if (ssl_active_flag)
8544 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8545 else if (tls_active_flag)
8546 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8549 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8550 case SSL_ERROR_NONE:
8557 case SSL_ERROR_WANT_WRITE:
8558 case SSL_ERROR_WANT_READ:
8560 case SSL_ERROR_SYSCALL:
8563 case SSL_ERROR_WANT_X509_LOOKUP:
8565 case SSL_ERROR_ZERO_RETURN:
8576 if (ttnproto == NP_EK4LOGIN) {
8577 debug(F101,"myfillbuf calling krb4_des_read() fd","",ttyfd);
8578 if ((n = krb4_des_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8583 #endif /* RLOGCODE */
8587 if (ttnproto == NP_EK5LOGIN) {
8588 debug(F101,"myfillbuf calling krb5_des_read() fd","",ttyfd);
8589 if ((n = krb5_des_read(ttyfd,(char *)mybuf,sizeof(mybuf),0)) < 0)
8594 #endif /* RLOGCODE */
8596 if (ttnproto == NP_K5U2U) {
8597 debug(F101,"myfillbuf calling krb5_u2u_read() fd","",ttyfd);
8598 if ((n = krb5_u2u_read(ttyfd,(char *)mybuf,sizeof(mybuf))) < 0)
8603 #endif /* KRB5_U2U */
8605 #endif /* CK_KERBEROS */
8609 /* Special handling for HP-UX pty i/o */
8611 if (ttpty && pty_trap_pending(ttyfd) > 0) {
8612 debug(F101,"myfillbuf calling pty_trap_handler() fd","",ttyfd);
8613 if (pty_trap_handler(ttyfd) > 0) {
8618 #endif /* HAVE_PTYTRAP */
8620 debug(F101,"myfillbuf calling read() fd","",ttyfd);
8621 n = read(fd, mybuf, sizeof(mybuf));
8622 debug(F101,"SVORPOSIX myfillbuf read","",n);
8623 debug(F101,"SVORPOSIX myfillbuf errno","",errno);
8624 debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
8628 /* When we have a PTY trap in place the connection cannot */
8629 /* be closed until the trap receives a close indication. */
8630 if (n == 0 && ttpty)
8632 #endif /* HAVE_PTYTRAP */
8637 #endif /* BEOSORBEBOX */
8641 #else /* not AT&T or POSIX */
8644 /* This is quoted from the old myread(). The semantics seem to be
8645 * alright, but maybe errno would not need to be set even when
8646 * there is no error? I don't know aegis.
8658 count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
8660 if (st.all == ios_$get_conditional_failed) /* get at least one */
8661 count = ios_$get((short)fd, 0, mybuf, 1L, st);
8662 if (st.all == ios_$end_of_file)
8664 else if (st.all != status_$ok) {
8668 return(count > 0 ? count : -3);
8673 /* This is for systems with FIONREAD. FIONREAD returns the number
8674 * of characters available for reading. If none are available, wait
8675 * until something arrives, otherwise return all there is.
8690 SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
8691 Depends on SunOS having FIONREAD, not because we use it, but just so this
8692 code is grouped correctly within the #ifdefs. Let's hope Solaris keeps it.
8694 We call x25xin() instead of read() so that Q-Bit packets, which contain
8695 X.25 service-level information (e.g. PAD parameter changes), can be processed
8696 transparently to the upper-level code. This is a blocking read, and so
8697 we depend on higher-level code (such as ttinc()) to set any necessary alarms.
8700 if (netconn && nettype == NET_SX25) {
8701 while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
8702 return(x - 1); /* "-1" compensates for extra status byte */
8707 if (ssl_active_flag || tls_active_flag) {
8710 if (ssl_active_flag)
8711 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8713 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8714 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8715 case SSL_ERROR_NONE:
8722 case SSL_ERROR_WANT_WRITE:
8723 case SSL_ERROR_WANT_READ:
8725 case SSL_ERROR_SYSCALL:
8728 case SSL_ERROR_WANT_X509_LOOKUP:
8730 case SSL_ERROR_ZERO_RETURN:
8741 if (ttnproto == NP_EK4LOGIN) {
8742 if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8747 #endif /* RLOGCODE */
8751 if (ttnproto == NP_EK5LOGIN) {
8752 if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8757 #endif /* RLOGCODE */
8759 if (ttnproto == NP_K5U2U) {
8760 if ((x = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8765 #endif /* KRB5_U2U */
8767 #endif /* CK_KERBEROS */
8770 debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
8771 x = ioctl(fd, FIONREAD, &avail);
8774 debug(F101,"myfillbuf FIONREAD","",x);
8775 debug(F101,"myfillbuf FIONREAD avail","",avail);
8776 debug(F101,"myfillbuf FIONREAD errno","",errno);
8779 if (x < 0 || avail == 0)
8782 if (avail > MYBUFLEN)
8787 x = read(fd, mybuf, (int) avail);
8790 debug(F101,"myfillbuf avail","",avail);
8791 debug(F101,"myfillbuf read","",x);
8792 debug(F101,"myfillbuf read errno","",errno);
8794 ckhexdump("myfillbuf mybuf",mybuf,x);
8797 if (x < 1) x = -3; /* read 0 == connection loss */
8801 #else /* !FIONREAD */
8802 /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
8803 /* When there is no other possibility, read 1 character at a time. */
8809 if (ssl_active_flag || tls_active_flag) {
8812 if (ssl_active_flag)
8813 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8815 count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8816 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8817 case SSL_ERROR_NONE:
8824 case SSL_ERROR_WANT_WRITE:
8825 case SSL_ERROR_WANT_READ:
8827 case SSL_ERROR_SYSCALL:
8830 case SSL_ERROR_WANT_X509_LOOKUP:
8832 case SSL_ERROR_ZERO_RETURN:
8843 if (ttnproto == NP_EK4LOGIN) {
8844 if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8849 #endif /* RLOGCODE */
8853 if (ttnproto == NP_EK5LOGIN) {
8854 if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8859 #endif /* RLOGCODE */
8861 if (ttnproto == NP_K5U2U) {
8862 if ((len = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8867 #endif /* KRB5_U2U */
8869 #endif /* CK_KERBEROS */
8877 x = read(fd, mybuf, 1);
8878 return(x > 0 ? x : -3);
8881 #endif /* !FIONREAD */
8887 /* T T _ T N O P T -- Handle Telnet negotions in incoming data */
8889 Call with the IAC that was encountered.
8891 -3: If connection has dropped or gone bad.
8892 -2: On Telnet protocol error resulting in inconsistent states.
8893 0: If negotiation OK and caller has nothing to do.
8894 1: If packet start character has changed (new value is in global stchr).
8895 255: If there was a quoted IAC as data.
8896 or: Not at all if we got a legitimate Telnet Logout request.
8900 tt_tnopt(n) int n; { /* Handle Telnet options */
8901 /* In case caller did not already check these conditions... */
8903 ((xlocal && netconn && IS_TELNET()) ||
8904 (!xlocal && sstelnet))) {
8907 debug(F100,"ttinl calling tn_doop()","",0);
8908 tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
8909 debug(F111,"ttinl tn_doop() returned","tx",tx);
8913 case -1: /* I/O error */
8914 ttimoff(); /* Turn off timer */
8916 case -2: /* Connection failed. */
8918 ttimoff(); /* Turn off timer */
8921 case 1: /* ECHO change */
8924 case 2: /* ECHO change */
8927 case 3: /* Quoted IAC */
8929 return((unsigned)255);
8932 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
8936 ) { /* Remote in Server mode */
8937 ttimoff(); /* Turn off timer */
8938 debug(F100,"u_start and !inserver","",0);
8939 return(-2); /* End server mode */
8940 } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
8942 ) { /* I'm no longer in Server Mode */
8943 debug(F100,"me_start and server","",0);
8949 case 5: { /* Start character change */
8950 /* extern CHAR stchr; */
8951 /* start = stchr; */
8954 #endif /* IKS_OPTION */
8955 case 6: /* Remote Logout */
8959 if (inserver && !local)
8960 doexit(GOOD_EXIT,0);
8970 #endif /* TCPSOCKET */
8972 /* T T F L U I -- Flush tty input buffer */
8975 ttflux() { /* But first... */
8978 Flush internal MYREAD buffer.
8982 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
8983 (!xlocal && sstelnet)));
8984 #endif /* TCPSOCKET */
8985 debug(F101,"ttflux my_count","",my_count);
8989 while (my_count > 0) {
8991 #ifdef CK_ENCRYPTION
8992 if (TELOPT_U(TELOPT_ENCRYPTION))
8993 ck_tn_decrypt((char *)&ch,1);
8994 #endif /* CK_ENCRYPTION */
8999 #endif /* TCPSOCKET */
9001 #ifdef CK_ENCRYPTION
9002 if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
9003 ck_tn_decrypt(&mybuf[my_item+1],my_count);
9004 #endif /* CK_ENCRYPTION */
9005 #endif /* COMMENT */
9006 my_count = 0; /* Reset count to zero */
9007 my_item = -1; /* And buffer index to -1 */
9016 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
9017 (!xlocal && sstelnet)));
9018 #endif /* TCPSOCKET */
9028 ttpush = -1; /* Clear the peek-ahead char */
9029 while (le_data && (le_inbuf() > 0)) {
9031 if (le_getchar(&ch) > 0) { /* Clear any more... */
9032 debug(F101,"ttflui le_inbuf ch","",ch);
9035 #endif /* TTLEBUF */
9036 debug(F101,"ttflui ttpipe","",ttpipe);
9040 Flush internal MYREAD buffer *NEXT*, in all cases.
9046 /* Network flush is done specially, in the network support module. */
9047 if ((netconn || sstelnet) && !ttpipe && !ttpty) {
9048 debug(F100,"ttflui netflui","",0);
9052 tnc_send_purge_data(TNC_PURGE_RECEIVE);
9053 #endif /* TN_COMPORT */
9054 #endif /* COMMENT */
9057 #endif /* NETCONN */
9059 debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
9064 sio_$control((short)yfd, sio_$flush_in, true, st);
9065 if (st.all != status_$ok) {
9066 fprintf(stderr, "flush failed: "); error_$print(st);
9067 } else { /* sometimes the flush doesn't work */
9070 /* eat all the characters that shouldn't be available */
9071 ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
9072 if (st.all == ios_$get_conditional_failed) break;
9073 fprintf(stderr, "flush failed(2): "); error_$print(st);
9077 #ifdef BSD44 /* 4.4 BSD */
9078 n = FREAD; /* Specify read queue */
9079 debug(F100,"ttflui BSD44","",0);
9080 ioctl(fd,TIOCFLUSH,&n);
9083 #undef POSIX /* Uh oh... */
9085 #ifdef POSIX /* POSIX */
9086 debug(F100,"ttflui POSIX","",0);
9087 tcflush(fd,TCIFLUSH);
9089 #ifdef ATTSV /* System V */
9091 debug(F100,"ttflui ATTSV","",0);
9094 #else /* Not BSD44, POSIX, or Sys V */
9095 #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */
9096 #ifdef ANYBSD /* Berkeley */
9097 n = FREAD; /* Specify read queue */
9098 debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
9099 ioctl(fd,TIOCFLUSH,&n);
9100 #else /* Others (V7, etc) */
9101 debug(F100,"ttflui TIOCFLUSH","",0);
9102 ioctl(fd,TIOCFLUSH,0);
9104 #else /* All others... */
9106 No system call (that we know about) for input buffer flushing.
9107 So see how many there are and read them in a loop, using ttinc().
9108 ttinc() is buffered, so we're not getting charged with a system call
9109 per character, just a function call.
9111 if ((n = ttchk()) > 0) {
9112 debug(F101,"ttflui read loop","",n);
9113 while ((n--) && ttinc(0) > 0) ;
9115 #endif /* TIOCFLUSH */
9127 ttfluo() { /* Flush output buffer */
9140 return(tcflush(fd,TCOFLUSH));
9143 return(ioctl(fd,TCFLSH,1));
9145 return(0); /* All others, nothing */
9151 /* Interrupt Functions */
9153 /* Set up terminal interrupts on console terminal */
9155 #ifndef FIONREAD /* We don't need esctrp() */
9156 #ifndef SELECT /* if we have any of these... */
9163 esctrp(foo) int foo; { /* trap console escapes (^\) */
9164 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9166 debug(F101,"esctrp caught SIGQUIT","",conesc);
9168 #endif /* SVORPOSIX */
9174 esctrp(foo) int foo; { /* trap console escapes (^\) */
9175 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9177 debug(F101,"esctrp caught SIGQUIT","",conesc);
9184 esctrp(foo) int foo; { /* trap console escapes (^\) */
9186 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9191 #endif /* CK_POLL */
9193 #endif /* FIONREAD */
9195 /* C O N B G T -- Background Test */
9197 static int jc = 0; /* 0 = no job control */
9200 Call with flag == 1 to prevent signal test, which can not be expected
9201 to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
9203 Call with flag == 0 to use the signal test, but only if the process-group
9204 test fails, as it does on some UNIX systems, where getpgrp() is buggy,
9205 requires an argument when the man page says it doesn't, or vice versa.
9207 If flag == 0 and the process-group test fails, then we determine background
9208 status simply (but not necessarily reliably) from isatty().
9210 conbgt() sets the global backgrd = 1 if we appear to be in the background,
9211 and to 0 if we seem to be in the foreground. conbgt() is highly prone to
9215 conbgt(flag) int flag; {
9216 int x = -1, /* process group or SIGINT test */
9217 y = 0; /* isatty() test */
9219 Check for background operation, even if not running on real tty, so that
9220 background flag can be set correctly. If background status is detected,
9221 then Kermit will not issue its interactive prompt or most messages.
9222 If your prompt goes away, you can blame (and fix?) this function.
9225 /* Use process-group test if possible. */
9227 #ifdef POSIX /* We can do it in POSIX */
9230 #ifdef BSD4 /* and in BSD 4.x. */
9233 #ifdef HPUXJOBCTL /* and in most HP-UX's */
9236 #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
9238 #endif /* TIOCGPGRP */
9239 #endif /* HPUXJOBCTL */
9243 #ifdef MIPS /* Except if it doesn't work... */
9253 Semi-reliable process-group test. Check whether this process's group is
9254 the same as the controlling terminal's process group. This works if the
9255 getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
9257 PID_T mypgrp = (PID_T)0; /* Kermit's process group */
9258 PID_T ctpgrp = (PID_T)0; /* The terminal's process group */
9259 #ifndef _POSIX_SOURCE
9261 The getpgrp() prototype is obtained from system header files for POSIX
9262 and Sys V R4 compilations. Other systems, who knows. Some complain about
9263 a duplicate declaration here, others don't, so it's safer to leave it in
9264 if we don't know for certain.
9269 extern PID_T getpgrp();
9271 #endif /* PS2AIX10 */
9273 #endif /* _POSIX_SOURCE */
9275 /* Get my process group. */
9277 #ifdef SVR3 /* Maybe this should be ATTSV? */
9278 /* This function is not described in SVID R2 */
9280 /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
9284 /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
9288 /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
9292 /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
9294 #ifdef OSF32 /* (was OSF40) */
9296 /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
9297 #else /* BSD, V7, etc */
9301 mypgrp = getpgrp(0);
9303 /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
9311 /* MINIX does not support job control so Kermit is always in foreground */
9314 #else /* Not MINIX */
9316 /* Now get controlling tty's process group */
9318 ctpgrp = tcgetpgrp(1); /* The POSIX way */
9319 /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
9321 ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
9322 /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
9323 #endif /* BSD44ORPOSIX */
9325 if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
9326 x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
9327 else x = -1; /* If error, remember. */
9328 debug(F101,"conbgt process group test","",x);
9329 #endif /* PGROUP_T */
9332 /* Try to see if job control is available */
9334 #ifdef NOJC /* User override */
9335 jc = 0; /* No job control allowed */
9336 debug(F111,"NOJC","jc",jc);
9341 #ifdef SVR4ORPOSIX /* POSIX actually tells us */
9342 debug(F100,"SVR4ORPOSIX jc test...","",0);
9343 #ifdef _SC_JOB_CONTROL
9350 jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
9352 debug(F101,"sysconf fails, jcshell","",jcshell);
9353 jc = (jchdlr == SIG_DFL) ? 1 : 0;
9355 debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
9356 #endif /* __386BSD__ */
9357 #endif /* __bsdi__ */
9359 #ifdef _POSIX_JOB_CONTROL
9360 jc = 1; /* By definition */
9361 debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
9363 jc = 0; /* Assume job control not allowed */
9364 debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
9365 #endif /* _POSIX_JOB_CONTROL */
9366 #endif /* _SC_JOB_CONTROL */
9369 jc = 1; /* Job control allowed */
9370 debug(F111,"BSD job control","jc",jc);
9373 jc = 1; /* JC allowed */
9374 debug(F111,"SVR3 job control","jc",jc);
9377 jc = 1; /* JC allowed */
9378 debug(F111,"X/OS job control","jc",jc);
9381 jc = 1; /* JC allowed */
9382 debug(F111,"HP-UX 9.0 job control","jc",jc);
9385 jc = 1; /* JC allowed */
9386 debug(F111,"HP-UX 10.0 job control","jc",jc);
9388 jc = 0; /* JC not allowed */
9389 debug(F111,"job control catch-all","jc",jc);
9395 #endif /* SVR4ORPOSIX */
9398 debug(F101,"conbgt jc","",jc);
9400 debug(F101,"conbgt jcshell","",jcshell);
9402 At this point, if jc == 1 but jcshell == 0, it means that the OS supports
9403 job control, but the shell or other process we are running under does not
9404 (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
9405 will come of it. So...
9408 if (jc > 0 && jcshell == 0) jc = 0;
9412 Another background test.
9413 Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
9414 which is done by the shell (sh) if the program is started with '&'.
9415 Unfortunately, this is NOT done by csh or ksh so watch out!
9416 Note, it's safe to set SIGINT to SIG_IGN here, because further down
9417 we always set it to something else.
9418 Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
9421 if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
9423 SIGTYP (*osigint)();
9425 osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
9427 x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
9428 /* debug(F101,"conbgt osigint","",osigint); */
9429 /* debug(F101,"conbgt signal test","",x); */
9432 /* Also check to see if we're running with redirected stdio. */
9433 /* This is not really background operation, but we want to act as though */
9437 if (inserver) { /* Internet Kermit Server */
9438 backgrd = 0; /* is not in the background */
9443 y = (isatty(0) && isatty(1)) ? 1 : 0;
9444 debug(F101,"conbgt isatty test","",y);
9447 /* The process group and/or signal test doesn't work under these... */
9460 backgrd = (x || !y) ? 1 : 0;
9466 debug(F101,"conbgt backgrd","",backgrd);
9469 /* C O N I N T -- Console Interrupt setter */
9472 First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
9473 Second arg is pointer to function to handle SIGTSTP (suspend).
9476 VOID /* Set terminal interrupt traps. */
9479 conint(f,s) SIGTYP (*f)(), (*s)();
9481 conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
9484 conint(f,s) SIGTYP (*f)(), (*s)();
9485 #endif /* CK_ANSIC */
9488 debug(F101,"conint conistate","",conistate);
9490 conbgt(0); /* Do background test. */
9492 /* Set the desired handlers for hangup and software termination. */
9495 signal(SIGTERM,f); /* Software termination */
9496 #endif /* SIGTERM */
9499 Prior to July 1999 we used to call sighup() here but now it's called in
9500 sysinit() so SIGHUP can be caught during execution of the init file or
9504 /* Now handle keyboard stop, quit, and interrupt signals. */
9505 /* Check if invoked in background -- if so signals set to be ignored. */
9506 /* However, if running under a job control shell, don't ignore them. */
9507 /* We won't be getting any, as we aren't in the terminal's process group. */
9509 debug(F101,"conint backgrd","",backgrd);
9510 debug(F101,"conint jc","",jc);
9512 if (backgrd && !jc) { /* In background, ignore signals */
9513 debug(F101,"conint background ignoring signals, jc","",jc);
9515 signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
9516 #endif /* SIGTSTP */
9517 signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
9518 signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
9520 conistate = CONI_NOI;
9521 } else { /* Else in foreground or suspended */
9522 debug(F101,"conint foreground catching signals, jc","",jc);
9523 signal(SIGINT,f); /* Catch terminal interrupt */
9524 sigint_ign = (f == SIG_IGN) ? 1 : 0;
9526 #ifdef SIGTSTP /* Keyboard stop (suspend) */
9527 /* debug(F101,"conint SIGSTSTP","",s); */
9528 if (s == NULL) s = SIG_DFL;
9529 #ifdef NOJC /* No job control allowed. */
9530 signal(SIGTSTP,SIG_IGN);
9531 #else /* Job control allowed */
9532 if (jc) /* if available. */
9535 signal(SIGTSTP,SIG_IGN);
9537 #endif /* SIGTSTP */
9541 #ifndef FIONREAD /* Watch out, we don't know this... */
9545 signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
9547 #endif /* CK_POLL */
9549 #endif /* FIONREAD */
9550 if (conesc) conesc = 0; /* Clear out pending escapes */
9553 signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
9554 if (conesc) conesc = 0;
9557 signal(SIGQUIT,f); /* Apollo, catch it like others. */
9559 signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
9562 #endif /* SVORPOSIX */
9564 conistate = CONI_INT;
9569 /* C O N N O I -- Reset console terminal interrupts */
9572 connoi() { /* Console-no-interrupts */
9574 debug(F101,"connoi conistate","",conistate);
9576 signal(SIGTSTP,SIG_IGN); /* Suspend */
9577 #endif /* SIGTSTP */
9578 conint(SIG_IGN,SIG_IGN); /* Interrupt */
9579 sigint_ign = 1; /* Remember we did this ourselves */
9581 signal(SIGQUIT,SIG_IGN); /* Quit */
9582 #endif /* SIGQUIT */
9584 signal(SIGTERM,SIG_IGN); /* Term */
9585 #endif /* SIGTERM */
9586 conistate = CONI_NOI;
9589 /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */
9593 Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
9594 eliminates blocking on a read, because we can read /dev/kmem to get the
9595 number of characters available for raw input. If your system can't
9596 or you won't let the world read /dev/kmem then you must figure out a
9597 different way to do the counting of characters available, or else replace
9598 this by a dummy function that always returns 0.
9601 * Call this routine as: initrawq(tty)
9602 * where tty is the file descriptor of a terminal. It will return
9603 * (as a char *) the kernel-mode memory address of the rawq character
9604 * count, which may then be read. It has the side-effect of flushing
9605 * input on the terminal.
9608 * John Mackin, Physiology Dept., University of Sydney (Australia)
9609 * ...!decvax!mulga!physiol.su.oz!john
9611 * Permission is hereby granted to do anything with this code, as
9612 * long as this comment is retained unmodified and no commercial
9613 * advantage is gained.
9619 #include <sys/proc.h>
9620 #endif /* COHERENT */
9626 #include <sys/proc.h>
9627 #endif /* COHERENT */
9630 initrawq(tty) int tty; {
9644 static struct nlist nl[] = {
9649 static struct proc *pp;
9653 NPTYPE xproc; /* Its type is defined in makefile. */
9657 if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
9658 nlist(BOOTNAME, nl);
9659 if (nl[0].n_type == 0) err("proc array");
9661 if (nl[1].n_type == 0) err("nproc");
9663 lseek(m, (long)(nl[1].n_value), 0);
9664 read (m, &xproc, sizeof(xproc));
9665 saval = signal(SIGALRM, catch);
9666 if ((pid = fork()) == 0) {
9672 if(setjmp(jjbuf) == 0) {
9676 signal(SIGALRM, SIG_DFL);
9679 pp = (struct proc *) nl[0].n_value;
9681 if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
9682 if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
9684 lseek(m, (long)(nl[1].n_value), 0);
9685 read(m, &xproc, sizeof(xproc));
9687 if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
9688 if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
9689 if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
9690 err("read proc table");
9691 for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
9692 if (pp -> p_pid == (short) pid) goto iout;
9694 err("no such proc");
9698 qaddr = (char *)(pp -> p_wchan);
9709 /* More V7-support functions... */
9715 ckmakmsg(buf,200,"fatal error in initrawq: ", s, NULL, NULL);
9721 catch(foo) int foo; {
9726 /* G E N B R K -- Simulate a modem break. */
9740 genbrk(fn,msec) int fn, msec; {
9741 struct sgttyb ttbuf;
9742 int ret, sospeed, x, y;
9744 ret = ioctl(fn, TIOCGETP, &ttbuf);
9745 sospeed = ttbuf.sg_ospeed;
9746 ttbuf.sg_ospeed = BSPEED;
9747 ret = ioctl(fn, TIOCSETP, &ttbuf);
9748 y = (int)strlen(brnuls);
9749 x = ( BSPEED * 100 ) / msec;
9751 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9752 ttbuf.sg_ospeed = sospeed;
9753 ret = ioctl(fn, TIOCSETP, &ttbuf);
9754 ret = write(fn, "@", 1);
9761 genbrk(fn,msec) int fn, msec; {
9762 struct termios ttbuf;
9766 ret = tcgetattr(fn, &ttbuf);
9767 sospeed = ttbuf.c_ospeed;
9768 ttbuf.c_ospeed = BSPEED;
9769 ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
9770 y = (int)strlen(brnuls);
9771 x = ( BSPEED * 100 ) / msec;
9773 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9774 ttbuf.c_ospeed = sospeed;
9775 ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
9776 ret = write(fn, "@", 1);
9783 I N C H K -- Check if chars waiting to be read on given file descriptor.
9785 This routine is a merger of ttchk() and conchk().
9787 channel == 0 to check console.
9788 channel == 1 to check communications connection.
9790 fd = file descriptor.
9792 >= 0: number of characters waiting, 0 or greater,
9793 -1: on any kind of error,
9794 -2: if there is (definitely) no connection.
9795 Note: In UNIX we don't have to call nettchk() because a socket
9796 file descriptor works just like in serial i/o, ioctls and all.
9797 (But this will change if we add non-file-descriptor channels,
9798 such as IBM X.25 for AIX...)
9801 in_chk(channel, fd) int channel, fd; {
9802 int x, n = 0; /* Workers, n = return value */
9803 extern int clsondisc; /* Close on disconnect */
9805 The first section checks to make sure we have a connection,
9806 but only if we're in local mode.
9810 debug(F111,"in_chk entry",ckitoa(fd),channel);
9811 debug(F101,"in_chk ttyfd","",ttyfd);
9812 debug(F101,"in_chk ttpty","",ttpty);
9816 But don't say connection is gone if we have any buffered-stuff.
9819 debug(F101,"in_chk ttpush","",ttpush);
9827 #endif /* TTLEBUF */
9831 /* Special handling for HP-UX pty i/o */
9832 if (ttpty && pty_trap_pending(ttyfd) > 0) {
9833 if (pty_trap_handler(ttyfd) > 0) {
9838 #endif /* HAVE_PTYTRAP */
9841 if (channel) { /* Checking communications channel */
9842 if (ttyfd < 0) { /* No connection */
9843 return(-2); /* That's what this means */
9844 } else if (xlocal && /* In local mode */
9845 (!netconn /* Serial connection or */
9847 || istncomport() /* Telnet Com Port */
9848 #endif /* TN_COMPORT */
9849 ) && ttcarr != CAR_OFF /* with CARRIER WATCH ON (or AUTO) */
9853 Seems like this would be a good idea but it prevents C-Kermit from
9854 popping back to the prompt automatically when carrier drops. However,
9855 commenting this out prevents us from seeing the NO CARRIER message.
9858 && my_count < 1 /* Nothing in our internal buffer */
9860 #endif /* COMMENT */
9863 x = ttgmdm(); /* So get modem signals */
9864 debug(F101,"in_chk close-on-disconnect","",clsondisc);
9865 if (x > -1) { /* Check for carrier */
9866 if (!(x & BM_DCD)) { /* No carrier */
9867 debug(F101,"in_chk carrier lost","",x);
9868 if (clsondisc) /* If "close-on-disconnect" */
9869 ttclos(0); /* close device & release lock. */
9870 return(-2); /* This means "disconnected" */
9872 /* In case I/O to device after CD dropped always fails */
9873 /* as in Debian Linux 2.1 and Unixware 2.1... */
9875 debug(F101,"in_chk ttgmdm I/O error","",errno);
9876 debug(F101,"in_chk ttgmdm gotsigs","",gotsigs);
9877 if (gotsigs) { /* If we got signals before... */
9878 if (errno == 5 || errno == 6) { /* I/O error etc */
9879 if (clsondisc) /* like when modem hangs up */
9884 /* If we never got modem signals successfully on this */
9885 /* connection before, we can't conclude that THIS failure */
9886 /* means the connection was lost. */
9892 /* We seem to have a connection so now see if any bytes are waiting on it */
9895 if (ssl_active_flag || tls_active_flag) {
9896 n += SSL_pending(ssl_active_flag?ssl_con:tls_con);
9897 debug(F101,"in_chk SSL_pending","",n);
9908 /* It is not safe to read any data when using encrypted Klogin */
9909 if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
9911 if (ttnproto == NP_EK4LOGIN) {
9912 n += krb4_des_avail(ttyfd);
9913 debug(F101,"in_chk krb4_des_avail","",n);
9917 if (ttnproto == NP_EK5LOGIN) {
9918 n += krb5_des_avail(ttyfd);
9919 debug(F101,"in_chk krb5_des_avail","",n);
9922 if (ttnproto == NP_K5U2U) {
9923 n += krb5_u2u_avail(ttyfd);
9924 debug(F101,"in_chk krb5_des_avail","",n);
9926 #endif /* KRB5_U2U */
9928 if (n < 0) /* Is this right? */
9933 #endif /* CK_KERBEROS */
9934 #endif /* RLOGCODE */
9936 errno = 0; /* Reset this so we log good info */
9938 x = ioctl(fd, FIONREAD, &n); /* BSD and lots of others */
9939 #ifdef DEBUG /* (the more the better) */
9941 debug(F101,"in_chk FIONREAD return code","",x);
9942 debug(F101,"in_chk FIONREAD count","",n);
9943 debug(F101,"in_chk FIONREAD errno","",errno);
9946 #else /* FIONREAD not defined */
9948 Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
9949 with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
9950 portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
9951 that I looked at, but it is needed to prevent the call from blocking), and
9952 the msghdr struct differs from place to place, so we would need another
9953 avalanche of ifdefs. Still, when FIONREAD is not available, this is the
9954 only other known method of asking the OS for the *number* of characters
9955 available for reading.
9957 #ifdef V7 /* UNIX V7: look in kernel memory */
9959 n = 0; /* But not in MINIX */
9964 lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
9965 x = read(kmem[TTY], &n, sizeof(int));
9966 if (x != sizeof(int))
9972 x = ioctl(fd, TIOCQCNT, &ttbuf); /* DEC Pro/3xx Venix V.1 */
9973 n = ttbuf.sg_ispeed & 0377; /* Circa 1984 */
9978 Here we skip all the undependable and expensive calls below if we
9979 already have something in our internal buffer. This tends to work quite
9980 nicely, so the only really bad case remaining is the one in which neither
9981 FIONREAD or MYREAD are defined, which is increasingly rare these days.
9983 if (channel != 0 && my_count > 0) {
9984 debug(F101,"in_chk buf my_count","",my_count);
9985 n = my_count; /* n was 0 before we got here */
9990 rdchk(), select(), and poll() tell us *if* data is available to be read, but
9991 not how much, so these should be used only as a final resort. Especially
9992 since these calls tend to add a lot overhead.
9994 #ifdef RDCHK /* This mostly SCO-specific */
9996 debug(F101,"in_chk rdchk","",n);
9997 #else /* No RDCHK */
10000 /* Only allows select on the console ... don't ask */
10004 fd_set rfds; /* Read file descriptors */
10006 FD_ZERO(rfds); /* Initialize them */
10007 FD_SET(fd,rfds); /* We want to look at this fd */
10009 FD_ZERO(&rfds); /* Initialize them */
10010 FD_SET(fd,&rfds); /* We want to look at this fd */
10011 tv.tv_sec = tv.tv_usec = 0L; /* A 0-valued timeval structure */
10012 #endif /* BELLV10 */
10014 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10015 debug(F101,"in_chk Plan 9 select","",n);
10018 n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
10019 debug(F101,"in_chk BELLV10 select","",n);
10022 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10023 debug(F101,"in_chk BSD44 select","",n);
10026 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10027 debug(F101,"in_chk BSD43 select","",n);
10030 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10031 debug(F101,"in_chk SOLARIS select","",n);
10034 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10035 debug(F101,"in_chk QNX6 select","",n);
10038 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10039 debug(F101,"in_chk QNX select","",n);
10042 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10043 debug(F101,"in_chk COHERENT select","",n);
10046 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10047 debug(F101,"in_chk SVR4 select","",n);
10050 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10051 debug(F101,"in_chk LINUX select","",n);
10053 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
10054 debug(F101,"in_chk OSF select","",n);
10056 n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
10057 debug(F101,"in_chk catchall select","",n);
10059 #endif /* __linux__ */
10061 #endif /* COHERENT */
10064 #endif /* SOLARIS */
10067 #endif /* BELLV10 */
10070 #else /* Not SELECT */
10076 pfd.events = POLLIN;
10078 n = poll(&pfd, 1, 0);
10079 debug(F101,"in_chk poll","",n);
10080 if ((n > 0) && (pfd.revents & POLLIN))
10083 #endif /* CK_POLL */
10084 #endif /* SELECT */
10086 #endif /* PROVX1 */
10088 #endif /* FIONREAD */
10090 /* From here down, treat console and communication device differently... */
10092 if (channel == 0) { /* Console */
10100 This is the hideous hack used in System V and POSIX systems that don't
10101 support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
10102 CONNECT-mode escape character is attached to SIGQUIT. Used, obviously,
10103 only on the console.
10105 if (conesc) { /* Escape character typed == SIGQUIT */
10106 debug(F100,"in_chk conesc","",conesc);
10108 signal(SIGQUIT,esctrp); /* Restore signal */
10112 #endif /* CK_POLL */
10113 #endif /* SELECT */
10114 #endif /* FIONREAD */
10115 #endif /* SVORPOSIX */
10117 return(n); /* Done with console */
10120 if (channel != 0) { /* Communications connection */
10125 select() or rdchk(), etc, has told us that something is waiting, but we
10126 don't know how much. So we do a read to get it and then we know. Note:
10127 This read is NOT nonblocking if nothing is there (because of VMIN=1), but
10128 it should be safe in this case since the OS tells us at least one byte is
10129 waiting to be read, and MYREAD reads return as much as is there without
10130 waiting for any more. Controlled tests on Solaris and Unixware (with
10131 FIONREAD deliberately undefined) show this to be true.
10133 debug(F101,"in_chk read my_count","",my_count);
10134 debug(F101,"in_chk read n","",n);
10135 if (n > 0 && my_count == 0) {
10136 /* This also catches disconnects etc */
10137 /* Do what mygetbuf does except don't grab a character */
10138 my_count = myfillbuf();
10139 my_item = -1; /* ^^^ */
10140 debug(F101,"in_chk myfillbuf my_count","",my_count);
10144 n = 0; /* NB: n is replaced by my_count */
10146 #endif /* FIONREAD */
10148 Here we add whatever we think is unread to what is still in our
10149 our internal buffer. Thus the importance of setting n to 0 just above.
10151 debug(F101,"in_chk my_count","",my_count);
10152 debug(F101,"in_chk n","",n);
10155 #endif /* MYREAD */
10157 debug(F101,"in_chk result","",n);
10159 /* Errors here don't prove the connection has dropped so just say 0 */
10161 return(n < 0 ? 0 : n);
10165 /* T T C H K -- Tell how many characters are waiting in tty input buffer */
10174 #endif /* NETCMD */
10176 return(in_chk(1,fd));
10179 /* T T X I N -- Get n characters from tty input buffer */
10181 /* Returns number of characters actually gotten, or -1 on failure */
10183 /* Intended for use only when it is known that n characters are actually */
10184 /* Available in the input buffer. */
10187 ttxin(n,buf) int n; CHAR *buf; {
10188 register int x = 0, c = -2;
10190 register int i = 0;
10191 #endif /* TTLEBUF */
10194 if (n < 1) /* Nothing to do */
10199 buf[0] = ttpush; /* Put pushed char in buffer*/
10200 ttpush = -1; /* Clear the push buffer */
10202 return(ttxin(n-1, &buf[1]) + 1);
10207 while (le_inbuf() > 0) {
10208 if (le_getchar(&buf[i])) {
10214 return(ttxin(n,&buf[i])+i);
10218 #endif /* TTLEBUF */
10224 #endif /* NETCMD */
10228 if (netconn && (ttnet == NET_SX25)) /* X.25 connection */
10229 return(x25xin(n,buf));
10230 #endif /* SUNX25 */
10233 /* riehm: possibly not needed. Test worked with normal reads and writes */
10234 if (netconn && (ttnet == NET_IX25)) { /* X.25 connection */
10236 if (x > 0) buf[x] = '\0';
10239 #endif /* IBMX25 */
10242 debug(F101,"ttxin MYREAD","",n);
10246 debug(F101,"ttxin myread returns","",c);
10247 if (c == -3) x = -1;
10250 buf[x++] = c & ttpmsk;
10253 /* It is impossible to know how many characters are waiting */
10254 /* to be read when you are using Encrypted Rlogin or SSL */
10255 /* as the transport since the number of real data bytes */
10256 /* can be greater or less than the number of bytes on the */
10257 /* wire which is what ttchk() returns. */
10258 if (netconn && (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN))
10261 #endif /* CK_KERBEROS */
10262 #endif /* RLOGCODE */
10264 if (ssl_active_flag || tls_active_flag)
10267 #endif /* CK_SSL */
10270 debug(F101,"ttxin READ","",n);
10271 x = read(fd,buf,n);
10272 for (c = 0; c < n; c++) /* Strip any parity */
10274 #endif /* MYREAD */
10276 debug(F101,"ttxin x","",x); /* Done */
10277 if (x > 0) buf[x] = '\0';
10282 /* T T O L -- Write string s, length n, to communication device. */
10285 >= 0 on success, number of characters actually written.
10288 #ifdef CK_ENCRYPTION
10289 CHAR * xpacket = NULL;
10291 #endif /* CK_ENCRYPTION */
10295 ttol(s,n) int n; CHAR *s; {
10296 int x, len, tries, fd;
10298 extern int dblflag; /* For SET SEND DOUBLE-CHARACTER */
10299 extern short dblt[];
10300 CHAR *p = NULL, *p2, *s2, c;
10302 #endif /* CKXXCHAR */
10304 if (ttyfd < 0) /* Not open? */
10308 /* debug(F101,"ttol ttyfd","",ttyfd); */
10309 ckhexdump("ttol s",s,n);
10317 #endif /* NETCMD */
10321 /* Double any characters that must be doubled. */
10322 debug(F101,"ttol dblflag","",dblflag);
10324 p = (CHAR *) malloc(n + n + 1);
10333 if (dblt[(unsigned) c] & 2) {
10343 ckhexdump("ttol doubled s",s,n);
10346 #endif /* CKXXCHAR */
10348 tries = TTOLMAXT; /* Allow up to this many tries */
10349 len = n; /* Remember original length */
10351 #ifdef CK_ENCRYPTION
10353 This is to avoid encrypting a packet that is already encrypted, e.g.
10354 when we resend a packet directly out of the packet buffer, and also to
10355 avoid encrypting a constant (literal) string, which can cause a memory
10358 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
10360 if (nxpacket < n) {
10366 x = n > 10240 ? n : 10240;
10367 xpacket = (CHAR *)malloc(x);
10369 fprintf(stderr,"ttol malloc failure\n");
10374 memcpy((char *)xpacket,(char *)s,n);
10376 ck_tn_encrypt((char *)s,n);
10378 #endif /* CK_ENCRYPTION */
10382 #ifdef CK_ENCRYPTION
10383 /* keep trying if we are encrypting */
10384 || TELOPT_ME(TELOPT_ENCRYPTION)
10385 #endif /* CK_ENCRYPTION */
10386 )) { /* Be persistent */
10387 debug(F101,"ttol try","",TTOLMAXT - tries);
10389 if (netconn && !ttpipe && !ttpty)
10390 x = nettol((char *)s,n); /* Write string to device */
10392 #endif /* BEOSORBEBOX */
10394 if (ttnet == NET_IX25)
10396 * this is a more controlled way of writing to X25
10397 * STREAMS, however write should also work!
10399 x = x25write(ttyfd, s, n);
10401 #endif /* IBMX25 */
10403 if (ssl_active_flag || tls_active_flag) {
10405 /* Write using SSL */
10407 if (ssl_active_flag)
10408 x = SSL_write(ssl_con, s, n);
10410 x = SSL_write(tls_con, s, n);
10411 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
10412 case SSL_ERROR_NONE:
10418 case SSL_ERROR_WANT_WRITE:
10419 case SSL_ERROR_WANT_READ:
10422 case SSL_ERROR_SYSCALL:
10425 case SSL_ERROR_WANT_X509_LOOKUP:
10426 case SSL_ERROR_SSL:
10427 case SSL_ERROR_ZERO_RETURN:
10433 #endif /* CK_SSL */
10437 if (ttnproto == NP_EK4LOGIN) {
10438 return(krb4_des_write(ttyfd,s,n));
10440 #endif /* RLOGCODE */
10444 if (ttnproto == NP_EK5LOGIN) {
10445 return(krb5_des_write(ttyfd,(char *)s,n,0));
10447 #endif /* RLOGCODE */
10449 if (ttnproto == NP_K5U2U) {
10450 return(krb5_u2u_write(ttyfd,(char *)s,n));
10452 #endif /* KRB5_U2U */
10454 #endif /* CK_KERBEROS */
10455 x = write(fd,s,n); /* Write string to device */
10457 if (x == n) { /* Worked? */
10458 debug(F101,"ttol ok","",x); /* OK */
10461 #endif /* CKXXCHAR */
10462 return(len); /* Done */
10463 } else if (x < 0) { /* No, got error? */
10464 debug(F101,"ttol write error","",errno);
10466 if (errno == EWOULDBLOCK) {
10470 #endif /* EWOULDBLOCK */
10472 if (netconn && ttnet == NET_TCPB) {
10473 debug(F101,"ttol TCP error","",errno);
10474 ttclos(0); /* Close the connection. */
10477 #endif /* TCPSOCKET */
10480 #endif /* CKXXCHAR */
10482 } else { /* No error, so partial success */
10483 debug(F101,"ttol partial","",x); /* This never happens */
10484 s += x; /* Point to part not written yet */
10485 n -= x; /* Adjust length */
10486 if (x > 0) msleep(10); /* Wait 10 msec */
10487 } /* Go back and try again */
10491 #endif /* CKXXCHAR */
10492 return(n < 1 ? len : -1); /* Return the results */
10495 /* T T O C -- Output a character to the communication line */
10498 This function should only be used for interactive, character-mode operations,
10499 like terminal connection, script execution, dialer i/o, where the overhead
10500 of the signals and alarms does not create a bottleneck.
10507 #endif /* CK_ANSIC */
10509 #define TTOC_TMO 15 /* Timeout in case we get stuck */
10512 if (ttyfd < 0) /* Check for not open. */
10519 #endif /* NETCMD */
10523 /* debug(F101,"ttoc","",(CHAR) c); */
10524 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10525 xx = alarm(TTOC_TMO); /* for this many seconds. */
10526 if (xx < 0) xx = 0; /* Save old alarm value. */
10527 /* debug(F101,"ttoc alarm","",xx); */
10529 #ifdef CK_POSIX_SIG
10533 #endif /* CK_POSIX_SIG */
10534 ) { /* Timer went off? */
10535 ttimoff(); /* Yes, cancel this alarm. */
10536 if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
10537 /* debug(F100,"ttoc timeout","",0); */
10540 #endif /* NETCONN */
10541 debug(F101,"ttoc timeout","",c);
10542 if (ttflow == FLO_XONX) {
10543 debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
10546 /* POSIX way to unstick. */
10547 debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
10549 #ifdef BSD4 /* Berkeley way to do it. */
10551 /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);". Who knows? */
10554 debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
10556 #endif /* TIOCSTART */
10558 /* Is there a Sys V way to do this? */
10564 #endif /* NETCONN */
10565 return(-1); /* Return failure code. */
10570 if (netconn && !ttpipe && !ttpty)
10573 #endif /* BEOSORBEBOX */
10574 #endif /* NETCONN */
10575 #ifdef CK_ENCRYPTION
10576 if (TELOPT_ME(TELOPT_ENCRYPTION))
10577 ck_tn_encrypt(&c,1);
10578 #endif /* CK_ENCRYPTION */
10580 /* riehm: maybe this isn't necessary after all. Test program
10581 * worked fine with data being sent and retrieved with normal
10582 * read's and writes!
10584 if (ttnet == NET_IX25)
10585 rc = x25write(ttyfd,&c,1); /* as above for X25 streams */
10587 #endif /* IBMX25 */
10589 if (ssl_active_flag || tls_active_flag) {
10591 /* Write using SSL */
10592 if (ssl_active_flag)
10593 rc = SSL_write(ssl_con, &c, 1);
10595 rc = SSL_write(tls_con, &c, 1);
10596 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)){
10597 case SSL_ERROR_NONE:
10599 case SSL_ERROR_WANT_WRITE:
10600 case SSL_ERROR_WANT_READ:
10603 case SSL_ERROR_SYSCALL:
10606 case SSL_ERROR_WANT_X509_LOOKUP:
10607 case SSL_ERROR_SSL:
10608 case SSL_ERROR_ZERO_RETURN:
10614 #endif /* CK_SSL */
10618 if (ttnproto == NP_EK4LOGIN) {
10619 rc = (krb4_des_write(ttyfd,(char *)&c,1) == 1);
10621 #endif /* RLOGCODE */
10625 if (ttnproto == NP_EK5LOGIN) {
10626 rc = (krb5_des_write(ttyfd,&c,1,0) == 1);
10628 #endif /* RLOGCODE */
10630 if (ttnproto == NP_K5U2U) {
10631 rc = (krb5_u2u_write(ttyfd,&c,1) == 1);
10633 #endif /* KRB5_U2U */
10635 #endif /* CK_KERBEROS */
10636 rc = write(fd,&c,1); /* Try to write the character. */
10637 if (rc < 1) { /* Failed */
10638 ttimoff(); /* Turn off the alarm. */
10639 alarm(xx); /* Restore previous alarm. */
10640 debug(F101,"ttoc errno","",errno); /* Log the error, */
10641 return(-1); /* and return the error code. */
10644 ttimoff(); /* Success, turn off the alarm. */
10645 alarm(xx); /* Restore previous alarm. */
10646 return(0); /* Return good code. */
10649 /* T T I N L -- Read a record (up to break character) from comm line. */
10651 Reads up to "max" characters from the connection, terminating on:
10652 (a) the packet length field if the "turn" argument is zero, or
10653 (b) on the packet-end character (eol) if the "turn" argument is nonzero
10654 (c) a certain number of Ctrl-C's in a row
10657 >= 0, the number of characters read upon success;
10658 -1 if "max" exceeded, timeout, or other correctable error;
10659 -2 on user interruption (c);
10660 -3 on fatal error like connection lost.
10662 The name of this routine dates from the early days when Kermit packets
10663 were, indeed, always lines of text. That was before control-character
10664 unprefixing and length-driven packet framing were introduced, which this
10665 version handle. NB: this routine is ONLY for reading incoming Kermit
10666 packets, nothing else. To read other kinds of incoming material, use
10667 ttinc() or ttxin().
10669 The bytes that were input are copied into "dest" with their parity bits
10670 stripped if parity was selected. Returns the number of bytes read.
10671 Bytes after the eol are available upon the next call to this function.
10673 The idea is to minimize the number of system calls per packet, and also to
10674 minimize timeouts. This function is the inner loop of the protocol and must
10675 be as efficient as possible. The current strategy is to use myread(), a
10676 macro to manage buffered (and generally nonblocking) reads.
10678 WARNING: This function calls parchk(), which is defined in another module.
10679 Normally, ckutio.c does not depend on code from any other module, but there
10680 is an exception in this case because all the other ck?tio.c modules also
10681 need to call parchk(), so it's better to have it defined in a common place.
10686 #define CTRLC '\03'
10688 We have four different declarations here because:
10689 (a) to allow Kermit to be built without the automatic parity sensing feature
10690 (b) one of each type for ANSI C, one for non-ANSI.
10694 static int pushedback = 0;
10699 ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
10701 ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
10702 #endif /* CK_ANSIC */
10703 #else /* not PARSENSE */
10705 ttinl(CHAR *dest, int max,int timo, CHAR eol)
10707 ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
10708 #endif /* CK_ANSIC */
10709 #endif /* PARSENSE */
10714 #endif /* MYREAD */
10719 #endif /* PARSENSE */
10721 int sopmask = 0xff; /* Start-Of-Packet mask */
10723 extern short dblt[]; /* Ignore-character table */
10724 extern int ignflag;
10725 #endif /* CKXXCHAR */
10728 #endif /* TCPSOCKET */
10731 extern int streaming;
10733 #endif /* STREAMING */
10735 if (ttyfd < 0) return(-3); /* Not open. */
10737 In February 2007 I fixed ttinl() to work better under the truly awful
10738 conditions encountered by the AM-APEX oceanographic floats that gather
10739 hurricane data and phone home using Iridium satellite modems, which under
10740 certain conditions, can send two packets back to back after a long pause.
10741 In this case the second packet would be ignored because the SOH was skipped
10742 due to the ttflui() call. But the reworked lookahead/pushback logic broke
10743 Kermit transfers on encrypted connections. This was fixed 12-13 August
10744 2007. All of this happened after 8.0.212 Dev.27 was released and before
10745 Dev.28, so no harm done other than the delay.
10747 debug(F101,"ttinl max","",max);
10748 debug(F101,"ttinl timo","",timo);
10754 #endif /* NETCMD */
10758 if (xlocal && conchk() > 0) /* Allow for console interruptions */
10760 #endif /* COMMENT */
10762 *dest = '\0'; /* Clear destination buffer */
10763 if (timo < 0) timo = 0; /* Safety */
10764 if (timo) { /* Don't time out if timo == 0 */
10766 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10767 xx = alarm(timo); /* Set it. */
10768 debug(F101,"ttinl alarm","",xx);
10771 #ifdef CK_POSIX_SIG
10775 #endif /* CK_POSIX_SIG */
10776 ) { /* Timer went off? */
10777 debug(F100,"ttinl timout","",0); /* Get here on timeout. */
10778 /* debug(F110," with",(char *) dest,0); */
10779 ttimoff(); /* Turn off timer */
10780 return(-1); /* and return error code. */
10782 register int i, n = -1; /* local variables */
10785 register int flag = 0;
10786 debug(F000,"ttinl start","",start);
10787 #endif /* PARSENSE */
10789 ttpmsk = ttprty ? 0177 : 0377; /* Set parity stripping mask. */
10790 sopmask = needpchk ? 0177 : ttpmsk; /* And SOP matching mask. */
10792 /* Now read into destination, stripping parity and looking for the */
10793 /* the packet terminator, and also for several Ctrl-C's typed in a row. */
10795 i = 0; /* Destination index */
10796 debug(F101,"ttinl eol","",eol);
10798 while (i < max-1) {
10801 /* On encrypted connections myread returns encrypted bytes */
10803 debug(F000,"TTINL myread char","",n);
10804 if (n < 0) { /* Timeout or i/o error? */
10807 debug(F101,"ttinl myread failure, n","",n);
10808 debug(F101,"ttinl myread errno","",errno);
10811 /* Don't let EINTR break packets. */
10813 if (errno == EINTR && i > 0) {
10814 debug(F111,"ttinl EINTR myread i","continuing",i);
10817 debug(F110,"ttinl non-EINTR -3","closing",0);
10819 ttimoff(); /* Turn off timer */
10823 } else if (n == -2 && netconn /* && timo == 0 */ ) {
10824 /* Here we try to catch broken network connections */
10825 /* even when ioctl() and read() do not catch them */
10826 debug(F111,"ttinl network myread failure","closing",n);
10833 /* Streaming and no data to read */
10834 else if (n == 0 && streaming && sndtyp == 'D')
10836 #endif /* STREAMING */
10837 break; /* Break out of while loop */
10840 #else /* not MYREAD (is this code used anywhere any more?) */
10842 The non-MYREAD code dates from the 1980s and was needed on certain platforms
10843 where there were no nonblocking reads. -fdc, 2007/02/22.
10845 if ((n = read(fd, &n, 1)) < 1)
10846 break; /* Error - break out of while loop */
10848 #endif /* MYREAD */
10850 /* Get here with char in n */
10852 #ifdef CK_ENCRYPTION
10853 if (TELOPT_U(TELOPT_ENCRYPTION) && !pushedback) {
10855 ck_tn_decrypt((char *)&ch,1);
10857 debug(F000,"TTINL decryp char","",n);
10860 #endif /* CK_ENCRYPTION */
10863 if (n == IAC && /* Handle Telnet options */
10864 ((xlocal && netconn && IS_TELNET()) ||
10865 (!xlocal && sstelnet))) {
10872 #endif /* NOPARSEN */
10873 if (n != 255) /* No data - go back for next char */
10875 } /* Quoted IAC - keep going */
10876 #endif /* TCPSOCKET */
10880 if (dblt[(unsigned) n] & 1) /* Character to ignore? */
10882 #endif /* CKXXCHAR */
10884 Use parity mask, rather than always stripping parity, to check for
10885 cancellation. Otherwise, runs like \x03\x83\x03 in a packet could cancel
10886 the transfer when parity is NONE. (Note that \x03\x03\x03 is extremely
10887 unlikely due to run-length encoding.)
10889 /* Check cancellation */
10890 if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
10891 if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
10892 if (timo) { /* Clear timer. */
10896 printf("^%c...\r\n",(char)(xfrchr+64));
10898 printf("Canceled...\r\n");
10901 } else ccn = 0; /* No cancellation, reset counter, */
10905 Restructured code allows for a new packet to appear somewhere in the
10906 middle of a previous one. -fdc, 24 Feb 2007.
10908 if ((n & sopmask) == start) { /* Start of Packet */
10909 debug(F101,"ttinl SOP i","",i);
10910 flag = 1; /* Flag that we are in a packet */
10911 havelen = 0; /* Invalidate previous length */
10912 pktlen = -1; /* (if any) in case we were */
10913 lplen = 0; /* alread processand a packet */
10914 i = 0; /* and reset the dest buffer pointer */
10916 if (flag == 0) { /* No SOP yet... */
10917 debug(F000,"ttinl skipping","",n);
10920 dest[i++] = n & ttpmsk;
10922 If we have not been instructed to wait for a turnaround character, we can go
10923 by the packet length field. If turn != 0, we must wait for the end of line
10924 (eol) character before returning. This is an egregious violation of all
10925 principles of layering... (Less egregious in C-Kermit 9.0, in which we go
10926 by the length field but also look for the eol in case it arrives early,
10927 e.g. if the length field was corrupted upwards.)
10931 if ((dest[1] & 0x7f) < 32) /* Garbage in length field */
10932 return(-1); /* fdc - 13 Apr 2010 */
10933 pktlen = xunchar(dest[1] & 0x7f);
10934 if (pktlen > 94) /* Rubout in length field */
10935 return(-1); /* fdc - 13 Apr 2010 */
10938 debug(F101,"ttinl pktlen value","",pktlen);
10940 } else if (i == 5 && pktlen == 0) {
10941 lplen = xunchar(dest[4] & 0x7f);
10942 } else if (i == 6 && pktlen == 0) {
10943 pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
10945 debug(F101,"ttinl extended length","",pktlen);
10950 Suppose we looked at the sequence number here and found it was out of
10951 range? This would mean either (a) incoming packets had SOP unprefixed
10952 and we are out of sync, or (b) the packet is damaged. Since (a) is bad
10953 practice, let's ignore it. So what should we do here if we know the
10956 1. Nothing -- keep trying to read the packet till we find what we think
10957 is the end, or we time out, and let the upper layer decide what to
10958 do. But since either the packet is corrupt or we are out of sync,
10959 our criterion for finding the end does not apply and we are likely
10960 to time out (or swallow a piece of the next packet) if our assumed
10961 length is too long. (This was the behavior prior to version 7.0.)
10963 2. set flag = 0 and continue? This would force us to wait for the
10964 next packet to come in, and therefore (in the nonwindowing case),
10965 would force a timeout in the other Kermit.
10967 3. set flag = 0 and continue, but only if the window size is > 1 and
10968 the window is not blocked? Talk about cheating!
10970 4. Return a failure code and let the upper layer decide what to do.
10971 This should be equivalent to 3, but without the cheating. So let's
10972 do it that way... But note that we must ignore the parity bit
10973 in case this is the first packet and we have not yet run parchk().
10975 if (i == 3) { /* Peek at sequence number */
10976 x = xunchar((dest[i-1] & 0x7f)); /* If it's not in range... */
10977 if (x < 0 || x > 63) {
10978 debug(F111,"ttinl bad seq",dest,x);
10979 if (timo) ttimoff();
10980 return(-1); /* return a nonfatal error */
10984 #else /* PARSENSE */
10985 dest[i++] = n & ttpmsk;
10986 #endif /* PARSENSE */
10988 /* Check for end of packet */
10991 ((n & ttpmsk) == eol) /* Always break on the eol char */
10993 || /* fdc - see notes of 13 Apr 2010 */
10995 Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
10996 This allows packet terminators and handshake characters to appear
10997 literally inside a packet data field.
10999 (havelen && (i > pktlen+1) &&
11000 (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
11002 #endif /* PARSENSE */
11005 Here we have either read the last byte of the packet based on its length
11006 field, or else we have read the packet terminator (eol) or the half-duplex
11007 line-turnaround char (turn).
11010 debug(F101,"ttinl got eol","",eol); /* (or turn) */
11011 dest[i] = '\0'; /* Yes, terminate the string, */
11012 /* debug(F101,"ttinl i","",i); */
11014 #else /* PARSENSE */
11018 if ((n & ttpmsk) != eol) {
11019 debug(F101,"ttinl EOP length","",pktlen);
11020 debug(F000,"ttinl EOP current char","",n);
11021 debug(F101,"ttinl EOP packet buf index","",i);
11022 } else debug(F101,"ttinl got eol","",eol);
11028 The packet was read based on its length. This leaves the packet terminator
11029 unread, and so ttchk() will always return at least 1 because of this,
11030 possibly giving a false positive to the "is there another packet waiting?"
11031 test. But if we know the terminator (or any other interpacket junk) is
11032 there, we can safely get rid of it.
11034 NOTE: This code reworked to (a) execute even if the debug log isn't active;
11035 and (b) actually work. -fdc, 2007/02/22. And again 2007/08/12-13 to also
11036 work on encrypted connections.
11038 debug(F101,"TTINL my_count","",my_count);
11039 if ((n & ttpmsk) != eol) { /* Not the packet terminator */
11041 while (my_count > 0) {
11042 x = myread(); /* (was ttinc(0) */
11043 debug(F000,"TTINL lkread char","",x);
11044 #ifdef CK_ENCRYPTION
11045 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11047 ck_tn_decrypt((char *)&ch,1);
11049 debug(F000,"TTINL lkdecr char","",x);
11051 #endif /* CK_ENCRYPTION */
11053 Note: while it might seem more elegant to simply
11054 push back the encrypted byte, that desynchronizes
11055 the decryption stream; the flag is necessary so we
11056 don't try to decrypt the same byte twice.
11058 if ((x & ttpmsk) == start) { /* Start of next packet */
11059 myunrd(x); /* Push back the decrypted byte */
11060 pushedback = 1; /* And set flag */
11061 debug(F000,"TTINL lkpush char","",x);
11066 #endif /* MYREAD */
11068 dest[i] = '\0'; /* Terminate the string, */
11069 if (needpchk) { /* Parity checked yet? */
11070 if (ttprty == 0) { /* No, check. */
11071 if ((ttprty = parchk(dest,start,i)) > 0) {
11073 debug(F101,"ttinl senses parity","",ttprty);
11074 debug(F110,"ttinl packet before",dest,0);
11076 for (j = 0; j < i; j++)
11077 dest[j] &= 0x7f; /* Strip parity from packet */
11078 debug(F110,"ttinl packet after ",dest,0);
11079 } else ttprty = 0; /* Restore if parchk error */
11084 #endif /* PARSENSE */
11086 if (timo) /* Turn off timer if it was on */
11088 ckhexdump("ttinl got",dest,i);
11091 /* ttinl() was called because there was non-packet */
11092 /* data sitting in the back channel. Ignore it. */
11093 if (streaming && sndtyp == 'D')
11095 #endif /* STREAMING */
11098 } /* End of while() */
11103 #endif /* NOXFER */
11105 /* T T I N C -- Read a character from the communication line */
11107 On success, returns the character that was read, >= 0.
11108 On failure, returns -1 or other negative myread error code,
11109 or -2 if connection is broken or ttyfd < 0.
11110 or -3 if session limit has expired,
11111 or -4 if something or other...
11112 NOTE: The API does not provide for ttinc() returning a special code
11113 upon timeout, but we need it. So for this we have a global variable,
11116 static int ttinctimo = 0; /* Yuk */
11119 ttinc(timo) int timo; {
11127 if (ttyfd < 0) return(-2); /* Not open. */
11129 is_tn = (xlocal && netconn && IS_TELNET()) ||
11130 (!xlocal && sstelnet);
11134 debug(F111,"ttinc","ttpush",ttpush);
11140 if (le_getchar(&ch) > 0) {
11141 debug(F111,"ttinc le_getchar","ch",ch);
11145 #endif /* TTLEBUF */
11151 #endif /* NETCMD */
11154 if ((timo <= 0) /* Untimed. */
11156 || (my_count > 0) /* Buffered char already waiting. */
11157 #endif /* MYREAD */
11160 /* Comm line failure returns -1 thru myread, so no &= 0377 */
11161 n = myread(); /* Wait for a character... */
11162 /* debug(F000,"ttinc MYREAD n","",n); */
11163 #ifdef CK_ENCRYPTION
11164 /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
11165 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11167 ck_tn_decrypt((char *)&ch,1);
11170 #endif /* CK_ENCRYPTION */
11173 if (ttpty && n < 0) {
11174 debug(F101,"ttinc error on pty","",n);
11178 #endif /* NETPTY */
11181 if ((n > -1) && is_tn)
11182 return((unsigned)(n & 0xff));
11184 #endif /* TNCODE */
11185 return(n < 0 ? n : (unsigned)(n & ttpmsk));
11189 while ((n = read(fd,&ch,1)) == 0) /* Wait for a character. */
11190 /* Shouldn't have to loop in ver 5A. */
11192 if (netconn) { /* Special handling for net */
11193 netclos(); /* If read() returns 0 it means */
11194 netconn = 0; /* the connection has dropped. */
11198 #endif /* NETCONN */
11200 /* debug(F101,"ttinc","",ch); */
11202 if ((n > 0) && is_tn) {
11203 #ifdef CK_ENCRYPTION
11204 if (TELOPT_U(TELOPT_ENCRYPTION)) {
11205 ck_tn_decrypt(&ch,1);
11208 #endif /* CK_ENCRYPTION */
11209 return((unsigned)(ch & 0xff));
11211 #endif /* TNCODE */
11212 return((n < 0) ? -4 : ((n == 0) ? -1 : (unsigned)(ch & ttpmsk)));
11213 #endif /* MYREAD */
11215 } else { /* Timed read */
11218 saval = signal(SIGALRM,timerh); /* Set up handler, save old one. */
11219 oldalarm = alarm(timo); /* Set alarm, save old one. */
11221 #ifdef CK_POSIX_SIG
11225 #endif /* CK_POSIX_SIG */
11226 ) { /* Timer expired */
11228 n = -1; /* set flag */
11231 n = myread(); /* If managing own buffer... */
11232 debug(F101,"ttinc myread","",n);
11235 n = read(fd,&ch,1); /* Otherwise call the system. */
11236 if (n == 0) n = -1;
11237 debug(F101,"ttinc read","",n);
11238 #endif /* MYREAD */
11240 #ifdef CK_ENCRYPTION
11241 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11242 ck_tn_decrypt((char *)&ch,1);
11244 #endif /* CK_ENCRYPTION */
11246 n = (unsigned) (ch & 0xff);
11248 n = (n < 0) ? -4 : -2; /* Special return codes. */
11250 ttimoff(); /* Turn off the timer */
11251 if (oldalarm > 0) {
11252 if (n == -1) /* and restore any previous alarm */
11254 if (oldalarm < 0) /* adjusted by our timeout interval */
11257 debug(F101,"ttinc restoring oldalarm","",oldalarm);
11263 if (n == -2) { /* read() returns 0 */
11264 netclos(); /* on network read failure */
11269 #endif /* NETCONN */
11271 if ((n > -1) && is_tn)
11272 return((unsigned)(n & 0xff));
11274 #endif /* TNCODE */
11275 /* Return masked char or neg. */
11276 return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
11280 /* S N D B R K -- Send a BREAK signal of the given duration */
11284 sndbrk(int msec) { /* Argument is milliseconds */
11286 sndbrk(msec) int msec; {
11287 #endif /* CK_ANSIC */
11298 #endif /* ANYBSD */
11307 #endif /* BSDBREAK */
11308 #endif /* COHERENT */
11313 #endif /* BSDBREAK */
11314 #endif /* BELLV10 */
11318 #endif /* PROVX1 */
11320 debug(F101,"ttsndb ttyfd","",ttyfd);
11321 if (ttyfd < 0) return(-1); /* Not open. */
11324 return p9sndbrk(msec);
11328 if (ttpipe) /* Pipe */
11329 return(ttoc('\0'));
11330 #endif /* NETCMD */
11333 return(ttoc('\0'));
11334 #endif /* NETPTY */
11335 if (netconn) /* Send network BREAK */
11336 return(netbreak());
11337 #endif /* NETCONN */
11339 if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
11341 #ifdef POSIX /* Easy in POSIX */
11344 debug(F111,"sndbrk POSIX",ckitoa(msec),(msec/375));
11346 x = tcsendbreak(ttyfd,msec / 375);
11347 debug(F111,"sndbrk tcsendbreak",ckitoa(errno),x);
11352 gtty(ttyfd,&ttbuf); /* Get current tty flags */
11353 spd = ttbuf.sg_ospeed; /* Save speed */
11354 ttbuf.sg_ospeed = B50; /* Change to 50 baud */
11355 stty(ttyfd,&ttbuf); /* ... */
11356 n = (int)strlen(brnuls); /* Send the right number of nulls */
11359 write(ttyfd,brnuls,n);
11360 ttbuf.sg_ospeed = spd; /* Restore speed */
11361 stty(ttyfd,&ttbuf); /* ... */
11365 sio_$control((short)ttyfd, sio_$send_break, msec, st);
11369 n = FWRITE; /* Flush output queue. */
11370 /* Watch out for int vs long problems in &n arg! */
11371 debug(F101,"sndbrk BSDBREAK","",msec);
11372 ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
11373 if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
11374 perror("Can't send BREAK");
11377 x = msleep(msec); /* Sleep for so many milliseconds */
11378 if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
11379 perror("BREAK stuck!!!");
11380 doexit(BAD_EXIT,-1); /* Get out, closing the line. */
11381 /* with bad exit status */
11387 No way to send a long BREAK in Sys V, so send a bunch of regular ones.
11388 (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
11389 but there's no way for this code to know for sure.)
11391 debug(F101,"sndbrk ATTSV","",msec);
11393 for (n = 0; n < x; n++) {
11394 /* Reportedly the cast breaks this function on some systems */
11395 /* But then why was it here in the first place? */
11396 if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
11397 perror("Can't send BREAK");
11404 debug(F101,"sndbrk V7","",msec);
11405 return(genbrk(ttyfd,250)); /* Simulate a BREAK */
11407 debug(F101,"sndbrk catchall","",msec);
11408 ttoc(0);ttoc(0);ttoc(0);ttoc(0);
11411 #endif /* BSDBREAK */
11414 #endif /* PROVX1 */
11419 /* T T S N D B -- Send a BREAK signal */
11424 if (netconn && istncomport())
11425 return((tnsndb(275L) >= 0) ? 0 : -1);
11427 #endif /* TN_COMPORT */
11428 return(sndbrk(275));
11431 /* T T S N D L B -- Send a Long BREAK signal */
11436 if (netconn && istncomport())
11437 return((tnsndb(1800L) >= 0) ? 0 : -1);
11439 #endif /* TN_COMPORT */
11440 return(sndbrk(1500));
11443 /* M S L E E P -- Millisecond version of sleep(). */
11446 Call with number of milliseconds (thousandths of seconds) to sleep.
11447 Intended only for small intervals. For big ones, just use sleep().
11448 Highly system-dependent.
11449 Returns 0 always, even if it didn't work.
11452 /* Define MSLFTIME for systems that must use an ftime() loop. */
11453 #ifdef ANYBSD /* For pre-4.2 BSD versions */
11457 #endif /* ANYBSD */
11459 #ifdef TOWER1 /* NCR Tower OS 1.0 */
11461 #endif /* TOWER1 */
11463 #ifdef COHERENT /* Coherent... */
11464 #ifndef _I386 /* Maybe Coherent/386 should get this, too */
11465 #define MSLFTIME /* Opinions are divided */
11467 #endif /* COHERENT */
11472 /* Millisecond timer */
11474 static long msecbase = 0L; /* Unsigned long not portable */
11477 getmsec() { /* Milliseconds since base time */
11479 struct timezone xz;
11486 gettimeofday(&tv, NULL)
11488 gettimeofday(&tv, &tz)
11490 #endif /* GTODONEARG */
11493 if (msecbase == 0L) { /* First call, set base time. */
11494 msecbase = tv.tv_sec;
11495 debug(F101,"getmsec base","",msecbase);
11497 return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
11499 #endif /* GETMSEC */
11500 #endif /* COMMENT */
11504 ttwait(fd, secs) int fd, secs; {
11512 if ((x = select(FD_SETSIZE,
11518 #endif /* HPUX1000 */
11522 debug(F101,"ttwait select errno","",errno);
11525 debug(F101,"ttwait OK","",errno);
11526 x = FD_ISSET(fd, &rfds);
11527 debug(F101,"ttwait select x","",x);
11531 #endif /* SELECT */
11536 Other possibilities here are:
11537 nanosleep(), reportedly defined in POSIX.4.
11538 sginap(), IRIX only (back to what IRIX version I don't know).
11545 #else /* BEOSORBEBOX */
11548 debug(F101,"msleep SELECT 1","",m);
11549 if (m <= 0) return(0);
11550 if (m >= 1000) { /* Catch big arguments. */
11553 if (m < 10) return(0);
11555 debug(F101,"msleep SELECT 2","",m);
11557 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
11558 debug(F101,"msleep BELLV10 select","",x);
11559 #else /* BELLV10 */
11561 gettimeofday(&tv, &tz);
11566 if (gettimeofday(&tv) < 0)
11569 if (gettimeofday(&tv,NULL) < 0)
11572 if (gettimeofday(&tv, NULL) < 0) /* wonder what this does... */
11574 if (gettimeofday(&tv, &tz) < 0)
11575 #endif /* NOTIMEZONE */
11577 #endif /* GTODONEARG */
11579 t1 = tv.tv_sec; /* Seconds */
11580 #endif /* COHERENT */
11582 tv.tv_sec = 0; /* Use select() */
11583 tv.tv_usec = m * 1000L;
11585 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11586 debug(F101,"msleep BSD44 select","",x);
11589 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11590 debug(F101,"msleep __linux__ select","",x);
11591 #else /* __linux__ */
11593 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11594 debug(F101,"msleep BSD43 select","",x);
11597 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11598 debug(F101,"msleep QNX6 select","",x);
11601 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11602 debug(F101,"msleep QNX select","",x);
11605 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11606 debug(F101,"msleep COHERENT select","",x);
11607 #else /* COHERENT */
11608 #ifdef HPUX1000 /* 10.00 only, not 10.10 or later */
11609 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11610 debug(F101,"msleep HP-UX 10.00 select","",x);
11611 #else /* HPUX1000 */
11613 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11614 debug(F101,"msleep SVR4 select","",x);
11617 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11618 debug(F101,"msleep OSF40 select","",x);
11621 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11622 debug(F101,"msleep OSF40 select","",x);
11624 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11625 debug(F101,"msleep catch-all select","",x);
11628 #endif /* HP1000 */
11630 #endif /* COHERENT */
11634 #endif /* __linux__ */
11636 #endif /* BELLV10 */
11639 #else /* Not SELECT */
11640 #ifdef CK_POLL /* We have poll() */
11641 struct pollfd pfd; /* Supply a valid address for poll() */
11643 #ifdef ODT30 /* But in SCO ODT 3.0 */
11644 #ifdef NAP /* we should use nap() instead */
11645 debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
11646 nap((long)m); /* seems to break dialing. */
11649 debug(F101,"msleep ODT 3.0 POLL","",m);
11654 debug(F101,"msleep POLL","",m);
11660 We could handle the above more cleanly by just letting nap() always
11661 take precedence over poll() in this routine, but there is no way to know
11662 whether that would break something else.
11665 #else /* Not POLL */
11668 "This routine is implemented using setitimer(2); it requires eight
11669 system calls...". In other words, it might take 5 minutes to sleep
11672 debug(F101,"msleep USLEEP","",m);
11673 if (m >= 1000) { /* Catch big arguments. */
11676 if (m < 10) return(0);
11678 usleep((unsigned int)(m * 1000));
11683 debug(F101,"msleep aegis","",m);
11685 dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */
11686 time_$wait(time_$relative, dur, st);
11690 debug(F101,"msleep Venix","",m);
11691 if (m <= 0) return(0);
11692 sleep(-((m * 60 + 500) / 1000));
11696 debug(F101,"msleep NAP","",m);
11702 extern long times(); /* Or #include <times.h> ? */
11704 long t1, t2, tarray[4];
11706 char *cp = getenv("HZ");
11710 if (cp && (hertz = atoi(cp))) {
11711 CLOCK_TICK = 1000 / hertz;
11712 } else { /* probably single user mode */
11714 CLOCK_TICK = 1000 / HZ;
11717 /* HZ always exists in, for instance, SCO Xenix, so you don't have to
11718 * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
11719 * have Xenix, you have should have nap(), so the best is to use -DNAP
11720 * in the makefile. Most systems have HZ.
11722 CLOCK_TICK = 17; /* 1/60 sec */
11724 printf("warning: environment variable HZ bad... using HZ=%d\r\n",
11725 1000 / CLOCK_TICK);
11730 debug(F101,"msleep ATTSV","",m);
11731 if (m <= 0) return(0);
11732 if (m >= 1000) { /* Catch big arguments. */
11735 if (m < 10) return(0);
11737 if ((t1 = times(tarray)) < 0) return(-1);
11739 if ((t2 = times(tarray)) < 0) return(-1);
11740 t3 = ((int)(t2 - t1)) * CLOCK_TICK;
11741 if (t3 > m) return(t3);
11743 #else /* Not ATTSV */
11744 #ifdef MSLFTIME /* Use ftime() loop... */
11746 debug(F101,"msleep MSLFTIME","",m);
11747 if (m <= 0) return(0);
11748 if (m >= 1000) { /* Catch big arguments. */
11751 if (m < 10) return(0);
11754 ftime(&ftp); /* void ftime() in QNX */
11756 if (ftime(&ftp) < 0) return(-1); /* Get base time. */
11758 t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
11760 ftime(&ftp); /* Get current time and compare. */
11761 t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
11762 if (t3 > m) return(0);
11765 /* This includes true POSIX, which has no way to do this. */
11766 debug(F101,"msleep busy loop","",m);
11767 if (m >= 1000) { /* Catch big arguments. */
11770 if (m < 10) return(0);
11772 if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */
11774 #endif /* MSLFTIME */
11777 #endif /* PROVX1 */
11779 #endif /* CK_POLL */
11780 #endif /* SELECT */
11781 #endif /* BEOSORBEBOX */
11782 #endif /* USLEEP */
11786 /* R T I M E R -- Reset elapsed time counter */
11790 tcount = time( (time_t *) 0 );
11794 /* G T I M E R -- Get current value of elapsed time counter in seconds */
11799 x = (int) (time( (time_t *) 0 ) - tcount);
11800 debug(F101,"gtimer","",x);
11801 return( (x < 0) ? 0 : x );
11806 Floating-point timers. Require not only floating point support, but
11807 also gettimeofday().
11809 static struct timeval tzero;
11813 #ifdef GTODONEARG /* Account for Mot's definition */
11814 (VOID) gettimeofday(&tzero);
11816 (VOID) gettimeofday(&tzero, (struct timezone *)0);
11817 #endif /* GTODONEARG */
11822 struct timeval tnow, tdelta;
11827 #ifdef GTODONEARG /* Account for Mot's definition */
11828 (VOID) gettimeofday(&tnow);
11830 (VOID) gettimeofday(&tnow, (struct timezone *)0);
11831 #endif /* GTODONEARG */
11833 tdelta.tv_sec = tnow.tv_sec - tzero.tv_sec;
11834 tdelta.tv_usec = tnow.tv_usec - tzero.tv_usec;
11836 if (tdelta.tv_usec < 0) {
11838 tdelta.tv_usec += 1000000;
11840 s = (CKFLOAT) tdelta.tv_sec + ((CKFLOAT) tdelta.tv_usec / 1000000.0);
11845 sprintf(fpbuf,"%f",s);
11846 debug(F110,"gftimer",fpbuf,0);
11851 #endif /* GFTIMER */
11853 /* Z T I M E -- Return asctime()-format date/time string */
11855 NOTE: as a side effect of calling this routine, we can also set the
11856 following two variables, giving the micro- and milliseconds (fractions of
11857 seconds) of the clock time. Currently this is done only in BSD-based builds
11858 that use gettimeofday(). When these variables are not filled in, they are
11859 left with a value of -1L.
11861 static char asctmbuf[64];
11864 ztime(s) char **s; {
11868 The gettimeofday() method, which also sets ztmsec and ztusec, works for
11869 all GFTIMER builds. NOTE: ztmsec and ztusec are defined in ckcmai.c,
11870 and extern declarations for them are in ckcdeb.h; thus they are
11871 declared in this file by inclusion of ckcdeb.h.
11874 struct tm *localtime();
11880 debug(F100,"ztime s==NULL","",0);
11883 /* No 2nd arg in Motorola SV88 and some others */
11884 if (gettimeofday(&tv) > -1)
11888 if (gettimeofday(&tv,NULL) > -1)
11891 if (gettimeofday(&tv, NULL) > -1) /* wonder what this does... */
11893 if (gettimeofday(&tv, &tz) > -1)
11894 #endif /* NOTIMEZONE */
11896 #endif /* COHERENT */
11897 #endif /* GTODONEARG */
11898 { /* Fill in tm struct */
11899 ztusec = tv.tv_usec; /* Microseconds */
11900 ztmsec = ztusec / 1000L; /* Milliseconds */
11905 tp = localtime(&zz); /* Convert to local time */
11912 tp = localtime(&zz);
11916 { /* avoid unaligned access trap on 64-bit platforms */
11919 tp = localtime(&zz);
11923 tp = localtime((time_t *)&tv.tv_sec); /* Convert to local time */
11925 tp = localtime(&tv.tv_sec);
11926 #endif /* MACOSX */
11928 #endif /* HPUX1000 */
11932 s2 = asctime(tp); /* Convert result to ASCII string */
11933 asctmbuf[0] = '\0';
11934 if (s2) ckstrncpy(asctmbuf,s2,64);
11936 debug(F111,"ztime GFTIMER gettimeofday",*s,ztusec);
11939 #else /* Not GFTIMER */
11941 #undef ZTIMEV7 /* Which systems need to use */
11942 #ifdef COHERENT /* old UNIX Version 7 way... */
11944 #endif /* COHERENT */
11947 #endif /* TOWER1 */
11952 #endif /* ANYBSD */
11964 Prototypes are in <time.h>, included above.
11966 time_t clock_storage;
11967 clock_storage = time((void *) 0);
11969 *s = ctime(&clock_storage);
11970 debug(F110,"ztime: HPUX 10.20",*s,0);
11973 #ifdef ATTSV /* AT&T way */
11974 /* extern long time(); */ /* Theoretically these should */
11975 char *ctime(); /* already been dcl'd in <time.h> */
11976 time_t clock_storage;
11977 clock_storage = time(
11986 #endif /* IRIX60 */
11989 *s = ctime( &clock_storage );
11990 debug(F110,"ztime: ATTSV",*s,0);
11993 #ifdef PROVX1 /* Venix 1.0 way */
11998 debug(F110,"ztime: PROVX1",*s,0);
12001 #ifdef BSD42 /* 4.2BSD way */
12003 struct tm *localtime();
12005 gettimeofday(&tv, &tz);
12006 ztusec = tv.tv_usec;
12007 ztmsec = tv.tv_usec / 1000L;
12008 tp = localtime(&tv.tv_sec);
12011 debug(F111,"ztime: BSD42",*s,ztusec);
12014 #ifdef MINIX /* MINIX way */
12016 extern long time(); /* Already got these from <time.h> */
12017 extern char *ctime();
12018 #endif /* COMMENT */
12023 debug(F110,"ztime: MINIX",*s,0);
12026 #ifdef ZTIMEV7 /* The regular way */
12028 struct tm *localtime();
12030 long xclock; /* or unsigned long for BeBox? */
12032 tp = localtime(&xclock);
12035 debug(F110,"ztime: ZTIMEV7",*s,0);
12037 #else /* Catch-all for others... */
12039 *s = "Day Mon 00 00:00:00 0000\n"; /* Dummy in asctime() format */
12040 debug(F110,"ztime: catch-all",*s,0);
12042 #endif /* ZTIMEV7 */
12045 #endif /* PROVX1 */
12047 #endif /* HPUX1020 */
12048 #endif /* GFTIMER */
12051 /* C O N G M -- Get console terminal modes. */
12054 Saves initial console mode, and establishes variables for switching
12055 between current (presumably normal) mode and other modes.
12056 Should be called when program starts, but only after establishing
12057 whether program is in the foreground or background.
12058 Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
12063 if (backgrd || !isatty(0)) { /* If in background. */
12064 cgmf = -1; /* Don't bother, modes are garbage. */
12067 if (cgmf > 0) return(0); /* Already did this. */
12068 debug(F100,"congm getting modes","",0); /* Need to do it. */
12070 ios_$inq_type_uid(ios_$stdin, conuid, st);
12071 if (st.all != status_$ok) {
12072 fprintf(stderr, "problem getting stdin objtype: ");
12075 concrp = (conuid == mbx_$uid);
12080 if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */
12082 fprintf(stderr,"Error opening %s\n", CTTNAM);
12087 #endif /* COMMENT */
12091 #endif /* !BEBOX */
12092 #ifdef BSD44ORPOSIX
12093 if (tcgetattr(fd,&ccold) < 0) return(-1);
12094 if (tcgetattr(fd,&cccbrk) < 0) return(-1);
12095 if (tcgetattr(fd,&ccraw) < 0) return(-1);
12098 if (ioctl(fd,TCGETA,&ccold) < 0) return(-1);
12099 if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
12100 if (ioctl(fd,TCGETA,&ccraw) < 0) return(-1);
12102 cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
12103 if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
12104 ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
12105 if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
12109 if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
12110 if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
12111 if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
12112 debug(F101,"cccbrk.sg_flags orig","", cccbrk.sg_flags);
12114 if (gtty(fd,&ccold) < 0) return(-1);
12115 if (gtty(fd,&cccbrk) < 0) return(-1);
12116 if (gtty(fd,&ccraw) < 0) return(-1);
12117 #endif /* BELLV10 */
12119 #endif /* BSD44ORPOSIX */
12120 #ifdef sony_news /* Sony NEWS */
12121 if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
12122 perror("congm error getting Kanji mode");
12123 debug(F101,"congm error getting Kanji mode","",0);
12124 km_con = -1; /* Make sure this stays undefined. */
12127 #endif /* sony_news */
12130 cgmf = 1; /* Flag that we got them. */
12136 congetbuf(x) int x; {
12138 n = CONBUFSIZ - (conbufp - conbuf); /* How much room left in buffer? */
12140 debug(F101,"congetbuf char loss","",x-n);
12143 x = read(0,conbufp,x);
12145 debug(F111,"congetbuf readahead",conbuf,x);
12149 /* C O N C B -- Put console in cbreak mode. */
12151 /* Returns 0 if ok, -1 if not */
12157 concb(esc) char esc;
12158 #endif /* CK_ANSIC */
12161 debug(F101,"concb constate","",constate);
12162 debug(F101,"concb cgmf","",cgmf);
12163 debug(F101,"concb backgrd","",backgrd);
12165 if (constate == CON_CB)
12168 if (cgmf < 1) /* Did we get console modes yet? */
12169 if (!backgrd) /* No, in background? */
12170 congm(); /* No, try to get them now. */
12171 if (cgmf < 1) /* Still don't have them? */
12172 return(0); /* Give up. */
12173 debug(F101,"concb ttyfd","",ttyfd);
12174 debug(F101,"concb ttfdflg","",ttfdflg);
12176 /* This breaks returning to prompt after protocol with "-l 0" */
12177 /* Commented out July 1998 */
12178 if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
12180 #endif /* COMMENT */
12182 debug(F101,"concb isatty","",x);
12183 if (!x) return(0); /* Only when running on real ttys */
12184 debug(F101,"concb xsuspend","",xsuspend);
12185 if (backgrd) /* Do nothing if in background. */
12187 escchr = esc; /* Make this available to other fns */
12188 ckxech = 1; /* Program can echo characters */
12191 if (concrp) return(write(1, "\035\002", 2));
12192 if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
12197 #endif /* COHERENT */
12202 #ifndef SVORPOSIX /* BSD, V7, etc */
12203 debug(F101,"cccbrk.sg_flags concb 1","", cccbrk.sg_flags);
12204 debug(F101,"concb stty CBREAK","",0);
12205 cccbrk.sg_flags |= (CBREAK|CRMOD); /* Set to character wakeup, */
12206 cccbrk.sg_flags &= ~ECHO; /* no echo. */
12207 debug(F101,"cccbrk.sg_flags concb 2","", cccbrk.sg_flags);
12210 BSD stty() clears the console buffer. So if anything is waiting in it,
12211 we have to read it now to avoid losing it.
12218 x = ioctl(0,TIOCSETP,&cccbrk);
12220 x = stty(0,&cccbrk);
12221 debug(F101,"cccbrk.sg_flags concb x","", x);
12222 #endif /* BELLV10 */
12223 #else /* Sys V and POSIX */
12225 debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
12227 /* Don't mess with IEXTEN */
12228 cccbrk.c_lflag &= ~(ICANON|ECHO);
12231 cccbrk.c_lflag &= ~(ICANON|ECHO);
12233 cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
12234 #endif /* COHERENT */
12236 cccbrk.c_lflag |= ISIG; /* Allow signals in command mode. */
12237 cccbrk.c_iflag |= IGNBRK; /* But ignore BREAK signal */
12238 cccbrk.c_iflag &= ~BRKINT;
12241 debug(F100,"concb OXOS is defined","",0);
12242 cccbrk.c_lflag &= ~(ICANON|ECHO);
12243 cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
12247 Believe it or not, in SCO UNIX, VSUSP is greater than NCC, and so this
12248 array reference is out of bounds. It's only a debug() call so who needs it.
12251 debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
12253 #endif /* COMMENT */
12255 debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
12256 cccbrk.c_cc[0] = 003; /* Interrupt char is Control-C */
12258 debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
12259 cccbrk.c_cc[VINTR] = 003;
12262 cccbrk.c_cc[1] = escchr; /* escape during packet modes */
12264 cccbrk.c_cc[VQUIT] = escchr;
12267 cccbrk.c_cc[4] = 1;
12271 cccbrk.c_cc[VMIN] = 1;
12278 cccbrk.c_cc[5] = 0;
12281 cccbrk.c_cc[5] = 1;
12285 cccbrk.c_cc[VTIME] = 1;
12293 #ifdef BSD44ORPOSIX /* Set new modes */
12294 x = tcsetattr(0,TCSADRAIN,&cccbrk);
12295 #else /* ATTSV */ /* or the POSIX way */
12296 x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */
12297 #endif /* BSD44ORPOSIX */
12298 #endif /* SVORPOSIX */
12302 #endif /* COHERENT */
12304 debug(F101,"concb x","",x);
12305 debug(F101,"concb errno","",errno);
12309 if (kmem[CON] < 0) {
12310 qaddr[CON] = initrawq(0);
12311 if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
12312 fprintf(stderr, "Can't read /dev/kmem in concb.\n");
12313 perror("/dev/kmem");
12324 debug(F101,"concb returns","",x);
12328 /* C O N B I N -- Put console in binary mode */
12330 /* Returns 0 if ok, -1 if not */
12336 conbin(esc) char esc;
12337 #endif /* CK_ANSIC */
12342 debug(F101,"conbin constate","",constate);
12344 if (constate == CON_BIN)
12347 if (!isatty(0)) return(0); /* only for real ttys */
12348 congm(); /* Get modes if necessary. */
12349 debug(F100,"conbin","",0);
12350 escchr = esc; /* Make this available to other fns */
12351 ckxech = 1; /* Program can echo characters */
12354 if (concrp) return(write(1, "\035\002", 2));
12355 if (conuid == input_pad_$uid) {
12356 pad_$raw(ios_$stdin, st);
12363 #endif /* COHERENT */
12371 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12374 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12376 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
12377 #endif /* COHERENT */
12380 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12381 ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
12383 ccraw.c_iflag |= IGNPAR;
12385 Note that for terminal sessions we disable Xon/Xoff flow control to allow
12386 the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
12387 transfers to work when C-Kermit is in the middle, etc. Hardware flow
12388 control, if in use, is not affected.
12392 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
12395 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
12399 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
12401 ccraw.c_oflag &= ~OPOST;
12404 WHAT THE HECK WAS THIS FOR?
12405 The B9600 setting (obviously) prevents CONNECT from working at any
12406 speed other than 9600 when you are logged in to the 7300 on a serial
12407 line. Maybe some of the other flags are necessary -- if so, put back
12408 the ones that are needed. This code is supposed to work the same, no
12409 matter whether you are logged in to the 7300 on the real console device,
12410 or through a serial port.
12413 ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
12414 #endif /* ATT7300 */
12415 #endif /* COMMENT */
12417 /*** Kermit used to put the console in 8-bit raw mode, but some users have
12418 *** pointed out that this should not be done, since some sites actually
12419 *** use terminals with parity settings on their Unix systems, and if we
12420 *** override the current settings and stop doing parity, then their terminals
12421 *** will display blotches for characters whose parity is wrong. Therefore,
12422 *** the following two lines are commented out (Larry Afrin, Clemson U):
12424 *** ccraw.c_cflag &= ~(PARENB|CSIZE);
12425 *** ccraw.c_cflag |= (CS8|CREAD);
12427 *** Sys III/V sites that have trouble with this can restore these lines.
12430 ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */
12432 ccraw.c_cc[VINTR] = 003;
12435 ccraw.c_cc[1] = escchr; /* Escape during packet mode */
12437 ccraw.c_cc[VQUIT] = escchr;
12444 ccraw.c_cc[VMIN] = 1;
12459 ccraw.c_cc[VTIME] = 1;
12467 #ifdef BSD44ORPOSIX
12468 x = tcsetattr(0,TCSADRAIN,&ccraw); /* Set new modes. */
12470 x = ioctl(0,TCSETAW,&ccraw);
12471 #endif /* BSD44ORPOSIX */
12472 #else /* Berkeley, etc. */
12473 x = conchk(); /* Because stty() is destructive */
12476 ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF (ha) */
12477 ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
12479 x = ioctl(0,TIOCSETP,&ccraw);
12481 x = stty(0,&ccraw);
12482 #endif /* BELLV10 */
12483 #endif /* SVORPOSIX */
12487 constate = CON_BIN;
12489 debug(F101,"conbin returns","",x);
12494 #endif /* COHERENT */
12499 /* C O N R E S -- Restore the console terminal */
12504 debug(F101,"conres cgmf","",cgmf);
12505 debug(F101,"conres constate","",constate);
12507 if (cgmf < 1) /* Do nothing if modes unchanged */
12509 if (constate == CON_RES)
12512 if (!isatty(0)) return(0); /* only for real ttys */
12513 debug(F100,"conres isatty ok","",0);
12514 ckxech = 0; /* System should echo chars */
12518 if (concrp) return(write(1, "\035\001", 2));
12519 if (conuid == input_pad_$uid) {
12520 pad_$cooked(ios_$stdin, st);
12521 constate = CON_RES;
12529 #ifdef BSD44ORPOSIX
12530 debug(F100,"conres restoring tcsetattr","",0);
12531 x = tcsetattr(0,TCSADRAIN,&ccold);
12534 debug(F100,"conres restoring ioctl","",0);
12535 x = ioctl(0,TCSETAW,&ccold);
12536 #else /* BSD, V7, and friends */
12537 #ifdef sony_news /* Sony NEWS */
12539 ioctl(0,TIOCKSET,&km_con); /* Restore console Kanji mode */
12540 #endif /* sony_news */
12542 debug(F100,"conres restoring stty","",0);
12543 x = conchk(); /* Because stty() is destructive */
12547 x = ioctl(0,TIOCSETP,&ccold);
12549 x = stty(0,&ccold);
12550 #endif /* BELLV10 */
12552 #endif /* BSD44ORPOSIX */
12555 constate = CON_RES;
12557 debug(F101,"conres returns","",x);
12561 /* C O N O C -- Output a character to the console terminal */
12568 #endif /* CK_ANSIC */
12572 if (inserver && !local)
12575 #ifdef CK_ENCRYPTION
12576 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12577 ck_tn_encrypt(&c,1);
12578 #endif /* CK_ENCRYPTION */
12582 return conwrite(&c,1);
12584 return(write(1,&c,1));
12588 /* C O N X O -- Write x characters to the console terminal */
12591 conxo(x,s) int x; char *s; {
12594 if (inserver && !local)
12595 return(ttol((CHAR *)s,x));
12597 #ifdef CK_ENCRYPTION
12598 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12599 ck_tn_encrypt(s,x);
12600 #endif /* CK_ENCRYPTION */
12604 return(conwrite(s,x));
12606 return(write(1,s,x));
12610 /* C O N O L -- Write a line to the console terminal */
12613 conol(s) char *s; {
12615 if (!s) s = ""; /* Always do this! */
12621 if (inserver && !local)
12622 return(ttol((CHAR *)s,len));
12624 #ifdef CK_ENCRYPTION
12625 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION)) {
12626 if (nxpacket < len) {
12632 len = len > 10240 ? len : 10240;
12633 xpacket = (CHAR *)malloc(len);
12635 fprintf(stderr,"ttol malloc failure\n");
12640 memcpy(xpacket,s,len);
12641 s = (char *)xpacket;
12642 ck_tn_encrypt(s,len);
12644 #endif /* CK_ENCRYPTION */
12648 return(conwrite(s,len));
12650 return(write(1,s,len));
12654 /* C O N O L A -- Write an array of lines to the console terminal */
12657 conola(s) char *s[]; {
12663 for (i = 0; ; i++) {
12665 if (!p) p = ""; /* Let's not dump core shall we? */
12669 if (inserver && !local)
12670 x = ttol((CHAR *)p,(int)strlen(p));
12680 /* C O N O L L -- Output a string followed by CRLF */
12683 conoll(s) char *s; {
12691 if (inserver && !local) {
12692 if (*s) ttol((CHAR *)s,(int)strlen(s));
12693 return(ttol(buf,2));
12699 #ifdef CK_ENCRYPTION
12700 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12701 ck_tn_encrypt((char *)buf,2);
12702 #endif /* CK_ENCRYPTION */
12706 return(conwrite(buf, 2));
12708 return(write(1,buf,2));
12712 /* C O N C H K -- Return how many characters available at console */
12714 We could also use select() here to cover a few more systems that are not
12715 covered by any of the following, e.g. HP-UX 9.0x on the model 800.
12719 static int contyp = 0; /* +1 for isatty, -1 otherwise */
12721 if (contyp == 0) /* This prevents unnecessary */
12722 contyp = (isatty(0) ? 1 : -1); /* duplicated calls to isatty() */
12723 debug(F101,"conchk contyp","",contyp);
12724 if (backgrd || (contyp < 0))
12728 if (conbufn > 0) return(conbufn); /* use old count if nonzero */
12730 /* read in more characters */
12731 conbufn = ios_$get(ios_$stdin,
12732 ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
12733 if (st.all != status_$ok) conbufn = 0;
12738 if (inserver && !local)
12739 return(in_chk(1,ttyfd));
12742 return(in_chk(0,0));
12746 /* C O N I N C -- Get a character from the console */
12748 Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
12749 read. Upon success, returns the character. Upon failure, returns -1.
12750 A timed read that does not complete within the timeout period returns -2.
12753 coninc(timo) int timo; {
12754 int n = 0; CHAR ch;
12757 if (conbufn > 0) { /* If something already buffered */
12759 return((unsigned)(*conbufp++ & 0xff));
12762 errno = 0; /* Clear this */
12764 if (inserver && !local) {
12767 return(ttinctimo ? -2 : -1);
12773 #ifdef aegis /* Apollo Aegis only... */
12774 debug(F101,"coninc timo","",timo);
12776 if (conchk() > 0) {
12778 return((unsigned)(*conbufp++ & 0xff));
12790 debug(F111,"ttinc","ttpush",ttpush);
12796 if (le_getchar(&ch) > 0) {
12797 debug(F111,"ttinc LocalEchoInBuf","ch",ch);
12802 #endif /* TTLEBUF */
12804 if (timo <= 0) { /* Untimed, blocking read. */
12805 while (1) { /* Keep trying till we get one. */
12806 n = read(0, &ch, 1); /* Read a character. */
12807 if (n == 0) continue; /* Shouldn't happen. */
12808 if (n > 0) { /* If read was successful, */
12810 #ifdef CK_ENCRYPTION
12811 debug(F100,"coninc decrypt 1","",0);
12812 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12813 ck_tn_decrypt((char *)&ch,1);
12814 #endif /* CK_ENCRYPTION */
12816 return((unsigned)(ch & 0xff)); /* return the character. */
12819 /* Come here if read() returned an error. */
12821 debug(F101, "coninc(0) errno","",errno); /* Log the error. */
12824 #ifdef CIE /* CIE Regulus has no EINTR symbol? */
12830 This routine is used for several different purposes. In CONNECT mode, it is
12831 used to do an untimed, blocking read from the keyboard in the lower CONNECT
12832 fork. During local-mode file transfer, it reads a character from the
12833 console to interrupt the file transfer (like A for a status report, X to
12834 cancel a file, etc). Obviously, we don't want the reads in the latter case
12835 to be blocking, or the file transfer would stop until the user typed
12836 something. Unfortunately, System V does not allow the console device input
12837 buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
12838 used instead. During local-mode file transfer, the SIGQUIT signal is armed
12839 and trapped by esctrp(), and this routine pretends to have read the quit
12840 character from the keyboard normally. But, kludge or no kludge, the read()
12841 issued by this command, under System V only, can fail if a signal -- ANY
12842 signal -- is caught while the read is pending. This can occur not only when
12843 the user types the quit character, but also during telnet negotiations, when
12844 the lower CONNECT fork signals the upper one about an echoing mode change.
12845 When this happens, we have to post the read() again. This is apparently not
12846 a problem in BSD-based UNIX versions.
12848 if (errno == EINTR) /* Read interrupted. */
12849 if (conesc) { /* If by SIGQUIT, */
12850 conesc = 0; /* the conesc variable is set, */
12851 return(escchr); /* so return the escape character. */
12852 } else continue; /* By other signal, try again. */
12855 This might be dangerous, but let's do this on non-System V versions too,
12856 since at least one SunOS 4.1.2 user complains of immediate disconnections
12857 upon first making a TELNET connection.
12859 if (errno == EINTR) /* Read interrupted. */
12861 #endif /* SVORPOSIX */
12863 if (errno == EINTR) /* Read interrupted. */
12866 return(-1); /* Error */
12870 if (deblog && timo <= 0) {
12871 debug(F100,"coninc timeout logic error","",0);
12876 /* Timed read... */
12878 saval = signal(SIGALRM,timerh); /* Set up timeout handler. */
12879 xx = alarm(timo); /* Set the alarm. */
12880 debug(F101,"coninc alarm set","",timo);
12882 #ifdef CK_POSIX_SIG
12886 #endif /* CK_POSIX_SIG */
12887 ) /* The read() timed out. */
12888 n = -2; /* Code for timeout. */
12890 n = read(0, &ch, 1);
12891 ttimoff(); /* Turn off timer */
12892 if (n > 0) { /* Got character OK. */
12894 #ifdef CK_ENCRYPTION
12895 debug(F100,"coninc decrypt 2","",0);
12896 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12897 ck_tn_decrypt((char *)&ch,1);
12898 #endif /* CK_ENCRYPTION */
12900 return((unsigned)(ch & 0xff)); /* Return it. */
12903 read() returned an error. Same deal as above, but without the loop.
12905 debug(F101, "coninc(timo) n","",n);
12906 debug(F101, "coninc(timo) errno","",errno);
12909 if (n == -1 && errno == EINTR && conesc != 0) {
12911 return(escchr); /* User entered escape character. */
12913 #endif /* SVORPOSIX */
12914 if (n == 0 && errno > 0) { /* It's an error */
12917 #endif /* ! OXOS */
12921 /* C O N G K S -- Console Get Keyboard Scancode */
12925 This function needs to be filled in with the various system-dependent
12926 system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
12927 keyboard scan code. Unfortunately there aren't any.
12930 congks(timo) int timo; {
12933 if (inserver && !local)
12934 return(ttinc(timo));
12937 return(coninc(timo));
12939 #endif /* congks */
12943 /* A T T D I A L -- Dial up the remote system using internal modem
12944 * Purpose: to open and dial a number on the internal modem available on the
12945 * ATT7300 UNIX PC. Written by Joe Doupnik. Superceeds version written by
12946 * Richard E. Hill, Dickinson, TX. which employed dial(3c).
12947 * Uses information in <sys/phone.h> and our status int attmodem.
12949 attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
12952 attmodem &= ~ISMODEM; /* modem not in use yet */
12953 /* Ensure O_NDELAY is set, else i/o traffic hangs */
12954 /* We turn this flag off once the dial is complete */
12955 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
12957 /* Condition line, check availability & DATA mode, turn on speaker */
12958 if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
12959 printf("cannot access phone\n");
12963 ioctl(ttyfd,PIOCGETP,&dialer); /* get phone dialer parameters */
12965 if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */
12966 printf(" Should not dial with modem in VOICE mode.\n");
12967 printf(" Exit Kermit, switch to DATA and retry call.\n");
12971 #ifdef ATTTONED /* Old way, tone dialing only. */
12972 dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */
12973 dialer.c_lineparam &= ~PULSE; /* not with pulses. */
12975 /* Leave current pulse/tone state alone. */
12976 /* But what about DATA? Add it back if you have trouble. */
12977 /* sys/phone says you get DATA automatically by opening device RDWR */
12979 dialer.c_waitdialtone = 5; /* wait 5 sec for dialtone */
12981 dialer.c_feedback = SPEAKERON|NORMSPK|RINGON; /* control speaker */
12983 /* sys/phone says RINGON used only for incoming voice calls */
12984 dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
12985 dialer.c_feedback |= SPEAKERON|NORMSPK;
12987 dialer.c_waitflash = 500; /* 0.5 sec flash hook */
12988 if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) { /* set phone parameters */
12989 printf("Cannot set modem characteristics\n");
12993 ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */
12996 fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
12997 line_status:%o feedback:%o\n",
12998 dialer.c_lineparam, dialer.c_waitdialtone,
12999 dialer.c_linestatus, dialer.c_feedback);
13002 attmodem |= ISMODEM; /* modem is now in-use */
13004 for (telnum = telnbr; *telnum != '\0'; telnum++) /* dial number */
13006 /* Tone dialing only */
13007 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13008 perror("Error in dialing");
13012 #else /* Allow Pulse or Tone dialing */
13014 case 't': case 'T': case '%': /* Tone dialing requested */
13015 dialer.c_lineparam |= DTMF;
13016 dialer.c_lineparam &= ~PULSE;
13017 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13018 printf("Cannot set modem to tone dialing\n");
13023 case 'd': case 'D': case 'p': case 'P': case '^':
13024 dialer.c_lineparam |= PULSE;
13025 dialer.c_lineparam &= ~DTMF;
13026 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
13027 printf("Cannot set modem to pulse dialing\n");
13033 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
13034 perror("Dialing error");
13042 ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */
13043 do { /* wait for modems to Connect */
13044 if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */
13045 perror("Cannot get modems to connect");
13049 } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
13050 /* Turn off O_NDELAY flag now. */
13051 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
13052 signal(SIGHUP, sighup); /* hangup on loss of carrier */
13053 return(0); /* return success */
13057 Offgetty, ongetty functions. These function get the 'getty(1m)' off
13058 and restore it to the indicated line. Shell's return codes are:
13059 0: Can't do it. Probably a user logged on.
13060 1: No need. No getty on that line.
13061 2: Done, you should restore the getty when you're done.
13062 DOGETY System(3), however, returns them as 0, 256, 512, respectively.
13063 Thanks to Kevin O'Gorman, Anarm Software Systems.
13065 getoff.sh looks like: geton.sh looks like:
13066 setgetty $1 0 setgetty $1 1
13072 /* O F F G E T T Y -- Turn off getty(1m) for the communications tty line
13073 * and get status so it can be restarted after the line is hung up.
13076 offgetty(ttname) char *ttname; {
13078 while (*ttname != '\0') ttname++; /* seek terminator of path */
13079 ttname -= 3; /* get last 3 chars of name */
13080 sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
13081 return(zsyscmd(temp));
13084 /* O N G E T T Y -- Turn on getty(1m) for the communications tty line */
13087 ongetty(ttname) char *ttname; {
13089 while (*ttname != '\0') ttname++; /* comms tty path name */
13091 sprintf(temp,"/usr/bin/geton.sh %s",ttname);
13092 return(zsyscmd(temp));
13094 #endif /* ATT7300 */
13096 /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
13098 * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
13099 * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
13100 * 2 = Auto: For "modem direct": The same as "Off".
13101 * For real modem types: Heed carrier during connect, but ignore
13102 * it anytime else. Compatible with pre-5A C-Kermit versions.
13104 * As you can see, this setting does not affect dialing, which always ignores
13105 * carrier (unless there is some special exception for some modem type). It
13106 * does affect ttopen() if it is set before ttopen() is used. This setting
13107 * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
13108 * (or should be) always called before any communications is tried, which
13109 * means that, practically speaking, the effect is immediate.
13111 * Of course, nothing of this applies to remote mode (xlocal = 0).
13113 * Someone has yet to uncover how to manipulate the carrier in the BSD
13114 * environment (or any non-termio using environment). Until that time, this
13115 * will simply be a no-op for BSD.
13117 * Note that in previous versions, the carrier was most often left unchanged
13118 * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX. This
13119 * has changed. Now it is controlled by ttcarr in conjunction with these
13123 ttscarr(carrier) int carrier; {
13125 debug(F101, "ttscarr","",ttcarr);
13129 /* C A R R C T L -- Set tty modes for carrier treatment.
13131 * Sets the appropriate bits in a termio or sgttyb struct for carrier control
13132 * (actually, there are no bits in sgttyb for that), or performs any other
13133 * operations needed to control this on the current system. The function does
13134 * not do the actual TCSETA or stty, since often we want to set other bits too
13135 * first. Don't call this function when xlocal is 0, or the tty is not opened.
13137 * We don't know how to do anything like carrier control on non-ATTSV systems,
13138 * except, apparently, ultrix. See above. It is also known that this doesn't
13139 * have much effect on a Xenix system. For Xenix, one should switch back and
13140 * forth between the upper and lower case device files. Maybe later.
13141 * Presently, Xenix will stick to the mode it was opened with.
13143 * carrier: 0 = ignore carrier, 1 = require carrier.
13144 * The current state is saved in curcarr, and checked to save labour.
13148 #ifdef BSD44ORPOSIX
13149 carrctl(ttpar, carrier) struct termios *ttpar; int carrier;
13151 carrctl(ttpar, carrier) struct termio *ttpar; int carrier;
13152 #endif /* BSD44ORPOSIX */
13154 debug(F101, "carrctl","",carrier);
13156 ttpar->c_cflag &= ~CLOCAL;
13158 ttpar->c_cflag |= CLOCAL;
13161 #else /* Berkeley, V7, et al... */
13163 carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
13164 debug(F101, "carrctl","",carrier);
13165 if (carrier == curcarr)
13171 Old code from somebody at DEC that tends to get stuck, time out, etc.
13174 ioctl(ttyfd, TIOCMODEM, &temp);
13175 ioctl(ttyfd, TIOCHPCL, 0);
13177 /* (According to the manuals, TIOCNCAR should be preferred */
13178 /* over TIOCNMODEM...) */
13179 ioctl(ttyfd, TIOCNMODEM, &temp);
13183 New code from Jamie Watson that, he says, eliminates the problems.
13186 ioctl(ttyfd, TIOCCAR);
13187 ioctl(ttyfd, TIOCHPCL);
13189 ioctl(ttyfd, TIOCNCAR);
13191 #endif /* COMMENT */
13192 #endif /* ultrix */
13195 #endif /* SVORPOSIX */
13198 /* T T G M D M -- Get modem signals */
13200 Looks for RS-232 modem signals, and returns those that are on in as its
13201 return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
13204 -2 if the communication device does not have modem control (e.g. telnet)
13206 >= 0 on success, with a bit mask containing the modem signals that are on.
13210 Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
13211 modem control, namely the TIOCMGET ioctl.
13220 #endif /* SUNOS4 */
13223 SCO OpenServer R5.0.4. The TIOCMGET definition is hardwired in because it
13224 is skipped in termio.h when _POSIX_SOURCE is defined. But _POSIX_SOURCE
13225 must be defined in order to get the high serial speeds that are new to
13226 5.0.4. However, the regular SCO drivers do not implement TIOCMGET, so the
13227 ioctl() returns -1 with errno 22 (invalid function). But third-party
13228 drivers, e.g. for Digiboard, do implement it, and so it should work on ports
13229 driven by those drivers.
13233 #define TIOCMGET (('t'<<8)|29)
13234 #endif /* TIOCMGET */
13235 #endif /* SCO_OSR504 */
13238 /* Because POSIX strictness in <sys/termio.h> won't let us see these. */
13240 #define TIOCM_DTR 0x0002 /* data terminal ready */
13241 #define TIOCM_RTS 0x0004 /* request to send */
13242 #define TIOCM_CTS 0x0020 /* clear to send */
13243 #define TIOCM_CAR 0x0040 /* carrier detect */
13244 #define TIOCM_RNG 0x0080 /* ring */
13245 #define TIOCM_DSR 0x0100 /* data set ready */
13246 #define TIOCM_CD TIOCM_CAR
13247 #define TIOCM_RI TIOCM_RNG
13248 #endif /* TIOCM_DTR */
13249 #endif /* CK_SCOV5 */
13256 #endif /* TIOCMGET */
13259 "A serial communication program that can't read modem signals
13260 is like a car without windows."
13266 #include <sys/qioctl.h>
13268 unsigned long y, mdmbits[2];
13271 if (xlocal && ttyfd < 0)
13275 if (netconn) { /* Network connection */
13277 if (istncomport()) {
13281 #endif /* TN_COMPORT */
13282 return(-2); /* No modem signals */
13284 #endif /* NETCONN */
13287 if (ttpipe) return(-2);
13288 #endif /* NETCMD */
13290 if (ttpty) return(-2);
13291 #endif /* NETPTY */
13296 * From <sys/qioctl.h>:
13298 * SERIAL devices (all Dev.ser versions)
13299 * 0 : DTR 8 = Data Bits 0 16 - reserved 24 - reserved
13300 * 1 : RTS 9 = Data Bits 1 17 - reserved 25 - reserved
13301 * 2 = Out 1 10 = Stop Bits 18 - reserved 26 - reserved
13302 * 3 = Int Enable 11 = Par Enable 19 - reserved 27 - reserved
13303 * 4 = Loop 12 = Par Even 20 = CTS 28 - reserved
13304 * 5 - reserved 13 = Par Stick 21 = DSR 29 - reserved
13305 * 6 - reserved 14 : Break 22 = RI 30 - reserved
13306 * 7 - reserved 15 = 0 23 = CD 31 - reserved
13309 x = qnx_ioctl(ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4);
13310 debug(F101,"ttgmdm qnx_ioctl","",x);
13311 debug(F101,"ttgmdm qnx_ioctl errno","",errno);
13313 debug(F101,"ttgmdm qnx_ioctl mdmbits[0]","",mdmbits[0]);
13314 debug(F101,"ttgmdm qnx_ioctl mdmbits[1]","",mdmbits[1]);
13316 if (y & 0x000001L) z |= BM_DTR; /* Bit 0 */
13317 if (y & 0x000002L) z |= BM_RTS; /* Bit 1 */
13318 if (y & 0x100000L) z |= BM_CTS; /* Bit 20 */
13319 if (y & 0x200000L) z |= BM_DSR; /* Bit 21 */
13320 if (y & 0x400000L) z |= BM_RNG; /* Bit 22 */
13321 if (y & 0x800000L) z |= BM_DCD; /* Bit 23 */
13322 debug(F101,"ttgmdm qnx result","",z);
13323 debug(F110,"ttgmdm qnx CD = ",(z & BM_DCD) ? "On" : "Off", 0);
13328 #ifdef HPUX /* HPUX has its own way */
13331 #ifdef HPUX10 /* Modem flag word */
13332 mflag y; /* mflag typedef'd in <sys/modem.h> */
13340 unsigned long y; /* Not sure about pre-8.0... */
13343 #endif /* HPUX10 */
13345 if (xlocal && ttyfd < 0)
13349 if (netconn) { /* Network connection */
13351 if (istncomport()) {
13355 #endif /* TN_COMPORT */
13356 return(-2); /* No modem signals */
13358 #endif /* NETCONN */
13361 if (ttpipe) return(-2);
13362 #endif /* NETCMD */
13364 if (ttpty) return(-2);
13365 #endif /* NETPTY */
13367 if (xlocal) /* Get modem signals */
13368 x = ioctl(ttyfd,MCGETA,&y);
13370 x = ioctl(0,MCGETA,&y);
13371 if (x < 0) return(-1);
13372 debug(F101,"ttgmdm","",y);
13374 z = 0; /* Initialize return value */
13376 /* Now set bits for each modem signal that is reported to be on. */
13379 /* Clear To Send */
13380 debug(F101,"ttgmdm HPUX CTS","",y & MCTS);
13381 if (y & MCTS) z |= BM_CTS;
13384 /* Data Set Ready */
13385 debug(F101,"ttgmdm HPUX DSR","",y & MDSR);
13386 if (y & MDSR) z |= BM_DSR;
13390 debug(F101,"ttgmdm HPUX DCD","",y & MDCD);
13391 if (y & MDCD) z |= BM_DCD;
13394 /* Ring Indicate */
13395 debug(F101,"ttgmdm HPUX RI","",y & MRI);
13396 if (y & MRI) z |= BM_RNG;
13399 /* Data Terminal Ready */
13400 debug(F101,"ttgmdm HPUX DTR","",y & MDTR);
13401 if (y & MDTR) z |= BM_DTR;
13404 /* Request To Send */
13405 debug(F101,"ttgmdm HPUX RTS","",y & MRTS);
13406 if (y & MRTS) z |= BM_RTS;
13415 Note, TIOCMGET might already have been defined in <sys/ioctl.h> or elsewhere.
13416 If not, we try including <sys/ttycom.h> -- if this blows up then more ifdefs
13420 #include <sys/ttycom.h>
13421 #endif /* TIOCMGET */
13425 debug(F100,"ttgmdm K_MDMCTL defined","",0);
13428 if (netconn) { /* Network connection */
13430 if (istncomport()) {
13434 #endif /* TN_COMPORT */
13435 return(-2); /* No modem signals */
13437 #endif /* NETCONN */
13440 if (ttpipe) return(-2);
13441 #endif /* NETCMD */
13443 if (ttpty) return(-2);
13444 #endif /* NETPTY */
13446 if (xlocal && ttyfd < 0)
13450 x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */
13452 x = ioctl(0,TIOCMGET,&y);
13453 debug(F101,"ttgmdm TIOCMGET ioctl","",x);
13455 debug(F101,"ttgmdm errno","",errno);
13458 debug(F101,"ttgmdm bits","",y);
13460 z = 0; /* Initialize return value. */
13462 /* Clear To Send */
13463 if (y & TIOCM_CTS) z |= BM_CTS;
13464 debug(F101,"ttgmdm TIOCM_CTS defined","",TIOCM_CTS);
13466 debug(F100,"ttgmdm TIOCM_CTS not defined","",0);
13469 /* Data Set Ready */
13470 if (y & TIOCM_DSR) z |= BM_DSR;
13471 debug(F101,"ttgmdm TIOCM_DSR defined","",TIOCM_DSR);
13473 debug(F100,"ttgmdm TIOCM_DSR not defined","",0);
13477 if (y & TIOCM_CAR) z |= BM_DCD;
13478 debug(F101,"ttgmdm TIOCM_CAR defined","",TIOCM_CAR);
13480 debug(F100,"ttgmdm TIOCM_CAR not defined","",0);
13483 /* Ring Indicate */
13484 if (y & TIOCM_RNG) z |= BM_RNG;
13485 debug(F101,"ttgmdm TIOCM_RNG defined","",TIOCM_RNG);
13487 debug(F100,"ttgmdm TIOCM_RNG not defined","",0);
13490 /* Data Terminal Ready */
13491 if (y & TIOCM_DTR) z |= BM_DTR;
13492 debug(F101,"ttgmdm TIOCM_DTR defined","",TIOCM_DTR);
13494 debug(F100,"ttgmdm TIOCM_DTR not defined","",0);
13497 /* Request To Send */
13498 if (y & TIOCM_RTS) z |= BM_RTS;
13499 debug(F101,"ttgmdm TIOCM_RTS defined","",TIOCM_RTS);
13501 debug(F100,"ttgmdm TIOCM_RTS not defined","",0);
13506 #else /* !K_MDMCTL catch-All */
13508 debug(F100,"ttgmdm K_MDMCTL not defined","",0);
13510 debug(F100,"ttgmdm TIOCMGET defined","",0);
13512 debug(F100,"ttgmdm TIOCMGET not defined","",0);
13513 #endif /* TIOCMGET */
13515 debug(F100,"ttgmdm _SVID3 defined","",0);
13517 debug(F100,"ttgmdm _SVID3 not defined","",0);
13518 #endif /* _SVID3 */
13521 if (netconn) { /* Network connection */
13523 if (istncomport()) {
13527 #endif /* TN_COMPORT */
13528 return(-2); /* No modem signals */
13530 #endif /* NETCONN */
13533 if (ttpipe) return(-2);
13534 #endif /* NETCMD */
13536 if (ttpty) return(-2);
13537 #endif /* NETPTY */
13539 return(-3); /* Sorry, I don't know how... */
13541 #endif /* K_MDMCTL */
13546 /* P S U S P E N D -- Put this process in the background. */
13549 Call with flag nonzero if suspending is allowed, zero if not allowed.
13550 Returns 0 on apparent success, -1 on failure (flag was zero, or
13551 kill() returned an error code.
13554 psuspend(flag) int flag; {
13557 extern int rtu_bug;
13560 if (flag == 0) return(-1);
13567 The big question here is whether job control is *really* supported.
13568 There's no way Kermit can know for sure. The fact that SIGTSTP is
13569 defined does not guarantee the Unix kernel supports it, and the fact
13570 that the Unix kernel supports it doesn't guarantee that the user's
13571 shell (or other process that invoked Kermit) supports it.
13576 if (kill(0,SIGSTOP) < 0
13578 /* Let's try this for MIPS too. */
13579 && kill(getpid(),SIGSTOP) < 0
13581 ) { /* If job control, suspend the job */
13583 debug(F101,"psuspend error","",errno);
13586 debug(F100,"psuspend ok","",0);
13590 #endif /* SIGTSTP */
13595 setuid package, by Kristoffer Eriksson, with contributions from Dean
13599 /* The following is for SCO when CK_ANSILIBS is defined... */
13602 #ifndef NOGETID_PROTOS
13603 #define NOGETID_PROTOS
13604 #endif /* NOGETID_PROTOS */
13605 #endif /* CK_ANSILIBS */
13606 #endif /* M_UNIX */
13608 #ifndef _POSIX_SOURCE
13616 #ifndef NOGETID_PROTOS
13617 _PROTOTYP( UID_T getuid, (void) );
13618 _PROTOTYP( UID_T geteuid, (void) );
13619 _PROTOTYP( UID_T getreuid, (void) );
13620 _PROTOTYP( UID_T getgid, (void) );
13621 _PROTOTYP( UID_T getegid, (void) );
13622 _PROTOTYP( UID_T getregid, (void) );
13623 #endif /* NOGETID_PROTOS */
13625 _PROTOTYP( UID_T getreuid, (void) );
13626 _PROTOTYP( UID_T getregid, (void) );
13627 #endif /* COHERENT */
13628 #endif /* HPUX10 */
13630 #endif /* sequent */
13631 #endif /* PS2AIX10 */
13633 #endif /* SUNOS4 */
13634 #endif /* _POSIX_SOURCE */
13637 Subject: Set-user-id
13638 To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
13639 Date: Sat, 21 Apr 90 4:48:25 MES
13640 From: Kristoffer Eriksson <ske@pkmab.se>
13642 This is a set of functions to be used in programs that may be run set-user-id
13643 and/or set-group-id. They handle both the case where the program is not run
13644 with such privileges (nothing special happens then), and the case where one
13645 or both of these set-id modes are used. The program is made to run with the
13646 user's real user and group ids most of the time, except for when more
13647 privileges are needed. Don't set-user-id to "root".
13649 This works on System V and POSIX. In BSD, it depends on the
13650 "saved-set-user-id" feature.
13653 #define UID_ROOT 0 /* Root user and group ids */
13657 The following code defines the symbol SETEUID for UNIX systems based
13658 on BSD4.4 (either -Encumbered or -Lite). This program will then use
13659 seteuid() and setegid() instead of setuid() and setgid(), which still
13660 don't allow arbitrary switching. It also avoids setreuid() and
13661 setregid(), which are included in BSD4.4 for compatibility only, are
13662 insecure, and print warnings to stderr under at least one system (NetBSD
13663 1.0). Note that POSIX systems should still use setuid() and setgid();
13664 the seteuid() and setegid() functions are BSD4.4 extensions to the
13665 POSIX model. Mike Long <mike.long@analog.com>, 8/94.
13672 The following construction automatically defines the symbol SETREUID for
13673 UNIX versions based on Berkeley Unix 4.2 and 4.3. If this symbol is
13674 defined, then this program will use getreuid() and getregid() calls in
13675 preference to getuid() and getgid(), which in Berkeley-based Unixes do
13676 not allow arbitrary switching back and forth of real & effective uid.
13677 This construction also allows -DSETREUID to be put on the cc command line
13678 for any system that has and wants to use setre[ug]id(). It also prevents
13679 automatic definition of SETREUID if -DNOSETREU is included on the cc
13680 command line (or otherwise defined).
13682 #ifdef FT18 /* None of this for Fortune. */
13693 #endif /* SETEUID */
13694 #endif /* NOSETREU */
13695 #endif /* SETREUID */
13696 #endif /* !BSD41 */
13697 #endif /* !BSD29 */
13698 #endif /* ANYBSD */
13700 /* Variables for user and group IDs. */
13702 static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
13703 static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
13706 /* P R I V _ I N I -- Initialize privileges package */
13708 /* Called as early as possible in a set-uid or set-gid program to store the
13709 * set-to uid and/or gid and step down to the users real uid and gid. The
13710 * stored id's can be temporarily restored (allowed in System V) during
13711 * operations that require the privilege. Most of the time, the program
13712 * should execute in unpriviliged state, to not impose any security threat.
13714 * Note: Don't forget that access() always uses the real id:s to determine
13715 * file access, even with privileges restored.
13717 * Returns an error mask, with error values or:ed together:
13718 * 1 if setuid() fails,
13719 * 2 if setgid() fails, and
13720 * 4 if the program is set-user-id to "root", which can't be handled.
13722 * Only the return value 0 indicates real success. In case of failure,
13723 * those privileges that could be reduced have been, at least, but the
13724 * program should be aborted none-the-less.
13726 * Also note that these functions do not expect the uid or gid to change
13727 * without their knowing. It may work if it is only done temporarily, but
13728 * you're on your own.
13734 #ifndef HAVE_LOCKDEV
13736 /* Save real ID:s. */
13737 realuid = getuid();
13738 realgid = getgid();
13740 /* Save current effective ID:s, those set to at program exec. */
13741 privuid = geteuid();
13742 privgid = getegid();
13744 /* If running set-uid, go down to real uid, otherwise remember that
13745 * no privileged uid is available.
13749 * 1) If the real uid is already "root" and the set-uid uid (the
13750 * initial effective uid) is not "root", then we would have trouble
13751 * if we went "down" to "root" here, and then temporarily back to the
13752 * set-uid uid (not "root") and then again tried to become "root". I
13753 * think the "saved set-uid" is lost when changing uid from effective
13754 * uid "root", which changes all uid, not only the effective uid. But
13755 * in this situation, we can simply go to "root" and stay there all
13756 * the time. That should give sufficient privilege (understatement!),
13757 * and give the right uids for subprocesses.
13759 * 2) If the set-uid (the initial effective uid) is "root", and we
13760 * change uid to the real uid, we can't change it back to "root" when
13761 * we need the privilege, for the same reason as in 1). Thus, we can't
13762 * handle programs that are set-user-id to "root" at all. The program
13763 * should be stopped. Use some other uid. "root" is probably too
13764 * privileged for such things, anyway. (The uid is reverted to the
13765 * real uid until termination.)
13767 * These two exceptions have the effect that the "root" uid will never
13768 * be one of the two uids that are being switched between, which also
13769 * means we don't have to check for such cases in the switching
13772 * Note that exception 1) is handled by these routines (by constantly
13773 * running with uid "root", while exception 2) is a serious error, and
13774 * is not provided for at all in the switching functions.
13776 if (realuid == privuid)
13777 privuid = (UID_T) -1; /* Not running set-user-id. */
13779 /* If running set-gid, go down to real gid, otherwise remember that
13780 * no privileged gid is available.
13782 * There are no exception like there is for the user id, since there
13783 * is no group id that is privileged in the manner of uid "root".
13784 * There could be equivalent problems for group changing if the
13785 * program sometimes ran with uid "root" and sometimes not, but
13786 * that is already avoided as explained above.
13788 * Thus we can expect always to be able to switch to the "saved set-
13789 * gid" when we want, and back to the real gid again. You may also
13790 * draw the conclusion that set-gid provides for fewer hassles than
13795 fprintf(stderr,"UID_ROOT=%d\n",UID_ROOT);
13796 fprintf(stderr,"realuid=%d\n",realuid);
13797 fprintf(stderr,"privuid=%d\n",privuid);
13798 #endif /* SUIDDEBUG */
13800 if (realgid == privgid) /* If not running set-user-id, */
13801 privgid = (GID_T) -1; /* remember it this way. */
13803 err = priv_off(); /* Turn off setuid privilege. */
13805 if (privuid == UID_ROOT) /* If setuid to root, */
13806 err |= 4; /* return this error. */
13808 if (realuid == UID_ROOT) { /* If real id is root, */
13809 privuid = (UID_T) -1; /* stay root at all times. */
13811 /* If Kermit installed SUID uucp and user is running as root */
13812 err &= ~1; /* System V R0 does not save UID */
13813 #endif /* ATT7300 */
13815 #endif /* HAVE_LOCKDEV */
13820 /* Macros for hiding the differences in UID/GID setting between various Unix
13821 * systems. These macros should always be called with both the privileged ID
13822 * and the non-privileged ID. The one in the second argument, will become the
13823 * effective ID. The one in the first argument will be retained for later
13828 /* On BSD systems with the saved-UID feature, we just juggle the effective
13829 * UID back and forth, and leave the real UID at its true value. The kernel
13830 * allows switching to both the current real UID, the effective UID, and the
13831 * UID which the program is set-UID to. The saved set-UID always holds the
13832 * privileged UID for us, and the real UID will always be the non-privileged,
13833 * and we can freely choose one of them for the effective UID at any time.
13835 #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
13836 #define switchgid(hidden,active) setregid( (GID_T) -1, active)
13838 #else /* SETREUID,!SAVEDUID */
13840 /* On systems with setreXid() but without the saved-UID feature, notably
13841 * BSD 4.2, we swap the real and effective UIDs each time. It's
13842 * the effective UID that we are interested in, but we have to retain the
13843 * unused UID somewhere to enable us to restore it later, and we do this
13844 * in the real UID. The kernel only allows switching to either the current
13845 * real or the effective UID, unless you're "root".
13847 #define switchuid(hidden,active) setreuid(hidden,active)
13848 #define switchgid(hidden,active) setregid(hidden,active)
13851 #else /* !SETREUID, !SAVEDUID */
13855 BSD 4.4 works similarly to System V and POSIX (see below), but uses
13856 seteXid() instead of setXid() to change effective IDs. In addition, the
13857 seteXid() functions work the same for "root" as for other users.
13859 #define switchuid(hidden,active) seteuid(active)
13860 #define switchgid(hidden,active) setegid(active)
13862 #else /* !SETEUID */
13864 /* On System V and POSIX, the only thing we can change is the effective UID
13865 * (unless the current effective UID is "root", but initsuid() avoids that for
13866 * us). The kernel allows switching to the current real UID or to the saved
13867 * set-UID. These are always set to the non-privileged UID and the privileged
13868 * UID, respectively, and we only change the effective UID. This breaks if
13869 * the current effective UID is "root", though, because for "root" setuid/gid
13870 * becomes more powerful, which is why initsuid() treats "root" specially.
13871 * Note: That special treatment maybe could be ignored for BSD? Note: For
13872 * systems that don't fit any of these four cases, we simply can't support
13875 #define switchuid(hidden,active) setuid(active)
13876 #define switchgid(hidden,active) setgid(active)
13878 #endif /* SETEUID */
13879 #endif /* SETREUID */
13882 /* P R I V _ O N -- Turn on the setuid and/or setgid */
13884 /* Go to the privileged uid (gid) that the program is set-user-id
13885 * (set-group-id) to, unless the program is running unprivileged.
13886 * If setuid() fails, return value will be 1. If getuid() fails it
13887 * will be 2. Return immediately after first failure, and the function
13888 * tries to restore any partial work done. Returns 0 on success.
13889 * Group id is changed first, since it is less serious than user id.
13893 #ifndef HAVE_LOCKDEV
13894 if (privgid != (GID_T) -1)
13895 if (switchgid(realgid,privgid))
13898 if (privuid != (UID_T) -1)
13899 if (switchuid(realuid,privuid)) {
13900 if (privgid != (GID_T) -1)
13901 switchgid(privgid,realgid);
13904 #endif /* HAVE_LOCKDEV */
13908 /* P R I V _ O F F -- Turn on the real uid and gid */
13910 /* Return to the unprivileged uid (gid) after an temporary visit to
13911 * privileged status, unless the program is running without set-user-id
13912 * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
13913 * in setgid() or:ed together. The functions tries to return both uid
13914 * and gid to unprivileged state, regardless of errors. Returns 0 on
13920 #ifndef HAVE_LOCKDEV
13921 if (privuid != (UID_T) -1)
13922 if (switchuid(privuid,realuid))
13925 if (privgid != (GID_T) -1)
13926 if (switchgid(privgid,realgid))
13928 #endif /* HAVE_LOCKDEV */
13932 /* Turn off privilege permanently. No going back. This is necessary before
13933 * a fork() on BSD43 machines that don't save the setUID or setGID, because
13934 * we swap the real and effective ids, and we don't want to let the forked
13935 * process swap them again and get the privilege back. It will work on other
13936 * machines too, such that you can rely on its effect always being the same,
13937 * for instance, even when you're in priv_on() state when this is called.
13938 * (Well, that part about "permanent" is on System V only true if you follow
13939 * this with a call to exec(), but that's what we want it for anyway.)
13940 * Added by Dean Long -- dlong@midgard.ucsc.edu
13944 #ifndef HAVE_LOCKDEV
13947 if (privuid != (UID_T) -1)
13948 if (setreuid(realuid,realuid))
13951 if (privgid != (GID_T) -1)
13952 if (setregid(realgid,realgid))
13960 if (privuid != (UID_T) -1)
13961 if (setuid(realuid)) {
13962 debug(F101,"setuid failed","",errno);
13964 debug(F101,"ruid","",getuid());
13965 debug(F101,"euid","",geteuid());
13967 debug(F101,"setuid","",realuid);
13968 if (privgid != (GID_T) -1)
13969 if (setgid(realgid)) {
13970 debug(F101,"setgid failed","",errno);
13972 debug(F101,"rgid","",getgid());
13973 debug(F101,"egid","",getegid());
13975 debug(F101,"setgid","",realgid);
13978 /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
13979 return(priv_off());
13980 #endif /* SETEUID */
13981 #endif /* SETREUID */
13984 #endif /* HAVE_LOCKDEV */
13987 /* P R I V _ O P N -- For opening protected files or devices. */
13990 priv_opn(name, modes) char *name; int modes; {
13992 priv_on(); /* Turn privileges on */
13993 debug(F111,"priv_opn",name,modes);
13995 x = open(name, modes); /* Try to open the device */
13996 debug(F101,"priv_opn result","",x);
13997 debug(F101,"priv_opn errno","",errno);
13998 priv_off(); /* Turn privileges off */
13999 return(x); /* Return open's return code */
14002 /* P R I V _ C H K -- Check privileges. */
14004 /* Try to turn them off. If turning them off did not succeed, cancel them */
14009 x = priv_off(); /* Turn off privs. */
14010 if (x != 0 || getuid() == privuid || geteuid() == privuid)
14012 if (x != 0 || getgid() == privgid || getegid() == privgid)
14013 y = y | priv_can();
14023 ttimoff() { /* Turn off any timer interrupts */
14026 As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
14027 SIG_DFL (to catch alarms, or if there is no handler, to exit). This is to
14028 cure (mask, really) a deeper problem with stray alarms that occurs on some
14029 systems, possibly having to do with sleep(), that caused core dumps. It
14030 should be OK to do this, because no code in this module uses nested alarms.
14031 (But we still have to watch out for SCRIPT and DIAL...)
14033 /* xx = */ alarm(0);
14034 /* debug(F101,"ttimoff alarm","",xx); */
14035 if (saval) { /* Restore any previous */
14036 signal(SIGALRM,saval); /* alarm handler. */
14037 /* debug(F101,"ttimoff alarm restoring saval","",saval); */
14040 signal(SIGALRM,SIG_IGN); /* Used to be SIG_DFL */
14041 /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
14047 tt_is_secure() { /* Tells whether the current connection is secure */
14055 #endif /* SSHBUILTIN */
14056 #ifdef CK_ENCRYPTION
14057 || ck_tn_encrypting() && ck_tn_decrypting()
14058 #endif /* CK_ENCRYPTION */
14060 || tls_active_flag || ssl_active_flag
14061 #endif /* CK_SSL */
14064 #ifdef CK_ENCRYPTION
14065 || ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN
14066 #endif /* CK_ENCRYPTION */
14067 #endif /* CK_KERBEROS */
14068 #endif /* RLOGCODE */
14076 /* External protocol handler parameters from ckuus3.c */
14077 extern int exp_handler, exp_stderr, exp_timo;
14082 /* The right size is 24576 */
14084 #ifndef PTY_PBUF_SIZE /* Size of buffer to read from pty */
14085 #define PTY_PBUF_SIZE 24576 /* and write to net. */
14086 #endif /* PTY_PBUF_SIZE */
14088 #ifndef PTY_TBUF_SIZE /* Size of buffer to read from net */
14089 #define PTY_TBUF_SIZE 24576 /* and write to pty. */
14090 #endif /* PTY_TBUF_SIZE */
14092 #ifdef O_NDELAY /* Whether to use nonblocking */
14093 #ifndef PTY_NO_NDELAY /* reads on the pseudoterminal */
14094 #ifndef PTY_USE_NDELAY
14095 #define PTY_USE_NDELAY
14096 #endif /* PTY_USE_NDELAY */
14097 #endif /* PTY_NO_NDELAY */
14098 #endif /* O_NDELAY */
14100 #ifndef HAVE_OPENPTY
14101 #ifndef USE_CKUPTY_C
14102 #define USE_CKUPTY_C
14103 #endif /* USE_CKUPTY_C */
14104 #endif /* HAVE_OPENPTY */
14107 pty_make_raw(fd) int fd; {
14110 #ifdef BSD44ORPOSIX /* POSIX */
14113 #ifdef ATTSV /* AT&T UNIX */
14115 struct termio tp = {0};
14118 #endif /* CK_ANSIC */
14120 struct sgttyb tp; /* Traditional */
14122 #endif /* BSD44ORPOSIX */
14124 debug(F101,"pty_make_raw fd","",fd);
14127 #ifdef BSD44ORPOSIX /* POSIX */
14128 x = tcgetattr(fd,&tp);
14129 debug(F101,"pty_make_raw tcgetattr","",x);
14131 #ifdef ATTSV /* AT&T UNIX */
14132 x = ioctl(fd,TCGETA,&tp);
14133 debug(F101,"pty_make_raw TCGETA ioctl","",x);
14136 debug(F101,"pty_make_raw ttty","",x);
14138 #endif /* BSD44ORPOSIX */
14139 debug(F101,"pty_make_raw GET errno","",errno);
14141 #ifdef USE_CFMAKERAW
14144 debug(F101,"pty_make_raw cfmakeraw errno","",errno);
14145 #else /* USE_CFMAKERAW */
14149 /* This very simple version recommended by Serg Iakolev doesn't work */
14151 tp.c_lflag &= ~(ECHO|ICANON|IEXTEN|ISIG);
14152 tp.c_iflag &= ~(BRKINT|ICRNL|INPCK|ISTRIP|IXON);
14153 tp.c_cflag &= ~(CSIZE|PARENB);
14155 tp.c_oflag &= ~(OPOST);
14157 tp.c_cc[VTIME] = 0;
14159 debug(F101,"pty_make_raw 1 c_cc[] NCCS","",NCCS);
14160 debug(F101,"pty_make_raw 1 iflags","",tp.c_iflag);
14161 debug(F101,"pty_make_raw 1 oflags","",tp.c_oflag);
14162 debug(F101,"pty_make_raw 1 lflags","",tp.c_lflag);
14163 debug(F101,"pty_make_raw 1 cflags","",tp.c_cflag);
14168 In this version we unset everything and then set only the
14169 bits we know we need.
14173 tp.c_iflag |= IGNBRK;
14175 tp.c_iflag |= IMAXBEL;
14176 #endif /* IMAXBEL */
14184 tp.c_lflag |= NOKERNINFO;
14185 #endif /* NOKERNINFO */
14189 tp.c_cflag |= CS8|CREAD;
14191 for (i = 0; i < NCCS; i++) { /* No special characters */
14195 tp.c_cc[VMIN] = 1; /* But always wait for input */
14197 debug(F101,"pty_make_raw 2 c_cc[] NCCS","",NCCS);
14198 debug(F101,"pty_make_raw 2 iflags","",tp.c_iflag);
14199 debug(F101,"pty_make_raw 2 oflags","",tp.c_oflag);
14200 debug(F101,"pty_make_raw 2 lflags","",tp.c_lflag);
14201 debug(F101,"pty_make_raw 2 cflags","",tp.c_cflag);
14203 #else /* COMMENT */
14205 In this version we set or unset every single flag explicitly. It works a
14206 bit better than the simple version just above, but it's still far from
14210 tp.c_iflag &= ~(PARMRK|ISTRIP|BRKINT|INLCR|IGNCR|ICRNL);
14211 tp.c_iflag &= ~(INPCK|IGNPAR|IXANY|IXON|IXOFF);
14212 tp.c_iflag |= IGNBRK;
14215 tp.c_iflag |= IMAXBEL;
14217 tp.c_iflag &= ~IMAXBEL;
14218 #endif /* COMMENT */
14219 #endif /* IMAXBEL */
14221 tp.c_iflag &= ~IUCLC;
14226 tp.c_oflag &= ~BSDLY;
14229 tp.c_oflag &= ~CRDLY;
14232 tp.c_oflag &= ~FFDLY;
14235 tp.c_oflag &= ~NLDLY;
14238 tp.c_oflag &= ~TABDLY;
14239 #endif /* TABDLY */
14241 tp.c_oflag &= ~VTDLY;
14244 tp.c_oflag &= ~OFDEL;
14247 tp.c_oflag &= ~OFILL;
14250 tp.c_oflag &= ~OLCUC;
14253 tp.c_oflag &= ~CMSPAR;
14254 #endif /* CMSPAR */
14255 tp.c_oflag &= ~OPOST;
14257 tp.c_oflag &= ~OXTABS;
14258 #endif /* OXTABS */
14261 tp.c_oflag &= ~ONOCR; /* Maybe should be |=? */
14262 tp.c_oflag |= ONOCR; /* makes no difference either way */
14264 #endif /* COMMENT */
14266 tp.c_oflag &= ~ONOEOT;
14267 #endif /* ONOEOT */
14269 tp.c_oflag &= ~ONLRET;
14270 #endif /* ONLRET */
14272 tp.c_oflag &= ~ONLCR;
14275 tp.c_oflag &= ~OCRNL;
14279 tp.c_lflag &= ~ECHO;
14281 tp.c_lflag &= ~ECHOE;
14284 tp.c_lflag &= ~ECHONL;
14285 #endif /* ECHONL */
14287 tp.c_lflag &= ~ECHOPRT;
14288 #endif /* ECHOPRT */
14290 tp.c_lflag &= ~ECHOKE;
14291 #endif /* ECHOKE */
14293 tp.c_lflag &= ~ECHOCTL;
14294 #endif /* ECHOCTL */
14296 tp.c_lflag &= ~XCASE;
14299 tp.c_lflag &= ~ALTWERASE;
14300 #endif /* ALTWERASE */
14302 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN|EXTPROC);
14304 tp.c_lflag &= ~(ICANON|ISIG|IEXTEN|TOSTOP|FLUSHO|PENDIN);
14305 #endif /* EXTPROC */
14307 tp.c_lflag |= NOKERNINFO;
14308 #endif /* NOKERNINFO */
14310 tp.c_lflag &= ~NOFLSH; /* TRY IT THE OTHER WAY? */
14312 tp.c_lflag |= NOFLSH; /* No, this way is worse */
14313 #endif /* COMMENT */
14316 tp.c_cflag &= ~(CSIZE|PARENB|PARODD);
14317 tp.c_cflag |= CS8|CREAD;
14320 tp.c_cflag &= ~(MDMBUF);
14323 tp.c_cflag &= ~(CCAR_OFLOW); /* two names for the same thing */
14324 #endif /* CCAR_OFLOW */
14325 #endif /* MDMBUF */
14328 tp.c_cflag &= ~(CCTS_OFLOW);
14329 #endif /* CCTS_OFLOW */
14331 tp.c_cflag &= ~(CDSR_OFLOW);
14332 #endif /* CDSR_OFLOW */
14334 tp.c_cflag &= ~(CDTR_IFLOW);
14335 #endif /* CDTR_IFLOW */
14337 tp.c_cflag &= ~(CRTS_IFLOW);
14338 #endif /* CRTS_IFLOW */
14340 tp.c_cflag &= ~(CRTSXOFF);
14341 #endif /* CRTSXOFF */
14343 tp.c_cflag &= ~(CRTSCTS);
14344 #endif /* CRTSCTS */
14346 tp.c_cflag &= ~(CLOCAL);
14347 #endif /* CLOCAL */
14349 tp.c_cflag &= ~(CSTOPB);
14350 #endif /* CSTOPB */
14352 tp.c_cflag &= ~(HUPCL);
14355 for (i = 0; i < NCCS; i++) { /* No special characters */
14359 tp.c_cc[VMIN] = 1; /* But always wait for input */
14361 debug(F101,"pty_make_raw 3 c_cc[] NCCS","",NCCS);
14362 debug(F101,"pty_make_raw 3 iflags","",tp.c_iflag);
14363 debug(F101,"pty_make_raw 3 oflags","",tp.c_oflag);
14364 debug(F101,"pty_make_raw 3 lflags","",tp.c_lflag);
14365 debug(F101,"pty_make_raw 3 cflags","",tp.c_cflag);
14366 #endif /* COMMENT */
14367 #endif /* COMMENT */
14370 #ifdef BSD44ORPOSIX /* POSIX */
14371 x = tcsetattr(fd,TCSANOW,&tp);
14372 debug(F101,"pty_make_raw tcsetattr","",x);
14374 #ifdef ATTSV /* AT&T UNIX */
14375 x = ioctl(fd,TCSETA,&tp);
14376 debug(F101,"pty_make_raw ioctl","",x);
14378 x = stty(fd,&tp); /* Traditional */
14379 debug(F101,"pty_make_raw stty","",x);
14381 #endif /* BSD44ORPOSIX */
14382 debug(F101,"pty_make_raw errno","",errno);
14384 #endif /* __NetBSD__ */
14388 pty_chk(fd) int fd; {
14392 x = ioctl(fd, FIONREAD, &n); /* BSD and most others */
14393 ckmakmsg(msgbuf,500,
14394 "pty_chk ioctl FIONREAD errno=",
14398 debug(F100,msgbuf,"",0);
14401 debug(F101,"pty_chk rdchk","",n);
14404 #endif /* FIONREAD */
14405 return((n > -1) ? n : 0);
14409 pty_get_status(fd,pid) int fd; PID_T pid; {
14410 int x, status = -1;
14413 debug(F101,"pty_get_status fd","",fd);
14414 debug(F101,"pty_get_status pid","",pid);
14416 if (pexitstat > -1)
14420 /* Not only unnecessary but harmful */
14422 x = kill(pty_fork_pid,0);
14423 debug(F101,"pty_get_status kill value","",x);
14424 debug(F101,"pty_get_status kill errno","",errno);
14425 if (x > -1 && errno != ESRCH)
14426 return(-1); /* Fork still there */
14427 /* Fork seems to be gone */
14428 #endif /* COMMENT */
14431 x = waitpid(pty_fork_pid,&status,WNOHANG);
14432 debug(F111,"pty_get_status waitpid",ckitoa(errno),x);
14433 if (x <= 0 && errno == 0) {
14434 debug(F101,"pty_get_status waitpid return","",-1);
14438 if (x != pty_fork_pid)
14440 "pty_get_status waitpid pid doesn't match","",pty_fork_pid);
14441 debug(F101,"pty_get_status waitpid status","",status);
14442 debug(F101,"pty_get_status waitpid errno","",errno);
14443 if (WIFEXITED(status)) {
14444 debug(F100,"pty_get_status WIFEXITED","",0);
14445 status = WEXITSTATUS(status);
14446 debug(F101,"pty_get_status fork exit status","",status);
14449 #endif /* COMMENT */
14451 pexitstat = status;
14453 debug(F100,"pty_get_status waitpid unexpected status","",0);
14456 debug(F101,"pty_get_status return status","",status);
14460 /* t t p t y c m d -- Run command on pty and forward to net */
14463 Needed for running external protocols on secure connections.
14464 For example, if C-Kermit has made an SSL/TLS or Kerberos Telnet
14465 connection, and then needs to transfer a file with Zmodem, which is
14466 an external program, this routine reads Zmodem's output, encrypts it,
14467 and then forwards it out the connection, and reads the encrypted data
14468 stream coming in from the connection, decrypts it, and forwards it to
14471 Works like a TCP/IP port forwarder except one end is a pty rather
14472 than a socket, which introduces some complications:
14474 . On most platforms, select() always indicates the output side of
14475 the pty has characters waiting to be read, even when it doesn't,
14476 even when the pty process has already exited.
14478 . Nonblocking reads must be used on the pty, because there is no
14479 way on certain platforms (e.g. NetBSD) to find out how many characters
14480 are available to be read (the FIONREAD ioctl always says 0). The code
14481 also allows for blocking reads (if O_NDELAY and O_NONBLOCK are not
14482 defined, or if PTY_NO_NDELAY is defined), but on some platforms this can
14483 result in single-byte reads and writes (NetBSD again).
14485 . Testing for "EOF" on the pty is problematic. select() never gives
14486 any indication. After the pty process has exited and the fork has
14487 disappeared, read() can still return with 0 bytes read but without an
14488 error (NetBSD); no known test on the pty file descriptor will indicate
14489 that it is no longer valid. The process ID of the pty fork can be
14490 tested on some platforms (NetBSD, luckily) but not others (Solaris,
14493 On the network side, we use ttinc() and ttoc(), which, for network
14494 connections, handle any active security methods.
14496 Call with s = command.
14497 Returns 0 on failure, 1 on success.
14498 fdc - December 2006 - August 2007.
14500 NOTE: This code defaults to nonblocking reads if O_NDELAY or O_NONBLOCK are
14501 defined in the header files, which should be true of every recent Unix
14502 platform. If this causes trouble somewhere, define PTY_NO_NDELAY, e.g. when
14506 make platformname KFLAGS=-DPTY_NO_NODELAY
14508 static int have_pty = 0; /* Do we have a pty? */
14510 static SIGTYP (*save_sigchld)() = NULL; /* For catching SIGCHLD */
14513 sigchld_handler(sig) int sig; {
14514 have_pty = 0; /* We don't have a pty */
14516 if (save_sigchld) {
14517 (VOID) signal(SIGCHLD,save_sigchld);
14518 save_sigchld = NULL;
14521 debug(F100,"**************","",0);
14522 debug(F100,"SIGCHLD caught","",0);
14523 debug(F100,"**************","",0);
14531 ttptycmd(s) char *s; {
14532 CHAR tbuf[PTY_TBUF_SIZE]; /* Read from net, write to pty */
14533 int tbuf_avail = 0; /* Pointers for tbuf */
14534 int tbuf_written = 0;
14535 static int in_state = 0; /* For TELNET IAC and NVT in */
14536 static int out_prev = 0; /* Simpler scheme for out */
14538 CHAR pbuf[PTY_PBUF_SIZE]; /* Read from pty, write to net */
14539 CHAR dbuf[PTY_PBUF_SIZE + PTY_PBUF_SIZE + 1]; /* Double-size buffer */
14540 int pbuf_avail = 0; /* Pointers for pbuf */
14541 int pbuf_written = 0;
14543 int ptyfd = -1; /* Pty file descriptor */
14544 int have_net = 0; /* We have a network connection */
14545 int pty_err = 0; /* Got error on pty */
14546 int net_err = 0; /* Got error on net */
14547 int status = -1; /* Pty process exit status */
14548 int rc = 0; /* Our return code */
14550 int x1 = 0, x2 = 0; /* Workers... */
14551 int c, n, m, t, x; /* Workers */
14553 long seconds_to_wait = 0L; /* select() timeout */
14554 struct timeval tv, *tv2; /* For select() */
14556 int in, out, err; /* For select() */
14558 fd_set in, out, err;
14559 #endif /* INTSELECT */
14560 int nfds = 0; /* For select() */
14562 int pset = 0, tset = 0, pnotset = 0, tnotset = 0; /* stats/debuggin only */
14563 int read_net_bytes = 0; /* Stats */
14564 int write_net_bytes = 0; /* Stats */
14565 int read_pty_bytes = 0; /* Stats */
14566 int write_pty_bytes = 0; /* Stats */
14567 int is_tn = 0; /* TELNET protocol is active */
14571 #ifndef USE_CKUPTY_C
14572 struct termios term;
14573 struct winsize twin;
14574 struct stringarray * q;
14575 char ** args = NULL;
14576 #endif /* USE_CKUPTY_C */
14578 in_state = 0; /* No previous character yet */
14581 printf("?Sorry, communication channel is not open\n");
14587 debug(F100,"ttptycmd fail: nopush","",0);
14590 if (!s) s = ""; /* Defense de bogus arguments */
14591 if (!*s) return(0);
14592 pexitstat = -1; /* Fork process exit status */
14595 is_tn = (xlocal && netconn && IS_TELNET()) || /* Telnet protocol active */
14596 (!xlocal && sstelnet);
14597 #endif /* TNCODE */
14599 debug(F110,"ttptycmd command",s,0);
14600 debug(F101,"ttptycmd ttyfd","",ttyfd);
14601 debug(F101,"ttptycmd is_tn","",is_tn);
14602 debug(F101,"ttptycmd ckermit pid","",getpid());
14604 #ifdef USE_CKUPTY_C
14605 /* Call ckupty.c module to get and set up the pty fork */
14606 /* fc 1 == "run an external protocol" */
14607 debug(F100,"ttptycmd using ckupty.c","",0);
14608 if (do_pty(&ptyfd,s,1) < 0) { /* Start the command on a pty */
14609 debug(F100,"ttptycmd do_pty fails","",0);
14613 pty_master_fd = ptyfd;
14615 slavefd = pty_slave_fd; /* This is not visible to us */
14616 #endif /* COMMENT */
14617 debug(F111,"ttptycmd ptyfd","USE_CKUPTY_C",ptyfd);
14618 debug(F111,"ttptycmd masterfd","USE_CKUPTY_C",masterfd);
14619 debug(F111,"ttptycmd fork pid","USE_CKUPTY_C",pty_fork_pid);
14621 /* "ioctl inappropriate on device" for pty master */
14622 pty_make_raw(masterfd);
14623 #endif /* SOLARIS */
14625 #else /* USE_CKUPTY_C */
14627 debug(F100,"ttptycmd OPENPTY","",0);
14628 if (tcgetattr(0, &term) == -1) { /* Get controlling terminal's modes */
14629 perror("tcgetattr");
14632 if (ioctl(0, TIOCGWINSZ, (char *) &twin) == -1) { /* and window size */
14633 perror("ioctl TIOCGWINSZ");
14636 if (openpty(&masterfd, &slavefd, NULL, NULL, NULL) == -1) {
14637 debug(F101,"ttptycmd openpty failed errno","",errno);
14641 debug(F101,"ttptycmd openpty masterfd","",masterfd);
14642 debug(F101,"ttptycmd openpty slavefd","",slavefd);
14643 pty_master_fd = masterfd;
14644 pty_slave_fd = slavefd;
14645 debug(F101,"ttptycmd openpty pty_master_fd","",pty_master_fd);
14647 /* Put pty master in raw mode but let forked app control the slave */
14648 pty_make_raw(masterfd);
14652 /* TIOCREMOTE,0 = disable all termio processing */
14653 x = ioctl(masterfd, TIOCREMOTE, 1);
14654 debug(F111,"ttptycmd ioctl TIOCREMOTE",ckitoa(x),errno);
14655 #endif /* TIOCREMOTE */
14657 /* TIOCTTY,0 = disable all termio processing */
14658 x = ioctl(masterfd, TIOCTTY, 0);
14659 debug(F111,"ttptycmd ioctl TIOCTTY",ckitoa(x),errno);
14660 #endif /* TIOCTTY */
14661 #endif /* COMMENT */
14663 have_pty = 1; /* We have an open pty */
14664 save_sigchld = signal(SIGCHLD, sigchld_handler); /* Catch fork quit */
14666 pty_fork_pid = fork(); /* Make fork for external protocol */
14667 debug(F101,"ttptycmd pty_fork_pid","",pty_fork_pid);
14668 if (pty_fork_pid == -1) {
14671 } else if (pty_fork_pid == 0) { /* In new fork */
14673 debug(F101,"ttptycmd new fork pid","",getpid());
14674 close(masterfd); /* Slave quarters no masters allowed */
14676 debug(F101,"ttptycmd new fork setsid","",x);
14678 perror("ttptycmd setsid");
14681 signal(SIGINT,SIG_IGN); /* Let upper fork catch this */
14685 /* Make pty the controlling terminal for the process */
14686 /* THIS CAUSES AN INFINITE SIGWINCH INTERRUPT LOOP */
14687 x = ioctl(slavefd, TIOCSCTTY, NULL);
14688 debug(F101,"ttptycmd TIOCSCTTY","",x);
14689 #endif /* TIOCSCTTY */
14690 #endif /* COMMENT */
14692 /* Initialize slave pty modes and size to those of our terminal */
14693 if (tcsetattr(slavefd, TCSANOW, &term) == -1) {
14694 perror("ttptycmd tcsetattr");
14697 if (ioctl(slavefd, TIOCSWINSZ, &twin) == -1) {
14698 perror("ttptycmd ioctl");
14703 /* Disassociate this process from its terminal */
14704 /* THIS HAS NO EFFECT */
14705 x = ioctl(slavefd, TIOCNOTTY, NULL);
14706 debug(F101,"ttptycmd TIOCNOTTY","",x);
14707 #endif /* TIOCNOTTY */
14708 #endif /* COMMENT */
14712 /* Ignore terminal output interrupts */
14713 /* THIS HAS NO EFFECT */
14714 debug(F100,"ttptycmd ignoring SIGTTOU","",0);
14715 signal(SIGTTOU, SIG_IGN);
14716 #endif /* SIGTTOU */
14718 /* Ignore terminal output interrupts */
14719 /* THIS HAS NO EFFECT */
14720 debug(F100,"ttptycmd ignoring SIGTSTP","",0);
14721 signal(SIGTSTP, SIG_IGN);
14722 #endif /* SIGTSTP */
14723 #endif /* COMMENT */
14725 pty_make_raw(slavefd); /* Put it in rawmode */
14728 if (dup2(slavefd, STDIN_FILENO) != STDIN_FILENO ||
14729 dup2(slavefd, STDOUT_FILENO) != STDOUT_FILENO) {
14730 debug(F101,"ttptycmd new fork dup2 error","",errno);
14731 perror("ttptycmd dup2");
14734 debug(F100,"ttptycmd new fork dup2 ok","",0);
14736 /* Parse external protocol command line */
14737 q = cksplit(1,0,s,NULL,"\\%[]&$+-/=*^_@!{}/<>|.#~'`:;?",7,0,0);
14739 debug(F100,"ttptycmd cksplit failed","",0);
14743 debug(F100,"ttptycmd cksplit ok","",0);
14745 args = q->a_head + 1;
14746 for (i = 0; i <= n; i++) {
14750 /* sometimes cksplit() doesn't terminate the list */
14751 if ((i == n) && args[i]) {
14752 if ((int)strlen(args[i]) == 0)
14753 makestr(&(args[i]),NULL);
14760 Putting the slave pty in rawmode should not be necessary because the
14761 external protocol program is supposed to do that itself. Yet doing this
14762 here cuts down on Zmodem binary-file transmission errors by 30-50% but
14763 still doesn't eliminate them.
14765 pty_make_raw(STDIN_FILENO);
14766 pty_make_raw(STDOUT_FILENO);
14767 #endif /* COMMENT */
14769 debug(F100,"ttptycmd execvp'ing external protocol","",0);
14770 execvp(args[0],args);
14771 perror("execvp failed");
14772 debug(F101,"ttptycmd execvp failed","",errno);
14776 /* (there are better ways to do this...) */
14777 msleep(1000); /* Make parent wait for child to be ready */
14778 ptyfd = masterfd; /* We talk to the master */
14780 #endif /* USE_CKUPTY_C */
14782 debug(F101,"ttptycmd ptyfd","",ptyfd);
14784 printf("?Failure to get pty\n");
14787 have_pty = 1; /* We have an open pty or we wouldn't he here */
14789 debug(F101,"ttptycmd PTY_PBUF_SIZE","",PTY_PBUF_SIZE);
14790 debug(F101,"ttptycmd PTY_TBUF_SIZE","",PTY_TBUF_SIZE);
14792 #ifdef PTY_USE_NDELAY
14794 NOTE: If select() and ioctl(ptyfd,FIONREAD,&n) return true indications
14795 on the pty, we don't need nonblocking reads. Performance of either
14796 method seems to be about the same, so use whatever works.
14799 x = fcntl(ptyfd,F_SETFL,fcntl(ptyfd,F_GETFL, 0)|O_NDELAY);
14800 ckmakmsg(msgbuf,500,
14801 "ttptycmd set O_NDELAY errno=",
14805 debug(F100,msgbuf,"",0);
14806 #endif /* PTY_USE_NDELAY */
14809 /* Not necessary, the protocol module already did this */
14811 #ifdef USE_CFMAKERAW
14812 if (tcgetattr(ttyfd, &term) > -1) {
14814 debug(F101,"ttptycmd net cfmakeraw errno","",errno);
14815 x tcsetattr(ttyfd, TCSANOW, &term);
14816 debug(F101,"ttptycmd net tcsetattr","",x);
14817 debug(F101,"ttptycmd net tcsetattr","",errno);
14820 if (local) /* Put network connection in */
14821 ttpkt(ttspeed,ttflow,ttprty); /* "packet mode". */
14823 conbin((char)escchr); /* OR... pty_make_raw(0) */
14824 #endif /* USE_CFMAKERAW */
14825 #endif /* COMMENT */
14829 debug(F101,"<<< ttptycmd TELOPT_ME_BINARY","",TELOPT_ME(TELOPT_BINARY));
14830 debug(F101,"<<< ttptycmd TELOPT_U_BINARY","",TELOPT_U(TELOPT_BINARY));
14832 #endif /* TNCODE */
14834 debug(F101,"ttptycmd entering loop - seconds_to_wait","",seconds_to_wait);
14836 while (have_pty || have_net) {
14837 FD_ZERO(&in); /* Initialize select() structs */
14839 FD_ZERO(&err); /* (not used because useless) */
14842 debug(F101,"ttptycmd loop top have_pty","",have_pty);
14843 debug(F101,"ttptycmd loop top have_net","",have_net);
14845 /* Pty is open and we have room to read from it? */
14846 if (have_pty && pbuf_avail < PTY_PBUF_SIZE) {
14847 debug(F100,"ttptycmd FD_SET ptyfd in","",0);
14848 FD_SET(ptyfd, &in);
14851 /* Network is open and we have room to read from it? */
14852 if (have_net && have_pty && tbuf_avail < PTY_TBUF_SIZE) {
14853 debug(F100,"ttptycmd FD_SET ttyfd in","",0);
14854 FD_SET(ttyfd, &in);
14855 if (ttyfd > nfds) nfds = ttyfd;
14857 /* Pty is open and we have stuff to write to it? */
14858 if (have_pty && tbuf_avail - tbuf_written > 0) {
14859 debug(F100,"ttptycmd FD_SET ptyfd out","",0);
14860 FD_SET (ptyfd, &out);
14861 if (ptyfd > nfds) nfds = ptyfd;
14863 /* Net is open and we have stuff to write to it? */
14864 debug(F101,"ttptycmd pbuf_avail-pbuf_written","",
14865 pbuf_avail - pbuf_written);
14866 if (have_net && pbuf_avail - pbuf_written > 0) {
14867 debug(F100,"ttptycmd FD_SET ttyfd out","",0);
14868 FD_SET (ttyfd, &out);
14869 if (ttyfd > nfds) nfds = ttyfd;
14871 /* We don't use err because it's not really for errors, */
14872 /* but for out of band data on the TCP socket, which, if it is */
14873 /* to be handled at all, is handled in the tt*() routines */
14875 nfds++; /* 0-based to 1-based */
14876 debug(F101,"ttptycmd nfds","",nfds);
14878 debug(F100,"ttptycmd NO FDs set for select","",0);
14880 /* This is not right -- sleeping won't accomplish anything */
14881 debug(F101,"ttptycmd msleep","",100);
14884 debug(F100,"ttptycmd no pty - quitting loop","",0);
14890 if (seconds_to_wait > 0L) { /* Timeout in case nothing happens */
14891 tv.tv_sec = seconds_to_wait; /* for a long time */
14897 x = select(nfds, &in, &out, NULL, tv2);
14898 debug(F101,"ttptycmd select","",x);
14900 if (errno == EINTR)
14902 debug(F101,"ttptycmd select error","",errno);
14906 debug(F101,"ttptycmd +++ select timeout","",seconds_to_wait);
14908 status = pty_get_status(ptyfd,pty_fork_pid);
14909 debug(F101,"ttptycmd pty_get_status A","",status);
14910 if (status > -1) pexitstat = status;
14915 /* We want to handle any pending writes first to make room */
14916 /* for new incoming. */
14918 if (FD_ISSET(ttyfd, &out)) { /* Can write to net? */
14920 s = pbuf + pbuf_written; /* Current spot for sending */
14922 if (is_tn) { /* ttol() doesn't double IACs */
14923 CHAR c; /* Rewrite string with IACs doubled */
14925 s = pbuf + pbuf_written; /* Source */
14927 for (i = 0; i < pbuf_avail - pbuf_written; i++) {
14928 c = s[i]; /* Next character */
14929 if (c == IAC) { /* If it's IAC */
14930 dbuf[x++] = c; /* put another one */
14931 debug(F000,">>> QUOTED IAC","",c);
14932 } else if (c != 0x0a && out_prev == 0x0d) { /* Bare CR */
14933 if (!TELOPT_ME(TELOPT_BINARY)) { /* NVT rule */
14936 debug(F000,">>> CR-NUL","",c);
14939 dbuf[x++] = c; /* Copy and count it */
14940 debug(F000,">>> char",ckitoa(in_state),c);
14943 s = dbuf; /* New source */
14945 #endif /* TNCODE */
14946 x = pbuf_avail - pbuf_written; /* How much to send */
14948 debug(F101,"ttptycmd bytes to send","",x);
14950 debug(F101,">>> ttol","",x);
14953 debug(F111,"ttptycmd ttol error",ckitoa(x),errno);
14956 write_net_bytes += x;
14959 if (FD_ISSET(ptyfd, &out)) { /* Can write to pty? */
14960 debug(F100,"ttptycmd FD_ISSET ptyfd out","",0);
14963 x = write(ptyfd,tbuf + tbuf_written,tbuf_avail - tbuf_written);
14965 /* Byte loop to rule out data overruns in the pty */
14966 /* (it makes no difference) */
14968 char *p = tbuf+tbuf_written;
14969 int n = tbuf_avail - tbuf_written;
14970 for (x = 0; x < n; x++) {
14972 if (write(ptyfd,&(p[x]),1) < 0)
14976 #endif /* COMMENT */
14977 debug(F111,"ttptycmd ptyfd write",ckitoa(errno),x);
14980 write_pty_bytes += x;
14984 if (pexitstat < 0) {
14985 status = pty_get_status(ptyfd,pty_fork_pid);
14986 debug(F101,"ttptycmd pty_get_status B","",status);
14987 if (status > -1) pexitstat = status;
14990 debug(F100,"ttptycmd +++ ptyfd write error","",0);
14993 if (FD_ISSET(ttyfd, &in)) { /* Can read from net? */
14995 debug(F100,"ttptycmd FD_ISSET ttyfd in","",0);
14996 n = in_chk(1,ttyfd);
14997 debug(F101,"ttptycmd in_chk(ttyfd)","",n);
14998 if (n < 0 || ttyfd == -1) {
14999 debug(F101,"ttptycmd +++ ttyfd errno","",errno);
15001 } else if (n > 0) {
15002 if (n > PTY_TBUF_SIZE - tbuf_avail)
15003 n = PTY_TBUF_SIZE - tbuf_avail;
15004 debug(F101,"ttptycmd net read size adjusted","",n);
15005 if (xlocal && netconn) {
15007 We have to use a byte loop here because ttxin()
15008 does not decrypt or, for that matter, handle Telnet.
15012 p = tbuf + tbuf_avail;
15013 for (x = 0; x < n; x++) {
15014 if ((c = ttinc(0)) < 0)
15016 if (!is_tn) { /* Not Telnet - keep all bytes */
15018 debug(F000,"<<< char","",c);
15020 } else { /* Telnet - must handle IAC and NVT */
15021 debug(F000,"<<< char",ckitoa(in_state),c);
15023 case 0x00: /* NUL */
15024 if (in_state == HAVE_CR) {
15025 debug(F000,"<<< SKIP","",c);
15028 debug(F000,"<<< Keep","",c);
15032 case 0x0d: /* CR */
15033 if (!TELOPT_U(TELOPT_BINARY))
15034 in_state = HAVE_CR;
15036 debug(F000,"<<< Keep","",c);
15039 case 0x0f: /* Ctrl-O */
15040 case 0x16: /* Ctrl-V */
15043 debug(F000,"<<< QUOT","",c);
15045 #endif /* COMMENT */
15046 case 0xff: /* IAC */
15047 if (in_state == HAVE_IAC) {
15048 debug(F000,"<<< KEEP","",c);
15052 debug(F000,"<<< SKIP","",c);
15053 in_state = HAVE_IAC;
15056 default: /* All others */
15057 if (in_state == HAVE_IAC) {
15060 tn_doop() will consume an unknown number of bytes and we'll overshoot
15061 the for-loop. The only Telnet command I've ever seen arrive here is
15062 a Data Mark, which comes when the remote protocol exits and the remote
15063 job returns to its shell prompt. On the assumption it's a 1-byte command,
15064 we don't write out the IAC or the command, and we clear the state. If
15065 we called tn_doop() we'd have no way of knowing how many bytes it took
15066 from the input stream.
15069 xx = tn_doop((CHAR)c,duplex,ttinc);
15070 debug(F111,"<<< DOOP",ckctoa(c),xx);
15072 debug(F101,"<<< DOOP","",c);
15073 #endif /* COMMENT */
15077 debug(F000,"<<< keep","",c);
15081 #endif /* TNCODE */
15084 ckmakmsg(msgbuf,500,
15085 "ttptycmd read net [ttinc loop] errno=",
15089 debug(F100,msgbuf,"",0);
15091 x = ttxin(n,tbuf+tbuf_avail);
15092 debug(F101,"ttptycmd ttxin x","",x);
15096 debug(F101,"ttptycmd read net error","",x);
15100 read_net_bytes += x;
15106 if (FD_ISSET(ptyfd, &in)) { /* Read from pty? */
15108 debug(F100,"ttptycmd FD_ISSET ptyfd in","",0);
15109 #ifdef PTY_USE_NDELAY
15113 This does not work on nonblocking channels
15114 on certain platforms such as NetBSD.
15116 n = pty_chk(ptyfd);
15117 #endif /* PTY_USE_NDELAY */
15118 debug(F101,"ttptycmd pty_chk() n","",n);
15123 if (n > PTY_PBUF_SIZE - pbuf_avail)
15124 n = PTY_PBUF_SIZE - pbuf_avail;
15125 debug(F101,"ttptycmd pty read size adjusted","",n);
15127 x = read(ptyfd,pbuf+pbuf_avail,n);
15130 ckmakmsg(msgbuf,500,
15131 "ttptycmd read pty errno=",
15135 debug(F100,msgbuf,"",0);
15139 if (x < 0 && errno == EAGAIN)
15142 if (x < 0) { /* This works on Solaris and Linux */
15143 pty_err++; /* but not NetBSD */
15144 debug(F100,"TERMINATION TEST A","",0);
15148 #endif /* COMMENT */
15149 if (pexitstat < 0) {
15150 status = pty_get_status(ptyfd,pty_fork_pid);
15151 debug(F101,"ttptycmd pty_get_status C","",status);
15152 if (status > -1) pexitstat = status;
15157 if (x == 0 && !pty_err) { /* This works on NetBSD but */
15158 debug(F100,"TERMINATION TEST B","",0);
15159 status = pexitstat > -1 ? pexitstat :
15160 pty_get_status(ptyfd,pty_fork_pid);
15161 debug(F101,"ttptycmd pty_get_status D","",status);
15163 pexitstat = status;
15166 } else { /* Select() lied */
15167 pty_err = 0; /* pty still there but has nothing */
15168 msleep(100); /* sleep a bit */
15172 /* Hopefully the next two are no longer needed... */
15174 #ifndef PTY_USE_NDELAY
15177 errno != 0 && errno != EAGAIN
15178 #endif /* PTY_USE_NDELAY */
15180 debug(F100,"TERMINATION TEST C","",0);
15182 debug(F101,"ttptycmd SET pty_err","",pty_err);
15183 if (errno == EIO) /* errno == EIO is like EOF */
15191 pbuf[pbuf_avail + x] = '\0';
15192 debug(F111,"ttptycmd added to pty buffer",
15193 pbuf+pbuf_avail,x);
15196 #endif /* COMMENT */
15198 read_pty_bytes += x;
15199 } else { /* n == 0 with blocking reads */
15201 "PTY READ RETURNED ZERO BYTES - SHOULD NOT HAPPEN",
15207 /* If writes have caught up to reads, reset the buffers */
15209 if (pbuf_written == pbuf_avail)
15210 pbuf_written = pbuf_avail = 0;
15211 if (tbuf_written == tbuf_avail)
15212 tbuf_written = tbuf_avail = 0;
15214 /* See if we can exit */
15216 x1 = pbuf_avail - pbuf_written;
15217 x2 = tbuf_avail - tbuf_written;
15219 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pty_err","",pty_err);
15220 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x1 [write to net]","",x1);
15221 debug(F101,"ttptycmd pty_err LOOP EXIT TEST x2 [write to pty]","",x2);
15222 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc","",rc);
15223 debug(F101,"ttptycmd pty_err LOOP EXIT TEST status","",status);
15224 debug(F101,"ttptycmd pty_err LOOP EXIT TEST pexitstat","",pexitstat);
15226 if (net_err) { /* Net error? */
15227 debug(F101,"ttptycmd net_err LOOP EXIT TEST net_err","",net_err);
15231 printf("?Connection closed\n");
15235 debug(F101,"ttptycmd net_err LOOP EXIT TEST x1","",x1);
15239 if (pty_err) { /* Pty error? */
15241 if (pexitstat < 0) {
15242 status = pty_get_status(ptyfd,pty_fork_pid);
15243 debug(F101,"ttptycmd pty_get_status E","",status);
15244 if (status > -1) pexitstat = status;
15248 if (x1 == 0 && x2 == 0) { /* If buffers are caught up */
15249 rc = 1; /* set preliminary return to success */
15250 debug(F101,"ttptycmd pty_err LOOP EXIT TEST rc 2","",rc);
15251 break; /* and exit the loop */
15255 debug(F101,"ttptycmd +++ have_pty","",have_pty);
15256 if (have_pty) { /* In case select() failed */
15257 #ifdef USE_CKUPTY_C
15263 #endif /* USE_CKUPTY_C */
15265 pty_master_fd = -1;
15266 debug(F101,"ttptycmd +++ pexitstat","",pexitstat);
15267 if (pexitstat < 0) { /* Try one last time to get status */
15268 status = pty_get_status(ptyfd,pty_fork_pid);
15269 debug(F101,"ttptycmd pty_get_status F","",status);
15270 if (status > -1) pexitstat = status;
15272 debug(F101,"ttptycmd +++ final pexitstat","",pexitstat);
15273 if (deblog) { /* Stats for debug log */
15274 debug(F101,"ttptycmd +++ pset ","",pset);
15275 debug(F101,"ttptycmd +++ pnotset","",pnotset);
15276 debug(F101,"ttptycmd +++ tset ","",tset);
15277 debug(F101,"ttptycmd +++ tnotset","",tnotset);
15279 debug(F101,"ttptycmd +++ read_pty_bytes","",read_pty_bytes);
15280 debug(F101,"ttptycmd +++ write_net_bytes","",write_net_bytes);
15281 debug(F101,"ttptycmd +++ read_net_bytes","",read_net_bytes);
15282 debug(F101,"ttptycmd +++ write_pty_bytes","",write_pty_bytes);
15285 If we got the external protocol's exit status from waitpid(), we use that
15286 to set our return code. If not, we fall back on whatever rc was previously
15287 set to, namely 1 (success) if the pty fork seemed to terminate, 0 otherwise.
15289 if (save_sigchld) { /* Restore this if we changed it */
15290 (VOID) signal(SIGCHLD,save_sigchld);
15291 save_sigchld = NULL;
15294 x = kill(pty_fork_pid,SIGHUP); /* In case it's still there */
15296 debug(F101,"ttptycmd fork kill SIGHUP","",x);
15297 if (pexitstat > -1)
15298 rc = (pexitstat == 0 ? 1 : 0);
15299 debug(F101,"ttptycmd +++ rc","",rc);
15300 if (!local) { /* If in remote mode */
15301 conres(); /* restore console to CBREAK mode */
15302 concb((char)escchr);
15306 #endif /* NETPTY */
15307 #endif /* SELECT */
15309 /* T T R U N C M D -- Redirect an external command over the connection. */
15312 TTRUNCMD is the routine that was originally used for running external
15313 protocols. It is very simple and works fine provided (a) the connection
15314 is not encrypted, and (b) the external protocol uses standard i/o
15315 (file descriptors 0 and 1) for file transfer.
15319 ttruncmd(s) char *s; {
15320 PID_T pid; /* pid of lower fork */
15321 int wstat; /* for wait() */
15326 printf("?Sorry, device is not open\n");
15330 debug(F100,"ttruncmd fail: nopush","",0);
15336 It might also be necessary to use the pty routine for other reasons,
15337 e.g. because the external program does not use stdio.
15341 If we have a network connection we use a different routine because
15342 (a) if the connection is encrypted, the mechanism used here can't deal
15343 with it; and (b) it won't handle any network protocols either, e.g.
15344 Telnet, Rlogin, K5 U-to-U, etc. However, this routine works much
15345 better (faster, more transparent) on serial connections and when
15346 C-Kermit is in remote mode (i.e. is on the far end).
15348 /* For testing always use this */
15350 return(ttptycmd(s));
15351 #endif /* NETCONN */
15355 if (tt_is_secure()) {
15357 external protocols over secure connections not supported in this OS.\n"
15361 #endif /* NETPTY */
15363 conres(); /* Make console normal */
15365 if ((pid = fork()) == 0) { /* Make a child fork */
15366 if (priv_can()) /* Child: turn off privs. */
15368 dup2(ttyfd, 0); /* Give stdin/out to the line */
15371 debug(F101,"ttruncmd system",s,x);
15372 _exit(x ? BAD_EXIT : 0);
15374 SIGTYP (*istat)(), (*qstat)();
15375 if (pid == (PID_T) -1) /* fork() failed? */
15377 istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
15378 qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
15381 while (((wstat = wait(&statusp)) != pid) && (wstat != -1)) ;
15382 #else /* Not COMMENT */
15384 wstat = wait(&statusp);
15385 debug(F101,"ttruncmd wait","",wstat);
15386 if (wstat == pid || wstat == -1)
15389 #endif /* COMMENT */
15391 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
15392 debug(F101,"ttruncmd wait statusp","",statusp);
15393 debug(F101,"ttruncmd wait pexitstat","",pexitstat);
15394 signal(SIGINT,istat); /* Restore interrupts */
15395 signal(SIGQUIT,qstat);
15397 concb((char)escchr); /* Restore console to CBREAK mode */
15398 return(statusp == 0 ? 1 : 0);
15400 #endif /* CK_REDIR */
15404 cmdate2tm(char * date, int gmt) /* date as "yyyymmdd hh:mm:ss" */
15406 cmdate2tm(date,gmt) char * date; int gmt;
15409 /* date as "yyyymmdd hh:mm:ss" */
15410 static struct tm _tm;
15413 if (strlen(date) != 17 ||
15421 _tm = *gmtime(&now);
15423 _tm = *localtime(&now);
15424 _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
15425 (date[2]-'0')*10 + (date[3]-'0')-1900;
15426 _tm.tm_mon = (date[4]-'0')*10 + (date[5]-'0')-1;
15427 _tm.tm_mday = (date[6]-'0')*10 + (date[7]-'0');
15428 _tm.tm_hour = (date[9]-'0')*10 + (date[10]-'0');
15429 _tm.tm_min = (date[12]-'0')*10 + (date[13]-'0');
15430 _tm.tm_sec = (date[15]-'0')*10 + (date[16]-'0');
15432 /* Should we set _tm.tm_isdst to -1 here? */
15446 priv_kill(pid, sig) int pid, sig; {
15450 debug(F100,"priv_kill priv_on failed","",0);
15451 i = kill(pid, sig);
15453 debug(F100,"priv_kill priv_off failed","",0);
15459 /* #ifdef BE_DR_7 */
15461 alarm() function not supplied with Be OS DR7 - this one contributed by
15466 This should mimic the UNIX/POSIX alarm() function well enough, with the
15467 caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
15468 and wait for the alarm thread to finish.
15471 alarm(unsigned int seconds) {
15472 long time_left = 0;
15474 /* If an alarm is active, turn it off, saving the unused time */
15475 if (alarm_thread != -1) {
15476 /* We'll be generous and count partial seconds as whole seconds. */
15477 time_left = alarm_struct.time -
15478 ((system_time() - time_started) / 1000000.0);
15480 /* Kill the alarm thread */
15481 kill_thread (alarm_thread);
15483 /* We need to clean up as though the alarm occured. */
15485 alarm_struct.thread = -1;
15486 alarm_struct.time = 0;
15490 /* Set a new alarm clock, if requested. */
15492 alarm_struct.thread = find_thread(NULL);
15493 alarm_struct.time = seconds;
15494 time_started = system_time();
15495 alarm_thread = spawn_thread (do_alarm,
15498 (void *) &alarm_struct
15500 resume_thread (alarm_thread);
15503 /* Now return [unused time | 0] */
15504 return ((unsigned int) time_left);
15508 This function is the departure from UNIX/POSIX alarm handling. In the case
15509 of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
15510 handler. When Be implements alarm(), this function call can be eliminated
15511 from user's SIGALRM signal handlers.
15515 alarm_expired(void) {
15518 if (alarm_thread != -1) {
15519 wait_for_thread (alarm_thread, &ret_val);
15525 This is the function that snoozes the requisite number of seconds and then
15526 SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
15527 uses thread_id; currently they are both typdef'ed as long, but I'll do the
15528 cast anyway. This function is run in a separate thread.
15532 do_alarm (void *alarm_struct) {
15533 snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
15534 kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
15536 ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
15537 ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
15539 /* #endif */ /* BE_DR_7 */
15540 #endif /* BEOSORBEBOX */
15545 p9ttyctl(char letter, int num, int param) {
15554 len = sprintf(cmd + 1, "%d", param) + 1;
15559 if (write(ttyctlfd, cmd, len) == len) {
15561 /* fprintf(stdout, "wrote '%s'\n", cmd); */
15568 p9ttyparity(char l) {
15569 return p9ttyctl('p', 0, l);
15573 p9tthflow(int flow, int status) {
15574 return p9ttyctl('m', 1, status);
15578 p9ttsspd(int cps) {
15579 if (p9ttyctl('b', 1, cps * 10) < 0)
15581 ttylastspeed = cps * 10;
15586 p9openttyctl(char *ttname) {
15589 if (ttyctlfd >= 0) {
15594 sprintf(name, "%sctl", ttname);
15595 ttyctlfd = open(name, 1);
15601 if (consctlfd >= 0) {
15602 if (write(consctlfd, "rawon", 5) == 5)
15615 if (consctlfd >= 0) {
15616 if (write(consctlfd, "rawoff", 6) == 6)
15623 p9sndbrk(int msec) {
15624 if (ttyctlfd >= 0) {
15626 int i = sprintf(cmd, "k%d", msec);
15627 if (write(ttyctlfd, cmd, i) == i)
15634 conwrite(char *buf, int n) {
15636 static int length = 0;
15637 static int holdingcr = 0;
15639 for (x = 0; x < n; x++) {
15643 write(1, buf + (x - normal), normal);
15647 /* write(noisefd, "1000 300", 8); */
15649 } else if (c == '\r') {
15651 write(1, buf + (x - normal), normal);
15656 } else if (c == '\n') {
15657 write(1, buf + (x - normal), normal + 1);
15661 } else if (c == '\b') {
15663 write(1, buf + (x - normal), normal);
15675 while (length-- > 0)
15677 length = 0; /* compiler bug */
15684 write(1, buf + (x - normal), normal);
15691 conprint(char *fmt, ...) {
15692 static char buf[1000]; /* not safe if on the stack */
15698 i = vsprintf(buf, fmt, ap);
15703 /* fprintf, printf, perror replacements... */
15705 /* f p r i n t f */
15709 #include <stdarg.h>
15710 #else /* CK_ANSIC */
15712 #include <stdarg.h>
15714 #include <varargs.h>
15715 #endif /* __GNUC__ */
15716 #endif /* CK_ANSIC */
15719 static char str1[4096];
15720 static char str2[4096];
15723 ckxfprintf(FILE * file, const char * format, ...)
15724 #else /* CK_ANSIC */
15725 ckxfprintf(va_alist) va_dcl
15726 #endif /* CK_ANSIC */
15728 int i, j, len, got_cr;
15733 va_start(args, format);
15734 #else /* CK_ANSIC */
15738 file = va_arg(args,FILE *);
15739 format = va_arg(args,char *);
15740 #endif /* CK_ANSIC */
15742 if (!inserver || (file != stdout && file != stderr && file != stdin)) {
15743 rc = vfprintf(file,format,args);
15746 rc = vsprintf(str1, format, args);
15747 len = strlen(str1);
15748 if (len >= sizeof(str1)) {
15749 debug(F101,"ckxfprintf() buffer overflow","",len);
15750 doexit(BAD_EXIT,1);
15752 for (i = 0, j = 0, got_cr = 0;
15753 i < len && j < sizeof(str1)-2;
15755 /* We can't use 255 as a case label because of signed chars */
15756 c = (unsigned)(str1[i] & 0xff);
15759 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15765 #endif /* TNCODE */
15770 && !TELOPT_ME(TELOPT_BINARY)
15771 #endif /* TNCODE */
15786 && !TELOPT_ME(TELOPT_BINARY)
15787 #endif /* TNCODE */
15796 && !TELOPT_ME(TELOPT_BINARY)
15797 #endif /* TNCODE */
15800 #ifdef CK_ENCRYPTION
15802 if (TELOPT_ME(TELOPT_ENCRYPTION))
15803 ck_tn_encrypt(str2,j);
15804 #endif /* TNCODE */
15805 #endif /* CK_ENCRYPTION */
15807 if (inserver && (ssl_active_flag || tls_active_flag)) {
15808 /* Write using SSL */
15811 if (ssl_active_flag)
15812 rc = SSL_write(ssl_con, p, j);
15814 rc = SSL_write(tls_con, p, j);
15815 debug(F111,"ckxfprintf","SSL_write",rc);
15816 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
15817 case SSL_ERROR_NONE:
15823 case SSL_ERROR_WANT_WRITE:
15824 case SSL_ERROR_WANT_READ:
15825 case SSL_ERROR_SYSCALL:
15828 case SSL_ERROR_WANT_X509_LOOKUP:
15829 case SSL_ERROR_SSL:
15830 case SSL_ERROR_ZERO_RETURN:
15835 #endif /* CK_SSL */
15836 fwrite(str2,sizeof(char),j,stdout);
15841 #endif /* fprintf */
15849 ckxprintf(const char * format, ...)
15850 #else /* CK_ANSIC */
15851 ckxprintf(va_alist) va_dcl
15852 #endif /* CK_ANSIC */
15854 int i, j, len, got_cr;
15859 va_start(args, format);
15860 #else /* CK_ANSIC */
15863 format = va_arg(args,char *);
15864 #endif /* CK_ANSIC */
15867 rc = vprintf(format, args);
15870 rc = vsprintf(str1, format, args);
15871 len = strlen(str1);
15872 if (len >= sizeof(str1)) {
15873 debug(F101,"ckxprintf() buffer overflow","",len);
15874 doexit(BAD_EXIT,1);
15876 for (i = 0, j = 0, got_cr=0;
15877 i < len && j < sizeof(str1)-2;
15879 c = (unsigned)(str1[i] & 0xff);
15882 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
15888 #endif /* TNCODE */
15893 && !TELOPT_ME(TELOPT_BINARY)
15894 #endif /* TNCODE */
15909 && !TELOPT_ME(TELOPT_BINARY)
15910 #endif /* TNCODE */
15920 && !TELOPT_ME(TELOPT_BINARY)
15921 #endif /* TNCODE */
15924 #ifdef CK_ENCRYPTION
15926 if (TELOPT_ME(TELOPT_ENCRYPTION))
15927 ck_tn_encrypt(str2,j);
15928 #endif /* TNCODE */
15929 #endif /* CK_ENCRYPTION */
15931 if (inserver && (ssl_active_flag || tls_active_flag)) {
15933 /* Write using SSL */
15935 if (ssl_active_flag)
15936 rc = SSL_write(ssl_con, p, j);
15938 rc = SSL_write(tls_con, p, j);
15939 debug(F111,"ckxprintf","SSL_write",rc);
15940 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
15941 case SSL_ERROR_NONE:
15947 case SSL_ERROR_WANT_WRITE:
15948 case SSL_ERROR_WANT_READ:
15949 case SSL_ERROR_SYSCALL:
15952 case SSL_ERROR_WANT_X509_LOOKUP:
15953 case SSL_ERROR_SSL:
15954 case SSL_ERROR_ZERO_RETURN:
15959 #endif /* CK_SSL */
15960 rc = fwrite(str2,sizeof(char),j,stdout);
15965 #endif /* printf */
15971 _PROTOTYP(char * ck_errstr,(VOID));
15979 #endif /* CK_SCOV5 */
15982 ckxperror(const char * str)
15983 #else /* CK_ANSIC */
15984 ckxperror(str) char * str;
15985 #endif /* CK_ANSIC */
15987 char * errstr = ck_errstr();
15991 #endif /* CK_SCOV5 */
15993 ckxprintf("%s%s %s\n",str,*errstr?":":"",errstr);
15995 #endif /* perror */
16000 /* Minix doesn't have a gettimeofday call (but MINIX3 does).
16001 * We fake one here using time(2)
16006 gettimeofday(struct timeval *tp, struct timezone *tzp) {
16007 tp->tv_usec = 0L; /* Close enough for horseshoes */
16008 if(time(&(tp->tv_sec))==-1)
16012 #endif /* MINIX3 */
16016 readlink(const char *path, void *buf, size_t bufsiz) {
16020 #endif /* MINIX3 */
16022 #endif /* MINIX2 */