summaryrefslogtreecommitdiffstats
path: root/contrib/sendmail/src/conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'contrib/sendmail/src/conf.c')
-rw-r--r--contrib/sendmail/src/conf.c6376
1 files changed, 0 insertions, 6376 deletions
diff --git a/contrib/sendmail/src/conf.c b/contrib/sendmail/src/conf.c
deleted file mode 100644
index 0cbb88e..0000000
--- a/contrib/sendmail/src/conf.c
+++ /dev/null
@@ -1,6376 +0,0 @@
-/*
- * Copyright (c) 1998-2007 Sendmail, Inc. and its suppliers.
- * All rights reserved.
- * Copyright (c) 1983, 1995-1997 Eric P. Allman. All rights reserved.
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * By using this file, you agree to the terms and conditions set
- * forth in the LICENSE file which can be found at the top level of
- * the sendmail distribution.
- *
- */
-
-#include <sendmail.h>
-
-SM_RCSID("@(#)$Id: conf.c,v 8.1136 2007/10/10 00:06:45 ca Exp $")
-
-#include <sm/sendmail.h>
-#include <sendmail/pathnames.h>
-#if NEWDB
-# include "sm/bdb.h"
-#endif /* NEWDB */
-
-#include <daemon.h>
-#include "map.h"
-
-#ifdef DEC
-# if NETINET6
-/* for the IPv6 device lookup */
-# define _SOCKADDR_LEN
-# include <macros.h>
-# endif /* NETINET6 */
-#endif /* DEC */
-
-# include <sys/ioctl.h>
-# include <sys/param.h>
-
-#include <limits.h>
-#if NETINET || NETINET6
-# include <arpa/inet.h>
-#endif /* NETINET || NETINET6 */
-#if HASULIMIT && defined(HPUX11)
-# include <ulimit.h>
-#endif /* HASULIMIT && defined(HPUX11) */
-
-static void setupmaps __P((void));
-static void setupmailers __P((void));
-static void setupqueues __P((void));
-static int get_num_procs_online __P((void));
-static int add_hostnames __P((SOCKADDR *));
-
-#if NETINET6 && NEEDSGETIPNODE
-static struct hostent *getipnodebyname __P((char *, int, int, int *));
-static struct hostent *getipnodebyaddr __P((char *, int, int, int *));
-#endif /* NETINET6 && NEEDSGETIPNODE */
-
-
-/*
-** CONF.C -- Sendmail Configuration Tables.
-**
-** Defines the configuration of this installation.
-**
-** Configuration Variables:
-** HdrInfo -- a table describing well-known header fields.
-** Each entry has the field name and some flags,
-** which are described in sendmail.h.
-**
-** Notes:
-** I have tried to put almost all the reasonable
-** configuration information into the configuration
-** file read at runtime. My intent is that anything
-** here is a function of the version of UNIX you
-** are running, or is really static -- for example
-** the headers are a superset of widely used
-** protocols. If you find yourself playing with
-** this file too much, you may be making a mistake!
-*/
-
-
-/*
-** Header info table
-** Final (null) entry contains the flags used for any other field.
-**
-** Not all of these are actually handled specially by sendmail
-** at this time. They are included as placeholders, to let
-** you know that "someday" I intend to have sendmail do
-** something with them.
-*/
-
-struct hdrinfo HdrInfo[] =
-{
- /* originator fields, most to least significant */
- { "resent-sender", H_FROM|H_RESENT, NULL },
- { "resent-from", H_FROM|H_RESENT, NULL },
- { "resent-reply-to", H_FROM|H_RESENT, NULL },
- { "sender", H_FROM, NULL },
- { "from", H_FROM, NULL },
- { "reply-to", H_FROM, NULL },
- { "errors-to", H_FROM|H_ERRORSTO, NULL },
- { "full-name", H_ACHECK, NULL },
- { "return-receipt-to", H_RECEIPTTO, NULL },
- { "delivery-receipt-to", H_RECEIPTTO, NULL },
- { "disposition-notification-to", H_FROM, NULL },
-
- /* destination fields */
- { "to", H_RCPT, NULL },
- { "resent-to", H_RCPT|H_RESENT, NULL },
- { "cc", H_RCPT, NULL },
- { "resent-cc", H_RCPT|H_RESENT, NULL },
- { "bcc", H_RCPT|H_BCC, NULL },
- { "resent-bcc", H_RCPT|H_BCC|H_RESENT, NULL },
- { "apparently-to", H_RCPT, NULL },
-
- /* message identification and control */
- { "message-id", 0, NULL },
- { "resent-message-id", H_RESENT, NULL },
- { "message", H_EOH, NULL },
- { "text", H_EOH, NULL },
-
- /* date fields */
- { "date", 0, NULL },
- { "resent-date", H_RESENT, NULL },
-
- /* trace fields */
- { "received", H_TRACE|H_FORCE, NULL },
- { "x400-received", H_TRACE|H_FORCE, NULL },
- { "via", H_TRACE|H_FORCE, NULL },
- { "mail-from", H_TRACE|H_FORCE, NULL },
-
- /* miscellaneous fields */
- { "comments", H_FORCE|H_ENCODABLE, NULL },
- { "return-path", H_FORCE|H_ACHECK|H_BINDLATE, NULL },
- { "content-transfer-encoding", H_CTE, NULL },
- { "content-type", H_CTYPE, NULL },
- { "content-length", H_ACHECK, NULL },
- { "subject", H_ENCODABLE, NULL },
- { "x-authentication-warning", H_FORCE, NULL },
-
- { NULL, 0, NULL }
-};
-
-
-
-/*
-** Privacy values
-*/
-
-struct prival PrivacyValues[] =
-{
- { "public", PRIV_PUBLIC },
- { "needmailhelo", PRIV_NEEDMAILHELO },
- { "needexpnhelo", PRIV_NEEDEXPNHELO },
- { "needvrfyhelo", PRIV_NEEDVRFYHELO },
- { "noexpn", PRIV_NOEXPN },
- { "novrfy", PRIV_NOVRFY },
- { "restrictexpand", PRIV_RESTRICTEXPAND },
- { "restrictmailq", PRIV_RESTRICTMAILQ },
- { "restrictqrun", PRIV_RESTRICTQRUN },
- { "noetrn", PRIV_NOETRN },
- { "noverb", PRIV_NOVERB },
- { "authwarnings", PRIV_AUTHWARNINGS },
- { "noreceipts", PRIV_NORECEIPTS },
- { "nobodyreturn", PRIV_NOBODYRETN },
- { "goaway", PRIV_GOAWAY },
- { "noactualrecipient", PRIV_NOACTUALRECIPIENT },
- { NULL, 0 }
-};
-
-/*
-** DontBlameSendmail values
-*/
-
-struct dbsval DontBlameSendmailValues[] =
-{
- { "safe", DBS_SAFE },
- { "assumesafechown", DBS_ASSUMESAFECHOWN },
- { "groupwritabledirpathsafe", DBS_GROUPWRITABLEDIRPATHSAFE },
- { "groupwritableforwardfilesafe",
- DBS_GROUPWRITABLEFORWARDFILESAFE },
- { "groupwritableincludefilesafe",
- DBS_GROUPWRITABLEINCLUDEFILESAFE },
- { "groupwritablealiasfile", DBS_GROUPWRITABLEALIASFILE },
- { "worldwritablealiasfile", DBS_WORLDWRITABLEALIASFILE },
- { "forwardfileinunsafedirpath", DBS_FORWARDFILEINUNSAFEDIRPATH },
- { "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH },
- { "mapinunsafedirpath", DBS_MAPINUNSAFEDIRPATH },
- { "linkedaliasfileinwritabledir",
- DBS_LINKEDALIASFILEINWRITABLEDIR },
- { "linkedclassfileinwritabledir",
- DBS_LINKEDCLASSFILEINWRITABLEDIR },
- { "linkedforwardfileinwritabledir",
- DBS_LINKEDFORWARDFILEINWRITABLEDIR },
- { "linkedincludefileinwritabledir",
- DBS_LINKEDINCLUDEFILEINWRITABLEDIR },
- { "linkedmapinwritabledir", DBS_LINKEDMAPINWRITABLEDIR },
- { "linkedserviceswitchfileinwritabledir",
- DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR },
- { "filedeliverytohardlink", DBS_FILEDELIVERYTOHARDLINK },
- { "filedeliverytosymlink", DBS_FILEDELIVERYTOSYMLINK },
- { "writemaptohardlink", DBS_WRITEMAPTOHARDLINK },
- { "writemaptosymlink", DBS_WRITEMAPTOSYMLINK },
- { "writestatstohardlink", DBS_WRITESTATSTOHARDLINK },
- { "writestatstosymlink", DBS_WRITESTATSTOSYMLINK },
- { "forwardfileingroupwritabledirpath",
- DBS_FORWARDFILEINGROUPWRITABLEDIRPATH },
- { "includefileingroupwritabledirpath",
- DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH },
- { "classfileinunsafedirpath", DBS_CLASSFILEINUNSAFEDIRPATH },
- { "errorheaderinunsafedirpath", DBS_ERRORHEADERINUNSAFEDIRPATH },
- { "helpfileinunsafedirpath", DBS_HELPFILEINUNSAFEDIRPATH },
- { "forwardfileinunsafedirpathsafe",
- DBS_FORWARDFILEINUNSAFEDIRPATHSAFE },
- { "includefileinunsafedirpathsafe",
- DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE },
- { "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH },
- { "runwritableprogram", DBS_RUNWRITABLEPROGRAM },
- { "nonrootsafeaddr", DBS_NONROOTSAFEADDR },
- { "truststickybit", DBS_TRUSTSTICKYBIT },
- { "dontwarnforwardfileinunsafedirpath",
- DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH },
- { "insufficiententropy", DBS_INSUFFICIENTENTROPY },
- { "groupreadablesasldbfile", DBS_GROUPREADABLESASLDBFILE },
- { "groupwritablesasldbfile", DBS_GROUPWRITABLESASLDBFILE },
- { "groupwritableforwardfile", DBS_GROUPWRITABLEFORWARDFILE },
- { "groupwritableincludefile", DBS_GROUPWRITABLEINCLUDEFILE },
- { "worldwritableforwardfile", DBS_WORLDWRITABLEFORWARDFILE },
- { "worldwritableincludefile", DBS_WORLDWRITABLEINCLUDEFILE },
- { "groupreadablekeyfile", DBS_GROUPREADABLEKEYFILE },
-#if _FFR_GROUPREADABLEAUTHINFOFILE
- { "groupreadableadefaultauthinfofile",
- DBS_GROUPREADABLEAUTHINFOFILE },
-#endif /* _FFR_GROUPREADABLEAUTHINFOFILE */
- { NULL, 0 }
-};
-
-/*
-** Miscellaneous stuff.
-*/
-
-int DtableSize = 50; /* max open files; reset in 4.2bsd */
-/*
-** SETDEFAULTS -- set default values
-**
-** Some of these must be initialized using direct code since they
-** depend on run-time values. So let's do all of them this way.
-**
-** Parameters:
-** e -- the default envelope.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Initializes a bunch of global variables to their
-** default values.
-*/
-
-#define MINUTES * 60
-#define HOURS * 60 MINUTES
-#define DAYS * 24 HOURS
-
-#ifndef MAXRULERECURSION
-# define MAXRULERECURSION 50 /* max ruleset recursion depth */
-#endif /* ! MAXRULERECURSION */
-
-void
-setdefaults(e)
- register ENVELOPE *e;
-{
- int i;
- int numprocs;
- struct passwd *pw;
-
- numprocs = get_num_procs_online();
- SpaceSub = ' '; /* option B */
- QueueLA = 8 * numprocs; /* option x */
- RefuseLA = 12 * numprocs; /* option X */
- WkRecipFact = 30000L; /* option y */
- WkClassFact = 1800L; /* option z */
- WkTimeFact = 90000L; /* option Z */
- QueueFactor = WkRecipFact * 20; /* option q */
- QueueMode = QM_NORMAL; /* what queue items to act upon */
- FileMode = (RealUid != geteuid()) ? 0644 : 0600;
- /* option F */
- QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600;
- /* option QueueFileMode */
-
- if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) ||
- ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) ||
- ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0))
- {
- DefUid = pw->pw_uid; /* option u */
- DefGid = pw->pw_gid; /* option g */
- DefUser = newstr(pw->pw_name);
- }
- else
- {
- DefUid = 1; /* option u */
- DefGid = 1; /* option g */
- setdefuser();
- }
- TrustedUid = 0;
- if (tTd(37, 4))
- sm_dprintf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%d\n",
- DefUser != NULL ? DefUser : "<1:1>",
- (int) DefUid, (int) DefGid);
- CheckpointInterval = 10; /* option C */
- MaxHopCount = 25; /* option h */
- set_delivery_mode(SM_FORK, e); /* option d */
- e->e_errormode = EM_PRINT; /* option e */
- e->e_qgrp = NOQGRP;
- e->e_qdir = NOQDIR;
- e->e_xfqgrp = NOQGRP;
- e->e_xfqdir = NOQDIR;
- e->e_ctime = curtime();
- SevenBitInput = false; /* option 7 */
- MaxMciCache = 1; /* option k */
- MciCacheTimeout = 5 MINUTES; /* option K */
- LogLevel = 9; /* option L */
-#if MILTER
- MilterLogLevel = -1;
-#endif /* MILTER */
- inittimeouts(NULL, false); /* option r */
- PrivacyFlags = PRIV_PUBLIC; /* option p */
- MeToo = true; /* option m */
- SendMIMEErrors = true; /* option f */
- SuperSafe = SAFE_REALLY; /* option s */
- clrbitmap(DontBlameSendmail); /* DontBlameSendmail option */
-#if MIME8TO7
- MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */
-#else /* MIME8TO7 */
- MimeMode = MM_PASS8BIT;
-#endif /* MIME8TO7 */
- for (i = 0; i < MAXTOCLASS; i++)
- {
- TimeOuts.to_q_return[i] = 5 DAYS; /* option T */
- TimeOuts.to_q_warning[i] = 0; /* option T */
- }
- ServiceSwitchFile = "/etc/mail/service.switch";
- ServiceCacheMaxAge = (time_t) 10;
- HostsFile = _PATH_HOSTS;
- PidFile = newstr(_PATH_SENDMAILPID);
- MustQuoteChars = "@,;:\\()[].'";
- MciInfoTimeout = 30 MINUTES;
- MaxRuleRecursion = MAXRULERECURSION;
- MaxAliasRecursion = 10;
- MaxMacroRecursion = 10;
- ColonOkInAddr = true;
- DontLockReadFiles = true;
- DontProbeInterfaces = DPI_PROBEALL;
- DoubleBounceAddr = "postmaster";
- MaxHeadersLength = MAXHDRSLEN;
- MaxMimeHeaderLength = MAXLINE;
- MaxMimeFieldLength = MaxMimeHeaderLength / 2;
- MaxForwardEntries = 0;
- FastSplit = 1;
- MaxNOOPCommands = MAXNOOPCOMMANDS;
-#if SASL
- AuthMechanisms = newstr(AUTH_MECHANISMS);
- AuthRealm = NULL;
- MaxSLBits = INT_MAX;
-#endif /* SASL */
-#if STARTTLS
- TLS_Srv_Opts = TLS_I_SRV;
-#endif /* STARTTLS */
-#ifdef HESIOD_INIT
- HesiodContext = NULL;
-#endif /* HESIOD_INIT */
-#if NETINET6
- /* Detect if IPv6 is available at run time */
- i = socket(AF_INET6, SOCK_STREAM, 0);
- if (i >= 0)
- {
- InetMode = AF_INET6;
- (void) close(i);
- }
- else
- InetMode = AF_INET;
-#else /* NETINET6 */
- InetMode = AF_INET;
-#endif /* NETINET6 */
- ControlSocketName = NULL;
- memset(&ConnectOnlyTo, '\0', sizeof(ConnectOnlyTo));
- DataFileBufferSize = 4096;
- XscriptFileBufferSize = 4096;
- for (i = 0; i < MAXRWSETS; i++)
- RuleSetNames[i] = NULL;
-#if MILTER
- InputFilters[0] = NULL;
-#endif /* MILTER */
- RejectLogInterval = 3 HOURS;
-#if REQUIRES_DIR_FSYNC
- RequiresDirfsync = true;
-#endif /* REQUIRES_DIR_FSYNC */
- ConnectionRateWindowSize = 60;
- setupmaps();
- setupqueues();
- setupmailers();
- setupheaders();
-}
-
-
-/*
-** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
-*/
-
-void
-setdefuser()
-{
- struct passwd *defpwent;
- static char defuserbuf[40];
-
- DefUser = defuserbuf;
- defpwent = sm_getpwuid(DefUid);
- (void) sm_strlcpy(defuserbuf,
- (defpwent == NULL || defpwent->pw_name == NULL)
- ? "nobody" : defpwent->pw_name,
- sizeof(defuserbuf));
- if (tTd(37, 4))
- sm_dprintf("setdefuser: DefUid=%d, DefUser=%s\n",
- (int) DefUid, DefUser);
-}
-/*
-** SETUPQUEUES -- initialize default queues
-**
-** The mqueue QUEUE structure gets filled in after readcf() but
-** we need something to point to now for the mailer setup,
-** which use "mqueue" as default queue.
-*/
-
-static void
-setupqueues()
-{
- char buf[100];
-
- MaxRunnersPerQueue = 1;
- (void) sm_strlcpy(buf, "mqueue, P=/var/spool/mqueue", sizeof(buf));
- makequeue(buf, false);
-}
-/*
-** SETUPMAILERS -- initialize default mailers
-*/
-
-static void
-setupmailers()
-{
- char buf[100];
-
- (void) sm_strlcpy(buf, "prog, P=/bin/sh, F=lsouDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u",
- sizeof(buf));
- makemailer(buf);
-
- (void) sm_strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE \201u",
- sizeof(buf));
- makemailer(buf);
-
- (void) sm_strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u",
- sizeof(buf));
- makemailer(buf);
- initerrmailers();
-}
-/*
-** SETUPMAPS -- set up map classes
-*/
-
-#define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \
- { \
- extern bool parse __P((MAP *, char *)); \
- extern bool open __P((MAP *, int)); \
- extern void close __P((MAP *)); \
- extern char *lookup __P((MAP *, char *, char **, int *)); \
- extern void store __P((MAP *, char *, char *)); \
- s = stab(name, ST_MAPCLASS, ST_ENTER); \
- s->s_mapclass.map_cname = name; \
- s->s_mapclass.map_ext = ext; \
- s->s_mapclass.map_cflags = flags; \
- s->s_mapclass.map_parse = parse; \
- s->s_mapclass.map_open = open; \
- s->s_mapclass.map_close = close; \
- s->s_mapclass.map_lookup = lookup; \
- s->s_mapclass.map_store = store; \
- }
-
-static void
-setupmaps()
-{
- register STAB *s;
-
-#if NEWDB
-# if DB_VERSION_MAJOR > 1
- int major_v, minor_v, patch_v;
-
- (void) db_version(&major_v, &minor_v, &patch_v);
- if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR)
- {
- errno = 0;
- syserr("Berkeley DB version mismatch: compiled against %d.%d.%d, run-time linked against %d.%d.%d",
- DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH,
- major_v, minor_v, patch_v);
- }
-# endif /* DB_VERSION_MAJOR > 1 */
-
- MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
- map_parseargs, hash_map_open, db_map_close,
- db_map_lookup, db_map_store);
-
- MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
- map_parseargs, bt_map_open, db_map_close,
- db_map_lookup, db_map_store);
-#endif /* NEWDB */
-
-#if NDBM
- MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE,
- map_parseargs, ndbm_map_open, ndbm_map_close,
- ndbm_map_lookup, ndbm_map_store);
-#endif /* NDBM */
-
-#if NIS
- MAPDEF("nis", NULL, MCF_ALIASOK,
- map_parseargs, nis_map_open, null_map_close,
- nis_map_lookup, null_map_store);
-#endif /* NIS */
-
-#if NISPLUS
- MAPDEF("nisplus", NULL, MCF_ALIASOK,
- map_parseargs, nisplus_map_open, null_map_close,
- nisplus_map_lookup, null_map_store);
-#endif /* NISPLUS */
-
-#if LDAPMAP
- MAPDEF("ldap", NULL, MCF_ALIASOK|MCF_NOTPERSIST,
- ldapmap_parseargs, ldapmap_open, ldapmap_close,
- ldapmap_lookup, null_map_store);
-#endif /* LDAPMAP */
-
-#if PH_MAP
- MAPDEF("ph", NULL, MCF_NOTPERSIST,
- ph_map_parseargs, ph_map_open, ph_map_close,
- ph_map_lookup, null_map_store);
-#endif /* PH_MAP */
-
-#if MAP_NSD
- /* IRIX 6.5 nsd support */
- MAPDEF("nsd", NULL, MCF_ALIASOK,
- map_parseargs, null_map_open, null_map_close,
- nsd_map_lookup, null_map_store);
-#endif /* MAP_NSD */
-
-#if HESIOD
- MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY,
- map_parseargs, hes_map_open, hes_map_close,
- hes_map_lookup, null_map_store);
-#endif /* HESIOD */
-
-#if NETINFO
- MAPDEF("netinfo", NULL, MCF_ALIASOK,
- map_parseargs, ni_map_open, null_map_close,
- ni_map_lookup, null_map_store);
-#endif /* NETINFO */
-
-#if 0
- MAPDEF("dns", NULL, 0,
- dns_map_init, null_map_open, null_map_close,
- dns_map_lookup, null_map_store);
-#endif /* 0 */
-
-#if NAMED_BIND
-# if DNSMAP
-# if _FFR_DNSMAP_ALIASABLE
- MAPDEF("dns", NULL, MCF_ALIASOK,
- dns_map_parseargs, dns_map_open, null_map_close,
- dns_map_lookup, null_map_store);
-# else /* _FFR_DNSMAP_ALIASABLE */
- MAPDEF("dns", NULL, 0,
- dns_map_parseargs, dns_map_open, null_map_close,
- dns_map_lookup, null_map_store);
-# endif /* _FFR_DNSMAP_ALIASABLE */
-# endif /* DNSMAP */
-#endif /* NAMED_BIND */
-
-#if NAMED_BIND
- /* best MX DNS lookup */
- MAPDEF("bestmx", NULL, MCF_OPTFILE,
- map_parseargs, null_map_open, null_map_close,
- bestmx_map_lookup, null_map_store);
-#endif /* NAMED_BIND */
-
- MAPDEF("host", NULL, 0,
- host_map_init, null_map_open, null_map_close,
- host_map_lookup, null_map_store);
-
- MAPDEF("text", NULL, MCF_ALIASOK,
- map_parseargs, text_map_open, null_map_close,
- text_map_lookup, null_map_store);
-
- MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY,
- map_parseargs, stab_map_open, null_map_close,
- stab_map_lookup, stab_map_store);
-
- MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE,
- map_parseargs, impl_map_open, impl_map_close,
- impl_map_lookup, impl_map_store);
-
- /* access to system passwd file */
- MAPDEF("user", NULL, MCF_OPTFILE,
- map_parseargs, user_map_open, null_map_close,
- user_map_lookup, null_map_store);
-
- /* dequote map */
- MAPDEF("dequote", NULL, 0,
- dequote_init, null_map_open, null_map_close,
- dequote_map, null_map_store);
-
-#if MAP_REGEX
- MAPDEF("regex", NULL, 0,
- regex_map_init, null_map_open, null_map_close,
- regex_map_lookup, null_map_store);
-#endif /* MAP_REGEX */
-
-#if USERDB
- /* user database */
- MAPDEF("userdb", ".db", 0,
- map_parseargs, null_map_open, null_map_close,
- udb_map_lookup, null_map_store);
-#endif /* USERDB */
-
- /* arbitrary programs */
- MAPDEF("program", NULL, MCF_ALIASOK,
- map_parseargs, null_map_open, null_map_close,
- prog_map_lookup, null_map_store);
-
- /* sequenced maps */
- MAPDEF("sequence", NULL, MCF_ALIASOK,
- seq_map_parse, null_map_open, null_map_close,
- seq_map_lookup, seq_map_store);
-
- /* switched interface to sequenced maps */
- MAPDEF("switch", NULL, MCF_ALIASOK,
- map_parseargs, switch_map_open, null_map_close,
- seq_map_lookup, seq_map_store);
-
- /* null map lookup -- really for internal use only */
- MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE,
- map_parseargs, null_map_open, null_map_close,
- null_map_lookup, null_map_store);
-
- /* syslog map -- logs information to syslog */
- MAPDEF("syslog", NULL, 0,
- syslog_map_parseargs, null_map_open, null_map_close,
- syslog_map_lookup, null_map_store);
-
- /* macro storage map -- rulesets can set macros */
- MAPDEF("macro", NULL, 0,
- dequote_init, null_map_open, null_map_close,
- macro_map_lookup, null_map_store);
-
- /* arithmetic map -- add/subtract/compare */
- MAPDEF("arith", NULL, 0,
- dequote_init, null_map_open, null_map_close,
- arith_map_lookup, null_map_store);
-
-#if SOCKETMAP
- /* arbitrary daemons */
- MAPDEF("socket", NULL, MCF_ALIASOK,
- map_parseargs, socket_map_open, socket_map_close,
- socket_map_lookup, null_map_store);
-#endif /* SOCKETMAP */
-
-#if _FFR_DPRINTF_MAP
- /* dprintf map -- logs information to syslog */
- MAPDEF("dprintf", NULL, 0,
- dprintf_map_parseargs, null_map_open, null_map_close,
- dprintf_map_lookup, null_map_store);
-#endif /* _FFR_DPRINTF_MAP */
-
- if (tTd(38, 2))
- {
- /* bogus map -- always return tempfail */
- MAPDEF("bogus", NULL, MCF_ALIASOK|MCF_OPTFILE,
- map_parseargs, null_map_open, null_map_close,
- bogus_map_lookup, null_map_store);
- }
-}
-
-#undef MAPDEF
-/*
-** INITHOSTMAPS -- initial host-dependent maps
-**
-** This should act as an interface to any local service switch
-** provided by the host operating system.
-**
-** Parameters:
-** none
-**
-** Returns:
-** none
-**
-** Side Effects:
-** Should define maps "host" and "users" as necessary
-** for this OS. If they are not defined, they will get
-** a default value later. It should check to make sure
-** they are not defined first, since it's possible that
-** the config file has provided an override.
-*/
-
-void
-inithostmaps()
-{
- register int i;
- int nmaps;
- char *maptype[MAXMAPSTACK];
- short mapreturn[MAXMAPACTIONS];
- char buf[MAXLINE];
-
- /*
- ** Make sure we have a host map.
- */
-
- if (stab("host", ST_MAP, ST_FIND) == NULL)
- {
- /* user didn't initialize: set up host map */
- (void) sm_strlcpy(buf, "host host", sizeof(buf));
-#if NAMED_BIND
- if (ConfigLevel >= 2)
- (void) sm_strlcat(buf, " -a. -D", sizeof(buf));
-#endif /* NAMED_BIND */
- (void) makemapentry(buf);
- }
-
- /*
- ** Set up default aliases maps
- */
-
- nmaps = switch_map_find("aliases", maptype, mapreturn);
- for (i = 0; i < nmaps; i++)
- {
- if (strcmp(maptype[i], "files") == 0 &&
- stab("aliases.files", ST_MAP, ST_FIND) == NULL)
- {
- (void) sm_strlcpy(buf, "aliases.files null",
- sizeof(buf));
- (void) makemapentry(buf);
- }
-#if NISPLUS
- else if (strcmp(maptype[i], "nisplus") == 0 &&
- stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL)
- {
- (void) sm_strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir",
- sizeof(buf));
- (void) makemapentry(buf);
- }
-#endif /* NISPLUS */
-#if NIS
- else if (strcmp(maptype[i], "nis") == 0 &&
- stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
- {
- (void) sm_strlcpy(buf, "aliases.nis nis mail.aliases",
- sizeof(buf));
- (void) makemapentry(buf);
- }
-#endif /* NIS */
-#if NETINFO
- else if (strcmp(maptype[i], "netinfo") == 0 &&
- stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
- {
- (void) sm_strlcpy(buf, "aliases.netinfo netinfo -z, /aliases",
- sizeof(buf));
- (void) makemapentry(buf);
- }
-#endif /* NETINFO */
-#if HESIOD
- else if (strcmp(maptype[i], "hesiod") == 0 &&
- stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL)
- {
- (void) sm_strlcpy(buf, "aliases.hesiod hesiod aliases",
- sizeof(buf));
- (void) makemapentry(buf);
- }
-#endif /* HESIOD */
-#if LDAPMAP && defined(SUN_EXTENSIONS) && \
- defined(SUN_SIMPLIFIED_LDAP) && HASLDAPGETALIASBYNAME
- else if (strcmp(maptype[i], "ldap") == 0 &&
- stab("aliases.ldap", ST_MAP, ST_FIND) == NULL)
- {
- (void) strlcpy(buf, "aliases.ldap ldap -b . -h localhost -k mail=%0 -v mailgroup",
- sizeof buf);
- (void) makemapentry(buf);
- }
-#endif /* LDAPMAP && defined(SUN_EXTENSIONS) && ... */
- }
- if (stab("aliases", ST_MAP, ST_FIND) == NULL)
- {
- (void) sm_strlcpy(buf, "aliases switch aliases", sizeof(buf));
- (void) makemapentry(buf);
- }
-}
-
-/*
-** SWITCH_MAP_FIND -- find the list of types associated with a map
-**
-** This is the system-dependent interface to the service switch.
-**
-** Parameters:
-** service -- the name of the service of interest.
-** maptype -- an out-array of strings containing the types
-** of access to use for this service. There can
-** be at most MAXMAPSTACK types for a single service.
-** mapreturn -- an out-array of return information bitmaps
-** for the map.
-**
-** Returns:
-** The number of map types filled in, or -1 for failure.
-**
-** Side effects:
-** Preserves errno so nothing in the routine clobbers it.
-*/
-
-#if defined(SOLARIS) || (defined(sony_news) && defined(__svr4))
-# define _USE_SUN_NSSWITCH_
-#endif /* defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) */
-
-#if _FFR_HPUX_NSSWITCH
-# ifdef __hpux
-# define _USE_SUN_NSSWITCH_
-# endif /* __hpux */
-#endif /* _FFR_HPUX_NSSWITCH */
-
-#ifdef _USE_SUN_NSSWITCH_
-# include <nsswitch.h>
-#endif /* _USE_SUN_NSSWITCH_ */
-
-#if defined(ultrix) || (defined(__osf__) && defined(__alpha))
-# define _USE_DEC_SVC_CONF_
-#endif /* defined(ultrix) || (defined(__osf__) && defined(__alpha)) */
-
-#ifdef _USE_DEC_SVC_CONF_
-# include <sys/svcinfo.h>
-#endif /* _USE_DEC_SVC_CONF_ */
-
-int
-switch_map_find(service, maptype, mapreturn)
- char *service;
- char *maptype[MAXMAPSTACK];
- short mapreturn[MAXMAPACTIONS];
-{
- int svcno = 0;
- int save_errno = errno;
-
-#ifdef _USE_SUN_NSSWITCH_
- struct __nsw_switchconfig *nsw_conf;
- enum __nsw_parse_err pserr;
- struct __nsw_lookup *lk;
- static struct __nsw_lookup lkp0 =
- { "files", {1, 0, 0, 0}, NULL, NULL };
- static struct __nsw_switchconfig lkp_default =
- { 0, "sendmail", 3, &lkp0 };
-
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
-
- if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL)
- lk = lkp_default.lookups;
- else
- lk = nsw_conf->lookups;
- svcno = 0;
- while (lk != NULL && svcno < MAXMAPSTACK)
- {
- maptype[svcno] = lk->service_name;
- if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN)
- mapreturn[MA_NOTFOUND] |= 1 << svcno;
- if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN)
- mapreturn[MA_TRYAGAIN] |= 1 << svcno;
- if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN)
- mapreturn[MA_TRYAGAIN] |= 1 << svcno;
- svcno++;
- lk = lk->next;
- }
- errno = save_errno;
- return svcno;
-#endif /* _USE_SUN_NSSWITCH_ */
-
-#ifdef _USE_DEC_SVC_CONF_
- struct svcinfo *svcinfo;
- int svc;
-
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
-
- svcinfo = getsvc();
- if (svcinfo == NULL)
- goto punt;
- if (strcmp(service, "hosts") == 0)
- svc = SVC_HOSTS;
- else if (strcmp(service, "aliases") == 0)
- svc = SVC_ALIASES;
- else if (strcmp(service, "passwd") == 0)
- svc = SVC_PASSWD;
- else
- {
- errno = save_errno;
- return -1;
- }
- for (svcno = 0; svcno < SVC_PATHSIZE && svcno < MAXMAPSTACK; svcno++)
- {
- switch (svcinfo->svcpath[svc][svcno])
- {
- case SVC_LOCAL:
- maptype[svcno] = "files";
- break;
-
- case SVC_YP:
- maptype[svcno] = "nis";
- break;
-
- case SVC_BIND:
- maptype[svcno] = "dns";
- break;
-
-# ifdef SVC_HESIOD
- case SVC_HESIOD:
- maptype[svcno] = "hesiod";
- break;
-# endif /* SVC_HESIOD */
-
- case SVC_LAST:
- errno = save_errno;
- return svcno;
- }
- }
- errno = save_errno;
- return svcno;
-#endif /* _USE_DEC_SVC_CONF_ */
-
-#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
- /*
- ** Fall-back mechanism.
- */
-
- STAB *st;
- static time_t servicecachetime; /* time service switch was cached */
- time_t now = curtime();
-
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
-
- if ((now - servicecachetime) > (time_t) ServiceCacheMaxAge)
- {
- /* (re)read service switch */
- register SM_FILE_T *fp;
- long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK;
-
- if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR,
- DontBlameSendmail))
- sff |= SFF_NOWLINK;
-
- if (ConfigFileRead)
- servicecachetime = now;
- fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff);
- if (fp != NULL)
- {
- char buf[MAXLINE];
-
- while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf,
- sizeof(buf)) != NULL)
- {
- register char *p;
-
- p = strpbrk(buf, "#\n");
- if (p != NULL)
- *p = '\0';
- p = strpbrk(buf, " \t");
- if (p != NULL)
- *p++ = '\0';
- if (buf[0] == '\0')
- continue;
- if (p == NULL)
- {
- sm_syslog(LOG_ERR, NOQID,
- "Bad line on %.100s: %.100s",
- ServiceSwitchFile,
- buf);
- continue;
- }
- while (isspace(*p))
- p++;
- if (*p == '\0')
- continue;
-
- /*
- ** Find/allocate space for this service entry.
- ** Space for all of the service strings
- ** are allocated at once. This means
- ** that we only have to free the first
- ** one to free all of them.
- */
-
- st = stab(buf, ST_SERVICE, ST_ENTER);
- if (st->s_service[0] != NULL)
- sm_free((void *) st->s_service[0]); /* XXX */
- p = newstr(p);
- for (svcno = 0; svcno < MAXMAPSTACK; )
- {
- if (*p == '\0')
- break;
- st->s_service[svcno++] = p;
- p = strpbrk(p, " \t");
- if (p == NULL)
- break;
- *p++ = '\0';
- while (isspace(*p))
- p++;
- }
- if (svcno < MAXMAPSTACK)
- st->s_service[svcno] = NULL;
- }
- (void) sm_io_close(fp, SM_TIME_DEFAULT);
- }
- }
-
- /* look up entry in cache */
- st = stab(service, ST_SERVICE, ST_FIND);
- if (st != NULL && st->s_service[0] != NULL)
- {
- /* extract data */
- svcno = 0;
- while (svcno < MAXMAPSTACK)
- {
- maptype[svcno] = st->s_service[svcno];
- if (maptype[svcno++] == NULL)
- break;
- }
- errno = save_errno;
- return --svcno;
- }
-#endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */
-
-#if !defined(_USE_SUN_NSSWITCH_)
- /* if the service file doesn't work, use an absolute fallback */
-# ifdef _USE_DEC_SVC_CONF_
- punt:
-# endif /* _USE_DEC_SVC_CONF_ */
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
- svcno = 0;
- if (strcmp(service, "aliases") == 0)
- {
- maptype[svcno++] = "files";
-# if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO)
- maptype[svcno++] = "netinfo";
-# endif /* defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) */
-# ifdef AUTO_NIS_ALIASES
-# if NISPLUS
- maptype[svcno++] = "nisplus";
-# endif /* NISPLUS */
-# if NIS
- maptype[svcno++] = "nis";
-# endif /* NIS */
-# endif /* AUTO_NIS_ALIASES */
- errno = save_errno;
- return svcno;
- }
- if (strcmp(service, "hosts") == 0)
- {
-# if NAMED_BIND
- maptype[svcno++] = "dns";
-# else /* NAMED_BIND */
-# if defined(sun) && !defined(BSD)
- /* SunOS */
- maptype[svcno++] = "nis";
-# endif /* defined(sun) && !defined(BSD) */
-# endif /* NAMED_BIND */
-# if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO)
- maptype[svcno++] = "netinfo";
-# endif /* defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) */
- maptype[svcno++] = "files";
- errno = save_errno;
- return svcno;
- }
- errno = save_errno;
- return -1;
-#endif /* !defined(_USE_SUN_NSSWITCH_) */
-}
-/*
-** USERNAME -- return the user id of the logged in user.
-**
-** Parameters:
-** none.
-**
-** Returns:
-** The login name of the logged in user.
-**
-** Side Effects:
-** none.
-**
-** Notes:
-** The return value is statically allocated.
-*/
-
-char *
-username()
-{
- static char *myname = NULL;
- extern char *getlogin();
- register struct passwd *pw;
-
- /* cache the result */
- if (myname == NULL)
- {
- myname = getlogin();
- if (myname == NULL || myname[0] == '\0')
- {
- pw = sm_getpwuid(RealUid);
- if (pw != NULL)
- myname = pw->pw_name;
- }
- else
- {
- uid_t uid = RealUid;
-
- if ((pw = sm_getpwnam(myname)) == NULL ||
- (uid != 0 && uid != pw->pw_uid))
- {
- pw = sm_getpwuid(uid);
- if (pw != NULL)
- myname = pw->pw_name;
- }
- }
- if (myname == NULL || myname[0] == '\0')
- {
- syserr("554 5.3.0 Who are you?");
- myname = "postmaster";
- }
- else if (strpbrk(myname, ",;:/|\"\\") != NULL)
- myname = addquotes(myname, NULL);
- else
- myname = sm_pstrdup_x(myname);
- }
- return myname;
-}
-/*
-** TTYPATH -- Get the path of the user's tty
-**
-** Returns the pathname of the user's tty. Returns NULL if
-** the user is not logged in or if s/he has write permission
-** denied.
-**
-** Parameters:
-** none
-**
-** Returns:
-** pathname of the user's tty.
-** NULL if not logged in or write permission denied.
-**
-** Side Effects:
-** none.
-**
-** WARNING:
-** Return value is in a local buffer.
-**
-** Called By:
-** savemail
-*/
-
-char *
-ttypath()
-{
- struct stat stbuf;
- register char *pathn;
- extern char *ttyname();
- extern char *getlogin();
-
- /* compute the pathname of the controlling tty */
- if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
- (pathn = ttyname(0)) == NULL)
- {
- errno = 0;
- return NULL;
- }
-
- /* see if we have write permission */
- if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode))
- {
- errno = 0;
- return NULL;
- }
-
- /* see if the user is logged in */
- if (getlogin() == NULL)
- return NULL;
-
- /* looks good */
- return pathn;
-}
-/*
-** CHECKCOMPAT -- check for From and To person compatible.
-**
-** This routine can be supplied on a per-installation basis
-** to determine whether a person is allowed to send a message.
-** This allows restriction of certain types of internet
-** forwarding or registration of users.
-**
-** If the hosts are found to be incompatible, an error
-** message should be given using "usrerr" and an EX_ code
-** should be returned. You can also set to->q_status to
-** a DSN-style status code.
-**
-** EF_NO_BODY_RETN can be set in e->e_flags to suppress the
-** body during the return-to-sender function; this should be done
-** on huge messages. This bit may already be set by the ESMTP
-** protocol.
-**
-** Parameters:
-** to -- the person being sent to.
-**
-** Returns:
-** an exit status
-**
-** Side Effects:
-** none (unless you include the usrerr stuff)
-*/
-
-int
-checkcompat(to, e)
- register ADDRESS *to;
- register ENVELOPE *e;
-{
- if (tTd(49, 1))
- sm_dprintf("checkcompat(to=%s, from=%s)\n",
- to->q_paddr, e->e_from.q_paddr);
-
-#ifdef EXAMPLE_CODE
- /* this code is intended as an example only */
- register STAB *s;
-
- s = stab("arpa", ST_MAILER, ST_FIND);
- if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 &&
- to->q_mailer == s->s_mailer)
- {
- usrerr("553 No ARPA mail through this machine: see your system administration");
- /* e->e_flags |= EF_NO_BODY_RETN; to suppress body on return */
- to->q_status = "5.7.1";
- return EX_UNAVAILABLE;
- }
-#endif /* EXAMPLE_CODE */
- return EX_OK;
-}
-
-#ifdef SUN_EXTENSIONS
-static void
-init_md_sun()
-{
- struct stat sbuf;
-
- /* Check for large file descriptor */
- if (fstat(fileno(stdin), &sbuf) < 0)
- {
- if (errno == EOVERFLOW)
- {
- perror("stdin");
- exit(EX_NOINPUT);
- }
- }
-}
-#endif /* SUN_EXTENSIONS */
-
-/*
-** INIT_MD -- do machine dependent initializations
-**
-** Systems that have global modes that should be set should do
-** them here rather than in main.
-*/
-
-#ifdef _AUX_SOURCE
-# include <compat.h>
-#endif /* _AUX_SOURCE */
-
-#if SHARE_V1
-# include <shares.h>
-#endif /* SHARE_V1 */
-
-void
-init_md(argc, argv)
- int argc;
- char **argv;
-{
-#ifdef _AUX_SOURCE
- setcompat(getcompat() | COMPAT_BSDPROT);
-#endif /* _AUX_SOURCE */
-
-#ifdef SUN_EXTENSIONS
- init_md_sun();
-#endif /* SUN_EXTENSIONS */
-
-#if _CONVEX_SOURCE
- /* keep gethostby*() from stripping the local domain name */
- set_domain_trim_off();
-#endif /* _CONVEX_SOURCE */
-#if defined(__QNX__) && !defined(__QNXNTO__)
- /*
- ** Due to QNX's network distributed nature, you can target a tcpip
- ** stack on a different node in the qnx network; this patch lets
- ** this feature work. The __sock_locate() must be done before the
- ** environment is clear.
- */
- __sock_locate();
-#endif /* __QNX__ */
-#if SECUREWARE || defined(_SCO_unix_)
- set_auth_parameters(argc, argv);
-
-# ifdef _SCO_unix_
- /*
- ** This is required for highest security levels (the kernel
- ** won't let it call set*uid() or run setuid binaries without
- ** it). It may be necessary on other SECUREWARE systems.
- */
-
- if (getluid() == -1)
- setluid(0);
-# endif /* _SCO_unix_ */
-#endif /* SECUREWARE || defined(_SCO_unix_) */
-
-
-#ifdef VENDOR_DEFAULT
- VendorCode = VENDOR_DEFAULT;
-#else /* VENDOR_DEFAULT */
- VendorCode = VENDOR_BERKELEY;
-#endif /* VENDOR_DEFAULT */
-}
-/*
-** INIT_VENDOR_MACROS -- vendor-dependent macro initializations
-**
-** Called once, on startup.
-**
-** Parameters:
-** e -- the global envelope.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** vendor-dependent.
-*/
-
-void
-init_vendor_macros(e)
- register ENVELOPE *e;
-{
-}
-/*
-** GETLA -- get the current load average
-**
-** This code stolen from la.c.
-**
-** Parameters:
-** none.
-**
-** Returns:
-** The current load average as an integer.
-**
-** Side Effects:
-** none.
-*/
-
-/* try to guess what style of load average we have */
-#define LA_ZERO 1 /* always return load average as zero */
-#define LA_INT 2 /* read kmem for avenrun; interpret as long */
-#define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */
-#define LA_SUBR 4 /* call getloadavg */
-#define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */
-#define LA_SHORT 6 /* read kmem for avenrun; interpret as short */
-#define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */
-#define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */
-#define LA_DGUX 9 /* special DGUX implementation */
-#define LA_HPUX 10 /* special HPUX implementation */
-#define LA_IRIX6 11 /* special IRIX 6.2 implementation */
-#define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */
-#define LA_DEVSHORT 13 /* read short from a device */
-#define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */
-#define LA_PSET 15 /* Solaris per-processor-set load average */
-#define LA_LONGLONG 17 /* read kmem for avenrun; interpret as long long */
-
-/* do guesses based on general OS type */
-#ifndef LA_TYPE
-# define LA_TYPE LA_ZERO
-#endif /* ! LA_TYPE */
-
-#ifndef FSHIFT
-# if defined(unixpc)
-# define FSHIFT 5
-# endif /* defined(unixpc) */
-
-# if defined(__alpha) || defined(IRIX)
-# define FSHIFT 10
-# endif /* defined(__alpha) || defined(IRIX) */
-
-#endif /* ! FSHIFT */
-
-#ifndef FSHIFT
-# define FSHIFT 8
-#endif /* ! FSHIFT */
-
-#ifndef FSCALE
-# define FSCALE (1 << FSHIFT)
-#endif /* ! FSCALE */
-
-#ifndef LA_AVENRUN
-# ifdef SYSTEM5
-# define LA_AVENRUN "avenrun"
-# else /* SYSTEM5 */
-# define LA_AVENRUN "_avenrun"
-# endif /* SYSTEM5 */
-#endif /* ! LA_AVENRUN */
-
-/* _PATH_KMEM should be defined in <paths.h> */
-#ifndef _PATH_KMEM
-# define _PATH_KMEM "/dev/kmem"
-#endif /* ! _PATH_KMEM */
-
-#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG)
-
-# include <nlist.h>
-
-/* _PATH_UNIX should be defined in <paths.h> */
-# ifndef _PATH_UNIX
-# if defined(SYSTEM5)
-# define _PATH_UNIX "/unix"
-# else /* defined(SYSTEM5) */
-# define _PATH_UNIX "/vmunix"
-# endif /* defined(SYSTEM5) */
-# endif /* ! _PATH_UNIX */
-
-# ifdef _AUX_SOURCE
-struct nlist Nl[2];
-# else /* _AUX_SOURCE */
-struct nlist Nl[] =
-{
- { LA_AVENRUN },
- { 0 },
-};
-# endif /* _AUX_SOURCE */
-# define X_AVENRUN 0
-
-int
-getla()
-{
- int j;
- static int kmem = -1;
-# if LA_TYPE == LA_INT
- long avenrun[3];
-# else /* LA_TYPE == LA_INT */
-# if LA_TYPE == LA_SHORT
- short avenrun[3];
-# else
-# if LA_TYPE == LA_LONGLONG
- long long avenrun[3];
-# else /* LA_TYPE == LA_LONGLONG */
- double avenrun[3];
-# endif /* LA_TYPE == LA_LONGLONG */
-# endif /* LA_TYPE == LA_SHORT */
-# endif /* LA_TYPE == LA_INT */
- extern off_t lseek();
-
- if (kmem < 0)
- {
-# ifdef _AUX_SOURCE
- (void) sm_strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN,
- sizeof(Nl[X_AVENRUN].n_name));
- Nl[1].n_name[0] = '\0';
-# endif /* _AUX_SOURCE */
-
-# if defined(_AIX3) || defined(_AIX4)
- if (knlist(Nl, 1, sizeof(Nl[0])) < 0)
-# else /* defined(_AIX3) || defined(_AIX4) */
- if (nlist(_PATH_UNIX, Nl) < 0)
-# endif /* defined(_AIX3) || defined(_AIX4) */
- {
- if (tTd(3, 1))
- sm_dprintf("getla: nlist(%s): %s\n", _PATH_UNIX,
- sm_errstring(errno));
- return -1;
- }
- if (Nl[X_AVENRUN].n_value == 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: nlist(%s, %s) ==> 0\n",
- _PATH_UNIX, LA_AVENRUN);
- return -1;
- }
-# ifdef NAMELISTMASK
- Nl[X_AVENRUN].n_value &= NAMELISTMASK;
-# endif /* NAMELISTMASK */
-
- kmem = open(_PATH_KMEM, 0, 0);
- if (kmem < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: open(/dev/kmem): %s\n",
- sm_errstring(errno));
- return -1;
- }
- if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
- fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
- sm_errstring(errno));
- (void) close(kmem);
- kmem = -1;
- return -1;
- }
- }
- if (tTd(3, 20))
- sm_dprintf("getla: symbol address = %#lx\n",
- (unsigned long) Nl[X_AVENRUN].n_value);
- if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 ||
- read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
- {
- /* thank you Ian */
- if (tTd(3, 1))
- sm_dprintf("getla: lseek or read: %s\n",
- sm_errstring(errno));
- return -1;
- }
-# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG)
- if (tTd(3, 5))
- {
-# if LA_TYPE == LA_SHORT
- sm_dprintf("getla: avenrun = %d", avenrun[0]);
- if (tTd(3, 15))
- sm_dprintf(", %d, %d", avenrun[1], avenrun[2]);
-# else /* LA_TYPE == LA_SHORT */
-# if LA_TYPE == LA_LONGLONG
- sm_dprintf("getla: avenrun = %lld", avenrun[0]);
- if (tTd(3, 15))
- sm_dprintf(", %lld, %lld", avenrun[1], avenrun[2]);
-# else /* LA_TYPE == LA_LONGLONG */
- sm_dprintf("getla: avenrun = %ld", avenrun[0]);
- if (tTd(3, 15))
- sm_dprintf(", %ld, %ld", avenrun[1], avenrun[2]);
-# endif /* LA_TYPE == LA_LONGLONG */
-# endif /* LA_TYPE == LA_SHORT */
- sm_dprintf("\n");
- }
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n",
- (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
-# else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
- if (tTd(3, 5))
- {
- sm_dprintf("getla: avenrun = %g", avenrun[0]);
- if (tTd(3, 15))
- sm_dprintf(", %g, %g", avenrun[1], avenrun[2]);
- sm_dprintf("\n");
- }
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
- return ((int) (avenrun[0] + 0.5));
-# endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
-}
-
-#endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */
-
-#if LA_TYPE == LA_READKSYM
-
-# include <sys/ksym.h>
-
-int
-getla()
-{
- int j;
- static int kmem = -1;
- long avenrun[3];
- struct mioc_rksym mirk;
-
- if (kmem < 0)
- {
- kmem = open("/dev/kmem", 0, 0);
- if (kmem < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: open(/dev/kmem): %s\n",
- sm_errstring(errno));
- return -1;
- }
- if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
- fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
- sm_errstring(errno));
- (void) close(kmem);
- kmem = -1;
- return -1;
- }
- }
- mirk.mirk_symname = LA_AVENRUN;
- mirk.mirk_buf = avenrun;
- mirk.mirk_buflen = sizeof(avenrun);
- if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n",
- sm_errstring(errno));
- return -1;
- }
- if (tTd(3, 5))
- {
- sm_dprintf("getla: avenrun = %d", avenrun[0]);
- if (tTd(3, 15))
- sm_dprintf(", %d, %d", avenrun[1], avenrun[2]);
- sm_dprintf("\n");
- }
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n",
- (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
-}
-
-#endif /* LA_TYPE == LA_READKSYM */
-
-#if LA_TYPE == LA_DGUX
-
-# include <sys/dg_sys_info.h>
-
-int
-getla()
-{
- struct dg_sys_info_load_info load_info;
-
- dg_sys_info((long *)&load_info,
- DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
-
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n", (int) (load_info.one_minute + 0.5));
-
- return ((int) (load_info.one_minute + 0.5));
-}
-
-#endif /* LA_TYPE == LA_DGUX */
-
-#if LA_TYPE == LA_HPUX
-
-/* forward declarations to keep gcc from complaining */
-struct pst_dynamic;
-struct pst_status;
-struct pst_static;
-struct pst_vminfo;
-struct pst_diskinfo;
-struct pst_processor;
-struct pst_lv;
-struct pst_swapinfo;
-
-# include <sys/param.h>
-# include <sys/pstat.h>
-
-int
-getla()
-{
- struct pst_dynamic pstd;
-
- if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic),
- (size_t) 1, 0) == -1)
- return 0;
-
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
-
- return (int) (pstd.psd_avg_1_min + 0.5);
-}
-
-#endif /* LA_TYPE == LA_HPUX */
-
-#if LA_TYPE == LA_SUBR
-
-int
-getla()
-{
- double avenrun[3];
-
- if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: getloadavg failed: %s",
- sm_errstring(errno));
- return -1;
- }
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
- return ((int) (avenrun[0] + 0.5));
-}
-
-#endif /* LA_TYPE == LA_SUBR */
-
-#if LA_TYPE == LA_MACH
-
-/*
-** This has been tested on NEXTSTEP release 2.1/3.X.
-*/
-
-# if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
-# include <mach/mach.h>
-# else /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */
-# include <mach.h>
-# endif /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */
-
-int
-getla()
-{
- processor_set_t default_set;
- kern_return_t error;
- unsigned int info_count;
- struct processor_set_basic_info info;
- host_t host;
-
- error = processor_set_default(host_self(), &default_set);
- if (error != KERN_SUCCESS)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: processor_set_default failed: %s",
- sm_errstring(errno));
- return -1;
- }
- info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
- if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
- &host, (processor_set_info_t)&info,
- &info_count) != KERN_SUCCESS)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: processor_set_info failed: %s",
- sm_errstring(errno));
- return -1;
- }
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n",
- (int) ((info.load_average + (LOAD_SCALE / 2)) /
- LOAD_SCALE));
- return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
-}
-
-#endif /* LA_TYPE == LA_MACH */
-
-#if LA_TYPE == LA_PROCSTR
-# if SM_CONF_BROKEN_STRTOD
- ERROR: This OS has most likely a broken strtod() implemenentation.
- ERROR: The function is required for getla().
- ERROR: Check the compilation options _LA_PROCSTR and
- ERROR: _SM_CONF_BROKEN_STRTOD (without the leading _).
-# endif /* SM_CONF_BROKEN_STRTOD */
-
-/*
-** Read /proc/loadavg for the load average. This is assumed to be
-** in a format like "0.15 0.12 0.06".
-**
-** Initially intended for Linux. This has been in the kernel
-** since at least 0.99.15.
-*/
-
-# ifndef _PATH_LOADAVG
-# define _PATH_LOADAVG "/proc/loadavg"
-# endif /* ! _PATH_LOADAVG */
-
-int
-getla()
-{
- double avenrun;
- register int result;
- SM_FILE_T *fp;
-
- fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_LOADAVG, SM_IO_RDONLY,
- NULL);
- if (fp == NULL)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: sm_io_open(%s): %s\n",
- _PATH_LOADAVG, sm_errstring(errno));
- return -1;
- }
- result = sm_io_fscanf(fp, SM_TIME_DEFAULT, "%lf", &avenrun);
- (void) sm_io_close(fp, SM_TIME_DEFAULT);
- if (result != 1)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: sm_io_fscanf() = %d: %s\n",
- result, sm_errstring(errno));
- return -1;
- }
-
- if (tTd(3, 1))
- sm_dprintf("getla(): %.2f\n", avenrun);
-
- return ((int) (avenrun + 0.5));
-}
-
-#endif /* LA_TYPE == LA_PROCSTR */
-
-#if LA_TYPE == LA_IRIX6
-
-# include <sys/sysmp.h>
-
-# ifdef _UNICOSMP
-# define CAST_SYSMP(x) (x)
-# else /* _UNICOSMP */
-# define CAST_SYSMP(x) ((x) & 0x7fffffff)
-# endif /* _UNICOSMP */
-
-int
-getla(void)
-{
- int j;
- static int kmem = -1;
- int avenrun[3];
-
- if (kmem < 0)
- {
- kmem = open(_PATH_KMEM, 0, 0);
- if (kmem < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: open(%s): %s\n", _PATH_KMEM,
- sm_errstring(errno));
- return -1;
- }
- if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
- fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n",
- sm_errstring(errno));
- (void) close(kmem);
- kmem = -1;
- return -1;
- }
- }
-
- if (lseek(kmem, CAST_SYSMP(sysmp(MP_KERNADDR, MPKA_AVENRUN)), SEEK_SET)
- == -1 ||
- read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
- {
- if (tTd(3, 1))
- sm_dprintf("getla: lseek or read: %s\n",
- sm_errstring(errno));
- return -1;
- }
- if (tTd(3, 5))
- {
- sm_dprintf("getla: avenrun = %ld", (long int) avenrun[0]);
- if (tTd(3, 15))
- sm_dprintf(", %ld, %ld",
- (long int) avenrun[1], (long int) avenrun[2]);
- sm_dprintf("\n");
- }
-
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n",
- (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
-
-}
-#endif /* LA_TYPE == LA_IRIX6 */
-
-#if LA_TYPE == LA_KSTAT
-
-# include <kstat.h>
-
-int
-getla()
-{
- static kstat_ctl_t *kc = NULL;
- static kstat_t *ksp = NULL;
- kstat_named_t *ksn;
- int la;
-
- if (kc == NULL) /* if not initialized before */
- kc = kstat_open();
- if (kc == NULL)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: kstat_open(): %s\n",
- sm_errstring(errno));
- return -1;
- }
- if (ksp == NULL)
- ksp = kstat_lookup(kc, "unix", 0, "system_misc");
- if (ksp == NULL)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: kstat_lookup(): %s\n",
- sm_errstring(errno));
- return -1;
- }
- if (kstat_read(kc, ksp, NULL) < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: kstat_read(): %s\n",
- sm_errstring(errno));
- return -1;
- }
- ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
- la = ((double) ksn->value.ul + FSCALE/2) / FSCALE;
- /* kstat_close(kc); /o do not close for fast access */
- return la;
-}
-
-#endif /* LA_TYPE == LA_KSTAT */
-
-#if LA_TYPE == LA_DEVSHORT
-
-/*
-** Read /dev/table/avenrun for the load average. This should contain
-** three shorts for the 1, 5, and 15 minute loads. We only read the
-** first, since that's all we care about.
-**
-** Intended for SCO OpenServer 5.
-*/
-
-# ifndef _PATH_AVENRUN
-# define _PATH_AVENRUN "/dev/table/avenrun"
-# endif /* ! _PATH_AVENRUN */
-
-int
-getla()
-{
- static int afd = -1;
- short avenrun;
- int loadav;
- int r;
-
- errno = EBADF;
-
- if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1)
- {
- if (errno != EBADF)
- return -1;
- afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
- if (afd < 0)
- {
- sm_syslog(LOG_ERR, NOQID,
- "can't open %s: %s",
- _PATH_AVENRUN, sm_errstring(errno));
- return -1;
- }
- }
-
- r = read(afd, &avenrun, sizeof(avenrun));
-
- if (tTd(3, 5))
- sm_dprintf("getla: avenrun = %d\n", avenrun);
- loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n", loadav);
- return loadav;
-}
-
-#endif /* LA_TYPE == LA_DEVSHORT */
-
-#if LA_TYPE == LA_ALPHAOSF
-struct rtentry;
-struct mbuf;
-# include <sys/table.h>
-
-int
-getla()
-{
- int ave = 0;
- struct tbl_loadavg tab;
-
- if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: table %s\n", sm_errstring(errno));
- return -1;
- }
-
- if (tTd(3, 1))
- sm_dprintf("getla: scale = %d\n", tab.tl_lscale);
-
- if (tab.tl_lscale)
- ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) /
- tab.tl_lscale);
- else
- ave = (int) (tab.tl_avenrun.d[2] + 0.5);
-
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n", ave);
-
- return ave;
-}
-
-#endif /* LA_TYPE == LA_ALPHAOSF */
-
-#if LA_TYPE == LA_PSET
-
-int
-getla()
-{
- double avenrun[3];
-
- if (pset_getloadavg(PS_MYID, avenrun,
- sizeof(avenrun) / sizeof(avenrun[0])) < 0)
- {
- if (tTd(3, 1))
- sm_dprintf("getla: pset_getloadavg failed: %s",
- sm_errstring(errno));
- return -1;
- }
- if (tTd(3, 1))
- sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5));
- return ((int) (avenrun[0] + 0.5));
-}
-
-#endif /* LA_TYPE == LA_PSET */
-
-#if LA_TYPE == LA_ZERO
-
-int
-getla()
-{
- if (tTd(3, 1))
- sm_dprintf("getla: ZERO\n");
- return 0;
-}
-
-#endif /* LA_TYPE == LA_ZERO */
-
-/*
- * Copyright 1989 Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of M.I.T. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. M.I.T. makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors: Many and varied...
- */
-
-/* Non Apollo stuff removed by Don Lewis 11/15/93 */
-#ifndef lint
-SM_UNUSED(static char rcsid[]) = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
-#endif /* ! lint */
-
-#ifdef apollo
-# undef volatile
-# include <apollo/base.h>
-
-/* ARGSUSED */
-int getloadavg( call_data )
- caddr_t call_data; /* pointer to (double) return value */
-{
- double *avenrun = (double *) call_data;
- int i;
- status_$t st;
- long loadav[3];
-
- proc1_$get_loadav(loadav, &st);
- *avenrun = loadav[0] / (double) (1 << 16);
- return 0;
-}
-#endif /* apollo */
-/*
-** SM_GETLA -- get the current load average
-**
-** Parameters:
-** none
-**
-** Returns:
-** none
-**
-** Side Effects:
-** Set CurrentLA to the current load average.
-** Set {load_avg} in GlobalMacros to the current load average.
-*/
-
-void
-sm_getla()
-{
- char labuf[8];
-
- CurrentLA = getla();
- (void) sm_snprintf(labuf, sizeof(labuf), "%d", CurrentLA);
- macdefine(&GlobalMacros, A_TEMP, macid("{load_avg}"), labuf);
-}
-/*
-** SHOULDQUEUE -- should this message be queued or sent?
-**
-** Compares the message cost to the load average to decide.
-**
-** Note: Do NOT change this API! It is documented in op.me
-** and theoretically the user can change this function...
-**
-** Parameters:
-** pri -- the priority of the message in question.
-** ct -- the message creation time (unused, but see above).
-**
-** Returns:
-** true -- if this message should be queued up for the
-** time being.
-** false -- if the load is low enough to send this message.
-**
-** Side Effects:
-** none.
-*/
-
-/* ARGSUSED1 */
-bool
-shouldqueue(pri, ct)
- long pri;
- time_t ct;
-{
- bool rval;
-#if _FFR_MEMSTAT
- long memfree;
-#endif /* _FFR_MEMSTAT */
-
- if (tTd(3, 30))
- sm_dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ",
- CurrentLA, pri);
-
-#if _FFR_MEMSTAT
- if (QueueLowMem > 0 &&
- sm_memstat_get(MemoryResource, &memfree) >= 0 &&
- memfree < QueueLowMem)
- {
- if (tTd(3, 30))
- sm_dprintf("true (memfree=%ld < QueueLowMem=%ld)\n",
- memfree, QueueLowMem);
- return true;
- }
-#endif /* _FFR_MEMSTAT */
- if (CurrentLA < QueueLA)
- {
- if (tTd(3, 30))
- sm_dprintf("false (CurrentLA < QueueLA)\n");
- return false;
- }
- rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1));
- if (tTd(3, 30))
- sm_dprintf("%s (by calculation)\n", rval ? "true" : "false");
- return rval;
-}
-
-/*
-** REFUSECONNECTIONS -- decide if connections should be refused
-**
-** Parameters:
-** e -- the current envelope.
-** dn -- number of daemon.
-** active -- was this daemon actually active?
-**
-** Returns:
-** true if incoming SMTP connections should be refused
-** (for now).
-** false if we should accept new work.
-**
-** Side Effects:
-** Sets process title when it is rejecting connections.
-*/
-
-bool
-refuseconnections(e, dn, active)
- ENVELOPE *e;
- int dn;
- bool active;
-{
- static time_t lastconn[MAXDAEMONS];
- static int conncnt[MAXDAEMONS];
- static time_t firstrejtime[MAXDAEMONS];
- static time_t nextlogtime[MAXDAEMONS];
- int limit;
-#if _FFR_MEMSTAT
- long memfree;
-#endif /* _FFR_MEMSTAT */
-
-#if XLA
- if (!xla_smtp_ok())
- return true;
-#endif /* XLA */
-
- SM_ASSERT(dn >= 0);
- SM_ASSERT(dn < MAXDAEMONS);
- if (ConnRateThrottle > 0)
- {
- time_t now;
-
- now = curtime();
- if (active)
- {
- if (now != lastconn[dn])
- {
- lastconn[dn] = now;
- conncnt[dn] = 1;
- }
- else if (conncnt[dn]++ > ConnRateThrottle)
- {
-#define D_MSG_CRT "deferring connections on daemon %s: %d per second"
- /* sleep to flatten out connection load */
- sm_setproctitle(true, e, D_MSG_CRT,
- Daemons[dn].d_name,
- ConnRateThrottle);
- if (LogLevel > 8)
- sm_syslog(LOG_INFO, NOQID, D_MSG_CRT,
- Daemons[dn].d_name,
- ConnRateThrottle);
- (void) sleep(1);
- }
- }
- else if (now != lastconn[dn])
- conncnt[dn] = 0;
- }
-
-
-#if _FFR_MEMSTAT
- if (RefuseLowMem > 0 &&
- sm_memstat_get(MemoryResource, &memfree) >= 0 &&
- memfree < RefuseLowMem)
- {
-# define R_MSG_LM "rejecting connections on daemon %s: free memory: %ld"
- sm_setproctitle(true, e, R_MSG_LM, Daemons[dn].d_name, memfree);
- if (LogLevel > 8)
- sm_syslog(LOG_NOTICE, NOQID, R_MSG_LM,
- Daemons[dn].d_name, memfree);
- return true;
- }
-#endif /* _FFR_MEMSTAT */
- sm_getla();
- limit = (Daemons[dn].d_refuseLA != DPO_NOTSET) ?
- Daemons[dn].d_refuseLA : RefuseLA;
- if (limit > 0 && CurrentLA >= limit)
- {
- time_t now;
-
-# define R_MSG_LA "rejecting connections on daemon %s: load average: %d"
-# define R2_MSG_LA "have been rejecting connections on daemon %s for %s"
- sm_setproctitle(true, e, R_MSG_LA, Daemons[dn].d_name,
- CurrentLA);
- if (LogLevel > 8)
- sm_syslog(LOG_NOTICE, NOQID, R_MSG_LA,
- Daemons[dn].d_name, CurrentLA);
- now = curtime();
- if (firstrejtime[dn] == 0)
- {
- firstrejtime[dn] = now;
- nextlogtime[dn] = now + RejectLogInterval;
- }
- else if (nextlogtime[dn] < now)
- {
- sm_syslog(LOG_ERR, NOQID, R2_MSG_LA, Daemons[dn].d_name,
- pintvl(now - firstrejtime[dn], true));
- nextlogtime[dn] = now + RejectLogInterval;
- }
- return true;
- }
- else
- firstrejtime[dn] = 0;
-
- limit = (Daemons[dn].d_delayLA != DPO_NOTSET) ?
- Daemons[dn].d_delayLA : DelayLA;
- if (limit > 0 && CurrentLA >= limit)
- {
- time_t now;
- static time_t log_delay = (time_t) 0;
-
-# define MIN_DELAY_LOG 90 /* wait before logging this again */
-# define D_MSG_LA "delaying connections on daemon %s: load average=%d >= %d"
- /* sleep to flatten out connection load */
- sm_setproctitle(true, e, D_MSG_LA, Daemons[dn].d_name, limit);
- if (LogLevel > 8 && (now = curtime()) > log_delay)
- {
- sm_syslog(LOG_INFO, NOQID, D_MSG_LA,
- Daemons[dn].d_name, CurrentLA, limit);
- log_delay = now + MIN_DELAY_LOG;
- }
- (void) sleep(1);
- }
-
- limit = (Daemons[dn].d_maxchildren != DPO_NOTSET) ?
- Daemons[dn].d_maxchildren : MaxChildren;
- if (limit > 0 && CurChildren >= limit)
- {
- proc_list_probe();
- if (CurChildren >= limit)
- {
-#define R_MSG_CHILD "rejecting connections on daemon %s: %d children, max %d"
- sm_setproctitle(true, e, R_MSG_CHILD,
- Daemons[dn].d_name, CurChildren,
- limit);
- if (LogLevel > 8)
- sm_syslog(LOG_INFO, NOQID, R_MSG_CHILD,
- Daemons[dn].d_name, CurChildren,
- limit);
- return true;
- }
- }
- return false;
-}
-
-/*
-** SETPROCTITLE -- set process title for ps
-**
-** Parameters:
-** fmt -- a printf style format string.
-** a, b, c -- possible parameters to fmt.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Clobbers argv of our main procedure so ps(1) will
-** display the title.
-*/
-
-#define SPT_NONE 0 /* don't use it at all */
-#define SPT_REUSEARGV 1 /* cover argv with title information */
-#define SPT_BUILTIN 2 /* use libc builtin */
-#define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
-#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
-#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
-#define SPT_SCO 6 /* write kernel u. area */
-#define SPT_CHANGEARGV 7 /* write our own strings into argv[] */
-
-#ifndef SPT_TYPE
-# define SPT_TYPE SPT_REUSEARGV
-#endif /* ! SPT_TYPE */
-
-
-#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
-
-# if SPT_TYPE == SPT_PSTAT
-# include <sys/pstat.h>
-# endif /* SPT_TYPE == SPT_PSTAT */
-# if SPT_TYPE == SPT_PSSTRINGS
-# include <machine/vmparam.h>
-# include <sys/exec.h>
-# ifndef PS_STRINGS /* hmmmm.... apparently not available after all */
-# undef SPT_TYPE
-# define SPT_TYPE SPT_REUSEARGV
-# else /* ! PS_STRINGS */
-# ifndef NKPDE /* FreeBSD 2.0 */
-# define NKPDE 63
-typedef unsigned int *pt_entry_t;
-# endif /* ! NKPDE */
-# endif /* ! PS_STRINGS */
-# endif /* SPT_TYPE == SPT_PSSTRINGS */
-
-# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
-# define SETPROC_STATIC static
-# else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
-# define SETPROC_STATIC
-# endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
-
-# if SPT_TYPE == SPT_SYSMIPS
-# include <sys/sysmips.h>
-# include <sys/sysnews.h>
-# endif /* SPT_TYPE == SPT_SYSMIPS */
-
-# if SPT_TYPE == SPT_SCO
-# include <sys/immu.h>
-# include <sys/dir.h>
-# include <sys/user.h>
-# include <sys/fs/s5param.h>
-# if PSARGSZ > MAXLINE
-# define SPT_BUFSIZE PSARGSZ
-# endif /* PSARGSZ > MAXLINE */
-# endif /* SPT_TYPE == SPT_SCO */
-
-# ifndef SPT_PADCHAR
-# define SPT_PADCHAR ' '
-# endif /* ! SPT_PADCHAR */
-
-#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
-
-#ifndef SPT_BUFSIZE
-# define SPT_BUFSIZE MAXLINE
-#endif /* ! SPT_BUFSIZE */
-
-#if _FFR_SPT_ALIGN
-
-/*
-** It looks like the Compaq Tru64 5.1A now aligns argv and envp to
-** 64 bit alignment, so unless each piece of argv and envp is a multiple
-** of 8 bytes (including terminating NULL), initsetproctitle() won't use
-** any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE if
-** you use this FFR.
-*/
-
-# ifdef SPT_ALIGN_SIZE
-# define SPT_ALIGN(x, align) (((((x) + SPT_ALIGN_SIZE) >> (align)) << (align)) - 1)
-# else /* SPT_ALIGN_SIZE */
-# define SPT_ALIGN(x, align) (x)
-# endif /* SPT_ALIGN_SIZE */
-#else /* _FFR_SPT_ALIGN */
-# define SPT_ALIGN(x, align) (x)
-#endif /* _FFR_SPT_ALIGN */
-
-/*
-** Pointers for setproctitle.
-** This allows "ps" listings to give more useful information.
-*/
-
-static char **Argv = NULL; /* pointer to argument vector */
-static char *LastArgv = NULL; /* end of argv */
-#if SPT_TYPE != SPT_BUILTIN
-static void setproctitle __P((const char *, ...));
-#endif /* SPT_TYPE != SPT_BUILTIN */
-
-void
-initsetproctitle(argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
-{
- register int i;
- int align;
- extern char **environ;
-
- /*
- ** Move the environment so setproctitle can use the space at
- ** the top of memory.
- */
-
- if (envp != NULL)
- {
- for (i = 0; envp[i] != NULL; i++)
- continue;
- environ = (char **) xalloc(sizeof(char *) * (i + 1));
- for (i = 0; envp[i] != NULL; i++)
- environ[i] = newstr(envp[i]);
- environ[i] = NULL;
- }
-
- /*
- ** Save start and extent of argv for setproctitle.
- */
-
- Argv = argv;
-
- /*
- ** Determine how much space we can use for setproctitle.
- ** Use all contiguous argv and envp pointers starting at argv[0]
- */
-
- align = -1;
-# if _FFR_SPT_ALIGN
-# ifdef SPT_ALIGN_SIZE
- for (i = SPT_ALIGN_SIZE; i > 0; i >>= 1)
- align++;
-# endif /* SPT_ALIGN_SIZE */
-# endif /* _FFR_SPT_ALIGN */
-
- for (i = 0; i < argc; i++)
- {
- if (i == 0 || LastArgv + 1 == argv[i])
- LastArgv = argv[i] + SPT_ALIGN(strlen(argv[i]), align);
- }
- for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++)
- {
- if (LastArgv + 1 == envp[i])
- LastArgv = envp[i] + SPT_ALIGN(strlen(envp[i]), align);
- }
-}
-
-#if SPT_TYPE != SPT_BUILTIN
-
-/*VARARGS1*/
-static void
-# ifdef __STDC__
-setproctitle(const char *fmt, ...)
-# else /* __STDC__ */
-setproctitle(fmt, va_alist)
- const char *fmt;
- va_dcl
-# endif /* __STDC__ */
-{
-# if SPT_TYPE != SPT_NONE
- register int i;
- register char *p;
- SETPROC_STATIC char buf[SPT_BUFSIZE];
- SM_VA_LOCAL_DECL
-# if SPT_TYPE == SPT_PSTAT
- union pstun pst;
-# endif /* SPT_TYPE == SPT_PSTAT */
-# if SPT_TYPE == SPT_SCO
- int j;
- off_t seek_off;
- static int kmem = -1;
- static pid_t kmempid = -1;
- struct user u;
-# endif /* SPT_TYPE == SPT_SCO */
-
- p = buf;
-
- /* print sendmail: heading for grep */
- (void) sm_strlcpy(p, "sendmail: ", SPACELEFT(buf, p));
- p += strlen(p);
-
- /* print the argument string */
- SM_VA_START(ap, fmt);
- (void) sm_vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
- SM_VA_END(ap);
-
- i = (int) strlen(buf);
- if (i < 0)
- return;
-
-# if SPT_TYPE == SPT_PSTAT
- pst.pst_command = buf;
- pstat(PSTAT_SETCMD, pst, i, 0, 0);
-# endif /* SPT_TYPE == SPT_PSTAT */
-# if SPT_TYPE == SPT_PSSTRINGS
- PS_STRINGS->ps_nargvstr = 1;
- PS_STRINGS->ps_argvstr = buf;
-# endif /* SPT_TYPE == SPT_PSSTRINGS */
-# if SPT_TYPE == SPT_SYSMIPS
- sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
-# endif /* SPT_TYPE == SPT_SYSMIPS */
-# if SPT_TYPE == SPT_SCO
- if (kmem < 0 || kmempid != CurrentPid)
- {
- if (kmem >= 0)
- (void) close(kmem);
- kmem = open(_PATH_KMEM, O_RDWR, 0);
- if (kmem < 0)
- return;
- if ((j = fcntl(kmem, F_GETFD, 0)) < 0 ||
- fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0)
- {
- (void) close(kmem);
- kmem = -1;
- return;
- }
- kmempid = CurrentPid;
- }
- buf[PSARGSZ - 1] = '\0';
- seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
- if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
- (void) write(kmem, buf, PSARGSZ);
-# endif /* SPT_TYPE == SPT_SCO */
-# if SPT_TYPE == SPT_REUSEARGV
- if (LastArgv == NULL)
- return;
-
- if (i > LastArgv - Argv[0] - 2)
- {
- i = LastArgv - Argv[0] - 2;
- buf[i] = '\0';
- }
- (void) sm_strlcpy(Argv[0], buf, i + 1);
- p = &Argv[0][i];
- while (p < LastArgv)
- *p++ = SPT_PADCHAR;
- Argv[1] = NULL;
-# endif /* SPT_TYPE == SPT_REUSEARGV */
-# if SPT_TYPE == SPT_CHANGEARGV
- Argv[0] = buf;
- Argv[1] = 0;
-# endif /* SPT_TYPE == SPT_CHANGEARGV */
-# endif /* SPT_TYPE != SPT_NONE */
-}
-
-#endif /* SPT_TYPE != SPT_BUILTIN */
-/*
-** SM_SETPROCTITLE -- set process task and set process title for ps
-**
-** Possibly set process status and call setproctitle() to
-** change the ps display.
-**
-** Parameters:
-** status -- whether or not to store as process status
-** e -- the current envelope.
-** fmt -- a printf style format string.
-** a, b, c -- possible parameters to fmt.
-**
-** Returns:
-** none.
-*/
-
-/*VARARGS2*/
-void
-#ifdef __STDC__
-sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...)
-#else /* __STDC__ */
-sm_setproctitle(status, e, fmt, va_alist)
- bool status;
- ENVELOPE *e;
- const char *fmt;
- va_dcl
-#endif /* __STDC__ */
-{
- char buf[SPT_BUFSIZE];
- SM_VA_LOCAL_DECL
-
- /* print the argument string */
- SM_VA_START(ap, fmt);
- (void) sm_vsnprintf(buf, sizeof(buf), fmt, ap);
- SM_VA_END(ap);
-
- if (status)
- proc_list_set(CurrentPid, buf);
-
- if (ProcTitlePrefix != NULL)
- {
- char prefix[SPT_BUFSIZE];
-
- expand(ProcTitlePrefix, prefix, sizeof(prefix), e);
- setproctitle("%s: %s", prefix, buf);
- }
- else
- setproctitle("%s", buf);
-}
-/*
-** WAITFOR -- wait for a particular process id.
-**
-** Parameters:
-** pid -- process id to wait for.
-**
-** Returns:
-** status of pid.
-** -1 if pid never shows up.
-**
-** Side Effects:
-** none.
-*/
-
-int
-waitfor(pid)
- pid_t pid;
-{
- int st;
- pid_t i;
-
- do
- {
- errno = 0;
- i = sm_wait(&st);
- if (i > 0)
- proc_list_drop(i, st, NULL);
- } while ((i >= 0 || errno == EINTR) && i != pid);
- if (i < 0)
- return -1;
- return st;
-}
-/*
-** SM_WAIT -- wait
-**
-** Parameters:
-** status -- pointer to status (return value)
-**
-** Returns:
-** pid
-*/
-
-pid_t
-sm_wait(status)
- int *status;
-{
-# ifdef WAITUNION
- union wait st;
-# else /* WAITUNION */
- auto int st;
-# endif /* WAITUNION */
- pid_t i;
-# if defined(ISC_UNIX) || defined(_SCO_unix_)
- int savesig;
-# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
-
-# if defined(ISC_UNIX) || defined(_SCO_unix_)
- savesig = sm_releasesignal(SIGCHLD);
-# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
- i = wait(&st);
-# if defined(ISC_UNIX) || defined(_SCO_unix_)
- if (savesig > 0)
- sm_blocksignal(SIGCHLD);
-# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
-# ifdef WAITUNION
- *status = st.w_status;
-# else /* WAITUNION */
- *status = st;
-# endif /* WAITUNION */
- return i;
-}
-/*
-** REAPCHILD -- pick up the body of my child, lest it become a zombie
-**
-** Parameters:
-** sig -- the signal that got us here (unused).
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Picks up extant zombies.
-** Control socket exits may restart/shutdown daemon.
-**
-** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD
-** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE
-** DOING.
-*/
-
-/* ARGSUSED0 */
-SIGFUNC_DECL
-reapchild(sig)
- int sig;
-{
- int save_errno = errno;
- int st;
- pid_t pid;
-# if HASWAITPID
- auto int status;
- int count;
-
- count = 0;
- while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
- {
- st = status;
- if (count++ > 1000)
- break;
-# else /* HASWAITPID */
-# ifdef WNOHANG
- union wait status;
-
- while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0)
- {
- st = status.w_status;
-# else /* WNOHANG */
- auto int status;
-
- /*
- ** Catch one zombie -- we will be re-invoked (we hope) if there
- ** are more. Unreliable signals probably break this, but this
- ** is the "old system" situation -- waitpid or wait3 are to be
- ** strongly preferred.
- */
-
- if ((pid = wait(&status)) > 0)
- {
- st = status;
-# endif /* WNOHANG */
-# endif /* HASWAITPID */
- /* Drop PID and check if it was a control socket child */
- proc_list_drop(pid, st, NULL);
- }
- FIX_SYSV_SIGNAL(sig, reapchild);
- errno = save_errno;
- return SIGFUNC_RETURN;
-}
-/*
-** GETDTABLESIZE -- return number of file descriptors
-**
-** Only on non-BSD systems
-**
-** Parameters:
-** none
-**
-** Returns:
-** size of file descriptor table
-**
-** Side Effects:
-** none
-*/
-
-#ifdef SOLARIS
-# include <sys/resource.h>
-#endif /* SOLARIS */
-
-int
-getdtsize()
-{
-# ifdef RLIMIT_NOFILE
- struct rlimit rl;
-
- if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
- return rl.rlim_cur;
-# endif /* RLIMIT_NOFILE */
-
-# if HASGETDTABLESIZE
- return getdtablesize();
-# else /* HASGETDTABLESIZE */
-# ifdef _SC_OPEN_MAX
- return sysconf(_SC_OPEN_MAX);
-# else /* _SC_OPEN_MAX */
- return NOFILE;
-# endif /* _SC_OPEN_MAX */
-# endif /* HASGETDTABLESIZE */
-}
-/*
-** UNAME -- get the UUCP name of this system.
-*/
-
-#if !HASUNAME
-
-int
-uname(name)
- struct utsname *name;
-{
- SM_FILE_T *file;
- char *n;
-
- name->nodename[0] = '\0';
-
- /* try /etc/whoami -- one line with the node name */
- if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, "/etc/whoami",
- SM_IO_RDONLY, NULL)) != NULL)
- {
- (void) sm_io_fgets(file, SM_TIME_DEFAULT, name->nodename,
- NODE_LENGTH + 1);
- (void) sm_io_close(file, SM_TIME_DEFAULT);
- n = strchr(name->nodename, '\n');
- if (n != NULL)
- *n = '\0';
- if (name->nodename[0] != '\0')
- return 0;
- }
-
- /* try /usr/include/whoami.h -- has a #define somewhere */
- if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT,
- "/usr/include/whoami.h", SM_IO_RDONLY, NULL))
- != NULL)
- {
- char buf[MAXLINE];
-
- while (sm_io_fgets(file, SM_TIME_DEFAULT,
- buf, sizeof(buf)) != NULL)
- {
- if (sm_io_sscanf(buf, "#define sysname \"%*[^\"]\"",
- NODE_LENGTH, name->nodename) > 0)
- break;
- }
- (void) sm_io_close(file, SM_TIME_DEFAULT);
- if (name->nodename[0] != '\0')
- return 0;
- }
-
- return -1;
-}
-#endif /* !HASUNAME */
-/*
-** INITGROUPS -- initialize groups
-**
-** Stub implementation for System V style systems
-*/
-
-#if !HASINITGROUPS
-
-initgroups(name, basegid)
- char *name;
- int basegid;
-{
- return 0;
-}
-
-#endif /* !HASINITGROUPS */
-/*
-** SETGROUPS -- set group list
-**
-** Stub implementation for systems that don't have group lists
-*/
-
-#ifndef NGROUPS_MAX
-
-int
-setgroups(ngroups, grouplist)
- int ngroups;
- GIDSET_T grouplist[];
-{
- return 0;
-}
-
-#endif /* ! NGROUPS_MAX */
-/*
-** SETSID -- set session id (for non-POSIX systems)
-*/
-
-#if !HASSETSID
-
-pid_t
-setsid __P ((void))
-{
-# ifdef TIOCNOTTY
- int fd;
-
- fd = open("/dev/tty", O_RDWR, 0);
- if (fd >= 0)
- {
- (void) ioctl(fd, TIOCNOTTY, (char *) 0);
- (void) close(fd);
- }
-# endif /* TIOCNOTTY */
-# ifdef SYS5SETPGRP
- return setpgrp();
-# else /* SYS5SETPGRP */
- return setpgid(0, CurrentPid);
-# endif /* SYS5SETPGRP */
-}
-
-#endif /* !HASSETSID */
-/*
-** FSYNC -- dummy fsync
-*/
-
-#if NEEDFSYNC
-
-fsync(fd)
- int fd;
-{
-# ifdef O_SYNC
- return fcntl(fd, F_SETFL, O_SYNC);
-# else /* O_SYNC */
- /* nothing we can do */
- return 0;
-# endif /* O_SYNC */
-}
-
-#endif /* NEEDFSYNC */
-/*
-** DGUX_INET_ADDR -- inet_addr for DG/UX
-**
-** Data General DG/UX version of inet_addr returns a struct in_addr
-** instead of a long. This patches things. Only needed on versions
-** prior to 5.4.3.
-*/
-
-#ifdef DGUX_5_4_2
-
-# undef inet_addr
-
-long
-dgux_inet_addr(host)
- char *host;
-{
- struct in_addr haddr;
-
- haddr = inet_addr(host);
- return haddr.s_addr;
-}
-
-#endif /* DGUX_5_4_2 */
-/*
-** GETOPT -- for old systems or systems with bogus implementations
-*/
-
-#if !SM_CONF_GETOPT
-
-/*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
- */
-
-
-/*
-** this version hacked to add `atend' flag to allow state machine
-** to reset if invoked by the program to scan args for a 2nd time
-*/
-
-# if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86";
-# endif /* defined(LIBC_SCCS) && !defined(lint) */
-
-/*
-** get option letter from argument vector
-*/
-# ifdef _CONVEX_SOURCE
-extern int optind, opterr, optopt;
-extern char *optarg;
-# else /* _CONVEX_SOURCE */
-int opterr = 1; /* if error message should be printed */
-int optind = 1; /* index into parent argv vector */
-int optopt = 0; /* character checked for validity */
-char *optarg = NULL; /* argument associated with option */
-# endif /* _CONVEX_SOURCE */
-
-# define BADCH (int)'?'
-# define EMSG ""
-# define tell(s) if (opterr) \
- {sm_io_fputs(smioerr, SM_TIME_DEFAULT, *nargv); \
- (void) sm_io_fputs(smioerr, SM_TIME_DEFAULT, s); \
- (void) sm_io_putc(smioerr, SM_TIME_DEFAULT, optopt); \
- (void) sm_io_putc(smioerr, SM_TIME_DEFAULT, '\n'); \
- return BADCH;}
-
-int
-getopt(nargc,nargv,ostr)
- int nargc;
- char *const *nargv;
- const char *ostr;
-{
- static char *place = EMSG; /* option letter processing */
- static char atend = 0;
- register char *oli = NULL; /* option letter list index */
-
- if (atend) {
- atend = 0;
- place = EMSG;
- }
- if(!*place) { /* update scanning pointer */
- if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
- atend++;
- return -1;
- }
- if (*place == '-') { /* found "--" */
- ++optind;
- atend++;
- return -1;
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
- if (!*place) ++optind;
- tell(": illegal option -- ");
- }
- if (oli && *++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place) ++optind;
- }
- else { /* need an argument */
- if (*place) optarg = place; /* no white space */
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- tell(": option requires an argument -- ");
- }
- else optarg = nargv[optind]; /* white space */
- place = EMSG;
- ++optind;
- }
- return optopt; /* dump back option letter */
-}
-
-#endif /* !SM_CONF_GETOPT */
-/*
-** USERSHELLOK -- tell if a user's shell is ok for unrestricted use
-**
-** Parameters:
-** user -- the name of the user we are checking.
-** shell -- the user's shell from /etc/passwd
-**
-** Returns:
-** true -- if it is ok to use this for unrestricted access.
-** false -- if the shell is restricted.
-*/
-
-#if !HASGETUSERSHELL
-
-# ifndef _PATH_SHELLS
-# define _PATH_SHELLS "/etc/shells"
-# endif /* ! _PATH_SHELLS */
-
-# if defined(_AIX3) || defined(_AIX4)
-# include <userconf.h>
-# if _AIX4 >= 40200
-# include <userpw.h>
-# endif /* _AIX4 >= 40200 */
-# include <usersec.h>
-# endif /* defined(_AIX3) || defined(_AIX4) */
-
-static char *DefaultUserShells[] =
-{
- "/bin/sh", /* standard shell */
-# ifdef MPE
- "/SYS/PUB/CI",
-# else /* MPE */
- "/usr/bin/sh",
- "/bin/csh", /* C shell */
- "/usr/bin/csh",
-# endif /* MPE */
-# ifdef __hpux
-# ifdef V4FS
- "/usr/bin/rsh", /* restricted Bourne shell */
- "/usr/bin/ksh", /* Korn shell */
- "/usr/bin/rksh", /* restricted Korn shell */
- "/usr/bin/pam",
- "/usr/bin/keysh", /* key shell (extended Korn shell) */
- "/usr/bin/posix/sh",
-# else /* V4FS */
- "/bin/rsh", /* restricted Bourne shell */
- "/bin/ksh", /* Korn shell */
- "/bin/rksh", /* restricted Korn shell */
- "/bin/pam",
- "/usr/bin/keysh", /* key shell (extended Korn shell) */
- "/bin/posix/sh",
- "/sbin/sh",
-# endif /* V4FS */
-# endif /* __hpux */
-# if defined(_AIX3) || defined(_AIX4)
- "/bin/ksh", /* Korn shell */
- "/usr/bin/ksh",
- "/bin/tsh", /* trusted shell */
- "/usr/bin/tsh",
- "/bin/bsh", /* Bourne shell */
- "/usr/bin/bsh",
-# endif /* defined(_AIX3) || defined(_AIX4) */
-# if defined(__svr4__) || defined(__svr5__)
- "/bin/ksh", /* Korn shell */
- "/usr/bin/ksh",
-# endif /* defined(__svr4__) || defined(__svr5__) */
-# ifdef sgi
- "/sbin/sh", /* SGI's shells really live in /sbin */
- "/usr/bin/sh",
- "/sbin/bsh", /* classic Bourne shell */
- "/bin/bsh",
- "/usr/bin/bsh",
- "/sbin/csh", /* standard csh */
- "/bin/csh",
- "/usr/bin/csh",
- "/sbin/jsh", /* classic Bourne shell w/ job control*/
- "/bin/jsh",
- "/usr/bin/jsh",
- "/bin/ksh", /* Korn shell */
- "/sbin/ksh",
- "/usr/bin/ksh",
- "/sbin/tcsh", /* Extended csh */
- "/bin/tcsh",
- "/usr/bin/tcsh",
-# endif /* sgi */
- NULL
-};
-
-#endif /* !HASGETUSERSHELL */
-
-#define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
-
-bool
-usershellok(user, shell)
- char *user;
- char *shell;
-{
-# if HASGETUSERSHELL
- register char *p;
- extern char *getusershell();
-
- if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
- ConfigLevel <= 1)
- return true;
-
- setusershell();
- while ((p = getusershell()) != NULL)
- if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
- break;
- endusershell();
- return p != NULL;
-# else /* HASGETUSERSHELL */
-# if USEGETCONFATTR
- auto char *v;
-# endif /* USEGETCONFATTR */
- register SM_FILE_T *shellf;
- char buf[MAXLINE];
-
- if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
- ConfigLevel <= 1)
- return true;
-
-# if USEGETCONFATTR
- /*
- ** Naturally IBM has a "better" idea.....
- **
- ** What a crock. This interface isn't documented, it is
- ** considered part of the security library (-ls), and it
- ** only works if you are running as root (since the list
- ** of valid shells is obviously a source of great concern).
- ** I recommend that you do NOT define USEGETCONFATTR,
- ** especially since you are going to have to set up an
- ** /etc/shells anyhow to handle the cases where getconfattr
- ** fails.
- */
-
- if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL)
- {
- while (*v != '\0')
- {
- if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0)
- return true;
- v += strlen(v) + 1;
- }
- return false;
- }
-# endif /* USEGETCONFATTR */
-
- shellf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_SHELLS,
- SM_IO_RDONLY, NULL);
- if (shellf == NULL)
- {
- /* no /etc/shells; see if it is one of the std shells */
- char **d;
-
- if (errno != ENOENT && LogLevel > 3)
- sm_syslog(LOG_ERR, NOQID,
- "usershellok: cannot open %s: %s",
- _PATH_SHELLS, sm_errstring(errno));
-
- for (d = DefaultUserShells; *d != NULL; d++)
- {
- if (strcmp(shell, *d) == 0)
- return true;
- }
- return false;
- }
-
- while (sm_io_fgets(shellf, SM_TIME_DEFAULT, buf, sizeof(buf)) != NULL)
- {
- register char *p, *q;
-
- p = buf;
- while (*p != '\0' && *p != '#' && *p != '/')
- p++;
- if (*p == '#' || *p == '\0')
- continue;
- q = p;
- while (*p != '\0' && *p != '#' && !(isascii(*p) && isspace(*p)))
- p++;
- *p = '\0';
- if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
- {
- (void) sm_io_close(shellf, SM_TIME_DEFAULT);
- return true;
- }
- }
- (void) sm_io_close(shellf, SM_TIME_DEFAULT);
- return false;
-# endif /* HASGETUSERSHELL */
-}
-/*
-** FREEDISKSPACE -- see how much free space is on the queue filesystem
-**
-** Only implemented if you have statfs.
-**
-** Parameters:
-** dir -- the directory in question.
-** bsize -- a variable into which the filesystem
-** block size is stored.
-**
-** Returns:
-** The number of blocks free on the queue filesystem.
-** -1 if the statfs call fails.
-**
-** Side effects:
-** Puts the filesystem block size into bsize.
-*/
-
-/* statfs types */
-# define SFS_NONE 0 /* no statfs implementation */
-# define SFS_USTAT 1 /* use ustat */
-# define SFS_4ARGS 2 /* use four-argument statfs call */
-# define SFS_VFS 3 /* use <sys/vfs.h> implementation */
-# define SFS_MOUNT 4 /* use <sys/mount.h> implementation */
-# define SFS_STATFS 5 /* use <sys/statfs.h> implementation */
-# define SFS_STATVFS 6 /* use <sys/statvfs.h> implementation */
-
-# ifndef SFS_TYPE
-# define SFS_TYPE SFS_NONE
-# endif /* ! SFS_TYPE */
-
-# if SFS_TYPE == SFS_USTAT
-# include <ustat.h>
-# endif /* SFS_TYPE == SFS_USTAT */
-# if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
-# include <sys/statfs.h>
-# endif /* SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS */
-# if SFS_TYPE == SFS_VFS
-# include <sys/vfs.h>
-# endif /* SFS_TYPE == SFS_VFS */
-# if SFS_TYPE == SFS_MOUNT
-# include <sys/mount.h>
-# endif /* SFS_TYPE == SFS_MOUNT */
-# if SFS_TYPE == SFS_STATVFS
-# include <sys/statvfs.h>
-# endif /* SFS_TYPE == SFS_STATVFS */
-
-long
-freediskspace(dir, bsize)
- const char *dir;
- long *bsize;
-{
-# if SFS_TYPE == SFS_NONE
- if (bsize != NULL)
- *bsize = 4096L;
-
- /* assume free space is plentiful */
- return (long) LONG_MAX;
-# else /* SFS_TYPE == SFS_NONE */
-# if SFS_TYPE == SFS_USTAT
- struct ustat fs;
- struct stat statbuf;
-# define FSBLOCKSIZE DEV_BSIZE
-# define SFS_BAVAIL f_tfree
-# else /* SFS_TYPE == SFS_USTAT */
-# if defined(ultrix)
- struct fs_data fs;
-# define SFS_BAVAIL fd_bfreen
-# define FSBLOCKSIZE 1024L
-# else /* defined(ultrix) */
-# if SFS_TYPE == SFS_STATVFS
- struct statvfs fs;
-# define FSBLOCKSIZE fs.f_frsize
-# else /* SFS_TYPE == SFS_STATVFS */
- struct statfs fs;
-# define FSBLOCKSIZE fs.f_bsize
-# endif /* SFS_TYPE == SFS_STATVFS */
-# endif /* defined(ultrix) */
-# endif /* SFS_TYPE == SFS_USTAT */
-# ifndef SFS_BAVAIL
-# define SFS_BAVAIL f_bavail
-# endif /* ! SFS_BAVAIL */
-
-# if SFS_TYPE == SFS_USTAT
- if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
-# else /* SFS_TYPE == SFS_USTAT */
-# if SFS_TYPE == SFS_4ARGS
- if (statfs(dir, &fs, sizeof(fs), 0) == 0)
-# else /* SFS_TYPE == SFS_4ARGS */
-# if SFS_TYPE == SFS_STATVFS
- if (statvfs(dir, &fs) == 0)
-# else /* SFS_TYPE == SFS_STATVFS */
-# if defined(ultrix)
- if (statfs(dir, &fs) > 0)
-# else /* defined(ultrix) */
- if (statfs(dir, &fs) == 0)
-# endif /* defined(ultrix) */
-# endif /* SFS_TYPE == SFS_STATVFS */
-# endif /* SFS_TYPE == SFS_4ARGS */
-# endif /* SFS_TYPE == SFS_USTAT */
- {
- if (bsize != NULL)
- *bsize = FSBLOCKSIZE;
- if (fs.SFS_BAVAIL <= 0)
- return 0;
- else if (fs.SFS_BAVAIL > LONG_MAX)
- return (long) LONG_MAX;
- else
- return (long) fs.SFS_BAVAIL;
- }
- return -1;
-# endif /* SFS_TYPE == SFS_NONE */
-}
-/*
-** ENOUGHDISKSPACE -- is there enough free space on the queue file systems?
-**
-** Parameters:
-** msize -- the size to check against. If zero, we don't yet
-** know how big the message will be, so just check for
-** a "reasonable" amount.
-** e -- envelope, or NULL -- controls logging
-**
-** Returns:
-** true if in every queue group there is at least one
-** queue directory whose file system contains enough free space.
-** false otherwise.
-**
-** Side Effects:
-** If there is not enough disk space and e != NULL
-** then sm_syslog is called.
-*/
-
-bool
-enoughdiskspace(msize, e)
- long msize;
- ENVELOPE *e;
-{
- int i;
-
- if (MinBlocksFree <= 0 && msize <= 0)
- {
- if (tTd(4, 80))
- sm_dprintf("enoughdiskspace: no threshold\n");
- return true;
- }
-
- filesys_update();
- for (i = 0; i < NumQueue; ++i)
- {
- if (pickqdir(Queue[i], msize, e) < 0)
- return false;
- }
- return true;
-}
-/*
-** TRANSIENTERROR -- tell if an error code indicates a transient failure
-**
-** This looks at an errno value and tells if this is likely to
-** go away if retried later.
-**
-** Parameters:
-** err -- the errno code to classify.
-**
-** Returns:
-** true if this is probably transient.
-** false otherwise.
-*/
-
-bool
-transienterror(err)
- int err;
-{
- switch (err)
- {
- case EIO: /* I/O error */
- case ENXIO: /* Device not configured */
- case EAGAIN: /* Resource temporarily unavailable */
- case ENOMEM: /* Cannot allocate memory */
- case ENODEV: /* Operation not supported by device */
- case ENFILE: /* Too many open files in system */
- case EMFILE: /* Too many open files */
- case ENOSPC: /* No space left on device */
- case ETIMEDOUT: /* Connection timed out */
-#ifdef ESTALE
- case ESTALE: /* Stale NFS file handle */
-#endif /* ESTALE */
-#ifdef ENETDOWN
- case ENETDOWN: /* Network is down */
-#endif /* ENETDOWN */
-#ifdef ENETUNREACH
- case ENETUNREACH: /* Network is unreachable */
-#endif /* ENETUNREACH */
-#ifdef ENETRESET
- case ENETRESET: /* Network dropped connection on reset */
-#endif /* ENETRESET */
-#ifdef ECONNABORTED
- case ECONNABORTED: /* Software caused connection abort */
-#endif /* ECONNABORTED */
-#ifdef ECONNRESET
- case ECONNRESET: /* Connection reset by peer */
-#endif /* ECONNRESET */
-#ifdef ENOBUFS
- case ENOBUFS: /* No buffer space available */
-#endif /* ENOBUFS */
-#ifdef ESHUTDOWN
- case ESHUTDOWN: /* Can't send after socket shutdown */
-#endif /* ESHUTDOWN */
-#ifdef ECONNREFUSED
- case ECONNREFUSED: /* Connection refused */
-#endif /* ECONNREFUSED */
-#ifdef EHOSTDOWN
- case EHOSTDOWN: /* Host is down */
-#endif /* EHOSTDOWN */
-#ifdef EHOSTUNREACH
- case EHOSTUNREACH: /* No route to host */
-#endif /* EHOSTUNREACH */
-#ifdef EDQUOT
- case EDQUOT: /* Disc quota exceeded */
-#endif /* EDQUOT */
-#ifdef EPROCLIM
- case EPROCLIM: /* Too many processes */
-#endif /* EPROCLIM */
-#ifdef EUSERS
- case EUSERS: /* Too many users */
-#endif /* EUSERS */
-#ifdef EDEADLK
- case EDEADLK: /* Resource deadlock avoided */
-#endif /* EDEADLK */
-#ifdef EISCONN
- case EISCONN: /* Socket already connected */
-#endif /* EISCONN */
-#ifdef EINPROGRESS
- case EINPROGRESS: /* Operation now in progress */
-#endif /* EINPROGRESS */
-#ifdef EALREADY
- case EALREADY: /* Operation already in progress */
-#endif /* EALREADY */
-#ifdef EADDRINUSE
- case EADDRINUSE: /* Address already in use */
-#endif /* EADDRINUSE */
-#ifdef EADDRNOTAVAIL
- case EADDRNOTAVAIL: /* Can't assign requested address */
-#endif /* EADDRNOTAVAIL */
-#ifdef ETXTBSY
- case ETXTBSY: /* (Apollo) file locked */
-#endif /* ETXTBSY */
-#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
- case ENOSR: /* Out of streams resources */
-#endif /* defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) */
-#ifdef ENOLCK
- case ENOLCK: /* No locks available */
-#endif /* ENOLCK */
- case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */
- return true;
- }
-
- /* nope, must be permanent */
- return false;
-}
-/*
-** LOCKFILE -- lock a file using flock or (shudder) fcntl locking
-**
-** Parameters:
-** fd -- the file descriptor of the file.
-** filename -- the file name (for error messages).
-** ext -- the filename extension.
-** type -- type of the lock. Bits can be:
-** LOCK_EX -- exclusive lock.
-** LOCK_NB -- non-blocking.
-** LOCK_UN -- unlock.
-**
-** Returns:
-** true if the lock was acquired.
-** false otherwise.
-*/
-
-bool
-lockfile(fd, filename, ext, type)
- int fd;
- char *filename;
- char *ext;
- int type;
-{
- int i;
- int save_errno;
-# if !HASFLOCK
- int action;
- struct flock lfd;
-
- if (ext == NULL)
- ext = "";
-
- memset(&lfd, '\0', sizeof(lfd));
- if (bitset(LOCK_UN, type))
- lfd.l_type = F_UNLCK;
- else if (bitset(LOCK_EX, type))
- lfd.l_type = F_WRLCK;
- else
- lfd.l_type = F_RDLCK;
-
- if (bitset(LOCK_NB, type))
- action = F_SETLK;
- else
- action = F_SETLKW;
-
- if (tTd(55, 60))
- sm_dprintf("lockfile(%s%s, action=%d, type=%d): ",
- filename, ext, action, lfd.l_type);
-
- while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
- continue;
- if (i >= 0)
- {
- if (tTd(55, 60))
- sm_dprintf("SUCCESS\n");
- return true;
- }
- save_errno = errno;
-
- if (tTd(55, 60))
- sm_dprintf("(%s) ", sm_errstring(save_errno));
-
- /*
- ** On SunOS, if you are testing using -oQ/tmp/mqueue or
- ** -oA/tmp/aliases or anything like that, and /tmp is mounted
- ** as type "tmp" (that is, served from swap space), the
- ** previous fcntl will fail with "Invalid argument" errors.
- ** Since this is fairly common during testing, we will assume
- ** that this indicates that the lock is successfully grabbed.
- */
-
- if (save_errno == EINVAL)
- {
- if (tTd(55, 60))
- sm_dprintf("SUCCESS\n");
- return true;
- }
-
- if (!bitset(LOCK_NB, type) ||
- (save_errno != EACCES && save_errno != EAGAIN))
- {
- int omode = fcntl(fd, F_GETFL, 0);
- uid_t euid = geteuid();
-
- errno = save_errno;
- syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
- filename, ext, fd, type, omode, euid);
- dumpfd(fd, true, true);
- }
-# else /* !HASFLOCK */
- if (ext == NULL)
- ext = "";
-
- if (tTd(55, 60))
- sm_dprintf("lockfile(%s%s, type=%o): ", filename, ext, type);
-
- while ((i = flock(fd, type)) < 0 && errno == EINTR)
- continue;
- if (i >= 0)
- {
- if (tTd(55, 60))
- sm_dprintf("SUCCESS\n");
- return true;
- }
- save_errno = errno;
-
- if (tTd(55, 60))
- sm_dprintf("(%s) ", sm_errstring(save_errno));
-
- if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK)
- {
- int omode = fcntl(fd, F_GETFL, 0);
- uid_t euid = geteuid();
-
- errno = save_errno;
- syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
- filename, ext, fd, type, omode, euid);
- dumpfd(fd, true, true);
- }
-# endif /* !HASFLOCK */
- if (tTd(55, 60))
- sm_dprintf("FAIL\n");
- errno = save_errno;
- return false;
-}
-/*
-** CHOWNSAFE -- tell if chown is "safe" (executable only by root)
-**
-** Unfortunately, given that we can't predict other systems on which
-** a remote mounted (NFS) filesystem will be mounted, the answer is
-** almost always that this is unsafe.
-**
-** Note also that many operating systems have non-compliant
-** implementations of the _POSIX_CHOWN_RESTRICTED variable and the
-** fpathconf() routine. According to IEEE 1003.1-1990, if
-** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then
-** no non-root process can give away the file. However, vendors
-** don't take NFS into account, so a comfortable value of
-** _POSIX_CHOWN_RESTRICTED tells us nothing.
-**
-** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf()
-** even on files where chown is not restricted. Many systems get
-** this wrong on NFS-based filesystems (that is, they say that chown
-** is restricted [safe] on NFS filesystems where it may not be, since
-** other systems can access the same filesystem and do file giveaway;
-** only the NFS server knows for sure!) Hence, it is important to
-** get the value of SAFENFSPATHCONF correct -- it should be defined
-** _only_ after testing (see test/t_pathconf.c) a system on an unsafe
-** NFS-based filesystem to ensure that you can get meaningful results.
-** If in doubt, assume unsafe!
-**
-** You may also need to tweak IS_SAFE_CHOWN -- it should be a
-** condition indicating whether the return from pathconf indicates
-** that chown is safe (typically either > 0 or >= 0 -- there isn't
-** even any agreement about whether a zero return means that a file
-** is or is not safe). It defaults to "> 0".
-**
-** If the parent directory is safe (writable only by owner back
-** to the root) then we can relax slightly and trust fpathconf
-** in more circumstances. This is really a crock -- if this is an
-** NFS mounted filesystem then we really know nothing about the
-** underlying implementation. However, most systems pessimize and
-** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which
-** we interpret as unsafe, as we should. Thus, this heuristic gets
-** us into a possible problem only on systems that have a broken
-** pathconf implementation and which are also poorly configured
-** (have :include: files in group- or world-writable directories).
-**
-** Parameters:
-** fd -- the file descriptor to check.
-** safedir -- set if the parent directory is safe.
-**
-** Returns:
-** true -- if the chown(2) operation is "safe" -- that is,
-** only root can chown the file to an arbitrary user.
-** false -- if an arbitrary user can give away a file.
-*/
-
-#ifndef IS_SAFE_CHOWN
-# define IS_SAFE_CHOWN > 0
-#endif /* ! IS_SAFE_CHOWN */
-
-bool
-chownsafe(fd, safedir)
- int fd;
- bool safedir;
-{
-# if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \
- (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H))
- int rval;
-
- /* give the system administrator a chance to override */
- if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail))
- return true;
-
- /*
- ** Some systems (e.g., SunOS) seem to have the call and the
- ** #define _PC_CHOWN_RESTRICTED, but don't actually implement
- ** the call. This heuristic checks for that.
- */
-
- errno = 0;
- rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
-# if SAFENFSPATHCONF
- return errno == 0 && rval IS_SAFE_CHOWN;
-# else /* SAFENFSPATHCONF */
- return safedir && errno == 0 && rval IS_SAFE_CHOWN;
-# endif /* SAFENFSPATHCONF */
-# else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */
- return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail);
-# endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */
-}
-/*
-** RESETLIMITS -- reset system controlled resource limits
-**
-** This is to avoid denial-of-service attacks
-**
-** Parameters:
-** none
-**
-** Returns:
-** none
-*/
-
-#if HASSETRLIMIT
-# ifdef RLIMIT_NEEDS_SYS_TIME_H
-# include <sm/time.h>
-# endif /* RLIMIT_NEEDS_SYS_TIME_H */
-# include <sys/resource.h>
-#endif /* HASSETRLIMIT */
-
-void
-resetlimits()
-{
-#if HASSETRLIMIT
- struct rlimit lim;
-
- lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
- (void) setrlimit(RLIMIT_CPU, &lim);
- (void) setrlimit(RLIMIT_FSIZE, &lim);
-# ifdef RLIMIT_NOFILE
- lim.rlim_cur = lim.rlim_max = FD_SETSIZE;
- (void) setrlimit(RLIMIT_NOFILE, &lim);
-# endif /* RLIMIT_NOFILE */
-#else /* HASSETRLIMIT */
-# if HASULIMIT
- (void) ulimit(2, 0x3fffff);
- (void) ulimit(4, FD_SETSIZE);
-# endif /* HASULIMIT */
-#endif /* HASSETRLIMIT */
- errno = 0;
-}
-/*
-** SETVENDOR -- process vendor code from V configuration line
-**
-** Parameters:
-** vendor -- string representation of vendor.
-**
-** Returns:
-** true -- if ok.
-** false -- if vendor code could not be processed.
-**
-** Side Effects:
-** It is reasonable to set mode flags here to tweak
-** processing in other parts of the code if necessary.
-** For example, if you are a vendor that uses $%y to
-** indicate YP lookups, you could enable that here.
-*/
-
-bool
-setvendor(vendor)
- char *vendor;
-{
- if (sm_strcasecmp(vendor, "Berkeley") == 0)
- {
- VendorCode = VENDOR_BERKELEY;
- return true;
- }
-
- /* add vendor extensions here */
-
-#ifdef SUN_EXTENSIONS
- if (sm_strcasecmp(vendor, "Sun") == 0)
- {
- VendorCode = VENDOR_SUN;
- return true;
- }
-#endif /* SUN_EXTENSIONS */
-#ifdef DEC
- if (sm_strcasecmp(vendor, "Digital") == 0)
- {
- VendorCode = VENDOR_DEC;
- return true;
- }
-#endif /* DEC */
-
-#if defined(VENDOR_NAME) && defined(VENDOR_CODE)
- if (sm_strcasecmp(vendor, VENDOR_NAME) == 0)
- {
- VendorCode = VENDOR_CODE;
- return true;
- }
-#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
-
- return false;
-}
-/*
-** GETVENDOR -- return vendor name based on vendor code
-**
-** Parameters:
-** vendorcode -- numeric representation of vendor.
-**
-** Returns:
-** string containing vendor name.
-*/
-
-char *
-getvendor(vendorcode)
- int vendorcode;
-{
-#if defined(VENDOR_NAME) && defined(VENDOR_CODE)
- /*
- ** Can't have the same switch case twice so need to
- ** handle VENDOR_CODE outside of switch. It might
- ** match one of the existing VENDOR_* codes.
- */
-
- if (vendorcode == VENDOR_CODE)
- return VENDOR_NAME;
-#endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */
-
- switch (vendorcode)
- {
- case VENDOR_BERKELEY:
- return "Berkeley";
-
- case VENDOR_SUN:
- return "Sun";
-
- case VENDOR_HP:
- return "HP";
-
- case VENDOR_IBM:
- return "IBM";
-
- case VENDOR_SENDMAIL:
- return "Sendmail";
-
- default:
- return "Unknown";
- }
-}
-/*
-** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults
-**
-** Vendor_pre_defaults is called before reading the configuration
-** file; vendor_post_defaults is called immediately after.
-**
-** Parameters:
-** e -- the global environment to initialize.
-**
-** Returns:
-** none.
-*/
-
-#if SHARE_V1
-int DefShareUid; /* default share uid to run as -- unused??? */
-#endif /* SHARE_V1 */
-
-void
-vendor_pre_defaults(e)
- ENVELOPE *e;
-{
-#if SHARE_V1
- /* OTHERUID is defined in shares.h, do not be alarmed */
- DefShareUid = OTHERUID;
-#endif /* SHARE_V1 */
-#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
- sun_pre_defaults(e);
-#endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */
-#ifdef apollo
- /*
- ** stupid domain/os can't even open
- ** /etc/mail/sendmail.cf without this
- */
-
- sm_setuserenv("ISP", NULL);
- sm_setuserenv("SYSTYPE", NULL);
-#endif /* apollo */
-}
-
-
-void
-vendor_post_defaults(e)
- ENVELOPE *e;
-{
-#ifdef __QNX__
- /* Makes sure the SOCK environment variable remains */
- sm_setuserenv("SOCK", NULL);
-#endif /* __QNX__ */
-#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
- sun_post_defaults(e);
-#endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */
-}
-/*
-** VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode
-*/
-
-void
-vendor_daemon_setup(e)
- ENVELOPE *e;
-{
-#if HASSETLOGIN
- (void) setlogin(RunAsUserName);
-#endif /* HASSETLOGIN */
-#if SECUREWARE
- if (getluid() != -1)
- {
- usrerr("Daemon cannot have LUID");
- finis(false, true, EX_USAGE);
- }
-#endif /* SECUREWARE */
-}
-/*
-** VENDOR_SET_UID -- do setup for setting a user id
-**
-** This is called when we are still root.
-**
-** Parameters:
-** uid -- the uid we are about to become.
-**
-** Returns:
-** none.
-*/
-
-void
-vendor_set_uid(uid)
- UID_T uid;
-{
- /*
- ** We need to setup the share groups (lnodes)
- ** and add auditing information (luid's)
- ** before we loose our ``root''ness.
- */
-#if SHARE_V1
- if (setupshares(uid, syserr) != 0)
- syserr("Unable to set up shares");
-#endif /* SHARE_V1 */
-#if SECUREWARE
- (void) setup_secure(uid);
-#endif /* SECUREWARE */
-}
-/*
-** VALIDATE_CONNECTION -- check connection for rationality
-**
-** If the connection is rejected, this routine should log an
-** appropriate message -- but should never issue any SMTP protocol.
-**
-** Parameters:
-** sap -- a pointer to a SOCKADDR naming the peer.
-** hostname -- the name corresponding to sap.
-** e -- the current envelope.
-**
-** Returns:
-** error message from rejection.
-** NULL if not rejected.
-*/
-
-#if TCPWRAPPERS
-# include <tcpd.h>
-
-/* tcpwrappers does no logging, but you still have to declare these -- ugh */
-int allow_severity = LOG_INFO;
-int deny_severity = LOG_NOTICE;
-#endif /* TCPWRAPPERS */
-
-char *
-validate_connection(sap, hostname, e)
- SOCKADDR *sap;
- char *hostname;
- ENVELOPE *e;
-{
-#if TCPWRAPPERS
- char *host;
- char *addr;
- extern int hosts_ctl();
-#endif /* TCPWRAPPERS */
-
- if (tTd(48, 3))
- sm_dprintf("validate_connection(%s, %s)\n",
- hostname, anynet_ntoa(sap));
-
- connection_rate_check(sap, e);
- if (rscheck("check_relay", hostname, anynet_ntoa(sap),
- e, RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID, NULL) != EX_OK)
- {
- static char reject[BUFSIZ*2];
- extern char MsgBuf[];
-
- if (tTd(48, 4))
- sm_dprintf(" ... validate_connection: BAD (rscheck)\n");
-
- if (strlen(MsgBuf) >= 3)
- (void) sm_strlcpy(reject, MsgBuf, sizeof(reject));
- else
- (void) sm_strlcpy(reject, "Access denied", sizeof(reject));
-
- return reject;
- }
-
-#if TCPWRAPPERS
- if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']')
- host = "unknown";
- else
- host = hostname;
- addr = anynet_ntoa(sap);
-
-# if NETINET6
- /* TCP/Wrappers don't want the IPv6: protocol label */
- if (addr != NULL && sm_strncasecmp(addr, "IPv6:", 5) == 0)
- addr += 5;
-# endif /* NETINET6 */
-
- if (!hosts_ctl("sendmail", host, addr, STRING_UNKNOWN))
- {
- if (tTd(48, 4))
- sm_dprintf(" ... validate_connection: BAD (tcpwrappers)\n");
- if (LogLevel > 3)
- sm_syslog(LOG_NOTICE, e->e_id,
- "tcpwrappers (%s, %s) rejection",
- host, addr);
- return "Access denied";
- }
-#endif /* TCPWRAPPERS */
- if (tTd(48, 4))
- sm_dprintf(" ... validate_connection: OK\n");
- return NULL;
-}
-
-/*
-** STRTOL -- convert string to long integer
-**
-** For systems that don't have it in the C library.
-**
-** This is taken verbatim from the 4.4-Lite C library.
-*/
-
-#if NEEDSTRTOL
-
-# if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
-# endif /* defined(LIBC_SCCS) && !defined(lint) */
-
-/*
-** Convert a string to a long integer.
-**
-** Ignores `locale' stuff. Assumes that the upper and lower case
-** alphabets and digits are each contiguous.
-*/
-
-long
-strtol(nptr, endptr, base)
- const char *nptr;
- char **endptr;
- register int base;
-{
- register const char *s = nptr;
- register unsigned long acc;
- register int c;
- register unsigned long cutoff;
- register int neg = 0, any, cutlim;
-
- /*
- ** Skip white space and pick up leading +/- sign if any.
- ** If base is 0, allow 0x for hex and 0 for octal, else
- ** assume decimal; if base is already 16, allow 0x.
- */
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else if (c == '+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
-
- /*
- ** Compute the cutoff value between legal numbers and illegal
- ** numbers. That is the largest legal value, divided by the
- ** base. An input number that is greater than this value, if
- ** followed by a legal input character, is too big. One that
- ** is equal to this value may be valid or not; the limit
- ** between valid and invalid numbers is then based on the last
- ** digit. For instance, if the range for longs is
- ** [-2147483648..2147483647] and the input base is 10,
- ** cutoff will be set to 214748364 and cutlim to either
- ** 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
- ** a value > 214748364, or equal but the next digit is > 7 (or 8),
- ** the number is too big, and we will return a range error.
- **
- ** Set any if any `digits' consumed; make it negative to indicate
- ** overflow.
- */
- cutoff = neg ? -(unsigned long) LONG_MIN : LONG_MAX;
- cutlim = cutoff % (unsigned long) base;
- cutoff /= (unsigned long) base;
- for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LONG_MIN : LONG_MAX;
- errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *endptr = (char *)(any ? s - 1 : nptr);
- return acc;
-}
-
-#endif /* NEEDSTRTOL */
-/*
-** STRSTR -- find first substring in string
-**
-** Parameters:
-** big -- the big (full) string.
-** little -- the little (sub) string.
-**
-** Returns:
-** A pointer to the first instance of little in big.
-** big if little is the null string.
-** NULL if little is not contained in big.
-*/
-
-#if NEEDSTRSTR
-
-char *
-strstr(big, little)
- char *big;
- char *little;
-{
- register char *p = big;
- int l;
-
- if (*little == '\0')
- return big;
- l = strlen(little);
-
- while ((p = strchr(p, *little)) != NULL)
- {
- if (strncmp(p, little, l) == 0)
- return p;
- p++;
- }
- return NULL;
-}
-
-#endif /* NEEDSTRSTR */
-/*
-** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
-**
-** Some operating systems have wierd problems with the gethostbyXXX
-** routines. For example, Solaris versions at least through 2.3
-** don't properly deliver a canonical h_name field. This tries to
-** work around these problems.
-**
-** Support IPv6 as well as IPv4.
-*/
-
-#if NETINET6 && NEEDSGETIPNODE
-
-# ifndef AI_DEFAULT
-# define AI_DEFAULT 0 /* dummy */
-# endif /* ! AI_DEFAULT */
-# ifndef AI_ADDRCONFIG
-# define AI_ADDRCONFIG 0 /* dummy */
-# endif /* ! AI_ADDRCONFIG */
-# ifndef AI_V4MAPPED
-# define AI_V4MAPPED 0 /* dummy */
-# endif /* ! AI_V4MAPPED */
-# ifndef AI_ALL
-# define AI_ALL 0 /* dummy */
-# endif /* ! AI_ALL */
-
-static struct hostent *
-getipnodebyname(name, family, flags, err)
- char *name;
- int family;
- int flags;
- int *err;
-{
- bool resv6 = true;
- struct hostent *h;
-
- if (family == AF_INET6)
- {
- /* From RFC2133, section 6.1 */
- resv6 = bitset(RES_USE_INET6, _res.options);
- _res.options |= RES_USE_INET6;
- }
- SM_SET_H_ERRNO(0);
- h = gethostbyname(name);
- if (!resv6)
- _res.options &= ~RES_USE_INET6;
- *err = h_errno;
- return h;
-}
-
-static struct hostent *
-getipnodebyaddr(addr, len, family, err)
- char *addr;
- int len;
- int family;
- int *err;
-{
- struct hostent *h;
-
- SM_SET_H_ERRNO(0);
- h = gethostbyaddr(addr, len, family);
- *err = h_errno;
- return h;
-}
-
-void
-freehostent(h)
- struct hostent *h;
-{
- /*
- ** Stub routine -- if they don't have getipnodeby*(),
- ** they probably don't have the free routine either.
- */
-
- return;
-}
-#endif /* NETINET6 && NEEDSGETIPNODE */
-
-struct hostent *
-sm_gethostbyname(name, family)
- char *name;
- int family;
-{
- int save_errno;
- struct hostent *h = NULL;
-#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
-# if SOLARIS == 20300 || SOLARIS == 203
- static struct hostent hp;
- static char buf[1000];
- extern struct hostent *_switch_gethostbyname_r();
-
- if (tTd(61, 10))
- sm_dprintf("_switch_gethostbyname_r(%s)... ", name);
- h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
- save_errno = errno;
-# else /* SOLARIS == 20300 || SOLARIS == 203 */
- extern struct hostent *__switch_gethostbyname();
-
- if (tTd(61, 10))
- sm_dprintf("__switch_gethostbyname(%s)... ", name);
- h = __switch_gethostbyname(name);
- save_errno = errno;
-# endif /* SOLARIS == 20300 || SOLARIS == 203 */
-#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
- int nmaps;
-# if NETINET6
- int flags = AI_DEFAULT|AI_ALL;
- int err;
-# endif /* NETINET6 */
- char *maptype[MAXMAPSTACK];
- short mapreturn[MAXMAPACTIONS];
- char hbuf[MAXNAME];
-
- if (tTd(61, 10))
- sm_dprintf("sm_gethostbyname(%s, %d)... ", name, family);
-
-# if NETINET6
-# if ADDRCONFIG_IS_BROKEN
- flags &= ~AI_ADDRCONFIG;
-# endif /* ADDRCONFIG_IS_BROKEN */
- h = getipnodebyname(name, family, flags, &err);
- SM_SET_H_ERRNO(err);
-# else /* NETINET6 */
- h = gethostbyname(name);
-# endif /* NETINET6 */
-
- save_errno = errno;
- if (h == NULL)
- {
- if (tTd(61, 10))
- sm_dprintf("failure\n");
-
- nmaps = switch_map_find("hosts", maptype, mapreturn);
- while (--nmaps >= 0)
- {
- if (strcmp(maptype[nmaps], "nis") == 0 ||
- strcmp(maptype[nmaps], "files") == 0)
- break;
- }
-
- if (nmaps >= 0)
- {
- /* try short name */
- if (strlen(name) > sizeof(hbuf) - 1)
- {
- errno = save_errno;
- return NULL;
- }
- (void) sm_strlcpy(hbuf, name, sizeof(hbuf));
- (void) shorten_hostname(hbuf);
-
- /* if it hasn't been shortened, there's no point */
- if (strcmp(hbuf, name) != 0)
- {
- if (tTd(61, 10))
- sm_dprintf("sm_gethostbyname(%s, %d)... ",
- hbuf, family);
-
-# if NETINET6
- h = getipnodebyname(hbuf, family, flags, &err);
- SM_SET_H_ERRNO(err);
- save_errno = errno;
-# else /* NETINET6 */
- h = gethostbyname(hbuf);
- save_errno = errno;
-# endif /* NETINET6 */
- }
- }
- }
-#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */
- if (tTd(61, 10))
- {
- if (h == NULL)
- sm_dprintf("failure\n");
- else
- {
- sm_dprintf("%s\n", h->h_name);
- if (tTd(61, 11))
- {
-#if NETINET6
- struct in6_addr ia6;
- char buf6[INET6_ADDRSTRLEN];
-#else /* NETINET6 */
- struct in_addr ia;
-#endif /* NETINET6 */
- size_t i;
-
- if (h->h_aliases != NULL)
- for (i = 0; h->h_aliases[i] != NULL;
- i++)
- sm_dprintf("\talias: %s\n",
- h->h_aliases[i]);
- for (i = 0; h->h_addr_list[i] != NULL; i++)
- {
- char *addr;
-
-#if NETINET6
- memmove(&ia6, h->h_addr_list[i],
- IN6ADDRSZ);
- addr = anynet_ntop(&ia6,
- buf6, sizeof(buf6));
-#else /* NETINET6 */
- memmove(&ia, h->h_addr_list[i],
- INADDRSZ);
- addr = (char *) inet_ntoa(ia);
-#endif /* NETINET6 */
- if (addr != NULL)
- sm_dprintf("\taddr: %s\n", addr);
- }
- }
- }
- }
- errno = save_errno;
- return h;
-}
-
-struct hostent *
-sm_gethostbyaddr(addr, len, type)
- char *addr;
- int len;
- int type;
-{
- struct hostent *hp;
-
-#if NETINET6
- if (type == AF_INET6 &&
- IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *) addr))
- {
- /* Avoid reverse lookup for IPv6 unspecified address */
- SM_SET_H_ERRNO(HOST_NOT_FOUND);
- return NULL;
- }
-#endif /* NETINET6 */
-
-#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204)
-# if SOLARIS == 20300 || SOLARIS == 203
- {
- static struct hostent he;
- static char buf[1000];
- extern struct hostent *_switch_gethostbyaddr_r();
-
- hp = _switch_gethostbyaddr_r(addr, len, type, &he,
- buf, sizeof(buf), &h_errno);
- }
-# else /* SOLARIS == 20300 || SOLARIS == 203 */
- {
- extern struct hostent *__switch_gethostbyaddr();
-
- hp = __switch_gethostbyaddr(addr, len, type);
- }
-# endif /* SOLARIS == 20300 || SOLARIS == 203 */
-#else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
-# if NETINET6
- {
- int err;
-
- hp = getipnodebyaddr(addr, len, type, &err);
- SM_SET_H_ERRNO(err);
- }
-# else /* NETINET6 */
- hp = gethostbyaddr(addr, len, type);
-# endif /* NETINET6 */
-#endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */
- return hp;
-}
-/*
-** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid
-*/
-
-struct passwd *
-sm_getpwnam(user)
- char *user;
-{
-#ifdef _AIX4
- extern struct passwd *_getpwnam_shadow(const char *, const int);
-
- return _getpwnam_shadow(user, 0);
-#else /* _AIX4 */
- return getpwnam(user);
-#endif /* _AIX4 */
-}
-
-struct passwd *
-sm_getpwuid(uid)
- UID_T uid;
-{
-#if defined(_AIX4) && 0
- extern struct passwd *_getpwuid_shadow(const int, const int);
-
- return _getpwuid_shadow(uid,0);
-#else /* defined(_AIX4) && 0 */
- return getpwuid(uid);
-#endif /* defined(_AIX4) && 0 */
-}
-/*
-** SECUREWARE_SETUP_SECURE -- Convex SecureWare setup
-**
-** Set up the trusted computing environment for C2 level security
-** under SecureWare.
-**
-** Parameters:
-** uid -- uid of the user to initialize in the TCB
-**
-** Returns:
-** none
-**
-** Side Effects:
-** Initialized the user in the trusted computing base
-*/
-
-#if SECUREWARE
-
-# include <sys/security.h>
-# include <prot.h>
-
-void
-secureware_setup_secure(uid)
- UID_T uid;
-{
- int rc;
-
- if (getluid() != -1)
- return;
-
- if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN)
- {
- switch (rc)
- {
- case SSI_NO_PRPW_ENTRY:
- syserr("No protected passwd entry, uid = %d",
- (int) uid);
- break;
-
- case SSI_LOCKED:
- syserr("Account has been disabled, uid = %d",
- (int) uid);
- break;
-
- case SSI_RETIRED:
- syserr("Account has been retired, uid = %d",
- (int) uid);
- break;
-
- case SSI_BAD_SET_LUID:
- syserr("Could not set LUID, uid = %d", (int) uid);
- break;
-
- case SSI_BAD_SET_PRIVS:
- syserr("Could not set kernel privs, uid = %d",
- (int) uid);
-
- default:
- syserr("Unknown return code (%d) from set_secure_info(%d)",
- rc, (int) uid);
- break;
- }
- finis(false, true, EX_NOPERM);
- }
-}
-#endif /* SECUREWARE */
-/*
-** ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address
-**
-** Add hostnames to class 'w' based on the IP address read from
-** the network interface.
-**
-** Parameters:
-** sa -- a pointer to a SOCKADDR containing the address
-**
-** Returns:
-** 0 if successful, -1 if host lookup fails.
-*/
-
-static int
-add_hostnames(sa)
- SOCKADDR *sa;
-{
- struct hostent *hp;
- char **ha;
- char hnb[MAXHOSTNAMELEN];
-
- /* lookup name with IP address */
- switch (sa->sa.sa_family)
- {
-#if NETINET
- case AF_INET:
- hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr,
- sizeof(sa->sin.sin_addr),
- sa->sa.sa_family);
- break;
-#endif /* NETINET */
-
-#if NETINET6
- case AF_INET6:
- hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr,
- sizeof(sa->sin6.sin6_addr),
- sa->sa.sa_family);
- break;
-#endif /* NETINET6 */
-
- default:
- /* Give warning about unsupported family */
- if (LogLevel > 3)
- sm_syslog(LOG_WARNING, NOQID,
- "Unsupported address family %d: %.100s",
- sa->sa.sa_family, anynet_ntoa(sa));
- return -1;
- }
-
- if (hp == NULL)
- {
- int save_errno = errno;
-
- if (LogLevel > 3 &&
-#if NETINET6
- !(sa->sa.sa_family == AF_INET6 &&
- IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) &&
-#endif /* NETINET6 */
- true)
- sm_syslog(LOG_WARNING, NOQID,
- "gethostbyaddr(%.100s) failed: %d",
- anynet_ntoa(sa),
-#if NAMED_BIND
- h_errno
-#else /* NAMED_BIND */
- -1
-#endif /* NAMED_BIND */
- );
- errno = save_errno;
- return -1;
- }
-
- /* save its cname */
- if (!wordinclass((char *) hp->h_name, 'w'))
- {
- setclass('w', (char *) hp->h_name);
- if (tTd(0, 4))
- sm_dprintf("\ta.k.a.: %s\n", hp->h_name);
-
- if (sm_snprintf(hnb, sizeof(hnb), "[%s]", hp->h_name) <
- sizeof(hnb)
- && !wordinclass((char *) hnb, 'w'))
- setclass('w', hnb);
- }
- else
- {
- if (tTd(0, 43))
- sm_dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name);
- }
-
- /* save all it aliases name */
- for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++)
- {
- if (!wordinclass(*ha, 'w'))
- {
- setclass('w', *ha);
- if (tTd(0, 4))
- sm_dprintf("\ta.k.a.: %s\n", *ha);
- if (sm_snprintf(hnb, sizeof(hnb),
- "[%s]", *ha) < sizeof(hnb) &&
- !wordinclass((char *) hnb, 'w'))
- setclass('w', hnb);
- }
- else
- {
- if (tTd(0, 43))
- sm_dprintf("\ta.k.a.: %s (already in $=w)\n",
- *ha);
- }
- }
-#if NETINET6
- freehostent(hp);
-#endif /* NETINET6 */
- return 0;
-}
-/*
-** LOAD_IF_NAMES -- load interface-specific names into $=w
-**
-** Parameters:
-** none.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Loads $=w with the names of all the interfaces.
-*/
-
-#if !NETINET
-# define SIOCGIFCONF_IS_BROKEN 1 /* XXX */
-#endif /* !NETINET */
-
-#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
-struct rtentry;
-struct mbuf;
-# ifndef SUNOS403
-# include <sm/time.h>
-# endif /* ! SUNOS403 */
-# if (_AIX4 >= 40300) && !defined(_NET_IF_H)
-# undef __P
-# endif /* (_AIX4 >= 40300) && !defined(_NET_IF_H) */
-# include <net/if.h>
-#endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
-
-void
-load_if_names()
-{
-# if NETINET6 && defined(SIOCGLIFCONF)
-# ifdef __hpux
-
- /*
- ** Unfortunately, HP has changed all of the structures,
- ** making life difficult for implementors.
- */
-
-# define lifconf if_laddrconf
-# define lifc_len iflc_len
-# define lifc_buf iflc_buf
-# define lifreq if_laddrreq
-# define lifr_addr iflr_addr
-# define lifr_name iflr_name
-# define lifr_flags iflr_flags
-# define ss_family sa_family
-# undef SIOCGLIFNUM
-# endif /* __hpux */
-
- int s;
- int i;
- size_t len;
- int numifs;
- char *buf;
- struct lifconf lifc;
-# ifdef SIOCGLIFNUM
- struct lifnum lifn;
-# endif /* SIOCGLIFNUM */
-
- s = socket(InetMode, SOCK_DGRAM, 0);
- if (s == -1)
- return;
-
- /* get the list of known IP address from the kernel */
-# ifdef __hpux
- i = ioctl(s, SIOCGIFNUM, (char *) &numifs);
-# endif /* __hpux */
-# ifdef SIOCGLIFNUM
- lifn.lifn_family = AF_UNSPEC;
- lifn.lifn_flags = 0;
- i = ioctl(s, SIOCGLIFNUM, (char *)&lifn);
- numifs = lifn.lifn_count;
-# endif /* SIOCGLIFNUM */
-
-# if defined(__hpux) || defined(SIOCGLIFNUM)
- if (i < 0)
- {
- /* can't get number of interfaces -- fall back */
- if (tTd(0, 4))
- sm_dprintf("SIOCGLIFNUM failed: %s\n",
- sm_errstring(errno));
- numifs = -1;
- }
- else if (tTd(0, 42))
- sm_dprintf("system has %d interfaces\n", numifs);
- if (numifs < 0)
-# endif /* defined(__hpux) || defined(SIOCGLIFNUM) */
- numifs = MAXINTERFACES;
-
- if (numifs <= 0)
- {
- (void) close(s);
- return;
- }
-
- len = lifc.lifc_len = numifs * sizeof(struct lifreq);
- buf = lifc.lifc_buf = xalloc(lifc.lifc_len);
-# ifndef __hpux
- lifc.lifc_family = AF_UNSPEC;
- lifc.lifc_flags = 0;
-# endif /* ! __hpux */
- if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0)
- {
- if (tTd(0, 4))
- sm_dprintf("SIOCGLIFCONF failed: %s\n",
- sm_errstring(errno));
- (void) close(s);
- sm_free(buf);
- return;
- }
-
- /* scan the list of IP address */
- if (tTd(0, 40))
- sm_dprintf("scanning for interface specific names, lifc_len=%ld\n",
- (long) len);
-
- for (i = 0; i < len && i >= 0; )
- {
- int flags;
- struct lifreq *ifr = (struct lifreq *)&buf[i];
- SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr;
- int af = ifr->lifr_addr.ss_family;
- char *addr;
- char *name;
- struct in6_addr ia6;
- struct in_addr ia;
-# ifdef SIOCGLIFFLAGS
- struct lifreq ifrf;
-# endif /* SIOCGLIFFLAGS */
- char ip_addr[256];
- char buf6[INET6_ADDRSTRLEN];
-
- /*
- ** We must close and recreate the socket each time
- ** since we don't know what type of socket it is now
- ** (each status function may change it).
- */
-
- (void) close(s);
-
- s = socket(af, SOCK_DGRAM, 0);
- if (s == -1)
- {
- sm_free(buf); /* XXX */
- return;
- }
-
- /*
- ** If we don't have a complete ifr structure,
- ** don't try to use it.
- */
-
- if ((len - i) < sizeof(*ifr))
- break;
-
-# ifdef BSD4_4_SOCKADDR
- if (sa->sa.sa_len > sizeof(ifr->lifr_addr))
- i += sizeof(ifr->lifr_name) + sa->sa.sa_len;
- else
-# endif /* BSD4_4_SOCKADDR */
-# ifdef DEC
- /* fix for IPv6 size differences */
- i += sizeof(ifr->ifr_name) +
- max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len);
-# else /* DEC */
- i += sizeof(*ifr);
-# endif /* DEC */
-
- if (tTd(0, 20))
- sm_dprintf("%s\n", anynet_ntoa(sa));
-
- if (af != AF_INET && af != AF_INET6)
- continue;
-
-# ifdef SIOCGLIFFLAGS
- memset(&ifrf, '\0', sizeof(struct lifreq));
- (void) sm_strlcpy(ifrf.lifr_name, ifr->lifr_name,
- sizeof(ifrf.lifr_name));
- if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0)
- {
- if (tTd(0, 4))
- sm_dprintf("SIOCGLIFFLAGS failed: %s\n",
- sm_errstring(errno));
- continue;
- }
-
- name = ifr->lifr_name;
- flags = ifrf.lifr_flags;
-
- if (tTd(0, 41))
- sm_dprintf("\tflags: %lx\n", (unsigned long) flags);
-
- if (!bitset(IFF_UP, flags))
- continue;
-# endif /* SIOCGLIFFLAGS */
-
- ip_addr[0] = '\0';
-
- /* extract IP address from the list*/
- switch (af)
- {
- case AF_INET6:
-# ifdef __KAME__
- /* convert into proper scoped address */
- if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) ||
- IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) &&
- sa->sin6.sin6_scope_id == 0)
- {
- struct in6_addr *ia6p;
-
- ia6p = &sa->sin6.sin6_addr;
- sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] |
- ((unsigned int)ia6p->s6_addr[2] << 8));
- ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0;
- }
-# endif /* __KAME__ */
- ia6 = sa->sin6.sin6_addr;
- if (IN6_IS_ADDR_UNSPECIFIED(&ia6))
- {
- addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
- message("WARNING: interface %s is UP with %s address",
- name, addr == NULL ? "(NULL)" : addr);
- continue;
- }
-
- /* save IP address in text from */
- addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
- if (addr != NULL)
- (void) sm_snprintf(ip_addr, sizeof(ip_addr),
- "[%.*s]",
- (int) sizeof(ip_addr) - 3,
- addr);
- break;
-
- case AF_INET:
- ia = sa->sin.sin_addr;
- if (ia.s_addr == INADDR_ANY ||
- ia.s_addr == INADDR_NONE)
- {
- message("WARNING: interface %s is UP with %s address",
- name, inet_ntoa(ia));
- continue;
- }
-
- /* save IP address in text from */
- (void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]",
- (int) sizeof(ip_addr) - 3, inet_ntoa(ia));
- break;
- }
-
- if (*ip_addr == '\0')
- continue;
-
- if (!wordinclass(ip_addr, 'w'))
- {
- setclass('w', ip_addr);
- if (tTd(0, 4))
- sm_dprintf("\ta.k.a.: %s\n", ip_addr);
- }
-
-# ifdef SIOCGLIFFLAGS
- /* skip "loopback" interface "lo" */
- if (DontProbeInterfaces == DPI_SKIPLOOPBACK &&
- bitset(IFF_LOOPBACK, flags))
- continue;
-# endif /* SIOCGLIFFLAGS */
- (void) add_hostnames(sa);
- }
- sm_free(buf); /* XXX */
- (void) close(s);
-# else /* NETINET6 && defined(SIOCGLIFCONF) */
-# if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
- int s;
- int i;
- struct ifconf ifc;
- int numifs;
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s == -1)
- return;
-
- /* get the list of known IP address from the kernel */
-# if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN
- if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0)
- {
- /* can't get number of interfaces -- fall back */
- if (tTd(0, 4))
- sm_dprintf("SIOCGIFNUM failed: %s\n",
- sm_errstring(errno));
- numifs = -1;
- }
- else if (tTd(0, 42))
- sm_dprintf("system has %d interfaces\n", numifs);
- if (numifs < 0)
-# endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */
- numifs = MAXINTERFACES;
-
- if (numifs <= 0)
- {
- (void) close(s);
- return;
- }
- ifc.ifc_len = numifs * sizeof(struct ifreq);
- ifc.ifc_buf = xalloc(ifc.ifc_len);
- if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
- {
- if (tTd(0, 4))
- sm_dprintf("SIOCGIFCONF failed: %s\n",
- sm_errstring(errno));
- (void) close(s);
- return;
- }
-
- /* scan the list of IP address */
- if (tTd(0, 40))
- sm_dprintf("scanning for interface specific names, ifc_len=%d\n",
- ifc.ifc_len);
-
- for (i = 0; i < ifc.ifc_len && i >= 0; )
- {
- int af;
- struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i];
- SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr;
-# if NETINET6
- char *addr;
- struct in6_addr ia6;
-# endif /* NETINET6 */
- struct in_addr ia;
-# ifdef SIOCGIFFLAGS
- struct ifreq ifrf;
-# endif /* SIOCGIFFLAGS */
- char ip_addr[256];
-# if NETINET6
- char buf6[INET6_ADDRSTRLEN];
-# endif /* NETINET6 */
-
- /*
- ** If we don't have a complete ifr structure,
- ** don't try to use it.
- */
-
- if ((ifc.ifc_len - i) < sizeof(*ifr))
- break;
-
-# ifdef BSD4_4_SOCKADDR
- if (sa->sa.sa_len > sizeof(ifr->ifr_addr))
- i += sizeof(ifr->ifr_name) + sa->sa.sa_len;
- else
-# endif /* BSD4_4_SOCKADDR */
- i += sizeof(*ifr);
-
- if (tTd(0, 20))
- sm_dprintf("%s\n", anynet_ntoa(sa));
-
- af = ifr->ifr_addr.sa_family;
- if (af != AF_INET
-# if NETINET6
- && af != AF_INET6
-# endif /* NETINET6 */
- )
- continue;
-
-# ifdef SIOCGIFFLAGS
- memset(&ifrf, '\0', sizeof(struct ifreq));
- (void) sm_strlcpy(ifrf.ifr_name, ifr->ifr_name,
- sizeof(ifrf.ifr_name));
- (void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
- if (tTd(0, 41))
- sm_dprintf("\tflags: %lx\n",
- (unsigned long) ifrf.ifr_flags);
-# define IFRFREF ifrf
-# else /* SIOCGIFFLAGS */
-# define IFRFREF (*ifr)
-# endif /* SIOCGIFFLAGS */
-
- if (!bitset(IFF_UP, IFRFREF.ifr_flags))
- continue;
-
- ip_addr[0] = '\0';
-
- /* extract IP address from the list*/
- switch (af)
- {
- case AF_INET:
- ia = sa->sin.sin_addr;
- if (ia.s_addr == INADDR_ANY ||
- ia.s_addr == INADDR_NONE)
- {
- message("WARNING: interface %s is UP with %s address",
- ifr->ifr_name, inet_ntoa(ia));
- continue;
- }
-
- /* save IP address in text from */
- (void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]",
- (int) sizeof(ip_addr) - 3,
- inet_ntoa(ia));
- break;
-
-# if NETINET6
- case AF_INET6:
-# ifdef __KAME__
- /* convert into proper scoped address */
- if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) ||
- IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) &&
- sa->sin6.sin6_scope_id == 0)
- {
- struct in6_addr *ia6p;
-
- ia6p = &sa->sin6.sin6_addr;
- sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] |
- ((unsigned int)ia6p->s6_addr[2] << 8));
- ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0;
- }
-# endif /* __KAME__ */
- ia6 = sa->sin6.sin6_addr;
- if (IN6_IS_ADDR_UNSPECIFIED(&ia6))
- {
- addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
- message("WARNING: interface %s is UP with %s address",
- ifr->ifr_name,
- addr == NULL ? "(NULL)" : addr);
- continue;
- }
-
- /* save IP address in text from */
- addr = anynet_ntop(&ia6, buf6, sizeof(buf6));
- if (addr != NULL)
- (void) sm_snprintf(ip_addr, sizeof(ip_addr),
- "[%.*s]",
- (int) sizeof(ip_addr) - 3,
- addr);
- break;
-
-# endif /* NETINET6 */
- }
-
- if (ip_addr[0] == '\0')
- continue;
-
- if (!wordinclass(ip_addr, 'w'))
- {
- setclass('w', ip_addr);
- if (tTd(0, 4))
- sm_dprintf("\ta.k.a.: %s\n", ip_addr);
- }
-
- /* skip "loopback" interface "lo" */
- if (DontProbeInterfaces == DPI_SKIPLOOPBACK &&
- bitset(IFF_LOOPBACK, IFRFREF.ifr_flags))
- continue;
-
- (void) add_hostnames(sa);
- }
- sm_free(ifc.ifc_buf); /* XXX */
- (void) close(s);
-# undef IFRFREF
-# endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */
-# endif /* NETINET6 && defined(SIOCGLIFCONF) */
-}
-/*
-** ISLOOPBACK -- is socket address in the loopback net?
-**
-** Parameters:
-** sa -- socket address.
-**
-** Returns:
-** true -- is socket address in the loopback net?
-** false -- otherwise
-**
-*/
-
-bool
-isloopback(sa)
- SOCKADDR sa;
-{
-#if NETINET6
- if (IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr))
- return true;
-#else /* NETINET6 */
- /* XXX how to correctly extract IN_LOOPBACKNET part? */
- if (((ntohl(sa.sin.sin_addr.s_addr) & IN_CLASSA_NET)
- >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET)
- return true;
-#endif /* NETINET6 */
- return false;
-}
-/*
-** GET_NUM_PROCS_ONLINE -- return the number of processors currently online
-**
-** Parameters:
-** none.
-**
-** Returns:
-** The number of processors online.
-*/
-
-static int
-get_num_procs_online()
-{
- int nproc = 0;
-
-#ifdef USESYSCTL
-# if defined(CTL_HW) && defined(HW_NCPU)
- size_t sz;
- int mib[2];
-
- mib[0] = CTL_HW;
- mib[1] = HW_NCPU;
- sz = (size_t) sizeof(nproc);
- (void) sysctl(mib, 2, &nproc, &sz, NULL, 0);
-# endif /* defined(CTL_HW) && defined(HW_NCPU) */
-#else /* USESYSCTL */
-# ifdef _SC_NPROCESSORS_ONLN
- nproc = (int) sysconf(_SC_NPROCESSORS_ONLN);
-# else /* _SC_NPROCESSORS_ONLN */
-# ifdef __hpux
-# include <sys/pstat.h>
- struct pst_dynamic psd;
-
- if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1)
- nproc = psd.psd_proc_cnt;
-# endif /* __hpux */
-# endif /* _SC_NPROCESSORS_ONLN */
-#endif /* USESYSCTL */
-
- if (nproc <= 0)
- nproc = 1;
- return nproc;
-}
-/*
-** SM_CLOSEFROM -- close file descriptors
-**
-** Parameters:
-** lowest -- first fd to close
-** highest -- last fd + 1 to close
-**
-** Returns:
-** none
-*/
-
-void
-sm_closefrom(lowest, highest)
- int lowest, highest;
-{
-#if HASCLOSEFROM
- closefrom(lowest);
-#else /* HASCLOSEFROM */
- int i;
-
- for (i = lowest; i < highest; i++)
- (void) close(i);
-#endif /* HASCLOSEFROM */
-}
-#if HASFDWALK
-/*
-** CLOSEFD_WALK -- walk fd's arranging to close them
-** Callback for fdwalk()
-**
-** Parameters:
-** lowest -- first fd to arrange to be closed
-** fd -- fd to arrange to be closed
-**
-** Returns:
-** zero
-*/
-
-static int
-closefd_walk(lowest, fd)
- void *lowest;
- int fd;
-{
- if (fd >= *(int *)lowest)
- (void) fcntl(fd, F_SETFD, FD_CLOEXEC);
- return 0;
-}
-#endif /* HASFDWALK */
-/*
-** SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed
-**
-** Parameters:
-** lowest -- first fd to arrange to be closed
-** highest -- last fd + 1 to arrange to be closed
-**
-** Returns:
-** none
-*/
-
-void
-sm_close_on_exec(highest, lowest)
- int highest, lowest;
-{
-#if HASFDWALK
- (void) fdwalk(closefd_walk, &lowest);
-#else /* HASFDWALK */
- int i, j;
-
- for (i = lowest; i < highest; i++)
- {
- if ((j = fcntl(i, F_GETFD, 0)) != -1)
- (void) fcntl(i, F_SETFD, j | FD_CLOEXEC);
- }
-#endif /* HASFDWALK */
-}
-/*
-** SEED_RANDOM -- seed the random number generator
-**
-** Parameters:
-** none
-**
-** Returns:
-** none
-*/
-
-void
-seed_random()
-{
-#if HASSRANDOMDEV
- srandomdev();
-#else /* HASSRANDOMDEV */
- long seed;
- struct timeval t;
-
- seed = (long) CurrentPid;
- if (gettimeofday(&t, NULL) >= 0)
- seed += t.tv_sec + t.tv_usec;
-
-# if HASRANDOM
- (void) srandom(seed);
-# else /* HASRANDOM */
- (void) srand((unsigned int) seed);
-# endif /* HASRANDOM */
-#endif /* HASSRANDOMDEV */
-}
-/*
-** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE
-**
-** Parameters:
-** level -- syslog level
-** id -- envelope ID or NULL (NOQUEUE)
-** fmt -- format string
-** arg... -- arguments as implied by fmt.
-**
-** Returns:
-** none
-*/
-
-/* VARARGS3 */
-void
-#ifdef __STDC__
-sm_syslog(int level, const char *id, const char *fmt, ...)
-#else /* __STDC__ */
-sm_syslog(level, id, fmt, va_alist)
- int level;
- const char *id;
- const char *fmt;
- va_dcl
-#endif /* __STDC__ */
-{
- char *buf;
- size_t bufsize;
- char *begin, *end;
- int save_errno;
- int seq = 1;
- int idlen;
- char buf0[MAXLINE];
- char *newstring;
- extern int SyslogPrefixLen;
- SM_VA_LOCAL_DECL
-
- save_errno = errno;
- if (id == NULL)
- id = "NOQUEUE";
- idlen = strlen(id) + SyslogPrefixLen;
-
- buf = buf0;
- bufsize = sizeof(buf0);
-
- for (;;)
- {
- int n;
-
- /* print log message into buf */
- SM_VA_START(ap, fmt);
- n = sm_vsnprintf(buf, bufsize, fmt, ap);
- SM_VA_END(ap);
- SM_ASSERT(n > 0);
- if (n < bufsize)
- break;
-
- /* String too small, redo with correct size */
- bufsize = n + 1;
- if (buf != buf0)
- {
- sm_free(buf);
- buf = NULL;
- }
- buf = sm_malloc_x(bufsize);
- }
-
- /* clean up buf after it has been expanded with args */
- newstring = str2prt(buf);
- if ((strlen(newstring) + idlen + 1) < SYSLOG_BUFSIZE)
- {
-#if LOG
- if (*id == '\0')
- {
- if (tTd(89, 8))
- sm_dprintf("%s\n", newstring);
- else
- syslog(level, "%s", newstring);
- }
- else
- {
- if (tTd(89, 8))
- sm_dprintf("%s: %s\n", id, newstring);
- else
- syslog(level, "%s: %s", id, newstring);
- }
-#else /* LOG */
- /*XXX should do something more sensible */
- if (*id == '\0')
- (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n",
- newstring);
- else
- (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
- "%s: %s\n", id, newstring);
-#endif /* LOG */
- if (buf != buf0)
- sm_free(buf);
- errno = save_errno;
- return;
- }
-
-/*
-** additional length for splitting: " ..." + 3, where 3 is magic to
-** have some data for the next entry.
-*/
-
-#define SL_SPLIT 7
-
- begin = newstring;
- idlen += 5; /* strlen("[999]"), see below */
- while (*begin != '\0' &&
- (strlen(begin) + idlen) > SYSLOG_BUFSIZE)
- {
- char save;
-
- if (seq >= 999)
- {
- /* Too many messages */
- break;
- }
- end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT;
- while (end > begin)
- {
- /* Break on comma or space */
- if (*end == ',' || *end == ' ')
- {
- end++; /* Include separator */
- break;
- }
- end--;
- }
- /* No separator, break midstring... */
- if (end == begin)
- end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT;
- save = *end;
- *end = 0;
-#if LOG
- if (tTd(89, 8))
- sm_dprintf("%s[%d]: %s ...\n", id, seq++, begin);
- else
- syslog(level, "%s[%d]: %s ...", id, seq++, begin);
-#else /* LOG */
- (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
- "%s[%d]: %s ...\n", id, seq++, begin);
-#endif /* LOG */
- *end = save;
- begin = end;
- }
- if (seq >= 999)
- {
-#if LOG
- if (tTd(89, 8))
- sm_dprintf("%s[%d]: log terminated, too many parts\n",
- id, seq);
- else
- syslog(level, "%s[%d]: log terminated, too many parts",
- id, seq);
-#else /* LOG */
- (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
- "%s[%d]: log terminated, too many parts\n", id, seq);
-#endif /* LOG */
- }
- else if (*begin != '\0')
- {
-#if LOG
- if (tTd(89, 8))
- sm_dprintf("%s[%d]: %s\n", id, seq, begin);
- else
- syslog(level, "%s[%d]: %s", id, seq, begin);
-#else /* LOG */
- (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT,
- "%s[%d]: %s\n", id, seq, begin);
-#endif /* LOG */
- }
- if (buf != buf0)
- sm_free(buf);
- errno = save_errno;
-}
-/*
-** HARD_SYSLOG -- call syslog repeatedly until it works
-**
-** Needed on HP-UX, which apparently doesn't guarantee that
-** syslog succeeds during interrupt handlers.
-*/
-
-#if defined(__hpux) && !defined(HPUX11)
-
-# define MAXSYSLOGTRIES 100
-# undef syslog
-# ifdef V4FS
-# define XCNST const
-# define CAST (const char *)
-# else /* V4FS */
-# define XCNST
-# define CAST
-# endif /* V4FS */
-
-void
-# ifdef __STDC__
-hard_syslog(int pri, XCNST char *msg, ...)
-# else /* __STDC__ */
-hard_syslog(pri, msg, va_alist)
- int pri;
- XCNST char *msg;
- va_dcl
-# endif /* __STDC__ */
-{
- int i;
- char buf[SYSLOG_BUFSIZE];
- SM_VA_LOCAL_DECL
-
- SM_VA_START(ap, msg);
- (void) sm_vsnprintf(buf, sizeof(buf), msg, ap);
- SM_VA_END(ap);
-
- for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; )
- continue;
-}
-
-# undef CAST
-#endif /* defined(__hpux) && !defined(HPUX11) */
-#if NEEDLOCAL_HOSTNAME_LENGTH
-/*
-** LOCAL_HOSTNAME_LENGTH
-**
-** This is required to get sendmail to compile against BIND 4.9.x
-** on Ultrix.
-**
-** Unfortunately, a Compaq Y2K patch kit provides it without
-** bumping __RES in /usr/include/resolv.h so we can't automatically
-** figure out whether it is needed.
-*/
-
-int
-local_hostname_length(hostname)
- char *hostname;
-{
- size_t len_host, len_domain;
-
- if (!*_res.defdname)
- res_init();
- len_host = strlen(hostname);
- len_domain = strlen(_res.defdname);
- if (len_host > len_domain &&
- (sm_strcasecmp(hostname + len_host - len_domain,
- _res.defdname) == 0) &&
- hostname[len_host - len_domain - 1] == '.')
- return len_host - len_domain - 1;
- else
- return 0;
-}
-#endif /* NEEDLOCAL_HOSTNAME_LENGTH */
-
-#if NEEDLINK
-/*
-** LINK -- clone a file
-**
-** Some OS's lacks link() and hard links. Since sendmail is using
-** link() as an efficient way to clone files, this implementation
-** will simply do a file copy.
-**
-** NOTE: This link() replacement is not a generic replacement as it
-** does not handle all of the semantics of the real link(2).
-**
-** Parameters:
-** source -- pathname of existing file.
-** target -- pathname of link (clone) to be created.
-**
-** Returns:
-** 0 -- success.
-** -1 -- failure, see errno for details.
-*/
-
-int
-link(source, target)
- const char *source;
- const char *target;
-{
- int save_errno;
- int sff;
- int src = -1, dst = -1;
- ssize_t readlen;
- ssize_t writelen;
- char buf[BUFSIZ];
- struct stat st;
-
- sff = SFF_REGONLY|SFF_OPENASROOT;
- if (DontLockReadFiles)
- sff |= SFF_NOLOCK;
-
- /* Open the original file */
- src = safeopen((char *)source, O_RDONLY, 0, sff);
- if (src < 0)
- goto fail;
-
- /* Obtain the size and the mode */
- if (fstat(src, &st) < 0)
- goto fail;
-
- /* Create the duplicate copy */
- sff &= ~SFF_NOLOCK;
- sff |= SFF_CREAT;
- dst = safeopen((char *)target, O_CREAT|O_EXCL|O_WRONLY,
- st.st_mode, sff);
- if (dst < 0)
- goto fail;
-
- /* Copy all of the bytes one buffer at a time */
- while ((readlen = read(src, &buf, sizeof(buf))) > 0)
- {
- ssize_t left = readlen;
- char *p = buf;
-
- while (left > 0 &&
- (writelen = write(dst, p, (size_t) left)) >= 0)
- {
- left -= writelen;
- p += writelen;
- }
- if (writelen < 0)
- break;
- }
-
- /* Any trouble reading? */
- if (readlen < 0 || writelen < 0)
- goto fail;
-
- /* Close the input file */
- if (close(src) < 0)
- {
- src = -1;
- goto fail;
- }
- src = -1;
-
- /* Close the output file */
- if (close(dst) < 0)
- {
- /* don't set dst = -1 here so we unlink the file */
- goto fail;
- }
-
- /* Success */
- return 0;
-
- fail:
- save_errno = errno;
- if (src >= 0)
- (void) close(src);
- if (dst >= 0)
- {
- (void) unlink(target);
- (void) close(dst);
- }
- errno = save_errno;
- return -1;
-}
-#endif /* NEEDLINK */
-
-/*
-** Compile-Time options
-*/
-
-char *CompileOptions[] =
-{
-#if ALLOW_255
- "ALLOW_255",
-#endif /* ALLOW_255 */
-#if NAMED_BIND
-# if DNSMAP
- "DNSMAP",
-# endif /* DNSMAP */
-#endif /* NAMED_BIND */
-#if EGD
- "EGD",
-#endif /* EGD */
-#if HESIOD
- "HESIOD",
-#endif /* HESIOD */
-#if HES_GETMAILHOST
- "HES_GETMAILHOST",
-#endif /* HES_GETMAILHOST */
-#if LDAPMAP
- "LDAPMAP",
-#endif /* LDAPMAP */
-#if LDAP_REFERRALS
- "LDAP_REFERRALS",
-#endif /* LDAP_REFERRALS */
-#if LOG
- "LOG",
-#endif /* LOG */
-#if MAP_NSD
- "MAP_NSD",
-#endif /* MAP_NSD */
-#if MAP_REGEX
- "MAP_REGEX",
-#endif /* MAP_REGEX */
-#if MATCHGECOS
- "MATCHGECOS",
-#endif /* MATCHGECOS */
-#if MILTER
- "MILTER",
-#endif /* MILTER */
-#if MIME7TO8
- "MIME7TO8",
-#endif /* MIME7TO8 */
-#if MIME7TO8_OLD
- "MIME7TO8_OLD",
-#endif /* MIME7TO8_OLD */
-#if MIME8TO7
- "MIME8TO7",
-#endif /* MIME8TO7 */
-#if NAMED_BIND
- "NAMED_BIND",
-#endif /* NAMED_BIND */
-#if NDBM
- "NDBM",
-#endif /* NDBM */
-#if NETINET
- "NETINET",
-#endif /* NETINET */
-#if NETINET6
- "NETINET6",
-#endif /* NETINET6 */
-#if NETINFO
- "NETINFO",
-#endif /* NETINFO */
-#if NETISO
- "NETISO",
-#endif /* NETISO */
-#if NETNS
- "NETNS",
-#endif /* NETNS */
-#if NETUNIX
- "NETUNIX",
-#endif /* NETUNIX */
-#if NETX25
- "NETX25",
-#endif /* NETX25 */
-#if NEWDB
- "NEWDB",
-#endif /* NEWDB */
-#if NIS
- "NIS",
-#endif /* NIS */
-#if NISPLUS
- "NISPLUS",
-#endif /* NISPLUS */
-#if NO_DH
- "NO_DH",
-#endif /* NO_DH */
-#if PH_MAP
- "PH_MAP",
-#endif /* PH_MAP */
-#ifdef PICKY_HELO_CHECK
- "PICKY_HELO_CHECK",
-#endif /* PICKY_HELO_CHECK */
-#if PIPELINING
- "PIPELINING",
-#endif /* PIPELINING */
-#if SASL
-# if SASL >= 20000
- "SASLv2",
-# else /* SASL >= 20000 */
- "SASL",
-# endif /* SASL >= 20000 */
-#endif /* SASL */
-#if SCANF
- "SCANF",
-#endif /* SCANF */
-#if SM_LDAP_ERROR_ON_MISSING_ARGS
- "SM_LDAP_ERROR_ON_MISSING_ARGS",
-#endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */
-#if SMTPDEBUG
- "SMTPDEBUG",
-#endif /* SMTPDEBUG */
-#if SOCKETMAP
- "SOCKETMAP",
-#endif /* SOCKETMAP */
-#if STARTTLS
- "STARTTLS",
-#endif /* STARTTLS */
-#if SUID_ROOT_FILES_OK
- "SUID_ROOT_FILES_OK",
-#endif /* SUID_ROOT_FILES_OK */
-#if TCPWRAPPERS
- "TCPWRAPPERS",
-#endif /* TCPWRAPPERS */
-#if TLS_NO_RSA
- "TLS_NO_RSA",
-#endif /* TLS_NO_RSA */
-#if TLS_VRFY_PER_CTX
- "TLS_VRFY_PER_CTX",
-#endif /* TLS_VRFY_PER_CTX */
-#if USERDB
- "USERDB",
-#endif /* USERDB */
-#if USE_LDAP_INIT
- "USE_LDAP_INIT",
-#endif /* USE_LDAP_INIT */
-#if USE_TTYPATH
- "USE_TTYPATH",
-#endif /* USE_TTYPATH */
-#if XDEBUG
- "XDEBUG",
-#endif /* XDEBUG */
-#if XLA
- "XLA",
-#endif /* XLA */
- NULL
-};
-
-
-/*
-** OS compile options.
-*/
-
-char *OsCompileOptions[] =
-{
-#if ADDRCONFIG_IS_BROKEN
- "ADDRCONFIG_IS_BROKEN",
-#endif /* ADDRCONFIG_IS_BROKEN */
-#ifdef AUTO_NETINFO_HOSTS
- "AUTO_NETINFO_HOSTS",
-#endif /* AUTO_NETINFO_HOSTS */
-#ifdef AUTO_NIS_ALIASES
- "AUTO_NIS_ALIASES",
-#endif /* AUTO_NIS_ALIASES */
-#if BROKEN_RES_SEARCH
- "BROKEN_RES_SEARCH",
-#endif /* BROKEN_RES_SEARCH */
-#ifdef BSD4_4_SOCKADDR
- "BSD4_4_SOCKADDR",
-#endif /* BSD4_4_SOCKADDR */
-#if BOGUS_O_EXCL
- "BOGUS_O_EXCL",
-#endif /* BOGUS_O_EXCL */
-#if DEC_OSF_BROKEN_GETPWENT
- "DEC_OSF_BROKEN_GETPWENT",
-#endif /* DEC_OSF_BROKEN_GETPWENT */
-#if FAST_PID_RECYCLE
- "FAST_PID_RECYCLE",
-#endif /* FAST_PID_RECYCLE */
-#if HASCLOSEFROM
- "HASCLOSEFROM",
-#endif /* HASCLOSEFROM */
-#if HASFCHOWN
- "HASFCHOWN",
-#endif /* HASFCHOWN */
-#if HASFCHMOD
- "HASFCHMOD",
-#endif /* HASFCHMOD */
-#if HASFDWALK
- "HASFDWALK",
-#endif /* HASFDWALK */
-#if HASFLOCK
- "HASFLOCK",
-#endif /* HASFLOCK */
-#if HASGETDTABLESIZE
- "HASGETDTABLESIZE",
-#endif /* HASGETDTABLESIZE */
-#if HASGETUSERSHELL
- "HASGETUSERSHELL",
-#endif /* HASGETUSERSHELL */
-#if HASINITGROUPS
- "HASINITGROUPS",
-#endif /* HASINITGROUPS */
-#if HASLDAPGETALIASBYNAME
- "HASLDAPGETALIASBYNAME",
-#endif /* HASLDAPGETALIASBYNAME */
-#if HASLSTAT
- "HASLSTAT",
-#endif /* HASLSTAT */
-#if HASNICE
- "HASNICE",
-#endif /* HASNICE */
-#if HASRANDOM
- "HASRANDOM",
-#endif /* HASRANDOM */
-#if HASRRESVPORT
- "HASRRESVPORT",
-#endif /* HASRRESVPORT */
-#if HASSETEGID
- "HASSETEGID",
-#endif /* HASSETEGID */
-#if HASSETLOGIN
- "HASSETLOGIN",
-#endif /* HASSETLOGIN */
-#if HASSETREGID
- "HASSETREGID",
-#endif /* HASSETREGID */
-#if HASSETRESGID
- "HASSETRESGID",
-#endif /* HASSETRESGID */
-#if HASSETREUID
- "HASSETREUID",
-#endif /* HASSETREUID */
-#if HASSETRLIMIT
- "HASSETRLIMIT",
-#endif /* HASSETRLIMIT */
-#if HASSETSID
- "HASSETSID",
-#endif /* HASSETSID */
-#if HASSETUSERCONTEXT
- "HASSETUSERCONTEXT",
-#endif /* HASSETUSERCONTEXT */
-#if HASSETVBUF
- "HASSETVBUF",
-#endif /* HASSETVBUF */
-#if HAS_ST_GEN
- "HAS_ST_GEN",
-#endif /* HAS_ST_GEN */
-#if HASSRANDOMDEV
- "HASSRANDOMDEV",
-#endif /* HASSRANDOMDEV */
-#if HASURANDOMDEV
- "HASURANDOMDEV",
-#endif /* HASURANDOMDEV */
-#if HASSTRERROR
- "HASSTRERROR",
-#endif /* HASSTRERROR */
-#if HASULIMIT
- "HASULIMIT",
-#endif /* HASULIMIT */
-#if HASUNAME
- "HASUNAME",
-#endif /* HASUNAME */
-#if HASUNSETENV
- "HASUNSETENV",
-#endif /* HASUNSETENV */
-#if HASWAITPID
- "HASWAITPID",
-#endif /* HASWAITPID */
-#if IDENTPROTO
- "IDENTPROTO",
-#endif /* IDENTPROTO */
-#if IP_SRCROUTE
- "IP_SRCROUTE",
-#endif /* IP_SRCROUTE */
-#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
- "LOCK_ON_OPEN",
-#endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */
-#if MILTER_NO_NAGLE
- "MILTER_NO_NAGLE ",
-#endif /* MILTER_NO_NAGLE */
-#if NEEDFSYNC
- "NEEDFSYNC",
-#endif /* NEEDFSYNC */
-#if NEEDLINK
- "NEEDLINK",
-#endif /* NEEDLINK */
-#if NEEDLOCAL_HOSTNAME_LENGTH
- "NEEDLOCAL_HOSTNAME_LENGTH",
-#endif /* NEEDLOCAL_HOSTNAME_LENGTH */
-#if NEEDSGETIPNODE
- "NEEDSGETIPNODE",
-#endif /* NEEDSGETIPNODE */
-#if NEEDSTRSTR
- "NEEDSTRSTR",
-#endif /* NEEDSTRSTR */
-#if NEEDSTRTOL
- "NEEDSTRTOL",
-#endif /* NEEDSTRTOL */
-#ifdef NO_GETSERVBYNAME
- "NO_GETSERVBYNAME",
-#endif /* NO_GETSERVBYNAME */
-#if NOFTRUNCATE
- "NOFTRUNCATE",
-#endif /* NOFTRUNCATE */
-#if REQUIRES_DIR_FSYNC
- "REQUIRES_DIR_FSYNC",
-#endif /* REQUIRES_DIR_FSYNC */
-#if RLIMIT_NEEDS_SYS_TIME_H
- "RLIMIT_NEEDS_SYS_TIME_H",
-#endif /* RLIMIT_NEEDS_SYS_TIME_H */
-#if SAFENFSPATHCONF
- "SAFENFSPATHCONF",
-#endif /* SAFENFSPATHCONF */
-#if SECUREWARE
- "SECUREWARE",
-#endif /* SECUREWARE */
-#if SHARE_V1
- "SHARE_V1",
-#endif /* SHARE_V1 */
-#if SIOCGIFCONF_IS_BROKEN
- "SIOCGIFCONF_IS_BROKEN",
-#endif /* SIOCGIFCONF_IS_BROKEN */
-#if SIOCGIFNUM_IS_BROKEN
- "SIOCGIFNUM_IS_BROKEN",
-#endif /* SIOCGIFNUM_IS_BROKEN */
-#if SNPRINTF_IS_BROKEN
- "SNPRINTF_IS_BROKEN",
-#endif /* SNPRINTF_IS_BROKEN */
-#if SO_REUSEADDR_IS_BROKEN
- "SO_REUSEADDR_IS_BROKEN",
-#endif /* SO_REUSEADDR_IS_BROKEN */
-#if SYS5SETPGRP
- "SYS5SETPGRP",
-#endif /* SYS5SETPGRP */
-#if SYSTEM5
- "SYSTEM5",
-#endif /* SYSTEM5 */
-#if USE_DOUBLE_FORK
- "USE_DOUBLE_FORK",
-#endif /* USE_DOUBLE_FORK */
-#if USE_ENVIRON
- "USE_ENVIRON",
-#endif /* USE_ENVIRON */
-#if USE_SA_SIGACTION
- "USE_SA_SIGACTION",
-#endif /* USE_SA_SIGACTION */
-#if USE_SIGLONGJMP
- "USE_SIGLONGJMP",
-#endif /* USE_SIGLONGJMP */
-#if USEGETCONFATTR
- "USEGETCONFATTR",
-#endif /* USEGETCONFATTR */
-#if USESETEUID
- "USESETEUID",
-#endif /* USESETEUID */
-#ifdef USESYSCTL
- "USESYSCTL",
-#endif /* USESYSCTL */
-#if USING_NETSCAPE_LDAP
- "USING_NETSCAPE_LDAP",
-#endif /* USING_NETSCAPE_LDAP */
-#ifdef WAITUNION
- "WAITUNION",
-#endif /* WAITUNION */
- NULL
-};
-
-/*
-** FFR compile options.
-*/
-
-char *FFRCompileOptions[] =
-{
-#if _FFR_ADDR_TYPE_MODES
- /* more info in {addr_type}, requires m4 changes! */
- "_FFR_ADDR_TYPE_MODES",
-#endif /* _FFR_ADDR_TYPE_MODES */
-#if _FFR_ALLOW_SASLINFO
- /* DefaultAuthInfo can be specified by user. */
- /* DefaultAuthInfo doesn't really work in 8.13 anymore. */
- "_FFR_ALLOW_SASLINFO",
-#endif /* _FFR_ALLOW_SASLINFO */
-#if _FFR_BESTMX_BETTER_TRUNCATION
- /* Better truncation of list of MX records for dns map. */
- "_FFR_BESTMX_BETTER_TRUNCATION",
-#endif /* _FFR_BESTMX_BETTER_TRUNCATION */
-#if _FFR_CATCH_BROKEN_MTAS
- /* Deal with MTAs that send a reply during the DATA phase. */
- "_FFR_CATCH_BROKEN_MTAS",
-#endif /* _FFR_CATCH_BROKEN_MTAS */
-#if _FFR_CHK_QUEUE
- /* Stricter checks about queue directory permissions. */
- "_FFR_CHK_QUEUE",
-#endif /* _FFR_CHK_QUEUE */
-#if _FFR_CLIENT_SIZE
- /* Don't try to send mail if its size exceeds SIZE= of server. */
- "_FFR_CLIENT_SIZE",
-#endif /* _FFR_CLIENT_SIZE */
-#if _FFR_CRLPATH
- /* CRLPath; needs documentation; Al Smith */
- "_FFR_CRLPATH",
-#endif /* _FFR_CRLPATH */
-#if _FFR_DAEMON_NETUNIX
- /* Allow local (not just TCP) socket connection to server. */
- "_FFR_DAEMON_NETUNIX",
-#endif /* _FFR_DAEMON_NETUNIX */
-#if _FFR_DEPRECATE_MAILER_FLAG_I
- /* What it says :-) */
- "_FFR_DEPRECATE_MAILER_FLAG_I",
-#endif /* _FFR_DEPRECATE_MAILER_FLAG_I */
-#if _FFR_DM_ONE
- /* deliver first TA in background, then queue */
- "_FFR_DM_ONE",
-#endif /* _FFR_DM_ONE */
-#if _FFR_DIGUNIX_SAFECHOWN
- /* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */
-/* Problem noted by Anne Bennett of Concordia University */
- "_FFR_DIGUNIX_SAFECHOWN",
-#endif /* _FFR_DIGUNIX_SAFECHOWN */
-#if _FFR_DNSMAP_ALIASABLE
- /* Allow dns map type to be used for aliases. */
-/* Don Lewis of TDK */
- "_FFR_DNSMAP_ALIASABLE",
-#endif /* _FFR_DNSMAP_ALIASABLE */
-#if _FFR_DONTLOCKFILESFORREAD_OPTION
- /* Enable DontLockFilesForRead option. */
- "_FFR_DONTLOCKFILESFORREAD_OPTION",
-#endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */
-#if _FFR_DOTTED_USERNAMES
- /* Allow usernames with '.' */
- "_FFR_DOTTED_USERNAMES",
-#endif /* _FFR_DOTTED_USERNAMES */
-#if _FFR_DPO_CS
- /*
- ** Make DaemonPortOptions case sensitive.
- ** For some unknown reasons the code converted every option
- ** to uppercase (first letter only, as that's the only one that
- ** is actually checked). This prevented all new lower case options
- ** from working...
- ** The documentation doesn't say anything about case (in)sensitivity,
- ** which means it should be case sensitive by default,
- ** but it's not a good idea to change this within a patch release,
- ** so let's delay this to 8.15.
- */
-
- "_FFR_DPO_CS",
-#endif /* _FFR_DPO_CS */
-#if _FFR_DPRINTF_MAP
- /* dprintf map for logging */
- "_FFR_DPRINTF_MAP",
-#endif /* _FFR_DPRINTF_MAP */
-#if _FFR_DROP_TRUSTUSER_WARNING
- /*
- ** Don't issue this warning:
- ** "readcf: option TrustedUser may cause problems on systems
- ** which do not support fchown() if UseMSP is not set.
- */
-
- "_FFR_DROP_TRUSTUSER_WARNING",
-#endif /* _FFR_DROP_TRUSTUSER_WARNING */
-#if _FFR_EIGHT_BIT_ADDR_OK
- /* EightBitAddrOK: allow 8-bit e-mail addresses */
- "_FFR_EIGHT_BIT_ADDR_OK",
-#endif /* _FFR_EIGHT_BIT_ADDR_OK */
-#if _FFR_EXTRA_MAP_CHECK
- /* perform extra checks on $( $) in R lines */
- "_FFR_EXTRA_MAP_CHECK",
-#endif /* _FFR_EXTRA_MAP_CHECK */
-#if _FFR_GETHBN_ExFILE
- /*
- ** According to Motonori Nakamura some gethostbyname()
- ** implementations (TurboLinux?) may (temporarily) fail
- ** due to a lack of file discriptors. Enabling this FFR
- ** will check errno for EMFILE and ENFILE and in case of a match
- ** cause a temporary error instead of a permanent error.
- ** The right solution is of course to file a bug against those
- ** systems such that they actually set h_errno = TRY_AGAIN.
- */
-
- "_FFR_GETHBN_ExFILE",
-#endif /* _FFR_GETHBN_ExFILE */
-#if _FFR_FIX_DASHT
- /*
- ** If using -t, force not sending to argv recipients, even
- ** if they are mentioned in the headers.
- */
-
- "_FFR_FIX_DASHT",
-#endif /* _FFR_FIX_DASHT */
-#if _FFR_FORWARD_SYSERR
- /* Cause a "syserr" if forward file isn't "safe". */
- "_FFR_FORWARD_SYSERR",
-#endif /* _FFR_FORWARD_SYSERR */
-#if _FFR_GEN_ORCPT
- /* Generate a ORCPT DSN arg if not already provided */
- "_FFR_GEN_ORCPT",
-#endif /* _FFR_GEN_ORCPT */
-#if _FFR_GROUPREADABLEAUTHINFOFILE
- /* Allow group readable DefaultAuthInfo file. */
- "_FFR_GROUPREADABLEAUTHINFOFILE",
-#endif /* _FFR_GROUPREADABLEAUTHINFOFILE */
-#if _FFR_HANDLE_ISO8859_GECOS
- /*
- ** Allow ISO 8859 characters in GECOS field: replace them
- ** ith ASCII "equivalent".
- */
-
-/* Peter Eriksson of Linkopings universitet */
- "_FFR_HANDLE_ISO8859_GECOS",
-#endif /* _FFR_HANDLE_ISO8859_GECOS */
-#if _FFR_HPUX_NSSWITCH
- /* Use nsswitch on HP-UX */
- "_FFR_HPUX_NSSWITCH",
-#endif /* _FFR_HPUX_NSSWITCH */
-#if _FFR_IGNORE_BOGUS_ADDR
- /* Ignore addresses for which prescan() failed */
- "_FFR_IGNORE_BOGUS_ADDR",
-#endif /* _FFR_IGNORE_BOGUS_ADDR */
-#if _FFR_IGNORE_EXT_ON_HELO
- /* Ignore extensions offered in response to HELO */
- "_FFR_IGNORE_EXT_ON_HELO",
-#endif /* _FFR_IGNORE_EXT_ON_HELO */
-#if _FFR_MAXDATASIZE
- /*
- ** It is possible that a header is larger than MILTER_CHUNK_SIZE,
- ** hence this shouldn't be used as limit for milter communication.
- ** see also libmilter/comm.c
- ** Gurusamy Sarathy of ActiveState
- */
-
- "_FFR_MAXDATASIZE",
-#endif /* _FFR_MAXDATASIZE */
-#if _FFR_MAX_FORWARD_ENTRIES
- /* Try to limit number of .forward entries */
- /* (doesn't work) */
-/* Randall S. Winchester of the University of Maryland */
- "_FFR_MAX_FORWARD_ENTRIES",
-#endif /* _FFR_MAX_FORWARD_ENTRIES */
-#if _FFR_MAX_SLEEP_TIME
- /* Limit sleep(2) time in libsm/clock.c */
- "_FFR_MAX_SLEEP_TIME",
-#endif /* _FFR_MAX_SLEEP_TIME */
-#if _FFR_MEMSTAT
- /* Check free memory */
- "_FFR_MEMSTAT",
-#endif /* _FFR_MEMSTAT */
-#if _FFR_MILTER_CHECK
- "_FFR_MILTER_CHECK",
-#endif /* _FFR_MILTER_CHECK */
-#if _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF
- /*
- ** milter_body() uses the same conversion algorithm as putbody()
- ** to translate the "local" df format (\n) to SMTP format (\r\n).
- ** However, putbody() and mime8to7() use different conversion
- ** algorithms.
- ** If the input date does not follow the SMTP standard
- ** (e.g., if it has "naked \r"s), then the output from putbody()
- ** and mime8to7() will most likely be different.
- ** By turning on this FFR milter_body() will try to "imitate"
- ** mime8to7().
- ** Note: there is no (simple) way to deal with both conversions
- ** in a consistent manner. Moreover, as the "GiGo" principle applies,
- ** it's not really worth to fix it.
- */
-
- "_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF",
-#endif /* _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF */
-#if _FFR_MILTER_CHECK_REJECTIONS_TOO
- /*
- ** Also send RCPTs that are rejected by check_rcpt to a milter
- ** (if requested during option negotiation).
- */
-
- "_FFR_MILTER_CHECK_REJECTIONS_TOO",
-#endif /* _FFR_MILTER_CHECK_REJECTIONS_TOO */
-#if _FFR_MIME7TO8_OLD
- /* Old mime7to8 code, the new is broken for at least one example. */
- "_FFR_MIME7TO8_OLD",
-#endif /* _FFR_MAX_SLEEP_TIME */
-#if _FFR_MORE_MACROS
- /* allow more long macro names ("unprintable" characters). */
- "_FFR_MORE_MACROS",
-#endif /* _FFR_MORE_MACROS */
-#if _FFR_MSG_ACCEPT
- /* allow to override "Message accepted for delivery" */
- "_FFR_MSG_ACCEPT",
-#endif /* _FFR_MSG_ACCEPT */
-#if _FFR_NODELAYDSN_ON_HOLD
- /* Do not issue a DELAY DSN for mailers that use the hold flag. */
-/* Steven Pitzl */
- "_FFR_NODELAYDSN_ON_HOLD",
-#endif /* _FFR_NODELAYDSN_ON_HOLD */
-#if _FFR_NO_PIPE
- /* Disable PIPELINING, delay client if used. */
- "_FFR_NO_PIPE",
-#endif /* _FFR_NO_PIPE */
-#if _FFR_LDAP_NETWORK_TIMEOUT
- /* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */
- "_FFR_LDAP_NETWORK_TIMEOUT",
-#endif /* _FFR_LDAP_NETWORK_TIMEOUT */
-#if _FFR_LOG_NTRIES
- /* log ntries=, from Nik Clayton of FreeBSD */
- "_FFR_LOG_NTRIES",
-#endif /* _FFR_LOG_NTRIES */
-#if _FFR_QF_PARANOIA
- "_FFR_QF_PARANOIA",
-#endif /* _FFR_QF_PARANOIA */
-#if _FFR_QUEUEDELAY
- /* Exponential queue delay; disabled in 8.13 since it isn't used. */
- "_FFR_QUEUEDELAY",
-#endif /* _FFR_QUEUEDELAY */
-#if _FFR_QUEUE_GROUP_SORTORDER
- /* Allow QueueSortOrder per queue group. */
-/* XXX: Still need to actually use qgrp->qg_sortorder */
- "_FFR_QUEUE_GROUP_SORTORDER",
-#endif /* _FFR_QUEUE_GROUP_SORTORDER */
-#if _FFR_QUEUE_MACRO
- /* Define {queue} macro. */
- "_FFR_QUEUE_MACRO",
-#endif /* _FFR_QUEUE_MACRO */
-#if _FFR_QUEUE_RUN_PARANOIA
- /* Additional checks when doing queue runs; interval of checks */
- "_FFR_QUEUE_RUN_PARANOIA",
-#endif /* _FFR_QUEUE_RUN_PARANOIA */
-#if _FFR_QUEUE_SCHED_DBG
- /* Debug output for the queue scheduler. */
- "_FFR_QUEUE_SCHED_DBG",
-#endif /* _FFR_QUEUE_SCHED_DBG */
-#if _FFR_REDIRECTEMPTY
- /*
- ** envelope <> can't be sent to mailing lists, only owner-
- ** send spam of this type to owner- of the list
- ** ---- to stop spam from going to mailing lists.
- */
-
- "_FFR_REDIRECTEMPTY",
-#endif /* _FFR_REDIRECTEMPTY */
-#if _FFR_RESET_MACRO_GLOBALS
- /* Allow macro 'j' to be set dynamically via rulesets. */
- "_FFR_RESET_MACRO_GLOBALS",
-#endif /* _FFR_RESET_MACRO_GLOBALS */
-#if _FFR_RHS
- /* Random shuffle for queue sorting. */
- "_FFR_RHS",
-#endif /* _FFR_RHS */
-#if _FFR_RUNPQG
- /*
- ** allow -qGqueue_group -qp to work, i.e.,
- ** restrict a persistent queue runner to a queue group.
- */
-
- "_FFR_RUNPQG",
-#endif /* _FFR_RUNPQG */
-#if _FFR_SESSID
- /* session id (for logging) */
- "_FFR_SESSID",
-#endif /* _FFR_SESSID */
-#if _FFR_SHM_STATUS
- /* Donated code (unused). */
- "_FFR_SHM_STATUS",
-#endif /* _FFR_SHM_STATUS */
-#if _FFR_LDAP_SINGLEDN
- /*
- ** The LDAP database map code in Sendmail 8.12.10, when
- ** given the -1 switch, would match only a single DN,
- ** but was able to return multiple attributes for that
- ** DN. In Sendmail 8.13 this "bug" was corrected to
- ** only return if exactly one attribute matched.
- **
- ** Unfortunately, our configuration uses the former
- ** behaviour. Attached is a relatively simple patch
- ** to 8.13.4 which adds a -2 switch (for lack of a
- ** better option) which returns the single dn/multiple
- ** attributes.
- **
- ** Jeffrey T. Eaton, Carnegie-Mellon University
- */
-
- "_FFR_LDAP_SINGLEDN",
-#endif /* _FFR_LDAP_SINGLEDN */
-#if _FFR_SKIP_DOMAINS
- /* process every N'th domain instead of every N'th message */
- "_FFR_SKIP_DOMAINS",
-#endif /* _FFR_SKIP_DOMAINS */
-#if _FFR_SLEEP_USE_SELECT
- /* Use select(2) in libsm/clock.c to emulate sleep(2) */
- "_FFR_SLEEP_USE_SELECT ",
-#endif /* _FFR_SLEEP_USE_SELECT */
-#if _FFR_SPT_ALIGN
- /*
- ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64
- ** bit alignment, so unless each piece of argv and envp is a multiple
- ** of 8 bytes (including terminating NULL), initsetproctitle() won't
- ** use any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE
- ** if you use this FFR.
- */
-
-/* Chris Adams of HiWAAY Informations Services */
- "_FFR_SPT_ALIGN",
-#endif /* _FFR_SPT_ALIGN */
-#if _FFR_SS_PER_DAEMON
- /* SuperSafe per DaemonPortOptions: 'T' (better letter?) */
- "_FFR_SS_PER_DAEMON",
-#endif /* _FFR_SS_PER_DAEMON */
-#if _FFR_TIMERS
- /* Donated code (unused). */
- "_FFR_TIMERS",
-#endif /* _FFR_TIMERS */
-#if _FFR_TLS_1
- /* More STARTTLS options, e.g., secondary certs. */
- "_FFR_TLS_1",
-#endif /* _FFR_TLS_1 */
-#if _FFR_TRUSTED_QF
- /*
- ** If we don't own the file mark it as unsafe.
- ** However, allow TrustedUser to own it as well
- ** in case TrustedUser manipulates the queue.
- */
-
- "_FFR_TRUSTED_QF",
-#endif /* _FFR_TRUSTED_QF */
-#if _FFR_USE_SEM_LOCKING
- "_FFR_USE_SEM_LOCKING",
-#endif /* _FFR_USE_SEM_LOCKING */
-#if _FFR_USE_SETLOGIN
- /* Use setlogin() */
-/* Peter Philipp */
- "_FFR_USE_SETLOGIN",
-#endif /* _FFR_USE_SETLOGIN */
- NULL
-};
-
OpenPOWER on IntegriCloud