summaryrefslogtreecommitdiffstats
path: root/libexec/telnetd
diff options
context:
space:
mode:
authormarkm <markm@FreeBSD.org>2003-07-16 20:59:15 +0000
committermarkm <markm@FreeBSD.org>2003-07-16 20:59:15 +0000
commitd6aec2b6d60b4b7b11a4a51d8a87a963e942803c (patch)
treed0941cea5c5d555255e1721af0d195e7b1148f6a /libexec/telnetd
parent23022fa9406006dadd2eafdf36b94c737d737135 (diff)
downloadFreeBSD-src-d6aec2b6d60b4b7b11a4a51d8a87a963e942803c.zip
FreeBSD-src-d6aec2b6d60b4b7b11a4a51d8a87a963e942803c.tar.gz
Very big makeover in the way telnet, telnetd and libtelnet are built.
Previously, there were two copies of telnet; a non-crypto version that lived in the usual places, and a crypto version that lived in crypto/telnet/. The latter was built in a broken manner somewhat akin to other "contribified" sources. This meant that there were 4 telnets competing with each other at build time - KerberosIV, Kerberos5, plain-old-secure and base. KerberosIV is no longer in the running, but the other three took it in turns to jump all over each other during a "make buildworld". As the crypto issue has been clarified, and crypto _calls_ are not a problem, crypto/telnet has been repo-copied to contrib/telnet, and with this commit, all telnets are now "contribified". The contrib path was chosen to not destroy history in the repository, and differs from other contrib/ entries in that it may be worked on as "normal" BSD code. There is no dangerous crypto in these sources, only a very weak system less strong than enigma(1). Kerberos5 telnet and Secure telnet are now selected by using the usual macros in /etc/make.conf, and the build process is unsurprising and less treacherous.
Diffstat (limited to 'libexec/telnetd')
-rw-r--r--libexec/telnetd/Makefile24
-rw-r--r--libexec/telnetd/defs.h258
-rw-r--r--libexec/telnetd/ext.h206
-rw-r--r--libexec/telnetd/global.c52
-rw-r--r--libexec/telnetd/pathnames.h56
-rw-r--r--libexec/telnetd/slc.c484
-rw-r--r--libexec/telnetd/state.c1512
-rw-r--r--libexec/telnetd/sys_term.c1192
-rw-r--r--libexec/telnetd/telnetd.8593
-rw-r--r--libexec/telnetd/telnetd.c1117
-rw-r--r--libexec/telnetd/telnetd.h49
-rw-r--r--libexec/telnetd/termstat.c610
-rw-r--r--libexec/telnetd/utility.c900
13 files changed, 15 insertions, 7038 deletions
diff --git a/libexec/telnetd/Makefile b/libexec/telnetd/Makefile
index 031000d..96d11fe 100644
--- a/libexec/telnetd/Makefile
+++ b/libexec/telnetd/Makefile
@@ -3,6 +3,9 @@
# Do not define -DKLUDGELINEMODE, as it does not interact well with many
# telnet implementations.
+TELNETDIR= ${.CURDIR}/../../contrib/telnet
+.PATH: ${TELNETDIR}/telnetd
+
PROG= telnetd
MAN= telnetd.8
@@ -11,7 +14,7 @@ SRCS= global.c slc.c state.c sys_term.c telnetd.c \
CFLAGS+= -DLINEMODE -DUSE_TERMIO -DDIAGNOSTICS -DOLD_ENVIRON \
-DENV_HACK \
- -I${.CURDIR}/../../lib -DINET6
+ -I${TELNETDIR} -DINET6
WARNS?= 2
WFORMAT?= 0
@@ -25,13 +28,16 @@ LIBTELNET= ${.CURDIR}/../../lib/libtelnet/libtelnet.a
DPADD= ${LIBUTIL} ${LIBTERMCAP} ${LIBTELNET}
LDADD= -lutil -ltermcap ${LIBTELNET}
-unifdef:
- -cd ${.CURDIR} ; \
- ( for i in *.[ch] ; do \
- unifdef -UAUTHENTICATION -UENCRYPTION \
- ${.CURDIR}/../../crypto/telnet/telnetd/$$i \
- > ${.CURDIR}/$$i ; \
- echo $$i ; \
- done )
+.if !defined(NO_CRYPTO)
+SRCS+= authenc.c
+CFLAGS+= -DAUTHENTICATION -DENCRYPTION
+DPADD+= ${LIBMP} ${LIBCRYPTO} ${LIBCRYPT} ${LIBPAM}
+LDADD+= -lmp -lcrypto -lcrypt ${MINUSLPAM}
+.if !defined(NO_KERBEROS)
+CFLAGS+= -DKRB5 -DFORWARD -Dnet_write=telnet_net_write
+DPADD+= ${LIBKRB5} ${LIBASN1} ${LIBROKEN} ${LIBCOM_ERR}
+LDADD+= -lkrb5 -lasn1 -lroken -lcom_err
+.endif
+.endif
.include <bsd.prog.mk>
diff --git a/libexec/telnetd/defs.h b/libexec/telnetd/defs.h
deleted file mode 100644
index d727f36..0000000
--- a/libexec/telnetd/defs.h
+++ /dev/null
@@ -1,258 +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
- * $FreeBSD$
- */
-
-/*
- * Telnet server defines
- */
-#include <sys/types.h>
-#include <sys/param.h>
-
-#ifndef BSD
-# define BSD 43
-#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>
-#include <sys/wait.h>
-#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
-
-#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
-
-#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/libexec/telnetd/ext.h b/libexec/telnetd/ext.h
deleted file mode 100644
index 04aa4a3..0000000
--- a/libexec/telnetd/ext.h
+++ /dev/null
@@ -1,206 +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
- * $FreeBSD$
- */
-
-/*
- * 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 */
-
-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], *nfrontp, *nbackp;
-extern char *neturg; /* one past last bye of urgent data */
-
-extern int pcc, ncc;
-
-extern int pty, net;
-extern char line[16];
-extern int SYNCHing; /* we are in TELNET SYNCH mode */
-
-extern void
- _termstat(void),
- add_slc(char, char, cc_t),
- check_slc(void),
- change_slc(char, char, cc_t),
- cleanup(int),
- clientstat(int, int, int),
- copy_termbuf(char *, size_t),
- deferslc(void),
- defer_terminit(void),
- do_opt_slc(unsigned char *, int),
- doeof(void),
- dooption(int),
- dontoption(int),
- edithost(char *, char *),
- fatal(int, const char *),
- fatalperror(int, const char *),
- get_slc_defaults(void),
- init_env(void),
- init_termbuf(void),
- interrupt(void),
- localstat(void),
- flowstat(void),
- netclear(void),
- netflush(void),
-#ifdef DIAGNOSTICS
- printoption(const char *, int),
- printdata(const char *, char *, int),
- printsub(char, unsigned char *, int),
-#endif
- process_slc(unsigned char, unsigned char, cc_t),
- ptyflush(void),
- putchr(int),
- putf(char *, char *),
- recv_ayt(void),
- send_do(int, int),
- send_dont(int, int),
- send_slc(void),
- send_status(void),
- send_will(int, int),
- send_wont(int, int),
- sendbrk(void),
- sendsusp(void),
- set_termbuf(void),
- start_login(char *, int, char *),
- start_slc(int),
- start_slave(char *, int, char *),
- suboption(void),
- telrcv(void),
- ttloop(void),
- tty_binaryin(int),
- tty_binaryout(int);
-
-extern int
- end_slc(unsigned char **),
- getnpty(void),
-#ifndef convex
- getpty(int *),
-#endif
- login_tty(int),
- spcset(int, cc_t *, cc_t **),
- stilloob(int),
- terminit(void),
- termstat(void),
- tty_flowmode(void),
- tty_restartany(void),
- tty_isbinaryin(void),
- tty_isbinaryout(void),
- tty_iscrnl(void),
- tty_isecho(void),
- tty_isediting(void),
- tty_islitecho(void),
- tty_isnewmap(void),
- tty_israw(void),
- tty_issofttab(void),
- tty_istrapsig(void),
- tty_linemode(void);
-
-extern void
- tty_rspeed(int),
- tty_setecho(int),
- tty_setedit(int),
- tty_setlinemode(int),
- tty_setlitecho(int),
- tty_setsig(int),
- tty_setsofttab(int),
- tty_tspeed(int),
- willoption(int),
- wontoption(int);
-
-int output_data(const char *, ...) __printflike(1, 2);
-void output_datalen(const char *, int);
-void startslave(char *, int, char *);
-
-
-
-/*
- * 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;
-
-#ifndef DEFAULT_IM
-# 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
diff --git a/libexec/telnetd/global.c b/libexec/telnetd/global.c
deleted file mode 100644
index 2ed82d0..0000000
--- a/libexec/telnetd/global.c
+++ /dev/null
@@ -1,52 +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.
- */
-
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)global.c 8.1 (Berkeley) 6/4/93";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-/*
- * 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/libexec/telnetd/pathnames.h b/libexec/telnetd/pathnames.h
deleted file mode 100644
index ed8ee88..0000000
--- a/libexec/telnetd/pathnames.h
+++ /dev/null
@@ -1,56 +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
- * $FreeBSD$
- */
-
-#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/libexec/telnetd/slc.c b/libexec/telnetd/slc.c
deleted file mode 100644
index ad03441..0000000
--- a/libexec/telnetd/slc.c
+++ /dev/null
@@ -1,484 +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.
- */
-
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)slc.c 8.2 (Berkeley) 5/30/95";
-#endif
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "telnetd.h"
-
-#ifdef LINEMODE
-/*
- * local variables
- */
-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(void)
-{
- 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.
- */
-static void
-default_slc(void)
-{
- 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(void)
-{
- 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(char func, char flag, 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(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(unsigned char **bufp)
-{
- int len;
-
- /*
- * 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;
- output_datalen(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(unsigned char func, unsigned char flag, cc_t val)
-{
- 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(char func, char flag, cc_t val)
-{
- int hislevel, mylevel;
-
- hislevel = flag & SLC_LEVELBITS;
- mylevel = slctab[(int)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[(int)func].current.flag = flag;
- slctab[(int)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[(int)func].current.flag = SLC_NOSUPPORT;
- } else {
- slctab[(int)func].current.flag = slctab[(int)func].defset.flag;
- }
- slctab[(int)func].current.val = slctab[(int)func].defset.val;
- add_slc(func, slctab[(int)func].current.flag,
- slctab[(int)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[(int)func].sptr) {
- /*
- * We can change this one.
- */
- slctab[(int)func].current.val = val;
- *(slctab[(int)func].sptr) = val;
- slctab[(int)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[(int)func].current.flag = flag;
- slctab[(int)func].current.val = val;
- flag |= SLC_ACK;
- } else if (hislevel == SLC_CANTCHANGE &&
- mylevel == SLC_CANTCHANGE) {
- flag &= ~SLC_LEVELBITS;
- flag |= SLC_NOSUPPORT;
- slctab[(int)func].current.flag = flag;
- } else {
- flag &= ~SLC_LEVELBITS;
- flag |= mylevel;
- slctab[(int)func].current.flag = flag;
- if (mylevel == SLC_CANTCHANGE) {
- slctab[(int)func].current.val =
- slctab[(int)func].defset.val;
- val = slctab[(int)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(void)
-{
- 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(unsigned char *ptr, int len)
-{
- unsigned char func, flag;
- cc_t val;
- 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(void)
-{
- 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/libexec/telnetd/state.c b/libexec/telnetd/state.c
deleted file mode 100644
index 7b733e4..0000000
--- a/libexec/telnetd/state.c
+++ /dev/null
@@ -1,1512 +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.
- */
-
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)state.c 8.5 (Berkeley) 5/30/95";
-#endif
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <stdarg.h>
-#include "telnetd.h"
-
-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 " */
-
-static void doclientstat(void);
-
-void
-telrcv(void)
-{
- int c;
- static int state = TS_DATA;
-
- while (ncc > 0) {
- if ((&ptyobuf[BUFSIZ] - pfrontp) < 2)
- break;
- c = *netip++ & 0377, ncc--;
- switch (state) {
-
- case TS_CR:
- state = TS_DATA;
- /* Strip off \n or \0 after a \r */
- if ((c == 0) || (c == '\n')) {
- break;
- }
- /* FALLTHROUGH */
-
- 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 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
- {
- 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 */
- output_data("%c%c", IAC, 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, "panic state=%d", state);
- printf("telnetd: panic state=%d\n", state);
- exit(1);
- }
- }
-} /* 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(int option, int 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]++;
- }
- output_data((const char *)doopt, option);
-
- DIAG(TD_OPTIONS, printoption("td: send do", option));
-}
-
-void
-willoption(int option)
-{
- int changeok = 0;
- void (*func)(void) = 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 */
-
-
-
- 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 */
-
-
- case TELOPT_LFLOW:
- func = flowstat;
- break;
- }
- }
- }
- set_his_state_will(option);
- if (func)
- (*func)();
-} /* end of willoption */
-
-void
-send_dont(int option, int 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]++;
- }
- output_data((const char *)dont, option);
-
- DIAG(TD_OPTIONS, printoption("td: send dont", option));
-}
-
-void
-wontoption(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;
- lmodetype = KLUDGE_LINEMODE;
-# 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;
-
-
- /*
- * 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;
-
- default:
- break;
- }
- }
- }
- set_his_state_wont(option);
-
-} /* end of wontoption */
-
-void
-send_will(int option, int 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]++;
- }
- output_data((const char *)will, option);
-
- 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(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;
-
- 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(int option, int 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]++;
- }
- output_data((const char *)wont, option);
-
- DIAG(TD_OPTIONS, printoption("td: send wont", option));
-}
-
-void
-dontoption(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(void)
-{
- int subchar;
-
- DIAG(TD_OPTIONS, {netflush(); printsub('<', subpointer, SB_LEN()+2);});
-
- subchar = SB_GET();
- switch (subchar) {
- case TELOPT_TSPEED: {
- 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()) {
- 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: {
- 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: {
- 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: {
- int c;
- 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) {
- 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();
- /* FALLTHROUGH */
- 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,
- output_data("ENVIRON VALUE and VAR are reversed!\r\n"));
-
- }
- }
- 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();
- /* FALLTHROUGH */
- default:
- *cp++ = c;
- break;
- }
- }
- *cp = '\0';
- if (valp)
- (void)setenv(varp, valp, 1);
- else
- unsetenv(varp);
- break;
- } /* end of case TELOPT_NEW_ENVIRON */
-
- default:
- break;
- } /* end of switch */
-
-} /* end of suboption */
-
-static void
-doclientstat(void)
-{
- 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(void)
-{
- unsigned char statusbuf[256];
- unsigned char *ncp;
- 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 (i == IAC)
- ADD(IAC);
- }
- if (his_want_state_is_will(i)) {
- ADD(DO);
- ADD_DATA(i);
- if (i == IAC)
- ADD(IAC);
- }
- }
-
- 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);
-
- output_datalen(statusbuf, ncp - statusbuf);
- netflush(); /* Send it on its way */
-
- DIAG(TD_OPTIONS,
- {printsub('>', statusbuf, ncp - statusbuf); netflush();});
-}
-
-/*
- * This function appends data to nfrontp and advances nfrontp.
- * Returns the number of characters written altogether (the
- * buffer may have been flushed in the process).
- */
-
-int
-output_data(const char *format, ...)
-{
- va_list args;
- int len;
- char *buf;
-
- va_start(args, format);
- if ((len = vasprintf(&buf, format, args)) == -1)
- return -1;
- output_datalen(buf, len);
- va_end(args);
- free(buf);
- return (len);
-}
-
-void
-output_datalen(const char *buf, int len)
-{
- int remaining, copied;
-
- remaining = BUFSIZ - (nfrontp - netobuf);
- while (len > 0) {
- /* Free up enough space if the room is too low*/
- if ((len > BUFSIZ ? BUFSIZ : len) > remaining) {
- netflush();
- remaining = BUFSIZ - (nfrontp - netobuf);
- }
-
- /* Copy out as much as will fit */
- copied = remaining > len ? len : remaining;
- memmove(nfrontp, buf, copied);
- nfrontp += copied;
- len -= copied;
- remaining -= copied;
- buf += copied;
- }
- return;
-}
diff --git a/libexec/telnetd/sys_term.c b/libexec/telnetd/sys_term.c
deleted file mode 100644
index e0525d6..0000000
--- a/libexec/telnetd/sys_term.c
+++ /dev/null
@@ -1,1192 +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.
- */
-
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)sys_term.c 8.4+1 (Berkeley) 5/30/95";
-#endif
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include <sys/types.h>
-#include <sys/tty.h>
-#include <libutil.h>
-#include <stdlib.h>
-#include <utmp.h>
-
-#include "telnetd.h"
-#include "pathnames.h"
-
-
-int cleanopen(char *);
-void scrub_env(void);
-
-struct utmp wtmp;
-
-#ifdef _PATH_WTMP
-char wtmpf[] = _PATH_WTMP;
-#else
-char wtmpf[] = "/var/log/wtmp";
-#endif
-#ifdef _PATH_UTMP
-char utmpf[] = _PATH_UTMP;
-#else
-char utmpf[] = "/var/run/utmp";
-#endif
-
-char *envinit[3];
-extern char **environ;
-
-#define SCPYN(a, b) (void) strncpy(a, b, sizeof(a))
-#define SCMPN(a, b) strncmp(a, b, sizeof(a))
-
-#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
-
-#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 */
-# 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 */
-#endif /* USE_TERMIO */
-
-#include <sys/types.h>
-#include <libutil.h>
-
-int cleanopen(char *);
-void scrub_env(void);
-static char **addarg(char **, const char *);
-
-/*
- * 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(void)
-{
-#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
- (void) tcgetattr(pty, &termbuf);
-#endif
- termbuf2 = termbuf;
-}
-
-#if defined(LINEMODE) && defined(TIOCPKT_IOCTL)
-void
-copy_termbuf(char *cp, size_t len)
-{
- if (len > sizeof(termbuf))
- len = sizeof(termbuf);
- memmove((char *)&termbuf, cp, len);
- termbuf2 = termbuf;
-}
-#endif /* defined(LINEMODE) && defined(TIOCPKT_IOCTL) */
-
-void
-set_termbuf(void)
-{
- /*
- * 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)))
- (void) tcsetattr(pty, TCSANOW, &termbuf);
-#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(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 */
-
-
-#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);
-
-int
-spcset(int func, cc_t *valp, cc_t **valpp)
-{
- 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 */
-
-/*
- * 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.
- */
-char alpha[] = "0123456789abcdefghijklmnopqrstuv";
-char line[16];
-
-int
-getpty(int *ptynum __unused)
-{
- int p;
- const char *cp;
- char *p1, *p2;
- int i;
-
- (void) strcpy(line, _PATH_DEV);
- (void) strcat(line, "ptyXX");
- p1 = &line[8];
- p2 = &line[9];
-
- 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 = alpha[i];
- p = open(line, 2);
- if (p > 0) {
- line[5] = 't';
- chown(line, 0, 0);
- chmod(line, 0600);
- return(p);
- }
- }
- }
- return(-1);
-}
-
-#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.
- */
-
-
-int
-tty_linemode(void)
-{
-#ifndef USE_TERMIO
- return(termbuf.state & TS_EXTPROC);
-#else
- return(termbuf.c_lflag & EXTPROC);
-#endif
-}
-
-void
-tty_setlinemode(int on)
-{
-#ifdef TIOCEXT
- set_termbuf();
- (void) ioctl(pty, TIOCEXT, (char *)&on);
- init_termbuf();
-#else /* !TIOCEXT */
-# ifdef EXTPROC
- if (on)
- termbuf.c_lflag |= EXTPROC;
- else
- termbuf.c_lflag &= ~EXTPROC;
-# endif
-#endif /* TIOCEXT */
-}
-#endif /* LINEMODE */
-
-int
-tty_isecho(void)
-{
-#ifndef USE_TERMIO
- return (termbuf.sg.sg_flags & ECHO);
-#else
- return (termbuf.c_lflag & ECHO);
-#endif
-}
-
-int
-tty_flowmode(void)
-{
-#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(void)
-{
-#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(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(void)
-{
-#ifndef USE_TERMIO
- return(termbuf.sg.sg_flags & RAW);
-#else
- return(!(termbuf.c_lflag & ICANON));
-#endif
-}
-
-
-void
-tty_binaryin(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(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(void)
-{
-#ifndef USE_TERMIO
- return(termbuf.lflags & LPASS8);
-#else
- return(!(termbuf.c_iflag & ISTRIP));
-#endif
-}
-
-int
-tty_isbinaryout(void)
-{
-#ifndef USE_TERMIO
- return(termbuf.lflags & LLITOUT);
-#else
- return(!(termbuf.c_oflag&OPOST));
-#endif
-}
-
-#ifdef LINEMODE
-int
-tty_isediting(void)
-{
-#ifndef USE_TERMIO
- return(!(termbuf.sg.sg_flags & (CBREAK|RAW)));
-#else
- return(termbuf.c_lflag & ICANON);
-#endif
-}
-
-int
-tty_istrapsig(void)
-{
-#ifndef USE_TERMIO
- return(!(termbuf.sg.sg_flags&RAW));
-#else
- return(termbuf.c_lflag & ISIG);
-#endif
-}
-
-void
-tty_setedit(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(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(void)
-{
-#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(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(void)
-{
-#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(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(void)
-{
-#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_BAUD */
-
-void
-tty_tspeed(int val)
-{
-#ifdef DECODE_BAUD
- 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_BAUD */
- cfsetospeed(&termbuf, val);
-#endif /* DECODE_BAUD */
-}
-
-void
-tty_rspeed(int val)
-{
-#ifdef DECODE_BAUD
- 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 */
-}
-
-/*
- * getptyslave()
- *
- * Open the slave side of the pty, and do any initialization
- * that is necessary.
- */
-static void
-getptyslave(void)
-{
- int t = -1;
- char erase;
-
-# 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
-
- t = cleanopen(line);
- if (t < 0)
- fatalperror(net, line);
-
-
- /*
- * 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 all other termios/termio based
- * systems, other than 4.4BSD. In 4.4BSD the
- * kernel does the initial terminal setup.
- */
- 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");
- if (net > 2)
- (void) close(net);
-}
-
-#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(char *li)
-{
- int t;
-
- /*
- * Make sure that other people can't open the
- * slave side of the connection.
- */
- (void) chown(li, 0, 0);
- (void) chmod(li, 0600);
-
- (void) revoke(li);
-
- t = open(line, O_RDWR|O_NOCTTY);
-
- if (t < 0)
- return(-1);
-
- return(t);
-}
-
-/*
- * startslave(host)
- *
- * Given a hostname, do whatever
- * is necessary to startup the login process on the slave side of the pty.
- */
-
-/* ARGSUSED */
-void
-startslave(char *host, int autologin, char *autoname)
-{
- int i;
-
-
-
- if ((i = fork()) < 0)
- fatalperror(net, "fork");
- if (i) {
- } else {
- getptyslave();
- start_login(host, autologin, autoname);
- /*NOTREACHED*/
- }
-}
-
-void
-init_env(void)
-{
- char **envp;
-
- envp = envinit;
- if ((*envp = getenv("TZ")))
- *envp++ -= 3;
- *envp = 0;
- environ = envinit;
-}
-
-
-/*
- * start_login(host)
- *
- * Assuming that we are now running as a child processes, this
- * function will turn us into the login process.
- */
-
-#define undef1 __unused
-
-void
-start_login(char *host undef1, int autologin undef1, char *name undef1)
-{
- char **argv;
-
- 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)
-#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 (getenv("USER")) {
- argv = addarg(argv, "--");
- argv = addarg(argv, getenv("USER"));
-#if defined(LOGIN_ARGS) && defined(NO_LOGIN_P)
- {
- 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");
- }
- closelog();
-
- if (altlogin == NULL) {
- altlogin = _PATH_LOGIN;
- }
- execv(altlogin, argv);
-
- syslog(LOG_ERR, "%s: %m", altlogin);
- fatalperror(net, altlogin);
- /*NOTREACHED*/
-}
-
-static char **
-addarg(char **argv, const char *val)
-{
- 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[(long)argv[-1]]) {
- --argv;
- *argv = (char *)((long)(*argv) + 10);
- argv = (char **)realloc(argv, sizeof(*argv)*((long)(*argv) + 2));
- if (argv == NULL)
- return(NULL);
- argv++;
- cpp = &argv[(long)argv[-1] - 10];
- }
- *cpp++ = strdup(val);
- *cpp = 0;
- return(argv);
-}
-
-/*
- * scrub_env()
- *
- * We only accept the environment variables listed below.
- */
-void
-scrub_env(void)
-{
- static const char *rej[] = {
- "TERMCAP=/",
- NULL
- };
-
- static const char *acc[] = {
- "XAUTH=", "XAUTHORITY=", "DISPLAY=",
- "TERM=",
- "EDITOR=",
- "PAGER=",
- "LOGNAME=",
- "POSIXLY_CORRECT=",
- "PRINTER=",
- NULL
- };
-
- char **cpp, **cpp2;
- const char **p;
-
- for (cpp2 = cpp = environ; *cpp; cpp++) {
- int reject_it = 0;
-
- for(p = rej; *p; p++)
- if(strncmp(*cpp, *p, strlen(*p)) == 0) {
- reject_it = 1;
- break;
- }
- if (reject_it)
- continue;
-
- for(p = acc; *p; p++)
- if(strncmp(*cpp, *p, strlen(*p)) == 0)
- break;
- if(*p != NULL)
- *cpp2++ = *cpp;
- }
- *cpp2 = NULL;
-}
-
-/*
- * 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(int sig __unused)
-{
- char *p;
- sigset_t mask;
-
- p = line + sizeof(_PATH_DEV) - 1;
- /*
- * Block all signals before clearing the utmp entry. We don't want to
- * be called again after calling logout() and then not add the wtmp
- * entry because of not finding the corresponding entry in utmp.
- */
- sigfillset(&mask);
- sigprocmask(SIG_SETMASK, &mask, NULL);
- 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);
-}
diff --git a/libexec/telnetd/telnetd.8 b/libexec/telnetd/telnetd.8
deleted file mode 100644
index 306e15e..0000000
--- a/libexec/telnetd/telnetd.8
+++ /dev/null
@@ -1,593 +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
-.\" $FreeBSD$
-.\"
-.Dd January 27, 2000
-.Dt TELNETD 8
-.Os
-.Sh NAME
-.Nm telnetd
-.Nd DARPA
-.Tn TELNET
-protocol server
-.Sh SYNOPSIS
-.Nm /usr/libexec/telnetd
-.Op Fl BUhlkn
-.Op Fl D Ar debugmode
-.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 u Ar len
-.Op Fl debug Op Ar port
-.Sh DESCRIPTION
-The
-.Nm
-utility is a server which supports the
-.Tn DARPA
-standard
-.Tn TELNET
-virtual terminal protocol.
-The
-.Nm
-utility 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
-manually, instead of through
-.Xr inetd 8 .
-If started up this way,
-.Ar port
-may be specified to run
-.Nm
-on an alternate
-.Tn TCP
-port number.
-.Pp
-The
-.Nm
-utility accepts the following options:
-.Bl -tag -width indent
-.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
-has been compiled with support for the
-.Dv AUTHENTICATION
-option.
-There are several valid values for
-.Ar authmode :
-.Bl -tag -width debug
-.It Cm debug
-Turn on authentication debugging code.
-.It Cm 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 Cm 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 Cm 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 Cm 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 Cm off
-Disable the authentication code.
-All user verification will happen through the
-.Xr login 1
-program.
-.El
-.It Fl B
-Specify bftp server mode. In this mode,
-.Nm
-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
-to print out debugging information
-to the connection, allowing the user to see what
-.Nm
-is doing.
-There are several possible values for
-.Ar debugmode :
-.Bl -tag -width exercise
-.It Cm options
-Print information about the negotiation of
-.Tn TELNET
-options.
-.It Cm report
-Print the
-.Cm options
-information, plus some additional information
-about what processing is going on.
-.It Cm netdata
-Display the data stream received by
-.Nm .
-.It Cm ptydata
-Display data written to the pty.
-.It Cm exercise
-Has not been implemented yet.
-.El
-.It Fl debug
-Enable debugging on each socket created by
-.Nm
-(see
-.Dv SO_DEBUG
-in
-.Xr socket 2 ) .
-.It Fl edebug
-If
-.Nm
-has been compiled with support for data encryption, then the
-.Fl edebug
-option may be used to enable encryption debugging code.
-.It Fl h
-Disable the printing of host-specific information before
-login has been completed.
-.It Fl k
-This option is only useful if
-.Nm
-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
-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 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
-Specify line mode. Try 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
-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 p Ar loginprog
-Specify 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 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.
-.It Fl U
-This option causes
-.Nm
-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
-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 .
-.El
-.Pp
-The
-.Nm
-utility 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 .
-The
-.Nm
-utility 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
-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
-.Dq cooked
-mode, and with
-.Dv XTABS and
-.Dv CRMOD
-enabled (see
-.Xr tty 4 ) .
-.Pp
-The
-.Nm
-utility 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
-.Nm
-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
-.Nm
-will not be doing any terminal echoing, so the
-client should do any terminal echoing that is needed.
-.It "WILL BINARY"
-Indicate 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"
-Indicate that it will not be sending
-.Dv IAC GA ,
-go ahead, commands.
-.It "WILL STATUS"
-Indicate 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 .
-.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
-is compiled with support for data encryption, and
-indicates a willingness to decrypt
-the data stream.
-.El
-.Pp
-The
-.Nm
-utility has support for enabling remotely the following
-.Tn TELNET
-options:
-.Bl -tag -width "DO AUTHENTICATION"
-.It "DO BINARY"
-Sent to indicate that
-.Nm
-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
-.Bx 4.2
-.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"
-Indicate 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"
-Indicate 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"
-Indicate a desire to be able to request information
-about the speed of the serial line to which
-the client is attached.
-.It "DO XDISPLOC"
-Indicate a desire to be able to request the name
-of the X Window System display that is associated with
-the telnet client.
-.It "DO NEW-ENVIRON"
-Indicate a desire to be able to request environment
-variable information, as described in RFC 1572.
-.It "DO ENVIRON"
-Indicate a desire to be able to request environment
-variable information, as described in RFC 1408.
-.It "DO LINEMODE"
-Only sent if
-.Nm
-is compiled with support for linemode, and
-requests that the client do line by line processing.
-.It "DO TIMING-MARK"
-Only sent if
-.Nm
-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
-is compiled with support for authentication, and
-indicates a willingness to receive authentication
-information for automatic login.
-.It "DO ENCRYPT"
-Only sent if
-.Nm
-is compiled with support for data encryption, and
-indicates a willingness to decrypt
-the data stream.
-.El
-.Sh NOTES
-By default
-.Nm
-will read the
-.Em \&he ,
-.Em \&hn ,
-and
-.Em \&im
-capabilities from
-.Pa /etc/gettytab
-and use that information (if present) to determine
-what to display before the login: prompt. You can
-also use a System V style
-.Pa /etc/issue
-file by using the
-.Em \&if
-capability, which will override
-.Em \&im .
-The information specified in either
-.Em \&im
-or
-.Em \&if
-will be displayed to both console and remote logins.
-.\" .Sh ENVIRONMENT
-.Sh FILES
-.Bl -tag -width /usr/ucb/bftp -compact
-.It Pa /etc/services
-.It Pa /etc/gettytab
-.It Pa /etc/iptos
-(if supported)
-.It Pa /usr/ucb/bftp
-(if supported)
-.El
-.Sh "SEE ALSO"
-.Xr bftp 1 ,
-.Xr login 1 ,
-.Xr gettytab 5 ,
-.Xr telnet 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
-.El
-.Sh BUGS
-Some
-.Tn TELNET
-commands are only partially implemented.
-.Pp
-Because of bugs in the original
-.Bx 4.2
-.Xr telnet 1 ,
-.Nm
-performs some dubious protocol exchanges to try to discover if the remote
-client is, in fact, a
-.Bx 4.2
-.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
-The
-.Nm
-utility never sends
-.Tn TELNET
-.Dv IAC GA
-(go ahead) commands.
-.Sh HISTORY
-IPv6 support was added by WIDE/KAME project.
diff --git a/libexec/telnetd/telnetd.c b/libexec/telnetd/telnetd.c
deleted file mode 100644
index 042fea5..0000000
--- a/libexec/telnetd/telnetd.c
+++ /dev/null
@@ -1,1117 +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.
- */
-
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)telnetd.c 8.4 (Berkeley) 5/30/95";
-#endif
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#include "telnetd.h"
-#include "pathnames.h"
-
-#include <sys/mman.h>
-#include <err.h>
-#include <libutil.h>
-#include <paths.h>
-#include <termcap.h>
-#include <utmp.h>
-
-#include <arpa/inet.h>
-
-#include <libtelnet/misc.h>
-
-char remote_hostname[MAXHOSTNAMELEN];
-size_t utmp_len = sizeof(remote_hostname) - 1;
-int registerd_host_only = 0;
-
-
-/*
- * I/O data buffers,
- * pointers, and counters.
- */
-char ptyibuf[BUFSIZ], *ptyip = ptyibuf;
-char ptyibuf2[BUFSIZ];
-
-int readstream(int, char *, int);
-void doit(struct sockaddr *);
-int terminaltypeok(char *);
-
-int hostinfo = 1; /* do we print login banner? */
-
-static int debug = 0;
-int keepalive = 1;
-const char *altlogin;
-
-void doit(struct sockaddr *);
-int terminaltypeok(char *);
-void startslave(char *, int, char *);
-extern void usage(void);
-static void _gettermname(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',
- '4', '6',
-#ifdef BFTPDAEMON
- 'B',
-#endif
-#ifdef DIAGNOSTICS
- 'D', ':',
-#endif
-#ifdef LINEMODE
- 'l',
-#endif
- '\0'
-};
-
-int family = AF_INET;
-
-#ifndef MAXHOSTNAMELEN
-#define MAXHOSTNAMELEN 256
-#endif /* MAXHOSTNAMELEN */
-
-char *hostname;
-char host_name[MAXHOSTNAMELEN];
-
-extern void telnet(int, int, char *);
-
-int level;
-char user_name[256];
-
-int
-main(int argc, char *argv[])
-{
- struct sockaddr_storage from;
- int on = 1, fromlen;
- int ch;
-#if defined(IPPROTO_IP) && defined(IP_TOS)
- int tos = -1;
-#endif
-
- pfrontp = pbackp = ptyobuf;
- netip = netibuf;
- nfrontp = nbackp = netobuf;
-
- /*
- * This initialization causes linemode to default to a configuration
- * that works on all telnet clients, including the FreeBSD client.
- * This is not quite the same as the telnet client issuing a "mode
- * character" command, but has most of the same benefits, and is
- * preferable since some clients (like usofts) don't have the
- * mode character command anyway and linemode breaks things.
- * The most notable symptom of fix is that csh "set filec" operations
- * like <ESC> (filename completion) and ^D (choices) keys now work
- * in telnet sessions and can be used more than once on the same line.
- * CR/LF handling is also corrected in some termio modes. This
- * change resolves problem reports bin/771 and bin/1037.
- */
-
- linemode=1; /*Default to mode that works on bulk of clients*/
-
- while ((ch = getopt(argc, argv, valid_opts)) != -1) {
- switch(ch) {
-
-
-#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 */
-
-
- case 'h':
- hostinfo = 0;
- break;
-
-#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;
-
- case 'S':
-#ifdef HAS_GETTOS
- if ((tos = parsetos(optarg, "tcp")) < 0)
- warnx("%s%s%s",
- "bad TOS argument '", optarg,
- "'; will try to use default TOS");
-#else
- warnx("TOS option unavailable; -S flag not supported");
-#endif
- break;
-
- case 'u':
- utmp_len = (size_t)atoi(optarg);
- if (utmp_len >= sizeof(remote_hostname))
- utmp_len = sizeof(remote_hostname) - 1;
- break;
-
- case 'U':
- registerd_host_only = 1;
- break;
-
-
- case '4':
- family = AF_INET;
- break;
-
-#ifdef INET6
- case '6':
- family = AF_INET6;
- break;
-#endif
-
- default:
- warnx("%c: unknown option", ch);
- /* FALLTHROUGH */
- case '?':
- usage();
- /* NOTREACHED */
- }
- }
-
- argc -= optind;
- argv += optind;
-
- if (debug) {
- int s, ns, foo, error;
- const char *service = "telnet";
- struct addrinfo hints, *res;
-
- if (argc > 1) {
- usage();
- /* NOT REACHED */
- } else if (argc == 1)
- service = *argv;
-
- memset(&hints, 0, sizeof(hints));
- hints.ai_flags = AI_PASSIVE;
- hints.ai_family = family;
- hints.ai_socktype = SOCK_STREAM;
- hints.ai_protocol = 0;
- error = getaddrinfo(NULL, service, &hints, &res);
-
- if (error) {
- errx(1, "tcp/%s: %s\n", service, gai_strerror(error));
- if (error == EAI_SYSTEM)
- errx(1, "tcp/%s: %s\n", service, strerror(errno));
- usage();
- }
-
- s = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
- if (s < 0)
- err(1, "socket");
- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR,
- (char *)&on, sizeof(on));
- if (bind(s, res->ai_addr, res->ai_addrlen) < 0)
- err(1, "bind");
- if (listen(s, 1) < 0)
- err(1, "listen");
- foo = res->ai_addrlen;
- ns = accept(s, res->ai_addr, &foo);
- if (ns < 0)
- err(1, "accept");
- (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 */
- }
-
- openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
- fromlen = sizeof (from);
- if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
- warn("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 (from.ss_family == AF_INET) {
-# 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((struct sockaddr *)&from);
- /* NOTREACHED */
- return(0);
-} /* end of main */
-
- void
-usage()
-{
- fprintf(stderr, "usage: telnetd");
-#ifdef BFTPDAEMON
- fprintf(stderr, " [-B]");
-#endif
- fprintf(stderr, " [-debug]");
-#ifdef DIAGNOSTICS
- fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
-#endif
- fprintf(stderr, " [-h]");
-#if defined(LINEMODE) && defined(KLUDGELINEMODE)
- fprintf(stderr, " [-k]");
-#endif
-#ifdef LINEMODE
- fprintf(stderr, " [-l]");
-#endif
- fprintf(stderr, " [-n]");
- fprintf(stderr, "\n\t");
-#ifdef HAS_GETTOS
- fprintf(stderr, " [-S tos]");
-#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
-};
-
-
-#define undef2 __unused
-
-static int
-getterminaltype(char *name undef2)
-{
- int retval = -1;
-
- settimer(baseline);
-
- 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 (
- 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();
- }
- if (his_state_is_will(TELOPT_TSPEED)) {
- static unsigned char sb[] =
- { IAC, SB, TELOPT_TSPEED, TELQUAL_SEND, IAC, SE };
-
- output_datalen(sb, 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 };
-
- output_datalen(sb, 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 };
-
- output_datalen(sb, 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 };
-
- output_datalen(sb, sizeof sb);
- DIAG(TD_OPTIONS, printsub('>', sb + 2, sizeof sb - 2););
- }
- if (his_state_is_will(TELOPT_TTYPE)) {
-
- output_datalen(ttytype_sbbuf, 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)-1);
- first[sizeof(first)-1] = '\0';
- for(;;) {
- /*
- * Save the unknown name, and request the next name.
- */
- (void) strncpy(last, terminaltype, sizeof(last)-1);
- last[sizeof(last)-1] = '\0';
- _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(terminaltype)-1);
- terminaltype[sizeof(terminaltype)-1] = '\0';
- }
- break;
- }
- }
- }
- }
- return(retval);
-} /* end of getterminaltype */
-
-static void
-_gettermname(void)
-{
- /*
- * 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);
- output_datalen(ttytype_sbbuf, sizeof ttytype_sbbuf);
- DIAG(TD_OPTIONS, printsub('>', ttytype_sbbuf + 2,
- sizeof ttytype_sbbuf - 2););
- while (sequenceIs(ttypesubopt, baseline))
- ttloop();
-}
-
-int
-terminaltypeok(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);
-}
-
-/*
- * Get a pty, scan input lines.
- */
-void
-doit(struct sockaddr *who)
-{
- int err_; /* XXX */
- 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;
-
- if ((lp = getpty()) == NULL)
- fatal(net, "Out of ptys");
-
- if ((pty = open(lp, 2)) >= 0) {
- strlcpy(line,lp,sizeof(line));
- line[5] = 't';
- break;
- }
- }
-#endif
-
- /* get name of connected client */
- if (realhostname_sa(remote_hostname, sizeof(remote_hostname) - 1,
- who, who->sa_len) == HOSTNAME_INVALIDADDR && registerd_host_only)
- fatal(net, "Couldn't resolve your address into a host name.\r\n\
- Please contact your net administrator");
- remote_hostname[sizeof(remote_hostname) - 1] = '\0';
-
- trimdomain(remote_hostname, UT_HOSTSIZE);
- if (!isdigit(remote_hostname[0]) && strlen(remote_hostname) > utmp_len)
- err_ = getnameinfo(who, who->sa_len, remote_hostname,
- sizeof(remote_hostname), NULL, 0,
- NI_NUMERICHOST|NI_WITHSCOPEID);
- /* XXX: do 'err_' check */
-
- (void) gethostname(host_name, sizeof(host_name) - 1);
- host_name[sizeof(host_name) - 1] = '\0';
- hostname = host_name;
-
-
- init_env();
- /*
- * get terminal type.
- */
- *user_name = 0;
- level = getterminaltype(user_name);
- setenv("TERM", terminaltype ? terminaltype : "network", 1);
-
- telnet(net, pty, remote_hostname); /* begin server process */
-
- /*NOTREACHED*/
-} /* end of doit */
-
-/*
- * Main loop. Select from pty and network, and
- * hand data to telnet receiver finite state machine.
- */
-void
-telnet(int f, int p, char *host)
-{
- int on = 1;
-#define TABBUFSIZ 512
- char defent[TABBUFSIZ];
- char defstrs[TABBUFSIZ];
-#undef TABBUFSIZ
- char *HE;
- char *HN;
- char *IM;
- 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, output_data("td: simulating recv\r\n"));
- 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);
-
- /*
- * Turn on packet mode
- */
- (void) ioctl(p, TIOCPKT, (char *)&on);
-
-#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(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);
-
-#ifdef TIOCNOTTY
- {
- int t;
- t = open(_PATH_TTY, O_RDWR);
- if (t >= 0) {
- (void) ioctl(t, TIOCNOTTY, (char *)0);
- (void) close(t);
- }
- }
-#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 (getent(defent, "default") == 1) {
- char *cp=defstrs;
-
- HE = Getstr("he", &cp);
- HN = Getstr("hn", &cp);
- IM = Getstr("im", &cp);
- if (HN && *HN)
- (void) strlcpy(host_name, HN, sizeof(host_name));
- if (IM == 0)
- IM = strdup("");
- } else {
- IM = strdup(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, output_data("td: Entering processing loop\r\n"));
-
- /*
- * 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;
- int c;
-
- if (ncc < 0 && pcc < 0)
- break;
-
- 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),
- output_data("td: netread %d chars\r\n", ncc));
- DIAG(TD_NETDATA, printdata("nd", netip, ncc));
- }
-
- /*
- * Something to read from the pty...
- */
- if (FD_ISSET(p, &ibits)) {
- pcc = read(p, ptyibuf, BUFSIZ);
- /*
- * 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;
-#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.
- */
- output_data("%c%c", IAC, 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;
- output_data("%c%c%c%c%c%c",
- IAC, SB, TELOPT_LFLOW,
- flowmode ? LFLOW_ON
- : LFLOW_OFF,
- IAC, SE);
- DIAG(TD_OPTIONS, printsub('>',
- (unsigned char *)nfrontp-4,
- 4););
- }
- }
- pcc--;
- ptyip = ptyibuf+1;
- }
- }
-
- while (pcc > 0) {
- if ((&netobuf[BUFSIZ] - nfrontp) < 2)
- break;
- c = *ptyip++ & 0377, pcc--;
- if (c == IAC)
- output_data("%c", c);
- output_data("%c", c);
- if ((c == '\r') && (my_state_is_wont(TELOPT_BINARY))) {
- if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
- output_data("%c", *ptyip++ & 0377);
- pcc--;
- } else
- output_data("%c", '\0');
- }
- }
-
- 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
-
-/*
- * Send interrupt to process on other side of pty.
- * If it is in raw mode, just write NULL;
- * otherwise, write intr char.
- */
-void
-interrupt(void)
-{
- ptyflush(); /* half-hearted */
-
-#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 */
-}
-
-/*
- * Send quit to process on other side of pty.
- * If it is in raw mode, just write NULL;
- * otherwise, write quit char.
- */
-void
-sendbrk(void)
-{
- 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(void)
-{
-#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(void)
-{
-#if defined(SIGINFO) && defined(TCSIG)
- if (slctab[SLC_AYT].sptr && *slctab[SLC_AYT].sptr != _POSIX_VDISABLE) {
- (void) ioctl(pty, TCSIG, (char *)SIGINFO);
- return;
- }
-#endif
- output_data("\r\n[Yes]\r\n");
-}
-
-void
-doeof(void)
-{
- 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/libexec/telnetd/telnetd.h b/libexec/telnetd/telnetd.h
deleted file mode 100644
index 5bfc572..0000000
--- a/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
- * $FreeBSD$
- */
-
-
-#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 const char *altlogin;
diff --git a/libexec/telnetd/termstat.c b/libexec/telnetd/termstat.c
deleted file mode 100644
index 8d8257d..0000000
--- a/libexec/telnetd/termstat.c
+++ /dev/null
@@ -1,610 +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.
- */
-
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)termstat.c 8.2 (Berkeley) 5/30/95";
-#endif
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#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 */
-
-#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)
-{
- int need_will_echo = 0;
-
- /*
- * 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);
- }
- }
-
-
- /*
- * 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 */
- output_data("%c%c%c%c%c%c%c", IAC, SB,
- TELOPT_LINEMODE, LM_MODE, useeditmode,
- IAC, SE);
- 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.
- */
- output_data("%c%c%c%c%c%c%c", IAC, SB,
- TELOPT_LINEMODE, LM_MODE, useeditmode,
- IAC, SE);
- 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(void)
-{
- if (his_state_is_will(TELOPT_LFLOW)) {
- if (tty_flowmode() != flowmode) {
- flowmode = tty_flowmode();
- output_data("%c%c%c%c%c%c",
- IAC, SB, TELOPT_LFLOW,
- flowmode ? LFLOW_ON : LFLOW_OFF,
- IAC, SE);
- }
- if (tty_restartany() != restartany) {
- restartany = tty_restartany();
- output_data("%c%c%c%c%c%c",
- IAC, SB, TELOPT_LFLOW,
- restartany ? LFLOW_RESTART_ANY
- : LFLOW_RESTART_XON,
- IAC, SE);
- }
- }
-}
-
-/*
- * 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(int code, int parm1, int parm2)
-{
-
- /*
- * 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;
- output_data("%c%c%c%c%c%c%c", IAC,
- SB, TELOPT_LINEMODE, LM_MODE,
- useeditmode, IAC, SE);
- editmode = useeditmode;
- }
-
-
- tty_setlinemode(uselinemode);
-
- linemode = uselinemode;
-
- if (!linemode)
- send_will(TELOPT_ECHO, 1);
- }
- break;
-
- case LM_MODE:
- {
- 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) {
- output_data("%c%c%c%c%c%c%c", IAC,
- SB, TELOPT_LINEMODE, LM_MODE,
- useeditmode|MODE_ACK,
- IAC, SE);
- }
-
- 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 separate 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 */
-
- netflush();
-
-} /* end of clientstat */
-
-#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(void)
-{
-
- /*
- * 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(void)
-{
- return(_terminit);
-
-} /* end of terminit */
-#endif /* LINEMODE */
diff --git a/libexec/telnetd/utility.c b/libexec/telnetd/utility.c
deleted file mode 100644
index 042b248..0000000
--- a/libexec/telnetd/utility.c
+++ /dev/null
@@ -1,900 +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.
- */
-
-#if 0
-#ifndef lint
-static const char sccsid[] = "@(#)utility.c 8.4 (Berkeley) 5/30/95";
-#endif /* not lint */
-#endif
-#include <sys/cdefs.h>
-__FBSDID("$FreeBSD$");
-
-#ifdef __FreeBSD__
-#include <locale.h>
-#include <sys/utsname.h>
-#endif
-#include <string.h>
-#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()
-{
-
- DIAG(TD_REPORT, output_data("td: ttloop\r\n"));
- if (nfrontp - nbackp > 0) {
- netflush();
- }
- ncc = read(net, netibuf, sizeof netibuf);
- if (ncc < 0) {
- syslog(LOG_INFO, "ttloop: read: %m");
- exit(1);
- } else if (ncc == 0) {
- syslog(LOG_INFO, "ttloop: peer died: %m");
- exit(1);
- }
- DIAG(TD_REPORT, output_data("td: ttloop read %d chars\r\n", ncc));
- 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(int s)
-{
- static struct timeval timeout = { 0, 0 };
- fd_set excepts;
- int value;
-
- do {
- FD_ZERO(&excepts);
- FD_SET(s, &excepts);
- memset((char *)&timeout, 0, sizeof timeout);
- 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(void)
-{
- int n;
-
- if ((n = pfrontp - pbackp) > 0) {
- DIAG(TD_REPORT | TD_PTYDATA,
- output_data("td: ptyflush %d chars\r\n", n));
- 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.
- */
-static char *
-nextitem(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 */
- {
- 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(void)
-{
- char *thisitem, *next;
- char *good;
-#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
- ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
-
- thisitem = netobuf;
-
- while ((next = nextitem(thisitem)) <= nbackp) {
- thisitem = next;
- }
-
- /* Now, thisitem is first before/at boundary. */
-
- good = netobuf; /* where the good bytes go */
-
- 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(void)
-{
- int n;
- extern int not42;
-
- while ((n = nfrontp - nbackp) > 0) {
-#if 0
- /* XXX This causes output_data() to recurse and die */
- DIAG(TD_REPORT, {
- n += output_data("td: netflush %d chars\r\n", n);
- });
-#endif
- /*
- * 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 == -1) {
- if (errno == EWOULDBLOCK || errno == EINTR)
- continue;
- cleanup(0);
- /* NOTREACHED */
- }
- nbackp += n;
- if (nbackp >= neturg) {
- neturg = 0;
- }
- if (nbackp == nfrontp) {
- nbackp = nfrontp = netobuf;
- }
- }
- return;
-} /* end of netflush */
-
-
-/*
- * miscellaneous functions doing a variety of little jobs follow ...
- */
-
-
-void
-fatal(int f, const char *msg)
-{
- char buf[BUFSIZ];
-
- (void) snprintf(buf, sizeof(buf), "telnetd: %s.\r\n", msg);
- (void) write(f, buf, (int)strlen(buf));
- sleep(1); /*XXX*/
- exit(1);
-}
-
-void
-fatalperror(int f, const char *msg)
-{
- char buf[BUFSIZ];
-
- (void) snprintf(buf, sizeof(buf), "%s: %s", msg, strerror(errno));
- fatal(f, buf);
-}
-
-char editedhost[32];
-
-void
-edithost(char *pat, char *host)
-{
- char *res = editedhost;
-
- if (!pat)
- pat = strdup("");
- 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;
-
-static void
-putstr(const char *s)
-{
-
- while (*s)
- putchr(*s++);
-}
-
-void
-putchr(int cc)
-{
- *putlocation++ = cc;
-}
-
-#ifdef __FreeBSD__
-static char fmtstr[] = { "%+" };
-#else
-static char fmtstr[] = { "%l:%M%P on %A, %d %B %Y" };
-#endif
-
-void
-putf(char *cp, char *where)
-{
- char *slash;
- time_t t;
- char db[100];
-#ifdef __FreeBSD__
- static struct utsname kerninfo;
-
- if (!*kerninfo.sysname)
- uname(&kerninfo);
-#endif
-
- putlocation = where;
-
- while (*cp) {
- if (*cp =='\n') {
- putstr("\r\n");
- cp++;
- continue;
- } else 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;
-
-#ifdef __FreeBSD__
- case 's':
- putstr(kerninfo.sysname);
- break;
-
- case 'm':
- putstr(kerninfo.machine);
- break;
-
- case 'r':
- putstr(kerninfo.release);
- break;
-
- case 'v':
- putstr(kerninfo.version);
- break;
-#endif
-
- case '%':
- putchr('%');
- break;
- }
- cp++;
- }
-}
-
-#ifdef DIAGNOSTICS
-/*
- * Print telnet options and commands in plain text, if possible.
- */
-void
-printoption(const char *fmt, int option)
-{
- if (TELOPT_OK(option))
- output_data("%s %s\r\n", fmt, TELOPT(option));
- else if (TELCMD_OK(option))
- output_data("%s %s\r\n", fmt, TELCMD(option));
- else
- output_data("%s %d\r\n", fmt, option);
- return;
-}
-
-void
-printsub(char direction, unsigned char *pointer, int length)
-{
- int i = 0;
-
- if (!(diagnostic & TD_OPTIONS))
- return;
-
- if (direction) {
- output_data("td: %s suboption ",
- direction == '<' ? "recv" : "send");
- if (length >= 3) {
- int j;
-
- i = pointer[length-2];
- j = pointer[length-1];
-
- if (i != IAC || j != SE) {
- output_data("(terminated by ");
- if (TELOPT_OK(i))
- output_data("%s ", TELOPT(i));
- else if (TELCMD_OK(i))
- output_data("%s ", TELCMD(i));
- else
- output_data("%d ", i);
- if (TELOPT_OK(j))
- output_data("%s", TELOPT(j));
- else if (TELCMD_OK(j))
- output_data("%s", TELCMD(j));
- else
- output_data("%d", j);
- output_data(", not IAC SE!) ");
- }
- }
- length -= 2;
- }
- if (length < 1) {
- output_data("(Empty suboption??\?)");
- return;
- }
- switch (pointer[0]) {
- case TELOPT_TTYPE:
- output_data("TERMINAL-TYPE ");
- switch (pointer[1]) {
- case TELQUAL_IS:
- output_data("IS \"%.*s\"", length-2, (char *)pointer+2);
- break;
- case TELQUAL_SEND:
- output_data("SEND");
- break;
- default:
- output_data(
- "- unknown qualifier %d (0x%x).",
- pointer[1], pointer[1]);
- }
- break;
- case TELOPT_TSPEED:
- output_data("TERMINAL-SPEED");
- if (length < 2) {
- output_data(" (empty suboption??\?)");
- break;
- }
- switch (pointer[1]) {
- case TELQUAL_IS:
- output_data(" IS %.*s", length-2, (char *)pointer+2);
- break;
- default:
- if (pointer[1] == 1)
- output_data(" SEND");
- else
- output_data(" %d (unknown)", pointer[1]);
- for (i = 2; i < length; i++) {
- output_data(" ?%d?", pointer[i]);
- }
- break;
- }
- break;
-
- case TELOPT_LFLOW:
- output_data("TOGGLE-FLOW-CONTROL");
- if (length < 2) {
- output_data(" (empty suboption??\?)");
- break;
- }
- switch (pointer[1]) {
- case LFLOW_OFF:
- output_data(" OFF"); break;
- case LFLOW_ON:
- output_data(" ON"); break;
- case LFLOW_RESTART_ANY:
- output_data(" RESTART-ANY"); break;
- case LFLOW_RESTART_XON:
- output_data(" RESTART-XON"); break;
- default:
- output_data(" %d (unknown)", pointer[1]);
- }
- for (i = 2; i < length; i++) {
- output_data(" ?%d?", pointer[i]);
- }
- break;
-
- case TELOPT_NAWS:
- output_data("NAWS");
- if (length < 2) {
- output_data(" (empty suboption??\?)");
- break;
- }
- if (length == 2) {
- output_data(" ?%d?", pointer[1]);
- break;
- }
- output_data(" %d %d (%d)",
- pointer[1], pointer[2],
- (int)((((unsigned int)pointer[1])<<8)|((unsigned int)pointer[2])));
- if (length == 4) {
- output_data(" ?%d?", pointer[3]);
- break;
- }
- output_data(" %d %d (%d)",
- pointer[3], pointer[4],
- (int)((((unsigned int)pointer[3])<<8)|((unsigned int)pointer[4])));
- for (i = 5; i < length; i++) {
- output_data(" ?%d?", pointer[i]);
- }
- break;
-
- case TELOPT_LINEMODE:
- output_data("LINEMODE ");
- if (length < 2) {
- output_data(" (empty suboption??\?)");
- break;
- }
- switch (pointer[1]) {
- case WILL:
- output_data("WILL ");
- goto common;
- case WONT:
- output_data("WONT ");
- goto common;
- case DO:
- output_data("DO ");
- goto common;
- case DONT:
- output_data("DONT ");
- common:
- if (length < 3) {
- output_data("(no option??\?)");
- break;
- }
- switch (pointer[2]) {
- case LM_FORWARDMASK:
- output_data("Forward Mask");
- for (i = 3; i < length; i++) {
- output_data(" %x", pointer[i]);
- }
- break;
- default:
- output_data("%d (unknown)", pointer[2]);
- for (i = 3; i < length; i++) {
- output_data(" %d", pointer[i]);
- }
- break;
- }
- break;
-
- case LM_SLC:
- output_data("SLC");
- for (i = 2; i < length - 2; i += 3) {
- if (SLC_NAME_OK(pointer[i+SLC_FUNC]))
- output_data(" %s", SLC_NAME(pointer[i+SLC_FUNC]));
- else
- output_data(" %d", pointer[i+SLC_FUNC]);
- switch (pointer[i+SLC_FLAGS]&SLC_LEVELBITS) {
- case SLC_NOSUPPORT:
- output_data(" NOSUPPORT"); break;
- case SLC_CANTCHANGE:
- output_data(" CANTCHANGE"); break;
- case SLC_VARIABLE:
- output_data(" VARIABLE"); break;
- case SLC_DEFAULT:
- output_data(" DEFAULT"); break;
- }
- output_data("%s%s%s",
- pointer[i+SLC_FLAGS]&SLC_ACK ? "|ACK" : "",
- pointer[i+SLC_FLAGS]&SLC_FLUSHIN ? "|FLUSHIN" : "",
- pointer[i+SLC_FLAGS]&SLC_FLUSHOUT ? "|FLUSHOUT" : "");
- if (pointer[i+SLC_FLAGS]& ~(SLC_ACK|SLC_FLUSHIN|
- SLC_FLUSHOUT| SLC_LEVELBITS)) {
- output_data("(0x%x)", pointer[i+SLC_FLAGS]);
- }
- output_data(" %d;", pointer[i+SLC_VALUE]);
- if ((pointer[i+SLC_VALUE] == IAC) &&
- (pointer[i+SLC_VALUE+1] == IAC))
- i++;
- }
- for (; i < length; i++) {
- output_data(" ?%d?", pointer[i]);
- }
- break;
-
- case LM_MODE:
- output_data("MODE ");
- if (length < 3) {
- output_data("(no mode??\?)");
- 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" : "");
- output_data("%s", tbuf[1] ? &tbuf[1] : "0");
- }
- if (pointer[2]&~(MODE_EDIT|MODE_TRAPSIG|MODE_ACK)) {
- output_data(" (0x%x)", pointer[2]);
- }
- for (i = 3; i < length; i++) {
- output_data(" ?0x%x?", pointer[i]);
- }
- break;
- default:
- output_data("%d (unknown)", pointer[1]);
- for (i = 2; i < length; i++) {
- output_data(" %d", pointer[i]);
- }
- }
- break;
-
- case TELOPT_STATUS: {
- const char *cp;
- int j, k;
-
- output_data("STATUS");
-
- switch (pointer[1]) {
- default:
- if (pointer[1] == TELQUAL_SEND)
- output_data(" SEND");
- else
- output_data(" %d (unknown)", pointer[1]);
- for (i = 2; i < length; i++) {
- output_data(" ?%d?", pointer[i]);
- }
- break;
- case TELQUAL_IS:
- output_data(" IS\r\n");
-
- 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]))
- output_data(" %s %s", cp, TELOPT(pointer[i]));
- else
- output_data(" %s %d", cp, pointer[i]);
-
- output_data("\r\n");
- break;
-
- case SB:
- output_data(" SB ");
- 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) {
- output_data(" SE");
- i = j;
- } else
- i = j - 1;
-
- output_data("\r\n");
-
- break;
-
- default:
- output_data(" %d", pointer[i]);
- break;
- }
- }
- break;
- }
- break;
- }
-
- case TELOPT_XDISPLOC:
- output_data("X-DISPLAY-LOCATION ");
- switch (pointer[1]) {
- case TELQUAL_IS:
- output_data("IS \"%.*s\"", length-2, (char *)pointer+2);
- break;
- case TELQUAL_SEND:
- output_data("SEND");
- break;
- default:
- output_data("- unknown qualifier %d (0x%x).",
- pointer[1], pointer[1]);
- }
- break;
-
- case TELOPT_NEW_ENVIRON:
- output_data("NEW-ENVIRON ");
- goto env_common1;
- case TELOPT_OLD_ENVIRON:
- output_data("OLD-ENVIRON");
- env_common1:
- switch (pointer[1]) {
- case TELQUAL_IS:
- output_data("IS ");
- goto env_common;
- case TELQUAL_SEND:
- output_data("SEND ");
- goto env_common;
- case TELQUAL_INFO:
- output_data("INFO ");
- env_common:
- {
- int noquote = 2;
- for (i = 2; i < length; i++ ) {
- switch (pointer[i]) {
- case NEW_ENV_VAR:
- output_data("\" VAR " + noquote);
- noquote = 2;
- break;
-
- case NEW_ENV_VALUE:
- output_data("\" VALUE " + noquote);
- noquote = 2;
- break;
-
- case ENV_ESC:
- output_data("\" ESC " + noquote);
- noquote = 2;
- break;
-
- case ENV_USERVAR:
- output_data("\" USERVAR " + noquote);
- noquote = 2;
- break;
-
- default:
- if (isprint(pointer[i]) && pointer[i] != '"') {
- if (noquote) {
- output_data("\"");
- noquote = 0;
- }
- output_data("%c", pointer[i]);
- } else {
- output_data("\" %03o " + noquote,
- pointer[i]);
- noquote = 2;
- }
- break;
- }
- }
- if (!noquote)
- output_data("\"");
- break;
- }
- }
- break;
-
-
-
- default:
- if (TELOPT_OK(pointer[0]))
- output_data("%s (unknown)", TELOPT(pointer[0]));
- else
- output_data("%d (unknown)", pointer[i]);
- for (i = 1; i < length; i++) {
- output_data(" %d", pointer[i]);
- }
- break;
- }
- output_data("\r\n");
-}
-
-/*
- * Dump a data buffer in hex and ascii to the output data stream.
- */
-void
-printdata(const char *tag, char *ptr, int cnt)
-{
- 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 */
- output_data("%s: ", tag);
- for (i = 0; i < 20 && cnt; i++) {
- output_data("%02x", *ptr);
- if (isprint(*ptr)) {
- xbuf[i] = *ptr;
- } else {
- xbuf[i] = '.';
- }
- if (i % 2) {
- output_data(" ");
- }
- cnt--;
- ptr++;
- }
- xbuf[i] = '\0';
- output_data(" %s\r\n", xbuf );
- }
-}
-#endif /* DIAGNOSTICS */
OpenPOWER on IntegriCloud