114465Ssam #ifndef lint
2*37465Sbostic static char sccsid[] = "@(#)mail.local.c	4.36 (Berkeley) 04/21/89";
314465Ssam #endif
414465Ssam 
529763Skarels #include <sys/param.h>
616731Sralph #include <sys/stat.h>
716731Sralph #include <sys/file.h>
816731Sralph 
9579Sroot #include <ctype.h>
10579Sroot #include <stdio.h>
11579Sroot #include <pwd.h>
12579Sroot #include <utmp.h>
13579Sroot #include <signal.h>
14579Sroot #include <setjmp.h>
15579Sroot #include <sysexits.h>
16*37465Sbostic #include "pathnames.h"
17579Sroot 
1816731Sralph 	/* copylet flags */
1916731Sralph #define REMOTE		1		/* remote mail, add rmtmsg */
2016731Sralph #define ORDINARY	2
2116731Sralph #define ZAP		3		/* zap header and trailing empty line */
2216731Sralph #define	FORWARD		4
23579Sroot 
2416731Sralph #define	LSIZE		256
2516731Sralph #define	MAXLET		300		/* maximum number of letters */
2616731Sralph #define	MAILMODE	0600		/* mode of created mail */
27579Sroot 
28579Sroot char	line[LSIZE];
29579Sroot char	resp[LSIZE];
30579Sroot struct let {
31579Sroot 	long	adr;
32579Sroot 	char	change;
33579Sroot } let[MAXLET];
34579Sroot int	nlet	= 0;
35579Sroot char	lfil[50];
36579Sroot long	iop, time();
37579Sroot char	*getenv();
38579Sroot char	*index();
39*37465Sbostic char	lettmp[] = _PATH_TMP;
40*37465Sbostic char	maildir[] = _PATH_MAILDIR;
41579Sroot char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
42579Sroot char	dead[] = "dead.letter";
43579Sroot char	forwmsg[] = " forwarded\n";
44579Sroot FILE	*tmpf;
45579Sroot FILE	*malf;
4629763Skarels char	my_name[60];
47579Sroot char	*getlogin();
48579Sroot int	error;
49579Sroot int	changed;
50579Sroot int	forward;
51579Sroot char	from[] = "From ";
52579Sroot long	ftell();
5316731Sralph int	delex();
54579Sroot char	*ctime();
55579Sroot int	flgf;
56579Sroot int	flgp;
57579Sroot int	delflg = 1;
58579Sroot int	hseqno;
59579Sroot jmp_buf	sjbuf;
60579Sroot int	rmail;
61579Sroot 
62579Sroot main(argc, argv)
63579Sroot char **argv;
64579Sroot {
6533341Sbostic 	register int i;
6629763Skarels 	char *name;
6719868Smiriam 	struct passwd *pwent;
68579Sroot 
6933341Sbostic 	if (!(name = getlogin()) || !*name || !(pwent = getpwnam(name)) ||
7033341Sbostic 	    getuid() != pwent->pw_uid)
71579Sroot 		pwent = getpwuid(getuid());
7233341Sbostic 	strncpy(my_name, pwent ? pwent->pw_name : "???", sizeof(my_name)-1);
7316731Sralph 	if (setjmp(sjbuf))
7416731Sralph 		done();
7514912Sralph 	for (i=SIGHUP; i<=SIGTERM; i++)
7616731Sralph 		setsig(i, delex);
7717533Sralph 	i = mkstemp(lettmp);
7836487Sbostic 	tmpf = fdopen(i, "r+");
7917533Sralph 	if (i < 0 || tmpf == NULL)
8016731Sralph 		panic("mail: %s: cannot open for writing", lettmp);
8116731Sralph 	/*
8216731Sralph 	 * This protects against others reading mail from temp file and
8316731Sralph 	 * if we exit, the file will be deleted already.
8416731Sralph 	 */
8516731Sralph 	unlink(lettmp);
86579Sroot 	if (argv[0][0] == 'r')
87579Sroot 		rmail++;
88579Sroot 	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
89579Sroot 	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
90579Sroot 		printmail(argc, argv);
91579Sroot 	else
926015Swnj 		bulkmail(argc, argv);
93579Sroot 	done();
94579Sroot }
95579Sroot 
96579Sroot setsig(i, f)
97579Sroot int i;
98579Sroot int (*f)();
99579Sroot {
10016731Sralph 	if (signal(i, SIG_IGN) != SIG_IGN)
101579Sroot 		signal(i, f);
102579Sroot }
103579Sroot 
104579Sroot any(c, str)
105579Sroot 	register int c;
106579Sroot 	register char *str;
107579Sroot {
108579Sroot 
109579Sroot 	while (*str)
110579Sroot 		if (c == *str++)
111579Sroot 			return(1);
112579Sroot 	return(0);
113579Sroot }
114579Sroot 
115579Sroot printmail(argc, argv)
11616731Sralph 	char **argv;
117579Sroot {
118579Sroot 	int flg, i, j, print;
119579Sroot 	char *p, *getarg();
120579Sroot 	struct stat statb;
121579Sroot 
122579Sroot 	setuid(getuid());
123579Sroot 	cat(mailfile, maildir, my_name);
12416731Sralph #ifdef notdef
125579Sroot 	if (stat(mailfile, &statb) >= 0
126579Sroot 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
127579Sroot 		strcat(mailfile, "/");
128579Sroot 		strcat(mailfile, my_name);
129579Sroot 	}
13016731Sralph #endif
13116731Sralph 	for (; argc > 1; argv++, argc--) {
13216731Sralph 		if (argv[1][0] != '-')
13316731Sralph 			break;
13416731Sralph 		switch (argv[1][1]) {
13516731Sralph 
13616731Sralph 		case 'p':
13716731Sralph 			flgp++;
13816731Sralph 			/* fall thru... */
13916731Sralph 		case 'q':
14016731Sralph 			delflg = 0;
14116731Sralph 			break;
14216731Sralph 
14316731Sralph 		case 'f':
14416731Sralph 			if (argc >= 3) {
14516731Sralph 				strcpy(mailfile, argv[2]);
14616731Sralph 				argv++, argc--;
147579Sroot 			}
148579Sroot 			break;
14916731Sralph 
15016731Sralph 		case 'b':
15116731Sralph 			forward = 1;
15216731Sralph 			break;
15316731Sralph 
15416731Sralph 		default:
15516731Sralph 			panic("unknown option %c", argv[1][1]);
15616731Sralph 			/*NOTREACHED*/
15716731Sralph 		}
158579Sroot 	}
159579Sroot 	malf = fopen(mailfile, "r");
160579Sroot 	if (malf == NULL) {
16116731Sralph 		printf("No mail.\n");
162579Sroot 		return;
163579Sroot 	}
16416731Sralph 	flock(fileno(malf), LOCK_SH);
165579Sroot 	copymt(malf, tmpf);
16616731Sralph 	fclose(malf);			/* implicit unlock */
16733607Sbostic 	fseek(tmpf, 0L, L_SET);
168579Sroot 
169579Sroot 	changed = 0;
170579Sroot 	print = 1;
171579Sroot 	for (i = 0; i < nlet; ) {
172579Sroot 		j = forward ? i : nlet - i - 1;
17316731Sralph 		if (setjmp(sjbuf)) {
17416731Sralph 			print = 0;
175579Sroot 		} else {
176579Sroot 			if (print)
177579Sroot 				copylet(j, stdout, ORDINARY);
178579Sroot 			print = 1;
179579Sroot 		}
180579Sroot 		if (flgp) {
181579Sroot 			i++;
182579Sroot 			continue;
183579Sroot 		}
184579Sroot 		setjmp(sjbuf);
18516731Sralph 		fputs("? ", stdout);
186579Sroot 		fflush(stdout);
187579Sroot 		if (fgets(resp, LSIZE, stdin) == NULL)
188579Sroot 			break;
189579Sroot 		switch (resp[0]) {
190579Sroot 
191579Sroot 		default:
19216731Sralph 			printf("usage\n");
193579Sroot 		case '?':
194579Sroot 			print = 0;
19516731Sralph 			printf("q\tquit\n");
19616731Sralph 			printf("x\texit without changing mail\n");
19716731Sralph 			printf("p\tprint\n");
19816731Sralph 			printf("s[file]\tsave (default mbox)\n");
19916731Sralph 			printf("w[file]\tsame without header\n");
20016731Sralph 			printf("-\tprint previous\n");
20116731Sralph 			printf("d\tdelete\n");
20216731Sralph 			printf("+\tnext (no delete)\n");
20316731Sralph 			printf("m user\tmail to user\n");
20416731Sralph 			printf("! cmd\texecute cmd\n");
205579Sroot 			break;
206579Sroot 
207579Sroot 		case '+':
208579Sroot 		case 'n':
209579Sroot 		case '\n':
210579Sroot 			i++;
211579Sroot 			break;
212579Sroot 		case 'x':
213579Sroot 			changed = 0;
214579Sroot 		case 'q':
215579Sroot 			goto donep;
216579Sroot 		case 'p':
217579Sroot 			break;
218579Sroot 		case '^':
219579Sroot 		case '-':
220579Sroot 			if (--i < 0)
221579Sroot 				i = 0;
222579Sroot 			break;
223579Sroot 		case 'y':
224579Sroot 		case 'w':
225579Sroot 		case 's':
226579Sroot 			flg = 0;
227579Sroot 			if (resp[1] != '\n' && resp[1] != ' ') {
228579Sroot 				printf("illegal\n");
229579Sroot 				flg++;
230579Sroot 				print = 0;
231579Sroot 				continue;
232579Sroot 			}
233579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
234579Sroot 				p = getenv("HOME");
23516731Sralph 				if (p != 0)
236579Sroot 					cat(resp+1, p, "/mbox");
237579Sroot 				else
238579Sroot 					cat(resp+1, "", "mbox");
239579Sroot 			}
240579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
241579Sroot 				malf = fopen(lfil, "a");
242579Sroot 				if (malf == NULL) {
24316731Sralph 					printf("mail: %s: cannot append\n",
24416731Sralph 					    lfil);
245579Sroot 					flg++;
246579Sroot 					continue;
247579Sroot 				}
248579Sroot 				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
249579Sroot 				fclose(malf);
250579Sroot 			}
251579Sroot 			if (flg)
252579Sroot 				print = 0;
253579Sroot 			else {
254579Sroot 				let[j].change = 'd';
255579Sroot 				changed++;
256579Sroot 				i++;
257579Sroot 			}
258579Sroot 			break;
259579Sroot 		case 'm':
260579Sroot 			flg = 0;
261579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
262579Sroot 				i++;
263579Sroot 				continue;
264579Sroot 			}
265579Sroot 			if (resp[1] != ' ') {
266579Sroot 				printf("invalid command\n");
267579Sroot 				flg++;
268579Sroot 				print = 0;
269579Sroot 				continue;
270579Sroot 			}
271579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
27217019Sralph 				if (!sendmail(j, lfil, my_name))
273579Sroot 					flg++;
274579Sroot 			if (flg)
275579Sroot 				print = 0;
276579Sroot 			else {
277579Sroot 				let[j].change = 'd';
278579Sroot 				changed++;
279579Sroot 				i++;
280579Sroot 			}
281579Sroot 			break;
282579Sroot 		case '!':
283579Sroot 			system(resp+1);
284579Sroot 			printf("!\n");
285579Sroot 			print = 0;
286579Sroot 			break;
287579Sroot 		case 'd':
288579Sroot 			let[j].change = 'd';
289579Sroot 			changed++;
290579Sroot 			i++;
291579Sroot 			if (resp[1] == 'q')
292579Sroot 				goto donep;
293579Sroot 			break;
294579Sroot 		}
295579Sroot 	}
296579Sroot    donep:
297579Sroot 	if (changed)
298579Sroot 		copyback();
299579Sroot }
300579Sroot 
30116731Sralph /* copy temp or whatever back to /usr/spool/mail */
30216731Sralph copyback()
303579Sroot {
30433607Sbostic 	register int i, c;
30533607Sbostic 	long oldmask;
30633607Sbostic 	int fd, new = 0;
307579Sroot 	struct stat stbuf;
308579Sroot 
30933607Sbostic 	oldmask = sigblock(sigmask(SIGINT)|sigmask(SIGHUP)|sigmask(SIGQUIT));
31016731Sralph 	fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE);
31116731Sralph 	if (fd >= 0) {
31216731Sralph 		flock(fd, LOCK_EX);
31336487Sbostic 		malf = fdopen(fd, "r+");
31416731Sralph 	}
31516731Sralph 	if (fd < 0 || malf == NULL)
31616731Sralph 		panic("can't rewrite %s", lfil);
31716731Sralph 	fstat(fd, &stbuf);
318579Sroot 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
31916731Sralph 		fseek(malf, let[nlet].adr, L_SET);
32016731Sralph 		fseek(tmpf, let[nlet].adr, L_SET);
32116731Sralph 		while ((c = getc(malf)) != EOF)
32216731Sralph 			putc(c, tmpf);
323579Sroot 		let[++nlet].adr = stbuf.st_size;
324579Sroot 		new = 1;
32533607Sbostic 		fseek(malf, 0L, L_SET);
326579Sroot 	}
32733607Sbostic 	ftruncate(fd, 0L);
328579Sroot 	for (i = 0; i < nlet; i++)
32916731Sralph 		if (let[i].change != 'd')
330579Sroot 			copylet(i, malf, ORDINARY);
33116731Sralph 	fclose(malf);		/* implict unlock */
332579Sroot 	if (new)
33316731Sralph 		printf("New mail has arrived.\n");
33416731Sralph 	sigsetmask(oldmask);
335579Sroot }
336579Sroot 
33716731Sralph /* copy mail (f1) to temp (f2) */
33816731Sralph copymt(f1, f2)
33916731Sralph 	FILE *f1, *f2;
340579Sroot {
341579Sroot 	long nextadr;
342579Sroot 
343579Sroot 	nlet = nextadr = 0;
344579Sroot 	let[0].adr = 0;
345579Sroot 	while (fgets(line, LSIZE, f1) != NULL) {
346579Sroot 		if (isfrom(line))
347579Sroot 			let[nlet++].adr = nextadr;
348579Sroot 		nextadr += strlen(line);
349579Sroot 		fputs(line, f2);
350579Sroot 	}
351579Sroot 	let[nlet].adr = nextadr;	/* last plus 1 */
352579Sroot }
353579Sroot 
35411893Seric copylet(n, f, type)
35511893Seric 	FILE *f;
35611893Seric {
35711893Seric 	int ch;
35811893Seric 	long k;
35929763Skarels 	char hostname[MAXHOSTNAMELEN];
36011893Seric 
36116731Sralph 	fseek(tmpf, let[n].adr, L_SET);
362579Sroot 	k = let[n+1].adr - let[n].adr;
36316731Sralph 	while (k-- > 1 && (ch = getc(tmpf)) != '\n')
36416731Sralph 		if (type != ZAP)
36516731Sralph 			putc(ch, f);
36616731Sralph 	switch (type) {
36716731Sralph 
36816731Sralph 	case REMOTE:
3696199Sroot 		gethostname(hostname, sizeof (hostname));
3706199Sroot 		fprintf(f, " remote from %s\n", hostname);
37116731Sralph 		break;
37216731Sralph 
37316731Sralph 	case FORWARD:
374579Sroot 		fprintf(f, forwmsg);
37516731Sralph 		break;
37616731Sralph 
37716731Sralph 	case ORDINARY:
37816731Sralph 		putc(ch, f);
37916731Sralph 		break;
38016731Sralph 
38117019Sralph 	case ZAP:
38217019Sralph 		break;
38317019Sralph 
38416731Sralph 	default:
38516731Sralph 		panic("Bad letter type %d to copylet.", type);
38616731Sralph 	}
38716731Sralph 	while (k-- > 1) {
38816731Sralph 		ch = getc(tmpf);
38916731Sralph 		putc(ch, f);
39016731Sralph 	}
39116731Sralph 	if (type != ZAP || ch != '\n')
39216731Sralph 		putc(getc(tmpf), f);
393579Sroot }
394579Sroot 
395579Sroot isfrom(lp)
396579Sroot register char *lp;
397579Sroot {
398579Sroot 	register char *p;
399579Sroot 
400579Sroot 	for (p = from; *p; )
401579Sroot 		if (*lp++ != *p++)
402579Sroot 			return(0);
403579Sroot 	return(1);
404579Sroot }
405579Sroot 
4066015Swnj bulkmail(argc, argv)
407579Sroot char **argv;
408579Sroot {
40929763Skarels 	char *truename;
410579Sroot 	int first;
411579Sroot 	register char *cp;
412579Sroot 	char *newargv[1000];
413579Sroot 	register char **ap;
414579Sroot 	register char **vp;
415579Sroot 	int dflag;
416579Sroot 
417579Sroot 	dflag = 0;
41829763Skarels 	delflg = 0;
41916731Sralph 	if (argc < 1) {
420579Sroot 		fprintf(stderr, "puke\n");
42116731Sralph 		return;
42216731Sralph 	}
423579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
424579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
425579Sroot 			dflag++;
42616731Sralph 	if (!dflag) {
4279978Seric 		/* give it to sendmail, rah rah! */
428579Sroot 		unlink(lettmp);
429579Sroot 		ap = newargv+1;
430579Sroot 		if (rmail)
431579Sroot 			*ap-- = "-s";
4329978Seric 		*ap = "-sendmail";
4334461Sroot 		setuid(getuid());
434*37465Sbostic 		execv(_PATH_SENDMAIL, ap);
435*37465Sbostic 		perror(_PATH_SENDMAIL);
436579Sroot 		exit(EX_UNAVAILABLE);
437579Sroot 	}
438579Sroot 
43929763Skarels 	truename = 0;
440579Sroot 	line[0] = '\0';
441579Sroot 
442579Sroot 	/*
443579Sroot 	 * When we fall out of this, argv[1] should be first name,
444579Sroot 	 * argc should be number of names + 1.
445579Sroot 	 */
446579Sroot 
447579Sroot 	while (argc > 1 && *argv[1] == '-') {
448579Sroot 		cp = *++argv;
449579Sroot 		argc--;
450579Sroot 		switch (cp[1]) {
451579Sroot 		case 'r':
45216731Sralph 			if (argc <= 1)
453579Sroot 				usage();
45429763Skarels 			truename = argv[1];
45515346Skarels 			fgets(line, LSIZE, stdin);
45635645Sbostic 			if (strncmp("From", line, 4) == 0)
45715346Skarels 				line[0] = '\0';
458579Sroot 			argv++;
459579Sroot 			argc--;
460579Sroot 			break;
461579Sroot 
462579Sroot 		case 'h':
46316731Sralph 			if (argc <= 1)
464579Sroot 				usage();
465579Sroot 			hseqno = atoi(argv[1]);
466579Sroot 			argv++;
467579Sroot 			argc--;
468579Sroot 			break;
469579Sroot 
470579Sroot 		case 'd':
471579Sroot 			break;
472579Sroot 
473579Sroot 		default:
474579Sroot 			usage();
475579Sroot 		}
476579Sroot 	}
47716731Sralph 	if (argc <= 1)
478579Sroot 		usage();
47929763Skarels 	if (truename == 0)
48029763Skarels 		truename = my_name;
481579Sroot 	time(&iop);
482579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
483579Sroot 	iop = ftell(tmpf);
48416731Sralph 	flgf = first = 1;
48516731Sralph 	for (;;) {
48616731Sralph 		if (first) {
48716731Sralph 			first = 0;
48816731Sralph 			if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL)
48916731Sralph 				break;
49016731Sralph 		} else {
49116731Sralph 			if (fgets(line, LSIZE, stdin) == NULL)
49216731Sralph 				break;
49316731Sralph 		}
49416731Sralph 		if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin)))
495579Sroot 			break;
496579Sroot 		if (isfrom(line))
49716731Sralph 			putc('>', tmpf);
498579Sroot 		fputs(line, tmpf);
499579Sroot 		flgf = 0;
500579Sroot 	}
50116731Sralph 	putc('\n', tmpf);
502579Sroot 	nlet = 1;
503579Sroot 	let[0].adr = 0;
504579Sroot 	let[1].adr = ftell(tmpf);
505579Sroot 	if (flgf)
506579Sroot 		return;
50716731Sralph 	while (--argc > 0)
5086015Swnj 		if (!sendmail(0, *++argv, truename))
509579Sroot 			error++;
51010644Seric 	if (error && safefile(dead)) {
511579Sroot 		setuid(getuid());
512579Sroot 		malf = fopen(dead, "w");
513579Sroot 		if (malf == NULL) {
51416731Sralph 			printf("mail: cannot open %s\n", dead);
515579Sroot 			fclose(tmpf);
516579Sroot 			return;
517579Sroot 		}
518579Sroot 		copylet(0, malf, ZAP);
519579Sroot 		fclose(malf);
52016731Sralph 		printf("Mail saved in %s\n", dead);
521579Sroot 	}
522579Sroot 	fclose(tmpf);
523579Sroot }
524579Sroot 
52517019Sralph sendrmt(n, name)
526579Sroot char *name;
527579Sroot {
528579Sroot 	FILE *rmf, *popen();
529579Sroot 	register char *p;
530579Sroot 	char rsys[64], cmd[64];
53117019Sralph 	register pid;
532579Sroot 	int sts;
533579Sroot 
53417019Sralph #ifdef notdef
53517019Sralph 	if (any('^', name)) {
536579Sroot 		while (p = index(name, '^'))
537579Sroot 			*p = '!';
538579Sroot 		if (strncmp(name, "researc", 7)) {
539579Sroot 			strcpy(rsys, "research");
540579Sroot 			if (*name != '!')
541579Sroot 				--name;
542579Sroot 			goto skip;
543579Sroot 		}
544579Sroot 	}
54517019Sralph #endif
54617019Sralph 	for (p=rsys; *name!='!'; *p++ = *name++)
54717019Sralph 		if (*name=='\0')
54817019Sralph 			return(0);	/* local address, no '!' */
549579Sroot 	*p = '\0';
55017019Sralph 	if (name[1]=='\0') {
55116731Sralph 		printf("null name\n");
552579Sroot 		return(0);
553579Sroot 	}
554579Sroot skip:
555579Sroot 	if ((pid = fork()) == -1) {
556579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
557579Sroot 		return(0);
558579Sroot 	}
559579Sroot 	if (pid) {
560579Sroot 		while (wait(&sts) != pid) {
561579Sroot 			if (wait(&sts)==-1)
562579Sroot 				return(0);
563579Sroot 		}
564579Sroot 		return(!sts);
565579Sroot 	}
566579Sroot 	setuid(getuid());
56717019Sralph 	if (any('!', name+1))
56832414Sbostic 		(void)sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
56917019Sralph 	else
57032414Sbostic 		(void)sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
571579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
572579Sroot 		exit(1);
57317019Sralph 	copylet(n, rmf, REMOTE);
57410783Seric 	exit(pclose(rmf) != 0);
575579Sroot }
576579Sroot 
577579Sroot usage()
578579Sroot {
579579Sroot 
580579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
58115299Skarels 	error = EX_USAGE;
58216731Sralph 	done();
583579Sroot }
584579Sroot 
5856015Swnj #include <sys/socket.h>
5869226Ssam #include <netinet/in.h>
58710227Ssam #include <netdb.h>
5886015Swnj 
58916731Sralph notifybiff(msg)
59016731Sralph 	char *msg;
59116731Sralph {
59216731Sralph 	static struct sockaddr_in addr;
59316731Sralph 	static int f = -1;
59416731Sralph 
59516731Sralph 	if (addr.sin_family == 0) {
59616731Sralph 		struct hostent *hp = gethostbyname("localhost");
59716731Sralph 		struct servent *sp = getservbyname("biff", "udp");
59816731Sralph 
59916731Sralph 		if (hp && sp) {
60016731Sralph 			addr.sin_family = hp->h_addrtype;
60116731Sralph 			bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
60216731Sralph 			addr.sin_port = sp->s_port;
60316731Sralph 		}
60416731Sralph 	}
60516731Sralph 	if (addr.sin_family) {
60616731Sralph 		if (f < 0)
60716731Sralph 			f = socket(AF_INET, SOCK_DGRAM, 0);
60831237Sbostic 		if (f >= 0)
60931237Sbostic 			sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr));
61016731Sralph 	}
61116731Sralph }
61216731Sralph 
6136015Swnj sendmail(n, name, fromaddr)
61416731Sralph 	int n;
61516731Sralph 	char *name, *fromaddr;
616579Sroot {
61716731Sralph 	char file[256];
61816731Sralph 	int mask, fd;
61916731Sralph 	struct passwd *pw;
62016731Sralph #ifdef notdef
621579Sroot 	struct stat statb;
62216731Sralph #endif
6233666Swnj 	char buf[128];
624579Sroot 
62517019Sralph 	if (*name=='!')
62617019Sralph 		name++;
62717019Sralph 	if (any('!', name))
62817019Sralph 		return (sendrmt(n, name));
629579Sroot 	if ((pw = getpwnam(name)) == NULL) {
63016731Sralph 		printf("mail: can't send to %s\n", name);
631579Sroot 		return(0);
632579Sroot 	}
633579Sroot 	cat(file, maildir, name);
63416731Sralph #ifdef notdef
635579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
636579Sroot 		strcat(file, "/");
637579Sroot 		strcat(file, name);
638579Sroot 	}
63916731Sralph #endif
64010644Seric 	if (!safefile(file))
6414458Sroot 		return(0);
64216731Sralph 	fd = open(file, O_WRONLY | O_CREAT, MAILMODE);
64316731Sralph 	if (fd >= 0) {
64416731Sralph 		flock(fd, LOCK_EX);
64516731Sralph 		malf = fdopen(fd, "a");
64616731Sralph 	}
64716731Sralph 	if (fd < 0 || malf == NULL) {
64816731Sralph 		close(fd);
64916731Sralph 		printf("mail: %s: cannot append\n", file);
650579Sroot 		return(0);
651579Sroot 	}
65216731Sralph 	fchown(fd, pw->pw_uid, pw->pw_gid);
65333607Sbostic 	(void)sprintf(buf, "%s@%ld\n", name, ftell(malf));
654579Sroot 	copylet(n, malf, ORDINARY);
6556015Swnj 	fclose(malf);
65616731Sralph 	notifybiff(buf);
657579Sroot 	return(1);
658579Sroot }
659579Sroot 
66016731Sralph delex(i)
661579Sroot {
66229763Skarels 	if (i != SIGINT) {
66329763Skarels 		setsig(i, SIG_DFL);
66433608Sbostic 		sigsetmask(sigblock(0L) &~ sigmask(i));
66529763Skarels 	}
66616731Sralph 	putc('\n', stderr);
66716731Sralph 	if (delflg)
668579Sroot 		longjmp(sjbuf, 1);
66929763Skarels 	if (error == 0)
67029763Skarels 		error = i;
671579Sroot 	done();
672579Sroot }
673579Sroot 
67416731Sralph done()
675579Sroot {
676579Sroot 
677579Sroot 	unlink(lettmp);
678579Sroot 	exit(error);
679579Sroot }
680579Sroot 
681579Sroot cat(to, from1, from2)
68216731Sralph 	char *to, *from1, *from2;
683579Sroot {
68416731Sralph 	register char *cp, *dp;
685579Sroot 
68616731Sralph 	cp = to;
68716731Sralph 	for (dp = from1; *cp = *dp++; cp++)
68816731Sralph 		;
68916731Sralph 	for (dp = from2; *cp++ = *dp++; )
69016731Sralph 		;
691579Sroot }
692579Sroot 
69316731Sralph /* copy p... into s, update p */
69416731Sralph char *
69516731Sralph getarg(s, p)
69616731Sralph 	register char *s, *p;
697579Sroot {
698579Sroot 	while (*p == ' ' || *p == '\t')
699579Sroot 		p++;
700579Sroot 	if (*p == '\n' || *p == '\0')
701579Sroot 		return(NULL);
702579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
703579Sroot 		*s++ = *p++;
704579Sroot 	*s = '\0';
705579Sroot 	return(p);
706579Sroot }
70710644Seric 
70810644Seric safefile(f)
70910644Seric 	char *f;
71010644Seric {
71110644Seric 	struct stat statb;
71210644Seric 
71310644Seric 	if (lstat(f, &statb) < 0)
71410644Seric 		return (1);
71510644Seric 	if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
71616731Sralph 		fprintf(stderr,
71716731Sralph 		    "mail: %s has more than one link or is a symbolic link\n",
71816731Sralph 		    f);
71910644Seric 		return (0);
72010644Seric 	}
72110644Seric 	return (1);
72210644Seric }
72316731Sralph 
72416731Sralph panic(msg, a1, a2, a3)
72516731Sralph 	char *msg;
72616731Sralph {
72716731Sralph 
72816731Sralph 	fprintf(stderr, "mail: ");
72916731Sralph 	fprintf(stderr, msg, a1, a2, a3);
73016731Sralph 	fprintf(stderr, "\n");
73116731Sralph 	done();
73216731Sralph }
733