Retire MINIX telnet(1)

..which, for some strange reason, was installed as "ttn".

Change-Id: I5ad2f969ad7978a27fb7345f8434470ca427d429
This commit is contained in:
David van Moolenbroek 2017-02-14 18:48:16 +00:00
parent 34a8cf369f
commit 4d04ccc15b
9 changed files with 3 additions and 1340 deletions

View File

@ -547,7 +547,7 @@
./usr/bin/true minix-base
./usr/bin/truncate minix-base
./usr/bin/tsort minix-base
./usr/bin/ttn minix-base
./usr/bin/ttn minix-base obsolete
./usr/bin/tty minix-base
./usr/bin/udpstat minix-base obsolete
./usr/bin/ul minix-base

View File

@ -437,7 +437,7 @@
./usr/libdata/debug/usr/bin/trace.debug minix-debug debug
./usr/libdata/debug/usr/bin/truncate.debug minix-debug debug
./usr/libdata/debug/usr/bin/tsort.debug minix-debug debug
./usr/libdata/debug/usr/bin/ttn.debug minix-debug debug
./usr/libdata/debug/usr/bin/ttn.debug minix-debug debug,obsolete
./usr/libdata/debug/usr/bin/tty.debug minix-debug debug
./usr/libdata/debug/usr/bin/udpstat.debug minix-debug debug,obsolete
./usr/libdata/debug/usr/bin/ul.debug minix-debug debug

View File

@ -365,7 +365,7 @@
./usr/man/man1/tail.1 minix-man
./usr/man/man1/tar.1 minix-man
./usr/man/man1/tee.1 minix-man
./usr/man/man1/telnet.1 minix-man
./usr/man/man1/telnet.1 minix-man obsolete
./usr/man/man1/template.1 minix-man obsolete
./usr/man/man1/term.1 minix-man
./usr/man/man1/termcap.1 minix-man

View File

@ -23,7 +23,6 @@ SUBDIR= at backup \
rotate setup \
slip spell sprofalyze sprofdiff srccrc \
svrctl swifi synctree sysenv \
telnet \
telnetd term termcap tget \
truncate umount \
update version vol \

View File

@ -1,7 +0,0 @@
# Makefile for telnet
PROG= ttn
SRCS= ttn.c ttn_conf.c
MAN= telnet.1
.include <bsd.prog.mk>

View File

@ -1,587 +0,0 @@
.\" Copyright (c) 1983 Regents of the University of California.
.\" All rights reserved. The Berkeley software License Agreement
.\" specifies the terms and conditions for redistribution.
.\"
.\" @(#)telnet.1c 6.5 (Berkeley) 5/10/86
.\"
.TH TELNET 1 "May 10, 1986"
.UC 5
.SH NAME
telnet \- user interface to the \s-1TELNET\s0 protocol
.SH SYNOPSIS
telnet [
.I host
[
.I port
] ]
.SH DESCRIPTION
.I Telnet
is used to communicate with another host using the
.B TELNET
protocol.
If
.I telnet
is invoked without arguments, it enters command mode,
indicated by its prompt (\*(lqtelnet>\*(rq).
In this mode, it accepts and executes the commands listed below.
If it is invoked with arguments, it performs an
.B open
command (see below) with those arguments.
.PP
Once a connection has been opened,
.I telnet
enters an input mode.
The input mode entered will be either \*(lqcharacter at a time\*(rq
or \*(lqline by line\*(rq
depending on what the remote system supports.
.PP
In \*(lqcharacter at a time\*(rq mode, most
text typed is immediately sent to the remote host for processing.
.PP
In \*(lqline by line\*(rq mode, all text is echoed locally,
and (normally) only completed lines are sent to the remote host.
The \*(lqlocal echo character\*(rq (initially \*(lq^E\*(rq) may be used
to turn off and on the local echo
(this would mostly be used to enter passwords
without the password being echoed).
.PP
In either mode, if the
.I localchars
toggle is TRUE (the default in line mode; see below),
the user's
.IR quit ,
.IR intr ,
and
.I flush
characters are trapped locally, and sent as
.B TELNET
protocol sequences to the remote side.
There are options (see
.B toggle
.I autoflush
and
.B toggle
.I autosynch
below)
which cause this action to flush subsequent output to the terminal
(until the remote host acknowledges the
.B TELNET
sequence) and flush previous terminal input
(in the case of
.I quit
and
.IR intr ).
.PP
While connected to a remote host,
.I telnet
command mode may be entered by typing the
.I telnet
\*(lqescape character\*(rq (initially \*(lq^]\*(rq).
When in command mode, the normal terminal editing conventions are available.
.PP
.B COMMANDS
.PP
The following commands are available.
Only enough of each command to uniquely identify it need be typed
(this is also true for arguments to the
.BR mode ,
.BR set ,
.BR toggle ,
and
.B display
commands).
.PP
.TP
.B open \fIhost\fP \fR[\fP \fIport\fP \fR]\fP
.br
Open a connection to the named host.
If no port number
is specified,
.I telnet
will attempt to contact a
.B TELNET
server at the default port.
The host specification may be either a host name (see
.IR hosts (5))
or an Internet address specified in the \*(lqdot notation\*(rq (see
.IR inet (3N)).
.TP
.B close
.br
Close a
.B TELNET
session and return to command mode.
.TP
.B quit
.br
Close any open
.B TELNET
session and exit
.IR telnet .
An end of file (in command mode) will also close a session and exit.
.TP
.B z
.br
Suspend
.IR telnet .
This command only works when the user is using the
.IR csh (1).
.TP
.B mode \fItype\fP
.br
.I Type
is either
.I line
(for \*(lqline by line\*(rq mode)
or
.I character
(for \*(lqcharacter at a time\*(rq mode).
The remote host is asked for permission to go into the requested mode.
If the remote host is capable of entering that mode, the requested
mode will be entered.
.TP
.B status
.br
Show the current status of
.IR telnet .
This includes the peer one is connected to, as well
as the current mode.
.TP
.B display \fR[\fP \fIargument...\fP \fR]\fP
.br
Displays all, or some, of the
.B set
and
.B toggle
values (see below).
.TP
.B ? \fR[\fP \fIcommand\fP \fR]\fP
.br
Get help. With no arguments,
.I telnet
prints a help summary.
If a command is specified,
.I telnet
will print the help information for just that command.
.TP
.B send \fIarguments\fP
.br
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):
.RS
.TP
.I escape
.br
Sends the current
.I telnet
escape character (initially \*(lq^]\*(rq).
.TP
.I synch
.br
Sends the
.B TELNET SYNCH
sequence.
This sequence causes the remote system to discard all previously typed
(but not yet read) input.
This sequence is sent as TCP urgent
data (and may not work if the remote system is a 4.2 BSD system -- if
it doesn't work, a lower case \*(lqr\*(rq may be echoed on the terminal).
.TP
.I brk
.br
Sends the
.B TELNET BRK
(Break) sequence, which may have significance to the remote
system.
.TP
.I ip
.br
Sends the
.B TELNET IP
(Interrupt Process) sequence, which should cause the remote
system to abort the currently running process.
.TP
.I ao
.br
Sends the
.B TELNET AO
(Abort Output) sequence, which should cause the remote system to flush
all output
.B from
the remote system
.B to
the user's terminal.
.TP
.I ayt
.br
Sends the
.B TELNET AYT
(Are You There)
sequence, to which the remote system may or may not choose to respond.
.TP
.I ec
.br
Sends the
.B TELNET EC
(Erase Character)
sequence, which should cause the remote system to erase the last character
entered.
.TP
.I el
.br
Sends the
.B TELNET EL
(Erase Line)
sequence, which should cause the remote system to erase the line currently
being entered.
.TP
.I ga
.br
Sends the
.B TELNET GA
(Go Ahead)
sequence, which likely has no significance to the remote system.
.TP
.I nop
.br
Sends the
.B TELNET NOP
(No OPeration)
sequence.
.TP
.I ?
.br
Prints out help information for the
.B send
command.
.RE
.TP
.B set \fIargument value\fP
.br
Set any one of a number of
.I telnet
variables to a specific value.
The special value \*(lqoff\*(rq turns off the function associated with
the variable.
The values of variables may be interrogated with the
.B display
command.
The variables which may be specified are:
.RS
.TP
.I echo
.br
This is the value (initially \*(lq^E\*(rq) which, when in
\*(lqline by line\*(rq mode, toggles between doing local echoing
of entered characters (for normal processing), and suppressing
echoing of entered characters (for entering, say, a password).
.TP
.I escape
.br
This is the
.I telnet
escape character (initially \*(lq^[\*(rq) which causes entry
into
.I telnet
command mode (when connected to a remote system).
.TP
.I interrupt
.br
If
.I telnet
is in
.I localchars
mode (see
.B toggle
.I localchars
below)
and the
.I interrupt
character is typed, a
.B TELNET IP
sequence (see
.B send
.I ip
above)
is sent to the remote host.
The initial value for the interrupt character is taken to be
the terminal's
.B intr
character.
.TP
.I quit
.br
If
.I telnet
is in
.I localchars
mode (see
.B toggle
.I localchars
below)
and the
.I quit
character is typed, a
.B TELNET BRK
sequence (see
.B send
.I brk
above)
is sent to the remote host.
The initial value for the quit character is taken to be
the terminal's
.B quit
character.
.TP
.I flushoutput
.br
If
.I telnet
is in
.I localchars
mode (see
.B toggle
.I localchars
below)
and the
.I flushoutput
character is typed, a
.B TELNET AO
sequence (see
.B send
.I ao
above)
is sent to the remote host.
The initial value for the flush character is taken to be
the terminal's
.B flush
character.
.TP
.I erase
.br
If
.I telnet
is in
.I localchars
mode (see
.B toggle
.I localchars
below),
.B and
if
.I telnet
is operating in \*(lqcharacter at a time\*(rq mode, then when this
character is typed, a
.B TELNET EC
sequence (see
.B send
.I ec
above)
is sent to the remote system.
The initial value for the erase character is taken to be
the terminal's
.B erase
character.
.TP
.I kill
.br
If
.I telnet
is in
.I localchars
mode (see
.B toggle
.I localchars
below),
.B and
if
.I telnet
is operating in \*(lqcharacter at a time\*(rq mode, then when this
character is typed, a
.B TELNET EL
sequence (see
.B send
.I el
above)
is sent to the remote system.
The initial value for the kill character is taken to be
the terminal's
.B kill
character.
.TP
.I eof
.br
If
.I telnet
is operating in \*(lqline by line\*(rq mode, entering this character
as the first character on a line will cause this character to be
sent to the remote system.
The initial value of the eof character is taken to be the terminal's
.B eof
character.
.RE
.TP
.B toggle \fIarguments...\fP
.br
Toggle (between
TRUE
and
FALSE)
various flags that control how
.I telnet
responds to events.
More than one argument may be specified.
The state of these flags may be interrogated with the
.B display
command.
Valid arguments are:
.RS
.TP
.I localchars
.br
If this is
TRUE,
then the
.IR flush ,
.IR interrupt ,
.IR quit ,
.IR erase ,
and
.I kill
characters (see
.B set
above) are recognized locally, and transformed into (hopefully) appropriate
.B TELNET
control sequences
(respectively
.IR ao ,
.IR ip ,
.IR brk ,
.IR ec ,
and
.IR el ;
see
.B send
above).
The initial value for this toggle is TRUE in \*(lqline by line\*(rq mode,
and FALSE in \*(lqcharacter at a time\*(rq mode.
.TP
.I autoflush
.br
If
.I autoflush
and
.I localchars
are both
TRUE,
then when the
.IR ao ,
.IR intr ,
or
.I quit
characters are recognized (and transformed into
.B TELNET
sequences; see
.B set
above for details),
.I telnet
refuses to display any data on the user's terminal
until the remote system acknowledges (via a
.B TELNET
.I Timing Mark
option)
that it has processed those
.B TELNET
sequences.
The initial value for this toggle is TRUE if the terminal user had not
done an "stty noflsh", otherwise FALSE (see
.IR stty(1)).
.TP
.I autosynch
If
.I autosynch
and
.I localchars
are both
TRUE,
then when either the
.I intr
or
.I quit
characters is typed (see
.B set
above for descriptions of the
.I intr
and
.I quit
characters), the resulting
.B TELNET
sequence sent is followed by the
.B TELNET SYNCH
sequence.
This procedure
.B should
cause the remote system to begin throwing away all previously
typed input until both of the
.B TELNET
sequences have been read and acted upon.
The initial value of this toggle is FALSE.
.TP
.I crmod
.br
Toggle carriage return mode.
When this mode is enabled, most carriage return characters received from
the remote host will be mapped into a carriage return followed by
a line feed.
This mode does not affect those characters typed by the user, only
those received from the remote host.
This mode is not very useful unless the remote host
only sends carriage return, but never line feed.
The initial value for this toggle is FALSE.
.TP
.I debug
.br
Toggles socket level debugging (useful only to the
.IR super user ).
The initial value for this toggle is FALSE.
.TP
.I options
.br
Toggles the display of some internal
.I telnet
protocol processing (having to do with
.B TELNET
options).
The initial value for this toggle is FALSE.
.TP
.I netdata
.br
Toggles the display of all network data (in hexadecimal format).
The initial value for this toggle is FALSE.
.TP
.I ?
.br
Displays the legal
.B toggle
commands.
.RE
.SH BUGS
.PP
There is no adequate way for dealing with flow control.
.PP
On some remote systems, echo has to be turned off manually when in
\*(lqline by line\*(rq mode.
.PP
There is enough settable state to justify a
.RI . telnetrc
file.
.PP
No capability for a
.RI . telnetrc
file is provided.
.PP
In \*(lqline by line\*(rq mode, the terminal's
.I eof
character is only recognized (and sent to the remote system)
when it is the first character on a line.

View File

@ -1,686 +0,0 @@
/*
ttn.c
*/
#include <sys/types.h>
#include <sys/ioctl.h>
#include <assert.h>
#include <errno.h>
#include <fcntl.h>
#include <termios.h>
#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <net/hton.h>
#include <net/netlib.h>
#include <net/gen/in.h>
#include <net/gen/inet.h>
#include <netdb.h>
#include <net/gen/tcp.h>
#include <net/gen/tcp_io.h>
#include <arpa/inet.h>
#include "ttn.h"
#if __STDC__
#define PROTOTYPE(func,args) func args
#else
#define PROTOTYPE(func,args) func()
#endif
static int do_read(int fd, char *buf, unsigned len);
static void screen(void);
static void keyboard(void);
static void send_brk(void);
static int process_opt (char *bp, int count);
static void do_option (int optsrt);
static void dont_option (int optsrt);
static void will_option (int optsrt);
static void wont_option (int optsrt);
static int writeall (int fd, char *buffer, int buf_size);
static int sb_termtype (char *sb, int count);
static void fatal(char *fmt, ...);
static void usage(void);
#if DEBUG
#define where() (fprintf(stderr, "%s %d:", __FILE__, __LINE__))
#endif
static char *prog_name;
static int tcp_fd;
static char *term_env;
static int esc_char= '~';
static enum { LS_NORM, LS_BOL, LS_ESC } line_state= LS_BOL;
int main(int argc, char *argv[])
{
struct hostent *hostent;
struct servent *servent;
ipaddr_t host;
tcpport_t port;
int pid, ppid;
nwio_tcpconf_t tcpconf;
int c, r;
nwio_tcpcl_t tcpconnopt;
struct termios termios;
char *tcp_device, *remote_name, *port_name;
char *e_arg;
(prog_name=strrchr(argv[0],'/')) ? prog_name++ : (prog_name=argv[0]);
e_arg= NULL;
while (c= getopt(argc, argv, "?e:"), c != -1)
{
switch(c)
{
case '?': usage();
case 'e': e_arg= optarg; break;
default:
fatal("Optind failed: '%c'", c);
}
}
if (optind >= argc)
usage();
remote_name= argv[optind++];
if (optind < argc)
port_name= argv[optind++];
else
port_name= NULL;
if (optind != argc)
usage();
if (e_arg)
{
switch(strlen(e_arg))
{
case 0: esc_char= -1; break;
case 1: esc_char= e_arg[0]; break;
default: fatal("Invalid escape character '%s'", e_arg);
}
}
hostent= gethostbyname(remote_name);
if (!hostent)
fatal("Unknown host %s", remote_name);
host= *(ipaddr_t *)(hostent->h_addr);
if (!port_name)
port= htons(TCPPORT_TELNET);
else
{
servent= getservbyname (port_name, "tcp");
if (!servent)
{
port= htons(strtol(port_name, (char **)0, 0));
if (!port)
fatal("Unknown port %s", port_name);
}
else
port= (tcpport_t)(servent->s_port);
}
fprintf(stderr, "Connecting to %s:%u...\n",
inet_ntoa(*(struct in_addr *)&host), ntohs(port));
tcp_device= getenv("TCP_DEVICE");
if (tcp_device == NULL)
tcp_device= TCP_DEVICE;
tcp_fd= open (tcp_device, O_RDWR);
if (tcp_fd == -1)
fatal("Unable to open %s: %s", tcp_device, strerror(errno));
tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
tcpconf.nwtc_remaddr= host;
tcpconf.nwtc_remport= port;
r= ioctl (tcp_fd, NWIOSTCPCONF, &tcpconf);
if (r == -1)
fatal("NWIOSTCPCONF failed: %s", strerror(errno));
tcpconnopt.nwtcl_flags= 0;
do
{
r= ioctl (tcp_fd, NWIOTCPCONN, &tcpconnopt);
if (r == -1 && errno == EAGAIN)
{
fprintf(stderr, "%s: Got EAGAIN, sleeping(1s)\n",
prog_name);
sleep(1);
}
} while (r == -1 && errno == EAGAIN);
if (r == -1)
fatal("Unable to connect: %s", strerror(errno));
printf("Connected\n");
ppid= getpid();
pid= fork();
switch(pid)
{
case 0:
keyboard();
#if DEBUG
fprintf(stderr, "killing %d with %d\r\n", ppid, SIGKILL);
#endif
kill(ppid, SIGKILL);
break;
case -1:
fprintf(stderr, "%s: fork failed: %s\r\n", argv[0],
strerror(errno));
exit(1);
break;
default:
tcgetattr(0, &termios);
screen();
#if DEBUG
fprintf(stderr, "killing %d with %d\r\n", pid, SIGKILL);
#endif
kill(pid, SIGKILL);
tcsetattr(0, TCSANOW, &termios);
break;
}
exit(0);
}
static int do_read(fd, buf, len)
int fd;
char *buf;
unsigned len;
{
nwio_tcpopt_t tcpopt;
int count;
for (;;)
{
count= read (fd, buf, len);
if (count <0)
{
if (errno == EURG || errno == ENOURG)
{
/* Toggle urgent mode. */
tcpopt.nwto_flags= errno == EURG ?
NWTO_RCV_URG : NWTO_RCV_NOTURG;
if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) == -1)
{
return -1;
}
continue;
}
return -1;
}
return count;
}
}
static void screen()
{
char buffer[1024], *bp, *iacptr;
int count, optsize;
for (;;)
{
count= do_read (tcp_fd, buffer, sizeof(buffer));
#if DEBUG && 0
{ where(); fprintf(stderr, "read %d bytes\r\n", count); }
#endif
if (count <0)
{
perror ("read");
return;
}
if (!count)
return;
bp= buffer;
do
{
iacptr= memchr (bp, IAC, count);
if (!iacptr)
{
write(1, bp, count);
count= 0;
}
if (iacptr && iacptr>bp)
{
#if DEBUG
{ where(); fprintf(stderr, "iacptr-bp= %d\r\n", iacptr-bp); }
#endif
write(1, bp, iacptr-bp);
count -= (iacptr-bp);
bp= iacptr;
continue;
}
if (iacptr)
{
assert (iacptr == bp);
optsize= process_opt(bp, count);
#if DEBUG && 0
{ where(); fprintf(stderr, "process_opt(...)= %d\r\n", optsize); }
#endif
if (optsize<0)
return;
assert (optsize);
bp += optsize;
count -= optsize;
}
} while (count);
}
}
static void keyboard()
{
char c, buffer[1024];
int count;
for (;;)
{
count= read (0, buffer, 1 /* sizeof(buffer) */);
if (count == -1)
fatal("Read: %s\r\n", strerror(errno));
if (!count)
return;
if (line_state != LS_NORM)
{
c= buffer[0];
if (line_state == LS_BOL)
{
if (c == esc_char)
{
line_state= LS_ESC;
continue;
}
line_state= LS_NORM;
}
else if (line_state == LS_ESC)
{
line_state= LS_NORM;
if (c == '.')
return;
if (c == '#')
{
send_brk();
continue;
}
/* Not a valid command or a repeat of the
* escape char
*/
if (c != esc_char)
{
c= esc_char;
write(tcp_fd, &c, 1);
}
}
}
if (buffer[0] == '\n')
write(tcp_fd, "\r", 1);
count= write(tcp_fd, buffer, count);
if (buffer[0] == '\r')
{
line_state= LS_BOL;
write(tcp_fd, "\0", 1);
}
if (count<0)
{
perror("write");
fprintf(stderr, "errno= %d\r\n", errno);
return;
}
if (!count)
return;
}
}
static void send_brk(void)
{
int r;
unsigned char buffer[2];
buffer[0]= IAC;
buffer[1]= IAC_BRK;
r= writeall(tcp_fd, (char *)buffer, 2);
if (r == -1)
fatal("Error writing to TCP connection: %s", strerror(errno));
}
#define next_char(var) \
if (offset<count) { (var) = bp[offset++]; } \
else if (do_read(tcp_fd, (char *)&(var), 1) <= 0) \
{ perror ("read"); return -1; }
static int process_opt (char *bp, int count)
{
unsigned char iac, command, optsrt, sb_command;
int offset, result; ;
#if DEBUG && 0
{ where(); fprintf(stderr, "process_opt(bp= 0x%x, count= %d)\r\n",
bp, count); }
#endif
offset= 0;
assert (count);
next_char(iac);
assert (iac == IAC);
next_char(command);
switch(command)
{
case IAC_NOP:
break;
case IAC_DataMark:
/* Ought to flush input queue or something. */
break;
case IAC_BRK:
fprintf(stderr, "got a BRK\r\n");
break;
case IAC_IP:
fprintf(stderr, "got a IP\r\n");
break;
case IAC_AO:
fprintf(stderr, "got a AO\r\n");
break;
case IAC_AYT:
fprintf(stderr, "got a AYT\r\n");
break;
case IAC_EC:
fprintf(stderr, "got a EC\r\n");
break;
case IAC_EL:
fprintf(stderr, "got a EL\r\n");
break;
case IAC_GA:
fprintf(stderr, "got a GA\r\n");
break;
case IAC_SB:
next_char(sb_command);
switch (sb_command)
{
case OPT_TERMTYPE:
#if DEBUG && 0
fprintf(stderr, "got SB TERMINAL-TYPE\r\n");
#endif
result= sb_termtype(bp+offset, count-offset);
if (result<0)
return result;
else
return result+offset;
default:
fprintf(stderr, "got an unknown SB (skiping)\r\n");
for (;;)
{
next_char(iac);
if (iac != IAC)
continue;
next_char(optsrt);
if (optsrt == IAC)
continue;
if (optsrt != IAC_SE)
fprintf(stderr, "got IAC %d\r\n", optsrt);
break;
}
}
break;
case IAC_WILL:
next_char(optsrt);
will_option(optsrt);
break;
case IAC_WONT:
next_char(optsrt);
wont_option(optsrt);
break;
case IAC_DO:
next_char(optsrt);
do_option(optsrt);
break;
case IAC_DONT:
next_char(optsrt);
dont_option(optsrt);
break;
case IAC:
fprintf(stderr, "got a IAC\r\n");
break;
default:
fprintf(stderr, "got unknown command (%d)\r\n", command);
}
return offset;
}
static void do_option (int optsrt)
{
unsigned char reply[3];
int result;
switch (optsrt)
{
case OPT_TERMTYPE:
if (WILL_terminal_type)
return;
if (!WILL_terminal_type_allowed)
{
reply[0]= IAC;
reply[1]= IAC_WONT;
reply[2]= optsrt;
}
else
{
WILL_terminal_type= TRUE;
term_env= getenv("TERM");
if (!term_env)
term_env= "unknown";
reply[0]= IAC;
reply[1]= IAC_WILL;
reply[2]= optsrt;
}
break;
default:
#if DEBUG
fprintf(stderr, "got a DO (%d)\r\n", optsrt);
fprintf(stderr, "WONT (%d)\r\n", optsrt);
#endif
reply[0]= IAC;
reply[1]= IAC_WONT;
reply[2]= optsrt;
break;
}
result= writeall(tcp_fd, (char *)reply, 3);
if (result<0)
perror("write");
}
static void will_option (int optsrt)
{
unsigned char reply[3];
int result;
switch (optsrt)
{
case OPT_ECHO:
if (DO_echo)
break;
if (!DO_echo_allowed)
{
reply[0]= IAC;
reply[1]= IAC_DONT;
reply[2]= optsrt;
}
else
{
struct termios termios;
tcgetattr(0, &termios);
termios.c_iflag &= ~(ICRNL|IGNCR|INLCR|IXON|IXOFF);
termios.c_oflag &= ~(OPOST);
termios.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
tcsetattr(0, TCSANOW, &termios);
DO_echo= TRUE;
reply[0]= IAC;
reply[1]= IAC_DO;
reply[2]= optsrt;
}
result= writeall(tcp_fd, (char *)reply, 3);
if (result<0)
perror("write");
break;
case OPT_SUPP_GA:
if (DO_suppress_go_ahead)
break;
if (!DO_suppress_go_ahead_allowed)
{
reply[0]= IAC;
reply[1]= IAC_DONT;
reply[2]= optsrt;
}
else
{
DO_suppress_go_ahead= TRUE;
reply[0]= IAC;
reply[1]= IAC_DO;
reply[2]= optsrt;
}
result= writeall(tcp_fd, (char *)reply, 3);
if (result<0)
perror("write");
break;
default:
#if DEBUG
fprintf(stderr, "got a WILL (%d)\r\n", optsrt);
fprintf(stderr, "DONT (%d)\r\n", optsrt);
#endif
reply[0]= IAC;
reply[1]= IAC_DONT;
reply[2]= optsrt;
result= writeall(tcp_fd, (char *)reply, 3);
if (result<0)
perror("write");
break;
}
}
static int writeall (fd, buffer, buf_size)
int fd;
char *buffer;
int buf_size;
{
int result;
while (buf_size)
{
result= write (fd, buffer, buf_size);
if (result <= 0)
return -1;
assert (result <= buf_size);
buffer += result;
buf_size -= result;
}
return 0;
}
static void dont_option (int optsrt)
{
switch (optsrt)
{
default:
#if DEBUG
fprintf(stderr, "got a DONT (%d)\r\n", optsrt);
#endif
break;
}
}
static void wont_option (int optsrt)
{
switch (optsrt)
{
default:
#if DEBUG
fprintf(stderr, "got a WONT (%d)\r\n", optsrt);
#endif
break;
}
}
static int sb_termtype (char *bp, int count)
{
unsigned char command, iac, optsrt;
unsigned char buffer[4];
int offset, result;
offset= 0;
next_char(command);
if (command == TERMTYPE_SEND)
{
buffer[0]= IAC;
buffer[1]= IAC_SB;
buffer[2]= OPT_TERMTYPE;
buffer[3]= TERMTYPE_IS;
result= writeall(tcp_fd, (char *)buffer,4);
if (result<0)
return result;
count= strlen(term_env);
if (!count)
{
term_env= "unknown";
count= strlen(term_env);
}
result= writeall(tcp_fd, term_env, count);
if (result<0)
return result;
buffer[0]= IAC;
buffer[1]= IAC_SE;
result= writeall(tcp_fd, (char *)buffer,2);
if (result<0)
return result;
}
else
{
#if DEBUG
where();
#endif
fprintf(stderr, "got an unknown command (skipping)\r\n");
}
for (;;)
{
next_char(iac);
if (iac != IAC)
continue;
next_char(optsrt);
if (optsrt == IAC)
continue;
if (optsrt != IAC_SE)
{
#if DEBUG
where();
#endif
fprintf(stderr, "got IAC %d\r\n", optsrt);
}
break;
}
return offset;
}
static void fatal(char *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
fprintf(stderr, "%s: ", prog_name);
vfprintf(stderr, fmt, ap);
fprintf(stderr, "\n");
va_end(ap);
exit(1);
}
static void usage(void)
{
fprintf(stderr, "Usage: %s [-e esc-char] host [port]\r\n",
prog_name);
exit(1);
}
/*
* $PchId: ttn.c,v 1.5 2002/05/07 12:06:41 philip Exp $
*/

View File

@ -1,44 +0,0 @@
/*
ttn.h
*/
#ifndef TTN_H
#define TTN_H
#define IAC 255
#define IAC_SE 240
#define IAC_NOP 241
#define IAC_DataMark 242
#define IAC_BRK 243
#define IAC_IP 244
#define IAC_AO 245
#define IAC_AYT 246
#define IAC_EC 247
#define IAC_EL 248
#define IAC_GA 249
#define IAC_SB 250
#define IAC_WILL 251
#define IAC_WONT 252
#define IAC_DO 253
#define IAC_DONT 254
#define OPT_ECHO 1
#define OPT_SUPP_GA 3
#define OPT_TERMTYPE 24
#define TERMTYPE_SEND 1
#define TERMTYPE_IS 0
#define FALSE 0
#define TRUE (!(FALSE))
extern int DO_echo;
extern int DO_echo_allowed;
extern int WILL_terminal_type;
extern int WILL_terminal_type_allowed;
extern int DO_suppress_go_ahead;
extern int DO_suppress_go_ahead_allowed;
extern int WILL_suppress_go_ahead;
extern int WILL_suppress_go_ahead_allowed;
#endif /* TTN_H */

View File

@ -1,12 +0,0 @@
/*
ttn_conf.c
*/
#include "ttn.h"
int DO_echo= FALSE;
int DO_echo_allowed= TRUE;
int WILL_terminal_type= FALSE;
int WILL_terminal_type_allowed= TRUE;
int DO_suppress_go_ahead= FALSE;
int DO_suppress_go_ahead_allowed= TRUE;