home *** CD-ROM | disk | FTP | other *** search
- /*#define PROCDEBUG*/
- /*
- * SENDMAIL / RMAIL
- *
- * (C) Copyright 1989-1990 by Matthew Dillon, All Rights Reserved.
- *
- * Domain-Path Enhancement by Henning Schmiedehausen. This is PD.
- * Changes copyright 1993 by Michael B. Smith. This is PD.
- * MAILLOG idea and changes by Jeff Van Epps. This is PD.
- *
- * SENDMAIL <file -f from -t to -s subject -c cc -b bcc -r
- * RMAIL user
- *
- * Example: Sendmail <datafile -froot
- *
- * From: line is automatically added but can be overriden by a From:
- * header in the file. stdin is made up of a list of headers, a blank
- * line, and then data until EOF.
- *
- * The -r option tells sendmail that this is incoming mail.
- * If av [0] begins with an 'r' for RMail instead of an 's' for
- * Sendmail, then the rmail argument format is used (rmail user),
- * as well as forcing -r.
- */
-
- #include "defs.h"
-
- #include <fcntl.h>
- #include <log.h>
- #include <time.h>
- #include <pwd.h>
- #include <config.h>
- #include <version.h>
- #include <owndevunit.h>
-
- IDENT (".31");
-
- #ifdef PROCDEBUG
- int
- debug_delay = 0;
-
- #define PROC(x) const char _proc [] = { x }; printf ("%s: enter\n", _proc)
- #define D(x) printf ("%s: ", _proc); if (debug_delay) Delay (debug_delay); printf x
- #else
- #define PROC(x)
- #define D(x)
- #endif
-
- Prototype char *DefaultNode;
- Prototype char *NodeName;
- Prototype char *DomainPath;
- Prototype int ROpt;
- Prototype int BounceOpt;
- Prototype int UserBounceOpt;
- Prototype int CcPmBounceOpt;
-
- Local void Usage (void);
- Local int brk (void);
- Local void myexit (void);
- Local struct Node *MakeNode (struct List *, char *);
- Local void MakeToFixNode (struct List *, char *, char *);
- Local int fixCallBack (const char *, struct List *, int);
- Local void IntegrateHeader (char *, int);
- Local void FromFixup (struct List *);
- Local void ToFixup (struct List *);
- Local void MakeToAddrNode (struct List *, char *);
- Local FILE *TermMailToUUCP (FILE *);
- Local FILE *SendMailTo (struct List *, FILE *);
- Local FILE *OneMailTo (char *, FILE *, int);
- Local FILE *OneMailToPipe (char *, FILE *);
- Local FILE *OneMailToUser (char *, FILE *);
- Local FILE *OneMailToFile (char *, FILE *);
- Local FILE *OneMailToUUCP (char *, char *, FILE *);
- Local void DumpHeaderInfo (FILE *, int, int, int, char *);
- Local void DumpHeader (FILE *, char *, struct List *, char *);
- Local void DumpHeaderLast (FILE *, char *, struct List *, char *);
- Local char *FindHeader (char *);
- Local void DumpCombineHeader (FILE *, char *, struct List *, char *);
- Local char *atime (time_t *);
- Local int GetHourOffset (char *);
- Local void PostPend (char *, int);
- Local void FindSource (const char *);
- Local char *BounceMail (FILE *, char *, char *, char *);
- Local void DoBounceMail (FILE *, char *, char *, char *, int);
-
- #define RCVR_UUCP 1
- #define RCVR_SENDMAIL 2
-
- #define REMOTE_FROM "remote from"
-
- char
- *CheckUser,
- *UserName,
- *RealName,
- *NodeName,
- *DomainPath = "",
- *DomainName,
- *TimeZoneName, /* All caps, ex: PST */
- *DefaultNode, /* for addr formats we don't understand */
- *MailLog = NULL; /* Where to log mail, when enabled */
-
- struct List
- RecvList, /* Received: */
- FromList, /* last one rules */
- ToList, /* To: */
- CcList, /* Cc: */
- BccList, /* Bcc: */
- XccList, /* list of actual mail to be sent */
- SubjList, /* Subject: */
- HdrList, /* other headers not specifically parsed */
- UUHostList; /* tracking mail sent to a given UUCP host */
-
- char
- ScrBuf [1024],
- ScrBuf2 [1024],
- TempFileBuf [256];
- int
- isRMail = 0, /* my basename() is r* */
- isSendMail = 1, /* opposite of isRMail */
- _bufsiz = 8192, /* for stdio */
- TopSeq, /* Top sequence no for Message-Id: */
- Notify = 0, /* if > 0, a local message was delivered */
- ROpt = 0, /* RMAIL flag */
- BounceOpt = 0, /* whether or not to generate domain bounces */
- UserBounceOpt, /* whether or not to generate user bounces */
- CcPmBounceOpt, /* whether or not to CC postmaster on bounces*/
- Strip_UUCP = 0, /* if addr ends with UUCP, then strip it off */
- SmartUUCP = 0, /* use FQDN in Received: headers, per RFC976 */
- LogMail = 0, /* Log mailsize to UULib:MailLog */
- ForceNoBounce,
- NoHdrOpt = 0; /* ignore headers opt */
-
- static char
- OrigFromLine [512],
- FromLine [512]; /* 'From ' line, if ROpt */
-
- time_t
- T; /* current time */
-
- struct Library
- *OwnDevUnitBase = NULL;
-
- /*
- ** MailLog stuff
- */
- static char
- FromSystem [128], /* system where mail originated */
- FromUser [128], /* use who originated mail */
- Feed [128]; /* system which passed mail to us */
- static int
- MailSize = 0; /* how big the mail message is */
-
- int
- main (int ac, char **av)
- {
- FILE
- *fi;
-
- PROC ("main");
-
- onbreak (brk);
-
- LogProgram = "Sendmail";
-
- NewList (&RecvList);
- NewList (&FromList);
- NewList (&ToList);
- NewList (&CcList);
- NewList (&BccList);
- NewList (&XccList);
- NewList (&SubjList);
- NewList (&HdrList);
- NewList (&UUHostList);
-
- atexit (myexit);
- if ((OwnDevUnitBase = OpenLibrary (ODU_NAME, 0)) == NULL) {
- fprintf (stderr, "Unable to open %s\n", ODU_NAME);
- exit (20);
- }
-
- UserName = GetUserName ();
- RealName = GetRealName ();
-
- T = time (NULL); /* for global timestamps */
- TopSeq = GetSequence (1); /* for message ids */
- D (("TopSeq = %ld\n", TopSeq));
-
- if (UserName == NULL) {
- fprintf (stderr, "Sendmail: UserName config entry not found!\n");
- ulog (-1, "UserName config missing");
- exit (20);
- }
-
- if (RealName == NULL) {
- fprintf (stderr, "Sendmail: RealName config entry not found!\n");
- ulog (-1, "RealName config missing");
- exit (20);
- }
-
- NodeName = FindConfig (NODENAME);
- CheckUser = FindConfig (CHECKUSER);
-
- D (("UserName '%s', RealName '%s', NodeName '%s'\n", UserName, RealName, NodeName));
-
- {
- char
- *ptr = GetConfig (MAILBOUNCE, "0");
-
- if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
- D (("BounceOpt set\n"));
- BounceOpt = 1;
- }
-
- ptr = GetConfig (USERBOUNCE, "0");
- if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
- D (("UserBounceOpt set\n"));
- UserBounceOpt = 1;
- }
-
- ptr = GetConfig (CCPMBOUNCE, "0");
- if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
- D (("CcPmBounceOpt set\n"));
- CcPmBounceOpt = 1;
- }
-
- ptr = GetConfig ("StripUUCP", "0");
- if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
- D (("StripUUCP set\n"));
- Strip_UUCP = 1;
- }
-
- ptr = GetConfig ("SmartUUCP", "0");
- if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
- D (("SmartUUCP set\n"));
- SmartUUCP = 1;
- }
-
- ptr = GetConfig ("LogMail", "0");
- if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y') {
- D (("LogMail set\n"));
- LogMail = 1;
-
- MailLog = GetConfig ("MailLog", "UUSpool:MailLog");
- }
- }
-
- if (NodeName == NULL) {
- fprintf (stderr, "Sendmail: NodeName config entry not found!\n");
- ulog (-1, "NodeName config missing");
- exit (20);
- }
-
- DomainName = FindConfig (DOMAINNAME);
- if (DomainName == NULL) {
- fprintf (stderr, "Sendmail: DomainName config entry not found! using .UUCP\n");
- DomainName = ".uucp";
- }
-
- D (("DomainName '%s'\n", DomainName));
-
- {
- char
- *str = GetConfig (DOMAINPATH, "N");
-
- if (str [0] == 'y' || str [0] == 'Y' || str [0] == '1') {
- D (("DomainPath set\n"));
- DomainPath = DomainName;
- }
- }
-
- DefaultNode = FindConfig (DEFAULTNODE);
- TimeZoneName = FindConfig (TIMEZONE);
-
- D (("DefaultNode '%s', TimeZone '%s'\n", DefaultNode, TimeZoneName));
-
- LoadAliases ();
-
- {
- char
- *ptr = av [0] + strlen (av [0]);
-
- /*
- * Skip path
- */
-
- while (ptr >= av[0] && *ptr != ':' && *ptr != '/')
- --ptr;
- ++ptr;
-
- if (*ptr == 'r' || *ptr == 'R') {
- isRMail = 1;
- isSendMail = 0;
- LogProgram = "RMail";
- }
- }
-
- if (isRMail) {
- if (ac <= 1) {
- MakeNode (&BccList, "MAILER-DAEMON");
- }
- else {
- int
- i;
-
- for (i = 1; i < ac; ++i)
- MakeNode (&BccList, av [i]);
- }
- UserName = "postmaster"; /* XXX */
- RealName = "Mr.Amiga"; /* XXX */
- ROpt = 1; /* no header processing */
- }
-
- if (isSendMail) {
- int
- i;
- char
- *arg;
-
- for (i = 1; i < ac; ++i) {
- arg = av [i];
- if (*arg != '-')
- Usage ();
- arg += 2;
- switch (arg [-1]) {
- case 'f':
- UserName = av [i + 1];
- if (strchr (UserName, '@') || strchr (UserName, '!'))
- MakeNode (&FromList, UserName);
- else {
- sprintf (ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
- MakeNode (&FromList, ScrBuf);
- }
- ++i;
- break;
- case 'R':
- RealName = av [++i];
- break;
- case 't':
- MakeNode (&ToList, av [++i]);
- break;
- case 'c':
- MakeNode (&CcList, av [++i]);
- break;
- case 'b':
- MakeNode (&BccList, av [++i]);
- break;
- case 's':
- MakeNode (&SubjList, av [++i]);
- break;
- case 'r':
- if (strcmp (arg, "aw") == 0)
- NoHdrOpt = 1;
- else
- ++ROpt;
- break;
- default:
- Usage ();
- }
- }
-
- if (LogMail) {
- char
- *p;
- /*
- ** For locally originated mail, record our system
- ** name and the sending user.
- */
- strcpy (FromSystem, NodeName);
- strcpy (Feed, NodeName);
- strcpy (FromUser, UserName);
- if (p = strchr (FromUser, '@')) {
- *p = '\0';
- strcpy (FromSystem, p + 1);
- }
- else
- if (p = strrchr (UserName, '!')) {
- strcpy (FromUser, p + 1);
- strncpy (FromSystem, UserName, p - UserName);
- FromSystem [p - UserName] = '\0';
- }
- }
- }
-
- D (("isRmail %ld, isSendMail %ld, ROpt %ld, NoHdrOpt %ld\n",
- isRMail, isSendMail, ROpt, NoHdrOpt));
-
- /*
- * Read headers from input file. Headers are not necessarily
- * contained on a single line. Maximum 4096 chars per header.
- */
-
- if (ROpt) {
- if (fgets (ScrBuf, sizeof (ScrBuf), stdin) == NULL) {
- D (("exit, no mail file!\n"));
- ulog (-1, "Error: empty mail file");
- exit (20);
- }
-
- if (strncmp (ScrBuf, ">From ", 6) && strncmp (ScrBuf, "From ", 5)) {
- ulog (-1, "Receive mail, expected 'From ', got %s", ScrBuf);
- }
- else {
- int
- ofst = ScrBuf [0] == '>' ? 1 : 0;
-
- strncpy (OrigFromLine, ScrBuf + ofst, sizeof (OrigFromLine));
- strcpy (FromLine, "From ");
- if (strstr (ScrBuf, REMOTE_FROM))
- PostPend (ScrBuf + (5 + ofst), 1);
-
- while (fgets (ScrBuf, sizeof (ScrBuf), stdin) && strncmp (ScrBuf, ">From ", 6) == 0) {
- strncpy (OrigFromLine, ScrBuf + 1, sizeof (OrigFromLine));
- if (strstr (ScrBuf, REMOTE_FROM))
- PostPend (ScrBuf + 6, 1);
- }
- strcpy (ScrBuf2, OrigFromLine + 5);
- PostPend (ScrBuf2, 0);
- if (LogMail) {
- /*
- ** For externally generated mail, parse the
- ** From line to find the Feed, FromSystem,
- ** and FromUser.
- */
- FindSource (FromLine);
- }
- }
- }
- else {
- ScrBuf [0] = '\n';
- if (NoHdrOpt == 0)
- if (fgets (ScrBuf, sizeof (ScrBuf), stdin) == NULL) {
- D (("exit, no mail file!\n"));
- ulog (-1, "Error: empty mail file");
- exit (20);
- }
- }
-
- if (NoHdrOpt == 0) {
- static char
- *Hdr = NULL;
- static int
- h_size = 0;
- int
- i = 0; /* index into Hdr */
-
- if (!Hdr) {
- h_size = 4096;
- Hdr = malloc (h_size);
- if (!Hdr) {
- ulog (-1, "Error: No memory!");
- exit (20);
- }
- }
-
- while (ScrBuf [0] != '\n') {
- char
- *ptr = ScrBuf;
-
- while (*ptr && *ptr != ' ' && *ptr != '\t' && *ptr != ':')
- ++ptr;
-
- if (*ptr == ':') { /* found new header */
- if (i) /* Dump old header */
- IntegrateHeader (Hdr, i);
- strcpy (Hdr, ScrBuf);
- i = strlen (Hdr);
- }
- else { /* append to existing header */
- int
- len = strlen (ScrBuf);
-
- if (i == 0)
- fprintf (stderr, "Expected a Header!\n");
-
- if ((i + len) >= h_size) {
- h_size += 1024;
- Hdr = realloc (Hdr, h_size);
- if (!Hdr) {
- ulog (-1, "Error: Not enough memory!");
- exit (20);
- }
- }
-
- strcpy (Hdr + i, ScrBuf);
- i = i + strlen (Hdr + i);
- }
-
- if (fgets (ScrBuf, sizeof (ScrBuf), stdin) == NULL)
- ScrBuf [0] = '\n';
- }
-
- if (i)
- IntegrateHeader (Hdr, i);
-
- if (ScrBuf [0] != '\n') {
- fprintf (stderr, "sendmail: no mail\n");
- ulog (0, "No Mail");
- exit (5);
- }
- }
-
- /*
- * Parse & fixup each To:, Cc:, and Bcc: field.
- *
- * From: we add the personal info arg from the password file
- * To: we expand any aliases
- *
- * OpenLog() : log optimization
- */
-
- OpenLog ();
- if (ROpt) {
- ToFixup (&BccList);
- }
- else {
- FromFixup (&FromList);
- ToFixup (&ToList);
- ToFixup (&CcList);
- ToFixup (&BccList);
- }
- CloseLog ();
-
- if (IsListEmpty (&XccList)) {
- ulog (-1, "Error: No destination specified!");
- D (("exit, Empty destination lists!\n"));
- exit (20);
- }
-
- /*
- * If no Subject: field add a dummy one
- */
-
- if (IsListEmpty (&SubjList))
- MakeNode (&SubjList, "<none>");
-
- if (IsListEmpty (&FromList)) {
- sprintf (ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
- MakeNode (&FromList, ScrBuf);
- }
-
- fi = SendMailTo (&XccList, stdin);
-
- if (fi && fi != stdin)
- fclose (fi);
-
- if (TempFileBuf [0])
- remove (TempFileBuf);
-
- UnLockFiles ();
-
- /*
- * Notify if T:MailRdy does not exist (created by us, deleted by
- * notify when notify exits). Prevents running multiple notifies.
- */
-
- if (Notify) {
- int
- fd = open ("T:MailRdy", O_RDONLY);
-
- if (fd < 0) {
- char
- *cmd;
-
- if (cmd = FindConfig (MAILREADYCMD)) {
- fd = open ("T:MailRdy", O_CREAT|O_TRUNC, 0666);
- if (fd >= 0)
- close (fd);
- sprintf (ScrBuf, "Run %s -x T:MailRdy", cmd);
- Execute (ScrBuf, 0, 0);
- }
- }
- else {
- close (fd);
- }
-
- /*
- * signal for update for any utilities that support it.
- */
- {
- struct MsgPort
- *port;
-
- Forbid ();
- if ((port = FindPort ("T:MailRdy")) && port->mp_SigTask)
- Signal (port->mp_SigTask, 1 << port->mp_SigBit);
- Permit ();
- }
- }
-
- return 0;
- }
-
- void
- myexit (void)
- {
- PROC ("myexit");
-
- UnLockFiles ();
-
- if (OwnDevUnitBase) {
- CloseLibrary (OwnDevUnitBase);
- OwnDevUnitBase = NULL;
- }
-
- D (("exit\n"));
- return;
- }
-
- void
- Usage (void)
- {
- fprintf (stderr,
- "Sendmail [-f user] [-t addr] [-c addr] [-b addr] [-s subj] [-r] [-raw] <file\n"
- "RMail user... <file\n"
- );
-
- exit (20);
- }
-
- int
- brk (void)
- {
- UnLockFiles ();
- return 0;
- }
-
- /*
- * Strips string and creates named node which is appended to the
- * given list.
- */
-
- struct Node *
- MakeNode (struct List *list, char *str)
- {
- struct Node
- *node;
- char
- *ptr;
-
- PROC ("MakeNode");
- D (("str '%s'\n", str));
-
- while (*str == ' ' || *str == '\t')
- ++str;
- for (ptr = str + strlen (str) - 1; ptr >= str && (*ptr == ' ' || *ptr == '\t'); --ptr)
- ;
- ++ptr;
- *ptr = 0;
- node = malloc (sizeof (struct Node) + strlen (str) + 1);
- if (!node) {
- ulog (-1, "MakeNode: no memory!");
- exit (20);
- }
- node->ln_Pri = 0;
- node->ln_Name = (char *) (node + 1);
- strcpy (node->ln_Name, str);
- AddTail (list, node);
-
- D (("exit\n"));
- return node;
- }
-
- /*
- * Ultimate to field , handles basic user security and expands aliases.
- */
-
- void
- MakeToFixNode (struct List *list, char *str, char *send)
- {
- char
- *ptr;
- int
- len,
- c;
-
- PROC ("MakeToFixNode");
- D (("str '%s', send '%s'\n", str ? str : "<none>", send ? send : "<none>"));
-
- while (str < send && (*str == ' ' || *str == '\t'))
- ++str;
- for (ptr = send - 1; ptr >= str && (*ptr == ' ' || *ptr == '\t'); --ptr)
- ;
- ++ptr;
-
- len = ptr - str;
- if (len < 0) {
- D (("exit, len < 0\n"));
- return;
- }
-
- /*
- * str [0..len-1]
- */
-
- c = str [len];
- str [len] = 0;
-
- if (ROpt) { /* disallow remote asking for special options */
- ulog (-1, "Received mail for %s", str);
- if (str [0] == '>' || str [0] == '<' || str [0] == '|') {
- ulog (-1, "bad user %s", str);
- D (("exit, bad user\n"));
- return;
- }
- }
-
- /*
- * expand aliases. If the str exists as an alias and the special
- * :: (do not expand alias in To: field) is used, then the name of
- * the alias is placed in the To: field.
- */
-
- if (AliasExists (str))
- ForceNoBounce = 1;
-
- if (UserAliasList (str, fixCallBack, list, 1)) {
- struct Node
- *node;
-
- sprintf (ScrBuf, "%s@%s%s", str, NodeName, DomainName);
-
- node = malloc (sizeof (struct Node) + strlen (ScrBuf) + 1);
- if (!node) {
- ulog (-1, "MakeToFixNode: no memory!");
- exit (30);
- }
- node->ln_Pri = 0;
- node->ln_Name = (char *) (node + 1);
- strcpy (node->ln_Name, ScrBuf);
- AddTail (list, node);
- D (("List 0x%lx, added '%s'\n", (long) list, ScrBuf));
- }
-
- ForceNoBounce = 0;
- str [len] = c;
-
- D (("exit\n"));
- return;
- }
-
- int
- fixCallBack (const char *user, struct List *list, int showto)
- {
- struct Node
- *node;
-
- PROC ("fixCallBack");
- D (("user '%s', showto %ld\n", user, showto));
-
- if (user [0] == '<') {
- FILE
- *fi = fopen (user + 1, "r");
- char
- *buf = malloc (256);
-
- if (fi == NULL) {
- ulog (-1, "Unable to open < file %s", user + 1);
- D (("exit, can't open '%s'\n", user + 1));
-
- return 0;
- }
- if (!buf) {
- ulog (-1, "fixCallBack: no memory!");
- exit (30);
- }
-
- while (fgets (buf, 256, fi)) {
- int
- i = 0,
- j;
-
- while (buf [i] == ' ' || buf [i] == '\t')
- ++i;
- if (buf [i] == 0 || buf [i] == '\n')
- continue;
- for (j = i; buf [j] && buf [j] != '\n' && buf [j] != ' ' && buf [j] != '\t'; ++j)
- ;
- buf [j] = 0;
- UserAliasList (buf, fixCallBack, list, showto);
- }
-
- fclose (fi);
- free (buf);
- D (("exit, read from file\n"));
-
- return 0;
- }
-
- if (showto)
- ulog (-1, "Sending mail to %s", user);
-
- if (user [0] == '\\')
- ++user;
-
- /*
- * add to Xcc (actual send list). If showto < 0 then the alias was
- * given to us for display (To: field display) purposes only and
- * should NOT be added to the Xcc list
- */
-
- if (showto >= 0) {
- node = malloc (sizeof (struct Node) + strlen (user) + 1);
- if (!node) {
- ulog (-1, "fixCallBack: no memory!");
- exit (30);
- }
- node->ln_Name = (char *) (node + 1);
- node->ln_Pri = ForceNoBounce;
- strcpy (node->ln_Name, user);
- AddTail (&XccList, node);
- D (("List 0x%lx (XccList) added '%s'\n", (long) &XccList, user));
- }
-
- /*
- * If an alias element is to be shown in the To: field of the
- * message, do so. If it is a local user with no qualifications,
- * then append our full domain name.
- *
- * do not show any > or | redirections
- */
-
- if (showto && *user != '|' && *user != '>') {
- int
- localFix = 1;
- char
- *ptr;
-
- for (ptr = user; *ptr; ++ptr) {
- if (*ptr == '!' || *ptr == '@' || *ptr == '%' || *ptr == ':') {
- localFix = 0;
- break;
- }
- }
- if (localFix)
- sprintf (ScrBuf, "%s@%s%s", user, NodeName, DomainName);
- else
- strcpy (ScrBuf, user);
-
- node = malloc (sizeof (struct Node) + strlen (ScrBuf) + 1);
- if (!node) {
- ulog (-1, "fixCallBack: No memory!");
- exit (30);
- }
- node->ln_Pri = 0;
- node->ln_Name = (char *) (node + 1);
- strcpy (node->ln_Name, ScrBuf);
- AddTail (list, node);
- D (("List 0x%lx added '%s'\n", (long) list, ScrBuf));
- }
-
- D (("exit\n"));
- return 0;
- }
-
- /*
- * Integrates a header
- */
-
- void
- IntegrateHeader (char *hdr, int len)
- {
- PROC ("IntegrateHeader");
-
- if (hdr [len - 1] == '\n') /* strip trailing newline */
- hdr [len - 1] = 0;
- D (("header '%s', len %ld\n", hdr, len));
-
- if (strnicmp (hdr, "From:", 5) == 0) {
- MakeNode (&FromList, hdr + 5);
- D (("exit, From\n"));
- return;
- }
-
- if (strnicmp (hdr, "To:", 3) == 0) {
- MakeNode (&ToList, hdr + 3);
- D (("exit, To\n"));
- return;
- }
-
- if (strnicmp (hdr, "Cc:", 3) == 0) {
- MakeNode (&CcList, hdr + 3);
- D (("exit, CC\n"));
- return;
- }
-
- if (strnicmp (hdr, "Bcc:", 4) == 0) {
- MakeNode (&BccList, hdr + 4);
- D (("exit, BCC\n"));
- return;
- }
-
- if (strnicmp (hdr, "Subject:", 8) == 0) {
- MakeNode (&SubjList, hdr + 8);
- D (("exit, Subject\n"));
- return;
- }
-
- if (strnicmp (hdr, "Received:", 9) == 0) {
- MakeNode (&RecvList, hdr + 9);
- D (("exit, Received\n"));
- return;
- }
-
- MakeNode (&HdrList, hdr);
-
- D (("exit\n"));
- return;
- }
-
- /*
- * Adds (personal info) to FromList based on passwd entry or, if
- * that is not available, from the Config entry 'RealName' or
- * ENV:REALNAME (env:REALNAME takes precedence)
- */
-
- void
- FromFixup (struct List *list)
- {
- struct Node
- *node,
- *nn;
- struct List
- tmpList;
-
- PROC ("FromFixup");
-
- NewList (&tmpList);
-
- while (node = RemHead (list)) {
- /*
- * FIXME. use pw_gecos/pw_real_name entry.
- */
- nn = malloc (sizeof (struct Node) + strlen (node->ln_Name) + strlen (RealName) + 16);
- if (!nn) {
- ulog (-1, "FromFixUp: no memory!");
- exit (30);
- }
- nn->ln_Name = (char *) (nn + 1);
- if (strlen (RealName) == 0)
- sprintf (nn->ln_Name, "%s", node->ln_Name);
- else
- sprintf (nn->ln_Name, "%s (%s)", node->ln_Name, RealName);
- free (node);
- AddTail (&tmpList, nn);
- }
-
- while (node = RemHead (&tmpList)) {
- AddTail (list, node);
- D (("List 0x%lx added '%s'\n", list, node->ln_Name));
- }
-
- D (("exit\n"));
- return;
- }
-
- /*
- * Converts an unparsed list of names into a list of single address
- * fields, removing any personal idents from the entries. These will
- * be recombined after processing when the data file is written out.
- *
- * Also expands sendmail aliases (UULib:Aliases) (HACK)
- */
-
- void
- ToFixup (struct List *list)
- {
- struct Node
- *node;
- struct List
- tmpList;
-
- PROC ("ToFixup");
-
- NewList (&tmpList);
-
- while (node = RemHead (list)) {
- char
- *ptr,
- *str = node->ln_Name;
-
- while (*str) { /* breakup fields by newline or comma */
- for (ptr = str; *ptr && *ptr != '\n' && *ptr != ','; ++ptr)
- ;
- MakeToAddrNode (&tmpList, str);
- str = ptr;
- while (*str == '\n' || *str == ',' || *str == ' ' || *str == '\t')
- ++str;
- }
- free (node);
- }
-
- while (node = RemHead (&tmpList)) {
- AddTail (list, node);
- D (("List 0x%lx added '%s'\n", list, node->ln_Name));
- }
-
- D (("exit\n"));
- return;
- }
-
- /*
- * Extracts a single name / address (comma or newline delimited)
- * field and creates a new node.
- */
-
- void
- MakeToAddrNode (struct List *list, char *str)
- {
- char
- *p1,
- *p2;
- int
- ns = 0; /* non-whitespace encountered */
-
- PROC ("MakeToAddrNode");
-
- for (p1 = str; *p1 && *p1 != ',' && *p1 != '\n'; ++p1) {
- if (*p1 == '(') { /* addr (name) OR (name) addr */
- if (ns) { /* addr (name) */
- MakeToFixNode (list, str, p1);
- }
- else {
- while (*p1 && *p1 != ',' && *p1 != '\n' && *p1 != ')')
- ++p1;
- if (*p1 == ')') {
- for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n'; ++p2)
- ;
- MakeToFixNode (list, p1 + 1, p2);
- }
- }
-
- D (("exit, '('\n"));
- return;
- }
-
- if (*p1 == '<') { /* <addr> */
- for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n' && *p2 != '>'; ++p2)
- ;
- if (*p2 == '>')
- MakeToFixNode (list, p1 + 1, p2);
-
- D (("exit, '<'\n"));
- return;
- }
-
- if (*p1 != ' ' && *p1 != '\t')
- ns = 1;
- }
-
- MakeToFixNode (list, str, p1);
-
- D (("exit\n"));
- return;
- }
-
- /*
- * Send mail to <recipiants>
- *
- * -Local mail
- * -Machine path (UUCP)
- */
-
- FILE *
- SendMailTo (struct List *list, FILE *fi)
- {
- struct Node
- *node;
-
- PROC ("SendMailTo");
-
- for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) {
- D (("List 0x%lx processing '%s'\n", (long) list, node->ln_Name));
- fi = OneMailTo (node->ln_Name, fi, node->ln_Pri);
- }
-
- fi = TermMailToUUCP (fi);
-
- D (("exit\n"));
- return fi;
- }
-
- FILE *
- OneMailTo (char *toaddr, FILE *rfi, int nobounce)
- {
- int
- i;
- char
- c;
- static char
- ToAddr [512],
- Buf [512],
- typeBuf [16],
- classBuf [16],
- addrBuf [128];
-
- PROC ("OneMailTo");
- D (("toaddr '%s', nobounce %ld\n", toaddr ? toaddr : "<none>", nobounce));
-
- if (toaddr [0] == '|') { /* pipe through command */
- rfi = OneMailToPipe (toaddr + 1, rfi);
- D (("exit, Pipe\n"));
- return rfi;
- }
-
- if (toaddr [0] == '>') { /* copy to file */
- rfi = OneMailToFile (toaddr + 1, rfi);
- D (("exit, File\n"));
- return rfi;
- }
-
- strncpy (ToAddr, toaddr, sizeof (ToAddr));
- ToAddr [sizeof (ToAddr) - 1] = 0;
-
- loop:
- for (i = 0; c = ToAddr [i]; ++i) {
- if (c == '!' || c == '%' || c == '@' || c == ':')
- break;
- }
-
- if (c == 0) { /* local name */
- rfi = OneMailToUser (ToAddr, rfi);
- D (("exit, User\n"));
- return rfi;
- }
-
- /*
- * Non-Local mail
- */
-
- i = ParseAddress (ToAddr, Buf, strlen (ToAddr));
- /*
- * Buf now contains ToAddr converted to a bang-path.
- * 'i' is the offset in Buf to the first bang (strlen (first-element))
- */
-
- if (DomainLookup (Buf, strlen (Buf), typeBuf, classBuf, addrBuf, nobounce)) {
- printf ("type %s class %s addr %s ROUTE %s\n", typeBuf, classBuf, addrBuf, Buf);
-
- /*
- * Note: the distinction between Mail Destination and
- * Mail Forwarder is:
- *
- * MD removes the first machine from the rmail line.
- *
- * MF does NOT.
- */
-
- if (stricmp (classBuf, "UU") == 0) {
- if (stricmp (typeBuf, "MD") == 0) {
- rfi = OneMailToUUCP (addrBuf, Buf + i + 1, rfi);
- D (("exit, UUCP MD (address '%s', isRMail %ld)\n", Buf + i + 1, isRMail));
- return rfi;
- }
- else {
- /* should be MF - Mail Forwarder */
- rfi = OneMailToUUCP (addrBuf, Buf, rfi);
- D (("exit, UUCP, type should be MF (is '%s')\n", typeBuf));
- return rfi;
- }
- }
- else
- if (stricmp (classBuf, "LL") == 0) { /* local mail, loop */
- for (i = 0; Buf [i] && Buf [i] != '!'; ++i)
- ;
-
- if (Buf [i] == 0) {
- strcpy (Buf + i, "postmaster");
- --i;
- }
- strcpy (ToAddr, Buf + i + 1);
-
- D (("local loop, addr '%s'\n", ToAddr));
- goto loop;
- }
- else
- if (stricmp (classBuf, "NOHOST") == 0) { /* negative match */
- BounceMail(rfi, "Host Unknown", "No known path to host", Buf);
- return rfi;
- }
- else {
- ulog (-1, "Unsupported domain class: %s", classBuf);
- fprintf (stderr, "Unsupported domain class: %s\n", classBuf);
- }
-
- D (("exit, unknown domain class for destination\n"));
- return rfi;
- }
-
- /*
- * handle bounced mail here. We only reach this point if BounceMode
- * was enabled (only way the DomainLookup() could return 0)
- *
- * Include the headers and first few lines of the message in the
- * bounced mail. Do not bounce mail from mailer-daemon
- */
-
- if (!BounceMail (rfi, "Host Unknown", "No known path to host", Buf)) {
- ulog (-1, "Could not find domain for %s, no mail sent", Buf);
- fprintf (stderr, "Unable to send mail to %s\n", Buf);
- }
-
- D (("exit\n"));
- return rfi;
- }
-
- char *
- BounceMail (FILE *rfi, char *errsubj, char *errtxt, char *name)
- {
- char
- *from;
-
- if (from = FindHeader ("From:")) {
- if (stristr (from, "mailer-daemon")) {
- /* prevent loops */
- ulog (-1, "Received mailer-daemon bounce: %s", from);
- }
- else {
- DoBounceMail(rfi, errsubj, errtxt, name, FALSE);
-
- if (CcPmBounceOpt) {
- /* Postmaster copy */
- DoBounceMail(rfi, errsubj, errtxt, name, TRUE);
- }
- }
- }
-
- return from;
- }
-
- void
- DoBounceMail (FILE *rfi, char *errsubj, char *errtxt, char *name, int ispmcopy)
- {
- char
- *from;
-
- if ((from = FindHeader ("Sender:")) || (from = FindHeader ("From:"))) {
- FILE
- *fo;
- long
- pos = ftell (rfi);
-
- /*
- * return mail to sender
- */
-
- strcpy (ScrBuf2, TmpFileName ("t:bounce"));
- if (fo = fopen (ScrBuf2, "w")) {
- fprintf (fo, "From: MAILER-DAEMON@%s%s\n", NodeName, DomainName);
-
- if (ispmcopy) {
- fprintf (fo, "To: postmaster@%s%s\n", NodeName, DomainName);
- }
- else {
- fprintf (fo, "To: %s\n", from);
- }
-
- fprintf (fo, "Subject: Returned mail: %s\n", errsubj);
- fprintf (fo, "Precedence: junk\n");
-
- if (ispmcopy) {
- fprintf (fo, "Sender: %s\n", from);
- }
- else {
- fprintf (fo, "Sender: postmaster@%s%s\n", NodeName, DomainName);
- }
-
- fprintf (fo, "\n ----- Error summary follows -----\n");
- fprintf (fo, "%s... %s\n", name, errtxt);
- fprintf (fo, "Message returned to sender.\n\n");
-
- if (ispmcopy) {
- fprintf (fo, " ----- Message headers follow -----\n");
-
- DumpHeaderInfo (fo, RCVR_SENDMAIL, 0, 0, "");
- }
- else {
- fprintf(fo, " ----- Unsent message follows -----\n");
-
- DumpHeaderInfo (fo, RCVR_SENDMAIL, 0, 0, "");
-
- while (fgets (ScrBuf, sizeof (ScrBuf), rfi)) {
- fputs (ScrBuf, fo);
- }
- }
- fclose (fo);
- sprintf (ScrBuf, "sendmail -R \"Mail Delivery Subsystem\" <%s", ScrBuf2);
- system (ScrBuf);
- }
-
- fseek (rfi, pos, 0);
- remove (ScrBuf2);
- }
-
- return;
- }
-
- FILE *
- OneMailToPipe (char *toaddr, FILE *rfi)
- {
- FILE
- *fi;
- char
- *ptr;
- static long
- pos = 0;
-
- PROC ("OneMailToPipe");
- D (("toaddr '%s'\n", toaddr ? toaddr : "<none>"));
-
- if (TempFileBuf [0] == 0) {
- strcpy (TempFileBuf, TmpFileName ("T:pipe"));
- fi = fopen (TempFileBuf, "w");
- if (fi == NULL) {
- ulog (-1, "Unable to open temp file %s for command: %s", TempFileBuf, toaddr);
- D (("exit, can't open '%s'\n", TempFileBuf));
- return rfi;
- }
- DumpHeaderInfo (fi, RCVR_SENDMAIL, 0, 1, "");
- pos = ftell (fi);
-
- while (fgets (ScrBuf, sizeof (ScrBuf), rfi)) {
- if (ScrBuf [0] == 'F' && strncmp (ScrBuf, "From ", 5) == 0)
- strins (ScrBuf, ">");
- fputs (ScrBuf, fi);
- }
- if (LogMail)
- MailSize = ftell (fi);
- fclose (fi);
- }
- strcpy (ScrBuf, toaddr);
-
- ptr = toaddr;
- if (strnicmp (toaddr, "run", 3) == 0) {
- ptr += 3;
- while (*ptr == ' ' || *ptr == '\t')
- ++ptr;
- }
- while (*ptr && *ptr != ' ' && *ptr != '\t')
- ++ptr;
-
- if (*ptr == 0)
- strcat(ScrBuf, " ");
-
- sprintf (ScrBuf + (ptr - toaddr + 1), "<%s %s", TempFileBuf, ptr);
- D (("Command: '%s'\n", ScrBuf));
-
- if (Execute (ScrBuf, 0, 0) == 0)
- ulog (-1, "Couldn't execute %s", ScrBuf);
-
- fi = fopen (TempFileBuf, "r");
- if (fi) {
- if (rfi != stdin)
- fclose (rfi);
- rfi = fi;
- fseek (rfi, pos, 0);
- }
- else {
- ulog (-1, "Couldn't reopen temp '%s', mail failed!", TempFileBuf);
- rfi = stdin;
- }
-
- D (("exit\n"));
- return rfi;
- }
-
- FILE *
- OneMailToUser (char *toaddr, FILE *rfi)
- {
- char
- filename [512],
- mybuf [512],
- mybuf2 [512],
- *p;
-
- PROC ("OneMailToUser");
- D (("toaddr '%s'\n", toaddr ? toaddr : "<none>"));
-
- for (p = toaddr; *p; p++) {
- if (strchr ("`'\"/: <>", *p)) {
- if (UserBounceOpt)
- BounceMail (rfi, "Invalid address", "Illegal character in username", toaddr);
- else
- ulog (-1, "%s: invalid character in name", toaddr);
- return (rfi);
- }
- }
-
- ++Notify;
-
- if (CheckUser) {
- FILE
- *fi;
- int
- retcode;
-
- strcpy (filename, TmpFileName ("T:pipe"));
- sprintf (mybuf, "%s \"%s\" >%s", CheckUser, toaddr, filename);
- if (retcode = system (mybuf)) {
- if (UserBounceOpt) {
- fi = fopen (filename, "r");
- if (fi == NULL) {
- ulog (-1, "Unable to open temp file %s for command: %s", filename, CheckUser);
- return rfi;
- }
-
- fgets (mybuf2, sizeof (mybuf2), fi);
- fclose (fi);
- unlink (filename);
-
- sprintf (mybuf, "CheckUser failed: %s", mybuf2);
- mybuf [strlen (mybuf) - 1] = '\0'; /* kill that darned newline */
- BounceMail (rfi, "Delivery failure", mybuf, toaddr);
- return rfi;
- }
- else {
- ulog (-1, "%s (Config file CheckUser command) returned %d", CheckUser, retcode);
- unlink (filename);
- return rfi;
- }
- }
-
- fi = fopen (filename, "r");
- if (fi == NULL) {
- ulog (-1, "Unable to open temp file %s for command '%s'", filename, CheckUser);
- return rfi;
- }
-
- fgets (mybuf, sizeof (mybuf), fi);
- fclose (fi);
- unlink (filename);
-
- mybuf [strlen (mybuf) - 1] = '\0'; /* kill that darned newline */
- toaddr = mybuf;
- }
- else {
- strcpy (ScrBuf, MakeConfigPath (UUMAIL, toaddr));
- toaddr = ScrBuf;
- }
-
- if (toaddr [0] != '*') {
- return OneMailToFile (toaddr, rfi);
- }
-
- /* error */
- if (UserBounceOpt)
- BounceMail (rfi, "User unknown", "User unknown", toaddr + 1);
- else
- ulog (-1, "No such user '%s', no mail sent", toaddr + 1);
-
-
- D (("exit, error from CheckUser '%s'\n", toaddr));
- return rfi;
- }
-
- FILE *
- OneMailToFile (char *tofile, FILE *rfi)
- {
- FILE
- *fo;
- static char
- DataFile [128];
- long
- pos;
-
- PROC ("OneMailToFile");
- D (("tofile '%s'\n", tofile ? tofile : "<none>"));
-
- strcpy (DataFile, tofile);
-
- LockFile (DataFile);
-
- fo = fopen (DataFile, "a");
- if (fo == NULL) {
- D (("couldn't open '%s'\n", DataFile));
- strcpy (DataFile, "T:MailOverflow");
- fo = fopen (DataFile, "a");
- if (fo)
- ulog (-1, "Could not append to %s, appending to %s", tofile, DataFile);
- else
- ulog (-1, "Can't append to anywhere! (%s)", tofile);
- }
-
- if (fo) {
- DumpHeaderInfo (fo, RCVR_SENDMAIL, 0, 1, "");
- pos = ftell (fo);
- while (fgets (ScrBuf, sizeof (ScrBuf), rfi)) {
- if (ScrBuf [0] == 'F' && strncmp (ScrBuf, "From ", 5) == 0)
- strins (ScrBuf, ">");
- if (LogMail)
- MailSize = ftell (fo);
- fputs (ScrBuf, fo);
- }
-
- if (ScrBuf [0] != '\n')
- fputs ("\n", fo);
- fclose (fo);
- if (rfi != stdin)
- fclose (rfi);
- rfi = fopen (DataFile, "r");
- fseek (rfi, pos, 0);
- }
-
- UnLockFile (DataFile);
-
- D (("exit\n"));
- return rfi;
- }
-
- /*
- * UUCP MAILER. Generate a control node for each destination. When the
- * mail is terminated, a batch file will be created for each destination
- * host.
- */
-
- FILE *
- OneMailToUUCP (char *toaddr, char *skipaddr, FILE *rfi)
- {
- UUHostNode
- *uh;
- struct Node
- *node;
- int
- i,
- j,
- hostLen,
- maxRMailLen = atoi (GetConfig (MAXRMAILLEN, "0"));
-
- PROC ("OneMailToUUCP");
- D (("toaddr '%s', skipaddr '%s'\n", toaddr ? toaddr : "<none>", skipaddr ? skipaddr : "<none>"));
-
- /*
- * find host, first element of 'toaddr'
- */
-
- loop:
- if (Strip_UUCP) {
- for (i = 0; toaddr [i] && toaddr [i] != '!'; ++i)
- /*for (i = 0; toaddr [i] && toaddr [i] != '!' && i != 7; ++i) CUTNODENAME */
- ;
- j = strlen (toaddr);
- if (j > 5 && toaddr [j - 5] == '.' && strnicmp (&toaddr [j - 4], "uucp", 4) == 0)
- i = j;
- }
- else
- for (i = 0; toaddr [i] && toaddr [i] != '!' && toaddr [i] != '.'; ++i)
- /*for (i = 0; toaddr [i] && toaddr [i] != '!' && toaddr [i] != '.' && i != 7; ++i) CUTNODENAME */
- ;
-
- D (("after search, i %ld, toaddr [i] = 0x%lx\n", i, (toaddr [i] & 0xff)));
-
- /*
- * search for UUHostNode in UUHostList, append to node list for
- * rmail line.
- */
-
- uh = NULL;
- for (node = UUHostList.lh_Head; node->ln_Succ; node = node->ln_Succ) {
- if (strlen (node->ln_Name) == i && strnicmp (node->ln_Name, toaddr, i) == 0) {
- uh = (UUHostNode *) node;
- break;
- }
- }
-
- D (("after HostList scan, uh = 0x%lx\n", uh));
-
- if (uh == NULL) {
- uh = malloc (sizeof (UUHostNode) + i + 1);
- if (!uh) {
- ulog (-1, "OneMailToUUCP: no memory!");
- exit (30);
- }
- uh->uh_Node.ln_Name = (char *) (uh + 1);
- uh->uh_Len = 10; /* 'C rmail \0' == 9 */
- uh->uh_NAddr = 0;
- strncpy (uh->uh_Node.ln_Name, toaddr, i);
- uh->uh_Node.ln_Name [i] = 0;
- AddTail (&UUHostList, &uh->uh_Node);
- NewList (&uh->uh_List);
- D (("List 0x%lx (UUHostList) added '%s'\n", &UUHostList, uh->uh_Node.ln_Name));
- }
-
- while (toaddr [i] && toaddr [i] != '!')
- ++i;
- if (toaddr [i] == '!')
- ++i;
-
- hostLen = strlen (toaddr + i) + strlen (skipaddr) + 3;
- D (("hostLen %ld\n", hostLen));
-
- if (uh->uh_NAddr > 0 && uh->uh_Len + hostLen > maxRMailLen) {
- rfi = TermMailToUUCP (rfi);
- goto loop;
- }
-
- node = malloc (sizeof (struct Node) + hostLen + 1);
- if (!node) {
- ulog (-1, "OneMailToUUCP: no memory!");
- exit (30);
- }
- node->ln_Pri = 0;
- node->ln_Name = (char *) (node + 1);
- AddTail (&uh->uh_List, node);
-
- if (toaddr [i]) {
- sprintf (node->ln_Name, "%s!%s", toaddr + i, skipaddr);
- }
- else {
- sprintf (node->ln_Name, "%s", skipaddr);
- }
- D (("List 0x%lx (uh_List) added '%s'\n", &uh->uh_List, node->ln_Name));
-
- uh->uh_NAddr++;
- uh->uh_Len += strlen (node->ln_Name) + 1; /* inc space */
-
- D (("exit\n"));
- return rfi;
- }
-
-
- FILE *
- TermMailToUUCP (FILE *rfi)
- {
- UUHostNode
- *uh;
- int
- pos;
- char
- *uux = GetConfigProgram (UUX),
- *receivers = NULL,
- *tmp;
- static FILE
- *ml = NULL;
-
- PROC ("TermMailToUUCP");
-
- /*
- ** build copy of file
- */
-
- if (TempFileBuf [0] == '\0') {
- FILE
- *fi;
-
- tmp = TmpFileName ("T:Mail");
- strcpy (TempFileBuf, tmp);
-
- fi = fopen (tmp, "w");
- if (!fi) {
- ulog (-1, "Error, Can't open %s", tmp);
- D (("exit, can't open '%s'\n", tmp));
- return rfi;
- }
-
- DumpHeaderInfo (fi, RCVR_UUCP, 1, 0, "");
- pos = ftell (fi);
-
- while (fgets (ScrBuf, sizeof (ScrBuf), rfi)) {
- if (ScrBuf [0] == 'F' && strncmp (ScrBuf, "From ", 5) == 0)
- strins (ScrBuf, ">");
- fputs (ScrBuf, fi);
- }
- if (LogMail)
- MailSize = ftell (fi);
- fclose (fi);
- if (rfi != stdin)
- fclose (rfi);
- fi = fopen (tmp, "r");
- fseek (fi, pos, 0);
- rfi = fi;
- }
- else
- tmp = TempFileBuf;
-
- if (LogMail && !ml) {
- ml = fopen (MailLog, "a");
- if (!ml)
- ulog (-1, "Could not open MailLog file '%s'", MailLog);
- }
-
- /*
- ** spool to deliver file
- */
-
- while (uh = (struct UUHostNode *) RemHead ((struct List *) &UUHostList)) {
- struct List
- *list;
- struct Node
- *node;
- char
- *sys,
- *cmd;
- int
- rslt,
- totlen = 0;
-
- sys = uh->uh_Node.ln_Name;
- D (("scanning for system '%s'\n", sys));
-
- list = &uh->uh_List;
-
- for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) {
- D (("looking at space for '%s'\n", node->ln_Name ? node->ln_Name : "<beats me>"));
- totlen += strlen (node->ln_Name) + 1;
- }
-
- totlen += strlen (uux) + strlen (sys) + strlen (tmp) + 50;
- D (("total calculated cmd length %ld\n", totlen));
-
- cmd = malloc (totlen);
- if (!cmd) {
- ulog (-1, "TermMailToUUCP: Failed, No memory for UUX!");
- return rfi;
- }
-
- if (ml) {
- receivers = malloc (totlen);
- if (!receivers) {
- ulog (-1, "TermMailToUUCP: No memory to log!");
- }
- }
-
- sprintf (cmd, "%s -g A %s \"%s!rmail", uux, tmp, sys);
-
- if (receivers)
- strcpy (receivers, "");
-
- for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) {
- strcat (cmd, " ");
- strcat (cmd, node->ln_Name);
- if (receivers) {
- strcat (receivers, " ");
- strcat (receivers, node->ln_Name);
- }
- }
- strcat (cmd, "\"");
-
- D (("actual command length %ld\n", strlen (cmd)));
- D (("actual command '%s'\n", cmd));
- ulog (2, "UUX command '%s'", cmd);
-
- rslt = system (cmd);
-
- D (("command result %ld\n", rslt));
- ulog (2, "UUX command result %ld", rslt);
-
- free (cmd);
- if (receivers) {
- /* LogMail and ml will also be set */
- fprintf (ml, "%s %s %s %ld %s%s\n",
- Feed,
- FromSystem,
- FromUser,
- MailSize,
- sys,
- receivers
- );
- fflush (ml);
- free (receivers);
- receivers = NULL;
- }
- }
-
- D (("exit\n"));
- return rfi;
- }
-
- void
- DumpHeaderInfo (FILE *fi, int rcvr, int resend, int local, char *prestr)
- {
- PROC ("DumpHeaderInfo");
- D (("rcvr %ld, resend %ld, local %ld, prestr '%s'\n",
- rcvr, resend, local, prestr ? prestr : "<none>"));
- /*
- * Write header info
- */
-
- if (ROpt && FromLine [0]) {
- if (resend && SmartUUCP == 0)
- fprintf (fi, "%s%s %s remote from %s%s\n", prestr, FromLine, atime(&T), NodeName, DomainPath);
- else
- fprintf (fi, "%s%s %s\n", prestr, FromLine, atime (&T));
- }
- else {
- if (local)
- fprintf (fi, "%sFrom %s %s\n", prestr, UserName, atime (&T));
- else
- if (SmartUUCP)
- fprintf (fi, "%sFrom %s@%s%s %s\n", prestr, UserName, NodeName, DomainName, atime (&T));
- else
- fprintf (fi, "%sFrom %s %s remote from %s%s\n", prestr, UserName, atime (&T), NodeName, DomainPath);
- }
-
- fprintf (fi, "%sReceived: by %s%s ("
- VERSION
- "/Amiga)\n\t id <%s@%s%s>; %s\n",
- prestr, NodeName, DomainName, SeqToName (TopSeq),
- NodeName, DomainName, atime (&T)
- );
-
- DumpHeader (fi, "Received:", &RecvList, prestr);
-
- if (ROpt == 0) {
- if (FindHeader ("Date:") == NULL) {
- D (("Added Date: header\n"));
- fprintf (fi, "%sDate: %s\n", prestr, atime (&T));
- }
-
- if (FindHeader ("Message-Id:") == NULL) {
- time_t
- t2 = T + 3600 * GetHourOffset (TimeZoneName);
- struct tm
- *ut;
-
- D (("Added Message-ID header\n"));
- ut = localtime (&t2);
-
- fprintf (fi, "%sMessage-Id: <%02d%02d%02d%02d%02d.%s@%s%s>\n",
- prestr,
- ut->tm_year % 100, ut->tm_mon + 1, ut->tm_mday,
- ut->tm_hour, ut->tm_min,
- SeqToName (TopSeq), NodeName, DomainName
- );
- }
- }
-
- /*
- * From:, To:, Cc:, Subject: (Bcc: never written to header),
- * and any other header fields
- */
-
- DumpHeader (fi, NULL, &HdrList, prestr);
- DumpHeaderLast (fi, "From:", &FromList, prestr);
- DumpCombineHeader (fi, "To:", &ToList, prestr);
-
- if (!IsListEmpty (&CcList))
- DumpCombineHeader (fi, "Cc:", &CcList, prestr);
-
- DumpHeaderLast (fi, "Subject:", &SubjList, prestr);
-
- fprintf (fi, "\n");
-
- D (("exit\n"));
- return;
- }
-
- void
- DumpHeader (FILE *fi, char *field, struct List *list, char *prestr)
- {
- struct Node
- *node;
-
- PROC ("DumpHeader");
- D (("field '%s', prestr '%s'\n", field ? field : "<none>", prestr ? prestr : "<none>"));
-
- if (IsListEmpty (list)) {
- D (("exit, empty list\n"));
- return;
- }
-
- for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) {
- if (field)
- fprintf (fi, "%s%s %s\n", prestr, field, node->ln_Name);
- else
- fprintf (fi, "%s%s\n", prestr, node->ln_Name);
- }
-
- D (("exit\n"));
- return;
- }
-
- void
- DumpHeaderLast (FILE *fi, char *field, struct List *list, char *prestr)
- {
- struct Node
- *node;
-
- PROC ("DumpHeaderLast");
- D (("field '%s', prestr '%s'\n", field ? field : "<none>", prestr ? prestr : "<none>"));
-
- if (IsListEmpty (list)) {
- D (("exit, empty list\n"));
- return;
- }
-
- if (node = list->lh_TailPred) {
- if (field)
- fprintf (fi, "%s%s %s\n", prestr, field, node->ln_Name);
- else
- fprintf (fi, "%s%s\n", prestr, node->ln_Name);
- D (("exit, returned %s\n", field ? field : "<none>"));
- }
- #ifdef PROCDEBUG
- else {
- D (("exit, empty node for field %s\n", field));
- }
- #endif
-
- return;
- }
-
- char *
- FindHeader (char *field)
- {
- struct Node
- *node;
- char
- *ptr = NULL;
- int
- len = strlen (field);
-
- PROC ("FindHeader");
- D (("field '%s'\n", field ? field : "<none>"));
-
- for (node = HdrList.lh_Head; node->ln_Succ; node = node->ln_Succ) {
- if (strnicmp (node->ln_Name, field, len) == 0) {
- ptr = node->ln_Name;
- break;
- }
- }
-
- if (ptr == NULL && !IsListEmpty (&FromList)) {
- node = FromList.lh_TailPred;
- if (strnicmp ("From:", field, len) == 0)
- ptr = node->ln_Name - len;
- }
-
- if (ptr == NULL && !IsListEmpty (&SubjList)) {
- node = SubjList.lh_TailPred;
- if (strnicmp ("Subject:", field, len) == 0)
- ptr = node->ln_Name - len;
- }
-
- if (ptr) {
- ptr += len;
- while (*ptr == ' ' || *ptr == '\t')
- ++ptr;
- }
-
- #ifdef PROCDEBUG
- if (!ptr) {
- D (("exit, returning NULL ptr\n"));
- }
- else {
- D (("exit, returning '%s'\n", ptr));
- }
- #endif
- return ptr;
- }
-
- void
- DumpCombineHeader (FILE *fi, char *field, struct List *list, char *prestr)
- {
- struct Node
- *node;
- int
- ci = 0;
-
- PROC ("DumpCombineHeader");
- D (("field '%s', prestr '%s'\n", field ? field : "<none>", prestr ? prestr : "<none>"));
-
- fprintf (fi, "%s%s ", prestr, field);
-
- if (IsListEmpty (list)) {
- fprintf (fi, "\n");
- D (("exit, empty list\n"));
- return;
- }
-
- for (node = list->lh_Head; node->ln_Succ; node = node->ln_Succ) {
- if (ci && ci + strlen (node->ln_Name) > 70) {
- fprintf (fi, ",\n%s\t", prestr);
- ci = 0;
- }
- if (ci)
- fprintf (fi, ", ");
- fprintf (fi, "%s", node->ln_Name);
- ci += strlen (node->ln_Name) + 2;
- }
- fprintf (fi, "\n");
-
- D (("exit\n"));
- return;
- }
-
- int
- GetHourOffset (char *tz)
- {
- int
- i;
-
- static struct {
- char *Name;
- int Hours;
- } TZAry [] = {
- "GMT", 0,
- "UT", 0,
- "UTC", 0,
- "PST", 8,
- "MST", 7,
- "CST", 6,
- "EST", 5,
- "AST", 4,
- "PDT", 7,
- "MDT", 6,
- "CDT", 5,
- "EDT", 4,
- "ADT", 3,
- "CET", -1,
- "MET", -1, /* alternate, please use CET */
- "MEZ", -1, /* alternate, please use CET */
- "CED", -2, /* central european daylight saving time */
- "CEDT", -2, /* alternate */
- "MED", -2, /* alternate, please use CED */
- "CEST", -2, /* alternate, please use CED */
- "MESZ", -2, /* alternate, please use CED */
- "EET", -2, /* ?? */
- "JST", -9,
- "HST", -10, /* Hawaiian Sandard Time */
- NULL, 0
- };
-
- PROC ("GetHourOffset");
- D (("tz = '%s'\n", tz));
-
- if (tz [0] == '+' || tz [0] == '-') {
- int
- i = ((tz [1] - '0') * 10) + (tz [2] - '0');
-
- /* Unfortunately, we don't deal with partial timezones - FIXME */
- if (tz [0] == '-')
- i = 0 - i;
-
- D (("exit, i %ld\n", i));
- return i;
- }
-
- for (i = 0; TZAry [i].Name; ++i) {
- if (strncmp (tz, TZAry [i].Name, 3) == 0) {
- D (("exit, %ld\n", TZAry [i].Hours));
- return TZAry [i].Hours;
- }
- }
-
- ulog (-1, "Unknown Timezone: %s", tz);
- fprintf (stderr, "Unknown Timezone: %s\n", tz);
-
- D (("exit, unknown, returning 6\n"));
- return 6;
- }
-
- void
- PostPend (char *str, int frend)
- {
- char
- *ptr;
-
- PROC ("PostPend");
- D (("str '%s', frend %ld\n", str, frend));
-
- if (frend) {
- ptr = str + strlen(str);
- while (ptr > str && *ptr != ' ' && *ptr != '\t') {
- if (*ptr == '\n')
- *ptr = 0;
- --ptr;
- }
- str = ptr + 1;
- }
-
- for (ptr = str; *ptr && *ptr != ' ' && *ptr != '\t' && *ptr != '\n'; ++ptr)
- ;
-
- if (frend)
- *ptr++ = '!';
- *ptr = 0;
- for (ptr = FromLine + 5; *ptr && *ptr != ' ' && *ptr != '\t'; ++ptr)
- ;
- strins (ptr, str);
-
- D (("exit\n"));
- return;
- }
-
- /*
- * Parse the from line and figure out Feed, FromSystem, FromUser.
- */
-
- void
- FindSource (const char *line)
- {
- char
- *path,
- *p,
- *templine,
- buf [256];
-
- templine = strdup (line);
- (void) strtok (templine, " ");
- path = strtok (NULL, " ");
- ParseAddress (path, buf, strlen (path));
- p = strrchr (buf, (int) '!');
- if (p == NULL) {
- strcpy (FromSystem, NodeName);
- strcpy (Feed, NodeName);
- strcpy (FromUser, path);
- }
- else {
- *p = '\0';
- strcpy (FromUser, p + 1);
- p = strrchr (buf, (int) '!');
- if (p == NULL)
- p = buf;
- else
- p++;
- strcpy (FromSystem, p);
- strcpy (Feed, strtok (buf, "! "));
- }
-
- free (templine);
-
- return;
- }
-