138032Speter/*
2261194Sgshapiro * Copyright (c) 1998-2013 Proofpoint, Inc. and its suppliers.
364565Sgshapiro *	All rights reserved.
438032Speter * Copyright (c) 1983, 1995-1997 Eric P. Allman.  All rights reserved.
538032Speter * Copyright (c) 1988, 1993
638032Speter *	The Regents of the University of California.  All rights reserved.
738032Speter *
838032Speter * By using this file, you agree to the terms and conditions set
938032Speter * forth in the LICENSE file which can be found at the top level of
1038032Speter * the sendmail distribution.
1138032Speter *
1238032Speter */
1338032Speter
1490795Sgshapiro#include <sendmail.h>
1538032Speter
16285229SgshapiroSM_RCSID("@(#)$Id: conf.c,v 8.1192 2014-01-27 18:23:21 ca Exp $")
1790795Sgshapiro
18168520Sgshapiro#include <sm/sendmail.h>
1964565Sgshapiro#include <sendmail/pathnames.h>
20120259Sgshapiro#if NEWDB
21120259Sgshapiro# include "sm/bdb.h"
22363466Sgshapiro#endif
2364565Sgshapiro
24168520Sgshapiro#include <daemon.h>
25168520Sgshapiro#include "map.h"
26363466Sgshapiro#include <ratectrl.h>
27168520Sgshapiro
28157006Sgshapiro#ifdef DEC
29157006Sgshapiro# if NETINET6
30157006Sgshapiro/* for the IPv6 device lookup */
31157006Sgshapiro#  define _SOCKADDR_LEN
32157006Sgshapiro#  include <macros.h>
33157006Sgshapiro# endif /* NETINET6 */
34157006Sgshapiro#endif /* DEC */
35157006Sgshapiro
3638032Speter# include <sys/ioctl.h>
3738032Speter# include <sys/param.h>
3838032Speter
3964565Sgshapiro#include <limits.h>
4064565Sgshapiro#if NETINET || NETINET6
4164565Sgshapiro# include <arpa/inet.h>
42363466Sgshapiro#endif
4364565Sgshapiro#if HASULIMIT && defined(HPUX11)
4464565Sgshapiro# include <ulimit.h>
45363466Sgshapiro#endif
46363466Sgshapiro#if STARTTLS
47363466Sgshapiro# include "tls.h"
48363466Sgshapiro#endif
4964565Sgshapiro
5064565Sgshapirostatic void	setupmaps __P((void));
5164565Sgshapirostatic void	setupmailers __P((void));
5290795Sgshapirostatic void	setupqueues __P((void));
5364565Sgshapirostatic int	get_num_procs_online __P((void));
54141862Sgshapirostatic int	add_hostnames __P((SOCKADDR *));
5564565Sgshapiro
56141862Sgshapiro#if NETINET6 && NEEDSGETIPNODE
57223067Sgshapirostatic struct hostent *sm_getipnodebyname __P((const char *, int, int, int *));
58223067Sgshapirostatic struct hostent *sm_getipnodebyaddr __P((const void *, size_t, int, int *));
59223067Sgshapiro#else /* NETINET6 && NEEDSGETIPNODE */
60244833Sgshapiro#define sm_getipnodebyname getipnodebyname
61223067Sgshapiro#define sm_getipnodebyaddr getipnodebyaddr
62141862Sgshapiro#endif /* NETINET6 && NEEDSGETIPNODE */
6364565Sgshapiro
64141862Sgshapiro
6538032Speter/*
6638032Speter**  CONF.C -- Sendmail Configuration Tables.
6738032Speter**
6838032Speter**	Defines the configuration of this installation.
6938032Speter**
7038032Speter**	Configuration Variables:
7138032Speter**		HdrInfo -- a table describing well-known header fields.
7238032Speter**			Each entry has the field name and some flags,
7338032Speter**			which are described in sendmail.h.
7438032Speter**
7538032Speter**	Notes:
7638032Speter**		I have tried to put almost all the reasonable
7738032Speter**		configuration information into the configuration
7838032Speter**		file read at runtime.  My intent is that anything
7938032Speter**		here is a function of the version of UNIX you
8038032Speter**		are running, or is really static -- for example
8138032Speter**		the headers are a superset of widely used
8238032Speter**		protocols.  If you find yourself playing with
8338032Speter**		this file too much, you may be making a mistake!
8438032Speter*/
8538032Speter
8638032Speter
8738032Speter/*
8838032Speter**  Header info table
8938032Speter**	Final (null) entry contains the flags used for any other field.
9038032Speter**
9138032Speter**	Not all of these are actually handled specially by sendmail
9238032Speter**	at this time.  They are included as placeholders, to let
9338032Speter**	you know that "someday" I intend to have sendmail do
9438032Speter**	something with them.
9538032Speter*/
9638032Speter
9738032Speterstruct hdrinfo	HdrInfo[] =
9838032Speter{
9964565Sgshapiro		/* originator fields, most to least significant */
10064565Sgshapiro	{ "resent-sender",		H_FROM|H_RESENT,	NULL	},
10164565Sgshapiro	{ "resent-from",		H_FROM|H_RESENT,	NULL	},
10264565Sgshapiro	{ "resent-reply-to",		H_FROM|H_RESENT,	NULL	},
10364565Sgshapiro	{ "sender",			H_FROM,			NULL	},
10464565Sgshapiro	{ "from",			H_FROM,			NULL	},
10564565Sgshapiro	{ "reply-to",			H_FROM,			NULL	},
10664565Sgshapiro	{ "errors-to",			H_FROM|H_ERRORSTO,	NULL	},
10764565Sgshapiro	{ "full-name",			H_ACHECK,		NULL	},
10864565Sgshapiro	{ "return-receipt-to",		H_RECEIPTTO,		NULL	},
109132946Sgshapiro	{ "delivery-receipt-to",	H_RECEIPTTO,		NULL	},
11090795Sgshapiro	{ "disposition-notification-to",	H_FROM,		NULL	},
11138032Speter
11238032Speter		/* destination fields */
11364565Sgshapiro	{ "to",				H_RCPT,			NULL	},
11464565Sgshapiro	{ "resent-to",			H_RCPT|H_RESENT,	NULL	},
11564565Sgshapiro	{ "cc",				H_RCPT,			NULL	},
11664565Sgshapiro	{ "resent-cc",			H_RCPT|H_RESENT,	NULL	},
11764565Sgshapiro	{ "bcc",			H_RCPT|H_BCC,		NULL	},
11864565Sgshapiro	{ "resent-bcc",			H_RCPT|H_BCC|H_RESENT,	NULL	},
11964565Sgshapiro	{ "apparently-to",		H_RCPT,			NULL	},
12038032Speter
12138032Speter		/* message identification and control */
12264565Sgshapiro	{ "message-id",			0,			NULL	},
12364565Sgshapiro	{ "resent-message-id",		H_RESENT,		NULL	},
124363466Sgshapiro#if !NO_EOH_FIELDS
12564565Sgshapiro	{ "message",			H_EOH,			NULL	},
12664565Sgshapiro	{ "text",			H_EOH,			NULL	},
127363466Sgshapiro#endif
12838032Speter
12938032Speter		/* date fields */
13064565Sgshapiro	{ "date",			0,			NULL	},
13164565Sgshapiro	{ "resent-date",		H_RESENT,		NULL	},
13238032Speter
13338032Speter		/* trace fields */
13464565Sgshapiro	{ "received",			H_TRACE|H_FORCE,	NULL	},
13564565Sgshapiro	{ "x400-received",		H_TRACE|H_FORCE,	NULL	},
13664565Sgshapiro	{ "via",			H_TRACE|H_FORCE,	NULL	},
13764565Sgshapiro	{ "mail-from",			H_TRACE|H_FORCE,	NULL	},
13838032Speter
13938032Speter		/* miscellaneous fields */
14064565Sgshapiro	{ "comments",			H_FORCE|H_ENCODABLE,	NULL	},
14164565Sgshapiro	{ "return-path",		H_FORCE|H_ACHECK|H_BINDLATE,	NULL	},
14264565Sgshapiro	{ "content-transfer-encoding",	H_CTE,			NULL	},
14364565Sgshapiro	{ "content-type",		H_CTYPE,		NULL	},
14464565Sgshapiro	{ "content-length",		H_ACHECK,		NULL	},
14564565Sgshapiro	{ "subject",			H_ENCODABLE,		NULL	},
14664565Sgshapiro	{ "x-authentication-warning",	H_FORCE,		NULL	},
14738032Speter
14864565Sgshapiro	{ NULL,				0,			NULL	}
14938032Speter};
15038032Speter
15138032Speter
15238032Speter
15338032Speter/*
15438032Speter**  Privacy values
15538032Speter*/
15638032Speter
15738032Speterstruct prival PrivacyValues[] =
15838032Speter{
15938032Speter	{ "public",		PRIV_PUBLIC		},
16038032Speter	{ "needmailhelo",	PRIV_NEEDMAILHELO	},
16138032Speter	{ "needexpnhelo",	PRIV_NEEDEXPNHELO	},
16238032Speter	{ "needvrfyhelo",	PRIV_NEEDVRFYHELO	},
16338032Speter	{ "noexpn",		PRIV_NOEXPN		},
16438032Speter	{ "novrfy",		PRIV_NOVRFY		},
16590795Sgshapiro	{ "restrictexpand",	PRIV_RESTRICTEXPAND	},
16638032Speter	{ "restrictmailq",	PRIV_RESTRICTMAILQ	},
16738032Speter	{ "restrictqrun",	PRIV_RESTRICTQRUN	},
16838032Speter	{ "noetrn",		PRIV_NOETRN		},
16938032Speter	{ "noverb",		PRIV_NOVERB		},
17038032Speter	{ "authwarnings",	PRIV_AUTHWARNINGS	},
17138032Speter	{ "noreceipts",		PRIV_NORECEIPTS		},
17264565Sgshapiro	{ "nobodyreturn",	PRIV_NOBODYRETN		},
17338032Speter	{ "goaway",		PRIV_GOAWAY		},
174141862Sgshapiro	{ "noactualrecipient",	PRIV_NOACTUALRECIPIENT	},
17538032Speter	{ NULL,			0			}
17638032Speter};
17738032Speter
17838032Speter/*
17938032Speter**  DontBlameSendmail values
18038032Speter*/
18190795Sgshapiro
18238032Speterstruct dbsval DontBlameSendmailValues[] =
18338032Speter{
18438032Speter	{ "safe",			DBS_SAFE			},
18538032Speter	{ "assumesafechown",		DBS_ASSUMESAFECHOWN		},
18638032Speter	{ "groupwritabledirpathsafe",	DBS_GROUPWRITABLEDIRPATHSAFE	},
18738032Speter	{ "groupwritableforwardfilesafe",
18838032Speter					DBS_GROUPWRITABLEFORWARDFILESAFE },
18938032Speter	{ "groupwritableincludefilesafe",
19038032Speter					DBS_GROUPWRITABLEINCLUDEFILESAFE },
19138032Speter	{ "groupwritablealiasfile",	DBS_GROUPWRITABLEALIASFILE	},
19238032Speter	{ "worldwritablealiasfile",	DBS_WORLDWRITABLEALIASFILE	},
19338032Speter	{ "forwardfileinunsafedirpath",	DBS_FORWARDFILEINUNSAFEDIRPATH	},
19438032Speter	{ "includefileinunsafedirpath",	DBS_INCLUDEFILEINUNSAFEDIRPATH	},
19538032Speter	{ "mapinunsafedirpath",		DBS_MAPINUNSAFEDIRPATH	},
19638032Speter	{ "linkedaliasfileinwritabledir",
19738032Speter					DBS_LINKEDALIASFILEINWRITABLEDIR },
19838032Speter	{ "linkedclassfileinwritabledir",
19938032Speter					DBS_LINKEDCLASSFILEINWRITABLEDIR },
20038032Speter	{ "linkedforwardfileinwritabledir",
20138032Speter					DBS_LINKEDFORWARDFILEINWRITABLEDIR },
20238032Speter	{ "linkedincludefileinwritabledir",
20338032Speter					DBS_LINKEDINCLUDEFILEINWRITABLEDIR },
20438032Speter	{ "linkedmapinwritabledir",	DBS_LINKEDMAPINWRITABLEDIR	},
20538032Speter	{ "linkedserviceswitchfileinwritabledir",
20638032Speter					DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR },
20738032Speter	{ "filedeliverytohardlink",	DBS_FILEDELIVERYTOHARDLINK	},
20838032Speter	{ "filedeliverytosymlink",	DBS_FILEDELIVERYTOSYMLINK	},
20938032Speter	{ "writemaptohardlink",		DBS_WRITEMAPTOHARDLINK		},
21038032Speter	{ "writemaptosymlink",		DBS_WRITEMAPTOSYMLINK		},
21138032Speter	{ "writestatstohardlink",	DBS_WRITESTATSTOHARDLINK	},
21238032Speter	{ "writestatstosymlink",	DBS_WRITESTATSTOSYMLINK		},
21338032Speter	{ "forwardfileingroupwritabledirpath",
21438032Speter					DBS_FORWARDFILEINGROUPWRITABLEDIRPATH },
21538032Speter	{ "includefileingroupwritabledirpath",
21638032Speter					DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH },
21738032Speter	{ "classfileinunsafedirpath",	DBS_CLASSFILEINUNSAFEDIRPATH	},
21838032Speter	{ "errorheaderinunsafedirpath",	DBS_ERRORHEADERINUNSAFEDIRPATH	},
21938032Speter	{ "helpfileinunsafedirpath",	DBS_HELPFILEINUNSAFEDIRPATH	},
22038032Speter	{ "forwardfileinunsafedirpathsafe",
22138032Speter					DBS_FORWARDFILEINUNSAFEDIRPATHSAFE },
22238032Speter	{ "includefileinunsafedirpathsafe",
22338032Speter					DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE },
22438032Speter	{ "runprograminunsafedirpath",	DBS_RUNPROGRAMINUNSAFEDIRPATH	},
22538032Speter	{ "runwritableprogram",		DBS_RUNWRITABLEPROGRAM		},
22664565Sgshapiro	{ "nonrootsafeaddr",		DBS_NONROOTSAFEADDR		},
22764565Sgshapiro	{ "truststickybit",		DBS_TRUSTSTICKYBIT		},
22864565Sgshapiro	{ "dontwarnforwardfileinunsafedirpath",
22964565Sgshapiro					DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH },
23064565Sgshapiro	{ "insufficiententropy",	DBS_INSUFFICIENTENTROPY },
23190795Sgshapiro	{ "groupreadablesasldbfile",	DBS_GROUPREADABLESASLDBFILE	},
23290795Sgshapiro	{ "groupwritablesasldbfile",	DBS_GROUPWRITABLESASLDBFILE	},
23366497Sgshapiro	{ "groupwritableforwardfile",	DBS_GROUPWRITABLEFORWARDFILE	},
23466497Sgshapiro	{ "groupwritableincludefile",	DBS_GROUPWRITABLEINCLUDEFILE	},
23566497Sgshapiro	{ "worldwritableforwardfile",	DBS_WORLDWRITABLEFORWARDFILE	},
23666497Sgshapiro	{ "worldwritableincludefile",	DBS_WORLDWRITABLEINCLUDEFILE	},
23790795Sgshapiro	{ "groupreadablekeyfile",	DBS_GROUPREADABLEKEYFILE	},
238285229Sgshapiro	{ "groupreadabledefaultauthinfofile",
23990795Sgshapiro					DBS_GROUPREADABLEAUTHINFOFILE	},
24038032Speter	{ NULL,				0				}
24138032Speter};
24238032Speter
24338032Speter/*
24438032Speter**  Miscellaneous stuff.
24538032Speter*/
24638032Speter
24738032Speterint	DtableSize =	50;		/* max open files; reset in 4.2bsd */
24890795Sgshapiro/*
24938032Speter**  SETDEFAULTS -- set default values
25038032Speter**
25190795Sgshapiro**	Some of these must be initialized using direct code since they
25290795Sgshapiro**	depend on run-time values. So let's do all of them this way.
25338032Speter**
25438032Speter**	Parameters:
25538032Speter**		e -- the default envelope.
25638032Speter**
25738032Speter**	Returns:
25838032Speter**		none.
25938032Speter**
26038032Speter**	Side Effects:
26138032Speter**		Initializes a bunch of global variables to their
26238032Speter**		default values.
26338032Speter*/
26438032Speter
26538032Speter#define MINUTES		* 60
26638032Speter#define HOURS		* 60 MINUTES
26738032Speter#define DAYS		* 24 HOURS
26838032Speter
26938032Speter#ifndef MAXRULERECURSION
27038032Speter# define MAXRULERECURSION	50	/* max ruleset recursion depth */
271363466Sgshapiro#endif
27238032Speter
27338032Spetervoid
27438032Spetersetdefaults(e)
27538032Speter	register ENVELOPE *e;
27638032Speter{
27738032Speter	int i;
27864565Sgshapiro	int numprocs;
27938032Speter	struct passwd *pw;
28038032Speter
28164565Sgshapiro	numprocs = get_num_procs_online();
28238032Speter	SpaceSub = ' ';				/* option B */
28364565Sgshapiro	QueueLA = 8 * numprocs;			/* option x */
28464565Sgshapiro	RefuseLA = 12 * numprocs;		/* option X */
28538032Speter	WkRecipFact = 30000L;			/* option y */
28638032Speter	WkClassFact = 1800L;			/* option z */
28738032Speter	WkTimeFact = 90000L;			/* option Z */
28838032Speter	QueueFactor = WkRecipFact * 20;		/* option q */
28990795Sgshapiro	QueueMode = QM_NORMAL;		/* what queue items to act upon */
29038032Speter	FileMode = (RealUid != geteuid()) ? 0644 : 0600;
29138032Speter						/* option F */
29264565Sgshapiro	QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600;
29364565Sgshapiro						/* option QueueFileMode */
29438032Speter
29564565Sgshapiro	if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) ||
29664565Sgshapiro	    ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) ||
29764565Sgshapiro	    ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0))
29838032Speter	{
29938032Speter		DefUid = pw->pw_uid;		/* option u */
30038032Speter		DefGid = pw->pw_gid;		/* option g */
30138032Speter		DefUser = newstr(pw->pw_name);
30238032Speter	}
30338032Speter	else
30438032Speter	{
30538032Speter		DefUid = 1;			/* option u */
30638032Speter		DefGid = 1;			/* option g */
30738032Speter		setdefuser();
30838032Speter	}
30942580Speter	TrustedUid = 0;
31038032Speter	if (tTd(37, 4))
311285229Sgshapiro		sm_dprintf("setdefaults: DefUser=%s, DefUid=%ld, DefGid=%ld\n",
31264565Sgshapiro			DefUser != NULL ? DefUser : "<1:1>",
313285229Sgshapiro			(long) DefUid, (long) DefGid);
31438032Speter	CheckpointInterval = 10;		/* option C */
31538032Speter	MaxHopCount = 25;			/* option h */
31664565Sgshapiro	set_delivery_mode(SM_FORK, e);		/* option d */
31738032Speter	e->e_errormode = EM_PRINT;		/* option e */
31890795Sgshapiro	e->e_qgrp = NOQGRP;
31990795Sgshapiro	e->e_qdir = NOQDIR;
32090795Sgshapiro	e->e_xfqgrp = NOQGRP;
32190795Sgshapiro	e->e_xfqdir = NOQDIR;
32264565Sgshapiro	e->e_ctime = curtime();
323363466Sgshapiro#if _FFR_EAI
324363466Sgshapiro	e->e_smtputf8 = false;
325363466Sgshapiro#endif
32690795Sgshapiro	SevenBitInput = false;			/* option 7 */
32738032Speter	MaxMciCache = 1;			/* option k */
32838032Speter	MciCacheTimeout = 5 MINUTES;		/* option K */
32938032Speter	LogLevel = 9;				/* option L */
33090795Sgshapiro#if MILTER
33190795Sgshapiro	MilterLogLevel = -1;
332363466Sgshapiro#endif
33390795Sgshapiro	inittimeouts(NULL, false);		/* option r */
33438032Speter	PrivacyFlags = PRIV_PUBLIC;		/* option p */
33590795Sgshapiro	MeToo = true;				/* option m */
33690795Sgshapiro	SendMIMEErrors = true;			/* option f */
33790795Sgshapiro	SuperSafe = SAFE_REALLY;		/* option s */
33864565Sgshapiro	clrbitmap(DontBlameSendmail);		/* DontBlameSendmail option */
33938032Speter#if MIME8TO7
34038032Speter	MimeMode = MM_CVTMIME|MM_PASS8BIT;	/* option 8 */
341363466Sgshapiro#else
34238032Speter	MimeMode = MM_PASS8BIT;
343363466Sgshapiro#endif
34438032Speter	for (i = 0; i < MAXTOCLASS; i++)
34538032Speter	{
34638032Speter		TimeOuts.to_q_return[i] = 5 DAYS;	/* option T */
34738032Speter		TimeOuts.to_q_warning[i] = 0;		/* option T */
34838032Speter	}
34964565Sgshapiro	ServiceSwitchFile = "/etc/mail/service.switch";
35038032Speter	ServiceCacheMaxAge = (time_t) 10;
35138032Speter	HostsFile = _PATH_HOSTS;
35238032Speter	PidFile = newstr(_PATH_SENDMAILPID);
35338032Speter	MustQuoteChars = "@,;:\\()[].'";
35438032Speter	MciInfoTimeout = 30 MINUTES;
35538032Speter	MaxRuleRecursion = MAXRULERECURSION;
35638032Speter	MaxAliasRecursion = 10;
35738032Speter	MaxMacroRecursion = 10;
35890795Sgshapiro	ColonOkInAddr = true;
35990795Sgshapiro	DontLockReadFiles = true;
36090795Sgshapiro	DontProbeInterfaces = DPI_PROBEALL;
36138032Speter	DoubleBounceAddr = "postmaster";
36243733Speter	MaxHeadersLength = MAXHDRSLEN;
363112813Sgshapiro	MaxMimeHeaderLength = MAXLINE;
364112813Sgshapiro	MaxMimeFieldLength = MaxMimeHeaderLength / 2;
36564565Sgshapiro	MaxForwardEntries = 0;
36690795Sgshapiro	FastSplit = 1;
367157006Sgshapiro	MaxNOOPCommands = MAXNOOPCOMMANDS;
36864565Sgshapiro#if SASL
36964565Sgshapiro	AuthMechanisms = newstr(AUTH_MECHANISMS);
370132946Sgshapiro	AuthRealm = NULL;
37190795Sgshapiro	MaxSLBits = INT_MAX;
372363466Sgshapiro#endif
37390795Sgshapiro#if STARTTLS
37490795Sgshapiro	TLS_Srv_Opts = TLS_I_SRV;
375285229Sgshapiro	if (NULL == EVP_digest)
376285229Sgshapiro		EVP_digest = EVP_md5();
377363466Sgshapiro# if _FFR_TLSFB2CLEAR
378363466Sgshapiro	TLSFallbacktoClear = true;
379363466Sgshapiro# endif
380363466Sgshapiro	Srv_SSL_Options = SSL_OP_ALL;
381363466Sgshapiro	Clt_SSL_Options = SSL_OP_ALL
382363466Sgshapiro# ifdef SSL_OP_NO_SSLv2
383363466Sgshapiro		| SSL_OP_NO_SSLv2
384363466Sgshapiro# endif
385363466Sgshapiro# ifdef SSL_OP_NO_TICKET
386363466Sgshapiro		| SSL_OP_NO_TICKET
387363466Sgshapiro# endif
388363466Sgshapiro		;
389363466Sgshapiro# ifdef SSL_OP_TLSEXT_PADDING
390363466Sgshapiro	/* SSL_OP_TLSEXT_PADDING breaks compatibility with some sites */
391363466Sgshapiro	Srv_SSL_Options &= ~SSL_OP_TLSEXT_PADDING;
392363466Sgshapiro	Clt_SSL_Options &= ~SSL_OP_TLSEXT_PADDING;
393363466Sgshapiro# endif /* SSL_OP_TLSEXT_PADDING */
39490795Sgshapiro#endif /* STARTTLS */
39538032Speter#ifdef HESIOD_INIT
39638032Speter	HesiodContext = NULL;
397363466Sgshapiro#endif
39864565Sgshapiro#if NETINET6
39964565Sgshapiro	/* Detect if IPv6 is available at run time */
40064565Sgshapiro	i = socket(AF_INET6, SOCK_STREAM, 0);
40164565Sgshapiro	if (i >= 0)
40264565Sgshapiro	{
40364565Sgshapiro		InetMode = AF_INET6;
40464565Sgshapiro		(void) close(i);
40564565Sgshapiro	}
40664565Sgshapiro	else
40764565Sgshapiro		InetMode = AF_INET;
408285229Sgshapiro#if !IPV6_FULL
409285229Sgshapiro	UseCompressedIPv6Addresses = true;
410285229Sgshapiro#endif
41164565Sgshapiro#else /* NETINET6 */
41264565Sgshapiro	InetMode = AF_INET;
41364565Sgshapiro#endif /* NETINET6 */
41442580Speter	ControlSocketName = NULL;
415168520Sgshapiro	memset(&ConnectOnlyTo, '\0', sizeof(ConnectOnlyTo));
41664565Sgshapiro	DataFileBufferSize = 4096;
41764565Sgshapiro	XscriptFileBufferSize = 4096;
41864565Sgshapiro	for (i = 0; i < MAXRWSETS; i++)
41964565Sgshapiro		RuleSetNames[i] = NULL;
42090795Sgshapiro#if MILTER
42164565Sgshapiro	InputFilters[0] = NULL;
422363466Sgshapiro#endif
423110563Sgshapiro	RejectLogInterval = 3 HOURS;
424132946Sgshapiro#if REQUIRES_DIR_FSYNC
425110563Sgshapiro	RequiresDirfsync = true;
426363466Sgshapiro#endif
427203004Sgshapiro#if _FFR_RCPTTHROTDELAY
428203004Sgshapiro	BadRcptThrottleDelay = 1;
429363466Sgshapiro#endif
430132946Sgshapiro	ConnectionRateWindowSize = 60;
431285229Sgshapiro#if _FFR_BOUNCE_QUEUE
432285229Sgshapiro	BounceQueue = NOQGRP;
433363466Sgshapiro#endif
43438032Speter	setupmaps();
43590795Sgshapiro	setupqueues();
43638032Speter	setupmailers();
43738032Speter	setupheaders();
43838032Speter}
43938032Speter
44038032Speter/*
44138032Speter**  SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
44238032Speter*/
44338032Speter
44438032Spetervoid
44538032Spetersetdefuser()
44638032Speter{
44738032Speter	struct passwd *defpwent;
44838032Speter	static char defuserbuf[40];
44938032Speter
45038032Speter	DefUser = defuserbuf;
45138032Speter	defpwent = sm_getpwuid(DefUid);
45290795Sgshapiro	(void) sm_strlcpy(defuserbuf,
45390795Sgshapiro			  (defpwent == NULL || defpwent->pw_name == NULL)
45490795Sgshapiro			   ? "nobody" : defpwent->pw_name,
455168520Sgshapiro			  sizeof(defuserbuf));
45638032Speter	if (tTd(37, 4))
457285229Sgshapiro		sm_dprintf("setdefuser: DefUid=%ld, DefUser=%s\n",
458285229Sgshapiro			   (long) DefUid, DefUser);
45938032Speter}
46090795Sgshapiro/*
46190795Sgshapiro**  SETUPQUEUES -- initialize default queues
46290795Sgshapiro**
46390795Sgshapiro**	The mqueue QUEUE structure gets filled in after readcf() but
46490795Sgshapiro**	we need something to point to now for the mailer setup,
46590795Sgshapiro**	which use "mqueue" as default queue.
46690795Sgshapiro*/
46790795Sgshapiro
46890795Sgshapirostatic void
46990795Sgshapirosetupqueues()
47090795Sgshapiro{
47190795Sgshapiro	char buf[100];
47290795Sgshapiro
47390795Sgshapiro	MaxRunnersPerQueue = 1;
474168520Sgshapiro	(void) sm_strlcpy(buf, "mqueue, P=/var/spool/mqueue", sizeof(buf));
47590795Sgshapiro	makequeue(buf, false);
47690795Sgshapiro}
47790795Sgshapiro/*
47838032Speter**  SETUPMAILERS -- initialize default mailers
47938032Speter*/
48038032Speter
48164565Sgshapirostatic void
48238032Spetersetupmailers()
48338032Speter{
48438032Speter	char buf[100];
48538032Speter
48690795Sgshapiro	(void) sm_strlcpy(buf, "prog, P=/bin/sh, F=lsouDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u",
487168520Sgshapiro			sizeof(buf));
48838032Speter	makemailer(buf);
48938032Speter
49090795Sgshapiro	(void) sm_strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE \201u",
491168520Sgshapiro			sizeof(buf));
49238032Speter	makemailer(buf);
49338032Speter
49490795Sgshapiro	(void) sm_strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u",
495168520Sgshapiro			sizeof(buf));
49638032Speter	makemailer(buf);
49764565Sgshapiro	initerrmailers();
49838032Speter}
49990795Sgshapiro/*
50038032Speter**  SETUPMAPS -- set up map classes
50138032Speter*/
50238032Speter
50338032Speter#define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \
50438032Speter	{ \
50538032Speter		extern bool parse __P((MAP *, char *)); \
50638032Speter		extern bool open __P((MAP *, int)); \
50738032Speter		extern void close __P((MAP *)); \
50838032Speter		extern char *lookup __P((MAP *, char *, char **, int *)); \
50938032Speter		extern void store __P((MAP *, char *, char *)); \
51038032Speter		s = stab(name, ST_MAPCLASS, ST_ENTER); \
51138032Speter		s->s_mapclass.map_cname = name; \
51238032Speter		s->s_mapclass.map_ext = ext; \
51338032Speter		s->s_mapclass.map_cflags = flags; \
51438032Speter		s->s_mapclass.map_parse = parse; \
51538032Speter		s->s_mapclass.map_open = open; \
51638032Speter		s->s_mapclass.map_close = close; \
51738032Speter		s->s_mapclass.map_lookup = lookup; \
51838032Speter		s->s_mapclass.map_store = store; \
51938032Speter	}
52038032Speter
52164565Sgshapirostatic void
52238032Spetersetupmaps()
52338032Speter{
52438032Speter	register STAB *s;
52538032Speter
52690795Sgshapiro#if NEWDB
527120259Sgshapiro# if DB_VERSION_MAJOR > 1
528120259Sgshapiro	int major_v, minor_v, patch_v;
529120259Sgshapiro
530120259Sgshapiro	(void) db_version(&major_v, &minor_v, &patch_v);
531120259Sgshapiro	if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR)
532120259Sgshapiro	{
533120259Sgshapiro		errno = 0;
534120259Sgshapiro		syserr("Berkeley DB version mismatch: compiled against %d.%d.%d, run-time linked against %d.%d.%d",
535120259Sgshapiro		  DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
536120259Sgshapiro		  major_v, minor_v, patch_v);
537120259Sgshapiro	}
538120259Sgshapiro# endif /* DB_VERSION_MAJOR > 1 */
539120259Sgshapiro
54038032Speter	MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
54138032Speter		map_parseargs, hash_map_open, db_map_close,
54238032Speter		db_map_lookup, db_map_store);
54338032Speter
54438032Speter	MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
54538032Speter		map_parseargs, bt_map_open, db_map_close,
54638032Speter		db_map_lookup, db_map_store);
54764565Sgshapiro#endif /* NEWDB */
54838032Speter
54990795Sgshapiro#if NDBM
55038032Speter	MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE,
55138032Speter		map_parseargs, ndbm_map_open, ndbm_map_close,
55238032Speter		ndbm_map_lookup, ndbm_map_store);
553363466Sgshapiro#endif
55438032Speter
555363466Sgshapiro#if CDB
556363466Sgshapiro	MAPDEF("cdb", CDBEXT, MCF_ALIASOK|MCF_REBUILDABLE,
557363466Sgshapiro		map_parseargs, cdb_map_open, cdb_map_close,
558363466Sgshapiro		cdb_map_lookup, cdb_map_store);
559363466Sgshapiro#endif
560363466Sgshapiro
56190795Sgshapiro#if NIS
56238032Speter	MAPDEF("nis", NULL, MCF_ALIASOK,
56338032Speter		map_parseargs, nis_map_open, null_map_close,
56438032Speter		nis_map_lookup, null_map_store);
565363466Sgshapiro#endif
56638032Speter
56790795Sgshapiro#if NISPLUS
56838032Speter	MAPDEF("nisplus", NULL, MCF_ALIASOK,
56938032Speter		map_parseargs, nisplus_map_open, null_map_close,
57038032Speter		nisplus_map_lookup, null_map_store);
571363466Sgshapiro#endif
57264565Sgshapiro
57390795Sgshapiro#if LDAPMAP
57490795Sgshapiro	MAPDEF("ldap", NULL, MCF_ALIASOK|MCF_NOTPERSIST,
57564565Sgshapiro		ldapmap_parseargs, ldapmap_open, ldapmap_close,
57664565Sgshapiro		ldapmap_lookup, null_map_store);
577363466Sgshapiro#endif
57864565Sgshapiro
57990795Sgshapiro#if PH_MAP
58090795Sgshapiro	MAPDEF("ph", NULL, MCF_NOTPERSIST,
58164565Sgshapiro		ph_map_parseargs, ph_map_open, ph_map_close,
58264565Sgshapiro		ph_map_lookup, null_map_store);
583363466Sgshapiro#endif
58464565Sgshapiro
58564565Sgshapiro#if MAP_NSD
58664565Sgshapiro	/* IRIX 6.5 nsd support */
58764565Sgshapiro	MAPDEF("nsd", NULL, MCF_ALIASOK,
58864565Sgshapiro	       map_parseargs, null_map_open, null_map_close,
58964565Sgshapiro	       nsd_map_lookup, null_map_store);
590363466Sgshapiro#endif
59164565Sgshapiro
59290795Sgshapiro#if HESIOD
593363466Sgshapiro	MAPDEF("hesiod", NULL, MCF_ALIASOK,
59490795Sgshapiro		map_parseargs, hes_map_open, hes_map_close,
59538032Speter		hes_map_lookup, null_map_store);
596363466Sgshapiro#endif
59738032Speter
59838032Speter#if NETINFO
59938032Speter	MAPDEF("netinfo", NULL, MCF_ALIASOK,
60038032Speter		map_parseargs, ni_map_open, null_map_close,
60138032Speter		ni_map_lookup, null_map_store);
602363466Sgshapiro#endif
60338032Speter
60438032Speter#if 0
60538032Speter	MAPDEF("dns", NULL, 0,
60638032Speter		dns_map_init, null_map_open, null_map_close,
60738032Speter		dns_map_lookup, null_map_store);
60864565Sgshapiro#endif /* 0 */
60938032Speter
61038032Speter#if NAMED_BIND
61190795Sgshapiro# if DNSMAP
61294337Sgshapiro#  if _FFR_DNSMAP_ALIASABLE
61394337Sgshapiro	MAPDEF("dns", NULL, MCF_ALIASOK,
61494337Sgshapiro	       dns_map_parseargs, dns_map_open, null_map_close,
61594337Sgshapiro	       dns_map_lookup, null_map_store);
61694337Sgshapiro#  else /* _FFR_DNSMAP_ALIASABLE */
61790795Sgshapiro	MAPDEF("dns", NULL, 0,
61890795Sgshapiro	       dns_map_parseargs, dns_map_open, null_map_close,
61990795Sgshapiro	       dns_map_lookup, null_map_store);
62094337Sgshapiro#  endif /* _FFR_DNSMAP_ALIASABLE */
62190795Sgshapiro# endif /* DNSMAP */
62290795Sgshapiro#endif /* NAMED_BIND */
62390795Sgshapiro
62490795Sgshapiro#if NAMED_BIND
62538032Speter	/* best MX DNS lookup */
62638032Speter	MAPDEF("bestmx", NULL, MCF_OPTFILE,
62738032Speter		map_parseargs, null_map_open, null_map_close,
62838032Speter		bestmx_map_lookup, null_map_store);
629363466Sgshapiro#endif
63038032Speter
63138032Speter	MAPDEF("host", NULL, 0,
63238032Speter		host_map_init, null_map_open, null_map_close,
63338032Speter		host_map_lookup, null_map_store);
63438032Speter
63538032Speter	MAPDEF("text", NULL, MCF_ALIASOK,
63638032Speter		map_parseargs, text_map_open, null_map_close,
63738032Speter		text_map_lookup, null_map_store);
63838032Speter
639363466Sgshapiro	MAPDEF("stab", NULL, MCF_ALIASOK,
64038032Speter		map_parseargs, stab_map_open, null_map_close,
64138032Speter		stab_map_lookup, stab_map_store);
64238032Speter
643363466Sgshapiro	MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_REBUILDABLE,
64438032Speter		map_parseargs, impl_map_open, impl_map_close,
64538032Speter		impl_map_lookup, impl_map_store);
64638032Speter
64738032Speter	/* access to system passwd file */
64838032Speter	MAPDEF("user", NULL, MCF_OPTFILE,
64938032Speter		map_parseargs, user_map_open, null_map_close,
65038032Speter		user_map_lookup, null_map_store);
65138032Speter
65238032Speter	/* dequote map */
65338032Speter	MAPDEF("dequote", NULL, 0,
65438032Speter		dequote_init, null_map_open, null_map_close,
65538032Speter		dequote_map, null_map_store);
65638032Speter
65790795Sgshapiro#if MAP_REGEX
65838032Speter	MAPDEF("regex", NULL, 0,
65938032Speter		regex_map_init, null_map_open, null_map_close,
66038032Speter		regex_map_lookup, null_map_store);
661363466Sgshapiro#endif
66238032Speter
66338032Speter#if USERDB
66438032Speter	/* user database */
66538032Speter	MAPDEF("userdb", ".db", 0,
66638032Speter		map_parseargs, null_map_open, null_map_close,
66738032Speter		udb_map_lookup, null_map_store);
668363466Sgshapiro#endif
66938032Speter
67038032Speter	/* arbitrary programs */
67138032Speter	MAPDEF("program", NULL, MCF_ALIASOK,
67238032Speter		map_parseargs, null_map_open, null_map_close,
67338032Speter		prog_map_lookup, null_map_store);
67438032Speter
67538032Speter	/* sequenced maps */
67638032Speter	MAPDEF("sequence", NULL, MCF_ALIASOK,
67738032Speter		seq_map_parse, null_map_open, null_map_close,
67838032Speter		seq_map_lookup, seq_map_store);
67938032Speter
68038032Speter	/* switched interface to sequenced maps */
68138032Speter	MAPDEF("switch", NULL, MCF_ALIASOK,
68238032Speter		map_parseargs, switch_map_open, null_map_close,
68338032Speter		seq_map_lookup, seq_map_store);
68438032Speter
68538032Speter	/* null map lookup -- really for internal use only */
68638032Speter	MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE,
68738032Speter		map_parseargs, null_map_open, null_map_close,
68838032Speter		null_map_lookup, null_map_store);
68938032Speter
69038032Speter	/* syslog map -- logs information to syslog */
69138032Speter	MAPDEF("syslog", NULL, 0,
69264565Sgshapiro		syslog_map_parseargs, null_map_open, null_map_close,
69364565Sgshapiro		syslog_map_lookup, null_map_store);
69464565Sgshapiro
69564565Sgshapiro	/* macro storage map -- rulesets can set macros */
69664565Sgshapiro	MAPDEF("macro", NULL, 0,
69764565Sgshapiro		dequote_init, null_map_open, null_map_close,
69864565Sgshapiro		macro_map_lookup, null_map_store);
69964565Sgshapiro
70064565Sgshapiro	/* arithmetic map -- add/subtract/compare */
70164565Sgshapiro	MAPDEF("arith", NULL, 0,
70264565Sgshapiro		dequote_init, null_map_open, null_map_close,
70364565Sgshapiro		arith_map_lookup, null_map_store);
70464565Sgshapiro
705261194Sgshapiro	/* "arpa" map -- IP -> arpa */
706261194Sgshapiro	MAPDEF("arpa", NULL, 0,
707261194Sgshapiro		dequote_init, null_map_open, null_map_close,
708261194Sgshapiro		arpa_map_lookup, null_map_store);
709261194Sgshapiro
710132946Sgshapiro#if SOCKETMAP
711132946Sgshapiro	/* arbitrary daemons */
712132946Sgshapiro	MAPDEF("socket", NULL, MCF_ALIASOK,
713132946Sgshapiro		map_parseargs, socket_map_open, socket_map_close,
714132946Sgshapiro		socket_map_lookup, null_map_store);
715363466Sgshapiro#endif
716132946Sgshapiro
717168520Sgshapiro#if _FFR_DPRINTF_MAP
718168520Sgshapiro	/* dprintf map -- logs information to syslog */
719168520Sgshapiro	MAPDEF("dprintf", NULL, 0,
720168520Sgshapiro		dprintf_map_parseargs, null_map_open, null_map_close,
721168520Sgshapiro		dprintf_map_lookup, null_map_store);
722363466Sgshapiro#endif
723168520Sgshapiro
724363466Sgshapiro#if _FFR_SETDEBUG_MAP
725363466Sgshapiro	/* setdebug map -- set debug levels */
726363466Sgshapiro	MAPDEF("setdebug", NULL, 0,
727363466Sgshapiro		dequote_init, null_map_open, null_map_close,
728363466Sgshapiro		setdebug_map_lookup, null_map_store);
729363466Sgshapiro#endif
730363466Sgshapiro
731363466Sgshapiro#if _FFR_SETOPT_MAP
732363466Sgshapiro	/* setopt map -- set option */
733363466Sgshapiro	MAPDEF("setopt", NULL, 0,
734363466Sgshapiro		dequote_init, null_map_open, null_map_close,
735363466Sgshapiro		setopt_map_lookup, null_map_store);
736363466Sgshapiro#endif
737363466Sgshapiro
73864565Sgshapiro	if (tTd(38, 2))
73964565Sgshapiro	{
74064565Sgshapiro		/* bogus map -- always return tempfail */
74164565Sgshapiro		MAPDEF("bogus",	NULL, MCF_ALIASOK|MCF_OPTFILE,
74264565Sgshapiro		       map_parseargs, null_map_open, null_map_close,
74364565Sgshapiro		       bogus_map_lookup, null_map_store);
74464565Sgshapiro	}
74538032Speter}
74638032Speter
74738032Speter#undef MAPDEF
74890795Sgshapiro/*
74938032Speter**  INITHOSTMAPS -- initial host-dependent maps
75038032Speter**
75138032Speter**	This should act as an interface to any local service switch
75238032Speter**	provided by the host operating system.
75338032Speter**
75438032Speter**	Parameters:
75538032Speter**		none
75638032Speter**
75738032Speter**	Returns:
75838032Speter**		none
75938032Speter**
76038032Speter**	Side Effects:
76138032Speter**		Should define maps "host" and "users" as necessary
76238032Speter**		for this OS.  If they are not defined, they will get
76338032Speter**		a default value later.  It should check to make sure
76438032Speter**		they are not defined first, since it's possible that
76538032Speter**		the config file has provided an override.
76638032Speter*/
76738032Speter
76838032Spetervoid
76938032Speterinithostmaps()
77038032Speter{
77138032Speter	register int i;
77238032Speter	int nmaps;
77338032Speter	char *maptype[MAXMAPSTACK];
77438032Speter	short mapreturn[MAXMAPACTIONS];
77538032Speter	char buf[MAXLINE];
77638032Speter
77738032Speter	/*
77838032Speter	**  Make sure we have a host map.
77938032Speter	*/
78038032Speter
78138032Speter	if (stab("host", ST_MAP, ST_FIND) == NULL)
78238032Speter	{
78338032Speter		/* user didn't initialize: set up host map */
784168520Sgshapiro		(void) sm_strlcpy(buf, "host host", sizeof(buf));
78538032Speter#if NAMED_BIND
78638032Speter		if (ConfigLevel >= 2)
787168520Sgshapiro			(void) sm_strlcat(buf, " -a. -D", sizeof(buf));
788363466Sgshapiro#endif
78938032Speter		(void) makemapentry(buf);
79038032Speter	}
79138032Speter
79238032Speter	/*
79338032Speter	**  Set up default aliases maps
79438032Speter	*/
79538032Speter
79638032Speter	nmaps = switch_map_find("aliases", maptype, mapreturn);
79738032Speter	for (i = 0; i < nmaps; i++)
79838032Speter	{
79938032Speter		if (strcmp(maptype[i], "files") == 0 &&
80038032Speter		    stab("aliases.files", ST_MAP, ST_FIND) == NULL)
80138032Speter		{
80290795Sgshapiro			(void) sm_strlcpy(buf, "aliases.files null",
803168520Sgshapiro					  sizeof(buf));
80438032Speter			(void) makemapentry(buf);
80538032Speter		}
806363466Sgshapiro#if CDB
807363466Sgshapiro		else if (strcmp(maptype[i], "cdb") == 0 &&
808363466Sgshapiro			 stab("aliases.cdb", ST_MAP, ST_FIND) == NULL)
809363466Sgshapiro		{
810363466Sgshapiro			(void) sm_strlcpy(buf, "aliases.cdb null", sizeof(buf));
811363466Sgshapiro			(void) makemapentry(buf);
812363466Sgshapiro		}
813363466Sgshapiro#endif /* CDB */
81490795Sgshapiro#if NISPLUS
81538032Speter		else if (strcmp(maptype[i], "nisplus") == 0 &&
81690795Sgshapiro			 stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL)
81738032Speter		{
81890795Sgshapiro			(void) sm_strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir",
819168520Sgshapiro				sizeof(buf));
82038032Speter			(void) makemapentry(buf);
82138032Speter		}
82264565Sgshapiro#endif /* NISPLUS */
82390795Sgshapiro#if NIS
82438032Speter		else if (strcmp(maptype[i], "nis") == 0 &&
82590795Sgshapiro			 stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
82638032Speter		{
82790795Sgshapiro			(void) sm_strlcpy(buf, "aliases.nis nis mail.aliases",
828168520Sgshapiro				sizeof(buf));
82938032Speter			(void) makemapentry(buf);
83038032Speter		}
83164565Sgshapiro#endif /* NIS */
83264565Sgshapiro#if NETINFO
83338032Speter		else if (strcmp(maptype[i], "netinfo") == 0 &&
83490795Sgshapiro			 stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
83538032Speter		{
83690795Sgshapiro			(void) sm_strlcpy(buf, "aliases.netinfo netinfo -z, /aliases",
837168520Sgshapiro				sizeof(buf));
83838032Speter			(void) makemapentry(buf);
83938032Speter		}
84064565Sgshapiro#endif /* NETINFO */
84190795Sgshapiro#if HESIOD
84238032Speter		else if (strcmp(maptype[i], "hesiod") == 0 &&
84390795Sgshapiro			 stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL)
84438032Speter		{
84590795Sgshapiro			(void) sm_strlcpy(buf, "aliases.hesiod hesiod aliases",
846168520Sgshapiro				sizeof(buf));
84738032Speter			(void) makemapentry(buf);
84838032Speter		}
84964565Sgshapiro#endif /* HESIOD */
850168520Sgshapiro#if LDAPMAP && defined(SUN_EXTENSIONS) && \
851168520Sgshapiro    defined(SUN_SIMPLIFIED_LDAP) && HASLDAPGETALIASBYNAME
852168520Sgshapiro		else if (strcmp(maptype[i], "ldap") == 0 &&
853168520Sgshapiro		    stab("aliases.ldap", ST_MAP, ST_FIND) == NULL)
85438032Speter		{
855203004Sgshapiro			(void) sm_strlcpy(buf, "aliases.ldap ldap -b . -h localhost -k mail=%0 -v mailgroup",
85664565Sgshapiro				sizeof buf);
85738032Speter			(void) makemapentry(buf);
85838032Speter		}
859168520Sgshapiro#endif /* LDAPMAP && defined(SUN_EXTENSIONS) && ... */
86038032Speter	}
861168520Sgshapiro	if (stab("aliases", ST_MAP, ST_FIND) == NULL)
86238032Speter	{
863168520Sgshapiro		(void) sm_strlcpy(buf, "aliases switch aliases", sizeof(buf));
86438032Speter		(void) makemapentry(buf);
86538032Speter	}
86638032Speter}
867168520Sgshapiro
86890795Sgshapiro/*
86938032Speter**  SWITCH_MAP_FIND -- find the list of types associated with a map
87038032Speter**
87138032Speter**	This is the system-dependent interface to the service switch.
87238032Speter**
87338032Speter**	Parameters:
87438032Speter**		service -- the name of the service of interest.
87538032Speter**		maptype -- an out-array of strings containing the types
87638032Speter**			of access to use for this service.  There can
87738032Speter**			be at most MAXMAPSTACK types for a single service.
87838032Speter**		mapreturn -- an out-array of return information bitmaps
87938032Speter**			for the map.
88038032Speter**
88138032Speter**	Returns:
88238032Speter**		The number of map types filled in, or -1 for failure.
88364565Sgshapiro**
88464565Sgshapiro**	Side effects:
88564565Sgshapiro**		Preserves errno so nothing in the routine clobbers it.
88638032Speter*/
88738032Speter
88838032Speter#if defined(SOLARIS) || (defined(sony_news) && defined(__svr4))
88938032Speter# define _USE_SUN_NSSWITCH_
890363466Sgshapiro#endif
89138032Speter
89290795Sgshapiro#if _FFR_HPUX_NSSWITCH
89390795Sgshapiro# ifdef __hpux
89490795Sgshapiro#  define _USE_SUN_NSSWITCH_
895363466Sgshapiro# endif
89690795Sgshapiro#endif /* _FFR_HPUX_NSSWITCH */
89790795Sgshapiro
89838032Speter#ifdef _USE_SUN_NSSWITCH_
89938032Speter# include <nsswitch.h>
900363466Sgshapiro#endif
90138032Speter
90238032Speter#if defined(ultrix) || (defined(__osf__) && defined(__alpha))
90338032Speter# define _USE_DEC_SVC_CONF_
904363466Sgshapiro#endif
90538032Speter
90638032Speter#ifdef _USE_DEC_SVC_CONF_
90738032Speter# include <sys/svcinfo.h>
908363466Sgshapiro#endif
90938032Speter
91038032Speterint
91138032Speterswitch_map_find(service, maptype, mapreturn)
91238032Speter	char *service;
91338032Speter	char *maptype[MAXMAPSTACK];
91438032Speter	short mapreturn[MAXMAPACTIONS];
91538032Speter{
91671348Sgshapiro	int svcno = 0;
91764565Sgshapiro	int save_errno = errno;
91838032Speter
91938032Speter#ifdef _USE_SUN_NSSWITCH_
92038032Speter	struct __nsw_switchconfig *nsw_conf;
92138032Speter	enum __nsw_parse_err pserr;
92238032Speter	struct __nsw_lookup *lk;
92338032Speter	static struct __nsw_lookup lkp0 =
92438032Speter		{ "files", {1, 0, 0, 0}, NULL, NULL };
92538032Speter	static struct __nsw_switchconfig lkp_default =
92638032Speter		{ 0, "sendmail", 3, &lkp0 };
92738032Speter
92838032Speter	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
92938032Speter		mapreturn[svcno] = 0;
93038032Speter
93138032Speter	if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL)
93238032Speter		lk = lkp_default.lookups;
93338032Speter	else
93438032Speter		lk = nsw_conf->lookups;
93538032Speter	svcno = 0;
93671348Sgshapiro	while (lk != NULL && svcno < MAXMAPSTACK)
93738032Speter	{
93838032Speter		maptype[svcno] = lk->service_name;
93938032Speter		if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN)
94038032Speter			mapreturn[MA_NOTFOUND] |= 1 << svcno;
94138032Speter		if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN)
94238032Speter			mapreturn[MA_TRYAGAIN] |= 1 << svcno;
94338032Speter		if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN)
94438032Speter			mapreturn[MA_TRYAGAIN] |= 1 << svcno;
94538032Speter		svcno++;
94638032Speter		lk = lk->next;
94738032Speter	}
94864565Sgshapiro	errno = save_errno;
94938032Speter	return svcno;
95064565Sgshapiro#endif /* _USE_SUN_NSSWITCH_ */
95138032Speter
95238032Speter#ifdef _USE_DEC_SVC_CONF_
95338032Speter	struct svcinfo *svcinfo;
95438032Speter	int svc;
95538032Speter
95638032Speter	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
95738032Speter		mapreturn[svcno] = 0;
95838032Speter
95938032Speter	svcinfo = getsvc();
96038032Speter	if (svcinfo == NULL)
96138032Speter		goto punt;
96238032Speter	if (strcmp(service, "hosts") == 0)
96338032Speter		svc = SVC_HOSTS;
96438032Speter	else if (strcmp(service, "aliases") == 0)
96538032Speter		svc = SVC_ALIASES;
96638032Speter	else if (strcmp(service, "passwd") == 0)
96738032Speter		svc = SVC_PASSWD;
96838032Speter	else
96964565Sgshapiro	{
97064565Sgshapiro		errno = save_errno;
97138032Speter		return -1;
97264565Sgshapiro	}
97371348Sgshapiro	for (svcno = 0; svcno < SVC_PATHSIZE && svcno < MAXMAPSTACK; svcno++)
97438032Speter	{
97538032Speter		switch (svcinfo->svcpath[svc][svcno])
97638032Speter		{
97738032Speter		  case SVC_LOCAL:
97838032Speter			maptype[svcno] = "files";
97938032Speter			break;
98038032Speter
98138032Speter		  case SVC_YP:
98238032Speter			maptype[svcno] = "nis";
98338032Speter			break;
98438032Speter
98538032Speter		  case SVC_BIND:
98638032Speter			maptype[svcno] = "dns";
98738032Speter			break;
98838032Speter
98964565Sgshapiro# ifdef SVC_HESIOD
99038032Speter		  case SVC_HESIOD:
99138032Speter			maptype[svcno] = "hesiod";
99238032Speter			break;
993363466Sgshapiro# endif
99438032Speter
99538032Speter		  case SVC_LAST:
99664565Sgshapiro			errno = save_errno;
99738032Speter			return svcno;
99838032Speter		}
99938032Speter	}
100064565Sgshapiro	errno = save_errno;
100138032Speter	return svcno;
100264565Sgshapiro#endif /* _USE_DEC_SVC_CONF_ */
100338032Speter
100438032Speter#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
100538032Speter	/*
100638032Speter	**  Fall-back mechanism.
100738032Speter	*/
100838032Speter
100938032Speter	STAB *st;
101090795Sgshapiro	static time_t servicecachetime;	/* time service switch was cached */
101138032Speter	time_t now = curtime();
101238032Speter
101338032Speter	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
101438032Speter		mapreturn[svcno] = 0;
101538032Speter
101690795Sgshapiro	if ((now - servicecachetime) > (time_t) ServiceCacheMaxAge)
101738032Speter	{
101838032Speter		/* (re)read service switch */
101990795Sgshapiro		register SM_FILE_T *fp;
102064565Sgshapiro		long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK;
102138032Speter
102264565Sgshapiro		if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR,
102364565Sgshapiro			    DontBlameSendmail))
102438032Speter			sff |= SFF_NOWLINK;
102538032Speter
102638032Speter		if (ConfigFileRead)
102790795Sgshapiro			servicecachetime = now;
102838032Speter		fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff);
102938032Speter		if (fp != NULL)
103038032Speter		{
103138032Speter			char buf[MAXLINE];
103238032Speter
103390795Sgshapiro			while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf,
1034249729Sgshapiro					   sizeof(buf)) >= 0)
103538032Speter			{
103638032Speter				register char *p;
103738032Speter
103838032Speter				p = strpbrk(buf, "#\n");
103938032Speter				if (p != NULL)
104038032Speter					*p = '\0';
1041203004Sgshapiro#ifndef SM_NSSWITCH_DELIMS
1042203004Sgshapiro# define SM_NSSWITCH_DELIMS	" \t"
1043363466Sgshapiro#endif
1044203004Sgshapiro				p = strpbrk(buf, SM_NSSWITCH_DELIMS);
104538032Speter				if (p != NULL)
104638032Speter					*p++ = '\0';
104738032Speter				if (buf[0] == '\0')
104838032Speter					continue;
104942580Speter				if (p == NULL)
105042580Speter				{
105142580Speter					sm_syslog(LOG_ERR, NOQID,
105242580Speter						  "Bad line on %.100s: %.100s",
105342580Speter						  ServiceSwitchFile,
105442580Speter						  buf);
105542580Speter					continue;
105642580Speter				}
1057363466Sgshapiro				while (SM_ISSPACE(*p))
105838032Speter					p++;
105938032Speter				if (*p == '\0')
106038032Speter					continue;
106138032Speter
106238032Speter				/*
106338032Speter				**  Find/allocate space for this service entry.
106438032Speter				**	Space for all of the service strings
106538032Speter				**	are allocated at once.  This means
106638032Speter				**	that we only have to free the first
106738032Speter				**	one to free all of them.
106838032Speter				*/
106938032Speter
107038032Speter				st = stab(buf, ST_SERVICE, ST_ENTER);
107138032Speter				if (st->s_service[0] != NULL)
107290795Sgshapiro					sm_free((void *) st->s_service[0]); /* XXX */
107338032Speter				p = newstr(p);
107438032Speter				for (svcno = 0; svcno < MAXMAPSTACK; )
107538032Speter				{
107638032Speter					if (*p == '\0')
107738032Speter						break;
107838032Speter					st->s_service[svcno++] = p;
107938032Speter					p = strpbrk(p, " \t");
108038032Speter					if (p == NULL)
108138032Speter						break;
108238032Speter					*p++ = '\0';
1083363466Sgshapiro					while (SM_ISSPACE(*p))
108438032Speter						p++;
108538032Speter				}
108638032Speter				if (svcno < MAXMAPSTACK)
108738032Speter					st->s_service[svcno] = NULL;
108838032Speter			}
108990795Sgshapiro			(void) sm_io_close(fp, SM_TIME_DEFAULT);
109038032Speter		}
109138032Speter	}
109238032Speter
109338032Speter	/* look up entry in cache */
109438032Speter	st = stab(service, ST_SERVICE, ST_FIND);
109538032Speter	if (st != NULL && st->s_service[0] != NULL)
109638032Speter	{
109738032Speter		/* extract data */
109838032Speter		svcno = 0;
109938032Speter		while (svcno < MAXMAPSTACK)
110038032Speter		{
110138032Speter			maptype[svcno] = st->s_service[svcno];
110238032Speter			if (maptype[svcno++] == NULL)
110338032Speter				break;
110438032Speter		}
110564565Sgshapiro		errno = save_errno;
110638032Speter		return --svcno;
110738032Speter	}
110864565Sgshapiro#endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */
110938032Speter
111038032Speter#if !defined(_USE_SUN_NSSWITCH_)
111138032Speter	/* if the service file doesn't work, use an absolute fallback */
111238032Speter# ifdef _USE_DEC_SVC_CONF_
111338032Speter  punt:
1114363466Sgshapiro# endif
111538032Speter	for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
111638032Speter		mapreturn[svcno] = 0;
111738032Speter	svcno = 0;
111838032Speter	if (strcmp(service, "aliases") == 0)
111938032Speter	{
1120363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
112138032Speter		maptype[svcno++] = "files";
1122363466Sgshapiro# if CDB
1123363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
1124363466Sgshapiro		maptype[svcno++] = "cdb";
1125363466Sgshapiro# endif
112664565Sgshapiro# if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO)
1127363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
112864565Sgshapiro		maptype[svcno++] = "netinfo";
1129363466Sgshapiro# endif
113038032Speter# ifdef AUTO_NIS_ALIASES
113190795Sgshapiro#  if NISPLUS
1132363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
113338032Speter		maptype[svcno++] = "nisplus";
1134363466Sgshapiro#  endif
113590795Sgshapiro#  if NIS
1136363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
113738032Speter		maptype[svcno++] = "nis";
1138363466Sgshapiro#  endif
113964565Sgshapiro# endif /* AUTO_NIS_ALIASES */
114064565Sgshapiro		errno = save_errno;
114138032Speter		return svcno;
114238032Speter	}
114338032Speter	if (strcmp(service, "hosts") == 0)
114438032Speter	{
114564565Sgshapiro# if NAMED_BIND
1146363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
114738032Speter		maptype[svcno++] = "dns";
114864565Sgshapiro# else /* NAMED_BIND */
114964565Sgshapiro#  if defined(sun) && !defined(BSD)
115038032Speter		/* SunOS */
1151363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
115238032Speter		maptype[svcno++] = "nis";
115364565Sgshapiro#  endif /* defined(sun) && !defined(BSD) */
115464565Sgshapiro# endif /* NAMED_BIND */
115564565Sgshapiro# if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO)
1156363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
115764565Sgshapiro		maptype[svcno++] = "netinfo";
1158363466Sgshapiro# endif
1159363466Sgshapiro		SM_ASSERT(svcno < MAXMAPSTACK);
116038032Speter		maptype[svcno++] = "files";
116164565Sgshapiro		errno = save_errno;
116238032Speter		return svcno;
116338032Speter	}
116464565Sgshapiro	errno = save_errno;
116538032Speter	return -1;
116664565Sgshapiro#endif /* !defined(_USE_SUN_NSSWITCH_) */
116738032Speter}
116890795Sgshapiro/*
116938032Speter**  USERNAME -- return the user id of the logged in user.
117038032Speter**
117138032Speter**	Parameters:
117238032Speter**		none.
117338032Speter**
117438032Speter**	Returns:
117538032Speter**		The login name of the logged in user.
117638032Speter**
117738032Speter**	Side Effects:
117838032Speter**		none.
117938032Speter**
118038032Speter**	Notes:
118138032Speter**		The return value is statically allocated.
118238032Speter*/
118338032Speter
118438032Speterchar *
118538032Speterusername()
118638032Speter{
118738032Speter	static char *myname = NULL;
118838032Speter	extern char *getlogin();
118938032Speter	register struct passwd *pw;
119038032Speter
119138032Speter	/* cache the result */
119238032Speter	if (myname == NULL)
119338032Speter	{
119438032Speter		myname = getlogin();
119538032Speter		if (myname == NULL || myname[0] == '\0')
119638032Speter		{
119738032Speter			pw = sm_getpwuid(RealUid);
119838032Speter			if (pw != NULL)
119990795Sgshapiro				myname = pw->pw_name;
120038032Speter		}
120138032Speter		else
120238032Speter		{
120338032Speter			uid_t uid = RealUid;
120438032Speter
120538032Speter			if ((pw = sm_getpwnam(myname)) == NULL ||
120638032Speter			      (uid != 0 && uid != pw->pw_uid))
120738032Speter			{
120838032Speter				pw = sm_getpwuid(uid);
120938032Speter				if (pw != NULL)
121090795Sgshapiro					myname = pw->pw_name;
121138032Speter			}
121238032Speter		}
121338032Speter		if (myname == NULL || myname[0] == '\0')
121438032Speter		{
121564565Sgshapiro			syserr("554 5.3.0 Who are you?");
121638032Speter			myname = "postmaster";
121738032Speter		}
121890795Sgshapiro		else if (strpbrk(myname, ",;:/|\"\\") != NULL)
121990795Sgshapiro			myname = addquotes(myname, NULL);
122090795Sgshapiro		else
122190795Sgshapiro			myname = sm_pstrdup_x(myname);
122238032Speter	}
122364565Sgshapiro	return myname;
122438032Speter}
122590795Sgshapiro/*
122638032Speter**  TTYPATH -- Get the path of the user's tty
122738032Speter**
122838032Speter**	Returns the pathname of the user's tty.  Returns NULL if
122938032Speter**	the user is not logged in or if s/he has write permission
123038032Speter**	denied.
123138032Speter**
123238032Speter**	Parameters:
123338032Speter**		none
123438032Speter**
123538032Speter**	Returns:
123638032Speter**		pathname of the user's tty.
123738032Speter**		NULL if not logged in or write permission denied.
123838032Speter**
123938032Speter**	Side Effects:
124038032Speter**		none.
124138032Speter**
124238032Speter**	WARNING:
124338032Speter**		Return value is in a local buffer.
124438032Speter**
124538032Speter**	Called By:
124638032Speter**		savemail
124738032Speter*/
124838032Speter
124938032Speterchar *
125038032Speterttypath()
125138032Speter{
125238032Speter	struct stat stbuf;
125338032Speter	register char *pathn;
125438032Speter	extern char *ttyname();
125538032Speter	extern char *getlogin();
125638032Speter
125738032Speter	/* compute the pathname of the controlling tty */
125838032Speter	if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
125938032Speter	    (pathn = ttyname(0)) == NULL)
126038032Speter	{
126138032Speter		errno = 0;
126264565Sgshapiro		return NULL;
126338032Speter	}
126438032Speter
126538032Speter	/* see if we have write permission */
126638032Speter	if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode))
126738032Speter	{
126838032Speter		errno = 0;
126964565Sgshapiro		return NULL;
127038032Speter	}
127138032Speter
127238032Speter	/* see if the user is logged in */
127338032Speter	if (getlogin() == NULL)
127464565Sgshapiro		return NULL;
127538032Speter
127638032Speter	/* looks good */
127764565Sgshapiro	return pathn;
127838032Speter}
127990795Sgshapiro/*
128038032Speter**  CHECKCOMPAT -- check for From and To person compatible.
128138032Speter**
128238032Speter**	This routine can be supplied on a per-installation basis
128338032Speter**	to determine whether a person is allowed to send a message.
128438032Speter**	This allows restriction of certain types of internet
128538032Speter**	forwarding or registration of users.
128638032Speter**
128738032Speter**	If the hosts are found to be incompatible, an error
128838032Speter**	message should be given using "usrerr" and an EX_ code
128938032Speter**	should be returned.  You can also set to->q_status to
129038032Speter**	a DSN-style status code.
129138032Speter**
129238032Speter**	EF_NO_BODY_RETN can be set in e->e_flags to suppress the
129338032Speter**	body during the return-to-sender function; this should be done
129438032Speter**	on huge messages.  This bit may already be set by the ESMTP
129538032Speter**	protocol.
129638032Speter**
129738032Speter**	Parameters:
129838032Speter**		to -- the person being sent to.
129938032Speter**
130038032Speter**	Returns:
130138032Speter**		an exit status
130238032Speter**
130338032Speter**	Side Effects:
130438032Speter**		none (unless you include the usrerr stuff)
130538032Speter*/
130638032Speter
130738032Speterint
130838032Spetercheckcompat(to, e)
130938032Speter	register ADDRESS *to;
131038032Speter	register ENVELOPE *e;
131138032Speter{
131238032Speter	if (tTd(49, 1))
131390795Sgshapiro		sm_dprintf("checkcompat(to=%s, from=%s)\n",
131438032Speter			to->q_paddr, e->e_from.q_paddr);
131538032Speter
131664565Sgshapiro#ifdef EXAMPLE_CODE
131738032Speter	/* this code is intended as an example only */
131838032Speter	register STAB *s;
131938032Speter
132038032Speter	s = stab("arpa", ST_MAILER, ST_FIND);
132138032Speter	if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 &&
132238032Speter	    to->q_mailer == s->s_mailer)
132338032Speter	{
132438032Speter		usrerr("553 No ARPA mail through this machine: see your system administration");
132564565Sgshapiro		/* e->e_flags |= EF_NO_BODY_RETN; to suppress body on return */
132638032Speter		to->q_status = "5.7.1";
132764565Sgshapiro		return EX_UNAVAILABLE;
132838032Speter	}
132964565Sgshapiro#endif /* EXAMPLE_CODE */
133064565Sgshapiro	return EX_OK;
133138032Speter}
1332168520Sgshapiro
1333168520Sgshapiro#ifdef SUN_EXTENSIONS
1334168520Sgshapirostatic void
1335168520Sgshapiroinit_md_sun()
1336168520Sgshapiro{
1337168520Sgshapiro	struct stat sbuf;
1338168520Sgshapiro
1339168520Sgshapiro	/* Check for large file descriptor */
1340168520Sgshapiro	if (fstat(fileno(stdin), &sbuf) < 0)
1341168520Sgshapiro	{
1342168520Sgshapiro		if (errno == EOVERFLOW)
1343168520Sgshapiro		{
1344168520Sgshapiro			perror("stdin");
1345168520Sgshapiro			exit(EX_NOINPUT);
1346168520Sgshapiro		}
1347168520Sgshapiro	}
1348168520Sgshapiro}
1349168520Sgshapiro#endif /* SUN_EXTENSIONS */
1350168520Sgshapiro
135190795Sgshapiro/*
135238032Speter**  INIT_MD -- do machine dependent initializations
135338032Speter**
135438032Speter**	Systems that have global modes that should be set should do
135538032Speter**	them here rather than in main.
135638032Speter*/
135738032Speter
135838032Speter#ifdef _AUX_SOURCE
135938032Speter# include <compat.h>
1360363466Sgshapiro#endif
136138032Speter
136238032Speter#if SHARE_V1
136338032Speter# include <shares.h>
1364363466Sgshapiro#endif
136538032Speter
136638032Spetervoid
136738032Speterinit_md(argc, argv)
136838032Speter	int argc;
136938032Speter	char **argv;
137038032Speter{
137138032Speter#ifdef _AUX_SOURCE
137238032Speter	setcompat(getcompat() | COMPAT_BSDPROT);
1373363466Sgshapiro#endif
137438032Speter
137538032Speter#ifdef SUN_EXTENSIONS
137638032Speter	init_md_sun();
1377363466Sgshapiro#endif
137838032Speter
137938032Speter#if _CONVEX_SOURCE
138038032Speter	/* keep gethostby*() from stripping the local domain name */
138138032Speter	set_domain_trim_off();
1382363466Sgshapiro#endif
1383168520Sgshapiro#if defined(__QNX__) && !defined(__QNXNTO__)
138438032Speter	/*
138542580Speter	**  Due to QNX's network distributed nature, you can target a tcpip
138642580Speter	**  stack on a different node in the qnx network; this patch lets
138742580Speter	**  this feature work.  The __sock_locate() must be done before the
138842580Speter	**  environment is clear.
138938032Speter	*/
139038032Speter	__sock_locate();
139164565Sgshapiro#endif /* __QNX__ */
139238032Speter#if SECUREWARE || defined(_SCO_unix_)
139338032Speter	set_auth_parameters(argc, argv);
139438032Speter
139538032Speter# ifdef _SCO_unix_
139638032Speter	/*
139738032Speter	**  This is required for highest security levels (the kernel
139838032Speter	**  won't let it call set*uid() or run setuid binaries without
139938032Speter	**  it).  It may be necessary on other SECUREWARE systems.
140038032Speter	*/
140138032Speter
140238032Speter	if (getluid() == -1)
140338032Speter		setluid(0);
140464565Sgshapiro# endif /* _SCO_unix_ */
140564565Sgshapiro#endif /* SECUREWARE || defined(_SCO_unix_) */
140638032Speter
140764565Sgshapiro
140838032Speter#ifdef VENDOR_DEFAULT
140938032Speter	VendorCode = VENDOR_DEFAULT;
1410363466Sgshapiro#else
141138032Speter	VendorCode = VENDOR_BERKELEY;
1412363466Sgshapiro#endif
141338032Speter}
141490795Sgshapiro/*
141538032Speter**  INIT_VENDOR_MACROS -- vendor-dependent macro initializations
141638032Speter**
141738032Speter**	Called once, on startup.
141838032Speter**
141938032Speter**	Parameters:
142038032Speter**		e -- the global envelope.
142138032Speter**
142238032Speter**	Returns:
142338032Speter**		none.
142438032Speter**
142538032Speter**	Side Effects:
142638032Speter**		vendor-dependent.
142738032Speter*/
142838032Speter
142938032Spetervoid
143038032Speterinit_vendor_macros(e)
143138032Speter	register ENVELOPE *e;
143238032Speter{
143338032Speter}
143490795Sgshapiro/*
143538032Speter**  GETLA -- get the current load average
143638032Speter**
143738032Speter**	This code stolen from la.c.
143838032Speter**
143938032Speter**	Parameters:
144038032Speter**		none.
144138032Speter**
144238032Speter**	Returns:
144338032Speter**		The current load average as an integer.
144438032Speter**
144538032Speter**	Side Effects:
144638032Speter**		none.
144738032Speter*/
144838032Speter
144938032Speter/* try to guess what style of load average we have */
145038032Speter#define LA_ZERO		1	/* always return load average as zero */
145138032Speter#define LA_INT		2	/* read kmem for avenrun; interpret as long */
145238032Speter#define LA_FLOAT	3	/* read kmem for avenrun; interpret as float */
145338032Speter#define LA_SUBR		4	/* call getloadavg */
145438032Speter#define LA_MACH		5	/* MACH load averages (as on NeXT boxes) */
145538032Speter#define LA_SHORT	6	/* read kmem for avenrun; interpret as short */
145638032Speter#define LA_PROCSTR	7	/* read string ("1.17") from /proc/loadavg */
145738032Speter#define LA_READKSYM	8	/* SVR4: use MIOC_READKSYM ioctl call */
145838032Speter#define LA_DGUX		9	/* special DGUX implementation */
145938032Speter#define LA_HPUX		10	/* special HPUX implementation */
146038032Speter#define LA_IRIX6	11	/* special IRIX 6.2 implementation */
146138032Speter#define LA_KSTAT	12	/* special Solaris kstat(3k) implementation */
146238032Speter#define LA_DEVSHORT	13	/* read short from a device */
146338032Speter#define LA_ALPHAOSF	14	/* Digital UNIX (OSF/1 on Alpha) table() call */
146471348Sgshapiro#define LA_PSET		15	/* Solaris per-processor-set load average */
1465147081Sgshapiro#define LA_LONGLONG	17 /* read kmem for avenrun; interpret as long long */
146638032Speter
146738032Speter/* do guesses based on general OS type */
146838032Speter#ifndef LA_TYPE
146938032Speter# define LA_TYPE	LA_ZERO
1470363466Sgshapiro#endif
147138032Speter
147238032Speter#ifndef FSHIFT
147338032Speter# if defined(unixpc)
147438032Speter#  define FSHIFT	5
1475363466Sgshapiro# endif
147638032Speter
147738032Speter# if defined(__alpha) || defined(IRIX)
147838032Speter#  define FSHIFT	10
1479363466Sgshapiro# endif
148038032Speter
148164565Sgshapiro#endif /* ! FSHIFT */
148238032Speter
148338032Speter#ifndef FSHIFT
148438032Speter# define FSHIFT		8
1485363466Sgshapiro#endif
148638032Speter
148738032Speter#ifndef FSCALE
148838032Speter# define FSCALE		(1 << FSHIFT)
1489363466Sgshapiro#endif
149038032Speter
149138032Speter#ifndef LA_AVENRUN
149238032Speter# ifdef SYSTEM5
149338032Speter#  define LA_AVENRUN	"avenrun"
1494363466Sgshapiro# else
149538032Speter#  define LA_AVENRUN	"_avenrun"
1496363466Sgshapiro# endif
149764565Sgshapiro#endif /* ! LA_AVENRUN */
149838032Speter
149938032Speter/* _PATH_KMEM should be defined in <paths.h> */
150038032Speter#ifndef _PATH_KMEM
150138032Speter# define _PATH_KMEM	"/dev/kmem"
1502363466Sgshapiro#endif
150338032Speter
1504147081Sgshapiro#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG)
150538032Speter
150664565Sgshapiro# include <nlist.h>
150738032Speter
150838032Speter/* _PATH_UNIX should be defined in <paths.h> */
150964565Sgshapiro# ifndef _PATH_UNIX
151064565Sgshapiro#  if defined(SYSTEM5)
151164565Sgshapiro#   define _PATH_UNIX	"/unix"
1512363466Sgshapiro#  else
151364565Sgshapiro#   define _PATH_UNIX	"/vmunix"
1514363466Sgshapiro#  endif
151564565Sgshapiro# endif /* ! _PATH_UNIX */
151638032Speter
151764565Sgshapiro# ifdef _AUX_SOURCE
151838032Speterstruct nlist	Nl[2];
151964565Sgshapiro# else /* _AUX_SOURCE */
152038032Speterstruct nlist	Nl[] =
152138032Speter{
152238032Speter	{ LA_AVENRUN },
152338032Speter	{ 0 },
152438032Speter};
152564565Sgshapiro# endif /* _AUX_SOURCE */
152664565Sgshapiro# define X_AVENRUN	0
152738032Speter
152890795Sgshapiroint
152938032Spetergetla()
153038032Speter{
153190795Sgshapiro	int j;
153238032Speter	static int kmem = -1;
153364565Sgshapiro# if LA_TYPE == LA_INT
153438032Speter	long avenrun[3];
153564565Sgshapiro# else /* LA_TYPE == LA_INT */
153664565Sgshapiro#  if LA_TYPE == LA_SHORT
153738032Speter	short avenrun[3];
1538147081Sgshapiro#  else
1539147081Sgshapiro#   if LA_TYPE == LA_LONGLONG
1540147081Sgshapiro	long long avenrun[3];
1541363466Sgshapiro#   else
154238032Speter	double avenrun[3];
1543363466Sgshapiro#   endif
154464565Sgshapiro#  endif /* LA_TYPE == LA_SHORT */
154564565Sgshapiro# endif /* LA_TYPE == LA_INT */
154638032Speter	extern off_t lseek();
154738032Speter
154838032Speter	if (kmem < 0)
154938032Speter	{
155064565Sgshapiro# ifdef _AUX_SOURCE
155190795Sgshapiro		(void) sm_strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN,
1552168520Sgshapiro			       sizeof(Nl[X_AVENRUN].n_name));
155338032Speter		Nl[1].n_name[0] = '\0';
155464565Sgshapiro# endif /* _AUX_SOURCE */
155538032Speter
155664565Sgshapiro# if defined(_AIX3) || defined(_AIX4)
1557168520Sgshapiro		if (knlist(Nl, 1, sizeof(Nl[0])) < 0)
1558363466Sgshapiro# else
155938032Speter		if (nlist(_PATH_UNIX, Nl) < 0)
1560363466Sgshapiro# endif
156138032Speter		{
156238032Speter			if (tTd(3, 1))
156390795Sgshapiro				sm_dprintf("getla: nlist(%s): %s\n", _PATH_UNIX,
156490795Sgshapiro					   sm_errstring(errno));
156564565Sgshapiro			return -1;
156638032Speter		}
156738032Speter		if (Nl[X_AVENRUN].n_value == 0)
156838032Speter		{
156938032Speter			if (tTd(3, 1))
157090795Sgshapiro				sm_dprintf("getla: nlist(%s, %s) ==> 0\n",
157138032Speter					_PATH_UNIX, LA_AVENRUN);
157264565Sgshapiro			return -1;
157338032Speter		}
157464565Sgshapiro# ifdef NAMELISTMASK
157538032Speter		Nl[X_AVENRUN].n_value &= NAMELISTMASK;
1576363466Sgshapiro# endif
157738032Speter
157838032Speter		kmem = open(_PATH_KMEM, 0, 0);
157938032Speter		if (kmem < 0)
158038032Speter		{
158138032Speter			if (tTd(3, 1))
158290795Sgshapiro				sm_dprintf("getla: open(/dev/kmem): %s\n",
158390795Sgshapiro					   sm_errstring(errno));
158464565Sgshapiro			return -1;
158538032Speter		}
158690795Sgshapiro		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
158790795Sgshapiro		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
158890795Sgshapiro		{
158990795Sgshapiro			if (tTd(3, 1))
159090795Sgshapiro				sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
159190795Sgshapiro					   sm_errstring(errno));
159290795Sgshapiro			(void) close(kmem);
159390795Sgshapiro			kmem = -1;
159490795Sgshapiro			return -1;
159590795Sgshapiro		}
159638032Speter	}
159738032Speter	if (tTd(3, 20))
159890795Sgshapiro		sm_dprintf("getla: symbol address = %#lx\n",
159990795Sgshapiro			(unsigned long) Nl[X_AVENRUN].n_value);
160038032Speter	if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 ||
1601182352Sgshapiro	    read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun))
160238032Speter	{
160338032Speter		/* thank you Ian */
160438032Speter		if (tTd(3, 1))
160590795Sgshapiro			sm_dprintf("getla: lseek or read: %s\n",
160690795Sgshapiro				   sm_errstring(errno));
160764565Sgshapiro		return -1;
160838032Speter	}
1609147081Sgshapiro# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG)
161038032Speter	if (tTd(3, 5))
161138032Speter	{
161238032Speter#  if LA_TYPE == LA_SHORT
161390795Sgshapiro		sm_dprintf("getla: avenrun = %d", avenrun[0]);
161438032Speter		if (tTd(3, 15))
161590795Sgshapiro			sm_dprintf(", %d, %d", avenrun[1], avenrun[2]);
161664565Sgshapiro#  else /* LA_TYPE == LA_SHORT */
1617147081Sgshapiro#   if LA_TYPE == LA_LONGLONG
1618147081Sgshapiro		sm_dprintf("getla: avenrun = %lld", avenrun[0]);
1619147081Sgshapiro		if (tTd(3, 15))
1620147081Sgshapiro			sm_dprintf(", %lld, %lld", avenrun[1], avenrun[2]);
1621147081Sgshapiro#   else /* LA_TYPE == LA_LONGLONG */
162290795Sgshapiro		sm_dprintf("getla: avenrun = %ld", avenrun[0]);
162338032Speter		if (tTd(3, 15))
162490795Sgshapiro			sm_dprintf(", %ld, %ld", avenrun[1], avenrun[2]);
1625147081Sgshapiro#   endif /* LA_TYPE == LA_LONGLONG */
162664565Sgshapiro#  endif /* LA_TYPE == LA_SHORT */
162790795Sgshapiro		sm_dprintf("\n");
162838032Speter	}
162938032Speter	if (tTd(3, 1))
163090795Sgshapiro		sm_dprintf("getla: %d\n",
163164565Sgshapiro			(int) (avenrun[0] + FSCALE/2) >> FSHIFT);
163238032Speter	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
1633147081Sgshapiro# else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
163438032Speter	if (tTd(3, 5))
163538032Speter	{
163690795Sgshapiro		sm_dprintf("getla: avenrun = %g", avenrun[0]);
163738032Speter		if (tTd(3, 15))
163890795Sgshapiro			sm_dprintf(", %g, %g", avenrun[1], avenrun[2]);
163990795Sgshapiro		sm_dprintf("\n");
164038032Speter	}
164138032Speter	if (tTd(3, 1))
164290795Sgshapiro		sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
164338032Speter	return ((int) (avenrun[0] + 0.5));
1644147081Sgshapiro# endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
164538032Speter}
164638032Speter
1647147081Sgshapiro#endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
164838032Speter
164938032Speter#if LA_TYPE == LA_READKSYM
165038032Speter
165138032Speter# include <sys/ksym.h>
165238032Speter
165390795Sgshapiroint
165438032Spetergetla()
165538032Speter{
165690795Sgshapiro	int j;
165738032Speter	static int kmem = -1;
165838032Speter	long avenrun[3];
165938032Speter	struct mioc_rksym mirk;
166038032Speter
166138032Speter	if (kmem < 0)
166238032Speter	{
166338032Speter		kmem = open("/dev/kmem", 0, 0);
166438032Speter		if (kmem < 0)
166538032Speter		{
166638032Speter			if (tTd(3, 1))
166790795Sgshapiro				sm_dprintf("getla: open(/dev/kmem): %s\n",
166890795Sgshapiro					   sm_errstring(errno));
166964565Sgshapiro			return -1;
167038032Speter		}
167190795Sgshapiro		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
167290795Sgshapiro		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
167390795Sgshapiro		{
167490795Sgshapiro			if (tTd(3, 1))
167590795Sgshapiro				sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
167690795Sgshapiro					   sm_errstring(errno));
167790795Sgshapiro			(void) close(kmem);
167890795Sgshapiro			kmem = -1;
167990795Sgshapiro			return -1;
168090795Sgshapiro		}
168138032Speter	}
168238032Speter	mirk.mirk_symname = LA_AVENRUN;
168338032Speter	mirk.mirk_buf = avenrun;
168438032Speter	mirk.mirk_buflen = sizeof(avenrun);
168538032Speter	if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0)
168638032Speter	{
168738032Speter		if (tTd(3, 1))
168890795Sgshapiro			sm_dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n",
168990795Sgshapiro				   sm_errstring(errno));
169038032Speter		return -1;
169138032Speter	}
169238032Speter	if (tTd(3, 5))
169338032Speter	{
169490795Sgshapiro		sm_dprintf("getla: avenrun = %d", avenrun[0]);
169538032Speter		if (tTd(3, 15))
169690795Sgshapiro			sm_dprintf(", %d, %d", avenrun[1], avenrun[2]);
169790795Sgshapiro		sm_dprintf("\n");
169838032Speter	}
169938032Speter	if (tTd(3, 1))
170090795Sgshapiro		sm_dprintf("getla: %d\n",
170164565Sgshapiro			(int) (avenrun[0] + FSCALE/2) >> FSHIFT);
170238032Speter	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
170338032Speter}
170438032Speter
170538032Speter#endif /* LA_TYPE == LA_READKSYM */
170638032Speter
170738032Speter#if LA_TYPE == LA_DGUX
170838032Speter
170938032Speter# include <sys/dg_sys_info.h>
171038032Speter
171190795Sgshapiroint
171238032Spetergetla()
171338032Speter{
171438032Speter	struct dg_sys_info_load_info load_info;
171538032Speter
171638032Speter	dg_sys_info((long *)&load_info,
171738032Speter		DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
171838032Speter
171938032Speter	if (tTd(3, 1))
172090795Sgshapiro		sm_dprintf("getla: %d\n", (int) (load_info.one_minute + 0.5));
172138032Speter
172264565Sgshapiro	return ((int) (load_info.one_minute + 0.5));
172338032Speter}
172438032Speter
172538032Speter#endif /* LA_TYPE == LA_DGUX */
172638032Speter
172738032Speter#if LA_TYPE == LA_HPUX
172838032Speter
172938032Speter/* forward declarations to keep gcc from complaining */
173038032Speterstruct pst_dynamic;
173138032Speterstruct pst_status;
173238032Speterstruct pst_static;
173338032Speterstruct pst_vminfo;
173438032Speterstruct pst_diskinfo;
173538032Speterstruct pst_processor;
173638032Speterstruct pst_lv;
173738032Speterstruct pst_swapinfo;
173838032Speter
173938032Speter# include <sys/param.h>
174038032Speter# include <sys/pstat.h>
174138032Speter
174290795Sgshapiroint
174338032Spetergetla()
174438032Speter{
174538032Speter	struct pst_dynamic pstd;
174638032Speter
174738032Speter	if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic),
174838032Speter			     (size_t) 1, 0) == -1)
174938032Speter		return 0;
175038032Speter
175138032Speter	if (tTd(3, 1))
175290795Sgshapiro		sm_dprintf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
175338032Speter
175438032Speter	return (int) (pstd.psd_avg_1_min + 0.5);
175538032Speter}
175638032Speter
175738032Speter#endif /* LA_TYPE == LA_HPUX */
175838032Speter
175938032Speter#if LA_TYPE == LA_SUBR
176038032Speter
176190795Sgshapiroint
176238032Spetergetla()
176338032Speter{
176438032Speter	double avenrun[3];
176538032Speter
176638032Speter	if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
176738032Speter	{
176838032Speter		if (tTd(3, 1))
176990795Sgshapiro			sm_dprintf("getla: getloadavg failed: %s",
177090795Sgshapiro				   sm_errstring(errno));
177164565Sgshapiro		return -1;
177238032Speter	}
177338032Speter	if (tTd(3, 1))
177490795Sgshapiro		sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
177538032Speter	return ((int) (avenrun[0] + 0.5));
177638032Speter}
177738032Speter
177838032Speter#endif /* LA_TYPE == LA_SUBR */
177938032Speter
178038032Speter#if LA_TYPE == LA_MACH
178138032Speter
178238032Speter/*
178338032Speter**  This has been tested on NEXTSTEP release 2.1/3.X.
178438032Speter*/
178538032Speter
178664565Sgshapiro# if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
178764565Sgshapiro#  include <mach/mach.h>
1788363466Sgshapiro# else
178964565Sgshapiro#  include <mach.h>
1790363466Sgshapiro# endif
179138032Speter
179290795Sgshapiroint
179338032Spetergetla()
179438032Speter{
179538032Speter	processor_set_t default_set;
179638032Speter	kern_return_t error;
179738032Speter	unsigned int info_count;
179838032Speter	struct processor_set_basic_info info;
179938032Speter	host_t host;
180038032Speter
180138032Speter	error = processor_set_default(host_self(), &default_set);
180238032Speter	if (error != KERN_SUCCESS)
180338032Speter	{
180438032Speter		if (tTd(3, 1))
180590795Sgshapiro			sm_dprintf("getla: processor_set_default failed: %s",
180690795Sgshapiro				   sm_errstring(errno));
180738032Speter		return -1;
180838032Speter	}
180938032Speter	info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
181038032Speter	if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
181138032Speter			       &host, (processor_set_info_t)&info,
181238032Speter			       &info_count) != KERN_SUCCESS)
181338032Speter	{
181438032Speter		if (tTd(3, 1))
181590795Sgshapiro			sm_dprintf("getla: processor_set_info failed: %s",
181690795Sgshapiro				   sm_errstring(errno));
181738032Speter		return -1;
181838032Speter	}
181938032Speter	if (tTd(3, 1))
182090795Sgshapiro		sm_dprintf("getla: %d\n",
182164565Sgshapiro			(int) ((info.load_average + (LOAD_SCALE / 2)) /
182264565Sgshapiro			       LOAD_SCALE));
182338032Speter	return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
182438032Speter}
182538032Speter
182638032Speter#endif /* LA_TYPE == LA_MACH */
182738032Speter
182838032Speter#if LA_TYPE == LA_PROCSTR
182990795Sgshapiro# if SM_CONF_BROKEN_STRTOD
183090795Sgshapiro	ERROR: This OS has most likely a broken strtod() implemenentation.
183190795Sgshapiro	ERROR: The function is required for getla().
183290795Sgshapiro	ERROR: Check the compilation options _LA_PROCSTR and
183390795Sgshapiro	ERROR: _SM_CONF_BROKEN_STRTOD (without the leading _).
183490795Sgshapiro# endif /* SM_CONF_BROKEN_STRTOD */
183538032Speter
183638032Speter/*
183738032Speter**  Read /proc/loadavg for the load average.  This is assumed to be
183838032Speter**  in a format like "0.15 0.12 0.06".
183938032Speter**
184038032Speter**	Initially intended for Linux.  This has been in the kernel
184138032Speter**	since at least 0.99.15.
184238032Speter*/
184338032Speter
184438032Speter# ifndef _PATH_LOADAVG
184538032Speter#  define _PATH_LOADAVG	"/proc/loadavg"
1846363466Sgshapiro# endif
184738032Speter
184890795Sgshapiroint
184938032Spetergetla()
185038032Speter{
185138032Speter	double avenrun;
185238032Speter	register int result;
185390795Sgshapiro	SM_FILE_T *fp;
185438032Speter
185590795Sgshapiro	fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_LOADAVG, SM_IO_RDONLY,
185690795Sgshapiro			NULL);
185738032Speter	if (fp == NULL)
185838032Speter	{
185938032Speter		if (tTd(3, 1))
186090795Sgshapiro			sm_dprintf("getla: sm_io_open(%s): %s\n",
186190795Sgshapiro				   _PATH_LOADAVG, sm_errstring(errno));
186238032Speter		return -1;
186338032Speter	}
186490795Sgshapiro	result = sm_io_fscanf(fp, SM_TIME_DEFAULT, "%lf", &avenrun);
186590795Sgshapiro	(void) sm_io_close(fp, SM_TIME_DEFAULT);
186638032Speter	if (result != 1)
186738032Speter	{
186838032Speter		if (tTd(3, 1))
186990795Sgshapiro			sm_dprintf("getla: sm_io_fscanf() = %d: %s\n",
187090795Sgshapiro				   result, sm_errstring(errno));
187138032Speter		return -1;
187238032Speter	}
187338032Speter
187438032Speter	if (tTd(3, 1))
187590795Sgshapiro		sm_dprintf("getla(): %.2f\n", avenrun);
187638032Speter
187738032Speter	return ((int) (avenrun + 0.5));
187838032Speter}
187938032Speter
188038032Speter#endif /* LA_TYPE == LA_PROCSTR */
188138032Speter
188238032Speter#if LA_TYPE == LA_IRIX6
188338032Speter
188464565Sgshapiro# include <sys/sysmp.h>
188564565Sgshapiro
1886132946Sgshapiro# ifdef _UNICOSMP
1887132946Sgshapiro#  define CAST_SYSMP(x)	(x)
1888363466Sgshapiro# else
1889132946Sgshapiro#  define CAST_SYSMP(x)	((x) & 0x7fffffff)
1890363466Sgshapiro# endif
1891132946Sgshapiro
189290795Sgshapiroint
189390795Sgshapirogetla(void)
189438032Speter{
189590795Sgshapiro	int j;
189638032Speter	static int kmem = -1;
189738032Speter	int avenrun[3];
189838032Speter
189938032Speter	if (kmem < 0)
190038032Speter	{
190138032Speter		kmem = open(_PATH_KMEM, 0, 0);
190238032Speter		if (kmem < 0)
190338032Speter		{
190438032Speter			if (tTd(3, 1))
190590795Sgshapiro				sm_dprintf("getla: open(%s): %s\n", _PATH_KMEM,
190690795Sgshapiro					   sm_errstring(errno));
190738032Speter			return -1;
190838032Speter		}
190990795Sgshapiro		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
191090795Sgshapiro		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
191190795Sgshapiro		{
191290795Sgshapiro			if (tTd(3, 1))
191390795Sgshapiro				sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
191490795Sgshapiro					   sm_errstring(errno));
191590795Sgshapiro			(void) close(kmem);
191690795Sgshapiro			kmem = -1;
191790795Sgshapiro			return -1;
191890795Sgshapiro		}
191938032Speter	}
192038032Speter
1921132946Sgshapiro	if (lseek(kmem, CAST_SYSMP(sysmp(MP_KERNADDR, MPKA_AVENRUN)), SEEK_SET)
1922132946Sgshapiro		== -1 ||
1923182352Sgshapiro	    read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun))
192438032Speter	{
192538032Speter		if (tTd(3, 1))
192690795Sgshapiro			sm_dprintf("getla: lseek or read: %s\n",
192790795Sgshapiro				   sm_errstring(errno));
192838032Speter		return -1;
192938032Speter	}
193038032Speter	if (tTd(3, 5))
193138032Speter	{
193290795Sgshapiro		sm_dprintf("getla: avenrun = %ld", (long int) avenrun[0]);
193338032Speter		if (tTd(3, 15))
193490795Sgshapiro			sm_dprintf(", %ld, %ld",
193564565Sgshapiro				(long int) avenrun[1], (long int) avenrun[2]);
193690795Sgshapiro		sm_dprintf("\n");
193738032Speter	}
193838032Speter
193938032Speter	if (tTd(3, 1))
194090795Sgshapiro		sm_dprintf("getla: %d\n",
194164565Sgshapiro			(int) (avenrun[0] + FSCALE/2) >> FSHIFT);
194238032Speter	return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
194338032Speter
194438032Speter}
194564565Sgshapiro#endif /* LA_TYPE == LA_IRIX6 */
194638032Speter
194738032Speter#if LA_TYPE == LA_KSTAT
194838032Speter
194964565Sgshapiro# include <kstat.h>
195038032Speter
195190795Sgshapiroint
195238032Spetergetla()
195338032Speter{
195438032Speter	static kstat_ctl_t *kc = NULL;
195538032Speter	static kstat_t *ksp = NULL;
195638032Speter	kstat_named_t *ksn;
195738032Speter	int la;
195838032Speter
195938032Speter	if (kc == NULL)		/* if not initialized before */
196038032Speter		kc = kstat_open();
196138032Speter	if (kc == NULL)
196238032Speter	{
196338032Speter		if (tTd(3, 1))
196490795Sgshapiro			sm_dprintf("getla: kstat_open(): %s\n",
196590795Sgshapiro				   sm_errstring(errno));
196638032Speter		return -1;
196738032Speter	}
196838032Speter	if (ksp == NULL)
196938032Speter		ksp = kstat_lookup(kc, "unix", 0, "system_misc");
197038032Speter	if (ksp == NULL)
197138032Speter	{
197238032Speter		if (tTd(3, 1))
197390795Sgshapiro			sm_dprintf("getla: kstat_lookup(): %s\n",
197490795Sgshapiro				   sm_errstring(errno));
197538032Speter		return -1;
197638032Speter	}
197738032Speter	if (kstat_read(kc, ksp, NULL) < 0)
197838032Speter	{
197938032Speter		if (tTd(3, 1))
198090795Sgshapiro			sm_dprintf("getla: kstat_read(): %s\n",
198190795Sgshapiro				   sm_errstring(errno));
198238032Speter		return -1;
198338032Speter	}
198438032Speter	ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
198590795Sgshapiro	la = ((double) ksn->value.ul + FSCALE/2) / FSCALE;
198638032Speter	/* kstat_close(kc); /o do not close for fast access */
198738032Speter	return la;
198838032Speter}
198938032Speter
199038032Speter#endif /* LA_TYPE == LA_KSTAT */
199138032Speter
199238032Speter#if LA_TYPE == LA_DEVSHORT
199338032Speter
199438032Speter/*
199538032Speter**  Read /dev/table/avenrun for the load average.  This should contain
199638032Speter**  three shorts for the 1, 5, and 15 minute loads.  We only read the
199738032Speter**  first, since that's all we care about.
199838032Speter**
199938032Speter**	Intended for SCO OpenServer 5.
200038032Speter*/
200138032Speter
200238032Speter# ifndef _PATH_AVENRUN
200338032Speter#  define _PATH_AVENRUN	"/dev/table/avenrun"
2004363466Sgshapiro# endif
200538032Speter
200690795Sgshapiroint
200738032Spetergetla()
200838032Speter{
200938032Speter	static int afd = -1;
201038032Speter	short avenrun;
201138032Speter	int loadav;
201238032Speter	int r;
201338032Speter
201438032Speter	errno = EBADF;
201538032Speter
201638032Speter	if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1)
201738032Speter	{
201838032Speter		if (errno != EBADF)
201938032Speter			return -1;
202038032Speter		afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
202138032Speter		if (afd < 0)
202238032Speter		{
202338032Speter			sm_syslog(LOG_ERR, NOQID,
202490795Sgshapiro				"can't open %s: %s",
202590795Sgshapiro				_PATH_AVENRUN, sm_errstring(errno));
202638032Speter			return -1;
202738032Speter		}
202838032Speter	}
202938032Speter
2030168520Sgshapiro	r = read(afd, &avenrun, sizeof(avenrun));
2031182352Sgshapiro	if (r != sizeof(avenrun))
2032182352Sgshapiro	{
2033182352Sgshapiro		sm_syslog(LOG_ERR, NOQID,
2034182352Sgshapiro			"can't read %s: %s", _PATH_AVENRUN,
2035182352Sgshapiro			r == -1 ? sm_errstring(errno) : "short read");
2036182352Sgshapiro		return -1;
2037182352Sgshapiro	}
203838032Speter
203938032Speter	if (tTd(3, 5))
204090795Sgshapiro		sm_dprintf("getla: avenrun = %d\n", avenrun);
204138032Speter	loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
204238032Speter	if (tTd(3, 1))
204390795Sgshapiro		sm_dprintf("getla: %d\n", loadav);
204438032Speter	return loadav;
204538032Speter}
204638032Speter
204738032Speter#endif /* LA_TYPE == LA_DEVSHORT */
204838032Speter
204938032Speter#if LA_TYPE == LA_ALPHAOSF
205038032Speterstruct rtentry;
205138032Speterstruct mbuf;
205238032Speter# include <sys/table.h>
205338032Speter
205490795Sgshapiroint
205590795Sgshapirogetla()
205638032Speter{
205738032Speter	int ave = 0;
205838032Speter	struct tbl_loadavg tab;
205938032Speter
206038032Speter	if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1)
206138032Speter	{
206238032Speter		if (tTd(3, 1))
206390795Sgshapiro			sm_dprintf("getla: table %s\n", sm_errstring(errno));
206464565Sgshapiro		return -1;
206538032Speter	}
206638032Speter
206738032Speter	if (tTd(3, 1))
206890795Sgshapiro		sm_dprintf("getla: scale = %d\n", tab.tl_lscale);
206938032Speter
207038032Speter	if (tab.tl_lscale)
207164565Sgshapiro		ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) /
207264565Sgshapiro		       tab.tl_lscale);
207338032Speter	else
207464565Sgshapiro		ave = (int) (tab.tl_avenrun.d[2] + 0.5);
207538032Speter
207638032Speter	if (tTd(3, 1))
207790795Sgshapiro		sm_dprintf("getla: %d\n", ave);
207838032Speter
207938032Speter	return ave;
208038032Speter}
208138032Speter
208264565Sgshapiro#endif /* LA_TYPE == LA_ALPHAOSF */
208338032Speter
208471348Sgshapiro#if LA_TYPE == LA_PSET
208571348Sgshapiro
208690795Sgshapiroint
208771348Sgshapirogetla()
208871348Sgshapiro{
208971348Sgshapiro	double avenrun[3];
209071348Sgshapiro
209171348Sgshapiro	if (pset_getloadavg(PS_MYID, avenrun,
209271348Sgshapiro			    sizeof(avenrun) / sizeof(avenrun[0])) < 0)
209371348Sgshapiro	{
209471348Sgshapiro		if (tTd(3, 1))
209590795Sgshapiro			sm_dprintf("getla: pset_getloadavg failed: %s",
209690795Sgshapiro				   sm_errstring(errno));
209771348Sgshapiro		return -1;
209871348Sgshapiro	}
209971348Sgshapiro	if (tTd(3, 1))
210090795Sgshapiro		sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
210171348Sgshapiro	return ((int) (avenrun[0] + 0.5));
210271348Sgshapiro}
210371348Sgshapiro
210471348Sgshapiro#endif /* LA_TYPE == LA_PSET */
210571348Sgshapiro
210638032Speter#if LA_TYPE == LA_ZERO
210738032Speter
210890795Sgshapiroint
210938032Spetergetla()
211038032Speter{
211138032Speter	if (tTd(3, 1))
211290795Sgshapiro		sm_dprintf("getla: ZERO\n");
211364565Sgshapiro	return 0;
211438032Speter}
211538032Speter
211638032Speter#endif /* LA_TYPE == LA_ZERO */
211738032Speter
211838032Speter/*
211938032Speter * Copyright 1989 Massachusetts Institute of Technology
212038032Speter *
212138032Speter * Permission to use, copy, modify, distribute, and sell this software and its
212238032Speter * documentation for any purpose is hereby granted without fee, provided that
212338032Speter * the above copyright notice appear in all copies and that both that
212438032Speter * copyright notice and this permission notice appear in supporting
212538032Speter * documentation, and that the name of M.I.T. not be used in advertising or
212638032Speter * publicity pertaining to distribution of the software without specific,
212738032Speter * written prior permission.  M.I.T. makes no representations about the
212838032Speter * suitability of this software for any purpose.  It is provided "as is"
212938032Speter * without express or implied warranty.
213038032Speter *
213138032Speter * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
213238032Speter * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
213338032Speter * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
213438032Speter * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
213538032Speter * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
213638032Speter * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
213738032Speter *
213838032Speter * Authors:  Many and varied...
213938032Speter */
214038032Speter
214138032Speter/* Non Apollo stuff removed by Don Lewis 11/15/93 */
214238032Speter#ifndef lint
214390795SgshapiroSM_UNUSED(static char  rcsid[]) = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
2144363466Sgshapiro#endif
214538032Speter
214638032Speter#ifdef apollo
214738032Speter# undef volatile
214864565Sgshapiro# include <apollo/base.h>
214938032Speter
215038032Speter/* ARGSUSED */
215138032Speterint getloadavg( call_data )
215290795Sgshapiro	caddr_t call_data;	/* pointer to (double) return value */
215338032Speter{
215490795Sgshapiro	double *avenrun = (double *) call_data;
215590795Sgshapiro	int i;
215690795Sgshapiro	status_$t      st;
215790795Sgshapiro	long loadav[3];
215890795Sgshapiro
215990795Sgshapiro	proc1_$get_loadav(loadav, &st);
216090795Sgshapiro	*avenrun = loadav[0] / (double) (1 << 16);
216190795Sgshapiro	return 0;
216238032Speter}
216364565Sgshapiro#endif /* apollo */
216490795Sgshapiro/*
216590795Sgshapiro**  SM_GETLA -- get the current load average
216664565Sgshapiro**
216764565Sgshapiro**	Parameters:
216890795Sgshapiro**		none
216964565Sgshapiro**
217064565Sgshapiro**	Returns:
217190795Sgshapiro**		none
217264565Sgshapiro**
217364565Sgshapiro**	Side Effects:
217490795Sgshapiro**		Set CurrentLA to the current load average.
217590795Sgshapiro**		Set {load_avg} in GlobalMacros to the current load average.
217664565Sgshapiro*/
217764565Sgshapiro
217890795Sgshapirovoid
217990795Sgshapirosm_getla()
218064565Sgshapiro{
218190795Sgshapiro	char labuf[8];
218264565Sgshapiro
218390795Sgshapiro	CurrentLA = getla();
2184168520Sgshapiro	(void) sm_snprintf(labuf, sizeof(labuf), "%d", CurrentLA);
218590795Sgshapiro	macdefine(&GlobalMacros, A_TEMP, macid("{load_avg}"), labuf);
218664565Sgshapiro}
218790795Sgshapiro/*
218838032Speter**  SHOULDQUEUE -- should this message be queued or sent?
218938032Speter**
219038032Speter**	Compares the message cost to the load average to decide.
219138032Speter**
219290795Sgshapiro**	Note: Do NOT change this API! It is documented in op.me
219390795Sgshapiro**		and theoretically the user can change this function...
219490795Sgshapiro**
219538032Speter**	Parameters:
219638032Speter**		pri -- the priority of the message in question.
219790795Sgshapiro**		ct -- the message creation time (unused, but see above).
219838032Speter**
219938032Speter**	Returns:
220090795Sgshapiro**		true -- if this message should be queued up for the
220138032Speter**			time being.
220290795Sgshapiro**		false -- if the load is low enough to send this message.
220338032Speter**
220438032Speter**	Side Effects:
220538032Speter**		none.
220638032Speter*/
220738032Speter
220864565Sgshapiro/* ARGSUSED1 */
220938032Speterbool
221064565Sgshapiroshouldqueue(pri, ct)
221138032Speter	long pri;
221264565Sgshapiro	time_t ct;
221338032Speter{
221438032Speter	bool rval;
2215157006Sgshapiro#if _FFR_MEMSTAT
2216157006Sgshapiro	long memfree;
2217363466Sgshapiro#endif
221838032Speter
221938032Speter	if (tTd(3, 30))
222090795Sgshapiro		sm_dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ",
222164565Sgshapiro			CurrentLA, pri);
2222157006Sgshapiro
2223157006Sgshapiro#if _FFR_MEMSTAT
2224157006Sgshapiro	if (QueueLowMem > 0 &&
2225157006Sgshapiro	    sm_memstat_get(MemoryResource, &memfree) >= 0 &&
2226157006Sgshapiro	    memfree < QueueLowMem)
2227157006Sgshapiro	{
2228157006Sgshapiro		if (tTd(3, 30))
2229159613Sgshapiro			sm_dprintf("true (memfree=%ld < QueueLowMem=%ld)\n",
2230157006Sgshapiro				memfree, QueueLowMem);
2231157006Sgshapiro		return true;
2232157006Sgshapiro	}
2233157006Sgshapiro#endif /* _FFR_MEMSTAT */
223464565Sgshapiro	if (CurrentLA < QueueLA)
223538032Speter	{
223638032Speter		if (tTd(3, 30))
223790795Sgshapiro			sm_dprintf("false (CurrentLA < QueueLA)\n");
223890795Sgshapiro		return false;
223938032Speter	}
224064565Sgshapiro	rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1));
224138032Speter	if (tTd(3, 30))
224290795Sgshapiro		sm_dprintf("%s (by calculation)\n", rval ? "true" : "false");
224338032Speter	return rval;
224438032Speter}
2245168520Sgshapiro
224690795Sgshapiro/*
224738032Speter**  REFUSECONNECTIONS -- decide if connections should be refused
224838032Speter**
224938032Speter**	Parameters:
225064565Sgshapiro**		e -- the current envelope.
2251168520Sgshapiro**		dn -- number of daemon.
225290795Sgshapiro**		active -- was this daemon actually active?
225338032Speter**
225438032Speter**	Returns:
225590795Sgshapiro**		true if incoming SMTP connections should be refused
225638032Speter**			(for now).
225790795Sgshapiro**		false if we should accept new work.
225838032Speter**
225938032Speter**	Side Effects:
226038032Speter**		Sets process title when it is rejecting connections.
226138032Speter*/
226238032Speter
226338032Speterbool
2264168520Sgshapirorefuseconnections(e, dn, active)
226564565Sgshapiro	ENVELOPE *e;
2266168520Sgshapiro	int dn;
226790795Sgshapiro	bool active;
226838032Speter{
226990795Sgshapiro	static time_t lastconn[MAXDAEMONS];
227090795Sgshapiro	static int conncnt[MAXDAEMONS];
2271110563Sgshapiro	static time_t firstrejtime[MAXDAEMONS];
2272110563Sgshapiro	static time_t nextlogtime[MAXDAEMONS];
2273168520Sgshapiro	int limit;
2274157006Sgshapiro#if _FFR_MEMSTAT
2275157006Sgshapiro	long memfree;
2276363466Sgshapiro#endif
227790795Sgshapiro
227890795Sgshapiro#if XLA
227938032Speter	if (!xla_smtp_ok())
228090795Sgshapiro		return true;
2281363466Sgshapiro#endif
228238032Speter
2283168520Sgshapiro	SM_ASSERT(dn >= 0);
2284168520Sgshapiro	SM_ASSERT(dn < MAXDAEMONS);
228590795Sgshapiro	if (ConnRateThrottle > 0)
228690795Sgshapiro	{
228790795Sgshapiro		time_t now;
228890795Sgshapiro
228990795Sgshapiro		now = curtime();
229090795Sgshapiro		if (active)
229190795Sgshapiro		{
2292168520Sgshapiro			if (now != lastconn[dn])
229390795Sgshapiro			{
2294168520Sgshapiro				lastconn[dn] = now;
2295168520Sgshapiro				conncnt[dn] = 1;
229690795Sgshapiro			}
2297168520Sgshapiro			else if (conncnt[dn]++ > ConnRateThrottle)
229890795Sgshapiro			{
229990795Sgshapiro#define D_MSG_CRT "deferring connections on daemon %s: %d per second"
230090795Sgshapiro				/* sleep to flatten out connection load */
230190795Sgshapiro				sm_setproctitle(true, e, D_MSG_CRT,
2302168520Sgshapiro						Daemons[dn].d_name,
2303168520Sgshapiro						ConnRateThrottle);
230490795Sgshapiro				if (LogLevel > 8)
230590795Sgshapiro					sm_syslog(LOG_INFO, NOQID, D_MSG_CRT,
2306168520Sgshapiro						  Daemons[dn].d_name,
2307168520Sgshapiro						  ConnRateThrottle);
230890795Sgshapiro				(void) sleep(1);
230990795Sgshapiro			}
231090795Sgshapiro		}
2311168520Sgshapiro		else if (now != lastconn[dn])
2312168520Sgshapiro			conncnt[dn] = 0;
231390795Sgshapiro	}
231490795Sgshapiro
2315157006Sgshapiro
2316157006Sgshapiro#if _FFR_MEMSTAT
2317157006Sgshapiro	if (RefuseLowMem > 0 &&
2318157006Sgshapiro	    sm_memstat_get(MemoryResource, &memfree) >= 0 &&
2319157006Sgshapiro	    memfree < RefuseLowMem)
2320157006Sgshapiro	{
2321157006Sgshapiro# define R_MSG_LM "rejecting connections on daemon %s: free memory: %ld"
2322168520Sgshapiro		sm_setproctitle(true, e, R_MSG_LM, Daemons[dn].d_name, memfree);
2323157006Sgshapiro		if (LogLevel > 8)
2324168520Sgshapiro			sm_syslog(LOG_NOTICE, NOQID, R_MSG_LM,
2325168520Sgshapiro				Daemons[dn].d_name, memfree);
2326157006Sgshapiro		return true;
2327157006Sgshapiro	}
2328157006Sgshapiro#endif /* _FFR_MEMSTAT */
232990795Sgshapiro	sm_getla();
2330168520Sgshapiro	limit = (Daemons[dn].d_refuseLA != DPO_NOTSET) ?
2331168520Sgshapiro		Daemons[dn].d_refuseLA : RefuseLA;
2332168520Sgshapiro	if (limit > 0 && CurrentLA >= limit)
233338032Speter	{
2334110563Sgshapiro		time_t now;
2335110563Sgshapiro
233690795Sgshapiro# define R_MSG_LA "rejecting connections on daemon %s: load average: %d"
2337132946Sgshapiro# define R2_MSG_LA "have been rejecting connections on daemon %s for %s"
2338168520Sgshapiro		sm_setproctitle(true, e, R_MSG_LA, Daemons[dn].d_name,
2339168520Sgshapiro				CurrentLA);
234090795Sgshapiro		if (LogLevel > 8)
2341168520Sgshapiro			sm_syslog(LOG_NOTICE, NOQID, R_MSG_LA,
2342168520Sgshapiro				Daemons[dn].d_name, CurrentLA);
2343110563Sgshapiro		now = curtime();
2344168520Sgshapiro		if (firstrejtime[dn] == 0)
2345110563Sgshapiro		{
2346168520Sgshapiro			firstrejtime[dn] = now;
2347168520Sgshapiro			nextlogtime[dn] = now + RejectLogInterval;
2348110563Sgshapiro		}
2349168520Sgshapiro		else if (nextlogtime[dn] < now)
2350110563Sgshapiro		{
2351168520Sgshapiro			sm_syslog(LOG_ERR, NOQID, R2_MSG_LA, Daemons[dn].d_name,
2352168520Sgshapiro				  pintvl(now - firstrejtime[dn], true));
2353168520Sgshapiro			nextlogtime[dn] = now + RejectLogInterval;
2354110563Sgshapiro		}
235590795Sgshapiro		return true;
235638032Speter	}
2357110563Sgshapiro	else
2358168520Sgshapiro		firstrejtime[dn] = 0;
235938032Speter
2360168520Sgshapiro	limit = (Daemons[dn].d_delayLA != DPO_NOTSET) ?
2361168520Sgshapiro		Daemons[dn].d_delayLA : DelayLA;
2362168520Sgshapiro	if (limit > 0 && CurrentLA >= limit)
236390795Sgshapiro	{
236490795Sgshapiro		time_t now;
236590795Sgshapiro		static time_t log_delay = (time_t) 0;
236690795Sgshapiro
236790795Sgshapiro# define MIN_DELAY_LOG	90	/* wait before logging this again */
236890795Sgshapiro# define D_MSG_LA "delaying connections on daemon %s: load average=%d >= %d"
236990795Sgshapiro		/* sleep to flatten out connection load */
2370203004Sgshapiro		sm_setproctitle(true, e, D_MSG_LA, Daemons[dn].d_name,
2371285229Sgshapiro				CurrentLA, limit);
237290795Sgshapiro		if (LogLevel > 8 && (now = curtime()) > log_delay)
237390795Sgshapiro		{
237490795Sgshapiro			sm_syslog(LOG_INFO, NOQID, D_MSG_LA,
2375168520Sgshapiro				  Daemons[dn].d_name, CurrentLA, limit);
237690795Sgshapiro			log_delay = now + MIN_DELAY_LOG;
237790795Sgshapiro		}
237890795Sgshapiro		(void) sleep(1);
237990795Sgshapiro	}
238090795Sgshapiro
2381168520Sgshapiro	limit = (Daemons[dn].d_maxchildren != DPO_NOTSET) ?
2382168520Sgshapiro		Daemons[dn].d_maxchildren : MaxChildren;
2383168520Sgshapiro	if (limit > 0 && CurChildren >= limit)
238438032Speter	{
238538032Speter		proc_list_probe();
2386168520Sgshapiro		if (CurChildren >= limit)
238738032Speter		{
238890795Sgshapiro#define R_MSG_CHILD "rejecting connections on daemon %s: %d children, max %d"
238990795Sgshapiro			sm_setproctitle(true, e, R_MSG_CHILD,
2390168520Sgshapiro					Daemons[dn].d_name, CurChildren,
2391168520Sgshapiro					limit);
239290795Sgshapiro			if (LogLevel > 8)
239390795Sgshapiro				sm_syslog(LOG_INFO, NOQID, R_MSG_CHILD,
2394168520Sgshapiro					Daemons[dn].d_name, CurChildren,
2395168520Sgshapiro					limit);
239690795Sgshapiro			return true;
239738032Speter		}
239838032Speter	}
239990795Sgshapiro	return false;
240038032Speter}
2401168520Sgshapiro
240290795Sgshapiro/*
240338032Speter**  SETPROCTITLE -- set process title for ps
240438032Speter**
240538032Speter**	Parameters:
240638032Speter**		fmt -- a printf style format string.
240738032Speter**		a, b, c -- possible parameters to fmt.
240838032Speter**
240938032Speter**	Returns:
241038032Speter**		none.
241138032Speter**
241238032Speter**	Side Effects:
241338032Speter**		Clobbers argv of our main procedure so ps(1) will
241438032Speter**		display the title.
241538032Speter*/
241638032Speter
241738032Speter#define SPT_NONE	0	/* don't use it at all */
241838032Speter#define SPT_REUSEARGV	1	/* cover argv with title information */
241938032Speter#define SPT_BUILTIN	2	/* use libc builtin */
242038032Speter#define SPT_PSTAT	3	/* use pstat(PSTAT_SETCMD, ...) */
242138032Speter#define SPT_PSSTRINGS	4	/* use PS_STRINGS->... */
242238032Speter#define SPT_SYSMIPS	5	/* use sysmips() supported by NEWS-OS 6 */
242338032Speter#define SPT_SCO		6	/* write kernel u. area */
242438032Speter#define SPT_CHANGEARGV	7	/* write our own strings into argv[] */
242538032Speter
242638032Speter#ifndef SPT_TYPE
242738032Speter# define SPT_TYPE	SPT_REUSEARGV
2428363466Sgshapiro#endif
242938032Speter
243064565Sgshapiro
243138032Speter#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
243238032Speter
243338032Speter# if SPT_TYPE == SPT_PSTAT
243438032Speter#  include <sys/pstat.h>
2435363466Sgshapiro# endif
243638032Speter# if SPT_TYPE == SPT_PSSTRINGS
243738032Speter#  include <machine/vmparam.h>
243838032Speter#  include <sys/exec.h>
243938032Speter#  ifndef PS_STRINGS	/* hmmmm....  apparently not available after all */
244038032Speter#   undef SPT_TYPE
244138032Speter#   define SPT_TYPE	SPT_REUSEARGV
244264565Sgshapiro#  else /* ! PS_STRINGS */
244338032Speter#   ifndef NKPDE			/* FreeBSD 2.0 */
244438032Speter#    define NKPDE 63
244538032Spetertypedef unsigned int	*pt_entry_t;
244664565Sgshapiro#   endif /* ! NKPDE */
244764565Sgshapiro#  endif /* ! PS_STRINGS */
244864565Sgshapiro# endif /* SPT_TYPE == SPT_PSSTRINGS */
244938032Speter
245038032Speter# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
245138032Speter#  define SETPROC_STATIC	static
2452363466Sgshapiro# else
245338032Speter#  define SETPROC_STATIC
2454363466Sgshapiro# endif
245538032Speter
245638032Speter# if SPT_TYPE == SPT_SYSMIPS
245738032Speter#  include <sys/sysmips.h>
245838032Speter#  include <sys/sysnews.h>
2459363466Sgshapiro# endif
246038032Speter
246138032Speter# if SPT_TYPE == SPT_SCO
246238032Speter#  include <sys/immu.h>
246338032Speter#  include <sys/dir.h>
246438032Speter#  include <sys/user.h>
246538032Speter#  include <sys/fs/s5param.h>
246638032Speter#  if PSARGSZ > MAXLINE
246738032Speter#   define SPT_BUFSIZE	PSARGSZ
2468363466Sgshapiro#  endif
246964565Sgshapiro# endif /* SPT_TYPE == SPT_SCO */
247038032Speter
247138032Speter# ifndef SPT_PADCHAR
247238032Speter#  define SPT_PADCHAR	' '
2473363466Sgshapiro# endif
247438032Speter
247542580Speter#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
247642580Speter
247764565Sgshapiro#ifndef SPT_BUFSIZE
247864565Sgshapiro# define SPT_BUFSIZE	MAXLINE
2479363466Sgshapiro#endif
248038032Speter
248198125Sgshapiro#if _FFR_SPT_ALIGN
248298125Sgshapiro
248338032Speter/*
248498125Sgshapiro**  It looks like the Compaq Tru64 5.1A now aligns argv and envp to
248598125Sgshapiro**  64 bit alignment, so unless each piece of argv and envp is a multiple
248698125Sgshapiro**  of 8 bytes (including terminating NULL), initsetproctitle() won't use
248798125Sgshapiro**  any of the space beyond argv[0].  Be sure to set SPT_ALIGN_SIZE if
248898125Sgshapiro**  you use this FFR.
248998125Sgshapiro*/
249098125Sgshapiro
249198125Sgshapiro# ifdef SPT_ALIGN_SIZE
249298844Sgshapiro#  define SPT_ALIGN(x, align)	(((((x) + SPT_ALIGN_SIZE) >> (align)) << (align)) - 1)
2493363466Sgshapiro# else
249498125Sgshapiro#  define SPT_ALIGN(x, align)	(x)
2495363466Sgshapiro# endif
249698125Sgshapiro#else /* _FFR_SPT_ALIGN */
249798125Sgshapiro# define SPT_ALIGN(x, align)	(x)
249898125Sgshapiro#endif /* _FFR_SPT_ALIGN */
249998125Sgshapiro
250098125Sgshapiro/*
250138032Speter**  Pointers for setproctitle.
250238032Speter**	This allows "ps" listings to give more useful information.
250338032Speter*/
250438032Speter
250564565Sgshapirostatic char	**Argv = NULL;		/* pointer to argument vector */
250664565Sgshapirostatic char	*LastArgv = NULL;	/* end of argv */
250764565Sgshapiro#if SPT_TYPE != SPT_BUILTIN
250864565Sgshapirostatic void	setproctitle __P((const char *, ...));
2509363466Sgshapiro#endif
251038032Speter
251138032Spetervoid
251238032Speterinitsetproctitle(argc, argv, envp)
251338032Speter	int argc;
251438032Speter	char **argv;
251538032Speter	char **envp;
251638032Speter{
251790795Sgshapiro	register int i;
2518363466Sgshapiro#if _FFR_SPT_ALIGN
251998125Sgshapiro	int align;
2520363466Sgshapiro#endif
252138032Speter	extern char **environ;
252238032Speter
252338032Speter	/*
252438032Speter	**  Move the environment so setproctitle can use the space at
252538032Speter	**  the top of memory.
252638032Speter	*/
252738032Speter
2528102531Sgshapiro	if (envp != NULL)
2529102531Sgshapiro	{
2530102531Sgshapiro		for (i = 0; envp[i] != NULL; i++)
2531102531Sgshapiro			continue;
2532168520Sgshapiro		environ = (char **) xalloc(sizeof(char *) * (i + 1));
2533102531Sgshapiro		for (i = 0; envp[i] != NULL; i++)
2534102531Sgshapiro			environ[i] = newstr(envp[i]);
2535102531Sgshapiro		environ[i] = NULL;
2536102531Sgshapiro	}
253738032Speter
253838032Speter	/*
253938032Speter	**  Save start and extent of argv for setproctitle.
254038032Speter	*/
254138032Speter
254238032Speter	Argv = argv;
254338032Speter
254438032Speter	/*
254564565Sgshapiro	**  Determine how much space we can use for setproctitle.
254638032Speter	**  Use all contiguous argv and envp pointers starting at argv[0]
254764565Sgshapiro	*/
254898125Sgshapiro
2549363466Sgshapiro# if _FFR_SPT_ALIGN
255098125Sgshapiro	align = -1;
2551120259Sgshapiro#  ifdef SPT_ALIGN_SIZE
255298125Sgshapiro	for (i = SPT_ALIGN_SIZE; i > 0; i >>= 1)
255398125Sgshapiro		align++;
2554363466Sgshapiro#  endif
2555120259Sgshapiro# endif /* _FFR_SPT_ALIGN */
255698125Sgshapiro
255738032Speter	for (i = 0; i < argc; i++)
255838032Speter	{
255964565Sgshapiro		if (i == 0 || LastArgv + 1 == argv[i])
256098125Sgshapiro			LastArgv = argv[i] + SPT_ALIGN(strlen(argv[i]), align);
256138032Speter	}
2562102531Sgshapiro	for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++)
256338032Speter	{
256438032Speter		if (LastArgv + 1 == envp[i])
256598125Sgshapiro			LastArgv = envp[i] + SPT_ALIGN(strlen(envp[i]), align);
256638032Speter	}
256738032Speter}
256838032Speter
256938032Speter#if SPT_TYPE != SPT_BUILTIN
257038032Speter
257138032Speter/*VARARGS1*/
257264565Sgshapirostatic void
257338032Speter# ifdef __STDC__
257438032Spetersetproctitle(const char *fmt, ...)
257564565Sgshapiro# else /* __STDC__ */
257638032Spetersetproctitle(fmt, va_alist)
257738032Speter	const char *fmt;
257838032Speter	va_dcl
257964565Sgshapiro# endif /* __STDC__ */
258038032Speter{
258138032Speter# if SPT_TYPE != SPT_NONE
258264565Sgshapiro	register int i;
258338032Speter	register char *p;
258438032Speter	SETPROC_STATIC char buf[SPT_BUFSIZE];
258590795Sgshapiro	SM_VA_LOCAL_DECL
258638032Speter#  if SPT_TYPE == SPT_PSTAT
258738032Speter	union pstun pst;
2588363466Sgshapiro#  endif
258938032Speter#  if SPT_TYPE == SPT_SCO
259090795Sgshapiro	int j;
259138032Speter	off_t seek_off;
259238032Speter	static int kmem = -1;
259377352Sgshapiro	static pid_t kmempid = -1;
259438032Speter	struct user u;
259564565Sgshapiro#  endif /* SPT_TYPE == SPT_SCO */
259638032Speter
259738032Speter	p = buf;
259838032Speter
259938032Speter	/* print sendmail: heading for grep */
260090795Sgshapiro	(void) sm_strlcpy(p, "sendmail: ", SPACELEFT(buf, p));
260138032Speter	p += strlen(p);
260238032Speter
260338032Speter	/* print the argument string */
260490795Sgshapiro	SM_VA_START(ap, fmt);
260590795Sgshapiro	(void) sm_vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
260690795Sgshapiro	SM_VA_END(ap);
260738032Speter
260890795Sgshapiro	i = (int) strlen(buf);
260990795Sgshapiro	if (i < 0)
261090795Sgshapiro		return;
261138032Speter
261238032Speter#  if SPT_TYPE == SPT_PSTAT
261338032Speter	pst.pst_command = buf;
261438032Speter	pstat(PSTAT_SETCMD, pst, i, 0, 0);
2615363466Sgshapiro#  endif
261638032Speter#  if SPT_TYPE == SPT_PSSTRINGS
261738032Speter	PS_STRINGS->ps_nargvstr = 1;
261838032Speter	PS_STRINGS->ps_argvstr = buf;
2619363466Sgshapiro#  endif
262038032Speter#  if SPT_TYPE == SPT_SYSMIPS
262138032Speter	sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
2622363466Sgshapiro#  endif
262338032Speter#  if SPT_TYPE == SPT_SCO
262490795Sgshapiro	if (kmem < 0 || kmempid != CurrentPid)
262538032Speter	{
262638032Speter		if (kmem >= 0)
262771348Sgshapiro			(void) close(kmem);
262838032Speter		kmem = open(_PATH_KMEM, O_RDWR, 0);
262938032Speter		if (kmem < 0)
263038032Speter			return;
263190795Sgshapiro		if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
263290795Sgshapiro		    fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
263390795Sgshapiro		{
263490795Sgshapiro			(void) close(kmem);
263590795Sgshapiro			kmem = -1;
263690795Sgshapiro			return;
263790795Sgshapiro		}
263890795Sgshapiro		kmempid = CurrentPid;
263938032Speter	}
264038032Speter	buf[PSARGSZ - 1] = '\0';
264138032Speter	seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
264238032Speter	if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
264338032Speter		(void) write(kmem, buf, PSARGSZ);
264464565Sgshapiro#  endif /* SPT_TYPE == SPT_SCO */
264538032Speter#  if SPT_TYPE == SPT_REUSEARGV
264664565Sgshapiro	if (LastArgv == NULL)
264764565Sgshapiro		return;
264864565Sgshapiro
264938032Speter	if (i > LastArgv - Argv[0] - 2)
265038032Speter	{
265138032Speter		i = LastArgv - Argv[0] - 2;
265238032Speter		buf[i] = '\0';
265338032Speter	}
265490795Sgshapiro	(void) sm_strlcpy(Argv[0], buf, i + 1);
265538032Speter	p = &Argv[0][i];
265638032Speter	while (p < LastArgv)
265738032Speter		*p++ = SPT_PADCHAR;
265838032Speter	Argv[1] = NULL;
265964565Sgshapiro#  endif /* SPT_TYPE == SPT_REUSEARGV */
266038032Speter#  if SPT_TYPE == SPT_CHANGEARGV
266138032Speter	Argv[0] = buf;
2662363466Sgshapiro	Argv[1] = NULL;
2663363466Sgshapiro#  endif
266438032Speter# endif /* SPT_TYPE != SPT_NONE */
266538032Speter}
2666363466Sgshapiro#endif /* SPT_TYPE != SPT_BUILTIN */
266738032Speter
266890795Sgshapiro/*
266942580Speter**  SM_SETPROCTITLE -- set process task and set process title for ps
267042580Speter**
267142580Speter**	Possibly set process status and call setproctitle() to
267242580Speter**	change the ps display.
267342580Speter**
267442580Speter**	Parameters:
267542580Speter**		status -- whether or not to store as process status
267664565Sgshapiro**		e -- the current envelope.
267742580Speter**		fmt -- a printf style format string.
267842580Speter**		a, b, c -- possible parameters to fmt.
267942580Speter**
268042580Speter**	Returns:
268142580Speter**		none.
268242580Speter*/
268342580Speter
2684223067Sgshapiro/*VARARGS3*/
268542580Spetervoid
268664565Sgshapiro#ifdef __STDC__
268764565Sgshapirosm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...)
268864565Sgshapiro#else /* __STDC__ */
268964565Sgshapirosm_setproctitle(status, e, fmt, va_alist)
269042580Speter	bool status;
269164565Sgshapiro	ENVELOPE *e;
269242580Speter	const char *fmt;
269342580Speter	va_dcl
269464565Sgshapiro#endif /* __STDC__ */
269542580Speter{
269642580Speter	char buf[SPT_BUFSIZE];
269790795Sgshapiro	SM_VA_LOCAL_DECL
269842580Speter
269942580Speter	/* print the argument string */
270090795Sgshapiro	SM_VA_START(ap, fmt);
2701168520Sgshapiro	(void) sm_vsnprintf(buf, sizeof(buf), fmt, ap);
270290795Sgshapiro	SM_VA_END(ap);
270342580Speter
270442580Speter	if (status)
270590795Sgshapiro		proc_list_set(CurrentPid, buf);
270664565Sgshapiro
270764565Sgshapiro	if (ProcTitlePrefix != NULL)
270864565Sgshapiro	{
270964565Sgshapiro		char prefix[SPT_BUFSIZE];
271064565Sgshapiro
2711168520Sgshapiro		expand(ProcTitlePrefix, prefix, sizeof(prefix), e);
271264565Sgshapiro		setproctitle("%s: %s", prefix, buf);
271364565Sgshapiro	}
271464565Sgshapiro	else
271564565Sgshapiro		setproctitle("%s", buf);
271642580Speter}
271790795Sgshapiro/*
271838032Speter**  WAITFOR -- wait for a particular process id.
271938032Speter**
272038032Speter**	Parameters:
272138032Speter**		pid -- process id to wait for.
272238032Speter**
272338032Speter**	Returns:
272438032Speter**		status of pid.
272538032Speter**		-1 if pid never shows up.
272638032Speter**
272738032Speter**	Side Effects:
272838032Speter**		none.
272938032Speter*/
273038032Speter
273138032Speterint
273238032Speterwaitfor(pid)
273338032Speter	pid_t pid;
273438032Speter{
273590795Sgshapiro	int st;
273690795Sgshapiro	pid_t i;
273790795Sgshapiro
273890795Sgshapiro	do
273990795Sgshapiro	{
274090795Sgshapiro		errno = 0;
274190795Sgshapiro		i = sm_wait(&st);
274290795Sgshapiro		if (i > 0)
274390795Sgshapiro			proc_list_drop(i, st, NULL);
274490795Sgshapiro	} while ((i >= 0 || errno == EINTR) && i != pid);
274590795Sgshapiro	if (i < 0)
274690795Sgshapiro		return -1;
274790795Sgshapiro	return st;
274890795Sgshapiro}
274990795Sgshapiro/*
275090795Sgshapiro**  SM_WAIT -- wait
275190795Sgshapiro**
275290795Sgshapiro**	Parameters:
275390795Sgshapiro**		status -- pointer to status (return value)
275490795Sgshapiro**
275590795Sgshapiro**	Returns:
275690795Sgshapiro**		pid
275790795Sgshapiro*/
275890795Sgshapiro
275990795Sgshapiropid_t
276090795Sgshapirosm_wait(status)
276190795Sgshapiro	int *status;
276290795Sgshapiro{
276364565Sgshapiro# ifdef WAITUNION
276438032Speter	union wait st;
2765363466Sgshapiro# else
276638032Speter	auto int st;
2767363466Sgshapiro# endif
276838032Speter	pid_t i;
276964565Sgshapiro# if defined(ISC_UNIX) || defined(_SCO_unix_)
277038032Speter	int savesig;
2771363466Sgshapiro# endif
277238032Speter
277364565Sgshapiro# if defined(ISC_UNIX) || defined(_SCO_unix_)
277490795Sgshapiro	savesig = sm_releasesignal(SIGCHLD);
2775363466Sgshapiro# endif
277690795Sgshapiro	i = wait(&st);
277764565Sgshapiro# if defined(ISC_UNIX) || defined(_SCO_unix_)
277890795Sgshapiro	if (savesig > 0)
277990795Sgshapiro		sm_blocksignal(SIGCHLD);
2780363466Sgshapiro# endif
278164565Sgshapiro# ifdef WAITUNION
278290795Sgshapiro	*status = st.w_status;
2783363466Sgshapiro# else
278490795Sgshapiro	*status = st;
2785363466Sgshapiro# endif
278690795Sgshapiro	return i;
278738032Speter}
278890795Sgshapiro/*
278938032Speter**  REAPCHILD -- pick up the body of my child, lest it become a zombie
279038032Speter**
279138032Speter**	Parameters:
279238032Speter**		sig -- the signal that got us here (unused).
279338032Speter**
279438032Speter**	Returns:
279538032Speter**		none.
279638032Speter**
279738032Speter**	Side Effects:
279838032Speter**		Picks up extant zombies.
279964565Sgshapiro**		Control socket exits may restart/shutdown daemon.
280077352Sgshapiro**
280177352Sgshapiro**	NOTE:	THIS CAN BE CALLED FROM A SIGNAL HANDLER.  DO NOT ADD
280277352Sgshapiro**		ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
280377352Sgshapiro**		DOING.
280438032Speter*/
280538032Speter
280664565Sgshapiro/* ARGSUSED0 */
280738032SpeterSIGFUNC_DECL
280838032Speterreapchild(sig)
280938032Speter	int sig;
281038032Speter{
281164565Sgshapiro	int save_errno = errno;
281264565Sgshapiro	int st;
281338032Speter	pid_t pid;
281477352Sgshapiro# if HASWAITPID
281538032Speter	auto int status;
281638032Speter	int count;
281738032Speter
281838032Speter	count = 0;
281938032Speter	while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
282038032Speter	{
282164565Sgshapiro		st = status;
282238032Speter		if (count++ > 1000)
282338032Speter			break;
282477352Sgshapiro# else /* HASWAITPID */
282577352Sgshapiro#  ifdef WNOHANG
282690795Sgshapiro	union wait status;
282790795Sgshapiro
282838032Speter	while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0)
282964565Sgshapiro	{
283064565Sgshapiro		st = status.w_status;
283177352Sgshapiro#  else /* WNOHANG */
283290795Sgshapiro	auto int status;
283390795Sgshapiro
283438032Speter	/*
283538032Speter	**  Catch one zombie -- we will be re-invoked (we hope) if there
283638032Speter	**  are more.  Unreliable signals probably break this, but this
283738032Speter	**  is the "old system" situation -- waitpid or wait3 are to be
283838032Speter	**  strongly preferred.
283938032Speter	*/
284038032Speter
284138032Speter	if ((pid = wait(&status)) > 0)
284264565Sgshapiro	{
284364565Sgshapiro		st = status;
284477352Sgshapiro#  endif /* WNOHANG */
284577352Sgshapiro# endif /* HASWAITPID */
284664565Sgshapiro		/* Drop PID and check if it was a control socket child */
284790795Sgshapiro		proc_list_drop(pid, st, NULL);
284864565Sgshapiro	}
284977352Sgshapiro	FIX_SYSV_SIGNAL(sig, reapchild);
285064565Sgshapiro	errno = save_errno;
285138032Speter	return SIGFUNC_RETURN;
285238032Speter}
285390795Sgshapiro/*
2854285229Sgshapiro**  GETDTSIZE -- return number of file descriptors
285538032Speter**
285638032Speter**	Only on non-BSD systems
285738032Speter**
285838032Speter**	Parameters:
285938032Speter**		none
286038032Speter**
286138032Speter**	Returns:
286238032Speter**		size of file descriptor table
286338032Speter**
286438032Speter**	Side Effects:
286538032Speter**		none
286638032Speter*/
286738032Speter
286838032Speter#ifdef SOLARIS
286938032Speter# include <sys/resource.h>
2870363466Sgshapiro#endif
287138032Speter
287238032Speterint
287338032Spetergetdtsize()
287438032Speter{
287564565Sgshapiro# ifdef RLIMIT_NOFILE
287638032Speter	struct rlimit rl;
287738032Speter
287838032Speter	if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
287938032Speter		return rl.rlim_cur;
288064565Sgshapiro# endif /* RLIMIT_NOFILE */
288138032Speter
288264565Sgshapiro# if HASGETDTABLESIZE
288338032Speter	return getdtablesize();
288464565Sgshapiro# else /* HASGETDTABLESIZE */
288538032Speter#  ifdef _SC_OPEN_MAX
288638032Speter	return sysconf(_SC_OPEN_MAX);
2887363466Sgshapiro#  else
288838032Speter	return NOFILE;
2889363466Sgshapiro#  endif
289064565Sgshapiro# endif /* HASGETDTABLESIZE */
289138032Speter}
289290795Sgshapiro/*
289338032Speter**  UNAME -- get the UUCP name of this system.
289438032Speter*/
289538032Speter
289664565Sgshapiro#if !HASUNAME
289738032Speter
289838032Speterint
289938032Speteruname(name)
290038032Speter	struct utsname *name;
290138032Speter{
290290795Sgshapiro	SM_FILE_T *file;
290338032Speter	char *n;
290438032Speter
290538032Speter	name->nodename[0] = '\0';
290638032Speter
290738032Speter	/* try /etc/whoami -- one line with the node name */
290890795Sgshapiro	if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, "/etc/whoami",
290990795Sgshapiro			       SM_IO_RDONLY, NULL)) != NULL)
291038032Speter	{
291190795Sgshapiro		(void) sm_io_fgets(file, SM_TIME_DEFAULT, name->nodename,
291290795Sgshapiro				   NODE_LENGTH + 1);
291390795Sgshapiro		(void) sm_io_close(file, SM_TIME_DEFAULT);
291438032Speter		n = strchr(name->nodename, '\n');
291538032Speter		if (n != NULL)
291638032Speter			*n = '\0';
291738032Speter		if (name->nodename[0] != '\0')
291864565Sgshapiro			return 0;
291938032Speter	}
292038032Speter
292138032Speter	/* try /usr/include/whoami.h -- has a #define somewhere */
292290795Sgshapiro	if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
292390795Sgshapiro			       "/usr/include/whoami.h", SM_IO_RDONLY, NULL))
292490795Sgshapiro	    != NULL)
292538032Speter	{
292638032Speter		char buf[MAXLINE];
292738032Speter
292898125Sgshapiro		while (sm_io_fgets(file, SM_TIME_DEFAULT,
2929249729Sgshapiro				   buf, sizeof(buf)) >= 0)
293064565Sgshapiro		{
293190795Sgshapiro			if (sm_io_sscanf(buf, "#define sysname \"%*[^\"]\"",
293238032Speter					NODE_LENGTH, name->nodename) > 0)
293338032Speter				break;
293464565Sgshapiro		}
293590795Sgshapiro		(void) sm_io_close(file, SM_TIME_DEFAULT);
293638032Speter		if (name->nodename[0] != '\0')
293764565Sgshapiro			return 0;
293838032Speter	}
293938032Speter
294064565Sgshapiro	return -1;
294138032Speter}
294264565Sgshapiro#endif /* !HASUNAME */
294390795Sgshapiro/*
294438032Speter**  INITGROUPS -- initialize groups
294538032Speter**
294638032Speter**	Stub implementation for System V style systems
294738032Speter*/
294838032Speter
294964565Sgshapiro#if !HASINITGROUPS
295038032Speterinitgroups(name, basegid)
295138032Speter	char *name;
295238032Speter	int basegid;
295338032Speter{
295438032Speter	return 0;
295538032Speter}
2956363466Sgshapiro#endif /* !HASINITGROUPS */
295738032Speter
295890795Sgshapiro/*
295938032Speter**  SETGROUPS -- set group list
296038032Speter**
296138032Speter**	Stub implementation for systems that don't have group lists
296238032Speter*/
296338032Speter
296438032Speter#ifndef NGROUPS_MAX
296538032Speterint
296638032Spetersetgroups(ngroups, grouplist)
296738032Speter	int ngroups;
296838032Speter	GIDSET_T grouplist[];
296938032Speter{
297038032Speter	return 0;
297138032Speter}
2972363466Sgshapiro#endif /* ! NGROUPS_MAX */
297338032Speter
297490795Sgshapiro/*
297538032Speter**  SETSID -- set session id (for non-POSIX systems)
297638032Speter*/
297738032Speter
297864565Sgshapiro#if !HASSETSID
297938032Speter
298038032Speterpid_t
298138032Spetersetsid __P ((void))
298238032Speter{
298364565Sgshapiro#  ifdef TIOCNOTTY
298438032Speter	int fd;
298538032Speter
298638032Speter	fd = open("/dev/tty", O_RDWR, 0);
298738032Speter	if (fd >= 0)
298838032Speter	{
298966497Sgshapiro		(void) ioctl(fd, TIOCNOTTY, (char *) 0);
299038032Speter		(void) close(fd);
299138032Speter	}
299264565Sgshapiro#  endif /* TIOCNOTTY */
299364565Sgshapiro#  ifdef SYS5SETPGRP
299438032Speter	return setpgrp();
2995363466Sgshapiro#  else
299690795Sgshapiro	return setpgid(0, CurrentPid);
2997363466Sgshapiro#  endif
299838032Speter}
299938032Speter
300064565Sgshapiro#endif /* !HASSETSID */
300190795Sgshapiro/*
300238032Speter**  FSYNC -- dummy fsync
300338032Speter*/
300438032Speter
300564565Sgshapiro#if NEEDFSYNC
300638032Speter
300738032Speterfsync(fd)
300838032Speter	int fd;
300938032Speter{
301038032Speter# ifdef O_SYNC
301138032Speter	return fcntl(fd, F_SETFL, O_SYNC);
3012363466Sgshapiro# else
301338032Speter	/* nothing we can do */
301438032Speter	return 0;
3015363466Sgshapiro# endif
301638032Speter}
3017363466Sgshapiro#endif /* NEEDFSYNC */
301838032Speter
301990795Sgshapiro/*
302038032Speter**  DGUX_INET_ADDR -- inet_addr for DG/UX
302138032Speter**
302238032Speter**	Data General DG/UX version of inet_addr returns a struct in_addr
302338032Speter**	instead of a long.  This patches things.  Only needed on versions
302438032Speter**	prior to 5.4.3.
302538032Speter*/
302638032Speter
302738032Speter#ifdef DGUX_5_4_2
302838032Speter
302964565Sgshapiro# undef inet_addr
303038032Speter
303138032Speterlong
303238032Speterdgux_inet_addr(host)
303338032Speter	char *host;
303438032Speter{
303538032Speter	struct in_addr haddr;
303638032Speter
303738032Speter	haddr = inet_addr(host);
303838032Speter	return haddr.s_addr;
303938032Speter}
304038032Speter
304164565Sgshapiro#endif /* DGUX_5_4_2 */
304290795Sgshapiro/*
304338032Speter**  GETOPT -- for old systems or systems with bogus implementations
304438032Speter*/
304538032Speter
304690795Sgshapiro#if !SM_CONF_GETOPT
304738032Speter
304838032Speter/*
304938032Speter * Copyright (c) 1985 Regents of the University of California.
305038032Speter * All rights reserved.  The Berkeley software License Agreement
305138032Speter * specifies the terms and conditions for redistribution.
305238032Speter */
305338032Speter
305438032Speter
305538032Speter/*
305642580Speter**  this version hacked to add `atend' flag to allow state machine
305742580Speter**  to reset if invoked by the program to scan args for a 2nd time
305838032Speter*/
305938032Speter
306064565Sgshapiro# if defined(LIBC_SCCS) && !defined(lint)
306138032Speterstatic char sccsid[] = "@(#)getopt.c	4.3 (Berkeley) 3/9/86";
3062363466Sgshapiro# endif
306338032Speter
306438032Speter/*
306590795Sgshapiro**  get option letter from argument vector
306690795Sgshapiro*/
306764565Sgshapiro# ifdef _CONVEX_SOURCE
306838032Speterextern int	optind, opterr, optopt;
306938032Speterextern char	*optarg;
307064565Sgshapiro# else /* _CONVEX_SOURCE */
307138032Speterint	opterr = 1;		/* if error message should be printed */
307238032Speterint	optind = 1;		/* index into parent argv vector */
307338032Speterint	optopt = 0;		/* character checked for validity */
307438032Speterchar	*optarg = NULL;		/* argument associated with option */
307564565Sgshapiro# endif /* _CONVEX_SOURCE */
307638032Speter
307764565Sgshapiro# define BADCH	(int)'?'
307864565Sgshapiro# define EMSG	""
307990795Sgshapiro# define tell(s)	if (opterr) \
308090795Sgshapiro			{sm_io_fputs(smioerr, SM_TIME_DEFAULT, *nargv); \
308190795Sgshapiro			(void) sm_io_fputs(smioerr, SM_TIME_DEFAULT, s); \
308290795Sgshapiro			(void) sm_io_putc(smioerr, SM_TIME_DEFAULT, optopt); \
308390795Sgshapiro			(void) sm_io_putc(smioerr, SM_TIME_DEFAULT, '\n'); \
308490795Sgshapiro			return BADCH;}
308538032Speter
308638032Speterint
308738032Spetergetopt(nargc,nargv,ostr)
308838032Speter	int		nargc;
308938032Speter	char *const	*nargv;
309038032Speter	const char	*ostr;
309138032Speter{
309238032Speter	static char	*place = EMSG;	/* option letter processing */
309338032Speter	static char	atend = 0;
309438032Speter	register char	*oli = NULL;	/* option letter list index */
309538032Speter
309638032Speter	if (atend) {
309738032Speter		atend = 0;
309838032Speter		place = EMSG;
309938032Speter	}
310038032Speter	if(!*place) {			/* update scanning pointer */
310138032Speter		if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
310238032Speter			atend++;
310338032Speter			return -1;
310438032Speter		}
310538032Speter		if (*place == '-') {	/* found "--" */
310638032Speter			++optind;
310738032Speter			atend++;
310838032Speter			return -1;
310938032Speter		}
311038032Speter	}				/* option letter okay? */
311138032Speter	if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
311238032Speter		if (!*place) ++optind;
311338032Speter		tell(": illegal option -- ");
311438032Speter	}
311538032Speter	if (oli && *++oli != ':') {		/* don't need argument */
311638032Speter		optarg = NULL;
311738032Speter		if (!*place) ++optind;
311838032Speter	}
311938032Speter	else {				/* need an argument */
312038032Speter		if (*place) optarg = place;	/* no white space */
312138032Speter		else if (nargc <= ++optind) {	/* no arg */
312238032Speter			place = EMSG;
312338032Speter			tell(": option requires an argument -- ");
312438032Speter		}
312564565Sgshapiro		else optarg = nargv[optind];	/* white space */
312638032Speter		place = EMSG;
312738032Speter		++optind;
312838032Speter	}
312990795Sgshapiro	return optopt;			/* dump back option letter */
313038032Speter}
313138032Speter
313290795Sgshapiro#endif /* !SM_CONF_GETOPT */
313390795Sgshapiro/*
313438032Speter**  USERSHELLOK -- tell if a user's shell is ok for unrestricted use
313538032Speter**
313638032Speter**	Parameters:
313738032Speter**		user -- the name of the user we are checking.
313838032Speter**		shell -- the user's shell from /etc/passwd
313938032Speter**
314038032Speter**	Returns:
314190795Sgshapiro**		true -- if it is ok to use this for unrestricted access.
314290795Sgshapiro**		false -- if the shell is restricted.
314338032Speter*/
314438032Speter
314538032Speter#if !HASGETUSERSHELL
314638032Speter
314738032Speter# ifndef _PATH_SHELLS
314838032Speter#  define _PATH_SHELLS	"/etc/shells"
3149363466Sgshapiro# endif
315038032Speter
315138032Speter# if defined(_AIX3) || defined(_AIX4)
315238032Speter#  include <userconf.h>
315338032Speter#  if _AIX4 >= 40200
315438032Speter#   include <userpw.h>
3155363466Sgshapiro#  endif
315638032Speter#  include <usersec.h>
315764565Sgshapiro# endif /* defined(_AIX3) || defined(_AIX4) */
315838032Speter
315964565Sgshapirostatic char	*DefaultUserShells[] =
316038032Speter{
316138032Speter	"/bin/sh",		/* standard shell */
316290795Sgshapiro# ifdef MPE
316390795Sgshapiro	"/SYS/PUB/CI",
316490795Sgshapiro# else /* MPE */
316538032Speter	"/usr/bin/sh",
316638032Speter	"/bin/csh",		/* C shell */
316738032Speter	"/usr/bin/csh",
316890795Sgshapiro# endif /* MPE */
316964565Sgshapiro# ifdef __hpux
317064565Sgshapiro#  ifdef V4FS
317138032Speter	"/usr/bin/rsh",		/* restricted Bourne shell */
317238032Speter	"/usr/bin/ksh",		/* Korn shell */
317338032Speter	"/usr/bin/rksh",	/* restricted Korn shell */
317438032Speter	"/usr/bin/pam",
317538032Speter	"/usr/bin/keysh",	/* key shell (extended Korn shell) */
317638032Speter	"/usr/bin/posix/sh",
317764565Sgshapiro#  else /* V4FS */
317838032Speter	"/bin/rsh",		/* restricted Bourne shell */
317938032Speter	"/bin/ksh",		/* Korn shell */
318038032Speter	"/bin/rksh",		/* restricted Korn shell */
318138032Speter	"/bin/pam",
318238032Speter	"/usr/bin/keysh",	/* key shell (extended Korn shell) */
318338032Speter	"/bin/posix/sh",
3184112813Sgshapiro	"/sbin/sh",
318564565Sgshapiro#  endif /* V4FS */
318664565Sgshapiro# endif /* __hpux */
318764565Sgshapiro# if defined(_AIX3) || defined(_AIX4)
318838032Speter	"/bin/ksh",		/* Korn shell */
318938032Speter	"/usr/bin/ksh",
319038032Speter	"/bin/tsh",		/* trusted shell */
319138032Speter	"/usr/bin/tsh",
319238032Speter	"/bin/bsh",		/* Bourne shell */
319338032Speter	"/usr/bin/bsh",
319464565Sgshapiro# endif /* defined(_AIX3) || defined(_AIX4) */
319564565Sgshapiro# if defined(__svr4__) || defined(__svr5__)
319638032Speter	"/bin/ksh",		/* Korn shell */
319738032Speter	"/usr/bin/ksh",
319864565Sgshapiro# endif /* defined(__svr4__) || defined(__svr5__) */
319964565Sgshapiro# ifdef sgi
320038032Speter	"/sbin/sh",		/* SGI's shells really live in /sbin */
3201102531Sgshapiro	"/usr/bin/sh",
3202110563Sgshapiro	"/sbin/bsh",		/* classic Bourne shell */
3203102531Sgshapiro	"/bin/bsh",
3204102531Sgshapiro	"/usr/bin/bsh",
3205102531Sgshapiro	"/sbin/csh",		/* standard csh */
3206102531Sgshapiro	"/bin/csh",
3207102531Sgshapiro	"/usr/bin/csh",
3208110563Sgshapiro	"/sbin/jsh",		/* classic Bourne shell w/ job control*/
3209102531Sgshapiro	"/bin/jsh",
3210102531Sgshapiro	"/usr/bin/jsh",
321138032Speter	"/bin/ksh",		/* Korn shell */
321238032Speter	"/sbin/ksh",
321338032Speter	"/usr/bin/ksh",
3214102531Sgshapiro	"/sbin/tcsh",		/* Extended csh */
3215102531Sgshapiro	"/bin/tcsh",
321638032Speter	"/usr/bin/tcsh",
321764565Sgshapiro# endif /* sgi */
321838032Speter	NULL
321938032Speter};
322038032Speter
322164565Sgshapiro#endif /* !HASGETUSERSHELL */
322238032Speter
322338032Speter#define WILDCARD_SHELL	"/SENDMAIL/ANY/SHELL/"
322438032Speter
322538032Speterbool
322638032Speterusershellok(user, shell)
322738032Speter	char *user;
322838032Speter	char *shell;
322938032Speter{
323064565Sgshapiro# if HASGETUSERSHELL
323138032Speter	register char *p;
323238032Speter	extern char *getusershell();
323338032Speter
323438032Speter	if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
323538032Speter	    ConfigLevel <= 1)
323690795Sgshapiro		return true;
323738032Speter
323838032Speter	setusershell();
323938032Speter	while ((p = getusershell()) != NULL)
324038032Speter		if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
324138032Speter			break;
324238032Speter	endusershell();
324338032Speter	return p != NULL;
324464565Sgshapiro# else /* HASGETUSERSHELL */
324564565Sgshapiro#  if USEGETCONFATTR
324638032Speter	auto char *v;
3247363466Sgshapiro#  endif
324890795Sgshapiro	register SM_FILE_T *shellf;
324938032Speter	char buf[MAXLINE];
325038032Speter
325138032Speter	if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
325238032Speter	    ConfigLevel <= 1)
325390795Sgshapiro		return true;
325438032Speter
325564565Sgshapiro#  if USEGETCONFATTR
325638032Speter	/*
325738032Speter	**  Naturally IBM has a "better" idea.....
325838032Speter	**
325938032Speter	**	What a crock.  This interface isn't documented, it is
326038032Speter	**	considered part of the security library (-ls), and it
326138032Speter	**	only works if you are running as root (since the list
326238032Speter	**	of valid shells is obviously a source of great concern).
326338032Speter	**	I recommend that you do NOT define USEGETCONFATTR,
326438032Speter	**	especially since you are going to have to set up an
326538032Speter	**	/etc/shells anyhow to handle the cases where getconfattr
326638032Speter	**	fails.
326738032Speter	*/
326838032Speter
326938032Speter	if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL)
327038032Speter	{
327138032Speter		while (*v != '\0')
327238032Speter		{
327338032Speter			if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0)
327490795Sgshapiro				return true;
327538032Speter			v += strlen(v) + 1;
327638032Speter		}
327790795Sgshapiro		return false;
327838032Speter	}
327964565Sgshapiro#  endif /* USEGETCONFATTR */
328038032Speter
328190795Sgshapiro	shellf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_SHELLS,
328290795Sgshapiro			    SM_IO_RDONLY, NULL);
328338032Speter	if (shellf == NULL)
328438032Speter	{
328538032Speter		/* no /etc/shells; see if it is one of the std shells */
328638032Speter		char **d;
328764565Sgshapiro
328838032Speter		if (errno != ENOENT && LogLevel > 3)
328938032Speter			sm_syslog(LOG_ERR, NOQID,
329038032Speter				  "usershellok: cannot open %s: %s",
329190795Sgshapiro				  _PATH_SHELLS, sm_errstring(errno));
329238032Speter
329338032Speter		for (d = DefaultUserShells; *d != NULL; d++)
329438032Speter		{
329538032Speter			if (strcmp(shell, *d) == 0)
329690795Sgshapiro				return true;
329738032Speter		}
329890795Sgshapiro		return false;
329938032Speter	}
330038032Speter
3301249729Sgshapiro	while (sm_io_fgets(shellf, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0)
330238032Speter	{
330338032Speter		register char *p, *q;
330438032Speter
330538032Speter		p = buf;
330638032Speter		while (*p != '\0' && *p != '#' && *p != '/')
330738032Speter			p++;
330838032Speter		if (*p == '#' || *p == '\0')
330938032Speter			continue;
331038032Speter		q = p;
3311363466Sgshapiro		while (*p != '\0' && *p != '#' && !(SM_ISSPACE(*p)))
331238032Speter			p++;
331338032Speter		*p = '\0';
331438032Speter		if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
331538032Speter		{
331690795Sgshapiro			(void) sm_io_close(shellf, SM_TIME_DEFAULT);
331790795Sgshapiro			return true;
331838032Speter		}
331938032Speter	}
332090795Sgshapiro	(void) sm_io_close(shellf, SM_TIME_DEFAULT);
332190795Sgshapiro	return false;
332264565Sgshapiro# endif /* HASGETUSERSHELL */
332338032Speter}
332490795Sgshapiro/*
332538032Speter**  FREEDISKSPACE -- see how much free space is on the queue filesystem
332638032Speter**
332738032Speter**	Only implemented if you have statfs.
332838032Speter**
332938032Speter**	Parameters:
333038032Speter**		dir -- the directory in question.
333138032Speter**		bsize -- a variable into which the filesystem
333238032Speter**			block size is stored.
333338032Speter**
333438032Speter**	Returns:
333564565Sgshapiro**		The number of blocks free on the queue filesystem.
333638032Speter**		-1 if the statfs call fails.
333738032Speter**
333838032Speter**	Side effects:
333938032Speter**		Puts the filesystem block size into bsize.
334038032Speter*/
334138032Speter
334238032Speter/* statfs types */
334390795Sgshapiro# define SFS_NONE	0	/* no statfs implementation */
334490795Sgshapiro# define SFS_USTAT	1	/* use ustat */
334590795Sgshapiro# define SFS_4ARGS	2	/* use four-argument statfs call */
334690795Sgshapiro# define SFS_VFS	3	/* use <sys/vfs.h> implementation */
334790795Sgshapiro# define SFS_MOUNT	4	/* use <sys/mount.h> implementation */
334890795Sgshapiro# define SFS_STATFS	5	/* use <sys/statfs.h> implementation */
334990795Sgshapiro# define SFS_STATVFS	6	/* use <sys/statvfs.h> implementation */
335038032Speter
335190795Sgshapiro# ifndef SFS_TYPE
335290795Sgshapiro#  define SFS_TYPE	SFS_NONE
3353363466Sgshapiro# endif
335438032Speter
335590795Sgshapiro# if SFS_TYPE == SFS_USTAT
335690795Sgshapiro#  include <ustat.h>
3357363466Sgshapiro# endif
335890795Sgshapiro# if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
335990795Sgshapiro#  include <sys/statfs.h>
3360363466Sgshapiro# endif
336190795Sgshapiro# if SFS_TYPE == SFS_VFS
336290795Sgshapiro#  include <sys/vfs.h>
3363363466Sgshapiro# endif
336490795Sgshapiro# if SFS_TYPE == SFS_MOUNT
336590795Sgshapiro#  include <sys/mount.h>
3366363466Sgshapiro# endif
336790795Sgshapiro# if SFS_TYPE == SFS_STATVFS
336890795Sgshapiro#  include <sys/statvfs.h>
3369363466Sgshapiro# endif
337038032Speter
337138032Speterlong
337238032Speterfreediskspace(dir, bsize)
3373168520Sgshapiro	const char *dir;
337438032Speter	long *bsize;
337538032Speter{
337690795Sgshapiro# if SFS_TYPE == SFS_NONE
337790795Sgshapiro	if (bsize != NULL)
337890795Sgshapiro		*bsize = 4096L;
337990795Sgshapiro
338090795Sgshapiro	/* assume free space is plentiful */
338190795Sgshapiro	return (long) LONG_MAX;
338290795Sgshapiro# else /* SFS_TYPE == SFS_NONE */
338364565Sgshapiro#  if SFS_TYPE == SFS_USTAT
338438032Speter	struct ustat fs;
338538032Speter	struct stat statbuf;
338664565Sgshapiro#   define FSBLOCKSIZE	DEV_BSIZE
338764565Sgshapiro#   define SFS_BAVAIL	f_tfree
338864565Sgshapiro#  else /* SFS_TYPE == SFS_USTAT */
338964565Sgshapiro#   if defined(ultrix)
339038032Speter	struct fs_data fs;
339164565Sgshapiro#    define SFS_BAVAIL	fd_bfreen
339264565Sgshapiro#    define FSBLOCKSIZE	1024L
339364565Sgshapiro#   else /* defined(ultrix) */
339464565Sgshapiro#    if SFS_TYPE == SFS_STATVFS
339538032Speter	struct statvfs fs;
339664565Sgshapiro#     define FSBLOCKSIZE	fs.f_frsize
339764565Sgshapiro#    else /* SFS_TYPE == SFS_STATVFS */
339838032Speter	struct statfs fs;
339964565Sgshapiro#     define FSBLOCKSIZE	fs.f_bsize
340064565Sgshapiro#    endif /* SFS_TYPE == SFS_STATVFS */
340164565Sgshapiro#   endif /* defined(ultrix) */
340264565Sgshapiro#  endif /* SFS_TYPE == SFS_USTAT */
340364565Sgshapiro#  ifndef SFS_BAVAIL
340464565Sgshapiro#   define SFS_BAVAIL f_bavail
3405363466Sgshapiro#  endif
340638032Speter
340764565Sgshapiro#  if SFS_TYPE == SFS_USTAT
340838032Speter	if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
340964565Sgshapiro#  else /* SFS_TYPE == SFS_USTAT */
341064565Sgshapiro#   if SFS_TYPE == SFS_4ARGS
3411168520Sgshapiro	if (statfs(dir, &fs, sizeof(fs), 0) == 0)
341264565Sgshapiro#   else /* SFS_TYPE == SFS_4ARGS */
341364565Sgshapiro#    if SFS_TYPE == SFS_STATVFS
341438032Speter	if (statvfs(dir, &fs) == 0)
341564565Sgshapiro#    else /* SFS_TYPE == SFS_STATVFS */
341664565Sgshapiro#     if defined(ultrix)
341738032Speter	if (statfs(dir, &fs) > 0)
341864565Sgshapiro#     else /* defined(ultrix) */
341938032Speter	if (statfs(dir, &fs) == 0)
342064565Sgshapiro#     endif /* defined(ultrix) */
342164565Sgshapiro#    endif /* SFS_TYPE == SFS_STATVFS */
342264565Sgshapiro#   endif /* SFS_TYPE == SFS_4ARGS */
342364565Sgshapiro#  endif /* SFS_TYPE == SFS_USTAT */
342438032Speter	{
342538032Speter		if (bsize != NULL)
342638032Speter			*bsize = FSBLOCKSIZE;
342738032Speter		if (fs.SFS_BAVAIL <= 0)
342838032Speter			return 0;
342938032Speter		else if (fs.SFS_BAVAIL > LONG_MAX)
343064565Sgshapiro			return (long) LONG_MAX;
343138032Speter		else
343238032Speter			return (long) fs.SFS_BAVAIL;
343338032Speter	}
343464565Sgshapiro	return -1;
343590795Sgshapiro# endif /* SFS_TYPE == SFS_NONE */
343638032Speter}
343790795Sgshapiro/*
343890795Sgshapiro**  ENOUGHDISKSPACE -- is there enough free space on the queue file systems?
343938032Speter**
344038032Speter**	Parameters:
344138032Speter**		msize -- the size to check against.  If zero, we don't yet
344238032Speter**		know how big the message will be, so just check for
344338032Speter**		a "reasonable" amount.
344490795Sgshapiro**		e -- envelope, or NULL -- controls logging
344538032Speter**
344638032Speter**	Returns:
344790795Sgshapiro**		true if in every queue group there is at least one
344890795Sgshapiro**		queue directory whose file system contains enough free space.
344990795Sgshapiro**		false otherwise.
345090795Sgshapiro**
345190795Sgshapiro**	Side Effects:
345290795Sgshapiro**		If there is not enough disk space and e != NULL
345390795Sgshapiro**		then sm_syslog is called.
345438032Speter*/
345538032Speter
345638032Speterbool
345790795Sgshapiroenoughdiskspace(msize, e)
345838032Speter	long msize;
345990795Sgshapiro	ENVELOPE *e;
346038032Speter{
346190795Sgshapiro	int i;
346238032Speter
3463203004Sgshapiro#if _FFR_TESTS
3464203004Sgshapiro	if (tTd(4, 101))
3465203004Sgshapiro		return false;
3466363466Sgshapiro#endif
346738032Speter	if (MinBlocksFree <= 0 && msize <= 0)
346838032Speter	{
346938032Speter		if (tTd(4, 80))
347090795Sgshapiro			sm_dprintf("enoughdiskspace: no threshold\n");
347190795Sgshapiro		return true;
347238032Speter	}
347338032Speter
347490795Sgshapiro	filesys_update();
347590795Sgshapiro	for (i = 0; i < NumQueue; ++i)
347638032Speter	{
347790795Sgshapiro		if (pickqdir(Queue[i], msize, e) < 0)
347890795Sgshapiro			return false;
347938032Speter	}
348090795Sgshapiro	return true;
348138032Speter}
348290795Sgshapiro/*
348338032Speter**  TRANSIENTERROR -- tell if an error code indicates a transient failure
348438032Speter**
348538032Speter**	This looks at an errno value and tells if this is likely to
348638032Speter**	go away if retried later.
348738032Speter**
348838032Speter**	Parameters:
348938032Speter**		err -- the errno code to classify.
349038032Speter**
349138032Speter**	Returns:
349290795Sgshapiro**		true if this is probably transient.
349390795Sgshapiro**		false otherwise.
349438032Speter*/
349538032Speter
349638032Speterbool
349738032Spetertransienterror(err)
349838032Speter	int err;
349938032Speter{
350038032Speter	switch (err)
350138032Speter	{
350238032Speter	  case EIO:			/* I/O error */
350338032Speter	  case ENXIO:			/* Device not configured */
350438032Speter	  case EAGAIN:			/* Resource temporarily unavailable */
350538032Speter	  case ENOMEM:			/* Cannot allocate memory */
350638032Speter	  case ENODEV:			/* Operation not supported by device */
350738032Speter	  case ENFILE:			/* Too many open files in system */
350838032Speter	  case EMFILE:			/* Too many open files */
350938032Speter	  case ENOSPC:			/* No space left on device */
351038032Speter	  case ETIMEDOUT:		/* Connection timed out */
351138032Speter#ifdef ESTALE
351238032Speter	  case ESTALE:			/* Stale NFS file handle */
3513363466Sgshapiro#endif
351438032Speter#ifdef ENETDOWN
351538032Speter	  case ENETDOWN:		/* Network is down */
3516363466Sgshapiro#endif
351738032Speter#ifdef ENETUNREACH
351838032Speter	  case ENETUNREACH:		/* Network is unreachable */
3519363466Sgshapiro#endif
352038032Speter#ifdef ENETRESET
352138032Speter	  case ENETRESET:		/* Network dropped connection on reset */
3522363466Sgshapiro#endif
352338032Speter#ifdef ECONNABORTED
352438032Speter	  case ECONNABORTED:		/* Software caused connection abort */
3525363466Sgshapiro#endif
352638032Speter#ifdef ECONNRESET
352738032Speter	  case ECONNRESET:		/* Connection reset by peer */
3528363466Sgshapiro#endif
352938032Speter#ifdef ENOBUFS
353038032Speter	  case ENOBUFS:			/* No buffer space available */
3531363466Sgshapiro#endif
353238032Speter#ifdef ESHUTDOWN
353338032Speter	  case ESHUTDOWN:		/* Can't send after socket shutdown */
3534363466Sgshapiro#endif
353538032Speter#ifdef ECONNREFUSED
353638032Speter	  case ECONNREFUSED:		/* Connection refused */
3537363466Sgshapiro#endif
353838032Speter#ifdef EHOSTDOWN
353938032Speter	  case EHOSTDOWN:		/* Host is down */
3540363466Sgshapiro#endif
354138032Speter#ifdef EHOSTUNREACH
354238032Speter	  case EHOSTUNREACH:		/* No route to host */
3543363466Sgshapiro#endif
354438032Speter#ifdef EDQUOT
354538032Speter	  case EDQUOT:			/* Disc quota exceeded */
3546363466Sgshapiro#endif
354738032Speter#ifdef EPROCLIM
354838032Speter	  case EPROCLIM:		/* Too many processes */
3549363466Sgshapiro#endif
355038032Speter#ifdef EUSERS
355138032Speter	  case EUSERS:			/* Too many users */
3552363466Sgshapiro#endif
355338032Speter#ifdef EDEADLK
355438032Speter	  case EDEADLK:			/* Resource deadlock avoided */
3555363466Sgshapiro#endif
355638032Speter#ifdef EISCONN
355738032Speter	  case EISCONN:			/* Socket already connected */
3558363466Sgshapiro#endif
355938032Speter#ifdef EINPROGRESS
356038032Speter	  case EINPROGRESS:		/* Operation now in progress */
3561363466Sgshapiro#endif
356238032Speter#ifdef EALREADY
356338032Speter	  case EALREADY:		/* Operation already in progress */
3564363466Sgshapiro#endif
356538032Speter#ifdef EADDRINUSE
356638032Speter	  case EADDRINUSE:		/* Address already in use */
3567363466Sgshapiro#endif
356838032Speter#ifdef EADDRNOTAVAIL
356938032Speter	  case EADDRNOTAVAIL:		/* Can't assign requested address */
3570363466Sgshapiro#endif
357138032Speter#ifdef ETXTBSY
357238032Speter	  case ETXTBSY:			/* (Apollo) file locked */
3573363466Sgshapiro#endif
357438032Speter#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
357538032Speter	  case ENOSR:			/* Out of streams resources */
3576363466Sgshapiro#endif
357764565Sgshapiro#ifdef ENOLCK
357864565Sgshapiro	  case ENOLCK:			/* No locks available */
3579363466Sgshapiro#endif
358038032Speter	  case E_SM_OPENTIMEOUT:	/* PSEUDO: open timed out */
358190795Sgshapiro		return true;
358238032Speter	}
358338032Speter
358438032Speter	/* nope, must be permanent */
358590795Sgshapiro	return false;
358638032Speter}
358790795Sgshapiro/*
358838032Speter**  LOCKFILE -- lock a file using flock or (shudder) fcntl locking
358938032Speter**
359038032Speter**	Parameters:
359138032Speter**		fd -- the file descriptor of the file.
359238032Speter**		filename -- the file name (for error messages).
359338032Speter**		ext -- the filename extension.
359438032Speter**		type -- type of the lock.  Bits can be:
359538032Speter**			LOCK_EX -- exclusive lock.
359638032Speter**			LOCK_NB -- non-blocking.
359771348Sgshapiro**			LOCK_UN -- unlock.
359838032Speter**
359938032Speter**	Returns:
360090795Sgshapiro**		true if the lock was acquired.
360190795Sgshapiro**		false otherwise.
360238032Speter*/
360338032Speter
360438032Speterbool
360538032Speterlockfile(fd, filename, ext, type)
360638032Speter	int fd;
360738032Speter	char *filename;
360838032Speter	char *ext;
360938032Speter	int type;
361038032Speter{
361138032Speter	int i;
361238032Speter	int save_errno;
361338032Speter# if !HASFLOCK
361438032Speter	int action;
361538032Speter	struct flock lfd;
361638032Speter
361738032Speter	if (ext == NULL)
361838032Speter		ext = "";
361938032Speter
3620168520Sgshapiro	memset(&lfd, '\0', sizeof(lfd));
362138032Speter	if (bitset(LOCK_UN, type))
362238032Speter		lfd.l_type = F_UNLCK;
362338032Speter	else if (bitset(LOCK_EX, type))
362438032Speter		lfd.l_type = F_WRLCK;
362538032Speter	else
362638032Speter		lfd.l_type = F_RDLCK;
362738032Speter
362838032Speter	if (bitset(LOCK_NB, type))
362938032Speter		action = F_SETLK;
363038032Speter	else
363138032Speter		action = F_SETLKW;
363238032Speter
363338032Speter	if (tTd(55, 60))
363490795Sgshapiro		sm_dprintf("lockfile(%s%s, action=%d, type=%d): ",
363538032Speter			filename, ext, action, lfd.l_type);
363638032Speter
363738032Speter	while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
363838032Speter		continue;
363938032Speter	if (i >= 0)
364038032Speter	{
364138032Speter		if (tTd(55, 60))
364290795Sgshapiro			sm_dprintf("SUCCESS\n");
364390795Sgshapiro		return true;
364438032Speter	}
364538032Speter	save_errno = errno;
364638032Speter
364738032Speter	if (tTd(55, 60))
364890795Sgshapiro		sm_dprintf("(%s) ", sm_errstring(save_errno));
364938032Speter
365038032Speter	/*
365138032Speter	**  On SunOS, if you are testing using -oQ/tmp/mqueue or
365238032Speter	**  -oA/tmp/aliases or anything like that, and /tmp is mounted
365338032Speter	**  as type "tmp" (that is, served from swap space), the
365438032Speter	**  previous fcntl will fail with "Invalid argument" errors.
365538032Speter	**  Since this is fairly common during testing, we will assume
365638032Speter	**  that this indicates that the lock is successfully grabbed.
365738032Speter	*/
365838032Speter
365938032Speter	if (save_errno == EINVAL)
366038032Speter	{
366138032Speter		if (tTd(55, 60))
366290795Sgshapiro			sm_dprintf("SUCCESS\n");
366390795Sgshapiro		return true;
366438032Speter	}
366538032Speter
366664565Sgshapiro	if (!bitset(LOCK_NB, type) ||
366764565Sgshapiro	    (save_errno != EACCES && save_errno != EAGAIN))
366838032Speter	{
366994337Sgshapiro		int omode = fcntl(fd, F_GETFL, 0);
367094337Sgshapiro		uid_t euid = geteuid();
367194337Sgshapiro
367238032Speter		errno = save_errno;
3673285229Sgshapiro		syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)",
3674285229Sgshapiro		       filename, ext, fd, type, omode, (long) euid);
367590795Sgshapiro		dumpfd(fd, true, true);
367638032Speter	}
367764565Sgshapiro# else /* !HASFLOCK */
367838032Speter	if (ext == NULL)
367938032Speter		ext = "";
368038032Speter
368138032Speter	if (tTd(55, 60))
368290795Sgshapiro		sm_dprintf("lockfile(%s%s, type=%o): ", filename, ext, type);
368338032Speter
368438032Speter	while ((i = flock(fd, type)) < 0 && errno == EINTR)
368538032Speter		continue;
368638032Speter	if (i >= 0)
368738032Speter	{
368838032Speter		if (tTd(55, 60))
368990795Sgshapiro			sm_dprintf("SUCCESS\n");
369090795Sgshapiro		return true;
369138032Speter	}
369238032Speter	save_errno = errno;
369338032Speter
369438032Speter	if (tTd(55, 60))
369590795Sgshapiro		sm_dprintf("(%s) ", sm_errstring(save_errno));
369638032Speter
369738032Speter	if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK)
369838032Speter	{
369994337Sgshapiro		int omode = fcntl(fd, F_GETFL, 0);
370094337Sgshapiro		uid_t euid = geteuid();
370194337Sgshapiro
370238032Speter		errno = save_errno;
3703285229Sgshapiro		syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)",
3704285229Sgshapiro			filename, ext, fd, type, omode, (long) euid);
370590795Sgshapiro		dumpfd(fd, true, true);
370638032Speter	}
370764565Sgshapiro# endif /* !HASFLOCK */
370838032Speter	if (tTd(55, 60))
370990795Sgshapiro		sm_dprintf("FAIL\n");
371038032Speter	errno = save_errno;
371190795Sgshapiro	return false;
371238032Speter}
371390795Sgshapiro/*
371438032Speter**  CHOWNSAFE -- tell if chown is "safe" (executable only by root)
371538032Speter**
371638032Speter**	Unfortunately, given that we can't predict other systems on which
371738032Speter**	a remote mounted (NFS) filesystem will be mounted, the answer is
371838032Speter**	almost always that this is unsafe.
371938032Speter**
372038032Speter**	Note also that many operating systems have non-compliant
372138032Speter**	implementations of the _POSIX_CHOWN_RESTRICTED variable and the
372238032Speter**	fpathconf() routine.  According to IEEE 1003.1-1990, if
372338032Speter**	_POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then
372438032Speter**	no non-root process can give away the file.  However, vendors
372538032Speter**	don't take NFS into account, so a comfortable value of
372638032Speter**	_POSIX_CHOWN_RESTRICTED tells us nothing.
372738032Speter**
372838032Speter**	Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf()
372938032Speter**	even on files where chown is not restricted.  Many systems get
373038032Speter**	this wrong on NFS-based filesystems (that is, they say that chown
373138032Speter**	is restricted [safe] on NFS filesystems where it may not be, since
373238032Speter**	other systems can access the same filesystem and do file giveaway;
373338032Speter**	only the NFS server knows for sure!)  Hence, it is important to
373438032Speter**	get the value of SAFENFSPATHCONF correct -- it should be defined
373538032Speter**	_only_ after testing (see test/t_pathconf.c) a system on an unsafe
373638032Speter**	NFS-based filesystem to ensure that you can get meaningful results.
373738032Speter**	If in doubt, assume unsafe!
373838032Speter**
373938032Speter**	You may also need to tweak IS_SAFE_CHOWN -- it should be a
374038032Speter**	condition indicating whether the return from pathconf indicates
374138032Speter**	that chown is safe (typically either > 0 or >= 0 -- there isn't
374238032Speter**	even any agreement about whether a zero return means that a file
374338032Speter**	is or is not safe).  It defaults to "> 0".
374438032Speter**
374538032Speter**	If the parent directory is safe (writable only by owner back
374638032Speter**	to the root) then we can relax slightly and trust fpathconf
374738032Speter**	in more circumstances.  This is really a crock -- if this is an
374838032Speter**	NFS mounted filesystem then we really know nothing about the
374938032Speter**	underlying implementation.  However, most systems pessimize and
375038032Speter**	return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which
375138032Speter**	we interpret as unsafe, as we should.  Thus, this heuristic gets
375238032Speter**	us into a possible problem only on systems that have a broken
375338032Speter**	pathconf implementation and which are also poorly configured
375438032Speter**	(have :include: files in group- or world-writable directories).
375538032Speter**
375638032Speter**	Parameters:
375738032Speter**		fd -- the file descriptor to check.
375838032Speter**		safedir -- set if the parent directory is safe.
375938032Speter**
376038032Speter**	Returns:
376190795Sgshapiro**		true -- if the chown(2) operation is "safe" -- that is,
376238032Speter**			only root can chown the file to an arbitrary user.
376390795Sgshapiro**		false -- if an arbitrary user can give away a file.
376438032Speter*/
376538032Speter
376638032Speter#ifndef IS_SAFE_CHOWN
376738032Speter# define IS_SAFE_CHOWN	> 0
3768363466Sgshapiro#endif
376938032Speter
377038032Speterbool
377138032Speterchownsafe(fd, safedir)
377238032Speter	int fd;
377338032Speter	bool safedir;
377438032Speter{
377564565Sgshapiro# if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \
377638032Speter    (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H))
377738032Speter	int rval;
377838032Speter
377938032Speter	/* give the system administrator a chance to override */
378064565Sgshapiro	if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail))
378190795Sgshapiro		return true;
378238032Speter
378338032Speter	/*
378438032Speter	**  Some systems (e.g., SunOS) seem to have the call and the
378538032Speter	**  #define _PC_CHOWN_RESTRICTED, but don't actually implement
378638032Speter	**  the call.  This heuristic checks for that.
378738032Speter	*/
378838032Speter
378938032Speter	errno = 0;
379038032Speter	rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
379164565Sgshapiro#  if SAFENFSPATHCONF
379238032Speter	return errno == 0 && rval IS_SAFE_CHOWN;
3793363466Sgshapiro#  else
379438032Speter	return safedir && errno == 0 && rval IS_SAFE_CHOWN;
3795363466Sgshapiro#  endif
379690795Sgshapiro# else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */
379764565Sgshapiro	return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail);
379890795Sgshapiro# endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */
379938032Speter}
380090795Sgshapiro/*
380138032Speter**  RESETLIMITS -- reset system controlled resource limits
380238032Speter**
380338032Speter**	This is to avoid denial-of-service attacks
380438032Speter**
380538032Speter**	Parameters:
380638032Speter**		none
380738032Speter**
380838032Speter**	Returns:
380938032Speter**		none
381038032Speter*/
381138032Speter
381238032Speter#if HASSETRLIMIT
381338032Speter# ifdef RLIMIT_NEEDS_SYS_TIME_H
3814157006Sgshapiro#  include <sm/time.h>
3815363466Sgshapiro# endif
381638032Speter# include <sys/resource.h>
381764565Sgshapiro#endif /* HASSETRLIMIT */
381838032Speter
381938032Spetervoid
382038032Speterresetlimits()
382138032Speter{
382238032Speter#if HASSETRLIMIT
382338032Speter	struct rlimit lim;
382438032Speter
382538032Speter	lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
382638032Speter	(void) setrlimit(RLIMIT_CPU, &lim);
382738032Speter	(void) setrlimit(RLIMIT_FSIZE, &lim);
382838032Speter# ifdef RLIMIT_NOFILE
382938032Speter	lim.rlim_cur = lim.rlim_max = FD_SETSIZE;
383038032Speter	(void) setrlimit(RLIMIT_NOFILE, &lim);
3831363466Sgshapiro# endif
383264565Sgshapiro#else /* HASSETRLIMIT */
383338032Speter# if HASULIMIT
383438032Speter	(void) ulimit(2, 0x3fffff);
383538032Speter	(void) ulimit(4, FD_SETSIZE);
3836363466Sgshapiro# endif
383764565Sgshapiro#endif /* HASSETRLIMIT */
383838032Speter	errno = 0;
383938032Speter}
384090795Sgshapiro/*
384138032Speter**  SETVENDOR -- process vendor code from V configuration line
384238032Speter**
384338032Speter**	Parameters:
384438032Speter**		vendor -- string representation of vendor.
384538032Speter**
384638032Speter**	Returns:
384790795Sgshapiro**		true -- if ok.
384890795Sgshapiro**		false -- if vendor code could not be processed.
384938032Speter**
385038032Speter**	Side Effects:
385138032Speter**		It is reasonable to set mode flags here to tweak
385238032Speter**		processing in other parts of the code if necessary.
385338032Speter**		For example, if you are a vendor that uses $%y to
385438032Speter**		indicate YP lookups, you could enable that here.
385538032Speter*/
385638032Speter
385738032Speterbool
385838032Spetersetvendor(vendor)
385938032Speter	char *vendor;
386038032Speter{
386190795Sgshapiro	if (sm_strcasecmp(vendor, "Berkeley") == 0)
386238032Speter	{
386338032Speter		VendorCode = VENDOR_BERKELEY;
386490795Sgshapiro		return true;
386538032Speter	}
386638032Speter
386738032Speter	/* add vendor extensions here */
386838032Speter
386938032Speter#ifdef SUN_EXTENSIONS
387090795Sgshapiro	if (sm_strcasecmp(vendor, "Sun") == 0)
387138032Speter	{
387238032Speter		VendorCode = VENDOR_SUN;
387390795Sgshapiro		return true;
387438032Speter	}
387564565Sgshapiro#endif /* SUN_EXTENSIONS */
3876157006Sgshapiro#ifdef DEC
3877157006Sgshapiro	if (sm_strcasecmp(vendor, "Digital") == 0)
3878157006Sgshapiro	{
3879157006Sgshapiro		VendorCode = VENDOR_DEC;
3880157006Sgshapiro		return true;
3881157006Sgshapiro	}
3882157006Sgshapiro#endif /* DEC */
388338032Speter
388442580Speter#if defined(VENDOR_NAME) && defined(VENDOR_CODE)
388590795Sgshapiro	if (sm_strcasecmp(vendor, VENDOR_NAME) == 0)
388642580Speter	{
388742580Speter		VendorCode = VENDOR_CODE;
388890795Sgshapiro		return true;
388942580Speter	}
389064565Sgshapiro#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
389142580Speter
389290795Sgshapiro	return false;
389338032Speter}
389490795Sgshapiro/*
389542580Speter**  GETVENDOR -- return vendor name based on vendor code
389642580Speter**
389742580Speter**	Parameters:
389842580Speter**		vendorcode -- numeric representation of vendor.
389942580Speter**
390042580Speter**	Returns:
390142580Speter**		string containing vendor name.
390242580Speter*/
390342580Speter
390442580Speterchar *
390542580Spetergetvendor(vendorcode)
390642580Speter	int vendorcode;
390742580Speter{
390842580Speter#if defined(VENDOR_NAME) && defined(VENDOR_CODE)
390942580Speter	/*
391064565Sgshapiro	**  Can't have the same switch case twice so need to
391142580Speter	**  handle VENDOR_CODE outside of switch.  It might
391242580Speter	**  match one of the existing VENDOR_* codes.
391342580Speter	*/
391442580Speter
391542580Speter	if (vendorcode == VENDOR_CODE)
391642580Speter		return VENDOR_NAME;
391764565Sgshapiro#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
391842580Speter
391942580Speter	switch (vendorcode)
392042580Speter	{
392190795Sgshapiro	  case VENDOR_BERKELEY:
392290795Sgshapiro		return "Berkeley";
392364565Sgshapiro
392490795Sgshapiro	  case VENDOR_SUN:
392590795Sgshapiro		return "Sun";
392642580Speter
392790795Sgshapiro	  case VENDOR_HP:
392890795Sgshapiro		return "HP";
392942580Speter
393090795Sgshapiro	  case VENDOR_IBM:
393190795Sgshapiro		return "IBM";
393242580Speter
393390795Sgshapiro	  case VENDOR_SENDMAIL:
393490795Sgshapiro		return "Sendmail";
393542580Speter
393690795Sgshapiro	  default:
393790795Sgshapiro		return "Unknown";
393842580Speter	}
393942580Speter}
394090795Sgshapiro/*
394138032Speter**  VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults
394238032Speter**
394338032Speter**	Vendor_pre_defaults is called before reading the configuration
394438032Speter**	file; vendor_post_defaults is called immediately after.
394538032Speter**
394638032Speter**	Parameters:
394738032Speter**		e -- the global environment to initialize.
394838032Speter**
394938032Speter**	Returns:
395038032Speter**		none.
395138032Speter*/
395238032Speter
395338032Speter#if SHARE_V1
395438032Speterint	DefShareUid;	/* default share uid to run as -- unused??? */
3955363466Sgshapiro#endif
395638032Speter
395738032Spetervoid
395838032Spetervendor_pre_defaults(e)
395938032Speter	ENVELOPE *e;
396038032Speter{
396138032Speter#if SHARE_V1
396238032Speter	/* OTHERUID is defined in shares.h, do not be alarmed */
396338032Speter	DefShareUid = OTHERUID;
3964363466Sgshapiro#endif
396538032Speter#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
396638032Speter	sun_pre_defaults(e);
3967363466Sgshapiro#endif
396838032Speter#ifdef apollo
396964565Sgshapiro	/*
397064565Sgshapiro	**  stupid domain/os can't even open
397164565Sgshapiro	**  /etc/mail/sendmail.cf without this
397264565Sgshapiro	*/
397364565Sgshapiro
3974157006Sgshapiro	sm_setuserenv("ISP", NULL);
3975157006Sgshapiro	sm_setuserenv("SYSTYPE", NULL);
397664565Sgshapiro#endif /* apollo */
397738032Speter}
397838032Speter
397938032Speter
398038032Spetervoid
398138032Spetervendor_post_defaults(e)
398238032Speter	ENVELOPE *e;
398338032Speter{
398438032Speter#ifdef __QNX__
398538032Speter	/* Makes sure the SOCK environment variable remains */
3986168520Sgshapiro	sm_setuserenv("SOCK", NULL);
3987363466Sgshapiro#endif
398838032Speter#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
398938032Speter	sun_post_defaults(e);
3990363466Sgshapiro#endif
399138032Speter}
399290795Sgshapiro/*
399338032Speter**  VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode
399438032Speter*/
399538032Speter
399638032Spetervoid
399738032Spetervendor_daemon_setup(e)
399838032Speter	ENVELOPE *e;
399938032Speter{
400064565Sgshapiro#if HASSETLOGIN
400164565Sgshapiro	(void) setlogin(RunAsUserName);
4002363466Sgshapiro#endif
400338032Speter#if SECUREWARE
400438032Speter	if (getluid() != -1)
400538032Speter	{
400638032Speter		usrerr("Daemon cannot have LUID");
400790795Sgshapiro		finis(false, true, EX_USAGE);
400838032Speter	}
400938032Speter#endif /* SECUREWARE */
401038032Speter}
401190795Sgshapiro/*
401238032Speter**  VENDOR_SET_UID -- do setup for setting a user id
401338032Speter**
401438032Speter**	This is called when we are still root.
401538032Speter**
401638032Speter**	Parameters:
401738032Speter**		uid -- the uid we are about to become.
401838032Speter**
401938032Speter**	Returns:
402038032Speter**		none.
402138032Speter*/
402238032Speter
402338032Spetervoid
402438032Spetervendor_set_uid(uid)
402538032Speter	UID_T uid;
402638032Speter{
402764565Sgshapiro	/*
402838032Speter	**  We need to setup the share groups (lnodes)
402964565Sgshapiro	**  and add auditing information (luid's)
403038032Speter	**  before we loose our ``root''ness.
403138032Speter	*/
403238032Speter#if SHARE_V1
403338032Speter	if (setupshares(uid, syserr) != 0)
403438032Speter		syserr("Unable to set up shares");
4035363466Sgshapiro#endif
403638032Speter#if SECUREWARE
403738032Speter	(void) setup_secure(uid);
4038363466Sgshapiro#endif
403938032Speter}
404090795Sgshapiro/*
404138032Speter**  VALIDATE_CONNECTION -- check connection for rationality
404238032Speter**
404338032Speter**	If the connection is rejected, this routine should log an
404438032Speter**	appropriate message -- but should never issue any SMTP protocol.
404538032Speter**
404638032Speter**	Parameters:
404738032Speter**		sap -- a pointer to a SOCKADDR naming the peer.
404838032Speter**		hostname -- the name corresponding to sap.
404938032Speter**		e -- the current envelope.
405038032Speter**
405138032Speter**	Returns:
405238032Speter**		error message from rejection.
405338032Speter**		NULL if not rejected.
405438032Speter*/
405538032Speter
405638032Speter#if TCPWRAPPERS
405738032Speter# include <tcpd.h>
405838032Speter
405938032Speter/* tcpwrappers does no logging, but you still have to declare these -- ugh */
406038032Speterint	allow_severity	= LOG_INFO;
406138032Speterint	deny_severity	= LOG_NOTICE;
406264565Sgshapiro#endif /* TCPWRAPPERS */
406338032Speter
406438032Speterchar *
406538032Spetervalidate_connection(sap, hostname, e)
406638032Speter	SOCKADDR *sap;
406738032Speter	char *hostname;
406838032Speter	ENVELOPE *e;
406938032Speter{
407090795Sgshapiro#if TCPWRAPPERS
407138032Speter	char *host;
407290795Sgshapiro	char *addr;
407390795Sgshapiro	extern int hosts_ctl();
407490795Sgshapiro#endif /* TCPWRAPPERS */
407538032Speter
407638032Speter	if (tTd(48, 3))
407790795Sgshapiro		sm_dprintf("validate_connection(%s, %s)\n",
407838032Speter			hostname, anynet_ntoa(sap));
407938032Speter
4080132946Sgshapiro	connection_rate_check(sap, e);
4081285229Sgshapiro	if (rscheck("check_relay", hostname, anynet_ntoa(sap), e,
4082285229Sgshapiro		    RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID, NULL, NULL) != EX_OK)
408338032Speter	{
408438032Speter		static char reject[BUFSIZ*2];
408538032Speter		extern char MsgBuf[];
408638032Speter
408738032Speter		if (tTd(48, 4))
408890795Sgshapiro			sm_dprintf("  ... validate_connection: BAD (rscheck)\n");
408938032Speter
409064565Sgshapiro		if (strlen(MsgBuf) >= 3)
4091168520Sgshapiro			(void) sm_strlcpy(reject, MsgBuf, sizeof(reject));
409238032Speter		else
4093168520Sgshapiro			(void) sm_strlcpy(reject, "Access denied", sizeof(reject));
409438032Speter
409538032Speter		return reject;
409638032Speter	}
409738032Speter
409890795Sgshapiro#if TCPWRAPPERS
409938032Speter	if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']')
410038032Speter		host = "unknown";
410138032Speter	else
410238032Speter		host = hostname;
410390795Sgshapiro	addr = anynet_ntoa(sap);
410490795Sgshapiro
410590795Sgshapiro# if NETINET6
410690795Sgshapiro	/* TCP/Wrappers don't want the IPv6: protocol label */
410790795Sgshapiro	if (addr != NULL && sm_strncasecmp(addr, "IPv6:", 5) == 0)
410890795Sgshapiro		addr += 5;
410990795Sgshapiro# endif /* NETINET6 */
411090795Sgshapiro
411190795Sgshapiro	if (!hosts_ctl("sendmail", host, addr, STRING_UNKNOWN))
411238032Speter	{
411338032Speter		if (tTd(48, 4))
411490795Sgshapiro			sm_dprintf("  ... validate_connection: BAD (tcpwrappers)\n");
411590795Sgshapiro		if (LogLevel > 3)
411664565Sgshapiro			sm_syslog(LOG_NOTICE, e->e_id,
411790795Sgshapiro				  "tcpwrappers (%s, %s) rejection",
411890795Sgshapiro				  host, addr);
411938032Speter		return "Access denied";
412038032Speter	}
412190795Sgshapiro#endif /* TCPWRAPPERS */
412238032Speter	if (tTd(48, 4))
412390795Sgshapiro		sm_dprintf("  ... validate_connection: OK\n");
412438032Speter	return NULL;
412538032Speter}
412638032Speter
412790795Sgshapiro/*
412838032Speter**  STRTOL -- convert string to long integer
412938032Speter**
413038032Speter**	For systems that don't have it in the C library.
413138032Speter**
413238032Speter**	This is taken verbatim from the 4.4-Lite C library.
413338032Speter*/
413438032Speter
413564565Sgshapiro#if NEEDSTRTOL
413638032Speter
413764565Sgshapiro# if defined(LIBC_SCCS) && !defined(lint)
413838032Speterstatic char sccsid[] = "@(#)strtol.c	8.1 (Berkeley) 6/4/93";
4139363466Sgshapiro# endif
414038032Speter
414138032Speter/*
414290795Sgshapiro**  Convert a string to a long integer.
414390795Sgshapiro**
414490795Sgshapiro**  Ignores `locale' stuff.  Assumes that the upper and lower case
414590795Sgshapiro**  alphabets and digits are each contiguous.
414690795Sgshapiro*/
414738032Speter
414838032Speterlong
414938032Speterstrtol(nptr, endptr, base)
415038032Speter	const char *nptr;
415138032Speter	char **endptr;
415238032Speter	register int base;
415338032Speter{
415438032Speter	register const char *s = nptr;
415538032Speter	register unsigned long acc;
415638032Speter	register int c;
415738032Speter	register unsigned long cutoff;
415838032Speter	register int neg = 0, any, cutlim;
415938032Speter
416038032Speter	/*
416190795Sgshapiro	**  Skip white space and pick up leading +/- sign if any.
416290795Sgshapiro	**  If base is 0, allow 0x for hex and 0 for octal, else
416390795Sgshapiro	**  assume decimal; if base is already 16, allow 0x.
416490795Sgshapiro	*/
416538032Speter	do {
416638032Speter		c = *s++;
4167363466Sgshapiro	} while (SM_ISSPACE(c));
416838032Speter	if (c == '-') {
416938032Speter		neg = 1;
417038032Speter		c = *s++;
417138032Speter	} else if (c == '+')
417238032Speter		c = *s++;
417338032Speter	if ((base == 0 || base == 16) &&
417438032Speter	    c == '0' && (*s == 'x' || *s == 'X')) {
417538032Speter		c = s[1];
417638032Speter		s += 2;
417738032Speter		base = 16;
417838032Speter	}
417938032Speter	if (base == 0)
418038032Speter		base = c == '0' ? 8 : 10;
418138032Speter
418238032Speter	/*
418390795Sgshapiro	**  Compute the cutoff value between legal numbers and illegal
418490795Sgshapiro	**  numbers.  That is the largest legal value, divided by the
418590795Sgshapiro	**  base.  An input number that is greater than this value, if
418690795Sgshapiro	**  followed by a legal input character, is too big.  One that
418790795Sgshapiro	**  is equal to this value may be valid or not; the limit
418890795Sgshapiro	**  between valid and invalid numbers is then based on the last
418990795Sgshapiro	**  digit.  For instance, if the range for longs is
419090795Sgshapiro	**  [-2147483648..2147483647] and the input base is 10,
419190795Sgshapiro	**  cutoff will be set to 214748364 and cutlim to either
419290795Sgshapiro	**  7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
419390795Sgshapiro	**  a value > 214748364, or equal but the next digit is > 7 (or 8),
419490795Sgshapiro	**  the number is too big, and we will return a range error.
419590795Sgshapiro	**
419690795Sgshapiro	**  Set any if any `digits' consumed; make it negative to indicate
419790795Sgshapiro	**  overflow.
419890795Sgshapiro	*/
419990795Sgshapiro	cutoff = neg ? -(unsigned long) LONG_MIN : LONG_MAX;
420090795Sgshapiro	cutlim = cutoff % (unsigned long) base;
420190795Sgshapiro	cutoff /= (unsigned long) base;
420238032Speter	for (acc = 0, any = 0;; c = *s++) {
4203203004Sgshapiro		if (isascii(c) && isdigit(c))
420438032Speter			c -= '0';
4205203004Sgshapiro		else if (isascii(c) && isalpha(c))
420638032Speter			c -= isupper(c) ? 'A' - 10 : 'a' - 10;
420738032Speter		else
420838032Speter			break;
420938032Speter		if (c >= base)
421038032Speter			break;
421138032Speter		if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
421238032Speter			any = -1;
421338032Speter		else {
421438032Speter			any = 1;
421538032Speter			acc *= base;
421638032Speter			acc += c;
421738032Speter		}
421838032Speter	}
421938032Speter	if (any < 0) {
422038032Speter		acc = neg ? LONG_MIN : LONG_MAX;
422138032Speter		errno = ERANGE;
422238032Speter	} else if (neg)
422338032Speter		acc = -acc;
4224363466Sgshapiro	if (endptr != NULL)
422538032Speter		*endptr = (char *)(any ? s - 1 : nptr);
422664565Sgshapiro	return acc;
422738032Speter}
422838032Speter
422964565Sgshapiro#endif /* NEEDSTRTOL */
423090795Sgshapiro/*
423138032Speter**  STRSTR -- find first substring in string
423238032Speter**
423338032Speter**	Parameters:
423438032Speter**		big -- the big (full) string.
423538032Speter**		little -- the little (sub) string.
423638032Speter**
423738032Speter**	Returns:
423838032Speter**		A pointer to the first instance of little in big.
423938032Speter**		big if little is the null string.
424038032Speter**		NULL if little is not contained in big.
424138032Speter*/
424238032Speter
424364565Sgshapiro#if NEEDSTRSTR
424438032Speter
424538032Speterchar *
424638032Speterstrstr(big, little)
424738032Speter	char *big;
424838032Speter	char *little;
424938032Speter{
425038032Speter	register char *p = big;
425138032Speter	int l;
425238032Speter
425338032Speter	if (*little == '\0')
425438032Speter		return big;
425538032Speter	l = strlen(little);
425638032Speter
425738032Speter	while ((p = strchr(p, *little)) != NULL)
425838032Speter	{
425938032Speter		if (strncmp(p, little, l) == 0)
426038032Speter			return p;
426138032Speter		p++;
426238032Speter	}
426338032Speter	return NULL;
426438032Speter}
426538032Speter
426664565Sgshapiro#endif /* NEEDSTRSTR */
426790795Sgshapiro/*
426838032Speter**  SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
426938032Speter**
4270223067Sgshapiro**	Some operating systems have weird problems with the gethostbyXXX
427138032Speter**	routines.  For example, Solaris versions at least through 2.3
427238032Speter**	don't properly deliver a canonical h_name field.  This tries to
427338032Speter**	work around these problems.
427464565Sgshapiro**
427564565Sgshapiro**	Support IPv6 as well as IPv4.
427638032Speter*/
427738032Speter
427877352Sgshapiro#if NETINET6 && NEEDSGETIPNODE
427964565Sgshapiro
428064565Sgshapiro# ifndef AI_DEFAULT
428164565Sgshapiro#  define AI_DEFAULT	0	/* dummy */
4282363466Sgshapiro# endif
428364565Sgshapiro# ifndef AI_ADDRCONFIG
428464565Sgshapiro#  define AI_ADDRCONFIG	0	/* dummy */
4285363466Sgshapiro# endif
428664565Sgshapiro# ifndef AI_V4MAPPED
428764565Sgshapiro#  define AI_V4MAPPED	0	/* dummy */
4288363466Sgshapiro# endif
428964565Sgshapiro# ifndef AI_ALL
429064565Sgshapiro#  define AI_ALL	0	/* dummy */
4291363466Sgshapiro# endif
429264565Sgshapiro
429364565Sgshapirostatic struct hostent *
4294223067Sgshapirosm_getipnodebyname(name, family, flags, err)
4295223067Sgshapiro	const char *name;
429664565Sgshapiro	int family;
429764565Sgshapiro	int flags;
429864565Sgshapiro	int *err;
429964565Sgshapiro{
430064565Sgshapiro	struct hostent *h;
4301261194Sgshapiro# if HAS_GETHOSTBYNAME2
430264565Sgshapiro
4303261194Sgshapiro	h = gethostbyname2(name, family);
4304261194Sgshapiro	if (h == NULL)
4305261194Sgshapiro		*err = h_errno;
4306261194Sgshapiro	return h;
4307261194Sgshapiro
4308261194Sgshapiro# else /* HAS_GETHOSTBYNAME2 */
4309363466Sgshapiro#  ifdef RES_USE_INET6
4310261194Sgshapiro	bool resv6 = true;
4311261194Sgshapiro
431264565Sgshapiro	if (family == AF_INET6)
431364565Sgshapiro	{
431464565Sgshapiro		/* From RFC2133, section 6.1 */
431564565Sgshapiro		resv6 = bitset(RES_USE_INET6, _res.options);
431664565Sgshapiro		_res.options |= RES_USE_INET6;
431764565Sgshapiro	}
4318363466Sgshapiro#  endif /* RES_USE_INET6 */
431973191Sgshapiro	SM_SET_H_ERRNO(0);
432064565Sgshapiro	h = gethostbyname(name);
4321363466Sgshapiro#  ifdef RES_USE_INET6
432290795Sgshapiro	if (!resv6)
432390795Sgshapiro		_res.options &= ~RES_USE_INET6;
4324363466Sgshapiro#  endif
4325261194Sgshapiro
4326261194Sgshapiro	/* the function is supposed to return only the requested family */
4327261194Sgshapiro	if (h != NULL && h->h_addrtype != family)
4328261194Sgshapiro	{
4329261194Sgshapiro#  if NETINET6
4330261194Sgshapiro		freehostent(h);
4331363466Sgshapiro#  endif
4332261194Sgshapiro		h = NULL;
4333261194Sgshapiro		*err = NO_DATA;
4334261194Sgshapiro	}
4335261194Sgshapiro	else
4336261194Sgshapiro		*err = h_errno;
433764565Sgshapiro	return h;
4338261194Sgshapiro# endif /* HAS_GETHOSTBYNAME2 */
433964565Sgshapiro}
434064565Sgshapiro
434164565Sgshapirostatic struct hostent *
4342223067Sgshapirosm_getipnodebyaddr(addr, len, family, err)
4343223067Sgshapiro	const void *addr;
4344223067Sgshapiro	size_t len;
434564565Sgshapiro	int family;
434664565Sgshapiro	int *err;
434764565Sgshapiro{
434864565Sgshapiro	struct hostent *h;
434964565Sgshapiro
435073191Sgshapiro	SM_SET_H_ERRNO(0);
435164565Sgshapiro	h = gethostbyaddr(addr, len, family);
435264565Sgshapiro	*err = h_errno;
435364565Sgshapiro	return h;
435464565Sgshapiro}
435571348Sgshapiro
435671348Sgshapirovoid
435771348Sgshapirofreehostent(h)
435871348Sgshapiro	struct hostent *h;
435971348Sgshapiro{
436071348Sgshapiro	/*
436171348Sgshapiro	**  Stub routine -- if they don't have getipnodeby*(),
436271348Sgshapiro	**  they probably don't have the free routine either.
436371348Sgshapiro	*/
436471348Sgshapiro
436571348Sgshapiro	return;
436671348Sgshapiro}
436790795Sgshapiro#endif /* NETINET6 && NEEDSGETIPNODE */
436864565Sgshapiro
436938032Speterstruct hostent *
437064565Sgshapirosm_gethostbyname(name, family)
437138032Speter	char *name;
437264565Sgshapiro	int family;
437338032Speter{
437473191Sgshapiro	int save_errno;
437564565Sgshapiro	struct hostent *h = NULL;
437638032Speter#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
437738032Speter# if SOLARIS == 20300 || SOLARIS == 203
437838032Speter	static struct hostent hp;
437938032Speter	static char buf[1000];
438038032Speter	extern struct hostent *_switch_gethostbyname_r();
438138032Speter
438238032Speter	if (tTd(61, 10))
438390795Sgshapiro		sm_dprintf("_switch_gethostbyname_r(%s)... ", name);
438438032Speter	h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
438573191Sgshapiro	save_errno = errno;
438664565Sgshapiro# else /* SOLARIS == 20300 || SOLARIS == 203 */
438738032Speter	extern struct hostent *__switch_gethostbyname();
438838032Speter
438938032Speter	if (tTd(61, 10))
439090795Sgshapiro		sm_dprintf("__switch_gethostbyname(%s)... ", name);
439138032Speter	h = __switch_gethostbyname(name);
439273191Sgshapiro	save_errno = errno;
439364565Sgshapiro# endif /* SOLARIS == 20300 || SOLARIS == 203 */
439464565Sgshapiro#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
439538032Speter	int nmaps;
439664565Sgshapiro# if NETINET6
4397249729Sgshapiro#  ifndef SM_IPNODEBYNAME_FLAGS
4398249729Sgshapiro    /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */
4399249729Sgshapiro#   define SM_IPNODEBYNAME_FLAGS	AI_ADDRCONFIG
4400363466Sgshapiro#  endif
4401249729Sgshapiro
4402249729Sgshapiro	int flags = SM_IPNODEBYNAME_FLAGS;
440364565Sgshapiro	int err;
440464565Sgshapiro# endif /* NETINET6 */
440538032Speter	char *maptype[MAXMAPSTACK];
440638032Speter	short mapreturn[MAXMAPACTIONS];
440738032Speter	char hbuf[MAXNAME];
440838032Speter
440938032Speter	if (tTd(61, 10))
441090795Sgshapiro		sm_dprintf("sm_gethostbyname(%s, %d)... ", name, family);
441164565Sgshapiro
441264565Sgshapiro# if NETINET6
441364565Sgshapiro#  if ADDRCONFIG_IS_BROKEN
441464565Sgshapiro	flags &= ~AI_ADDRCONFIG;
4415363466Sgshapiro#  endif
4416223067Sgshapiro	h = sm_getipnodebyname(name, family, flags, &err);
441773191Sgshapiro	SM_SET_H_ERRNO(err);
441864565Sgshapiro# else /* NETINET6 */
441938032Speter	h = gethostbyname(name);
442064565Sgshapiro# endif /* NETINET6 */
442164565Sgshapiro
442264565Sgshapiro	save_errno = errno;
442338032Speter	if (h == NULL)
442438032Speter	{
442538032Speter		if (tTd(61, 10))
442690795Sgshapiro			sm_dprintf("failure\n");
442738032Speter
442838032Speter		nmaps = switch_map_find("hosts", maptype, mapreturn);
442938032Speter		while (--nmaps >= 0)
443071348Sgshapiro		{
443138032Speter			if (strcmp(maptype[nmaps], "nis") == 0 ||
443238032Speter			    strcmp(maptype[nmaps], "files") == 0)
443338032Speter				break;
443471348Sgshapiro		}
443571348Sgshapiro
443638032Speter		if (nmaps >= 0)
443738032Speter		{
443838032Speter			/* try short name */
4439168520Sgshapiro			if (strlen(name) > sizeof(hbuf) - 1)
444064565Sgshapiro			{
444164565Sgshapiro				errno = save_errno;
444238032Speter				return NULL;
444364565Sgshapiro			}
4444168520Sgshapiro			(void) sm_strlcpy(hbuf, name, sizeof(hbuf));
444573191Sgshapiro			(void) shorten_hostname(hbuf);
444638032Speter
444738032Speter			/* if it hasn't been shortened, there's no point */
444838032Speter			if (strcmp(hbuf, name) != 0)
444938032Speter			{
445038032Speter				if (tTd(61, 10))
445190795Sgshapiro					sm_dprintf("sm_gethostbyname(%s, %d)... ",
445264565Sgshapiro					       hbuf, family);
445364565Sgshapiro
445464565Sgshapiro# if NETINET6
4455223067Sgshapiro				h = sm_getipnodebyname(hbuf, family, flags, &err);
445673191Sgshapiro				SM_SET_H_ERRNO(err);
445764565Sgshapiro				save_errno = errno;
445864565Sgshapiro# else /* NETINET6 */
445938032Speter				h = gethostbyname(hbuf);
446064565Sgshapiro				save_errno = errno;
446164565Sgshapiro# endif /* NETINET6 */
446238032Speter			}
446338032Speter		}
446438032Speter	}
446564565Sgshapiro#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
4466261194Sgshapiro
4467261194Sgshapiro	/* the function is supposed to return only the requested family */
4468261194Sgshapiro	if (h != NULL && h->h_addrtype != family)
4469261194Sgshapiro	{
4470261194Sgshapiro# if NETINET6
4471261194Sgshapiro		freehostent(h);
4472363466Sgshapiro# endif
4473261194Sgshapiro		h = NULL;
4474261194Sgshapiro		SM_SET_H_ERRNO(NO_DATA);
4475261194Sgshapiro	}
4476261194Sgshapiro
447738032Speter	if (tTd(61, 10))
447838032Speter	{
447938032Speter		if (h == NULL)
448090795Sgshapiro			sm_dprintf("failure\n");
448138032Speter		else
448264565Sgshapiro		{
448390795Sgshapiro			sm_dprintf("%s\n", h->h_name);
448464565Sgshapiro			if (tTd(61, 11))
448564565Sgshapiro			{
4486261194Sgshapiro				struct in_addr ia;
4487261194Sgshapiro				size_t i;
448864565Sgshapiro#if NETINET6
448964565Sgshapiro				struct in6_addr ia6;
449064565Sgshapiro				char buf6[INET6_ADDRSTRLEN];
4491363466Sgshapiro#endif
449264565Sgshapiro
449364565Sgshapiro				if (h->h_aliases != NULL)
449464565Sgshapiro					for (i = 0; h->h_aliases[i] != NULL;
449564565Sgshapiro					     i++)
449690795Sgshapiro						sm_dprintf("\talias: %s\n",
449764565Sgshapiro							h->h_aliases[i]);
449864565Sgshapiro				for (i = 0; h->h_addr_list[i] != NULL; i++)
449964565Sgshapiro				{
450064565Sgshapiro					char *addr;
450164565Sgshapiro
4502261194Sgshapiro					addr = NULL;
450364565Sgshapiro#if NETINET6
4504261194Sgshapiro					if (h->h_addrtype == AF_INET6)
4505261194Sgshapiro					{
4506261194Sgshapiro						memmove(&ia6, h->h_addr_list[i],
4507261194Sgshapiro							IN6ADDRSZ);
4508261194Sgshapiro						addr = anynet_ntop(&ia6,
4509261194Sgshapiro							buf6, sizeof(buf6));
4510261194Sgshapiro					}
4511261194Sgshapiro					else
451264565Sgshapiro#endif /* NETINET6 */
4513261194Sgshapiro					/* "else" in #if code above */
4514261194Sgshapiro					{
4515261194Sgshapiro						memmove(&ia, h->h_addr_list[i],
4516261194Sgshapiro							INADDRSZ);
4517261194Sgshapiro						addr = (char *) inet_ntoa(ia);
4518261194Sgshapiro					}
451964565Sgshapiro					if (addr != NULL)
452090795Sgshapiro						sm_dprintf("\taddr: %s\n", addr);
452164565Sgshapiro				}
452264565Sgshapiro			}
452364565Sgshapiro		}
452438032Speter	}
452564565Sgshapiro	errno = save_errno;
452638032Speter	return h;
452738032Speter}
452838032Speter
452938032Speterstruct hostent *
453038032Spetersm_gethostbyaddr(addr, len, type)
453138032Speter	char *addr;
453238032Speter	int len;
453338032Speter	int type;
453438032Speter{
453564565Sgshapiro	struct hostent *hp;
453673191Sgshapiro
453773191Sgshapiro#if NETINET6
453873191Sgshapiro	if (type == AF_INET6 &&
453973191Sgshapiro	    IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *) addr))
454073191Sgshapiro	{
454173191Sgshapiro		/* Avoid reverse lookup for IPv6 unspecified address */
454273191Sgshapiro		SM_SET_H_ERRNO(HOST_NOT_FOUND);
454373191Sgshapiro		return NULL;
454473191Sgshapiro	}
454573191Sgshapiro#endif /* NETINET6 */
454673191Sgshapiro
454738032Speter#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204)
454838032Speter# if SOLARIS == 20300 || SOLARIS == 203
454973191Sgshapiro	{
455073191Sgshapiro		static struct hostent he;
455173191Sgshapiro		static char buf[1000];
455273191Sgshapiro		extern struct hostent *_switch_gethostbyaddr_r();
455338032Speter
455473191Sgshapiro		hp = _switch_gethostbyaddr_r(addr, len, type, &he,
455573191Sgshapiro					     buf, sizeof(buf), &h_errno);
455673191Sgshapiro	}
455764565Sgshapiro# else /* SOLARIS == 20300 || SOLARIS == 203 */
455873191Sgshapiro	{
455973191Sgshapiro		extern struct hostent *__switch_gethostbyaddr();
456038032Speter
456173191Sgshapiro		hp = __switch_gethostbyaddr(addr, len, type);
456273191Sgshapiro	}
456364565Sgshapiro# endif /* SOLARIS == 20300 || SOLARIS == 203 */
456464565Sgshapiro#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
456564565Sgshapiro# if NETINET6
456673191Sgshapiro	{
456773191Sgshapiro		int err;
456864565Sgshapiro
4569223067Sgshapiro		hp = sm_getipnodebyaddr(addr, len, type, &err);
457073191Sgshapiro		SM_SET_H_ERRNO(err);
457173191Sgshapiro	}
457264565Sgshapiro# else /* NETINET6 */
457364565Sgshapiro	hp = gethostbyaddr(addr, len, type);
457464565Sgshapiro# endif /* NETINET6 */
457577352Sgshapiro#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
457664565Sgshapiro	return hp;
457738032Speter}
457890795Sgshapiro/*
457938032Speter**  SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid
458038032Speter*/
458138032Speter
458238032Speterstruct passwd *
458338032Spetersm_getpwnam(user)
458438032Speter	char *user;
458538032Speter{
458690795Sgshapiro#ifdef _AIX4
458738032Speter	extern struct passwd *_getpwnam_shadow(const char *, const int);
458838032Speter
458938032Speter	return _getpwnam_shadow(user, 0);
459090795Sgshapiro#else /* _AIX4 */
459138032Speter	return getpwnam(user);
459290795Sgshapiro#endif /* _AIX4 */
459338032Speter}
459438032Speter
459538032Speterstruct passwd *
459638032Spetersm_getpwuid(uid)
459738032Speter	UID_T uid;
459838032Speter{
459990795Sgshapiro#if defined(_AIX4) && 0
460038032Speter	extern struct passwd *_getpwuid_shadow(const int, const int);
460138032Speter
460238032Speter	return _getpwuid_shadow(uid,0);
460390795Sgshapiro#else /* defined(_AIX4) && 0 */
460438032Speter	return getpwuid(uid);
460590795Sgshapiro#endif /* defined(_AIX4) && 0 */
460638032Speter}
460790795Sgshapiro/*
460838032Speter**  SECUREWARE_SETUP_SECURE -- Convex SecureWare setup
460938032Speter**
461038032Speter**	Set up the trusted computing environment for C2 level security
461138032Speter**	under SecureWare.
461238032Speter**
461338032Speter**	Parameters:
461438032Speter**		uid -- uid of the user to initialize in the TCB
461538032Speter**
461638032Speter**	Returns:
461738032Speter**		none
461838032Speter**
461938032Speter**	Side Effects:
462038032Speter**		Initialized the user in the trusted computing base
462138032Speter*/
462238032Speter
462338032Speter#if SECUREWARE
462438032Speter
462538032Speter# include <sys/security.h>
462638032Speter# include <prot.h>
462738032Speter
462838032Spetervoid
462938032Spetersecureware_setup_secure(uid)
463038032Speter	UID_T uid;
463138032Speter{
463238032Speter	int rc;
463338032Speter
463438032Speter	if (getluid() != -1)
463538032Speter		return;
463664565Sgshapiro
463738032Speter	if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN)
463838032Speter	{
463938032Speter		switch (rc)
464038032Speter		{
464138032Speter		  case SSI_NO_PRPW_ENTRY:
464290795Sgshapiro			syserr("No protected passwd entry, uid = %d",
464390795Sgshapiro			       (int) uid);
464438032Speter			break;
464538032Speter
464638032Speter		  case SSI_LOCKED:
464790795Sgshapiro			syserr("Account has been disabled, uid = %d",
464890795Sgshapiro			       (int) uid);
464938032Speter			break;
465038032Speter
465138032Speter		  case SSI_RETIRED:
465290795Sgshapiro			syserr("Account has been retired, uid = %d",
465390795Sgshapiro			       (int) uid);
465438032Speter			break;
465538032Speter
465638032Speter		  case SSI_BAD_SET_LUID:
465790795Sgshapiro			syserr("Could not set LUID, uid = %d", (int) uid);
465838032Speter			break;
465938032Speter
466038032Speter		  case SSI_BAD_SET_PRIVS:
466190795Sgshapiro			syserr("Could not set kernel privs, uid = %d",
466290795Sgshapiro			       (int) uid);
466338032Speter
466438032Speter		  default:
466564565Sgshapiro			syserr("Unknown return code (%d) from set_secure_info(%d)",
466690795Sgshapiro				rc, (int) uid);
466738032Speter			break;
466838032Speter		}
466990795Sgshapiro		finis(false, true, EX_NOPERM);
467038032Speter	}
467138032Speter}
467238032Speter#endif /* SECUREWARE */
467390795Sgshapiro/*
467464565Sgshapiro**  ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address
467542580Speter**
467642580Speter**	Add hostnames to class 'w' based on the IP address read from
467742580Speter**	the network interface.
467842580Speter**
467942580Speter**	Parameters:
468042580Speter**		sa -- a pointer to a SOCKADDR containing the address
468142580Speter**
468242580Speter**	Returns:
468342580Speter**		0 if successful, -1 if host lookup fails.
468442580Speter*/
468542580Speter
468664565Sgshapirostatic int
468742580Speteradd_hostnames(sa)
468842580Speter	SOCKADDR *sa;
468942580Speter{
469042580Speter	struct hostent *hp;
469164565Sgshapiro	char **ha;
469264565Sgshapiro	char hnb[MAXHOSTNAMELEN];
469342580Speter
469442580Speter	/* lookup name with IP address */
469542580Speter	switch (sa->sa.sa_family)
469642580Speter	{
469764565Sgshapiro#if NETINET
469890795Sgshapiro	  case AF_INET:
469990795Sgshapiro		hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr,
470090795Sgshapiro				      sizeof(sa->sin.sin_addr),
470190795Sgshapiro				      sa->sa.sa_family);
470290795Sgshapiro		break;
470364565Sgshapiro#endif /* NETINET */
470442580Speter
470564565Sgshapiro#if NETINET6
470690795Sgshapiro	  case AF_INET6:
470790795Sgshapiro		hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr,
470890795Sgshapiro				      sizeof(sa->sin6.sin6_addr),
470990795Sgshapiro				      sa->sa.sa_family);
471090795Sgshapiro		break;
471164565Sgshapiro#endif /* NETINET6 */
471264565Sgshapiro
471390795Sgshapiro	  default:
471490795Sgshapiro		/* Give warning about unsupported family */
471590795Sgshapiro		if (LogLevel > 3)
471690795Sgshapiro			sm_syslog(LOG_WARNING, NOQID,
471790795Sgshapiro				  "Unsupported address family %d: %.100s",
471890795Sgshapiro				  sa->sa.sa_family, anynet_ntoa(sa));
471990795Sgshapiro		return -1;
472042580Speter	}
472142580Speter
472242580Speter	if (hp == NULL)
472342580Speter	{
472442580Speter		int save_errno = errno;
472542580Speter
472664565Sgshapiro		if (LogLevel > 3 &&
4727244833Sgshapiro#if NETINET && defined(IN_LINKLOCAL)
4728244833Sgshapiro		    !(sa->sa.sa_family == AF_INET &&
4729244833Sgshapiro		      IN_LINKLOCAL(ntohl(sa->sin.sin_addr.s_addr))) &&
4730363466Sgshapiro#endif
473164565Sgshapiro#if NETINET6
473264565Sgshapiro		    !(sa->sa.sa_family == AF_INET6 &&
473364565Sgshapiro		      IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) &&
4734363466Sgshapiro#endif
473590795Sgshapiro		    true)
473642580Speter			sm_syslog(LOG_WARNING, NOQID,
473790795Sgshapiro				  "gethostbyaddr(%.100s) failed: %d",
473890795Sgshapiro				  anynet_ntoa(sa),
473942580Speter#if NAMED_BIND
474090795Sgshapiro				  h_errno
4741363466Sgshapiro#else
474290795Sgshapiro				  -1
4743363466Sgshapiro#endif
474490795Sgshapiro				 );
474542580Speter		errno = save_errno;
474642580Speter		return -1;
474742580Speter	}
474842580Speter
474942580Speter	/* save its cname */
475042580Speter	if (!wordinclass((char *) hp->h_name, 'w'))
475142580Speter	{
475242580Speter		setclass('w', (char *) hp->h_name);
475342580Speter		if (tTd(0, 4))
475490795Sgshapiro			sm_dprintf("\ta.k.a.: %s\n", hp->h_name);
475564565Sgshapiro
4756168520Sgshapiro		if (sm_snprintf(hnb, sizeof(hnb), "[%s]", hp->h_name) <
4757168520Sgshapiro								sizeof(hnb)
475864565Sgshapiro		    && !wordinclass((char *) hnb, 'w'))
475964565Sgshapiro			setclass('w', hnb);
476042580Speter	}
476164565Sgshapiro	else
476264565Sgshapiro	{
476364565Sgshapiro		if (tTd(0, 43))
476490795Sgshapiro			sm_dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name);
476564565Sgshapiro	}
476642580Speter
476742580Speter	/* save all it aliases name */
476864565Sgshapiro	for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
476942580Speter	{
477064565Sgshapiro		if (!wordinclass(*ha, 'w'))
477142580Speter		{
477264565Sgshapiro			setclass('w', *ha);
477342580Speter			if (tTd(0, 4))
477490795Sgshapiro				sm_dprintf("\ta.k.a.: %s\n", *ha);
4775168520Sgshapiro			if (sm_snprintf(hnb, sizeof(hnb),
4776168520Sgshapiro				     "[%s]", *ha) < sizeof(hnb) &&
477764565Sgshapiro			    !wordinclass((char *) hnb, 'w'))
477864565Sgshapiro				setclass('w', hnb);
477942580Speter		}
478064565Sgshapiro		else
478164565Sgshapiro		{
478264565Sgshapiro			if (tTd(0, 43))
478390795Sgshapiro				sm_dprintf("\ta.k.a.: %s (already in $=w)\n",
478464565Sgshapiro					*ha);
478564565Sgshapiro		}
478642580Speter	}
478790795Sgshapiro#if NETINET6
478871348Sgshapiro	freehostent(hp);
4789363466Sgshapiro#endif
479042580Speter	return 0;
479142580Speter}
479290795Sgshapiro/*
479338032Speter**  LOAD_IF_NAMES -- load interface-specific names into $=w
479438032Speter**
479538032Speter**	Parameters:
479638032Speter**		none.
479738032Speter**
479838032Speter**	Returns:
479938032Speter**		none.
480038032Speter**
480138032Speter**	Side Effects:
480238032Speter**		Loads $=w with the names of all the interfaces.
480338032Speter*/
480438032Speter
480564565Sgshapiro#if !NETINET
480664565Sgshapiro# define SIOCGIFCONF_IS_BROKEN	1 /* XXX */
4807363466Sgshapiro#endif
480864565Sgshapiro
480938032Speter#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
481038032Speterstruct rtentry;
481138032Speterstruct mbuf;
481238032Speter# ifndef SUNOS403
4813157006Sgshapiro#  include <sm/time.h>
4814363466Sgshapiro# endif
481564565Sgshapiro# if (_AIX4 >= 40300) && !defined(_NET_IF_H)
481638032Speter#  undef __P
4817363466Sgshapiro# endif
481838032Speter# include <net/if.h>
481964565Sgshapiro#endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
482038032Speter
482138032Spetervoid
482238032Speterload_if_names()
482338032Speter{
482490795Sgshapiro# if NETINET6 && defined(SIOCGLIFCONF)
482590795Sgshapiro#  ifdef __hpux
482690795Sgshapiro
482790795Sgshapiro    /*
482890795Sgshapiro    **  Unfortunately, HP has changed all of the structures,
482990795Sgshapiro    **  making life difficult for implementors.
483090795Sgshapiro    */
483190795Sgshapiro
483290795Sgshapiro#   define lifconf	if_laddrconf
483390795Sgshapiro#   define lifc_len	iflc_len
483490795Sgshapiro#   define lifc_buf	iflc_buf
483590795Sgshapiro#   define lifreq	if_laddrreq
483690795Sgshapiro#   define lifr_addr	iflr_addr
483790795Sgshapiro#   define lifr_name	iflr_name
483890795Sgshapiro#   define lifr_flags	iflr_flags
483990795Sgshapiro#   define ss_family	sa_family
484090795Sgshapiro#   undef SIOCGLIFNUM
484190795Sgshapiro#  endif /* __hpux */
484290795Sgshapiro
484338032Speter	int s;
484438032Speter	int i;
484590795Sgshapiro	size_t len;
484690795Sgshapiro	int numifs;
484790795Sgshapiro	char *buf;
484864565Sgshapiro	struct lifconf lifc;
484990795Sgshapiro#  ifdef SIOCGLIFNUM
485064565Sgshapiro	struct lifnum lifn;
4851363466Sgshapiro#  endif
485264565Sgshapiro
485364565Sgshapiro	s = socket(InetMode, SOCK_DGRAM, 0);
485464565Sgshapiro	if (s == -1)
485564565Sgshapiro		return;
485664565Sgshapiro
485764565Sgshapiro	/* get the list of known IP address from the kernel */
485890795Sgshapiro#  ifdef __hpux
485990795Sgshapiro	i = ioctl(s, SIOCGIFNUM, (char *) &numifs);
4860363466Sgshapiro#  endif
486190795Sgshapiro#  ifdef SIOCGLIFNUM
486264565Sgshapiro	lifn.lifn_family = AF_UNSPEC;
486364565Sgshapiro	lifn.lifn_flags = 0;
486490795Sgshapiro	i = ioctl(s, SIOCGLIFNUM, (char *)&lifn);
486590795Sgshapiro	numifs = lifn.lifn_count;
486690795Sgshapiro#  endif /* SIOCGLIFNUM */
486790795Sgshapiro
486890795Sgshapiro#  if defined(__hpux) || defined(SIOCGLIFNUM)
486990795Sgshapiro	if (i < 0)
487064565Sgshapiro	{
487164565Sgshapiro		/* can't get number of interfaces -- fall back */
487264565Sgshapiro		if (tTd(0, 4))
487390795Sgshapiro			sm_dprintf("SIOCGLIFNUM failed: %s\n",
487490795Sgshapiro				   sm_errstring(errno));
487564565Sgshapiro		numifs = -1;
487664565Sgshapiro	}
487790795Sgshapiro	else if (tTd(0, 42))
487890795Sgshapiro		sm_dprintf("system has %d interfaces\n", numifs);
487964565Sgshapiro	if (numifs < 0)
488090795Sgshapiro#  endif /* defined(__hpux) || defined(SIOCGLIFNUM) */
488164565Sgshapiro		numifs = MAXINTERFACES;
488264565Sgshapiro
488364565Sgshapiro	if (numifs <= 0)
488464565Sgshapiro	{
488571348Sgshapiro		(void) close(s);
488664565Sgshapiro		return;
488764565Sgshapiro	}
488890795Sgshapiro
4889168520Sgshapiro	len = lifc.lifc_len = numifs * sizeof(struct lifreq);
489090795Sgshapiro	buf = lifc.lifc_buf = xalloc(lifc.lifc_len);
489190795Sgshapiro#  ifndef __hpux
489264565Sgshapiro	lifc.lifc_family = AF_UNSPEC;
489364565Sgshapiro	lifc.lifc_flags = 0;
4894363466Sgshapiro#  endif
489564565Sgshapiro	if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0)
489664565Sgshapiro	{
489764565Sgshapiro		if (tTd(0, 4))
489890795Sgshapiro			sm_dprintf("SIOCGLIFCONF failed: %s\n",
489990795Sgshapiro				   sm_errstring(errno));
490071348Sgshapiro		(void) close(s);
490190795Sgshapiro		sm_free(buf);
490264565Sgshapiro		return;
490364565Sgshapiro	}
490464565Sgshapiro
490564565Sgshapiro	/* scan the list of IP address */
490664565Sgshapiro	if (tTd(0, 40))
490790795Sgshapiro		sm_dprintf("scanning for interface specific names, lifc_len=%ld\n",
490890795Sgshapiro			   (long) len);
490964565Sgshapiro
491090795Sgshapiro	for (i = 0; i < len && i >= 0; )
491164565Sgshapiro	{
491290795Sgshapiro		int flags;
491390795Sgshapiro		struct lifreq *ifr = (struct lifreq *)&buf[i];
491464565Sgshapiro		SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr;
491590795Sgshapiro		int af = ifr->lifr_addr.ss_family;
491664565Sgshapiro		char *addr;
491790795Sgshapiro		char *name;
491864565Sgshapiro		struct in6_addr ia6;
491964565Sgshapiro		struct in_addr ia;
492090795Sgshapiro#  ifdef SIOCGLIFFLAGS
492164565Sgshapiro		struct lifreq ifrf;
4922363466Sgshapiro#  endif
492364565Sgshapiro		char ip_addr[256];
492464565Sgshapiro		char buf6[INET6_ADDRSTRLEN];
492564565Sgshapiro
492664565Sgshapiro		/*
492764565Sgshapiro		**  We must close and recreate the socket each time
492864565Sgshapiro		**  since we don't know what type of socket it is now
492964565Sgshapiro		**  (each status function may change it).
493064565Sgshapiro		*/
493164565Sgshapiro
493264565Sgshapiro		(void) close(s);
493364565Sgshapiro
493464565Sgshapiro		s = socket(af, SOCK_DGRAM, 0);
493564565Sgshapiro		if (s == -1)
493671348Sgshapiro		{
493790795Sgshapiro			sm_free(buf); /* XXX */
493864565Sgshapiro			return;
493971348Sgshapiro		}
494064565Sgshapiro
494164565Sgshapiro		/*
494264565Sgshapiro		**  If we don't have a complete ifr structure,
494364565Sgshapiro		**  don't try to use it.
494464565Sgshapiro		*/
494564565Sgshapiro
4946168520Sgshapiro		if ((len - i) < sizeof(*ifr))
494764565Sgshapiro			break;
494864565Sgshapiro
494990795Sgshapiro#  ifdef BSD4_4_SOCKADDR
4950168520Sgshapiro		if (sa->sa.sa_len > sizeof(ifr->lifr_addr))
4951168520Sgshapiro			i += sizeof(ifr->lifr_name) + sa->sa.sa_len;
495264565Sgshapiro		else
495390795Sgshapiro#  endif /* BSD4_4_SOCKADDR */
4954157006Sgshapiro#  ifdef DEC
4955157006Sgshapiro			/* fix for IPv6  size differences */
4956168520Sgshapiro			i += sizeof(ifr->ifr_name) +
4957157006Sgshapiro			     max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
4958157006Sgshapiro#   else /* DEC */
4959168520Sgshapiro			i += sizeof(*ifr);
4960157006Sgshapiro#   endif /* DEC */
496164565Sgshapiro
496264565Sgshapiro		if (tTd(0, 20))
496390795Sgshapiro			sm_dprintf("%s\n", anynet_ntoa(sa));
496464565Sgshapiro
496564565Sgshapiro		if (af != AF_INET && af != AF_INET6)
496664565Sgshapiro			continue;
496764565Sgshapiro
496890795Sgshapiro#  ifdef SIOCGLIFFLAGS
496964565Sgshapiro		memset(&ifrf, '\0', sizeof(struct lifreq));
497090795Sgshapiro		(void) sm_strlcpy(ifrf.lifr_name, ifr->lifr_name,
497190795Sgshapiro				  sizeof(ifrf.lifr_name));
497264565Sgshapiro		if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0)
497364565Sgshapiro		{
497464565Sgshapiro			if (tTd(0, 4))
497590795Sgshapiro				sm_dprintf("SIOCGLIFFLAGS failed: %s\n",
497690795Sgshapiro					   sm_errstring(errno));
497764565Sgshapiro			continue;
497864565Sgshapiro		}
497964565Sgshapiro
498090795Sgshapiro		name = ifr->lifr_name;
498190795Sgshapiro		flags = ifrf.lifr_flags;
498290795Sgshapiro
498390795Sgshapiro		if (tTd(0, 41))
498490795Sgshapiro			sm_dprintf("\tflags: %lx\n", (unsigned long) flags);
498590795Sgshapiro
498690795Sgshapiro		if (!bitset(IFF_UP, flags))
498764565Sgshapiro			continue;
498890795Sgshapiro#  endif /* SIOCGLIFFLAGS */
498964565Sgshapiro
499064565Sgshapiro		ip_addr[0] = '\0';
499164565Sgshapiro
499264565Sgshapiro		/* extract IP address from the list*/
499364565Sgshapiro		switch (af)
499464565Sgshapiro		{
499564565Sgshapiro		  case AF_INET6:
4996223067Sgshapiro			SETV6LOOPBACKADDRFOUND(*sa);
499773191Sgshapiro#  ifdef __KAME__
499873191Sgshapiro			/* convert into proper scoped address */
499973191Sgshapiro			if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) ||
500073191Sgshapiro			     IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) &&
500171348Sgshapiro			    sa->sin6.sin6_scope_id == 0)
500264565Sgshapiro			{
500373191Sgshapiro				struct in6_addr *ia6p;
500473191Sgshapiro
500573191Sgshapiro				ia6p = &sa->sin6.sin6_addr;
500673191Sgshapiro				sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] |
500773191Sgshapiro							       ((unsigned int)ia6p->s6_addr[2] << 8));
500873191Sgshapiro				ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0;
500971348Sgshapiro			}
501073191Sgshapiro#  endif /* __KAME__ */
501173191Sgshapiro			ia6 = sa->sin6.sin6_addr;
501271348Sgshapiro			if (IN6_IS_ADDR_UNSPECIFIED(&ia6))
501371348Sgshapiro			{
5014168520Sgshapiro				addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
501564565Sgshapiro				message("WARNING: interface %s is UP with %s address",
501690795Sgshapiro					name, addr == NULL ? "(NULL)" : addr);
501764565Sgshapiro				continue;
501864565Sgshapiro			}
501964565Sgshapiro
502064565Sgshapiro			/* save IP address in text from */
5021168520Sgshapiro			addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
502264565Sgshapiro			if (addr != NULL)
5023168520Sgshapiro				(void) sm_snprintf(ip_addr, sizeof(ip_addr),
502490795Sgshapiro						   "[%.*s]",
5025168520Sgshapiro						   (int) sizeof(ip_addr) - 3,
502690795Sgshapiro						   addr);
502764565Sgshapiro			break;
502864565Sgshapiro
502964565Sgshapiro		  case AF_INET:
503064565Sgshapiro			ia = sa->sin.sin_addr;
503164565Sgshapiro			if (ia.s_addr == INADDR_ANY ||
503264565Sgshapiro			    ia.s_addr == INADDR_NONE)
503364565Sgshapiro			{
503464565Sgshapiro				message("WARNING: interface %s is UP with %s address",
503590795Sgshapiro					name, inet_ntoa(ia));
503664565Sgshapiro				continue;
503764565Sgshapiro			}
503864565Sgshapiro
503964565Sgshapiro			/* save IP address in text from */
5040168520Sgshapiro			(void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]",
5041168520Sgshapiro					(int) sizeof(ip_addr) - 3, inet_ntoa(ia));
504264565Sgshapiro			break;
504364565Sgshapiro		}
504464565Sgshapiro
504564565Sgshapiro		if (*ip_addr == '\0')
504664565Sgshapiro			continue;
504764565Sgshapiro
504864565Sgshapiro		if (!wordinclass(ip_addr, 'w'))
504964565Sgshapiro		{
505064565Sgshapiro			setclass('w', ip_addr);
505164565Sgshapiro			if (tTd(0, 4))
505290795Sgshapiro				sm_dprintf("\ta.k.a.: %s\n", ip_addr);
505364565Sgshapiro		}
505464565Sgshapiro
505590795Sgshapiro#  ifdef SIOCGLIFFLAGS
505664565Sgshapiro		/* skip "loopback" interface "lo" */
505790795Sgshapiro		if (DontProbeInterfaces == DPI_SKIPLOOPBACK &&
505890795Sgshapiro		    bitset(IFF_LOOPBACK, flags))
505964565Sgshapiro			continue;
506090795Sgshapiro#  endif /* SIOCGLIFFLAGS */
506164565Sgshapiro		(void) add_hostnames(sa);
506264565Sgshapiro	}
506390795Sgshapiro	sm_free(buf); /* XXX */
506471348Sgshapiro	(void) close(s);
506590795Sgshapiro# else /* NETINET6 && defined(SIOCGLIFCONF) */
506690795Sgshapiro#  if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
506764565Sgshapiro	int s;
506864565Sgshapiro	int i;
506938032Speter	struct ifconf ifc;
507038032Speter	int numifs;
507138032Speter
507238032Speter	s = socket(AF_INET, SOCK_DGRAM, 0);
507338032Speter	if (s == -1)
507438032Speter		return;
507538032Speter
507638032Speter	/* get the list of known IP address from the kernel */
507790795Sgshapiro#   if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN
507838032Speter	if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0)
507938032Speter	{
508038032Speter		/* can't get number of interfaces -- fall back */
508138032Speter		if (tTd(0, 4))
508290795Sgshapiro			sm_dprintf("SIOCGIFNUM failed: %s\n",
508390795Sgshapiro				   sm_errstring(errno));
508438032Speter		numifs = -1;
508538032Speter	}
508638032Speter	else if (tTd(0, 42))
508790795Sgshapiro		sm_dprintf("system has %d interfaces\n", numifs);
508838032Speter	if (numifs < 0)
508990795Sgshapiro#   endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */
509064565Sgshapiro		numifs = MAXINTERFACES;
509138032Speter
509238032Speter	if (numifs <= 0)
509338032Speter	{
509464565Sgshapiro		(void) close(s);
509538032Speter		return;
509638032Speter	}
5097168520Sgshapiro	ifc.ifc_len = numifs * sizeof(struct ifreq);
509838032Speter	ifc.ifc_buf = xalloc(ifc.ifc_len);
509938032Speter	if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
510038032Speter	{
510138032Speter		if (tTd(0, 4))
510290795Sgshapiro			sm_dprintf("SIOCGIFCONF failed: %s\n",
510390795Sgshapiro				   sm_errstring(errno));
510464565Sgshapiro		(void) close(s);
510538032Speter		return;
510638032Speter	}
510738032Speter
510838032Speter	/* scan the list of IP address */
510938032Speter	if (tTd(0, 40))
511090795Sgshapiro		sm_dprintf("scanning for interface specific names, ifc_len=%d\n",
511138032Speter			ifc.ifc_len);
511238032Speter
511390795Sgshapiro	for (i = 0; i < ifc.ifc_len && i >= 0; )
511438032Speter	{
511564565Sgshapiro		int af;
511638032Speter		struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i];
511742580Speter		SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr;
511864565Sgshapiro#   if NETINET6
511964565Sgshapiro		char *addr;
512064565Sgshapiro		struct in6_addr ia6;
5121363466Sgshapiro#   endif
512238032Speter		struct in_addr ia;
512364565Sgshapiro#   ifdef SIOCGIFFLAGS
512438032Speter		struct ifreq ifrf;
5125363466Sgshapiro#   endif
512638032Speter		char ip_addr[256];
512764565Sgshapiro#   if NETINET6
512864565Sgshapiro		char buf6[INET6_ADDRSTRLEN];
5129363466Sgshapiro#   endif
513038032Speter
513164565Sgshapiro		/*
513264565Sgshapiro		**  If we don't have a complete ifr structure,
513364565Sgshapiro		**  don't try to use it.
513464565Sgshapiro		*/
513564565Sgshapiro
5136168520Sgshapiro		if ((ifc.ifc_len - i) < sizeof(*ifr))
513764565Sgshapiro			break;
513864565Sgshapiro
513964565Sgshapiro#   ifdef BSD4_4_SOCKADDR
5140168520Sgshapiro		if (sa->sa.sa_len > sizeof(ifr->ifr_addr))
5141168520Sgshapiro			i += sizeof(ifr->ifr_name) + sa->sa.sa_len;
514238032Speter		else
514364565Sgshapiro#   endif /* BSD4_4_SOCKADDR */
5144168520Sgshapiro			i += sizeof(*ifr);
514538032Speter
514638032Speter		if (tTd(0, 20))
514790795Sgshapiro			sm_dprintf("%s\n", anynet_ntoa(sa));
514838032Speter
514964565Sgshapiro		af = ifr->ifr_addr.sa_family;
515064565Sgshapiro		if (af != AF_INET
515164565Sgshapiro#   if NETINET6
515264565Sgshapiro		    && af != AF_INET6
5153363466Sgshapiro#   endif
515464565Sgshapiro		    )
515538032Speter			continue;
515638032Speter
515764565Sgshapiro#   ifdef SIOCGIFFLAGS
515864565Sgshapiro		memset(&ifrf, '\0', sizeof(struct ifreq));
515990795Sgshapiro		(void) sm_strlcpy(ifrf.ifr_name, ifr->ifr_name,
516064565Sgshapiro			       sizeof(ifrf.ifr_name));
516164565Sgshapiro		(void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
516238032Speter		if (tTd(0, 41))
516390795Sgshapiro			sm_dprintf("\tflags: %lx\n",
516464565Sgshapiro				(unsigned long) ifrf.ifr_flags);
516564565Sgshapiro#    define IFRFREF ifrf
516664565Sgshapiro#   else /* SIOCGIFFLAGS */
516764565Sgshapiro#    define IFRFREF (*ifr)
516864565Sgshapiro#   endif /* SIOCGIFFLAGS */
516964565Sgshapiro
517038032Speter		if (!bitset(IFF_UP, IFRFREF.ifr_flags))
517138032Speter			continue;
517238032Speter
517364565Sgshapiro		ip_addr[0] = '\0';
517464565Sgshapiro
517538032Speter		/* extract IP address from the list*/
517664565Sgshapiro		switch (af)
517738032Speter		{
517864565Sgshapiro		  case AF_INET:
517964565Sgshapiro			ia = sa->sin.sin_addr;
518064565Sgshapiro			if (ia.s_addr == INADDR_ANY ||
518164565Sgshapiro			    ia.s_addr == INADDR_NONE)
518264565Sgshapiro			{
518364565Sgshapiro				message("WARNING: interface %s is UP with %s address",
518464565Sgshapiro					ifr->ifr_name, inet_ntoa(ia));
518564565Sgshapiro				continue;
518664565Sgshapiro			}
518764565Sgshapiro
518864565Sgshapiro			/* save IP address in text from */
5189168520Sgshapiro			(void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]",
5190168520Sgshapiro					(int) sizeof(ip_addr) - 3,
519164565Sgshapiro					inet_ntoa(ia));
519264565Sgshapiro			break;
519364565Sgshapiro
519464565Sgshapiro#   if NETINET6
519564565Sgshapiro		  case AF_INET6:
5196223067Sgshapiro			SETV6LOOPBACKADDRFOUND(*sa);
519773191Sgshapiro#    ifdef __KAME__
519873191Sgshapiro			/* convert into proper scoped address */
519973191Sgshapiro			if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) ||
520073191Sgshapiro			     IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) &&
520173191Sgshapiro			    sa->sin6.sin6_scope_id == 0)
520273191Sgshapiro			{
520373191Sgshapiro				struct in6_addr *ia6p;
520473191Sgshapiro
520573191Sgshapiro				ia6p = &sa->sin6.sin6_addr;
520673191Sgshapiro				sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] |
520773191Sgshapiro							       ((unsigned int)ia6p->s6_addr[2] << 8));
520873191Sgshapiro				ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0;
520973191Sgshapiro			}
521073191Sgshapiro#    endif /* __KAME__ */
521164565Sgshapiro			ia6 = sa->sin6.sin6_addr;
521271348Sgshapiro			if (IN6_IS_ADDR_UNSPECIFIED(&ia6))
521364565Sgshapiro			{
5214168520Sgshapiro				addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
521564565Sgshapiro				message("WARNING: interface %s is UP with %s address",
521664565Sgshapiro					ifr->ifr_name,
521764565Sgshapiro					addr == NULL ? "(NULL)" : addr);
521864565Sgshapiro				continue;
521964565Sgshapiro			}
522064565Sgshapiro
522164565Sgshapiro			/* save IP address in text from */
5222168520Sgshapiro			addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
522364565Sgshapiro			if (addr != NULL)
5224168520Sgshapiro				(void) sm_snprintf(ip_addr, sizeof(ip_addr),
522590795Sgshapiro						   "[%.*s]",
5226168520Sgshapiro						   (int) sizeof(ip_addr) - 3,
522790795Sgshapiro						   addr);
522864565Sgshapiro			break;
522964565Sgshapiro
523064565Sgshapiro#   endif /* NETINET6 */
523138032Speter		}
523238032Speter
523364565Sgshapiro		if (ip_addr[0] == '\0')
523464565Sgshapiro			continue;
523564565Sgshapiro
523638032Speter		if (!wordinclass(ip_addr, 'w'))
523738032Speter		{
523838032Speter			setclass('w', ip_addr);
523938032Speter			if (tTd(0, 4))
524090795Sgshapiro				sm_dprintf("\ta.k.a.: %s\n", ip_addr);
524138032Speter		}
524238032Speter
524338032Speter		/* skip "loopback" interface "lo" */
524490795Sgshapiro		if (DontProbeInterfaces == DPI_SKIPLOOPBACK &&
524590795Sgshapiro		    bitset(IFF_LOOPBACK, IFRFREF.ifr_flags))
524638032Speter			continue;
524738032Speter
524842580Speter		(void) add_hostnames(sa);
524938032Speter	}
525090795Sgshapiro	sm_free(ifc.ifc_buf); /* XXX */
525164565Sgshapiro	(void) close(s);
525290795Sgshapiro#   undef IFRFREF
525390795Sgshapiro#  endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
525490795Sgshapiro# endif /* NETINET6 && defined(SIOCGLIFCONF) */
525538032Speter}
525690795Sgshapiro/*
525764565Sgshapiro**  ISLOOPBACK -- is socket address in the loopback net?
525864565Sgshapiro**
525964565Sgshapiro**	Parameters:
526064565Sgshapiro**		sa -- socket address.
526164565Sgshapiro**
526264565Sgshapiro**	Returns:
526390795Sgshapiro**		true -- is socket address in the loopback net?
526490795Sgshapiro**		false -- otherwise
526564565Sgshapiro**
526664565Sgshapiro*/
526764565Sgshapiro
526864565Sgshapirobool
526964565Sgshapiroisloopback(sa)
527064565Sgshapiro	SOCKADDR sa;
527164565Sgshapiro{
527264565Sgshapiro	/* XXX how to correctly extract IN_LOOPBACKNET part? */
5273363466Sgshapiro#define SM_IS_IPV4_LOOP(a) (((ntohl(a) & IN_CLASSA_NET) \
527464565Sgshapiro	     >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
5275363466Sgshapiro#if NETINET6
5276363466Sgshapiro	if (sa.sa.sa_family == AF_INET6 &&
5277363466Sgshapiro	    IN6_IS_ADDR_V4MAPPED(&sa.sin6.sin6_addr) &&
5278363466Sgshapiro	    SM_IS_IPV4_LOOP(((uint32_t *) (&sa.sin6.sin6_addr))[3]))
527990795Sgshapiro		return true;
5280363466Sgshapiro	if (sa.sa.sa_family == AF_INET6 &&
5281363466Sgshapiro	    IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr))
5282363466Sgshapiro		return true;
5283363466Sgshapiro#endif
5284363466Sgshapiro#if NETINET
5285363466Sgshapiro	if (sa.sa.sa_family == AF_INET &&
5286363466Sgshapiro	    SM_IS_IPV4_LOOP(sa.sin.sin_addr.s_addr))
5287363466Sgshapiro		return true;
5288363466Sgshapiro#endif
528990795Sgshapiro	return false;
529064565Sgshapiro}
5291363466Sgshapiro
529290795Sgshapiro/*
529338032Speter**  GET_NUM_PROCS_ONLINE -- return the number of processors currently online
529438032Speter**
529538032Speter**	Parameters:
529638032Speter**		none.
529738032Speter**
529838032Speter**	Returns:
529938032Speter**		The number of processors online.
530038032Speter*/
530138032Speter
530264565Sgshapirostatic int
530338032Speterget_num_procs_online()
530438032Speter{
530538032Speter	int nproc = 0;
530638032Speter
530764565Sgshapiro#ifdef USESYSCTL
530864565Sgshapiro# if defined(CTL_HW) && defined(HW_NCPU)
530964565Sgshapiro	size_t sz;
531064565Sgshapiro	int mib[2];
531164565Sgshapiro
531264565Sgshapiro	mib[0] = CTL_HW;
531364565Sgshapiro	mib[1] = HW_NCPU;
5314168520Sgshapiro	sz = (size_t) sizeof(nproc);
531564565Sgshapiro	(void) sysctl(mib, 2, &nproc, &sz, NULL, 0);
531690795Sgshapiro# endif /* defined(CTL_HW) && defined(HW_NCPU) */
531764565Sgshapiro#else /* USESYSCTL */
531864565Sgshapiro# ifdef _SC_NPROCESSORS_ONLN
531938032Speter	nproc = (int) sysconf(_SC_NPROCESSORS_ONLN);
532064565Sgshapiro# else /* _SC_NPROCESSORS_ONLN */
532164565Sgshapiro#  ifdef __hpux
532264565Sgshapiro#   include <sys/pstat.h>
532364565Sgshapiro	struct pst_dynamic psd;
532464565Sgshapiro
532564565Sgshapiro	if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1)
532664565Sgshapiro		nproc = psd.psd_proc_cnt;
532764565Sgshapiro#  endif /* __hpux */
532864565Sgshapiro# endif /* _SC_NPROCESSORS_ONLN */
532964565Sgshapiro#endif /* USESYSCTL */
533064565Sgshapiro
533138032Speter	if (nproc <= 0)
533238032Speter		nproc = 1;
533338032Speter	return nproc;
533438032Speter}
533590795Sgshapiro/*
5336132946Sgshapiro**  SM_CLOSEFROM -- close file descriptors
5337132946Sgshapiro**
5338132946Sgshapiro**	Parameters:
5339132946Sgshapiro**		lowest -- first fd to close
5340132946Sgshapiro**		highest -- last fd + 1 to close
5341132946Sgshapiro**
5342132946Sgshapiro**	Returns:
5343132946Sgshapiro**		none
5344132946Sgshapiro*/
5345132946Sgshapiro
5346132946Sgshapirovoid
5347132946Sgshapirosm_closefrom(lowest, highest)
5348132946Sgshapiro	int lowest, highest;
5349132946Sgshapiro{
5350132946Sgshapiro#if HASCLOSEFROM
5351132946Sgshapiro	closefrom(lowest);
5352132946Sgshapiro#else /* HASCLOSEFROM */
5353132946Sgshapiro	int i;
5354132946Sgshapiro
5355132946Sgshapiro	for (i = lowest; i < highest; i++)
5356132946Sgshapiro		(void) close(i);
5357132946Sgshapiro#endif /* HASCLOSEFROM */
5358132946Sgshapiro}
5359132946Sgshapiro#if HASFDWALK
5360132946Sgshapiro/*
5361132946Sgshapiro**  CLOSEFD_WALK -- walk fd's arranging to close them
5362132946Sgshapiro**	Callback for fdwalk()
5363132946Sgshapiro**
5364132946Sgshapiro**	Parameters:
5365132946Sgshapiro**		lowest -- first fd to arrange to be closed
5366132946Sgshapiro**		fd -- fd to arrange to be closed
5367132946Sgshapiro**
5368132946Sgshapiro**	Returns:
5369132946Sgshapiro**		zero
5370132946Sgshapiro*/
5371132946Sgshapiro
5372132946Sgshapirostatic int
5373132946Sgshapiroclosefd_walk(lowest, fd)
5374132946Sgshapiro	void *lowest;
5375132946Sgshapiro	int fd;
5376132946Sgshapiro{
5377132946Sgshapiro	if (fd >= *(int *)lowest)
5378132946Sgshapiro		(void) fcntl(fd, F_SETFD, FD_CLOEXEC);
5379132946Sgshapiro	return 0;
5380132946Sgshapiro}
5381132946Sgshapiro#endif /* HASFDWALK */
5382132946Sgshapiro/*
5383132946Sgshapiro**  SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed
5384132946Sgshapiro**
5385132946Sgshapiro**	Parameters:
5386132946Sgshapiro**		lowest -- first fd to arrange to be closed
5387132946Sgshapiro**		highest -- last fd + 1 to arrange to be closed
5388132946Sgshapiro**
5389132946Sgshapiro**	Returns:
5390132946Sgshapiro**		none
5391132946Sgshapiro*/
5392132946Sgshapiro
5393132946Sgshapirovoid
5394266527Sgshapirosm_close_on_exec(lowest, highest)
5395266527Sgshapiro	int lowest, highest;
5396132946Sgshapiro{
5397132946Sgshapiro#if HASFDWALK
5398132946Sgshapiro	(void) fdwalk(closefd_walk, &lowest);
5399132946Sgshapiro#else /* HASFDWALK */
5400132946Sgshapiro	int i, j;
5401132946Sgshapiro
5402132946Sgshapiro	for (i = lowest; i < highest; i++)
5403132946Sgshapiro	{
5404132946Sgshapiro		if ((j = fcntl(i, F_GETFD, 0)) != -1)
5405132946Sgshapiro			(void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
5406132946Sgshapiro	}
5407132946Sgshapiro#endif /* HASFDWALK */
5408132946Sgshapiro}
5409132946Sgshapiro/*
541064565Sgshapiro**  SEED_RANDOM -- seed the random number generator
541164565Sgshapiro**
541264565Sgshapiro**	Parameters:
541364565Sgshapiro**		none
541464565Sgshapiro**
541564565Sgshapiro**	Returns:
541664565Sgshapiro**		none
541764565Sgshapiro*/
541864565Sgshapiro
541964565Sgshapirovoid
542064565Sgshapiroseed_random()
542164565Sgshapiro{
542264565Sgshapiro#if HASSRANDOMDEV
542364565Sgshapiro	srandomdev();
542464565Sgshapiro#else /* HASSRANDOMDEV */
542564565Sgshapiro	long seed;
542664565Sgshapiro	struct timeval t;
542764565Sgshapiro
542890795Sgshapiro	seed = (long) CurrentPid;
542964565Sgshapiro	if (gettimeofday(&t, NULL) >= 0)
543064565Sgshapiro		seed += t.tv_sec + t.tv_usec;
543164565Sgshapiro
543264565Sgshapiro# if HASRANDOM
543364565Sgshapiro	(void) srandom(seed);
5434363466Sgshapiro# else
543564565Sgshapiro	(void) srand((unsigned int) seed);
5436363466Sgshapiro# endif
543764565Sgshapiro#endif /* HASSRANDOMDEV */
543864565Sgshapiro}
543990795Sgshapiro/*
544038032Speter**  SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE
544138032Speter**
544238032Speter**	Parameters:
544338032Speter**		level -- syslog level
544438032Speter**		id -- envelope ID or NULL (NOQUEUE)
544538032Speter**		fmt -- format string
544638032Speter**		arg... -- arguments as implied by fmt.
544738032Speter**
544838032Speter**	Returns:
544938032Speter**		none
545038032Speter*/
545138032Speter
545238032Speter/* VARARGS3 */
545338032Spetervoid
545464565Sgshapiro#ifdef __STDC__
545538032Spetersm_syslog(int level, const char *id, const char *fmt, ...)
545664565Sgshapiro#else /* __STDC__ */
545738032Spetersm_syslog(level, id, fmt, va_alist)
545838032Speter	int level;
545938032Speter	const char *id;
546038032Speter	const char *fmt;
546138032Speter	va_dcl
546264565Sgshapiro#endif /* __STDC__ */
546338032Speter{
5464157006Sgshapiro	char *buf;
5465157006Sgshapiro	size_t bufsize;
546638032Speter	char *begin, *end;
546764565Sgshapiro	int save_errno;
546838032Speter	int seq = 1;
546938032Speter	int idlen;
547064565Sgshapiro	char buf0[MAXLINE];
547190795Sgshapiro	char *newstring;
547290795Sgshapiro	extern int SyslogPrefixLen;
547390795Sgshapiro	SM_VA_LOCAL_DECL
547464565Sgshapiro
547590795Sgshapiro	save_errno = errno;
547638032Speter	if (id == NULL)
547738032Speter		id = "NOQUEUE";
5478173343Sgshapiro	idlen = strlen(id) + SyslogPrefixLen;
547964565Sgshapiro
5480157006Sgshapiro	buf = buf0;
5481168520Sgshapiro	bufsize = sizeof(buf0);
548238032Speter
548364565Sgshapiro	for (;;)
548464565Sgshapiro	{
548590795Sgshapiro		int n;
548638032Speter
548790795Sgshapiro		/* print log message into buf */
548890795Sgshapiro		SM_VA_START(ap, fmt);
548990795Sgshapiro		n = sm_vsnprintf(buf, bufsize, fmt, ap);
549090795Sgshapiro		SM_VA_END(ap);
5491285229Sgshapiro		SM_ASSERT(n >= 0);
549290795Sgshapiro		if (n < bufsize)
549364565Sgshapiro			break;
549464565Sgshapiro
549538032Speter		/* String too small, redo with correct size */
549690795Sgshapiro		bufsize = n + 1;
549764565Sgshapiro		if (buf != buf0)
549890795Sgshapiro		{
549977352Sgshapiro			sm_free(buf);
550090795Sgshapiro			buf = NULL;
550190795Sgshapiro		}
550290795Sgshapiro		buf = sm_malloc_x(bufsize);
550338032Speter	}
550490795Sgshapiro
550590795Sgshapiro	/* clean up buf after it has been expanded with args */
550690795Sgshapiro	newstring = str2prt(buf);
550790795Sgshapiro	if ((strlen(newstring) + idlen + 1) < SYSLOG_BUFSIZE)
550838032Speter	{
550938032Speter#if LOG
551038032Speter		if (*id == '\0')
5511168520Sgshapiro		{
5512244833Sgshapiro			if (tTd(89, 10))
5513244833Sgshapiro			{
5514244833Sgshapiro				struct timeval tv;
5515244833Sgshapiro
5516244833Sgshapiro				gettimeofday(&tv, NULL);
5517244833Sgshapiro				sm_dprintf("%ld.%06ld %s\n", (long) tv.tv_sec,
5518244833Sgshapiro					(long) tv.tv_usec, newstring);
5519244833Sgshapiro			}
5520244833Sgshapiro			else if (tTd(89, 8))
5521168520Sgshapiro				sm_dprintf("%s\n", newstring);
5522168520Sgshapiro			else
5523168520Sgshapiro				syslog(level, "%s", newstring);
5524168520Sgshapiro		}
552538032Speter		else
5526168520Sgshapiro		{
5527244833Sgshapiro			if (tTd(89, 10))
5528244833Sgshapiro			{
5529244833Sgshapiro				struct timeval tv;
5530244833Sgshapiro
5531244833Sgshapiro				gettimeofday(&tv, NULL);
5532244833Sgshapiro				sm_dprintf("%ld.%06ld %s: %s\n", (long) tv.tv_sec,
5533244833Sgshapiro					(long) tv.tv_usec, id, newstring);
5534244833Sgshapiro			}
5535244833Sgshapiro			else if (tTd(89, 8))
5536168520Sgshapiro				sm_dprintf("%s: %s\n", id, newstring);
5537168520Sgshapiro			else
5538168520Sgshapiro				syslog(level, "%s: %s", id, newstring);
5539168520Sgshapiro		}
554064565Sgshapiro#else /* LOG */
554138032Speter		/*XXX should do something more sensible */
554238032Speter		if (*id == '\0')
554390795Sgshapiro			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n",
554490795Sgshapiro					     newstring);
554538032Speter		else
554690795Sgshapiro			(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
554790795Sgshapiro					     "%s: %s\n", id, newstring);
554864565Sgshapiro#endif /* LOG */
5549157006Sgshapiro		if (buf != buf0)
5550157006Sgshapiro			sm_free(buf);
555164565Sgshapiro		errno = save_errno;
555238032Speter		return;
555338032Speter	}
555438032Speter
555590795Sgshapiro/*
555690795Sgshapiro**  additional length for splitting: " ..." + 3, where 3 is magic to
555790795Sgshapiro**  have some data for the next entry.
555890795Sgshapiro*/
555990795Sgshapiro
556090795Sgshapiro#define SL_SPLIT 7
556190795Sgshapiro
556290795Sgshapiro	begin = newstring;
556390795Sgshapiro	idlen += 5;	/* strlen("[999]"), see below */
556438032Speter	while (*begin != '\0' &&
556590795Sgshapiro	       (strlen(begin) + idlen) > SYSLOG_BUFSIZE)
556638032Speter	{
556738032Speter		char save;
556864565Sgshapiro
556990795Sgshapiro		if (seq >= 999)
557038032Speter		{
557138032Speter			/* Too many messages */
557238032Speter			break;
557338032Speter		}
557490795Sgshapiro		end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT;
557538032Speter		while (end > begin)
557638032Speter		{
557738032Speter			/* Break on comma or space */
557838032Speter			if (*end == ',' || *end == ' ')
557938032Speter			{
558038032Speter				end++;	  /* Include separator */
558138032Speter				break;
558238032Speter			}
558338032Speter			end--;
558438032Speter		}
558538032Speter		/* No separator, break midstring... */
558638032Speter		if (end == begin)
558790795Sgshapiro			end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT;
558838032Speter		save = *end;
558938032Speter		*end = 0;
559038032Speter#if LOG
5591168520Sgshapiro		if (tTd(89, 8))
5592168520Sgshapiro			sm_dprintf("%s[%d]: %s ...\n", id, seq++, begin);
5593168520Sgshapiro		else
5594168520Sgshapiro			syslog(level, "%s[%d]: %s ...", id, seq++, begin);
559564565Sgshapiro#else /* LOG */
559690795Sgshapiro		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
559790795Sgshapiro				     "%s[%d]: %s ...\n", id, seq++, begin);
559864565Sgshapiro#endif /* LOG */
559938032Speter		*end = save;
560038032Speter		begin = end;
560138032Speter	}
560290795Sgshapiro	if (seq >= 999)
5603168520Sgshapiro	{
560438032Speter#if LOG
5605168520Sgshapiro		if (tTd(89, 8))
5606168520Sgshapiro			sm_dprintf("%s[%d]: log terminated, too many parts\n",
5607168520Sgshapiro				id, seq);
5608168520Sgshapiro		else
5609168520Sgshapiro			syslog(level, "%s[%d]: log terminated, too many parts",
5610168520Sgshapiro				id, seq);
561164565Sgshapiro#else /* LOG */
561290795Sgshapiro		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
561390795Sgshapiro			      "%s[%d]: log terminated, too many parts\n", id, seq);
561464565Sgshapiro#endif /* LOG */
5615168520Sgshapiro	}
561638032Speter	else if (*begin != '\0')
5617168520Sgshapiro	{
561838032Speter#if LOG
5619168520Sgshapiro		if (tTd(89, 8))
5620168520Sgshapiro			sm_dprintf("%s[%d]: %s\n", id, seq, begin);
5621168520Sgshapiro		else
5622168520Sgshapiro			syslog(level, "%s[%d]: %s", id, seq, begin);
562364565Sgshapiro#else /* LOG */
562490795Sgshapiro		(void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
562590795Sgshapiro				     "%s[%d]: %s\n", id, seq, begin);
562664565Sgshapiro#endif /* LOG */
5627168520Sgshapiro	}
5628157006Sgshapiro	if (buf != buf0)
5629157006Sgshapiro		sm_free(buf);
563064565Sgshapiro	errno = save_errno;
563138032Speter}
563290795Sgshapiro/*
563338032Speter**  HARD_SYSLOG -- call syslog repeatedly until it works
563438032Speter**
563538032Speter**	Needed on HP-UX, which apparently doesn't guarantee that
563638032Speter**	syslog succeeds during interrupt handlers.
563738032Speter*/
563838032Speter
563938032Speter#if defined(__hpux) && !defined(HPUX11)
564038032Speter
564138032Speter# define MAXSYSLOGTRIES	100
564238032Speter# undef syslog
564338032Speter# ifdef V4FS
564438032Speter#  define XCNST	const
564538032Speter#  define CAST	(const char *)
5646363466Sgshapiro# else
564738032Speter#  define XCNST
564838032Speter#  define CAST
5649363466Sgshapiro# endif
565038032Speter
565138032Spetervoid
565238032Speter# ifdef __STDC__
565338032Speterhard_syslog(int pri, XCNST char *msg, ...)
565464565Sgshapiro# else /* __STDC__ */
565538032Speterhard_syslog(pri, msg, va_alist)
565638032Speter	int pri;
565738032Speter	XCNST char *msg;
565838032Speter	va_dcl
565964565Sgshapiro# endif /* __STDC__ */
566038032Speter{
566138032Speter	int i;
566238032Speter	char buf[SYSLOG_BUFSIZE];
566390795Sgshapiro	SM_VA_LOCAL_DECL
566438032Speter
566590795Sgshapiro	SM_VA_START(ap, msg);
5666168520Sgshapiro	(void) sm_vsnprintf(buf, sizeof(buf), msg, ap);
566790795Sgshapiro	SM_VA_END(ap);
566838032Speter
566938032Speter	for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; )
567038032Speter		continue;
567138032Speter}
567238032Speter
567338032Speter# undef CAST
567464565Sgshapiro#endif /* defined(__hpux) && !defined(HPUX11) */
567564565Sgshapiro#if NEEDLOCAL_HOSTNAME_LENGTH
567690795Sgshapiro/*
567738032Speter**  LOCAL_HOSTNAME_LENGTH
567838032Speter**
567938032Speter**	This is required to get sendmail to compile against BIND 4.9.x
568038032Speter**	on Ultrix.
568164565Sgshapiro**
568264565Sgshapiro**	Unfortunately, a Compaq Y2K patch kit provides it without
568364565Sgshapiro**	bumping __RES in /usr/include/resolv.h so we can't automatically
568464565Sgshapiro**	figure out whether it is needed.
568538032Speter*/
568638032Speter
568738032Speterint
568838032Speterlocal_hostname_length(hostname)
568938032Speter	char *hostname;
569038032Speter{
569190795Sgshapiro	size_t len_host, len_domain;
569238032Speter
569338032Speter	if (!*_res.defdname)
569438032Speter		res_init();
569538032Speter	len_host = strlen(hostname);
569638032Speter	len_domain = strlen(_res.defdname);
569738032Speter	if (len_host > len_domain &&
569890795Sgshapiro	    (sm_strcasecmp(hostname + len_host - len_domain,
569964565Sgshapiro			_res.defdname) == 0) &&
570038032Speter	    hostname[len_host - len_domain - 1] == '.')
570138032Speter		return len_host - len_domain - 1;
570238032Speter	else
570338032Speter		return 0;
570438032Speter}
570564565Sgshapiro#endif /* NEEDLOCAL_HOSTNAME_LENGTH */
570638032Speter
570790795Sgshapiro#if NEEDLINK
570890795Sgshapiro/*
570990795Sgshapiro**  LINK -- clone a file
571090795Sgshapiro**
571190795Sgshapiro**	Some OS's lacks link() and hard links.  Since sendmail is using
571290795Sgshapiro**	link() as an efficient way to clone files, this implementation
571390795Sgshapiro**	will simply do a file copy.
571490795Sgshapiro**
571590795Sgshapiro**	NOTE: This link() replacement is not a generic replacement as it
571690795Sgshapiro**	does not handle all of the semantics of the real link(2).
571790795Sgshapiro**
571890795Sgshapiro**	Parameters:
571990795Sgshapiro**		source -- pathname of existing file.
572090795Sgshapiro**		target -- pathname of link (clone) to be created.
572190795Sgshapiro**
572290795Sgshapiro**	Returns:
572390795Sgshapiro**		0 -- success.
572490795Sgshapiro**		-1 -- failure, see errno for details.
572590795Sgshapiro*/
572690795Sgshapiro
572790795Sgshapiroint
572890795Sgshapirolink(source, target)
572990795Sgshapiro	const char *source;
573090795Sgshapiro	const char *target;
573190795Sgshapiro{
573290795Sgshapiro	int save_errno;
573390795Sgshapiro	int sff;
573490795Sgshapiro	int src = -1, dst = -1;
573590795Sgshapiro	ssize_t readlen;
573690795Sgshapiro	ssize_t writelen;
573790795Sgshapiro	char buf[BUFSIZ];
573890795Sgshapiro	struct stat st;
573990795Sgshapiro
574090795Sgshapiro	sff = SFF_REGONLY|SFF_OPENASROOT;
574190795Sgshapiro	if (DontLockReadFiles)
574290795Sgshapiro		sff |= SFF_NOLOCK;
574390795Sgshapiro
574490795Sgshapiro	/* Open the original file */
574590795Sgshapiro	src = safeopen((char *)source, O_RDONLY, 0, sff);
574690795Sgshapiro	if (src < 0)
574790795Sgshapiro		goto fail;
574890795Sgshapiro
574990795Sgshapiro	/* Obtain the size and the mode */
575090795Sgshapiro	if (fstat(src, &st) < 0)
575190795Sgshapiro		goto fail;
575290795Sgshapiro
575390795Sgshapiro	/* Create the duplicate copy */
575490795Sgshapiro	sff &= ~SFF_NOLOCK;
575590795Sgshapiro	sff |= SFF_CREAT;
575690795Sgshapiro	dst = safeopen((char *)target, O_CREAT|O_EXCL|O_WRONLY,
575790795Sgshapiro		       st.st_mode, sff);
575890795Sgshapiro	if (dst < 0)
575990795Sgshapiro		goto fail;
576090795Sgshapiro
576190795Sgshapiro	/* Copy all of the bytes one buffer at a time */
576290795Sgshapiro	while ((readlen = read(src, &buf, sizeof(buf))) > 0)
576390795Sgshapiro	{
576490795Sgshapiro		ssize_t left = readlen;
576590795Sgshapiro		char *p = buf;
576690795Sgshapiro
576790795Sgshapiro		while (left > 0 &&
576890795Sgshapiro		       (writelen = write(dst, p, (size_t) left)) >= 0)
576990795Sgshapiro		{
577090795Sgshapiro			left -= writelen;
577190795Sgshapiro			p += writelen;
577290795Sgshapiro		}
577394337Sgshapiro		if (writelen < 0)
577490795Sgshapiro			break;
577590795Sgshapiro	}
577690795Sgshapiro
577790795Sgshapiro	/* Any trouble reading? */
577890795Sgshapiro	if (readlen < 0 || writelen < 0)
577990795Sgshapiro		goto fail;
578090795Sgshapiro
578190795Sgshapiro	/* Close the input file */
578290795Sgshapiro	if (close(src) < 0)
578390795Sgshapiro	{
578490795Sgshapiro		src = -1;
578590795Sgshapiro		goto fail;
578690795Sgshapiro	}
578790795Sgshapiro	src = -1;
578890795Sgshapiro
578990795Sgshapiro	/* Close the output file */
579090795Sgshapiro	if (close(dst) < 0)
579190795Sgshapiro	{
579290795Sgshapiro		/* don't set dst = -1 here so we unlink the file */
579390795Sgshapiro		goto fail;
579490795Sgshapiro	}
579590795Sgshapiro
579690795Sgshapiro	/* Success */
579790795Sgshapiro	return 0;
579890795Sgshapiro
579990795Sgshapiro fail:
580090795Sgshapiro	save_errno = errno;
580190795Sgshapiro	if (src >= 0)
580290795Sgshapiro		(void) close(src);
580390795Sgshapiro	if (dst >= 0)
580490795Sgshapiro	{
580590795Sgshapiro		(void) unlink(target);
580690795Sgshapiro		(void) close(dst);
580790795Sgshapiro	}
580890795Sgshapiro	errno = save_errno;
580990795Sgshapiro	return -1;
581090795Sgshapiro}
581190795Sgshapiro#endif /* NEEDLINK */
581290795Sgshapiro
581390795Sgshapiro/*
581438032Speter**  Compile-Time options
581538032Speter*/
581638032Speter
5817363466Sgshapiro#define SM_STR(x) #x
5818363466Sgshapiro#define SM_XSTR(x) SM_STR(x)
5819363466Sgshapiro
582038032Speterchar	*CompileOptions[] =
582138032Speter{
5822132946Sgshapiro#if ALLOW_255
5823132946Sgshapiro	"ALLOW_255",
5824285229Sgshapiro#endif
5825363466Sgshapiro#if DANE
5826363466Sgshapiro# if STARTTLS
5827363466Sgshapiro	"DANE",
5828363466Sgshapiro# else
5829363466Sgshapiro#  error "DANE set but STARTTLS not defined"
5830363466Sgshapiro# endif
5831363466Sgshapiro#endif
583290795Sgshapiro#if NAMED_BIND
583390795Sgshapiro# if DNSMAP
583490795Sgshapiro	"DNSMAP",
5835285229Sgshapiro# endif
5836285229Sgshapiro#endif
583777352Sgshapiro#if EGD
583877352Sgshapiro	"EGD",
5839285229Sgshapiro#endif
584090795Sgshapiro#if HESIOD
584138032Speter	"HESIOD",
5842285229Sgshapiro#endif
5843285229Sgshapiro#if HESIOD_ALLOW_NUMERIC_LOGIN
5844285229Sgshapiro	"HESIOD_ALLOW_NUMERIC_LOGIN",
5845285229Sgshapiro#endif
584638032Speter#if HES_GETMAILHOST
584738032Speter	"HES_GETMAILHOST",
5848285229Sgshapiro#endif
5849285229Sgshapiro#if IPV6_FULL
5850285229Sgshapiro	/* Use uncompressed IPv6 address format (no "::") by default */
5851285229Sgshapiro	"IPV6_FULL",
5852285229Sgshapiro#endif
585390795Sgshapiro#if LDAPMAP
585438032Speter	"LDAPMAP",
5855285229Sgshapiro#endif
5856363466Sgshapiro#if LDAP_NETWORK_TIMEOUT
5857363466Sgshapiro# if LDAPMAP && defined(LDAP_OPT_NETWORK_TIMEOUT)
5858363466Sgshapiro	/* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */
5859363466Sgshapiro	"LDAP_NETWORK_TIMEOUT",
5860363466Sgshapiro# else
5861363466Sgshapiro#  ERROR: _LDAP_NETWORK_TIMEOUT requires _LDAPMAP
5862363466Sgshapiro# endif
5863363466Sgshapiro#endif
5864157006Sgshapiro#if LDAP_REFERRALS
5865157006Sgshapiro	"LDAP_REFERRALS",
5866285229Sgshapiro#endif
586790795Sgshapiro#if LOG
586890795Sgshapiro	"LOG",
5869285229Sgshapiro#endif
587090795Sgshapiro#if MAP_NSD
587164565Sgshapiro	"MAP_NSD",
5872285229Sgshapiro#endif
587390795Sgshapiro#if MAP_REGEX
587438032Speter	"MAP_REGEX",
5875285229Sgshapiro#endif
587638032Speter#if MATCHGECOS
587738032Speter	"MATCHGECOS",
5878285229Sgshapiro#endif
5879363466Sgshapiro#if MAXDAEMONS != 10
5880363466Sgshapiro	"MAXDAEMONS=" SM_XSTR(MAXDAEMONS),
5881363466Sgshapiro#endif
5882363466Sgshapiro#if defined(MSGIDLOGLEN)
5883363466Sgshapiro	"MSGIDLOGLEN=" SM_XSTR(MSGIDLOGLEN),
5884363466Sgshapiro#endif
588590795Sgshapiro#if MILTER
588690795Sgshapiro	"MILTER",
5887285229Sgshapiro#endif
588838032Speter#if MIME7TO8
588938032Speter	"MIME7TO8",
5890285229Sgshapiro#endif
5891125823Sgshapiro#if MIME7TO8_OLD
5892125823Sgshapiro	"MIME7TO8_OLD",
5893285229Sgshapiro#endif
589438032Speter#if MIME8TO7
589538032Speter	"MIME8TO7",
5896285229Sgshapiro#endif
589738032Speter#if NAMED_BIND
589838032Speter	"NAMED_BIND",
5899285229Sgshapiro#endif
590090795Sgshapiro#if NDBM
590138032Speter	"NDBM",
5902285229Sgshapiro#endif
590338032Speter#if NETINET
590438032Speter	"NETINET",
5905285229Sgshapiro#endif
590664565Sgshapiro#if NETINET6
590764565Sgshapiro	"NETINET6",
5908285229Sgshapiro#endif
590938032Speter#if NETINFO
591038032Speter	"NETINFO",
5911285229Sgshapiro#endif
591238032Speter#if NETISO
591338032Speter	"NETISO",
5914285229Sgshapiro#endif
591538032Speter#if NETNS
591638032Speter	"NETNS",
5917285229Sgshapiro#endif
591838032Speter#if NETUNIX
591938032Speter	"NETUNIX",
5920285229Sgshapiro#endif
592138032Speter#if NETX25
592238032Speter	"NETX25",
5923285229Sgshapiro#endif
5924363466Sgshapiro#if NO_EOH_FIELDS
5925363466Sgshapiro	"NO_EOH_FIELDS",
5926363466Sgshapiro#endif
592790795Sgshapiro#if NEWDB
5928363466Sgshapiro# if defined(DB_VERSION_MAJOR) && defined(DB_VERSION_MINOR)
5929363466Sgshapiro	"NEWDB=" SM_XSTR(DB_VERSION_MAJOR) "." SM_XSTR(DB_VERSION_MINOR),
5930363466Sgshapiro# else
593138032Speter	"NEWDB",
5932363466Sgshapiro# endif
5933285229Sgshapiro#endif
5934363466Sgshapiro#if CDB
5935363466Sgshapiro	"CDB=" SM_XSTR(CDB),
5936363466Sgshapiro#endif
593790795Sgshapiro#if NIS
593838032Speter	"NIS",
5939285229Sgshapiro#endif
594090795Sgshapiro#if NISPLUS
594138032Speter	"NISPLUS",
5942285229Sgshapiro#endif
594390795Sgshapiro#if NO_DH
594490795Sgshapiro	"NO_DH",
5945285229Sgshapiro#endif
594690795Sgshapiro#if PH_MAP
594764565Sgshapiro	"PH_MAP",
5948285229Sgshapiro#endif
594990795Sgshapiro#ifdef PICKY_HELO_CHECK
595090795Sgshapiro	"PICKY_HELO_CHECK",
5951285229Sgshapiro#endif
595290795Sgshapiro#if PIPELINING
595390795Sgshapiro	"PIPELINING",
5954285229Sgshapiro#endif
595564565Sgshapiro#if SASL
595698125Sgshapiro# if SASL >= 20000
595798125Sgshapiro	"SASLv2",
5958363466Sgshapiro# else
595964565Sgshapiro	"SASL",
5960285229Sgshapiro# endif
5961285229Sgshapiro#endif
596238032Speter#if SCANF
596338032Speter	"SCANF",
5964285229Sgshapiro#endif
5965168520Sgshapiro#if SM_LDAP_ERROR_ON_MISSING_ARGS
5966168520Sgshapiro	"SM_LDAP_ERROR_ON_MISSING_ARGS",
5967285229Sgshapiro#endif
596838032Speter#if SMTPDEBUG
596938032Speter	"SMTPDEBUG",
5970285229Sgshapiro#endif
5971132946Sgshapiro#if SOCKETMAP
5972132946Sgshapiro	"SOCKETMAP",
5973285229Sgshapiro#endif
597464565Sgshapiro#if STARTTLS
597564565Sgshapiro	"STARTTLS",
5976285229Sgshapiro#endif
597790795Sgshapiro#if SUID_ROOT_FILES_OK
597838032Speter	"SUID_ROOT_FILES_OK",
5979285229Sgshapiro#endif
5980363466Sgshapiro#if SYSLOG_BUFSIZE > 1024
5981363466Sgshapiro	"SYSLOG_BUFSIZE=" SM_XSTR(SYSLOG_BUFSIZE),
5982363466Sgshapiro#endif
598338032Speter#if TCPWRAPPERS
598438032Speter	"TCPWRAPPERS",
5985285229Sgshapiro#endif
598690795Sgshapiro#if TLS_NO_RSA
598790795Sgshapiro	"TLS_NO_RSA",
5988285229Sgshapiro#endif
5989363466Sgshapiro#if TLS_EC
5990363466Sgshapiro	/* elliptic curves */
5991363466Sgshapiro	"TLS_EC",
5992363466Sgshapiro#endif
599390795Sgshapiro#if TLS_VRFY_PER_CTX
599490795Sgshapiro	"TLS_VRFY_PER_CTX",
5995285229Sgshapiro#endif
599638032Speter#if USERDB
599738032Speter	"USERDB",
5998285229Sgshapiro#endif
599994337Sgshapiro#if USE_LDAP_INIT
600094337Sgshapiro	"USE_LDAP_INIT",
6001285229Sgshapiro#endif
6002132946Sgshapiro#if USE_TTYPATH
6003132946Sgshapiro	"USE_TTYPATH",
6004285229Sgshapiro#endif
600538032Speter#if XDEBUG
600638032Speter	"XDEBUG",
6007285229Sgshapiro#endif
600890795Sgshapiro#if XLA
600938032Speter	"XLA",
6010285229Sgshapiro#endif
601138032Speter	NULL
601238032Speter};
601338032Speter
601438032Speter
601538032Speter/*
601638032Speter**  OS compile options.
601738032Speter*/
601838032Speter
601938032Speterchar	*OsCompileOptions[] =
602038032Speter{
602190795Sgshapiro#if ADDRCONFIG_IS_BROKEN
602290795Sgshapiro	"ADDRCONFIG_IS_BROKEN",
6023285229Sgshapiro#endif
602490795Sgshapiro#ifdef AUTO_NETINFO_HOSTS
602590795Sgshapiro	"AUTO_NETINFO_HOSTS",
6026285229Sgshapiro#endif
602790795Sgshapiro#ifdef AUTO_NIS_ALIASES
602890795Sgshapiro	"AUTO_NIS_ALIASES",
6029285229Sgshapiro#endif
603090795Sgshapiro#if BROKEN_RES_SEARCH
603190795Sgshapiro	"BROKEN_RES_SEARCH",
6032285229Sgshapiro#endif
603390795Sgshapiro#ifdef BSD4_4_SOCKADDR
603490795Sgshapiro	"BSD4_4_SOCKADDR",
6035285229Sgshapiro#endif
603638032Speter#if BOGUS_O_EXCL
603738032Speter	"BOGUS_O_EXCL",
6038285229Sgshapiro#endif
603990795Sgshapiro#if DEC_OSF_BROKEN_GETPWENT
604090795Sgshapiro	"DEC_OSF_BROKEN_GETPWENT",
6041285229Sgshapiro#endif
6042363466Sgshapiro#if DNSSEC_TEST
6043363466Sgshapiro	"DNSSEC_TEST",
6044363466Sgshapiro#endif
604564565Sgshapiro#if FAST_PID_RECYCLE
604664565Sgshapiro	"FAST_PID_RECYCLE",
6047285229Sgshapiro#endif
6048132946Sgshapiro#if HASCLOSEFROM
6049132946Sgshapiro	"HASCLOSEFROM",
6050285229Sgshapiro#endif
605164565Sgshapiro#if HASFCHOWN
605264565Sgshapiro	"HASFCHOWN",
6053285229Sgshapiro#endif
605438032Speter#if HASFCHMOD
605538032Speter	"HASFCHMOD",
6056285229Sgshapiro#endif
6057132946Sgshapiro#if HASFDWALK
6058132946Sgshapiro	"HASFDWALK",
6059285229Sgshapiro#endif
606038032Speter#if HASFLOCK
606138032Speter	"HASFLOCK",
6062285229Sgshapiro#endif
606338032Speter#if HASGETDTABLESIZE
606438032Speter	"HASGETDTABLESIZE",
6065285229Sgshapiro#endif
6066363466Sgshapiro#if HAS_GETHOSTBYNAME2
6067363466Sgshapiro	"HAS_GETHOSTBYNAME2",
6068363466Sgshapiro#endif
606938032Speter#if HASGETUSERSHELL
607038032Speter	"HASGETUSERSHELL",
6071285229Sgshapiro#endif
607238032Speter#if HASINITGROUPS
607338032Speter	"HASINITGROUPS",
6074285229Sgshapiro#endif
6075168520Sgshapiro#if HASLDAPGETALIASBYNAME
6076168520Sgshapiro	"HASLDAPGETALIASBYNAME",
6077285229Sgshapiro#endif
607838032Speter#if HASLSTAT
607938032Speter	"HASLSTAT",
6080285229Sgshapiro#endif
608190795Sgshapiro#if HASNICE
608290795Sgshapiro	"HASNICE",
6083285229Sgshapiro#endif
608464565Sgshapiro#if HASRANDOM
608564565Sgshapiro	"HASRANDOM",
6086285229Sgshapiro#endif
608790795Sgshapiro#if HASRRESVPORT
608890795Sgshapiro	"HASRRESVPORT",
6089285229Sgshapiro#endif
609090795Sgshapiro#if HASSETEGID
609190795Sgshapiro	"HASSETEGID",
6092285229Sgshapiro#endif
609364565Sgshapiro#if HASSETLOGIN
609464565Sgshapiro	"HASSETLOGIN",
6095285229Sgshapiro#endif
609690795Sgshapiro#if HASSETREGID
609790795Sgshapiro	"HASSETREGID",
6098285229Sgshapiro#endif
609990795Sgshapiro#if HASSETRESGID
610090795Sgshapiro	"HASSETRESGID",
6101285229Sgshapiro#endif
610238032Speter#if HASSETREUID
610338032Speter	"HASSETREUID",
6104285229Sgshapiro#endif
610538032Speter#if HASSETRLIMIT
610638032Speter	"HASSETRLIMIT",
6107285229Sgshapiro#endif
610838032Speter#if HASSETSID
610938032Speter	"HASSETSID",
6110285229Sgshapiro#endif
611138032Speter#if HASSETUSERCONTEXT
611238032Speter	"HASSETUSERCONTEXT",
6113285229Sgshapiro#endif
611438032Speter#if HASSETVBUF
611538032Speter	"HASSETVBUF",
6116285229Sgshapiro#endif
611738032Speter#if HAS_ST_GEN
611838032Speter	"HAS_ST_GEN",
6119285229Sgshapiro#endif
612064565Sgshapiro#if HASSRANDOMDEV
612164565Sgshapiro	"HASSRANDOMDEV",
6122285229Sgshapiro#endif
612364565Sgshapiro#if HASURANDOMDEV
612464565Sgshapiro	"HASURANDOMDEV",
6125285229Sgshapiro#endif
612638032Speter#if HASSTRERROR
612738032Speter	"HASSTRERROR",
6128285229Sgshapiro#endif
612938032Speter#if HASULIMIT
613038032Speter	"HASULIMIT",
6131285229Sgshapiro#endif
613238032Speter#if HASUNAME
613338032Speter	"HASUNAME",
6134285229Sgshapiro#endif
613538032Speter#if HASUNSETENV
613638032Speter	"HASUNSETENV",
6137285229Sgshapiro#endif
613838032Speter#if HASWAITPID
613938032Speter	"HASWAITPID",
6140285229Sgshapiro#endif
6141223067Sgshapiro#if HAVE_NANOSLEEP
6142223067Sgshapiro	"HAVE_NANOSLEEP",
6143285229Sgshapiro#endif
614438032Speter#if IDENTPROTO
614538032Speter	"IDENTPROTO",
6146285229Sgshapiro#endif
614738032Speter#if IP_SRCROUTE
614838032Speter	"IP_SRCROUTE",
6149285229Sgshapiro#endif
615038032Speter#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
615138032Speter	"LOCK_ON_OPEN",
6152285229Sgshapiro#endif
6153168520Sgshapiro#if MILTER_NO_NAGLE
6154168520Sgshapiro	"MILTER_NO_NAGLE ",
6155285229Sgshapiro#endif
615638032Speter#if NEEDFSYNC
615738032Speter	"NEEDFSYNC",
6158285229Sgshapiro#endif
615990795Sgshapiro#if NEEDLINK
616090795Sgshapiro	"NEEDLINK",
6161285229Sgshapiro#endif
616290795Sgshapiro#if NEEDLOCAL_HOSTNAME_LENGTH
616390795Sgshapiro	"NEEDLOCAL_HOSTNAME_LENGTH",
6164285229Sgshapiro#endif
616590795Sgshapiro#if NEEDSGETIPNODE
616690795Sgshapiro	"NEEDSGETIPNODE",
6167285229Sgshapiro#endif
616890795Sgshapiro#if NEEDSTRSTR
616990795Sgshapiro	"NEEDSTRSTR",
6170285229Sgshapiro#endif
617190795Sgshapiro#if NEEDSTRTOL
617290795Sgshapiro	"NEEDSTRTOL",
6173285229Sgshapiro#endif
617490795Sgshapiro#ifdef NO_GETSERVBYNAME
617590795Sgshapiro	"NO_GETSERVBYNAME",
6176285229Sgshapiro#endif
617738032Speter#if NOFTRUNCATE
617838032Speter	"NOFTRUNCATE",
6179285229Sgshapiro#endif
618090795Sgshapiro#if REQUIRES_DIR_FSYNC
618190795Sgshapiro	"REQUIRES_DIR_FSYNC",
6182285229Sgshapiro#endif
618338032Speter#if RLIMIT_NEEDS_SYS_TIME_H
618438032Speter	"RLIMIT_NEEDS_SYS_TIME_H",
6185285229Sgshapiro#endif
618638032Speter#if SAFENFSPATHCONF
618738032Speter	"SAFENFSPATHCONF",
6188285229Sgshapiro#endif
618938032Speter#if SECUREWARE
619038032Speter	"SECUREWARE",
6191285229Sgshapiro#endif
6192249729Sgshapiro#if SFS_TYPE == SFS_4ARGS
6193249729Sgshapiro	"SFS_4ARGS",
6194249729Sgshapiro#elif SFS_TYPE == SFS_MOUNT
6195249729Sgshapiro	"SFS_MOUNT",
6196249729Sgshapiro#elif SFS_TYPE == SFS_NONE
6197249729Sgshapiro	"SFS_NONE",
6198249729Sgshapiro#elif SFS_TYPE == SFS_NT
6199249729Sgshapiro	"SFS_NT",
6200249729Sgshapiro#elif SFS_TYPE == SFS_STATFS
6201249729Sgshapiro	"SFS_STATFS",
6202249729Sgshapiro#elif SFS_TYPE == SFS_STATVFS
6203249729Sgshapiro	"SFS_STATVFS",
6204249729Sgshapiro#elif SFS_TYPE == SFS_USTAT
6205249729Sgshapiro	"SFS_USTAT",
6206249729Sgshapiro#elif SFS_TYPE == SFS_VFS
6207249729Sgshapiro	"SFS_VFS",
6208249729Sgshapiro#endif
620938032Speter#if SHARE_V1
621038032Speter	"SHARE_V1",
6211285229Sgshapiro#endif
621238032Speter#if SIOCGIFCONF_IS_BROKEN
621338032Speter	"SIOCGIFCONF_IS_BROKEN",
6214285229Sgshapiro#endif
621538032Speter#if SIOCGIFNUM_IS_BROKEN
621638032Speter	"SIOCGIFNUM_IS_BROKEN",
6217285229Sgshapiro#endif
621864565Sgshapiro#if SNPRINTF_IS_BROKEN
621964565Sgshapiro	"SNPRINTF_IS_BROKEN",
6220285229Sgshapiro#endif
622164565Sgshapiro#if SO_REUSEADDR_IS_BROKEN
622264565Sgshapiro	"SO_REUSEADDR_IS_BROKEN",
6223285229Sgshapiro#endif
622438032Speter#if SYS5SETPGRP
622538032Speter	"SYS5SETPGRP",
6226285229Sgshapiro#endif
622738032Speter#if SYSTEM5
622838032Speter	"SYSTEM5",
6229285229Sgshapiro#endif
623090795Sgshapiro#if USE_DOUBLE_FORK
623190795Sgshapiro	"USE_DOUBLE_FORK",
6232285229Sgshapiro#endif
623390795Sgshapiro#if USE_ENVIRON
623490795Sgshapiro	"USE_ENVIRON",
6235285229Sgshapiro#endif
623638032Speter#if USE_SA_SIGACTION
623738032Speter	"USE_SA_SIGACTION",
6238285229Sgshapiro#endif
623938032Speter#if USE_SIGLONGJMP
624038032Speter	"USE_SIGLONGJMP",
6241285229Sgshapiro#endif
624290795Sgshapiro#if USEGETCONFATTR
624390795Sgshapiro	"USEGETCONFATTR",
6244285229Sgshapiro#endif
624538032Speter#if USESETEUID
624638032Speter	"USESETEUID",
6247285229Sgshapiro#endif
624890795Sgshapiro#ifdef USESYSCTL
624990795Sgshapiro	"USESYSCTL",
6250285229Sgshapiro#endif
6251223067Sgshapiro#if USE_OPENSSL_ENGINE
6252363466Sgshapiro	/*
6253363466Sgshapiro	**  0: OpenSSL ENGINE?
6254363466Sgshapiro	**  1: Support Sun OpenSSL patch for SPARC T4 pkcs11
6255363466Sgshapiro	**  2: none
6256363466Sgshapiro	*/
6257363466Sgshapiro# if USE_OPENSSL_ENGINE != 1
6258363466Sgshapiro	"USE_OPENSSL_ENGINE=" SM_XSTR(USE_OPENSSL_ENGINE),
6259363466Sgshapiro# else
6260223067Sgshapiro	"USE_OPENSSL_ENGINE",
6261285229Sgshapiro#endif
6262363466Sgshapiro#endif
626390795Sgshapiro#if USING_NETSCAPE_LDAP
626490795Sgshapiro	"USING_NETSCAPE_LDAP",
6265285229Sgshapiro#endif
626690795Sgshapiro#ifdef WAITUNION
626790795Sgshapiro	"WAITUNION",
6268285229Sgshapiro#endif
626938032Speter	NULL
627038032Speter};
627164565Sgshapiro
627290795Sgshapiro/*
627390795Sgshapiro**  FFR compile options.
627490795Sgshapiro*/
627590795Sgshapiro
627690795Sgshapirochar	*FFRCompileOptions[] =
627790795Sgshapiro{
6278285229Sgshapiro#if _FFR_ADD_BCC
6279363466Sgshapiro	/* see cf/feature/bcc.m4 */
6280285229Sgshapiro	"_FFR_ADD_BCC",
6281285229Sgshapiro#endif
6282173343Sgshapiro#if _FFR_ADDR_TYPE_MODES
6283173343Sgshapiro	/* more info in {addr_type}, requires m4 changes! */
6284173343Sgshapiro	"_FFR_ADDR_TYPE_MODES",
6285285229Sgshapiro#endif
6286285229Sgshapiro#if _FFR_ALIAS_DETAIL
6287285229Sgshapiro	/* try to handle +detail for aliases */
6288285229Sgshapiro	"_FFR_ALIAS_DETAIL",
6289285229Sgshapiro#endif
629090795Sgshapiro#if _FFR_ALLOW_SASLINFO
6291112813Sgshapiro	/* DefaultAuthInfo can be specified by user. */
6292132946Sgshapiro	/* DefaultAuthInfo doesn't really work in 8.13 anymore. */
629390795Sgshapiro	"_FFR_ALLOW_SASLINFO",
6294285229Sgshapiro#endif
6295182352Sgshapiro#if _FFR_BADRCPT_SHUTDOWN
6296182352Sgshapiro	/* shut down connection (421) if there are too many bad RCPTs */
6297182352Sgshapiro	"_FFR_BADRCPT_SHUTDOWN",
6298285229Sgshapiro#endif
629990795Sgshapiro#if _FFR_BESTMX_BETTER_TRUNCATION
6300112813Sgshapiro	/* Better truncation of list of MX records for dns map. */
630190795Sgshapiro	"_FFR_BESTMX_BETTER_TRUNCATION",
6302285229Sgshapiro#endif
6303363466Sgshapiro#if _FFR_BLANKENV_MACV
6304363466Sgshapiro	/* also look up macros in BlankEnvelope */
6305363466Sgshapiro	"_FFR_BLANKENV_MACV",
6306363466Sgshapiro#endif
6307285229Sgshapiro#if _FFR_BOUNCE_QUEUE
6308285229Sgshapiro	/* Separate, unprocessed queue for DSNs */
6309285229Sgshapiro	/* John Gardiner Myers of Proofpoint */
6310285229Sgshapiro	"_FFR_BOUNCE_QUEUE",
6311285229Sgshapiro#endif
631290795Sgshapiro#if _FFR_CATCH_BROKEN_MTAS
6313112813Sgshapiro	/* Deal with MTAs that send a reply during the DATA phase. */
631490795Sgshapiro	"_FFR_CATCH_BROKEN_MTAS",
6315285229Sgshapiro#endif
631698125Sgshapiro#if _FFR_CHK_QUEUE
6317112813Sgshapiro	/* Stricter checks about queue directory permissions. */
631898125Sgshapiro	"_FFR_CHK_QUEUE",
6319285229Sgshapiro#endif
6320363466Sgshapiro#if _FFR_CLIENTCA
6321363466Sgshapiro	/*
6322363466Sgshapiro	**  Allow to set client specific CA values.
6323363466Sgshapiro	**  CACertFile: see doc/op.*:
6324363466Sgshapiro	**  "The DNs of these certificates are sent to the client
6325363466Sgshapiro	**  during the TLS handshake (as part of the CertificateRequest)
6326363466Sgshapiro	**  as the list of acceptable CAs.
6327363466Sgshapiro	**  However, do not list too many root CAs in that file,
6328363466Sgshapiro	**  otherwise the TLS handshake may fail;"
6329363466Sgshapiro	**  In TLSv1.3 the certs in CACertFile are also sent by
6330363466Sgshapiro	**  the client to the server and there is seemingly a
6331363466Sgshapiro	**  16KB limit (just in OpenSSL?).
6332363466Sgshapiro	**  Having a separate CACertFile for the client
6333363466Sgshapiro	**  helps to avoid this problem.
6334363466Sgshapiro	*/
6335363466Sgshapiro
6336363466Sgshapiro	"_FFR_CLIENTCA",
6337363466Sgshapiro#endif
6338120259Sgshapiro#if _FFR_CLIENT_SIZE
6339120259Sgshapiro	/* Don't try to send mail if its size exceeds SIZE= of server. */
6340120259Sgshapiro	"_FFR_CLIENT_SIZE",
6341285229Sgshapiro#endif
6342157006Sgshapiro#if _FFR_DM_ONE
6343157006Sgshapiro	/* deliver first TA in background, then queue */
6344157006Sgshapiro	"_FFR_DM_ONE",
6345285229Sgshapiro#endif
634694337Sgshapiro#if _FFR_DIGUNIX_SAFECHOWN
6347112813Sgshapiro	/* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */
634894337Sgshapiro/* Problem noted by Anne Bennett of Concordia University */
634994337Sgshapiro	"_FFR_DIGUNIX_SAFECHOWN",
6350285229Sgshapiro#endif
635194337Sgshapiro#if _FFR_DNSMAP_ALIASABLE
6352112813Sgshapiro	/* Allow dns map type to be used for aliases. */
635394337Sgshapiro/* Don Lewis of TDK */
635494337Sgshapiro	"_FFR_DNSMAP_ALIASABLE",
6355285229Sgshapiro#endif
635690795Sgshapiro#if _FFR_DONTLOCKFILESFORREAD_OPTION
6357112813Sgshapiro	/* Enable DontLockFilesForRead option. */
635890795Sgshapiro	"_FFR_DONTLOCKFILESFORREAD_OPTION",
6359285229Sgshapiro#endif
636090795Sgshapiro#if _FFR_DOTTED_USERNAMES
6361112813Sgshapiro	/* Allow usernames with '.' */
636290795Sgshapiro	"_FFR_DOTTED_USERNAMES",
6363285229Sgshapiro#endif
6364168520Sgshapiro#if _FFR_DPO_CS
6365168520Sgshapiro	/*
6366168520Sgshapiro	**  Make DaemonPortOptions case sensitive.
6367168520Sgshapiro	**  For some unknown reasons the code converted every option
6368168520Sgshapiro	**  to uppercase (first letter only, as that's the only one that
6369168520Sgshapiro	**  is actually checked). This prevented all new lower case options
6370168520Sgshapiro	**  from working...
6371168520Sgshapiro	**  The documentation doesn't say anything about case (in)sensitivity,
6372168520Sgshapiro	**  which means it should be case sensitive by default,
6373168520Sgshapiro	**  but it's not a good idea to change this within a patch release,
6374168520Sgshapiro	**  so let's delay this to 8.15.
6375168520Sgshapiro	*/
6376168520Sgshapiro
6377168520Sgshapiro	"_FFR_DPO_CS",
6378285229Sgshapiro#endif
6379173343Sgshapiro#if _FFR_DPRINTF_MAP
6380173343Sgshapiro	/* dprintf map for logging */
6381173343Sgshapiro	"_FFR_DPRINTF_MAP",
6382285229Sgshapiro#endif
638390795Sgshapiro#if _FFR_DROP_TRUSTUSER_WARNING
6384112813Sgshapiro	/*
6385112813Sgshapiro	**  Don't issue this warning:
6386112813Sgshapiro	**  "readcf: option TrustedUser may cause problems on systems
6387112813Sgshapiro	**  which do not support fchown() if UseMSP is not set.
6388112813Sgshapiro	*/
6389112813Sgshapiro
639090795Sgshapiro	"_FFR_DROP_TRUSTUSER_WARNING",
6391285229Sgshapiro#endif
6392168520Sgshapiro#if _FFR_EIGHT_BIT_ADDR_OK
6393168520Sgshapiro	/* EightBitAddrOK: allow 8-bit e-mail addresses */
6394168520Sgshapiro	"_FFR_EIGHT_BIT_ADDR_OK",
6395285229Sgshapiro#endif
6396363466Sgshapiro#if _FFR_EXPAND_HELONAME
6397363466Sgshapiro	/* perform macro expansion for heloname */
6398363466Sgshapiro	"_FFR_EXPAND_HELONAME",
6399363466Sgshapiro#endif
6400120259Sgshapiro#if _FFR_EXTRA_MAP_CHECK
6401120259Sgshapiro	/* perform extra checks on $( $) in R lines */
6402120259Sgshapiro	"_FFR_EXTRA_MAP_CHECK",
6403285229Sgshapiro#endif
6404168520Sgshapiro#if _FFR_GETHBN_ExFILE
6405168520Sgshapiro	/*
6406168520Sgshapiro	**  According to Motonori Nakamura some gethostbyname()
6407168520Sgshapiro	**  implementations (TurboLinux?) may (temporarily) fail
6408285229Sgshapiro	**  due to a lack of file descriptors. Enabling this FFR
6409168520Sgshapiro	**  will check errno for EMFILE and ENFILE and in case of a match
6410168520Sgshapiro	**  cause a temporary error instead of a permanent error.
6411168520Sgshapiro	**  The right solution is of course to file a bug against those
6412168520Sgshapiro	**  systems such that they actually set h_errno = TRY_AGAIN.
6413168520Sgshapiro	*/
6414168520Sgshapiro
6415168520Sgshapiro	"_FFR_GETHBN_ExFILE",
6416285229Sgshapiro#endif
6417249729Sgshapiro#if _FFR_FIPSMODE
6418249729Sgshapiro	/* FIPSMode (if supported by OpenSSL library) */
6419249729Sgshapiro	"_FFR_FIPSMODE",
6420285229Sgshapiro#endif
642190795Sgshapiro#if _FFR_FIX_DASHT
6422112813Sgshapiro	/*
6423112813Sgshapiro	**  If using -t, force not sending to argv recipients, even
6424112813Sgshapiro	**  if they are mentioned in the headers.
6425112813Sgshapiro	*/
6426112813Sgshapiro
642790795Sgshapiro	"_FFR_FIX_DASHT",
6428285229Sgshapiro#endif
642990795Sgshapiro#if _FFR_FORWARD_SYSERR
6430112813Sgshapiro	/* Cause a "syserr" if forward file isn't "safe". */
643190795Sgshapiro	"_FFR_FORWARD_SYSERR",
6432285229Sgshapiro#endif
643390795Sgshapiro#if _FFR_GEN_ORCPT
6434112813Sgshapiro	/* Generate a ORCPT DSN arg if not already provided */
643590795Sgshapiro	"_FFR_GEN_ORCPT",
6436285229Sgshapiro#endif
643794337Sgshapiro#if _FFR_HANDLE_ISO8859_GECOS
6438112813Sgshapiro	/*
6439112813Sgshapiro	**  Allow ISO 8859 characters in GECOS field: replace them
6440285229Sgshapiro	**  with ASCII "equivalent".
6441112813Sgshapiro	*/
6442112813Sgshapiro
644394337Sgshapiro/* Peter Eriksson of Linkopings universitet */
644494337Sgshapiro	"_FFR_HANDLE_ISO8859_GECOS",
6445285229Sgshapiro#endif
6446285229Sgshapiro#if _FFR_HANDLE_HDR_RW_TEMPFAIL
6447285229Sgshapiro	/*
6448285229Sgshapiro	**  Temporary header rewriting problems from remotename() etc
6449285229Sgshapiro	**  are not "sticky" for mci (e.g., during queue runs).
6450285229Sgshapiro	*/
6451285229Sgshapiro
6452285229Sgshapiro	"_FFR_HANDLE_HDR_RW_TEMPFAIL",
6453285229Sgshapiro#endif
645490795Sgshapiro#if _FFR_HPUX_NSSWITCH
6455112813Sgshapiro	/* Use nsswitch on HP-UX */
645690795Sgshapiro	"_FFR_HPUX_NSSWITCH",
6457285229Sgshapiro#endif
6458120259Sgshapiro#if _FFR_IGNORE_BOGUS_ADDR
6459120259Sgshapiro	/* Ignore addresses for which prescan() failed */
6460120259Sgshapiro	"_FFR_IGNORE_BOGUS_ADDR",
6461285229Sgshapiro#endif
646290795Sgshapiro#if _FFR_IGNORE_EXT_ON_HELO
6463112813Sgshapiro	/* Ignore extensions offered in response to HELO */
646490795Sgshapiro	"_FFR_IGNORE_EXT_ON_HELO",
6465285229Sgshapiro#endif
6466363466Sgshapiro#if _FFR_KEEPBCC
6467363466Sgshapiro	/* Keep Bcc header */
6468363466Sgshapiro	"_FFR_KEEPBCC",
6469285229Sgshapiro#endif
6470182352Sgshapiro#if _FFR_LOCAL_DAEMON
6471182352Sgshapiro	/* Local daemon mode (-bl) which only accepts loopback connections */
6472182352Sgshapiro	"_FFR_LOCAL_DAEMON",
6473285229Sgshapiro#endif
6474285229Sgshapiro#if _FFR_LOG_MORE1
6475285229Sgshapiro	/* log some TLS/AUTH info in from= too */
6476363466Sgshapiro	"_FFR_LOG_MORE1=" SM_XSTR(_FFR_LOG_MORE1),
6477285229Sgshapiro#endif
6478285229Sgshapiro#if _FFR_LOG_MORE2
6479285229Sgshapiro	/* log some TLS info in to= too */
6480363466Sgshapiro	"_FFR_LOG_MORE2=" SM_XSTR(_FFR_LOG_MORE2),
6481285229Sgshapiro#endif
6482363466Sgshapiro#if _FFR_LOG_MORE1 > 1 || _FFR_LOG_MORE2 > 1
6483363466Sgshapiro# if _FFR_LOG_MORE1 != _FFR_LOG_MORE2
6484363466Sgshapiro   ERROR: FFR_LOG_MORE1 != FFR_LOG_MORE2
6485363466Sgshapiro# endif
6486285229Sgshapiro#endif
6487203004Sgshapiro#if _FFR_MAIL_MACRO
6488363466Sgshapiro	/* make the "real" sender address available in {mail_from} */
6489203004Sgshapiro	"_FFR_MAIL_MACRO",
6490285229Sgshapiro#endif
6491132946Sgshapiro#if _FFR_MAXDATASIZE
6492132946Sgshapiro	/*
6493132946Sgshapiro	**  It is possible that a header is larger than MILTER_CHUNK_SIZE,
6494132946Sgshapiro	**  hence this shouldn't be used as limit for milter communication.
6495132946Sgshapiro	**  see also libmilter/comm.c
6496132946Sgshapiro	**  Gurusamy Sarathy of ActiveState
6497132946Sgshapiro	*/
6498132946Sgshapiro
6499141862Sgshapiro	"_FFR_MAXDATASIZE",
6500285229Sgshapiro#endif
650190795Sgshapiro#if _FFR_MAX_FORWARD_ENTRIES
6502112813Sgshapiro	/* Try to limit number of .forward entries */
6503112813Sgshapiro	/* (doesn't work) */
650490795Sgshapiro/* Randall S. Winchester of the University of Maryland */
650590795Sgshapiro	"_FFR_MAX_FORWARD_ENTRIES",
6506285229Sgshapiro#endif
6507120259Sgshapiro#if _FFR_MAX_SLEEP_TIME
6508120259Sgshapiro	/* Limit sleep(2) time in libsm/clock.c */
6509120259Sgshapiro	"_FFR_MAX_SLEEP_TIME",
6510285229Sgshapiro#endif
6511203004Sgshapiro#if _FFR_MDS_NEGOTIATE
6512363466Sgshapiro	/* MaxDataSize negotiation with libmilter */
6513203004Sgshapiro	"_FFR_MDS_NEGOTIATE",
6514285229Sgshapiro#endif
6515157006Sgshapiro#if _FFR_MEMSTAT
6516157006Sgshapiro	/* Check free memory */
6517157006Sgshapiro	"_FFR_MEMSTAT",
6518285229Sgshapiro#endif
6519168520Sgshapiro#if _FFR_MILTER_CHECK
6520168520Sgshapiro	"_FFR_MILTER_CHECK",
6521285229Sgshapiro#endif
6522285229Sgshapiro#if _FFR_MILTER_CONNECT_REPLYCODE
6523285229Sgshapiro	/* milter: propagate replycode returned by connect commands */
6524285229Sgshapiro	/* John Gardiner Myers of Proofpoint */
6525285229Sgshapiro	"_FFR_MILTER_CONNECT_REPLYCODE ",
6526285229Sgshapiro#endif
6527168520Sgshapiro#if _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF
6528168520Sgshapiro	/*
6529168520Sgshapiro	**  milter_body() uses the same conversion algorithm as putbody()
6530168520Sgshapiro	**  to translate the "local" df format (\n) to SMTP format (\r\n).
6531168520Sgshapiro	**  However, putbody() and mime8to7() use different conversion
6532168520Sgshapiro	**  algorithms.
6533168520Sgshapiro	**  If the input date does not follow the SMTP standard
6534168520Sgshapiro	**  (e.g., if it has "naked \r"s), then the output from putbody()
6535168520Sgshapiro	**  and mime8to7() will most likely be different.
6536168520Sgshapiro	**  By turning on this FFR milter_body() will try to "imitate"
6537168520Sgshapiro	**  mime8to7().
6538168520Sgshapiro	**  Note: there is no (simple) way to deal with both conversions
6539168520Sgshapiro	**  in a consistent manner. Moreover, as the "GiGo" principle applies,
6540168520Sgshapiro	**  it's not really worth to fix it.
6541168520Sgshapiro	*/
6542168520Sgshapiro
6543168520Sgshapiro	"_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF",
6544285229Sgshapiro#endif
6545168520Sgshapiro#if _FFR_MILTER_CHECK_REJECTIONS_TOO
6546168520Sgshapiro	/*
6547168520Sgshapiro	**  Also send RCPTs that are rejected by check_rcpt to a milter
6548168520Sgshapiro	**  (if requested during option negotiation).
6549168520Sgshapiro	*/
6550168520Sgshapiro
6551168520Sgshapiro	"_FFR_MILTER_CHECK_REJECTIONS_TOO",
6552285229Sgshapiro#endif
6553203004Sgshapiro#if _FFR_MILTER_ENHSC
6554203004Sgshapiro	/* extract enhanced status code from milter replies for dsn= logging */
6555203004Sgshapiro	"_FFR_MILTER_ENHSC",
6556285229Sgshapiro#endif
6557132946Sgshapiro#if _FFR_MIME7TO8_OLD
6558132946Sgshapiro	/* Old mime7to8 code, the new is broken for at least one example. */
6559132946Sgshapiro	"_FFR_MIME7TO8_OLD",
6560285229Sgshapiro#endif
6561173343Sgshapiro#if _FFR_MORE_MACROS
6562173343Sgshapiro	/* allow more long macro names ("unprintable" characters). */
6563173343Sgshapiro	"_FFR_MORE_MACROS",
6564285229Sgshapiro#endif
6565157006Sgshapiro#if _FFR_MSG_ACCEPT
6566157006Sgshapiro	/* allow to override "Message accepted for delivery" */
6567157006Sgshapiro	"_FFR_MSG_ACCEPT",
6568285229Sgshapiro#endif
656990795Sgshapiro#if _FFR_NODELAYDSN_ON_HOLD
6570112813Sgshapiro	/* Do not issue a DELAY DSN for mailers that use the hold flag. */
657190795Sgshapiro/* Steven Pitzl */
657290795Sgshapiro	"_FFR_NODELAYDSN_ON_HOLD",
6573285229Sgshapiro#endif
657490795Sgshapiro#if _FFR_NO_PIPE
6575112813Sgshapiro	/* Disable PIPELINING, delay client if used. */
657690795Sgshapiro	"_FFR_NO_PIPE",
6577285229Sgshapiro#endif
6578363466Sgshapiro#if _FFR_LDAP_SINGLEDN
6579363466Sgshapiro	/*
6580363466Sgshapiro	**  The LDAP database map code in Sendmail 8.12.10, when
6581363466Sgshapiro	**  given the -1 switch, would match only a single DN,
6582363466Sgshapiro	**  but was able to return multiple attributes for that
6583363466Sgshapiro	**  DN.  In Sendmail 8.13 this "bug" was corrected to
6584363466Sgshapiro	**  only return if exactly one attribute matched.
6585363466Sgshapiro	**
6586363466Sgshapiro	**  Unfortunately, our configuration uses the former
6587363466Sgshapiro	**  behaviour.  Attached is a relatively simple patch
6588363466Sgshapiro	**  to 8.13.4 which adds a -2 switch (for lack of a
6589363466Sgshapiro	**  better option) which returns the single dn/multiple
6590363466Sgshapiro	**  attributes.
6591363466Sgshapiro	**
6592363466Sgshapiro	** Jeffrey T. Eaton, Carnegie-Mellon University
6593363466Sgshapiro	*/
6594363466Sgshapiro
6595363466Sgshapiro	"_FFR_LDAP_SINGLEDN",
6596285229Sgshapiro#endif
6597147081Sgshapiro#if _FFR_LOG_NTRIES
6598147081Sgshapiro	/* log ntries=, from Nik Clayton of FreeBSD */
6599147081Sgshapiro	"_FFR_LOG_NTRIES",
6600285229Sgshapiro#endif
6601363466Sgshapiro#if _FFR_OCC
6602363466Sgshapiro# if SM_CONF_SHM
6603363466Sgshapiro	/* outgoing connection control (not yet working) */
6604363466Sgshapiro	"_FFR_OCC",
6605363466Sgshapiro# else
6606363466Sgshapiro#  ERROR: FFR_OCC requires _SM_CONF_SHM
6607363466Sgshapiro# endif
6608363466Sgshapiro#endif
6609285229Sgshapiro#if _FFR_PROXY
6610285229Sgshapiro	/* "proxy" (synchronous) delivery mode */
6611285229Sgshapiro	"_FFR_PROXY",
6612285229Sgshapiro#endif
6613168520Sgshapiro#if _FFR_QF_PARANOIA
6614363466Sgshapiro	/* Check to make sure key fields were read from qf */
6615168520Sgshapiro	"_FFR_QF_PARANOIA",
6616285229Sgshapiro#endif
661794337Sgshapiro#if _FFR_QUEUE_GROUP_SORTORDER
6618112813Sgshapiro	/* Allow QueueSortOrder per queue group. */
661994337Sgshapiro/* XXX: Still need to actually use qgrp->qg_sortorder */
662094337Sgshapiro	"_FFR_QUEUE_GROUP_SORTORDER",
6621285229Sgshapiro#endif
662290795Sgshapiro#if _FFR_QUEUE_MACRO
6623112813Sgshapiro	/* Define {queue} macro. */
662490795Sgshapiro	"_FFR_QUEUE_MACRO",
6625285229Sgshapiro#endif
662694337Sgshapiro#if _FFR_QUEUE_RUN_PARANOIA
6627157006Sgshapiro	/* Additional checks when doing queue runs; interval of checks */
662894337Sgshapiro	"_FFR_QUEUE_RUN_PARANOIA",
6629285229Sgshapiro#endif
663090795Sgshapiro#if _FFR_QUEUE_SCHED_DBG
6631112813Sgshapiro	/* Debug output for the queue scheduler. */
663290795Sgshapiro	"_FFR_QUEUE_SCHED_DBG",
6633285229Sgshapiro#endif
6634285229Sgshapiro#if _FFR_RCPTFLAGS
6635363466Sgshapiro	/* dynamic mailer modifications via {rcpt_flags}*/
6636285229Sgshapiro	"_FFR_RCPTFLAGS",
6637285229Sgshapiro#endif
6638203004Sgshapiro#if _FFR_RCPTTHROTDELAY
6639203004Sgshapiro	/* configurable delay for BadRcptThrottle */
6640223067Sgshapiro	"_FFR_RCPTTHROTDELAY",
6641285229Sgshapiro#endif
664290795Sgshapiro#if _FFR_REDIRECTEMPTY
6643112813Sgshapiro	/*
6644112813Sgshapiro	**  envelope <> can't be sent to mailing lists, only owner-
6645112813Sgshapiro	**  send spam of this type to owner- of the list
6646112813Sgshapiro	**  ----  to stop spam from going to mailing lists.
6647112813Sgshapiro	*/
6648112813Sgshapiro
664990795Sgshapiro	"_FFR_REDIRECTEMPTY",
6650285229Sgshapiro#endif
6651249729Sgshapiro#if _FFR_REJECT_NUL_BYTE
6652249729Sgshapiro	/* reject NUL bytes in body */
6653249729Sgshapiro	"_FFR_REJECT_NUL_BYTE",
6654285229Sgshapiro#endif
665590795Sgshapiro#if _FFR_RESET_MACRO_GLOBALS
6656112813Sgshapiro	/* Allow macro 'j' to be set dynamically via rulesets. */
665790795Sgshapiro	"_FFR_RESET_MACRO_GLOBALS",
6658285229Sgshapiro#endif
665990795Sgshapiro#if _FFR_RHS
6660112813Sgshapiro	/* Random shuffle for queue sorting. */
666190795Sgshapiro	"_FFR_RHS",
6662285229Sgshapiro#endif
6663173343Sgshapiro#if _FFR_RUNPQG
6664173343Sgshapiro	/*
6665173343Sgshapiro	**  allow -qGqueue_group -qp to work, i.e.,
6666173343Sgshapiro	**  restrict a persistent queue runner to a queue group.
6667173343Sgshapiro	*/
6668173343Sgshapiro
6669173343Sgshapiro	"_FFR_RUNPQG",
6670285229Sgshapiro#endif
6671173343Sgshapiro#if _FFR_SESSID
6672363466Sgshapiro	/* session id (for logging): WIP, no logging yet!  */
6673173343Sgshapiro	"_FFR_SESSID",
6674285229Sgshapiro#endif
6675363466Sgshapiro#if _FFR_SETANYOPT
6676363466Sgshapiro	"_FFR_SETANYOPT",
6677363466Sgshapiro#endif
6678363466Sgshapiro#if _FFR_SETDEBUG_MAP
6679363466Sgshapiro	"_FFR_SETDEBUG_MAP",
6680363466Sgshapiro#endif
6681363466Sgshapiro#if _FFR_SETOPT_MAP
6682363466Sgshapiro	"_FFR_SETOPT_MAP",
6683363466Sgshapiro#endif
668490795Sgshapiro#if _FFR_SHM_STATUS
6685112813Sgshapiro	/* Donated code (unused). */
668690795Sgshapiro	"_FFR_SHM_STATUS",
6687285229Sgshapiro#endif
6688132946Sgshapiro#if _FFR_SKIP_DOMAINS
6689132946Sgshapiro	/* process every N'th domain instead of every N'th message */
6690141862Sgshapiro	"_FFR_SKIP_DOMAINS",
6691285229Sgshapiro#endif
6692120259Sgshapiro#if _FFR_SLEEP_USE_SELECT
6693120259Sgshapiro	/* Use select(2) in libsm/clock.c to emulate sleep(2) */
6694120259Sgshapiro	"_FFR_SLEEP_USE_SELECT ",
6695285229Sgshapiro#endif
6696363466Sgshapiro#if _FFR_SM_LDAP_DBG
6697363466Sgshapiro# if LDAPMAP && defined(LBER_OPT_LOG_PRINT_FN)
6698363466Sgshapiro	/* LDAP debugging */
6699363466Sgshapiro	"_FFR_SM_LDAP_DBG",
6700363466Sgshapiro# else
6701363466Sgshapiro#  ERROR: FFR_SM_LDAP_DBG requires _LDAPMAP and LBER_OPT_LOG_PRINT_FN
6702363466Sgshapiro# endif
6703363466Sgshapiro#endif
670498125Sgshapiro#if _FFR_SPT_ALIGN
6705112813Sgshapiro	/*
6706112813Sgshapiro	**  It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64
6707112813Sgshapiro	**  bit alignment, so unless each piece of argv and envp is a multiple
6708112813Sgshapiro	**  of 8 bytes (including terminating NULL), initsetproctitle() won't
6709112813Sgshapiro	**  use any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE
6710112813Sgshapiro	**  if you use this FFR.
6711112813Sgshapiro	*/
6712112813Sgshapiro
671398125Sgshapiro/* Chris Adams of HiWAAY Informations Services */
671498125Sgshapiro	"_FFR_SPT_ALIGN",
6715285229Sgshapiro#endif
6716147081Sgshapiro#if _FFR_SS_PER_DAEMON
6717147081Sgshapiro	/* SuperSafe per DaemonPortOptions: 'T' (better letter?) */
6718147081Sgshapiro	"_FFR_SS_PER_DAEMON",
6719285229Sgshapiro#endif
6720203004Sgshapiro#if _FFR_TESTS
6721203004Sgshapiro	/* enable some test code */
6722203004Sgshapiro	"_FFR_TESTS",
6723285229Sgshapiro#endif
672490795Sgshapiro#if _FFR_TIMERS
6725112813Sgshapiro	/* Donated code (unused). */
672690795Sgshapiro	"_FFR_TIMERS",
6727285229Sgshapiro#endif
6728363466Sgshapiro#if _FFR_TLS_ALTNAMES
6729363466Sgshapiro	/* store subjectAltNames in class {cert_altnames} */
6730363466Sgshapiro# if STARTTLS
6731363466Sgshapiro	"_FFR_TLS_ALTNAMES",
6732363466Sgshapiro# else
6733363466Sgshapiro#  error "_FFR_TLS_ALTNAMES set but STARTTLS not defined"
6734363466Sgshapiro# endif
6735285229Sgshapiro#endif
6736363466Sgshapiro#if _FFR_TLSFB2CLEAR
6737363466Sgshapiro	/* set default for TLSFallbacktoClear to true */
6738363466Sgshapiro# if STARTTLS
6739363466Sgshapiro	"_FFR_TLSFB2CLEAR",
6740363466Sgshapiro# else
6741363466Sgshapiro#  error "_FFR_TLSFB2CLEAR set but STARTTLS not defined"
6742363466Sgshapiro# endif
6743363466Sgshapiro#endif
6744285229Sgshapiro#if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE
6745285229Sgshapiro	/*
6746285229Sgshapiro	**  Use SSL_CTX_use_certificate_chain_file()
6747285229Sgshapiro	**  instead of SSL_CTX_use_certificate_file()
6748285229Sgshapiro	*/
6749285229Sgshapiro
6750363466Sgshapiro# if STARTTLS
6751285229Sgshapiro	"_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE",
6752363466Sgshapiro# else
6753363466Sgshapiro#  error "_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE set but STARTTLS not defined"
6754363466Sgshapiro# endif
6755285229Sgshapiro#endif
675690795Sgshapiro#if _FFR_TRUSTED_QF
6757112813Sgshapiro	/*
6758112813Sgshapiro	**  If we don't own the file mark it as unsafe.
6759112813Sgshapiro	**  However, allow TrustedUser to own it as well
6760112813Sgshapiro	**  in case TrustedUser manipulates the queue.
6761112813Sgshapiro	*/
6762112813Sgshapiro
676390795Sgshapiro	"_FFR_TRUSTED_QF",
6764285229Sgshapiro#endif
6765261194Sgshapiro#if _FFR_USE_GETPWNAM_ERRNO
6766261194Sgshapiro	/*
6767261194Sgshapiro	**  See libsm/mbdb.c: only enable this on OSs
6768261194Sgshapiro	**  that implement the correct (POSIX) semantics.
6769266527Sgshapiro	**  This will need to become an OS-specific #if enabled
6770266527Sgshapiro	**  in one of the headers files under include/sm/os/ .
6771261194Sgshapiro	*/
6772261194Sgshapiro
6773261194Sgshapiro	"_FFR_USE_GETPWNAM_ERRNO",
6774285229Sgshapiro#endif
6775363466Sgshapiro#if _FFR_VRFY_TRUSTED_FIRST
6776363466Sgshapiro	/*
6777363466Sgshapiro	**  Sets X509_V_FLAG_TRUSTED_FIRST if -d88;.101 is used.
6778363466Sgshapiro	**  X509_VERIFY_PARAM_set_flags(3)
6779363466Sgshapiro	**  When X509_V_FLAG_TRUSTED_FIRST is set, construction of the
6780363466Sgshapiro	**  certificate chain in X509_verify_cert(3) will search the trust
6781363466Sgshapiro	**  store for issuer certificates before searching the provided
6782363466Sgshapiro	**  untrusted certificates. Local issuer certificates are often more
6783363466Sgshapiro	**  likely to satisfy local security requirements and lead to a locally
6784363466Sgshapiro	**  trusted root. This is especially important when some certificates
6785363466Sgshapiro	**  in the trust store have explicit trust settings (see "TRUST
6786363466Sgshapiro	**  SETTINGS" in x509(1)).
6787363466Sgshapiro	**  As of OpenSSL 1.1.0 this option is on by default.
6788363466Sgshapiro	*/
6789363466Sgshapiro
6790363466Sgshapiro# if defined(X509_V_FLAG_TRUSTED_FIRST)
6791363466Sgshapiro	"_FFR_VRFY_TRUSTED_FIRST",
6792363466Sgshapiro# else
6793363466Sgshapiro#  error "FFR_VRFY_TRUSTED_FIRST set but X509_V_FLAG_TRUSTED_FIRST not defined"
6794363466Sgshapiro# endif
6795363466Sgshapiro#endif
6796363466Sgshapiro
6797147081Sgshapiro#if _FFR_USE_SEM_LOCKING
6798363466Sgshapiro	/* Use semaphore locking */
6799147081Sgshapiro	"_FFR_USE_SEM_LOCKING",
6800285229Sgshapiro#endif
680194337Sgshapiro#if _FFR_USE_SETLOGIN
6802112813Sgshapiro	/* Use setlogin() */
680394337Sgshapiro/* Peter Philipp */
680494337Sgshapiro	"_FFR_USE_SETLOGIN",
6805285229Sgshapiro#endif
6806285229Sgshapiro#if _FFR_XCNCT
6807363466Sgshapiro	/* X-Connect support */
6808285229Sgshapiro	"_FFR_XCNCT",
6809285229Sgshapiro#endif
6810363466Sgshapiro#if _FFR_EAI
6811363466Sgshapiro
6812363466Sgshapiro	/*
6813363466Sgshapiro	**  Initial/Partial/Experimental EAI (SMTPUTF8) support.
6814363466Sgshapiro	**  NOTE: This is currently BROKEN as the handling of
6815363466Sgshapiro	**  envelope addresses in sendmail is NOT 8-bit clean
6816363466Sgshapiro	**  (in contrast to header addresses/values).
6817363466Sgshapiro	**  Requires ICU include files and library depending on the OS.
6818363466Sgshapiro	**  Patch from Arnt Gulbrandsen.
6819363466Sgshapiro	*/
6820363466Sgshapiro
6821363466Sgshapiro# if !ALLOW_255
6822363466Sgshapiro#  ERROR FFR_EAI requires _ALLOW_255
6823363466Sgshapiro# endif
6824363466Sgshapiro# if _FFR_EIGHT_BIT_ADDR_OK
6825363466Sgshapiro#  error "Cannot enable both of these FFRs: FFR_EAI FFR_EIGHT_BIT_ADDR_OK"
6826363466Sgshapiro# endif
6827363466Sgshapiro	"_FFR_EAI",
6828363466Sgshapiro#endif
682990795Sgshapiro	NULL
683090795Sgshapiro};
6831