114465Ssam #ifndef lint
2*14912Sralph static char sccsid[] = "@(#)mail.local.c	4.17 (Berkeley) 09/07/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();
84*14912Sralph 	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 			}
449579Sroot 			gaver++;
450579Sroot 			strcpy(truename, argv[1]);
451579Sroot 			fgets(line, LSIZE, stdin);
452579Sroot 			if (strcmpn("From", line, 4) == 0)
453579Sroot 				line[0] = '\0';
454579Sroot 			argv++;
455579Sroot 			argc--;
456579Sroot 			break;
457579Sroot 
458579Sroot 		case 'h':
459579Sroot 			if (argc <= 0) {
460579Sroot 				usage();
461579Sroot 				done();
462579Sroot 			}
463579Sroot 			hseqno = atoi(argv[1]);
464579Sroot 			argv++;
465579Sroot 			argc--;
466579Sroot 			break;
467579Sroot 
468579Sroot 		case 'd':
469579Sroot 			break;
470579Sroot 
471579Sroot 		default:
472579Sroot 			usage();
473579Sroot 			done();
474579Sroot 		}
475579Sroot 	}
476579Sroot 	if (argc <= 1) {
477579Sroot 		usage();
478579Sroot 		done();
479579Sroot 	}
480579Sroot 	if (gaver == 0)
481579Sroot 		strcpy(truename, my_name);
482579Sroot 	/*
483579Sroot 	if (argc > 4 && strcmp(argv[1], "-r") == 0) {
484579Sroot 		strcpy(truename, argv[2]);
485579Sroot 		argc -= 2;
486579Sroot 		argv += 2;
487579Sroot 		fgets(line, LSIZE, stdin);
488579Sroot 		if (strcmpn("From", line, 4) == 0)
489579Sroot 			line[0] = '\0';
490579Sroot 	} else
491579Sroot 		strcpy(truename, my_name);
492579Sroot 	*/
493579Sroot 	time(&iop);
494579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
495579Sroot 	iop = ftell(tmpf);
496579Sroot 	flgf = 1;
497579Sroot 	for (first = 1;; first = 0) {
498579Sroot 		if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
499579Sroot 			break;
500579Sroot 		if (!first && fgets(line, LSIZE, stdin) == NULL)
501579Sroot 			break;
502579Sroot 		if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
503579Sroot 			break;
504579Sroot 		if (isfrom(line))
505579Sroot 			fputs(">", tmpf);
506579Sroot 		fputs(line, tmpf);
507579Sroot 		flgf = 0;
508579Sroot 	}
509579Sroot 	fputs("\n", tmpf);
510579Sroot 	nlet = 1;
511579Sroot 	let[0].adr = 0;
512579Sroot 	let[1].adr = ftell(tmpf);
513579Sroot 	fclose(tmpf);
514579Sroot 	if (flgf)
515579Sroot 		return;
516579Sroot 	tmpf = fopen(lettmp, "r");
517579Sroot 	if (tmpf == NULL) {
518579Sroot 		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
519579Sroot 		return;
520579Sroot 	}
5216015Swnj 	while (--argc > 0) {
5226015Swnj 		if (!sendmail(0, *++argv, truename))
523579Sroot 			error++;
5246015Swnj 	}
52510644Seric 	if (error && safefile(dead)) {
526579Sroot 		setuid(getuid());
527579Sroot 		malf = fopen(dead, "w");
528579Sroot 		if (malf == NULL) {
529579Sroot 			fprintf(stdout, "mail: cannot open %s\n", dead);
530579Sroot 			fclose(tmpf);
531579Sroot 			return;
532579Sroot 		}
533579Sroot 		copylet(0, malf, ZAP);
534579Sroot 		fclose(malf);
535579Sroot 		fprintf(stdout, "Mail saved in %s\n", dead);
536579Sroot 	}
537579Sroot 	fclose(tmpf);
538579Sroot }
539579Sroot 
540579Sroot sendrmt(n, name, rcmd)
541579Sroot char *name;
542579Sroot char *rcmd;
543579Sroot {
544579Sroot 	FILE *rmf, *popen();
545579Sroot 	register char *p;
546579Sroot 	char rsys[64], cmd[64];
547579Sroot 	register local, pid;
548579Sroot 	int sts;
549579Sroot 
550579Sroot 	local = 0;
551579Sroot 	if (index(name, '^')) {
552579Sroot 		while (p = index(name, '^'))
553579Sroot 			*p = '!';
554579Sroot 		if (strncmp(name, "researc", 7)) {
555579Sroot 			strcpy(rsys, "research");
556579Sroot 			if (*name != '!')
557579Sroot 				--name;
558579Sroot 			goto skip;
559579Sroot 		}
560579Sroot 	}
561579Sroot 	if (*name=='!')
562579Sroot 		name++;
563579Sroot 	for(p=rsys; *name!='!'; *p++ = *name++)
564579Sroot 		if (*name=='\0') {
565579Sroot 			local++;
566579Sroot 			break;
567579Sroot 		}
568579Sroot 	*p = '\0';
569579Sroot 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
570579Sroot 		fprintf(stdout, "null name\n");
571579Sroot 		return(0);
572579Sroot 	}
573579Sroot skip:
574579Sroot 	if ((pid = fork()) == -1) {
575579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
576579Sroot 		return(0);
577579Sroot 	}
578579Sroot 	if (pid) {
579579Sroot 		while (wait(&sts) != pid) {
580579Sroot 			if (wait(&sts)==-1)
581579Sroot 				return(0);
582579Sroot 		}
583579Sroot 		return(!sts);
584579Sroot 	}
585579Sroot 	setuid(getuid());
586579Sroot 	if (local)
587579Sroot 		sprintf(cmd, "%s %s", rcmd, rsys);
588579Sroot 	else {
589579Sroot 		if (index(name+1, '!'))
590579Sroot 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
591579Sroot 		else
592579Sroot 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
593579Sroot 	}
594579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
595579Sroot 		exit(1);
596579Sroot 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
59710783Seric 	exit(pclose(rmf) != 0);
598579Sroot }
599579Sroot 
600579Sroot usage()
601579Sroot {
602579Sroot 
603579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
604579Sroot }
605579Sroot 
6066015Swnj #include <sys/socket.h>
6079226Ssam #include <netinet/in.h>
60810227Ssam #include <netdb.h>
60910227Ssam struct sockaddr_in biffaddr;
6106015Swnj 
6116015Swnj sendmail(n, name, fromaddr)
612579Sroot int n;
613579Sroot char *name;
614579Sroot char *fromaddr;
615579Sroot {
616579Sroot 	char file[100];
617579Sroot 	register char *p;
618579Sroot 	register mask;
619579Sroot 	struct passwd *pw, *getpwnam();
620579Sroot 	struct stat statb;
6213666Swnj 	char buf[128];
6223666Swnj 	int f;
62310227Ssam 	struct hostent *hp = NULL;
62410227Ssam 	struct servent *sp = NULL;
625579Sroot 
626579Sroot 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
627579Sroot 		;
628579Sroot 	if (*p == '!'|| *p=='^')
629579Sroot 		return(sendrmt(n, name, 0));
630579Sroot 	if ((pw = getpwnam(name)) == NULL) {
631579Sroot 		fprintf(stdout, "mail: can't send to %s\n", name);
632579Sroot 		return(0);
633579Sroot 	}
634579Sroot 	cat(file, maildir, name);
635579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
636579Sroot 		strcat(file, "/");
637579Sroot 		strcat(file, name);
638579Sroot 	}
639579Sroot 	mask = umask(MAILMODE);
64010644Seric 	if (!safefile(file))
6414458Sroot 		return(0);
64211893Seric 	lock(file);
643579Sroot 	malf = fopen(file, "a");
644579Sroot 	umask(mask);
645579Sroot 	if (malf == NULL) {
64611893Seric 		unlock();
647579Sroot 		fprintf(stdout, "mail: cannot append to %s\n", file);
648579Sroot 		return(0);
649579Sroot 	}
6506015Swnj 	chown(file, pw->pw_uid, pw->pw_gid);
6513666Swnj 	{
65210227Ssam 		hp = gethostbyname("localhost");
65310227Ssam 		sp = getservbyname("biff", "udp");
65410227Ssam 		if (hp && sp) {
65510227Ssam 			f = socket(AF_INET, SOCK_DGRAM, 0, 0);
65610227Ssam 			sprintf(buf, "%s@%d\n", name, ftell(malf));
65710227Ssam 		}
6583666Swnj 	}
659579Sroot 	copylet(n, malf, ORDINARY);
6606015Swnj 	fclose(malf);
66110227Ssam 	if (hp && sp) {
66210227Ssam 		biffaddr.sin_family = hp->h_addrtype;
66310227Ssam 		bcopy(hp->h_addr, &biffaddr.sin_addr, hp->h_length);
66410227Ssam 		biffaddr.sin_port = sp->s_port;
6659226Ssam 		sendto(f, buf, strlen(buf)+1, 0, &biffaddr, sizeof (biffaddr));
6663666Swnj 		close(f);
6673666Swnj 	}
668579Sroot 	unlock();
669579Sroot 	return(1);
670579Sroot }
671579Sroot 
672579Sroot delete(i)
673579Sroot {
674579Sroot 	setsig(i, delete);
675579Sroot 	fprintf(stderr, "\n");
676579Sroot 	if(delflg)
677579Sroot 		longjmp(sjbuf, 1);
678579Sroot 	done();
679579Sroot }
680579Sroot 
681579Sroot /*
682579Sroot  * Lock the specified mail file by setting the file mailfile.lock.
683579Sroot  * We must, of course, be careful to unlink the lock file by a call
684579Sroot  * to unlock before we stop.  The algorithm used here is to see if
685579Sroot  * the lock exists, and if it does, to check its modify time.  If it
686579Sroot  * is older than 30 seconds, we assume error and set our own file.
687579Sroot  * Otherwise, we wait for 5 seconds and try again.
688579Sroot  */
689579Sroot 
690579Sroot char	*maillock	= ".lock";		/* Lock suffix for mailname */
691579Sroot char	*lockname	= "/usr/spool/mail/tmXXXXXX";
692579Sroot char	locktmp[30];				/* Usable lock temporary */
693579Sroot char	curlock[50];				/* Last used name of lock */
694579Sroot int	locked;					/* To note that we locked it */
695579Sroot 
696579Sroot lock(file)
697579Sroot char *file;
698579Sroot {
699579Sroot 	register int f;
700579Sroot 	struct stat sbuf;
701579Sroot 	long curtime;
702579Sroot 	int statfailed;
703579Sroot 
704579Sroot 	if (locked || flgf)
705579Sroot 		return(0);
706579Sroot 	strcpy(curlock, file);
707579Sroot 	strcat(curlock, maillock);
708579Sroot 	strcpy(locktmp, lockname);
709579Sroot 	mktemp(locktmp);
710579Sroot 	unlink(locktmp);
711579Sroot 	statfailed = 0;
712579Sroot 	for (;;) {
713579Sroot 		f = lock1(locktmp, curlock);
714579Sroot 		if (f == 0) {
715579Sroot 			locked = 1;
716579Sroot 			return(0);
717579Sroot 		}
718579Sroot 		if (stat(curlock, &sbuf) < 0) {
719579Sroot 			if (statfailed++ > 5)
720579Sroot 				return(-1);
721579Sroot 			sleep(5);
722579Sroot 			continue;
723579Sroot 		}
724579Sroot 		statfailed = 0;
725579Sroot 		time(&curtime);
726579Sroot 		if (curtime < sbuf.st_ctime + 30) {
727579Sroot 			sleep(5);
728579Sroot 			continue;
729579Sroot 		}
730579Sroot 		unlink(curlock);
731579Sroot 	}
732579Sroot }
733579Sroot 
734579Sroot /*
735579Sroot  * Remove the mail lock, and note that we no longer
736579Sroot  * have it locked.
737579Sroot  */
738579Sroot 
739579Sroot unlock()
740579Sroot {
741579Sroot 
742579Sroot 	unlink(curlock);
743579Sroot 	locked = 0;
744579Sroot }
745579Sroot 
746579Sroot /*
747579Sroot  * Attempt to set the lock by creating the temporary file,
748579Sroot  * then doing a link/unlink.  If it fails, return -1 else 0
749579Sroot  */
750579Sroot 
751579Sroot lock1(tempfile, name)
752579Sroot 	char tempfile[], name[];
753579Sroot {
754579Sroot 	register int fd;
755579Sroot 
756579Sroot 	fd = creat(tempfile, 0);
757579Sroot 	if (fd < 0)
758579Sroot 		return(-1);
759579Sroot 	close(fd);
760579Sroot 	if (link(tempfile, name) < 0) {
761579Sroot 		unlink(tempfile);
762579Sroot 		return(-1);
763579Sroot 	}
764579Sroot 	unlink(tempfile);
765579Sroot 	return(0);
766579Sroot }
767579Sroot 
768579Sroot done()
769579Sroot {
770579Sroot 	if(locked)
771579Sroot 		unlock();
772579Sroot 	unlink(lettmp);
773579Sroot 	unlink(locktmp);
774579Sroot 	exit(error);
775579Sroot }
776579Sroot 
777579Sroot cat(to, from1, from2)
778579Sroot char *to, *from1, *from2;
779579Sroot {
780579Sroot 	int i, j;
781579Sroot 
782579Sroot 	j = 0;
783579Sroot 	for (i=0; from1[i]; i++)
784579Sroot 		to[j++] = from1[i];
785579Sroot 	for (i=0; from2[i]; i++)
786579Sroot 		to[j++] = from2[i];
787579Sroot 	to[j] = 0;
788579Sroot }
789579Sroot 
790579Sroot char *getarg(s, p)	/* copy p... into s, update p */
791579Sroot register char *s, *p;
792579Sroot {
793579Sroot 	while (*p == ' ' || *p == '\t')
794579Sroot 		p++;
795579Sroot 	if (*p == '\n' || *p == '\0')
796579Sroot 		return(NULL);
797579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
798579Sroot 		*s++ = *p++;
799579Sroot 	*s = '\0';
800579Sroot 	return(p);
801579Sroot }
80210644Seric 
80310644Seric safefile(f)
80410644Seric 	char *f;
80510644Seric {
80610644Seric 	struct stat statb;
80710644Seric 
80810644Seric 	if (lstat(f, &statb) < 0)
80910644Seric 		return (1);
81010644Seric 	if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
81110644Seric 		fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f);
81210644Seric 		return (0);
81310644Seric 	}
81410644Seric 	return (1);
81510644Seric }
816