⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 queue.c

📁 早期freebsd实现
💻 C
📖 第 1 页 / 共 3 页
字号:
/* * Copyright (c) 1983 Eric P. Allman * Copyright (c) 1988, 1993 *	The Regents of the University of California.  All rights reserved. * * Redistribution and use in source and binary forms, with or without * modification, are permitted provided that the following conditions * are met: * 1. Redistributions of source code must retain the above copyright *    notice, this list of conditions and the following disclaimer. * 2. Redistributions in binary form must reproduce the above copyright *    notice, this list of conditions and the following disclaimer in the *    documentation and/or other materials provided with the distribution. * 3. All advertising materials mentioning features or use of this software *    must display the following acknowledgement: *	This product includes software developed by the University of *	California, Berkeley and its contributors. * 4. Neither the name of the University nor the names of its contributors *    may be used to endorse or promote products derived from this software *    without specific prior written permission. * * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF * SUCH DAMAGE. */# include "sendmail.h"#ifndef lint#ifdef QUEUEstatic char sccsid[] = "@(#)queue.c	8.41 (Berkeley) 4/18/94 (with queueing)";#elsestatic char sccsid[] = "@(#)queue.c	8.41 (Berkeley) 4/18/94 (without queueing)";#endif#endif /* not lint */# include <errno.h># include <pwd.h># include <dirent.h># ifdef QUEUE/***  Work queue.*/struct work{	char		*w_name;	/* name of control file */	long		w_pri;		/* priority of message, see below */	time_t		w_ctime;	/* creation time of message */	struct work	*w_next;	/* next in queue */};typedef struct work	WORK;WORK	*WorkQ;			/* queue of things to be done *//***  QUEUEUP -- queue a message up for future transmission.****	Parameters:**		e -- the envelope to queue up.**		queueall -- if TRUE, queue all addresses, rather than**			just those with the QQUEUEUP flag set.**		announce -- if TRUE, tell when you are queueing up.****	Returns:**		none.****	Side Effects:**		The current request are saved in a control file.**		The queue file is left locked.*/queueup(e, queueall, announce)	register ENVELOPE *e;	bool queueall;	bool announce;{	char *qf;	register FILE *tfp;	register HDR *h;	register ADDRESS *q;	int fd;	int i;	bool newid;	register char *p;	MAILER nullmailer;	MCI mcibuf;	char buf[MAXLINE], tf[MAXLINE];	/*	**  Create control file.	*/	newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);	/* if newid, queuename will create a locked qf file in e->lockfp */	strcpy(tf, queuename(e, 't'));	tfp = e->e_lockfp;	if (tfp == NULL)		newid = FALSE;	/* if newid, just write the qf file directly (instead of tf file) */	if (!newid)	{		/* get a locked tf file */		for (i = 0; i < 128; i++)		{			fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);			if (fd < 0)			{				if (errno != EEXIST)					break;#ifdef LOG				if (LogLevel > 0 && (i % 32) == 0)					syslog(LOG_ALERT, "queueup: cannot create %s, uid=%d: %s",						tf, geteuid(), errstring(errno));#endif			}			else			{				if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB))					break;#ifdef LOG				else if (LogLevel > 0 && (i % 32) == 0)					syslog(LOG_ALERT, "queueup: cannot lock %s: %s",						tf, errstring(errno));#endif				close(fd);			}			if ((i % 32) == 31)			{				/* save the old temp file away */				(void) rename(tf, queuename(e, 'T'));			}			else				sleep(i % 32);		}		if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL)		{			printopenfds(TRUE);			syserr("!queueup: cannot create queue temp file %s, uid=%d",				tf, geteuid());		}	}	if (tTd(40, 1))		printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id,			newid ? " (new id)" : "");	if (tTd(40, 9))	{		printf("  tfp=");		dumpfd(fileno(tfp), TRUE, FALSE);		printf("  lockfp=");		if (e->e_lockfp == NULL)			printf("NULL\n");		else			dumpfd(fileno(e->e_lockfp), TRUE, FALSE);	}	/*	**  If there is no data file yet, create one.	*/	if (e->e_df == NULL)	{		register FILE *dfp;		extern putbody();		e->e_df = queuename(e, 'd');		e->e_df = newstr(e->e_df);		fd = open(e->e_df, O_WRONLY|O_CREAT|O_TRUNC, FileMode);		if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL)			syserr("!queueup: cannot create data temp file %s, uid=%d",				e->e_df, geteuid());		bzero(&mcibuf, sizeof mcibuf);		mcibuf.mci_out = dfp;		mcibuf.mci_mailer = FileMailer;		(*e->e_putbody)(&mcibuf, e, NULL);		(void) xfclose(dfp, "queueup dfp", e->e_id);		e->e_putbody = putbody;	}	/*	**  Output future work requests.	**	Priority and creation time should be first, since	**	they are required by orderq.	*/	/* output message priority */	fprintf(tfp, "P%ld\n", e->e_msgpriority);	/* output creation time */	fprintf(tfp, "T%ld\n", e->e_ctime);	/* output type and name of data file */	if (e->e_bodytype != NULL)		fprintf(tfp, "B%s\n", e->e_bodytype);	fprintf(tfp, "D%s\n", e->e_df);	/* message from envelope, if it exists */	if (e->e_message != NULL)		fprintf(tfp, "M%s\n", e->e_message);	/* send various flag bits through */	p = buf;	if (bitset(EF_WARNING, e->e_flags))		*p++ = 'w';	if (bitset(EF_RESPONSE, e->e_flags))		*p++ = 'r';	*p++ = '\0';	if (buf[0] != '\0')		fprintf(tfp, "F%s\n", buf);	/* $r and $s and $_ macro values */	if ((p = macvalue('r', e)) != NULL)		fprintf(tfp, "$r%s\n", p);	if ((p = macvalue('s', e)) != NULL)		fprintf(tfp, "$s%s\n", p);	if ((p = macvalue('_', e)) != NULL)		fprintf(tfp, "$_%s\n", p);	/* output name of sender */	fprintf(tfp, "S%s\n", e->e_from.q_paddr);	/* output list of error recipients */	printctladdr(NULL, NULL);	for (q = e->e_errorqueue; q != NULL; q = q->q_next)	{		if (!bitset(QDONTSEND|QBADADDR, q->q_flags))		{			printctladdr(q, tfp);			fprintf(tfp, "E%s\n", q->q_paddr);		}	}	/* output list of recipient addresses */	for (q = e->e_sendqueue; q != NULL; q = q->q_next)	{		if (bitset(QQUEUEUP, q->q_flags) ||		    (queueall && !bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags)))		{			printctladdr(q, tfp);			fprintf(tfp, "R%s\n", q->q_paddr);			if (announce)			{				e->e_to = q->q_paddr;				message("queued");				if (LogLevel > 8)					logdelivery(NULL, NULL, "queued", NULL, e);				e->e_to = NULL;			}			if (tTd(40, 1))			{				printf("queueing ");				printaddr(q, FALSE);			}		}	}	/*	**  Output headers for this message.	**	Expand macros completely here.  Queue run will deal with	**	everything as absolute headers.	**		All headers that must be relative to the recipient	**		can be cracked later.	**	We set up a "null mailer" -- i.e., a mailer that will have	**	no effect on the addresses as they are output.	*/	bzero((char *) &nullmailer, sizeof nullmailer);	nullmailer.m_re_rwset = nullmailer.m_rh_rwset =			nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;	nullmailer.m_eol = "\n";	bzero(&mcibuf, sizeof mcibuf);	mcibuf.mci_mailer = &nullmailer;	mcibuf.mci_out = tfp;	define('g', "\201f", e);	for (h = e->e_header; h != NULL; h = h->h_link)	{		extern bool bitzerop();		/* don't output null headers */		if (h->h_value == NULL || h->h_value[0] == '\0')			continue;		/* don't output resent headers on non-resent messages */		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))			continue;		/* expand macros; if null, don't output header at all */		if (bitset(H_DEFAULT, h->h_flags))		{			(void) expand(h->h_value, buf, &buf[sizeof buf], e);			if (buf[0] == '\0')				continue;		}		/* output this header */		fprintf(tfp, "H");		/* if conditional, output the set of conditions */		if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags))		{			int j;			(void) putc('?', tfp);			for (j = '\0'; j <= '\177'; j++)				if (bitnset(j, h->h_mflags))					(void) putc(j, tfp);			(void) putc('?', tfp);		}		/* output the header: expand macros, convert addresses */		if (bitset(H_DEFAULT, h->h_flags))		{			fprintf(tfp, "%s: %s\n", h->h_field, buf);		}		else if (bitset(H_FROM|H_RCPT, h->h_flags))		{			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);			FILE *savetrace = TrafficLogFile;			TrafficLogFile = NULL;			if (bitset(H_FROM, h->h_flags))				oldstyle = FALSE;			commaize(h, h->h_value, oldstyle, &mcibuf, e);			TrafficLogFile = savetrace;		}		else			fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);	}	/*	**  Clean up.	*/	if (fflush(tfp) < 0 || fsync(fileno(tfp)) < 0 || ferror(tfp))	{		if (newid)			syserr("!552 Error writing control file %s", tf);		else			syserr("!452 Error writing control file %s", tf);	}	if (!newid)	{		/* rename (locked) tf to be (locked) qf */		qf = queuename(e, 'q');		if (rename(tf, qf) < 0)			syserr("cannot rename(%s, %s), df=%s, uid=%d",				tf, qf, e->e_df, geteuid());		/* close and unlock old (locked) qf */		if (e->e_lockfp != NULL)			(void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id);		e->e_lockfp = tfp;	}	else		qf = tf;	errno = 0;	e->e_flags |= EF_INQUEUE;# ifdef LOG	/* save log info */	if (LogLevel > 79)		syslog(LOG_DEBUG, "%s: queueup, qf=%s, df=%s\n", e->e_id, qf, e->e_df);# endif /* LOG */	if (tTd(40, 1))		printf("<<<<< done queueing %s <<<<<\n\n", e->e_id);	return;}printctladdr(a, tfp)	register ADDRESS *a;	FILE *tfp;{	char *uname;	register struct passwd *pw;	register ADDRESS *q;	uid_t uid;	static ADDRESS *lastctladdr;	static uid_t lastuid;	/* initialization */	if (a == NULL || a->q_alias == NULL || tfp == NULL)	{		if (lastctladdr != NULL && tfp != NULL)			fprintf(tfp, "C\n");		lastctladdr = NULL;		lastuid = 0;		return;	}	/* find the active uid */	q = getctladdr(a);	if (q == NULL)		uid = 0;	else		uid = q->q_uid;	a = a->q_alias;	/* check to see if this is the same as last time */	if (lastctladdr != NULL && uid == lastuid &&	    strcmp(lastctladdr->q_paddr, a->q_paddr) == 0)		return;	lastuid = uid;	lastctladdr = a;	if (uid == 0 || (pw = getpwuid(uid)) == NULL)		uname = "";	else		uname = pw->pw_name;	fprintf(tfp, "C%s:%s\n", uname, a->q_paddr);}/***  RUNQUEUE -- run the jobs in the queue.****	Gets the stuff out of the queue in some presumably logical**	order and processes them.****	Parameters:**		forkflag -- TRUE if the queue scanning should be done in**			a child process.  We double-fork so it is not our**			child and we don't have to clean up after it.****	Returns:**		none.****	Side Effects:**		runs things in the mail queue.*/ENVELOPE	QueueEnvelope;		/* the queue run envelope */runqueue(forkflag)	bool forkflag;{	register ENVELOPE *e;	extern ENVELOPE BlankEnvelope;	/*	**  If no work will ever be selected, don't even bother reading	**  the queue.	*/	CurrentLA = getla();	/* get load average */	if (shouldqueue(0L, curtime()))	{		if (Verbose)			printf("Skipping queue run -- load average too high\n");		if (forkflag && QueueIntvl != 0)			(void) setevent(QueueIntvl, runqueue, TRUE);		return;	}	/*	**  See if we want to go off and do other useful work.	*/	if (forkflag)	{		int pid;#ifdef SIGCHLD		extern void reapchild();		(void) setsignal(SIGCHLD, reapchild);#endif		pid = dofork();		if (pid != 0)		{			/* parent -- pick up intermediate zombie */#ifndef SIGCHLD			(void) waitfor(pid);#endif /* SIGCHLD */			if (QueueIntvl != 0)				(void) setevent(QueueIntvl, runqueue, TRUE);			return;		}		/* child -- double fork */#ifndef SIGCHLD		if (fork() != 0)			exit(EX_OK);#else /* SIGCHLD */		(void) setsignal(SIGCHLD, SIG_DFL);#endif /* SIGCHLD */	}	setproctitle("running queue: %s", QueueDir);# ifdef LOG	if (LogLevel > 69)		syslog(LOG_DEBUG, "runqueue %s, pid=%d, forkflag=%d",			QueueDir, getpid(), forkflag);# endif /* LOG */	/*	**  Release any resources used by the daemon code.	*/# ifdef DAEMON	clrdaemon();# endif /* DAEMON */	/* force it to run expensive jobs */

⌨️ 快捷键说明

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