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*10227Ssam static char SccsId[] = "@(#)mail.local.c	4.11	01/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 
361579Sroot copylet(n, f, type) FILE *f;
362579Sroot {	int ch, k;
363579Sroot 	fseek(tmpf, let[n].adr, 0);
364579Sroot 	k = let[n+1].adr - let[n].adr;
365579Sroot 	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')
366579Sroot 		if(type!=ZAP) fputc(ch,f);
3676199Sroot 	if(type==REMOTE) {
3686199Sroot 		char hostname[32];
3696199Sroot 		gethostname(hostname, sizeof (hostname));
3706199Sroot 		fprintf(f, " remote from %s\n", hostname);
3716199Sroot 	} else if (type==FORWARD)
372579Sroot 		fprintf(f, forwmsg);
373579Sroot 	else if(type==ORDINARY)
374579Sroot 		fputc(ch,f);
375579Sroot 	while(k-->1)
376579Sroot 		fputc(ch=fgetc(tmpf), f);
377579Sroot 	if(type!=ZAP || ch!= '\n')
378579Sroot 		fputc(fgetc(tmpf), f);
379579Sroot }
380579Sroot 
381579Sroot isfrom(lp)
382579Sroot register char *lp;
383579Sroot {
384579Sroot 	register char *p;
385579Sroot 
386579Sroot 	for (p = from; *p; )
387579Sroot 		if (*lp++ != *p++)
388579Sroot 			return(0);
389579Sroot 	return(1);
390579Sroot }
391579Sroot 
3926015Swnj bulkmail(argc, argv)
393579Sroot char **argv;
394579Sroot {
395579Sroot 	char truename[100];
396579Sroot 	int first;
397579Sroot 	register char *cp;
398579Sroot 	int gaver = 0;
399579Sroot 	char *newargv[1000];
400579Sroot 	register char **ap;
401579Sroot 	register char **vp;
402579Sroot 	int dflag;
403579Sroot 
404579Sroot 	dflag = 0;
405579Sroot 	if (argc < 1)
406579Sroot 		fprintf(stderr, "puke\n");
407579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
408579Sroot 	{
409579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
410579Sroot 			dflag++;
411579Sroot 	}
412579Sroot 	if (!dflag)
413579Sroot 	{
4149978Seric 		/* give it to sendmail, rah rah! */
415579Sroot 		unlink(lettmp);
416579Sroot 		ap = newargv+1;
417579Sroot 		if (rmail)
418579Sroot 			*ap-- = "-s";
4199978Seric 		*ap = "-sendmail";
4204461Sroot 		setuid(getuid());
4219978Seric 		execv(SENDMAIL, ap);
4229978Seric 		perror(SENDMAIL);
423579Sroot 		exit(EX_UNAVAILABLE);
424579Sroot 	}
425579Sroot 
426579Sroot 	truename[0] = 0;
427579Sroot 	line[0] = '\0';
428579Sroot 
429579Sroot 	/*
430579Sroot 	 * When we fall out of this, argv[1] should be first name,
431579Sroot 	 * argc should be number of names + 1.
432579Sroot 	 */
433579Sroot 
434579Sroot 	while (argc > 1 && *argv[1] == '-') {
435579Sroot 		cp = *++argv;
436579Sroot 		argc--;
437579Sroot 		switch (cp[1]) {
438579Sroot 		case 'r':
439579Sroot 			if (argc <= 0) {
440579Sroot 				usage();
441579Sroot 				done();
442579Sroot 			}
443579Sroot 			gaver++;
444579Sroot 			strcpy(truename, argv[1]);
445579Sroot 			fgets(line, LSIZE, stdin);
446579Sroot 			if (strcmpn("From", line, 4) == 0)
447579Sroot 				line[0] = '\0';
448579Sroot 			argv++;
449579Sroot 			argc--;
450579Sroot 			break;
451579Sroot 
452579Sroot 		case 'h':
453579Sroot 			if (argc <= 0) {
454579Sroot 				usage();
455579Sroot 				done();
456579Sroot 			}
457579Sroot 			hseqno = atoi(argv[1]);
458579Sroot 			argv++;
459579Sroot 			argc--;
460579Sroot 			break;
461579Sroot 
462579Sroot 		case 'd':
463579Sroot 			break;
464579Sroot 
465579Sroot 		default:
466579Sroot 			usage();
467579Sroot 			done();
468579Sroot 		}
469579Sroot 	}
470579Sroot 	if (argc <= 1) {
471579Sroot 		usage();
472579Sroot 		done();
473579Sroot 	}
474579Sroot 	if (gaver == 0)
475579Sroot 		strcpy(truename, my_name);
476579Sroot 	/*
477579Sroot 	if (argc > 4 && strcmp(argv[1], "-r") == 0) {
478579Sroot 		strcpy(truename, argv[2]);
479579Sroot 		argc -= 2;
480579Sroot 		argv += 2;
481579Sroot 		fgets(line, LSIZE, stdin);
482579Sroot 		if (strcmpn("From", line, 4) == 0)
483579Sroot 			line[0] = '\0';
484579Sroot 	} else
485579Sroot 		strcpy(truename, my_name);
486579Sroot 	*/
487579Sroot 	time(&iop);
488579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
489579Sroot 	iop = ftell(tmpf);
490579Sroot 	flgf = 1;
491579Sroot 	for (first = 1;; first = 0) {
492579Sroot 		if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
493579Sroot 			break;
494579Sroot 		if (!first && fgets(line, LSIZE, stdin) == NULL)
495579Sroot 			break;
496579Sroot 		if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
497579Sroot 			break;
498579Sroot 		if (isfrom(line))
499579Sroot 			fputs(">", tmpf);
500579Sroot 		fputs(line, tmpf);
501579Sroot 		flgf = 0;
502579Sroot 	}
503579Sroot 	fputs("\n", tmpf);
504579Sroot 	nlet = 1;
505579Sroot 	let[0].adr = 0;
506579Sroot 	let[1].adr = ftell(tmpf);
507579Sroot 	fclose(tmpf);
508579Sroot 	if (flgf)
509579Sroot 		return;
510579Sroot 	tmpf = fopen(lettmp, "r");
511579Sroot 	if (tmpf == NULL) {
512579Sroot 		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
513579Sroot 		return;
514579Sroot 	}
5156015Swnj 	while (--argc > 0) {
5166015Swnj 		if (!sendmail(0, *++argv, truename))
517579Sroot 			error++;
5186015Swnj 	}
519579Sroot 	if (error) {
520579Sroot 		setuid(getuid());
521579Sroot 		malf = fopen(dead, "w");
522579Sroot 		if (malf == NULL) {
523579Sroot 			fprintf(stdout, "mail: cannot open %s\n", dead);
524579Sroot 			fclose(tmpf);
525579Sroot 			return;
526579Sroot 		}
527579Sroot 		copylet(0, malf, ZAP);
528579Sroot 		fclose(malf);
529579Sroot 		fprintf(stdout, "Mail saved in %s\n", dead);
530579Sroot 	}
531579Sroot 	fclose(tmpf);
532579Sroot }
533579Sroot 
534579Sroot sendrmt(n, name, rcmd)
535579Sroot char *name;
536579Sroot char *rcmd;
537579Sroot {
538579Sroot 	FILE *rmf, *popen();
539579Sroot 	register char *p;
540579Sroot 	char rsys[64], cmd[64];
541579Sroot 	register local, pid;
542579Sroot 	int sts;
543579Sroot 
544579Sroot 	local = 0;
545579Sroot 	if (index(name, '^')) {
546579Sroot 		while (p = index(name, '^'))
547579Sroot 			*p = '!';
548579Sroot 		if (strncmp(name, "researc", 7)) {
549579Sroot 			strcpy(rsys, "research");
550579Sroot 			if (*name != '!')
551579Sroot 				--name;
552579Sroot 			goto skip;
553579Sroot 		}
554579Sroot 	}
555579Sroot 	if (*name=='!')
556579Sroot 		name++;
557579Sroot 	for(p=rsys; *name!='!'; *p++ = *name++)
558579Sroot 		if (*name=='\0') {
559579Sroot 			local++;
560579Sroot 			break;
561579Sroot 		}
562579Sroot 	*p = '\0';
563579Sroot 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
564579Sroot 		fprintf(stdout, "null name\n");
565579Sroot 		return(0);
566579Sroot 	}
567579Sroot skip:
568579Sroot 	if ((pid = fork()) == -1) {
569579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
570579Sroot 		return(0);
571579Sroot 	}
572579Sroot 	if (pid) {
573579Sroot 		while (wait(&sts) != pid) {
574579Sroot 			if (wait(&sts)==-1)
575579Sroot 				return(0);
576579Sroot 		}
577579Sroot 		return(!sts);
578579Sroot 	}
579579Sroot 	setuid(getuid());
580579Sroot 	if (local)
581579Sroot 		sprintf(cmd, "%s %s", rcmd, rsys);
582579Sroot 	else {
583579Sroot 		if (index(name+1, '!'))
584579Sroot 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
585579Sroot 		else
586579Sroot 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
587579Sroot 	}
588579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
589579Sroot 		exit(1);
590579Sroot 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
591579Sroot 	pclose(rmf);
592579Sroot 	exit(0);
593579Sroot }
594579Sroot 
595579Sroot usage()
596579Sroot {
597579Sroot 
598579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
599579Sroot }
600579Sroot 
6016015Swnj #include <sys/socket.h>
6029226Ssam #include <netinet/in.h>
603*10227Ssam #include <netdb.h>
604*10227Ssam struct sockaddr_in biffaddr;
6056015Swnj 
6066015Swnj sendmail(n, name, fromaddr)
607579Sroot int n;
608579Sroot char *name;
609579Sroot char *fromaddr;
610579Sroot {
611579Sroot 	char file[100];
612579Sroot 	register char *p;
613579Sroot 	register mask;
614579Sroot 	struct passwd *pw, *getpwnam();
615579Sroot 	struct stat statb;
6163666Swnj 	char buf[128];
6173666Swnj 	int f;
618*10227Ssam 	struct hostent *hp = NULL;
619*10227Ssam 	struct servent *sp = NULL;
620579Sroot 
621579Sroot 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
622579Sroot 		;
623579Sroot 	if (*p == '!'|| *p=='^')
624579Sroot 		return(sendrmt(n, name, 0));
625579Sroot 	if ((pw = getpwnam(name)) == NULL) {
626579Sroot 		fprintf(stdout, "mail: can't send to %s\n", name);
627579Sroot 		return(0);
628579Sroot 	}
629579Sroot 	cat(file, maildir, name);
630579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
631579Sroot 		strcat(file, "/");
632579Sroot 		strcat(file, name);
633579Sroot 	}
634579Sroot 	mask = umask(MAILMODE);
6354459Sroot 	if (stat(file, &statb) >= 0 && statb.st_nlink != 1) {
6364458Sroot 		fprintf(stdout, "mail: %s's mail file has more than one link\n", name);
6374458Sroot 		return(0);
6384458Sroot 	}
639579Sroot 	malf = fopen(file, "a");
640579Sroot 	umask(mask);
641579Sroot 	if (malf == NULL) {
642579Sroot 		fprintf(stdout, "mail: cannot append to %s\n", file);
643579Sroot 		return(0);
644579Sroot 	}
645579Sroot 	lock(file);
6466015Swnj 	chown(file, pw->pw_uid, pw->pw_gid);
6473666Swnj 	{
648*10227Ssam 		hp = gethostbyname("localhost");
649*10227Ssam 		sp = getservbyname("biff", "udp");
650*10227Ssam 		if (hp && sp) {
651*10227Ssam 			f = socket(AF_INET, SOCK_DGRAM, 0, 0);
652*10227Ssam 			sprintf(buf, "%s@%d\n", name, ftell(malf));
653*10227Ssam 		}
6543666Swnj 	}
655579Sroot 	copylet(n, malf, ORDINARY);
6566015Swnj 	fclose(malf);
657*10227Ssam 	if (hp && sp) {
658*10227Ssam 		biffaddr.sin_family = hp->h_addrtype;
659*10227Ssam 		bcopy(hp->h_addr, &biffaddr.sin_addr, hp->h_length);
660*10227Ssam 		biffaddr.sin_port = sp->s_port;
6619226Ssam 		sendto(f, buf, strlen(buf)+1, 0, &biffaddr, sizeof (biffaddr));
6623666Swnj 		close(f);
6633666Swnj 	}
664579Sroot 	unlock();
665579Sroot 	return(1);
666579Sroot }
667579Sroot 
668579Sroot delete(i)
669579Sroot {
670579Sroot 	setsig(i, delete);
671579Sroot 	fprintf(stderr, "\n");
672579Sroot 	if(delflg)
673579Sroot 		longjmp(sjbuf, 1);
674579Sroot 	done();
675579Sroot }
676579Sroot 
677579Sroot /*
678579Sroot  * Lock the specified mail file by setting the file mailfile.lock.
679579Sroot  * We must, of course, be careful to unlink the lock file by a call
680579Sroot  * to unlock before we stop.  The algorithm used here is to see if
681579Sroot  * the lock exists, and if it does, to check its modify time.  If it
682579Sroot  * is older than 30 seconds, we assume error and set our own file.
683579Sroot  * Otherwise, we wait for 5 seconds and try again.
684579Sroot  */
685579Sroot 
686579Sroot char	*maillock	= ".lock";		/* Lock suffix for mailname */
687579Sroot char	*lockname	= "/usr/spool/mail/tmXXXXXX";
688579Sroot char	locktmp[30];				/* Usable lock temporary */
689579Sroot char	curlock[50];				/* Last used name of lock */
690579Sroot int	locked;					/* To note that we locked it */
691579Sroot 
692579Sroot lock(file)
693579Sroot char *file;
694579Sroot {
695579Sroot 	register int f;
696579Sroot 	struct stat sbuf;
697579Sroot 	long curtime;
698579Sroot 	int statfailed;
699579Sroot 
700579Sroot 	if (locked || flgf)
701579Sroot 		return(0);
702579Sroot 	strcpy(curlock, file);
703579Sroot 	strcat(curlock, maillock);
704579Sroot 	strcpy(locktmp, lockname);
705579Sroot 	mktemp(locktmp);
706579Sroot 	unlink(locktmp);
707579Sroot 	statfailed = 0;
708579Sroot 	for (;;) {
709579Sroot 		f = lock1(locktmp, curlock);
710579Sroot 		if (f == 0) {
711579Sroot 			locked = 1;
712579Sroot 			return(0);
713579Sroot 		}
714579Sroot 		if (stat(curlock, &sbuf) < 0) {
715579Sroot 			if (statfailed++ > 5)
716579Sroot 				return(-1);
717579Sroot 			sleep(5);
718579Sroot 			continue;
719579Sroot 		}
720579Sroot 		statfailed = 0;
721579Sroot 		time(&curtime);
722579Sroot 		if (curtime < sbuf.st_ctime + 30) {
723579Sroot 			sleep(5);
724579Sroot 			continue;
725579Sroot 		}
726579Sroot 		unlink(curlock);
727579Sroot 	}
728579Sroot }
729579Sroot 
730579Sroot /*
731579Sroot  * Remove the mail lock, and note that we no longer
732579Sroot  * have it locked.
733579Sroot  */
734579Sroot 
735579Sroot unlock()
736579Sroot {
737579Sroot 
738579Sroot 	unlink(curlock);
739579Sroot 	locked = 0;
740579Sroot }
741579Sroot 
742579Sroot /*
743579Sroot  * Attempt to set the lock by creating the temporary file,
744579Sroot  * then doing a link/unlink.  If it fails, return -1 else 0
745579Sroot  */
746579Sroot 
747579Sroot lock1(tempfile, name)
748579Sroot 	char tempfile[], name[];
749579Sroot {
750579Sroot 	register int fd;
751579Sroot 
752579Sroot 	fd = creat(tempfile, 0);
753579Sroot 	if (fd < 0)
754579Sroot 		return(-1);
755579Sroot 	close(fd);
756579Sroot 	if (link(tempfile, name) < 0) {
757579Sroot 		unlink(tempfile);
758579Sroot 		return(-1);
759579Sroot 	}
760579Sroot 	unlink(tempfile);
761579Sroot 	return(0);
762579Sroot }
763579Sroot 
764579Sroot done()
765579Sroot {
766579Sroot 	if(locked)
767579Sroot 		unlock();
768579Sroot 	unlink(lettmp);
769579Sroot 	unlink(locktmp);
770579Sroot 	exit(error);
771579Sroot }
772579Sroot 
773579Sroot cat(to, from1, from2)
774579Sroot char *to, *from1, *from2;
775579Sroot {
776579Sroot 	int i, j;
777579Sroot 
778579Sroot 	j = 0;
779579Sroot 	for (i=0; from1[i]; i++)
780579Sroot 		to[j++] = from1[i];
781579Sroot 	for (i=0; from2[i]; i++)
782579Sroot 		to[j++] = from2[i];
783579Sroot 	to[j] = 0;
784579Sroot }
785579Sroot 
786579Sroot char *getarg(s, p)	/* copy p... into s, update p */
787579Sroot register char *s, *p;
788579Sroot {
789579Sroot 	while (*p == ' ' || *p == '\t')
790579Sroot 		p++;
791579Sroot 	if (*p == '\n' || *p == '\0')
792579Sroot 		return(NULL);
793579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
794579Sroot 		*s++ = *p++;
795579Sroot 	*s = '\0';
796579Sroot 	return(p);
797579Sroot }
798