home *** CD-ROM | disk | FTP | other *** search
/ High Voltage Shareware / high1.zip / high1 / DIR3 / KA9Q212.ZIP / FORWARD.C < prev    next >
C/C++ Source or Header  |  1993-07-16  |  24KB  |  859 lines

  1. /* Some of the code in this file was originally based on the following file:
  2.  * gateway.c : Paul Healy, EI9GL, 900818
  3.  *
  4.  * Rewrote forwarding mechanism to use "X-Forwarded-To" paradigm instead of
  5.  * "X-BBS-To", added timer support, etc.  Anders Klemets, SM0RGV, 901009.
  6.  */
  7.  
  8. /****************************************************************************
  9. *    $Id: forward.c 1.2 93/07/16 11:44:42 ROOT_DOS Exp $
  10. *    08 May 93    1.2        GT    Fix warnings.                                    *
  11. ****************************************************************************/
  12.  
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <ctype.h>
  16. #include <time.h>
  17. #include "global.h"
  18. #include "config.h"
  19. #include "bm.h"
  20. #include "mailbox.h"
  21. #include "smtp.h"
  22. #include "cmdparse.h"
  23. #include "proc.h"
  24. #include "socket.h"
  25. #include "timer.h"
  26. #include "usock.h"
  27. #include "netuser.h"
  28. #include "ax25.h"
  29. #include "netrom.h"
  30. #include "nr4.h"
  31. #include "files.h"
  32.  
  33. #define ISPROMPT(s)    (strlen(s) > 1 && s[strlen(s)-2] == '>')
  34. static struct timer fwdtimer;
  35.  
  36. static char *findident __ARGS((char *str, int n, char *result));
  37. static void sendmsg __ARGS((struct mbx *m,int msgn));
  38. static char *mbxtime __ARGS((char *line));
  39. static int fwdinit __ARGS((struct mbx *m));
  40. static char *fwdanybbs __ARGS((struct mbx *m));
  41. static int timeok __ARGS((char *line));
  42. static void fwdtick __ARGS((void *v));
  43. static int isconnbbs __ARGS((struct mbx *m));
  44. static void startfwd __ARGS((int a,void *v1,void *v2));
  45. static int openconn __ARGS((int argc,char *argv[],void *p));
  46. static int sendmsgtobbs __ARGS((struct mbx *m,int msgn,char *dest,int bulletin));
  47. static int makecl __ARGS((struct mbx *m,int msgn,char *dest,char *line,char *subj,int bulletin));
  48. static char *grabtext __ARGS((char *from,char *to,int marker));
  49.  
  50. /***************************************************************************
  51.    findident copies the 'n'th alphanumeric sequence from 'str' to result.
  52.    It returns a ptr to result. It returns "\0" for missing identifier etc.
  53.    Uses isalnum macro to decide on alphanumeric/non-alnum status.
  54. */
  55. static char *
  56. findident(str, n, result)
  57. char *str, *result;
  58. int n;
  59. {
  60.    int count; /* current identifier */
  61.    count = 0;
  62.    *result = '\0';
  63.    while ( (count<n) && (*str!='\0') ) { /* Process alnum or non alnum seq */
  64.       while ( (*str!='\0') && (!isalnum(*str)) ) /* Get rid of ';:.@%"# etc */
  65.          str++;
  66.       if ( (str!='\0') && isalnum(*str) ) { /* this is an alnum seq */
  67.          count++;
  68.          while ( (*str!='\0') && (isalnum(*str) || (*str=='_')) )
  69.             if (count==n)
  70.                *result++ = *str++;
  71.             else str++;
  72.          if (count==n)
  73.             *result = '\0';
  74.          }
  75.       }
  76.    return result;
  77. }
  78. /**************************************************************************/
  79. static void
  80. sendmsg(m,msgn)
  81. struct mbx *m;
  82. int msgn;
  83. {
  84.     char buf[LINELEN], tb[LINELEN], *cp;
  85.     int len, rec = 0;
  86.     long cnt;
  87.     fseek(m->mfile,m->mbox[msgn].start,0);
  88.     cnt = m->mbox[msgn].size;
  89.  
  90.     /* If the data part of the message starts with "R:" the RFC-822
  91.      * headers will not be forwarded. Instead we will add an R:
  92.      * line of our own.
  93.      */
  94.     for(;;) {
  95.         if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
  96.             break;
  97.         cnt -= strlen(buf);
  98.         if(rec == 1) {    /* look at the line following Received: */
  99.              ++rec;
  100.              if((cp = strchr(buf,';')) != NULLCHAR){
  101.               strcpy(tb,cp+1);     /* get the date of receipt */
  102.               ++rec;
  103.              }
  104.         }
  105.         /* The first Received: line is the one that we have added */
  106.         if(!rec && htype(buf) == RECEIVED)
  107.              ++rec;
  108.         if(*buf == '\n') {
  109.              if(rec == 3 && cnt > 1) {
  110.               fread(buf,1,2,m->mfile);
  111.               cnt -= 2;
  112.               if(strncmp(buf,"R:",2) == 0) {
  113.                    pax25(buf,Mycall);
  114.                    if((cp = strchr(buf,'-')) != NULLCHAR)
  115.                     *cp = '\0';    /* remove SSID */
  116.                    usprintf(m->user,"R:%s @%s %s (%s)\nR:",
  117.                     mbxtime(tb),buf,Hostname,Version);
  118.                    break;
  119.               }
  120.              }
  121.              /* Start over, forwarding the RFC-822 headers */
  122.              fseek(m->mfile,m->mbox[msgn].start,0);
  123.              cnt = m->mbox[msgn].size;
  124.              rec = 0;
  125.              break;
  126.         }
  127.        }
  128.     while(rec != 3) {    /* Forward the RFC-822 headers */
  129.         if(fgets(buf,sizeof(buf),m->mfile) == NULLCHAR)
  130.             break;
  131.         cnt -= strlen(buf);
  132.         switch(htype(buf)) {
  133.         case XFORWARD: /* Do not forward the "X-Forwarded-To:" lines */
  134.         case STATUS:   /* Don't forward the "Status:" line either */
  135.              break;
  136.         default:
  137.              usputs(m->user,buf);
  138.         }
  139.         if(*buf == '\n')    /* last header line */
  140.             break;
  141.     }
  142.     do {    /* the rest of the message is treated below */
  143.         len = min((int) cnt, (int) sizeof(buf)-1);
  144.         if(fread(buf,1,len,m->mfile) != len)
  145.             break;
  146.         cnt -= len;
  147.         buf[len] = '\0';
  148.         usputs(m->user,buf);
  149.     } while(cnt);
  150. }
  151.  
  152. /* Parse a line for date and time in Arpanet format
  153.  * (Day, day Month year hh:mm:ss Zone) and return it in mailbox format
  154.  * (yymmdd/hhmmz)
  155.  */
  156. static char *
  157. mbxtime(line)
  158. char *line;
  159. {
  160.      extern char *Months[];
  161.      static char buf[12];
  162.      char *cp;
  163.      int i, day;
  164.      cp = line;
  165.      while(isspace(*cp))    /* skip initial blanks */
  166.       ++cp;
  167.      if(*cp == '\0')
  168.       return NULLCHAR;
  169.      if(strlen(cp) < 22)
  170.       return NULLCHAR;
  171.      cp += 5;
  172.      day = atoi(cp);
  173.      if(*(++cp) != ' ')
  174.       ++cp;
  175.      ++cp;
  176.      for(i=0; i < 12; ++i)
  177.       if(strnicmp(Months[i],cp,3) == 0)
  178.            break;
  179.      if(i == 12)
  180.       return NULLCHAR;
  181.      sprintf(buf,"%02d%02d%02d/%02d%02d%c",atoi(cp + 4),i,day,atoi(cp + 7),
  182.          atoi(cp + 10), (strnicmp(cp + 16,"GMT",3) &&
  183.                  strnicmp(cp + 16,"UTC",3)) ? ' ' : 'z');
  184.      return buf;
  185. }
  186.      
  187. static char *
  188. grabtext(from, to, marker)
  189. char *from, *to;
  190. int marker;
  191. {
  192.    while (*from!=marker)
  193.       *to++ = *from++;
  194.    *to = '\0';
  195.    return from+1;
  196. }
  197.  
  198. /* Makes a command line and returns -1 if the message cannot be sent. */
  199. static int
  200. makecl(m, msgn, dest, line, subj, bulletin)
  201. struct mbx *m;
  202. int msgn;        /* Message number */
  203. char *dest;        /* Destination address to use instead of To: line */
  204. char *line, *subj;    /* Buffers to keep command line and subject */
  205. int bulletin;        /* True if message is in public message area */
  206. {
  207.    char bid[LINELEN], to[LINELEN], atbbs[LINELEN], from[LINELEN],
  208.     buf[LINELEN], *cp;
  209.    if(m->mfile == NULLFILE)
  210.     return -1;
  211.    if(!bulletin && (m->mbox[msgn].status & BM_READ))
  212.     return -1;    /* the message was already read */
  213.    fseek(m->mfile,m->mbox[msgn].start,0);
  214.    *bid = *to = *atbbs = *from = '\0';
  215.    if(subj != NULLCHAR)
  216.     *subj = '\0';
  217.    m->stype = bulletin ? 'B' : 'P';    /* default to SB or SP */
  218.    while (fgets(buf,sizeof(buf),m->mfile)) {
  219.       if (buf[0] == '\n')
  220.          break; /* envelope finished */
  221.       switch (htype(buf)) {
  222.       case TO:
  223.         /* The following code tries to parse "To: " lines where the
  224.          * address looks like any of the following: "to@atbbs",
  225.          * "<to@atbbs>", "<to%atbbs@host>" and with possible spaces
  226.          * surrounding the '<>' characters.
  227.          */
  228.         if((cp = getaddress(buf,0)) == NULLCHAR)
  229.         break;
  230.         strcpy(to,cp);
  231.         if((cp = strchr(to,'%')) != NULLCHAR) { /* look for a '%' */
  232.          strcpy(atbbs,cp + 1);
  233.          *cp = '\0';    /* "to" ends at the '%' character */
  234.         }
  235.         else {    /* no '%' but maybe a '@'? */
  236.          if((cp = strchr(to,'@')) != NULLCHAR) {
  237.               strcpy(atbbs,cp + 1);
  238.               *cp = '\0';    /* "to" ends at the '@' character */
  239.          }
  240.         }
  241.         if(*atbbs != '\0')        /* either '%' or '@' found */
  242.          /* cut "atbbs" at the first '@' character */
  243.          for(cp = atbbs; *cp != '\0'; ++cp)
  244.               if(*cp == '@') {
  245.                *cp = '\0';
  246.                break;
  247.               }
  248.         /* "to" or "atbbs" should not be more than 6 characters (ALEN).
  249.          * If "to" is too long, it might simply be because the area name
  250.          * is longer than 6 characters, but it might also be because
  251.          * the address on the To: line is in an obscure format that we
  252.          * failed to parse (eg '!' character notation.)
  253.          */
  254.         if(strlen(to) > ALEN) {
  255.         /* Play safe and set "to" and "atbbs" to the area name */
  256.         strcpy(to,m->area);
  257.         strcpy(atbbs,m->area);
  258.               }
  259.         if(*atbbs == '\0')
  260.         strcpy(atbbs,to);
  261.               to[ALEN] = '\0';
  262.         /* Only if the BBS supports "hierarchical routing designators"
  263.          * is the atbbs field allowd to be longer than 6 characters and
  264.          * have dots in it.
  265.          */
  266.         if((m->sid & MBX_HIER_SID) == 0) {
  267.          atbbs[ALEN] = '\0';    /* 6 character limit */
  268.          if((cp = strchr(atbbs,'.')) != NULLCHAR)
  269.               *cp = '\0';    /* cut "atbbs" at first dot */
  270.         }
  271.             break;
  272.       case MSGID:
  273.         /* The following code distinguishes between two different types
  274.          * of Message-IDs: <abcde@callsign.bbs> and <abcde@host.domain>.
  275.          * The first type is converted to $abcde and the second to
  276.          * $abcde_host.domain. This preserves compability with BBSes.
  277.          */
  278.         if((cp = getname(buf)) == NULLCHAR)
  279.          break;
  280.         bid[0] = '$';
  281.         strcpy(&bid[1],cp);
  282.               cp = strchr(bid,'@');
  283.         /* A trailing ".bbs" indicates that the Message-ID was generated
  284.          * from a BBS style message, and not a RFC-822 message.
  285.          */
  286.         if(cp != NULLCHAR && stricmp(&bid[strlen(bid) - 4], ".bbs") == 0)
  287.         *cp = '\0';
  288.         else
  289.         *cp = '_';
  290.         bid[13] = '\0';    /* BIDs should be no longer than 13 bytes */
  291.               break;
  292.       case SUBJECT:
  293.         if(subj != NULLCHAR)
  294.               (void) grabtext(buf+9, subj, '\n');
  295.             break;
  296.       case FROM:
  297.         if((cp = getaddress(buf,0)) != NULLCHAR) {
  298.         findident(cp, 1, from);        /* cp points to from@domain */
  299.         from[ALEN] = '\0';    /* 6 character limit */
  300.         }
  301.             break;
  302.       case XFORWARD:
  303.         if((cp = getaddress(buf,0)) == NULLCHAR)
  304.          break;
  305.         if(stricmp(m->name,cp) == 0)
  306.         /* This message has already been forwarded, abort */
  307.         return -1;
  308.         break;
  309.       case BBSTYPE:
  310.         m->stype = buf[16];
  311.         break;
  312.       default:
  313.         break;
  314.       }
  315.    }
  316.    /* Check for an invalid RFC-822 header */
  317.    if((to[0] == '\0' && ((dest != NULLCHAR && *dest == '\0') ||
  318.       dest == NULLCHAR)) || from[0] == '\0')
  319.     return -1;
  320.  
  321.    if(line != NULLCHAR) {
  322.     if(dest != NULLCHAR && *dest != '\0'){
  323.          /* strip off hierarchical routing designators from the predefined
  324.           * destination address if they are not supported
  325.           */
  326.          if((m->sid & MBX_HIER_SID) == 0 && (cp = strchr(dest,'.')) !=
  327.            NULLCHAR)
  328.         *cp = '\0';
  329.          sprintf(line, "S%c %s < %s ", m->stype, dest, from);
  330.     }
  331.     else
  332.          sprintf(line, "S%c %s @ %s < %s ", m->stype, to, atbbs, from);
  333.     if(bulletin & (m->sid & MBX_SID))
  334.          strcat(line,bid);
  335.     strcat(line,"\n");
  336.    }
  337.    return 0;
  338. }
  339.  
  340. static int /* 0 = ok, -1 = problem so disc */
  341. sendmsgtobbs(m, msgn, dest, bulletin)
  342. struct mbx *m;
  343. int msgn;
  344. char *dest;        /* Optional destination address to override To: line */
  345. int bulletin;
  346. {
  347.    int result = -1;
  348.    char line[64], subj[256];
  349.    if(makecl(m, msgn, dest, line, subj, bulletin) == -1)
  350.     return 0;    /* do not forward this particular message */
  351.    tputs(line);         /* Send mail offer to bbs */
  352.    rip(line);
  353.    usflush(m->user);
  354.    if (recvline (m->user, m->line, MBXLINE) != -1 ) {
  355.       if (m->line[0] == 'O' || m->line[0] == 'o' || (m->sid & MBX_SID) == 0) {
  356.      /* Got 'OK' or any line if the bbs is unsofisticated */
  357.          tprintf("%s\n", subj);
  358.      sendmsg(m,msgn);    /* send the message */
  359.          tputs("/EX\n"); /* was 0x1a */
  360.          usflush(m->user);
  361.            /* get F> for a good deliver */
  362.            while (recvline (m->user, m->line, MBXLINE) != -1 )
  363.         if (ISPROMPT(m->line)) {
  364.             log(m->user,"MBOX bbs mail sent: %s ", line);
  365.             if(bulletin)
  366.                 m->mbox[msgn].status |= BM_FORWARDED;
  367.             else
  368.                 m->mbox[msgn].status |= BM_DELETE;
  369.             m->change = 1;
  370.             result = 0;
  371.             break;
  372.         }
  373.       }
  374.       else { /* OK response not received from bbs */
  375.        if (m->line[0] == 'N' || m->line[0] == 'n') { /* 'NO' respone */
  376.               log(m->user,"MBOX bbs mail refused: %s\n     %s",line,m->line);
  377.         /* Mark refused message as forwarded if it is a bulletin.
  378.          * The message was probably a duplicate. Non-bulletin
  379.          * messages are sent without BID, so they cannot be dected
  380.          * as duplicates. The reason why it was refused is probably
  381.          * because the address was invalid. Retry later.
  382.          */
  383.         if(bulletin){
  384.             m->mbox[msgn].status |= BM_FORWARDED;
  385.             m->change = 1;
  386.         }
  387.           }
  388.             /* should get a F> here */
  389.           while (recvline (m->user, m->line, MBXLINE) != -1 )
  390.               if (ISPROMPT(m->line)) {
  391.                   result = 0;
  392.             break;
  393.               }
  394.       }
  395.    } /* OK or NO here */
  396.    return result;
  397. }
  398.  
  399. /* This is the main entry point for reverse forwarding. It is also used
  400.  * for normal, "forward", forwarding.
  401.  */
  402. int
  403. dorevfwd(argc,argv,p)
  404. int argc;
  405. char *argv[];
  406. void *p;
  407. {
  408.     char oldarea[64], *cp;
  409.     struct mbx *m;
  410.     int i, bulletin, err = 0;
  411.     m = (struct mbx *)p;
  412.     log(m->user,"MBOX forwarding mail to: %s ", m->name);
  413.     /* indicate we are doing reverse forwarding, if we are not already
  414.      * doing normal forwarding.
  415.      */
  416.     if(m->state != MBX_FORWARD)
  417.         m->state = MBX_REVFWD;
  418.     if(fwdinit(m) != -1) {
  419.         strcpy(oldarea,m->area);
  420.         while(!err && fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  421.             if(*m->line == '-')    /* end of record reached */
  422.                 break;
  423.             rip(m->line);        /* adds extra null at end */
  424.             cp = strchr(m->line,' '); /* remove trailing blanks */
  425.             if(cp != NULLCHAR)
  426.                 *cp = '\0';
  427.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  428.                 *cp = '\0';
  429.             if(*m->line == '\0' || *m->line == '.')
  430.                 continue;
  431.             changearea(m,m->line);
  432.             bulletin = isarea(m->line);    /* public area */
  433.             /* get the optional destination field, cp will point
  434.              * at null byte if it is missing.
  435.              */
  436.             cp = &m->line[strlen(m->line)] + 1;
  437.             while(*cp != '\0' && isspace(*cp)) /* strip blanks */
  438.                  ++cp;
  439.             for(i=1; i<=m->nmsgs; i++)
  440.                 if(sendmsgtobbs(m, i, cp, bulletin) == -1) {
  441.                     err = 1;    /* abort */
  442.                     break;
  443.                 }
  444.         }
  445.         fclose(m->tfile);
  446.         m->tfile = NULLFILE;
  447.         if(*oldarea != '\0')
  448.             changearea(m,oldarea);
  449.     }
  450.     if(m->state == MBX_FORWARD)
  451.         return 0;
  452.     tprintf("*** Done\n");
  453.     if((m->sid & MBX_RLI_SID))    /* disconnect if it is a W0RLI bbs */
  454.         return domboxbye(0,NULL,m);
  455.     return 0;
  456. }
  457.  
  458. /* Read the forward file for a record for the connected BBS. If found,
  459.  * return 1 if this is the right time to forward, m->tfile is left pointing
  460.  * at the first message area to be forwarded.
  461.  */
  462. static int
  463. fwdinit(m)
  464. struct mbx *m;
  465. {
  466.     char host[80];
  467.     int start = 1;
  468.     if((m->tfile = fopen(Forwardfile,READ_TEXT)) == NULLFILE)
  469.         return -1;
  470.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  471.         if(*m->line == '\n')
  472.             continue;
  473.         /* lines starting with '-' separate the forwarding records */
  474.         if(*m->line == '-') {
  475.             start = 1;
  476.             continue;
  477.         }
  478.         if(start) {
  479.             start = 0;
  480.             /* get the name of this forwarding record */
  481.             findident(m->line,1,host);
  482.             if(stricmp(m->name,host) == 0) {
  483.                 if(!timeok(m->line))
  484.                     break;
  485.                 /* eat the connect command line */
  486.                 fgets(m->line,MBXLINE,m->tfile);
  487.                 return 0;
  488.             }
  489.         }
  490.     }
  491.     fclose(m->tfile);
  492.     m->tfile = NULLFILE;
  493.     return -1;
  494. }
  495. /* Read the forward file for a record for the connected BBS. If found,
  496.  * determine if this is the right time to forward, and return the command
  497.  * line to establish a forwarding connection. m->tfile is left pointing
  498.  * at the first message area to be forwarded.
  499.  */
  500. static char *
  501. fwdanybbs(m)
  502. struct mbx *m;
  503. {
  504.     char host[80];
  505.     int start = 1;
  506.     if(m->tfile == NULLFILE && (m->tfile = fopen(Forwardfile,READ_TEXT))
  507.                     == NULLFILE)
  508.         return NULLCHAR;
  509.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  510.         if(*m->line == '\n')
  511.             continue;
  512.         /* lines starting with '-' separate the forwarding records */
  513.         if(*m->line == '-') {
  514.             start = 1;
  515.             continue;
  516.         }
  517.         if(start) {
  518.             start = 0;
  519.             /* get the name of this forwarding record */
  520.             findident(m->line,1,host);
  521.             strcpy(m->name,host);
  522.             if(!timeok(m->line))
  523.                 continue;    /* too late or too early */
  524.             /* get the connect command line */
  525.             fgets(m->line,MBXLINE,m->tfile);
  526.             return strdup(m->line);
  527.         }
  528.     }
  529.     fclose(m->tfile);
  530.     m->tfile = NULLFILE;
  531.     return NULLCHAR;
  532. }
  533.  
  534. /* get any groups of four digits that specify the begin and ending hours of
  535.  * forwarding. Returns 1 if forwarding may take place.
  536.  */
  537. static int
  538. timeok(line)
  539. char *line;
  540. {
  541.     char hours[80], *now;
  542.     long t;
  543.     int t1, t2, pos = 2;
  544.     findident(line,pos++,hours);
  545.     if(*hours == '\0')
  546.         return 1;    /* no digits default to 0023, ie. anytime */
  547.     time(&t);
  548.     now = ctime(&t) + 11;
  549.     *(now + 2) = '\0';
  550.     while(*hours != '\0') {
  551.         t1 = (*hours - '0') * 10 + (*(hours+1) - '0');
  552.         t2 = (*(hours+2) - '0') * 10 + (*(hours+3) - '0');
  553.         if(atoi(now) >= t1 && atoi(now) <= t2)
  554.             return 1;        /* right in time */
  555.         findident(line,pos++,hours);    /* get next group if any */
  556.     }
  557.     return 0;    /* too early or too late */
  558. }
  559.  
  560. int
  561. dombtimer(argc,argv,p)
  562. int argc;
  563. char *argv[];
  564. void *p;
  565. {
  566.     if(argc < 2){
  567.         tprintf("Forwarding timer: %lu/%lu\n",
  568.         read_timer(&fwdtimer)/1000L,
  569.         dur_timer(&fwdtimer)/1000L);
  570.         return 0;
  571.     }
  572.     fwdtimer.func = (void (*)())fwdtick;/* what to call on timeout */
  573.     fwdtimer.arg = NULL;        /* dummy value */
  574.     set_timer(&fwdtimer,atol(argv[1])*1000L); /* set timer duration */
  575.     start_timer(&fwdtimer);        /* and fire it up */
  576.     return 0;
  577. }
  578.  
  579. int
  580. dombkick(argc,argv,p)
  581. int argc;
  582. char *argv[];
  583. void *p;
  584. {
  585.     fwdtick(NULL);
  586.     return 0;
  587. }
  588.  
  589. /* called when the forward timer expires or explicitly by dombkick() */
  590. static void
  591. fwdtick(v)
  592. void *v;
  593. {
  594.     char *cc, *cp;
  595.     struct mbx *m;
  596.     int i, bulletin, skip = 0;
  597.     /* restart the timer */
  598.     start_timer(&fwdtimer);
  599.     if((m = newmbx()) == NULLMBX)
  600.         return;
  601.     m->user = Curproc->output;
  602.     m->state = MBX_TRYING;
  603.     while((cc = fwdanybbs(m)) != NULLCHAR) {
  604.         if(isconnbbs(m)) /* already connected to this BBS, skip it */
  605.             skip = 1;
  606.         while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  607.             if(*m->line == '-') {    /* end of record reached */
  608.                 skip = 0;
  609.                 break;
  610.             }
  611.             if((cp = strchr(m->line,' ')) != NULLCHAR)
  612.                 *cp = '\0';
  613.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  614.                 *cp = '\0';
  615.             if(skip || *m->line == '\0' || *m->line == '.')
  616.                 continue;
  617.             rip(m->line);
  618.             changearea(m,m->line);
  619.             bulletin = isarea(m->line);    /* public area */
  620.             /* check if there are any messages in this area
  621.              * that need to be forwarded.
  622.              */
  623.             for(i=1; i<=m->nmsgs; i++)
  624.                 if(makecl(m, i, NULLCHAR, NULLCHAR, NULLCHAR,
  625.                    bulletin) == 0) {
  626.                     newproc("Mbox forwarding", 2048,
  627.                         startfwd, 0, (void *)cc,
  628.                         (void *)strdup(m->name),0);
  629.                     skip = 1;
  630.                     cc = NULLCHAR;
  631.                     break;
  632.                 }
  633.         }
  634.         free(cc);
  635.     }
  636.     exitbbs(m);
  637. }
  638.  
  639. /* returns 1 if m->name matches the name of another connected mailbox. */
  640. static int
  641. isconnbbs(m)
  642. struct mbx *m;
  643. {
  644.     int i;
  645.     for(i = 0; i < NUMMBX; ++i)
  646.         if(Mbox[i] != NULLMBX && Mbox[i] != m &&
  647.             stricmp(m->name,Mbox[i]->name) == 0)
  648.                 return 1;
  649.     return 0;
  650. }
  651.  
  652. /* possible commands on the command line in the forwarding file */
  653. static struct cmds cfwdcmds[] = {
  654.     { "tcp",        openconn,    0, 0, NULLCHAR },
  655.     { "telnet",    openconn,    0, 0, NULLCHAR },
  656. #ifdef AX25
  657.     { "ax25",        openconn,    0, 0, NULLCHAR },
  658.     { "connect",    openconn,    0, 0, NULLCHAR },
  659. #endif
  660. #ifdef NETROM
  661.     { "netrom",    openconn,    0, 0, NULLCHAR },
  662. #endif
  663.     { NULLCHAR }
  664. };
  665.  
  666. /* this function is called whenever the forwarding timer expires */
  667. static void
  668. startfwd(a,v1,v2)
  669. int a;
  670. void *v1, *v2;
  671. {
  672.     struct mbx *m;
  673.     char *cc;
  674.     cc = (char *) v1;
  675.     if((m = newmbx()) == NULLMBX) {
  676.         free(cc);
  677.         free((char *)v2);
  678.         return;
  679.     }
  680.     strcpy(m->name,(char *)v2);
  681.     free((char *)v2);
  682.     m->state = MBX_TRYING;
  683.     /* open the connection, m->user will be the new socket */
  684.     if(cmdparse(cfwdcmds,cc,(void *)m) == -1) {
  685.         free(cc);
  686.         exitbbs(m);
  687.         return;
  688.     }
  689.     free(cc);
  690.     m->state = MBX_FORWARD;
  691.     sockowner(m->user,Curproc);
  692.     close_s(Curproc->output);
  693.     close_s(Curproc->input);
  694.     /* m->user will be closed automatically when this process exits */
  695.     Curproc->output = Curproc->input = m->user;
  696.     /* We'll do our own flushing right before we read input */
  697.     setflush(m->user,-1);
  698.  
  699.     if(fwdinit(m) == -1) {
  700.         /* it is probably not the right time to forward anymore */
  701.         exitbbs(m);
  702.         return;
  703.     }
  704.     /* read the connect script. Lines starting with a dot will be sent
  705.      * to the remote BBS.
  706.      */
  707.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR)
  708.         if(*m->line == '.')
  709.             tputs(m->line + 1);
  710.         else
  711.             break;
  712.     usflush(m->user);
  713.     fclose(m->tfile);
  714.     m->tfile = NULLFILE;
  715.  
  716.     /* read the initial output from the bbs, looking for the SID */
  717.     for(;;) {
  718.         if(recvline(m->user,m->line,MBXLINE) == -1) {
  719.             exitbbs(m);
  720.             return;
  721.         }
  722.         if(ISPROMPT(m->line))
  723.             break;
  724.         if(*m->line == '[') {        /* parse the SID */
  725.             rip(m->line);
  726.             mbx_parse(m);
  727.             continue;
  728.         }
  729.     }
  730.     /* Now sync the two ends as telnet password messes them up */
  731.     if(socklen(m->user,0))        /* discard any remaining input */
  732.         recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  733.  
  734.     /* send our SID if the peer announced its SID */
  735.     if(m->sid & MBX_SID) {
  736.         tputs("[NET-H$]\n");
  737.         usflush(m->user);
  738.         for(;;) {
  739.             if(recvline(m->user,m->line,MBXLINE) == -1) {
  740.                 exitbbs(m);
  741.                 return;
  742.             }
  743.             if(ISPROMPT(m->line))
  744.                 break;
  745.         }
  746.     }
  747.     /* start the actual forwarding */
  748.     dorevfwd(0,NULL,(void *)m);
  749.     /* ask for reverse forwarding or just disconnect */
  750.     if(((m->sid & MBX_SID) && tputs("F>\n") == -1) ||
  751.        (m->sid & MBX_SID) == 0) {
  752.         exitbbs(m);
  753.         close_s(Curproc->output);
  754.         return;
  755.     }
  756.     usflush(m->user);
  757.     /* parse the commands that are are received during reverse
  758.      * forwarding.
  759.      */
  760.     while(recvline(m->user,m->line,MBXLINE) > 0) {
  761.         rip(m->line);
  762.         if(mbx_parse(m) == 2)    /* got the "*** Done" command */
  763.             break;
  764.         tputs("F>\n");
  765.         usflush(m->user);
  766.     }
  767.     exitbbs(m);
  768.     close_s(Curproc->output);
  769. }
  770.  
  771. /* open a network connection based upon information in the cc line.
  772.  * m->user is set to the socket number.
  773.  */
  774. static int
  775. openconn(argc,argv,p)
  776. int argc;
  777. char *argv[];
  778. void *p;
  779. {
  780.     struct mbx *m;
  781.     char sock[MAXSOCKSIZE]
  782. #if    0
  783.     , *np, alias[AXBUF]
  784. #endif
  785.     ;
  786.     union sp sp;
  787.     int len;
  788.     m = (struct mbx *)p;
  789.     sp.p = sock;
  790.     if(argc < 2)
  791.         return -1;
  792.     switch(*argv[0]) {
  793.     case 't':
  794.         sp.in->sin_family = AF_INET;
  795.         if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0)
  796.             return -1;
  797.         /* get the optional port number */
  798.         if(argc > 2)
  799.             sp.in->sin_port = atoi(argv[2]);
  800.         else
  801.             sp.in->sin_port = IPPORT_TELNET;
  802.         if((m->user = socket(AF_INET,SOCK_STREAM,0)) == -1)
  803.             return -1;
  804.         len = sizeof(*sp.in);
  805.         break;
  806. #ifdef AX25
  807.     case 'a':
  808.     case 'c':    /* allow 'c' for 'connect' as well */
  809.         if(argc < 3)
  810.             return -1;
  811.         sp.ax->sax_family = AF_AX25;
  812.         strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
  813.         setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
  814.         /* no digipeaters for now, use the "ax25 route add" command */
  815.         if((m->user = socket(AF_AX25,SOCK_STREAM,0)) == -1)
  816.             return -1;
  817.         len = sizeof(*sp.ax);
  818.         break;
  819. #endif /* AX25 */
  820. #ifdef NETROM
  821.     case 'n':
  822.         sp.nr->nr_family = AF_NETROM;
  823.         len = sizeof(*sp.nr);
  824.         if((m->user = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1)
  825.             return -1;
  826.         memcpy(sp.nr->nr_addr.user,Nr4user,AXALEN);
  827.         memcpy(sp.nr->nr_addr.node,Mycall,AXALEN);
  828.         bind(m->user,sp.p,len);
  829.         /* See if the requested destination could be an alias, and
  830.          * use it if it is.  Otherwise assume it is an AX.25
  831.          * address.
  832.          */
  833.         if (putalias(alias,argv[1],0) != -1 &&
  834.             (np = find_nralias(alias)) != NULLCHAR) {
  835.                 memcpy(sp.nr->nr_addr.user,np,AXALEN) ;
  836.                 memcpy(sp.nr->nr_addr.node,np,AXALEN) ;
  837.         }
  838.         else {    /* parse ax25 callsign */
  839.         /* Only the user callsign of the remote station is never
  840.          * used by NET/ROM, but it is needed for the psocket() call.
  841.          */
  842.             setcall(sp.nr->nr_addr.user,argv[1]);
  843.             setcall(sp.nr->nr_addr.node,argv[1]);
  844.         }
  845.         break;
  846. #endif /* NETROM */
  847.     default:
  848.         return -1;
  849.     }
  850.     sockmode(m->user,SOCK_ASCII);
  851.     if(connect(m->user,sp.p,len) == -1) {
  852.         log(m->user,"MBOX forward failed: %s errno %d",
  853.                 sockerr(m->user),errno);
  854.         close_s(m->user);
  855.         return -1;
  856.     }
  857.     return m->user;
  858. }
  859.