diff options
author | markm <markm@FreeBSD.org> | 1996-11-07 14:42:57 +0000 |
---|---|---|
committer | markm <markm@FreeBSD.org> | 1996-11-07 14:42:57 +0000 |
commit | 524bda369e953d881ee7553b09e8264a246ab63d (patch) | |
tree | 18c8a25efc2a6c44c6b545bda4a0be55a4d7a8b2 /secure/libexec/telnetd | |
parent | fc40bcb55d3fa6be84318069bec334bf41b56601 (diff) | |
download | FreeBSD-src-524bda369e953d881ee7553b09e8264a246ab63d.zip FreeBSD-src-524bda369e953d881ee7553b09e8264a246ab63d.tar.gz |
Secure telnet is now in eBones.
Diffstat (limited to 'secure/libexec/telnetd')
-rw-r--r-- | secure/libexec/telnetd/Makefile | 28 | ||||
-rw-r--r-- | secure/libexec/telnetd/authenc.c | 91 | ||||
-rw-r--r-- | secure/libexec/telnetd/defs.h | 296 | ||||
-rw-r--r-- | secure/libexec/telnetd/ext.h | 242 | ||||
-rw-r--r-- | secure/libexec/telnetd/global.c | 48 | ||||
-rw-r--r-- | secure/libexec/telnetd/pathnames.h | 55 | ||||
-rw-r--r-- | secure/libexec/telnetd/slc.c | 491 | ||||
-rw-r--r-- | secure/libexec/telnetd/state.c | 1612 | ||||
-rw-r--r-- | secure/libexec/telnetd/sys_term.c | 2324 | ||||
-rw-r--r-- | secure/libexec/telnetd/telnetd.8 | 613 | ||||
-rw-r--r-- | secure/libexec/telnetd/telnetd.c | 1598 | ||||
-rw-r--r-- | secure/libexec/telnetd/telnetd.h | 49 | ||||
-rw-r--r-- | secure/libexec/telnetd/termstat.c | 669 | ||||
-rw-r--r-- | secure/libexec/telnetd/utility.c | 1202 |
14 files changed, 0 insertions, 9318 deletions
diff --git a/secure/libexec/telnetd/Makefile b/secure/libexec/telnetd/Makefile deleted file mode 100644 index c0c82ee..0000000 --- a/secure/libexec/telnetd/Makefile +++ /dev/null @@ -1,28 +0,0 @@ -# @(#)Makefile 8.2 (Berkeley) 12/15/93 -# $Id$ - -# Do not define -DKLUDGELINEMODE, as it does not interact well with many -# telnet implementations. - -PROG= telnetd -MAN8= telnetd.8 - -SRCS= authenc.c global.c slc.c state.c sys_term.c telnetd.c \ - termstat.c utility.c - -DPADD= ${TELNETOBJDIR}/libtelnet.a ${LIBUTIL} ${LIBTERMCAP} -LDADD= -L${TELNETOBJDIR} -lutil -ltermcap -ltelnet - -CFLAGS+= -DLINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON -DENV_HACK -CFLAGS+= -DENCRYPTION -I${.CURDIR}/../../lib - -.if exists(${DESTDIR}/usr/lib/libkrb.a) && (defined(MAKE_EBONES)) -CFLAGS+=-DAUTHENTICATION -LDADD+= -ldes -lkrb -DPADD+= ${LIBDES} ${LIBKRB} -.endif - -# Used only in krb4encpwd.c and rsaencpwd.c (libtelnet), not yet active -#LDADD+= -ldescrypt - -.include <bsd.prog.mk> diff --git a/secure/libexec/telnetd/authenc.c b/secure/libexec/telnetd/authenc.c deleted file mode 100644 index ccb463c..0000000 --- a/secure/libexec/telnetd/authenc.c +++ /dev/null @@ -1,91 +0,0 @@ -/*- - * Copyright (c) 1991, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)authenc.c 8.2 (Berkeley) 5/30/95"; -#endif /* not lint */ - -#if defined(AUTHENTICATION) || defined(ENCRYPTION) -#include "telnetd.h" -#include <libtelnet/misc.h> - - int -net_write(str, len) - unsigned char *str; - int len; -{ - if (nfrontp + len < netobuf + BUFSIZ) { - memmove((void *)nfrontp, (void *)str, len); - nfrontp += len; - return(len); - } - return(0); -} - - void -net_encrypt() -{ -#ifdef ENCRYPTION - char *s = (nclearto > nbackp) ? nclearto : nbackp; - if (s < nfrontp && encrypt_output) { - (*encrypt_output)((unsigned char *)s, nfrontp - s); - } - nclearto = nfrontp; -#endif /* ENCRYPTION */ -} - - int -telnet_spin() -{ - ttloop(); - return(0); -} - - char * -telnet_getenv(val) - char *val; -{ - extern char *getenv(); - return(getenv(val)); -} - - char * -telnet_gets(prompt, result, length, echo) - char *prompt; - char *result; - int length; - int echo; -{ - return((char *)0); -} -#endif /* defined(AUTHENTICATION) || defined(ENCRYPTION) */ diff --git a/secure/libexec/telnetd/defs.h b/secure/libexec/telnetd/defs.h deleted file mode 100644 index a73d4a6..0000000 --- a/secure/libexec/telnetd/defs.h +++ /dev/null @@ -1,296 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)defs.h 8.1 (Berkeley) 6/4/93 - */ - -/* - * Telnet server defines - */ -#include <sys/types.h> -#include <sys/param.h> - -#ifndef BSD -# define BSD 43 -#endif - -#if defined(CRAY) && !defined(LINEMODE) -# define SYSV_TERMIO -# define LINEMODE -# define KLUDGELINEMODE -# define DIAGNOSTICS -# if defined(UNICOS50) && !defined(UNICOS5) -# define UNICOS5 -# endif -# if !defined(UNICOS5) -# define BFTPDAEMON -# define HAS_IP_TOS -# endif -#endif /* CRAY */ -#if defined(UNICOS5) && !defined(NO_SETSID) -# define NO_SETSID -#endif - -#if defined(PRINTOPTIONS) && defined(DIAGNOSTICS) -#define TELOPTS -#define TELCMDS -#define SLC_NAMES -#endif - -#if defined(SYSV_TERMIO) && !defined(USE_TERMIO) -# define USE_TERMIO -#endif - -#include <sys/socket.h> -#ifndef CRAY -#include <sys/wait.h> -#endif /* CRAY */ -#include <fcntl.h> -#include <sys/file.h> -#include <sys/stat.h> -#include <sys/time.h> -#ifndef FILIO_H -#include <sys/ioctl.h> -#else -#include <sys/filio.h> -#endif - -#include <netinet/in.h> - -#include <arpa/telnet.h> - -#include <stdio.h> -#ifdef __STDC__ -#include <stdlib.h> -#endif -#include <signal.h> -#include <errno.h> -#include <netdb.h> -#include <syslog.h> -#ifndef LOG_DAEMON -#define LOG_DAEMON 0 -#endif -#ifndef LOG_ODELAY -#define LOG_ODELAY 0 -#endif -#include <ctype.h> -#ifndef NO_STRING_H -#include <string.h> -#else -#include <strings.h> -#endif - -#ifndef USE_TERMIO -#include <sgtty.h> -#else -# ifdef SYSV_TERMIO -# include <termio.h> -# else -# include <termios.h> -# endif -#endif -#if !defined(USE_TERMIO) || defined(NO_CC_T) -typedef unsigned char cc_t; -#endif - -#ifdef __STDC__ -#include <unistd.h> -#endif - -#ifndef _POSIX_VDISABLE -# ifdef VDISABLE -# define _POSIX_VDISABLE VDISABLE -# else -# define _POSIX_VDISABLE ((unsigned char)'\377') -# endif -#endif - - -#ifdef CRAY -# ifdef CRAY1 -# include <sys/pty.h> -# ifndef FD_ZERO -# include <sys/select.h> -# endif /* FD_ZERO */ -# endif /* CRAY1 */ - -#include <memory.h> -#endif /* CRAY */ - -#ifdef __hpux -#include <sys/ptyio.h> -#endif - -#if !defined(TIOCSCTTY) && defined(TCSETCTTY) -# define TIOCSCTTY TCSETCTTY -#endif - -#ifndef FD_SET -#ifndef HAVE_fd_set -typedef struct fd_set { int fds_bits[1]; } fd_set; -#endif - -#define FD_SET(n, p) ((p)->fds_bits[0] |= (1<<(n))) -#define FD_CLR(n, p) ((p)->fds_bits[0] &= ~(1<<(n))) -#define FD_ISSET(n, p) ((p)->fds_bits[0] & (1<<(n))) -#define FD_ZERO(p) ((p)->fds_bits[0] = 0) -#endif /* FD_SET */ - -/* - * I/O data buffers defines - */ -#define NETSLOP 64 -#ifdef CRAY -#undef BUFSIZ -#define BUFSIZ 2048 -#endif - -#define NIACCUM(c) { *netip++ = c; \ - ncc++; \ - } - -/* clock manipulations */ -#define settimer(x) (clocks.x = ++clocks.system) -#define sequenceIs(x,y) (clocks.x < clocks.y) - -/* - * Linemode support states, in decreasing order of importance - */ -#define REAL_LINEMODE 0x04 -#define KLUDGE_OK 0x03 -#define NO_AUTOKLUDGE 0x02 -#define KLUDGE_LINEMODE 0x01 -#define NO_LINEMODE 0x00 - -/* - * Structures of information for each special character function. - */ -typedef struct { - unsigned char flag; /* the flags for this function */ - cc_t val; /* the value of the special character */ -} slcent, *Slcent; - -typedef struct { - slcent defset; /* the default settings */ - slcent current; /* the current settings */ - cc_t *sptr; /* a pointer to the char in */ - /* system data structures */ -} slcfun, *Slcfun; - -#ifdef DIAGNOSTICS -/* - * Diagnostics capabilities - */ -#define TD_REPORT 0x01 /* Report operations to client */ -#define TD_EXERCISE 0x02 /* Exercise client's implementation */ -#define TD_NETDATA 0x04 /* Display received data stream */ -#define TD_PTYDATA 0x08 /* Display data passed to pty */ -#define TD_OPTIONS 0x10 /* Report just telnet options */ -#endif /* DIAGNOSTICS */ - -/* - * We keep track of each side of the option negotiation. - */ - -#define MY_STATE_WILL 0x01 -#define MY_WANT_STATE_WILL 0x02 -#define MY_STATE_DO 0x04 -#define MY_WANT_STATE_DO 0x08 - -/* - * Macros to check the current state of things - */ - -#define my_state_is_do(opt) (options[opt]&MY_STATE_DO) -#define my_state_is_will(opt) (options[opt]&MY_STATE_WILL) -#define my_want_state_is_do(opt) (options[opt]&MY_WANT_STATE_DO) -#define my_want_state_is_will(opt) (options[opt]&MY_WANT_STATE_WILL) - -#define my_state_is_dont(opt) (!my_state_is_do(opt)) -#define my_state_is_wont(opt) (!my_state_is_will(opt)) -#define my_want_state_is_dont(opt) (!my_want_state_is_do(opt)) -#define my_want_state_is_wont(opt) (!my_want_state_is_will(opt)) - -#define set_my_state_do(opt) (options[opt] |= MY_STATE_DO) -#define set_my_state_will(opt) (options[opt] |= MY_STATE_WILL) -#define set_my_want_state_do(opt) (options[opt] |= MY_WANT_STATE_DO) -#define set_my_want_state_will(opt) (options[opt] |= MY_WANT_STATE_WILL) - -#define set_my_state_dont(opt) (options[opt] &= ~MY_STATE_DO) -#define set_my_state_wont(opt) (options[opt] &= ~MY_STATE_WILL) -#define set_my_want_state_dont(opt) (options[opt] &= ~MY_WANT_STATE_DO) -#define set_my_want_state_wont(opt) (options[opt] &= ~MY_WANT_STATE_WILL) - -/* - * Tricky code here. What we want to know is if the MY_STATE_WILL - * and MY_WANT_STATE_WILL bits have the same value. Since the two - * bits are adjacent, a little arithmatic will show that by adding - * in the lower bit, the upper bit will be set if the two bits were - * different, and clear if they were the same. - */ -#define my_will_wont_is_changing(opt) \ - ((options[opt]+MY_STATE_WILL) & MY_WANT_STATE_WILL) - -#define my_do_dont_is_changing(opt) \ - ((options[opt]+MY_STATE_DO) & MY_WANT_STATE_DO) - -/* - * Make everything symetrical - */ - -#define HIS_STATE_WILL MY_STATE_DO -#define HIS_WANT_STATE_WILL MY_WANT_STATE_DO -#define HIS_STATE_DO MY_STATE_WILL -#define HIS_WANT_STATE_DO MY_WANT_STATE_WILL - -#define his_state_is_do my_state_is_will -#define his_state_is_will my_state_is_do -#define his_want_state_is_do my_want_state_is_will -#define his_want_state_is_will my_want_state_is_do - -#define his_state_is_dont my_state_is_wont -#define his_state_is_wont my_state_is_dont -#define his_want_state_is_dont my_want_state_is_wont -#define his_want_state_is_wont my_want_state_is_dont - -#define set_his_state_do set_my_state_will -#define set_his_state_will set_my_state_do -#define set_his_want_state_do set_my_want_state_will -#define set_his_want_state_will set_my_want_state_do - -#define set_his_state_dont set_my_state_wont -#define set_his_state_wont set_my_state_dont -#define set_his_want_state_dont set_my_want_state_wont -#define set_his_want_state_wont set_my_want_state_dont - -#define his_will_wont_is_changing my_do_dont_is_changing -#define his_do_dont_is_changing my_will_wont_is_changing diff --git a/secure/libexec/telnetd/ext.h b/secure/libexec/telnetd/ext.h deleted file mode 100644 index db3f1c3..0000000 --- a/secure/libexec/telnetd/ext.h +++ /dev/null @@ -1,242 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)ext.h 8.2 (Berkeley) 12/15/93 - */ - -/* - * Telnet server variable declarations - */ -extern char options[256]; -extern char do_dont_resp[256]; -extern char will_wont_resp[256]; -extern int linemode; /* linemode on/off */ -#ifdef LINEMODE -extern int uselinemode; /* what linemode to use (on/off) */ -extern int editmode; /* edit modes in use */ -extern int useeditmode; /* edit modes to use */ -extern int alwayslinemode; /* command line option */ -extern int lmodetype; /* Client support for linemode */ -#endif /* LINEMODE */ -extern int flowmode; /* current flow control state */ -extern int restartany; /* restart output on any character state */ -#ifdef DIAGNOSTICS -extern int diagnostic; /* telnet diagnostic capabilities */ -#endif /* DIAGNOSTICS */ -#ifdef BFTPDAEMON -extern int bftpd; /* behave as bftp daemon */ -#endif /* BFTPDAEMON */ -#if defined(SecurID) -extern int require_SecurID; -#endif -#if defined(AUTHENTICATION) -extern int auth_level; -#endif - -extern slcfun slctab[NSLC + 1]; /* slc mapping table */ - -char *terminaltype; - -/* - * I/O data buffers, pointers, and counters. - */ -extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp; - -extern char netibuf[BUFSIZ], *netip; - -extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp; -extern char *neturg; /* one past last bye of urgent data */ - -extern int pcc, ncc; - -#if defined(CRAY2) && defined(UNICOS5) -extern int unpcc; /* characters left unprocessed by CRAY-2 terminal routine */ -extern char *unptyip; /* pointer to remaining characters in buffer */ -#endif - -extern int pty, net; -extern char *line; -extern int SYNCHing; /* we are in TELNET SYNCH mode */ - -#ifndef P -# ifdef __STDC__ -# define P(x) x -# else -# define P(x) () -# endif -#endif - -extern void - _termstat P((void)), - add_slc P((int, int, int)), - check_slc P((void)), - change_slc P((int, int, int)), - cleanup P((int)), - clientstat P((int, int, int)), - copy_termbuf P((char *, int)), - deferslc P((void)), - defer_terminit P((void)), - do_opt_slc P((unsigned char *, int)), - doeof P((void)), - dooption P((int)), - dontoption P((int)), - edithost P((char *, char *)), - fatal P((int, char *)), - fatalperror P((int, char *)), - get_slc_defaults P((void)), - init_env P((void)), - init_termbuf P((void)), - interrupt P((void)), - localstat P((void)), - flowstat P((void)), - netclear P((void)), - netflush P((void)), -#ifdef DIAGNOSTICS - printoption P((char *, int)), - printdata P((char *, char *, int)), - printsub P((int, unsigned char *, int)), -#endif - ptyflush P((void)), - putchr P((int)), - putf P((char *, char *)), - recv_ayt P((void)), - send_do P((int, int)), - send_dont P((int, int)), - send_slc P((void)), - send_status P((void)), - send_will P((int, int)), - send_wont P((int, int)), - sendbrk P((void)), - sendsusp P((void)), - set_termbuf P((void)), - start_login P((char *, int, char *)), - start_slc P((int)), -#if defined(AUTHENTICATION) - start_slave P((char *)), -#else - start_slave P((char *, int, char *)), -#endif - suboption P((void)), - telrcv P((void)), - ttloop P((void)), - tty_binaryin P((int)), - tty_binaryout P((int)); - -extern int - end_slc P((unsigned char **)), - getnpty P((void)), -#ifndef convex - getpty P((int *)), -#endif - login_tty P((int)), - spcset P((int, cc_t *, cc_t **)), - stilloob P((int)), - terminit P((void)), - termstat P((void)), - tty_flowmode P((void)), - tty_restartany P((void)), - tty_isbinaryin P((void)), - tty_isbinaryout P((void)), - tty_iscrnl P((void)), - tty_isecho P((void)), - tty_isediting P((void)), - tty_islitecho P((void)), - tty_isnewmap P((void)), - tty_israw P((void)), - tty_issofttab P((void)), - tty_istrapsig P((void)), - tty_linemode P((void)); - -extern void - tty_rspeed P((int)), - tty_setecho P((int)), - tty_setedit P((int)), - tty_setlinemode P((int)), - tty_setlitecho P((int)), - tty_setsig P((int)), - tty_setsofttab P((int)), - tty_tspeed P((int)), - willoption P((int)), - wontoption P((int)), - writenet P((unsigned char *, int)); - -#ifdef ENCRYPTION -extern void (*encrypt_output) P((unsigned char *, int)); -extern int (*decrypt_input) P((int)); -extern char *nclearto; -#endif /* ENCRYPTION */ - - -/* - * The following are some clocks used to decide how to interpret - * the relationship between various variables. - */ - -extern struct { - int - system, /* what the current time is */ - echotoggle, /* last time user entered echo character */ - modenegotiated, /* last time operating mode negotiated */ - didnetreceive, /* last time we read data from network */ - ttypesubopt, /* ttype subopt is received */ - tspeedsubopt, /* tspeed subopt is received */ - environsubopt, /* environ subopt is received */ - oenvironsubopt, /* old environ subopt is received */ - xdisplocsubopt, /* xdisploc subopt is received */ - baseline, /* time started to do timed action */ - gotDM; /* when did we last see a data mark */ -} clocks; - - -#if defined(CRAY2) && defined(UNICOS5) -extern int needtermstat; -#endif - -#ifndef DEFAULT_IM -# ifdef CRAY -# define DEFAULT_IM "\r\n\r\nCray UNICOS (%h) (%t)\r\n\r\r\n\r" -# else -# ifdef sun -# define DEFAULT_IM "\r\n\r\nSunOS UNIX (%h) (%t)\r\n\r\r\n\r" -# else -# ifdef ultrix -# define DEFAULT_IM "\r\n\r\nULTRIX (%h) (%t)\r\n\r\r\n\r" -# else -# ifdef __FreeBSD__ -# define DEFAULT_IM "\r\n\r\nFreeBSD (%h) (%t)\r\n\r\r\n\r" -# else -# define DEFAULT_IM "\r\n\r\n4.4 BSD UNIX (%h) (%t)\r\n\r\r\n\r" -# endif -# endif -# endif -# endif -#endif diff --git a/secure/libexec/telnetd/global.c b/secure/libexec/telnetd/global.c deleted file mode 100644 index af21acc..0000000 --- a/secure/libexec/telnetd/global.c +++ /dev/null @@ -1,48 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)global.c 8.1 (Berkeley) 6/4/93"; -#endif /* not lint */ - -/* - * Allocate global variables. We do this - * by including the header file that defines - * them all as externs, but first we define - * the keyword "extern" to be nothing, so that - * we will actually allocate the space. - */ - -#include "defs.h" -#define extern -#include "ext.h" diff --git a/secure/libexec/telnetd/pathnames.h b/secure/libexec/telnetd/pathnames.h deleted file mode 100644 index 4e14a88..0000000 --- a/secure/libexec/telnetd/pathnames.h +++ /dev/null @@ -1,55 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)pathnames.h 8.1 (Berkeley) 6/4/93 - */ - -#if BSD > 43 - -# include <paths.h> - -# ifndef _PATH_LOGIN -# define _PATH_LOGIN "/usr/bin/login" -# endif - -#else - -# define _PATH_TTY "/dev/tty" -# ifndef _PATH_LOGIN -# define _PATH_LOGIN "/bin/login" -# endif - -#endif - -#ifdef BFTPDAEMON -#define BFTPPATH "/usr/ucb/bftp" -#endif /* BFTPDAEMON */ diff --git a/secure/libexec/telnetd/slc.c b/secure/libexec/telnetd/slc.c deleted file mode 100644 index 6cbb7ab..0000000 --- a/secure/libexec/telnetd/slc.c +++ /dev/null @@ -1,491 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)slc.c 8.2 (Berkeley) 5/30/95"; -#endif /* not lint */ - -#include "telnetd.h" - -#ifdef LINEMODE -/* - * local varibles - */ -static unsigned char *def_slcbuf = (unsigned char *)0; -static int def_slclen = 0; -static int slcchange; /* change to slc is requested */ -static unsigned char *slcptr; /* pointer into slc buffer */ -static unsigned char slcbuf[NSLC*6]; /* buffer for slc negotiation */ - -/* - * send_slc - * - * Write out the current special characters to the client. - */ - void -send_slc() -{ - register int i; - - /* - * Send out list of triplets of special characters - * to client. We only send info on the characters - * that are currently supported. - */ - for (i = 1; i <= NSLC; i++) { - if ((slctab[i].defset.flag & SLC_LEVELBITS) == SLC_NOSUPPORT) - continue; - add_slc((unsigned char)i, slctab[i].current.flag, - slctab[i].current.val); - } - -} /* end of send_slc */ - -/* - * default_slc - * - * Set pty special characters to all the defaults. - */ - void -default_slc() -{ - register int i; - - for (i = 1; i <= NSLC; i++) { - slctab[i].current.val = slctab[i].defset.val; - if (slctab[i].current.val == (cc_t)(_POSIX_VDISABLE)) - slctab[i].current.flag = SLC_NOSUPPORT; - else - slctab[i].current.flag = slctab[i].defset.flag; - if (slctab[i].sptr) { - *(slctab[i].sptr) = slctab[i].defset.val; - } - } - slcchange = 1; - -} /* end of default_slc */ -#endif /* LINEMODE */ - -/* - * get_slc_defaults - * - * Initialize the slc mapping table. - */ - void -get_slc_defaults() -{ - register int i; - - init_termbuf(); - - for (i = 1; i <= NSLC; i++) { - slctab[i].defset.flag = - spcset(i, &slctab[i].defset.val, &slctab[i].sptr); - slctab[i].current.flag = SLC_NOSUPPORT; - slctab[i].current.val = 0; - } - -} /* end of get_slc_defaults */ - -#ifdef LINEMODE -/* - * add_slc - * - * Add an slc triplet to the slc buffer. - */ - void -add_slc(func, flag, val) - register char func, flag; - register cc_t val; -{ - - if ((*slcptr++ = (unsigned char)func) == 0xff) - *slcptr++ = 0xff; - - if ((*slcptr++ = (unsigned char)flag) == 0xff) - *slcptr++ = 0xff; - - if ((*slcptr++ = (unsigned char)val) == 0xff) - *slcptr++ = 0xff; - -} /* end of add_slc */ - -/* - * start_slc - * - * Get ready to process incoming slc's and respond to them. - * - * The parameter getit is non-zero if it is necessary to grab a copy - * of the terminal control structures. - */ - void -start_slc(getit) - register int getit; -{ - - slcchange = 0; - if (getit) - init_termbuf(); - (void) sprintf((char *)slcbuf, "%c%c%c%c", - IAC, SB, TELOPT_LINEMODE, LM_SLC); - slcptr = slcbuf + 4; - -} /* end of start_slc */ - -/* - * end_slc - * - * Finish up the slc negotiation. If something to send, then send it. - */ - int -end_slc(bufp) - register unsigned char **bufp; -{ - register int len; - void netflush(); - - /* - * If a change has occured, store the new terminal control - * structures back to the terminal driver. - */ - if (slcchange) { - set_termbuf(); - } - - /* - * If the pty state has not yet been fully processed and there is a - * deferred slc request from the client, then do not send any - * sort of slc negotiation now. We will respond to the client's - * request very soon. - */ - if (def_slcbuf && (terminit() == 0)) { - return(0); - } - - if (slcptr > (slcbuf + 4)) { - if (bufp) { - *bufp = &slcbuf[4]; - return(slcptr - slcbuf - 4); - } else { - (void) sprintf((char *)slcptr, "%c%c", IAC, SE); - slcptr += 2; - len = slcptr - slcbuf; - writenet(slcbuf, len); - netflush(); /* force it out immediately */ - DIAG(TD_OPTIONS, printsub('>', slcbuf+2, len-2);); - } - } - return (0); - -} /* end of end_slc */ - -/* - * process_slc - * - * Figure out what to do about the client's slc - */ - void -process_slc(func, flag, val) - register unsigned char func, flag; - register cc_t val; -{ - register int hislevel, mylevel, ack; - - /* - * Ensure that we know something about this function - */ - if (func > NSLC) { - add_slc(func, SLC_NOSUPPORT, 0); - return; - } - - /* - * Process the special case requests of 0 SLC_DEFAULT 0 - * and 0 SLC_VARIABLE 0. Be a little forgiving here, don't - * worry about whether the value is actually 0 or not. - */ - if (func == 0) { - if ((flag = flag & SLC_LEVELBITS) == SLC_DEFAULT) { - default_slc(); - send_slc(); - } else if (flag == SLC_VARIABLE) { - send_slc(); - } - return; - } - - /* - * Appears to be a function that we know something about. So - * get on with it and see what we know. - */ - - hislevel = flag & SLC_LEVELBITS; - mylevel = slctab[func].current.flag & SLC_LEVELBITS; - ack = flag & SLC_ACK; - /* - * ignore the command if: - * the function value and level are the same as what we already have; - * or the level is the same and the ack bit is set - */ - if (hislevel == mylevel && (val == slctab[func].current.val || ack)) { - return; - } else if (ack) { - /* - * If we get here, we got an ack, but the levels don't match. - * This shouldn't happen. If it does, it is probably because - * we have sent two requests to set a variable without getting - * a response between them, and this is the first response. - * So, ignore it, and wait for the next response. - */ - return; - } else { - change_slc(func, flag, val); - } - -} /* end of process_slc */ - -/* - * change_slc - * - * Process a request to change one of our special characters. - * Compare client's request with what we are capable of supporting. - */ - void -change_slc(func, flag, val) - register char func, flag; - register cc_t val; -{ - register int hislevel, mylevel; - - hislevel = flag & SLC_LEVELBITS; - mylevel = slctab[func].defset.flag & SLC_LEVELBITS; - /* - * If client is setting a function to NOSUPPORT - * or DEFAULT, then we can easily and directly - * accomodate the request. - */ - if (hislevel == SLC_NOSUPPORT) { - slctab[func].current.flag = flag; - slctab[func].current.val = (cc_t)_POSIX_VDISABLE; - flag |= SLC_ACK; - add_slc(func, flag, val); - return; - } - if (hislevel == SLC_DEFAULT) { - /* - * Special case here. If client tells us to use - * the default on a function we don't support, then - * return NOSUPPORT instead of what we may have as a - * default level of DEFAULT. - */ - if (mylevel == SLC_DEFAULT) { - slctab[func].current.flag = SLC_NOSUPPORT; - } else { - slctab[func].current.flag = slctab[func].defset.flag; - } - slctab[func].current.val = slctab[func].defset.val; - add_slc(func, slctab[func].current.flag, - slctab[func].current.val); - return; - } - - /* - * Client wants us to change to a new value or he - * is telling us that he can't change to our value. - * Some of the slc's we support and can change, - * some we do support but can't change, - * and others we don't support at all. - * If we can change it then we have a pointer to - * the place to put the new value, so change it, - * otherwise, continue the negotiation. - */ - if (slctab[func].sptr) { - /* - * We can change this one. - */ - slctab[func].current.val = val; - *(slctab[func].sptr) = val; - slctab[func].current.flag = flag; - flag |= SLC_ACK; - slcchange = 1; - add_slc(func, flag, val); - } else { - /* - * It is not possible for us to support this - * request as he asks. - * - * If our level is DEFAULT, then just ack whatever was - * sent. - * - * If he can't change and we can't change, - * then degenerate to NOSUPPORT. - * - * Otherwise we send our level back to him, (CANTCHANGE - * or NOSUPPORT) and if CANTCHANGE, send - * our value as well. - */ - if (mylevel == SLC_DEFAULT) { - slctab[func].current.flag = flag; - slctab[func].current.val = val; - flag |= SLC_ACK; - } else if (hislevel == SLC_CANTCHANGE && - mylevel == SLC_CANTCHANGE) { - flag &= ~SLC_LEVELBITS; - flag |= SLC_NOSUPPORT; - slctab[func].current.flag = flag; - } else { - flag &= ~SLC_LEVELBITS; - flag |= mylevel; - slctab[func].current.flag = flag; - if (mylevel == SLC_CANTCHANGE) { - slctab[func].current.val = - slctab[func].defset.val; - val = slctab[func].current.val; - } - } - add_slc(func, flag, val); - } - -} /* end of change_slc */ - -#if defined(USE_TERMIO) && (VEOF == VMIN) -cc_t oldeofc = '\004'; -#endif - -/* - * check_slc - * - * Check the special characters in use and notify the client if any have - * changed. Only those characters that are capable of being changed are - * likely to have changed. If a local change occurs, kick the support level - * and flags up to the defaults. - */ - void -check_slc() -{ - register int i; - - for (i = 1; i <= NSLC; i++) { -#if defined(USE_TERMIO) && (VEOF == VMIN) - /* - * In a perfect world this would be a neat little - * function. But in this world, we should not notify - * client of changes to the VEOF char when - * ICANON is off, because it is not representing - * a special character. - */ - if (i == SLC_EOF) { - if (!tty_isediting()) - continue; - else if (slctab[i].sptr) - oldeofc = *(slctab[i].sptr); - } -#endif /* defined(USE_TERMIO) && defined(SYSV_TERMIO) */ - if (slctab[i].sptr && - (*(slctab[i].sptr) != slctab[i].current.val)) { - slctab[i].current.val = *(slctab[i].sptr); - if (*(slctab[i].sptr) == (cc_t)_POSIX_VDISABLE) - slctab[i].current.flag = SLC_NOSUPPORT; - else - slctab[i].current.flag = slctab[i].defset.flag; - add_slc((unsigned char)i, slctab[i].current.flag, - slctab[i].current.val); - } - } -} /* check_slc */ - -/* - * do_opt_slc - * - * Process an slc option buffer. Defer processing of incoming slc's - * until after the terminal state has been processed. Save the first slc - * request that comes along, but discard all others. - * - * ptr points to the beginning of the buffer, len is the length. - */ - void -do_opt_slc(ptr, len) - register unsigned char *ptr; - register int len; -{ - register unsigned char func, flag; - cc_t val; - register unsigned char *end = ptr + len; - - if (terminit()) { /* go ahead */ - while (ptr < end) { - func = *ptr++; - if (ptr >= end) break; - flag = *ptr++; - if (ptr >= end) break; - val = (cc_t)*ptr++; - - process_slc(func, flag, val); - - } - } else { - /* - * save this slc buffer if it is the first, otherwise dump - * it. - */ - if (def_slcbuf == (unsigned char *)0) { - def_slclen = len; - def_slcbuf = (unsigned char *)malloc((unsigned)len); - if (def_slcbuf == (unsigned char *)0) - return; /* too bad */ - memmove(def_slcbuf, ptr, len); - } - } - -} /* end of do_opt_slc */ - -/* - * deferslc - * - * Do slc stuff that was deferred. - */ - void -deferslc() -{ - if (def_slcbuf) { - start_slc(1); - do_opt_slc(def_slcbuf, def_slclen); - (void) end_slc(0); - free(def_slcbuf); - def_slcbuf = (unsigned char *)0; - def_slclen = 0; - } - -} /* end of deferslc */ - -#endif /* LINEMODE */ diff --git a/secure/libexec/telnetd/state.c b/secure/libexec/telnetd/state.c deleted file mode 100644 index 4ee8bea..0000000 --- a/secure/libexec/telnetd/state.c +++ /dev/null @@ -1,1612 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)state.c 8.5 (Berkeley) 5/30/95"; -#endif /* not lint */ - -#include "telnetd.h" -#if defined(AUTHENTICATION) -#include <libtelnet/auth.h> -#endif - -unsigned char doopt[] = { IAC, DO, '%', 'c', 0 }; -unsigned char dont[] = { IAC, DONT, '%', 'c', 0 }; -unsigned char will[] = { IAC, WILL, '%', 'c', 0 }; -unsigned char wont[] = { IAC, WONT, '%', 'c', 0 }; -int not42 = 1; - -/* - * Buffer for sub-options, and macros - * for suboptions buffer manipulations - */ -unsigned char subbuffer[512], *subpointer= subbuffer, *subend= subbuffer; - -#define SB_CLEAR() subpointer = subbuffer -#define SB_TERM() { subend = subpointer; SB_CLEAR(); } -#define SB_ACCUM(c) if (subpointer < (subbuffer+sizeof subbuffer)) { \ - *subpointer++ = (c); \ - } -#define SB_GET() ((*subpointer++)&0xff) -#define SB_EOF() (subpointer >= subend) -#define SB_LEN() (subend - subpointer) - -#ifdef ENV_HACK -unsigned char *subsave; -#define SB_SAVE() subsave = subpointer; -#define SB_RESTORE() subpointer = subsave; -#endif - - -/* - * State for recv fsm - */ -#define TS_DATA 0 /* base state */ -#define TS_IAC 1 /* look for double IAC's */ -#define TS_CR 2 /* CR-LF ->'s CR */ -#define TS_SB 3 /* throw away begin's... */ -#define TS_SE 4 /* ...end's (suboption negotiation) */ -#define TS_WILL 5 /* will option negotiation */ -#define TS_WONT 6 /* wont " */ -#define TS_DO 7 /* do " */ -#define TS_DONT 8 /* dont " */ - - void -telrcv() -{ - register int c; - static int state = TS_DATA; -#if defined(CRAY2) && defined(UNICOS5) - char *opfrontp = pfrontp; -#endif - - while (ncc > 0) { - if ((&ptyobuf[BUFSIZ] - pfrontp) < 2) - break; - c = *netip++ & 0377, ncc--; -#ifdef ENCRYPTION - if (decrypt_input) - c = (*decrypt_input)(c); -#endif /* ENCRYPTION */ - switch (state) { - - case TS_CR: - state = TS_DATA; - /* Strip off \n or \0 after a \r */ - if ((c == 0) || (c == '\n')) { - break; - } - /* FALL THROUGH */ - - case TS_DATA: - if (c == IAC) { - state = TS_IAC; - break; - } - /* - * We now map \r\n ==> \r for pragmatic reasons. - * Many client implementations send \r\n when - * the user hits the CarriageReturn key. - * - * We USED to map \r\n ==> \n, since \r\n says - * that we want to be in column 1 of the next - * printable line, and \n is the standard - * unix way of saying that (\r is only good - * if CRMOD is set, which it normally is). - */ - if ((c == '\r') && his_state_is_wont(TELOPT_BINARY)) { - int nc = *netip; -#ifdef ENCRYPTION - if (decrypt_input) - nc = (*decrypt_input)(nc & 0xff); -#endif /* ENCRYPTION */ -#ifdef LINEMODE - /* - * If we are operating in linemode, - * convert to local end-of-line. - */ - if (linemode && (ncc > 0) && (('\n' == nc) || - ((0 == nc) && tty_iscrnl())) ) { - netip++; ncc--; - c = '\n'; - } else -#endif - { -#ifdef ENCRYPTION - if (decrypt_input) - (void)(*decrypt_input)(-1); -#endif /* ENCRYPTION */ - state = TS_CR; - } - } - *pfrontp++ = c; - break; - - case TS_IAC: -gotiac: switch (c) { - - /* - * Send the process on the pty side an - * interrupt. Do this with a NULL or - * interrupt char; depending on the tty mode. - */ - case IP: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - interrupt(); - break; - - case BREAK: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - sendbrk(); - break; - - /* - * Are You There? - */ - case AYT: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - recv_ayt(); - break; - - /* - * Abort Output - */ - case AO: - { - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - - if (slctab[SLC_AO].sptr && - *slctab[SLC_AO].sptr != (cc_t)(_POSIX_VDISABLE)) { - *pfrontp++ = - (unsigned char)*slctab[SLC_AO].sptr; - } - - netclear(); /* clear buffer back */ - *nfrontp++ = IAC; - *nfrontp++ = DM; - neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - break; - } - - /* - * Erase Character and - * Erase Line - */ - case EC: - case EL: - { - cc_t ch; - - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - ptyflush(); /* half-hearted */ - init_termbuf(); - if (c == EC) - ch = *slctab[SLC_EC].sptr; - else - ch = *slctab[SLC_EL].sptr; - if (ch != (cc_t)(_POSIX_VDISABLE)) - *pfrontp++ = (unsigned char)ch; - break; - } - - /* - * Check for urgent data... - */ - case DM: - DIAG(TD_OPTIONS, - printoption("td: recv IAC", c)); - SYNCHing = stilloob(net); - settimer(gotDM); - break; - - - /* - * Begin option subnegotiation... - */ - case SB: - state = TS_SB; - SB_CLEAR(); - continue; - - case WILL: - state = TS_WILL; - continue; - - case WONT: - state = TS_WONT; - continue; - - case DO: - state = TS_DO; - continue; - - case DONT: - state = TS_DONT; - continue; - case EOR: - if (his_state_is_will(TELOPT_EOR)) - doeof(); - break; - - /* - * Handle RFC 10xx Telnet linemode option additions - * to command stream (EOF, SUSP, ABORT). - */ - case xEOF: - doeof(); - break; - - case SUSP: - sendsusp(); - break; - - case ABORT: - sendbrk(); - break; - - case IAC: - *pfrontp++ = c; - break; - } - state = TS_DATA; - break; - - case TS_SB: - if (c == IAC) { - state = TS_SE; - } else { - SB_ACCUM(c); - } - break; - - case TS_SE: - if (c != SE) { - if (c != IAC) { - /* - * bad form of suboption negotiation. - * handle it in such a way as to avoid - * damage to local state. Parse - * suboption buffer found so far, - * then treat remaining stream as - * another command sequence. - */ - - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(c); - subpointer -= 2; - - SB_TERM(); - suboption(); - state = TS_IAC; - goto gotiac; - } - SB_ACCUM(c); - state = TS_SB; - } else { - /* for DIAGNOSTICS */ - SB_ACCUM(IAC); - SB_ACCUM(SE); - subpointer -= 2; - - SB_TERM(); - suboption(); /* handle sub-option */ - state = TS_DATA; - } - break; - - case TS_WILL: - willoption(c); - state = TS_DATA; - continue; - - case TS_WONT: - wontoption(c); - state = TS_DATA; - continue; - - case TS_DO: - dooption(c); - state = TS_DATA; - continue; - - case TS_DONT: - dontoption(c); - state = TS_DATA; - continue; - - default: - syslog(LOG_ERR, "telnetd: panic state=%d\n", state); - printf("telnetd: panic state=%d\n", state); - exit(1); - } - } -#if defined(CRAY2) && defined(UNICOS5) - if (!linemode) { - char xptyobuf[BUFSIZ+NETSLOP]; - char xbuf2[BUFSIZ]; - register char *cp; - int n = pfrontp - opfrontp, oc; - memmove(xptyobuf, opfrontp, n); - pfrontp = opfrontp; - pfrontp += term_input(xptyobuf, pfrontp, n, BUFSIZ+NETSLOP, - xbuf2, &oc, BUFSIZ); - for (cp = xbuf2; oc > 0; --oc) - if ((*nfrontp++ = *cp++) == IAC) - *nfrontp++ = IAC; - } -#endif /* defined(CRAY2) && defined(UNICOS5) */ -} /* end of telrcv */ - -/* - * The will/wont/do/dont state machines are based on Dave Borman's - * Telnet option processing state machine. - * - * These correspond to the following states: - * my_state = the last negotiated state - * want_state = what I want the state to go to - * want_resp = how many requests I have sent - * All state defaults are negative, and resp defaults to 0. - * - * When initiating a request to change state to new_state: - * - * if ((want_resp == 0 && new_state == my_state) || want_state == new_state) { - * do nothing; - * } else { - * want_state = new_state; - * send new_state; - * want_resp++; - * } - * - * When receiving new_state: - * - * if (want_resp) { - * want_resp--; - * if (want_resp && (new_state == my_state)) - * want_resp--; - * } - * if ((want_resp == 0) && (new_state != want_state)) { - * if (ok_to_switch_to new_state) - * want_state = new_state; - * else - * want_resp++; - * send want_state; - * } - * my_state = new_state; - * - * Note that new_state is implied in these functions by the function itself. - * will and do imply positive new_state, wont and dont imply negative. - * - * Finally, there is one catch. If we send a negative response to a - * positive request, my_state will be the positive while want_state will - * remain negative. my_state will revert to negative when the negative - * acknowlegment arrives from the peer. Thus, my_state generally tells - * us not only the last negotiated state, but also tells us what the peer - * wants to be doing as well. It is important to understand this difference - * as we may wish to be processing data streams based on our desired state - * (want_state) or based on what the peer thinks the state is (my_state). - * - * This all works fine because if the peer sends a positive request, the data - * that we receive prior to negative acknowlegment will probably be affected - * by the positive state, and we can process it as such (if we can; if we - * can't then it really doesn't matter). If it is that important, then the - * peer probably should be buffering until this option state negotiation - * is complete. - * - */ - void -send_do(option, init) - int option, init; -{ - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_will(option)) || - his_want_state_is_will(option)) - return; - /* - * Special case for TELOPT_TM: We send a DO, but pretend - * that we sent a DONT, so that we can send more DOs if - * we want to. - */ - if (option == TELOPT_TM) - set_his_want_state_wont(option); - else - set_his_want_state_will(option); - do_dont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)doopt, option); - nfrontp += sizeof (dont) - 2; - - DIAG(TD_OPTIONS, printoption("td: send do", option)); -} - -#ifdef AUTHENTICATION -extern void auth_request(); -#endif -#ifdef LINEMODE -extern void doclientstat(); -#endif -#ifdef ENCRYPTION -extern void encrypt_send_support(); -#endif /* ENCRYPTION */ - - void -willoption(option) - int option; -{ - int changeok = 0; - void (*func)() = 0; - - /* - * process input from peer. - */ - - DIAG(TD_OPTIONS, printoption("td: recv will", option)); - - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_will(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_wont(option)) { - switch (option) { - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(1); - set_termbuf(); - changeok++; - break; - - case TELOPT_ECHO: - /* - * See comments below for more info. - */ - not42 = 0; /* looks like a 4.2 system */ - break; - - case TELOPT_TM: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * This telnetd implementation does not really - * support timing marks, it just uses them to - * support the kludge linemode stuff. If we - * receive a will or wont TM in response to our - * do TM request that may have been sent to - * determine kludge linemode support, process - * it, otherwise TM should get a negative - * response back. - */ - /* - * Handle the linemode kludge stuff. - * If we are not currently supporting any - * linemode at all, then we assume that this - * is the client telling us to use kludge - * linemode in response to our query. Set the - * linemode type that is to be supported, note - * that the client wishes to use linemode, and - * eat the will TM as though it never arrived. - */ - if (lmodetype < KLUDGE_LINEMODE) { - lmodetype = KLUDGE_LINEMODE; - clientstat(TELOPT_LINEMODE, WILL, 0); - send_wont(TELOPT_SGA, 1); - } else if (lmodetype == NO_AUTOKLUDGE) { - lmodetype = KLUDGE_OK; - } -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - /* - * We never respond to a WILL TM, and - * we leave the state WONT. - */ - return; - - case TELOPT_LFLOW: - /* - * If we are going to support flow control - * option, then don't worry peer that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_DEFAULT; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_DEFAULT; - case TELOPT_TTYPE: - case TELOPT_SGA: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_XDISPLOC: - case TELOPT_NEW_ENVIRON: - case TELOPT_OLD_ENVIRON: - changeok++; - break; - -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * Note client's desire to use linemode. - */ - lmodetype = REAL_LINEMODE; -# endif /* KLUDGELINEMODE */ - func = doclientstat; - changeok++; - break; -#endif /* LINEMODE */ - -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - changeok++; - break; -#endif - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - changeok++; - break; -#endif /* ENCRYPTION */ - - default: - break; - } - if (changeok) { - set_his_want_state_will(option); - send_do(option, 0); - } else { - do_dont_resp[option]++; - send_dont(option, 0); - } - } else { - /* - * Option processing that should happen when - * we receive conformation of a change in - * state that we had requested. - */ - switch (option) { - case TELOPT_ECHO: - not42 = 0; /* looks like a 4.2 system */ - /* - * Egads, he responded "WILL ECHO". Turn - * it off right now! - */ - send_dont(option, 1); - /* - * "WILL ECHO". Kludge upon kludge! - * A 4.2 client is now echoing user input at - * the tty. This is probably undesireable and - * it should be stopped. The client will - * respond WONT TM to the DO TM that we send to - * check for kludge linemode. When the WONT TM - * arrives, linemode will be turned off and a - * change propogated to the pty. This change - * will cause us to process the new pty state - * in localstat(), which will notice that - * linemode is off and send a WILL ECHO - * so that we are properly in character mode and - * all is well. - */ - break; -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * Note client's desire to use linemode. - */ - lmodetype = REAL_LINEMODE; -# endif /* KLUDGELINEMODE */ - func = doclientstat; - break; -#endif /* LINEMODE */ - -#ifdef AUTHENTICATION - case TELOPT_AUTHENTICATION: - func = auth_request; - break; -#endif - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - func = encrypt_send_support; - break; -#endif /* ENCRYPTION */ - case TELOPT_LFLOW: - func = flowstat; - break; - } - } - } - set_his_state_will(option); - if (func) - (*func)(); -} /* end of willoption */ - - void -send_dont(option, init) - int option, init; -{ - if (init) { - if ((do_dont_resp[option] == 0 && his_state_is_wont(option)) || - his_want_state_is_wont(option)) - return; - set_his_want_state_wont(option); - do_dont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)dont, option); - nfrontp += sizeof (doopt) - 2; - - DIAG(TD_OPTIONS, printoption("td: send dont", option)); -} - - void -wontoption(option) - int option; -{ - /* - * Process client input. - */ - - DIAG(TD_OPTIONS, printoption("td: recv wont", option)); - - if (do_dont_resp[option]) { - do_dont_resp[option]--; - if (do_dont_resp[option] && his_state_is_wont(option)) - do_dont_resp[option]--; - } - if (do_dont_resp[option] == 0) { - if (his_want_state_is_will(option)) { - /* it is always ok to change to negative state */ - switch (option) { - case TELOPT_ECHO: - not42 = 1; /* doesn't seem to be a 4.2 system */ - break; - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryin(0); - set_termbuf(); - break; - -#ifdef LINEMODE - case TELOPT_LINEMODE: -# ifdef KLUDGELINEMODE - /* - * If real linemode is supported, then client is - * asking to turn linemode off. - */ - if (lmodetype != REAL_LINEMODE) - break; -# endif /* KLUDGELINEMODE */ - clientstat(TELOPT_LINEMODE, WONT, 0); - break; -#endif /* LINEMODE */ - - case TELOPT_TM: - /* - * If we get a WONT TM, and had sent a DO TM, - * don't respond with a DONT TM, just leave it - * as is. Short circut the state machine to - * achive this. - */ - set_his_want_state_wont(TELOPT_TM); - return; - - case TELOPT_LFLOW: - /* - * If we are not going to support flow control - * option, then let peer know that we can't - * change the flow control characters. - */ - slctab[SLC_XON].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XON].defset.flag |= SLC_CANTCHANGE; - slctab[SLC_XOFF].defset.flag &= ~SLC_LEVELBITS; - slctab[SLC_XOFF].defset.flag |= SLC_CANTCHANGE; - break; - -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; -#endif - - /* - * For options that we might spin waiting for - * sub-negotiation, if the client turns off the - * option rather than responding to the request, - * we have to treat it here as if we got a response - * to the sub-negotiation, (by updating the timers) - * so that we'll break out of the loop. - */ - case TELOPT_TTYPE: - settimer(ttypesubopt); - break; - - case TELOPT_TSPEED: - settimer(tspeedsubopt); - break; - - case TELOPT_XDISPLOC: - settimer(xdisplocsubopt); - break; - - case TELOPT_OLD_ENVIRON: - settimer(oenvironsubopt); - break; - - case TELOPT_NEW_ENVIRON: - settimer(environsubopt); - break; - - default: - break; - } - set_his_want_state_wont(option); - if (his_state_is_will(option)) - send_dont(option, 0); - } else { - switch (option) { - case TELOPT_TM: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - if (lmodetype < NO_AUTOKLUDGE) { - lmodetype = NO_LINEMODE; - clientstat(TELOPT_LINEMODE, WONT, 0); - send_will(TELOPT_SGA, 1); - send_will(TELOPT_ECHO, 1); - } -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - break; - -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - auth_finished(0, AUTH_REJECT); - break; -#endif - default: - break; - } - } - } - set_his_state_wont(option); - -} /* end of wontoption */ - - void -send_will(option, init) - int option, init; -{ - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_will(option))|| - my_want_state_is_will(option)) - return; - set_my_want_state_will(option); - will_wont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)will, option); - nfrontp += sizeof (doopt) - 2; - - DIAG(TD_OPTIONS, printoption("td: send will", option)); -} - -#if !defined(LINEMODE) || !defined(KLUDGELINEMODE) -/* - * When we get a DONT SGA, we will try once to turn it - * back on. If the other side responds DONT SGA, we - * leave it at that. This is so that when we talk to - * clients that understand KLUDGELINEMODE but not LINEMODE, - * we'll keep them in char-at-a-time mode. - */ -int turn_on_sga = 0; -#endif - - void -dooption(option) - int option; -{ - int changeok = 0; - - /* - * Process client input. - */ - - DIAG(TD_OPTIONS, printoption("td: recv do", option)); - - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_will(option)) - will_wont_resp[option]--; - } - if ((will_wont_resp[option] == 0) && (my_want_state_is_wont(option))) { - switch (option) { - case TELOPT_ECHO: -#ifdef LINEMODE -# ifdef KLUDGELINEMODE - if (lmodetype == NO_LINEMODE) -# else - if (his_state_is_wont(TELOPT_LINEMODE)) -# endif -#endif - { - init_termbuf(); - tty_setecho(1); - set_termbuf(); - } - changeok++; - break; - - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(1); - set_termbuf(); - changeok++; - break; - - case TELOPT_SGA: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * If kludge linemode is in use, then we must - * process an incoming do SGA for linemode - * purposes. - */ - if (lmodetype == KLUDGE_LINEMODE) { - /* - * Receipt of "do SGA" in kludge - * linemode is the peer asking us to - * turn off linemode. Make note of - * the request. - */ - clientstat(TELOPT_LINEMODE, WONT, 0); - /* - * If linemode did not get turned off - * then don't tell peer that we did. - * Breaking here forces a wont SGA to - * be returned. - */ - if (linemode) - break; - } -#else - turn_on_sga = 0; -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - changeok++; - break; - - case TELOPT_STATUS: - changeok++; - break; - - case TELOPT_TM: - /* - * Special case for TM. We send a WILL, but - * pretend we sent a WONT. - */ - send_will(option, 0); - set_my_want_state_wont(option); - set_my_state_wont(option); - return; - - case TELOPT_LOGOUT: - /* - * When we get a LOGOUT option, respond - * with a WILL LOGOUT, make sure that - * it gets written out to the network, - * and then just go away... - */ - set_my_want_state_will(TELOPT_LOGOUT); - send_will(TELOPT_LOGOUT, 0); - set_my_state_will(TELOPT_LOGOUT); - (void)netflush(); - cleanup(0); - /* NOT REACHED */ - break; - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - changeok++; - break; -#endif /* ENCRYPTION */ - case TELOPT_LINEMODE: - case TELOPT_TTYPE: - case TELOPT_NAWS: - case TELOPT_TSPEED: - case TELOPT_LFLOW: - case TELOPT_XDISPLOC: -#ifdef TELOPT_ENVIRON - case TELOPT_NEW_ENVIRON: -#endif - case TELOPT_OLD_ENVIRON: - default: - break; - } - if (changeok) { - set_my_want_state_will(option); - send_will(option, 0); - } else { - will_wont_resp[option]++; - send_wont(option, 0); - } - } - set_my_state_will(option); - -} /* end of dooption */ - - void -send_wont(option, init) - int option, init; -{ - if (init) { - if ((will_wont_resp[option] == 0 && my_state_is_wont(option)) || - my_want_state_is_wont(option)) - return; - set_my_want_state_wont(option); - will_wont_resp[option]++; - } - (void) sprintf(nfrontp, (char *)wont, option); - nfrontp += sizeof (wont) - 2; - - DIAG(TD_OPTIONS, printoption("td: send wont", option)); -} - - void -dontoption(option) - int option; -{ - /* - * Process client input. - */ - - - DIAG(TD_OPTIONS, printoption("td: recv dont", option)); - - if (will_wont_resp[option]) { - will_wont_resp[option]--; - if (will_wont_resp[option] && my_state_is_wont(option)) - will_wont_resp[option]--; - } - if ((will_wont_resp[option] == 0) && (my_want_state_is_will(option))) { - switch (option) { - case TELOPT_BINARY: - init_termbuf(); - tty_binaryout(0); - set_termbuf(); - break; - - case TELOPT_ECHO: /* we should stop echoing */ -#ifdef LINEMODE -# ifdef KLUDGELINEMODE - if ((lmodetype != REAL_LINEMODE) && - (lmodetype != KLUDGE_LINEMODE)) -# else - if (his_state_is_wont(TELOPT_LINEMODE)) -# endif -#endif - { - init_termbuf(); - tty_setecho(0); - set_termbuf(); - } - break; - - case TELOPT_SGA: -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * If kludge linemode is in use, then we - * must process an incoming do SGA for - * linemode purposes. - */ - if ((lmodetype == KLUDGE_LINEMODE) || - (lmodetype == KLUDGE_OK)) { - /* - * The client is asking us to turn - * linemode on. - */ - lmodetype = KLUDGE_LINEMODE; - clientstat(TELOPT_LINEMODE, WILL, 0); - /* - * If we did not turn line mode on, - * then what do we say? Will SGA? - * This violates design of telnet. - * Gross. Very Gross. - */ - } - break; -#else - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); - set_my_state_wont(option); - if (turn_on_sga ^= 1) - send_will(option, 1); - return; -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - - default: - break; - } - - set_my_want_state_wont(option); - if (my_state_is_will(option)) - send_wont(option, 0); - } - set_my_state_wont(option); - -} /* end of dontoption */ - -#ifdef ENV_HACK -int env_ovar = -1; -int env_ovalue = -1; -#else /* ENV_HACK */ -# define env_ovar OLD_ENV_VAR -# define env_ovalue OLD_ENV_VALUE -#endif /* ENV_HACK */ - -/* - * suboption() - * - * Look at the sub-option buffer, and try to be helpful to the other - * side. - * - * Currently we recognize: - * - * Terminal type is - * Linemode - * Window size - * Terminal speed - */ - void -suboption() -{ - register int subchar; - - DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);}); - - subchar = SB_GET(); - switch (subchar) { - case TELOPT_TSPEED: { - register int xspeed, rspeed; - - if (his_state_is_wont(TELOPT_TSPEED)) /* Ignore if option disabled */ - break; - - settimer(tspeedsubopt); - - if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; - - xspeed = atoi((char *)subpointer); - - while (SB_GET() != ',' && !SB_EOF()); - if (SB_EOF()) - return; - - rspeed = atoi((char *)subpointer); - clientstat(TELOPT_TSPEED, xspeed, rspeed); - - break; - - } /* end of case TELOPT_TSPEED */ - - case TELOPT_TTYPE: { /* Yaaaay! */ - static char terminalname[41]; - - if (his_state_is_wont(TELOPT_TTYPE)) /* Ignore if option disabled */ - break; - settimer(ttypesubopt); - - if (SB_EOF() || SB_GET() != TELQUAL_IS) { - return; /* ??? XXX but, this is the most robust */ - } - - terminaltype = terminalname; - - while ((terminaltype < (terminalname + sizeof terminalname-1)) && - !SB_EOF()) { - register int c; - - c = SB_GET(); - if (isupper(c)) { - c = tolower(c); - } - *terminaltype++ = c; /* accumulate name */ - } - *terminaltype = 0; - terminaltype = terminalname; - break; - } /* end of case TELOPT_TTYPE */ - - case TELOPT_NAWS: { - register int xwinsize, ywinsize; - - if (his_state_is_wont(TELOPT_NAWS)) /* Ignore if option disabled */ - break; - - if (SB_EOF()) - return; - xwinsize = SB_GET() << 8; - if (SB_EOF()) - return; - xwinsize |= SB_GET(); - if (SB_EOF()) - return; - ywinsize = SB_GET() << 8; - if (SB_EOF()) - return; - ywinsize |= SB_GET(); - clientstat(TELOPT_NAWS, xwinsize, ywinsize); - - break; - - } /* end of case TELOPT_NAWS */ - -#ifdef LINEMODE - case TELOPT_LINEMODE: { - register int request; - - if (his_state_is_wont(TELOPT_LINEMODE)) /* Ignore if option disabled */ - break; - /* - * Process linemode suboptions. - */ - if (SB_EOF()) - break; /* garbage was sent */ - request = SB_GET(); /* get will/wont */ - - if (SB_EOF()) - break; /* another garbage check */ - - if (request == LM_SLC) { /* SLC is not preceeded by WILL or WONT */ - /* - * Process suboption buffer of slc's - */ - start_slc(1); - do_opt_slc(subpointer, subend - subpointer); - (void) end_slc(0); - break; - } else if (request == LM_MODE) { - if (SB_EOF()) - return; - useeditmode = SB_GET(); /* get mode flag */ - clientstat(LM_MODE, 0, 0); - break; - } - - if (SB_EOF()) - break; - switch (SB_GET()) { /* what suboption? */ - case LM_FORWARDMASK: - /* - * According to spec, only server can send request for - * forwardmask, and client can only return a positive response. - * So don't worry about it. - */ - - default: - break; - } - break; - } /* end of case TELOPT_LINEMODE */ -#endif - case TELOPT_STATUS: { - int mode; - - if (SB_EOF()) - break; - mode = SB_GET(); - switch (mode) { - case TELQUAL_SEND: - if (my_state_is_will(TELOPT_STATUS)) - send_status(); - break; - - case TELQUAL_IS: - break; - - default: - break; - } - break; - } /* end of case TELOPT_STATUS */ - - case TELOPT_XDISPLOC: { - if (SB_EOF() || SB_GET() != TELQUAL_IS) - return; - settimer(xdisplocsubopt); - subpointer[SB_LEN()] = '\0'; - (void)setenv("DISPLAY", (char *)subpointer, 1); - break; - } /* end of case TELOPT_XDISPLOC */ - -#ifdef TELOPT_NEW_ENVIRON - case TELOPT_NEW_ENVIRON: -#endif - case TELOPT_OLD_ENVIRON: { - register int c; - register char *cp, *varp, *valp; - - if (SB_EOF()) - return; - c = SB_GET(); - if (c == TELQUAL_IS) { - if (subchar == TELOPT_OLD_ENVIRON) - settimer(oenvironsubopt); - else - settimer(environsubopt); - } else if (c != TELQUAL_INFO) { - return; - } - -#ifdef TELOPT_NEW_ENVIRON - if (subchar == TELOPT_NEW_ENVIRON) { - while (!SB_EOF()) { - c = SB_GET(); - if ((c == NEW_ENV_VAR) || (c == ENV_USERVAR)) - break; - } - } else -#endif - { -#ifdef ENV_HACK - /* - * We only want to do this if we haven't already decided - * whether or not the other side has its VALUE and VAR - * reversed. - */ - if (env_ovar < 0) { - register int last = -1; /* invalid value */ - int empty = 0; - int got_var = 0, got_value = 0, got_uservar = 0; - - /* - * The other side might have its VALUE and VAR values - * reversed. To be interoperable, we need to determine - * which way it is. If the first recognized character - * is a VAR or VALUE, then that will tell us what - * type of client it is. If the fist recognized - * character is a USERVAR, then we continue scanning - * the suboption looking for two consecutive - * VAR or VALUE fields. We should not get two - * consecutive VALUE fields, so finding two - * consecutive VALUE or VAR fields will tell us - * what the client is. - */ - SB_SAVE(); - while (!SB_EOF()) { - c = SB_GET(); - switch(c) { - case OLD_ENV_VAR: - if (last < 0 || last == OLD_ENV_VAR - || (empty && (last == OLD_ENV_VALUE))) - goto env_ovar_ok; - got_var++; - last = OLD_ENV_VAR; - break; - case OLD_ENV_VALUE: - if (last < 0 || last == OLD_ENV_VALUE - || (empty && (last == OLD_ENV_VAR))) - goto env_ovar_wrong; - got_value++; - last = OLD_ENV_VALUE; - break; - case ENV_USERVAR: - /* count strings of USERVAR as one */ - if (last != ENV_USERVAR) - got_uservar++; - if (empty) { - if (last == OLD_ENV_VALUE) - goto env_ovar_ok; - if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - last = ENV_USERVAR; - break; - case ENV_ESC: - if (!SB_EOF()) - c = SB_GET(); - /* FALL THROUGH */ - default: - empty = 0; - continue; - } - empty = 1; - } - if (empty) { - if (last == OLD_ENV_VALUE) - goto env_ovar_ok; - if (last == OLD_ENV_VAR) - goto env_ovar_wrong; - } - /* - * Ok, the first thing was a USERVAR, and there - * are not two consecutive VAR or VALUE commands, - * and none of the VAR or VALUE commands are empty. - * If the client has sent us a well-formed option, - * then the number of VALUEs received should always - * be less than or equal to the number of VARs and - * USERVARs received. - * - * If we got exactly as many VALUEs as VARs and - * USERVARs, the client has the same definitions. - * - * If we got exactly as many VARs as VALUEs and - * USERVARS, the client has reversed definitions. - */ - if (got_uservar + got_var == got_value) { - env_ovar_ok: - env_ovar = OLD_ENV_VAR; - env_ovalue = OLD_ENV_VALUE; - } else if (got_uservar + got_value == got_var) { - env_ovar_wrong: - env_ovar = OLD_ENV_VALUE; - env_ovalue = OLD_ENV_VAR; - DIAG(TD_OPTIONS, {sprintf(nfrontp, - "ENVIRON VALUE and VAR are reversed!\r\n"); - nfrontp += strlen(nfrontp);}); - - } - } - SB_RESTORE(); -#endif - - while (!SB_EOF()) { - c = SB_GET(); - if ((c == env_ovar) || (c == ENV_USERVAR)) - break; - } - } - - if (SB_EOF()) - return; - - cp = varp = (char *)subpointer; - valp = 0; - - while (!SB_EOF()) { - c = SB_GET(); - if (subchar == TELOPT_OLD_ENVIRON) { - if (c == env_ovar) - c = NEW_ENV_VAR; - else if (c == env_ovalue) - c = NEW_ENV_VALUE; - } - switch (c) { - - case NEW_ENV_VALUE: - *cp = '\0'; - cp = valp = (char *)subpointer; - break; - - case NEW_ENV_VAR: - case ENV_USERVAR: - *cp = '\0'; - if (valp) - (void)setenv(varp, valp, 1); - else - unsetenv(varp); - cp = varp = (char *)subpointer; - valp = 0; - break; - - case ENV_ESC: - if (SB_EOF()) - break; - c = SB_GET(); - /* FALL THROUGH */ - default: - *cp++ = c; - break; - } - } - *cp = '\0'; - if (valp) - (void)setenv(varp, valp, 1); - else - unsetenv(varp); - break; - } /* end of case TELOPT_NEW_ENVIRON */ -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - if (SB_EOF()) - break; - switch(SB_GET()) { - case TELQUAL_SEND: - case TELQUAL_REPLY: - /* - * These are sent by us and cannot be sent by - * the client. - */ - break; - case TELQUAL_IS: - auth_is(subpointer, SB_LEN()); - break; - case TELQUAL_NAME: - auth_name(subpointer, SB_LEN()); - break; - } - break; -#endif -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - if (SB_EOF()) - break; - switch(SB_GET()) { - case ENCRYPT_SUPPORT: - encrypt_support(subpointer, SB_LEN()); - break; - case ENCRYPT_IS: - encrypt_is(subpointer, SB_LEN()); - break; - case ENCRYPT_REPLY: - encrypt_reply(subpointer, SB_LEN()); - break; - case ENCRYPT_START: - encrypt_start(subpointer, SB_LEN()); - break; - case ENCRYPT_END: - encrypt_end(); - break; - case ENCRYPT_REQSTART: - encrypt_request_start(subpointer, SB_LEN()); - break; - case ENCRYPT_REQEND: - /* - * We can always send an REQEND so that we cannot - * get stuck encrypting. We should only get this - * if we have been able to get in the correct mode - * anyhow. - */ - encrypt_request_end(); - break; - case ENCRYPT_ENC_KEYID: - encrypt_enc_keyid(subpointer, SB_LEN()); - break; - case ENCRYPT_DEC_KEYID: - encrypt_dec_keyid(subpointer, SB_LEN()); - break; - default: - break; - } - break; -#endif /* ENCRYPTION */ - - default: - break; - } /* end of switch */ - -} /* end of suboption */ - - void -doclientstat() -{ - clientstat(TELOPT_LINEMODE, WILL, 0); -} - -#define ADD(c) *ncp++ = c -#define ADD_DATA(c) { *ncp++ = c; if (c == SE || c == IAC) *ncp++ = c; } - void -send_status() -{ - unsigned char statusbuf[256]; - register unsigned char *ncp; - register unsigned char i; - - ncp = statusbuf; - - netflush(); /* get rid of anything waiting to go out */ - - ADD(IAC); - ADD(SB); - ADD(TELOPT_STATUS); - ADD(TELQUAL_IS); - - /* - * We check the want_state rather than the current state, - * because if we received a DO/WILL for an option that we - * don't support, and the other side didn't send a DONT/WONT - * in response to our WONT/DONT, then the "state" will be - * WILL/DO, and the "want_state" will be WONT/DONT. We - * need to go by the latter. - */ - for (i = 0; i < (unsigned char)NTELOPTS; i++) { - if (my_want_state_is_will(i)) { - ADD(WILL); - ADD_DATA(i); - } - if (his_want_state_is_will(i)) { - ADD(DO); - ADD_DATA(i); - } - } - - if (his_want_state_is_will(TELOPT_LFLOW)) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (flowmode) { - ADD(LFLOW_ON); - } else { - ADD(LFLOW_OFF); - } - ADD(SE); - - if (restartany >= 0) { - ADD(SB); - ADD(TELOPT_LFLOW); - if (restartany) { - ADD(LFLOW_RESTART_ANY); - } else { - ADD(LFLOW_RESTART_XON); - } - ADD(SE); - } - } - -#ifdef LINEMODE - if (his_want_state_is_will(TELOPT_LINEMODE)) { - unsigned char *cp, *cpe; - int len; - - ADD(SB); - ADD(TELOPT_LINEMODE); - ADD(LM_MODE); - ADD_DATA(editmode); - ADD(SE); - - ADD(SB); - ADD(TELOPT_LINEMODE); - ADD(LM_SLC); - start_slc(0); - send_slc(); - len = end_slc(&cp); - for (cpe = cp + len; cp < cpe; cp++) - ADD_DATA(*cp); - ADD(SE); - } -#endif /* LINEMODE */ - - ADD(IAC); - ADD(SE); - - writenet(statusbuf, ncp - statusbuf); - netflush(); /* Send it on its way */ - - DIAG(TD_OPTIONS, - {printsub('>', statusbuf, ncp - statusbuf); netflush();}); -} diff --git a/secure/libexec/telnetd/sys_term.c b/secure/libexec/telnetd/sys_term.c deleted file mode 100644 index cb8245f..0000000 --- a/secure/libexec/telnetd/sys_term.c +++ /dev/null @@ -1,2324 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95"; -#endif /* not lint */ - -#include "telnetd.h" -#include "pathnames.h" - -#if defined(AUTHENTICATION) -#include <libtelnet/auth.h> -#endif - -extern char *altlogin; - -#if defined(CRAY) || defined(__hpux) -# define PARENT_DOES_UTMP -#endif - -int utmp_len = MAXHOSTNAMELEN; -#ifdef NEWINIT -#include <initreq.h> -#else /* NEWINIT*/ -# ifdef UTMPX -# include <utmpx.h> -struct utmpx wtmp; -# else -# include <utmp.h> -struct utmp wtmp; -# endif /* UTMPX */ - -# ifndef PARENT_DOES_UTMP -#ifdef _PATH_WTMP -char wtmpf[] = _PATH_WTMP; -#else -char wtmpf[] = "/usr/adm/wtmp"; -#endif -#ifdef _PATH_UTMP -char utmpf[] = _PATH_UTMP; -#else -char utmpf[] = "/etc/utmp"; -#endif -# else /* PARENT_DOES_UTMP */ -char wtmpf[] = "/etc/wtmp"; -# endif /* PARENT_DOES_UTMP */ - -# ifdef CRAY -#include <tmpdir.h> -#include <sys/wait.h> -# if (UNICOS_LVL == '7.0') || (UNICOS_LVL == '7.1') -# define UNICOS7x -# endif - -# ifdef UNICOS7x -#include <sys/sysv.h> -#include <sys/secstat.h> -extern int secflag; -extern struct sysv sysv; -# endif /* UNICOS7x */ -# endif /* CRAY */ -#endif /* NEWINIT */ - -#ifdef STREAMSPTY -#include <sac.h> -#include <sys/stropts.h> -#endif - -#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a)) -#define SCMPN(a, b) strncmp(a, b, sizeof(a)) - -#ifdef STREAMS -#include <sys/stream.h> -#endif -#ifdef __hpux -#include <sys/resource.h> -#include <sys/proc.h> -#endif -#include <sys/tty.h> -#ifdef t_erase -#undef t_erase -#undef t_kill -#undef t_intrc -#undef t_quitc -#undef t_startc -#undef t_stopc -#undef t_eofc -#undef t_brkc -#undef t_suspc -#undef t_dsuspc -#undef t_rprntc -#undef t_flushc -#undef t_werasc -#undef t_lnextc -#endif - -#if defined(UNICOS5) && defined(CRAY2) && !defined(EXTPROC) -# define EXTPROC 0400 -#endif - -#ifndef USE_TERMIO -struct termbuf { - struct sgttyb sg; - struct tchars tc; - struct ltchars ltc; - int state; - int lflags; -} termbuf, termbuf2; -# define cfsetospeed(tp, val) (tp)->sg.sg_ospeed = (val) -# define cfsetispeed(tp, val) (tp)->sg.sg_ispeed = (val) -# define cfgetospeed(tp) (tp)->sg.sg_ospeed -# define cfgetispeed(tp) (tp)->sg.sg_ispeed -#else /* USE_TERMIO */ -# ifdef SYSV_TERMIO -# define termios termio -# endif -# ifndef TCSANOW -# ifdef TCSETS -# define TCSANOW TCSETS -# define TCSADRAIN TCSETSW -# define tcgetattr(f, t) ioctl(f, TCGETS, (char *)t) -# else -# ifdef TCSETA -# define TCSANOW TCSETA -# define TCSADRAIN TCSETAW -# define tcgetattr(f, t) ioctl(f, TCGETA, (char *)t) -# else -# define TCSANOW TIOCSETA -# define TCSADRAIN TIOCSETAW -# define tcgetattr(f, t) ioctl(f, TIOCGETA, (char *)t) -# endif -# endif -# define tcsetattr(f, a, t) ioctl(f, a, t) -# define cfsetospeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ - (tp)->c_cflag |= (val) -# define cfgetospeed(tp) ((tp)->c_cflag & CBAUD) -# ifdef CIBAUD -# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CIBAUD; \ - (tp)->c_cflag |= ((val)<<IBSHIFT) -# define cfgetispeed(tp) (((tp)->c_cflag & CIBAUD)>>IBSHIFT) -# else -# define cfsetispeed(tp, val) (tp)->c_cflag &= ~CBAUD; \ - (tp)->c_cflag |= (val) -# define cfgetispeed(tp) ((tp)->c_cflag & CBAUD) -# endif -# endif /* TCSANOW */ -struct termios termbuf, termbuf2; /* pty control structure */ -# ifdef STREAMSPTY -int ttyfd = -1; -# endif -#endif /* USE_TERMIO */ - -/* - * init_termbuf() - * copy_termbuf(cp) - * set_termbuf() - * - * These three routines are used to get and set the "termbuf" structure - * to and from the kernel. init_termbuf() gets the current settings. - * copy_termbuf() hands in a new "termbuf" to write to the kernel, and - * set_termbuf() writes the structure into the kernel. - */ - - void -init_termbuf() -{ -#ifndef USE_TERMIO - (void) ioctl(pty, TIOCGETP, (char *)&termbuf.sg); - (void) ioctl(pty, TIOCGETC, (char *)&termbuf.tc); - (void) ioctl(pty, TIOCGLTC, (char *)&termbuf.ltc); -# ifdef TIOCGSTATE - (void) ioctl(pty, TIOCGSTATE, (char *)&termbuf.state); -# endif -#else -# ifdef STREAMSPTY - (void) tcgetattr(ttyfd, &termbuf); -# else - (void) tcgetattr(pty, &termbuf); -# endif -#endif - termbuf2 = termbuf; -} - -#if defined(LINEMODE) && defined(TIOCPKT_IOCTL) - void -copy_termbuf(cp, len) - char *cp; - int len; -{ - if (len > sizeof(termbuf)) - len = sizeof(termbuf); - memmove((char *)&termbuf, cp, len); - termbuf2 = termbuf; -} -#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */ - - void -set_termbuf() -{ - /* - * Only make the necessary changes. - */ -#ifndef USE_TERMIO - if (memcmp((char *)&termbuf.sg, (char *)&termbuf2.sg, - sizeof(termbuf.sg))) - (void) ioctl(pty, TIOCSETN, (char *)&termbuf.sg); - if (memcmp((char *)&termbuf.tc, (char *)&termbuf2.tc, - sizeof(termbuf.tc))) - (void) ioctl(pty, TIOCSETC, (char *)&termbuf.tc); - if (memcmp((char *)&termbuf.ltc, (char *)&termbuf2.ltc, - sizeof(termbuf.ltc))) - (void) ioctl(pty, TIOCSLTC, (char *)&termbuf.ltc); - if (termbuf.lflags != termbuf2.lflags) - (void) ioctl(pty, TIOCLSET, (char *)&termbuf.lflags); -#else /* USE_TERMIO */ - if (memcmp((char *)&termbuf, (char *)&termbuf2, sizeof(termbuf))) -# ifdef STREAMSPTY - (void) tcsetattr(ttyfd, TCSANOW, &termbuf); -# else - (void) tcsetattr(pty, TCSANOW, &termbuf); -# endif -# if defined(CRAY2) && defined(UNICOS5) - needtermstat = 1; -# endif -#endif /* USE_TERMIO */ -} - - -/* - * spcset(func, valp, valpp) - * - * This function takes various special characters (func), and - * sets *valp to the current value of that character, and - * *valpp to point to where in the "termbuf" structure that - * value is kept. - * - * It returns the SLC_ level of support for this function. - */ - -#ifndef USE_TERMIO - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; -{ - switch(func) { - case SLC_EOF: - *valp = termbuf.tc.t_eofc; - *valpp = (cc_t *)&termbuf.tc.t_eofc; - return(SLC_VARIABLE); - case SLC_EC: - *valp = termbuf.sg.sg_erase; - *valpp = (cc_t *)&termbuf.sg.sg_erase; - return(SLC_VARIABLE); - case SLC_EL: - *valp = termbuf.sg.sg_kill; - *valpp = (cc_t *)&termbuf.sg.sg_kill; - return(SLC_VARIABLE); - case SLC_IP: - *valp = termbuf.tc.t_intrc; - *valpp = (cc_t *)&termbuf.tc.t_intrc; - return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_ABORT: - *valp = termbuf.tc.t_quitc; - *valpp = (cc_t *)&termbuf.tc.t_quitc; - return(SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_XON: - *valp = termbuf.tc.t_startc; - *valpp = (cc_t *)&termbuf.tc.t_startc; - return(SLC_VARIABLE); - case SLC_XOFF: - *valp = termbuf.tc.t_stopc; - *valpp = (cc_t *)&termbuf.tc.t_stopc; - return(SLC_VARIABLE); - case SLC_AO: - *valp = termbuf.ltc.t_flushc; - *valpp = (cc_t *)&termbuf.ltc.t_flushc; - return(SLC_VARIABLE); - case SLC_SUSP: - *valp = termbuf.ltc.t_suspc; - *valpp = (cc_t *)&termbuf.ltc.t_suspc; - return(SLC_VARIABLE); - case SLC_EW: - *valp = termbuf.ltc.t_werasc; - *valpp = (cc_t *)&termbuf.ltc.t_werasc; - return(SLC_VARIABLE); - case SLC_RP: - *valp = termbuf.ltc.t_rprntc; - *valpp = (cc_t *)&termbuf.ltc.t_rprntc; - return(SLC_VARIABLE); - case SLC_LNEXT: - *valp = termbuf.ltc.t_lnextc; - *valpp = (cc_t *)&termbuf.ltc.t_lnextc; - return(SLC_VARIABLE); - case SLC_FORW1: - *valp = termbuf.tc.t_brkc; - *valpp = (cc_t *)&termbuf.ltc.t_lnextc; - return(SLC_VARIABLE); - case SLC_BRK: - case SLC_SYNCH: - case SLC_AYT: - case SLC_EOR: - *valp = (cc_t)0; - *valpp = (cc_t *)0; - return(SLC_DEFAULT); - default: - *valp = (cc_t)0; - *valpp = (cc_t *)0; - return(SLC_NOSUPPORT); - } -} - -#else /* USE_TERMIO */ - - int -spcset(func, valp, valpp) - int func; - cc_t *valp; - cc_t **valpp; -{ - -#define setval(a, b) *valp = termbuf.c_cc[a]; \ - *valpp = &termbuf.c_cc[a]; \ - return(b); -#define defval(a) *valp = ((cc_t)a); *valpp = (cc_t *)0; return(SLC_DEFAULT); - - switch(func) { - case SLC_EOF: - setval(VEOF, SLC_VARIABLE); - case SLC_EC: - setval(VERASE, SLC_VARIABLE); - case SLC_EL: - setval(VKILL, SLC_VARIABLE); - case SLC_IP: - setval(VINTR, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_ABORT: - setval(VQUIT, SLC_VARIABLE|SLC_FLUSHIN|SLC_FLUSHOUT); - case SLC_XON: -#ifdef VSTART - setval(VSTART, SLC_VARIABLE); -#else - defval(0x13); -#endif - case SLC_XOFF: -#ifdef VSTOP - setval(VSTOP, SLC_VARIABLE); -#else - defval(0x11); -#endif - case SLC_EW: -#ifdef VWERASE - setval(VWERASE, SLC_VARIABLE); -#else - defval(0); -#endif - case SLC_RP: -#ifdef VREPRINT - setval(VREPRINT, SLC_VARIABLE); -#else - defval(0); -#endif - case SLC_LNEXT: -#ifdef VLNEXT - setval(VLNEXT, SLC_VARIABLE); -#else - defval(0); -#endif - case SLC_AO: -#if !defined(VDISCARD) && defined(VFLUSHO) -# define VDISCARD VFLUSHO -#endif -#ifdef VDISCARD - setval(VDISCARD, SLC_VARIABLE|SLC_FLUSHOUT); -#else - defval(0); -#endif - case SLC_SUSP: -#ifdef VSUSP - setval(VSUSP, SLC_VARIABLE|SLC_FLUSHIN); -#else - defval(0); -#endif -#ifdef VEOL - case SLC_FORW1: - setval(VEOL, SLC_VARIABLE); -#endif -#ifdef VEOL2 - case SLC_FORW2: - setval(VEOL2, SLC_VARIABLE); -#endif - case SLC_AYT: -#ifdef VSTATUS - setval(VSTATUS, SLC_VARIABLE); -#else - defval(0); -#endif - - case SLC_BRK: - case SLC_SYNCH: - case SLC_EOR: - defval(0); - - default: - *valp = 0; - *valpp = 0; - return(SLC_NOSUPPORT); - } -} -#endif /* USE_TERMIO */ - -#ifdef CRAY -/* - * getnpty() - * - * Return the number of pty's configured into the system. - */ - int -getnpty() -{ -#ifdef _SC_CRAY_NPTY - int numptys; - - if ((numptys = sysconf(_SC_CRAY_NPTY)) != -1) - return numptys; - else -#endif /* _SC_CRAY_NPTY */ - return 128; -} -#endif /* CRAY */ - -#ifndef convex -/* - * getpty() - * - * Allocate a pty. As a side effect, the external character - * array "line" contains the name of the slave side. - * - * Returns the file descriptor of the opened pty. - */ -#ifndef __GNUC__ -char *line = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -#else -static char Xline[] = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -char *line = Xline; -#endif -#ifdef CRAY -char *myline = "\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0\0"; -#endif /* CRAY */ - - int -getpty(ptynum) -int *ptynum; -{ - register int p; -#ifdef STREAMSPTY - int t; - char *ptsname(); - - p = open("/dev/ptmx", 2); - if (p > 0) { - grantpt(p); - unlockpt(p); - strcpy(line, ptsname(p)); - return(p); - } - -#else /* ! STREAMSPTY */ -#ifndef CRAY - register char *cp, *p1, *p2; - register int i; -#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 - int dummy; -#endif - -#ifndef __hpux - (void) sprintf(line, "/dev/ptyXX"); - p1 = &line[8]; - p2 = &line[9]; -#else - (void) sprintf(line, "/dev/ptym/ptyXX"); - p1 = &line[13]; - p2 = &line[14]; -#endif - - for (cp = "pqrsPQRS"; *cp; cp++) { - struct stat stb; - - *p1 = *cp; - *p2 = '0'; - /* - * This stat() check is just to keep us from - * looping through all 256 combinations if there - * aren't that many ptys available. - */ - if (stat(line, &stb) < 0) - break; - for (i = 0; i < 32; i++) { - *p2 = "0123456789abcdefghijklmnopqrstuv"[i]; - p = open(line, 2); - if (p > 0) { -#ifndef __hpux - line[5] = 't'; -#else - for (p1 = &line[8]; *p1; p1++) - *p1 = *(p1+1); - line[9] = 't'; -#endif - chown(line, 0, 0); - chmod(line, 0600); -#if defined(sun) && defined(TIOCGPGRP) && BSD < 199207 - if (ioctl(p, TIOCGPGRP, &dummy) == 0 - || errno != EIO) { - chmod(line, 0666); - close(p); - line[5] = 'p'; - } else -#endif /* defined(sun) && defined(TIOCGPGRP) && BSD < 199207 */ - return(p); - } - } - } -#else /* CRAY */ - extern lowpty, highpty; - struct stat sb; - - for (*ptynum = lowpty; *ptynum <= highpty; (*ptynum)++) { - (void) sprintf(myline, "/dev/pty/%03d", *ptynum); - p = open(myline, 2); - if (p < 0) - continue; - (void) sprintf(line, "/dev/ttyp%03d", *ptynum); - /* - * Here are some shenanigans to make sure that there - * are no listeners lurking on the line. - */ - if(stat(line, &sb) < 0) { - (void) close(p); - continue; - } - if(sb.st_uid || sb.st_gid || sb.st_mode != 0600) { - chown(line, 0, 0); - chmod(line, 0600); - (void)close(p); - p = open(myline, 2); - if (p < 0) - continue; - } - /* - * Now it should be safe...check for accessability. - */ - if (access(line, 6) == 0) - return(p); - else { - /* no tty side to pty so skip it */ - (void) close(p); - } - } -#endif /* CRAY */ -#endif /* STREAMSPTY */ - return(-1); -} -#endif /* convex */ - -#ifdef LINEMODE -/* - * tty_flowmode() Find out if flow control is enabled or disabled. - * tty_linemode() Find out if linemode (external processing) is enabled. - * tty_setlinemod(on) Turn on/off linemode. - * tty_isecho() Find out if echoing is turned on. - * tty_setecho(on) Enable/disable character echoing. - * tty_israw() Find out if terminal is in RAW mode. - * tty_binaryin(on) Turn on/off BINARY on input. - * tty_binaryout(on) Turn on/off BINARY on output. - * tty_isediting() Find out if line editing is enabled. - * tty_istrapsig() Find out if signal trapping is enabled. - * tty_setedit(on) Turn on/off line editing. - * tty_setsig(on) Turn on/off signal trapping. - * tty_issofttab() Find out if tab expansion is enabled. - * tty_setsofttab(on) Turn on/off soft tab expansion. - * tty_islitecho() Find out if typed control chars are echoed literally - * tty_setlitecho() Turn on/off literal echo of control chars - * tty_tspeed(val) Set transmit speed to val. - * tty_rspeed(val) Set receive speed to val. - */ - -#ifdef convex -static int linestate; -#endif - - int -tty_linemode() -{ -#ifndef convex -#ifndef USE_TERMIO - return(termbuf.state & TS_EXTPROC); -#else - return(termbuf.c_lflag & EXTPROC); -#endif -#else - return(linestate); -#endif -} - - void -tty_setlinemode(on) - int on; -{ -#ifdef TIOCEXT -# ifndef convex - set_termbuf(); -# else - linestate = on; -# endif - (void) ioctl(pty, TIOCEXT, (char *)&on); -# ifndef convex - init_termbuf(); -# endif -#else /* !TIOCEXT */ -# ifdef EXTPROC - if (on) - termbuf.c_lflag |= EXTPROC; - else - termbuf.c_lflag &= ~EXTPROC; -# endif -#endif /* TIOCEXT */ -} -#endif /* LINEMODE */ - - int -tty_isecho() -{ -#ifndef USE_TERMIO - return (termbuf.sg.sg_flags & ECHO); -#else - return (termbuf.c_lflag & ECHO); -#endif -} - - int -tty_flowmode() -{ -#ifndef USE_TERMIO - return(((termbuf.tc.t_startc) > 0 && (termbuf.tc.t_stopc) > 0) ? 1 : 0); -#else - return((termbuf.c_iflag & IXON) ? 1 : 0); -#endif -} - - int -tty_restartany() -{ -#ifndef USE_TERMIO -# ifdef DECCTQ - return((termbuf.lflags & DECCTQ) ? 0 : 1); -# else - return(-1); -# endif -#else - return((termbuf.c_iflag & IXANY) ? 1 : 0); -#endif -} - - void -tty_setecho(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags |= ECHO|CRMOD; - else - termbuf.sg.sg_flags &= ~(ECHO|CRMOD); -#else - if (on) - termbuf.c_lflag |= ECHO; - else - termbuf.c_lflag &= ~ECHO; -#endif -} - - int -tty_israw() -{ -#ifndef USE_TERMIO - return(termbuf.sg.sg_flags & RAW); -#else - return(!(termbuf.c_lflag & ICANON)); -#endif -} - -#if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - int -tty_setraw(on) -{ -# ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags |= RAW; - else - termbuf.sg.sg_flags &= ~RAW; -# else - if (on) - termbuf.c_lflag &= ~ICANON; - else - termbuf.c_lflag |= ICANON; -# endif -} -#endif - - void -tty_binaryin(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - termbuf.lflags |= LPASS8; - else - termbuf.lflags &= ~LPASS8; -#else - if (on) { - termbuf.c_iflag &= ~ISTRIP; - } else { - termbuf.c_iflag |= ISTRIP; - } -#endif -} - - void -tty_binaryout(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - termbuf.lflags |= LLITOUT; - else - termbuf.lflags &= ~LLITOUT; -#else - if (on) { - termbuf.c_cflag &= ~(CSIZE|PARENB); - termbuf.c_cflag |= CS8; - termbuf.c_oflag &= ~OPOST; - } else { - termbuf.c_cflag &= ~CSIZE; - termbuf.c_cflag |= CS7|PARENB; - termbuf.c_oflag |= OPOST; - } -#endif -} - - int -tty_isbinaryin() -{ -#ifndef USE_TERMIO - return(termbuf.lflags & LPASS8); -#else - return(!(termbuf.c_iflag & ISTRIP)); -#endif -} - - int -tty_isbinaryout() -{ -#ifndef USE_TERMIO - return(termbuf.lflags & LLITOUT); -#else - return(!(termbuf.c_oflag&OPOST)); -#endif -} - -#ifdef LINEMODE - int -tty_isediting() -{ -#ifndef USE_TERMIO - return(!(termbuf.sg.sg_flags & (CBREAK|RAW))); -#else - return(termbuf.c_lflag & ICANON); -#endif -} - - int -tty_istrapsig() -{ -#ifndef USE_TERMIO - return(!(termbuf.sg.sg_flags&RAW)); -#else - return(termbuf.c_lflag & ISIG); -#endif -} - - void -tty_setedit(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags &= ~CBREAK; - else - termbuf.sg.sg_flags |= CBREAK; -#else - if (on) - termbuf.c_lflag |= ICANON; - else - termbuf.c_lflag &= ~ICANON; -#endif -} - - void -tty_setsig(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - ; -#else - if (on) - termbuf.c_lflag |= ISIG; - else - termbuf.c_lflag &= ~ISIG; -#endif -} -#endif /* LINEMODE */ - - int -tty_issofttab() -{ -#ifndef USE_TERMIO - return (termbuf.sg.sg_flags & XTABS); -#else -# ifdef OXTABS - return (termbuf.c_oflag & OXTABS); -# endif -# ifdef TABDLY - return ((termbuf.c_oflag & TABDLY) == TAB3); -# endif -#endif -} - - void -tty_setsofttab(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - termbuf.sg.sg_flags |= XTABS; - else - termbuf.sg.sg_flags &= ~XTABS; -#else - if (on) { -# ifdef OXTABS - termbuf.c_oflag |= OXTABS; -# endif -# ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB3; -# endif - } else { -# ifdef OXTABS - termbuf.c_oflag &= ~OXTABS; -# endif -# ifdef TABDLY - termbuf.c_oflag &= ~TABDLY; - termbuf.c_oflag |= TAB0; -# endif - } -#endif -} - - int -tty_islitecho() -{ -#ifndef USE_TERMIO - return (!(termbuf.lflags & LCTLECH)); -#else -# ifdef ECHOCTL - return (!(termbuf.c_lflag & ECHOCTL)); -# endif -# ifdef TCTLECH - return (!(termbuf.c_lflag & TCTLECH)); -# endif -# if !defined(ECHOCTL) && !defined(TCTLECH) - return (0); /* assumes ctl chars are echoed '^x' */ -# endif -#endif -} - - void -tty_setlitecho(on) - int on; -{ -#ifndef USE_TERMIO - if (on) - termbuf.lflags &= ~LCTLECH; - else - termbuf.lflags |= LCTLECH; -#else -# ifdef ECHOCTL - if (on) - termbuf.c_lflag &= ~ECHOCTL; - else - termbuf.c_lflag |= ECHOCTL; -# endif -# ifdef TCTLECH - if (on) - termbuf.c_lflag &= ~TCTLECH; - else - termbuf.c_lflag |= TCTLECH; -# endif -#endif -} - - int -tty_iscrnl() -{ -#ifndef USE_TERMIO - return (termbuf.sg.sg_flags & CRMOD); -#else - return (termbuf.c_iflag & ICRNL); -#endif -} - -/* - * Try to guess whether speeds are "encoded" (4.2BSD) or just numeric (4.4BSD). - */ -#if B4800 != 4800 -#define DECODE_BAUD -#endif - -#ifdef DECODE_BAUD - -/* - * A table of available terminal speeds - */ -struct termspeeds { - int speed; - int value; -} termspeeds[] = { - { 0, B0 }, { 50, B50 }, { 75, B75 }, - { 110, B110 }, { 134, B134 }, { 150, B150 }, - { 200, B200 }, { 300, B300 }, { 600, B600 }, - { 1200, B1200 }, { 1800, B1800 }, { 2400, B2400 }, - { 4800, B4800 }, -#ifdef B7200 - { 7200, B7200 }, -#endif - { 9600, B9600 }, -#ifdef B14400 - { 14400, B14400 }, -#endif -#ifdef B19200 - { 19200, B19200 }, -#endif -#ifdef B28800 - { 28800, B28800 }, -#endif -#ifdef B38400 - { 38400, B38400 }, -#endif -#ifdef B57600 - { 57600, B57600 }, -#endif -#ifdef B115200 - { 115200, B115200 }, -#endif -#ifdef B230400 - { 230400, B230400 }, -#endif - { -1, 0 } -}; -#endif /* DECODE_BUAD */ - - void -tty_tspeed(val) - int val; -{ -#ifdef DECODE_BAUD - register struct termspeeds *tp; - - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetospeed(&termbuf, tp->value); -#else /* DECODE_BUAD */ - cfsetospeed(&termbuf, val); -#endif /* DECODE_BUAD */ -} - - void -tty_rspeed(val) - int val; -{ -#ifdef DECODE_BAUD - register struct termspeeds *tp; - - for (tp = termspeeds; (tp->speed != -1) && (val > tp->speed); tp++) - ; - if (tp->speed == -1) /* back up to last valid value */ - --tp; - cfsetispeed(&termbuf, tp->value); -#else /* DECODE_BAUD */ - cfsetispeed(&termbuf, val); -#endif /* DECODE_BAUD */ -} - -#if defined(CRAY2) && defined(UNICOS5) - int -tty_isnewmap() -{ - return((termbuf.c_oflag & OPOST) && (termbuf.c_oflag & ONLCR) && - !(termbuf.c_oflag & ONLRET)); -} -#endif - -#ifdef PARENT_DOES_UTMP -# ifndef NEWINIT -extern struct utmp wtmp; -extern char wtmpf[]; -# else /* NEWINIT */ -int gotalarm; - - /* ARGSUSED */ - void -nologinproc(sig) - int sig; -{ - gotalarm++; -} -# endif /* NEWINIT */ -#endif /* PARENT_DOES_UTMP */ - -#ifndef NEWINIT -# ifdef PARENT_DOES_UTMP -extern void utmp_sig_init P((void)); -extern void utmp_sig_reset P((void)); -extern void utmp_sig_wait P((void)); -extern void utmp_sig_notify P((int)); -# endif /* PARENT_DOES_UTMP */ -#endif - -/* - * getptyslave() - * - * Open the slave side of the pty, and do any initialization - * that is necessary. The return value is a file descriptor - * for the slave side. - */ - int -getptyslave() -{ - register int t = -1; - char erase; - -#if !defined(CRAY) || !defined(NEWINIT) -# ifdef LINEMODE - int waslm; -# endif -# ifdef TIOCGWINSZ - struct winsize ws; - extern int def_row, def_col; -# endif - extern int def_tspeed, def_rspeed; - /* - * Opening the slave side may cause initilization of the - * kernel tty structure. We need remember the state of - * if linemode was turned on - * terminal window size - * terminal speed - * erase character - * so that we can re-set them if we need to. - */ -# ifdef LINEMODE - waslm = tty_linemode(); -# endif - erase = termbuf.c_cc[VERASE]; - - /* - * Make sure that we don't have a controlling tty, and - * that we are the session (process group) leader. - */ -# ifdef TIOCNOTTY - t = open(_PATH_TTY, O_RDWR); - if (t >= 0) { - (void) ioctl(t, TIOCNOTTY, (char *)0); - (void) close(t); - } -# endif - - -# ifdef PARENT_DOES_UTMP - /* - * Wait for our parent to get the utmp stuff to get done. - */ - utmp_sig_wait(); -# endif - - t = cleanopen(line); - if (t < 0) - fatalperror(net, line); - -#ifdef STREAMSPTY -#ifdef USE_TERMIO - ttyfd = t; -#endif - if (ioctl(t, I_PUSH, "ptem") < 0) - fatal(net, "I_PUSH ptem"); - if (ioctl(t, I_PUSH, "ldterm") < 0) - fatal(net, "I_PUSH ldterm"); - if (ioctl(t, I_PUSH, "ttcompat") < 0) - fatal(net, "I_PUSH ttcompat"); - if (ioctl(pty, I_PUSH, "pckt") < 0) - fatal(net, "I_PUSH pckt"); -#endif - - /* - * set up the tty modes as we like them to be. - */ - init_termbuf(); -# ifdef TIOCGWINSZ - if (def_row || def_col) { - memset((char *)&ws, 0, sizeof(ws)); - ws.ws_col = def_col; - ws.ws_row = def_row; - (void)ioctl(t, TIOCSWINSZ, (char *)&ws); - } -# endif - - /* - * Settings for sgtty based systems - */ -# ifndef USE_TERMIO - termbuf.sg.sg_flags |= CRMOD|ANYP|ECHO|XTABS; -# endif /* USE_TERMIO */ - - /* - * Settings for UNICOS (and HPUX) - */ -# if defined(CRAY) || defined(__hpux) - termbuf.c_oflag = OPOST|ONLCR|TAB3; - termbuf.c_iflag = IGNPAR|ISTRIP|ICRNL|IXON; - termbuf.c_lflag = ISIG|ICANON|ECHO|ECHOE|ECHOK; - termbuf.c_cflag = EXTB|HUPCL|CS8; -# endif - - /* - * Settings for all other termios/termio based - * systems, other than 4.4BSD. In 4.4BSD the - * kernel does the initial terminal setup. - */ -# if defined(USE_TERMIO) && !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) -# ifndef OXTABS -# define OXTABS 0 -# endif - termbuf.c_lflag |= ECHO; - termbuf.c_oflag |= ONLCR|OXTABS; - termbuf.c_iflag |= ICRNL; - termbuf.c_iflag &= ~IXOFF; -# endif /* defined(USE_TERMIO) && !defined(CRAY) && (BSD <= 43) */ - tty_rspeed((def_rspeed > 0) ? def_rspeed : 9600); - tty_tspeed((def_tspeed > 0) ? def_tspeed : 9600); - if (erase) - termbuf.c_cc[VERASE] = erase; -# ifdef LINEMODE - if (waslm) - tty_setlinemode(1); -# endif /* LINEMODE */ - - /* - * Set the tty modes, and make this our controlling tty. - */ - set_termbuf(); - if (login_tty(t) == -1) - fatalperror(net, "login_tty"); -#endif /* !defined(CRAY) || !defined(NEWINIT) */ - if (net > 2) - (void) close(net); -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - /* - * Leave the pty open so that we can write out the rlogin - * protocol for /bin/login, if the authentication works. - */ -#else - if (pty > 2) { - (void) close(pty); - pty = -1; - } -#endif -} - -#if !defined(CRAY) || !defined(NEWINIT) -#ifndef O_NOCTTY -#define O_NOCTTY 0 -#endif -/* - * Open the specified slave side of the pty, - * making sure that we have a clean tty. - */ - int -cleanopen(line) - char *line; -{ - register int t; -#ifdef UNICOS7x - struct secstat secbuf; -#endif /* UNICOS7x */ - -#ifndef STREAMSPTY - /* - * Make sure that other people can't open the - * slave side of the connection. - */ - (void) chown(line, 0, 0); - (void) chmod(line, 0600); -#endif - -# if !defined(CRAY) && (BSD > 43) - (void) revoke(line); -# endif -#ifdef UNICOS7x - if (secflag) { - if (secstat(line, &secbuf) < 0) - return(-1); - if (setulvl(secbuf.st_slevel) < 0) - return(-1); - if (setucmp(secbuf.st_compart) < 0) - return(-1); - } -#endif /* UNICOS7x */ - - t = open(line, O_RDWR|O_NOCTTY); - -#ifdef UNICOS7x - if (secflag) { - if (setulvl(sysv.sy_minlvl) < 0) - return(-1); - if (setucmp(0) < 0) - return(-1); - } -#endif /* UNICOS7x */ - - if (t < 0) - return(-1); - - /* - * Hangup anybody else using this ttyp, then reopen it for - * ourselves. - */ -# if !(defined(CRAY) || defined(__hpux)) && (BSD <= 43) && !defined(STREAMSPTY) - (void) signal(SIGHUP, SIG_IGN); - vhangup(); - (void) signal(SIGHUP, SIG_DFL); - t = open(line, O_RDWR|O_NOCTTY); - if (t < 0) - return(-1); -# endif -# if defined(CRAY) && defined(TCVHUP) - { - register int i; - (void) signal(SIGHUP, SIG_IGN); - (void) ioctl(t, TCVHUP, (char *)0); - (void) signal(SIGHUP, SIG_DFL); - -#ifdef UNICOS7x - if (secflag) { - if (secstat(line, &secbuf) < 0) - return(-1); - if (setulvl(secbuf.st_slevel) < 0) - return(-1); - if (setucmp(secbuf.st_compart) < 0) - return(-1); - } -#endif /* UNICOS7x */ - - i = open(line, O_RDWR); - -#ifdef UNICOS7x - if (secflag) { - if (setulvl(sysv.sy_minlvl) < 0) - return(-1); - if (setucmp(0) < 0) - return(-1); - } -#endif /* UNICOS7x */ - - if (i < 0) - return(-1); - (void) close(t); - t = i; - } -# endif /* defined(CRAY) && defined(TCVHUP) */ - return(t); -} -#endif /* !defined(CRAY) || !defined(NEWINIT) */ - -#if BSD <= 43 - - int -login_tty(t) - int t; -{ - if (setsid() < 0) { -#ifdef ultrix - /* - * The setsid() may have failed because we - * already have a pgrp == pid. Zero out - * our pgrp and try again... - */ - if ((setpgrp(0, 0) < 0) || (setsid() < 0)) -#endif - fatalperror(net, "setsid()"); - } -# ifdef TIOCSCTTY - if (ioctl(t, TIOCSCTTY, (char *)0) < 0) - fatalperror(net, "ioctl(sctty)"); -# if defined(CRAY) - /* - * Close the hard fd to /dev/ttypXXX, and re-open through - * the indirect /dev/tty interface. - */ - close(t); - if ((t = open("/dev/tty", O_RDWR)) < 0) - fatalperror(net, "open(/dev/tty)"); -# endif -# else - /* - * We get our controlling tty assigned as a side-effect - * of opening up a tty device. But on BSD based systems, - * this only happens if our process group is zero. The - * setsid() call above may have set our pgrp, so clear - * it out before opening the tty... - */ -# ifndef SOLARIS - (void) setpgrp(0, 0); -# else - (void) setpgrp(); -# endif - close(open(line, O_RDWR)); -# endif - if (t != 0) - (void) dup2(t, 0); - if (t != 1) - (void) dup2(t, 1); - if (t != 2) - (void) dup2(t, 2); - if (t > 2) - close(t); - return(0); -} -#endif /* BSD <= 43 */ - -#ifdef NEWINIT -char *gen_id = "fe"; -#endif - -/* - * startslave(host) - * - * Given a hostname, do whatever - * is necessary to startup the login process on the slave side of the pty. - */ - -/* ARGSUSED */ - void -startslave(host, autologin, autoname) - char *host; - int autologin; - char *autoname; -{ - register int i; - long time(); - char name[256]; -#ifdef NEWINIT - extern char *ptyip; - struct init_request request; - void nologinproc(); - register int n; -#endif /* NEWINIT */ - -#if defined(AUTHENTICATION) - if (!autoname || !autoname[0]) - autologin = 0; - - if (autologin < auth_level) { - fatal(net, "Authorization failed"); - exit(1); - } -#endif - -#ifndef NEWINIT -# ifdef PARENT_DOES_UTMP - utmp_sig_init(); -# endif /* PARENT_DOES_UTMP */ - - if ((i = fork()) < 0) - fatalperror(net, "fork"); - if (i) { -# ifdef PARENT_DOES_UTMP - /* - * Cray parent will create utmp entry for child and send - * signal to child to tell when done. Child waits for signal - * before doing anything important. - */ - register int pid = i; - void sigjob P((int)); - - setpgrp(); - utmp_sig_reset(); /* reset handler to default */ - /* - * Create utmp entry for child - */ - (void) time(&wtmp.ut_time); - wtmp.ut_type = LOGIN_PROCESS; - wtmp.ut_pid = pid; - SCPYN(wtmp.ut_user, "LOGIN"); - SCPYN(wtmp.ut_host, host); - SCPYN(wtmp.ut_line, line + sizeof("/dev/") - 1); -#ifndef __hpux - SCPYN(wtmp.ut_id, wtmp.ut_line+3); -#else - SCPYN(wtmp.ut_id, wtmp.ut_line+7); -#endif - pututline(&wtmp); - endutent(); - if ((i = open(wtmpf, O_WRONLY|O_APPEND)) >= 0) { - (void) write(i, (char *)&wtmp, sizeof(struct utmp)); - (void) close(i); - } -#ifdef CRAY - (void) signal(WJSIGNAL, sigjob); -#endif - utmp_sig_notify(pid); -# endif /* PARENT_DOES_UTMP */ - } else { - getptyslave(autologin); - start_login(host, autologin, autoname); - /*NOTREACHED*/ - } -#else /* NEWINIT */ - - /* - * Init will start up login process if we ask nicely. We only wait - * for it to start up and begin normal telnet operation. - */ - if ((i = open(INIT_FIFO, O_WRONLY)) < 0) { - char tbuf[128]; - (void) sprintf(tbuf, "Can't open %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - memset((char *)&request, 0, sizeof(request)); - request.magic = INIT_MAGIC; - SCPYN(request.gen_id, gen_id); - SCPYN(request.tty_id, &line[8]); - SCPYN(request.host, host); - SCPYN(request.term_type, terminaltype ? terminaltype : "network"); -#if !defined(UNICOS5) - request.signal = SIGCLD; - request.pid = getpid(); -#endif -#ifdef BFTPDAEMON - /* - * Are we working as the bftp daemon? - */ - if (bftpd) { - SCPYN(request.exec_name, BFTPPATH); - } -#endif /* BFTPDAEMON */ - if (write(i, (char *)&request, sizeof(request)) < 0) { - char tbuf[128]; - (void) sprintf(tbuf, "Can't write to %s\n", INIT_FIFO); - fatalperror(net, tbuf); - } - (void) close(i); - (void) signal(SIGALRM, nologinproc); - for (i = 0; ; i++) { - char tbuf[128]; - alarm(15); - n = read(pty, ptyip, BUFSIZ); - if (i == 3 || n >= 0 || !gotalarm) - break; - gotalarm = 0; - sprintf(tbuf, "telnetd: waiting for /etc/init to start login process on %s\r\n", line); - (void) write(net, tbuf, strlen(tbuf)); - } - if (n < 0 && gotalarm) - fatal(net, "/etc/init didn't start login process"); - pcc += n; - alarm(0); - (void) signal(SIGALRM, SIG_DFL); - - return; -#endif /* NEWINIT */ -} - -char *envinit[3]; -extern char **environ; - - void -init_env() -{ - extern char *getenv(); - char **envp; - - envp = envinit; - if (*envp = getenv("TZ")) - *envp++ -= 3; -#if defined(CRAY) || defined(__hpux) - else - *envp++ = "TZ=GMT0"; -#endif - *envp = 0; - environ = envinit; -} - -#ifndef NEWINIT - -/* - * start_login(host) - * - * Assuming that we are now running as a child processes, this - * function will turn us into the login process. - */ - - void -start_login(host, autologin, name) - char *host; - int autologin; - char *name; -{ - register char *cp; - register char **argv; - char **addarg(), *user; - extern char *getenv(); -#ifdef UTMPX - register int pid = getpid(); - struct utmpx utmpx; -#endif -#ifdef SOLARIS - char *term; - char termbuf[64]; -#endif - -#ifdef UTMPX - /* - * Create utmp entry for child - */ - - memset(&utmpx, 0, sizeof(utmpx)); - SCPYN(utmpx.ut_user, ".telnet"); - SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); - utmpx.ut_pid = pid; - utmpx.ut_id[0] = 't'; - utmpx.ut_id[1] = 'n'; - utmpx.ut_id[2] = SC_WILDC; - utmpx.ut_id[3] = SC_WILDC; - utmpx.ut_type = LOGIN_PROCESS; - (void) time(&utmpx.ut_tv.tv_sec); - if (makeutx(&utmpx) == NULL) - fatal(net, "makeutx failed"); -#endif - - scrub_env(); - - /* - * -h : pass on name of host. - * WARNING: -h is accepted by login if and only if - * getuid() == 0. - * -p : don't clobber the environment (so terminal type stays set). - * - * -f : force this login, he has already been authenticated - */ - argv = addarg(0, "login"); - -#if !defined(NO_LOGIN_H) - -# if defined (AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - /* - * Don't add the "-h host" option if we are going - * to be adding the "-r host" option down below... - */ - if ((auth_level < 0) || (autologin != AUTH_VALID)) -# endif - { - argv = addarg(argv, "-h"); - argv = addarg(argv, host); -#ifdef SOLARIS - /* - * SVR4 version of -h takes TERM= as second arg, or - - */ - term = getenv("TERM"); - if (term == NULL || term[0] == 0) { - term = "-"; - } else { - strcpy(termbuf, "TERM="); - strncat(termbuf, term, sizeof(termbuf) - 6); - term = termbuf; - } - argv = addarg(argv, term); -#endif - } -#endif -#if !defined(NO_LOGIN_P) - argv = addarg(argv, "-p"); -#endif -#ifdef LINEMODE - /* - * Set the environment variable "LINEMODE" to either - * "real" or "kludge" if we are operating in either - * real or kludge linemode. - */ - if (lmodetype == REAL_LINEMODE) - setenv("LINEMODE", "real", 1); -# ifdef KLUDGELINEMODE - else if (lmodetype == KLUDGE_LINEMODE || lmodetype == KLUDGE_OK) - setenv("LINEMODE", "kludge", 1); -# endif -#endif -#ifdef BFTPDAEMON - /* - * Are we working as the bftp daemon? If so, then ask login - * to start bftp instead of shell. - */ - if (bftpd) { - argv = addarg(argv, "-e"); - argv = addarg(argv, BFTPPATH); - } else -#endif -#if defined (SecurID) - /* - * don't worry about the -f that might get sent. - * A -s is supposed to override it anyhow. - */ - if (require_SecurID) - argv = addarg(argv, "-s"); -#endif -#if defined (AUTHENTICATION) - if (auth_level >= 0 && autologin == AUTH_VALID) { -# if !defined(NO_LOGIN_F) - argv = addarg(argv, "-f"); - argv = addarg(argv, name); -# else -# if defined(LOGIN_R) - /* - * We don't have support for "login -f", but we - * can fool /bin/login into thinking that we are - * rlogind, and allow us to log in without a - * password. The rlogin protocol expects - * local-user\0remote-user\0term/speed\0 - */ - - if (pty > 2) { - register char *cp; - char speed[128]; - int isecho, israw, xpty, len; - extern int def_rspeed; -# ifndef LOGIN_HOST - /* - * Tell login that we are coming from "localhost". - * If we passed in the real host name, then the - * user would have to allow .rhost access from - * every machine that they want authenticated - * access to work from, which sort of defeats - * the purpose of an authenticated login... - * So, we tell login that the session is coming - * from "localhost", and the user will only have - * to have "localhost" in their .rhost file. - */ -# define LOGIN_HOST "localhost" -# endif - argv = addarg(argv, "-r"); - argv = addarg(argv, LOGIN_HOST); - - xpty = pty; -# ifndef STREAMSPTY - pty = 0; -# else - ttyfd = 0; -# endif - init_termbuf(); - isecho = tty_isecho(); - israw = tty_israw(); - if (isecho || !israw) { - tty_setecho(0); /* Turn off echo */ - tty_setraw(1); /* Turn on raw */ - set_termbuf(); - } - len = strlen(name)+1; - write(xpty, name, len); - write(xpty, name, len); - sprintf(speed, "%s/%d", (cp = getenv("TERM")) ? cp : "", - (def_rspeed > 0) ? def_rspeed : 9600); - len = strlen(speed)+1; - write(xpty, speed, len); - - if (isecho || !israw) { - init_termbuf(); - tty_setecho(isecho); - tty_setraw(israw); - set_termbuf(); - if (!israw) { - /* - * Write a newline to ensure - * that login will be able to - * read the line... - */ - write(xpty, "\n", 1); - } - } - pty = xpty; - } -# else - argv = addarg(argv, name); -# endif -# endif - } else -#endif - if (user = getenv("USER")) { - if (strchr(user, '-')) { - syslog(LOG_ERR, "tried to pass user \"%s\" to login", - user); - fatal(net, "invalid user"); - } - argv = addarg(argv, getenv("USER")); -#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P) - { - register char **cpp; - for (cpp = environ; *cpp; cpp++) - argv = addarg(argv, *cpp); - } -#endif - /* - * Assume that login will set the USER variable - * correctly. For SysV systems, this means that - * USER will no longer be set, just LOGNAME by - * login. (The problem is that if the auto-login - * fails, and the user then specifies a different - * account name, he can get logged in with both - * LOGNAME and USER in his environment, but the - * USER value will be wrong. - */ - unsetenv("USER"); - } -#ifdef SOLARIS - else { - char **p; - - argv = addarg(argv, ""); /* no login name */ - for (p = environ; *p; p++) { - argv = addarg(argv, *p); - } - } -#endif /* SOLARIS */ -#if defined(AUTHENTICATION) && defined(NO_LOGIN_F) && defined(LOGIN_R) - if (pty > 2) - close(pty); -#endif - closelog(); - - if (altlogin == NULL) { - altlogin = _PATH_LOGIN; - } - execv(altlogin, argv); - - syslog(LOG_ERR, "%s: %m\n", altlogin); - fatalperror(net, altlogin); - /*NOTREACHED*/ -} - - char ** -addarg(argv, val) - register char **argv; - register char *val; -{ - register char **cpp; - - if (argv == NULL) { - /* - * 10 entries, a leading length, and a null - */ - argv = (char **)malloc(sizeof(*argv) * 12); - if (argv == NULL) - return(NULL); - *argv++ = (char *)10; - *argv = (char *)0; - } - for (cpp = argv; *cpp; cpp++) - ; - if (cpp == &argv[(int)argv[-1]]) { - --argv; - *argv = (char *)((int)(*argv) + 10); - argv = (char **)realloc(argv, sizeof(*argv)*((int)(*argv) + 2)); - if (argv == NULL) - return(NULL); - argv++; - cpp = &argv[(int)argv[-1] - 10]; - } - *cpp++ = val; - *cpp = 0; - return(argv); -} -#endif /* NEWINIT */ - -/* - * scrub_env() - * - * Remove a few things from the environment that - * don't need to be there. - */ -scrub_env() -{ - register char **cpp, **cpp2; - - for (cpp2 = cpp = environ; *cpp; cpp++) { -#ifdef __FreeBSD__ - if (strncmp(*cpp, "LD_LIBRARY_PATH=", 16) && - strncmp(*cpp, "LD_PRELOAD=", 11) && -#else - if (strncmp(*cpp, "LD_", 3) && - strncmp(*cpp, "_RLD_", 5) && - strncmp(*cpp, "LIBPATH=", 8) && -#endif - strncmp(*cpp, "IFS=", 4)) - *cpp2++ = *cpp; - } - *cpp2 = 0; -} - -/* - * cleanup() - * - * This is the routine to call when we are all through, to - * clean up anything that needs to be cleaned up. - */ - /* ARGSUSED */ - void -cleanup(sig) - int sig; -{ -#ifndef PARENT_DOES_UTMP -# if (BSD > 43) || defined(convex) - char *p; - - p = line + sizeof("/dev/") - 1; - if (logout(p)) - logwtmp(p, "", ""); - (void)chmod(line, 0666); - (void)chown(line, 0, 0); - *p = 'p'; - (void)chmod(line, 0666); - (void)chown(line, 0, 0); - (void) shutdown(net, 2); - exit(1); -# else - void rmut(); - - rmut(); - vhangup(); /* XXX */ - (void) shutdown(net, 2); - exit(1); -# endif -#else /* PARENT_DOES_UTMP */ -# ifdef NEWINIT - (void) shutdown(net, 2); - exit(1); -# else /* NEWINIT */ -# ifdef CRAY - static int incleanup = 0; - register int t; - int child_status; /* status of child process as returned by waitpid */ - int flags = WNOHANG|WUNTRACED; - - /* - * 1: Pick up the zombie, if we are being called - * as the signal handler. - * 2: If we are a nested cleanup(), return. - * 3: Try to clean up TMPDIR. - * 4: Fill in utmp with shutdown of process. - * 5: Close down the network and pty connections. - * 6: Finish up the TMPDIR cleanup, if needed. - */ - if (sig == SIGCHLD) { - while (waitpid(-1, &child_status, flags) > 0) - ; /* VOID */ - /* Check if the child process was stopped - * rather than exited. We want cleanup only if - * the child has died. - */ - if (WIFSTOPPED(child_status)) { - return; - } - } - t = sigblock(sigmask(SIGCHLD)); - if (incleanup) { - sigsetmask(t); - return; - } - incleanup = 1; - sigsetmask(t); -#ifdef UNICOS7x - if (secflag) { - /* - * We need to set ourselves back to a null - * label to clean up. - */ - - setulvl(sysv.sy_minlvl); - setucmp((long)0); - } -#endif /* UNICOS7x */ - - t = cleantmp(&wtmp); - setutent(); /* just to make sure */ -# endif /* CRAY */ - rmut(line); - close(pty); - (void) shutdown(net, 2); -# ifdef CRAY - if (t == 0) - cleantmp(&wtmp); -# endif /* CRAY */ - exit(1); -# endif /* NEWINT */ -#endif /* PARENT_DOES_UTMP */ -} - -#if defined(PARENT_DOES_UTMP) && !defined(NEWINIT) -/* - * _utmp_sig_rcv - * utmp_sig_init - * utmp_sig_wait - * These three functions are used to coordinate the handling of - * the utmp file between the server and the soon-to-be-login shell. - * The server actually creates the utmp structure, the child calls - * utmp_sig_wait(), until the server calls utmp_sig_notify() and - * signals the future-login shell to proceed. - */ -static int caught=0; /* NZ when signal intercepted */ -static void (*func)(); /* address of previous handler */ - - void -_utmp_sig_rcv(sig) - int sig; -{ - caught = 1; - (void) signal(SIGUSR1, func); -} - - void -utmp_sig_init() -{ - /* - * register signal handler for UTMP creation - */ - if ((int)(func = signal(SIGUSR1, _utmp_sig_rcv)) == -1) - fatalperror(net, "telnetd/signal"); -} - - void -utmp_sig_reset() -{ - (void) signal(SIGUSR1, func); /* reset handler to default */ -} - -# ifdef __hpux -# define sigoff() /* do nothing */ -# define sigon() /* do nothing */ -# endif - - void -utmp_sig_wait() -{ - /* - * Wait for parent to write our utmp entry. - */ - sigoff(); - while (caught == 0) { - pause(); /* wait until we get a signal (sigon) */ - sigoff(); /* turn off signals while we check caught */ - } - sigon(); /* turn on signals again */ -} - - void -utmp_sig_notify(pid) -{ - kill(pid, SIGUSR1); -} - -# ifdef CRAY -static int gotsigjob = 0; - - /*ARGSUSED*/ - void -sigjob(sig) - int sig; -{ - register int jid; - register struct jobtemp *jp; - - while ((jid = waitjob(NULL)) != -1) { - if (jid == 0) { - return; - } - gotsigjob++; - jobend(jid, NULL, NULL); - } -} - -/* - * jid_getutid: - * called by jobend() before calling cleantmp() - * to find the correct $TMPDIR to cleanup. - */ - - struct utmp * -jid_getutid(jid) - int jid; -{ - struct utmp *cur = NULL; - - setutent(); /* just to make sure */ - while (cur = getutent()) { - if ( (cur->ut_type != NULL) && (jid == cur->ut_jid) ) { - return(cur); - } - } - - return(0); -} - -/* - * Clean up the TMPDIR that login created. - * The first time this is called we pick up the info - * from the utmp. If the job has already gone away, - * then we'll clean up and be done. If not, then - * when this is called the second time it will wait - * for the signal that the job is done. - */ - int -cleantmp(wtp) - register struct utmp *wtp; -{ - struct utmp *utp; - static int first = 1; - register int mask, omask, ret; - extern struct utmp *getutid P((const struct utmp *_Id)); - - - mask = sigmask(WJSIGNAL); - - if (first == 0) { - omask = sigblock(mask); - while (gotsigjob == 0) - sigpause(omask); - return(1); - } - first = 0; - setutent(); /* just to make sure */ - - utp = getutid(wtp); - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } - /* - * Nothing to clean up if the user shell was never started. - */ - if (utp->ut_type != USER_PROCESS || utp->ut_jid == 0) - return(1); - - /* - * Block the WJSIGNAL while we are in jobend(). - */ - omask = sigblock(mask); - ret = jobend(utp->ut_jid, utp->ut_tpath, utp->ut_user); - sigsetmask(omask); - return(ret); -} - - int -jobend(jid, path, user) - register int jid; - register char *path; - register char *user; -{ - static int saved_jid = 0; - static int pty_saved_jid = 0; - static char saved_path[sizeof(wtmp.ut_tpath)+1]; - static char saved_user[sizeof(wtmp.ut_user)+1]; - - /* - * this little piece of code comes into play - * only when ptyreconnect is used to reconnect - * to an previous session. - * - * this is the only time when the - * "saved_jid != jid" code is executed. - */ - - if ( saved_jid && saved_jid != jid ) { - if (!path) { /* called from signal handler */ - pty_saved_jid = jid; - } else { - pty_saved_jid = saved_jid; - } - } - - if (path) { - strncpy(saved_path, path, sizeof(wtmp.ut_tpath)); - strncpy(saved_user, user, sizeof(wtmp.ut_user)); - saved_path[sizeof(saved_path)] = '\0'; - saved_user[sizeof(saved_user)] = '\0'; - } - if (saved_jid == 0) { - saved_jid = jid; - return(0); - } - - /* if the jid has changed, get the correct entry from the utmp file */ - - if ( saved_jid != jid ) { - struct utmp *utp = NULL; - struct utmp *jid_getutid(); - - utp = jid_getutid(pty_saved_jid); - - if (utp == 0) { - syslog(LOG_ERR, "Can't get /etc/utmp entry to clean TMPDIR"); - return(-1); - } - - cleantmpdir(jid, utp->ut_tpath, utp->ut_user); - return(1); - } - - cleantmpdir(jid, saved_path, saved_user); - return(1); -} - -/* - * Fork a child process to clean up the TMPDIR - */ -cleantmpdir(jid, tpath, user) - register int jid; - register char *tpath; - register char *user; -{ - switch(fork()) { - case -1: - syslog(LOG_ERR, "TMPDIR cleanup(%s): fork() failed: %m\n", - tpath); - break; - case 0: - execl(CLEANTMPCMD, CLEANTMPCMD, user, tpath, 0); - syslog(LOG_ERR, "TMPDIR cleanup(%s): execl(%s) failed: %m\n", - tpath, CLEANTMPCMD); - exit(1); - default: - /* - * Forget about child. We will exit, and - * /etc/init will pick it up. - */ - break; - } -} -# endif /* CRAY */ -#endif /* defined(PARENT_DOES_UTMP) && !defined(NEWINIT) */ - -/* - * rmut() - * - * This is the function called by cleanup() to - * remove the utmp entry for this person. - */ - -#ifdef UTMPX - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - struct utmpx *utxp, utmpx; - - /* - * This updates the utmpx and utmp entries and make a wtmp/x entry - */ - - SCPYN(utmpx.ut_line, line + sizeof("/dev/") - 1); - utxp = getutxline(&utmpx); - if (utxp) { - utxp->ut_type = DEAD_PROCESS; - utxp->ut_exit.e_termination = 0; - utxp->ut_exit.e_exit = 0; - (void) time(&utmpx.ut_tv.tv_sec); - utmpx.ut_tv.tv_usec = 0; - modutx(utxp); - } - endutxent(); -} /* end of rmut */ -#endif - -#if !defined(UTMPX) && !(defined(CRAY) || defined(__hpux)) && BSD <= 43 - void -rmut() -{ - register f; - int found = 0; - struct utmp *u, *utmp; - int nutmp; - struct stat statbf; - - f = open(utmpf, O_RDWR); - if (f >= 0) { - (void) fstat(f, &statbf); - utmp = (struct utmp *)malloc((unsigned)statbf.st_size); - if (!utmp) - syslog(LOG_ERR, "utmp malloc failed"); - if (statbf.st_size && utmp) { - nutmp = read(f, (char *)utmp, (int)statbf.st_size); - nutmp /= sizeof(struct utmp); - - for (u = utmp ; u < &utmp[nutmp] ; u++) { - if (SCMPN(u->ut_line, line+5) || - u->ut_name[0]==0) - continue; - (void) lseek(f, ((long)u)-((long)utmp), L_SET); - SCPYN(u->ut_name, ""); - SCPYN(u->ut_host, ""); - (void) time(&u->ut_time); - (void) write(f, (char *)u, sizeof(wtmp)); - found++; - } - } - (void) close(f); - } - if (found) { - f = open(wtmpf, O_WRONLY|O_APPEND); - if (f >= 0) { - SCPYN(wtmp.ut_line, line+5); - SCPYN(wtmp.ut_name, ""); - SCPYN(wtmp.ut_host, ""); - (void) time(&wtmp.ut_time); - (void) write(f, (char *)&wtmp, sizeof(wtmp)); - (void) close(f); - } - } - (void) chmod(line, 0666); - (void) chown(line, 0, 0); - line[strlen("/dev/")] = 'p'; - (void) chmod(line, 0666); - (void) chown(line, 0, 0); -} /* end of rmut */ -#endif /* CRAY */ - -#ifdef __hpux -rmut (line) -char *line; -{ - struct utmp utmp; - struct utmp *utptr; - int fd; /* for /etc/wtmp */ - - utmp.ut_type = USER_PROCESS; - (void) strncpy(utmp.ut_id, line+12, sizeof(utmp.ut_id)); - (void) setutent(); - utptr = getutid(&utmp); - /* write it out only if it exists */ - if (utptr) { - utptr->ut_type = DEAD_PROCESS; - utptr->ut_time = time((long *) 0); - (void) pututline(utptr); - /* set wtmp entry if wtmp file exists */ - if ((fd = open(wtmpf, O_WRONLY | O_APPEND)) >= 0) { - (void) write(fd, utptr, sizeof(utmp)); - (void) close(fd); - } - } - (void) endutent(); - - (void) chmod(line, 0666); - (void) chown(line, 0, 0); - line[14] = line[13]; - line[13] = line[12]; - line[8] = 'm'; - line[9] = '/'; - line[10] = 'p'; - line[11] = 't'; - line[12] = 'y'; - (void) chmod(line, 0666); - (void) chown(line, 0, 0); -} -#endif diff --git a/secure/libexec/telnetd/telnetd.8 b/secure/libexec/telnetd/telnetd.8 deleted file mode 100644 index 846189d..0000000 --- a/secure/libexec/telnetd/telnetd.8 +++ /dev/null @@ -1,613 +0,0 @@ -.\" Copyright (c) 1983, 1993 -.\" The Regents of the University of California. All rights reserved. -.\" -.\" Redistribution and use in source and binary forms, with or without -.\" modification, are permitted provided that the following conditions -.\" are met: -.\" 1. Redistributions of source code must retain the above copyright -.\" notice, this list of conditions and the following disclaimer. -.\" 2. Redistributions in binary form must reproduce the above copyright -.\" notice, this list of conditions and the following disclaimer in the -.\" documentation and/or other materials provided with the distribution. -.\" 3. All advertising materials mentioning features or use of this software -.\" must display the following acknowledgement: -.\" This product includes software developed by the University of -.\" California, Berkeley and its contributors. -.\" 4. Neither the name of the University nor the names of its contributors -.\" may be used to endorse or promote products derived from this software -.\" without specific prior written permission. -.\" -.\" THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND -.\" ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE -.\" IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE -.\" ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE -.\" FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL -.\" DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS -.\" OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) -.\" HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT -.\" LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY -.\" OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF -.\" SUCH DAMAGE. -.\" -.\" @(#)telnetd.8 8.4 (Berkeley) 6/1/94 -.\" -.Dd June 1, 1994 -.Dt TELNETD 8 -.Os BSD 4.2 -.Sh NAME -.Nm telnetd -.Nd DARPA -.Tn TELNET -protocol server -.Sh SYNOPSIS -.Nm /usr/libexec/telnetd -.Op Fl BUhlkns -.Op Fl D Ar debugmode -.Op Fl I Ns Ar initid -.Op Fl S Ar tos -.Op Fl X Ar authtype -.Op Fl a Ar authmode -.Op Fl edebug -.Op Fl P Ar loginprog -.Op Fl r Ns Ar lowpty-highpty -.Op Fl u Ar len -.Op Fl debug Op Ar port -.Sh DESCRIPTION -The -.Nm telnetd -command is a server which supports the -.Tn DARPA -standard -.Tn TELNET -virtual terminal protocol. -.Nm Telnetd -is normally invoked by the internet server (see -.Xr inetd 8 ) -for requests to connect to the -.Tn TELNET -port as indicated by the -.Pa /etc/services -file (see -.Xr services 5 ) . -The -.Fl debug -option may be used to start up -.Nm telnetd -manually, instead of through -.Xr inetd 8 . -If started up this way, -.Ar port -may be specified to run -.Nm telnetd -on an alternate -.Tn TCP -port number. -.Pp -The -.Nm telnetd -command accepts the following options: -.Bl -tag -width "-a authmode" -.It Fl a Ar authmode -This option may be used for specifying what mode should -be used for authentication. -Note that this option is only useful if -.Nm telnetd -has been compiled with support for the -.Dv AUTHENTICATION -option. -There are several valid values for -.Ar authmode: -.Bl -tag -width debug -.It debug -Turns on authentication debugging code. -.It user -Only allow connections when the remote user -can provide valid authentication information -to identify the remote user, -and is allowed access to the specified account -without providing a password. -.It valid -Only allow connections when the remote user -can provide valid authentication information -to identify the remote user. -The -.Xr login 1 -command will provide any additional user verification -needed if the remote user is not allowed automatic -access to the specified account. -.It other -Only allow connections that supply some authentication information. -This option is currently not supported -by any of the existing authentication mechanisms, -and is thus the same as specifying -.Fl a -.Cm valid . -.It none -This is the default state. -Authentication information is not required. -If no or insufficient authentication information -is provided, then the -.Xr login 1 -program will provide the necessary user -verification. -.It off -This disables the authentication code. -All user verification will happen through the -.Xr login 1 -program. -.El -.It Fl B -Specifies bftp server mode. In this mode, -.Nm telnetd -causes login to start a -.Xr bftp 1 -session rather than the user's -normal shell. In bftp daemon mode normal -logins are not supported, and it must be used -on a port other than the normal -.Tn TELNET -port. -.It Fl D Ar debugmode -This option may be used for debugging purposes. -This allows -.Nm telnetd -to print out debugging information -to the connection, allowing the user to see what -.Nm telnetd -is doing. -There are several possible values for -.Ar debugmode: -.Bl -tag -width exercise -.It Cm options -Prints information about the negotiation of -.Tn TELNET -options. -.It Cm report -Prints the -.Cm options -information, plus some additional information -about what processing is going on. -.It Cm netdata -Displays the data stream received by -.Nm telnetd. -.It Cm ptydata -Displays data written to the pty. -.It Cm exercise -Has not been implemented yet. -.El -.It Fl debug -Enables debugging on each socket created by -.Nm telnetd -(see -.Dv SO_DEBUG -in -.Xr socket 2 ) . -.It Fl edebug -If -.Nm telnetd -has been compiled with support for data encryption, then the -.Fl edebug -option may be used to enable encryption debugging code. -.It Fl P Ar loginprog -Specifies an alternate -.Xr login 1 -command to run to complete the login. The alternate command must -understand the same command arguments as the standard login. -.It Fl h -Disables the printing of host-specific information before -login has been completed. -.It Fl I Ar initid -This option is only applicable to -.Tn UNICOS -systems prior to 7.0. -It specifies the -.Dv ID -from -.Pa /etc/inittab -to use when init starts login sessions. The default -.Dv ID -is -.Dv fe. -.It Fl k -This option is only useful if -.Nm telnetd -has been compiled with both linemode and kludge linemode -support. If the -.Fl k -option is specified, then if the remote client does not -support the -.Dv LINEMODE -option, then -.Nm telnetd -will operate in character at a time mode. -It will still support kludge linemode, but will only -go into kludge linemode if the remote client requests -it. -(This is done by by the client sending -.Dv DONT SUPPRESS-GO-AHEAD -and -.Dv DONT ECHO . ) -The -.Fl k -option is most useful when there are remote clients -that do not support kludge linemode, but pass the heuristic -(if they respond with -.Dv WILL TIMING-MARK -in response to a -.Dv DO TIMING-MARK) -for kludge linemode support. -.It Fl l -Specifies line mode. Tries to force clients to use line- -at-a-time mode. -If the -.Dv LINEMODE -option is not supported, it will go -into kludge linemode. -.It Fl n -Disable -.Dv TCP -keep-alives. Normally -.Nm telnetd -enables the -.Tn TCP -keep-alive mechanism to probe connections that -have been idle for some period of time to determine -if the client is still there, so that idle connections -from machines that have crashed or can no longer -be reached may be cleaned up. -.It Fl r Ar lowpty-highpty -This option is only enabled when -.Nm telnetd -is compiled for -.Dv UNICOS. -It specifies an inclusive range of pseudo-terminal devices to -use. If the system has sysconf variable -.Dv _SC_CRAY_NPTY -configured, the default pty search range is 0 to -.Dv _SC_CRAY_NPTY; -otherwise, the default range is 0 to 128. Either -.Ar lowpty -or -.Ar highpty -may be omitted to allow changing -either end of the search range. If -.Ar lowpty -is omitted, the - character is still required so that -.Nm telnetd -can differentiate -.Ar highpty -from -.Ar lowpty . -.It Fl s -This option is only enabled if -.Nm telnetd -is compiled with support for -.Tn SecurID -cards. -It causes the -.Fl s -option to be passed on to -.Xr login 1 , -and thus is only useful if -.Xr login 1 -supports the -.Fl s -flag to indicate that only -.Tn SecurID -validated logins are allowed, and is -usually useful for controlling remote logins -from outside of a firewall. -.It Fl S Ar tos -.It Fl u Ar len -This option is used to specify the size of the field -in the -.Dv utmp -structure that holds the remote host name. -If the resolved host name is longer than -.Ar len , -the dotted decimal value will be used instead. -This allows hosts with very long host names that -overflow this field to still be uniquely identified. -Specifying -.Fl u0 -indicates that only dotted decimal addresses -should be put into the -.Pa utmp -file. -.ne 1i -.It Fl U -This option causes -.Nm telnetd -to refuse connections from addresses that -cannot be mapped back into a symbolic name -via the -.Xr gethostbyaddr 3 -routine. -.It Fl X Ar authtype -This option is only valid if -.Nm telnetd -has been built with support for the authentication option. -It disables the use of -.Ar authtype -authentication, and -can be used to temporarily disable -a specific authentication type without having to recompile -.Nm telnetd . -.El -.Pp -.Nm Telnetd -operates by allocating a pseudo-terminal device (see -.Xr pty 4 ) -for a client, then creating a login process which has -the slave side of the pseudo-terminal as -.Dv stdin , -.Dv stdout -and -.Dv stderr . -.Nm Telnetd -manipulates the master side of the pseudo-terminal, -implementing the -.Tn TELNET -protocol and passing characters -between the remote client and the login process. -.Pp -When a -.Tn TELNET -session is started up, -.Nm telnetd -sends -.Tn TELNET -options to the client side indicating -a willingness to do the -following -.Tn TELNET -options, which are described in more detail below: -.Bd -literal -offset indent -DO AUTHENTICATION -WILL ENCRYPT -DO TERMINAL TYPE -DO TSPEED -DO XDISPLOC -DO NEW-ENVIRON -DO ENVIRON -WILL SUPPRESS GO AHEAD -DO ECHO -DO LINEMODE -DO NAWS -WILL STATUS -DO LFLOW -DO TIMING-MARK -.Ed -.Pp -The pseudo-terminal allocated to the client is configured -to operate in \*(lqcooked\*(rq mode, and with -.Dv XTABS and -.Dv CRMOD -enabled (see -.Xr tty 4 ) . -.Pp -.Nm Telnetd -has support for enabling locally the following -.Tn TELNET -options: -.Bl -tag -width "DO AUTHENTICATION" -.It "WILL ECHO" -When the -.Dv LINEMODE -option is enabled, a -.Dv WILL ECHO -or -.Dv WONT ECHO -will be sent to the client to indicate the -current state of terminal echoing. -When terminal echo is not desired, a -.Dv WILL ECHO -is sent to indicate that -.Tn telnetd -will take care of echoing any data that needs to be -echoed to the terminal, and then nothing is echoed. -When terminal echo is desired, a -.Dv WONT ECHO -is sent to indicate that -.Tn telnetd -will not be doing any terminal echoing, so the -client should do any terminal echoing that is needed. -.It "WILL BINARY" -Indicates that the client is willing to send a -8 bits of data, rather than the normal 7 bits -of the Network Virtual Terminal. -.It "WILL SGA" -Indicates that it will not be sending -.Dv IAC GA, -go ahead, commands. -.It "WILL STATUS" -Indicates a willingness to send the client, upon -request, of the current status of all -.Tn TELNET -options. -.It "WILL TIMING-MARK" -Whenever a -.Dv DO TIMING-MARK -command is received, it is always responded -to with a -.Dv WILL TIMING-MARK -.ne 1i -.It "WILL LOGOUT" -When a -.Dv DO LOGOUT -is received, a -.Dv WILL LOGOUT -is sent in response, and the -.Tn TELNET -session is shut down. -.It "WILL ENCRYPT" -Only sent if -.Nm telnetd -is compiled with support for data encryption, and -indicates a willingness to decrypt -the data stream. -.El -.Pp -.Nm Telnetd -has support for enabling remotely the following -.Tn TELNET -options: -.Bl -tag -width "DO AUTHENTICATION" -.It "DO BINARY" -Sent to indicate that -.Tn telnetd -is willing to receive an 8 bit data stream. -.It "DO LFLOW" -Requests that the client handle flow control -characters remotely. -.It "DO ECHO" -This is not really supported, but is sent to identify a 4.2BSD -.Xr telnet 1 -client, which will improperly respond with -.Dv WILL ECHO. -If a -.Dv WILL ECHO -is received, a -.Dv DONT ECHO -will be sent in response. -.It "DO TERMINAL-TYPE" -Indicates a desire to be able to request the -name of the type of terminal that is attached -to the client side of the connection. -.It "DO SGA" -Indicates that it does not need to receive -.Dv IAC GA, -the go ahead command. -.It "DO NAWS" -Requests that the client inform the server when -the window (display) size changes. -.It "DO TERMINAL-SPEED" -Indicates a desire to be able to request information -about the speed of the serial line to which -the client is attached. -.It "DO XDISPLOC" -Indicates a desire to be able to request the name -of the X windows display that is associated with -the telnet client. -.It "DO NEW-ENVIRON" -Indicates a desire to be able to request environment -variable information, as described in RFC 1572. -.It "DO ENVIRON" -Indicates a desire to be able to request environment -variable information, as described in RFC 1408. -.It "DO LINEMODE" -Only sent if -.Nm telnetd -is compiled with support for linemode, and -requests that the client do line by line processing. -.It "DO TIMING-MARK" -Only sent if -.Nm telnetd -is compiled with support for both linemode and -kludge linemode, and the client responded with -.Dv WONT LINEMODE. -If the client responds with -.Dv WILL TM, -the it is assumed that the client supports -kludge linemode. -Note that the -.Op Fl k -option can be used to disable this. -.It "DO AUTHENTICATION" -Only sent if -.Nm telnetd -is compiled with support for authentication, and -indicates a willingness to receive authentication -information for automatic login. -.It "DO ENCRYPT" -Only sent if -.Nm telnetd -is compiled with support for data encryption, and -indicates a willingness to decrypt -the data stream. -.Sh ENVIRONMENT -.Sh FILES -.Pa /etc/services -.br -.Pa /etc/inittab -(UNICOS systems only) -.br -.Pa /etc/iptos -(if supported) -.br -.Pa /usr/ucb/bftp -(if supported) -.Sh "SEE ALSO" -.Xr telnet 1 , -.Xr login 1 , -.Xr bftp 1 -(if supported) -.Sh STANDARDS -.Bl -tag -compact -width RFC-1572 -.It Cm RFC-854 -.Tn TELNET -PROTOCOL SPECIFICATION -.It Cm RFC-855 -TELNET OPTION SPECIFICATIONS -.It Cm RFC-856 -TELNET BINARY TRANSMISSION -.It Cm RFC-857 -TELNET ECHO OPTION -.It Cm RFC-858 -TELNET SUPPRESS GO AHEAD OPTION -.It Cm RFC-859 -TELNET STATUS OPTION -.It Cm RFC-860 -TELNET TIMING MARK OPTION -.It Cm RFC-861 -TELNET EXTENDED OPTIONS - LIST OPTION -.It Cm RFC-885 -TELNET END OF RECORD OPTION -.It Cm RFC-1073 -Telnet Window Size Option -.It Cm RFC-1079 -Telnet Terminal Speed Option -.It Cm RFC-1091 -Telnet Terminal-Type Option -.It Cm RFC-1096 -Telnet X Display Location Option -.It Cm RFC-1123 -Requirements for Internet Hosts -- Application and Support -.It Cm RFC-1184 -Telnet Linemode Option -.It Cm RFC-1372 -Telnet Remote Flow Control Option -.It Cm RFC-1416 -Telnet Authentication Option -.It Cm RFC-1411 -Telnet Authentication: Kerberos Version 4 -.It Cm RFC-1412 -Telnet Authentication: SPX -.It Cm RFC-1571 -Telnet Environment Option Interoperability Issues -.It Cm RFC-1572 -Telnet Environment Option -.Sh BUGS -Some -.Tn TELNET -commands are only partially implemented. -.Pp -Because of bugs in the original 4.2 BSD -.Xr telnet 1 , -.Nm telnetd -performs some dubious protocol exchanges to try to discover if the remote -client is, in fact, a 4.2 BSD -.Xr telnet 1 . -.Pp -Binary mode -has no common interpretation except between similar operating systems -(Unix in this case). -.Pp -The terminal type name received from the remote client is converted to -lower case. -.Pp -.Nm Telnetd -never sends -.Tn TELNET -.Dv IAC GA -(go ahead) commands. diff --git a/secure/libexec/telnetd/telnetd.c b/secure/libexec/telnetd/telnetd.c deleted file mode 100644 index 40fdad5..0000000 --- a/secure/libexec/telnetd/telnetd.c +++ /dev/null @@ -1,1598 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char copyright[] = -"@(#) Copyright (c) 1989, 1993\n\ - The Regents of the University of California. All rights reserved.\n"; -#endif /* not lint */ - -#ifndef lint -static char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95"; -#endif /* not lint */ - -#include "telnetd.h" -#include "pathnames.h" - -#if defined(_SC_CRAY_SECURE_SYS) && !defined(SCM_SECURITY) -/* - * UNICOS 6.0/6.1 do not have SCM_SECURITY defined, so we can - * use it to tell us to turn off all the socket security code, - * since that is only used in UNICOS 7.0 and later. - */ -# undef _SC_CRAY_SECURE_SYS -#endif - -#if defined(_SC_CRAY_SECURE_SYS) -#include <sys/sysv.h> -#include <sys/secdev.h> -# ifdef SO_SEC_MULTI /* 8.0 code */ -#include <sys/secparm.h> -#include <sys/usrv.h> -# endif /* SO_SEC_MULTI */ -int secflag; -char tty_dev[16]; -struct secdev dv; -struct sysv sysv; -# ifdef SO_SEC_MULTI /* 8.0 code */ -struct socksec ss; -# else /* SO_SEC_MULTI */ /* 7.0 code */ -struct socket_security ss; -# endif /* SO_SEC_MULTI */ -#endif /* _SC_CRAY_SECURE_SYS */ - -#if defined(AUTHENTICATION) -#include <libtelnet/auth.h> -int auth_level = 0; -#endif -#if defined(SecurID) -int require_SecurID = 0; -#endif - -extern int utmp_len; -int registerd_host_only = 0; - -#ifdef STREAMSPTY -# include <stropts.h> -# include <termio.h> -/* make sure we don't get the bsd version */ -# include "/usr/include/sys/tty.h" -# include <sys/ptyvar.h> - -/* - * Because of the way ptyibuf is used with streams messages, we need - * ptyibuf+1 to be on a full-word boundary. The following wierdness - * is simply to make that happen. - */ -long ptyibufbuf[BUFSIZ/sizeof(long)+1]; -char *ptyibuf = ((char *)&ptyibufbuf[1])-1; -char *ptyip = ((char *)&ptyibufbuf[1])-1; -char ptyibuf2[BUFSIZ]; -unsigned char ctlbuf[BUFSIZ]; -struct strbuf strbufc, strbufd; - -int readstream(); - -#else /* ! STREAMPTY */ - -/* - * I/O data buffers, - * pointers, and counters. - */ -char ptyibuf[BUFSIZ], *ptyip = ptyibuf; -char ptyibuf2[BUFSIZ]; - -#endif /* ! STREAMPTY */ - -int hostinfo = 1; /* do we print login banner? */ - -#ifdef CRAY -extern int newmap; /* nonzero if \n maps to ^M^J */ -int lowpty = 0, highpty; /* low, high pty numbers */ -#endif /* CRAY */ - -int debug = 0; -int keepalive = 1; -char *progname; -char *altlogin; - -extern void usage P((void)); - -/* - * The string to pass to getopt(). We do it this way so - * that only the actual options that we support will be - * passed off to getopt(). - */ -char valid_opts[] = { - 'd', ':', 'h', 'k', 'n', 'p', ':', 'S', ':', 'u', ':', 'U', -#ifdef AUTHENTICATION - 'a', ':', 'X', ':', -#endif -#ifdef BFTPDAEMON - 'B', -#endif -#ifdef DIAGNOSTICS - 'D', ':', -#endif -#ifdef ENCRYPTION - 'e', ':', -#endif -#if defined(CRAY) && defined(NEWINIT) - 'I', ':', -#endif -#ifdef LINEMODE - 'l', -#endif -#ifdef CRAY - 'r', ':', -#endif -#ifdef SecurID - 's', -#endif - '\0' -}; - -main(argc, argv) - char *argv[]; -{ - struct sockaddr_in from; - int on = 1, fromlen; - register int ch; - extern char *optarg; - extern int optind; -#if defined(IPPROTO_IP) && defined(IP_TOS) - int tos = -1; -#endif - - pfrontp = pbackp = ptyobuf; - netip = netibuf; - nfrontp = nbackp = netobuf; -#ifdef ENCRYPTION - nclearto = 0; -#endif /* ENCRYPTION */ - - progname = *argv; - -#ifdef CRAY - /* - * Get number of pty's before trying to process options, - * which may include changing pty range. - */ - highpty = getnpty(); -#endif /* CRAY */ - - while ((ch = getopt(argc, argv, valid_opts)) != EOF) { - switch(ch) { - -#ifdef AUTHENTICATION - case 'a': - /* - * Check for required authentication level - */ - if (strcmp(optarg, "debug") == 0) { - extern int auth_debug_mode; - auth_debug_mode = 1; - } else if (strcasecmp(optarg, "none") == 0) { - auth_level = 0; - } else if (strcasecmp(optarg, "other") == 0) { - auth_level = AUTH_OTHER; - } else if (strcasecmp(optarg, "user") == 0) { - auth_level = AUTH_USER; - } else if (strcasecmp(optarg, "valid") == 0) { - auth_level = AUTH_VALID; - } else if (strcasecmp(optarg, "off") == 0) { - /* - * This hack turns off authentication - */ - auth_level = -1; - } else { - fprintf(stderr, - "telnetd: unknown authorization level for -a\n"); - } - break; -#endif /* AUTHENTICATION */ - -#ifdef BFTPDAEMON - case 'B': - bftpd++; - break; -#endif /* BFTPDAEMON */ - - case 'd': - if (strcmp(optarg, "ebug") == 0) { - debug++; - break; - } - usage(); - /* NOTREACHED */ - break; - -#ifdef DIAGNOSTICS - case 'D': - /* - * Check for desired diagnostics capabilities. - */ - if (!strcmp(optarg, "report")) { - diagnostic |= TD_REPORT|TD_OPTIONS; - } else if (!strcmp(optarg, "exercise")) { - diagnostic |= TD_EXERCISE; - } else if (!strcmp(optarg, "netdata")) { - diagnostic |= TD_NETDATA; - } else if (!strcmp(optarg, "ptydata")) { - diagnostic |= TD_PTYDATA; - } else if (!strcmp(optarg, "options")) { - diagnostic |= TD_OPTIONS; - } else { - usage(); - /* NOT REACHED */ - } - break; -#endif /* DIAGNOSTICS */ - -#ifdef ENCRYPTION - case 'e': - if (strcmp(optarg, "debug") == 0) { - extern int encrypt_debug_mode; - encrypt_debug_mode = 1; - break; - } - usage(); - /* NOTREACHED */ - break; -#endif /* ENCRYPTION */ - - case 'h': - hostinfo = 0; - break; - -#if defined(CRAY) && defined(NEWINIT) - case 'I': - { - extern char *gen_id; - gen_id = optarg; - break; - } -#endif /* defined(CRAY) && defined(NEWINIT) */ - -#ifdef LINEMODE - case 'l': - alwayslinemode = 1; - break; -#endif /* LINEMODE */ - - case 'k': -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - lmodetype = NO_AUTOKLUDGE; -#else - /* ignore -k option if built without kludge linemode */ -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - break; - - case 'n': - keepalive = 0; - break; - - case 'p': - altlogin = optarg; - break; - -#ifdef CRAY - case 'r': - { - char *strchr(); - char *c; - - /* - * Allow the specification of alterations - * to the pty search range. It is legal to - * specify only one, and not change the - * other from its default. - */ - c = strchr(optarg, '-'); - if (c) { - *c++ = '\0'; - highpty = atoi(c); - } - if (*optarg != '\0') - lowpty = atoi(optarg); - if ((lowpty > highpty) || (lowpty < 0) || - (highpty > 32767)) { - usage(); - /* NOT REACHED */ - } - break; - } -#endif /* CRAY */ - -#ifdef SecurID - case 's': - /* SecurID required */ - require_SecurID = 1; - break; -#endif /* SecurID */ - case 'S': -#ifdef HAS_GETTOS - if ((tos = parsetos(optarg, "tcp")) < 0) - fprintf(stderr, "%s%s%s\n", - "telnetd: Bad TOS argument '", optarg, - "'; will try to use default TOS"); -#else - fprintf(stderr, "%s%s\n", "TOS option unavailable; ", - "-S flag not supported\n"); -#endif - break; - - case 'u': - utmp_len = atoi(optarg); - break; - - case 'U': - registerd_host_only = 1; - break; - -#ifdef AUTHENTICATION - case 'X': - /* - * Check for invalid authentication types - */ - auth_disable_name(optarg); - break; -#endif /* AUTHENTICATION */ - - default: - fprintf(stderr, "telnetd: %c: unknown option\n", ch); - /* FALLTHROUGH */ - case '?': - usage(); - /* NOTREACHED */ - } - } - - argc -= optind; - argv += optind; - - if (debug) { - int s, ns, foo; - struct servent *sp; - static struct sockaddr_in sin = { AF_INET }; - - if (argc > 1) { - usage(); - /* NOT REACHED */ - } else if (argc == 1) { - if (sp = getservbyname(*argv, "tcp")) { - sin.sin_port = sp->s_port; - } else { - sin.sin_port = atoi(*argv); - if ((int)sin.sin_port <= 0) { - fprintf(stderr, "telnetd: %s: bad port #\n", *argv); - usage(); - /* NOT REACHED */ - } - sin.sin_port = htons((u_short)sin.sin_port); - } - } else { - sp = getservbyname("telnet", "tcp"); - if (sp == 0) { - fprintf(stderr, "telnetd: tcp/telnet: unknown service\n"); - exit(1); - } - sin.sin_port = sp->s_port; - } - - s = socket(AF_INET, SOCK_STREAM, 0); - if (s < 0) { - perror("telnetd: socket");; - exit(1); - } - (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, - (char *)&on, sizeof(on)); - if (bind(s, (struct sockaddr *)&sin, sizeof sin) < 0) { - perror("bind"); - exit(1); - } - if (listen(s, 1) < 0) { - perror("listen"); - exit(1); - } - foo = sizeof sin; - ns = accept(s, (struct sockaddr *)&sin, &foo); - if (ns < 0) { - perror("accept"); - exit(1); - } - (void) dup2(ns, 0); - (void) close(ns); - (void) close(s); -#ifdef convex - } else if (argc == 1) { - ; /* VOID*/ /* Just ignore the host/port name */ -#endif - } else if (argc > 0) { - usage(); - /* NOT REACHED */ - } - -#if defined(_SC_CRAY_SECURE_SYS) - secflag = sysconf(_SC_CRAY_SECURE_SYS); - - /* - * Get socket's security label - */ - if (secflag) { - int szss = sizeof(ss); -#ifdef SO_SEC_MULTI /* 8.0 code */ - int sock_multi; - int szi = sizeof(int); -#endif /* SO_SEC_MULTI */ - - memset((char *)&dv, 0, sizeof(dv)); - - if (getsysv(&sysv, sizeof(struct sysv)) != 0) { - perror("getsysv"); - exit(1); - } - - /* - * Get socket security label and set device values - * {security label to be set on ttyp device} - */ -#ifdef SO_SEC_MULTI /* 8.0 code */ - if ((getsockopt(0, SOL_SOCKET, SO_SECURITY, - (char *)&ss, &szss) < 0) || - (getsockopt(0, SOL_SOCKET, SO_SEC_MULTI, - (char *)&sock_multi, &szi) < 0)) { - perror("getsockopt"); - exit(1); - } else { - dv.dv_actlvl = ss.ss_actlabel.lt_level; - dv.dv_actcmp = ss.ss_actlabel.lt_compart; - if (!sock_multi) { - dv.dv_minlvl = dv.dv_maxlvl = dv.dv_actlvl; - dv.dv_valcmp = dv.dv_actcmp; - } else { - dv.dv_minlvl = ss.ss_minlabel.lt_level; - dv.dv_maxlvl = ss.ss_maxlabel.lt_level; - dv.dv_valcmp = ss.ss_maxlabel.lt_compart; - } - dv.dv_devflg = 0; - } -#else /* SO_SEC_MULTI */ /* 7.0 code */ - if (getsockopt(0, SOL_SOCKET, SO_SECURITY, - (char *)&ss, &szss) >= 0) { - dv.dv_actlvl = ss.ss_slevel; - dv.dv_actcmp = ss.ss_compart; - dv.dv_minlvl = ss.ss_minlvl; - dv.dv_maxlvl = ss.ss_maxlvl; - dv.dv_valcmp = ss.ss_maxcmp; - } -#endif /* SO_SEC_MULTI */ - } -#endif /* _SC_CRAY_SECURE_SYS */ - - openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON); - fromlen = sizeof (from); - if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) { - fprintf(stderr, "%s: ", progname); - perror("getpeername"); - _exit(1); - } - if (keepalive && - setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, - (char *)&on, sizeof (on)) < 0) { - syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m"); - } - -#if defined(IPPROTO_IP) && defined(IP_TOS) - { -# if defined(HAS_GETTOS) - struct tosent *tp; - if (tos < 0 && (tp = gettosbyname("telnet", "tcp"))) - tos = tp->t_tos; -# endif - if (tos < 0) - tos = 020; /* Low Delay bit */ - if (tos - && (setsockopt(0, IPPROTO_IP, IP_TOS, - (char *)&tos, sizeof(tos)) < 0) - && (errno != ENOPROTOOPT) ) - syslog(LOG_WARNING, "setsockopt (IP_TOS): %m"); - } -#endif /* defined(IPPROTO_IP) && defined(IP_TOS) */ - net = 0; - doit(&from); - /* NOTREACHED */ -} /* end of main */ - - void -usage() -{ - fprintf(stderr, "Usage: telnetd"); -#ifdef AUTHENTICATION - fprintf(stderr, " [-a (debug|other|user|valid|off|none)]\n\t"); -#endif -#ifdef BFTPDAEMON - fprintf(stderr, " [-B]"); -#endif - fprintf(stderr, " [-debug]"); -#ifdef DIAGNOSTICS - fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t"); -#endif -#ifdef AUTHENTICATION - fprintf(stderr, " [-edebug]"); -#endif - fprintf(stderr, " [-h]"); -#if defined(CRAY) && defined(NEWINIT) - fprintf(stderr, " [-Iinitid]"); -#endif -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - fprintf(stderr, " [-k]"); -#endif -#ifdef LINEMODE - fprintf(stderr, " [-l]"); -#endif - fprintf(stderr, " [-n]"); -#ifdef CRAY - fprintf(stderr, " [-r[lowpty]-[highpty]]"); -#endif - fprintf(stderr, "\n\t"); -#ifdef SecurID - fprintf(stderr, " [-s]"); -#endif -#ifdef HAS_GETTOS - fprintf(stderr, " [-S tos]"); -#endif -#ifdef AUTHENTICATION - fprintf(stderr, " [-X auth-type]"); -#endif - fprintf(stderr, " [-u utmp_hostname_length] [-U]"); - fprintf(stderr, " [port]\n"); - exit(1); -} - -/* - * getterminaltype - * - * Ask the other end to send along its terminal type and speed. - * Output is the variable terminaltype filled in. - */ -static unsigned char ttytype_sbbuf[] = { - IAC, SB, TELOPT_TTYPE, TELQUAL_SEND, IAC, SE -}; - - int -getterminaltype(name) - char *name; -{ - int retval = -1; - void _gettermname(); - - settimer(baseline); -#if defined(AUTHENTICATION) - /* - * Handle the Authentication option before we do anything else. - */ - send_do(TELOPT_AUTHENTICATION, 1); - while (his_will_wont_is_changing(TELOPT_AUTHENTICATION)) - ttloop(); - if (his_state_is_will(TELOPT_AUTHENTICATION)) { - retval = auth_wait(name); - } -#endif - -#ifdef ENCRYPTION - send_will(TELOPT_ENCRYPT, 1); -#endif /* ENCRYPTION */ - send_do(TELOPT_TTYPE, 1); - send_do(TELOPT_TSPEED, 1); - send_do(TELOPT_XDISPLOC, 1); - send_do(TELOPT_NEW_ENVIRON, 1); - send_do(TELOPT_OLD_ENVIRON, 1); - while ( -#ifdef ENCRYPTION - his_do_dont_is_changing(TELOPT_ENCRYPT) || -#endif /* ENCRYPTION */ - his_will_wont_is_changing(TELOPT_TTYPE) || - his_will_wont_is_changing(TELOPT_TSPEED) || - his_will_wont_is_changing(TELOPT_XDISPLOC) || - his_will_wont_is_changing(TELOPT_NEW_ENVIRON) || - his_will_wont_is_changing(TELOPT_OLD_ENVIRON)) { - ttloop(); - } -#ifdef ENCRYPTION - /* - * Wait for the negotiation of what type of encryption we can - * send with. If autoencrypt is not set, this will just return. - */ - if (his_state_is_will(TELOPT_ENCRYPT)) { - encrypt_wait(); - } -#endif /* ENCRYPTION */ - if (his_state_is_will(TELOPT_TSPEED)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE }; - - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - if (his_state_is_will(TELOPT_XDISPLOC)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_XDISPLOC, TELQUAL_SEND, IAC, SE }; - - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - if (his_state_is_will(TELOPT_NEW_ENVIRON)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_NEW_ENVIRON, TELQUAL_SEND, IAC, SE }; - - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - else if (his_state_is_will(TELOPT_OLD_ENVIRON)) { - static unsigned char sb[] = - { IAC, SB, TELOPT_OLD_ENVIRON, TELQUAL_SEND, IAC, SE }; - - memmove(nfrontp, sb, sizeof sb); - nfrontp += sizeof sb; - DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2);); - } - if (his_state_is_will(TELOPT_TTYPE)) { - - memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; - DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); - } - if (his_state_is_will(TELOPT_TSPEED)) { - while (sequenceIs(tspeedsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_XDISPLOC)) { - while (sequenceIs(xdisplocsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_NEW_ENVIRON)) { - while (sequenceIs(environsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_OLD_ENVIRON)) { - while (sequenceIs(oenvironsubopt, baseline)) - ttloop(); - } - if (his_state_is_will(TELOPT_TTYPE)) { - char first[256], last[256]; - - while (sequenceIs(ttypesubopt, baseline)) - ttloop(); - - /* - * If the other side has already disabled the option, then - * we have to just go with what we (might) have already gotten. - */ - if (his_state_is_will(TELOPT_TTYPE) && !terminaltypeok(terminaltype)) { - (void) strncpy(first, terminaltype, sizeof(first)); - for(;;) { - /* - * Save the unknown name, and request the next name. - */ - (void) strncpy(last, terminaltype, sizeof(last)); - _gettermname(); - if (terminaltypeok(terminaltype)) - break; - if ((strncmp(last, terminaltype, sizeof(last)) == 0) || - his_state_is_wont(TELOPT_TTYPE)) { - /* - * We've hit the end. If this is the same as - * the first name, just go with it. - */ - if (strncmp(first, terminaltype, sizeof(first)) == 0) - break; - /* - * Get the terminal name one more time, so that - * RFC1091 compliant telnets will cycle back to - * the start of the list. - */ - _gettermname(); - if (strncmp(first, terminaltype, sizeof(first)) != 0) - (void) strncpy(terminaltype, first, sizeof(first)); - break; - } - } - } - } - return(retval); -} /* end of getterminaltype */ - - void -_gettermname() -{ - /* - * If the client turned off the option, - * we can't send another request, so we - * just return. - */ - if (his_state_is_wont(TELOPT_TTYPE)) - return; - settimer(baseline); - memmove(nfrontp, ttytype_sbbuf, sizeof ttytype_sbbuf); - nfrontp += sizeof ttytype_sbbuf; - DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2, - sizeof ttytype_sbbuf - 2);); - while (sequenceIs(ttypesubopt, baseline)) - ttloop(); -} - - int -terminaltypeok(s) - char *s; -{ - char buf[1024]; - - if (terminaltype == NULL) - return(1); - - /* - * tgetent() will return 1 if the type is known, and - * 0 if it is not known. If it returns -1, it couldn't - * open the database. But if we can't open the database, - * it won't help to say we failed, because we won't be - * able to verify anything else. So, we treat -1 like 1. - */ - if (tgetent(buf, s) == 0) - return(0); - return(1); -} - -#ifndef MAXHOSTNAMELEN -#define MAXHOSTNAMELEN 64 -#endif /* MAXHOSTNAMELEN */ - -char *hostname; -char host_name[MAXHOSTNAMELEN]; -char remote_host_name[MAXHOSTNAMELEN]; - -extern void telnet P((int, int, char *)); - -int level; -char user_name[256]; -/* - * Get a pty, scan input lines. - */ -doit(who) - struct sockaddr_in *who; -{ - char *host, *inet_ntoa(); - int t; - struct hostent *hp; - int ptynum; - - /* - * Find an available pty to use. - */ -#ifndef convex - pty = getpty(&ptynum); - if (pty < 0) - fatal(net, "All network ports in use"); -#else - for (;;) { - char *lp; - extern char *line, *getpty(); - - if ((lp = getpty()) == NULL) - fatal(net, "Out of ptys"); - - if ((pty = open(lp, 2)) >= 0) { - strcpy(line,lp); - line[5] = 't'; - break; - } - } -#endif - -#if defined(_SC_CRAY_SECURE_SYS) - /* - * set ttyp line security label - */ - if (secflag) { - char slave_dev[16]; - - sprintf(tty_dev, "/dev/pty/%03d", ptynum); - if (setdevs(tty_dev, &dv) < 0) - fatal(net, "cannot set pty security"); - sprintf(slave_dev, "/dev/ttyp%03d", ptynum); - if (setdevs(slave_dev, &dv) < 0) - fatal(net, "cannot set tty security"); - } -#endif /* _SC_CRAY_SECURE_SYS */ - - /* get name of connected client */ - hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr), - who->sin_family); - - if (hp == NULL && registerd_host_only) { - fatal(net, "Couldn't resolve your address into a host name.\r\n\ - Please contact your net administrator"); - } else if (hp && - (strlen(hp->h_name) <= (unsigned int)((utmp_len < 0) ? -utmp_len - : utmp_len))) { - host = hp->h_name; - } else { - host = inet_ntoa(who->sin_addr); - } - /* - * We must make a copy because Kerberos is probably going - * to also do a gethost* and overwrite the static data... - */ - strncpy(remote_host_name, host, sizeof(remote_host_name)-1); - remote_host_name[sizeof(remote_host_name)-1] = 0; - host = remote_host_name; - - (void) gethostname(host_name, sizeof (host_name)); - hostname = host_name; - -#if defined(AUTHENTICATION) || defined(ENCRYPTION) - auth_encrypt_init(hostname, host, "TELNETD", 1); -#endif - - init_env(); - /* - * get terminal type. - */ - *user_name = 0; - level = getterminaltype(user_name); - setenv("TERM", terminaltype ? terminaltype : "network", 1); - -#if defined(_SC_CRAY_SECURE_SYS) - if (secflag) { - if (setulvl(dv.dv_actlvl) < 0) - fatal(net,"cannot setulvl()"); - if (setucmp(dv.dv_actcmp) < 0) - fatal(net, "cannot setucmp()"); - } -#endif /* _SC_CRAY_SECURE_SYS */ - - telnet(net, pty, host); /* begin server process */ - - /*NOTREACHED*/ -} /* end of doit */ - -#if defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) - int -Xterm_output(ibufp, obuf, icountp, ocount) - char **ibufp, *obuf; - int *icountp, ocount; -{ - int ret; - ret = term_output(*ibufp, obuf, *icountp, ocount); - *ibufp += *icountp; - *icountp = 0; - return(ret); -} -#define term_output Xterm_output -#endif /* defined(CRAY2) && defined(UNICOS5) && defined(UNICOS50) */ - -/* - * Main loop. Select from pty and network, and - * hand data to telnet receiver finite state machine. - */ - void -telnet(f, p, host) - int f, p; - char *host; -{ - int on = 1; -#define TABBUFSIZ 512 - char defent[TABBUFSIZ]; - char defstrs[TABBUFSIZ]; -#undef TABBUFSIZ - char *HE; - char *HN; - char *IM; - void netflush(); - int nfd; - - /* - * Initialize the slc mapping table. - */ - get_slc_defaults(); - - /* - * Do some tests where it is desireable to wait for a response. - * Rather than doing them slowly, one at a time, do them all - * at once. - */ - if (my_state_is_wont(TELOPT_SGA)) - send_will(TELOPT_SGA, 1); - /* - * Is the client side a 4.2 (NOT 4.3) system? We need to know this - * because 4.2 clients are unable to deal with TCP urgent data. - * - * To find out, we send out a "DO ECHO". If the remote system - * answers "WILL ECHO" it is probably a 4.2 client, and we note - * that fact ("WILL ECHO" ==> that the client will echo what - * WE, the server, sends it; it does NOT mean that the client will - * echo the terminal input). - */ - send_do(TELOPT_ECHO, 1); - -#ifdef LINEMODE - if (his_state_is_wont(TELOPT_LINEMODE)) { - /* Query the peer for linemode support by trying to negotiate - * the linemode option. - */ - linemode = 0; - editmode = 0; - send_do(TELOPT_LINEMODE, 1); /* send do linemode */ - } -#endif /* LINEMODE */ - - /* - * Send along a couple of other options that we wish to negotiate. - */ - send_do(TELOPT_NAWS, 1); - send_will(TELOPT_STATUS, 1); - flowmode = 1; /* default flow control state */ - restartany = -1; /* uninitialized... */ - send_do(TELOPT_LFLOW, 1); - - /* - * Spin, waiting for a response from the DO ECHO. However, - * some REALLY DUMB telnets out there might not respond - * to the DO ECHO. So, we spin looking for NAWS, (most dumb - * telnets so far seem to respond with WONT for a DO that - * they don't understand...) because by the time we get the - * response, it will already have processed the DO ECHO. - * Kludge upon kludge. - */ - while (his_will_wont_is_changing(TELOPT_NAWS)) - ttloop(); - - /* - * But... - * The client might have sent a WILL NAWS as part of its - * startup code; if so, we'll be here before we get the - * response to the DO ECHO. We'll make the assumption - * that any implementation that understands about NAWS - * is a modern enough implementation that it will respond - * to our DO ECHO request; hence we'll do another spin - * waiting for the ECHO option to settle down, which is - * what we wanted to do in the first place... - */ - if (his_want_state_is_will(TELOPT_ECHO) && - his_state_is_will(TELOPT_NAWS)) { - while (his_will_wont_is_changing(TELOPT_ECHO)) - ttloop(); - } - /* - * On the off chance that the telnet client is broken and does not - * respond to the DO ECHO we sent, (after all, we did send the - * DO NAWS negotiation after the DO ECHO, and we won't get here - * until a response to the DO NAWS comes back) simulate the - * receipt of a will echo. This will also send a WONT ECHO - * to the client, since we assume that the client failed to - * respond because it believes that it is already in DO ECHO - * mode, which we do not want. - */ - if (his_want_state_is_will(TELOPT_ECHO)) { - DIAG(TD_OPTIONS, - {sprintf(nfrontp, "td: simulating recv\r\n"); - nfrontp += strlen(nfrontp);}); - willoption(TELOPT_ECHO); - } - - /* - * Finally, to clean things up, we turn on our echo. This - * will break stupid 4.2 telnets out of local terminal echo. - */ - - if (my_state_is_wont(TELOPT_ECHO)) - send_will(TELOPT_ECHO, 1); - -#ifndef STREAMSPTY - /* - * Turn on packet mode - */ - (void) ioctl(p, TIOCPKT, (char *)&on); -#endif - -#if defined(LINEMODE) && defined(KLUDGELINEMODE) - /* - * Continuing line mode support. If client does not support - * real linemode, attempt to negotiate kludge linemode by sending - * the do timing mark sequence. - */ - if (lmodetype < REAL_LINEMODE) - send_do(TELOPT_TM, 1); -#endif /* defined(LINEMODE) && defined(KLUDGELINEMODE) */ - - /* - * Call telrcv() once to pick up anything received during - * terminal type negotiation, 4.2/4.3 determination, and - * linemode negotiation. - */ - telrcv(); - - (void) ioctl(f, FIONBIO, (char *)&on); - (void) ioctl(p, FIONBIO, (char *)&on); -#if defined(CRAY2) && defined(UNICOS5) - init_termdriver(f, p, interrupt, sendbrk); -#endif - -#if defined(SO_OOBINLINE) - (void) setsockopt(net, SOL_SOCKET, SO_OOBINLINE, - (char *)&on, sizeof on); -#endif /* defined(SO_OOBINLINE) */ - -#ifdef SIGTSTP - (void) signal(SIGTSTP, SIG_IGN); -#endif -#ifdef SIGTTOU - /* - * Ignoring SIGTTOU keeps the kernel from blocking us - * in ttioct() in /sys/tty.c. - */ - (void) signal(SIGTTOU, SIG_IGN); -#endif - - (void) signal(SIGCHLD, cleanup); - -#if defined(CRAY2) && defined(UNICOS5) - /* - * Cray-2 will send a signal when pty modes are changed by slave - * side. Set up signal handler now. - */ - if ((int)signal(SIGUSR1, termstat) < 0) - perror("signal"); - else if (ioctl(p, TCSIGME, (char *)SIGUSR1) < 0) - perror("ioctl:TCSIGME"); - /* - * Make processing loop check terminal characteristics early on. - */ - termstat(); -#endif - -#ifdef TIOCNOTTY - { - register int t; - t = open(_PATH_TTY, O_RDWR); - if (t >= 0) { - (void) ioctl(t, TIOCNOTTY, (char *)0); - (void) close(t); - } - } -#endif - -#if defined(CRAY) && defined(NEWINIT) && defined(TIOCSCTTY) - (void) setsid(); - ioctl(p, TIOCSCTTY, 0); -#endif - - /* - * Show banner that getty never gave. - * - * We put the banner in the pty input buffer. This way, it - * gets carriage return null processing, etc., just like all - * other pty --> client data. - */ - -#if !defined(CRAY) || !defined(NEWINIT) - if (getenv("USER")) - hostinfo = 0; -#endif - - if (getent(defent, "default") == 1) { - char *getstr(); - char *cp=defstrs; - - HE = getstr("he", &cp); - HN = getstr("hn", &cp); - IM = getstr("im", &cp); - if (HN && *HN) - (void) strcpy(host_name, HN); - if (IM == 0) - IM = ""; - } else { - IM = DEFAULT_IM; - HE = 0; - } - edithost(HE, host_name); - if (hostinfo && *IM) - putf(IM, ptyibuf2); - - if (pcc) - (void) strncat(ptyibuf2, ptyip, pcc+1); - ptyip = ptyibuf2; - pcc = strlen(ptyip); -#ifdef LINEMODE - /* - * Last check to make sure all our states are correct. - */ - init_termbuf(); - localstat(); -#endif /* LINEMODE */ - - DIAG(TD_REPORT, - {sprintf(nfrontp, "td: Entering processing loop\r\n"); - nfrontp += strlen(nfrontp);}); - - /* - * Startup the login process on the slave side of the terminal - * now. We delay this until here to insure option negotiation - * is complete. - */ - startslave(host, level, user_name); - - nfd = ((f > p) ? f : p) + 1; - for (;;) { - fd_set ibits, obits, xbits; - register int c; - - if (ncc < 0 && pcc < 0) - break; - -#if defined(CRAY2) && defined(UNICOS5) - if (needtermstat) - _termstat(); -#endif /* defined(CRAY2) && defined(UNICOS5) */ - FD_ZERO(&ibits); - FD_ZERO(&obits); - FD_ZERO(&xbits); - /* - * Never look for input if there's still - * stuff in the corresponding output buffer - */ - if (nfrontp - nbackp || pcc > 0) { - FD_SET(f, &obits); - } else { - FD_SET(p, &ibits); - } - if (pfrontp - pbackp || ncc > 0) { - FD_SET(p, &obits); - } else { - FD_SET(f, &ibits); - } - if (!SYNCHing) { - FD_SET(f, &xbits); - } - if ((c = select(nfd, &ibits, &obits, &xbits, - (struct timeval *)0)) < 1) { - if (c == -1) { - if (errno == EINTR) { - continue; - } - } - sleep(5); - continue; - } - - /* - * Any urgent data? - */ - if (FD_ISSET(net, &xbits)) { - SYNCHing = 1; - } - - /* - * Something to read from the network... - */ - if (FD_ISSET(net, &ibits)) { -#if !defined(SO_OOBINLINE) - /* - * In 4.2 (and 4.3 beta) systems, the - * OOB indication and data handling in the kernel - * is such that if two separate TCP Urgent requests - * come in, one byte of TCP data will be overlaid. - * This is fatal for Telnet, but we try to live - * with it. - * - * In addition, in 4.2 (and...), a special protocol - * is needed to pick up the TCP Urgent data in - * the correct sequence. - * - * What we do is: if we think we are in urgent - * mode, we look to see if we are "at the mark". - * If we are, we do an OOB receive. If we run - * this twice, we will do the OOB receive twice, - * but the second will fail, since the second - * time we were "at the mark", but there wasn't - * any data there (the kernel doesn't reset - * "at the mark" until we do a normal read). - * Once we've read the OOB data, we go ahead - * and do normal reads. - * - * There is also another problem, which is that - * since the OOB byte we read doesn't put us - * out of OOB state, and since that byte is most - * likely the TELNET DM (data mark), we would - * stay in the TELNET SYNCH (SYNCHing) state. - * So, clocks to the rescue. If we've "just" - * received a DM, then we test for the - * presence of OOB data when the receive OOB - * fails (and AFTER we did the normal mode read - * to clear "at the mark"). - */ - if (SYNCHing) { - int atmark; - - (void) ioctl(net, SIOCATMARK, (char *)&atmark); - if (atmark) { - ncc = recv(net, netibuf, sizeof (netibuf), MSG_OOB); - if ((ncc == -1) && (errno == EINVAL)) { - ncc = read(net, netibuf, sizeof (netibuf)); - if (sequenceIs(didnetreceive, gotDM)) { - SYNCHing = stilloob(net); - } - } - } else { - ncc = read(net, netibuf, sizeof (netibuf)); - } - } else { - ncc = read(net, netibuf, sizeof (netibuf)); - } - settimer(didnetreceive); -#else /* !defined(SO_OOBINLINE)) */ - ncc = read(net, netibuf, sizeof (netibuf)); -#endif /* !defined(SO_OOBINLINE)) */ - if (ncc < 0 && errno == EWOULDBLOCK) - ncc = 0; - else { - if (ncc <= 0) { - break; - } - netip = netibuf; - } - DIAG((TD_REPORT | TD_NETDATA), - {sprintf(nfrontp, "td: netread %d chars\r\n", ncc); - nfrontp += strlen(nfrontp);}); - DIAG(TD_NETDATA, printdata("nd", netip, ncc)); - } - - /* - * Something to read from the pty... - */ - if (FD_ISSET(p, &ibits)) { -#ifndef STREAMSPTY - pcc = read(p, ptyibuf, BUFSIZ); -#else - pcc = readstream(p, ptyibuf, BUFSIZ); -#endif - /* - * On some systems, if we try to read something - * off the master side before the slave side is - * opened, we get EIO. - */ - if (pcc < 0 && (errno == EWOULDBLOCK || -#ifdef EAGAIN - errno == EAGAIN || -#endif - errno == EIO)) { - pcc = 0; - } else { - if (pcc <= 0) - break; -#if !defined(CRAY2) || !defined(UNICOS5) -#ifdef LINEMODE - /* - * If ioctl from pty, pass it through net - */ - if (ptyibuf[0] & TIOCPKT_IOCTL) { - copy_termbuf(ptyibuf+1, pcc-1); - localstat(); - pcc = 1; - } -#endif /* LINEMODE */ - if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) { - netclear(); /* clear buffer back */ -#ifndef NO_URGENT - /* - * There are client telnets on some - * operating systems get screwed up - * royally if we send them urgent - * mode data. - */ - *nfrontp++ = IAC; - *nfrontp++ = DM; - neturg = nfrontp-1; /* off by one XXX */ - DIAG(TD_OPTIONS, - printoption("td: send IAC", DM)); - -#endif - } - if (his_state_is_will(TELOPT_LFLOW) && - (ptyibuf[0] & - (TIOCPKT_NOSTOP|TIOCPKT_DOSTOP))) { - int newflow = - ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0; - if (newflow != flowmode) { - flowmode = newflow; - (void) sprintf(nfrontp, - "%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - flowmode ? LFLOW_ON - : LFLOW_OFF, - IAC, SE); - nfrontp += 6; - DIAG(TD_OPTIONS, printsub('>', - (unsigned char *)nfrontp-4, - 4);); - } - } - pcc--; - ptyip = ptyibuf+1; -#else /* defined(CRAY2) && defined(UNICOS5) */ - if (!uselinemode) { - unpcc = pcc; - unptyip = ptyibuf; - pcc = term_output(&unptyip, ptyibuf2, - &unpcc, BUFSIZ); - ptyip = ptyibuf2; - } else - ptyip = ptyibuf; -#endif /* defined(CRAY2) && defined(UNICOS5) */ - } - } - - while (pcc > 0) { - if ((&netobuf[BUFSIZ] - nfrontp) < 2) - break; - c = *ptyip++ & 0377, pcc--; - if (c == IAC) - *nfrontp++ = c; -#if defined(CRAY2) && defined(UNICOS5) - else if (c == '\n' && - my_state_is_wont(TELOPT_BINARY) && newmap) - *nfrontp++ = '\r'; -#endif /* defined(CRAY2) && defined(UNICOS5) */ - *nfrontp++ = c; - if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) { - if (pcc > 0 && ((*ptyip & 0377) == '\n')) { - *nfrontp++ = *ptyip++ & 0377; - pcc--; - } else - *nfrontp++ = '\0'; - } - } -#if defined(CRAY2) && defined(UNICOS5) - /* - * If chars were left over from the terminal driver, - * note their existence. - */ - if (!uselinemode && unpcc) { - pcc = unpcc; - unpcc = 0; - ptyip = unptyip; - } -#endif /* defined(CRAY2) && defined(UNICOS5) */ - - if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0) - netflush(); - if (ncc > 0) - telrcv(); - if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0) - ptyflush(); - } - cleanup(0); -} /* end of telnet */ - -#ifndef TCSIG -# ifdef TIOCSIG -# define TCSIG TIOCSIG -# endif -#endif - -#ifdef STREAMSPTY - -int flowison = -1; /* current state of flow: -1 is unknown */ - -int readstream(p, ibuf, bufsize) - int p; - char *ibuf; - int bufsize; -{ - int flags = 0; - int ret = 0; - struct termios *tsp; - struct termio *tp; - struct iocblk *ip; - char vstop, vstart; - int ixon; - int newflow; - - strbufc.maxlen = BUFSIZ; - strbufc.buf = (char *)ctlbuf; - strbufd.maxlen = bufsize-1; - strbufd.len = 0; - strbufd.buf = ibuf+1; - ibuf[0] = 0; - - ret = getmsg(p, &strbufc, &strbufd, &flags); - if (ret < 0) /* error of some sort -- probably EAGAIN */ - return(-1); - - if (strbufc.len <= 0 || ctlbuf[0] == M_DATA) { - /* data message */ - if (strbufd.len > 0) { /* real data */ - return(strbufd.len + 1); /* count header char */ - } else { - /* nothing there */ - errno = EAGAIN; - return(-1); - } - } - - /* - * It's a control message. Return 1, to look at the flag we set - */ - - switch (ctlbuf[0]) { - case M_FLUSH: - if (ibuf[1] & FLUSHW) - ibuf[0] = TIOCPKT_FLUSHWRITE; - return(1); - - case M_IOCTL: - ip = (struct iocblk *) (ibuf+1); - - switch (ip->ioc_cmd) { - case TCSETS: - case TCSETSW: - case TCSETSF: - tsp = (struct termios *) - (ibuf+1 + sizeof(struct iocblk)); - vstop = tsp->c_cc[VSTOP]; - vstart = tsp->c_cc[VSTART]; - ixon = tsp->c_iflag & IXON; - break; - case TCSETA: - case TCSETAW: - case TCSETAF: - tp = (struct termio *) (ibuf+1 + sizeof(struct iocblk)); - vstop = tp->c_cc[VSTOP]; - vstart = tp->c_cc[VSTART]; - ixon = tp->c_iflag & IXON; - break; - default: - errno = EAGAIN; - return(-1); - } - - newflow = (ixon && (vstart == 021) && (vstop == 023)) ? 1 : 0; - if (newflow != flowison) { /* it's a change */ - flowison = newflow; - ibuf[0] = newflow ? TIOCPKT_DOSTOP : TIOCPKT_NOSTOP; - return(1); - } - } - - /* nothing worth doing anything about */ - errno = EAGAIN; - return(-1); -} -#endif /* STREAMSPTY */ - -/* - * Send interrupt to process on other side of pty. - * If it is in raw mode, just write NULL; - * otherwise, write intr char. - */ - void -interrupt() -{ - ptyflush(); /* half-hearted */ - -#if defined(STREAMSPTY) && defined(TIOCSIGNAL) - /* Streams PTY style ioctl to post a signal */ - { - int sig = SIGINT; - (void) ioctl(pty, TIOCSIGNAL, &sig); - (void) ioctl(pty, I_FLUSH, FLUSHR); - } -#else -#ifdef TCSIG - (void) ioctl(pty, TCSIG, (char *)SIGINT); -#else /* TCSIG */ - init_termbuf(); - *pfrontp++ = slctab[SLC_IP].sptr ? - (unsigned char)*slctab[SLC_IP].sptr : '\177'; -#endif /* TCSIG */ -#endif -} - -/* - * Send quit to process on other side of pty. - * If it is in raw mode, just write NULL; - * otherwise, write quit char. - */ - void -sendbrk() -{ - ptyflush(); /* half-hearted */ -#ifdef TCSIG - (void) ioctl(pty, TCSIG, (char *)SIGQUIT); -#else /* TCSIG */ - init_termbuf(); - *pfrontp++ = slctab[SLC_ABORT].sptr ? - (unsigned char)*slctab[SLC_ABORT].sptr : '\034'; -#endif /* TCSIG */ -} - - void -sendsusp() -{ -#ifdef SIGTSTP - ptyflush(); /* half-hearted */ -# ifdef TCSIG - (void) ioctl(pty, TCSIG, (char *)SIGTSTP); -# else /* TCSIG */ - *pfrontp++ = slctab[SLC_SUSP].sptr ? - (unsigned char)*slctab[SLC_SUSP].sptr : '\032'; -# endif /* TCSIG */ -#endif /* SIGTSTP */ -} - -/* - * When we get an AYT, if ^T is enabled, use that. Otherwise, - * just send back "[Yes]". - */ - void -recv_ayt() -{ -#if defined(SIGINFO) && defined(TCSIG) - if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) { - (void) ioctl(pty, TCSIG, (char *)SIGINFO); - return; - } -#endif - (void) strcpy(nfrontp, "\r\n[Yes]\r\n"); - nfrontp += 9; -} - - void -doeof() -{ - init_termbuf(); - -#if defined(LINEMODE) && defined(USE_TERMIO) && (VEOF == VMIN) - if (!tty_isediting()) { - extern char oldeofc; - *pfrontp++ = oldeofc; - return; - } -#endif - *pfrontp++ = slctab[SLC_EOF].sptr ? - (unsigned char)*slctab[SLC_EOF].sptr : '\004'; -} diff --git a/secure/libexec/telnetd/telnetd.h b/secure/libexec/telnetd/telnetd.h deleted file mode 100644 index 234b973..0000000 --- a/secure/libexec/telnetd/telnetd.h +++ /dev/null @@ -1,49 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - * - * @(#)telnetd.h 8.1 (Berkeley) 6/4/93 - */ - - -#include "defs.h" -#include "ext.h" - -#ifdef DIAGNOSTICS -#define DIAG(a,b) if (diagnostic & (a)) b -#else -#define DIAG(a,b) -#endif - -/* other external variables */ -extern char **environ; -extern int errno; - diff --git a/secure/libexec/telnetd/termstat.c b/secure/libexec/telnetd/termstat.c deleted file mode 100644 index f499137..0000000 --- a/secure/libexec/telnetd/termstat.c +++ /dev/null @@ -1,669 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95"; -#endif /* not lint */ - -#include "telnetd.h" - -/* - * local variables - */ -int def_tspeed = -1, def_rspeed = -1; -#ifdef TIOCSWINSZ -int def_row = 0, def_col = 0; -#endif -#ifdef LINEMODE -static int _terminit = 0; -#endif /* LINEMODE */ - -#if defined(CRAY2) && defined(UNICOS5) -int newmap = 1; /* nonzero if \n maps to ^M^J */ -#endif - -#ifdef LINEMODE -/* - * localstat - * - * This function handles all management of linemode. - * - * Linemode allows the client to do the local editing of data - * and send only complete lines to the server. Linemode state is - * based on the state of the pty driver. If the pty is set for - * external processing, then we can use linemode. Further, if we - * can use real linemode, then we can look at the edit control bits - * in the pty to determine what editing the client should do. - * - * Linemode support uses the following state flags to keep track of - * current and desired linemode state. - * alwayslinemode : true if -l was specified on the telnetd - * command line. It means to have linemode on as much as - * possible. - * - * lmodetype: signifies whether the client can - * handle real linemode, or if use of kludgeomatic linemode - * is preferred. It will be set to one of the following: - * REAL_LINEMODE : use linemode option - * NO_KLUDGE : don't initiate kludge linemode. - * KLUDGE_LINEMODE : use kludge linemode - * NO_LINEMODE : client is ignorant of linemode - * - * linemode, uselinemode : linemode is true if linemode - * is currently on, uselinemode is the state that we wish - * to be in. If another function wishes to turn linemode - * on or off, it sets or clears uselinemode. - * - * editmode, useeditmode : like linemode/uselinemode, but - * these contain the edit mode states (edit and trapsig). - * - * The state variables correspond to some of the state information - * in the pty. - * linemode: - * In real linemode, this corresponds to whether the pty - * expects external processing of incoming data. - * In kludge linemode, this more closely corresponds to the - * whether normal processing is on or not. (ICANON in - * system V, or COOKED mode in BSD.) - * If the -l option was specified (alwayslinemode), then - * an attempt is made to force external processing on at - * all times. - * - * The following heuristics are applied to determine linemode - * handling within the server. - * 1) Early on in starting up the server, an attempt is made - * to negotiate the linemode option. If this succeeds - * then lmodetype is set to REAL_LINEMODE and all linemode - * processing occurs in the context of the linemode option. - * 2) If the attempt to negotiate the linemode option failed, - * and the "-k" (don't initiate kludge linemode) isn't set, - * then we try to use kludge linemode. We test for this - * capability by sending "do Timing Mark". If a positive - * response comes back, then we assume that the client - * understands kludge linemode (ech!) and the - * lmodetype flag is set to KLUDGE_LINEMODE. - * 3) Otherwise, linemode is not supported at all and - * lmodetype remains set to NO_LINEMODE (which happens - * to be 0 for convenience). - * 4) At any time a command arrives that implies a higher - * state of linemode support in the client, we move to that - * linemode support. - * - * A short explanation of kludge linemode is in order here. - * 1) The heuristic to determine support for kludge linemode - * is to send a do timing mark. We assume that a client - * that supports timing marks also supports kludge linemode. - * A risky proposition at best. - * 2) Further negotiation of linemode is done by changing the - * the server's state regarding SGA. If server will SGA, - * then linemode is off, if server won't SGA, then linemode - * is on. - */ - void -localstat() -{ - void netflush(); - int need_will_echo = 0; - -#if defined(CRAY2) && defined(UNICOS5) - /* - * Keep track of that ol' CR/NL mapping while we're in the - * neighborhood. - */ - newmap = tty_isnewmap(); -#endif /* defined(CRAY2) && defined(UNICOS5) */ - - /* - * Check for changes to flow control if client supports it. - */ - flowstat(); - - /* - * Check linemode on/off state - */ - uselinemode = tty_linemode(); - - /* - * If alwayslinemode is on, and pty is changing to turn it off, then - * force linemode back on. - */ - if (alwayslinemode && linemode && !uselinemode) { - uselinemode = 1; - tty_setlinemode(uselinemode); - } - - if (uselinemode) { - /* - * Check for state of BINARY options. - * - * We only need to do the binary dance if we are actually going - * to use linemode. As this confuses some telnet clients - * that don't support linemode, and doesn't gain us - * anything, we don't do it unless we're doing linemode. - * -Crh (henrich@msu.edu) - */ - - if (tty_isbinaryin()) { - if (his_want_state_is_wont(TELOPT_BINARY)) - send_do(TELOPT_BINARY, 1); - } else { - if (his_want_state_is_will(TELOPT_BINARY)) - send_dont(TELOPT_BINARY, 1); - } - - if (tty_isbinaryout()) { - if (my_want_state_is_wont(TELOPT_BINARY)) - send_will(TELOPT_BINARY, 1); - } else { - if (my_want_state_is_will(TELOPT_BINARY)) - send_wont(TELOPT_BINARY, 1); - } - } - -#ifdef ENCRYPTION - /* - * If the terminal is not echoing, but editing is enabled, - * something like password input is going to happen, so - * if we the other side is not currently sending encrypted - * data, ask the other side to start encrypting. - */ - if (his_state_is_will(TELOPT_ENCRYPT)) { - static int enc_passwd = 0; - if (uselinemode && !tty_isecho() && tty_isediting() - && (enc_passwd == 0) && !decrypt_input) { - encrypt_send_request_start(); - enc_passwd = 1; - } else if (enc_passwd) { - encrypt_send_request_end(); - enc_passwd = 0; - } - } -#endif /* ENCRYPTION */ - - /* - * Do echo mode handling as soon as we know what the - * linemode is going to be. - * If the pty has echo turned off, then tell the client that - * the server will echo. If echo is on, then the server - * will echo if in character mode, but in linemode the - * client should do local echoing. The state machine will - * not send anything if it is unnecessary, so don't worry - * about that here. - * - * If we need to send the WILL ECHO (because echo is off), - * then delay that until after we have changed the MODE. - * This way, when the user is turning off both editing - * and echo, the client will get editing turned off first. - * This keeps the client from going into encryption mode - * and then right back out if it is doing auto-encryption - * when passwords are being typed. - */ - if (uselinemode) { - if (tty_isecho()) - send_wont(TELOPT_ECHO, 1); - else - need_will_echo = 1; -#ifdef KLUDGELINEMODE - if (lmodetype == KLUDGE_OK) - lmodetype = KLUDGE_LINEMODE; -#endif - } - - /* - * If linemode is being turned off, send appropriate - * command and then we're all done. - */ - if (!uselinemode && linemode) { -# ifdef KLUDGELINEMODE - if (lmodetype == REAL_LINEMODE) { -# endif /* KLUDGELINEMODE */ - send_dont(TELOPT_LINEMODE, 1); -# ifdef KLUDGELINEMODE - } else if (lmodetype == KLUDGE_LINEMODE) - send_will(TELOPT_SGA, 1); -# endif /* KLUDGELINEMODE */ - send_will(TELOPT_ECHO, 1); - linemode = uselinemode; - goto done; - } - -# ifdef KLUDGELINEMODE - /* - * If using real linemode check edit modes for possible later use. - * If we are in kludge linemode, do the SGA negotiation. - */ - if (lmodetype == REAL_LINEMODE) { -# endif /* KLUDGELINEMODE */ - useeditmode = 0; - if (tty_isediting()) - useeditmode |= MODE_EDIT; - if (tty_istrapsig()) - useeditmode |= MODE_TRAPSIG; - if (tty_issofttab()) - useeditmode |= MODE_SOFT_TAB; - if (tty_islitecho()) - useeditmode |= MODE_LIT_ECHO; -# ifdef KLUDGELINEMODE - } else if (lmodetype == KLUDGE_LINEMODE) { - if (tty_isediting() && uselinemode) - send_wont(TELOPT_SGA, 1); - else - send_will(TELOPT_SGA, 1); - } -# endif /* KLUDGELINEMODE */ - - /* - * Negotiate linemode on if pty state has changed to turn it on. - * Send appropriate command and send along edit mode, then all done. - */ - if (uselinemode && !linemode) { -# ifdef KLUDGELINEMODE - if (lmodetype == KLUDGE_LINEMODE) { - send_wont(TELOPT_SGA, 1); - } else if (lmodetype == REAL_LINEMODE) { -# endif /* KLUDGELINEMODE */ - send_do(TELOPT_LINEMODE, 1); - /* send along edit modes */ - (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB, - TELOPT_LINEMODE, LM_MODE, useeditmode, - IAC, SE); - nfrontp += 7; - editmode = useeditmode; -# ifdef KLUDGELINEMODE - } -# endif /* KLUDGELINEMODE */ - linemode = uselinemode; - goto done; - } - -# ifdef KLUDGELINEMODE - /* - * None of what follows is of any value if not using - * real linemode. - */ - if (lmodetype < REAL_LINEMODE) - goto done; -# endif /* KLUDGELINEMODE */ - - if (linemode && his_state_is_will(TELOPT_LINEMODE)) { - /* - * If edit mode changed, send edit mode. - */ - if (useeditmode != editmode) { - /* - * Send along appropriate edit mode mask. - */ - (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, SB, - TELOPT_LINEMODE, LM_MODE, useeditmode, - IAC, SE); - nfrontp += 7; - editmode = useeditmode; - } - - - /* - * Check for changes to special characters in use. - */ - start_slc(0); - check_slc(); - (void) end_slc(0); - } - -done: - if (need_will_echo) - send_will(TELOPT_ECHO, 1); - /* - * Some things should be deferred until after the pty state has - * been set by the local process. Do those things that have been - * deferred now. This only happens once. - */ - if (_terminit == 0) { - _terminit = 1; - defer_terminit(); - } - - netflush(); - set_termbuf(); - return; - -} /* end of localstat */ -#endif /* LINEMODE */ - -/* - * flowstat - * - * Check for changes to flow control - */ - void -flowstat() -{ - if (his_state_is_will(TELOPT_LFLOW)) { - if (tty_flowmode() != flowmode) { - flowmode = tty_flowmode(); - (void) sprintf(nfrontp, "%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - flowmode ? LFLOW_ON : LFLOW_OFF, - IAC, SE); - nfrontp += 6; - } - if (tty_restartany() != restartany) { - restartany = tty_restartany(); - (void) sprintf(nfrontp, "%c%c%c%c%c%c", - IAC, SB, TELOPT_LFLOW, - restartany ? LFLOW_RESTART_ANY - : LFLOW_RESTART_XON, - IAC, SE); - nfrontp += 6; - } - } -} - -/* - * clientstat - * - * Process linemode related requests from the client. - * Client can request a change to only one of linemode, editmode or slc's - * at a time, and if using kludge linemode, then only linemode may be - * affected. - */ - void -clientstat(code, parm1, parm2) - register int code, parm1, parm2; -{ - void netflush(); - - /* - * Get a copy of terminal characteristics. - */ - init_termbuf(); - - /* - * Process request from client. code tells what it is. - */ - switch (code) { -#ifdef LINEMODE - case TELOPT_LINEMODE: - /* - * Don't do anything unless client is asking us to change - * modes. - */ - uselinemode = (parm1 == WILL); - if (uselinemode != linemode) { -# ifdef KLUDGELINEMODE - /* - * If using kludge linemode, make sure that - * we can do what the client asks. - * We can not turn off linemode if alwayslinemode - * and the ICANON bit is set. - */ - if (lmodetype == KLUDGE_LINEMODE) { - if (alwayslinemode && tty_isediting()) { - uselinemode = 1; - } - } - - /* - * Quit now if we can't do it. - */ - if (uselinemode == linemode) - return; - - /* - * If using real linemode and linemode is being - * turned on, send along the edit mode mask. - */ - if (lmodetype == REAL_LINEMODE && uselinemode) -# else /* KLUDGELINEMODE */ - if (uselinemode) -# endif /* KLUDGELINEMODE */ - { - useeditmode = 0; - if (tty_isediting()) - useeditmode |= MODE_EDIT; - if (tty_istrapsig) - useeditmode |= MODE_TRAPSIG; - if (tty_issofttab()) - useeditmode |= MODE_SOFT_TAB; - if (tty_islitecho()) - useeditmode |= MODE_LIT_ECHO; - (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, - SB, TELOPT_LINEMODE, LM_MODE, - useeditmode, IAC, SE); - nfrontp += 7; - editmode = useeditmode; - } - - - tty_setlinemode(uselinemode); - - linemode = uselinemode; - - if (!linemode) - send_will(TELOPT_ECHO, 1); - } - break; - - case LM_MODE: - { - register int ack, changed; - - /* - * Client has sent along a mode mask. If it agrees with - * what we are currently doing, ignore it; if not, it could - * be viewed as a request to change. Note that the server - * will change to the modes in an ack if it is different from - * what we currently have, but we will not ack the ack. - */ - useeditmode &= MODE_MASK; - ack = (useeditmode & MODE_ACK); - useeditmode &= ~MODE_ACK; - - if (changed = (useeditmode ^ editmode)) { - /* - * This check is for a timing problem. If the - * state of the tty has changed (due to the user - * application) we need to process that info - * before we write in the state contained in the - * ack!!! This gets out the new MODE request, - * and when the ack to that command comes back - * we'll set it and be in the right mode. - */ - if (ack) - localstat(); - if (changed & MODE_EDIT) - tty_setedit(useeditmode & MODE_EDIT); - - if (changed & MODE_TRAPSIG) - tty_setsig(useeditmode & MODE_TRAPSIG); - - if (changed & MODE_SOFT_TAB) - tty_setsofttab(useeditmode & MODE_SOFT_TAB); - - if (changed & MODE_LIT_ECHO) - tty_setlitecho(useeditmode & MODE_LIT_ECHO); - - set_termbuf(); - - if (!ack) { - (void) sprintf(nfrontp, "%c%c%c%c%c%c%c", IAC, - SB, TELOPT_LINEMODE, LM_MODE, - useeditmode|MODE_ACK, - IAC, SE); - nfrontp += 7; - } - - editmode = useeditmode; - } - - break; - - } /* end of case LM_MODE */ -#endif /* LINEMODE */ - - case TELOPT_NAWS: -#ifdef TIOCSWINSZ - { - struct winsize ws; - - def_col = parm1; - def_row = parm2; -#ifdef LINEMODE - /* - * Defer changing window size until after terminal is - * initialized. - */ - if (terminit() == 0) - return; -#endif /* LINEMODE */ - - /* - * Change window size as requested by client. - */ - - ws.ws_col = parm1; - ws.ws_row = parm2; - (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); - } -#endif /* TIOCSWINSZ */ - - break; - - case TELOPT_TSPEED: - { - def_tspeed = parm1; - def_rspeed = parm2; -#ifdef LINEMODE - /* - * Defer changing the terminal speed. - */ - if (terminit() == 0) - return; -#endif /* LINEMODE */ - /* - * Change terminal speed as requested by client. - * We set the receive speed first, so that if we can't - * store seperate receive and transmit speeds, the transmit - * speed will take precedence. - */ - tty_rspeed(parm2); - tty_tspeed(parm1); - set_termbuf(); - - break; - - } /* end of case TELOPT_TSPEED */ - - default: - /* What? */ - break; - } /* end of switch */ - -#if defined(CRAY2) && defined(UNICOS5) - /* - * Just in case of the likely event that we changed the pty state. - */ - rcv_ioctl(); -#endif /* defined(CRAY2) && defined(UNICOS5) */ - - netflush(); - -} /* end of clientstat */ - -#if defined(CRAY2) && defined(UNICOS5) - void -termstat() -{ - needtermstat = 1; -} - - void -_termstat() -{ - needtermstat = 0; - init_termbuf(); - localstat(); - rcv_ioctl(); -} -#endif /* defined(CRAY2) && defined(UNICOS5) */ - -#ifdef LINEMODE -/* - * defer_terminit - * - * Some things should not be done until after the login process has started - * and all the pty modes are set to what they are supposed to be. This - * function is called when the pty state has been processed for the first time. - * It calls other functions that do things that were deferred in each module. - */ - void -defer_terminit() -{ - - /* - * local stuff that got deferred. - */ - if (def_tspeed != -1) { - clientstat(TELOPT_TSPEED, def_tspeed, def_rspeed); - def_tspeed = def_rspeed = 0; - } - -#ifdef TIOCSWINSZ - if (def_col || def_row) { - struct winsize ws; - - memset((char *)&ws, 0, sizeof(ws)); - ws.ws_col = def_col; - ws.ws_row = def_row; - (void) ioctl(pty, TIOCSWINSZ, (char *)&ws); - } -#endif - - /* - * The only other module that currently defers anything. - */ - deferslc(); - -} /* end of defer_terminit */ - -/* - * terminit - * - * Returns true if the pty state has been processed yet. - */ - int -terminit() -{ - return(_terminit); - -} /* end of terminit */ -#endif /* LINEMODE */ diff --git a/secure/libexec/telnetd/utility.c b/secure/libexec/telnetd/utility.c deleted file mode 100644 index e2f285a..0000000 --- a/secure/libexec/telnetd/utility.c +++ /dev/null @@ -1,1202 +0,0 @@ -/* - * Copyright (c) 1989, 1993 - * The Regents of the University of California. All rights reserved. - * - * Redistribution and use in source and binary forms, with or without - * modification, are permitted provided that the following conditions - * are met: - * 1. Redistributions of source code must retain the above copyright - * notice, this list of conditions and the following disclaimer. - * 2. Redistributions in binary form must reproduce the above copyright - * notice, this list of conditions and the following disclaimer in the - * documentation and/or other materials provided with the distribution. - * 3. All advertising materials mentioning features or use of this software - * must display the following acknowledgement: - * This product includes software developed by the University of - * California, Berkeley and its contributors. - * 4. Neither the name of the University nor the names of its contributors - * may be used to endorse or promote products derived from this software - * without specific prior written permission. - * - * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND - * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE - * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE - * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE - * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL - * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS - * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) - * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT - * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY - * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGE. - */ - -#ifndef lint -static char sccsid[] = "@(#)utility.c 8.4 (Berkeley) 5/30/95"; -#endif /* not lint */ - -#ifdef __FreeBSD__ -#include <locale.h> -#endif -#define PRINTOPTIONS -#include "telnetd.h" - -/* - * utility functions performing io related tasks - */ - -/* - * ttloop - * - * A small subroutine to flush the network output buffer, get some data - * from the network, and pass it through the telnet state machine. We - * also flush the pty input buffer (by dropping its data) if it becomes - * too full. - */ - - void -ttloop() -{ - void netflush(); - - DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop\r\n"); - nfrontp += strlen(nfrontp);}); - if (nfrontp-nbackp) { - netflush(); - } - ncc = read(net, netibuf, sizeof netibuf); - if (ncc < 0) { - syslog(LOG_INFO, "ttloop: read: %m\n"); - exit(1); - } else if (ncc == 0) { - syslog(LOG_INFO, "ttloop: peer died: %m\n"); - exit(1); - } - DIAG(TD_REPORT, {sprintf(nfrontp, "td: ttloop read %d chars\r\n", ncc); - nfrontp += strlen(nfrontp);}); - netip = netibuf; - telrcv(); /* state machine */ - if (ncc > 0) { - pfrontp = pbackp = ptyobuf; - telrcv(); - } -} /* end of ttloop */ - -/* - * Check a descriptor to see if out of band data exists on it. - */ - int -stilloob(s) - int s; /* socket number */ -{ - static struct timeval timeout = { 0 }; - fd_set excepts; - int value; - - do { - FD_ZERO(&excepts); - FD_SET(s, &excepts); - value = select(s+1, (fd_set *)0, (fd_set *)0, &excepts, &timeout); - } while ((value == -1) && (errno == EINTR)); - - if (value < 0) { - fatalperror(pty, "select"); - } - if (FD_ISSET(s, &excepts)) { - return 1; - } else { - return 0; - } -} - - void -ptyflush() -{ - int n; - - if ((n = pfrontp - pbackp) > 0) { - DIAG((TD_REPORT | TD_PTYDATA), - { sprintf(nfrontp, "td: ptyflush %d chars\r\n", n); - nfrontp += strlen(nfrontp); }); - DIAG(TD_PTYDATA, printdata("pd", pbackp, n)); - n = write(pty, pbackp, n); - } - if (n < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return; - cleanup(0); - } - pbackp += n; - if (pbackp == pfrontp) - pbackp = pfrontp = ptyobuf; -} - -/* - * nextitem() - * - * Return the address of the next "item" in the TELNET data - * stream. This will be the address of the next character if - * the current address is a user data character, or it will - * be the address of the character following the TELNET command - * if the current address is a TELNET IAC ("I Am a Command") - * character. - */ - char * -nextitem(current) - char *current; -{ - if ((*current&0xff) != IAC) { - return current+1; - } - switch (*(current+1)&0xff) { - case DO: - case DONT: - case WILL: - case WONT: - return current+3; - case SB: /* loop forever looking for the SE */ - { - register char *look = current+2; - - for (;;) { - if ((*look++&0xff) == IAC) { - if ((*look++&0xff) == SE) { - return look; - } - } - } - } - default: - return current+2; - } -} /* end of nextitem */ - - -/* - * netclear() - * - * We are about to do a TELNET SYNCH operation. Clear - * the path to the network. - * - * Things are a bit tricky since we may have sent the first - * byte or so of a previous TELNET command into the network. - * So, we have to scan the network buffer from the beginning - * until we are up to where we want to be. - * - * A side effect of what we do, just to keep things - * simple, is to clear the urgent data pointer. The principal - * caller should be setting the urgent data pointer AFTER calling - * us in any case. - */ - void -netclear() -{ - register char *thisitem, *next; - char *good; -#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \ - ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)) - -#ifdef ENCRYPTION - thisitem = nclearto > netobuf ? nclearto : netobuf; -#else /* ENCRYPTION */ - thisitem = netobuf; -#endif /* ENCRYPTION */ - - while ((next = nextitem(thisitem)) <= nbackp) { - thisitem = next; - } - - /* Now, thisitem is first before/at boundary. */ - -#ifdef ENCRYPTION - good = nclearto > netobuf ? nclearto : netobuf; -#else /* ENCRYPTION */ - good = netobuf; /* where the good bytes go */ -#endif /* ENCRYPTION */ - - while (nfrontp > thisitem) { - if (wewant(thisitem)) { - int length; - - next = thisitem; - do { - next = nextitem(next); - } while (wewant(next) && (nfrontp > next)); - length = next-thisitem; - memmove(good, thisitem, length); - good += length; - thisitem = next; - } else { - thisitem = nextitem(thisitem); - } - } - - nbackp = netobuf; - nfrontp = good; /* next byte to be sent */ - neturg = 0; -} /* end of netclear */ - -/* - * netflush - * Send as much data as possible to the network, - * handling requests for urgent data. - */ - void -netflush() -{ - int n; - extern int not42; - - if ((n = nfrontp - nbackp) > 0) { - DIAG(TD_REPORT, - { sprintf(nfrontp, "td: netflush %d chars\r\n", n); - n += strlen(nfrontp); /* get count first */ - nfrontp += strlen(nfrontp); /* then move pointer */ - }); -#ifdef ENCRYPTION - if (encrypt_output) { - char *s = nclearto ? nclearto : nbackp; - if (nfrontp - s > 0) { - (*encrypt_output)((unsigned char *)s, nfrontp-s); - nclearto = nfrontp; - } - } -#endif /* ENCRYPTION */ - /* - * if no urgent data, or if the other side appears to be an - * old 4.2 client (and thus unable to survive TCP urgent data), - * write the entire buffer in non-OOB mode. - */ - if ((neturg == 0) || (not42 == 0)) { - n = write(net, nbackp, n); /* normal write */ - } else { - n = neturg - nbackp; - /* - * In 4.2 (and 4.3) systems, there is some question about - * what byte in a sendOOB operation is the "OOB" data. - * To make ourselves compatible, we only send ONE byte - * out of band, the one WE THINK should be OOB (though - * we really have more the TCP philosophy of urgent data - * rather than the Unix philosophy of OOB data). - */ - if (n > 1) { - n = send(net, nbackp, n-1, 0); /* send URGENT all by itself */ - } else { - n = send(net, nbackp, n, MSG_OOB); /* URGENT data */ - } - } - } - if (n < 0) { - if (errno == EWOULDBLOCK || errno == EINTR) - return; - cleanup(0); - } - nbackp += n; -#ifdef ENCRYPTION - if (nbackp > nclearto) - nclearto = 0; -#endif /* ENCRYPTION */ - if (nbackp >= neturg) { - neturg = 0; - } - if (nbackp == nfrontp) { - nbackp = nfrontp = netobuf; -#ifdef ENCRYPTION - nclearto = 0; -#endif /* ENCRYPTION */ - } - return; -} /* end of netflush */ - - -/* - * writenet - * - * Just a handy little function to write a bit of raw data to the net. - * It will force a transmit of the buffer if necessary - * - * arguments - * ptr - A pointer to a character string to write - * len - How many bytes to write - */ - void -writenet(ptr, len) - register unsigned char *ptr; - register int len; -{ - /* flush buffer if no room for new data) */ - if ((&netobuf[BUFSIZ] - nfrontp) < len) { - /* if this fails, don't worry, buffer is a little big */ - netflush(); - } - - memmove(nfrontp, ptr, len); - nfrontp += len; - -} /* end of writenet */ - - -/* - * miscellaneous functions doing a variety of little jobs follow ... - */ - - - void -fatal(f, msg) - int f; - char *msg; -{ - char buf[BUFSIZ]; - - (void) sprintf(buf, "telnetd: %s.\r\n", msg); -#ifdef ENCRYPTION - if (encrypt_output) { - /* - * Better turn off encryption first.... - * Hope it flushes... - */ - encrypt_send_end(); - netflush(); - } -#endif /* ENCRYPTION */ - (void) write(f, buf, (int)strlen(buf)); - sleep(1); /*XXX*/ - exit(1); -} - - void -fatalperror(f, msg) - int f; - char *msg; -{ - char buf[BUFSIZ], *strerror(); - - (void) sprintf(buf, "%s: %s", msg, strerror(errno)); - fatal(f, buf); -} - -char editedhost[32]; - - void -edithost(pat, host) - register char *pat; - register char *host; -{ - register char *res = editedhost; - char *strncpy(); - - if (!pat) - pat = ""; - while (*pat) { - switch (*pat) { - - case '#': - if (*host) - host++; - break; - - case '@': - if (*host) - *res++ = *host++; - break; - - default: - *res++ = *pat; - break; - } - if (res == &editedhost[sizeof editedhost - 1]) { - *res = '\0'; - return; - } - pat++; - } - if (*host) - (void) strncpy(res, host, - sizeof editedhost - (res - editedhost) -1); - else - *res = '\0'; - editedhost[sizeof editedhost - 1] = '\0'; -} - -static char *putlocation; - - void -putstr(s) - register char *s; -{ - - while (*s) - putchr(*s++); -} - - void -putchr(cc) - int cc; -{ - *putlocation++ = cc; -} - -#ifdef __FreeBSD__ -static char fmtstr[] = { "%+" }; -#else -/* - * This is split on two lines so that SCCS will not see the M - * between two % signs and expand it... - */ -static char fmtstr[] = { "%l:%M\ -%P on %A, %d %B %Y" }; -#endif - - void -putf(cp, where) - register char *cp; - char *where; -{ - char *slash; - time_t t; - char db[100]; -#ifdef STREAMSPTY - extern char *strchr(); -#else - extern char *strrchr(); -#endif - - putlocation = where; - - while (*cp) { - if (*cp != '%') { - putchr(*cp++); - continue; - } - switch (*++cp) { - - case 't': -#ifdef STREAMSPTY - /* names are like /dev/pts/2 -- we want pts/2 */ - slash = strchr(line+1, '/'); -#else - slash = strrchr(line, '/'); -#endif - if (slash == (char *) 0) - putstr(line); - else - putstr(&slash[1]); - break; - - case 'h': - putstr(editedhost); - break; - - case 'd': -#ifdef __FreeBSD__ - setlocale(LC_TIME, ""); -#endif - (void)time(&t); - (void)strftime(db, sizeof(db), fmtstr, localtime(&t)); - putstr(db); - break; - - case '%': - putchr('%'); - break; - } - cp++; - } -} - -#ifdef DIAGNOSTICS -/* - * Print telnet options and commands in plain text, if possible. - */ - void -printoption(fmt, option) - register char *fmt; - register int option; -{ - if (TELOPT_OK(option)) - sprintf(nfrontp, "%s %s\r\n", fmt, TELOPT(option)); - else if (TELCMD_OK(option)) - sprintf(nfrontp, "%s %s\r\n", fmt, TELCMD(option)); - else - sprintf(nfrontp, "%s %d\r\n", fmt, option); - nfrontp += strlen(nfrontp); - return; -} - - void -printsub(direction, pointer, length) - char direction; /* '<' or '>' */ - unsigned char *pointer; /* where suboption data sits */ - int length; /* length of suboption data */ -{ - register int i; - char buf[512]; - - if (!(diagnostic & TD_OPTIONS)) - return; - - if (direction) { - sprintf(nfrontp, "td: %s suboption ", - direction == '<' ? "recv" : "send"); - nfrontp += strlen(nfrontp); - if (length >= 3) { - register int j; - - i = pointer[length-2]; - j = pointer[length-1]; - - if (i != IAC || j != SE) { - sprintf(nfrontp, "(terminated by "); - nfrontp += strlen(nfrontp); - if (TELOPT_OK(i)) - sprintf(nfrontp, "%s ", TELOPT(i)); - else if (TELCMD_OK(i)) - sprintf(nfrontp, "%s ", TELCMD(i)); - else - sprintf(nfrontp, "%d ", i); - nfrontp += strlen(nfrontp); - if (TELOPT_OK(j)) - sprintf(nfrontp, "%s", TELOPT(j)); - else if (TELCMD_OK(j)) - sprintf(nfrontp, "%s", TELCMD(j)); - else - sprintf(nfrontp, "%d", j); - nfrontp += strlen(nfrontp); - sprintf(nfrontp, ", not IAC SE!) "); - nfrontp += strlen(nfrontp); - } - } - length -= 2; - } - if (length < 1) { - sprintf(nfrontp, "(Empty suboption??\?)"); - nfrontp += strlen(nfrontp); - return; - } - switch (pointer[0]) { - case TELOPT_TTYPE: - sprintf(nfrontp, "TERMINAL-TYPE "); - nfrontp += strlen(nfrontp); - switch (pointer[1]) { - case TELQUAL_IS: - sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); - break; - case TELQUAL_SEND: - sprintf(nfrontp, "SEND"); - break; - default: - sprintf(nfrontp, - "- unknown qualifier %d (0x%x).", - pointer[1], pointer[1]); - } - nfrontp += strlen(nfrontp); - break; - case TELOPT_TSPEED: - sprintf(nfrontp, "TERMINAL-SPEED"); - nfrontp += strlen(nfrontp); - if (length < 2) { - sprintf(nfrontp, " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case TELQUAL_IS: - sprintf(nfrontp, " IS %.*s", length-2, (char *)pointer+2); - nfrontp += strlen(nfrontp); - break; - default: - if (pointer[1] == 1) - sprintf(nfrontp, " SEND"); - else - sprintf(nfrontp, " %d (unknown)", pointer[1]); - nfrontp += strlen(nfrontp); - for (i = 2; i < length; i++) { - sprintf(nfrontp, " ?%d?", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - } - break; - - case TELOPT_LFLOW: - sprintf(nfrontp, "TOGGLE-FLOW-CONTROL"); - nfrontp += strlen(nfrontp); - if (length < 2) { - sprintf(nfrontp, " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case LFLOW_OFF: - sprintf(nfrontp, " OFF"); break; - case LFLOW_ON: - sprintf(nfrontp, " ON"); break; - case LFLOW_RESTART_ANY: - sprintf(nfrontp, " RESTART-ANY"); break; - case LFLOW_RESTART_XON: - sprintf(nfrontp, " RESTART-XON"); break; - default: - sprintf(nfrontp, " %d (unknown)", pointer[1]); - } - nfrontp += strlen(nfrontp); - for (i = 2; i < length; i++) { - sprintf(nfrontp, " ?%d?", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - - case TELOPT_NAWS: - sprintf(nfrontp, "NAWS"); - nfrontp += strlen(nfrontp); - if (length < 2) { - sprintf(nfrontp, " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - if (length == 2) { - sprintf(nfrontp, " ?%d?", pointer[1]); - nfrontp += strlen(nfrontp); - break; - } - sprintf(nfrontp, " %d %d (%d)", - pointer[1], pointer[2], - (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2]))); - nfrontp += strlen(nfrontp); - if (length == 4) { - sprintf(nfrontp, " ?%d?", pointer[3]); - nfrontp += strlen(nfrontp); - break; - } - sprintf(nfrontp, " %d %d (%d)", - pointer[3], pointer[4], - (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4]))); - nfrontp += strlen(nfrontp); - for (i = 5; i < length; i++) { - sprintf(nfrontp, " ?%d?", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - - case TELOPT_LINEMODE: - sprintf(nfrontp, "LINEMODE "); - nfrontp += strlen(nfrontp); - if (length < 2) { - sprintf(nfrontp, " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case WILL: - sprintf(nfrontp, "WILL "); - goto common; - case WONT: - sprintf(nfrontp, "WONT "); - goto common; - case DO: - sprintf(nfrontp, "DO "); - goto common; - case DONT: - sprintf(nfrontp, "DONT "); - common: - nfrontp += strlen(nfrontp); - if (length < 3) { - sprintf(nfrontp, "(no option??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[2]) { - case LM_FORWARDMASK: - sprintf(nfrontp, "Forward Mask"); - nfrontp += strlen(nfrontp); - for (i = 3; i < length; i++) { - sprintf(nfrontp, " %x", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - default: - sprintf(nfrontp, "%d (unknown)", pointer[2]); - nfrontp += strlen(nfrontp); - for (i = 3; i < length; i++) { - sprintf(nfrontp, " %d", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - } - break; - - case LM_SLC: - sprintf(nfrontp, "SLC"); - nfrontp += strlen(nfrontp); - for (i = 2; i < length - 2; i += 3) { - if (SLC_NAME_OK(pointer[i+SLC_FUNC])) - sprintf(nfrontp, " %s", SLC_NAME(pointer[i+SLC_FUNC])); - else - sprintf(nfrontp, " %d", pointer[i+SLC_FUNC]); - nfrontp += strlen(nfrontp); - switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) { - case SLC_NOSUPPORT: - sprintf(nfrontp, " NOSUPPORT"); break; - case SLC_CANTCHANGE: - sprintf(nfrontp, " CANTCHANGE"); break; - case SLC_VARIABLE: - sprintf(nfrontp, " VARIABLE"); break; - case SLC_DEFAULT: - sprintf(nfrontp, " DEFAULT"); break; - } - nfrontp += strlen(nfrontp); - sprintf(nfrontp, "%s%s%s", - pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "", - pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "", - pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : ""); - nfrontp += strlen(nfrontp); - if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN| - SLC_FLUSHOUT| SLC_LEVELBITS)) { - sprintf(nfrontp, "(0x%x)", pointer[i+SLC_FLAGS]); - nfrontp += strlen(nfrontp); - } - sprintf(nfrontp, " %d;", pointer[i+SLC_VALUE]); - nfrontp += strlen(nfrontp); - if ((pointer[i+SLC_VALUE] == IAC) && - (pointer[i+SLC_VALUE+1] == IAC)) - i++; - } - for (; i < length; i++) { - sprintf(nfrontp, " ?%d?", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - - case LM_MODE: - sprintf(nfrontp, "MODE "); - nfrontp += strlen(nfrontp); - if (length < 3) { - sprintf(nfrontp, "(no mode??\?)"); - nfrontp += strlen(nfrontp); - break; - } - { - char tbuf[32]; - sprintf(tbuf, "%s%s%s%s%s", - pointer[2]&MODE_EDIT ? "|EDIT" : "", - pointer[2]&MODE_TRAPSIG ? "|TRAPSIG" : "", - pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "", - pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "", - pointer[2]&MODE_ACK ? "|ACK" : ""); - sprintf(nfrontp, "%s", tbuf[1] ? &tbuf[1] : "0"); - nfrontp += strlen(nfrontp); - } - if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) { - sprintf(nfrontp, " (0x%x)", pointer[2]); - nfrontp += strlen(nfrontp); - } - for (i = 3; i < length; i++) { - sprintf(nfrontp, " ?0x%x?", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - default: - sprintf(nfrontp, "%d (unknown)", pointer[1]); - nfrontp += strlen(nfrontp); - for (i = 2; i < length; i++) { - sprintf(nfrontp, " %d", pointer[i]); - nfrontp += strlen(nfrontp); - } - } - break; - - case TELOPT_STATUS: { - register char *cp; - register int j, k; - - sprintf(nfrontp, "STATUS"); - nfrontp += strlen(nfrontp); - - switch (pointer[1]) { - default: - if (pointer[1] == TELQUAL_SEND) - sprintf(nfrontp, " SEND"); - else - sprintf(nfrontp, " %d (unknown)", pointer[1]); - nfrontp += strlen(nfrontp); - for (i = 2; i < length; i++) { - sprintf(nfrontp, " ?%d?", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - case TELQUAL_IS: - sprintf(nfrontp, " IS\r\n"); - nfrontp += strlen(nfrontp); - - for (i = 2; i < length; i++) { - switch(pointer[i]) { - case DO: cp = "DO"; goto common2; - case DONT: cp = "DONT"; goto common2; - case WILL: cp = "WILL"; goto common2; - case WONT: cp = "WONT"; goto common2; - common2: - i++; - if (TELOPT_OK(pointer[i])) - sprintf(nfrontp, " %s %s", cp, TELOPT(pointer[i])); - else - sprintf(nfrontp, " %s %d", cp, pointer[i]); - nfrontp += strlen(nfrontp); - - sprintf(nfrontp, "\r\n"); - nfrontp += strlen(nfrontp); - break; - - case SB: - sprintf(nfrontp, " SB "); - nfrontp += strlen(nfrontp); - i++; - j = k = i; - while (j < length) { - if (pointer[j] == SE) { - if (j+1 == length) - break; - if (pointer[j+1] == SE) - j++; - else - break; - } - pointer[k++] = pointer[j++]; - } - printsub(0, &pointer[i], k - i); - if (i < length) { - sprintf(nfrontp, " SE"); - nfrontp += strlen(nfrontp); - i = j; - } else - i = j - 1; - - sprintf(nfrontp, "\r\n"); - nfrontp += strlen(nfrontp); - - break; - - default: - sprintf(nfrontp, " %d", pointer[i]); - nfrontp += strlen(nfrontp); - break; - } - } - break; - } - break; - } - - case TELOPT_XDISPLOC: - sprintf(nfrontp, "X-DISPLAY-LOCATION "); - nfrontp += strlen(nfrontp); - switch (pointer[1]) { - case TELQUAL_IS: - sprintf(nfrontp, "IS \"%.*s\"", length-2, (char *)pointer+2); - break; - case TELQUAL_SEND: - sprintf(nfrontp, "SEND"); - break; - default: - sprintf(nfrontp, "- unknown qualifier %d (0x%x).", - pointer[1], pointer[1]); - } - nfrontp += strlen(nfrontp); - break; - - case TELOPT_NEW_ENVIRON: - sprintf(nfrontp, "NEW-ENVIRON "); - goto env_common1; - case TELOPT_OLD_ENVIRON: - sprintf(nfrontp, "OLD-ENVIRON"); - env_common1: - nfrontp += strlen(nfrontp); - switch (pointer[1]) { - case TELQUAL_IS: - sprintf(nfrontp, "IS "); - goto env_common; - case TELQUAL_SEND: - sprintf(nfrontp, "SEND "); - goto env_common; - case TELQUAL_INFO: - sprintf(nfrontp, "INFO "); - env_common: - nfrontp += strlen(nfrontp); - { - register int noquote = 2; - for (i = 2; i < length; i++ ) { - switch (pointer[i]) { - case NEW_ENV_VAR: - sprintf(nfrontp, "\" VAR " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - case NEW_ENV_VALUE: - sprintf(nfrontp, "\" VALUE " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - case ENV_ESC: - sprintf(nfrontp, "\" ESC " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - case ENV_USERVAR: - sprintf(nfrontp, "\" USERVAR " + noquote); - nfrontp += strlen(nfrontp); - noquote = 2; - break; - - default: - def_case: - if (isprint(pointer[i]) && pointer[i] != '"') { - if (noquote) { - *nfrontp++ = '"'; - noquote = 0; - } - *nfrontp++ = pointer[i]; - } else { - sprintf(nfrontp, "\" %03o " + noquote, - pointer[i]); - nfrontp += strlen(nfrontp); - noquote = 2; - } - break; - } - } - if (!noquote) - *nfrontp++ = '"'; - break; - } - } - break; - -#if defined(AUTHENTICATION) - case TELOPT_AUTHENTICATION: - sprintf(nfrontp, "AUTHENTICATION"); - nfrontp += strlen(nfrontp); - - if (length < 2) { - sprintf(nfrontp, " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case TELQUAL_REPLY: - case TELQUAL_IS: - sprintf(nfrontp, " %s ", (pointer[1] == TELQUAL_IS) ? - "IS" : "REPLY"); - nfrontp += strlen(nfrontp); - if (AUTHTYPE_NAME_OK(pointer[2])) - sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[2])); - else - sprintf(nfrontp, "%d ", pointer[2]); - nfrontp += strlen(nfrontp); - if (length < 3) { - sprintf(nfrontp, "(partial suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - sprintf(nfrontp, "%s|%s", - ((pointer[3] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[3] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - nfrontp += strlen(nfrontp); - - auth_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - sprintf(nfrontp, "%s", buf); - nfrontp += strlen(nfrontp); - break; - - case TELQUAL_SEND: - i = 2; - sprintf(nfrontp, " SEND "); - nfrontp += strlen(nfrontp); - while (i < length) { - if (AUTHTYPE_NAME_OK(pointer[i])) - sprintf(nfrontp, "%s ", AUTHTYPE_NAME(pointer[i])); - else - sprintf(nfrontp, "%d ", pointer[i]); - nfrontp += strlen(nfrontp); - if (++i >= length) { - sprintf(nfrontp, "(partial suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - sprintf(nfrontp, "%s|%s ", - ((pointer[i] & AUTH_WHO_MASK) == AUTH_WHO_CLIENT) ? - "CLIENT" : "SERVER", - ((pointer[i] & AUTH_HOW_MASK) == AUTH_HOW_MUTUAL) ? - "MUTUAL" : "ONE-WAY"); - nfrontp += strlen(nfrontp); - ++i; - } - break; - - case TELQUAL_NAME: - i = 2; - sprintf(nfrontp, " NAME \""); - nfrontp += strlen(nfrontp); - while (i < length) - *nfrontp += pointer[i++]; - *nfrontp += '"'; - break; - - default: - for (i = 2; i < length; i++) { - sprintf(nfrontp, " ?%d?", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - } - break; -#endif - -#ifdef ENCRYPTION - case TELOPT_ENCRYPT: - sprintf(nfrontp, "ENCRYPT"); - nfrontp += strlen(nfrontp); - if (length < 2) { - sprintf(nfrontp, " (empty suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - switch (pointer[1]) { - case ENCRYPT_START: - sprintf(nfrontp, " START"); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_END: - sprintf(nfrontp, " END"); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_REQSTART: - sprintf(nfrontp, " REQUEST-START"); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_REQEND: - sprintf(nfrontp, " REQUEST-END"); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_IS: - case ENCRYPT_REPLY: - sprintf(nfrontp, " %s ", (pointer[1] == ENCRYPT_IS) ? - "IS" : "REPLY"); - nfrontp += strlen(nfrontp); - if (length < 3) { - sprintf(nfrontp, " (partial suboption??\?)"); - nfrontp += strlen(nfrontp); - break; - } - if (ENCTYPE_NAME_OK(pointer[2])) - sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[2])); - else - sprintf(nfrontp, " %d (unknown)", pointer[2]); - nfrontp += strlen(nfrontp); - - encrypt_printsub(&pointer[1], length - 1, buf, sizeof(buf)); - sprintf(nfrontp, "%s", buf); - nfrontp += strlen(nfrontp); - break; - - case ENCRYPT_SUPPORT: - i = 2; - sprintf(nfrontp, " SUPPORT "); - nfrontp += strlen(nfrontp); - while (i < length) { - if (ENCTYPE_NAME_OK(pointer[i])) - sprintf(nfrontp, "%s ", ENCTYPE_NAME(pointer[i])); - else - sprintf(nfrontp, "%d ", pointer[i]); - nfrontp += strlen(nfrontp); - i++; - } - break; - - case ENCRYPT_ENC_KEYID: - sprintf(nfrontp, " ENC_KEYID", pointer[1]); - nfrontp += strlen(nfrontp); - goto encommon; - - case ENCRYPT_DEC_KEYID: - sprintf(nfrontp, " DEC_KEYID", pointer[1]); - nfrontp += strlen(nfrontp); - goto encommon; - - default: - sprintf(nfrontp, " %d (unknown)", pointer[1]); - nfrontp += strlen(nfrontp); - encommon: - for (i = 2; i < length; i++) { - sprintf(nfrontp, " %d", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - } - break; -#endif /* ENCRYPTION */ - - default: - if (TELOPT_OK(pointer[0])) - sprintf(nfrontp, "%s (unknown)", TELOPT(pointer[0])); - else - sprintf(nfrontp, "%d (unknown)", pointer[i]); - nfrontp += strlen(nfrontp); - for (i = 1; i < length; i++) { - sprintf(nfrontp, " %d", pointer[i]); - nfrontp += strlen(nfrontp); - } - break; - } - sprintf(nfrontp, "\r\n"); - nfrontp += strlen(nfrontp); -} - -/* - * Dump a data buffer in hex and ascii to the output data stream. - */ - void -printdata(tag, ptr, cnt) - register char *tag; - register char *ptr; - register int cnt; -{ - register int i; - char xbuf[30]; - - while (cnt) { - /* flush net output buffer if no room for new data) */ - if ((&netobuf[BUFSIZ] - nfrontp) < 80) { - netflush(); - } - - /* add a line of output */ - sprintf(nfrontp, "%s: ", tag); - nfrontp += strlen(nfrontp); - for (i = 0; i < 20 && cnt; i++) { - sprintf(nfrontp, "%02x", *ptr); - nfrontp += strlen(nfrontp); - if (isprint(*ptr)) { - xbuf[i] = *ptr; - } else { - xbuf[i] = '.'; - } - if (i % 2) { - *nfrontp = ' '; - nfrontp++; - } - cnt--; - ptr++; - } - xbuf[i] = '\0'; - sprintf(nfrontp, " %s\r\n", xbuf ); - nfrontp += strlen(nfrontp); - } -} -#endif /* DIAGNOSTICS */ |