1579Sroot #include <ctype.h>
2579Sroot #include <stdio.h>
3579Sroot #include <pwd.h>
4579Sroot #include <utmp.h>
5579Sroot #include <signal.h>
6579Sroot #include <sys/types.h>
7579Sroot #include <sys/stat.h>
8579Sroot #include <setjmp.h>
9579Sroot #include <whoami.h>
10579Sroot #include <sysexits.h>
11579Sroot 
12*6015Swnj static char SccsId[] = "@(#)mail.local.c	4.6	02/28/82";
13580Seric 
14579Sroot #define DELIVERMAIL	"/etc/delivermail"
15579Sroot 
16579Sroot 
17579Sroot /*copylet flags */
18579Sroot 	/*remote mail, add rmtmsg */
19579Sroot #define REMOTE	1
20579Sroot 	/* zap header and trailing empty line */
21579Sroot #define ZAP	3
22579Sroot #define ORDINARY 2
23579Sroot #define	FORWARD	4
24579Sroot #define	LSIZE	256
25579Sroot #define	MAXLET	300	/* maximum number of letters */
26579Sroot #define	MAILMODE (~0644)		/* mode of created mail */
27580Seric # ifndef DELIVERMAIL
28579Sroot #define	RMAIL	"/usr/net/bin/sendberkmail"
29579Sroot #define LOCNAM1	"csvax"
30579Sroot #define LOCNAM2	"ucbvax"
31579Sroot #define LOCNAM3	"vax"
32579Sroot #define LOCNAM4	"v"
33580Seric # endif
34579Sroot 
35579Sroot char	line[LSIZE];
36579Sroot char	resp[LSIZE];
37579Sroot struct let {
38579Sroot 	long	adr;
39579Sroot 	char	change;
40579Sroot } let[MAXLET];
41579Sroot int	nlet	= 0;
42579Sroot char	lfil[50];
43579Sroot long	iop, time();
44579Sroot char	*getenv();
45579Sroot char	*index();
46579Sroot char	lettmp[] = "/tmp/maXXXXX";
47579Sroot char	maildir[] = "/usr/spool/mail/";
48579Sroot char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
49579Sroot char	dead[] = "dead.letter";
50579Sroot char	*thissys = sysname;
51579Sroot char	*netname = "vax";
52579Sroot char	forwmsg[] = " forwarded\n";
53579Sroot FILE	*tmpf;
54579Sroot FILE	*malf;
55579Sroot char	*my_name;
56579Sroot char	*getlogin();
57579Sroot struct	passwd	*getpwuid();
58579Sroot int	error;
59579Sroot int	changed;
60579Sroot int	forward;
61579Sroot char	from[] = "From ";
62579Sroot long	ftell();
63579Sroot int	delete();
64579Sroot char	*ctime();
65579Sroot int	flgf;
66579Sroot int	flgp;
67579Sroot int	delflg = 1;
68579Sroot int	hseqno;
69579Sroot jmp_buf	sjbuf;
70579Sroot int	rmail;
71579Sroot 
72579Sroot main(argc, argv)
73579Sroot char **argv;
74579Sroot {
75579Sroot 	register i;
76579Sroot 	char sobuf[BUFSIZ];
77579Sroot 
78579Sroot 	setbuf(stdout, sobuf);
79579Sroot 	mktemp(lettmp);
80579Sroot 	unlink(lettmp);
81579Sroot 	my_name = getlogin();
82579Sroot 	if (my_name == NULL || strlen(my_name) == 0) {
83579Sroot 		struct passwd *pwent;
84579Sroot 		pwent = getpwuid(getuid());
85579Sroot 		if (pwent==NULL)
86579Sroot 			my_name = "???";
87579Sroot 		else
88579Sroot 			my_name = pwent->pw_name;
89579Sroot 	}
90579Sroot 	if(setjmp(sjbuf)) done();
91579Sroot 	for (i=0; i<20; i++)
92579Sroot 		setsig(i, delete);
93579Sroot 	tmpf = fopen(lettmp, "w");
94579Sroot 	if (tmpf == NULL) {
95579Sroot 		fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
96579Sroot 		done();
97579Sroot 	}
98579Sroot 	if (argv[0][0] == 'r')
99579Sroot 		rmail++;
100579Sroot 	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
101579Sroot 	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
102579Sroot 		printmail(argc, argv);
103579Sroot 	else
104*6015Swnj 		bulkmail(argc, argv);
105579Sroot 	done();
106579Sroot }
107579Sroot 
108579Sroot setsig(i, f)
109579Sroot int i;
110579Sroot int (*f)();
111579Sroot {
112579Sroot 	if(signal(i, SIG_IGN)!=SIG_IGN)
113579Sroot 		signal(i, f);
114579Sroot }
115579Sroot 
116579Sroot any(c, str)
117579Sroot 	register int c;
118579Sroot 	register char *str;
119579Sroot {
120579Sroot 
121579Sroot 	while (*str)
122579Sroot 		if (c == *str++)
123579Sroot 			return(1);
124579Sroot 	return(0);
125579Sroot }
126579Sroot 
127579Sroot printmail(argc, argv)
128579Sroot char **argv;
129579Sroot {
130579Sroot 	int flg, i, j, print;
131579Sroot 	char *p, *getarg();
132579Sroot 	struct stat statb;
133579Sroot 
134579Sroot 	setuid(getuid());
135579Sroot 	cat(mailfile, maildir, my_name);
136579Sroot 	if (stat(mailfile, &statb) >= 0
137579Sroot 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
138579Sroot 		strcat(mailfile, "/");
139579Sroot 		strcat(mailfile, my_name);
140579Sroot 	}
141579Sroot 	for (; argc>1; argv++, argc--) {
142579Sroot 		if (argv[1][0]=='-') {
143579Sroot 			if (argv[1][1]=='q')
144579Sroot 				delflg = 0;
145579Sroot 			else if (argv[1][1]=='p') {
146579Sroot 				flgp++;
147579Sroot 				delflg = 0;
148579Sroot 			} else if (argv[1][1]=='f') {
149579Sroot 				if (argc>=3) {
150579Sroot 					strcpy(mailfile, argv[2]);
151579Sroot 					argv++;
152579Sroot 					argc--;
153579Sroot 				}
154579Sroot 			} else if (argv[1][1]=='r') {
155579Sroot 				forward = 1;
156579Sroot 			} else if (argv[1][1]=='h') {
157579Sroot 				forward = 1;
158579Sroot 			} else {
159579Sroot 				fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
160579Sroot 				done();
161579Sroot 			}
162579Sroot 		} else
163579Sroot 			break;
164579Sroot 	}
165579Sroot 	malf = fopen(mailfile, "r");
166579Sroot 	if (malf == NULL) {
167579Sroot 		fprintf(stdout, "No mail.\n");
168579Sroot 		return;
169579Sroot 	}
170579Sroot 	lock(mailfile);
171579Sroot 	copymt(malf, tmpf);
172579Sroot 	fclose(malf);
173579Sroot 	fclose(tmpf);
174579Sroot 	unlock();
175579Sroot 	tmpf = fopen(lettmp, "r");
176579Sroot 
177579Sroot 	changed = 0;
178579Sroot 	print = 1;
179579Sroot 	for (i = 0; i < nlet; ) {
180579Sroot 		j = forward ? i : nlet - i - 1;
181579Sroot 		if(setjmp(sjbuf)) {
182579Sroot 			print=0;
183579Sroot 		} else {
184579Sroot 			if (print)
185579Sroot 				copylet(j, stdout, ORDINARY);
186579Sroot 			print = 1;
187579Sroot 		}
188579Sroot 		if (flgp) {
189579Sroot 			i++;
190579Sroot 			continue;
191579Sroot 		}
192579Sroot 		setjmp(sjbuf);
193579Sroot 		fprintf(stdout, "? ");
194579Sroot 		fflush(stdout);
195579Sroot 		if (fgets(resp, LSIZE, stdin) == NULL)
196579Sroot 			break;
197579Sroot 		switch (resp[0]) {
198579Sroot 
199579Sroot 		default:
200579Sroot 			fprintf(stderr, "usage\n");
201579Sroot 		case '?':
202579Sroot 			print = 0;
203579Sroot 			fprintf(stderr, "q\tquit\n");
204579Sroot 			fprintf(stderr, "x\texit without changing mail\n");
205579Sroot 			fprintf(stderr, "p\tprint\n");
206579Sroot 			fprintf(stderr, "s[file]\tsave (default mbox)\n");
207579Sroot 			fprintf(stderr, "w[file]\tsame without header\n");
208579Sroot 			fprintf(stderr, "-\tprint previous\n");
209579Sroot 			fprintf(stderr, "d\tdelete\n");
210579Sroot 			fprintf(stderr, "+\tnext (no delete)\n");
211579Sroot 			fprintf(stderr, "m user\tmail to user\n");
212579Sroot 			fprintf(stderr, "! cmd\texecute cmd\n");
213579Sroot 			break;
214579Sroot 
215579Sroot 		case '+':
216579Sroot 		case 'n':
217579Sroot 		case '\n':
218579Sroot 			i++;
219579Sroot 			break;
220579Sroot 		case 'x':
221579Sroot 			changed = 0;
222579Sroot 		case 'q':
223579Sroot 			goto donep;
224579Sroot 		case 'p':
225579Sroot 			break;
226579Sroot 		case '^':
227579Sroot 		case '-':
228579Sroot 			if (--i < 0)
229579Sroot 				i = 0;
230579Sroot 			break;
231579Sroot 		case 'y':
232579Sroot 		case 'w':
233579Sroot 		case 's':
234579Sroot 			flg = 0;
235579Sroot 			if (resp[1] != '\n' && resp[1] != ' ') {
236579Sroot 				printf("illegal\n");
237579Sroot 				flg++;
238579Sroot 				print = 0;
239579Sroot 				continue;
240579Sroot 			}
241579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
242579Sroot 				p = getenv("HOME");
243579Sroot 				if(p != 0)
244579Sroot 					cat(resp+1, p, "/mbox");
245579Sroot 				else
246579Sroot 					cat(resp+1, "", "mbox");
247579Sroot 			}
248579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
249579Sroot 				malf = fopen(lfil, "a");
250579Sroot 				if (malf == NULL) {
251579Sroot 					fprintf(stdout, "mail: cannot append to %s\n", lfil);
252579Sroot 					flg++;
253579Sroot 					continue;
254579Sroot 				}
255579Sroot 				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
256579Sroot 				fclose(malf);
257579Sroot 			}
258579Sroot 			if (flg)
259579Sroot 				print = 0;
260579Sroot 			else {
261579Sroot 				let[j].change = 'd';
262579Sroot 				changed++;
263579Sroot 				i++;
264579Sroot 			}
265579Sroot 			break;
266579Sroot 		case 'm':
267579Sroot 			flg = 0;
268579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
269579Sroot 				i++;
270579Sroot 				continue;
271579Sroot 			}
272579Sroot 			if (resp[1] != ' ') {
273579Sroot 				printf("invalid command\n");
274579Sroot 				flg++;
275579Sroot 				print = 0;
276579Sroot 				continue;
277579Sroot 			}
278579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
279579Sroot 				if (!sendrmt(j, lfil, "/bin/mail"))	/* couldn't send it */
280579Sroot 					flg++;
281579Sroot 			if (flg)
282579Sroot 				print = 0;
283579Sroot 			else {
284579Sroot 				let[j].change = 'd';
285579Sroot 				changed++;
286579Sroot 				i++;
287579Sroot 			}
288579Sroot 			break;
289579Sroot 		case '!':
290579Sroot 			system(resp+1);
291579Sroot 			printf("!\n");
292579Sroot 			print = 0;
293579Sroot 			break;
294579Sroot 		case 'd':
295579Sroot 			let[j].change = 'd';
296579Sroot 			changed++;
297579Sroot 			i++;
298579Sroot 			if (resp[1] == 'q')
299579Sroot 				goto donep;
300579Sroot 			break;
301579Sroot 		}
302579Sroot 	}
303579Sroot    donep:
304579Sroot 	if (changed)
305579Sroot 		copyback();
306579Sroot }
307579Sroot 
308579Sroot copyback()	/* copy temp or whatever back to /usr/spool/mail */
309579Sroot {
310579Sroot 	register i, n, c;
311579Sroot 	int new = 0;
312579Sroot 	struct stat stbuf;
313579Sroot 
314579Sroot 	signal(SIGINT, SIG_IGN);
315579Sroot 	signal(SIGHUP, SIG_IGN);
316579Sroot 	signal(SIGQUIT, SIG_IGN);
317579Sroot 	lock(mailfile);
318579Sroot 	stat(mailfile, &stbuf);
319579Sroot 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
320579Sroot 		malf = fopen(mailfile, "r");
321579Sroot 		if (malf == NULL) {
322579Sroot 			fprintf(stdout, "mail: can't re-read %s\n", mailfile);
323579Sroot 			done();
324579Sroot 		}
325579Sroot 		fseek(malf, let[nlet].adr, 0);
326579Sroot 		fclose(tmpf);
327579Sroot 		tmpf = fopen(lettmp, "a");
328579Sroot 		fseek(tmpf, let[nlet].adr, 0);
329579Sroot 		while ((c = fgetc(malf)) != EOF)
330579Sroot 			fputc(c, tmpf);
331579Sroot 		fclose(malf);
332579Sroot 		fclose(tmpf);
333579Sroot 		tmpf = fopen(lettmp, "r");
334579Sroot 		let[++nlet].adr = stbuf.st_size;
335579Sroot 		new = 1;
336579Sroot 	}
337579Sroot 	malf = fopen(mailfile, "w");
338579Sroot 	if (malf == NULL) {
339579Sroot 		fprintf(stderr, "mail: can't rewrite %s\n", lfil);
340579Sroot 		done();
341579Sroot 	}
342579Sroot 	n = 0;
343579Sroot 	for (i = 0; i < nlet; i++)
344579Sroot 		if (let[i].change != 'd') {
345579Sroot 			copylet(i, malf, ORDINARY);
346579Sroot 			n++;
347579Sroot 		}
348579Sroot 	fclose(malf);
349579Sroot 	if (new)
350579Sroot 		fprintf(stdout, "new mail arrived\n");
351579Sroot 	unlock();
352579Sroot }
353579Sroot 
354579Sroot copymt(f1, f2)	/* copy mail (f1) to temp (f2) */
355579Sroot FILE *f1, *f2;
356579Sroot {
357579Sroot 	long nextadr;
358579Sroot 
359579Sroot 	nlet = nextadr = 0;
360579Sroot 	let[0].adr = 0;
361579Sroot 	while (fgets(line, LSIZE, f1) != NULL) {
362579Sroot 		if (isfrom(line))
363579Sroot 			let[nlet++].adr = nextadr;
364579Sroot 		nextadr += strlen(line);
365579Sroot 		fputs(line, f2);
366579Sroot 	}
367579Sroot 	let[nlet].adr = nextadr;	/* last plus 1 */
368579Sroot }
369579Sroot 
370579Sroot copylet(n, f, type) FILE *f;
371579Sroot {	int ch, k;
372579Sroot 	fseek(tmpf, let[n].adr, 0);
373579Sroot 	k = let[n+1].adr - let[n].adr;
374579Sroot 	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')
375579Sroot 		if(type!=ZAP) fputc(ch,f);
376579Sroot 	if(type==REMOTE)
377579Sroot 		fprintf(f, " remote from %s\n", thissys);
378579Sroot 	else if (type==FORWARD)
379579Sroot 		fprintf(f, forwmsg);
380579Sroot 	else if(type==ORDINARY)
381579Sroot 		fputc(ch,f);
382579Sroot 	while(k-->1)
383579Sroot 		fputc(ch=fgetc(tmpf), f);
384579Sroot 	if(type!=ZAP || ch!= '\n')
385579Sroot 		fputc(fgetc(tmpf), f);
386579Sroot }
387579Sroot 
388579Sroot isfrom(lp)
389579Sroot register char *lp;
390579Sroot {
391579Sroot 	register char *p;
392579Sroot 
393579Sroot 	for (p = from; *p; )
394579Sroot 		if (*lp++ != *p++)
395579Sroot 			return(0);
396579Sroot 	return(1);
397579Sroot }
398579Sroot 
399*6015Swnj bulkmail(argc, argv)
400579Sroot char **argv;
401579Sroot {
402579Sroot 	char truename[100];
403579Sroot 	int first;
404579Sroot 	register char *cp;
405579Sroot 	int gaver = 0;
406579Sroot # ifdef DELIVERMAIL
407579Sroot 	char *newargv[1000];
408579Sroot 	register char **ap;
409579Sroot 	register char **vp;
410579Sroot 	int dflag;
411579Sroot 
412579Sroot 	dflag = 0;
413579Sroot 	if (argc < 1)
414579Sroot 		fprintf(stderr, "puke\n");
415579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
416579Sroot 	{
417579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
418579Sroot 			dflag++;
419579Sroot 	}
420579Sroot 	if (!dflag)
421579Sroot 	{
422579Sroot 		/* give it to delivermail, rah rah! */
423579Sroot 		unlink(lettmp);
424579Sroot 		ap = newargv+1;
425579Sroot 		if (rmail)
426579Sroot 			*ap-- = "-s";
427579Sroot 		*ap = "-delivermail";
4284461Sroot 		setuid(getuid());
429579Sroot 		execv(DELIVERMAIL, ap);
430579Sroot 		perror(DELIVERMAIL);
431579Sroot 		exit(EX_UNAVAILABLE);
432579Sroot 	}
433579Sroot # endif DELIVERMAIL
434579Sroot 
435579Sroot 	truename[0] = 0;
436579Sroot 	line[0] = '\0';
437579Sroot 
438579Sroot 	/*
439579Sroot 	 * When we fall out of this, argv[1] should be first name,
440579Sroot 	 * argc should be number of names + 1.
441579Sroot 	 */
442579Sroot 
443579Sroot 	while (argc > 1 && *argv[1] == '-') {
444579Sroot 		cp = *++argv;
445579Sroot 		argc--;
446579Sroot 		switch (cp[1]) {
447579Sroot 		case 'r':
448579Sroot 			if (argc <= 0) {
449579Sroot 				usage();
450579Sroot 				done();
451579Sroot 			}
452579Sroot 			gaver++;
453579Sroot 			strcpy(truename, argv[1]);
454579Sroot 			fgets(line, LSIZE, stdin);
455579Sroot 			if (strcmpn("From", line, 4) == 0)
456579Sroot 				line[0] = '\0';
457579Sroot 			argv++;
458579Sroot 			argc--;
459579Sroot 			break;
460579Sroot 
461579Sroot 		case 'h':
462579Sroot 			if (argc <= 0) {
463579Sroot 				usage();
464579Sroot 				done();
465579Sroot 			}
466579Sroot 			hseqno = atoi(argv[1]);
467579Sroot 			argv++;
468579Sroot 			argc--;
469579Sroot 			break;
470579Sroot 
471579Sroot # ifdef DELIVERMAIL
472579Sroot 		case 'd':
473579Sroot 			break;
474579Sroot # endif DELIVERMAIL
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);
493579Sroot 		if (strcmpn("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 	}
526*6015Swnj 	while (--argc > 0) {
527*6015Swnj 		if (!sendmail(0, *++argv, truename))
528579Sroot 			error++;
529*6015Swnj 	}
530579Sroot 	if (error) {
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);
602579Sroot 	pclose(rmf);
603579Sroot 	exit(0);
604579Sroot }
605579Sroot 
606580Seric # ifndef DELIVERMAIL
607579Sroot /*
608579Sroot  * Send mail on the Berkeley network.
609579Sroot  * Sorry Bill, sendrmt() is so awful we just gave up.
610579Sroot  */
611579Sroot 
612579Sroot sendberkmail(n, name, fromaddr)
613579Sroot 	char name[];
614579Sroot 	char fromaddr[];
615579Sroot {
616579Sroot 	char cmd[200];
617579Sroot 	register FILE *cmdf;
618579Sroot 
619579Sroot 	sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name);
620579Sroot 	if ((cmdf = popen(cmd, "w")) == NULL) {
621579Sroot 		perror(RMAIL);
622579Sroot 		return(0);
623579Sroot 	}
624579Sroot 	copylet(n, cmdf, ORDINARY);
625579Sroot 	pclose(cmdf);
626579Sroot 	return(9);
627579Sroot }
628580Seric # endif
629579Sroot 
630579Sroot usage()
631579Sroot {
632579Sroot 
633579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
634579Sroot }
635579Sroot 
636*6015Swnj #include <sys/socket.h>
637*6015Swnj #include <net/in.h>
638*6015Swnj #include <wellknown.h>
639*6015Swnj struct sockaddr_in biffaddr = { AF_INET, IPPORT_BIFFUDP };
640*6015Swnj char *localhost = "localhost";
641*6015Swnj 
642*6015Swnj sendmail(n, name, fromaddr)
643579Sroot int n;
644579Sroot char *name;
645579Sroot char *fromaddr;
646579Sroot {
647579Sroot 	char file[100];
648579Sroot 	register char *p;
649579Sroot 	register mask;
650579Sroot 	struct passwd *pw, *getpwnam();
651579Sroot 	struct stat statb;
6523666Swnj 	char buf[128];
6533666Swnj 	int f;
654579Sroot 
655580Seric # ifndef DELIVERMAIL
656579Sroot 	stripfx(LOCNAM1, &name);
657579Sroot 	stripfx(LOCNAM2, &name);
658579Sroot 	stripfx(LOCNAM3, &name);
659579Sroot 	stripfx(LOCNAM4, &name);
660579Sroot 	if(*name == ':')name++;		/* skip colon in to-name */
661580Seric 	for(p=name; *p!=':' && *p!='!' && *p!='^' &&*p!='\0'; p++);
662579Sroot 	/* if(*p == ':') return(sendrmt(n, name, RMAIL)); */
663579Sroot 	if (*p == ':')
664579Sroot 		return(sendberkmail(n, name, fromaddr));
665580Seric 	else if (*p=='\0' && strcmp(name, "msgs") == 0)
666580Seric 		return(sendrmt(n, "-s", "/usr/ucb/msgs"));
667580Seric # endif
668579Sroot 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
669579Sroot 		;
670579Sroot 	if (*p == '!'|| *p=='^')
671579Sroot 		return(sendrmt(n, name, 0));
672579Sroot 	if ((pw = getpwnam(name)) == NULL) {
673579Sroot 		fprintf(stdout, "mail: can't send to %s\n", name);
674579Sroot 		return(0);
675579Sroot 	}
676579Sroot 	cat(file, maildir, name);
677579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
678579Sroot 		strcat(file, "/");
679579Sroot 		strcat(file, name);
680579Sroot 	}
681579Sroot 	mask = umask(MAILMODE);
6824459Sroot 	if (stat(file, &statb) >= 0 && statb.st_nlink != 1) {
6834458Sroot 		fprintf(stdout, "mail: %s's mail file has more than one link\n", name);
6844458Sroot 		return(0);
6854458Sroot 	}
686579Sroot 	malf = fopen(file, "a");
687579Sroot 	umask(mask);
688579Sroot 	if (malf == NULL) {
689579Sroot 		fprintf(stdout, "mail: cannot append to %s\n", file);
690579Sroot 		return(0);
691579Sroot 	}
692579Sroot 	lock(file);
693*6015Swnj 	chown(file, pw->pw_uid, pw->pw_gid);
6943666Swnj 	{
695*6015Swnj 		f = socket(SOCK_DGRAM, 0, 0, 0);
6963666Swnj 		sprintf(buf, "%s@%d\n", name, ftell(malf));
6973666Swnj 	}
698579Sroot 	copylet(n, malf, ORDINARY);
699*6015Swnj 	fclose(malf);
7003666Swnj 	if (f >= 0) {
701*6015Swnj 		biffaddr.sin_addr.s_addr = rhost(&localhost);
702*6015Swnj 		send(f, &biffaddr, buf, strlen(buf)+1);
7033666Swnj 		close(f);
7043666Swnj 	}
705579Sroot 	unlock();
706579Sroot 	return(1);
707579Sroot }
708579Sroot 
709579Sroot delete(i)
710579Sroot {
711579Sroot 	setsig(i, delete);
712579Sroot 	fprintf(stderr, "\n");
713579Sroot 	if(delflg)
714579Sroot 		longjmp(sjbuf, 1);
715579Sroot 	done();
716579Sroot }
717579Sroot 
718579Sroot /*
719579Sroot  * Lock the specified mail file by setting the file mailfile.lock.
720579Sroot  * We must, of course, be careful to unlink the lock file by a call
721579Sroot  * to unlock before we stop.  The algorithm used here is to see if
722579Sroot  * the lock exists, and if it does, to check its modify time.  If it
723579Sroot  * is older than 30 seconds, we assume error and set our own file.
724579Sroot  * Otherwise, we wait for 5 seconds and try again.
725579Sroot  */
726579Sroot 
727579Sroot char	*maillock	= ".lock";		/* Lock suffix for mailname */
728579Sroot char	*lockname	= "/usr/spool/mail/tmXXXXXX";
729579Sroot char	locktmp[30];				/* Usable lock temporary */
730579Sroot char	curlock[50];				/* Last used name of lock */
731579Sroot int	locked;					/* To note that we locked it */
732579Sroot 
733579Sroot lock(file)
734579Sroot char *file;
735579Sroot {
736579Sroot 	register int f;
737579Sroot 	struct stat sbuf;
738579Sroot 	long curtime;
739579Sroot 	int statfailed;
740579Sroot 
741579Sroot 	if (locked || flgf)
742579Sroot 		return(0);
743579Sroot 	strcpy(curlock, file);
744579Sroot 	strcat(curlock, maillock);
745579Sroot 	strcpy(locktmp, lockname);
746579Sroot 	mktemp(locktmp);
747579Sroot 	unlink(locktmp);
748579Sroot 	statfailed = 0;
749579Sroot 	for (;;) {
750579Sroot 		f = lock1(locktmp, curlock);
751579Sroot 		if (f == 0) {
752579Sroot 			locked = 1;
753579Sroot 			return(0);
754579Sroot 		}
755579Sroot 		if (stat(curlock, &sbuf) < 0) {
756579Sroot 			if (statfailed++ > 5)
757579Sroot 				return(-1);
758579Sroot 			sleep(5);
759579Sroot 			continue;
760579Sroot 		}
761579Sroot 		statfailed = 0;
762579Sroot 		time(&curtime);
763579Sroot 		if (curtime < sbuf.st_ctime + 30) {
764579Sroot 			sleep(5);
765579Sroot 			continue;
766579Sroot 		}
767579Sroot 		unlink(curlock);
768579Sroot 	}
769579Sroot }
770579Sroot 
771579Sroot /*
772579Sroot  * Remove the mail lock, and note that we no longer
773579Sroot  * have it locked.
774579Sroot  */
775579Sroot 
776579Sroot unlock()
777579Sroot {
778579Sroot 
779579Sroot 	unlink(curlock);
780579Sroot 	locked = 0;
781579Sroot }
782579Sroot 
783579Sroot /*
784579Sroot  * Attempt to set the lock by creating the temporary file,
785579Sroot  * then doing a link/unlink.  If it fails, return -1 else 0
786579Sroot  */
787579Sroot 
788579Sroot lock1(tempfile, name)
789579Sroot 	char tempfile[], name[];
790579Sroot {
791579Sroot 	register int fd;
792579Sroot 
793579Sroot 	fd = creat(tempfile, 0);
794579Sroot 	if (fd < 0)
795579Sroot 		return(-1);
796579Sroot 	close(fd);
797579Sroot 	if (link(tempfile, name) < 0) {
798579Sroot 		unlink(tempfile);
799579Sroot 		return(-1);
800579Sroot 	}
801579Sroot 	unlink(tempfile);
802579Sroot 	return(0);
803579Sroot }
804579Sroot 
805579Sroot done()
806579Sroot {
807579Sroot 	if(locked)
808579Sroot 		unlock();
809579Sroot 	unlink(lettmp);
810579Sroot 	unlink(locktmp);
811579Sroot 	exit(error);
812579Sroot }
813579Sroot 
814579Sroot cat(to, from1, from2)
815579Sroot char *to, *from1, *from2;
816579Sroot {
817579Sroot 	int i, j;
818579Sroot 
819579Sroot 	j = 0;
820579Sroot 	for (i=0; from1[i]; i++)
821579Sroot 		to[j++] = from1[i];
822579Sroot 	for (i=0; from2[i]; i++)
823579Sroot 		to[j++] = from2[i];
824579Sroot 	to[j] = 0;
825579Sroot }
826579Sroot 
827579Sroot char *getarg(s, p)	/* copy p... into s, update p */
828579Sroot register char *s, *p;
829579Sroot {
830579Sroot 	while (*p == ' ' || *p == '\t')
831579Sroot 		p++;
832579Sroot 	if (*p == '\n' || *p == '\0')
833579Sroot 		return(NULL);
834579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
835579Sroot 		*s++ = *p++;
836579Sroot 	*s = '\0';
837579Sroot 	return(p);
838579Sroot }
839580Seric # ifndef DELIVERMAIL
840579Sroot /*
841579Sroot 	stripfx(prefix string, pointer to string)
842579Sroot 
843579Sroot 	takes a ptr to string and compares it to prefix string.
844579Sroot 	may be called multiple times
845579Sroot */
846579Sroot stripfx(pfx, name)
847579Sroot 	char *pfx;
848579Sroot 	char **name;
849579Sroot {
850579Sroot 	register char *cp = *name;
851579Sroot 
852579Sroot 	while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
853579Sroot 		cp++, pfx++;
854579Sroot 	if (*cp != ':' || *pfx != 0)
855579Sroot 		return;
856579Sroot 	*name = cp;
857579Sroot }
858580Seric # endif
859