/* * 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 #ifndef unknown_port # include #endif #include #include #include #ifdef unknown_port extern int errno; #endif #include #include #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); }