114465Ssam #ifndef lint
2*19868Smiriam static char sccsid[] = "@(#)mail.local.c	4.25 (Berkeley) 05/01/85";
314465Ssam #endif
414465Ssam 
516731Sralph #include <sys/types.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>
16579Sroot 
179978Seric #define SENDMAIL	"/usr/lib/sendmail"
18579Sroot 
1916731Sralph 	/* copylet flags */
2016731Sralph #define REMOTE		1		/* remote mail, add rmtmsg */
2116731Sralph #define ORDINARY	2
2216731Sralph #define ZAP		3		/* zap header and trailing empty line */
2316731Sralph #define	FORWARD		4
24579Sroot 
2516731Sralph #define	LSIZE		256
2616731Sralph #define	MAXLET		300		/* maximum number of letters */
2716731Sralph #define	MAILMODE	0600		/* mode of created mail */
28579Sroot 
29579Sroot char	line[LSIZE];
30579Sroot char	resp[LSIZE];
31579Sroot struct let {
32579Sroot 	long	adr;
33579Sroot 	char	change;
34579Sroot } let[MAXLET];
35579Sroot int	nlet	= 0;
36579Sroot char	lfil[50];
37579Sroot long	iop, time();
38579Sroot char	*getenv();
39579Sroot char	*index();
40579Sroot char	lettmp[] = "/tmp/maXXXXX";
41579Sroot char	maildir[] = "/usr/spool/mail/";
42579Sroot char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
43579Sroot char	dead[] = "dead.letter";
44579Sroot char	forwmsg[] = " forwarded\n";
45579Sroot FILE	*tmpf;
46579Sroot FILE	*malf;
47579Sroot char	*my_name;
48579Sroot char	*getlogin();
49579Sroot int	error;
50579Sroot int	changed;
51579Sroot int	forward;
52579Sroot char	from[] = "From ";
53579Sroot long	ftell();
5416731Sralph int	delex();
55579Sroot char	*ctime();
56579Sroot int	flgf;
57579Sroot int	flgp;
58579Sroot int	delflg = 1;
59579Sroot int	hseqno;
60579Sroot jmp_buf	sjbuf;
61579Sroot int	rmail;
62579Sroot 
63579Sroot main(argc, argv)
64579Sroot char **argv;
65579Sroot {
66579Sroot 	register i;
67*19868Smiriam 	struct passwd *pwent;
68579Sroot 
69579Sroot 	my_name = getlogin();
7016731Sralph 	if (my_name == NULL || *my_name == '\0') {
71579Sroot 		pwent = getpwuid(getuid());
72579Sroot 		if (pwent==NULL)
73579Sroot 			my_name = "???";
74579Sroot 		else
75579Sroot 			my_name = pwent->pw_name;
76579Sroot 	}
77*19868Smiriam 	else {
78*19868Smiriam 		pwent = getpwnam(my_name);
79*19868Smiriam 		if ( getuid() != pwent->pw_uid) {
80*19868Smiriam 			pwent = getpwuid(getuid());
81*19868Smiriam 			my_name = pwent->pw_name;
82*19868Smiriam 		}
83*19868Smiriam 	}
8416731Sralph 	if (setjmp(sjbuf))
8516731Sralph 		done();
8614912Sralph 	for (i=SIGHUP; i<=SIGTERM; i++)
8716731Sralph 		setsig(i, delex);
8817533Sralph 	i = mkstemp(lettmp);
8917533Sralph 	tmpf = fdopen(i, "r+w");
9017533Sralph 	if (i < 0 || tmpf == NULL)
9116731Sralph 		panic("mail: %s: cannot open for writing", lettmp);
9216731Sralph 	/*
9316731Sralph 	 * This protects against others reading mail from temp file and
9416731Sralph 	 * if we exit, the file will be deleted already.
9516731Sralph 	 */
9616731Sralph 	unlink(lettmp);
97579Sroot 	if (argv[0][0] == 'r')
98579Sroot 		rmail++;
99579Sroot 	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
100579Sroot 	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
101579Sroot 		printmail(argc, argv);
102579Sroot 	else
1036015Swnj 		bulkmail(argc, argv);
104579Sroot 	done();
105579Sroot }
106579Sroot 
107579Sroot setsig(i, f)
108579Sroot int i;
109579Sroot int (*f)();
110579Sroot {
11116731Sralph 	if (signal(i, SIG_IGN) != SIG_IGN)
112579Sroot 		signal(i, f);
113579Sroot }
114579Sroot 
115579Sroot any(c, str)
116579Sroot 	register int c;
117579Sroot 	register char *str;
118579Sroot {
119579Sroot 
120579Sroot 	while (*str)
121579Sroot 		if (c == *str++)
122579Sroot 			return(1);
123579Sroot 	return(0);
124579Sroot }
125579Sroot 
126579Sroot printmail(argc, argv)
12716731Sralph 	char **argv;
128579Sroot {
129579Sroot 	int flg, i, j, print;
130579Sroot 	char *p, *getarg();
131579Sroot 	struct stat statb;
132579Sroot 
133579Sroot 	setuid(getuid());
134579Sroot 	cat(mailfile, maildir, my_name);
13516731Sralph #ifdef notdef
136579Sroot 	if (stat(mailfile, &statb) >= 0
137579Sroot 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
138579Sroot 		strcat(mailfile, "/");
139579Sroot 		strcat(mailfile, my_name);
140579Sroot 	}
14116731Sralph #endif
14216731Sralph 	for (; argc > 1; argv++, argc--) {
14316731Sralph 		if (argv[1][0] != '-')
14416731Sralph 			break;
14516731Sralph 		switch (argv[1][1]) {
14616731Sralph 
14716731Sralph 		case 'p':
14816731Sralph 			flgp++;
14916731Sralph 			/* fall thru... */
15016731Sralph 		case 'q':
15116731Sralph 			delflg = 0;
15216731Sralph 			break;
15316731Sralph 
15416731Sralph 		case 'f':
15516731Sralph 			if (argc >= 3) {
15616731Sralph 				strcpy(mailfile, argv[2]);
15716731Sralph 				argv++, argc--;
158579Sroot 			}
159579Sroot 			break;
16016731Sralph 
16116731Sralph 		case 'b':
16216731Sralph 			forward = 1;
16316731Sralph 			break;
16416731Sralph 
16516731Sralph 		default:
16616731Sralph 			panic("unknown option %c", argv[1][1]);
16716731Sralph 			/*NOTREACHED*/
16816731Sralph 		}
169579Sroot 	}
170579Sroot 	malf = fopen(mailfile, "r");
171579Sroot 	if (malf == NULL) {
17216731Sralph 		printf("No mail.\n");
173579Sroot 		return;
174579Sroot 	}
17516731Sralph 	flock(fileno(malf), LOCK_SH);
176579Sroot 	copymt(malf, tmpf);
17716731Sralph 	fclose(malf);			/* implicit unlock */
17816731Sralph 	fseek(tmpf, 0, L_SET);
179579Sroot 
180579Sroot 	changed = 0;
181579Sroot 	print = 1;
182579Sroot 	for (i = 0; i < nlet; ) {
183579Sroot 		j = forward ? i : nlet - i - 1;
18416731Sralph 		if (setjmp(sjbuf)) {
18516731Sralph 			print = 0;
186579Sroot 		} else {
187579Sroot 			if (print)
188579Sroot 				copylet(j, stdout, ORDINARY);
189579Sroot 			print = 1;
190579Sroot 		}
191579Sroot 		if (flgp) {
192579Sroot 			i++;
193579Sroot 			continue;
194579Sroot 		}
195579Sroot 		setjmp(sjbuf);
19616731Sralph 		fputs("? ", stdout);
197579Sroot 		fflush(stdout);
198579Sroot 		if (fgets(resp, LSIZE, stdin) == NULL)
199579Sroot 			break;
200579Sroot 		switch (resp[0]) {
201579Sroot 
202579Sroot 		default:
20316731Sralph 			printf("usage\n");
204579Sroot 		case '?':
205579Sroot 			print = 0;
20616731Sralph 			printf("q\tquit\n");
20716731Sralph 			printf("x\texit without changing mail\n");
20816731Sralph 			printf("p\tprint\n");
20916731Sralph 			printf("s[file]\tsave (default mbox)\n");
21016731Sralph 			printf("w[file]\tsame without header\n");
21116731Sralph 			printf("-\tprint previous\n");
21216731Sralph 			printf("d\tdelete\n");
21316731Sralph 			printf("+\tnext (no delete)\n");
21416731Sralph 			printf("m user\tmail to user\n");
21516731Sralph 			printf("! cmd\texecute cmd\n");
216579Sroot 			break;
217579Sroot 
218579Sroot 		case '+':
219579Sroot 		case 'n':
220579Sroot 		case '\n':
221579Sroot 			i++;
222579Sroot 			break;
223579Sroot 		case 'x':
224579Sroot 			changed = 0;
225579Sroot 		case 'q':
226579Sroot 			goto donep;
227579Sroot 		case 'p':
228579Sroot 			break;
229579Sroot 		case '^':
230579Sroot 		case '-':
231579Sroot 			if (--i < 0)
232579Sroot 				i = 0;
233579Sroot 			break;
234579Sroot 		case 'y':
235579Sroot 		case 'w':
236579Sroot 		case 's':
237579Sroot 			flg = 0;
238579Sroot 			if (resp[1] != '\n' && resp[1] != ' ') {
239579Sroot 				printf("illegal\n");
240579Sroot 				flg++;
241579Sroot 				print = 0;
242579Sroot 				continue;
243579Sroot 			}
244579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
245579Sroot 				p = getenv("HOME");
24616731Sralph 				if (p != 0)
247579Sroot 					cat(resp+1, p, "/mbox");
248579Sroot 				else
249579Sroot 					cat(resp+1, "", "mbox");
250579Sroot 			}
251579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
252579Sroot 				malf = fopen(lfil, "a");
253579Sroot 				if (malf == NULL) {
25416731Sralph 					printf("mail: %s: cannot append\n",
25516731Sralph 					    lfil);
256579Sroot 					flg++;
257579Sroot 					continue;
258579Sroot 				}
259579Sroot 				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
260579Sroot 				fclose(malf);
261579Sroot 			}
262579Sroot 			if (flg)
263579Sroot 				print = 0;
264579Sroot 			else {
265579Sroot 				let[j].change = 'd';
266579Sroot 				changed++;
267579Sroot 				i++;
268579Sroot 			}
269579Sroot 			break;
270579Sroot 		case 'm':
271579Sroot 			flg = 0;
272579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
273579Sroot 				i++;
274579Sroot 				continue;
275579Sroot 			}
276579Sroot 			if (resp[1] != ' ') {
277579Sroot 				printf("invalid command\n");
278579Sroot 				flg++;
279579Sroot 				print = 0;
280579Sroot 				continue;
281579Sroot 			}
282579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
28317019Sralph 				if (!sendmail(j, lfil, my_name))
284579Sroot 					flg++;
285579Sroot 			if (flg)
286579Sroot 				print = 0;
287579Sroot 			else {
288579Sroot 				let[j].change = 'd';
289579Sroot 				changed++;
290579Sroot 				i++;
291579Sroot 			}
292579Sroot 			break;
293579Sroot 		case '!':
294579Sroot 			system(resp+1);
295579Sroot 			printf("!\n");
296579Sroot 			print = 0;
297579Sroot 			break;
298579Sroot 		case 'd':
299579Sroot 			let[j].change = 'd';
300579Sroot 			changed++;
301579Sroot 			i++;
302579Sroot 			if (resp[1] == 'q')
303579Sroot 				goto donep;
304579Sroot 			break;
305579Sroot 		}
306579Sroot 	}
307579Sroot    donep:
308579Sroot 	if (changed)
309579Sroot 		copyback();
310579Sroot }
311579Sroot 
31216731Sralph /* copy temp or whatever back to /usr/spool/mail */
31316731Sralph copyback()
314579Sroot {
31516731Sralph 	register i, c;
31616731Sralph 	int fd, new = 0, oldmask;
317579Sroot 	struct stat stbuf;
318579Sroot 
31916731Sralph #define	mask(s)	(1 << ((s) - 1))
32016731Sralph 	oldmask = sigblock(mask(SIGINT)|mask(SIGHUP)|mask(SIGQUIT));
32116731Sralph #undef mask
32216731Sralph 	fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE);
32316731Sralph 	if (fd >= 0) {
32416731Sralph 		flock(fd, LOCK_EX);
32516731Sralph 		malf = fdopen(fd, "r+w");
32616731Sralph 	}
32716731Sralph 	if (fd < 0 || malf == NULL)
32816731Sralph 		panic("can't rewrite %s", lfil);
32916731Sralph 	fstat(fd, &stbuf);
330579Sroot 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
33116731Sralph 		fseek(malf, let[nlet].adr, L_SET);
33216731Sralph 		fseek(tmpf, let[nlet].adr, L_SET);
33316731Sralph 		while ((c = getc(malf)) != EOF)
33416731Sralph 			putc(c, tmpf);
335579Sroot 		let[++nlet].adr = stbuf.st_size;
336579Sroot 		new = 1;
33716731Sralph 		fseek(malf, 0, L_SET);
338579Sroot 	}
33916731Sralph 	ftruncate(fd, 0);
340579Sroot 	for (i = 0; i < nlet; i++)
34116731Sralph 		if (let[i].change != 'd')
342579Sroot 			copylet(i, malf, ORDINARY);
34316731Sralph 	fclose(malf);		/* implict unlock */
344579Sroot 	if (new)
34516731Sralph 		printf("New mail has arrived.\n");
34616731Sralph 	sigsetmask(oldmask);
347579Sroot }
348579Sroot 
34916731Sralph /* copy mail (f1) to temp (f2) */
35016731Sralph copymt(f1, f2)
35116731Sralph 	FILE *f1, *f2;
352579Sroot {
353579Sroot 	long nextadr;
354579Sroot 
355579Sroot 	nlet = nextadr = 0;
356579Sroot 	let[0].adr = 0;
357579Sroot 	while (fgets(line, LSIZE, f1) != NULL) {
358579Sroot 		if (isfrom(line))
359579Sroot 			let[nlet++].adr = nextadr;
360579Sroot 		nextadr += strlen(line);
361579Sroot 		fputs(line, f2);
362579Sroot 	}
363579Sroot 	let[nlet].adr = nextadr;	/* last plus 1 */
364579Sroot }
365579Sroot 
36611893Seric copylet(n, f, type)
36711893Seric 	FILE *f;
36811893Seric {
36911893Seric 	int ch;
37011893Seric 	long k;
37116731Sralph 	char hostname[32];
37211893Seric 
37316731Sralph 	fseek(tmpf, let[n].adr, L_SET);
374579Sroot 	k = let[n+1].adr - let[n].adr;
37516731Sralph 	while (k-- > 1 && (ch = getc(tmpf)) != '\n')
37616731Sralph 		if (type != ZAP)
37716731Sralph 			putc(ch, f);
37816731Sralph 	switch (type) {
37916731Sralph 
38016731Sralph 	case REMOTE:
3816199Sroot 		gethostname(hostname, sizeof (hostname));
3826199Sroot 		fprintf(f, " remote from %s\n", hostname);
38316731Sralph 		break;
38416731Sralph 
38516731Sralph 	case FORWARD:
386579Sroot 		fprintf(f, forwmsg);
38716731Sralph 		break;
38816731Sralph 
38916731Sralph 	case ORDINARY:
39016731Sralph 		putc(ch, f);
39116731Sralph 		break;
39216731Sralph 
39317019Sralph 	case ZAP:
39417019Sralph 		break;
39517019Sralph 
39616731Sralph 	default:
39716731Sralph 		panic("Bad letter type %d to copylet.", type);
39816731Sralph 	}
39916731Sralph 	while (k-- > 1) {
40016731Sralph 		ch = getc(tmpf);
40116731Sralph 		putc(ch, f);
40216731Sralph 	}
40316731Sralph 	if (type != ZAP || ch != '\n')
40416731Sralph 		putc(getc(tmpf), f);
405579Sroot }
406579Sroot 
407579Sroot isfrom(lp)
408579Sroot register char *lp;
409579Sroot {
410579Sroot 	register char *p;
411579Sroot 
412579Sroot 	for (p = from; *p; )
413579Sroot 		if (*lp++ != *p++)
414579Sroot 			return(0);
415579Sroot 	return(1);
416579Sroot }
417579Sroot 
4186015Swnj bulkmail(argc, argv)
419579Sroot char **argv;
420579Sroot {
421579Sroot 	char truename[100];
422579Sroot 	int first;
423579Sroot 	register char *cp;
424579Sroot 	int gaver = 0;
425579Sroot 	char *newargv[1000];
426579Sroot 	register char **ap;
427579Sroot 	register char **vp;
428579Sroot 	int dflag;
429579Sroot 
430579Sroot 	dflag = 0;
43116731Sralph 	if (argc < 1) {
432579Sroot 		fprintf(stderr, "puke\n");
43316731Sralph 		return;
43416731Sralph 	}
435579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
436579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
437579Sroot 			dflag++;
43816731Sralph 	if (!dflag) {
4399978Seric 		/* give it to sendmail, rah rah! */
440579Sroot 		unlink(lettmp);
441579Sroot 		ap = newargv+1;
442579Sroot 		if (rmail)
443579Sroot 			*ap-- = "-s";
4449978Seric 		*ap = "-sendmail";
4454461Sroot 		setuid(getuid());
4469978Seric 		execv(SENDMAIL, ap);
4479978Seric 		perror(SENDMAIL);
448579Sroot 		exit(EX_UNAVAILABLE);
449579Sroot 	}
450579Sroot 
451579Sroot 	truename[0] = 0;
452579Sroot 	line[0] = '\0';
453579Sroot 
454579Sroot 	/*
455579Sroot 	 * When we fall out of this, argv[1] should be first name,
456579Sroot 	 * argc should be number of names + 1.
457579Sroot 	 */
458579Sroot 
459579Sroot 	while (argc > 1 && *argv[1] == '-') {
460579Sroot 		cp = *++argv;
461579Sroot 		argc--;
462579Sroot 		switch (cp[1]) {
463579Sroot 		case 'r':
46416731Sralph 			if (argc <= 1)
465579Sroot 				usage();
46615346Skarels 			gaver++;
46715346Skarels 			strcpy(truename, argv[1]);
46815346Skarels 			fgets(line, LSIZE, stdin);
46915346Skarels 			if (strcmpn("From", line, 4) == 0)
47015346Skarels 				line[0] = '\0';
471579Sroot 			argv++;
472579Sroot 			argc--;
473579Sroot 			break;
474579Sroot 
475579Sroot 		case 'h':
47616731Sralph 			if (argc <= 1)
477579Sroot 				usage();
478579Sroot 			hseqno = atoi(argv[1]);
479579Sroot 			argv++;
480579Sroot 			argc--;
481579Sroot 			break;
482579Sroot 
483579Sroot 		case 'd':
484579Sroot 			break;
485579Sroot 
486579Sroot 		default:
487579Sroot 			usage();
488579Sroot 		}
489579Sroot 	}
49016731Sralph 	if (argc <= 1)
491579Sroot 		usage();
492579Sroot 	if (gaver == 0)
493579Sroot 		strcpy(truename, my_name);
494579Sroot 	time(&iop);
495579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
496579Sroot 	iop = ftell(tmpf);
49716731Sralph 	flgf = first = 1;
49816731Sralph 	for (;;) {
49916731Sralph 		if (first) {
50016731Sralph 			first = 0;
50116731Sralph 			if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL)
50216731Sralph 				break;
50316731Sralph 		} else {
50416731Sralph 			if (fgets(line, LSIZE, stdin) == NULL)
50516731Sralph 				break;
50616731Sralph 		}
50716731Sralph 		if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin)))
508579Sroot 			break;
509579Sroot 		if (isfrom(line))
51016731Sralph 			putc('>', tmpf);
511579Sroot 		fputs(line, tmpf);
512579Sroot 		flgf = 0;
513579Sroot 	}
51416731Sralph 	putc('\n', tmpf);
515579Sroot 	nlet = 1;
516579Sroot 	let[0].adr = 0;
517579Sroot 	let[1].adr = ftell(tmpf);
518579Sroot 	if (flgf)
519579Sroot 		return;
52016731Sralph 	while (--argc > 0)
5216015Swnj 		if (!sendmail(0, *++argv, truename))
522579Sroot 			error++;
52310644Seric 	if (error && safefile(dead)) {
524579Sroot 		setuid(getuid());
525579Sroot 		malf = fopen(dead, "w");
526579Sroot 		if (malf == NULL) {
52716731Sralph 			printf("mail: cannot open %s\n", dead);
528579Sroot 			fclose(tmpf);
529579Sroot 			return;
530579Sroot 		}
531579Sroot 		copylet(0, malf, ZAP);
532579Sroot 		fclose(malf);
53316731Sralph 		printf("Mail saved in %s\n", dead);
534579Sroot 	}
535579Sroot 	fclose(tmpf);
536579Sroot }
537579Sroot 
53817019Sralph sendrmt(n, name)
539579Sroot char *name;
540579Sroot {
541579Sroot 	FILE *rmf, *popen();
542579Sroot 	register char *p;
543579Sroot 	char rsys[64], cmd[64];
54417019Sralph 	register pid;
545579Sroot 	int sts;
546579Sroot 
54717019Sralph #ifdef notdef
54817019Sralph 	if (any('^', name)) {
549579Sroot 		while (p = index(name, '^'))
550579Sroot 			*p = '!';
551579Sroot 		if (strncmp(name, "researc", 7)) {
552579Sroot 			strcpy(rsys, "research");
553579Sroot 			if (*name != '!')
554579Sroot 				--name;
555579Sroot 			goto skip;
556579Sroot 		}
557579Sroot 	}
55817019Sralph #endif
55917019Sralph 	for (p=rsys; *name!='!'; *p++ = *name++)
56017019Sralph 		if (*name=='\0')
56117019Sralph 			return(0);	/* local address, no '!' */
562579Sroot 	*p = '\0';
56317019Sralph 	if (name[1]=='\0') {
56416731Sralph 		printf("null name\n");
565579Sroot 		return(0);
566579Sroot 	}
567579Sroot skip:
568579Sroot 	if ((pid = fork()) == -1) {
569579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
570579Sroot 		return(0);
571579Sroot 	}
572579Sroot 	if (pid) {
573579Sroot 		while (wait(&sts) != pid) {
574579Sroot 			if (wait(&sts)==-1)
575579Sroot 				return(0);
576579Sroot 		}
577579Sroot 		return(!sts);
578579Sroot 	}
579579Sroot 	setuid(getuid());
58017019Sralph 	if (any('!', name+1))
58117019Sralph 		sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
58217019Sralph 	else
58317019Sralph 		sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
584579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
585579Sroot 		exit(1);
58617019Sralph 	copylet(n, rmf, REMOTE);
58710783Seric 	exit(pclose(rmf) != 0);
588579Sroot }
589579Sroot 
590579Sroot usage()
591579Sroot {
592579Sroot 
593579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
59415299Skarels 	error = EX_USAGE;
59516731Sralph 	done();
596579Sroot }
597579Sroot 
5986015Swnj #include <sys/socket.h>
5999226Ssam #include <netinet/in.h>
60010227Ssam #include <netdb.h>
6016015Swnj 
60216731Sralph notifybiff(msg)
60316731Sralph 	char *msg;
60416731Sralph {
60516731Sralph 	static struct sockaddr_in addr;
60616731Sralph 	static int f = -1;
60716731Sralph 
60816731Sralph 	if (addr.sin_family == 0) {
60916731Sralph 		struct hostent *hp = gethostbyname("localhost");
61016731Sralph 		struct servent *sp = getservbyname("biff", "udp");
61116731Sralph 
61216731Sralph 		if (hp && sp) {
61316731Sralph 			addr.sin_family = hp->h_addrtype;
61416731Sralph 			bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
61516731Sralph 			addr.sin_port = sp->s_port;
61616731Sralph 		}
61716731Sralph 	}
61816731Sralph 	if (addr.sin_family) {
61916731Sralph 		if (f < 0)
62016731Sralph 			f = socket(AF_INET, SOCK_DGRAM, 0);
62116731Sralph 		sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr));
62216731Sralph 	}
62316731Sralph }
62416731Sralph 
6256015Swnj sendmail(n, name, fromaddr)
62616731Sralph 	int n;
62716731Sralph 	char *name, *fromaddr;
628579Sroot {
62916731Sralph 	char file[256];
63016731Sralph 	int mask, fd;
63116731Sralph 	struct passwd *pw;
63216731Sralph #ifdef notdef
633579Sroot 	struct stat statb;
63416731Sralph #endif
6353666Swnj 	char buf[128];
636579Sroot 
63717019Sralph 	if (*name=='!')
63817019Sralph 		name++;
63917019Sralph 	if (any('!', name))
64017019Sralph 		return (sendrmt(n, name));
641579Sroot 	if ((pw = getpwnam(name)) == NULL) {
64216731Sralph 		printf("mail: can't send to %s\n", name);
643579Sroot 		return(0);
644579Sroot 	}
645579Sroot 	cat(file, maildir, name);
64616731Sralph #ifdef notdef
647579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
648579Sroot 		strcat(file, "/");
649579Sroot 		strcat(file, name);
650579Sroot 	}
65116731Sralph #endif
65210644Seric 	if (!safefile(file))
6534458Sroot 		return(0);
65416731Sralph 	fd = open(file, O_WRONLY | O_CREAT, MAILMODE);
65516731Sralph 	if (fd >= 0) {
65616731Sralph 		flock(fd, LOCK_EX);
65716731Sralph 		malf = fdopen(fd, "a");
65816731Sralph 	}
65916731Sralph 	if (fd < 0 || malf == NULL) {
66016731Sralph 		close(fd);
66116731Sralph 		printf("mail: %s: cannot append\n", file);
662579Sroot 		return(0);
663579Sroot 	}
66416731Sralph 	fchown(fd, pw->pw_uid, pw->pw_gid);
66516731Sralph 	sprintf(buf, "%s@%d\n", name, ftell(malf));
666579Sroot 	copylet(n, malf, ORDINARY);
6676015Swnj 	fclose(malf);
66816731Sralph 	notifybiff(buf);
669579Sroot 	return(1);
670579Sroot }
671579Sroot 
67216731Sralph delex(i)
673579Sroot {
67416731Sralph 	setsig(i, delex);
67516731Sralph 	putc('\n', stderr);
67616731Sralph 	if (delflg)
677579Sroot 		longjmp(sjbuf, 1);
678579Sroot 	done();
679579Sroot }
680579Sroot 
68116731Sralph done()
682579Sroot {
683579Sroot 
684579Sroot 	unlink(lettmp);
685579Sroot 	exit(error);
686579Sroot }
687579Sroot 
688579Sroot cat(to, from1, from2)
68916731Sralph 	char *to, *from1, *from2;
690579Sroot {
69116731Sralph 	register char *cp, *dp;
692579Sroot 
69316731Sralph 	cp = to;
69416731Sralph 	for (dp = from1; *cp = *dp++; cp++)
69516731Sralph 		;
69616731Sralph 	for (dp = from2; *cp++ = *dp++; )
69716731Sralph 		;
698579Sroot }
699579Sroot 
70016731Sralph /* copy p... into s, update p */
70116731Sralph char *
70216731Sralph getarg(s, p)
70316731Sralph 	register char *s, *p;
704579Sroot {
705579Sroot 	while (*p == ' ' || *p == '\t')
706579Sroot 		p++;
707579Sroot 	if (*p == '\n' || *p == '\0')
708579Sroot 		return(NULL);
709579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
710579Sroot 		*s++ = *p++;
711579Sroot 	*s = '\0';
712579Sroot 	return(p);
713579Sroot }
71410644Seric 
71510644Seric safefile(f)
71610644Seric 	char *f;
71710644Seric {
71810644Seric 	struct stat statb;
71910644Seric 
72010644Seric 	if (lstat(f, &statb) < 0)
72110644Seric 		return (1);
72210644Seric 	if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
72316731Sralph 		fprintf(stderr,
72416731Sralph 		    "mail: %s has more than one link or is a symbolic link\n",
72516731Sralph 		    f);
72610644Seric 		return (0);
72710644Seric 	}
72810644Seric 	return (1);
72910644Seric }
73016731Sralph 
73116731Sralph panic(msg, a1, a2, a3)
73216731Sralph 	char *msg;
73316731Sralph {
73416731Sralph 
73516731Sralph 	fprintf(stderr, "mail: ");
73616731Sralph 	fprintf(stderr, msg, a1, a2, a3);
73716731Sralph 	fprintf(stderr, "\n");
73816731Sralph 	done();
73916731Sralph }
740