home *** CD-ROM | disk | FTP | other *** search
-
- /*
- * SENDMAIL / RMAIL
- *
- * (C) Copyright 1989-1990 by Matthew Dillon, All Rights Reserved.
- * Domain-Path Enhancement by Henning Schmiedehausen. 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 incomming 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.
- *
- * Hierarchical Spool Conversion 1 Dec 93,
- * Mike J. Bruins bruins@hal9000.apana.org.au
- */
-
- #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(".19");
-
- Prototype char *DefaultNode;
- Prototype char *NodeName;
- Prototype char *DomainPath;
- Prototype char ROpt;
- Prototype char BounceOpt;
-
- Local void Usage(void);
- Local int brk(void);
- Local void myexit(void);
- Local NODE *MakeNode(LIST *, char *);
- Local void MakeToFixNode(LIST *, char *, char *);
- Local void fixCallBack(char *, LIST *, int);
- Local void IntegrateHeader(char *, short);
- Local void FromFixup(LIST *);
- Local void ToFixup(LIST *);
- Local void MakeToAddrNode(LIST *, char *);
- Local FILE *TermMailToUUCP(FILE *);
- Local FILE *SendMailTo(LIST *, FILE *);
- Local FILE *OneMailTo(char *, FILE *, short);
- 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 *, LIST *, char *);
- Local char *FindHeader(char *);
- Local void DumpCombineHeader(FILE *, char *, LIST *, char *);
- Local char *atime(time_t *);
- Local int GetHourOffset(char *);
- Local void PostPend(char *, int);
- Local int EmptyList(LIST *);
-
-
- #define RCVR_UUCP 1
- #define RCVR_SENDMAIL 2
-
- char *UserName;
- char *RealName;
- char *NodeName;
- char *DomainPath = "";
- char CutNodeName[8];
- char *DomainName;
- char *TimeZoneName; /* All caps, ex: PST */
- char *DefaultNode; /* for addr formats we don't understand */
- LIST RecvList; /* Received: */
- LIST FromList; /* last one rules */
- LIST ToList; /* To: */
- LIST CcList; /* Cc: */
- LIST BccList; /* Bcc: */
- LIST XccList; /* list of actual mail to be sent */
- LIST SubjList; /* Subject: */
- LIST HdrList; /* other headers not specifically parsed */
- LIST UUHostList; /* tracking mail sent to a given UUCP host */
-
- char DiagnosticMessage[128];
- char ScrBuf[1024];
- char ScrBuf2[1024];
- char TempFileBuf[256];
- int Seq; /* UUCP sequence no */
- int TopSeq; /* Top sequence no for Message-Id: */
- char Notify;
- char ROpt; /* RMAIL flag */
- char BounceOpt;
- char ForceNoBounce;
- char NoHdrOpt; /* ignore headers opt */
- static char OrigFromLine[512];
- static char FromLine[512]; /* 'From ' line, if ROpt */
-
- int _bufsiz = 4096; /* for stdio */
- time_t T; /* current time */
- struct Library *OwnDevUnitBase;
-
- main(ac, av)
- char *av[];
- {
- short isRMail = 0;
- short isSendMail = 1;
- FILE *fi;
-
- onbreak(brk);
-
- 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) {
- printf("Unable to open %s\n", ODU_NAME);
- exit(20);
- }
-
- UserName = GetUserName();
- RealName = GetRealName();
-
- T = time(NULL);
- TopSeq = GetSequence(1);
-
- if (UserName == NULL) {
- puts("Sendmail: UserName config entry not found!");
- ulog(0, "UserName config missing");
- exit(1);
- }
- if (RealName == NULL) {
- puts("Sendmail: RealName config entry not found!");
- ulog(0, "RealName config missing");
- exit(1);
- }
-
- NodeName = FindConfig("NodeName");
- {
- char *ptr = GetConfig(MAILBOUNCE, "0");
- if (*ptr == '1' || *ptr == 'y' || *ptr == 'Y')
- BounceOpt = 1;
- }
- strncpy(CutNodeName, NodeName, 7);
- if (NodeName == NULL) {
- puts("Sendmail: NodeName config entry not found!");
- ulog(0, "NodeName config missing");
- exit(1);
- }
- DomainName = FindConfig("DomainName");
- if (DomainName == NULL) {
- puts("Sendmail: DomainName config entry not found! using .UUCP");
- DomainName = ".uucp";
- }
- {
- char *str = GetConfig(DOMAINPATH, "N");
- if (str[0] == 'y' || str[0] == 'Y' || str[0] == '1')
- DomainPath = DomainName;
- }
- DefaultNode = FindConfig(DEFAULTNODE);
- TimeZoneName = FindConfig("TimeZone");
-
- 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;
- }
- }
-
- if (isRMail) {
- if (ac <= 1) {
- MakeNode(&BccList, "Mailer-Daemon");
- } else {
- short 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) {
- short 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];
- 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();
- }
- }
- }
-
- /*
- * Read headers from input file. Headers are not necessarily
- * contained on a single line. Maximum 4096 chars per header.
- */
-
- if (ROpt) {
- fgets(ScrBuf, sizeof(ScrBuf), stdin);
- strcpy(OrigFromLine, ScrBuf);
- if (strncmp(ScrBuf, "From ", 5) != 0) {
- ulog(-1, "Receive mail, expected 'From ', got %s", ScrBuf);
- }
- strcpy(FromLine, "From ");
- PostPend(ScrBuf + 5, 1);
-
- while (fgets(ScrBuf, sizeof(ScrBuf), stdin) && strncmp(ScrBuf, ">From ", 6) == 0) {
- strcpy(OrigFromLine, ScrBuf + 1);
- PostPend(ScrBuf + 6, 1);
- }
- strcpy(ScrBuf2, OrigFromLine + 5);
- PostPend(ScrBuf2, 0);
- } else {
- ScrBuf[0] = '\n';
- if (NoHdrOpt == 0)
- fgets(ScrBuf, sizeof(ScrBuf), stdin);
- }
- if (NoHdrOpt == 0) {
- static char Hdr[4096];
- short i = 0; /* index into Hdr */
-
- 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 */
- if (i == 0)
- puts("Expected a Header!");
- 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') {
- puts("sendmail: no mail");
- ulog(0, "No Mail");
- exit(1);
- }
- }
-
- /*
- * 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 == 0)
- FromFixup(&FromList);
- if (ROpt) {
- ToFixup(&BccList);
- } else {
- ToFixup(&ToList);
- ToFixup(&CcList);
- ToFixup(&BccList);
- }
- CloseLog();
-
- /*
- * If no Subject: field add a dummy one
- */
-
- if (EmptyList(&SubjList))
- MakeNode(&SubjList, "");
-
- if (EmptyList(&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, NULL, NULL);
- }
- } else {
- close(fd);
- }
-
- /*
- * signal for update for any utilities that support it.
- */
- {
- MsgPort *port;
- Forbid();
- if ((port = FindPort("T:MailRdy")) && port->mp_SigTask)
- Signal(port->mp_SigTask, 1 << port->mp_SigBit);
- Permit();
- }
- }
- return(0);
- }
-
- void
- myexit()
- {
- UnLockFiles();
-
- if (OwnDevUnitBase) {
- CloseLibrary(OwnDevUnitBase);
- OwnDevUnitBase = NULL;
- }
- }
-
- void
- Usage()
- {
- printf(
- "Sendmail -f user [-t address -c address -b address -s subject -r]\n"
- "RMail user\n"
- );
- }
-
- int
- brk()
- {
- UnLockFiles();
- return(0);
- }
-
- /*
- * Strips string and creates named node which is appended to the
- * given list.
- */
-
- NODE *
- MakeNode(list, str)
- LIST *list;
- char *str;
- {
- NODE *node;
- char *ptr;
-
- while (*str == ' ' || *str == '\t')
- ++str;
- for (ptr = str + strlen(str) - 1; ptr >= str && (*ptr == ' ' || *ptr == '\t'); --ptr);
- ++ptr;
- *ptr = 0;
- node = malloc(sizeof(NODE) + strlen(str) + 1);
- node->ln_Pri = 0;
- node->ln_Name = (char *)(node + 1);
- strcpy(node->ln_Name, str);
- AddTail(list, node);
- return(node);
- }
-
- /*
- * Ultimate to field , handles basic user security and expands aliases.
- */
-
- void
- MakeToFixNode(list, str, send)
- LIST *list;
- char *str;
- char *send;
- {
- char *ptr;
- short len;
- short c;
-
- while (str < send && (*str == ' ' || *str == '\t'))
- ++str;
- for (ptr = send - 1; ptr >= str && (*ptr == ' ' || *ptr == '\t'); --ptr);
- ++ptr;
-
- len = ptr - str;
- if (len < 0)
- 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] == '|' || strchr(str, '/') || strchr(str, ':')) {
- ulog(-1, "SendMail, bad user %s", str);
- 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, (long)list, 1)) {
- NODE *node;
-
- sprintf(ScrBuf, "%s@%s%s", str, NodeName, DomainName);
-
- node = malloc(sizeof(NODE) + strlen(ScrBuf) + 1);
- node->ln_Pri = 0;
- node->ln_Name = (char *)(node + 1);
- strcpy(node->ln_Name, ScrBuf);
- AddTail(list, node);
- }
- ForceNoBounce = 0;
- str[len] = c;
- }
-
- void
- fixCallBack(user, list, showto)
- char *user;
- LIST *list;
- int showto;
- {
- NODE *node;
-
- 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);
- return;
- }
- while (fgets(buf, 256, fi)) {
- short i = 0;
- short 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, (long)list, showto);
- }
- fclose(fi);
- free(buf);
- return;
- }
-
- if (showto)
- ulog(-1, "Sendmail, 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(NODE) + strlen(user) + 1);
- node->ln_Name = (char *)(node + 1);
- node->ln_Pri = ForceNoBounce;
- strcpy(node->ln_Name, user);
- AddTail(&XccList, node);
- }
-
- /*
- * 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 != '>') {
- short 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(NODE) + strlen(ScrBuf) + 1);
- node->ln_Pri = 0;
- node->ln_Name = (char *)(node + 1);
- strcpy(node->ln_Name, ScrBuf);
- AddTail(list, node);
- }
- }
-
- /*
- * Integrates a header
- */
-
- void
- IntegrateHeader(hdr, len)
- char *hdr;
- short len;
- {
- if (hdr[len-1] == '\n') /* strip trailing newline */
- hdr[len-1] = 0;
-
- if (strncmp(hdr, "From:", 5) == 0) {
- MakeNode(&FromList, hdr + 5);
- return;
- }
- if (strncmp(hdr, "To:", 3) == 0) {
- MakeNode(&ToList, hdr + 3);
- return;
- }
- if (strncmp(hdr, "Cc:", 3) == 0) {
- MakeNode(&CcList, hdr + 3);
- return;
- }
- if (strncmp(hdr, "Bcc:", 4) == 0) {
- MakeNode(&BccList, hdr + 4);
- return;
- }
- if (strncmp(hdr, "Subject:", 8) == 0) {
- MakeNode(&SubjList, hdr + 8);
- return;
- }
- if (strncmp(hdr, "Received:", 9) == 0) {
- MakeNode(&RecvList, hdr + 9);
- return;
- }
- MakeNode(&HdrList, hdr);
- }
-
- /*
- * 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(list)
- LIST *list;
- {
- NODE *node;
- NODE *nn;
- LIST tmpList;
-
- NewList(&tmpList);
-
- while (node = RemHead(list)) {
- /*
- * FIXME. Fix getpwnam() and use pw_gecos entry.
- */
- nn = malloc(sizeof(NODE) + strlen(node->ln_Name) + strlen(RealName) + 16);
- nn->ln_Name = (char *)(nn + 1);
- sprintf(nn->ln_Name, "%s (%s)", node->ln_Name, RealName);
- free(node);
- AddTail(&tmpList, nn);
- }
- while (node = RemHead(&tmpList))
- AddTail(list, node);
- }
-
- /*
- * 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(list)
- LIST *list;
- {
- NODE *node;
- LIST tmpList;
-
- NewList(&tmpList);
-
- while (node = RemHead(list)) {
- char *str = node->ln_Name;
- char *ptr;
-
- 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);
- }
-
- /*
- * Extracts a single name / address (comma or newline delimited)
- * field and creates a new node.
- */
-
- void
- MakeToAddrNode(list, str)
- LIST *list;
- char *str;
- {
- char *p1, *p2;
- short ns = 0; /* non-whitespace encountered */
-
- 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);
- }
- }
- return;
- }
-
- if (*p1 == '<') { /* <addr> */
- for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n' && *p2 != '>'; ++p2);
- if (*p2 == '>')
- MakeToFixNode(list, p1 + 1, p2);
- return;
- }
- if (*p1 != ' ' && *p1 != '\t')
- ns = 1;
- }
- MakeToFixNode(list, str, p1);
- }
-
-
- /*
- * Send mail to <recipiants>
- *
- * -Local mail
- * -Machine path (UUCP)
- *
- * NOTE: now groups mail
- */
-
- FILE *
- SendMailTo(list, fi)
- LIST *list;
- FILE *fi;
- {
- NODE *node;
-
- for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ)
- fi = OneMailTo(node->ln_Name, fi, node->ln_Pri);
- fi = TermMailToUUCP(fi);
- return(fi);
- }
-
- FILE *
- OneMailTo(toaddr, rfi, nobounce)
- char *toaddr;
- FILE *rfi;
- short nobounce;
- {
- short i;
- char c;
- static char ToAddr[512];
- static char Buf[512];
- static char typeBuf[16];
- static char classBuf[16];
- static char addrBuf[128];
-
- if (toaddr[0] == '|') /* pipe through command */
- return(OneMailToPipe(toaddr + 1, rfi));
- if (toaddr[0] == '>') /* copy to file */
- return(OneMailToFile(toaddr + 1, 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 */
- return(OneMailToUser(ToAddr, rfi));
-
- /*
- * Non-Local mail
- */
-
- i = ParseAddress(ToAddr, Buf, strlen(ToAddr));
- if (DomainLookup(Buf, strlen(Buf), typeBuf, classBuf, addrBuf, nobounce)) {
- printf("type %s class %s addr %s ROUTE %s\n", typeBuf, classBuf, addrBuf, Buf);
-
- /*
- * Note distinction between mail destination and mail forwarder.
- * mail destination removes the first machine from the rmail line
- * mail forwarder does NOT
- */
-
- if (strcmpi(classBuf, "UU") == 0) {
- if (strcmpi(typeBuf, "MD") == 0)
- return(OneMailToUUCP(addrBuf, Buf + i + 1, rfi));
- else
- return(OneMailToUUCP(addrBuf, Buf, rfi));
- } else if (strcmpi(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);
- goto loop;
- } else {
- ulog(-1, "Unsupported domain class: %s", classBuf);
- printf("Unsupported domain class: %s\n", classBuf);
- }
- return(rfi);
- } else {
- char *from;
-
- /*
- * 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 (from = FindHeader("From:")) {
- if (strstr(from, "mailer-daemon") || strstr(from, "MAILER-DAEMON")) {
- ulog(-1, "Received mailer-daemon bounce: %s", from);
- } else {
- if ((from = FindHeader("Sender:")) || (from = FindHeader("From:"))) {
- FILE *fo;
- long pos = ftell(rfi);
- short maxlines = 10;
-
- /*
- * return mail to sender
- */
-
- strcpy(ScrBuf2, TmpFileName("t:bounce"));
- if (fo = fopen(ScrBuf2, "w")) {
- fprintf(fo, "From: MAILER-DAEMON@%s%s (mailer-daemon)\n", NodeName, DomainName);
- fprintf(fo, "To: %s\n", from);
- fprintf(fo, "Subject: Returned mail: host unknown\n");
- fprintf(fo, "Precedence: junk\n");
- fprintf(fo, "Sender: postmaster@%s%s (Mr-Amiga)\n", NodeName, DomainName);
- fprintf(fo, "\n");
- fprintf(fo, "%s%s is unable to resolve: %s\n", NodeName, DomainName, Buf);
- fprintf(fo, "message returned to sender:\n\n");
-
- DumpHeaderInfo(fo, RCVR_SENDMAIL, 0, 0, ":");
-
- fprintf(fo, "a few lines of the Bounced Message follows:\n");
- while (maxlines && fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
- fputs(ScrBuf, fo);
- --maxlines;
- }
- if (maxlines)
- fprintf(fo, "...\n\n");
- fclose(fo);
- sprintf(ScrBuf, "sendmail <%s", ScrBuf2);
- system(ScrBuf);
- }
- fseek(rfi, pos, 0);
- remove(ScrBuf2);
- }
- }
- } else {
- ulog(-1, "Could not find domain for %s, no mail sent", Buf);
- printf("Unable to send mail to %s\n", Buf);
- }
- return(rfi);
- }
- }
-
-
- FILE *
- OneMailToPipe(toaddr, rfi)
- char *toaddr;
- FILE *rfi;
- {
- FILE *fi;
- char *ptr;
- static long pos;
-
- 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);
- return(rfi);
- }
- DumpHeaderInfo(fi, RCVR_SENDMAIL, 0, 1, "");
- pos = ftell(fi);
- #ifdef NOTDEF /* removed */
- if (ROpt) {
- if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
- fputs(ScrBuf, fo);
- }
- #endif
- while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
- if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
- strins(ScrBuf, " ");
- fputs(ScrBuf, fi);
- }
- fclose(fi);
- }
- strcpy(ScrBuf, toaddr);
-
- ptr = toaddr;
- if (strncmpi(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);
- if (Execute(ScrBuf, NULL, NULL) == 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;
- }
- return(rfi);
- }
-
- FILE *
- OneMailToUser(toaddr, rfi)
- char *toaddr;
- FILE *rfi;
- {
- ++Notify;
- strcpy(ScrBuf, MakeConfigPath(UUMAIL, toaddr));
- return(OneMailToFile(ScrBuf, rfi));
- }
-
- FILE *
- OneMailToFile(tofile, rfi)
- char *tofile;
- FILE *rfi;
- {
- FILE *fo;
- static char DataFile[128];
- long pos;
-
- strcpy(DataFile, tofile);
-
- LockFile(DataFile);
- fo = fopen(DataFile, "a");
- if (fo == NULL) {
- 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);
- #ifdef NOTDEF
- if (ROpt) {
- if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
- fputs(ScrBuf, fo);
- }
- #endif
- while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
- if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
- strins(ScrBuf, " ");
- 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);
- 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(toaddr, skipaddr, rfi)
- char *toaddr;
- char *skipaddr;
- FILE *rfi;
- {
- UUHostNode *uh;
- struct Node *node;
- short i;
- int hostLen;
- int maxRMailLen = atoi(GetConfig(MAXRMAILLEN, "0"));
-
- /*
- * find host, first element of 'toaddr'
- */
-
- loop:
- for (i = 0; toaddr[i] && toaddr[i] != '!' && toaddr[i] != '.' && i != 7; ++i);
-
- /*
- * search for UUHostNode in UUHostList, append to node list for
- * rmail line.
- */
-
- for (uh = GetHead(&UUHostList); uh; uh = GetSucc(&uh->uh_Node)) {
- if (strlen(uh->uh_Node.ln_Name) == i && strnicmp(uh->uh_Node.ln_Name, toaddr, i) == 0)
- break;
- }
- if (uh == NULL) {
- uh = malloc(sizeof(UUHostNode) + i + 1);
- uh->uh_Node.ln_Name = (char *)(uh + 1);
- uh->uh_Len = 10; /* 'C rmail' */
- 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);
- }
-
- while (toaddr[i] && toaddr[i] != '!')
- ++i;
- if (toaddr[i] == '!')
- ++i;
-
- hostLen = strlen(toaddr + i) + strlen(skipaddr) + 3;
-
- if (uh->uh_NAddr > 0 && uh->uh_Len + hostLen > maxRMailLen) {
- rfi = TermMailToUUCP(rfi);
- goto loop;
- }
-
-
- node = malloc(sizeof(struct Node) + hostLen + 1);
- 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);
- }
- ++uh->uh_NAddr;
- uh->uh_Len += strlen(node->ln_Name) + 1; /* inc space */
- return(rfi);
- }
-
-
- FILE *
- TermMailToUUCP(rfi)
- FILE *rfi;
- {
- static char ExecFile[128];
- static char RemoteExecFile[128];
- static char CommandFile[128];
- static char DataFile[128];
- static char RemoteDataFile[128];
- UUHostNode *uh;
- char spoolDir[256];
- short foff;
- short failure = 0;
-
- while (uh = RemHead(&UUHostList)) {
- int seq;
- long pos;
- FILE *fi;
-
- Seq = seq = GetSequence(4);
- /* hierarch - bruins */
- strcpy(spoolDir,MakeConfigPath(UUSPOOL, uh->uh_Node.ln_Name));
- if(spoolDir==NULL || *spoolDir=='\0'){
- ulog(-1,"Can't create spool for \"%s\".", uh->uh_Node.ln_Name);
- return(-1);
- }
- if(chdir(spoolDir)){
- ulog(-1,"Can't change to spool: \"%s\".",spoolDir);
- if(mkdir(spoolDir)){
- ulog(-1,"Can't find spool \"%s\", creating.",spoolDir);
- return(-1);
- }
- chdir(spoolDir);
- }
-
- foff = strlen(spoolDir)+1; /* hierarch - bruins */
-
- sprintf(CommandFile, "%s/C.%sA%s", spoolDir, uh->uh_Node.ln_Name, SeqToName(seq));
- sprintf(DataFile, "%s/D.%sB%s", spoolDir, uh->uh_Node.ln_Name, SeqToName(seq));
- sprintf(ExecFile, "%s/D.%sX%s", spoolDir, uh->uh_Node.ln_Name, SeqToName(seq));
- ++seq;
- sprintf(RemoteExecFile, "%s/X.%sX%s", spoolDir, CutNodeName, SeqToName(seq));
- ++seq;
- sprintf(RemoteDataFile, "%s/D.%sB%s", spoolDir, CutNodeName, SeqToName(seq));
-
- LockFile(CommandFile);
- LockFile(DataFile);
-
- /*
- * Note, cannot run uuxqt from sendmail as uuxqt may call
- * sendmail itself!
- */
-
- if (strncmp(uh->uh_Node.ln_Name, NodeName, 7) == 0) {
- strcpy(ExecFile, RemoteExecFile);
- strcpy(RemoteDataFile, DataFile);
- }
-
- fi = fopen(ExecFile, "w");
-
- if (fi == NULL) {
- UnLockFile(CommandFile);
- UnLockFile(DataFile);
- failure = 1;
- break;
- }
-
- fprintf(fi, "U %s %s\n", UserName, NodeName);
- fprintf(fi, "F %s\n", RemoteDataFile + foff);
- fprintf(fi, "I %s\n", RemoteDataFile + foff);
- fprintf(fi, "C rmail");
-
- {
- struct Node *node;
-
- while (node = RemHead(&uh->uh_List)) {
- fprintf(fi, " %s", node->ln_Name);
- free(node);
- }
- fputc('\n', fi);
- }
- fclose(fi);
-
- if (strnicmp(uh->uh_Node.ln_Name, NodeName, 7) != 0) {
- fi = fopen(CommandFile, "w");
- if (fi == NULL) {
- UnLockFile(CommandFile);
- UnLockFile(DataFile);
- failure = 1;
- break;
- }
-
- fprintf(fi, "S %s %s %s - %s 0666\n", DataFile + foff, RemoteDataFile + foff, UserName, DataFile + foff);
- fprintf(fi, "S %s %s %s - %s 0666\n", ExecFile + foff, RemoteExecFile + foff, UserName, ExecFile + foff);
- fclose(fi);
- }
-
- fi = fopen(DataFile, "w");
- if (fi == NULL) {
- UnLockFile(CommandFile);
- UnLockFile(DataFile);
- remove(CommandFile);
- failure = 1;
- break;
- }
-
- DumpHeaderInfo(fi, RCVR_UUCP, 1, 0, "");
- pos = ftell(fi);
-
- #ifdef NOTDEF
- if (ROpt) {
- if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
- fputs(ScrBuf, fi);
- }
- #endif
- while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
- if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
- strins(ScrBuf, " ");
- fputs(ScrBuf, fi);
- }
- fclose(fi);
- if (rfi != stdin)
- fclose(rfi);
- fi = fopen(DataFile, "r");
- fseek(fi, pos, 0);
- rfi = fi;
-
- UnLockFile(CommandFile);
- UnLockFile(DataFile);
- free(uh);
- }
- if (failure) {
- puts("Fail");
- ulog(-1, "Output failed %s", CommandFile);
- }
- return(rfi);
- }
-
- void
- DumpHeaderInfo(fi, rcvr, resend, local, prestr)
- FILE *fi;
- int rcvr, resend, local;
- char *prestr;
- {
- char *source;
-
- /*
- * Write header info
- */
-
- #ifdef NOTDEF
- if (rcvr == RCVR_UUCP)
- source = "AmigaUUCP";
- else
- source = "Sendmail";
- #endif
-
- if (ROpt) {
- if (resend)
- 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
- 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\tid AA0%s; %s\n",
- prestr, NodeName, DomainName, SeqToName(Seq), atime(&T)
- );
- DumpHeader(fi, "Received:", &RecvList, prestr);
- if (ROpt == 0) {
- time_t t2 = T + 3600 * GetHourOffset(TimeZoneName);
- struct tm *ut;
-
- if (FindHeader("Date:") == NULL)
- fprintf(fi, "%sDate: %s\n", prestr, atime(&T));
- ut = localtime(&t2);
- fprintf(fi, "%sMessage-Id: <%02d%02d%02d%02d%02d.AA0%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);
- DumpHeader(fi, "From:", &FromList, prestr);
- DumpCombineHeader(fi, "To:", &ToList, prestr);
- if (!EmptyList(&CcList))
- DumpCombineHeader(fi, "Cc:", &CcList, prestr);
- DumpHeader(fi, "Subject:", &SubjList, prestr);
-
- fprintf(fi, "\n");
- }
-
- void
- DumpHeader(fi, field, list, prestr)
- FILE *fi;
- char *field;
- LIST *list;
- char *prestr;
- {
- NODE *node;
-
- for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; 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);
- }
- }
-
- char *
- FindHeader(field)
- char *field;
- {
- NODE *node;
- char *ptr = NULL;
- short len = strlen(field);
-
- for (node = HdrList.lh_Head; node != (NODE *)&HdrList.lh_Tail; node = node->ln_Succ) {
- if (strncmp(node->ln_Name, field, len) == 0) {
- ptr = node->ln_Name;
- break;
- }
- }
- if (ptr == NULL) {
- if ((node = (void *)GetTail(&FromList)) && strncmp("From:", field, len) == 0)
- ptr = node->ln_Name - len;
- }
- if (ptr == NULL) {
- if ((node = (void *)GetTail(&SubjList)) && strncmp("Subject:", field, len) == 0)
- ptr = node->ln_Name - len;
- }
- if (ptr) {
- ptr += len;
- while (*ptr == ' ' || *ptr == '\t')
- ++ptr;
- }
- return(ptr);
- }
-
- void
- DumpCombineHeader(fi, field, list, prestr)
- FILE *fi;
- char *field;
- LIST *list;
- char *prestr;
- {
- NODE *node;
- short ci = 0;
-
- fprintf(fi, "%s%s ", prestr, field);
- for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; 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");
- }
-
- #ifdef NOTDEF /* now in uucp:src/lib */
- char *
- atime(pt)
- time_t *pt;
- {
- static char buf[40];
- static char *mo[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
- "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
- };
- static char *dow[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
- struct tm *ut = localtime(pt);
-
- sprintf(buf, "%s, %d %s %02d %02d:%02d:%02d %s",
- dow[ut->tm_wday], ut->tm_mday, mo[ut->tm_mon],
- ut->tm_year % 100, ut->tm_hour, ut->tm_min, ut->tm_sec,
- TimeZoneName
- );
- return(buf);
- }
- #endif
-
- int
- GetHourOffset(tz)
- char *tz;
- {
- short i;
-
- static struct {
- char *Name;
- short 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
- };
- for (i = 0; TZAry[i].Name; ++i) {
- if (strncmp(tz, TZAry[i].Name, 3) == 0)
- return((int)TZAry[i].Hours);
- }
- ulog(-1, "Unknown Timezone: %s", tz);
- /* printf("Unknown Timezone: %s\n", tz); - bruins */
- return(6);
- }
-
- void
- PostPend(str, frend)
- char *str;
- int frend;
- {
- char *ptr;
- 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);
- }
-
- EmptyList(list)
- LIST *list;
- {
- if (list->lh_Head == (NODE *)&list->lh_Tail)
- return(1);
- return(0);
- }
-
-