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

📄 queue.c

📁 <B>Digital的Unix操作系统VAX 4.2源码</B>
💻 C
📖 第 1 页 / 共 2 页
字号:
#ifndef lintstatic	char	*sccsid = "@(#)queue.c	4.1	(ULTRIX)	7/2/90";#endif lint/************************************************************************ *									* *			Copyright (c) 1987 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.	* *									* ************************************************************************/# include "sendmail.h"# include <pwd.h># include <sys/stat.h># include <sys/dir.h># include <signal.h># include <errno.h># ifndef QUEUE# ifndef lintstatic char	SccsId[] = "@(#)queue.c @(#)queue.c	1.1 (ULTRIX) 7/17/87 (no queueing)";# endif not lint# else QUEUE# ifndef lintstatic char	SccsId[] = "@(#)queue.c @(#)queue.c	1.1 (ULTRIX) 7/17/87 (with queueing)";# endif not lint/***  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.*/queueup(e, queueall, announce)	register ENVELOPE *e;	bool queueall;	bool announce;{	char *tf;	char *qf;	char buf[MAXLINE];	register FILE *tfp;	register HDR *h;	register ADDRESS *q;	MAILER nullmailer;	/*	**  Create control file.	*/	tf = newstr(queuename(e, 't'));	tfp = fopen(tf, "w");	if (tfp == NULL)	{		syserr("queueup: cannot create temp file %s", tf);		return;	}	(void) chmod(tf, FileMode);# ifdef DEBUG	if (tTd(40, 1))		printf("queueing %s\n", e->e_id);# endif DEBUG	/*	**  If there is no data file yet, create one.	*/	if (e->e_df == NULL)	{		register FILE *dfp;		extern putbody();		e->e_df = newstr(queuename(e, 'd'));		dfp = fopen(e->e_df, "w");		if (dfp == NULL)		{			syserr("queueup: cannot create %s", e->e_df);			(void) fclose(tfp);			return;		}		(void) chmod(e->e_df, FileMode);		(*e->e_putbody)(dfp, ProgMailer, e);		(void) fclose(dfp);		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 name of data file */	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);	/* output name of sender */	fprintf(tfp, "S%s\n", e->e_from.q_paddr);	/* output list of recipient addresses */	for (q = e->e_sendqueue; q != NULL; q = q->q_next)	{		if (queueall ? !bitset(QDONTSEND, q->q_flags) :			       bitset(QQUEUEUP, q->q_flags))		{			char *ctluser, *getctluser();			bool badctladdr();			if (badctladdr(q))	/* sanity/safety */				continue;			if ((ctluser = getctluser(q)) == NULL)				fprintf(tfp, "R%s\n", q->q_paddr);			else				fprintf(tfp, "R(%s) %s\n", ctluser, q->q_paddr);			if (announce)			{				e->e_to = q->q_paddr;				message(Arpa_Info, "queued");				if (LogLevel > 4)					logdelivery("queued");				e->e_to = NULL;			}#ifdef DEBUG			if (tTd(40, 1))			{				printf("queueing ");				printaddr(q, FALSE);			}#endif DEBUG		}	}	/* output list of error recipients */	for (q = e->e_errorqueue; q != NULL; q = q->q_next)	{		if (!bitset(QDONTSEND, q->q_flags))		{			char *ctluser, *getctluser();			bool badctladdr();			if (badctladdr(q))	/* sanity/safety */				continue;			if ((ctluser = getctluser(q)) == NULL)				fprintf(tfp, "E%s\n", q->q_paddr);			else				fprintf(tfp, "E(%s) %s\n", ctluser, q->q_paddr);		}	}	/*	**  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_r_rwset = nullmailer.m_s_rwset = -1;	nullmailer.m_eol = "\n";	define('g', "\001f", 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;		/* 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))		{			(void) expand(h->h_value, buf, &buf[sizeof buf], e);			fprintf(tfp, "%s: %s\n", h->h_field, buf);		}		else if (bitset(H_FROM|H_RCPT, h->h_flags))		{			commaize(h, h->h_value, tfp, bitset(EF_OLDSTYLE, e->e_flags),				 &nullmailer);		}		else			fprintf(tfp, "%s: %s\n", h->h_field, h->h_value);	}	/*	**  Clean up.	*/	(void) fclose(tfp);	qf = queuename(e, 'q');	if (tf != NULL)	{		(void) unlink(qf);		if (rename(tf, qf) < 0)			syserr("cannot unlink(%s, %s), df=%s", tf, qf, e->e_df);		errno = 0;	}# ifdef LOG	/* save log info */	if (LogLevel > 15)		syslog(LOG_INFO, "%s: queueup, qf=%s, df=%s\n", e->e_id, qf, e->e_df);# endif LOG}/***  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.*/runqueue(forkflag)	bool forkflag;{	extern bool shouldqueue();	/*	**  If no work will ever be selected, don't even bother reading	**  the queue.	*/	if (shouldqueue(-100000000L))	{		if (Verbose)			printf("Skipping queue run -- load average too high\n");		if (forkflag)			return;		finis();	}	/*	**  See if we want to go off and do other useful work.	*/	if (forkflag)	{		int pid;		pid = dofork();		if (pid != 0)		{			extern reapchild();			/* parent -- pick up intermediate zombie */#ifndef SIGCHLD			(void) waitfor(pid);#else SIGCHLD			(void) signal(SIGCHLD, reapchild);#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) signal(SIGCHLD, SIG_DFL);#endif SIGCHLD	}	setproctitle("running queue");# ifdef LOG	if (LogLevel > 11)		syslog(LOG_INFO, "runqueue %s, pid=%d", QueueDir, getpid());# endif LOG	/*	**  Release any resources used by the daemon code.	*/# ifdef DAEMON	clrdaemon();# endif DAEMON	/*	**  Make sure the alias database is open.	*/	initaliases(AliasFile, FALSE);	/*	**  Start making passes through the queue.	**	First, read and sort the entire queue.	**	Then, process the work in that order.	**		But if you take too long, start over.	*/	/* order the existing work requests */	(void) orderq(FALSE);	/* process them once at a time */	while (WorkQ != NULL)	{		WORK *w = WorkQ;		WorkQ = WorkQ->w_next;		dowork(w);		free(w->w_name);		free((char *) w);	}	finis();}/***  ORDERQ -- order the work queue.****	Parameters:**		doall -- if set, include everything in the queue (even**			the jobs that cannot be run because the load**			average is too high).  Otherwise, exclude those**			jobs.****	Returns:**		The number of request in the queue (not necessarily**		the number of requests in WorkQ however).****	Side Effects:**		Sets WorkQ to the queue of available work, in order.*/# define NEED_P		001# define NEED_T		002orderq(doall)	bool doall;{	register struct direct *d;	register WORK *w;	DIR *f;	register int i;	WORK wlist[QUEUESIZE+1];	int wn = -1;	extern workcmpf();	/* clear out old WorkQ */	for (w = WorkQ; w != NULL; )	{		register WORK *nw = w->w_next;		WorkQ = nw;		free(w->w_name);		free((char *) w);		w = nw;	}	/* open the queue directory */	f = opendir(".");	if (f == NULL)	{		syserr("orderq: cannot open \"%s\" as \".\"", QueueDir);		return (0);	}	/*	**  Read the work directory.	*/	while ((d = readdir(f)) != NULL)	{		FILE *cf;		char lbuf[MAXNAME];		/* is this an interesting entry? */		if (d->d_name[0] != 'q' || d->d_name[1] != 'f')			continue;		/* yes -- open control file (if not too many files) */		if (++wn >= QUEUESIZE)			continue;		cf = fopen(d->d_name, "r");		if (cf == NULL)		{			/* this may be some random person sending hir msgs */			/* syserr("orderq: cannot open %s", cbuf); */#ifdef DEBUG			if (tTd(41, 2))				printf("orderq: cannot open %s (%d)\n",					d->d_name, errno);#endif DEBUG			errno = 0;			wn--;			continue;		}		w = &wlist[wn];		w->w_name = newstr(d->d_name);		/* make sure jobs in creation don't clog queue */		w->w_pri = 0x7fffffff;		w->w_ctime = 0;		/* extract useful information */		i = NEED_P | NEED_T;		while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)		{			extern long atol();			switch (lbuf[0])			{			  case 'P':				w->w_pri = atol(&lbuf[1]);				i &= ~NEED_P;				break;			  case 'T':				w->w_ctime = atol(&lbuf[1]);				i &= ~NEED_T;				break;			}		}		(void) fclose(cf);		if (!doall && shouldqueue(w->w_pri))		{			/* don't even bother sorting this job in */			wn--;		}	}	(void) closedir(f);	wn++;	/*	**  Sort the work directory.	*/	qsort((char *) wlist, min(wn, QUEUESIZE), sizeof *wlist, workcmpf);	/*	**  Convert the work list into canonical form.	**	Should be turning it into a list of envelopes here perhaps.	*/	WorkQ = NULL;	for (i = min(wn, QUEUESIZE); --i >= 0; )	{		w = (WORK *) xalloc(sizeof *w);		w->w_name = wlist[i].w_name;		w->w_pri = wlist[i].w_pri;		w->w_ctime = wlist[i].w_ctime;		w->w_next = WorkQ;		WorkQ = w;	}# ifdef DEBUG	if (tTd(40, 1))	{		for (w = WorkQ; w != NULL; w = w->w_next)			printf("%32s: pri=%ld\n", w->w_name, w->w_pri);	}# endif DEBUG	return (wn);}/***  WORKCMPF -- compare function for ordering work.****	Parameters:**		a -- the first argument.**		b -- the second argument.****	Returns:**		-1 if a < b**		 0 if a == b**		+1 if a > b****	Side Effects:**		none.*/workcmpf(a, b)	register WORK *a;	register WORK *b;{	long pa = a->w_pri + a->w_ctime;	long pb = b->w_pri + b->w_ctime;	if (pa == pb)		return (0);	else if (pa > pb)		return (1);	else		return (-1);}/***  DOWORK -- do a work request.****	Parameters:**		w -- the work request to be satisfied.****	Returns:**		none.****	Side Effects:**		The work request is satisfied if possible.*/dowork(w)	register WORK *w;{	register int i;	extern bool shouldqueue();# ifdef DEBUG	if (tTd(40, 1))		printf("dowork: %s pri %ld\n", w->w_name, w->w_pri);# endif DEBUG	/*	**  Ignore jobs that are too expensive for the moment.	*/	if (shouldqueue(w->w_pri))	{		if (Verbose)			printf("\nSkipping %s\n", w->w_name + 2);		return;	}	/*	**  Fork for work.	*/	if (ForkQueueRuns)	{		i = fork();		if (i < 0)		{			syserr("dowork: cannot fork");			return;		}	}	else	{		i = 0;	}	if (i == 0)	{		/*		**  CHILD		**	Lock the control file to avoid duplicate deliveries.		**		Then run the file as though we had just read it.		**	We save an idea of the temporary name so we		**		can recover on interrupt.		*/		/* set basic modes, etc. */		(void) alarm(0);		clearenvelope(CurEnv, FALSE);		QueueRun = TRUE;		ErrorMode = EM_MAIL;		CurEnv->e_id = &w->w_name[2];# ifdef LOG		if (LogLevel > 11)

⌨️ 快捷键说明

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