xref: /csrg-svn/old/berknet/v6mail.c (revision 8208)
1*8208Smckusick static char sccsid[] = "@(#)v6mail.c	4.1	(Berkeley)	09/12/82";
2*8208Smckusick 
3*8208Smckusick /*
4*8208Smckusick  * Version 6 Cory mail--
5*8208Smckusick  *	a clean and simple mail program
6*8208Smckusick  *	machine and version independent
7*8208Smckusick  *		Eric Schmidt
8*8208Smckusick  *	must run as setuid root to chown the destination mailbox
9*8208Smckusick  *	if NOTROOT defined, doesn't need to run as root
10*8208Smckusick  *
11*8208Smckusick  *	DON'T CHANGE THIS CODE
12*8208Smckusick  *		bitch to "csvax:schmidt" instead
13*8208Smckusick  */
14*8208Smckusick 
15*8208Smckusick /*
16*8208Smckusick  * mail command usage
17*8208Smckusick  *	mail [-yn]
18*8208Smckusick  *		prints your mail
19*8208Smckusick  *	mail people
20*8208Smckusick  *		sends standard input to people
21*8208Smckusick  *
22*8208Smckusick  *	mail -r fromaddr people
23*8208Smckusick  *		sends mail from the network
24*8208Smckusick  *
25*8208Smckusick  *	mail -d people
26*8208Smckusick  *		don't call delivermail, send mail directly
27*8208Smckusick  *	mail msgs
28*8208Smckusick  *		send to "msgs"
29*8208Smckusick  *	mail filename
30*8208Smckusick  *		mail to filename instead of user (must be at least one /)
31*8208Smckusick  *	mail -D
32*8208Smckusick  *		delete the invokers mailbox (more efficient than
33*8208Smckusick  *			mail -n >/dev/null)
34*8208Smckusick  */
35*8208Smckusick 
36*8208Smckusick /*
37*8208Smckusick  *	bugs:
38*8208Smckusick  *		Ingres 11/70 multiple names/uid?
39*8208Smckusick  *	additions:
40*8208Smckusick  *		Save? type 'x' - doesn't unlink the mail file
41*8208Smckusick  */
42*8208Smckusick /*
43*8208Smckusick  * BIFF is an immediate notification flag using the MPX stuff
44*8208Smckusick  */
45*8208Smckusick # include "local.h"
46*8208Smckusick # include <stdio.h>
47*8208Smckusick # include "mach.h"
48*8208Smckusick 
49*8208Smckusick # ifdef RAND
50*8208Smckusick 
51*8208Smckusick /* for all machines at RAND */
52*8208Smckusick # define MAILMODE 0644
53*8208Smckusick 
54*8208Smckusick # endif RAND
55*8208Smckusick 
56*8208Smckusick # ifdef NOSC
57*8208Smckusick 
58*8208Smckusick /* for all machines at NOSC */
59*8208Smckusick # define MAILMODE 0644
60*8208Smckusick 
61*8208Smckusick # endif NOSC
62*8208Smckusick 
63*8208Smckusick # ifdef BERKELEY
64*8208Smckusick /* for Berkeley */
65*8208Smckusick /* for each machine */
66*8208Smckusick /* lump the CC machines into one */
67*8208Smckusick # ifdef CCV7
68*8208Smckusick # define MAILMODE 0600
69*8208Smckusick # define MSGSCMD "/usr/ucb/bin/msgs"
70*8208Smckusick # endif
71*8208Smckusick 
72*8208Smckusick # ifdef CCV6
73*8208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs"
74*8208Smckusick # define MAILMODE 0600
75*8208Smckusick # endif
76*8208Smckusick 
77*8208Smckusick # ifdef ING70
78*8208Smckusick # define MAILMODE 0666
79*8208Smckusick # define MSGSCMD "/usr/bin/msgs"
80*8208Smckusick # define NOTROOT
81*8208Smckusick # endif
82*8208Smckusick 
83*8208Smckusick # ifdef INGVAX
84*8208Smckusick # define MAILMODE 0644
85*8208Smckusick # define MSGSCMD "/usr/ucb/msgs"
86*8208Smckusick # endif
87*8208Smckusick 
88*8208Smckusick /*
89*8208Smckusick # ifdef VIRUS
90*8208Smckusick # define MAILMODE 0644
91*8208Smckusick # define MSGSCMD "/usr/bin/msgs"
92*8208Smckusick # endif
93*8208Smckusick */
94*8208Smckusick 
95*8208Smckusick # ifdef UCBVAX
96*8208Smckusick # define MAILMODE 0644
97*8208Smckusick # define MSGSCMD "/usr/ucb/msgs"
98*8208Smckusick # define BIFF
99*8208Smckusick # endif
100*8208Smckusick 
101*8208Smckusick # ifdef IMAGE
102*8208Smckusick # define MAILMODE 0644
103*8208Smckusick # define MSGSCMD "/usr/bin/msgs"
104*8208Smckusick # endif
105*8208Smckusick 
106*8208Smckusick # ifdef KIM
107*8208Smckusick # define MAILMODE 0644
108*8208Smckusick # define MSGSCMD "/usr/ucb/msgs"
109*8208Smckusick # endif
110*8208Smckusick 
111*8208Smckusick # ifdef ESVAX
112*8208Smckusick # define MAILMODE 0644
113*8208Smckusick # define MSGSCMD "/usr/ucb/msgs"
114*8208Smckusick # endif
115*8208Smckusick 
116*8208Smckusick # ifdef Q
117*8208Smckusick # define MAILMODE 0600
118*8208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs"
119*8208Smckusick # endif
120*8208Smckusick 
121*8208Smckusick # ifdef ARPAVAX
122*8208Smckusick # define MAILMODE 0644
123*8208Smckusick # define MSGSCMD "/usr/ucb/msgs"
124*8208Smckusick # define BIFF
125*8208Smckusick # endif
126*8208Smckusick 
127*8208Smckusick # ifdef SRC
128*8208Smckusick # define MAILMODE 0600
129*8208Smckusick # define MSGSCMD "/usr/bin/msgs"
130*8208Smckusick # endif
131*8208Smckusick 
132*8208Smckusick # ifdef MATHSTAT
133*8208Smckusick # define MAILMODE 0600
134*8208Smckusick # define MSGSCMD "/usr/bin/msgs"
135*8208Smckusick # endif
136*8208Smckusick 
137*8208Smckusick # ifdef CSVAX
138*8208Smckusick # define MAILMODE 0644
139*8208Smckusick # define MSGSCMD "/usr/ucb/msgs"
140*8208Smckusick # define BIFF
141*8208Smckusick # endif
142*8208Smckusick 
143*8208Smckusick # ifdef ONYX
144*8208Smckusick # define MAILMODE 0644
145*8208Smckusick # define MSGSCMD "/usr/ucb/bin/msgs"
146*8208Smckusick # endif
147*8208Smckusick 
148*8208Smckusick # ifdef CORY
149*8208Smckusick # define MAILMODE 0600
150*8208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs"
151*8208Smckusick # endif
152*8208Smckusick 
153*8208Smckusick # ifdef EECS40
154*8208Smckusick # define MAILMODE 0644
155*8208Smckusick # define MSGSCMD "/usr/bin/msgs"
156*8208Smckusick # endif
157*8208Smckusick /* end of berkeley defsn */
158*8208Smckusick 
159*8208Smckusick # endif
160*8208Smckusick /* end of per-machine ifdefs */
161*8208Smckusick 
162*8208Smckusick # ifdef USRMAIL
163*8208Smckusick # define MAILDIR "/usr/mail"
164*8208Smckusick # else
165*8208Smckusick # define MAILDIR "/usr/spool/mail"
166*8208Smckusick # endif
167*8208Smckusick 
168*8208Smckusick char	lettmp[]  = "/tmp/MaXXXXX";	/* keep letter before sending it */
169*8208Smckusick char	preptmp[] = "/tmp/mbXXXXX";	/* if prepending msg, use this file */
170*8208Smckusick int	chew;				/* if true, strip extra from lines */
171*8208Smckusick int	dflag;				/* if true, don't call delivermail */
172*8208Smckusick char	shopcnt[30] = "0";		/* hop count parameter for rmt mail */
173*8208Smckusick int	errs;				/* no of errs in sending */
174*8208Smckusick char	deleteonly;			/* if true, just delete mailbox */
175*8208Smckusick char 	remname[50];			/* if non-empty, from line extra */
176*8208Smckusick 
177*8208Smckusick char _sobuf[BUFSIZ];
178*8208Smckusick main(argc, argv)
179*8208Smckusick char **argv;
180*8208Smckusick {
181*8208Smckusick 	register int myuid;
182*8208Smckusick 	int delexit();
183*8208Smckusick 	char namebuf[128], *sn = NULL, logindir[60];
184*8208Smckusick 	struct passwd *pwd;
185*8208Smckusick 
186*8208Smckusick 	setbuf(stdout,_sobuf);
187*8208Smckusick 	mktemp(lettmp);
188*8208Smckusick 	mktemp(preptmp);
189*8208Smckusick 	unlink(lettmp);
190*8208Smckusick 	unlink(preptmp);
191*8208Smckusick 	myuid = getuid();
192*8208Smckusick 	logindir[0] = 0;
193*8208Smckusick 	sn = getlogin();
194*8208Smckusick 	if(sn == NULL || *sn == 0 || *sn == ' '){
195*8208Smckusick 		pwd = getpwuid(myuid);		/* will read passwd file */
196*8208Smckusick 		if(pwd != NULL){
197*8208Smckusick 			sn = pwd->pw_name;
198*8208Smckusick 			strcpy(logindir,pwd->pw_dir);
199*8208Smckusick 		}
200*8208Smckusick 		if(sn == NULL){
201*8208Smckusick 			fprintf(stderr,"Who are you?\n");
202*8208Smckusick 			delexit(EX_OSFILE);
203*8208Smckusick 		}
204*8208Smckusick 	}
205*8208Smckusick 	strcpy(namebuf,sn);
206*8208Smckusick 	if (argc < 2)
207*8208Smckusick 		goto hitit;
208*8208Smckusick 	for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
209*8208Smckusick 	switch(argv[0][1]) {
210*8208Smckusick 		case 'y':
211*8208Smckusick 		case 'n':
212*8208Smckusick 			argc++, argv--;
213*8208Smckusick hitit:
214*8208Smckusick 			printmail(argc, argv, namebuf,logindir);
215*8208Smckusick 			delexit(EX_OK);
216*8208Smckusick 
217*8208Smckusick 		case 'r':	/* one-arg -r--   -r addr */
218*8208Smckusick 			if (argc < 2)
219*8208Smckusick 				continue;
220*8208Smckusick 			/* ignore -r if not network or root */
221*8208Smckusick 			if (strcmp("network", namebuf) == 0 || myuid == 0 ||
222*8208Smckusick 			    strcmp("uucp", namebuf) == 0 || index(argv[1], '!') != NULL) {
223*8208Smckusick 				strcpy(namebuf,argv[1]);
224*8208Smckusick 				chew++;		/* eat From lines */
225*8208Smckusick 			}
226*8208Smckusick 			else strcpy(remname, argv[1]);
227*8208Smckusick 			argc--, argv++;
228*8208Smckusick 			continue;
229*8208Smckusick 		case 'h':	/* hop count - used by network */
230*8208Smckusick 			if(argc < 2) continue;
231*8208Smckusick 			strcpy(shopcnt,argv[1]);
232*8208Smckusick 			argc--, argv++;
233*8208Smckusick 			continue;
234*8208Smckusick 		case 'd':	/* really deliver this message */
235*8208Smckusick 			dflag++;
236*8208Smckusick 			continue;
237*8208Smckusick 		case 'D':	/* only delete the invokers mailbox */
238*8208Smckusick 			deleteonly++;
239*8208Smckusick 			goto hitit;		/* delete mail box, thats all */
240*8208Smckusick 	}
241*8208Smckusick 	/* if we are already ignoring signals, catch sigint */
242*8208Smckusick 	if(signal(SIGINT,SIG_IGN) != SIG_IGN)
243*8208Smckusick 		signal(SIGINT, delexit);
244*8208Smckusick 	argc++, argv--;
245*8208Smckusick 	bulkmail(argc, argv, namebuf);
246*8208Smckusick 	delexit(EX_OK);
247*8208Smckusick }
248*8208Smckusick 
249*8208Smckusick printmail(argc, argv, name, logindir)
250*8208Smckusick char **argv;
251*8208Smckusick char *name, *logindir;
252*8208Smckusick {
253*8208Smckusick 	register int c;
254*8208Smckusick 	FILE *fdin;
255*8208Smckusick 	char sfnmail[60], mbox[120];
256*8208Smckusick 	struct stat statbuf;
257*8208Smckusick 
258*8208Smckusick # ifdef OLDMAIL
259*8208Smckusick 	if(logindir[0] == 0){
260*8208Smckusick 		pwd = getpwuid(getuid());
261*8208Smckusick 		if(pwd == NULL){
262*8208Smckusick 			fprintf(stderr,"Can't get directory\n");
263*8208Smckusick 			exit(EX_OSFILE);
264*8208Smckusick 		}
265*8208Smckusick 		strcpy(logindir, pwd->pw_dir);
266*8208Smckusick 	}
267*8208Smckusick 	sprintf(sfnmail,"%s/.mail",logindir);
268*8208Smckusick # else
269*8208Smckusick 	sprintf(sfnmail,"%s/%s",MAILDIR,name);
270*8208Smckusick # endif
271*8208Smckusick 	if(deleteonly){
272*8208Smckusick 		remove(sfnmail);
273*8208Smckusick 		return;
274*8208Smckusick 	}
275*8208Smckusick 	if (stat(sfnmail, &statbuf)>=0 && statbuf.st_nlink==1 &&
276*8208Smckusick 		getsize(&statbuf) > 0L && (fdin = fopen(sfnmail, "r")) != NULL){
277*8208Smckusick 		getput(fdin, stdout);
278*8208Smckusick 		fclose(fdin);
279*8208Smckusick 		fflush(stdout);
280*8208Smckusick 		c = 'y';
281*8208Smckusick 		if (argc<2) {
282*8208Smckusick 			if(isatty(0)){
283*8208Smckusick 				printf("Save(y-n) ?");
284*8208Smckusick 				fflush(stdout);
285*8208Smckusick 				c = getchar();
286*8208Smckusick 			}
287*8208Smckusick 		} else
288*8208Smckusick 			c = argv[1][1];
289*8208Smckusick 		if (!any(c, "xyn"))
290*8208Smckusick 			delexit(EX_OK);
291*8208Smckusick 		if (c == 'y') {
292*8208Smckusick 			sprintf(mbox,"%s/mbox",logindir);
293*8208Smckusick 			if (accesss(mbox)) {
294*8208Smckusick 				printf("Saved mail in 'mbox'\n");
295*8208Smckusick 				if(insert(sfnmail, mbox, getuid(),getgid()))
296*8208Smckusick 					remove(sfnmail);
297*8208Smckusick 			}
298*8208Smckusick 			else printf("In wrong directory\n");
299*8208Smckusick 		}
300*8208Smckusick 		else if(c != 'x') remove(sfnmail);
301*8208Smckusick 	} else
302*8208Smckusick 		printf("No mail.\n");
303*8208Smckusick }
304*8208Smckusick 
305*8208Smckusick bulkmail(argc, argv, from)
306*8208Smckusick char **argv, *from;
307*8208Smckusick {
308*8208Smckusick 	extern int errno;
309*8208Smckusick 	char linebuf[BUFSIZ];
310*8208Smckusick 	char *getdate();
311*8208Smckusick 	FILE *fdout;
312*8208Smckusick 
313*8208Smckusick # ifdef DELIVERM
314*8208Smckusick 	/*
315*8208Smckusick 	**  Ship off to delivermail if appropriate (and possible)
316*8208Smckusick 	*/
317*8208Smckusick 
318*8208Smckusick 	if (!dflag)
319*8208Smckusick 	{
320*8208Smckusick 		argv[0] = "-delivermail";
321*8208Smckusick 		argv[argc] = 0;
322*8208Smckusick 		execv("/etc/delivermail", argv);
323*8208Smckusick 		/* oops...  better just deliver it. */
324*8208Smckusick 		fprintf(stderr, "Not using delivermail\n");
325*8208Smckusick 		errno = 0;
326*8208Smckusick 		argv[argc] = (char *)-1;
327*8208Smckusick 	}
328*8208Smckusick # endif
329*8208Smckusick 
330*8208Smckusick 	fdout = fopen(lettmp, "w");
331*8208Smckusick 	if (fdout == NULL) {
332*8208Smckusick 		perror(lettmp);
333*8208Smckusick 		delexit(EX_OSFILE);
334*8208Smckusick 	}
335*8208Smckusick 	/*
336*8208Smckusick 	 * If delivering mail from the network via mail -r,
337*8208Smckusick 	 * Strip the leading line and throw it away, as long
338*8208Smckusick 	 * as it begins with "From ..." (and preserve the date if poss.)
339*8208Smckusick 	 */
340*8208Smckusick 	if (chew) {
341*8208Smckusick 		fgets(linebuf,BUFSIZ,stdin);
342*8208Smckusick 		if(strncmp(linebuf,"From ",5) != 0){
343*8208Smckusick 			fline(fdout,NULL,from);
344*8208Smckusick 			fprintf(fdout,"%s", linebuf);
345*8208Smckusick 		}
346*8208Smckusick 		else fline(fdout,getdate(linebuf),from);
347*8208Smckusick 	}
348*8208Smckusick 	else fline(fdout,NULL,from);
349*8208Smckusick 	if(remname[0]) fprintf(fdout,"(from %s)\n",remname);
350*8208Smckusick 
351*8208Smckusick 	/* on the image machine, promt with subj */
352*8208Smckusick 	if(getput(stdin,fdout) == 0)
353*8208Smckusick 		delexit(EX_OSERR);
354*8208Smckusick 	putc('\n',fdout);
355*8208Smckusick 	fclose(fdout);
356*8208Smckusick 	while (--argc > 0)
357*8208Smckusick 		sendto(*++argv,from);
358*8208Smckusick 	delexit(errs);
359*8208Smckusick }
360*8208Smckusick /* print from line, with date date, if date = NULL, compute it */
361*8208Smckusick fline(fdout,date,from)
362*8208Smckusick FILE *fdout;
363*8208Smckusick char *date;
364*8208Smckusick char *from;
365*8208Smckusick {
366*8208Smckusick 	int tbuf[2];
367*8208Smckusick 
368*8208Smckusick 	if(date == NULL){
369*8208Smckusick 		time(tbuf);
370*8208Smckusick 		date = ctime(tbuf);
371*8208Smckusick 	}
372*8208Smckusick 	fprintf(fdout,"From %s  %s", from, date);
373*8208Smckusick }
374*8208Smckusick /* look over linebuf and return ptr to date, NULL if error */
375*8208Smckusick char *getdate(linebuf)
376*8208Smckusick char *linebuf;
377*8208Smckusick {
378*8208Smckusick 	register char *s;
379*8208Smckusick 	s = linebuf;
380*8208Smckusick 	while(*s){
381*8208Smckusick 		if(strncmp(s," Sun ",5) == 0
382*8208Smckusick 		|| strncmp(s," Mon ",5) == 0
383*8208Smckusick 		|| strncmp(s," Tue ",5) == 0
384*8208Smckusick 		|| strncmp(s," Wed ",5) == 0
385*8208Smckusick 		|| strncmp(s," Thu ",5) == 0
386*8208Smckusick 		|| strncmp(s," Fri ",5) == 0
387*8208Smckusick 		|| strncmp(s," Sat ",5) == 0)
388*8208Smckusick 			return(++s);
389*8208Smckusick 		s++;
390*8208Smckusick 	}
391*8208Smckusick 	return(NULL);
392*8208Smckusick }
393*8208Smckusick 
394*8208Smckusick sendto(person, fromaddr)
395*8208Smckusick char *person;
396*8208Smckusick char *fromaddr;
397*8208Smckusick {
398*8208Smckusick 	static int saved = 0;
399*8208Smckusick 	register int hisuid, hisgid;
400*8208Smckusick 	char sfnmail[60], logindir[60];
401*8208Smckusick 	struct passwd *pwd;
402*8208Smckusick 
403*8208Smckusick 	stripmach(&person);
404*8208Smckusick 	if(person[0] == ':')person++;
405*8208Smckusick 	/* delivermail provides these services */
406*8208Smckusick 	if(any(':',person)
407*8208Smckusick # ifdef MSGSCMD
408*8208Smckusick 		|| strcmp(person,"msgs") == 0
409*8208Smckusick # endif
410*8208Smckusick 		){
411*8208Smckusick 		int pid;
412*8208Smckusick 		int pidchild;
413*8208Smckusick 
414*8208Smckusick 		while((pid = fork()) == -1)sleep(2);
415*8208Smckusick 		if (pid < 0) {
416*8208Smckusick 			perror("fork");
417*8208Smckusick 			goto assback;
418*8208Smckusick 		}
419*8208Smckusick 		if (pid == 0) {
420*8208Smckusick 			fclose(stdin);
421*8208Smckusick 			freopen(lettmp,"r",stdin);
422*8208Smckusick 			setuid(getuid());	/* insure no security hole*/
423*8208Smckusick 			if (strcmp(person,"msgs") != 0) {
424*8208Smckusick 				/*
425*8208Smckusick 				sendberkmail will add the machine, e.g.
426*8208Smckusick 				CSVAX:schmidt, if the -f flag is not set
427*8208Smckusick 				*/
428*8208Smckusick 				execl("/usr/net/bin/sendberkmail",
429*8208Smckusick 				"sendberkmail", "-t",person,"-h",shopcnt,
430*8208Smckusick 				chew ? "-f" : 0,fromaddr,0);
431*8208Smckusick 				perror("/usr/net/bin/sendberkmail");
432*8208Smckusick 			}
433*8208Smckusick # ifdef MSGSCMD
434*8208Smckusick 			else {
435*8208Smckusick 				execl(MSGSCMD, "msgs", "-s", 0);
436*8208Smckusick 				perror(MSGSCMD);
437*8208Smckusick 			}
438*8208Smckusick # endif
439*8208Smckusick 			exit(EX_UNAVAILABLE);
440*8208Smckusick 		}
441*8208Smckusick 		for (;;) {
442*8208Smckusick 			register int rcode = wait(&pidchild);
443*8208Smckusick 			if (rcode == -1)
444*8208Smckusick 				goto assback;
445*8208Smckusick 			if (rcode == pid)
446*8208Smckusick 				break;
447*8208Smckusick 		}
448*8208Smckusick 		if ((pidchild & 0377) != 0 || (pidchild >> 8) != 0)
449*8208Smckusick 			goto assback;
450*8208Smckusick 		return;
451*8208Smckusick 	}
452*8208Smckusick 
453*8208Smckusick 	if(!any('/',person)){
454*8208Smckusick 	/* if name has no / in it, we assume it is a user's name */
455*8208Smckusick # ifdef HPASSWD
456*8208Smckusick 		hisuid = uidfromsn(person);
457*8208Smckusick # else
458*8208Smckusick 		pwd = getpwnam(person);
459*8208Smckusick 		if(pwd != NULL){
460*8208Smckusick 			hisuid = guid(pwd->pw_uid,pwd->pw_gid);
461*8208Smckusick 			hisgid = pwd->pw_gid;
462*8208Smckusick 			strcpy(logindir,pwd->pw_dir);
463*8208Smckusick 		}
464*8208Smckusick 		else hisuid = -1;
465*8208Smckusick # endif
466*8208Smckusick 		if(hisuid == -1){
467*8208Smckusick 	assback:
468*8208Smckusick 			fflush(stdout);
469*8208Smckusick 			fprintf(stderr,"Can't send to %s.\n", person);
470*8208Smckusick 			errs++;
471*8208Smckusick 			if (isatty(0) && saved==0) {
472*8208Smckusick 				saved++;
473*8208Smckusick 				if (accesss("dead.letter")) {
474*8208Smckusick 					printf("Letter saved in 'dead.letter'\n");
475*8208Smckusick 					insert(lettmp, "dead.letter",
476*8208Smckusick 						getuid(),getgid());
477*8208Smckusick 				} else
478*8208Smckusick 					printf("In wrong directory\n");
479*8208Smckusick 			}
480*8208Smckusick 			return;
481*8208Smckusick 		}
482*8208Smckusick # ifdef OLDMAIL
483*8208Smckusick 		sprintf(sfnmail,"%s/.mail",logindir);
484*8208Smckusick # else
485*8208Smckusick 		sprintf(sfnmail,"%s/%s",MAILDIR,person);
486*8208Smckusick # endif
487*8208Smckusick 		lock(sfnmail);
488*8208Smckusick 		insert(lettmp, sfnmail, hisuid, hisgid);
489*8208Smckusick 		unlock();
490*8208Smckusick 		}
491*8208Smckusick 	else {		/* it has / in it, "person" is a file */
492*8208Smckusick 		if(accesss(person)){
493*8208Smckusick 			lock(person);
494*8208Smckusick 			insert(lettmp, person, -1, -1);
495*8208Smckusick 			unlock();
496*8208Smckusick 		}
497*8208Smckusick 		else
498*8208Smckusick 			fprintf(stderr,"Can't access %s\n",person);
499*8208Smckusick 	}
500*8208Smckusick }
501*8208Smckusick 
502*8208Smckusick /* return 1 if success, 0 otherwise */
503*8208Smckusick insert(from, to, uid, gid)
504*8208Smckusick char *from, *to;
505*8208Smckusick {
506*8208Smckusick # ifdef V6
507*8208Smckusick 	return(prepend(from,to,uid, gid));
508*8208Smckusick # else
509*8208Smckusick 	return(append(from,to,uid, gid));
510*8208Smckusick # endif
511*8208Smckusick }
512*8208Smckusick /* return 1 if success, 0 otherwise */
513*8208Smckusick append(from,to,uid, gid)
514*8208Smckusick char *from, *to;
515*8208Smckusick {
516*8208Smckusick 	register FILE *fdin, *fdout;
517*8208Smckusick 	int ret;
518*8208Smckusick 	struct stat statbuf;
519*8208Smckusick #ifdef BIFF
520*8208Smckusick /* biff ... */
521*8208Smckusick 	char *rindex();
522*8208Smckusick 	char *cp;
523*8208Smckusick 	char buf[100];
524*8208Smckusick 	int f;
525*8208Smckusick /* end biff */
526*8208Smckusick #endif BIFF
527*8208Smckusick 	if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) {
528*8208Smckusick 		fprintf(stderr, "Exotic destination %s\n", to);
529*8208Smckusick 		errs++;
530*8208Smckusick 		return(0);
531*8208Smckusick 	}
532*8208Smckusick 	if ((fdout = fopen(to, "a")) == NULL) {
533*8208Smckusick 		perror(to);
534*8208Smckusick 		errs++;
535*8208Smckusick 		return(0);
536*8208Smckusick 	}
537*8208Smckusick # ifndef NOTROOT
538*8208Smckusick 	if(uid != -1)mchown(to, uid, gid);
539*8208Smckusick # endif
540*8208Smckusick 	if(uid != -1)chmod(to, MAILMODE);
541*8208Smckusick 	if ((fdin = fopen(from, "r")) == NULL) {
542*8208Smckusick 		perror(from);
543*8208Smckusick 		return(0);
544*8208Smckusick 	}
545*8208Smckusick #ifdef BIFF
546*8208Smckusick 	{
547*8208Smckusick 		f = open("/dev/mail", 1);
548*8208Smckusick 		cp = rindex(to, '/');
549*8208Smckusick 		if (cp) {
550*8208Smckusick 			sprintf(buf, "%s@%d\n", cp+1, ftell(fdout));
551*8208Smckusick 		}
552*8208Smckusick 	}
553*8208Smckusick #endif BIFF
554*8208Smckusick 	ret = getput(fdin,fdout);
555*8208Smckusick 	fclose(fdin);
556*8208Smckusick 	fclose(fdout);
557*8208Smckusick #ifdef BIFF
558*8208Smckusick 	if (cp && f >= 0) {
559*8208Smckusick 		write(f, buf, strlen(buf)+1);
560*8208Smckusick 		close(f);
561*8208Smckusick 	}
562*8208Smckusick #endif BIFF
563*8208Smckusick 	return(ret);
564*8208Smckusick }
565*8208Smckusick 
566*8208Smckusick /* return 1 if success, 0 otherwise */
567*8208Smckusick prepend(from, to, uid, gid)
568*8208Smckusick char *from, *to;
569*8208Smckusick {
570*8208Smckusick 	register int (*sig)();
571*8208Smckusick 	struct stat statbuf;
572*8208Smckusick 	FILE *fdout, *fdin;
573*8208Smckusick 	int ret;
574*8208Smckusick 
575*8208Smckusick 	if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) {
576*8208Smckusick 		fprintf(stderr, "Exotic destination %s\n", to);
577*8208Smckusick 		goto badexit;
578*8208Smckusick 	}
579*8208Smckusick 	unlink(preptmp);
580*8208Smckusick 	if ((fdout = fopen(preptmp, "w")) == NULL) {
581*8208Smckusick 		perror("mail");
582*8208Smckusick 		goto badexit;
583*8208Smckusick 	}
584*8208Smckusick 	chmod(preptmp, MAILMODE);
585*8208Smckusick 	if ((fdin = fopen(from, "r")) == NULL) {
586*8208Smckusick 		perror("mail");
587*8208Smckusick 		goto badexit;
588*8208Smckusick 	}
589*8208Smckusick 	if(getput(fdin,fdout) == 0){
590*8208Smckusick 		perror("file i/o");
591*8208Smckusick 		goto badexit;
592*8208Smckusick 	}
593*8208Smckusick 	fclose(fdin);
594*8208Smckusick 	fdin = fopen(to, "r");
595*8208Smckusick 	/* ignore error since may not exist */
596*8208Smckusick 	if(fdin != NULL && getput(fdin,fdout) == 0){
597*8208Smckusick 		perror("file i/o");
598*8208Smckusick 		goto badexit;
599*8208Smckusick 	}
600*8208Smckusick 	if(fdin != NULL)fclose(fdin);
601*8208Smckusick 	fclose(fdout);
602*8208Smckusick 	sig = signal(SIGINT, SIG_IGN);
603*8208Smckusick 	remove(to);
604*8208Smckusick 	if ((fdout = fopen(to, "w")) == NULL) {
605*8208Smckusick 		perror(to);
606*8208Smckusick 		unlink(preptmp);
607*8208Smckusick 		signal(SIGINT, sig);
608*8208Smckusick 		goto badexit;
609*8208Smckusick 	}
610*8208Smckusick # ifdef NOTROOT
611*8208Smckusick 	if(uid != -1)chmod(to,0666);
612*8208Smckusick # else
613*8208Smckusick 	if(uid != -1)mchown(to, uid, gid);
614*8208Smckusick # endif
615*8208Smckusick 	if(stat(to, &statbuf) < 0 || statbuf.st_nlink != 1) {
616*8208Smckusick 		fclose(fdout);
617*8208Smckusick 		signal(SIGINT, sig);
618*8208Smckusick 		goto badexit;
619*8208Smckusick 	}
620*8208Smckusick 	if ((fdin = fopen(preptmp, "r"))  == NULL) {
621*8208Smckusick 		perror("mail");
622*8208Smckusick 		signal(SIGINT, sig);
623*8208Smckusick 		goto badexit;
624*8208Smckusick 	}
625*8208Smckusick 	ret = getput(fdin,fdout);
626*8208Smckusick 	fclose(fdout);
627*8208Smckusick 	fclose(fdin);
628*8208Smckusick 	signal(SIGINT, sig);
629*8208Smckusick 	return(ret);
630*8208Smckusick badexit:
631*8208Smckusick 	unlink(preptmp);
632*8208Smckusick 	errs++;
633*8208Smckusick 	return(0);
634*8208Smckusick }
635*8208Smckusick 
636*8208Smckusick delexit(ex)
637*8208Smckusick {
638*8208Smckusick 	unlink(lettmp);
639*8208Smckusick 	unlink(preptmp);
640*8208Smckusick 	exit(ex);
641*8208Smckusick }
642*8208Smckusick 
643*8208Smckusick /* return 1 if ok, 0 otherwise */
644*8208Smckusick getput(fdin, fdout)
645*8208Smckusick register FILE *fdin, *fdout;
646*8208Smckusick {
647*8208Smckusick 	extern int errno;
648*8208Smckusick 	register int c;
649*8208Smckusick 
650*8208Smckusick 	while((c = getc(fdin)) != EOF) {
651*8208Smckusick 		errno = 0;
652*8208Smckusick 		putc(c,fdout);
653*8208Smckusick 		if(errno) {
654*8208Smckusick 			perror("mail");
655*8208Smckusick 			return(0);
656*8208Smckusick 		}
657*8208Smckusick 	}
658*8208Smckusick 	return(1);
659*8208Smckusick }
660*8208Smckusick 
661*8208Smckusick accesss(s1)
662*8208Smckusick register char *s1;
663*8208Smckusick {
664*8208Smckusick 	struct stat statbuf;
665*8208Smckusick 		if(stat(s1,&statbuf)<0 || access(s1,2) == 0)
666*8208Smckusick 		return(1);
667*8208Smckusick 	return(0);
668*8208Smckusick }
669*8208Smckusick 
670*8208Smckusick any(c, str)
671*8208Smckusick 	register char *str, c;
672*8208Smckusick {
673*8208Smckusick 	register char *f;
674*8208Smckusick 
675*8208Smckusick 	f = str;
676*8208Smckusick 	while (*f)
677*8208Smckusick 		if (c == *f++)
678*8208Smckusick 			return(1);
679*8208Smckusick 	return(0);
680*8208Smckusick }
681*8208Smckusick char	locktmp[30];				/* Usable lock temporary */
682*8208Smckusick char	curlock[50];				/* Last used name of lock */
683*8208Smckusick int	locked;					/* To note that we locked it */
684*8208Smckusick 
685*8208Smckusick /*
686*8208Smckusick  * Lock the specified mail file by setting the file mailfile.lock.
687*8208Smckusick  * We must, of course, be careful to unlink the lock file by a call
688*8208Smckusick  * to unlock before we stop.  The algorithm used here is to see if
689*8208Smckusick  * the lock exists, and if it does, to check its modify time.  If it
690*8208Smckusick  * is older than 30 seconds, we assume error and set our own file.
691*8208Smckusick  * Otherwise, we wait for 5 seconds and try again.
692*8208Smckusick  */
693*8208Smckusick 
694*8208Smckusick lock(file)
695*8208Smckusick char *file;
696*8208Smckusick {
697*8208Smckusick 	register int f;
698*8208Smckusick 	struct stat statbuf;
699*8208Smckusick 	long curtime;
700*8208Smckusick /*
701*8208Smckusick    if using OLDMAIL, and NOTROOT, cann't lock since can't necessarily
702*8208Smckusick    write on user's login directory
703*8208Smckusick */
704*8208Smckusick # ifdef OLDMAIL
705*8208Smckusick 	return;
706*8208Smckusick # endif
707*8208Smckusick 
708*8208Smckusick 	if (file == NULL) {
709*8208Smckusick 		printf("Locked = %d\n", locked);
710*8208Smckusick 		return(0);
711*8208Smckusick 	}
712*8208Smckusick 	if (locked)
713*8208Smckusick 		return(0);
714*8208Smckusick 	sprintf(curlock,"%s%s",file,".mail");
715*8208Smckusick 	sprintf(locktmp,"%s/tmXXXXXX",MAILDIR);
716*8208Smckusick 	mktemp(locktmp);
717*8208Smckusick 	unlink(locktmp);
718*8208Smckusick 	for (;;) {
719*8208Smckusick 		f = lock1(locktmp, curlock);
720*8208Smckusick 		if (f == 0) {
721*8208Smckusick 			locked = 1;
722*8208Smckusick 			return(0);
723*8208Smckusick 		}
724*8208Smckusick 		if (stat(curlock, &statbuf) < 0)
725*8208Smckusick 			return(0);
726*8208Smckusick 		time(&curtime);
727*8208Smckusick 		if (curtime < statbuf.st_mtime + 30) {
728*8208Smckusick 			sleep(5);
729*8208Smckusick 			continue;
730*8208Smckusick 		}
731*8208Smckusick 		unlink(curlock);
732*8208Smckusick 	}
733*8208Smckusick }
734*8208Smckusick 
735*8208Smckusick /*
736*8208Smckusick  * Remove the mail lock, and note that we no longer
737*8208Smckusick  * have it locked.
738*8208Smckusick  */
739*8208Smckusick 
740*8208Smckusick unlock()
741*8208Smckusick {
742*8208Smckusick 
743*8208Smckusick 	if (locked)
744*8208Smckusick 		unlink(curlock);
745*8208Smckusick 	locked = 0;
746*8208Smckusick }
747*8208Smckusick 
748*8208Smckusick /*
749*8208Smckusick  * Attempt to set the lock by creating the temporary file,
750*8208Smckusick  * then doing a link/unlink.  If it fails, return -1 else 0
751*8208Smckusick  */
752*8208Smckusick 
753*8208Smckusick lock1(tempfile, name)
754*8208Smckusick 	char tempfile[], name[];
755*8208Smckusick {
756*8208Smckusick 	int fno;
757*8208Smckusick 
758*8208Smckusick 	fno = creat(tempfile, 0400);
759*8208Smckusick 	if (fno < 0)
760*8208Smckusick 		return(-1);
761*8208Smckusick 	close(fno);
762*8208Smckusick 	if (link(tempfile, name) < 0) {
763*8208Smckusick 		unlink(tempfile);
764*8208Smckusick 		return(-1);
765*8208Smckusick 	}
766*8208Smckusick 	unlink(tempfile);
767*8208Smckusick 	return(0);
768*8208Smckusick }
769*8208Smckusick 
770*8208Smckusick /*
771*8208Smckusick 	stripfx(prefix string, pointer to string)
772*8208Smckusick 
773*8208Smckusick 	takes a ptr to string and compares it to prefix string.
774*8208Smckusick 	may be called multiple times
775*8208Smckusick 	returns ":username"
776*8208Smckusick */
777*8208Smckusick stripfx(pfx, name)
778*8208Smckusick 	register char *pfx;
779*8208Smckusick 	register char **name;
780*8208Smckusick {
781*8208Smckusick 	register char *cp = *name;
782*8208Smckusick 
783*8208Smckusick 	while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
784*8208Smckusick 		cp++, pfx++;
785*8208Smckusick 	if (*cp != ':' || *pfx != 0)
786*8208Smckusick 		return;
787*8208Smckusick 	*name = cp;
788*8208Smckusick }
789*8208Smckusick stripmach(pperson)
790*8208Smckusick register char **pperson;
791*8208Smckusick {
792*8208Smckusick # ifdef RAND
793*8208Smckusick /* for machines at RAND */
794*8208Smckusick # ifdef GRAPHICS
795*8208Smckusick 	stripfx("g",pperson);
796*8208Smckusick 	stripfx("graphics",pperson);
797*8208Smckusick # endif
798*8208Smckusick # ifdef TP
799*8208Smckusick 	stripfx("t",pperson);
800*8208Smckusick 	stripfx("tp",pperson);
801*8208Smckusick # endif
802*8208Smckusick # ifdef VAX
803*8208Smckusick 	stripfx("v",pperson);
804*8208Smckusick 	stripfx("vax",pperson);
805*8208Smckusick # endif
806*8208Smckusick /* end of defns for Rand */
807*8208Smckusick # endif
808*8208Smckusick 
809*8208Smckusick # ifdef NOSC
810*8208Smckusick /* for machines at NOSC */
811*8208Smckusick # ifdef ATTS
812*8208Smckusick 	stripfx("a",pperson);
813*8208Smckusick 	stripfx("atts",pperson);
814*8208Smckusick # endif
815*8208Smckusick # ifdef CCMM
816*8208Smckusick 	stripfx("c",pperson);
817*8208Smckusick 	stripfx("ccmm",pperson);
818*8208Smckusick # endif
819*8208Smckusick # ifdef MSSF
820*8208Smckusick 	stripfx("m",pperson);
821*8208Smckusick 	stripfx("mssf",pperson);
822*8208Smckusick # endif
823*8208Smckusick /* end of defns for NOSC */
824*8208Smckusick # endif
825*8208Smckusick 
826*8208Smckusick # ifdef BERKELEY
827*8208Smckusick 
828*8208Smckusick /* for Berkeley */
829*8208Smckusick # ifdef A
830*8208Smckusick 	stripfx("a",pperson);
831*8208Smckusick # endif
832*8208Smckusick # ifdef B
833*8208Smckusick 	stripfx("b",pperson);
834*8208Smckusick # endif
835*8208Smckusick # ifdef C
836*8208Smckusick 	stripfx("c",pperson);
837*8208Smckusick # endif
838*8208Smckusick # ifdef D
839*8208Smckusick 	stripfx("d",pperson);
840*8208Smckusick # endif
841*8208Smckusick # ifdef E
842*8208Smckusick 	stripfx("e",pperson);
843*8208Smckusick # endif
844*8208Smckusick # ifdef ING70
845*8208Smckusick 	stripfx("i",pperson);
846*8208Smckusick 	stripfx("ing70",pperson);
847*8208Smckusick 	stripfx("ingres",pperson);
848*8208Smckusick # endif
849*8208Smckusick # ifdef INGVAX
850*8208Smckusick 	stripfx("j",pperson);
851*8208Smckusick 	stripfx("ingvax",pperson);
852*8208Smckusick # endif
853*8208Smckusick # ifdef VIRUS
854*8208Smckusick 	stripfx("k",pperson);
855*8208Smckusick 	stripfx("virus",pperson);
856*8208Smckusick # endif
857*8208Smckusick # ifdef IMAGE
858*8208Smckusick 	stripfx("m",pperson);
859*8208Smckusick 	stripfx("image",pperson);
860*8208Smckusick # endif
861*8208Smckusick # ifdef KIM
862*8208Smckusick 	stripfx("n",pperson);
863*8208Smckusick 	stripfx("kim",pperson);
864*8208Smckusick # endif
865*8208Smckusick # ifdef ESVAX
866*8208Smckusick 	stripfx("o",pperson);
867*8208Smckusick 	stripfx("esvax",pperson);
868*8208Smckusick # endif
869*8208Smckusick # ifdef Q
870*8208Smckusick 	stripfx("q",pperson);
871*8208Smckusick # endif
872*8208Smckusick # ifdef ARPAVAX
873*8208Smckusick 	stripfx("r",pperson);
874*8208Smckusick 	stripfx("arpavax",pperson);
875*8208Smckusick # endif
876*8208Smckusick # ifdef SRC
877*8208Smckusick 	stripfx("s",pperson);
878*8208Smckusick 	stripfx("src",pperson);
879*8208Smckusick # endif
880*8208Smckusick # ifdef MATHSTAT
881*8208Smckusick 	stripfx("t",pperson);
882*8208Smckusick 	stripfx("mathstat",pperson);
883*8208Smckusick # endif
884*8208Smckusick # ifdef CSVAX
885*8208Smckusick 	stripfx("v",pperson);
886*8208Smckusick 	stripfx("vax",pperson);
887*8208Smckusick 	stripfx("csvax",pperson);
888*8208Smckusick # endif
889*8208Smckusick # ifdef CORY
890*8208Smckusick 	stripfx("y",pperson);
891*8208Smckusick 	stripfx("cory",pperson);
892*8208Smckusick # endif
893*8208Smckusick # ifdef EECS40
894*8208Smckusick 	stripfx("z",pperson);
895*8208Smckusick 	stripfx("eecs40",pperson);
896*8208Smckusick # endif
897*8208Smckusick /* end of berkeley defns */
898*8208Smckusick # endif
899*8208Smckusick }
900*8208Smckusick /*
901*8208Smckusick    this removes the mail file sfn by either truncating it, as required
902*8208Smckusick    on OLDMAIL systems, or unlinking it. If the unlink fails, we truncate it.
903*8208Smckusick */
904*8208Smckusick remove(sfn)
905*8208Smckusick char *sfn;
906*8208Smckusick {
907*8208Smckusick 	int i;
908*8208Smckusick # ifdef OLDMAIL
909*8208Smckusick 	i = creat(sfn,0666);
910*8208Smckusick 	if(i >= 0)close(i);
911*8208Smckusick # else
912*8208Smckusick 	if(unlink(sfn) < 0){
913*8208Smckusick 		i = creat(sfn,MAILMODE);
914*8208Smckusick 		if(i >= 0)close(i);
915*8208Smckusick 	}
916*8208Smckusick # endif
917*8208Smckusick }
918