int FwdUsers;

void exitfwd __ARGS((struct mbx *m));
int fbbparse __ARGS((struct fbbpacket *msglst, char *fbline, char *area));
int fbbdofs __ARGS((struct fbbpacket *msglst,struct fwd *f,int msgcnt,long *mindeferred,long *maxdeferred,int idx));
int dofbbrecv __ARGS((struct fwd *f));
int dofbbsend __ARGS((struct fwd *f));
int dofbbfwd __ARGS((int argc,char *argv[],void *p));
extern int msgidcheck __ARGS((char *string));
extern int issysarea __ARGS((char *name));


/* This code was moved for the FBBFWD stuff to compile without warning messages. */
void exitfwd(struct mbx *m) {
    FwdUsers--;
    if(m->state != MBX_TRYING) log(m->user,"MBOX fwd exit: %s",m->name); /* N5KNX: log exits */
    exitbbs(m);
}

#ifdef FBBFWD
int    FBBMAXMSGS     = 5;   /* Maximum number of messages to process. */

/* This code converts/parses a FBB FB type message to a fbbpacket structure. */
int fbbparse(struct fbbpacket *msglst, char *fbline, char *area){
   char *cp;

   char *atbbs;
   char *to;

   /* FB/FA */
   cp = strtok(fbline," ");
   if(strlen(cp) < sizeof(msglst->fbbcmd))
      strcpy(msglst->fbbcmd, cp);

   /* Message type */
   cp = strtok('\0', " ");
   msglst->type = cp[0];

   /* From id */
   cp = strtok('\0', " ");
   free(msglst->from);
   msglst->from = strdup(cp);

   /* hostname ( @somewhere ) */
   cp = strtok('\0', " ");
   atbbs = strdup(cp);

   /* To: id */
   cp = strtok('\0', " ");
   to = strdup(cp);

   free(msglst->to);
   msglst->to = malloc(strlen(to) + strlen(atbbs) + 2);

   strcpy(msglst->to, to);
   strcat(msglst->to, "@");
   strcat(msglst->to, atbbs);

   /* Bid */
   cp = strtok('\0', " ");
   free(msglst->messageid);
   msglst->messageid = strdup(cp);

   /* Size */
   cp = strtok('\0', " ");
   msglst->size = atoi(cp);

   free(to);
   free(atbbs);

   return 1;
}


/* This code processes a FS packet from a remote system.
// A '+' means the message is accepted.
//   '-' means the message is rejected.
//   '=' means the message is accepted but do not send it yet.
//       deferred messages (=) are a real pain to process. :(
//
// RC =  0 means an error was detected.
//       1 means an 'FF' was received from the remote system.
//       2 means an 'Fx' (where x is something) was received.
*/

int fbbdofs(struct fbbpacket *msglst,
            struct fwd *f,
            int    msgcnt,
            long   *mindeferred,
            long   *maxdeferred,
            int    idx){

   int i;
   struct mbx *m;

   m      = f->m;

   /* Send any data in our buffer. */
   usflush(m->user);
   /* Get the FS line. */
   if(recvline (m->user, m->line, MBXLINE) == -1 )
      return 0;

   rip(m->line);

   /* Make sure we got a "FS " line. Anything else is an error. */
   if(strnicmp(m->line,"FS ", 3) != 0) {
      tprintf("FBB Error: Expected 'FS ' string. Received \'%s\' string.\n",m->line);
      return 0;
   }

   /* Check to see if we got too many responses.
   // The next check makes sure we got enough of the right responses. */
   if((strlen(m->line) > msgcnt + 3))
      return 0;


   /* Validate FS line. Clean up unused entries. */
   for(i=0;i<FBBMAXMSGS;i++) {
      if(i<msgcnt) {
         if((m->line[3+i] != '+') &&
            (m->line[3+i] != '-') &&
            (m->line[3+i] != '=')) {
            tprintf("FBB Error: Expected '+, -, or ='. Received \'%c\'.\n",m->line[3+i]);
            return 0;
         }
      } else  {
         /* Zero out and free rest of the FS structure. */
         msglst[i].accept = 0;
         free(msglst[i].to);
         msglst[i].to        = NULLCHAR;
         free(msglst[i].from);
         msglst[i].from      = NULLCHAR;
         free(msglst[i].messageid);
         msglst[i].messageid = NULLCHAR;
         free(msglst[i].sline);
         msglst[i].sline     = NULLCHAR;
      }
   }


   /* The FS line is OK. Now we can send the '+' messages and delete the
   // '-' messages. */
   for(i=0;i<msgcnt;i++) {
      pwait(NULL);
      rip(msglst[i].sline); /* pretty up log. */

      MbForwarded++;

      if(m->line[3+i] == '+') {
         /* Message is wanted. We need to send it.
         // Do not update the X-Forwarded Header yet. FBB does not tell us
         // if it received the message or not. We have to send all our
         // messages and then see if the connect is still there. If we get
         // a valid FBB Response, then we can assume that the messages were
         // delivered and update the X-Forwarded flag. */

         msglst[i].accept = 2;

#if 0
         /* I do not like having to re-read the index here, but sendmsg()
         // needs a lot of index info so it needs to be done. */

         /* Re-position filepointer to index.... */
         lseek(idx,m->mbox[msglst[i].number].indexoffset,SEEK_SET);

         /* Clear/Free the previous index */
         default_index(m->area,&f->ind);

         /* and read the index. */
         read_index(idx,&f->ind);

         /* Send a subject line. */
         tprintf("%s\n",f->ind.subject);

         /* sendmsg() assumes that f->bid will hold the message id.
         // msglst[i].bid was saved from the makecl() call. */
         strcpy(f->bid, msglst[i].bid);

         /* Send the text of the message. */
         sendmsg(f, msglst[i].number);

         /* Send a ctrl-z ... that is OCTAL(32) */
         tputs("\032\n");
         usflush(m->user);

         /* and finally free the index. */
         default_index(m->area,&f->ind);
#else
	 changearea(f->m, msglst[i].area, (int) 1);

         /* Send a subject line. */
         tprintf("%s\n",msglst[i].subject);

         /* Send the text of the message. */
         sendmsg(f->m, msglst[i].number, msglst[i].bid);

         /* Send a ctrl-z ... that is OCTAL(32) */
         tputs("\032\n");
         usflush(m->user);

#endif
      } else
         /* The remote system does not want this message.
         // Go ahead and mark the msg as so. If the link goes
         // down, we still want to mark this message as unwanted.
         // One the link goes back up, we do not want to ask the
         // remote system again about this because it already
         // told us no. This is handeled differently than '+'
         // messages. */

         if(m->line[3+i] == '-') {
            msglst[i].accept = 1;
            /* mark message as forwarded or deleted. */
#if 0
            if(m->areatype == AREA)
               m->mbox[msglst[i].number].status |= BM_FORWARDED;
            else
               m->mbox[msglst[i].number].status |= BM_DELETE;
#else
	    mark_forwarded (msglst[i].fwdfile, msglst[i].fwdfileindex);
#endif
            m->change = 1;

            log(m->user,"MBOX bbs mail refused: %s ", msglst[i].sline);
         } else
            /* The remote system wants this message... later.... not now.
            // To handle this... we ignore the message for now and we
            // attempt to update the m->lastread message number to the
            // first deferred message. That way the next time we transfer
            // messages, we will ask about this message again. BUT... during
            // this tranfer sequence, we do not want to keep asking about
            // the  same message so we have to keep track of the highest
            // dererred message.
            // Anyway... the mindeferred counter is the FIRST deferred
            // message we do and is used to update the m->lastread counter.
            // The maxdeferred counter is the last deferred message. */

            if(m->line[3+i] == '=') {
               msglst[i].accept = 3;
#if 0	/* nothing else needs to be done for TNOS */
               /* Re-position filepointer to index.... */
               lseek(idx,m->mbox[msglst[i].number].indexoffset,SEEK_SET);

               /* Clear/Free the previous index */
               default_index(m->area,&f->ind);

               /* and read the index. */
               read_index(idx,&f->ind);

               /* maxdeferred will point to the highest deferred msg we have
               // processed. */
               if(*maxdeferred < f->ind.msgid)
                  *maxdeferred = f->ind.msgid;

               /* mindeferred will point to the first deferred msg we have
               // processed. */
               if(*mindeferred == 0)
                  *mindeferred = f->ind.msgid;

               /* and finally free the index. */
               default_index(m->area,&f->ind);
#endif
            }

   }


   /* Now we will get a line from the remote system to make sure that the
   // messages were received ok. */

   usflush(m->user);
   if(recvline(m->user,m->line,MBXLINE) == -1) {
      /* There was a problem. We did not get a response from the remote
      // system after we sent our messages. */
      return 0;
   } else {
      /* We got a response back, so we can update our '+' messages. */
      for(i=0;i<FBBMAXMSGS;i++) {
         if(msglst[i].accept == 2) {
            /* mark message as sent. */
#if 0
            if(m->areatype == AREA)
               m->mbox[msglst[i].number].status |= BM_FORWARDED;
            else
               m->mbox[msglst[i].number].status |= BM_DELETE;
#else
	    mark_forwarded (msglst[i].fwdfile, msglst[i].fwdfileindex);
#endif
            m->change = 1;

            /* For each valid note. */
            log(m->user,"MBOX bbs mail sent: %s ", msglst[i].sline);

            free(msglst[i].to);
            msglst[i].to        = NULLCHAR;
            free(msglst[i].from);
            msglst[i].from      = NULLCHAR;
            free(msglst[i].messageid);
            msglst[i].messageid = NULLCHAR;
            free(msglst[i].sline);
            msglst[i].sline     = NULLCHAR;
         }
      }
   }

   /* Change forward direction */
   m->state = MBX_REVFWD;
   if(strnicmp(m->line,"FF", 2) == 0)
      return 1;
   else
      return 2;
}

int dofbbrecv(struct fwd *f)
{
    int  msgcnt;
    int  msgsize = 0;

    int  FBBok;
    int  FBBdone;

    int  i;
    int  FirstTime;

    char FBBresp[9];
    char *cp;


    struct fbbpacket *msglst;
    struct mbx       *m;

    msglst = f->msglst;
    m      = f->m;

    msgcnt = 0;


    FBBdone   = FALSE;
    FirstTime = TRUE;

    /* Loop till we have received a F> or 5 FB blocks. */
    for(;;) {
        if(FirstTime) {
           /* Change the Firsttime flag and skip the read. */
           FirstTime = FALSE;
           if(m->line[0] == 0) {
              if(recvline (m->user, m->line, MBXLINE) == -1)
                break;
           }
        } else
           if(recvline (m->user, m->line, MBXLINE) == -1)
             break;

        pwait(NULL);
        /* Start off  with FBBok = FALSE.
        // If we get a FB or F> we will reset it to TRUE and
        // continue on. If we get something else we will exit. */
        FBBok = FALSE;

        /* strip any trailing NL characters. */
        rip(m->line);
        /* lowercase command. */
        cp = m->line;
        while(*cp){
           if(isupper(*cp))
              *cp = tolower(*cp);
           ++cp;
        }


        if(strncmp(m->line,"ff",2) == 0) {
           /* End of FBB Packet */
           return 2;
        }

        if(strncmp(m->line,"fq",2) == 0) {
           /* End of FBB Packet */
           return 3;
        }

        if(strncmp(m->line,"f>",2) == 0) {
           /* End of FBB Packet */
           FBBdone = TRUE;
           break;
        }

        if(strncmp(m->line,"fb",2) == 0) {
           /* Another message */
           if(msgcnt > FBBMAXMSGS) {
              /* Too many in fact. We are only supposed to accept
              // 5 (FBBMAXMSGS) msgs. */
              break;
           } else {
              log(m->user,"MBOX %s: %s",m->name,m->line);
              fbbparse(&msglst[msgcnt], m->line,m->area);
              msgsize += msglst[msgcnt].size;
              msgcnt++;
              FBBok = TRUE;
           }
        }

        /* If we did not reset the FBBok flag, something is wrong and we
        // need to exit. */
        if(!FBBok) {
           break;
        }

    }

    /* We have exited the FB....F> loop.
    // If FBBdone = TRUE we are ok... otherwise we received bad data. */
    if((!FBBdone))
       return 0;

    /* FB....F> data looks ok. Now process it and build our FS line. */
    strcpy(FBBresp, "FS ");
    /* Check each message in the list to see if we want it or not. */
    for(i=0;i<msgcnt;i++) {
       pwait(NULL);
       /* first check the msgid. If that works, run it through the
       // rewrite file. */
       if(!msgidcheck(msglst[i].messageid)) {
          msglst[i].accept = 2;
          pwait(NULL);
          if((cp = rewrite_address(msglst[i].to)) != NULLCHAR) {
             /* See if this is on the reject list. */
             if(!strcmp(cp,"refuse"))
                msglst[i].accept = 1;
             free(cp);
          }
       } else {
          msglst[i].accept = 1;
       }

       switch (msglst[i].accept) {
       case 0:
          printf("Programing error.... msglst.accept = 0 and that is not valid.\n");
          FBBresp[i+3] = '-';
          break;
       case 1:
          FBBresp[i+3] = '-';
          break;
       case 2:
          FBBresp[i+3] = '+';
          break;
       case 3:
          FBBresp[i+3] = '=';
          break;
       } /* endswitch */
    }
    /* Add a null to the end of the string. */
    FBBresp[i+3] = '\0';

    /* Now we can send it. */
    tprintf("%s\n", FBBresp);
    usflush(m->user);

    /* The remote system will start sending the messages.
    // Loop through the message list. */

    for(i=0;i<msgcnt;i++) {
       if(msglst[i].accept == 2) {
          pwait(NULL);
          sprintf(m->line, "send %s < %s $%s", msglst[i].to,
                                               msglst[i].from,
                                               msglst[i].messageid);

          /* Call mbx_parse to parse the send command. */
          mbx_parse(m);
       }
    }

    if(Mtrace)
       printf("FBBRECV: We've sent our data.\n");
    return 1;
}


int dofbbsend(struct fwd *f)
{
#if 0
   int    msgcnt;
   int    TMsgCnt;
   int    err = 0;
   int    i;
   int    rc;
   int    idx;
   int    indlen;
   int    MsgOk;

   int    FBBdone;
   int    FBBok;
   int    FirstRead;

   char   *cp;
   char   fn[64];
   char   oldarea[64];

   char   *savefsline;

   struct indexhdr hdr;
   struct fwdbbs *bbs;

   /* for makecl() */
   int    bulletin = (f->m->areatype == AREA);
   char   *subj = NULL;
   char   line[64];

   struct fwdarealist   *fwdarea;
   struct fwdarealist   *curarea;
   struct fwdarealist   *newarea;

   struct fbbpacket *msglst;
   struct mbx       *m;

   msglst = f->msglst;
   m      = f->m;

   savefsline = NULLCHAR;

    /*===================================================================
    //
    // This is the message forwarding code.
    //
    //===================================================================
    // we are in send mode now.... */

    /* clear index */
    memset(&f->ind,0,sizeof(struct mailindex));

    /* Check to see if we have any info to send and make sure it is the
    // right time to send data. */
    if(fwdinit(f->m) == -1) {
       /* The bbs is not in the forward.bbs file or it is the wrong time
       // to send.
       // Return a 0 to indicate that we have no data for the remote
       // system. */

       return 0;
    } else {
       /* It is ok to send data to the remote system. */
       strcpy(oldarea,m->area);

       /* Check to see if we have already read the list of areas to send
       // for this bbs. If f->FwdAreas == NULL, we have not read the
       // list so we need to do so. If it's not NULL then we've already
       // read the list and we do not need to do it again.
       //
       // Since FBB calls this code for each block of 5 messages, we
       // want to reduce the number of times we read the foward.bbs
       // file to pull out the forward area info. */

       if(!f->FwdAreas) {
          /* Set curarea to NULL to prevent a warning message. */
          curarea = NULL;

          while(!err && fgets(m->line,MBXLINE,m->tfile) != NULLCHAR) {
             pwait(NULL);
             /* Skip over non-area lines. */
             if(*m->line == '-')     /* end of record reached */
                break;
             cp = m->line;
             rip(cp);           /* adds extra null at end */
             /* skip spaces */
             while(*cp && (*cp == ' ' || *cp == '\t'))
                cp++;
             if(*cp == '\0' || *cp == '.' || *cp == '#' ||
                *cp == '+'  || *cp == '&' || *cp == '@')
                continue;       /* ignore empty or connect-script lines */

             /* remove trailing spaces or tabs */
             firsttoken(cp);

             /* Get memory for area info */
             newarea = malloc(sizeof(struct fwdarealist));

             /* Setup area info */
             newarea->name        = strdup(cp);
             newarea->mindeferred = 0;
             newarea->maxdeferred = 0;
             newarea->next        = NULL;

             /* Insert area into list */
             if(f->FwdAreas == NULL) {
                 f->FwdAreas = newarea;
             } else {
                 curarea->next = newarea;
             }
             curarea = newarea;
          }
       }

       /* We are done with the forward.bbs file so we can close it. */
       fclose(m->tfile);
       m->tfile = NULLFILE;

    }

    TMsgCnt = 0;
    FBBok  = TRUE;

    fwdarea = f->FwdAreas;
    while(fwdarea) {
        /* Change to area. */

        cp = fwdarea->name;
        changearea(f->m,cp);

        if(Mtrace)
           printf("Processing message area %s. LastRead = %ld.\n", cp, m->lastread);

        /* Now create the index filename */
        sprintf(fn,"%s/%s.ind",Mailspool,cp);

        /* get the optional destination field, cp will point
         * at null byte if it is missing.
         */
        while(*cp && *cp != ' ' && *cp != '\t')
            cp++;
        /* find end of optional destination */
        while(*cp && (*cp == ' ' || *cp == '\t')) /* strip blanks */
            ++cp;
        cp = strdup(cp);

        /* Loop backwards through message list
        // Stop when we've found a message that we've
        // already processed. */

        for(i = m->nmsgs; i; i--) {
            if(!fwdarea->maxdeferred) {
               if(m->mbox[i].msgid <= m->lastread) {
                  break;
               }
            } else {
               if(m->mbox[i].msgid <= fwdarea->maxdeferred) {
                  break;
               }
            }
        }

        FBBdone = FALSE;

        if(Mtrace)
           printf("i = %d. m->nmsgs = %d.\n", i, m->nmsgs);

        FirstRead = i;

        /* Check for new messages. */
        if(i != m->nmsgs) {
           i++;
           /* open the index file */
           if((idx=open(fn,READBINARY)) != -1) {
               /* check if there are any messages in this area
                * that need to be forwarded.
                */
               if(read_header(idx,&hdr) != -1) {
                   /* Position at correct index entry. */
                   lseek(idx,m->mbox[i].indexoffset,SEEK_SET);

                   /* Reset msgcnt; */
                   msgcnt  = 0;
                   FBBdone = FALSE;

                   /* i is set above.... points to next message to
                   // process. */
                   for(; i<=m->nmsgs; i++) {
                       pwait(NULL);
                       /* Read index. Save size for later use. */
                       indlen = read_index(idx,&f->ind);
                       if(indlen == -1) {
                           err = 1;
                           /* Done with this index, clear it */
                           default_index(m->area,&f->ind);
                           break;
                       }

                       MsgOk = TRUE;
                       /* Check x-forwarded-to fields */
                       for(bbs=f->ind.bbslist;bbs;bbs=bbs->next) {
                          if(!stricmp(bbs->call,m->name)) {
                             MsgOk = FALSE;
                             /* Done with this index, clear it */
                             default_index(m->area,&f->ind);
                             break;
                          }
                       }

                       /* We want to send this message. */
                       if(MsgOk) {
                          /* Build FB line. */
                          rc = makecl(f, i, cp, line, NULL, &bulletin);
                          /* If FB line ok, send it. */
                          if(rc != -1) {
                             /* Copy FB line for message log. */
                             free(msglst[msgcnt].sline);
                             msglst[msgcnt].sline = strdup(line);

                             /* Keep track of message number in area. */
                             msglst[msgcnt].number = i;

                             /* Keep track of makecl() modified bid. */
                             strcpy(msglst[msgcnt].bid, f->bid);

                             /* uppercase the FB line and send it. */
                             strupr(line);
                             tprintf("%s", line);

                             fbbparse(&msglst[msgcnt], line, m->area);
                             msgcnt++;
                             TMsgCnt++;

                             /* If we have filled our FB Block */
                             if(msgcnt >= FBBMAXMSGS) {
                                /* Send a end-of FB Block flag */
                                tprintf("F>\n");

                                /* Process an incoming FS and receive messages. */
                                rc = fbbdofs(msglst, f, msgcnt, &fwdarea->mindeferred, &fwdarea->maxdeferred, idx);
                                free(savefsline);
                                savefsline = strdup(m->line);

                                /* Reset counter. */
                                msgcnt  = 0;

                                if(!rc) {
                                   FBBok = FALSE;
                                   FBBdone = TRUE;
                                } else
                                if(rc == 1) {
                                   FBBok = TRUE;
                                   FBBdone = FALSE;
                                } else
                                if(rc == 2) {
                                   FBBok = TRUE;
                                   FBBdone = TRUE;
                                }
                             }
                          }
                       }

                       /* Done with this index, clear it */
                       default_index(m->area,&f->ind);
                       m->newlastread = m->mbox[i].msgid;

                       scanmail(f->m);
                       pwait(NULL);

                       /* If we got an error from dofs() or the response
                       // from dofs() was 2, we are done with this message
                       // transfer. If we got a 1 from dofs() we can send
                       // more messages now so we do not need to exit. */
                       if(FBBdone)
                         break;
                   } /* end for() */

                   /* Done with this index, clear it */
                   default_index(m->area,&f->ind);

                   /* Finish off any FB messages. */
                   if(msgcnt) {
                      /* Send a end-of FB Block flag */
                      tprintf("F>\n");
                      /* Process an incoming FS and receive messages. */
                      rc = fbbdofs(msglst, f, msgcnt, &fwdarea->mindeferred, &fwdarea->maxdeferred, idx);
                      free(savefsline);
                      savefsline = strdup(m->line);

                      /* Reset counter. */
                      msgcnt  = 0;

                      if(!rc) {
                         FBBok = FALSE;
                         FBBdone = TRUE;
                      } else
                      if(rc == 1) {
                         FBBok = TRUE;
                         FBBdone = FALSE;
                      } else
                      if(rc == 2) {
                         FBBok = TRUE;
                         FBBdone = TRUE;
                      }
                   } /* end if() */
               } /* end if() */
           } /* end if() */
           close(idx);
           idx = 0;

           /* If we got an error from dofs() or the response
           // from dofs() was 2, we are done with this message
           // transfer. If we got a 1 from dofs() we can send
           // more messages now so we do not need to exit. */
           if(FBBdone) {
             free(cp);
             break;
           }
        } /* end if() */

        /* Done with the area. Close the *.txt file if it was open. */
        if(m->mfile) {
            fclose(m->mfile);
            m->mfile = NULL;
        }
        free(cp);

        if(fwdarea->mindeferred != 0) {
           m->lastread    = 0;
           m->newlastread = fwdarea->mindeferred;
        }

        if(FBBdone)
           break;

        /* Do next area. */
        fwdarea = fwdarea->next;
    } /* end while() */

    /* An error occured. Reset m->lastread so we will process this area again. */
    if(!FBBok) {
        m->lastread    = 0;
        m->newlastread = FirstRead;
    }

    /* change back to original message area. */
    if(*oldarea != '\0')
        changearea(f->m,oldarea);


    /* set up the result from fbbdofs() call. */
    if(savefsline) {
       strcpy(m->line, savefsline);
       free(savefsline);
    }

    if(!FBBok)
       /* We had an error. */
       return 3;

    if(TMsgCnt == 0) {
       if(Mtrace)
          printf("FBBSEND: No Data to send.\n");
       /* We had no data. */
       return 2;
    }

#endif
    return 1;
}

/* This is the main entry point for FBB forwarding. */
int
dofbbfwd(argc,argv,p)
int argc;
char *argv[];
void *p;
{
    struct fwd       f;
    struct mbx       *m;
    struct fbbpacket *msglst;

    int    i;
    int    Done;
    int    rc;
    int    FBBRdone = FALSE;         /* Receiving system has no more data. */
    int    NeedData;
    int    FBBfwd;

#if 0
    struct fwdarealist *fwdareas;
    struct fwdarealist *curareas;
#endif

    f.m = (struct mbx *)p;
    m   = f.m;

#if 0
    memset(&f.ind,0,sizeof(struct mailindex));
#endif

    log(f.m->user,"MBOX FBB forwarding mail to: %s ", f.m->name);

    /* First verify that this is a FBB type system. */
    if(!(f.m->sid & MBX_FBBFWD)) {
       tprintf("Huh?\n");
       usflush(m->user);
       return -1;
    }

#if 0
    /* Start with fresh copy of FwdAreas list */
    f.FwdAreas = NULL;
#endif

    /* Get memory for the msglst array. */
    f.msglst = (struct fbbpacket *)callocw((unsigned)FBBMAXMSGS,sizeof(struct fbbpacket));
    msglst = f.msglst;

    /* Clear out the msglst array. */
    for(i=0;i<FBBMAXMSGS;i++) {
       msglst[i].to        = NULLCHAR;
       msglst[i].from      = NULLCHAR;
       msglst[i].messageid = NULLCHAR;
       msglst[i].sline     = NULLCHAR;
       msglst[i].size      = 0;
    }

    NeedData = FALSE;
    Done     = FALSE;
    FBBfwd   = FALSE;

    /* See if we were called because we received a FB from the remote system. */
    if(argc == 0) {
       f.m->state = MBX_FORWARD; /* We are in send mode. */
       FBBRdone   = FALSE;
       NeedData   = TRUE;
       FBBfwd     = TRUE;
    }
    else
    if(strnicmp(argv[0],"FB",2) == 0) {
       if(argc != 7) {
          tprintf("Huh?\n");
          usflush(m->user);
          Done     = TRUE;
       } else {
          sprintf(f.m->line,"FB %s %s %s %s %s %s",argv[1],
                                                   argv[2],
                                                   argv[3],
                                                   argv[4],
                                                   argv[5],
                                                   argv[6]);
          /* indicate that we are in receive mode. */
          f.m->state = MBX_REVFWD;
          FBBRdone = FALSE;
       }
    } else {
       /* Must have received a FF from the remote system. */
       f.m->state = MBX_FORWARD; /* We are in send mode. */
       FBBRdone = TRUE;
    }


    if(Mtrace)
       printf("FBB Forwarding started.\n");

    while(!Done) {
       pwait(NULL);
       if(f.m->state == MBX_REVFWD) {
          if(Mtrace)
             printf("FBBFWD: Receiving data from remote system.\n");

          if(NeedData) {
             /* null out the line. */
             f.m->line[0] = 0;
          }

          /* Receive data from remote system.
          // Process FB....F> block. */
          rc = dofbbrecv(&f);
          if(rc == 0)
             /* An error occured. */
             Done = TRUE;
          else
             if(rc == 2)
                /* Remote system sent us a FF */
                FBBRdone = TRUE;
          else
             if(rc == 3) {
                /* Remote system sent us a FQ so break; and disconnect. */
                tprintf("FQ\n");
                usflush(m->user);
                Done = TRUE;
             }

          /* Change status. */
          f.m->state  = MBX_FORWARD;
       } else {
          if(Mtrace)
             printf("FBBFWD: Sending data to remote system.\n");

          NeedData = FALSE;
          /* Change status. */
          rc = dofbbsend(&f);
          if(rc == 3)
             /* An error occured. */
             break;
          if((rc == 0) || (rc == 2)) {
             /* We had no data for remote system. */
             if(FBBRdone) {
                /* They have no more data for us....
                // So we break out of this loop and send our FQ and disconnect. */
                if(Mtrace)
                   printf("FBBSEND: No Data to send. No Data to receive.\n");
                break;
             } else {
                /* Tell them that we do not have any data for them. */
                if(Mtrace)
                   printf("FBBSEND: No Data to send. Sending FF\n");
                tprintf("FF\n");
                usflush(m->user);
                NeedData = TRUE;
             }
          }

          /* Change status. */
          f.m->state  = MBX_REVFWD;
       }
    } /* endwhile */

    /* free anything in the msglst array. */
    for(i=0;i<FBBMAXMSGS;i++) {
       free(msglst[i].to);
       free(msglst[i].from);
       free(msglst[i].messageid);
       free(msglst[i].sline);
    }

    /* Now free the msglst array. */
    free(msglst);

#if 0
    /* Free our FwdAreas list */
    fwdareas = f.FwdAreas;
    while(fwdareas) {
        free(fwdareas->name);
        curareas = fwdareas;
        fwdareas = fwdareas->next;
        free(curareas);
    }
#endif

    /* We're done. Send our FQ and we're out of here. */
    tprintf("FQ\n");
    usflush(m->user);
    if(FBBfwd)
       exitfwd(m);
    else
       return domboxbye(0,NULL,m);
    return 0;
}
#endif /* ifdef FBBFWD */

