Here's forward.c, much simpler and very straightforward:

while( more targets to go )
{
  parse to see what command to run
  open a pipe to the command
  send the header to the pipe
  send remaining lines from the database to the pipe
  close the pipe

  next target
}

It might look like I only picked a different bottleneck than before (here
it's the database, before it was the number of open pipes) but actually
this algorithm is just the database version as before, but with the pipe
openings happening once for each loop rather than all at once and stored
to a list, then going through the list and sending on all the pipes. My
goal was the eliminate the "start everything all at once" resource hog.

The only consumer of forward.c was pipe.c, so there was no trouble paring
it to the bone to match up with the pared down pipe.c. Note that the
function definition has changed. The new pipe.c I posted does not reflect
this change yet, but it's all alpha 1 anyways... I haven't tested
anything, although it looks correct and compiles cleanly ;-)

Aaron
/* $Id: forward.c,v 1.26 2003/03/17 16:04:08 roel Exp $
 * (c) 2000-2002 IC&S, The Netherlands
 *
 * takes care of forwarding mail to an external address */

#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <time.h>
#include "db.h"
#include "debug.h"
#include "list.h"
#include "bounce.h"
#include "forward.h"
#include "dbmail.h"
#include <string.h>
#include <stdlib.h>

extern struct list smtpItems;


/* For each of the addresses or programs in targets,
 * send out a copy of the message pointed to by msgidnr.
 *
 * Returns 0 if all went well, -1 if there was an error.
 * FIXME: there is no detail in the error reporting,
 * so there's no way to tell *which* targets failed...
 * */
int pipe_forward(u64_t msgidnr, struct list *targets, char *from, char *header, 
u64_t headersize)
{

  struct element *target=NULL;
  char *command=NULL;
  FILE *pipe=NULL;
  int err;
  field_t sendmail;
  char timestr[50];
  time_t td;
  struct tm tm;
 

  time(&td);              /* get time */
  tm = *localtime(&td);   /* get components */
  strftime(timestr, sizeof(timestr), "%a %b %e %H:%M:%S %Y", &tm);
  
  GetConfigValue("SENDMAIL", &smtpItems, sendmail);
  if (sendmail[0] == '\0')
    trace(TRACE_FATAL, "pipe_forward(): SENDMAIL not configured (see config 
file). Stop.");
  
  trace (TRACE_INFO,"pipe_forward(): delivering to %d external addresses", 
list_totalnodes(targets));

  if (!msgidnr)
    {
      trace(TRACE_ERROR,"pipe_forward(): got NULL as message id number");
      return -1;
    }
  
  target = list_getstart (targets);

  while (target != NULL)
    {
      if ((((char *)target->data)[0]=='|') || (((char *)target->data)[0]=='!'))
        {
        
          /* external pipe command */
          command = (char *)my_malloc(strlen((char *)(target->data)));
          if (!command)
            {
              trace(TRACE_ERROR,"pipe_forward(): out of memory");
              return -1;
            }
          strcpy (command, (char *)(target->data)+1); /* skip the pipe (|) sign 
*/
        }
      else
        {
          /* pipe to sendmail */
          command = (char *)my_malloc(strlen((char *)(target->data))+
                                            strlen(sendmail)+2); /* +2 for 
extra space and \0 */
          if (!command)
            {
              trace(TRACE_ERROR,"pipe_forward(): out of memory");
              return -1;
            }

          trace (TRACE_DEBUG,"pipe_forward(): allocated memory for external 
command call");
          sprintf (command, "%s %s",sendmail, (char *)(target->data));
        }

      trace (TRACE_INFO,"pipe_forward(): opening pipe to command %s", command);
        
      pipe = popen(command,"w"); /* opening pipe */
      my_free (command);
      command = NULL;

      if (pipe != NULL)
        {
          trace (TRACE_DEBUG,"pipe_forward(): call to popen() successfully 
opened pipe %d", fileno(pipe));
                        
          if (((char *)target->data)[0]=='!')
            {
              /* ! tells us to prepend an mbox style header in this pipe */
              trace (TRACE_DEBUG,"pipe_forward(): appending mbox style from 
header to pipe returnpath : %s", from);
              /* format: From<space>address<space><space>Date */
              fprintf (pipe, "From %s  %s\n", from, timestr);   
            }

          /* first send header if this is a direct pipe through */
          fprintf (pipe, "%s", header);
          trace (TRACE_DEBUG,"pipe_forward(): wrote header to pipe");  

          trace (TRACE_INFO,"pipe_forward(): sending message id number [%llu] 
to forward pipe", msgidnr);
                        
          err = ferror(pipe);

          trace (TRACE_DEBUG, "pipe_forward(): ferror reports"
              " %d, feof reports %d on pipe %d", err,
              feof (pipe),
              fileno (pipe));

          if (!err)
            {
              if (msgidnr!= 0)
                {
                  db_send_message_lines (pipe, msgidnr, -2, 1);
                }
            }

          trace (TRACE_DEBUG, "pipe_forward(): closing pipes");

          if (!ferror(pipe))
            {
              pclose (pipe);
              trace (TRACE_DEBUG, "pipe_forward(): pipe closed");
            }
          else
            {
              trace (TRACE_ERROR,"pipe_forward(): error on pipe");
            }
        }
      else 
        {
          trace (TRACE_ERROR,"pipe_forward(): Could not open pipe to" " 
[%s]",sendmail);
        }
      target = target->nextnode;
    }

  return 0;                     
}

Reply via email to