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