home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / TIPMAIL.C < prev    next >
C/C++ Source or Header  |  1994-07-05  |  15KB  |  481 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.  *      Jan '93 Doug Crompton
  9.  *              Mods to code to make it work with both terminal
  10.  *              and Modem. Timers and CD check revamped. Now Always
  11.  *              detects CD loss and timeouts work properly.
  12.  *              Setting Tiptimeout to 0 disables idle timeout
  13.  *      Feb '93 Added code to support Xmodem - RAW Serial DATA
  14.  *      Mar '93 Changed asy_send to asy_sen_wait, an internal function
  15.  *              To eliminate asyinc buffers from growing beyond control
  16.  *              and to stop data from flowing to serial device if CD is lost
  17.  *      Jun '94 James Dugal - added code to reset server if CD lost or idle
  18.  *              timeout occurs.  Also mark closure of tip socket to avoid probs.
  19.  *
  20.  * Command Syntax now : 'start tip <interface> <modem|terminal> [timeout sec]'
  21.  */
  22. #include "global.h"
  23. #if defined TIPSERVER || defined TELNETSERVER
  24. #include "mbuf.h"
  25. #include "timer.h"
  26. #include "proc.h"
  27. #include "iface.h"
  28. #ifndef UNIX
  29. #include "i8250.h"
  30. #endif
  31. #ifdef LINUX
  32. #include "lxasy.h"
  33. #endif
  34. #include "asy.h"
  35. #include "socket.h"
  36. #include "usock.h"
  37. #include "telnet.h"
  38. #include "mailbox.h"
  39. #include "tipmail.h"
  40. #include "devparam.h"
  41. #include "lapb.h"
  42.   
  43. #ifdef TIPSERVER
  44.   
  45. static void tip_in __ARGS((int dev,void *n1,void *n2));
  46. static void tipidle __ARGS((void *t));
  47. static int asy_send_wait __ARGS((int dev,int modem,struct mbuf *bp));
  48.   
  49. #define Tiptimeout 180;      /* Default tip inactivity timeout (seconds) */
  50.   
  51. /* Input process */
  52. static void
  53. tip_in(dev,n1,n2)
  54. int dev;
  55. void *n1,*n2;
  56. {
  57.     struct tipcb *tip;
  58.     struct mbuf *bp;
  59.     char *buf[2], line[MBXLINE];
  60.     int c, ret, pos = 0;
  61.   
  62.     tip = (struct tipcb *) n1;
  63.   
  64.     while((c = get_asy(dev)) != -1){
  65.         tip->firstwarn=1;
  66.         tip->timeout=tip->default_timeout;
  67.         Asy[dev].iface->lastrecv = secclock();
  68.         if (!tip->raw) {
  69.             bp = NULLBUF;
  70.             c &= 0x7f;
  71.             ret = 0;
  72.             if(tip->echo == WONT){
  73.                 switch(c){
  74.                     case 21:        /* CTRL-U */        /*DCB*/
  75.                         if (pos){
  76.                             bp = qdata("^U\r\n",4);
  77.                             pos = 0;
  78.                         }
  79.                         ret = 1;
  80.                         break;
  81.                     case 18:        /* CTRL-R */
  82.                         if(pos){    /* DCB */
  83.                             bp = pushdown(qdata(line,pos),4);
  84.                             memcpy(bp->data,"^R\r\n",4);
  85.                         }
  86.                         ret = 1;
  87.                         break;
  88.                     case 0x7f:      /* DEL */
  89.                     case '\b':
  90.                         bp = NULLBUF;
  91.                         if(pos){
  92.                             --pos;
  93.                             bp = qdata("\b \b",3);
  94.                         }
  95.                         ret = 1;
  96.                         break;
  97.                     case '\r':
  98.                         c = '\n';       /* CR => NL */
  99.                     case '\n':
  100.                         bp = qdata("\r\n",2);
  101.                         break;
  102.                     default:
  103.                         bp = pushdown(NULLBUF,1);
  104.                         *bp->data = c;
  105.                         break;
  106.                 }
  107.                 asy_send_wait(dev,tip->chk_modem_cd,bp);
  108.                 tip->iface->lastsent = secclock();
  109.                 if(ret)
  110.                     continue;
  111.             }
  112.             line[pos++] = c;
  113.             if(pos == MBXLINE - 1 || tip->echo == WILL
  114.             || c == '\n'){
  115.                 line[pos] = '\0';
  116.                 pos = 0;
  117.                 usputs(tip->s,line);
  118.                 usflush(tip->s);
  119.             }
  120.         } else {
  121.             usputc(tip->s,c);
  122.             usflush(tip->s);
  123.         }
  124.     }
  125.     /* get_asy() failed, terminate */
  126.     close_s(tip->s); tip->s = -1;
  127.     tip->in = tip->proc;     /* tip0 must kill me last, not first! */
  128.     tip->proc = Curproc;
  129.     buf[1] = Asy[dev].iface->name;
  130.     tip0(2,buf,NULL);
  131. }
  132. /* Start mailbox on serial line */
  133. int
  134. tipstart(argc,argv,p)
  135. int argc;
  136. char *argv[];
  137. void *p;
  138. {
  139.     register struct iface *ifp;
  140.     register struct asy *ap;
  141.     register struct tipcb *tip;
  142.     struct mbuf *bp, *dp, *op; /* op is output, dp is duplicate */
  143. #ifndef LINUX
  144.     struct fifo *fp;
  145. #endif
  146.     char *buf[2];
  147.     int dev, c, i, off, cnt, cmd, s[2], type = TIP_LINK;
  148.   
  149.     if((ifp = if_lookup(argv[1])) == NULLIF){
  150.         tprintf(Badinterface,argv[1]);
  151.         return 1;
  152.     }
  153.     for(dev=0,ap = Asy;dev < ASY_MAX;dev++,ap++)
  154.         if(ap->iface == ifp)
  155.             break;
  156.     if(dev == ASY_MAX){
  157.         tprintf("Interface %s not asy port\n",argv[1]);
  158.         return 1;
  159.     }
  160.     if(ifp->raw == bitbucket){
  161.         tprintf("Tip session already active on %s\n",argv[1]);
  162.         return 1;
  163.     }
  164.     psignal(Curproc,0);     /* Don't keep the parser waiting */
  165.     chname(Curproc,"Mbox tip");
  166.     tip = (struct tipcb *) callocw(1,sizeof(struct tipcb));
  167.   
  168.     tprintf("Tip started on %s - ",argv[1]);
  169.     switch (argv[2][0]) {
  170.         case 'm':
  171.         case 'M':
  172.             tip->chk_modem_cd=1;
  173.             tputs(" with");
  174.             break;
  175.         default : tip->chk_modem_cd=0;
  176.             tputs(" without");
  177.     }
  178.     tputs(" CD check - ");
  179.     if (argc>3)
  180.         tip->default_timeout=atoi(argv[3]);
  181.     else
  182.         tip->default_timeout=Tiptimeout;
  183.   
  184.     if (tip->default_timeout)
  185.         tprintf("%d Second",tip->default_timeout);
  186.     else
  187.         tputs("No");
  188.     tputs(" Timeout\n");
  189.   
  190.     /* Save output handler and temporarily redirect output to null */
  191.     tip->asy_dev=dev;
  192.     tip->rawsave = ifp->raw;
  193.     ifp->raw = bitbucket;
  194.     tip->iface = ifp;
  195.     tip->proc = Curproc;
  196.     tip->timer.func = tipidle;
  197.     tip->timer.arg = (void *) tip;
  198.     tip->raw=0;
  199.     tip->next = Tiplist;
  200.     Tiplist = tip;
  201.     buf[1] = ifp->name;
  202.   
  203.     /* Suspend packet input drivers */
  204.     suspend(ifp->rxproc);
  205.   
  206.     for(;;) {
  207.         ifp->ioctl(ifp,PARAM_UP,TRUE,0L);
  208.   
  209.         /* Wait for DCD to be asserted if modem*/
  210.         if (tip->chk_modem_cd) {
  211.             pause(1000L);
  212.             while (! carrier_detect(tip->asy_dev))
  213.                 pwait(NULL);
  214.             pause(1000L);
  215.         }
  216.   
  217.         if(socketpair(AF_LOCAL,SOCK_STREAM,0,s) == -1){
  218.             tprintf("Could not create socket pair, errno %d\n",errno);
  219.             tip0(2,buf,p);
  220.             return 1;
  221.         }
  222.         seteol(s[0],"\n");
  223.         seteol(s[1],"\n");
  224.         tip->echo = WONT;
  225.         tip->s = s[0];
  226.         if (tip->chk_modem_cd) {
  227.             log(tip->s,"Telephone MBOX Login");
  228.         }
  229. #ifdef MAILBOX
  230.         newproc("MBOX Tip Server",2048,mbx_incom,s[1],(void *)type,(void *)tip,0);
  231. #else
  232.         newproc("TTYLINK Tip",2048,ttylink_tcp,s[1],NULL,NULL,0);
  233. #endif
  234.         /* check for line idle timeout and CD failure */
  235.         tip->firstwarn=1;
  236.         tip->timeout=tip->default_timeout;
  237.         set_timer(&tip->timer,1000L);
  238.         start_timer(&tip->timer);
  239.   
  240.         setflush(tip->s,-1);
  241.         sockmode(tip->s,SOCK_ASCII);
  242.   
  243.         /* Now fork into two paths, one rx, one tx */
  244. #ifndef LINUX
  245.         /* first clear (ignore) junk in asyinc input
  246.            which is always receiving - modem can garbage
  247.            on disconnect
  248.         */
  249.         fp = &ap->fifo;
  250.         fp->wp = fp->rp = fp->buf;
  251.         fp->cnt = 0;
  252. #endif
  253.   
  254.         tip->in = newproc("Mbox tip in",256,tip_in,dev,(void *)tip,NULL,0);
  255.         while((cnt = recv_mbuf(tip->s,&bp,0,NULL,0)) != -1) {
  256.             if(!tip->raw) {
  257.                 dup_p(&dp,bp,off=0,cnt); /* dup the whole pkt to pull */
  258.                 for (i=0; i<cnt; i++)
  259.                 switch(PULLCHAR(&dp)) {
  260.                     case IAC:      /* ignore most telnet options */
  261.                         dup_p(&op,bp,off,i-off);
  262.                         asy_send_wait(dev,tip->chk_modem_cd,op);
  263.                         ifp->lastsent = secclock();
  264.   
  265.                         if((cmd = ++i < cnt ?  PULLCHAR(&dp) :
  266.                             recvchar(tip->s)) == -1)
  267.                             break;
  268.                         if(cmd > 250 && cmd < 255) {
  269.                             if((c = ++i < cnt ? PULLCHAR(&dp) :
  270.                                 recvchar(tip->s)) == -1)
  271.                                 break;
  272.                             switch(cmd){
  273.                                 case WILL:
  274.                                     if(c == TN_ECHO) {
  275.                                         tip->echo = cmd;
  276.                                         cmd = DO;
  277.                                     }
  278.                                     else
  279.                                         cmd = DONT;
  280.                                     break;
  281.                                 case WONT:
  282.                                     if(c == TN_ECHO)
  283.                                         tip->echo = cmd;
  284.                                     cmd = DONT;
  285.                                     break;
  286.                                 case DO:
  287.                                 case DONT:
  288.                                     cmd = WONT;
  289.                                     break;
  290.                             }
  291. /*                      usprintf(tip->s,"%c%c%c",IAC,cmd,c);    */
  292.                             usputc(tip->s,IAC);
  293.                             usputc(tip->s,cmd);
  294.                             usputc(tip->s,c);
  295.                             usflush(tip->s);
  296.                         }
  297.                         off = i + 1;
  298.                         break;
  299.                     case '\r':
  300.                         if ( ++i < cnt &&  /* Skip NL but not IAC */
  301.                         (PULLCHAR(&dp) == IAC)) {
  302.                             dp = pushdown(dp,1);
  303.                             *dp->data = IAC;
  304.                         }
  305.                         break;
  306.                     case '\n':
  307.                         dup_p(&op,bp,off,i-off);
  308.                         append(&op,qdata("\r\n",2));
  309.                         asy_send_wait(dev,tip->chk_modem_cd,op);
  310.                         ifp->lastsent = secclock();
  311.                         off = i + 1;
  312.                         break;
  313.                 }
  314.   
  315.                 (void)pullup(&bp,NULLCHAR,off);
  316.                 asy_send_wait(dev,tip->chk_modem_cd,bp);
  317.             } else {
  318.                 asy_send_wait(dev,tip->chk_modem_cd,bp);
  319.             }
  320.             ifp->lastsent = secclock();
  321.             tip->firstwarn=1;
  322.             tip->timeout=tip->default_timeout;
  323.             if (pwait(NULL)) break;       /* alert() provides errno */
  324.         }
  325.  
  326.         stop_timer(&tip->timer);
  327.         pause(2000L);
  328.         close_s(tip->s); tip->s = -1;
  329.         killproc(tip->in);
  330.         tip->in=NULLPROC;
  331.   
  332.         pwait(itop(s[1])); /* let mailbox terminate, if necessary */
  333.   
  334.         /* Tell line to go down if modem */
  335.         if (tip->chk_modem_cd) {
  336.             ifp->ioctl(ifp,PARAM_DOWN,TRUE,0L);
  337.             pause(5000L);
  338.         }
  339.   
  340.     }
  341. }
  342.   
  343. /* Send a message on the specified serial line
  344.    Wait for queue to empty - for slow serial
  345.    lines where data flow control is desired
  346.    Eliminates large queue - I.E. memory hogging
  347.    Stops data from flowing if CD is lost       */
  348.   
  349. static int
  350. asy_send_wait(dev,modem,bp)
  351. int dev;
  352. int modem;
  353. struct mbuf *bp;
  354.   
  355. {
  356.     if (carrier_detect(dev) || !modem) {
  357.         asy_send(dev,bp);
  358.         while (len_p((struct mbuf*)&Asy[dev].sndq)>1
  359.         && (carrier_detect(dev) || !modem)){
  360.             pwait(NULL);
  361.         }
  362.   
  363.     } else {
  364.         free_p(bp);
  365.     }
  366.     return 0;
  367. }
  368.   
  369. int
  370. tip0(argc,argv,p)
  371. int argc;
  372. char *argv[];
  373. void *p;
  374. {
  375.     register struct iface *ifp;
  376.     struct tipcb *tip, *prev = NULLTIP;
  377.     struct proc *proc;
  378.   
  379.     if((ifp = if_lookup(argv[1])) == NULLIF){
  380.         tprintf(Badinterface,argv[1]);
  381.         return 1;
  382.     }
  383.     for(tip = Tiplist; tip != NULLTIP; prev = tip, tip = tip->next)
  384.         if(tip->iface == ifp) {
  385.             if(prev != NULLTIP)
  386.                 prev->next = tip->next;
  387.             else
  388.                 Tiplist = tip->next;
  389.             proc = tip->proc;
  390.             close_s(tip->s); tip->s = -1;
  391.             ifp->raw = tip->rawsave;
  392.             resume(ifp->rxproc);
  393.             stop_timer(&tip->timer);
  394.             killproc(tip->in);
  395.             tip->in = NULLPROC;
  396.             free((char *)tip);
  397.             killproc(proc);
  398.             return 0;
  399.         }
  400.     return 0;
  401. }
  402.   
  403. static void
  404. tipidle(t)
  405. void *t;
  406. {
  407.     struct tipcb *tip;
  408.     static char *msg1 = "Line idle - One minute until disconnect...\007\r\n";
  409.     static char *msg2 = "Disconnecting...\007\r\n";
  410.     tip = (struct tipcb *) t;
  411.   
  412.     if (! carrier_detect(tip->asy_dev) && tip->chk_modem_cd) {
  413.         close_s(tip->s); tip->s = -1;
  414.         alert(tip->proc, ENOTCONN);   /* tell tipstart() about hangup */
  415.         return;
  416.     }
  417.   
  418.     if (--tip->timeout<=0 && tip->default_timeout!=0) {
  419.         if (tip->firstwarn) {
  420.             tip->iface->lastsent = secclock();
  421.             asy_send_wait(tip->iface->dev,tip->chk_modem_cd,
  422.             qdata(msg1,strlen(msg1)));
  423.             tip->timeout=60;
  424.             start_timer(&tip->timer);
  425.             tip->firstwarn=0;
  426.         } else {
  427.             asy_send_wait(tip->iface->dev,tip->chk_modem_cd,
  428.             qdata(msg2,strlen(msg2)));
  429.             close_s(tip->s); tip->s = -1;
  430.             alert(tip->proc, EALARM);   /* tell tipstart() about timeout */
  431.         }
  432.     } else {
  433.         start_timer(&tip->timer);
  434.     }
  435. }
  436.   
  437. #endif /* TIPSERVER */
  438.   
  439. #ifdef TELNETSERVER
  440.   
  441. /* Start up Telnet server */
  442. int
  443. telnet1(argc,argv,p)
  444. int argc;
  445. char *argv[];
  446. void *p;
  447. {
  448.     int16 port;
  449.   
  450.     if(argc < 2)
  451.         port = IPPORT_TELNET;
  452.     else
  453.         port = atoi(argv[1]);
  454.   
  455. #ifdef MAILBOX
  456.     return start_tcp(port,"MBOX Server",mbx_incom,2048);
  457. #else
  458.     return start_tcp(port,"TTYLINK Server",ttylink_tcp,2048);
  459. #endif
  460. }
  461.   
  462. /* Stop telnet server */
  463. int
  464. telnet0(argc,argv,p)
  465. int argc;
  466. char *argv[];
  467. void *p;
  468. {
  469.     int16 port;
  470.   
  471.     if(argc < 2)
  472.         port = IPPORT_TELNET;
  473.     else
  474.         port = atoi(argv[1]);
  475.     return stop_tcp(port);
  476. }
  477.   
  478. #endif  /* TELNETSERVER */
  479.   
  480. #endif /* TIP | TELNET */
  481.