home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HAM Radio 3
/
hamradioversion3.0examsandprograms1992.iso
/
packet
/
n17jsrc
/
tipmail.c
< prev
next >
Wrap
C/C++ Source or Header
|
1991-05-31
|
7KB
|
325 lines
/* "Dumb terminal" mailbox interface
* Copyright 1991 Phil Karn, KA9Q
*
* May '91 Bill Simpson
* move to separate file for compilation & linking
*/
#include "global.h"
#include "mbuf.h"
#include "timer.h"
#include "proc.h"
#include "iface.h"
#ifndef UNIX
#include "8250.h"
#endif
#include "asy.h"
#include "socket.h"
#include "usock.h"
#include "telnet.h"
#include "mailbox.h"
#include "tipmail.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));
unsigned Tiptimeout = 180; /* Default tip inactivity timeout (seconds) */
/* 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 == bitbucket){
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 = bitbucket;
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)
/* Wait for DCD to be asserted */
get_rlsd_asy(dev,RLSD_UP);
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,RLSD_DOWN);
}
}
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);
}
static int Stelnet = -1;
/* Start up Telnet server */
int
telnet1(argc,argv,p)
int argc;
char *argv[];
void *p;
{
struct sockaddr_in lsocket;
int s;
int type;
if(Stelnet != -1){
return 0;
}
psignal(Curproc,0); /* Don't keep the parser waiting */
chname(Curproc,"Telnet listener");
lsocket.sin_family = AF_INET;
lsocket.sin_addr.s_addr = INADDR_ANY;
if(argc < 2)
lsocket.sin_port = IPPORT_TELNET;
else
lsocket.sin_port = atoi(argv[1]);
Stelnet = socket(AF_INET,SOCK_STREAM,0);
bind(Stelnet,(char *)&lsocket,sizeof(lsocket));
listen(Stelnet,1);
for(;;){
if((s = accept(Stelnet,NULLCHAR,(int *)NULL)) == -1)
break; /* Service is shutting down */
if(availmem() < Memthresh){
shutdown(s,1);
} else {
/* Spawn a server */
type = TELNET;
newproc("mbox",2048,mbx_incom,s,(void *)type,NULL,0);
}
}
return 0;
}
/* Stop telnet server */
int
telnet0(argc,argv,p)
int argc;
char *argv[];
void *p;
{
close_s(Stelnet);
Stelnet = -1;
return 0;
}