1*579Sroot #include <ctype.h>
2*579Sroot #include <stdio.h>
3*579Sroot #include <pwd.h>
4*579Sroot #include <utmp.h>
5*579Sroot #include <signal.h>
6*579Sroot #include <sys/types.h>
7*579Sroot #include <sys/stat.h>
8*579Sroot #include <setjmp.h>
9*579Sroot #include <whoami.h>
10*579Sroot #include <sysexits.h>
11*579Sroot 
12*579Sroot #define DELIVERMAIL	"/etc/delivermail"
13*579Sroot 
14*579Sroot 
15*579Sroot /*copylet flags */
16*579Sroot 	/*remote mail, add rmtmsg */
17*579Sroot #define REMOTE	1
18*579Sroot 	/* zap header and trailing empty line */
19*579Sroot #define ZAP	3
20*579Sroot #define ORDINARY 2
21*579Sroot #define	FORWARD	4
22*579Sroot #define	LSIZE	256
23*579Sroot #define	MAXLET	300	/* maximum number of letters */
24*579Sroot #define	MAILMODE (~0644)		/* mode of created mail */
25*579Sroot #define	RMAIL	"/usr/net/bin/sendberkmail"
26*579Sroot #define LOCNAM1	"csvax"
27*579Sroot #define LOCNAM2	"ucbvax"
28*579Sroot #define LOCNAM3	"vax"
29*579Sroot #define LOCNAM4	"v"
30*579Sroot 
31*579Sroot char	line[LSIZE];
32*579Sroot char	resp[LSIZE];
33*579Sroot struct let {
34*579Sroot 	long	adr;
35*579Sroot 	char	change;
36*579Sroot } let[MAXLET];
37*579Sroot int	nlet	= 0;
38*579Sroot char	lfil[50];
39*579Sroot long	iop, time();
40*579Sroot char	*getenv();
41*579Sroot char	*index();
42*579Sroot char	lettmp[] = "/tmp/maXXXXX";
43*579Sroot char	maildir[] = "/usr/spool/mail/";
44*579Sroot char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";
45*579Sroot char	dead[] = "dead.letter";
46*579Sroot char	*thissys = sysname;
47*579Sroot char	*netname = "vax";
48*579Sroot char	forwmsg[] = " forwarded\n";
49*579Sroot FILE	*tmpf;
50*579Sroot FILE	*malf;
51*579Sroot char	*my_name;
52*579Sroot char	*getlogin();
53*579Sroot struct	passwd	*getpwuid();
54*579Sroot int	error;
55*579Sroot int	changed;
56*579Sroot int	forward;
57*579Sroot char	from[] = "From ";
58*579Sroot long	ftell();
59*579Sroot int	delete();
60*579Sroot char	*ctime();
61*579Sroot int	flgf;
62*579Sroot int	flgp;
63*579Sroot int	delflg = 1;
64*579Sroot int	hseqno;
65*579Sroot jmp_buf	sjbuf;
66*579Sroot int	rmail;
67*579Sroot 
68*579Sroot main(argc, argv)
69*579Sroot char **argv;
70*579Sroot {
71*579Sroot 	register i;
72*579Sroot 	char sobuf[BUFSIZ];
73*579Sroot 
74*579Sroot 	setbuf(stdout, sobuf);
75*579Sroot 	mktemp(lettmp);
76*579Sroot 	unlink(lettmp);
77*579Sroot 	my_name = getlogin();
78*579Sroot 	if (my_name == NULL || strlen(my_name) == 0) {
79*579Sroot 		struct passwd *pwent;
80*579Sroot 		pwent = getpwuid(getuid());
81*579Sroot 		if (pwent==NULL)
82*579Sroot 			my_name = "???";
83*579Sroot 		else
84*579Sroot 			my_name = pwent->pw_name;
85*579Sroot 	}
86*579Sroot 	if(setjmp(sjbuf)) done();
87*579Sroot 	for (i=0; i<20; i++)
88*579Sroot 		setsig(i, delete);
89*579Sroot 	tmpf = fopen(lettmp, "w");
90*579Sroot 	if (tmpf == NULL) {
91*579Sroot 		fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);
92*579Sroot 		done();
93*579Sroot 	}
94*579Sroot 	if (argv[0][0] == 'r')
95*579Sroot 		rmail++;
96*579Sroot 	if (argv[0][0] != 'r' &&	/* no favors for rmail*/
97*579Sroot 	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))
98*579Sroot 		printmail(argc, argv);
99*579Sroot 	else
100*579Sroot 		sendmail(argc, argv);
101*579Sroot 	done();
102*579Sroot }
103*579Sroot 
104*579Sroot setsig(i, f)
105*579Sroot int i;
106*579Sroot int (*f)();
107*579Sroot {
108*579Sroot 	if(signal(i, SIG_IGN)!=SIG_IGN)
109*579Sroot 		signal(i, f);
110*579Sroot }
111*579Sroot 
112*579Sroot any(c, str)
113*579Sroot 	register int c;
114*579Sroot 	register char *str;
115*579Sroot {
116*579Sroot 
117*579Sroot 	while (*str)
118*579Sroot 		if (c == *str++)
119*579Sroot 			return(1);
120*579Sroot 	return(0);
121*579Sroot }
122*579Sroot 
123*579Sroot printmail(argc, argv)
124*579Sroot char **argv;
125*579Sroot {
126*579Sroot 	int flg, i, j, print;
127*579Sroot 	char *p, *getarg();
128*579Sroot 	struct stat statb;
129*579Sroot 
130*579Sroot 	setuid(getuid());
131*579Sroot 	cat(mailfile, maildir, my_name);
132*579Sroot 	if (stat(mailfile, &statb) >= 0
133*579Sroot 	    && (statb.st_mode & S_IFMT) == S_IFDIR) {
134*579Sroot 		strcat(mailfile, "/");
135*579Sroot 		strcat(mailfile, my_name);
136*579Sroot 	}
137*579Sroot 	for (; argc>1; argv++, argc--) {
138*579Sroot 		if (argv[1][0]=='-') {
139*579Sroot 			if (argv[1][1]=='q')
140*579Sroot 				delflg = 0;
141*579Sroot 			else if (argv[1][1]=='p') {
142*579Sroot 				flgp++;
143*579Sroot 				delflg = 0;
144*579Sroot 			} else if (argv[1][1]=='f') {
145*579Sroot 				if (argc>=3) {
146*579Sroot 					strcpy(mailfile, argv[2]);
147*579Sroot 					argv++;
148*579Sroot 					argc--;
149*579Sroot 				}
150*579Sroot 			} else if (argv[1][1]=='r') {
151*579Sroot 				forward = 1;
152*579Sroot 			} else if (argv[1][1]=='h') {
153*579Sroot 				forward = 1;
154*579Sroot 			} else {
155*579Sroot 				fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);
156*579Sroot 				done();
157*579Sroot 			}
158*579Sroot 		} else
159*579Sroot 			break;
160*579Sroot 	}
161*579Sroot 	malf = fopen(mailfile, "r");
162*579Sroot 	if (malf == NULL) {
163*579Sroot 		fprintf(stdout, "No mail.\n");
164*579Sroot 		return;
165*579Sroot 	}
166*579Sroot 	lock(mailfile);
167*579Sroot 	copymt(malf, tmpf);
168*579Sroot 	fclose(malf);
169*579Sroot 	fclose(tmpf);
170*579Sroot 	unlock();
171*579Sroot 	tmpf = fopen(lettmp, "r");
172*579Sroot 
173*579Sroot 	changed = 0;
174*579Sroot 	print = 1;
175*579Sroot 	for (i = 0; i < nlet; ) {
176*579Sroot 		j = forward ? i : nlet - i - 1;
177*579Sroot 		if(setjmp(sjbuf)) {
178*579Sroot 			print=0;
179*579Sroot 		} else {
180*579Sroot 			if (print)
181*579Sroot 				copylet(j, stdout, ORDINARY);
182*579Sroot 			print = 1;
183*579Sroot 		}
184*579Sroot 		if (flgp) {
185*579Sroot 			i++;
186*579Sroot 			continue;
187*579Sroot 		}
188*579Sroot 		setjmp(sjbuf);
189*579Sroot 		fprintf(stdout, "? ");
190*579Sroot 		fflush(stdout);
191*579Sroot 		if (fgets(resp, LSIZE, stdin) == NULL)
192*579Sroot 			break;
193*579Sroot 		switch (resp[0]) {
194*579Sroot 
195*579Sroot 		default:
196*579Sroot 			fprintf(stderr, "usage\n");
197*579Sroot 		case '?':
198*579Sroot 			print = 0;
199*579Sroot 			fprintf(stderr, "q\tquit\n");
200*579Sroot 			fprintf(stderr, "x\texit without changing mail\n");
201*579Sroot 			fprintf(stderr, "p\tprint\n");
202*579Sroot 			fprintf(stderr, "s[file]\tsave (default mbox)\n");
203*579Sroot 			fprintf(stderr, "w[file]\tsame without header\n");
204*579Sroot 			fprintf(stderr, "-\tprint previous\n");
205*579Sroot 			fprintf(stderr, "d\tdelete\n");
206*579Sroot 			fprintf(stderr, "+\tnext (no delete)\n");
207*579Sroot 			fprintf(stderr, "m user\tmail to user\n");
208*579Sroot 			fprintf(stderr, "! cmd\texecute cmd\n");
209*579Sroot 			break;
210*579Sroot 
211*579Sroot 		case '+':
212*579Sroot 		case 'n':
213*579Sroot 		case '\n':
214*579Sroot 			i++;
215*579Sroot 			break;
216*579Sroot 		case 'x':
217*579Sroot 			changed = 0;
218*579Sroot 		case 'q':
219*579Sroot 			goto donep;
220*579Sroot 		case 'p':
221*579Sroot 			break;
222*579Sroot 		case '^':
223*579Sroot 		case '-':
224*579Sroot 			if (--i < 0)
225*579Sroot 				i = 0;
226*579Sroot 			break;
227*579Sroot 		case 'y':
228*579Sroot 		case 'w':
229*579Sroot 		case 's':
230*579Sroot 			flg = 0;
231*579Sroot 			if (resp[1] != '\n' && resp[1] != ' ') {
232*579Sroot 				printf("illegal\n");
233*579Sroot 				flg++;
234*579Sroot 				print = 0;
235*579Sroot 				continue;
236*579Sroot 			}
237*579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
238*579Sroot 				p = getenv("HOME");
239*579Sroot 				if(p != 0)
240*579Sroot 					cat(resp+1, p, "/mbox");
241*579Sroot 				else
242*579Sroot 					cat(resp+1, "", "mbox");
243*579Sroot 			}
244*579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {
245*579Sroot 				malf = fopen(lfil, "a");
246*579Sroot 				if (malf == NULL) {
247*579Sroot 					fprintf(stdout, "mail: cannot append to %s\n", lfil);
248*579Sroot 					flg++;
249*579Sroot 					continue;
250*579Sroot 				}
251*579Sroot 				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);
252*579Sroot 				fclose(malf);
253*579Sroot 			}
254*579Sroot 			if (flg)
255*579Sroot 				print = 0;
256*579Sroot 			else {
257*579Sroot 				let[j].change = 'd';
258*579Sroot 				changed++;
259*579Sroot 				i++;
260*579Sroot 			}
261*579Sroot 			break;
262*579Sroot 		case 'm':
263*579Sroot 			flg = 0;
264*579Sroot 			if (resp[1] == '\n' || resp[1] == '\0') {
265*579Sroot 				i++;
266*579Sroot 				continue;
267*579Sroot 			}
268*579Sroot 			if (resp[1] != ' ') {
269*579Sroot 				printf("invalid command\n");
270*579Sroot 				flg++;
271*579Sroot 				print = 0;
272*579Sroot 				continue;
273*579Sroot 			}
274*579Sroot 			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )
275*579Sroot 				if (!sendrmt(j, lfil, "/bin/mail"))	/* couldn't send it */
276*579Sroot 					flg++;
277*579Sroot 			if (flg)
278*579Sroot 				print = 0;
279*579Sroot 			else {
280*579Sroot 				let[j].change = 'd';
281*579Sroot 				changed++;
282*579Sroot 				i++;
283*579Sroot 			}
284*579Sroot 			break;
285*579Sroot 		case '!':
286*579Sroot 			system(resp+1);
287*579Sroot 			printf("!\n");
288*579Sroot 			print = 0;
289*579Sroot 			break;
290*579Sroot 		case 'd':
291*579Sroot 			let[j].change = 'd';
292*579Sroot 			changed++;
293*579Sroot 			i++;
294*579Sroot 			if (resp[1] == 'q')
295*579Sroot 				goto donep;
296*579Sroot 			break;
297*579Sroot 		}
298*579Sroot 	}
299*579Sroot    donep:
300*579Sroot 	if (changed)
301*579Sroot 		copyback();
302*579Sroot }
303*579Sroot 
304*579Sroot copyback()	/* copy temp or whatever back to /usr/spool/mail */
305*579Sroot {
306*579Sroot 	register i, n, c;
307*579Sroot 	int new = 0;
308*579Sroot 	struct stat stbuf;
309*579Sroot 
310*579Sroot 	signal(SIGINT, SIG_IGN);
311*579Sroot 	signal(SIGHUP, SIG_IGN);
312*579Sroot 	signal(SIGQUIT, SIG_IGN);
313*579Sroot 	lock(mailfile);
314*579Sroot 	stat(mailfile, &stbuf);
315*579Sroot 	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */
316*579Sroot 		malf = fopen(mailfile, "r");
317*579Sroot 		if (malf == NULL) {
318*579Sroot 			fprintf(stdout, "mail: can't re-read %s\n", mailfile);
319*579Sroot 			done();
320*579Sroot 		}
321*579Sroot 		fseek(malf, let[nlet].adr, 0);
322*579Sroot 		fclose(tmpf);
323*579Sroot 		tmpf = fopen(lettmp, "a");
324*579Sroot 		fseek(tmpf, let[nlet].adr, 0);
325*579Sroot 		while ((c = fgetc(malf)) != EOF)
326*579Sroot 			fputc(c, tmpf);
327*579Sroot 		fclose(malf);
328*579Sroot 		fclose(tmpf);
329*579Sroot 		tmpf = fopen(lettmp, "r");
330*579Sroot 		let[++nlet].adr = stbuf.st_size;
331*579Sroot 		new = 1;
332*579Sroot 	}
333*579Sroot 	malf = fopen(mailfile, "w");
334*579Sroot 	if (malf == NULL) {
335*579Sroot 		fprintf(stderr, "mail: can't rewrite %s\n", lfil);
336*579Sroot 		done();
337*579Sroot 	}
338*579Sroot 	n = 0;
339*579Sroot 	for (i = 0; i < nlet; i++)
340*579Sroot 		if (let[i].change != 'd') {
341*579Sroot 			copylet(i, malf, ORDINARY);
342*579Sroot 			n++;
343*579Sroot 		}
344*579Sroot 	fclose(malf);
345*579Sroot 	if (new)
346*579Sroot 		fprintf(stdout, "new mail arrived\n");
347*579Sroot 	unlock();
348*579Sroot }
349*579Sroot 
350*579Sroot copymt(f1, f2)	/* copy mail (f1) to temp (f2) */
351*579Sroot FILE *f1, *f2;
352*579Sroot {
353*579Sroot 	long nextadr;
354*579Sroot 
355*579Sroot 	nlet = nextadr = 0;
356*579Sroot 	let[0].adr = 0;
357*579Sroot 	while (fgets(line, LSIZE, f1) != NULL) {
358*579Sroot 		if (isfrom(line))
359*579Sroot 			let[nlet++].adr = nextadr;
360*579Sroot 		nextadr += strlen(line);
361*579Sroot 		fputs(line, f2);
362*579Sroot 	}
363*579Sroot 	let[nlet].adr = nextadr;	/* last plus 1 */
364*579Sroot }
365*579Sroot 
366*579Sroot copylet(n, f, type) FILE *f;
367*579Sroot {	int ch, k;
368*579Sroot 	fseek(tmpf, let[n].adr, 0);
369*579Sroot 	k = let[n+1].adr - let[n].adr;
370*579Sroot 	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')
371*579Sroot 		if(type!=ZAP) fputc(ch,f);
372*579Sroot 	if(type==REMOTE)
373*579Sroot 		fprintf(f, " remote from %s\n", thissys);
374*579Sroot 	else if (type==FORWARD)
375*579Sroot 		fprintf(f, forwmsg);
376*579Sroot 	else if(type==ORDINARY)
377*579Sroot 		fputc(ch,f);
378*579Sroot 	while(k-->1)
379*579Sroot 		fputc(ch=fgetc(tmpf), f);
380*579Sroot 	if(type!=ZAP || ch!= '\n')
381*579Sroot 		fputc(fgetc(tmpf), f);
382*579Sroot }
383*579Sroot 
384*579Sroot isfrom(lp)
385*579Sroot register char *lp;
386*579Sroot {
387*579Sroot 	register char *p;
388*579Sroot 
389*579Sroot 	for (p = from; *p; )
390*579Sroot 		if (*lp++ != *p++)
391*579Sroot 			return(0);
392*579Sroot 	return(1);
393*579Sroot }
394*579Sroot 
395*579Sroot sendmail(argc, argv)
396*579Sroot char **argv;
397*579Sroot {
398*579Sroot 	char truename[100];
399*579Sroot 	int first;
400*579Sroot 	register char *cp;
401*579Sroot 	int gaver = 0;
402*579Sroot # ifdef DELIVERMAIL
403*579Sroot 	char *newargv[1000];
404*579Sroot 	register char **ap;
405*579Sroot 	register char **vp;
406*579Sroot 	int dflag;
407*579Sroot 
408*579Sroot 	dflag = 0;
409*579Sroot 	if (argc < 1)
410*579Sroot 		fprintf(stderr, "puke\n");
411*579Sroot 	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)
412*579Sroot 	{
413*579Sroot 		if (ap[0][0] == '-' && ap[0][1] == 'd')
414*579Sroot 			dflag++;
415*579Sroot 	}
416*579Sroot 	if (!dflag)
417*579Sroot 	{
418*579Sroot 		/* give it to delivermail, rah rah! */
419*579Sroot 		unlink(lettmp);
420*579Sroot 		ap = newargv+1;
421*579Sroot 		if (rmail)
422*579Sroot 			*ap-- = "-s";
423*579Sroot 		*ap = "-delivermail";
424*579Sroot 		execv(DELIVERMAIL, ap);
425*579Sroot 		perror(DELIVERMAIL);
426*579Sroot 		exit(EX_UNAVAILABLE);
427*579Sroot 	}
428*579Sroot # endif DELIVERMAIL
429*579Sroot 
430*579Sroot 	truename[0] = 0;
431*579Sroot 	line[0] = '\0';
432*579Sroot 
433*579Sroot 	/*
434*579Sroot 	 * When we fall out of this, argv[1] should be first name,
435*579Sroot 	 * argc should be number of names + 1.
436*579Sroot 	 */
437*579Sroot 
438*579Sroot 	while (argc > 1 && *argv[1] == '-') {
439*579Sroot 		cp = *++argv;
440*579Sroot 		argc--;
441*579Sroot 		switch (cp[1]) {
442*579Sroot 		case 'r':
443*579Sroot 			if (argc <= 0) {
444*579Sroot 				usage();
445*579Sroot 				done();
446*579Sroot 			}
447*579Sroot 			gaver++;
448*579Sroot 			strcpy(truename, argv[1]);
449*579Sroot 			fgets(line, LSIZE, stdin);
450*579Sroot 			if (strcmpn("From", line, 4) == 0)
451*579Sroot 				line[0] = '\0';
452*579Sroot 			argv++;
453*579Sroot 			argc--;
454*579Sroot 			break;
455*579Sroot 
456*579Sroot 		case 'h':
457*579Sroot 			if (argc <= 0) {
458*579Sroot 				usage();
459*579Sroot 				done();
460*579Sroot 			}
461*579Sroot 			hseqno = atoi(argv[1]);
462*579Sroot 			argv++;
463*579Sroot 			argc--;
464*579Sroot 			break;
465*579Sroot 
466*579Sroot # ifdef DELIVERMAIL
467*579Sroot 		case 'd':
468*579Sroot 			break;
469*579Sroot # endif DELIVERMAIL
470*579Sroot 
471*579Sroot 		default:
472*579Sroot 			usage();
473*579Sroot 			done();
474*579Sroot 		}
475*579Sroot 	}
476*579Sroot 	if (argc <= 1) {
477*579Sroot 		usage();
478*579Sroot 		done();
479*579Sroot 	}
480*579Sroot 	if (gaver == 0)
481*579Sroot 		strcpy(truename, my_name);
482*579Sroot 	/*
483*579Sroot 	if (argc > 4 && strcmp(argv[1], "-r") == 0) {
484*579Sroot 		strcpy(truename, argv[2]);
485*579Sroot 		argc -= 2;
486*579Sroot 		argv += 2;
487*579Sroot 		fgets(line, LSIZE, stdin);
488*579Sroot 		if (strcmpn("From", line, 4) == 0)
489*579Sroot 			line[0] = '\0';
490*579Sroot 	} else
491*579Sroot 		strcpy(truename, my_name);
492*579Sroot 	*/
493*579Sroot 	time(&iop);
494*579Sroot 	fprintf(tmpf, "%s%s %s", from, truename, ctime(&iop));
495*579Sroot 	iop = ftell(tmpf);
496*579Sroot 	flgf = 1;
497*579Sroot 	for (first = 1;; first = 0) {
498*579Sroot 		if (first && line[0] == '\0' && fgets(line, LSIZE, stdin) == NULL)
499*579Sroot 			break;
500*579Sroot 		if (!first && fgets(line, LSIZE, stdin) == NULL)
501*579Sroot 			break;
502*579Sroot 		if (line[0] == '.' && line[1] == '\n' && isatty(fileno(stdin)))
503*579Sroot 			break;
504*579Sroot 		if (isfrom(line))
505*579Sroot 			fputs(">", tmpf);
506*579Sroot 		fputs(line, tmpf);
507*579Sroot 		flgf = 0;
508*579Sroot 	}
509*579Sroot 	fputs("\n", tmpf);
510*579Sroot 	nlet = 1;
511*579Sroot 	let[0].adr = 0;
512*579Sroot 	let[1].adr = ftell(tmpf);
513*579Sroot 	fclose(tmpf);
514*579Sroot 	if (flgf)
515*579Sroot 		return;
516*579Sroot 	tmpf = fopen(lettmp, "r");
517*579Sroot 	if (tmpf == NULL) {
518*579Sroot 		fprintf(stderr, "mail: cannot reopen %s for reading\n", lettmp);
519*579Sroot 		return;
520*579Sroot 	}
521*579Sroot 	while (--argc > 0)
522*579Sroot 		if (!send(0, *++argv, truename))
523*579Sroot 			error++;
524*579Sroot 	if (error) {
525*579Sroot 		setuid(getuid());
526*579Sroot 		malf = fopen(dead, "w");
527*579Sroot 		if (malf == NULL) {
528*579Sroot 			fprintf(stdout, "mail: cannot open %s\n", dead);
529*579Sroot 			fclose(tmpf);
530*579Sroot 			return;
531*579Sroot 		}
532*579Sroot 		copylet(0, malf, ZAP);
533*579Sroot 		fclose(malf);
534*579Sroot 		fprintf(stdout, "Mail saved in %s\n", dead);
535*579Sroot 	}
536*579Sroot 	fclose(tmpf);
537*579Sroot }
538*579Sroot 
539*579Sroot sendrmt(n, name, rcmd)
540*579Sroot char *name;
541*579Sroot char *rcmd;
542*579Sroot {
543*579Sroot 	FILE *rmf, *popen();
544*579Sroot 	register char *p;
545*579Sroot 	char rsys[64], cmd[64];
546*579Sroot 	register local, pid;
547*579Sroot 	int sts;
548*579Sroot 
549*579Sroot 	local = 0;
550*579Sroot 	if (index(name, '^')) {
551*579Sroot 		while (p = index(name, '^'))
552*579Sroot 			*p = '!';
553*579Sroot 		if (strncmp(name, "researc", 7)) {
554*579Sroot 			strcpy(rsys, "research");
555*579Sroot 			if (*name != '!')
556*579Sroot 				--name;
557*579Sroot 			goto skip;
558*579Sroot 		}
559*579Sroot 	}
560*579Sroot 	if (*name=='!')
561*579Sroot 		name++;
562*579Sroot 	for(p=rsys; *name!='!'; *p++ = *name++)
563*579Sroot 		if (*name=='\0') {
564*579Sroot 			local++;
565*579Sroot 			break;
566*579Sroot 		}
567*579Sroot 	*p = '\0';
568*579Sroot 	if ((!local && *name=='\0') || (local && *rsys=='\0')) {
569*579Sroot 		fprintf(stdout, "null name\n");
570*579Sroot 		return(0);
571*579Sroot 	}
572*579Sroot skip:
573*579Sroot 	if ((pid = fork()) == -1) {
574*579Sroot 		fprintf(stderr, "mail: can't create proc for remote\n");
575*579Sroot 		return(0);
576*579Sroot 	}
577*579Sroot 	if (pid) {
578*579Sroot 		while (wait(&sts) != pid) {
579*579Sroot 			if (wait(&sts)==-1)
580*579Sroot 				return(0);
581*579Sroot 		}
582*579Sroot 		return(!sts);
583*579Sroot 	}
584*579Sroot 	setuid(getuid());
585*579Sroot 	if (local)
586*579Sroot 		sprintf(cmd, "%s %s", rcmd, rsys);
587*579Sroot 	else {
588*579Sroot 		if (index(name+1, '!'))
589*579Sroot 			sprintf(cmd, "uux - %s!rmail \\(%s\\)", rsys, name+1);
590*579Sroot 		else
591*579Sroot 			sprintf(cmd, "uux - %s!rmail %s", rsys, name+1);
592*579Sroot 	}
593*579Sroot 	if ((rmf=popen(cmd, "w")) == NULL)
594*579Sroot 		exit(1);
595*579Sroot 	copylet(n, rmf, local ? !strcmp(rcmd, "/bin/mail") ? FORWARD : ORDINARY : REMOTE);
596*579Sroot 	pclose(rmf);
597*579Sroot 	exit(0);
598*579Sroot }
599*579Sroot 
600*579Sroot /*
601*579Sroot  * Send mail on the Berkeley network.
602*579Sroot  * Sorry Bill, sendrmt() is so awful we just gave up.
603*579Sroot  */
604*579Sroot 
605*579Sroot sendberkmail(n, name, fromaddr)
606*579Sroot 	char name[];
607*579Sroot 	char fromaddr[];
608*579Sroot {
609*579Sroot 	char cmd[200];
610*579Sroot 	register FILE *cmdf;
611*579Sroot 
612*579Sroot 	sprintf(cmd, "%s -h %d -f %s -t %s", RMAIL, hseqno, fromaddr, name);
613*579Sroot 	if ((cmdf = popen(cmd, "w")) == NULL) {
614*579Sroot 		perror(RMAIL);
615*579Sroot 		return(0);
616*579Sroot 	}
617*579Sroot 	copylet(n, cmdf, ORDINARY);
618*579Sroot 	pclose(cmdf);
619*579Sroot 	return(9);
620*579Sroot }
621*579Sroot 
622*579Sroot usage()
623*579Sroot {
624*579Sroot 
625*579Sroot 	fprintf(stderr, "Usage: mail [ -f ] people . . .\n");
626*579Sroot }
627*579Sroot 
628*579Sroot send(n, name, fromaddr)
629*579Sroot int n;
630*579Sroot char *name;
631*579Sroot char *fromaddr;
632*579Sroot {
633*579Sroot 	char file[100];
634*579Sroot 	register char *p;
635*579Sroot 	register mask;
636*579Sroot 	struct passwd *pw, *getpwnam();
637*579Sroot 	struct stat statb;
638*579Sroot 
639*579Sroot 	stripfx(LOCNAM1, &name);
640*579Sroot 	stripfx(LOCNAM2, &name);
641*579Sroot 	stripfx(LOCNAM3, &name);
642*579Sroot 	stripfx(LOCNAM4, &name);
643*579Sroot 	if(*name == ':')name++;		/* skip colon in to-name */
644*579Sroot 	for(p=name; *p!=':' &&*p!='\0'; p++);
645*579Sroot 	/* if(*p == ':') return(sendrmt(n, name, RMAIL)); */
646*579Sroot 	if (*p == ':')
647*579Sroot 		return(sendberkmail(n, name, fromaddr));
648*579Sroot 	else if (strcmp(name, "msgs") == 0) return(sendrmt(n, "-s", "/usr/ucb/msgs"));
649*579Sroot 	for(p=name; *p!='!'&&*p!='^' &&*p!='\0'; p++)
650*579Sroot 		;
651*579Sroot 	if (*p == '!'|| *p=='^')
652*579Sroot 		return(sendrmt(n, name, 0));
653*579Sroot 	if ((pw = getpwnam(name)) == NULL) {
654*579Sroot 		fprintf(stdout, "mail: can't send to %s\n", name);
655*579Sroot 		return(0);
656*579Sroot 	}
657*579Sroot 	cat(file, maildir, name);
658*579Sroot 	if (stat(file, &statb) >= 0 && (statb.st_mode & S_IFMT) == S_IFDIR) {
659*579Sroot 		strcat(file, "/");
660*579Sroot 		strcat(file, name);
661*579Sroot 	}
662*579Sroot 	mask = umask(MAILMODE);
663*579Sroot 	malf = fopen(file, "a");
664*579Sroot 	umask(mask);
665*579Sroot 	if (malf == NULL) {
666*579Sroot 		fprintf(stdout, "mail: cannot append to %s\n", file);
667*579Sroot 		return(0);
668*579Sroot 	}
669*579Sroot 	lock(file);
670*579Sroot 	chown(file, pw->pw_uid, pw->pw_gid);
671*579Sroot 	copylet(n, malf, ORDINARY);
672*579Sroot 	fclose(malf);
673*579Sroot 	unlock();
674*579Sroot 	return(1);
675*579Sroot }
676*579Sroot 
677*579Sroot delete(i)
678*579Sroot {
679*579Sroot 	setsig(i, delete);
680*579Sroot 	fprintf(stderr, "\n");
681*579Sroot 	if(delflg)
682*579Sroot 		longjmp(sjbuf, 1);
683*579Sroot 	done();
684*579Sroot }
685*579Sroot 
686*579Sroot /*
687*579Sroot  * Lock the specified mail file by setting the file mailfile.lock.
688*579Sroot  * We must, of course, be careful to unlink the lock file by a call
689*579Sroot  * to unlock before we stop.  The algorithm used here is to see if
690*579Sroot  * the lock exists, and if it does, to check its modify time.  If it
691*579Sroot  * is older than 30 seconds, we assume error and set our own file.
692*579Sroot  * Otherwise, we wait for 5 seconds and try again.
693*579Sroot  */
694*579Sroot 
695*579Sroot char	*maillock	= ".lock";		/* Lock suffix for mailname */
696*579Sroot char	*lockname	= "/usr/spool/mail/tmXXXXXX";
697*579Sroot char	locktmp[30];				/* Usable lock temporary */
698*579Sroot char	curlock[50];				/* Last used name of lock */
699*579Sroot int	locked;					/* To note that we locked it */
700*579Sroot 
701*579Sroot lock(file)
702*579Sroot char *file;
703*579Sroot {
704*579Sroot 	register int f;
705*579Sroot 	struct stat sbuf;
706*579Sroot 	long curtime;
707*579Sroot 	int statfailed;
708*579Sroot 
709*579Sroot 	if (locked || flgf)
710*579Sroot 		return(0);
711*579Sroot 	strcpy(curlock, file);
712*579Sroot 	strcat(curlock, maillock);
713*579Sroot 	strcpy(locktmp, lockname);
714*579Sroot 	mktemp(locktmp);
715*579Sroot 	unlink(locktmp);
716*579Sroot 	statfailed = 0;
717*579Sroot 	for (;;) {
718*579Sroot 		f = lock1(locktmp, curlock);
719*579Sroot 		if (f == 0) {
720*579Sroot 			locked = 1;
721*579Sroot 			return(0);
722*579Sroot 		}
723*579Sroot 		if (stat(curlock, &sbuf) < 0) {
724*579Sroot 			if (statfailed++ > 5)
725*579Sroot 				return(-1);
726*579Sroot 			sleep(5);
727*579Sroot 			continue;
728*579Sroot 		}
729*579Sroot 		statfailed = 0;
730*579Sroot 		time(&curtime);
731*579Sroot 		if (curtime < sbuf.st_ctime + 30) {
732*579Sroot 			sleep(5);
733*579Sroot 			continue;
734*579Sroot 		}
735*579Sroot 		unlink(curlock);
736*579Sroot 	}
737*579Sroot }
738*579Sroot 
739*579Sroot /*
740*579Sroot  * Remove the mail lock, and note that we no longer
741*579Sroot  * have it locked.
742*579Sroot  */
743*579Sroot 
744*579Sroot unlock()
745*579Sroot {
746*579Sroot 
747*579Sroot 	unlink(curlock);
748*579Sroot 	locked = 0;
749*579Sroot }
750*579Sroot 
751*579Sroot /*
752*579Sroot  * Attempt to set the lock by creating the temporary file,
753*579Sroot  * then doing a link/unlink.  If it fails, return -1 else 0
754*579Sroot  */
755*579Sroot 
756*579Sroot lock1(tempfile, name)
757*579Sroot 	char tempfile[], name[];
758*579Sroot {
759*579Sroot 	register int fd;
760*579Sroot 
761*579Sroot 	fd = creat(tempfile, 0);
762*579Sroot 	if (fd < 0)
763*579Sroot 		return(-1);
764*579Sroot 	close(fd);
765*579Sroot 	if (link(tempfile, name) < 0) {
766*579Sroot 		unlink(tempfile);
767*579Sroot 		return(-1);
768*579Sroot 	}
769*579Sroot 	unlink(tempfile);
770*579Sroot 	return(0);
771*579Sroot }
772*579Sroot 
773*579Sroot done()
774*579Sroot {
775*579Sroot 	if(locked)
776*579Sroot 		unlock();
777*579Sroot 	unlink(lettmp);
778*579Sroot 	unlink(locktmp);
779*579Sroot 	exit(error);
780*579Sroot }
781*579Sroot 
782*579Sroot cat(to, from1, from2)
783*579Sroot char *to, *from1, *from2;
784*579Sroot {
785*579Sroot 	int i, j;
786*579Sroot 
787*579Sroot 	j = 0;
788*579Sroot 	for (i=0; from1[i]; i++)
789*579Sroot 		to[j++] = from1[i];
790*579Sroot 	for (i=0; from2[i]; i++)
791*579Sroot 		to[j++] = from2[i];
792*579Sroot 	to[j] = 0;
793*579Sroot }
794*579Sroot 
795*579Sroot char *getarg(s, p)	/* copy p... into s, update p */
796*579Sroot register char *s, *p;
797*579Sroot {
798*579Sroot 	while (*p == ' ' || *p == '\t')
799*579Sroot 		p++;
800*579Sroot 	if (*p == '\n' || *p == '\0')
801*579Sroot 		return(NULL);
802*579Sroot 	while (*p != ' ' && *p != '\t' && *p != '\n' && *p != '\0')
803*579Sroot 		*s++ = *p++;
804*579Sroot 	*s = '\0';
805*579Sroot 	return(p);
806*579Sroot }
807*579Sroot /*
808*579Sroot 	stripfx(prefix string, pointer to string)
809*579Sroot 
810*579Sroot 	takes a ptr to string and compares it to prefix string.
811*579Sroot 	may be called multiple times
812*579Sroot */
813*579Sroot stripfx(pfx, name)
814*579Sroot 	char *pfx;
815*579Sroot 	char **name;
816*579Sroot {
817*579Sroot 	register char *cp = *name;
818*579Sroot 
819*579Sroot 	while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
820*579Sroot 		cp++, pfx++;
821*579Sroot 	if (*cp != ':' || *pfx != 0)
822*579Sroot 		return;
823*579Sroot 	*name = cp;
824*579Sroot }
825