Logo Search packages:      
Sourcecode: maildrop version File versions  Download package

makemime.c

/*
** Copyright 2000-2001 Double Precision, Inc.  See COPYING for
** distribution information.
*/

#if   HAVE_CONFIG_H
#include "rfc2045_config.h"
#endif
#include    <sys/types.h>
#include    <sys/stat.h>
#include    <time.h>
#include    <stdio.h>
#include    <errno.h>
#include    <string.h>
#include    <signal.h>
#if   HAVE_STRINGS_H
#include    <strings.h>
#endif
#if   HAVE_UNISTD_H
#include    <unistd.h>
#endif
#include    <stdlib.h>
#include    <ctype.h>
#include    <pwd.h>
#include    <fcntl.h>
#include    <signal.h>
#include    "rfc2045.h"
#include    "rfc2045charset.h"
#if HAVE_UNISTD_H
#include    <unistd.h>
#endif
#if HAVE_SYS_WAIT_H
#include    <sys/wait.h>
#endif
#include    "numlib/numlib.h"

#if     HAS_GETHOSTNAME
#else
int gethostname(const char *, size_t);
#endif

static const char rcsid[]="$Id: makemime.c,v 1.11 2003/03/07 00:47:30 mrsam Exp $";

struct arg_list {
      struct arg_list *next;
      char *arg;
      } ;

/******************************************************************************

Open some file or a pipe for reading and writing.

******************************************************************************/

static FILE *openfile_or_pipe(const char *filename, const char *mode)
{
int   fd;
FILE  *fp;

      if (strcmp(filename, "-") == 0)     /* stdin or stdout */
            fd=dup( strcmp(mode, "r") ? 1:0);
      else if (*filename == '&')
            fd=dup( atoi(filename+1));    /* file descriptor */
      else fd=open(filename, (strcmp(mode, "r") ? O_WRONLY|O_CREAT|O_TRUNC:
                  O_RDONLY), 0666); /* or a file */
      if (fd < 0)
      {
            perror(filename);
            exit(1);
      }
      fp=fdopen(fd, mode);
      if (!fp)
      {
            perror("fdopen");
            exit(1);
      }
      return (fp);
}

/******************************************************************************

Open some file.  If we get a pipe, open a temporary file, and drain pipe's
contents into it.

******************************************************************************/

static FILE *openfile(const char *filename)
{
FILE  *fp=openfile_or_pipe(filename, "r");
int   fd=fileno(fp);
off_t orig_pos;

      if ((orig_pos=lseek(fd, 0L, SEEK_CUR)) == -1 ||
            lseek(fd, 0L, SEEK_END) == -1 ||
            lseek(fd, 0L, SEEK_CUR) == -1 ||
            lseek(fd, orig_pos, SEEK_SET) == -1)      /* Must be a pipe */
      {
      FILE *t=tmpfile();
      int   c;

            if (!t)
            {
                  perror("tmpfile");
                  exit(1);
            }

            while ((c=getc(fp)) != EOF)
                  putc(c, t);
            if (ferror(fp) || fflush(t)
                  || ferror(t) || fseek(t, 0L, SEEK_SET) == -1)
            {
                  perror("write");
                  exit(1);
            }
            fclose(fp);
            fp=t;
      }
      return (fp);
}

/******************************************************************************

Build argv/argc from a file.

******************************************************************************/

static void read_args(int *argcp, char ***argvp, const char *file)
{
FILE  *fp=openfile_or_pipe(file, "r");
struct arg_list *argfirst=0, *arglast=0, *argp;
char  buffer[BUFSIZ];
char  *p;
int   c;

      *argcp=0;
      while (fgets(buffer, sizeof(buffer), fp) != 0)
      {
      const char *q;

            if ((p=strchr(buffer, '\n')) != 0)
                  *p=0;
            else while ((c=getc(fp)) != '\n' && c != EOF)
                  ;     /* Just dump the excess */

            /* Skip the filler. */

            q=buffer;
            while (*q && isspace((int)(unsigned char)*q))
                  ++q;
            if (!*q)    continue;
            if (*q == '#')    continue;
            if (strcmp(buffer, "-") == 0) break;

            argp=(struct arg_list *)malloc(sizeof(struct arg_list)+1+
                  strlen(q));
            if (!argp)
            {
                  perror("malloc");
                  exit(1);
            }
            if (arglast)
                  arglast->next=argp;
            else
                  argfirst=argp;
            arglast=argp;
            ++*argcp;
            argp->next=0;
            argp->arg=strcpy((char *)(argp+1), q);
      }

      if ((*argvp=malloc(sizeof (char *) * (*argcp+1))) == 0)
      {
            perror("malloc");
            exit(1);
      }
      c=0;
      for (argp=argfirst; argp; argp=argp->next)
      {
            (*argvp)[c]= argp->arg;
            ++c;
      }
      (*argvp)[c]=0;
}

static void usage()
{
      fprintf(stderr,
"Usage:\n"
"  makemime -c type [-o file] [-e encoding] [-C charset] [-N name] \\\n"
"                   [-a \"Header: Contents\"] file\n"
"           -m [ type ] [-o file] [-e encoding] [-a \"Header: Contents\"] file\n"
"           -j [-o file] file1 file2\n"
"           @file\n"
"\n"
"   file:  filename    - read or write from filename\n"
"          -           - read or write from stdin or stdout\n"
"          &n          - read or write from file descriptor n\n"
"          \\( opts \\)  - read from child process, that generates [ opts ]\n"
"\n"
"Options:\n"
"\n"
"  -c type         - create a new MIME section from \"file\" with this\n"
"                    Content-Type: (default is application/octet-stream).\n"
"  -C charset      - MIME charset of a new text/plain section.\n"
"  -N name         - MIME content name of the new mime section.\n"
"  -m [ type ]     - create a multipart mime section from \"file\" of this\n"
"                    Content-Type: (default is multipart/mixed).\n"
"  -e encoding     - use the given encoding (7bit, 8bit, quoted-printable,\n"
"                    or base64), instead of guessing.  Omit \"-e\" and use\n"
"                    -c auto to set Content-Type: to text/plain or\n"
"                    application/octet-stream based on picked encoding.\n"
"  -j file1 file2  - join mime section file2 to multipart section file1.\n"
"  -o file         - write ther result to file, instead of stdout (not\n"
"                    allowed in child processes).\n"
"  -a header       - prepend an additional header to the output.\n"
"\n"
"  @file - read all of the above options from file, one option or\n"
"          value on each line.\n"
      );
      exit (0);
}

/******************************************************************************

The arguments are parsed into the following structure, as a tree.

******************************************************************************/
struct mimestruct {

      /*
      ** One or two input files.  We initialize either file or child,
      ** depending on the source being a file, or a child process.
      ** Later, we open a file pointer in either case.
      */

      const char *inputfile1, *inputfile2;
      struct mimestruct *inputchild1, *inputchild2;
      FILE *inputfp1, *inputfp2;
      pid_t child1, child2;

      /* Output file.  Defaults to "-", stdout */

      const char *outputfile;
      FILE  *outputfp;

            /* The handler and open functions */

      void (*handler_func)(struct mimestruct *);
      void (*open_func)(struct mimestruct *);

            /* The new mime type, and encoding (-e) */
      const char *mimetype;
      const char *mimeencoding;
      const char *textplaincharset;
      const char *contentname;

            /* A list of -a headers */
      struct arg_list *a_first, *a_last;
      } ;

static void createsimplemime(struct mimestruct *);
static void createmultipartmime(struct mimestruct *);
static void joinmultipart(struct mimestruct *);

static void opencreatesimplemime(struct mimestruct *);
static void opencreatemultipartmime(struct mimestruct *);
static void openjoinmultipart(struct mimestruct *);

/******************************************************************************

Recursively build the mimestruct tree.

******************************************************************************/

struct mimestruct *parseargs(int *argcp, char ***argvp)
{
struct mimestruct *m=malloc(sizeof(struct mimestruct));
int argc= *argcp;
char **argv= *argvp;

      if (!m)
      {
            perror("malloc");
            exit(1);
      }
      memset(m, 0, sizeof(*m));

      if (argc == 0 || argv[0][0] != '-') usage();

      if (strncmp(argv[0], "-c", 2) == 0)
      {
            m->handler_func= &createsimplemime;
            m->open_func= &opencreatesimplemime;
            if (argv[0][2])
            {
                  m->mimetype=argv[0]+2;
                  --argc;
                  ++argv;
            }
            else
            {
                  --argc;
                  ++argv;
                  if (argc && argv[0][0] != '-' && argv[0][0] != ')')
                  {
                        m->mimetype=argv[0];
                        --argc;
                        ++argv;
                  }
                  else
                        m->mimetype="application/octet-stream";
            }

            while (isspace((int)(unsigned char)*m->mimetype))
                  ++m->mimetype;
      }
      else if (strncmp(argv[0], "-m", 2) == 0)
      {
            m->handler_func= &createmultipartmime;
            m->open_func= &opencreatemultipartmime;
            if (argv[0][2])
            {
                  m->mimetype=argv[0]+2;
                  --argc;
                  ++argv;
            }
            else
            {
                  --argc;
                  ++argv;
                  if (argc && argv[0][0] != '-' && argv[0][0] != ')')
                  {
                        m->mimetype=argv[0];
                        --argc;
                        ++argv;
                  }
                  else
                        m->mimetype="multipart/mixed";
            }
            while (isspace((int)(unsigned char)*m->mimetype))
                  ++m->mimetype;
      }
      else if (strncmp(argv[0], "-j", 2) == 0)
      {
      const char *filename;

            m->handler_func= &joinmultipart;
            m->open_func= &openjoinmultipart;
            if (argv[0][2])
            {
                  filename=argv[0]+2;
                  --argc;
                  ++argv;
            }
            else
            {
                  --argc;
                  ++argv;
                  if (argc == 0)    usage();
                  filename=argv[0];
                  --argc;
                  ++argv;
            }

            while (isspace((int)(unsigned char)*filename))
                  ++filename;

            if (strcmp(filename, "(") == 0)
            {
                  m->inputchild2=parseargs(&argc, &argv);
                  if (argc == 0 || strcmp(argv[0], ")"))
                        usage();
                  --argc;
                  ++argv;
            }
            else
                  m->inputfile2=filename;
      }
      else
            usage();

      /* Handle common options */

      while (argc)
      {
            if (strncmp(argv[0], "-o", 2) == 0)
            {
            const char *f=argv[0]+2;

                  ++argv;
                  --argc;
                  if (*f == 0)
                  {
                        if (!argc)  usage();
                        f=argv[0];
                        ++argv;
                        --argc;
                  }
                  while (isspace((int)(unsigned char)*f))
                        ++f;
                  m->outputfile=f;
                  continue;
            }

            if (strncmp(argv[0], "-C", 2) == 0)
            {
                  char *f=argv[0]+2;

                  ++argv;
                  --argc;


                  if (*f == 0)
                  {
                        if (!argc)  usage();
                        f=argv[0];
                        ++argv;
                        --argc;
                  }
                  while (isspace((int)(unsigned char)*f))
                        ++f;
                  m->textplaincharset=f;
                  continue;
            }

            if (strncmp(argv[0], "-N", 2) == 0)
            {
                  char *f=argv[0]+2;

                  ++argv;
                  --argc;


                  if (*f == 0)
                  {
                        if (!argc)  usage();
                        f=argv[0];
                        ++argv;
                        --argc;
                  }
                  while (isspace((int)(unsigned char)*f))
                        ++f;
                  m->contentname=f;
                  continue;
            }

            if (strncmp(argv[0], "-e", 2) == 0)
            {
            char *f=argv[0]+2, *q;

                  ++argv;
                  --argc;

                  if (*f == 0)
                  {
                        if (!argc)  usage();
                        f=argv[0];
                        ++argv;
                        --argc;
                  }

                  for (q=f; *q; q++)
                        *q=tolower((int)(unsigned char)*q);

                  while (isspace((int)(unsigned char)*f))
                        ++f;

                  if (strcmp(f, "7bit") && strcmp(f, "8bit") &&
                        strcmp(f, "quoted-printable") &&
                        strcmp(f, "base64"))
                        usage();

                  m->mimeencoding=f;
                  continue;
            }

            if (strncmp(argv[0], "-a", 2) == 0)
            {
            char *f=argv[0]+2;
            struct arg_list *a;

                  ++argv;
                  --argc;

                  if (*f == 0)
                  {
                        if (!argc)  usage();
                        f=argv[0];
                        ++argv;
                        --argc;
                  }

                  while (isspace((int)(unsigned char)*f))
                        ++f;

                  a=malloc(sizeof(struct arg_list));
                  if (!a)
                  {
                        perror("malloc");
                        exit(1);
                  }
                  if (m->a_last)
                        m->a_last->next=a;
                  else  m->a_first=a;
                  m->a_last=a;
                  a->arg=f;
                  a->next=0;
                  continue;
            }
            break;
      }

      /* We must now have the input file argument */

      if (!argc)  usage();

      if (strcmp(argv[0], "(") == 0)
      {
            --argc;
            ++argv;
            m->inputchild1=parseargs(&argc, &argv);
            if (argc == 0 || strcmp(argv[0], ")"))
                  usage();
            --argc;
            ++argv;
      }
      else
      {
            m->inputfile1=argv[0];
            --argc;
            ++argv;
      }

      *argcp=argc;
      *argvp=argv;
      return (m);
}

/******************************************************************************

After we're done, terminate with a zero exit code if all child processes also
terminated with a zero exit code.  Otherwise, terminate with a non-zero exit
code thus propagating any child's non-zero exit code to parent.

******************************************************************************/

static void goodexit(struct mimestruct *m, int exitcode)
{
      if (m->outputfp && (fflush(m->outputfp) || ferror(m->outputfp)))
      {
            perror("makemime");
            exit(1);
      }

      /*
      ** Drain any leftover input, so that the child doesn't get
      ** a SIGPIPE.
      */

      while (m->inputfp1 && !feof(m->inputfp1) && !ferror(m->inputfp1))
            getc(m->inputfp1);

      while (m->inputfp2 && !feof(m->inputfp2) && !ferror(m->inputfp2))
            getc(m->inputfp2);

      if (m->inputfp1)
      {
            if (ferror(m->inputfp1))
            {
                  perror("makemime");
                  exitcode=1;
            }

            fclose(m->inputfp1);
      }
      if (m->inputfp2)
      {
            if (ferror(m->inputfp2))
            {
                  perror("makemime");
                  exitcode=1;
            }

            fclose(m->inputfp2);
      }

      while (m->child1 > 0 && m->child2 > 0)
      {
      int   waitstat;
      pid_t p=wait(&waitstat);

            if (p <= 0 && errno == ECHILD)      break;

            if (p == m->child1)
                  m->child1=0;
            else if (p == m->child2)
                  m->child2=0;
            else  continue;
            if (waitstat)     exitcode=1;
      }
      exit(exitcode);
}

int main(int argc, char **argv)
{
struct      mimestruct *m;

      signal(SIGCHLD, SIG_DFL);
      if (argc > 1 && argv[1][0] == '@')
            read_args(&argc, &argv, argv[1]+1);
      else if (argc > 1)
      {
            --argc;
            ++argv;
      }

      m=parseargs(&argc, &argv);
      if (argc)   usage();    /* Some arguments left */

      (*m->open_func)(m);
      (*m->handler_func)(m);
      goodexit(m, 0);
      return (0);
}

static int encode_outfp(const char *p, size_t n, void *vp)
{
      if (fwrite(p, n, 1, *(FILE **)vp) != 1)
            return -1;
      return 0;
}

static void createsimplemime(struct mimestruct *m)
{
struct      arg_list *a;
struct rfc2045_encode_info encode_info;

      /* Determine encoding by reading the file, as follows:
      **
      ** Default to 7bit.  Use 8bit if high-ascii bytes found.  Use
      ** quoted printable if lines more than 200 characters found.
      ** Use base64 if a null byte is found.
      */

      if (m->mimeencoding == 0)
      {
      long  orig_pos=ftell(m->inputfp1);

            if (orig_pos == -1)
            {
                  perror("ftell");
                  goodexit(m, 1);
            }

            m->mimeencoding=rfc2045_encode_autodetect_fp(m->inputfp1, 1);

            if (ferror(m->inputfp1)
                  || fseek(m->inputfp1, orig_pos, SEEK_SET)<0)
            {
                  perror("fseek");
                  goodexit(m, 1);
            }

            if (strcmp(m->mimetype, "auto") == 0)
                  m->mimetype=
                        strcmp(m->mimeencoding, "base64") == 0
                        ? (m->textplaincharset=0,
                           "application/octet-stream"):"text/plain";
      }

      for (a=m->a_first; a; a=a->next)
            fprintf(m->outputfp, "%s\n", a->arg);

      fprintf(m->outputfp, "Content-Type: %s", m->mimetype);
      if (m->textplaincharset && *m->textplaincharset)
      {
            const char *c;

            fprintf(m->outputfp, "; charset=\"");
            for (c=m->textplaincharset; *c; c++)
            {
                  if (*c != '"' && *c != '\\')
                        putc(*c, m->outputfp);
            }
            fprintf(m->outputfp, "\"");
      }

      if (m->contentname && *m->contentname)
      {
            const char *chset=m->textplaincharset ? m->textplaincharset
                  : "iso-8859-1";
            char *s;
            const char nameStr[]="name";
            int len;

            rfc2231_attrCreate(nameStr, m->contentname, chset,
                           NULL,
                           &len,
                           "");

            s=malloc(len);

            if (s)
            {
                  rfc2231_attrCreate(nameStr, m->contentname, chset,
                                 s,
                                 &len,
                                 "");

                  fprintf(m->outputfp, "; %s", s);
                  free(s);
            }
      }

      fprintf(m->outputfp, "\nContent-Transfer-Encoding: %s\n\n",
            m->mimeencoding);

      rfc2045_encode_start(&encode_info, m->mimeencoding,
                       &encode_outfp,
                       &m->outputfp);
      {
            char input_buf[BUFSIZ];
            int n;

            while ((n=fread(input_buf, 1, sizeof(input_buf),
                        m->inputfp1)) > 0)
            {
                  if ( rfc2045_encode(&encode_info, input_buf, n))
                        break;
            }

            rfc2045_encode_end(&encode_info);
      }
}

/******************************************************************************

Satisfy paranoia by making sure that the MIME boundary we picked does not
appear in the contents of the bounded section.

******************************************************************************/

static int tryboundary(struct mimestruct *m, FILE *f, const char *bbuf)
{
char  buf[BUFSIZ];
char  *p;
int   l=strlen(bbuf);
int   c;
long  orig_pos=ftell(f);

      if (orig_pos == -1)
      {
            perror("ftell");
            goodexit(m, 1);
      }

      while ((p=fgets(buf, sizeof(buf), f)) != 0)
      {
            if (p[0] == '-' && p[1] == '-' &&
                  strncmp(p+2, bbuf, l) == 0)
                  break;

            if ((p=strchr(buf, '\n')) != 0)
                  *p=0;
            else while ((c=getc(f)) != EOF && c != '\n')
                  ;
      }

      if (ferror(f) || fseek(f, orig_pos, SEEK_SET)<0)
      {
            perror("fseek");
            goodexit(m, 1);
      }

      return (p ? 1:0);
}

/******************************************************************************

Create a MIME boundary for some content.

******************************************************************************/

static const char *mkboundary(struct mimestruct *m, FILE *f)
{
pid_t pid=getpid();
time_t      t;
static unsigned n=0;
static char bbuf[NUMBUFSIZE*4];
char  buf[NUMBUFSIZE];

      time(&t);

      do
      {
            strcpy(bbuf, "=_");
            strcat(bbuf, libmail_str_size_t(++n, buf));
            strcat(bbuf, "_");
            strcat(bbuf, libmail_str_time_t(t, buf));
            strcat(bbuf, "_");
            strcat(bbuf, libmail_str_pid_t(pid, buf));
      } while (tryboundary(m, f, bbuf));
      return (bbuf);
}

static void createmultipartmime(struct mimestruct *m)
{
const char *b=mkboundary(m, m->inputfp1);
struct arg_list *a;
int   c;

      if (m->mimeencoding == 0)
            m->mimeencoding="8bit";

      for (a=m->a_first; a; a=a->next)
            fprintf(m->outputfp, "%s\n", a->arg);
      fprintf(m->outputfp, "Content-Type: %s; boundary=\"%s\"\n"
                  "Content-Transfer-Encoding: %s\n\n"
                  RFC2045MIMEMSG
                  "\n--%s\n",
            m->mimetype, b,
            m->mimeencoding,
            b);
      while ((c=getc(m->inputfp1)) != EOF)
            putc(c, m->outputfp);
      fprintf(m->outputfp, "\n--%s--\n", b);
}

static void joinmultipart(struct mimestruct *m)
{
const char *new_boundary;
char  *old_boundary=0;
int   old_boundary_len=0;
char  buffer[BUFSIZ];
char  *p;
int   c;

      do
      {
            new_boundary=mkboundary(m, m->inputfp1);
      } while (tryboundary(m, m->inputfp2, new_boundary));

      /* Copy the header */

      for (;;)
      {
            if (fgets(buffer, sizeof(buffer), m->inputfp2) == 0)
            {
                  buffer[0]=0;
                  break;
            }

            if (strcmp(buffer, "\r\n") == 0 ||
                buffer[0] == '\n' || strncmp(buffer, "--", 2) == 0)
                  break;

            if (strncasecmp(buffer, "content-type:", 13))
            {
                  fprintf(m->outputfp, "%s", buffer);
                  if ((p=strchr(buffer, '\n')) != 0)  continue;
                  while ((c=getc(m->inputfp2)) != EOF && c != '\n')
                        putc(c, m->outputfp);
                  continue;
            }

            if ((p=strchr(buffer, '\n')) == 0)
                  while ((c=getc(m->inputfp2)) != EOF && c != '\n')
                        ;

            p=strchr(buffer+13, ';');
            if (p)      *p=0;
            fprintf(m->outputfp, "Content-Type:%s; boundary=\"%s\"\n",
                  buffer+13, new_boundary);

            for (;;)
            {
                  c=getc(m->inputfp2);
                  if (c != EOF)     ungetc(c, m->inputfp2);
                  if (c == '\n' || !isspace((int)(unsigned char)c))
                        break;
                  while ((c=getc(m->inputfp2)) != EOF && c != '\n')
                        ;
            }
      }

      do
      {
            if (strncmp(buffer, "--", 2) == 0)
            {
                  if (old_boundary == 0)
                  {
                        old_boundary=malloc(strlen(buffer)+1);
                        if (!old_boundary)
                        {
                              perror("malloc");
                              exit(1);
                        }
                        strcpy(old_boundary, buffer);
                        if ((p=strchr(old_boundary, '\n')) != 0)
                        {
                              if (p > old_boundary && p[-1] == '\r')
                                    --p;
                              *p=0;
                        }
                        p=old_boundary+strlen(old_boundary);
                        if (p >= old_boundary+4 &&
                              strcmp(p-2, "--") == 0)
                              p[-2]=0;
                        old_boundary_len=strlen(old_boundary);
                  }


                  if (strncasecmp(buffer, old_boundary,
                        old_boundary_len) == 0)
                  {
                        if ((p=strchr(buffer, '\n')) != 0)
                              *p=0;
                        else while ((c=getc(m->inputfp2)) != '\n'
                              && c != EOF)
                              ;

                        c=strlen(buffer);
                        if (c > 0 && buffer[c-1] == '\r')
                              buffer[--c]=0;

                        if (c >= 4 && strcmp(buffer+(c-2), "--") == 0)
                              break;
                        fprintf(m->outputfp, "--%s\n",
                              new_boundary);
                        continue;
                  }
            }
            fprintf(m->outputfp, "%s", buffer);
            if ((p=strchr(buffer, '\n')) == 0)
                  while ((c=getc(m->inputfp2)) != '\n' && c != EOF)
                        ;
      } while (fgets(buffer, sizeof(buffer), m->inputfp2) != 0);

      fprintf(m->outputfp, "--%s\n", new_boundary);

      while ((c=getc(m->inputfp1)) != EOF)
            putc(c, m->outputfp);

      fprintf(m->outputfp, "\n--%s--\n", new_boundary);
      goodexit(m, 0);
}

/******************************************************************************

Open input from a child process

******************************************************************************/

static FILE *openchild(struct mimestruct *parent, struct mimestruct *child,
      pid_t *pidptr,
      int usescratch)
{
int   pipefd[2];
char  buf[NUMBUFSIZE];
char  buf2[NUMBUFSIZE+1];
FILE  *fp;

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

      *pidptr=fork();

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

      if (*pidptr == 0)
      {
            /* Duplicate pipe on stdout */

            close(pipefd[0]);
            close(1);
            dup(pipefd[1]);
            close(pipefd[1]);

            /* Close any input files opened by parent */

            if (parent->inputfp1)   fclose(parent->inputfp1);
            if (parent->inputfp2)   fclose(parent->inputfp2);

            /* Open, then execute the child process */

            (*child->open_func)(child);
            (*child->handler_func)(child);
            goodexit(child, 0);
      }
      close(pipefd[1]);

      /*
      ** Open the pipe by calling openfile(), automatically creating
      ** the scratch file, if necessary.
      */

      buf[0]='&';
      strcpy(buf+1, libmail_str_size_t(pipefd[0], buf2));

      fp= usescratch ? openfile(buf):openfile_or_pipe(buf, "r");
      close(pipefd[0]); /* fd was duped by openfile */
      return (fp);
}

static void openoutput(struct mimestruct *m)
{
      if (!m->outputfile)
            m->outputfile="-";

      m->outputfp= openfile_or_pipe(m->outputfile, "w");
}

static void openjoinmultipart(struct mimestruct *m)
{
      /* number two is the multipart section */
      if (m->inputchild2)
            m->inputfp2=openchild(m, m->inputchild2, &m->child2, 1);
      else
            m->inputfp2=openfile(m->inputfile2);


      if (m->inputchild1)
            m->inputfp1=openchild(m, m->inputchild1, &m->child1, 1);
      else
            m->inputfp1=openfile(m->inputfile1);
      openoutput(m);
}

static void opencreatesimplemime(struct mimestruct *m)
{
      if (m->inputchild1)
            m->inputfp1=openchild(m, m->inputchild1, &m->child1,
                  m->mimeencoding ? 0:1);
      else
            m->inputfp1= m->mimeencoding
                  ? openfile_or_pipe(m->inputfile1, "r")
                  : openfile(m->inputfile1);
      openoutput(m);
}

static void opencreatemultipartmime(struct mimestruct *m)
{
      if (m->inputchild1)
            m->inputfp1=openchild(m, m->inputchild1, &m->child1, 1);
      else
            m->inputfp1=openfile_or_pipe(m->inputfile1, "r");
      openoutput(m);
}


Generated by  Doxygen 1.6.0   Back to index