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 <sysexits.h>
10579Sroot 
11*11893Seric static char SccsId[] = "@(#)mail.local.c	4.14	04/10/83";
12580Seric 
139978Seric #define SENDMAIL	"/usr/lib/sendmail"
14579Sroot 
15579Sroot 
16579Sroot /*copylet flags */
17579Sroot 	/*remote mail, add rmtmsg */
18579Sroot #define REMOTE	1
19579Sroot 	/* zap header and trailing empty line */
20579Sroot #define ZAP	3
21579Sroot #define ORDINARY 2
22579Sroot #define	FORWARD	4
23579Sroot #define	LSIZE	256
24579Sroot #define	MAXLET	300	/* maximum number of letters */
25579Sroot #define	MAILMODE (~0644)		/* mode of created mail */
26579Sroot 
27579Sroot char	line[LSIZE];
28579Sroot char	resp[LSIZE];
29579Sroot struct let {
30579Sroot 	long	adr;
31579Sroot 	char	change;
32579Sroot } let[MAXLET];
33579Sroot int	nlet	= 0;
34579Sroot char	lfil[50];
35579Sroot long	iop, time();
36579Sroot char	*getenv();
37579Sroot char	*index();
38579Sroot char	lettmp[] = "/tmp/maXXXXX";
39579Sroot char	maildir[] = "/usr/spool/mail/";
40579Sroot char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
41579Sroot char	dead[] = "dead.letter";
42579Sroot char	*netname = "vax";
43579Sroot char	forwmsg[] = " forwarded\n";
44579Sroot FILE	*tmpf;
45579Sroot FILE	*malf;
46579Sroot char	*my_name;
47579Sroot char	*getlogin();
48579Sroot struct	passwd	*getpwuid();
49579Sroot int	error;
50579Sroot int	changed;
51579Sroot int	forward;
52579Sroot char	from[] = "From ";
53579Sroot long	ftell();
54579Sroot int	delete();
55579Sroot char	*ctime();
56579Sroot int	flgf;
57579Sroot int	flgp;
58579Sroot int	delflg = 1;
59579Sroot int	hseqno;
60579Sroot jmp_buf	sjbuf;
61579Sroot int	rmail;
62579Sroot 
63579Sroot main(argc, argv)
64579Sroot char **argv;
65579Sroot {
66579Sroot 	register i;
67579Sroot 	char sobuf[BUFSIZ];
68579Sroot 
69579Sroot 	setbuf(stdout, sobuf);
70579Sroot 	mktemp(lettmp);
71579Sroot 	unlink(lettmp);
72579Sroot 	my_name = getlogin();
73579Sroot 	if (my_name == NULL || strlen(my_name) == 0) {
74579Sroot 		struct passwd *pwent;
75579Sroot 		pwent = getpwuid(getuid());
76579Sroot 		if (pwent==NULL)
77579Sroot 			my_name = "???";
78579Sroot 		else
79579Sroot 			my_name = pwent->pw_name;
80579Sroot 	}
81579Sroot 	if(setjmp(sjbuf)) done();
82579Sroot 	for (i=0; i<20; i++)
83579Sroot 		setsig(i, delete);
84579Sroot 	tmpf = fopen(lettmp, "w");
85579Sroot 	if (tmpf == NULL) {
86579Sroot 		fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
87579Sroot 		done();
88579Sroot 	}
89579Sroot 	if (argv[0][0] == 'r')
90579Sroot 		rmail++;
91579Sroot 	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
92579Sroot 	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
93579Sroot 		printmail(argc, argv);
94579Sroot 	else
956015Swnj 		bulkmail(argc, argv);
96579Sroot 	done();
97579Sroot }
98579Sroot 
99579Sroot setsig(i, f)
100579Sroot int i;
101579Sroot int (*f)();
102579Sroot {
103579Sroot 	if(signal(i, SIG_IGN)!=SIG_IGN)
104579Sroot 		signal(i, f);
105579Sroot }
106579Sroot 
107579Sroot any(c, str)
108579Sroot 	register int c;
109579Sroot 	register char *str;
110579Sroot {
111579Sroot 
112579Sroot 	while (*str)
113579Sroot 		if (c == *str++)
114579Sroot 			return(1);
115579Sroot 	return(0);
116579Sroot }
117579Sroot 
118579Sroot printmail(argc, argv)
119579Sroot char **argv;
120579Sroot {
121579Sroot 	int flg, i, j, print;
122579Sroot 	char *p, *getarg();
123579Sroot 	struct stat statb;
124579Sroot 
125579Sroot 	setuid(getuid());
126579Sroot 	cat(mailfile, maildir, my_name);
127579Sroot 	if (stat(mailfile, &statb) >= 0
128579Sroot 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
129579Sroot 		strcat(mailfile, "/");
130579Sroot 		strcat(mailfile, my_name);
131579Sroot 	}
132579Sroot 	for (; argc>1; argv++, argc--) {
133579Sroot 		if (argv[1][0]=='-') {
134579Sroot 			if (argv[1][1]=='q')
135579Sroot 				delflg = 0;
136579Sroot 			else if (argv[1][1]=='p') {
137579Sroot 				flgp++;
138579Sroot 				delflg = 0;
139579Sroot 			} else if (argv[1][1]=='f') {
140579Sroot 				if (argc>=3) {
141579Sroot 					strcpy(mailfile, argv[2]);
142579Sroot 					argv++;
143579Sroot 					argc--;
144579Sroot 				}
145579Sroot 			} else if (argv[1][1]=='r') {
146579Sroot 				forward = 1;
147579Sroot 			} else if (argv[1][1]=='h') {
148579Sroot 				forward = 1;
149579Sroot 			} else {
150579Sroot 				fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
151579Sroot 				done();
152579Sroot 			}
153579Sroot 		} else
154579Sroot 			break;
155579Sroot 	}
156579Sroot 	malf = fopen(mailfile, "r");
157579Sroot 	if (malf == NULL) {
158579Sroot 		fprintf(stdout, "No mail.\n");
159579Sroot 		return;
160579Sroot 	}
161579Sroot 	lock(mailfile);
162579Sroot 	copymt(malf, tmpf);
163579Sroot 	fclose(malf);
164579Sroot 	fclose(tmpf);
165579Sroot 	unlock();
166579Sroot 	tmpf = fopen(lettmp, "r");
167579Sroot 
168579Sroot 	changed = 0;
169579Sroot 	print = 1;
170579Sroot 	for (i = 0; i < nlet; ) {
171579Sroot 		j = forward ? i : nlet - i - 1;
172579Sroot 		if(setjmp(sjbuf)) {
173579Sroot 			print=0;
174579Sroot 		} else {
175579Sroot 			if (print)
176579Sroot 				copylet(j, stdout, ORDINARY);
177579Sroot 			print = 1;
178579Sroot 		}
179579Sroot 		if (flgp) {
180579Sroot 			i++;
181579Sroot 			continue;
182579Sroot 		}
183579Sroot 		setjmp(sjbuf);
184579Sroot 		fprintf(stdout, "? ");
185579Sroot 		fflush(stdout);
186579Sroot 		if (fgets(resp, LSIZE, stdin) == NULL)
187579Sroot 			break;
188579Sroot 		switch (resp[0]) {
189579Sroot 
190579Sroot 		default:
191579Sroot 			fprintf(stderr, "usage\n");
192579Sroot 		case '?':
193579Sroot 			print = 0;
194579Sroot 			fprintf(stderr, "q\tquit\n");
195579Sroot 			fprintf(stderr, "x\texit without changing mail\n");
196579Sroot 			fprintf(stderr, "p\tprint\n");
197579Sroot 			fprintf(stderr, "s[file]\tsave (default mbox)\n");
198579Sroot 			fprintf(stderr, "w[file]\tsame without header\n");
199579Sroot 			fprintf(stderr, "-\tprint previous\n");
200579Sroot 			fprintf(stderr, "d\tdelete\n");
201579Sroot 			fprintf(stderr, "+\tnext (no delete)\n");
202579Sroot 			fprintf(stderr, "m user\tmail to user\n");
203579Sroot 			fprintf(stderr, "! cmd\texecute cmd\n");
204579Sroot 			break;
205579Sroot 
206579Sroot 		case '+':
207579Sroot 		case 'n':
208579Sroot 		case '\n':
209579Sroot 			i++;
210579Sroot 			break;
211579Sroot 		case 'x':
212579Sroot 			changed = 0;
213579Sroot 		case 'q':
214579Sroot 			goto donep;
215579Sroot 		case 'p':
216579Sroot 			break;
217579Sroot 		case '^':
218579Sroot 		case '-':
219579Sroot 			if (--i < 0)
220579Sroot 				i = 0;
221579Sroot 			break;
222579Sroot 		case 'y':
223579Sroot 		case 'w':
224579Sroot 		case 's':
225579Sroot 			flg = 0;
226579Sroot 			if (resp[1] != '\n' && resp[1] != ' ') {
227579Sroot 				printf("illegal\n");
228579Sroot 				flg++;
229579Sroot 				print = 0;
230579Sroot 				continue;
231579Sroot 			}
232579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
233579Sroot 				p = getenv("HOME");
234579Sroot 				if(p != 0)
235579Sroot 					cat(resp+1, p, "/mbox");
236579Sroot 				else
237579Sroot 					cat(resp+1, "", "mbox");
238579Sroot 			}
239579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
240579Sroot 				malf = fopen(lfil, "a");
241579Sroot 				if (malf == NULL) {
242579Sroot 					fprintf(stdout, "mail: cannot append to %s\n", lfil);
243579Sroot 					flg++;
244579Sroot 					continue;
245579Sroot 				}
246579Sroot 				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
247579Sroot 				fclose(malf);
248579Sroot 			}
249579Sroot 			if (flg)
250579Sroot 				print = 0;
251579Sroot 			else {
252579Sroot 				let[j].change = 'd';
253579Sroot 				changed++;
254579Sroot 				i++;
255579Sroot 			}
256579Sroot 			break;
257579Sroot 		case 'm':
258579Sroot 			flg = 0;
259579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
260579Sroot 				i++;
261579Sroot 				continue;
262579Sroot 			}
263579Sroot 			if (resp[1] != ' ') {
264579Sroot 				printf("invalid command\n");
265579Sroot 				flg++;
266579Sroot 				print = 0;
267579Sroot 				continue;
268579Sroot 			}
269579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
270579Sroot 				if (!sendrmt(j, lfil, "/bin/mail"))	/* couldn't send it */
271579Sroot 					flg++;
272579Sroot 			if (flg)
273579Sroot 				print = 0;
274579Sroot 			else {
275579Sroot 				let[j].change = 'd';
276579Sroot 				changed++;
277579Sroot 				i++;
278579Sroot 			}
279579Sroot 			break;
280579Sroot 		case '!':
281579Sroot 			system(resp+1);
282579Sroot 			printf("!\n");
283579Sroot 			print = 0;
284579Sroot 			break;
285579Sroot 		case 'd':
286579Sroot 			let[j].change = 'd';
287579Sroot 			changed++;
288579Sroot 			i++;
289579Sroot 			if (resp[1] == 'q')
290579Sroot 				goto donep;
291579Sroot 			break;
292579Sroot 		}
293579Sroot 	}
294579Sroot    donep:
295579Sroot 	if (changed)
296579Sroot 		copyback();
297579Sroot }
298579Sroot 
299579Sroot copyback()	/* copy temp or whatever back to /usr/spool/mail */
300579Sroot {
301579Sroot 	register i, n, c;
302579Sroot 	int new = 0;
303579Sroot 	struct stat stbuf;
304579Sroot 
305579Sroot 	signal(SIGINT, SIG_IGN);
306579Sroot 	signal(SIGHUP, SIG_IGN);
307579Sroot 	signal(SIGQUIT, SIG_IGN);
308579Sroot 	lock(mailfile);
309579Sroot 	stat(mailfile, &stbuf);
310579Sroot 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
311579Sroot 		malf = fopen(mailfile, "r");
312579Sroot 		if (malf == NULL) {
313579Sroot 			fprintf(stdout, "mail: can't re-read %s\n", mailfile);
314579Sroot 			done();
315579Sroot 		}
316579Sroot 		fseek(malf, let[nlet].adr, 0);
317579Sroot 		fclose(tmpf);
318579Sroot 		tmpf = fopen(lettmp, "a");
319579Sroot 		fseek(tmpf, let[nlet].adr, 0);
320579Sroot 		while ((c = fgetc(malf)) != EOF)
321579Sroot 			fputc(c, tmpf);
322579Sroot 		fclose(malf);
323579Sroot 		fclose(tmpf);
324579Sroot 		tmpf = fopen(lettmp, "r");
325579Sroot 		let[++nlet].adr = stbuf.st_size;
326579Sroot 		new = 1;
327579Sroot 	}
328579Sroot 	malf = fopen(mailfile, "w");
329579Sroot 	if (malf == NULL) {
330579Sroot 		fprintf(stderr, "mail: can't rewrite %s\n", lfil);
331579Sroot 		done();
332579Sroot 	}
333579Sroot 	n = 0;
334579Sroot 	for (i = 0; i < nlet; i++)
335579Sroot 		if (let[i].change != 'd') {
336579Sroot 			copylet(i, malf, ORDINARY);
337579Sroot 			n++;
338579Sroot 		}
339579Sroot 	fclose(malf);
340579Sroot 	if (new)
341579Sroot 		fprintf(stdout, "new mail arrived\n");
342579Sroot 	unlock();
343579Sroot }
344579Sroot 
345579Sroot copymt(f1, f2)	/* copy mail (f1) to temp (f2) */
346579Sroot FILE *f1, *f2;
347579Sroot {
348579Sroot 	long nextadr;
349579Sroot 
350579Sroot 	nlet = nextadr = 0;
351579Sroot 	let[0].adr = 0;
352579Sroot 	while (fgets(line, LSIZE, f1) != NULL) {
353579Sroot 		if (isfrom(line))
354579Sroot 			let[nlet++].adr = nextadr;
355579Sroot 		nextadr += strlen(line);
356579Sroot 		fputs(line, f2);
357579Sroot 	}
358579Sroot 	let[nlet].adr = nextadr;	/* last plus 1 */
359579Sroot }
360579Sroot 
361*11893Seric copylet(n, f, type)
362*11893Seric 	FILE *f;
363*11893Seric {
364*11893Seric 	int ch;
365*11893Seric 	long k;
366*11893Seric 
367579Sroot 	fseek(tmpf, let[n].adr, 0);
368579Sroot 	k = let[n+1].adr - let[n].adr;
369579Sroot 	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')
370579Sroot 		if(type!=ZAP) fputc(ch,f);
3716199Sroot 	if(type==REMOTE) {
3726199Sroot 		char hostname[32];
3736199Sroot 		gethostname(hostname, sizeof (hostname));
3746199Sroot 		fprintf(f, " remote from %s\n", hostname);
3756199Sroot 	} else if (type==FORWARD)
376579Sroot 		fprintf(f, forwmsg);
377579Sroot 	else if(type==ORDINARY)
378579Sroot 		fputc(ch,f);
379579Sroot 	while(k-->1)
380579Sroot 		fputc(ch=fgetc(tmpf), f);
381579Sroot 	if(type!=ZAP || ch!= '\n')
382579Sroot 		fputc(fgetc(tmpf), f);
383579Sroot }
384579Sroot 
385579Sroot isfrom(lp)
386579Sroot register char *lp;
387579Sroot {
388579Sroot 	register char *p;
389579Sroot 
390579Sroot 	for (p = from; *p; )
391579Sroot 		if (*lp++ != *p++)
392579Sroot 			return(0);
393579Sroot 	return(1);
394579Sroot }
395579Sroot 
3966015Swnj bulkmail(argc, argv)
397579Sroot char **argv;
398579Sroot {
399579Sroot 	char truename[100];
400579Sroot 	int first;
401579Sroot 	register char *cp;
402579Sroot 	int gaver = 0;
403579Sroot 	char *newargv[1000];
404579Sroot 	register char **ap;
405579Sroot 	register char **vp;
406579Sroot 	int dflag;
407579Sroot 
408579Sroot 	dflag = 0;
409579Sroot 	if (argc < 1)
410579Sroot 		fprintf(stderr, "puke\n");
411579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
412579Sroot 	{
413579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
414579Sroot 			dflag++;
415579Sroot 	}
416579Sroot 	if (!dflag)
417579Sroot 	{
4189978Seric 		/* give it to sendmail, rah rah! */
419579Sroot 		unlink(lettmp);
420579Sroot 		ap = newargv+1;
421579Sroot 		if (rmail)
422579Sroot 			*ap-- = "-s";
4239978Seric 		*ap = "-sendmail";
4244461Sroot 		setuid(getuid());
4259978Seric 		execv(SENDMAIL, ap);
4269978Seric 		perror(SENDMAIL);
427579Sroot 		exit(EX_UNAVAILABLE);
428579Sroot 	}
429579Sroot 
430579Sroot 	truename[0] = 0;
431579Sroot 	line[0] = '\0';
432579Sroot 
433579Sroot 	/*
434579Sroot 	 * When we fall out of this, argv[1] should be first name,
435579Sroot 	 * argc should be number of names + 1.
436579Sroot 	 */
437579Sroot 
438579Sroot 	while (argc > 1 && *argv[1] == '-') {
439579Sroot 		cp = *++argv;
440579Sroot 		argc--;
441579Sroot 		switch (cp[1]) {
442579Sroot 		case 'r':
443579Sroot 			if (argc <= 0) {
444579Sroot 				usage();
445579Sroot 				done();
446579Sroot 			}
447579Sroot 			gaver++;
448579Sroot 			strcpy(truename, argv[1]);
449579Sroot 			fgets(line, LSIZE, stdin);
450579Sroot 			if (strcmpn("From", line, 4) == 0)
451579Sroot 				line[0] = '\0';
452579Sroot 			argv++;
453579Sroot 			argc--;
454579Sroot 			break;
455579Sroot 
456579Sroot 		case 'h':
457579Sroot 			if (argc <= 0) {
458579Sroot 				usage();
459579Sroot 				done();
460579Sroot 			}
461579Sroot 			hseqno = atoi(argv[1]);
462579Sroot 			argv++;
463579Sroot 			argc--;
464579Sroot 			break;
465579Sroot 
466579Sroot 		case 'd':
467579Sroot 			break;
468579Sroot 
469579Sroot 		default:
470579Sroot 			usage();
471579Sroot 			done();
472579Sroot 		}
473579Sroot 	}
474579Sroot 	if (argc <= 1) {
475579Sroot 		usage();
476579Sroot 		done();
477579Sroot 	}
478579Sroot 	if (gaver == 0)
479579Sroot 		strcpy(truename, my_name);
480579Sroot 	/*
481579Sroot 	if (argc > 4 && strcmp(argv[1], "-r") == 0) {
482579Sroot 		strcpy(truename, argv[2]);
483579Sroot 		argc -= 2;
484579Sroot 		argv += 2;
485579Sroot 		fgets(line, LSIZE, stdin);
486579Sroot 		if (strcmpn("From", line, 4) == 0)
487579Sroot 			line[0] = '\0';
488579Sroot 	} else
489579Sroot 		strcpy(truename, my_name);
490579Sroot 	*/
491579Sroot 	time(&iop);
492579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
493579Sroot 	iop = ftell(tmpf);
494579Sroot 	flgf = 1;
495579Sroot 	for (first = 1;; first = 0) {
496579Sroot 		if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
497579Sroot 			break;
498579Sroot 		if (!first && fgets(line, LSIZE, stdin) == NULL)
499579Sroot 			break;
500579Sroot 		if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
501579Sroot 			break;
502579Sroot 		if (isfrom(line))
503579Sroot 			fputs(">", tmpf);
504579Sroot 		fputs(line, tmpf);
505579Sroot 		flgf = 0;
506579Sroot 	}
507579Sroot 	fputs("\n", tmpf);
508579Sroot 	nlet = 1;
509579Sroot 	let[0].adr = 0;
510579Sroot 	let[1].adr = ftell(tmpf);
511579Sroot 	fclose(tmpf);
512579Sroot 	if (flgf)
513579Sroot 		return;
514579Sroot 	tmpf = fopen(lettmp, "r");
515579Sroot 	if (tmpf == NULL) {
516579Sroot 		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
517579Sroot 		return;
518579Sroot 	}
5196015Swnj 	while (--argc > 0) {
5206015Swnj 		if (!sendmail(0, *++argv, truename))
521579Sroot 			error++;
5226015Swnj 	}
52310644Seric 	if (error && safefile(dead)) {
524579Sroot 		setuid(getuid());
525579Sroot 		malf = fopen(dead, "w");
526579Sroot 		if (malf == NULL) {
527579Sroot 			fprintf(stdout, "mail: cannot open %s\n", dead);
528579Sroot 			fclose(tmpf);
529579Sroot 			return;
530579Sroot 		}
531579Sroot 		copylet(0, malf, ZAP);
532579Sroot 		fclose(malf);
533579Sroot 		fprintf(stdout, "Mail saved in %s\n", dead);
534579Sroot 	}
535579Sroot 	fclose(tmpf);
536579Sroot }
537579Sroot 
538579Sroot sendrmt(n, name, rcmd)
539579Sroot char *name;
540579Sroot char *rcmd;
541579Sroot {
542579Sroot 	FILE *rmf, *popen();
543579Sroot 	register char *p;
544579Sroot 	char rsys[64], cmd[64];
545579Sroot 	register local, pid;
546579Sroot 	int sts;
547579Sroot 
548579Sroot 	local = 0;
549579Sroot 	if (index(name, '^')) {
550579Sroot 		while (p = index(name, '^'))
551579Sroot 			*p = '!';
552579Sroot 		if (strncmp(name, "researc", 7)) {
553579Sroot 			strcpy(rsys, "research");
554579Sroot 			if (*name != '!')
555579Sroot 				--name;
556579Sroot 			goto skip;
557579Sroot 		}
558579Sroot 	}
559579Sroot 	if (*name=='!')
560579Sroot 		name++;
561579Sroot 	for(p=rsys; *name!='!'; *p++ = *name++)
562579Sroot 		if (*name=='\0') {
563579Sroot 			local++;
564579Sroot 			break;
565579Sroot 		}
566579Sroot 	*p = '\0';
567579Sroot 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
568579Sroot 		fprintf(stdout, "null name\n");
569579Sroot 		return(0);
570579Sroot 	}
571579Sroot skip:
572579Sroot 	if ((pid = fork()) == -1) {
573579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
574579Sroot 		return(0);
575579Sroot 	}
576579Sroot 	if (pid) {
577579Sroot 		while (wait(&sts) != pid) {
578579Sroot 			if (wait(&sts)==-1)
579579Sroot 				return(0);
580579Sroot 		}
581579Sroot 		return(!sts);
582579Sroot 	}
583579Sroot 	setuid(getuid());
584579Sroot 	if (local)
585579Sroot 		sprintf(cmd, "%s %s", rcmd, rsys);
586579Sroot 	else {
587579Sroot 		if (index(name+1, '!'))
588579Sroot 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
589579Sroot 		else
590579Sroot 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
591579Sroot 	}
592579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
593579Sroot 		exit(1);
594579Sroot 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
59510783Seric 	exit(pclose(rmf) != 0);
596579Sroot }
597579Sroot 
598579Sroot usage()
599579Sroot {
600579Sroot 
601579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
602579Sroot }
603579Sroot 
6046015Swnj #include <sys/socket.h>
6059226Ssam #include <netinet/in.h>
60610227Ssam #include <netdb.h>
60710227Ssam struct sockaddr_in biffaddr;
6086015Swnj 
6096015Swnj sendmail(n, name, fromaddr)
610579Sroot int n;
611579Sroot char *name;
612579Sroot char *fromaddr;
613579Sroot {
614579Sroot 	char file[100];
615579Sroot 	register char *p;
616579Sroot 	register mask;
617579Sroot 	struct passwd *pw, *getpwnam();
618579Sroot 	struct stat statb;
6193666Swnj 	char buf[128];
6203666Swnj 	int f;
62110227Ssam 	struct hostent *hp = NULL;
62210227Ssam 	struct servent *sp = NULL;
623579Sroot 
624579Sroot 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
625579Sroot 		;
626579Sroot 	if (*p == '!'|| *p=='^')
627579Sroot 		return(sendrmt(n, name, 0));
628579Sroot 	if ((pw = getpwnam(name)) == NULL) {
629579Sroot 		fprintf(stdout, "mail: can't send to %s\n", name);
630579Sroot 		return(0);
631579Sroot 	}
632579Sroot 	cat(file, maildir, name);
633579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
634579Sroot 		strcat(file, "/");
635579Sroot 		strcat(file, name);
636579Sroot 	}
637579Sroot 	mask = umask(MAILMODE);
63810644Seric 	if (!safefile(file))
6394458Sroot 		return(0);
640*11893Seric 	lock(file);
641579Sroot 	malf = fopen(file, "a");
642579Sroot 	umask(mask);
643579Sroot 	if (malf == NULL) {
644*11893Seric 		unlock();
645579Sroot 		fprintf(stdout, "mail: cannot append to %s\n", file);
646579Sroot 		return(0);
647579Sroot 	}
6486015Swnj 	chown(file, pw->pw_uid, pw->pw_gid);
6493666Swnj 	{
65010227Ssam 		hp = gethostbyname("localhost");
65110227Ssam 		sp = getservbyname("biff", "udp");
65210227Ssam 		if (hp && sp) {
65310227Ssam 			f = socket(AF_INET, SOCK_DGRAM, 0, 0);
65410227Ssam 			sprintf(buf, "%s@%d\n", name, ftell(malf));
65510227Ssam 		}
6563666Swnj 	}
657579Sroot 	copylet(n, malf, ORDINARY);
6586015Swnj 	fclose(malf);
65910227Ssam 	if (hp && sp) {
66010227Ssam 		biffaddr.sin_family = hp->h_addrtype;
66110227Ssam 		bcopy(hp->h_addr, &biffaddr.sin_addr, hp->h_length);
66210227Ssam 		biffaddr.sin_port = sp->s_port;
6639226Ssam 		sendto(f, buf, strlen(buf)+1, 0, &biffaddr, sizeof (biffaddr));
6643666Swnj 		close(f);
6653666Swnj 	}
666579Sroot 	unlock();
667579Sroot 	return(1);
668579Sroot }
669579Sroot 
670579Sroot delete(i)
671579Sroot {
672579Sroot 	setsig(i, delete);
673579Sroot 	fprintf(stderr, "\n");
674579Sroot 	if(delflg)
675579Sroot 		longjmp(sjbuf, 1);
676579Sroot 	done();
677579Sroot }
678579Sroot 
679579Sroot /*
680579Sroot  * Lock the specified mail file by setting the file mailfile.lock.
681579Sroot  * We must, of course, be careful to unlink the lock file by a call
682579Sroot  * to unlock before we stop.  The algorithm used here is to see if
683579Sroot  * the lock exists, and if it does, to check its modify time.  If it
684579Sroot  * is older than 30 seconds, we assume error and set our own file.
685579Sroot  * Otherwise, we wait for 5 seconds and try again.
686579Sroot  */
687579Sroot 
688579Sroot char	*maillock	= ".lock";		/* Lock suffix for mailname */
689579Sroot char	*lockname	= "/usr/spool/mail/tmXXXXXX";
690579Sroot char	locktmp[30];				/* Usable lock temporary */
691579Sroot char	curlock[50];				/* Last used name of lock */
692579Sroot int	locked;					/* To note that we locked it */
693579Sroot 
694579Sroot lock(file)
695579Sroot char *file;
696579Sroot {
697579Sroot 	register int f;
698579Sroot 	struct stat sbuf;
699579Sroot 	long curtime;
700579Sroot 	int statfailed;
701579Sroot 
702579Sroot 	if (locked || flgf)
703579Sroot 		return(0);
704579Sroot 	strcpy(curlock, file);
705579Sroot 	strcat(curlock, maillock);
706579Sroot 	strcpy(locktmp, lockname);
707579Sroot 	mktemp(locktmp);
708579Sroot 	unlink(locktmp);
709579Sroot 	statfailed = 0;
710579Sroot 	for (;;) {
711579Sroot 		f = lock1(locktmp, curlock);
712579Sroot 		if (f == 0) {
713579Sroot 			locked = 1;
714579Sroot 			return(0);
715579Sroot 		}
716579Sroot 		if (stat(curlock, &sbuf) < 0) {
717579Sroot 			if (statfailed++ > 5)
718579Sroot 				return(-1);
719579Sroot 			sleep(5);
720579Sroot 			continue;
721579Sroot 		}
722579Sroot 		statfailed = 0;
723579Sroot 		time(&curtime);
724579Sroot 		if (curtime < sbuf.st_ctime + 30) {
725579Sroot 			sleep(5);
726579Sroot 			continue;
727579Sroot 		}
728579Sroot 		unlink(curlock);
729579Sroot 	}
730579Sroot }
731579Sroot 
732579Sroot /*
733579Sroot  * Remove the mail lock, and note that we no longer
734579Sroot  * have it locked.
735579Sroot  */
736579Sroot 
737579Sroot unlock()
738579Sroot {
739579Sroot 
740579Sroot 	unlink(curlock);
741579Sroot 	locked = 0;
742579Sroot }
743579Sroot 
744579Sroot /*
745579Sroot  * Attempt to set the lock by creating the temporary file,
746579Sroot  * then doing a link/unlink.  If it fails, return -1 else 0
747579Sroot  */
748579Sroot 
749579Sroot lock1(tempfile, name)
750579Sroot 	char tempfile[], name[];
751579Sroot {
752579Sroot 	register int fd;
753579Sroot 
754579Sroot 	fd = creat(tempfile, 0);
755579Sroot 	if (fd < 0)
756579Sroot 		return(-1);
757579Sroot 	close(fd);
758579Sroot 	if (link(tempfile, name) < 0) {
759579Sroot 		unlink(tempfile);
760579Sroot 		return(-1);
761579Sroot 	}
762579Sroot 	unlink(tempfile);
763579Sroot 	return(0);
764579Sroot }
765579Sroot 
766579Sroot done()
767579Sroot {
768579Sroot 	if(locked)
769579Sroot 		unlock();
770579Sroot 	unlink(lettmp);
771579Sroot 	unlink(locktmp);
772579Sroot 	exit(error);
773579Sroot }
774579Sroot 
775579Sroot cat(to, from1, from2)
776579Sroot char *to, *from1, *from2;
777579Sroot {
778579Sroot 	int i, j;
779579Sroot 
780579Sroot 	j = 0;
781579Sroot 	for (i=0; from1[i]; i++)
782579Sroot 		to[j++] = from1[i];
783579Sroot 	for (i=0; from2[i]; i++)
784579Sroot 		to[j++] = from2[i];
785579Sroot 	to[j] = 0;
786579Sroot }
787579Sroot 
788579Sroot char *getarg(s, p)	/* copy p... into s, update p */
789579Sroot register char *s, *p;
790579Sroot {
791579Sroot 	while (*p == ' ' || *p == '\t')
792579Sroot 		p++;
793579Sroot 	if (*p == '\n' || *p == '\0')
794579Sroot 		return(NULL);
795579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
796579Sroot 		*s++ = *p++;
797579Sroot 	*s = '\0';
798579Sroot 	return(p);
799579Sroot }
80010644Seric 
80110644Seric safefile(f)
80210644Seric 	char *f;
80310644Seric {
80410644Seric 	struct stat statb;
80510644Seric 
80610644Seric 	if (lstat(f, &statb) < 0)
80710644Seric 		return (1);
80810644Seric 	if (statb.st_nlink != 1 || (statb.st_mode & S_IFMT) == S_IFLNK) {
80910644Seric 		fprintf(stderr, "mail: %s has more than one link or is a symbolic link\n", f);
81010644Seric 		return (0);
81110644Seric 	}
81210644Seric 	return (1);
81310644Seric }
814