home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
The Datafile PD-CD 3
/
PDCD_3.iso
/
internet
/
netlite
/
NET
/
c
/
TELNET
< prev
next >
Wrap
Text File
|
1993-04-10
|
14KB
|
470 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "dbox.h"
#include "werr.h"
#include "global.h"
#include "mbuf.h"
#include "timer.h"
#include "icmp.h"
#include "netuser.h"
#include "tcp.h"
#include "telnet.h"
#include "session.h"
#include "misc.h"
#include "domain.h"
static int telnet(int32, char *, char *, char *, struct session *);
static int telnet_error(char *, char *, struct session *);
static void free_telnet(struct telnet *);
static void willopt(struct telnet *, char);
static void wontopt(struct telnet *, char);
static void doopt(struct telnet *, char);
static void dontopt(struct telnet *, char);
static void answer(struct telnet *, int, int);
#define CTLZ 26
#define TELNET_Connect 0
#define TELNET_Host 1
#define TELNET_Port 3
extern char nospace[];
extern char badhost[];
int refuse_echo = 0;
int unix_line_mode = 0; /* if true turn <cr> to <nl> when in line mode */
#ifdef DEBUG
char *t_options[] = {
"Transmit Binary",
"Echo",
"",
"Suppress Go Ahead",
"",
"Status",
"Timing Mark"
};
#endif
void start_telnet(void)
{
struct session *session;
char buffer[80];
char Host[256];
char Port[5];
dbox d;
if ((d = dbox_new("TELNET")) == NULL)
return;
dbox_setfield(d, TELNET_Host, "");
dbox_setfield(d, TELNET_Port, "23");
dbox_show(d);
if (dbox_fillin(d) == TELNET_Connect)
{
dbox_getfield(d, TELNET_Host, Host, 255);
dbox_getfield(d, TELNET_Port, Port, 4);
/* Allocate a session descriptor */
sprintf(buffer, "TELNET - %.60s", Host);
if ((session = newsession(buffer)) == NULLSESSION)
{
werr(0, "Too many sessions");
return;
}
session->name = strdup(Host);
session->type = RESOLVING;
session->parse = NULLVFP;
sprintf(buffer, "Resolving %.60s ...\n", Host);
Window_Write(session->window, buffer, strlen(buffer));
resolve_a(Host, Port, NULLCHAR, session, telnet, telnet_error);
}
dbox_dispose(&d);
}
static int telnet_error(char *host, char *message, struct session *s)
{
char buffer[80];
sprintf(buffer, "Cannot TELNET to %s - %s\n", host, message);
Window_Write(s->window, buffer, strlen(buffer));
detachsession(s);
return 0;
}
/* Execute user telnet command */
static int telnet(int32 address, char *host, char *port, char *arg2, struct session *s)
{
char buffer[80];
struct telnet *tn;
struct tcb *tcb;
struct socket lsocket, fsocket;
host = host;
arg2 = arg2;
lsocket.address = ip_addr;
lsocket.port = lport++;
fsocket.address = address;
fsocket.port = (atoi(port) > 0) ? atoi(port) : TELNET_PORT;
s->type = TELNET;
s->addr = fsocket.address;
if ((refuse_echo == 0) && (unix_line_mode != 0))
s->parse = unix_send_tel;
else
s->parse = send_tel;
s->echo = 0;
s->raw = 1;
/* Create and initialize a Telnet protocol descriptor */
if((tn = (struct telnet *)calloc(1,sizeof(struct telnet))) == NULLTN)
{
Window_Write(s->window, nospace, strlen(nospace));
detachsession(s);
return 1;
}
tn->session = s; /* Upward pointer */
tn->state = TS_DATA;
s->cb.telnet = tn; /* Downward pointer */
sprintf(buffer, "Trying [%s] ...\n", inet_ntoa(address));
Window_Write(s->window, buffer, strlen(buffer));
tcb = open_tcp(&lsocket,&fsocket,TCP_ACTIVE,0,
(void (*)())rcv_char,(void(*)())tn_tx,(void(*)())t_state,0,(char *)tn);
tn->tcb = tcb; /* Downward pointer */
return 0;
}
/* Process typed characters */
void unix_send_tel(struct session *session, char *buf, int16 n)
{
int i;
for (i=0; (i<n) && (buf[i] != '\r'); i++)
;
if (buf[i] == '\r') {
buf[i] = '\n';
n = i+1;
}
send_tel(session, buf,n);
}
void send_tel(struct session *session, char *buf, int16 n)
{
struct mbuf *bp;
if(session->cb.telnet == NULLTN || session->cb.telnet->tcb == NULLTCB)
return;
bp = qdata(buf,n);
send_tcp(session->cb.telnet->tcb, bp);
}
/* Process incoming TELNET characters */
void tel_input(register struct telnet *tn, struct mbuf *bp)
{
char c;
register char *s;
char *line;
if ((line = s = malloc(len_mbuf(bp) + 1)) == NULL)
{
free_p(bp);
return;
}
/* Optimization for very common special case -- no special chars */
if(tn->state == TS_DATA){
while(bp != NULLBUF && memchr(bp->data,IAC,bp->cnt) == NULLCHAR){
while (bp->cnt-- != 0) *s++ = *bp->data++;
bp = free_mbuf(bp);
}
}
while (pullup(&bp,&c,1) == 1) {
switch(tn->state){
case TS_DATA:
if(uchar(c) == IAC){
tn->state = TS_IAC;
} else {
if(!tn->remote[TN_TRANSMIT_BINARY])
*s++ = c & 0x7f;
}
break;
case TS_IAC:
switch(uchar(c)){
case WILL:
tn->state = TS_WILL;
break;
case WONT:
tn->state = TS_WONT;
break;
case DO:
tn->state = TS_DO;
break;
case DONT:
tn->state = TS_DONT;
break;
case IAC:
Window_Write(tn->session->window, &c, 1);
tn->state = TS_DATA;
break;
default:
tn->state = TS_DATA;
break;
}
break;
case TS_WILL:
willopt(tn,c);
tn->state = TS_DATA;
break;
case TS_WONT:
wontopt(tn,c);
tn->state = TS_DATA;
break;
case TS_DO:
doopt(tn,c);
tn->state = TS_DATA;
break;
case TS_DONT:
dontopt(tn,c);
tn->state = TS_DATA;
break;
}
}
Window_Write(tn->session->window, line, s - line);
free(line);
}
/* Telnet receiver upcall routine */
void rcv_char(register struct tcb *tcb, int16 cnt)
{
struct mbuf *bp;
struct telnet *tn;
if((tn = (struct telnet *)tcb->user) == NULLTN){
/* Unknown connection; ignore it */
return;
}
if(recv_tcp(tcb,&bp,cnt) > 0)
tel_input(tn,bp);
}
/* Handle transmit upcalls. Used only for file uploading */
void tn_tx(struct tcb *tcb, int16 cnt)
{
tcb = tcb;
cnt = cnt;
}
/* State change upcall routine */
void t_state(register struct tcb *tcb, char old, char new)
{
char buffer[40];
struct telnet *tn;
extern char *tcpstates[];
extern char *reasons[];
extern char *unreach[];
extern char *exceed[];
old = old;
/* Can't add a check for unknown connecti