[comp.sources.amiga] v90i188: UUCP 1.06D - UNIX compatible uucp/news/mail system, Part10/12

Amiga-Request@cs.odu.edu (Amiga Sources/Binaries Moderator) (06/28/90)

Submitted-by: Matt Dillon <@uunet.uu.net:overload!dillon>
Posting-number: Volume 90, Issue 188
Archive-name: unix/uucp-1.06d/part10

#!/bin/sh
# This is a shell archive.  Remove anything before this line, then unpack
# it by saving it into a file and typing "sh file".  To overwrite existing
# files, type "sh file -c".  You can also feed this as standard input via
# unshar, or by typing "sh <file", e.g..  If this archive is complete, you
# will see the following message at the end:
#		"End of archive 10 (of 12)."
# Contents:  uucp2/src/sendmail/sendmail.c
# Wrapped by tadguy@xanth on Thu Jun 28 08:21:35 1990
PATH=/bin:/usr/bin:/usr/ucb ; export PATH
if test -f 'uucp2/src/sendmail/sendmail.c' -a "${1}" != "-c" ; then 
  echo shar: Will not clobber existing file \"'uucp2/src/sendmail/sendmail.c'\"
else
echo shar: Extracting \"'uucp2/src/sendmail/sendmail.c'\" \(24049 characters\)
sed "s/^X//" >'uucp2/src/sendmail/sendmail.c' <<'END_OF_FILE'
X
X/*
X *  SENDMAIL / RMAIL
X *
X *  $Header: Beta:src/uucp/src/sendmail/RCS/sendmail.c,v 1.1 90/02/02 12:15:01 dillon Exp Locker: dillon $
X *
X *  (C) Copyright 1989-1990 by Matthew Dillon,  All Rights Reserved.
X *
X *  SENDMAIL <file -f from -t to -s subject -c cc -b bcc -r
X *  RMAIL user
X *
X *  Example:	Sendmail <datafile -froot
X *
X *  From: line is automatically added but can be overriden by a From:
X *  header in the file.  stdin is made up of a list of headers, a blank
X *  line, and then data until EOF.
X *
X *  the -r option tells sendmail that this is incomming mail.
X *  If av[0] begins with an 'r' for RMail instead of an 's' for
X *  Sendmail, then the rmail argument format is used (rmail user),
X *  as well as forcing -r.
X */
X
X#include "defs.h"
X
X#include <fcntl.h>
X#include <log.h>
X#include <time.h>
X#include <pwd.h>
X
Xtypedef struct List	LIST;
Xtypedef struct Node	NODE;
X
XIDENT(".06");
X
XLocal	void Usage(void);
XLocal	int brk(void);
XLocal	NODE *MakeNode(LIST *, char *);
XLocal	void MakeToFixNode(LIST *, char *, char *);
XLocal	void fixCallBack(char *);
XLocal	void IntegrateHeader(char *, short);
XLocal	void FromFixup(LIST *);
XLocal	void ToFixup(LIST *);
XLocal	void MakeToAddrNode(LIST *, char *);
XLocal	FILE *SendMailTo(LIST *, FILE *);
XLocal	FILE *OneMailTo(char *, FILE *);
XLocal	FILE *OneMailToPipe(char *, FILE *);
XLocal	FILE *OneMailToUser(char *, FILE *);
XLocal	FILE *OneMailToFile(char *, FILE *);
XLocal	FILE *OneMailToUUCP(char *, char *, FILE *);
XLocal	void DumpHeaderInfo(FILE *, int, int, int);
XLocal	void DumpHeader(FILE *, char *, LIST *);
XLocal	NODE *FindHeader(char *);
XLocal	void DumpCombineHeader(FILE *, char *, LIST *);
XLocal	char *atime(time_t *);
XLocal	int GetHourOffset(char *);
XLocal	void PostPend(char *, int);
XLocal	int EmptyList(LIST *);
X
X
X#define RCVR_UUCP	1
X#define RCVR_SENDMAIL	2
X
Xchar	*UserName;
Xchar	*RealName;
Xchar	*NodeName;
Xchar	*DomainName;
Xchar	*TimeZoneName;	/*  All caps, ex: PST			 */
Xchar	*DefaultNode;	/*  for addr formats we don't understand */
XLIST	RecvList;	/*  Received:	    */
XLIST	FromList;	/*  last one rules  */
XLIST	ToList; 	/*  To: 	    */
XLIST	CcList; 	/*  Cc: 	    */
XLIST	BccList;	/*  Bcc:	    */
XLIST	XccList;	/*  list of actual mail to be sent  */
XLIST	SubjList;	/*  Subject:	    */
XLIST	HdrList;	/*  other headers not specifically parsed */
Xchar	ScrBuf[1024];
Xchar	ScrBuf2[1024];
Xchar	TempFileBuf[256];
Xint	Seq;		/*  UUCP sequence no	*/
Xchar	Notify;
Xchar	ROpt;		/*  Receive-Mail flag	*/
Xstatic char OrigFromLine[512];
Xstatic char FromLine[512];  /*	'From ' line, if ROpt   */
X
X
X
Xmain(ac, av)
Xchar *av[];
X{
X    short isRMail = 0;
X    short isSendMail = 1;
X    FILE *fi;
X
X    onbreak(brk);
X
X    NewList(&RecvList);
X    NewList(&FromList);
X    NewList(&ToList);
X    NewList(&CcList);
X    NewList(&BccList);
X    NewList(&XccList);
X    NewList(&SubjList);
X    NewList(&HdrList);
X
X    UserName = GetUserName();
X    RealName = GetRealName();
X
X    if (UserName == NULL) {
X	puts("Sendmail: UserName config entry not found!");
X	ulog(0, "UserName config missing");
X	exit(1);
X    }
X    if (RealName == NULL) {
X	puts("Sendmail: RealName config entry not found!");
X	ulog(0, "RealName config missing");
X	exit(1);
X    }
X
X    NodeName = FindConfig("NodeName");
X    if (NodeName == NULL) {
X	puts("Sendmail: NodeName config entry not found!");
X	ulog(0, "NodeName config missing");
X	exit(1);
X    }
X    DomainName = FindConfig("DomainName");
X    if (DomainName == NULL) {
X	puts("Sendmail: DomainName config entry not found! using .UUCP");
X	DomainName = ".UUCP";
X    }
X    DefaultNode = FindConfig("DefaultNode");
X    TimeZoneName = FindConfig("TimeZone");
X
X    LoadAliases();
X
X    {
X	char *ptr = av[0] + strlen(av[0]);
X
X	/*
X	 *  Skip path
X	 */
X
X	while (ptr >= av[0] && *ptr != ':' && *ptr != '/')
X	    --ptr;
X	++ptr;
X
X	if (*ptr == 'r' || *ptr == 'R') {
X	    isRMail = 1;
X	    isSendMail = 0;
X	}
X    }
X
X    if (isRMail) {
X	char *addr = (ac == 2) ? av[1] : "Mailer-Daemon";
X
X	MakeNode(&BccList, addr);
X	UserName = "postmaster";    /*  XXX  */
X	RealName = "Mr.Amiga";      /*  XXX  */
X	ROpt = 1;		    /*	no header processing */
X    }
X    if (isSendMail) {
X	short i;
X	char *arg;
X	for (i = 1; i < ac; ++i) {
X	    arg = av[i];
X	    if (*arg != '-')
X		Usage();
X	    switch(arg[1]) {
X	    case 'f':
X		UserName = av[i+1];
X		sprintf(ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
X		MakeNode(&FromList, ScrBuf);
X		++i;
X		break;
X	    case 'r':
X		RealName = av[++i];
X		break;
X	    case 't':
X		MakeNode(&ToList, av[++i]);
X		break;
X	    case 'c':
X		MakeNode(&CcList, av[++i]);
X		break;
X	    case 'b':
X		MakeNode(&BccList, av[++i]);
X		break;
X	    case 's':
X		MakeNode(&SubjList, av[++i]);
X		break;
X	    case 'r':
X		++ROpt;
X		break;
X	    default:
X		Usage();
X	    }
X	}
X    }
X
X    /*
X     *	Read headers from input file.  Headers are not necessarily
X     *	contained on a single line.  Maximum 4096 chars per header.
X     */
X
X    if (ROpt) {
X	fgets(ScrBuf, sizeof(ScrBuf), stdin);
X	strcpy(OrigFromLine, ScrBuf);
X	if (strncmp(ScrBuf, "From ", 5) != 0) {
X	    ulog(-1, "Receive mail, expected 'From ', got %s", ScrBuf);
X	}
X	strcpy(FromLine, "From ");
X	PostPend(ScrBuf + 5, 1);
X
X	while (fgets(ScrBuf, sizeof(ScrBuf), stdin) && strncmp(ScrBuf, ">From ", 6) == 0) {
X	    strcpy(OrigFromLine, ScrBuf + 1);
X	    PostPend(ScrBuf + 6, 1);
X	}
X	strcpy(ScrBuf2, OrigFromLine + 5);
X	PostPend(ScrBuf2, 0);
X    } else {
X	ScrBuf[0] = '\n';
X	fgets(ScrBuf, sizeof(ScrBuf), stdin);
X    }
X    {
X	static char Hdr[4096];
X	short i = 0;		/*  index into Hdr  */
X
X	while (ScrBuf[0] != '\n') {
X	    char *ptr = ScrBuf;
X	    while (*ptr && *ptr != ' ' && *ptr != 9 && *ptr != ':')
X		++ptr;
X	    if (*ptr == ':') {  /*  found new header */
X		if (i)          /*  Dump old header  */
X		    IntegrateHeader(Hdr, i);
X		strcpy(Hdr, ScrBuf);
X		i = strlen(Hdr);
X	    } else {		/*  append to existing header	*/
X		if (i == 0)
X		    puts("Expected a Header!");
X		strcpy(Hdr + i, ScrBuf);
X		i = i + strlen(Hdr + i);
X	    }
X
X	    if (fgets(ScrBuf, sizeof(ScrBuf), stdin) == NULL)
X		ScrBuf[0] = '\n';
X	}
X	if (i)
X	    IntegrateHeader(Hdr, i);
X
X	if (ScrBuf[0] != '\n') {
X	    puts("sendmail: no mail");
X	    ulog(0, "No Mail");
X	    exit(1);
X	}
X    }
X
X    /*
X     *	Parse & fixup each To:, Cc:, and Bcc: field.
X     *
X     *	From:	we add the personal info arg from the password file
X     *	To:	we expand any aliases
X     */
X
X    if (ROpt == 0)
X	FromFixup(&FromList);
X    if (ROpt) {
X	ToFixup(&BccList);
X    } else {
X	ToFixup(&ToList);
X	ToFixup(&CcList);
X	ToFixup(&BccList);
X    }
X
X    /*
X     *	If no Subject: field add a dummy one
X     */
X
X    if (EmptyList(&SubjList))
X	MakeNode(&SubjList, "");
X
X    if (EmptyList(&FromList)) {
X	sprintf(ScrBuf, "%s@%s%s", UserName, NodeName, DomainName);
X	MakeNode(&FromList, ScrBuf);
X    }
X
X    fi = SendMailTo(&XccList, stdin);
X    if (fi && fi != stdin)
X	fclose(fi);
X    if (TempFileBuf[0])
X	remove(TempFileBuf);
X    UnLockFiles();
X
X    /*
X     *	Notify if T:MailRdy does not exist (created by us, deleted by
X     *	notify when notify exits).  Prevents running multiple notifies.
X     */
X
X    if (Notify) {
X	int fd = open("T:MailRdy", O_RDONLY);
X	if (fd < 0) {
X	    char *cmd;
X
X
X	    if (cmd = FindConfig(MAILREADYCMD)) {
X		fd = open("T:MailRdy", O_CREAT|O_TRUNC, 0666);
X		if (fd >= 0)
X		    close(fd);
X		sprintf(ScrBuf, "Run %s -x T:MailRdy", cmd);
X		Execute(ScrBuf, NULL, NULL);
X	    }
X	} else {
X	    close(fd);
X	}
X    }
X    return(0);
X}
X
Xvoid
XUsage()
X{
X    printf(
X	"Sendmail -f user [-t address -c address -b address -s subject -r]\n"
X	"RMail user\n"
X    );
X}
X
Xint
Xbrk()
X{
X    return(0);
X}
X
X/*
X *  Strips string and creates named node which is appended to the
X *  given list.
X */
X
XNODE *
XMakeNode(list, str)
XLIST *list;
Xchar *str;
X{
X    NODE *node;
X    char *ptr;
X
X    while (*str == ' ' || *str == 9)
X	++str;
X    for (ptr = str + strlen(str); ptr >= str && (*ptr == ' ' || *ptr == 9); --ptr);
X    ++ptr;
X    *ptr = 0;
X    node = malloc(sizeof(NODE) + strlen(str) + 1);
X    node->ln_Name = (char *)(node + 1);
X    strcpy(node->ln_Name, str);
X    AddTail(list, node);
X    return(node);
X}
X
X/*
X *
X */
X
Xvoid
XMakeToFixNode(list, str, send)
XLIST *list;
Xchar *str;
Xchar *send;
X{
X    char *ptr;
X    short len;
X    short c;
X    void fixCallBack();
X
X    while (str < send && (*str == ' ' || *str == 9))
X	++str;
X    for (ptr = send - 1; ptr >= str && (*ptr == ' ' || *ptr == 9); --ptr);
X    ++ptr;
X
X    len = ptr - str;
X    if (len < 0)
X	return;
X
X    /*
X     *	str[0..len-1]
X     */
X
X    c = str[len];
X    str[len] = 0;
X
X    if (ROpt) {     /*  disallow remote asking for special options */
X	ulog(-1, "Received mail for %s", str);
X	if (str[0] == '>' || str[0] == '<' || str[0] == '|' || str[0] == ':' || str[0] == '/') {
X	    ulog(-1, "SendMail, bad user %s", str);
X	    return;
X	}
X    }
X
X    {
X	NODE *node = malloc(sizeof(NODE) + strlen(str) + 1);
X
X	node->ln_Name = (char *)(node + 1);
X	strcpy(node->ln_Name, str);
X	AddTail(list, node);
X    }
X
X    UserAliasList(str, fixCallBack);    /*  from lib/alias.c    */
X    str[len] = c;
X}
X
Xvoid
XfixCallBack(user)
Xchar *user;
X{
X    NODE    *node;
X
X    if (user[0] == '<') {
X	FILE *fi = fopen(user + 1, "r");
X	char *buf = malloc(256);
X
X	if (fi == NULL) {
X	    ulog(-1, "Unable to open < file %s", user + 1);
X	    return;
X	}
X	while (fgets(buf, 256, fi)) {
X	    short i = 0;
X	    short j;
X	    while (buf[i] == ' ' || buf[i] == 9)
X		++i;
X	    if (buf[i] == 0 || buf[i] == '\n')
X		continue;
X	    for (j = i; buf[j] && buf[j] != '\n' && buf[j] != ' ' && buf[j] != 9; ++j);
X	    buf[j] = 0;
X	    UserAliasList(buf, fixCallBack);
X	}
X	fclose(fi);
X	free(buf);
X	return;
X    }
X
X    ulog(-1, "Sendmail, Sending mail to %s", user);
X
X    if (user[0] == '\\')
X	++user;
X
X    node = malloc(sizeof(NODE) + strlen(user) + 1);
X    node->ln_Name = (char *)(node + 1);
X    strcpy(node->ln_Name, user);
X    AddTail(&XccList, node);
X}
X
X
X/*
X *  Integrates a header
X */
X
Xvoid
XIntegrateHeader(hdr, len)
Xchar *hdr;
Xshort len;
X{
X    if (hdr[len-1] == '\n')     /*  strip trailing newline  */
X	hdr[len-1] = 0;
X
X    if (strncmp(hdr, "From:", 5) == 0) {
X	MakeNode(&FromList, hdr + 5);
X	return;
X    }
X    if (strncmp(hdr, "To:", 3) == 0) {
X	MakeNode(&ToList, hdr + 3);
X	return;
X    }
X    if (strncmp(hdr, "Cc:", 3) == 0) {
X	MakeNode(&CcList, hdr + 3);
X	return;
X    }
X    if (strncmp(hdr, "Bcc:", 4) == 0) {
X	MakeNode(&BccList, hdr + 4);
X	return;
X    }
X    if (strncmp(hdr, "Subject:", 8) == 0) {
X	MakeNode(&SubjList, hdr + 8);
X	return;
X    }
X    if (strncmp(hdr, "Received:", 9) == 0) {
X	MakeNode(&RecvList, hdr + 9);
X	return;
X    }
X    MakeNode(&HdrList, hdr);
X}
X
X/*
X *  Adds (personal info) to FromList based on passwd entry or, if
X *  that is not available, from the Config entry 'RealName' or
X *  ENV:REALNAME (env:REALNAME takes precedence)
X */
X
Xvoid
XFromFixup(list)
XLIST *list;
X{
X    NODE *node;
X    NODE *nn;
X    LIST tmpList;
X
X    NewList(&tmpList);
X
X    while (node = RemHead(list)) {
X	/*
X	 *  FIXME.  Fix getpwnam() and use pw_gecos entry.
X	 */
X	nn = malloc(sizeof(NODE) + strlen(node->ln_Name) + strlen(RealName) + 16);
X	nn->ln_Name = (char *)(nn + 1);
X	sprintf(nn->ln_Name, "%s (%s)", node->ln_Name, RealName);
X	free(node);
X	AddTail(&tmpList, nn);
X    }
X    while (node = RemHead(&tmpList))
X	AddTail(list, node);
X}
X
X/*
X *  Converts an unparsed list of names into a list of single address
X *  fields, removing any personal idents from the entries.  These will
X *  be recombined after processing when the data file is written out.
X *
X *  Also expands sendmail aliases (UULIB:Aliases) (HACK)
X */
X
Xvoid
XToFixup(list)
XLIST *list;
X{
X    NODE *node;
X    LIST tmpList;
X
X    NewList(&tmpList);
X
X    while (node = RemHead(list)) {
X	char *str = node->ln_Name;
X	char *ptr;
X
X	while (*str) {      /*  breakup fields by newline or comma */
X	    for (ptr = str; *ptr && *ptr != '\n' && *ptr != ','; ++ptr);
X	    MakeToAddrNode(&tmpList, str);
X	    str = ptr;
X	    while (*str == '\n' || *str == ',' || *str == ' ' || *str == 9)
X		++str;
X	}
X	free(node);
X    }
X    while (node = RemHead(&tmpList))
X	AddTail(list, node);
X}
X
X/*
X *  Extracts a single name / address (comma or newline delimited)
X *  field and creates a new node.
X */
X
Xvoid
XMakeToAddrNode(list, str)
XLIST *list;
Xchar *str;
X{
X    char *p1, *p2;
X    short ns = 0;	/*  non-whitespace encountered */
X
X    for (p1 = str; *p1 && *p1 != ',' && *p1 != '\n'; ++p1) {
X	if (*p1 == '(') {   /*  addr (name) OR (name) addr */
X	    if (ns) {       /*  addr (name) */
X		MakeToFixNode(list, str, p1);
X	    } else {
X		while (*p1 && *p1 != ',' && *p1 != '\n' && *p1 != ')')
X		    ++p1;
X		if (*p1 == ')') {
X		    for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n'; ++p2);
X		    MakeToFixNode(list, p1 + 1, p2);
X		}
X	    }
X	    return;
X	}
X
X	if (*p1 == '<') {   /*  <addr>  */
X	    for (p2 = p1 + 1; *p2 && *p2 != ',' && *p2 != '\n' && *p2 != '>'; ++p2);
X	    if (*p2 == '>')
X		MakeToFixNode(list, p1 + 1, p2);
X	    return;
X	}
X	if (*p1 != ' ' && *p1 != 9)
X	    ns = 1;
X    }
X    MakeToFixNode(list, str, p1);
X}
X
X
X/*
X *  Send mail to <recipeant>
X *
X *	-Local mail
X *	-Machine path (UUCP)
X */
X
XFILE *
XSendMailTo(list, fi)
XLIST *list;
XFILE *fi;
X{
X    NODE *node;
X
X    for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ)
X	fi = OneMailTo(node->ln_Name, fi);
X    return(fi);
X}
X
XFILE *
XOneMailTo(toaddr, rfi)
Xchar *toaddr;
XFILE *rfi;
X{
X    short i;
X    char c;
X    static char ToAddr[512];
X    static char Buf[512];
X    static char typeBuf[16];
X    static char classBuf[16];
X    static char addrBuf[128];
X
X    if (toaddr[0] == '|')       /*  pipe through command    */
X	return(OneMailToPipe(toaddr + 1, rfi));
X    if (toaddr[0] == '>')       /*  copy to file            */
X	return(OneMailToFile(toaddr + 1, rfi));
X
X    strncpy(ToAddr, toaddr, sizeof(ToAddr));
X    ToAddr[sizeof(ToAddr) - 1] = 0;
X
Xloop:
X    for (i = 0; c = ToAddr[i]; ++i) {
X	if (c == '!' || c == '%' || c == '@' || c == ':')
X	    break;
X    }
X    if (c == 0)                 /*  local name  */
X	return(OneMailToUser(ToAddr, rfi));
X
X    /*
X     *	Non-Local mail
X     */
X
X    i = ParseAddress(ToAddr, Buf, strlen(ToAddr));
X    if (DomainLookup(Buf, strlen(Buf), typeBuf, classBuf, addrBuf)) {
X	printf("type %s class %s addr %s\n", typeBuf, classBuf, addrBuf);
X	printf("buf %s\n", Buf);
X
X	/*
X	 *  Note distinction between mail destination and mail forwarder.
X	 *  mail destination removes the first machine from the rmail line
X	 *  mail forwarder does NOT
X	 */
X
X	if (strcmpi(classBuf, "UU") == 0) {
X	    if (strcmpi(typeBuf, "MD") == 0)
X		return(OneMailToUUCP(addrBuf, Buf + i + 1, rfi));
X	    else
X		return(OneMailToUUCP(addrBuf, Buf, rfi));
X	} else if (strcmpi(classBuf, "LL") == 0) {  /*  local mail, loop */
X	    for (i = 0; Buf[i] && Buf[i] != '!'; ++i);
X	    if (Buf[i] == 0) {
X		strcpy(Buf + i, "postmaster");
X		--i;
X	    }
X	    strcpy(ToAddr, Buf + i + 1);
X	    goto loop;
X	} else {
X	    ulog(-1, "Unsupported domain class: %s", classBuf);
X	    printf("Unsupported domain class: %s\n", classBuf);
X	}
X	return(rfi);
X    } else {
X	ulog(-1, "Could not find domain for %s, no mail sent", Buf);
X	printf("Unable to send mail to %s\n", Buf);
X	return(rfi);
X    }
X}
X
X
XFILE *
XOneMailToPipe(toaddr, rfi)
Xchar *toaddr;
XFILE *rfi;
X{
X    FILE *fi;
X    char *ptr;
X    static long pos;
X
X    if (TempFileBuf[0] == 0) {
X	strcpy(TempFileBuf, TmpFileName("T:pipe"));
X	fi = fopen(TempFileBuf, "w");
X	if (fi == NULL) {
X	    ulog(-1, "Unable to open temp file %s for command: %s", TempFileBuf, toaddr);
X	    return(rfi);
X	}
X	DumpHeaderInfo(fi, RCVR_SENDMAIL, 0, 1);
X	pos = ftell(fi);
X	while (fgets(ScrBuf, sizeof(ScrBuf), rfi))
X	    fputs(ScrBuf, fi);
X	fclose(fi);
X    }
X    strcpy(ScrBuf, toaddr);
X
X    ptr = toaddr;
X    if (strncmpi(toaddr, "run", 3) == 0) {
X	ptr += 3;
X	while (*ptr == ' ' || *ptr == 9)
X	    ++ptr;
X    }
X    while (*ptr && *ptr != ' ' && *ptr != 9)
X	++ptr;
X
X    if (*ptr == 0)
X	strcat(ScrBuf, " ");
X    sprintf(ScrBuf + (ptr - toaddr + 1), "<%s %s", TempFileBuf, ptr);
X    if (Execute(ScrBuf, NULL, NULL) == 0)
X	ulog(-1, "Couldn't execute %s", ScrBuf);
X
X    fi = fopen(TempFileBuf, "r");
X    if (fi) {
X	if (rfi != stdin)
X	    fclose(rfi);
X	rfi = fi;
X	fseek(rfi, pos, 0);
X    } else {
X	ulog(-1, "Couldn't reopen temp '%s', mail failed!", TempFileBuf);
X	rfi = stdin;
X    }
X    return(rfi);
X}
X
XFILE *
XOneMailToUser(toaddr, rfi)
Xchar *toaddr;
XFILE *rfi;
X{
X    ++Notify;
X    strcpy(ScrBuf, MakeConfigPath(UUMAIL, toaddr));
X    return(OneMailToFile(ScrBuf, rfi));
X}
X
XFILE *
XOneMailToFile(tofile, rfi)
Xchar *tofile;
XFILE *rfi;
X{
X    FILE *fo;
X    static char DataFile[128];
X    long pos;
X
X    strcpy(DataFile, tofile);
X
X    LockFile(DataFile);
X    fo = fopen(DataFile, "a");
X    if (fo == NULL) {
X	strcpy(DataFile, "T:MailOverflow");
X	fo = fopen(DataFile, "a");
X	if (fo)
X	    ulog(-1, "Could not append to %s, appending to %s", tofile, DataFile);
X	else
X	    ulog(-1, "Can't append to anywhere! (%s)", tofile);
X    }
X    if (fo) {
X	DumpHeaderInfo(fo, RCVR_SENDMAIL, 0, 1);
X	pos = ftell(fo);
X	if (ROpt) {
X	    if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
X		fputs(ScrBuf, fo);
X	}
X	while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
X	    if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
X		strins(ScrBuf, " ");
X	    fputs(ScrBuf, fo);
X	}
X	fclose(fo);
X	if (rfi != stdin)
X	    fclose(rfi);
X	rfi = fopen(DataFile, "r");
X	fseek(rfi, pos, 0);
X    }
X    UnLockFile(DataFile);
X    return(rfi);
X}
X
XFILE *
XOneMailToUUCP(toaddr, skipaddr, rfi)
Xchar *toaddr;
Xchar *skipaddr;
XFILE *rfi;
X{
X    static char ExecFile[128];
X    static char XExecFile[128];
X    static char CommandFile[128];
X    static char DataFile[128];
X    static char DestNode[256];
X    /*static char ToAddr[256];*/
X    FILE *fi;
X    int seq;
X    long pos;
X    short i;
X    short ai;
X    char *spoolDir = strdup(MakeConfigPath(UUSPOOL, ""));
X
X    /*
X     *	If the destination node
X     */
X
X    strcpy(DestNode, toaddr);
X
X    ai = -1;
X    for (i = 0; DestNode[i]; ++i) {
X	/*
X	 *  Remember index for additional paths
X	 */
X
X	if (DestNode[i] == '!') {
X	    DestNode[i] = 0;
X	    ai = i + 1;
X	    break;
X	}
X
X	/*
X	 *  Cut off machine name at 7 chars and ignore any domain
X	 *  info.
X	 */
X
X	if (i == 7 || DestNode[i] == '.')
X	    DestNode[i] = 0;
X    }
X
X    Seq = seq = GetSequence(4);
X
X#define FOFF	strlen(spoolDir)
X
X    sprintf(ExecFile,   "%sD.%sX%04d", spoolDir, DestNode, seq++);
X    sprintf(XExecFile,  "%sX.%sX%04d", spoolDir, DestNode, seq++);
X    sprintf(CommandFile,"%sC.%sA%04d", spoolDir, DestNode, seq++);
X    sprintf(DataFile,   "%sD.%sB%04d", spoolDir, DestNode, seq);
X
X    LockFile(CommandFile);
X    LockFile(DataFile);
X
X    /*
X     *	Note, cannot run uuxqt from sendmail as uuxqt may call
X     *	sendmail!
X     */
X
X    if (strncmp(DestNode, NodeName, 7) == 0)
X	fi = fopen(XExecFile, "w");
X    else
X	fi = fopen(ExecFile, "w");
X
X    if (fi == NULL)
X	goto fail;
X
X    fprintf(fi, "U %s\n", UserName);
X    fprintf(fi, "F %s\n", DataFile + FOFF);
X    fprintf(fi, "I %s\n", DataFile + FOFF);
X    if (ai >= 0)
X	fprintf(fi, "C rmail %s!%s\n", DestNode + ai, skipaddr);
X    else
X	fprintf(fi, "C rmail %s\n", skipaddr);
X    fclose(fi);
X
X    if (strncmp(DestNode, NodeName, 7)) {
X	fi = fopen(CommandFile, "w");
X	if (fi == NULL)
X	    goto fail;
X
X	fprintf(fi, "S %s %s %s - %s 0666\n", DataFile + FOFF, DataFile + FOFF, UserName, DataFile + FOFF);
X	fprintf(fi, "S %s %s %s - %s 0666\n", ExecFile + FOFF, XExecFile + FOFF, UserName, ExecFile + FOFF);
X	fclose(fi);
X    }
X
X    fi = fopen(DataFile, "w");
X    if (fi == NULL)
X	goto fail;
X
X    DumpHeaderInfo(fi, RCVR_UUCP, 1, 0);
X    pos = ftell(fi);
X
X    if (ROpt) {
X	if (fgets(ScrBuf, sizeof(ScrBuf), rfi))
X	    fputs(ScrBuf, fi);
X    }
X    while (fgets(ScrBuf, sizeof(ScrBuf), rfi)) {
X	if (ScrBuf[0] == 'F' && strncmp(ScrBuf, "From ", 5) == 0)
X	    strins(ScrBuf, " ");
X	fputs(ScrBuf, fi);
X    }
X    fclose(fi);
X    if (rfi != stdin)
X	fclose(rfi);
X    fi = fopen(DataFile, "r");
X    fseek(fi, pos, 0);
X
X    UnLockFile(CommandFile);
X    UnLockFile(DataFile);
X
X    free(spoolDir);
X
X    return(fi);
Xfail:
X    UnLockFile(CommandFile);
X    UnLockFile(DataFile);
X
X    free(spoolDir);
X    puts("Fail");
X    ulog(-1, "Output failed %s", CommandFile);
X    return(rfi);
X}
X
Xvoid
XDumpHeaderInfo(fi, rcvr, resend, local)
XFILE *fi;
Xint rcvr, resend, local;
X{
X    char *source;
X    time_t t;
X
X    time(&t);
X
X    /*
X     *	Write header info
X     */
X
X    if (rcvr == RCVR_UUCP)
X	source = "AmigaUUCP";
X    else
X	source = "Sendmail";
X
X    if (ROpt) {
X	if (resend)
X	    fprintf(fi, "%s %s remote from %s\n", FromLine, atime(&t), NodeName);
X	else
X	    fprintf(fi, "%s %s\n", FromLine, atime(&t));
X    } else {
X	if (local)
X	    fprintf(fi, "From %s %s\n", UserName, atime(&t));
X	else
X	    fprintf(fi, "From %s %s remote from %s\n", UserName, atime(&t), NodeName);
X    }
X    fprintf(fi, "Received: by %s%s (1.05D/Amiga)\n\tid AA%05d; %s\n",
X	NodeName, DomainName, Seq, atime(&t)
X    );
X    DumpHeader(fi, "Received:", &RecvList);
X    if (ROpt == 0) {
X	time_t t2 = t + 3600 * GetHourOffset(TimeZoneName);
X	struct tm *ut;
X
X	if (FindHeader("Date:") == NULL)
X	    fprintf(fi, "Date: %s\n", atime(&t));
X	ut = localtime(&t2);
X	fprintf(fi, "Message-Id: <%02d%02d%02d%02d%02d.AA%05d@%s%s>\n",
X	    ut->tm_year % 100, ut->tm_mon + 1, ut->tm_mday, ut->tm_hour, ut->tm_min,
X	    Seq, NodeName, DomainName
X	);
X    }
X
X    /*
X     *	From:, To:, Cc:, Subject: (Bcc: never written to header),
X     *	and any other header fields
X     */
X
X    DumpHeader(fi, NULL, &HdrList);
X    DumpHeader(fi, "From:", &FromList);
X    DumpCombineHeader(fi, "To:", &ToList);
X    if (!EmptyList(&CcList))
X	DumpCombineHeader(fi, "Cc:", &CcList);
X    DumpHeader(fi, "Subject:", &SubjList);
X
X    fprintf(fi, "\n");
X}
X
Xvoid
XDumpHeader(fi, field, list)
XFILE *fi;
Xchar *field;
XLIST *list;
X{
X    NODE *node;
X
X    for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ) {
X	if (field)
X	    fprintf(fi, "%s %s\n", field, node->ln_Name);
X	else
X	    fprintf(fi, "%s\n", node->ln_Name);
X    }
X}
X
XNODE *
XFindHeader(field)
Xchar *field;
X{
X    NODE *node;
X    short len = strlen(field);
X
X    for (node = HdrList.lh_Head; node != (NODE *)&HdrList.lh_Tail; node = node->ln_Succ) {
X	if (strncmp(node->ln_Name, field, len) == 0)
X	    return(node);
X    }
X    return(NULL);
X}
X
Xvoid
XDumpCombineHeader(fi, field, list)
XFILE *fi;
Xchar *field;
XLIST *list;
X{
X    NODE *node;
X    short ci = 0;
X
X    fprintf(fi, "%s ", field);
X    for (node = list->lh_Head; node != (NODE *)&list->lh_Tail; node = node->ln_Succ) {
X	if (ci && ci + strlen(node->ln_Name) > 70) {
X	    fprintf(fi, ",\n\t");
X	    ci = 0;
X	}
X	if (ci)
X	    fprintf(fi, ", ");
X	fprintf(fi, "%s", node->ln_Name);
X	ci += strlen(node->ln_Name) + 2;
X    }
X    fprintf(fi, "\n");
X}
X
Xchar *
Xatime(pt)
Xtime_t *pt;
X{
X    static char buf[40];
X    static char *mo[12] = { "Jan", "Feb", "Mar", "Apr", "May", "Jun",
X			    "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
X			};
X    static char *dow[7] = { "Sun", "Mon", "Tue", "Wed", "Thu", "Fri", "Sat" };
X    struct tm *ut = localtime(pt);
X
X    sprintf(buf, "%s, %d %s %02d %02d:%02d:%02d %s",
X	dow[ut->tm_wday], ut->tm_mday, mo[ut->tm_mon],
X	ut->tm_year % 100, ut->tm_hour, ut->tm_min, ut->tm_sec,
X	TimeZoneName
X    );
X    return(buf);
X}
X
Xint
XGetHourOffset(tz)
Xchar *tz;
X{
X    short i;
X
X    static struct {
X	char *Name;
X	short Hours;
X    } TZAry[] = {
X	"GMT",  0,
X	"UT",   0,
X	"PST",  8,
X	"MST",  7,
X	"CST",  6,
X	"EST",  5,
X	"AST",  4,
X	"PDT",  7,
X	"MDT",  6,
X	"CDT",  5,
X	"EDT",  4,
X	"ADT",  3,
X	NULL, 0
X    };
X    for (i = 0; TZAry[i].Name; ++i) {
X	if (strncmp(tz, TZAry[i].Name, 3) == 0)
X	    return((int)TZAry[i].Hours);
X    }
X    ulog(-1, "Unknown Timezone: %s", tz);
X    printf("Unknown Timezone: %s", tz);
X    return(6);
X}
X
Xvoid
XPostPend(str, frend)
Xchar *str;
Xint frend;
X{
X    char *ptr;
X    if (frend) {
X	ptr = str + strlen(str);
X	while (ptr > str && *ptr != ' ' && *ptr != 9) {
X	    if (*ptr == '\n')
X		*ptr = 0;
X	    --ptr;
X	}
X	str = ptr + 1;
X    }
X    for (ptr = str; *ptr && *ptr != ' ' && *ptr != 9 && *ptr != '\n'; ++ptr);
X    if (frend)
X	*ptr++ = '!';
X    *ptr = 0;
X    for (ptr = FromLine + 5; *ptr && *ptr != ' ' && *ptr != 9; ++ptr);
X    strins(ptr, str);
X}
X
XEmptyList(list)
XLIST *list;
X{
X    if (list->lh_Head == (NODE *)&list->lh_Tail)
X	return(1);
X    return(0);
X}
X
END_OF_FILE
if test 24049 -ne `wc -c <'uucp2/src/sendmail/sendmail.c'`; then
    echo shar: \"'uucp2/src/sendmail/sendmail.c'\" unpacked with wrong size!
fi
# end of 'uucp2/src/sendmail/sendmail.c'
fi
echo shar: End of archive 10 \(of 12\).
cp /dev/null ark10isdone
MISSING=""
for I in 1 2 3 4 5 6 7 8 9 10 11 12 ; do
    if test ! -f ark${I}isdone ; then
	MISSING="${MISSING} ${I}"
    fi
done
if test "${MISSING}" = "" ; then
    echo You have unpacked all 12 archives.
    rm -f ark[1-9]isdone ark[1-9][0-9]isdone
else
    echo You still need to unpack the following archives:
    echo "        " ${MISSING}
fi
##  End of shell archive.
exit 0
-- 
Mail submissions (sources or binaries) to <amiga@cs.odu.edu>.
Mail comments to the moderator at <amiga-request@cs.odu.edu>.
Post requests for sources, and general discussion to comp.sys.amiga.