home *** CD-ROM | disk | FTP | other *** search
- /*
- * mmdfcatmail.c
- *
- * Due to the behavior of MMDF (at least on SCO Unix), we can't use
- * listserv's /usr/server/catmail program within an aliased pipe. MMDF strips
- * the first "From " line in pipes, which listserv requires. It would
- * probably be best if listserv always used the From: or Sender: rfc822 header.
- *
- * This program is a frontend to catmail. It reads ahead in a mail steam and
- * picks the sender's address from the rfc822 header and assembles a fake
- * "From addr date" line and sends the whole mess to catmail. All command line
- * arguments are passed directly to catmail.
- *
- * To use this facility with MMDF, add lines such as this to your
- * /usr/mmdf/table/alias.list:
- *
- * listserv: server|/usr/server/mmdfcatmail -r -f
- * somelist: server|/usr/server/mmdfcatmail -L SOMELIST -f
- *
- * Note that your /usr/mmdf/mmdftailor file must have the "trusted" keyword
- * in the ALIAS entry for the alias.list file or pipes will not work:
- *
- * ALIAS table=lalias, nobypass, trusted
- *
- * Here is the don't sue me copyright:
- *
- * Copyright 1993 Mark Diekhans (markd@grizzly.com)
- * Permission to use, copy, modify, and distribute this software and its
- * documentation for any purpose and without fee is hereby granted, provided
- * that the above copyright notice appear in all copies. Mark Diekhans makes
- * no representations about the suitability of this software for any purpose.
- * It is provided "as is" without express or implied warranty.
- *
- * PORT: Ported by Tasos Kotsikonas (tasos@cs.bu.edu):
- * - CATMAIL is defined in ansi/start.h or nonansi/start.h
- * - used wait3() for certain systems instead of waitpid()
- * - if WAIT3_NEEDS_UNION is defined then use a union status variable
- * - STDIN_FILENO replaced by fileno(stdin)
- * - WIFEXITED and WEXITSTATUS adjusted according to the system
- */
-
-
- #include <stdio.h>
- #ifndef unknown_port
- # include <unistd.h>
- #endif
- #include <string.h>
- #include <ctype.h>
- #include <errno.h>
- #ifdef unknown_port
- extern int errno;
- #endif
- #include <sys/types.h>
- #include <sys/wait.h>
-
- #include "defs.h"
- #include "struct.h"
- #include "global.h"
- #ifdef __STDC__
- # include "ansi/start.h"
- #else
- # include "nonansi/start.h"
- #endif
- #ifndef WAIT3_NEEDS_UNION
- # if defined (sequent) || defined (stardent) || defined (stellar) || \
- defined (titan) || defined (unknown_port)
- # ifdef WEXITSTATUS
- # undef WEXITSTATUS
- # endif
- # ifdef WIFEXITED
- # undef WIFEXITED
- # endif
- # endif
- #endif
-
- #ifndef WEXITSTATUS
- # define WEXITSTATUS(stat) ((int)(((stat)>>8)&0377))
- #endif
- # ifndef WIFEXITED
- # define WIFEXITED(stat) (((int)((stat)&0377))==0)
- # endif
-
- BOOLEAN tty_echo = FALSE; /* -e option off */
- FILE *report = NULL; /* Progress report to the administrator */
-
- extern void extract_address (char *);
-
- /*
- * Maximum number of lines to read looking for "From:" or "Sender:".
- */
- #define MAX_HEADER_LINES 2048
-
- /*
- * Type used to save header fields in memory. Also structure used to
- * keep a list of these header lines.
- */
- typedef struct strEntry_t {
- struct strEntry_t *next;
- char line [1]; /* MUST BE LAST FIELD. */
- } strEntry_t;
-
- typedef struct {
- strEntry_t *head;
- strEntry_t *tail;
- } strList_t;
-
- /*
- * Save a line away in a dynamically allocated structure and added that
- * structure to a list.
- */
-
- void
- SaveLine (const char *line,
- strList_t *list)
- {
- strEntry_t *entry;
-
- entry = (strEntry_t *) malloc (sizeof (strEntry_t) + (strlen (line)));
- strcpy (entry->line, line);
- entry->next = NULL;
-
- if (list->tail == NULL) {
- list->head = entry;
- } else {
- list->tail->next = entry;
- }
- list->tail = entry;
- }
-
- /*
- * Start the catmail process.
- */
- pid_t
- StartCatmail (const char **argv,
- FILE **toPipe)
- {
- int pipefds [2];
- pid_t pid;
-
- *toPipe = NULL;
-
- if (pipe (pipefds) == 0) {
- *toPipe = fdopen (pipefds [1], "w");
- }
- if (*toPipe == NULL) {
- fprintf (stderr, "open of pipe failed: %s", strerror (errno));
- exit (1);
- }
-
- pid = fork ();
- if (pid < 0) {
- fprintf (stderr, "fork failed: %s", strerror (errno));
- exit (1);
- }
- if (pid > 0) {
- close (pipefds [0]);
- return pid;
- }
-
- close (pipefds [1]);
- close (fileno (stdin));
- if (dup2 (pipefds [0], fileno (stdin)) < 0) {
- fprintf (stderr, "dup to stdin failed: %s", strerror (errno));
- exit (1);
- }
-
- argv [0] = strrchr (CATMAIL, '/');
- if (argv [0] == NULL)
- argv [0] = CATMAIL;
- execv (CATMAIL, argv);
-
- fprintf (stderr, "exec of %s failed: %s", CATMAIL, strerror (errno));
- exit (1);
- }
-
- /*
- * Do actual work of copying stdin catmail process, filling in the missing
- * "From address Date" line.
- */
- main (int argc,
- const char **argv)
- {
- strList_t headerList;
- strEntry_t *entry;
- char line [MAX_LINE + 1];
- char fromAddress [MAX_LINE];
- char date [MAX_LINE];
- int linesRead = 0;
- #ifdef WAIT3_NEEDS_UNION
- union wait waitStat;
- #else
- int waitStat;
- #endif
- pid_t pid;
- FILE *toPipe;
-
- headerList.head = NULL;
- headerList.tail = NULL;
- fromAddress [0] = '\0';
- date [0] = '\0';
-
- /*
- * Search for the minimum headers we need and save away lines for later
- * output.
- */
- while (! ((fromAddress [0] != '\0') && (date [0] != '\0'))) {
- if (fgets (line, MAX_LINE, stdin) == NULL)
- break;
-
- SaveLine (line, &headerList);
-
- if (strncmp (line, "From:", 5) == 0) {
- strcpy (fromAddress, line + 5);
- extract_address (fromAddress);
- continue;
- }
- if (strncmp (line, "Sender:", 6) == 0) {
- strcpy (fromAddress, line + 6);
- extract_address (fromAddress);
- continue;
- }
- if (strncmp (line, "Date:", 5) == 0) {
- strcpy (date, line + 6);
- continue;
- }
- linesRead++;
- if (linesRead > MAX_HEADER_LINES)
- break;
- }
- if (fromAddress [0] == '\0') {
- fprintf (stderr, "No \"From:\" or \"Sender:\" header found\n");
- exit (1);
- }
- if (date [0] == '\0') {
- fprintf (stderr, "No \"date:\" header found\n");
- exit (1);
- }
-
- pid = StartCatmail (argv, &toPipe);
-
- /*
- * Output our madeup from line. (date has "\n").
- */
- fprintf (toPipe, "From %s %s", fromAddress, date);
-
- entry = headerList.head;
- while (entry != NULL) {
- fputs (entry->line, toPipe);
- entry = entry->next;
- }
-
- while (fgets (line, MAX_LINE, stdin) != NULL)
- fputs (line, toPipe);
-
- fclose (toPipe);
-
- #if defined (sequent) || defined (stardent) || defined (stellar) || \
- defined (titan) || defined (unknown_port)
- do {
- } while ((pid = wait3 (&waitStat, WNOHANG, NULL)));
- if (pid < 0) {
- fprintf (stderr, "wait3 failed: %s", strerror (errno));
- exit (1);
- }
- #else
- if (waitpid (pid, &waitStat, 0) < 0) {
- fprintf (stderr, "waitpid failed: %s", strerror (errno));
- exit (1);
- }
- #endif
-
- if (WIFEXITED (waitStat))
- exit (WEXITSTATUS (waitStat));
-
- fprintf (stderr, "%s terminated for unknown reasons\n", CATMAIL);
- exit (1);
-
- }
-
- /*
- * The library needs this guy.
- */
- int
- gexit (int exitcode)
- {
- exit (exitcode);
- }
-
-