home *** CD-ROM | disk | FTP | other *** search
/ World of Ham Radio 1994 January / AMSOFT_1994.iso / packet / pbbs / cbbs / prog / mbfwd.c < prev    next >
Encoding:
C/C++ Source or Header  |  1993-12-31  |  20.2 KB  |  986 lines

  1.  
  2. /*
  3.  *  MBFWD.C - 3/20/89 - Autoforwarding.
  4.  *
  5.  *  The target port mode is set to idle if not connected,
  6.  *  set to remote if connected. It is set to disconnect or timeout
  7.  *  by getdat(), but this is checked and fixed up in getln().
  8.  *
  9.  *  All port input is through getln().
  10.  *  All file input is through nxtin().
  11.  */
  12.  
  13. #include "mb.h"
  14.  
  15. #define deepmax    5     /* Max nesting depth of indirection in fwd.mb */
  16.  
  17. #define fw_one     0x01  /* Forward to only one MailBox, given in fcall*/
  18. #define fw_anytime 0x02  /* Ignore the times in the "G" item           */
  19. #define fw_abort   0x04  /* Abort forwarding as soon as possible       */
  20. #define fw_tried   0x08  /* Attempted to forward to this MailBox       */
  21. #define fw_tiout   0x10  /* Forward timeout flag                       */
  22. #define fw_forced  0x20  /* Forced forward flag                        */
  23. #define fw_pass    0x40  /* Bypass forward sub file                    */
  24.  
  25. char  *script;           /* Pointer to where the connect script is     */
  26.  
  27. byte  fopts;             /* Options, see defines above.                */
  28. char  fwdtyp;
  29. char  *fwdfile;          /* The file name of fwd.mb root file          */
  30. FILE  *ifl[deepmax];     /* File variables for fwd.mb                  */
  31. short deep;              /* Current depth within fwd.mb                */
  32. char  path[80];          /* "G" item saved here, for logging           */
  33. char  fcall[10];         /* Call of the MailBox to forward to          */
  34.  
  35. /*
  36.  *  YF command: change the name of the forwarding root file.
  37.  */
  38.  
  39. newfwd()
  40. {
  41.   if (*port->fld[1])
  42.   {
  43.     free(fwdfile);
  44.     fwdfile = strdup(port->fld[1]);
  45.   }
  46.   sprintf(tmp->scr, "is %s\n", fwdfile);
  47.   outstr(tmp->scr);
  48. }
  49.  
  50. /*
  51.  *  Add a call to the list of BBS that have messages to be forwarded to them.
  52.  */
  53.  
  54. addbfwd(cp)
  55. char *cp;
  56. {
  57.   register short i;
  58.   register char *lp;
  59.  
  60.   for (i = 0, lp = bfwd; i < bfwdn; i++, lp += ln_call)
  61.     if (matchn(cp, lp, ln_call)) return;
  62.  
  63.   if (bfwdn < bfwdm) { strncpy(lp, cp, ln_call); bfwdn++; }
  64. }
  65.  
  66. /*
  67.  *  Add a call to the list of users that have unread messges.
  68.  */
  69.  
  70. addufwd(cp)
  71. char *cp;
  72. {
  73.   register short i;
  74.   register char *lp;
  75.  
  76.   for (i = 0, lp = ufwd; i < ufwdn; i++, lp += ln_call)
  77.     if (matchn(cp, lp, ln_call)) return;
  78.  
  79.   if (ufwdn < ufwdm) { strncpy(lp, cp, ln_call); ufwdn++; }
  80. }
  81.  
  82. /*
  83.  *  Check if a call has a message to be forwarded to it.
  84.  */
  85.  
  86. findfwd(cp, lp, n)
  87. char *cp, *lp;
  88. short n;
  89. {
  90.   register short i;
  91.  
  92.   for (i = 0; i < n; i++, lp += ln_call) if (wcm(cp, lp)) return true;
  93.   return false;
  94. }
  95.  
  96. /*
  97.  *  Add the info from one message header to the lists of calls
  98.  *  of stations that have messages to be forwarded to them.
  99.  *
  100.  *  ufwd - Calls to put in beacon line.
  101.  *  bfwd - Calls that have message TO or AT.
  102.  */
  103.  
  104. addfwd()
  105. {
  106.   register short i;
  107.   char *p, hcall[6];
  108.  
  109.   if (!(port->mmhs->stat & (m_bull | m_busy | m_kill | m_read | m_fwd | m_hold)))
  110.   {
  111.     if (*port->mmhs->bbs is ' ')
  112.     {
  113.       addufwd(port->mmhs->to);
  114.       addbfwd(port->mmhs->to);
  115.     }
  116.     else
  117.     {
  118.       if (port->mmhs->ext is 1)
  119.       {
  120.         for (i = 0; i < port->mmhs->count; i++) if (port->mmhs->flag[i])
  121.           addbfwd(port->mmhs->call[i]);
  122.       }
  123.       else
  124.       {
  125.         if (matchn(port->mmhs->bbs, cport->user->call, ln_call))
  126.           addufwd(port->mmhs->to);
  127.         else addbfwd(port->mmhs->bbs);
  128.         if (port->mmhs->ext is 2)
  129.         {
  130.           p = port->mmhs->call[0];
  131.           while((p = strchr(p, '.')) isnt NULL)
  132.           {
  133.             p++;
  134.             fill(hcall, ' ', ln_call);
  135.             pcall(hcall, p);
  136.             addbfwd(hcall);
  137.           }
  138.         }
  139.       }
  140.     }
  141.   }
  142. }
  143.  
  144. /*
  145.  *  Build the two lists of calls of stations that have
  146.  *  messages to be forwarded to them.
  147.  */
  148.  
  149. bldfwd()
  150. {
  151.   register word  h;
  152.  
  153.   ufwdn = 0;
  154.   bfwdn = 0;
  155.   read_rec(mfl, 0, (char *)mfhs);
  156.   for (h = mfhs->last; h; h--)
  157.   {
  158.     read_rec(mfl, h, (char *)port->mmhs);
  159.     if (!(port->mmhs->stat & (m_bull|m_busy|m_kill|m_read|m_fwd|m_hold)))
  160.     addfwd();
  161.   }
  162. }
  163.  
  164. /*
  165.  *  Return true if the current time is within
  166.  *  the time window for forwarding to this MailBox.
  167.  */
  168.  
  169. chktime()
  170. {
  171.   register short c, en, st;
  172.  
  173.   if (fopts & fw_anytime) return true;
  174.   curtim();
  175.   st = 10 * (int)(cport->line[2] - '0') + (int)(cport->line[3] - '0');
  176.   en = 10 * (int)(cport->line[4] - '0') + (int)(cport->line[5] - '0');
  177.   c  = 10 * (int)(l_time[0] - '0') + (int)(l_time[1] - '0');
  178.   if (st <= en) return ((c >= st) and (c <= en));
  179.   return ((c >= st) or (c <= en));
  180. }
  181.  
  182. /*
  183.  *  Check if it is ok to forward using this list.
  184.  *  Return a pointer to the port to use for forwarding, or NULL.
  185.  */
  186.  
  187. PORTS *chkfwd()
  188. {
  189.   register PORTS *p;
  190.  
  191.   if (fopts & fw_one)
  192.   if (!match (fcall, cport->fld[1]))       { passlst(); return NULL; }
  193.   if (!chktime())                          { passlst(); return NULL; }
  194.   if ((p = findport(cport->opt2)) is NULL) { passlst(); return NULL; }
  195.   if (!(p->flags & p_dofwd))               { passlst(); return NULL; }
  196.   if (fopts & fw_abort)                    { passlst(); return NULL; }
  197.   p->mode = idle;
  198.   return p;
  199. }
  200.  
  201. /*
  202.  *  Check if a disconnect happened.
  203.  */
  204.  
  205. chkdis()
  206. {
  207.   if (instat()) if (getdat()) if (isdis(port->line))
  208.     { cmdtnc(); port->mode = idle; return true; }
  209.   if (port->flags & p_trans) if (!isdcd())
  210.     { cmdtnc(); port->mode = idle; return true; }
  211.   return false;
  212. }
  213.  
  214. /*
  215.  *  Read the next input line from FWD.MB,
  216.  *  or from a file referenced from FWD.MB.
  217.  *  Return NULL if no more lines to read.
  218.  */
  219.  
  220. char *nxtin(p)
  221. char *p;
  222. {
  223.   register char *st, i;
  224.  
  225.   while (deep >= 0)
  226.   {
  227.     i = 1;
  228.     if ((st = fgets(p, 80, ifl[deep])) is NULL)
  229.     {
  230.       fclose(ifl[deep]);
  231.       deep--;
  232.     }
  233.     else
  234.     {
  235.       if (*p isnt '@') return st;
  236.       if (fopts & fw_pass) return st;
  237.       if (*(p+1) is ' ')
  238.       {
  239.         if (!chktime()) return st;
  240.         i = 6;
  241.       }
  242.       if (deep < (deepmax - 1))
  243.       {
  244.         strupr(p);
  245.         remnl(p);
  246.         deep++;
  247.         if ((ifl[deep] = fopen(p + i, "r")) is NULL) deep--;
  248.       }
  249.     }
  250.   }
  251.   return NULL;
  252. }
  253.  
  254. /*
  255.  *  Do some DOS commands.
  256.  */
  257.  
  258.  
  259. dofdos()
  260. {
  261.   register PORTS *p;
  262.  
  263.   if ((p = findport(cport->opt2)) is NULL) { passlst(); return; }
  264.   if (strlen(cport->fld[0]) > 3) if (!chktime()) { passlst(); return; }
  265.   if (fopts & fw_forced)
  266.   if (!((fopts & fw_one) and (match(fcall, cport->fld[1]))))
  267.   { passlst(); return; }
  268.  
  269. /*
  270.  *  Just in case, flush whatever might be currently open.
  271.  */
  272.  
  273.   clnuser();
  274.   clnmsg();
  275.   clnlog();
  276.  
  277.   while (nxtin(cport->line) isnt NULL)
  278.   {
  279.     if (iseof(cport->line)) return;
  280.     remnl(cport->line);
  281.     printf("\nRunning: %s\n", cport->line);
  282.     if (system(cport->line)) perror("Error");
  283.   }
  284. }
  285.  
  286. /*
  287.  *  The entry to fowarding.
  288.  */
  289.  
  290. fwd()
  291. {
  292.   register PORTS *p;
  293.  
  294. /*
  295.  *  If no fwd.mb file, then do nothing.
  296.  */
  297.  
  298.   deep = 0;
  299.   if ((ifl[deep] = fopen(fwdfile, "r")) is NULL) return;
  300.  
  301.   bldfwd();
  302.  
  303.   script = tmp->scr;
  304.   *script = '\0';
  305.  
  306.   while(nxtin(cport->line) isnt NULL)
  307.   {
  308.     bidok = false;
  309.     hidok = false;
  310.     ioport(cport);
  311.     strupr(cport->line);
  312.     parse();
  313.     fwdtyp = cport->opt1;
  314.     switch (fwdtyp)
  315.     {
  316.       case 'E':
  317.         passlst();
  318.         script = tmp->scr;
  319.         *script = '\0';
  320.         break;
  321.       case 'D':
  322.       case 'F':
  323.       case 'G':
  324.       case 'H':
  325.         if ((p = chkfwd()) isnt NULL)
  326.         {
  327.           fopts clrbit fw_tried;
  328. /*
  329.  *  Save tail of list header for logging.
  330.  */
  331.           strcpy(path, cport->line + 6);
  332.           remnl(path);
  333.           script = tmp->scr;
  334.           if (!*script)
  335.           {
  336.             *script = 'C';
  337.             strcpy(script + 1, cport->line + 6);
  338.             *(script + strlen(script) + 1) = '\0';
  339.           }
  340.           dofwd(p);
  341.           dorev(p);
  342.           distnc();
  343.           p->mode = idle;
  344.           ioport(cport);
  345.         }
  346.         script = tmp->scr;
  347.         *script = '\0';
  348.         break;
  349.  
  350.       case 'P':
  351.         dopar();
  352.         break;
  353.  
  354.       case '!':
  355.         dofdos();
  356.         break;
  357.  
  358.       case 'C':
  359.       case 'R':
  360.       case 'S':
  361.         strcpy(script, cport->line);
  362.         script += (strlen(cport->line) + 1);
  363.         *script = '\0';
  364.         break;
  365.  
  366.       default:  break;
  367.     }
  368.   }
  369.  
  370. /*
  371.  *  Put us back on the port we were on when we got here.
  372.  */
  373.  
  374.   ioport(cport);
  375.   bidok = false;
  376.   hidok = false;
  377. }
  378.  
  379. /*
  380.  *  A and AI commands.
  381.  */
  382.  
  383. all_fwd()
  384. {
  385.   byte pflg;
  386.   port->opt1 = 'X';
  387.   putcomd( port->opt1, port->opt2 );
  388.  
  389.   pflg = getp_flag();
  390.   putc_flag (pflg);
  391.   port->mode = logout;
  392. }
  393.  
  394. /*
  395.  *  X and XI commands.
  396.  */
  397.  
  398. sfwd()
  399. {
  400.   register PORTS *p;
  401.  
  402. /*
  403.  *  If remote sysop did the command, just remember it for later.
  404.  */
  405.  
  406.   if (port->mode & sysop) { savecmd(); return; }
  407.  
  408. /*
  409.  *  Set up parameters for fwd()
  410.  */
  411.  
  412.   fopts = fw_forced;
  413.   for (p = porthd; p isnt NULL; p = p->next)
  414.   {
  415.     p->ec = p->ecuser;
  416.     p->flags setbit p_dofwd;
  417.   }
  418.  
  419.   if (cport->flds is 2)
  420.   {
  421.     fopts setbit fw_one;
  422.     strncpy (fcall, cport->fld[1], ln_callp);
  423.   }
  424.  
  425.   if (cport->opt2 is 'I') fopts setbit fw_anytime;
  426.  
  427.   fwd();
  428.  
  429. /*
  430.  *  Reset the port flags.
  431.  */
  432.  
  433.   for (p = porthd; p isnt NULL; p = p->next)
  434.   {
  435.     p->ec = p->ecmon;
  436.     p->flags clrbit p_dofwd;
  437.   }
  438. }
  439.  
  440. /*
  441.  *  Automatic forwarding.
  442.  *  Called once each minute when the MailBox is idle.
  443.  */
  444.  
  445. afwd(curmin)
  446. int curmin;
  447. {
  448.   register PORTS *p;
  449.   register short anyfwd;
  450.  
  451. /*
  452.  *  Mark the ports that should forward at this minute.
  453.  */
  454.  
  455.   fopts = 0;
  456.   anyfwd = false;
  457.   for (p = porthd; p isnt NULL; p = p->next) if (p->fwdmin is curmin)
  458.   {
  459.     p->flags setbit p_dofwd;
  460.     p->ec = p->ecuser;
  461.     anyfwd = true;
  462.   }
  463.  
  464. /*
  465.  *  If any ports forward at this minute, do the forwarding.
  466.  */
  467.  
  468.   if (anyfwd)
  469.   {
  470.     setbusy();
  471.     alloff();   /* Turn off connects and monitoring */
  472.     if (s_flag & s_dv) begin_lock();
  473.     readmsg();
  474.     readusr();
  475.  
  476. /*
  477.  *  Write out mon and calls heard files
  478.  */
  479.     clsmon();
  480.  
  481. /*
  482.  *  Once a day, do wp and stale
  483.  */
  484.     if (!matchn(ufhs->wpdate, l_date, ln_date))
  485.     {
  486.       port->opt1 = '\0';
  487.       port->flds = 1;
  488.       dwuser();
  489.       stale();
  490.       strncpy(ufhs->wpdate, l_date, ln_date);
  491.       write_rec(ufl, 0, (char *)ufhs);
  492.     }
  493.     if (s_flag & s_dv) end_lock();
  494.  
  495. /*
  496.  * Check and see if the mailfile should be compressed
  497.  */
  498.     if (s_param & s_unt)
  499.     if (!matchn(mfhs->date, l_date, ln_date))
  500.     if (unt_hr <= (10 *(l_time[0] - '0') + (l_time[1] - '0')))
  501.     {
  502.       port->opt2 = 'A';
  503.       setunt();
  504.     }
  505.  
  506.     fwd();
  507.     clnlog();
  508.     setfwd();
  509.     clsmsg();
  510.     clsusr();
  511.     allon();    /* Turn on monitoring and connects */
  512.     clrbusy();
  513.   }
  514.  
  515. /*
  516.  *  Reset the port flags.
  517.  */
  518.  
  519.   for (p = porthd; p isnt NULL; p = p->next)
  520.   {
  521.     p->ec = p->ecmon;
  522.     p->flags clrbit p_dofwd;
  523.   }
  524. }
  525.  
  526. /*
  527.  *  Reverse forwarding.
  528.  *  Accept messages from the remote MailBox after forwarding to it.
  529.  */
  530.  
  531. dorev(p)
  532. PORTS *p;
  533. {
  534.   char rcall[6];
  535.   ioport(p);
  536.  
  537.   if (fwdtyp is 'G') return;
  538.   if (fwdtyp is 'D') return;
  539.  
  540.   if (p->mode & idle)
  541.   {
  542.     if (fwdtyp is 'F') return;
  543.     if (fwdtyp is 'H') if (fopts & fw_tried) return;
  544.     cmb();
  545.     if (p->mode & idle) return;
  546.   }
  547.  
  548.   pcall(rcall, path + 2);
  549.   rduser(rcall, p->user);
  550.   log ('M', 'F', 'R', path);  /* Log start of reverse forward */
  551.  
  552.   if (p->tmode)
  553.   {
  554.      cmdtnc();
  555.      trantnc();
  556.   }
  557.  
  558.   while(true)
  559.   {
  560.     outstr("F>\n");
  561.     getln();
  562.     if (p->mode & idle) return;
  563.     parse();
  564.  
  565.     if (p->opt1 isnt 'S') return;
  566.     {
  567.       sndmsg();
  568.       if (p->mode & gone) return;
  569.       addfwd();
  570.     }
  571.   }
  572. }
  573.  
  574. /*
  575.  *  F> command: do reverse forward to logged user.
  576.  */
  577.  
  578. fwdcmd()
  579. {
  580.   register PORTS *p;
  581.   register short ok;
  582.  
  583. /*
  584.  *  If no fwd.mb file, then do nothing.
  585.  */
  586.  
  587.   p = port;
  588.   deep = 0;
  589.   if ((ifl[deep] = fopen(fwdfile, "r")) is NULL) { p->mode = forced; return; }
  590.  
  591.   ioport(cport);
  592.  
  593. /*
  594.  *  Find the users E, F, G, or H list in the fwd.mb file.
  595.  */
  596.  
  597.   ok = false;
  598.   while(!ok and (nxtin(cport->line) isnt NULL))
  599.   {
  600.     strupr(cport->line);
  601.     parse();
  602.     fwdtyp = cport->opt1;
  603.  
  604.     switch(fwdtyp)
  605.     {
  606.       case 'D' :
  607.       case 'E' :
  608.       case 'F' :
  609.       case 'G' :
  610.       case 'H' :
  611.         pcall(fcall, cport->fld[1]);
  612.         ok = matchn(fcall, p->user->call, ln_call);
  613.  
  614.         if (!ok) passlst();
  615.         break;
  616.  
  617.       case '!' :
  618.       case 'P' :
  619.         passlst();
  620.         break;
  621.  
  622.       default  : ;   /* 'C', 'R', 'S' */
  623.     }
  624.   }
  625.  
  626.   ioport(p);
  627.  
  628.   if (ok)
  629.   {
  630.     log ('M', 'F', 'S', nullstr);      /* Log start of forwarding */
  631.     bldfwd();
  632.     remnl(cport->line);
  633.     strcpy( path, cport->line+6 );
  634.     dofwd(p);
  635.     log ('M', 'F', 'E', nullstr);      /* Log end of forwarding */
  636.   }
  637.  
  638.   while (deep >= 0) { fclose(ifl[deep]); deep--; }
  639.   if(p->mode is idle) return;
  640.   outstr("*** Done.\n");
  641. }
  642.  
  643. /*
  644.  *  Pass a sublist in the forwarding file.
  645.  */
  646.  
  647. passlst()
  648. {
  649.   fopts setbit fw_pass;
  650.   while (true)
  651.   {
  652.     if (nxtin(cport->line) is NULL) {fopts clrbit fw_pass; return;}
  653.     if (iseof(cport->line)) {fopts clrbit fw_pass; return;}
  654.   }
  655. }
  656.  
  657. /*
  658.  *  Set tnc parameters.
  659.  */
  660.  
  661. dopar()
  662. {
  663.   register PORTS *p;
  664.  
  665.   if ((p = findport(cport->opt2)) is NULL) { passlst(); return; }
  666.  
  667.   if (strlen(cport->fld[0]) > 3) if (!chktime()) { passlst(); return; }
  668.  
  669.   ioport(p);
  670.   while (nxtin(cport->line) isnt NULL)
  671.   {
  672.     if (iseof(cport->line)) { ioport(cport); return; }
  673.     onetnc(cport->line);
  674.   }
  675.   ioport(cport);
  676. }
  677.  
  678. /*
  679.  *  Get a line from the current port.
  680.  *  Handle disconnect, timeout, and ^F.
  681.  */
  682.  
  683. getln()
  684. {
  685.   while (!getdat());
  686.   if (port->mode & forced) fopts setbit fw_abort;
  687.   if (port->mode & gone) { distnc(); port->mode = idle; }
  688. }
  689.  
  690. /*
  691.  *  Eat the remote MailBox prompt.
  692.  */
  693.  
  694. eat()
  695. {
  696.   register char c;
  697.  
  698.   if (fwdtyp is 'D') c = ':'; else c = '>';
  699.   while(true) {
  700.     getln();
  701.     if (!(port->mode & remote)) return;
  702.     if (port->line[0] is '[') isbid();
  703.     if ((port->mode & remote) and (port->line[strlen(port->line) - 2] is c)) {
  704.       return;
  705.     }
  706.   } 
  707. }
  708.  
  709. /*
  710.  *  Connect to a remote Mailox.
  711.  *  Port mode idle at entry.
  712.  *  On return, port mode is remote if the connect worked, else idle.
  713.  */
  714.  
  715. cmb()
  716. {
  717.   port->flags setbit p_dotmr;
  718.   port->mode = remote;
  719.  
  720. /*
  721.  *  Execute the connect script.
  722.  */
  723.  
  724.   while(*script)
  725.   {
  726.     switch (*script++)
  727.     {
  728.       case 'C' :
  729.         contnc(script);
  730.         if (port->mode & idle) return;
  731.         if (port->dev is p_tnc) do
  732.         {
  733.           getln();
  734.           if (port->mode & idle) return;
  735.         }
  736.         while (!iscon(port->line));
  737.         break;
  738.  
  739.       case 'S' :
  740.         outstr(script);
  741.         break;
  742.  
  743.       case 'R' :
  744.         getln();
  745.         if (port->mode & idle) return;
  746.         strupr(port->line);
  747.         if (*script isnt '!')
  748.         if (!search(port->line, script, strlen(script)-1))
  749.           { distnc(); port->mode = idle; return; }
  750.         break;
  751.  
  752.        default: ;
  753.     }
  754.     while(*script++);  /* Move to next script line */
  755.   }
  756.  
  757. /*
  758.  *  In theory, now connected to MailBox. Eat login messge.
  759.  */
  760.  
  761.   eat();
  762.   if (!(port->mode & remote)) return;
  763.   if (bidok) {
  764.     outstr(vers);
  765.     eat();
  766.   }
  767. }
  768.  
  769. /*
  770.  *  Forward whatever messages go to this MailBox.
  771.  */
  772.  
  773. dofwd(p)
  774. PORTS *p;
  775. {
  776.   register char *st;
  777.  
  778.   st = nxtin(cport->line);
  779.   while (!iseof(cport->line) and (st isnt NULL))
  780.   {
  781.     ioport(cport);
  782.     parse();
  783.     ioport(p);
  784.     pcall (tcall, cport->fld[0]);
  785.  
  786.     if (findfwd(tcall, bfwd, bfwdn))
  787.     {
  788.       fmsg();
  789.       if (fopts & fw_tried) if (p->mode & idle)
  790.       {
  791.          p->mmhs->stat clrbit m_busy;
  792.          wt_mmhs();
  793.          passlst();
  794.          return;
  795.       }
  796.     }
  797.  
  798.     st = nxtin(cport->line);
  799.   }
  800. }
  801.  
  802. /*
  803.  *  Send the message text.
  804.  */
  805.  
  806. xmtmsg()
  807. {
  808.   register FILE *fl;
  809.  
  810.   sprintf(port->line, "%s%u", msgdir, port->mmhs->number);
  811.   if ((fl = fopen(port->line, "r")) is NULL) nofile(port->line); else
  812.   {
  813.     fseek(fl, (long)RECSIZE, 0);
  814.     while(fgets(tmp->scr, scrmax, fl) isnt NULL)
  815.     {
  816.       if (chkdis()) { fclose(fl); return false; }
  817.       outstr(tmp->scr);
  818.     }
  819.     fclose (fl);
  820.   }
  821.   if (fwdtyp is 'D')
  822.   {
  823.     outstr(".\n");
  824.     outstr("y\n");
  825.   }
  826.   else
  827.   {
  828.     outchar (cpmeof);
  829.     outchar ('\n');
  830.   }
  831.   return true;
  832. }
  833.  
  834. /*
  835.  *  Forward all messages TO or AT tcall
  836.  *  to the MailBox we are connected to.
  837.  */
  838.  
  839. fmsg()
  840. {
  841.   char *a, *b, *c;
  842.   char hcall[6];
  843.   register PORTS *p;
  844.   register word h;
  845.   register short i, ok, kill, extnr, kok, hasit;
  846.  
  847.   hasit = true;   /* just initialize it to something */
  848.  
  849.   p = port;
  850.   for (h = mfhs->last; h; h--)
  851.   {
  852.     if (s_flag & s_dv) begin_lock();
  853.     read_rec(mfl, h, (char *)p->mmhs);
  854.  
  855.     ok = (!(p->mmhs->stat & (m_bull|m_kill|m_read|m_fwd|m_hold|m_busy)));
  856. /*
  857.  *  Decide whether to forward this one.
  858.  */
  859.     if (ok)
  860.     {
  861.       if (p->mmhs->ext is 1)
  862.       {
  863.         ok = false;
  864.         for (i = 0; !ok and (i < p->mmhs->count); i++) if (p->mmhs->flag[i])
  865.           if (wcm(tcall, p->mmhs->call[i])) { ok = true; extnr = i; }
  866.       }
  867.       else if (*p->mmhs->bbs isnt ' ')
  868.       {
  869.         ok = wcm(tcall, p->mmhs->bbs);
  870.         if (!ok) if (p->mmhs->ext is 2)
  871.         {
  872.           c = p->mmhs->call[0];
  873.           while(!ok and ((c=strchr(c, '.')) isnt NULL))
  874.           {
  875.             c++;
  876.             fill(hcall, ' ', ln_call);
  877.             pcall(hcall, c);
  878.             ok = wcm(tcall, hcall);
  879.           }
  880.         }
  881.       }
  882.       else ok = wcm(tcall, p->mmhs->to);
  883.     }
  884.  
  885.     if (ok)
  886.     {
  887.       p->mmhs->stat setbit m_busy;
  888.       wt_mmhs();
  889.     }
  890.     if (s_flag & s_dv) end_lock();
  891.  
  892. /*
  893.  *  If we DO forward this one, forward this one.
  894.  */
  895.     if (ok)
  896.     {
  897.       if (fopts & fw_tiout) { wait (p->ftime); fopts clrbit fw_tiout; }
  898.       fopts setbit fw_tried;
  899.       if (p->mode & idle) cmb();
  900.       if (p->mode & idle) return;
  901.  
  902.       if (fwdtyp is 'D') prtx("mail $G\n");
  903.  
  904.       if (*p->mmhs->bbs is ' ') prtx("S$B $G < $P");
  905.       else if((hidok)and(p->mmhs->ext is 2)) prtx("S$B $G @ $h < $P");
  906.       else prtx("S$B $G @ $A < $P");
  907.  
  908.       if (bidok) if (*p->mmhs->bid isnt ' ') {
  909.         outstr(" $");
  910.         a = p->line;
  911.         b = p->mmhs->bid;
  912.         unbl(a, b, ln_bid);
  913.         outstr(p->line);
  914.       }
  915.       outchar('\n');
  916.       getln(); if (p->mode & idle) return;
  917.       if (bidok)
  918.       {
  919.         if(*p->line < ' ') { getln(); if(p->mode & idle) return; }
  920.         switch(*p->line)
  921.         {
  922.           case 'O': hasit = false;
  923.                     outstr(p->mmhs->title);
  924.                     outchar('\n'); break;
  925.           case 'N': hasit = true; break;
  926.           default : p->mmhs->stat clrbit m_busy;
  927.                     wt_mmhs();
  928.                     return;
  929.         }
  930.       }
  931.       else
  932.       {
  933.         hasit = false;        /* you'll want to send msg */
  934.         outstr(p->mmhs->title); outchar('\n');
  935.         if (fwdtyp isnt 'D')
  936.         {
  937.           getln(); if (p->mode & idle) return;
  938.         }
  939.       }
  940.       if (!hasit)
  941.       {
  942.         curtim();
  943.         if (port->dev is p_tnc) prtx(mm[4]);
  944.         if (!xmtmsg()) { fopts setbit fw_tiout; return;}
  945.       }
  946.       eat(); if (p->mode & idle){ fopts setbit fw_tiout; return; }
  947. /*
  948.  *  The message actually forwarded.
  949.  *  Kill it, mark it, or whatever.
  950.  */
  951.       sprintf(p->line, "%u %s", p->mmhs->number, path);
  952.       log ('M', 'F', ' ', p->line);
  953.  
  954.       kill = false;
  955.       kok = false;
  956. /*
  957.  *  If cc: list exists, mark this call as forwarded.
  958.  */
  959.       if (p->mmhs->ext is 1)
  960.       {
  961.         p->mmhs->flag[extnr] = false;
  962.         for (i = 0; i < p->mmhs->count; i++) if (p->mmhs->flag[i]) kok = true;
  963.       }
  964.  
  965.       if (!kok)
  966.       {
  967.         if ((p->mmhs->type is 'F') or (p->mmhs->type is 'B')
  968.           or (p->mmhs->ext is 1))
  969.         kill = s_param & s_fkill;
  970.         else kill = s_param & s_kill;
  971.       }
  972.  
  973.       if (kill) p->mmhs->stat setbit m_kill;
  974.       else if (!kok)
  975.       {
  976.         if ((p->mmhs->ext is 1) and (p->mmhs->type is 'B'))
  977.         p->mmhs->stat setbit m_bull;
  978.         else p->mmhs->stat setbit m_fwd;
  979.       }
  980.       p->mmhs->stat clrbit m_busy;
  981.       write_rec(mfl, p->mmhs->rn, (char *)p->mmhs);
  982.       makehdr2();
  983.     }
  984.   }
  985. }
  986.