File:  [MW Coherent from dump] / coherent / d / bin / mail / send.c
Revision 1.1.1.1 (vendor branch): download - view: text, annotated - select for diffs
Wed May 29 04:56:39 2019 UTC (7 years, 2 months ago) by root
Branches: MarkWilliams, MAIN
CVS tags: relic, HEAD
coherent

#include <stdio.h>
#include <sys/types.h>
#include <sys/mdata.h>
#include <time.h>
#include <pwd.h>
#include <utmp.h>
#include <sys/stat.h>
#include "mail.h"

#define SITENAMELEN	32	/* max length of sitename */
#define NODENAME	"/etc/uucpname"
#define DOMAINNAME	"/etc/domain"
#define	ALIAS	"/usr/lib/mail/aliases"
char	domain [64];

extern	char	*strtok();
FILE	*aliasfp;
char	aliasbuf [BUFSIZ];
char	*findalias();
static	**gusers;
char mysite[SITENAMELEN];	/* this host's uucpname */

extern	char	*temp;
extern	int	myuid;		/* User-id of mail user */
extern	int	mygid;		/* Group-id of mail user */
extern	char	cmdname[];	/* Command for x{en,de}code filter */
				/* and for tail recursion to uumail */
				/* and for editor recursion */
extern	char	*editname;	/* name of editor	   */
extern	char	*askcc;		/* Ask for CC: list? (YES/NO) */
extern	int	callmexmail;	/* Xmail modifier present */
extern	char	wrerr[];
extern	char	myname[];	/* User name */
extern	char	myfullname[];	/* full user name */
extern	int	mflag;		/* `You have mail.' message to recipient */
extern	int	verbflag;	/* verbose flag */
extern	char	templ[];	/* Temp file name template */
extern	char	mydead[];	/* $HOME/dead.letter */
extern	char	mysig[];
extern	char	nosave[];
extern	int	callmermail;

static	int	eflag;		/* Edit this mail */
static	int	senderr;
struct	tm	*tp;
char	toerr[] = "Cannot create temporary file\n";
char	header[BUFSIZ];		/* Message header */
char	boxname[256];		/* Destination mailbox */
char	aftralias [BUFSIZ];		/* name after alias processing */
char	remotefrom [32];	/* "remote from uucp" */

char	nosend[] = "Can't send mail to '%s'\n";
char	nopubk[] = "Can't send xmail to '%s'\n";
static	int fromtty;

/*
 * Send the message found on
 * the file pointer to the list
 * of people (argv style) with
 * a NULL pointer at the end.
 * The message is copied to a temp-file
 * from position `start' to `end' (or EOF).
 */
send2(fp, users, start, end, asksubj)
FILE *fp;
register char **users;
fsize_t start, end;
int	asksubj;
{
	char	**getcc();
	FILE 	*xfp, *tfp, *sigfp;
	time_t	curtime;

	uucpname();
	domainname();
	senderr = 0;
	temp = templ;
/*fprintf(stderr, "send2(fp, users, %ld, %ld, %d)\n", start, end, asksubj);*/
	fromtty = isatty(fileno(fp));
	if ((tfp = fopen(temp, "w")) != NULL) {
		fclose(tfp);
		if ((tfp = fopen(temp, "r+w")) == NULL)
			merr(toerr);
	} else
		merr(toerr);
	chown(temp, myuid, mygid);
	unlink(temp);
	temp = NULL;
	fseek(fp, start, 0);
	end -= start;

	eflag = 0;
	if (fromtty && asksubj && !callmermail) {
		fprintf(stdout, "Subject: ");
		fflush(stdout);
		if (fgets(msgline, NLINE, fp) != NULL) {
			if (strlen(msgline) > 1)
				fprintf(tfp, "Subject: %s", msgline);
		}
	}
	for (;;) {
		if (fgets(msgline, NLINE, fp) == NULL)
			break;
		if (fp == stdin)
			if ((strcmp(".\n", msgline)==0))
				break;
			else if ((strcmp("?\n", msgline)==0)) {
				eflag = 1;
				break;
			}
/*		fprintf(stderr, ":%s:", msgline);	*/
		fputs(msgline, tfp);
		end -= strlen(msgline);	/* compiler bug */		
		if (end <= 0) {
			break;
		}
	}
	if (!callmermail && (sigfp = fopen(mysig, "r")) != NULL) {
		fputs("\n", tfp);
		while (fgets(msgline, NLINE, sigfp) != NULL) {
			fputs(msgline, tfp);
		}
		fclose(sigfp);
	}
	/*
	 * If interrupted, bug out.
	 */
	if (intcheck()) {
		fclose(tfp);
		return;
	}
	/*
	 * Now, see if user wants to edit the message
	 */
	if (eflag) {
		xfp = tfp;
		temp = templ;
		if ((tfp = fopen(temp, "wr")) == NULL)
			merr(toerr);
		chown(temp, myuid, mygid);
		mcopy(xfp, tfp, (fsize_t)0, (fsize_t)MAXLONG, 0);
		fclose(xfp);
		sprintf(cmdname, "%s %s", editname, templ);
		system(cmdname);
		unlink(temp);
		temp = NULL;
	}
	/*
	 * Otherwise if empty message, bug out.
	 */
	else if (ftell(tfp) == 0) {
		fclose(tfp);
		return;
	}
	/*
	 * Now see if a copy list is requested.
	 */
	if (askcc)
		users = getcc(users);
	gusers = users;
	/*
	 * Now send the message.
	 */
	time(&curtime);
	tp = localtime(&curtime);
	if (callmexmail)
		xsend(users, tfp);
	else
		usend(users, tfp);
}

usend(users, tfp)
char **users;
FILE *tfp;
{
	FILE *xfp;
	char	*cp, *ap;
	char	**ulist;
	register struct passwd *pwp;

	for (ulist = users; *ulist != NULL; ulist++) {
		rewind(tfp);
		strcpy(aftralias, *ulist);
		if (index(*ulist, '!') == 0) {
			ap = findalias(*ulist);
			if (ap != NULL) {
				strcpy(aftralias, ap);
				if (verbflag && strcmp(aftralias, ap))
					fprintf(stderr,
					"name %s aliased to %s\n",
					*ulist, aftralias);
			}
		}
		if ((cp = index(aftralias, '!')) != NULL) {
			*cp++ = '\0';
			if (rsend(aftralias, cp, tfp) != 0) 
				senderr = 1;
			continue;
		}
		sprintf(boxname, "%s%s", SPOOLDIR, aftralias);
		if ((pwp = getpwnam(aftralias)) == NULL) {
			mmsg(nosend, aftralias);
			senderr = 1;
			continue;
		}
		mlock(pwp->pw_uid);
		if ((xfp = fopen(boxname, "a")) == NULL) {
			mmsg(nosend, aftralias);
			senderr = 1;
			munlock();
			continue;
		}
		chown(boxname, pwp->pw_uid, pwp->pw_gid);
		if (build_header(aftralias, NULL, tfp, xfp) != 1
		  || mcopy(tfp, xfp, ftell(tfp), (fsize_t)MAXLONG, 0)) {
			merr(wrerr, boxname);
			senderr = 1;
		} else
			fprintf(xfp, "\1\1\n");
		fflush(xfp);
		munlock();
		advise(aftralias);
	}
	if (senderr && fromtty && ! callmexmail) {
		if (maccess(mydead) < 0
		 || (xfp = fopen(mydead, "a")) == NULL
		 || mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG, 0))
			mmsg(nosave, mydead);
		else
			mmsg("Letter saved in %s\n", mydead);
		if (xfp != NULL) {
			chown(mydead, myuid, mygid);
			fclose(xfp);
		}
	}
	fclose(tfp);
}

rsend(system, user, tfp)
char	*user;
char	*system;
FILE	*tfp;
{
	FILE	*xfp;
	int	i;

	sprintf(cmdname, "uux -r - %s!rmail '(%s)'", system, user);
	if (verbflag)
		fprintf(stderr, "Queueing remote mail to %s!%s\n",
		system, user);
	if ((xfp = popen(cmdname, "w")) == NULL) {
		mmsg("Can't pipe to %s\n", cmdname);
		return 1;
	}
	if (build_header(user, mysite, tfp, xfp) != 1 
	  || mcopy(tfp, xfp, ftell(tfp), (fsize_t)MAXLONG, 0)) {
		merr(wrerr, cmdname);
		return 1;
	}
	if (i = (pclose(xfp) != 0)) {
		mmsg("uux has failed, status %d\n", i);
		return 1;
	}
	return 0;
}

xsend(users, tfp) char **users; FILE *tfp;
{
	register char **ulist;
	register char *cp;
	register struct passwd *pwp;
	FILE *xfp;

	for (ulist = users; *ulist!=NULL; ulist++) {
		rewind(tfp);
		sprintf(boxname, "%s%s", SPOOLDIR, *ulist);
		sprintf(cmdname, "xencode %s >> %s", *ulist, boxname);
		if (index(*ulist, '!') != NULL
		 || (pwp = getpwnam(*ulist)) == NULL) {
			mmsg(nosend, *ulist);
			continue;
		}
		if (xaccess(*ulist) == 0) {
			mmsg(nopubk, *ulist);
			continue;
		}
		mlock(pwp->pw_uid);
		if ((xfp = fopen(boxname, "a")) == NULL) {
			mmsg(nosend, *ulist);
			munlock();
			continue;
		}
		chown(boxname, pwp->pw_uid, pwp->pw_gid);
		fprintf(xfp, "From xmail %s %s\n", cp,
			tzname[tp->tm_isdst ? 1 : 0]);
		fclose(xfp);
		if ((xfp = popen(cmdname, "w")) == NULL) {
			mmsg("Can't pipe to xencode\n");
			continue;
		}
		if (fwrite(header, strlen(header), 1, xfp) != 1
		 || mcopy(tfp, xfp, (fsize_t)0, (fsize_t)MAXLONG, 0)) {
			merr(wrerr, cmdname);
		}
		pclose(xfp);
		munlock();
	}
	fclose(tfp);
}

/*
 * If the `-m' option is specified, advise
 * the recipient of the presence of mail.
 */
advise(recipient)
char *recipient;
{
	register FILE *fp;
	register FILE *tfp;
	struct utmp ut;
	char tty[30];
	struct stat sb;

	if (!mflag)
		return;
	if ((fp = fopen("/etc/utmp", "r")) == NULL)
		return;
	while (fread(&ut, sizeof ut, 1, fp) == 1)
		if (strncmp(ut.ut_name, recipient, DIRSIZ) == 0) {
			sprintf(tty, "/dev/%s", ut.ut_line);
			if (stat(tty, &sb)<0 || (sb.st_mode&S_IEXEC)==0)
				continue;
			if ((tfp = fopen(tty, "w")) != NULL) {
				fprintf(tfp, "\7%s: you have mail.\n", myname);
				fclose(tfp);
			}
		}
	fclose(fp);
}

uucpname()
{
	FILE *uufile;

	if (NULL == (uufile = fopen(NODENAME, "r"))) {
		strcpy(mysite, "<unknown>");
		return;
	}
	fgets(mysite, sizeof mysite, uufile);
	mysite[strlen(mysite) - 1] = '\0';	/* remove '\n' */
	fclose(uufile);
	return;
}

domainname()
{
	FILE *domfile;
	if((domfile = fopen(DOMAINNAME, "r")) == NULL) {
		strcpy(domain, ".UNKNOWN");
		return;
	}
	fgets(domain, sizeof domain, domfile);
	domain [strlen(domain) - 1] = '\0';
	fclose (domfile);
	return;
}

char	*
findalias(who)
{
	char	*name, *newname;
	static	whobuf [64];
	int	recurcount;
	int	hit;

	if (aliasfp == NULL) {
		if ((aliasfp = fopen(ALIAS, "r")) == NULL) {
			mmsg("Cannot open alias file\n");
			return who;
		}
	}
	recurcount = 0;
	strcpy(whobuf, who);
	for (; ; ) {
		fseek(aliasfp, 0L, 0);
		hit = 0;
		while (fgets(aliasbuf, BUFSIZ, aliasfp) != NULL) {
			name = strtok(aliasbuf," #:\t");
			newname = strtok(NULL, "#(), \t\n");
			if (strcmp(name, whobuf) == 0) {
				strcpy(whobuf, newname);
				if (recurcount++ > 4) {
					sprintf(whobuf,
					"Too many alias recursions for %s\n",
						who);
					mmsg(whobuf);
					return who;
				}
				hit = 1;
				break;
			}
		}
		if (hit == 0)
			return whobuf;
	}
	return whobuf;
}

char *
arpadate(tp)
struct	tm	*tp;
{
	static	char arpabuf [64];
	static	char months[] = "JanFebMarAprMayJunJulAugSepOctNovDec";
	sprintf(arpabuf, "%d %c%c%c %d %02d:%02d:%02d",
		tp->tm_mday,
		months[tp->tm_mon * 3],
		months[tp->tm_mon * 3 + 1],
		months[tp->tm_mon * 3 + 2],
		tp->tm_year,
		tp->tm_hour, tp->tm_min, tp->tm_sec);
	return arpabuf;
}

char *
msgid(tp)
struct	tm	*tp;
{
	static	char	msgidbuf [32];
	sprintf(msgidbuf, "%02d%02d%02d%02d%02d",
	tp->tm_year, tp->tm_mon + 1, tp->tm_mday, tp->tm_hour, tp->tm_min);
	return msgidbuf;
}

build_header(user, site, tfp, xfp)
char	*user;
char	*site;
FILE	*tfp;
FILE	*xfp;
{
	char	*cp;
	char	**ulist;
	long	pos;
	int	processid;

	cp = asctime(tp);
	cp[strlen(cp)-1] = 0;
/*	if (!callmermail) {	*/
		sprintf(header, "From %s %s %s", myname, cp,
			tzname[tp->tm_isdst ? 1 : 0]);
		if (site != NULL) {
			strcat(header, " remote from ");
			strcat(header, site);
		}
		strcat(header, "\n");
/*	}	*/
	if (fwrite(header, strlen(header), 1, xfp) != 1)
		return 0;
	pos = ftell(tfp);
	/* scan to end of From_ lines */
	while (fgets(header, NLINE, tfp) != NULL) {
		if ((strncmp (header, "From ", 5) != 0) &&
			(strncmp (header, ">From ", 6) != 0)) {
			break;
		}
		if (fwrite(header, strlen(header), 1, xfp) != 1)
			return 0;
		pos = ftell(tfp);
	}
	fseek(tfp, pos, 0);
	processid = getpid();
	if (callmermail) {
		sprintf(header,
		"Received: by %s (mail v %s)\n\tid AA%d; %s\n",
			mysite, revnop(), processid, arpadate(tp));
		if (fwrite(header, strlen(header), 1, xfp) != 1)
			return 0;
	} else {
		sprintf(header, "Message-Id: <%s.AA%d.V%s.%s@%s>\n",
			msgid(tp), processid, revnop(), mysite, domain);
		if (fwrite(header, strlen(header), 1, xfp) != 1)
			return 0;
		sprintf(header, "Date: %s\nFrom: %s!%s (%s)\n",
			arpadate(tp), mysite, myname, myfullname);
		if (fwrite(header, strlen(header), 1, xfp) != 1)
			return 0;
		sprintf(header, "To:   %s\n", user);
		if (fwrite(header, strlen(header), 1, xfp) != 1)
			return 0;
		if (gusers[0] != NULL && gusers[1] != NULL) {
			strcpy(header, "cc:");
			for (ulist = gusers; *ulist != NULL; ulist++) {
				strcat(header, " ");
				strcat(header, *ulist);
			}
			strcat(header, "\n");
			if (fwrite(header, strlen(header), 1, xfp) != 1)
				return 0;
		}
	}
	return 1;
}


unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.