DataMuseum.dk

Presents historical artifacts from the history of:

DKUUG/EUUG Conference tapes

This is an automatic "excavation" of a thematic subset of
artifacts from Datamuseum.dk's BitArchive.

See our Wiki for more about DKUUG/EUUG Conference tapes

Excavated with: AutoArchaeologist - Free & Open Source Software.


top - metrics - download
Index: T b

⟦7049a471a⟧ TextFile

    Length: 15286 (0x3bb6)
    Types: TextFile
    Names: »binmail.c,v«

Derivation

└─⟦9ae75bfbd⟧ Bits:30007242 EUUGD3: Starter Kit
    └─⟦bfebc70e2⟧ »EurOpenD3/mail/sendmail-5.65b+IDA-1.4.3.tar.Z« 
        └─⟦f9e35cd84⟧ 
            └─⟦this⟧ »sendmail/binmail/RCS/binmail.c,v« 

TextFile

head     4.36;
branch   4.36.0;
access   ;
symbols  UICSO:4.36.0 VANILLA:4.36;
locks    ; strict;
comment  @ * @;


4.36
date     90.11.30.14.14.06;  author paul;  state Exp;
branches 4.36.0.1;
next     ;

4.36.0.1
date     90.11.30.14.22.29;  author paul;  state Exp;
branches ;
next     ;


desc
@@



4.36
log
@Sendmail V5.65 distribution
@
text
@#ifndef lint
static char sccsid[] = "@@(#)delivermail.c	4.36 (Berkeley) 4/21/89";
#endif

#include <sys/param.h>
#include <sys/stat.h>
#include <sys/file.h>

#include <ctype.h>
#include <stdio.h>
#include <pwd.h>
#include <utmp.h>
#include <signal.h>
#include <setjmp.h>
#include <sysexits.h>
#include "pathnames.h"

	/* copylet flags */
#define REMOTE		1		/* remote mail, add rmtmsg */
#define ORDINARY	2
#define ZAP		3		/* zap header and trailing empty line */
#define	FORWARD		4

#define	LSIZE		256
#define	MAXLET		300		/* maximum number of letters */
#define	MAILMODE	0600		/* mode of created mail */

char	line[LSIZE];
char	resp[LSIZE];
struct let {
	long	adr;
	char	change;
} let[MAXLET];
int	nlet	= 0;
char	lfil[50];
long	iop, time();
char	*getenv();
char	*index();
char	lettmp[] = _PATH_TMP;
char	maildir[] = _PATH_MAILDIR;
char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
char	dead[] = "dead.letter";
char	forwmsg[] = " forwarded\n";
FILE	*tmpf;
FILE	*malf;
char	my_name[60];
char	*getlogin();
int	error;
int	changed;
int	forward;
char	from[] = "From ";
long	ftell();
int	delex();
char	*ctime();
int	flgf;
int	flgp;
int	delflg = 1;
int	hseqno;
jmp_buf	sjbuf;
int	rmail;

main(argc, argv)
char **argv;
{
	register int i;
	char *name;
	struct passwd *pwent;

	if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) ||
	    getuid() != pwent->pw_uid) 
		pwent = getpwuid(getuid());
	strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1);
	if (setjmp(sjbuf))
		done();
	for (i=SIGHUP; i<=SIGTERM; i++)
		setsig(i, delex);
	i = mkstemp(lettmp);
	tmpf = fdopen(i, "r+");
	if (i < 0 || tmpf == NULL)
		panic("mail: %s: cannot open for writing", lettmp);
	/*
	 * This protects against others reading mail from temp file and
	 * if we exit, the file will be deleted already.
	 */
	unlink(lettmp);
	if (argv[0][0] == 'r')
		rmail++;
	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
		printmail(argc, argv);
	else
		bulkmail(argc, argv);
	done();
}

setsig(i, f)
int i;
int (*f)();
{
	if (signal(i, SIG_IGN) != SIG_IGN)
		signal(i, f);
}

any(c, str)
	register int c;
	register char *str;
{

	while (*str)
		if (c == *str++)
			return(1);
	return(0);
}

printmail(argc, argv)
	char **argv;
{
	int flg, i, j, print;
	char *p, *getarg();
	struct stat statb;

	setuid(getuid());
	cat(mailfile, maildir, my_name);
#ifdef notdef
	if (stat(mailfile, &statb) >= 0
	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
		strcat(mailfile, "/");
		strcat(mailfile, my_name);
	}
#endif
	for (; argc > 1; argv++, argc--) {
		if (argv[1][0] != '-')
			break;
		switch (argv[1][1]) {

		case 'p':
			flgp++;
			/* fall thru... */
		case 'q':
			delflg = 0;
			break;

		case 'f':
			if (argc >= 3) {
				strcpy(mailfile, argv[2]);
				argv++, argc--;
			}
			break;

		case 'b':
			forward = 1;
			break;

		default:
			panic("unknown option %c", argv[1][1]);
			/*NOTREACHED*/
		}
	}
	malf = fopen(mailfile, "r");
	if (malf == NULL) {
		printf("No mail.\n");
		return;
	}
	flock(fileno(malf), LOCK_SH);
	copymt(malf, tmpf);
	fclose(malf);			/* implicit unlock */
	fseek(tmpf, 0L, L_SET);

	changed = 0;
	print = 1;
	for (i = 0; i < nlet; ) {
		j = forward ? i : nlet - i - 1;
		if (setjmp(sjbuf)) {
			print = 0;
		} else {
			if (print)
				copylet(j, stdout, ORDINARY);
			print = 1;
		}
		if (flgp) {
			i++;
			continue;
		}
		setjmp(sjbuf);
		fputs("? ", stdout);
		fflush(stdout);
		if (fgets(resp, LSIZE, stdin) == NULL)
			break;
		switch (resp[0]) {

		default:
			printf("usage\n");
		case '?':
			print = 0;
			printf("q\tquit\n");
			printf("x\texit without changing mail\n");
			printf("p\tprint\n");
			printf("s[file]\tsave (default mbox)\n");
			printf("w[file]\tsame without header\n");
			printf("-\tprint previous\n");
			printf("d\tdelete\n");
			printf("+\tnext (no delete)\n");
			printf("m user\tmail to user\n");
			printf("! cmd\texecute cmd\n");
			break;

		case '+':
		case 'n':
		case '\n':
			i++;
			break;
		case 'x':
			changed = 0;
		case 'q':
			goto donep;
		case 'p':
			break;
		case '^':
		case '-':
			if (--i < 0)
				i = 0;
			break;
		case 'y':
		case 'w':
		case 's':
			flg = 0;
			if (resp[1] != '\n' && resp[1] != ' ') {
				printf("illegal\n");
				flg++;
				print = 0;
				continue;
			}
			if (resp[1] == '\n' || resp[1] == '\0') {
				p = getenv("HOME");
				if (p != 0)
					cat(resp+1, p, "/mbox");
				else
					cat(resp+1, "", "mbox");
			}
			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
				malf = fopen(lfil, "a");
				if (malf == NULL) {
					printf("mail: %s: cannot append\n",
					    lfil);
					flg++;
					continue;
				}
				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
				fclose(malf);
			}
			if (flg)
				print = 0;
			else {
				let[j].change = 'd';
				changed++;
				i++;
			}
			break;
		case 'm':
			flg = 0;
			if (resp[1] == '\n' || resp[1] == '\0') {
				i++;
				continue;
			}
			if (resp[1] != ' ') {
				printf("invalid command\n");
				flg++;
				print = 0;
				continue;
			}
			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
				if (!sendmail(j, lfil, my_name))
					flg++;
			if (flg)
				print = 0;
			else {
				let[j].change = 'd';
				changed++;
				i++;
			}
			break;
		case '!':
			system(resp+1);
			printf("!\n");
			print = 0;
			break;
		case 'd':
			let[j].change = 'd';
			changed++;
			i++;
			if (resp[1] == 'q')
				goto donep;
			break;
		}
	}
   donep:
	if (changed)
		copyback();
}

/* copy temp or whatever back to /usr/spool/mail */
copyback()
{
	register int i, c;
	long oldmask;
	int fd, new = 0;
	struct stat stbuf;

	oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT));
	fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE);
	if (fd >= 0) {
		flock(fd, LOCK_EX);
		malf = fdopen(fd, "r+");
	}
	if (fd < 0 || malf == NULL)
		panic("can't rewrite %s", lfil);
	fstat(fd, &stbuf);
	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
		fseek(malf, let[nlet].adr, L_SET);
		fseek(tmpf, let[nlet].adr, L_SET);
		while ((c = getc(malf)) != EOF)
			putc(c, tmpf);
		let[++nlet].adr = stbuf.st_size;
		new = 1;
		fseek(malf, 0L, L_SET);
	}
	ftruncate(fd, 0L);
	for (i = 0; i < nlet; i++)
		if (let[i].change != 'd')
			copylet(i, malf, ORDINARY);
	fclose(malf);		/* implict unlock */
	if (new)
		printf("New mail has arrived.\n");
	sigsetmask(oldmask);
}

/* copy mail (f1) to temp (f2) */
copymt(f1, f2)
	FILE *f1, *f2;
{
	long nextadr;

	nlet = nextadr = 0;
	let[0].adr = 0;
	while (fgets(line, LSIZE, f1) != NULL) {
		if (isfrom(line))
			let[nlet++].adr = nextadr;
		nextadr += strlen(line);
		fputs(line, f2);
	}
	let[nlet].adr = nextadr;	/* last plus 1 */
}

copylet(n, f, type)
	FILE *f;
{
	int ch;
	long k;
	char hostname[MAXHOSTNAMELEN];

	fseek(tmpf, let[n].adr, L_SET);
	k = let[n+1].adr - let[n].adr;
	while (k-- > 1 && (ch = getc(tmpf)) != '\n')
		if (type != ZAP)
			putc(ch, f);
	switch (type) {

	case REMOTE:
		gethostname(hostname, sizeof (hostname));
		fprintf(f, " remote from %s\n", hostname);
		break;

	case FORWARD:
		fprintf(f, forwmsg);
		break;

	case ORDINARY:
		putc(ch, f);
		break;

	case ZAP:
		break;

	default:
		panic("Bad letter type %d to copylet.", type);
	}
	while (k-- > 1) {
		ch = getc(tmpf);
		putc(ch, f);
	}
	if (type != ZAP || ch != '\n')
		putc(getc(tmpf), f);
}

isfrom(lp)
register char *lp;
{
	register char *p;

	for (p = from; *p; )
		if (*lp++ != *p++)
			return(0);
	return(1);
}

bulkmail(argc, argv)
char **argv;
{
	char *truename;
	int first;
	register char *cp;
	char *newargv[1000];
	register char **ap;
	register char **vp;
	int dflag;

	dflag = 0;
	delflg = 0;
	if (argc < 1) {
		fprintf(stderr, "puke\n");
		return;
	}
	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
		if (ap[0][0] == '-' && ap[0][1] == 'd')
			dflag++;
	if (!dflag) {
		/* give it to sendmail, rah rah! */
		unlink(lettmp);
		ap = newargv+1;
		if (rmail)
			*ap-- = "-s";
		*ap = "-sendmail";
		setuid(getuid());
		execv(_PATH_SENDMAIL, ap);
		perror(_PATH_SENDMAIL);
		exit(EX_UNAVAILABLE);
	}

	truename = 0;
	line[0] = '\0';

	/*
	 * When we fall out of this, argv[1] should be first name,
	 * argc should be number of names + 1.
	 */

	while (argc > 1 && *argv[1] == '-') {
		cp = *++argv;
		argc--;
		switch (cp[1]) {
		case 'r':
			if (argc <= 1)
				usage();
			truename = argv[1];
			fgets(line, LSIZE, stdin);
			if (strncmp("From", line, 4) == 0)
				line[0] = '\0';
			argv++;
			argc--;
			break;

		case 'h':
			if (argc <= 1)
				usage();
			hseqno = atoi(argv[1]);
			argv++;
			argc--;
			break;

		case 'd':
			break;
		
		default:
			usage();
		}
	}
	if (argc <= 1)
		usage();
	if (truename == 0)
		truename = my_name;
	time(&iop);
	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
	iop = ftell(tmpf);
	flgf = first = 1;
	for (;;) {
		if (first) {
			first = 0;
			if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL)
				break;
		} else {
			if (fgets(line, LSIZE, stdin) == NULL)
				break;
		}
		if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin)))
			break;
		if (isfrom(line))
			putc('>', tmpf);
		fputs(line, tmpf);
		flgf = 0;
	}
	putc('\n', tmpf);
	nlet = 1;
	let[0].adr = 0;
	let[1].adr = ftell(tmpf);
	if (flgf)
		return;
	while (--argc > 0)
		if (!sendmail(0, *++argv, truename))
			error++;
	if (error && safefile(dead)) {
		setuid(getuid());
		malf = fopen(dead, "w");
		if (malf == NULL) {
			printf("mail: cannot open %s\n", dead);
			fclose(tmpf);
			return;
		}
		copylet(0, malf, ZAP);
		fclose(malf);
		printf("Mail saved in %s\n", dead);
	}
	fclose(tmpf);
}

sendrmt(n, name)
char *name;
{
	FILE *rmf, *popen();
	register char *p;
	char rsys[64], cmd[64];
	register pid;
	int sts;

#ifdef notdef
	if (any('^', name)) {
		while (p = index(name, '^'))
			*p = '!';
		if (strncmp(name, "researc", 7)) {
			strcpy(rsys, "research");
			if (*name != '!')
				--name;
			goto skip;
		}
	}
#endif
	for (p=rsys; *name!='!'; *p++ = *name++)
		if (*name=='\0')
			return(0);	/* local address, no '!' */
	*p = '\0';
	if (name[1]=='\0') {
		printf("null name\n");
		return(0);
	}
skip:
	if ((pid = fork()) == -1) {
		fprintf(stderr, "mail: can't create proc for remote\n");
		return(0);
	}
	if (pid) {
		while (wait(&sts) != pid) {
			if (wait(&sts)==-1)
				return(0);
		}
		return(!sts);
	}
	setuid(getuid());
	if (any('!', name+1))
		(void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
	else
		(void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
	if ((rmf=popen(cmd, "w")) == NULL)
		exit(1);
	copylet(n, rmf, REMOTE);
	exit(pclose(rmf) != 0);
}

usage()
{

	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
	error = EX_USAGE;
	done();
}

#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>

notifybiff(msg)
	char *msg;
{
	static struct sockaddr_in addr;
	static int f = -1;

	if (addr.sin_family == 0) {
		struct hostent *hp = gethostbyname("localhost");
		struct servent *sp = getservbyname("biff", "udp");

		if (hp && sp) {
			addr.sin_family = hp->h_addrtype;
			bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
			addr.sin_port = sp->s_port;
		}
	}
	if (addr.sin_family) {
		if (f < 0)
			f = socket(AF_INET, SOCK_DGRAM, 0);
		if (f >= 0)
			sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr));
	}
}

sendmail(n, name, fromaddr)
	int n;
	char *name, *fromaddr;
{
	char file[256];
	int mask, fd;
	struct passwd *pw;
#ifdef notdef
	struct stat statb;
#endif
	char buf[128];

	if (*name=='!')
		name++;
	if (any('!', name))
		return (sendrmt(n, name));
	if ((pw = getpwnam(name)) == NULL) {
		printf("mail: can't send to %s\n", name);
		return(0);
	}
	cat(file, maildir, name);
#ifdef notdef
	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
		strcat(file, "/");
		strcat(file, name);
	}
#endif
	if (!safefile(file))
		return(0);
	fd = open(file, O_WRONLY | O_CREAT, MAILMODE);
	if (fd >= 0) {
		flock(fd, LOCK_EX);
		malf = fdopen(fd, "a");
	}
	if (fd < 0 || malf == NULL) {
		close(fd);
		printf("mail: %s: cannot append\n", file);
		return(0);
	}
	fchown(fd, pw->pw_uid, pw->pw_gid);
	(void)sprintf(buf, "%s@@%ld\n", name, ftell(malf));
	copylet(n, malf, ORDINARY);
	fclose(malf);
	notifybiff(buf);
	return(1);
}

delex(i)
{
	if (i != SIGINT) {
		setsig(i, SIG_DFL);
		sigsetmask(sigblock(0L) &~ sigmask(i));
	}
	putc('\n', stderr);
	if (delflg)
		longjmp(sjbuf, 1);
	if (error == 0)
		error = i;
	done();
}

done()
{

	unlink(lettmp);
	exit(error);
}

cat(to, from1, from2)
	char *to, *from1, *from2;
{
	register char *cp, *dp;

	cp = to;
	for (dp = from1; *cp = *dp++; cp++)
		;
	for (dp = from2; *cp++ = *dp++; )
		;
}

/* copy p... into s, update p */
char *
getarg(s, p)
	register char *s, *p;
{
	while (*p == ' ' || *p == '\t')
		p++;
	if (*p == '\n' || *p == '\0')
		return(NULL);
	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
		*s++ = *p++;
	*s = '\0';
	return(p);
}

safefile(f)
	char *f;
{
	struct stat statb;

	if (lstat(f, &statb) < 0)
		return (1);
	if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
		fprintf(stderr,
		    "mail: %s has more than one link or is a symbolic link\n",
		    f);
		return (0);
	}
	return (1);
}

panic(msg, a1, a2, a3)
	char *msg;
{

	fprintf(stderr, "mail: ");
	fprintf(stderr, msg, a1, a2, a3);
	fprintf(stderr, "\n");
	done();
}
@


4.36.0.1
log
@Date:    Fri, 23 Nov 90 14:44:41 +1300
To:      "Paul Pomes, UofIllinois-CSO" <paul@@uxc.cso.uiuc.edu>
From:    Andy.Linton@@comp.vuw.ac.nz
Subject: locking in /bin/mail (with the details (:-))
X-Mailer: XMH (using mh 6.7) 

We use the LCK_BEL locking in 'mh' as we have the spool directory mounted via
NFS. The flock (real or emulated) is not good enough and results in races
which unfortunately end up in "dead heats" at times.
@
text
@a120 4
#if defined(MH_LCK_BEL)
	int lk_fd;
	extern int lkopen(), lkclose();
#endif /* MH_LCK_BEL */
a158 7
#if defined(LOCKF_FLOCK)
	/*
         * We can't get a lock on a file that
         * isn't opened for writing - sigh!
         */
        malf = fopen(mailfile, "r+");
#else
a159 1
#endif /* LOCKF_FLOCK */
a163 3
#if defined(MH_LCK_BEL)
	lk_fd = lkopen(mailfile, O_RDONLY);
#endif /* MH_LCK_BEL */
a166 3
#if defined(MH_LCK_BEL)
	(void) lkclose(lk_fd, mailfile);
#endif /* MH_LCK_BEL */
a307 4
#if defined(MH_LCK_BEL)
	int lk_fd;
	extern int lkopen(), lkclose();
#endif /* MH_LCK_BEL */
d312 2
a313 5
#if defined(MH_LCK_BEL)
	    lk_fd = lkopen(mailfile, O_RDWR);
#endif /* MH_LCK_BEL */
	    flock(fd, LOCK_EX);
	    malf = fdopen(fd, "r+");
a331 3
#if defined(MH_LCK_BEL)
	(void) lkclose(lk_fd, mailfile);
#endif /* MH_LCK_BEL */
a623 4
#if defined(MH_LCK_BEL)
	int lk_fd;
	extern int lkopen(), lkclose();
#endif /* MH_LCK_BEL */
d644 2
a645 5
#if defined(MH_LCK_BEL)
	    lk_fd = lkopen(mailfile, O_RDWR);
#endif /* MH_LCK_BEL */
	    flock(fd, LOCK_EX);
	    malf = fdopen(fd, "a");
a655 4
#if defined(MH_LCK_BEL)
	(void) lkclose(lk_fd, mailfile);
#endif /* MH_LCK_BEL */

@