xref: /csrg-svn/old/berknet/v6mail.c (revision 10217)
1*10217Ssam static char sccsid[] = "@(#)v6mail.c	4.4	(Berkeley)	01/09/83";
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 /*
43*10217Ssam  * BIFF is an immediate notification flag using the IPC 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];
main(argc,argv)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 
printmail(argc,argv,name,logindir)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 
bulkmail(argc,argv,from)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 */
fline(fdout,date,from)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 */
getdate(linebuf)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 
sendto(person,fromaddr)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 */
insert(from,to,uid,gid)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 }
512*10217Ssam 
513*10217Ssam #ifdef BIFF
514*10217Ssam #include <sys/socket.h>
515*10217Ssam #include <netinet/in.h>
516*10217Ssam #include <netdb.h>
517*10217Ssam #endif
518*10217Ssam 
5198208Smckusick /* return 1 if success, 0 otherwise */
append(from,to,uid,gid)5208208Smckusick append(from,to,uid, gid)
5218208Smckusick char *from, *to;
5228208Smckusick {
5238208Smckusick 	register FILE *fdin, *fdout;
5248208Smckusick 	int ret;
5258208Smckusick 	struct stat statbuf;
5268208Smckusick #ifdef BIFF
527*10217Ssam 	char *cp, buf[100], *rindex();
528*10217Ssam 	int s;
529*10217Ssam 	struct hostent *hp;
530*10217Ssam 	struct sockaddr_in sin;
531*10217Ssam 	struct servent *sp;
532*10217Ssam #endif
5338208Smckusick 	if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) {
5348208Smckusick 		fprintf(stderr, "Exotic destination %s\n", to);
5358208Smckusick 		errs++;
5368208Smckusick 		return(0);
5378208Smckusick 	}
5388208Smckusick 	if ((fdout = fopen(to, "a")) == NULL) {
5398208Smckusick 		perror(to);
5408208Smckusick 		errs++;
5418208Smckusick 		return(0);
5428208Smckusick 	}
5438208Smckusick # ifndef NOTROOT
5448208Smckusick 	if(uid != -1)mchown(to, uid, gid);
5458208Smckusick # endif
5468208Smckusick 	if(uid != -1)chmod(to, MAILMODE);
5478208Smckusick 	if ((fdin = fopen(from, "r")) == NULL) {
5488208Smckusick 		perror(from);
5498208Smckusick 		return(0);
5508208Smckusick 	}
5518208Smckusick #ifdef BIFF
552*10217Ssam 	{ s = socket(AF_INET, SOCK_STREAM, 0, 0);
553*10217Ssam 	  cp = rindex(to, '/');
554*10217Ssam 	  if (cp)
555*10217Ssam 		sprintf(buf, "%s@%d\n", cp+1, ftell(fdout));
5568208Smckusick 	}
557*10217Ssam #endif
5588208Smckusick 	ret = getput(fdin,fdout);
5598208Smckusick 	fclose(fdin);
5608208Smckusick 	fclose(fdout);
5618208Smckusick #ifdef BIFF
562*10217Ssam 	if (cp && s >= 0) {
563*10217Ssam 		hp = gethostbyname("localhost");
564*10217Ssam 		sp = getservent("biff", "udp");
565*10217Ssam 		if (hp && sp) {
566*10217Ssam 			bcopy(hp->h_addr, &sin.sin_addr, hp->h_length);
567*10217Ssam 			sin.sin_family = hp->h_addrtype;
568*10217Ssam 			sin.sin_port = sp->s_port;
569*10217Ssam 			(void) sendto(s, buf, strlen(buf) + 1, 0,
570*10217Ssam 				&sin, sizeof (sin));
571*10217Ssam 		}
572*10217Ssam 		close(s);
5738208Smckusick 	}
574*10217Ssam #endif
5758208Smckusick 	return(ret);
5768208Smckusick }
5778208Smckusick 
5788208Smckusick /* return 1 if success, 0 otherwise */
prepend(from,to,uid,gid)5798208Smckusick prepend(from, to, uid, gid)
5808208Smckusick char *from, *to;
5818208Smckusick {
5828208Smckusick 	register int (*sig)();
5838208Smckusick 	struct stat statbuf;
5848208Smckusick 	FILE *fdout, *fdin;
5858208Smckusick 	int ret;
5868208Smckusick 
5878208Smckusick 	if (stat(to, &statbuf) >= 0 && (statbuf.st_mode&S_IFDIR) != 0) {
5888208Smckusick 		fprintf(stderr, "Exotic destination %s\n", to);
5898208Smckusick 		goto badexit;
5908208Smckusick 	}
5918208Smckusick 	unlink(preptmp);
5928208Smckusick 	if ((fdout = fopen(preptmp, "w")) == NULL) {
5938208Smckusick 		perror("mail");
5948208Smckusick 		goto badexit;
5958208Smckusick 	}
5968208Smckusick 	chmod(preptmp, MAILMODE);
5978208Smckusick 	if ((fdin = fopen(from, "r")) == NULL) {
5988208Smckusick 		perror("mail");
5998208Smckusick 		goto badexit;
6008208Smckusick 	}
6018208Smckusick 	if(getput(fdin,fdout) == 0){
6028208Smckusick 		perror("file i/o");
6038208Smckusick 		goto badexit;
6048208Smckusick 	}
6058208Smckusick 	fclose(fdin);
6068208Smckusick 	fdin = fopen(to, "r");
6078208Smckusick 	/* ignore error since may not exist */
6088208Smckusick 	if(fdin != NULL && getput(fdin,fdout) == 0){
6098208Smckusick 		perror("file i/o");
6108208Smckusick 		goto badexit;
6118208Smckusick 	}
6128208Smckusick 	if(fdin != NULL)fclose(fdin);
6138208Smckusick 	fclose(fdout);
6148208Smckusick 	sig = signal(SIGINT, SIG_IGN);
6158208Smckusick 	remove(to);
6168208Smckusick 	if ((fdout = fopen(to, "w")) == NULL) {
6178208Smckusick 		perror(to);
6188208Smckusick 		unlink(preptmp);
6198208Smckusick 		signal(SIGINT, sig);
6208208Smckusick 		goto badexit;
6218208Smckusick 	}
6228208Smckusick # ifdef NOTROOT
6238208Smckusick 	if(uid != -1)chmod(to,0666);
6248208Smckusick # else
6258208Smckusick 	if(uid != -1)mchown(to, uid, gid);
6268208Smckusick # endif
6278208Smckusick 	if(stat(to, &statbuf) < 0 || statbuf.st_nlink != 1) {
6288208Smckusick 		fclose(fdout);
6298208Smckusick 		signal(SIGINT, sig);
6308208Smckusick 		goto badexit;
6318208Smckusick 	}
6328208Smckusick 	if ((fdin = fopen(preptmp, "r"))  == NULL) {
6338208Smckusick 		perror("mail");
6348208Smckusick 		signal(SIGINT, sig);
6358208Smckusick 		goto badexit;
6368208Smckusick 	}
6378208Smckusick 	ret = getput(fdin,fdout);
6388208Smckusick 	fclose(fdout);
6398208Smckusick 	fclose(fdin);
6408208Smckusick 	signal(SIGINT, sig);
6418208Smckusick 	return(ret);
6428208Smckusick badexit:
6438208Smckusick 	unlink(preptmp);
6448208Smckusick 	errs++;
6458208Smckusick 	return(0);
6468208Smckusick }
6478208Smckusick 
delexit(ex)6488208Smckusick delexit(ex)
6498208Smckusick {
6508208Smckusick 	unlink(lettmp);
6518208Smckusick 	unlink(preptmp);
6528208Smckusick 	exit(ex);
6538208Smckusick }
6548208Smckusick 
6558208Smckusick /* return 1 if ok, 0 otherwise */
getput(fdin,fdout)6568208Smckusick getput(fdin, fdout)
6578208Smckusick register FILE *fdin, *fdout;
6588208Smckusick {
6598208Smckusick 	extern int errno;
6608208Smckusick 	register int c;
6618208Smckusick 
6628208Smckusick 	while((c = getc(fdin)) != EOF) {
6638208Smckusick 		errno = 0;
6648208Smckusick 		putc(c,fdout);
6658208Smckusick 		if(errno) {
6668208Smckusick 			perror("mail");
6678208Smckusick 			return(0);
6688208Smckusick 		}
6698208Smckusick 	}
6708208Smckusick 	return(1);
6718208Smckusick }
6728208Smckusick 
accesss(s1)6738208Smckusick accesss(s1)
6748208Smckusick register char *s1;
6758208Smckusick {
6768208Smckusick 	struct stat statbuf;
6778208Smckusick 		if(stat(s1,&statbuf)<0 || access(s1,2) == 0)
6788208Smckusick 		return(1);
6798208Smckusick 	return(0);
6808208Smckusick }
6818208Smckusick 
any(c,str)6828208Smckusick any(c, str)
6838208Smckusick 	register char *str, c;
6848208Smckusick {
6858208Smckusick 	register char *f;
6868208Smckusick 
6878208Smckusick 	f = str;
6888208Smckusick 	while (*f)
6898208Smckusick 		if (c == *f++)
6908208Smckusick 			return(1);
6918208Smckusick 	return(0);
6928208Smckusick }
6938208Smckusick char	locktmp[30];				/* Usable lock temporary */
6948208Smckusick char	curlock[50];				/* Last used name of lock */
6958208Smckusick int	locked;					/* To note that we locked it */
6968208Smckusick 
6978208Smckusick /*
6988208Smckusick  * Lock the specified mail file by setting the file mailfile.lock.
6998208Smckusick  * We must, of course, be careful to unlink the lock file by a call
7008208Smckusick  * to unlock before we stop.  The algorithm used here is to see if
7018208Smckusick  * the lock exists, and if it does, to check its modify time.  If it
7028208Smckusick  * is older than 30 seconds, we assume error and set our own file.
7038208Smckusick  * Otherwise, we wait for 5 seconds and try again.
7048208Smckusick  */
7058208Smckusick 
lock(file)7068208Smckusick lock(file)
7078208Smckusick char *file;
7088208Smckusick {
7098208Smckusick 	register int f;
7108208Smckusick 	struct stat statbuf;
7118208Smckusick 	long curtime;
7128208Smckusick /*
7138208Smckusick    if using OLDMAIL, and NOTROOT, cann't lock since can't necessarily
7148208Smckusick    write on user's login directory
7158208Smckusick */
7168208Smckusick # ifdef OLDMAIL
7178208Smckusick 	return;
7188208Smckusick # endif
7198208Smckusick 
7208208Smckusick 	if (file == NULL) {
7218208Smckusick 		printf("Locked = %d\n", locked);
7228208Smckusick 		return(0);
7238208Smckusick 	}
7248208Smckusick 	if (locked)
7258208Smckusick 		return(0);
7269983Seric 	sprintf(curlock,"%s%s",file,".lock");
7278208Smckusick 	sprintf(locktmp,"%s/tmXXXXXX",MAILDIR);
7288208Smckusick 	mktemp(locktmp);
7298208Smckusick 	unlink(locktmp);
7308208Smckusick 	for (;;) {
7318208Smckusick 		f = lock1(locktmp, curlock);
7328208Smckusick 		if (f == 0) {
7338208Smckusick 			locked = 1;
7348208Smckusick 			return(0);
7358208Smckusick 		}
7368208Smckusick 		if (stat(curlock, &statbuf) < 0)
7378208Smckusick 			return(0);
7388208Smckusick 		time(&curtime);
7398208Smckusick 		if (curtime < statbuf.st_mtime + 30) {
7408208Smckusick 			sleep(5);
7418208Smckusick 			continue;
7428208Smckusick 		}
7438208Smckusick 		unlink(curlock);
7448208Smckusick 	}
7458208Smckusick }
7468208Smckusick 
7478208Smckusick /*
7488208Smckusick  * Remove the mail lock, and note that we no longer
7498208Smckusick  * have it locked.
7508208Smckusick  */
7518208Smckusick 
unlock()7528208Smckusick unlock()
7538208Smckusick {
7548208Smckusick 
7558208Smckusick 	if (locked)
7568208Smckusick 		unlink(curlock);
7578208Smckusick 	locked = 0;
7588208Smckusick }
7598208Smckusick 
7608208Smckusick /*
7618208Smckusick  * Attempt to set the lock by creating the temporary file,
7628208Smckusick  * then doing a link/unlink.  If it fails, return -1 else 0
7638208Smckusick  */
7648208Smckusick 
lock1(tempfile,name)7658208Smckusick lock1(tempfile, name)
7668208Smckusick 	char tempfile[], name[];
7678208Smckusick {
7688208Smckusick 	int fno;
7698208Smckusick 
7708208Smckusick 	fno = creat(tempfile, 0400);
7718208Smckusick 	if (fno < 0)
7728208Smckusick 		return(-1);
7738208Smckusick 	close(fno);
7748208Smckusick 	if (link(tempfile, name) < 0) {
7758208Smckusick 		unlink(tempfile);
7768208Smckusick 		return(-1);
7778208Smckusick 	}
7788208Smckusick 	unlink(tempfile);
7798208Smckusick 	return(0);
7808208Smckusick }
7818208Smckusick 
7828208Smckusick /*
7838208Smckusick 	stripfx(prefix string, pointer to string)
7848208Smckusick 
7858208Smckusick 	takes a ptr to string and compares it to prefix string.
7868208Smckusick 	may be called multiple times
7878208Smckusick 	returns ":username"
7888208Smckusick */
stripfx(pfx,name)7898208Smckusick stripfx(pfx, name)
7908208Smckusick 	register char *pfx;
7918208Smckusick 	register char **name;
7928208Smckusick {
7938208Smckusick 	register char *cp = *name;
7948208Smckusick 
7958208Smckusick 	while (*pfx && (*cp == *pfx || *cp == toupper(*pfx)))
7968208Smckusick 		cp++, pfx++;
7978208Smckusick 	if (*cp != ':' || *pfx != 0)
7988208Smckusick 		return;
7998208Smckusick 	*name = cp;
8008208Smckusick }
stripmach(pperson)8018208Smckusick stripmach(pperson)
8028208Smckusick register char **pperson;
8038208Smckusick {
8048208Smckusick # ifdef RAND
8058208Smckusick /* for machines at RAND */
8068208Smckusick # ifdef GRAPHICS
8078208Smckusick 	stripfx("g",pperson);
8088208Smckusick 	stripfx("graphics",pperson);
8098208Smckusick # endif
8108208Smckusick # ifdef TP
8118208Smckusick 	stripfx("t",pperson);
8128208Smckusick 	stripfx("tp",pperson);
8138208Smckusick # endif
8148208Smckusick # ifdef VAX
8158208Smckusick 	stripfx("v",pperson);
8168208Smckusick 	stripfx("vax",pperson);
8178208Smckusick # endif
8188208Smckusick /* end of defns for Rand */
8198208Smckusick # endif
8208208Smckusick 
8218208Smckusick # ifdef NOSC
8228208Smckusick /* for machines at NOSC */
8238208Smckusick # ifdef ATTS
8248208Smckusick 	stripfx("a",pperson);
8258208Smckusick 	stripfx("atts",pperson);
8268208Smckusick # endif
8278208Smckusick # ifdef CCMM
8288208Smckusick 	stripfx("c",pperson);
8298208Smckusick 	stripfx("ccmm",pperson);
8308208Smckusick # endif
8318208Smckusick # ifdef MSSF
8328208Smckusick 	stripfx("m",pperson);
8338208Smckusick 	stripfx("mssf",pperson);
8348208Smckusick # endif
8358208Smckusick /* end of defns for NOSC */
8368208Smckusick # endif
8378208Smckusick 
8388208Smckusick # ifdef BERKELEY
8398208Smckusick 
8408208Smckusick /* for Berkeley */
8418208Smckusick # ifdef A
8428208Smckusick 	stripfx("a",pperson);
8438208Smckusick # endif
8448208Smckusick # ifdef B
8458208Smckusick 	stripfx("b",pperson);
8468208Smckusick # endif
8478208Smckusick # ifdef C
8488208Smckusick 	stripfx("c",pperson);
8498208Smckusick # endif
8508208Smckusick # ifdef D
8518208Smckusick 	stripfx("d",pperson);
8528208Smckusick # endif
8538208Smckusick # ifdef E
8548208Smckusick 	stripfx("e",pperson);
8558208Smckusick # endif
8568208Smckusick # ifdef ING70
8578208Smckusick 	stripfx("i",pperson);
8588208Smckusick 	stripfx("ing70",pperson);
8598208Smckusick 	stripfx("ingres",pperson);
8608208Smckusick # endif
8618208Smckusick # ifdef INGVAX
8628208Smckusick 	stripfx("j",pperson);
8638208Smckusick 	stripfx("ingvax",pperson);
8648208Smckusick # endif
8658208Smckusick # ifdef VIRUS
8668208Smckusick 	stripfx("k",pperson);
8678208Smckusick 	stripfx("virus",pperson);
8688208Smckusick # endif
8698208Smckusick # ifdef IMAGE
8708208Smckusick 	stripfx("m",pperson);
8718208Smckusick 	stripfx("image",pperson);
8728208Smckusick # endif
8738208Smckusick # ifdef KIM
8748208Smckusick 	stripfx("n",pperson);
8758208Smckusick 	stripfx("kim",pperson);
8768208Smckusick # endif
8778208Smckusick # ifdef ESVAX
8788208Smckusick 	stripfx("o",pperson);
8798208Smckusick 	stripfx("esvax",pperson);
8808208Smckusick # endif
8818208Smckusick # ifdef Q
8828208Smckusick 	stripfx("q",pperson);
8838208Smckusick # endif
8848208Smckusick # ifdef ARPAVAX
8858208Smckusick 	stripfx("r",pperson);
8868208Smckusick 	stripfx("arpavax",pperson);
8878208Smckusick # endif
8888208Smckusick # ifdef SRC
8898208Smckusick 	stripfx("s",pperson);
8908208Smckusick 	stripfx("src",pperson);
8918208Smckusick # endif
8928208Smckusick # ifdef MATHSTAT
8938208Smckusick 	stripfx("t",pperson);
8948208Smckusick 	stripfx("mathstat",pperson);
8958208Smckusick # endif
8968208Smckusick # ifdef CSVAX
8978208Smckusick 	stripfx("v",pperson);
8988208Smckusick 	stripfx("vax",pperson);
8998208Smckusick 	stripfx("csvax",pperson);
9008208Smckusick # endif
9018208Smckusick # ifdef CORY
9028208Smckusick 	stripfx("y",pperson);
9038208Smckusick 	stripfx("cory",pperson);
9048208Smckusick # endif
9058208Smckusick # ifdef EECS40
9068208Smckusick 	stripfx("z",pperson);
9078208Smckusick 	stripfx("eecs40",pperson);
9088208Smckusick # endif
9098208Smckusick /* end of berkeley defns */
9108208Smckusick # endif
9118208Smckusick }
9128208Smckusick /*
9138208Smckusick    this removes the mail file sfn by either truncating it, as required
9148208Smckusick    on OLDMAIL systems, or unlinking it. If the unlink fails, we truncate it.
9158208Smckusick */
remove(sfn)9168208Smckusick remove(sfn)
9178208Smckusick char *sfn;
9188208Smckusick {
9198208Smckusick 	int i;
9208208Smckusick # ifdef OLDMAIL
9218208Smckusick 	i = creat(sfn,0666);
9228208Smckusick 	if(i >= 0)close(i);
9238208Smckusick # else
9248208Smckusick 	if(unlink(sfn) < 0){
9258208Smckusick 		i = creat(sfn,MAILMODE);
9268208Smckusick 		if(i >= 0)close(i);
9278208Smckusick 	}
9288208Smckusick # endif
9298208Smckusick }
930