conf.c revision 363466
1/*
2 * Copyright (c) 1998-2013 Proofpoint, Inc. and its suppliers.
3 *	All rights reserved.
4 * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
5 * Copyright (c) 1988, 1993
6 *	The Regents of the University of California.  All rights reserved.
7 *
8 * By using this file, you agree to the terms and conditions set
9 * forth in the LICENSE file which can be found at the top level of
10 * the sendmail distribution.
11 *
12 */
13
14#include <sendmail.h>
15
16SM_RCSID("@(#)$Id: conf.c,v 8.1192 2014-01-27 18:23:21 ca Exp $")
17
18#include <sm/sendmail.h>
19#include <sendmail/pathnames.h>
20#if NEWDB
21# include "sm/bdb.h"
22#endif
23
24#include <daemon.h>
25#include "map.h"
26#include <ratectrl.h>
27
28#ifdef DEC
29# if NETINET6
30/* for the IPv6 device lookup */
31#  define _SOCKADDR_LEN
32#  include <macros.h>
33# endif /* NETINET6 */
34#endif /* DEC */
35
36# include <sys/ioctl.h>
37# include <sys/param.h>
38
39#include <limits.h>
40#if NETINET || NETINET6
41# include <arpa/inet.h>
42#endif
43#if HASULIMIT && defined(HPUX11)
44# include <ulimit.h>
45#endif
46#if STARTTLS
47# include "tls.h"
48#endif
49
50static void	setupmaps __P((void));
51static void	setupmailers __P((void));
52static void	setupqueues __P((void));
53static int	get_num_procs_online __P((void));
54static int	add_hostnames __P((SOCKADDR *));
55
56#if NETINET6 && NEEDSGETIPNODE
57static struct hostent *sm_getipnodebyname __P((const char *, int, int, int *));
58static struct hostent *sm_getipnodebyaddr __P((const void *, size_t, int, int *));
59#else /* NETINET6 && NEEDSGETIPNODE */
60#define sm_getipnodebyname getipnodebyname
61#define sm_getipnodebyaddr getipnodebyaddr
62#endif /* NETINET6 && NEEDSGETIPNODE */
63
64
65/*
66**  CONF.C -- Sendmail Configuration Tables.
67**
68**	Defines the configuration of this installation.
69**
70**	Configuration Variables:
71**		HdrInfo -- a table describing well-known header fields.
72**			Each entry has the field name and some flags,
73**			which are described in sendmail.h.
74**
75**	Notes:
76**		I have tried to put almost all the reasonable
77**		configuration information into the configuration
78**		file read at runtime.  My intent is that anything
79**		here is a function of the version of UNIX you
80**		are running, or is really static -- for example
81**		the headers are a superset of widely used
82**		protocols.  If you find yourself playing with
83**		this file too much, you may be making a mistake!
84*/
85
86
87/*
88**  Header info table
89**	Final (null) entry contains the flags used for any other field.
90**
91**	Not all of these are actually handled specially by sendmail
92**	at this time.  They are included as placeholders, to let
93**	you know that "someday" I intend to have sendmail do
94**	something with them.
95*/
96
97struct hdrinfo	HdrInfo[] =
98{
99		/* originator fields, most to least significant */
100	{ "resent-sender",		H_FROM|H_RESENT,	NULL	},
101	{ "resent-from",		H_FROM|H_RESENT,	NULL	},
102	{ "resent-reply-to",		H_FROM|H_RESENT,	NULL	},
103	{ "sender",			H_FROM,			NULL	},
104	{ "from",			H_FROM,			NULL	},
105	{ "reply-to",			H_FROM,			NULL	},
106	{ "errors-to",			H_FROM|H_ERRORSTO,	NULL	},
107	{ "full-name",			H_ACHECK,		NULL	},
108	{ "return-receipt-to",		H_RECEIPTTO,		NULL	},
109	{ "delivery-receipt-to",	H_RECEIPTTO,		NULL	},
110	{ "disposition-notification-to",	H_FROM,		NULL	},
111
112		/* destination fields */
113	{ "to",				H_RCPT,			NULL	},
114	{ "resent-to",			H_RCPT|H_RESENT,	NULL	},
115	{ "cc",				H_RCPT,			NULL	},
116	{ "resent-cc",			H_RCPT|H_RESENT,	NULL	},
117	{ "bcc",			H_RCPT|H_BCC,		NULL	},
118	{ "resent-bcc",			H_RCPT|H_BCC|H_RESENT,	NULL	},
119	{ "apparently-to",		H_RCPT,			NULL	},
120
121		/* message identification and control */
122	{ "message-id",			0,			NULL	},
123	{ "resent-message-id",		H_RESENT,		NULL	},
124#if !NO_EOH_FIELDS
125	{ "message",			H_EOH,			NULL	},
126	{ "text",			H_EOH,			NULL	},
127#endif
128
129		/* date fields */
130	{ "date",			0,			NULL	},
131	{ "resent-date",		H_RESENT,		NULL	},
132
133		/* trace fields */
134	{ "received",			H_TRACE|H_FORCE,	NULL	},
135	{ "x400-received",		H_TRACE|H_FORCE,	NULL	},
136	{ "via",			H_TRACE|H_FORCE,	NULL	},
137	{ "mail-from",			H_TRACE|H_FORCE,	NULL	},
138
139		/* miscellaneous fields */
140	{ "comments",			H_FORCE|H_ENCODABLE,	NULL	},
141	{ "return-path",		H_FORCE|H_ACHECK|H_BINDLATE,	NULL	},
142	{ "content-transfer-encoding",	H_CTE,			NULL	},
143	{ "content-type",		H_CTYPE,		NULL	},
144	{ "content-length",		H_ACHECK,		NULL	},
145	{ "subject",			H_ENCODABLE,		NULL	},
146	{ "x-authentication-warning",	H_FORCE,		NULL	},
147
148	{ NULL,				0,			NULL	}
149};
150
151
152
153/*
154**  Privacy values
155*/
156
157struct prival PrivacyValues[] =
158{
159	{ "public",		PRIV_PUBLIC		},
160	{ "needmailhelo",	PRIV_NEEDMAILHELO	},
161	{ "needexpnhelo",	PRIV_NEEDEXPNHELO	},
162	{ "needvrfyhelo",	PRIV_NEEDVRFYHELO	},
163	{ "noexpn",		PRIV_NOEXPN		},
164	{ "novrfy",		PRIV_NOVRFY		},
165	{ "restrictexpand",	PRIV_RESTRICTEXPAND	},
166	{ "restrictmailq",	PRIV_RESTRICTMAILQ	},
167	{ "restrictqrun",	PRIV_RESTRICTQRUN	},
168	{ "noetrn",		PRIV_NOETRN		},
169	{ "noverb",		PRIV_NOVERB		},
170	{ "authwarnings",	PRIV_AUTHWARNINGS	},
171	{ "noreceipts",		PRIV_NORECEIPTS		},
172	{ "nobodyreturn",	PRIV_NOBODYRETN		},
173	{ "goaway",		PRIV_GOAWAY		},
174	{ "noactualrecipient",	PRIV_NOACTUALRECIPIENT	},
175	{ NULL,			0			}
176};
177
178/*
179**  DontBlameSendmail values
180*/
181
182struct dbsval DontBlameSendmailValues[] =
183{
184	{ "safe",			DBS_SAFE			},
185	{ "assumesafechown",		DBS_ASSUMESAFECHOWN		},
186	{ "groupwritabledirpathsafe",	DBS_GROUPWRITABLEDIRPATHSAFE	},
187	{ "groupwritableforwardfilesafe",
188					DBS_GROUPWRITABLEFORWARDFILESAFE },
189	{ "groupwritableincludefilesafe",
190					DBS_GROUPWRITABLEINCLUDEFILESAFE },
191	{ "groupwritablealiasfile",	DBS_GROUPWRITABLEALIASFILE	},
192	{ "worldwritablealiasfile",	DBS_WORLDWRITABLEALIASFILE	},
193	{ "forwardfileinunsafedirpath",	DBS_FORWARDFILEINUNSAFEDIRPATH	},
194	{ "includefileinunsafedirpath",	DBS_INCLUDEFILEINUNSAFEDIRPATH	},
195	{ "mapinunsafedirpath",		DBS_MAPINUNSAFEDIRPATH	},
196	{ "linkedaliasfileinwritabledir",
197					DBS_LINKEDALIASFILEINWRITABLEDIR },
198	{ "linkedclassfileinwritabledir",
199					DBS_LINKEDCLASSFILEINWRITABLEDIR },
200	{ "linkedforwardfileinwritabledir",
201					DBS_LINKEDFORWARDFILEINWRITABLEDIR },
202	{ "linkedincludefileinwritabledir",
203					DBS_LINKEDINCLUDEFILEINWRITABLEDIR },
204	{ "linkedmapinwritabledir",	DBS_LINKEDMAPINWRITABLEDIR	},
205	{ "linkedserviceswitchfileinwritabledir",
206					DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR },
207	{ "filedeliverytohardlink",	DBS_FILEDELIVERYTOHARDLINK	},
208	{ "filedeliverytosymlink",	DBS_FILEDELIVERYTOSYMLINK	},
209	{ "writemaptohardlink",		DBS_WRITEMAPTOHARDLINK		},
210	{ "writemaptosymlink",		DBS_WRITEMAPTOSYMLINK		},
211	{ "writestatstohardlink",	DBS_WRITESTATSTOHARDLINK	},
212	{ "writestatstosymlink",	DBS_WRITESTATSTOSYMLINK		},
213	{ "forwardfileingroupwritabledirpath",
214					DBS_FORWARDFILEINGROUPWRITABLEDIRPATH },
215	{ "includefileingroupwritabledirpath",
216					DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH },
217	{ "classfileinunsafedirpath",	DBS_CLASSFILEINUNSAFEDIRPATH	},
218	{ "errorheaderinunsafedirpath",	DBS_ERRORHEADERINUNSAFEDIRPATH	},
219	{ "helpfileinunsafedirpath",	DBS_HELPFILEINUNSAFEDIRPATH	},
220	{ "forwardfileinunsafedirpathsafe",
221					DBS_FORWARDFILEINUNSAFEDIRPATHSAFE },
222	{ "includefileinunsafedirpathsafe",
223					DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE },
224	{ "runprograminunsafedirpath",	DBS_RUNPROGRAMINUNSAFEDIRPATH	},
225	{ "runwritableprogram",		DBS_RUNWRITABLEPROGRAM		},
226	{ "nonrootsafeaddr",		DBS_NONROOTSAFEADDR		},
227	{ "truststickybit",		DBS_TRUSTSTICKYBIT		},
228	{ "dontwarnforwardfileinunsafedirpath",
229					DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH },
230	{ "insufficiententropy",	DBS_INSUFFICIENTENTROPY },
231	{ "groupreadablesasldbfile",	DBS_GROUPREADABLESASLDBFILE	},
232	{ "groupwritablesasldbfile",	DBS_GROUPWRITABLESASLDBFILE	},
233	{ "groupwritableforwardfile",	DBS_GROUPWRITABLEFORWARDFILE	},
234	{ "groupwritableincludefile",	DBS_GROUPWRITABLEINCLUDEFILE	},
235	{ "worldwritableforwardfile",	DBS_WORLDWRITABLEFORWARDFILE	},
236	{ "worldwritableincludefile",	DBS_WORLDWRITABLEINCLUDEFILE	},
237	{ "groupreadablekeyfile",	DBS_GROUPREADABLEKEYFILE	},
238	{ "groupreadabledefaultauthinfofile",
239					DBS_GROUPREADABLEAUTHINFOFILE	},
240	{ NULL,				0				}
241};
242
243/*
244**  Miscellaneous stuff.
245*/
246
247int	DtableSize =	50;		/* max open files; reset in 4.2bsd */
248/*
249**  SETDEFAULTS -- set default values
250**
251**	Some of these must be initialized using direct code since they
252**	depend on run-time values. So let's do all of them this way.
253**
254**	Parameters:
255**		e -- the default envelope.
256**
257**	Returns:
258**		none.
259**
260**	Side Effects:
261**		Initializes a bunch of global variables to their
262**		default values.
263*/
264
265#define MINUTES		* 60
266#define HOURS		* 60 MINUTES
267#define DAYS		* 24 HOURS
268
269#ifndef MAXRULERECURSION
270# define MAXRULERECURSION	50	/* max ruleset recursion depth */
271#endif
272
273void
274setdefaults(e)
275	register ENVELOPE *e;
276{
277	int i;
278	int numprocs;
279	struct passwd *pw;
280
281	numprocs = get_num_procs_online();
282	SpaceSub = ' ';				/* option B */
283	QueueLA = 8 * numprocs;			/* option x */
284	RefuseLA = 12 * numprocs;		/* option X */
285	WkRecipFact = 30000L;			/* option y */
286	WkClassFact = 1800L;			/* option z */
287	WkTimeFact = 90000L;			/* option Z */
288	QueueFactor = WkRecipFact * 20;		/* option q */
289	QueueMode = QM_NORMAL;		/* what queue items to act upon */
290	FileMode = (RealUid != geteuid()) ? 0644 : 0600;
291						/* option F */
292	QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600;
293						/* option QueueFileMode */
294
295	if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) ||
296	    ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) ||
297	    ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0))
298	{
299		DefUid = pw->pw_uid;		/* option u */
300		DefGid = pw->pw_gid;		/* option g */
301		DefUser = newstr(pw->pw_name);
302	}
303	else
304	{
305		DefUid = 1;			/* option u */
306		DefGid = 1;			/* option g */
307		setdefuser();
308	}
309	TrustedUid = 0;
310	if (tTd(37, 4))
311		sm_dprintf("setdefaults: DefUser=%s, DefUid=%ld, DefGid=%ld\n",
312			DefUser != NULL ? DefUser : "<1:1>",
313			(long) DefUid, (long) DefGid);
314	CheckpointInterval = 10;		/* option C */
315	MaxHopCount = 25;			/* option h */
316	set_delivery_mode(SM_FORK, e);		/* option d */
317	e->e_errormode = EM_PRINT;		/* option e */
318	e->e_qgrp = NOQGRP;
319	e->e_qdir = NOQDIR;
320	e->e_xfqgrp = NOQGRP;
321	e->e_xfqdir = NOQDIR;
322	e->e_ctime = curtime();
323#if _FFR_EAI
324	e->e_smtputf8 = false;
325#endif
326	SevenBitInput = false;			/* option 7 */
327	MaxMciCache = 1;			/* option k */
328	MciCacheTimeout = 5 MINUTES;		/* option K */
329	LogLevel = 9;				/* option L */
330#if MILTER
331	MilterLogLevel = -1;
332#endif
333	inittimeouts(NULL, false);		/* option r */
334	PrivacyFlags = PRIV_PUBLIC;		/* option p */
335	MeToo = true;				/* option m */
336	SendMIMEErrors = true;			/* option f */
337	SuperSafe = SAFE_REALLY;		/* option s */
338	clrbitmap(DontBlameSendmail);		/* DontBlameSendmail option */
339#if MIME8TO7
340	MimeMode = MM_CVTMIME|MM_PASS8BIT;	/* option 8 */
341#else
342	MimeMode = MM_PASS8BIT;
343#endif
344	for (i = 0; i < MAXTOCLASS; i++)
345	{
346		TimeOuts.to_q_return[i] = 5 DAYS;	/* option T */
347		TimeOuts.to_q_warning[i] = 0;		/* option T */
348	}
349	ServiceSwitchFile = "/etc/mail/service.switch";
350	ServiceCacheMaxAge = (time_t) 10;
351	HostsFile = _PATH_HOSTS;
352	PidFile = newstr(_PATH_SENDMAILPID);
353	MustQuoteChars = "@,;:\\()[].'";
354	MciInfoTimeout = 30 MINUTES;
355	MaxRuleRecursion = MAXRULERECURSION;
356	MaxAliasRecursion = 10;
357	MaxMacroRecursion = 10;
358	ColonOkInAddr = true;
359	DontLockReadFiles = true;
360	DontProbeInterfaces = DPI_PROBEALL;
361	DoubleBounceAddr = "postmaster";
362	MaxHeadersLength = MAXHDRSLEN;
363	MaxMimeHeaderLength = MAXLINE;
364	MaxMimeFieldLength = MaxMimeHeaderLength / 2;
365	MaxForwardEntries = 0;
366	FastSplit = 1;
367	MaxNOOPCommands = MAXNOOPCOMMANDS;
368#if SASL
369	AuthMechanisms = newstr(AUTH_MECHANISMS);
370	AuthRealm = NULL;
371	MaxSLBits = INT_MAX;
372#endif
373#if STARTTLS
374	TLS_Srv_Opts = TLS_I_SRV;
375	if (NULL == EVP_digest)
376		EVP_digest = EVP_md5();
377# if _FFR_TLSFB2CLEAR
378	TLSFallbacktoClear = true;
379# endif
380	Srv_SSL_Options = SSL_OP_ALL;
381	Clt_SSL_Options = SSL_OP_ALL
382# ifdef SSL_OP_NO_SSLv2
383		| SSL_OP_NO_SSLv2
384# endif
385# ifdef SSL_OP_NO_TICKET
386		| SSL_OP_NO_TICKET
387# endif
388		;
389# ifdef SSL_OP_TLSEXT_PADDING
390	/* SSL_OP_TLSEXT_PADDING breaks compatibility with some sites */
391	Srv_SSL_Options &= ~SSL_OP_TLSEXT_PADDING;
392	Clt_SSL_Options &= ~SSL_OP_TLSEXT_PADDING;
393# endif /* SSL_OP_TLSEXT_PADDING */
394#endif /* STARTTLS */
395#ifdef HESIOD_INIT
396	HesiodContext = NULL;
397#endif
398#if NETINET6
399	/* Detect if IPv6 is available at run time */
400	i = socket(AF_INET6, SOCK_STREAM, 0);
401	if (i >= 0)
402	{
403		InetMode = AF_INET6;
404		(void) close(i);
405	}
406	else
407		InetMode = AF_INET;
408#if !IPV6_FULL
409	UseCompressedIPv6Addresses = true;
410#endif
411#else /* NETINET6 */
412	InetMode = AF_INET;
413#endif /* NETINET6 */
414	ControlSocketName = NULL;
415	memset(&ConnectOnlyTo, '\0', sizeof(ConnectOnlyTo));
416	DataFileBufferSize = 4096;
417	XscriptFileBufferSize = 4096;
418	for (i = 0; i < MAXRWSETS; i++)
419		RuleSetNames[i] = NULL;
420#if MILTER
421	InputFilters[0] = NULL;
422#endif
423	RejectLogInterval = 3 HOURS;
424#if REQUIRES_DIR_FSYNC
425	RequiresDirfsync = true;
426#endif
427#if _FFR_RCPTTHROTDELAY
428	BadRcptThrottleDelay = 1;
429#endif
430	ConnectionRateWindowSize = 60;
431#if _FFR_BOUNCE_QUEUE
432	BounceQueue = NOQGRP;
433#endif
434	setupmaps();
435	setupqueues();
436	setupmailers();
437	setupheaders();
438}
439
440/*
441**  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
442*/
443
444void
445setdefuser()
446{
447	struct passwd *defpwent;
448	static char defuserbuf[40];
449
450	DefUser = defuserbuf;
451	defpwent = sm_getpwuid(DefUid);
452	(void) sm_strlcpy(defuserbuf,
453			  (defpwent == NULL || defpwent->pw_name == NULL)
454			   ? "nobody" : defpwent->pw_name,
455			  sizeof(defuserbuf));
456	if (tTd(37, 4))
457		sm_dprintf("setdefuser: DefUid=%ld, DefUser=%s\n",
458			   (long) DefUid, DefUser);
459}
460/*
461**  SETUPQUEUES -- initialize default queues
462**
463**	The mqueue QUEUE structure gets filled in after readcf() but
464**	we need something to point to now for the mailer setup,
465**	which use "mqueue" as default queue.
466*/
467
468static void
469setupqueues()
470{
471	char buf[100];
472
473	MaxRunnersPerQueue = 1;
474	(void) sm_strlcpy(buf, "mqueue, P=/var/spool/mqueue", sizeof(buf));
475	makequeue(buf, false);
476}
477/*
478**  SETUPMAILERS -- initialize default mailers
479*/
480
481static void
482setupmailers()
483{
484	char buf[100];
485
486	(void) sm_strlcpy(buf, "prog, P=/bin/sh, F=lsouDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u",
487			sizeof(buf));
488	makemailer(buf);
489
490	(void) sm_strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE \201u",
491			sizeof(buf));
492	makemailer(buf);
493
494	(void) sm_strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u",
495			sizeof(buf));
496	makemailer(buf);
497	initerrmailers();
498}
499/*
500**  SETUPMAPS -- set up map classes
501*/
502
503#define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \
504	{ \
505		extern bool parse __P((MAP *, char *)); \
506		extern bool open __P((MAP *, int)); \
507		extern void close __P((MAP *)); \
508		extern char *lookup __P((MAP *, char *, char **, int *)); \
509		extern void store __P((MAP *, char *, char *)); \
510		s = stab(name, ST_MAPCLASS, ST_ENTER); \
511		s->s_mapclass.map_cname = name; \
512		s->s_mapclass.map_ext = ext; \
513		s->s_mapclass.map_cflags = flags; \
514		s->s_mapclass.map_parse = parse; \
515		s->s_mapclass.map_open = open; \
516		s->s_mapclass.map_close = close; \
517		s->s_mapclass.map_lookup = lookup; \
518		s->s_mapclass.map_store = store; \
519	}
520
521static void
522setupmaps()
523{
524	register STAB *s;
525
526#if NEWDB
527# if DB_VERSION_MAJOR > 1
528	int major_v, minor_v, patch_v;
529
530	(void) db_version(&major_v, &minor_v, &patch_v);
531	if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR)
532	{
533		errno = 0;
534		syserr("Berkeley DB version mismatch: compiled against %d.%d.%d, run-time linked against %d.%d.%d",
535		  DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
536		  major_v, minor_v, patch_v);
537	}
538# endif /* DB_VERSION_MAJOR > 1 */
539
540	MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
541		map_parseargs, hash_map_open, db_map_close,
542		db_map_lookup, db_map_store);
543
544	MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
545		map_parseargs, bt_map_open, db_map_close,
546		db_map_lookup, db_map_store);
547#endif /* NEWDB */
548
549#if NDBM
550	MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE,
551		map_parseargs, ndbm_map_open, ndbm_map_close,
552		ndbm_map_lookup, ndbm_map_store);
553#endif
554
555#if CDB
556	MAPDEF("cdb", CDBEXT, MCF_ALIASOK|MCF_REBUILDABLE,
557		map_parseargs, cdb_map_open, cdb_map_close,
558		cdb_map_lookup, cdb_map_store);
559#endif
560
561#if NIS
562	MAPDEF("nis", NULL, MCF_ALIASOK,
563		map_parseargs, nis_map_open, null_map_close,
564		nis_map_lookup, null_map_store);
565#endif
566
567#if NISPLUS
568	MAPDEF("nisplus", NULL, MCF_ALIASOK,
569		map_parseargs, nisplus_map_open, null_map_close,
570		nisplus_map_lookup, null_map_store);
571#endif
572
573#if LDAPMAP
574	MAPDEF("ldap", NULL, MCF_ALIASOK|MCF_NOTPERSIST,
575		ldapmap_parseargs, ldapmap_open, ldapmap_close,
576		ldapmap_lookup, null_map_store);
577#endif
578
579#if PH_MAP
580	MAPDEF("ph", NULL, MCF_NOTPERSIST,
581		ph_map_parseargs, ph_map_open, ph_map_close,
582		ph_map_lookup, null_map_store);
583#endif
584
585#if MAP_NSD
586	/* IRIX 6.5 nsd support */
587	MAPDEF("nsd", NULL, MCF_ALIASOK,
588	       map_parseargs, null_map_open, null_map_close,
589	       nsd_map_lookup, null_map_store);
590#endif
591
592#if HESIOD
593	MAPDEF("hesiod", NULL, MCF_ALIASOK,
594		map_parseargs, hes_map_open, hes_map_close,
595		hes_map_lookup, null_map_store);
596#endif
597
598#if NETINFO
599	MAPDEF("netinfo", NULL, MCF_ALIASOK,
600		map_parseargs, ni_map_open, null_map_close,
601		ni_map_lookup, null_map_store);
602#endif
603
604#if 0
605	MAPDEF("dns", NULL, 0,
606		dns_map_init, null_map_open, null_map_close,
607		dns_map_lookup, null_map_store);
608#endif /* 0 */
609
610#if NAMED_BIND
611# if DNSMAP
612#  if _FFR_DNSMAP_ALIASABLE
613	MAPDEF("dns", NULL, MCF_ALIASOK,
614	       dns_map_parseargs, dns_map_open, null_map_close,
615	       dns_map_lookup, null_map_store);
616#  else /* _FFR_DNSMAP_ALIASABLE */
617	MAPDEF("dns", NULL, 0,
618	       dns_map_parseargs, dns_map_open, null_map_close,
619	       dns_map_lookup, null_map_store);
620#  endif /* _FFR_DNSMAP_ALIASABLE */
621# endif /* DNSMAP */
622#endif /* NAMED_BIND */
623
624#if NAMED_BIND
625	/* best MX DNS lookup */
626	MAPDEF("bestmx", NULL, MCF_OPTFILE,
627		map_parseargs, null_map_open, null_map_close,
628		bestmx_map_lookup, null_map_store);
629#endif
630
631	MAPDEF("host", NULL, 0,
632		host_map_init, null_map_open, null_map_close,
633		host_map_lookup, null_map_store);
634
635	MAPDEF("text", NULL, MCF_ALIASOK,
636		map_parseargs, text_map_open, null_map_close,
637		text_map_lookup, null_map_store);
638
639	MAPDEF("stab", NULL, MCF_ALIASOK,
640		map_parseargs, stab_map_open, null_map_close,
641		stab_map_lookup, stab_map_store);
642
643	MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_REBUILDABLE,
644		map_parseargs, impl_map_open, impl_map_close,
645		impl_map_lookup, impl_map_store);
646
647	/* access to system passwd file */
648	MAPDEF("user", NULL, MCF_OPTFILE,
649		map_parseargs, user_map_open, null_map_close,
650		user_map_lookup, null_map_store);
651
652	/* dequote map */
653	MAPDEF("dequote", NULL, 0,
654		dequote_init, null_map_open, null_map_close,
655		dequote_map, null_map_store);
656
657#if MAP_REGEX
658	MAPDEF("regex", NULL, 0,
659		regex_map_init, null_map_open, null_map_close,
660		regex_map_lookup, null_map_store);
661#endif
662
663#if USERDB
664	/* user database */
665	MAPDEF("userdb", ".db", 0,
666		map_parseargs, null_map_open, null_map_close,
667		udb_map_lookup, null_map_store);
668#endif
669
670	/* arbitrary programs */
671	MAPDEF("program", NULL, MCF_ALIASOK,
672		map_parseargs, null_map_open, null_map_close,
673		prog_map_lookup, null_map_store);
674
675	/* sequenced maps */
676	MAPDEF("sequence", NULL, MCF_ALIASOK,
677		seq_map_parse, null_map_open, null_map_close,
678		seq_map_lookup, seq_map_store);
679
680	/* switched interface to sequenced maps */
681	MAPDEF("switch", NULL, MCF_ALIASOK,
682		map_parseargs, switch_map_open, null_map_close,
683		seq_map_lookup, seq_map_store);
684
685	/* null map lookup -- really for internal use only */
686	MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE,
687		map_parseargs, null_map_open, null_map_close,
688		null_map_lookup, null_map_store);
689
690	/* syslog map -- logs information to syslog */
691	MAPDEF("syslog", NULL, 0,
692		syslog_map_parseargs, null_map_open, null_map_close,
693		syslog_map_lookup, null_map_store);
694
695	/* macro storage map -- rulesets can set macros */
696	MAPDEF("macro", NULL, 0,
697		dequote_init, null_map_open, null_map_close,
698		macro_map_lookup, null_map_store);
699
700	/* arithmetic map -- add/subtract/compare */
701	MAPDEF("arith", NULL, 0,
702		dequote_init, null_map_open, null_map_close,
703		arith_map_lookup, null_map_store);
704
705	/* "arpa" map -- IP -> arpa */
706	MAPDEF("arpa", NULL, 0,
707		dequote_init, null_map_open, null_map_close,
708		arpa_map_lookup, null_map_store);
709
710#if SOCKETMAP
711	/* arbitrary daemons */
712	MAPDEF("socket", NULL, MCF_ALIASOK,
713		map_parseargs, socket_map_open, socket_map_close,
714		socket_map_lookup, null_map_store);
715#endif
716
717#if _FFR_DPRINTF_MAP
718	/* dprintf map -- logs information to syslog */
719	MAPDEF("dprintf", NULL, 0,
720		dprintf_map_parseargs, null_map_open, null_map_close,
721		dprintf_map_lookup, null_map_store);
722#endif
723
724#if _FFR_SETDEBUG_MAP
725	/* setdebug map -- set debug levels */
726	MAPDEF("setdebug", NULL, 0,
727		dequote_init, null_map_open, null_map_close,
728		setdebug_map_lookup, null_map_store);
729#endif
730
731#if _FFR_SETOPT_MAP
732	/* setopt map -- set option */
733	MAPDEF("setopt", NULL, 0,
734		dequote_init, null_map_open, null_map_close,
735		setopt_map_lookup, null_map_store);
736#endif
737
738	if (tTd(38, 2))
739	{
740		/* bogus map -- always return tempfail */
741		MAPDEF("bogus",	NULL, MCF_ALIASOK|MCF_OPTFILE,
742		       map_parseargs, null_map_open, null_map_close,
743		       bogus_map_lookup, null_map_store);
744	}
745}
746
747#undef MAPDEF
748/*
749**  INITHOSTMAPS -- initial host-dependent maps
750**
751**	This should act as an interface to any local service switch
752**	provided by the host operating system.
753**
754**	Parameters:
755**		none
756**
757**	Returns:
758**		none
759**
760**	Side Effects:
761**		Should define maps "host" and "users" as necessary
762**		for this OS.  If they are not defined, they will get
763**		a default value later.  It should check to make sure
764**		they are not defined first, since it's possible that
765**		the config file has provided an override.
766*/
767
768void
769inithostmaps()
770{
771	register int i;
772	int nmaps;
773	char *maptype[MAXMAPSTACK];
774	short mapreturn[MAXMAPACTIONS];
775	char buf[MAXLINE];
776
777	/*
778	**  Make sure we have a host map.
779	*/
780
781	if (stab("host", ST_MAP, ST_FIND) == NULL)
782	{
783		/* user didn't initialize: set up host map */
784		(void) sm_strlcpy(buf, "host host", sizeof(buf));
785#if NAMED_BIND
786		if (ConfigLevel >= 2)
787			(void) sm_strlcat(buf, " -a. -D", sizeof(buf));
788#endif
789		(void) makemapentry(buf);
790	}
791
792	/*
793	**  Set up default aliases maps
794	*/
795
796	nmaps = switch_map_find("aliases", maptype, mapreturn);
797	for (i = 0; i < nmaps; i++)
798	{
799		if (strcmp(maptype[i], "files") == 0 &&
800		    stab("aliases.files", ST_MAP, ST_FIND) == NULL)
801		{
802			(void) sm_strlcpy(buf, "aliases.files null",
803					  sizeof(buf));
804			(void) makemapentry(buf);
805		}
806#if CDB
807		else if (strcmp(maptype[i], "cdb") == 0 &&
808			 stab("aliases.cdb", ST_MAP, ST_FIND) == NULL)
809		{
810			(void) sm_strlcpy(buf, "aliases.cdb null", sizeof(buf));
811			(void) makemapentry(buf);
812		}
813#endif /* CDB */
814#if NISPLUS
815		else if (strcmp(maptype[i], "nisplus") == 0 &&
816			 stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL)
817		{
818			(void) sm_strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir",
819				sizeof(buf));
820			(void) makemapentry(buf);
821		}
822#endif /* NISPLUS */
823#if NIS
824		else if (strcmp(maptype[i], "nis") == 0 &&
825			 stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
826		{
827			(void) sm_strlcpy(buf, "aliases.nis nis mail.aliases",
828				sizeof(buf));
829			(void) makemapentry(buf);
830		}
831#endif /* NIS */
832#if NETINFO
833		else if (strcmp(maptype[i], "netinfo") == 0 &&
834			 stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
835		{
836			(void) sm_strlcpy(buf, "aliases.netinfo netinfo -z, /aliases",
837				sizeof(buf));
838			(void) makemapentry(buf);
839		}
840#endif /* NETINFO */
841#if HESIOD
842		else if (strcmp(maptype[i], "hesiod") == 0 &&
843			 stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL)
844		{
845			(void) sm_strlcpy(buf, "aliases.hesiod hesiod aliases",
846				sizeof(buf));
847			(void) makemapentry(buf);
848		}
849#endif /* HESIOD */
850#if LDAPMAP && defined(SUN_EXTENSIONS) && \
851    defined(SUN_SIMPLIFIED_LDAP) && HASLDAPGETALIASBYNAME
852		else if (strcmp(maptype[i], "ldap") == 0 &&
853		    stab("aliases.ldap", ST_MAP, ST_FIND) == NULL)
854		{
855			(void) sm_strlcpy(buf, "aliases.ldap ldap -b . -h localhost -k mail=%0 -v mailgroup",
856				sizeof buf);
857			(void) makemapentry(buf);
858		}
859#endif /* LDAPMAP && defined(SUN_EXTENSIONS) && ... */
860	}
861	if (stab("aliases", ST_MAP, ST_FIND) == NULL)
862	{
863		(void) sm_strlcpy(buf, "aliases switch aliases", sizeof(buf));
864		(void) makemapentry(buf);
865	}
866}
867
868/*
869**  SWITCH_MAP_FIND -- find the list of types associated with a map
870**
871**	This is the system-dependent interface to the service switch.
872**
873**	Parameters:
874**		service -- the name of the service of interest.
875**		maptype -- an out-array of strings containing the types
876**			of access to use for this service.  There can
877**			be at most MAXMAPSTACK types for a single service.
878**		mapreturn -- an out-array of return information bitmaps
879**			for the map.
880**
881**	Returns:
882**		The number of map types filled in, or -1 for failure.
883**
884**	Side effects:
885**		Preserves errno so nothing in the routine clobbers it.
886*/
887
888#if defined(SOLARIS) || (defined(sony_news) && defined(__svr4))
889# define _USE_SUN_NSSWITCH_
890#endif
891
892#if _FFR_HPUX_NSSWITCH
893# ifdef __hpux
894#  define _USE_SUN_NSSWITCH_
895# endif
896#endif /* _FFR_HPUX_NSSWITCH */
897
898#ifdef _USE_SUN_NSSWITCH_
899# include <nsswitch.h>
900#endif
901
902#if defined(ultrix) || (defined(__osf__) && defined(__alpha))
903# define _USE_DEC_SVC_CONF_
904#endif
905
906#ifdef _USE_DEC_SVC_CONF_
907# include <sys/svcinfo.h>
908#endif
909
910int
911switch_map_find(service, maptype, mapreturn)
912	char *service;
913	char *maptype[MAXMAPSTACK];
914	short mapreturn[MAXMAPACTIONS];
915{
916	int svcno = 0;
917	int save_errno = errno;
918
919#ifdef _USE_SUN_NSSWITCH_
920	struct __nsw_switchconfig *nsw_conf;
921	enum __nsw_parse_err pserr;
922	struct __nsw_lookup *lk;
923	static struct __nsw_lookup lkp0 =
924		{ "files", {1, 0, 0, 0}, NULL, NULL };
925	static struct __nsw_switchconfig lkp_default =
926		{ 0, "sendmail", 3, &lkp0 };
927
928	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
929		mapreturn[svcno] = 0;
930
931	if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL)
932		lk = lkp_default.lookups;
933	else
934		lk = nsw_conf->lookups;
935	svcno = 0;
936	while (lk != NULL && svcno < MAXMAPSTACK)
937	{
938		maptype[svcno] = lk->service_name;
939		if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN)
940			mapreturn[MA_NOTFOUND] |= 1 << svcno;
941		if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN)
942			mapreturn[MA_TRYAGAIN] |= 1 << svcno;
943		if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN)
944			mapreturn[MA_TRYAGAIN] |= 1 << svcno;
945		svcno++;
946		lk = lk->next;
947	}
948	errno = save_errno;
949	return svcno;
950#endif /* _USE_SUN_NSSWITCH_ */
951
952#ifdef _USE_DEC_SVC_CONF_
953	struct svcinfo *svcinfo;
954	int svc;
955
956	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
957		mapreturn[svcno] = 0;
958
959	svcinfo = getsvc();
960	if (svcinfo == NULL)
961		goto punt;
962	if (strcmp(service, "hosts") == 0)
963		svc = SVC_HOSTS;
964	else if (strcmp(service, "aliases") == 0)
965		svc = SVC_ALIASES;
966	else if (strcmp(service, "passwd") == 0)
967		svc = SVC_PASSWD;
968	else
969	{
970		errno = save_errno;
971		return -1;
972	}
973	for (svcno = 0; svcno < SVC_PATHSIZE && svcno < MAXMAPSTACK; svcno++)
974	{
975		switch (svcinfo->svcpath[svc][svcno])
976		{
977		  case SVC_LOCAL:
978			maptype[svcno] = "files";
979			break;
980
981		  case SVC_YP:
982			maptype[svcno] = "nis";
983			break;
984
985		  case SVC_BIND:
986			maptype[svcno] = "dns";
987			break;
988
989# ifdef SVC_HESIOD
990		  case SVC_HESIOD:
991			maptype[svcno] = "hesiod";
992			break;
993# endif
994
995		  case SVC_LAST:
996			errno = save_errno;
997			return svcno;
998		}
999	}
1000	errno = save_errno;
1001	return svcno;
1002#endif /* _USE_DEC_SVC_CONF_ */
1003
1004#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
1005	/*
1006	**  Fall-back mechanism.
1007	*/
1008
1009	STAB *st;
1010	static time_t servicecachetime;	/* time service switch was cached */
1011	time_t now = curtime();
1012
1013	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
1014		mapreturn[svcno] = 0;
1015
1016	if ((now - servicecachetime) > (time_t) ServiceCacheMaxAge)
1017	{
1018		/* (re)read service switch */
1019		register SM_FILE_T *fp;
1020		long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK;
1021
1022		if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR,
1023			    DontBlameSendmail))
1024			sff |= SFF_NOWLINK;
1025
1026		if (ConfigFileRead)
1027			servicecachetime = now;
1028		fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff);
1029		if (fp != NULL)
1030		{
1031			char buf[MAXLINE];
1032
1033			while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf,
1034					   sizeof(buf)) >= 0)
1035			{
1036				register char *p;
1037
1038				p = strpbrk(buf, "#\n");
1039				if (p != NULL)
1040					*p = '\0';
1041#ifndef SM_NSSWITCH_DELIMS
1042# define SM_NSSWITCH_DELIMS	" \t"
1043#endif
1044				p = strpbrk(buf, SM_NSSWITCH_DELIMS);
1045				if (p != NULL)
1046					*p++ = '\0';
1047				if (buf[0] == '\0')
1048					continue;
1049				if (p == NULL)
1050				{
1051					sm_syslog(LOG_ERR, NOQID,
1052						  "Bad line on %.100s: %.100s",
1053						  ServiceSwitchFile,
1054						  buf);
1055					continue;
1056				}
1057				while (SM_ISSPACE(*p))
1058					p++;
1059				if (*p == '\0')
1060					continue;
1061
1062				/*
1063				**  Find/allocate space for this service entry.
1064				**	Space for all of the service strings
1065				**	are allocated at once.  This means
1066				**	that we only have to free the first
1067				**	one to free all of them.
1068				*/
1069
1070				st = stab(buf, ST_SERVICE, ST_ENTER);
1071				if (st->s_service[0] != NULL)
1072					sm_free((void *) st->s_service[0]); /* XXX */
1073				p = newstr(p);
1074				for (svcno = 0; svcno < MAXMAPSTACK; )
1075				{
1076					if (*p == '\0')
1077						break;
1078					st->s_service[svcno++] = p;
1079					p = strpbrk(p, " \t");
1080					if (p == NULL)
1081						break;
1082					*p++ = '\0';
1083					while (SM_ISSPACE(*p))
1084						p++;
1085				}
1086				if (svcno < MAXMAPSTACK)
1087					st->s_service[svcno] = NULL;
1088			}
1089			(void) sm_io_close(fp, SM_TIME_DEFAULT);
1090		}
1091	}
1092
1093	/* look up entry in cache */
1094	st = stab(service, ST_SERVICE, ST_FIND);
1095	if (st != NULL && st->s_service[0] != NULL)
1096	{
1097		/* extract data */
1098		svcno = 0;
1099		while (svcno < MAXMAPSTACK)
1100		{
1101			maptype[svcno] = st->s_service[svcno];
1102			if (maptype[svcno++] == NULL)
1103				break;
1104		}
1105		errno = save_errno;
1106		return --svcno;
1107	}
1108#endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */
1109
1110#if !defined(_USE_SUN_NSSWITCH_)
1111	/* if the service file doesn't work, use an absolute fallback */
1112# ifdef _USE_DEC_SVC_CONF_
1113  punt:
1114# endif
1115	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
1116		mapreturn[svcno] = 0;
1117	svcno = 0;
1118	if (strcmp(service, "aliases") == 0)
1119	{
1120		SM_ASSERT(svcno < MAXMAPSTACK);
1121		maptype[svcno++] = "files";
1122# if CDB
1123		SM_ASSERT(svcno < MAXMAPSTACK);
1124		maptype[svcno++] = "cdb";
1125# endif
1126# if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO)
1127		SM_ASSERT(svcno < MAXMAPSTACK);
1128		maptype[svcno++] = "netinfo";
1129# endif
1130# ifdef AUTO_NIS_ALIASES
1131#  if NISPLUS
1132		SM_ASSERT(svcno < MAXMAPSTACK);
1133		maptype[svcno++] = "nisplus";
1134#  endif
1135#  if NIS
1136		SM_ASSERT(svcno < MAXMAPSTACK);
1137		maptype[svcno++] = "nis";
1138#  endif
1139# endif /* AUTO_NIS_ALIASES */
1140		errno = save_errno;
1141		return svcno;
1142	}
1143	if (strcmp(service, "hosts") == 0)
1144	{
1145# if NAMED_BIND
1146		SM_ASSERT(svcno < MAXMAPSTACK);
1147		maptype[svcno++] = "dns";
1148# else /* NAMED_BIND */
1149#  if defined(sun) && !defined(BSD)
1150		/* SunOS */
1151		SM_ASSERT(svcno < MAXMAPSTACK);
1152		maptype[svcno++] = "nis";
1153#  endif /* defined(sun) && !defined(BSD) */
1154# endif /* NAMED_BIND */
1155# if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO)
1156		SM_ASSERT(svcno < MAXMAPSTACK);
1157		maptype[svcno++] = "netinfo";
1158# endif
1159		SM_ASSERT(svcno < MAXMAPSTACK);
1160		maptype[svcno++] = "files";
1161		errno = save_errno;
1162		return svcno;
1163	}
1164	errno = save_errno;
1165	return -1;
1166#endif /* !defined(_USE_SUN_NSSWITCH_) */
1167}
1168/*
1169**  USERNAME -- return the user id of the logged in user.
1170**
1171**	Parameters:
1172**		none.
1173**
1174**	Returns:
1175**		The login name of the logged in user.
1176**
1177**	Side Effects:
1178**		none.
1179**
1180**	Notes:
1181**		The return value is statically allocated.
1182*/
1183
1184char *
1185username()
1186{
1187	static char *myname = NULL;
1188	extern char *getlogin();
1189	register struct passwd *pw;
1190
1191	/* cache the result */
1192	if (myname == NULL)
1193	{
1194		myname = getlogin();
1195		if (myname == NULL || myname[0] == '\0')
1196		{
1197			pw = sm_getpwuid(RealUid);
1198			if (pw != NULL)
1199				myname = pw->pw_name;
1200		}
1201		else
1202		{
1203			uid_t uid = RealUid;
1204
1205			if ((pw = sm_getpwnam(myname)) == NULL ||
1206			      (uid != 0 && uid != pw->pw_uid))
1207			{
1208				pw = sm_getpwuid(uid);
1209				if (pw != NULL)
1210					myname = pw->pw_name;
1211			}
1212		}
1213		if (myname == NULL || myname[0] == '\0')
1214		{
1215			syserr("554 5.3.0 Who are you?");
1216			myname = "postmaster";
1217		}
1218		else if (strpbrk(myname, ",;:/|\"\\") != NULL)
1219			myname = addquotes(myname, NULL);
1220		else
1221			myname = sm_pstrdup_x(myname);
1222	}
1223	return myname;
1224}
1225/*
1226**  TTYPATH -- Get the path of the user's tty
1227**
1228**	Returns the pathname of the user's tty.  Returns NULL if
1229**	the user is not logged in or if s/he has write permission
1230**	denied.
1231**
1232**	Parameters:
1233**		none
1234**
1235**	Returns:
1236**		pathname of the user's tty.
1237**		NULL if not logged in or write permission denied.
1238**
1239**	Side Effects:
1240**		none.
1241**
1242**	WARNING:
1243**		Return value is in a local buffer.
1244**
1245**	Called By:
1246**		savemail
1247*/
1248
1249char *
1250ttypath()
1251{
1252	struct stat stbuf;
1253	register char *pathn;
1254	extern char *ttyname();
1255	extern char *getlogin();
1256
1257	/* compute the pathname of the controlling tty */
1258	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
1259	    (pathn = ttyname(0)) == NULL)
1260	{
1261		errno = 0;
1262		return NULL;
1263	}
1264
1265	/* see if we have write permission */
1266	if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode))
1267	{
1268		errno = 0;
1269		return NULL;
1270	}
1271
1272	/* see if the user is logged in */
1273	if (getlogin() == NULL)
1274		return NULL;
1275
1276	/* looks good */
1277	return pathn;
1278}
1279/*
1280**  CHECKCOMPAT -- check for From and To person compatible.
1281**
1282**	This routine can be supplied on a per-installation basis
1283**	to determine whether a person is allowed to send a message.
1284**	This allows restriction of certain types of internet
1285**	forwarding or registration of users.
1286**
1287**	If the hosts are found to be incompatible, an error
1288**	message should be given using "usrerr" and an EX_ code
1289**	should be returned.  You can also set to->q_status to
1290**	a DSN-style status code.
1291**
1292**	EF_NO_BODY_RETN can be set in e->e_flags to suppress the
1293**	body during the return-to-sender function; this should be done
1294**	on huge messages.  This bit may already be set by the ESMTP
1295**	protocol.
1296**
1297**	Parameters:
1298**		to -- the person being sent to.
1299**
1300**	Returns:
1301**		an exit status
1302**
1303**	Side Effects:
1304**		none (unless you include the usrerr stuff)
1305*/
1306
1307int
1308checkcompat(to, e)
1309	register ADDRESS *to;
1310	register ENVELOPE *e;
1311{
1312	if (tTd(49, 1))
1313		sm_dprintf("checkcompat(to=%s, from=%s)\n",
1314			to->q_paddr, e->e_from.q_paddr);
1315
1316#ifdef EXAMPLE_CODE
1317	/* this code is intended as an example only */
1318	register STAB *s;
1319
1320	s = stab("arpa", ST_MAILER, ST_FIND);
1321	if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 &&
1322	    to->q_mailer == s->s_mailer)
1323	{
1324		usrerr("553 No ARPA mail through this machine: see your system administration");
1325		/* e->e_flags |= EF_NO_BODY_RETN; to suppress body on return */
1326		to->q_status = "5.7.1";
1327		return EX_UNAVAILABLE;
1328	}
1329#endif /* EXAMPLE_CODE */
1330	return EX_OK;
1331}
1332
1333#ifdef SUN_EXTENSIONS
1334static void
1335init_md_sun()
1336{
1337	struct stat sbuf;
1338
1339	/* Check for large file descriptor */
1340	if (fstat(fileno(stdin), &sbuf) < 0)
1341	{
1342		if (errno == EOVERFLOW)
1343		{
1344			perror("stdin");
1345			exit(EX_NOINPUT);
1346		}
1347	}
1348}
1349#endif /* SUN_EXTENSIONS */
1350
1351/*
1352**  INIT_MD -- do machine dependent initializations
1353**
1354**	Systems that have global modes that should be set should do
1355**	them here rather than in main.
1356*/
1357
1358#ifdef _AUX_SOURCE
1359# include <compat.h>
1360#endif
1361
1362#if SHARE_V1
1363# include <shares.h>
1364#endif
1365
1366void
1367init_md(argc, argv)
1368	int argc;
1369	char **argv;
1370{
1371#ifdef _AUX_SOURCE
1372	setcompat(getcompat() | COMPAT_BSDPROT);
1373#endif
1374
1375#ifdef SUN_EXTENSIONS
1376	init_md_sun();
1377#endif
1378
1379#if _CONVEX_SOURCE
1380	/* keep gethostby*() from stripping the local domain name */
1381	set_domain_trim_off();
1382#endif
1383#if defined(__QNX__) && !defined(__QNXNTO__)
1384	/*
1385	**  Due to QNX's network distributed nature, you can target a tcpip
1386	**  stack on a different node in the qnx network; this patch lets
1387	**  this feature work.  The __sock_locate() must be done before the
1388	**  environment is clear.
1389	*/
1390	__sock_locate();
1391#endif /* __QNX__ */
1392#if SECUREWARE || defined(_SCO_unix_)
1393	set_auth_parameters(argc, argv);
1394
1395# ifdef _SCO_unix_
1396	/*
1397	**  This is required for highest security levels (the kernel
1398	**  won't let it call set*uid() or run setuid binaries without
1399	**  it).  It may be necessary on other SECUREWARE systems.
1400	*/
1401
1402	if (getluid() == -1)
1403		setluid(0);
1404# endif /* _SCO_unix_ */
1405#endif /* SECUREWARE || defined(_SCO_unix_) */
1406
1407
1408#ifdef VENDOR_DEFAULT
1409	VendorCode = VENDOR_DEFAULT;
1410#else
1411	VendorCode = VENDOR_BERKELEY;
1412#endif
1413}
1414/*
1415**  INIT_VENDOR_MACROS -- vendor-dependent macro initializations
1416**
1417**	Called once, on startup.
1418**
1419**	Parameters:
1420**		e -- the global envelope.
1421**
1422**	Returns:
1423**		none.
1424**
1425**	Side Effects:
1426**		vendor-dependent.
1427*/
1428
1429void
1430init_vendor_macros(e)
1431	register ENVELOPE *e;
1432{
1433}
1434/*
1435**  GETLA -- get the current load average
1436**
1437**	This code stolen from la.c.
1438**
1439**	Parameters:
1440**		none.
1441**
1442**	Returns:
1443**		The current load average as an integer.
1444**
1445**	Side Effects:
1446**		none.
1447*/
1448
1449/* try to guess what style of load average we have */
1450#define LA_ZERO		1	/* always return load average as zero */
1451#define LA_INT		2	/* read kmem for avenrun; interpret as long */
1452#define LA_FLOAT	3	/* read kmem for avenrun; interpret as float */
1453#define LA_SUBR		4	/* call getloadavg */
1454#define LA_MACH		5	/* MACH load averages (as on NeXT boxes) */
1455#define LA_SHORT	6	/* read kmem for avenrun; interpret as short */
1456#define LA_PROCSTR	7	/* read string ("1.17") from /proc/loadavg */
1457#define LA_READKSYM	8	/* SVR4: use MIOC_READKSYM ioctl call */
1458#define LA_DGUX		9	/* special DGUX implementation */
1459#define LA_HPUX		10	/* special HPUX implementation */
1460#define LA_IRIX6	11	/* special IRIX 6.2 implementation */
1461#define LA_KSTAT	12	/* special Solaris kstat(3k) implementation */
1462#define LA_DEVSHORT	13	/* read short from a device */
1463#define LA_ALPHAOSF	14	/* Digital UNIX (OSF/1 on Alpha) table() call */
1464#define LA_PSET		15	/* Solaris per-processor-set load average */
1465#define LA_LONGLONG	17 /* read kmem for avenrun; interpret as long long */
1466
1467/* do guesses based on general OS type */
1468#ifndef LA_TYPE
1469# define LA_TYPE	LA_ZERO
1470#endif
1471
1472#ifndef FSHIFT
1473# if defined(unixpc)
1474#  define FSHIFT	5
1475# endif
1476
1477# if defined(__alpha) || defined(IRIX)
1478#  define FSHIFT	10
1479# endif
1480
1481#endif /* ! FSHIFT */
1482
1483#ifndef FSHIFT
1484# define FSHIFT		8
1485#endif
1486
1487#ifndef FSCALE
1488# define FSCALE		(1 << FSHIFT)
1489#endif
1490
1491#ifndef LA_AVENRUN
1492# ifdef SYSTEM5
1493#  define LA_AVENRUN	"avenrun"
1494# else
1495#  define LA_AVENRUN	"_avenrun"
1496# endif
1497#endif /* ! LA_AVENRUN */
1498
1499/* _PATH_KMEM should be defined in <paths.h> */
1500#ifndef _PATH_KMEM
1501# define _PATH_KMEM	"/dev/kmem"
1502#endif
1503
1504#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG)
1505
1506# include <nlist.h>
1507
1508/* _PATH_UNIX should be defined in <paths.h> */
1509# ifndef _PATH_UNIX
1510#  if defined(SYSTEM5)
1511#   define _PATH_UNIX	"/unix"
1512#  else
1513#   define _PATH_UNIX	"/vmunix"
1514#  endif
1515# endif /* ! _PATH_UNIX */
1516
1517# ifdef _AUX_SOURCE
1518struct nlist	Nl[2];
1519# else /* _AUX_SOURCE */
1520struct nlist	Nl[] =
1521{
1522	{ LA_AVENRUN },
1523	{ 0 },
1524};
1525# endif /* _AUX_SOURCE */
1526# define X_AVENRUN	0
1527
1528int
1529getla()
1530{
1531	int j;
1532	static int kmem = -1;
1533# if LA_TYPE == LA_INT
1534	long avenrun[3];
1535# else /* LA_TYPE == LA_INT */
1536#  if LA_TYPE == LA_SHORT
1537	short avenrun[3];
1538#  else
1539#   if LA_TYPE == LA_LONGLONG
1540	long long avenrun[3];
1541#   else
1542	double avenrun[3];
1543#   endif
1544#  endif /* LA_TYPE == LA_SHORT */
1545# endif /* LA_TYPE == LA_INT */
1546	extern off_t lseek();
1547
1548	if (kmem < 0)
1549	{
1550# ifdef _AUX_SOURCE
1551		(void) sm_strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN,
1552			       sizeof(Nl[X_AVENRUN].n_name));
1553		Nl[1].n_name[0] = '\0';
1554# endif /* _AUX_SOURCE */
1555
1556# if defined(_AIX3) || defined(_AIX4)
1557		if (knlist(Nl, 1, sizeof(Nl[0])) < 0)
1558# else
1559		if (nlist(_PATH_UNIX, Nl) < 0)
1560# endif
1561		{
1562			if (tTd(3, 1))
1563				sm_dprintf("getla: nlist(%s): %s\n", _PATH_UNIX,
1564					   sm_errstring(errno));
1565			return -1;
1566		}
1567		if (Nl[X_AVENRUN].n_value == 0)
1568		{
1569			if (tTd(3, 1))
1570				sm_dprintf("getla: nlist(%s, %s) ==> 0\n",
1571					_PATH_UNIX, LA_AVENRUN);
1572			return -1;
1573		}
1574# ifdef NAMELISTMASK
1575		Nl[X_AVENRUN].n_value &= NAMELISTMASK;
1576# endif
1577
1578		kmem = open(_PATH_KMEM, 0, 0);
1579		if (kmem < 0)
1580		{
1581			if (tTd(3, 1))
1582				sm_dprintf("getla: open(/dev/kmem): %s\n",
1583					   sm_errstring(errno));
1584			return -1;
1585		}
1586		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
1587		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
1588		{
1589			if (tTd(3, 1))
1590				sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
1591					   sm_errstring(errno));
1592			(void) close(kmem);
1593			kmem = -1;
1594			return -1;
1595		}
1596	}
1597	if (tTd(3, 20))
1598		sm_dprintf("getla: symbol address = %#lx\n",
1599			(unsigned long) Nl[X_AVENRUN].n_value);
1600	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 ||
1601	    read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun))
1602	{
1603		/* thank you Ian */
1604		if (tTd(3, 1))
1605			sm_dprintf("getla: lseek or read: %s\n",
1606				   sm_errstring(errno));
1607		return -1;
1608	}
1609# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG)
1610	if (tTd(3, 5))
1611	{
1612#  if LA_TYPE == LA_SHORT
1613		sm_dprintf("getla: avenrun = %d", avenrun[0]);
1614		if (tTd(3, 15))
1615			sm_dprintf(", %d, %d", avenrun[1], avenrun[2]);
1616#  else /* LA_TYPE == LA_SHORT */
1617#   if LA_TYPE == LA_LONGLONG
1618		sm_dprintf("getla: avenrun = %lld", avenrun[0]);
1619		if (tTd(3, 15))
1620			sm_dprintf(", %lld, %lld", avenrun[1], avenrun[2]);
1621#   else /* LA_TYPE == LA_LONGLONG */
1622		sm_dprintf("getla: avenrun = %ld", avenrun[0]);
1623		if (tTd(3, 15))
1624			sm_dprintf(", %ld, %ld", avenrun[1], avenrun[2]);
1625#   endif /* LA_TYPE == LA_LONGLONG */
1626#  endif /* LA_TYPE == LA_SHORT */
1627		sm_dprintf("\n");
1628	}
1629	if (tTd(3, 1))
1630		sm_dprintf("getla: %d\n",
1631			(int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1632	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1633# else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
1634	if (tTd(3, 5))
1635	{
1636		sm_dprintf("getla: avenrun = %g", avenrun[0]);
1637		if (tTd(3, 15))
1638			sm_dprintf(", %g, %g", avenrun[1], avenrun[2]);
1639		sm_dprintf("\n");
1640	}
1641	if (tTd(3, 1))
1642		sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
1643	return ((int) (avenrun[0] + 0.5));
1644# endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
1645}
1646
1647#endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
1648
1649#if LA_TYPE == LA_READKSYM
1650
1651# include <sys/ksym.h>
1652
1653int
1654getla()
1655{
1656	int j;
1657	static int kmem = -1;
1658	long avenrun[3];
1659	struct mioc_rksym mirk;
1660
1661	if (kmem < 0)
1662	{
1663		kmem = open("/dev/kmem", 0, 0);
1664		if (kmem < 0)
1665		{
1666			if (tTd(3, 1))
1667				sm_dprintf("getla: open(/dev/kmem): %s\n",
1668					   sm_errstring(errno));
1669			return -1;
1670		}
1671		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
1672		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
1673		{
1674			if (tTd(3, 1))
1675				sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
1676					   sm_errstring(errno));
1677			(void) close(kmem);
1678			kmem = -1;
1679			return -1;
1680		}
1681	}
1682	mirk.mirk_symname = LA_AVENRUN;
1683	mirk.mirk_buf = avenrun;
1684	mirk.mirk_buflen = sizeof(avenrun);
1685	if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0)
1686	{
1687		if (tTd(3, 1))
1688			sm_dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n",
1689				   sm_errstring(errno));
1690		return -1;
1691	}
1692	if (tTd(3, 5))
1693	{
1694		sm_dprintf("getla: avenrun = %d", avenrun[0]);
1695		if (tTd(3, 15))
1696			sm_dprintf(", %d, %d", avenrun[1], avenrun[2]);
1697		sm_dprintf("\n");
1698	}
1699	if (tTd(3, 1))
1700		sm_dprintf("getla: %d\n",
1701			(int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1702	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1703}
1704
1705#endif /* LA_TYPE == LA_READKSYM */
1706
1707#if LA_TYPE == LA_DGUX
1708
1709# include <sys/dg_sys_info.h>
1710
1711int
1712getla()
1713{
1714	struct dg_sys_info_load_info load_info;
1715
1716	dg_sys_info((long *)&load_info,
1717		DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
1718
1719	if (tTd(3, 1))
1720		sm_dprintf("getla: %d\n", (int) (load_info.one_minute + 0.5));
1721
1722	return ((int) (load_info.one_minute + 0.5));
1723}
1724
1725#endif /* LA_TYPE == LA_DGUX */
1726
1727#if LA_TYPE == LA_HPUX
1728
1729/* forward declarations to keep gcc from complaining */
1730struct pst_dynamic;
1731struct pst_status;
1732struct pst_static;
1733struct pst_vminfo;
1734struct pst_diskinfo;
1735struct pst_processor;
1736struct pst_lv;
1737struct pst_swapinfo;
1738
1739# include <sys/param.h>
1740# include <sys/pstat.h>
1741
1742int
1743getla()
1744{
1745	struct pst_dynamic pstd;
1746
1747	if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic),
1748			     (size_t) 1, 0) == -1)
1749		return 0;
1750
1751	if (tTd(3, 1))
1752		sm_dprintf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
1753
1754	return (int) (pstd.psd_avg_1_min + 0.5);
1755}
1756
1757#endif /* LA_TYPE == LA_HPUX */
1758
1759#if LA_TYPE == LA_SUBR
1760
1761int
1762getla()
1763{
1764	double avenrun[3];
1765
1766	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
1767	{
1768		if (tTd(3, 1))
1769			sm_dprintf("getla: getloadavg failed: %s",
1770				   sm_errstring(errno));
1771		return -1;
1772	}
1773	if (tTd(3, 1))
1774		sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
1775	return ((int) (avenrun[0] + 0.5));
1776}
1777
1778#endif /* LA_TYPE == LA_SUBR */
1779
1780#if LA_TYPE == LA_MACH
1781
1782/*
1783**  This has been tested on NEXTSTEP release 2.1/3.X.
1784*/
1785
1786# if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
1787#  include <mach/mach.h>
1788# else
1789#  include <mach.h>
1790# endif
1791
1792int
1793getla()
1794{
1795	processor_set_t default_set;
1796	kern_return_t error;
1797	unsigned int info_count;
1798	struct processor_set_basic_info info;
1799	host_t host;
1800
1801	error = processor_set_default(host_self(), &default_set);
1802	if (error != KERN_SUCCESS)
1803	{
1804		if (tTd(3, 1))
1805			sm_dprintf("getla: processor_set_default failed: %s",
1806				   sm_errstring(errno));
1807		return -1;
1808	}
1809	info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
1810	if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
1811			       &host, (processor_set_info_t)&info,
1812			       &info_count) != KERN_SUCCESS)
1813	{
1814		if (tTd(3, 1))
1815			sm_dprintf("getla: processor_set_info failed: %s",
1816				   sm_errstring(errno));
1817		return -1;
1818	}
1819	if (tTd(3, 1))
1820		sm_dprintf("getla: %d\n",
1821			(int) ((info.load_average + (LOAD_SCALE / 2)) /
1822			       LOAD_SCALE));
1823	return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
1824}
1825
1826#endif /* LA_TYPE == LA_MACH */
1827
1828#if LA_TYPE == LA_PROCSTR
1829# if SM_CONF_BROKEN_STRTOD
1830	ERROR: This OS has most likely a broken strtod() implemenentation.
1831	ERROR: The function is required for getla().
1832	ERROR: Check the compilation options _LA_PROCSTR and
1833	ERROR: _SM_CONF_BROKEN_STRTOD (without the leading _).
1834# endif /* SM_CONF_BROKEN_STRTOD */
1835
1836/*
1837**  Read /proc/loadavg for the load average.  This is assumed to be
1838**  in a format like "0.15 0.12 0.06".
1839**
1840**	Initially intended for Linux.  This has been in the kernel
1841**	since at least 0.99.15.
1842*/
1843
1844# ifndef _PATH_LOADAVG
1845#  define _PATH_LOADAVG	"/proc/loadavg"
1846# endif
1847
1848int
1849getla()
1850{
1851	double avenrun;
1852	register int result;
1853	SM_FILE_T *fp;
1854
1855	fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_LOADAVG, SM_IO_RDONLY,
1856			NULL);
1857	if (fp == NULL)
1858	{
1859		if (tTd(3, 1))
1860			sm_dprintf("getla: sm_io_open(%s): %s\n",
1861				   _PATH_LOADAVG, sm_errstring(errno));
1862		return -1;
1863	}
1864	result = sm_io_fscanf(fp, SM_TIME_DEFAULT, "%lf", &avenrun);
1865	(void) sm_io_close(fp, SM_TIME_DEFAULT);
1866	if (result != 1)
1867	{
1868		if (tTd(3, 1))
1869			sm_dprintf("getla: sm_io_fscanf() = %d: %s\n",
1870				   result, sm_errstring(errno));
1871		return -1;
1872	}
1873
1874	if (tTd(3, 1))
1875		sm_dprintf("getla(): %.2f\n", avenrun);
1876
1877	return ((int) (avenrun + 0.5));
1878}
1879
1880#endif /* LA_TYPE == LA_PROCSTR */
1881
1882#if LA_TYPE == LA_IRIX6
1883
1884# include <sys/sysmp.h>
1885
1886# ifdef _UNICOSMP
1887#  define CAST_SYSMP(x)	(x)
1888# else
1889#  define CAST_SYSMP(x)	((x) & 0x7fffffff)
1890# endif
1891
1892int
1893getla(void)
1894{
1895	int j;
1896	static int kmem = -1;
1897	int avenrun[3];
1898
1899	if (kmem < 0)
1900	{
1901		kmem = open(_PATH_KMEM, 0, 0);
1902		if (kmem < 0)
1903		{
1904			if (tTd(3, 1))
1905				sm_dprintf("getla: open(%s): %s\n", _PATH_KMEM,
1906					   sm_errstring(errno));
1907			return -1;
1908		}
1909		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
1910		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
1911		{
1912			if (tTd(3, 1))
1913				sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
1914					   sm_errstring(errno));
1915			(void) close(kmem);
1916			kmem = -1;
1917			return -1;
1918		}
1919	}
1920
1921	if (lseek(kmem, CAST_SYSMP(sysmp(MP_KERNADDR, MPKA_AVENRUN)), SEEK_SET)
1922		== -1 ||
1923	    read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun))
1924	{
1925		if (tTd(3, 1))
1926			sm_dprintf("getla: lseek or read: %s\n",
1927				   sm_errstring(errno));
1928		return -1;
1929	}
1930	if (tTd(3, 5))
1931	{
1932		sm_dprintf("getla: avenrun = %ld", (long int) avenrun[0]);
1933		if (tTd(3, 15))
1934			sm_dprintf(", %ld, %ld",
1935				(long int) avenrun[1], (long int) avenrun[2]);
1936		sm_dprintf("\n");
1937	}
1938
1939	if (tTd(3, 1))
1940		sm_dprintf("getla: %d\n",
1941			(int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1942	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1943
1944}
1945#endif /* LA_TYPE == LA_IRIX6 */
1946
1947#if LA_TYPE == LA_KSTAT
1948
1949# include <kstat.h>
1950
1951int
1952getla()
1953{
1954	static kstat_ctl_t *kc = NULL;
1955	static kstat_t *ksp = NULL;
1956	kstat_named_t *ksn;
1957	int la;
1958
1959	if (kc == NULL)		/* if not initialized before */
1960		kc = kstat_open();
1961	if (kc == NULL)
1962	{
1963		if (tTd(3, 1))
1964			sm_dprintf("getla: kstat_open(): %s\n",
1965				   sm_errstring(errno));
1966		return -1;
1967	}
1968	if (ksp == NULL)
1969		ksp = kstat_lookup(kc, "unix", 0, "system_misc");
1970	if (ksp == NULL)
1971	{
1972		if (tTd(3, 1))
1973			sm_dprintf("getla: kstat_lookup(): %s\n",
1974				   sm_errstring(errno));
1975		return -1;
1976	}
1977	if (kstat_read(kc, ksp, NULL) < 0)
1978	{
1979		if (tTd(3, 1))
1980			sm_dprintf("getla: kstat_read(): %s\n",
1981				   sm_errstring(errno));
1982		return -1;
1983	}
1984	ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
1985	la = ((double) ksn->value.ul + FSCALE/2) / FSCALE;
1986	/* kstat_close(kc); /o do not close for fast access */
1987	return la;
1988}
1989
1990#endif /* LA_TYPE == LA_KSTAT */
1991
1992#if LA_TYPE == LA_DEVSHORT
1993
1994/*
1995**  Read /dev/table/avenrun for the load average.  This should contain
1996**  three shorts for the 1, 5, and 15 minute loads.  We only read the
1997**  first, since that's all we care about.
1998**
1999**	Intended for SCO OpenServer 5.
2000*/
2001
2002# ifndef _PATH_AVENRUN
2003#  define _PATH_AVENRUN	"/dev/table/avenrun"
2004# endif
2005
2006int
2007getla()
2008{
2009	static int afd = -1;
2010	short avenrun;
2011	int loadav;
2012	int r;
2013
2014	errno = EBADF;
2015
2016	if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1)
2017	{
2018		if (errno != EBADF)
2019			return -1;
2020		afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
2021		if (afd < 0)
2022		{
2023			sm_syslog(LOG_ERR, NOQID,
2024				"can't open %s: %s",
2025				_PATH_AVENRUN, sm_errstring(errno));
2026			return -1;
2027		}
2028	}
2029
2030	r = read(afd, &avenrun, sizeof(avenrun));
2031	if (r != sizeof(avenrun))
2032	{
2033		sm_syslog(LOG_ERR, NOQID,
2034			"can't read %s: %s", _PATH_AVENRUN,
2035			r == -1 ? sm_errstring(errno) : "short read");
2036		return -1;
2037	}
2038
2039	if (tTd(3, 5))
2040		sm_dprintf("getla: avenrun = %d\n", avenrun);
2041	loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
2042	if (tTd(3, 1))
2043		sm_dprintf("getla: %d\n", loadav);
2044	return loadav;
2045}
2046
2047#endif /* LA_TYPE == LA_DEVSHORT */
2048
2049#if LA_TYPE == LA_ALPHAOSF
2050struct rtentry;
2051struct mbuf;
2052# include <sys/table.h>
2053
2054int
2055getla()
2056{
2057	int ave = 0;
2058	struct tbl_loadavg tab;
2059
2060	if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1)
2061	{
2062		if (tTd(3, 1))
2063			sm_dprintf("getla: table %s\n", sm_errstring(errno));
2064		return -1;
2065	}
2066
2067	if (tTd(3, 1))
2068		sm_dprintf("getla: scale = %d\n", tab.tl_lscale);
2069
2070	if (tab.tl_lscale)
2071		ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) /
2072		       tab.tl_lscale);
2073	else
2074		ave = (int) (tab.tl_avenrun.d[2] + 0.5);
2075
2076	if (tTd(3, 1))
2077		sm_dprintf("getla: %d\n", ave);
2078
2079	return ave;
2080}
2081
2082#endif /* LA_TYPE == LA_ALPHAOSF */
2083
2084#if LA_TYPE == LA_PSET
2085
2086int
2087getla()
2088{
2089	double avenrun[3];
2090
2091	if (pset_getloadavg(PS_MYID, avenrun,
2092			    sizeof(avenrun) / sizeof(avenrun[0])) < 0)
2093	{
2094		if (tTd(3, 1))
2095			sm_dprintf("getla: pset_getloadavg failed: %s",
2096				   sm_errstring(errno));
2097		return -1;
2098	}
2099	if (tTd(3, 1))
2100		sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
2101	return ((int) (avenrun[0] + 0.5));
2102}
2103
2104#endif /* LA_TYPE == LA_PSET */
2105
2106#if LA_TYPE == LA_ZERO
2107
2108int
2109getla()
2110{
2111	if (tTd(3, 1))
2112		sm_dprintf("getla: ZERO\n");
2113	return 0;
2114}
2115
2116#endif /* LA_TYPE == LA_ZERO */
2117
2118/*
2119 * Copyright 1989 Massachusetts Institute of Technology
2120 *
2121 * Permission to use, copy, modify, distribute, and sell this software and its
2122 * documentation for any purpose is hereby granted without fee, provided that
2123 * the above copyright notice appear in all copies and that both that
2124 * copyright notice and this permission notice appear in supporting
2125 * documentation, and that the name of M.I.T. not be used in advertising or
2126 * publicity pertaining to distribution of the software without specific,
2127 * written prior permission.  M.I.T. makes no representations about the
2128 * suitability of this software for any purpose.  It is provided "as is"
2129 * without express or implied warranty.
2130 *
2131 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
2132 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
2133 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
2134 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
2135 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
2136 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
2137 *
2138 * Authors:  Many and varied...
2139 */
2140
2141/* Non Apollo stuff removed by Don Lewis 11/15/93 */
2142#ifndef lint
2143SM_UNUSED(static char  rcsid[]) = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
2144#endif
2145
2146#ifdef apollo
2147# undef volatile
2148# include <apollo/base.h>
2149
2150/* ARGSUSED */
2151int getloadavg( call_data )
2152	caddr_t call_data;	/* pointer to (double) return value */
2153{
2154	double *avenrun = (double *) call_data;
2155	int i;
2156	status_$t      st;
2157	long loadav[3];
2158
2159	proc1_$get_loadav(loadav, &st);
2160	*avenrun = loadav[0] / (double) (1 << 16);
2161	return 0;
2162}
2163#endif /* apollo */
2164/*
2165**  SM_GETLA -- get the current load average
2166**
2167**	Parameters:
2168**		none
2169**
2170**	Returns:
2171**		none
2172**
2173**	Side Effects:
2174**		Set CurrentLA to the current load average.
2175**		Set {load_avg} in GlobalMacros to the current load average.
2176*/
2177
2178void
2179sm_getla()
2180{
2181	char labuf[8];
2182
2183	CurrentLA = getla();
2184	(void) sm_snprintf(labuf, sizeof(labuf), "%d", CurrentLA);
2185	macdefine(&GlobalMacros, A_TEMP, macid("{load_avg}"), labuf);
2186}
2187/*
2188**  SHOULDQUEUE -- should this message be queued or sent?
2189**
2190**	Compares the message cost to the load average to decide.
2191**
2192**	Note: Do NOT change this API! It is documented in op.me
2193**		and theoretically the user can change this function...
2194**
2195**	Parameters:
2196**		pri -- the priority of the message in question.
2197**		ct -- the message creation time (unused, but see above).
2198**
2199**	Returns:
2200**		true -- if this message should be queued up for the
2201**			time being.
2202**		false -- if the load is low enough to send this message.
2203**
2204**	Side Effects:
2205**		none.
2206*/
2207
2208/* ARGSUSED1 */
2209bool
2210shouldqueue(pri, ct)
2211	long pri;
2212	time_t ct;
2213{
2214	bool rval;
2215#if _FFR_MEMSTAT
2216	long memfree;
2217#endif
2218
2219	if (tTd(3, 30))
2220		sm_dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ",
2221			CurrentLA, pri);
2222
2223#if _FFR_MEMSTAT
2224	if (QueueLowMem > 0 &&
2225	    sm_memstat_get(MemoryResource, &memfree) >= 0 &&
2226	    memfree < QueueLowMem)
2227	{
2228		if (tTd(3, 30))
2229			sm_dprintf("true (memfree=%ld < QueueLowMem=%ld)\n",
2230				memfree, QueueLowMem);
2231		return true;
2232	}
2233#endif /* _FFR_MEMSTAT */
2234	if (CurrentLA < QueueLA)
2235	{
2236		if (tTd(3, 30))
2237			sm_dprintf("false (CurrentLA < QueueLA)\n");
2238		return false;
2239	}
2240	rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1));
2241	if (tTd(3, 30))
2242		sm_dprintf("%s (by calculation)\n", rval ? "true" : "false");
2243	return rval;
2244}
2245
2246/*
2247**  REFUSECONNECTIONS -- decide if connections should be refused
2248**
2249**	Parameters:
2250**		e -- the current envelope.
2251**		dn -- number of daemon.
2252**		active -- was this daemon actually active?
2253**
2254**	Returns:
2255**		true if incoming SMTP connections should be refused
2256**			(for now).
2257**		false if we should accept new work.
2258**
2259**	Side Effects:
2260**		Sets process title when it is rejecting connections.
2261*/
2262
2263bool
2264refuseconnections(e, dn, active)
2265	ENVELOPE *e;
2266	int dn;
2267	bool active;
2268{
2269	static time_t lastconn[MAXDAEMONS];
2270	static int conncnt[MAXDAEMONS];
2271	static time_t firstrejtime[MAXDAEMONS];
2272	static time_t nextlogtime[MAXDAEMONS];
2273	int limit;
2274#if _FFR_MEMSTAT
2275	long memfree;
2276#endif
2277
2278#if XLA
2279	if (!xla_smtp_ok())
2280		return true;
2281#endif
2282
2283	SM_ASSERT(dn >= 0);
2284	SM_ASSERT(dn < MAXDAEMONS);
2285	if (ConnRateThrottle > 0)
2286	{
2287		time_t now;
2288
2289		now = curtime();
2290		if (active)
2291		{
2292			if (now != lastconn[dn])
2293			{
2294				lastconn[dn] = now;
2295				conncnt[dn] = 1;
2296			}
2297			else if (conncnt[dn]++ > ConnRateThrottle)
2298			{
2299#define D_MSG_CRT "deferring connections on daemon %s: %d per second"
2300				/* sleep to flatten out connection load */
2301				sm_setproctitle(true, e, D_MSG_CRT,
2302						Daemons[dn].d_name,
2303						ConnRateThrottle);
2304				if (LogLevel > 8)
2305					sm_syslog(LOG_INFO, NOQID, D_MSG_CRT,
2306						  Daemons[dn].d_name,
2307						  ConnRateThrottle);
2308				(void) sleep(1);
2309			}
2310		}
2311		else if (now != lastconn[dn])
2312			conncnt[dn] = 0;
2313	}
2314
2315
2316#if _FFR_MEMSTAT
2317	if (RefuseLowMem > 0 &&
2318	    sm_memstat_get(MemoryResource, &memfree) >= 0 &&
2319	    memfree < RefuseLowMem)
2320	{
2321# define R_MSG_LM "rejecting connections on daemon %s: free memory: %ld"
2322		sm_setproctitle(true, e, R_MSG_LM, Daemons[dn].d_name, memfree);
2323		if (LogLevel > 8)
2324			sm_syslog(LOG_NOTICE, NOQID, R_MSG_LM,
2325				Daemons[dn].d_name, memfree);
2326		return true;
2327	}
2328#endif /* _FFR_MEMSTAT */
2329	sm_getla();
2330	limit = (Daemons[dn].d_refuseLA != DPO_NOTSET) ?
2331		Daemons[dn].d_refuseLA : RefuseLA;
2332	if (limit > 0 && CurrentLA >= limit)
2333	{
2334		time_t now;
2335
2336# define R_MSG_LA "rejecting connections on daemon %s: load average: %d"
2337# define R2_MSG_LA "have been rejecting connections on daemon %s for %s"
2338		sm_setproctitle(true, e, R_MSG_LA, Daemons[dn].d_name,
2339				CurrentLA);
2340		if (LogLevel > 8)
2341			sm_syslog(LOG_NOTICE, NOQID, R_MSG_LA,
2342				Daemons[dn].d_name, CurrentLA);
2343		now = curtime();
2344		if (firstrejtime[dn] == 0)
2345		{
2346			firstrejtime[dn] = now;
2347			nextlogtime[dn] = now + RejectLogInterval;
2348		}
2349		else if (nextlogtime[dn] < now)
2350		{
2351			sm_syslog(LOG_ERR, NOQID, R2_MSG_LA, Daemons[dn].d_name,
2352				  pintvl(now - firstrejtime[dn], true));
2353			nextlogtime[dn] = now + RejectLogInterval;
2354		}
2355		return true;
2356	}
2357	else
2358		firstrejtime[dn] = 0;
2359
2360	limit = (Daemons[dn].d_delayLA != DPO_NOTSET) ?
2361		Daemons[dn].d_delayLA : DelayLA;
2362	if (limit > 0 && CurrentLA >= limit)
2363	{
2364		time_t now;
2365		static time_t log_delay = (time_t) 0;
2366
2367# define MIN_DELAY_LOG	90	/* wait before logging this again */
2368# define D_MSG_LA "delaying connections on daemon %s: load average=%d >= %d"
2369		/* sleep to flatten out connection load */
2370		sm_setproctitle(true, e, D_MSG_LA, Daemons[dn].d_name,
2371				CurrentLA, limit);
2372		if (LogLevel > 8 && (now = curtime()) > log_delay)
2373		{
2374			sm_syslog(LOG_INFO, NOQID, D_MSG_LA,
2375				  Daemons[dn].d_name, CurrentLA, limit);
2376			log_delay = now + MIN_DELAY_LOG;
2377		}
2378		(void) sleep(1);
2379	}
2380
2381	limit = (Daemons[dn].d_maxchildren != DPO_NOTSET) ?
2382		Daemons[dn].d_maxchildren : MaxChildren;
2383	if (limit > 0 && CurChildren >= limit)
2384	{
2385		proc_list_probe();
2386		if (CurChildren >= limit)
2387		{
2388#define R_MSG_CHILD "rejecting connections on daemon %s: %d children, max %d"
2389			sm_setproctitle(true, e, R_MSG_CHILD,
2390					Daemons[dn].d_name, CurChildren,
2391					limit);
2392			if (LogLevel > 8)
2393				sm_syslog(LOG_INFO, NOQID, R_MSG_CHILD,
2394					Daemons[dn].d_name, CurChildren,
2395					limit);
2396			return true;
2397		}
2398	}
2399	return false;
2400}
2401
2402/*
2403**  SETPROCTITLE -- set process title for ps
2404**
2405**	Parameters:
2406**		fmt -- a printf style format string.
2407**		a, b, c -- possible parameters to fmt.
2408**
2409**	Returns:
2410**		none.
2411**
2412**	Side Effects:
2413**		Clobbers argv of our main procedure so ps(1) will
2414**		display the title.
2415*/
2416
2417#define SPT_NONE	0	/* don't use it at all */
2418#define SPT_REUSEARGV	1	/* cover argv with title information */
2419#define SPT_BUILTIN	2	/* use libc builtin */
2420#define SPT_PSTAT	3	/* use pstat(PSTAT_SETCMD, ...) */
2421#define SPT_PSSTRINGS	4	/* use PS_STRINGS->... */
2422#define SPT_SYSMIPS	5	/* use sysmips() supported by NEWS-OS 6 */
2423#define SPT_SCO		6	/* write kernel u. area */
2424#define SPT_CHANGEARGV	7	/* write our own strings into argv[] */
2425
2426#ifndef SPT_TYPE
2427# define SPT_TYPE	SPT_REUSEARGV
2428#endif
2429
2430
2431#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
2432
2433# if SPT_TYPE == SPT_PSTAT
2434#  include <sys/pstat.h>
2435# endif
2436# if SPT_TYPE == SPT_PSSTRINGS
2437#  include <machine/vmparam.h>
2438#  include <sys/exec.h>
2439#  ifndef PS_STRINGS	/* hmmmm....  apparently not available after all */
2440#   undef SPT_TYPE
2441#   define SPT_TYPE	SPT_REUSEARGV
2442#  else /* ! PS_STRINGS */
2443#   ifndef NKPDE			/* FreeBSD 2.0 */
2444#    define NKPDE 63
2445typedef unsigned int	*pt_entry_t;
2446#   endif /* ! NKPDE */
2447#  endif /* ! PS_STRINGS */
2448# endif /* SPT_TYPE == SPT_PSSTRINGS */
2449
2450# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
2451#  define SETPROC_STATIC	static
2452# else
2453#  define SETPROC_STATIC
2454# endif
2455
2456# if SPT_TYPE == SPT_SYSMIPS
2457#  include <sys/sysmips.h>
2458#  include <sys/sysnews.h>
2459# endif
2460
2461# if SPT_TYPE == SPT_SCO
2462#  include <sys/immu.h>
2463#  include <sys/dir.h>
2464#  include <sys/user.h>
2465#  include <sys/fs/s5param.h>
2466#  if PSARGSZ > MAXLINE
2467#   define SPT_BUFSIZE	PSARGSZ
2468#  endif
2469# endif /* SPT_TYPE == SPT_SCO */
2470
2471# ifndef SPT_PADCHAR
2472#  define SPT_PADCHAR	' '
2473# endif
2474
2475#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
2476
2477#ifndef SPT_BUFSIZE
2478# define SPT_BUFSIZE	MAXLINE
2479#endif
2480
2481#if _FFR_SPT_ALIGN
2482
2483/*
2484**  It looks like the Compaq Tru64 5.1A now aligns argv and envp to
2485**  64 bit alignment, so unless each piece of argv and envp is a multiple
2486**  of 8 bytes (including terminating NULL), initsetproctitle() won't use
2487**  any of the space beyond argv[0].  Be sure to set SPT_ALIGN_SIZE if
2488**  you use this FFR.
2489*/
2490
2491# ifdef SPT_ALIGN_SIZE
2492#  define SPT_ALIGN(x, align)	(((((x) + SPT_ALIGN_SIZE) >> (align)) << (align)) - 1)
2493# else
2494#  define SPT_ALIGN(x, align)	(x)
2495# endif
2496#else /* _FFR_SPT_ALIGN */
2497# define SPT_ALIGN(x, align)	(x)
2498#endif /* _FFR_SPT_ALIGN */
2499
2500/*
2501**  Pointers for setproctitle.
2502**	This allows "ps" listings to give more useful information.
2503*/
2504
2505static char	**Argv = NULL;		/* pointer to argument vector */
2506static char	*LastArgv = NULL;	/* end of argv */
2507#if SPT_TYPE != SPT_BUILTIN
2508static void	setproctitle __P((const char *, ...));
2509#endif
2510
2511void
2512initsetproctitle(argc, argv, envp)
2513	int argc;
2514	char **argv;
2515	char **envp;
2516{
2517	register int i;
2518#if _FFR_SPT_ALIGN
2519	int align;
2520#endif
2521	extern char **environ;
2522
2523	/*
2524	**  Move the environment so setproctitle can use the space at
2525	**  the top of memory.
2526	*/
2527
2528	if (envp != NULL)
2529	{
2530		for (i = 0; envp[i] != NULL; i++)
2531			continue;
2532		environ = (char **) xalloc(sizeof(char *) * (i + 1));
2533		for (i = 0; envp[i] != NULL; i++)
2534			environ[i] = newstr(envp[i]);
2535		environ[i] = NULL;
2536	}
2537
2538	/*
2539	**  Save start and extent of argv for setproctitle.
2540	*/
2541
2542	Argv = argv;
2543
2544	/*
2545	**  Determine how much space we can use for setproctitle.
2546	**  Use all contiguous argv and envp pointers starting at argv[0]
2547	*/
2548
2549# if _FFR_SPT_ALIGN
2550	align = -1;
2551#  ifdef SPT_ALIGN_SIZE
2552	for (i = SPT_ALIGN_SIZE; i > 0; i >>= 1)
2553		align++;
2554#  endif
2555# endif /* _FFR_SPT_ALIGN */
2556
2557	for (i = 0; i < argc; i++)
2558	{
2559		if (i == 0 || LastArgv + 1 == argv[i])
2560			LastArgv = argv[i] + SPT_ALIGN(strlen(argv[i]), align);
2561	}
2562	for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++)
2563	{
2564		if (LastArgv + 1 == envp[i])
2565			LastArgv = envp[i] + SPT_ALIGN(strlen(envp[i]), align);
2566	}
2567}
2568
2569#if SPT_TYPE != SPT_BUILTIN
2570
2571/*VARARGS1*/
2572static void
2573# ifdef __STDC__
2574setproctitle(const char *fmt, ...)
2575# else /* __STDC__ */
2576setproctitle(fmt, va_alist)
2577	const char *fmt;
2578	va_dcl
2579# endif /* __STDC__ */
2580{
2581# if SPT_TYPE != SPT_NONE
2582	register int i;
2583	register char *p;
2584	SETPROC_STATIC char buf[SPT_BUFSIZE];
2585	SM_VA_LOCAL_DECL
2586#  if SPT_TYPE == SPT_PSTAT
2587	union pstun pst;
2588#  endif
2589#  if SPT_TYPE == SPT_SCO
2590	int j;
2591	off_t seek_off;
2592	static int kmem = -1;
2593	static pid_t kmempid = -1;
2594	struct user u;
2595#  endif /* SPT_TYPE == SPT_SCO */
2596
2597	p = buf;
2598
2599	/* print sendmail: heading for grep */
2600	(void) sm_strlcpy(p, "sendmail: ", SPACELEFT(buf, p));
2601	p += strlen(p);
2602
2603	/* print the argument string */
2604	SM_VA_START(ap, fmt);
2605	(void) sm_vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
2606	SM_VA_END(ap);
2607
2608	i = (int) strlen(buf);
2609	if (i < 0)
2610		return;
2611
2612#  if SPT_TYPE == SPT_PSTAT
2613	pst.pst_command = buf;
2614	pstat(PSTAT_SETCMD, pst, i, 0, 0);
2615#  endif
2616#  if SPT_TYPE == SPT_PSSTRINGS
2617	PS_STRINGS->ps_nargvstr = 1;
2618	PS_STRINGS->ps_argvstr = buf;
2619#  endif
2620#  if SPT_TYPE == SPT_SYSMIPS
2621	sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
2622#  endif
2623#  if SPT_TYPE == SPT_SCO
2624	if (kmem < 0 || kmempid != CurrentPid)
2625	{
2626		if (kmem >= 0)
2627			(void) close(kmem);
2628		kmem = open(_PATH_KMEM, O_RDWR, 0);
2629		if (kmem < 0)
2630			return;
2631		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
2632		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
2633		{
2634			(void) close(kmem);
2635			kmem = -1;
2636			return;
2637		}
2638		kmempid = CurrentPid;
2639	}
2640	buf[PSARGSZ - 1] = '\0';
2641	seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
2642	if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
2643		(void) write(kmem, buf, PSARGSZ);
2644#  endif /* SPT_TYPE == SPT_SCO */
2645#  if SPT_TYPE == SPT_REUSEARGV
2646	if (LastArgv == NULL)
2647		return;
2648
2649	if (i > LastArgv - Argv[0] - 2)
2650	{
2651		i = LastArgv - Argv[0] - 2;
2652		buf[i] = '\0';
2653	}
2654	(void) sm_strlcpy(Argv[0], buf, i + 1);
2655	p = &Argv[0][i];
2656	while (p < LastArgv)
2657		*p++ = SPT_PADCHAR;
2658	Argv[1] = NULL;
2659#  endif /* SPT_TYPE == SPT_REUSEARGV */
2660#  if SPT_TYPE == SPT_CHANGEARGV
2661	Argv[0] = buf;
2662	Argv[1] = NULL;
2663#  endif
2664# endif /* SPT_TYPE != SPT_NONE */
2665}
2666#endif /* SPT_TYPE != SPT_BUILTIN */
2667
2668/*
2669**  SM_SETPROCTITLE -- set process task and set process title for ps
2670**
2671**	Possibly set process status and call setproctitle() to
2672**	change the ps display.
2673**
2674**	Parameters:
2675**		status -- whether or not to store as process status
2676**		e -- the current envelope.
2677**		fmt -- a printf style format string.
2678**		a, b, c -- possible parameters to fmt.
2679**
2680**	Returns:
2681**		none.
2682*/
2683
2684/*VARARGS3*/
2685void
2686#ifdef __STDC__
2687sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...)
2688#else /* __STDC__ */
2689sm_setproctitle(status, e, fmt, va_alist)
2690	bool status;
2691	ENVELOPE *e;
2692	const char *fmt;
2693	va_dcl
2694#endif /* __STDC__ */
2695{
2696	char buf[SPT_BUFSIZE];
2697	SM_VA_LOCAL_DECL
2698
2699	/* print the argument string */
2700	SM_VA_START(ap, fmt);
2701	(void) sm_vsnprintf(buf, sizeof(buf), fmt, ap);
2702	SM_VA_END(ap);
2703
2704	if (status)
2705		proc_list_set(CurrentPid, buf);
2706
2707	if (ProcTitlePrefix != NULL)
2708	{
2709		char prefix[SPT_BUFSIZE];
2710
2711		expand(ProcTitlePrefix, prefix, sizeof(prefix), e);
2712		setproctitle("%s: %s", prefix, buf);
2713	}
2714	else
2715		setproctitle("%s", buf);
2716}
2717/*
2718**  WAITFOR -- wait for a particular process id.
2719**
2720**	Parameters:
2721**		pid -- process id to wait for.
2722**
2723**	Returns:
2724**		status of pid.
2725**		-1 if pid never shows up.
2726**
2727**	Side Effects:
2728**		none.
2729*/
2730
2731int
2732waitfor(pid)
2733	pid_t pid;
2734{
2735	int st;
2736	pid_t i;
2737
2738	do
2739	{
2740		errno = 0;
2741		i = sm_wait(&st);
2742		if (i > 0)
2743			proc_list_drop(i, st, NULL);
2744	} while ((i >= 0 || errno == EINTR) && i != pid);
2745	if (i < 0)
2746		return -1;
2747	return st;
2748}
2749/*
2750**  SM_WAIT -- wait
2751**
2752**	Parameters:
2753**		status -- pointer to status (return value)
2754**
2755**	Returns:
2756**		pid
2757*/
2758
2759pid_t
2760sm_wait(status)
2761	int *status;
2762{
2763# ifdef WAITUNION
2764	union wait st;
2765# else
2766	auto int st;
2767# endif
2768	pid_t i;
2769# if defined(ISC_UNIX) || defined(_SCO_unix_)
2770	int savesig;
2771# endif
2772
2773# if defined(ISC_UNIX) || defined(_SCO_unix_)
2774	savesig = sm_releasesignal(SIGCHLD);
2775# endif
2776	i = wait(&st);
2777# if defined(ISC_UNIX) || defined(_SCO_unix_)
2778	if (savesig > 0)
2779		sm_blocksignal(SIGCHLD);
2780# endif
2781# ifdef WAITUNION
2782	*status = st.w_status;
2783# else
2784	*status = st;
2785# endif
2786	return i;
2787}
2788/*
2789**  REAPCHILD -- pick up the body of my child, lest it become a zombie
2790**
2791**	Parameters:
2792**		sig -- the signal that got us here (unused).
2793**
2794**	Returns:
2795**		none.
2796**
2797**	Side Effects:
2798**		Picks up extant zombies.
2799**		Control socket exits may restart/shutdown daemon.
2800**
2801**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
2802**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
2803**		DOING.
2804*/
2805
2806/* ARGSUSED0 */
2807SIGFUNC_DECL
2808reapchild(sig)
2809	int sig;
2810{
2811	int save_errno = errno;
2812	int st;
2813	pid_t pid;
2814# if HASWAITPID
2815	auto int status;
2816	int count;
2817
2818	count = 0;
2819	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
2820	{
2821		st = status;
2822		if (count++ > 1000)
2823			break;
2824# else /* HASWAITPID */
2825#  ifdef WNOHANG
2826	union wait status;
2827
2828	while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0)
2829	{
2830		st = status.w_status;
2831#  else /* WNOHANG */
2832	auto int status;
2833
2834	/*
2835	**  Catch one zombie -- we will be re-invoked (we hope) if there
2836	**  are more.  Unreliable signals probably break this, but this
2837	**  is the "old system" situation -- waitpid or wait3 are to be
2838	**  strongly preferred.
2839	*/
2840
2841	if ((pid = wait(&status)) > 0)
2842	{
2843		st = status;
2844#  endif /* WNOHANG */
2845# endif /* HASWAITPID */
2846		/* Drop PID and check if it was a control socket child */
2847		proc_list_drop(pid, st, NULL);
2848	}
2849	FIX_SYSV_SIGNAL(sig, reapchild);
2850	errno = save_errno;
2851	return SIGFUNC_RETURN;
2852}
2853/*
2854**  GETDTSIZE -- return number of file descriptors
2855**
2856**	Only on non-BSD systems
2857**
2858**	Parameters:
2859**		none
2860**
2861**	Returns:
2862**		size of file descriptor table
2863**
2864**	Side Effects:
2865**		none
2866*/
2867
2868#ifdef SOLARIS
2869# include <sys/resource.h>
2870#endif
2871
2872int
2873getdtsize()
2874{
2875# ifdef RLIMIT_NOFILE
2876	struct rlimit rl;
2877
2878	if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
2879		return rl.rlim_cur;
2880# endif /* RLIMIT_NOFILE */
2881
2882# if HASGETDTABLESIZE
2883	return getdtablesize();
2884# else /* HASGETDTABLESIZE */
2885#  ifdef _SC_OPEN_MAX
2886	return sysconf(_SC_OPEN_MAX);
2887#  else
2888	return NOFILE;
2889#  endif
2890# endif /* HASGETDTABLESIZE */
2891}
2892/*
2893**  UNAME -- get the UUCP name of this system.
2894*/
2895
2896#if !HASUNAME
2897
2898int
2899uname(name)
2900	struct utsname *name;
2901{
2902	SM_FILE_T *file;
2903	char *n;
2904
2905	name->nodename[0] = '\0';
2906
2907	/* try /etc/whoami -- one line with the node name */
2908	if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, "/etc/whoami",
2909			       SM_IO_RDONLY, NULL)) != NULL)
2910	{
2911		(void) sm_io_fgets(file, SM_TIME_DEFAULT, name->nodename,
2912				   NODE_LENGTH + 1);
2913		(void) sm_io_close(file, SM_TIME_DEFAULT);
2914		n = strchr(name->nodename, '\n');
2915		if (n != NULL)
2916			*n = '\0';
2917		if (name->nodename[0] != '\0')
2918			return 0;
2919	}
2920
2921	/* try /usr/include/whoami.h -- has a #define somewhere */
2922	if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
2923			       "/usr/include/whoami.h", SM_IO_RDONLY, NULL))
2924	    != NULL)
2925	{
2926		char buf[MAXLINE];
2927
2928		while (sm_io_fgets(file, SM_TIME_DEFAULT,
2929				   buf, sizeof(buf)) >= 0)
2930		{
2931			if (sm_io_sscanf(buf, "#define sysname \"%*[^\"]\"",
2932					NODE_LENGTH, name->nodename) > 0)
2933				break;
2934		}
2935		(void) sm_io_close(file, SM_TIME_DEFAULT);
2936		if (name->nodename[0] != '\0')
2937			return 0;
2938	}
2939
2940	return -1;
2941}
2942#endif /* !HASUNAME */
2943/*
2944**  INITGROUPS -- initialize groups
2945**
2946**	Stub implementation for System V style systems
2947*/
2948
2949#if !HASINITGROUPS
2950initgroups(name, basegid)
2951	char *name;
2952	int basegid;
2953{
2954	return 0;
2955}
2956#endif /* !HASINITGROUPS */
2957
2958/*
2959**  SETGROUPS -- set group list
2960**
2961**	Stub implementation for systems that don't have group lists
2962*/
2963
2964#ifndef NGROUPS_MAX
2965int
2966setgroups(ngroups, grouplist)
2967	int ngroups;
2968	GIDSET_T grouplist[];
2969{
2970	return 0;
2971}
2972#endif /* ! NGROUPS_MAX */
2973
2974/*
2975**  SETSID -- set session id (for non-POSIX systems)
2976*/
2977
2978#if !HASSETSID
2979
2980pid_t
2981setsid __P ((void))
2982{
2983#  ifdef TIOCNOTTY
2984	int fd;
2985
2986	fd = open("/dev/tty", O_RDWR, 0);
2987	if (fd >= 0)
2988	{
2989		(void) ioctl(fd, TIOCNOTTY, (char *) 0);
2990		(void) close(fd);
2991	}
2992#  endif /* TIOCNOTTY */
2993#  ifdef SYS5SETPGRP
2994	return setpgrp();
2995#  else
2996	return setpgid(0, CurrentPid);
2997#  endif
2998}
2999
3000#endif /* !HASSETSID */
3001/*
3002**  FSYNC -- dummy fsync
3003*/
3004
3005#if NEEDFSYNC
3006
3007fsync(fd)
3008	int fd;
3009{
3010# ifdef O_SYNC
3011	return fcntl(fd, F_SETFL, O_SYNC);
3012# else
3013	/* nothing we can do */
3014	return 0;
3015# endif
3016}
3017#endif /* NEEDFSYNC */
3018
3019/*
3020**  DGUX_INET_ADDR -- inet_addr for DG/UX
3021**
3022**	Data General DG/UX version of inet_addr returns a struct in_addr
3023**	instead of a long.  This patches things.  Only needed on versions
3024**	prior to 5.4.3.
3025*/
3026
3027#ifdef DGUX_5_4_2
3028
3029# undef inet_addr
3030
3031long
3032dgux_inet_addr(host)
3033	char *host;
3034{
3035	struct in_addr haddr;
3036
3037	haddr = inet_addr(host);
3038	return haddr.s_addr;
3039}
3040
3041#endif /* DGUX_5_4_2 */
3042/*
3043**  GETOPT -- for old systems or systems with bogus implementations
3044*/
3045
3046#if !SM_CONF_GETOPT
3047
3048/*
3049 * Copyright (c) 1985 Regents of the University of California.
3050 * All rights reserved.  The Berkeley software License Agreement
3051 * specifies the terms and conditions for redistribution.
3052 */
3053
3054
3055/*
3056**  this version hacked to add `atend' flag to allow state machine
3057**  to reset if invoked by the program to scan args for a 2nd time
3058*/
3059
3060# if defined(LIBC_SCCS) && !defined(lint)
3061static char sccsid[] = "@(#)getopt.c	4.3 (Berkeley) 3/9/86";
3062# endif
3063
3064/*
3065**  get option letter from argument vector
3066*/
3067# ifdef _CONVEX_SOURCE
3068extern int	optind, opterr, optopt;
3069extern char	*optarg;
3070# else /* _CONVEX_SOURCE */
3071int	opterr = 1;		/* if error message should be printed */
3072int	optind = 1;		/* index into parent argv vector */
3073int	optopt = 0;		/* character checked for validity */
3074char	*optarg = NULL;		/* argument associated with option */
3075# endif /* _CONVEX_SOURCE */
3076
3077# define BADCH	(int)'?'
3078# define EMSG	""
3079# define tell(s)	if (opterr) \
3080			{sm_io_fputs(smioerr, SM_TIME_DEFAULT, *nargv); \
3081			(void) sm_io_fputs(smioerr, SM_TIME_DEFAULT, s); \
3082			(void) sm_io_putc(smioerr, SM_TIME_DEFAULT, optopt); \
3083			(void) sm_io_putc(smioerr, SM_TIME_DEFAULT, '\n'); \
3084			return BADCH;}
3085
3086int
3087getopt(nargc,nargv,ostr)
3088	int		nargc;
3089	char *const	*nargv;
3090	const char	*ostr;
3091{
3092	static char	*place = EMSG;	/* option letter processing */
3093	static char	atend = 0;
3094	register char	*oli = NULL;	/* option letter list index */
3095
3096	if (atend) {
3097		atend = 0;
3098		place = EMSG;
3099	}
3100	if(!*place) {			/* update scanning pointer */
3101		if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
3102			atend++;
3103			return -1;
3104		}
3105		if (*place == '-') {	/* found "--" */
3106			++optind;
3107			atend++;
3108			return -1;
3109		}
3110	}				/* option letter okay? */
3111	if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
3112		if (!*place) ++optind;
3113		tell(": illegal option -- ");
3114	}
3115	if (oli && *++oli != ':') {		/* don't need argument */
3116		optarg = NULL;
3117		if (!*place) ++optind;
3118	}
3119	else {				/* need an argument */
3120		if (*place) optarg = place;	/* no white space */
3121		else if (nargc <= ++optind) {	/* no arg */
3122			place = EMSG;
3123			tell(": option requires an argument -- ");
3124		}
3125		else optarg = nargv[optind];	/* white space */
3126		place = EMSG;
3127		++optind;
3128	}
3129	return optopt;			/* dump back option letter */
3130}
3131
3132#endif /* !SM_CONF_GETOPT */
3133/*
3134**  USERSHELLOK -- tell if a user's shell is ok for unrestricted use
3135**
3136**	Parameters:
3137**		user -- the name of the user we are checking.
3138**		shell -- the user's shell from /etc/passwd
3139**
3140**	Returns:
3141**		true -- if it is ok to use this for unrestricted access.
3142**		false -- if the shell is restricted.
3143*/
3144
3145#if !HASGETUSERSHELL
3146
3147# ifndef _PATH_SHELLS
3148#  define _PATH_SHELLS	"/etc/shells"
3149# endif
3150
3151# if defined(_AIX3) || defined(_AIX4)
3152#  include <userconf.h>
3153#  if _AIX4 >= 40200
3154#   include <userpw.h>
3155#  endif
3156#  include <usersec.h>
3157# endif /* defined(_AIX3) || defined(_AIX4) */
3158
3159static char	*DefaultUserShells[] =
3160{
3161	"/bin/sh",		/* standard shell */
3162# ifdef MPE
3163	"/SYS/PUB/CI",
3164# else /* MPE */
3165	"/usr/bin/sh",
3166	"/bin/csh",		/* C shell */
3167	"/usr/bin/csh",
3168# endif /* MPE */
3169# ifdef __hpux
3170#  ifdef V4FS
3171	"/usr/bin/rsh",		/* restricted Bourne shell */
3172	"/usr/bin/ksh",		/* Korn shell */
3173	"/usr/bin/rksh",	/* restricted Korn shell */
3174	"/usr/bin/pam",
3175	"/usr/bin/keysh",	/* key shell (extended Korn shell) */
3176	"/usr/bin/posix/sh",
3177#  else /* V4FS */
3178	"/bin/rsh",		/* restricted Bourne shell */
3179	"/bin/ksh",		/* Korn shell */
3180	"/bin/rksh",		/* restricted Korn shell */
3181	"/bin/pam",
3182	"/usr/bin/keysh",	/* key shell (extended Korn shell) */
3183	"/bin/posix/sh",
3184	"/sbin/sh",
3185#  endif /* V4FS */
3186# endif /* __hpux */
3187# if defined(_AIX3) || defined(_AIX4)
3188	"/bin/ksh",		/* Korn shell */
3189	"/usr/bin/ksh",
3190	"/bin/tsh",		/* trusted shell */
3191	"/usr/bin/tsh",
3192	"/bin/bsh",		/* Bourne shell */
3193	"/usr/bin/bsh",
3194# endif /* defined(_AIX3) || defined(_AIX4) */
3195# if defined(__svr4__) || defined(__svr5__)
3196	"/bin/ksh",		/* Korn shell */
3197	"/usr/bin/ksh",
3198# endif /* defined(__svr4__) || defined(__svr5__) */
3199# ifdef sgi
3200	"/sbin/sh",		/* SGI's shells really live in /sbin */
3201	"/usr/bin/sh",
3202	"/sbin/bsh",		/* classic Bourne shell */
3203	"/bin/bsh",
3204	"/usr/bin/bsh",
3205	"/sbin/csh",		/* standard csh */
3206	"/bin/csh",
3207	"/usr/bin/csh",
3208	"/sbin/jsh",		/* classic Bourne shell w/ job control*/
3209	"/bin/jsh",
3210	"/usr/bin/jsh",
3211	"/bin/ksh",		/* Korn shell */
3212	"/sbin/ksh",
3213	"/usr/bin/ksh",
3214	"/sbin/tcsh",		/* Extended csh */
3215	"/bin/tcsh",
3216	"/usr/bin/tcsh",
3217# endif /* sgi */
3218	NULL
3219};
3220
3221#endif /* !HASGETUSERSHELL */
3222
3223#define WILDCARD_SHELL	"/SENDMAIL/ANY/SHELL/"
3224
3225bool
3226usershellok(user, shell)
3227	char *user;
3228	char *shell;
3229{
3230# if HASGETUSERSHELL
3231	register char *p;
3232	extern char *getusershell();
3233
3234	if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
3235	    ConfigLevel <= 1)
3236		return true;
3237
3238	setusershell();
3239	while ((p = getusershell()) != NULL)
3240		if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
3241			break;
3242	endusershell();
3243	return p != NULL;
3244# else /* HASGETUSERSHELL */
3245#  if USEGETCONFATTR
3246	auto char *v;
3247#  endif
3248	register SM_FILE_T *shellf;
3249	char buf[MAXLINE];
3250
3251	if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
3252	    ConfigLevel <= 1)
3253		return true;
3254
3255#  if USEGETCONFATTR
3256	/*
3257	**  Naturally IBM has a "better" idea.....
3258	**
3259	**	What a crock.  This interface isn't documented, it is
3260	**	considered part of the security library (-ls), and it
3261	**	only works if you are running as root (since the list
3262	**	of valid shells is obviously a source of great concern).
3263	**	I recommend that you do NOT define USEGETCONFATTR,
3264	**	especially since you are going to have to set up an
3265	**	/etc/shells anyhow to handle the cases where getconfattr
3266	**	fails.
3267	*/
3268
3269	if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL)
3270	{
3271		while (*v != '\0')
3272		{
3273			if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0)
3274				return true;
3275			v += strlen(v) + 1;
3276		}
3277		return false;
3278	}
3279#  endif /* USEGETCONFATTR */
3280
3281	shellf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_SHELLS,
3282			    SM_IO_RDONLY, NULL);
3283	if (shellf == NULL)
3284	{
3285		/* no /etc/shells; see if it is one of the std shells */
3286		char **d;
3287
3288		if (errno != ENOENT && LogLevel > 3)
3289			sm_syslog(LOG_ERR, NOQID,
3290				  "usershellok: cannot open %s: %s",
3291				  _PATH_SHELLS, sm_errstring(errno));
3292
3293		for (d = DefaultUserShells; *d != NULL; d++)
3294		{
3295			if (strcmp(shell, *d) == 0)
3296				return true;
3297		}
3298		return false;
3299	}
3300
3301	while (sm_io_fgets(shellf, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
3302	{
3303		register char *p, *q;
3304
3305		p = buf;
3306		while (*p != '\0' && *p != '#' && *p != '/')
3307			p++;
3308		if (*p == '#' || *p == '\0')
3309			continue;
3310		q = p;
3311		while (*p != '\0' && *p != '#' && !(SM_ISSPACE(*p)))
3312			p++;
3313		*p = '\0';
3314		if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
3315		{
3316			(void) sm_io_close(shellf, SM_TIME_DEFAULT);
3317			return true;
3318		}
3319	}
3320	(void) sm_io_close(shellf, SM_TIME_DEFAULT);
3321	return false;
3322# endif /* HASGETUSERSHELL */
3323}
3324/*
3325**  FREEDISKSPACE -- see how much free space is on the queue filesystem
3326**
3327**	Only implemented if you have statfs.
3328**
3329**	Parameters:
3330**		dir -- the directory in question.
3331**		bsize -- a variable into which the filesystem
3332**			block size is stored.
3333**
3334**	Returns:
3335**		The number of blocks free on the queue filesystem.
3336**		-1 if the statfs call fails.
3337**
3338**	Side effects:
3339**		Puts the filesystem block size into bsize.
3340*/
3341
3342/* statfs types */
3343# define SFS_NONE	0	/* no statfs implementation */
3344# define SFS_USTAT	1	/* use ustat */
3345# define SFS_4ARGS	2	/* use four-argument statfs call */
3346# define SFS_VFS	3	/* use <sys/vfs.h> implementation */
3347# define SFS_MOUNT	4	/* use <sys/mount.h> implementation */
3348# define SFS_STATFS	5	/* use <sys/statfs.h> implementation */
3349# define SFS_STATVFS	6	/* use <sys/statvfs.h> implementation */
3350
3351# ifndef SFS_TYPE
3352#  define SFS_TYPE	SFS_NONE
3353# endif
3354
3355# if SFS_TYPE == SFS_USTAT
3356#  include <ustat.h>
3357# endif
3358# if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
3359#  include <sys/statfs.h>
3360# endif
3361# if SFS_TYPE == SFS_VFS
3362#  include <sys/vfs.h>
3363# endif
3364# if SFS_TYPE == SFS_MOUNT
3365#  include <sys/mount.h>
3366# endif
3367# if SFS_TYPE == SFS_STATVFS
3368#  include <sys/statvfs.h>
3369# endif
3370
3371long
3372freediskspace(dir, bsize)
3373	const char *dir;
3374	long *bsize;
3375{
3376# if SFS_TYPE == SFS_NONE
3377	if (bsize != NULL)
3378		*bsize = 4096L;
3379
3380	/* assume free space is plentiful */
3381	return (long) LONG_MAX;
3382# else /* SFS_TYPE == SFS_NONE */
3383#  if SFS_TYPE == SFS_USTAT
3384	struct ustat fs;
3385	struct stat statbuf;
3386#   define FSBLOCKSIZE	DEV_BSIZE
3387#   define SFS_BAVAIL	f_tfree
3388#  else /* SFS_TYPE == SFS_USTAT */
3389#   if defined(ultrix)
3390	struct fs_data fs;
3391#    define SFS_BAVAIL	fd_bfreen
3392#    define FSBLOCKSIZE	1024L
3393#   else /* defined(ultrix) */
3394#    if SFS_TYPE == SFS_STATVFS
3395	struct statvfs fs;
3396#     define FSBLOCKSIZE	fs.f_frsize
3397#    else /* SFS_TYPE == SFS_STATVFS */
3398	struct statfs fs;
3399#     define FSBLOCKSIZE	fs.f_bsize
3400#    endif /* SFS_TYPE == SFS_STATVFS */
3401#   endif /* defined(ultrix) */
3402#  endif /* SFS_TYPE == SFS_USTAT */
3403#  ifndef SFS_BAVAIL
3404#   define SFS_BAVAIL f_bavail
3405#  endif
3406
3407#  if SFS_TYPE == SFS_USTAT
3408	if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
3409#  else /* SFS_TYPE == SFS_USTAT */
3410#   if SFS_TYPE == SFS_4ARGS
3411	if (statfs(dir, &fs, sizeof(fs), 0) == 0)
3412#   else /* SFS_TYPE == SFS_4ARGS */
3413#    if SFS_TYPE == SFS_STATVFS
3414	if (statvfs(dir, &fs) == 0)
3415#    else /* SFS_TYPE == SFS_STATVFS */
3416#     if defined(ultrix)
3417	if (statfs(dir, &fs) > 0)
3418#     else /* defined(ultrix) */
3419	if (statfs(dir, &fs) == 0)
3420#     endif /* defined(ultrix) */
3421#    endif /* SFS_TYPE == SFS_STATVFS */
3422#   endif /* SFS_TYPE == SFS_4ARGS */
3423#  endif /* SFS_TYPE == SFS_USTAT */
3424	{
3425		if (bsize != NULL)
3426			*bsize = FSBLOCKSIZE;
3427		if (fs.SFS_BAVAIL <= 0)
3428			return 0;
3429		else if (fs.SFS_BAVAIL > LONG_MAX)
3430			return (long) LONG_MAX;
3431		else
3432			return (long) fs.SFS_BAVAIL;
3433	}
3434	return -1;
3435# endif /* SFS_TYPE == SFS_NONE */
3436}
3437/*
3438**  ENOUGHDISKSPACE -- is there enough free space on the queue file systems?
3439**
3440**	Parameters:
3441**		msize -- the size to check against.  If zero, we don't yet
3442**		know how big the message will be, so just check for
3443**		a "reasonable" amount.
3444**		e -- envelope, or NULL -- controls logging
3445**
3446**	Returns:
3447**		true if in every queue group there is at least one
3448**		queue directory whose file system contains enough free space.
3449**		false otherwise.
3450**
3451**	Side Effects:
3452**		If there is not enough disk space and e != NULL
3453**		then sm_syslog is called.
3454*/
3455
3456bool
3457enoughdiskspace(msize, e)
3458	long msize;
3459	ENVELOPE *e;
3460{
3461	int i;
3462
3463#if _FFR_TESTS
3464	if (tTd(4, 101))
3465		return false;
3466#endif
3467	if (MinBlocksFree <= 0 && msize <= 0)
3468	{
3469		if (tTd(4, 80))
3470			sm_dprintf("enoughdiskspace: no threshold\n");
3471		return true;
3472	}
3473
3474	filesys_update();
3475	for (i = 0; i < NumQueue; ++i)
3476	{
3477		if (pickqdir(Queue[i], msize, e) < 0)
3478			return false;
3479	}
3480	return true;
3481}
3482/*
3483**  TRANSIENTERROR -- tell if an error code indicates a transient failure
3484**
3485**	This looks at an errno value and tells if this is likely to
3486**	go away if retried later.
3487**
3488**	Parameters:
3489**		err -- the errno code to classify.
3490**
3491**	Returns:
3492**		true if this is probably transient.
3493**		false otherwise.
3494*/
3495
3496bool
3497transienterror(err)
3498	int err;
3499{
3500	switch (err)
3501	{
3502	  case EIO:			/* I/O error */
3503	  case ENXIO:			/* Device not configured */
3504	  case EAGAIN:			/* Resource temporarily unavailable */
3505	  case ENOMEM:			/* Cannot allocate memory */
3506	  case ENODEV:			/* Operation not supported by device */
3507	  case ENFILE:			/* Too many open files in system */
3508	  case EMFILE:			/* Too many open files */
3509	  case ENOSPC:			/* No space left on device */
3510	  case ETIMEDOUT:		/* Connection timed out */
3511#ifdef ESTALE
3512	  case ESTALE:			/* Stale NFS file handle */
3513#endif
3514#ifdef ENETDOWN
3515	  case ENETDOWN:		/* Network is down */
3516#endif
3517#ifdef ENETUNREACH
3518	  case ENETUNREACH:		/* Network is unreachable */
3519#endif
3520#ifdef ENETRESET
3521	  case ENETRESET:		/* Network dropped connection on reset */
3522#endif
3523#ifdef ECONNABORTED
3524	  case ECONNABORTED:		/* Software caused connection abort */
3525#endif
3526#ifdef ECONNRESET
3527	  case ECONNRESET:		/* Connection reset by peer */
3528#endif
3529#ifdef ENOBUFS
3530	  case ENOBUFS:			/* No buffer space available */
3531#endif
3532#ifdef ESHUTDOWN
3533	  case ESHUTDOWN:		/* Can't send after socket shutdown */
3534#endif
3535#ifdef ECONNREFUSED
3536	  case ECONNREFUSED:		/* Connection refused */
3537#endif
3538#ifdef EHOSTDOWN
3539	  case EHOSTDOWN:		/* Host is down */
3540#endif
3541#ifdef EHOSTUNREACH
3542	  case EHOSTUNREACH:		/* No route to host */
3543#endif
3544#ifdef EDQUOT
3545	  case EDQUOT:			/* Disc quota exceeded */
3546#endif
3547#ifdef EPROCLIM
3548	  case EPROCLIM:		/* Too many processes */
3549#endif
3550#ifdef EUSERS
3551	  case EUSERS:			/* Too many users */
3552#endif
3553#ifdef EDEADLK
3554	  case EDEADLK:			/* Resource deadlock avoided */
3555#endif
3556#ifdef EISCONN
3557	  case EISCONN:			/* Socket already connected */
3558#endif
3559#ifdef EINPROGRESS
3560	  case EINPROGRESS:		/* Operation now in progress */
3561#endif
3562#ifdef EALREADY
3563	  case EALREADY:		/* Operation already in progress */
3564#endif
3565#ifdef EADDRINUSE
3566	  case EADDRINUSE:		/* Address already in use */
3567#endif
3568#ifdef EADDRNOTAVAIL
3569	  case EADDRNOTAVAIL:		/* Can't assign requested address */
3570#endif
3571#ifdef ETXTBSY
3572	  case ETXTBSY:			/* (Apollo) file locked */
3573#endif
3574#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
3575	  case ENOSR:			/* Out of streams resources */
3576#endif
3577#ifdef ENOLCK
3578	  case ENOLCK:			/* No locks available */
3579#endif
3580	  case E_SM_OPENTIMEOUT:	/* PSEUDO: open timed out */
3581		return true;
3582	}
3583
3584	/* nope, must be permanent */
3585	return false;
3586}
3587/*
3588**  LOCKFILE -- lock a file using flock or (shudder) fcntl locking
3589**
3590**	Parameters:
3591**		fd -- the file descriptor of the file.
3592**		filename -- the file name (for error messages).
3593**		ext -- the filename extension.
3594**		type -- type of the lock.  Bits can be:
3595**			LOCK_EX -- exclusive lock.
3596**			LOCK_NB -- non-blocking.
3597**			LOCK_UN -- unlock.
3598**
3599**	Returns:
3600**		true if the lock was acquired.
3601**		false otherwise.
3602*/
3603
3604bool
3605lockfile(fd, filename, ext, type)
3606	int fd;
3607	char *filename;
3608	char *ext;
3609	int type;
3610{
3611	int i;
3612	int save_errno;
3613# if !HASFLOCK
3614	int action;
3615	struct flock lfd;
3616
3617	if (ext == NULL)
3618		ext = "";
3619
3620	memset(&lfd, '\0', sizeof(lfd));
3621	if (bitset(LOCK_UN, type))
3622		lfd.l_type = F_UNLCK;
3623	else if (bitset(LOCK_EX, type))
3624		lfd.l_type = F_WRLCK;
3625	else
3626		lfd.l_type = F_RDLCK;
3627
3628	if (bitset(LOCK_NB, type))
3629		action = F_SETLK;
3630	else
3631		action = F_SETLKW;
3632
3633	if (tTd(55, 60))
3634		sm_dprintf("lockfile(%s%s, action=%d, type=%d): ",
3635			filename, ext, action, lfd.l_type);
3636
3637	while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
3638		continue;
3639	if (i >= 0)
3640	{
3641		if (tTd(55, 60))
3642			sm_dprintf("SUCCESS\n");
3643		return true;
3644	}
3645	save_errno = errno;
3646
3647	if (tTd(55, 60))
3648		sm_dprintf("(%s) ", sm_errstring(save_errno));
3649
3650	/*
3651	**  On SunOS, if you are testing using -oQ/tmp/mqueue or
3652	**  -oA/tmp/aliases or anything like that, and /tmp is mounted
3653	**  as type "tmp" (that is, served from swap space), the
3654	**  previous fcntl will fail with "Invalid argument" errors.
3655	**  Since this is fairly common during testing, we will assume
3656	**  that this indicates that the lock is successfully grabbed.
3657	*/
3658
3659	if (save_errno == EINVAL)
3660	{
3661		if (tTd(55, 60))
3662			sm_dprintf("SUCCESS\n");
3663		return true;
3664	}
3665
3666	if (!bitset(LOCK_NB, type) ||
3667	    (save_errno != EACCES && save_errno != EAGAIN))
3668	{
3669		int omode = fcntl(fd, F_GETFL, 0);
3670		uid_t euid = geteuid();
3671
3672		errno = save_errno;
3673		syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)",
3674		       filename, ext, fd, type, omode, (long) euid);
3675		dumpfd(fd, true, true);
3676	}
3677# else /* !HASFLOCK */
3678	if (ext == NULL)
3679		ext = "";
3680
3681	if (tTd(55, 60))
3682		sm_dprintf("lockfile(%s%s, type=%o): ", filename, ext, type);
3683
3684	while ((i = flock(fd, type)) < 0 && errno == EINTR)
3685		continue;
3686	if (i >= 0)
3687	{
3688		if (tTd(55, 60))
3689			sm_dprintf("SUCCESS\n");
3690		return true;
3691	}
3692	save_errno = errno;
3693
3694	if (tTd(55, 60))
3695		sm_dprintf("(%s) ", sm_errstring(save_errno));
3696
3697	if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK)
3698	{
3699		int omode = fcntl(fd, F_GETFL, 0);
3700		uid_t euid = geteuid();
3701
3702		errno = save_errno;
3703		syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)",
3704			filename, ext, fd, type, omode, (long) euid);
3705		dumpfd(fd, true, true);
3706	}
3707# endif /* !HASFLOCK */
3708	if (tTd(55, 60))
3709		sm_dprintf("FAIL\n");
3710	errno = save_errno;
3711	return false;
3712}
3713/*
3714**  CHOWNSAFE -- tell if chown is "safe" (executable only by root)
3715**
3716**	Unfortunately, given that we can't predict other systems on which
3717**	a remote mounted (NFS) filesystem will be mounted, the answer is
3718**	almost always that this is unsafe.
3719**
3720**	Note also that many operating systems have non-compliant
3721**	implementations of the _POSIX_CHOWN_RESTRICTED variable and the
3722**	fpathconf() routine.  According to IEEE 1003.1-1990, if
3723**	_POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then
3724**	no non-root process can give away the file.  However, vendors
3725**	don't take NFS into account, so a comfortable value of
3726**	_POSIX_CHOWN_RESTRICTED tells us nothing.
3727**
3728**	Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf()
3729**	even on files where chown is not restricted.  Many systems get
3730**	this wrong on NFS-based filesystems (that is, they say that chown
3731**	is restricted [safe] on NFS filesystems where it may not be, since
3732**	other systems can access the same filesystem and do file giveaway;
3733**	only the NFS server knows for sure!)  Hence, it is important to
3734**	get the value of SAFENFSPATHCONF correct -- it should be defined
3735**	_only_ after testing (see test/t_pathconf.c) a system on an unsafe
3736**	NFS-based filesystem to ensure that you can get meaningful results.
3737**	If in doubt, assume unsafe!
3738**
3739**	You may also need to tweak IS_SAFE_CHOWN -- it should be a
3740**	condition indicating whether the return from pathconf indicates
3741**	that chown is safe (typically either > 0 or >= 0 -- there isn't
3742**	even any agreement about whether a zero return means that a file
3743**	is or is not safe).  It defaults to "> 0".
3744**
3745**	If the parent directory is safe (writable only by owner back
3746**	to the root) then we can relax slightly and trust fpathconf
3747**	in more circumstances.  This is really a crock -- if this is an
3748**	NFS mounted filesystem then we really know nothing about the
3749**	underlying implementation.  However, most systems pessimize and
3750**	return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which
3751**	we interpret as unsafe, as we should.  Thus, this heuristic gets
3752**	us into a possible problem only on systems that have a broken
3753**	pathconf implementation and which are also poorly configured
3754**	(have :include: files in group- or world-writable directories).
3755**
3756**	Parameters:
3757**		fd -- the file descriptor to check.
3758**		safedir -- set if the parent directory is safe.
3759**
3760**	Returns:
3761**		true -- if the chown(2) operation is "safe" -- that is,
3762**			only root can chown the file to an arbitrary user.
3763**		false -- if an arbitrary user can give away a file.
3764*/
3765
3766#ifndef IS_SAFE_CHOWN
3767# define IS_SAFE_CHOWN	> 0
3768#endif
3769
3770bool
3771chownsafe(fd, safedir)
3772	int fd;
3773	bool safedir;
3774{
3775# if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \
3776    (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H))
3777	int rval;
3778
3779	/* give the system administrator a chance to override */
3780	if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail))
3781		return true;
3782
3783	/*
3784	**  Some systems (e.g., SunOS) seem to have the call and the
3785	**  #define _PC_CHOWN_RESTRICTED, but don't actually implement
3786	**  the call.  This heuristic checks for that.
3787	*/
3788
3789	errno = 0;
3790	rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
3791#  if SAFENFSPATHCONF
3792	return errno == 0 && rval IS_SAFE_CHOWN;
3793#  else
3794	return safedir && errno == 0 && rval IS_SAFE_CHOWN;
3795#  endif
3796# else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */
3797	return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail);
3798# endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */
3799}
3800/*
3801**  RESETLIMITS -- reset system controlled resource limits
3802**
3803**	This is to avoid denial-of-service attacks
3804**
3805**	Parameters:
3806**		none
3807**
3808**	Returns:
3809**		none
3810*/
3811
3812#if HASSETRLIMIT
3813# ifdef RLIMIT_NEEDS_SYS_TIME_H
3814#  include <sm/time.h>
3815# endif
3816# include <sys/resource.h>
3817#endif /* HASSETRLIMIT */
3818
3819void
3820resetlimits()
3821{
3822#if HASSETRLIMIT
3823	struct rlimit lim;
3824
3825	lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
3826	(void) setrlimit(RLIMIT_CPU, &lim);
3827	(void) setrlimit(RLIMIT_FSIZE, &lim);
3828# ifdef RLIMIT_NOFILE
3829	lim.rlim_cur = lim.rlim_max = FD_SETSIZE;
3830	(void) setrlimit(RLIMIT_NOFILE, &lim);
3831# endif
3832#else /* HASSETRLIMIT */
3833# if HASULIMIT
3834	(void) ulimit(2, 0x3fffff);
3835	(void) ulimit(4, FD_SETSIZE);
3836# endif
3837#endif /* HASSETRLIMIT */
3838	errno = 0;
3839}
3840/*
3841**  SETVENDOR -- process vendor code from V configuration line
3842**
3843**	Parameters:
3844**		vendor -- string representation of vendor.
3845**
3846**	Returns:
3847**		true -- if ok.
3848**		false -- if vendor code could not be processed.
3849**
3850**	Side Effects:
3851**		It is reasonable to set mode flags here to tweak
3852**		processing in other parts of the code if necessary.
3853**		For example, if you are a vendor that uses $%y to
3854**		indicate YP lookups, you could enable that here.
3855*/
3856
3857bool
3858setvendor(vendor)
3859	char *vendor;
3860{
3861	if (sm_strcasecmp(vendor, "Berkeley") == 0)
3862	{
3863		VendorCode = VENDOR_BERKELEY;
3864		return true;
3865	}
3866
3867	/* add vendor extensions here */
3868
3869#ifdef SUN_EXTENSIONS
3870	if (sm_strcasecmp(vendor, "Sun") == 0)
3871	{
3872		VendorCode = VENDOR_SUN;
3873		return true;
3874	}
3875#endif /* SUN_EXTENSIONS */
3876#ifdef DEC
3877	if (sm_strcasecmp(vendor, "Digital") == 0)
3878	{
3879		VendorCode = VENDOR_DEC;
3880		return true;
3881	}
3882#endif /* DEC */
3883
3884#if defined(VENDOR_NAME) && defined(VENDOR_CODE)
3885	if (sm_strcasecmp(vendor, VENDOR_NAME) == 0)
3886	{
3887		VendorCode = VENDOR_CODE;
3888		return true;
3889	}
3890#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
3891
3892	return false;
3893}
3894/*
3895**  GETVENDOR -- return vendor name based on vendor code
3896**
3897**	Parameters:
3898**		vendorcode -- numeric representation of vendor.
3899**
3900**	Returns:
3901**		string containing vendor name.
3902*/
3903
3904char *
3905getvendor(vendorcode)
3906	int vendorcode;
3907{
3908#if defined(VENDOR_NAME) && defined(VENDOR_CODE)
3909	/*
3910	**  Can't have the same switch case twice so need to
3911	**  handle VENDOR_CODE outside of switch.  It might
3912	**  match one of the existing VENDOR_* codes.
3913	*/
3914
3915	if (vendorcode == VENDOR_CODE)
3916		return VENDOR_NAME;
3917#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
3918
3919	switch (vendorcode)
3920	{
3921	  case VENDOR_BERKELEY:
3922		return "Berkeley";
3923
3924	  case VENDOR_SUN:
3925		return "Sun";
3926
3927	  case VENDOR_HP:
3928		return "HP";
3929
3930	  case VENDOR_IBM:
3931		return "IBM";
3932
3933	  case VENDOR_SENDMAIL:
3934		return "Sendmail";
3935
3936	  default:
3937		return "Unknown";
3938	}
3939}
3940/*
3941**  VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults
3942**
3943**	Vendor_pre_defaults is called before reading the configuration
3944**	file; vendor_post_defaults is called immediately after.
3945**
3946**	Parameters:
3947**		e -- the global environment to initialize.
3948**
3949**	Returns:
3950**		none.
3951*/
3952
3953#if SHARE_V1
3954int	DefShareUid;	/* default share uid to run as -- unused??? */
3955#endif
3956
3957void
3958vendor_pre_defaults(e)
3959	ENVELOPE *e;
3960{
3961#if SHARE_V1
3962	/* OTHERUID is defined in shares.h, do not be alarmed */
3963	DefShareUid = OTHERUID;
3964#endif
3965#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
3966	sun_pre_defaults(e);
3967#endif
3968#ifdef apollo
3969	/*
3970	**  stupid domain/os can't even open
3971	**  /etc/mail/sendmail.cf without this
3972	*/
3973
3974	sm_setuserenv("ISP", NULL);
3975	sm_setuserenv("SYSTYPE", NULL);
3976#endif /* apollo */
3977}
3978
3979
3980void
3981vendor_post_defaults(e)
3982	ENVELOPE *e;
3983{
3984#ifdef __QNX__
3985	/* Makes sure the SOCK environment variable remains */
3986	sm_setuserenv("SOCK", NULL);
3987#endif
3988#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
3989	sun_post_defaults(e);
3990#endif
3991}
3992/*
3993**  VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode
3994*/
3995
3996void
3997vendor_daemon_setup(e)
3998	ENVELOPE *e;
3999{
4000#if HASSETLOGIN
4001	(void) setlogin(RunAsUserName);
4002#endif
4003#if SECUREWARE
4004	if (getluid() != -1)
4005	{
4006		usrerr("Daemon cannot have LUID");
4007		finis(false, true, EX_USAGE);
4008	}
4009#endif /* SECUREWARE */
4010}
4011/*
4012**  VENDOR_SET_UID -- do setup for setting a user id
4013**
4014**	This is called when we are still root.
4015**
4016**	Parameters:
4017**		uid -- the uid we are about to become.
4018**
4019**	Returns:
4020**		none.
4021*/
4022
4023void
4024vendor_set_uid(uid)
4025	UID_T uid;
4026{
4027	/*
4028	**  We need to setup the share groups (lnodes)
4029	**  and add auditing information (luid's)
4030	**  before we loose our ``root''ness.
4031	*/
4032#if SHARE_V1
4033	if (setupshares(uid, syserr) != 0)
4034		syserr("Unable to set up shares");
4035#endif
4036#if SECUREWARE
4037	(void) setup_secure(uid);
4038#endif
4039}
4040/*
4041**  VALIDATE_CONNECTION -- check connection for rationality
4042**
4043**	If the connection is rejected, this routine should log an
4044**	appropriate message -- but should never issue any SMTP protocol.
4045**
4046**	Parameters:
4047**		sap -- a pointer to a SOCKADDR naming the peer.
4048**		hostname -- the name corresponding to sap.
4049**		e -- the current envelope.
4050**
4051**	Returns:
4052**		error message from rejection.
4053**		NULL if not rejected.
4054*/
4055
4056#if TCPWRAPPERS
4057# include <tcpd.h>
4058
4059/* tcpwrappers does no logging, but you still have to declare these -- ugh */
4060int	allow_severity	= LOG_INFO;
4061int	deny_severity	= LOG_NOTICE;
4062#endif /* TCPWRAPPERS */
4063
4064char *
4065validate_connection(sap, hostname, e)
4066	SOCKADDR *sap;
4067	char *hostname;
4068	ENVELOPE *e;
4069{
4070#if TCPWRAPPERS
4071	char *host;
4072	char *addr;
4073	extern int hosts_ctl();
4074#endif /* TCPWRAPPERS */
4075
4076	if (tTd(48, 3))
4077		sm_dprintf("validate_connection(%s, %s)\n",
4078			hostname, anynet_ntoa(sap));
4079
4080	connection_rate_check(sap, e);
4081	if (rscheck("check_relay", hostname, anynet_ntoa(sap), e,
4082		    RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID, NULL, NULL) != EX_OK)
4083	{
4084		static char reject[BUFSIZ*2];
4085		extern char MsgBuf[];
4086
4087		if (tTd(48, 4))
4088			sm_dprintf("  ... validate_connection: BAD (rscheck)\n");
4089
4090		if (strlen(MsgBuf) >= 3)
4091			(void) sm_strlcpy(reject, MsgBuf, sizeof(reject));
4092		else
4093			(void) sm_strlcpy(reject, "Access denied", sizeof(reject));
4094
4095		return reject;
4096	}
4097
4098#if TCPWRAPPERS
4099	if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']')
4100		host = "unknown";
4101	else
4102		host = hostname;
4103	addr = anynet_ntoa(sap);
4104
4105# if NETINET6
4106	/* TCP/Wrappers don't want the IPv6: protocol label */
4107	if (addr != NULL && sm_strncasecmp(addr, "IPv6:", 5) == 0)
4108		addr += 5;
4109# endif /* NETINET6 */
4110
4111	if (!hosts_ctl("sendmail", host, addr, STRING_UNKNOWN))
4112	{
4113		if (tTd(48, 4))
4114			sm_dprintf("  ... validate_connection: BAD (tcpwrappers)\n");
4115		if (LogLevel > 3)
4116			sm_syslog(LOG_NOTICE, e->e_id,
4117				  "tcpwrappers (%s, %s) rejection",
4118				  host, addr);
4119		return "Access denied";
4120	}
4121#endif /* TCPWRAPPERS */
4122	if (tTd(48, 4))
4123		sm_dprintf("  ... validate_connection: OK\n");
4124	return NULL;
4125}
4126
4127/*
4128**  STRTOL -- convert string to long integer
4129**
4130**	For systems that don't have it in the C library.
4131**
4132**	This is taken verbatim from the 4.4-Lite C library.
4133*/
4134
4135#if NEEDSTRTOL
4136
4137# if defined(LIBC_SCCS) && !defined(lint)
4138static char sccsid[] = "@(#)strtol.c	8.1 (Berkeley) 6/4/93";
4139# endif
4140
4141/*
4142**  Convert a string to a long integer.
4143**
4144**  Ignores `locale' stuff.  Assumes that the upper and lower case
4145**  alphabets and digits are each contiguous.
4146*/
4147
4148long
4149strtol(nptr, endptr, base)
4150	const char *nptr;
4151	char **endptr;
4152	register int base;
4153{
4154	register const char *s = nptr;
4155	register unsigned long acc;
4156	register int c;
4157	register unsigned long cutoff;
4158	register int neg = 0, any, cutlim;
4159
4160	/*
4161	**  Skip white space and pick up leading +/- sign if any.
4162	**  If base is 0, allow 0x for hex and 0 for octal, else
4163	**  assume decimal; if base is already 16, allow 0x.
4164	*/
4165	do {
4166		c = *s++;
4167	} while (SM_ISSPACE(c));
4168	if (c == '-') {
4169		neg = 1;
4170		c = *s++;
4171	} else if (c == '+')
4172		c = *s++;
4173	if ((base == 0 || base == 16) &&
4174	    c == '0' && (*s == 'x' || *s == 'X')) {
4175		c = s[1];
4176		s += 2;
4177		base = 16;
4178	}
4179	if (base == 0)
4180		base = c == '0' ? 8 : 10;
4181
4182	/*
4183	**  Compute the cutoff value between legal numbers and illegal
4184	**  numbers.  That is the largest legal value, divided by the
4185	**  base.  An input number that is greater than this value, if
4186	**  followed by a legal input character, is too big.  One that
4187	**  is equal to this value may be valid or not; the limit
4188	**  between valid and invalid numbers is then based on the last
4189	**  digit.  For instance, if the range for longs is
4190	**  [-2147483648..2147483647] and the input base is 10,
4191	**  cutoff will be set to 214748364 and cutlim to either
4192	**  7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
4193	**  a value > 214748364, or equal but the next digit is > 7 (or 8),
4194	**  the number is too big, and we will return a range error.
4195	**
4196	**  Set any if any `digits' consumed; make it negative to indicate
4197	**  overflow.
4198	*/
4199	cutoff = neg ? -(unsigned long) LONG_MIN : LONG_MAX;
4200	cutlim = cutoff % (unsigned long) base;
4201	cutoff /= (unsigned long) base;
4202	for (acc = 0, any = 0;; c = *s++) {
4203		if (isascii(c) && isdigit(c))
4204			c -= '0';
4205		else if (isascii(c) && isalpha(c))
4206			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
4207		else
4208			break;
4209		if (c >= base)
4210			break;
4211		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
4212			any = -1;
4213		else {
4214			any = 1;
4215			acc *= base;
4216			acc += c;
4217		}
4218	}
4219	if (any < 0) {
4220		acc = neg ? LONG_MIN : LONG_MAX;
4221		errno = ERANGE;
4222	} else if (neg)
4223		acc = -acc;
4224	if (endptr != NULL)
4225		*endptr = (char *)(any ? s - 1 : nptr);
4226	return acc;
4227}
4228
4229#endif /* NEEDSTRTOL */
4230/*
4231**  STRSTR -- find first substring in string
4232**
4233**	Parameters:
4234**		big -- the big (full) string.
4235**		little -- the little (sub) string.
4236**
4237**	Returns:
4238**		A pointer to the first instance of little in big.
4239**		big if little is the null string.
4240**		NULL if little is not contained in big.
4241*/
4242
4243#if NEEDSTRSTR
4244
4245char *
4246strstr(big, little)
4247	char *big;
4248	char *little;
4249{
4250	register char *p = big;
4251	int l;
4252
4253	if (*little == '\0')
4254		return big;
4255	l = strlen(little);
4256
4257	while ((p = strchr(p, *little)) != NULL)
4258	{
4259		if (strncmp(p, little, l) == 0)
4260			return p;
4261		p++;
4262	}
4263	return NULL;
4264}
4265
4266#endif /* NEEDSTRSTR */
4267/*
4268**  SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
4269**
4270**	Some operating systems have weird problems with the gethostbyXXX
4271**	routines.  For example, Solaris versions at least through 2.3
4272**	don't properly deliver a canonical h_name field.  This tries to
4273**	work around these problems.
4274**
4275**	Support IPv6 as well as IPv4.
4276*/
4277
4278#if NETINET6 && NEEDSGETIPNODE
4279
4280# ifndef AI_DEFAULT
4281#  define AI_DEFAULT	0	/* dummy */
4282# endif
4283# ifndef AI_ADDRCONFIG
4284#  define AI_ADDRCONFIG	0	/* dummy */
4285# endif
4286# ifndef AI_V4MAPPED
4287#  define AI_V4MAPPED	0	/* dummy */
4288# endif
4289# ifndef AI_ALL
4290#  define AI_ALL	0	/* dummy */
4291# endif
4292
4293static struct hostent *
4294sm_getipnodebyname(name, family, flags, err)
4295	const char *name;
4296	int family;
4297	int flags;
4298	int *err;
4299{
4300	struct hostent *h;
4301# if HAS_GETHOSTBYNAME2
4302
4303	h = gethostbyname2(name, family);
4304	if (h == NULL)
4305		*err = h_errno;
4306	return h;
4307
4308# else /* HAS_GETHOSTBYNAME2 */
4309#  ifdef RES_USE_INET6
4310	bool resv6 = true;
4311
4312	if (family == AF_INET6)
4313	{
4314		/* From RFC2133, section 6.1 */
4315		resv6 = bitset(RES_USE_INET6, _res.options);
4316		_res.options |= RES_USE_INET6;
4317	}
4318#  endif /* RES_USE_INET6 */
4319	SM_SET_H_ERRNO(0);
4320	h = gethostbyname(name);
4321#  ifdef RES_USE_INET6
4322	if (!resv6)
4323		_res.options &= ~RES_USE_INET6;
4324#  endif
4325
4326	/* the function is supposed to return only the requested family */
4327	if (h != NULL && h->h_addrtype != family)
4328	{
4329#  if NETINET6
4330		freehostent(h);
4331#  endif
4332		h = NULL;
4333		*err = NO_DATA;
4334	}
4335	else
4336		*err = h_errno;
4337	return h;
4338# endif /* HAS_GETHOSTBYNAME2 */
4339}
4340
4341static struct hostent *
4342sm_getipnodebyaddr(addr, len, family, err)
4343	const void *addr;
4344	size_t len;
4345	int family;
4346	int *err;
4347{
4348	struct hostent *h;
4349
4350	SM_SET_H_ERRNO(0);
4351	h = gethostbyaddr(addr, len, family);
4352	*err = h_errno;
4353	return h;
4354}
4355
4356void
4357freehostent(h)
4358	struct hostent *h;
4359{
4360	/*
4361	**  Stub routine -- if they don't have getipnodeby*(),
4362	**  they probably don't have the free routine either.
4363	*/
4364
4365	return;
4366}
4367#endif /* NETINET6 && NEEDSGETIPNODE */
4368
4369struct hostent *
4370sm_gethostbyname(name, family)
4371	char *name;
4372	int family;
4373{
4374	int save_errno;
4375	struct hostent *h = NULL;
4376#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
4377# if SOLARIS == 20300 || SOLARIS == 203
4378	static struct hostent hp;
4379	static char buf[1000];
4380	extern struct hostent *_switch_gethostbyname_r();
4381
4382	if (tTd(61, 10))
4383		sm_dprintf("_switch_gethostbyname_r(%s)... ", name);
4384	h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
4385	save_errno = errno;
4386# else /* SOLARIS == 20300 || SOLARIS == 203 */
4387	extern struct hostent *__switch_gethostbyname();
4388
4389	if (tTd(61, 10))
4390		sm_dprintf("__switch_gethostbyname(%s)... ", name);
4391	h = __switch_gethostbyname(name);
4392	save_errno = errno;
4393# endif /* SOLARIS == 20300 || SOLARIS == 203 */
4394#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
4395	int nmaps;
4396# if NETINET6
4397#  ifndef SM_IPNODEBYNAME_FLAGS
4398    /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */
4399#   define SM_IPNODEBYNAME_FLAGS	AI_ADDRCONFIG
4400#  endif
4401
4402	int flags = SM_IPNODEBYNAME_FLAGS;
4403	int err;
4404# endif /* NETINET6 */
4405	char *maptype[MAXMAPSTACK];
4406	short mapreturn[MAXMAPACTIONS];
4407	char hbuf[MAXNAME];
4408
4409	if (tTd(61, 10))
4410		sm_dprintf("sm_gethostbyname(%s, %d)... ", name, family);
4411
4412# if NETINET6
4413#  if ADDRCONFIG_IS_BROKEN
4414	flags &= ~AI_ADDRCONFIG;
4415#  endif
4416	h = sm_getipnodebyname(name, family, flags, &err);
4417	SM_SET_H_ERRNO(err);
4418# else /* NETINET6 */
4419	h = gethostbyname(name);
4420# endif /* NETINET6 */
4421
4422	save_errno = errno;
4423	if (h == NULL)
4424	{
4425		if (tTd(61, 10))
4426			sm_dprintf("failure\n");
4427
4428		nmaps = switch_map_find("hosts", maptype, mapreturn);
4429		while (--nmaps >= 0)
4430		{
4431			if (strcmp(maptype[nmaps], "nis") == 0 ||
4432			    strcmp(maptype[nmaps], "files") == 0)
4433				break;
4434		}
4435
4436		if (nmaps >= 0)
4437		{
4438			/* try short name */
4439			if (strlen(name) > sizeof(hbuf) - 1)
4440			{
4441				errno = save_errno;
4442				return NULL;
4443			}
4444			(void) sm_strlcpy(hbuf, name, sizeof(hbuf));
4445			(void) shorten_hostname(hbuf);
4446
4447			/* if it hasn't been shortened, there's no point */
4448			if (strcmp(hbuf, name) != 0)
4449			{
4450				if (tTd(61, 10))
4451					sm_dprintf("sm_gethostbyname(%s, %d)... ",
4452					       hbuf, family);
4453
4454# if NETINET6
4455				h = sm_getipnodebyname(hbuf, family, flags, &err);
4456				SM_SET_H_ERRNO(err);
4457				save_errno = errno;
4458# else /* NETINET6 */
4459				h = gethostbyname(hbuf);
4460				save_errno = errno;
4461# endif /* NETINET6 */
4462			}
4463		}
4464	}
4465#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
4466
4467	/* the function is supposed to return only the requested family */
4468	if (h != NULL && h->h_addrtype != family)
4469	{
4470# if NETINET6
4471		freehostent(h);
4472# endif
4473		h = NULL;
4474		SM_SET_H_ERRNO(NO_DATA);
4475	}
4476
4477	if (tTd(61, 10))
4478	{
4479		if (h == NULL)
4480			sm_dprintf("failure\n");
4481		else
4482		{
4483			sm_dprintf("%s\n", h->h_name);
4484			if (tTd(61, 11))
4485			{
4486				struct in_addr ia;
4487				size_t i;
4488#if NETINET6
4489				struct in6_addr ia6;
4490				char buf6[INET6_ADDRSTRLEN];
4491#endif
4492
4493				if (h->h_aliases != NULL)
4494					for (i = 0; h->h_aliases[i] != NULL;
4495					     i++)
4496						sm_dprintf("\talias: %s\n",
4497							h->h_aliases[i]);
4498				for (i = 0; h->h_addr_list[i] != NULL; i++)
4499				{
4500					char *addr;
4501
4502					addr = NULL;
4503#if NETINET6
4504					if (h->h_addrtype == AF_INET6)
4505					{
4506						memmove(&ia6, h->h_addr_list[i],
4507							IN6ADDRSZ);
4508						addr = anynet_ntop(&ia6,
4509							buf6, sizeof(buf6));
4510					}
4511					else
4512#endif /* NETINET6 */
4513					/* "else" in #if code above */
4514					{
4515						memmove(&ia, h->h_addr_list[i],
4516							INADDRSZ);
4517						addr = (char *) inet_ntoa(ia);
4518					}
4519					if (addr != NULL)
4520						sm_dprintf("\taddr: %s\n", addr);
4521				}
4522			}
4523		}
4524	}
4525	errno = save_errno;
4526	return h;
4527}
4528
4529struct hostent *
4530sm_gethostbyaddr(addr, len, type)
4531	char *addr;
4532	int len;
4533	int type;
4534{
4535	struct hostent *hp;
4536
4537#if NETINET6
4538	if (type == AF_INET6 &&
4539	    IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *) addr))
4540	{
4541		/* Avoid reverse lookup for IPv6 unspecified address */
4542		SM_SET_H_ERRNO(HOST_NOT_FOUND);
4543		return NULL;
4544	}
4545#endif /* NETINET6 */
4546
4547#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204)
4548# if SOLARIS == 20300 || SOLARIS == 203
4549	{
4550		static struct hostent he;
4551		static char buf[1000];
4552		extern struct hostent *_switch_gethostbyaddr_r();
4553
4554		hp = _switch_gethostbyaddr_r(addr, len, type, &he,
4555					     buf, sizeof(buf), &h_errno);
4556	}
4557# else /* SOLARIS == 20300 || SOLARIS == 203 */
4558	{
4559		extern struct hostent *__switch_gethostbyaddr();
4560
4561		hp = __switch_gethostbyaddr(addr, len, type);
4562	}
4563# endif /* SOLARIS == 20300 || SOLARIS == 203 */
4564#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
4565# if NETINET6
4566	{
4567		int err;
4568
4569		hp = sm_getipnodebyaddr(addr, len, type, &err);
4570		SM_SET_H_ERRNO(err);
4571	}
4572# else /* NETINET6 */
4573	hp = gethostbyaddr(addr, len, type);
4574# endif /* NETINET6 */
4575#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
4576	return hp;
4577}
4578/*
4579**  SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid
4580*/
4581
4582struct passwd *
4583sm_getpwnam(user)
4584	char *user;
4585{
4586#ifdef _AIX4
4587	extern struct passwd *_getpwnam_shadow(const char *, const int);
4588
4589	return _getpwnam_shadow(user, 0);
4590#else /* _AIX4 */
4591	return getpwnam(user);
4592#endif /* _AIX4 */
4593}
4594
4595struct passwd *
4596sm_getpwuid(uid)
4597	UID_T uid;
4598{
4599#if defined(_AIX4) && 0
4600	extern struct passwd *_getpwuid_shadow(const int, const int);
4601
4602	return _getpwuid_shadow(uid,0);
4603#else /* defined(_AIX4) && 0 */
4604	return getpwuid(uid);
4605#endif /* defined(_AIX4) && 0 */
4606}
4607/*
4608**  SECUREWARE_SETUP_SECURE -- Convex SecureWare setup
4609**
4610**	Set up the trusted computing environment for C2 level security
4611**	under SecureWare.
4612**
4613**	Parameters:
4614**		uid -- uid of the user to initialize in the TCB
4615**
4616**	Returns:
4617**		none
4618**
4619**	Side Effects:
4620**		Initialized the user in the trusted computing base
4621*/
4622
4623#if SECUREWARE
4624
4625# include <sys/security.h>
4626# include <prot.h>
4627
4628void
4629secureware_setup_secure(uid)
4630	UID_T uid;
4631{
4632	int rc;
4633
4634	if (getluid() != -1)
4635		return;
4636
4637	if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN)
4638	{
4639		switch (rc)
4640		{
4641		  case SSI_NO_PRPW_ENTRY:
4642			syserr("No protected passwd entry, uid = %d",
4643			       (int) uid);
4644			break;
4645
4646		  case SSI_LOCKED:
4647			syserr("Account has been disabled, uid = %d",
4648			       (int) uid);
4649			break;
4650
4651		  case SSI_RETIRED:
4652			syserr("Account has been retired, uid = %d",
4653			       (int) uid);
4654			break;
4655
4656		  case SSI_BAD_SET_LUID:
4657			syserr("Could not set LUID, uid = %d", (int) uid);
4658			break;
4659
4660		  case SSI_BAD_SET_PRIVS:
4661			syserr("Could not set kernel privs, uid = %d",
4662			       (int) uid);
4663
4664		  default:
4665			syserr("Unknown return code (%d) from set_secure_info(%d)",
4666				rc, (int) uid);
4667			break;
4668		}
4669		finis(false, true, EX_NOPERM);
4670	}
4671}
4672#endif /* SECUREWARE */
4673/*
4674**  ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address
4675**
4676**	Add hostnames to class 'w' based on the IP address read from
4677**	the network interface.
4678**
4679**	Parameters:
4680**		sa -- a pointer to a SOCKADDR containing the address
4681**
4682**	Returns:
4683**		0 if successful, -1 if host lookup fails.
4684*/
4685
4686static int
4687add_hostnames(sa)
4688	SOCKADDR *sa;
4689{
4690	struct hostent *hp;
4691	char **ha;
4692	char hnb[MAXHOSTNAMELEN];
4693
4694	/* lookup name with IP address */
4695	switch (sa->sa.sa_family)
4696	{
4697#if NETINET
4698	  case AF_INET:
4699		hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr,
4700				      sizeof(sa->sin.sin_addr),
4701				      sa->sa.sa_family);
4702		break;
4703#endif /* NETINET */
4704
4705#if NETINET6
4706	  case AF_INET6:
4707		hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr,
4708				      sizeof(sa->sin6.sin6_addr),
4709				      sa->sa.sa_family);
4710		break;
4711#endif /* NETINET6 */
4712
4713	  default:
4714		/* Give warning about unsupported family */
4715		if (LogLevel > 3)
4716			sm_syslog(LOG_WARNING, NOQID,
4717				  "Unsupported address family %d: %.100s",
4718				  sa->sa.sa_family, anynet_ntoa(sa));
4719		return -1;
4720	}
4721
4722	if (hp == NULL)
4723	{
4724		int save_errno = errno;
4725
4726		if (LogLevel > 3 &&
4727#if NETINET && defined(IN_LINKLOCAL)
4728		    !(sa->sa.sa_family == AF_INET &&
4729		      IN_LINKLOCAL(ntohl(sa->sin.sin_addr.s_addr))) &&
4730#endif
4731#if NETINET6
4732		    !(sa->sa.sa_family == AF_INET6 &&
4733		      IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) &&
4734#endif
4735		    true)
4736			sm_syslog(LOG_WARNING, NOQID,
4737				  "gethostbyaddr(%.100s) failed: %d",
4738				  anynet_ntoa(sa),
4739#if NAMED_BIND
4740				  h_errno
4741#else
4742				  -1
4743#endif
4744				 );
4745		errno = save_errno;
4746		return -1;
4747	}
4748
4749	/* save its cname */
4750	if (!wordinclass((char *) hp->h_name, 'w'))
4751	{
4752		setclass('w', (char *) hp->h_name);
4753		if (tTd(0, 4))
4754			sm_dprintf("\ta.k.a.: %s\n", hp->h_name);
4755
4756		if (sm_snprintf(hnb, sizeof(hnb), "[%s]", hp->h_name) <
4757								sizeof(hnb)
4758		    && !wordinclass((char *) hnb, 'w'))
4759			setclass('w', hnb);
4760	}
4761	else
4762	{
4763		if (tTd(0, 43))
4764			sm_dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name);
4765	}
4766
4767	/* save all it aliases name */
4768	for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
4769	{
4770		if (!wordinclass(*ha, 'w'))
4771		{
4772			setclass('w', *ha);
4773			if (tTd(0, 4))
4774				sm_dprintf("\ta.k.a.: %s\n", *ha);
4775			if (sm_snprintf(hnb, sizeof(hnb),
4776				     "[%s]", *ha) < sizeof(hnb) &&
4777			    !wordinclass((char *) hnb, 'w'))
4778				setclass('w', hnb);
4779		}
4780		else
4781		{
4782			if (tTd(0, 43))
4783				sm_dprintf("\ta.k.a.: %s (already in $=w)\n",
4784					*ha);
4785		}
4786	}
4787#if NETINET6
4788	freehostent(hp);
4789#endif
4790	return 0;
4791}
4792/*
4793**  LOAD_IF_NAMES -- load interface-specific names into $=w
4794**
4795**	Parameters:
4796**		none.
4797**
4798**	Returns:
4799**		none.
4800**
4801**	Side Effects:
4802**		Loads $=w with the names of all the interfaces.
4803*/
4804
4805#if !NETINET
4806# define SIOCGIFCONF_IS_BROKEN	1 /* XXX */
4807#endif
4808
4809#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
4810struct rtentry;
4811struct mbuf;
4812# ifndef SUNOS403
4813#  include <sm/time.h>
4814# endif
4815# if (_AIX4 >= 40300) && !defined(_NET_IF_H)
4816#  undef __P
4817# endif
4818# include <net/if.h>
4819#endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
4820
4821void
4822load_if_names()
4823{
4824# if NETINET6 && defined(SIOCGLIFCONF)
4825#  ifdef __hpux
4826
4827    /*
4828    **  Unfortunately, HP has changed all of the structures,
4829    **  making life difficult for implementors.
4830    */
4831
4832#   define lifconf	if_laddrconf
4833#   define lifc_len	iflc_len
4834#   define lifc_buf	iflc_buf
4835#   define lifreq	if_laddrreq
4836#   define lifr_addr	iflr_addr
4837#   define lifr_name	iflr_name
4838#   define lifr_flags	iflr_flags
4839#   define ss_family	sa_family
4840#   undef SIOCGLIFNUM
4841#  endif /* __hpux */
4842
4843	int s;
4844	int i;
4845	size_t len;
4846	int numifs;
4847	char *buf;
4848	struct lifconf lifc;
4849#  ifdef SIOCGLIFNUM
4850	struct lifnum lifn;
4851#  endif
4852
4853	s = socket(InetMode, SOCK_DGRAM, 0);
4854	if (s == -1)
4855		return;
4856
4857	/* get the list of known IP address from the kernel */
4858#  ifdef __hpux
4859	i = ioctl(s, SIOCGIFNUM, (char *) &numifs);
4860#  endif
4861#  ifdef SIOCGLIFNUM
4862	lifn.lifn_family = AF_UNSPEC;
4863	lifn.lifn_flags = 0;
4864	i = ioctl(s, SIOCGLIFNUM, (char *)&lifn);
4865	numifs = lifn.lifn_count;
4866#  endif /* SIOCGLIFNUM */
4867
4868#  if defined(__hpux) || defined(SIOCGLIFNUM)
4869	if (i < 0)
4870	{
4871		/* can't get number of interfaces -- fall back */
4872		if (tTd(0, 4))
4873			sm_dprintf("SIOCGLIFNUM failed: %s\n",
4874				   sm_errstring(errno));
4875		numifs = -1;
4876	}
4877	else if (tTd(0, 42))
4878		sm_dprintf("system has %d interfaces\n", numifs);
4879	if (numifs < 0)
4880#  endif /* defined(__hpux) || defined(SIOCGLIFNUM) */
4881		numifs = MAXINTERFACES;
4882
4883	if (numifs <= 0)
4884	{
4885		(void) close(s);
4886		return;
4887	}
4888
4889	len = lifc.lifc_len = numifs * sizeof(struct lifreq);
4890	buf = lifc.lifc_buf = xalloc(lifc.lifc_len);
4891#  ifndef __hpux
4892	lifc.lifc_family = AF_UNSPEC;
4893	lifc.lifc_flags = 0;
4894#  endif
4895	if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0)
4896	{
4897		if (tTd(0, 4))
4898			sm_dprintf("SIOCGLIFCONF failed: %s\n",
4899				   sm_errstring(errno));
4900		(void) close(s);
4901		sm_free(buf);
4902		return;
4903	}
4904
4905	/* scan the list of IP address */
4906	if (tTd(0, 40))
4907		sm_dprintf("scanning for interface specific names, lifc_len=%ld\n",
4908			   (long) len);
4909
4910	for (i = 0; i < len && i >= 0; )
4911	{
4912		int flags;
4913		struct lifreq *ifr = (struct lifreq *)&buf[i];
4914		SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr;
4915		int af = ifr->lifr_addr.ss_family;
4916		char *addr;
4917		char *name;
4918		struct in6_addr ia6;
4919		struct in_addr ia;
4920#  ifdef SIOCGLIFFLAGS
4921		struct lifreq ifrf;
4922#  endif
4923		char ip_addr[256];
4924		char buf6[INET6_ADDRSTRLEN];
4925
4926		/*
4927		**  We must close and recreate the socket each time
4928		**  since we don't know what type of socket it is now
4929		**  (each status function may change it).
4930		*/
4931
4932		(void) close(s);
4933
4934		s = socket(af, SOCK_DGRAM, 0);
4935		if (s == -1)
4936		{
4937			sm_free(buf); /* XXX */
4938			return;
4939		}
4940
4941		/*
4942		**  If we don't have a complete ifr structure,
4943		**  don't try to use it.
4944		*/
4945
4946		if ((len - i) < sizeof(*ifr))
4947			break;
4948
4949#  ifdef BSD4_4_SOCKADDR
4950		if (sa->sa.sa_len > sizeof(ifr->lifr_addr))
4951			i += sizeof(ifr->lifr_name) + sa->sa.sa_len;
4952		else
4953#  endif /* BSD4_4_SOCKADDR */
4954#  ifdef DEC
4955			/* fix for IPv6  size differences */
4956			i += sizeof(ifr->ifr_name) +
4957			     max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
4958#   else /* DEC */
4959			i += sizeof(*ifr);
4960#   endif /* DEC */
4961
4962		if (tTd(0, 20))
4963			sm_dprintf("%s\n", anynet_ntoa(sa));
4964
4965		if (af != AF_INET && af != AF_INET6)
4966			continue;
4967
4968#  ifdef SIOCGLIFFLAGS
4969		memset(&ifrf, '\0', sizeof(struct lifreq));
4970		(void) sm_strlcpy(ifrf.lifr_name, ifr->lifr_name,
4971				  sizeof(ifrf.lifr_name));
4972		if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0)
4973		{
4974			if (tTd(0, 4))
4975				sm_dprintf("SIOCGLIFFLAGS failed: %s\n",
4976					   sm_errstring(errno));
4977			continue;
4978		}
4979
4980		name = ifr->lifr_name;
4981		flags = ifrf.lifr_flags;
4982
4983		if (tTd(0, 41))
4984			sm_dprintf("\tflags: %lx\n", (unsigned long) flags);
4985
4986		if (!bitset(IFF_UP, flags))
4987			continue;
4988#  endif /* SIOCGLIFFLAGS */
4989
4990		ip_addr[0] = '\0';
4991
4992		/* extract IP address from the list*/
4993		switch (af)
4994		{
4995		  case AF_INET6:
4996			SETV6LOOPBACKADDRFOUND(*sa);
4997#  ifdef __KAME__
4998			/* convert into proper scoped address */
4999			if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) ||
5000			     IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) &&
5001			    sa->sin6.sin6_scope_id == 0)
5002			{
5003				struct in6_addr *ia6p;
5004
5005				ia6p = &sa->sin6.sin6_addr;
5006				sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] |
5007							       ((unsigned int)ia6p->s6_addr[2] << 8));
5008				ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0;
5009			}
5010#  endif /* __KAME__ */
5011			ia6 = sa->sin6.sin6_addr;
5012			if (IN6_IS_ADDR_UNSPECIFIED(&ia6))
5013			{
5014				addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
5015				message("WARNING: interface %s is UP with %s address",
5016					name, addr == NULL ? "(NULL)" : addr);
5017				continue;
5018			}
5019
5020			/* save IP address in text from */
5021			addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
5022			if (addr != NULL)
5023				(void) sm_snprintf(ip_addr, sizeof(ip_addr),
5024						   "[%.*s]",
5025						   (int) sizeof(ip_addr) - 3,
5026						   addr);
5027			break;
5028
5029		  case AF_INET:
5030			ia = sa->sin.sin_addr;
5031			if (ia.s_addr == INADDR_ANY ||
5032			    ia.s_addr == INADDR_NONE)
5033			{
5034				message("WARNING: interface %s is UP with %s address",
5035					name, inet_ntoa(ia));
5036				continue;
5037			}
5038
5039			/* save IP address in text from */
5040			(void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]",
5041					(int) sizeof(ip_addr) - 3, inet_ntoa(ia));
5042			break;
5043		}
5044
5045		if (*ip_addr == '\0')
5046			continue;
5047
5048		if (!wordinclass(ip_addr, 'w'))
5049		{
5050			setclass('w', ip_addr);
5051			if (tTd(0, 4))
5052				sm_dprintf("\ta.k.a.: %s\n", ip_addr);
5053		}
5054
5055#  ifdef SIOCGLIFFLAGS
5056		/* skip "loopback" interface "lo" */
5057		if (DontProbeInterfaces == DPI_SKIPLOOPBACK &&
5058		    bitset(IFF_LOOPBACK, flags))
5059			continue;
5060#  endif /* SIOCGLIFFLAGS */
5061		(void) add_hostnames(sa);
5062	}
5063	sm_free(buf); /* XXX */
5064	(void) close(s);
5065# else /* NETINET6 && defined(SIOCGLIFCONF) */
5066#  if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
5067	int s;
5068	int i;
5069	struct ifconf ifc;
5070	int numifs;
5071
5072	s = socket(AF_INET, SOCK_DGRAM, 0);
5073	if (s == -1)
5074		return;
5075
5076	/* get the list of known IP address from the kernel */
5077#   if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN
5078	if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0)
5079	{
5080		/* can't get number of interfaces -- fall back */
5081		if (tTd(0, 4))
5082			sm_dprintf("SIOCGIFNUM failed: %s\n",
5083				   sm_errstring(errno));
5084		numifs = -1;
5085	}
5086	else if (tTd(0, 42))
5087		sm_dprintf("system has %d interfaces\n", numifs);
5088	if (numifs < 0)
5089#   endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */
5090		numifs = MAXINTERFACES;
5091
5092	if (numifs <= 0)
5093	{
5094		(void) close(s);
5095		return;
5096	}
5097	ifc.ifc_len = numifs * sizeof(struct ifreq);
5098	ifc.ifc_buf = xalloc(ifc.ifc_len);
5099	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
5100	{
5101		if (tTd(0, 4))
5102			sm_dprintf("SIOCGIFCONF failed: %s\n",
5103				   sm_errstring(errno));
5104		(void) close(s);
5105		return;
5106	}
5107
5108	/* scan the list of IP address */
5109	if (tTd(0, 40))
5110		sm_dprintf("scanning for interface specific names, ifc_len=%d\n",
5111			ifc.ifc_len);
5112
5113	for (i = 0; i < ifc.ifc_len && i >= 0; )
5114	{
5115		int af;
5116		struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i];
5117		SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr;
5118#   if NETINET6
5119		char *addr;
5120		struct in6_addr ia6;
5121#   endif
5122		struct in_addr ia;
5123#   ifdef SIOCGIFFLAGS
5124		struct ifreq ifrf;
5125#   endif
5126		char ip_addr[256];
5127#   if NETINET6
5128		char buf6[INET6_ADDRSTRLEN];
5129#   endif
5130
5131		/*
5132		**  If we don't have a complete ifr structure,
5133		**  don't try to use it.
5134		*/
5135
5136		if ((ifc.ifc_len - i) < sizeof(*ifr))
5137			break;
5138
5139#   ifdef BSD4_4_SOCKADDR
5140		if (sa->sa.sa_len > sizeof(ifr->ifr_addr))
5141			i += sizeof(ifr->ifr_name) + sa->sa.sa_len;
5142		else
5143#   endif /* BSD4_4_SOCKADDR */
5144			i += sizeof(*ifr);
5145
5146		if (tTd(0, 20))
5147			sm_dprintf("%s\n", anynet_ntoa(sa));
5148
5149		af = ifr->ifr_addr.sa_family;
5150		if (af != AF_INET
5151#   if NETINET6
5152		    && af != AF_INET6
5153#   endif
5154		    )
5155			continue;
5156
5157#   ifdef SIOCGIFFLAGS
5158		memset(&ifrf, '\0', sizeof(struct ifreq));
5159		(void) sm_strlcpy(ifrf.ifr_name, ifr->ifr_name,
5160			       sizeof(ifrf.ifr_name));
5161		(void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
5162		if (tTd(0, 41))
5163			sm_dprintf("\tflags: %lx\n",
5164				(unsigned long) ifrf.ifr_flags);
5165#    define IFRFREF ifrf
5166#   else /* SIOCGIFFLAGS */
5167#    define IFRFREF (*ifr)
5168#   endif /* SIOCGIFFLAGS */
5169
5170		if (!bitset(IFF_UP, IFRFREF.ifr_flags))
5171			continue;
5172
5173		ip_addr[0] = '\0';
5174
5175		/* extract IP address from the list*/
5176		switch (af)
5177		{
5178		  case AF_INET:
5179			ia = sa->sin.sin_addr;
5180			if (ia.s_addr == INADDR_ANY ||
5181			    ia.s_addr == INADDR_NONE)
5182			{
5183				message("WARNING: interface %s is UP with %s address",
5184					ifr->ifr_name, inet_ntoa(ia));
5185				continue;
5186			}
5187
5188			/* save IP address in text from */
5189			(void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]",
5190					(int) sizeof(ip_addr) - 3,
5191					inet_ntoa(ia));
5192			break;
5193
5194#   if NETINET6
5195		  case AF_INET6:
5196			SETV6LOOPBACKADDRFOUND(*sa);
5197#    ifdef __KAME__
5198			/* convert into proper scoped address */
5199			if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) ||
5200			     IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) &&
5201			    sa->sin6.sin6_scope_id == 0)
5202			{
5203				struct in6_addr *ia6p;
5204
5205				ia6p = &sa->sin6.sin6_addr;
5206				sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] |
5207							       ((unsigned int)ia6p->s6_addr[2] << 8));
5208				ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0;
5209			}
5210#    endif /* __KAME__ */
5211			ia6 = sa->sin6.sin6_addr;
5212			if (IN6_IS_ADDR_UNSPECIFIED(&ia6))
5213			{
5214				addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
5215				message("WARNING: interface %s is UP with %s address",
5216					ifr->ifr_name,
5217					addr == NULL ? "(NULL)" : addr);
5218				continue;
5219			}
5220
5221			/* save IP address in text from */
5222			addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
5223			if (addr != NULL)
5224				(void) sm_snprintf(ip_addr, sizeof(ip_addr),
5225						   "[%.*s]",
5226						   (int) sizeof(ip_addr) - 3,
5227						   addr);
5228			break;
5229
5230#   endif /* NETINET6 */
5231		}
5232
5233		if (ip_addr[0] == '\0')
5234			continue;
5235
5236		if (!wordinclass(ip_addr, 'w'))
5237		{
5238			setclass('w', ip_addr);
5239			if (tTd(0, 4))
5240				sm_dprintf("\ta.k.a.: %s\n", ip_addr);
5241		}
5242
5243		/* skip "loopback" interface "lo" */
5244		if (DontProbeInterfaces == DPI_SKIPLOOPBACK &&
5245		    bitset(IFF_LOOPBACK, IFRFREF.ifr_flags))
5246			continue;
5247
5248		(void) add_hostnames(sa);
5249	}
5250	sm_free(ifc.ifc_buf); /* XXX */
5251	(void) close(s);
5252#   undef IFRFREF
5253#  endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
5254# endif /* NETINET6 && defined(SIOCGLIFCONF) */
5255}
5256/*
5257**  ISLOOPBACK -- is socket address in the loopback net?
5258**
5259**	Parameters:
5260**		sa -- socket address.
5261**
5262**	Returns:
5263**		true -- is socket address in the loopback net?
5264**		false -- otherwise
5265**
5266*/
5267
5268bool
5269isloopback(sa)
5270	SOCKADDR sa;
5271{
5272	/* XXX how to correctly extract IN_LOOPBACKNET part? */
5273#define SM_IS_IPV4_LOOP(a) (((ntohl(a) & IN_CLASSA_NET) \
5274	     >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
5275#if NETINET6
5276	if (sa.sa.sa_family == AF_INET6 &&
5277	    IN6_IS_ADDR_V4MAPPED(&sa.sin6.sin6_addr) &&
5278	    SM_IS_IPV4_LOOP(((uint32_t *) (&sa.sin6.sin6_addr))[3]))
5279		return true;
5280	if (sa.sa.sa_family == AF_INET6 &&
5281	    IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr))
5282		return true;
5283#endif
5284#if NETINET
5285	if (sa.sa.sa_family == AF_INET &&
5286	    SM_IS_IPV4_LOOP(sa.sin.sin_addr.s_addr))
5287		return true;
5288#endif
5289	return false;
5290}
5291
5292/*
5293**  GET_NUM_PROCS_ONLINE -- return the number of processors currently online
5294**
5295**	Parameters:
5296**		none.
5297**
5298**	Returns:
5299**		The number of processors online.
5300*/
5301
5302static int
5303get_num_procs_online()
5304{
5305	int nproc = 0;
5306
5307#ifdef USESYSCTL
5308# if defined(CTL_HW) && defined(HW_NCPU)
5309	size_t sz;
5310	int mib[2];
5311
5312	mib[0] = CTL_HW;
5313	mib[1] = HW_NCPU;
5314	sz = (size_t) sizeof(nproc);
5315	(void) sysctl(mib, 2, &nproc, &sz, NULL, 0);
5316# endif /* defined(CTL_HW) && defined(HW_NCPU) */
5317#else /* USESYSCTL */
5318# ifdef _SC_NPROCESSORS_ONLN
5319	nproc = (int) sysconf(_SC_NPROCESSORS_ONLN);
5320# else /* _SC_NPROCESSORS_ONLN */
5321#  ifdef __hpux
5322#   include <sys/pstat.h>
5323	struct pst_dynamic psd;
5324
5325	if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1)
5326		nproc = psd.psd_proc_cnt;
5327#  endif /* __hpux */
5328# endif /* _SC_NPROCESSORS_ONLN */
5329#endif /* USESYSCTL */
5330
5331	if (nproc <= 0)
5332		nproc = 1;
5333	return nproc;
5334}
5335/*
5336**  SM_CLOSEFROM -- close file descriptors
5337**
5338**	Parameters:
5339**		lowest -- first fd to close
5340**		highest -- last fd + 1 to close
5341**
5342**	Returns:
5343**		none
5344*/
5345
5346void
5347sm_closefrom(lowest, highest)
5348	int lowest, highest;
5349{
5350#if HASCLOSEFROM
5351	closefrom(lowest);
5352#else /* HASCLOSEFROM */
5353	int i;
5354
5355	for (i = lowest; i < highest; i++)
5356		(void) close(i);
5357#endif /* HASCLOSEFROM */
5358}
5359#if HASFDWALK
5360/*
5361**  CLOSEFD_WALK -- walk fd's arranging to close them
5362**	Callback for fdwalk()
5363**
5364**	Parameters:
5365**		lowest -- first fd to arrange to be closed
5366**		fd -- fd to arrange to be closed
5367**
5368**	Returns:
5369**		zero
5370*/
5371
5372static int
5373closefd_walk(lowest, fd)
5374	void *lowest;
5375	int fd;
5376{
5377	if (fd >= *(int *)lowest)
5378		(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
5379	return 0;
5380}
5381#endif /* HASFDWALK */
5382/*
5383**  SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed
5384**
5385**	Parameters:
5386**		lowest -- first fd to arrange to be closed
5387**		highest -- last fd + 1 to arrange to be closed
5388**
5389**	Returns:
5390**		none
5391*/
5392
5393void
5394sm_close_on_exec(lowest, highest)
5395	int lowest, highest;
5396{
5397#if HASFDWALK
5398	(void) fdwalk(closefd_walk, &lowest);
5399#else /* HASFDWALK */
5400	int i, j;
5401
5402	for (i = lowest; i < highest; i++)
5403	{
5404		if ((j = fcntl(i, F_GETFD, 0)) != -1)
5405			(void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
5406	}
5407#endif /* HASFDWALK */
5408}
5409/*
5410**  SEED_RANDOM -- seed the random number generator
5411**
5412**	Parameters:
5413**		none
5414**
5415**	Returns:
5416**		none
5417*/
5418
5419void
5420seed_random()
5421{
5422#if HASSRANDOMDEV
5423	srandomdev();
5424#else /* HASSRANDOMDEV */
5425	long seed;
5426	struct timeval t;
5427
5428	seed = (long) CurrentPid;
5429	if (gettimeofday(&t, NULL) >= 0)
5430		seed += t.tv_sec + t.tv_usec;
5431
5432# if HASRANDOM
5433	(void) srandom(seed);
5434# else
5435	(void) srand((unsigned int) seed);
5436# endif
5437#endif /* HASSRANDOMDEV */
5438}
5439/*
5440**  SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE
5441**
5442**	Parameters:
5443**		level -- syslog level
5444**		id -- envelope ID or NULL (NOQUEUE)
5445**		fmt -- format string
5446**		arg... -- arguments as implied by fmt.
5447**
5448**	Returns:
5449**		none
5450*/
5451
5452/* VARARGS3 */
5453void
5454#ifdef __STDC__
5455sm_syslog(int level, const char *id, const char *fmt, ...)
5456#else /* __STDC__ */
5457sm_syslog(level, id, fmt, va_alist)
5458	int level;
5459	const char *id;
5460	const char *fmt;
5461	va_dcl
5462#endif /* __STDC__ */
5463{
5464	char *buf;
5465	size_t bufsize;
5466	char *begin, *end;
5467	int save_errno;
5468	int seq = 1;
5469	int idlen;
5470	char buf0[MAXLINE];
5471	char *newstring;
5472	extern int SyslogPrefixLen;
5473	SM_VA_LOCAL_DECL
5474
5475	save_errno = errno;
5476	if (id == NULL)
5477		id = "NOQUEUE";
5478	idlen = strlen(id) + SyslogPrefixLen;
5479
5480	buf = buf0;
5481	bufsize = sizeof(buf0);
5482
5483	for (;;)
5484	{
5485		int n;
5486
5487		/* print log message into buf */
5488		SM_VA_START(ap, fmt);
5489		n = sm_vsnprintf(buf, bufsize, fmt, ap);
5490		SM_VA_END(ap);
5491		SM_ASSERT(n >= 0);
5492		if (n < bufsize)
5493			break;
5494
5495		/* String too small, redo with correct size */
5496		bufsize = n + 1;
5497		if (buf != buf0)
5498		{
5499			sm_free(buf);
5500			buf = NULL;
5501		}
5502		buf = sm_malloc_x(bufsize);
5503	}
5504
5505	/* clean up buf after it has been expanded with args */
5506	newstring = str2prt(buf);
5507	if ((strlen(newstring) + idlen + 1) < SYSLOG_BUFSIZE)
5508	{
5509#if LOG
5510		if (*id == '\0')
5511		{
5512			if (tTd(89, 10))
5513			{
5514				struct timeval tv;
5515
5516				gettimeofday(&tv, NULL);
5517				sm_dprintf("%ld.%06ld %s\n", (long) tv.tv_sec,
5518					(long) tv.tv_usec, newstring);
5519			}
5520			else if (tTd(89, 8))
5521				sm_dprintf("%s\n", newstring);
5522			else
5523				syslog(level, "%s", newstring);
5524		}
5525		else
5526		{
5527			if (tTd(89, 10))
5528			{
5529				struct timeval tv;
5530
5531				gettimeofday(&tv, NULL);
5532				sm_dprintf("%ld.%06ld %s: %s\n", (long) tv.tv_sec,
5533					(long) tv.tv_usec, id, newstring);
5534			}
5535			else if (tTd(89, 8))
5536				sm_dprintf("%s: %s\n", id, newstring);
5537			else
5538				syslog(level, "%s: %s", id, newstring);
5539		}
5540#else /* LOG */
5541		/*XXX should do something more sensible */
5542		if (*id == '\0')
5543			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n",
5544					     newstring);
5545		else
5546			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
5547					     "%s: %s\n", id, newstring);
5548#endif /* LOG */
5549		if (buf != buf0)
5550			sm_free(buf);
5551		errno = save_errno;
5552		return;
5553	}
5554
5555/*
5556**  additional length for splitting: " ..." + 3, where 3 is magic to
5557**  have some data for the next entry.
5558*/
5559
5560#define SL_SPLIT 7
5561
5562	begin = newstring;
5563	idlen += 5;	/* strlen("[999]"), see below */
5564	while (*begin != '\0' &&
5565	       (strlen(begin) + idlen) > SYSLOG_BUFSIZE)
5566	{
5567		char save;
5568
5569		if (seq >= 999)
5570		{
5571			/* Too many messages */
5572			break;
5573		}
5574		end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT;
5575		while (end > begin)
5576		{
5577			/* Break on comma or space */
5578			if (*end == ',' || *end == ' ')
5579			{
5580				end++;	  /* Include separator */
5581				break;
5582			}
5583			end--;
5584		}
5585		/* No separator, break midstring... */
5586		if (end == begin)
5587			end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT;
5588		save = *end;
5589		*end = 0;
5590#if LOG
5591		if (tTd(89, 8))
5592			sm_dprintf("%s[%d]: %s ...\n", id, seq++, begin);
5593		else
5594			syslog(level, "%s[%d]: %s ...", id, seq++, begin);
5595#else /* LOG */
5596		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
5597				     "%s[%d]: %s ...\n", id, seq++, begin);
5598#endif /* LOG */
5599		*end = save;
5600		begin = end;
5601	}
5602	if (seq >= 999)
5603	{
5604#if LOG
5605		if (tTd(89, 8))
5606			sm_dprintf("%s[%d]: log terminated, too many parts\n",
5607				id, seq);
5608		else
5609			syslog(level, "%s[%d]: log terminated, too many parts",
5610				id, seq);
5611#else /* LOG */
5612		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
5613			      "%s[%d]: log terminated, too many parts\n", id, seq);
5614#endif /* LOG */
5615	}
5616	else if (*begin != '\0')
5617	{
5618#if LOG
5619		if (tTd(89, 8))
5620			sm_dprintf("%s[%d]: %s\n", id, seq, begin);
5621		else
5622			syslog(level, "%s[%d]: %s", id, seq, begin);
5623#else /* LOG */
5624		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
5625				     "%s[%d]: %s\n", id, seq, begin);
5626#endif /* LOG */
5627	}
5628	if (buf != buf0)
5629		sm_free(buf);
5630	errno = save_errno;
5631}
5632/*
5633**  HARD_SYSLOG -- call syslog repeatedly until it works
5634**
5635**	Needed on HP-UX, which apparently doesn't guarantee that
5636**	syslog succeeds during interrupt handlers.
5637*/
5638
5639#if defined(__hpux) && !defined(HPUX11)
5640
5641# define MAXSYSLOGTRIES	100
5642# undef syslog
5643# ifdef V4FS
5644#  define XCNST	const
5645#  define CAST	(const char *)
5646# else
5647#  define XCNST
5648#  define CAST
5649# endif
5650
5651void
5652# ifdef __STDC__
5653hard_syslog(int pri, XCNST char *msg, ...)
5654# else /* __STDC__ */
5655hard_syslog(pri, msg, va_alist)
5656	int pri;
5657	XCNST char *msg;
5658	va_dcl
5659# endif /* __STDC__ */
5660{
5661	int i;
5662	char buf[SYSLOG_BUFSIZE];
5663	SM_VA_LOCAL_DECL
5664
5665	SM_VA_START(ap, msg);
5666	(void) sm_vsnprintf(buf, sizeof(buf), msg, ap);
5667	SM_VA_END(ap);
5668
5669	for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; )
5670		continue;
5671}
5672
5673# undef CAST
5674#endif /* defined(__hpux) && !defined(HPUX11) */
5675#if NEEDLOCAL_HOSTNAME_LENGTH
5676/*
5677**  LOCAL_HOSTNAME_LENGTH
5678**
5679**	This is required to get sendmail to compile against BIND 4.9.x
5680**	on Ultrix.
5681**
5682**	Unfortunately, a Compaq Y2K patch kit provides it without
5683**	bumping __RES in /usr/include/resolv.h so we can't automatically
5684**	figure out whether it is needed.
5685*/
5686
5687int
5688local_hostname_length(hostname)
5689	char *hostname;
5690{
5691	size_t len_host, len_domain;
5692
5693	if (!*_res.defdname)
5694		res_init();
5695	len_host = strlen(hostname);
5696	len_domain = strlen(_res.defdname);
5697	if (len_host > len_domain &&
5698	    (sm_strcasecmp(hostname + len_host - len_domain,
5699			_res.defdname) == 0) &&
5700	    hostname[len_host - len_domain - 1] == '.')
5701		return len_host - len_domain - 1;
5702	else
5703		return 0;
5704}
5705#endif /* NEEDLOCAL_HOSTNAME_LENGTH */
5706
5707#if NEEDLINK
5708/*
5709**  LINK -- clone a file
5710**
5711**	Some OS's lacks link() and hard links.  Since sendmail is using
5712**	link() as an efficient way to clone files, this implementation
5713**	will simply do a file copy.
5714**
5715**	NOTE: This link() replacement is not a generic replacement as it
5716**	does not handle all of the semantics of the real link(2).
5717**
5718**	Parameters:
5719**		source -- pathname of existing file.
5720**		target -- pathname of link (clone) to be created.
5721**
5722**	Returns:
5723**		0 -- success.
5724**		-1 -- failure, see errno for details.
5725*/
5726
5727int
5728link(source, target)
5729	const char *source;
5730	const char *target;
5731{
5732	int save_errno;
5733	int sff;
5734	int src = -1, dst = -1;
5735	ssize_t readlen;
5736	ssize_t writelen;
5737	char buf[BUFSIZ];
5738	struct stat st;
5739
5740	sff = SFF_REGONLY|SFF_OPENASROOT;
5741	if (DontLockReadFiles)
5742		sff |= SFF_NOLOCK;
5743
5744	/* Open the original file */
5745	src = safeopen((char *)source, O_RDONLY, 0, sff);
5746	if (src < 0)
5747		goto fail;
5748
5749	/* Obtain the size and the mode */
5750	if (fstat(src, &st) < 0)
5751		goto fail;
5752
5753	/* Create the duplicate copy */
5754	sff &= ~SFF_NOLOCK;
5755	sff |= SFF_CREAT;
5756	dst = safeopen((char *)target, O_CREAT|O_EXCL|O_WRONLY,
5757		       st.st_mode, sff);
5758	if (dst < 0)
5759		goto fail;
5760
5761	/* Copy all of the bytes one buffer at a time */
5762	while ((readlen = read(src, &buf, sizeof(buf))) > 0)
5763	{
5764		ssize_t left = readlen;
5765		char *p = buf;
5766
5767		while (left > 0 &&
5768		       (writelen = write(dst, p, (size_t) left)) >= 0)
5769		{
5770			left -= writelen;
5771			p += writelen;
5772		}
5773		if (writelen < 0)
5774			break;
5775	}
5776
5777	/* Any trouble reading? */
5778	if (readlen < 0 || writelen < 0)
5779		goto fail;
5780
5781	/* Close the input file */
5782	if (close(src) < 0)
5783	{
5784		src = -1;
5785		goto fail;
5786	}
5787	src = -1;
5788
5789	/* Close the output file */
5790	if (close(dst) < 0)
5791	{
5792		/* don't set dst = -1 here so we unlink the file */
5793		goto fail;
5794	}
5795
5796	/* Success */
5797	return 0;
5798
5799 fail:
5800	save_errno = errno;
5801	if (src >= 0)
5802		(void) close(src);
5803	if (dst >= 0)
5804	{
5805		(void) unlink(target);
5806		(void) close(dst);
5807	}
5808	errno = save_errno;
5809	return -1;
5810}
5811#endif /* NEEDLINK */
5812
5813/*
5814**  Compile-Time options
5815*/
5816
5817#define SM_STR(x) #x
5818#define SM_XSTR(x) SM_STR(x)
5819
5820char	*CompileOptions[] =
5821{
5822#if ALLOW_255
5823	"ALLOW_255",
5824#endif
5825#if DANE
5826# if STARTTLS
5827	"DANE",
5828# else
5829#  error "DANE set but STARTTLS not defined"
5830# endif
5831#endif
5832#if NAMED_BIND
5833# if DNSMAP
5834	"DNSMAP",
5835# endif
5836#endif
5837#if EGD
5838	"EGD",
5839#endif
5840#if HESIOD
5841	"HESIOD",
5842#endif
5843#if HESIOD_ALLOW_NUMERIC_LOGIN
5844	"HESIOD_ALLOW_NUMERIC_LOGIN",
5845#endif
5846#if HES_GETMAILHOST
5847	"HES_GETMAILHOST",
5848#endif
5849#if IPV6_FULL
5850	/* Use uncompressed IPv6 address format (no "::") by default */
5851	"IPV6_FULL",
5852#endif
5853#if LDAPMAP
5854	"LDAPMAP",
5855#endif
5856#if LDAP_NETWORK_TIMEOUT
5857# if LDAPMAP && defined(LDAP_OPT_NETWORK_TIMEOUT)
5858	/* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */
5859	"LDAP_NETWORK_TIMEOUT",
5860# else
5861#  ERROR: _LDAP_NETWORK_TIMEOUT requires _LDAPMAP
5862# endif
5863#endif
5864#if LDAP_REFERRALS
5865	"LDAP_REFERRALS",
5866#endif
5867#if LOG
5868	"LOG",
5869#endif
5870#if MAP_NSD
5871	"MAP_NSD",
5872#endif
5873#if MAP_REGEX
5874	"MAP_REGEX",
5875#endif
5876#if MATCHGECOS
5877	"MATCHGECOS",
5878#endif
5879#if MAXDAEMONS != 10
5880	"MAXDAEMONS=" SM_XSTR(MAXDAEMONS),
5881#endif
5882#if defined(MSGIDLOGLEN)
5883	"MSGIDLOGLEN=" SM_XSTR(MSGIDLOGLEN),
5884#endif
5885#if MILTER
5886	"MILTER",
5887#endif
5888#if MIME7TO8
5889	"MIME7TO8",
5890#endif
5891#if MIME7TO8_OLD
5892	"MIME7TO8_OLD",
5893#endif
5894#if MIME8TO7
5895	"MIME8TO7",
5896#endif
5897#if NAMED_BIND
5898	"NAMED_BIND",
5899#endif
5900#if NDBM
5901	"NDBM",
5902#endif
5903#if NETINET
5904	"NETINET",
5905#endif
5906#if NETINET6
5907	"NETINET6",
5908#endif
5909#if NETINFO
5910	"NETINFO",
5911#endif
5912#if NETISO
5913	"NETISO",
5914#endif
5915#if NETNS
5916	"NETNS",
5917#endif
5918#if NETUNIX
5919	"NETUNIX",
5920#endif
5921#if NETX25
5922	"NETX25",
5923#endif
5924#if NO_EOH_FIELDS
5925	"NO_EOH_FIELDS",
5926#endif
5927#if NEWDB
5928# if defined(DB_VERSION_MAJOR) && defined(DB_VERSION_MINOR)
5929	"NEWDB=" SM_XSTR(DB_VERSION_MAJOR) "." SM_XSTR(DB_VERSION_MINOR),
5930# else
5931	"NEWDB",
5932# endif
5933#endif
5934#if CDB
5935	"CDB=" SM_XSTR(CDB),
5936#endif
5937#if NIS
5938	"NIS",
5939#endif
5940#if NISPLUS
5941	"NISPLUS",
5942#endif
5943#if NO_DH
5944	"NO_DH",
5945#endif
5946#if PH_MAP
5947	"PH_MAP",
5948#endif
5949#ifdef PICKY_HELO_CHECK
5950	"PICKY_HELO_CHECK",
5951#endif
5952#if PIPELINING
5953	"PIPELINING",
5954#endif
5955#if SASL
5956# if SASL >= 20000
5957	"SASLv2",
5958# else
5959	"SASL",
5960# endif
5961#endif
5962#if SCANF
5963	"SCANF",
5964#endif
5965#if SM_LDAP_ERROR_ON_MISSING_ARGS
5966	"SM_LDAP_ERROR_ON_MISSING_ARGS",
5967#endif
5968#if SMTPDEBUG
5969	"SMTPDEBUG",
5970#endif
5971#if SOCKETMAP
5972	"SOCKETMAP",
5973#endif
5974#if STARTTLS
5975	"STARTTLS",
5976#endif
5977#if SUID_ROOT_FILES_OK
5978	"SUID_ROOT_FILES_OK",
5979#endif
5980#if SYSLOG_BUFSIZE > 1024
5981	"SYSLOG_BUFSIZE=" SM_XSTR(SYSLOG_BUFSIZE),
5982#endif
5983#if TCPWRAPPERS
5984	"TCPWRAPPERS",
5985#endif
5986#if TLS_NO_RSA
5987	"TLS_NO_RSA",
5988#endif
5989#if TLS_EC
5990	/* elliptic curves */
5991	"TLS_EC",
5992#endif
5993#if TLS_VRFY_PER_CTX
5994	"TLS_VRFY_PER_CTX",
5995#endif
5996#if USERDB
5997	"USERDB",
5998#endif
5999#if USE_LDAP_INIT
6000	"USE_LDAP_INIT",
6001#endif
6002#if USE_TTYPATH
6003	"USE_TTYPATH",
6004#endif
6005#if XDEBUG
6006	"XDEBUG",
6007#endif
6008#if XLA
6009	"XLA",
6010#endif
6011	NULL
6012};
6013
6014
6015/*
6016**  OS compile options.
6017*/
6018
6019char	*OsCompileOptions[] =
6020{
6021#if ADDRCONFIG_IS_BROKEN
6022	"ADDRCONFIG_IS_BROKEN",
6023#endif
6024#ifdef AUTO_NETINFO_HOSTS
6025	"AUTO_NETINFO_HOSTS",
6026#endif
6027#ifdef AUTO_NIS_ALIASES
6028	"AUTO_NIS_ALIASES",
6029#endif
6030#if BROKEN_RES_SEARCH
6031	"BROKEN_RES_SEARCH",
6032#endif
6033#ifdef BSD4_4_SOCKADDR
6034	"BSD4_4_SOCKADDR",
6035#endif
6036#if BOGUS_O_EXCL
6037	"BOGUS_O_EXCL",
6038#endif
6039#if DEC_OSF_BROKEN_GETPWENT
6040	"DEC_OSF_BROKEN_GETPWENT",
6041#endif
6042#if DNSSEC_TEST
6043	"DNSSEC_TEST",
6044#endif
6045#if FAST_PID_RECYCLE
6046	"FAST_PID_RECYCLE",
6047#endif
6048#if HASCLOSEFROM
6049	"HASCLOSEFROM",
6050#endif
6051#if HASFCHOWN
6052	"HASFCHOWN",
6053#endif
6054#if HASFCHMOD
6055	"HASFCHMOD",
6056#endif
6057#if HASFDWALK
6058	"HASFDWALK",
6059#endif
6060#if HASFLOCK
6061	"HASFLOCK",
6062#endif
6063#if HASGETDTABLESIZE
6064	"HASGETDTABLESIZE",
6065#endif
6066#if HAS_GETHOSTBYNAME2
6067	"HAS_GETHOSTBYNAME2",
6068#endif
6069#if HASGETUSERSHELL
6070	"HASGETUSERSHELL",
6071#endif
6072#if HASINITGROUPS
6073	"HASINITGROUPS",
6074#endif
6075#if HASLDAPGETALIASBYNAME
6076	"HASLDAPGETALIASBYNAME",
6077#endif
6078#if HASLSTAT
6079	"HASLSTAT",
6080#endif
6081#if HASNICE
6082	"HASNICE",
6083#endif
6084#if HASRANDOM
6085	"HASRANDOM",
6086#endif
6087#if HASRRESVPORT
6088	"HASRRESVPORT",
6089#endif
6090#if HASSETEGID
6091	"HASSETEGID",
6092#endif
6093#if HASSETLOGIN
6094	"HASSETLOGIN",
6095#endif
6096#if HASSETREGID
6097	"HASSETREGID",
6098#endif
6099#if HASSETRESGID
6100	"HASSETRESGID",
6101#endif
6102#if HASSETREUID
6103	"HASSETREUID",
6104#endif
6105#if HASSETRLIMIT
6106	"HASSETRLIMIT",
6107#endif
6108#if HASSETSID
6109	"HASSETSID",
6110#endif
6111#if HASSETUSERCONTEXT
6112	"HASSETUSERCONTEXT",
6113#endif
6114#if HASSETVBUF
6115	"HASSETVBUF",
6116#endif
6117#if HAS_ST_GEN
6118	"HAS_ST_GEN",
6119#endif
6120#if HASSRANDOMDEV
6121	"HASSRANDOMDEV",
6122#endif
6123#if HASURANDOMDEV
6124	"HASURANDOMDEV",
6125#endif
6126#if HASSTRERROR
6127	"HASSTRERROR",
6128#endif
6129#if HASULIMIT
6130	"HASULIMIT",
6131#endif
6132#if HASUNAME
6133	"HASUNAME",
6134#endif
6135#if HASUNSETENV
6136	"HASUNSETENV",
6137#endif
6138#if HASWAITPID
6139	"HASWAITPID",
6140#endif
6141#if HAVE_NANOSLEEP
6142	"HAVE_NANOSLEEP",
6143#endif
6144#if IDENTPROTO
6145	"IDENTPROTO",
6146#endif
6147#if IP_SRCROUTE
6148	"IP_SRCROUTE",
6149#endif
6150#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
6151	"LOCK_ON_OPEN",
6152#endif
6153#if MILTER_NO_NAGLE
6154	"MILTER_NO_NAGLE ",
6155#endif
6156#if NEEDFSYNC
6157	"NEEDFSYNC",
6158#endif
6159#if NEEDLINK
6160	"NEEDLINK",
6161#endif
6162#if NEEDLOCAL_HOSTNAME_LENGTH
6163	"NEEDLOCAL_HOSTNAME_LENGTH",
6164#endif
6165#if NEEDSGETIPNODE
6166	"NEEDSGETIPNODE",
6167#endif
6168#if NEEDSTRSTR
6169	"NEEDSTRSTR",
6170#endif
6171#if NEEDSTRTOL
6172	"NEEDSTRTOL",
6173#endif
6174#ifdef NO_GETSERVBYNAME
6175	"NO_GETSERVBYNAME",
6176#endif
6177#if NOFTRUNCATE
6178	"NOFTRUNCATE",
6179#endif
6180#if REQUIRES_DIR_FSYNC
6181	"REQUIRES_DIR_FSYNC",
6182#endif
6183#if RLIMIT_NEEDS_SYS_TIME_H
6184	"RLIMIT_NEEDS_SYS_TIME_H",
6185#endif
6186#if SAFENFSPATHCONF
6187	"SAFENFSPATHCONF",
6188#endif
6189#if SECUREWARE
6190	"SECUREWARE",
6191#endif
6192#if SFS_TYPE == SFS_4ARGS
6193	"SFS_4ARGS",
6194#elif SFS_TYPE == SFS_MOUNT
6195	"SFS_MOUNT",
6196#elif SFS_TYPE == SFS_NONE
6197	"SFS_NONE",
6198#elif SFS_TYPE == SFS_NT
6199	"SFS_NT",
6200#elif SFS_TYPE == SFS_STATFS
6201	"SFS_STATFS",
6202#elif SFS_TYPE == SFS_STATVFS
6203	"SFS_STATVFS",
6204#elif SFS_TYPE == SFS_USTAT
6205	"SFS_USTAT",
6206#elif SFS_TYPE == SFS_VFS
6207	"SFS_VFS",
6208#endif
6209#if SHARE_V1
6210	"SHARE_V1",
6211#endif
6212#if SIOCGIFCONF_IS_BROKEN
6213	"SIOCGIFCONF_IS_BROKEN",
6214#endif
6215#if SIOCGIFNUM_IS_BROKEN
6216	"SIOCGIFNUM_IS_BROKEN",
6217#endif
6218#if SNPRINTF_IS_BROKEN
6219	"SNPRINTF_IS_BROKEN",
6220#endif
6221#if SO_REUSEADDR_IS_BROKEN
6222	"SO_REUSEADDR_IS_BROKEN",
6223#endif
6224#if SYS5SETPGRP
6225	"SYS5SETPGRP",
6226#endif
6227#if SYSTEM5
6228	"SYSTEM5",
6229#endif
6230#if USE_DOUBLE_FORK
6231	"USE_DOUBLE_FORK",
6232#endif
6233#if USE_ENVIRON
6234	"USE_ENVIRON",
6235#endif
6236#if USE_SA_SIGACTION
6237	"USE_SA_SIGACTION",
6238#endif
6239#if USE_SIGLONGJMP
6240	"USE_SIGLONGJMP",
6241#endif
6242#if USEGETCONFATTR
6243	"USEGETCONFATTR",
6244#endif
6245#if USESETEUID
6246	"USESETEUID",
6247#endif
6248#ifdef USESYSCTL
6249	"USESYSCTL",
6250#endif
6251#if USE_OPENSSL_ENGINE
6252	/*
6253	**  0: OpenSSL ENGINE?
6254	**  1: Support Sun OpenSSL patch for SPARC T4 pkcs11
6255	**  2: none
6256	*/
6257# if USE_OPENSSL_ENGINE != 1
6258	"USE_OPENSSL_ENGINE=" SM_XSTR(USE_OPENSSL_ENGINE),
6259# else
6260	"USE_OPENSSL_ENGINE",
6261#endif
6262#endif
6263#if USING_NETSCAPE_LDAP
6264	"USING_NETSCAPE_LDAP",
6265#endif
6266#ifdef WAITUNION
6267	"WAITUNION",
6268#endif
6269	NULL
6270};
6271
6272/*
6273**  FFR compile options.
6274*/
6275
6276char	*FFRCompileOptions[] =
6277{
6278#if _FFR_ADD_BCC
6279	/* see cf/feature/bcc.m4 */
6280	"_FFR_ADD_BCC",
6281#endif
6282#if _FFR_ADDR_TYPE_MODES
6283	/* more info in {addr_type}, requires m4 changes! */
6284	"_FFR_ADDR_TYPE_MODES",
6285#endif
6286#if _FFR_ALIAS_DETAIL
6287	/* try to handle +detail for aliases */
6288	"_FFR_ALIAS_DETAIL",
6289#endif
6290#if _FFR_ALLOW_SASLINFO
6291	/* DefaultAuthInfo can be specified by user. */
6292	/* DefaultAuthInfo doesn't really work in 8.13 anymore. */
6293	"_FFR_ALLOW_SASLINFO",
6294#endif
6295#if _FFR_BADRCPT_SHUTDOWN
6296	/* shut down connection (421) if there are too many bad RCPTs */
6297	"_FFR_BADRCPT_SHUTDOWN",
6298#endif
6299#if _FFR_BESTMX_BETTER_TRUNCATION
6300	/* Better truncation of list of MX records for dns map. */
6301	"_FFR_BESTMX_BETTER_TRUNCATION",
6302#endif
6303#if _FFR_BLANKENV_MACV
6304	/* also look up macros in BlankEnvelope */
6305	"_FFR_BLANKENV_MACV",
6306#endif
6307#if _FFR_BOUNCE_QUEUE
6308	/* Separate, unprocessed queue for DSNs */
6309	/* John Gardiner Myers of Proofpoint */
6310	"_FFR_BOUNCE_QUEUE",
6311#endif
6312#if _FFR_CATCH_BROKEN_MTAS
6313	/* Deal with MTAs that send a reply during the DATA phase. */
6314	"_FFR_CATCH_BROKEN_MTAS",
6315#endif
6316#if _FFR_CHK_QUEUE
6317	/* Stricter checks about queue directory permissions. */
6318	"_FFR_CHK_QUEUE",
6319#endif
6320#if _FFR_CLIENTCA
6321	/*
6322	**  Allow to set client specific CA values.
6323	**  CACertFile: see doc/op.*:
6324	**  "The DNs of these certificates are sent to the client
6325	**  during the TLS handshake (as part of the CertificateRequest)
6326	**  as the list of acceptable CAs.
6327	**  However, do not list too many root CAs in that file,
6328	**  otherwise the TLS handshake may fail;"
6329	**  In TLSv1.3 the certs in CACertFile are also sent by
6330	**  the client to the server and there is seemingly a
6331	**  16KB limit (just in OpenSSL?).
6332	**  Having a separate CACertFile for the client
6333	**  helps to avoid this problem.
6334	*/
6335
6336	"_FFR_CLIENTCA",
6337#endif
6338#if _FFR_CLIENT_SIZE
6339	/* Don't try to send mail if its size exceeds SIZE= of server. */
6340	"_FFR_CLIENT_SIZE",
6341#endif
6342#if _FFR_DM_ONE
6343	/* deliver first TA in background, then queue */
6344	"_FFR_DM_ONE",
6345#endif
6346#if _FFR_DIGUNIX_SAFECHOWN
6347	/* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */
6348/* Problem noted by Anne Bennett of Concordia University */
6349	"_FFR_DIGUNIX_SAFECHOWN",
6350#endif
6351#if _FFR_DNSMAP_ALIASABLE
6352	/* Allow dns map type to be used for aliases. */
6353/* Don Lewis of TDK */
6354	"_FFR_DNSMAP_ALIASABLE",
6355#endif
6356#if _FFR_DONTLOCKFILESFORREAD_OPTION
6357	/* Enable DontLockFilesForRead option. */
6358	"_FFR_DONTLOCKFILESFORREAD_OPTION",
6359#endif
6360#if _FFR_DOTTED_USERNAMES
6361	/* Allow usernames with '.' */
6362	"_FFR_DOTTED_USERNAMES",
6363#endif
6364#if _FFR_DPO_CS
6365	/*
6366	**  Make DaemonPortOptions case sensitive.
6367	**  For some unknown reasons the code converted every option
6368	**  to uppercase (first letter only, as that's the only one that
6369	**  is actually checked). This prevented all new lower case options
6370	**  from working...
6371	**  The documentation doesn't say anything about case (in)sensitivity,
6372	**  which means it should be case sensitive by default,
6373	**  but it's not a good idea to change this within a patch release,
6374	**  so let's delay this to 8.15.
6375	*/
6376
6377	"_FFR_DPO_CS",
6378#endif
6379#if _FFR_DPRINTF_MAP
6380	/* dprintf map for logging */
6381	"_FFR_DPRINTF_MAP",
6382#endif
6383#if _FFR_DROP_TRUSTUSER_WARNING
6384	/*
6385	**  Don't issue this warning:
6386	**  "readcf: option TrustedUser may cause problems on systems
6387	**  which do not support fchown() if UseMSP is not set.
6388	*/
6389
6390	"_FFR_DROP_TRUSTUSER_WARNING",
6391#endif
6392#if _FFR_EIGHT_BIT_ADDR_OK
6393	/* EightBitAddrOK: allow 8-bit e-mail addresses */
6394	"_FFR_EIGHT_BIT_ADDR_OK",
6395#endif
6396#if _FFR_EXPAND_HELONAME
6397	/* perform macro expansion for heloname */
6398	"_FFR_EXPAND_HELONAME",
6399#endif
6400#if _FFR_EXTRA_MAP_CHECK
6401	/* perform extra checks on $( $) in R lines */
6402	"_FFR_EXTRA_MAP_CHECK",
6403#endif
6404#if _FFR_GETHBN_ExFILE
6405	/*
6406	**  According to Motonori Nakamura some gethostbyname()
6407	**  implementations (TurboLinux?) may (temporarily) fail
6408	**  due to a lack of file descriptors. Enabling this FFR
6409	**  will check errno for EMFILE and ENFILE and in case of a match
6410	**  cause a temporary error instead of a permanent error.
6411	**  The right solution is of course to file a bug against those
6412	**  systems such that they actually set h_errno = TRY_AGAIN.
6413	*/
6414
6415	"_FFR_GETHBN_ExFILE",
6416#endif
6417#if _FFR_FIPSMODE
6418	/* FIPSMode (if supported by OpenSSL library) */
6419	"_FFR_FIPSMODE",
6420#endif
6421#if _FFR_FIX_DASHT
6422	/*
6423	**  If using -t, force not sending to argv recipients, even
6424	**  if they are mentioned in the headers.
6425	*/
6426
6427	"_FFR_FIX_DASHT",
6428#endif
6429#if _FFR_FORWARD_SYSERR
6430	/* Cause a "syserr" if forward file isn't "safe". */
6431	"_FFR_FORWARD_SYSERR",
6432#endif
6433#if _FFR_GEN_ORCPT
6434	/* Generate a ORCPT DSN arg if not already provided */
6435	"_FFR_GEN_ORCPT",
6436#endif
6437#if _FFR_HANDLE_ISO8859_GECOS
6438	/*
6439	**  Allow ISO 8859 characters in GECOS field: replace them
6440	**  with ASCII "equivalent".
6441	*/
6442
6443/* Peter Eriksson of Linkopings universitet */
6444	"_FFR_HANDLE_ISO8859_GECOS",
6445#endif
6446#if _FFR_HANDLE_HDR_RW_TEMPFAIL
6447	/*
6448	**  Temporary header rewriting problems from remotename() etc
6449	**  are not "sticky" for mci (e.g., during queue runs).
6450	*/
6451
6452	"_FFR_HANDLE_HDR_RW_TEMPFAIL",
6453#endif
6454#if _FFR_HPUX_NSSWITCH
6455	/* Use nsswitch on HP-UX */
6456	"_FFR_HPUX_NSSWITCH",
6457#endif
6458#if _FFR_IGNORE_BOGUS_ADDR
6459	/* Ignore addresses for which prescan() failed */
6460	"_FFR_IGNORE_BOGUS_ADDR",
6461#endif
6462#if _FFR_IGNORE_EXT_ON_HELO
6463	/* Ignore extensions offered in response to HELO */
6464	"_FFR_IGNORE_EXT_ON_HELO",
6465#endif
6466#if _FFR_KEEPBCC
6467	/* Keep Bcc header */
6468	"_FFR_KEEPBCC",
6469#endif
6470#if _FFR_LOCAL_DAEMON
6471	/* Local daemon mode (-bl) which only accepts loopback connections */
6472	"_FFR_LOCAL_DAEMON",
6473#endif
6474#if _FFR_LOG_MORE1
6475	/* log some TLS/AUTH info in from= too */
6476	"_FFR_LOG_MORE1=" SM_XSTR(_FFR_LOG_MORE1),
6477#endif
6478#if _FFR_LOG_MORE2
6479	/* log some TLS info in to= too */
6480	"_FFR_LOG_MORE2=" SM_XSTR(_FFR_LOG_MORE2),
6481#endif
6482#if _FFR_LOG_MORE1 > 1 || _FFR_LOG_MORE2 > 1
6483# if _FFR_LOG_MORE1 != _FFR_LOG_MORE2
6484   ERROR: FFR_LOG_MORE1 != FFR_LOG_MORE2
6485# endif
6486#endif
6487#if _FFR_MAIL_MACRO
6488	/* make the "real" sender address available in {mail_from} */
6489	"_FFR_MAIL_MACRO",
6490#endif
6491#if _FFR_MAXDATASIZE
6492	/*
6493	**  It is possible that a header is larger than MILTER_CHUNK_SIZE,
6494	**  hence this shouldn't be used as limit for milter communication.
6495	**  see also libmilter/comm.c
6496	**  Gurusamy Sarathy of ActiveState
6497	*/
6498
6499	"_FFR_MAXDATASIZE",
6500#endif
6501#if _FFR_MAX_FORWARD_ENTRIES
6502	/* Try to limit number of .forward entries */
6503	/* (doesn't work) */
6504/* Randall S. Winchester of the University of Maryland */
6505	"_FFR_MAX_FORWARD_ENTRIES",
6506#endif
6507#if _FFR_MAX_SLEEP_TIME
6508	/* Limit sleep(2) time in libsm/clock.c */
6509	"_FFR_MAX_SLEEP_TIME",
6510#endif
6511#if _FFR_MDS_NEGOTIATE
6512	/* MaxDataSize negotiation with libmilter */
6513	"_FFR_MDS_NEGOTIATE",
6514#endif
6515#if _FFR_MEMSTAT
6516	/* Check free memory */
6517	"_FFR_MEMSTAT",
6518#endif
6519#if _FFR_MILTER_CHECK
6520	"_FFR_MILTER_CHECK",
6521#endif
6522#if _FFR_MILTER_CONNECT_REPLYCODE
6523	/* milter: propagate replycode returned by connect commands */
6524	/* John Gardiner Myers of Proofpoint */
6525	"_FFR_MILTER_CONNECT_REPLYCODE ",
6526#endif
6527#if _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF
6528	/*
6529	**  milter_body() uses the same conversion algorithm as putbody()
6530	**  to translate the "local" df format (\n) to SMTP format (\r\n).
6531	**  However, putbody() and mime8to7() use different conversion
6532	**  algorithms.
6533	**  If the input date does not follow the SMTP standard
6534	**  (e.g., if it has "naked \r"s), then the output from putbody()
6535	**  and mime8to7() will most likely be different.
6536	**  By turning on this FFR milter_body() will try to "imitate"
6537	**  mime8to7().
6538	**  Note: there is no (simple) way to deal with both conversions
6539	**  in a consistent manner. Moreover, as the "GiGo" principle applies,
6540	**  it's not really worth to fix it.
6541	*/
6542
6543	"_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF",
6544#endif
6545#if _FFR_MILTER_CHECK_REJECTIONS_TOO
6546	/*
6547	**  Also send RCPTs that are rejected by check_rcpt to a milter
6548	**  (if requested during option negotiation).
6549	*/
6550
6551	"_FFR_MILTER_CHECK_REJECTIONS_TOO",
6552#endif
6553#if _FFR_MILTER_ENHSC
6554	/* extract enhanced status code from milter replies for dsn= logging */
6555	"_FFR_MILTER_ENHSC",
6556#endif
6557#if _FFR_MIME7TO8_OLD
6558	/* Old mime7to8 code, the new is broken for at least one example. */
6559	"_FFR_MIME7TO8_OLD",
6560#endif
6561#if _FFR_MORE_MACROS
6562	/* allow more long macro names ("unprintable" characters). */
6563	"_FFR_MORE_MACROS",
6564#endif
6565#if _FFR_MSG_ACCEPT
6566	/* allow to override "Message accepted for delivery" */
6567	"_FFR_MSG_ACCEPT",
6568#endif
6569#if _FFR_NODELAYDSN_ON_HOLD
6570	/* Do not issue a DELAY DSN for mailers that use the hold flag. */
6571/* Steven Pitzl */
6572	"_FFR_NODELAYDSN_ON_HOLD",
6573#endif
6574#if _FFR_NO_PIPE
6575	/* Disable PIPELINING, delay client if used. */
6576	"_FFR_NO_PIPE",
6577#endif
6578#if _FFR_LDAP_SINGLEDN
6579	/*
6580	**  The LDAP database map code in Sendmail 8.12.10, when
6581	**  given the -1 switch, would match only a single DN,
6582	**  but was able to return multiple attributes for that
6583	**  DN.  In Sendmail 8.13 this "bug" was corrected to
6584	**  only return if exactly one attribute matched.
6585	**
6586	**  Unfortunately, our configuration uses the former
6587	**  behaviour.  Attached is a relatively simple patch
6588	**  to 8.13.4 which adds a -2 switch (for lack of a
6589	**  better option) which returns the single dn/multiple
6590	**  attributes.
6591	**
6592	** Jeffrey T. Eaton, Carnegie-Mellon University
6593	*/
6594
6595	"_FFR_LDAP_SINGLEDN",
6596#endif
6597#if _FFR_LOG_NTRIES
6598	/* log ntries=, from Nik Clayton of FreeBSD */
6599	"_FFR_LOG_NTRIES",
6600#endif
6601#if _FFR_OCC
6602# if SM_CONF_SHM
6603	/* outgoing connection control (not yet working) */
6604	"_FFR_OCC",
6605# else
6606#  ERROR: FFR_OCC requires _SM_CONF_SHM
6607# endif
6608#endif
6609#if _FFR_PROXY
6610	/* "proxy" (synchronous) delivery mode */
6611	"_FFR_PROXY",
6612#endif
6613#if _FFR_QF_PARANOIA
6614	/* Check to make sure key fields were read from qf */
6615	"_FFR_QF_PARANOIA",
6616#endif
6617#if _FFR_QUEUE_GROUP_SORTORDER
6618	/* Allow QueueSortOrder per queue group. */
6619/* XXX: Still need to actually use qgrp->qg_sortorder */
6620	"_FFR_QUEUE_GROUP_SORTORDER",
6621#endif
6622#if _FFR_QUEUE_MACRO
6623	/* Define {queue} macro. */
6624	"_FFR_QUEUE_MACRO",
6625#endif
6626#if _FFR_QUEUE_RUN_PARANOIA
6627	/* Additional checks when doing queue runs; interval of checks */
6628	"_FFR_QUEUE_RUN_PARANOIA",
6629#endif
6630#if _FFR_QUEUE_SCHED_DBG
6631	/* Debug output for the queue scheduler. */
6632	"_FFR_QUEUE_SCHED_DBG",
6633#endif
6634#if _FFR_RCPTFLAGS
6635	/* dynamic mailer modifications via {rcpt_flags}*/
6636	"_FFR_RCPTFLAGS",
6637#endif
6638#if _FFR_RCPTTHROTDELAY
6639	/* configurable delay for BadRcptThrottle */
6640	"_FFR_RCPTTHROTDELAY",
6641#endif
6642#if _FFR_REDIRECTEMPTY
6643	/*
6644	**  envelope <> can't be sent to mailing lists, only owner-
6645	**  send spam of this type to owner- of the list
6646	**  ----  to stop spam from going to mailing lists.
6647	*/
6648
6649	"_FFR_REDIRECTEMPTY",
6650#endif
6651#if _FFR_REJECT_NUL_BYTE
6652	/* reject NUL bytes in body */
6653	"_FFR_REJECT_NUL_BYTE",
6654#endif
6655#if _FFR_RESET_MACRO_GLOBALS
6656	/* Allow macro 'j' to be set dynamically via rulesets. */
6657	"_FFR_RESET_MACRO_GLOBALS",
6658#endif
6659#if _FFR_RHS
6660	/* Random shuffle for queue sorting. */
6661	"_FFR_RHS",
6662#endif
6663#if _FFR_RUNPQG
6664	/*
6665	**  allow -qGqueue_group -qp to work, i.e.,
6666	**  restrict a persistent queue runner to a queue group.
6667	*/
6668
6669	"_FFR_RUNPQG",
6670#endif
6671#if _FFR_SESSID
6672	/* session id (for logging): WIP, no logging yet!  */
6673	"_FFR_SESSID",
6674#endif
6675#if _FFR_SETANYOPT
6676	"_FFR_SETANYOPT",
6677#endif
6678#if _FFR_SETDEBUG_MAP
6679	"_FFR_SETDEBUG_MAP",
6680#endif
6681#if _FFR_SETOPT_MAP
6682	"_FFR_SETOPT_MAP",
6683#endif
6684#if _FFR_SHM_STATUS
6685	/* Donated code (unused). */
6686	"_FFR_SHM_STATUS",
6687#endif
6688#if _FFR_SKIP_DOMAINS
6689	/* process every N'th domain instead of every N'th message */
6690	"_FFR_SKIP_DOMAINS",
6691#endif
6692#if _FFR_SLEEP_USE_SELECT
6693	/* Use select(2) in libsm/clock.c to emulate sleep(2) */
6694	"_FFR_SLEEP_USE_SELECT ",
6695#endif
6696#if _FFR_SM_LDAP_DBG
6697# if LDAPMAP && defined(LBER_OPT_LOG_PRINT_FN)
6698	/* LDAP debugging */
6699	"_FFR_SM_LDAP_DBG",
6700# else
6701#  ERROR: FFR_SM_LDAP_DBG requires _LDAPMAP and LBER_OPT_LOG_PRINT_FN
6702# endif
6703#endif
6704#if _FFR_SPT_ALIGN
6705	/*
6706	**  It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64
6707	**  bit alignment, so unless each piece of argv and envp is a multiple
6708	**  of 8 bytes (including terminating NULL), initsetproctitle() won't
6709	**  use any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE
6710	**  if you use this FFR.
6711	*/
6712
6713/* Chris Adams of HiWAAY Informations Services */
6714	"_FFR_SPT_ALIGN",
6715#endif
6716#if _FFR_SS_PER_DAEMON
6717	/* SuperSafe per DaemonPortOptions: 'T' (better letter?) */
6718	"_FFR_SS_PER_DAEMON",
6719#endif
6720#if _FFR_TESTS
6721	/* enable some test code */
6722	"_FFR_TESTS",
6723#endif
6724#if _FFR_TIMERS
6725	/* Donated code (unused). */
6726	"_FFR_TIMERS",
6727#endif
6728#if _FFR_TLS_ALTNAMES
6729	/* store subjectAltNames in class {cert_altnames} */
6730# if STARTTLS
6731	"_FFR_TLS_ALTNAMES",
6732# else
6733#  error "_FFR_TLS_ALTNAMES set but STARTTLS not defined"
6734# endif
6735#endif
6736#if _FFR_TLSFB2CLEAR
6737	/* set default for TLSFallbacktoClear to true */
6738# if STARTTLS
6739	"_FFR_TLSFB2CLEAR",
6740# else
6741#  error "_FFR_TLSFB2CLEAR set but STARTTLS not defined"
6742# endif
6743#endif
6744#if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE
6745	/*
6746	**  Use SSL_CTX_use_certificate_chain_file()
6747	**  instead of SSL_CTX_use_certificate_file()
6748	*/
6749
6750# if STARTTLS
6751	"_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE",
6752# else
6753#  error "_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE set but STARTTLS not defined"
6754# endif
6755#endif
6756#if _FFR_TRUSTED_QF
6757	/*
6758	**  If we don't own the file mark it as unsafe.
6759	**  However, allow TrustedUser to own it as well
6760	**  in case TrustedUser manipulates the queue.
6761	*/
6762
6763	"_FFR_TRUSTED_QF",
6764#endif
6765#if _FFR_USE_GETPWNAM_ERRNO
6766	/*
6767	**  See libsm/mbdb.c: only enable this on OSs
6768	**  that implement the correct (POSIX) semantics.
6769	**  This will need to become an OS-specific #if enabled
6770	**  in one of the headers files under include/sm/os/ .
6771	*/
6772
6773	"_FFR_USE_GETPWNAM_ERRNO",
6774#endif
6775#if _FFR_VRFY_TRUSTED_FIRST
6776	/*
6777	**  Sets X509_V_FLAG_TRUSTED_FIRST if -d88;.101 is used.
6778	**  X509_VERIFY_PARAM_set_flags(3)
6779	**  When X509_V_FLAG_TRUSTED_FIRST is set, construction of the
6780	**  certificate chain in X509_verify_cert(3) will search the trust
6781	**  store for issuer certificates before searching the provided
6782	**  untrusted certificates. Local issuer certificates are often more
6783	**  likely to satisfy local security requirements and lead to a locally
6784	**  trusted root. This is especially important when some certificates
6785	**  in the trust store have explicit trust settings (see "TRUST
6786	**  SETTINGS" in x509(1)).
6787	**  As of OpenSSL 1.1.0 this option is on by default.
6788	*/
6789
6790# if defined(X509_V_FLAG_TRUSTED_FIRST)
6791	"_FFR_VRFY_TRUSTED_FIRST",
6792# else
6793#  error "FFR_VRFY_TRUSTED_FIRST set but X509_V_FLAG_TRUSTED_FIRST not defined"
6794# endif
6795#endif
6796
6797#if _FFR_USE_SEM_LOCKING
6798	/* Use semaphore locking */
6799	"_FFR_USE_SEM_LOCKING",
6800#endif
6801#if _FFR_USE_SETLOGIN
6802	/* Use setlogin() */
6803/* Peter Philipp */
6804	"_FFR_USE_SETLOGIN",
6805#endif
6806#if _FFR_XCNCT
6807	/* X-Connect support */
6808	"_FFR_XCNCT",
6809#endif
6810#if _FFR_EAI
6811
6812	/*
6813	**  Initial/Partial/Experimental EAI (SMTPUTF8) support.
6814	**  NOTE: This is currently BROKEN as the handling of
6815	**  envelope addresses in sendmail is NOT 8-bit clean
6816	**  (in contrast to header addresses/values).
6817	**  Requires ICU include files and library depending on the OS.
6818	**  Patch from Arnt Gulbrandsen.
6819	*/
6820
6821# if !ALLOW_255
6822#  ERROR FFR_EAI requires _ALLOW_255
6823# endif
6824# if _FFR_EIGHT_BIT_ADDR_OK
6825#  error "Cannot enable both of these FFRs: FFR_EAI FFR_EIGHT_BIT_ADDR_OK"
6826# endif
6827	"_FFR_EAI",
6828#endif
6829	NULL
6830};
6831