mail.c

来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 1,321 行 · 第 1/2 页

C
1,321
字号
#ifndef lintstatic  char    *sccsid = "@(#)mail.c	4.3  (ULTRIX)        4/4/91";#endif lint/************************************************************************ *									* *			Copyright (c) 1984 by				* *		Digital Equipment Corporation, Maynard, MA		* *			All rights reserved.				* *									* *   This software is furnished under a license and may be used and	* *   copied  only  in accordance with the terms of such license and	* *   with the  inclusion  of  the  above  copyright  notice.   This	* *   software  or  any  other copies thereof may not be provided or	* *   otherwise made available to any other person.  No title to and	* *   ownership of the software is hereby transferred.			* *									* *   This software is  derived  from  software  received  from  the	* *   University    of   California,   Berkeley,   and   from   Bell	* *   Laboratories.  Use, duplication, or disclosure is  subject  to	* *   restrictions  under  license  agreements  with  University  of	* *   California and with AT&T.						* *									* *   The information in this software is subject to change  without	* *   notice  and should not be construed as a commitment by Digital	* *   Equipment Corporation.						* *									* *   Digital assumes no responsibility for the use  or  reliability	* *   of its software on equipment which is not supplied by Digital.	* *									* ************************************************************************//* * "binmail"   /usr/binmail * *	"@(#)mail.c	4.18 (Berkeley) 9/9/83"; * *	EDIT HISTORY: * *	19-Jan-89  John Haxby *		Having recoded safefile, the code that ensures that the file *		created with the right owner and mode turned out to be *		somewhat dodgy.  Changed MAILMODE to be the mode that the file *		is created with rather than the umask and removed the *		associated (and somewhat redundant) calls to umask().  Removed *		a misleading comment about calling chown() (it wasn't) and *		moved the setreuid() call from immediately before fdopen() *		(which doesn't open the file) to immediately before the *		safefile() which does.  Note that this UID swapping is *		primarily for the sake of NFS since root doesn't have *		sufficient privilege across NFS -- the call to safefile() to *		create the dead.letter file is not changed since we don't have *		a specific UID to set ourselves to.  Note that the code, at *		present, requires the spool directory to be world writeable, *		we should really have fallback code to try create the maildrop *		as root when we can't create it as the user. * *      20-Dec-89  John Haxby/Paul Sharpe *              Recoded safefile() to return a file-descriptor, but only when *              the file is (hopefully) definitely 'safe': else race *              conditions may allow unauthorised mailbox access. * *	15-Jun-88  John Haxby *		Increased size of 'truename' to prevent SIGSEGV *		(which, incidentally, causes endless looping through *	         the signal) * *	08-Jun-88  Mark Parenti *		Changed signal handlers to void. * *	22-Jan-88  John Haxby *		Added -e flag for X/OPEN. * *	27-Feb-1987  Ray Glaser *		Added logic to extend the wait time on stale lock *		files to be a function of the system load ave. * *	12-Feb-1987  Ray Glaser  *		Massive revision to the file locking logic for NFS. * *	15-Dec-1986  Marc Teitelbaum  - 0001 *		Only chown spool mailfile if we created it. *		Security reasons.  Also, bump timeout on *		waiting for lock to 60 seconds.  30 seems *		too low.  Flock would be preferable, but no *		time right now and much gastric distress. * *	aps00 10/26/83	-- added check for UID of uucp otherwise, would *				fail if mail is comming from off system, *				via uucp. *	02-Apr-84	mah.  Fix for gethostname for queued file.  This *				is to reflect 4.21 (Berkeley). * */#include <ctype.h>#include <stdio.h>#include <errno.h>#include <pwd.h>#include <utmp.h>#include <signal.h>#include <syslog.h>#include <sys/types.h>#include <sys/stat.h>#include <setjmp.h>#include <sysexits.h>#include <sys/file.h>#include <sys/ioctl.h>#include <sys/param.h>#include <nlist.h>#define SENDMAIL	"/usr/lib/sendmail"int OVERRIDE = 0;	/* Flag set if lock file overridden */int FIRSTSLEEP = 1;int LOCKSLEEP = 9;	/* Basic # seconds to sleep between checks for			 * name.lock file existance and to ck the			 * peak load ave.			 */#define OLOCKSLEEPS 19 int LOCKSLEEPS = OLOCKSLEEPS;	/* Basic # of times to sleep & wait for 			 	 * name.lock  file to disappear of its' 	 			 * own accord before we blow it away.		 		 */ /*copylet flags */	/*remote mail, add rmtmsg */#define REMOTE	1	/* zap header and trailing empty line */#define ZAP	3#define ORDINARY 2#define	FORWARD	4#define	LSIZE	256#define	MAXLET	300	/* maximum number of letters */#define	MAILMODE 0600	/* mode of created mail */struct	nlist Nl[] ={	{ "_avenrun" },#define	X_AVENRUN	0	{ 0 },};int load = 0;int peak = 1;	/* Peak load ave seen */int oload = 0;char hostname[255];char	line[LSIZE];char	resp[LSIZE];struct let {	long	adr;	char	change;} let[MAXLET];int	nlet	= 0;char	lfil[50];long	iop, time();char	*getenv();char	*index();char	lettmp[] = "/tmp/maXXXXX";char	maildir[] = "/usr/spool/mail/";char	mailfile[] = "/usr/spool/mail/xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx";char	dead[] = "dead.letter";char	*netname = "vax";char	forwmsg[] = " forwarded\n";FILE	*tmpf;FILE	*malf;char	*my_name;char	*getlogin();struct	passwd	*getpwuid();int	error;int	changed;int	forward;char	from[] = "From ";long	ftell();void	delete();char	*ctime();int	flgf;int	flgp;int	delflg = 1;int	hseqno;jmp_buf	sjbuf;int	rmail;main(argc, argv)char **argv;{	register i;	char sobuf[BUFSIZ];	setbuf(stdout, sobuf);	mktemp(lettmp);	unlink(lettmp);	my_name = getlogin();	if (my_name == NULL || strlen(my_name) == 0) {		struct passwd *pwent;		pwent = getpwuid(getuid());		if (pwent==NULL)			my_name = "???";		else			my_name = pwent->pw_name;	}	if(setjmp(sjbuf)) done();	for (i=SIGHUP; i<=SIGTERM; i++)		setsig(i, delete);	tmpf = fopen(lettmp, "w");	if (tmpf == NULL) {		fprintf(stderr, "mail: cannot open %s for writing\n", lettmp);		done();	}	if (argv[0][0] == 'r')		rmail++;	if (argv[0][0] != 'r' &&	/* no favors for rmail*/	   (argc == 1 || argv[1][0] == '-' && !any(argv[1][1], "rhd")))		printmail(argc, argv);	else		bulkmail(argc, argv);	done();}setsig(i, f)int i;void (*f)();{	if(signal(i, SIG_IGN)!=SIG_IGN)		signal(i, f);}any(c, str)	register int c;	register char *str;{	while (*str)		if (c == *str++)			return(1);	return(0);}printmail(argc, argv)char **argv;{	int flg, i, j, print, check = 0;	char *p, *getarg();	struct stat statb;	setuid(getuid());	cat(mailfile, maildir, my_name);	if (stat(mailfile, &statb) >= 0	    && (statb.st_mode & S_IFMT) == S_IFDIR) {		strcat(mailfile, "/");		strcat(mailfile, my_name);	}	for (; argc>1; argv++, argc--) {		if (argv[1][0]=='-') {			if (argv[1][1]=='q')				delflg = 0;			else if (argv[1][1]=='p') {				flgp++;				delflg = 0;			} else if (argv[1][1]=='f') {				if (argc>=3) {					strcpy(mailfile, argv[2]);					argv++;					argc--;				}			} else if (argv[1][1]=='r') {				forward = 1;			} else if (argv[1][1]=='h') {				forward = 1;			} else if (argv[1][1]=='e') {				check = 1;			} else {				fprintf(stderr, "mail: unknown option %c\n", argv[1][1]);				done();			}		} else			break;	}	malf = fopen(mailfile, "r");	if (malf == NULL) {		if (check) {			error = 1;			done();		} else {			fprintf(stdout, "No mail.\n");			return;		}	}	lock(mailfile);	copymt(malf, tmpf);	fclose(malf);/* PJS: Signal an error on failing to fclose. */	if (fclose(tmpf) == EOF) {		perror("mail");		done();	}	unlock();	if (check) {		error = nlet == 0;		done();	}	tmpf = fopen(lettmp, "r");	changed = 0;	print = 1;	for (i = 0; i < nlet; ) {		j = forward ? i : nlet - i - 1;		if(setjmp(sjbuf)) {			print=0;		} else {			if (print)				copylet(j, stdout, ORDINARY);			print = 1;		}		if (flgp) {			i++;			continue;		}		setjmp(sjbuf);		fprintf(stdout, "? ");		fflush(stdout);		if (fgets(resp, LSIZE, stdin) == NULL)			break;		switch (resp[0]) {		default:			fprintf(stderr, "usage\n");		case '?':			print = 0;			fprintf(stderr, "q\tquit\n");			fprintf(stderr, "x\texit without changing mail\n");			fprintf(stderr, "p\tprint\n");			fprintf(stderr, "s[file]\tsave (default mbox)\n");			fprintf(stderr, "w[file]\tsame without header\n");			fprintf(stderr, "-\tprint previous\n");			fprintf(stderr, "d\tdelete\n");			fprintf(stderr, "+\tnext (no delete)\n");			fprintf(stderr, "m user\tmail to user\n");			fprintf(stderr, "! cmd\texecute cmd\n");			break;		case '+':		case 'n':		case '\n':			i++;			break;		case 'x':			changed = 0;		case 'q':			goto donep;		case 'p':			break;		case '^':		case '-':			if (--i < 0)				i = 0;			break;		case 'y':		case 'w':		case 's':			flg = 0;			if (resp[1] != '\n' && resp[1] != ' ') {				printf("illegal\n");				flg++;				print = 0;				continue;			}			if (resp[1] == '\n' || resp[1] == '\0') {				p = getenv("HOME");				if(p != 0)					cat(resp+1, p, "/mbox");				else					cat(resp+1, "", "mbox");			}			for (p = resp+1; (p = getarg(lfil, p)) != NULL; ) {				malf = fopen(lfil, "a");				if (malf == NULL) {					fprintf(stdout, "mail: cannot append to %s\n", lfil);					flg++;					continue;				}				copylet(j, malf, resp[0]=='w'? ZAP: ORDINARY);/* PJS: Signal an error on failing to fclose. */				if (fclose(malf) == EOF) {					perror("mail");					done();				}			}			if (flg)				print = 0;			else {				let[j].change = 'd';				changed++;				i++;			}			break;		case 'm':			flg = 0;			if (resp[1] == '\n' || resp[1] == '\0') {				i++;				continue;			}			if (resp[1] != ' ') {				printf("invalid command\n");				flg++;				print = 0;				continue;			}			for (p = resp+1; (p = getarg(lfil, p)) != NULL; )				if (!sendrmt(j, lfil, "/bin/mail"))	/* couldn't send it */					flg++;			if (flg)				print = 0;			else {				let[j].change = 'd';				changed++;				i++;			}			break;		case '!':			system(resp+1);			printf("!\n");			print = 0;			break;		case 'd':			let[j].change = 'd';			changed++;			i++;			if (resp[1] == 'q')				goto donep;			break;		}	}   donep:	if (changed)		copyback();}copyback()	/* copy temp or whatever back to /usr/spool/mail */{	register i, n, c;	int new = 0;	struct stat stbuf;	signal(SIGINT, SIG_IGN);	signal(SIGHUP, SIG_IGN);	signal(SIGQUIT, SIG_IGN);	lock(mailfile);	stat(mailfile, &stbuf);	if (stbuf.st_size != let[nlet].adr) {	/* new mail has arrived */		malf = fopen(mailfile, "r");		if (malf == NULL) {			fprintf(stdout, "mail: can't re-read %s\n", mailfile);			done();		}		fseek(malf, let[nlet].adr, 0);		fclose(tmpf);		tmpf = fopen(lettmp, "a");		fseek(tmpf, let[nlet].adr, 0);/* PJS: Test the putc, in case there is no more file space... */		while ((c = fgetc(malf)) != EOF)			if (fputc(c, tmpf) != c) {				perror("mail");				done();			}/* PJS: Test the closing of the file, in case there is no more file space. */		if (fclose(malf) == EOF) {			perror("mail");			done();		}		if (fclose(tmpf) == EOF) {			perror("mail");			done();		}		tmpf = fopen(lettmp, "r");		let[++nlet].adr = stbuf.st_size;		new = 1;	}	malf = fopen(mailfile, "w");	if (malf == NULL) {		fprintf(stderr, "mail: can't rewrite %s\n", lfil);		done();	}	n = 0;	for (i = 0; i < nlet; i++)		if (let[i].change != 'd') {			copylet(i, malf, ORDINARY);			n++;		}/* PJS: test closing of mailfile, in case there is no more file space. */	if (fclose(malf) == EOF) {		fprintf(stderr,"mail: can't close copied mailfile '%s'\n",					mailfile);		done();	}	if (new)		fprintf(stdout, "new mail arrived\n");	unlock();}copymt(f1, f2)	/* copy mail (f1) to temp (f2) */FILE *f1, *f2;{	long nextadr;	nlet = nextadr = 0;	let[0].adr = 0;	while (fgets(line, LSIZE, f1) != NULL) {		if (isfrom(line))			let[nlet++].adr = nextadr;		nextadr += strlen(line);/* PJS: Test for output, in case there is no more file space. */		if (fputs(line, f2) < 0) {			perror("mail");			done();		}	}	let[nlet].adr = nextadr;	/* last plus 1 */}copylet(n, f, type)	FILE *f;{	int ch;	long k;	fseek(tmpf, let[n].adr, 0);	k = let[n+1].adr - let[n].adr;	while(k-- > 1 && (ch=fgetc(tmpf))!='\n')		if(type!=ZAP)/* PJS: Test for output, in case there is no more file space. */			if (fputc(ch,f) != ch) {				perror("mail");				done();			}	if(type==REMOTE) {		char hostname[32];		gethostname(hostname, sizeof (hostname));		fprintf(f, " remote from %s\n", hostname);	} else if (type==FORWARD)		fprintf(f, forwmsg);	else if(type==ORDINARY)/* PJS: Test for output, in case there is no more file space. */		if (fputc(ch,f) != ch) {			perror("mail");			done();		}/* PJS: Test for output, in case there is no more file space. */	while(k-->1) {		ch=fgetc(tmpf);		if (fputc(ch, f) != ch) {			perror("mail");			done();		}	}/* PJS: Test for output, in case there is no more file space. */	if(type!=ZAP || ch!= '\n') {		ch = fgetc(tmpf);		if (fputc(ch, f) != ch) {			perror("mail");			done();		}	}}isfrom(lp)register char *lp;{	register char *p;	for (p = from; *p; )		if (*lp++ != *p++)			return(0);	return(1);}bulkmail(argc, argv)char **argv;{	char truename[1024];	/* maximum permitted by sendmail */	int first;	register char *cp;	int gaver = 0;	char *newargv[1000];	register char **ap;	register char **vp;	int dflag;	int	mald;		/* 'safe' file desc returned for mail spool */	dflag = 0;	if (argc < 1)		fprintf(stderr, "puke\n");	for (vp = argv, ap = newargv + 1; (*ap = *vp++) != 0; ap++)	{		if (ap[0][0] == '-' && ap[0][1] == 'd')			dflag++;	}	if (!dflag)	{		/* give it to sendmail, rah rah! */		unlink(lettmp);		ap = newargv+1;		if (rmail)			*ap-- = "-s";		*ap = "-sendmail";		setuid(getuid());		execv(SENDMAIL, ap);		perror(SENDMAIL);		exit(EX_UNAVAILABLE);	}	truename[0] = 0;	line[0] = '\0';	/*	 * When we fall out of this, argv[1] should be first name,	 * argc should be number of names + 1.	 */	while (argc > 1 && *argv[1] == '-') {		cp = *++argv;		argc--;		switch (cp[1]) {		case 'r':			if (argc <= 0) {				fprintf(stderr,				  "r flag needs more argument\n");				usage();				done();			}			gaver++;			strcpy(truename, argv[1]);			fgets(line, LSIZE, stdin);			if (strcmpn("From", line, 4) == 0)				line[0] = '\0';			argv++;			argc--;			break;		case 'h':			if (argc <= 0) {				fprintf(stderr,				  "h flag needs more arguments\n");				usage();				done();			}			hseqno = atoi(argv[1]);			argv++;			argc--;			break;

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?