Back to index

courier  0.68.2
Defines | Functions
outbox.c File Reference
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>
#include <ctype.h>
#include <fcntl.h>
#include "outbox.h"
#include "imapwrite.h"
#include <sys/types.h>
#include <sys/stat.h>

Go to the source code of this file.

Defines

#define WEXITSTATUS(stat_val)   ((unsigned)(stat_val) >> 8)
#define WIFEXITED(stat_val)   (((stat_val) & 255) == 0)

Functions

int is_outbox (const char *mailbox)
const char * defaultSendFrom ()
static void errlogger (char *buffer)
int check_outbox (const char *message, const char *mailbox)
int imapd_sendmsg (const char *message, char **argv, void(*err_func)(char *))

Define Documentation

#define WEXITSTATUS (   stat_val)    ((unsigned)(stat_val) >> 8)

Definition at line 29 of file outbox.c.

#define WIFEXITED (   stat_val)    (((stat_val) & 255) == 0)

Definition at line 32 of file outbox.c.


Function Documentation

int check_outbox ( const char *  message,
const char *  mailbox 
)

Definition at line 75 of file outbox.c.

{
       char *argv[10];
       const char *from;

       if (!is_outbox(mailbox))
              return (0);

       from=defaultSendFrom();

       argv[1]="-oi";
       argv[2]="-t";
       argv[3]=NULL;
       if (from)
       {
              argv[3]="-f";
              argv[4]=(char *)from;
              argv[5]=NULL;
       }

       return (imapd_sendmsg(message, argv, errlogger));
}

Here is the call graph for this function:

Here is the caller graph for this function:

const char* defaultSendFrom ( )

Definition at line 52 of file outbox.c.

{
       const char *from;

       from=getenv("AUTHADDR");
       if (!from || !*from)
              from=getenv("AUTHENTICATED");
       if (from && !*from)
              from=NULL;

       return from;
}

Here is the caller graph for this function:

static void errlogger ( char *  buffer) [static]

Definition at line 69 of file outbox.c.

{
       fprintf(stderr, "ERR: error sending a message, user=%s: %s\n",
              getenv("AUTHENTICATED"), buffer);
}

Here is the caller graph for this function:

int imapd_sendmsg ( const char *  message,
char **  argv,
void(*)(char *)  err_func 
)

Definition at line 98 of file outbox.c.

{
       char buffer[512];
       int i;
       int ch;
       const char *from=defaultSendFrom();
       const char *hdrfrom;

       const char *prog;

       int pipefd[2];
       FILE *pipefp, *pipesendmail;
       pid_t pid, pid2;
       int waitstat;

       signal(SIGCHLD, SIG_DFL);
       signal(SIGPIPE, SIG_DFL);

       if (pipe(pipefd) < 0)
              write_error_exit("pipe");

       prog=getenv("SENDMAIL");
       if (!prog  || !*prog)
              prog="sendmail";


       pid=fork();

       if (pid < 0)
              write_error_exit("fork");

       if (pid > 0)  /* Parent reads err message, checks exit status */
       {
              i=0;
              close(pipefd[1]);
              pipefp=fdopen(pipefd[0], "r");
              if (pipefp == NULL)
                     write_error_exit("fdopen");
              while ((ch=getc(pipefp)) != EOF)
              {
                     if ((unsigned char)ch < ' ')
                            ch='/';
                     if (i < sizeof(buffer)-1)
                            buffer[i++]=ch;
              }
              fclose(pipefp);
              close(pipefd[0]);
              buffer[i]=0;

              while ((pid2=wait(&waitstat)) != pid)
                     if (pid2 < 0 && errno == ECHILD)
                            break;

              if (pid2 < 0 || !WIFEXITED(waitstat) || WEXITSTATUS(waitstat))
              {
                     if (buffer[0] == '\0')
                     {
                            buffer[0]=0;
                            strncat(buffer, prog, 128);

#ifdef WIFSIGNALED
#ifdef WTERMSIG
                            if (WIFSIGNALED(waitstat))
                                   sprintf(buffer+strlen(buffer),
                                          " terminated with signal %d",
                                          (int)WTERMSIG(waitstat));
                            else
#endif
#endif
                                   strcat(buffer, " failed without logging an error.  This shouldn't happen.");
                     }

                     (*err_func)(buffer);
                     return (-1);
              }
              return (0);
       }

       close(pipefd[0]);
       close(1);
       close(2);
       if (dup(pipefd[1]) != 1 || dup(pipefd[1]) != 2)
       {
              perror("dup(pipefd) failed");
              exit(1);
       }
       close(pipefd[1]);

       pipefp=fopen(message, "r");
       if (pipefp == NULL)
       {
              perror(message);
              exit(1);
       }

       /* Child forks again, second child process runs sendmail */

       if (pipe(pipefd) < 0)
       {
              perror("pipe");
              exit(1);
       }

       pid=fork();

       if (pid < 0)
       {
              perror("fork");
              exit(1);
       }

       if (pid == 0)
       {
              fclose(pipefp);
              close(pipefd[1]);
              close(0);
              errno=EINVAL;
              if (dup(pipefd[0]) != 0)
              {
                     perror("dup");
                     exit(1);
              }

              argv[0]=(char *)prog;

              execvp(prog, argv);
              perror(prog);
              exit(1);
       }

       close(pipefd[0]);

       pipesendmail=fdopen(pipefd[1], "w");
       if (!pipesendmail)
       {
              perror("fdopen");
              kill(pid, SIGTERM);
              close(pipefd[1]);
              exit(1);
       }

       if ((hdrfrom=getenv("HEADERFROM")) != NULL && *hdrfrom && from)
              fprintf(pipesendmail, "%s: %s\n", hdrfrom, from);
       while ((ch=getc(pipefp)) != EOF)
              putc(ch, pipesendmail);
       fclose(pipefp);
       fclose(pipesendmail);

       while ((pid2=wait(&waitstat)) != pid)
              if (pid2 < 0 && errno == ECHILD)
                     break;

       if (pid2 < 0 || !WIFEXITED(waitstat) || WEXITSTATUS(waitstat))
       {
              fprintf(stderr, "Message send FAILED.\n");
              exit(1);
       }
       exit(0);
       return (0);
}

Here is the call graph for this function:

Here is the caller graph for this function:

int is_outbox ( const char *  mailbox)

Definition at line 39 of file outbox.c.

{
       const char *p=getenv("OUTBOX");

       if (strncmp(mailbox, "./", 2) == 0)
              mailbox += 2;

       if (p == NULL || *p == 0 || strcmp(p, mailbox))
              return (0);

       return (1);
}

Here is the caller graph for this function: