* Rebase patchset with debians one.
* Now uses cmake to build.
Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
Signed-off-by: Michael Tremer <michael.tremer@ipfire.org>
--- /dev/null
+Description: Source patches present in package 0.17-18woody3.
+ Multiple files are touched by this legacy patch. It has been
+ pruned to reproduce source package netkit-telnet_0.17-18.
+ .
+ Implement IPv6 support.
+ .
+ Read `/etc/telnetrc'.
+ .
+ Various buffer length errors.
+ .
+ Fix IAC+SB crashes due to format errors.
+ .
+ The server accepts numerical TOS together with `-S'.
+ .
+ Remote DOS hole, CAN-2004-0911, moved to a separate file.
+ .
+ Buffer overflow, CAN-2005-0469, moved to a separate file.
+
+Comment: Recovered from source netkit-telnet_0.17-18woody3.diff.gz.
+Author: Herbert Xu, Jason Gunthorpe
+Forwarded: no
+Last-Update: 2015-01-26
+
+--- a/telnet/commands.cc
++++ b/telnet/commands.cc
+@@ -86,10 +86,6 @@
+
+ #define HELPINDENT ((int) sizeof ("connect"))
+
+-#ifndef MAXHOSTNAMELEN
+-#define MAXHOSTNAMELEN 64
+-#endif MAXHOSTNAMELEN
+-
+ #if defined(HAS_IPPROTO_IP) && defined(IP_TOS)
+ int tos = -1;
+ #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */
+@@ -98,7 +94,7 @@
+
+
+ char *hostname;
+-static char _hostname[MAXHOSTNAMELEN];
++static char *_hostname;
+
+ //typedef int (*intrtn_t)(int argc, const char *argv[]);
+
+@@ -161,7 +157,7 @@
+ assert(argc>=1);
+ if (nargs>=0 && argc!=nargs+1) {
+ fprintf(stderr, "Wrong number of arguments for command.\n");
+- fprintf(stderr, "Try %s ? for help\n", argv[0]);
++ fprintf(stderr, "Try ? %s for help\n", argv[0]);
+ return 0; /* is this right? */
+ }
+ if (nargs==-2) {
+@@ -689,9 +685,9 @@
+ "print encryption debugging information" },
+ #endif
+
+- { "skiprc", "don't read ~/.telnetrc file",
++ { "skiprc", "don't read the telnetrc files",
+ NULL, &skiprc,
+- "read ~/.telnetrc file" },
++ "read the telnetrc files" },
+ { "binary",
+ "sending and receiving of binary data",
+ togbinary, NULL,
+@@ -1615,15 +1611,20 @@
+ #endif
+
+ int tn(int argc, const char *argv[]) {
+- register struct hostent *host = 0;
+ struct sockaddr_in sn;
+- struct servent *sp = 0;
+ char *srp = NULL;
+ int srlen;
+-
++ int family = 0;
+ const char *cmd, *volatile user = 0;
+ const char *portp = NULL;
+ char *hostp = NULL;
++ char *resolv_hostp;
++ struct addrinfo hints;
++ struct addrinfo *hostaddr = 0;
++ int res;
++ char name[NI_MAXHOST];
++ char service[NI_MAXSERV];
++ struct addrinfo *tmpaddr;
+
+ /* clear the socket address prior to use */
+ memset(&sn, 0, sizeof(sn));
+@@ -1632,6 +1633,10 @@
+ printf("?Already connected to %s\n", hostname);
+ return 0;
+ }
++ if (_hostname) {
++ delete[] _hostname;
++ _hostname = 0;
++ }
+ if (argc < 2) {
+ (void) strcpy(line, "open ");
+ printf("(to) ");
+@@ -1662,6 +1667,20 @@
+ autologin = 1;
+ continue;
+ }
++ if (strcmp(*argv, "-6") == 0) {
++ --argc; ++argv;
++#ifdef AF_INET6
++ family = AF_INET6;
++#else
++ puts("IPv6 unsupported");
++#endif
++ continue;
++ }
++ if (strcmp(*argv, "-4") == 0) {
++ --argc; ++argv;
++ family = AF_INET;
++ continue;
++ }
+ if (hostp == 0) {
+ /* this leaks memory - FIXME */
+ hostp = strdup(*argv++);
+@@ -1680,6 +1699,8 @@
+ if (hostp == 0)
+ goto usage;
+
++ resolv_hostp = hostp;
++
+ #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
+ if (hostp[0] == '@' || hostp[0] == '!') {
+ if ((hostname = strrchr(hostp, ':')) == NULL)
+@@ -1696,78 +1717,94 @@
+ } else {
+ sn.sin_addr.s_addr = temp;
+ sn.sin_family = AF_INET;
++ /*
++ * For source route we just make sure to get the IP given
++ * on the command line when looking up the port.
++ */
++ resolv_hostp = inet_ntoa(sn.sin_addr);
+ }
+ }
+- else {
+-#endif
+- if (inet_aton(hostp, &sn.sin_addr)) {
+- sn.sin_family = AF_INET;
+- strcpy(_hostname, hostp);
+- hostname = _hostname;
+- }
+- else {
+- host = gethostbyname(hostp);
+- if (host) {
+- sn.sin_family = host->h_addrtype;
+- if (host->h_length > (int)sizeof(sn.sin_addr)) {
+- host->h_length = sizeof(sn.sin_addr);
+- }
+-#if defined(h_addr) /* In 4.3, this is a #define */
+- memcpy((caddr_t)&sn.sin_addr,
+- host->h_addr_list[0], host->h_length);
+-#else /* defined(h_addr) */
+- memcpy((caddr_t)&sn.sin_addr, host->h_addr, host->h_length);
+-#endif /* defined(h_addr) */
+- strncpy(_hostname, host->h_name, sizeof(_hostname));
+- _hostname[sizeof(_hostname)-1] = '\0';
+- hostname = _hostname;
+- } else {
+- herror(hostp);
+- return 0;
+- }
+- }
+-#if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
+- }
+ #endif
++
++ /* User port or the default name of telnet. */
+ if (portp) {
+ if (*portp == '-') {
+ portp++;
+ telnetport = 1;
+ } else
+ telnetport = 0;
+- sn.sin_port = atoi(portp);
+- if (sn.sin_port == 0) {
+- sp = getservbyname(portp, "tcp");
+- if (sp)
+- sn.sin_port = sp->s_port;
+- else {
+- printf("%s: bad port number\n", portp);
+- return 0;
+- }
+- }
+- else {
+- sn.sin_port = htons(sn.sin_port);
+- }
+- }
++ }
+ else {
+- if (sp == 0) {
+- sp = getservbyname("telnet", "tcp");
+- if (sp == 0) {
+- fprintf(stderr, "telnet: tcp/telnet: unknown service\n");
+- return 0;
+- }
+- sn.sin_port = sp->s_port;
+- }
++ portp = "telnet";
+ telnetport = 1;
+ }
+- printf("Trying %s...\n", inet_ntoa(sn.sin_addr));
++
++ /* We only understand SOCK_STREAM sockets. */
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_socktype = SOCK_STREAM;
++ hints.ai_flags = AI_NUMERICHOST;
++ hints.ai_family = family;
++
++ /* Resolve both the host and service simultaneously. */
++ res = getaddrinfo(resolv_hostp, portp, &hints, &hostaddr);
++ if (res == EAI_NONAME) {
++ hints.ai_flags = AI_CANONNAME;
++ res = getaddrinfo(resolv_hostp, portp, &hints, &hostaddr);
++ } else if (hostaddr) {
++ hostaddr->ai_canonname = 0;
++ }
++ if (res || !hostaddr) {
++ fprintf(stderr, "telnet: could not resolve %s/%s: %s\n", resolv_hostp, portp, gai_strerror(res));
++ return 0;
++ }
++
++ /* Try to connect to every listed round robin IP. */
++ tmpaddr = hostaddr;
++ errno = 0;
+ do {
+- int x = nlink.connect(debug, host, &sn, srp, srlen, tos);
+- if (!x) return 0;
+- else if (x==1) continue;
++ int x;
++
++ if (!tmpaddr) {
++ if (errno)
++ perror("telnet: Unable to connect to remote host");
++ else
++ fputs("telnet: Unable to connect to remote host: "
++ "Bad port number\n", stderr);
++err:
++ freeaddrinfo(hostaddr);
++ return 0;
++ }
++
++ if (tmpaddr->ai_family == AF_UNIX) {
++nextaddr:
++ tmpaddr = tmpaddr->ai_next;
++ continue;
++ }
++
++ getnameinfo(tmpaddr->ai_addr, tmpaddr->ai_addrlen,
++ name, sizeof(name), service, sizeof(service),
++ NI_NUMERICHOST | NI_NUMERICSERV);
++
++ printf("Trying %s...\n", name);
++ x = nlink.connect(debug, tmpaddr, srp, srlen, tos);
++ if (!x)
++ goto err;
++ else if (x==1)
++ goto nextaddr;
++
+ connected++;
+ } while (connected == 0);
++ if (tmpaddr->ai_canonname == 0) {
++ hostname = new char[strlen(hostp)+1];
++ strcpy(hostname, hostp);
++ }
++ else {
++ hostname = new char[strlen(tmpaddr->ai_canonname)+1];
++ strcpy(hostname, tmpaddr->ai_canonname);
++ }
++
+ cmdrc(hostp, hostname);
++ freeaddrinfo(hostaddr);
+ if (autologin && user == NULL) {
+ struct passwd *pw;
+
+@@ -2013,31 +2050,16 @@
+ return 0;
+ }
+
+-static char *rcname = 0;
+-static char rcbuf[128];
+-
+-void cmdrc(const char *m1, const char *m2) {
++static void readrc(const char *m1, const char *m2, const char *rcname) {
+ FILE *rcfile;
+ int gotmachine = 0;
+ int l1 = strlen(m1);
+ int l2 = strlen(m2);
+- char m1save[64];
+-
+- if (skiprc) return;
++ char m1save[strlen(m1) + 1];
+
+ strcpy(m1save, m1);
+ m1 = m1save;
+
+- if (rcname == 0) {
+- rcname = getenv("HOME");
+- if (rcname)
+- strcpy(rcbuf, rcname);
+- else
+- rcbuf[0] = '\0';
+- strcat(rcbuf, "/.telnetrc");
+- rcname = rcbuf;
+- }
+-
+ rcfile = fopen(rcname, "r");
+ if (!rcfile) return;
+
+@@ -2073,6 +2095,25 @@
+ fclose(rcfile);
+ }
+
++void cmdrc(const char *m1, const char *m2) {
++ static char *rcname = 0;
++ static char rcbuf[128];
++
++ if (skiprc) return;
++
++ readrc(m1, m2, "/etc/telnetrc");
++ if (rcname == 0) {
++ rcname = getenv("HOME");
++ if (rcname)
++ strcpy(rcbuf, rcname);
++ else
++ rcbuf[0] = '\0';
++ strcat(rcbuf, "/.telnetrc");
++ rcname = rcbuf;
++ }
++ readrc(m1, m2, rcname);
++}
++
+ #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
+
+ /*
+--- a/telnet/main.cc
++++ b/telnet/main.cc
+@@ -45,7 +45,10 @@
+
+ #include <sys/types.h>
+ #include <getopt.h>
++#include <stdlib.h>
+ #include <string.h>
++#include <netdb.h>
++#include <errno.h>
+
+ #include "ring.h"
+ #include "externs.h"
+@@ -80,12 +83,13 @@
+ void usage(void) {
+ fprintf(stderr, "Usage: %s %s%s%s%s\n",
+ prompt,
+- " [-8] [-E] [-L] [-a] [-d] [-e char] [-l user] [-n tracefile]",
+- "\n\t",
++ "[-4] [-6] [-8] [-E] [-L] [-a] [-d] [-e char] [-l user]",
++ "\n\t[-n tracefile]",
+ #ifdef TN3270
++ "\n\t"
+ "[-noasynch] [-noasynctty] [-noasyncnet] [-r] [-t transcom]\n\t",
+ #else
+- "[-r] ",
++ " [-r] ",
+ #endif
+ "[host-name [port]]"
+ );
+@@ -103,6 +107,7 @@
+ extern int optind;
+ int ch;
+ char *user;
++ int family;
+
+ tninit(); /* Clear out things */
+ #if defined(CRAY) && !defined(__STDC__)
+@@ -117,12 +122,23 @@
+ prompt = argv[0];
+
+ user = NULL;
++ family = 0;
+
+ rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
+ autologin = -1;
+
+- while ((ch = getopt(argc, argv, "8EKLS:X:ade:k:l:n:rt:x")) != EOF) {
++ while ((ch = getopt(argc, argv, "468EKLS:X:ade:k:l:n:rt:x")) != EOF) {
+ switch(ch) {
++ case '4':
++ family = AF_INET;
++ break;
++ case '6':
++#ifdef AF_INET6
++ family = AF_INET6;
++#else
++ fputs("IPv6 unsupported\n", stderr);
++#endif
++ break;
+ case '8':
+ eight = 3; /* binary output and input */
+ break;
+@@ -137,19 +153,22 @@
+ break;
+ case 'S':
+ {
+-#ifdef HAS_GETTOS
+ extern int tos;
++ int num;
+
+- if ((tos = parsetos(optarg, "tcp")) < 0)
++#ifdef HAS_GETTOS
++ if ((num = parsetos(optarg, "tcp")) < 0) {
++#else
++ errno = 0;
++ num = strtol(optarg, 0, 0);
++ if (errno) {
++#endif
+ fprintf(stderr, "%s%s%s%s\n",
+ prompt, ": Bad TOS argument '",
+ optarg,
+ "; will try to use default TOS");
+-#else
+- fprintf(stderr,
+- "%s: Warning: -S ignored, no parsetos() support.\n",
+- prompt);
+-#endif
++ } else
++ tos = num;
+ }
+ break;
+ case 'X':
+@@ -233,6 +252,9 @@
+ *argp++ = "-l";
+ *argp++ = user;
+ }
++ if (family) {
++ *argp++ = family == AF_INET ? "-4" : "-6";
++ }
+ *argp++ = argv[0]; /* host */
+ if (argc > 1)
+ *argp++ = argv[1]; /* port */
+--- a/telnet/netlink.cc
++++ b/telnet/netlink.cc
+@@ -81,20 +81,23 @@
+ ::close(net);
+ }
+
+-int netlink::connect(int debug, struct hostent *host,
+- struct sockaddr_in *sn,
++int netlink::connect(int debug, struct addrinfo *addr,
+ char *srcroute, int srlen, int tos)
+ {
+ int on=1;
+
+- net = socket(AF_INET, SOCK_STREAM, 0);
++ net = socket(addr->ai_family, SOCK_STREAM, 0);
+ if (net < 0) {
++ if (errno == EAFNOSUPPORT)
++ return 1;
+ perror("telnet: socket");
+ return 0;
+ }
+
+ #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
+ if (srcroute) {
++ if (addr->ai_family != AF_INET)
++ fputs("Source route is only supported for IPv4\n", stderr);
+ if (setsockopt(net, IPPROTO_IP, IP_OPTIONS, srcroute, srlen) < 0)
+ perror("setsockopt (IP_OPTIONS)");
+ }
+@@ -108,7 +111,7 @@
+ #endif
+ if (tos < 0) tos = 020; /* Low Delay bit */
+ if (tos && (setsockopt(net, IPPROTO_IP, IP_TOS, &tos, sizeof(int)) < 0)
+- && (errno != ENOPROTOOPT))
++ && (errno != ENOPROTOOPT) && (errno != EOPNOTSUPP))
+ perror("telnet: setsockopt (IP_TOS) (ignored)");
+ #endif /* defined(IPPROTO_IP) && defined(IP_TOS) */
+
+@@ -116,27 +119,8 @@
+ perror("setsockopt (SO_DEBUG)");
+ }
+
+- if (::connect(net, (struct sockaddr *)sn, sizeof(*sn)) < 0) {
+-#if defined(h_addr) /* In 4.3, this is a #define */
+- if (host && host->h_addr_list[1]) {
+- int oerrno = errno;
+-
+- fprintf(stderr, "telnet: connect to address %s: ",
+- inet_ntoa(sn->sin_addr));
+- errno = oerrno;
+- perror(NULL);
+- host->h_addr_list++;
+- if (host->h_length > (int)sizeof(sn->sin_addr)) {
+- host->h_length = sizeof(sn->sin_addr);
+- }
+- memcpy(&sn->sin_addr, host->h_addr_list[0], host->h_length);
+- close(net);
+- return 1;
+- }
+-#endif /* defined(h_addr) */
+-
+- perror("telnet: Unable to connect to remote host");
+- return 0;
++ if (::connect(net, addr->ai_addr, addr->ai_addrlen) < 0) {
++ return 1;
+ }
+ return 2;
+ }
+--- a/telnet/netlink.h
++++ b/telnet/netlink.h
+@@ -6,8 +6,7 @@
+ netlink();
+ ~netlink();
+
+- int connect(int debug, struct hostent *host,
+- struct sockaddr_in *sin,
++ int connect(int debug, struct addrinfo *hostaddr,
+ char *srcroute, int srlen,
+ int tos);
+ void close(int doshutdown);
+--- a/telnet/network.cc
++++ b/telnet/network.cc
+@@ -40,6 +40,7 @@
+ #include <sys/types.h>
+ #include <sys/socket.h>
+ #include <sys/time.h>
++#include <stdlib.h>
+ #include <errno.h>
+ #include <arpa/telnet.h>
+
+--- a/telnet/ring.cc
++++ b/telnet/ring.cc
+@@ -165,7 +165,7 @@
+
+ /////////////////////////////////////////////////// supply //////////////
+
+-void ringbuf::printf(const char *format, ...) {
++void ringbuf::xprintf(const char *format, ...) {
+ char xbuf[256];
+ va_list ap;
+ va_start(ap, format);
+--- a/telnet/ring.h
++++ b/telnet/ring.h
+@@ -83,7 +83,7 @@
+ // manual supply
+ void putch(char c) { write(&c, 1); }
+ void write(const char *buffer, int ct);
+- void printf(const char *format, ...);
++ void xprintf(const char *format, ...);
+ int empty_count() { return size - count; }
+
+ // automatic supply
+--- a/telnet/sys_bsd.cc
++++ b/telnet/sys_bsd.cc
+@@ -189,18 +189,25 @@
+ * Various signal handling routines.
+ */
+
++#if 0
+ static void deadpeer(int /*sig*/) {
+ setcommandmode();
+ siglongjmp(peerdied, -1);
+ }
++#endif
+
+ static void intr(int /*sig*/) {
+ if (localchars) {
+ intp();
+ }
+ else {
++#if 0
+ setcommandmode();
+ siglongjmp(toplevel, -1);
++#else
++ signal(SIGINT, SIG_DFL);
++ raise(SIGINT);
++#endif
+ }
+ }
+
+@@ -214,6 +221,8 @@
+ sendabort();
+ return;
+ }
++ signal(SIGQUIT, SIG_DFL);
++ raise(SIGQUIT);
+ }
+
+ #ifdef SIGWINCH
+@@ -238,7 +247,9 @@
+ void sys_telnet_init(void) {
+ signal(SIGINT, intr);
+ signal(SIGQUIT, intr2);
++#if 0
+ signal(SIGPIPE, deadpeer);
++#endif
+ #ifdef SIGWINCH
+ signal(SIGWINCH, sendwin);
+ #endif
+--- a/telnet/telnet.1
++++ b/telnet/telnet.1
+@@ -42,7 +42,7 @@
+ protocol
+ .Sh SYNOPSIS
+ .Nm telnet
+-.Op Fl 8ELadr
++.Op Fl 468ELadr
+ .Op Fl S Ar tos
+ .Op Fl e Ar escapechar
+ .Op Fl l Ar user
+@@ -68,6 +68,10 @@
+ .Pp
+ Options:
+ .Bl -tag -width indent
++.It Fl 4
++Force IPv4 address resolution.
++.It Fl 6
++Force IPv6 address resolution.
+ .It Fl 8
+ Request 8-bit operation. This causes an attempt to negotiate the
+ .Dv TELNET BINARY
+@@ -474,17 +478,21 @@
+ placing a dash before the port number.
+ .Pp
+ After establishing a connection, any commands associated with the
+-remote host in the user's
++remote host in
++.Pa /etc/telnetrc
++and the user's
+ .Pa .telnetrc
+-file are executed.
++file are executed, in that order.
+ .Pp
+-The format of the .telnetrc file is as follows: Lines beginning with a
++The format of the telnetrc files is as follows: Lines beginning with a
+ #, and blank lines, are ignored. The rest of the file should consist
+ of hostnames and sequences of
+ .Nm telnet
+ commands to use with that host. Commands should be one per line,
+ indented by whitespace; lines beginning without whitespace are
+-interpreted as hostnames. Upon connecting to a particular host, the
++interpreted as hostnames. Lines beginning with the special hostname
++.Ql DEFAULT
++will apply to all hosts. Upon connecting to a particular host, the
+ commands associated with that host are executed.
+ .It Ic quit
+ Close any open session and exit
+@@ -1184,9 +1192,7 @@
+ When the skiprc toggle is
+ .Dv TRUE ,
+ .Tn telnet
+-does not read the
+-.Pa \&.telnetrc
+-file. The initial value for this toggle is
++does not read the telnetrc files. The initial value for this toggle is
+ .Dv FALSE.
+ .It Ic termdata
+ Toggles the display of all terminal data (in hexadecimal format).
+@@ -1239,7 +1245,9 @@
+ .Dv TELNET ENVIRON
+ option.
+ .Sh FILES
+-.Bl -tag -width ~/.telnetrc -compact
++.Bl -tag -width /etc/telnetrc -compact
++.It Pa /etc/telnetrc
++global telnet startup values
+ .It Pa ~/.telnetrc
+ user customized telnet startup values
+ .El
+--- a/telnet/telnet.cc
++++ b/telnet/telnet.cc
+@@ -646,7 +646,7 @@
+ mklist(termbuf, tname, termtypes);
+ next = 0;
+ }
+- if (next==termtypes.num()) next = 0;
++ if (next==termtypes.num()-1) next = 0;
+ return termtypes[next++];
+ }
+ /*
+@@ -681,7 +681,7 @@
+ }
+ #endif /* TN3270 */
+ name = gettermname();
+- netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
++ netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
+ TELQUAL_IS, name, IAC, SE);
+ }
+ break;
+@@ -693,7 +693,7 @@
+ if (SB_GET() == TELQUAL_SEND) {
+ long oospeed, iispeed;
+ TerminalSpeeds(&iispeed, &oospeed);
+- netoring.printf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
++ netoring.xprintf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
+ TELQUAL_IS, oospeed, iispeed, IAC, SE);
+ }
+ break;
+@@ -780,7 +780,7 @@
+ send_wont(TELOPT_XDISPLOC, 1);
+ break;
+ }
+- netoring.printf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
++ netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
+ TELQUAL_IS, dp, IAC, SE);
+ }
+ break;
+@@ -798,7 +798,7 @@
+ return;
+ }
+
+- netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
++ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ DONT, cmd[0], IAC, SE);
+ }
+
+@@ -815,7 +815,7 @@
+ /*@*/ printf("lm_do: no command!!!\n"); /* Should not happen... */
+ return;
+ }
+- netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
++ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ WONT, cmd[0], IAC, SE);
+ }
+
+@@ -838,7 +838,7 @@
+ k |= MODE_ACK;
+ }
+
+- netoring.printf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE,
++ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE,
+ k, IAC, SE);
+
+ setconnmode(0); /* set changed mode */
+@@ -933,11 +933,11 @@
+
+ void slc_import(int def) {
+ if (def) {
+- netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
++ netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE);
+ }
+ else {
+- netoring.printf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
++ netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE);
+ }
+ }
+@@ -1142,6 +1142,7 @@
+ }
+ }
+
++/* OPT_REPLY_SIZE must be a multiple of 2. */
+ #define OPT_REPLY_SIZE 256
+ unsigned char *opt_reply;
+ unsigned char *opt_replyp;
+@@ -1173,6 +1174,7 @@
+
+ void env_opt_add(const char *ep) {
+ const char *vp;
++ const unsigned char *tp;
+ unsigned char c;
+
+ if (opt_reply == NULL) /*XXX*/
+@@ -1185,11 +1187,12 @@
+ return;
+ }
+ vp = env_getvalue(ep, 1);
+- if (opt_replyp + (vp ? strlen(vp) : 0) + strlen(ep) + 6 > opt_replyend)
++ tp = opt_replyp + (vp ? strlen(vp) * 2 : 0) + strlen(ep) * 2 + 6;
++ if (tp > opt_replyend)
+ {
+ register int len;
+- opt_replyend += OPT_REPLY_SIZE;
+- len = opt_replyend - opt_reply;
++ len = ((tp - opt_reply) + OPT_REPLY_SIZE - 1) & ~(OPT_REPLY_SIZE - 1);
++ opt_replyend = opt_reply + len;
+ opt_reply = (unsigned char *)realloc(opt_reply, len);
+ if (opt_reply == NULL) {
+ /*@*/ printf("env_opt_add: realloc() failed!!!\n");
+--- a/telnet/terminal.cc
++++ b/telnet/terminal.cc
+@@ -45,6 +45,8 @@
+ #include <signal.h>
+ #include <errno.h>
+ #include <stdio.h>
++#include <string.h>
++#include <stdlib.h>
+
+ #include "ring.h"
+ #include "defines.h"
+--- a/telnet/utilities.cc
++++ b/telnet/utilities.cc
+@@ -47,6 +47,8 @@
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #include <ctype.h>
++#include <string.h>
++#include <stdlib.h>
+
+ #include "ring.h"
+ #include "defines.h"
+--- a/telnetd/authenc.c
++++ b/telnetd/authenc.c
+@@ -42,18 +42,6 @@
+ return(0);
+ }
+
+-void
+-net_encrypt()
+-{
+-#if defined(ENCRYPT)
+- char *s = (nclearto > nbackp) ? nclearto : nbackp;
+- if (s < nfrontp && encrypt_output) {
+- (*encrypt_output)((unsigned char *)s, nfrontp - s);
+- }
+- nclearto = nfrontp;
+-#endif
+-}
+-
+ int
+ telnet_spin()
+ {
+--- a/telnetd/defs.h
++++ b/telnetd/defs.h
+@@ -55,10 +55,11 @@
+ #include <fcntl.h>
+ #include <sys/file.h>
+ #include <sys/stat.h>
+-#include <sys/time.h>
++#include <time.h>
+ #include <sys/ioctl.h>
+ #include <netinet/in.h>
+ #include <arpa/telnet.h>
++#include <sys/uio.h>
+ #include <stdio.h>
+ #include <stdlib.h>
+ #include <signal.h>
+--- a/telnetd/ext.h
++++ b/telnetd/ext.h
+@@ -81,12 +81,11 @@
+ */
+ extern char ptyobuf[BUFSIZ+NETSLOP], *pfrontp, *pbackp;
+ extern char netibuf[BUFSIZ], *netip;
+-extern char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
+-extern char *neturg; /* one past last byte of urgent data */
+ extern int pcc, ncc;
++extern FILE *netfile;
+
+ /* printf into netobuf */
+-void netoprintf(const char *fmt, ...) __attribute((format (printf, 1, 2)));
++#define netoprintf(fmt, ...) fprintf(netfile, fmt, ## __VA_ARGS__)
+
+ extern int pty, net;
+ extern char *line;
+@@ -96,7 +95,7 @@
+ void add_slc(int, int, int);
+ void check_slc(void);
+ void change_slc(int, int, int);
+-void cleanup(int);
++void cleanup(int) __attribute__ ((noreturn));
+ void clientstat(int, int, int);
+ void copy_termbuf(char *, int);
+ void deferslc(void);
+@@ -106,8 +105,8 @@
+ void dooption(int);
+ void dontoption(int);
+ void edithost(const char *, const char *);
+-void fatal(int, const char *);
+-void fatalperror(int, const char *);
++void fatal(int, const char *) __attribute__ ((noreturn));
++void fatalperror(int, const char *) __attribute__ ((noreturn));
+ void get_slc_defaults(void);
+ void init_env(void);
+ void init_termbuf(void);
+@@ -115,6 +114,8 @@
+ void localstat(void);
+ void netclear(void);
+ void netflush(void);
++size_t netbuflen(int);
++void sendurg(const char *, size_t);
+
+ #ifdef DIAGNOSTICS
+ void printoption(const char *, int);
+@@ -182,10 +183,11 @@
+ void tty_tspeed(int);
+ void willoption(int);
+ void wontoption(int);
+-void writenet(unsigned char *, int);
++#define writenet(b, l) fwrite(b, 1, l, netfile)
++void netopen(void);
+
+ #if defined(ENCRYPT)
+-extern void (*encrypt_output)(unsigned char *, int);
++extern void (*encrypt_output)(const unsigned char *, int);
+ extern int (*decrypt_input)(int);
+ extern char *nclearto;
+ #endif
+--- a/telnetd/global.c
++++ b/telnetd/global.c
+@@ -87,11 +87,10 @@
+
+ char netibuf[BUFSIZ], *netip;
+
+-char netobuf[BUFSIZ+NETSLOP], *nfrontp, *nbackp;
+-char *neturg; /* one past last bye of urgent data */
+-
+ int pcc, ncc;
+
++FILE *netfile;
++
+ int pty, net;
+ int SYNCHing; /* we are in TELNET SYNCH mode */
+
+--- a/telnetd/issue.net.5
++++ b/telnetd/issue.net.5
+@@ -40,4 +40,4 @@
+ .Sh FILES
+ .Pa /etc/issue.net
+ .Sh "SEE ALSO"
+-.Xr telnetd 8
++.Xr in.telnetd 8
+--- a/telnetd/setproctitle.c
++++ b/telnetd/setproctitle.c
+@@ -139,7 +139,7 @@
+ (void) strcpy(Argv[0], buf);
+ p = &Argv[0][i];
+ while (p < LastArgv)
+- *p++ = ' ';
++ *p++ = '\0';
+ Argv[1] = NULL;
+ }
+
+--- a/telnetd/state.c
++++ b/telnetd/state.c
+@@ -179,6 +179,7 @@
+ */
+ case AO:
+ {
++ static const char msg[] = { IAC, DM };
+ DIAG(TD_OPTIONS, printoption("td: recv IAC", c));
+ ptyflush(); /* half-hearted */
+ init_termbuf();
+@@ -191,9 +192,7 @@
+ }
+
+ netclear(); /* clear buffer back */
+- *nfrontp++ = (char)IAC;
+- *nfrontp++ = (char)DM;
+- neturg = nfrontp-1; /* off by one XXX */
++ sendurg(msg, sizeof(msg));
+ DIAG(TD_OPTIONS, printoption("td: send IAC", DM));
+ break;
+ }
+--- a/telnetd/sys_term.c
++++ b/telnetd/sys_term.c
+@@ -41,8 +41,6 @@
+
+ #include "telnetd.h"
+ #include "pathnames.h"
+-#include "logout.h"
+-#include "logwtmp.h"
+
+ #if defined(__GLIBC__) && (__GLIBC__ >= 2)
+ /* mmm, nonstandard */
+@@ -681,7 +679,9 @@
+ memcpy(&argvfoo, &avs.argv, sizeof(argvfoo));
+ execv(loginprg, argvfoo);
+
++ openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+ syslog(LOG_ERR, "%s: %m\n", loginprg);
++ closelog();
+ fatalperror(net, loginprg);
+ }
+
+--- a/telnetd/telnetd.8
++++ b/telnetd/telnetd.8
+@@ -161,7 +161,7 @@
+ .It Fl L Ar loginprg
+ This option may be used to specify a different login program.
+ By default,
+-.Pa /bin/login
++.Pa /usr/sbin/telnetlogin
+ is used.
+ .It Fl n
+ Disable
+@@ -406,6 +406,7 @@
+ indicates a willingness to decrypt
+ the data stream.
+ .Xr issue.net 5 ) .
++.El
+ .Sh FILES
+ .Pa /etc/services ,
+ .Pa /etc/issue.net
+@@ -458,6 +459,7 @@
+ Telnet Environment Option Interoperability Issues
+ .It Cm RFC-1572
+ Telnet Environment Option
++.El
+ .Sh BUGS
+ Some
+ .Tn TELNET
+--- a/telnetd/telnetd.c
++++ b/telnetd/telnetd.c
+@@ -43,12 +43,16 @@
+
+ #include "../version.h"
+
++#include <sys/socket.h>
+ #include <netdb.h>
+ #include <termcap.h>
+ #include <netinet/in.h>
+ /* #include <netinet/ip.h> */ /* Don't think this is used at all here */
+ #include <arpa/inet.h>
+ #include <assert.h>
++#include <poll.h>
++#include <fcntl.h>
++#include <unistd.h>
+ #include "telnetd.h"
+ #include "pathnames.h"
+ #include "setproctitle.h"
+@@ -68,7 +72,7 @@
+ #define HAS_IPPROTO_IP
+ #endif
+
+-static void doit(struct sockaddr_in *who);
++static void doit(struct sockaddr *who, socklen_t who_len);
+ static int terminaltypeok(const char *s);
+
+ /*
+@@ -82,15 +86,119 @@
+
+ int debug = 0;
+ int keepalive = 1;
++#ifdef LOGIN_WRAPPER
++char *loginprg = LOGIN_WRAPPER;
++#else
+ char *loginprg = _PATH_LOGIN;
+-char *progname;
++#endif
+
+ extern void usage(void);
+
++static void
++wait_for_connection(const char *service)
++{
++ struct addrinfo hints;
++ struct addrinfo *res, *addr;
++ struct pollfd *fds, *fdp;
++ int nfds;
++ int i;
++ int error;
++ int on = 1;
++
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = PF_UNSPEC;
++ hints.ai_flags = AI_PASSIVE;
++ hints.ai_socktype = SOCK_STREAM;
++ error = getaddrinfo(NULL, service, &hints, &res);
++ if (error) {
++ char *p;
++ error = asprintf(&p, "getaddrinfo: %s\n", gai_strerror(error));
++ fatal(2, error >= 0 ? p : "");
++ }
++
++ for (addr = res, nfds = 0; addr; addr = addr->ai_next, nfds++)
++ ;
++ fds = malloc(sizeof(struct pollfd) * nfds);
++ for (addr = res, fdp = fds; addr; addr = addr->ai_next, fdp++) {
++ int s;
++
++ if (addr->ai_family == AF_LOCAL) {
++nextaddr:
++ fdp--;
++ nfds--;
++ continue;
++ }
++
++ s = socket(addr->ai_family, SOCK_STREAM, 0);
++ if (s < 0) {
++ if (errno == EAFNOSUPPORT || errno == EINVAL) {
++ goto nextaddr;
++ }
++ fatalperror(2, "socket");
++ }
++ if (setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on))) {
++ fatalperror(2, "setsockopt");
++ }
++ if (bind(s, addr->ai_addr, addr->ai_addrlen)) {
++#ifdef linux
++ if (fdp != fds && errno == EADDRINUSE) {
++ close(s);
++ goto nextaddr;
++ }
++#endif
++ fatalperror(2, "bind");
++ }
++ if (listen(s, 1)) {
++ fatalperror(2, "listen");
++ }
++ if (fcntl(s, F_SETFL, O_NONBLOCK)) {
++ fatalperror(2, "fcntl");
++ }
++
++ fdp->fd = s;
++ fdp->events = POLLIN;
++ }
++
++ freeaddrinfo(res);
++
++ while (1) {
++ if (poll(fds, nfds, -1) < 0) {
++ if (errno == EINTR) {
++ continue;
++ }
++ fatalperror(2, "poll");
++ }
++
++ for (i = 0, fdp = fds; i < nfds; i++, fdp++) {
++ int fd;
++
++ if (!(fdp->revents & POLLIN)) {
++ continue;
++ }
++
++ fd = accept(fdp->fd, 0, 0);
++ if (fd >= 0) {
++ dup2(fd, 0);
++ close(fd);
++ goto out;
++ }
++ if (errno != EAGAIN) {
++ fatalperror(2, "accept");
++ }
++ }
++ }
++
++out:
++ for (i = 0, fdp = fds; i < nfds; i++, fdp++) {
++ close(fdp->fd);
++ }
++ free(fds);
++}
++
+ int
+ main(int argc, char *argv[], char *env[])
+ {
+- struct sockaddr_in from;
++ struct sockaddr_storage from;
+ int on = 1;
+ socklen_t fromlen;
+ register int ch;
+@@ -103,12 +211,6 @@
+
+ pfrontp = pbackp = ptyobuf;
+ netip = netibuf;
+- nfrontp = nbackp = netobuf;
+-#if defined(ENCRYPT)
+- nclearto = 0;
+-#endif
+-
+- progname = *argv;
+
+ while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:L:")) != EOF) {
+ switch(ch) {
+@@ -249,74 +351,18 @@
+ argv += optind;
+
+ if (debug) {
+- int s, ns;
+- socklen_t foo;
+- struct servent *sp;
+- struct sockaddr_in sn;
+-
+- memset(&sn, 0, sizeof(sn));
+- sn.sin_family = AF_INET;
+-
+- if (argc > 1) {
+- usage();
+- /* NOTREACHED */
+- } else if (argc == 1) {
+- if ((sp = getservbyname(*argv, "tcp"))!=NULL) {
+- sn.sin_port = sp->s_port;
+- }
+- else {
+- int pt = atoi(*argv);
+- if (pt <= 0) {
+- fprintf(stderr, "telnetd: %s: bad port number\n",
+- *argv);
+- usage();
+- /* NOTREACHED */
+- }
+- sn.sin_port = htons(pt);
+- }
+- } else {
+- sp = getservbyname("telnet", "tcp");
+- if (sp == 0) {
+- fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");
+- exit(1);
++ if (argc > 1) {
++ usage();
++ /* NOTREACHED */
+ }
+- sn.sin_port = sp->s_port;
+- }
+
+- s = socket(AF_INET, SOCK_STREAM, 0);
+- if (s < 0) {
+- perror("telnetd: socket");;
+- exit(1);
+- }
+- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));
+- if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {
+- perror("bind");
+- exit(1);
+- }
+- if (listen(s, 1) < 0) {
+- perror("listen");
+- exit(1);
+- }
+- foo = sizeof(sn);
+- ns = accept(s, (struct sockaddr *)&sn, &foo);
+- if (ns < 0) {
+- perror("accept");
+- exit(1);
+- }
+- (void) dup2(ns, 0);
+- (void) close(ns);
+- (void) close(s);
+- } else if (argc > 0) {
+- usage();
+- /* NOT REACHED */
++ wait_for_connection((argc == 1) ? *argv : "telnet");
+ }
+
+ openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);
+ fromlen = sizeof (from);
+ if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {
+- fprintf(stderr, "%s: ", progname);
+- perror("getpeername");
+- _exit(1);
++ fatalperror(2, "getpeername");
+ }
+ if (keepalive &&
+ setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {
+@@ -339,7 +385,8 @@
+ }
+ #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */
+ net = 0;
+- doit(&from);
++ netopen();
++ doit((struct sockaddr *)&from, fromlen);
+ /* NOTREACHED */
+ return 0;
+ } /* end of main */
+@@ -354,7 +401,7 @@
+ #ifdef BFTPDAEMON
+ fprintf(stderr, " [-B]");
+ #endif
+- fprintf(stderr, " [-debug]");
++ fprintf(stderr, " [-debug port]");
+ #ifdef DIAGNOSTICS
+ fprintf(stderr, " [-D (options|report|exercise|netdata|ptydata)]\n\t");
+ #endif
+@@ -373,7 +420,7 @@
+ #ifdef AUTHENTICATE
+ fprintf(stderr, " [-X auth-type]");
+ #endif
+- fprintf(stderr, " [port]\n");
++ fprintf(stderr, "\n");
+ exit(1);
+ }
+
+@@ -608,54 +655,45 @@
+ * Get a pty, scan input lines.
+ */
+ static void
+-doit(struct sockaddr_in *who)
++doit(struct sockaddr *who, socklen_t who_len)
+ {
+ const char *host;
+- struct hostent *hp;
+ int level;
+ char user_name[256];
++ int i;
++ struct addrinfo hints, *res;
+
+ /*
+ * Find an available pty to use.
+ */
+ pty = getpty();
+ if (pty < 0)
+- fatal(net, "All network ports in use");
++ fatalperror(net, "getpty");
+
+ /* get name of connected client */
+- hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),
+- who->sin_family);
+- if (hp)
+- host = hp->h_name;
+- else
+- host = inet_ntoa(who->sin_addr);
+-
+- /*
+- * We must make a copy because Kerberos is probably going
+- * to also do a gethost* and overwrite the static data...
+- */
+- {
+- int i;
+- strncpy(remote_host_name, host, sizeof(remote_host_name)-1);
+- remote_host_name[sizeof(remote_host_name)-1] = 0;
+-
+- /* Disallow funnies. */
+- for (i=0; remote_host_name[i]; i++) {
+- if (remote_host_name[i]<=32 || remote_host_name[i]>126)
+- remote_host_name[i] = '?';
+- }
++ if (getnameinfo(who, who_len, remote_host_name,
++ sizeof(remote_host_name), 0, 0, 0)) {
++ syslog(LOG_ERR, "doit: getnameinfo: %m");
++ *remote_host_name = 0;
++ }
++
++ /* Disallow funnies. */
++ for (i=0; remote_host_name[i]; i++) {
++ if (remote_host_name[i]<=32 || remote_host_name[i]>126)
++ remote_host_name[i] = '?';
+ }
+ host = remote_host_name;
+
+ /* Get local host name */
+- {
+- struct hostent *h;
+- gethostname(host_name, sizeof(host_name));
+- h = gethostbyname(host_name);
+- if (h) {
+- strncpy(host_name, h->h_name, sizeof(host_name));
+- host_name[sizeof(host_name)-1] = 0;
+- }
++ gethostname(host_name, sizeof(host_name));
++ memset(&hints, 0, sizeof(hints));
++ hints.ai_family = PF_UNSPEC;
++ hints.ai_flags = AI_CANONNAME;
++ if ((i = getaddrinfo(host_name, 0, &hints, &res)))
++ syslog(LOG_WARNING, "doit: getaddrinfo: %s", gai_strerror(i));
++ else {
++ strncpy(host_name, res->ai_canonname, sizeof(host_name)-1);
++ host_name[sizeof(host_name)-1] = 0;
+ }
+
+ #if defined(AUTHENTICATE) || defined(ENCRYPT)
+@@ -892,7 +930,7 @@
+ * Never look for input if there's still
+ * stuff in the corresponding output buffer
+ */
+- if (nfrontp - nbackp || pcc > 0) {
++ if (netbuflen(1) || pcc > 0) {
+ FD_SET(f, &obits);
+ if (f >= hifd) hifd = f+1;
+ }
+@@ -1033,6 +1071,7 @@
+ }
+ #endif /* LINEMODE */
+ if (ptyibuf[0] & TIOCPKT_FLUSHWRITE) {
++ static const char msg[] = { IAC, DM };
+ netclear(); /* clear buffer back */
+ #ifndef NO_URGENT
+ /*
+@@ -1041,8 +1080,7 @@
+ * royally if we send them urgent
+ * mode data.
+ */
+- netoprintf("%c%c", IAC, DM);
+- neturg = nfrontp-1; /* off by one XXX */
++ sendurg(msg, sizeof(msg));
+ #endif
+ }
+ if (his_state_is_will(TELOPT_LFLOW) &&
+@@ -1058,23 +1096,21 @@
+ }
+ }
+
+- while (pcc > 0) {
+- if ((&netobuf[BUFSIZ] - nfrontp) < 2)
+- break;
++ while (pcc > 0 && !netbuflen(0)) {
+ c = *ptyip++ & 0377, pcc--;
+ if (c == IAC)
+- *nfrontp++ = c;
+- *nfrontp++ = c;
++ putc(c, netfile);
++ putc(c, netfile);
+ if ((c == '\r' ) && (my_state_is_wont(TELOPT_BINARY))) {
+ if (pcc > 0 && ((*ptyip & 0377) == '\n')) {
+- *nfrontp++ = *ptyip++ & 0377;
++ putc(*ptyip++ & 0377, netfile);
+ pcc--;
+ }
+- else *nfrontp++ = '\0';
++ else putc('\0', netfile);
+ }
+ }
+
+- if (FD_ISSET(f, &obits) && (nfrontp - nbackp) > 0)
++ if (FD_ISSET(f, &obits))
+ netflush();
+ if (ncc > 0)
+ telrcv();
+--- a/telnetd/utility.c
++++ b/telnetd/utility.c
+@@ -41,6 +41,7 @@
+
+ #include <stdarg.h>
+ #include <sys/utsname.h>
++#include <sys/time.h>
+
+ #ifdef AUTHENTICATE
+ #include <libtelnet/auth.h>
+@@ -48,34 +49,19 @@
+
+ #include "telnetd.h"
+
+-/*
+- * utility functions performing io related tasks
+- */
+-
+-void
+-netoprintf(const char *fmt, ...)
+-{
+- int len, maxsize;
+- va_list ap;
+- int done=0;
+-
+- while (!done) {
+- maxsize = sizeof(netobuf) - (nfrontp - netobuf);
+-
+- va_start(ap, fmt);
+- len = vsnprintf(nfrontp, maxsize, fmt, ap);
+- va_end(ap);
+-
+- if (len<0 || len==maxsize) {
+- /* didn't fit */
+- netflush();
+- }
+- else {
+- done = 1;
+- }
+- }
+- nfrontp += len;
+-}
++struct buflist {
++ struct buflist *next;
++ char *buf;
++ size_t len;
++};
++
++static struct buflist head = { next: &head, buf: 0, len: 0 };
++static struct buflist *tail = &head;
++static size_t skip;
++static int trailing;
++static size_t listlen;
++static int doclear;
++static struct buflist *urg;
+
+ /*
+ * ttloop
+@@ -92,9 +78,7 @@
+
+ DIAG(TD_REPORT, netoprintf("td: ttloop\r\n"););
+
+- if (nfrontp-nbackp) {
+- netflush();
+- }
++ netflush();
+ ncc = read(net, netibuf, sizeof(netibuf));
+ if (ncc < 0) {
+ syslog(LOG_INFO, "ttloop: read: %m\n");
+@@ -168,33 +152,64 @@
+ * 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 */
+- {
+- register char *look = current+2;
+-
+- for (;;) {
+- if ((*look++&0xff) == IAC) {
+- if ((*look++&0xff) == SE) {
+- return look;
+- }
++const char *
++nextitem(
++ const unsigned char *current, const unsigned char *end,
++ const unsigned char *next, const unsigned char *nextend
++) {
++ if (*current++ != IAC) {
++ while (current < end && *current++ != IAC)
++ ;
++ goto out;
++ }
++
++ if (current >= end) {
++ current = next;
++ if (!current) {
++ return 0;
+ }
+- }
++ end = nextend;
++ next = 0;
+ }
+- default:
+- return current+2;
+- }
++
++ switch (*current++) {
++ case DO:
++ case DONT:
++ case WILL:
++ case WONT:
++ current++;
++ break;
++ case SB: /* loop forever looking for the SE */
++ for (;;) {
++ int iac;
++
++ while (iac = 0, current < end) {
++ if (*current++ == IAC) {
++ if (current >= end) {
++ iac = 1;
++ break;
++ }
++iac:
++ if (*current++ == SE) {
++ goto out;
++ }
++ }
++ }
++
++ current = next;
++ if (!current) {
++ return 0;
++ }
++ end = nextend;
++ next = 0;
++ if (iac) {
++ goto iac;
++ }
++ }
++ }
++
++out:
++ return next ? next + (current - end) : current;
+ } /* end of nextitem */
+
+
+@@ -216,145 +231,102 @@
+ */
+ void netclear(void)
+ {
+- register char *thisitem, *next;
+- char *good;
+-#define wewant(p) ((nfrontp > p) && ((*p&0xff) == IAC) && \
+- ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL))
++ doclear++;
++ netflush();
++ doclear--;
++} /* end of netclear */
+
+-#if defined(ENCRYPT)
+- thisitem = nclearto > netobuf ? nclearto : netobuf;
+-#else
+- thisitem = netobuf;
+-#endif
++static void
++netwritebuf(void)
++{
++ struct iovec *vector;
++ struct iovec *v;
++ struct buflist *lp;
++ ssize_t n;
++ size_t len;
++ int ltrailing = trailing;
+
+- while ((next = nextitem(thisitem)) <= nbackp) {
+- thisitem = next;
+- }
++ vector = malloc(listlen * sizeof(struct iovec));
++ if (!vector) {
++ return;
++ }
+
+- /* Now, thisitem is first before/at boundary. */
++ len = listlen - (doclear & ltrailing);
++ v = vector;
++ lp = head.next;
++ while (lp != &head) {
++ if (lp == urg) {
++ len = v - vector;
++ if (!len) {
++ n = send(net, lp->buf, 1, MSG_OOB);
++ if (n > 0) {
++ urg = 0;
++ }
++ goto epi;
++ }
++ break;
++ }
++ v->iov_base = lp->buf;
++ v->iov_len = lp->len;
++ v++;
++ lp = lp->next;
++ }
+
+-#if defined(ENCRYPT)
+- good = nclearto > netobuf ? nclearto : netobuf;
+-#else
+- good = netobuf; /* where the good bytes go */
+-#endif
++ vector->iov_base = (char *)vector->iov_base + skip;
++ vector->iov_len -= skip;
++
++ n = writev(net, vector, len);
+
+- while (nfrontp > thisitem) {
+- if (wewant(thisitem)) {
+- int length;
+-
+- next = thisitem;
+- do {
+- next = nextitem(next);
+- } while (wewant(next) && (nfrontp > next));
+- length = next-thisitem;
+- bcopy(thisitem, good, length);
+- good += length;
+- thisitem = next;
+- } else {
+- thisitem = nextitem(thisitem);
++epi:
++ free(vector);
++
++ if (n < 0) {
++ if (errno != EWOULDBLOCK && errno != EINTR)
++ cleanup(0);
++ return;
+ }
+- }
+
+- nbackp = netobuf;
+- nfrontp = good; /* next byte to be sent */
+- neturg = 0;
+-} /* end of netclear */
++ len = n + skip;
+
+-/*
+- * netflush
+- * Send as much data as possible to the network,
+- * handling requests for urgent data.
+- */
+-extern int not42;
+-void
+-netflush(void)
+-{
+- int n;
++ lp = head.next;
++ while (lp->len <= len) {
++ if (lp == tail && ltrailing) {
++ break;
++ }
+
+- if ((n = nfrontp - nbackp) > 0) {
+- DIAG(TD_REPORT,
+- { netoprintf("td: netflush %d chars\r\n", n);
+- n = nfrontp - nbackp; /* update count */
+- });
+-#if defined(ENCRYPT)
+- if (encrypt_output) {
+- char *s = nclearto ? nclearto : nbackp;
+- if (nfrontp - s > 0) {
+- (*encrypt_output)((unsigned char *)s, nfrontp-s);
+- nclearto = nfrontp;
++ len -= lp->len;
++
++ head.next = lp->next;
++ listlen--;
++ free(lp->buf);
++ free(lp);
++
++ lp = head.next;
++ if (lp == &head) {
++ tail = &head;
++ break;
+ }
+ }
+-#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 < 0) {
+- if (errno == EWOULDBLOCK || errno == EINTR)
+- return;
+- cleanup(0);
+- }
+- nbackp += n;
+-#if defined(ENCRYPT)
+- if (nbackp > nclearto)
+- nclearto = 0;
+-#endif
+- if (nbackp >= neturg) {
+- neturg = 0;
+- }
+- if (nbackp == nfrontp) {
+- nbackp = nfrontp = netobuf;
+-#if defined(ENCRYPT)
+- nclearto = 0;
+-#endif
+- }
+- return;
+-} /* end of netflush */
+
++ skip = len;
++}
+
+ /*
+- * writenet
+- *
+- * Just a handy little function to write a bit of raw data to the net.
+- * It will force a transmit of the buffer if necessary
+- *
+- * arguments
+- * ptr - A pointer to a character string to write
+- * len - How many bytes to write
++ * netflush
++ * Send as much data as possible to the network,
++ * handling requests for urgent data.
+ */
+-void writenet(register unsigned char *ptr, register int len)
++void
++netflush(void)
+ {
+- /* flush buffer if no room for new data) */
+- if ((&netobuf[BUFSIZ] - nfrontp) < len) {
+- /* if this fails, don't worry, buffer is a little big */
+- netflush();
++ if (fflush(netfile)) {
++ /* out of memory? */
++ cleanup(0);
+ }
+-
+- bcopy(ptr, nfrontp, len);
+- nfrontp += len;
+-
+-} /* end of writenet */
++ if (listlen) {
++ netwritebuf();
++ }
++}
+
+
+ /*
+@@ -391,18 +363,30 @@
+ fatal(f, buf);
+ }
+
+-char editedhost[32];
++char *editedhost;
+ struct utsname kerninfo;
+
+ void
+ edithost(const char *pat, const char *host)
+ {
+- char *res = editedhost;
++ char *res;
+
+ uname(&kerninfo);
+
+ if (!pat)
+ pat = "";
++
++ res = realloc(editedhost, strlen(pat) + strlen(host) + 1);
++ if (!res) {
++ if (editedhost) {
++ free(editedhost);
++ editedhost = 0;
++ }
++ fprintf(stderr, "edithost: Out of memory\n");
++ return;
++ }
++ editedhost = res;
++
+ while (*pat) {
+ switch (*pat) {
+
+@@ -420,18 +404,12 @@
+ *res++ = *pat;
+ break;
+ }
+- if (res == &editedhost[sizeof editedhost - 1]) {
+- *res = '\0';
+- return;
+- }
+ pat++;
+ }
+ if (*host)
+- (void) strncpy(res, host,
+- sizeof editedhost - (res - editedhost) -1);
++ (void) strcpy(res, host);
+ else
+ *res = '\0';
+- editedhost[sizeof editedhost - 1] = '\0';
+ }
+
+ static char *putlocation;
+@@ -475,7 +453,9 @@
+ break;
+
+ case 'h':
+- putstr(editedhost);
++ if (editedhost) {
++ putstr(editedhost);
++ }
+ break;
+
+ case 'd':
+@@ -1118,11 +1098,6 @@
+ 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 */
+ netoprintf("%s: ", tag);
+ for (i = 0; i < 20 && cnt; i++) {
+@@ -1143,3 +1118,154 @@
+ }
+ }
+ #endif /* DIAGNOSTICS */
++
++static struct buflist *
++addbuf(const char *buf, size_t len)
++{
++ struct buflist *bufl;
++
++ bufl = malloc(sizeof(struct buflist));
++ if (!bufl) {
++ return 0;
++ }
++ bufl->next = tail->next;
++ bufl->buf = malloc(len);
++ if (!bufl->buf) {
++ free(bufl);
++ return 0;
++ }
++ bufl->len = len;
++
++ tail = tail->next = bufl;
++ listlen++;
++
++ memcpy(bufl->buf, buf, len);
++ return bufl;
++}
++
++static ssize_t
++netwrite(void *cookie, const char *buf, size_t len)
++{
++ size_t ret;
++ const char *const end = buf + len;
++ int ltrailing = trailing;
++ int ldoclear = doclear;
++
++#define wewant(p) ((*p&0xff) == IAC) && \
++ ((*(p+1)&0xff) != EC) && ((*(p+1)&0xff) != EL)
++
++ ret = 0;
++
++ if (ltrailing) {
++ const char *p;
++ size_t l;
++ size_t m = tail->len;
++
++ p = nextitem(tail->buf, tail->buf + tail->len, buf, end);
++ ltrailing = !p;
++ if (ltrailing) {
++ p = end;
++ }
++
++ l = p - buf;
++ tail->len += l;
++ tail->buf = realloc(tail->buf, tail->len);
++ if (!tail->buf) {
++ return -1;
++ }
++
++ memcpy(tail->buf + m, buf, l);
++ buf += l;
++ len -= l;
++ ret += l;
++ trailing = ltrailing;
++ }
++
++ if (ldoclear) {
++ struct buflist *lpprev;
++
++ skip = 0;
++ lpprev = &head;
++ for (;;) {
++ struct buflist *lp;
++
++ lp = lpprev->next;
++
++ if (lp == &head) {
++ tail = lpprev;
++ break;
++ }
++
++ if (lp == tail && ltrailing) {
++ break;
++ }
++
++ if (!wewant(lp->buf)) {
++ lpprev->next = lp->next;
++ listlen--;
++ free(lp->buf);
++ free(lp);
++ } else {
++ lpprev = lp;
++ }
++ }
++ }
++
++ while (len) {
++ const char *p;
++ size_t l;
++
++ p = nextitem(buf, end, 0, 0);
++ ltrailing = !p;
++ if (ltrailing) {
++ p = end;
++ } else if (ldoclear) {
++ if (!wewant(buf)) {
++ l = p - buf;
++ goto cont;
++ }
++ }
++
++ l = p - buf;
++ if (!addbuf(buf, l)) {
++ return ret ? ret : -1;
++ }
++ trailing = ltrailing;
++
++cont:
++ buf += l;
++ len -= l;
++ ret += l;
++ }
++
++ netwritebuf();
++ return ret;
++}
++
++void
++netopen() {
++ static const cookie_io_functions_t funcs = {
++ read: 0, write: netwrite, seek: 0, close: 0
++ };
++
++ netfile = fopencookie(0, "w", funcs);
++}
++
++extern int not42;
++void
++sendurg(const char *buf, size_t len) {
++ if (!not42) {
++ fwrite(buf, 1, len, netfile);
++ return;
++ }
++
++ urg = addbuf(buf, len);
++}
++
++size_t
++netbuflen(int flush) {
++ if (flush) {
++ netflush();
++ }
++ return listlen != 1 ? listlen : tail->len - skip;
++}
+--- a/telnetlogin/telnetlogin.8
++++ b/telnetlogin/telnetlogin.8
+@@ -40,6 +40,7 @@
+ .Nm telnetlogin
+ .Op Fl h Ar host
+ .Op Fl p
++.Op Ar username
+ .Sh DESCRIPTION
+ .Nm telnetlogin
+ is a setuid wrapper that runs
+@@ -62,10 +63,8 @@
+ .Nm telnetd 8
+ normally provides them in.
+ .Nm telnetlogin
+-also only accepts the environment variables
++also does sanity checks on the environment variables
+ .Ev TERM ,
+-.Ev DISPLAY ,
+-.Ev POSIXLY_CORRECT ,
+ and
+ .Ev REMOTEHOST .
+ It also insists that the standard input, output, and error streams are
+@@ -83,7 +82,7 @@
+ .Nm telnetlogin
+ does not permit the
+ .Fl f
+-option to login, and does not permit passing a username, so will not
++option to login, so will not
+ work with telnetds that perform authentication via Kerberos or SSL.
+ .Pp
+ THIS IS PRESENTLY EXPERIMENTAL CODE; USE WITH CAUTION.
+--- a/telnetlogin/telnetlogin.c
++++ b/telnetlogin/telnetlogin.c
+@@ -51,20 +51,24 @@
+ #include <string.h>
+ #include <stdarg.h>
+ #include <stdio.h>
++#include <syslog.h>
+
+ #ifndef _PATH_LOGIN
+ #define _PATH_LOGIN "/bin/login"
+ #endif
+
++extern char **environ;
++
+ static const char *remhost = NULL;
+
++static void die(const char *, ...) __attribute__ ((noreturn));
++
+ static void die(const char *fmt, ...) {
+ va_list ap;
+- fprintf(stderr, "telnetlogin: ");
++ openlog("telnetlogin", LOG_PID, LOG_AUTHPRIV);
+ va_start(ap, fmt);
+- vfprintf(stderr, fmt, ap);
++ vsyslog(LOG_CRIT, fmt, ap);
+ va_end(ap);
+- fprintf(stderr, "\n");
+ exit(1);
+ }
+
+@@ -86,41 +90,6 @@
+ return 0;
+ }
+
+-static int check_display(char *disp) {
+- char *colon, *s;
+- struct hostent *hp;
+- int num;
+-
+- colon = strchr(disp, ':');
+- if (!colon) return -1;
+- *colon = 0; /* temporarily */
+-
+- if (check_a_hostname(disp)) return -1;
+-
+- hp = gethostbyname(disp);
+- if (!hp) return -1;
+-
+- *colon = ':';
+- s = colon+1;
+- while (*s && isdigit(*s)) s++;
+- if (*s) {
+- if (*s!='.') return -1;
+- s++;
+- while (*s && isdigit(*s)) s++;
+- }
+- if (*s) return -1;
+-
+- num = atoi(colon+1);
+- if (num<0 || num>99) return -1;
+-
+- return 0;
+-}
+-
+-static int check_posixly_correct(char *val) {
+- if (strlen(val)==0 || !strcmp(val, "1")) return 0;
+- return -1;
+-}
+-
+ static int check_remotehost(char *val) {
+ if (check_a_hostname(val)) return -1;
+ if (remhost && strcmp(val, remhost)) return -1;
+@@ -132,8 +101,6 @@
+ int (*validator)(char *);
+ } legal_envs[] = {
+ { "TERM", check_term },
+- { "DISPLAY", check_display },
+- { "POSIXLY_CORRECT", check_posixly_correct },
+ { "REMOTEHOST", check_remotehost },
+ { NULL, NULL }
+ };
+@@ -166,10 +133,7 @@
+ static char argv0[] = "login";
+ int argn, i, j;
+ const char *rh = NULL;
+- char **envs = __environ;
+-
+- /* make as sure as possible no library routines or anything can use it */
+- __environ = NULL;
++ char **envs = environ;
+
+ /* first, make sure our stdin/stdout/stderr are aimed somewhere */
+ i = open("/", O_RDONLY);
+@@ -194,6 +158,9 @@
+ if (argn < argc && !strcmp(argv[argn], "-p")) {
+ argn++;
+ }
++ if (argn < argc && argv[argn][0] != '-') {
++ argn++;
++ }
+ if (argn < argc) die("Illegal args: too many args");
+ argv[0] = argv0;
+
+@@ -201,21 +168,22 @@
+ if (envs) for (i=0; envs[i]; i++) {
+ char *testenv = envs[i];
+ size_t testlen = strlen(testenv);
+- int ok = 0;
+- for (j=0; legal_envs[j].name && !ok; j++) {
++ for (j=0; legal_envs[j].name; j++) {
+ const char *okenv = legal_envs[j].name;
+ size_t oklen = strlen(okenv);
++ int sign;
+
+ if (testlen < oklen) continue;
+ if (testenv[oklen]!='=') continue;
+- if (memcmp(testenv, okenv, oklen)) continue;
++ if ((sign = memcmp(testenv, okenv, oklen)) < 0) {
++ continue;
++ } else if (sign > 0) {
++ break;
++ }
+ if (legal_envs[j].validator(testenv+oklen+1)) {
+ die("Invalid environment: bad value for %s", okenv);
+ }
+- ok = 1;
+- }
+- if (!ok) {
+- die("Illegal environment: forbidden variable");
++ break;
+ }
+ }
+
+@@ -234,6 +202,13 @@
+ * but, should we insist that ruid==nobody?
+ */
+
++#ifdef debian
++ /*
++ * Debian's /bin/login doesn't work properly unless we're really root.
++ */
++ setuid(0);
++#endif
++
+ /*
+ * don't do anything with limits, itimers, or process priority either
+ */
--- /dev/null
+Description: Incremental patches from 0.17-18 to 0.17-24.
+ A large set of mixed code patches on top of upstream's source.
+ It has been pruned to reproduce the step from source package
+ netkit-telnet_0.17-18 to netkit-telnet_0.17-24.
+ .
+ Support also Hurd.
+ [telnetd/sys_term.c, telnetd/ext.h]
+ .
+ Do not reset access mode and owner of TTY when client ends the session.
+ [telnetd/sys_term.c (cleanup)]
+ .
+ Path of telnetlogin.
+ [telnetd/telnetd.8]
+ .
+ Adjust 8-bit mode to be without mandatory binary option.
+ A new command line switch `-7' is added to telnet.
+ [telnet/main.cc, telnet/telnet.cc, telnet/terminal.cc,
+ telnet/defines.h, telnet/externs.h]
+ .
+ Allow telnetrc files to specify a port in addition to host name.
+ [telnet/commands.cc, telnet/proto.h, telnet/telnet.1]
+ .
+ Disable 8-bit mode of client if parity bit is enabled.
+ [telnet/main.cc]
+ .
+ Remove obsolete compiler warnings, and disable trigraph warning.
+ Protect tokens ifter #endif.
+ [configure, telnet/terminal.cc]
+ .
+ Support option `-b' in client.
+ [telnet/commands.cc, telnet/main.cc, telnet/netlink.cc,
+ telnet/netlink.h, telnet/telnet.1]
+ .
+ Accept numeric telnet options.
+ [telnet/command.cc]
+ .
+ Buffer overflow due to $HOME, moved to a separate file.
+ .
+ Remote DOS hole, CAN-2004-0911, moved to a separate file.
+ .
+ Buffer overflow, CAN-2005-0469, moved to a separate file.
+
+Comment: interdiff netkit-telnet_0.17-{18woody3,29}.diff
+Author: Herbert Xu, Robert Millan
+Bug-Debian: http://bugs.debian.org/149325
+ http://bugs.debian.org/150812
+ http://bugs.debian.org/144921
+ http://bugs.debian.org/194736
+ http://bugs.debian.org/203544
+ http://bugs.debian.org/242018
+Forwarded: no
+Last-Update: 2015-01-27
+
+--- a/telnet/commands.cc
++++ b/telnet/commands.cc
+@@ -476,6 +476,7 @@
+ int send_tncmd(int (*func)(int, int), const char *cmd, const char *name) {
+ char **cpp;
+ extern char *telopts[];
++ long opt;
+
+ if (isprefix(name, "help") || isprefix(name, "?")) {
+ register int col, len;
+@@ -502,16 +503,23 @@
+ name, cmd);
+ return 0;
+ }
++
++ opt = cpp - telopts;
+ if (cpp == 0) {
+- fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
++ char *end;
++
++ opt = strtol(name, &end, 10);
++ if (*end || opt < 0 || opt > 255) {
++ fprintf(stderr, "'%s': unknown argument ('send %s ?' for help).\n",
+ name, cmd);
+- return 0;
++ return 0;
++ }
+ }
+ if (!connected) {
+ printf("?Need to be connected first.\n");
+ return 0;
+ }
+- (*func)(cpp - telopts, 1);
++ (*func)(opt, 1);
+ return 1;
+ }
+
+@@ -1615,7 +1623,7 @@
+ char *srp = NULL;
+ int srlen;
+ int family = 0;
+- const char *cmd, *volatile user = 0;
++ const char *cmd, *volatile user = 0, *srchostp = 0;
+ const char *portp = NULL;
+ char *hostp = NULL;
+ char *resolv_hostp;
+@@ -1662,6 +1670,14 @@
+ --argc;
+ continue;
+ }
++ if (strcmp(*argv, "-b") == 0) {
++ --argc; ++argv;
++ if (argc == 0)
++ goto usage;
++ srchostp = *argv++;
++ --argc;
++ continue;
++ }
+ if (strcmp(*argv, "-a") == 0) {
+ --argc; ++argv;
+ autologin = 1;
+@@ -1744,6 +1760,20 @@
+ hints.ai_socktype = SOCK_STREAM;
+ hints.ai_flags = AI_NUMERICHOST;
+ hints.ai_family = family;
++
++ if (srchostp) {
++ res = getaddrinfo(srchostp, "0", &hints, &hostaddr);
++ if (res) {
++ fprintf(stderr, "telnet: could not resolve %s: %s\n", srchostp,
++ gai_strerror(res));
++ return 0;
++ }
++ hints.ai_family = hostaddr->ai_family;
++ res = nlink.bind(hostaddr);
++ freeaddrinfo(hostaddr);
++ if (res < 0)
++ return 0;
++ }
+
+ /* Resolve both the host and service simultaneously. */
+ res = getaddrinfo(resolv_hostp, portp, &hints, &hostaddr);
+@@ -1803,7 +1833,7 @@
+ strcpy(hostname, tmpaddr->ai_canonname);
+ }
+
+- cmdrc(hostp, hostname);
++ cmdrc(hostp, hostname, portp);
+ freeaddrinfo(hostaddr);
+ if (autologin && user == NULL) {
+ struct passwd *pw;
+@@ -2050,15 +2080,21 @@
+ return 0;
+ }
+
+-static void readrc(const char *m1, const char *m2, const char *rcname) {
++static void readrc(const char *m1, const char *m2, const char *port,
++ const char *rcname)
++{
+ FILE *rcfile;
+ int gotmachine = 0;
+ int l1 = strlen(m1);
+ int l2 = strlen(m2);
+- char m1save[strlen(m1) + 1];
++ int lport = strlen(port);
++ char m1save[l1 + 1];
++ char portsave[lport + 1];
+
+ strcpy(m1save, m1);
+ m1 = m1save;
++ strcpy(portsave, port);
++ port = portsave;
+
+ rcfile = fopen(rcname, "r");
+ if (!rcfile) return;
+@@ -2083,6 +2119,13 @@
+ strncpy(line, &line[7], sizeof(line) - 7);
+ else
+ continue;
++
++ if (line[0] == ':') {
++ if (!strncasecmp(&line[1], port, lport))
++ continue;
++ strncpy(line, &line[lport + 1], sizeof(line) - lport - 1);
++ }
++
+ if (line[0] != ' ' && line[0] != '\t' && line[0] != '\n')
+ continue;
+ gotmachine = 1;
+@@ -2095,13 +2138,13 @@
+ fclose(rcfile);
+ }
+
+-void cmdrc(const char *m1, const char *m2) {
++void cmdrc(const char *m1, const char *m2, const char *port) {
+ static char *rcname = 0;
+ static char rcbuf[128];
+
+ if (skiprc) return;
+
+- readrc(m1, m2, "/etc/telnetrc");
++ readrc(m1, m2, port, "/etc/telnetrc");
+ if (rcname == 0) {
+ rcname = getenv("HOME");
+ if (rcname)
+@@ -2111,7 +2154,7 @@
+ strcat(rcbuf, "/.telnetrc");
+ rcname = rcbuf;
+ }
+- readrc(m1, m2, rcname);
++ readrc(m1, m2, port, rcname);
+ }
+
+ #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
+--- a/telnet/main.cc
++++ b/telnet/main.cc
+@@ -84,7 +84,7 @@
+ fprintf(stderr, "Usage: %s %s%s%s%s\n",
+ prompt,
+ "[-4] [-6] [-8] [-E] [-L] [-a] [-d] [-e char] [-l user]",
+- "\n\t[-n tracefile]",
++ "\n\t[-n tracefile] [ -b addr ]",
+ #ifdef TN3270
+ "\n\t"
+ "[-noasynch] [-noasynctty] [-noasyncnet] [-r] [-t transcom]\n\t",
+@@ -106,7 +106,7 @@
+ extern char *optarg;
+ extern int optind;
+ int ch;
+- char *user;
++ char *user, *srcaddr;
+ int family;
+
+ tninit(); /* Clear out things */
+@@ -115,19 +115,22 @@
+ #endif
+
+ TerminalSaveState();
++ if ((old_tc.c_cflag & (CSIZE|PARENB)) != CS8)
++ eight = 0;
+
+ if ((prompt = strrchr(argv[0], '/'))!=NULL)
+ ++prompt;
+ else
+ prompt = argv[0];
+
+- user = NULL;
++ user = srcaddr = NULL;
+ family = 0;
+
+ rlogin = (strncmp(prompt, "rlog", 4) == 0) ? '~' : _POSIX_VDISABLE;
+ autologin = -1;
+
+- while ((ch = getopt(argc, argv, "468EKLS:X:ade:k:l:n:rt:x")) != EOF) {
++ while ((ch = getopt(argc, argv,
++ "4678EKLS:X:ab:de:k:l:n:rt:x")) != EOF) {
+ switch(ch) {
+ case '4':
+ family = AF_INET;
+@@ -139,8 +142,11 @@
+ fputs("IPv6 unsupported\n", stderr);
+ #endif
+ break;
++ case '7':
++ eight = 0; /* 7-bit ouput and input */
++ break;
+ case '8':
+- eight = 3; /* binary output and input */
++ binary = 3; /* binary output and input */
+ break;
+ case 'E':
+ rlogin = escapechar = _POSIX_VDISABLE;
+@@ -149,7 +155,7 @@
+ //autologin = 0;
+ break;
+ case 'L':
+- eight |= 2; /* binary output only */
++ binary |= 2; /* binary output only */
+ break;
+ case 'S':
+ {
+@@ -229,6 +235,9 @@
+ "%s: -x ignored, no encryption support.\n",
+ prompt);
+ break;
++ case 'b':
++ srcaddr = optarg;
++ break;
+ case '?':
+ default:
+ usage();
+@@ -252,6 +261,10 @@
+ *argp++ = "-l";
+ *argp++ = user;
+ }
++ if (srcaddr) {
++ *argp++ = "-b";
++ *argp++ = srcaddr;
++ }
+ if (family) {
+ *argp++ = family == AF_INET ? "-4" : "-6";
+ }
+--- a/telnet/netlink.cc
++++ b/telnet/netlink.cc
+@@ -79,20 +79,56 @@
+ shutdown(net, 2);
+ }
+ ::close(net);
++ net = -1;
++}
++
++int netlink::bind(struct addrinfo *addr)
++{
++ int res;
++
++ res = socket(addr->ai_family);
++ if (res < 2) {
++ if (res == 1)
++ perror("telnet: socket");
++ return -1;
++ }
++
++ if (::bind(net, addr->ai_addr, addr->ai_addrlen) < 0) {
++ perror("telnet: bind");
++ return -1;
++ }
++
++ return 0;
++}
++
++int netlink::socket(int family)
++{
++ if (this->family != family)
++ close(0);
++
++ if (net < 0) {
++ this->family = family;
++ net = ::socket(family, SOCK_STREAM, 0);
++ if (net < 0) {
++ if (errno == EAFNOSUPPORT)
++ return 1;
++ perror("telnet: socket");
++ return 0;
++ }
++ }
++
++ return 2;
+ }
+
+ int netlink::connect(int debug, struct addrinfo *addr,
+ char *srcroute, int srlen, int tos)
+ {
+ int on=1;
++ int res;
+
+- net = socket(addr->ai_family, SOCK_STREAM, 0);
+- if (net < 0) {
+- if (errno == EAFNOSUPPORT)
+- return 1;
+- perror("telnet: socket");
+- return 0;
+- }
++ res = socket(addr->ai_family);
++ if (res < 2)
++ return res;
+
+ #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
+ if (srcroute) {
+--- a/telnet/netlink.h
++++ b/telnet/netlink.h
+@@ -1,11 +1,15 @@
+
+ class netlink {
++ private:
++ int family;
+ protected:
+ int net;
+ public:
+ netlink();
+ ~netlink();
+
++ int bind(struct addrinfo *hostaddr);
++ int socket(int family);
+ int connect(int debug, struct addrinfo *hostaddr,
+ char *srcroute, int srlen,
+ int tos);
+--- a/telnet/telnet.1
++++ b/telnet/telnet.1
+@@ -44,6 +44,7 @@
+ .Nm telnet
+ .Op Fl 468ELadr
+ .Op Fl S Ar tos
++.Op Fl b Ar address
+ .Op Fl e Ar escapechar
+ .Op Fl l Ar user
+ .Op Fl n Ar tracefile
+@@ -93,6 +94,8 @@
+ option if supported by the remote system. The username is retrieved
+ via
+ .Xr getlogin 3 .
++.It Fl b Ar address
++Use bind(2) on the local socket to bind it to a specific local address.
+ .It Fl d
+ Sets the initial value of the
+ .Ic debug
+@@ -492,7 +495,15 @@
+ indented by whitespace; lines beginning without whitespace are
+ interpreted as hostnames. Lines beginning with the special hostname
+ .Ql DEFAULT
+-will apply to all hosts. Upon connecting to a particular host, the
++will apply to all hosts. Hostnames including
++.Ql DEFAULT
++may be followed immediately by a colon and a port number or string.
++If a port is specified it must match exactly with what is specified
++on the command line. If no port was specified on the command line,
++then the value
++.Ql telnet
++is used.
++Upon connecting to a particular host, the
+ commands associated with that host are executed.
+ .It Ic quit
+ Close any open session and exit
+--- a/telnet/telnet.cc
++++ b/telnet/telnet.cc
+@@ -88,7 +88,8 @@
+ char will_wont_resp[256];
+
+ int
+-eight = 0,
++ eight = 3,
++ binary = 0,
+ autologin = 0, /* Autologin anyone? */
+ skiprc = 0,
+ connected,
+@@ -1743,8 +1744,8 @@
+ send_do(TELOPT_STATUS, 1);
+ if (env_getvalue("DISPLAY", 0))
+ send_will(TELOPT_XDISPLOC, 1);
+- if (eight)
+- tel_enter_binary(eight);
++ if (binary)
++ tel_enter_binary(binary);
+ }
+ #endif /* !defined(TN3270) */
+
+--- a/telnet/terminal.cc
++++ b/telnet/terminal.cc
+@@ -157,9 +157,11 @@
+ if (localflow)
+ mode |= MODE_FLOW;
+
+- if (my_want_state_is_will(TELOPT_BINARY))
++ if ((eight & 1) || my_want_state_is_will(TELOPT_BINARY))
+ mode |= MODE_INBIN;
+
++ if (eight & 2)
++ mode |= MODE_OUT8;
+ if (his_want_state_is_will(TELOPT_BINARY))
+ mode |= MODE_OUTBIN;
+
+@@ -451,10 +453,13 @@
+ // breaks SunOS.
+ tmp_tc.c_iflag |= ISTRIP;
+ }
+- if (f & MODE_OUTBIN) {
++ if (f & (MODE_OUTBIN|MODE_OUT8)) {
+ tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+ tmp_tc.c_cflag |= CS8;
+- tmp_tc.c_oflag &= ~OPOST;
++ if (f & MODE_OUTBIN)
++ tmp_tc.c_oflag &= ~OPOST;
++ else
++ tmp_tc.c_oflag |= OPOST;
+ } else {
+ tmp_tc.c_cflag &= ~(CSIZE|PARENB);
+ tmp_tc.c_cflag |= old_tc.c_cflag & (CSIZE|PARENB);
+@@ -470,7 +475,7 @@
+
+ #ifdef SIGINFO
+ signal(SIGINFO, ayt);
+-#endif SIGINFO
++#endif /* SIGINFO */
+
+ #if defined(NOKERNINFO)
+ tmp_tc.c_lflag |= NOKERNINFO;
+@@ -506,7 +511,7 @@
+
+ #ifdef SIGINFO
+ signal(SIGINFO, ayt_status);
+-#endif SIGINFO
++#endif /* SIGINFO */
+
+ #ifdef SIGTSTP
+ signal(SIGTSTP, SIG_DFL);
+--- a/telnetd/ext.h
++++ b/telnetd/ext.h
+@@ -88,7 +88,7 @@
+ #define netoprintf(fmt, ...) fprintf(netfile, fmt, ## __VA_ARGS__)
+
+ extern int pty, net;
+-extern char *line;
++extern const char *line;
+ extern int SYNCHing; /* we are in TELNET SYNCH mode */
+
+ void _termstat(void);
+--- a/telnetd/sys_term.c
++++ b/telnetd/sys_term.c
+@@ -204,17 +204,17 @@
+ *
+ * Returns the file descriptor of the opened pty.
+ */
+-static char linedata[PATH_MAX];
+-char *line = linedata;
++const char *line;
+
+ static int ptyslavefd=-1;
+
+ int getpty(void) {
+ int masterfd;
+
+- if (openpty(&masterfd, &ptyslavefd, line, NULL, NULL)) {
++ if (openpty(&masterfd, &ptyslavefd, NULL, NULL, NULL)) {
+ return -1;
+ }
++ line = ttyname(ptyslavefd);
+ return masterfd;
+ }
+
+@@ -720,25 +720,11 @@
+ * clean up anything that needs to be cleaned up.
+ */
+ void cleanup(int sig) {
+- char *p;
++ const char *p;
+ (void)sig;
+
+ p = line + sizeof("/dev/") - 1;
+ if (logout(p)) logwtmp(p, "", "");
+-#ifdef PARANOID_TTYS
+- /*
+- * dholland 16-Aug-96 chmod the tty when not in use
+- * This will make it harder to attach unwanted stuff to it
+- * (which is a security risk) but will break some programs.
+- */
+- chmod(line, 0600);
+-#else
+- chmod(line, 0666);
+-#endif
+- chown(line, 0, 0);
+- *p = 'p';
+- chmod(line, 0666);
+- chown(line, 0, 0);
+ shutdown(net, 2);
+ exit(0);
+ }
+--- a/telnetd/telnetd.8
++++ b/telnetd/telnetd.8
+@@ -161,7 +161,7 @@
+ .It Fl L Ar loginprg
+ This option may be used to specify a different login program.
+ By default,
+-.Pa /usr/sbin/telnetlogin
++.Pa /usr/lib/telnetlogin
+ is used.
+ .It Fl n
+ Disable
+--- a/telnet/defines.h
++++ b/telnet/defines.h
+@@ -50,3 +50,5 @@
+ #define MODE_COMMAND_LINE(m) ((m)==-1)
+
+ #define CONTROL(x) ((x)&0x1f) /* CTRL(x) is not portable */
++
++#define MODE_OUT8 0x8000 /* binary mode sans -opost */
+--- a/telnet/proto.h
++++ b/telnet/proto.h
+@@ -13,7 +13,7 @@
+ void auth_encrypt_user(char *);
+ void auth_name(unsigned char *, int);
+ void auth_printsub(unsigned char *, int, unsigned char *, int);
+-void cmdrc(const char *m1, const char *m2);
++void cmdrc(const char *, const char *, const char *);
+ void env_init(void);
+ int getconnmode(void);
+ void init_network(void);
+--- a/telnet/externs.h
++++ b/telnet/externs.h
+@@ -48,9 +48,7 @@
+ typedef unsigned char cc_t;
+ #endif
+
+-#ifdef __linux__
+ #include <unistd.h> /* get _POSIX_VDISABLE */
+-#endif
+
+ #ifndef _POSIX_VDISABLE
+ #error "Please fix externs.h to define _POSIX_VDISABLE"
+@@ -60,7 +58,8 @@
+
+ extern int autologin; /* Autologin enabled */
+ extern int skiprc; /* Don't process the ~/.telnetrc file */
+-extern int eight; /* use eight bit mode (binary in and/or out */
++extern int eight; /* use eight bit mode (binary in and/or out) */
++extern int binary; /* use binary option (in and/or out) */
+ extern int flushout; /* flush output */
+ extern int connected; /* Are we connected to the other side? */
+ extern int globalmode; /* Mode tty should be in */
+@@ -225,6 +224,8 @@
+
+ //#if 0
+ extern struct termios new_tc;
++extern struct termios old_tc;
++
+
+ #define termEofChar new_tc.c_cc[VEOF]
+ #define termEraseChar new_tc.c_cc[VERASE]
--- /dev/null
+Description: Fix buffer overflow when $HOME is large.
+ Very long values of $HOME will extend beyond fixed rcbuf[128].
+ In its stead, use dynamic allocation.
+
+Author: Josh Martin
+Bug-Debian: http://bugs.debian.org/264846
+Comment: Introduced in netkit-telnet_0.17-25.
+Forwarded: no
+Last-Update: 2004-08-13
+
+--- netkit-telnet-0.17.orig/telnet/commands.cc
++++ netkit-telnet-0.17/telnet/commands.cc
+@@ -2139,22 +2139,18 @@
+ }
+
+ void cmdrc(const char *m1, const char *m2, const char *port) {
+- static char *rcname = 0;
+- static char rcbuf[128];
++ char *rcname = NULL;
+
+ if (skiprc) return;
+
+ readrc(m1, m2, port, "/etc/telnetrc");
+- if (rcname == 0) {
+- rcname = getenv("HOME");
+- if (rcname)
+- strcpy(rcbuf, rcname);
+- else
+- rcbuf[0] = '\0';
+- strcat(rcbuf, "/.telnetrc");
+- rcname = rcbuf;
+- }
++ if (asprintf (&rcname, "%s/.telnetrc", getenv ("HOME")) == -1)
++ {
++ perror ("asprintf");
++ return;
++ }
+ readrc(m1, m2, port, rcname);
++ free (rcname);
+ }
+
+ #if defined(IP_OPTIONS) && defined(HAS_IPPROTO_IP)
--- /dev/null
+Description: Fix remote DOS hole, CAN-2004-0911.
+ telnetd/utility.c (netwritebuf): Check that `listlen' is positive
+ before any action. Otherwise do nothing, just return.
+ .
+ Patch made public in bug report.
+
+Author: Herbert Xu
+Bug-Debian: http://bugs.debian.org/273694
+Comment: Introduced in ntekit-telnet_0.17-26.
+Forwarded: no
+Last-Update: 2004-07-27
+
+Index: netkit-telnet-0.17/telnetd/utility.c
+===================================================================
+RCS file: /home/gondolin/herbert/src/CVS/debian/netkit-telnet/telnetd/utility.c,v
+retrieving revision 1.8
+diff -u -r1.8 utility.c
+--- netkit-telnet-0.17/telnetd/utility.c 18 Jan 2002 09:13:36 -0000 1.8
++++ netkit-telnet-0.17/telnetd/utility.c 25 Sep 2004 01:22:51 -0000
+@@ -246,6 +246,9 @@
+ size_t len;
+ int ltrailing = trailing;
+
++ if (!listlen)
++ return;
++
+ vector = malloc(listlen * sizeof(struct iovec));
+ if (!vector) {
+ return;
+@@ -323,9 +326,7 @@
+ /* out of memory? */
+ cleanup(0);
+ }
+- if (listlen) {
+- netwritebuf();
+- }
++ netwritebuf();
+ }
+
+
--- /dev/null
+Description: Buffer overflow in LINEMODE suboptions, CAN-2005-0469.
+ telnet/telnet.cc (slc_add_reply): Check that sufficiently space
+ still is available beyond `slc_replyp'.
+ .
+ Extracted by comparison of netkit-telnet_0.17-18woody3,
+ netkit-telnet_0.17-29, and netkit-telnet-ssl_0.17.24+0.1-7.1.
+
+Author: Martin 'Joey' Schultze.
+Comment: Introduced in netkit-telnet_0.17-28.
+Forwarded: no
+Last-Update: 2015-01-26
+
+--- netkit-telnet-0.17.orig/telnet/telnet.cc
++++ netkit-telnet-0.17/telnet/telnet.cc
+@@ -1051,6 +1051,7 @@
+
+
+ unsigned char slc_reply[128];
++unsigned char const * const slc_reply_eom = &slc_reply[sizeof(slc_reply)];
+ unsigned char *slc_replyp;
+
+ void slc_start_reply(void) {
+@@ -1062,6 +1063,14 @@
+ }
+
+ void slc_add_reply(int func, int flags, int value) {
++ /* A sequence of up to 6 bytes my be written for this member of the SLC
++ * suboption list by this function. The end of negotiation command,
++ * which is written by slc_end_reply(), will require 2 additional
++ * bytes. Do not proceed unless there is sufficient space for these
++ * items.
++ */
++ if (&slc_replyp[6+2] > slc_reply_eom)
++ return;
+ if ((*slc_replyp++ = func) == IAC)
+ *slc_replyp++ = IAC;
+ if ((*slc_replyp++ = flags) == IAC)
--- /dev/null
+Description: Reject invalid port numbers.
+ Check that any port number is within the range of a short integer.
+Author: Justin Pryzby
+Bug-Debian: http://bugs.debian.org/300273
+Comment: interdiff netkit-telnet_0.17-{29.34}.diff
+Forwarded: no
+Last-Update: 2005-10-09
+
+diff -u netkit-telnet-0.17/telnet/commands.cc netkit-telnet-0.17/telnet/commands.cc
+--- netkit-telnet-0.17/telnet/commands.cc
++++ netkit-telnet-0.17/telnet/commands.cc
+@@ -1747,8 +1747,22 @@
+ if (*portp == '-') {
+ portp++;
+ telnetport = 1;
+- } else
++ } else {
+ telnetport = 0;
++ if (*portp >='0' && *portp<='9') {
++ char *end;
++ long int p;
++
++ p=strtol(portp, &end, 10);
++ if (ERANGE==errno && (LONG_MIN==p || LONG_MAX==p)) {
++ fprintf(stderr, "telnet: port %s overflows\n", portp);
++ return 0;
++ } else if (p<=0 || p>=65536) {
++ fprintf(stderr, "telnet: port %s out of range\n", portp);
++ return 0;
++ }
++ }
++ }
+ }
+ else {
+ portp = "telnet";
--- /dev/null
+Description: Avoid unsetting environment variable TERM.
+ Do not reset TERM to "UNKNOWN", when it is unknown in the local host.
+Author: Philippe Troin
+Bug-Debian: http://bugs.debian.org/237324
+Comment: interdiff netkit-telnet_0.17-{34,36}.diff
+Forwarded: no
+Last-Update: 2008-06-22
+
+diff -u netkit-telnet-0.17/telnet/telnet.cc netkit-telnet-0.17/telnet/telnet.cc
+--- netkit-telnet-0.17/telnet/telnet.cc
++++ netkit-telnet-0.17/telnet/telnet.cc
+@@ -640,7 +640,7 @@
+ if (resettermname) {
+ resettermname = 0;
+ tname = env_getvalue("TERM", 0);
+- if (!tname || my_setupterm(tname, 1, &err)) {
++ if (!tname /* || my_setupterm(tname, 1, &err) */) {
+ termbuf[0] = 0;
+ tname = "UNKNOWN";
+ }
--- /dev/null
+Description: Format string is not a string literal.
+ Hardened builds are failing due to "-Werror=format-security".
+ Insertion of a trivial format string resolves the failure.
+Author: Mats Erik Andersson <debian@gisladisker.se>
+Forwarded: no
+Last-Update: 2015-01-09
+
+--- netkit-telnet-0.17/telnetd/utility.c.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnetd/utility.c 2015-01-09 23:11:41.695499612 +0100
+@@ -890,17 +890,17 @@
+ case ENV_VAR:
+ if (pointer[1] == TELQUAL_SEND)
+ goto def_case;
+- netoprintf("\" VAR " + noquote);
++ netoprintf("%s", "\" VAR " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_VALUE:
+- netoprintf("\" VALUE " + noquote);
++ netoprintf("%s", "\" VALUE " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_ESC:
+- netoprintf("\" ESC " + noquote);
++ netoprintf("%s", "\" ESC " + noquote);
+ noquote = 2;
+ break;
+
+--- netkit-telnet-0.17/telnet/utilities.cc.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnet/utilities.cc 2015-01-09 23:33:05.219513739 +0100
+@@ -583,17 +583,17 @@
+ case ENV_VAR:
+ if (pointer[1] == TELQUAL_SEND)
+ goto def_case;
+- fprintf(NetTrace, "\" VAR " + noquote);
++ fprintf(NetTrace, "%s", "\" VAR " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_VALUE:
+- fprintf(NetTrace, "\" VALUE " + noquote);
++ fprintf(NetTrace, "%s", "\" VALUE " + noquote);
+ noquote = 2;
+ break;
+
+ case ENV_ESC:
+- fprintf(NetTrace, "\" ESC " + noquote);
++ fprintf(NetTrace, "%s", "\" ESC " + noquote);
+ noquote = 2;
+ break;
+
--- /dev/null
+Description: Nit picking on troff macros.
+ Annoying misprints which Lintian complains on.
+ .
+ A minor inconsistency bug, misnaming the original escape character.
+Author: Mats Erik Andersson <debian@gisladisker.se>
+Bug-Debian: http://bugs.debian.org/676258
+Forwarded: no
+Last-Update: 2015-01-10
+
+--- netkit-telnet-0.17/telnet/telnet.1.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnet/telnet.1 2015-01-10 01:35:37.775594668 +0100
+@@ -711,7 +711,7 @@
+ .It Ic escape
+ This is the
+ .Nm telnet
+-escape character (initially \*(Lq^[\*(Rq) which causes entry
++escape character (initially \*(Lq^]\*(Rq) which causes entry
+ into
+ .Nm telnet
+ command mode (when connected to a remote system).
+@@ -1167,10 +1167,12 @@
+ is sent as
+ .Ic abort ,
+ and
+-.Ic eof and
+-.B suspend
++.Ic eof
++and
++.Ic suspend
+ are sent as
+-.Ic eof and
++.Ic eof
++and
+ .Ic susp ,
+ see
+ .Ic send
+--- netkit-telnet-0.17/telnetd/issue.net.5.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnetd/issue.net.5 2015-01-10 01:01:20.827572027 +0100
+@@ -22,7 +22,7 @@
+ - show the current tty
+ .It %h
+ - show the system node name (FQDN)
+-.It %D
++.It \&%D
+ - show the name of the NIS domain
+ .It %d
+ - show the current time and date
+--- netkit-telnet-0.17/telnetd/telnetd.8.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnetd/telnetd.8 2015-01-10 00:30:52.891551907 +0100
+@@ -261,7 +261,7 @@
+ .Ed
+ .Pp
+ The pseudo-terminal allocated to the client is configured
+-to operate in \*(lqcooked\*(rq mode, and with
++to operate in \*(Lqcooked\*(Rq mode, and with
+ .Dv XTABS
+ .Dv CRMOD
+ enabled (see
+--- netkit-telnet-0.17/telnetlogin/telnetlogin.8.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnetlogin/telnetlogin.8 2015-01-10 01:18:25.835583309 +0100
+@@ -60,7 +60,7 @@
+ accepts only the subset of options to
+ .Xr login 1
+ shown above, in the order listed. This is the order
+-.Nm telnetd 8
++.Xr telnetd 8
+ normally provides them in.
+ .Nm telnetlogin
+ also does sanity checks on the environment variables
--- /dev/null
+Description: Selected protocol refinement.
+ Let the manual pages express NEW-ENVIRON as the only
+ supported environment mechanism.
+ .
+ Let the diagnostic printout correctly identify the observed
+ modi of local flow control.
+ .
+ Let the server in debug mode correctly decode only the suboption
+ part of a status response, by ignoring the initial `IAC SB'.
+ .
+ Let the server and client decode suboptions containing also ENV_USERVAR
+ in addition to the already known ENV_VAR.
+ .
+ Make the command `status' be as verbose as in other clients.
+ .
+ Several calls to printsub() were missing in `telnet.cc', thus failing
+ to display options that the client sends to the server. Instead only
+ the received responses were display in some few negotiations, namely
+ TELOPT_TTYPE, TELOPT_TSPEED, TELOPT_XDISPLOC and TELOPT_LINEMODE
+
+Author: Mats Erik Andersson <debian@gisladisker.se>
+Forwarded: no
+Last-Update: 2015-03-09
+
+--- netkit-telnet-0.17/telnet/telnet.1.orig 2015-01-10 01:35:37.775594668 +0100
++++ netkit-telnet-0.17/telnet/telnet.1 2015-01-13 22:22:47.371626252 +0100
+@@ -90,7 +90,7 @@
+ .Ev USER
+ variable
+ of the
+-.Ev ENVIRON
++.Ev NEW-ENVIRON
+ option if supported by the remote system. The username is retrieved
+ via
+ .Xr getlogin 3 .
+@@ -131,7 +131,7 @@
+ sending the specified name as the
+ .Dv USER
+ environment variable, so it requires that the remote system support the
+-.Ev TELNET ENVIRON
++.Ev TELNET NEW-ENVIRON
+ option. This option implies the
+ .Fl a
+ option, and may also be used with the
+@@ -327,7 +327,7 @@
+ command is used to propagate environment variables across the
+ .Nm telnet
+ link using the
+-.Dv TELNET ENVIRON
++.Dv TELNET NEW-ENVIRON
+ protocol option.
+ All variables exported from the shell are defined, but only the
+ .Ev DISPLAY
+@@ -1044,7 +1044,7 @@
+ attempts to use it to perform automatic authentication. If the
+ .Dv TELNET AUTHENTICATION
+ option is not supported, the user's login name is propagated using the
+-.Dv TELNET ENVIRON
++.Dv TELNET NEW-ENVIRON
+ option.
+ Setting this flag is the same as specifying the
+ .Ar a
+@@ -1255,7 +1255,7 @@
+ environment variables.
+ Other environment variables may be propagated
+ to the other side via the
+-.Dv TELNET ENVIRON
++.Dv TELNET NEW-ENVIRON
+ option.
+ .Sh FILES
+ .Bl -tag -width /etc/telnetrc -compact
+--- netkit-telnet-0.17/telnetd/telnetd.8.orig 2015-01-10 00:30:52.891551907 +0100
++++ netkit-telnet-0.17/telnetd/telnetd.8 2015-01-13 23:06:04.039624516 +0100
+@@ -250,7 +250,6 @@
+ DO TSPEED
+ DO XDISPLOC
+ DO NEW-ENVIRON
+-DO ENVIRON
+ WILL SUPPRESS GO AHEAD
+ DO ECHO
+ DO LINEMODE
+@@ -372,9 +371,6 @@
+ .It "DO NEW-ENVIRON"
+ Indicates a desire to be able to request environment
+ variable information, as described in RFC 1572.
+-.It "DO ENVIRON"
+-Indicates a desire to be able to request environment
+-variable information, as described in RFC 1408.
+ .It "DO LINEMODE"
+ Only sent if
+ .Nm telnetd
+--- netkit-telnet-0.17/telnet/utilities.cc.orig 2015-01-09 23:33:05.219513739 +0100
++++ netkit-telnet-0.17/telnet/utilities.cc 2015-03-09 15:07:32.965473513 +0100
+@@ -335,10 +335,14 @@
+ break;
+ }
+ switch (pointer[1]) {
+- case 0:
++ case LFLOW_OFF:
+ fprintf(NetTrace, " OFF"); break;
+- case 1:
++ case LFLOW_ON:
+ fprintf(NetTrace, " ON"); break;
++ case LFLOW_RESTART_ANY:
++ fprintf(NetTrace, " RESTART-ANY"); break;
++ case LFLOW_RESTART_XON:
++ fprintf(NetTrace, " RESTART-XON"); break;
+ default:
+ fprintf(NetTrace, " %d (unknown)", pointer[1]);
+ }
+@@ -454,7 +458,7 @@
+ pointer[2]&MODE_SOFT_TAB ? "|SOFT_TAB" : "",
+ pointer[2]&MODE_LIT_ECHO ? "|LIT_ECHO" : "",
+ pointer[2]&MODE_ACK ? "|ACK" : "");
+- fprintf(NetTrace, "%s", tbuf[1] ? &tbuf[1] : "0");
++ fprintf(NetTrace, "%s", tbuf[0] ? &tbuf[1] : "0");
+ }
+ if (pointer[2]&~(MODE_MASK))
+ fprintf(NetTrace, " (0x%x)", pointer[2]);
+@@ -580,10 +584,14 @@
+ register int noquote = 2;
+ for (i = 2; i < length; i++ ) {
+ switch (pointer[i]) {
++ case ENV_USERVAR:
+ case ENV_VAR:
+ if (pointer[1] == TELQUAL_SEND)
+ goto def_case;
+- fprintf(NetTrace, "%s", "\" VAR " + noquote);
++ if (pointer[i] == ENV_VAR)
++ fprintf(NetTrace, "%s", "\" VAR " + noquote);
++ else
++ fprintf(NetTrace, "%s", "\" USERVAR " + noquote);
+ noquote = 2;
+ break;
+
+@@ -624,7 +632,7 @@
+ if (TELOPT_OK(pointer[0]))
+ fprintf(NetTrace, "%s (unknown)", TELOPT(pointer[0]));
+ else
+- fprintf(NetTrace, "%d (unknown)", pointer[i]);
++ fprintf(NetTrace, "%d (unknown)", pointer[0]);
+ for (i = 1; i < length; i++)
+ fprintf(NetTrace, " %d", pointer[i]);
+ break;
+--- netkit-telnet-0.17/telnetd/utility.c.orig 2015-01-09 23:11:41.695499612 +0100
++++ netkit-telnet-0.17/telnetd/utility.c 2015-01-14 18:03:48.552691379 +0100
+@@ -643,10 +643,14 @@
+ break;
+ }
+ switch (pointer[1]) {
+- case 0:
++ case LFLOW_OFF:
+ netoprintf(" OFF"); break;
+- case 1:
++ case LFLOW_ON:
+ netoprintf(" ON"); break;
++ case LFLOW_RESTART_ANY:
++ netoprintf(" RESTART-ANY"); break;
++ case LFLOW_RESTART_XON:
++ netoprintf(" RESTART-XON"); break;
+ default:
+ netoprintf(" %d (unknown)", pointer[1]);
+ }
+@@ -792,15 +796,6 @@
+ netoprintf("STATUS");
+
+ switch (pointer[1]) {
+- default:
+- if (pointer[1] == TELQUAL_SEND)
+- netoprintf(" SEND");
+- else
+- netoprintf(" %d (unknown)", pointer[1]);
+- for (i = 2; i < length; i++) {
+- netoprintf(" ?%d?", pointer[i]);
+- }
+- break;
+ case TELQUAL_IS:
+ netoprintf(" IS\r\n");
+
+@@ -852,6 +847,15 @@
+ }
+ }
+ break;
++ default:
++ if (pointer[1] == TELQUAL_SEND)
++ netoprintf(" SEND");
++ else
++ netoprintf(" %d (unknown)", pointer[1]);
++ for (i = 2; i < length; i++) {
++ netoprintf(" ?%d?", pointer[i]);
++ }
++ break;
+ }
+ break;
+ }
+@@ -887,10 +891,14 @@
+ register int noquote = 2;
+ for (i = 2; i < length; i++ ) {
+ switch (pointer[i]) {
++ case ENV_USERVAR:
+ case ENV_VAR:
+ if (pointer[1] == TELQUAL_SEND)
+ goto def_case;
+- netoprintf("%s", "\" VAR " + noquote);
++ if (pointer[i] == ENV_VAR)
++ netoprintf("%s", "\" VAR " + noquote);
++ else
++ netoprintf("%s", "\" USERVAR " + noquote);
+ noquote = 2;
+ break;
+
+@@ -1080,7 +1088,7 @@
+ if (TELOPT_OK(pointer[0]))
+ netoprintf("%s (unknown)", TELOPT(pointer[0]));
+ else
+- netoprintf("%d (unknown)", pointer[i]);
++ netoprintf("%d (unknown)", pointer[0]);
+ for (i = 1; i < length; i++) {
+ netoprintf(" %d", pointer[i]);
+ }
+--- netkit-telnet-0.17/telnet/commands.cc.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnet/commands.cc 2015-01-21 23:20:17.488735411 +0100
+@@ -1605,7 +1605,7 @@
+ }
+
+ static int status(void) {
+- int notmuch = 1;
++ int notmuch = 0;
+ return dostatus(notmuch);
+ }
+
+--- netkit-telnet-0.17/telnet/telnet.cc.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnet/telnet.cc 2015-01-22 14:34:01.402828217 +0100
+@@ -684,6 +684,15 @@
+ name = gettermname();
+ netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_TTYPE,
+ TELQUAL_IS, name, IAC, SE);
++ {
++ unsigned char tbuf[7 + 20]; /* 20 chars for terminal name. */
++ int len;
++
++ len = snprintf((char *) tbuf, sizeof(tbuf), "%c%c%c%c%s%c%c",
++ IAC, SB, TELOPT_TTYPE, TELQUAL_IS, name, IAC, SE);
++ if (len > 6 && len < sizeof(tbuf))
++ printsub('>', &tbuf[2], len - 2);
++ }
+ }
+ break;
+ case TELOPT_TSPEED:
+@@ -696,6 +705,16 @@
+ TerminalSpeeds(&iispeed, &oospeed);
+ netoring.xprintf("%c%c%c%c%ld,%ld%c%c", IAC, SB, TELOPT_TSPEED,
+ TELQUAL_IS, oospeed, iispeed, IAC, SE);
++ {
++ unsigned char tbuf[8 + 20]; /* 20 characters for two speeds. */
++ int len;
++
++ len = snprintf((char *) tbuf, sizeof(tbuf), "%c%c%c%c%ld,%ld%c%c",
++ IAC, SB, TELOPT_TSPEED, TELQUAL_IS,
++ oospeed, iispeed, IAC, SE);
++ if (len > 7 && len < sizeof(tbuf))
++ printsub('>', &tbuf[2], len - 2);
++ }
+ }
+ break;
+ case TELOPT_LFLOW:
+@@ -783,6 +802,15 @@
+ }
+ netoring.xprintf("%c%c%c%c%s%c%c", IAC, SB, TELOPT_XDISPLOC,
+ TELQUAL_IS, dp, IAC, SE);
++ {
++ unsigned char tbuf[7 + 30]; /* 30 chars for display name. */
++ int len;
++
++ len = snprintf((char *) tbuf, sizeof(tbuf), "%c%c%c%c%s%c%c",
++ IAC, SB, TELOPT_XDISPLOC, TELQUAL_IS, dp, IAC, SE);
++ if (len > 6 && len < sizeof(tbuf))
++ printsub('>', &tbuf[2], len - 2);
++ }
+ }
+ break;
+
+@@ -801,6 +829,14 @@
+
+ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ DONT, cmd[0], IAC, SE);
++ {
++ unsigned char tbuf[8];
++ int len;
++
++ len = snprintf((char *) tbuf, sizeof(tbuf), "%c%c%c%c%c%c%c",
++ IAC, SB, TELOPT_LINEMODE, DONT, cmd[0], IAC, SE);
++ printsub('>', &tbuf[2], len - 2);
++ }
+ }
+
+ void lm_wont(unsigned char * /*cmd*/, int len) {
+@@ -818,6 +854,14 @@
+ }
+ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ WONT, cmd[0], IAC, SE);
++ {
++ unsigned char tbuf[8];
++ int len;
++
++ len = snprintf((char *) tbuf, sizeof(tbuf), "%c%c%c%c%c%c%c",
++ IAC, SB, TELOPT_LINEMODE, WONT, cmd[0], IAC, SE);
++ printsub('>', &tbuf[2], len - 2);
++ }
+ }
+
+ void lm_dont(unsigned char * /*cmd*/, int len) {
+@@ -841,6 +885,14 @@
+
+ netoring.xprintf("%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE, LM_MODE,
+ k, IAC, SE);
++ {
++ unsigned char tbuf[8];
++ int len;
++
++ len = snprintf((char *) tbuf, sizeof(tbuf), "%c%c%c%c%c%c%c",
++ IAC, SB, TELOPT_LINEMODE, LM_MODE, k, IAC, SE);
++ printsub('>', &tbuf[2], len - 2);
++ }
+
+ setconnmode(0); /* set changed mode */
+ }
+@@ -933,14 +985,23 @@
+ }
+
+ void slc_import(int def) {
++ unsigned char cmd, tbuf[10];
++ int len;
++
+ if (def) {
++ cmd = SLC_DEFAULT;
+ netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ LM_SLC, 0, SLC_DEFAULT, 0, IAC, SE);
+ }
+ else {
++ cmd = SLC_VARIABLE;
+ netoring.xprintf("%c%c%c%c%c%c%c%c%c", IAC, SB, TELOPT_LINEMODE,
+ LM_SLC, 0, SLC_VARIABLE, 0, IAC, SE);
+ }
++
++ len = snprintf((char *) tbuf, sizeof(tbuf), "%c%c%c%c%c%c%c%c%c",
++ IAC, SB, TELOPT_LINEMODE, LM_SLC, 0, cmd, 0, IAC, SE);
++ printsub('>', &tbuf[2], len - 2);
+ }
+
+ void slc_export(void) {
--- /dev/null
+Description: Support user variables in environment.
+ Include conditionally protected code, allowing the server to accept
+ variables from the client marked as user defined, i.e., ENV_USERVAR,
+ into the environment. The code is made active by the compiler macro
+ ACCEPT_USERVAR. This would let clients from Solaris and FreeBSD set
+ variables exported by the user.
+ [telnetd/state.c (suboption)]
+ .
+ Fix incorrect offset while diagnostically printing suboptions.
+ [telnetd/state.c (send_status)]
+ .
+ Add LANG and LC_* to the list of acceptable environment variables.
+ [telnetd/state.c (envvarok)]
+ .
+ Let the client executable announce most environment variables as user
+ defined, i.e., as ENV_USERVAR. A new function wellknown_var() checks
+ whether a proposed variable name is known well enough to be kept as
+ ENV_VAR, thus nominally undergo more scrutiny at the server's end.
+ These addition are also conditioned by the macro ACCEPT_USERVAR:
+ [telnet/telnet.cc (env_opt_add)]
+
+Author: Mats Erik Andersson <debian@gisladisker.se>
+Bug-Debian: http://bugs.debian.org/237268
+Forwarded: no
+Last-Update: 2015-03-09
+
+--- netkit-telnet-0.17/telnetd/state.c.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnetd/state.c 2015-03-07 13:53:41.241039630 +0100
+@@ -1157,7 +1157,7 @@
+ } /* end of case TELOPT_XDISPLOC */
+
+ case TELOPT_ENVIRON: {
+- register int c;
++ register int c, is_uservar = 0;
+ register char *cp, *varp, *valp;
+
+ if (SB_EOF())
+@@ -1168,12 +1168,17 @@
+ else if (c != TELQUAL_INFO)
+ return;
+
+- while (!SB_EOF() && SB_GET() != ENV_VAR)
+- ;
++ while (!SB_EOF()) {
++ c = SB_GET();
++ if (c == ENV_VAR || c == ENV_USERVAR)
++ break;
++ }
+
+ if (SB_EOF())
+ return;
+
++ is_uservar = (c == ENV_USERVAR) ? 1 : 0;
++
+ cp = varp = (char *)subpointer;
+ valp = 0;
+
+@@ -1184,14 +1189,20 @@
+ cp = valp = (char *)subpointer;
+ break;
+
++ case ENV_USERVAR:
+ case ENV_VAR:
+ *cp = '\0';
+- if (envvarok(varp)) {
++ if (envvarok(varp)
++#ifdef ACCEPT_USERVAR
++ || is_uservar
++#endif
++ ) {
+ if (valp)
+ (void)setenv(varp, valp, 1);
+ else
+ unsetenv(varp);
+ }
++ is_uservar = (c == ENV_USERVAR) ? 1 : 0;
+ cp = varp = (char *)subpointer;
+ valp = 0;
+ break;
+@@ -1208,7 +1219,11 @@
+ }
+ }
+ *cp = '\0';
+- if (envvarok(varp)) {
++ if (envvarok(varp)
++#ifdef ACCEPT_USERVAR
++ || is_uservar
++#endif
++ ) {
+ if (valp)
+ (void)setenv(varp, valp, 1);
+ else
+@@ -1367,7 +1382,7 @@
+ writenet(statusbuf, ncp - statusbuf);
+ netflush(); /* Send it on its way */
+
+- DIAG(TD_OPTIONS, {printsub('>', statusbuf, ncp - statusbuf); netflush();});
++ DIAG(TD_OPTIONS, {printsub('>', statusbuf + 2, ncp - statusbuf - 2); netflush();});
+ }
+
+ /* check that variable is safe to pass to login or shell */
+@@ -1399,6 +1414,8 @@ static int envvarok(char *varp) {
+ if (!strcmp(varp, "USER")) return 1;
+ if (!strcmp(varp, "LOGNAME")) return 1;
+ if (!strcmp(varp, "POSIXLY_CORRECT")) return 1;
++ if (!strcmp(varp, "LANG")) return 1;
++ if (!strncmp(varp, "LC_", 3)) return 1;
+
+ /* optionally syslog(LOG_INFO) here */
+ return 0;
+--- netkit-telnet-0.17/telnet/telnet.cc.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnet/telnet.cc 2015-03-09 14:35:22.513396375 +0100
+@@ -1213,6 +1213,40 @@ void env_opt(unsigned char *buf, int len
+ }
+ }
+
++#ifdef ACCEPT_USERVAR
++namespace {
++ const struct stems {
++ const char *stem; /* Initial part, or a full name. */
++ const int len; /* Naught indicates a full name. */
++ } wellknown_stems[] = {
++ { "ACCT", 0 },
++ { "DISPLAY", 0 },
++ { "JOB", 0 },
++ { "LANG", 0 },
++ { "LC_", 3 },
++ { "LOGNAME", 0 },
++ { "POSIXLY_CORRECT", 0 },
++ { "PRINTER", 0 },
++ { "SSH_", 4 },
++ { "SYSTEMTYPE", 0 },
++ { "TERM", 0 },
++ { "USER", 0 },
++ { "XAUTHORITY", 0 },
++ { NULL, 0 }
++ };
++
++ int wellknown_var(const char *name) {
++ const stems *stem;
++ for (stem = wellknown_stems; stem->stem != NULL; stem++)
++ if ((stem->len ? strncmp(name, stem->stem, stem->len)
++ : strcmp(name, stem->stem)) == 0)
++ return 1;
++
++ return 0;
++ }
++} /* Anonymous namespace */
++#endif /* ACCEPT_USERVAR */
++
+ /* OPT_REPLY_SIZE must be a multiple of 2. */
+ #define OPT_REPLY_SIZE 256
+ unsigned char *opt_reply;
+@@ -1273,7 +1307,16 @@ void env_opt_add(const char *ep) {
+ opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
+ opt_replyend = opt_reply + len;
+ }
++
++#ifdef ACCEPT_USERVAR
++ if (wellknown_var(ep))
++ *opt_replyp++ = ENV_VAR;
++ else
++ *opt_replyp++ = ENV_USERVAR;
++#else /* !ACCEPT_USERVAR */
+ *opt_replyp++ = ENV_VAR;
++#endif
++
+ for (;;) {
+ while ((c = *ep++)!=0) {
+ switch(c) {
--- /dev/null
+Description: Drain input stream from child process.
+ When the server process receives SIGCHILD, there might
+ well be data pending in the PTY buffer, intended for
+ the client waiting eagerly at the network link.
+ .
+ Replace the old signal handler for SIGCHILD with a simpler
+ version that sets a semaphor. That semaphor is then sampled
+ at a suitable time during the I/O main loop, and execution
+ is transferred to the old handler after flushing the queue.
+ .
+ In the original signal handler, call waitpid() in order to
+ remove the child process from the kernel's process list.
+ .
+ Make some small adjustment to debugging output.
+Author: Mats Erik Andersson <debian@gisladisker.se>
+Bug-Debian: http://bugs.debian.org/607415
+Forwarded: no
+Last-Update: 2015-01-20
+
+--- netkit-telnet-0.17/telnetd/sys_term.c.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnetd/sys_term.c 2015-03-07 15:44:01.185237034 +0100
+@@ -39,6 +39,8 @@
+
+ #include <utmp.h>
+
++#include <sys/wait.h>
++
+ #include "telnetd.h"
+ #include "pathnames.h"
+
+@@ -720,11 +722,16 @@
+ * clean up anything that needs to be cleaned up.
+ */
+ void cleanup(int sig) {
++ int stat = 0;
+ const char *p;
+- (void)sig;
++
++ if (sig == SIGCHLD) {
++ if (waitpid(-1, &stat, WNOHANG) > 0)
++ stat = WEXITSTATUS(stat);
++ }
+
+ p = line + sizeof("/dev/") - 1;
+ if (logout(p)) logwtmp(p, "", "");
+ shutdown(net, 2);
+- exit(0);
++ exit(stat);
+ }
+--- netkit-telnet-0.17/telnetd/telnetd.c.orig 2015-01-09 20:22:23.000000000 +0100
++++ netkit-telnet-0.17/telnetd/telnetd.c 2015-01-20 13:59:40.625777998 +0100
+@@ -92,9 +92,17 @@
+ char *loginprg = _PATH_LOGIN;
+ #endif
+
++static int got_sigchld = 0;
++
+ extern void usage(void);
+
+ static void
++catch_sigchld(int sig)
++{
++ got_sigchld = 1;
++}
++
++static void
+ wait_for_connection(const char *service)
+ {
+ struct addrinfo hints;
+@@ -870,9 +878,9 @@
+ */
+ signal(SIGTTOU, SIG_IGN);
+ #endif
+-
+- signal(SIGCHLD, cleanup);
+-
++
++ signal(SIGCHLD, catch_sigchld);
++
+ #ifdef TIOCNOTTY
+ {
+ register int t;
+@@ -1091,6 +1099,11 @@
+ ptyibuf[0] & TIOCPKT_DOSTOP ? 1 : 0,
+ IAC, SE);
+ }
++
++ DIAG((TD_REPORT | TD_PTYDATA),
++ netoprintf("td: ptyread %d chars\r\n", pcc););
++ DIAG(TD_PTYDATA, printdata("pd", ptyibuf, pcc));
++
+ pcc--;
+ ptyip = ptyibuf+1;
+ }
+@@ -1116,6 +1129,11 @@
+ telrcv();
+ if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
+ ptyflush();
++
++ if (got_sigchld) {
++ netflush();
++ cleanup(SIGCHLD); /* Not returning. */
++ }
+ }
+ cleanup(0);
+ } /* end of telnet */
+--- netkit-telnet-0.17/telnetd/utility.c.orig 2015-01-14 18:03:48.552691379 +0100
++++ netkit-telnet-0.17/telnetd/utility.c 2015-01-19 16:06:55.783013012 +0100
+@@ -1110,7 +1110,7 @@
+ /* add a line of output */
+ netoprintf("%s: ", tag);
+ for (i = 0; i < 20 && cnt; i++) {
+- netoprintf("%02x", *ptr);
++ netoprintf("%02x", (unsigned char) *ptr);
+ if (isprint(*ptr)) {
+ xbuf[i] = *ptr;
+ } else {
+--- netkit-telnet-0.17/telnetd/telnetd.8.orig 2015-01-13 23:06:04.039624516 +0100
++++ netkit-telnet-0.17/telnetd/telnetd.8 2015-01-20 14:35:13.973804769 +0100
+@@ -124,12 +124,13 @@
+ program.
+ .El
+ .It Fl D Ar debugmode
+-This option may be used for debugging purposes. This allows
++This option may be used for debugging purposes. It allows
+ .Nm telnetd
+ to print out debugging information to the connection, allowing the
+ user to see what
+ .Nm telnetd
+-is doing. There are several possible values for
++is doing. Repeated use of the option arranges composite debug reports.
++There are several possible values for
+ .Ar debugmode:
+ .Bl -tag -width exercise
+ .It Cm options
--- /dev/null
+Description: Logical error in host name check.
+ Mutually exclusive conditions were juxtaposed with logical AND,
+ resulting in a test never being effective.
+Author: Ian Beckwith <ianb@debian.org>
+Comment: Incorporated from netkit-telnet-ssl.
+Forwarded: no
+Last Update: 2015-01-30
+
+--- netkit-telnet-0.17.orig/telnetlogin/telnetlogin.c
++++ netkit-telnet-0.17/telnetlogin/telnetlogin.c
+@@ -76,7 +76,7 @@
+ int i=0;
+ /* should we check length? */
+ for (i=0; hname[i]; i++) {
+- if (hname[i]<=32 && hname[i]>126) return -1;
++ if ((hname[i]<=32) || (hname[i]>126)) return -1;
+ }
+ return 0;
+ }
--- /dev/null
+Description: Resolve remote host as numeric host identifier.
+ Implement a new switch '-N' in the server, avoiding reverse DNS
+ resolution and instead registering a numeric host representation.
+ The environment variable REMOTEHOST is set to this numeric address.
+ .
+ The change could be of benefit in PAM rules for access control as well
+ as for accounting and tracing of network activity. In addition, the use
+ of '-N' mitigates cases when a hostile third party might have gained
+ control of reverse DNS resolution and is trying to inject fake answers.
+
+Author: Dean Gaudet
+Bug-Debian: http://bugs.debian.org/258371
+Comment: The patch was first applied to netkit-telnet-ssl.
+Last-Update: 2004-12-05
+
+--- netkit-telnet-0.17/telnetd/telnetd.c.orig
++++ netkit-telnet-0.17/telnetd/telnetd.c
+@@ -86,6 +86,7 @@ int hostinfo = 1; /* do we print login
+
+ int debug = 0;
+ int keepalive = 1;
++int numeric_hosts = 0;
+ #ifdef LOGIN_WRAPPER
+ char *loginprg = LOGIN_WRAPPER;
+ #else
+@@ -220,7 +221,7 @@ main(int argc, char *argv[], char *env[]
+ pfrontp = pbackp = ptyobuf;
+ netip = netibuf;
+
+- while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:L:")) != EOF) {
++ while ((ch = getopt(argc, argv, "d:a:e:lhnNr:I:D:B:sS:a:X:L:")) != EOF) {
+ switch(ch) {
+
+ #ifdef AUTHENTICATE
+@@ -319,6 +320,10 @@ main(int argc, char *argv[], char *env[]
+ keepalive = 0;
+ break;
+
++ case 'N':
++ numeric_hosts = 1;
++ break;
++
+ #ifdef SecurID
+ case 's':
+ /* SecurID required */
+@@ -680,7 +685,8 @@ doit(struct sockaddr *who, socklen_t who
+
+ /* get name of connected client */
+ if (getnameinfo(who, who_len, remote_host_name,
+- sizeof(remote_host_name), 0, 0, 0)) {
++ sizeof(remote_host_name), 0, 0,
++ numeric_hosts ? NI_NUMERICHOST : 0)) {
+ syslog(LOG_ERR, "doit: getnameinfo: %m");
+ *remote_host_name = 0;
+ }
+--- netkit-telnet-0.17/telnetd/telnetd.8.orig
++++ netkit-telnet-0.17/telnetd/telnetd.8
+@@ -42,7 +42,7 @@
+ protocol server
+ .Sh SYNOPSIS
+ .Nm /usr/sbin/in.telnetd
+-.Op Fl hns
++.Op Fl hnNs
+ .Op Fl a Ar authmode
+ .Op Fl D Ar debugmode
+ .Op Fl L Ar loginprg
+@@ -176,6 +176,9 @@
+ 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 N
++Disable reverse DNS lookups and use the numeric IP address in logs
++and REMOTEHOST environment variable.
+ .It Fl s
+ This option is only enabled if
+ .Nm telnetd
+++ /dev/null
-diff -uNr netkit-telnet-0.17/telnetd/telnetd.c netkit-telnet-0.17.ipv6/telnetd/telnetd.c\r
---- netkit-telnet-0.17/telnetd/telnetd.c 2006-07-13 08:37:18.000000000 +0200\r
-+++ netkit-telnet-0.17.ipv6/telnetd/telnetd.c 2006-07-14 08:36:11.000000000 +0200\r
-@@ -49,6 +49,7 @@\r
- /* #include <netinet/ip.h> */ /* Don't think this is used at all here */\r
- #include <arpa/inet.h>\r
- #include <assert.h>\r
-+#include <sys/poll.h>\r
- #include "telnetd.h"\r
- #include "pathnames.h"\r
- #include "setproctitle.h"\r
-@@ -68,7 +69,7 @@\r
- #define HAS_IPPROTO_IP\r
- #endif\r
- \r
--static void doit(struct sockaddr_in *who);\r
-+static void doit(struct sockaddr *who, socklen_t wholen);\r
- static int terminaltypeok(const char *s);\r
- \r
- /*\r
-@@ -90,7 +91,7 @@\r
- int\r
- main(int argc, char *argv[], char *env[])\r
- {\r
-- struct sockaddr_in from;\r
-+ struct sockaddr from;\r
- int on = 1;\r
- socklen_t fromlen;\r
- register int ch;\r
-@@ -248,64 +249,89 @@\r
- argc -= optind;\r
- argv += optind;\r
- \r
-- if (debug) {\r
-- int s, ns;\r
-- socklen_t foo;\r
-- struct servent *sp;\r
-- struct sockaddr_in sn;\r
-+ int s = 0;\r
- \r
-- memset(&sn, 0, sizeof(sn));\r
-- sn.sin_family = AF_INET;\r
-+ if (debug) {\r
-+ struct addrinfo *ai;\r
-+ unsigned int nfds = 0;\r
-+ struct pollfd fds[2];\r
- \r
- if (argc > 1) {\r
-- usage();\r
-- /* NOTREACHED */\r
-- } else if (argc == 1) {\r
-- if ((sp = getservbyname(*argv, "tcp"))!=NULL) {\r
-- sn.sin_port = sp->s_port;\r
-- } \r
-- else {\r
-- int pt = atoi(*argv);\r
-- if (pt <= 0) {\r
-- fprintf(stderr, "telnetd: %s: bad port number\n",\r
-- *argv);\r
-- usage();\r
-- /* NOTREACHED */\r
-- }\r
-- sn.sin_port = htons(pt);\r
-- }\r
-+ usage();\r
-+ /* NOTREACHED */\r
- } else {\r
-- sp = getservbyname("telnet", "tcp");\r
-- if (sp == 0) {\r
-- fprintf(stderr, "telnetd: tcp/telnet: unknown service\n");\r
-- exit(1);\r
-- }\r
-- sn.sin_port = sp->s_port;\r
-- }\r
-+ struct addrinfo hints;\r
-+\r
-+ memset (&hints, '\0', sizeof (hints));\r
-+ hints.ai_socktype = SOCK_STREAM;\r
-+ hints.ai_flags = AI_ADDRCONFIG | AI_PASSIVE;\r
-+ hints.ai_protocol = IPPROTO_TCP;\r
-+\r
-+ if (argc == 0) {\r
-+ if (getaddrinfo(NULL, "telnet", &hints, &ai) != 0) {\r
-+ fprintf(stderr, "telnetd: %s: bad port number\n", *argv);\r
-+ usage();\r
-+ /* NOTREACHED */\r
-+ }\r
-+ } else {\r
-+ if (getaddrinfo(NULL, *argv, &hints, &ai) != 0) {\r
-+ fprintf(stderr, "telnetd: %s: bad port number\n", *argv);\r
-+ usage();\r
-+ /* NOTREACHED */\r
-+ }\r
-+ }\r
-+ } \r
- \r
-- s = socket(AF_INET, SOCK_STREAM, 0);\r
-- if (s < 0) {\r
-+ struct addrinfo *runp;\r
-+ int b = 0;\r
-+ for (runp = ai; ((runp != NULL) && (nfds < sizeof (fds) / sizeof (fds[0]))); runp = runp->ai_next) {\r
-+ fds[nfds].fd = socket(runp->ai_family, runp->ai_socktype, runp->ai_protocol);\r
-+ if (fds[nfds].fd < 0) {\r
- perror("telnetd: socket");;\r
-- exit(1);\r
-+ exit(1);\r
-+ }\r
-+ fds[nfds].events = POLLIN;\r
-+ (void) setsockopt(fds[nfds].fd, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));\r
-+\r
-+ if (bind(fds[nfds].fd, runp->ai_addr, runp->ai_addrlen) != 0) {\r
-+ // Unable to bind to given port. One of the reason can be\r
-+ // that we can't bind to both IPv4 and IPv6\r
-+ break;\r
-+ } else { \r
-+ b++;\r
-+ }\r
-+\r
-+ if (listen(fds[nfds].fd, 1) < 0) {\r
-+ perror("listen");\r
-+ exit(1);\r
-+ }\r
-+ nfds++;\r
- }\r
-- (void) setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on));\r
-- if (bind(s, (struct sockaddr *)&sn, sizeof(sn)) < 0) {\r
-- perror("bind");\r
-- exit(1);\r
-- }\r
-- if (listen(s, 1) < 0) {\r
-- perror("listen");\r
-- exit(1);\r
-+ freeaddrinfo(ai);\r
-+\r
-+ if (b == 0) {\r
-+ perror("bind");\r
-+ exit(1);\r
- }\r
-- foo = sizeof(sn);\r
-- ns = accept(s, (struct sockaddr *)&sn, &foo);\r
-- if (ns < 0) {\r
-- perror("accept");\r
-- exit(1);\r
-+\r
-+ int n = poll (fds, nfds, -1);\r
-+ if (n > 0) {\r
-+ unsigned int i;\r
-+ for (i = 0; i < nfds; i++) {\r
-+ if (fds[i].revents & POLLIN) {\r
-+ struct sockaddr_storage rem;\r
-+ socklen_t remlen = sizeof(rem);\r
-+ int fd = accept(fds[i].fd, (struct sockaddr *) &rem, &remlen);\r
-+\r
-+ if (fd < 0) {\r
-+ perror("accept");\r
-+ exit(1);\r
-+ }\r
-+\r
-+ s = fd;\r
-+ }\r
-+ }\r
- }\r
-- (void) dup2(ns, 0);\r
-- (void) close(ns);\r
-- (void) close(s);\r
- } else if (argc > 0) {\r
- usage();\r
- /* NOT REACHED */\r
-@@ -313,13 +339,13 @@\r
- \r
- openlog("telnetd", LOG_PID | LOG_ODELAY, LOG_DAEMON);\r
- fromlen = sizeof (from);\r
-- if (getpeername(0, (struct sockaddr *)&from, &fromlen) < 0) {\r
-+ if (getpeername(s, &from, &fromlen) < 0) {\r
- fprintf(stderr, "%s: ", progname);\r
- perror("getpeername");\r
- _exit(1);\r
- }\r
- if (keepalive &&\r
-- setsockopt(0, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {\r
-+ setsockopt(s, SOL_SOCKET, SO_KEEPALIVE, &on, sizeof (on)) < 0) {\r
- syslog(LOG_WARNING, "setsockopt (SO_KEEPALIVE): %m");\r
- }\r
- \r
-@@ -333,13 +359,13 @@\r
- if (tos < 0)\r
- tos = 020; /* Low Delay bit */\r
- if (tos\r
-- && (setsockopt(0, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)\r
-+ && (setsockopt(s, IPPROTO_IP, IP_TOS, &tos, sizeof(tos)) < 0)\r
- && (errno != ENOPROTOOPT) )\r
- syslog(LOG_WARNING, "setsockopt (IP_TOS): %m");\r
- }\r
- #endif /* defined(HAS_IPPROTO_IP) && defined(IP_TOS) */\r
-- net = 0;\r
-- doit(&from);\r
-+ net = s;\r
-+ doit(&from, fromlen);\r
- /* NOTREACHED */\r
- return 0;\r
- } /* end of main */\r
-@@ -608,10 +634,9 @@\r
- * Get a pty, scan input lines.\r
- */\r
- static void\r
--doit(struct sockaddr_in *who)\r
-+doit(struct sockaddr *who, socklen_t wholen)\r
- {\r
- const char *host;\r
-- struct hostent *hp;\r
- int level;\r
- char user_name[256];\r
- \r
-@@ -623,12 +648,18 @@\r
- fatal(net, "All network ports in use");\r
- \r
- /* get name of connected client */\r
-- hp = gethostbyaddr((char *)&who->sin_addr, sizeof (struct in_addr),\r
-- who->sin_family);\r
-- if (hp)\r
-- host = hp->h_name;\r
-- else\r
-- host = inet_ntoa(who->sin_addr);\r
-+ int error = -1;\r
-+ char namebuf[255];\r
-+\r
-+ error = getnameinfo(who, wholen, namebuf, sizeof(namebuf), NULL, 0, 0);\r
-+ \r
-+ if (error) {\r
-+ perror("getnameinfo: localhost");\r
-+ perror(gai_strerror(error));\r
-+ exit(1); \r
-+ }\r
-+ \r
-+ host = namebuf;\r
- \r
- /*\r
- * We must make a copy because Kerberos is probably going\r
-@@ -649,13 +680,21 @@\r
- \r
- /* Get local host name */\r
- {\r
-- struct hostent *h;\r
-+ struct addrinfo hints;\r
-+ struct addrinfo *res;\r
-+ int e;\r
-+\r
-+ memset(&hints, '\0', sizeof(hints));\r
-+ hints.ai_socktype = SOCK_STREAM;\r
-+ hints.ai_flags = AI_ADDRCONFIG;\r
-+\r
- gethostname(host_name, sizeof(host_name));\r
-- h = gethostbyname(host_name);\r
-- if (h) {\r
-- strncpy(host_name, h->h_name, sizeof(host_name));\r
-- host_name[sizeof(host_name)-1] = 0;\r
-+ if ((e = getaddrinfo(host_name, NULL, &hints, &res)) != 0) {\r
-+ perror("getaddrinfo: localhost");\r
-+ perror(gai_strerror(e));\r
-+ exit(1);\r
- }\r
-+ freeaddrinfo(res);\r
- }\r
- \r
- #if defined(AUTHENTICATE) || defined(ENCRYPT)\r
+++ /dev/null
---- netkit-telnet-0.17.orig/telnetd/telnetd.c 2007-03-13 16:31:20.000000000 +0000
-+++ netkit-telnet-0.17.orig/telnetd/telnetd.c 2007-03-13 16:31:26.000000000 +0000
-@@ -653,6 +653,11 @@ doit(struct sockaddr *who, socklen_t who
-
- error = getnameinfo(who, wholen, namebuf, sizeof(namebuf), NULL, 0, 0);
-
-+ /* if we can't get a hostname now, settle for an address */
-+ if(error == EAI_AGAIN)
-+ error = getnameinfo(who, wholen, namebuf, sizeof(namebuf),
-+ NULL, 0, NI_NUMERICHOST);
-+
- if (error) {
- perror("getnameinfo: localhost");
- perror(gai_strerror(error));
-@@ -681,7 +686,7 @@ doit(struct sockaddr *who, socklen_t who
- /* Get local host name */
- {
- struct addrinfo hints;
-- struct addrinfo *res;
-+ struct addrinfo *res = 0;
- int e;
-
- memset(&hints, '\0', sizeof(hints));
-@@ -690,11 +695,14 @@ doit(struct sockaddr *who, socklen_t who
-
- gethostname(host_name, sizeof(host_name));
- if ((e = getaddrinfo(host_name, NULL, &hints, &res)) != 0) {
-- perror("getaddrinfo: localhost");
-- perror(gai_strerror(e));
-- exit(1);
-+ if(e != EAI_AGAIN) {
-+ fprintf(stderr, "getaddrinfo: localhost %s\n",
-+ gai_strerror(e));
-+ exit(1);
-+ }
- }
-- freeaddrinfo(res);
-+ if(res)
-+ freeaddrinfo(res);
- }
-
- #if defined(AUTHENTICATE) || defined(ENCRYPT)
-
+++ /dev/null
---- netkit-telnet-0.17.orig/telnetd/telnetd.c.reallynodns 2009-03-12 14:32:29.000000000 -0700
-+++ netkit-telnet-0.17.orig/telnetd/telnetd.c 2009-03-12 14:51:59.000000000 -0700
-@@ -85,6 +85,7 @@
- int keepalive = 1;
- char *loginprg = _PATH_LOGIN;
- char *progname;
-+int lookupself = 1;
-
- extern void usage(void);
-
-@@ -111,7 +112,7 @@
-
- progname = *argv;
-
-- while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:L:")) != EOF) {
-+ while ((ch = getopt(argc, argv, "d:a:e:lhnr:I:D:B:sS:a:X:L:N")) != EOF) {
- switch(ch) {
-
- #ifdef AUTHENTICATE
-@@ -210,6 +211,10 @@
- keepalive = 0;
- break;
-
-+ case 'N':
-+ lookupself = 0;
-+ break;
-+
- #ifdef SecurID
- case 's':
- /* SecurID required */
-@@ -393,6 +398,7 @@
- #endif
- fprintf(stderr, " [-L login_program]");
- fprintf(stderr, " [-n]");
-+ fprintf(stderr, " [-N]");
- #ifdef SecurID
- fprintf(stderr, " [-s]");
- #endif
-@@ -691,15 +697,20 @@
-
- memset(&hints, '\0', sizeof(hints));
- hints.ai_socktype = SOCK_STREAM;
-- hints.ai_flags = AI_ADDRCONFIG;
-+ hints.ai_flags = AI_CANONNAME;
-
- gethostname(host_name, sizeof(host_name));
-- if ((e = getaddrinfo(host_name, NULL, &hints, &res)) != 0) {
-- if(e != EAI_AGAIN) {
-- fprintf(stderr, "getaddrinfo: localhost %s\n",
-- gai_strerror(e));
-- exit(1);
-- }
-+ /*
-+ * Optionally canonicalize the local host name, in case
-+ * gethostname() returns foo, we want foo.example.com
-+ */
-+ if (lookupself &&
-+ (e = getaddrinfo(host_name, NULL, &hints, &res)) == 0) {
-+ if (res->ai_canonname) {
-+ strncpy(host_name, res->ai_canonname,
-+ sizeof(host_name)-1);
-+ host_name[sizeof(host_name)-1] = 0;
-+ }
- }
- if(res)
- freeaddrinfo(res);
---- netkit-telnet-0.17.orig/telnetd/telnetd.8.reallynodns 2009-03-12 14:54:54.000000000 -0700
-+++ netkit-telnet-0.17.orig/telnetd/telnetd.8 2009-03-12 14:56:58.000000000 -0700
-@@ -42,7 +42,7 @@
- protocol server
- .Sh SYNOPSIS
- .Nm /usr/sbin/in.telnetd
--.Op Fl hns
-+.Op Fl hnNs
- .Op Fl a Ar authmode
- .Op Fl D Ar debugmode
- .Op Fl L Ar loginprg
-@@ -175,6 +175,10 @@
- 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 N
-+Do not use DNS to canonicalize the local hostname;
-+.Fn gethostname 2
-+returns a fully qualified name.
- .It Fl s
- This option is only enabled if
- .Nm telnetd
+++ /dev/null
-diff -ru netkit-telnet-0.17.orig/telnet/main.c netkit-telnet-0.17/telnet/main.c
---- netkit-telnet-0.17.orig/telnet/main.c 2003-05-15 20:07:40.000000000 +0200
-+++ netkit-telnet-0.17/telnet/main.c 2003-05-16 00:18:28.000000000 +0200
-@@ -143,7 +143,7 @@
- while ((ch = getopt(argc, argv, "78DEKLS:X:ab:cde:fFk:l:n:rt:x")) != -1) {
- switch(ch) {
- case '8':
-- eight = 3; /* binary output and input */
-+ binary = 3; /* send TELNET BINARY option for output and input */
- break;
- case '7':
- eight = 0;
-@@ -165,7 +165,7 @@
- #endif
- break;
- case 'L':
-- eight |= 2; /* binary output only */
-+ binary = 2; /* send TELNET BINARY option for output only */
- break;
- case 'S':
- {
-diff -ru netkit-telnet-0.17.orig/telnet/telnet.1 netkit-telnet-0.17/telnet/telnet.1
---- netkit-telnet-0.17.orig/telnet/telnet.1 2003-05-15 20:07:40.000000000 +0200
-+++ netkit-telnet-0.17/telnet/telnet.1 2003-05-15 23:38:37.000000000 +0200
-@@ -76,6 +76,8 @@
- .Pp
- The options are as follows:
- .Bl -tag -width Ds
-+.It Fl 7
-+Strip 8th bit on input and output. Telnet is 8-bit clean by default but doesn't send the TELNET BINARY option unless forced.
- .It Fl 8
- Specifies an 8-bit data path.
- This causes an attempt to negotiate the
+++ /dev/null
---- netkit-telnet-0.17/telnet/telnet.c.CAN-2005-468_469 2005-03-17 13:48:58.000000000 +0100
-+++ netkit-telnet-0.17/telnet/telnet.c 2005-03-17 14:02:27.000000000 +0100
-@@ -1310,22 +1310,66 @@
- }
-
-
--unsigned char slc_reply[128];
-+#define SLC_REPLY_SIZE 128
-+unsigned char *slc_reply;
- unsigned char *slc_replyp;
-+unsigned char *slc_replyend;
-
- void
- slc_start_reply(void)
- {
-+ slc_reply = (unsigned char *)malloc(SLC_REPLY_SIZE);
-+ if (slc_reply == NULL) {
-+/*@*/ printf("slc_start_reply: malloc()/realloc() failed!!!\n");
-+ slc_reply = slc_replyp = slc_replyend = NULL;
-+ return;
-+ }
-+
- slc_replyp = slc_reply;
-+ slc_replyend = slc_reply + SLC_REPLY_SIZE;
- *slc_replyp++ = IAC;
- *slc_replyp++ = SB;
- *slc_replyp++ = TELOPT_LINEMODE;
- *slc_replyp++ = LM_SLC;
- }
-
-+static int
-+slc_assure_buffer(int want_len);
-+
-+ static int
-+slc_assure_buffer(int want_len)
-+{
-+ if ((slc_replyp + want_len) >= slc_replyend) {
-+ int len;
-+ int old_len = slc_replyp - slc_reply;
-+ unsigned char *p;
-+
-+ len = old_len
-+ + (want_len / SLC_REPLY_SIZE + 1) * SLC_REPLY_SIZE;
-+ p = (unsigned char *)realloc(slc_reply, len);
-+ if (p == NULL)
-+ free(slc_reply);
-+ slc_reply = p;
-+ if (slc_reply == NULL) {
-+/*@*/ printf("slc_add_reply: realloc() failed!!!\n");
-+ slc_reply = slc_replyp = slc_replyend = NULL;
-+ return 1;
-+ }
-+ slc_replyp = slc_reply + old_len;
-+ slc_replyend = slc_reply + len;
-+ }
-+ return 0;
-+}
-+
- void
- slc_add_reply(unsigned char func, unsigned char flags, cc_t value)
- {
-+ if (slc_assure_buffer(6))
-+ return;
-+
-+ if (slc_replyp == NULL)
-+ return;
-+
- if ((*slc_replyp++ = func) == IAC)
- *slc_replyp++ = IAC;
- if ((*slc_replyp++ = flags) == IAC)
-@@ -1339,6 +1383,12 @@
- {
- int len;
-
-+ if (slc_assure_buffer(2))
-+ return;
-+
-+ if (slc_replyp == NULL)
-+ return;
-+
- *slc_replyp++ = IAC;
- *slc_replyp++ = SE;
- len = slc_replyp - slc_reply;
-@@ -1456,7 +1506,7 @@
- }
- }
-
--#define OPT_REPLY_SIZE 256
-+#define OPT_REPLY_SIZE 1024
- unsigned char *opt_reply;
- unsigned char *opt_replyp;
- unsigned char *opt_replyend;
-@@ -1490,10 +1540,38 @@
- env_opt_start_info(void)
- {
- env_opt_start();
-- if (opt_replyp)
-+ if (opt_replyp && (opt_replyp > opt_reply))
- opt_replyp[-1] = TELQUAL_INFO;
- }
-
-+static int
-+env_opt_assure_buffer(int want_len);
-+
-+ static int
-+env_opt_assure_buffer(int want_len)
-+{
-+ if ((opt_replyp + want_len) >= opt_replyend) {
-+ int len;
-+ unsigned char *p;
-+ int old_len = opt_replyp - opt_reply;
-+
-+ len = old_len
-+ + (want_len / OPT_REPLY_SIZE + 1) * OPT_REPLY_SIZE;
-+ p = (unsigned char *)realloc(opt_reply, len);
-+ if (p == NULL)
-+ free(opt_reply);
-+ opt_reply = p;
-+ if (opt_reply == NULL) {
-+/*@*/ printf("env_opt_add: realloc() failed!!!\n");
-+ opt_reply = opt_replyp = opt_replyend = NULL;
-+ return 1;
-+ }
-+ opt_replyp = opt_reply + old_len;
-+ opt_replyend = opt_reply + len;
-+ }
-+ return 0;
-+}
-+
- void
- env_opt_add(unsigned char *ep)
- {
-@@ -1515,25 +1593,12 @@
- return;
- }
- vp = env_getvalue(ep, 1);
-- if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
-- strlen((char *)ep) + 6 > opt_replyend)
-- {
-- int len;
-- unsigned char *p;
-- opt_replyend += OPT_REPLY_SIZE;
-- len = opt_replyend - opt_reply;
-- p = (unsigned char *)realloc(opt_reply, len);
-- if (p == NULL)
-- free(opt_reply);
-- opt_reply = p;
-- if (opt_reply == NULL) {
--/*@*/ printf("env_opt_add: realloc() failed!!!\n");
-- opt_reply = opt_replyp = opt_replyend = NULL;
-- return;
-- }
-- opt_replyp = opt_reply + len - (opt_replyend - opt_replyp);
-- opt_replyend = opt_reply + len;
-- }
-+
-+ /* use the double length in case it gots escaped */
-+ if (env_opt_assure_buffer((vp ? strlen((char *)vp)*2 : 0) +
-+ strlen((char *)ep)*2 + 6))
-+ return;
-+
- if (opt_welldefined((char *)ep))
- #ifdef OLD_ENVIRON
- if (telopt_environ == TELOPT_OLD_ENVIRON)
-@@ -1588,8 +1653,14 @@
- {
- int len;
-
-+ if (opt_reply == NULL) /*XXX*/
-+ return; /*XXX*/
-+
-+
- len = opt_replyp - opt_reply + 2;
- if (emptyok || len > 6) {
-+ if (env_opt_assure_buffer(2))
-+ return;
- *opt_replyp++ = IAC;
- *opt_replyp++ = SE;
- if (NETROOM() > len) {
+++ /dev/null
-diff -ur netkit-telnet-0.17/telnetd/setproctitle.c netkit-telnet-0.17.new/telnetd/setproctitle.c
---- netkit-telnet-0.17/telnetd/setproctitle.c 1999-12-11 00:06:39.000000000 +0100
-+++ netkit-telnet-0.17.new/telnetd/setproctitle.c 2004-06-28 16:48:51.153514392 +0200
-@@ -139,7 +139,7 @@
- (void) strcpy(Argv[0], buf);
- p = &Argv[0][i];
- while (p < LastArgv)
-- *p++ = ' ';
-+ *p++ = '\0';
- Argv[1] = NULL;
- }
-
+++ /dev/null
---- netkit-telnet-0.17/telnetd/telnetd.c.cleanup_race 2005-01-11 18:39:49.578123000 -0500
-+++ netkit-telnet-0.17/telnetd/telnetd.c 2005-01-11 18:42:45.909616000 -0500
-@@ -1081,6 +1081,8 @@
- if (FD_ISSET(p, &obits) && (pfrontp - pbackp) > 0)
- ptyflush();
- }
-+ /* to avoid a race for wtmp lock */
-+ signal(SIGCHLD, SIG_IGN);
- cleanup(0);
- } /* end of telnet */
-
+++ /dev/null
---- netkit-telnet-0.17/configure.confverb 2000-07-29 20:00:29.000000000 +0200
-+++ netkit-telnet-0.17/configure 2004-07-05 10:50:36.492963840 +0200
-@@ -263,14 +263,19 @@
- cat <<EOF >__conftest.cc
- #include <unistd.h>
- #include <signal.h>
--int count=0;
-+volatile int count=0;
- void handle(int foo) { count++; }
- int main() {
-+ sigset_t sset;
- int pid=getpid();
-+ sigemptyset(&sset);
-+ sigaddset(&sset, SIGINT);
-+ sigprocmask(SIG_UNBLOCK, &sset, NULL);
- signal(SIGINT, handle);
- kill(pid,SIGINT);
- kill(pid,SIGINT);
- kill(pid,SIGINT);
-+ sleep(1);
- if (count!=3) return 1;
- return 0;
- }
+++ /dev/null
---- netkit-telnet-0.17-pre-20000204/telnet/commands.c.env Thu Apr 8 19:30:20 1999
-+++ netkit-telnet-0.17-pre-20000204/telnet/commands.c Tue May 16 17:19:47 2000
-@@ -1815,11 +1815,11 @@
- }
-
- unsigned char *
--env_getvalue(unsigned char *var)
-+env_getvalue(unsigned char *var, int exported_only)
- {
-- struct env_lst *ep;
-+ struct env_lst *ep = env_find(var);
-
-- if ((ep = env_find(var)))
-+ if (ep && (!exported_only || ep->export))
- return(ep->value);
- return(NULL);
- }
---- netkit-telnet-0.17-pre-20000204/telnet/telnet.c.env Tue May 16 17:19:47 2000
-+++ netkit-telnet-0.17-pre-20000204/telnet/telnet.c Tue May 16 17:19:47 2000
-@@ -438,7 +438,7 @@
- #endif
-
- case TELOPT_XDISPLOC: /* X Display location */
-- if (env_getvalue((unsigned char *)"DISPLAY"))
-+ if (env_getvalue((unsigned char *)"DISPLAY", 0))
- new_state_ok = 1;
- break;
-
-@@ -693,7 +693,7 @@
- resettermname = 0;
- if (tnamep && tnamep != unknown)
- free(tnamep);
-- if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
-+ if ((tname = (char *)env_getvalue((unsigned char *)"TERM", 0)) &&
- (setupterm(tname, 1, &errret) == 0)) {
- tnamep = mklist(ttytype, tname);
- } else {
-@@ -870,7 +870,7 @@
- unsigned char temp[50], *dp;
- int len;
-
-- if ((dp = env_getvalue((unsigned char *)"DISPLAY")) == NULL) {
-+ if ((dp = env_getvalue((unsigned char *)"DISPLAY", 0)) == NULL) {
- /*
- * Something happened, we no longer have a DISPLAY
- * variable. So, turn off the option.
-@@ -1527,7 +1527,7 @@
- env_opt_add(ep);
- return;
- }
-- vp = env_getvalue(ep);
-+ vp = env_getvalue(ep, 1);
- if (opt_replyp + (vp ? strlen((char *)vp) : 0) +
- strlen((char *)ep) + 6 > opt_replyend)
- {
-@@ -2170,7 +2170,7 @@
- send_will(TELOPT_LINEMODE, 1);
- send_will(TELOPT_NEW_ENVIRON, 1);
- send_do(TELOPT_STATUS, 1);
-- if (env_getvalue((unsigned char *)"DISPLAY"))
-+ if (env_getvalue((unsigned char *)"DISPLAY", 0))
- send_will(TELOPT_XDISPLOC, 1);
- if (binary)
- tel_enter_binary(binary);
---- netkit-telnet-0.17-pre-20000204/telnet/externs.h.env Mon Feb 8 15:56:11 1999
-+++ netkit-telnet-0.17-pre-20000204/telnet/externs.h Tue May 16 17:19:47 2000
-@@ -203,7 +203,7 @@
- void env_send (unsigned char *);
- void env_list (void);
- unsigned char * env_default(int init, int welldefined);
--unsigned char * env_getvalue(unsigned char *var);
-+unsigned char * env_getvalue(unsigned char *var, int exported_only);
-
- void set_escape_char(char *s);
- unsigned long sourceroute(char *arg, char **cpp, int *lenp);
-@@ -335,7 +335,7 @@
- void env_opt_end (int);
-
- unsigned char *env_default (int, int);
--unsigned char *env_getvalue (unsigned char *);
-+unsigned char *env_getvalue (unsigned char *, int);
-
- int get_status (void);
- int dosynch (void);
+++ /dev/null
-diff -up netkit-telnet-0.17/telnet/sys_bsd.c.errnosysbsd netkit-telnet-0.17/telnet/sys_bsd.c
---- netkit-telnet-0.17/telnet/sys_bsd.c.errnosysbsd 2007-09-20 10:57:58.000000000 +0200
-+++ netkit-telnet-0.17/telnet/sys_bsd.c 2007-09-20 11:10:08.000000000 +0200
-@@ -375,6 +375,7 @@ TerminalNewMode(int f)
- int onoff;
- int old;
- cc_t esc;
-+ int err;
-
- globalmode = f&~MODE_FORCE;
- if (prevmode == f)
-@@ -407,6 +408,12 @@ TerminalNewMode(int f)
- tcsetattr(tin, TCSADRAIN, &tmp_tc);
- #endif /* USE_TERMIO */
- old = ttyflush(SYNCHing|flushout);
-+ if (old < 0) {
-+ err = errno;
-+ if (! ((err == EINTR) || (err == EAGAIN) || (err == ENOSPC))) {
-+ break;
-+ }
-+ }
- } while (old < 0 || old > 1);
- }
-
+++ /dev/null
---- netkit-telnet-0.17/telnetd/utility.c.issue Sun Dec 12 09:59:45 1999
-+++ netkit-telnet-0.17/telnetd/utility.c Wed Jul 18 11:14:11 2001
-@@ -460,13 +460,13 @@
- putlocation = where;
-
- while (*cp) {
-- if (*cp != '%') {
-+ if (*cp != '%' && *cp != '\\') {
- putchr(*cp++);
- continue;
- }
- switch (*++cp) {
-
-- case 't':
-+ case 'l':
- slash = strrchr(line, '/');
- if (slash == NULL)
- putstr(line);
-@@ -474,21 +474,28 @@
- putstr(slash+1);
- break;
-
-+ case 'n':
- case 'h':
- putstr(editedhost);
- break;
-
-+ case 't':
- case 'd':
- (void)time(&t);
- (void)strftime(db, sizeof(db), fmtstr, localtime(&t));
- putstr(db);
- break;
-
-+ case '\\':
-+ putchr('\\');
-+ break;
-+
- case '%':
- putchr('%');
- break;
-
- case 'D':
-+ case 'o':
- {
- char buff[128];
-
-@@ -515,7 +522,7 @@
- c = fgetc(fp);
- } while (c != EOF && c != '\n');
- continue;
-- } else if (c == '%') {
-+ } else if (c == '%' || c == '\\') {
- buff[0] = c;
- c = fgetc(fp);
- if (c == EOF) break;
---- netkit-telnet-0.17/telnetd/issue.net.5.issue Sun Jul 30 19:57:09 2000
-+++ netkit-telnet-0.17/telnetd/issue.net.5 Wed Jul 18 11:03:09 2001
-@@ -15,16 +15,17 @@
- .Pa /etc/issue.net
- is a text file which contains a message or system identification to be
- printed before the login prompt of a telnet session. It may contain
--various `%-char' sequences. The following sequences are supported by
-+various `%-char' (or, alternatively, '\\-char') sequences. The following
-+sequences are supported by
- .Ic telnetd :
- .Bl -tag -offset indent -compact -width "abcde"
--.It %t
-+.It %l
- - show the current tty
--.It %h
-+.It %h, %n
- - show the system node name (FQDN)
--.It %D
-+.It %D, %o
- - show the name of the NIS domain
--.It %d
-+.It %d, %t
- - show the current time and date
- .It %s
- - show the name of the operating system
+++ /dev/null
-diff -u telnet/commands.c telnet.new/commands.c
---- telnet/commands.c Sat Sep 1 12:55:18 2001
-+++ telnet.new/commands.c Sat Sep 1 12:54:36 2001
-@@ -2354,6 +2354,7 @@
- hints.ai_flags = AI_CANONNAME;
- if (portp == NULL) {
- portp = "telnet";
-+ telnetport = 1;
- } else if (*portp == '-') {
- portp++;
- telnetport = 1;
-@@ -2397,7 +2398,6 @@
- if (error) {
- warn("%s: %s", aliasp, gai_strerror(error));
- close(net);
-- freeaddrinfo(ares);
- continue;
- }
- if (bind(net, ares->ai_addr, ares->ai_addrlen) < 0) {
-@@ -2414,7 +2414,7 @@
- perror("setsockopt (IP_OPTIONS)");
- #endif
- #if defined(IPPROTO_IP) && defined(IP_TOS)
-- {
-+ if (res->ai_family == AF_INET) {
- # if defined(HAS_GETTOS)
- struct tosent *tp;
- if (tos < 0 && (tp = gettosbyname("telnet", "tcp")))
-@@ -2438,7 +2438,7 @@
- char hbuf[NI_MAXHOST];
-
- if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-- NULL, 0, NI_NUMERICHOST) != 0) {
-+ NULL, 0, niflags) != 0) {
- strcpy(hbuf, "(invalid)");
- }
- fprintf(stderr, "telnet: connect to address %s: %s\n", hbuf,
+++ /dev/null
-diff -up netkit-telnet-0.17/telnetd/ext.h.sa-01-49 netkit-telnet-0.17/telnetd/ext.h
---- netkit-telnet-0.17/telnetd/ext.h.sa-01-49 1999-12-12 15:59:44.000000000 +0100
-+++ netkit-telnet-0.17/telnetd/ext.h 2011-01-20 22:39:54.000000000 +0100
-@@ -86,7 +86,10 @@ extern char *neturg; /* one past last b
- extern int pcc, ncc;
-
- /* printf into netobuf */
--void netoprintf(const char *fmt, ...) __attribute((format (printf, 1, 2)));
-+/* void netoprintf(const char *fmt, ...) __attribute((format (printf, 1, 2))); */
-+#define netoprintf output_data
-+int output_data(const char *, ...) __attribute((format (printf, 1, 2)));
-+void output_datalen(const char *, int);
-
- extern int pty, net;
- extern char *line;
-@@ -182,7 +185,10 @@ void tty_setsofttab(int);
- void tty_tspeed(int);
- void willoption(int);
- void wontoption(int);
-+
-+#if 0
- void writenet(unsigned char *, int);
-+#endif
-
- #if defined(ENCRYPT)
- extern void (*encrypt_output)(unsigned char *, int);
-diff -up netkit-telnet-0.17/telnetd/slc.c.sa-01-49 netkit-telnet-0.17/telnetd/slc.c
---- netkit-telnet-0.17/telnetd/slc.c.sa-01-49 1999-12-12 15:59:44.000000000 +0100
-+++ netkit-telnet-0.17/telnetd/slc.c 2011-01-20 22:39:54.000000000 +0100
-@@ -183,7 +183,7 @@ int end_slc(unsigned char **bufp) {
- else {
- snprintf(slcbuf+slcoff, sizeof(slcbuf)-slcoff, "%c%c", IAC, SE);
- slcoff += 2;
-- writenet(slcbuf, slcoff);
-+ output_datalen(slcbuf, slcoff);
- netflush(); /* force it out immediately */
- }
- }
-diff -up netkit-telnet-0.17/telnetd/state.c.sa-01-49 netkit-telnet-0.17/telnetd/state.c
---- netkit-telnet-0.17/telnetd/state.c.sa-01-49 1999-12-12 20:41:44.000000000 +0100
-+++ netkit-telnet-0.17/telnetd/state.c 2011-01-20 22:43:34.000000000 +0100
-@@ -37,6 +37,7 @@
- char state_rcsid[] =
- "$Id: state.c,v 1.12 1999/12/12 19:41:44 dholland Exp $";
-
-+#include <stdarg.h>
- #include "telnetd.h"
-
- int not42 = 1;
-@@ -1365,7 +1366,7 @@ void send_status(void) {
- ADD(IAC);
- ADD(SE);
-
-- writenet(statusbuf, ncp - statusbuf);
-+ output_datalen(statusbuf, ncp - statusbuf);
- netflush(); /* Send it on its way */
-
- DIAG(TD_OPTIONS, {printsub('>', statusbuf, ncp - statusbuf); netflush();});
-diff -up netkit-telnet-0.17/telnetd/termstat.c.sa-01-49 netkit-telnet-0.17/telnetd/termstat.c
---- netkit-telnet-0.17/telnetd/termstat.c.sa-01-49 1999-12-12 15:59:45.000000000 +0100
-+++ netkit-telnet-0.17/telnetd/termstat.c 2011-01-20 22:39:54.000000000 +0100
-@@ -128,7 +128,6 @@ static int _terminit = 0;
- void
- localstat()
- {
-- void netflush();
- int need_will_echo = 0;
-
- /*
-diff -up netkit-telnet-0.17/telnetd/utility.c.sa-01-49 netkit-telnet-0.17/telnetd/utility.c
---- netkit-telnet-0.17/telnetd/utility.c.sa-01-49 2011-01-20 22:39:54.000000000 +0100
-+++ netkit-telnet-0.17/telnetd/utility.c 2011-01-20 22:48:02.000000000 +0100
-@@ -38,8 +38,10 @@ char util_rcsid[] =
- "$Id: utility.c,v 1.11 1999/12/12 14:59:45 dholland Exp $";
-
- #define PRINTOPTIONS
-+#define _GNU_SOURCE
-
- #include <stdarg.h>
-+#include <stdio.h>
- #include <sys/utsname.h>
-
- #ifdef AUTHENTICATE
-@@ -52,6 +54,53 @@ char util_rcsid[] =
- * utility functions performing io related tasks
- */
-
-+/*
-+ * 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;
-+}
-+
-+/**
- void
- netoprintf(const char *fmt, ...)
- {
-@@ -67,7 +116,7 @@ netoprintf(const char *fmt, ...)
- va_end(ap);
-
- if (len<0 || len==maxsize) {
-- /* didn't fit */
-+ / * did not fit * /
- netflush();
- }
- else {
-@@ -76,6 +125,7 @@ netoprintf(const char *fmt, ...)
- }
- nfrontp += len;
- }
-+*/
-
- /*
- * ttloop
-@@ -273,10 +323,15 @@ netflush(void)
- int n;
-
- if ((n = nfrontp - nbackp) > 0) {
-+
-+#if 0
-+ /* XXX This causes output_data() to recurse and die */
- DIAG(TD_REPORT,
- { netoprintf("td: netflush %d chars\r\n", n);
- n = nfrontp - nbackp; /* update count */
- });
-+#endif
-+
- #if defined(ENCRYPT)
- if (encrypt_output) {
- char *s = nclearto ? nclearto : nbackp;
-@@ -310,11 +365,14 @@ netflush(void)
- }
- }
- }
-- if (n < 0) {
-- if (errno == EWOULDBLOCK || errno == EINTR)
-- return;
-- cleanup(0);
-- }
-+
-+ if (n == -1) {
-+ if (errno == EWOULDBLOCK || errno == EINTR)
-+ return;
-+ cleanup(0);
-+ /* NOTREACHED */
-+ }
-+
- nbackp += n;
- #if defined(ENCRYPT)
- if (nbackp > nclearto)
-@@ -332,7 +390,7 @@ netflush(void)
- return;
- } /* end of netflush */
-
--
-+#if 0
- /*
- * writenet
- *
-@@ -355,7 +413,7 @@ void writenet(register unsigned char *pt
- nfrontp += len;
-
- } /* end of writenet */
--
-+#endif
-
- /*
- * miscellaneous functions doing a variety of little jobs follow ...
+++ /dev/null
-diff -uNr telnet/Makefile telnet.obsd-cvs/Makefile
---- telnet/Makefile Mon Jul 27 18:25:13 1998
-+++ telnet.obsd-cvs/Makefile Sat Mar 10 10:54:26 2001
-@@ -36,22 +36,20 @@
-
- PROG= telnet
-
--CFLAGS+=-DTERMCAP -DKLUDGELINEMODE -DUSE_TERMIO -DSKEY -Dunix
--CFLAGS+=-DENV_HACK -D_USE_OLD_CURSES_
-+CFLAGS+=-DKLUDGELINEMODE -DUSE_TERMIO -DENV_HACK -DSKEY -Dunix
- CFLAGS+=-I${.CURDIR}/../../lib
--LDADD+= -locurses -ltelnet
--DPADD= ${LIBOLDCURSES} ${LIBTELNET}
-+LDADD+= -lcurses -ltelnet
-+DPADD= ${LIBCURSES} ${LIBTELNET
-
- SRCS= authenc.c commands.c main.c network.c ring.c sys_bsd.c telnet.c \
- terminal.c tn3270.c utilities.c
-
- .include <bsd.own.mk> # for KERBEROS
-
--.if (${KERBEROS} == "yes")
-+.if (${KERBEROS:L} == "yes")
- CFLAGS+=-DENCRYPTION -DAUTHENTICATION -DKRB4
- LDADD+= -lkrb -ldes
- DPADD+= ${LIBDES} ${LIBKRB}
- .endif
-
- .include <bsd.prog.mk>
--
-diff -uNr telnet/commands.c telnet.obsd-cvs/commands.c
---- telnet/commands.c Fri Apr 9 02:30:20 1999
-+++ telnet.obsd-cvs/commands.c Sat Mar 10 10:51:22 2001
-@@ -1,4 +1,4 @@
--/* $OpenBSD: commands.c,v 1.20 1999/01/04 07:55:05 art Exp $ */
-+/* $OpenBSD: commands.c,v 1.34 2000/11/08 21:49:44 aaron Exp $ */
- /* $NetBSD: commands.c,v 1.14 1996/03/24 22:03:48 jtk Exp $ */
-
- /*
-@@ -69,7 +69,7 @@
- int status;
-
- if(argc != 3) {
-- printf("%s sequence challenge\n", argv[0]);
-+ printf("usage: %s sequence challenge\n", argv[0]);
- return 0;
- }
-
-@@ -2175,17 +2175,19 @@
- int gotmachine = 0;
- int l1 = strlen(m1);
- int l2 = strlen(m2);
-- char m1save[64];
-+ char m1save[MAXHOSTNAMELEN];
-
- if (skiprc)
- return;
-
-- strcpy(m1save, m1);
-+ strncpy(m1save, m1, sizeof(m1save));
- m1 = m1save;
-
- if (rcname[0] == 0) {
- char *home = getenv("HOME");
-
-+ if (home == NULL || *home == '\0')
-+ return;
- snprintf (rcname, sizeof(rcname), "%s/.telnetrc",
- home ? home : "");
- }
-@@ -2248,15 +2250,9 @@
- int
- tn(int argc, char *argv[])
- {
-- struct hostent *host = 0, *alias = 0;
--#if defined(AF_INET6)
-- struct sockaddr_in6 sin6;
--#endif
-+ struct addrinfo hints, *res, *res0;
-+ int error;
- struct sockaddr_in sin;
-- struct sockaddr_in ladr;
-- struct sockaddr *sa;
-- int sa_size;
-- struct servent *sp = 0;
- unsigned long temp;
- #if !defined(__linux__)
- extern char *inet_ntoa();
-@@ -2266,15 +2262,18 @@
- int srlen;
- #endif
- char *cmd, *hostp = 0, *portp = 0, *user = 0, *aliasp = 0;
-- int family, port = 0;
--
-+ int retry;
-+#ifdef NI_WITHSCOPEID
-+ const int niflags = NI_NUMERICHOST | NI_WITHSCOPEID;
-+#else
-+ const int niflags = NI_NUMERICHOST;
-+#endif
-+
- /* clear the socket address prior to use */
- memset((char *)&sin, 0, sizeof(sin));
-
- if (connected) {
- printf("?Already connected to %s\r\n", hostname);
-- seteuid(getuid());
-- setuid(getuid());
- return 0;
- }
- if (argc < 2) {
-@@ -2324,8 +2323,6 @@
- }
- usage:
- printf("usage: %s [-l user] [-a] host-name [port]\r\n", cmd);
-- seteuid(getuid());
-- setuid(getuid());
- return 0;
- }
- if (hostp == 0)
-@@ -2340,185 +2337,80 @@
- temp = sourceroute(hostp, &srp, &srlen);
- if (temp == 0) {
- herror(srp);
-- seteuid(getuid());
-- setuid(getuid());
- return 0;
- } else if (temp == -1) {
- printf("Bad source route option: %s\r\n", hostp);
-- seteuid(getuid());
-- setuid(getuid());
- return 0;
- } else {
- abort();
- }
-- } else {
--#endif
-- memset (&sin, 0, sizeof(sin));
--#if defined(HAVE_INET_PTON) && defined(AF_INET6)
-- memset (&sin6, 0, sizeof(sin6));
--
-- if(inet_pton(AF_INET6, hostp, &sin6.sin6_addr)) {
-- sin6.sin6_family = family = AF_INET6;
-- sa = (struct sockaddr *)&sin6;
-- sa_size = sizeof(sin6);
-- strcpy(_hostname, hostp);
-- hostname =_hostname;
-- } else
--#endif
-- if(inet_aton(hostp, &sin.sin_addr)){
-- sin.sin_family = family = AF_INET;
-- sa = (struct sockaddr *)&sin;
-- sa_size = sizeof(sin);
-- strcpy(_hostname, hostp);
-- hostname = _hostname;
-- } else {
--#ifdef HAVE_GETHOSTBYNAME2
-- host = gethostbyname2(hostp, AF_INET6);
-- if(host == NULL)
-- host = gethostbyname2(hostp, AF_INET);
--#else
-- host = gethostbyname(hostp);
--#endif
-- if (host) {
-- strncpy(_hostname, host->h_name, sizeof(_hostname));
-- family = host->h_addrtype;
--
-- switch(family) {
-- case AF_INET:
-- memset(&sin, 0, sizeof(sin));
-- sa_size = sizeof(sin);
-- sa = (struct sockaddr *)&sin;
-- sin.sin_family = family;
--
-- memcpy(&sin.sin_addr, *host->h_addr_list, sizeof(struct in_addr));
-- break;
--#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
-- case AF_INET6:
-- memset(&sin6, 0, sizeof(sin6));
-- sa_size = sizeof(sin6);
-- sa = (struct sockaddr *)&sin6;
-- sin6.sin6_family = family;
-- memcpy(&sin6.sin6_addr, *host->h_addr_list, sizeof(struct in6_addr));
-- break;
--#endif
-- default:
-- fprintf(stderr, "Bad address family: %d\n", family);
-- return 0;
-- }
--
-- _hostname[sizeof(_hostname)-1] = '\0';
-- hostname = _hostname;
-- } else {
-- herror(hostp);
-- seteuid(getuid());
-- setuid(getuid());
-- return 0;
-- }
-- }
--#if defined(IP_OPTIONS) && defined(IPPROTO_IP)
-- }
-+ } else
- #endif
-- if (portp) {
-- if (*portp == '-') {
-- portp++;
-- telnetport = 1;
-- } else
-- telnetport = 0;
-- port = atoi(portp);
-- if (port == 0) {
-- sp = getservbyname(portp, "tcp");
-- if (sp)
-- port = sp->s_port;
-- else {
-- printf("%s: bad port number\r\n", portp);
-- seteuid(getuid());
-- setuid(getuid());
-- return 0;
-- }
-- } else {
-- port = htons(port);
-- }
-- } else {
-- if (sp == 0) {
-- sp = getservbyname("telnet", "tcp");
-- if (sp == 0) {
-- fprintf(stderr, "telnet: tcp/telnet: unknown service\r\n");
-- seteuid(getuid());
-- setuid(getuid());
-- return 0;
-- }
-- port = sp->s_port;
-+ {
-+ hostname = hostp;
-+ memset(&hints, 0, sizeof(hints));
-+ hints.ai_family = PF_UNSPEC;
-+ hints.ai_socktype = SOCK_STREAM;
-+ hints.ai_flags = AI_CANONNAME;
-+ if (portp == NULL) {
-+ portp = "telnet";
-+ } else if (*portp == '-') {
-+ portp++;
-+ telnetport = 1;
-+ }
-+ h_errno = 0;
-+ error = getaddrinfo(hostp, portp, &hints, &res0);
-+ if (error) {
-+ if (error == EAI_SERVICE)
-+ warnx("%s: bad port", portp);
-+ else
-+ warnx("%s: %s", hostp, gai_strerror(error));
-+ if (h_errno)
-+ herror(hostp);
-+ return 0;
- }
-- telnetport = 1;
- }
-- switch(family) {
-- case AF_INET:
-- sin.sin_port = port;
-- printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr));
-- break;
--#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
-- case AF_INET6: {
--#ifndef INET6_ADDRSTRLEN
--#define INET6_ADDRSTRLEN 46
--#endif
-
-- char buf[INET6_ADDRSTRLEN];
--
-- sin6.sin6_port = port;
--#ifdef HAVE_INET_NTOP
-- printf("Trying %s...\r\n", inet_ntop(AF_INET6,
-- &sin6.sin6_addr,
-- buf,
-- sizeof(buf)));
--#endif
-- break;
-- }
--#endif
-- default:
-- abort();
-- }
--
-- do {
-- net = socket(family, SOCK_STREAM, 0);
-- seteuid(getuid());
-- setuid(getuid());
-- if (net < 0) {
-- perror("telnet: socket");
-- return 0;
-+ net = -1;
-+ retry = 0;
-+ for (res = res0; res; res = res->ai_next) {
-+ if (1 /* retry */) {
-+ char hbuf[NI_MAXHOST];
-+
-+ if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-+ NULL, 0, niflags) != 0) {
-+ strcpy(hbuf, "(invalid)");
-+ }
-+ printf("Trying %s...\r\n", hbuf);
- }
-+ net = socket(res->ai_family, res->ai_socktype, res->ai_protocol);
-+ if (net < 0)
-+ continue;
-+
- if (aliasp) {
-- memset ((caddr_t)&ladr, 0, sizeof (ladr));
-- temp = inet_addr(aliasp);
-- if (temp != INADDR_NONE) {
-- ladr.sin_addr.s_addr = temp;
-- ladr.sin_family = AF_INET;
-- alias = gethostbyaddr((char *)&temp, sizeof(temp), AF_INET);
-- } else {
-- alias = gethostbyname(aliasp);
-- if (alias) {
-- ladr.sin_family = alias->h_addrtype;
--#if defined(h_addr) /* In 4.3, this is a #define */
-- memmove((caddr_t)&ladr.sin_addr,
-- alias->h_addr_list[0], alias->h_length);
--#else /* defined(h_addr) */
-- memmove((caddr_t)&ladr.sin_addr, alias->h_addr,
-- alias->h_length);
--#endif /* defined(h_addr) */
-- } else {
-- herror(aliasp);
-- return 0;
-- }
-+ struct addrinfo ahints, *ares;
-+ memset(&ahints, 0, sizeof(ahints));
-+ ahints.ai_family = PF_UNSPEC;
-+ ahints.ai_socktype = SOCK_STREAM;
-+ ahints.ai_flags = AI_PASSIVE;
-+ error = getaddrinfo(aliasp, "0", &ahints, &ares);
-+ if (error) {
-+ warn("%s: %s", aliasp, gai_strerror(error));
-+ close(net);
-+ freeaddrinfo(ares);
-+ continue;
- }
-- ladr.sin_port = htons(0);
--
-- if (bind (net, (struct sockaddr *)&ladr, sizeof(ladr)) < 0) {
-- perror(aliasp);;
-+ if (bind(net, ares->ai_addr, ares->ai_addrlen) < 0) {
-+ perror(aliasp);
- (void) close(net); /* dump descriptor */
-- return 0;
-+ freeaddrinfo(ares);
-+ continue;
- }
-+ freeaddrinfo(ares);
- }
- #if defined(IP_OPTIONS) && defined(IPPROTO_IP)
-- if (srp && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
-+ if (srp && res->ai_family == AF_INET
-+ && setsockopt(net, IPPROTO_IP, IP_OPTIONS, (char *)srp, srlen) < 0)
- perror("setsockopt (IP_OPTIONS)");
- #endif
- #if defined(IPPROTO_IP) && defined(IP_TOS)
-@@ -2542,65 +2434,32 @@
- perror("setsockopt (SO_DEBUG)");
- }
-
-- if (connect(net, sa, sa_size) < 0) {
-- int retry = 0;
--
-- if (host && host->h_addr_list[1]) {
-- int oerrno = errno;
-- retry = 1;
--
-- switch(family) {
-- case AF_INET :
-- fprintf(stderr, "telnet: connect to address %s: ",
-- inet_ntoa(sin.sin_addr));
-- ++host->h_addr_list;
-- memcpy(&sin.sin_addr, *host->h_addr_list, sizeof(struct in_addr));
-- break;
--#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
-- case AF_INET6: {
-- char buf[INET6_ADDRSTRLEN];
--
-- fprintf(stderr, "telnet: connect to address %s: ",
-- inet_ntop(AF_INET6, &sin6.sin6_addr, buf,
-- sizeof(buf)));
-- ++host->h_addr_list;
-- memcpy(&sin6.sin6_addr, *host->h_addr_list, sizeof(struct in6_addr));
-- break;
-- }
--#endif
-- default:
-- abort();
-- }
--
-- errno = oerrno;
-- perror(NULL);
--
-- switch(family) {
-- case AF_INET :
-- printf("Trying %s...\r\n", inet_ntoa(sin.sin_addr));
-- break;
--#if defined(AF_INET6) && defined(HAVE_STRUCT_SOCKADDR_IN6)
-- case AF_INET6: {
-- printf("Trying %s...\r\n", inet_ntop(AF_INET6,
-- &sin6.sin6_addr,
-- buf,
-- sizeof(buf)));
-- break;
-- }
--#endif
-- }
--
-- (void) NetClose(net);
-- continue;
-+ if (connect(net, res->ai_addr, res->ai_addrlen) < 0) {
-+ char hbuf[NI_MAXHOST];
-+
-+ if (getnameinfo(res->ai_addr, res->ai_addrlen, hbuf, sizeof(hbuf),
-+ NULL, 0, NI_NUMERICHOST) != 0) {
-+ strcpy(hbuf, "(invalid)");
- }
-- perror("telnet: Unable to connect to remote host");
-- return 0;
-+ fprintf(stderr, "telnet: connect to address %s: %s\n", hbuf,
-+ strerror(errno));
-+
-+ close(net);
-+ net = -1;
-+ retry++;
-+ continue;
- }
-+
- connected++;
- #if defined(AUTHENTICATION) || defined(ENCRYPTION)
- auth_encrypt_connect(connected);
- #endif /* defined(AUTHENTICATION) */
-- } while (connected == 0);
-+ break;
-+ }
-+ freeaddrinfo(res0);
-+ if (net < 0) {
-+ return 0;
-+ }
- cmdrc(hostp, hostname);
- if (autologin && user == NULL) {
- struct passwd *pw;
-@@ -2652,6 +2511,9 @@
- encrypthelp[] = "turn on (off) encryption ('encrypt ?' for more)",
- #endif
- zhelp[] = "suspend telnet",
-+#ifdef SKEY
-+ skeyhelp[] = "compute response to s/key challenge",
-+#endif
- shellhelp[] = "invoke a subshell",
- envhelp[] = "change environment variables ('environ ?' for more)",
- modestring[] = "try to enter line or character mode ('mode ?' for more)";
-@@ -2690,7 +2552,7 @@
- { "environ", envhelp, env_cmd, 0 },
- { "?", helphelp, help, 0 },
- #if defined(SKEY)
-- { "skey", NULL, skey_calc, 0 },
-+ { "skey", skeyhelp, skey_calc, 0 },
- #endif
- { 0, 0, 0, 0 }
- };
-diff -uNr telnet/externs.h telnet.obsd-cvs/externs.h
---- telnet/externs.h Mon Feb 8 22:56:11 1999
-+++ telnet.obsd-cvs/externs.h Sat Mar 10 10:54:35 2001
-@@ -1,4 +1,4 @@
--/* $OpenBSD: externs.h,v 1.4 1998/03/12 17:31:32 deraadt Exp $ */
-+/* $OpenBSD: externs.h,v 1.5 1998/03/12 2001/01/22 11:03:38 fgsch Exp $ */
- /* $KTH: externs.h,v 1.16 1997/11/29 02:28:35 joda Exp $ */
-
- /*
-@@ -447,7 +447,7 @@
- *Ibackp, /* Oldest byte of 3270 data */
- Ibuf[], /* 3270 buffer */
- *Ifrontp, /* Where next 3270 byte goes */
-- tline[],
-+ tline[200],
- *transcom; /* Transparent command */
-
- extern int
-diff -uNr telnet/main.c telnet.obsd-cvs/main.c
---- telnet/main.c Wed Apr 7 23:23:35 1999
-+++ telnet.obsd-cvs/main.c Sat Mar 10 09:59:35 2001
-@@ -1,4 +1,4 @@
--/* $OpenBSD: main.c,v 1.7 1998/05/15 03:16:38 art Exp $ */
-+/* $OpenBSD: main.c,v 1.10 2001/01/21 22:46:37 aaron Exp $ */
- /* $NetBSD: main.c,v 1.5 1996/02/28 21:04:05 thorpej Exp $ */
-
- /*
-@@ -81,10 +81,10 @@
- prompt,
- #ifdef AUTHENTICATION
- "[-8] [-E] [-K] [-L] [-S tos] [-X atype] [-a] [-c] [-d] [-e char]",
-- "\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] [-b hostalias ]",
-+ "\n\t[-k realm] [-l user] [-f/-F] [-n tracefile] [-b hostalias ] ",
- #else
- "[-8] [-E] [-L] [-S tos] [-a] [-c] [-d] [-e char] [-l user]",
-- "\n\t[-n tracefile] [-b hostalias ]",
-+ "\n\t[-n tracefile] [-b hostalias ] ",
- #endif
- #if defined(TN3270) && defined(unix)
- # ifdef AUTHENTICATION
-@@ -95,13 +95,11 @@
- #else
- "[-r] ",
- #endif
-+ "\n\r "
- #ifdef ENCRYPTION
-- "[-x] [host-name [port]]"
--#else
--
-- "[host-name [port]]"
-+ "[-x] "
- #endif
-- );
-+ "[host-name [port]]");
- exit(1);
- }
-
-@@ -276,8 +274,8 @@
- break;
- case 't':
- #if defined(TN3270) && defined(unix)
-+ (void)strncpy(tline, optarg, sizeof(tline));
- transcom = tline;
-- (void)strcpy(transcom, optarg);
- #else
- fprintf(stderr,
- "%s: Warning: -t ignored, no TN3270 support.\n",
-diff -uNr telnet/sys_bsd.c telnet.obsd-cvs/sys_bsd.c
---- telnet/sys_bsd.c Wed Apr 7 21:38:31 1999
-+++ telnet.obsd-cvs/sys_bsd.c Sat Mar 10 10:55:18 2001
-@@ -1,4 +1,4 @@
--/* $OpenBSD: sys_bsd.c,v 1.6 1998/12/28 11:13:51 deraadt Exp $ */
-+/* $OpenBSD: sys_bsd.c,v 1.8 2000/10/10 15:41:10 millert Exp $ */
- /* $NetBSD: sys_bsd.c,v 1.11 1996/02/28 21:04:10 thorpej Exp $ */
-
- /*
-@@ -35,6 +35,7 @@
- */
-
- #include "telnet_locl.h"
-+#include <err.h>
-
- /*
- * The following routines try to encapsulate what is system dependent
-@@ -198,9 +199,10 @@
- TerminalFlushOutput(void)
- {
- #ifdef TIOCFLUSH
-- (void) ioctl(fileno(stdout), TIOCFLUSH, (char *) 0);
-+ int com = FWRITE;
-+ (void) ioctl(fileno(stdout), TIOCFLUSH, (int *) &com);
- #else
-- (void) ioctl(fileno(stdout), TCFLSH, (char *) 0);
-+ (void) ioctl(fileno(stdout), TCFLSH, (int *) 0);
- #endif
- }
-
-diff -uNr telnet/telnet.c telnet.obsd-cvs/telnet.c
---- telnet/telnet.c Wed Apr 7 23:22:14 1999
-+++ telnet.obsd-cvs/telnet.c Sat Mar 10 11:02:34 2001
-@@ -1,4 +1,4 @@
--/* $OpenBSD: telnet.c,v 1.6 1998/07/27 15:29:29 millert Exp $ */
-+/* $OpenBSD: telnet.c,v 1.11 2000/11/10 15:33:13 provos millert Exp $ */
- /* $NetBSD: telnet.c,v 1.7 1996/02/28 21:04:15 thorpej Exp $ */
-
- /*
-@@ -35,6 +35,8 @@
- */
-
- #include "telnet_locl.h"
-+#include <curses.h>
-+#include <term.h>
-
- #define strip(x) (eight ? (x) : ((x) & 0x7f))
-
-@@ -523,10 +525,9 @@
- }
-
- /*
-- * Given a buffer returned by tgetent(), this routine will turn
-- * the pipe seperated list of names in the buffer into an array
-- * of pointers to null terminated names. We toss out any bad,
-- * duplicate, or verbose names (names with spaces).
-+ * This routine will turn a pipe seperated list of names in the buffer
-+ * into an array of pointers to NUL terminated names. We toss out any
-+ * bad, duplicate, or verbose names (names with spaces).
- */
-
- int is_unique P((char *, char **, char **));
-@@ -554,7 +555,7 @@
- /*
- * Count up the number of names.
- */
-- for (n = 1, cp = buf; *cp && *cp != ':'; cp++) {
-+ for (n = 1, cp = buf; *cp; cp++) {
- if (*cp == '|')
- n++;
- }
-@@ -659,25 +660,6 @@
- return (1);
- }
-
--static char termbuf[1024];
--
--int telnet_setupterm P((char *tname, int fd, int *errp)); /* XXX move elsewhere */
-- /*ARGSUSED*/
-- int
--telnet_setupterm(char *tname, int fd, int *errp)
--{
-- (void)fd;
-- if (tgetent(termbuf, tname) == 1) {
-- termbuf[1023] = '\0';
-- if (errp)
-- *errp = 1;
-- return(0);
-- }
-- if (errp)
-- *errp = 0;
-- return(-1);
--}
--
- int resettermname = 1;
-
- char *gettermname P((void)); /* XXX move elsewhere */
-@@ -687,15 +669,15 @@
- char *tname;
- static char **tnamep = 0;
- static char **next;
-- int err;
-+ int errret;
-
- if (resettermname) {
- resettermname = 0;
- if (tnamep && tnamep != unknown)
- free(tnamep);
- if ((tname = (char *)env_getvalue((unsigned char *)"TERM")) &&
-- (telnet_setupterm(tname, 1, &err) == 0)) {
-- tnamep = mklist(termbuf, tname);
-+ (setupterm(tname, 1, &errret) == 0)) {
-+ tnamep = mklist(ttytype, tname);
- } else {
- if (tname && ((int)strlen(tname) <= 40)) {
- unknown[0] = tname;
-@@ -1482,10 +1464,15 @@
- void
- env_opt_start(void)
- {
-- if (opt_reply)
-- opt_reply = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
-- else
-- opt_reply = (unsigned char *)malloc(OPT_REPLY_SIZE);
-+ unsigned char *p;
-+
-+ if (opt_reply) {
-+ p = (unsigned char *)realloc(opt_reply, OPT_REPLY_SIZE);
-+ if (p == NULL)
-+ free(opt_reply);
-+ } else
-+ p = (unsigned char *)malloc(OPT_REPLY_SIZE);
-+ opt_reply = p;
- if (opt_reply == NULL) {
- /*@*/ printf("env_opt_start: malloc()/realloc() failed!!!\n");
- opt_reply = opt_replyp = opt_replyend = NULL;
-@@ -1532,9 +1519,13 @@
- strlen((char *)ep) + 6 > opt_replyend)
- {
- int len;
-+ unsigned char *p;
- opt_replyend += OPT_REPLY_SIZE;
- len = opt_replyend - opt_reply;
-- opt_reply = (unsigned char *)realloc(opt_reply, len);
-+ p = (unsigned char *)realloc(opt_reply, len);
-+ if (p == NULL)
-+ free(opt_reply);
-+ opt_reply = p;
- if (opt_reply == NULL) {
- /*@*/ printf("env_opt_add: realloc() failed!!!\n");
- opt_reply = opt_replyp = opt_replyend = NULL;
-@@ -1945,7 +1936,7 @@
- command(0, "z\n", 2);
- continue;
- }
-- if (sc == escape) {
-+ if (sc == escape && escape != _POSIX_VDISABLE) {
- command(0, (char *)tbp, tcc);
- bol = 1;
- count += tcc;
-@@ -1962,7 +1953,7 @@
- }
- if ((sc == '\n') || (sc == '\r'))
- bol = 1;
-- } else if (sc == escape) {
-+ } else if (sc == escape && escape != _POSIX_VDISABLE) {
- /*
- * Double escape is a pass through of a single escape character.
- */
-diff -uNr telnet/telnet_locl.h telnet.obsd-cvs/telnet_locl.h
---- telnet/telnet_locl.h Thu Mar 12 06:57:44 1998
-+++ telnet.obsd-cvs/telnet_locl.h Sat Mar 10 11:12:37 2001
-@@ -1,4 +1,4 @@
--/* $OpenBSD: telnet_locl.h,v 1.1 1998/03/12 04:57:44 art Exp $ */
-+/* $OpenBSD: telnet_locl.h,v 1.2 1999/12/11 09:08:09 itojun Exp $ */
- /* $KTH: telnet_locl.h,v 1.13 1997/11/03 21:37:55 assar Exp $ */
-
- /*
-@@ -86,7 +86,5 @@
- #include "defines.h"
- #include "types.h"
-
--#undef AF_INET6 /* XXX - it has not been tested and it doesn't exist yet */
--
- /* prototypes */
-
-diff -uNr libtelnet/kerberos.c libtelnet.obsd-cvs/kerberos.c
---- libtelnet/kerberos.c Mon Feb 8 23:38:17 1999
-+++ libtelnet.obsd-cvs/kerberos.c Sat Mar 10 11:11:03 2001
-@@ -320,11 +320,10 @@
- char ts[MAXPATHLEN];
- struct passwd *pw = getpwnam(UserNameRequested);
-
-- if(pw){
-+ if (pw) {
- snprintf(ts, sizeof(ts),
-- "%s%u",
-- TKT_ROOT,
-- (unsigned)pw->pw_uid);
-+ "%s%u", TKT_ROOT, (unsigned)pw->pw_uid);
-+ /* XXX allocation failure? */
- setenv("KRBTKFILE", ts, 1);
- }
- Data(ap, KRB_ACCEPT, NULL, 0);
-@@ -609,16 +608,26 @@
- {
- unsigned char *p = buf;
-
-- p += krb_put_nir(cred->service, cred->instance, cred->realm, p);
-+ memcpy (p, cred->service, ANAME_SZ);
-+ p += ANAME_SZ;
-+ memcpy (p, cred->instance, INST_SZ);
-+ p += INST_SZ;
-+ memcpy (p, cred->realm, REALM_SZ);
-+ p += REALM_SZ;
- memcpy(p, cred->session, 8);
- p += 8;
- *p++ = cred->lifetime;
- *p++ = cred->kvno;
-- p += krb_put_int(cred->ticket_st.length, p, 4);
-+ p += krb_put_int(cred->ticket_st.length, p, 4, 4);
- memcpy(p, cred->ticket_st.dat, cred->ticket_st.length);
- p += cred->ticket_st.length;
-- p += krb_put_int(cred->issue_date, p, 4);
-- p += krb_put_nir(cred->pname, cred->pinst, NULL, p);
-+ p += krb_put_int(cred->issue_date, p, 4, 4);
-+ strncpy (cred->pname, p, ANAME_SZ);
-+ cred->pname[ANAME_SZ - 1] = '\0';
-+ p += ANAME_SZ;
-+ strncpy (cred->pinst, p, INST_SZ);
-+ cred->pinst[INST_SZ - 1] = '\0';
-+ p += INST_SZ;
- return p - buf;
- }
-
-@@ -627,7 +636,16 @@
- {
- unsigned char *p = buf;
-
-- p += krb_get_nir(p, cred->service, cred->instance, cred->realm);
-+ strncpy (cred->service, p, ANAME_SZ);
-+ cred->service[ANAME_SZ - 1] = '\0';
-+ p += ANAME_SZ;
-+ strncpy (cred->instance, p, INST_SZ);
-+ cred->instance[INST_SZ - 1] = '\0';
-+ p += INST_SZ;
-+ strncpy (cred->realm, p, REALM_SZ);
-+ cred->realm[REALM_SZ - 1] = '\0';
-+ p += REALM_SZ;
-+
- memcpy(cred->session, p, 8);
- p += 8;
- cred->lifetime = *p++;
-@@ -636,7 +654,10 @@
- memcpy(cred->ticket_st.dat, p, cred->ticket_st.length);
- cred->ticket_st.mbz = 0;
- p += krb_get_int(p, (u_int32_t *)&cred->issue_date, 4, 0);
-- p += krb_get_nir(p, cred->pname, cred->pinst, NULL);
-+ p += krb_get_nir(p,
-+ cred->pname, sizeof(cred->pname),
-+ cred->pinst, sizeof(cred->pinst),
-+ NULL, 0);
- return 0;
- }
-
---- telnet/telnet.1 Thu Nov 12 01:01:46 1998
-+++ telnet.obsd-cvs/telnet.1 Thu Nov 9 19:52:41 2000
-@@ -1,4 +1,4 @@
--.\" $OpenBSD: telnet.1,v 1.14 1998/11/11 23:01:46 aaron Exp $
-+.\" $OpenBSD: telnet.1,v 1.27 2000/11/09 17:52:41 aaron Exp $
- .\" $NetBSD: telnet.1,v 1.5 1996/02/28 21:04:12 thorpej Exp $
- .\"
- .\" Copyright (c) 1983, 1990, 1993
-@@ -36,45 +36,34 @@
- .\"
- .Dd February 3, 1994
- .Dt TELNET 1
--.Os BSD 4.2
-+.Os
- .Sh NAME
- .Nm telnet
--.Nd user interface to the
-+.Nd user interface to the
- .Tn TELNET
- protocol
- .Sh SYNOPSIS
- .Nm telnet
--.Op Fl 8
--.Op Fl E
--.Op Fl F
--.Op Fl K
--.Op Fl L
--.Op Fl S Ar tos
-+.Op Fl 8EFKLacdfrx
- .Op Fl X Ar authtype
--.Op Fl a
- .Op Fl b Ar hostalias
--.Op Fl c
--.Op Fl d
- .Op Fl e Ar escapechar
--.Op Fl f
- .Op Fl k Ar realm
- .Op Fl l Ar user
- .Op Fl n Ar tracefile
--.Op Fl r
--.Op Fl x
- .Oo
- .Ar host
- .Op Ar port
- .Oc
- .Sh DESCRIPTION
- The
--.Nm telnet
-+.Nm
- command
--is used to communicate with another host using the
-+is used to communicate with another host using the
- .Tn TELNET
- protocol.
- If
--.Nm telnet
-+.Nm
- is invoked without the
- .Ar host
- argument, it enters command mode,
-@@ -85,11 +74,11 @@
- .Ic open
- command with those arguments.
- .Pp
--Options:
--.Bl -tag -width indent
-+The options are as follows:
-+.Bl -tag -width Ds
- .It Fl 8
--Specifies an 8-bit data path. This causes an attempt to
--negotiate the
-+Specifies an 8-bit data path.
-+This causes an attempt to negotiate the
- .Dv TELNET BINARY
- option on both input and output.
- .It Fl E
-@@ -103,18 +92,9 @@
- .It Fl K
- Specifies no automatic login to the remote system.
- .It Fl L
--Specifies an 8-bit data path on output. This causes the
--BINARY option to be negotiated on output.
--.It Fl S Ar tos
--Sets the IP type-of-service (TOS) option for the telnet
--connection to the value
--.Ar tos ,
--which can be a numeric TOS value
--or, on systems that support it, a symbolic
--TOS name found in the
--.Pa /etc/iptos
--file.
--.It Fl X Ar atype
-+Specifies an 8-bit data path on output.
-+This causes the BINARY option to be negotiated on output.
-+.It Fl X Ar atype
- Disables the
- .Ar atype
- type of authentication.
-@@ -144,7 +124,8 @@
- .It Fl c
- Disables the reading of the user's
- .Pa \&.telnetrc
--file. (See the
-+file.
-+(See the
- .Ic toggle skiprc
- command on this man page.)
- .It Fl d
-@@ -152,7 +133,7 @@
- .Ic debug
- toggle to
- .Dv TRUE .
--.It Fl e Ar escapechar
-+.It Fl e Ar escapechar
- Sets the initial
- .Nm
- escape character to
-@@ -169,14 +150,14 @@
- If Kerberos authentication is being used, the
- .Fl k
- option requests that
--.Nm telnet
-+.Nm
- obtain tickets for the remote host in
- realm
- .Ar realm
- instead of the remote host's realm, as determined
- by
- .Xr krb_realmofhost 3 .
--.It Fl l Ar user
-+.It Fl l Ar user
- When connecting to the remote system, if the remote system
- understands the
- .Ev ENVIRON
-@@ -189,7 +170,7 @@
- This option may also be used with the
- .Ic open
- command.
--.It Fl n Ar tracefile
-+.It Fl n Ar tracefile
- Opens
- .Ar tracefile
- for recording trace information.
-@@ -210,35 +191,38 @@
- Indicates the official name, an alias, or the Internet address
- of a remote host.
- .It Ar port
--Indicates a port number (address of an application). If a number is
--not specified, the default
--.Nm telnet
-+Indicates a port number (address of an application).
-+If a number is not specified, the default
-+.Nm
- port is used.
- .El
- .Pp
--When in rlogin mode, a line of the form ~. disconnects from the
-+When in rlogin mode, a line of the form ~.
-+disconnects from the
- remote host; ~ is the telnet escape character.
- Similarly, the line ~^Z suspends the telnet session.
- The line ~^] escapes to the normal telnet escape prompt.
- .Pp
- Once a connection has been opened,
--.Nm telnet
-+.Nm
- will attempt to enable the
- .Dv TELNET LINEMODE
- option.
- If this fails,
--.Nm telnet
-+.Nm
- will revert to one of two input modes:
- either ``character at a time''
- or ``old line by line''
- depending on what the remote system supports.
- .Pp
--When
-+When
- .Dv LINEMODE
- is enabled, character processing is done on the
--local system, under the control of the remote system. When input
-+local system, under the control of the remote system.
-+When input
- editing or character echoing is to be disabled, the remote system
--will relay that information. The remote system will also relay
-+will relay that information.
-+The remote system will also relay
- changes to any special characters that happen on the remote
- system, so that they can take effect on the local system.
- .Pp
-@@ -252,7 +236,7 @@
- (this would mostly be used to enter passwords
- without the password being echoed).
- .Pp
--If the
-+If the
- .Dv LINEMODE
- option is enabled, or if the
- .Ic localchars
-@@ -267,7 +251,7 @@
- characters are trapped locally, and sent as
- .Tn TELNET
- protocol sequences to the remote side.
--If
-+If
- .Dv LINEMODE
- has ever been enabled, then the user's
- .Ic susp
-@@ -278,9 +262,9 @@
- protocol sequences,
- and
- .Ic quit
--is sent as a
-+is sent as a
- .Dv TELNET ABORT
--instead of
-+instead of
- .Dv BREAK .
- There are options (see
- .Ic toggle
-@@ -296,17 +280,26 @@
- (in the case of
- .Ic quit
- and
--.Ic intr ) .
-+.Ic intr ) .
- .Pp
- While connected to a remote host,
--.Nm telnet
-+.Nm
- command mode may be entered by typing the
--.Nm telnet
-+.Nm
- ``escape character'' (initially ``^]'').
- When in command mode, the normal terminal editing conventions are available.
-+Note that the escape character will return to the command mode of the initial
-+invocation of
-+.Nm
-+that has the controlling terminal.
-+Use the
-+.Cm send escape
-+command to switch to command mode in subsequent
-+.Nm
-+processes on remote hosts.
- .Pp
- The following
--.Nm telnet
-+.Nm
- commands are available.
- Only enough of each command to uniquely identify it need be typed
- (this is also true for arguments to the
-@@ -320,26 +313,28 @@
- .Ic display
- commands).
- .Bl -tag -width "mode type"
--.It Ic auth Ar argument Op Ar ...
-+.It Ic auth Ar argument Op Ar ...
- The
- .Ic auth
- command manipulates the information sent through the
- .Dv TELNET AUTHENTICATE
--option. Valid arguments for the
--auth command are as follows:
-+option.
-+Valid arguments for the
-+.Ic auth
-+command are as follows:
- .Bl -tag -width "disable type"
- .It Ic disable Ar type
- Disables the specified
- .Ar type
--of authentication. To
--obtain a list of available types, use the
-+of authentication.
-+To obtain a list of available types, use the
- .Ic auth disable \&?
- command.
- .It Ic enable Ar type
- Enables the specified
- .Ar type
--of authentication. To
--obtain a list of available types, use the
-+of authentication.
-+To obtain a list of available types, use the
- .Ic auth enable \&?
- command.
- .It Ic status
-@@ -350,7 +345,7 @@
- Close a
- .Tn TELNET
- session and return to command mode.
--.It Ic display Ar argument Op Ar ...
-+.It Ic display Ar argument Op Ar ...
- Displays all, or some, of the
- .Ic set
- and
-@@ -368,26 +363,27 @@
- .It Ic disable Ar type Ic [input|output]
- Disables the specified
- .Ar type
--of encryption. If you
--omit
-+of encryption.
-+If you omit
- .Ic input
- and
- .Ic output ,
- both input and output
--are disabled. To obtain a list of available
--types, use the
-+are disabled.
-+To obtain a list of available types, use the
- .Ic encrypt disable \&?
- command.
- .It Ic enable Ar type Ic [input|output]
- Enables the specified
- .Ar type
--of encryption. If you
--omit
-+of encryption.
-+If you omit
- .Ic input
- and
- .Ic output ,
- both input and output are
--enabled. To obtain a list of available types, use the
-+enabled.
-+To obtain a list of available types, use the
- .Ic encrypt enable \&?
- command.
- .It Ic input
-@@ -407,18 +403,20 @@
- .Ic encrypt stop output
- command.
- .It Ic start Ic [input|output]
--Attempts to start encryption. If you omit
-+Attempts to start encryption.
-+If you omit
- .Ic input
- and
--.Ic output,
--both input and output are enabled. To
--obtain a list of available types, use the
-+.Ic output ,
-+both input and output are enabled.
-+To obtain a list of available types, use the
- .Ic encrypt enable \&?
- command.
- .It Ic status
- Lists the current status of encryption.
- .It Ic stop Ic [input|output]
--Stops encryption. If you omit
-+Stops encryption.
-+If you omit
- .Ic input
- and
- .Ic output ,
-@@ -431,7 +429,7 @@
- .Ic encrypt stop
- commands.
- .El
--.It Ic environ Ar arguments Op Ar ...
-+.It Ic environ Ar arguments Op Ar ...
- The
- .Ic environ
- command is used to manipulate the
-@@ -456,7 +454,7 @@
- .Ic environ
- command are:
- .Bl -tag -width Fl
--.It Ic define Ar variable value
-+.It Ic define Ar variable value
- Define the variable
- .Ar variable
- to have a value of
-@@ -466,15 +464,15 @@
- .Ar value
- may be enclosed in single or double quotes so
- that tabs and spaces may be included.
--.It Ic undefine Ar variable
-+.It Ic undefine Ar variable
- Remove
- .Ar variable
- from the list of environment variables.
--.It Ic export Ar variable
-+.It Ic export Ar variable
- Mark the variable
- .Ar variable
- to be exported to the remote side.
--.It Ic unexport Ar variable
-+.It Ic unexport Ar variable
- Mark the variable
- .Ar variable
- to not be exported unless
-@@ -508,7 +506,7 @@
- suspending a user's session for later reattachment,
- the logout argument indicates that you
- should terminate the session immediately.
--.It Ic mode Ar type
-+.It Ic mode Ar type
- .Ar type
- is one of several options, depending on the state of the
- .Tn TELNET
-@@ -529,40 +527,40 @@
- option, or, if the remote side does not understand the
- .Dv LINEMODE
- option, then attempt to enter ``old-line-by-line'' mode.
--.It Ic isig Pq Ic \-isig
--Attempt to enable (disable) the
-+.It Ic isig Pq Ic \-isig
-+Attempt to enable (disable) the
- .Dv TRAPSIG
--mode of the
-+mode of the
- .Dv LINEMODE
- option.
--This requires that the
-+This requires that the
- .Dv LINEMODE
- option be enabled.
--.It Ic edit Pq Ic \-edit
--Attempt to enable (disable) the
-+.It Ic edit Pq Ic \-edit
-+Attempt to enable (disable) the
- .Dv EDIT
--mode of the
-+mode of the
- .Dv LINEMODE
- option.
--This requires that the
-+This requires that the
- .Dv LINEMODE
- option be enabled.
--.It Ic softtabs Pq Ic \-softtabs
--Attempt to enable (disable) the
-+.It Ic softtabs Pq Ic \-softtabs
-+Attempt to enable (disable) the
- .Dv SOFT_TAB
--mode of the
-+mode of the
- .Dv LINEMODE
- option.
--This requires that the
-+This requires that the
- .Dv LINEMODE
- option be enabled.
--.It Ic litecho Pq Ic \-litecho
--Attempt to enable (disable) the
-+.It Ic litecho Pq Ic \-litecho
-+Attempt to enable (disable) the
- .Dv LIT_ECHO
--mode of the
-+mode of the
- .Dv LINEMODE
- option.
--This requires that the
-+This requires that the
- .Dv LINEMODE
- option be enabled.
- .It Ic \&?
-@@ -579,7 +577,7 @@
- Open a connection to the named host.
- If no port number
- is specified,
--.Nm telnet
-+.Nm
- will attempt to contact a
- .Tn TELNET
- server at the default port.
-@@ -594,24 +592,29 @@
- .Ev ENVIRON
- option.
- When connecting to a non-standard port,
--.Nm telnet
-+.Nm
- omits any automatic initiation of
- .Tn TELNET
--options. When the port number is preceded by a minus sign,
-+options.
-+When the port number is preceded by a minus sign,
- the initial option negotiation is done.
- After establishing a connection, the file
- .Pa \&.telnetrc
- in the
--user's home directory is opened. Lines beginning with a ``#'' are
--comment lines. Blank lines are ignored. Lines that begin
--without white space are the start of a machine entry. The
--first thing on the line is the name of the machine that is
--being connected to. The rest of the line, and successive
--lines that begin with white space are assumed to be
--.Nm telnet
-+user's home directory is opened.
-+Lines beginning with a ``#'' are
-+comment lines.
-+Blank lines are ignored.
-+Lines that begin
-+without whitespace are the start of a machine entry.
-+The first thing on the line is the name of the machine that is
-+being connected to.
-+The rest of the line, and successive
-+lines that begin with whitespace are assumed to be
-+.Nm
- commands and are processed as if they had been typed
- in manually to the
--.Nm telnet
-+.Nm
- command prompt.
- .It Ic quit
- Close any open
-@@ -619,7 +622,7 @@
- session and exit
- .Nm telnet .
- An end-of-file (in command mode) will also close a session and exit.
--.It Ic send Ar arguments
-+.It Ic send Ar arguments
- Sends one or more special character sequences to the remote host.
- The following are the arguments which may be specified
- (more than one argument may be specified at a time):
-@@ -673,7 +676,7 @@
- sequence.
- .It Ic escape
- Sends the current
--.Nm telnet
-+.Nm
- escape character (initially ``^]'').
- .It Ic ga
- Sends the
-@@ -788,12 +791,12 @@
- .Ic send
- command.
- .El
--.It Ic set Ar argument value
--.It Ic unset Ar argument value
-+.It Ic set Ar argument value
-+.It Ic unset Ar argument value
- The
- .Ic set
- command will set any one of a number of
--.Nm telnet
-+.Nm
- variables to a specific value or to
- .Dv TRUE .
- The special value
-@@ -811,7 +814,8 @@
- .Ic display
- command.
- The variables which may be set or unset, but not toggled, are
--listed here. In addition, any of the variables for the
-+listed here.
-+In addition, any of the variables for the
- .Ic toggle
- command may be explicitly set or unset using
- the
-@@ -832,7 +836,8 @@
- sequence (see
- .Ic send ayt
- preceding) is sent to the
--remote host. The initial value for the "Are You There"
-+remote host.
-+The initial value for the "Are You There"
- character is the terminal's status character.
- .It Ic echo
- This is the value (initially ``^E'') which, when in
-@@ -841,7 +846,7 @@
- echoing of entered characters (for entering, say, a password).
- .It Ic eof
- If
--.Nm telnet
-+.Nm
- is operating in
- .Dv LINEMODE
- or ``old line by line'' mode, entering this character
-@@ -854,7 +859,7 @@
- character.
- .It Ic erase
- If
--.Nm telnet
-+.Nm
- is in
- .Ic localchars
- mode (see
-@@ -862,7 +867,7 @@
- .Ic localchars
- below),
- and if
--.Nm telnet
-+.Nm
- is operating in ``character at a time'' mode, then when this
- character is typed, a
- .Dv TELNET EC
-@@ -879,14 +884,14 @@
- character.
- .It Ic escape
- This is the
--.Nm telnet
-+.Nm
- escape character (initially ``^['') which causes entry
- into
--.Nm telnet
-+.Nm
- command mode (when connected to a remote system).
- .It Ic flushoutput
- If
--.Nm telnet
-+.Nm
- is in
- .Ic localchars
- mode (see
-@@ -916,12 +921,13 @@
- .Dv LINEMODE ,
- these are the
- characters that, when typed, cause partial lines to be
--forwarded to the remote system. The initial value for
-+forwarded to the remote system.
-+The initial value for
- the forwarding characters are taken from the terminal's
- eol and eol2 characters.
- .It Ic interrupt
- If
--.Nm telnet
-+.Nm
- is in
- .Ic localchars
- mode (see
-@@ -945,7 +951,7 @@
- character.
- .It Ic kill
- If
--.Nm telnet
-+.Nm
- is in
- .Ic localchars
- mode (see
-@@ -953,7 +959,7 @@
- .Ic localchars
- below),
- and if
--.Nm telnet
-+.Nm
- is operating in ``character at a time'' mode, then when this
- character is typed, a
- .Dv TELNET EL
-@@ -970,7 +976,7 @@
- character.
- .It Ic lnext
- If
--.Nm telnet
-+.Nm
- is operating in
- .Dv LINEMODE
- or ``old line by line'' mode, then this character is taken to
-@@ -985,7 +991,7 @@
- character.
- .It Ic quit
- If
--.Nm telnet
-+.Nm
- is in
- .Ic localchars
- mode (see
-@@ -1009,7 +1015,7 @@
- character.
- .It Ic reprint
- If
--.Nm telnet
-+.Nm
- is operating in
- .Dv LINEMODE
- or old line by line'' mode, then this character is taken to
-@@ -1031,8 +1037,9 @@
- This character, at the beginning of a line, followed by
- a "." closes the connection; when followed by a ^Z it
- suspends the
--.Nm telnet
--command. The initial state is to
-+.Nm
-+command.
-+The initial state is to
- disable the
- .Ic rlogin
- escape character.
-@@ -1066,7 +1073,7 @@
- character.
- .It Ic susp
- If
--.Nm telnet
-+.Nm
- is in
- .Ic localchars
- mode, or
-@@ -1093,12 +1100,13 @@
- .Ic option
- tracing being
- .Dv TRUE ,
--will be written. If it is set to
-+will be written.
-+If it is set to
- .Dq Fl ,
- then tracing information will be written to standard output (the default).
- .It Ic worderase
- If
--.Nm telnet
-+.Nm
- is operating in
- .Dv LINEMODE
- or ``old line by line'' mode, then this character is taken to
-@@ -1117,25 +1125,32 @@
- .Pq Ic unset
- commands.
- .El
--.It Ic slc Ar state
-+.It Ic skey Ar sequence challenge
-+The
-+.Ic skey
-+command computes a response to the S/Key challenge.
-+See
-+.Xr skey 1
-+for more information on the S/Key system.
-+.It Ic slc Ar state
- The
- .Ic slc
- command (Set Local Characters) is used to set
- or change the state of the special
--characters when the
-+characters when the
- .Dv TELNET LINEMODE
- option has
--been enabled. Special characters are characters that get
--mapped to
-+been enabled.
-+Special characters are characters that get mapped to
- .Tn TELNET
- commands sequences (like
- .Ic ip
- or
--.Ic quit )
-+.Ic quit )
- or line editing characters (like
- .Ic erase
- and
--.Ic kill ) .
-+.Ic kill ) .
- By default, the local special characters are exported.
- .Bl -tag -width Fl
- .It Ic check
-@@ -1144,15 +1159,15 @@
- character settings, and if there are any discrepancies with
- the local side, the local side will switch to the remote value.
- .It Ic export
--Switch to the local defaults for the special characters. The
--local default characters are those of the local terminal at
-+Switch to the local defaults for the special characters.
-+The local default characters are those of the local terminal at
- the time when
--.Nm telnet
-+.Nm
- was started.
- .It Ic import
- Switch to the remote defaults for the special characters.
- The remote default characters are those of the remote system
--at the time when the
-+at the time when the
- .Tn TELNET
- connection was established.
- .It Ic \&?
-@@ -1165,13 +1180,13 @@
- .Nm telnet .
- This includes the peer one is connected to, as well
- as the current mode.
--.It Ic toggle Ar arguments Op Ar ...
-+.It Ic toggle Ar arguments Op Ar ...
- Toggle (between
- .Dv TRUE
- and
- .Dv FALSE )
- various flags that control how
--.Nm telnet
-+.Nm
- responds to events.
- These flags may be set explicitly to
- .Dv TRUE
-@@ -1206,7 +1221,7 @@
- sequences; see
- .Ic set
- above for details),
--.Nm telnet
-+.Nm
- refuses to display any data on the user's terminal
- until the remote system acknowledges (via a
- .Dv TELNET TIMING MARK
-@@ -1220,13 +1235,14 @@
- done an "stty noflsh", otherwise
- .Dv FALSE
- (see
--.Xr stty 1 ) .
-+.Xr stty 1 ) .
- .It Ic autodecrypt
- When the
- .Dv TELNET ENCRYPT
- option is negotiated, by
- default the actual encryption (decryption) of the data
--stream does not start automatically. The
-+stream does not start automatically.
-+The
- .Ic autoencrypt
- .Pq Ic autodecrypt
- command states that encryption of the
-@@ -1238,7 +1254,8 @@
- .Dv TELNET AUTHENTICATION
- option
- .Tn TELNET
--attempts to use it to perform automatic authentication. If the
-+attempts to use it to perform automatic authentication.
-+If the
- .Dv AUTHENTICATION
- option is not supported, the user's login
- name are propagated through the
-@@ -1314,7 +1331,7 @@
- The initial value for this toggle is
- .Dv FALSE .
- .It Ic debug
--Toggles socket level debugging (useful only to the super-user).
-+Toggles socket level debugging (useful only to the superuser).
- The initial value for this toggle is
- .Dv FALSE .
- .It Ic encdebug
-@@ -1340,7 +1357,7 @@
- .Ic brk ,
- .Ic ec ,
- and
--.Ic el ;
-+.Ic el ;
- see
- .Ic send
- above).
-@@ -1379,7 +1396,7 @@
- .Dv FALSE .
- .It Ic options
- Toggles the display of some internal
--.Nm telnet
-+.Nm
- protocol processing (having to do with
- .Tn TELNET
- options).
-@@ -1404,8 +1421,8 @@
- skips the reading of the
- .Pa \&.telnetrc
- file in the user's home
--directory when connections are opened. The initial
--value for this toggle is
-+directory when connections are opened.
-+The initial value for this toggle is
- .Dv FALSE .
- .It Ic termdata
- Toggles the display of all terminal data (in hexadecimal format).
-@@ -1416,9 +1433,10 @@
- .Ic verbose_encrypt
- toggle is
- .Dv TRUE ,
--.Nm telnet
-+.Nm
- prints out a message each time encryption is enabled or
--disabled. The initial value for this toggle is
-+disabled.
-+The initial value for this toggle is
- .Dv FALSE .
- .It Ic \&?
- Displays the legal
-@@ -1430,22 +1448,24 @@
- .Nm telnet .
- This command only works when the user is using the
- .Xr csh 1 .
--.It Ic \&! Op Ar command
-+.It Ic \&! Op Ar command
- Execute a single command in a subshell on the local
--system. If
-+system.
-+If
- .Ar command
- is omitted, then an interactive
- subshell is invoked.
--.It Ic \&? Op Ar command
--Get help. With no arguments,
--.Nm telnet
-+.It Ic \&? Op Ar command
-+Get help.
-+With no arguments,
-+.Nm
- prints a help summary.
- If a command is specified,
--.Nm telnet
-+.Nm
- will print the help information for just that command.
- .El
- .Sh ENVIRONMENT
--.Nm telnet
-+.Nm
- uses at least the
- .Ev HOME ,
- .Ev SHELL ,
-@@ -1464,16 +1484,18 @@
- .El
- .Sh HISTORY
- The
--.Nm telnet
-+.Nm
- command appeared in
- .Bx 4.2 .
- .Sh NOTES
- On some remote systems, echo has to be turned off manually when in
- ``old line by line'' mode.
- .Pp
--In ``old line by line'' mode or
-+In ``old line by line'' mode or
- .Dv LINEMODE
- the terminal's
- .Ic eof
- character is only recognized (and sent to the remote system)
- when it is the first character on a line.
-+.Pp
-+Source routing is not supported yet for IPv6.
+++ /dev/null
---- netkit-telnet-0.17/telnet/commands.c.old 2006-04-30 10:24:49.000000000 -0700
-+++ netkit-telnet-0.17/telnet/commands.c 2006-04-30 10:37:10.000000000 -0700
-@@ -1669,9 +1669,15 @@
-
- /* If this is not the full name, try to get it via DNS */
- if (strchr(hbuf, '.') == 0) {
-- struct hostent *he = gethostbyname(hbuf);
-- if (he != 0)
-- strncpy(hbuf, he->h_name, sizeof hbuf-1);
-+ struct addrinfo hints;
-+ struct addrinfo *res;
-+ memset (&hints, '\0', sizeof (hints));
-+ hints.ai_flags = AI_V4MAPPED | AI_ADDRCONFIG | AI_CANONNAME;
-+ if (getaddrinfo (hbuf, NULL, &hints, &res) == 0) {
-+ if (res->ai_canonname != NULL)
-+ strncpy(hbuf, res->ai_canonname, sizeof hbuf-1);
-+ freeaddrinfo (res);
-+ }
- hbuf[sizeof hbuf-1] = '\0';
- }
-
-@@ -2832,17 +2838,15 @@
- if (!c)
- cp2 = 0;
-
-- if ((tmp = inet_addr(cp)) != -1) {
-- sin_addr.s_addr = tmp;
-- } else if ((host = gethostbyname(cp))) {
--#if defined(h_addr)
-- memmove((caddr_t)&sin_addr,
-- host->h_addr_list[0],
-- sizeof(sin_addr));
--#else
-- memmove((caddr_t)&sin_addr, host->h_addr,
-- sizeof(sin_addr));
--#endif
-+ struct addrinfo hints;
-+ memset (&hints, '\0', sizeof (hints));
-+ // XXX The code here seems to allow only IPv4 addresses.
-+ hints.ai_family = AF_INET;
-+ hints.ai_flags = AI_ADDRCONFIG;
-+ struct addrinfo *aires;
-+ if (getaddrinfo (cp, NULL, &hints, &aires) == 0) {
-+ sin_addr = ((struct sockaddr_in *) aires->ai_addr)->sin_addr;
-+ freeaddrinfo (aires);
- } else {
- *cpp = cp;
- return(0);
+++ /dev/null
---- telnetd/telnetd.c 2005-01-19 14:37:25.000000000 +0000
-+++ telnetd/telnetd.c.new 2005-01-19 14:48:12.000000000 +0000
-@@ -697,6 +697,7 @@
- int on = 1;
- char *HE;
- const char *IM;
-+ int pty_read_ok = 0; /* track whether the pty read has worked yet */
-
- /*
- * Initialize the slc mapping table.
-@@ -1016,12 +1017,13 @@
- * off the master side before the slave side is
- * opened, we get EIO.
- */
-- if (pcc < 0 && (errno == EWOULDBLOCK || errno == EIO)) {
-+ if (pcc < 0 && (errno == EWOULDBLOCK || (errno == EIO && pty_read_ok == 0))) {
- pcc = 0;
- }
- else {
- if (pcc <= 0)
- break;
-+ pty_read_ok = 1; /* mark connection up for read */
- #ifdef LINEMODE
- /*
- * If ioctl from pty, pass it through net
+++ /dev/null
---- telnetd/defs.h Mon Aug 2 06:14:03 1999
-+++ telnetd.new/defs.h Sun Mar 11 03:28:13 2001
-@@ -56,6 +56,7 @@
- #include <sys/file.h>
- #include <sys/stat.h>
- #include <sys/time.h>
-+#include <time.h>
- #include <sys/ioctl.h>
- #include <netinet/in.h>
- #include <arpa/telnet.h>
--- /dev/null
+Description: Use cmake as build system
+Author: Christoph Biedl <debian.axhn@manchmal.in-ulm.de>
+Bug-Debian: https://bugs.debian.org/912131
+Last-Update: 2019-02-24
+
+--- /dev/null
++++ b/CMakeLists.txt
+@@ -0,0 +1,27 @@
++cmake_minimum_required(VERSION 3.7)
++project(netkit-telnet)
++
++set(BIN_DIR "${CMAKE_INSTALL_PREFIX}/bin")
++set(SBIN_DIR "${CMAKE_INSTALL_PREFIX}/sbin")
++set(MAN_DIR "${CMAKE_INSTALL_PREFIX}/share/man")
++
++set(USE_GLIBC 1)
++
++set(
++ CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
++ -D_GNU_SOURCE \
++ -DACCEPT_USERVAR \
++ -Wall \
++ -Wno-trigraphs \
++")
++set(
++ CMAKE_C_FLAGS "${CMAKE_C_FLAGS} \
++ -D_GNU_SOURCE \
++ -DACCEPT_USERVAR \
++ -Wall \
++ -Wno-trigraphs \
++")
++
++add_subdirectory(telnet)
++add_subdirectory(telnetd)
++add_subdirectory(telnetlogin)
+--- /dev/null
++++ b/telnet/CMakeLists.txt
+@@ -0,0 +1,31 @@
++
++set(
++ CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} \
++ -DUSE_TERMIO \
++ -DKLUDGELINEMODE \
++")
++
++add_executable(
++ telnet
++ commands.cc
++ environ.cc
++ genget.cc
++ main.cc
++ netlink.cc
++ network.cc
++ ring.cc
++ sys_bsd.cc
++ telnet.cc
++ terminal.cc
++ tn3270.cc
++ utilities.cc
++)
++install(
++ TARGETS telnet
++ DESTINATION ${BIN_DIR}
++)
++
++install(
++ FILES telnet.1
++ DESTINATION ${MAN_DIR}/man1/
++)
+--- /dev/null
++++ b/telnetd/CMakeLists.txt
+@@ -0,0 +1,43 @@
++
++set(CMAKE_C_FLAGS "\
++ ${CMAKE_C_FLAGS} \
++ -DISSUE_FILE='\"/etc/issue.net\"' \
++ -DPARANOID_TTYS \
++ -DNO_REVOKE \
++ -DKLUDGELINEMODE \
++ -DDIAGNOSTICS \
++ -DLOGIN_WRAPPER='\"/usr/lib/telnetlogin\"' \
++")
++
++add_executable(
++ in.telnetd
++ global.c
++ setproctitle.c
++ slc.c
++ state.c
++ sys_term.c
++ telnetd.c
++ termstat.c
++ utility.c
++)
++target_link_libraries(
++ in.telnetd
++ ncurses
++ util
++)
++install(
++ TARGETS in.telnetd
++ DESTINATION ${SBIN_DIR}
++)
++
++install(
++ FILES telnetd.8
++ DESTINATION ${MAN_DIR}/man8/
++ RENAME in.telnetd.8
++)
++install(
++ CODE "execute_process( \
++ COMMAND ${CMAKE_COMMAND} -E create_symlink \
++ telnetd.8 \$ENV{DESTDIR}${MAN_DIR}/man8/in.telnetd.8 \
++ )"
++)
+--- /dev/null
++++ b/telnetlogin/CMakeLists.txt
+@@ -0,0 +1,19 @@
++
++add_executable(
++ telnetlogin
++ telnetlogin.c
++)
++install(
++ TARGETS telnetlogin
++ DESTINATION ${SBIN_DIR}
++ PERMISSIONS
++ SETUID
++ OWNER_WRITE OWNER_READ OWNER_EXECUTE
++ GROUP_READ GROUP_EXECUTE
++
++)
++
++install(
++ FILES telnetlogin.8
++ DESTINATION ${MAN_DIR}/man8/
++)
name = telnet
version = 0.17
-release = 3
+release = 4
groups = Applications/Internet
url = http://www.ibiblio.org/pub/Linux/system/network/netkit/
source_dl = http://www.ibiblio.org/pub/Linux/system/network/netkit/
sources = netkit-%{thisapp}.tar.gz
-sources += telnet-client.tar.gz
-
-# Apply patches in a special order
-patches = \
- telnet-client-cvs.patch0 \
- telnetd-0.17.patch0 \
- telnet-0.17-env.patch \
- telnet-0.17-pek.patch0 \
- telnet-0.17-issue.patch \
- telnet-0.17-sa-01-49.patch \
- telnet-0.17-8bit.patch \
- telnet-0.17-argv.patch \
- telnet-0.17-conf.patch \
- telnet-0.17-cleanup_race.patch \
- telnetd-0.17-pty_read.patch0 \
- telnet-0.17-CAN-2005-468_469.patch \
- telnet-gethostbyname.patch \
- netkit-telnet-0.17-ipv6.diff \
- netkit-telnet-0.17-nodns.patch \
- telnet-0.17-errno_test_sys_bsd.patch \
- netkit-telnet-0.17-reallynodns.patch
build
requires
+ cmake
gcc-c++
ncurses-devel
end
DIR_APP = %{DIR_SRC}/netkit-%{thisapp}
- # Overwite configure options, because configure script
- # doesn't accept flags for used compiler or host definition
- configure_options = \
- --prefix=/usr
-
- # For the telnet client we have to extract a second tarball into the source
- # directory of the main tarball.
- prepare
- cd %{DIR_SRC} && %{MACRO_EXTRACT} %{DIR_DL}/netkit-%{thisapp}.tar.gz
- cd %{DIR_APP} && mv telnet telnet-netkit
- cd %{DIR_APP} && %{MACRO_EXTRACT} %{DIR_DL}/telnet-client.tar.gz
+ build
+ %{cmake}
- %{MACRO_PATCHES}
-
- sed -i configure \
- -e "s/LDFLAGS=/LDFLAGS=\"%{LDFLAGS}\"/"
+ make %{PARALLELISMFLAGS}
end
- install
- # We have to create the directories on our own
- mkdir -pv %{BUILDROOT}/usr/man/man{1,5,8}
- mkdir -pv %{BUILDROOT}/usr/{,s}bin
-
- make install INSTALLROOT=%{BUILDROOT}
-
- # Move manpages to correct place
- mkdir -pv %{BUILDROOT}/usr/share
- mv %{BUILDROOT}/usr/man %{BUILDROOT}/usr/share/man
-
+ install_cmds
# Remove telnetd, we don't want it
- rm -rf %{BUILDROOT}/usr/sbin
- rm -rf %{BUILDROOT}/usr/share/man/man8
- rm -rf %{BUILDROOT}/usr/share/man/man5
+ rm -rvf %{BUILDROOT}%{sbindir}/*telnetd*
+ rm -rvf %{BUILDROOT}%{sbindir}/telnetlogin
+ rm -rvf %{BUILDROOT}%{mandir}/man8/*telnetd*
+ rm -rvf %{BUILDROOT}%{mandir}/man8/telnetlogin*
end
end
packages
package %{name}
- end
package %{name}-debuginfo
template DEBUGINFO