static char sccsid
[] = "@(#)telnet.c 4.4 (Berkeley) %G%";
#define ctrl(x) ((x) & 037)
#define strip(x) ((x)&0177)
#define INFINITY 10000000
#define swab(x) ((((x) >> 8) | ((x) << 8)) & 0xffff)
char ttyobuf
[BUFSIZ
], *tfrontp
= ttyobuf
, *tbackp
= ttyobuf
;
{ IAC
, DO
, TELOPT_ECHO
, IAC
, DO
, TELOPT_SGA
,
*nfrontp
= netobuf
+ 9, *nbackp
= netobuf
;
char doopt
[] = { IAC
, DO
, '%', 'c', 0 };
char dont
[] = { IAC
, DONT
, '%', 'c', 0 };
char will
[] = { IAC
, WILL
, '%', 'c', 0 };
char wont
[] = { IAC
, WONT
, '%', 'c', 0 };
int tn(), quit(), suspend(), bye(), help();
int setescape(), status(), toggle(), setoptions();
#define HELPINDENT (sizeof("connect"))
char ohelp
[] = "connect to a site";
char chelp
[] = "close current connection";
char qhelp
[] = "exit telnet";
char zhelp
[] = "suspend telnet";
char ehelp
[] = "set escape character";
char shelp
[] = "print status information";
char hhelp
[] = "print help information";
char phelp
[] = "toggle viewing of options processing";
{ "escape", ehelp
, setescape
},
{ "status", shelp
, status
},
{ "options", phelp
, setoptions
},
struct sockaddr_in sin
= { AF_INET
, swab(IPPORT_TELNET
) };
if (setjmp(toplevel
) != 0)
printf("?Already connected to %s\n", host_name
);
strcpy(line
, "Connect ");
gets(&line
[strlen(line
)]);
printf("usage: %s host-name [port]\n", argv
[0]);
sin
.sin_addr
.s_addr
= rhost(&argv
[1]);
if (sin
.sin_addr
.s_addr
== (u_long
)-1) {
printf("%s: unknown host\n", argv
[1]);
sin
.sin_port
= atoi(argv
[2]);
printf("%s: bad port number\n", argv
[2]);
if ((net
= socket(SOCK_STREAM
, 0, 0, 0)) < 0) {
sigset(SIGPIPE
, deadpeer
);
if (connect(net
, &sin
)) {
strcpy(host_name
, argv
[1]);
call(status
, "status", 0);
if (setjmp(peerdied
) == 0)
fprintf(stderr
, "Connection closed by foreign host.\n");
* Print status about the connection.
printf("Connected to %s.\n", host_name
);
printf("No connection.\n");
printf("Escape character is '%s'.\n", control(escape
));
register char **argp
= margv
;
while (*cp
!= '\0' && !isspace(*cp
))
kill(0, SIGTSTP
); /* get whole process group */
ioctl(net
, SIOCDONE
, &how
);
printf("Connection closed.\n");
* Call each command handler with argc == 0 and argv[0] == name.
printf("Commands may be abbreviated. Commands are:\n\n");
for (c
= cmdtab
; c
->name
; c
++)
printf("%-*s\t%s\n", HELPINDENT
, c
->name
, c
->help
);
if (c
== (struct cmd
*)-1)
printf("?Ambiguous help command %s\n", arg
);
else if (c
== (struct cmd
*)0)
printf("?Invalid help command %s\n", arg
);
* Call routine with argc, argv set from args (terminated by 0).
for (argc
= 0, argp
= &args
; *argp
++ != 0; argc
++)
ioctl(fileno(stdin
), TIOCGETP
, &stbuf
);
stbuf
.sg_flags
|= ECHO
|CRMOD
;
stbuf
.sg_flags
&= ~(ECHO
|CRMOD
);
stbuf
.sg_flags
|= ECHO
|CRMOD
;
ioctl(fileno(stdin
), TIOCSETN
, &stbuf
);
ioctl(fileno(stdin
), FIONBIO
, &onoff
);
ioctl(fileno(stdout
), FIONBIO
, &onoff
);
char sibuf
[BUFSIZ
], *sbp
;
char tibuf
[BUFSIZ
], *tbp
;
* Select from tty and network...
int tin
= fileno(stdin
), tout
= fileno(stdout
);
printoption("<--", doopt
, TELOPT_ECHO
);
sprintf(nfrontp
, doopt
, TELOPT_ECHO
);
nfrontp
+= sizeof(doopt
) - 2;
printoption("<--", doopt
, TELOPT_SGA
);
sprintf(nfrontp
, doopt
, TELOPT_SGA
);
nfrontp
+= sizeof(doopt
) - 2;
printoption("<--", will
, TELOPT_SGA
);
sprintf(nfrontp
, will
, TELOPT_SGA
);
nfrontp
+= sizeof(doopt
) - 2;
int ibits
= 0, obits
= 0;
select(32, &ibits
, &obits
, INFINITY
);
if (ibits
== 0 && obits
== 0) {
* Something to read from the network...
scc
= read(s
, sibuf
, sizeof(sibuf
));
if (scc
< 0 && errno
== EWOULDBLOCK
)
* Something to read from the tty...
if (ibits
& (1 << tin
)) {
tcc
= read(tin
, tibuf
, sizeof(tibuf
));
if (tcc
< 0 && errno
== EWOULDBLOCK
)
if ((&netobuf
[BUFSIZ
] - nfrontp
) < 2)
c
= *tbp
++ & 0377, tcc
--;
if (strip(c
) == escape
) {
if ((obits
& (1 << s
)) && (nfrontp
- nbackp
) > 0)
if ((obits
& (1 << tout
)) && (tfrontp
- tbackp
) > 0)
if (c
== (struct cmd
*)-1) {
printf("?Ambiguous command\n");
printf("?Invalid command\n");
(*c
->handler
)(margc
, margv
);
* Telnet receiver states for fsm
static int state
= TS_DATA
;
c
= *sbp
++ & 0377, scc
--;
ioctl(fileno(stdout
), TIOCFLUSH
, 0);
printoption("-->", will
, c
);
printoption("-->", wont
, c
);
printoption("-->", doopt
, c
);
printoption("-->", dont
, c
);
sprintf(nfrontp
, wont
, c
);
nfrontp
+= sizeof(wont
) - 2;
printoption("<--", wont
, c
);
sprintf(nfrontp
, fmt
, option
);
nfrontp
+= sizeof(dont
) - 2;
printoption("<--", fmt
, option
);
sprintf(nfrontp
, fmt
, option
);
nfrontp
+= sizeof(doopt
) - 2;
printoption("<--", fmt
, option
);
sprintf(nfrontp
, fmt
, option
);
nfrontp
+= sizeof(doopt
) - 2;
printoption("<--", fmt
, option
);
* Set the escape character.
printf("new escape character: ");
printf("Escape character is '%s'.\n", control(escape
));
showoptions
= !showoptions
;
printf("%s show option processing.\n", showoptions
? "Will" : "Wont");
* Construct a control character sequence
* for a special character.
register struct cmd
*c
, *found
;
register int nmatches
, longest
;
for (c
= cmdtab
; p
= c
->name
; c
++) {
for (q
= name
; *q
== *p
++; q
++)
if (*q
== 0) /* exact match? */
if (!*q
) { /* the name was a prefix */
if (q
- name
> longest
) {
} else if (q
- name
== longest
)
return ((struct cmd
*)-1);
sigset(SIGPIPE
, deadpeer
);
if ((n
= tfrontp
- tbackp
) > 0)
n
= write(fd
, tbackp
, n
);
if (n
< 0 && errno
== EWOULDBLOCK
)
tbackp
= tfrontp
= ttyobuf
;
if ((n
= nfrontp
- nbackp
) > 0)
n
= write(fd
, nbackp
, n
);
if (n
< 0 && errno
== EWOULDBLOCK
)
nbackp
= nfrontp
= netobuf
;
printoption(direction
, fmt
, option
)
printf("%s ", direction
);
if (option
< TELOPT_SUPDUP
)
printf("%s %s\r\n", fmt
, telopts
[option
]);
printf("%s %d\r\n", fmt
, option
);