114465Ssam #ifndef lint
2*15299Skarels static char sccsid[] = "@(#)mail.local.c	4.20 (Berkeley) 10/27/83";
314465Ssam #endif
414465Ssam 
5579Sroot #include <ctype.h>
6579Sroot #include <stdio.h>
7579Sroot #include <pwd.h>
8579Sroot #include <utmp.h>
9579Sroot #include <signal.h>
10579Sroot #include <sys/types.h>
11579Sroot #include <sys/stat.h>
12579Sroot #include <setjmp.h>
13579Sroot #include <sysexits.h>
14579Sroot 
159978Seric #define SENDMAIL	"/usr/lib/sendmail"
16579Sroot 
17579Sroot 
18579Sroot /*copylet flags */
19579Sroot 	/*remote mail, add rmtmsg */
20579Sroot #define REMOTE	1
21579Sroot 	/* zap header and trailing empty line */
22579Sroot #define ZAP	3
23579Sroot #define ORDINARY 2
24579Sroot #define	FORWARD	4
25579Sroot #define	LSIZE	256
26579Sroot #define	MAXLET	300	/* maximum number of letters */
2711899Sleres #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	*netname = "vax";
45579Sroot char	forwmsg[] = " forwarded\n";
46579Sroot FILE	*tmpf;
47579Sroot FILE	*malf;
48579Sroot char	*my_name;
49579Sroot char	*getlogin();
50579Sroot struct	passwd	*getpwuid();
51579Sroot int	error;
52579Sroot int	changed;
53579Sroot int	forward;
54579Sroot char	from[] = "From ";
55579Sroot long	ftell();
56579Sroot int	delete();
57579Sroot char	*ctime();
58579Sroot int	flgf;
59579Sroot int	flgp;
60579Sroot int	delflg = 1;
61579Sroot int	hseqno;
62579Sroot jmp_buf	sjbuf;
63579Sroot int	rmail;
64579Sroot 
65579Sroot main(argc, argv)
66579Sroot char **argv;
67579Sroot {
68579Sroot 	register i;
69579Sroot 	char sobuf[BUFSIZ];
70579Sroot 
71579Sroot 	setbuf(stdout, sobuf);
72579Sroot 	mktemp(lettmp);
73579Sroot 	unlink(lettmp);
74579Sroot 	my_name = getlogin();
75579Sroot 	if (my_name == NULL || strlen(my_name) == 0) {
76579Sroot 		struct passwd *pwent;
77579Sroot 		pwent = getpwuid(getuid());
78579Sroot 		if (pwent==NULL)
79579Sroot 			my_name = "???";
80579Sroot 		else
81579Sroot 			my_name = pwent->pw_name;
82579Sroot 	}
83579Sroot 	if(setjmp(sjbuf)) done();
8414912Sralph 	for (i=SIGHUP; i<=SIGTERM; i++)
85579Sroot 		setsig(i, delete);
86579Sroot 	tmpf = fopen(lettmp, "w");
87579Sroot 	if (tmpf == NULL) {
88579Sroot 		fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
89579Sroot 		done();
90579Sroot 	}
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 {
105579Sroot 	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)
121579Sroot 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);
129579Sroot 	if (stat(mailfile, &statb) >= 0
130579Sroot 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
131579Sroot 		strcat(mailfile, "/");
132579Sroot 		strcat(mailfile, my_name);
133579Sroot 	}
134579Sroot 	for (; argc>1; argv++, argc--) {
135579Sroot 		if (argv[1][0]=='-') {
136579Sroot 			if (argv[1][1]=='q')
137579Sroot 				delflg = 0;
138579Sroot 			else if (argv[1][1]=='p') {
139579Sroot 				flgp++;
140579Sroot 				delflg = 0;
141579Sroot 			} else if (argv[1][1]=='f') {
142579Sroot 				if (argc>=3) {
143579Sroot 					strcpy(mailfile, argv[2]);
144579Sroot 					argv++;
145579Sroot 					argc--;
146579Sroot 				}
147579Sroot 			} else if (argv[1][1]=='r') {
148579Sroot 				forward = 1;
149579Sroot 			} else if (argv[1][1]=='h') {
150579Sroot 				forward = 1;
151579Sroot 			} else {
152579Sroot 				fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
153579Sroot 				done();
154579Sroot 			}
155579Sroot 		} else
156579Sroot 			break;
157579Sroot 	}
158579Sroot 	malf = fopen(mailfile, "r");
159579Sroot 	if (malf == NULL) {
160579Sroot 		fprintf(stdout, "No mail.\n");
161579Sroot 		return;
162579Sroot 	}
163579Sroot 	lock(mailfile);
164579Sroot 	copymt(malf, tmpf);
165579Sroot 	fclose(malf);
166579Sroot 	fclose(tmpf);
167579Sroot 	unlock();
168579Sroot 	tmpf = fopen(lettmp, "r");
169579Sroot 
170579Sroot 	changed = 0;
171579Sroot 	print = 1;
172579Sroot 	for (i = 0; i < nlet; ) {
173579Sroot 		j = forward ? i : nlet - i - 1;
174579Sroot 		if(setjmp(sjbuf)) {
175579Sroot 			print=0;
176579Sroot 		} else {
177579Sroot 			if (print)
178579Sroot 				copylet(j, stdout, ORDINARY);
179579Sroot 			print = 1;
180579Sroot 		}
181579Sroot 		if (flgp) {
182579Sroot 			i++;
183579Sroot 			continue;
184579Sroot 		}
185579Sroot 		setjmp(sjbuf);
186579Sroot 		fprintf(stdout, "? ");
187579Sroot 		fflush(stdout);
188579Sroot 		if (fgets(resp, LSIZE, stdin) == NULL)
189579Sroot 			break;
190579Sroot 		switch (resp[0]) {
191579Sroot 
192579Sroot 		default:
193579Sroot 			fprintf(stderr, "usage\n");
194579Sroot 		case '?':
195579Sroot 			print = 0;
196579Sroot 			fprintf(stderr, "q\tquit\n");
197579Sroot 			fprintf(stderr, "x\texit without changing mail\n");
198579Sroot 			fprintf(stderr, "p\tprint\n");
199579Sroot 			fprintf(stderr, "s[file]\tsave (default mbox)\n");
200579Sroot 			fprintf(stderr, "w[file]\tsame without header\n");
201579Sroot 			fprintf(stderr, "-\tprint previous\n");
202579Sroot 			fprintf(stderr, "d\tdelete\n");
203579Sroot 			fprintf(stderr, "+\tnext (no delete)\n");
204579Sroot 			fprintf(stderr, "m user\tmail to user\n");
205579Sroot 			fprintf(stderr, "! cmd\texecute cmd\n");
206579Sroot 			break;
207579Sroot 
208579Sroot 		case '+':
209579Sroot 		case 'n':
210579Sroot 		case '\n':
211579Sroot 			i++;
212579Sroot 			break;
213579Sroot 		case 'x':
214579Sroot 			changed = 0;
215579Sroot 		case 'q':
216579Sroot 			goto donep;
217579Sroot 		case 'p':
218579Sroot 			break;
219579Sroot 		case '^':
220579Sroot 		case '-':
221579Sroot 			if (--i < 0)
222579Sroot 				i = 0;
223579Sroot 			break;
224579Sroot 		case 'y':
225579Sroot 		case 'w':
226579Sroot 		case 's':
227579Sroot 			flg = 0;
228579Sroot 			if (resp[1] != '\n' && resp[1] != ' ') {
229579Sroot 				printf("illegal\n");
230579Sroot 				flg++;
231579Sroot 				print = 0;
232579Sroot 				continue;
233579Sroot 			}
234579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
235579Sroot 				p = getenv("HOME");
236579Sroot 				if(p != 0)
237579Sroot 					cat(resp+1, p, "/mbox");
238579Sroot 				else
239579Sroot 					cat(resp+1, "", "mbox");
240579Sroot 			}
241579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
242579Sroot 				malf = fopen(lfil, "a");
243579Sroot 				if (malf == NULL) {
244579Sroot 					fprintf(stdout, "mail: cannot append to %s\n", 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; )
272579Sroot 				if (!sendrmt(j, lfil, "/bin/mail"))	/* couldn't send it */
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 
301579Sroot copyback()	/* copy temp or whatever back to /usr/spool/mail */
302579Sroot {
303579Sroot 	register i, n, c;
304579Sroot 	int new = 0;
305579Sroot 	struct stat stbuf;
306579Sroot 
307579Sroot 	signal(SIGINT, SIG_IGN);
308579Sroot 	signal(SIGHUP, SIG_IGN);
309579Sroot 	signal(SIGQUIT, SIG_IGN);
310579Sroot 	lock(mailfile);
311579Sroot 	stat(mailfile, &stbuf);
312579Sroot 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
313579Sroot 		malf = fopen(mailfile, "r");
314579Sroot 		if (malf == NULL) {
315579Sroot 			fprintf(stdout, "mail: can't re-read %s\n", mailfile);
316579Sroot 			done();
317579Sroot 		}
318579Sroot 		fseek(malf, let[nlet].adr, 0);
319579Sroot 		fclose(tmpf);
320579Sroot 		tmpf = fopen(lettmp, "a");
321579Sroot 		fseek(tmpf, let[nlet].adr, 0);
322579Sroot 		while ((c = fgetc(malf)) != EOF)
323579Sroot 			fputc(c, tmpf);
324579Sroot 		fclose(malf);
325579Sroot 		fclose(tmpf);
326579Sroot 		tmpf = fopen(lettmp, "r");
327579Sroot 		let[++nlet].adr = stbuf.st_size;
328579Sroot 		new = 1;
329579Sroot 	}
330579Sroot 	malf = fopen(mailfile, "w");
331579Sroot 	if (malf == NULL) {
332579Sroot 		fprintf(stderr, "mail: can't rewrite %s\n", lfil);
333579Sroot 		done();
334579Sroot 	}
335579Sroot 	n = 0;
336579Sroot 	for (i = 0; i < nlet; i++)
337579Sroot 		if (let[i].change != 'd') {
338579Sroot 			copylet(i, malf, ORDINARY);
339579Sroot 			n++;
340579Sroot 		}
341579Sroot 	fclose(malf);
342579Sroot 	if (new)
343579Sroot 		fprintf(stdout, "new mail arrived\n");
344579Sroot 	unlock();
345579Sroot }
346579Sroot 
347579Sroot copymt(f1, f2)	/* copy mail (f1) to temp (f2) */
348579Sroot FILE *f1, *f2;
349579Sroot {
350579Sroot 	long nextadr;
351579Sroot 
352579Sroot 	nlet = nextadr = 0;
353579Sroot 	let[0].adr = 0;
354579Sroot 	while (fgets(line, LSIZE, f1) != NULL) {
355579Sroot 		if (isfrom(line))
356579Sroot 			let[nlet++].adr = nextadr;
357579Sroot 		nextadr += strlen(line);
358579Sroot 		fputs(line, f2);
359579Sroot 	}
360579Sroot 	let[nlet].adr = nextadr;	/* last plus 1 */
361579Sroot }
362579Sroot 
36311893Seric copylet(n, f, type)
36411893Seric 	FILE *f;
36511893Seric {
36611893Seric 	int ch;
36711893Seric 	long k;
36811893Seric 
369579Sroot 	fseek(tmpf, let[n].adr, 0);
370579Sroot 	k = let[n+1].adr - let[n].adr;
371579Sroot 	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')
372579Sroot 		if(type!=ZAP) fputc(ch,f);
3736199Sroot 	if(type==REMOTE) {
3746199Sroot 		char hostname[32];
3756199Sroot 		gethostname(hostname, sizeof (hostname));
3766199Sroot 		fprintf(f, " remote from %s\n", hostname);
3776199Sroot 	} else if (type==FORWARD)
378579Sroot 		fprintf(f, forwmsg);
379579Sroot 	else if(type==ORDINARY)
380579Sroot 		fputc(ch,f);
381579Sroot 	while(k-->1)
382579Sroot 		fputc(ch=fgetc(tmpf), f);
383579Sroot 	if(type!=ZAP || ch!= '\n')
384579Sroot 		fputc(fgetc(tmpf), f);
385579Sroot }
386579Sroot 
387579Sroot isfrom(lp)
388579Sroot register char *lp;
389579Sroot {
390579Sroot 	register char *p;
391579Sroot 
392579Sroot 	for (p = from; *p; )
393579Sroot 		if (*lp++ != *p++)
394579Sroot 			return(0);
395579Sroot 	return(1);
396579Sroot }
397579Sroot 
3986015Swnj bulkmail(argc, argv)
399579Sroot char **argv;
400579Sroot {
401579Sroot 	char truename[100];
402579Sroot 	int first;
403579Sroot 	register char *cp;
404579Sroot 	int gaver = 0;
405579Sroot 	char *newargv[1000];
406579Sroot 	register char **ap;
407579Sroot 	register char **vp;
408579Sroot 	int dflag;
409579Sroot 
410579Sroot 	dflag = 0;
411579Sroot 	if (argc < 1)
412579Sroot 		fprintf(stderr, "puke\n");
413579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
414579Sroot 	{
415579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
416579Sroot 			dflag++;
417579Sroot 	}
418579Sroot 	if (!dflag)
419579Sroot 	{
4209978Seric 		/* give it to sendmail, rah rah! */
421579Sroot 		unlink(lettmp);
422579Sroot 		ap = newargv+1;
423579Sroot 		if (rmail)
424579Sroot 			*ap-- = "-s";
4259978Seric 		*ap = "-sendmail";
4264461Sroot 		setuid(getuid());
4279978Seric 		execv(SENDMAIL, ap);
4289978Seric 		perror(SENDMAIL);
429579Sroot 		exit(EX_UNAVAILABLE);
430579Sroot 	}
431579Sroot 
432579Sroot 	truename[0] = 0;
433579Sroot 	line[0] = '\0';
434579Sroot 
435579Sroot 	/*
436579Sroot 	 * When we fall out of this, argv[1] should be first name,
437579Sroot 	 * argc should be number of names + 1.
438579Sroot 	 */
439579Sroot 
440579Sroot 	while (argc > 1 && *argv[1] == '-') {
441579Sroot 		cp = *++argv;
442579Sroot 		argc--;
443579Sroot 		switch (cp[1]) {
444579Sroot 		case 'r':
445579Sroot 			if (argc <= 0) {
446579Sroot 				usage();
447579Sroot 				done();
448579Sroot 			}
44915288Seric 			if (strcmp(my_name, "root") == 0 ||
45015288Seric 			    strcmp(my_name, "daemon") == 0 ||
45115288Seric 			    strcmp(my_name, "network") == 0 ||
45215288Seric 			    strcmp(my_name, "uucp")) {
45315288Seric 				gaver++;
45415288Seric 				strcpy(truename, argv[1]);
45515288Seric 				fgets(line, LSIZE, stdin);
45615288Seric 				if (strncmp("From", line, 4) == 0)
45715288Seric 					line[0] = '\0';
45814934Sralph 			}
459579Sroot 			argv++;
460579Sroot 			argc--;
461579Sroot 			break;
462579Sroot 
463579Sroot 		case 'h':
464579Sroot 			if (argc <= 0) {
465579Sroot 				usage();
466579Sroot 				done();
467579Sroot 			}
468579Sroot 			hseqno = atoi(argv[1]);
469579Sroot 			argv++;
470579Sroot 			argc--;
471579Sroot 			break;
472579Sroot 
473579Sroot 		case 'd':
474579Sroot 			break;
475579Sroot 
476579Sroot 		default:
477579Sroot 			usage();
478579Sroot 			done();
479579Sroot 		}
480579Sroot 	}
481579Sroot 	if (argc <= 1) {
482579Sroot 		usage();
483579Sroot 		done();
484579Sroot 	}
485579Sroot 	if (gaver == 0)
486579Sroot 		strcpy(truename, my_name);
487579Sroot 	/*
488579Sroot 	if (argc > 4 && strcmp(argv[1], "-r") == 0) {
489579Sroot 		strcpy(truename, argv[2]);
490579Sroot 		argc -= 2;
491579Sroot 		argv += 2;
492579Sroot 		fgets(line, LSIZE, stdin);
49315288Seric 		if (strncmp("From", line, 4) == 0)
494579Sroot 			line[0] = '\0';
495579Sroot 	} else
496579Sroot 		strcpy(truename, my_name);
497579Sroot 	*/
498579Sroot 	time(&iop);
499579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
500579Sroot 	iop = ftell(tmpf);
501579Sroot 	flgf = 1;
502579Sroot 	for (first = 1;; first = 0) {
503579Sroot 		if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
504579Sroot 			break;
505579Sroot 		if (!first && fgets(line, LSIZE, stdin) == NULL)
506579Sroot 			break;
507579Sroot 		if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
508579Sroot 			break;
509579Sroot 		if (isfrom(line))
510579Sroot 			fputs(">", tmpf);
511579Sroot 		fputs(line, tmpf);
512579Sroot 		flgf = 0;
513579Sroot 	}
514579Sroot 	fputs("\n", tmpf);
515579Sroot 	nlet = 1;
516579Sroot 	let[0].adr = 0;
517579Sroot 	let[1].adr = ftell(tmpf);
518579Sroot 	fclose(tmpf);
519579Sroot 	if (flgf)
520579Sroot 		return;
521579Sroot 	tmpf = fopen(lettmp, "r");
522579Sroot 	if (tmpf == NULL) {
523579Sroot 		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
524579Sroot 		return;
525579Sroot 	}
5266015Swnj 	while (--argc > 0) {
5276015Swnj 		if (!sendmail(0, *++argv, truename))
528579Sroot 			error++;
5296015Swnj 	}
53010644Seric 	if (error && safefile(dead)) {
531579Sroot 		setuid(getuid());
532579Sroot 		malf = fopen(dead, "w");
533579Sroot 		if (malf == NULL) {
534579Sroot 			fprintf(stdout, "mail: cannot open %s\n", dead);
535579Sroot 			fclose(tmpf);
536579Sroot 			return;
537579Sroot 		}
538579Sroot 		copylet(0, malf, ZAP);
539579Sroot 		fclose(malf);
540579Sroot 		fprintf(stdout, "Mail saved in %s\n", dead);
541579Sroot 	}
542579Sroot 	fclose(tmpf);
543579Sroot }
544579Sroot 
545579Sroot sendrmt(n, name, rcmd)
546579Sroot char *name;
547579Sroot char *rcmd;
548579Sroot {
549579Sroot 	FILE *rmf, *popen();
550579Sroot 	register char *p;
551579Sroot 	char rsys[64], cmd[64];
552579Sroot 	register local, pid;
553579Sroot 	int sts;
554579Sroot 
555579Sroot 	local = 0;
556579Sroot 	if (index(name, '^')) {
557579Sroot 		while (p = index(name, '^'))
558579Sroot 			*p = '!';
559579Sroot 		if (strncmp(name, "researc", 7)) {
560579Sroot 			strcpy(rsys, "research");
561579Sroot 			if (*name != '!')
562579Sroot 				--name;
563579Sroot 			goto skip;
564579Sroot 		}
565579Sroot 	}
566579Sroot 	if (*name=='!')
567579Sroot 		name++;
568579Sroot 	for(p=rsys; *name!='!'; *p++ = *name++)
569579Sroot 		if (*name=='\0') {
570579Sroot 			local++;
571579Sroot 			break;
572579Sroot 		}
573579Sroot 	*p = '\0';
574579Sroot 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
575579Sroot 		fprintf(stdout, "null name\n");
576579Sroot 		return(0);
577579Sroot 	}
578579Sroot skip:
579579Sroot 	if ((pid = fork()) == -1) {
580579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
581579Sroot 		return(0);
582579Sroot 	}
583579Sroot 	if (pid) {
584579Sroot 		while (wait(&sts) != pid) {
585579Sroot 			if (wait(&sts)==-1)
586579Sroot 				return(0);
587579Sroot 		}
588579Sroot 		return(!sts);
589579Sroot 	}
590579Sroot 	setuid(getuid());
591579Sroot 	if (local)
592579Sroot 		sprintf(cmd, "%s %s", rcmd, rsys);
593579Sroot 	else {
594579Sroot 		if (index(name+1, '!'))
595579Sroot 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
596579Sroot 		else
597579Sroot 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
598579Sroot 	}
599579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
600579Sroot 		exit(1);
601579Sroot 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
60210783Seric 	exit(pclose(rmf) != 0);
603579Sroot }
604579Sroot 
605579Sroot usage()
606579Sroot {
607579Sroot 
608579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
609*15299Skarels 	error = EX_USAGE;
610579Sroot }
611579Sroot 
6126015Swnj #include <sys/socket.h>
6139226Ssam #include <netinet/in.h>
61410227Ssam #include <netdb.h>
61510227Ssam struct sockaddr_in biffaddr;
6166015Swnj 
6176015Swnj sendmail(n, name, fromaddr)
618579Sroot int n;
619579Sroot char *name;
620579Sroot char *fromaddr;
621579Sroot {
622579Sroot 	char file[100];
623579Sroot 	register char *p;
624579Sroot 	register mask;
625579Sroot 	struct passwd *pw, *getpwnam();
626579Sroot 	struct stat statb;
6273666Swnj 	char buf[128];
6283666Swnj 	int f;
62910227Ssam 	struct hostent *hp = NULL;
63010227Ssam 	struct servent *sp = NULL;
631579Sroot 
632579Sroot 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
633579Sroot 		;
634579Sroot 	if (*p == '!'|| *p=='^')
635579Sroot 		return(sendrmt(n, name, 0));
636579Sroot 	if ((pw = getpwnam(name)) == NULL) {
637579Sroot 		fprintf(stdout, "mail: can't send to %s\n", name);
638579Sroot 		return(0);
639579Sroot 	}
640579Sroot 	cat(file, maildir, name);
641579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
642579Sroot 		strcat(file, "/");
643579Sroot 		strcat(file, name);
644579Sroot 	}
645579Sroot 	mask = umask(MAILMODE);
64610644Seric 	if (!safefile(file))
6474458Sroot 		return(0);
64811893Seric 	lock(file);
649579Sroot 	malf = fopen(file, "a");
650579Sroot 	umask(mask);
651579Sroot 	if (malf == NULL) {
65211893Seric 		unlock();
653579Sroot 		fprintf(stdout, "mail: cannot append to %s\n", file);
654579Sroot 		return(0);
655579Sroot 	}
6566015Swnj 	chown(file, pw->pw_uid, pw->pw_gid);
6573666Swnj 	{
65810227Ssam 		hp = gethostbyname("localhost");
65910227Ssam 		sp = getservbyname("biff", "udp");
66010227Ssam 		if (hp && sp) {
66110227Ssam 			f = socket(AF_INET, SOCK_DGRAM, 0, 0);
66210227Ssam 			sprintf(buf, "%s@%d\n", name, ftell(malf));
66310227Ssam 		}
6643666Swnj 	}
665579Sroot 	copylet(n, malf, ORDINARY);
6666015Swnj 	fclose(malf);
66710227Ssam 	if (hp && sp) {
66810227Ssam 		biffaddr.sin_family = hp->h_addrtype;
66910227Ssam 		bcopy(hp->h_addr, &biffaddr.sin_addr, hp->h_length);
67010227Ssam 		biffaddr.sin_port = sp->s_port;
6719226Ssam 		sendto(f, buf, strlen(buf)+1, 0, &biffaddr, sizeof (biffaddr));
6723666Swnj 		close(f);
6733666Swnj 	}
674579Sroot 	unlock();
675579Sroot 	return(1);
676579Sroot }
677579Sroot 
678579Sroot delete(i)
679579Sroot {
680579Sroot 	setsig(i, delete);
681579Sroot 	fprintf(stderr, "\n");
682579Sroot 	if(delflg)
683579Sroot 		longjmp(sjbuf, 1);
684579Sroot 	done();
685579Sroot }
686579Sroot 
687579Sroot /*
688579Sroot  * Lock the specified mail file by setting the file mailfile.lock.
689579Sroot  * We must, of course, be careful to unlink the lock file by a call
690579Sroot  * to unlock before we stop.  The algorithm used here is to see if
691579Sroot  * the lock exists, and if it does, to check its modify time.  If it
692579Sroot  * is older than 30 seconds, we assume error and set our own file.
693579Sroot  * Otherwise, we wait for 5 seconds and try again.
694579Sroot  */
695579Sroot 
696579Sroot char	*maillock	= ".lock";		/* Lock suffix for mailname */
697579Sroot char	*lockname	= "/usr/spool/mail/tmXXXXXX";
698579Sroot char	locktmp[30];				/* Usable lock temporary */
699579Sroot char	curlock[50];				/* Last used name of lock */
700579Sroot int	locked;					/* To note that we locked it */
701579Sroot 
702579Sroot lock(file)
703579Sroot char *file;
704579Sroot {
705579Sroot 	register int f;
706579Sroot 	struct stat sbuf;
707579Sroot 	long curtime;
708579Sroot 	int statfailed;
709579Sroot 
710579Sroot 	if (locked || flgf)
711579Sroot 		return(0);
712579Sroot 	strcpy(curlock, file);
713579Sroot 	strcat(curlock, maillock);
714579Sroot 	strcpy(locktmp, lockname);
715579Sroot 	mktemp(locktmp);
716579Sroot 	unlink(locktmp);
717579Sroot 	statfailed = 0;
718579Sroot 	for (;;) {
719579Sroot 		f = lock1(locktmp, curlock);
720579Sroot 		if (f == 0) {
721579Sroot 			locked = 1;
722579Sroot 			return(0);
723579Sroot 		}
724579Sroot 		if (stat(curlock, &sbuf) < 0) {
725579Sroot 			if (statfailed++ > 5)
726579Sroot 				return(-1);
727579Sroot 			sleep(5);
728579Sroot 			continue;
729579Sroot 		}
730579Sroot 		statfailed = 0;
731579Sroot 		time(&curtime);
732579Sroot 		if (curtime < sbuf.st_ctime + 30) {
733579Sroot 			sleep(5);
734579Sroot 			continue;
735579Sroot 		}
736579Sroot 		unlink(curlock);
737579Sroot 	}
738579Sroot }
739579Sroot 
740579Sroot /*
741579Sroot  * Remove the mail lock, and note that we no longer
742579Sroot  * have it locked.
743579Sroot  */
744579Sroot 
745579Sroot unlock()
746579Sroot {
747579Sroot 
748579Sroot 	unlink(curlock);
749579Sroot 	locked = 0;
750579Sroot }
751579Sroot 
752579Sroot /*
753579Sroot  * Attempt to set the lock by creating the temporary file,
754579Sroot  * then doing a link/unlink.  If it fails, return -1 else 0
755579Sroot  */
756579Sroot 
757579Sroot lock1(tempfile, name)
758579Sroot 	char tempfile[], name[];
759579Sroot {
760579Sroot 	register int fd;
761579Sroot 
762579Sroot 	fd = creat(tempfile, 0);
763579Sroot 	if (fd < 0)
764579Sroot 		return(-1);
765579Sroot 	close(fd);
766579Sroot 	if (link(tempfile, name) < 0) {
767579Sroot 		unlink(tempfile);
768579Sroot 		return(-1);
769579Sroot 	}
770579Sroot 	unlink(tempfile);
771579Sroot 	return(0);
772579Sroot }
773579Sroot 
774579Sroot done()
775579Sroot {
776579Sroot 	if(locked)
777579Sroot 		unlock();
778579Sroot 	unlink(lettmp);
779579Sroot 	unlink(locktmp);
780579Sroot 	exit(error);
781579Sroot }
782579Sroot 
783579Sroot cat(to, from1, from2)
784579Sroot char *to, *from1, *from2;
785579Sroot {
786579Sroot 	int i, j;
787579Sroot 
788579Sroot 	j = 0;
789579Sroot 	for (i=0; from1[i]; i++)
790579Sroot 		to[j++] = from1[i];
791579Sroot 	for (i=0; from2[i]; i++)
792579Sroot 		to[j++] = from2[i];
793579Sroot 	to[j] = 0;
794579Sroot }
795579Sroot 
796579Sroot char *getarg(s, p)	/* copy p... into s, update p */
797579Sroot register char *s, *p;
798579Sroot {
799579Sroot 	while (*p == ' ' || *p == '\t')
800579Sroot 		p++;
801579Sroot 	if (*p == '\n' || *p == '\0')
802579Sroot 		return(NULL);
803579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
804579Sroot 		*s++ = *p++;
805579Sroot 	*s = '\0';
806579Sroot 	return(p);
807579Sroot }
80810644Seric 
80910644Seric safefile(f)
81010644Seric 	char *f;
81110644Seric {
81210644Seric 	struct stat statb;
81310644Seric 
81410644Seric 	if (lstat(f, &statb) < 0)
81510644Seric 		return (1);
81610644Seric 	if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
81710644Seric 		fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f);
81810644Seric 		return (0);
81910644Seric 	}
82010644Seric 	return (1);
82110644Seric }
822