home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 1
/
HamRadio.cdr
/
misc
/
src0131
/
tip.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-01-26
|
8KB
|
349 lines
/* "Dumb terminal" session command for serial lines
* Copyright 1991 Phil Karn, KA9Q
*/
#include <stdio.h>
#include "global.h"
#include "mbuf.h"
#include "iface.h"
#ifndef UNIX
#include "8250.h"
#endif
#include "asy.h"
#include "session.h"
#include "proc.h"
#include "tty.h"
#include "socket.h"
#include "commands.h"
#include "config.h"
#ifdef MAILBOX
#include "telnet.h"
#include "timer.h"
#include "mailbox.h"
static struct tipcb {
struct tipcb *next;
struct proc *proc;
struct proc *in;
struct iface *iface;
int (*rawsave) __ARGS((struct iface *,struct mbuf *));
int s;
int echo;
struct timer timer;
} *Tiplist;
#define NULLTIP (struct tipcb *)0
static void tip_in __ARGS((int dev,void *n1,void *n2));
static void tipidle __ARGS((void *t));
#endif
static void tip_out __ARGS((int dev,void *n1,void *n2));
/* Execute user telnet command */
int
dotip(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct session *sp;
register struct iface *ifp;
register struct asy *ap;
int (*rawsave) __ARGS((struct iface *,struct mbuf *));
int dev;
int c;
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf("Interface %s unknown\n",argv[1]);
return 1;
}
for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
if(ap->iface == ifp)
break;
if(dev == ASY_MAX){
tprintf("Interface %s not asy port\n",argv[1]);
return 1;
}
if(ifp->raw == dumppkt){
tprintf("tip or dialer session already active on %s\n",argv[1]);
return 1;
}
/* Allocate a session descriptor */
if((sp = newsession(argv[1],TIP)) == NULLSESSION){
tprintf("Too many sessions\n");
return 1;
}
/* Save output handler and temporarily redirect output to null */
rawsave = ifp->raw;
ifp->raw = dumppkt;
/* Suspend packet input drivers */
suspend(ifp->rxproc);
/* Put tty into raw mode */
sp->ttystate.echo = 0;
sp->ttystate.edit = 0;
sockmode(sp->output,SOCK_BINARY);
/* Now fork into two paths, one rx, one tx */
sp->proc1 = newproc("tip_out",256,tip_out,dev,NULL,NULL,0);
while((c = get_asy(ifp->dev)) != -1)
tputc(c & 0x7f);
killproc(sp->proc1);
sp->proc1 = NULLPROC;
ifp->raw = rawsave;
resume(ifp->rxproc);
keywait(NULLCHAR,1);
freesession(sp);
return 1;
}
/* Output process, DTE version */
static void
tip_out(dev,n1,n2)
int dev;
void *n1,*n2;
{
struct mbuf *bp;
int c;
while((c = recvchar(Curproc->input)) != EOF){
if(c == '\n')
c = '\r'; /* NL => CR */
bp = pushdown(NULLBUF,1);
bp->data[0] = c;
asy_send(dev,bp);
Asy[dev].iface->lastsent = secclock();
}
}
#ifdef MAILBOX
/* Input process */
static void
tip_in(dev,n1,n2)
int dev;
void *n1,*n2;
{
struct tipcb *tip;
struct mbuf *bp;
char *buf[2], line[MBXLINE];
int c, ret, pos = 0;
tip = (struct tipcb *) n1;
while((c = get_asy(dev)) != -1){
Asy[dev].iface->lastrecv = secclock();
c &= 0x7f;
ret = 0;
if(tip->echo == WONT){
switch(c){
case 18: /* CTRL-R */
bp = pushdown(qdata(line,pos),4);
memcpy(bp->data,"^R\r\n",4);
ret = 1;
break;
case 0x7f: /* DEL */
case '\b':
bp = NULLBUF;
if(pos){
--pos;
bp = qdata("\b \b",3);
}
ret = 1;
break;
case '\r':
c = '\n'; /* CR => NL */
case '\n':
bp = qdata("\r\n",2);
break;
default:
bp = pushdown(NULLBUF,1);
*bp->data = c;
break;
}
asy_send(dev,bp);
tip->iface->lastsent = secclock();
if(ret)
continue;
}
line[pos++] = c;
if(pos == MBXLINE - 1 || tip->echo == WILL
|| c == '\n'){
line[pos] = '\0';
pos = 0;
usputs(tip->s,line);
usflush(tip->s);
}
}
/* get_asy() failed, terminate */
close_s(tip->s);
tip->in = tip->proc;
tip->proc = Curproc;
buf[1] = Asy[dev].iface->name;
tip0(2,buf,NULL);
}
/* Start mailbox on serial line */
int
tipstart(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct iface *ifp;
register struct asy *ap;
struct tipcb *tip;
struct mbuf *bp;
char *buf[2];
int dev, c, cmd, s[2], type = TIP;
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf("Interface %s unknown\n",argv[1]);
return 1;
}
for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
if(ap->iface == ifp)
break;
if(dev == ASY_MAX){
tprintf("Interface %s not asy port\n",argv[1]);
return 1;
}
if(ifp->raw == dumppkt){
tprintf("Tip session already active on %s\n",argv[1]);
return 1;
}
psignal(Curproc,0); /* Don't keep the parser waiting */
chname(Curproc,"Mbox tip");
tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
/* Save output handler and temporarily redirect output to null */
tip->rawsave = ifp->raw;
ifp->raw = dumppkt;
tip->iface = ifp;
tip->proc = Curproc;
tip->timer.func = tipidle;
tip->timer.arg = (void *) tip;
tip->next = Tiplist;
Tiplist = tip;
buf[1] = ifp->name;
/* Suspend packet input drivers */
suspend(ifp->rxproc);
for(;;) {
if(ap->rlsd_line_control)
get_rlsd_asy(dev,100);/* Wait for DCD to be asserted */
if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
tprintf("Could not create socket pair, errno %d\n",errno);
tip0(2,buf,p);
return 1;
}
seteol(s[0],"\n");
seteol(s[1],"\n");
tip->echo = WONT;
tip->s = s[0];
newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,NULL,0);
set_timer(&tip->timer,Tiptimeout*1000);
start_timer(&tip->timer);
setflush(tip->s,-1);
sockmode(tip->s,SOCK_ASCII);
/* Now fork into two paths, one rx, one tx */
tip->in = newproc("Mbox tip in",256,tip_in,dev,(void *)tip,
NULL,0);
while((c = recvchar(tip->s)) != -1) {
if(c == IAC){ /* ignore most telnet options */
if((cmd = recvchar(tip->s)) == -1)
break;
if(cmd > 250 && cmd < 255) {
if((c = recvchar(tip->s)) == -1)
break;
switch(cmd){
case WILL:
if(c == TN_ECHO) {
tip->echo = cmd;
cmd = DO;
}
else
cmd = DONT;
break;
case WONT:
if(c == TN_ECHO)
tip->echo = cmd;
cmd = DONT;
break;
case DO:
case DONT:
cmd = WONT;
break;
}
usprintf(tip->s,"%c%c%c",IAC,cmd,c);
usflush(tip->s);
}
continue;
}
if(c == '\n')
bp = qdata("\r\n",2);
else {
bp = pushdown(NULLBUF,1);
*bp->data = c;
}
asy_send(dev,bp);
ifp->lastsent = secclock();
}
close_s(tip->s);
killproc(tip->in);
tip->in = NULLPROC;
pwait(itop(s[1])); /* let mailbox terminate, if necessary */
stop_timer(&tip->timer);
if(ap->rlsd_line_control)
/* Wait for DCD to be dropped */
get_rlsd_asy(dev,1);
}
}
int
tip0(argc,argv,p)
int argc;
char *argv[];
void *p;
{
register struct iface *ifp;
struct tipcb *tip, *prev = NULLTIP;
struct proc *proc;
if((ifp = if_lookup(argv[1])) == NULLIF){
tprintf("Interface %s unknown\n",argv[1]);
return 1;
}
for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
if(tip->iface == ifp) {
if(prev != NULLTIP)
prev->next = tip->next;
else
Tiplist = tip->next;
proc = tip->proc;
close_s(tip->s);
ifp->raw = tip->rawsave;
resume(ifp->rxproc);
stop_timer(&tip->timer);
killproc(tip->in);
free((char *)tip);
killproc(proc);
return 0;
}
return 0;
}
static void
tipidle(t)
void *t;
{
struct tipcb *tip;
static char *msg = "You have been idle too long. Please hang up.\r\n";
tip = (struct tipcb *) t;
if(secclock() - tip->iface->lastrecv < Tiptimeout){
set_timer(&tip->timer,(Tiptimeout-secclock() *
tip->iface->lastrecv)*1000);
start_timer(&tip->timer);
return;
}
asy_send(tip->iface->dev,qdata(msg,strlen(msg)));
tip->iface->lastsent = secclock();
close_s(tip->s);
}
#endif