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