home *** CD-ROM | disk | FTP | other *** search
/ Media Share 9 / MEDIASHARE_09.ISO / hamradio / s920603.zip / TIPMAIL.C < prev    next >
C/C++ Source or Header  |  1992-05-19  |  7KB  |  327 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 "n8250.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.     FILE *network;
  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.             fputs(line,tip->network);
  95.             fflush(tip->network);
  96.         }
  97.     }
  98.     /* get_asy() failed, terminate */
  99.     fclose(tip->network);
  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.         printf("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.         printf("Interface %s not asy port\n",argv[1]);
  128.         return 1;
  129.     }
  130.     if(ifp->raw == bitbucket){
  131.         printf("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,1);
  155.  
  156.         if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
  157.             printf("Could not create socket pair, errno %d\n",errno);
  158.             tip0(2,buf,p);
  159.             return 1;
  160.         }
  161.         tip->echo = WONT;
  162.         tip->network = fdopen(s[0],"r+t");
  163.         newproc("mbx_incom",2048,mbx_incom,s[1],(void *)type,NULL,0);
  164.         set_timer(&tip->timer,Tiptimeout*1000);
  165.         start_timer(&tip->timer);
  166.  
  167.         /* Now fork into two paths, one rx, one tx */
  168.         tip->in = newproc("Mbox tip in",
  169.                 256,tip_in,dev,(void *)tip,NULL,0);
  170.         while((c = getc(tip->network)) != -1) {
  171.             if(c == IAC){    /* ignore most telnet options */
  172.                 if((cmd = getc(tip->network)) == -1)
  173.                     break;
  174.                 if(cmd > 250 && cmd < 255) {
  175.                     if((c = getc(tip->network)) == -1)
  176.                         break;
  177.                     switch(cmd){
  178.                     case WILL:
  179.                         if(c == TN_ECHO) {
  180.                             tip->echo = cmd;
  181.                             cmd = DO;
  182.                         }
  183.                         else
  184.                             cmd = DONT;
  185.                         break;
  186.                     case WONT:
  187.                         if(c == TN_ECHO)
  188.                             tip->echo = cmd;
  189.                         cmd = DONT;
  190.                         break;
  191.                     case DO:
  192.                     case DONT:
  193.                         cmd = WONT;
  194.                         break;
  195.                     }
  196.                     fprintf(tip->network,"%c%c%c",IAC,cmd,c);
  197.                     fflush(tip->network);
  198.                 }
  199.                 continue;
  200.             }
  201.             if(c == '\n')
  202.                 bp = qdata("\r\n",2);
  203.             else {
  204.                 bp = pushdown(NULLBUF,1);
  205.                 *bp->data = c;
  206.             }
  207.             asy_send(dev,bp);
  208.             ifp->lastsent = secclock();
  209.         }
  210.         fclose(tip->network);
  211.         killproc(tip->in);
  212.         tip->in = NULLPROC;
  213.         pwait(itop(s[1])); /* let mailbox terminate, if necessary */
  214.         stop_timer(&tip->timer);
  215.  
  216.         /* Tell line to go down */
  217.         ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  218.  
  219.         /* Wait for DCD to be dropped */
  220.         get_rlsd_asy(dev,0);
  221.     }
  222. }
  223. int
  224. tip0(argc,argv,p)
  225. int argc;
  226. char *argv[];
  227. void *p;
  228. {
  229.     register struct iface *ifp;
  230.     struct tipcb *tip, *prev = NULLTIP;
  231.     struct proc *proc;
  232.  
  233.     if((ifp = if_lookup(argv[1])) == NULLIF){
  234.         printf("Interface %s unknown\n",argv[1]);
  235.         return 1;
  236.     }
  237.     for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  238.         if(tip->iface == ifp) {
  239.             if(prev != NULLTIP)
  240.                 prev->next = tip->next;
  241.             else
  242.                 Tiplist = tip->next;
  243.             proc = tip->proc;
  244.             fclose(tip->network);
  245.             ifp->raw = tip->rawsave;
  246.             resume(ifp->rxproc);
  247.             stop_timer(&tip->timer);
  248.             killproc(tip->in);
  249.             free((char *)tip);
  250.             killproc(proc);
  251.             return 0;
  252.         }
  253.     return 0;
  254. }
  255. static void
  256. tipidle(t)
  257. void *t;
  258. {
  259.     struct tipcb *tip;
  260.     static char *msg = "You have been idle too long. Please hang up.\r\n";
  261.     tip = (struct tipcb *) t;
  262.     if(secclock() - tip->iface->lastrecv < Tiptimeout){
  263.         set_timer(&tip->timer,(Tiptimeout-secclock() *
  264.          tip->iface->lastrecv)*1000);
  265.         start_timer(&tip->timer);
  266.         return;
  267.     }
  268.     asy_send(tip->iface->dev,qdata(msg,strlen(msg)));
  269.     tip->iface->lastsent = secclock();
  270.     fclose(tip->network);
  271. }
  272.  
  273. static int Stelnet = -1;
  274.  
  275. /* Start up Telnet server */
  276. int
  277. telnet1(argc,argv,p)
  278. int argc;
  279. char *argv[];
  280. void *p;
  281. {
  282.     struct sockaddr_in lsocket;
  283.     int s;
  284.     int type;
  285.  
  286.     if(Stelnet != -1){
  287.         return 0;
  288.     }
  289.     psignal(Curproc,0);     /* Don't keep the parser waiting */
  290.     chname(Curproc,"Telnet listener");
  291.  
  292.     lsocket.sin_family = AF_INET;
  293.     lsocket.sin_addr.s_addr = INADDR_ANY;
  294.     if(argc < 2)
  295.         lsocket.sin_port = IPPORT_TELNET;
  296.     else
  297.         lsocket.sin_port = atoi(argv[1]);
  298.     Stelnet = socket(AF_INET,SOCK_STREAM,0);
  299.     bind(Stelnet,(char *)&lsocket,sizeof(lsocket));
  300.     listen(Stelnet,1);
  301.     for(;;){
  302.         if((s = accept(Stelnet,NULLCHAR,(int *)NULL)) == -1)
  303.             break;    /* Service is shutting down */
  304.  
  305.         if(availmem() != 0){
  306.             shutdown(s,1);
  307.         } else {
  308.             /* Spawn a server */
  309.             type = TELNET;
  310.             newproc("mbox",2048,mbx_incom,s,(void *)type,NULL,0);
  311.         }
  312.     }
  313.     return 0;
  314. }
  315. /* Stop telnet server */
  316. int
  317. telnet0(argc,argv,p)
  318. int argc;
  319. char *argv[];
  320. void *p;
  321. {
  322.     close_s(Stelnet);
  323.     Stelnet = -1;
  324.     return 0;
  325. }
  326.  
  327.