2 char *ckxv = "Aegis Communications support, 8.0.303, 17 Apr 2004";
5 char *ckxv = "Plan 9 Communications support, 8.0.303, 17 Apr 2004";
7 char *ckxv = "UNIX Communications support, 8.0.303, 17 Apr 2004";
13 /* C-Kermit interrupt, communications control and I/O functions for UNIX */
16 Author: Frank da Cruz (fdc@columbia.edu),
17 Columbia University Academic Information Systems, New York City.
19 Copyright (C) 1985, 2004,
20 Trustees of Columbia University in the City of New York.
21 All rights reserved. See the C-Kermit COPYING.TXT file or the
22 copyright text in the ckcmai.c module for disclaimer and permissions.
26 NOTE TO CONTRIBUTORS: This file, and all the other C-Kermit files, must be
27 compatible with C preprocessors that support only #ifdef, #else, #endif,
28 #define, and #undef. Please do not use #if, logical operators, or other
29 preprocessor features in any of the portable C-Kermit modules. You can,
30 of course, use these constructions in platform-specific modules when they
31 are supported by all compilers/preprocessors that could be used on that
35 extern int nettype; /* Defined in ckcmai.c */
39 #include "ckcsym.h" /* This must go first */
40 #include "ckcdeb.h" /* This must go second */
46 #endif /* _NO_PROTO */
50 #include <errno.h> /* System error numbers */
60 #endif /* __FreeBSD__ */
62 #endif /* __386BSD__ */
66 #endif /* SCO_OSR504 */
72 #define FD_SETSIZE (3 * sizeof(long) * 8)
73 static struct timeval tv;
80 #include "ckcnet.h" /* Symbols for network types. */
86 The directory-related includes are here because we need to test some
87 file-system-related symbols to find out which system we're being compiled
88 under. For example, MAXNAMLEN is defined in BSD4.2 but not 4.1.
90 #ifdef SDIRENT /* Directory bits... */
99 #else /* !NDIR, !XNDIR */
101 #include "/usr/lib/ndir.h"
102 #else /* !RTU, !NDIR, !XNDIR */
105 #include <sys/dirent.h>
109 #else /* !RTU, !NDIR, !XNDIR, !DIRENT, i.e. all others */
122 /* I don't know why this is needed here since we never reference bzero(). */
123 /* But without it C-Kermit won't link in an HP-UX 5.xx non-TCP build. */
125 bzero(s,n) char *s; int n; {
126 extern char * memset();
129 #endif /* TCPSOCKET */
132 /* Definition of HZ, used in msleep() */
135 #define HZ ( 1000 / CLOCK_TICK )
140 #define HZ ( 1000 / CLOCK_TICK )
143 #define nap(x) (void)syscall(3112, (x))
151 #undef NGROUPS_MAX /* Prevent multiple definition warnings */
155 NOTE: HP-UX 8.0 has a <sys/poll.h>, but there is no corresponding
156 library routine, so _poll comes up undefined at link time.
159 #ifndef AIXRS /* IBM AIX needs special handling */
160 #include <poll.h> /* "standard" (SVID) i/o multiplexing, etc */
162 #ifdef SVR4 /* AIX 3.2 is like SVID... */
164 #else /* But AIX 3.1 is not ... */
165 #include <sys/poll.h> /* The include file is in include/sys */
166 #define events reqevents /* And it does not map IBM-specific member */
167 #define revents rtnevents /* names to the System V equivalents */
172 #include <signal.h> /* Signals */
174 /* For setjmp and longjmp */
183 The following test differentiates between 4.1 BSD and 4.2 & later.
184 If you have a 4.1BSD system with the DIRENT library, this test could
185 mistakenly diagnose 4.2BSD and then later enable the use of system calls
186 that aren't defined. If indeed there are such systems, we can use some
187 other way of testing for 4.1BSD, or add yet another compile-time switch.
191 #ifndef FT21 /* Except for Fortune. */
193 #ifndef BELLV10 /* And Bell Labs Research UNIX V10 */
198 #endif /* MAXNAMLEN */
201 Minix 2.0 support added by Terry McConnell,
202 Syracuse University <tmc@barnyard.syr.edu>
203 No more sgtty interface, posix compliant.
206 #define _MINIX /* Needed for some Minix header files */
207 #undef MINIX /* Old minix 1.0: used sgtty interface */
212 #include <sys/types.h>
213 #include <sys/ioctl.h>
216 #undef TIOCGETC /* defined in sys/ioctl.h, but not really supported */
221 MINIX 1.0 support added by Charles Hedrick,
222 Rutgers University <hedrick@aramis.rutgers.edu>.
223 MINIX also has V7 enabled.
232 #ifdef CK_REDIR /* <sys/wait.h> needed only for REDIRECT command. */
234 If anybody can figure out how to make this work with NeXTSTEP, be
235 my guest! (NeXTBlah/NeXTBlah/bsd/sys/wait.h does not define WEXITSTATUS)
237 #ifndef CK_WAIT_H /* If wait.h not already included... */
238 #ifdef OSF /* force OSF to select POSIX wait */
239 #ifdef _BSD /* instead of BSD (see ckcdeb.h) */
244 #include <sys/wait.h> /* Include it */
247 #define _BSD /* Restore it */
249 #endif /* CK_OSF_BSD */
251 #endif /* CK_WAIT_H */
252 #endif /* CK_REDIR */
254 #include "ckuver.h" /* Version herald */
255 char *ckxsys = HERALD;
258 #include <sys/utsname.h>
260 #ifdef TRU64 /* Tru64 UNIX 4.0 and later */
261 /* Verified on Tru64 4.0F - might break on 4.0E or earlier */
262 #include <sys/sysinfo.h> /* (don't know about OSF/1 or DU) */
263 #include <machine/hal_sysinfo.h>
266 #ifdef SOLARIS25 /* Solaris 2.5 and later */
267 #include <sys/systeminfo.h> /* (don't know about earlier ones) */
268 #endif /* SOLARIS25 */
276 static int hpis800 = 0;
277 #endif /* HPUX9PLUS */
279 #define CK_SYSNMLN SYS_NMLN
282 #define CK_SYSNMLN _SYS_NMLN
285 #define CK_SYSNMLN UTSLEN
287 #define CK_SYSNMLN 31
289 #endif /* _SYS_NMLN */
290 #endif /* SYS_NMLN */
291 char unm_mch[CK_SYSNMLN+1] = { '\0', '\0' };
292 char unm_mod[CK_SYSNMLN+1] = { '\0', '\0' };
293 char unm_nam[CK_SYSNMLN+1] = { '\0', '\0' };
294 char unm_rel[CK_SYSNMLN+1] = { '\0', '\0' };
295 char unm_ver[CK_SYSNMLN+1] = { '\0', '\0' };
296 #endif /* CK_UTSNAME */
299 #include <stat.h> /* For chasing symlinks, etc. */
301 #include <sys/stat.h>
304 /* UUCP lockfile material... */
308 #ifdef HAVE_BAUDBOY /* Red Hat baudboy/lockdev */
313 #include <libutil.h> /* FreeBSD */
315 #include <util.h> /* OpenBSD */
316 #endif /* HAVE_BAUDBOY */
317 #endif /* __FreeBSD */
318 #endif /* USE_UU_LOCK */
319 #else /* USETTYLOCK */
321 /* Name of UUCP tty device lockfile */
327 #endif /* LINUXFSSTND */
331 #endif /* ACUCNTRL */
334 PIDSTRING means use ASCII string to represent pid in lockfile.
351 #endif /* COHERENT */
356 #endif /* PIDSTRING */
358 /* Now the PIDSTRING exceptions... */
364 #endif /* PIDSTRING */
366 #ifdef __bsdi__ /* BSDI (at least thru 1.1) */
369 #endif /* PIDSTRING */
370 #endif /* __bsdi__ */
372 #ifdef OSF32 /* Digital UNIX (OSF/1) 3.2 */
375 #endif /* PIDSTRING */
379 LOCK_DIR is the name of the lockfile directory.
380 If LOCK_DIR is already defined (e.g. on command line), we don't change it.
385 #define LOCK_DIR "/var/spool/lock"
392 #define LOCK_DIR "/var/spool/lock"
395 #define LOCK_DIR "/var/spool/lock"
398 #define LOCK_DIR "/var/spool/lock"
401 #define LOCK_DIR "/var/spool/lock"
403 /* So which ones is this for? */
404 /* Probably original 4.4BSD on Vangogh */
405 /* Plus who knows about Mac OS X... It doesn't even have a cu program */
406 #define LOCK_DIR "/var/spool/uucp"
407 #endif /* __OpenBSD__ */
408 #endif /* __NetBSD__ */
409 #endif /* __FreeBSD__ */
410 #endif /* __386BSD__ */
413 #define LOCK_DIR "/var/spool/locks"
416 #define LOCK_DIR "/var/spool/locks"
418 #ifdef RTAIX /* IBM RT PC AIX 2.2.1 */
419 #define LOCK_DIR "/etc/locks"
422 #define LOCK_DIR "/etc/locks"
425 #define LOCK_DIR "/etc/locks"
429 #define LOCK_DIR "/usr/spool/uucp"
432 #define LOCK_DIR "/usr/spool/uucp"
435 #define LOCK_DIR "/var/spool/locks"
438 #define LOCK_DIR "/var/spool/locks"
441 #define LOCK_DIR "/var/lock";
443 #define LOCK_DIR "/usr/spool/locks"
444 #endif /* LINUXFSSTND */
451 #define LOCK_DIR "/usr/spool/uucp/LCK"
454 #define LOCK_DIR "/usr/spool/uucp"
456 #define LOCK_DIR "/usr/spool/uucp"
457 #endif /* COHERENT */
466 #endif /* !LOCK_DIR (outside ifndef) */
468 #ifdef OSF2 /* OSF/1 2.0 or later */
469 #ifdef LOCK_DIR /* (maybe 1.x too, who knows...) */
471 #define LOCK_DIR "/var/spool/locks"
472 #endif /* LOCK_DIR */
476 /* Sorry no more lockf() -- we lock first and THEN open the device. */
480 #define LOCKF /* Use lockf() on tty device in SVR4 */
486 #ifdef NOLOCKF /* But NOLOCKF cancels LOCKF */
492 /* More about this below... */
494 #endif /* USETTYLOCK */
498 MYREAD means use our internally defined nonblocking buffered read routine.
508 /* bits for attmodem: internal modem in use, restart getty */
522 #define O_NDELAY O_NONBLOCK
523 #endif /* O_NDELAY */
524 #endif /* __bsdi__ */
527 Variables available to outside world:
529 dftty -- Pointer to default tty name string, like "/dev/tty".
530 dfloc -- 0 if dftty is console, 1 if external line.
531 dfprty -- Default parity
532 dfflow -- Default flow control
533 ckxech -- Flag for who echoes console typein:
534 1 - The program (system echo is turned off)
535 0 - The system (or front end, or terminal).
536 functions that want to do their own echoing should check this flag
539 flfnam -- Name of lock file, including its path, e.g.,
540 "/usr/spool/uucp/LCK..cul0" or "/etc/locks/tty77"
541 lkflfn -- Name of link to lock file, including its paths
542 haslock -- Flag set if this kermit established a uucp lock.
543 lockpid -- PID of other process that has desired line open, as string.
544 backgrd -- Flag indicating program executing in background ( & on
545 end of shell command). Used to ignore INT and QUIT signals.
546 rtu_bug -- Set by stptrap(). RTU treats ^Z as EOF (but only when we handle
549 Functions for assigned communication line (either external or console tty):
551 sysinit() -- System dependent program initialization
552 syscleanup() -- System dependent program shutdown
553 ttopen(ttname,local,mdmtyp,timo) -- Open the named tty for exclusive access.
554 ttclos() -- Close & reset the tty, releasing any access lock.
555 ttsspd(cps) -- Set the transmission speed of the tty.
556 ttgspd() -- Get (read) the the transmission speed of the tty.
557 ttpkt(speed,flow,parity) -- Put the tty in packet mode and set the speed.
558 ttvt(speed,flow) -- Put the tty in virtual terminal mode.
559 or in DIALING or CONNECTED modem control state.
560 ttres() -- Restore original tty modes.
561 ttscarr(carrier) -- Set carrier control mode, on/off/auto.
562 ttinl(dest,max,timo) -- Timed read line from the tty.
563 ttinc(timo) -- Timed read character from tty.
564 myread() -- Raw mode bulk buffer read, gives subsequent
565 chars one at a time and simulates FIONREAD.
566 myunrd(c) -- Places c back in buffer to be read (one only)
567 ttchk() -- See how many characters in tty input buffer.
568 ttxin(n,buf) -- Read n characters from tty (untimed).
569 ttol(string,length) -- Write a string to the tty.
570 ttoc(c) -- Write a character to the tty.
571 ttflui() -- Flush tty input buffer.
572 ttsndb() -- Send BREAK signal.
573 ttsndlb() -- Send Long BREAK signal.
575 ttlock(ttname) -- "Lock" tty device against uucp collisions.
576 ttunlck() -- Unlock tty device.
578 For ATT7300/Unix PC, System V:
579 attdial(ttname,speed,telnbr) -- dials ATT7300/Unix PC internal modem
580 offgetty(ttname) -- Turns off getty(1m) for comms line
581 ongetty(ttname) -- Restores getty() to comms line
585 Functions for console terminal:
587 congm() -- Get console terminal modes.
588 concb(esc) -- Put the console in single-character wakeup mode with no echo.
589 conbin(esc) -- Put the console in binary (raw) mode.
590 conres() -- Restore the console to mode obtained by congm().
591 conoc(c) -- Unbuffered output, one character to console.
592 conol(s) -- Unbuffered output, null-terminated string to the console.
593 conola(s) -- Unbuffered output, array of strings to the console.
594 conxo(n,s) -- Unbuffered output, n characters to the console.
595 conchk() -- Check if characters available at console (bsd 4.2).
596 Check if escape char (^\) typed at console (System III/V).
597 coninc(timo) -- Timed get a character from the console.
598 congks(timo) -- Timed get keyboard scan code.
599 conint() -- Enable terminal interrupts on the console if not background.
600 connoi() -- Disable terminal interrupts on the console if not background.
604 msleep(m) -- Millisecond sleep
605 ztime(&s) -- Return pointer to date/time string
606 rtimer() -- Reset timer
607 gtimer() -- Get elapsed time since last call to rtimer()
610 /* Conditional Includes */
612 /* Whether to include <sys/file.h> */
614 #ifdef RTU /* RTU doesn't */
618 #ifdef CIE /* CIE does. */
622 #ifdef BSD41 /* 4.1 BSD doesn't */
626 #ifdef is68k /* Integrated Solutions 68000 UNIX */
627 #define NOFILEH /* e.g. on Plexux P60 and Sun-1 */
630 #ifdef MINIX /* MINIX */
634 #ifdef COHERENT /* Coherent */
636 #endif /* COHERENT */
638 #ifndef NOFILEH /* Now include if selected. */
639 #include <sys/file.h>
644 #ifdef BSD44ORPOSIX /* POSIX uses termios.h */
648 #undef _POSIX_SOURCE /* Get extra stuff from termios.h */
650 #endif /* __bsdi__ */
653 #include <sys/ioctl.h>
664 #define _POSIX_SOURCE
666 #endif /* __bsdi__ */
667 #ifndef BSD44 /* Really POSIX */
668 #ifndef CK_QNX32 /* was CK_QNX32 */
669 #define NOSYSIOCTLH /* No ioctl's allowed. */
670 #undef ultrix /* Turn off any ultrix features. */
671 #endif /* CK_QNX32 */
675 /* System III, System V */
684 /* Need this for termiox structure, RTS/CTS and DTR/CD flow control */
686 struct termiox rctsx;
690 /* Sorry, this is truly disgusting but it's SCO's fault. */
695 #endif /* SCO_OSR504 */
696 #include <sys/termiox.h>
697 struct termiox rctsx;
701 #endif /* CK_SVID3_X */
702 #endif /* STERMIOX */
706 #ifdef COHERENT /* Use termio.h, not sgtty.h for Coherent */
708 #endif /* COHERENT */
710 #ifdef MINIX /* MINIX uses ioctl's */
711 #define NOSYSIOCTLH /* but has no <sys/ioctl.h> */
716 #ifndef NOSYSIOCTLH /* Others use ioctl() */
719 This is to get rid of cpp warning messages that occur because all of
720 these symbols are defined by both termios.h and ioctl.h on the SUN.
742 #include <sys/ioctl.h>
743 #endif /* NOSYSIOCTLH */
745 We really, really, REALLY want FIONREAD, because it is the only way to find
746 out not just *if* stuff is waiting to be read, but how much, which is
747 critical to our sliding-window and streaming procedures, not to mention
748 efficiency of CONNECT, etc.
751 #include <sys/filio.h> /* For FIONREAD */
758 /* It wasn't found in ioctl.h or term*.h - try these places: */
760 #include <sys/filio.h>
763 #include <sys/filio.h>
765 #endif /* UNIXWARE */
766 #endif /* FIONREAD */
768 #ifdef XENIX /* Was M_UNIX but XENIX implies M_UNIX and applies to XENIX too */
770 <sys/socket.h> included above via "ckcnet.h" defines FIONREAD as
771 something. Due to this, in_chk() uses the FIONREAD instead of RDCHK
772 and the hot keys during file transfer (X to cancel file etc) do not
773 work because FIONREAD doesn't work even though it is defined.
775 NOTE: This might also be true elsewhere.
779 #endif /* FIONREAD */
782 #ifdef CK_SCOV5 /* Ditto for SCO OpenServer 5.0 */
785 #endif /* FIONREAD */
788 /* Whether to include <fcntl.h> */
790 #ifndef is68k /* Only a few don't have this one. */
796 #endif /* COHERENT */
800 #endif /* not is68k */
806 #include <sys/fcntl.h>
808 #endif /* COHERENT */
810 #ifdef ATT7300 /* Unix PC, internal modem dialer */
811 #include <sys/phone.h>
814 #ifdef HPUX /* HP-UX variations. */
816 #include <sys/modem.h> /* HP-UX modem signals */
817 #ifdef hp9000s500 /* Model 500 */
819 #endif /* hp9000s500 */
823 #endif /* HPUXPRE65 */
825 #include <sys/bsdtty.h> /* HP-UX Berkeley tty support */
826 #endif /* HPUXJOBCTL */
830 Which time.h files to include... See ckcdeb.h for defaults.
831 Note that 0, 1, 2, or all 3 of these can be included according to
832 the symbol definitions.
842 #include <sys/time.h>
843 #endif /* SYSTIMEH */
844 #endif /* NOSYSTIMEH */
848 #include <sys/timeb.h>
849 #endif /* SYSTIMEBH */
850 #endif /* NOSYSTIMEBH */
855 In certain POSIX builds (like Unixware 7), <[sys/]time.h> refuses to
856 define the structs we need to access the higher speeds, so we have to
867 #endif /* DCLTIMEVAL */
868 #endif /* NODCLTIMEVAL */
871 /* THIS IS OBSOLETE since about Linux 0.92 */
873 #include <linux/serial.h>
874 #endif /* OLINUXHISPEED */
875 #ifdef __alpha__ /* Linux on DEC Alpha */
876 #ifndef __GLIBC__ /* But not with glibc */
877 #include <asm/termios.h>
878 #endif /* __GLIBC__ */
879 #endif /* __alpha__ */
880 #endif /* __linux__ */
882 #ifdef NOIEXTEN /* This is broken on some systems */
883 #undef IEXTEN /* like Convex/OS 9.1 */
884 #endif /* NOIEXTEN */
885 #ifndef IEXTEN /* Turn off ^O/^V processing. */
886 #define IEXTEN 0 /* Needed, at least, on BSDI. */
889 Pick up definitions needed for select() if we don't have them already.
890 Normally they come from <sys/types.h> but some systems get them from
891 <sys/select.h>... Rather than hardwire all of them into the source, we
892 include it if SELECT_H is defined in compile-time CFLAGS.
896 #include <sys/select.h>
897 #endif /* SELECT_H */
898 #endif /* SCO_OSR504 */
901 #include "/sys/ins/base.ins.c"
902 #include "/sys/ins/error.ins.c"
903 #include "/sys/ins/ios.ins.c"
904 #include "/sys/ins/sio.ins.c"
905 #include "/sys/ins/pad.ins.c"
906 #include "/sys/ins/time.ins.c"
907 #include "/sys/ins/pfm.ins.c"
908 #include "/sys/ins/pgm.ins.c"
909 #include "/sys/ins/ec2.ins.c"
910 #include "/sys/ins/type_uids.ins.c"
911 #include <default_acl.h>
916 #ifdef sxaE50 /* PFU Compact A SX/A TISP V10/L50 */
920 /* The following #defines are catch-alls for those systems */
921 /* that didn't have or couldn't find <file.h>... */
933 #endif /* O_RDONLY */
937 Modem signals are also forbidden in the POSIX world. But some POSIX-based
938 platforms let us at them anyway if we know where to look.
941 /* Doesn't work for Linux */
944 #endif /* UNIXWARE7 */
945 #endif /* NEEDMDMDEFS */
949 #define TIOCMGET (('t'<<8)|29)
950 #endif /* TIOCMGET */
953 #define TIOCM_DTR 0x0002
954 #endif /* TIOCM_DTR */
956 #define TIOCM_RTS 0x0004
957 #endif /* TIOCM_RTS */
959 #define TIOCM_CTS 0x0020
960 #endif /* TIOCM_CTS */
962 #define TIOCM_CAR 0x0040
963 #endif /* TIOCM_CAR */
965 #define TIOCM_RNG 0x0080
966 #endif /* TIOCM_RNG */
968 #define TIOCM_DSR 0x0100
969 #endif /* TIOCM_DSR */
970 #endif /* NEEDMDMDEFS */
971 #endif /* SVORPOSIX */
980 #define TCGETA TCGETS
981 #define TCSETA TCSETS
982 #define TCSETAW TCSETSW
983 #define TCSETAF TCSETSF
984 #define termio termios
987 #ifdef SVORPOSIX /* AT&T Sys V or POSIX */
988 #ifdef UNIXWAREPOSIX /* UnixWare 7 POSIX build */
990 In Unixware POSIX builds, <[sys/]time.h> refuses to define the
991 structs we need to access the higher speeds, so we have to do it
1002 #endif /* UNIXWAREPOSIX */
1003 #endif /* SVORPOSIX */
1008 Because Xenix <time.h> doesn't declare time() if we're using gcc.
1012 #endif /* __GNUC__ */
1014 /* Special stuff for V7 input buffer peeking */
1017 int kmem[2] = { -1, -1};
1018 char *initrawq(), *qaddr[2]={0,0};
1023 /* dftty is the device name of the default device for file transfer */
1024 /* dfloc is 0 if dftty is the user's console terminal, 1 if an external line */
1027 char * dftty = NULL;
1028 char * dfmdm = "none";
1029 int dfloc = 0; /* that goes in local mode by default */
1033 char *dftty = "/dev/com1.dout"; /* Only example so far of a system */
1034 char *dfmdm = "none";
1035 int dfloc = 1; /* that goes in local mode by default */
1037 char *dftty = CTTNAM; /* Remote by default, use normal */
1038 char *dfmdm = "none";
1039 int dfloc = 0; /* controlling terminal name. */
1042 char *dftty = DFTTY; /* Default location specified on */
1043 char *dfmdm = "none"; /* command line. */
1044 int dfloc = 1; /* controlling terminal name. */
1048 #define CON_RES 0 /* Console state is "reset" */
1049 #define CON_CB 1 /* Console state is CBREAK */
1050 #define CON_BIN 2 /* Console state is binary */
1051 static int constate = CON_RES;
1053 #define CONI_RES 0 /* Console interrupts are "reset" */
1054 #define CONI_INT 1 /* Console intterupts are set */
1055 #define CONI_NOI 2 /* Console intterupts are disabled */
1056 static int conistate = CONI_RES;
1059 #define CONBUFSIZ 15
1061 #define CONBUFSIZ 255
1062 #endif /* CK_SMALL */
1063 static char conbuf[CONBUFSIZ]; /* Console readahead buffer */
1064 static int conbufn = 0; /* Chars in readahead buffer */
1065 static char *conbufp = conbuf; /* Next char in readahead buffer */
1067 char cttnam[DEVNAMLEN+1] = { '\0', '\0' }; /* Determined at runtime */
1070 int rtu_bug = 0; /* set to 1 when returning from SIGTSTP */
1073 int dfprty = DEFPAR; /* Default parity (0 = none) */
1074 int ttprty = 0; /* The parity that is in use. */
1075 static int ttpmsk = 0xff; /* Parity stripping mask. */
1076 int ttmdm = 0; /* Modem in use. */
1077 int ttcarr = CAR_AUT; /* Carrier handling mode. */
1078 int dfflow = FLO_NONE; /* Default flow control is NONE */
1079 int backgrd = 0; /* Assume in foreground (no '&' ) */
1081 int iniflags = -1; /* fcntl flags for ttyfd */
1082 #endif /* F_SETFL */
1083 int fdflag = 0; /* Flag for redirected stdio */
1084 int ttfdflg = 0; /* Open File descriptor was given */
1085 int tvtflg = 0; /* Flag that ttvt has been called */
1086 long ttspeed = -1L; /* For saving speed */
1087 int ttflow = -9; /* For saving flow */
1088 int ttld = -1; /* Line discipline */
1091 static int km_con = -1; /* Kanji mode for console tty */
1092 static int km_ext = -1; /* Kanji mode for external device */
1093 #endif /* sony_news */
1096 static int needpchk = 1; /* Need parity check */
1098 static int needpchk = 0;
1099 #endif /* PARSENSE */
1101 extern int stopbits; /* Stop bits */
1104 Unfortunately we must do this with global variables rather than through the
1105 tt...() APIs to avoid changing the APIs and the many modules that use them.
1106 If hwparity != 0, this indicates 8 data bits + parity, rather than 7 data
1107 bits + parity or 8 data bits and no parity, and overrides the regular parity
1108 variable, which is communicated to this module thru ttpkt(), and represented
1109 locally by the ttprty variable.
1111 extern int hwparity; /* Hardware parity */
1112 #endif /* HWPARITY */
1116 static int nodelay_sav = -1;
1117 #endif /* TCP_NODELAY */
1118 #endif /* TCPSOCKET */
1120 static int sigint_ign = 0; /* SIGINT is ignored */
1123 Having this module rely on external globals is bad, but fixing this
1124 requires overhaul of the ck*tio.c modules for all the different operating
1125 systems supported by C-Kermit. Left for a future release.
1127 extern int ttnproto; /* Defined in ckcnet.c */
1128 extern int ttnet; /* Defined in ckcnet.c */
1129 extern int nopush, xfrcan, xfrchr, xfrnum; /* Defined in ckcmai.c */
1130 extern int xsuspend, wasclosed;
1131 extern int inserver, local;
1133 int ckxech = 0; /* 0 if system normally echoes console characters, else 1 */
1135 int ckmaxfiles = 0; /* Max number of open files */
1137 #ifdef CK_ENCRYPTION /* Kerberos */
1139 extern int me_encrypt, u_encrypt;
1140 #endif /* CK_ENCRYPTION */
1142 /* Declarations of variables global within this module */
1144 #ifdef TTLEBUF /* See ckcnet.h */
1146 #define LEBUFSIZ 4096
1147 static CHAR le_buf[LEBUFSIZ];
1148 static int le_start = 0, le_end = 0, le_data = 0;
1149 #endif /* TTLEBUF */
1151 static int gotsigs = 0;
1153 static time_t tcount = (time_t)0; /* Elapsed time counter */
1155 static SIGTYP (*saval)() = NULL; /* For saving alarm() handler */
1156 static SIGTYP (*savquit)() = NULL; /* and other signal handlers */
1158 static SIGTYP (*savusr1)() = NULL;
1159 #endif /* SIGUSR1 */
1161 static SIGTYP (*savusr2)() = NULL;
1162 #endif /* SIGUSR2 */
1164 static SIGTYP (*savpipe)() = NULL;
1165 #endif /* SIGPIPE */
1167 static SIGTYP (*savdanger)() = NULL;
1168 #endif /* SIGDANGER */
1171 static SIGTYP (*jchdlr)() = NULL; /* For checking suspend handler */
1173 static int jcshell = -1; /* And flag for result */
1176 BREAKNULS is defined for systems that simulate sending a BREAK signal
1177 by sending a bunch of NUL characters at low speed.
1182 #endif /* BREAKNULS */
1188 #endif /* BREAKNULS */
1192 static char /* A string of nulls */
1193 *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";
1194 #endif /* BREAKNULS */
1196 #ifdef CK_POSIX_SIG /* Longjump buffers */
1197 static sigjmp_buf sjbuf; /* POSIX signal handling */
1199 static jmp_buf sjbuf;
1200 #endif /* CK_POSIX_SIG */
1203 static jmp_buf jjbuf;
1206 /* static */ /* (Not static any more) */
1207 int ttyfd = -1; /* TTY file descriptor */
1209 int ttpipe = 0; /* NETCMD: Use pipe instead of ttyfd */
1210 int ttpty = 0; /* NETPTY: Use pty instead of ttfyd */
1214 static int pipe0[2], pipe1[2]; /* Pipes for net i/o */
1215 #endif /* NETCONN */
1216 static PID_T ttpid = 0; /* Process ID for fork */
1217 static int fdin, fdout; /* File descriptors for pipe */
1218 static FILE * ttout = NULL; /* File pointer for output pipe */
1220 /* fdopen() needs declaring because it's not declared in <stdio.h> */
1221 _PROTOTYP( FILE * fdopen, (int, char *) );
1222 #endif /* DCLFDOPEN */
1225 extern int pexitstat, quiet;
1228 int ttyctlfd = -1; /* TTY control channel - What? UNIX doesn't have one? */
1229 int consctlfd = -1; /* Console control channel */
1230 int noisefd = -1; /* tone channel */
1231 static int ttylastspeed = -1; /* So we can lie about the speed */
1234 int telnetfd = 0; /* File descriptor is for telnet */
1236 int x25fd = 0; /* File descriptor is for X.25 */
1237 #endif /* NETCONN */
1239 char lockpid[16] = { '\0', '\0' }; /* PID stored in lockfile, as string */
1241 static int lkf = 0, /* Line lock flag */
1242 cgmf = 0, /* Flag that console modes saved */
1243 xlocal = 0, /* Flag for tty local or remote */
1244 curcarr = 0; /* Carrier mode: require/ignore. */
1246 static int netconn = 0; /* 1 if network connection active */
1248 static char escchr; /* Escape or attn character */
1251 #include <sys/time.h>
1252 #endif /* CK_SCO32V4 */
1255 static struct timeval tv; /* For getting time, from sys/time.h */
1256 #endif /* HAVE_TV */
1258 static struct timezone tz;
1259 #endif /* HAVE_TZ */
1262 static struct timeb ftp; /* And from sys/timeb.h */
1266 static long xclock; /* For getting time from sys/time.h */
1267 static struct timeb ftp; /* And from sys/timeb.h */
1271 static long xclock; /* For getting time from sys/time.h */
1272 static struct timeb ftp; /* And from sys/timeb.h */
1276 static long xclock; /* For getting time from sys/time.h */
1277 static struct timeb ftp; /* And from sys/timeb.h */
1278 #endif /* BELLV10 */
1281 static long xclock; /* For getting time from sys/time.h */
1282 static struct timeb ftp; /* And from sys/timeb.h */
1286 static long xclock; /* For getting time from sys/time.h */
1287 static struct timeb ftp; /* And from sys/timeb.h */
1291 static long xclock; /* For getting time from sys/time.h */
1292 static struct timeb ftp; /* And from sys/timeb.h */
1293 #endif /* COHERENT */
1299 /* sgtty/termio information... */
1301 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
1302 static struct termios
1303 ttold, ttraw, tttvt, ttcur,
1304 ccold, ccraw, cccbrk;
1305 #else /* BSD, V7, etc */
1307 #ifdef COHERENT /* Hack alert... */
1309 #endif /* COHERENT */
1312 static struct termio ttold = {0}; /* Init'd for word alignment, */
1313 static struct termio ttraw = {0}; /* which is important for some */
1314 static struct termio tttvt = {0}; /* systems, like Zilog... */
1315 static struct termio ttcur = {0};
1316 static struct termio ccold = {0};
1317 static struct termio ccraw = {0};
1318 static struct termio cccbrk = {0};
1320 static struct sgttyb /* sgtty info... */
1321 ttold, ttraw, tttvt, ttcur, /* for communication line */
1322 ccold, ccraw, cccbrk; /* and for console */
1324 static struct ttydevb /* Device info... */
1325 tdold, tdcur; /* for communication device */
1326 #endif /* BELLV10 */
1328 static struct tchars tchold, tchnoi;
1331 #endif /* TIOCGETC */
1333 static struct ltchars ltchold, ltchnoi;
1335 #endif /* TIOCGLTC */
1336 int lmodef = 0; /* Local modes */
1339 #endif /* BSD44ORPOSIX */
1342 /* It picks up the speeds but they don't work */
1343 #ifdef UNIXWARE /* For higher serial speeds */
1344 #ifdef UW7 /* in Unixware 7.0 */
1345 #include <sys/asyc.h> /* This picks up 57600 and 115200 */
1347 #endif /* UNIXWARE */
1348 #endif /* COMMENT */
1351 static struct sgttyb ttbuf;
1355 /* do we really need this? */
1356 static struct sgttyb vanilla;
1360 static int attmodem = 0; /* ATT7300 internal-modem status */
1361 struct updata dialer = {0}; /* Condition dialer for data call */
1362 #endif /* ATT7300 */
1368 char lkflfn[FLFNAML] = { '\0', '\0' }; /* and possible link to it */
1370 char lock2[FLFNAML] = { '\0', '\0' }; /* Name of second lockfile */
1371 #endif /* USETTYLOCK */
1375 char flfnam[FLFNAML+1] = { '\0', '\0' }; /* UUCP lock file path name */
1377 int haslock = 0; /* =1 if this kermit locked uucp */
1381 static int conesc = 0; /* set to 1 if esc char (^\) typed */
1384 static int conesc = 0;
1387 static int conesc = 0;
1390 #endif /* SVORPOSIX */
1393 /* Local copy of comm device name or network host */
1394 static char ttnmsv[DEVNAMLEN+1] = { '\0', '\0' };
1396 static char lockname[DEVNAMLEN+1]; /* Ditto, the part after "/dev/". */
1397 #endif /* USETTYLOCK */
1400 static status_$t st; /* error status return value */
1401 static short concrp = 0; /* true if console is CRP pad */
1402 static uid_$t ttyuid; /* tty type uid */
1403 static uid_$t conuid; /* stdout type uid */
1405 /* APOLLO Aegis main()
1406 * establish acl usage and cleanup handling
1407 * this makes sure that CRP pads
1408 * get restored to a usable mode
1410 main(argc,argv) int argc; char **argv; {
1412 pfm_$cleanup_rec dirty;
1414 PID_T pid = getpid();
1416 /* acl usage according to invoking environment */
1417 default_acl(USE_DEFENV);
1419 /* establish a cleanup continuation */
1420 status = pfm_$cleanup(dirty);
1421 if (status.all != pfm_$cleanup_set) {
1422 /* only handle faults for the original process */
1423 if (pid == getpid() && status.all > pgm_$max_severity) {
1424 /* blew up in main process */
1426 pfm_$cleanup_rec clean;
1428 /* restore the console in any case */
1431 /* attempt a clean exit */
1432 debug(F101, "cleanup fault status", "", status.all);
1434 /* doexit(), then send status to continuation */
1435 quo = pfm_$cleanup(clean);
1436 if (quo.all == pfm_$cleanup_set)
1437 doexit(pgm_$program_faulted,-1);
1438 else if (quo.all > pgm_$max_severity)
1439 pfm_$signal(quo); /* blew up in doexit() */
1441 /* send to the original continuation */
1442 pfm_$signal(status);
1445 return(ckcmai(argc, argv));
1449 /* ANSI-style prototypes for internal functions. */
1450 /* Functions used outside this module are prototyped in ckcker.h. */
1453 _PROTOTYP( SIGTYP timerh, () );
1454 _PROTOTYP( SIGTYP cctrap, () );
1455 _PROTOTYP( SIGTYP esctrp, () );
1456 _PROTOTYP( SIGTYP sig_ign, () );
1458 _PROTOTYP( SIGTYP timerh, (int) );
1459 _PROTOTYP( SIGTYP cctrap, (int) );
1460 _PROTOTYP( SIGTYP esctrp, (int) );
1462 _PROTOTYP( int do_open, (char *) );
1463 _PROTOTYP( static int in_chk, (int, int) );
1464 _PROTOTYP( static int ttrpid, (char *) );
1465 _PROTOTYP( static int ttchkpid, (char *) );
1466 _PROTOTYP( static int ttlock, (char *) );
1467 _PROTOTYP( static int ttunlck, (void) );
1468 _PROTOTYP( int mygetbuf, (void) );
1469 _PROTOTYP( int myfillbuf, (void) );
1470 _PROTOTYP( VOID conbgt, (int) );
1472 _PROTOTYP( VOID acucntrl, (char *, char *) );
1473 #endif /* ACUCNTRL */
1476 _PROTOTYP( int carrctl, (struct termios *, int) );
1479 _PROTOTYP( int carrctl, (struct termio *, int) );
1481 _PROTOTYP( int carrctl, (struct sgttyb *, int) );
1483 #endif /* BSD44ORPOSIX */
1486 _PROTOTYP( int attdial, (char *, long, char *) );
1487 _PROTOTYP( int offgetty, (char *) );
1488 _PROTOTYP( int ongetty, (char *) );
1489 #endif /* ATT7300 */
1493 /* BeOS is not capable of using SELECT on anything but sockets */
1496 #include <kernel/OS.h>
1497 /* #ifdef BE_DR_7 */
1498 static double time_started = 0.0;
1499 struct ALARM_STRUCT {
1503 static thread_id alarm_thread = -1;
1504 static struct ALARM_STRUCT alarm_struct;
1505 _PROTOTYP( long do_alarm, (void *) );
1506 _PROTOTYP( unsigned int alarm, (unsigned int) );
1507 _PROTOTYP( void alarm_expired, (void) );
1508 /* #endif */ /* BE_DR_7 */
1509 #endif /* BEOSORBEBOX */
1512 #define xunchar(ch) (((ch) - 32 ) & 0xFF ) /* Character to number */
1513 #endif /* xunchar */
1517 xxlast(char *s, char c)
1520 xxlast(s,c) char *s; char c;
1521 #endif /* CK_ANSIC */
1522 /* xxlast */ { /* Last occurrence of character c in string s. */
1524 for (i = (int)strlen(s); i > 0; i--)
1525 if (s[i-1] == c ) return(s + (i - 1));
1529 /* Timeout handler for communication line input functions */
1533 timerh(foo) int foo; {
1536 /* #ifdef BE_DR_7 */
1538 /* #endif */ /* BE_DR_7 */
1539 #endif /* BEOSORBEBOX */
1541 siglongjmp(sjbuf,1);
1544 #endif /* CK_POSIX_SIG */
1549 xtimerh(foo) int foo; { /* Like timerh() but does */
1550 #ifdef BEOSORBEBOX /* not reset the timer itslef */
1551 /* #ifdef BE_DR_7 */
1553 /* #endif */ /* BE_DR_7 */
1554 #endif /* BEOSORBEBOX */
1556 siglongjmp(sjbuf,1);
1559 #endif /* CK_POSIX_SIG */
1563 /* Control-C trap for communication line input functions */
1565 int cc_int; /* Flag */
1566 SIGTYP (* occt)(); /* For saving old SIGINT handler */
1570 cctrap(foo) int foo; { /* Needs arg for ANSI C */
1571 cc_int = 1; /* signal() prototype. */
1575 /* S Y S I N I T -- System-dependent program initialization. */
1578 * ttgwsiz() returns:
1579 * 1 tt_rows and tt_cols are known, both altered, both > 0
1580 * 0 tt_rows and/or tt_cols are known, both altered, one or both <= 0
1581 * -1 tt_rows and tt_cols are unknown and unaltered
1584 extern int tt_rows, tt_cols;
1589 int rows = 0, cols = 0;
1590 p = getenv("LINES");
1591 debug(F110,"xttgwsiz LINES",p,0);
1595 p = getenv("COLUMNS");
1596 debug(F110,"xttgwsiz COLUMNS",p,0);
1613 le_init() { /* LocalEchoInit() */
1615 for (i = 0; i < LEBUFSIZ; i++)
1623 le_clean() { /* LocalEchoCleanup() */
1631 if (le_start != le_end) {
1634 LEBUFSIZ) % LEBUFSIZ;
1636 debug(F111,"le_inbuf","chars waiting",rc);
1644 le_putchar(ch) CHAR ch;
1645 #endif /* CK_ANSIC */
1648 /* In UNIX we do not have another thread taking chars out of the buffer */
1649 while ((le_start - le_end == 1) ||
1650 (le_start == 0 && le_end == LEBUFSIZ - 1)) {
1651 /* Buffer is full */
1652 debug(F111,"le_putchar","Buffer is Full",ch);
1653 ReleaseLocalEchoMutex() ;
1655 RequestLocalEchoMutex( SEM_INDEFINITE_WAIT ) ;
1658 if ((le_start - le_end + LEBUFSIZ)%LEBUFSIZ == 1) {
1659 debug(F110,"le_putchar","buffer is full",0);
1662 #endif /* COMMENT */
1663 le_buf[le_end++] = ch;
1664 if (le_end == LEBUFSIZ)
1672 le_puts(CHAR * s, int n)
1674 le_puts(s,n) CHAR * s; int n;
1675 #endif /* CK_ANSIC */
1679 CHAR * p = (CHAR *)"le_puts";
1681 for (i = 0; i < n; i++)
1682 rc = le_putchar((char)s[i]);
1683 debug(F101,"le_puts","",rc);
1691 le_putstr(s) CHAR * s;
1692 #endif /* CK_ANSIC */
1696 p = (CHAR *)"le_putstr";
1697 hexdump(p,s,(int)strlen((char *)s));
1698 for (p = s; *p && !rc; p++)
1699 rc = le_putchar(*p);
1705 le_getchar(CHAR * pch)
1706 #else /* CK_ANSIC */
1707 le_getchar(pch) CHAR * pch;
1708 #endif /* CK_ANSIC */
1711 if (le_start != le_end) {
1712 *pch = le_buf[le_start];
1713 le_buf[le_start] = 0;
1716 if (le_start == LEBUFSIZ)
1719 if (le_start == le_end) {
1728 #endif /* TTLEBUF */
1732 Some systems like OSF/1 use TIOCGSIZE instead of TIOCGWINSZ.
1733 But as far as I know, whenever TIOCGSIZE is defined, it is
1734 equated to TIOCGWINSZ. For cases where this is not done, try this:
1738 #define TIOCGWINSZ TIOCGSIZE
1739 #endif /* TIOCGSIZE */
1740 #endif /* TIOCGWINSZ */
1741 #endif /* COMMENT */
1743 static int tt_xpixel = 0, tt_ypixel = 0;
1751 NOTE: TIOCGWSIZ works here too, but only in the 32-bit version.
1752 This code works for both the 16- and 32-bit versions.
1754 extern int dev_size(int, int, int, int *, int *);
1757 if (dev_size(0, -1, -1, &r, &c) == 0) {
1758 debug(F101,"ttgwsiz QNX r","",r);
1759 debug(F101,"ttgwsiz QNX c","",c);
1762 return ((r > 0 && c > 0) ? 1 : 0);
1763 } else return(xttgwsiz());
1767 /* Note, this was M_UNIX, changed to XENIX to allow cross compilation... */
1768 #ifdef XENIX /* SCO UNIX 3.2v4.0 */
1769 #include <sys/stream.h> /* typedef mblk_t needed by ptem.h */
1770 #include <sys/ptem.h> /* for ttgwsiz() */
1773 #ifdef I386IX /* Ditto for Interactive */
1774 #include <sys/stream.h>
1775 #include <sys/ptem.h>
1778 /* Note, the above might be needed for some other older SVR3 Intel makes... */
1788 x = ioctl(0, (int)TIOCGWINSZ, (char *)&w);
1789 debug(F101,"ttgwsiz TIOCGWINSZ","",x);
1792 } else if (w.ws_row > 0 && w.ws_col > 0) {
1795 tt_xpixel = w.ws_xpixel;
1796 tt_ypixel = w.ws_ypixel;
1797 debug(F101,"ttgwsiz tt_rows","",tt_rows);
1798 debug(F101,"ttgwsiz tt_cols","",tt_cols);
1801 debug(F100,"ttgwsiz TIOCGWINSZ 00","",0);
1806 #endif /* TIOCGWINSZ */
1815 winchh(foo) int foo; { /* SIGWINCH handler */
1818 extern int pty_fork_pid;
1824 #endif /* CK_TTYFD */
1825 extern int tt_rows, tt_cols, cmd_rows, cmd_cols;
1828 debug(F100,"***************","",0);
1829 debug(F100,"SIGWINCH caught","",0);
1830 debug(F100,"***************","",0);
1832 debug(F101,"SIGWINCH pty_fork_pid","",pty_fork_pid);
1836 signal(SIGWINCH,winchh); /* Re-arm the signal */
1837 x = ttgwsiz(); /* Get new window size */
1838 cmd_rows = tt_rows; /* Adjust command screen too */
1842 if /* If we don't have a connection */
1843 #ifdef VMS /* we're done. */
1850 #endif /* CK_TTYFD */
1854 if (pty_fork_pid > -1) { /* "set host" to a PTY? */
1858 struct winsize w; /* Resize the PTY */
1862 w.ws_xpixel = tt_xpixel;
1863 w.ws_ypixel = tt_ypixel;
1864 x = ioctl(ttyfd,TIOCSWINSZ,&w);
1865 debug(F101,"winchh TIOCSWINSZ","",x);
1866 debug(F101,"winchh TIOCSWINSZ errno","",errno);
1867 #endif /* TIOCSWINSZ */
1870 x = kill(pty_fork_pid,SIGWINCH);
1871 debug(F101,"winchh kill","",x);
1872 debug(F101,"winchh kill errno","",errno);
1877 This should be OK. It might seem that sending this from
1878 interrupt level could interfere with another TELNET IAC string
1879 that was in the process of being sent. But we always send
1880 TELNET strings with a single write(), which should prevent mixups.
1881 blah_snaws() should protect themselves from being called on the
1882 wrong kind of connection.
1886 if (x > 0 && tt_rows > 0 && tt_cols > 0) {
1890 #endif /* RLOGCODE */
1892 #endif /* NOTTGWSIZ */
1893 #endif /* TCPSOCKET */
1896 #endif /* SIGWINCH */
1897 #endif /* NOSIGWINCH */
1900 sighup(foo) int foo; { /* SIGHUP handler */
1902 debug(F100,"***************","",0);
1903 debug(F100,"SIGHUP received","",0);
1904 debug(F100,"***************","",0);
1905 doexit(BAD_EXIT,-1);
1907 SIGRETURN; /* Shut picky compilers up... */
1911 /* Exists but there is no prototype in the header files */
1912 _PROTOTYP( char * ttyname, (int) );
1915 _PROTOTYP( char * ttyname, (int) );
1918 _PROTOTYP( char * ttyname, (int) );
1921 _PROTOTYP( char * ttyname, (int) );
1924 _PROTOTYP( char * ttyname, (int) );
1927 _PROTOTYP( char * ttyname, (int) );
1930 _PROTOTYP( char * ttyname, (int) );
1932 #endif /* PS2AIX10 */
1936 #endif /* SV68R3V6 */
1937 #endif /* CK_SCO32V4 */
1939 #ifndef SIGUSR1 /* User-defined signals */
1941 #endif /* SIGUSR1 */
1945 #endif /* SIGUSR2 */
1948 ignorsigs() sets certain signals to SIG_IGN. But when a signal is
1949 ignored, it remains ignored across exec(), so we have to restore these
1950 signals before exec(), which is the purpose of restorsigs().
1953 ignorsigs() { /* Ignore these signals */
1954 savquit = signal(SIGQUIT,SIG_IGN); /* Ignore Quit signal */
1956 #ifdef SIGDANGER /* Ignore danger signals */
1958 This signal is sent when the system is low on swap space. Processes
1959 that don't handle it are candidates for termination. If swap space doesn't
1960 clear out enough, we still might be terminated via kill() -- nothing we can
1961 do about that! Conceivably, this could be improved by installing a real
1962 signal handler that warns the user, but that would be pretty complicated,
1963 since we are not always in control of the screen -- e.g. during remote-mode
1966 savdanger = signal(SIGDANGER,SIG_IGN); /* e.g. in AIX */
1967 #endif /* SIGDANGER */
1970 This one comes when a TCP/IP connection is broken by the remote.
1971 We prefer to catch this situation by examining error codes from write().
1973 savpipe = signal(SIGPIPE,SIG_IGN);
1974 #endif /* SIGPIPE */
1975 savusr1 = signal(SIGUSR1,SIG_IGN); /* Ignore user-defined signals */
1976 savusr2 = signal(SIGUSR2,SIG_IGN);
1980 restorsigs() { /* Restore these signals */
1981 (VOID) signal(SIGQUIT,savquit); /* (used in ckufio.c) */
1983 (VOID) signal(SIGDANGER,savdanger);
1984 #endif /* SIGDANGER */
1986 (VOID) signal(SIGPIPE,savpipe);
1987 #endif /* SIGPIPE */
1988 (VOID) signal(SIGUSR1,savusr1);
1989 (VOID) signal(SIGUSR2,savusr2);
1997 struct utsname name;
1998 #endif /* CK_UTSNAME */
2000 extern char startupdir[];
2002 BEFORE ANYTHING ELSE: Initialize the setuid package.
2003 Change to the user's real user and group ID.
2004 If this can't be done, don't run at all.
2008 fprintf(stderr,"PRIV_INI=%d\n",x);
2009 #endif /* SUIDDEBUG */
2011 if (x & 1) fprintf(stderr,"Fatal: setuid failure.\n");
2012 if (x & 2) fprintf(stderr,"Fatal: setgid failure.\n");
2013 if (x & 4) fprintf(stderr,"Fatal: C-Kermit setuid to root!\n");
2016 signal(SIGINT,SIG_IGN); /* Ignore interrupts at first */
2017 signal(SIGFPE,SIG_IGN); /* Ignore floating-point exceptions */
2018 signal(SIGHUP,sighup); /* Catch SIGHUP */
2021 signal(SIGWINCH,winchh); /* Catch window-size change */
2022 #endif /* SIGWINCH */
2023 #endif /* NOSIGWINCH */
2027 Get the initial job control state.
2028 If it is SIG_IGN, that means the shell does not support job control,
2029 and so we'd better not suspend ourselves.
2032 jchdlr = signal(SIGTSTP,SIG_IGN);
2033 if (jchdlr == SIG_IGN) {
2035 debug(F100,"sysinit jchdlr: SIG_IGN","",0);
2036 } else if (jchdlr == SIG_DFL) {
2037 debug(F100,"sysinit jchdlr: SIG_DFL","",0);
2040 debug(F100,"sysinit jchdlr: other","",0);
2043 (VOID) signal(SIGTSTP,jchdlr); /* Put it back... */
2044 #endif /* SIGTSTP */
2047 conbgt(0); /* See if we're in the background */
2048 congm(); /* Get console modes */
2050 (VOID) signal(SIGALRM,SIG_IGN); /* Ignore alarms */
2052 ignorsigs(); /* Ignore some other signals */
2055 iniflags = fcntl(0,F_GETFL,0); /* Get stdin flags */
2056 #endif /* F_SETFL */
2059 gtty(0,&vanilla); /* Get sgtty info */
2062 set42sig(); /* Don't ask! (hakanson@cs.orst.edu) */
2066 Warning: on some UNIX systems (SVR4?), ttyname() reportedly opens /dev but
2067 never closes it. If it is called often enough, we run out of file
2068 descriptors and subsequent open()'s of other devices or files can fail.
2072 if (isatty(0)) /* Name of controlling terminal */
2078 debug(F110,"sysinit ttyname(0)",s,0);
2087 ckstrncpy((char *)cttnam,s,DEVNAMLEN+1);
2091 #endif /* SVORPOSIX */
2093 ckstrncpy((char *)cttnam,dftty,DEVNAMLEN+1);
2094 debug(F110,"sysinit CTTNAM",CTTNAM,0);
2095 debug(F110,"sysinit cttnam",cttnam,0);
2097 ttgwsiz(); /* Get window (screen) dimensions. */
2101 ckmaxfiles = sysconf(_SC_OPEN_MAX);
2102 #endif /* _SC_OPEN_MAX */
2103 #endif /* NOSYSCONF */
2107 consctlfd = open("/dev/consctl", O_WRONLY);
2108 /*noisefd = open("/dev/noise", O_WRONLY)*/
2114 if (uname(&name) > -1) {
2115 ckstrncpy(unm_mch,name.machine,CK_SYSNMLN);
2116 ckstrncpy(unm_nam,name.sysname,CK_SYSNMLN);
2117 ckstrncpy(unm_rel,name.release,CK_SYSNMLN);
2118 ckstrncpy(unm_ver,name.version,CK_SYSNMLN);
2121 debug(F110,"sysinit uname machine",unm_mch,0);
2122 debug(F110,"sysinit uname sysname",unm_nam,0);
2123 debug(F110,"sysinit uname release",unm_rel,0);
2124 debug(F110,"sysinit uname version",unm_ver,0);
2129 if (name.machine[5] == '8')
2133 debug(F101,"sysinit hpis800","",hpis800);
2134 #endif /* HPUX9PLUS */
2136 getsysinfo(GSI_PLATFORM_NAME, unm_mod, CK_SYSNMLN, 0, 0);
2137 debug(F110,"sysinit getsysinfo model",unm_mod,0);
2140 sysinfo(SI_PLATFORM, unm_mod, CK_SYSNMLN);
2141 debug(F110,"sysinit sysinfo model",unm_mod,0);
2142 #endif /* SOLARIS25 */
2144 #endif /* CK_UTSNAME */
2146 #ifdef CK_ENVIRONMENT
2149 extern char tn_env_acct[], tn_env_disp[], tn_env_job[],
2150 tn_env_prnt[], tn_env_sys[];
2152 extern char uidbuf[];
2153 extern char * whoami();
2161 debug(F110,"sysinit uidbuf from USER",uidbuf,0);
2164 p = getenv("LOGNAME");
2165 debug(F110,"sysinit uidbuf from LOGNAME",uidbuf,0);
2170 debug(F110,"sysinit uidbuf from whoami()",uidbuf,0);
2173 ckstrncpy(uidbuf, *p ? p : "UNKNOWN", UIDBUFLEN);
2177 debug(F110,"sysinit final uidbuf",uidbuf,0);
2178 #endif /* CKSENDUID */
2181 if ((p = getenv("JOB"))) ckstrncpy(tn_env_job,p,63);
2182 if ((p = getenv("ACCT"))) ckstrncpy(tn_env_acct,p,63);
2183 if ((p = getenv("PRINTER"))) ckstrncpy(tn_env_prnt,p,63);
2184 if ((p = getenv("DISPLAY"))) ckstrncpy(tn_env_disp,p,63);
2186 ckstrncpy(tn_env_sys,"Aegis",64);
2189 ckstrncpy(tn_env_sys,"Plan9",64);
2191 ckstrncpy(tn_env_sys,"UNIX",64);
2196 #endif /* CK_ENVIRONMENT */
2199 extern char * tn_loc;
2201 if (p = getenv("LOCATION"))
2202 if (tn_loc = (char *)malloc((int)strlen(p)+1))
2203 strcpy(tn_loc,p); /* safe */
2205 #endif /* CK_SNDLOC */
2207 ckstrncpy(startupdir, zgtdir(), CKMAXPATH);
2208 startupdir[CKMAXPATH] = '\0';
2209 x = strlen(startupdir);
2211 startupdir[0] = '/';
2212 startupdir[1] = '\0';
2213 } else if (startupdir[x-1] != '/') {
2214 startupdir[x] = '/';
2215 startupdir[x+1] = '\0';
2217 debug(F110,"sysinit startupdir",startupdir,0);
2220 #endif /* TTLEBUF */
2222 /* This should catch the ncurses platforms */
2223 /* Some platforms don't have putenv(), like NeXTSTEP */
2224 putenv("NCURSES_NO_SETBUF=1");
2225 #endif /* BSD44ORPOSIX */
2229 /* S Y S C L E A N U P -- System-dependent program cleanup. */
2235 fcntl(0,F_SETFL,iniflags); /* Restore stdin flags */
2236 #endif /* F_SETFL */
2238 stty(0,&vanilla); /* Get sgtty info */
2241 if (ttpid) kill(ttpid,9);
2246 /* T T O P E N -- Open a tty for exclusive access. */
2250 ttname: character string - device name or network host name.
2252 If called with lcl < 0, sets value of lcl as follows:
2253 0: the terminal named by ttname is the job's controlling terminal.
2254 1: the terminal named by ttname is not the job's controlling terminal.
2255 But watch out: if a line is already open, or if requested line can't
2256 be opened, then lcl remains (and is returned as) -1.
2258 Less than zero: ttname is a network host name.
2259 Zero or greater: ttname is a terminal device name.
2260 Zero means a local connection (don't use modem signals).
2261 Positive means use modem signals.
2264 nonzero = number of seconds to wait for open() to return before timing out.
2268 -5 if device is in use
2269 -4 if access to device is denied
2270 -3 if access to lock directory denied
2271 -2 upon timeout waiting for device to open
2274 static int ttotmo = 0; /* Timeout flag */
2275 /* Flag kept here to avoid being clobbered by longjmp. */
2278 ttopen(ttname,lcl,modem,timo) char *ttname; int *lcl, modem, timo; {
2281 #define ctermid(x) strcpy(x,"")
2285 extern char *ctermid(); /* Wish they all had this! */
2286 #else /* CIE Regulus */
2287 #define ctermid(x) strcpy(x,"")
2289 #endif /* SVORPOSIX */
2297 char fullname[DEVNAMLEN+1];
2298 #endif /* OPENFIRST */
2300 char * fnam; /* Full name after expansion */
2305 #define NAMEFD /* Feature to allow name to be an open file descriptor */
2310 debug(F101,"ttopen telnetfd","",telnetfd);
2313 debug(F110,"ttopen ttname",ttname,0);
2314 debug(F110,"ttopen ttnmsv",ttnmsv,0);
2315 debug(F101,"ttopen modem","",modem);
2316 debug(F101,"ttopen netconn","",netconn);
2317 debug(F101,"ttopen ttyfd","",ttyfd);
2318 debug(F101,"ttopen *lcl","",*lcl);
2319 debug(F101,"ttopen ttmdm","",ttmdm);
2320 debug(F101,"ttopen ttnet","",ttnet);
2325 if (ttyfd > -1) { /* If device already opened */
2326 if (!strncmp(ttname,ttnmsv,DEVNAMLEN)) /* are new & old names equal? */
2327 return(0); /* Yes, nothing to do - just return */
2328 ttnmsv[0] = '\0'; /* No, clear out old name */
2329 ttclos(ttyfd); /* close old connection. */
2331 wasclosed = 0; /* New connection, not closed yet. */
2332 ttpipe = 0; /* Assume it's not a pipe */
2333 ttpty = 0; /* or a pty... */
2337 This is a bit tricky... Suppose that previously Kermit had dialed a telnet
2338 modem server ("set host xxx:2001, set modem type usr, dial ..."). Then the
2339 connection was closed (ttyfd = -1), and then a REDIAL command was given. At
2340 this point we've obliterated the negative modem type hack, and so would
2341 treat the IP hostname as a device name, and would then fail because of "No
2342 such device or directory". But the previous connection has left behind some
2343 clues, so let's use them...
2345 if (ttyfd < 0) { /* Connection is not open */
2346 if (!strcmp(ttname,ttnmsv)) { /* Old and new names the same? */
2347 if (((netconn > 0) && (ttmdm < 0)) ||
2349 (!ckstrchr(ttname,'/')) && (ckstrchr(ttname,':')))
2352 x = (ttmdm < 0) ? -ttmdm : ttnet;
2353 rc = netopen(ttname, lcl, x);
2354 debug(F111,"ttopen REOPEN netopen",ttname,rc);
2366 #endif /* NETCONN */
2369 debug(F100,"ttopen MAXNAMLEN defined","",0);
2371 debug(F100,"ttopen MAXNAMLEN *NOT* defined","",0);
2375 debug(F100,"ttopen BSD4 defined","",0);
2377 debug(F100,"ttopen BSD4 *NOT* defined","",0);
2381 debug(F100,"ttopen BSD42 defined","",0);
2383 debug(F100,"ttopen BSD42 *NOT* defined","",0);
2387 debug(F100,"ttopen MYREAD defined","",0);
2389 debug(F100,"ttopen MYREAD *NOT* defined","",0);
2393 if (modem < 0) { /* modem < 0 = code for network */
2396 modem = -modem; /* Positive network type number */
2397 fdflag = 0; /* Stdio not redirected. */
2398 netconn = 1; /* And it's a network connection */
2399 debug(F111,"ttopen net",ttname,modem);
2401 for (p = ttname; isdigit(*p); p++) ; /* Check for all digits */
2402 if (*p == '\0' && (telnetfd || x25fd)) { /* Avoid X.121 addresses */
2403 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2404 ttfdflg = 1; /* We got an open file descriptor */
2405 debug(F111,"ttopen net ttfdflg",ttname,ttfdflg);
2406 debug(F101,"ttopen net ttyfd","",ttyfd);
2407 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2408 x = 1; /* Return code is "good". */
2411 if (ttnproto != NP_TCPRAW)
2412 ttnproto = NP_TELNET;
2419 } else { /* Host name or address given */
2421 if (modem == NET_PTY) {
2424 debug(F100,"ttopen PTY: nopush","",0);
2429 netconn = 1; /* but we don't use network i/o */
2431 debug(F110,"ttopen PTY",ttname,0);
2434 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2435 xlocal = *lcl = 1; /* It's local */
2446 dup2() is not available on older System V platforms like AT&T 3Bx. For
2447 those systems we punt by not defining NETCMD, but we might be able to do
2448 better -- see workarounds for this problem in ckufio.c (search for dup2).
2450 if (modem == NET_CMD) {
2452 debug(F100,"ttopen pipe: nopush","",0);
2455 if (pipe(pipe0) || pipe(pipe1)) {
2456 perror("Pipe error");
2459 ttpid = fork(); /* Make a fork */
2462 case -1: /* Error making fork */
2467 perror("Fork error");
2469 case 0: /* Child. */
2478 default: /* Parent */
2481 fdin = pipe0[0]; /* Read from pipe */
2482 fdout = pipe1[1]; /* Write to pipe */
2483 ttout = fdopen(fdout,"w"); /* Get stream so we can */
2484 if (!ttout) { /* make it unbuffered. */
2485 perror("fdopen failure");
2489 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2490 xlocal = *lcl = 1; /* It's local */
2491 netconn = 1; /* Call it a network connection */
2492 ttmdm = modem; /* Remember network type */
2501 x = netopen(ttname, lcl, modem); /* (see ckcnet.h) */
2503 ckstrncpy(ttnmsv,ttname,DEVNAMLEN);
2509 #ifdef sony_news /* Sony NEWS */
2510 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get Kanji mode */
2511 perror("ttopen error getting Kanji mode (network)");
2512 debug(F111,"ttopen error getting Kanji mode","network",0);
2513 km_ext = -1; /* Make sure this stays undefined. */
2515 #endif /* sony_news */
2517 xlocal = *lcl = 1; /* Network connections are local. */
2518 debug(F101,"ttopen net x","",x);
2520 /* Let netopen() do this */
2521 if (x > -1 && !x25fd)
2522 x = tn_ini(); /* Initialize TELNET protocol */
2523 #endif /* COMMENT */
2526 } else { /* Terminal device */
2527 #endif /* NETCONN */
2531 This code lets you give Kermit an open file descriptor for a serial
2532 communication device, rather than a device name. Kermit assumes that the
2533 line is already open, locked, conditioned with the right parameters, etc.
2535 for (p = ttname; isdigit(*p); p++) ; /* Check for all-digits */
2537 ttyfd = atoi(ttname); /* Is there a way to test it's open? */
2538 debug(F111,"ttopen got open fd",ttname,ttyfd);
2539 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Remember the "name". */
2540 if (ttyfd >= 0 && ttyfd < 3) /* If it's stdio... */
2541 xlocal = *lcl = 0; /* we're in remote mode */
2542 else /* otherwise */
2543 xlocal = *lcl = 1; /* local mode. */
2544 netconn = 0; /* Assume it's not a network. */
2545 tvtflg = 0; /* Might need to initialize modes. */
2546 ttmdm = modem; /* Remember modem type. */
2547 fdflag = 0; /* Stdio not redirected. */
2548 ttfdflg = 1; /* Flag we were opened this way. */
2549 debug(F111,"ttopen non-net ttfdflg",ttname,ttfdflg);
2550 debug(F101,"ttopen non-net ttyfd","",ttyfd);
2552 #ifdef sony_news /* Sony NEWS */
2553 /* Get device Kanji mode */
2554 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) {
2555 perror("ttopen error getting Kanji mode");
2556 debug(F101,"ttopen error getting Kanji mode","",0);
2557 km_ext = -1; /* Make sure this stays undefined. */
2559 #endif /* sony_news */
2561 return(0); /* Return success */
2566 #endif /* NETCONN */
2568 /* Here we have to open a serial device of the given name. */
2570 netconn = 0; /* So it's not a network connection */
2571 occt = signal(SIGINT, cctrap); /* Set Control-C trap, save old one */
2574 tvtflg = 0; /* Flag for use by ttvt(). */
2575 /* 0 = ttvt not called yet for this device */
2577 fdflag = (!isatty(0) || !isatty(1)); /* Flag for stdio redirected */
2578 debug(F101,"ttopen fdflag","",fdflag);
2580 ttmdm = modem; /* Make this available to other fns */
2581 xlocal = *lcl; /* Make this available to other fns */
2583 /* Code for handling bidirectional tty lines goes here. */
2584 /* Use specified method for turning off logins and suppressing getty. */
2587 /* Should put call to priv_on() here, but that would be very risky! */
2588 acucntrl("disable",ttname); /* acucntrl() program. */
2589 /* and priv_off() here... */
2592 if ((attmodem & DOGETY) == 0) /* offgetty() program. */
2593 attmodem |= offgetty(ttname); /* Remember response. */
2594 #endif /* ATT7300 */
2595 #endif /* ACUCNTRL */
2599 1985-2001: opens device first then gets lock; reason:
2600 Kermit usually has to run setuid or setgid in order to create a lockfile.
2601 If you give a SET LINE command for a device that happens to be your job's
2602 controlling terminal, Kermit doesn't have to create a lockfile, and in fact
2603 should not create one, and would fail if it tried to if it did not have the
2604 required privileges. But you can't find out if two tty device names are
2605 equivalent until you have a file descriptor that you can give to ttyname().
2606 But this can cause a race condition between Kermit and [m]getty. So see
2611 In the following section, we open the tty device for read/write.
2612 If a modem has been specified via "set modem" prior to "set line"
2613 then the O_NDELAY parameter is used in the open, provided this symbol
2614 is defined (e.g. in fcntl.h), so that the program does not hang waiting
2615 for carrier (which in most cases won't be present because a connection
2616 has not been dialed yet). O_NDELAY is removed later on in ttopen(). It
2617 would make more sense to first determine if the line is local before
2618 doing this, but because ttyname() requires a file descriptor, we have
2619 to open it first. See do_open().
2621 Now open the device using the desired treatment of carrier.
2622 If carrier is REQUIRED, then open could hang forever, so an optional
2623 timer is provided. If carrier is not required, the timer should never
2624 go off, and should do no harm...
2626 ttotmo = 0; /* Flag no timeout */
2627 debug(F101,"ttopen timo","",timo);
2628 debug(F101,"ttopen xlocal","",xlocal);
2631 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2632 xx = alarm(timo); /* Timed open() */
2633 debug(F101,"ttopen alarm","",xx);
2639 #endif /* CK_POSIX_SIG */
2641 ttotmo = 1; /* Flag timeout. */
2642 } else ttyfd = do_open(ttname);
2644 debug(F111,"ttopen","modem",modem);
2645 debug(F101,"ttopen ttyfd","",ttyfd);
2646 debug(F101,"ttopen alarm return","",ttotmo);
2649 ttyfd = do_open(ttname);
2651 debug(F111,"ttopen ttyfd",ttname,ttyfd);
2652 if (ttyfd < 0) { /* If couldn't open, fail. */
2653 debug(F101,"ttopen errno","",errno);
2654 if (errno > 0 && !quiet)
2655 perror(ttname); /* Print message */
2658 if (attmodem & DOGETY) /* was getty(1m) running before us? */
2659 ongetty(ttnmsv); /* yes, restart on tty line */
2660 attmodem &= ~DOGETY; /* no phone in use, getty restored */
2663 /* Should put call to priv_on() here, but that would be risky! */
2664 acucntrl("enable",ttname); /* acucntrl() program. */
2665 /* and priv_off() here... */
2666 #endif /* ACUNTRL */
2667 #endif /* ATT7300 */
2669 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
2670 if (errno == EACCES) { /* Device is protected against user */
2671 debug(F110,"ttopen EACCESS",ttname,0); /* Return -4 */
2673 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
2678 extern int qnxportlock;
2680 debug(F101,"ttopen qnxopencount","",x);
2681 debug(F101,"ttopen qnxportlock","",qnxportlock);
2682 if (x < 0 && qnxportlock) {
2684 printf("?Can't get port open count\n");
2685 printf("(Try again with SET QNX-PORT-LOCK OFF)\n");
2686 return(-1); /* Indicate device is in use */
2688 if (x > 1) { /* 1 == me */
2691 return(-2); /* Indicate device is in use */
2693 printf("WARNING: \"%s\" looks busy...\n",ttdev);
2699 /* take this opportunity to open the control channel */
2700 if (p9openttyctl(ttname) < 0)
2702 /* Make sure it's a real tty. */
2703 if (!ttfdflg && !isatty(ttyfd) && strcmp(ttname,"/dev/null"))
2706 fprintf(stderr,"%s is not a terminal device\n",ttname);
2707 debug(F111,"ttopen not a tty",ttname,errno);
2711 signal(SIGINT,occt);
2716 /* Apollo C runtime claims that console pads are tty devices, which
2717 * is reasonable, but they aren't any good for packet transfer. */
2718 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
2719 if (st.all != status_$ok) {
2720 fprintf(stderr, "problem getting tty object type: ");
2722 } else if (ttyuid != sio_$uid) { /* reject non-SIO lines */
2723 close(ttyfd); ttyfd = -1;
2725 errno = ENOTTY; perror(ttname);
2726 signal(SIGINT,occt);
2731 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2733 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
2735 /* Caller wants us to figure out if line is controlling tty */
2738 if (strcmp(ttname,CTTNAM) == 0) { /* "/dev/tty" always remote */
2740 debug(F111,"ttopen ttname=CTTNAM",ttname,xlocal);
2741 } else if (strcmp(ttname,cttnam) == 0) {
2743 debug(F111,"ttopen ttname=cttnam",ttname,xlocal);
2744 } else if (cttnam[0]) {
2746 x = ttnmsv; /* ttyname() is broken */
2748 x = ttyname(ttyfd); /* Get real name of ttname. */
2749 #endif /* BEBOX_DR7 */
2752 xlocal = ((strncmp(x,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
2755 debug(F111,"ttopen ttyname(ttyfd) xlocal",x,xlocal);
2760 /* Note, the following code was added so that Unix "idle-line" snoopers */
2761 /* would not think Kermit was idle when it was transferring files, and */
2762 /* maybe log people out. */
2763 if (xlocal == 0) { /* Remote mode */
2764 if (fdflag == 0) { /* Standard i/o is not redirected */
2765 debug(F100,"ttopen setting ttyfd = 0","",0);
2767 /* On Lynx OS, fd 0 is open for read only. */
2770 close(ttyfd); /* Use file descriptor 0 */
2772 } else { /* Standard i/o is redirected */
2773 debug(F101,"ttopen stdio redirected","",ttyfd);
2776 #endif /* NOFDZERO */
2778 /* Now check if line is locked -- if so fail, else lock for ourselves */
2779 /* Note: After having done this, don't forget to delete the lock if you */
2780 /* leave ttopen() with an error condition. */
2782 lkf = 0; /* Check lock */
2785 if ((xx = ttlock(ttname)) < 0) { /* Can't lock it. */
2786 debug(F111,"ttopen ttlock fails",ttname,xx);
2787 /* WARNING - This close() can hang if tty is an empty socket... */
2788 close(ttyfd); /* Close the device. */
2789 ttyfd = -1; /* Erase its file descriptor. */
2791 signal(SIGINT,occt); /* Put old SIGINT back. */
2792 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
2793 if (xx == -2) { /* If lockfile says device in use, */
2795 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2796 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2797 if (xpid > -1) { /* If we got a pid */
2799 printf("Locked by process %d\n",xpid); /* tell them. */
2800 sprintf(lockpid,"%d",xpid); /* Record it too */
2801 debug(F110,"ttopen lockpid",lockpid,0);
2802 } else if (*flfnam) {
2803 extern char *DIRCMD;
2806 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2807 p = malloc(x); /* Print a directory listing. */
2809 Note: priv_on() won't help here, because we do not pass privs along to
2810 to inferior processes, in this case ls. So if the real user does not have
2811 directory-listing access to the lockfile directory, this will result in
2812 something like "not found". That's why we try this only as a last resort.
2814 if (p) { /* If we got the space... */
2815 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2816 zsyscmd(p); /* Get listing. */
2817 if (p) { /* free the space */
2824 return(-5); /* Code for device in use */
2825 } else return(-3); /* Access denied */
2828 #else /* OPENFIRST */
2831 27 Oct 2001: New simpler code that gets the lock first and then opens the
2832 device, which eliminates the race condition. The downside is you can no
2833 longer say "set line /dev/ttyp0" or whatever, where /dev/ttyp0 is your login
2834 terminal, without trying to create a lockfile, which fails if C-Kermit lacks
2835 privs, and if it succeeds, it has created a lockfile where it didn't create
2838 xlocal = *lcl; /* Is the device my login terminal? */
2839 debug(F111,"ttopen xlocal","A",xlocal);
2841 if (strcmp(ttname,CTTNAM) && netconn == 0) {
2842 if (zfnqfp(ttname,DEVNAMLEN+1,fullname)) {
2843 if ((int)strlen(fullname) > 0)
2847 debug(F110,"ttopen fnam",fnam,0);
2849 xlocal = (strcmp(fnam,CTTNAM) != 0);
2851 debug(F111,"ttopen xlocal","B",xlocal);
2853 lkf = 0; /* No lock yet */
2854 if (xlocal > 0) { /* If not... */
2856 xx = ttlock(fnam); /* Try to lock it. */
2857 debug(F101,"ttopen ttlock","",xx);
2858 if (xx < 0) { /* Can't lock it. */
2859 debug(F111,"ttopen ttlock fails",fnam,xx);
2860 if (xx == -2) { /* If lockfile says device in use, */
2862 debug(F111,"ttopen reading lockfile pid",flfnam,xx);
2863 xpid = ttrpid(flfnam); /* Try to read pid from lockfile */
2864 if (xpid > -1) { /* If we got a pid */
2866 printf("Locked by process %d\n",xpid); /* tell them. */
2867 ckstrncpy(lockpid,ckitoa(xpid),16);
2868 debug(F110,"ttopen lockpid",lockpid,0);
2870 } else if (flfnam[0] && !nopush) {
2871 extern char *DIRCMD;
2874 x = (int)strlen(flfnam) + (int)strlen(DIRCMD) + 2;
2875 p = malloc(x); /* Print a directory listing. */
2877 Note: priv_on() won't help here, because we do not pass privs along to
2878 to inferior processes, in this case ls. So if the real user does not have
2879 directory-listing access to the lockfile directory, this will result in
2880 something like "not found". That's why we try this only as a last resort.
2882 if (p) { /* If we got the space... */
2883 ckmakmsg(p,x,DIRCMD," ",flfnam,NULL);
2884 zsyscmd(p); /* Get listing. */
2885 if (p) { /* free the space */
2893 return(-5); /* Code for device in use */
2894 } else return(-3); /* Access denied */
2897 /* Have lock -- now it's safe to open the device */
2899 debug(F101,"ttopen lkf","",lkf);
2900 debug(F101,"ttopen timo","",timo);
2902 ttotmo = 0; /* Flag no timeout */
2905 saval = signal(SIGALRM,timerh); /* Timed, set up timer. */
2906 xx = alarm(timo); /* Timed open() */
2907 debug(F101,"ttopen alarm","",xx);
2913 #endif /* CK_POSIX_SIG */
2915 ttotmo = 1; /* Flag timeout. */
2917 ttyfd = do_open(fnam);
2920 debug(F111,"ttopen timed ttyfd",fnam,ttyfd);
2923 ttyfd = do_open(fnam);
2924 debug(F111,"ttopen untimed ttyfd",fnam,ttyfd);
2926 if (ttyfd < 0) { /* If couldn't open, fail. */
2927 debug(F111,"ttopen errno",fnam,errno);
2928 debug(F111,"ttopen xlocal","C",xlocal);
2930 debug(F100,"ttopen substituting 0","",0);
2933 if (errno > 0 && !quiet) {
2934 debug(F111,"ttopen perror",fnam,errno);
2935 perror(fnam); /* Print message */
2937 if (ttunlck()) /* Release the lock file */
2938 fprintf(stderr,"Warning, problem releasing lock\r\n");
2942 if (ttyfd < 0) { /* ttyfd is still < 0? */
2944 if (attmodem & DOGETY) /* was getty(1m) running before us? */
2945 ongetty(ttnmsv); /* yes, restart on tty line */
2946 attmodem &= ~DOGETY; /* no phone in use, getty restored */
2949 /* Should put call to priv_on() here, but that would be risky! */
2950 acucntrl("enable",fnam); /* acucntrl() program. */
2951 /* and priv_off() here... */
2952 #endif /* ACUNTRL */
2953 #endif /* ATT7300 */
2955 signal(SIGINT,occt); /* Put old Ctrl-C trap back. */
2956 if (errno == EACCES) { /* Device is protected against user */
2957 debug(F110,"ttopen EACCESS",fnam,0); /* Return -4 */
2959 } else return(ttotmo ? -2 : -1); /* Otherwise -2 if timeout, or -1 */
2962 /* Make sure it's a real tty. */
2965 /* take this opportunity to open the control channel */
2966 if (p9openttyctl(fnam) < 0)
2968 if (!ttfdflg && !isatty(ttyfd) && strcmp(fnam,"/dev/null"))
2971 fprintf(stderr,"%s is not a terminal device\n",fnam);
2972 debug(F111,"ttopen not a tty",fnam,errno);
2973 if (ttunlck()) /* Release the lock file */
2974 fprintf(stderr,"Warning, problem releasing lock\r\n");
2978 signal(SIGINT,occt);
2984 Apollo C runtime claims that console pads are tty devices, which
2985 is reasonable, but they aren't any good for packet transfer.
2987 ios_$inq_type_uid((short)ttyfd, ttyuid, st);
2988 if (st.all != status_$ok) {
2989 fprintf(stderr, "problem getting tty object type: ");
2991 } else if (ttyuid != sio_$uid) { /* Reject non-SIO lines */
2992 close(ttyfd); ttyfd = -1;
2994 errno = ENOTTY; perror(fnam);
2995 signal(SIGINT,occt);
3000 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3002 ckstrncpy(ttnmsv,ttname,DEVNAMLEN); /* Keep copy of name locally. */
3004 /* Caller wants us to figure out if line is controlling tty */
3008 if (strcmp(fnam,CTTNAM) == 0) { /* "/dev/tty" always remote */
3010 debug(F111,"ttopen fnam=CTTNAM",fnam,xlocal);
3011 } else if (strcmp(fnam,cttnam) == 0) {
3013 debug(F111,"ttopen fnam=cttnam",fnam,xlocal);
3014 } else if (cttnam[0]) {
3016 s = ttnmsv; /* ttyname() is broken */
3018 s = ttyname(ttyfd); /* Get real name of ttname. */
3019 #endif /* BEBOX_DR7 */
3022 xlocal = ((strncmp(s,cttnam,DEVNAMLEN) == 0) ? 0 : 1);
3025 debug(F111,"ttopen ttyname(ttyfd) xlocal",s,xlocal);
3030 /* Note, the following code was added so that Unix "idle-line" snoopers */
3031 /* would not think Kermit was idle when it was transferring files, and */
3032 /* maybe log people out. */
3033 if (xlocal == 0) { /* Remote mode */
3034 if (fdflag == 0) { /* Standard i/o is not redirected */
3035 debug(F100,"ttopen setting ttyfd = 0","",0);
3037 /* On Lynx OS, fd 0 is open for read only. */
3040 close(ttyfd); /* Use file descriptor 0 */
3042 } else { /* Standard i/o is redirected */
3043 debug(F101,"ttopen stdio redirected","",ttyfd);
3046 #endif /* NOFDZERO */
3047 #endif /* OPENFIRST */
3049 /* Got the line, now set the desired value for local. */
3051 if (*lcl != 0) *lcl = xlocal;
3053 /* Some special stuff for v7... */
3057 if (kmem[TTY] < 0) { /* If open, then skip this. */
3058 qaddr[TTY] = initrawq(ttyfd); /* Init the queue. */
3059 if ((kmem[TTY] = open("/dev/kmem", 0)) < 0) {
3060 fprintf(stderr, "Can't read /dev/kmem in ttopen.\n");
3061 perror("/dev/kmem");
3068 /* No failure returns after this point */
3071 ioctl(ttyfd, TIOCMODEM, &temp);
3073 if (xlocal && ioctl(ttyfd, TIOCSINUSE, NULL) < 0) {
3077 #endif /* TIOCSINUSE */
3080 /* Get tty device settings */
3082 #ifdef BSD44ORPOSIX /* POSIX */
3083 tcgetattr(ttyfd,&ttold);
3084 debug(F101,"ttopen tcgetattr ttold.c_lflag","",ttold.c_lflag);
3085 tcgetattr(ttyfd,&ttraw);
3086 debug(F101,"ttopen tcgetattr ttraw.c_lflag","",ttraw.c_lflag);
3087 tcgetattr(ttyfd,&tttvt);
3088 debug(F101,"ttopen tcgetattr tttvt.c_lflag","",tttvt.c_lflag);
3089 #else /* BSD, V7, and all others */
3090 #ifdef ATTSV /* AT&T UNIX */
3091 ioctl(ttyfd,TCGETA,&ttold);
3092 debug(F101,"ttopen ioctl TCGETA ttold.c_lflag","",ttold.c_lflag);
3093 ioctl(ttyfd,TCGETA,&ttraw);
3094 ioctl(ttyfd,TCGETA,&tttvt);
3097 ioctl(ttyfd,TIOCGETP,&ttold);
3098 debug(F101,"ttopen BELLV10 ttold.sg_flags","",ttold.sg_flags);
3099 ioctl(ttyfd,TIOCGDEV,&tdold);
3100 debug(F101,"ttopen BELLV10 tdold.flags","",tdold.flags);
3103 debug(F101,"ttopen gtty ttold.sg_flags","",ttold.sg_flags);
3104 #endif /* BELLV10 */
3106 #ifdef sony_news /* Sony NEWS */
3107 if (ioctl(ttyfd,TIOCKGET,&km_ext) < 0) { /* Get console Kanji mode */
3108 perror("ttopen error getting Kanji mode");
3109 debug(F101,"ttopen error getting Kanji mode","",0);
3110 km_ext = -1; /* Make sure this stays undefined. */
3112 #endif /* sony_news */
3115 debug(F100,"ttopen TIOCGETC","",0);
3116 tcharf = 0; /* In remote mode, also get */
3117 if (xlocal == 0) { /* special characters */
3118 if (ioctl(ttyfd,TIOCGETC,&tchold) < 0) {
3119 debug(F100,"ttopen TIOCGETC failed","",0);
3121 tcharf = 1; /* It worked. */
3122 ioctl(ttyfd,TIOCGETC,&tchnoi); /* Get another copy */
3123 debug(F100,"ttopen TIOCGETC ok","",0);
3127 debug(F100,"ttopen TIOCGETC not defined","",0);
3128 #endif /* TIOCGETC */
3131 debug(F100,"ttopen TIOCGLTC","",0);
3132 ltcharf = 0; /* In remote mode, also get */
3133 if (xlocal == 0) { /* local special characters */
3134 if (ioctl(ttyfd,TIOCGLTC,<chold) < 0) {
3135 debug(F100,"ttopen TIOCGLTC failed","",0);
3137 ltcharf = 1; /* It worked. */
3138 ioctl(ttyfd,TIOCGLTC,<chnoi); /* Get another copy */
3139 debug(F100,"ttopen TIOCGLTC ok","",0);
3143 debug(F100,"ttopen TIOCGLTC not defined","",0);
3144 #endif /* TIOCGLTC */
3147 debug(F100,"ttopen TIOCLGET","",0);
3149 if (ioctl(ttyfd,TIOCLGET,&lmode) < 0) {
3150 debug(F100,"ttopen TIOCLGET failed","",0);
3153 debug(F100,"ttopen TIOCLGET ok","",0);
3155 #endif /* TIOCLGET */
3158 ioctl(ttyfd,TIOCGETP,&ttraw);
3159 ioctl(ttyfd,TIOCGETP,&tttvt);
3161 gtty(ttyfd,&ttraw); /* And a copy of it for packets*/
3162 gtty(ttyfd,&tttvt); /* And one for virtual tty service */
3163 #endif /* BELLV10 */
3166 #endif /* BSD44ORPOSIX */
3168 /* Section for changing line discipline. It's restored in ttres(). */
3172 { union txname ld_name; int ld_idx = 0;
3175 ld_name.tx_which = ld_idx++;
3176 ioctl(ttyfd, TXGETCD, &ld_name);
3177 if (!strncmp(ld_name.tx_name, "rts", 3))
3179 } while (*ld_name.tx_name);
3180 debug(F101,"AIX line discipline","",ttld);
3186 /* For 4.1BSD only, force "old" tty driver, new one botches TANDEM. */
3188 ioctl(ttyfd, TIOCGETD, &ttld); /* Get and save line discipline */
3189 debug(F101,"4.1bsd line discipline","",ttld);
3190 k = OTTYDISC; /* Switch to "old" discipline */
3191 k = ioctl(ttyfd, TIOCSETD, &k);
3192 debug(F101,"4.1bsd tiocsetd","",k);
3197 /* This was previously done before the last two TCGETA or gtty above,
3198 * in both the ATTSV and not-ATTSV case. If it is not okay to have only
3199 * one copy if it here instead, give us a shout!
3201 sio_$control((short)ttyfd, sio_$raw_nl, false, st);
3202 if (xlocal) { /* ignore breaks from local line */
3203 sio_$control((short)ttyfd, sio_$int_enable, false, st);
3204 sio_$control((short)ttyfd, sio_$quit_enable, false, st);
3209 ttraw.c_line = 0; /* STTY line 0 for VX/VE */
3210 tttvt.c_line = 0; /* STTY line 0 for VX/VE */
3211 ioctl(ttyfd,TCSETA,&ttraw);
3214 /* If O_NDELAY was used during open(), then remove it now. */
3217 debug(F100,"ttopen O_NDELAY","",0);
3219 if (fcntl(ttyfd, F_GETFL, 0) & O_NDELAY) {
3220 debug(F100,"ttopen fcntl O_NDELAY","",0);
3222 if (fcntl(ttyfd,F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY) < 0) {
3223 debug(F100,"ttopen fcntl failure to unset O_NDELAY","",0);
3224 perror("Can't unset O_NDELAY");
3227 /* Some systems, notably Xenix (don't know how common this is in
3228 * other systems), need special treatment to get rid of the O_NDELAY
3229 * behaviour on read() with respect to carrier presence (i.e. read()
3230 * returning 0 when carrier absent), even though the above fcntl()
3231 * is enough to make read() wait for input when carrier is present.
3232 * This magic, in turn, requires CLOCAL for working when the carrier
3233 * is absent. But if xlocal == 0, presumably you already have CLOCAL
3234 * or you have a carrier, otherwise you wouldn't be running this.
3236 debug(F101,"ttopen xlocal","",xlocal);
3239 #ifdef COMMENT /* 12 Aug 1997 */
3242 ttraw.c_cflag |= CLOCAL;
3246 ttraw.c_cflag |= CLOCAL;
3247 #endif /* __FreeBSD__ */
3248 #endif /* __bsdi__ */
3249 #else /* Not COMMENT */
3251 if (xlocal) /* Unset this if it's defined. */
3252 ttraw.c_cflag |= CLOCAL;
3254 #endif /* COMMENT */
3255 debug(F101,"ttopen BSD44ORPOSIX calling tcsetattr","",TCSADRAIN);
3256 if (tcsetattr(ttyfd, TCSADRAIN, &ttraw) < 0) {
3257 debug(F100,"ttopen POSIX tcseattr fails","",0);
3258 perror("tcsetattr");
3260 #else /* !BSD44ORPOSIX */
3262 ttraw.c_cflag |= CLOCAL;
3263 debug(F100,"ttopen calling ioctl(TCSETA)","",0);
3265 if (ioctl(ttyfd, TCSETA, &ttraw) < 0) {
3266 debug(F101,"ttopen ioctl(TCSETA) fails","",errno);
3267 perror("ioctl(TCSETA)");
3270 #endif /* BSD44ORPOSIX */
3272 #ifndef NOCOTFMC /* = NO Close(Open()) To Force Mode Change */
3273 /* Reportedly lets uugetty grab the device in SCO UNIX 3.2 / XENIX 2.3 */
3274 debug(F100,"ttopen executing close/open","",0);
3275 close( priv_opn(fnam, O_RDWR) ); /* Magic to force change. */
3276 #endif /* NOCOTFMC */
3279 #endif /* O_NDELAY */
3281 /* Instruct the system how to treat the carrier, and set a few other tty
3284 * This also undoes the temporary setting of CLOCAL that may have been done
3285 * for the close(open()) above (except in Xenix). Also throw in ~ECHO, to
3286 * prevent the other end of the line from sitting there talking to itself,
3287 * producing garbage when the user performs a connect.
3289 * SCO Xenix unfortunately seems to ignore the actual state of CLOCAL.
3290 * Now it thinks CLOCAL is always on. It seems the only real solution for
3291 * Xenix is to switch between the lower and upper case device names.
3293 * This section may at some future time expand into setting a complete
3294 * collection of tty parameters, or call a function shared with ttpkt()/
3295 * ttvt() that does so. On the other hand, the initial parameters are not
3296 * that important, since ttpkt() or ttvt() should always fix that before
3297 * any communication is done. Well, we'll see...
3301 debug(F100,"ttopen calling carrctl","",0);
3302 carrctl(&ttraw, ttcarr == CAR_ON);
3303 debug(F100,"ttopen carrctl ok","",0);
3307 #endif /* COHERENT */
3310 ttraw.c_lflag &= ~ECHO;
3311 ttold.c_lflag &= ~ECHO;
3313 y = tcsetattr(ttyfd, TCSADRAIN, &ttraw);
3314 debug(F101,"ttopen tcsetattr","",y);
3316 y = ioctl(ttyfd, TCSETA, &ttraw);
3317 debug(F100,"ttopen ioctl","",y);
3318 #endif /* BSD44ORPOSIX */
3320 #else /* BSD, etc */
3321 ttraw.sg_flags &= ~ECHO;
3322 ttold.sg_flags &= ~ECHO;
3324 y = ioctl(ttyfd,TIOCSETP,&ttraw);
3325 debug(F100,"ttopen ioctl","",y);
3327 y = stty(ttyfd,&ttraw);
3328 debug(F100,"ttopen stty","",y);
3329 #endif /* BELLV10 */
3330 #endif /* SVORPOSIX */
3334 #endif /* COHERENT */
3336 /* ttflui(); */ /* This fails for some reason. */
3339 /* Get current speed */
3346 debug(F101,"ttopen ttspeed","",ttspeed);
3348 /* Done, make entries in debug log, restore Ctrl-C trap, and return. */
3350 debug(F101,"ttopen ttyfd","",ttyfd);
3351 debug(F101,"ttopen *lcl","",*lcl);
3352 debug(F111,"ttopen lock file",flfnam,lkf);
3353 signal(SIGINT,occt);
3354 sigint_ign = (occt == SIG_IGN) ? 1 : 0;
3360 /* D O _ O P E N -- Do the right kind of open() call for the tty. */
3363 do_open(ttname) char *ttname; {
3367 /* O_NONBLOCK on /dev/tty makes open() fail */
3368 return(priv_opn(ttname, O_RDWR |
3370 ((int)strcmp(ttname,"/dev/tty") == 0) ?
3372 (ttcarr != CAR_ON) ? O_NONBLOCK : 0)
3377 #ifndef O_NDELAY /* O_NDELAY not defined */
3378 return(priv_opn(ttname,2));
3379 #else /* O_NDELAY defined */
3383 Open comms line without waiting for carrier so initial call does not hang
3384 because state of "modem" is likely unknown at the initial call -jrd.
3385 If this is needed for the getty stuff to work, and the open would not work
3386 without O_NDELAY when getty is still on, then this special case is ok.
3387 Otherwise, get rid of it. -ske
3389 return(priv_opn(ttname, O_RDWR | O_NDELAY));
3391 #else /* !ATT7300 */
3393 /* Normal case. Use O_NDELAY according to SET CARRIER. See ttscarr(). */
3395 debug(F101,"do_open xlocal","",xlocal);
3396 debug(F111,"do_open flags A",ttname,flags);
3397 if (xlocal && (ttcarr != CAR_ON))
3399 debug(F111,"do_open flags B",ttname,flags);
3400 return(priv_opn(ttname, flags));
3401 #endif /* !ATT7300 */
3402 #endif /* O_NDELAY */
3406 /* T T C L O S -- Close the TTY, releasing any lock. */
3408 static int ttc_state = 0; /* ttclose() state */
3409 static char * ttc_nam[] = { "setup", "hangup", "reset", "close" };
3412 ttclos(foo) int foo; { /* Arg req'd for signal() prototype */
3414 extern int exithangup;
3416 debug(F101,"ttclos ttyfd","",ttyfd);
3417 debug(F101,"ttclos netconn","",netconn);
3418 debug(F101,"ttclos xlocal","",xlocal);
3420 debug(F100,"ttclos NOFDZERO","",0);
3421 #endif /* NOFDZERO */
3425 le_init(); /* No need for any of this */
3426 #endif /* TTLEBUF */
3427 #endif /* COMMENT */
3429 if (ttyfd < 0) /* Wasn't open. */
3432 if (ttfdflg) /* If we inherited ttyfd from */
3433 return(0); /* another process, don't close it. */
3435 tvtflg = 0; /* (some day get rid of this...) */
3441 tn_push(); /* Place any waiting data into input*/
3442 tn_sopt(DO,TELOPT_LOGOUT); /* Send LOGOUT option before close */
3443 TELOPT_UNANSWERED_DO(TELOPT_LOGOUT) = 1;
3444 tn_reset(); /* The Reset Telnet Option table. */
3447 if (ssl_active_flag) {
3449 BIO_printf(bio_err,"calling SSL_shutdown(ssl)\n");
3450 SSL_shutdown(ssl_con);
3453 ssl_active_flag = 0;
3455 if (tls_active_flag) {
3457 BIO_printf(bio_err,"calling SSL_shutdown(tls)\n");
3458 SSL_shutdown(tls_con);
3461 tls_active_flag = 0;
3467 if (ttpipe) { /* We've been using a pipe */
3472 close(fdin); /* Close these. */
3475 kill(ttpid,1); /* Kill fork with SIGHUP */
3477 wstat = wait(&statusp);
3478 if (wstat == ttpid || wstat == -1)
3480 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
3494 #endif /* NODOPTY */
3505 if (netconn) { /* If it's a network connection. */
3506 debug(F100,"ttclos closing net","",0);
3507 netclos(); /* Let the network module close it. */
3508 netconn = 0; /* No more network connection. */
3509 debug(F101,"ttclos ttyfd after netclos","",ttyfd); /* Should be -1 */
3512 #endif /* NETCONN */
3514 if (xlocal) { /* We're closing a SET LINE device */
3515 #ifdef FT21 /* Fortune 2.1-specific items ... */
3516 ioctl(ttyfd,TIOCHPCL, NULL);
3518 #ifdef ultrix /* Ultrix-specific items ... */
3520 /* Unset the INUSE flag that we set in ttopen() */
3521 ioctl(ttyfd, TIOCSINUSE, NULL);
3522 #endif /* TIOCSINUSE */
3523 ioctl(ttyfd, TIOCNMODEM, &x);
3525 /* What was this? */
3526 ioctl(ttyfd, TIOCNCAR, NULL);
3527 #endif /* COMMENT */
3531 /* This is to prevent us from sticking in tthang() or close(). */
3535 if (ttyfd > 0) { /* But skip it on stdin. */
3536 debug(F100,"ttclos setting O_NDELAY","",0);
3537 x = fcntl(ttyfd,F_SETFL,fcntl(ttyfd,F_GETFL, 0)|O_NDELAY);
3539 if (deblog && x == -1) {
3540 perror("Warning - Can't set O_NDELAY");
3541 debug(F101,"ttclos fcntl failure to set O_NDELAY","",x);
3546 #endif /* O_NDELAY */
3553 #endif /* NOFDZERO */
3555 saval = signal(SIGALRM,xtimerh); /* Enable timer interrupt. */
3556 xx = alarm(8); /* Allow 8 seconds. */
3557 debug(F101,"ttclos alarm","",xx);
3563 #endif /* CK_POSIX_SIG */
3564 ) { /* Timer went off? */
3567 debug(F111,"ttclos ALARM TRAP errno",ckitoa(ttc_state),errno);
3568 printf("ttclos() timeout: %s\n", ttc_nam[ttc_state]);
3571 /* Hang up the device (drop DTR) */
3574 debug(F111,"ttclos A",ckitoa(x),ttc_state);
3575 if (ttc_state < 1) {
3577 debug(F101,"ttclos exithangup","",exithangup);
3579 alarm(8); /* Re-arm the timer */
3580 debug(F101,"ttclos calling tthang()","",x);
3581 x = tthang(); /* Hang up first, then... */
3582 debug(F101,"ttclos tthang()","",x);
3585 /* Put back device modes as we found them */
3588 debug(F111,"ttclos B",ckitoa(x),ttc_state);
3589 if (ttc_state < 2) {
3591 /* Don't try to mess with tty modes if tthang failed() */
3592 /* since it probably won't work. */
3594 debug(F101,"ttclos calling ttres()","",x);
3595 signal(SIGALRM,xtimerh); /* Re-enable the alarm. */
3596 alarm(8); /* Re-arm the timer */
3597 x = ttres(); /* Reset device modes. */
3598 debug(F101,"ttclos ttres()","",x);
3602 /* Close the device */
3605 debug(F101,"ttclos C","",ttc_state);
3606 if (ttc_state < 3) {
3609 debug(F101,"ttclos calling close","",x);
3610 signal(SIGALRM,xtimerh); /* Re-enable alarm. */
3611 alarm(8); /* Re-arm the timer */
3612 x = close(ttyfd); /* Close the device. */
3613 debug(F101,"ttclos close()","",x);
3617 debug(F101,"ttclos D","",ttc_state);
3618 ttimoff(); /* Turn off timer. */
3620 printf("?WARNING - close failed: %s\n",ttnmsv);
3623 printf("errno = %d\n", errno);
3624 debug(F101,"ttclos failed","",errno);
3628 /* Unlock after closing but before any getty mumbo jumbo */
3630 debug(F100,"ttclos about to call ttunlck","",0);
3631 if (ttunlck()) /* Release uucp-style lock */
3632 fprintf(stderr,"Warning, problem releasing lock\r\n");
3635 /* For bidirectional lines, restore getty if it was there before. */
3637 #ifdef ACUCNTRL /* 4.3BSD acucntrl() method. */
3639 debug(F100,"ttclos ACUCNTRL","",0);
3640 acucntrl("enable",ttnmsv); /* Enable getty on the device. */
3643 #ifdef ATT7300 /* ATT UNIX PC (3B1, 7300) method. */
3645 debug(F100,"ttclos ATT7300 ongetty","",0);
3646 if (attmodem & DOGETY) /* Was getty(1m) running before us? */
3647 ongetty(ttnmsv); /* Yes, restart getty on tty line */
3648 attmodem &= ~DOGETY; /* No phone in use, getty restored */
3650 #endif /* ATT7300 */
3651 #endif /* System-dependent getty-restoring methods */
3654 km_ext = -1; /* Invalidate device's Kanji-mode */
3655 #endif /* sony_news */
3657 ttyfd = -1; /* Invalidate the file descriptor. */
3659 debug(F100,"ttclos done","",0);
3663 /* T T H A N G -- Hangup phone line or network connection. */
3666 0 if it does nothing.
3667 1 if it believes that it hung up successfully.
3668 -1 if it believes that the hangup attempt failed.
3671 #define HUPTIME 500 /* Milliseconds for hangup */
3674 /* The following didn't work but TIOCSDTR does work */
3676 /* Define HUP_POSIX to force non-POSIX builds to use the POSIX hangup method */
3677 #ifndef POSIX /* Such as Unixware 1.x, 2.x */
3680 #endif /* HUP_POSIX */
3682 #endif /* UNIXWARE */
3683 #endif /* COMMENT */
3685 #ifndef USE_TIOCSDTR
3687 /* Because the POSIX method (set output speed to 0) doesn't work in NetBSD */
3690 #define USE_TIOCSDTR
3691 #endif /* TIOCCDTR */
3692 #endif /* TIOCSDTR */
3693 #endif /* __NetBSD__ */
3694 #endif /* USE_TIOCSDTR */
3696 #ifndef HUP_CLOSE_POSIX
3698 #define HUP_CLOSE_POSIX
3701 #define HUP_CLOSE_POSIX
3702 #endif /* CK_SCOV5 */
3704 #endif /* HUP_CLOSE_POSIX */
3706 #ifdef NO_HUP_CLOSE_POSIX
3707 #ifdef HUP_CLOSE_POSIX
3708 #undef HUP_CLOSE_POSIX
3709 #endif /* HUP_CLOSE_POSIX */
3710 #endif /* NO_HUP_CLOSE_POSIX */
3717 int x = 0; /* Sometimes used as return code. */
3724 #endif /* COHERENT */
3726 #ifdef SVORPOSIX /* AT&T, POSIX, HPUX declarations. */
3727 int spdsav; /* for saving speed */
3733 #endif /* BSD44ORPOSIX */
3734 #endif /* HUP_POSIX */
3737 Early versions of HP-UX omitted the mflag typedef. If you get complaints
3738 about it, just change it to long (or better still, unsigned long).
3741 dtr_down = 00000000000,
3744 char modem_state[64];
3746 int flags; /* fcntl flags */
3747 unsigned short ttc_save;
3748 #endif /* SVORPOSIX */
3750 if (ttyfd < 0) return(0); /* Don't do this if not open */
3751 if (xlocal < 1) return(0); /* Don't do this if not local */
3755 return((ttclos(0) < 0) ? -1 : 1);
3759 return((ttclos(0) < 0) ? -1 : 1);
3762 if (netconn) { /* Network connection. */
3764 if (istncomport()) {
3765 int rc = tnc_set_dtr_state(0);
3768 rc = tnc_set_dtr_state(1);
3770 return(rc >= 0 ? 1 : -1);
3772 #endif /* TN_COMPORT */
3773 return((netclos() < 0) ? -1 : 1); /* Just close it. */
3775 #endif /* NETCONN */
3777 /* From here down, we handle real tty devices. */
3780 e.g. for Unixware 2, where we don't have a full POSIX build, we
3781 still have to use POSIX-style hangup. Thus the duplication of this
3782 and the next case, the only difference being we use a local termios
3783 struct here, since a different model is used elsewhere.
3785 NO LONGER USED as of C-Kermit 8.0 -- it turns out that this method,
3786 even though it compiles and executes without error, doesn't actually
3787 work (i.e. DTR does not drop), whereas the TIOCSDTR method works just fine,
3790 struct termios ttcur;
3792 debug(F100,"tthang HUP_POSIX style","",0);
3793 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3794 debug(F111,"tthang tcgetattr",ckitoa(errno),x);
3795 if (x < 0) return(-1);
3796 spdsav = cfgetospeed(&ttcur); /* Get current speed */
3797 debug(F111,"tthang cfgetospeed",ckitoa(errno),spdsav);
3798 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
3799 debug(F111,"tthang cfgetispeed",ckitoa(errno),spdsavi);
3800 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
3801 debug(F111,"tthang cfsetospeed",ckitoa(errno),x);
3802 if (x < 0) return(-1);
3803 x = cfsetispeed(&ttcur,B0);
3804 debug(F111,"tthang cfsetispeed",ckitoa(errno),x);
3805 if (x < 0) return(-1);
3806 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3807 debug(F111,"tthang tcsetattr B0",ckitoa(errno),x);
3808 if (x < 0) return(-1);
3809 msleep(HUPTIME); /* Sleep 0.5 sec */
3810 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
3811 if (x < 0) return(-1);
3812 debug(F111,"tthang cfsetospeed prev",ckitoa(errno),x);
3813 x = cfsetispeed(&ttcur,spdsavi);
3814 debug(F111,"tthang cfsetispeed prev",ckitoa(errno),x);
3815 if (x < 0) return(-1);
3816 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3817 debug(F111,"tthang tcsetattr restore",ckitoa(errno),x);
3818 if (x < 0) return(-1);
3826 x = tcdropline(ttyfd,500);
3827 debug(F101,"tthang QNX tcdropline","",x);
3828 ttcur.c_cflag |= CLOCAL;
3829 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3830 debug(F101,"tthang QNX tcsetattr restore","",x);
3832 debug(F101,"tthang QNX tcsetattr restore errno","",errno);
3835 /* Fix flags - ensure O_NONBLOCK is off */
3838 debug(F101,"tthang QNX iniflags","",iniflags);
3839 if (fcntl(ttyfd, F_SETFL, iniflags) == -1) {
3840 debug(F101,"tthang QNX F_SETFL errno","",errno);
3849 debug(F100,"tthang BSD44ORPOSIX USE_TIOCSDTR","",0);
3851 x = ioctl(ttyfd, TIOCCDTR, NULL);
3852 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCCDTR",ckitoa(errno),x);
3853 if (x < 0) return(-1);
3854 msleep(HUPTIME); /* Sleep 0.5 sec */
3856 x = ioctl(ttyfd, TIOCSDTR, NULL);
3857 debug(F111,"tthang BSD44ORPOSIX ioctl TIOCSDTR",ckitoa(errno),x);
3858 if (x < 0) return(-1);
3859 #else /* USE_TIOCSDTR */
3861 #ifdef HUP_CLOSE_POSIX
3863 In OSR5 versions where TIOCSDTR is not defined (up to and including at
3864 least 5.0.6a) the POSIX APIs in the "#else" part below are available but
3865 don't work, and no other APIs are available that do work. In this case
3866 we have to drop DTR by brute force: close and reopen the port. This
3867 code actually works, but all the steps are crucial: setting CLOCAL, the
3868 O_NDELAY manipulations, etc.
3870 debug(F100,"tthang HUP_CLOSE_POSIX close/open","",0);
3871 debug(F101,"tthang HUP_CLOSE_POSIX O_NONBLOCK","",O_NONBLOCK);
3872 debug(F101,"tthang HUP_CLOSE_POSIX O_NDELAY","",O_NDELAY);
3874 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3875 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr","",x);
3877 debug(F101,"tthang HUP_CLOSE_POSIX tcgetattr errno","",errno);
3882 x = close(ttyfd); /* Close without releasing lock */
3884 debug(F101,"tthang HUP_CLOSE_POSIX close errno","",errno);
3888 x = msleep(500); /* Pause half a second */
3889 if (x < 0) { /* Or if that doesn't work, 1 sec */
3890 debug(F101,"tthang HUP_CLOSE_POSIX msleep errno","",errno);
3894 ttyfd = priv_opn(ttnmsv, (O_RDWR|O_NDELAY)); /* Reopen the device */
3895 debug(F111,"tthang HUP_CLOSE_POSIX reopen",ttnmsv,ttyfd);
3897 debug(F101,"tthang HUP_CLOSE_POSIX reopen errno","",errno);
3900 debug(F101,"tthang HUP_CLOSE_POSIX re-ttopen ttyfd","",ttyfd);
3902 /* Restore previous attributes */
3906 ttcur.c_cflag |= CLOCAL;
3907 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3908 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore","",x);
3910 debug(F101,"tthang HUP_CLOSE_POSIX tcsetattr restore errno",
3914 /* Fix flags - ensure O_NDELAY and O_NONBLOCK are off */
3917 if ((x = fcntl(ttyfd, F_GETFL, 0)) == -1) {
3918 debug(F101,"tthang HUP_CLOSE_POSIX F_GETFL errno","",errno);
3921 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
3923 x &= ~(O_NONBLOCK|O_NDELAY);
3924 debug(F101,"tthang HUP_CLOSE_POSIX flags to set","",x);
3925 debug(F101,"tthang HUP_CLOSE_POSIX iniflags","",iniflags);
3926 if (fcntl(ttyfd, F_SETFL, x) == -1) {
3927 debug(F101,"tthang HUP_CLOSE_POSIX F_SETFL errno","",errno);
3932 if ((x = fcntl(ttyfd, F_GETFL, 0)) > -1) {
3933 debug(F101,"tthang HUP_CLOSE_POSIX flags","",x);
3934 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NONBLOCK",
3936 debug(F101,"tthang HUP_CLOSE_POSIX flags & O_NDELAY",
3942 #else /* HUP_CLOSE_POSIX */
3944 /* General BSD44ORPOSIX case (Linux, BSDI, FreeBSD, etc) */
3946 debug(F100,"tthang BSD44ORPOSIX B0","",0);
3947 x = tcgetattr(ttyfd, &ttcur); /* Get current attributes */
3948 debug(F111,"tthang BSD44ORPOSIX tcgetattr",ckitoa(errno),x);
3949 if (x < 0) return(-1);
3950 spdsav = cfgetospeed(&ttcur); /* Get current speed */
3951 debug(F111,"tthang BSD44ORPOSIX cfgetospeed",ckitoa(errno),spdsav);
3952 spdsavi = cfgetispeed(&ttcur); /* Get current speed */
3953 debug(F111,"tthang BSD44ORPOSIX cfgetispeed",ckitoa(errno),spdsavi);
3954 x = cfsetospeed(&ttcur,B0); /* Replace by 0 */
3955 debug(F111,"tthang BSD44ORPOSIX cfsetospeed",ckitoa(errno),x);
3956 if (x < 0) return(-1);
3957 x = cfsetispeed(&ttcur,B0);
3958 debug(F111,"tthang BSD44ORPOSIX cfsetispeed",ckitoa(errno),x);
3959 if (x < 0) return(-1);
3960 /* This gets EINVAL on NetBSD 1.4.1 because of B0... */
3961 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3962 debug(F111,"tthang BSD44ORPOSIX tcsetattr B0",ckitoa(errno),x);
3963 if (x < 0) return(-1);
3964 msleep(HUPTIME); /* Sleep 0.5 sec */
3965 debug(F101,"tthang BSD44ORPOSIX restore output speed","",spdsav);
3966 x = cfsetospeed(&ttcur,spdsav); /* Restore prev speed */
3967 debug(F111,"tthang BSD44ORPOSIX cfsetospeed prev",ckitoa(errno),x);
3968 if (x < 0) return(-1);
3969 debug(F101,"tthang BSD44ORPOSIX restore input speed","",spdsavi);
3970 x = cfsetispeed(&ttcur,spdsavi);
3971 debug(F111,"tthang BSD44ORPOSIX cfsetispeed prev",ckitoa(errno),x);
3972 if (x < 0) return(-1);
3973 ttcur.c_cflag |= CLOCAL; /* Don't expect CD after hangup */
3974 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
3975 debug(F111,"tthang BSD44ORPOSIX tcsetattr restore",ckitoa(errno),x);
3976 if (x < 0) return(-1);
3978 #endif /* HUP_CLOSE_POSIX */
3979 #endif /* USE_TIOCSDTR */
3985 #else /* BSD44ORPOSIX */
3987 #ifdef aegis /* Apollo Aegis */
3988 sio_$control((short)ttyfd, sio_$dtr, false, st); /* DTR down */
3989 msleep(HUPTIME); /* pause */
3990 sio_$control((short)ttyfd, sio_$dtr, true, st); /* DTR up */
3994 #ifdef ANYBSD /* Any BSD version. */
3995 #ifdef TIOCCDTR /* Except those that don't have this */
3996 debug(F100,"tthang BSD style","",0);
3997 if (ioctl(ttyfd,TIOCCDTR,0) < 0) { /* Clear DTR. */
3998 debug(F101,"tthang TIOCCDTR fails","",errno);
4001 msleep(HUPTIME); /* For about 1/2 sec */
4003 x = ioctl(ttyfd,TIOCSDTR,0); /* Restore DTR */
4006 For some reason, this tends to fail with "no such device or address"
4007 but the operation still works, probably because of the close/open
4008 later on. So let's not scare the user unnecessarily here.
4010 debug(F101,"tthang TIOCSDTR errno","",errno); /* Log the error */
4011 x = 1; /* Pretend we succeeded */
4012 } else if (x == 0) x = 1; /* Success */
4015 ioctl(ttyfd, TIOCSAVEMODES, 0);
4016 ioctl(ttyfd, TIOCHPCL, 0);
4017 close(ttyfd); /* Yes, must do this twice */
4018 if ((ttyfd = open(ttnmsv,2)) < 0) /* on Fortune computers... */
4019 return(-1); /* (but why?) */
4022 #endif /* COMMENT */
4023 #endif /* TIOCCDTR */
4024 close(do_open(ttnmsv)); /* Clear i/o error condition */
4027 /* This is definitely dangerous. Why was it here? */
4028 z = ttvt(ttspeed,ttflow); /* Restore modes. */
4029 debug(F101,"tthang ttvt returns","",z);
4030 return(z < 0 ? -1 : 1);
4033 #endif /* COMMENT */
4037 /* AT&T UNIX section, includes HP-UX and generic AT&T System III/V... */
4040 /* Hewlett Packard allows explicit manipulation of modem signals. */
4044 debug(F100,"tthang HP-UX style","",0);
4045 if (ioctl(ttyfd,MCSETAF,&dtr_down) < 0) /* lower DTR */
4046 return(-1); /* oops, can't. */
4047 msleep(HUPTIME); /* Pause half a second. */
4048 x = 1; /* Set return code */
4049 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4050 if ((modem_rtn & MDCD) != 0) /* Check if CD is low. */
4051 x = -1; /* CD didn't drop, fail. */
4054 /* Even if above calls fail, RTS & DTR should be turned back on. */
4055 modem_rtn = MRTS | MDTR;
4056 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) x = -1;
4059 /* New way, from Hellmuth Michaelis */
4060 debug(F100,"tthang HP-UX style, HPUXDEBUG","",0);
4061 if (ioctl(ttyfd,MCGETA,&modem_rtn) == -1) { /* Get current status. */
4062 debug(F100,"tthang HP-UX: can't get modem lines, NO HANGUP!","",0);
4065 sprintf(modem_state,"%#lx",modem_rtn);
4066 debug(F110,"tthang HP-UX: modem lines = ",modem_state,0);
4067 modem_sav = modem_rtn; /* Save current modem signals */
4068 modem_rtn &= ~MDTR; /* Turn DTR bit off */
4069 sprintf(modem_state,"%#lx",modem_rtn);
4070 debug(F110,"tthang HP-UX: DTR down = ",modem_state,0);
4071 if (ioctl(ttyfd,MCSETAF,&modem_rtn) < 0) { /* lower DTR */
4072 debug(F100,"tthang HP-UX: can't lower DTR!","",0);
4073 return(-1); /* oops, can't. */
4075 msleep(HUPTIME); /* Pause half a second. */
4076 x = 1; /* Set return code */
4077 if (ioctl(ttyfd,MCGETA,&modem_rtn) > -1) { /* Get line status. */
4078 sprintf(modem_state,"%#lx",modem_rtn);
4079 debug(F110,"tthang HP-UX: modem lines got = ",modem_state,0);
4080 if ((modem_rtn & MDCD) != 0) { /* Check if CD is low. */
4081 debug(F100,"tthang HP-UX: DCD not down","",0);
4082 x = -1; /* CD didn't drop, fail. */
4084 debug(F100,"tthang HP-UX: DCD down","",0);
4088 debug(F100,"tthang HP-UX: can't get DCD status !","",0);
4091 /* Even if above calls fail, DTR should be turned back on. */
4094 if (ioctl(ttyfd,MCSETAF,&modem_sav) < 0) {
4096 debug(F100,"tthang HP-UX: can't set saved state","",0);
4098 sprintf(modem_state,"%#lx",modem_sav);
4099 debug(F110,"tthang HP-UX: final modem lines = ",modem_state,0);
4102 #endif /* COMMENT */
4104 #else /* AT&T but not HP-UX */
4106 /* SVID for AT&T System V R3 defines ioctl's for handling modem signals. */
4107 /* It is not known how many, if any, systems actually implement them, */
4108 /* so we include them here in ifdef's. */
4111 Unixware has the TIOCMxxx symbols defined, but calling ioctl() with them
4112 gives error 22 (invalid argument).
4116 No modem-signal twiddling for IBM RT PC or RS/6000.
4117 In AIX 3.1 and earlier, the ioctl() call is broken.
4118 This code could be activated for AIX 3.1 with PTF 2006 or later
4119 (e.g. AIX 3.2), but close/open does the job too, so why bother.
4121 #ifdef TIOCMBIS /* Bit Set */
4122 #ifdef TIOCMBIC /* Bit Clear */
4123 #ifdef TIOCM_DTR /* DTR */
4125 /* Clear DTR, sleep 300 msec, turn it back on. */
4126 /* If any of the ioctl's return failure, go on to the next section. */
4128 z = TIOCM_DTR; /* Code for DTR. */
4131 This was the cause of the troubles with the Solaris Port Monitor.
4132 The problem is: RTS never comes back on. Moral: Don't do it!
4133 (But why doesn't it come back on? See the TIOCMBIS call...)
4135 #ifdef TIOCM_RTS /* Lower RTS too if symbol is known. */
4137 #endif /* TIOCM_RTS */
4138 #endif /* COMMENT */
4140 debug(F101,"tthang TIOCM signal mask","",z);
4141 if (ioctl(ttyfd,TIOCMBIC,&z) > -1) { /* Try to lower DTR. */
4142 debug(F100,"tthang TIOCMBIC ok","",0);
4143 msleep(HUPTIME); /* Pause half a second. */
4144 if (ioctl(ttyfd,TIOCMBIS,&z) > -1) { /* Try to turn it back on. */
4145 debug(F100,"tthang TIOCMBIS ok","",0);
4147 return(1); /* Success, done. */
4149 } else { /* Couldn't raise, continue. */
4150 debug(F101,"tthang TIOCMBIS errno","",errno);
4152 } else { /* Couldn't lower, continue. */
4153 debug(F101,"tthang TIOCMBIC errno","",errno);
4155 #endif /* TIOCM_DTR */
4156 #endif /* TIOCMBIC */
4157 #endif /* TIOCMBIS */
4161 General AT&T UNIX case, not HPUX. The following code is highly suspect. No
4162 two AT&T-based systems seem to do this the same way. The object is simply
4163 to turn off DTR and then turn it back on. SVID says the universal method
4164 for turning off DTR is to set the speed to zero, and this does seem to do
4165 the trick in all cases. But neither SVID nor any known man pages say how to
4166 turn DTR back on again. Some variants, like most Xenix implementations,
4167 raise DTR again when the speed is restored to a nonzero value. Others
4168 require the device to be closed and opened again, but this is risky because
4169 getty could seize the device during the instant it is closed.
4172 /* Return code for ioctl failures... */
4174 x = 1; /* ATT6300 doesn't want to fail... */
4177 #endif /* ATT6300 */
4179 debug(F100,"tthang get settings","",0);
4180 if (ioctl(ttyfd,TCGETA,&ttcur) < 0) /* Get current settings. */
4181 return(x); /* Fail if this doesn't work. */
4182 if ((flags = fcntl(ttyfd,F_GETFL,0)) < 0) /* Get device flags. */
4184 ttc_save = ttcur.c_cflag; /* Remember current speed. */
4185 spdsav = ttc_save & CBAUD;
4186 debug(F101,"tthang speed","",spdsav);
4189 debug(F100,"tthang turning O_NDELAY on","",0);
4190 fcntl(ttyfd, F_SETFL, flags | O_NDELAY); /* Activate O_NDELAY */
4191 #endif /* O_NDELAY */
4193 #ifdef ATT7300 /* This is the way it is SUPPOSED to work */
4194 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4197 ttcur.c_cflag &= ~CBAUD; /* Change the speed to zero. */
4198 #else /* This way really works but may be dangerous */
4200 ttcur.c_cflag = ~(CBAUD|CLOCAL); /* Special for AT&T 3B2s */
4201 /* (CLOCAL must be OFF) */
4203 #ifdef SCO3R2 /* SCO UNIX 3.2 */
4205 This is complete nonsense, but an SCO user claimed this change made
4206 hanging up work. Comments from other SCO UNIX 3.2 users would be
4209 ttcur.c_cflag = CBAUD|B0;
4211 #ifdef AIXRS /* AIX on RS/6000 */
4213 Can't set speed to zero on AIX 3.1 on RS/6000 64-port adapter,
4214 even though you can do it on the built-in port and the 8- and 16-port
4215 adapters. (Untested on 128-port adapter.)
4217 ttcur.c_cflag = CLOCAL|HUPCL|spdsav; /* Speed 0 causes EINVAL */
4218 #else /* None of the above */
4220 Set everything, including the speed, to zero, except for the CLOCAL
4223 ttcur.c_cflag = CLOCAL|HUPCL;
4228 #endif /* ATT7300 */
4231 /* and if none of those work, try one of these... */
4233 ttcur.c_cflag = CLOCAL;
4234 ttcur.c_cflag &= ~(CBAUD|HUPCL);
4235 ttcur.c_cflag &= ~(CBAUD|CREAD);
4236 ttcur.c_cflag &= ~(CBAUD|CREAD|HUPCL);
4237 /* or other combinations */
4238 #endif /* COMMENT */
4241 debug(F100,"tthang TCXONC","",0);
4242 if (ioctl(ttyfd, TCXONC, 1) < 0) {
4243 debug(F101,"tthang TCXONC failed","",errno);
4248 debug(F100,"tthang TIOCSTART","",0);
4249 if (ioctl(ttyfd, TIOCSTART, 0) < 0) {
4250 debug(F101,"tthang TIOCSTART failed","",errno);
4252 #endif /* TIOCSTART */
4254 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) { /* Fail if we can't. */
4255 debug(F101,"tthang TCSETAF failed","",errno);
4256 fcntl(ttyfd, F_SETFL, flags); /* Restore flags */
4257 return(-1); /* before returning. */
4259 msleep(300); /* Give modem time to notice. */
4263 /* Now, even though it doesn't say this in SVID or any man page, we have */
4264 /* to close and reopen the device. This is not necessary for all systems, */
4265 /* but it's impossible to predict which ones need it and which ones don't. */
4269 Special handling for ATT 7300 UNIX PC and 3B1, which have "phone"
4270 related ioctl's for their internal modems. attmodem has getty status and
4271 modem-in-use bit. Reportedly the ATT7300/3B1 PIOCDISC call is necessary,
4272 but also ruins the file descriptor, and no other phone(7) ioctl call can fix
4273 it. Whatever it does, it seems to escape detection with PIOCGETA and TCGETA.
4274 The only way to undo the damage is to close the fd and then reopen it.
4276 if (attmodem & ISMODEM) {
4277 debug(F100,"tthang attmodem close/open","",0);
4278 ioctl(ttyfd,PIOCUNHOLD,&dialer); /* Return call to handset. */
4279 ioctl(ttyfd,PIOCDISC,&dialer); /* Disconnect phone. */
4280 close(ttyfd); /* Close and reopen the fd. */
4281 ttyfd = priv_opn(ttnmsv, O_RDWR | O_NDELAY);
4282 attmodem &= ~ISMODEM; /* Phone no longer in use. */
4284 #else /* !ATT7300 */
4285 /* It seems we have to close and open the device for other AT&T systems */
4286 /* too, and this is the place to do it. The following code does the */
4287 /* famous close(open(...)) magic by default. If that doesn't work for you, */
4288 /* then try uncommenting the following statement or putting -DCLSOPN in */
4289 /* the makefile CFLAGS. */
4291 /* #define CLSOPN */
4293 #ifndef SCO32 /* Not needed by, and harmful to, SCO UNIX 3.2 / Xenix 2.3 */
4296 #define OPENFLGS O_RDWR | O_NDELAY
4298 #define OPENFLGS O_RDWR
4302 /* This method is used by default, i.e. unless CLSOPN is defined. */
4303 /* It is thought to be safer because there is no window where getty */
4304 /* can seize control of the device. The drawback is that it might not work. */
4306 debug(F101,"tthang close(open()), OPENFLGS","",OPENFLGS);
4307 close(priv_opn(ttnmsv, OPENFLGS));
4310 /* This method is used if you #define CLSOPN. It is more likely to work */
4311 /* than the previous method, but it's also more dangerous. */
4313 debug(F101,"tthang close/open, OPENFLGS","",OPENFLGS);
4316 ttyfd = priv_opn(ttnmsv, OPENFLGS); /* Open it again */
4321 #endif /* ATT7300 */
4323 #endif /* NOCOTFMC */
4325 /* Now put all flags & modes back the way we found them. */
4326 /* (Does the order of ioctl & fcntl matter ? ) */
4328 debug(F100,"tthang restore settings","",0);
4329 ttcur.c_cflag = ttc_save; /* Get old speed back. */
4330 if (ioctl(ttyfd,TCSETAF,&ttcur) < 0) /* ioctl parameters. */
4334 This is required for IBM RT and RS/6000, probably helps elsewhere too (?).
4335 After closing a modem line, the modem will probably not be asserting
4336 carrier any more, so we should not require carrier any more. If this
4337 causes trouble on non-IBM UNIXes, change the #ifdef to use _IBMR2 rather
4340 flags &= ~O_NDELAY; /* Don't require carrier on reopen */
4341 #endif /* O_NDELAY */
4342 if (fcntl(ttyfd,F_SETFL,flags) < 0) /* fcntl parameters */
4346 #endif /* not HPUX */
4348 #endif /* BSD44ORPOSIX */
4349 #endif /* HUP_POSIX */
4350 #endif /* NOLOCAL */
4354 Major change in 5A(174). We used to use LPASS8, if it was defined, to
4355 allow 8-bit data and Xon/Xoff flow control at the same time. But this
4356 LPASS8 business seems to have been causing trouble for everybody but me!
4357 For example, Annex terminal servers, commonly used with Encore computers,
4358 do not support LPASS8 even though the Encore itself does. Ditto for many
4359 other terminal servers, TELNET connections, rlogin connections, etc etc.
4360 Now, reportedly, even vanilla 4.3 BSD systems can't do this right on their
4361 serial lines, even though LPASS8 is a feature of 4.3BSD. So let's turn it
4362 off for everybody. That means we goes back to using raw mode, with no
4363 flow control. Phooey.
4365 NOTE: This must be done before the first reference to LPASS8 in this file,
4366 and after the last #include statment.
4372 /* T T R E S -- Restore terminal to "normal" mode. */
4374 /* ske@pkmab.se: There are two choices for what this function should do.
4375 * (1) Restore the tty to current "normal" mode, with carrier treatment
4376 * according to ttcarr, to be used after every kermit command. (2) Restore
4377 * the tty to the state it was in before kermit opened it. These choices
4378 * conflict, since ttold can't hold both choices of tty parameters. ttres()
4379 * is currently being called as in choice (1), but ttold basically holds
4380 * the initial parameters, as in (2), and the description at the beginning
4381 * of this file says (2).
4383 * I don't think restoring tty parameters after all kermit commands makes
4384 * much of a difference. Restoring them upon exit from kermit may be of
4385 * some use in some cases (when the line is not restored automatically on
4386 * close, by the operating system).
4388 * I can't choose which one it should be, so I haven't changed it. It
4389 * probably works as it is, too. It would probably even work even with
4390 * ttres() entirely deleted...
4392 * (from fdc: Actually, this function operates in remote mode too, so
4393 * it restores the console (command) terminal to whatever mode it was
4394 * in before packet operations began, so that commands work right again.)
4397 ttres() { /* Restore the tty to normal. */
4400 if (ttyfd < 0) return(-1); /* Not open. */
4402 if (ttfdflg) return(0); /* Don't mess with terminal modes if */
4403 /* we got ttyfd from another process */
4405 if (netconn) { /* Network connection */
4410 extern int tcp_nodelay; /* Just put this back if necessary */
4411 if (ttnet == NET_TCPB) {
4412 if (nodelay_sav > -1) {
4413 no_delay(ttyfd,nodelay_sav);
4418 #endif /* TCP_NODELAY */
4420 if (istncomport()) {
4422 if ((rc = tnsetflow(ttflow)) < 0)
4425 ttspeed = tnc_get_baud();
4426 else if ((rc = tnc_set_baud(ttspeed)) < 0)
4428 tnc_set_datasize(8);
4429 tnc_set_stopsize(stopbits);
4434 case 'e': /* Even */
4435 debug(F100,"ttres 8 bits + even parity","",0);
4439 debug(F100,"ttres 8 bits + odd parity","",0);
4442 case 'm': /* Mark */
4443 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
4446 case 's': /* Space */
4447 debug(F100,"ttres 8 bits + invalid parity: space","",0);
4452 #endif /* HWPARITY */
4454 tnc_set_parity(1); /* None */
4459 #endif /* TN_COMPORT */
4460 #endif /* TCPSOCKET */
4463 #endif /* NETCONN */
4465 if (ttpipe) return(0);
4468 if (ttpty) return(0);
4471 /* Real terminal device, so restore its original modes */
4473 #ifdef BSD44ORPOSIX /* For POSIX like this */
4474 debug(F100,"ttres BSD44ORPOSIX","",0);
4475 x = tcsetattr(ttyfd,TCSADRAIN,&ttold);
4476 #else /* For all others... */
4477 #ifdef ATTSV /* For AT&T versions... */
4478 debug(F100,"ttres ATTSV","",0);
4479 x = ioctl(ttyfd,TCSETAW,&ttold); /* Restore tty modes this way. */
4481 /* Here we restore the modes for BSD */
4483 #ifdef LPASS8 /* Undo "pass8" if it were done */
4485 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4486 debug(F100,"ttres TIOCLSET failed","",0);
4488 debug(F100,"ttres TIOCLSET ok","",0);
4492 #ifdef CK_DTRCTS /* Undo hardware flow if it were done */
4494 if (ioctl(ttyfd,TIOCLSET,&lmode) < 0)
4495 debug(F100,"ttres TIOCLSET failed","",0);
4497 debug(F100,"ttres TIOCLSET ok","",0);
4499 #endif /* CK_DTRCTS */
4501 #ifdef TIOCGETC /* Put back special characters */
4502 if (tcharf && (xlocal == 0)) {
4503 if (ioctl(ttyfd,TIOCSETC,&tchold) < 0)
4504 debug(F100,"ttres TIOCSETC failed","",0);
4506 debug(F100,"ttres TIOCSETC ok","",0);
4508 #endif /* TIOCGETC */
4510 #ifdef TIOCGLTC /* Put back local special characters */
4511 if (ltcharf && (xlocal == 0)) {
4512 if (ioctl(ttyfd,TIOCSLTC,<chold) < 0)
4513 debug(F100,"ttres TIOCSLTC failed","",0);
4515 debug(F100,"ttres TIOCSLTC ok","",0);
4517 #endif /* TIOCGLTC */
4520 debug(F100,"ttres BELLV10","",0);
4521 x = ioctl(ttyfd,TIOCSETP,&ttold); /* Restore both structs */
4522 x = ioctl(ttyfd,TIOCSDEV,&tdold);
4524 debug(F100,"ttres stty","",0);
4525 x = stty(ttyfd,&ttold); /* Restore tty modes the old way. */
4526 #endif /* BELLV10 */
4529 msleep(100); /* This replaces sleep(1)... */
4530 /* Put back sleep(1) if tty is */
4531 /* messed up after close. */
4533 #endif /* BSD44ORPOSIX */
4535 debug(F101,"ttres result","",x);
4537 if (x < 0) debug(F101,"ttres errno","",errno);
4542 x = ioctl(ttyfd, ttld & 1 ? TXADDCD : TXDELCD, "rts");
4543 debug(F101,"ttres AIX line discipline rts restore","",x);
4548 if (ttld > -1) { /* Put back line discipline */
4549 x = ioctl(ttyfd, TIOCSETD, &ttld);
4550 debug(F101,"ttres BSD41 line discipline restore","",x);
4551 if (x < 0) debug(F101,"...ioctl errno","",errno);
4557 x = xlocal ? km_ext : km_con; /* Restore Kanji mode. */
4558 if (x != -1) { /* Make sure we know original modes. */
4559 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
4560 perror("ttres can't set Kanji mode");
4561 debug(F101,"ttres error setting Kanji mode","",x);
4565 debug(F100,"ttres set Kanji mode ok","",0);
4566 #endif /* sony_news */
4568 tvtflg = 0; /* Invalidate terminal mode settings */
4569 debug(F101,"ttres return code","",x);
4575 /* T T C H K P I D -- Check lockfile pid */
4577 Read pid from lockfile named f, check that it's still valid.
4579 On failure to read pid, return 1.
4580 Otherwise, try to delete lockfile f and return 0 if successful, else 1.
4583 ttchkpid(f) char *f; {
4585 pid = ttrpid(f); /* Read pid from file. */
4586 if (pid > -1) { /* If we were able to read the pid.. */
4587 debug(F101,"ttchkpid lock pid","",pid);
4588 errno = 0; /* See if process still exists. */
4589 mypid = (int)getpid(); /* Get my own pid. */
4590 debug(F101,"ttchkpid my pid","",mypid);
4591 if (pid == mypid) { /* It's me! */
4592 x = -1; /* So I can delete it */
4593 errno = ESRCH; /* pretend it's invalid */
4594 } else { /* It's not me */
4595 x = kill((PID_T)pid, 0); /* See if it's a live process */
4596 debug(F101,"ttchkpid kill errno","",errno);
4598 debug(F101,"ttchkpid pid test","",x);
4599 if (x < 0 && errno == ESRCH) { /* pid is invalid */
4600 debug(F111,"removing stale lock",f,pid);
4602 printf("Removing stale lock %s (pid %d terminated)\n", f, pid);
4604 x = unlink(f); /* Remove the lockfile. */
4606 debug(F111,"ttchkpid unlink",f,x);
4608 return(0); /* Device is not locked after all */
4614 return(1); /* Failure to read pid */
4619 /* Aliases (different drivers) for HP-UX dialout devices: */
4621 static char *devprefix[] = { "tty", "ttyd", "cul", "cua", "cuad", "culd", "" };
4622 static int ttydexists = 0;
4626 /* T T R P I D -- Read pid from lockfile "name" */
4629 ttrpid(name) char *name; {
4635 debug(F110,"ttrpid",name,0);
4636 if (!name) return(-1);
4637 if (!*name) return(-1);
4639 len = zchki(name); /* Get file length */
4641 debug(F101,"ttrpid zchki","",len);
4647 fd = open(name,O_RDONLY); /* Try to open lockfile. */
4649 debug(F101,"ttrpid fd","",fd);
4653 Here we try to be flexible and allow for all different binary and string
4654 formats at runtime, rather than a specific format for each configuration
4655 hardwired at compile time.
4660 COHERENT uses a string PID but without leading spaces or 0's, so there is
4661 no way to tell from the file's length whether it contains a string or binary
4662 pid. So for COHERENT only, we only allow string pids. For all others, we
4663 decide based on the size of the lockfile.
4665 if (len > 4) { /* If file > 4 bytes it's a string */
4666 #endif /* COHERENT */
4667 x = read(fd,buf,(int)len);
4668 debug(F111,"ttrpid string read",buf,x);
4673 x = sscanf(buf,"%d",&pid); /* Get the integer pid from it. */
4676 } else if (len == 4) { /* 4 bytes so binary */
4677 x = read(fd, (char *)&pid, 4); /* Read the bytes into an int */
4678 debug(F101,"ttrpid integer read","",x);
4681 } else if (len == 2) { /* 2 bytes binary */
4682 x = read(fd, (char *)&spid, 2); /* Read the bytes into a short */
4683 debug(F101,"ttrpid short read","",x);
4690 #endif /* COHERENT */
4691 close(fd); /* Close the lockfile */
4692 debug(F101,"ttrpid pid","",pid);
4700 This function attempts to coordinate use of the communication device with
4701 other copies of Kermit and any other program that follows the UUCP
4702 device-locking conventions, which, unfortunately, vary among different UNIX
4703 implementations. The idea is to look for a file of a certain name, the
4704 "lockfile", in a certain directory. If such a file is found, then the line
4705 is presumed to be in use, and Kermit should not use it. If no such file is
4706 found, Kermit attempts to create one so that other programs will not use the
4707 same line at the same time. Because the lockfile and/or the directory it's
4708 in might lack write permission for the person running Kermit, Kermit could
4709 find itself running setuid to uucp or other user that does have the
4710 necessary permissions. At startup, Kermit has changed its effective uid to
4711 the user's real uid, and so ttlock() must switch back to the original
4712 effective uid in order to create the lockfile, and then back again to the
4713 real uid to prevent unauthorized access to other directories or files owned
4714 by the user the program is setuid to.
4716 Totally rewritten for C-Kermit 5A to eliminate windows of vulnerability,
4717 based on suggestions from Warren Tucker. Call with pointer to name of
4718 tty device. Returns:
4723 Note: Once privileges are turned on using priv_on(), it is essential that
4724 they are turned off again before this function returns.
4726 #ifdef SVR4 /* Lockfile uses device numbers. */
4728 Although I can't find this in writing anywhere (e.g. in SVID for SVR4),
4729 it is the behavior of the "reference version" of SVR4, i.e. the Intel
4730 port from UNIX Systems Laboratories, then called Univel UnixWare,
4731 then called Novell UnixWare, then called SCO Unixware, then called Caldera
4732 Open UNIX... It also makes much more sense than device-name-based lockfiles
4733 since there can be multiple names for the same device, symlinks, etc.
4736 #ifndef LFDEVNO /* Define this for SVR4 */
4737 #ifndef AIXRS /* But not for RS/6000 AIX 3.2, etc. */
4738 #ifndef BSD44 /* If anybody else needs it... */
4742 #ifndef IRIX51 /* SGI IRIX 5.1 or later */
4743 #ifndef CK_SCOV5 /* SCO Open Server 5.0 */
4745 #endif /* CK_SCOV5 */
4748 #endif /* __FreeBSD__ */
4749 #endif /* __386BSD__ */
4752 #endif /* LFDEVNO */ /* ... define it here or on CC */
4753 #endif /* NOLFDEVNO */
4754 #endif /* SVR4 */ /* command line. */
4758 #endif /* COHERENT */
4761 For platforms where the lockfile name is made from device/major/minor
4762 device number, as in SVR4. Which, if we must have lockfiles at all, is
4763 by far the best format, since it eliminates all the confusion that stems
4764 from multiple names (or drivers) for the same port, not to mention
4765 symlinks. It might even be a good idea to start using this form even
4766 on platforms where it's not supported, alongside the normal forms for those
4767 platforms, in order to get people used to it...
4770 #ifndef major /* If we didn't find it */
4771 #ifdef SVR4 /* then for Sys V R4 */
4772 #include <sys/mkdev.h> /* look here */
4773 #else /* or for SunOS versions */
4774 #ifdef SUNOS4 /* ... */
4775 #include <sys/sysmacros.h> /* look here */
4776 #else /* Otherwise take a chance: */
4777 #define major(dev) ( (int) ( ((unsigned)(dev) >> 8) & 0xff))
4778 #define minor(dev) ( (int) ( (dev) & 0xff))
4782 #endif /* LFDEVNO */
4784 /* No advisory locks if F_TLOCK and F_ULOCK are not defined at this point */
4791 #endif /* NOLOCKF */
4792 #endif /* F_TLOCK */
4800 #endif /* NOLOCKF */
4801 #endif /* F_ULOCK */
4804 static char linkto[DEVNAMLEN+1];
4805 static char * linkdev = NULL;
4810 char * uucplockdir = LOCK_DIR;
4812 char * uucplockdir = "";
4813 #endif /* LOCK_DIR */
4816 char * uucplockdir = LOCK_DIR;
4818 char * uucplockdir = "";
4819 #endif /* LOCK_DIR */
4820 #endif /* USETTYLOCK */
4822 char * uucplockdir = "";
4825 #ifdef QNX /* Only for QNX4 */
4826 int /* Visible to outside world */
4827 qnxopencount() { /* Get QNX device open count */
4828 struct _dev_info_entry info;
4831 x = -1; /* Unknown */
4833 if (!dev_info(ttyfd, &info)) {
4834 debug(F101,"ttlock QNX open_count","",info.open_count);
4835 x = info.open_count;
4843 ttglckdir() { /* Get Lockfile directory name */
4845 return("/var/spool/lock");
4846 #else /* __OpenBSD__ */
4848 return("/var/spool/lock");
4849 #else /* __FreeBSD__ */
4851 char * s = LOCK_DIR;
4852 #endif /* LOCK_DIR */
4858 #else /* LOCK_DIR */
4860 #endif /* LOCK_DIR */
4862 #endif /* __FreeBSD__ */
4863 #endif /* __OpenBSD__ */
4867 ttlock(ttdev) char *ttdev; {
4873 debug(F100,"ttlock NOUUCP","",0);
4874 ckstrncpy(flfnam,"NOLOCK",FLFNAML);
4880 haslock = 0; /* Not locked yet. */
4881 *flfnam = '\0'; /* Lockfile name is empty. */
4882 if (!strncmp(ttdev,"/dev/",5) && ttdev[5])
4883 ckstrncpy(lockname,ttdev+5,DEVNAMLEN);
4885 ckstrncpy(lockname,ttdev,DEVNAMLEN);
4887 This might be overkill, but it's not clear from the man pages whether
4888 ttylock() can be called without calling ttylocked() first, since the doc
4889 says that ttylocked() removes any stale lockfiles, but it does not say this
4890 about ttylock(). Also the docs don't say what ttylocked() returns in the
4891 case when it finds and removes a stale lockfile. So one or both calls to
4892 to ttylocked() might be superfluous, but they should do no harm. Also I'm
4893 assuming that we have to do all the same ID swapping, etc, with these
4894 routines as we do without them. Thus the priv_on/off() sandwich.
4897 priv_on(); /* Turn on privs */
4898 x = uu_lock(lockname); /* Try to set the lock */
4899 priv_off(); /* Turn privs off */
4900 debug(F111,"ttlock uu_lock",lockname,x);
4906 ckmakmsg(flfnam,FLFNAML,"/var/spool/lock/LCK..",lockname,NULL,NULL);
4913 #else /* USE_UU_LOCK */
4914 priv_on(); /* Turn on privs */
4915 if (ttylocked(lockname)) { /* This should remove any stale lock */
4916 if (ttylocked(lockname)) { /* so check again. */
4918 return(-5); /* Still locked, fail. */
4921 x = ttylock(lockname); /* Lock it. */
4922 priv_off(); /* Turn off privs */
4924 debug(F111,"ttlock lockname",lockname,x);
4927 We don't really know the name of the lockfile, but
4928 this is what the man page says it is. In USETTYLOCK
4929 builds, it is used only for display by SHOW COMM.
4931 ckmakmsg(flfnam,FLFNAML,"/etc/locks/LCK..",lockname,NULL,NULL);
4935 #endif /* USE_UU_LOCK */
4936 #else /* Systems that don't have ttylock()... */
4940 int lockfd; /* File descriptor for lock file. */
4941 PID_T pid; /* Process id of this process. */
4942 int tries; /* How many times we've tried... */
4943 struct stat devbuf; /* For device numbers (SVR4). */
4946 char pid_str[32]; /* My pid in string format. */
4947 #endif /* PIDSTRING */
4949 char *device, *devname;
4951 #define LFNAML 256 /* Max length for lock file name. */
4952 char lockfil[LFNAML]; /* Lock file name */
4954 char lklockf[LFNAML]; /* Name for link to lock file */
4957 char symlock[LFNAML]; /* Name for symlink lockfile name */
4958 #endif /* CKSYMLINK */
4959 char tmpnam[LFNAML+30]; /* Temporary lockfile name. */
4960 char *lockdir = LOCK_DIR; /* Defined near top of this file, */
4961 /* or on cc command line. */
4962 haslock = 0; /* Not locked yet. */
4963 *flfnam = '\0'; /* Lockfile name is empty. */
4964 lock2[0] = '\0'; /* Clear secondary lockfile name. */
4965 pid = getpid(); /* Get id of this process. */
4967 /* Construct name of lockfile and temporary file */
4969 /* device = name of tty device without the path, e.g. "ttyh8" */
4970 /* lockfil = name of lock file, without path, e.g. "LCK..ttyh8" */
4972 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
4974 if (stat(ttdev,&devbuf) < 0)
4978 islink = 1; /* Assume it's a symlink */
4979 linkto[0] = '\0'; /* But we don't know to what */
4982 This is undependable. If it worked it would save the readlink call if
4983 we knew the device name was not a link.
4986 islink = S_ISLNK(devbuf.st_mode);
4987 debug(F101,"ttlock stat S_ISLNK","",islink);
4988 #endif /* S_ISLNK */
4989 #endif /* COMMENT */
4991 n = readlink(ttdev,linkto,DEVNAMLEN); /* See if it's a link */
4992 debug(F111,"ttlock readlink",ttdev,n);
4993 if (n > -1) /* It is */
4997 debug(F111,"ttlock link",linkto,islink);
5000 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5001 debug(F110,"ttlock linkdev",linkdev,0);
5003 #endif /* CKSYMLINK */
5006 On SCO platforms, if we don't have a symlink, then let's pretend the
5007 name given for the device is a symlink, because later we will change
5008 the name if it contains any uppercase characters.
5010 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5013 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5014 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5015 debug(F110,"ttlock linkdev",linkdev,0);
5018 #ifdef M_XENIX /* SCO Xenix or UNIX */
5021 ckstrncpy(linkto,ttdev,DEVNAMLEN);
5022 linkdev = (devname = xxlast(linkto,'/')) ? devname + 1 : linkto;
5023 debug(F110,"ttlock linkdev",linkdev,0);
5025 #endif /* M_XENIX */
5026 #endif /* CK_SCOV5 */
5028 #ifdef ISIII /* Interactive System III, PC/IX */
5029 ckstrncpy(lockfil, device, DEVNAMLEN);
5030 #else /* not ISIII */
5031 #ifdef LFDEVNO /* Lockfilename has device numbers. */
5033 sprintf(lockfil,"LCK..%d.%d", /* SAFE */
5034 major(devbuf.st_rdev), /* major device number */
5035 0x1f & minor(devbuf.st_rdev)); /* minor device number */
5037 /* Note: %d changed to %u in 8.0 -- %u is part of SVID for SVR4 */
5038 /* Lockfile name format verified to agree with Solaris cu, Dec 2001 */
5039 sprintf(lockfil,"LK.%03u.%03u.%03u", /* SAFE */
5040 major(devbuf.st_dev), /* device */
5041 major(devbuf.st_rdev), /* major device number */
5042 minor(devbuf.st_rdev)); /* minor device number */
5043 #endif /* COHERENT */
5044 #else /* Not LFDEVNO */
5045 #ifdef PTX /* Dynix PTX */
5046 if ((device != &ttdev[5]) && (strncmp(ttdev,"/dev/",5) == 0)) {
5047 if ((int)strlen(device) + 8 < LFNAML)
5048 sprintf(lockfil,"LCK..%.3s%s", &ttdev[5], device);
5050 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5053 if ((int)strlen(device) + 5 < LFNAML)
5054 sprintf(lockfil,"LCK..%s", device);
5056 ckstrncpy(lockfil,"LOCKFILE_NAME_TOO_LONG",LFNAML);
5058 ckstrncpy(lklockf,device,DEVNAMLEN);
5063 ckmakmsg(symlock,LFNAML, "LCK..", linkdev, NULL, NULL);
5064 #endif /* CKSYMLINK */
5065 #endif /* LFDEVNO */
5068 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5070 /* Lowercase the entire filename. */
5071 /* SCO says we must do this in V5.0 and later. */
5072 /* BUT... watch out for devices -- like Digiboard Portserver */
5073 /* That can have hundreds of ports... */
5074 char *p = (char *)(lockfil + 5);
5075 while (*p) { if (isupper(*p)) *p = (char) tolower(*p); p++; }
5078 if (islink) { /* If no change */
5079 if (!strcmp(lockfil,symlock)) { /* then no second lockfile needed */
5084 #endif /* CKSYMLINK */
5086 #ifdef M_XENIX /* SCO Xenix or UNIX */
5089 x = (int)strlen(lockfil) - 1; /* Get last letter of device name. */
5090 if (x > 0) { /* If it's uppercase, lower it. */
5092 if (c >= 'A' && c <= 'Z') lockfil[x] += ('a' - 'A');
5097 if (!strcmp(lockfil,symlock)) { /* No change */
5098 islink = 0; /* so no second lockfile */
5102 #endif /* CKSYMLINK */
5103 #endif /* M_XENIX */
5104 #endif /* CK_SCOV5 */
5106 /* flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..ttyh8" */
5107 /* tmpnam = temporary unique, e.g. "/usr/spool/uucp/LTMP..pid" */
5109 ckmakmsg(flfnam,LFNAML,lockdir,"/",lockfil,NULL);
5112 ckmakmsg(lkflfn,FLFNAML,lockdir,"/",lklockf,NULL);
5117 /* If it's a link then also make a lockfile for the real name */
5118 debug(F111,"ttlock link symlock",symlock,islink);
5119 if (islink && symlock[0]) {
5120 /* But only if the lockfile names would be different. */
5121 /* WARNING: They won't be, e.g. for /dev/ttyd2 => /hw/ttys/ttyd2 */
5122 ckmakmsg(lock2,FLFNAML,lockdir,"/",symlock,NULL);
5123 debug(F110,"ttlock lock2",lock2,0);
5124 if (!strcmp(lock2,flfnam)) { /* Are lockfile names the same? */
5125 debug(F100,"ttlock lock2 cleared","",0);
5126 lock2[0] = '\0'; /* Clear secondary lockfile name. */
5129 #endif /* CKSYMLINK */
5130 #endif /* LFDEVNO */
5132 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* safe */
5133 debug(F110,"ttlock flfnam",flfnam,0);
5134 debug(F110,"ttlock tmpnam",tmpnam,0);
5136 priv_on(); /* Turn on privileges if possible. */
5137 lockfd = creat(tmpnam, 0444); /* Try to create temp lock file. */
5138 if (lockfd < 0) { /* Create failed. */
5139 debug(F111,"ttlock creat failed",tmpnam,errno);
5140 if (errno == ENOENT) {
5142 printf("UUCP not installed or Kermit misconfigured\n");
5146 unlink(tmpnam); /* Get rid of the temporary file. */
5148 priv_off(); /* Turn off privileges!!! */
5149 return(-1); /* Return failure code. */
5151 /* Now write the pid into the temp lockfile in the appropriate format */
5153 #ifdef PIDSTRING /* For Honey DanBer UUCP, */
5154 sprintf( /* write PID as decimal string */
5156 #ifdef LINUXFSSTND /* The "Linux File System Standard" */
5157 #ifdef FSSTND10 /* Version 1.0 calls for */
5158 "%010d\n", /* leading zeros */
5159 #else /* while version 1.2 calls for */
5160 "%10d\n", /* leading spaces */
5161 #endif /* FSSTND10 */
5164 "%d\n", /* with leading nothing */
5166 "%10d\n", /* with leading blanks */
5167 #endif /* COHERENT */
5168 #endif /* LINUXFSSTND */
5171 write(lockfd, pid_str, 11);
5172 debug(F111,"ttlock hdb pid string",pid_str,(int) pid);
5174 #else /* Not PIDSTRING, use integer PID */
5176 write(lockfd, (char *)&pid, sizeof(pid) );
5177 debug(F101,"ttlock pid","",(int) pid);
5179 #endif /* PIDSTRING */
5181 /* Now try to rename the temp file to the real lock file name. */
5182 /* This will fail if a lock file of that name already exists. */
5184 close(lockfd); /* Close the temp lockfile. */
5185 chmod(tmpnam,0444); /* Permission for a valid lock. */
5187 while (!haslock && tries++ < 2) {
5188 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5189 if (haslock) { /* If we got the lockfile */
5191 link(flfnam,lkflfn);
5195 if (islink && lock2[0])
5197 #endif /* LFDEVNO */
5198 #endif /* CKSYMLINK */
5201 /* Can't do this any more because device is not open yet so no ttyfd. */
5204 Advisory file locking works on SVR4, so we use it. In fact, it is
5205 necessary in some cases, e.g. when SLIP is involved. But it still doesn't
5206 seem to prevent multiple users accessing the same device by different names.
5208 while (lockf(ttyfd, F_TLOCK, 0L) != 0) {
5209 debug(F111, "ttlock lockf returns errno", "", errno);
5210 if ((++tries >= 3) || (errno != EAGAIN)) {
5211 x = unlink(flfnam); /* remove the lockfile */
5213 unlink(lkflfn); /* And any links to it... */
5217 if (islink && lock2[0])
5218 unlink(lock2); /* ditto... */
5219 #endif /* LFDEVNO */
5220 #endif /* CKSYMLINK */
5221 debug(F111,"ttlock unlink",flfnam,x);
5227 if (haslock) /* If we got an advisory lock */
5229 #endif /* COMMENT */
5230 break; /* We're done. */
5232 } else { /* We didn't create a new lockfile. */
5234 if (ttchkpid(flfnam)) { /* Check existing lockfile */
5235 priv_on(); /* cause ttchkpid turns priv_off... */
5236 unlink(tmpnam); /* Delete the tempfile */
5237 debug(F100,"ttlock found tty locked","",0);
5238 priv_off(); /* Turn off privs */
5239 return(-2); /* Code for device is in use. */
5244 unlink(tmpnam); /* Unlink (remove) the temp file. */
5245 priv_off(); /* Turn off privs */
5246 return(haslock ? 0 : -1); /* Return link's return code. */
5251 HP-UX gets its own copy of this routine, modeled after the observed behavior
5252 of the HP-UX 'cu' program. HP-UX serial device names consist of a base name
5253 such as "tty", "ttyd", "cua", "cul", "cuad", or "culd", followed by a unit
5254 designator which is a string of digits, possibly containing an imbedded
5255 letter "p". Examples (for base name "tty"):
5257 /dev/tty0, /dev/tty00, dev/ttyd00, /dev/tty0p0
5259 According to the HP-UX UUCP manual of 1988, the "0p0" notation has been
5260 used on Series 800 since HP-UX 2.00, and the "non-p" notation was used
5261 on other models. In HP-UX 10.00, "0p0" notation was adopted for all models.
5262 However, we make and enforce no such distinctions; either notation is
5263 accepted on any model or HP-UX version as a valid unit designator.
5265 If a valid unit is specified (as opposed to a designer name or symlink), we
5266 check for all aliases of the given unit according to the devprefix[] array.
5267 If no lockfiles are found for the given unit, we can have the device; we
5268 create a lockfile LCK..name in the lockfile directory appropriate for the
5269 HP-UX version (/var/spool/locks for 10.00 and later, /usr/spool/uucp for
5270 9.xx and earlier). If it is a "cua" or "cul" device, a second lockfile is
5271 created with the "ttyd" prefix. This is exactly what cu does.
5273 If the "set line" device does not have a valid unit designator, then it is
5274 used literally and no synomyms are searched for and only one lockfile is
5279 #define LFNAML 80 /* Max length for lock file name. */
5281 int lockfd; /* File descriptor for lock file. */
5282 PID_T pid; /* Process ID of this process. */
5283 int fpid; /* pid found in existing lockfile. */
5284 int tries; /* How many times we've tried... */
5285 int i, k; /* Workers */
5287 char *device, *devname; /* "/dev/xxx", "xxx" */
5288 char *unit, *p; /* <instance>p<port> part of xxx */
5290 char lockfil[LFNAML]; /* Lockfile name (no path) */
5291 char tmpnam[LFNAML]; /* Temporary lockfile name. */
5293 #ifdef HPUX10 /* Lockfile directory */
5294 char *lockdir = "/var/spool/locks"; /* Always this for 10.00 and higher */
5295 #else /* HP-UX 9.xx and below */
5297 char *lockdir = LOCK_DIR; /* Defined near top of this file */
5299 char *lockdir = "/usr/spool/uucp"; /* or not... */
5300 #endif /* LOCK_DIR */
5303 haslock = 0; /* Not locked yet. */
5304 *flfnam = '\0'; /* Lockfile name is empty. */
5305 lock2[0] = '\0'; /* Second one too. */
5306 pid = getpid(); /* Get my process ID */
5308 Construct name of lockfile and temporary file...
5309 device = name of tty device without the path, e.g. "tty0p0"
5310 lockfil = name of lock file, without path, e.g. "LCK..tty0p0"
5312 device = ((devname = xxlast(ttdev,'/')) != NULL ? devname+1 : ttdev);
5313 debug(F110,"TTLOCK device",device,0);
5314 ckmakmsg(lockfil,LFNAML,"LCK..",device,NULL,NULL);
5316 k = 0; /* Assume device is not locked */
5317 n = 0; /* Digit counter */
5318 unit = device; /* Unit = <instance>p<port> */
5319 while (*unit && !isdigit(*unit)) /* Search for digit... */
5321 p = unit; /* Verify <num>p<num> format... */
5322 debug(F110,"TTLOCK unit 1",unit,0);
5324 The unit number is recognized as:
5325 (a) any sequence of digits that runs to the end of the string.
5326 (b) any (a) that includes one and only one letter "p", with at least
5327 one digit before and after it.
5329 while (isdigit(*p)) p++, n++; /* Get a run of digits */
5330 if (*p && n > 0) { /* Have a "p"? */
5331 if (*p == 'p' && isdigit(*(p+1))) {
5334 while (isdigit(*p)) p++, n++;
5337 if (n == 0 || *p) unit = "";
5338 debug(F110,"TTLOCK unit 2",unit,0);
5340 if (*unit) { /* Device name has unit number. */
5341 /* The following loop not only searches for the various lockfile */
5342 /* synonyms, but also removes all -- not just one -- stale lockfile */
5343 /* for the device, should there be more than one. See ttchkpid(). */
5345 for (i = 0; *devprefix[i]; i++) { /* For each driver... */
5346 /* Make device name */
5347 ckmakmsg(lock2,FLFNAML,"/dev/",devprefix[i],unit,NULL);
5348 priv_on(); /* Privs on */
5349 k = zchki(lock2) != -1; /* See if device exists */
5350 priv_off(); /* Privs off */
5351 debug(F111,"TTLOCK exist",lock2,k);
5353 if (!strcmp(devprefix[i],"ttyd")) /* ttyd device exists */
5355 /* Make lockfile name */
5356 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",devprefix[i],unit);
5357 debug(F110,"TTLOCK checking",lock2,0);
5358 priv_on(); /* Privs on */
5359 k = zchki(lock2) != -1; /* See if lockfile exists */
5360 priv_off(); /* Privs off */
5361 debug(F111,"TTLOCK check for lock A",lock2,k);
5362 if (k) if (ttchkpid(lock2)) { /* If pid still active, fail. */
5363 ckstrncpy(flfnam,lock2,FLFNAML);
5368 } else { /* Some other device-name format */
5369 /* This takes care of symbolic links, etc... */
5370 /* But does not chase them down! */
5371 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..",device,NULL);
5373 k = zchki(lock2) != -1; /* Check for existing lockfile */
5375 debug(F111,"TTLOCK check for lock B",lock2,k);
5376 if (k) if (ttchkpid(lock2)) { /* Check pid from lockfile */
5377 ckstrncpy(flfnam,lock2,FLFNAML);
5378 debug(F110,"TTLOCK in use",device,0);
5379 debug(F101,"TTLOCK returns","",-2);
5384 Get here only if there is no (more) lockfile, so now we make one (or two)...
5385 flfnam = full lockfile pathname, e.g. "/usr/spool/uucp/LCK..cul0p0".
5386 tmpnam = unique temporary filname, e.g. "/usr/spool/uucp/LTMP..pid".
5388 ckmakmsg(flfnam,FLFNAML,lockdir,"/",lockfil,NULL); /* SET LINE device */
5390 /* If dialout device, also make one for corresponding dialin device */
5392 if (!strncmp(device,"cu",2) && *unit && ttydexists)
5393 ckmakmsg(lock2,FLFNAML,lockdir,"/LCK..ttyd",unit,NULL);
5395 if ((int)strlen(lockdir)+12 < LFNAML)
5396 sprintf(tmpnam,"%s/LTMP.%05d",lockdir,(int) pid); /* Make temp name */
5399 debug(F110,"TTLOCK flfnam",flfnam,0);
5400 debug(F110,"TTLOCK lock2",lock2,0);
5401 debug(F110,"TTLOCK tmpnam",tmpnam,0);
5405 Lockfile permissions...
5406 444 is standard, HP-UX 10.00 uses 664. It doesn't matter.
5407 Kermit uses 444; the difference lets us tell whether Kermit created
5410 priv_on(); /* Turn on privileges. */
5411 lockfd = creat(tmpnam, 0444); /* Try to create temporary file. */
5412 if (lockfd < 0) { /* Create failed. */
5413 debug(F111,"TTLOCK creat failed",tmpnam,errno);
5414 if (errno == ENOENT) {
5416 printf("UUCP not installed or Kermit misconfigured\n");
5420 unlink(tmpnam); /* Get rid of the temporary file. */
5422 priv_off(); /* Turn off privileges!!! */
5423 debug(F101,"TTLOCK returns","",-1);
5424 return(-1); /* Return failure code. */
5426 debug(F110,"TTLOCK temp ok",tmpnam,0);
5428 /* Now write our pid into the temp lockfile in integer format. */
5430 i = write(lockfd, (char *)&pid, sizeof(pid));
5434 debug(F101,"TTLOCK pid","",pid);
5435 debug(F101,"TTLOCK sizeof pid","",sizeof(pid));
5436 debug(F101,"TTLOCK write pid returns","",i);
5441 Now try to rename the temporary file to the real lockfile name.
5442 This will fail if a lock file of that name already exists, which
5443 will catch race conditions with other users.
5445 close(lockfd); /* Close the temp lockfile. */
5449 while (!haslock && tries++ < 2) {
5450 haslock = (link(tmpnam,flfnam) == 0); /* Create a link to it. */
5451 debug(F101,"TTLOCK link","",haslock);
5452 if (haslock) { /* If we made the lockfile... */
5455 /* We can't do this any more because we don't have a file descriptor yet. */
5456 #ifdef LOCKF /* Can be canceled with -DNOLOCKF */
5458 Create an advisory lock on the device through its file descriptor.
5459 This code actually seems to work. If it is executed, and then another
5460 process tries to open the same device under a different name to circumvent
5461 the lockfile, they get a "device busy" error.
5463 debug(F100,"TTLOCK LOCKF code...","",0);
5464 while ( lockf(ttyfd, F_TLOCK, 0L) != 0 ) {
5465 debug(F111, "TTLOCK lockf error", "", errno);
5466 if ((++tries >= 3) || (errno != EAGAIN)) {
5467 x = unlink(flfnam); /* Remove the lockfile */
5468 if (errno == EACCES && !quiet)
5469 printf("Device already locked by another process\n");
5476 #endif /* COMMENT */
5478 if (haslock) { /* If we made the lockfile ... */
5479 if (lock2[0]) { /* if there is to be a 2nd lockfile */
5480 lockfd = creat(lock2, 0444); /* Create it */
5481 debug(F111,"TTLOCK lock2 creat", lock2, lockfd);
5482 if (lockfd > -1) { /* Created OK, write pid. */
5483 write(lockfd, (char *)&pid, sizeof(pid) );
5484 close(lockfd); /* Close and */
5485 chmod(lock2, 0444); /* set permissions. */
5486 } else { /* Not OK, but don't fail. */
5487 lock2[0] = '\0'; /* Just remember it's not there. */
5490 break; /* and we're done. */
5494 unlink(tmpnam); /* Unlink (remove) the temp file. */
5495 priv_off(); /* Turn off privs */
5496 i = haslock ? 0 : -1; /* Our return value */
5497 debug(F101,"TTLOCK returns","",i);
5500 #endif /* USETTYLOCK */
5501 #endif /* !NOUUCP */
5504 /* T T U N L O C K */
5507 ttunlck() { /* Remove UUCP lockfile(s). */
5511 debug(F111,"ttunlck",flfnam,haslock);
5515 if (haslock && *flfnam) {
5517 priv_on(); /* Turn on privs */
5519 x = uu_unlock(lockname);
5520 #else /* USE_UU_LOCK */
5521 x = ttyunlock(lockname); /* Try to unlock */
5522 #endif /* USE_UU_LOCK */
5523 priv_off(); /* Turn off privs */
5524 if (x < 0 && !quiet)
5525 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5527 *flfnam = '\0'; /* Erase the name. */
5532 #else /* No ttylock()... */
5534 if (haslock && *flfnam) {
5535 /* Don't remove lockfile if we didn't make it ourselves */
5536 if ((x = ttrpid(flfnam)) != (int)getpid()) {
5537 debug(F111,"ttunlck lockfile seized",flfnam,x);
5538 printf("Warning - Lockfile %s seized by pid %d\n",
5544 priv_on(); /* Turn privileges on. */
5546 x = unlink(flfnam); /* Remove the lockfile. */
5547 debug(F111,"ttunlck unlink",flfnam,x);
5549 if (errno && !quiet)
5551 printf("Warning - Can't remove lockfile: %s\n", flfnam);
5554 *flfnam = '\0'; /* Erase the name. */
5558 x = unlink(lkflfn); /* Remove link to lockfile */
5559 debug(F111,"ttunlck AIX link unlink",lkflfn,x);
5561 if (errno && !quiet)
5563 printf("Warning - Can't remove link to lockfile: %s\n", lkflfn);
5567 if (lock2[0]) { /* If there is a second lockfile, */
5569 x = unlink(lock2); /* remove it too. */
5570 debug(F111,"ttunlck lock2 unlink",lock2,x);
5572 if (errno && !quiet)
5574 printf("Warning - Can't remove secondary lockfile: %s\n",
5578 lock2[0] = '\0'; /* Forget its name. */
5584 (VOID) lockf(ttyfd, F_ULOCK, 0L); /* Remove advisory lock */
5586 #endif /* COMMENT */
5588 priv_off(); /* Turn privileges off. */
5590 #endif /* USETTYLOCK */
5591 #endif /* !NOUUCP */
5596 4.3BSD-style UUCP line direction control.
5597 (Stan Barber, Rice U, 1980-something...)
5602 acucntrl(flag,ttname) char *flag, *ttname; {
5603 char x[DEVNAMLEN+32], *device, *devname;
5605 if (strcmp(ttname,CTTNAM) == 0 || xlocal == 0) /* If not local, */
5606 return; /* just return. */
5607 device = ((devname = xxlast(ttname,'/')) != NULL ? devname+1 : ttname);
5608 if (strncmp(device,"LCK..",4) == 0) device += 5;
5609 ckmakmsg(x,DEVNAMLEN+32,"/usr/lib/uucp/acucntrl ",flag," ",device);
5610 debug(F110,"called ",x,0);
5613 #endif /* ACUCNTRL */
5617 T T H F L O W -- Set or Reset hardware flow control.
5619 This is an attempt to collect all hardware-flow-control related code
5620 into a single module. Thanks to Rick Sladkey and John Kohl for lots of
5621 help here. Overview:
5623 Hardware flow control is not supported in many UNIX implementions. Even
5624 when it is supported, there is no (ha ha) "standard" for the programming
5625 interface. In general, 4.3BSD and earlier (sometimes), 4.4BSD, System V,
5626 SunOS, AIX, etc, have totally different methods. (And, not strictly
5627 relevant here, the programming interface often brings one only to a no-op
5628 in the device driver!)
5630 Among all these, we have two major types of APIs: those in which hardware
5631 flow control is determined by bits in the same termio/termios/sgtty mode
5632 word(s) that are used for controlling such items as CBREAK vs RAW mode, and
5633 which are also used by the ttvt(), ttpkt(), conbin(), and concb() routines
5634 for changing terminal modes. And those that use entirely different
5637 In the first category, it is important that any change in the mode bits be
5638 reflected in the relevant termio(s)/sgtty structure, so that subsequent
5639 changes to that structure do not wipe out the effects of this routine. That
5640 is why a pointer, attrs, to the appropriate structure is passed as a
5641 parameter to this routine.
5643 The second category should give us no worries, since any changes to hardware
5644 flow control accomplished by this routine should not affect the termio(s)/
5645 sgtty structures, and therefore will not be undone by later changes to them.
5647 The second argument, status, means to turn on hardware flow control if
5648 nonzero, and to turn it off if zero.
5650 Returns: 0 on apparent success, -1 on probable failure.
5654 The following business is for BSDI, where it was discovered that two
5655 separate bits, CCTS_OFLOW and CRTS_IFLOW, are used in hardware flow control,
5656 but CTRSCTS is defined (in <termios.h>) to be just CCTS_OFLOW rather both
5657 bits, so hwfc only works in one direction if you use CRTSCTS to control it.
5658 Other 4.4BSD-based Unixes such as FreeBSD 4.1, which use these two bits,
5659 define CRTSCTS correctly.
5666 #define CRTSCTS (CRTS_IFLOW|CCTS_OFLOW)
5667 #endif /* CRTS_IFLOW */
5668 #endif /* CCTS_OFLOW */
5669 #endif /* CRTSCTS */
5670 #endif /* FIXCRTSCTS */
5673 tthflow(flow, status, attrs)
5674 int flow, /* Type of flow control (ckcdeb.h) */
5675 status; /* Nonzero = turn it on */
5676 /* Zero = turn it off */
5677 #ifdef BSD44ORPOSIX /* POSIX or BSD44 */
5678 struct termios *attrs;
5679 #else /* System V */
5683 /* AT&T UNIX 3.51m can set but not test for hardware flow control */
5684 #define RTSFLOW CTSCD
5685 #define CTSFLOW CTSCD
5686 #endif /* ATT7300 */
5687 #endif /* UNIX351M */
5688 struct termio *attrs;
5689 #else /* BSD, V7, etc */
5690 struct sgttyb *attrs; /* sgtty info... */
5692 #endif /* BSD44ORPOSIX */
5695 int x = 0; /* tthflow() return code */
5698 return p9tthflow(flow, status);
5701 #ifndef OXOS /* NOT Olivetti X/OS... */
5703 For SunOS 4.0 and later in the BSD environment ...
5705 The declarations are copied and interpreted from the System V header files,
5706 so we don't actually have to pull in all the System V junk when building
5707 C-Kermit for SunOS in the BSD environment, which would be dangerous because
5708 having those symbols defined would cause us to take the wrong paths through
5709 the code. The code in this section is used in both the BSD and Sys V SunOS
5714 In SunOS 4.1 and later, we use the POSIX calls rather than ioctl calls
5715 because GNU CC uses different formats for the _IOxxx macros than regular CC;
5716 the POSIX forms work for both. But the POSIX calls are not available in
5719 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5720 #define TCSANOW 0 /* Do it now */
5723 unsigned long c_iflag; /* Input modes */
5724 unsigned long c_oflag; /* Output modes */
5725 unsigned long c_cflag; /* Control modes */
5726 unsigned long c_lflag; /* Line discipline modes */
5730 struct termios temp;
5732 _PROTOTYP( int tcgetattr, (int, struct termios *) );
5733 _PROTOTYP( int tcsetattr, (int, int, struct termios *) );
5735 When CRTSCTS is set, SunOS won't do output unless both CTS and CD are
5736 asserted. So we don't set CRTSCTS unless CD is up. This should be OK,
5737 since we don't need RTS/CTS during dialing, and after dialing is complete,
5738 we should have CD. If not, we still communicate, but without RTS/CTS.
5740 int mflags; /* Modem signal flags */
5743 if (ttpipe) return(0);
5746 if (ttpty) return(0);
5749 debug(F101,"tthflow SUNOS41 entry status","",status);
5750 if (!status) { /* Turn hard flow off */
5751 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5752 (temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5753 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5754 x = tcsetattr(ttyfd,TCSANOW,&temp);
5756 } else { /* Turn hard flow on */
5757 if (ioctl(ttyfd,TIOCMGET,&mflags) > -1 && /* Get modem signals */
5758 (mflags & TIOCM_CAR)) { /* Check for CD */
5759 debug(F100,"tthflow SunOS has CD","",0);
5760 if (tcgetattr(ttyfd, &temp) > -1 && /* Get device attributes */
5761 !(temp.c_cflag & CRTSCTS)) { /* Check for RTS/CTS */
5762 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5763 x = tcsetattr(ttyfd,TCSANOW,&temp);
5767 debug(F100,"tthflow SunOS no CD","",0);
5772 struct termios temp;
5774 if (ttpipe) return(0);
5777 if (ttpty) return(0);
5779 debug(F101,"tthflow QNX entry status","",status);
5780 if (tcgetattr(ttyfd, &temp) > -1) { /* Get device attributes */
5781 if (!status) { /* Turn hard flow off */
5782 if ((temp.c_cflag & (IHFLOW|OHFLOW)) == (IHFLOW|OHFLOW)) {
5783 temp.c_cflag &= ~(IHFLOW|OHFLOW); /* It's there, remove it */
5784 attrs->c_cflag &= ~(IHFLOW|OHFLOW);
5785 x = tcsetattr(ttyfd,TCSANOW,&temp);
5787 } else { /* Turn hard flow on */
5788 if ((temp.c_cflag & (IHFLOW|OHFLOW)) != (IHFLOW|OHFLOW)) {
5789 temp.c_cflag |= (IHFLOW|OHFLOW); /* Not there, add it */
5790 temp.c_iflag &= ~(IXON|IXOFF); /* Bye to IXON/IXOFF */
5791 ttraw.c_lflag |= IEXTEN; /* Must be on */
5792 x = tcsetattr(ttyfd,TCSANOW,&temp);
5793 attrs->c_cflag |= (IHFLOW|OHFLOW);
5794 attrs->c_iflag &= ~(IXON|IXOFF);
5799 debug(F100, "tthflow QNX getattr fails", "", 0);
5802 #ifdef POSIX_CRTSCTS
5804 POSIX_CRTSCTS is defined in ckcdeb.h or on CC command line.
5805 Note: Do not assume CRTSCTS is a one-bit field!
5807 struct termios temp;
5809 if (ttpipe) return(0);
5812 if (ttpty) return(0);
5814 debug(F101,"tthflow POSIX_CRTSCTS entry status","",status);
5816 x = tcgetattr(ttyfd, &temp);
5817 debug(F111,"tthflow POSIX_CRTSCTS tcgetattr",ckitoa(x),errno);
5822 if (!status) { /* Turn hard flow off */
5825 /* This can fail because of sign extension */
5826 /* e.g. in Linux where it's Bit 31 */
5827 (temp.c_cflag & CRTSCTS) == CRTSCTS
5829 (temp.c_cflag & CRTSCTS) != 0
5830 #endif /* COMMENT */
5832 temp.c_cflag &= ~CRTSCTS; /* It's there, remove it */
5833 attrs->c_cflag &= ~CRTSCTS;
5834 x = tcsetattr(ttyfd,TCSANOW,&temp);
5835 debug(F111,"tthflow POSIX_CRTSCTS OFF tcsetattr",
5838 } else { /* Turn hard flow on */
5841 /* This can fail because of sign extension */
5842 (temp.c_cflag & CRTSCTS) != CRTSCTS
5844 (temp.c_cflag & CRTSCTS) == 0
5845 #endif /* COMMENT */
5847 temp.c_cflag |= CRTSCTS; /* Not there, add it */
5848 temp.c_iflag &= ~(IXON|IXOFF|IXANY); /* Bye to IXON/IXOFF */
5849 x = tcsetattr(ttyfd,TCSANOW,&temp);
5850 debug(F111,"tthflow POSIX_CRTSCTS ON tcsetattr",
5852 attrs->c_cflag |= CRTSCTS;
5853 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
5860 SunOS 4.0 (and maybe earlier?). This code is dangerous because it
5861 prevents compilation with GNU gcc, which uses different formats for the
5862 _IORxxx macros than regular cc. SunOS 4.1 and later can use the POSIX
5863 routines above, which work for both cc and gcc.
5865 #define TCGETS _IOR(T, 8, struct termios) /* Get modes into termios struct */
5866 #define TCSETS _IOW(T, 9, struct termios) /* Set modes from termios struct */
5867 #define CRTSCTS 0x80000000 /* RTS/CTS flow control */
5870 unsigned long c_iflag; /* Input modes */
5871 unsigned long c_oflag; /* Output modes */
5872 unsigned long c_cflag; /* Control modes */
5873 unsigned long c_lflag; /* Line discipline modes */
5877 struct termios temp;
5879 if (ttpipe) return(0);
5882 if (ttpty) return(0);
5884 debug(F101,"tthflow entry status","",status);
5885 if (ioctl(ttyfd,TCGETS,&temp) > -1) { /* Get terminal modes. */
5886 if (status) { /* Turn hard flow on */
5887 temp.c_cflag |= CRTSCTS; /* Add RTS/CTS to them. */
5888 x = ioctl(ttyfd,TCSETS,&temp); /* Set them again. */
5889 attrs->c_cflag |= CRTSCTS; /* Add to global info. */
5890 } else { /* Turn hard flow off */
5891 temp.c_cflag &= ~CRTSCTS;
5892 x = ioctl(ttyfd,TCSETS,&temp);
5893 attrs->c_cflag &= ~CRTSCTS;
5896 #else /* Not SunOS 4.0 or later */
5897 #ifdef AIXRS /* IBM AIX RS/6000 */
5898 #ifndef AIX41 /* But only pre-4.x == SVR4 */
5900 if (ttpipe) return(0);
5903 if (ttpty) return(0);
5906 if ((x = ioctl(ttyfd, TXADDCD, "rts")) < 0 && errno != EBUSY)
5907 debug(F100,"hardflow TXADDCD (rts) error", "", 0);
5909 if ((x = ioctl(ttyfd, TXDELCD, "rts")) < 0 && errno != EINVAL)
5910 debug(F100,"hardflow TXDELCD (rts) error", "", 0);
5913 #else /* Not AIX RS/6000 */
5915 #ifdef ATTSV /* System V... */
5917 #ifdef CK_SCOV5 /* SCO Open Server 5.0 */
5920 #ifdef M_UNIX /* SCO UNIX 3.2v4.x or earlier */
5923 #endif /* CK_SCOV5 */
5925 #ifdef SCO_FORCE_RTSXOFF
5926 #ifdef CK_SCOUNIX /* But not SCO OpenServer 5.0.4 */
5927 #ifdef SCO_OSR504 /* or later... */
5929 #endif /* SCO_OSR504 */
5930 #endif /* CK_SCOUNIX */
5931 #endif /* SCO_FORCE_RTSXOFF */
5935 struct termios temp;
5937 if (ttpipe) return(0);
5940 if (ttpty) return(0);
5942 debug(F101,"tthflow SCOUNIX POSIX entry status","",status);
5944 x = tcgetattr(ttyfd, &temp);
5945 debug(F111,"tthflow SCO UNIX POSIX tcgetattr",ckitoa(x),errno);
5949 if (ttpipe) return(0);
5952 if (ttpty) return(0);
5954 debug(F101,"tthflow SCOUNIX non-POSIX entry status","",status);
5955 x = ioctl(ttyfd, TCGETA, &temp);
5956 debug(F111,"tthflow SCO UNIX non-POSIX TCGETA",ckitoa(x),errno);
5959 This is not really POSIX, since POSIX does not deal with hardware flow
5960 control, but we are using the POSIX APIs. In fact, RTSFLOW and CTSFLOW
5961 are defined in termio.h, but within #ifndef _POSIX_SOURCE..#endif. So
5962 let's try forcing their definitions here.
5965 #define CTSFLOW 0020000
5966 debug(F101,"tthflow SCO defining CTSFLOW","",CTSFLOW);
5968 debug(F101,"tthflow SCO CTSFLOW","",CTSFLOW);
5969 #endif /* CTSFLOW */
5971 #define RTSFLOW 0040000
5972 debug(F101,"tthflow SCO defining RTSFLOW","",RTSFLOW);
5974 debug(F101,"tthflow SCO RTSFLOW","",RTSFLOW);
5975 #endif /* RTSFLOW */
5977 #define ORTSFL 0100000
5978 debug(F101,"tthflow SCO defining ORTSFL","",ORTSFL);
5980 debug(F101,"tthflow SCO ORTSFL","",ORTSFL);
5984 if (status) { /* Turn it ON */
5985 temp.c_cflag |= RTSFLOW|CTSFLOW;
5986 attrs->c_cflag |= RTSFLOW|CTSFLOW;
5988 temp.c_cflag &= ~ORTSFL;
5989 attrs->c_cflag &= ~ORTSFL;
5991 temp.c_iflag &= ~(IXON|IXOFF|IXANY);
5992 attrs->c_iflag &= ~(IXON|IXOFF|IXANY);
5993 } else { /* Turn it OFF */
5995 temp.c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
5996 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW|ORTSFL);
5998 temp.c_cflag &= ~(RTSFLOW|CTSFLOW);
5999 attrs->c_cflag &= ~(RTSFLOW|CTSFLOW);
6003 x = tcsetattr(ttyfd, TCSADRAIN, &temp);
6005 x = ioctl(ttyfd, TCSETA, &temp);
6007 debug(F101,"tthflow SCO set modes","",x);
6009 #else /* Not SCO UNIX */
6011 if (ttpipe) return(0);
6014 if (ttpty) return(0);
6016 if (!status) { /* Turn it OFF */
6018 debug(F100,"tthflow ATTSV RTS/CTS OFF","",0);
6019 rctsx.x_hflag &= ~(RTSXOFF|CTSXON);
6021 x = ioctl(ttyfd,TCSETX,&rctsx);
6022 debug(F101,"tthflow ATTSV TCSETX OFF","",x);
6025 debug(F100,"tthflow TCSETX not defined","",0);
6028 debug(F100,"tthflow ATTSV RTSXOFF not defined","",0);
6029 #endif /* RTSXOFF */
6031 debug(F100,"tthflow ATTSV DTR/CD OFF","",0);
6032 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6033 x = ioctl(ttyfd,TCSETX,&rctsx);
6034 debug(F101,"tthflow ATTSV DTRXOFF OFF","",x);
6036 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6037 #endif /* DTRXOFF */
6038 } else { /* Turn it ON. */
6039 if (flow == FLO_RTSC) { /* RTS/CTS Flow control... */
6040 debug(F100,"tthflow ATTSV RTS/CTS ON","",0);
6042 /* This is the preferred way, according to SVID3 */
6044 x = ioctl(ttyfd,TCGETX,&rctsx);
6045 debug(F101,"tthflow TCGETX","",x);
6047 rctsx.x_hflag |= RTSXOFF | CTSXON;
6048 x = ioctl(ttyfd,TCSETX,&rctsx);
6049 debug(F100,"tthflow ATTSV ioctl","",x);
6052 debug(F100,"tthflow TCGETX not defined","",0);
6056 debug(F100,"tthflow RTSXOFF not defined","",0);
6058 #endif /* RTSXOFF */
6059 } else if (flow == FLO_DTRC) { /* DTR/CD Flow control... */
6060 debug(F100,"tthflow ATTSV DTR/CD ON","",0);
6062 /* This is straight out of SVID R4 */
6063 if (ioctl(ttyfd,TCGETX,&rctsx) > -1) {
6064 rctsx.x_hflag &= ~(DTRXOFF|CDXON);
6065 x = ioctl(ttyfd,TCSETX,&rctsx);
6068 debug(F100,"tthflow ATTSV DTRXOFF not defined","",0);
6070 #endif /* DTRXOFF */
6073 #endif /* CK_SCOUNIX */
6075 #else /* not System V... */
6081 if (ttpipe) return(0);
6084 if (ttpty) return(0);
6086 x = LDODTR | LDOCTS; /* Found only on UTEK? */
6087 if (flow == FLO_DTRT && status) { /* Use hardware flow control */
6089 x = ioctl(ttyfd,TIOCLBIS,&x);
6091 debug(F100,"hardflow TIOCLBIS error","",0);
6094 debug(F100,"hardflow TIOCLBIS ok","",0);
6099 x = ioctl(ttyfd,TIOCLBIC,&x);
6101 debug(F100,"hardflow TIOCLBIC error","",0);
6104 debug(F100,"hardflow TIOCLBIC ok","",0);
6110 #endif /* CK_DTRCTS */
6115 #endif /* POSIX_CRTSCTS */
6116 #endif /* SUNOS41 */
6120 struct termios temp; /* Olivetti X/OS ... */
6123 if (ttpipe) return(0);
6126 if (ttpty) return(0);
6128 x = ioctl(ttyfd,TCGETS,&temp);
6130 temp.c_cflag &= ~(CRTSCTS|CDTRCTS|CBRKFLOW|CDTRDSR|CRTSDSR);
6133 case FLO_RTSC: temp.c_cflag |= CRTSCTS; /* RTS/CTS (hard) */
6135 case FLO_DTRT: temp.c_cflag |= CDTRCTS; /* DTR/CTS (hard) */
6139 x = ioctl(ttyfd,TCSETS,&temp);
6147 /* T T P K T -- Condition the communication line for packets */
6148 /* or for modem dialing */
6151 If called with speed > -1, also set the speed.
6152 Returns 0 on success, -1 on failure.
6154 NOTE: the "xflow" parameter is supposed to be the currently selected
6155 type of flow control, but for historical reasons, this parameter is also
6156 used to indicate that we are dialing. Therefore, when the true flow
6157 control setting is needed, we access the external variable "flow", rather
6158 than trusting our "xflow" argument.
6162 ttpkt(long speed, int xflow, int parity)
6164 ttpkt(speed,xflow,parity) long speed; int xflow, parity;
6165 #endif /* CK_ANSIC */
6170 #endif /* NOLOCAL */
6172 extern int flow; /* REAL flow-control setting */
6174 if (ttyfd < 0) return(-1); /* Not open. */
6176 debug(F101,"ttpkt parity","",parity);
6177 debug(F101,"ttpkt xflow","",xflow);
6178 debug(F101,"ttpkt speed","",(int) speed);
6180 ttprty = parity; /* Let other tt functions see these. */
6181 ttspeed = speed; /* Make global copy for this module */
6182 ttpmsk = ttprty ? 0177 : 0377; /* Parity stripping mask */
6184 needpchk = ttprty ? 0 : 1; /* Parity check needed? */
6187 #endif /* PARSENSE */
6189 debug(F101,"ttpkt ttpmsk","",ttpmsk);
6190 debug(F101,"ttpkt netconn","",netconn);
6192 #ifdef NETCONN /* No mode-changing for telnet */
6196 if (ttnet == NET_TCPB) { /* But turn off Nagle */
6197 extern int tcp_nodelay;
6198 nodelay_sav = tcp_nodelay;
6201 #endif /* TCP_NODELAY */
6203 if (istncomport()) {
6205 if (tvtflg == 0 && speed == ttspeed && flow == ttflow
6206 /* && ttcarr == curcarr */ ) {
6207 debug(F100,"ttpkt modes already set, skipping...","",0);
6208 return(0); /* Already been called. */
6210 if (flow != ttflow) {
6211 if ((rc = tnsetflow(flow)) < 0)
6215 if (speed != ttspeed) {
6217 speed = tnc_get_baud();
6218 else if ((rc = tnc_set_baud(speed)) < 0)
6222 tnc_set_datasize(8);
6223 tnc_set_stopsize(stopbits);
6228 case 'e': /* Even */
6229 debug(F100,"ttres 8 bits + even parity","",0);
6233 debug(F100,"ttres 8 bits + odd parity","",0);
6236 case 'm': /* Mark */
6237 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
6240 case 's': /* Space */
6241 debug(F100,"ttres 8 bits + invalid parity: space","",0);
6246 #endif /* HWPARITY */
6248 tnc_set_parity(1); /* None */
6253 #endif /* TN_COMPORT */
6254 #endif /* TCPSOCKET */
6258 #endif /* NETCONN */
6260 if (ttpipe) return(0);
6263 if (ttpty) return(0);
6267 if (ttfdflg && !isatty(ttyfd)) return(0);
6272 #endif /* COHERENT */
6274 #ifndef SVORPOSIX /* Berkeley, V7, etc. */
6277 For some reason, with BSD terminal drivers, you can't set FLOW to XON/XOFF
6278 after having previously set it to NONE without closing and reopening the
6279 device. Unless there's something I overlooked below...
6281 if (ttflow == FLO_NONE && flow == FLO_XONX && xlocal == 0) {
6282 debug(F101,"ttpkt executing horrible flow kludge","",0);
6283 ttclos(0); /* Close it */
6285 ttopen(ttnmsv,&x,ttmdm,0); /* Open it again */
6288 #endif /* SVORPOSIX */
6290 #ifdef COHERENT /* This must be vestigial since we */
6291 #undef SVORPOSIX /* reverse it a few lines below... */
6292 #endif /* COHERENT */
6294 if (xflow != FLO_DIAL && xflow != FLO_DIAX)
6295 ttflow = xflow; /* Now make this available too. */
6299 s2 = (int) (speed / 10L); /* Convert bps to cps */
6300 debug(F101,"ttpkt calling ttsspd","",s2);
6301 s = ttsspd(s2); /* Check and set the speed */
6302 debug(F101,"ttpkt ttsspd result","",s);
6303 carrctl(&ttraw, xflow != FLO_DIAL /* Carrier control */
6304 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
6305 tvtflg = 0; /* So ttvt() will work next time */
6307 #endif /* NOLOCAL */
6311 #endif /* COHERENT */
6313 #ifndef SVORPOSIX /* BSD section */
6314 if (flow == FLO_RTSC || /* Hardware flow control */
6317 tthflow(flow, 1, &ttraw);
6318 debug(F100,"ttpkt hard flow, TANDEM off, RAW on","",0);
6319 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6320 ttraw.sg_flags |= RAW; /* Enter raw mode */
6321 } else if (flow == FLO_NONE) { /* No flow control */
6322 debug(F100,"ttpkt no flow, TANDEM off, RAW on","",0);
6323 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6324 tthflow(flow, 0, &ttraw); /* Turn off any hardware f/c too */
6325 ttraw.sg_flags |= RAW; /* Enter raw mode */
6326 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
6327 debug(F100,"ttpkt keeping original TANDEM","",0);
6328 ttraw.sg_flags &= ~TANDEM;
6329 ttraw.sg_flags |= (ttold.sg_flags & TANDEM);
6330 /* NOTE: We should also handle hardware flow control here! */
6333 /* SET FLOW XON/XOFF is in effect, or SET FLOW KEEP resulted in Xon/Xoff */
6335 if ((flow == FLO_XONX) || (ttraw.sg_flags & TANDEM)) {
6336 debug(F100,"ttpkt turning on TANDEM","",0);
6337 ttraw.sg_flags |= TANDEM; /* So ask for it. */
6339 #ifdef LPASS8 /* Can pass 8-bit data through? */
6340 /* If the LPASS8 local mode is available, then flow control can always */
6341 /* be used, even if parity is none and we are transferring 8-bit data. */
6342 /* But we only need to do all this if Xon/Xoff is requested. */
6343 /* BUT... this tends not to work through IP or LAT connections, terminal */
6344 /* servers, telnet, rlogin, etc, so it is currently disabled. */
6345 x = LPASS8; /* If LPASS8 defined, then */
6346 debug(F100,"ttpkt executing LPASS8 code","",0);
6347 if (lmodef) { /* TIOCLBIS must be too. */
6348 x = ioctl(ttyfd,TIOCLBIS,&x); /* Try to set LPASS8. */
6350 debug(F100,"ttpkt TIOCLBIS error","",0);
6353 debug(F100,"ttpkt TIOCLBIS ok","",0);
6357 But if we use LPASS8 mode, we must explicitly turn off
6358 terminal interrupts of all kinds.
6360 #ifdef TIOCGETC /* Not rawmode, */
6361 if (tcharf && (xlocal == 0)) { /* must turn off */
6362 tchnoi.t_intrc = -1; /* interrupt character */
6363 tchnoi.t_quitc = -1; /* and quit character. */
6364 tchnoi.t_startc = 17; /* Make sure xon */
6365 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6367 tchnoi.t_eofc = -1; /* eof character. */
6368 tchnoi.t_brkc = -1; /* brk character. */
6370 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6371 debug(F100,"ttpkt TIOCSETC failed","",0);
6374 debug(F100,"ttpkt TIOCSETC ok","",0);
6377 /* only for paranoid debugging */
6381 ioctl(0,TIOCGETC,&foo);
6383 "intr=%d,quit=%d, start=%d, stop=%d, eof=%d, brk=%d",
6384 foo.t_intrc, foo.t_quitc, foo.t_startc,
6385 foo.t_stopc, foo.t_eofc, foo.t_brkc);
6386 debug(F110,"ttpkt chars",tchbuf,0);
6388 #endif /* COMMENT */
6390 ttraw.sg_flags |= CBREAK; /* Needed for unknown reason */
6391 #endif /* TIOCGETC */
6393 /* Prevent suspend during packet mode */
6394 #ifdef TIOCGLTC /* Not rawmode, */
6395 if (ltcharf && (xlocal == 0)) { /* must turn off */
6396 ltchnoi.t_suspc = -1; /* suspend character */
6397 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6398 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6399 debug(F100,"ttpkt TIOCSLTC failed","",0);
6402 debug(F100,"ttpkt TIOCSLTC ok","",0);
6405 #endif /* TIOCGLTC */
6407 #else /* LPASS8 not defined */
6409 /* Previously, BSD-based implementations always */
6410 /* used rawmode for packets. Now, we use rawmode only if parity is NONE. */
6411 /* This allows the flow control requested above to actually work, but only */
6412 /* if the user asks for parity (which also means they get 8th-bit quoting). */
6414 if (parity) { /* If parity, */
6415 ttraw.sg_flags &= ~RAW; /* use cooked mode */
6419 #endif /* COMMENT */
6420 ttraw.sg_flags |= CBREAK;
6421 debug(F101,"ttpkt cooked, cbreak, parity","",parity);
6422 #ifdef TIOCGETC /* Not rawmode, */
6423 if (tcharf && (xlocal == 0)) { /* must turn off */
6424 tchnoi.t_intrc = -1; /* interrupt character */
6425 tchnoi.t_quitc = -1; /* and quit character. */
6426 tchnoi.t_startc = 17; /* Make sure xon */
6427 tchnoi.t_stopc = 19; /* and xoff not ignored. */
6429 tchnoi.t_eofc = -1; /* eof character. */
6430 tchnoi.t_brkc = -1; /* brk character. */
6432 if (ioctl(ttyfd,TIOCSETC,&tchnoi) < 0) {
6433 debug(F100,"ttpkt TIOCSETC failed","",0);
6436 debug(F100,"ttpkt TIOCSETC ok","",0);
6439 #endif /* TIOCGETC */
6440 #ifdef TIOCGLTC /* Not rawmode, */
6441 /* Prevent suspend during packet mode */
6442 if (ltcharf && (xlocal == 0)) { /* must turn off */
6443 ltchnoi.t_suspc = -1; /* suspend character */
6444 ltchnoi.t_dsuspc = -1; /* and delayed suspend character */
6445 if (ioctl(ttyfd,TIOCSLTC,&tchnoi) < 0) {
6446 debug(F100,"ttpkt TIOCSLTC failed","",0);
6449 debug(F100,"ttpkt TIOCSLTC ok","",0);
6452 #endif /* TIOCGLTC */
6453 } else { /* If no parity, */
6454 ttraw.sg_flags |= RAW; /* must use 8-bit raw mode. */
6455 debug(F101,"ttpkt setting rawmode, parity","",parity);
6458 } /* End of Xon/Xoff section */
6460 /* Don't echo, don't map CR to CRLF on output, don't fool with case */
6462 ttraw.sg_flags &= ~(ECHO|CRMOD|LCASE);
6464 ttraw.sg_flags &= ~(ECHO|CRMOD);
6468 ttraw.sg_flags &= ~ANYP; /* Must set this on old Towers */
6472 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0) /* Set the new modes. */
6476 if (stty(ttyfd,&ttraw) < 0) { /* Set the new modes. */
6477 debug(F101,"ttpkt stty failed","",errno);
6480 #endif /* BELLV10 */
6481 debug(F100,"ttpkt stty ok","",0);
6484 x = xlocal ? km_ext : km_con; /* Put line in ASCII mode. */
6485 if (x != -1) { /* Make sure we know original modes. */
6488 if (ioctl(ttyfd,TIOCKSET, &x) < 0) {
6489 perror("ttpkt can't set ASCII mode");
6490 debug(F101,"ttpkt error setting ASCII mode","",x);
6494 debug(F100,"ttpkt set ASCII mode ok","",0);
6495 #endif /* sony_news */
6497 if (xlocal == 0) { /* Turn this off so we can read */
6498 signal(SIGINT,SIG_IGN); /* Ctrl-C chars typed at console */
6501 tvtflg = 0; /* So ttvt() will work next time */
6502 debug(F100,"ttpkt success","",0);
6505 #endif /* Not ATTSV or POSIX */
6507 /* AT&T UNIX and POSIX */
6511 #endif /* COHERENT */
6514 if (flow == FLO_XONX) { /* Xon/Xoff */
6515 ttraw.c_iflag |= (IXON|IXOFF);
6516 tthflow(flow, 0, &ttraw);
6517 } else if (flow == FLO_NONE) { /* None */
6518 /* NOTE: We should also turn off hardware flow control here! */
6519 ttraw.c_iflag &= ~(IXON|IXOFF);
6520 tthflow(flow, 0, &ttraw);
6521 } else if (flow == FLO_KEEP) { /* Keep */
6522 ttraw.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
6523 ttraw.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
6524 /* NOTE: We should also handle hardware flow control here! */
6525 #ifdef POSIX_CRTSCTS
6526 /* In Linux case, we do this, which is unlikely to be portable */
6527 ttraw.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
6528 ttraw.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
6529 #endif /* POSIX_CRTSCTS */
6530 } else if (flow == FLO_RTSC || /* Hardware */
6533 ttraw.c_iflag &= ~(IXON|IXOFF); /* (190) */
6534 tthflow(flow, 1, &ttraw);
6536 ttraw.c_lflag &= ~(ICANON|ECHO);
6537 ttraw.c_lflag &= ~ISIG; /* Do NOT check for interrupt chars */
6541 if (flow != FLO_RTSC && flow != FLO_DTRC && flow != FLO_DTRT)
6544 ttraw.c_lflag &= ~IEXTEN; /* Turn off ^O/^V processing */
6545 #endif /* COHERENT */
6547 ttraw.c_cc[VDISCARD] = ttraw.c_cc[VLNEXT] = CDISABLE;
6549 ttraw.c_lflag |= NOFLSH; /* Don't flush */
6550 ttraw.c_iflag |= IGNPAR; /* Ignore parity errors */
6553 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
6555 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
6558 ttraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
6560 ttraw.c_oflag &= ~OPOST;
6561 ttraw.c_cflag &= ~(CSIZE);
6562 ttraw.c_cflag |= (CS8|CREAD|HUPCL);
6566 if (stopbits == 2) {
6567 ttraw.c_cflag |= CSTOPB; /* 2 stop bits */
6568 debug(F100,"ttpkt 2 stopbits","",0);
6569 } else if (stopbits == 1) {
6570 ttraw.c_cflag &= ~(CSTOPB); /* 1 stop bit */
6571 debug(F100,"ttpkt 1 stopbit","",0);
6577 if (hwparity && xlocal) { /* Hardware parity */
6578 ttraw.c_cflag |= PARENB; /* Enable parity */
6580 /* Uncomment this only if needed -- I don't think it is */
6581 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
6582 ttraw.c_cflag |= CS8; /* And set it to 8 */
6583 #endif /* COMMENT */
6585 ttraw.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
6586 debug(F100,"ttpkt IGNPAR","",0); /* that have parity errors */
6589 case 'e': /* Even */
6590 ttraw.c_cflag &= ~(PARODD);
6591 debug(F100,"ttpkt 8 bits + even parity","",0);
6594 ttraw.c_cflag |= PARODD;
6595 debug(F100,"ttpkt 8 bits + odd parity","",0);
6597 case 'm': /* Mark */
6598 case 's': /* Space */
6599 /* PAREXT is mentioned in SVID but the details are not given. */
6600 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
6601 debug(F100,"ttpkt 8 bits + invalid parity","",0);
6604 } else { /* We handle parity ourselves */
6605 #endif /* HWPARITY */
6606 ttraw.c_cflag &= ~(PARENB); /* Don't enable parity */
6609 #endif /* HWPARITY */
6612 ttraw.c_cc[4] = 48; /* So Series/1 doesn't interrupt on every char */
6615 #ifndef VEOF /* for DGUX this is VEOF, not VMIN */
6616 ttraw.c_cc[4] = 1; /* [VMIN] return max of this many characters or */
6620 ttraw.c_cc[VMIN] = 1;
6626 #ifndef VEOL /* for DGUX this is VEOL, not VTIME */
6627 ttraw.c_cc[5] = 0; /* [VTIME] when this many secs/10 expire w/no input */
6631 ttraw.c_cc[VTIME] = 0;
6639 #ifdef VINTR /* Turn off interrupt character */
6640 if (xlocal == 0) /* so ^C^C can break us out of */
6641 ttraw.c_cc[VINTR] = 0; /* packet mode. */
6645 if (p9ttyparity('n') < 0)
6651 ttraw.c_cc[VMIN] = 0; /* DR7 can only poll. */
6652 #endif /* BEOSORBEBOX */
6653 debug(F100,"ttpkt calling tcsetattr(TCSETAW)","",0);
6654 x = tcsetattr(ttyfd,TCSADRAIN,&ttraw);
6655 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr","",x);
6657 debug(F101,"ttpkt BSD44ORPOSIX tcsetattr errno","",errno);
6660 #else /* BSD44ORPOSIX */
6661 x = ioctl(ttyfd,TCSETAW,&ttraw);
6662 debug(F101,"ttpkt ATTSV ioctl TCSETAW","",x);
6663 if (x < 0) { /* set new modes . */
6664 debug(F101,"ttpkt ATTSV ioctl TCSETAW errno","",errno);
6667 #endif /* BSD44ORPOSIX */
6670 debug(F100,"ttpkt ok","",0);
6676 #endif /* COHERENT */
6680 /* T T S E T F L O W -- Set flow control immediately. */
6684 #endif /* COHERENT */
6687 ttsetflow(flow) int flow; {
6688 if (ttyfd < 0) /* A channel must be open */
6691 debug(F101,"ttsetflow flow","",flow);
6694 if (netconn && istncomport()) {
6695 debug(F101,"ttsetflow net modem","",ttmdm);
6696 return(tnsetflow(flow));
6698 #endif /* TN_COMPORT */
6700 if (ttpipe) return(0);
6703 if (ttpty) return(0);
6707 /* This seems to hurt... */
6708 if (flow == FLO_KEEP)
6710 #endif /* COMMENT */
6712 if (flow == FLO_RTSC || /* Hardware flow control... */
6715 tthflow(flow, 1, &ttraw);
6717 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6719 ttraw.c_iflag &= ~(IXON|IXOFF);
6720 #endif /* SVORPOSIX */
6722 } else if (flow == FLO_XONX) { /* Xon/Xoff... */
6725 ttraw.sg_flags |= TANDEM;
6727 ttraw.c_iflag |= (IXON|IXOFF);
6728 #endif /* SVORPOSIX */
6729 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off hardware flow control */
6731 } else if (flow == FLO_NONE) { /* No flow control */
6734 ttraw.sg_flags &= ~TANDEM; /* Turn off software flow control */
6736 ttraw.c_iflag &= ~(IXON|IXOFF);
6737 #endif /* SVORPOSIX */
6738 tthflow(FLO_RTSC, 0, &ttraw); /* Turn off any hardware f/c too */
6741 /* Set the new modes... */
6743 #ifndef SVORPOSIX /* BSD and friends */
6745 if (ioctl(ttyfd,TIOCSETP,&ttraw) < 0)
6749 if (stty(ttyfd,&ttraw) < 0)
6752 #endif /* BELLV10 */
6754 #ifdef BSD44ORPOSIX /* POSIX */
6755 if (tcsetattr(ttyfd,TCSADRAIN,&ttraw) < 0)
6757 #else /* System V */
6758 if (ioctl(ttyfd,TCSETAW,&ttraw) < 0)
6760 #endif /* BSD44ORPOSIX */
6761 #endif /* SVORPOSIX */
6766 #endif /* COHERENT */
6768 /* T T V T -- Condition communication device for use as virtual terminal. */
6772 ttvt(long speed, int flow)
6774 ttvt(speed,flow) long speed; int flow;
6775 #endif /* CK_ANSIC */
6779 debug(F101,"ttvt ttyfd","",ttyfd);
6780 debug(F101,"ttvt tvtflg","",tvtflg);
6781 debug(F111,"ttvt speed",ckitoa(ttspeed),speed);
6782 debug(F111,"ttvt flow",ckitoa(ttflow),flow);
6783 debug(F111,"ttvt curcarr",ckitoa(ttcarr),curcarr);
6785 /* Note: NetBSD and maybe other BSD44s have cfmakeraw() */
6786 /* Maybe it would be simpler to use it... */
6790 return(conbin((char)escchr));
6792 if (ttyfd < 0) { /* Not open. */
6795 else /* But maybe something buffered. */
6799 if (ttpipe) return(0);
6802 if (ttpty) return(0);
6809 extern int tcp_nodelay;
6810 if (ttnet == NET_TCPB) {
6811 if (nodelay_sav > -1) {
6812 no_delay(ttyfd,nodelay_sav);
6817 #endif /* TCP_NODELAY */
6819 if (istncomport()) {
6821 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
6822 /* && ttcarr == curcarr */ ) {
6823 debug(F100,"ttvt modes already set, skipping...","",0);
6824 return(0); /* Already been called. */
6826 if (flow != ttflow) {
6827 if ((rc = tnsetflow(flow)) < 0)
6831 if (speed != ttspeed) {
6833 speed = tnc_get_baud();
6834 else if ((rc = tnc_set_baud(speed)) < 0)
6838 tnc_set_datasize(8);
6839 tnc_set_stopsize(stopbits);
6844 case 'e': /* Even */
6845 debug(F100,"ttres 8 bits + even parity","",0);
6849 debug(F100,"ttres 8 bits + odd parity","",0);
6852 case 'm': /* Mark */
6853 debug(F100,"ttres 8 bits + invalid parity: mark","",0);
6856 case 's': /* Space */
6857 debug(F100,"ttres 8 bits + invalid parity: space","",0);
6862 #endif /* HWPARITY */
6864 tnc_set_parity(1); /* None */
6869 #endif /* TN_COMPORT */
6870 #endif /* TCPSOCKET */
6871 tvtflg = 1; /* Network connections... */
6872 debug(F100,"ttvt network connection, skipping...","",0);
6873 return(0); /* ... require no special setup */
6875 #endif /* NETCONN */
6877 if (tvtflg != 0 && speed == ttspeed && flow == ttflow
6878 /* && ttcarr == curcarr */ )
6880 debug(F100,"ttvt modes already set, skipping...","",0);
6881 return(0); /* Already been called. */
6889 debug(F100,"ttvt using external fd, skipping...","",0);
6893 debug(F100,"ttvt setting modes...","",0);
6895 if (xlocal) { /* For external lines... */
6896 s2 = (int) (speed / 10L);
6897 s = ttsspd(s2); /* Check/set the speed */
6898 carrctl(&tttvt, flow != FLO_DIAL /* Do carrier control */
6899 && (ttcarr == CAR_ON || (ttcarr == CAR_AUT && ttmdm != 0)));
6905 #endif /* COHERENT */
6908 /* Berkeley, V7, etc */
6909 if (flow == FLO_RTSC || /* Hardware flow control */
6912 tthflow(flow, 1, &tttvt);
6913 debug(F100,"ttvt hard flow, TANDEM off","",0);
6914 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
6915 } else if (flow == FLO_XONX) { /* Xon/Xoff flow control */
6916 debug(F100,"ttvt TANDEM on","",0);
6917 tttvt.sg_flags |= TANDEM; /* Ask for it. */
6918 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
6919 } else if (flow == FLO_NONE) {
6920 debug(F100,"ttvt no flow, TANDEM off, RAW on","",0);
6921 tttvt.sg_flags &= ~TANDEM; /* Turn off software flow control */
6922 tthflow(flow, 0, &tttvt); /* Turn off any hardware f/c too */
6923 tttvt.sg_flags |= RAW; /* Enter raw mode */
6924 } else if (flow == FLO_KEEP) { /* Keep device's original setting */
6925 debug(F100,"ttvt keeping original TANDEM","",0);
6926 tttvt.sg_flags &= ~TANDEM;
6927 tttvt.sg_flags |= (ttold.sg_flags & TANDEM);
6928 /* NOTE: We should also handle hardware flow control here! */
6930 tttvt.sg_flags |= RAW; /* Raw mode in all cases */
6932 tttvt.sg_flags &= ~(ECHO|ANYP); /* No echo or parity */
6934 tttvt.sg_flags &= ~ECHO; /* No echo */
6938 if (ioctl(ttyfd,TIOCSETP,&tttvt) < 0) /* Set the new modes */
6941 if (stty(ttyfd,&tttvt) < 0) /* Set the new modes */
6943 #endif /* BELLV10 */
6945 #else /* It is ATTSV or POSIX */
6947 if (flow == FLO_XONX) { /* Software flow control */
6948 tttvt.c_iflag |= (IXON|IXOFF); /* On if requested. */
6949 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
6950 debug(F100,"ttvt SVORPOSIX flow XON/XOFF","",0);
6951 } else if (flow == FLO_NONE) { /* NONE */
6952 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff */
6953 tthflow(flow, 0, &tttvt); /* Turn off hardware f/c */
6954 debug(F100,"ttvt SVORPOSIX flow NONE","",0);
6955 } else if (flow == FLO_KEEP) {
6956 tttvt.c_iflag &= ~(IXON|IXOFF); /* Turn off Xon/Xoff flags */
6957 tttvt.c_iflag |= (ttold.c_iflag & (IXON|IXOFF)); /* OR in old ones */
6958 #ifdef POSIX_CRTSCTS
6959 tttvt.c_cflag &= ~CRTSCTS; /* Turn off RTS/CTS flag */
6960 tttvt.c_cflag |= (ttold.c_cflag & CRTSCTS); /* OR in old one */
6961 #endif /* POSIX_CRTSCTS */
6962 debug(F100,"ttvt SVORPOSIX flow KEEP","",0);
6963 } else if (flow == FLO_RTSC || /* Hardware flow control */
6966 tttvt.c_iflag &= ~(IXON|IXOFF); /* (196) */
6967 tthflow(flow, 1, &tttvt);
6968 debug(F100,"ttvt SVORPOSIX flow HARD","",0);
6972 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
6974 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
6975 #endif /* COHERENT */
6977 /* Needed for hwfc */
6978 if (flow == FLO_RTSC || flow == FLO_DTRC || flow == FLO_DTRT)
6979 tttvt.c_lflag |= IEXTEN;
6982 tttvt.c_lflag &= ~(ISIG|ICANON|ECHO);
6983 tttvt.c_cc[VDISCARD] = tttvt.c_cc[VLNEXT] = CDISABLE;
6986 tttvt.c_iflag |= (IGNBRK|IGNPAR);
6992 if (stopbits == 2) {
6993 tttvt.c_cflag |= CSTOPB; /* 2 stop bits */
6994 debug(F100,"ttvt 2 stopbits","",0);
6995 } else if (stopbits == 1) {
6996 tttvt.c_cflag &= ~(CSTOPB); /* 1 stop bit */
6997 debug(F100,"ttvt 1 stopbit","",0);
7005 if (hwparity && xlocal) { /* Hardware parity */
7007 /* Uncomment this only if needed -- I don't think it is */
7008 ttraw.c_cflag &= ~(CSIZE); /* Clear out character-size mask */
7009 ttraw.c_cflag |= CS8; /* And set it to 8 */
7010 #endif /* COMMENT */
7012 debug(F101,"ttvt hwparity IGNPAR","",IGNPAR);
7013 tttvt.c_iflag |= IGNPAR; /* Don't discard incoming bytes */
7015 tttvt.c_cflag |= PARENB; /* Enable parity */
7018 case 'e': /* Even */
7019 tttvt.c_cflag &= ~(PARODD);
7020 debug(F100,"ttvt 8 bits + even parity","",0);
7023 tttvt.c_cflag |= PARODD;
7024 debug(F100,"ttvt 8 bits + odd parity","",0);
7026 case 'm': /* Mark */
7027 case 's': /* Space */
7028 /* PAREXT is mentioned in SVID but the details are not given. */
7029 /* PAREXT is not included in POSIX ISO/IEC 9945-1. */
7030 debug(F100,"ttvt 8 bits + invalid parity","",0);
7033 } else { /* We handle parity ourselves */
7034 #endif /* HWPARITY */
7035 tttvt.c_cflag &= ~(PARENB); /* Don't enable parity */
7038 #endif /* HWPARITY */
7042 /* Things not to do... */
7043 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP|IXANY);
7045 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|IUCLC|INPCK|ISTRIP|IXANY);
7048 tttvt.c_iflag &= ~(INLCR|IGNCR|ICRNL|INPCK|ISTRIP);
7050 tttvt.c_cflag &= ~(CSIZE); /* Zero out the char size field */
7051 tttvt.c_cflag |= (CS8|CREAD|HUPCL); /* Char size 8, enable receiver, hup */
7052 tttvt.c_oflag &= ~OPOST; /* Don't postprocess output */
7053 #ifndef VEOF /* DGUX termio has VEOF at entry 4, see comment above */
7058 tttvt.c_cc[VMIN] = 1;
7064 #ifndef VEOL /* DGUX termio has VEOL at entry 5, see comment above */
7069 tttvt.c_cc[VTIME] = 0;
7077 if (p9ttyparity('n') < 0)
7083 tttvt.c_cc[VMIN] = 0; /* DR7 can only poll. */
7084 #endif /* BEOSORBEBOX */
7086 x = tcsetattr(ttyfd,TCSADRAIN,&tttvt);
7087 debug(F101,"ttvt BSD44ORPOSIX tcsetattr","",x);
7089 debug(F101,"ttvt BSD44ORPOSIX tcsetattr errno","",errno);
7093 x = ioctl(ttyfd,TCSETAW,&tttvt);
7094 debug(F101,"ttvt ATTSV ioctl TCSETAW","",x);
7095 if (x < 0) { /* set new modes . */
7096 debug(F101,"ttvt ATTSV ioctl TCSETAW errno","",errno);
7099 #endif /* BSD44ORPOSIX */
7103 ttspeed = speed; /* Done, remember how we were */
7104 ttflow = flow; /* called, so we can decide how to */
7105 tvtflg = 1; /* respond next time. */
7106 debug(F100,"ttvt ok","",0);
7111 #endif /* COHERENT */
7113 #endif /* NOLOCAL */
7118 /* Serial speed department . . . */
7121 SCO OSR5.0.x might or might not support high speeds. Sometimes they are not
7122 defined in the header files but they are supported (e.g. when building with
7123 UDK compiler rather than /bin/cc), sometimes vice versa. Even though 5.0.4
7124 was the first release that came with high serial speeds standard, releases
7125 back to 5.0.0 could use them if certain patches (or "supplements") were
7126 applied to the SIO driver. Plus a lot of SCO installations run third-party
7131 #define B38400 0000017
7134 #define B57600 0000021
7137 #define B76800 0000022
7140 #define B115200 0000023
7141 #endif /* B115200 */
7143 #define B230400 0000024
7144 #endif /* B230400 */
7146 #define B460800 0000025
7147 #endif /* B460800 */
7149 #define B921600 0000026
7150 #endif /* B921600 */
7151 #endif /* CK_SCOV5 */
7153 Plan 9's native speed setting interface lets you set anything you like,
7154 but will fail if the hardware doesn't like it, so we allow all the common
7192 #define B14400 14400
7195 #define B19200 19200
7198 #define B28800 28800
7201 #define B38400 38400
7204 #define B57600 57600
7207 #define B76800 76800
7210 #define B115200 115200
7211 #endif /* B115200 */
7213 #define B230400 230400
7214 #endif /* B230400 */
7216 #define B460800 460800
7217 #endif /* B460800 */
7219 #define B921600 921600
7220 #endif /* B921600 */
7223 /* T T S S P D -- Checks and sets transmission rate. */
7225 /* Call with speed in characters (not bits!) per second. */
7226 /* Returns -1 on failure, 0 if it did nothing, 1 if it changed the speed. */
7228 #ifdef USETCSETSPEED
7230 The tcsetspeed() / tcgetspeed() interface lets you pass any number at all
7231 to be used as a speed to be set, rather than forcing a choice from a
7232 predefined list. It seems to be peculiar to UnixWare 7.
7234 These are the function codes to be passed to tc[gs]etspeed(),
7235 but for some reason they don't seem to be picked up from termios.h.
7239 #endif /* TCS_ALL */
7245 #endif /* TCS_OUT */
7246 #endif /* USETCSETSPEED */
7249 ttsspd(cps) int cps; {
7252 /* Watch out, speed_t should be unsigned, so don't compare with -1, etc... */
7258 int ok = 1; /* Speed check result, assume ok */
7260 #ifdef OLINUXHISPEED
7261 unsigned int spd_flags = 0;
7262 struct serial_struct serinfo;
7263 #endif /* OLINUXHISPEED */
7265 debug(F101,"ttsspd cps","",cps);
7266 debug(F101,"ttsspd ttyfd","",ttyfd);
7267 debug(F101,"ttsspd xlocal","",xlocal);
7269 if (ttyfd < 0 || xlocal == 0) /* Don't set speed on console */
7276 return(tnc_set_baud(cps * 10));
7278 #endif /* TN_COMPORT */
7281 #endif /* NETCONN */
7283 if (ttpipe) return(0);
7286 if (ttpty) return(0);
7289 if (cps < 0) return(-1);
7290 s = s2 = 0; /* NB: s and s2 might be unsigned */
7292 #ifdef USETCSETSPEED
7296 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7297 debug(F101,"ttsspd tcgetattr","",x);
7300 debug(F101,"ttsspd TCSETSPEED speed","",s);
7303 if (s == 8880L) { /* 75/1200 split speed requested */
7304 tcsetspeed(TCS_IN, &ttcur, 1200L);
7305 tcsetspeed(TCS_OUT, &ttcur, 75L);
7307 tcsetspeed(TCS_ALL, &ttcur, s); /* Put new speed in structs */
7309 if (errno & deblog) {
7310 debug(F101,"ttsspd TCSETSPEED errno","",errno);
7315 tcsetspeed(TCS_ALL, &ttraw, s);
7316 tcsetspeed(TCS_ALL, &tttvt, s);
7317 tcsetspeed(TCS_ALL, &ttold, s);
7319 if (s == 8880L) { /* 75/1200 split speed requested */
7320 tcsetspeed(TCS_IN, &ttraw, 1200L);
7321 tcsetspeed(TCS_OUT, &ttraw, 75L);
7322 tcsetspeed(TCS_IN, &tttvt, 1200L);
7323 tcsetspeed(TCS_OUT, &tttvt, 75L);
7324 tcsetspeed(TCS_IN, &ttold, 1200L);
7325 tcsetspeed(TCS_OUT, &ttold, 75L);
7327 tcsetspeed(TCS_ALL, &ttraw, s);
7328 tcsetspeed(TCS_ALL, &tttvt, s);
7329 tcsetspeed(TCS_ALL, &ttold, s);
7331 #endif /* COMMENT */
7333 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur); /* Set the speed */
7334 debug(F101,"ttsspd tcsetattr","",x);
7338 #else /* Not USETCSETSPEED */
7340 #ifdef MINIX2 /* Hack alert */
7341 #define MINIX /* Use pre-2.0 speed selection for Minix 2.0 as well */
7344 /* First check that the given speed is valid. */
7348 case 0: s = B0; break;
7349 case 5: s = B50; break;
7350 case 7: s = B75; break;
7352 case 11: s = B110; break;
7354 case 13: s = B134; break;
7355 case 15: s = B150; break;
7356 case 20: s = B200; break;
7358 case 30: s = B300; break;
7360 case 60: s = B600; break;
7362 case 120: s = B1200; break;
7364 case 180: s = B1800; break;
7366 case 240: s = B2400; break;
7367 case 480: s = B4800; break;
7369 case 888: s = B75; s2 = B1200; break; /* 888 = 75/1200 split speed */
7372 case 720: s = B7200; break;
7374 case 960: s = B9600; break;
7376 case 1440: s = B14400; break;
7379 case 1920: s = B19200; break;
7382 case 1920: s = EXTA; break;
7386 case 2880: s = B28800; break;
7389 case 3840: s = B38400;
7390 #ifdef OLINUXHISPEED
7391 spd_flags = ~ASYNC_SPD_MASK; /* Nonzero, but zero flags */
7392 #endif /* OLINUXHISPEED */
7394 #else /* B38400 not defined... */
7396 case 3840: s = EXTB; break;
7402 case 5760: s = _B57600; break;
7403 #endif /* _B57600 */
7405 case 11520: s = _B115200; break;
7406 #endif /* _B115200 */
7408 #ifdef OLINUXHISPEED
7410 This bit from <carlo@sg.tn.tudelft.nl>:
7411 "Only note to make is maybe this: When the ASYNC_SPD_CUST flags are set then
7412 setting the speed to 38400 will set the custom speed (and ttgspd returns
7413 38400), but speeds 57600 and 115200 won't work any more because I didn't
7414 want to mess up the speed flags when someone is doing sophisticated stuff
7415 like custom speeds..."
7417 case 5760: s = B38400; spd_flags = ASYNC_SPD_HI; break;
7418 case 11520: s = B38400; spd_flags = ASYNC_SPD_VHI; break;
7421 case 5760: s = B57600; break;
7424 case 7680: s = B76800; break;
7427 case 11520: s = B115200; break;
7428 #endif /* B115200 */
7429 #endif /* OLINUXHISPEED */
7431 case 15360: s = B153600; break;
7432 #endif /* B153600 */
7434 case 23040: s = B230400; break;
7435 #endif /* B230400 */
7437 case 30720: s = B307200; break;
7438 #endif /* B307200 */
7440 case 46080: s = B460800; break;
7443 case 92160: s = B921600; break;
7444 #endif /* B921600 */
7447 ok = 0; /* Good speed not found, so not ok */
7450 debug(F101,"ttsspd ok","",ok);
7451 debug(F101,"ttsspd s","",s);
7454 debug(F100,"ttsspd fails","",0);
7457 if (!s2) s2 = s; /* Set input speed */
7459 if (p9ttsspd(cps) < 0)
7463 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7464 debug(F101,"ttsspd tcgetattr","",x);
7467 #ifdef OLINUXHISPEED
7468 debug(F101,"ttsspd spd_flags","",spd_flags);
7469 if (spd_flags && spd_flags != ASYNC_SPD_CUST) {
7470 if (ioctl(ttyfd, TIOCGSERIAL, &serinfo) < 0) {
7471 debug(F100,"ttsspd: TIOCGSERIAL failed","",0);
7473 } else debug(F100,"ttsspd: TIOCGSERIAL ok","",0);
7474 serinfo.flags &= ~ASYNC_SPD_MASK;
7475 serinfo.flags |= (spd_flags & ASYNC_SPD_MASK);
7476 if (ioctl(ttyfd, TIOCSSERIAL, &serinfo) < 0)
7479 #endif /* OLINUXHISPEED */
7480 cfsetospeed(&ttcur,s);
7481 cfsetispeed(&ttcur,s2);
7482 cfsetospeed(&ttraw,s);
7483 cfsetispeed(&ttraw,s2);
7484 cfsetospeed(&tttvt,s);
7485 cfsetispeed(&tttvt,s2);
7486 cfsetospeed(&ttold,s);
7487 cfsetispeed(&ttold,s2);
7488 x = tcsetattr(ttyfd,TCSADRAIN,&ttcur);
7489 debug(F101,"ttsspd tcsetattr","",x);
7490 if (x < 0) return(-1);
7493 if (cps == 888) return(-1); /* No split speeds, sorry. */
7494 x = ioctl(ttyfd,TCGETA,&ttcur);
7495 debug(F101,"ttsspd TCGETA ioctl","",x);
7496 if (x < 0) return(-1);
7497 ttcur.c_cflag &= ~CBAUD;
7499 tttvt.c_cflag &= ~CBAUD;
7501 ttraw.c_cflag &= ~CBAUD;
7503 ttold.c_cflag &= ~CBAUD;
7505 x = ioctl(ttyfd,TCSETAW,&ttcur);
7506 debug(F101,"ttsspd TCSETAW ioctl","",x);
7507 if (x < 0) return(-1);
7510 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
7511 debug(F101,"ttsspd TIOCGDEV ioctl","",x);
7512 if (x < 0) return(-1);
7516 ok = ioctl(ttyfd,TIOCSDEV,&tdcur);
7517 debug(F101,"ttsspd BELLV10 ioctl","",ok);
7520 debug(F101,"ttsspd BELLV10 errno","",ok);
7524 x = gtty(ttyfd,&ttcur);
7525 debug(F101,"ttsspd gtty","",x);
7526 if (x < 0) return(-1);
7527 ttcur.sg_ospeed = s; ttcur.sg_ispeed = s2;
7528 tttvt.sg_ospeed = s; tttvt.sg_ispeed = s2;
7529 ttraw.sg_ospeed = s; ttraw.sg_ispeed = s2;
7530 ttold.sg_ospeed = s; ttold.sg_ispeed = s2;
7531 x = stty(ttyfd,&ttcur);
7532 debug(F101,"ttsspd stty","",x);
7533 if (x < 0) return(-1);
7534 #endif /* BELLV10 */
7536 #endif /* BSD44ORPOSIX */
7539 return(1); /* Return 1 = success. */
7540 #endif /* USETCSETSPEED */
7543 #endif /* NOLOCAL */
7545 /* C O N G S P D - Get speed of console terminal */
7550 This is a disgusting hack. The right way to do this would be to pass an
7551 argument to ttgspd(), but then we'd need to change the Kermit API and
7552 all of the ck?tio.c modules. (Currently used only for rlogin.)
7559 #endif /* NETCONN */
7563 debug(F101,"congspd","",spd);
7566 #endif /* NETCONN */
7571 /* T T S P D L I S T -- Get list of serial speeds allowed on this platform */
7574 static long spdlist[NSPDLIST];
7576 As written, this picks up the speeds known at compile time, and thus
7577 apply to the system where C-Kermit was built, rather than to the one where
7578 it is running. Suggestions for improvement are always welcome.
7583 for (i = 0; i < NSPDLIST; i++) /* Initialize the list */
7587 #ifdef USETCSETSPEED /* No way to find out what's legal */
7588 debug(F100,"ttspdlist USETCSETSPEED","",0);
7593 spdlist[i++] = 110L;
7595 spdlist[i++] = 134L;
7597 spdlist[i++] = 150L;
7598 spdlist[i++] = 200L;
7599 spdlist[i++] = 300L;
7600 spdlist[i++] = 600L;
7601 spdlist[i++] = 1200L;
7602 spdlist[i++] = 1800L;
7603 spdlist[i++] = 2400L;
7604 spdlist[i++] = 4800L;
7605 spdlist[i++] = 8880L;
7606 spdlist[i++] = 9600L;
7607 spdlist[i++] = 14400L;
7608 spdlist[i++] = 19200L;
7609 spdlist[i++] = 28800L;
7611 spdlist[i++] = 33600L;
7613 spdlist[i++] = 38400L;
7614 spdlist[i++] = 57600L;
7615 spdlist[i++] = 76800L;
7616 spdlist[i++] = 115200L;
7618 spdlist[i++] = 153600L;
7619 spdlist[i++] = 230400L;
7620 spdlist[i++] = 307200L;
7621 spdlist[i++] = 460800L;
7622 spdlist[i++] = 921600L;
7625 #else /* USETCSETSPEED */
7627 debug(F100,"ttspdlist no USETCSETSPEED","",0);
7630 debug(F101,"ttspdlist B50","",B50);
7634 debug(F101,"ttspdlist B75","",B75);
7638 debug(F101,"ttspdlist B110","",B110);
7639 spdlist[i++] = 110L;
7642 debug(F101,"ttspdlist B134","",B134);
7643 spdlist[i++] = 134L;
7646 debug(F101,"ttspdlist B150","",B150);
7647 spdlist[i++] = 150L;
7650 debug(F101,"ttspdlist B200","",B200);
7651 spdlist[i++] = 200L;
7654 debug(F101,"ttspdlist B300","",B300);
7655 spdlist[i++] = 300L;
7658 debug(F101,"ttspdlist B600","",B600);
7659 spdlist[i++] = 600L;
7662 debug(F101,"ttspdlist B1200","",B1200);
7663 spdlist[i++] = 1200L;
7666 debug(F101,"ttspdlist B1800","",B1800);
7667 spdlist[i++] = 1800L;
7670 debug(F101,"ttspdlist B2400","",B2400);
7671 spdlist[i++] = 2400L;
7674 debug(F101,"ttspdlist B4800","",B4800);
7675 spdlist[i++] = 4800L;
7678 debug(F101,"ttspdlist B9600","",B9600);
7679 spdlist[i++] = 9600L;
7682 debug(F101,"ttspdlist B14400","",B14400);
7683 spdlist[i++] = 14400L;
7686 debug(F101,"ttspdlist B19200","",B19200);
7687 spdlist[i++] = 19200L;
7690 debug(F101,"ttspdlist EXTA","",EXTA);
7691 spdlist[i++] = 19200L;
7695 debug(F101,"ttspdlist B28800","",B28800);
7696 spdlist[i++] = 28800L;
7699 debug(F101,"ttspdlist B33600","",B33600);
7700 spdlist[i++] = 33600L;
7703 debug(F101,"ttspdlist B38400","",B38400);
7704 spdlist[i++] = 38400L;
7707 debug(F101,"ttspdlist EXTB","",EXTB);
7708 spdlist[i++] = 38400L;
7712 debug(F101,"ttspdlist _B57600","",_B57600);
7713 spdlist[i++] = 57600L;
7716 debug(F101,"ttspdlist B57600","",B57600);
7717 spdlist[i++] = 57600L;
7719 #endif /* _B57600 */
7721 debug(F101,"ttspdlist B76800","",B76800);
7722 spdlist[i++] = 76800L;
7725 debug(F101,"ttspdlist _B115200","",_B115200);
7726 spdlist[i++] = 115200L;
7729 debug(F101,"ttspdlist B115200","",B115200);
7730 spdlist[i++] = 115200L;
7731 #endif /* B115200 */
7732 #endif /* _B115200 */
7734 debug(F101,"ttspdlist B153600","",B153600);
7735 spdlist[i++] = 153600L;
7736 #endif /* B153600 */
7738 debug(F101,"ttspdlist B230400","",B230400);
7739 spdlist[i++] = 230400L;
7740 #endif /* B230400 */
7742 debug(F101,"ttspdlist B307200","",B307200);
7743 spdlist[i++] = 307200L;
7744 #endif /* B307200 */
7746 debug(F101,"ttspdlist B460800","",B460800);
7747 spdlist[i++] = 460800L;
7748 #endif /* B460800 */
7750 debug(F101,"ttspdlist B921600","",B921600);
7751 spdlist[i++] = 921600L;
7752 #endif /* B921600 */
7753 #endif /* USETCSETSPEED */
7754 spdlist[0] = i - 1; /* Return count in 0th element */
7755 debug(F111,"ttspdlist spdlist","0",spdlist[0]);
7756 return((long *)spdlist);
7759 /* T T G S P D - Get speed of currently selected tty line */
7762 Unreliable. After SET LINE, it returns an actual speed, but not necessarily
7763 the real speed. On some systems, it returns the line's nominal speed, from
7764 /etc/ttytab. Even if you SET SPEED to something else, this function might
7768 ttgspd() { /* Get current serial device speed */
7773 speed_t /* Should be unsigned */
7775 int /* Isn't unsigned */
7780 #ifdef OLINUXHISPEED
7781 unsigned int spd_flags = 0;
7782 struct serial_struct serinfo;
7783 #endif /* OLINUXHISPEED */
7789 return(tnc_get_baud());
7791 #endif /* TN_COMPORT */
7792 return(-1); /* -1 if network connection */
7794 #endif /* NETCONN */
7796 if (ttpipe) return(-1);
7799 if (ttpty) return(-1);
7802 debug(F101,"ttgspd ttyfd","",ttyfd);
7804 #ifdef USETCSETSPEED
7806 x = tcgetattr(ttyfd,&ttcur); /* Get current speed */
7807 debug(F101,"ttgspd tcgetattr","",x);
7811 s = tcgetspeed(TCS_ALL, &ttcur);
7812 debug(F101,"ttsspd TCGETSPEED speed","",s);
7815 s1 = tcgetspeed(TCS_IN, &ttcur);
7816 s2 = tcgetspeed(TCS_OUT, &ttcur);
7817 if (s1 == 1200L && s2 == 75L)
7821 if (errno & deblog) {
7822 debug(F101,"ttsspd TCGETSPEED errno","",errno);
7827 #else /* Not USETCSETSPEED */
7835 #ifdef OLINUXHISPEED
7836 debug(F100,"ttgspd Linux OLINUXHISPEED","",0);
7837 #endif /* OLINUXHISPEED */
7841 s = cfgetospeed(&ccold);
7842 debug(F101,"ttgspd cfgetospeed 1 POSIX","",s);
7845 s = ccold.c_cflag & CBAUD;
7846 debug(F101,"ttgspd c_cflag CBAUD 1 ATTSV","",s);
7848 s = ccold.sg_ospeed; /* (obtained by congm()) */
7849 debug(F101,"ttgspd sg_ospeed 1","",s);
7851 #endif /* BSD44POSIX */
7855 if (tcgetattr(ttyfd,&ttcur) < 0) return(-1);
7856 s = cfgetospeed(&ttcur);
7857 debug(F101,"ttgspd cfgetospeed 2 BSDORPOSIX","",s);
7858 #ifdef OLINUXHISPEED
7859 if (ioctl(ttyfd,TIOCGSERIAL,&serinfo) > -1)
7860 spd_flags = serinfo.flags & ASYNC_SPD_MASK;
7861 debug(F101,"ttgspd spd_flags","",spd_flags);
7862 #endif /* OLINUXHISPEED */
7865 x = ioctl(ttyfd,TCGETA,&ttcur);
7866 debug(F101,"ttgspd ioctl 2 ATTSV x","",x);
7867 debug(F101,"ttgspd ioctl 2 ATTSV errno","",errno);
7868 if (x < 0) return(-1);
7869 s = ttcur.c_cflag & CBAUD;
7870 debug(F101,"ttgspd ioctl 2 ATTSV speed","",s);
7873 x = ioctl(ttyfd,TIOCGDEV,&tdcur);
7874 debug(F101,"ttgspd ioctl 2 BELLV10 x","",x);
7875 if (x < 0) return(-1);
7877 debug(F101,"ttgspd ioctl 2 BELLV10 speed","",s);
7879 x = gtty(ttyfd,&ttcur);
7880 debug(F101,"ttgspd gtty 2 x","",x);
7881 debug(F101,"ttgspd gtty 2 errno","",errno);
7882 if (x < 0) return(-1);
7883 s = ttcur.sg_ospeed;
7884 debug(F101,"ttgspd gtty 2 speed","",s);
7885 #endif /* BELLV10 */
7887 #endif /* BSD44ORPOSIX */
7889 debug(F101,"ttgspd code","",s);
7890 #ifdef OLINUXHISPEED
7891 debug(F101,"ttgspd spd_flags","",spd_flags);
7892 #endif /* OLINUXHISPEED */
7895 case B0: ss = 0L; break;
7900 MINIX defines the Bxx symbols to be bps/100, so B50==B75, B110==B134==B150,
7901 etc, making for many "duplicate case in switch" errors, which are fatal.
7904 case B50: ss = 50L; break;
7907 case B75: ss = 75L; break;
7912 case B110: ss = 110L; break;
7917 case B134: ss = 134L; break;
7920 case B150: ss = 150L; break;
7925 case B200: ss = 200L; break;
7929 case B300: ss = 300L; break;
7933 case B600: ss = 600L; break;
7937 case B1200: ss = 1200L; break;
7941 case B1800: ss = 1800L; break;
7945 case B2400: ss = 2400L; break;
7949 case B4800: ss = 4800L; break;
7953 case B7200: ss = 7200L; break;
7957 case B9600: ss = 9600L; break;
7961 case B19200: ss = 19200L; break;
7964 case EXTA: ss = 19200L; break;
7969 /* End of hack to make MINIX2 use MINIX1 speed setting */
7977 #ifdef OLINUXHISPEED
7979 case ASYNC_SPD_HI: ss = 57600L; break;
7980 case ASYNC_SPD_VHI: ss = 115200L; break;
7982 #endif /* OLINUXHISPEED */
7986 case EXTB: ss = 38400L; break;
7993 case _B57600: ss = 57600L; break;
7994 #endif /* _B57600 */
7996 case _B115200: ss = 115200L; break;
7997 #endif /* _B115200 */
8000 case B57600: ss = 57600L; break;
8003 case B76800: ss = 76800L; break;
8006 case B115200: ss = 115200L; break;
8007 #endif /* B115200 */
8009 case B153600: ss = 153600L; break;
8010 #endif /* B153600 */
8012 case B230400: ss = 230400L; break;
8013 #endif /* B230400 */
8015 case B307200: ss = 307200L; break;
8016 #endif /* B307200 */
8018 case B460800: ss = 460800L; break;
8019 #endif /* B460800 */
8022 case 92160: ss = 921600L; break;
8023 #endif /* B921600 */
8028 debug(F101,"ttgspd speed","",ss);
8031 #endif /* USETCSETSPEED */
8032 #endif /* NOLOCAL */
8034 #ifdef MINIX2 /* Another hack alert */
8039 FIONREAD data type... This has been defined as "long" for many, many
8040 years, and it worked OK until 64-bit platforms appeared. Thus we use
8041 int for 64-bit platforms, but keep long for the others. If we changed
8042 the default PEEKTYPE to int, this would probably break 16-bit builds
8043 (note that sizeof(long) == sizeof(int) on most 32-bit platforms), many
8044 of which we have no way of testing any more. Therefore, do not change
8045 the default definition of PEEKTYPE -- only add exceptions to it as needed.
8050 #endif /* FIONREAD */
8051 /* #define FIONREAD TIOCQUERY */
8052 /* #define PEEKTYPE int */
8053 #else /* Not COHERENT... */
8055 #ifdef OSF32 /* Digital UNIX 3.2 or higher */
8056 #define PEEKTYPE int
8058 #define PEEKTYPE long /* Elsewhere (see notes above) */
8060 #endif /* COHERENT */
8062 /* ckumyr.c by Kristoffer Eriksson, ske@pkmab.se, 15 Mar 1990. */
8066 /* Private buffer for myread() and its companions. Not for use by anything
8067 * else. ttflui() is allowed to reset them to initial values. ttchk() is
8068 * allowed to read my_count.
8070 * my_item is an index into mybuf[]. Increment it *before* reading mybuf[].
8072 * A global parity mask variable could be useful too. We could use it to
8073 * let myread() strip the parity on its own, instead of stripping sign
8074 * bits as it does now.
8077 #define MYBUFLEN 32768
8080 #define MYBUFLEN 256
8082 #define MYBUFLEN 1024
8084 #endif /* BIGBUFOK */
8088 #define MYBUFLEN 256
8090 On X.25 connections, there is an extra control byte at the beginning.
8092 static CHAR x25buf[MYBUFLEN+1]; /* Communication device input buffer */
8093 static CHAR *mybuf = x25buf+1;
8095 static CHAR mybuf[MYBUFLEN];
8098 static int my_count = 0; /* Number of chars still in mybuf */
8099 static int my_item = -1; /* Last index read from mybuf[] */
8101 /* T T P E E K -- Peek into our internal communications input buffers. */
8104 NOTE: This routine is peculiar to UNIX, and is used only by the
8105 select()-based CONNECT module, ckucns.c. It need not be replicated in
8106 the ck?tio.c of other platforms.
8118 #endif /* TTLEBUF */
8127 /* myread() -- Efficient read of one character from communications line.
8129 * Uses a private buffer to minimize the number of expensive read() system
8130 * calls. Essentially performs the equivalent of read() of 1 character, which
8131 * is then returned. By reading all available input from the system buffers
8132 * to the private buffer in one chunk, and then working from this buffer, the
8133 * number of system calls is reduced in any case where more than one character
8134 * arrives during the processing of the previous chunk, for instance high
8135 * baud rates or network type connections where input arrives in packets.
8136 * If the time needed for a read() system call approaches the time for more
8137 * than one character to arrive, then this mechanism automatically compensates
8138 * for that by performing bigger read()s less frequently. If the system load
8139 * is high, the same mechanism compensates for that too.
8141 * myread() is a macro that returns the next character from the buffer. If the
8142 * buffer is empty, mygetbuf() is called. See mygetbuf() for possible error
8145 * This should be efficient enough for any one-character-at-a-time loops.
8146 * For even better efficiency you might use memcpy()/bcopy() or such between
8147 * buffers (since they are often better optimized for copying), but it may not
8148 * be worth it if you have to take an extra pass over the buffer to strip
8149 * parity and check for CTRL-C anyway.
8151 * Note that if you have been using myread() from another program module, you
8152 * may have some trouble accessing this macro version and the private variables
8153 * it uses. In that case, just add a function in this module, that invokes the
8156 #define myread() (--my_count < 0 ? mygetbuf() : 255 & (int)mybuf[++my_item])
8158 /* Specification: Push back up to one character onto myread()'s queue.
8160 * This implementation: Push back characters into mybuf. At least one character
8161 * must have been read through myread() before myunrd() may be used. After
8162 * EOF or read error, again, myunrd() can not be used. Sometimes more than
8163 * one character can be pushed back, but only one character is guaranteed.
8164 * Since a previous myread() must have read its character out of mybuf[],
8165 * that guarantees that there is space for at least one character. If push
8166 * back was really needed after EOF, a small addition could provide that.
8168 * myunrd() is currently not called from anywhere inside kermit...
8170 #ifdef COMMENT /* not used */
8171 myunrd(ch) CHAR ch; {
8173 mybuf[my_item--] = ch;
8177 #endif /* COMMENT */
8179 /* T T P U S H B A C K -- Put n bytes back into the myread buffer */
8181 static CHAR * pushbuf = NULL;
8182 /* static int pushed = 0; */
8185 ttpushback(s,n) CHAR * s; int n; {
8186 debug(F101,"ttpushback n","",n);
8187 if (pushbuf || n > MYBUFLEN || n < 1)
8189 debug(F101,"ttpushback my_count","",my_count);
8191 if (!(pushbuf = (CHAR *)malloc(n+1)))
8193 memcpy(pushbuf,mybuf,my_count);
8194 /* pushed = my_count; */ /* (set but never used) */
8202 /* mygetbuf() -- Fill buffer for myread() and return first character.
8204 * This function is what myread() uses when it can't get the next character
8205 * directly from its buffer. First, it calls a system dependent myfillbuf()
8206 * to read at least one new character into the buffer, and then it returns
8207 * the first character just as myread() would have done. This function also
8208 * is responsible for all error conditions that myread() can indicate.
8210 * Returns: When OK => a positive character, 0 or greater.
8212 * When error => -3, error code in errno.
8214 * Older myread()s additionally returned -1 to indicate that there was nothing
8215 * to read, upon which the caller would call myread() again until it got
8216 * something. The new myread()/mygetbuf() always gets something. If it
8217 * doesn't, then make it do so! Any program that actually depends on the old
8218 * behaviour will break.
8220 * The older version also used to return -2 both for EOF and other errors,
8221 * and used to set errno to 9999 on EOF. The errno stuff is gone, EOF and
8222 * other errors now return different results, although Kermit currently never
8223 * checks to see which it was. It just disconnects in both cases.
8225 * Kermit lets the user use the quit key to perform some special commands
8226 * during file transfer. This causes read(), and thus also mygetbuf(), to
8227 * finish without reading anything and return the EINTR error. This should
8228 * be checked by the caller. Mygetbuf() could retry the read() on EINTR,
8229 * but if there is nothing to read, this could delay Kermit's reaction to
8230 * the command, and make Kermit appear unresponsive.
8232 * The debug() call should be removed for optimum performance.
8239 if (deblog && my_count > 0)
8240 debug(F101,"mygetbuf IMPROPERLY CALLED with my_count","",my_count);
8243 my_count = myfillbuf();
8247 if (deblog) debug(F101, "mygetbuf read", "", my_count);
8249 if (deblog) hexdump("mygetbuf read", mybuf, my_count);
8250 #endif /* COMMENT */
8253 if (my_count <= 0) {
8256 debug(F101,"mygetbuf errno","",errno);
8258 if (netconn && ttnet == NET_TCPB && errno != 0) {
8259 if (errno != EINTR) {
8260 debug(F101,"mygetbuf TCP error","",errno);
8261 ttclos(0); /* Close the connection. */
8265 #endif /* TCPSOCKET */
8266 if (!netconn && xlocal && errno) {
8267 if (errno != EINTR) {
8268 debug(F101,"mygetbuf SERIAL error","",errno);
8270 ttclos(0); /* Close the connection. */
8273 return((x < 0) ? -3 : -2);
8276 return((unsigned)(0xff & mybuf[my_item = 0]));
8280 * System-dependent read() into mybuf[], as many characters as possible.
8282 * Returns: OK => number of characters read, always more than zero.
8284 * Error => -1, error code in errno.
8286 * If there is input available in the system's buffers, all of it should be
8287 * read into mybuf[] and the function return immediately. If no input is
8288 * available, it should wait for a character to arrive, and return with that
8289 * one in mybuf[] as soon as possible. It may wait somewhat past the first
8290 * character, but be aware that any such delay lengthens the packet turnaround
8291 * time during kermit file transfers. Should never return with zero characters
8292 * unless EOF or irrecoverable read error.
8294 * Correct functioning depends on the correct tty parameters being used.
8295 * Better control of current parameters is required than may have been the
8296 * case in older Kermit releases. For instance, O_NDELAY (or equivalent) can
8297 * no longer be sometimes off and sometimes on like it used to, unless a
8298 * special myfillbuf() is written to handle that. Otherwise the ordinary
8299 * myfillbuf()s may think they have come to EOF.
8301 * If your system has a facility to directly perform the functioning of
8302 * myfillbuf(), then use it. If the system can tell you how many characters
8303 * are available in its buffers, then read that amount (but not less than 1).
8304 * If the system can return a special indication when you try to read without
8305 * anything to read, while allowing you to read all there is when there is
8306 * something, you may loop until there is something to read, but probably that
8307 * is not good for the system load.
8311 /* This is for System III/V with VMIN>0, VTIME=0 and O_NDELAY off,
8312 * and CLOCAL set any way you like. This way, read() will do exactly
8313 * what is required by myfillbuf(): If there is data in the buffers
8314 * of the O.S., all available data is read into mybuf, up to the size
8315 * of mybuf. If there is none, the first character to arrive is
8316 * awaited and returned.
8329 /* From S. Dezawa at Fujifilm in Japan. I don't know why this is */
8330 /* necessary for the sxa E50, but it is. */
8331 return read(fd, mybuf, 255);
8337 n = netxin(sizeof(mybuf), (char *)mybuf);
8338 debug(F101,"BEBOX SVORPOSIX network myfillbuf","",n);
8341 #endif /* NETCONN */
8342 n = read(fd, mybuf, sizeof(mybuf));
8343 debug(F101,"BEBOX SVORPOSIX notnet myfillbuf","",n);
8348 #else /* BEOSORBEBOX */
8350 debug(F100,"SVORPOSIX myfillbuf calling read()","",0);
8352 if (netconn && (nettype == NET_IX25)) {
8353 /* can't use sizeof because mybuf is a pointer, and not an array! */
8354 n = x25xin( MYBUFLEN, mybuf );
8359 if (ssl_active_flag || tls_active_flag) {
8362 if (ssl_active_flag)
8363 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8364 else if (tls_active_flag)
8365 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8368 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8369 case SSL_ERROR_NONE:
8376 case SSL_ERROR_WANT_WRITE:
8377 case SSL_ERROR_WANT_READ:
8379 case SSL_ERROR_SYSCALL:
8382 case SSL_ERROR_WANT_X509_LOOKUP:
8384 case SSL_ERROR_ZERO_RETURN:
8395 if (ttnproto == NP_EK4LOGIN) {
8396 if ((n = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8401 #endif /* RLOGCODE */
8405 if (ttnproto == NP_EK5LOGIN) {
8406 if ((n = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8411 #endif /* RLOGCODE */
8413 if (ttnproto == NP_K5U2U) {
8414 if ((n = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8419 #endif /* KRB5_U2U */
8421 #endif /* CK_KERBEROS */
8425 /* Special handling for HP-UX pty i/o */
8427 if (ttpty && pty_trap_pending(ttyfd) > 0) {
8428 if (pty_trap_handler(ttyfd) > 0) {
8433 #endif /* HAVE_PTYTRAP */
8435 n = read(fd, mybuf, sizeof(mybuf));
8436 debug(F101,"SVORPOSIX myfillbuf","",n);
8437 debug(F101,"SVORPOSIX myfillbuf ttcarr","",ttcarr);
8438 debug(F101,"SVORPOSIX myfillbuf errno","",errno);
8442 /* When we have a PTY trap in place the connection cannot */
8443 /* be closed until the trap receives a close indication. */
8444 if (n == 0 && ttpty)
8446 #endif /* HAVE_PTYTRAP */
8451 #endif /* BEOSORBEBOX */
8455 #else /* not AT&T or POSIX */
8458 /* This is quoted from the old myread(). The semantics seem to be
8459 * alright, but maybe errno would not need to be set even when
8460 * there is no error? I don't know aegis.
8472 count = ios_$get((short)fd, ios_$cond_opt, mybuf, 256L, st);
8474 if (st.all == ios_$get_conditional_failed) /* get at least one */
8475 count = ios_$get((short)fd, 0, mybuf, 1L, st);
8476 if (st.all == ios_$end_of_file)
8478 else if (st.all != status_$ok) {
8482 return(count > 0 ? count : -3);
8487 /* This is for systems with FIONREAD. FIONREAD returns the number
8488 * of characters available for reading. If none are available, wait
8489 * until something arrives, otherwise return all there is.
8504 SunLink X.25 support in this routine from Stefaan A. Eeckels, Eurostat (CEC).
8505 Depends on SunOS having FIONREAD, not because we use it, but just so this
8506 code is grouped correctly within the #ifdefs. Let's hope Solaris keeps it.
8508 We call x25xin() instead of read() so that Q-Bit packets, which contain
8509 X.25 service-level information (e.g. PAD parameter changes), can be processed
8510 transparently to the upper-level code. This is a blocking read, and so
8511 we depend on higher-level code (such as ttinc()) to set any necessary alarms.
8514 if (netconn && nettype == NET_SX25) {
8515 while ((x = x25xin(sizeof(x25buf), x25buf)) < 1) ;
8516 return(x - 1); /* "-1" compensates for extra status byte */
8521 if (ssl_active_flag || tls_active_flag) {
8524 if (ssl_active_flag)
8525 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8527 n = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8528 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8529 case SSL_ERROR_NONE:
8536 case SSL_ERROR_WANT_WRITE:
8537 case SSL_ERROR_WANT_READ:
8539 case SSL_ERROR_SYSCALL:
8542 case SSL_ERROR_WANT_X509_LOOKUP:
8544 case SSL_ERROR_ZERO_RETURN:
8555 if (ttnproto == NP_EK4LOGIN) {
8556 if ((x = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8561 #endif /* RLOGCODE */
8565 if (ttnproto == NP_EK5LOGIN) {
8566 if ((x = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8571 #endif /* RLOGCODE */
8573 if (ttnproto == NP_K5U2U) {
8574 if ((x = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8579 #endif /* KRB5_U2U */
8581 #endif /* CK_KERBEROS */
8584 debug(F101,"myfillbuf calling FIONREAD ioctl","",xlocal);
8585 x = ioctl(fd, FIONREAD, &avail);
8588 debug(F101,"myfillbuf FIONREAD","",x);
8589 debug(F101,"myfillbuf FIONREAD avail","",avail);
8590 debug(F101,"myfillbuf FIONREAD errno","",errno);
8593 if (x < 0 || avail == 0)
8596 if (avail > MYBUFLEN)
8601 x = read(fd, mybuf, (int) avail);
8604 debug(F101,"myfillbuf avail","",avail);
8605 debug(F101,"myfillbuf read","",x);
8606 debug(F101,"myfillbuf read errno","",errno);
8608 hexdump("myfillbuf mybuf",mybuf,x);
8611 if (x < 1) x = -3; /* read 0 == connection loss */
8615 #else /* !FIONREAD */
8616 /* Add other systems here, between #ifdef and #else, e.g. NETCONN. */
8617 /* When there is no other possibility, read 1 character at a time. */
8623 if (ssl_active_flag || tls_active_flag) {
8626 if (ssl_active_flag)
8627 n = SSL_read(ssl_con, (char *)mybuf, sizeof(mybuf));
8629 count = SSL_read(tls_con, (char *)mybuf, sizeof(mybuf));
8630 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,n)) {
8631 case SSL_ERROR_NONE:
8638 case SSL_ERROR_WANT_WRITE:
8639 case SSL_ERROR_WANT_READ:
8641 case SSL_ERROR_SYSCALL:
8644 case SSL_ERROR_WANT_X509_LOOKUP:
8646 case SSL_ERROR_ZERO_RETURN:
8657 if (ttnproto == NP_EK4LOGIN) {
8658 if ((len = krb4_des_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8663 #endif /* RLOGCODE */
8667 if (ttnproto == NP_EK5LOGIN) {
8668 if ((len = krb5_des_read(ttyfd,mybuf,sizeof(mybuf),0)) < 0)
8673 #endif /* RLOGCODE */
8675 if (ttnproto == NP_K5U2U) {
8676 if ((len = krb5_u2u_read(ttyfd,mybuf,sizeof(mybuf))) < 0)
8681 #endif /* KRB5_U2U */
8683 #endif /* CK_KERBEROS */
8691 x = read(fd, mybuf, 1);
8692 return(x > 0 ? x : -3);
8695 #endif /* !FIONREAD */
8705 /* T T _ T N O P T -- Handle Telnet negotions in incoming data */
8707 Call with the IAC that was encountered.
8709 -3: If connection has dropped or gone bad.
8710 -2: On Telnet protocol error resulting in inconsistent states.
8711 0: If negotiation OK and caller has nothing to do.
8712 1: If packet start character has changed (new value is in global stchr).
8713 255: If there was a quoted IAC as data.
8714 or: Not at all if we got a legitimate Telnet Logout request.
8718 tt_tnopt(n) int n; { /* Handle Telnet options */
8719 /* In case caller did not already check these conditions... */
8721 ((xlocal && netconn && IS_TELNET()) ||
8722 (!xlocal && sstelnet))) {
8726 debug(F100,"ttinl calling tn_doop()","",0);
8727 tx = tn_doop((CHAR)(n & 0xff),duplex,ttinc);
8728 debug(F111,"ttinl tn_doop() returned","tx",tx);
8732 case -1: /* I/O error */
8733 ttimoff(); /* Turn off timer */
8735 case -2: /* Connection failed. */
8737 ttimoff(); /* Turn off timer */
8740 case 1: /* ECHO change */
8743 case 2: /* ECHO change */
8746 case 3: /* Quoted IAC */
8748 return((unsigned)255);
8751 if (TELOPT_SB(TELOPT_KERMIT).kermit.u_start && server
8755 ) { /* Remote in Server mode */
8756 ttimoff(); /* Turn off timer */
8757 debug(F100,"u_start and !inserver","",0);
8758 return(-2); /* End server mode */
8759 } else if (!TELOPT_SB(TELOPT_KERMIT).kermit.me_start &&
8761 ) { /* I'm no longer in Server Mode */
8762 debug(F100,"me_start and server","",0);
8768 case 5: { /* Start character change */
8769 /* extern CHAR stchr; */
8770 /* start = stchr; */
8773 #endif /* IKS_OPTION */
8774 case 6: /* Remote Logout */
8778 if (inserver && !local)
8779 doexit(GOOD_EXIT,0);
8789 #endif /* TCPSOCKET */
8791 /* T T F L U I -- Flush tty input buffer */
8794 ttflux() { /* But first... */
8797 Flush internal MYREAD buffer.
8801 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
8802 (!xlocal && sstelnet)));
8803 #endif /* TCPSOCKET */
8804 debug(F101,"ttflux my_count","",my_count);
8808 while (my_count > 0) {
8810 #ifdef CK_ENCRYPTION
8811 if (TELOPT_U(TELOPT_ENCRYPTION))
8812 ck_tn_decrypt(&ch,1);
8813 #endif /* CK_ENCRYPTION */
8818 #endif /* TCPSOCKET */
8820 #ifdef CK_ENCRYPTION
8821 if (TELOPT_U(TELOPT_ENCRYPTION) && my_count > 0)
8822 ck_tn_decrypt(&mybuf[my_item+1],my_count);
8823 #endif /* CK_ENCRYPTION */
8824 #endif /* COMMENT */
8825 my_count = 0; /* Reset count to zero */
8826 my_item = -1; /* And buffer index to -1 */
8835 dotnopts = (((xlocal && netconn && IS_TELNET()) ||
8836 (!xlocal && sstelnet)));
8837 #endif /* TCPSOCKET */
8847 ttpush = -1; /* Clear the peek-ahead char */
8848 while (le_data && (le_inbuf() > 0)) {
8850 if (le_getchar(&ch) > 0) { /* Clear any more... */
8851 debug(F101,"ttflui le_inbuf ch","",ch);
8854 #endif /* TTLEBUF */
8855 debug(F101,"ttflui ttpipe","",ttpipe);
8859 Flush internal MYREAD buffer *NEXT*, in all cases.
8865 /* Network flush is done specially, in the network support module. */
8866 if ((netconn || sstelnet) && !ttpipe && !ttpty) {
8867 debug(F100,"ttflui netflui","",0);
8871 tnc_send_purge_data(TNC_PURGE_RECEIVE);
8872 #endif /* TN_COMPORT */
8873 #endif /* COMMENT */
8876 #endif /* NETCONN */
8878 debug(F101,"ttflui ttyfd","",ttyfd); /* Not network */
8883 sio_$control((short)yfd, sio_$flush_in, true, st);
8884 if (st.all != status_$ok) {
8885 fprintf(stderr, "flush failed: "); error_$print(st);
8886 } else { /* sometimes the flush doesn't work */
8889 /* eat all the characters that shouldn't be available */
8890 ios_$get((short)fd, ios_$cond_opt, buf, 256L, st); /* (void) */
8891 if (st.all == ios_$get_conditional_failed) break;
8892 fprintf(stderr, "flush failed(2): "); error_$print(st);
8896 #ifdef BSD44 /* 4.4 BSD */
8897 n = FREAD; /* Specify read queue */
8898 debug(F100,"ttflui BSD44","",0);
8899 ioctl(fd,TIOCFLUSH,&n);
8902 #undef POSIX /* Uh oh... */
8904 #ifdef POSIX /* POSIX */
8905 debug(F100,"ttflui POSIX","",0);
8906 tcflush(fd,TCIFLUSH);
8908 #ifdef ATTSV /* System V */
8910 debug(F100,"ttflui ATTSV","",0);
8913 #else /* Not BSD44, POSIX, or Sys V */
8914 #ifdef TIOCFLUSH /* Those with TIOCFLUSH defined */
8915 #ifdef ANYBSD /* Berkeley */
8916 n = FREAD; /* Specify read queue */
8917 debug(F100,"ttflui TIOCFLUSH ANYBSD","",0);
8918 ioctl(fd,TIOCFLUSH,&n);
8919 #else /* Others (V7, etc) */
8920 debug(F100,"ttflui TIOCFLUSH","",0);
8921 ioctl(fd,TIOCFLUSH,0);
8923 #else /* All others... */
8925 No system call (that we know about) for input buffer flushing.
8926 So see how many there are and read them in a loop, using ttinc().
8927 ttinc() is buffered, so we're not getting charged with a system call
8928 per character, just a function call.
8930 if ((n = ttchk()) > 0) {
8931 debug(F101,"ttflui read loop","",n);
8932 while ((n--) && ttinc(0) > 0) ;
8934 #endif /* TIOCFLUSH */
8946 ttfluo() { /* Flush output buffer */
8959 return(tcflush(fd,TCOFLUSH));
8962 return(ioctl(fd,TCFLSH,1));
8964 return(0); /* All others, nothing */
8970 /* Interrupt Functions */
8972 /* Set up terminal interrupts on console terminal */
8974 #ifndef FIONREAD /* We don't need esctrp() */
8975 #ifndef SELECT /* if we have any of these... */
8982 esctrp(foo) int foo; { /* trap console escapes (^\) */
8983 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
8985 debug(F101,"esctrp caught SIGQUIT","",conesc);
8987 #endif /* SVORPOSIX */
8993 esctrp(foo) int foo; { /* trap console escapes (^\) */
8994 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
8996 debug(F101,"esctrp caught SIGQUIT","",conesc);
9003 esctrp(foo) int foo; { /* trap console escapes (^\) */
9005 signal(SIGQUIT,SIG_IGN); /* ignore until trapped */
9010 #endif /* CK_POLL */
9012 #endif /* FIONREAD */
9014 /* C O N B G T -- Background Test */
9016 static int jc = 0; /* 0 = no job control */
9019 Call with flag == 1 to prevent signal test, which can not be expected
9020 to work during file transfer, when SIGINT probably *is* set to SIG_IGN.
9022 Call with flag == 0 to use the signal test, but only if the process-group
9023 test fails, as it does on some UNIX systems, where getpgrp() is buggy,
9024 requires an argument when the man page says it doesn't, or vice versa.
9026 If flag == 0 and the process-group test fails, then we determine background
9027 status simply (but not necessarily reliably) from isatty().
9029 conbgt() sets the global backgrd = 1 if we appear to be in the background,
9030 and to 0 if we seem to be in the foreground. conbgt() is highly prone to
9034 conbgt(flag) int flag; {
9035 int x = -1, /* process group or SIGINT test */
9036 y = 0; /* isatty() test */
9038 Check for background operation, even if not running on real tty, so that
9039 background flag can be set correctly. If background status is detected,
9040 then Kermit will not issue its interactive prompt or most messages.
9041 If your prompt goes away, you can blame (and fix?) this function.
9044 /* Use process-group test if possible. */
9046 #ifdef POSIX /* We can do it in POSIX */
9049 #ifdef BSD4 /* and in BSD 4.x. */
9052 #ifdef HPUXJOBCTL /* and in most HP-UX's */
9055 #ifdef TIOCGPGRP /* and anyplace that has this ioctl. */
9057 #endif /* TIOCGPGRP */
9058 #endif /* HPUXJOBCTL */
9062 #ifdef MIPS /* Except if it doesn't work... */
9068 Semi-reliable process-group test. Check whether this process's group is
9069 the same as the controlling terminal's process group. This works if the
9070 getpgrp() call doesn't lie (as it does in the SUNOS System V environment).
9072 PID_T mypgrp = (PID_T)0; /* Kermit's process group */
9073 PID_T ctpgrp = (PID_T)0; /* The terminal's process group */
9074 #ifndef _POSIX_SOURCE
9076 The getpgrp() prototype is obtained from system header files for POSIX
9077 and Sys V R4 compilations. Other systems, who knows. Some complain about
9078 a duplicate declaration here, others don't, so it's safer to leave it in
9079 if we don't know for certain.
9084 extern PID_T getpgrp();
9086 #endif /* PS2AIX10 */
9088 #endif /* _POSIX_SOURCE */
9090 /* Get my process group. */
9092 #ifdef SVR3 /* Maybe this should be ATTSV? */
9093 /* This function is not described in SVID R2 */
9095 /* debug(F101,"ATTSV conbgt process group","",(int) mypgrp); */
9099 /* debug(F101,"POSIX conbgt process group","",(int) mypgrp); */
9103 /* debug(F101,"OSF conbgt process group","",(int) mypgrp); */
9107 /* debug(F101,"QNX conbgt process group","",(int) mypgrp); */
9109 #ifdef OSF32 /* (was OSF40) */
9111 /* debug(F101,"Digital UNIX conbgt process group","",(int) mypgrp); */
9112 #else /* BSD, V7, etc */
9116 mypgrp = getpgrp(0);
9118 /* debug(F101,"BSD conbgt process group","",(int) mypgrp); */
9129 /* Now get controlling tty's process group */
9131 ctpgrp = tcgetpgrp(1); /* The POSIX way */
9132 /* debug(F101,"POSIX conbgt terminal process group","",(int) ctpgrp); */
9134 ioctl(1, TIOCGPGRP, &ctpgrp); /* Or the BSD way */
9135 /* debug(F101,"non-POSIX conbgt terminal process group","",(int) ctpgrp); */
9136 #endif /* BSD44ORPOSIX */
9139 #define BSD44ORPOSIX
9142 if ((mypgrp > (PID_T) 0) && (ctpgrp > (PID_T) 0))
9143 x = (mypgrp == ctpgrp) ? 0 : 1; /* If they differ, then background. */
9144 else x = -1; /* If error, remember. */
9145 debug(F101,"conbgt process group test","",x);
9146 #endif /* PGROUP_T */
9148 /* Try to see if job control is available */
9150 #ifdef NOJC /* User override */
9151 jc = 0; /* No job control allowed */
9152 debug(F111,"NOJC","jc",jc);
9157 #ifdef SVR4ORPOSIX /* POSIX actually tells us */
9158 debug(F100,"SVR4ORPOSIX jc test...","",0);
9159 #ifdef _SC_JOB_CONTROL
9166 jc = sysconf(_SC_JOB_CONTROL); /* Whatever system says */
9168 debug(F101,"sysconf fails, jcshell","",jcshell);
9169 jc = (jchdlr == SIG_DFL) ? 1 : 0;
9171 debug(F111,"sysconf(_SC_JOB_CONTROL)","jc",jc);
9172 #endif /* __386BSD__ */
9173 #endif /* __bsdi__ */
9175 #ifdef _POSIX_JOB_CONTROL
9176 jc = 1; /* By definition */
9177 debug(F111,"_POSIX_JOB_CONTROL is defined","jc",jc);
9179 jc = 0; /* Assume job control not allowed */
9180 debug(F111,"SVR4ORPOSIX _SC/POSIX_JOB_CONTROL not defined","jc",jc);
9181 #endif /* _POSIX_JOB_CONTROL */
9182 #endif /* _SC_JOB_CONTROL */
9185 jc = 1; /* Job control allowed */
9186 debug(F111,"BSD job control","jc",jc);
9189 jc = 1; /* JC allowed */
9190 debug(F111,"SVR3 job control","jc",jc);
9193 jc = 1; /* JC allowed */
9194 debug(F111,"X/OS job control","jc",jc);
9197 jc = 1; /* JC allowed */
9198 debug(F111,"HP-UX 9.0 job control","jc",jc);
9201 jc = 1; /* JC allowed */
9202 debug(F111,"HP-UX 10.0 job control","jc",jc);
9204 jc = 0; /* JC not allowed */
9205 debug(F111,"job control catch-all","jc",jc);
9211 #endif /* SVR4ORPOSIX */
9214 debug(F101,"conbgt jc","",jc);
9216 debug(F101,"conbgt jcshell","",jcshell);
9218 At this point, if jc == 1 but jcshell == 0, it means that the OS supports
9219 job control, but the shell or other process we are running under does not
9220 (jcshell is set in sysinit()) and so if we suspend ourselves, nothing good
9221 will come of it. So...
9224 if (jc > 0 && jcshell == 0) jc = 0;
9228 Another background test.
9229 Test if SIGINT (terminal interrupt) is set to SIG_IGN (ignore),
9230 which is done by the shell (sh) if the program is started with '&'.
9231 Unfortunately, this is NOT done by csh or ksh so watch out!
9232 Note, it's safe to set SIGINT to SIG_IGN here, because further down
9233 we always set it to something else.
9234 Note: as of 16 Jul 1999, we also skip this test if we set SIGINT to
9237 if (x < 0 && !flag && !sigint_ign) { /* Didn't get good results above... */
9239 SIGTYP (*osigint)();
9241 osigint = signal(SIGINT,SIG_IGN); /* What is SIGINT set to? */
9243 x = (osigint == SIG_IGN) ? 1 : 0; /* SIG_IGN? */
9244 debug(F101,"conbgt osigint","",osigint);
9245 debug(F101,"conbgt signal test","",x);
9248 /* Also check to see if we're running with redirected stdio. */
9249 /* This is not really background operation, but we want to act as though */
9253 if (inserver) { /* Internet Kermit Server */
9254 backgrd = 0; /* is not in the background */
9259 y = (isatty(0) && isatty(1)) ? 1 : 0;
9260 debug(F101,"conbgt isatty test","",y);
9263 /* The process group and/or signal test doesn't work under these... */
9276 backgrd = (x || !y) ? 1 : 0;
9282 debug(F101,"conbgt backgrd","",backgrd);
9285 /* C O N I N T -- Console Interrupt setter */
9288 First arg is pointer to function to handle SIGTERM & SIGINT (like Ctrl-C).
9289 Second arg is pointer to function to handle SIGTSTP (suspend).
9292 VOID /* Set terminal interrupt traps. */
9295 conint(f,s) SIGTYP (*f)(), (*s)();
9297 conint(SIGTYP (*f)(int), SIGTYP (*s)(int))
9300 conint(f,s) SIGTYP (*f)(), (*s)();
9301 #endif /* CK_ANSIC */
9304 debug(F101,"conint conistate","",conistate);
9306 conbgt(0); /* Do background test. */
9308 /* Set the desired handlers for hangup and software termination. */
9311 signal(SIGTERM,f); /* Software termination */
9312 #endif /* SIGTERM */
9315 Prior to July 1999 we used to call sighup() here but now it's called in
9316 sysinit() so SIGHUP can be caught during execution of the init file or
9320 /* Now handle keyboard stop, quit, and interrupt signals. */
9321 /* Check if invoked in background -- if so signals set to be ignored. */
9322 /* However, if running under a job control shell, don't ignore them. */
9323 /* We won't be getting any, as we aren't in the terminal's process group. */
9325 debug(F101,"conint backgrd","",backgrd);
9326 debug(F101,"conint jc","",jc);
9328 if (backgrd && !jc) { /* In background, ignore signals */
9329 debug(F101,"conint background ignoring signals, jc","",jc);
9331 signal(SIGTSTP,SIG_IGN); /* Keyboard stop */
9332 #endif /* SIGTSTP */
9333 signal(SIGQUIT,SIG_IGN); /* Keyboard quit */
9334 signal(SIGINT,SIG_IGN); /* Keyboard interrupt */
9336 conistate = CONI_NOI;
9337 } else { /* Else in foreground or suspended */
9338 debug(F101,"conint foreground catching signals, jc","",jc);
9339 signal(SIGINT,f); /* Catch terminal interrupt */
9340 sigint_ign = (f == SIG_IGN) ? 1 : 0;
9342 #ifdef SIGTSTP /* Keyboard stop (suspend) */
9343 /* debug(F101,"conint SIGSTSTP","",s); */
9344 if (s == NULL) s = SIG_DFL;
9345 #ifdef NOJC /* No job control allowed. */
9346 signal(SIGTSTP,SIG_IGN);
9347 #else /* Job control allowed */
9348 if (jc) /* if available. */
9351 signal(SIGTSTP,SIG_IGN);
9353 #endif /* SIGTSTP */
9357 #ifndef FIONREAD /* Watch out, we don't know this... */
9361 signal(SIGQUIT,esctrp); /* Quit signal, Sys III/V. */
9363 #endif /* CK_POLL */
9365 #endif /* FIONREAD */
9366 if (conesc) conesc = 0; /* Clear out pending escapes */
9369 signal(SIGQUIT,esctrp); /* V7 like Sys III/V */
9370 if (conesc) conesc = 0;
9373 signal(SIGQUIT,f); /* Apollo, catch it like others. */
9375 signal(SIGQUIT,SIG_IGN); /* Others, ignore like 4D & earlier. */
9378 #endif /* SVORPOSIX */
9380 conistate = CONI_INT;
9385 /* C O N N O I -- Reset console terminal interrupts */
9388 connoi() { /* Console-no-interrupts */
9390 debug(F101,"connoi conistate","",conistate);
9392 signal(SIGTSTP,SIG_IGN); /* Suspend */
9393 #endif /* SIGTSTP */
9394 conint(SIG_IGN,SIG_IGN); /* Interrupt */
9395 sigint_ign = 1; /* Remember we did this ourselves */
9397 signal(SIGQUIT,SIG_IGN); /* Quit */
9398 #endif /* SIGQUIT */
9400 signal(SIGTERM,SIG_IGN); /* Term */
9401 #endif /* SIGTERM */
9402 conistate = CONI_NOI;
9405 /* I N I T R A W Q -- Set up to read /dev/kmem for character count. */
9409 Used in Version 7 to simulate Berkeley's FIONREAD ioctl call. This
9410 eliminates blocking on a read, because we can read /dev/kmem to get the
9411 number of characters available for raw input. If your system can't
9412 or you won't let the world read /dev/kmem then you must figure out a
9413 different way to do the counting of characters available, or else replace
9414 this by a dummy function that always returns 0.
9417 * Call this routine as: initrawq(tty)
9418 * where tty is the file descriptor of a terminal. It will return
9419 * (as a char *) the kernel-mode memory address of the rawq character
9420 * count, which may then be read. It has the side-effect of flushing
9421 * input on the terminal.
9424 * John Mackin, Physiology Dept., University of Sydney (Australia)
9425 * ...!decvax!mulga!physiol.su.oz!john
9427 * Permission is hereby granted to do anything with this code, as
9428 * long as this comment is retained unmodified and no commercial
9429 * advantage is gained.
9435 #include <sys/proc.h>
9436 #endif /* COHERENT */
9442 #include <sys/proc.h>
9443 #endif /* COHERENT */
9446 initrawq(tty) int tty; {
9460 static struct nlist nl[] = {
9465 static struct proc *pp;
9469 NPTYPE xproc; /* Its type is defined in makefile. */
9473 if ((m = open("/dev/kmem", 0)) < 0) err("kmem");
9474 nlist(BOOTNAME, nl);
9475 if (nl[0].n_type == 0) err("proc array");
9477 if (nl[1].n_type == 0) err("nproc");
9479 lseek(m, (long)(nl[1].n_value), 0);
9480 read (m, &xproc, sizeof(xproc));
9481 saval = signal(SIGALRM, catch);
9482 if ((pid = fork()) == 0) {
9488 if(setjmp(jjbuf) == 0) {
9492 signal(SIGALRM, SIG_DFL);
9495 pp = (struct proc *) nl[0].n_value;
9497 if (lseek(m, (long)(nl[0].n_value), 0) < 0L) err("seek");
9498 if (read(m, &pp, sizeof(pp)) != sizeof(pp)) err("no read of proc ptr");
9500 lseek(m, (long)(nl[1].n_value), 0);
9501 read(m, &xproc, sizeof(xproc));
9503 if (lseek(m, (long)pp, 0) < 0L) err("Can't seek to proc");
9504 if ((p = malloc(xproc * sizeof(struct proc))) == NULL) err("malloc");
9505 if (read(m,p,xproc * sizeof(struct proc)) != xproc*sizeof(struct proc))
9506 err("read proc table");
9507 for (pp = (struct proc *)p; xproc > 0; --xproc, ++pp) {
9508 if (pp -> p_pid == (short) pid) goto iout;
9510 err("no such proc");
9514 qaddr = (char *)(pp -> p_wchan);
9525 /* More V7-support functions... */
9531 ckmakmsg(buf,200,"fatal error in initrawq: ", s, NULL, NULL);
9537 catch(foo) int foo; {
9542 /* G E N B R K -- Simulate a modem break. */
9556 genbrk(fn,msec) int fn, msec; {
9557 struct sgttyb ttbuf;
9558 int ret, sospeed, x, y;
9560 ret = ioctl(fn, TIOCGETP, &ttbuf);
9561 sospeed = ttbuf.sg_ospeed;
9562 ttbuf.sg_ospeed = BSPEED;
9563 ret = ioctl(fn, TIOCSETP, &ttbuf);
9564 y = (int)strlen(brnuls);
9565 x = ( BSPEED * 100 ) / msec;
9567 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9568 ttbuf.sg_ospeed = sospeed;
9569 ret = ioctl(fn, TIOCSETP, &ttbuf);
9570 ret = write(fn, "@", 1);
9577 genbrk(fn,msec) int fn, msec; {
9578 struct termios ttbuf;
9582 ret = tcgetattr(fn, &ttbuf);
9583 sospeed = ttbuf.c_ospeed;
9584 ttbuf.c_ospeed = BSPEED;
9585 ret = tcsetattr(fn,TCSADRAIN, &ttbuf);
9586 y = (int)strlen(brnuls);
9587 x = ( BSPEED * 100 ) / msec;
9589 ret = write(fn, brnuls, (( BSPEED * 100 ) / msec ));
9590 ttbuf.c_ospeed = sospeed;
9591 ret = tcsetattr(fn, TCSADRAIN, &ttbuf);
9592 ret = write(fn, "@", 1);
9599 I N C H K -- Check if chars waiting to be read on given file descriptor.
9601 This routine is a merger of ttchk() and conchk().
9603 channel == 0 to check console.
9604 channel == 1 to check communications connection.
9606 fd = file descriptor.
9608 >= 0: number of characters waiting, 0 or greater,
9609 -1: on any kind of error,
9610 -2: if there is (definitely) no connection.
9611 Note: In UNIX we don't have to call nettchk() because a socket
9612 file descriptor works just like in serial i/o, ioctls and all.
9613 (But this will change if we add non-file-descriptor channels,
9614 such as IBM X.25 for AIX...)
9617 in_chk(channel, fd) int channel, fd; {
9618 int x, n = 0; /* Workers, n = return value */
9619 extern int clsondisc; /* Close on disconnect */
9621 The first section checks to make sure we have a connection,
9622 but only if we're in local mode.
9626 debug(F111,"in_chk entry",ckitoa(fd),channel);
9627 debug(F101,"in_chk ttyfd","",ttyfd);
9628 debug(F101,"in_chk ttpty","",ttpty);
9632 But don't say connection is gone if we have any buffered-stuff.
9635 debug(F101,"in_chk ttpush","",ttpush);
9643 #endif /* TTLEBUF */
9647 /* Special handling for HP-UX pty i/o */
9648 if (ttpty && pty_trap_pending(ttyfd) > 0) {
9649 if (pty_trap_handler(ttyfd) > 0) {
9654 #endif /* HAVE_PTYTRAP */
9657 if (channel) { /* Checking communications channel */
9658 if (ttyfd < 0) { /* No connection */
9659 return(-2); /* That's what this means */
9660 } else if (xlocal && /* In local mode */
9661 (!netconn /* Serial connection or */
9663 || istncomport() /* Telnet Com Port */
9664 #endif /* TN_COMPORT */
9665 ) && ttcarr != CAR_OFF /* with CARRIER WATCH ON (or AUTO) */
9669 Seems like this would be a good idea but it prevents C-Kermit from
9670 popping back to the prompt automatically when carrier drops. However,
9671 commenting this out prevents us from seeing the NO CARRIER message.
9674 && my_count < 1 /* Nothing in our internal buffer */
9676 #endif /* COMMENT */
9679 x = ttgmdm(); /* So get modem signals */
9680 debug(F101,"in_chk close-on-disconnect","",clsondisc);
9681 if (x > -1) { /* Check for carrier */
9682 if (!(x & BM_DCD)) { /* No carrier */
9683 debug(F101,"in_chk carrier lost","",x);
9684 if (clsondisc) /* If "close-on-disconnect" */
9685 ttclos(0); /* close device & release lock. */
9686 return(-2); /* This means "disconnected" */
9688 /* In case I/O to device after CD dropped always fails */
9689 /* as in Debian Linux 2.1 and Unixware 2.1... */
9691 debug(F101,"in_chk ttgmdm I/O error","",errno);
9692 debug(F101,"in_chk ttgmdm gotsigs","",gotsigs);
9693 if (gotsigs) { /* If we got signals before... */
9694 if (errno == 5 || errno == 6) { /* I/O error etc */
9695 if (clsondisc) /* like when modem hangs up */
9700 /* If we never got modem signals successfully on this */
9701 /* connection before, we can't conclude that THIS failure */
9702 /* means the connection was lost. */
9708 /* We seem to have a connection so now see if any bytes are waiting on it */
9711 if (ssl_active_flag || tls_active_flag) {
9712 n += SSL_pending(ssl_active_flag?ssl_con:tls_con);
9713 debug(F101,"in_chk SSL_pending","",n);
9724 /* It is not safe to read any data when using encrypted Klogin */
9725 if (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN) {
9727 if (ttnproto == NP_EK4LOGIN) {
9728 n += krb4_des_avail(ttyfd);
9729 debug(F101,"in_chk krb4_des_avail","",n);
9733 if (ttnproto == NP_EK5LOGIN) {
9734 n += krb5_des_avail(ttyfd);
9735 debug(F101,"in_chk krb5_des_avail","",n);
9738 if (ttnproto == NP_K5U2U) {
9739 n += krb5_u2u_avail(ttyfd);
9740 debug(F101,"in_chk krb5_des_avail","",n);
9742 #endif /* KRB5_U2U */
9744 if (n < 0) /* Is this right? */
9749 #endif /* CK_KERBEROS */
9750 #endif /* RLOGCODE */
9752 errno = 0; /* Reset this so we log good info */
9754 x = ioctl(fd, FIONREAD, &n); /* BSD and lots of others */
9755 #ifdef DEBUG /* (the more the better) */
9757 debug(F101,"in_chk FIONREAD return code","",x);
9758 debug(F101,"in_chk FIONREAD count","",n);
9759 debug(F101,"in_chk FIONREAD errno","",errno);
9762 #else /* FIONREAD not defined */
9764 Here, if (netconn && ttnet == NET_TCPB), we might try calling recvmsg()
9765 with flags MSG_PEEK|MSG_DONTWAIT on the socket (ttyfd), except this is not
9766 portable (MSG_DONTWAIT isn't defined in any of the <sys/socket.h> files
9767 that I looked at, but it is needed to prevent the call from blocking), and
9768 the msghdr struct differs from place to place, so we would need another
9769 avalanche of ifdefs. Still, when FIONREAD is not available, this is the
9770 only other known method of asking the OS for the *number* of characters
9771 available for reading.
9773 #ifdef V7 /* UNIX V7: look in kernel memory */
9775 n = 0; /* But not in MINIX */
9780 lseek(kmem[TTY], (long) qaddr[TTY], 0); /* 7th Edition Unix */
9781 x = read(kmem[TTY], &n, sizeof(int));
9782 if (x != sizeof(int))
9788 x = ioctl(fd, TIOCQCNT, &ttbuf); /* DEC Pro/3xx Venix V.1 */
9789 n = ttbuf.sg_ispeed & 0377; /* Circa 1984 */
9794 Here we skip all the undependable and expensive calls below if we
9795 already have something in our internal buffer. This tends to work quite
9796 nicely, so the only really bad case remaining is the one in which neither
9797 FIONREAD or MYREAD are defined, which is increasingly rare these days.
9799 if (channel != 0 && my_count > 0) {
9800 debug(F101,"in_chk buf my_count","",my_count);
9801 n = my_count; /* n was 0 before we got here */
9806 rdchk(), select(), and poll() tell us *if* data is available to be read, but
9807 not how much, so these should be used only as a final resort. Especially
9808 since these calls tend to add a lot overhead.
9810 #ifdef RDCHK /* This mostly SCO-specific */
9812 debug(F101,"in_chk rdchk","",n);
9813 #else /* No RDCHK */
9816 /* Only allows select on the console ... don't ask */
9820 fd_set rfds; /* Read file descriptors */
9822 FD_ZERO(rfds); /* Initialize them */
9823 FD_SET(fd,rfds); /* We want to look at this fd */
9825 FD_ZERO(&rfds); /* Initialize them */
9826 FD_SET(fd,&rfds); /* We want to look at this fd */
9827 tv.tv_sec = tv.tv_usec = 0L; /* A 0-valued timeval structure */
9828 #endif /* BELLV10 */
9830 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9831 debug(F101,"in_chk Plan 9 select","",n);
9834 n = select( 128, rfds, (fd_set *)0, (fd_set *)0, 0 );
9835 debug(F101,"in_chk BELLV10 select","",n);
9838 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9839 debug(F101,"in_chk BSD44 select","",n);
9842 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9843 debug(F101,"in_chk BSD43 select","",n);
9846 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9847 debug(F101,"in_chk SOLARIS select","",n);
9850 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9851 debug(F101,"in_chk QNX6 select","",n);
9854 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9855 debug(F101,"in_chk QNX select","",n);
9858 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9859 debug(F101,"in_chk COHERENT select","",n);
9862 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9863 debug(F101,"in_chk SVR4 select","",n);
9866 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9867 debug(F101,"in_chk LINUX select","",n);
9869 n = select( FD_SETSIZE, &rfds, (fd_set *)0, (fd_set *)0, &tv );
9870 debug(F101,"in_chk OSF select","",n);
9872 n = select( FD_SETSIZE, &rfds, (int *)0, (int *)0, &tv );
9873 debug(F101,"in_chk catchall select","",n);
9875 #endif /* __linux__ */
9877 #endif /* COHERENT */
9880 #endif /* SOLARIS */
9883 #endif /* BELLV10 */
9886 #else /* Not SELECT */
9892 pfd.events = POLLIN;
9894 n = poll(&pfd, 1, 0);
9895 debug(F101,"in_chk poll","",n);
9896 if ((n > 0) && (pfd.revents & POLLIN))
9899 #endif /* CK_POLL */
9904 #endif /* FIONREAD */
9906 /* From here down, treat console and communication device differently... */
9908 if (channel == 0) { /* Console */
9916 This is the hideous hack used in System V and POSIX systems that don't
9917 support FIONREAD, rdchk(), select(), poll(), etc, in which the user's
9918 CONNECT-mode escape character is attached to SIGQUIT. Used, obviously,
9919 only on the console.
9921 if (conesc) { /* Escape character typed == SIGQUIT */
9922 debug(F100,"in_chk conesc","",conesc);
9924 signal(SIGQUIT,esctrp); /* Restore signal */
9928 #endif /* CK_POLL */
9930 #endif /* FIONREAD */
9931 #endif /* SVORPOSIX */
9933 return(n); /* Done with console */
9936 if (channel != 0) { /* Communications connection */
9941 select() or rdchk(), etc, has told us that something is waiting, but we
9942 don't know how much. So we do a read to get it and then we know. Note:
9943 This read is NOT nonblocking if nothing is there (because of VMIN=1), but
9944 it should be safe in this case since the OS tells us at least one byte is
9945 waiting to be read, and MYREAD reads return as much as is there without
9946 waiting for any more. Controlled tests on Solaris and Unixware (with
9947 FIONREAD deliberately undefined) show this to be true.
9949 debug(F101,"in_chk read my_count","",my_count);
9950 debug(F101,"in_chk read n","",n);
9951 if (n > 0 && my_count == 0) {
9952 /* This also catches disconnects etc */
9953 /* Do what mygetbuf does except don't grab a character */
9954 my_count = myfillbuf();
9955 my_item = -1; /* ^^^ */
9956 debug(F101,"in_chk myfillbuf my_count","",my_count);
9960 n = 0; /* NB: n is replaced by my_count */
9962 #endif /* FIONREAD */
9964 Here we add whatever we think is unread to what is still in our
9965 our internal buffer. Thus the importance of setting n to 0 just above.
9967 debug(F101,"in_chk my_count","",my_count);
9968 debug(F101,"in_chk n","",n);
9973 debug(F101,"in_chk result","",n);
9975 /* Errors here don't prove the connection has dropped so just say 0 */
9977 return(n < 0 ? 0 : n);
9981 /* T T C H K -- Tell how many characters are waiting in tty input buffer */
9992 return(in_chk(1,fd));
9995 /* T T X I N -- Get n characters from tty input buffer */
9997 /* Returns number of characters actually gotten, or -1 on failure */
9999 /* Intended for use only when it is known that n characters are actually */
10000 /* Available in the input buffer. */
10003 ttxin(n,buf) int n; CHAR *buf; {
10004 register int x = 0, c = -2;
10006 register int i = 0;
10007 #endif /* TTLEBUF */
10010 if (n < 1) /* Nothing to do */
10015 buf[0] = ttpush; /* Put pushed char in buffer*/
10016 ttpush = -1; /* Clear the push buffer */
10018 return(ttxin(n-1, &buf[1]) + 1);
10023 while (le_inbuf() > 0) {
10024 if (le_getchar(&buf[i])) {
10030 return(ttxin(n,&buf[i])+i);
10034 #endif /* TTLEBUF */
10040 #endif /* NETCMD */
10044 if (netconn && (ttnet == NET_SX25)) /* X.25 connection */
10045 return(x25xin(n,buf));
10046 #endif /* SUNX25 */
10049 /* riehm: possibly not needed. Test worked with normal reads and writes */
10050 if (netconn && (ttnet == NET_IX25)) { /* X.25 connection */
10052 if (x > 0) buf[x] = '\0';
10055 #endif /* IBMX25 */
10058 debug(F101,"ttxin MYREAD","",n);
10062 debug(F101,"ttxin myread returns","",c);
10063 if (c == -3) x = -1;
10066 buf[x++] = c & ttpmsk;
10069 /* It is impossible to know how many characters are waiting */
10070 /* to be read when you are using Encrypted Rlogin or SSL */
10071 /* as the transport since the number of real data bytes */
10072 /* can be greater or less than the number of bytes on the */
10073 /* wire which is what ttchk() returns. */
10074 if (netconn && (ttnproto == NP_EK4LOGIN || ttnproto == NP_EK5LOGIN))
10077 #endif /* CK_KERBEROS */
10078 #endif /* RLOGCODE */
10080 if (ssl_active_flag || tls_active_flag)
10083 #endif /* CK_SSL */
10086 debug(F101,"ttxin READ","",n);
10087 x = read(fd,buf,n);
10088 for (c = 0; c < n; c++) /* Strip any parity */
10090 #endif /* MYREAD */
10092 debug(F101,"ttxin x","",x); /* Done */
10093 if (x > 0) buf[x] = '\0';
10098 /* T T O L -- Write string s, length n, to communication device. */
10101 >= 0 on success, number of characters actually written.
10104 #ifdef CK_ENCRYPTION
10105 CHAR * xpacket = NULL;
10107 #endif /* CK_ENCRYPTION */
10111 ttol(s,n) int n; CHAR *s; {
10112 int x, len, tries, fd;
10114 extern int dblflag; /* For SET SEND DOUBLE-CHARACTER */
10115 extern short dblt[];
10116 CHAR *p = NULL, *p2, *s2, c;
10118 #endif /* CKXXCHAR */
10120 if (ttyfd < 0) /* Not open? */
10123 if (deblog) hexdump("ttol s",s,n);
10130 #endif /* NETCMD */
10134 /* Double any characters that must be doubled. */
10135 debug(F101,"ttol dblflag","",dblflag);
10137 p = (CHAR *) malloc(n + n + 1);
10146 if (dblt[(unsigned) c] & 2) {
10156 if (deblog) hexdump("ttol doubled s",s,n);
10159 #endif /* CKXXCHAR */
10161 tries = TTOLMAXT; /* Allow up to this many tries */
10162 len = n; /* Remember original length */
10164 #ifdef CK_ENCRYPTION
10166 This is to avoid encrypting a packet that is already encrypted, e.g.
10167 when we resend a packet directly out of the packet buffer, and also to
10168 avoid encrypting a constant (literal) string, which can cause a memory
10171 if (TELOPT_ME(TELOPT_ENCRYPTION)) {
10173 if (nxpacket < n) {
10179 x = n > 10240 ? n : 10240;
10180 xpacket = (CHAR *)malloc(x);
10182 fprintf(stderr,"ttol malloc failure\n");
10187 memcpy((char *)xpacket,(char *)s,n);
10189 ck_tn_encrypt((char *)s,n);
10191 #endif /* CK_ENCRYPTION */
10195 #ifdef CK_ENCRYPTION
10196 /* keep trying if we are encrypting */
10197 || TELOPT_ME(TELOPT_ENCRYPTION)
10198 #endif /* CK_ENCRYPTION */
10199 )) { /* Be persistent */
10200 debug(F101,"ttol try","",TTOLMAXT - tries);
10202 if (netconn && !ttpipe && !ttpty)
10203 x = nettol((char *)s,n); /* Write string to device */
10205 #endif /* BEOSORBEBOX */
10207 if (ttnet == NET_IX25)
10209 * this is a more controlled way of writing to X25
10210 * STREAMS, however write should also work!
10212 x = x25write(ttyfd, s, n);
10214 #endif /* IBMX25 */
10216 if (ssl_active_flag || tls_active_flag) {
10218 /* Write using SSL */
10220 if (ssl_active_flag)
10221 x = SSL_write(ssl_con, s, n);
10223 x = SSL_write(tls_con, s, n);
10224 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,x)) {
10225 case SSL_ERROR_NONE:
10231 case SSL_ERROR_WANT_WRITE:
10232 case SSL_ERROR_WANT_READ:
10235 case SSL_ERROR_SYSCALL:
10238 case SSL_ERROR_WANT_X509_LOOKUP:
10239 case SSL_ERROR_SSL:
10240 case SSL_ERROR_ZERO_RETURN:
10246 #endif /* CK_SSL */
10250 if (ttnproto == NP_EK4LOGIN) {
10251 return(krb4_des_write(ttyfd,s,n));
10253 #endif /* RLOGCODE */
10257 if (ttnproto == NP_EK5LOGIN) {
10258 return(krb5_des_write(ttyfd,s,n,0));
10260 #endif /* RLOGCODE */
10262 if (ttnproto == NP_K5U2U) {
10263 return(krb5_u2u_write(ttyfd,s,n));
10265 #endif /* KRB5_U2U */
10267 #endif /* CK_KERBEROS */
10268 x = write(fd,s,n); /* Write string to device */
10270 if (x == n) { /* Worked? */
10271 debug(F101,"ttol ok","",x); /* OK */
10274 #endif /* CKXXCHAR */
10275 return(len); /* Done */
10276 } else if (x < 0) { /* No, got error? */
10277 debug(F101,"ttol write error","",errno);
10279 if (errno == EWOULDBLOCK) {
10283 #endif /* EWOULDBLOCK */
10285 if (netconn && ttnet == NET_TCPB) {
10286 debug(F101,"ttol TCP error","",errno);
10287 ttclos(0); /* Close the connection. */
10290 #endif /* TCPSOCKET */
10293 #endif /* CKXXCHAR */
10295 } else { /* No error, so partial success */
10296 debug(F101,"ttol partial","",x); /* This never happens */
10297 s += x; /* Point to part not written yet */
10298 n -= x; /* Adjust length */
10299 if (x > 0) msleep(10); /* Wait 10 msec */
10300 } /* Go back and try again */
10304 #endif /* CKXXCHAR */
10305 return(n < 1 ? len : -1); /* Return the results */
10308 /* T T O C -- Output a character to the communication line */
10311 This function should only be used for interactive, character-mode operations,
10312 like terminal connection, script execution, dialer i/o, where the overhead
10313 of the signals and alarms does not create a bottleneck.
10320 #endif /* CK_ANSIC */
10322 #define TTOC_TMO 15 /* Timeout in case we get stuck */
10325 if (ttyfd < 0) /* Check for not open. */
10332 #endif /* NETCMD */
10336 /* debug(F101,"ttoc","",(CHAR) c); */
10337 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10338 xx = alarm(TTOC_TMO); /* for this many seconds. */
10339 if (xx < 0) xx = 0; /* Save old alarm value. */
10340 /* debug(F101,"ttoc alarm","",xx); */
10342 #ifdef CK_POSIX_SIG
10346 #endif /* CK_POSIX_SIG */
10347 ) { /* Timer went off? */
10348 ttimoff(); /* Yes, cancel this alarm. */
10349 if (xx - TTOC_TMO > 0) alarm(xx - TTOC_TMO); /* Restore previous one */
10350 /* debug(F100,"ttoc timeout","",0); */
10353 #endif /* NETCONN */
10354 debug(F101,"ttoc timeout","",c);
10355 if (ttflow == FLO_XONX) {
10356 debug(F101,"ttoc flow","",ttflow); /* Maybe we're xoff'd */
10359 /* POSIX way to unstick. */
10360 debug(F100,"ttoc tcflow","",tcflow(ttyfd,TCOON));
10362 #ifdef BSD4 /* Berkeley way to do it. */
10364 /* .... Used to be "ioctl(ttyfd, TIOCSTART, 0);". Who knows? */
10367 debug(F101,"ttoc TIOCSTART","",ioctl(ttyfd, TIOCSTART, &x));
10369 #endif /* TIOCSTART */
10371 /* Is there a Sys V way to do this? */
10377 #endif /* NETCONN */
10378 return(-1); /* Return failure code. */
10383 if (netconn && !ttpipe && !ttpty)
10386 #endif /* BEOSORBEBOX */
10387 #endif /* NETCONN */
10388 #ifdef CK_ENCRYPTION
10389 if (TELOPT_ME(TELOPT_ENCRYPTION))
10390 ck_tn_encrypt(&c,1);
10391 #endif /* CK_ENCRYPTION */
10393 /* riehm: maybe this isn't necessary after all. Test program
10394 * worked fine with data being sent and retrieved with normal
10395 * read's and writes!
10397 if (ttnet == NET_IX25)
10398 rc = x25write(ttyfd,&c,1); /* as above for X25 streams */
10400 #endif /* IBMX25 */
10402 if (ssl_active_flag || tls_active_flag) {
10404 /* Write using SSL */
10405 if (ssl_active_flag)
10406 rc = SSL_write(ssl_con, &c, 1);
10408 rc = SSL_write(tls_con, &c, 1);
10409 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)){
10410 case SSL_ERROR_NONE:
10412 case SSL_ERROR_WANT_WRITE:
10413 case SSL_ERROR_WANT_READ:
10416 case SSL_ERROR_SYSCALL:
10419 case SSL_ERROR_WANT_X509_LOOKUP:
10420 case SSL_ERROR_SSL:
10421 case SSL_ERROR_ZERO_RETURN:
10427 #endif /* CK_SSL */
10431 if (ttnproto == NP_EK4LOGIN) {
10432 rc = (krb4_des_write(ttyfd,&c,1) == 1);
10434 #endif /* RLOGCODE */
10438 if (ttnproto == NP_EK5LOGIN) {
10439 rc = (krb5_des_write(ttyfd,&c,1,0) == 1);
10441 #endif /* RLOGCODE */
10443 if (ttnproto == NP_K5U2U) {
10444 rc = (krb5_u2u_write(ttyfd,&c,1) == 1);
10446 #endif /* KRB5_U2U */
10448 #endif /* CK_KERBEROS */
10449 rc = write(fd,&c,1); /* Try to write the character. */
10450 if (rc < 1) { /* Failed */
10451 ttimoff(); /* Turn off the alarm. */
10452 alarm(xx); /* Restore previous alarm. */
10453 debug(F101,"ttoc errno","",errno); /* Log the error, */
10454 return(-1); /* and return the error code. */
10457 ttimoff(); /* Success, turn off the alarm. */
10458 alarm(xx); /* Restore previous alarm. */
10459 return(0); /* Return good code. */
10462 /* T T I N L -- Read a record (up to break character) from comm line. */
10464 Reads up to "max" characters from the communication line, terminating on:
10465 (a) the packet length field if the "turn" argument is zero, or
10466 (b) on the packet-end character (eol) if the "turn" argument is nonzero
10467 (c) a certain number of Ctrl-C's in a row
10470 >= 0, the number of characters read upon success;
10471 -1 if "max" exceeded, timeout, or other correctable error;
10472 -2 on user interruption (c);
10473 -3 on fatal error like connection lost.
10475 The characters that were input are copied into "dest" with their parity bits
10476 stripped if parity was selected. Returns the number of characters read.
10477 Characters after the eol are available upon the next call to this function.
10479 The idea is to minimize the number of system calls per packet, and also to
10480 minimize timeouts. This function is the inner loop of the protocol and must
10481 be as efficient as possible. The current strategy is to use myread().
10483 WARNING: This function calls parchk(), which is defined in another module.
10484 Normally, ckutio.c does not depend on code from any other module, but there
10485 is an exception in this case because all the other ck?tio.c modules also
10486 need to call parchk(), so it's better to have it defined in a common place.
10491 #define CTRLC '\03'
10493 We have four different declarations here because:
10494 (a) to allow Kermit to be built without the automatic parity sensing feature
10495 (b) one of each type for ANSI C, one for non-ANSI.
10498 static int csave = -1;
10504 ttinl(CHAR *dest, int max,int timo, CHAR eol, CHAR start, int turn)
10506 ttinl(dest,max,timo,eol,start,turn) int max,timo,turn; CHAR *dest, eol, start;
10507 #endif /* CK_ANSIC */
10508 #else /* not PARSENSE */
10510 ttinl(CHAR *dest, int max,int timo, CHAR eol)
10512 ttinl(dest,max,timo,eol) int max,timo; CHAR *dest, eol;
10513 #endif /* __SDTC__ */
10514 #endif /* PARSENSE */
10519 #endif /* MYREAD */
10524 #endif /* PARSENSE */
10526 int sopmask = 0xff; /* Start-Of-Packet mask */
10528 extern short dblt[]; /* Ignore-character table */
10529 extern int ignflag;
10530 #endif /* CKXXCHAR */
10533 #endif /* TCPSOCKET */
10536 extern int streaming;
10538 #endif /* STREAMING */
10540 if (ttyfd < 0) return(-3); /* Not open. */
10542 debug(F101,"ttinl max","",max);
10543 debug(F101,"ttinl timo","",timo);
10549 #endif /* NETCMD */
10553 if (xlocal && conchk() > 0) /* Allow for console interruptions */
10555 #endif /* COMMENT */
10557 *dest = '\0'; /* Clear destination buffer */
10558 if (timo < 0) timo = 0; /* Safety */
10559 if (timo) { /* Don't time out if timo == 0 */
10561 saval = signal(SIGALRM,timerh); /* Enable timer interrupt */
10562 xx = alarm(timo); /* Set it. */
10563 debug(F101,"ttinl alarm","",xx);
10566 #ifdef CK_POSIX_SIG
10570 #endif /* CK_POSIX_SIG */
10571 ) { /* Timer went off? */
10572 debug(F100,"ttinl timout","",0); /* Get here on timeout. */
10573 /* debug(F110," with",(char *) dest,0); */
10574 ttimoff(); /* Turn off timer */
10575 return(-1); /* and return error code. */
10577 register int i, n = -1; /* local variables */
10580 register int flag = 0;
10581 debug(F000,"ttinl start","",start);
10582 #endif /* PARSENSE */
10584 ttpmsk = ttprty ? 0177 : 0377; /* Set parity stripping mask. */
10585 sopmask = needpchk ? 0177 : ttpmsk; /* And SOP matching mask. */
10587 /* Now read into destination, stripping parity and looking for the */
10588 /* the packet terminator, and also for several Ctrl-C's typed in a row. */
10590 i = 0; /* Destination index */
10591 debug(F101,"ttinl eol","",eol);
10593 while (i < max-1) {
10595 /* debug(F101,"ttinl i","",i); */
10599 debug(F101,"ttinl unsaving","",n);
10602 if (xlocal && conchk() > 0) {
10603 /* Here we could catch keyboard interruptions. */
10604 /* But this would be VERY expensive. */
10605 /* We could also do it in myread() but it would be */
10606 /* expensive there too -- even if done with select()... */
10608 #endif /* COMMENT */
10609 if ((n = myread()) < 0) { /* Timeout or i/o error? */
10612 debug(F101,"ttinl myread failure, n","",n);
10613 debug(F101,"ttinl myread errno","",errno);
10616 /* Don't let EINTR break packets. */
10618 if (errno == EINTR && i > 0) {
10619 debug(F111,"ttinl EINTR myread i","continuing",i);
10622 debug(F110,"ttinl non-EINTR -3","closing",0);
10624 ttimoff(); /* Turn off timer */
10628 } else if (n == -2 && netconn /* && timo == 0 */ ) {
10629 /* Here we try to catch broken network connections */
10630 /* even when ioctl() and read() do not catch them */
10631 debug(F111,"ttinl network myread failure","closing",n);
10638 /* Streaming and no data to read */
10639 else if (n == 0 && streaming && sndtyp == 'D')
10641 #endif /* STREAMING */
10642 break; /* Break out of while loop */
10645 #else /* not MYREAD (is this code used anywhere any more?) */
10647 if (csave > -1) /* Char saved from last time */
10649 else if ((n = read(fd, &ch, 1)) < 1)
10650 break; /* Error - break out of while loop */
10653 #endif /* MYREAD */
10655 /* Get here with char in n */
10657 #ifdef CK_ENCRYPTION
10658 /* If csave > -1 we already decrypted this character */
10659 /* So don't decrypt it again */
10660 if (TELOPT_U(TELOPT_ENCRYPTION) && csave == -1) {
10662 ck_tn_decrypt(&ch,1);
10665 #endif /* CK_ENCRYPTION */
10667 csave = -1; /* Unflag that we unsaved a char */
10670 if (n == IAC && /* Handle Telnet options */
10671 ((xlocal && netconn && IS_TELNET()) ||
10672 (!xlocal && sstelnet))) {
10679 #endif /* NOPARSEN */
10680 if (n != 255) /* No data - go back for next char */
10682 } /* Quoted IAC - keep going */
10683 #endif /* TCPSOCKET */
10686 if (dblt[(unsigned) n] & 1) /* Character to ignore? */
10688 #endif /* CKXXCHAR */
10691 Use parity mask, rather than always stripping parity, to check for
10692 cancellation. Otherwise, runs like \x03\x83\x03 in a packet could cancel
10693 the transfer when parity is NONE. (Note that \x03\x03\x03 is extremely
10694 unlikely due to run-length encoding.)
10696 /* Check cancellation */
10697 if (!xlocal && xfrcan && ((n & ttpmsk) == xfrchr)) {
10698 if (++ccn >= xfrnum) { /* If xfrnum in a row, bail out. */
10699 if (timo) { /* Clear timer. */
10703 printf("^%c...\r\n",(char)(xfrchr+64));
10705 printf("Canceled...\r\n");
10708 } else ccn = 0; /* No cancellation, reset counter, */
10711 if (flag == 0) { /* Find the Start-Of-Packet. */
10712 if ((n & sopmask) == start) { /* Got it */
10714 } else { /* Keep looking... */
10715 debug(F000,"ttinl skipping","",n);
10719 dest[i++] = n & ttpmsk;
10721 If we have not been instructed to wait for a turnaround character, we
10722 can go by the packet length field. If turn != 0, we must wait for the
10723 end of line (eol) character before returning. This is an egregious
10724 violation of all principles of layering...
10728 pktlen = xunchar(dest[1] & 0x7f);
10731 debug(F101,"ttinl length","",pktlen);
10733 } else if (i == 5 && pktlen == 0) {
10734 lplen = xunchar(dest[4] & 0x7f);
10735 } else if (i == 6 && pktlen == 0) {
10736 pktlen = lplen * 95 + xunchar(dest[5] & 0x7f) + 5;
10738 debug(F101,"ttinl extended length","",pktlen);
10743 Suppose we looked at the sequence number here and found it was out of
10744 range? This would mean either (a) incoming packets had SOP unprefixed
10745 and we are out of sync, or (b) the packet is damaged. Since (a) is bad
10746 practice, let's ignore it. So what should we do here if we know the
10749 1. Nothing -- keep trying to read the packet till we find what we think
10750 is the end, or we time out, and let the upper layer decide what to
10751 do. But since either the packet is corrupt or we are out of sync,
10752 our criterion for finding the end does not apply and we are likely
10753 to time out (or swallow a piece of the next packet) if our assumed
10754 length is too long. (This was the behavior prior to version 7.0.)
10756 2. set flag = 0 and continue? This would force us to wait for the
10757 next packet to come in, and therefore (in the nonwindowing case),
10758 would force a timeout in the other Kermit.
10760 3. set flag = 0 and continue, but only if the window size is > 1 and
10761 the window is not blocked? Talk about cheating!
10763 4. Return a failure code and let the upper layer decide what to do.
10764 This should be equivalent to 3, but without the cheating. So let's
10765 do it that way... But note that we must ignore the parity bit
10766 in case this is the first packet and we have not yet run parchk().
10768 if (i == 3) { /* Peek at sequence number */
10769 x = xunchar((dest[i-1] & 0x7f)); /* If it's not in range... */
10770 if (x < 0 || x > 63) {
10771 debug(F111,"ttinl bad seq",dest,x);
10772 if (timo) ttimoff();
10773 return(-1); /* return a nonfatal error */
10777 #else /* PARSENSE */
10778 dest[i++] = n & ttpmsk;
10779 #endif /* PARSENSE */
10781 /* Check for end of packet */
10786 Purely length-driven if SET HANDSHAKE NONE (i.e. turn == 0).
10787 This allows packet terminators and handshake characters to appear
10788 literally inside a packet data field.
10790 (havelen && (i > pktlen+1) &&
10791 (!turn || (turn && (n & 0x7f) == turn))) /* (turn, not eol) */
10792 #else /* !PARSENSE */
10794 Built without PARSENSE, so just look for packet terminator.
10796 ((n & 0x7f) == eol)
10797 #endif /* PARSENSE */
10800 debug(F101,"ttinl got eol","",eol); /* (or turn) */
10801 dest[i] = '\0'; /* Yes, terminate the string, */
10802 /* debug(F101,"ttinl i","",i); */
10806 if ((n & 0x7f) != eol) {
10807 debug(F101,"ttinl EOP length","",pktlen);
10808 debug(F101,"ttinl i","",i);
10812 We read a packet based on its length. This leaves the EOP character still
10813 unread, and so ttchk() will always return at least 1 because of this. But
10814 if we know it is there, we can safely get rid of it. So...
10818 while (my_count > 0) {
10820 /* Start of next packet */
10821 if (x == start) { /* Save for next time */
10822 csave = (unsigned)((unsigned)x & 0xff);
10823 debug(F000,"ttinl csaved","",x);
10826 debug(F000,"ttinl removed","",x);
10829 #endif /* PARSENSE */
10830 #endif /* MYREAD */
10832 } else debug(F101,"ttinl got eol","",eol); /* (or turn) */
10835 dest[i] = '\0'; /* Terminate the string, */
10836 if (needpchk) { /* Parity checked yet? */
10837 if (ttprty == 0) { /* No, check. */
10838 if ((ttprty = parchk(dest,start,i)) > 0) {
10840 debug(F101,"ttinl senses parity","",ttprty);
10841 debug(F110,"ttinl packet before",dest,0);
10843 for (j = 0; j < i; j++)
10844 dest[j] &= 0x7f; /* Strip parity from packet */
10845 debug(F110,"ttinl packet after ",dest,0);
10846 } else ttprty = 0; /* Restore if parchk error */
10851 #endif /* PARSENSE */
10852 if (timo) { /* Turn off timer. */
10856 debug(F011,"ttinl got", dest, (i < 60) ? i : -60);
10857 #else /* COMMENT */
10858 hexdump("ttinl got",dest,i);
10859 #endif /* COMMENT */
10861 /* ttinl() was called because there was non-packet */
10862 /* data sitting int the channel. Ignore it. */
10863 if (streaming && sndtyp == 'D')
10865 #endif /* STREAMING */
10868 } /* End of while() */
10873 #endif /* NOXFER */
10875 /* T T I N C -- Read a character from the communication line */
10877 On success, returns the character that was read, >= 0.
10878 On failure, returns -1 or other negative myread error code,
10879 or -2 if connection is broken or ttyfd < 0.
10880 or -3 if session limit has expired,
10881 or -4 if something or other...
10882 NOTE: The API does not provide for ttinc() returning a special code
10883 upon timeout, but we need it. So for this we have a global variable,
10886 static int ttinctimo = 0; /* Yuk */
10889 ttinc(timo) int timo; {
10897 if (ttyfd < 0) return(-2); /* Not open. */
10899 is_tn = (xlocal && netconn && IS_TELNET()) ||
10900 (!xlocal && sstelnet);
10904 debug(F111,"ttinc","ttpush",ttpush);
10910 if (le_getchar(&ch) > 0) {
10911 debug(F111,"ttinc le_getchar","ch",ch);
10915 #endif /* TTLEBUF */
10921 #endif /* NETCMD */
10924 if ((timo <= 0) /* Untimed. */
10926 || (my_count > 0) /* Buffered char already waiting. */
10927 #endif /* MYREAD */
10930 /* Comm line failure returns -1 thru myread, so no &= 0377 */
10931 n = myread(); /* Wait for a character... */
10932 /* debug(F000,"ttinc MYREAD n","",n); */
10933 #ifdef CK_ENCRYPTION
10934 /* debug(F101,"ttinc u_encrypt","",TELOPT_U(TELOPT_ENCRYPTION)); */
10935 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
10937 ck_tn_decrypt(&ch,1);
10940 #endif /* CK_ENCRYPTION */
10943 if (ttpty && n < 0) {
10944 debug(F101,"ttinc error on pty","",n);
10948 #endif /* NETPTY */
10951 if ((n > -1) && is_tn)
10952 return((unsigned)(n & 0xff));
10954 #endif /* TNCODE */
10955 return(n < 0 ? n : (unsigned)(n & ttpmsk));
10959 while ((n = read(fd,&ch,1)) == 0) /* Wait for a character. */
10960 /* Shouldn't have to loop in ver 5A. */
10962 if (netconn) { /* Special handling for net */
10963 netclos(); /* If read() returns 0 it means */
10964 netconn = 0; /* the connection has dropped. */
10968 #endif /* NETCONN */
10970 /* debug(F101,"ttinc","",ch); */
10972 if ((n > 0) && is_tn) {
10973 #ifdef CK_ENCRYPTION
10974 if (TELOPT_U(TELOPT_ENCRYPTION)) {
10975 ck_tn_decrypt(&ch,1);
10978 #endif /* CK_ENCRYPTION */
10979 return((unsigned)(ch & 0xff));
10981 #endif /* TNCODE */
10982 return((n < 0) ? -4 : ((n == 0) ? -1 : (unsigned)(ch & ttpmsk)));
10983 #endif /* MYREAD */
10985 } else { /* Timed read */
10988 saval = signal(SIGALRM,timerh); /* Set up handler, save old one. */
10989 oldalarm = alarm(timo); /* Set alarm, save old one. */
10991 #ifdef CK_POSIX_SIG
10995 #endif /* CK_POSIX_SIG */
10996 ) { /* Timer expired */
10998 n = -1; /* set flag */
11001 n = myread(); /* If managing own buffer... */
11002 debug(F101,"ttinc myread","",n);
11005 n = read(fd,&ch,1); /* Otherwise call the system. */
11006 if (n == 0) n = -1;
11007 debug(F101,"ttinc read","",n);
11008 #endif /* MYREAD */
11010 #ifdef CK_ENCRYPTION
11011 if (TELOPT_U(TELOPT_ENCRYPTION) && n >= 0) {
11012 ck_tn_decrypt(&ch,1);
11014 #endif /* CK_ENCRYPTION */
11016 n = (unsigned) (ch & 0xff);
11018 n = (n < 0) ? -4 : -2; /* Special return codes. */
11020 ttimoff(); /* Turn off the timer */
11021 if (oldalarm > 0) {
11022 if (n == -1) /* and restore any previous alarm */
11024 if (oldalarm < 0) /* adjusted by our timeout interval */
11027 debug(F101,"ttinc restoring oldalarm","",oldalarm);
11033 if (n == -2) { /* read() returns 0 */
11034 netclos(); /* on network read failure */
11039 #endif /* NETCONN */
11041 if ((n > -1) && is_tn)
11042 return((unsigned)(n & 0xff));
11044 #endif /* TNCODE */
11045 /* Return masked char or neg. */
11046 return( (n < 0) ? n : (unsigned)(n & ttpmsk) );
11050 /* S N D B R K -- Send a BREAK signal of the given duration */
11054 sndbrk(int msec) { /* Argument is milliseconds */
11056 sndbrk(msec) int msec; {
11057 #endif /* CK_ANSIC */
11068 #endif /* ANYBSD */
11077 #endif /* BSDBREAK */
11078 #endif /* COHERENT */
11083 #endif /* BSDBREAK */
11084 #endif /* BELLV10 */
11088 #endif /* PROVX1 */
11090 debug(F101,"ttsndb ttyfd","",ttyfd);
11091 if (ttyfd < 0) return(-1); /* Not open. */
11094 return p9sndbrk(msec);
11098 if (ttpipe) /* Pipe */
11099 return(ttoc('\0'));
11100 #endif /* NETCMD */
11103 return(ttoc('\0'));
11104 #endif /* NETPTY */
11105 if (netconn) /* Send network BREAK */
11106 return(netbreak());
11107 #endif /* NETCONN */
11109 if (msec < 1 || msec > 5000) return(-1); /* Bad argument */
11111 #ifdef POSIX /* Easy in POSIX */
11114 debug(F111,"sndbrk POSIX",ckitoa(msec),(msec/375));
11116 x = tcsendbreak(ttyfd,msec / 375);
11117 debug(F111,"sndbrk tcsendbreak",ckitoa(errno),x);
11122 gtty(ttyfd,&ttbuf); /* Get current tty flags */
11123 spd = ttbuf.sg_ospeed; /* Save speed */
11124 ttbuf.sg_ospeed = B50; /* Change to 50 baud */
11125 stty(ttyfd,&ttbuf); /* ... */
11126 n = (int)strlen(brnuls); /* Send the right number of nulls */
11129 write(ttyfd,brnuls,n);
11130 ttbuf.sg_ospeed = spd; /* Restore speed */
11131 stty(ttyfd,&ttbuf); /* ... */
11135 sio_$control((short)ttyfd, sio_$send_break, msec, st);
11139 n = FWRITE; /* Flush output queue. */
11140 /* Watch out for int vs long problems in &n arg! */
11141 debug(F101,"sndbrk BSDBREAK","",msec);
11142 ioctl(ttyfd,TIOCFLUSH,&n); /* Ignore any errors.. */
11143 if (ioctl(ttyfd,TIOCSBRK,(char *)0) < 0) { /* Turn on BREAK */
11144 perror("Can't send BREAK");
11147 x = msleep(msec); /* Sleep for so many milliseconds */
11148 if (ioctl(ttyfd,TIOCCBRK,(char *)0) < 0) { /* Turn off BREAK */
11149 perror("BREAK stuck!!!");
11150 doexit(BAD_EXIT,-1); /* Get out, closing the line. */
11151 /* with bad exit status */
11157 No way to send a long BREAK in Sys V, so send a bunch of regular ones.
11158 (Actually, Sys V R4 is *supposed* to have the POSIX tcsendbreak() function,
11159 but there's no way for this code to know for sure.)
11161 debug(F101,"sndbrk ATTSV","",msec);
11163 for (n = 0; n < x; n++) {
11164 /* Reportedly the cast breaks this function on some systems */
11165 /* But then why was it here in the first place? */
11166 if (ioctl(ttyfd,TCSBRK, /* (char *) */ 0) < 0) {
11167 perror("Can't send BREAK");
11174 debug(F101,"sndbrk V7","",msec);
11175 return(genbrk(ttyfd,250)); /* Simulate a BREAK */
11177 debug(F101,"sndbrk catchall","",msec);
11178 ttoc(0);ttoc(0);ttoc(0);ttoc(0);
11181 #endif /* BSDBREAK */
11184 #endif /* PROVX1 */
11189 /* T T S N D B -- Send a BREAK signal */
11194 if (netconn && istncomport())
11195 return((tnsndb(275L) >= 0) ? 0 : -1);
11197 #endif /* TN_COMPORT */
11198 return(sndbrk(275));
11201 /* T T S N D L B -- Send a Long BREAK signal */
11206 if (netconn && istncomport())
11207 return((tnsndb(1800L) >= 0) ? 0 : -1);
11209 #endif /* TN_COMPORT */
11210 return(sndbrk(1500));
11213 /* M S L E E P -- Millisecond version of sleep(). */
11216 Call with number of milliseconds (thousandths of seconds) to sleep.
11217 Intended only for small intervals. For big ones, just use sleep().
11218 Highly system-dependent.
11219 Returns 0 always, even if it didn't work.
11222 /* Define MSLFTIME for systems that must use an ftime() loop. */
11223 #ifdef ANYBSD /* For pre-4.2 BSD versions */
11227 #endif /* ANYBSD */
11229 #ifdef TOWER1 /* NCR Tower OS 1.0 */
11231 #endif /* TOWER1 */
11233 #ifdef COHERENT /* Coherent... */
11234 #ifndef _I386 /* Maybe Coherent/386 should get this, too */
11235 #define MSLFTIME /* Opinions are divided */
11237 #endif /* COHERENT */
11242 /* Millisecond timer */
11244 static long msecbase = 0L; /* Unsigned long not portable */
11247 getmsec() { /* Milliseconds since base time */
11249 struct timezone xz;
11256 gettimeofday(&tv, NULL)
11258 gettimeofday(&tv, &tz)
11260 #endif /* GTODONEARG */
11263 if (msecbase == 0L) { /* First call, set base time. */
11264 msecbase = tv.tv_sec;
11265 debug(F101,"getmsec base","",msecbase);
11267 return(((tv.tv_sec - msecbase) * 1000L) + (tv.tv_usec / 1000L));
11269 #endif /* GETMSEC */
11270 #endif /* COMMENT */
11274 ttwait(fd, secs) int fd, secs; {
11282 if ((x = select(FD_SETSIZE,
11288 #endif /* HPUX1000 */
11292 debug(F101,"ttwait select errno","",errno);
11295 debug(F101,"ttwait OK","",errno);
11296 x = FD_ISSET(fd, &rfds);
11297 debug(F101,"ttwait select x","",x);
11301 #endif /* SELECT */
11306 Other possibilities here are:
11307 nanosleep(), reportedly defined in POSIX.4.
11308 sginap(), IRIX only (back to what IRIX version I don't know).
11315 #else /* BEOSORBEBOX */
11318 debug(F101,"msleep SELECT 1","",m);
11319 if (m <= 0) return(0);
11320 if (m >= 1000) { /* Catch big arguments. */
11323 if (m < 10) return(0);
11325 debug(F101,"msleep SELECT 2","",m);
11327 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, m );
11328 debug(F101,"msleep BELLV10 select","",x);
11329 #else /* BELLV10 */
11331 gettimeofday(&tv, &tz);
11336 if (gettimeofday(&tv) < 0)
11339 if (gettimeofday(&tv,NULL) < 0)
11342 if (gettimeofday(&tv, NULL) < 0) /* wonder what this does... */
11344 if (gettimeofday(&tv, &tz) < 0)
11345 #endif /* NOTIMEZONE */
11347 #endif /* GTODONEARG */
11349 t1 = tv.tv_sec; /* Seconds */
11350 #endif /* COHERENT */
11352 tv.tv_sec = 0; /* Use select() */
11353 tv.tv_usec = m * 1000L;
11355 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11356 debug(F101,"msleep BSD44 select","",x);
11359 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11360 debug(F101,"msleep __linux__ select","",x);
11361 #else /* __linux__ */
11363 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11364 debug(F101,"msleep BSD43 select","",x);
11367 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11368 debug(F101,"msleep QNX6 select","",x);
11371 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11372 debug(F101,"msleep QNX select","",x);
11375 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11376 debug(F101,"msleep COHERENT select","",x);
11377 #else /* COHERENT */
11378 #ifdef HPUX1000 /* 10.00 only, not 10.10 or later */
11379 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11380 debug(F101,"msleep HP-UX 10.00 select","",x);
11381 #else /* HPUX1000 */
11383 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11384 debug(F101,"msleep SVR4 select","",x);
11387 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11388 debug(F101,"msleep OSF40 select","",x);
11391 x = select( 0, (fd_set *)0, (fd_set *)0, (fd_set *)0, &tv );
11392 debug(F101,"msleep OSF40 select","",x);
11394 x = select( 0, (int *)0, (int *)0, (int *)0, &tv );
11395 debug(F101,"msleep catch-all select","",x);
11398 #endif /* HP1000 */
11400 #endif /* COHERENT */
11404 #endif /* __linux__ */
11406 #endif /* BELLV10 */
11409 #else /* Not SELECT */
11410 #ifdef CK_POLL /* We have poll() */
11411 struct pollfd pfd; /* Supply a valid address for poll() */
11413 #ifdef ODT30 /* But in SCO ODT 3.0 */
11414 #ifdef NAP /* we should use nap() instead */
11415 debug(F101,"msleep ODT 3.0 NAP","",m); /* because using poll() here */
11416 nap((long)m); /* seems to break dialing. */
11419 debug(F101,"msleep ODT 3.0 POLL","",m);
11424 debug(F101,"msleep POLL","",m);
11430 We could handle the above more cleanly by just letting nap() always
11431 take precedence over poll() in this routine, but there is no way to know
11432 whether that would break something else.
11435 #else /* Not POLL */
11438 "This routine is implemented using setitimer(2); it requires eight
11439 system calls...". In other words, it might take 5 minutes to sleep
11442 debug(F101,"msleep USLEEP","",m);
11443 if (m >= 1000) { /* Catch big arguments. */
11446 if (m < 10) return(0);
11448 usleep((unsigned int)(m * 1000));
11453 debug(F101,"msleep aegis","",m);
11455 dur.c2.low32 = 250 * m; /* one millisecond = 250 four microsecond ticks */
11456 time_$wait(time_$relative, dur, st);
11460 debug(F101,"msleep Venix","",m);
11461 if (m <= 0) return(0);
11462 sleep(-((m * 60 + 500) / 1000));
11466 debug(F101,"msleep NAP","",m);
11472 extern long times(); /* Or #include <times.h> ? */
11474 long t1, t2, tarray[4];
11476 char *cp = getenv("HZ");
11480 if (cp && (hertz = atoi(cp))) {
11481 CLOCK_TICK = 1000 / hertz;
11482 } else { /* probably single user mode */
11484 CLOCK_TICK = 1000 / HZ;
11487 /* HZ always exists in, for instance, SCO Xenix, so you don't have to
11488 * make special #ifdefs for XENIX here, like in ver 4F. Also, if you
11489 * have Xenix, you have should have nap(), so the best is to use -DNAP
11490 * in the makefile. Most systems have HZ.
11492 CLOCK_TICK = 17; /* 1/60 sec */
11494 printf("warning: environment variable HZ bad... using HZ=%d\r\n",
11495 1000 / CLOCK_TICK);
11500 debug(F101,"msleep ATTSV","",m);
11501 if (m <= 0) return(0);
11502 if (m >= 1000) { /* Catch big arguments. */
11505 if (m < 10) return(0);
11507 if ((t1 = times(tarray)) < 0) return(-1);
11509 if ((t2 = times(tarray)) < 0) return(-1);
11510 t3 = ((int)(t2 - t1)) * CLOCK_TICK;
11511 if (t3 > m) return(t3);
11513 #else /* Not ATTSV */
11514 #ifdef MSLFTIME /* Use ftime() loop... */
11516 debug(F101,"msleep MSLFTIME","",m);
11517 if (m <= 0) return(0);
11518 if (m >= 1000) { /* Catch big arguments. */
11521 if (m < 10) return(0);
11524 ftime(&ftp); /* void ftime() in QNX */
11526 if (ftime(&ftp) < 0) return(-1); /* Get base time. */
11528 t1 = ((ftp.time & 0xff) * 1000) + ftp.millitm;
11530 ftime(&ftp); /* Get current time and compare. */
11531 t3 = (((ftp.time & 0xff) * 1000) + ftp.millitm) - t1;
11532 if (t3 > m) return(0);
11535 /* This includes true POSIX, which has no way to do this. */
11536 debug(F101,"msleep busy loop","",m);
11537 if (m >= 1000) { /* Catch big arguments. */
11540 if (m < 10) return(0);
11542 if (m > 0) while (m > 0) m--; /* Just a dumb busy loop */
11544 #endif /* MSLFTIME */
11547 #endif /* PROVX1 */
11549 #endif /* CK_POLL */
11550 #endif /* SELECT */
11551 #endif /* BEOSORBEBOX */
11552 #endif /* USLEEP */
11556 /* R T I M E R -- Reset elapsed time counter */
11560 tcount = time( (time_t *) 0 );
11564 /* G T I M E R -- Get current value of elapsed time counter in seconds */
11569 x = (int) (time( (time_t *) 0 ) - tcount);
11570 debug(F101,"gtimer","",x);
11571 return( (x < 0) ? 0 : x );
11576 Floating-point timers. Require not only floating point support, but
11577 also gettimeofday().
11579 static struct timeval tzero;
11583 #ifdef GTODONEARG /* Account for Mot's definition */
11584 (VOID) gettimeofday(&tzero);
11586 (VOID) gettimeofday(&tzero, (struct timezone *)0);
11587 #endif /* GTODONEARG */
11592 struct timeval tnow, tdelta;
11597 #ifdef GTODONEARG /* Account for Mot's definition */
11598 (VOID) gettimeofday(&tnow);
11600 (VOID) gettimeofday(&tnow, (struct timezone *)0);
11601 #endif /* GTODONEARG */
11603 tdelta.tv_sec = tnow.tv_sec - tzero.tv_sec;
11604 tdelta.tv_usec = tnow.tv_usec - tzero.tv_usec;
11606 if (tdelta.tv_usec < 0) {
11608 tdelta.tv_usec += 1000000;
11610 s = (CKFLOAT) tdelta.tv_sec + ((CKFLOAT) tdelta.tv_usec / 1000000.0);
11615 sprintf(fpbuf,"%f",s);
11616 debug(F110,"gftimer",fpbuf,0);
11621 #endif /* GFTIMER */
11623 /* Z T I M E -- Return asctime()-format date/time string */
11625 NOTE: as a side effect of calling this routine, we can also set the
11626 following two variables, giving the micro- and milliseconds (fractions of
11627 seconds) of the clock time. Currently this is done only in BSD-based builds
11628 that use gettimeofday(). When these variables are not filled in, they are
11629 left with a value of -1L.
11631 static char asctmbuf[64];
11634 ztime(s) char **s; {
11638 The gettimeofday() method, which also sets ztmsec and ztusec, works for
11639 all GFTIMER builds. NOTE: ztmsec and ztusec are defined in ckcmai.c,
11640 and extern declarations for them are in ckcdeb.h; thus they are
11641 declared in this file by inclusion of ckcdeb.h.
11644 struct tm *localtime();
11650 debug(F100,"ztime s==NULL","",0);
11653 /* No 2nd arg in Motorola SV88 and some others */
11654 if (gettimeofday(&tv) > -1)
11658 if (gettimeofday(&tv,NULL) > -1)
11661 if (gettimeofday(&tv, NULL) > -1) /* wonder what this does... */
11663 if (gettimeofday(&tv, &tz) > -1)
11664 #endif /* NOTIMEZONE */
11666 #endif /* COHERENT */
11667 #endif /* GTODONEARG */
11668 { /* Fill in tm struct */
11669 ztusec = tv.tv_usec; /* Microseconds */
11670 ztmsec = ztusec / 1000L; /* Milliseconds */
11675 tp = localtime(&zz); /* Convert to local time */
11682 tp = localtime(&zz);
11686 { /* avoid unaligned access trap on 64-bit platforms */
11689 tp = localtime(&zz);
11693 tp = localtime((time_t *)&tv.tv_sec); /* Convert to local time */
11695 tp = localtime(&tv.tv_sec);
11696 #endif /* MACOSX */
11698 #endif /* HPUX1000 */
11702 s2 = asctime(tp); /* Convert result to ASCII string */
11703 asctmbuf[0] = '\0';
11704 if (s2) ckstrncpy(asctmbuf,s2,64);
11706 debug(F111,"ztime GFTIMER gettimeofday",*s,ztusec);
11709 #else /* Not GFTIMER */
11711 #undef ZTIMEV7 /* Which systems need to use */
11712 #ifdef COHERENT /* old UNIX Version 7 way... */
11714 #endif /* COHERENT */
11717 #endif /* TOWER1 */
11722 #endif /* ANYBSD */
11734 Prototypes are in <time.h>, included above.
11736 time_t clock_storage;
11737 clock_storage = time((void *) 0);
11739 *s = ctime(&clock_storage);
11740 debug(F110,"ztime: HPUX 10.20",*s,0);
11743 #ifdef ATTSV /* AT&T way */
11744 /* extern long time(); */ /* Theoretically these should */
11745 char *ctime(); /* already been dcl'd in <time.h> */
11746 time_t clock_storage;
11747 clock_storage = time(
11756 #endif /* IRIX60 */
11759 *s = ctime( &clock_storage );
11760 debug(F110,"ztime: ATTSV",*s,0);
11763 #ifdef PROVX1 /* Venix 1.0 way */
11768 debug(F110,"ztime: PROVX1",*s,0);
11771 #ifdef BSD42 /* 4.2BSD way */
11773 struct tm *localtime();
11775 gettimeofday(&tv, &tz);
11776 ztusec = tv.tv_usec;
11777 ztmsec = tv.tv_usec / 1000L;
11778 tp = localtime(&tv.tv_sec);
11781 debug(F111,"ztime: BSD42",*s,ztusec);
11784 #ifdef MINIX /* MINIX way */
11786 extern long time(); /* Already got these from <time.h> */
11787 extern char *ctime();
11788 #endif /* COMMENT */
11793 debug(F110,"ztime: MINIX",*s,0);
11796 #ifdef ZTIMEV7 /* The regular way */
11798 struct tm *localtime();
11800 long xclock; /* or unsigned long for BeBox? */
11802 tp = localtime(&xclock);
11805 debug(F110,"ztime: ZTIMEV7",*s,0);
11807 #else /* Catch-all for others... */
11809 *s = "Day Mon 00 00:00:00 0000\n"; /* Dummy in asctime() format */
11810 debug(F110,"ztime: catch-all",*s,0);
11812 #endif /* ZTIMEV7 */
11815 #endif /* PROVX1 */
11817 #endif /* HPUX1020 */
11818 #endif /* GFTIMER */
11821 /* C O N G M -- Get console terminal modes. */
11824 Saves initial console mode, and establishes variables for switching
11825 between current (presumably normal) mode and other modes.
11826 Should be called when program starts, but only after establishing
11827 whether program is in the foreground or background.
11828 Returns 1 if it got the modes OK, 0 if it did nothing, -1 on error.
11833 if (backgrd || !isatty(0)) { /* If in background. */
11834 cgmf = -1; /* Don't bother, modes are garbage. */
11837 if (cgmf > 0) return(0); /* Already did this. */
11838 debug(F100,"congm getting modes","",0); /* Need to do it. */
11840 ios_$inq_type_uid(ios_$stdin, conuid, st);
11841 if (st.all != status_$ok) {
11842 fprintf(stderr, "problem getting stdin objtype: ");
11845 concrp = (conuid == mbx_$uid);
11850 if ((fd = open(CTTNAM,2)) < 0) { /* Open controlling terminal */
11852 fprintf(stderr,"Error opening %s\n", CTTNAM);
11857 #endif /* COMMENT */
11861 #endif /* !BEBOX */
11862 #ifdef BSD44ORPOSIX
11863 if (tcgetattr(fd,&ccold) < 0) return(-1);
11864 if (tcgetattr(fd,&cccbrk) < 0) return(-1);
11865 if (tcgetattr(fd,&ccraw) < 0) return(-1);
11868 if (ioctl(fd,TCGETA,&ccold) < 0) return(-1);
11869 if (ioctl(fd,TCGETA,&cccbrk) < 0) return(-1);
11870 if (ioctl(fd,TCGETA,&ccraw) < 0) return(-1);
11872 cccbrk.c_line = 0; /* STTY line 0 for CDC VX/VE */
11873 if (ioctl(fd,TCSETA,&cccbrk) < 0) return(-1);
11874 ccraw.c_line = 0; /* STTY line 0 for CDC VX/VE */
11875 if (ioctl(fd,TCSETA,&ccraw) < 0) return(-1);
11879 if (ioctl(fd,TIOCGETP,&ccold) < 0) return(-1);
11880 if (ioctl(fd,TIOCGETP,&cccbrk) < 0) return(-1);
11881 if (ioctl(fd,TIOCGETP,&ccraw) < 0) return(-1);
11882 debug(F101,"cccbrk.sg_flags orig","", cccbrk.sg_flags);
11884 if (gtty(fd,&ccold) < 0) return(-1);
11885 if (gtty(fd,&cccbrk) < 0) return(-1);
11886 if (gtty(fd,&ccraw) < 0) return(-1);
11887 #endif /* BELLV10 */
11889 #endif /* BSD44ORPOSIX */
11890 #ifdef sony_news /* Sony NEWS */
11891 if (ioctl(fd,TIOCKGET,&km_con) < 0) { /* Get console Kanji mode */
11892 perror("congm error getting Kanji mode");
11893 debug(F101,"congm error getting Kanji mode","",0);
11894 km_con = -1; /* Make sure this stays undefined. */
11897 #endif /* sony_news */
11900 cgmf = 1; /* Flag that we got them. */
11906 congetbuf(x) int x; {
11908 n = CONBUFSIZ - (conbufp - conbuf); /* How much room left in buffer? */
11910 debug(F101,"congetbuf char loss","",x-n);
11913 x = read(0,conbufp,x);
11915 debug(F111,"congetbuf readahead",conbuf,x);
11919 /* C O N C B -- Put console in cbreak mode. */
11921 /* Returns 0 if ok, -1 if not */
11927 concb(esc) char esc;
11928 #endif /* CK_ANSIC */
11931 debug(F101,"concb constate","",constate);
11932 debug(F101,"concb cgmf","",cgmf);
11933 debug(F101,"concb backgrd","",backgrd);
11935 if (constate == CON_CB)
11938 if (cgmf < 1) /* Did we get console modes yet? */
11939 if (!backgrd) /* No, in background? */
11940 congm(); /* No, try to get them now. */
11941 if (cgmf < 1) /* Still don't have them? */
11942 return(0); /* Give up. */
11943 debug(F101,"concb ttyfd","",ttyfd);
11944 debug(F101,"concb ttfdflg","",ttfdflg);
11946 /* This breaks returning to prompt after protocol with "-l 0" */
11947 /* Commented out July 1998 */
11948 if (ttfdflg && ttyfd >= 0 && ttyfd < 3)
11950 #endif /* COMMENT */
11952 debug(F101,"concb isatty","",x);
11953 if (!x) return(0); /* Only when running on real ttys */
11954 debug(F101,"concb xsuspend","",xsuspend);
11955 if (backgrd) /* Do nothing if in background. */
11957 escchr = esc; /* Make this available to other fns */
11958 ckxech = 1; /* Program can echo characters */
11961 if (concrp) return(write(1, "\035\002", 2));
11962 if (conuid == input_pad_$uid) {pad_$raw(ios_$stdin, st); return(0);}
11967 #endif /* COHERENT */
11972 #ifndef SVORPOSIX /* BSD, V7, etc */
11973 debug(F101,"cccbrk.sg_flags concb 1","", cccbrk.sg_flags);
11974 debug(F101,"concb stty CBREAK","",0);
11975 cccbrk.sg_flags |= (CBREAK|CRMOD); /* Set to character wakeup, */
11976 cccbrk.sg_flags &= ~ECHO; /* no echo. */
11977 debug(F101,"cccbrk.sg_flags concb 2","", cccbrk.sg_flags);
11980 BSD stty() clears the console buffer. So if anything is waiting in it,
11981 we have to read it now to avoid losing it.
11988 x = ioctl(0,TIOCSETP,&cccbrk);
11990 x = stty(0,&cccbrk);
11991 debug(F101,"cccbrk.sg_flags concb x","", x);
11992 #endif /* BELLV10 */
11993 #else /* Sys V and POSIX */
11995 debug(F101,"concb cccbrk.c_flag","",cccbrk.c_lflag);
11997 /* Don't mess with IEXTEN */
11998 cccbrk.c_lflag &= ~(ICANON|ECHO);
12001 cccbrk.c_lflag &= ~(ICANON|ECHO);
12003 cccbrk.c_lflag &= ~(ICANON|ECHO|IEXTEN);
12004 #endif /* COHERENT */
12006 cccbrk.c_lflag |= ISIG; /* Allow signals in command mode. */
12007 cccbrk.c_iflag |= IGNBRK; /* But ignore BREAK signal */
12008 cccbrk.c_iflag &= ~BRKINT;
12011 debug(F100,"concb OXOS is defined","",0);
12012 cccbrk.c_lflag &= ~(ICANON|ECHO);
12013 cccbrk.c_cc[VDISCARD] = cccbrk.c_cc[VLNEXT] = CDISABLE;
12017 Believe it or not, in SCO UNIX, VSUSP is greater than NCC, and so this
12018 array reference is out of bounds. It's only a debug() call so who needs it.
12021 debug(F101,"concb c_cc[VSUSP]","",cccbrk.c_cc[VSUSP]);
12023 #endif /* COMMENT */
12025 debug(F101,"concb c_cc[0]","",cccbrk.c_cc[0]);
12026 cccbrk.c_cc[0] = 003; /* Interrupt char is Control-C */
12028 debug(F101,"concb c_cc[VINTR]","",cccbrk.c_cc[0]);
12029 cccbrk.c_cc[VINTR] = 003;
12032 cccbrk.c_cc[1] = escchr; /* escape during packet modes */
12034 cccbrk.c_cc[VQUIT] = escchr;
12037 cccbrk.c_cc[4] = 1;
12041 cccbrk.c_cc[VMIN] = 1;
12048 cccbrk.c_cc[5] = 0;
12051 cccbrk.c_cc[5] = 1;
12055 cccbrk.c_cc[VTIME] = 1;
12063 #ifdef BSD44ORPOSIX /* Set new modes */
12064 x = tcsetattr(0,TCSADRAIN,&cccbrk);
12065 #else /* ATTSV */ /* or the POSIX way */
12066 x = ioctl(0,TCSETAW,&cccbrk); /* the Sys V way */
12067 #endif /* BSD44ORPOSIX */
12068 #endif /* SVORPOSIX */
12072 #endif /* COHERENT */
12073 debug(F101,"concb x","",x);
12074 debug(F101,"concb errno","",errno);
12077 setbuf(stdout,NULL); /* Make console unbuffered. */
12078 debug(F100,"concb setbuf A","",0);
12084 setbuf(stdout,NULL); /* Make console unbuffered. */
12085 debug(F100,"concb setbuf B","",0);
12087 #endif /* NOSETBUF */
12089 #endif /* NONOSETBUF */
12093 if (kmem[CON] < 0) {
12094 qaddr[CON] = initrawq(0);
12095 if((kmem[CON] = open("/dev/kmem", 0)) < 0) {
12096 fprintf(stderr, "Can't read /dev/kmem in concb.\n");
12097 perror("/dev/kmem");
12108 debug(F101,"concb returns","",x);
12112 /* C O N B I N -- Put console in binary mode */
12114 /* Returns 0 if ok, -1 if not */
12120 conbin(esc) char esc;
12121 #endif /* CK_ANSIC */
12126 debug(F101,"conbin constate","",constate);
12128 if (constate == CON_BIN)
12131 if (!isatty(0)) return(0); /* only for real ttys */
12132 congm(); /* Get modes if necessary. */
12133 debug(F100,"conbin","",0);
12134 escchr = esc; /* Make this available to other fns */
12135 ckxech = 1; /* Program can echo characters */
12138 if (concrp) return(write(1, "\035\002", 2));
12139 if (conuid == input_pad_$uid) {
12140 pad_$raw(ios_$stdin, st);
12147 #endif /* COHERENT */
12155 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12158 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12160 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO|IEXTEN);
12161 #endif /* COHERENT */
12164 ccraw.c_lflag &= ~(ISIG|ICANON|ECHO);
12165 ccraw.c_cc[VDISCARD] = ccraw.c_cc[VLNEXT] = CDISABLE;
12167 ccraw.c_iflag |= IGNPAR;
12169 Note that for terminal sessions we disable Xon/Xoff flow control to allow
12170 the passage ^Q and ^S as data characters for EMACS, and to allow XMODEM
12171 transfers to work when C-Kermit is in the middle, etc. Hardware flow
12172 control, if in use, is not affected.
12176 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXANY|IXOFF
12179 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IUCLC|IXON|IXANY|IXOFF
12183 ccraw.c_iflag &= ~(IGNBRK|INLCR|IGNCR|ICRNL|IXON|IXOFF|INPCK|ISTRIP);
12185 ccraw.c_oflag &= ~OPOST;
12188 WHAT THE HECK WAS THIS FOR?
12189 The B9600 setting (obviously) prevents CONNECT from working at any
12190 speed other than 9600 when you are logged in to the 7300 on a serial
12191 line. Maybe some of the other flags are necessary -- if so, put back
12192 the ones that are needed. This code is supposed to work the same, no
12193 matter whether you are logged in to the 7300 on the real console device,
12194 or through a serial port.
12197 ccraw.c_cflag = CLOCAL | B9600 | CS8 | CREAD | HUPCL;
12198 #endif /* ATT7300 */
12199 #endif /* COMMENT */
12201 /*** Kermit used to put the console in 8-bit raw mode, but some users have
12202 *** pointed out that this should not be done, since some sites actually
12203 *** use terminals with parity settings on their Unix systems, and if we
12204 *** override the current settings and stop doing parity, then their terminals
12205 *** will display blotches for characters whose parity is wrong. Therefore,
12206 *** the following two lines are commented out (Larry Afrin, Clemson U):
12208 *** ccraw.c_cflag &= ~(PARENB|CSIZE);
12209 *** ccraw.c_cflag |= (CS8|CREAD);
12211 *** Sys III/V sites that have trouble with this can restore these lines.
12214 ccraw.c_cc[0] = 003; /* Interrupt char is Ctrl-C */
12216 ccraw.c_cc[VINTR] = 003;
12219 ccraw.c_cc[1] = escchr; /* Escape during packet mode */
12221 ccraw.c_cc[VQUIT] = escchr;
12228 ccraw.c_cc[VMIN] = 1;
12243 ccraw.c_cc[VTIME] = 1;
12251 #ifdef BSD44ORPOSIX
12252 x = tcsetattr(0,TCSADRAIN,&ccraw); /* Set new modes. */
12254 x = ioctl(0,TCSETAW,&ccraw);
12255 #endif /* BSD44ORPOSIX */
12256 #else /* Berkeley, etc. */
12257 x = conchk(); /* Because stty() is destructive */
12260 ccraw.sg_flags |= (RAW|TANDEM); /* Set rawmode, XON/XOFF (ha) */
12261 ccraw.sg_flags &= ~(ECHO|CRMOD); /* Set char wakeup, no echo */
12263 x = ioctl(0,TIOCSETP,&ccraw);
12265 x = stty(0,&ccraw);
12266 #endif /* BELLV10 */
12267 #endif /* SVORPOSIX */
12271 constate = CON_BIN;
12273 debug(F101,"conbin returns","",x);
12278 #endif /* COHERENT */
12283 /* C O N R E S -- Restore the console terminal */
12288 debug(F101,"conres cgmf","",cgmf);
12289 debug(F101,"conres constate","",constate);
12291 if (cgmf < 1) /* Do nothing if modes unchanged */
12293 if (constate == CON_RES)
12296 if (!isatty(0)) return(0); /* only for real ttys */
12297 debug(F100,"conres isatty ok","",0);
12298 ckxech = 0; /* System should echo chars */
12302 if (concrp) return(write(1, "\035\001", 2));
12303 if (conuid == input_pad_$uid) {
12304 pad_$cooked(ios_$stdin, st);
12305 constate = CON_RES;
12313 #ifdef BSD44ORPOSIX
12314 debug(F100,"conres restoring tcsetattr","",0);
12315 x = tcsetattr(0,TCSADRAIN,&ccold);
12318 debug(F100,"conres restoring ioctl","",0);
12319 x = ioctl(0,TCSETAW,&ccold);
12320 #else /* BSD, V7, and friends */
12321 #ifdef sony_news /* Sony NEWS */
12323 ioctl(0,TIOCKSET,&km_con); /* Restore console Kanji mode */
12324 #endif /* sony_news */
12326 debug(F100,"conres restoring stty","",0);
12327 x = conchk(); /* Because stty() is destructive */
12331 x = ioctl(0,TIOCSETP,&ccold);
12333 x = stty(0,&ccold);
12334 #endif /* BELLV10 */
12336 #endif /* BSD44ORPOSIX */
12339 constate = CON_RES;
12341 debug(F101,"conres returns","",x);
12345 /* C O N O C -- Output a character to the console terminal */
12352 #endif /* CK_ANSIC */
12356 if (inserver && !local)
12359 #ifdef CK_ENCRYPTION
12360 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12361 ck_tn_encrypt(&c,1);
12362 #endif /* CK_ENCRYPTION */
12366 return conwrite(&c,1);
12368 return(write(1,&c,1));
12372 /* C O N X O -- Write x characters to the console terminal */
12375 conxo(x,s) int x; char *s; {
12378 if (inserver && !local)
12379 return(ttol((CHAR *)s,x));
12381 #ifdef CK_ENCRYPTION
12382 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12383 ck_tn_encrypt(s,x);
12384 #endif /* CK_ENCRYPTION */
12388 return(conwrite(s,x));
12390 return(write(1,s,x));
12394 /* C O N O L -- Write a line to the console terminal */
12397 conol(s) char *s; {
12399 if (!s) s = ""; /* Always do this! */
12405 if (inserver && !local)
12406 return(ttol((CHAR *)s,len));
12408 #ifdef CK_ENCRYPTION
12409 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION)) {
12410 if (nxpacket < len) {
12416 len = len > 10240 ? len : 10240;
12417 xpacket = (char *)malloc(len);
12419 fprintf(stderr,"ttol malloc failure\n");
12424 memcpy(xpacket,s,len);
12426 ck_tn_encrypt(s,len);
12428 #endif /* CK_ENCRYPTION */
12432 return(conwrite(s,len));
12434 return(write(1,s,len));
12438 /* C O N O L A -- Write an array of lines to the console terminal */
12441 conola(s) char *s[]; {
12447 for (i = 0; ; i++) {
12449 if (!p) p = ""; /* Let's not dump core shall we? */
12453 if (inserver && !local)
12454 x = ttol((CHAR *)p,(int)strlen(p));
12464 /* C O N O L L -- Output a string followed by CRLF */
12467 conoll(s) char *s; {
12475 if (inserver && !local) {
12476 if (*s) ttol((CHAR *)s,(int)strlen(s));
12477 return(ttol(buf,2));
12483 #ifdef CK_ENCRYPTION
12484 if (inserver && TELOPT_ME(TELOPT_ENCRYPTION))
12485 ck_tn_encrypt(buf,2);
12486 #endif /* CK_ENCRYPTION */
12490 return(conwrite(buf, 2));
12492 return(write(1,buf,2));
12496 /* C O N C H K -- Return how many characters available at console */
12498 We could also use select() here to cover a few more systems that are not
12499 covered by any of the following, e.g. HP-UX 9.0x on the model 800.
12503 static int contyp = 0; /* +1 for isatty, -1 otherwise */
12505 if (contyp == 0) /* This prevents unnecessary */
12506 contyp = (isatty(0) ? 1 : -1); /* duplicated calls to isatty() */
12507 debug(F101,"conchk contyp","",contyp);
12508 if (backgrd || (contyp < 0))
12512 if (conbufn > 0) return(conbufn); /* use old count if nonzero */
12514 /* read in more characters */
12515 conbufn = ios_$get(ios_$stdin,
12516 ios_$cond_opt, conbuf, (long)sizeof(conbuf), st);
12517 if (st.all != status_$ok) conbufn = 0;
12522 if (inserver && !local)
12523 return(in_chk(1,ttyfd));
12526 return(in_chk(0,0));
12530 /* C O N I N C -- Get a character from the console */
12532 Call with timo > 0 to do a timed read, timo == 0 to do an untimed blocking
12533 read. Upon success, returns the character. Upon failure, returns -1.
12534 A timed read that does not complete within the timeout period returns -2.
12537 coninc(timo) int timo; {
12538 int n = 0; CHAR ch;
12541 if (conbufn > 0) { /* If something already buffered */
12543 return((unsigned)(*conbufp++ & 0xff));
12546 errno = 0; /* Clear this */
12548 if (inserver && !local) {
12551 return(ttinctimo ? -2 : -1);
12557 #ifdef aegis /* Apollo Aegis only... */
12558 debug(F101,"coninc timo","",timo);
12560 if (conchk() > 0) {
12562 return((unsigned)(*conbufp++ & 0xff));
12574 debug(F111,"ttinc","ttpush",ttpush);
12580 if (le_getchar(&ch) > 0) {
12581 debug(F111,"ttinc LocalEchoInBuf","ch",ch);
12586 #endif /* TTLEBUF */
12588 if (timo <= 0) { /* Untimed, blocking read. */
12589 while (1) { /* Keep trying till we get one. */
12590 n = read(0, &ch, 1); /* Read a character. */
12591 if (n == 0) continue; /* Shouldn't happen. */
12592 if (n > 0) { /* If read was successful, */
12594 #ifdef CK_ENCRYPTION
12595 debug(F100,"coninc decrypt 1","",0);
12596 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12597 ck_tn_decrypt(&ch,1);
12598 #endif /* CK_ENCRYPTION */
12600 return((unsigned)(ch & 0xff)); /* return the character. */
12603 /* Come here if read() returned an error. */
12605 debug(F101, "coninc(0) errno","",errno); /* Log the error. */
12608 #ifdef CIE /* CIE Regulus has no EINTR symbol? */
12614 This routine is used for several different purposes. In CONNECT mode, it is
12615 used to do an untimed, blocking read from the keyboard in the lower CONNECT
12616 fork. During local-mode file transfer, it reads a character from the
12617 console to interrupt the file transfer (like A for a status report, X to
12618 cancel a file, etc). Obviously, we don't want the reads in the latter case
12619 to be blocking, or the file transfer would stop until the user typed
12620 something. Unfortunately, System V does not allow the console device input
12621 buffer to be sampled nondestructively (e.g. by conchk()), so a kludge is
12622 used instead. During local-mode file transfer, the SIGQUIT signal is armed
12623 and trapped by esctrp(), and this routine pretends to have read the quit
12624 character from the keyboard normally. But, kludge or no kludge, the read()
12625 issued by this command, under System V only, can fail if a signal -- ANY
12626 signal -- is caught while the read is pending. This can occur not only when
12627 the user types the quit character, but also during telnet negotiations, when
12628 the lower CONNECT fork signals the upper one about an echoing mode change.
12629 When this happens, we have to post the read() again. This is apparently not
12630 a problem in BSD-based UNIX versions.
12632 if (errno == EINTR) /* Read interrupted. */
12633 if (conesc) { /* If by SIGQUIT, */
12634 conesc = 0; /* the conesc variable is set, */
12635 return(escchr); /* so return the escape character. */
12636 } else continue; /* By other signal, try again. */
12639 This might be dangerous, but let's do this on non-System V versions too,
12640 since at least one SunOS 4.1.2 user complains of immediate disconnections
12641 upon first making a TELNET connection.
12643 if (errno == EINTR) /* Read interrupted. */
12645 #endif /* SVORPOSIX */
12647 if (errno == EINTR) /* Read interrupted. */
12650 return(-1); /* Error */
12654 if (deblog && timo <= 0) {
12655 debug(F100,"coninc timeout logic error","",0);
12660 /* Timed read... */
12662 saval = signal(SIGALRM,timerh); /* Set up timeout handler. */
12663 xx = alarm(timo); /* Set the alarm. */
12664 debug(F101,"coninc alarm set","",timo);
12666 #ifdef CK_POSIX_SIG
12670 #endif /* CK_POSIX_SIG */
12671 ) /* The read() timed out. */
12672 n = -2; /* Code for timeout. */
12674 n = read(0, &ch, 1);
12675 ttimoff(); /* Turn off timer */
12676 if (n > 0) { /* Got character OK. */
12678 #ifdef CK_ENCRYPTION
12679 debug(F100,"coninc decrypt 2","",0);
12680 if (inserver && !local && TELOPT_U(TELOPT_ENCRYPTION))
12681 ck_tn_decrypt(&ch,1);
12682 #endif /* CK_ENCRYPTION */
12684 return((unsigned)(ch & 0xff)); /* Return it. */
12687 read() returned an error. Same deal as above, but without the loop.
12689 debug(F101, "coninc(timo) n","",n);
12690 debug(F101, "coninc(timo) errno","",errno);
12693 if (n == -1 && errno == EINTR && conesc != 0) {
12695 return(escchr); /* User entered escape character. */
12697 #endif /* SVORPOSIX */
12698 if (n == 0 && errno > 0) { /* It's an error */
12701 #endif /* ! OXOS */
12705 /* C O N G K S -- Console Get Keyboard Scancode */
12709 This function needs to be filled in with the various system-dependent
12710 system calls used by SUNOS, NeXT OS, Xenix, Aviion, etc, to read a full
12711 keyboard scan code. Unfortunately there aren't any.
12714 congks(timo) int timo; {
12717 if (inserver && !local)
12718 return(ttinc(timo));
12721 return(coninc(timo));
12723 #endif /* congks */
12727 /* A T T D I A L -- Dial up the remote system using internal modem
12728 * Purpose: to open and dial a number on the internal modem available on the
12729 * ATT7300 UNIX PC. Written by Joe Doupnik. Superceeds version written by
12730 * Richard E. Hill, Dickinson, TX. which employed dial(3c).
12731 * Uses information in <sys/phone.h> and our status int attmodem.
12733 attdial(ttname,speed,telnbr) char *ttname,*telnbr; long speed; {
12736 attmodem &= ~ISMODEM; /* modem not in use yet */
12737 /* Ensure O_NDELAY is set, else i/o traffic hangs */
12738 /* We turn this flag off once the dial is complete */
12739 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) | O_NDELAY);
12741 /* Condition line, check availability & DATA mode, turn on speaker */
12742 if (ioctl(ttyfd,PIOCOFFHOOK, &dialer) == -1) {
12743 printf("cannot access phone\n");
12747 ioctl(ttyfd,PIOCGETP,&dialer); /* get phone dialer parameters */
12749 if (dialer.c_lineparam & VOICE) { /* phone must be in DATA mode */
12750 printf(" Should not dial with modem in VOICE mode.\n");
12751 printf(" Exit Kermit, switch to DATA and retry call.\n");
12755 #ifdef ATTTONED /* Old way, tone dialing only. */
12756 dialer.c_lineparam = DATA | DTMF; /* Dial with tones, */
12757 dialer.c_lineparam &= ~PULSE; /* not with pulses. */
12759 /* Leave current pulse/tone state alone. */
12760 /* But what about DATA? Add it back if you have trouble. */
12761 /* sys/phone says you get DATA automatically by opening device RDWR */
12763 dialer.c_waitdialtone = 5; /* wait 5 sec for dialtone */
12765 dialer.c_feedback = SPEAKERON|NORMSPK|RINGON; /* control speaker */
12767 /* sys/phone says RINGON used only for incoming voice calls */
12768 dialer.c_feedback &= ~(SOFTSPK|LOUDSPK);
12769 dialer.c_feedback |= SPEAKERON|NORMSPK;
12771 dialer.c_waitflash = 500; /* 0.5 sec flash hook */
12772 if(ioctl(ttyfd,PIOCSETP,&dialer) == -1) { /* set phone parameters */
12773 printf("Cannot set modem characteristics\n");
12777 ioctl(ttyfd,PIOCRECONN,0); /* Turns on speaker for pulse */
12780 fprintf(stderr,"Phone line status. line_par:%o dialtone_wait:%o \
12781 line_status:%o feedback:%o\n",
12782 dialer.c_lineparam, dialer.c_waitdialtone,
12783 dialer.c_linestatus, dialer.c_feedback);
12786 attmodem |= ISMODEM; /* modem is now in-use */
12788 for (telnum = telnbr; *telnum != '\0'; telnum++) /* dial number */
12790 /* Tone dialing only */
12791 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
12792 perror("Error in dialing");
12796 #else /* Allow Pulse or Tone dialing */
12798 case 't': case 'T': case '%': /* Tone dialing requested */
12799 dialer.c_lineparam |= DTMF;
12800 dialer.c_lineparam &= ~PULSE;
12801 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
12802 printf("Cannot set modem to tone dialing\n");
12807 case 'd': case 'D': case 'p': case 'P': case '^':
12808 dialer.c_lineparam |= PULSE;
12809 dialer.c_lineparam &= ~DTMF;
12810 if (ioctl(ttyfd,PIOCSETP,&dialer) == -1) {
12811 printf("Cannot set modem to pulse dialing\n");
12817 if (ioctl(ttyfd,PIOCDIAL,telnum) != 0) {
12818 perror("Dialing error");
12826 ioctl(ttyfd,PIOCDIAL,"@"); /* terminator for data call */
12827 do { /* wait for modems to Connect */
12828 if (ioctl(ttyfd,PIOCGETP,&dialer) != 0) { /* get params */
12829 perror("Cannot get modems to connect");
12833 } while ((dialer.c_linestatus & MODEMCONNECTED) == 0);
12834 /* Turn off O_NDELAY flag now. */
12835 fcntl(ttyfd, F_SETFL, fcntl(ttyfd, F_GETFL, 0) & ~O_NDELAY);
12836 signal(SIGHUP, sighup); /* hangup on loss of carrier */
12837 return(0); /* return success */
12841 Offgetty, ongetty functions. These function get the 'getty(1m)' off
12842 and restore it to the indicated line. Shell's return codes are:
12843 0: Can't do it. Probably a user logged on.
12844 1: No need. No getty on that line.
12845 2: Done, you should restore the getty when you're done.
12846 DOGETY System(3), however, returns them as 0, 256, 512, respectively.
12847 Thanks to Kevin O'Gorman, Anarm Software Systems.
12849 getoff.sh looks like: geton.sh looks like:
12850 setgetty $1 0 setgetty $1 1
12856 /* O F F G E T T Y -- Turn off getty(1m) for the communications tty line
12857 * and get status so it can be restarted after the line is hung up.
12860 offgetty(ttname) char *ttname; {
12862 while (*ttname != '\0') ttname++; /* seek terminator of path */
12863 ttname -= 3; /* get last 3 chars of name */
12864 sprintf(temp,"/usr/bin/getoff.sh %s",ttname);
12865 return(zsyscmd(temp));
12868 /* O N G E T T Y -- Turn on getty(1m) for the communications tty line */
12871 ongetty(ttname) char *ttname; {
12873 while (*ttname != '\0') ttname++; /* comms tty path name */
12875 sprintf(temp,"/usr/bin/geton.sh %s",ttname);
12876 return(zsyscmd(temp));
12878 #endif /* ATT7300 */
12880 /* T T S C A R R -- Set ttcarr variable, controlling carrier handling.
12882 * 0 = Off: Always ignore carrier. E.g. you can connect without carrier.
12883 * 1 = On: Heed carrier, except during dialing. Carrier loss gives disconnect.
12884 * 2 = Auto: For "modem direct": The same as "Off".
12885 * For real modem types: Heed carrier during connect, but ignore
12886 * it anytime else. Compatible with pre-5A C-Kermit versions.
12888 * As you can see, this setting does not affect dialing, which always ignores
12889 * carrier (unless there is some special exception for some modem type). It
12890 * does affect ttopen() if it is set before ttopen() is used. This setting
12891 * takes effect on the next call to ttopen()/ttpkt()/ttvt(). And they are
12892 * (or should be) always called before any communications is tried, which
12893 * means that, practically speaking, the effect is immediate.
12895 * Of course, nothing of this applies to remote mode (xlocal = 0).
12897 * Someone has yet to uncover how to manipulate the carrier in the BSD
12898 * environment (or any non-termio using environment). Until that time, this
12899 * will simply be a no-op for BSD.
12901 * Note that in previous versions, the carrier was most often left unchanged
12902 * in ttpkt()/ttvt() unless they were called with FLO_DIAL or FLO_DIAX. This
12903 * has changed. Now it is controlled by ttcarr in conjunction with these
12907 ttscarr(carrier) int carrier; {
12909 debug(F101, "ttscarr","",ttcarr);
12913 /* C A R R C T L -- Set tty modes for carrier treatment.
12915 * Sets the appropriate bits in a termio or sgttyb struct for carrier control
12916 * (actually, there are no bits in sgttyb for that), or performs any other
12917 * operations needed to control this on the current system. The function does
12918 * not do the actual TCSETA or stty, since often we want to set other bits too
12919 * first. Don't call this function when xlocal is 0, or the tty is not opened.
12921 * We don't know how to do anything like carrier control on non-ATTSV systems,
12922 * except, apparently, ultrix. See above. It is also known that this doesn't
12923 * have much effect on a Xenix system. For Xenix, one should switch back and
12924 * forth between the upper and lower case device files. Maybe later.
12925 * Presently, Xenix will stick to the mode it was opened with.
12927 * carrier: 0 = ignore carrier, 1 = require carrier.
12928 * The current state is saved in curcarr, and checked to save labour.
12932 #ifdef BSD44ORPOSIX
12933 carrctl(ttpar, carrier) struct termios *ttpar; int carrier;
12935 carrctl(ttpar, carrier) struct termio *ttpar; int carrier;
12936 #endif /* BSD44ORPOSIX */
12938 debug(F101, "carrctl","",carrier);
12940 ttpar->c_cflag &= ~CLOCAL;
12942 ttpar->c_cflag |= CLOCAL;
12945 #else /* Berkeley, V7, et al... */
12947 carrctl(ttpar, carrier) struct sgttyb *ttpar; int carrier; {
12948 debug(F101, "carrctl","",carrier);
12949 if (carrier == curcarr)
12955 Old code from somebody at DEC that tends to get stuck, time out, etc.
12958 ioctl(ttyfd, TIOCMODEM, &temp);
12959 ioctl(ttyfd, TIOCHPCL, 0);
12961 /* (According to the manuals, TIOCNCAR should be preferred */
12962 /* over TIOCNMODEM...) */
12963 ioctl(ttyfd, TIOCNMODEM, &temp);
12967 New code from Jamie Watson that, he says, eliminates the problems.
12970 ioctl(ttyfd, TIOCCAR);
12971 ioctl(ttyfd, TIOCHPCL);
12973 ioctl(ttyfd, TIOCNCAR);
12975 #endif /* COMMENT */
12976 #endif /* ultrix */
12979 #endif /* SVORPOSIX */
12982 /* T T G M D M -- Get modem signals */
12984 Looks for RS-232 modem signals, and returns those that are on in as its
12985 return value, in a bit mask composed of the BM_xxx values defined in ckcdeb.h.
12988 -2 if the communication device does not have modem control (e.g. telnet)
12990 >= 0 on success, with a bit mask containing the modem signals that are on.
12994 Define the symbol K_MDMCTL if we have Sys V R3 / 4.3 BSD style
12995 modem control, namely the TIOCMGET ioctl.
13004 #endif /* SUNOS4 */
13007 SCO OpenServer R5.0.4. The TIOCMGET definition is hardwired in because it
13008 is skipped in termio.h when _POSIX_SOURCE is defined. But _POSIX_SOURCE
13009 must be defined in order to get the high serial speeds that are new to
13010 5.0.4. However, the regular SCO drivers do not implement TIOCMGET, so the
13011 ioctl() returns -1 with errno 22 (invalid function). But third-party
13012 drivers, e.g. for Digiboard, do implement it, and so it should work on ports
13013 driven by those drivers.
13017 #define TIOCMGET (('t'<<8)|29)
13018 #endif /* TIOCMGET */
13019 #endif /* SCO_OSR504 */
13022 /* Because POSIX strictness in <sys/termio.h> won't let us see these. */
13024 #define TIOCM_DTR 0x0002 /* data terminal ready */
13025 #define TIOCM_RTS 0x0004 /* request to send */
13026 #define TIOCM_CTS 0x0020 /* clear to send */
13027 #define TIOCM_CAR 0x0040 /* carrier detect */
13028 #define TIOCM_RNG 0x0080 /* ring */
13029 #define TIOCM_DSR 0x0100 /* data set ready */
13030 #define TIOCM_CD TIOCM_CAR
13031 #define TIOCM_RI TIOCM_RNG
13032 #endif /* TIOCM_DTR */
13033 #endif /* CK_SCOV5 */
13040 #endif /* TIOCMGET */
13043 "A serial communication program that can't read modem signals
13044 is like a car without windows."
13050 #include <sys/qioctl.h>
13052 unsigned long y, mdmbits[2];
13055 if (xlocal && ttyfd < 0)
13059 if (netconn) { /* Network connection */
13061 if (istncomport()) {
13065 #endif /* TN_COMPORT */
13066 return(-2); /* No modem signals */
13068 #endif /* NETCONN */
13071 if (ttpipe) return(-2);
13072 #endif /* NETCMD */
13074 if (ttpty) return(-2);
13075 #endif /* NETPTY */
13080 * From <sys/qioctl.h>:
13082 * SERIAL devices (all Dev.ser versions)
13083 * 0 : DTR 8 = Data Bits 0 16 - reserved 24 - reserved
13084 * 1 : RTS 9 = Data Bits 1 17 - reserved 25 - reserved
13085 * 2 = Out 1 10 = Stop Bits 18 - reserved 26 - reserved
13086 * 3 = Int Enable 11 = Par Enable 19 - reserved 27 - reserved
13087 * 4 = Loop 12 = Par Even 20 = CTS 28 - reserved
13088 * 5 - reserved 13 = Par Stick 21 = DSR 29 - reserved
13089 * 6 - reserved 14 : Break 22 = RI 30 - reserved
13090 * 7 - reserved 15 = 0 23 = CD 31 - reserved
13093 x = qnx_ioctl(ttyfd, QCTL_DEV_CTL, &mdmbits[0], 8, &mdmbits[0], 4);
13094 debug(F101,"ttgmdm qnx_ioctl","",x);
13095 debug(F101,"ttgmdm qnx_ioctl errno","",errno);
13097 debug(F101,"ttgmdm qnx_ioctl mdmbits[0]","",mdmbits[0]);
13098 debug(F101,"ttgmdm qnx_ioctl mdmbits[1]","",mdmbits[1]);
13100 if (y & 0x000001L) z |= BM_DTR; /* Bit 0 */
13101 if (y & 0x000002L) z |= BM_RTS; /* Bit 1 */
13102 if (y & 0x100000L) z |= BM_CTS; /* Bit 20 */
13103 if (y & 0x200000L) z |= BM_DSR; /* Bit 21 */
13104 if (y & 0x400000L) z |= BM_RNG; /* Bit 22 */
13105 if (y & 0x800000L) z |= BM_DCD; /* Bit 23 */
13106 debug(F101,"ttgmdm qnx result","",z);
13107 debug(F110,"ttgmdm qnx CD = ",(z & BM_DCD) ? "On" : "Off", 0);
13112 #ifdef HPUX /* HPUX has its own way */
13115 #ifdef HPUX10 /* Modem flag word */
13116 mflag y; /* mflag typedef'd in <sys/modem.h> */
13124 unsigned long y; /* Not sure about pre-8.0... */
13127 #endif /* HPUX10 */
13129 if (xlocal && ttyfd < 0)
13133 if (netconn) { /* Network connection */
13135 if (istncomport()) {
13139 #endif /* TN_COMPORT */
13140 return(-2); /* No modem signals */
13142 #endif /* NETCONN */
13145 if (ttpipe) return(-2);
13146 #endif /* NETCMD */
13148 if (ttpty) return(-2);
13149 #endif /* NETPTY */
13151 if (xlocal) /* Get modem signals */
13152 x = ioctl(ttyfd,MCGETA,&y);
13154 x = ioctl(0,MCGETA,&y);
13155 if (x < 0) return(-1);
13156 debug(F101,"ttgmdm","",y);
13158 z = 0; /* Initialize return value */
13160 /* Now set bits for each modem signal that is reported to be on. */
13163 /* Clear To Send */
13164 debug(F101,"ttgmdm HPUX CTS","",y & MCTS);
13165 if (y & MCTS) z |= BM_CTS;
13168 /* Data Set Ready */
13169 debug(F101,"ttgmdm HPUX DSR","",y & MDSR);
13170 if (y & MDSR) z |= BM_DSR;
13174 debug(F101,"ttgmdm HPUX DCD","",y & MDCD);
13175 if (y & MDCD) z |= BM_DCD;
13178 /* Ring Indicate */
13179 debug(F101,"ttgmdm HPUX RI","",y & MRI);
13180 if (y & MRI) z |= BM_RNG;
13183 /* Data Terminal Ready */
13184 debug(F101,"ttgmdm HPUX DTR","",y & MDTR);
13185 if (y & MDTR) z |= BM_DTR;
13188 /* Request To Send */
13189 debug(F101,"ttgmdm HPUX RTS","",y & MRTS);
13190 if (y & MRTS) z |= BM_RTS;
13199 Note, TIOCMGET might already have been defined in <sys/ioctl.h> or elsewhere.
13200 If not, we try including <sys/ttycom.h> -- if this blows up then more ifdefs
13204 #include <sys/ttycom.h>
13205 #endif /* TIOCMGET */
13209 debug(F100,"ttgmdm K_MDMCTL defined","",0);
13212 if (netconn) { /* Network connection */
13214 if (istncomport()) {
13218 #endif /* TN_COMPORT */
13219 return(-2); /* No modem signals */
13221 #endif /* NETCONN */
13224 if (ttpipe) return(-2);
13225 #endif /* NETCMD */
13227 if (ttpty) return(-2);
13228 #endif /* NETPTY */
13230 if (xlocal && ttyfd < 0)
13234 x = ioctl(ttyfd,TIOCMGET,&y); /* Get modem signals. */
13236 x = ioctl(0,TIOCMGET,&y);
13237 debug(F101,"ttgmdm TIOCMGET ioctl","",x);
13239 debug(F101,"ttgmdm errno","",errno);
13242 debug(F101,"ttgmdm bits","",y);
13244 z = 0; /* Initialize return value. */
13246 /* Clear To Send */
13247 if (y & TIOCM_CTS) z |= BM_CTS;
13248 debug(F101,"ttgmdm TIOCM_CTS defined","",TIOCM_CTS);
13250 debug(F100,"ttgmdm TIOCM_CTS not defined","",0);
13253 /* Data Set Ready */
13254 if (y & TIOCM_DSR) z |= BM_DSR;
13255 debug(F101,"ttgmdm TIOCM_DSR defined","",TIOCM_DSR);
13257 debug(F100,"ttgmdm TIOCM_DSR not defined","",0);
13261 if (y & TIOCM_CAR) z |= BM_DCD;
13262 debug(F101,"ttgmdm TIOCM_CAR defined","",TIOCM_CAR);
13264 debug(F100,"ttgmdm TIOCM_CAR not defined","",0);
13267 /* Ring Indicate */
13268 if (y & TIOCM_RNG) z |= BM_RNG;
13269 debug(F101,"ttgmdm TIOCM_RNG defined","",TIOCM_RNG);
13271 debug(F100,"ttgmdm TIOCM_RNG not defined","",0);
13274 /* Data Terminal Ready */
13275 if (y & TIOCM_DTR) z |= BM_DTR;
13276 debug(F101,"ttgmdm TIOCM_DTR defined","",TIOCM_DTR);
13278 debug(F100,"ttgmdm TIOCM_DTR not defined","",0);
13281 /* Request To Send */
13282 if (y & TIOCM_RTS) z |= BM_RTS;
13283 debug(F101,"ttgmdm TIOCM_RTS defined","",TIOCM_RTS);
13285 debug(F100,"ttgmdm TIOCM_RTS not defined","",0);
13290 #else /* !K_MDMCTL catch-All */
13292 debug(F100,"ttgmdm K_MDMCTL not defined","",0);
13294 debug(F100,"ttgmdm TIOCMGET defined","",0);
13296 debug(F100,"ttgmdm TIOCMGET not defined","",0);
13297 #endif /* TIOCMGET */
13299 debug(F100,"ttgmdm _SVID3 defined","",0);
13301 debug(F100,"ttgmdm _SVID3 not defined","",0);
13302 #endif /* _SVID3 */
13305 if (netconn) { /* Network connection */
13307 if (istncomport()) {
13311 #endif /* TN_COMPORT */
13312 return(-2); /* No modem signals */
13314 #endif /* NETCONN */
13317 if (ttpipe) return(-2);
13318 #endif /* NETCMD */
13320 if (ttpty) return(-2);
13321 #endif /* NETPTY */
13323 return(-3); /* Sorry, I don't know how... */
13325 #endif /* K_MDMCTL */
13330 /* P S U S P E N D -- Put this process in the background. */
13333 Call with flag nonzero if suspending is allowed, zero if not allowed.
13334 Returns 0 on apparent success, -1 on failure (flag was zero, or
13335 kill() returned an error code.
13338 psuspend(flag) int flag; {
13341 extern int rtu_bug;
13344 if (flag == 0) return(-1);
13351 The big question here is whether job control is *really* supported.
13352 There's no way Kermit can know for sure. The fact that SIGTSTP is
13353 defined does not guarantee the Unix kernel supports it, and the fact
13354 that the Unix kernel supports it doesn't guarantee that the user's
13355 shell (or other process that invoked Kermit) supports it.
13360 if (kill(0,SIGSTOP) < 0
13362 /* Let's try this for MIPS too. */
13363 && kill(getpid(),SIGSTOP) < 0
13365 ) { /* If job control, suspend the job */
13367 debug(F101,"psuspend error","",errno);
13370 debug(F100,"psuspend ok","",0);
13374 #endif /* SIGTSTP */
13379 setuid package, by Kristoffer Eriksson, with contributions from Dean
13383 /* The following is for SCO when CK_ANSILIBS is defined... */
13386 #ifndef NOGETID_PROTOS
13387 #define NOGETID_PROTOS
13388 #endif /* NOGETID_PROTOS */
13389 #endif /* CK_ANSILIBS */
13390 #endif /* M_UNIX */
13392 #ifndef _POSIX_SOURCE
13399 #ifndef NOGETID_PROTOS
13400 extern UID_T getuid(), geteuid(), getreuid();
13401 extern GID_T getgid(), getegid(), getregid();
13402 #endif /* NOGETID_PROTOS */
13404 extern UID_T getreuid();
13405 extern GID_T getregid();
13406 #endif /* COHERENT */
13408 #endif /* sequent */
13409 #endif /* PS2AIX10 */
13411 #endif /* SUNOS4 */
13412 #endif /* _POSIX_SOURCE */
13415 Subject: Set-user-id
13416 To: fdc@watsun.cc.columbia.edu (Frank da Cruz)
13417 Date: Sat, 21 Apr 90 4:48:25 MES
13418 From: Kristoffer Eriksson <ske@pkmab.se>
13420 This is a set of functions to be used in programs that may be run set-user-id
13421 and/or set-group-id. They handle both the case where the program is not run
13422 with such privileges (nothing special happens then), and the case where one
13423 or both of these set-id modes are used. The program is made to run with the
13424 user's real user and group ids most of the time, except for when more
13425 privileges are needed. Don't set-user-id to "root".
13427 This works on System V and POSIX. In BSD, it depends on the
13428 "saved-set-user-id" feature.
13431 #define UID_ROOT 0 /* Root user and group ids */
13435 The following code defines the symbol SETEUID for UNIX systems based
13436 on BSD4.4 (either -Encumbered or -Lite). This program will then use
13437 seteuid() and setegid() instead of setuid() and setgid(), which still
13438 don't allow arbitrary switching. It also avoids setreuid() and
13439 setregid(), which are included in BSD4.4 for compatibility only, are
13440 insecure, and print warnings to stderr under at least one system (NetBSD
13441 1.0). Note that POSIX systems should still use setuid() and setgid();
13442 the seteuid() and setegid() functions are BSD4.4 extensions to the
13443 POSIX model. Mike Long <mike.long@analog.com>, 8/94.
13450 The following construction automatically defines the symbol SETREUID for
13451 UNIX versions based on Berkeley Unix 4.2 and 4.3. If this symbol is
13452 defined, then this program will use getreuid() and getregid() calls in
13453 preference to getuid() and getgid(), which in Berkeley-based Unixes do
13454 not allow arbitrary switching back and forth of real & effective uid.
13455 This construction also allows -DSETREUID to be put on the cc command line
13456 for any system that has and wants to use setre[ug]id(). It also prevents
13457 automatic definition of SETREUID if -DNOSETREU is included on the cc
13458 command line (or otherwise defined).
13460 #ifdef FT18 /* None of this for Fortune. */
13471 #endif /* SETEUID */
13472 #endif /* NOSETREU */
13473 #endif /* SETREUID */
13474 #endif /* !BSD41 */
13475 #endif /* !BSD29 */
13476 #endif /* ANYBSD */
13478 /* Variables for user and group IDs. */
13480 static UID_T realuid = (UID_T) -1, privuid = (UID_T) -1;
13481 static GID_T realgid = (GID_T) -1, privgid = (GID_T) -1;
13484 /* P R I V _ I N I -- Initialize privileges package */
13486 /* Called as early as possible in a set-uid or set-gid program to store the
13487 * set-to uid and/or gid and step down to the users real uid and gid. The
13488 * stored id's can be temporarily restored (allowed in System V) during
13489 * operations that require the privilege. Most of the time, the program
13490 * should execute in unpriviliged state, to not impose any security threat.
13492 * Note: Don't forget that access() always uses the real id:s to determine
13493 * file access, even with privileges restored.
13495 * Returns an error mask, with error values or:ed together:
13496 * 1 if setuid() fails,
13497 * 2 if setgid() fails, and
13498 * 4 if the program is set-user-id to "root", which can't be handled.
13500 * Only the return value 0 indicates real success. In case of failure,
13501 * those privileges that could be reduced have been, at least, but the
13502 * program should be aborted none-the-less.
13504 * Also note that these functions do not expect the uid or gid to change
13505 * without their knowing. It may work if it is only done temporarily, but
13506 * you're on your own.
13512 #ifndef HAVE_BAUDBOY
13514 /* Save real ID:s. */
13515 realuid = getuid();
13516 realgid = getgid();
13518 /* Save current effective ID:s, those set to at program exec. */
13519 privuid = geteuid();
13520 privgid = getegid();
13522 /* If running set-uid, go down to real uid, otherwise remember that
13523 * no privileged uid is available.
13527 * 1) If the real uid is already "root" and the set-uid uid (the
13528 * initial effective uid) is not "root", then we would have trouble
13529 * if we went "down" to "root" here, and then temporarily back to the
13530 * set-uid uid (not "root") and then again tried to become "root". I
13531 * think the "saved set-uid" is lost when changing uid from effective
13532 * uid "root", which changes all uid, not only the effective uid. But
13533 * in this situation, we can simply go to "root" and stay there all
13534 * the time. That should give sufficient privilege (understatement!),
13535 * and give the right uids for subprocesses.
13537 * 2) If the set-uid (the initial effective uid) is "root", and we
13538 * change uid to the real uid, we can't change it back to "root" when
13539 * we need the privilege, for the same reason as in 1). Thus, we can't
13540 * handle programs that are set-user-id to "root" at all. The program
13541 * should be stopped. Use some other uid. "root" is probably too
13542 * privileged for such things, anyway. (The uid is reverted to the
13543 * real uid until termination.)
13545 * These two exceptions have the effect that the "root" uid will never
13546 * be one of the two uids that are being switched between, which also
13547 * means we don't have to check for such cases in the switching
13550 * Note that exception 1) is handled by these routines (by constantly
13551 * running with uid "root", while exception 2) is a serious error, and
13552 * is not provided for at all in the switching functions.
13554 if (realuid == privuid)
13555 privuid = (UID_T) -1; /* Not running set-user-id. */
13557 /* If running set-gid, go down to real gid, otherwise remember that
13558 * no privileged gid is available.
13560 * There are no exception like there is for the user id, since there
13561 * is no group id that is privileged in the manner of uid "root".
13562 * There could be equivalent problems for group changing if the
13563 * program sometimes ran with uid "root" and sometimes not, but
13564 * that is already avoided as explained above.
13566 * Thus we can expect always to be able to switch to the "saved set-
13567 * gid" when we want, and back to the real gid again. You may also
13568 * draw the conclusion that set-gid provides for fewer hassles than
13573 fprintf(stderr,"UID_ROOT=%d\n",UID_ROOT);
13574 fprintf(stderr,"realuid=%d\n",realuid);
13575 fprintf(stderr,"privuid=%d\n",privuid);
13576 #endif /* SUIDDEBUG */
13578 if (realgid == privgid) /* If not running set-user-id, */
13579 privgid = (GID_T) -1; /* remember it this way. */
13581 err = priv_off(); /* Turn off setuid privilege. */
13583 if (privuid == UID_ROOT) /* If setuid to root, */
13584 err |= 4; /* return this error. */
13586 if (realuid == UID_ROOT) { /* If real id is root, */
13587 privuid = (UID_T) -1; /* stay root at all times. */
13589 /* If Kermit installed SUID uucp and user is running as root */
13590 err &= ~1; /* System V R0 does not save UID */
13591 #endif /* ATT7300 */
13593 #endif /* HAVE_BAUDBOY */
13598 /* Macros for hiding the differences in UID/GID setting between various Unix
13599 * systems. These macros should always be called with both the privileged ID
13600 * and the non-privileged ID. The one in the second argument, will become the
13601 * effective ID. The one in the first argument will be retained for later
13606 /* On BSD systems with the saved-UID feature, we just juggle the effective
13607 * UID back and forth, and leave the real UID at its true value. The kernel
13608 * allows switching to both the current real UID, the effective UID, and the
13609 * UID which the program is set-UID to. The saved set-UID always holds the
13610 * privileged UID for us, and the real UID will always be the non-privileged,
13611 * and we can freely choose one of them for the effective UID at any time.
13613 #define switchuid(hidden,active) setreuid( (UID_T) -1, active)
13614 #define switchgid(hidden,active) setregid( (GID_T) -1, active)
13616 #else /* SETREUID,!SAVEDUID */
13618 /* On systems with setreXid() but without the saved-UID feature, notably
13619 * BSD 4.2, we swap the real and effective UIDs each time. It's
13620 * the effective UID that we are interested in, but we have to retain the
13621 * unused UID somewhere to enable us to restore it later, and we do this
13622 * in the real UID. The kernel only allows switching to either the current
13623 * real or the effective UID, unless you're "root".
13625 #define switchuid(hidden,active) setreuid(hidden,active)
13626 #define switchgid(hidden,active) setregid(hidden,active)
13629 #else /* !SETREUID, !SAVEDUID */
13633 BSD 4.4 works similarly to System V and POSIX (see below), but uses
13634 seteXid() instead of setXid() to change effective IDs. In addition, the
13635 seteXid() functions work the same for "root" as for other users.
13637 #define switchuid(hidden,active) seteuid(active)
13638 #define switchgid(hidden,active) setegid(active)
13640 #else /* !SETEUID */
13642 /* On System V and POSIX, the only thing we can change is the effective UID
13643 * (unless the current effective UID is "root", but initsuid() avoids that for
13644 * us). The kernel allows switching to the current real UID or to the saved
13645 * set-UID. These are always set to the non-privileged UID and the privileged
13646 * UID, respectively, and we only change the effective UID. This breaks if
13647 * the current effective UID is "root", though, because for "root" setuid/gid
13648 * becomes more powerful, which is why initsuid() treats "root" specially.
13649 * Note: That special treatment maybe could be ignored for BSD? Note: For
13650 * systems that don't fit any of these four cases, we simply can't support
13653 #define switchuid(hidden,active) setuid(active)
13654 #define switchgid(hidden,active) setgid(active)
13656 #endif /* SETEUID */
13657 #endif /* SETREUID */
13660 /* P R I V _ O N -- Turn on the setuid and/or setgid */
13662 /* Go to the privileged uid (gid) that the program is set-user-id
13663 * (set-group-id) to, unless the program is running unprivileged.
13664 * If setuid() fails, return value will be 1. If getuid() fails it
13665 * will be 2. Return immediately after first failure, and the function
13666 * tries to restore any partial work done. Returns 0 on success.
13667 * Group id is changed first, since it is less serious than user id.
13671 #ifndef HAVE_BAUDBOY
13672 if (privgid != (GID_T) -1)
13673 if (switchgid(realgid,privgid))
13676 if (privuid != (UID_T) -1)
13677 if (switchuid(realuid,privuid)) {
13678 if (privgid != (GID_T) -1)
13679 switchgid(privgid,realgid);
13682 #endif /* HAVE_BAUDBOY */
13686 /* P R I V _ O F F -- Turn on the real uid and gid */
13688 /* Return to the unprivileged uid (gid) after an temporary visit to
13689 * privileged status, unless the program is running without set-user-id
13690 * (set-group-id). Returns 1 for failure in setuid() and 2 for failure
13691 * in setgid() or:ed together. The functions tries to return both uid
13692 * and gid to unprivileged state, regardless of errors. Returns 0 on
13698 #ifndef HAVE_BAUDBOY
13699 if (privuid != (UID_T) -1)
13700 if (switchuid(privuid,realuid))
13703 if (privgid != (GID_T) -1)
13704 if (switchgid(privgid,realgid))
13706 #endif /* HAVE_BAUDBOY */
13710 /* Turn off privilege permanently. No going back. This is necessary before
13711 * a fork() on BSD43 machines that don't save the setUID or setGID, because
13712 * we swap the real and effective ids, and we don't want to let the forked
13713 * process swap them again and get the privilege back. It will work on other
13714 * machines too, such that you can rely on its effect always being the same,
13715 * for instance, even when you're in priv_on() state when this is called.
13716 * (Well, that part about "permanent" is on System V only true if you follow
13717 * this with a call to exec(), but that's what we want it for anyway.)
13718 * Added by Dean Long -- dlong@midgard.ucsc.edu
13722 #ifndef HAVE_BAUDBOY
13725 if (privuid != (UID_T) -1)
13726 if (setreuid(realuid,realuid))
13729 if (privgid != (GID_T) -1)
13730 if (setregid(realgid,realgid))
13738 if (privuid != (UID_T) -1)
13739 if (setuid(realuid)) {
13740 debug(F101,"setuid failed","",errno);
13742 debug(F101,"ruid","",getuid());
13743 debug(F101,"euid","",geteuid());
13745 debug(F101,"setuid","",realuid);
13746 if (privgid != (GID_T) -1)
13747 if (setgid(realgid)) {
13748 debug(F101,"setgid failed","",errno);
13750 debug(F101,"rgid","",getgid());
13751 debug(F101,"egid","",getegid());
13753 debug(F101,"setgid","",realgid);
13756 /* Easy way of using setuid()/setgid() instead of setreuid()/setregid().*/
13757 return(priv_off());
13758 #endif /* SETEUID */
13759 #endif /* SETREUID */
13762 #endif /* HAVE_BAUDBOY */
13765 /* P R I V _ O P N -- For opening protected files or devices. */
13768 priv_opn(name, modes) char *name; int modes; {
13770 priv_on(); /* Turn privileges on */
13771 debug(F111,"priv_opn",name,modes);
13773 x = open(name, modes); /* Try to open the device */
13774 debug(F101,"priv_opn result","",x);
13775 debug(F101,"priv_opn errno","",errno);
13776 priv_off(); /* Turn privileges off */
13777 return(x); /* Return open's return code */
13780 /* P R I V _ C H K -- Check privileges. */
13782 /* Try to turn them off. If turning them off did not succeed, cancel them */
13787 x = priv_off(); /* Turn off privs. */
13788 if (x != 0 || getuid() == privuid || geteuid() == privuid)
13790 if (x != 0 || getgid() == privgid || getegid() == privgid)
13791 y = y | priv_can();
13801 ttimoff() { /* Turn off any timer interrupts */
13804 As of 5A(183), we set SIGALRM to SIG_IGN (to ignore alarms) rather than to
13805 SIG_DFL (to catch alarms, or if there is no handler, to exit). This is to
13806 cure (mask, really) a deeper problem with stray alarms that occurs on some
13807 systems, possibly having to do with sleep(), that caused core dumps. It
13808 should be OK to do this, because no code in this module uses nested alarms.
13809 (But we still have to watch out for SCRIPT and DIAL...)
13811 /* xx = */ alarm(0);
13812 /* debug(F101,"ttimoff alarm","",xx); */
13813 if (saval) { /* Restore any previous */
13814 signal(SIGALRM,saval); /* alarm handler. */
13815 /* debug(F101,"ttimoff alarm restoring saval","",saval); */
13818 signal(SIGALRM,SIG_IGN); /* Used to be SIG_DFL */
13819 /* debug(F100,"ttimoff alarm SIG_IGN","",0); */
13823 /* T T R U N C M D -- Redirect an external command over the connection. */
13827 ttruncmd(s) char *s; {
13828 PID_T pid; /* pid of lower fork */
13829 int wstat; /* for wait() */
13834 printf("?Sorry, device is not open\n");
13838 debug(F100,"ttruncmd fail: nopush","",0);
13841 conres(); /* Make console normal */
13843 if ((pid = fork()) == 0) { /* Make a child fork */
13844 if (priv_can()) /* Child: turn off privs. */
13846 dup2(ttyfd, 0); /* Give stdin/out to the line */
13849 debug(F101,"ttruncmd system",s,x);
13850 _exit(x ? BAD_EXIT : 0);
13852 SIGTYP (*istat)(), (*qstat)();
13853 if (pid == (PID_T) -1) /* fork() failed? */
13855 istat = signal(SIGINT,SIG_IGN); /* Let the fork handle keyboard */
13856 qstat = signal(SIGQUIT,SIG_IGN); /* interrupts itself... */
13859 while (((wstat = wait(&statusp)) != pid) && (wstat != -1)) ;
13860 #else /* Not COMMENT */
13862 wstat = wait(&statusp);
13863 debug(F101,"ttruncmd wait","",wstat);
13864 if (wstat == pid || wstat == -1)
13867 #endif /* COMMENT */
13869 pexitstat = (statusp & 0xff) ? statusp : statusp >> 8;
13870 debug(F101,"ttruncmd wait statusp","",statusp);
13871 debug(F101,"ttruncmd wait pexitstat","",pexitstat);
13872 signal(SIGINT,istat); /* Restore interrupts */
13873 signal(SIGQUIT,qstat);
13875 concb((char)escchr); /* Restore console to CBREAK mode */
13876 return(statusp == 0 ? 1 : 0);
13878 #endif /* CK_REDIR */
13882 cmdate2tm(char * date, int gmt) /* date as "yyyymmdd hh:mm:ss" */
13884 cmdate2tm(date,gmt) char * date; int gmt;
13887 /* date as "yyyymmdd hh:mm:ss" */
13888 static struct tm _tm;
13891 if (strlen(date) != 17 ||
13899 _tm = *gmtime(&now);
13901 _tm = *localtime(&now);
13902 _tm.tm_year = (date[0]-'0')*1000 + (date[1]-'0')*100 +
13903 (date[2]-'0')*10 + (date[3]-'0')-1900;
13904 _tm.tm_mon = (date[4]-'0')*10 + (date[5]-'0')-1;
13905 _tm.tm_mday = (date[6]-'0')*10 + (date[7]-'0');
13906 _tm.tm_hour = (date[9]-'0')*10 + (date[10]-'0');
13907 _tm.tm_min = (date[12]-'0')*10 + (date[13]-'0');
13908 _tm.tm_sec = (date[15]-'0')*10 + (date[16]-'0');
13910 /* Should we set _tm.tm_isdst to -1 here? */
13924 priv_kill(pid, sig) int pid, sig; {
13928 debug(F100,"priv_kill priv_on failed","",0);
13929 i = kill(pid, sig);
13931 debug(F100,"priv_kill priv_off failed","",0);
13937 /* #ifdef BE_DR_7 */
13939 alarm() function not supplied with Be OS DR7 - this one contributed by
13944 This should mimic the UNIX/POSIX alarm() function well enough, with the
13945 caveat that one's SIGALRM handler must call alarm_expired() to clean up vars
13946 and wait for the alarm thread to finish.
13949 alarm(unsigned int seconds) {
13950 long time_left = 0;
13952 /* If an alarm is active, turn it off, saving the unused time */
13953 if (alarm_thread != -1) {
13954 /* We'll be generous and count partial seconds as whole seconds. */
13955 time_left = alarm_struct.time -
13956 ((system_time() - time_started) / 1000000.0);
13958 /* Kill the alarm thread */
13959 kill_thread (alarm_thread);
13961 /* We need to clean up as though the alarm occured. */
13963 alarm_struct.thread = -1;
13964 alarm_struct.time = 0;
13968 /* Set a new alarm clock, if requested. */
13970 alarm_struct.thread = find_thread(NULL);
13971 alarm_struct.time = seconds;
13972 time_started = system_time();
13973 alarm_thread = spawn_thread (do_alarm,
13976 (void *) &alarm_struct
13978 resume_thread (alarm_thread);
13981 /* Now return [unused time | 0] */
13982 return ((unsigned int) time_left);
13986 This function is the departure from UNIX/POSIX alarm handling. In the case
13987 of Be's missing alarm() function, this stuff needs to be done in the SIGALRM
13988 handler. When Be implements alarm(), this function call can be eliminated
13989 from user's SIGALRM signal handlers.
13993 alarm_expired(void) {
13996 if (alarm_thread != -1) {
13997 wait_for_thread (alarm_thread, &ret_val);
14003 This is the function that snoozes the requisite number of seconds and then
14004 SIGALRMs the calling thread. Note that kill() wants a pid_t arg, whilst Be
14005 uses thread_id; currently they are both typdef'ed as long, but I'll do the
14006 cast anyway. This function is run in a separate thread.
14010 do_alarm (void *alarm_struct) {
14011 snooze ((double) ((struct ALARM_STRUCT *) alarm_struct)->time * 1000000.0);
14012 kill ((pid_t)((struct ALARM_STRUCT *) alarm_struct)->thread, SIGALRM);
14014 ((struct ALARM_STRUCT *) alarm_struct)->thread = -1;
14015 ((struct ALARM_STRUCT *) alarm_struct)->time = 0;
14017 /* #endif */ /* BE_DR_7 */
14018 #endif /* BEOSORBEBOX */
14023 p9ttyctl(char letter, int num, int param) {
14032 len = sprintf(cmd + 1, "%d", param) + 1;
14037 if (write(ttyctlfd, cmd, len) == len) {
14039 /* fprintf(stdout, "wrote '%s'\n", cmd); */
14046 p9ttyparity(char l) {
14047 return p9ttyctl('p', 0, l);
14051 p9tthflow(int flow, int status) {
14052 return p9ttyctl('m', 1, status);
14056 p9ttsspd(int cps) {
14057 if (p9ttyctl('b', 1, cps * 10) < 0)
14059 ttylastspeed = cps * 10;
14064 p9openttyctl(char *ttname) {
14067 if (ttyctlfd >= 0) {
14072 sprintf(name, "%sctl", ttname);
14073 ttyctlfd = open(name, 1);
14079 if (consctlfd >= 0) {
14080 if (write(consctlfd, "rawon", 5) == 5)
14093 if (consctlfd >= 0) {
14094 if (write(consctlfd, "rawoff", 6) == 6)
14101 p9sndbrk(int msec) {
14102 if (ttyctlfd >= 0) {
14104 int i = sprintf(cmd, "k%d", msec);
14105 if (write(ttyctlfd, cmd, i) == i)
14112 conwrite(char *buf, int n) {
14114 static int length = 0;
14115 static int holdingcr = 0;
14117 for (x = 0; x < n; x++) {
14121 write(1, buf + (x - normal), normal);
14125 /* write(noisefd, "1000 300", 8); */
14127 } else if (c == '\r') {
14129 write(1, buf + (x - normal), normal);
14134 } else if (c == '\n') {
14135 write(1, buf + (x - normal), normal + 1);
14139 } else if (c == '\b') {
14141 write(1, buf + (x - normal), normal);
14153 while (length-- > 0)
14155 length = 0; /* compiler bug */
14162 write(1, buf + (x - normal), normal);
14169 conprint(char *fmt, ...) {
14170 static char buf[1000]; /* not safe if on the stack */
14176 i = vsprintf(buf, fmt, ap);
14181 /* fprintf, printf, perror replacements... */
14183 /* f p r i n t f */
14187 #include <stdarg.h>
14188 #else /* CK_ANSIC */
14189 #include <varargs.h>
14190 #endif /* CK_ANSIC */
14193 static char str1[4096];
14194 static char str2[4096];
14197 ckxfprintf(FILE * file, const char * format, ...)
14198 #else /* CK_ANSIC */
14199 ckxfprintf(va_alist) va_dcl
14200 #endif /* CK_ANSIC */
14202 int i, j, len, got_cr;
14207 va_start(args, format);
14208 #else /* CK_ANSIC */
14212 file = va_arg(args,FILE *);
14213 format = va_arg(args,char *);
14214 #endif /* CK_ANSIC */
14216 if (!inserver || (file != stdout && file != stderr && file != stdin)) {
14217 rc = vfprintf(file,format,args);
14220 rc = vsprintf(str1, format, args);
14221 len = strlen(str1);
14222 if (len >= sizeof(str1)) {
14223 debug(F101,"ckxfprintf() buffer overflow","",len);
14224 doexit(BAD_EXIT,1);
14226 for (i = 0, j = 0, got_cr = 0;
14227 i < len && j < sizeof(str1)-2;
14229 /* We can't use 255 as a case label because of signed chars */
14230 c = (unsigned)(str1[i] & 0xff);
14233 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
14239 #endif /* TNCODE */
14244 && !TELOPT_ME(TELOPT_BINARY)
14245 #endif /* TNCODE */
14260 && !TELOPT_ME(TELOPT_BINARY)
14261 #endif /* TNCODE */
14270 && !TELOPT_ME(TELOPT_BINARY)
14271 #endif /* TNCODE */
14274 #ifdef CK_ENCRYPTION
14276 if (TELOPT_ME(TELOPT_ENCRYPTION))
14277 ck_tn_encrypt(str2,j);
14278 #endif /* TNCODE */
14279 #endif /* CK_ENCRYPTION */
14281 if (inserver && (ssl_active_flag || tls_active_flag)) {
14282 /* Write using SSL */
14285 if (ssl_active_flag)
14286 rc = SSL_write(ssl_con, p, j);
14288 rc = SSL_write(tls_con, p, j);
14289 debug(F111,"ckxfprintf","SSL_write",rc);
14290 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
14291 case SSL_ERROR_NONE:
14297 case SSL_ERROR_WANT_WRITE:
14298 case SSL_ERROR_WANT_READ:
14299 case SSL_ERROR_SYSCALL:
14302 case SSL_ERROR_WANT_X509_LOOKUP:
14303 case SSL_ERROR_SSL:
14304 case SSL_ERROR_ZERO_RETURN:
14309 #endif /* CK_SSL */
14310 fwrite(str2,sizeof(char),j,stdout);
14315 #endif /* fprintf */
14323 ckxprintf(const char * format, ...)
14324 #else /* CK_ANSIC */
14325 ckxprintf(va_alist) va_dcl
14326 #endif /* CK_ANSIC */
14328 int i, j, len, got_cr;
14333 va_start(args, format);
14334 #else /* CK_ANSIC */
14337 format = va_arg(args,char *);
14338 #endif /* CK_ANSIC */
14341 rc = vprintf(format, args);
14344 rc = vsprintf(str1, format, args);
14345 len = strlen(str1);
14346 if (len >= sizeof(str1)) {
14347 debug(F101,"ckxprintf() buffer overflow","",len);
14348 doexit(BAD_EXIT,1);
14350 for (i = 0, j = 0, got_cr=0;
14351 i < len && j < sizeof(str1)-2;
14353 c = (unsigned)(str1[i] & 0xff);
14356 if (got_cr && !TELOPT_ME(TELOPT_BINARY))
14362 #endif /* TNCODE */
14367 && !TELOPT_ME(TELOPT_BINARY)
14368 #endif /* TNCODE */
14383 && !TELOPT_ME(TELOPT_BINARY)
14384 #endif /* TNCODE */
14394 && !TELOPT_ME(TELOPT_BINARY)
14395 #endif /* TNCODE */
14398 #ifdef CK_ENCRYPTION
14400 if (TELOPT_ME(TELOPT_ENCRYPTION))
14401 ck_tn_encrypt(str2,j);
14402 #endif /* TNCODE */
14403 #endif /* CK_ENCRYPTION */
14405 if (inserver && (ssl_active_flag || tls_active_flag)) {
14407 /* Write using SSL */
14409 if (ssl_active_flag)
14410 rc = SSL_write(ssl_con, p, j);
14412 rc = SSL_write(tls_con, p, j);
14413 debug(F111,"ckxprintf","SSL_write",rc);
14414 switch (SSL_get_error(ssl_active_flag?ssl_con:tls_con,rc)) {
14415 case SSL_ERROR_NONE:
14421 case SSL_ERROR_WANT_WRITE:
14422 case SSL_ERROR_WANT_READ:
14423 case SSL_ERROR_SYSCALL:
14426 case SSL_ERROR_WANT_X509_LOOKUP:
14427 case SSL_ERROR_SSL:
14428 case SSL_ERROR_ZERO_RETURN:
14433 #endif /* CK_SSL */
14434 rc = fwrite(str2,sizeof(char),j,stdout);
14439 #endif /* printf */
14445 _PROTOTYP(char * ck_errstr,(VOID));
14453 #endif /* CK_SCOV5 */
14456 ckxperror(const char * str)
14457 #else /* CK_ANSIC */
14458 ckxperror(str) char * str;
14459 #endif /* CK_ANSIC */
14461 char * errstr = ck_errstr();
14465 #endif /* CK_SCOV5 */
14467 ckxprintf("%s%s %s\n",str,*errstr?":":"",errstr);
14469 #endif /* perror */
14474 /* Minix doesn't have a gettimeofday call. We fake one here using time(2) */
14477 gettimeofday(struct timeval *tp, struct timezone *tzp) {
14478 tp->tv_usec = 0L; /* Close enough for horseshoes */
14479 if(time(&(tp->tv_sec))==-1)
14484 /* Minix does not support symbolic links. We implement a version of
14485 readlink that always fails */
14488 readlink(const char *path, void *buf, size_t bufsiz) {
14492 #endif /* MINIX2 */