queue.c revision 38032
1/*
2 * Copyright (c) 1998 Sendmail, Inc.  All rights reserved.
3 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
4 * Copyright (c) 1988, 1993
5 *	The Regents of the University of California.  All rights reserved.
6 *
7 * By using this file, you agree to the terms and conditions set
8 * forth in the LICENSE file which can be found at the top level of
9 * the sendmail distribution.
10 *
11 */
12
13# include "sendmail.h"
14
15#ifndef lint
16#if QUEUE
17static char sccsid[] = "@(#)queue.c	8.202 (Berkeley) 6/15/98 (with queueing)";
18#else
19static char sccsid[] = "@(#)queue.c	8.202 (Berkeley) 6/15/98 (without queueing)";
20#endif
21#endif /* not lint */
22
23# include <errno.h>
24# include <dirent.h>
25
26# if QUEUE
27
28/*
29**  Work queue.
30*/
31
32struct work
33{
34	char		*w_name;	/* name of control file */
35	char		*w_host;	/* name of recipient host */
36	bool		w_lock;		/* is message locked? */
37	bool		w_tooyoung;	/* is it too young to run? */
38	long		w_pri;		/* priority of message, see below */
39	time_t		w_ctime;	/* creation time of message */
40	struct work	*w_next;	/* next in queue */
41};
42
43typedef struct work	WORK;
44
45WORK	*WorkQ;			/* queue of things to be done */
46
47#define QF_VERSION	2	/* version number of this queue format */
48
49extern int orderq __P((bool));
50/*
51**  QUEUEUP -- queue a message up for future transmission.
52**
53**	Parameters:
54**		e -- the envelope to queue up.
55**		announce -- if TRUE, tell when you are queueing up.
56**
57**	Returns:
58**		none.
59**
60**	Side Effects:
61**		The current request are saved in a control file.
62**		The queue file is left locked.
63*/
64
65void
66queueup(e, announce)
67	register ENVELOPE *e;
68	bool announce;
69{
70	char *qf;
71	register FILE *tfp;
72	register HDR *h;
73	register ADDRESS *q;
74	int fd;
75	int i;
76	bool newid;
77	register char *p;
78	MAILER nullmailer;
79	MCI mcibuf;
80	char tf[MAXQFNAME];
81	char buf[MAXLINE];
82	extern void printctladdr __P((ADDRESS *, FILE *));
83
84	/*
85	**  Create control file.
86	*/
87
88	newid = (e->e_id == NULL) || !bitset(EF_INQUEUE, e->e_flags);
89
90	/* if newid, queuename will create a locked qf file in e->lockfp */
91	strcpy(tf, queuename(e, 't'));
92	tfp = e->e_lockfp;
93	if (tfp == NULL)
94		newid = FALSE;
95
96	/* if newid, just write the qf file directly (instead of tf file) */
97	if (!newid)
98	{
99		/* get a locked tf file */
100		for (i = 0; i < 128; i++)
101		{
102			fd = open(tf, O_CREAT|O_WRONLY|O_EXCL, FileMode);
103			if (fd < 0)
104			{
105				if (errno != EEXIST)
106					break;
107				if (LogLevel > 0 && (i % 32) == 0)
108					sm_syslog(LOG_ALERT, e->e_id,
109						"queueup: cannot create %s, uid=%d: %s",
110						tf, geteuid(), errstring(errno));
111			}
112			else
113			{
114				if (lockfile(fd, tf, NULL, LOCK_EX|LOCK_NB))
115					break;
116				else if (LogLevel > 0 && (i % 32) == 0)
117					sm_syslog(LOG_ALERT, e->e_id,
118						"queueup: cannot lock %s: %s",
119						tf, errstring(errno));
120				close(fd);
121			}
122
123			if ((i % 32) == 31)
124			{
125				/* save the old temp file away */
126				(void) rename(tf, queuename(e, 'T'));
127			}
128			else
129				sleep(i % 32);
130		}
131		if (fd < 0 || (tfp = fdopen(fd, "w")) == NULL)
132		{
133			printopenfds(TRUE);
134			syserr("!queueup: cannot create queue temp file %s, uid=%d",
135				tf, geteuid());
136		}
137	}
138
139	if (tTd(40, 1))
140		printf("\n>>>>> queueing %s%s >>>>>\n", e->e_id,
141			newid ? " (new id)" : "");
142	if (tTd(40, 3))
143	{
144		extern void printenvflags __P((ENVELOPE *));
145
146		printf("  e_flags=");
147		printenvflags(e);
148	}
149	if (tTd(40, 32))
150	{
151		printf("  sendq=");
152		printaddr(e->e_sendqueue, TRUE);
153	}
154	if (tTd(40, 9))
155	{
156		printf("  tfp=");
157		dumpfd(fileno(tfp), TRUE, FALSE);
158		printf("  lockfp=");
159		if (e->e_lockfp == NULL)
160			printf("NULL\n");
161		else
162			dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
163	}
164
165	/*
166	**  If there is no data file yet, create one.
167	*/
168
169	if (!bitset(EF_HAS_DF, e->e_flags))
170	{
171		register FILE *dfp = NULL;
172		char dfname[MAXQFNAME];
173		struct stat stbuf;
174
175		strcpy(dfname, queuename(e, 'd'));
176		fd = open(dfname, O_WRONLY|O_CREAT|O_TRUNC, FileMode);
177		if (fd < 0 || (dfp = fdopen(fd, "w")) == NULL)
178			syserr("!queueup: cannot create data temp file %s, uid=%d",
179				dfname, geteuid());
180		if (fstat(fd, &stbuf) < 0)
181			e->e_dfino = -1;
182		else
183		{
184			e->e_dfdev = stbuf.st_dev;
185			e->e_dfino = stbuf.st_ino;
186		}
187		e->e_flags |= EF_HAS_DF;
188		bzero(&mcibuf, sizeof mcibuf);
189		mcibuf.mci_out = dfp;
190		mcibuf.mci_mailer = FileMailer;
191		(*e->e_putbody)(&mcibuf, e, NULL);
192		(void) xfclose(dfp, "queueup dfp", e->e_id);
193		e->e_putbody = putbody;
194	}
195
196	/*
197	**  Output future work requests.
198	**	Priority and creation time should be first, since
199	**	they are required by orderq.
200	*/
201
202	/* output queue version number (must be first!) */
203	fprintf(tfp, "V%d\n", QF_VERSION);
204
205	/* output creation time */
206	fprintf(tfp, "T%ld\n", (long) e->e_ctime);
207
208	/* output last delivery time */
209	fprintf(tfp, "K%ld\n", (long) e->e_dtime);
210
211	/* output number of delivery attempts */
212	fprintf(tfp, "N%d\n", e->e_ntries);
213
214	/* output message priority */
215	fprintf(tfp, "P%ld\n", e->e_msgpriority);
216
217	/* output inode number of data file */
218	/* XXX should probably include device major/minor too */
219	if (e->e_dfino != -1)
220	{
221		if (sizeof e->e_dfino > sizeof(long))
222			fprintf(tfp, "I%d/%d/%s\n",
223				major(e->e_dfdev), minor(e->e_dfdev),
224				quad_to_string(e->e_dfino));
225		else
226			fprintf(tfp, "I%d/%d/%lu\n",
227				major(e->e_dfdev), minor(e->e_dfdev),
228				(unsigned long) e->e_dfino);
229	}
230
231	/* output body type */
232	if (e->e_bodytype != NULL)
233		fprintf(tfp, "B%s\n", denlstring(e->e_bodytype, TRUE, FALSE));
234
235#if _FFR_SAVE_CHARSET
236	if (e->e_charset != NULL)
237		fprintf(tfp, "X%s\n", denlstring(e->e_charset, TRUE, FALSE));
238#endif
239
240	/* message from envelope, if it exists */
241	if (e->e_message != NULL)
242		fprintf(tfp, "M%s\n", denlstring(e->e_message, TRUE, FALSE));
243
244	/* send various flag bits through */
245	p = buf;
246	if (bitset(EF_WARNING, e->e_flags))
247		*p++ = 'w';
248	if (bitset(EF_RESPONSE, e->e_flags))
249		*p++ = 'r';
250	if (bitset(EF_HAS8BIT, e->e_flags))
251		*p++ = '8';
252	if (bitset(EF_DELETE_BCC, e->e_flags))
253		*p++ = 'b';
254	if (bitset(EF_RET_PARAM, e->e_flags))
255		*p++ = 'd';
256	if (bitset(EF_NO_BODY_RETN, e->e_flags))
257		*p++ = 'n';
258	*p++ = '\0';
259	if (buf[0] != '\0')
260		fprintf(tfp, "F%s\n", buf);
261
262	/* $r and $s and $_ macro values */
263	if ((p = macvalue('r', e)) != NULL)
264		fprintf(tfp, "$r%s\n", denlstring(p, TRUE, FALSE));
265	if ((p = macvalue('s', e)) != NULL)
266		fprintf(tfp, "$s%s\n", denlstring(p, TRUE, FALSE));
267	if ((p = macvalue('_', e)) != NULL)
268		fprintf(tfp, "$_%s\n", denlstring(p, TRUE, FALSE));
269
270	/* output name of sender */
271	if (bitnset(M_UDBENVELOPE, e->e_from.q_mailer->m_flags))
272		p = e->e_sender;
273	else
274		p = e->e_from.q_paddr;
275	fprintf(tfp, "S%s\n", denlstring(p, TRUE, FALSE));
276
277	/* output ESMTP-supplied "original" information */
278	if (e->e_envid != NULL)
279		fprintf(tfp, "Z%s\n", denlstring(e->e_envid, TRUE, FALSE));
280
281	/* output list of recipient addresses */
282	printctladdr(NULL, NULL);
283	for (q = e->e_sendqueue; q != NULL; q = q->q_next)
284	{
285		if (bitset(QDONTSEND|QBADADDR|QSENT, q->q_flags))
286		{
287#if XDEBUG
288			if (bitset(QQUEUEUP, q->q_flags))
289				sm_syslog(LOG_DEBUG, e->e_id,
290					"dropenvelope: q_flags = %x, paddr = %s",
291					q->q_flags, q->q_paddr);
292#endif
293			continue;
294		}
295		printctladdr(q, tfp);
296		if (q->q_orcpt != NULL)
297			fprintf(tfp, "Q%s\n",
298				denlstring(q->q_orcpt, TRUE, FALSE));
299		putc('R', tfp);
300		if (bitset(QPRIMARY, q->q_flags))
301			putc('P', tfp);
302		if (bitset(QHASNOTIFY, q->q_flags))
303			putc('N', tfp);
304		if (bitset(QPINGONSUCCESS, q->q_flags))
305			putc('S', tfp);
306		if (bitset(QPINGONFAILURE, q->q_flags))
307			putc('F', tfp);
308		if (bitset(QPINGONDELAY, q->q_flags))
309			putc('D', tfp);
310		putc(':', tfp);
311		fprintf(tfp, "%s\n", denlstring(q->q_paddr, TRUE, FALSE));
312		if (announce)
313		{
314			e->e_to = q->q_paddr;
315			message("queued");
316			if (LogLevel > 8)
317				logdelivery(q->q_mailer, NULL, "queued",
318					    NULL, (time_t) 0, e);
319			e->e_to = NULL;
320		}
321		if (tTd(40, 1))
322		{
323			printf("queueing ");
324			printaddr(q, FALSE);
325		}
326	}
327
328	/*
329	**  Output headers for this message.
330	**	Expand macros completely here.  Queue run will deal with
331	**	everything as absolute headers.
332	**		All headers that must be relative to the recipient
333	**		can be cracked later.
334	**	We set up a "null mailer" -- i.e., a mailer that will have
335	**	no effect on the addresses as they are output.
336	*/
337
338	bzero((char *) &nullmailer, sizeof nullmailer);
339	nullmailer.m_re_rwset = nullmailer.m_rh_rwset =
340			nullmailer.m_se_rwset = nullmailer.m_sh_rwset = -1;
341	nullmailer.m_eol = "\n";
342	bzero(&mcibuf, sizeof mcibuf);
343	mcibuf.mci_mailer = &nullmailer;
344	mcibuf.mci_out = tfp;
345
346	define('g', "\201f", e);
347	for (h = e->e_header; h != NULL; h = h->h_link)
348	{
349		extern bool bitzerop __P((BITMAP));
350
351		/* don't output null headers */
352		if (h->h_value == NULL || h->h_value[0] == '\0')
353			continue;
354
355		/* don't output resent headers on non-resent messages */
356		if (bitset(H_RESENT, h->h_flags) && !bitset(EF_RESENT, e->e_flags))
357			continue;
358
359		/* expand macros; if null, don't output header at all */
360		if (bitset(H_DEFAULT, h->h_flags))
361		{
362			(void) expand(h->h_value, buf, sizeof buf, e);
363			if (buf[0] == '\0')
364				continue;
365		}
366
367		/* output this header */
368		fprintf(tfp, "H");
369
370		/* if conditional, output the set of conditions */
371		if (!bitzerop(h->h_mflags) && bitset(H_CHECK|H_ACHECK, h->h_flags))
372		{
373			int j;
374
375			(void) putc('?', tfp);
376			for (j = '\0'; j <= '\177'; j++)
377				if (bitnset(j, h->h_mflags))
378					(void) putc(j, tfp);
379			(void) putc('?', tfp);
380		}
381
382		/* output the header: expand macros, convert addresses */
383		if (bitset(H_DEFAULT, h->h_flags))
384		{
385			fprintf(tfp, "%s: %s\n",
386				h->h_field,
387				denlstring(buf, FALSE, TRUE));
388		}
389		else if (bitset(H_FROM|H_RCPT, h->h_flags))
390		{
391			bool oldstyle = bitset(EF_OLDSTYLE, e->e_flags);
392			FILE *savetrace = TrafficLogFile;
393
394			TrafficLogFile = NULL;
395
396			if (bitset(H_FROM, h->h_flags))
397				oldstyle = FALSE;
398
399			commaize(h, h->h_value, oldstyle, &mcibuf, e);
400
401			TrafficLogFile = savetrace;
402		}
403		else
404		{
405			fprintf(tfp, "%s: %s\n",
406				h->h_field,
407				denlstring(h->h_value, FALSE, TRUE));
408		}
409	}
410
411	/*
412	**  Clean up.
413	**
414	**	Write a terminator record -- this is to prevent
415	**	scurrilous crackers from appending any data.
416	*/
417
418	fprintf(tfp, ".\n");
419
420	if (fflush(tfp) < 0 ||
421	    (SuperSafe && fsync(fileno(tfp)) < 0) ||
422	    ferror(tfp))
423	{
424		if (newid)
425			syserr("!552 Error writing control file %s", tf);
426		else
427			syserr("!452 Error writing control file %s", tf);
428	}
429
430	if (!newid)
431	{
432		/* rename (locked) tf to be (locked) qf */
433		qf = queuename(e, 'q');
434		if (rename(tf, qf) < 0)
435			syserr("cannot rename(%s, %s), uid=%d",
436				tf, qf, geteuid());
437
438		/* close and unlock old (locked) qf */
439		if (e->e_lockfp != NULL)
440			(void) xfclose(e->e_lockfp, "queueup lockfp", e->e_id);
441		e->e_lockfp = tfp;
442	}
443	else
444		qf = tf;
445	errno = 0;
446	e->e_flags |= EF_INQUEUE;
447
448	/* save log info */
449	if (LogLevel > 79)
450		sm_syslog(LOG_DEBUG, e->e_id, "queueup, qf=%s", qf);
451
452	if (tTd(40, 1))
453		printf("<<<<< done queueing %s <<<<<\n\n", e->e_id);
454	return;
455}
456
457void
458printctladdr(a, tfp)
459	register ADDRESS *a;
460	FILE *tfp;
461{
462	char *uname;
463	register ADDRESS *q;
464	uid_t uid;
465	gid_t gid;
466	static ADDRESS *lastctladdr = NULL;
467	static uid_t lastuid;
468
469	/* initialization */
470	if (a == NULL || a->q_alias == NULL || tfp == NULL)
471	{
472		if (lastctladdr != NULL && tfp != NULL)
473			fprintf(tfp, "C\n");
474		lastctladdr = NULL;
475		lastuid = 0;
476		return;
477	}
478
479	/* find the active uid */
480	q = getctladdr(a);
481	if (q == NULL)
482	{
483		uname = NULL;
484		uid = 0;
485		gid = 0;
486	}
487	else
488	{
489		uname = q->q_ruser != NULL ? q->q_ruser : q->q_user;
490		uid = q->q_uid;
491		gid = q->q_gid;
492	}
493	a = a->q_alias;
494
495	/* check to see if this is the same as last time */
496	if (lastctladdr != NULL && uid == lastuid &&
497	    strcmp(lastctladdr->q_paddr, a->q_paddr) == 0)
498		return;
499	lastuid = uid;
500	lastctladdr = a;
501
502	if (uid == 0 || uname == NULL || uname[0] == '\0')
503		fprintf(tfp, "C");
504	else
505		fprintf(tfp, "C%s:%ld:%ld",
506			denlstring(uname, TRUE, FALSE), (long) uid, (long) gid);
507	fprintf(tfp, ":%s\n", denlstring(a->q_paddr, TRUE, FALSE));
508}
509/*
510**  RUNQUEUE -- run the jobs in the queue.
511**
512**	Gets the stuff out of the queue in some presumably logical
513**	order and processes them.
514**
515**	Parameters:
516**		forkflag -- TRUE if the queue scanning should be done in
517**			a child process.  We double-fork so it is not our
518**			child and we don't have to clean up after it.
519**		verbose -- if TRUE, print out status information.
520**
521**	Returns:
522**		TRUE if the queue run successfully began.
523**
524**	Side Effects:
525**		runs things in the mail queue.
526*/
527
528ENVELOPE	QueueEnvelope;		/* the queue run envelope */
529extern int	get_num_procs_online __P((void));
530
531bool
532runqueue(forkflag, verbose)
533	bool forkflag;
534	bool verbose;
535{
536	register ENVELOPE *e;
537	int njobs;
538	int sequenceno = 0;
539	time_t current_la_time;
540	extern ENVELOPE BlankEnvelope;
541	extern void clrdaemon __P((void));
542	extern void runqueueevent __P((void));
543
544	DoQueueRun = FALSE;
545
546	/*
547	**  If no work will ever be selected, don't even bother reading
548	**  the queue.
549	*/
550
551	CurrentLA = getla();	/* get load average */
552	current_la_time = curtime();
553
554	if (shouldqueue(WkRecipFact, current_la_time))
555	{
556		char *msg = "Skipping queue run -- load average too high";
557
558		if (verbose)
559			message("458 %s\n", msg);
560		if (LogLevel > 8)
561			sm_syslog(LOG_INFO, NOQID,
562				"runqueue: %s",
563				msg);
564		if (forkflag && QueueIntvl != 0)
565			(void) setevent(QueueIntvl, runqueueevent, 0);
566		return FALSE;
567	}
568
569	/*
570	**  See if we already have too many children.
571	*/
572
573	if (forkflag && QueueIntvl != 0 &&
574	    MaxChildren > 0 && CurChildren >= MaxChildren)
575	{
576		(void) setevent(QueueIntvl, runqueueevent, 0);
577		return FALSE;
578	}
579
580	/*
581	**  See if we want to go off and do other useful work.
582	*/
583
584	if (forkflag)
585	{
586		pid_t pid;
587		extern SIGFUNC_DECL intsig __P((int));
588		extern SIGFUNC_DECL reapchild __P((int));
589
590		blocksignal(SIGCHLD);
591		(void) setsignal(SIGCHLD, reapchild);
592
593		pid = dofork();
594		if (pid == -1)
595		{
596			const char *msg = "Skipping queue run -- fork() failed";
597			const char *err = errstring(errno);
598
599			if (verbose)
600				message("458 %s: %s\n", msg, err);
601			if (LogLevel > 8)
602				sm_syslog(LOG_INFO, NOQID,
603					"runqueue: %s: %s",
604					msg, err);
605			if (QueueIntvl != 0)
606				(void) setevent(QueueIntvl, runqueueevent, 0);
607			(void) releasesignal(SIGCHLD);
608			return FALSE;
609		}
610		if (pid != 0)
611		{
612			/* parent -- pick up intermediate zombie */
613			(void) blocksignal(SIGALRM);
614			proc_list_add(pid);
615			(void) releasesignal(SIGALRM);
616			releasesignal(SIGCHLD);
617			if (QueueIntvl != 0)
618				(void) setevent(QueueIntvl, runqueueevent, 0);
619			return TRUE;
620		}
621		/* child -- double fork and clean up signals */
622		proc_list_clear();
623		releasesignal(SIGCHLD);
624		(void) setsignal(SIGCHLD, SIG_DFL);
625		(void) setsignal(SIGHUP, intsig);
626	}
627
628	setproctitle("running queue: %s", QueueDir);
629
630	if (LogLevel > 69)
631		sm_syslog(LOG_DEBUG, NOQID,
632			"runqueue %s, pid=%d, forkflag=%d",
633			QueueDir, getpid(), forkflag);
634
635	/*
636	**  Release any resources used by the daemon code.
637	*/
638
639# if DAEMON
640	clrdaemon();
641# endif /* DAEMON */
642
643	/* force it to run expensive jobs */
644	NoConnect = FALSE;
645
646	/* drop privileges */
647	if (geteuid() == (uid_t) 0)
648		(void) drop_privileges(FALSE);
649
650	/*
651	**  Create ourselves an envelope
652	*/
653
654	CurEnv = &QueueEnvelope;
655	e = newenvelope(&QueueEnvelope, CurEnv);
656	e->e_flags = BlankEnvelope.e_flags;
657
658	/* make sure we have disconnected from parent */
659	if (forkflag)
660	{
661		disconnect(1, e);
662		QuickAbort = FALSE;
663	}
664
665	/*
666	**  Make sure the alias database is open.
667	*/
668
669	initmaps(FALSE, e);
670
671	/*
672	**  If we are running part of the queue, always ignore stored
673	**  host status.
674	*/
675
676	if (QueueLimitId != NULL || QueueLimitSender != NULL ||
677	    QueueLimitRecipient != NULL)
678	{
679		IgnoreHostStatus = TRUE;
680		MinQueueAge = 0;
681	}
682
683	/*
684	**  Start making passes through the queue.
685	**	First, read and sort the entire queue.
686	**	Then, process the work in that order.
687	**		But if you take too long, start over.
688	*/
689
690	/* order the existing work requests */
691	njobs = orderq(FALSE);
692
693	/* process them once at a time */
694	while (WorkQ != NULL)
695	{
696		WORK *w = WorkQ;
697
698		WorkQ = WorkQ->w_next;
699		e->e_to = NULL;
700
701		/*
702		**  Ignore jobs that are too expensive for the moment.
703		**
704		**	Get new load average every 30 seconds.
705		*/
706
707		if (current_la_time < curtime() - 30)
708		{
709			CurrentLA = getla();
710			current_la_time = curtime();
711		}
712		if (shouldqueue(WkRecipFact, current_la_time))
713		{
714			char *msg = "Aborting queue run: load average too high";
715
716			if (Verbose)
717				message("%s", msg);
718			if (LogLevel > 8)
719				sm_syslog(LOG_INFO, NOQID,
720					"runqueue: %s",
721					msg);
722			break;
723		}
724		sequenceno++;
725		if (shouldqueue(w->w_pri, w->w_ctime))
726		{
727			if (Verbose)
728				message("");
729			if (QueueSortOrder == QS_BYPRIORITY)
730			{
731				if (Verbose)
732					message("Skipping %s (sequence %d of %d) and flushing rest of queue",
733						w->w_name + 2,
734						sequenceno,
735						njobs);
736				if (LogLevel > 8)
737					sm_syslog(LOG_INFO, NOQID,
738						"runqueue: Flushing queue from %s (pri %ld, LA %d, %d of %d)",
739						w->w_name + 2,
740						w->w_pri,
741						CurrentLA,
742						sequenceno,
743						njobs);
744				break;
745			}
746			else if (Verbose)
747				message("Skipping %s (sequence %d of %d)",
748					w->w_name + 2, sequenceno, njobs);
749		}
750		else
751		{
752			pid_t pid;
753			extern pid_t dowork __P((char *, bool, bool, ENVELOPE *));
754
755			if (Verbose)
756			{
757				message("");
758				message("Running %s (sequence %d of %d)",
759					w->w_name + 2, sequenceno, njobs);
760			}
761			pid = dowork(w->w_name + 2, ForkQueueRuns, FALSE, e);
762			errno = 0;
763			if (pid != 0)
764				(void) waitfor(pid);
765		}
766		free(w->w_name);
767		if (w->w_host)
768			free(w->w_host);
769		free((char *) w);
770	}
771
772	/* exit without the usual cleanup */
773	e->e_id = NULL;
774	finis();
775	/*NOTREACHED*/
776	return TRUE;
777}
778
779
780/*
781**  RUNQUEUEEVENT -- stub for use in setevent
782*/
783
784void
785runqueueevent()
786{
787	DoQueueRun = TRUE;
788}
789/*
790**  ORDERQ -- order the work queue.
791**
792**	Parameters:
793**		doall -- if set, include everything in the queue (even
794**			the jobs that cannot be run because the load
795**			average is too high).  Otherwise, exclude those
796**			jobs.
797**
798**	Returns:
799**		The number of request in the queue (not necessarily
800**		the number of requests in WorkQ however).
801**
802**	Side Effects:
803**		Sets WorkQ to the queue of available work, in order.
804*/
805
806# define NEED_P		001
807# define NEED_T		002
808# define NEED_R		004
809# define NEED_S		010
810
811static WORK	*WorkList = NULL;
812static int	WorkListSize = 0;
813
814int
815orderq(doall)
816	bool doall;
817{
818	register struct dirent *d;
819	register WORK *w;
820	register char *p;
821	DIR *f;
822	register int i;
823	int wn = -1;
824	int wc;
825	QUEUE_CHAR *check;
826
827	if (tTd(41, 1))
828	{
829		printf("orderq:\n");
830
831		check = QueueLimitId;
832		while (check != NULL)
833		{
834			printf("\tQueueLimitId = %s\n",
835			       check->queue_match);
836			check = check->queue_next;
837		}
838
839		check = QueueLimitSender;
840		while (check != NULL)
841		{
842			printf("\tQueueLimitSender = %s\n",
843			       check->queue_match);
844			check = check->queue_next;
845		}
846
847		check = QueueLimitRecipient;
848		while (check != NULL)
849		{
850			printf("\tQueueLimitRecipient = %s\n",
851			       check->queue_match);
852			check = check->queue_next;
853		}
854	}
855
856	/* clear out old WorkQ */
857	for (w = WorkQ; w != NULL; )
858	{
859		register WORK *nw = w->w_next;
860
861		WorkQ = nw;
862		free(w->w_name);
863		if (w->w_host)
864			free(w->w_host);
865		free((char *) w);
866		w = nw;
867	}
868
869	/* open the queue directory */
870	f = opendir(".");
871	if (f == NULL)
872	{
873		syserr("orderq: cannot open \"%s\" as \".\"", QueueDir);
874		return (0);
875	}
876
877	/*
878	**  Read the work directory.
879	*/
880
881	while ((d = readdir(f)) != NULL)
882	{
883		FILE *cf;
884		int qfver = 0;
885		char lbuf[MAXNAME + 1];
886		extern bool strcontainedin __P((char *, char *));
887
888		if (tTd(41, 50))
889			printf("orderq: checking %s\n", d->d_name);
890
891		/* is this an interesting entry? */
892		if (d->d_name[0] != 'q' || d->d_name[1] != 'f')
893			continue;
894
895		if (strlen(d->d_name) > MAXQFNAME)
896			continue;
897
898		check = QueueLimitId;
899		while (check != NULL)
900		{
901			if (strcontainedin(check->queue_match, d->d_name))
902				break;
903			else
904				check = check->queue_next;
905		}
906		if (QueueLimitId != NULL && check == NULL)
907			continue;
908
909#ifdef PICKY_QF_NAME_CHECK
910		/*
911		**  Check queue name for plausibility.  This handles
912		**  both old and new type ids.
913		*/
914
915		p = d->d_name + 2;
916		if (isupper(p[0]) && isupper(p[2]))
917			p += 3;
918		else if (isupper(p[1]))
919			p += 2;
920		else
921			p = d->d_name;
922		for (i = 0; isdigit(*p); p++)
923			i++;
924		if (i < 5 || *p != '\0')
925		{
926			if (Verbose)
927				printf("orderq: bogus qf name %s\n", d->d_name);
928			if (LogLevel > 0)
929				sm_syslog(LOG_ALERT, NOQID,
930					"orderq: bogus qf name %s",
931					d->d_name);
932			if (strlen(d->d_name) > (SIZE_T) MAXNAME)
933				d->d_name[MAXNAME] = '\0';
934			strcpy(lbuf, d->d_name);
935			lbuf[0] = 'Q';
936			(void) rename(d->d_name, lbuf);
937			continue;
938		}
939#endif
940
941		/* open control file (if not too many files) */
942		if (++wn >= MaxQueueRun && MaxQueueRun > 0)
943		{
944			if (wn == MaxQueueRun && LogLevel > 0)
945				sm_syslog(LOG_ALERT, NOQID,
946					"WorkList for %s maxed out at %d",
947					QueueDir, MaxQueueRun);
948			continue;
949		}
950		if (wn >= WorkListSize)
951		{
952			extern void grow_wlist __P((void));
953
954			grow_wlist();
955			if (wn >= WorkListSize)
956				continue;
957		}
958
959		cf = fopen(d->d_name, "r");
960		if (cf == NULL)
961		{
962			/* this may be some random person sending hir msgs */
963			/* syserr("orderq: cannot open %s", cbuf); */
964			if (tTd(41, 2))
965				printf("orderq: cannot open %s: %s\n",
966					d->d_name, errstring(errno));
967			errno = 0;
968			wn--;
969			continue;
970		}
971		w = &WorkList[wn];
972		w->w_name = newstr(d->d_name);
973		w->w_host = NULL;
974		w->w_lock = !lockfile(fileno(cf), w->w_name, NULL, LOCK_SH|LOCK_NB);
975		w->w_tooyoung = FALSE;
976
977		/* make sure jobs in creation don't clog queue */
978		w->w_pri = 0x7fffffff;
979		w->w_ctime = 0;
980
981		/* extract useful information */
982		i = NEED_P | NEED_T;
983		if (QueueLimitSender != NULL)
984			i |= NEED_S;
985		if (QueueSortOrder == QS_BYHOST || QueueLimitRecipient != NULL)
986			i |= NEED_R;
987		while (i != 0 && fgets(lbuf, sizeof lbuf, cf) != NULL)
988		{
989			int c;
990			time_t age;
991			extern bool strcontainedin __P((char *, char *));
992
993			p = strchr(lbuf, '\n');
994			if (p != NULL)
995				*p = '\0';
996			else
997			{
998				/* flush rest of overly long line */
999				while ((c = getc(cf)) != EOF && c != '\n')
1000					continue;
1001			}
1002
1003			switch (lbuf[0])
1004			{
1005			  case 'V':
1006				qfver = atoi(&lbuf[1]);
1007				break;
1008
1009			  case 'P':
1010				w->w_pri = atol(&lbuf[1]);
1011				i &= ~NEED_P;
1012				break;
1013
1014			  case 'T':
1015				w->w_ctime = atol(&lbuf[1]);
1016				i &= ~NEED_T;
1017				break;
1018
1019			  case 'R':
1020				if (w->w_host == NULL &&
1021				    (p = strrchr(&lbuf[1], '@')) != NULL)
1022					w->w_host = newstr(&p[1]);
1023				if (QueueLimitRecipient == NULL)
1024				{
1025					i &= ~NEED_R;
1026					break;
1027				}
1028				if (qfver > 0)
1029				{
1030					p = strchr(&lbuf[1], ':');
1031					if (p == NULL)
1032						p = &lbuf[1];
1033				}
1034				else
1035					p = &lbuf[1];
1036				check = QueueLimitRecipient;
1037				while (check != NULL)
1038				{
1039					if (strcontainedin(check->queue_match,
1040							   p))
1041						break;
1042					else
1043						check = check->queue_next;
1044				}
1045				if (check != NULL)
1046					i &= ~NEED_R;
1047				break;
1048
1049			  case 'S':
1050				  check = QueueLimitSender;
1051				  while (check != NULL)
1052				  {
1053					  if (strcontainedin(check->queue_match,
1054							     &lbuf[1]))
1055						  break;
1056					  else
1057						  check = check->queue_next;
1058				  }
1059				  if (check != NULL)
1060					  i &= ~NEED_S;
1061				break;
1062
1063			  case 'K':
1064				age = curtime() - (time_t) atol(&lbuf[1]);
1065				if (age >= 0 && MinQueueAge > 0 &&
1066				    age < MinQueueAge)
1067					w->w_tooyoung = TRUE;
1068				break;
1069
1070			  case 'N':
1071				if (atol(&lbuf[1]) == 0)
1072					w->w_tooyoung = FALSE;
1073				break;
1074			}
1075		}
1076		(void) fclose(cf);
1077
1078		if ((!doall && shouldqueue(w->w_pri, w->w_ctime)) ||
1079		    bitset(NEED_R|NEED_S, i))
1080		{
1081			/* don't even bother sorting this job in */
1082			if (tTd(41, 49))
1083				printf("skipping %s (%x)\n", w->w_name, i);
1084			free(w->w_name);
1085			if (w->w_host)
1086				free(w->w_host);
1087			wn--;
1088		}
1089	}
1090	(void) closedir(f);
1091	wn++;
1092
1093	wc = min(wn, WorkListSize);
1094	if (wc > MaxQueueRun && MaxQueueRun > 0)
1095		wc = MaxQueueRun;
1096
1097	if (QueueSortOrder == QS_BYHOST)
1098	{
1099		extern int workcmpf1();
1100		extern int workcmpf2();
1101
1102		/*
1103		**  Sort the work directory for the first time,
1104		**  based on host name, lock status, and priority.
1105		*/
1106
1107		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf1);
1108
1109		/*
1110		**  If one message to host is locked, "lock" all messages
1111		**  to that host.
1112		*/
1113
1114		i = 0;
1115		while (i < wc)
1116		{
1117			if (!WorkList[i].w_lock)
1118			{
1119				i++;
1120				continue;
1121			}
1122			w = &WorkList[i];
1123			while (++i < wc)
1124			{
1125				extern int sm_strcasecmp __P((char *, char *));
1126
1127				if (WorkList[i].w_host == NULL &&
1128				    w->w_host == NULL)
1129					WorkList[i].w_lock = TRUE;
1130				else if (WorkList[i].w_host != NULL &&
1131					 w->w_host != NULL &&
1132					 sm_strcasecmp(WorkList[i].w_host, w->w_host) == 0)
1133					WorkList[i].w_lock = TRUE;
1134				else
1135					break;
1136			}
1137		}
1138
1139		/*
1140		**  Sort the work directory for the second time,
1141		**  based on lock status, host name, and priority.
1142		*/
1143
1144		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf2);
1145	}
1146	else if (QueueSortOrder == QS_BYTIME)
1147	{
1148		extern int workcmpf3();
1149
1150		/*
1151		**  Simple sort based on submission time only.
1152		*/
1153
1154		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf3);
1155	}
1156	else
1157	{
1158		extern int workcmpf0();
1159
1160		/*
1161		**  Simple sort based on queue priority only.
1162		*/
1163
1164		qsort((char *) WorkList, wc, sizeof *WorkList, workcmpf0);
1165	}
1166
1167	/*
1168	**  Convert the work list into canonical form.
1169	**	Should be turning it into a list of envelopes here perhaps.
1170	*/
1171
1172	WorkQ = NULL;
1173	for (i = wc; --i >= 0; )
1174	{
1175		w = (WORK *) xalloc(sizeof *w);
1176		w->w_name = WorkList[i].w_name;
1177		w->w_host = WorkList[i].w_host;
1178		w->w_lock = WorkList[i].w_lock;
1179		w->w_tooyoung = WorkList[i].w_tooyoung;
1180		w->w_pri = WorkList[i].w_pri;
1181		w->w_ctime = WorkList[i].w_ctime;
1182		w->w_next = WorkQ;
1183		WorkQ = w;
1184	}
1185	if (WorkList != NULL)
1186		free(WorkList);
1187	WorkList = NULL;
1188	WorkListSize = 0;
1189
1190	if (tTd(40, 1))
1191	{
1192		for (w = WorkQ; w != NULL; w = w->w_next)
1193			printf("%32s: pri=%ld\n", w->w_name, w->w_pri);
1194	}
1195
1196	return (wn);
1197}
1198/*
1199**  GROW_WLIST -- make the work list larger
1200**
1201**	Parameters:
1202**		none.
1203**
1204**	Returns:
1205**		none.
1206**
1207**	Side Effects:
1208**		Adds another QUEUESEGSIZE entries to WorkList if possible.
1209**		It can fail if there isn't enough memory, so WorkListSize
1210**		should be checked again upon return.
1211*/
1212
1213void
1214grow_wlist()
1215{
1216	if (tTd(41, 1))
1217		printf("grow_wlist: WorkListSize=%d\n", WorkListSize);
1218	if (WorkList == NULL)
1219	{
1220		WorkList = (WORK *) xalloc(sizeof(WORK) * (QUEUESEGSIZE + 1));
1221		WorkListSize = QUEUESEGSIZE;
1222	}
1223	else
1224	{
1225		int newsize = WorkListSize + QUEUESEGSIZE;
1226		WORK *newlist = (WORK *) realloc((char *)WorkList,
1227					  (unsigned)sizeof(WORK) * (newsize + 1));
1228
1229		if (newlist != NULL)
1230		{
1231			WorkListSize = newsize;
1232			WorkList = newlist;
1233			if (LogLevel > 1)
1234			{
1235				sm_syslog(LOG_NOTICE, NOQID,
1236					"grew WorkList for %s to %d",
1237					QueueDir, WorkListSize);
1238			}
1239		}
1240		else if (LogLevel > 0)
1241		{
1242			sm_syslog(LOG_ALERT, NOQID,
1243				"FAILED to grow WorkList for %s to %d",
1244				QueueDir, newsize);
1245		}
1246	}
1247	if (tTd(41, 1))
1248		printf("grow_wlist: WorkListSize now %d\n", WorkListSize);
1249}
1250/*
1251**  WORKCMPF0 -- simple priority-only compare function.
1252**
1253**	Parameters:
1254**		a -- the first argument.
1255**		b -- the second argument.
1256**
1257**	Returns:
1258**		-1 if a < b
1259**		 0 if a == b
1260**		+1 if a > b
1261**
1262**	Side Effects:
1263**		none.
1264*/
1265
1266int
1267workcmpf0(a, b)
1268	register WORK *a;
1269	register WORK *b;
1270{
1271	long pa = a->w_pri;
1272	long pb = b->w_pri;
1273
1274	if (pa == pb)
1275		return 0;
1276	else if (pa > pb)
1277		return 1;
1278	else
1279		return -1;
1280}
1281/*
1282**  WORKCMPF1 -- first compare function for ordering work based on host name.
1283**
1284**	Sorts on host name, lock status, and priority in that order.
1285**
1286**	Parameters:
1287**		a -- the first argument.
1288**		b -- the second argument.
1289**
1290**	Returns:
1291**		<0 if a < b
1292**		 0 if a == b
1293**		>0 if a > b
1294**
1295**	Side Effects:
1296**		none.
1297*/
1298
1299int
1300workcmpf1(a, b)
1301	register WORK *a;
1302	register WORK *b;
1303{
1304	int i;
1305	extern int sm_strcasecmp __P((char *, char *));
1306
1307	/* host name */
1308	if (a->w_host != NULL && b->w_host == NULL)
1309		return 1;
1310	else if (a->w_host == NULL && b->w_host != NULL)
1311		return -1;
1312	if (a->w_host != NULL && b->w_host != NULL &&
1313	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1314		return i;
1315
1316	/* lock status */
1317	if (a->w_lock != b->w_lock)
1318		return b->w_lock - a->w_lock;
1319
1320	/* job priority */
1321	return a->w_pri - b->w_pri;
1322}
1323/*
1324**  WORKCMPF2 -- second compare function for ordering work based on host name.
1325**
1326**	Sorts on lock status, host name, and priority in that order.
1327**
1328**	Parameters:
1329**		a -- the first argument.
1330**		b -- the second argument.
1331**
1332**	Returns:
1333**		<0 if a < b
1334**		 0 if a == b
1335**		>0 if a > b
1336**
1337**	Side Effects:
1338**		none.
1339*/
1340
1341int
1342workcmpf2(a, b)
1343	register WORK *a;
1344	register WORK *b;
1345{
1346	int i;
1347	extern int sm_strcasecmp __P((char *, char *));
1348
1349	/* lock status */
1350	if (a->w_lock != b->w_lock)
1351		return a->w_lock - b->w_lock;
1352
1353	/* host name */
1354	if (a->w_host != NULL && b->w_host == NULL)
1355		return 1;
1356	else if (a->w_host == NULL && b->w_host != NULL)
1357		return -1;
1358	if (a->w_host != NULL && b->w_host != NULL &&
1359	    (i = sm_strcasecmp(a->w_host, b->w_host)) != 0)
1360		return i;
1361
1362	/* job priority */
1363	return a->w_pri - b->w_pri;
1364}
1365/*
1366**  WORKCMPF3 -- simple submission-time-only compare function.
1367**
1368**	Parameters:
1369**		a -- the first argument.
1370**		b -- the second argument.
1371**
1372**	Returns:
1373**		-1 if a < b
1374**		 0 if a == b
1375**		+1 if a > b
1376**
1377**	Side Effects:
1378**		none.
1379*/
1380
1381int
1382workcmpf3(a, b)
1383	register WORK *a;
1384	register WORK *b;
1385{
1386	if (a->w_ctime > b->w_ctime)
1387		return 1;
1388	else if (a->w_ctime < b->w_ctime)
1389		return -1;
1390	else
1391		return 0;
1392}
1393/*
1394**  DOWORK -- do a work request.
1395**
1396**	Parameters:
1397**		id -- the ID of the job to run.
1398**		forkflag -- if set, run this in background.
1399**		requeueflag -- if set, reinstantiate the queue quickly.
1400**			This is used when expanding aliases in the queue.
1401**			If forkflag is also set, it doesn't wait for the
1402**			child.
1403**		e - the envelope in which to run it.
1404**
1405**	Returns:
1406**		process id of process that is running the queue job.
1407**
1408**	Side Effects:
1409**		The work request is satisfied if possible.
1410*/
1411
1412pid_t
1413dowork(id, forkflag, requeueflag, e)
1414	char *id;
1415	bool forkflag;
1416	bool requeueflag;
1417	register ENVELOPE *e;
1418{
1419	register pid_t pid;
1420	extern bool readqf __P((ENVELOPE *));
1421
1422	if (tTd(40, 1))
1423		printf("dowork(%s)\n", id);
1424
1425	/*
1426	**  Fork for work.
1427	*/
1428
1429	if (forkflag)
1430	{
1431		pid = fork();
1432		if (pid < 0)
1433		{
1434			syserr("dowork: cannot fork");
1435			return 0;
1436		}
1437		else if (pid > 0)
1438		{
1439			/* parent -- clean out connection cache */
1440			mci_flush(FALSE, NULL);
1441		}
1442		else
1443		{
1444			/* child -- error messages to the transcript */
1445			QuickAbort = OnlyOneError = FALSE;
1446		}
1447	}
1448	else
1449	{
1450		pid = 0;
1451	}
1452
1453	if (pid == 0)
1454	{
1455		/*
1456		**  CHILD
1457		**	Lock the control file to avoid duplicate deliveries.
1458		**		Then run the file as though we had just read it.
1459		**	We save an idea of the temporary name so we
1460		**		can recover on interrupt.
1461		*/
1462
1463		/* set basic modes, etc. */
1464		(void) alarm(0);
1465		clearenvelope(e, FALSE);
1466		e->e_flags |= EF_QUEUERUN|EF_GLOBALERRS;
1467		e->e_sendmode = SM_DELIVER;
1468		e->e_errormode = EM_MAIL;
1469		e->e_id = id;
1470		GrabTo = UseErrorsTo = FALSE;
1471		ExitStat = EX_OK;
1472		if (forkflag)
1473		{
1474			disconnect(1, e);
1475			OpMode = MD_DELIVER;
1476		}
1477		setproctitle("%s: from queue", id);
1478		if (LogLevel > 76)
1479			sm_syslog(LOG_DEBUG, e->e_id,
1480				"dowork, pid=%d",
1481				getpid());
1482
1483		/* don't use the headers from sendmail.cf... */
1484		e->e_header = NULL;
1485
1486		/* read the queue control file -- return if locked */
1487		if (!readqf(e))
1488		{
1489			if (tTd(40, 4) && e->e_id != NULL)
1490				printf("readqf(%s) failed\n", e->e_id);
1491			e->e_id = NULL;
1492			if (forkflag)
1493				exit(EX_OK);
1494			else
1495				return 0;
1496		}
1497
1498		e->e_flags |= EF_INQUEUE;
1499		eatheader(e, requeueflag);
1500
1501		if (requeueflag)
1502			queueup(e, FALSE);
1503
1504		/* do the delivery */
1505		sendall(e, SM_DELIVER);
1506
1507		/* finish up and exit */
1508		if (forkflag)
1509			finis();
1510		else
1511			dropenvelope(e, TRUE);
1512	}
1513	e->e_id = NULL;
1514	return pid;
1515}
1516/*
1517**  READQF -- read queue file and set up environment.
1518**
1519**	Parameters:
1520**		e -- the envelope of the job to run.
1521**
1522**	Returns:
1523**		TRUE if it successfully read the queue file.
1524**		FALSE otherwise.
1525**
1526**	Side Effects:
1527**		The queue file is returned locked.
1528*/
1529
1530bool
1531readqf(e)
1532	register ENVELOPE *e;
1533{
1534	register FILE *qfp;
1535	ADDRESS *ctladdr;
1536	struct stat st;
1537	char *bp;
1538	int qfver = 0;
1539	long hdrsize = 0;
1540	register char *p;
1541	char *orcpt = NULL;
1542	bool nomore = FALSE;
1543	char qf[MAXQFNAME];
1544	char buf[MAXLINE];
1545	extern ADDRESS *setctluser __P((char *, int));
1546
1547	/*
1548	**  Read and process the file.
1549	*/
1550
1551	strcpy(qf, queuename(e, 'q'));
1552	qfp = fopen(qf, "r+");
1553	if (qfp == NULL)
1554	{
1555		if (tTd(40, 8))
1556			printf("readqf(%s): fopen failure (%s)\n",
1557				qf, errstring(errno));
1558		if (errno != ENOENT)
1559			syserr("readqf: no control file %s", qf);
1560		return FALSE;
1561	}
1562
1563	if (!lockfile(fileno(qfp), qf, NULL, LOCK_EX|LOCK_NB))
1564	{
1565		/* being processed by another queuer */
1566		if (Verbose || tTd(40, 8))
1567			printf("%s: locked\n", e->e_id);
1568		if (LogLevel > 19)
1569			sm_syslog(LOG_DEBUG, e->e_id, "locked");
1570		(void) fclose(qfp);
1571		return FALSE;
1572	}
1573
1574	/*
1575	**  Check the queue file for plausibility to avoid attacks.
1576	*/
1577
1578	if (fstat(fileno(qfp), &st) < 0)
1579	{
1580		/* must have been being processed by someone else */
1581		if (tTd(40, 8))
1582			printf("readqf(%s): fstat failure (%s)\n",
1583				qf, errstring(errno));
1584		fclose(qfp);
1585		return FALSE;
1586	}
1587
1588	if ((st.st_uid != geteuid() && geteuid() != RealUid) ||
1589	    bitset(S_IWOTH|S_IWGRP, st.st_mode))
1590	{
1591		if (LogLevel > 0)
1592		{
1593			sm_syslog(LOG_ALERT, e->e_id,
1594				"bogus queue file, uid=%d, mode=%o",
1595				st.st_uid, st.st_mode);
1596		}
1597		if (tTd(40, 8))
1598			printf("readqf(%s): bogus file\n", qf);
1599		loseqfile(e, "bogus file uid in mqueue");
1600		fclose(qfp);
1601		return FALSE;
1602	}
1603
1604	if (st.st_size == 0)
1605	{
1606		/* must be a bogus file -- if also old, just remove it */
1607		if (st.st_ctime + 10 * 60 < curtime())
1608		{
1609			qf[0] = 'd';
1610			(void) unlink(qf);
1611			qf[0] = 'q';
1612			(void) unlink(qf);
1613		}
1614		fclose(qfp);
1615		return FALSE;
1616	}
1617
1618	if (st.st_nlink == 0)
1619	{
1620		/*
1621		**  Race condition -- we got a file just as it was being
1622		**  unlinked.  Just assume it is zero length.
1623		*/
1624
1625		fclose(qfp);
1626		return FALSE;
1627	}
1628
1629	/* good file -- save this lock */
1630	e->e_lockfp = qfp;
1631
1632	/* do basic system initialization */
1633	initsys(e);
1634	define('i', e->e_id, e);
1635
1636	LineNumber = 0;
1637	e->e_flags |= EF_GLOBALERRS;
1638	OpMode = MD_DELIVER;
1639	ctladdr = NULL;
1640	e->e_dfino = -1;
1641	e->e_msgsize = -1;
1642	while ((bp = fgetfolded(buf, sizeof buf, qfp)) != NULL)
1643	{
1644		register char *p;
1645		u_long qflags;
1646		ADDRESS *q;
1647		int mid;
1648		auto char *ep;
1649
1650		if (tTd(40, 4))
1651			printf("+++++ %s\n", bp);
1652		if (nomore)
1653		{
1654			/* hack attack */
1655			syserr("SECURITY ALERT: extra data in qf: %s", bp);
1656			fclose(qfp);
1657			loseqfile(e, "bogus queue line");
1658			return FALSE;
1659		}
1660		switch (bp[0])
1661		{
1662		  case 'V':		/* queue file version number */
1663			qfver = atoi(&bp[1]);
1664			if (qfver <= QF_VERSION)
1665				break;
1666			syserr("Version number in qf (%d) greater than max (%d)",
1667				qfver, QF_VERSION);
1668			fclose(qfp);
1669			loseqfile(e, "unsupported qf file version");
1670			return FALSE;
1671
1672		  case 'C':		/* specify controlling user */
1673			ctladdr = setctluser(&bp[1], qfver);
1674			break;
1675
1676		  case 'Q':		/* original recipient */
1677			orcpt = newstr(&bp[1]);
1678			break;
1679
1680		  case 'R':		/* specify recipient */
1681			p = bp;
1682			qflags = 0;
1683			if (qfver >= 1)
1684			{
1685				/* get flag bits */
1686				while (*++p != '\0' && *p != ':')
1687				{
1688					switch (*p)
1689					{
1690					  case 'N':
1691						qflags |= QHASNOTIFY;
1692						break;
1693
1694					  case 'S':
1695						qflags |= QPINGONSUCCESS;
1696						break;
1697
1698					  case 'F':
1699						qflags |= QPINGONFAILURE;
1700						break;
1701
1702					  case 'D':
1703						qflags |= QPINGONDELAY;
1704						break;
1705
1706					  case 'P':
1707						qflags |= QPRIMARY;
1708						break;
1709					}
1710				}
1711			}
1712			else
1713				qflags |= QPRIMARY;
1714			q = parseaddr(++p, NULLADDR, RF_COPYALL, '\0', NULL, e);
1715			if (q != NULL)
1716			{
1717				q->q_alias = ctladdr;
1718				if (qfver >= 1)
1719					q->q_flags &= ~Q_PINGFLAGS;
1720				q->q_flags |= qflags;
1721				q->q_orcpt = orcpt;
1722				(void) recipient(q, &e->e_sendqueue, 0, e);
1723			}
1724			orcpt = NULL;
1725			break;
1726
1727		  case 'E':		/* specify error recipient */
1728			/* no longer used */
1729			break;
1730
1731		  case 'H':		/* header */
1732			(void) chompheader(&bp[1], FALSE, NULL, e);
1733			hdrsize += strlen(&bp[1]);
1734			break;
1735
1736		  case 'L':		/* Solaris Content-Length: */
1737		  case 'M':		/* message */
1738			/* ignore this; we want a new message next time */
1739			break;
1740
1741		  case 'S':		/* sender */
1742			setsender(newstr(&bp[1]), e, NULL, '\0', TRUE);
1743			break;
1744
1745		  case 'B':		/* body type */
1746			e->e_bodytype = newstr(&bp[1]);
1747			break;
1748
1749#if _FFR_SAVE_CHARSET
1750		  case 'X':		/* character set */
1751			e->e_charset = newstr(&bp[1]);
1752			break;
1753#endif
1754
1755		  case 'D':		/* data file name */
1756			/* obsolete -- ignore */
1757			break;
1758
1759		  case 'T':		/* init time */
1760			e->e_ctime = atol(&bp[1]);
1761			break;
1762
1763		  case 'I':		/* data file's inode number */
1764			/* regenerated below */
1765			break;
1766
1767		  case 'K':		/* time of last deliver attempt */
1768			e->e_dtime = atol(&buf[1]);
1769			break;
1770
1771		  case 'N':		/* number of delivery attempts */
1772			e->e_ntries = atoi(&buf[1]);
1773
1774			/* if this has been tried recently, let it be */
1775			if (e->e_ntries > 0 &&
1776			    MinQueueAge > 0 && e->e_dtime <= curtime() &&
1777			    curtime() < e->e_dtime + MinQueueAge)
1778			{
1779				char *howlong = pintvl(curtime() - e->e_dtime, TRUE);
1780				extern void unlockqueue __P((ENVELOPE *));
1781
1782				if (Verbose || tTd(40, 8))
1783					printf("%s: too young (%s)\n",
1784						e->e_id, howlong);
1785				if (LogLevel > 19)
1786					sm_syslog(LOG_DEBUG, e->e_id,
1787						"too young (%s)",
1788						howlong);
1789				e->e_id = NULL;
1790				unlockqueue(e);
1791				return FALSE;
1792			}
1793			break;
1794
1795		  case 'P':		/* message priority */
1796			e->e_msgpriority = atol(&bp[1]) + WkTimeFact;
1797			break;
1798
1799		  case 'F':		/* flag bits */
1800			if (strncmp(bp, "From ", 5) == 0)
1801			{
1802				/* we are being spoofed! */
1803				syserr("SECURITY ALERT: bogus qf line %s", bp);
1804				fclose(qfp);
1805				loseqfile(e, "bogus queue line");
1806				return FALSE;
1807			}
1808			for (p = &bp[1]; *p != '\0'; p++)
1809			{
1810				switch (*p)
1811				{
1812				  case 'w':	/* warning sent */
1813					e->e_flags |= EF_WARNING;
1814					break;
1815
1816				  case 'r':	/* response */
1817					e->e_flags |= EF_RESPONSE;
1818					break;
1819
1820				  case '8':	/* has 8 bit data */
1821					e->e_flags |= EF_HAS8BIT;
1822					break;
1823
1824				  case 'b':	/* delete Bcc: header */
1825					e->e_flags |= EF_DELETE_BCC;
1826					break;
1827
1828				  case 'd':	/* envelope has DSN RET= */
1829					e->e_flags |= EF_RET_PARAM;
1830					break;
1831
1832				  case 'n':	/* don't return body */
1833					e->e_flags |= EF_NO_BODY_RETN;
1834					break;
1835				}
1836			}
1837			break;
1838
1839		  case 'Z':		/* original envelope id from ESMTP */
1840			e->e_envid = newstr(&bp[1]);
1841			break;
1842
1843		  case '$':		/* define macro */
1844			mid = macid(&bp[1], &ep);
1845			define(mid, newstr(ep), e);
1846			break;
1847
1848		  case '.':		/* terminate file */
1849			nomore = TRUE;
1850			break;
1851
1852		  default:
1853			syserr("readqf: %s: line %d: bad line \"%s\"",
1854				qf, LineNumber, shortenstring(bp, MAXSHORTSTR));
1855			fclose(qfp);
1856			loseqfile(e, "unrecognized line");
1857			return FALSE;
1858		}
1859
1860		if (bp != buf)
1861			free(bp);
1862	}
1863
1864	/*
1865	**  If we haven't read any lines, this queue file is empty.
1866	**  Arrange to remove it without referencing any null pointers.
1867	*/
1868
1869	if (LineNumber == 0)
1870	{
1871		errno = 0;
1872		e->e_flags |= EF_CLRQUEUE | EF_FATALERRS | EF_RESPONSE;
1873		return TRUE;
1874	}
1875
1876	/*
1877	**  Arrange to read the data file.
1878	*/
1879
1880	p = queuename(e, 'd');
1881	e->e_dfp = fopen(p, "r");
1882	if (e->e_dfp == NULL)
1883	{
1884		syserr("readqf: cannot open %s", p);
1885	}
1886	else
1887	{
1888		e->e_flags |= EF_HAS_DF;
1889		if (fstat(fileno(e->e_dfp), &st) >= 0)
1890		{
1891			e->e_msgsize = st.st_size + hdrsize;
1892			e->e_dfdev = st.st_dev;
1893			e->e_dfino = st.st_ino;
1894		}
1895	}
1896
1897	return TRUE;
1898}
1899/*
1900**  PRINTQUEUE -- print out a representation of the mail queue
1901**
1902**	Parameters:
1903**		none.
1904**
1905**	Returns:
1906**		none.
1907**
1908**	Side Effects:
1909**		Prints a listing of the mail queue on the standard output.
1910*/
1911
1912void
1913printqueue()
1914{
1915	register WORK *w;
1916	FILE *f;
1917	int nrequests;
1918	char buf[MAXLINE];
1919
1920	/*
1921	**  Check for permission to print the queue
1922	*/
1923
1924	if (bitset(PRIV_RESTRICTMAILQ, PrivacyFlags) && RealUid != 0)
1925	{
1926		struct stat st;
1927# ifdef NGROUPS_MAX
1928		int n;
1929		extern GIDSET_T InitialGidSet[NGROUPS_MAX];
1930# endif
1931
1932		if (stat(QueueDir, &st) < 0)
1933		{
1934			syserr("Cannot stat %s", QueueDir);
1935			return;
1936		}
1937# ifdef NGROUPS_MAX
1938		n = NGROUPS_MAX;
1939		while (--n >= 0)
1940		{
1941			if (InitialGidSet[n] == st.st_gid)
1942				break;
1943		}
1944		if (n < 0 && RealGid != st.st_gid)
1945# else
1946		if (RealGid != st.st_gid)
1947# endif
1948		{
1949			usrerr("510 You are not permitted to see the queue");
1950			setstat(EX_NOPERM);
1951			return;
1952		}
1953	}
1954
1955	/*
1956	**  Read and order the queue.
1957	*/
1958
1959	nrequests = orderq(TRUE);
1960
1961	/*
1962	**  Print the work list that we have read.
1963	*/
1964
1965	/* first see if there is anything */
1966	if (nrequests <= 0)
1967	{
1968		printf("Mail queue is empty\n");
1969		return;
1970	}
1971
1972	CurrentLA = getla();	/* get load average */
1973
1974	printf("\t\tMail Queue (%d request%s", nrequests, nrequests == 1 ? "" : "s");
1975	if (MaxQueueRun > 0 && nrequests > MaxQueueRun)
1976		printf(", only %d printed", MaxQueueRun);
1977	if (Verbose)
1978		printf(")\n--Q-ID-- --Size-- -Priority- ---Q-Time--- -----------Sender/Recipient-----------\n");
1979	else
1980		printf(")\n--Q-ID-- --Size-- -----Q-Time----- ------------Sender/Recipient------------\n");
1981	for (w = WorkQ; w != NULL; w = w->w_next)
1982	{
1983		struct stat st;
1984		auto time_t submittime = 0;
1985		long dfsize;
1986		int flags = 0;
1987		int qfver;
1988		char statmsg[MAXLINE];
1989		char bodytype[MAXNAME + 1];
1990
1991		printf("%8s", w->w_name + 2);
1992		f = fopen(w->w_name, "r");
1993		if (f == NULL)
1994		{
1995			printf(" (job completed)\n");
1996			errno = 0;
1997			continue;
1998		}
1999		w->w_name[0] = 'd';
2000		if (stat(w->w_name, &st) >= 0)
2001			dfsize = st.st_size;
2002		else
2003			dfsize = -1;
2004		if (w->w_lock)
2005			printf("*");
2006		else if (w->w_tooyoung)
2007			printf("-");
2008		else if (shouldqueue(w->w_pri, w->w_ctime))
2009			printf("X");
2010		else
2011			printf(" ");
2012		errno = 0;
2013
2014		statmsg[0] = bodytype[0] = '\0';
2015		qfver = 0;
2016		while (fgets(buf, sizeof buf, f) != NULL)
2017		{
2018			register int i;
2019			register char *p;
2020
2021			fixcrlf(buf, TRUE);
2022			switch (buf[0])
2023			{
2024			  case 'V':	/* queue file version */
2025				qfver = atoi(&buf[1]);
2026				break;
2027
2028			  case 'M':	/* error message */
2029				if ((i = strlen(&buf[1])) >= sizeof statmsg)
2030					i = sizeof statmsg - 1;
2031				bcopy(&buf[1], statmsg, i);
2032				statmsg[i] = '\0';
2033				break;
2034
2035			  case 'B':	/* body type */
2036				if ((i = strlen(&buf[1])) >= sizeof bodytype)
2037					i = sizeof bodytype - 1;
2038				bcopy(&buf[1], bodytype, i);
2039				bodytype[i] = '\0';
2040				break;
2041
2042			  case 'S':	/* sender name */
2043				if (Verbose)
2044					printf("%8ld %10ld%c%.12s %.78s",
2045					    dfsize,
2046					    w->w_pri,
2047					    bitset(EF_WARNING, flags) ? '+' : ' ',
2048					    ctime(&submittime) + 4,
2049					    &buf[1]);
2050				else
2051					printf("%8ld %.16s %.45s", dfsize,
2052					    ctime(&submittime), &buf[1]);
2053				if (statmsg[0] != '\0' || bodytype[0] != '\0')
2054				{
2055					printf("\n    %10.10s", bodytype);
2056					if (statmsg[0] != '\0')
2057						printf("   (%.*s)",
2058							Verbose ? 100 : 60,
2059							statmsg);
2060				}
2061				break;
2062
2063			  case 'C':	/* controlling user */
2064				if (Verbose)
2065					printf("\n\t\t\t\t      (---%.74s---)",
2066						&buf[1]);
2067				break;
2068
2069			  case 'R':	/* recipient name */
2070				p = &buf[1];
2071				if (qfver >= 1)
2072				{
2073					p = strchr(p, ':');
2074					if (p == NULL)
2075						break;
2076					p++;
2077				}
2078				if (Verbose)
2079					printf("\n\t\t\t\t\t  %.78s", p);
2080				else
2081					printf("\n\t\t\t\t   %.45s", p);
2082				break;
2083
2084			  case 'T':	/* creation time */
2085				submittime = atol(&buf[1]);
2086				break;
2087
2088			  case 'F':	/* flag bits */
2089				for (p = &buf[1]; *p != '\0'; p++)
2090				{
2091					switch (*p)
2092					{
2093					  case 'w':
2094						flags |= EF_WARNING;
2095						break;
2096					}
2097				}
2098			}
2099		}
2100		if (submittime == (time_t) 0)
2101			printf(" (no control file)");
2102		printf("\n");
2103		(void) fclose(f);
2104	}
2105}
2106
2107# endif /* QUEUE */
2108/*
2109**  QUEUENAME -- build a file name in the queue directory for this envelope.
2110**
2111**	Assigns an id code if one does not already exist.
2112**	This code is very careful to avoid trashing existing files
2113**	under any circumstances.
2114**
2115**	Parameters:
2116**		e -- envelope to build it in/from.
2117**		type -- the file type, used as the first character
2118**			of the file name.
2119**
2120**	Returns:
2121**		a pointer to the new file name (in a static buffer).
2122**
2123**	Side Effects:
2124**		If no id code is already assigned, queuename will
2125**		assign an id code, create a qf file, and leave a
2126**		locked, open-for-write file pointer in the envelope.
2127*/
2128
2129#ifndef ENOLCK
2130# define ENOLCK		-1
2131#endif
2132#ifndef ENOSPC
2133# define ENOSPC		-1
2134#endif
2135
2136char *
2137queuename(e, type)
2138	register ENVELOPE *e;
2139	int type;
2140{
2141	static pid_t pid = -1;
2142	static char c0;
2143	static char c1;
2144	static char c2;
2145	time_t now;
2146	struct tm *tm;
2147	static char buf[MAXNAME + 1];
2148
2149	if (e->e_id == NULL)
2150	{
2151		char qf[MAXQFNAME];
2152
2153		/* find a unique id */
2154		if (pid != getpid())
2155		{
2156			/* new process -- start back at "AA" */
2157			pid = getpid();
2158			now = curtime();
2159			tm = localtime(&now);
2160			c0 = 'A' + tm->tm_hour;
2161			c1 = 'A';
2162			c2 = 'A' - 1;
2163		}
2164		(void) snprintf(qf, sizeof qf, "qf%cAA%05d", c0, pid);
2165
2166		while (c1 < '~' || c2 < 'Z')
2167		{
2168			int i;
2169			int attempts = 0;
2170
2171			if (c2 >= 'Z')
2172			{
2173				c1++;
2174				c2 = 'A' - 1;
2175			}
2176			qf[3] = c1;
2177			qf[4] = ++c2;
2178			if (tTd(7, 20))
2179				printf("queuename: trying \"%s\"\n", qf);
2180
2181			i = open(qf, O_WRONLY|O_CREAT|O_EXCL, FileMode);
2182			if (i < 0)
2183			{
2184				if (errno == EEXIST)
2185					continue;
2186				syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
2187					qf, QueueDir, geteuid());
2188				exit(EX_UNAVAILABLE);
2189			}
2190			do
2191			{
2192				if (attempts > 0)
2193					sleep(attempts);
2194				e->e_lockfp = 0;
2195				if (lockfile(i, qf, NULL, LOCK_EX|LOCK_NB))
2196				{
2197					e->e_lockfp = fdopen(i, "w");
2198					break;
2199				}
2200			} while ((errno == ENOLCK || errno == ENOSPC) &&
2201				 attempts++ < 4);
2202
2203			/* Successful lock */
2204			if (e->e_lockfp != 0)
2205				break;
2206
2207#if !HASFLOCK
2208			if (errno != EAGAIN && errno != EACCES)
2209#else
2210			if (errno != EWOULDBLOCK)
2211#endif
2212			{
2213				syserr("queuename: Cannot lock \"%s\" in \"%s\" (euid=%d)",
2214					qf, QueueDir, geteuid());
2215				exit(EX_OSERR);
2216			}
2217
2218			/* a reader got the file; abandon it and try again */
2219			(void) close(i);
2220		}
2221		if (c1 >= '~' && c2 >= 'Z')
2222		{
2223			syserr("queuename: Cannot create \"%s\" in \"%s\" (euid=%d)",
2224				qf, QueueDir, geteuid());
2225			exit(EX_OSERR);
2226		}
2227		e->e_id = newstr(&qf[2]);
2228		define('i', e->e_id, e);
2229		if (tTd(7, 1))
2230			printf("queuename: assigned id %s, env=%lx\n",
2231			       e->e_id, (u_long) e);
2232		if (tTd(7, 9))
2233		{
2234			printf("  lockfd=");
2235			dumpfd(fileno(e->e_lockfp), TRUE, FALSE);
2236		}
2237		if (LogLevel > 93)
2238			sm_syslog(LOG_DEBUG, e->e_id, "assigned id");
2239	}
2240
2241	if (type == '\0')
2242		return (NULL);
2243	(void) snprintf(buf, sizeof buf, "%cf%s", type, e->e_id);
2244	if (tTd(7, 2))
2245		printf("queuename: %s\n", buf);
2246	return (buf);
2247}
2248/*
2249**  UNLOCKQUEUE -- unlock the queue entry for a specified envelope
2250**
2251**	Parameters:
2252**		e -- the envelope to unlock.
2253**
2254**	Returns:
2255**		none
2256**
2257**	Side Effects:
2258**		unlocks the queue for `e'.
2259*/
2260
2261void
2262unlockqueue(e)
2263	ENVELOPE *e;
2264{
2265	if (tTd(51, 4))
2266		printf("unlockqueue(%s)\n",
2267			e->e_id == NULL ? "NOQUEUE" : e->e_id);
2268
2269	/* if there is a lock file in the envelope, close it */
2270	if (e->e_lockfp != NULL)
2271		xfclose(e->e_lockfp, "unlockqueue", e->e_id);
2272	e->e_lockfp = NULL;
2273
2274	/* don't create a queue id if we don't already have one */
2275	if (e->e_id == NULL)
2276		return;
2277
2278	/* remove the transcript */
2279	if (LogLevel > 87)
2280		sm_syslog(LOG_DEBUG, e->e_id, "unlock");
2281	if (!tTd(51, 104))
2282		xunlink(queuename(e, 'x'));
2283
2284}
2285/*
2286**  SETCTLUSER -- create a controlling address
2287**
2288**	Create a fake "address" given only a local login name; this is
2289**	used as a "controlling user" for future recipient addresses.
2290**
2291**	Parameters:
2292**		user -- the user name of the controlling user.
2293**		qfver -- the version stamp of this qf file.
2294**
2295**	Returns:
2296**		An address descriptor for the controlling user.
2297**
2298**	Side Effects:
2299**		none.
2300*/
2301
2302ADDRESS *
2303setctluser(user, qfver)
2304	char *user;
2305	int qfver;
2306{
2307	register ADDRESS *a;
2308	struct passwd *pw;
2309	char *p;
2310
2311	/*
2312	**  See if this clears our concept of controlling user.
2313	*/
2314
2315	if (user == NULL || *user == '\0')
2316		return NULL;
2317
2318	/*
2319	**  Set up addr fields for controlling user.
2320	*/
2321
2322	a = (ADDRESS *) xalloc(sizeof *a);
2323	bzero((char *) a, sizeof *a);
2324
2325	if (*user == '\0')
2326	{
2327		p = NULL;
2328		a->q_user = newstr(DefUser);
2329	}
2330	else if (*user == ':')
2331	{
2332		p = &user[1];
2333		a->q_user = newstr(p);
2334	}
2335	else
2336	{
2337		p = strtok(user, ":");
2338		a->q_user = newstr(user);
2339		if (qfver >= 2)
2340		{
2341			if ((p = strtok(NULL, ":")) != NULL)
2342				a->q_uid = atoi(p);
2343			if ((p = strtok(NULL, ":")) != NULL)
2344				a->q_gid = atoi(p);
2345			if ((p = strtok(NULL, ":")) != NULL)
2346				a->q_flags |= QGOODUID;
2347		}
2348		else if ((pw = sm_getpwnam(user)) != NULL)
2349		{
2350			if (strcmp(pw->pw_dir, "/") == 0)
2351				a->q_home = "";
2352			else
2353				a->q_home = newstr(pw->pw_dir);
2354			a->q_uid = pw->pw_uid;
2355			a->q_gid = pw->pw_gid;
2356			a->q_flags |= QGOODUID;
2357		}
2358	}
2359
2360	a->q_flags |= QPRIMARY;		/* flag as a "ctladdr"  */
2361	a->q_mailer = LocalMailer;
2362	if (p == NULL)
2363		a->q_paddr = a->q_user;
2364	else
2365		a->q_paddr = newstr(p);
2366	return a;
2367}
2368/*
2369**  LOSEQFILE -- save the qf as Qf and try to let someone know
2370**
2371**	Parameters:
2372**		e -- the envelope (e->e_id will be used).
2373**		why -- reported to whomever can hear.
2374**
2375**	Returns:
2376**		none.
2377*/
2378
2379void
2380loseqfile(e, why)
2381	register ENVELOPE *e;
2382	char *why;
2383{
2384	char *p;
2385	char buf[MAXQFNAME + 1];
2386
2387	if (e == NULL || e->e_id == NULL)
2388		return;
2389	p = queuename(e, 'q');
2390	if (strlen(p) > MAXQFNAME)
2391	{
2392		syserr("loseqfile: queuename (%s) too long", p);
2393		return;
2394	}
2395	strcpy(buf, p);
2396	p = queuename(e, 'Q');
2397	if (rename(buf, p) < 0)
2398		syserr("cannot rename(%s, %s), uid=%d", buf, p, geteuid());
2399	else if (LogLevel > 0)
2400		sm_syslog(LOG_ALERT, e->e_id,
2401			"Losing %s: %s", buf, why);
2402}
2403