114465Ssam #ifndef lint
2*16731Sralph static char sccsid[] = "@(#)mail.local.c	4.22 (Berkeley) 07/19/84";
314465Ssam #endif
414465Ssam 
5*16731Sralph #include <sys/types.h>
6*16731Sralph #include <sys/stat.h>
7*16731Sralph #include <sys/file.h>
8*16731Sralph 
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 
19*16731Sralph 	/* copylet flags */
20*16731Sralph #define REMOTE		1		/* remote mail, add rmtmsg */
21*16731Sralph #define ORDINARY	2
22*16731Sralph #define ZAP		3		/* zap header and trailing empty line */
23*16731Sralph #define	FORWARD		4
24579Sroot 
25*16731Sralph #define	LSIZE		256
26*16731Sralph #define	MAXLET		300		/* maximum number of letters */
27*16731Sralph #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();
54*16731Sralph 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;
67579Sroot 
68579Sroot 	mktemp(lettmp);
69579Sroot 	unlink(lettmp);
70579Sroot 	my_name = getlogin();
71*16731Sralph 	if (my_name == NULL || *my_name == '\0') {
72579Sroot 		struct passwd *pwent;
73579Sroot 		pwent = getpwuid(getuid());
74579Sroot 		if (pwent==NULL)
75579Sroot 			my_name = "???";
76579Sroot 		else
77579Sroot 			my_name = pwent->pw_name;
78579Sroot 	}
79*16731Sralph 	if (setjmp(sjbuf))
80*16731Sralph 		done();
8114912Sralph 	for (i=SIGHUP; i<=SIGTERM; i++)
82*16731Sralph 		setsig(i, delex);
83*16731Sralph 	tmpf = fopen(lettmp, "w+r");
84*16731Sralph 	if (tmpf == NULL)
85*16731Sralph 		panic("mail: %s: cannot open for writing", lettmp);
86*16731Sralph 	/*
87*16731Sralph 	 * This protects against others reading mail from temp file and
88*16731Sralph 	 * if we exit, the file will be deleted already.
89*16731Sralph 	 */
90*16731Sralph 	unlink(lettmp);
91579Sroot 	if (argv[0][0] == 'r')
92579Sroot 		rmail++;
93579Sroot 	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
94579Sroot 	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
95579Sroot 		printmail(argc, argv);
96579Sroot 	else
976015Swnj 		bulkmail(argc, argv);
98579Sroot 	done();
99579Sroot }
100579Sroot 
101579Sroot setsig(i, f)
102579Sroot int i;
103579Sroot int (*f)();
104579Sroot {
105*16731Sralph 	if (signal(i, SIG_IGN) != SIG_IGN)
106579Sroot 		signal(i, f);
107579Sroot }
108579Sroot 
109579Sroot any(c, str)
110579Sroot 	register int c;
111579Sroot 	register char *str;
112579Sroot {
113579Sroot 
114579Sroot 	while (*str)
115579Sroot 		if (c == *str++)
116579Sroot 			return(1);
117579Sroot 	return(0);
118579Sroot }
119579Sroot 
120579Sroot printmail(argc, argv)
121*16731Sralph 	char **argv;
122579Sroot {
123579Sroot 	int flg, i, j, print;
124579Sroot 	char *p, *getarg();
125579Sroot 	struct stat statb;
126579Sroot 
127579Sroot 	setuid(getuid());
128579Sroot 	cat(mailfile, maildir, my_name);
129*16731Sralph #ifdef notdef
130579Sroot 	if (stat(mailfile, &statb) >= 0
131579Sroot 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
132579Sroot 		strcat(mailfile, "/");
133579Sroot 		strcat(mailfile, my_name);
134579Sroot 	}
135*16731Sralph #endif
136*16731Sralph 	for (; argc > 1; argv++, argc--) {
137*16731Sralph 		if (argv[1][0] != '-')
138*16731Sralph 			break;
139*16731Sralph 		switch (argv[1][1]) {
140*16731Sralph 
141*16731Sralph 		case 'p':
142*16731Sralph 			flgp++;
143*16731Sralph 			/* fall thru... */
144*16731Sralph 		case 'q':
145*16731Sralph 			delflg = 0;
146*16731Sralph 			break;
147*16731Sralph 
148*16731Sralph 		case 'f':
149*16731Sralph 			if (argc >= 3) {
150*16731Sralph 				strcpy(mailfile, argv[2]);
151*16731Sralph 				argv++, argc--;
152579Sroot 			}
153579Sroot 			break;
154*16731Sralph 
155*16731Sralph 		case 'b':
156*16731Sralph 			forward = 1;
157*16731Sralph 			break;
158*16731Sralph 
159*16731Sralph 		default:
160*16731Sralph 			panic("unknown option %c", argv[1][1]);
161*16731Sralph 			/*NOTREACHED*/
162*16731Sralph 		}
163579Sroot 	}
164579Sroot 	malf = fopen(mailfile, "r");
165579Sroot 	if (malf == NULL) {
166*16731Sralph 		printf("No mail.\n");
167579Sroot 		return;
168579Sroot 	}
169*16731Sralph 	flock(fileno(malf), LOCK_SH);
170579Sroot 	copymt(malf, tmpf);
171*16731Sralph 	fclose(malf);			/* implicit unlock */
172*16731Sralph 	fseek(tmpf, 0, L_SET);
173579Sroot 
174579Sroot 	changed = 0;
175579Sroot 	print = 1;
176579Sroot 	for (i = 0; i < nlet; ) {
177579Sroot 		j = forward ? i : nlet - i - 1;
178*16731Sralph 		if (setjmp(sjbuf)) {
179*16731Sralph 			print = 0;
180579Sroot 		} else {
181579Sroot 			if (print)
182579Sroot 				copylet(j, stdout, ORDINARY);
183579Sroot 			print = 1;
184579Sroot 		}
185579Sroot 		if (flgp) {
186579Sroot 			i++;
187579Sroot 			continue;
188579Sroot 		}
189579Sroot 		setjmp(sjbuf);
190*16731Sralph 		fputs("? ", stdout);
191579Sroot 		fflush(stdout);
192579Sroot 		if (fgets(resp, LSIZE, stdin) == NULL)
193579Sroot 			break;
194579Sroot 		switch (resp[0]) {
195579Sroot 
196579Sroot 		default:
197*16731Sralph 			printf("usage\n");
198579Sroot 		case '?':
199579Sroot 			print = 0;
200*16731Sralph 			printf("q\tquit\n");
201*16731Sralph 			printf("x\texit without changing mail\n");
202*16731Sralph 			printf("p\tprint\n");
203*16731Sralph 			printf("s[file]\tsave (default mbox)\n");
204*16731Sralph 			printf("w[file]\tsame without header\n");
205*16731Sralph 			printf("-\tprint previous\n");
206*16731Sralph 			printf("d\tdelete\n");
207*16731Sralph 			printf("+\tnext (no delete)\n");
208*16731Sralph 			printf("m user\tmail to user\n");
209*16731Sralph 			printf("! cmd\texecute cmd\n");
210579Sroot 			break;
211579Sroot 
212579Sroot 		case '+':
213579Sroot 		case 'n':
214579Sroot 		case '\n':
215579Sroot 			i++;
216579Sroot 			break;
217579Sroot 		case 'x':
218579Sroot 			changed = 0;
219579Sroot 		case 'q':
220579Sroot 			goto donep;
221579Sroot 		case 'p':
222579Sroot 			break;
223579Sroot 		case '^':
224579Sroot 		case '-':
225579Sroot 			if (--i < 0)
226579Sroot 				i = 0;
227579Sroot 			break;
228579Sroot 		case 'y':
229579Sroot 		case 'w':
230579Sroot 		case 's':
231579Sroot 			flg = 0;
232579Sroot 			if (resp[1] != '\n' && resp[1] != ' ') {
233579Sroot 				printf("illegal\n");
234579Sroot 				flg++;
235579Sroot 				print = 0;
236579Sroot 				continue;
237579Sroot 			}
238579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
239579Sroot 				p = getenv("HOME");
240*16731Sralph 				if (p != 0)
241579Sroot 					cat(resp+1, p, "/mbox");
242579Sroot 				else
243579Sroot 					cat(resp+1, "", "mbox");
244579Sroot 			}
245579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
246579Sroot 				malf = fopen(lfil, "a");
247579Sroot 				if (malf == NULL) {
248*16731Sralph 					printf("mail: %s: cannot append\n",
249*16731Sralph 					    lfil);
250579Sroot 					flg++;
251579Sroot 					continue;
252579Sroot 				}
253579Sroot 				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
254579Sroot 				fclose(malf);
255579Sroot 			}
256579Sroot 			if (flg)
257579Sroot 				print = 0;
258579Sroot 			else {
259579Sroot 				let[j].change = 'd';
260579Sroot 				changed++;
261579Sroot 				i++;
262579Sroot 			}
263579Sroot 			break;
264579Sroot 		case 'm':
265579Sroot 			flg = 0;
266579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
267579Sroot 				i++;
268579Sroot 				continue;
269579Sroot 			}
270579Sroot 			if (resp[1] != ' ') {
271579Sroot 				printf("invalid command\n");
272579Sroot 				flg++;
273579Sroot 				print = 0;
274579Sroot 				continue;
275579Sroot 			}
276579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
277*16731Sralph 				if (!sendrmt(j, lfil, "/bin/mail"))
278579Sroot 					flg++;
279579Sroot 			if (flg)
280579Sroot 				print = 0;
281579Sroot 			else {
282579Sroot 				let[j].change = 'd';
283579Sroot 				changed++;
284579Sroot 				i++;
285579Sroot 			}
286579Sroot 			break;
287579Sroot 		case '!':
288579Sroot 			system(resp+1);
289579Sroot 			printf("!\n");
290579Sroot 			print = 0;
291579Sroot 			break;
292579Sroot 		case 'd':
293579Sroot 			let[j].change = 'd';
294579Sroot 			changed++;
295579Sroot 			i++;
296579Sroot 			if (resp[1] == 'q')
297579Sroot 				goto donep;
298579Sroot 			break;
299579Sroot 		}
300579Sroot 	}
301579Sroot    donep:
302579Sroot 	if (changed)
303579Sroot 		copyback();
304579Sroot }
305579Sroot 
306*16731Sralph /* copy temp or whatever back to /usr/spool/mail */
307*16731Sralph copyback()
308579Sroot {
309*16731Sralph 	register i, c;
310*16731Sralph 	int fd, new = 0, oldmask;
311579Sroot 	struct stat stbuf;
312579Sroot 
313*16731Sralph #define	mask(s)	(1 << ((s) - 1))
314*16731Sralph 	oldmask = sigblock(mask(SIGINT)|mask(SIGHUP)|mask(SIGQUIT));
315*16731Sralph #undef mask
316*16731Sralph 	fd = open(mailfile, O_RDWR | O_CREAT, MAILMODE);
317*16731Sralph 	if (fd >= 0) {
318*16731Sralph 		flock(fd, LOCK_EX);
319*16731Sralph 		malf = fdopen(fd, "r+w");
320*16731Sralph 	}
321*16731Sralph 	if (fd < 0 || malf == NULL)
322*16731Sralph 		panic("can't rewrite %s", lfil);
323*16731Sralph 	fstat(fd, &stbuf);
324579Sroot 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
325*16731Sralph 		fseek(malf, let[nlet].adr, L_SET);
326*16731Sralph 		fseek(tmpf, let[nlet].adr, L_SET);
327*16731Sralph 		while ((c = getc(malf)) != EOF)
328*16731Sralph 			putc(c, tmpf);
329579Sroot 		let[++nlet].adr = stbuf.st_size;
330579Sroot 		new = 1;
331*16731Sralph 		fseek(malf, 0, L_SET);
332579Sroot 	}
333*16731Sralph 	ftruncate(fd, 0);
334579Sroot 	for (i = 0; i < nlet; i++)
335*16731Sralph 		if (let[i].change != 'd')
336579Sroot 			copylet(i, malf, ORDINARY);
337*16731Sralph 	fclose(malf);		/* implict unlock */
338579Sroot 	if (new)
339*16731Sralph 		printf("New mail has arrived.\n");
340*16731Sralph 	sigsetmask(oldmask);
341579Sroot }
342579Sroot 
343*16731Sralph /* copy mail (f1) to temp (f2) */
344*16731Sralph copymt(f1, f2)
345*16731Sralph 	FILE *f1, *f2;
346579Sroot {
347579Sroot 	long nextadr;
348579Sroot 
349579Sroot 	nlet = nextadr = 0;
350579Sroot 	let[0].adr = 0;
351579Sroot 	while (fgets(line, LSIZE, f1) != NULL) {
352579Sroot 		if (isfrom(line))
353579Sroot 			let[nlet++].adr = nextadr;
354579Sroot 		nextadr += strlen(line);
355579Sroot 		fputs(line, f2);
356579Sroot 	}
357579Sroot 	let[nlet].adr = nextadr;	/* last plus 1 */
358579Sroot }
359579Sroot 
36011893Seric copylet(n, f, type)
36111893Seric 	FILE *f;
36211893Seric {
36311893Seric 	int ch;
36411893Seric 	long k;
365*16731Sralph 	char hostname[32];
36611893Seric 
367*16731Sralph 	fseek(tmpf, let[n].adr, L_SET);
368579Sroot 	k = let[n+1].adr - let[n].adr;
369*16731Sralph 	while (k-- > 1 && (ch = getc(tmpf)) != '\n')
370*16731Sralph 		if (type != ZAP)
371*16731Sralph 			putc(ch, f);
372*16731Sralph 	switch (type) {
373*16731Sralph 
374*16731Sralph 	case REMOTE:
3756199Sroot 		gethostname(hostname, sizeof (hostname));
3766199Sroot 		fprintf(f, " remote from %s\n", hostname);
377*16731Sralph 		break;
378*16731Sralph 
379*16731Sralph 	case FORWARD:
380579Sroot 		fprintf(f, forwmsg);
381*16731Sralph 		break;
382*16731Sralph 
383*16731Sralph 	case ORDINARY:
384*16731Sralph 		putc(ch, f);
385*16731Sralph 		break;
386*16731Sralph 
387*16731Sralph 	default:
388*16731Sralph 		panic("Bad letter type %d to copylet.", type);
389*16731Sralph 	}
390*16731Sralph 	while (k-- > 1) {
391*16731Sralph 		ch = getc(tmpf);
392*16731Sralph 		putc(ch, f);
393*16731Sralph 	}
394*16731Sralph 	if (type != ZAP || ch != '\n')
395*16731Sralph 		putc(getc(tmpf), f);
396579Sroot }
397579Sroot 
398579Sroot isfrom(lp)
399579Sroot register char *lp;
400579Sroot {
401579Sroot 	register char *p;
402579Sroot 
403579Sroot 	for (p = from; *p; )
404579Sroot 		if (*lp++ != *p++)
405579Sroot 			return(0);
406579Sroot 	return(1);
407579Sroot }
408579Sroot 
4096015Swnj bulkmail(argc, argv)
410579Sroot char **argv;
411579Sroot {
412579Sroot 	char truename[100];
413579Sroot 	int first;
414579Sroot 	register char *cp;
415579Sroot 	int gaver = 0;
416579Sroot 	char *newargv[1000];
417579Sroot 	register char **ap;
418579Sroot 	register char **vp;
419579Sroot 	int dflag;
420579Sroot 
421579Sroot 	dflag = 0;
422*16731Sralph 	if (argc < 1) {
423579Sroot 		fprintf(stderr, "puke\n");
424*16731Sralph 		return;
425*16731Sralph 	}
426579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
427579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
428579Sroot 			dflag++;
429*16731Sralph 	if (!dflag) {
4309978Seric 		/* give it to sendmail, rah rah! */
431579Sroot 		unlink(lettmp);
432579Sroot 		ap = newargv+1;
433579Sroot 		if (rmail)
434579Sroot 			*ap-- = "-s";
4359978Seric 		*ap = "-sendmail";
4364461Sroot 		setuid(getuid());
4379978Seric 		execv(SENDMAIL, ap);
4389978Seric 		perror(SENDMAIL);
439579Sroot 		exit(EX_UNAVAILABLE);
440579Sroot 	}
441579Sroot 
442579Sroot 	truename[0] = 0;
443579Sroot 	line[0] = '\0';
444579Sroot 
445579Sroot 	/*
446579Sroot 	 * When we fall out of this, argv[1] should be first name,
447579Sroot 	 * argc should be number of names + 1.
448579Sroot 	 */
449579Sroot 
450579Sroot 	while (argc > 1 && *argv[1] == '-') {
451579Sroot 		cp = *++argv;
452579Sroot 		argc--;
453579Sroot 		switch (cp[1]) {
454579Sroot 		case 'r':
455*16731Sralph 			if (argc <= 1)
456579Sroot 				usage();
45715346Skarels 			gaver++;
45815346Skarels 			strcpy(truename, argv[1]);
45915346Skarels 			fgets(line, LSIZE, stdin);
46015346Skarels 			if (strcmpn("From", line, 4) == 0)
46115346Skarels 				line[0] = '\0';
462579Sroot 			argv++;
463579Sroot 			argc--;
464579Sroot 			break;
465579Sroot 
466579Sroot 		case 'h':
467*16731Sralph 			if (argc <= 1)
468579Sroot 				usage();
469579Sroot 			hseqno = atoi(argv[1]);
470579Sroot 			argv++;
471579Sroot 			argc--;
472579Sroot 			break;
473579Sroot 
474579Sroot 		case 'd':
475579Sroot 			break;
476579Sroot 
477579Sroot 		default:
478579Sroot 			usage();
479579Sroot 		}
480579Sroot 	}
481*16731Sralph 	if (argc <= 1)
482579Sroot 		usage();
483579Sroot 	if (gaver == 0)
484579Sroot 		strcpy(truename, my_name);
485579Sroot 	time(&iop);
486579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
487579Sroot 	iop = ftell(tmpf);
488*16731Sralph 	flgf = first = 1;
489*16731Sralph 	for (;;) {
490*16731Sralph 		if (first) {
491*16731Sralph 			first = 0;
492*16731Sralph 			if (*line == '\0' && fgets(line, LSIZE, stdin) == NULL)
493*16731Sralph 				break;
494*16731Sralph 		} else {
495*16731Sralph 			if (fgets(line, LSIZE, stdin) == NULL)
496*16731Sralph 				break;
497*16731Sralph 		}
498*16731Sralph 		if (*line == '.' && line[1] == '\n' && isatty(fileno(stdin)))
499579Sroot 			break;
500579Sroot 		if (isfrom(line))
501*16731Sralph 			putc('>', tmpf);
502579Sroot 		fputs(line, tmpf);
503579Sroot 		flgf = 0;
504579Sroot 	}
505*16731Sralph 	putc('\n', tmpf);
506579Sroot 	nlet = 1;
507579Sroot 	let[0].adr = 0;
508579Sroot 	let[1].adr = ftell(tmpf);
509579Sroot 	if (flgf)
510579Sroot 		return;
511*16731Sralph 	while (--argc > 0)
5126015Swnj 		if (!sendmail(0, *++argv, truename))
513579Sroot 			error++;
51410644Seric 	if (error && safefile(dead)) {
515579Sroot 		setuid(getuid());
516579Sroot 		malf = fopen(dead, "w");
517579Sroot 		if (malf == NULL) {
518*16731Sralph 			printf("mail: cannot open %s\n", dead);
519579Sroot 			fclose(tmpf);
520579Sroot 			return;
521579Sroot 		}
522579Sroot 		copylet(0, malf, ZAP);
523579Sroot 		fclose(malf);
524*16731Sralph 		printf("Mail saved in %s\n", dead);
525579Sroot 	}
526579Sroot 	fclose(tmpf);
527579Sroot }
528579Sroot 
529579Sroot sendrmt(n, name, rcmd)
530579Sroot char *name;
531579Sroot char *rcmd;
532579Sroot {
533579Sroot 	FILE *rmf, *popen();
534579Sroot 	register char *p;
535579Sroot 	char rsys[64], cmd[64];
536579Sroot 	register local, pid;
537579Sroot 	int sts;
538579Sroot 
539579Sroot 	local = 0;
540579Sroot 	if (index(name, '^')) {
541579Sroot 		while (p = index(name, '^'))
542579Sroot 			*p = '!';
543579Sroot 		if (strncmp(name, "researc", 7)) {
544579Sroot 			strcpy(rsys, "research");
545579Sroot 			if (*name != '!')
546579Sroot 				--name;
547579Sroot 			goto skip;
548579Sroot 		}
549579Sroot 	}
550579Sroot 	if (*name=='!')
551579Sroot 		name++;
552579Sroot 	for(p=rsys; *name!='!'; *p++ = *name++)
553579Sroot 		if (*name=='\0') {
554579Sroot 			local++;
555579Sroot 			break;
556579Sroot 		}
557579Sroot 	*p = '\0';
558579Sroot 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
559*16731Sralph 		printf("null name\n");
560579Sroot 		return(0);
561579Sroot 	}
562579Sroot skip:
563579Sroot 	if ((pid = fork()) == -1) {
564579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
565579Sroot 		return(0);
566579Sroot 	}
567579Sroot 	if (pid) {
568579Sroot 		while (wait(&sts) != pid) {
569579Sroot 			if (wait(&sts)==-1)
570579Sroot 				return(0);
571579Sroot 		}
572579Sroot 		return(!sts);
573579Sroot 	}
574579Sroot 	setuid(getuid());
575579Sroot 	if (local)
576579Sroot 		sprintf(cmd, "%s %s", rcmd, rsys);
577579Sroot 	else {
578579Sroot 		if (index(name+1, '!'))
579579Sroot 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
580579Sroot 		else
581579Sroot 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
582579Sroot 	}
583579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
584579Sroot 		exit(1);
585579Sroot 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
58610783Seric 	exit(pclose(rmf) != 0);
587579Sroot }
588579Sroot 
589579Sroot usage()
590579Sroot {
591579Sroot 
592579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
59315299Skarels 	error = EX_USAGE;
594*16731Sralph 	done();
595579Sroot }
596579Sroot 
5976015Swnj #include <sys/socket.h>
5989226Ssam #include <netinet/in.h>
59910227Ssam #include <netdb.h>
6006015Swnj 
601*16731Sralph notifybiff(msg)
602*16731Sralph 	char *msg;
603*16731Sralph {
604*16731Sralph 	static struct sockaddr_in addr;
605*16731Sralph 	static int f = -1;
606*16731Sralph 
607*16731Sralph 	if (addr.sin_family == 0) {
608*16731Sralph 		struct hostent *hp = gethostbyname("localhost");
609*16731Sralph 		struct servent *sp = getservbyname("biff", "udp");
610*16731Sralph 
611*16731Sralph 		if (hp && sp) {
612*16731Sralph 			addr.sin_family = hp->h_addrtype;
613*16731Sralph 			bcopy(hp->h_addr, &addr.sin_addr, hp->h_length);
614*16731Sralph 			addr.sin_port = sp->s_port;
615*16731Sralph 		}
616*16731Sralph 	}
617*16731Sralph 	if (addr.sin_family) {
618*16731Sralph 		if (f < 0)
619*16731Sralph 			f = socket(AF_INET, SOCK_DGRAM, 0);
620*16731Sralph 		sendto(f, msg, strlen(msg)+1, 0, &addr, sizeof (addr));
621*16731Sralph 	}
622*16731Sralph }
623*16731Sralph 
6246015Swnj sendmail(n, name, fromaddr)
625*16731Sralph 	int n;
626*16731Sralph 	char *name, *fromaddr;
627579Sroot {
628*16731Sralph 	char file[256];
629*16731Sralph 	int mask, fd;
630*16731Sralph 	struct passwd *pw;
631*16731Sralph #ifdef notdef
632579Sroot 	struct stat statb;
633*16731Sralph #endif
6343666Swnj 	char buf[128];
635579Sroot 
636*16731Sralph 	if (any(name, "!^"))
637*16731Sralph 		return (sendrmt(n, name, 0));
638579Sroot 	if ((pw = getpwnam(name)) == NULL) {
639*16731Sralph 		printf("mail: can't send to %s\n", name);
640579Sroot 		return(0);
641579Sroot 	}
642579Sroot 	cat(file, maildir, name);
643*16731Sralph #ifdef notdef
644579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
645579Sroot 		strcat(file, "/");
646579Sroot 		strcat(file, name);
647579Sroot 	}
648*16731Sralph #endif
64910644Seric 	if (!safefile(file))
6504458Sroot 		return(0);
651*16731Sralph 	fd = open(file, O_WRONLY | O_CREAT, MAILMODE);
652*16731Sralph 	if (fd >= 0) {
653*16731Sralph 		flock(fd, LOCK_EX);
654*16731Sralph 		malf = fdopen(fd, "a");
655*16731Sralph 	}
656*16731Sralph 	if (fd < 0 || malf == NULL) {
657*16731Sralph 		close(fd);
658*16731Sralph 		printf("mail: %s: cannot append\n", file);
659579Sroot 		return(0);
660579Sroot 	}
661*16731Sralph 	fchown(fd, pw->pw_uid, pw->pw_gid);
662*16731Sralph 	sprintf(buf, "%s@%d\n", name, ftell(malf));
663579Sroot 	copylet(n, malf, ORDINARY);
6646015Swnj 	fclose(malf);
665*16731Sralph 	notifybiff(buf);
666579Sroot 	return(1);
667579Sroot }
668579Sroot 
669*16731Sralph delex(i)
670579Sroot {
671*16731Sralph 	setsig(i, delex);
672*16731Sralph 	putc('\n', stderr);
673*16731Sralph 	if (delflg)
674579Sroot 		longjmp(sjbuf, 1);
675579Sroot 	done();
676579Sroot }
677579Sroot 
678*16731Sralph done()
679579Sroot {
680579Sroot 
681579Sroot 	unlink(lettmp);
682579Sroot 	exit(error);
683579Sroot }
684579Sroot 
685579Sroot cat(to, from1, from2)
686*16731Sralph 	char *to, *from1, *from2;
687579Sroot {
688*16731Sralph 	register char *cp, *dp;
689579Sroot 
690*16731Sralph 	cp = to;
691*16731Sralph 	for (dp = from1; *cp = *dp++; cp++)
692*16731Sralph 		;
693*16731Sralph 	for (dp = from2; *cp++ = *dp++; )
694*16731Sralph 		;
695579Sroot }
696579Sroot 
697*16731Sralph /* copy p... into s, update p */
698*16731Sralph char *
699*16731Sralph getarg(s, p)
700*16731Sralph 	register char *s, *p;
701579Sroot {
702579Sroot 	while (*p == ' ' || *p == '\t')
703579Sroot 		p++;
704579Sroot 	if (*p == '\n' || *p == '\0')
705579Sroot 		return(NULL);
706579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
707579Sroot 		*s++ = *p++;
708579Sroot 	*s = '\0';
709579Sroot 	return(p);
710579Sroot }
71110644Seric 
71210644Seric safefile(f)
71310644Seric 	char *f;
71410644Seric {
71510644Seric 	struct stat statb;
71610644Seric 
71710644Seric 	if (lstat(f, &statb) < 0)
71810644Seric 		return (1);
71910644Seric 	if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
720*16731Sralph 		fprintf(stderr,
721*16731Sralph 		    "mail: %s has more than one link or is a symbolic link\n",
722*16731Sralph 		    f);
72310644Seric 		return (0);
72410644Seric 	}
72510644Seric 	return (1);
72610644Seric }
727*16731Sralph 
728*16731Sralph panic(msg, a1, a2, a3)
729*16731Sralph 	char *msg;
730*16731Sralph {
731*16731Sralph 
732*16731Sralph 	fprintf(stderr, "mail: ");
733*16731Sralph 	fprintf(stderr, msg, a1, a2, a3);
734*16731Sralph 	fprintf(stderr, "\n");
735*16731Sralph 	done();
736*16731Sralph }
737