diff options
Diffstat (limited to 'contrib/sendmail/src/conf.c')
-rw-r--r-- | contrib/sendmail/src/conf.c | 6376 |
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 -}; - |