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*580Seric static char SccsId[] = "@(#)mail.local.c	1.2	08/04/80";
13*580Seric 
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 */
27*580Seric # 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"
33*580Seric # 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
104579Sroot 		sendmail(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 
399579Sroot sendmail(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";
428579Sroot 		execv(DELIVERMAIL, ap);
429579Sroot 		perror(DELIVERMAIL);
430579Sroot 		exit(EX_UNAVAILABLE);
431579Sroot 	}
432579Sroot # endif DELIVERMAIL
433579Sroot 
434579Sroot 	truename[0] = 0;
435579Sroot 	line[0] = '\0';
436579Sroot 
437579Sroot 	/*
438579Sroot 	 * When we fall out of this, argv[1] should be first name,
439579Sroot 	 * argc should be number of names + 1.
440579Sroot 	 */
441579Sroot 
442579Sroot 	while (argc > 1 && *argv[1] == '-') {
443579Sroot 		cp = *++argv;
444579Sroot 		argc--;
445579Sroot 		switch (cp[1]) {
446579Sroot 		case 'r':
447579Sroot 			if (argc <= 0) {
448579Sroot 				usage();
449579Sroot 				done();
450579Sroot 			}
451579Sroot 			gaver++;
452579Sroot 			strcpy(truename, argv[1]);
453579Sroot 			fgets(line, LSIZE, stdin);
454579Sroot 			if (strcmpn("From", line, 4) == 0)
455579Sroot 				line[0] = '\0';
456579Sroot 			argv++;
457579Sroot 			argc--;
458579Sroot 			break;
459579Sroot 
460579Sroot 		case 'h':
461579Sroot 			if (argc <= 0) {
462579Sroot 				usage();
463579Sroot 				done();
464579Sroot 			}
465579Sroot 			hseqno = atoi(argv[1]);
466579Sroot 			argv++;
467579Sroot 			argc--;
468579Sroot 			break;
469579Sroot 
470579Sroot # ifdef DELIVERMAIL
471579Sroot 		case 'd':
472579Sroot 			break;
473579Sroot # endif DELIVERMAIL
474579Sroot 
475579Sroot 		default:
476579Sroot 			usage();
477579Sroot 			done();
478579Sroot 		}
479579Sroot 	}
480579Sroot 	if (argc <= 1) {
481579Sroot 		usage();
482579Sroot 		done();
483579Sroot 	}
484579Sroot 	if (gaver == 0)
485579Sroot 		strcpy(truename, my_name);
486579Sroot 	/*
487579Sroot 	if (argc > 4 && strcmp(argv[1], "-r") == 0) {
488579Sroot 		strcpy(truename, argv[2]);
489579Sroot 		argc -= 2;
490579Sroot 		argv += 2;
491579Sroot 		fgets(line, LSIZE, stdin);
492579Sroot 		if (strcmpn("From", line, 4) == 0)
493579Sroot 			line[0] = '\0';
494579Sroot 	} else
495579Sroot 		strcpy(truename, my_name);
496579Sroot 	*/
497579Sroot 	time(&iop);
498579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
499579Sroot 	iop = ftell(tmpf);
500579Sroot 	flgf = 1;
501579Sroot 	for (first = 1;; first = 0) {
502579Sroot 		if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
503579Sroot 			break;
504579Sroot 		if (!first && fgets(line, LSIZE, stdin) == NULL)
505579Sroot 			break;
506579Sroot 		if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
507579Sroot 			break;
508579Sroot 		if (isfrom(line))
509579Sroot 			fputs(">", tmpf);
510579Sroot 		fputs(line, tmpf);
511579Sroot 		flgf = 0;
512579Sroot 	}
513579Sroot 	fputs("\n", tmpf);
514579Sroot 	nlet = 1;
515579Sroot 	let[0].adr = 0;
516579Sroot 	let[1].adr = ftell(tmpf);
517579Sroot 	fclose(tmpf);
518579Sroot 	if (flgf)
519579Sroot 		return;
520579Sroot 	tmpf = fopen(lettmp, "r");
521579Sroot 	if (tmpf == NULL) {
522579Sroot 		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
523579Sroot 		return;
524579Sroot 	}
525579Sroot 	while (--argc > 0)
526579Sroot 		if (!send(0, *++argv, truename))
527579Sroot 			error++;
528579Sroot 	if (error) {
529579Sroot 		setuid(getuid());
530579Sroot 		malf = fopen(dead, "w");
531579Sroot 		if (malf == NULL) {
532579Sroot 			fprintf(stdout, "mail: cannot open %s\n", dead);
533579Sroot 			fclose(tmpf);
534579Sroot 			return;
535579Sroot 		}
536579Sroot 		copylet(0, malf, ZAP);
537579Sroot 		fclose(malf);
538579Sroot 		fprintf(stdout, "Mail saved in %s\n", dead);
539579Sroot 	}
540579Sroot 	fclose(tmpf);
541579Sroot }
542579Sroot 
543579Sroot sendrmt(n, name, rcmd)
544579Sroot char *name;
545579Sroot char *rcmd;
546579Sroot {
547579Sroot 	FILE *rmf, *popen();
548579Sroot 	register char *p;
549579Sroot 	char rsys[64], cmd[64];
550579Sroot 	register local, pid;
551579Sroot 	int sts;
552579Sroot 
553579Sroot 	local = 0;
554579Sroot 	if (index(name, '^')) {
555579Sroot 		while (p = index(name, '^'))
556579Sroot 			*p = '!';
557579Sroot 		if (strncmp(name, "researc", 7)) {
558579Sroot 			strcpy(rsys, "research");
559579Sroot 			if (*name != '!')
560579Sroot 				--name;
561579Sroot 			goto skip;
562579Sroot 		}
563579Sroot 	}
564579Sroot 	if (*name=='!')
565579Sroot 		name++;
566579Sroot 	for(p=rsys; *name!='!'; *p++ = *name++)
567579Sroot 		if (*name=='\0') {
568579Sroot 			local++;
569579Sroot 			break;
570579Sroot 		}
571579Sroot 	*p = '\0';
572579Sroot 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
573579Sroot 		fprintf(stdout, "null name\n");
574579Sroot 		return(0);
575579Sroot 	}
576579Sroot skip:
577579Sroot 	if ((pid = fork()) == -1) {
578579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
579579Sroot 		return(0);
580579Sroot 	}
581579Sroot 	if (pid) {
582579Sroot 		while (wait(&sts) != pid) {
583579Sroot 			if (wait(&sts)==-1)
584579Sroot 				return(0);
585579Sroot 		}
586579Sroot 		return(!sts);
587579Sroot 	}
588579Sroot 	setuid(getuid());
589579Sroot 	if (local)
590579Sroot 		sprintf(cmd, "%s %s", rcmd, rsys);
591579Sroot 	else {
592579Sroot 		if (index(name+1, '!'))
593579Sroot 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
594579Sroot 		else
595579Sroot 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
596579Sroot 	}
597579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
598579Sroot 		exit(1);
599579Sroot 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
600579Sroot 	pclose(rmf);
601579Sroot 	exit(0);
602579Sroot }
603579Sroot 
604*580Seric # ifndef DELIVERMAIL
605579Sroot /*
606579Sroot  * Send mail on the Berkeley network.
607579Sroot  * Sorry Bill, sendrmt() is so awful we just gave up.
608579Sroot  */
609579Sroot 
610579Sroot sendberkmail(n, name, fromaddr)
611579Sroot 	char name[];
612579Sroot 	char fromaddr[];
613579Sroot {
614579Sroot 	char cmd[200];
615579Sroot 	register FILE *cmdf;
616579Sroot 
617579Sroot 	sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name);
618579Sroot 	if ((cmdf = popen(cmd, "w")) == NULL) {
619579Sroot 		perror(RMAIL);
620579Sroot 		return(0);
621579Sroot 	}
622579Sroot 	copylet(n, cmdf, ORDINARY);
623579Sroot 	pclose(cmdf);
624579Sroot 	return(9);
625579Sroot }
626*580Seric # endif
627579Sroot 
628579Sroot usage()
629579Sroot {
630579Sroot 
631579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
632579Sroot }
633579Sroot 
634579Sroot send(n, name, fromaddr)
635579Sroot int n;
636579Sroot char *name;
637579Sroot char *fromaddr;
638579Sroot {
639579Sroot 	char file[100];
640579Sroot 	register char *p;
641579Sroot 	register mask;
642579Sroot 	struct passwd *pw, *getpwnam();
643579Sroot 	struct stat statb;
644579Sroot 
645*580Seric # ifndef DELIVERMAIL
646579Sroot 	stripfx(LOCNAM1, &name);
647579Sroot 	stripfx(LOCNAM2, &name);
648579Sroot 	stripfx(LOCNAM3, &name);
649579Sroot 	stripfx(LOCNAM4, &name);
650579Sroot 	if(*name == ':')name++;		/* skip colon in to-name */
651*580Seric 	for(p=name; *p!=':' && *p!='!' && *p!='^' &&*p!='\0'; p++);
652579Sroot 	/* if(*p == ':') return(sendrmt(n, name, RMAIL)); */
653579Sroot 	if (*p == ':')
654579Sroot 		return(sendberkmail(n, name, fromaddr));
655*580Seric 	else if (*p=='\0' && strcmp(name, "msgs") == 0)
656*580Seric 		return(sendrmt(n, "-s", "/usr/ucb/msgs"));
657*580Seric # endif
658579Sroot 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
659579Sroot 		;
660579Sroot 	if (*p == '!'|| *p=='^')
661579Sroot 		return(sendrmt(n, name, 0));
662579Sroot 	if ((pw = getpwnam(name)) == NULL) {
663579Sroot 		fprintf(stdout, "mail: can't send to %s\n", name);
664579Sroot 		return(0);
665579Sroot 	}
666579Sroot 	cat(file, maildir, name);
667579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
668579Sroot 		strcat(file, "/");
669579Sroot 		strcat(file, name);
670579Sroot 	}
671579Sroot 	mask = umask(MAILMODE);
672579Sroot 	malf = fopen(file, "a");
673579Sroot 	umask(mask);
674579Sroot 	if (malf == NULL) {
675579Sroot 		fprintf(stdout, "mail: cannot append to %s\n", file);
676579Sroot 		return(0);
677579Sroot 	}
678579Sroot 	lock(file);
679579Sroot 	chown(file, pw->pw_uid, pw->pw_gid);
680579Sroot 	copylet(n, malf, ORDINARY);
681579Sroot 	fclose(malf);
682579Sroot 	unlock();
683579Sroot 	return(1);
684579Sroot }
685579Sroot 
686579Sroot delete(i)
687579Sroot {
688579Sroot 	setsig(i, delete);
689579Sroot 	fprintf(stderr, "\n");
690579Sroot 	if(delflg)
691579Sroot 		longjmp(sjbuf, 1);
692579Sroot 	done();
693579Sroot }
694579Sroot 
695579Sroot /*
696579Sroot  * Lock the specified mail file by setting the file mailfile.lock.
697579Sroot  * We must, of course, be careful to unlink the lock file by a call
698579Sroot  * to unlock before we stop.  The algorithm used here is to see if
699579Sroot  * the lock exists, and if it does, to check its modify time.  If it
700579Sroot  * is older than 30 seconds, we assume error and set our own file.
701579Sroot  * Otherwise, we wait for 5 seconds and try again.
702579Sroot  */
703579Sroot 
704579Sroot char	*maillock	= ".lock";		/* Lock suffix for mailname */
705579Sroot char	*lockname	= "/usr/spool/mail/tmXXXXXX";
706579Sroot char	locktmp[30];				/* Usable lock temporary */
707579Sroot char	curlock[50];				/* Last used name of lock */
708579Sroot int	locked;					/* To note that we locked it */
709579Sroot 
710579Sroot lock(file)
711579Sroot char *file;
712579Sroot {
713579Sroot 	register int f;
714579Sroot 	struct stat sbuf;
715579Sroot 	long curtime;
716579Sroot 	int statfailed;
717579Sroot 
718579Sroot 	if (locked || flgf)
719579Sroot 		return(0);
720579Sroot 	strcpy(curlock, file);
721579Sroot 	strcat(curlock, maillock);
722579Sroot 	strcpy(locktmp, lockname);
723579Sroot 	mktemp(locktmp);
724579Sroot 	unlink(locktmp);
725579Sroot 	statfailed = 0;
726579Sroot 	for (;;) {
727579Sroot 		f = lock1(locktmp, curlock);
728579Sroot 		if (f == 0) {
729579Sroot 			locked = 1;
730579Sroot 			return(0);
731579Sroot 		}
732579Sroot 		if (stat(curlock, &sbuf) < 0) {
733579Sroot 			if (statfailed++ > 5)
734579Sroot 				return(-1);
735579Sroot 			sleep(5);
736579Sroot 			continue;
737579Sroot 		}
738579Sroot 		statfailed = 0;
739579Sroot 		time(&curtime);
740579Sroot 		if (curtime < sbuf.st_ctime + 30) {
741579Sroot 			sleep(5);
742579Sroot 			continue;
743579Sroot 		}
744579Sroot 		unlink(curlock);
745579Sroot 	}
746579Sroot }
747579Sroot 
748579Sroot /*
749579Sroot  * Remove the mail lock, and note that we no longer
750579Sroot  * have it locked.
751579Sroot  */
752579Sroot 
753579Sroot unlock()
754579Sroot {
755579Sroot 
756579Sroot 	unlink(curlock);
757579Sroot 	locked = 0;
758579Sroot }
759579Sroot 
760579Sroot /*
761579Sroot  * Attempt to set the lock by creating the temporary file,
762579Sroot  * then doing a link/unlink.  If it fails, return -1 else 0
763579Sroot  */
764579Sroot 
765579Sroot lock1(tempfile, name)
766579Sroot 	char tempfile[], name[];
767579Sroot {
768579Sroot 	register int fd;
769579Sroot 
770579Sroot 	fd = creat(tempfile, 0);
771579Sroot 	if (fd < 0)
772579Sroot 		return(-1);
773579Sroot 	close(fd);
774579Sroot 	if (link(tempfile, name) < 0) {
775579Sroot 		unlink(tempfile);
776579Sroot 		return(-1);
777579Sroot 	}
778579Sroot 	unlink(tempfile);
779579Sroot 	return(0);
780579Sroot }
781579Sroot 
782579Sroot done()
783579Sroot {
784579Sroot 	if(locked)
785579Sroot 		unlock();
786579Sroot 	unlink(lettmp);
787579Sroot 	unlink(locktmp);
788579Sroot 	exit(error);
789579Sroot }
790579Sroot 
791579Sroot cat(to, from1, from2)
792579Sroot char *to, *from1, *from2;
793579Sroot {
794579Sroot 	int i, j;
795579Sroot 
796579Sroot 	j = 0;
797579Sroot 	for (i=0; from1[i]; i++)
798579Sroot 		to[j++] = from1[i];
799579Sroot 	for (i=0; from2[i]; i++)
800579Sroot 		to[j++] = from2[i];
801579Sroot 	to[j] = 0;
802579Sroot }
803579Sroot 
804579Sroot char *getarg(s, p)	/* copy p... into s, update p */
805579Sroot register char *s, *p;
806579Sroot {
807579Sroot 	while (*p == ' ' || *p == '\t')
808579Sroot 		p++;
809579Sroot 	if (*p == '\n' || *p == '\0')
810579Sroot 		return(NULL);
811579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
812579Sroot 		*s++ = *p++;
813579Sroot 	*s = '\0';
814579Sroot 	return(p);
815579Sroot }
816*580Seric # ifndef DELIVERMAIL
817579Sroot /*
818579Sroot 	stripfx(prefix string, pointer to string)
819579Sroot 
820579Sroot 	takes a ptr to string and compares it to prefix string.
821579Sroot 	may be called multiple times
822579Sroot */
823579Sroot stripfx(pfx, name)
824579Sroot 	char *pfx;
825579Sroot 	char **name;
826579Sroot {
827579Sroot 	register char *cp = *name;
828579Sroot 
829579Sroot 	while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
830579Sroot 		cp++, pfx++;
831579Sroot 	if (*cp != ':' || *pfx != 0)
832579Sroot 		return;
833579Sroot 	*name = cp;
834579Sroot }
835*580Seric # endif
836