xref: /csrg-svn/old/berknet/v6mail.c (revision 9983)
1*9983Seric static char sccsid[] = "@(#)v6mail.c	4.3	(Berkeley)	12/27/82";
28208Smckusick 
38208Smckusick /*
48208Smckusick  * Version 6 Cory mail--
58208Smckusick  *	a clean and simple mail program
68208Smckusick  *	machine and version independent
78208Smckusick  *		Eric Schmidt
88208Smckusick  *	must run as setuid root to chown the destination mailbox
98208Smckusick  *	if NOTROOT defined, doesn't need to run as root
108208Smckusick  *
118208Smckusick  *	DON'T CHANGE THIS CODE
128208Smckusick  *		bitch to "csvax:schmidt" instead
138208Smckusick  */
148208Smckusick 
158208Smckusick /*
168208Smckusick  * mail command usage
178208Smckusick  *	mail [-yn]
188208Smckusick  *		prints your mail
198208Smckusick  *	mail people
208208Smckusick  *		sends standard input to people
218208Smckusick  *
228208Smckusick  *	mail -r fromaddr people
238208Smckusick  *		sends mail from the network
248208Smckusick  *
258208Smckusick  *	mail -d people
269981Seric  *		don't call sendmail, send mail directly
278208Smckusick  *	mail msgs
288208Smckusick  *		send to "msgs"
298208Smckusick  *	mail filename
308208Smckusick  *		mail to filename instead of user (must be at least one /)
318208Smckusick  *	mail -D
328208Smckusick  *		delete the invokers mailbox (more efficient than
338208Smckusick  *			mail -n >/dev/null)
348208Smckusick  */
358208Smckusick 
368208Smckusick /*
378208Smckusick  *	bugs:
388208Smckusick  *		Ingres 11/70 multiple names/uid?
398208Smckusick  *	additions:
408208Smckusick  *		Save? type 'x' - doesn't unlink the mail file
418208Smckusick  */
428208Smckusick /*
438208Smckusick  * BIFF is an immediate notification flag using the MPX stuff
448208Smckusick  */
458208Smckusick # include "local.h"
468208Smckusick # include <stdio.h>
478208Smckusick # include "mach.h"
488208Smckusick 
498208Smckusick # ifdef RAND
508208Smckusick 
518208Smckusick /* for all machines at RAND */
528208Smckusick # define MAILMODE 0644
538208Smckusick 
548208Smckusick # endif RAND
558208Smckusick 
568208Smckusick # ifdef NOSC
578208Smckusick 
588208Smckusick /* for all machines at NOSC */
598208Smckusick # define MAILMODE 0644
608208Smckusick 
618208Smckusick # endif NOSC
628208Smckusick 
638208Smckusick # ifdef BERKELEY
648208Smckusick /* for Berkeley */
658208Smckusick /* for each machine */
668208Smckusick /* lump the CC machines into one */
678208Smckusick # ifdef CCV7
688208Smckusick # define MAILMODE 0600
698208Smckusick # define MSGSCMD "/usr/ucb/bin/msgs"
708208Smckusick # endif
718208Smckusick 
728208Smckusick # ifdef CCV6
738208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs"
748208Smckusick # define MAILMODE 0600
758208Smckusick # endif
768208Smckusick 
778208Smckusick # ifdef ING70
788208Smckusick # define MAILMODE 0666
798208Smckusick # define MSGSCMD "/usr/bin/msgs"
808208Smckusick # define NOTROOT
818208Smckusick # endif
828208Smckusick 
838208Smckusick # ifdef INGVAX
848208Smckusick # define MAILMODE 0644
858208Smckusick # define MSGSCMD "/usr/ucb/msgs"
868208Smckusick # endif
878208Smckusick 
888208Smckusick /*
898208Smckusick # ifdef VIRUS
908208Smckusick # define MAILMODE 0644
918208Smckusick # define MSGSCMD "/usr/bin/msgs"
928208Smckusick # endif
938208Smckusick */
948208Smckusick 
958208Smckusick # ifdef UCBVAX
968208Smckusick # define MAILMODE 0644
978208Smckusick # define MSGSCMD "/usr/ucb/msgs"
988208Smckusick # define BIFF
998208Smckusick # endif
1008208Smckusick 
1018208Smckusick # ifdef IMAGE
1028208Smckusick # define MAILMODE 0644
1038208Smckusick # define MSGSCMD "/usr/bin/msgs"
1048208Smckusick # endif
1058208Smckusick 
1068208Smckusick # ifdef KIM
1078208Smckusick # define MAILMODE 0644
1088208Smckusick # define MSGSCMD "/usr/ucb/msgs"
1098208Smckusick # endif
1108208Smckusick 
1118208Smckusick # ifdef ESVAX
1128208Smckusick # define MAILMODE 0644
1138208Smckusick # define MSGSCMD "/usr/ucb/msgs"
1148208Smckusick # endif
1158208Smckusick 
1168208Smckusick # ifdef Q
1178208Smckusick # define MAILMODE 0600
1188208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs"
1198208Smckusick # endif
1208208Smckusick 
1218208Smckusick # ifdef ARPAVAX
1228208Smckusick # define MAILMODE 0644
1238208Smckusick # define MSGSCMD "/usr/ucb/msgs"
1248208Smckusick # define BIFF
1258208Smckusick # endif
1268208Smckusick 
1278208Smckusick # ifdef SRC
1288208Smckusick # define MAILMODE 0600
1298208Smckusick # define MSGSCMD "/usr/bin/msgs"
1308208Smckusick # endif
1318208Smckusick 
1328208Smckusick # ifdef MATHSTAT
1338208Smckusick # define MAILMODE 0600
1348208Smckusick # define MSGSCMD "/usr/bin/msgs"
1358208Smckusick # endif
1368208Smckusick 
1378208Smckusick # ifdef CSVAX
1388208Smckusick # define MAILMODE 0644
1398208Smckusick # define MSGSCMD "/usr/ucb/msgs"
1408208Smckusick # define BIFF
1418208Smckusick # endif
1428208Smckusick 
1438208Smckusick # ifdef ONYX
1448208Smckusick # define MAILMODE 0644
1458208Smckusick # define MSGSCMD "/usr/ucb/bin/msgs"
1468208Smckusick # endif
1478208Smckusick 
1488208Smckusick # ifdef CORY
1498208Smckusick # define MAILMODE 0600
1508208Smckusick # define MSGSCMD "/usr/bin/eecs/msgs"
1518208Smckusick # endif
1528208Smckusick 
1538208Smckusick # ifdef EECS40
1548208Smckusick # define MAILMODE 0644
1558208Smckusick # define MSGSCMD "/usr/bin/msgs"
1568208Smckusick # endif
1578208Smckusick /* end of berkeley defsn */
1588208Smckusick 
1598208Smckusick # endif
1608208Smckusick /* end of per-machine ifdefs */
1618208Smckusick 
1628208Smckusick # ifdef USRMAIL
1638208Smckusick # define MAILDIR "/usr/mail"
1648208Smckusick # else
1658208Smckusick # define MAILDIR "/usr/spool/mail"
1668208Smckusick # endif
1678208Smckusick 
1688208Smckusick char	lettmp[]  = "/tmp/MaXXXXX";	/* keep letter before sending it */
1698208Smckusick char	preptmp[] = "/tmp/mbXXXXX";	/* if prepending msg, use this file */
1708208Smckusick int	chew;				/* if true, strip extra from lines */
1719981Seric int	dflag;				/* if true, don't call sendmail */
1728208Smckusick char	shopcnt[30] = "0";		/* hop count parameter for rmt mail */
1738208Smckusick int	errs;				/* no of errs in sending */
1748208Smckusick char	deleteonly;			/* if true, just delete mailbox */
1758208Smckusick char 	remname[50];			/* if non-empty, from line extra */
1768208Smckusick 
1778208Smckusick char _sobuf[BUFSIZ];
1788208Smckusick main(argc, argv)
1798208Smckusick char **argv;
1808208Smckusick {
1818208Smckusick 	register int myuid;
1828208Smckusick 	int delexit();
1838208Smckusick 	char namebuf[128], *sn = NULL, logindir[60];
1848208Smckusick 	struct passwd *pwd;
1858208Smckusick 
1868208Smckusick 	setbuf(stdout,_sobuf);
1878208Smckusick 	mktemp(lettmp);
1888208Smckusick 	mktemp(preptmp);
1898208Smckusick 	unlink(lettmp);
1908208Smckusick 	unlink(preptmp);
1918208Smckusick 	myuid = getuid();
1928208Smckusick 	logindir[0] = 0;
1938208Smckusick 	sn = getlogin();
1948208Smckusick 	if(sn == NULL || *sn == 0 || *sn == ' '){
1958208Smckusick 		pwd = getpwuid(myuid);		/* will read passwd file */
1968208Smckusick 		if(pwd != NULL){
1978208Smckusick 			sn = pwd->pw_name;
1988208Smckusick 			strcpy(logindir,pwd->pw_dir);
1998208Smckusick 		}
2008208Smckusick 		if(sn == NULL){
2018208Smckusick 			fprintf(stderr,"Who are you?\n");
2028208Smckusick 			delexit(EX_OSFILE);
2038208Smckusick 		}
2048208Smckusick 	}
2058208Smckusick 	strcpy(namebuf,sn);
2068208Smckusick 	if (argc < 2)
2078208Smckusick 		goto hitit;
2088208Smckusick 	for (argc--, argv++; argc > 0 && argv[0][0] == '-'; argc--, argv++)
2098208Smckusick 	switch(argv[0][1]) {
2108208Smckusick 		case 'y':
2118208Smckusick 		case 'n':
2128208Smckusick 			argc++, argv--;
2138208Smckusick hitit:
2148208Smckusick 			printmail(argc, argv, namebuf,logindir);
2158208Smckusick 			delexit(EX_OK);
2168208Smckusick 
2178208Smckusick 		case 'r':	/* one-arg -r--   -r addr */
2188208Smckusick 			if (argc < 2)
2198208Smckusick 				continue;
2208208Smckusick 			/* ignore -r if not network or root */
2218208Smckusick 			if (strcmp("network", namebuf) == 0 || myuid == 0 ||
2228208Smckusick 			    strcmp("uucp", namebuf) == 0 || index(argv[1], '!') != NULL) {
2238208Smckusick 				strcpy(namebuf,argv[1]);
2248208Smckusick 				chew++;		/* eat From lines */
2258208Smckusick 			}
2268208Smckusick 			else strcpy(remname, argv[1]);
2278208Smckusick 			argc--, argv++;
2288208Smckusick 			continue;
2298208Smckusick 		case 'h':	/* hop count - used by network */
2308208Smckusick 			if(argc < 2) continue;
2318208Smckusick 			strcpy(shopcnt,argv[1]);
2328208Smckusick 			argc--, argv++;
2338208Smckusick 			continue;
2348208Smckusick 		case 'd':	/* really deliver this message */
2358208Smckusick 			dflag++;
2368208Smckusick 			continue;
2378208Smckusick 		case 'D':	/* only delete the invokers mailbox */
2388208Smckusick 			deleteonly++;
2398208Smckusick 			goto hitit;		/* delete mail box, thats all */
2408208Smckusick 	}
2418208Smckusick 	/* if we are already ignoring signals, catch sigint */
2428208Smckusick 	if(signal(SIGINT,SIG_IGN) != SIG_IGN)
2438208Smckusick 		signal(SIGINT, delexit);
2448208Smckusick 	argc++, argv--;
2458208Smckusick 	bulkmail(argc, argv, namebuf);
2468208Smckusick 	delexit(EX_OK);
2478208Smckusick }
2488208Smckusick 
2498208Smckusick printmail(argc, argv, name, logindir)
2508208Smckusick char **argv;
2518208Smckusick char *name, *logindir;
2528208Smckusick {
2538208Smckusick 	register int c;
2548208Smckusick 	FILE *fdin;
2558208Smckusick 	char sfnmail[60], mbox[120];
2568208Smckusick 	struct stat statbuf;
2578208Smckusick 
2588208Smckusick # ifdef OLDMAIL
2598208Smckusick 	if(logindir[0] == 0){
2608208Smckusick 		pwd = getpwuid(getuid());
2618208Smckusick 		if(pwd == NULL){
2628208Smckusick 			fprintf(stderr,"Can't get directory\n");
2638208Smckusick 			exit(EX_OSFILE);
2648208Smckusick 		}
2658208Smckusick 		strcpy(logindir, pwd->pw_dir);
2668208Smckusick 	}
2678208Smckusick 	sprintf(sfnmail,"%s/.mail",logindir);
2688208Smckusick # else
2698208Smckusick 	sprintf(sfnmail,"%s/%s",MAILDIR,name);
2708208Smckusick # endif
2718208Smckusick 	if(deleteonly){
2728208Smckusick 		remove(sfnmail);
2738208Smckusick 		return;
2748208Smckusick 	}
2758208Smckusick 	if (stat(sfnmail, &statbuf)>=0 && statbuf.st_nlink==1 &&
2768208Smckusick 		getsize(&statbuf) > 0L && (fdin = fopen(sfnmail, "r")) != NULL){
2778208Smckusick 		getput(fdin, stdout);
2788208Smckusick 		fclose(fdin);
2798208Smckusick 		fflush(stdout);
2808208Smckusick 		c = 'y';
2818208Smckusick 		if (argc<2) {
2828208Smckusick 			if(isatty(0)){
2838208Smckusick 				printf("Save(y-n) ?");
2848208Smckusick 				fflush(stdout);
2858208Smckusick 				c = getchar();
2868208Smckusick 			}
2878208Smckusick 		} else
2888208Smckusick 			c = argv[1][1];
2898208Smckusick 		if (!any(c, "xyn"))
2908208Smckusick 			delexit(EX_OK);
2918208Smckusick 		if (c == 'y') {
2928208Smckusick 			sprintf(mbox,"%s/mbox",logindir);
2938208Smckusick 			if (accesss(mbox)) {
2948208Smckusick 				printf("Saved mail in 'mbox'\n");
2958208Smckusick 				if(insert(sfnmail, mbox, getuid(),getgid()))
2968208Smckusick 					remove(sfnmail);
2978208Smckusick 			}
2988208Smckusick 			else printf("In wrong directory\n");
2998208Smckusick 		}
3008208Smckusick 		else if(c != 'x') remove(sfnmail);
3018208Smckusick 	} else
3028208Smckusick 		printf("No mail.\n");
3038208Smckusick }
3048208Smckusick 
3058208Smckusick bulkmail(argc, argv, from)
3068208Smckusick char **argv, *from;
3078208Smckusick {
3088208Smckusick 	extern int errno;
3098208Smckusick 	char linebuf[BUFSIZ];
3108208Smckusick 	char *getdate();
3118208Smckusick 	FILE *fdout;
3128208Smckusick 
3139981Seric # ifdef SENDMAIL
3148208Smckusick 	/*
3159981Seric 	**  Ship off to sendmail if appropriate (and possible)
3168208Smckusick 	*/
3178208Smckusick 
3188208Smckusick 	if (!dflag)
3198208Smckusick 	{
3209981Seric 		argv[0] = "-sendmail";
3218208Smckusick 		argv[argc] = 0;
3229981Seric 		execv("/usr/lib/sendmail", argv);
3238208Smckusick 		/* oops...  better just deliver it. */
3249981Seric 		fprintf(stderr, "Not using sendmail\n");
3258208Smckusick 		errno = 0;
3268208Smckusick 		argv[argc] = (char *)-1;
3278208Smckusick 	}
3288208Smckusick # endif
3298208Smckusick 
3308208Smckusick 	fdout = fopen(lettmp, "w");
3318208Smckusick 	if (fdout == NULL) {
3328208Smckusick 		perror(lettmp);
3338208Smckusick 		delexit(EX_OSFILE);
3348208Smckusick 	}
3358208Smckusick 	/*
3368208Smckusick 	 * If delivering mail from the network via mail -r,
3378208Smckusick 	 * Strip the leading line and throw it away, as long
3388208Smckusick 	 * as it begins with "From ..." (and preserve the date if poss.)
3398208Smckusick 	 */
3408208Smckusick 	if (chew) {
3418208Smckusick 		fgets(linebuf,BUFSIZ,stdin);
3428208Smckusick 		if(strncmp(linebuf,"From ",5) != 0){
3438208Smckusick 			fline(fdout,NULL,from);
3448208Smckusick 			fprintf(fdout,"%s", linebuf);
3458208Smckusick 		}
3468208Smckusick 		else fline(fdout,getdate(linebuf),from);
3478208Smckusick 	}
3488208Smckusick 	else fline(fdout,NULL,from);
3498208Smckusick 	if(remname[0]) fprintf(fdout,"(from %s)\n",remname);
3508208Smckusick 
3518208Smckusick 	/* on the image machine, promt with subj */
3528208Smckusick 	if(getput(stdin,fdout) == 0)
3538208Smckusick 		delexit(EX_OSERR);
3548208Smckusick 	putc('\n',fdout);
3558208Smckusick 	fclose(fdout);
3568208Smckusick 	while (--argc > 0)
3578208Smckusick 		sendto(*++argv,from);
3588208Smckusick 	delexit(errs);
3598208Smckusick }
3608208Smckusick /* print from line, with date date, if date = NULL, compute it */
3618208Smckusick fline(fdout,date,from)
3628208Smckusick FILE *fdout;
3638208Smckusick char *date;
3648208Smckusick char *from;
3658208Smckusick {
3668208Smckusick 	int tbuf[2];
3678208Smckusick 
3688208Smckusick 	if(date == NULL){
3698208Smckusick 		time(tbuf);
3708208Smckusick 		date = ctime(tbuf);
3718208Smckusick 	}
3728208Smckusick 	fprintf(fdout,"From %s  %s", from, date);
3738208Smckusick }
3748208Smckusick /* look over linebuf and return ptr to date, NULL if error */
3758208Smckusick char *getdate(linebuf)
3768208Smckusick char *linebuf;
3778208Smckusick {
3788208Smckusick 	register char *s;
3798208Smckusick 	s = linebuf;
3808208Smckusick 	while(*s){
3818208Smckusick 		if(strncmp(s," Sun ",5) == 0
3828208Smckusick 		|| strncmp(s," Mon ",5) == 0
3838208Smckusick 		|| strncmp(s," Tue ",5) == 0
3848208Smckusick 		|| strncmp(s," Wed ",5) == 0
3858208Smckusick 		|| strncmp(s," Thu ",5) == 0
3868208Smckusick 		|| strncmp(s," Fri ",5) == 0
3878208Smckusick 		|| strncmp(s," Sat ",5) == 0)
3888208Smckusick 			return(++s);
3898208Smckusick 		s++;
3908208Smckusick 	}
3918208Smckusick 	return(NULL);
3928208Smckusick }
3938208Smckusick 
3948208Smckusick sendto(person, fromaddr)
3958208Smckusick char *person;
3968208Smckusick char *fromaddr;
3978208Smckusick {
3988208Smckusick 	static int saved = 0;
3998208Smckusick 	register int hisuid, hisgid;
4008208Smckusick 	char sfnmail[60], logindir[60];
4018208Smckusick 	struct passwd *pwd;
4028208Smckusick 
4038208Smckusick 	stripmach(&person);
4048208Smckusick 	if(person[0] == ':')person++;
4059981Seric 	/* sendmail provides these services */
4068208Smckusick 	if(any(':',person)
4078208Smckusick # ifdef MSGSCMD
4088208Smckusick 		|| strcmp(person,"msgs") == 0
4098208Smckusick # endif
4108208Smckusick 		){
4118208Smckusick 		int pid;
4128208Smckusick 		int pidchild;
4138208Smckusick 
4148208Smckusick 		while((pid = fork()) == -1)sleep(2);
4158208Smckusick 		if (pid < 0) {
4168208Smckusick 			perror("fork");
4178208Smckusick 			goto assback;
4188208Smckusick 		}
4198208Smckusick 		if (pid == 0) {
4208208Smckusick 			fclose(stdin);
4218208Smckusick 			freopen(lettmp,"r",stdin);
4228208Smckusick 			setuid(getuid());	/* insure no security hole*/
4238208Smckusick 			if (strcmp(person,"msgs") != 0) {
4248208Smckusick 				/*
4258208Smckusick 				sendberkmail will add the machine, e.g.
4268208Smckusick 				CSVAX:schmidt, if the -f flag is not set
4278208Smckusick 				*/
4288208Smckusick 				execl("/usr/net/bin/sendberkmail",
4298208Smckusick 				"sendberkmail", "-t",person,"-h",shopcnt,
4308208Smckusick 				chew ? "-f" : 0,fromaddr,0);
4318208Smckusick 				perror("/usr/net/bin/sendberkmail");
4328208Smckusick 			}
4338208Smckusick # ifdef MSGSCMD
4348208Smckusick 			else {
4358208Smckusick 				execl(MSGSCMD, "msgs", "-s", 0);
4368208Smckusick 				perror(MSGSCMD);
4378208Smckusick 			}
4388208Smckusick # endif
4398208Smckusick 			exit(EX_UNAVAILABLE);
4408208Smckusick 		}
4418208Smckusick 		for (;;) {
4428208Smckusick 			register int rcode = wait(&pidchild);
4438208Smckusick 			if (rcode == -1)
4448208Smckusick 				goto assback;
4458208Smckusick 			if (rcode == pid)
4468208Smckusick 				break;
4478208Smckusick 		}
4488208Smckusick 		if ((pidchild & 0377) != 0 || (pidchild >> 8) != 0)
4498208Smckusick 			goto assback;
4508208Smckusick 		return;
4518208Smckusick 	}
4528208Smckusick 
4538208Smckusick 	if(!any('/',person)){
4548208Smckusick 	/* if name has no / in it, we assume it is a user's name */
4558208Smckusick # ifdef HPASSWD
4568208Smckusick 		hisuid = uidfromsn(person);
4578208Smckusick # else
4588208Smckusick 		pwd = getpwnam(person);
4598208Smckusick 		if(pwd != NULL){
4608208Smckusick 			hisuid = guid(pwd->pw_uid,pwd->pw_gid);
4618208Smckusick 			hisgid = pwd->pw_gid;
4628208Smckusick 			strcpy(logindir,pwd->pw_dir);
4638208Smckusick 		}
4648208Smckusick 		else hisuid = -1;
4658208Smckusick # endif
4668208Smckusick 		if(hisuid == -1){
4678208Smckusick 	assback:
4688208Smckusick 			fflush(stdout);
4698208Smckusick 			fprintf(stderr,"Can't send to %s.\n", person);
4708208Smckusick 			errs++;
4718208Smckusick 			if (isatty(0) && saved==0) {
4728208Smckusick 				saved++;
4738208Smckusick 				if (accesss("dead.letter")) {
4748208Smckusick 					printf("Letter saved in 'dead.letter'\n");
4758208Smckusick 					insert(lettmp, "dead.letter",
4768208Smckusick 						getuid(),getgid());
4778208Smckusick 				} else
4788208Smckusick 					printf("In wrong directory\n");
4798208Smckusick 			}
4808208Smckusick 			return;
4818208Smckusick 		}
4828208Smckusick # ifdef OLDMAIL
4838208Smckusick 		sprintf(sfnmail,"%s/.mail",logindir);
4848208Smckusick # else
4858208Smckusick 		sprintf(sfnmail,"%s/%s",MAILDIR,person);
4868208Smckusick # endif
4878208Smckusick 		lock(sfnmail);
4888208Smckusick 		insert(lettmp, sfnmail, hisuid, hisgid);
4898208Smckusick 		unlock();
4908208Smckusick 		}
4918208Smckusick 	else {		/* it has / in it, "person" is a file */
4928208Smckusick 		if(accesss(person)){
4938208Smckusick 			lock(person);
4948208Smckusick 			insert(lettmp, person, -1, -1);
4958208Smckusick 			unlock();
4968208Smckusick 		}
4978208Smckusick 		else
4988208Smckusick 			fprintf(stderr,"Can't access %s\n",person);
4998208Smckusick 	}
5008208Smckusick }
5018208Smckusick 
5028208Smckusick /* return 1 if success, 0 otherwise */
5038208Smckusick insert(from, to, uid, gid)
5048208Smckusick char *from, *to;
5058208Smckusick {
5068208Smckusick # ifdef V6
5078208Smckusick 	return(prepend(from,to,uid, gid));
5088208Smckusick # else
5098208Smckusick 	return(append(from,to,uid, gid));
5108208Smckusick # endif
5118208Smckusick }
5128208Smckusick /* return 1 if success, 0 otherwise */
5138208Smckusick append(from,to,uid, gid)
5148208Smckusick char *from, *to;
5158208Smckusick {
5168208Smckusick 	register FILE *fdin, *fdout;
5178208Smckusick 	int ret;
5188208Smckusick 	struct stat statbuf;
5198208Smckusick #ifdef BIFF
5208208Smckusick /* biff ... */
5218208Smckusick 	char *rindex();
5228208Smckusick 	char *cp;
5238208Smckusick 	char buf[100];
5248208Smckusick 	int f;
5258208Smckusick /* end biff */
5268208Smckusick #endif BIFF
5278208Smckusick 	if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) {
5288208Smckusick 		fprintf(stderr, "Exotic destination %s\n", to);
5298208Smckusick 		errs++;
5308208Smckusick 		return(0);
5318208Smckusick 	}
5328208Smckusick 	if ((fdout = fopen(to, "a")) == NULL) {
5338208Smckusick 		perror(to);
5348208Smckusick 		errs++;
5358208Smckusick 		return(0);
5368208Smckusick 	}
5378208Smckusick # ifndef NOTROOT
5388208Smckusick 	if(uid != -1)mchown(to, uid, gid);
5398208Smckusick # endif
5408208Smckusick 	if(uid != -1)chmod(to, MAILMODE);
5418208Smckusick 	if ((fdin = fopen(from, "r")) == NULL) {
5428208Smckusick 		perror(from);
5438208Smckusick 		return(0);
5448208Smckusick 	}
5458208Smckusick #ifdef BIFF
5468208Smckusick 	{
5478208Smckusick 		f = open("/dev/mail", 1);
5488208Smckusick 		cp = rindex(to, '/');
5498208Smckusick 		if (cp) {
5508208Smckusick 			sprintf(buf, "%s@%d\n", cp+1, ftell(fdout));
5518208Smckusick 		}
5528208Smckusick 	}
5538208Smckusick #endif BIFF
5548208Smckusick 	ret = getput(fdin,fdout);
5558208Smckusick 	fclose(fdin);
5568208Smckusick 	fclose(fdout);
5578208Smckusick #ifdef BIFF
5588208Smckusick 	if (cp && f >= 0) {
5598208Smckusick 		write(f, buf, strlen(buf)+1);
5608208Smckusick 		close(f);
5618208Smckusick 	}
5628208Smckusick #endif BIFF
5638208Smckusick 	return(ret);
5648208Smckusick }
5658208Smckusick 
5668208Smckusick /* return 1 if success, 0 otherwise */
5678208Smckusick prepend(from, to, uid, gid)
5688208Smckusick char *from, *to;
5698208Smckusick {
5708208Smckusick 	register int (*sig)();
5718208Smckusick 	struct stat statbuf;
5728208Smckusick 	FILE *fdout, *fdin;
5738208Smckusick 	int ret;
5748208Smckusick 
5758208Smckusick 	if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) {
5768208Smckusick 		fprintf(stderr, "Exotic destination %s\n", to);
5778208Smckusick 		goto badexit;
5788208Smckusick 	}
5798208Smckusick 	unlink(preptmp);
5808208Smckusick 	if ((fdout = fopen(preptmp, "w")) == NULL) {
5818208Smckusick 		perror("mail");
5828208Smckusick 		goto badexit;
5838208Smckusick 	}
5848208Smckusick 	chmod(preptmp, MAILMODE);
5858208Smckusick 	if ((fdin = fopen(from, "r")) == NULL) {
5868208Smckusick 		perror("mail");
5878208Smckusick 		goto badexit;
5888208Smckusick 	}
5898208Smckusick 	if(getput(fdin,fdout) == 0){
5908208Smckusick 		perror("file i/o");
5918208Smckusick 		goto badexit;
5928208Smckusick 	}
5938208Smckusick 	fclose(fdin);
5948208Smckusick 	fdin = fopen(to, "r");
5958208Smckusick 	/* ignore error since may not exist */
5968208Smckusick 	if(fdin != NULL && getput(fdin,fdout) == 0){
5978208Smckusick 		perror("file i/o");
5988208Smckusick 		goto badexit;
5998208Smckusick 	}
6008208Smckusick 	if(fdin != NULL)fclose(fdin);
6018208Smckusick 	fclose(fdout);
6028208Smckusick 	sig = signal(SIGINT, SIG_IGN);
6038208Smckusick 	remove(to);
6048208Smckusick 	if ((fdout = fopen(to, "w")) == NULL) {
6058208Smckusick 		perror(to);
6068208Smckusick 		unlink(preptmp);
6078208Smckusick 		signal(SIGINT, sig);
6088208Smckusick 		goto badexit;
6098208Smckusick 	}
6108208Smckusick # ifdef NOTROOT
6118208Smckusick 	if(uid != -1)chmod(to,0666);
6128208Smckusick # else
6138208Smckusick 	if(uid != -1)mchown(to, uid, gid);
6148208Smckusick # endif
6158208Smckusick 	if(stat(to, &statbuf) < 0 || statbuf.st_nlink != 1) {
6168208Smckusick 		fclose(fdout);
6178208Smckusick 		signal(SIGINT, sig);
6188208Smckusick 		goto badexit;
6198208Smckusick 	}
6208208Smckusick 	if ((fdin = fopen(preptmp, "r"))  == NULL) {
6218208Smckusick 		perror("mail");
6228208Smckusick 		signal(SIGINT, sig);
6238208Smckusick 		goto badexit;
6248208Smckusick 	}
6258208Smckusick 	ret = getput(fdin,fdout);
6268208Smckusick 	fclose(fdout);
6278208Smckusick 	fclose(fdin);
6288208Smckusick 	signal(SIGINT, sig);
6298208Smckusick 	return(ret);
6308208Smckusick badexit:
6318208Smckusick 	unlink(preptmp);
6328208Smckusick 	errs++;
6338208Smckusick 	return(0);
6348208Smckusick }
6358208Smckusick 
6368208Smckusick delexit(ex)
6378208Smckusick {
6388208Smckusick 	unlink(lettmp);
6398208Smckusick 	unlink(preptmp);
6408208Smckusick 	exit(ex);
6418208Smckusick }
6428208Smckusick 
6438208Smckusick /* return 1 if ok, 0 otherwise */
6448208Smckusick getput(fdin, fdout)
6458208Smckusick register FILE *fdin, *fdout;
6468208Smckusick {
6478208Smckusick 	extern int errno;
6488208Smckusick 	register int c;
6498208Smckusick 
6508208Smckusick 	while((c = getc(fdin)) != EOF) {
6518208Smckusick 		errno = 0;
6528208Smckusick 		putc(c,fdout);
6538208Smckusick 		if(errno) {
6548208Smckusick 			perror("mail");
6558208Smckusick 			return(0);
6568208Smckusick 		}
6578208Smckusick 	}
6588208Smckusick 	return(1);
6598208Smckusick }
6608208Smckusick 
6618208Smckusick accesss(s1)
6628208Smckusick register char *s1;
6638208Smckusick {
6648208Smckusick 	struct stat statbuf;
6658208Smckusick 		if(stat(s1,&statbuf)<0 || access(s1,2) == 0)
6668208Smckusick 		return(1);
6678208Smckusick 	return(0);
6688208Smckusick }
6698208Smckusick 
6708208Smckusick any(c, str)
6718208Smckusick 	register char *str, c;
6728208Smckusick {
6738208Smckusick 	register char *f;
6748208Smckusick 
6758208Smckusick 	f = str;
6768208Smckusick 	while (*f)
6778208Smckusick 		if (c == *f++)
6788208Smckusick 			return(1);
6798208Smckusick 	return(0);
6808208Smckusick }
6818208Smckusick char	locktmp[30];				/* Usable lock temporary */
6828208Smckusick char	curlock[50];				/* Last used name of lock */
6838208Smckusick int	locked;					/* To note that we locked it */
6848208Smckusick 
6858208Smckusick /*
6868208Smckusick  * Lock the specified mail file by setting the file mailfile.lock.
6878208Smckusick  * We must, of course, be careful to unlink the lock file by a call
6888208Smckusick  * to unlock before we stop.  The algorithm used here is to see if
6898208Smckusick  * the lock exists, and if it does, to check its modify time.  If it
6908208Smckusick  * is older than 30 seconds, we assume error and set our own file.
6918208Smckusick  * Otherwise, we wait for 5 seconds and try again.
6928208Smckusick  */
6938208Smckusick 
6948208Smckusick lock(file)
6958208Smckusick char *file;
6968208Smckusick {
6978208Smckusick 	register int f;
6988208Smckusick 	struct stat statbuf;
6998208Smckusick 	long curtime;
7008208Smckusick /*
7018208Smckusick    if using OLDMAIL, and NOTROOT, cann't lock since can't necessarily
7028208Smckusick    write on user's login directory
7038208Smckusick */
7048208Smckusick # ifdef OLDMAIL
7058208Smckusick 	return;
7068208Smckusick # endif
7078208Smckusick 
7088208Smckusick 	if (file == NULL) {
7098208Smckusick 		printf("Locked = %d\n", locked);
7108208Smckusick 		return(0);
7118208Smckusick 	}
7128208Smckusick 	if (locked)
7138208Smckusick 		return(0);
714*9983Seric 	sprintf(curlock,"%s%s",file,".lock");
7158208Smckusick 	sprintf(locktmp,"%s/tmXXXXXX",MAILDIR);
7168208Smckusick 	mktemp(locktmp);
7178208Smckusick 	unlink(locktmp);
7188208Smckusick 	for (;;) {
7198208Smckusick 		f = lock1(locktmp, curlock);
7208208Smckusick 		if (f == 0) {
7218208Smckusick 			locked = 1;
7228208Smckusick 			return(0);
7238208Smckusick 		}
7248208Smckusick 		if (stat(curlock, &statbuf) < 0)
7258208Smckusick 			return(0);
7268208Smckusick 		time(&curtime);
7278208Smckusick 		if (curtime < statbuf.st_mtime + 30) {
7288208Smckusick 			sleep(5);
7298208Smckusick 			continue;
7308208Smckusick 		}
7318208Smckusick 		unlink(curlock);
7328208Smckusick 	}
7338208Smckusick }
7348208Smckusick 
7358208Smckusick /*
7368208Smckusick  * Remove the mail lock, and note that we no longer
7378208Smckusick  * have it locked.
7388208Smckusick  */
7398208Smckusick 
7408208Smckusick unlock()
7418208Smckusick {
7428208Smckusick 
7438208Smckusick 	if (locked)
7448208Smckusick 		unlink(curlock);
7458208Smckusick 	locked = 0;
7468208Smckusick }
7478208Smckusick 
7488208Smckusick /*
7498208Smckusick  * Attempt to set the lock by creating the temporary file,
7508208Smckusick  * then doing a link/unlink.  If it fails, return -1 else 0
7518208Smckusick  */
7528208Smckusick 
7538208Smckusick lock1(tempfile, name)
7548208Smckusick 	char tempfile[], name[];
7558208Smckusick {
7568208Smckusick 	int fno;
7578208Smckusick 
7588208Smckusick 	fno = creat(tempfile, 0400);
7598208Smckusick 	if (fno < 0)
7608208Smckusick 		return(-1);
7618208Smckusick 	close(fno);
7628208Smckusick 	if (link(tempfile, name) < 0) {
7638208Smckusick 		unlink(tempfile);
7648208Smckusick 		return(-1);
7658208Smckusick 	}
7668208Smckusick 	unlink(tempfile);
7678208Smckusick 	return(0);
7688208Smckusick }
7698208Smckusick 
7708208Smckusick /*
7718208Smckusick 	stripfx(prefix string, pointer to string)
7728208Smckusick 
7738208Smckusick 	takes a ptr to string and compares it to prefix string.
7748208Smckusick 	may be called multiple times
7758208Smckusick 	returns ":username"
7768208Smckusick */
7778208Smckusick stripfx(pfx, name)
7788208Smckusick 	register char *pfx;
7798208Smckusick 	register char **name;
7808208Smckusick {
7818208Smckusick 	register char *cp = *name;
7828208Smckusick 
7838208Smckusick 	while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
7848208Smckusick 		cp++, pfx++;
7858208Smckusick 	if (*cp != ':' || *pfx != 0)
7868208Smckusick 		return;
7878208Smckusick 	*name = cp;
7888208Smckusick }
7898208Smckusick stripmach(pperson)
7908208Smckusick register char **pperson;
7918208Smckusick {
7928208Smckusick # ifdef RAND
7938208Smckusick /* for machines at RAND */
7948208Smckusick # ifdef GRAPHICS
7958208Smckusick 	stripfx("g",pperson);
7968208Smckusick 	stripfx("graphics",pperson);
7978208Smckusick # endif
7988208Smckusick # ifdef TP
7998208Smckusick 	stripfx("t",pperson);
8008208Smckusick 	stripfx("tp",pperson);
8018208Smckusick # endif
8028208Smckusick # ifdef VAX
8038208Smckusick 	stripfx("v",pperson);
8048208Smckusick 	stripfx("vax",pperson);
8058208Smckusick # endif
8068208Smckusick /* end of defns for Rand */
8078208Smckusick # endif
8088208Smckusick 
8098208Smckusick # ifdef NOSC
8108208Smckusick /* for machines at NOSC */
8118208Smckusick # ifdef ATTS
8128208Smckusick 	stripfx("a",pperson);
8138208Smckusick 	stripfx("atts",pperson);
8148208Smckusick # endif
8158208Smckusick # ifdef CCMM
8168208Smckusick 	stripfx("c",pperson);
8178208Smckusick 	stripfx("ccmm",pperson);
8188208Smckusick # endif
8198208Smckusick # ifdef MSSF
8208208Smckusick 	stripfx("m",pperson);
8218208Smckusick 	stripfx("mssf",pperson);
8228208Smckusick # endif
8238208Smckusick /* end of defns for NOSC */
8248208Smckusick # endif
8258208Smckusick 
8268208Smckusick # ifdef BERKELEY
8278208Smckusick 
8288208Smckusick /* for Berkeley */
8298208Smckusick # ifdef A
8308208Smckusick 	stripfx("a",pperson);
8318208Smckusick # endif
8328208Smckusick # ifdef B
8338208Smckusick 	stripfx("b",pperson);
8348208Smckusick # endif
8358208Smckusick # ifdef C
8368208Smckusick 	stripfx("c",pperson);
8378208Smckusick # endif
8388208Smckusick # ifdef D
8398208Smckusick 	stripfx("d",pperson);
8408208Smckusick # endif
8418208Smckusick # ifdef E
8428208Smckusick 	stripfx("e",pperson);
8438208Smckusick # endif
8448208Smckusick # ifdef ING70
8458208Smckusick 	stripfx("i",pperson);
8468208Smckusick 	stripfx("ing70",pperson);
8478208Smckusick 	stripfx("ingres",pperson);
8488208Smckusick # endif
8498208Smckusick # ifdef INGVAX
8508208Smckusick 	stripfx("j",pperson);
8518208Smckusick 	stripfx("ingvax",pperson);
8528208Smckusick # endif
8538208Smckusick # ifdef VIRUS
8548208Smckusick 	stripfx("k",pperson);
8558208Smckusick 	stripfx("virus",pperson);
8568208Smckusick # endif
8578208Smckusick # ifdef IMAGE
8588208Smckusick 	stripfx("m",pperson);
8598208Smckusick 	stripfx("image",pperson);
8608208Smckusick # endif
8618208Smckusick # ifdef KIM
8628208Smckusick 	stripfx("n",pperson);
8638208Smckusick 	stripfx("kim",pperson);
8648208Smckusick # endif
8658208Smckusick # ifdef ESVAX
8668208Smckusick 	stripfx("o",pperson);
8678208Smckusick 	stripfx("esvax",pperson);
8688208Smckusick # endif
8698208Smckusick # ifdef Q
8708208Smckusick 	stripfx("q",pperson);
8718208Smckusick # endif
8728208Smckusick # ifdef ARPAVAX
8738208Smckusick 	stripfx("r",pperson);
8748208Smckusick 	stripfx("arpavax",pperson);
8758208Smckusick # endif
8768208Smckusick # ifdef SRC
8778208Smckusick 	stripfx("s",pperson);
8788208Smckusick 	stripfx("src",pperson);
8798208Smckusick # endif
8808208Smckusick # ifdef MATHSTAT
8818208Smckusick 	stripfx("t",pperson);
8828208Smckusick 	stripfx("mathstat",pperson);
8838208Smckusick # endif
8848208Smckusick # ifdef CSVAX
8858208Smckusick 	stripfx("v",pperson);
8868208Smckusick 	stripfx("vax",pperson);
8878208Smckusick 	stripfx("csvax",pperson);
8888208Smckusick # endif
8898208Smckusick # ifdef CORY
8908208Smckusick 	stripfx("y",pperson);
8918208Smckusick 	stripfx("cory",pperson);
8928208Smckusick # endif
8938208Smckusick # ifdef EECS40
8948208Smckusick 	stripfx("z",pperson);
8958208Smckusick 	stripfx("eecs40",pperson);
8968208Smckusick # endif
8978208Smckusick /* end of berkeley defns */
8988208Smckusick # endif
8998208Smckusick }
9008208Smckusick /*
9018208Smckusick    this removes the mail file sfn by either truncating it, as required
9028208Smckusick    on OLDMAIL systems, or unlinking it. If the unlink fails, we truncate it.
9038208Smckusick */
9048208Smckusick remove(sfn)
9058208Smckusick char *sfn;
9068208Smckusick {
9078208Smckusick 	int i;
9088208Smckusick # ifdef OLDMAIL
9098208Smckusick 	i = creat(sfn,0666);
9108208Smckusick 	if(i >= 0)close(i);
9118208Smckusick # else
9128208Smckusick 	if(unlink(sfn) < 0){
9138208Smckusick 		i = creat(sfn,MAILMODE);
9148208Smckusick 		if(i >= 0)close(i);
9158208Smckusick 	}
9168208Smckusick # endif
9178208Smckusick }
918