home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 3 / hamradioversion3.0examsandprograms1992.iso / packet / n17jsrc / tipmail.c < prev    next >
C/C++ Source or Header  |  1991-05-31  |  7KB  |  325 lines

  1. /* "Dumb terminal" mailbox interface
  2.  * Copyright 1991 Phil Karn, KA9Q
  3.  *
  4.  *    May '91    Bill Simpson
  5.  *        move to separate file for compilation & linking
  6.  */
  7. #include "global.h"
  8. #include "mbuf.h"
  9. #include "timer.h"
  10. #include "proc.h"
  11. #include "iface.h"
  12. #ifndef    UNIX
  13. #include "8250.h"
  14. #endif
  15. #include "asy.h"
  16. #include "socket.h"
  17. #include "usock.h"
  18. #include "telnet.h"
  19. #include "mailbox.h"
  20. #include "tipmail.h"
  21.  
  22. static struct tipcb {
  23.     struct tipcb *next;
  24.     struct proc *proc;
  25.     struct proc *in;
  26.     struct iface *iface;
  27.     int (*rawsave) __ARGS((struct iface *,struct mbuf *));
  28.     int s;
  29.     int echo;
  30.     struct timer timer;
  31. } *Tiplist;
  32. #define    NULLTIP    (struct tipcb *)0
  33.  
  34. static void tip_in __ARGS((int dev,void *n1,void *n2));
  35. static void tipidle __ARGS((void *t));
  36.  
  37. unsigned Tiptimeout = 180;    /* Default tip inactivity timeout (seconds) */
  38.  
  39. /* Input process */
  40. static void
  41. tip_in(dev,n1,n2)
  42. int dev;
  43. void *n1,*n2;
  44. {
  45.     struct tipcb *tip;
  46.     struct mbuf *bp;
  47.     char *buf[2], line[MBXLINE];
  48.     int c, ret, pos = 0;
  49.  
  50.     tip = (struct tipcb *) n1;
  51.     while((c = get_asy(dev)) != -1){
  52.         Asy[dev].iface->lastrecv = secclock();
  53.         c &= 0x7f;
  54.         ret = 0;
  55.         if(tip->echo == WONT){
  56.             switch(c){
  57.             case 18:    /* CTRL-R */
  58.                 bp = pushdown(qdata(line,pos),4);
  59.                 memcpy(bp->data,"^R\r\n",4);
  60.                 ret = 1;
  61.                 break;
  62.             case 0x7f:    /* DEL */
  63.             case '\b':
  64.                 bp = NULLBUF;
  65.                 if(pos){
  66.                     --pos;
  67.                     bp = qdata("\b \b",3);
  68.                 }
  69.                 ret = 1;
  70.                 break;
  71.             case '\r':
  72.                 c = '\n';    /* CR => NL */
  73.             case '\n':
  74.                 bp = qdata("\r\n",2);
  75.                 break;
  76.             default:
  77.                 bp = pushdown(NULLBUF,1);
  78.                 *bp->data = c;
  79.                 break;
  80.             }
  81.             asy_send(dev,bp);
  82.             tip->iface->lastsent = secclock();
  83.             if(ret)
  84.                 continue;
  85.         }
  86.         line[pos++] = c;
  87.         if(pos == MBXLINE - 1 || tip->echo == WILL
  88.           || c == '\n'){
  89.             line[pos] = '\0';
  90.             pos = 0;
  91.             usputs(tip->s,line);
  92.             usflush(tip->s);
  93.         }
  94.     }
  95.     /* get_asy() failed, terminate */
  96.     close_s(tip->s);
  97.     tip->in = tip->proc;
  98.     tip->proc = Curproc;
  99.     buf[1] = Asy[dev].iface->name;
  100.     tip0(2,buf,NULL);
  101. }
  102. /* Start mailbox on serial line */
  103. int
  104. tipstart(argc,argv,p)
  105. int argc;
  106. char *argv[];
  107. void *p;
  108. {
  109.     register struct iface *ifp;
  110.     register struct asy *ap;
  111.     struct tipcb *tip;
  112.     struct mbuf *bp;
  113.     char *buf[2];
  114.     int dev, c, cmd, s[2], type = TIP;
  115.  
  116.     if((ifp = if_lookup(argv[1])) == NULLIF){
  117.         tprintf("Interface %s unknown\n",argv[1]);
  118.         return 1;
  119.     }
  120.     for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
  121.         if(ap->iface == ifp)
  122.             break;
  123.     if(dev == ASY_MAX){
  124.         tprintf("Interface %s not asy port\n",argv[1]);
  125.         return 1;
  126.     }
  127.     if(ifp->raw == bitbucket){
  128.         tprintf("Tip session already active on %s\n",argv[1]);
  129.         return 1;
  130.     }
  131.     psignal(Curproc,0);    /* Don't keep the parser waiting */
  132.     chname(Curproc,"Mbox tip");
  133.     tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
  134.     /* Save output handler and temporarily redirect output to null */
  135.     tip->rawsave = ifp->raw;
  136.     ifp->raw = bitbucket;
  137.     tip->iface = ifp;
  138.     tip->proc = Curproc;
  139.     tip->timer.func = tipidle;
  140.     tip->timer.arg = (void *) tip;
  141.     tip->next = Tiplist;
  142.     Tiplist = tip;
  143.     buf[1] = ifp->name;
  144.  
  145.     /* Suspend packet input drivers */
  146.     suspend(ifp->rxproc);
  147.  
  148.     for(;;) {
  149.         if(ap->rlsd_line_control)
  150.             /* Wait for DCD to be asserted */
  151.             get_rlsd_asy(dev,RLSD_UP);
  152.  
  153.         if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
  154.             tprintf("Could not create socket pair, errno %d\n",errno);
  155.             tip0(2,buf,p);
  156.             return 1;
  157.         }
  158.         seteol(s[0],"\n");
  159.         seteol(s[1],"\n");
  160.         tip->echo = WONT;
  161.         tip->s = s[0];
  162.         newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,NULL,0);
  163.         set_timer(&tip->timer,Tiptimeout*1000);
  164.         start_timer(&tip->timer);
  165.         setflush(tip->s,-1);
  166.         sockmode(tip->s,SOCK_ASCII);
  167.  
  168.         /* Now fork into two paths, one rx, one tx */
  169.         tip->in = newproc("Mbox tip in",
  170.                 256,tip_in,dev,(void *)tip,NULL,0);
  171.         while((c = recvchar(tip->s)) != -1) {
  172.             if(c == IAC){    /* ignore most telnet options */
  173.                 if((cmd = recvchar(tip->s)) == -1)
  174.                     break;
  175.                 if(cmd > 250 && cmd < 255) {
  176.                     if((c = recvchar(tip->s)) == -1)
  177.                         break;
  178.                     switch(cmd){
  179.                     case WILL:
  180.                         if(c == TN_ECHO) {
  181.                             tip->echo = cmd;
  182.                             cmd = DO;
  183.                         }
  184.                         else
  185.                             cmd = DONT;
  186.                         break;
  187.                     case WONT:
  188.                         if(c == TN_ECHO)
  189.                             tip->echo = cmd;
  190.                         cmd = DONT;
  191.                         break;
  192.                     case DO:
  193.                     case DONT:
  194.                         cmd = WONT;
  195.                         break;
  196.                     }
  197.                     usprintf(tip->s,"%c%c%c",IAC,cmd,c);
  198.                     usflush(tip->s);
  199.                 }
  200.                 continue;
  201.             }
  202.             if(c == '\n')
  203.                 bp = qdata("\r\n",2);
  204.             else {
  205.                 bp = pushdown(NULLBUF,1);
  206.                 *bp->data = c;
  207.             }
  208.             asy_send(dev,bp);
  209.             ifp->lastsent = secclock();
  210.         }
  211.         close_s(tip->s);
  212.         killproc(tip->in);
  213.         tip->in = NULLPROC;
  214.         pwait(itop(s[1])); /* let mailbox terminate, if necessary */
  215.         stop_timer(&tip->timer);
  216.         if(ap->rlsd_line_control)
  217.             /* Wait for DCD to be dropped */
  218.             get_rlsd_asy(dev,RLSD_DOWN);
  219.     }
  220. }
  221. int
  222. tip0(argc,argv,p)
  223. int argc;
  224. char *argv[];
  225. void *p;
  226. {
  227.     register struct iface *ifp;
  228.     struct tipcb *tip, *prev = NULLTIP;
  229.     struct proc *proc;
  230.  
  231.     if((ifp = if_lookup(argv[1])) == NULLIF){
  232.         tprintf("Interface %s unknown\n",argv[1]);
  233.         return 1;
  234.     }
  235.     for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  236.         if(tip->iface == ifp) {
  237.             if(prev != NULLTIP)
  238.                 prev->next = tip->next;
  239.             else
  240.                 Tiplist = tip->next;
  241.             proc = tip->proc;
  242.             close_s(tip->s);
  243.             ifp->raw = tip->rawsave;
  244.             resume(ifp->rxproc);
  245.             stop_timer(&tip->timer);
  246.             killproc(tip->in);
  247.             free((char *)tip);
  248.             killproc(proc);
  249.             return 0;
  250.         }
  251.     return 0;
  252. }
  253. static void
  254. tipidle(t)
  255. void *t;
  256. {
  257.     struct tipcb *tip;
  258.     static char *msg = "You have been idle too long. Please hang up.\r\n";
  259.     tip = (struct tipcb *) t;
  260.     if(secclock() - tip->iface->lastrecv < Tiptimeout){
  261.         set_timer(&tip->timer,(Tiptimeout-secclock() *
  262.          tip->iface->lastrecv)*1000);
  263.         start_timer(&tip->timer);
  264.         return;
  265.     }
  266.     asy_send(tip->iface->dev,qdata(msg,strlen(msg)));
  267.     tip->iface->lastsent = secclock();
  268.     close_s(tip->s);
  269. }
  270.  
  271. static int Stelnet = -1;
  272.  
  273. /* Start up Telnet server */
  274. int
  275. telnet1(argc,argv,p)
  276. int argc;
  277. char *argv[];
  278. void *p;
  279. {
  280.     struct sockaddr_in lsocket;
  281.     int s;
  282.     int type;
  283.  
  284.     if(Stelnet != -1){
  285.         return 0;
  286.     }
  287.     psignal(Curproc,0);     /* Don't keep the parser waiting */
  288.     chname(Curproc,"Telnet listener");
  289.  
  290.     lsocket.sin_family = AF_INET;
  291.     lsocket.sin_addr.s_addr = INADDR_ANY;
  292.     if(argc < 2)
  293.         lsocket.sin_port = IPPORT_TELNET;
  294.     else
  295.         lsocket.sin_port = atoi(argv[1]);
  296.     Stelnet = socket(AF_INET,SOCK_STREAM,0);
  297.     bind(Stelnet,(char *)&lsocket,sizeof(lsocket));
  298.     listen(Stelnet,1);
  299.     for(;;){
  300.         if((s = accept(Stelnet,NULLCHAR,(int *)NULL)) == -1)
  301.             break;    /* Service is shutting down */
  302.  
  303.         if(availmem() < Memthresh){
  304.             shutdown(s,1);
  305.         } else {
  306.             /* Spawn a server */
  307.             type = TELNET;
  308.             newproc("mbox",2048,mbx_incom,s,(void *)type,NULL,0);
  309.         }
  310.     }
  311.     return 0;
  312. }
  313. /* Stop telnet server */
  314. int
  315. telnet0(argc,argv,p)
  316. int argc;
  317. char *argv[];
  318. void *p;
  319. {
  320.     close_s(Stelnet);
  321.     Stelnet = -1;
  322.     return 0;
  323. }
  324.  
  325.