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.