home *** CD-ROM | disk | FTP | other *** search
/ HAM Radio 1 / HamRadio.cdr / misc / tcpipsrc / tip.c < prev    next >
C/C++ Source or Header  |  1991-01-26  |  8KB  |  349 lines

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