home *** CD-ROM | disk | FTP | other *** search
/ The Pier Shareware 6 / The_Pier_Shareware_Number_6_(The_Pier_Exchange)_(1995).iso / 024 / psi110g.zip / FORWARD.C < prev    next >
C/C++ Source or Header  |  1994-08-04  |  43KB  |  1,288 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.  /* Mods by G1EMM and WG7J */
  8.  /* Mod to R: line to MSYS-style with bid by N2LSS: define MSYS_RLINE */
  9. #include <ctype.h>
  10. #include <time.h>
  11. #include "global.h"
  12. #ifdef MBFWD
  13. #include "bm.h"
  14. #include "mailbox.h"
  15. #include "smtp.h"
  16. #include "cmdparse.h"
  17. #include "proc.h"
  18. #include "socket.h"
  19. #include "timer.h"
  20. #include "usock.h"
  21. #include "netuser.h"
  22. #include "ax25.h"
  23. #include "netrom.h"
  24. #include "nr4.h"
  25. #include "files.h"
  26. #include "index.h"
  27.   
  28. extern int MbForwarded;
  29. extern char MboxId[];
  30. #define ISPROMPT(s) (strlen(s) > 1 && s[strlen(s)-2] == '>')
  31. static struct timer fwdtimer;
  32. static struct proc *FwdProc;
  33.   
  34. static char *findident __ARGS((char *str, int n, char *result));
  35. static void sendmsg __ARGS((struct fwd *f,int msgn));
  36. static char *mbxtime __ARGS((time_t date));
  37. static int fwdinit __ARGS((struct mbx *m));
  38. static char *fwdanybbs __ARGS((struct mbx *m,int *poll));
  39. static int timeok __ARGS((char *line));
  40. static void fwdtick __ARGS((void *v));
  41. static void fwdproc __ARGS((void));
  42. static int isconnbbs __ARGS((struct mbx *m));
  43. static void startfwd __ARGS((int a,void *v1,void *v2));
  44. static int openconn __ARGS((int argc,char *argv[],void *p));
  45. static int sendmsgtobbs __ARGS((struct fwd *f,int msgn,char *dest));
  46. static int makecl __ARGS((struct fwd *f,int msgn,char *dest,char *line,char **subj,int *bul));
  47. static char *grabtext __ARGS((char *from,char *to,int marker));
  48.   
  49. /***************************************************************************
  50.    findident copies the 'n'th alphanumeric sequence from 'str' to result.
  51.    It returns a ptr to result. It returns "\0" for missing identifier etc.
  52.    Uses isalnum macro to decide on alphanumeric/non-alnum status.
  53. */
  54. static char *
  55. findident(str, n, result)
  56. char *str, *result;
  57. int n;
  58. {
  59.     int count; /* current identifier */
  60.     count = 0;
  61.     *result = '\0';
  62.     while ( (count<n) && (*str!='\0') ) { /* Process alnum or non alnum seq */
  63.         while ( (*str!='\0') && (!isalnum(*str)) ) /* Get rid of ';:.@%"# etc */
  64.             str++;
  65.         if ( (*str!='\0') && isalnum(*str) ) { /* this is an alnum seq */
  66.             count++;
  67.             while ( (*str!='\0') && (isalnum(*str) || (*str=='_')) )
  68.                 if (count==n)
  69.                     *result++ = *str++;
  70.                 else str++;
  71.             if (count==n)
  72.                 *result = '\0';
  73.         }
  74.     }
  75.     return result;
  76. }
  77. /**************************************************************************/
  78. /* sendmsg() modified to send the R: line always.
  79.  * also added some additional strings like qth and zipcode etc. to R: line.
  80.  * Original SMTP headers get forwarded optionally.
  81.  * 920114 - WG7J
  82.  */
  83. extern char *Mbhaddress;
  84. extern char *Mbfwdinfo;
  85. extern char *Mbqth;
  86. extern char *Mbzip;
  87. extern int Mbsmtptoo;
  88. extern int UtcOffset;
  89. extern int Mbheader;
  90. extern char shortversion[];
  91.   
  92. static void
  93. sendmsg(f,msgn)
  94. struct fwd *f;
  95. int msgn;
  96. {
  97.     struct mbx *m = f->m;
  98.     int i,rheader = 0;
  99.     long start;
  100.     char buf[LINELEN], tb[LINELEN], *cp;
  101.   
  102.     /* If the data part of the message starts with "R:" the RFC-822
  103.      * headers will not be forwarded. Instead we will add an R:
  104.      * line of our own.
  105.      */
  106.     /* ALWAYS forward with "R:" line - WG7J */
  107.     /* Now conditional upon Mbheader - 921201, WG7J */
  108.     if(Mbheader) {
  109.         /* First send recv. date/time and bbs address */
  110.         usprintf(m->user,"R:%s",mbxtime(f->ind.mydate));
  111. #if defined(MSYS_RLINE)
  112.         /* Include the message number */
  113.         usprintf(m->user," %lu", f->ind.msgid);
  114. #endif
  115.         /* If exists, send H-address */
  116.         if(Mbhaddress != NULLCHAR)
  117. #if defined(MSYS_RLINE)
  118.             usprintf(m->user,"@%s",Mbhaddress);
  119. #else
  120.             usprintf(m->user," @:%s",Mbhaddress);
  121. #endif
  122.         /* location, if any */
  123.         if(Mbqth != NULLCHAR)
  124.             usprintf(m->user," [%s]",Mbqth);
  125.         /*if there is info, put it next */
  126.         if(Mbfwdinfo != NULLCHAR)
  127.             usprintf(m->user," %s",Mbfwdinfo);
  128. #if !defined(MSYS_RLINE)
  129.         /* number of the message */
  130.         usprintf(m->user," #:%lu",f->ind.msgid);
  131. #endif
  132.         /* The BID, is any */
  133.         if(f->bid[0] != '\0')
  134.             usprintf(m->user," $:%s",&f->bid[1]);
  135.         /* zip code of the bbs */
  136.         if(Mbzip != NULLCHAR)
  137.             usprintf(m->user," Z:%s",Mbzip);
  138.         usputc(m->user,'\n');
  139.     }
  140.   
  141.     /* Open the mailbox file */
  142.     sprintf(buf,"%s/%s.txt",Mailspool,m->area);
  143.     if((m->mfile = fopen(buf,"r")) == NULL) {
  144.         usputs(m->user,"Can not find message body!\n");
  145. #ifdef MAILERROR
  146.         mail_error("MBX FWD %s: Can not find mailfile for msg %d in %s", \
  147.         m->name,msgn,buf);
  148. #endif
  149.         return;
  150.     }
  151.   
  152.     /* point to start of this message in file */
  153.     start = m->mbox[msgn].start;
  154.     fseek(m->mfile,start,SEEK_SET);
  155.   
  156.     /* If we also send the smtp headers, now see if the message
  157.      * has any R: headers. If so, send them first.
  158.      */
  159.     if(Mbsmtptoo) {
  160.         while(fgets(buf,sizeof(buf),m->mfile) != NULL) {
  161.             if(*buf == '\n')
  162.                 break;          /* End of smtp headers */
  163.         }
  164.         if(ferror(m->mfile))
  165.             return;
  166.         /* Found start of msg text, check for R: lines */
  167.         while(fgets(buf,sizeof(buf),m->mfile) != NULL &&
  168.         !strncmp(buf,"R:",2)) {
  169.             rheader = 1;
  170.             usputs(m->user,buf);
  171.         }
  172.         /* again point to start of this message in file */
  173.         fseek(m->mfile,start,SEEK_SET);
  174.     }
  175.   
  176.     /* Go past the SMTP headers to the data of the message.
  177.      * Check if we need to forward the SMTP headers!
  178.      * 920114 - WG7J
  179.      */
  180.     if(Mbsmtptoo && (rheader || Mbheader))
  181.         usputc(m->user,'\n');
  182.     while(fgets(buf,sizeof(buf),m->mfile) != NULL &&
  183.     *buf != '\n') {
  184.         if(Mbsmtptoo) {
  185.             /* YES, forward SMTP headers TOO !*/
  186.             switch(htype(buf)) {
  187.                 case XFORWARD: /* Do not forward the "X-Forwarded-To:" lines */
  188.                 case STATUS:   /* Don't forward the "Status:" line either */
  189.                 case BBSTYPE:
  190.                 case SUBJECT:
  191.                 case TO:
  192.                 case DATE:
  193.                     break;
  194.                 case FROM:
  195.                 /* Don't forward the "From: " line either.
  196.                  * make it ">From: "
  197.                  */
  198.                     usputc(m->user,'>');
  199.                 /*note fall-through*/
  200.                 default:
  201.                     if(!strncmp(buf,"From ",5))
  202.                         usputc(m->user,'>');
  203.                     usputs(m->user,buf);
  204.             }
  205.         }
  206.     }
  207.   
  208.     /* Now we are at the start of message text.
  209.      * the rest of the message is treated below.
  210.      * Remember that R: lines have already been sent,
  211.      * if we sent smtp headers !
  212.      */
  213.     i = 1;
  214.   
  215.     while(fgets(buf,sizeof(buf),m->mfile) != NULL &&
  216.     strncmp(buf,"From ",5)) {
  217.         if(i) {
  218.             if(!strncmp(buf,"R:",2)) {
  219.                 if(Mbsmtptoo) continue;
  220.             } else {
  221.                 i = 0;
  222.                 if(*buf != '\n')
  223.                     /* Ensure body is separated from R: line */
  224.                     usputc(m->user,'\n');
  225.             }
  226.         }
  227.         usputs(m->user,buf);
  228.     }
  229.     fclose(m->mfile);
  230.     m->mfile = NULL;
  231.     return;
  232. }
  233.   
  234. /* Parse a line for date and time in Arpanet format
  235.  * (Day, day Month year hh:mm:ss Zone) and return it in mailbox format
  236.  * (yymmdd/hhmmz)
  237.  */
  238. static char *
  239. mbxtime(time_t date) {
  240.     time_t cdate;   /* Date corrected for timezone offset */
  241.     extern char *Months[];
  242.     static char buf[13];
  243.     char *cp;
  244.     int month;
  245.   
  246.     cdate = date;
  247.     /* adjust for GMT/UTC time - WG7J */
  248.     if(UtcOffset != 0)
  249.         cdate -= UtcOffset*3600L;
  250.     cp = ctime(&cdate);
  251.   
  252.     /* Check month */
  253.     for(month=0; month < 12; ++month)
  254.         if(strnicmp(Months[month],cp+4,3) == 0)
  255.             break;
  256.     if(month == 12)
  257.         return NULL;
  258.     month++;
  259.   
  260.     sprintf(buf,"%2.2s%02d%2.2s/%2.2s%2.2sz",cp+22,month,cp+8,cp+11,cp+14);
  261.     return buf;
  262. }
  263.   
  264. static char *
  265. grabtext(from, to, marker)
  266. char *from, *to;
  267. int marker;
  268. {
  269.     while (*from!=marker)
  270.         *to++ = *from++;
  271.     *to = '\0';
  272.     return from+1;
  273. }
  274.   
  275. /* Makes a command line and returns -1 if the message cannot be sent */
  276. static int
  277. makecl(f, msgn, dest, line, subj, bul)
  278. struct fwd *f;
  279. int msgn;               /* Message number */
  280. char *dest;             /* Destination address to use instead of To: line */
  281. char *line, **subj;      /* Buffers to keep command line and subject */
  282. int *bul;       /* True if message is in public message area */
  283. {
  284.     struct mbx *m = f->m;
  285.     struct let *cmsg = &m->mbox[msgn];
  286.     struct mailindex *ind = &f->ind;
  287.     struct fwdbbs *bbs;
  288.     int bulletin = *bul;
  289.     int foundbid = 0;
  290.     char *cp;
  291.     char *to,*atbbs;
  292.     char bid[60];
  293.   
  294.     if((cmsg->status & BM_HOLD) || (!bulletin && (cmsg->status & BM_READ)))
  295.         return -1;      /* the message was on hold or already read */
  296.   
  297.     /* The following code tries to parse the "To: " line where the
  298.      * address looks like "to", "to@atbbs", or "to%atbbs@host"
  299.      */
  300.     to = ind->to;
  301.     if((atbbs = strchr(to,'%')) != NULL) {
  302.         *atbbs++ = '\0';    /* "to" ends at the '%' character */
  303.         /* Now get rid of the following '@host' field */
  304.         if((cp = strchr(atbbs,'@')) != NULL)
  305.             *cp = '\0';
  306.     }
  307.     if((cp = strchr(to,'@')) != NULL) {
  308.         *cp = '\0';   /* "to" or "atbbs" ends at the '@' character */
  309.         if(!atbbs)
  310.             atbbs = cp + 1;
  311.     }
  312.     /*
  313.     if(!atbbs )
  314.         atbbs = to;
  315.      */
  316.   
  317.     /* "to" or "atbbs" should not be more than 6 characters (ALEN).
  318.      * If "to" is too long, it might simply be because the area name
  319.      * is longer than 6 characters, but it might also be because
  320.      * the address on the To: line is in an obscure format that we
  321.      * failed to parse (eg '!' character notation.)
  322.      */
  323.     if(strlen(to) > ALEN) {
  324.         /* Play safe and set "to" and "atbbs" to the area name */
  325.         to = m->area;
  326.         atbbs = m->area;
  327.     }
  328.     to=strdup(to);
  329.     atbbs=strdup(atbbs);
  330.     if(strlen(to) > ALEN)
  331.         to[ALEN] = '\0';    /* Maximum length is 6 */
  332.   
  333.     /* Only if the BBS supports "hierarchical routing designators"
  334.      * is the atbbs field allowd to be longer than 6 characters and
  335.      * have dots in it.
  336.      */
  337.     if((m->sid & MBX_HIER_SID) == 0) {
  338.         if(atbbs && strlen(atbbs) > ALEN)
  339.             atbbs[ALEN] = '\0';    /* 6 character limit */
  340.         if(atbbs && (cp = strchr(atbbs,'.')) != NULLCHAR)
  341.             *cp = '\0';       /* cut "atbbs" at first dot */
  342.     }
  343.   
  344.     /* The following code distinguishes between three different types
  345.      * of Message-IDs: abcde@callsign.bbs, abcde@otherhost.domain,
  346.      * and abcde@ourhost.domain.
  347.      * The first type is converted to $abcde and the second to
  348.      * $abcde_host.domain. The last to $abcde_first-part-of-H-address.
  349.      * This preserves compability with BBSes.
  350.      */
  351.     f->bid[0] = '\0';
  352.     strncpy(&bid[1],ind->messageid,sizeof(bid) - 1);
  353.     bid[sizeof(bid)-1] = '\0';
  354.     /* Is there a @hostname part ? */
  355.     if((cp = strchr(&bid[1],'@')) != NULL) {
  356.         bid[0] = '$';
  357.         if(stricmp(cp+strlen(cp) - 4, ".bbs") == 0) {
  358.             /*retain the bid given by user*/
  359.             *cp = '\0';
  360.             foundbid = 1; /* Indicate we found a 'real' bid - WG7J */
  361.         } else {
  362.             *cp++ = '_';
  363.             if(Mbhaddress && !strcmp(cp,Hostname)) {
  364.                 /* This is one of our messages!
  365.                  * Take the _host part from the H-address,
  366.                  * to form our bid - WG7J 930205
  367.                  */
  368.                 strcpy(cp,Mbhaddress);
  369.             }
  370.             /* This is now either $msg#@my_h-address, or $msg#_host.domain
  371.              * make this BID style '$msg#_host'
  372.              * ie. cut off after first period - WG7J
  373.              */
  374.             if((cp = strchr(cp,'.')) != NULL)
  375.                 *cp = '\0';
  376.   
  377.         }
  378.         bid[13] = '\0';     /* BIDs should be no longer than 13 bytes */
  379.         strcpy(f->bid,bid);
  380.     }
  381.   
  382.     if(ind->from) {
  383.         if((cp=strchr(ind->from,'@')) != NULL)
  384.             *cp = '\0';
  385.         if((cp=strchr(ind->from,'%')) != NULL)
  386.             *cp = '\0';
  387.         if(strstr(ind->from,m->name) != NULL) {
  388.             /* This message came from the connected BBS so Abort */
  389.             free(to);
  390.             free(atbbs);
  391.             return -1;
  392.         }
  393.         if(strlen(ind->from) > ALEN)
  394.             ind->from[ALEN] = '\0';      /* 6 character limit */
  395.     }
  396.   
  397.     if((*to == '\0' && ((dest != NULL && *dest == '\0') ||
  398.     dest == NULL)) || *ind->from == '\0') {
  399.         free(to);
  400.         free(atbbs);
  401.         return -1;
  402.     }
  403.   
  404.     if(line != NULL) {
  405.         if(dest != NULL && *dest != '\0'){
  406.             /* strip off hierarchical routing designators from the predefined
  407.              * destination address if they are not supported
  408.              */
  409.             if((m->sid & MBX_HIER_SID) == 0 && (cp = strchr(dest,'.')) !=
  410.                 NULLCHAR)
  411.                 *cp = '\0';
  412.             sprintf(line, "S%c %s < %s ", ind->type, dest, ind->from);
  413.         } else {
  414.             if(atbbs)
  415.                 sprintf(line, "S%c %s @ %s < %s ", ind->type, to, atbbs, ind->from);
  416.             else
  417.                 sprintf(line, "S%c %s < %s ", ind->type, to, ind->from);
  418.         }
  419.         /* Add the bid to bulletins,
  420.          * AND ALSO to anything that came in with a bid !
  421.          * Takes care off duplicate 'SP SYSOP@xxx $BID' problems.
  422.          * ALSO add it to ALL messages if the remote system supports MID's - WG7J
  423.          */
  424.         if((m->sid & MBX_MID) || ((bulletin || foundbid) & (m->sid & MBX_SID)))
  425.             strcat(line,f->bid);
  426.         strcat(line,"\n");
  427.     }
  428.     if(subj)
  429.         *subj = strdup(ind->subject);
  430.     free(to);
  431.     free(atbbs);
  432.     return 0;
  433. }
  434.   
  435. static int /* 0 = ok, -1 = problem so disc */
  436. sendmsgtobbs(f, msgn, dest)
  437. struct fwd *f;
  438. int msgn;
  439. char *dest;             /* Optional destination address to override To: line */
  440. {
  441.     int result = -1;
  442.     struct mbx *m = f->m;
  443.     struct fwdbbs *bbs;
  444.     int bulletin = (m->areatype == AREA);
  445.     char *subj = NULL;
  446.     char line[64];
  447.   
  448.     /* Check x-forwarded-to fields */
  449.     for(bbs=f->ind.bbslist;bbs;bbs=bbs->next)
  450.         if(!stricmp(bbs->call,m->name))
  451.             return 0;
  452.   
  453.     if(makecl(f, msgn, dest, line, &subj, &bulletin) == -1)
  454.         return 0;       /* do not forward this particular message */
  455.   
  456.     tputs(line);          /* Send mail offer to bbs */
  457. /*    rip(line); */
  458.     usflush(m->user);
  459.     if(recvline(m->user, m->line, MBXLINE) != -1 ) {
  460.         if(m->line[0] == 'O' || m->line[0] == 'o' || (m->sid & MBX_SID) == 0) {
  461.             /* Got 'OK' or any line if the bbs is unsofisticated */
  462.             tprintf("%s\n", subj);
  463.             sendmsg(f,msgn);   /* send the message */
  464. #ifdef FWDCTLZ
  465.             /* Some bbs code doesn't like /EX too well... */
  466.             tputs("\032\n");
  467. #else
  468.             tputs("/EX\n"); /* was 0x1a */
  469. #endif
  470.             usflush(m->user);
  471.             /* get F> for a good deliver */
  472.             while (recvline (m->user, m->line, MBXLINE) != -1 ) {
  473.                 if(ISPROMPT(m->line)) {
  474.                     rip(line);  /* N5KNX: now drop NL for nicer log entry */
  475.                     log(m->user,"MBOX bbs mail sent: %s ", line);
  476.                     if(m->areatype == AREA)
  477.                         m->mbox[msgn].status |= BM_FORWARDED;
  478.                     else
  479.                         m->mbox[msgn].status |= BM_DELETE;
  480.                     m->change = 1;
  481.                     result = 0;
  482.                     MbForwarded++;
  483.                     break;
  484.                 }
  485.             }
  486.         } else { /* OK response not received from bbs */
  487.             if (m->line[0] == 'N' || m->line[0] == 'n') { /* 'NO' respone */
  488.                 rip(m->line);   /* N5KNX: nicer log entry */
  489.                 log(m->user,"MBOX bbs mail refused: %s\t%s",line,m->line);
  490.                 /* Mark refused message as forwarded if it is a bulletin.
  491.                  * The message was probably a duplicate. Non-bulletin
  492.                  * messages are sent without BID, so they cannot be dected
  493.                  * as duplicates. The reason why it was refused is probably
  494.                  * because the address was invalid. Retry later.
  495.                  *
  496.                  * After lots of complaining, this behaviour is changed:
  497.                  * ALL messages that get the NO reply are marked
  498.                  * as forwarded ! - WG7J 930124
  499.                  */
  500.                 if(m->areatype == AREA)
  501.                     m->mbox[msgn].status |= BM_FORWARDED;
  502.                 else
  503.                     m->mbox[msgn].status |= BM_DELETE;
  504.                 m->change = 1;
  505.                 /* Count this as forwarded ! - WG7J */
  506.                 MbForwarded++;
  507.             }
  508.             /* should get a F> here */
  509.             while (recvline (m->user, m->line, MBXLINE) != -1 ) {
  510.                 if (ISPROMPT(m->line)) {
  511.                     result = 0;
  512.                     break;
  513.                 }
  514.             }
  515.         }
  516.     } /* OK or NO here */
  517.     free(subj);
  518.     return result;
  519. }
  520.   
  521. /* This is the main entry point for reverse forwarding. It is also used
  522.  * for normal, "forward", forwarding.
  523.  */
  524. int
  525. dorevfwd(argc,argv,p)
  526. int argc;
  527. char *argv[];
  528. void *p;
  529. {
  530.     char *cp, *dp;
  531.     int i, idx, err = 0;
  532.     struct fwd f;
  533.     struct indexhdr hdr;
  534.     struct fwdbbs *bbs;
  535.     char fn[64];
  536.     char oldarea[64];
  537.   
  538.     long before,after;
  539.   
  540.     f.m = (struct mbx *)p;
  541.     memset(&f.ind,0,sizeof(struct mailindex));
  542.   
  543.     log(f.m->user,"MBOX forwarding mail to: %s ", f.m->name);
  544.     /* indicate we are doing reverse forwarding, if we are not already
  545.      * doing normal forwarding.
  546.      */
  547.     if(f.m->state != MBX_FORWARD)
  548.         f.m->state = MBX_REVFWD;
  549.   
  550.     if(fwdinit(f.m) != -1) {
  551.         strcpy(oldarea,f.m->area);
  552.         while(!err && fgets(f.m->line,MBXLINE,f.m->tfile) != NULLCHAR) {
  553.             pwait(NULL);
  554.             if(*f.m->line == '-')     /* end of record reached */
  555.                 break;
  556.             cp = f.m->line;
  557.             rip(cp);           /* adds extra null at end */
  558.             /* skip spaces */
  559.             while(*cp && (*cp == ' ' || *cp == '\t'))
  560.                 cp++;
  561.             if(*cp == '\0' || *cp == '.' || *cp == '#' || *cp == '+' || *cp == '&' || *cp == '@')
  562.                 continue;    /* ignore empty or connect-script lines */
  563.             /* find end of area name, and beginning of optional destination string */
  564.             for (dp=cp; *dp && *dp != ' ' && *dp != '\t' && *dp != '\n'; dp++) ;
  565.             if (*dp) *dp++ = '\0';
  566.             changearea(f.m,cp);
  567.             /* Now create the index filename */
  568.             sprintf(fn,"%s/%s.ind",Mailspool,cp);
  569.   
  570.             /* strip leading blanks from dest */
  571.             cp=dp;
  572.             while(*cp && (*cp == ' ' || *cp == '\t'))
  573.                 cp++;
  574.             /* find end of optional destination */
  575.             for (dp=cp; *dp && *dp != ' ' && *dp != '\t' && *dp != '\n'; dp++) ;
  576.             if (*dp) *dp = '\0';
  577.  
  578.             cp = strdup(cp);
  579.             /* open the index file */
  580.             if((idx=open(fn,READBINARY)) != -1) {
  581.                 /* check if there are any messages in this area
  582.                  * that need to be forwarded.
  583.                  */
  584.                 if(read_header(idx,&hdr) != -1) {
  585.                     for(i=1; i<=f.m->nmsgs; i++) {
  586.                         pwait(NULL);
  587.                         if(read_index(idx,&f.ind) == -1) {
  588.                             err = 1;
  589.                             break;
  590.                         }
  591.                         if(sendmsgtobbs(&f, i, cp) == -1) {
  592.                             err = 1;        /* abort */
  593.                             break;
  594.                         }
  595.                         /* Done with this index, clear it */
  596.                         default_index(f.m->area,&f.ind);
  597.                         scanmail(f.m);
  598.                     }
  599.                 }
  600.                 close(idx);
  601.                 idx = 0;
  602.             }
  603.             if(f.m->mfile) {
  604.                 fclose(f.m->mfile);
  605.                 f.m->mfile = NULL;
  606.             }
  607.             free(cp);
  608.         }
  609.         fclose(f.m->tfile);
  610.         f.m->tfile = NULLFILE;
  611.         if(*oldarea != '\0')
  612.             changearea(f.m,oldarea);
  613.     }
  614.     default_index("",&f.ind);
  615.     if(f.m->state == MBX_FORWARD)
  616.         return 0;
  617.     tputs("*** Done\n");
  618. #ifdef notdef
  619.     /* Can't do this with polling anymore */
  620.     if((f.m->sid & MBX_RLI_SID))      /* disconnect if it is a W0RLI bbs */
  621.         return domboxbye(0,NULL,f.m);
  622. #endif
  623.     return 0;
  624. }
  625.   
  626. /* Read the forward file for a record for the connected BBS. If found,
  627.  * return 1 if this is the right time to forward, m->tfile is left pointing
  628.  * at the first message area to be forwarded.
  629.  */
  630. static int
  631. fwdinit(m)
  632. struct mbx *m;
  633. {
  634.     char host[80];
  635.     int start = 1;
  636.   
  637.     if((m->tfile = fopen(Forwardfile,READ_TEXT)) == NULLFILE)
  638.         return -1;
  639.   
  640.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  641.         if(*m->line == '\n')
  642.             continue;
  643.         /* lines starting with '-' separate the forwarding records */
  644.         if(*m->line == '-') {
  645.             start = 1;
  646.             continue;
  647.         }
  648.         if(start) {
  649.             start = 0;
  650.             /* get the name of this forwarding record */
  651.             findident(m->line,1,host);
  652.             if(stricmp(m->name,host) == 0) {
  653.                 if(!timeok(m->line))
  654.                     break;
  655.                 /* eat the connect command line */
  656.                 fgets(m->line,MBXLINE,m->tfile);
  657.                 return 0;
  658.             }
  659.         }
  660.     }
  661.     fclose(m->tfile);
  662.     m->tfile = NULLFILE;
  663.     return -1;
  664. }
  665. /* Read the forward file for a record for the connected BBS. If found,
  666.  * determine if this is the right time to forward, and return the command
  667.  * line to establish a forwarding connection. m->tfile is left pointing
  668.  * at the first message area to be forwarded.
  669.  */
  670. static char *
  671. fwdanybbs(m,poll)
  672. struct mbx *m;
  673. int *poll;
  674. {
  675.     char host[80];
  676.     int start = 1,i;
  677.   
  678.     if(m->tfile == NULLFILE && (m->tfile = fopen(Forwardfile,READ_TEXT))
  679.         == NULLFILE)
  680.         return NULLCHAR;
  681.     *poll = 0;  /* Default to no polling */
  682.     while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  683.         if(*m->line == '\n')
  684.             continue;
  685.         /* lines starting with '-' separate the forwarding records */
  686.         if(*m->line == '-') {
  687.             start = 1;
  688.             continue;
  689.         }
  690.         if(start) {
  691.             start = 0;
  692.             /* get the name of this forwarding record */
  693.             findident(m->line,1,host);
  694.             strcpy(m->name,host);
  695.             if(!timeok(m->line))
  696.                 continue;       /* too late or too early */
  697.             /* Check for polling - WG7J */
  698.             i=2;
  699.             findident(m->line,2,host);
  700.             while(*host) {
  701.                 if(*host == 'P' || *host == 'p') {
  702.                     *poll = 1;
  703.                     break;
  704.                 }
  705.                 i++;
  706.                 findident(m->line,i,host);
  707.             }
  708.             /* get the connect command line */
  709.             fgets(m->line,MBXLINE,m->tfile);
  710.             return strdup(m->line);
  711.         }
  712.     }
  713.     fclose(m->tfile);
  714.     m->tfile = NULLFILE;
  715.     return NULLCHAR;
  716. }
  717.   
  718. /* get any groups of four digits that specify the begin and ending hours of
  719.  * forwarding. Returns 1 if forwarding may take place.
  720.  */
  721. static int
  722. timeok(line)
  723. char *line;
  724. {
  725.     char hours[80], *now;
  726.     long t;
  727.     int t1, t2, pos = 2;
  728.     findident(line,pos++,hours);
  729.     if(*hours == '\0' || *hours == 'P' || *hours == 'p')
  730.         return 1;       /* no digits default to 0023, ie. anytime */
  731.     time(&t);
  732.     now = ctime(&t) + 11;
  733.     *(now + 2) = '\0';
  734.     while(*hours != '\0') {
  735.         t1 = (*hours - '0') * 10 + (*(hours+1) - '0');
  736.         t2 = (*(hours+2) - '0') * 10 + (*(hours+3) - '0');
  737.         if(atoi(now) >= t1 && atoi(now) <= t2)
  738.             return 1;               /* right in time */
  739.         findident(line,pos++,hours);    /* get next group if any */
  740.         if(*hours == 'P' || *hours == 'p')
  741.             return 0;
  742.     }
  743.     return 0;       /* too early or too late */
  744. }
  745.   
  746. int
  747. dombtimer(argc,argv,p)
  748. int argc;
  749. char *argv[];
  750. void *p;
  751. {
  752.     if(argc < 2){
  753.         tprintf("Forwarding timer: %lu/%lu server %s.\n",
  754.         read_timer(&fwdtimer)/1000L,
  755.         dur_timer(&fwdtimer)/1000L,
  756.         FwdProc != NULLPROC ? "started":"stopped");
  757.         return 0;
  758.     }
  759.     fwdtimer.func = (void (*)__ARGS((void *)))fwdtick;/* what to call on timeout */
  760.     fwdtimer.arg = NULL;            /* dummy value */
  761.     set_timer(&fwdtimer,atol(argv[1])*1000L); /* set timer duration */
  762.     pwait(NULL);
  763.     if (FwdProc != NULLPROC)    /* if someone is listening */
  764.         start_timer(&fwdtimer);     /* fire it up */
  765.     else
  766.         if(dur_timer(&fwdtimer) != 0)
  767.             tputs("Warning: forward server not started.\n");
  768.     return 0;
  769. }
  770.   
  771. int
  772. dombkick(argc,argv,p)
  773. int argc;
  774. char *argv[];
  775. void *p;
  776. {
  777.     if (FwdProc == NULLPROC) {
  778.         tputs("Forward server not started\n");
  779.         return 1;
  780.     }
  781.     psignal(&fwdtimer,0);
  782.     return 0;
  783. }
  784.   
  785. /* called when the forward timer expires or explicitly by dombkick() */
  786. /* MDMII: fwdproc is the old fwdtick.   But, since it can call pause, which is
  787.  * very very bad for timer functions :-( this has been converted to a server.
  788.  */
  789. static void
  790. fwdtick(v)
  791. void *v;
  792. {
  793.     psignal(&fwdtimer,0);           /* awake the forwarder */
  794.     start_timer(&fwdtimer);     /* and restart the timer */
  795. }
  796.   
  797. /* the main process for the mailbox forwarder */
  798. int
  799. fwdstart(argc,argv,p)
  800. int argc;
  801. char *argv[];
  802. void *p;
  803. {
  804.     if (FwdProc != NULLPROC)
  805.         return 0;       /* already started */
  806.   
  807.     FwdProc = Curproc;      /* set our flag */
  808.   
  809.     psignal(Curproc,0);     /* don't wait on us */
  810.   
  811.     start_timer(&fwdtimer);     /* start timer (ignored if 0) */
  812.   
  813.     for (;!pwait(&fwdtimer);)   /* wait for someone to tell us to try */
  814.         if (availmem() > Memthresh)
  815.             fwdproc();
  816.         else if(Mtrace)
  817.             tputs("fwd: forwarding skipped due to low memory\n");
  818.   
  819.     FwdProc = NULLPROC;     /* we are exiting */
  820.     return 0;           /* alerted from somewhere */
  821. }
  822.   
  823. /* (attempt to) kill the forwarder process */
  824. int
  825. fwd0(argc,argv,p)
  826. int argc;
  827. char *argv[];
  828. void *p;
  829. {
  830.     int i, max;         /* max attempts */
  831.   
  832.     stop_timer(&fwdtimer);      /* no more timer awakes */
  833.     max = 1;            /* Maximum attempts */
  834.     if (argc > 2)
  835.         setint(&max,NULLCHAR,argc,argv);
  836.   
  837.     for(i=0;i<max && FwdProc != NULLPROC;i++) {
  838.         alert(FwdProc,1);   /* signal regardless of location */
  839.         pwait(NULL);        /* let it see the alert */
  840.     }
  841.   
  842.     stop_timer(&fwdtimer);      /* in case timer tick restarted it */
  843.     return 0;
  844. }
  845.   
  846. /* MDMII: This is the old fwdtick function */
  847. static void
  848. fwdproc(void)
  849. {
  850.     char *cc, *cp, *fp;
  851.     struct mbx *m;
  852.     struct fwdbbs *bbs;
  853.     struct indexhdr hdr;
  854.     struct mailindex ind;
  855.     int i, idx, bulletin, poll,skip = 0;
  856.     char fn[FILE_PATH_SIZE];
  857.   
  858.     if(Mtrace)
  859.         tputs("mbox: fwd started\n");
  860.     if((m = newmbx()) == NULLMBX){
  861.         if(Mtrace)
  862.             tputs("fwd: no new mbox\n");
  863.         return;
  864.     }
  865.     m->user = Curproc->output;
  866.     m->state = MBX_TRYING;
  867.     memset(&ind,0,sizeof(struct mailindex));
  868.     while((cc = fwdanybbs(m,&poll)) != NULLCHAR) {
  869.         if(isconnbbs(m)) { /* already connected to this BBS, skip it */
  870.             skip = 1;
  871.             if(Mtrace)
  872.                 tprintf("fwd: %s already connected\n",m->name);
  873.         }
  874.         /* If we poll, there is no need to check message area, since this
  875.          * is also done later. It will speed things up here - WG7J
  876.          */
  877.         if(!skip && poll) {
  878.             if(Mtrace)
  879.                 tprintf("fwd: polling %s\n",m->name);
  880.             newproc("Mbox forwarding", 2048,startfwd, 0, (void *)cc,
  881.             (void *)strdup(m->name),0);
  882.             cc = NULLCHAR;
  883.             skip = 1;
  884.         }
  885.         if(!skip && Mtrace)
  886.             tprintf("fwd: %s - checking for messages\n",m->name);
  887.         while(fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
  888.             pwait(NULL);
  889.             if(*m->line == '-') {   /* end of record reached */
  890.                 skip = 0;
  891.                 break;
  892.             }
  893.             if((cp = strchr(m->line,' ')) != NULLCHAR)
  894.                 *cp = '\0';
  895.             if((cp = strchr(m->line,'\t')) != NULLCHAR)
  896.                 *cp = '\0';
  897.             if(skip || *m->line == '\0' || *m->line == '#' || *m->line == '.' || \
  898.                 *m->line == '+' || *m->line == '@' || *m->line == '&')
  899.                 continue;
  900.             rip(m->line);
  901.             bulletin = isarea(m->line);     /* public area */
  902.             sprintf(fn,"%s/%s.ind",Mailspool,m->line);
  903.             if((idx=open(fn,READBINARY)) != -1) {
  904.                 /* check if there are any messages in this area
  905.                  * that need to be forwarded.
  906.                  */
  907.                 if(read_header(idx,&hdr) == -1)
  908.                     hdr.msgs = 0;
  909.                 for(i=1; i<=hdr.msgs; i++) {
  910.                     pwait(NULL);
  911.                     /* Done with this index, clear it */
  912.                     default_index("",&ind);
  913.                     if(read_index(idx,&ind) == -1)
  914.                         break; /* Should not happen ! */
  915.                     /* Apply same tests as in makecl() */
  916.                     if(ind.status & BM_HOLD) continue;
  917.                     if(bulletin) {
  918.                         for(bbs = ind.bbslist;bbs;bbs=bbs->next)
  919.                             if(!stricmp(bbs->call,m->name))
  920.                                 break;
  921.                         if(bbs)
  922.                             continue;
  923.                     } else if(ind.status & BM_READ)
  924.                         continue;
  925.                     if(ind.from) {    /* Don't fwd back to originator */
  926.                         fp=strdup(ind.from);
  927.                         if((cp=strchr(fp,'@')) != NULL)
  928.                             *cp = '\0';
  929.                         if((cp=strchr(fp,'%')) != NULL)
  930.                             *cp = '\0';
  931.                         if(strstr(fp,m->name) != NULL) {
  932.                             free(fp);
  933.                             continue;
  934.                         }
  935.                         free(fp);
  936.                     }
  937.                     if(Mtrace)
  938.                         tprintf("fwd: starting %s (%s,#%d)\n",m->name, m->line, i);
  939.                     newproc("Mbox forwarding", 2048,
  940.                     startfwd, 0, (void *)cc,
  941.                     (void *)strdup(m->name),0);
  942.                     skip = 1;
  943.                     cc = NULLCHAR;
  944.                     break;
  945.                 }
  946.                 /* Done with this index, clear it */
  947.                 default_index("",&ind);
  948.                 close(idx);
  949.             }
  950.         }
  951.         free(cc);
  952.     }
  953.     default_index("",&ind);
  954.     usesock(Curproc->output);   /* compensate for close_s() in exitbbs */
  955.     exitbbs(m);
  956. }
  957.   
  958. /* returns 1 if m->name matches the name of another connected mailbox. */
  959. static int
  960. isconnbbs(m)
  961. struct mbx *m;
  962. {
  963.     struct mbx *mp;
  964.   
  965.     for(mp=Mbox;mp;mp=mp->next)
  966.         if((stricmp(mp->name,m->name) == 0) && (mp->state != MBX_TRYING) )
  967.             return 1;
  968.     return 0;
  969. }
  970.   
  971. /* possible commands on the command line in the forwarding file */
  972. static struct cmds cfwdcmds[] = {
  973.     "tcp",          openconn,       0, 0, NULLCHAR,
  974.     "telnet",       openconn,       0, 0, NULLCHAR,
  975. #ifdef AX25
  976.     "ax25",         openconn,       0, 0, NULLCHAR,
  977.     "connect",      openconn,       0, 0, NULLCHAR,
  978. #endif
  979. #ifdef NETROM
  980.     "netrom",       openconn,       0, 0, NULLCHAR,
  981. #endif
  982.     NULLCHAR
  983. };
  984.   
  985. int FwdUsers;
  986.   
  987. void exitfwd(struct mbx *m) {
  988.     FwdUsers--;
  989.     if(m->state != MBX_TRYING) log(m->user,"MBOX fwd exit: %s",m->name); /* N5KNX: log exits */
  990.     exitbbs(m);
  991. }
  992.   
  993. /* this function is called whenever the forwarding timer expires */
  994. static void
  995. startfwd(a,v1,v2)
  996. int a;
  997. void *v1, *v2;
  998. {
  999.     struct mbx *m;
  1000.     char *cc;
  1001.     int32 timeout;
  1002.     int rval;
  1003.     char *cp;
  1004.     char Continue[MBXLINE];
  1005.   
  1006.     cc = (char *) v1;
  1007.     if((m = newmbx()) == NULLMBX) {
  1008.         free(cc);
  1009.         free((char *)v2);
  1010.         return;
  1011.     }
  1012.     FwdUsers++;
  1013.     strcpy(m->name,(char *)v2);
  1014.     free((char *)v2);
  1015.     m->state = MBX_TRYING;
  1016.     /* open the connection, m->user will be the new socket */
  1017.     if(cmdparse(cfwdcmds,cc,(void *)m) == -1) {
  1018.         free(cc);
  1019.         usesock(Curproc->output);   /* compensate for close_s() in exitbbs */
  1020.         exitfwd(m);
  1021.         return;
  1022.     }
  1023.     free(cc);
  1024.     m->state = MBX_FORWARD;
  1025.     sockowner(m->user,Curproc);
  1026.     close_s(Curproc->output);
  1027.     close_s(Curproc->input);
  1028.     /* m->user will be closed automatically when this process exits */
  1029.     Curproc->output = Curproc->input = m->user;
  1030.     /* We'll do our own flushing right before we read input */
  1031.     setflush(m->user,-1);
  1032.   
  1033.     if(fwdinit(m) == -1) {
  1034.         /* it is probably not the right time to forward anymore */
  1035.         exitfwd(m);
  1036.         return;
  1037.     }
  1038.     /* read the connect script. Lines starting with a dot will be sent
  1039.      * to the remote BBS.
  1040.      */
  1041.     Continue[0] = '\0';
  1042.     while((cp=fgets(m->line,MBXLINE,m->tfile)) != NULLCHAR) {
  1043.         /* Expanded to do timeouts, and return string recognition - WG7J */
  1044.         switch(*m->line) {
  1045.             case '.':               /* send this line */
  1046.                 tputs(m->line + 1);
  1047.                 if(Mtrace)
  1048.                     printf("fwd: %s > %s\n",m->name,m->line+1);
  1049.                 Continue[0] = '\0';         /* reset reply string */
  1050.                 break;
  1051.             case '#':               /* comment line, ignore */
  1052.                 break;
  1053.             case '+':               /* string upon wich we continue ! */
  1054.                 strcpy(Continue,m->line+1);
  1055.                 rip(Continue);              /* get rid of \n */
  1056.                 break;
  1057.             case '&':               /* Wait a certain number of seconds */
  1058.                 timeout = atol(m->line+1);
  1059.                 pause(timeout * 1000L);
  1060.                 break;
  1061.             case '@':               /* string that sets timeout */
  1062.                 timeout = atol(m->line+1);
  1063.                 if(timeout)                 /* if a valid conversion */
  1064.                     timeout *= 1000;        /* in ms ! */
  1065.                 else
  1066.                     timeout = 90*1000L;     /* default to 1.5 minutes */
  1067.                 if(Mtrace)
  1068.                     printf("fwd: %s, wait %ld < %s\n",m->name,timeout/1000,Continue);
  1069.             /* Now do the actual response interpretations */
  1070.                 alarm(timeout);
  1071.                 rval = recvline(m->user,m->line,MBXLINE);
  1072.                 alarm(0L);
  1073.             /* Did we timeout, or connection disappear ? */
  1074.                 if(Mtrace) {
  1075.                     printf("fwd: %s, rx %d",m->name,rval);
  1076.                     if(rval >= 0)
  1077.                         printf(", %s",m->line);
  1078.                     else
  1079.                         putchar('\n');
  1080.                 }
  1081.                 if((rval < 0) || (strstr(m->line,Continue) == NULLCHAR)) {
  1082.                     if(Mtrace)
  1083.                         printf("fwd: %s, aborted!\n",m->name);
  1084.                     exitfwd(m);
  1085.                     return;
  1086.                 }
  1087.                 Continue[0] = '\0';         /* reset reply string */
  1088.                 break;
  1089.             default:        /* must be the end of the script */
  1090.                 goto go_on;
  1091.         }
  1092.   
  1093.         usflush(m->user);   /* send it, if any */
  1094.     }
  1095.     /* Now we've past all in-between stuff, go talk to the bbs ! */
  1096.     go_on:
  1097.     usflush(m->user);
  1098.     fclose(m->tfile);
  1099.     m->tfile = NULLFILE;
  1100.   
  1101.     /* make sure there is something left ! */
  1102.     if(cp == NULLCHAR) {
  1103.         if(Mtrace)
  1104.             puts("fwd: forward.bbs error!");
  1105.         exitfwd(m);
  1106.         return;
  1107.     }
  1108.     if(Mtrace)
  1109.         printf("fwd: %s, script done\n",m->name);
  1110.   
  1111.     /* read the initial output from the bbs, looking for the SID */
  1112.     for(;;) {
  1113.         if(recvline(m->user,m->line,MBXLINE) == -1) {
  1114.             exitfwd(m);
  1115.             return;
  1116.         }
  1117.         if(ISPROMPT(m->line))
  1118.             break;
  1119.         if(*m->line == '[') {           /* parse the SID */
  1120.             rip(m->line);
  1121.             mbx_parse(m);
  1122.             continue;
  1123.         }
  1124.     }
  1125.     /* Now sync the two ends as telnet password messes them up */
  1126.     if(socklen(m->user,0))          /* discard any remaining input */
  1127.         recv_mbuf(m->user,NULL,0,NULLCHAR,0);
  1128.   
  1129.     /* send our SID if the peer announced its SID */
  1130.     if(m->sid & MBX_SID) {
  1131.         tputs(MboxId);
  1132.         usflush(m->user);
  1133.         for(;;) {
  1134.             if(recvline(m->user,m->line,MBXLINE) == -1) {
  1135.                 exitfwd(m);
  1136.                 return;
  1137.             }
  1138.             if(ISPROMPT(m->line))
  1139.                 break;
  1140.         }
  1141.     }
  1142.     /* start the actual forwarding */
  1143.     dorevfwd(0,NULL,(void *)m);
  1144.     /* ask for reverse forwarding or just disconnect */
  1145.     if(((m->sid & MBX_SID) && tputs("F>\n") == -1) ||
  1146.     (m->sid & MBX_SID) == 0) {
  1147.         exitfwd(m);
  1148.         /* close_s(Curproc->output); exitfwd() calls exitbbs() which does this! */
  1149.         return;
  1150.     }
  1151.     usflush(m->user);
  1152.     /* parse the commands that are are received during reverse
  1153.      * forwarding.
  1154.      */
  1155.     while(recvline(m->user,m->line,MBXLINE) > 0) {
  1156.         rip(m->line);
  1157.         if(mbx_parse(m) == -2)   /* got the "*** Done" command */
  1158.             break;
  1159.         tputs("F>\n");
  1160.         usflush(m->user);
  1161.     }
  1162.     exitfwd(m);
  1163.     /* close_s(Curproc->output); exitfwd() calls exitbbs() which does this! */
  1164. }
  1165.   
  1166. /* open a network connection based upon information in the cc line.
  1167.  * m->user is set to the socket number.
  1168.  */
  1169. static int
  1170. openconn(argc,argv,p)
  1171. int argc;
  1172. char *argv[];
  1173. void *p;
  1174. {
  1175.     struct mbx *m;
  1176.     char sock[MAXSOCKSIZE], alias[AXBUF];
  1177.     struct nrroute_tab *rp;
  1178.     union sp sp;
  1179.     int len;
  1180.     char *remote;
  1181.   
  1182.     m = (struct mbx *)p;
  1183.     sp.p = sock;
  1184.     if(argc < 2) {
  1185.         if(Mtrace)
  1186.             tputs("fwd: connect command error\n");
  1187.         return -1;
  1188.     }
  1189.     remote = argv[1];
  1190.     switch(*argv[0]) {
  1191.         case 't':
  1192.             sp.in->sin_family = AF_INET;
  1193.             if((sp.in->sin_addr.s_addr = resolve(argv[1])) == 0) {
  1194.                 if(Mtrace)
  1195.                     tprintf("fwd: telnet - unknown host %s\n",argv[1]);
  1196.                 return -1;
  1197.             }
  1198.         /* get the optional port number */
  1199.             if(argc > 2)
  1200.                 sp.in->sin_port = atoip(argv[2]);
  1201.             else
  1202.                 sp.in->sin_port = IPPORT_TELNET;
  1203.             if((m->user = socket(AF_INET,SOCK_STREAM,0)) == -1) {
  1204.                 if(Mtrace)
  1205.                     tputs("fwd: unable to open telnet socket\n");
  1206.                 return -1;
  1207.             }
  1208.             len = sizeof(*sp.in);
  1209.             m->family = AF_INET; /*So the user list will be correct! - WG7J */
  1210.             break;
  1211. #ifdef AX25
  1212.         case 'a':
  1213.         case 'c':       /* allow 'c' for 'connect' as well */
  1214.             if(argc < 3) {
  1215.                 if(Mtrace)
  1216.                     tprintf("fwd: connect syntax error - %s %s ?\n",argv[0],argv[1]);
  1217.                 return -1;
  1218.             }
  1219.             sp.ax->sax_family = AF_AX25;
  1220.             strncpy(sp.ax->iface,argv[1],ILEN); /* the interface name */
  1221.             setcall(sp.ax->ax25_addr,argv[2]); /* the remote callsign */
  1222.         /* no digipeaters for now, use the "ax25 route add" command */
  1223.             if((m->user = socket(AF_AX25,SOCK_STREAM,0)) == -1) {
  1224.                 if(Mtrace)
  1225.                     tputs("fwd: Unable to open ax25 socket\n");
  1226.                 return -1;
  1227.             }
  1228.             len = sizeof(*sp.ax);
  1229.             m->family = AF_AX25; /*So the user list will be correct! - WG7J */
  1230.             remote = argv[2];
  1231.             break;
  1232. #endif /* AX25 */
  1233. #ifdef NETROM
  1234.         case 'n':
  1235.     /* See if the requested destination could be an alias, and
  1236.      * use it if it is.  Otherwise assume it is an AX.25
  1237.      * address.
  1238.      */
  1239.             putalias(alias,argv[1],0);
  1240.             strupr(argv[1]);
  1241.             if ((rp = find_nrboth(alias,argv[1])) == NULLNRRTAB)  {
  1242.                 if(Mtrace)
  1243.                     tprintf("fwd: Netrom route unavailable - %s\n",argv[1]);
  1244.                 return -1;
  1245.             }
  1246.     /* Setup the local side of the connection */
  1247.             sp.nr->nr_family = AF_NETROM;
  1248.             len = sizeof(*sp.nr);
  1249.             if((m->user = socket(AF_NETROM,SOCK_SEQPACKET,0)) == -1) {
  1250.                 if(Mtrace)
  1251.                     tprintf("fwd: unable to open netrom socket - %s\n",argv[1]);
  1252.   
  1253.                 return -1;
  1254.             }
  1255.             memcpy(sp.nr->nr_addr.user,Nr4user,AXALEN);
  1256.             memcpy(sp.nr->nr_addr.node,Nr_iface->hwaddr,AXALEN);
  1257.             bind(m->user,sp.p,len);
  1258.   
  1259.     /* Now the remote side */
  1260.             memcpy(sp.nr->nr_addr.node,rp->call,AXALEN) ;
  1261.     /* The user callsign of the remote station is never
  1262.          * used by NET/ROM, but it is needed for the psocket() call.
  1263.          */
  1264.             memcpy(sp.nr->nr_addr.user,rp->call,AXALEN) ;
  1265.   
  1266.             m->family = AF_NETROM; /*So the user list will be correct! - WG7J */
  1267.             break;
  1268. #endif /* NETROM */
  1269.         default:
  1270.             if(Mtrace)
  1271.                 tprintf("fwd: Invalid connect mode - %s\n",argv[0]);
  1272.   
  1273.             return -1;
  1274.     }
  1275.     sockmode(m->user,SOCK_ASCII);
  1276.     if(connect(m->user,sp.p,len) == -1) {
  1277.         log(m->user,"MBOX fwd failed: %s - %s errno %d",
  1278.         remote,sockerr(m->user),errno);
  1279.         if(Mtrace)
  1280.             tprintf("fwd: Connection failed to %s\n",remote);
  1281.         close_s(m->user);
  1282.         return -1;
  1283.     }
  1284.     return m->user;
  1285. }
  1286.   
  1287. #endif /*MBFWD*/
  1288.