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