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 16 SM_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 48 static void setupmaps __P((void)); 49 static void setupmailers __P((void)); 50 static void setupqueues __P((void)); 51 static int get_num_procs_online __P((void)); 52 static int add_hostnames __P((SOCKADDR *)); 53 54 #if NETINET6 && NEEDSGETIPNODE 55 static struct hostent *sm_getipnodebyname __P((const char *, int, int, int *)); 56 static 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 /* 86 ** Header info table 87 ** Final (null) entry contains the flags used for any other field. 88 ** 89 ** Not all of these are actually handled specially by sendmail 90 ** at this time. They are included as placeholders, to let 91 ** you know that "someday" I intend to have sendmail do 92 ** something with them. 93 */ 94 95 #if _FFR_MTA_MODE 96 # define Xflags H_ASIS 97 #else 98 # define Xflags 0 99 #endif 100 101 struct hdrinfo HdrInfo[] = 102 { 103 /* originator fields, most to least significant */ 104 { "resent-sender", H_FROM|H_RESENT, NULL }, 105 { "resent-from", H_FROM|H_RESENT, NULL }, 106 { "resent-reply-to", H_FROM|H_RESENT, NULL }, 107 { "sender", H_FROM, NULL }, 108 { "from", H_FROM | Xflags, NULL }, 109 { "reply-to", H_FROM | Xflags, NULL }, 110 { "errors-to", H_FROM|H_ERRORSTO, NULL }, 111 { "full-name", H_ACHECK, NULL }, 112 { "return-receipt-to", H_RECEIPTTO, NULL }, 113 { "delivery-receipt-to", H_RECEIPTTO, NULL }, 114 { "disposition-notification-to", H_FROM, NULL }, 115 116 /* destination fields */ 117 { "to", H_RCPT | Xflags, NULL }, 118 { "resent-to", H_RCPT|H_RESENT, NULL }, 119 { "cc", H_RCPT, NULL }, 120 { "resent-cc", H_RCPT|H_RESENT, NULL }, 121 { "bcc", H_RCPT|H_BCC, NULL }, 122 { "resent-bcc", H_RCPT|H_BCC|H_RESENT, NULL }, 123 { "apparently-to", H_RCPT, NULL }, 124 125 /* message identification and control */ 126 { "message-id", 0, NULL }, 127 { "resent-message-id", H_RESENT, NULL }, 128 #if !NO_EOH_FIELDS 129 { "message", H_EOH, NULL }, 130 { "text", H_EOH, NULL }, 131 #endif 132 133 /* date fields */ 134 { "date", 0, NULL }, 135 { "resent-date", H_RESENT, NULL }, 136 137 /* trace fields */ 138 { "received", H_TRACE|H_FORCE, NULL }, 139 { "x400-received", H_TRACE|H_FORCE, NULL }, 140 { "via", H_TRACE|H_FORCE, NULL }, 141 { "mail-from", H_TRACE|H_FORCE, NULL }, 142 143 /* miscellaneous fields */ 144 { "comments", H_FORCE|H_ENCODABLE, NULL }, 145 { "return-path", H_FORCE|H_ACHECK|H_BINDLATE, NULL }, 146 { "content-transfer-encoding", H_CTE, NULL }, 147 { "content-type", H_CTYPE, NULL }, 148 { "content-length", H_ACHECK, NULL }, 149 { "subject", H_ENCODABLE, NULL }, 150 { "x-authentication-warning", H_FORCE, NULL }, 151 152 { NULL, 0, NULL } 153 }; 154 155 /* 156 ** Privacy values 157 */ 158 159 struct prival PrivacyValues[] = 160 { 161 { "public", PRIV_PUBLIC }, 162 { "needmailhelo", PRIV_NEEDMAILHELO }, 163 { "needexpnhelo", PRIV_NEEDEXPNHELO }, 164 { "needvrfyhelo", PRIV_NEEDVRFYHELO }, 165 { "noexpn", PRIV_NOEXPN }, 166 { "novrfy", PRIV_NOVRFY }, 167 { "restrictexpand", PRIV_RESTRICTEXPAND }, 168 { "restrictmailq", PRIV_RESTRICTMAILQ }, 169 { "restrictqrun", PRIV_RESTRICTQRUN }, 170 { "noetrn", PRIV_NOETRN }, 171 { "noverb", PRIV_NOVERB }, 172 { "authwarnings", PRIV_AUTHWARNINGS }, 173 { "noreceipts", PRIV_NORECEIPTS }, 174 { "nobodyreturn", PRIV_NOBODYRETN }, 175 { "goaway", PRIV_GOAWAY }, 176 { "noactualrecipient", PRIV_NOACTUALRECIPIENT }, 177 #if _FFR_NOREFLECT 178 { "noreflection", PRIV_NOREFLECTION }, 179 #endif 180 { NULL, 0 } 181 }; 182 183 /* 184 ** DontBlameSendmail values 185 */ 186 187 struct dbsval DontBlameSendmailValues[] = 188 { 189 { "safe", DBS_SAFE }, 190 { "assumesafechown", DBS_ASSUMESAFECHOWN }, 191 { "groupwritabledirpathsafe", DBS_GROUPWRITABLEDIRPATHSAFE }, 192 { "groupwritableforwardfilesafe", 193 DBS_GROUPWRITABLEFORWARDFILESAFE }, 194 { "groupwritableincludefilesafe", 195 DBS_GROUPWRITABLEINCLUDEFILESAFE }, 196 { "groupwritablealiasfile", DBS_GROUPWRITABLEALIASFILE }, 197 { "worldwritablealiasfile", DBS_WORLDWRITABLEALIASFILE }, 198 { "forwardfileinunsafedirpath", DBS_FORWARDFILEINUNSAFEDIRPATH }, 199 { "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH }, 200 { "mapinunsafedirpath", DBS_MAPINUNSAFEDIRPATH }, 201 { "linkedaliasfileinwritabledir", 202 DBS_LINKEDALIASFILEINWRITABLEDIR }, 203 { "linkedclassfileinwritabledir", 204 DBS_LINKEDCLASSFILEINWRITABLEDIR }, 205 { "linkedforwardfileinwritabledir", 206 DBS_LINKEDFORWARDFILEINWRITABLEDIR }, 207 { "linkedincludefileinwritabledir", 208 DBS_LINKEDINCLUDEFILEINWRITABLEDIR }, 209 { "linkedmapinwritabledir", DBS_LINKEDMAPINWRITABLEDIR }, 210 { "linkedserviceswitchfileinwritabledir", 211 DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR }, 212 { "filedeliverytohardlink", DBS_FILEDELIVERYTOHARDLINK }, 213 { "filedeliverytosymlink", DBS_FILEDELIVERYTOSYMLINK }, 214 { "writemaptohardlink", DBS_WRITEMAPTOHARDLINK }, 215 { "writemaptosymlink", DBS_WRITEMAPTOSYMLINK }, 216 { "writestatstohardlink", DBS_WRITESTATSTOHARDLINK }, 217 { "writestatstosymlink", DBS_WRITESTATSTOSYMLINK }, 218 { "forwardfileingroupwritabledirpath", 219 DBS_FORWARDFILEINGROUPWRITABLEDIRPATH }, 220 { "includefileingroupwritabledirpath", 221 DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH }, 222 { "classfileinunsafedirpath", DBS_CLASSFILEINUNSAFEDIRPATH }, 223 { "errorheaderinunsafedirpath", DBS_ERRORHEADERINUNSAFEDIRPATH }, 224 { "helpfileinunsafedirpath", DBS_HELPFILEINUNSAFEDIRPATH }, 225 { "forwardfileinunsafedirpathsafe", 226 DBS_FORWARDFILEINUNSAFEDIRPATHSAFE }, 227 { "includefileinunsafedirpathsafe", 228 DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE }, 229 { "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH }, 230 { "runwritableprogram", DBS_RUNWRITABLEPROGRAM }, 231 { "nonrootsafeaddr", DBS_NONROOTSAFEADDR }, 232 { "truststickybit", DBS_TRUSTSTICKYBIT }, 233 { "dontwarnforwardfileinunsafedirpath", 234 DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH }, 235 { "insufficiententropy", DBS_INSUFFICIENTENTROPY }, 236 { "groupreadablesasldbfile", DBS_GROUPREADABLESASLDBFILE }, 237 { "groupwritablesasldbfile", DBS_GROUPWRITABLESASLDBFILE }, 238 { "groupwritableforwardfile", DBS_GROUPWRITABLEFORWARDFILE }, 239 { "groupwritableincludefile", DBS_GROUPWRITABLEINCLUDEFILE }, 240 { "worldwritableforwardfile", DBS_WORLDWRITABLEFORWARDFILE }, 241 { "worldwritableincludefile", DBS_WORLDWRITABLEINCLUDEFILE }, 242 { "groupreadablekeyfile", DBS_GROUPREADABLEKEYFILE }, 243 { "groupreadabledefaultauthinfofile", 244 DBS_GROUPREADABLEAUTHINFOFILE }, 245 { NULL, 0 } 246 }; 247 248 /* 249 ** Miscellaneous stuff. 250 */ 251 252 int 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 278 void 279 setdefaults(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 449 void 450 setdefuser() 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 473 static void 474 setupqueues() 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 486 static void 487 setupmailers() 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 526 static void 527 setupmaps() 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 773 void 774 inithostmaps() 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 915 int 916 switch_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 1189 char * 1190 username() 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 1254 char * 1255 ttypath() 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 1312 int 1313 checkcompat(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 1339 static void 1340 init_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 1371 void 1372 init_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 1413 #ifdef VENDOR_DEFAULT 1414 VendorCode = VENDOR_DEFAULT; 1415 #else 1416 VendorCode = VENDOR_BERKELEY; 1417 #endif 1418 } 1419 /* 1420 ** INIT_VENDOR_MACROS -- vendor-dependent macro initializations 1421 ** 1422 ** Called once, on startup. 1423 ** 1424 ** Parameters: 1425 ** e -- the global envelope. 1426 ** 1427 ** Returns: 1428 ** none. 1429 ** 1430 ** Side Effects: 1431 ** vendor-dependent. 1432 */ 1433 1434 void 1435 init_vendor_macros(e) 1436 register ENVELOPE *e; 1437 { 1438 } 1439 /* 1440 ** GETLA -- get the current load average 1441 ** 1442 ** This code stolen from la.c. 1443 ** 1444 ** Parameters: 1445 ** none. 1446 ** 1447 ** Returns: 1448 ** The current load average as an integer. 1449 ** 1450 ** Side Effects: 1451 ** none. 1452 */ 1453 1454 /* try to guess what style of load average we have */ 1455 #define LA_ZERO 1 /* always return load average as zero */ 1456 #define LA_INT 2 /* read kmem for avenrun; interpret as long */ 1457 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 1458 #define LA_SUBR 4 /* call getloadavg */ 1459 #define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */ 1460 #define LA_SHORT 6 /* read kmem for avenrun; interpret as short */ 1461 #define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */ 1462 #define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */ 1463 #define LA_DGUX 9 /* special DGUX implementation */ 1464 #define LA_HPUX 10 /* special HPUX implementation */ 1465 #define LA_IRIX6 11 /* special IRIX 6.2 implementation */ 1466 #define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */ 1467 #define LA_DEVSHORT 13 /* read short from a device */ 1468 #define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */ 1469 #define LA_PSET 15 /* Solaris per-processor-set load average */ 1470 #define LA_LONGLONG 17 /* read kmem for avenrun; interpret as long long */ 1471 1472 /* do guesses based on general OS type */ 1473 #ifndef LA_TYPE 1474 # define LA_TYPE LA_ZERO 1475 #endif 1476 1477 #ifndef FSHIFT 1478 # if defined(unixpc) 1479 # define FSHIFT 5 1480 # endif 1481 1482 # if defined(__alpha) || defined(IRIX) 1483 # define FSHIFT 10 1484 # endif 1485 1486 #endif /* ! FSHIFT */ 1487 1488 #ifndef FSHIFT 1489 # define FSHIFT 8 1490 #endif 1491 1492 #ifndef FSCALE 1493 # define FSCALE (1 << FSHIFT) 1494 #endif 1495 1496 #ifndef LA_AVENRUN 1497 # ifdef SYSTEM5 1498 # define LA_AVENRUN "avenrun" 1499 # else 1500 # define LA_AVENRUN "_avenrun" 1501 # endif 1502 #endif /* ! LA_AVENRUN */ 1503 1504 /* _PATH_KMEM should be defined in <paths.h> */ 1505 #ifndef _PATH_KMEM 1506 # define _PATH_KMEM "/dev/kmem" 1507 #endif 1508 1509 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) 1510 1511 # include <nlist.h> 1512 1513 /* _PATH_UNIX should be defined in <paths.h> */ 1514 # ifndef _PATH_UNIX 1515 # if defined(SYSTEM5) 1516 # define _PATH_UNIX "/unix" 1517 # else 1518 # define _PATH_UNIX "/vmunix" 1519 # endif 1520 # endif /* ! _PATH_UNIX */ 1521 1522 # ifdef _AUX_SOURCE 1523 struct nlist Nl[2]; 1524 # else /* _AUX_SOURCE */ 1525 struct nlist Nl[] = 1526 { 1527 { LA_AVENRUN }, 1528 { 0 }, 1529 }; 1530 # endif /* _AUX_SOURCE */ 1531 # define X_AVENRUN 0 1532 1533 int 1534 getla() 1535 { 1536 int j; 1537 static int kmem = -1; 1538 # if LA_TYPE == LA_INT 1539 long avenrun[3]; 1540 # else /* LA_TYPE == LA_INT */ 1541 # if LA_TYPE == LA_SHORT 1542 short avenrun[3]; 1543 # else 1544 # if LA_TYPE == LA_LONGLONG 1545 long long avenrun[3]; 1546 # else 1547 double avenrun[3]; 1548 # endif 1549 # endif /* LA_TYPE == LA_SHORT */ 1550 # endif /* LA_TYPE == LA_INT */ 1551 extern off_t lseek __P((int, off_t, int)); 1552 1553 if (kmem < 0) 1554 { 1555 # ifdef _AUX_SOURCE 1556 (void) sm_strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN, 1557 sizeof(Nl[X_AVENRUN].n_name)); 1558 Nl[1].n_name[0] = '\0'; 1559 # endif /* _AUX_SOURCE */ 1560 1561 # if defined(_AIX3) || defined(_AIX4) 1562 if (knlist(Nl, 1, sizeof(Nl[0])) < 0) 1563 # else 1564 if (nlist(_PATH_UNIX, Nl) < 0) 1565 # endif 1566 { 1567 if (tTd(3, 1)) 1568 sm_dprintf("getla: nlist(%s): %s\n", _PATH_UNIX, 1569 sm_errstring(errno)); 1570 return -1; 1571 } 1572 if (Nl[X_AVENRUN].n_value == 0) 1573 { 1574 if (tTd(3, 1)) 1575 sm_dprintf("getla: nlist(%s, %s) ==> 0\n", 1576 _PATH_UNIX, LA_AVENRUN); 1577 return -1; 1578 } 1579 # ifdef NAMELISTMASK 1580 Nl[X_AVENRUN].n_value &= NAMELISTMASK; 1581 # endif 1582 1583 kmem = open(_PATH_KMEM, 0, 0); 1584 if (kmem < 0) 1585 { 1586 if (tTd(3, 1)) 1587 sm_dprintf("getla: open(/dev/kmem): %s\n", 1588 sm_errstring(errno)); 1589 return -1; 1590 } 1591 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1592 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1593 { 1594 if (tTd(3, 1)) 1595 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1596 sm_errstring(errno)); 1597 (void) close(kmem); 1598 kmem = -1; 1599 return -1; 1600 } 1601 } 1602 if (tTd(3, 20)) 1603 sm_dprintf("getla: symbol address = %#lx\n", 1604 (unsigned long) Nl[X_AVENRUN].n_value); 1605 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 || 1606 read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun)) 1607 { 1608 /* thank you Ian */ 1609 if (tTd(3, 1)) 1610 sm_dprintf("getla: lseek or read: %s\n", 1611 sm_errstring(errno)); 1612 return -1; 1613 } 1614 # if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) 1615 if (tTd(3, 5)) 1616 { 1617 # if LA_TYPE == LA_SHORT 1618 sm_dprintf("getla: avenrun = %d", avenrun[0]); 1619 if (tTd(3, 15)) 1620 sm_dprintf(", %d, %d", avenrun[1], avenrun[2]); 1621 # else /* LA_TYPE == LA_SHORT */ 1622 # if LA_TYPE == LA_LONGLONG 1623 sm_dprintf("getla: avenrun = %lld", avenrun[0]); 1624 if (tTd(3, 15)) 1625 sm_dprintf(", %lld, %lld", avenrun[1], avenrun[2]); 1626 # else /* LA_TYPE == LA_LONGLONG */ 1627 sm_dprintf("getla: avenrun = %ld", avenrun[0]); 1628 if (tTd(3, 15)) 1629 sm_dprintf(", %ld, %ld", avenrun[1], avenrun[2]); 1630 # endif /* LA_TYPE == LA_LONGLONG */ 1631 # endif /* LA_TYPE == LA_SHORT */ 1632 sm_dprintf("\n"); 1633 } 1634 if (tTd(3, 1)) 1635 sm_dprintf("getla: %d\n", 1636 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1637 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1638 # else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */ 1639 if (tTd(3, 5)) 1640 { 1641 sm_dprintf("getla: avenrun = %g", avenrun[0]); 1642 if (tTd(3, 15)) 1643 sm_dprintf(", %g, %g", avenrun[1], avenrun[2]); 1644 sm_dprintf("\n"); 1645 } 1646 if (tTd(3, 1)) 1647 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 1648 return ((int) (avenrun[0] + 0.5)); 1649 # endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */ 1650 } 1651 1652 #endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) || (LA_TYPE == LA_LONGLONG) */ 1653 1654 #if LA_TYPE == LA_READKSYM 1655 1656 # include <sys/ksym.h> 1657 1658 int 1659 getla() 1660 { 1661 int j; 1662 static int kmem = -1; 1663 long avenrun[3]; 1664 struct mioc_rksym mirk; 1665 1666 if (kmem < 0) 1667 { 1668 kmem = open("/dev/kmem", 0, 0); 1669 if (kmem < 0) 1670 { 1671 if (tTd(3, 1)) 1672 sm_dprintf("getla: open(/dev/kmem): %s\n", 1673 sm_errstring(errno)); 1674 return -1; 1675 } 1676 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1677 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1678 { 1679 if (tTd(3, 1)) 1680 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1681 sm_errstring(errno)); 1682 (void) close(kmem); 1683 kmem = -1; 1684 return -1; 1685 } 1686 } 1687 mirk.mirk_symname = LA_AVENRUN; 1688 mirk.mirk_buf = avenrun; 1689 mirk.mirk_buflen = sizeof(avenrun); 1690 if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0) 1691 { 1692 if (tTd(3, 1)) 1693 sm_dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n", 1694 sm_errstring(errno)); 1695 return -1; 1696 } 1697 if (tTd(3, 5)) 1698 { 1699 sm_dprintf("getla: avenrun = %d", avenrun[0]); 1700 if (tTd(3, 15)) 1701 sm_dprintf(", %d, %d", avenrun[1], avenrun[2]); 1702 sm_dprintf("\n"); 1703 } 1704 if (tTd(3, 1)) 1705 sm_dprintf("getla: %d\n", 1706 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1707 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1708 } 1709 1710 #endif /* LA_TYPE == LA_READKSYM */ 1711 1712 #if LA_TYPE == LA_DGUX 1713 1714 # include <sys/dg_sys_info.h> 1715 1716 int 1717 getla() 1718 { 1719 struct dg_sys_info_load_info load_info; 1720 1721 dg_sys_info((long *)&load_info, 1722 DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); 1723 1724 if (tTd(3, 1)) 1725 sm_dprintf("getla: %d\n", (int) (load_info.one_minute + 0.5)); 1726 1727 return ((int) (load_info.one_minute + 0.5)); 1728 } 1729 1730 #endif /* LA_TYPE == LA_DGUX */ 1731 1732 #if LA_TYPE == LA_HPUX 1733 1734 /* forward declarations to keep gcc from complaining */ 1735 struct pst_dynamic; 1736 struct pst_status; 1737 struct pst_static; 1738 struct pst_vminfo; 1739 struct pst_diskinfo; 1740 struct pst_processor; 1741 struct pst_lv; 1742 struct pst_swapinfo; 1743 1744 # include <sys/param.h> 1745 # include <sys/pstat.h> 1746 1747 int 1748 getla() 1749 { 1750 struct pst_dynamic pstd; 1751 1752 if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic), 1753 (size_t) 1, 0) == -1) 1754 return 0; 1755 1756 if (tTd(3, 1)) 1757 sm_dprintf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); 1758 1759 return (int) (pstd.psd_avg_1_min + 0.5); 1760 } 1761 1762 #endif /* LA_TYPE == LA_HPUX */ 1763 1764 #if LA_TYPE == LA_SUBR 1765 1766 int 1767 getla() 1768 { 1769 double avenrun[3]; 1770 1771 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 1772 { 1773 if (tTd(3, 1)) 1774 sm_dprintf("getla: getloadavg failed: %s", 1775 sm_errstring(errno)); 1776 return -1; 1777 } 1778 if (tTd(3, 1)) 1779 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 1780 return ((int) (avenrun[0] + 0.5)); 1781 } 1782 1783 #endif /* LA_TYPE == LA_SUBR */ 1784 1785 #if LA_TYPE == LA_MACH 1786 1787 /* 1788 ** This has been tested on NEXTSTEP release 2.1/3.X. 1789 */ 1790 1791 # if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 1792 # include <mach/mach.h> 1793 # else 1794 # include <mach.h> 1795 # endif 1796 1797 int 1798 getla() 1799 { 1800 processor_set_t default_set; 1801 kern_return_t error; 1802 unsigned int info_count; 1803 struct processor_set_basic_info info; 1804 host_t host; 1805 1806 error = processor_set_default(host_self(), &default_set); 1807 if (error != KERN_SUCCESS) 1808 { 1809 if (tTd(3, 1)) 1810 sm_dprintf("getla: processor_set_default failed: %s", 1811 sm_errstring(errno)); 1812 return -1; 1813 } 1814 info_count = PROCESSOR_SET_BASIC_INFO_COUNT; 1815 if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, 1816 &host, (processor_set_info_t)&info, 1817 &info_count) != KERN_SUCCESS) 1818 { 1819 if (tTd(3, 1)) 1820 sm_dprintf("getla: processor_set_info failed: %s", 1821 sm_errstring(errno)); 1822 return -1; 1823 } 1824 if (tTd(3, 1)) 1825 sm_dprintf("getla: %d\n", 1826 (int) ((info.load_average + (LOAD_SCALE / 2)) / 1827 LOAD_SCALE)); 1828 return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE; 1829 } 1830 1831 #endif /* LA_TYPE == LA_MACH */ 1832 1833 #if LA_TYPE == LA_PROCSTR 1834 # if SM_CONF_BROKEN_STRTOD 1835 ERROR: This OS has most likely a broken strtod() implemenentation. 1836 ERROR: The function is required for getla(). 1837 ERROR: Check the compilation options _LA_PROCSTR and 1838 ERROR: _SM_CONF_BROKEN_STRTOD (without the leading _). 1839 # endif /* SM_CONF_BROKEN_STRTOD */ 1840 1841 /* 1842 ** Read /proc/loadavg for the load average. This is assumed to be 1843 ** in a format like "0.15 0.12 0.06". 1844 ** 1845 ** Initially intended for Linux. This has been in the kernel 1846 ** since at least 0.99.15. 1847 */ 1848 1849 # ifndef _PATH_LOADAVG 1850 # define _PATH_LOADAVG "/proc/loadavg" 1851 # endif 1852 1853 int 1854 getla() 1855 { 1856 double avenrun; 1857 register int result; 1858 SM_FILE_T *fp; 1859 1860 fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_LOADAVG, SM_IO_RDONLY, 1861 NULL); 1862 if (fp == NULL) 1863 { 1864 if (tTd(3, 1)) 1865 sm_dprintf("getla: sm_io_open(%s): %s\n", 1866 _PATH_LOADAVG, sm_errstring(errno)); 1867 return -1; 1868 } 1869 result = sm_io_fscanf(fp, SM_TIME_DEFAULT, "%lf", &avenrun); 1870 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1871 if (result != 1) 1872 { 1873 if (tTd(3, 1)) 1874 sm_dprintf("getla: sm_io_fscanf() = %d: %s\n", 1875 result, sm_errstring(errno)); 1876 return -1; 1877 } 1878 1879 if (tTd(3, 1)) 1880 sm_dprintf("getla(): %.2f\n", avenrun); 1881 1882 return ((int) (avenrun + 0.5)); 1883 } 1884 1885 #endif /* LA_TYPE == LA_PROCSTR */ 1886 1887 #if LA_TYPE == LA_IRIX6 1888 1889 # include <sys/sysmp.h> 1890 1891 # ifdef _UNICOSMP 1892 # define CAST_SYSMP(x) (x) 1893 # else 1894 # define CAST_SYSMP(x) ((x) & 0x7fffffff) 1895 # endif 1896 1897 int 1898 getla(void) 1899 { 1900 int j; 1901 static int kmem = -1; 1902 int avenrun[3]; 1903 1904 if (kmem < 0) 1905 { 1906 kmem = open(_PATH_KMEM, 0, 0); 1907 if (kmem < 0) 1908 { 1909 if (tTd(3, 1)) 1910 sm_dprintf("getla: open(%s): %s\n", _PATH_KMEM, 1911 sm_errstring(errno)); 1912 return -1; 1913 } 1914 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1915 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1916 { 1917 if (tTd(3, 1)) 1918 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1919 sm_errstring(errno)); 1920 (void) close(kmem); 1921 kmem = -1; 1922 return -1; 1923 } 1924 } 1925 1926 if (lseek(kmem, CAST_SYSMP(sysmp(MP_KERNADDR, MPKA_AVENRUN)), SEEK_SET) 1927 == -1 || 1928 read(kmem, (char *) avenrun, sizeof(avenrun)) != sizeof(avenrun)) 1929 { 1930 if (tTd(3, 1)) 1931 sm_dprintf("getla: lseek or read: %s\n", 1932 sm_errstring(errno)); 1933 return -1; 1934 } 1935 if (tTd(3, 5)) 1936 { 1937 sm_dprintf("getla: avenrun = %ld", (long int) avenrun[0]); 1938 if (tTd(3, 15)) 1939 sm_dprintf(", %ld, %ld", 1940 (long int) avenrun[1], (long int) avenrun[2]); 1941 sm_dprintf("\n"); 1942 } 1943 1944 if (tTd(3, 1)) 1945 sm_dprintf("getla: %d\n", 1946 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1947 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1948 1949 } 1950 #endif /* LA_TYPE == LA_IRIX6 */ 1951 1952 #if LA_TYPE == LA_KSTAT 1953 1954 # include <kstat.h> 1955 1956 int 1957 getla() 1958 { 1959 static kstat_ctl_t *kc = NULL; 1960 static kstat_t *ksp = NULL; 1961 kstat_named_t *ksn; 1962 int la; 1963 1964 if (kc == NULL) /* if not initialized before */ 1965 kc = kstat_open(); 1966 if (kc == NULL) 1967 { 1968 if (tTd(3, 1)) 1969 sm_dprintf("getla: kstat_open(): %s\n", 1970 sm_errstring(errno)); 1971 return -1; 1972 } 1973 if (ksp == NULL) 1974 ksp = kstat_lookup(kc, "unix", 0, "system_misc"); 1975 if (ksp == NULL) 1976 { 1977 if (tTd(3, 1)) 1978 sm_dprintf("getla: kstat_lookup(): %s\n", 1979 sm_errstring(errno)); 1980 return -1; 1981 } 1982 if (kstat_read(kc, ksp, NULL) < 0) 1983 { 1984 if (tTd(3, 1)) 1985 sm_dprintf("getla: kstat_read(): %s\n", 1986 sm_errstring(errno)); 1987 return -1; 1988 } 1989 ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min"); 1990 la = ((double) ksn->value.ul + FSCALE/2) / FSCALE; 1991 /* kstat_close(kc); /o do not close for fast access */ 1992 return la; 1993 } 1994 1995 #endif /* LA_TYPE == LA_KSTAT */ 1996 1997 #if LA_TYPE == LA_DEVSHORT 1998 1999 /* 2000 ** Read /dev/table/avenrun for the load average. This should contain 2001 ** three shorts for the 1, 5, and 15 minute loads. We only read the 2002 ** first, since that's all we care about. 2003 ** 2004 ** Intended for SCO OpenServer 5. 2005 */ 2006 2007 # ifndef _PATH_AVENRUN 2008 # define _PATH_AVENRUN "/dev/table/avenrun" 2009 # endif 2010 2011 int 2012 getla() 2013 { 2014 static int afd = -1; 2015 short avenrun; 2016 int loadav; 2017 int r; 2018 2019 errno = EBADF; 2020 2021 if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1) 2022 { 2023 if (errno != EBADF) 2024 return -1; 2025 afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC); 2026 if (afd < 0) 2027 { 2028 sm_syslog(LOG_ERR, NOQID, 2029 "can't open %s: %s", 2030 _PATH_AVENRUN, sm_errstring(errno)); 2031 return -1; 2032 } 2033 } 2034 2035 r = read(afd, &avenrun, sizeof(avenrun)); 2036 if (r != sizeof(avenrun)) 2037 { 2038 sm_syslog(LOG_ERR, NOQID, 2039 "can't read %s: %s", _PATH_AVENRUN, 2040 r == -1 ? sm_errstring(errno) : "short read"); 2041 return -1; 2042 } 2043 2044 if (tTd(3, 5)) 2045 sm_dprintf("getla: avenrun = %d\n", avenrun); 2046 loadav = (int) (avenrun + FSCALE/2) >> FSHIFT; 2047 if (tTd(3, 1)) 2048 sm_dprintf("getla: %d\n", loadav); 2049 return loadav; 2050 } 2051 2052 #endif /* LA_TYPE == LA_DEVSHORT */ 2053 2054 #if LA_TYPE == LA_ALPHAOSF 2055 struct rtentry; 2056 struct mbuf; 2057 # include <sys/table.h> 2058 2059 int 2060 getla() 2061 { 2062 int ave = 0; 2063 struct tbl_loadavg tab; 2064 2065 if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1) 2066 { 2067 if (tTd(3, 1)) 2068 sm_dprintf("getla: table %s\n", sm_errstring(errno)); 2069 return -1; 2070 } 2071 2072 if (tTd(3, 1)) 2073 sm_dprintf("getla: scale = %d\n", tab.tl_lscale); 2074 2075 if (tab.tl_lscale) 2076 ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) / 2077 tab.tl_lscale); 2078 else 2079 ave = (int) (tab.tl_avenrun.d[2] + 0.5); 2080 2081 if (tTd(3, 1)) 2082 sm_dprintf("getla: %d\n", ave); 2083 2084 return ave; 2085 } 2086 2087 #endif /* LA_TYPE == LA_ALPHAOSF */ 2088 2089 #if LA_TYPE == LA_PSET 2090 2091 int 2092 getla() 2093 { 2094 double avenrun[3]; 2095 2096 if (pset_getloadavg(PS_MYID, avenrun, 2097 sizeof(avenrun) / sizeof(avenrun[0])) < 0) 2098 { 2099 if (tTd(3, 1)) 2100 sm_dprintf("getla: pset_getloadavg failed: %s", 2101 sm_errstring(errno)); 2102 return -1; 2103 } 2104 if (tTd(3, 1)) 2105 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 2106 return ((int) (avenrun[0] + 0.5)); 2107 } 2108 2109 #endif /* LA_TYPE == LA_PSET */ 2110 2111 #if LA_TYPE == LA_ZERO 2112 2113 int 2114 getla() 2115 { 2116 if (tTd(3, 1)) 2117 sm_dprintf("getla: ZERO\n"); 2118 return 0; 2119 } 2120 2121 #endif /* LA_TYPE == LA_ZERO */ 2122 2123 /* 2124 * Copyright 1989 Massachusetts Institute of Technology 2125 * 2126 * Permission to use, copy, modify, distribute, and sell this software and its 2127 * documentation for any purpose is hereby granted without fee, provided that 2128 * the above copyright notice appear in all copies and that both that 2129 * copyright notice and this permission notice appear in supporting 2130 * documentation, and that the name of M.I.T. not be used in advertising or 2131 * publicity pertaining to distribution of the software without specific, 2132 * written prior permission. M.I.T. makes no representations about the 2133 * suitability of this software for any purpose. It is provided "as is" 2134 * without express or implied warranty. 2135 * 2136 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 2137 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. 2138 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 2139 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 2140 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 2141 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2142 * 2143 * Authors: Many and varied... 2144 */ 2145 2146 /* Non Apollo stuff removed by Don Lewis 11/15/93 */ 2147 #ifndef lint 2148 SM_UNUSED(static char rcsid[]) = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; 2149 #endif 2150 2151 #ifdef apollo 2152 # undef volatile 2153 # include <apollo/base.h> 2154 2155 /* ARGSUSED */ 2156 int getloadavg( call_data ) 2157 caddr_t call_data; /* pointer to (double) return value */ 2158 { 2159 double *avenrun = (double *) call_data; 2160 int i; 2161 status_$t st; 2162 long loadav[3]; 2163 2164 proc1_$get_loadav(loadav, &st); 2165 *avenrun = loadav[0] / (double) (1 << 16); 2166 return 0; 2167 } 2168 #endif /* apollo */ 2169 /* 2170 ** SM_GETLA -- get the current load average 2171 ** 2172 ** Parameters: 2173 ** none 2174 ** 2175 ** Returns: 2176 ** none 2177 ** 2178 ** Side Effects: 2179 ** Set CurrentLA to the current load average. 2180 ** Set {load_avg} in GlobalMacros to the current load average. 2181 */ 2182 2183 void 2184 sm_getla() 2185 { 2186 char labuf[8]; 2187 2188 CurrentLA = getla(); 2189 (void) sm_snprintf(labuf, sizeof(labuf), "%d", CurrentLA); 2190 macdefine(&GlobalMacros, A_TEMP, macid("{load_avg}"), labuf); 2191 } 2192 /* 2193 ** SHOULDQUEUE -- should this message be queued or sent? 2194 ** 2195 ** Compares the message cost to the load average to decide. 2196 ** 2197 ** Note: Do NOT change this API! It is documented in op.me 2198 ** and theoretically the user can change this function... 2199 ** 2200 ** Parameters: 2201 ** pri -- the priority of the message in question. 2202 ** ct -- the message creation time (unused, but see above). 2203 ** 2204 ** Returns: 2205 ** true -- if this message should be queued up for the 2206 ** time being. 2207 ** false -- if the load is low enough to send this message. 2208 ** 2209 ** Side Effects: 2210 ** none. 2211 */ 2212 2213 /* ARGSUSED1 */ 2214 bool 2215 shouldqueue(pri, ct) 2216 long pri; 2217 time_t ct; 2218 { 2219 bool rval; 2220 #if _FFR_MEMSTAT 2221 long memfree; 2222 #endif 2223 2224 if (tTd(3, 30)) 2225 sm_dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ", 2226 CurrentLA, pri); 2227 2228 #if _FFR_MEMSTAT 2229 if (QueueLowMem > 0 && 2230 sm_memstat_get(MemoryResource, &memfree) >= 0 && 2231 memfree < QueueLowMem) 2232 { 2233 if (tTd(3, 30)) 2234 sm_dprintf("true (memfree=%ld < QueueLowMem=%ld)\n", 2235 memfree, QueueLowMem); 2236 return true; 2237 } 2238 #endif /* _FFR_MEMSTAT */ 2239 if (CurrentLA < QueueLA) 2240 { 2241 if (tTd(3, 30)) 2242 sm_dprintf("false (CurrentLA < QueueLA)\n"); 2243 return false; 2244 } 2245 rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); 2246 if (tTd(3, 30)) 2247 sm_dprintf("%s (by calculation)\n", rval ? "true" : "false"); 2248 return rval; 2249 } 2250 2251 /* 2252 ** REFUSECONNECTIONS -- decide if connections should be refused 2253 ** 2254 ** Parameters: 2255 ** e -- the current envelope. 2256 ** dn -- number of daemon. 2257 ** active -- was this daemon actually active? 2258 ** 2259 ** Returns: 2260 ** true if incoming SMTP connections should be refused 2261 ** (for now). 2262 ** false if we should accept new work. 2263 ** 2264 ** Side Effects: 2265 ** Sets process title when it is rejecting connections. 2266 */ 2267 2268 bool 2269 refuseconnections(e, dn, active) 2270 ENVELOPE *e; 2271 int dn; 2272 bool active; 2273 { 2274 static time_t lastconn[MAXDAEMONS]; 2275 static int conncnt[MAXDAEMONS]; 2276 static time_t firstrejtime[MAXDAEMONS]; 2277 static time_t nextlogtime[MAXDAEMONS]; 2278 int limit; 2279 #if _FFR_MEMSTAT 2280 long memfree; 2281 #endif 2282 2283 #if XLA 2284 if (!xla_smtp_ok()) 2285 return true; 2286 #endif 2287 2288 SM_ASSERT(dn >= 0); 2289 SM_ASSERT(dn < MAXDAEMONS); 2290 if (ConnRateThrottle > 0) 2291 { 2292 time_t now; 2293 2294 now = curtime(); 2295 if (active) 2296 { 2297 if (now != lastconn[dn]) 2298 { 2299 lastconn[dn] = now; 2300 conncnt[dn] = 1; 2301 } 2302 else if (conncnt[dn]++ > ConnRateThrottle) 2303 { 2304 #define D_MSG_CRT "deferring connections on daemon %s: %d per second" 2305 /* sleep to flatten out connection load */ 2306 sm_setproctitle(true, e, D_MSG_CRT, 2307 Daemons[dn].d_name, 2308 ConnRateThrottle); 2309 if (LogLevel > 8) 2310 sm_syslog(LOG_INFO, NOQID, D_MSG_CRT, 2311 Daemons[dn].d_name, 2312 ConnRateThrottle); 2313 (void) sleep(1); 2314 } 2315 } 2316 else if (now != lastconn[dn]) 2317 conncnt[dn] = 0; 2318 } 2319 2320 2321 #if _FFR_MEMSTAT 2322 if (RefuseLowMem > 0 && 2323 sm_memstat_get(MemoryResource, &memfree) >= 0 && 2324 memfree < RefuseLowMem) 2325 { 2326 # define R_MSG_LM "rejecting connections on daemon %s: free memory: %ld" 2327 sm_setproctitle(true, e, R_MSG_LM, Daemons[dn].d_name, memfree); 2328 if (LogLevel > 8) 2329 sm_syslog(LOG_NOTICE, NOQID, R_MSG_LM, 2330 Daemons[dn].d_name, memfree); 2331 return true; 2332 } 2333 #endif /* _FFR_MEMSTAT */ 2334 sm_getla(); 2335 limit = (Daemons[dn].d_refuseLA != DPO_NOTSET) ? 2336 Daemons[dn].d_refuseLA : RefuseLA; 2337 if (limit > 0 && CurrentLA >= limit) 2338 { 2339 time_t now; 2340 2341 # define R_MSG_LA "rejecting connections on daemon %s: load average: %d" 2342 # define R2_MSG_LA "have been rejecting connections on daemon %s for %s" 2343 sm_setproctitle(true, e, R_MSG_LA, Daemons[dn].d_name, 2344 CurrentLA); 2345 if (LogLevel > 8) 2346 sm_syslog(LOG_NOTICE, NOQID, R_MSG_LA, 2347 Daemons[dn].d_name, CurrentLA); 2348 now = curtime(); 2349 if (firstrejtime[dn] == 0) 2350 { 2351 firstrejtime[dn] = now; 2352 nextlogtime[dn] = now + RejectLogInterval; 2353 } 2354 else if (nextlogtime[dn] < now) 2355 { 2356 sm_syslog(LOG_ERR, NOQID, R2_MSG_LA, Daemons[dn].d_name, 2357 pintvl(now - firstrejtime[dn], true)); 2358 nextlogtime[dn] = now + RejectLogInterval; 2359 } 2360 return true; 2361 } 2362 else 2363 firstrejtime[dn] = 0; 2364 2365 limit = (Daemons[dn].d_delayLA != DPO_NOTSET) ? 2366 Daemons[dn].d_delayLA : DelayLA; 2367 if (limit > 0 && CurrentLA >= limit) 2368 { 2369 time_t now; 2370 static time_t log_delay = (time_t) 0; 2371 2372 # define MIN_DELAY_LOG 90 /* wait before logging this again */ 2373 # define D_MSG_LA "delaying connections on daemon %s: load average=%d >= %d" 2374 /* sleep to flatten out connection load */ 2375 sm_setproctitle(true, e, D_MSG_LA, Daemons[dn].d_name, 2376 CurrentLA, limit); 2377 if (LogLevel > 8 && (now = curtime()) > log_delay) 2378 { 2379 sm_syslog(LOG_INFO, NOQID, D_MSG_LA, 2380 Daemons[dn].d_name, CurrentLA, limit); 2381 log_delay = now + MIN_DELAY_LOG; 2382 } 2383 (void) sleep(1); 2384 } 2385 2386 limit = (Daemons[dn].d_maxchildren != DPO_NOTSET) ? 2387 Daemons[dn].d_maxchildren : MaxChildren; 2388 if (limit > 0 && CurChildren >= limit) 2389 { 2390 proc_list_probe(); 2391 if (CurChildren >= limit) 2392 { 2393 #define R_MSG_CHILD "rejecting connections on daemon %s: %d children, max %d" 2394 sm_setproctitle(true, e, R_MSG_CHILD, 2395 Daemons[dn].d_name, CurChildren, 2396 limit); 2397 if (LogLevel > 8) 2398 sm_syslog(LOG_INFO, NOQID, R_MSG_CHILD, 2399 Daemons[dn].d_name, CurChildren, 2400 limit); 2401 return true; 2402 } 2403 } 2404 return false; 2405 } 2406 2407 /* 2408 ** SETPROCTITLE -- set process title for ps 2409 ** 2410 ** Parameters: 2411 ** fmt -- a printf style format string. 2412 ** a, b, c -- possible parameters to fmt. 2413 ** 2414 ** Returns: 2415 ** none. 2416 ** 2417 ** Side Effects: 2418 ** Clobbers argv of our main procedure so ps(1) will 2419 ** display the title. 2420 */ 2421 2422 #define SPT_NONE 0 /* don't use it at all */ 2423 #define SPT_REUSEARGV 1 /* cover argv with title information */ 2424 #define SPT_BUILTIN 2 /* use libc builtin */ 2425 #define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */ 2426 #define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */ 2427 #define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */ 2428 #define SPT_SCO 6 /* write kernel u. area */ 2429 #define SPT_CHANGEARGV 7 /* write our own strings into argv[] */ 2430 2431 #ifndef SPT_TYPE 2432 # define SPT_TYPE SPT_REUSEARGV 2433 #endif 2434 2435 2436 #if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN 2437 2438 # if SPT_TYPE == SPT_PSTAT 2439 # include <sys/pstat.h> 2440 # endif 2441 # if SPT_TYPE == SPT_PSSTRINGS 2442 # include <machine/vmparam.h> 2443 # include <sys/exec.h> 2444 # ifndef PS_STRINGS /* hmmmm.... apparently not available after all */ 2445 # undef SPT_TYPE 2446 # define SPT_TYPE SPT_REUSEARGV 2447 # else /* ! PS_STRINGS */ 2448 # ifndef NKPDE /* FreeBSD 2.0 */ 2449 # define NKPDE 63 2450 typedef unsigned int *pt_entry_t; 2451 # endif /* ! NKPDE */ 2452 # endif /* ! PS_STRINGS */ 2453 # endif /* SPT_TYPE == SPT_PSSTRINGS */ 2454 2455 # if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV 2456 # define SETPROC_STATIC static 2457 # else 2458 # define SETPROC_STATIC 2459 # endif 2460 2461 # if SPT_TYPE == SPT_SYSMIPS 2462 # include <sys/sysmips.h> 2463 # include <sys/sysnews.h> 2464 # endif 2465 2466 # if SPT_TYPE == SPT_SCO 2467 # include <sys/immu.h> 2468 # include <sys/dir.h> 2469 # include <sys/user.h> 2470 # include <sys/fs/s5param.h> 2471 # if PSARGSZ > MAXLINE 2472 # define SPT_BUFSIZE PSARGSZ 2473 # endif 2474 # endif /* SPT_TYPE == SPT_SCO */ 2475 2476 # ifndef SPT_PADCHAR 2477 # define SPT_PADCHAR ' ' 2478 # endif 2479 2480 #endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */ 2481 2482 #ifndef SPT_BUFSIZE 2483 # define SPT_BUFSIZE MAXLINE 2484 #endif 2485 2486 #if _FFR_SPT_ALIGN 2487 2488 /* 2489 ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 2490 ** 64 bit alignment, so unless each piece of argv and envp is a multiple 2491 ** of 8 bytes (including terminating NULL), initsetproctitle() won't use 2492 ** any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE if 2493 ** you use this FFR. 2494 */ 2495 2496 # ifdef SPT_ALIGN_SIZE 2497 # define SPT_ALIGN(x, align) (((((x) + SPT_ALIGN_SIZE) >> (align)) << (align)) - 1) 2498 # else 2499 # define SPT_ALIGN(x, align) (x) 2500 # endif 2501 #else /* _FFR_SPT_ALIGN */ 2502 # define SPT_ALIGN(x, align) (x) 2503 #endif /* _FFR_SPT_ALIGN */ 2504 2505 /* 2506 ** Pointers for setproctitle. 2507 ** This allows "ps" listings to give more useful information. 2508 */ 2509 2510 static char **Argv = NULL; /* pointer to argument vector */ 2511 static char *LastArgv = NULL; /* end of argv */ 2512 #if SPT_TYPE != SPT_BUILTIN 2513 static void setproctitle __P((const char *, ...)); 2514 #endif 2515 2516 void 2517 initsetproctitle(argc, argv, envp) 2518 int argc; 2519 char **argv; 2520 char **envp; 2521 { 2522 register int i; 2523 #if _FFR_SPT_ALIGN 2524 int align; 2525 #endif 2526 extern char **environ; 2527 2528 /* 2529 ** Move the environment so setproctitle can use the space at 2530 ** the top of memory. 2531 */ 2532 2533 if (envp != NULL) 2534 { 2535 for (i = 0; envp[i] != NULL; i++) 2536 continue; 2537 environ = (char **) xalloc(sizeof(char *) * (i + 1)); 2538 for (i = 0; envp[i] != NULL; i++) 2539 environ[i] = newstr(envp[i]); 2540 environ[i] = NULL; 2541 } 2542 2543 /* 2544 ** Save start and extent of argv for setproctitle. 2545 */ 2546 2547 Argv = argv; 2548 2549 /* 2550 ** Determine how much space we can use for setproctitle. 2551 ** Use all contiguous argv and envp pointers starting at argv[0] 2552 */ 2553 2554 #if _FFR_SPT_ALIGN 2555 align = -1; 2556 # ifdef SPT_ALIGN_SIZE 2557 for (i = SPT_ALIGN_SIZE; i > 0; i >>= 1) 2558 align++; 2559 # endif 2560 #endif /* _FFR_SPT_ALIGN */ 2561 2562 for (i = 0; i < argc; i++) 2563 { 2564 if (i == 0 || LastArgv + 1 == argv[i]) 2565 LastArgv = argv[i] + SPT_ALIGN(strlen(argv[i]), align); 2566 } 2567 for (i = 0; LastArgv != NULL && envp != NULL && envp[i] != NULL; i++) 2568 { 2569 if (LastArgv + 1 == envp[i]) 2570 LastArgv = envp[i] + SPT_ALIGN(strlen(envp[i]), align); 2571 } 2572 } 2573 2574 #if SPT_TYPE != SPT_BUILTIN 2575 2576 /*VARARGS1*/ 2577 static void 2578 # ifdef __STDC__ 2579 setproctitle(const char *fmt, ...) 2580 # else /* __STDC__ */ 2581 setproctitle(fmt, va_alist) 2582 const char *fmt; 2583 va_dcl 2584 # endif /* __STDC__ */ 2585 { 2586 # if SPT_TYPE != SPT_NONE 2587 register int i; 2588 register char *p; 2589 SETPROC_STATIC char buf[SPT_BUFSIZE]; 2590 SM_VA_LOCAL_DECL 2591 # if SPT_TYPE == SPT_PSTAT 2592 union pstun pst; 2593 # endif 2594 # if SPT_TYPE == SPT_SCO 2595 int j; 2596 off_t seek_off; 2597 static int kmem = -1; 2598 static pid_t kmempid = -1; 2599 struct user u; 2600 # endif /* SPT_TYPE == SPT_SCO */ 2601 2602 p = buf; 2603 2604 /* print sendmail: heading for grep */ 2605 (void) sm_strlcpy(p, "sendmail: ", SPACELEFT(buf, p)); 2606 p += strlen(p); 2607 2608 /* print the argument string */ 2609 SM_VA_START(ap, fmt); 2610 (void) sm_vsnprintf(p, SPACELEFT(buf, p), fmt, ap); 2611 SM_VA_END(ap); 2612 2613 i = (int) strlen(buf); 2614 if (i < 0) 2615 return; 2616 2617 # if SPT_TYPE == SPT_PSTAT 2618 pst.pst_command = buf; 2619 pstat(PSTAT_SETCMD, pst, i, 0, 0); 2620 # endif 2621 # if SPT_TYPE == SPT_PSSTRINGS 2622 PS_STRINGS->ps_nargvstr = 1; 2623 PS_STRINGS->ps_argvstr = buf; 2624 # endif 2625 # if SPT_TYPE == SPT_SYSMIPS 2626 sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf); 2627 # endif 2628 # if SPT_TYPE == SPT_SCO 2629 if (kmem < 0 || kmempid != CurrentPid) 2630 { 2631 if (kmem >= 0) 2632 (void) close(kmem); 2633 kmem = open(_PATH_KMEM, O_RDWR, 0); 2634 if (kmem < 0) 2635 return; 2636 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 2637 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 2638 { 2639 (void) close(kmem); 2640 kmem = -1; 2641 return; 2642 } 2643 kmempid = CurrentPid; 2644 } 2645 buf[PSARGSZ - 1] = '\0'; 2646 seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u; 2647 if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off) 2648 (void) write(kmem, buf, PSARGSZ); 2649 # endif /* SPT_TYPE == SPT_SCO */ 2650 # if SPT_TYPE == SPT_REUSEARGV 2651 if (LastArgv == NULL) 2652 return; 2653 2654 if (i > LastArgv - Argv[0] - 2) 2655 { 2656 i = LastArgv - Argv[0] - 2; 2657 buf[i] = '\0'; 2658 } 2659 (void) sm_strlcpy(Argv[0], buf, i + 1); 2660 p = &Argv[0][i]; 2661 while (p < LastArgv) 2662 *p++ = SPT_PADCHAR; 2663 Argv[1] = NULL; 2664 # endif /* SPT_TYPE == SPT_REUSEARGV */ 2665 # if SPT_TYPE == SPT_CHANGEARGV 2666 Argv[0] = buf; 2667 Argv[1] = NULL; 2668 # endif 2669 # endif /* SPT_TYPE != SPT_NONE */ 2670 } 2671 #endif /* SPT_TYPE != SPT_BUILTIN */ 2672 2673 /* 2674 ** SM_SETPROCTITLE -- set process task and set process title for ps 2675 ** 2676 ** Possibly set process status and call setproctitle() to 2677 ** change the ps display. 2678 ** 2679 ** Parameters: 2680 ** status -- whether or not to store as process status 2681 ** e -- the current envelope. 2682 ** fmt -- a printf style format string. 2683 ** a, b, c -- possible parameters to fmt. 2684 ** 2685 ** Returns: 2686 ** none. 2687 */ 2688 2689 /*VARARGS3*/ 2690 void 2691 #ifdef __STDC__ 2692 sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...) 2693 #else /* __STDC__ */ 2694 sm_setproctitle(status, e, fmt, va_alist) 2695 bool status; 2696 ENVELOPE *e; 2697 const char *fmt; 2698 va_dcl 2699 #endif /* __STDC__ */ 2700 { 2701 char buf[SPT_BUFSIZE]; 2702 SM_VA_LOCAL_DECL 2703 2704 /* print the argument string */ 2705 SM_VA_START(ap, fmt); 2706 (void) sm_vsnprintf(buf, sizeof(buf), fmt, ap); 2707 SM_VA_END(ap); 2708 2709 if (status) 2710 proc_list_set(CurrentPid, buf); 2711 2712 if (ProcTitlePrefix != NULL) 2713 { 2714 char prefix[SPT_BUFSIZE]; 2715 2716 expand(ProcTitlePrefix, prefix, sizeof(prefix), e); 2717 setproctitle("%s: %s", prefix, buf); 2718 } 2719 else 2720 setproctitle("%s", buf); 2721 } 2722 /* 2723 ** WAITFOR -- wait for a particular process id. 2724 ** 2725 ** Parameters: 2726 ** pid -- process id to wait for. 2727 ** 2728 ** Returns: 2729 ** status of pid. 2730 ** -1 if pid never shows up. 2731 ** 2732 ** Side Effects: 2733 ** none. 2734 */ 2735 2736 int 2737 waitfor(pid) 2738 pid_t pid; 2739 { 2740 int st; 2741 pid_t i; 2742 2743 do 2744 { 2745 errno = 0; 2746 i = sm_wait(&st); 2747 if (i > 0) 2748 proc_list_drop(i, st, NULL); 2749 } while ((i >= 0 || errno == EINTR) && i != pid); 2750 if (i < 0) 2751 return -1; 2752 return st; 2753 } 2754 /* 2755 ** SM_WAIT -- wait 2756 ** 2757 ** Parameters: 2758 ** status -- pointer to status (return value) 2759 ** 2760 ** Returns: 2761 ** pid 2762 */ 2763 2764 pid_t 2765 sm_wait(status) 2766 int *status; 2767 { 2768 #ifdef WAITUNION 2769 union wait st; 2770 #else 2771 auto int st; 2772 #endif 2773 pid_t i; 2774 #if defined(ISC_UNIX) || defined(_SCO_unix_) 2775 int savesig; 2776 #endif 2777 2778 #if defined(ISC_UNIX) || defined(_SCO_unix_) 2779 savesig = sm_releasesignal(SIGCHLD); 2780 #endif 2781 i = wait(&st); 2782 #if defined(ISC_UNIX) || defined(_SCO_unix_) 2783 if (savesig > 0) 2784 sm_blocksignal(SIGCHLD); 2785 #endif 2786 #ifdef WAITUNION 2787 *status = st.w_status; 2788 #else 2789 *status = st; 2790 #endif 2791 return i; 2792 } 2793 /* 2794 ** REAPCHILD -- pick up the body of my child, lest it become a zombie 2795 ** 2796 ** Parameters: 2797 ** sig -- the signal that got us here (unused). 2798 ** 2799 ** Returns: 2800 ** none. 2801 ** 2802 ** Side Effects: 2803 ** Picks up extant zombies. 2804 ** Control socket exits may restart/shutdown daemon. 2805 ** 2806 ** NOTE: THIS CAN BE CALLED FROM A SIGNAL HANDLER. DO NOT ADD 2807 ** ANYTHING TO THIS ROUTINE UNLESS YOU KNOW WHAT YOU ARE 2808 ** DOING. 2809 */ 2810 2811 /* ARGSUSED0 */ 2812 SIGFUNC_DECL 2813 reapchild(sig) 2814 int sig; 2815 { 2816 int save_errno = errno; 2817 int st; 2818 pid_t pid; 2819 #if HASWAITPID 2820 auto int status; 2821 int count; 2822 2823 count = 0; 2824 while ((pid = waitpid(-1, &status, WNOHANG)) > 0) 2825 { 2826 st = status; 2827 if (count++ > 1000) 2828 break; 2829 #else /* HASWAITPID */ 2830 # ifdef WNOHANG 2831 union wait status; 2832 2833 while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0) 2834 { 2835 st = status.w_status; 2836 # else /* WNOHANG */ 2837 auto int status; 2838 2839 /* 2840 ** Catch one zombie -- we will be re-invoked (we hope) if there 2841 ** are more. Unreliable signals probably break this, but this 2842 ** is the "old system" situation -- waitpid or wait3 are to be 2843 ** strongly preferred. 2844 */ 2845 2846 if ((pid = wait(&status)) > 0) 2847 { 2848 st = status; 2849 # endif /* WNOHANG */ 2850 #endif /* HASWAITPID */ 2851 /* Drop PID and check if it was a control socket child */ 2852 proc_list_drop(pid, st, NULL); 2853 } 2854 FIX_SYSV_SIGNAL(sig, reapchild); 2855 errno = save_errno; 2856 return SIGFUNC_RETURN; 2857 } 2858 /* 2859 ** GETDTSIZE -- return number of file descriptors 2860 ** 2861 ** Only on non-BSD systems 2862 ** 2863 ** Parameters: 2864 ** none 2865 ** 2866 ** Returns: 2867 ** size of file descriptor table 2868 ** 2869 ** Side Effects: 2870 ** none 2871 */ 2872 2873 #ifdef SOLARIS 2874 # include <sys/resource.h> 2875 #endif 2876 2877 int 2878 getdtsize() 2879 { 2880 #ifdef RLIMIT_NOFILE 2881 struct rlimit rl; 2882 2883 if (getrlimit(RLIMIT_NOFILE, &rl) >= 0) 2884 return rl.rlim_cur; 2885 #endif /* RLIMIT_NOFILE */ 2886 2887 #if HASGETDTABLESIZE 2888 return getdtablesize(); 2889 #else /* HASGETDTABLESIZE */ 2890 # ifdef _SC_OPEN_MAX 2891 return sysconf(_SC_OPEN_MAX); 2892 # else 2893 return NOFILE; 2894 # endif 2895 #endif /* HASGETDTABLESIZE */ 2896 } 2897 /* 2898 ** UNAME -- get the UUCP name of this system. 2899 */ 2900 2901 #if !HASUNAME 2902 2903 int 2904 uname(name) 2905 struct utsname *name; 2906 { 2907 SM_FILE_T *file; 2908 char *n; 2909 2910 name->nodename[0] = '\0'; 2911 2912 /* try /etc/whoami -- one line with the node name */ 2913 if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, "/etc/whoami", 2914 SM_IO_RDONLY, NULL)) != NULL) 2915 { 2916 (void) sm_io_fgets(file, SM_TIME_DEFAULT, name->nodename, 2917 NODE_LENGTH + 1); 2918 (void) sm_io_close(file, SM_TIME_DEFAULT); 2919 n = strchr(name->nodename, '\n'); 2920 if (n != NULL) 2921 *n = '\0'; 2922 if (name->nodename[0] != '\0') 2923 return 0; 2924 } 2925 2926 /* try /usr/include/whoami.h -- has a #define somewhere */ 2927 if ((file = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, 2928 "/usr/include/whoami.h", SM_IO_RDONLY, NULL)) 2929 != NULL) 2930 { 2931 char buf[MAXLINE]; 2932 2933 while (sm_io_fgets(file, SM_TIME_DEFAULT, 2934 buf, sizeof(buf)) >= 0) 2935 { 2936 if (sm_io_sscanf(buf, "#define sysname \"%*[^\"]\"", 2937 NODE_LENGTH, name->nodename) > 0) 2938 break; 2939 } 2940 (void) sm_io_close(file, SM_TIME_DEFAULT); 2941 if (name->nodename[0] != '\0') 2942 return 0; 2943 } 2944 2945 return -1; 2946 } 2947 #endif /* !HASUNAME */ 2948 /* 2949 ** INITGROUPS -- initialize groups 2950 ** 2951 ** Stub implementation for System V style systems 2952 */ 2953 2954 #if !HASINITGROUPS 2955 int 2956 initgroups(name, basegid) 2957 char *name; 2958 int basegid; 2959 { 2960 return 0; 2961 } 2962 #endif /* !HASINITGROUPS */ 2963 2964 /* 2965 ** SETGROUPS -- set group list 2966 ** 2967 ** Stub implementation for systems that don't have group lists 2968 */ 2969 2970 #ifndef NGROUPS_MAX 2971 int 2972 setgroups(ngroups, grouplist) 2973 int ngroups; 2974 GIDSET_T grouplist[]; 2975 { 2976 return 0; 2977 } 2978 #endif /* ! NGROUPS_MAX */ 2979 2980 /* 2981 ** SETSID -- set session id (for non-POSIX systems) 2982 */ 2983 2984 #if !HASSETSID 2985 2986 pid_t 2987 setsid __P ((void)) 2988 { 2989 # ifdef TIOCNOTTY 2990 int fd; 2991 2992 fd = open("/dev/tty", O_RDWR, 0); 2993 if (fd >= 0) 2994 { 2995 (void) ioctl(fd, TIOCNOTTY, (char *) 0); 2996 (void) close(fd); 2997 } 2998 # endif /* TIOCNOTTY */ 2999 # ifdef SYS5SETPGRP 3000 return setpgrp(); 3001 # else 3002 return setpgid(0, CurrentPid); 3003 # endif 3004 } 3005 3006 #endif /* !HASSETSID */ 3007 /* 3008 ** FSYNC -- dummy fsync 3009 */ 3010 3011 #if NEEDFSYNC 3012 int 3013 fsync(fd) 3014 int fd; 3015 { 3016 # ifdef O_SYNC 3017 return fcntl(fd, F_SETFL, O_SYNC); 3018 # else 3019 /* nothing we can do */ 3020 return 0; 3021 # endif 3022 } 3023 #endif /* NEEDFSYNC */ 3024 3025 /* 3026 ** DGUX_INET_ADDR -- inet_addr for DG/UX 3027 ** 3028 ** Data General DG/UX version of inet_addr returns a struct in_addr 3029 ** instead of a long. This patches things. Only needed on versions 3030 ** prior to 5.4.3. 3031 */ 3032 3033 #ifdef DGUX_5_4_2 3034 3035 # undef inet_addr 3036 3037 long 3038 dgux_inet_addr(host) 3039 char *host; 3040 { 3041 struct in_addr haddr; 3042 3043 haddr = inet_addr(host); 3044 return haddr.s_addr; 3045 } 3046 3047 #endif /* DGUX_5_4_2 */ 3048 /* 3049 ** GETOPT -- for old systems or systems with bogus implementations 3050 */ 3051 3052 #if !SM_CONF_GETOPT 3053 3054 /* 3055 * Copyright (c) 1985 Regents of the University of California. 3056 * All rights reserved. The Berkeley software License Agreement 3057 * specifies the terms and conditions for redistribution. 3058 */ 3059 3060 3061 /* 3062 ** this version hacked to add `atend' flag to allow state machine 3063 ** to reset if invoked by the program to scan args for a 2nd time 3064 */ 3065 3066 # if defined(LIBC_SCCS) && !defined(lint) 3067 static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86"; 3068 # endif 3069 3070 /* 3071 ** get option letter from argument vector 3072 */ 3073 # ifdef _CONVEX_SOURCE 3074 extern int optind, opterr, optopt; 3075 extern char *optarg; 3076 # else /* _CONVEX_SOURCE */ 3077 int opterr = 1; /* if error message should be printed */ 3078 int optind = 1; /* index into parent argv vector */ 3079 int optopt = 0; /* character checked for validity */ 3080 char *optarg = NULL; /* argument associated with option */ 3081 # endif /* _CONVEX_SOURCE */ 3082 3083 # define BADCH (int)'?' 3084 # define EMSG "" 3085 # define tell(s) if (opterr) \ 3086 {sm_io_fputs(smioerr, SM_TIME_DEFAULT, *nargv); \ 3087 (void) sm_io_fputs(smioerr, SM_TIME_DEFAULT, s); \ 3088 (void) sm_io_putc(smioerr, SM_TIME_DEFAULT, optopt); \ 3089 (void) sm_io_putc(smioerr, SM_TIME_DEFAULT, '\n'); \ 3090 return BADCH;} 3091 3092 int 3093 getopt(nargc,nargv,ostr) 3094 int nargc; 3095 char *const *nargv; 3096 const char *ostr; 3097 { 3098 static char *place = EMSG; /* option letter processing */ 3099 static char atend = 0; 3100 register char *oli = NULL; /* option letter list index */ 3101 3102 if (atend) { 3103 atend = 0; 3104 place = EMSG; 3105 } 3106 if(!*place) { /* update scanning pointer */ 3107 if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) { 3108 atend++; 3109 return -1; 3110 } 3111 if (*place == '-') { /* found "--" */ 3112 ++optind; 3113 atend++; 3114 return -1; 3115 } 3116 } /* option letter okay? */ 3117 if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) { 3118 if (!*place) ++optind; 3119 tell(": illegal option -- "); 3120 } 3121 if (oli && *++oli != ':') { /* don't need argument */ 3122 optarg = NULL; 3123 if (!*place) ++optind; 3124 } 3125 else { /* need an argument */ 3126 if (*place) optarg = place; /* no white space */ 3127 else if (nargc <= ++optind) { /* no arg */ 3128 place = EMSG; 3129 tell(": option requires an argument -- "); 3130 } 3131 else optarg = nargv[optind]; /* white space */ 3132 place = EMSG; 3133 ++optind; 3134 } 3135 return optopt; /* dump back option letter */ 3136 } 3137 3138 #endif /* !SM_CONF_GETOPT */ 3139 /* 3140 ** USERSHELLOK -- tell if a user's shell is ok for unrestricted use 3141 ** 3142 ** Parameters: 3143 ** user -- the name of the user we are checking. 3144 ** shell -- the user's shell from /etc/passwd 3145 ** 3146 ** Returns: 3147 ** true -- if it is ok to use this for unrestricted access. 3148 ** false -- if the shell is restricted. 3149 */ 3150 3151 #if !HASGETUSERSHELL 3152 3153 # ifndef _PATH_SHELLS 3154 # define _PATH_SHELLS "/etc/shells" 3155 # endif 3156 3157 # if defined(_AIX3) || defined(_AIX4) 3158 # include <userconf.h> 3159 # if _AIX4 >= 40200 3160 # include <userpw.h> 3161 # endif 3162 # include <usersec.h> 3163 # endif /* defined(_AIX3) || defined(_AIX4) */ 3164 3165 static char *DefaultUserShells[] = 3166 { 3167 "/bin/sh", /* standard shell */ 3168 # ifdef MPE 3169 "/SYS/PUB/CI", 3170 # else /* MPE */ 3171 "/usr/bin/sh", 3172 "/bin/csh", /* C shell */ 3173 "/usr/bin/csh", 3174 # endif /* MPE */ 3175 # ifdef __hpux 3176 # ifdef V4FS 3177 "/usr/bin/rsh", /* restricted Bourne shell */ 3178 "/usr/bin/ksh", /* Korn shell */ 3179 "/usr/bin/rksh", /* restricted Korn shell */ 3180 "/usr/bin/pam", 3181 "/usr/bin/keysh", /* key shell (extended Korn shell) */ 3182 "/usr/bin/posix/sh", 3183 # else /* V4FS */ 3184 "/bin/rsh", /* restricted Bourne shell */ 3185 "/bin/ksh", /* Korn shell */ 3186 "/bin/rksh", /* restricted Korn shell */ 3187 "/bin/pam", 3188 "/usr/bin/keysh", /* key shell (extended Korn shell) */ 3189 "/bin/posix/sh", 3190 "/sbin/sh", 3191 # endif /* V4FS */ 3192 # endif /* __hpux */ 3193 # if defined(_AIX3) || defined(_AIX4) 3194 "/bin/ksh", /* Korn shell */ 3195 "/usr/bin/ksh", 3196 "/bin/tsh", /* trusted shell */ 3197 "/usr/bin/tsh", 3198 "/bin/bsh", /* Bourne shell */ 3199 "/usr/bin/bsh", 3200 # endif /* defined(_AIX3) || defined(_AIX4) */ 3201 # if defined(__svr4__) || defined(__svr5__) 3202 "/bin/ksh", /* Korn shell */ 3203 "/usr/bin/ksh", 3204 # endif /* defined(__svr4__) || defined(__svr5__) */ 3205 # ifdef sgi 3206 "/sbin/sh", /* SGI's shells really live in /sbin */ 3207 "/usr/bin/sh", 3208 "/sbin/bsh", /* classic Bourne shell */ 3209 "/bin/bsh", 3210 "/usr/bin/bsh", 3211 "/sbin/csh", /* standard csh */ 3212 "/bin/csh", 3213 "/usr/bin/csh", 3214 "/sbin/jsh", /* classic Bourne shell w/ job control*/ 3215 "/bin/jsh", 3216 "/usr/bin/jsh", 3217 "/bin/ksh", /* Korn shell */ 3218 "/sbin/ksh", 3219 "/usr/bin/ksh", 3220 "/sbin/tcsh", /* Extended csh */ 3221 "/bin/tcsh", 3222 "/usr/bin/tcsh", 3223 # endif /* sgi */ 3224 NULL 3225 }; 3226 3227 #endif /* !HASGETUSERSHELL */ 3228 3229 #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/" 3230 3231 bool 3232 usershellok(user, shell) 3233 char *user; 3234 char *shell; 3235 { 3236 #if HASGETUSERSHELL 3237 register char *p; 3238 extern char *getusershell __P((void)); 3239 3240 if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') || 3241 ConfigLevel <= 1) 3242 return true; 3243 3244 setusershell(); 3245 while ((p = getusershell()) != NULL) 3246 if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0) 3247 break; 3248 endusershell(); 3249 return p != NULL; 3250 #else /* HASGETUSERSHELL */ 3251 # if USEGETCONFATTR 3252 auto char *v; 3253 # endif 3254 register SM_FILE_T *shellf; 3255 char buf[MAXLINE]; 3256 3257 if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') || 3258 ConfigLevel <= 1) 3259 return true; 3260 3261 # if USEGETCONFATTR 3262 /* 3263 ** Naturally IBM has a "better" idea..... 3264 ** 3265 ** What a crock. This interface isn't documented, it is 3266 ** considered part of the security library (-ls), and it 3267 ** only works if you are running as root (since the list 3268 ** of valid shells is obviously a source of great concern). 3269 ** I recommend that you do NOT define USEGETCONFATTR, 3270 ** especially since you are going to have to set up an 3271 ** /etc/shells anyhow to handle the cases where getconfattr 3272 ** fails. 3273 */ 3274 3275 if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL) 3276 { 3277 while (*v != '\0') 3278 { 3279 if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0) 3280 return true; 3281 v += strlen(v) + 1; 3282 } 3283 return false; 3284 } 3285 # endif /* USEGETCONFATTR */ 3286 3287 shellf = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_SHELLS, 3288 SM_IO_RDONLY, NULL); 3289 if (shellf == NULL) 3290 { 3291 /* no /etc/shells; see if it is one of the std shells */ 3292 char **d; 3293 3294 if (errno != ENOENT && LogLevel > 3) 3295 sm_syslog(LOG_ERR, NOQID, 3296 "usershellok: cannot open %s: %s", 3297 _PATH_SHELLS, sm_errstring(errno)); 3298 3299 for (d = DefaultUserShells; *d != NULL; d++) 3300 { 3301 if (strcmp(shell, *d) == 0) 3302 return true; 3303 } 3304 return false; 3305 } 3306 3307 while (sm_io_fgets(shellf, SM_TIME_DEFAULT, buf, sizeof(buf)) >= 0) 3308 { 3309 register char *p, *q; 3310 3311 p = buf; 3312 while (*p != '\0' && *p != '#' && *p != '/') 3313 p++; 3314 if (*p == '#' || *p == '\0') 3315 continue; 3316 q = p; 3317 while (*p != '\0' && *p != '#' && !(SM_ISSPACE(*p))) 3318 p++; 3319 *p = '\0'; 3320 if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0) 3321 { 3322 (void) sm_io_close(shellf, SM_TIME_DEFAULT); 3323 return true; 3324 } 3325 } 3326 (void) sm_io_close(shellf, SM_TIME_DEFAULT); 3327 return false; 3328 #endif /* HASGETUSERSHELL */ 3329 } 3330 /* 3331 ** FREEDISKSPACE -- see how much free space is on the queue filesystem 3332 ** 3333 ** Only implemented if you have statfs. 3334 ** 3335 ** Parameters: 3336 ** dir -- the directory in question. 3337 ** bsize -- a variable into which the filesystem 3338 ** block size is stored. 3339 ** 3340 ** Returns: 3341 ** The number of blocks free on the queue filesystem. 3342 ** -1 if the statfs call fails. 3343 ** 3344 ** Side effects: 3345 ** Puts the filesystem block size into bsize. 3346 */ 3347 3348 /* statfs types */ 3349 #define SFS_NONE 0 /* no statfs implementation */ 3350 #define SFS_USTAT 1 /* use ustat */ 3351 #define SFS_4ARGS 2 /* use four-argument statfs call */ 3352 #define SFS_VFS 3 /* use <sys/vfs.h> implementation */ 3353 #define SFS_MOUNT 4 /* use <sys/mount.h> implementation */ 3354 #define SFS_STATFS 5 /* use <sys/statfs.h> implementation */ 3355 #define SFS_STATVFS 6 /* use <sys/statvfs.h> implementation */ 3356 3357 #ifndef SFS_TYPE 3358 # define SFS_TYPE SFS_NONE 3359 #endif 3360 3361 #if SFS_TYPE == SFS_USTAT 3362 # include <ustat.h> 3363 #endif 3364 #if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS 3365 # include <sys/statfs.h> 3366 #endif 3367 #if SFS_TYPE == SFS_VFS 3368 # include <sys/vfs.h> 3369 #endif 3370 #if SFS_TYPE == SFS_MOUNT 3371 # include <sys/mount.h> 3372 #endif 3373 #if SFS_TYPE == SFS_STATVFS 3374 # include <sys/statvfs.h> 3375 #endif 3376 3377 long 3378 freediskspace(dir, bsize) 3379 const char *dir; 3380 long *bsize; 3381 { 3382 #if SFS_TYPE == SFS_NONE 3383 if (bsize != NULL) 3384 *bsize = 4096L; 3385 3386 /* assume free space is plentiful */ 3387 return (long) LONG_MAX; 3388 #else /* SFS_TYPE == SFS_NONE */ 3389 # if SFS_TYPE == SFS_USTAT 3390 struct ustat fs; 3391 struct stat statbuf; 3392 # define FSBLOCKSIZE DEV_BSIZE 3393 # define SFS_BAVAIL f_tfree 3394 # else /* SFS_TYPE == SFS_USTAT */ 3395 # if defined(ultrix) 3396 struct fs_data fs; 3397 # define SFS_BAVAIL fd_bfreen 3398 # define FSBLOCKSIZE 1024L 3399 # else /* defined(ultrix) */ 3400 # if SFS_TYPE == SFS_STATVFS 3401 struct statvfs fs; 3402 # define FSBLOCKSIZE fs.f_frsize 3403 # else /* SFS_TYPE == SFS_STATVFS */ 3404 struct statfs fs; 3405 # define FSBLOCKSIZE fs.f_bsize 3406 # endif /* SFS_TYPE == SFS_STATVFS */ 3407 # endif /* defined(ultrix) */ 3408 # endif /* SFS_TYPE == SFS_USTAT */ 3409 # ifndef SFS_BAVAIL 3410 # define SFS_BAVAIL f_bavail 3411 # endif 3412 3413 # if SFS_TYPE == SFS_USTAT 3414 if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0) 3415 # else /* SFS_TYPE == SFS_USTAT */ 3416 # if SFS_TYPE == SFS_4ARGS 3417 if (statfs(dir, &fs, sizeof(fs), 0) == 0) 3418 # else /* SFS_TYPE == SFS_4ARGS */ 3419 # if SFS_TYPE == SFS_STATVFS 3420 if (statvfs(dir, &fs) == 0) 3421 # else /* SFS_TYPE == SFS_STATVFS */ 3422 # if defined(ultrix) 3423 if (statfs(dir, &fs) > 0) 3424 # else /* defined(ultrix) */ 3425 if (statfs(dir, &fs) == 0) 3426 # endif /* defined(ultrix) */ 3427 # endif /* SFS_TYPE == SFS_STATVFS */ 3428 # endif /* SFS_TYPE == SFS_4ARGS */ 3429 # endif /* SFS_TYPE == SFS_USTAT */ 3430 { 3431 if (bsize != NULL) 3432 *bsize = FSBLOCKSIZE; 3433 if (fs.SFS_BAVAIL <= 0) 3434 return 0; 3435 else if (fs.SFS_BAVAIL > LONG_MAX) 3436 return (long) LONG_MAX; 3437 else 3438 return (long) fs.SFS_BAVAIL; 3439 } 3440 return -1; 3441 #endif /* SFS_TYPE == SFS_NONE */ 3442 } 3443 /* 3444 ** ENOUGHDISKSPACE -- is there enough free space on the queue file systems? 3445 ** 3446 ** Parameters: 3447 ** msize -- the size to check against. If zero, we don't yet 3448 ** know how big the message will be, so just check for 3449 ** a "reasonable" amount. 3450 ** e -- envelope, or NULL -- controls logging 3451 ** 3452 ** Returns: 3453 ** true if in every queue group there is at least one 3454 ** queue directory whose file system contains enough free space. 3455 ** false otherwise. 3456 ** 3457 ** Side Effects: 3458 ** If there is not enough disk space and e != NULL 3459 ** then sm_syslog is called. 3460 */ 3461 3462 bool 3463 enoughdiskspace(msize, e) 3464 long msize; 3465 ENVELOPE *e; 3466 { 3467 int i; 3468 3469 #if _FFR_TESTS 3470 if (tTd(4, 101)) 3471 return false; 3472 #endif 3473 if (MinBlocksFree <= 0 && msize <= 0) 3474 { 3475 if (tTd(4, 80)) 3476 sm_dprintf("enoughdiskspace: no threshold\n"); 3477 return true; 3478 } 3479 3480 filesys_update(); 3481 for (i = 0; i < NumQueue; ++i) 3482 { 3483 if (pickqdir(Queue[i], msize, e) < 0) 3484 return false; 3485 } 3486 return true; 3487 } 3488 /* 3489 ** TRANSIENTERROR -- tell if an error code indicates a transient failure 3490 ** 3491 ** This looks at an errno value and tells if this is likely to 3492 ** go away if retried later. 3493 ** 3494 ** Parameters: 3495 ** err -- the errno code to classify. 3496 ** 3497 ** Returns: 3498 ** true if this is probably transient. 3499 ** false otherwise. 3500 */ 3501 3502 bool 3503 transienterror(err) 3504 int err; 3505 { 3506 switch (err) 3507 { 3508 case EIO: /* I/O error */ 3509 case ENXIO: /* Device not configured */ 3510 case EAGAIN: /* Resource temporarily unavailable */ 3511 case ENOMEM: /* Cannot allocate memory */ 3512 case ENODEV: /* Operation not supported by device */ 3513 case ENFILE: /* Too many open files in system */ 3514 case EMFILE: /* Too many open files */ 3515 case ENOSPC: /* No space left on device */ 3516 case ETIMEDOUT: /* Connection timed out */ 3517 #ifdef ESTALE 3518 case ESTALE: /* Stale NFS file handle */ 3519 #endif 3520 #ifdef ENETDOWN 3521 case ENETDOWN: /* Network is down */ 3522 #endif 3523 #ifdef ENETUNREACH 3524 case ENETUNREACH: /* Network is unreachable */ 3525 #endif 3526 #ifdef ENETRESET 3527 case ENETRESET: /* Network dropped connection on reset */ 3528 #endif 3529 #ifdef ECONNABORTED 3530 case ECONNABORTED: /* Software caused connection abort */ 3531 #endif 3532 #ifdef ECONNRESET 3533 case ECONNRESET: /* Connection reset by peer */ 3534 #endif 3535 #ifdef ENOBUFS 3536 case ENOBUFS: /* No buffer space available */ 3537 #endif 3538 #ifdef ESHUTDOWN 3539 case ESHUTDOWN: /* Can't send after socket shutdown */ 3540 #endif 3541 #ifdef ECONNREFUSED 3542 case ECONNREFUSED: /* Connection refused */ 3543 #endif 3544 #ifdef EHOSTDOWN 3545 case EHOSTDOWN: /* Host is down */ 3546 #endif 3547 #ifdef EHOSTUNREACH 3548 case EHOSTUNREACH: /* No route to host */ 3549 #endif 3550 #ifdef EDQUOT 3551 case EDQUOT: /* Disc quota exceeded */ 3552 #endif 3553 #ifdef EPROCLIM 3554 case EPROCLIM: /* Too many processes */ 3555 #endif 3556 #ifdef EUSERS 3557 case EUSERS: /* Too many users */ 3558 #endif 3559 #ifdef EDEADLK 3560 case EDEADLK: /* Resource deadlock avoided */ 3561 #endif 3562 #ifdef EISCONN 3563 case EISCONN: /* Socket already connected */ 3564 #endif 3565 #ifdef EINPROGRESS 3566 case EINPROGRESS: /* Operation now in progress */ 3567 #endif 3568 #ifdef EALREADY 3569 case EALREADY: /* Operation already in progress */ 3570 #endif 3571 #ifdef EADDRINUSE 3572 case EADDRINUSE: /* Address already in use */ 3573 #endif 3574 #ifdef EADDRNOTAVAIL 3575 case EADDRNOTAVAIL: /* Can't assign requested address */ 3576 #endif 3577 #ifdef ETXTBSY 3578 case ETXTBSY: /* (Apollo) file locked */ 3579 #endif 3580 #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR)) 3581 case ENOSR: /* Out of streams resources */ 3582 #endif 3583 #ifdef ENOLCK 3584 case ENOLCK: /* No locks available */ 3585 #endif 3586 case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */ 3587 return true; 3588 } 3589 3590 /* nope, must be permanent */ 3591 return false; 3592 } 3593 /* 3594 ** LOCKFILE -- lock a file using flock or (shudder) fcntl locking 3595 ** 3596 ** Parameters: 3597 ** fd -- the file descriptor of the file. 3598 ** filename -- the file name (for error messages). 3599 ** ext -- the filename extension. 3600 ** type -- type of the lock. Bits can be: 3601 ** LOCK_EX -- exclusive lock. 3602 ** LOCK_NB -- non-blocking. 3603 ** LOCK_UN -- unlock. 3604 ** 3605 ** Returns: 3606 ** true if the lock was acquired. 3607 ** false otherwise. 3608 */ 3609 3610 bool 3611 lockfile(fd, filename, ext, type) 3612 int fd; 3613 char *filename; 3614 char *ext; 3615 int type; 3616 { 3617 int i; 3618 int save_errno; 3619 #if !HASFLOCK 3620 int action; 3621 struct flock lfd; 3622 3623 if (ext == NULL) 3624 ext = ""; 3625 3626 (void) memset(&lfd, '\0', sizeof(lfd)); 3627 if (bitset(LOCK_UN, type)) 3628 lfd.l_type = F_UNLCK; 3629 else if (bitset(LOCK_EX, type)) 3630 lfd.l_type = F_WRLCK; 3631 else 3632 lfd.l_type = F_RDLCK; 3633 3634 if (bitset(LOCK_NB, type)) 3635 action = F_SETLK; 3636 else 3637 action = F_SETLKW; 3638 3639 if (tTd(55, 60)) 3640 sm_dprintf("lockfile(%s%s, action=%d, type=%d): ", 3641 filename, ext, action, lfd.l_type); 3642 while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR) 3643 continue; 3644 if (i >= 0) 3645 { 3646 if (tTd(55, 60)) 3647 sm_dprintf("SUCCESS\n"); 3648 return true; 3649 } 3650 save_errno = errno; 3651 3652 if (tTd(55, 60)) 3653 sm_dprintf("(%s) ", sm_errstring(save_errno)); 3654 3655 /* 3656 ** On SunOS, if you are testing using -oQ/tmp/mqueue or 3657 ** -oA/tmp/aliases or anything like that, and /tmp is mounted 3658 ** as type "tmp" (that is, served from swap space), the 3659 ** previous fcntl will fail with "Invalid argument" errors. 3660 ** Since this is fairly common during testing, we will assume 3661 ** that this indicates that the lock is successfully grabbed. 3662 */ 3663 3664 if (save_errno == EINVAL) 3665 { 3666 if (tTd(55, 60)) 3667 sm_dprintf("SUCCESS\n"); 3668 return true; 3669 } 3670 3671 if (!bitset(LOCK_NB, type) || 3672 (save_errno != EACCES && save_errno != EAGAIN)) 3673 { 3674 int omode = fcntl(fd, F_GETFL, 0); 3675 uid_t euid = geteuid(); 3676 3677 errno = save_errno; 3678 syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)", 3679 filename, ext, fd, type, omode, (long) euid); 3680 dumpfd(fd, true, true); 3681 } 3682 #else /* !HASFLOCK */ 3683 if (ext == NULL) 3684 ext = ""; 3685 3686 if (tTd(55, 60)) 3687 sm_dprintf("lockfile(%s%s, type=%o): ", filename, ext, type); 3688 3689 while ((i = flock(fd, type)) < 0 && errno == EINTR) 3690 continue; 3691 if (i >= 0) 3692 { 3693 if (tTd(55, 60)) 3694 sm_dprintf("SUCCESS\n"); 3695 return true; 3696 } 3697 save_errno = errno; 3698 3699 if (tTd(55, 60)) 3700 sm_dprintf("(%s) ", sm_errstring(save_errno)); 3701 3702 if (!bitset(LOCK_NB, type) || save_errno != EWOULDBLOCK) 3703 { 3704 int omode = fcntl(fd, F_GETFL, 0); 3705 uid_t euid = geteuid(); 3706 3707 errno = save_errno; 3708 syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%ld)", 3709 filename, ext, fd, type, omode, (long) euid); 3710 dumpfd(fd, true, true); 3711 } 3712 #endif /* !HASFLOCK */ 3713 if (tTd(55, 60)) 3714 sm_dprintf("FAIL\n"); 3715 errno = save_errno; 3716 return false; 3717 } 3718 /* 3719 ** CHOWNSAFE -- tell if chown is "safe" (executable only by root) 3720 ** 3721 ** Unfortunately, given that we can't predict other systems on which 3722 ** a remote mounted (NFS) filesystem will be mounted, the answer is 3723 ** almost always that this is unsafe. 3724 ** 3725 ** Note also that many operating systems have non-compliant 3726 ** implementations of the _POSIX_CHOWN_RESTRICTED variable and the 3727 ** fpathconf() routine. According to IEEE 1003.1-1990, if 3728 ** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then 3729 ** no non-root process can give away the file. However, vendors 3730 ** don't take NFS into account, so a comfortable value of 3731 ** _POSIX_CHOWN_RESTRICTED tells us nothing. 3732 ** 3733 ** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf() 3734 ** even on files where chown is not restricted. Many systems get 3735 ** this wrong on NFS-based filesystems (that is, they say that chown 3736 ** is restricted [safe] on NFS filesystems where it may not be, since 3737 ** other systems can access the same filesystem and do file giveaway; 3738 ** only the NFS server knows for sure!) Hence, it is important to 3739 ** get the value of SAFENFSPATHCONF correct -- it should be defined 3740 ** _only_ after testing (see test/t_pathconf.c) a system on an unsafe 3741 ** NFS-based filesystem to ensure that you can get meaningful results. 3742 ** If in doubt, assume unsafe! 3743 ** 3744 ** You may also need to tweak IS_SAFE_CHOWN -- it should be a 3745 ** condition indicating whether the return from pathconf indicates 3746 ** that chown is safe (typically either > 0 or >= 0 -- there isn't 3747 ** even any agreement about whether a zero return means that a file 3748 ** is or is not safe). It defaults to "> 0". 3749 ** 3750 ** If the parent directory is safe (writable only by owner back 3751 ** to the root) then we can relax slightly and trust fpathconf 3752 ** in more circumstances. This is really a crock -- if this is an 3753 ** NFS mounted filesystem then we really know nothing about the 3754 ** underlying implementation. However, most systems pessimize and 3755 ** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which 3756 ** we interpret as unsafe, as we should. Thus, this heuristic gets 3757 ** us into a possible problem only on systems that have a broken 3758 ** pathconf implementation and which are also poorly configured 3759 ** (have :include: files in group- or world-writable directories). 3760 ** 3761 ** Parameters: 3762 ** fd -- the file descriptor to check. 3763 ** safedir -- set if the parent directory is safe. 3764 ** 3765 ** Returns: 3766 ** true -- if the chown(2) operation is "safe" -- that is, 3767 ** only root can chown the file to an arbitrary user. 3768 ** false -- if an arbitrary user can give away a file. 3769 */ 3770 3771 #ifndef IS_SAFE_CHOWN 3772 # define IS_SAFE_CHOWN > 0 3773 #endif 3774 3775 bool 3776 chownsafe(fd, safedir) 3777 int fd; 3778 bool safedir; 3779 { 3780 #if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \ 3781 (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H)) 3782 int rval; 3783 3784 /* give the system administrator a chance to override */ 3785 if (bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail)) 3786 return true; 3787 3788 /* 3789 ** Some systems (e.g., SunOS) seem to have the call and the 3790 ** #define _PC_CHOWN_RESTRICTED, but don't actually implement 3791 ** the call. This heuristic checks for that. 3792 */ 3793 3794 errno = 0; 3795 rval = fpathconf(fd, _PC_CHOWN_RESTRICTED); 3796 # if SAFENFSPATHCONF 3797 return errno == 0 && rval IS_SAFE_CHOWN; 3798 # else 3799 return safedir && errno == 0 && rval IS_SAFE_CHOWN; 3800 # endif 3801 #else /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */ 3802 return bitnset(DBS_ASSUMESAFECHOWN, DontBlameSendmail); 3803 #endif /* (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && ... */ 3804 } 3805 /* 3806 ** RESETLIMITS -- reset system controlled resource limits 3807 ** 3808 ** This is to avoid denial-of-service attacks 3809 ** 3810 ** Parameters: 3811 ** none 3812 ** 3813 ** Returns: 3814 ** none 3815 */ 3816 3817 #if HASSETRLIMIT 3818 # ifdef RLIMIT_NEEDS_SYS_TIME_H 3819 # include <sm/time.h> 3820 # endif 3821 # include <sys/resource.h> 3822 #endif /* HASSETRLIMIT */ 3823 3824 void 3825 resetlimits() 3826 { 3827 #if HASSETRLIMIT 3828 struct rlimit lim; 3829 3830 lim.rlim_cur = lim.rlim_max = RLIM_INFINITY; 3831 (void) setrlimit(RLIMIT_CPU, &lim); 3832 (void) setrlimit(RLIMIT_FSIZE, &lim); 3833 # ifdef RLIMIT_NOFILE 3834 lim.rlim_cur = lim.rlim_max = FD_SETSIZE; 3835 (void) setrlimit(RLIMIT_NOFILE, &lim); 3836 # endif 3837 #else /* HASSETRLIMIT */ 3838 # if HASULIMIT 3839 (void) ulimit(2, 0x3fffff); 3840 (void) ulimit(4, FD_SETSIZE); 3841 # endif 3842 #endif /* HASSETRLIMIT */ 3843 errno = 0; 3844 } 3845 /* 3846 ** SETVENDOR -- process vendor code from V configuration line 3847 ** 3848 ** Parameters: 3849 ** vendor -- string representation of vendor. 3850 ** 3851 ** Returns: 3852 ** true -- if ok. 3853 ** false -- if vendor code could not be processed. 3854 ** 3855 ** Side Effects: 3856 ** It is reasonable to set mode flags here to tweak 3857 ** processing in other parts of the code if necessary. 3858 ** For example, if you are a vendor that uses $%y to 3859 ** indicate YP lookups, you could enable that here. 3860 */ 3861 3862 bool 3863 setvendor(vendor) 3864 char *vendor; 3865 { 3866 if (SM_STRCASEEQ(vendor, "Berkeley")) 3867 { 3868 VendorCode = VENDOR_BERKELEY; 3869 return true; 3870 } 3871 3872 /* add vendor extensions here */ 3873 3874 #ifdef SUN_EXTENSIONS 3875 if (SM_STRCASEEQ(vendor, "Sun")) 3876 { 3877 VendorCode = VENDOR_SUN; 3878 return true; 3879 } 3880 #endif /* SUN_EXTENSIONS */ 3881 #ifdef DEC 3882 if (SM_STRCASEEQ(vendor, "Digital")) 3883 { 3884 VendorCode = VENDOR_DEC; 3885 return true; 3886 } 3887 #endif /* DEC */ 3888 3889 #if defined(VENDOR_NAME) && defined(VENDOR_CODE) 3890 if (SM_STRCASEEQ(vendor, VENDOR_NAME)) 3891 { 3892 VendorCode = VENDOR_CODE; 3893 return true; 3894 } 3895 #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ 3896 3897 return false; 3898 } 3899 /* 3900 ** GETVENDOR -- return vendor name based on vendor code 3901 ** 3902 ** Parameters: 3903 ** vendorcode -- numeric representation of vendor. 3904 ** 3905 ** Returns: 3906 ** string containing vendor name. 3907 */ 3908 3909 char * 3910 getvendor(vendorcode) 3911 int vendorcode; 3912 { 3913 #if defined(VENDOR_NAME) && defined(VENDOR_CODE) 3914 /* 3915 ** Can't have the same switch case twice so need to 3916 ** handle VENDOR_CODE outside of switch. It might 3917 ** match one of the existing VENDOR_* codes. 3918 */ 3919 3920 if (vendorcode == VENDOR_CODE) 3921 return VENDOR_NAME; 3922 #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ 3923 3924 switch (vendorcode) 3925 { 3926 case VENDOR_BERKELEY: 3927 return "Berkeley"; 3928 3929 case VENDOR_SUN: 3930 return "Sun"; 3931 3932 case VENDOR_HP: 3933 return "HP"; 3934 3935 case VENDOR_IBM: 3936 return "IBM"; 3937 3938 case VENDOR_SENDMAIL: 3939 return "Sendmail"; 3940 3941 default: 3942 return "Unknown"; 3943 } 3944 } 3945 /* 3946 ** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults 3947 ** 3948 ** Vendor_pre_defaults is called before reading the configuration 3949 ** file; vendor_post_defaults is called immediately after. 3950 ** 3951 ** Parameters: 3952 ** e -- the global environment to initialize. 3953 ** 3954 ** Returns: 3955 ** none. 3956 */ 3957 3958 #if SHARE_V1 3959 int DefShareUid; /* default share uid to run as -- unused??? */ 3960 #endif 3961 3962 void 3963 vendor_pre_defaults(e) 3964 ENVELOPE *e; 3965 { 3966 #if SHARE_V1 3967 /* OTHERUID is defined in shares.h, do not be alarmed */ 3968 DefShareUid = OTHERUID; 3969 #endif 3970 #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) 3971 sun_pre_defaults(e); 3972 #endif 3973 #ifdef apollo 3974 /* 3975 ** stupid domain/os can't even open 3976 ** /etc/mail/sendmail.cf without this 3977 */ 3978 3979 sm_setuserenv("ISP", NULL); 3980 sm_setuserenv("SYSTYPE", NULL); 3981 #endif /* apollo */ 3982 } 3983 3984 3985 void 3986 vendor_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 4001 void 4002 vendor_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 4028 void 4029 vendor_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 */ 4065 int allow_severity = LOG_INFO; 4066 int deny_severity = LOG_NOTICE; 4067 #endif /* TCPWRAPPERS */ 4068 4069 char * 4070 validate_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) 4143 static 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 4153 long 4154 strtol(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 4250 char * 4251 strstr(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 4298 static struct hostent * 4299 sm_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 4346 static struct hostent * 4347 sm_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 4361 void 4362 freehostent(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 4374 struct hostent * 4375 sm_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 4539 struct hostent * 4540 sm_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 4592 struct passwd * 4593 sm_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 4605 struct passwd * 4606 sm_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 4638 void 4639 secureware_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 4696 static int 4697 add_hostnames(sa) 4698 SOCKADDR *sa; 4699 { 4700 struct hostent *hp; 4701 char **ha; 4702 char hnb[MAXHOSTNAMELEN]; 4703 4704 /* lookup 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 4820 struct rtentry; 4821 struct 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 4831 void 4832 load_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 5288 bool 5289 isloopback(sa) 5290 SOCKADDR sa; 5291 { 5292 /* XXX how to correctly extract IN_LOOPBACKNET part? */ 5293 #define SM_IS_IPV4_LOOP(a) (((ntohl(a) & IN_CLASSA_NET) \ 5294 >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 5295 #if NETINET6 5296 if (sa.sa.sa_family == AF_INET6 && 5297 IN6_IS_ADDR_V4MAPPED(&sa.sin6.sin6_addr) && 5298 SM_IS_IPV4_LOOP(((uint32_t *) (&sa.sin6.sin6_addr))[3])) 5299 return true; 5300 if (sa.sa.sa_family == AF_INET6 && 5301 IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr)) 5302 return true; 5303 #endif 5304 #if NETINET 5305 if (sa.sa.sa_family == AF_INET && 5306 SM_IS_IPV4_LOOP(sa.sin.sin_addr.s_addr)) 5307 return true; 5308 #endif 5309 return false; 5310 } 5311 5312 /* 5313 ** GET_NUM_PROCS_ONLINE -- return the number of processors currently online 5314 ** 5315 ** Parameters: 5316 ** none. 5317 ** 5318 ** Returns: 5319 ** The number of processors online. 5320 */ 5321 5322 static int 5323 get_num_procs_online() 5324 { 5325 int nproc = 0; 5326 5327 #ifdef USESYSCTL 5328 # if defined(CTL_HW) && defined(HW_NCPU) 5329 size_t sz; 5330 int mib[2]; 5331 5332 mib[0] = CTL_HW; 5333 mib[1] = HW_NCPU; 5334 sz = (size_t) sizeof(nproc); 5335 (void) sysctl(mib, 2, &nproc, &sz, NULL, 0); 5336 # endif /* defined(CTL_HW) && defined(HW_NCPU) */ 5337 #else /* USESYSCTL */ 5338 # ifdef _SC_NPROCESSORS_ONLN 5339 nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); 5340 # else /* _SC_NPROCESSORS_ONLN */ 5341 # ifdef __hpux 5342 # include <sys/pstat.h> 5343 struct pst_dynamic psd; 5344 5345 if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) 5346 nproc = psd.psd_proc_cnt; 5347 # endif /* __hpux */ 5348 # endif /* _SC_NPROCESSORS_ONLN */ 5349 #endif /* USESYSCTL */ 5350 5351 if (nproc <= 0) 5352 nproc = 1; 5353 return nproc; 5354 } 5355 /* 5356 ** SM_CLOSEFROM -- close file descriptors 5357 ** 5358 ** Parameters: 5359 ** lowest -- first fd to close 5360 ** highest -- last fd + 1 to close 5361 ** 5362 ** Returns: 5363 ** none 5364 */ 5365 5366 void 5367 sm_closefrom(lowest, highest) 5368 int lowest, highest; 5369 { 5370 #if HASCLOSEFROM 5371 closefrom(lowest); 5372 #else /* HASCLOSEFROM */ 5373 int i; 5374 5375 for (i = lowest; i < highest; i++) 5376 (void) close(i); 5377 #endif /* HASCLOSEFROM */ 5378 } 5379 #if HASFDWALK 5380 /* 5381 ** CLOSEFD_WALK -- walk fd's arranging to close them 5382 ** Callback for fdwalk() 5383 ** 5384 ** Parameters: 5385 ** lowest -- first fd to arrange to be closed 5386 ** fd -- fd to arrange to be closed 5387 ** 5388 ** Returns: 5389 ** zero 5390 */ 5391 5392 static int 5393 closefd_walk(lowest, fd) 5394 void *lowest; 5395 int fd; 5396 { 5397 if (fd >= *(int *)lowest) 5398 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 5399 return 0; 5400 } 5401 #endif /* HASFDWALK */ 5402 /* 5403 ** SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed 5404 ** 5405 ** Parameters: 5406 ** lowest -- first fd to arrange to be closed 5407 ** highest -- last fd + 1 to arrange to be closed 5408 ** 5409 ** Returns: 5410 ** none 5411 */ 5412 5413 void 5414 sm_close_on_exec(lowest, highest) 5415 int lowest, highest; 5416 { 5417 #if HASFDWALK 5418 (void) fdwalk(closefd_walk, &lowest); 5419 #else /* HASFDWALK */ 5420 int i, j; 5421 5422 for (i = lowest; i < highest; i++) 5423 { 5424 if ((j = fcntl(i, F_GETFD, 0)) != -1) 5425 (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 5426 } 5427 #endif /* HASFDWALK */ 5428 } 5429 /* 5430 ** SEED_RANDOM -- seed the random number generator 5431 ** 5432 ** Parameters: 5433 ** none 5434 ** 5435 ** Returns: 5436 ** none 5437 */ 5438 5439 void 5440 seed_random() 5441 { 5442 #if HASSRANDOMDEV 5443 srandomdev(); 5444 #else /* HASSRANDOMDEV */ 5445 long seed; 5446 struct timeval t; 5447 5448 seed = (long) CurrentPid; 5449 if (gettimeofday(&t, NULL) >= 0) 5450 seed += t.tv_sec + t.tv_usec; 5451 5452 # if HASRANDOM 5453 (void) srandom(seed); 5454 # else 5455 (void) srand((unsigned int) seed); 5456 # endif 5457 #endif /* HASSRANDOMDEV */ 5458 } 5459 /* 5460 ** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE 5461 ** 5462 ** Parameters: 5463 ** level -- syslog level 5464 ** id -- envelope ID or NULL (NOQUEUE) 5465 ** fmt -- format string 5466 ** arg... -- arguments as implied by fmt. 5467 ** 5468 ** Returns: 5469 ** none 5470 */ 5471 5472 /* VARARGS3 */ 5473 void 5474 #ifdef __STDC__ 5475 sm_syslog(int level, const char *id, const char *fmt, ...) 5476 #else /* __STDC__ */ 5477 sm_syslog(level, id, fmt, va_alist) 5478 int level; 5479 const char *id; 5480 const char *fmt; 5481 va_dcl 5482 #endif /* __STDC__ */ 5483 { 5484 char *buf; 5485 size_t bufsize; 5486 char *begin, *end; 5487 int save_errno; 5488 int seq = 1; 5489 int idlen; 5490 char buf0[MAXLINE]; 5491 char *newstring; 5492 extern int SyslogPrefixLen; 5493 SM_VA_LOCAL_DECL 5494 5495 save_errno = errno; 5496 if (id == NULL) 5497 id = "NOQUEUE"; 5498 idlen = strlen(id) + SyslogPrefixLen; 5499 5500 buf = buf0; 5501 bufsize = sizeof(buf0); 5502 5503 for (;;) 5504 { 5505 int n; 5506 5507 /* print log message into buf */ 5508 SM_VA_START(ap, fmt); 5509 n = sm_vsnprintf(buf, bufsize, fmt, ap); 5510 SM_VA_END(ap); 5511 SM_ASSERT(n >= 0); 5512 if (n < bufsize) 5513 break; 5514 5515 /* String too small, redo with correct size */ 5516 bufsize = n + 1; 5517 if (buf != buf0) 5518 { 5519 sm_free(buf); 5520 buf = NULL; 5521 } 5522 buf = sm_malloc_x(bufsize); 5523 } 5524 5525 /* clean up buf after it has been expanded with args */ 5526 #if _FFR_LOGASIS >= 5 5527 /* for testing! */ 5528 newstring = buf; 5529 #else 5530 newstring = str2prt(buf); 5531 #endif 5532 if ((strlen(newstring) + idlen + 1) < SYSLOG_BUFSIZE) 5533 { 5534 #if LOG 5535 if (*id == '\0') 5536 { 5537 if (tTd(89, 10)) 5538 { 5539 struct timeval tv; 5540 5541 gettimeofday(&tv, NULL); 5542 sm_dprintf("%ld.%06ld %s\n", (long) tv.tv_sec, 5543 (long) tv.tv_usec, newstring); 5544 } 5545 else if (tTd(89, 8)) 5546 sm_dprintf("%s\n", newstring); 5547 else 5548 syslog(level, "%s", newstring); 5549 } 5550 else 5551 { 5552 if (tTd(89, 10)) 5553 { 5554 struct timeval tv; 5555 5556 gettimeofday(&tv, NULL); 5557 sm_dprintf("%ld.%06ld %s: %s\n", (long) tv.tv_sec, 5558 (long) tv.tv_usec, id, newstring); 5559 } 5560 else if (tTd(89, 8)) 5561 sm_dprintf("%s: %s\n", id, newstring); 5562 else 5563 syslog(level, "%s: %s", id, newstring); 5564 } 5565 #else /* LOG */ 5566 /*XXX should do something more sensible */ 5567 if (*id == '\0') 5568 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", 5569 newstring); 5570 else 5571 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5572 "%s: %s\n", id, newstring); 5573 #endif /* LOG */ 5574 if (buf != buf0) 5575 sm_free(buf); 5576 errno = save_errno; 5577 return; 5578 } 5579 5580 /* 5581 ** additional length for splitting: " ..." + 3, where 3 is magic to 5582 ** have some data for the next entry. 5583 */ 5584 5585 #define SL_SPLIT 7 5586 5587 begin = newstring; 5588 idlen += 5; /* strlen("[999]"), see below */ 5589 while (*begin != '\0' && 5590 (strlen(begin) + idlen) > SYSLOG_BUFSIZE) 5591 { 5592 char save; 5593 5594 if (seq >= 999) 5595 { 5596 /* Too many messages */ 5597 break; 5598 } 5599 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5600 while (end > begin) 5601 { 5602 /* Break on comma or space */ 5603 if (*end == ',' || *end == ' ') 5604 { 5605 end++; /* Include separator */ 5606 break; 5607 } 5608 end--; 5609 } 5610 /* No separator, break midstring... */ 5611 if (end == begin) 5612 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5613 save = *end; 5614 *end = 0; 5615 #if LOG 5616 if (tTd(89, 8)) 5617 sm_dprintf("%s[%d]: %s ...\n", id, seq++, begin); 5618 else 5619 syslog(level, "%s[%d]: %s ...", id, seq++, begin); 5620 #else /* LOG */ 5621 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5622 "%s[%d]: %s ...\n", id, seq++, begin); 5623 #endif /* LOG */ 5624 *end = save; 5625 begin = end; 5626 } 5627 if (seq >= 999) 5628 { 5629 #if LOG 5630 if (tTd(89, 8)) 5631 sm_dprintf("%s[%d]: log terminated, too many parts\n", 5632 id, seq); 5633 else 5634 syslog(level, "%s[%d]: log terminated, too many parts", 5635 id, seq); 5636 #else /* LOG */ 5637 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5638 "%s[%d]: log terminated, too many parts\n", id, seq); 5639 #endif /* LOG */ 5640 } 5641 else if (*begin != '\0') 5642 { 5643 #if LOG 5644 if (tTd(89, 8)) 5645 sm_dprintf("%s[%d]: %s\n", id, seq, begin); 5646 else 5647 syslog(level, "%s[%d]: %s", id, seq, begin); 5648 #else /* LOG */ 5649 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5650 "%s[%d]: %s\n", id, seq, begin); 5651 #endif /* LOG */ 5652 } 5653 if (buf != buf0) 5654 sm_free(buf); 5655 errno = save_errno; 5656 } 5657 /* 5658 ** HARD_SYSLOG -- call syslog repeatedly until it works 5659 ** 5660 ** Needed on HP-UX, which apparently doesn't guarantee that 5661 ** syslog succeeds during interrupt handlers. 5662 */ 5663 5664 #if defined(__hpux) && !defined(HPUX11) 5665 5666 # define MAXSYSLOGTRIES 100 5667 # undef syslog 5668 # ifdef V4FS 5669 # define XCNST const 5670 # define CAST (const char *) 5671 # else 5672 # define XCNST 5673 # define CAST 5674 # endif 5675 5676 void 5677 # ifdef __STDC__ 5678 hard_syslog(int pri, XCNST char *msg, ...) 5679 # else /* __STDC__ */ 5680 hard_syslog(pri, msg, va_alist) 5681 int pri; 5682 XCNST char *msg; 5683 va_dcl 5684 # endif /* __STDC__ */ 5685 { 5686 int i; 5687 char buf[SYSLOG_BUFSIZE]; 5688 SM_VA_LOCAL_DECL 5689 5690 SM_VA_START(ap, msg); 5691 (void) sm_vsnprintf(buf, sizeof(buf), msg, ap); 5692 SM_VA_END(ap); 5693 5694 for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; ) 5695 continue; 5696 } 5697 5698 # undef CAST 5699 #endif /* defined(__hpux) && !defined(HPUX11) */ 5700 #if NEEDLOCAL_HOSTNAME_LENGTH 5701 /* 5702 ** LOCAL_HOSTNAME_LENGTH 5703 ** 5704 ** This is required to get sendmail to compile against BIND 4.9.x 5705 ** on Ultrix. 5706 ** 5707 ** Unfortunately, a Compaq Y2K patch kit provides it without 5708 ** bumping __RES in /usr/include/resolv.h so we can't automatically 5709 ** figure out whether it is needed. 5710 */ 5711 5712 int 5713 local_hostname_length(hostname) 5714 char *hostname; 5715 { 5716 size_t len_host, len_domain; 5717 5718 if (!*_res.defdname) 5719 res_init(); 5720 len_host = strlen(hostname); 5721 len_domain = strlen(_res.defdname); 5722 if (len_host > len_domain && 5723 (SM_STRCASEEQ(hostname + len_host - len_domain, _res.defdname)) && 5724 hostname[len_host - len_domain - 1] == '.') 5725 return len_host - len_domain - 1; 5726 else 5727 return 0; 5728 } 5729 #endif /* NEEDLOCAL_HOSTNAME_LENGTH */ 5730 5731 #if NEEDLINK 5732 /* 5733 ** LINK -- clone a file 5734 ** 5735 ** Some OS's lacks link() and hard links. Since sendmail is using 5736 ** link() as an efficient way to clone files, this implementation 5737 ** will simply do a file copy. 5738 ** 5739 ** NOTE: This link() replacement is not a generic replacement as it 5740 ** does not handle all of the semantics of the real link(2). 5741 ** 5742 ** Parameters: 5743 ** source -- pathname of existing file. 5744 ** target -- pathname of link (clone) to be created. 5745 ** 5746 ** Returns: 5747 ** 0 -- success. 5748 ** -1 -- failure, see errno for details. 5749 */ 5750 5751 int 5752 link(source, target) 5753 const char *source; 5754 const char *target; 5755 { 5756 int save_errno; 5757 int sff; 5758 int src = -1, dst = -1; 5759 ssize_t readlen; 5760 ssize_t writelen; 5761 char buf[BUFSIZ]; 5762 struct stat st; 5763 5764 sff = SFF_REGONLY|SFF_OPENASROOT; 5765 if (DontLockReadFiles) 5766 sff |= SFF_NOLOCK; 5767 5768 /* Open the original file */ 5769 src = safeopen((char *)source, O_RDONLY, 0, sff); 5770 if (src < 0) 5771 goto fail; 5772 5773 /* Obtain the size and the mode */ 5774 if (fstat(src, &st) < 0) 5775 goto fail; 5776 5777 /* Create the duplicate copy */ 5778 sff &= ~SFF_NOLOCK; 5779 sff |= SFF_CREAT; 5780 dst = safeopen((char *)target, O_CREAT|O_EXCL|O_WRONLY, 5781 st.st_mode, sff); 5782 if (dst < 0) 5783 goto fail; 5784 5785 /* Copy all of the bytes one buffer at a time */ 5786 while ((readlen = read(src, &buf, sizeof(buf))) > 0) 5787 { 5788 ssize_t left = readlen; 5789 char *p = buf; 5790 5791 while (left > 0 && 5792 (writelen = write(dst, p, (size_t) left)) >= 0) 5793 { 5794 left -= writelen; 5795 p += writelen; 5796 } 5797 if (writelen < 0) 5798 break; 5799 } 5800 5801 /* Any trouble reading? */ 5802 if (readlen < 0 || writelen < 0) 5803 goto fail; 5804 5805 /* Close the input file */ 5806 if (close(src) < 0) 5807 { 5808 src = -1; 5809 goto fail; 5810 } 5811 src = -1; 5812 5813 /* Close the output file */ 5814 if (close(dst) < 0) 5815 { 5816 /* don't set dst = -1 here so we unlink the file */ 5817 goto fail; 5818 } 5819 5820 /* Success */ 5821 return 0; 5822 5823 fail: 5824 save_errno = errno; 5825 if (src >= 0) 5826 (void) close(src); 5827 if (dst >= 0) 5828 { 5829 (void) unlink(target); 5830 (void) close(dst); 5831 } 5832 errno = save_errno; 5833 return -1; 5834 } 5835 #endif /* NEEDLINK */ 5836 5837 /* 5838 ** Compile-Time options 5839 */ 5840 5841 #define SM_STR(x) #x 5842 #define SM_XSTR(x) SM_STR(x) 5843 5844 char *CompileOptions[] = 5845 { 5846 #if ALLOW_255 5847 /* if not enabled (and EightBitAddrOK not set): convert 0xff to 0x7f */ 5848 "ALLOW_255", 5849 #endif 5850 #if DANE 5851 "DANE", 5852 #endif 5853 #if NAMED_BIND 5854 # if DNSMAP 5855 "DNSMAP", 5856 # endif 5857 #endif 5858 #if EGD 5859 "EGD", 5860 #endif 5861 #if HESIOD 5862 "HESIOD", 5863 #endif 5864 #if HESIOD_ALLOW_NUMERIC_LOGIN 5865 "HESIOD_ALLOW_NUMERIC_LOGIN", 5866 #endif 5867 #if HES_GETMAILHOST 5868 "HES_GETMAILHOST", 5869 #endif 5870 #if IPV6_FULL 5871 /* Use uncompressed IPv6 address format (no "::") by default */ 5872 "IPV6_FULL", 5873 #endif 5874 #if LDAPMAP 5875 "LDAPMAP", 5876 #endif 5877 #if LDAP_NETWORK_TIMEOUT 5878 # if LDAPMAP 5879 /* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */ 5880 "LDAP_NETWORK_TIMEOUT", 5881 # else 5882 # ERROR "LDAP_NETWORK_TIMEOUT requires LDAPMAP" 5883 # endif 5884 #endif 5885 #if LDAP_REFERRALS 5886 # if LDAPMAP 5887 "LDAP_REFERRALS", 5888 # else 5889 # ERROR "LDAP_REFERRALS requires LDAPMAP" 5890 # endif 5891 #endif 5892 #if LOG 5893 "LOG", 5894 #endif 5895 #if MAP_NSD 5896 "MAP_NSD", 5897 #endif 5898 #if MAP_REGEX 5899 "MAP_REGEX", 5900 #endif 5901 #if MATCHGECOS 5902 "MATCHGECOS", 5903 #endif 5904 #if MAXDAEMONS != 10 5905 "MAXDAEMONS=" SM_XSTR(MAXDAEMONS), 5906 #endif 5907 #if defined(MSGIDLOGLEN) 5908 "MSGIDLOGLEN=" SM_XSTR(MSGIDLOGLEN), 5909 #endif 5910 #if MILTER 5911 "MILTER", 5912 #endif 5913 #if MIME7TO8 5914 "MIME7TO8", 5915 #endif 5916 #if MIME7TO8_OLD 5917 "MIME7TO8_OLD", 5918 #endif 5919 #if MIME8TO7 5920 "MIME8TO7", 5921 #endif 5922 #if NAMED_BIND 5923 "NAMED_BIND", 5924 #endif 5925 #if NDBM 5926 "NDBM", 5927 #endif 5928 #if NETINET 5929 "NETINET", 5930 #endif 5931 #if NETINET6 5932 "NETINET6", 5933 #endif 5934 #if NETINFO 5935 "NETINFO", 5936 #endif 5937 #if NETISO 5938 "NETISO", 5939 #endif 5940 #if NETNS 5941 "NETNS", 5942 #endif 5943 #if NETUNIX 5944 "NETUNIX", 5945 #endif 5946 #if NETX25 5947 "NETX25", 5948 #endif 5949 #if NO_EOH_FIELDS 5950 "NO_EOH_FIELDS", 5951 #endif 5952 #if NEWDB 5953 # if defined(DB_VERSION_MAJOR) && defined(DB_VERSION_MINOR) 5954 # if DB_VERSION_MAJOR >= 5 && !HASFLOCK 5955 # ERROR "Berkeley DB file locking needs flock() for version 5.x (and greater?)" 5956 # endif 5957 "NEWDB=" SM_XSTR(DB_VERSION_MAJOR) "." SM_XSTR(DB_VERSION_MINOR), 5958 # else 5959 "NEWDB", 5960 # endif 5961 #endif 5962 #if CDB 5963 "CDB=" SM_XSTR(CDB), 5964 #endif 5965 #if NIS 5966 "NIS", 5967 #endif 5968 #if NISPLUS 5969 "NISPLUS", 5970 #endif 5971 #if NO_DH 5972 "NO_DH", 5973 #endif 5974 #if PH_MAP 5975 "PH_MAP", 5976 #endif 5977 #ifdef PICKY_HELO_CHECK 5978 "PICKY_HELO_CHECK", 5979 #endif 5980 #if PIPELINING 5981 "PIPELINING", 5982 #endif 5983 #if SASL 5984 # if SASL >= 20000 5985 "SASLv2", 5986 # else 5987 "SASL", 5988 # endif 5989 #endif 5990 #if SCANF 5991 "SCANF", 5992 #endif 5993 #if SM_LDAP_ERROR_ON_MISSING_ARGS 5994 "SM_LDAP_ERROR_ON_MISSING_ARGS", 5995 #endif 5996 #if SMTPDEBUG 5997 "SMTPDEBUG", 5998 #endif 5999 #if SOCKETMAP 6000 "SOCKETMAP", 6001 #endif 6002 #if STARTTLS 6003 "STARTTLS", 6004 #endif 6005 #if SUID_ROOT_FILES_OK 6006 "SUID_ROOT_FILES_OK", 6007 #endif 6008 #if SYSLOG_BUFSIZE > 1024 6009 "SYSLOG_BUFSIZE=" SM_XSTR(SYSLOG_BUFSIZE), 6010 #endif 6011 #if TCPWRAPPERS 6012 "TCPWRAPPERS", 6013 #endif 6014 #if TLS_NO_RSA 6015 "TLS_NO_RSA", 6016 #endif 6017 #if TLS_EC 6018 /* elliptic curves */ 6019 "TLS_EC", 6020 #endif 6021 #if TLS_VRFY_PER_CTX 6022 "TLS_VRFY_PER_CTX", 6023 #endif 6024 #if USERDB 6025 "USERDB", 6026 #endif 6027 #if USE_EAI 6028 6029 /* 6030 ** Initial/Partial/Experimental EAI (SMTPUTF8) support. 6031 ** Requires ICU include files and library depending on the OS. 6032 ** Initial patch from Arnt Gulbrandsen. 6033 */ 6034 6035 # if !ALLOW_255 6036 # ERROR "USE_EAI requires ALLOW_255" 6037 # endif 6038 # if _FFR_EIGHT_BIT_ADDR_OK 6039 # ERROR "Cannot enable both USE_EAI and _FFR_EIGHT_BIT_ADDR_OK" 6040 # endif 6041 "USE_EAI", 6042 #endif 6043 #if USE_LDAP_INIT 6044 "USE_LDAP_INIT", 6045 #endif 6046 #if USE_TTYPATH 6047 "USE_TTYPATH", 6048 #endif 6049 #if XDEBUG 6050 "XDEBUG", 6051 #endif 6052 #if XLA 6053 "XLA", 6054 #endif 6055 NULL 6056 }; 6057 6058 6059 /* 6060 ** OS compile options. 6061 */ 6062 6063 char *OsCompileOptions[] = 6064 { 6065 #if ADDRCONFIG_IS_BROKEN 6066 "ADDRCONFIG_IS_BROKEN", 6067 #endif 6068 #ifdef AUTO_NETINFO_HOSTS 6069 "AUTO_NETINFO_HOSTS", 6070 #endif 6071 #ifdef AUTO_NIS_ALIASES 6072 "AUTO_NIS_ALIASES", 6073 #endif 6074 #if BROKEN_RES_SEARCH 6075 "BROKEN_RES_SEARCH", 6076 #endif 6077 #ifdef BSD4_4_SOCKADDR 6078 "BSD4_4_SOCKADDR", 6079 #endif 6080 #if BOGUS_O_EXCL 6081 "BOGUS_O_EXCL", 6082 #endif 6083 #if DEC_OSF_BROKEN_GETPWENT 6084 "DEC_OSF_BROKEN_GETPWENT", 6085 #endif 6086 #if DNSSEC_TEST 6087 "DNSSEC_TEST", 6088 #endif 6089 #if FAST_PID_RECYCLE 6090 "FAST_PID_RECYCLE", 6091 #endif 6092 #if HASCLOSEFROM 6093 "HASCLOSEFROM", 6094 #endif 6095 #if HASFCHOWN 6096 "HASFCHOWN", 6097 #endif 6098 #if HASFCHMOD 6099 "HASFCHMOD", 6100 #endif 6101 #if HASFDWALK 6102 "HASFDWALK", 6103 #endif 6104 #if HASFLOCK 6105 "HASFLOCK", 6106 #endif 6107 #if HASGETDTABLESIZE 6108 "HASGETDTABLESIZE", 6109 #endif 6110 #if HAS_GETHOSTBYNAME2 6111 "HAS_GETHOSTBYNAME2", 6112 #endif 6113 #if HASGETUSERSHELL 6114 "HASGETUSERSHELL", 6115 #endif 6116 #if HASINITGROUPS 6117 "HASINITGROUPS", 6118 #endif 6119 #if HASLDAPGETALIASBYNAME 6120 "HASLDAPGETALIASBYNAME", 6121 #endif 6122 #if HASLSTAT 6123 "HASLSTAT", 6124 #endif 6125 #if HASNICE 6126 "HASNICE", 6127 #endif 6128 #if HASRANDOM 6129 "HASRANDOM", 6130 #endif 6131 #if HASRRESVPORT 6132 "HASRRESVPORT", 6133 #endif 6134 #if HASSETEGID 6135 "HASSETEGID", 6136 #endif 6137 #if HASSETLOGIN 6138 "HASSETLOGIN", 6139 #endif 6140 #if HASSETREGID 6141 "HASSETREGID", 6142 #endif 6143 #if HASSETRESGID 6144 "HASSETRESGID", 6145 #endif 6146 #if HASSETREUID 6147 "HASSETREUID", 6148 #endif 6149 #if HASSETRLIMIT 6150 "HASSETRLIMIT", 6151 #endif 6152 #if HASSETSID 6153 "HASSETSID", 6154 #endif 6155 #if HASSETUSERCONTEXT 6156 "HASSETUSERCONTEXT", 6157 #endif 6158 #if HASSETVBUF 6159 "HASSETVBUF", 6160 #endif 6161 #if HAS_ST_GEN 6162 "HAS_ST_GEN", 6163 #endif 6164 #if HASSRANDOMDEV 6165 "HASSRANDOMDEV", 6166 #endif 6167 #if HASURANDOMDEV 6168 "HASURANDOMDEV", 6169 #endif 6170 #if HASSTRERROR 6171 "HASSTRERROR", 6172 #endif 6173 #if HASULIMIT 6174 "HASULIMIT", 6175 #endif 6176 #if HASUNAME 6177 "HASUNAME", 6178 #endif 6179 #if HASUNSETENV 6180 "HASUNSETENV", 6181 #endif 6182 #if HASWAITPID 6183 "HASWAITPID", 6184 #endif 6185 #if HAVE_NANOSLEEP 6186 "HAVE_NANOSLEEP", 6187 #endif 6188 #if IDENTPROTO 6189 "IDENTPROTO", 6190 #endif 6191 #if IP_SRCROUTE 6192 "IP_SRCROUTE", 6193 #endif 6194 #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 6195 "LOCK_ON_OPEN", 6196 #endif 6197 #if MILTER_NO_NAGLE 6198 "MILTER_NO_NAGLE ", 6199 #endif 6200 #if NEEDFSYNC 6201 "NEEDFSYNC", 6202 #endif 6203 #if NEEDLINK 6204 "NEEDLINK", 6205 #endif 6206 #if NEEDLOCAL_HOSTNAME_LENGTH 6207 "NEEDLOCAL_HOSTNAME_LENGTH", 6208 #endif 6209 #if NEEDSGETIPNODE 6210 "NEEDSGETIPNODE", 6211 #endif 6212 #if NEEDSTRSTR 6213 "NEEDSTRSTR", 6214 #endif 6215 #if NEEDSTRTOL 6216 "NEEDSTRTOL", 6217 #endif 6218 #ifdef NO_GETSERVBYNAME 6219 "NO_GETSERVBYNAME", 6220 #endif 6221 #if NOFTRUNCATE 6222 "NOFTRUNCATE", 6223 #endif 6224 #if REQUIRES_DIR_FSYNC 6225 "REQUIRES_DIR_FSYNC", 6226 #endif 6227 #if RLIMIT_NEEDS_SYS_TIME_H 6228 "RLIMIT_NEEDS_SYS_TIME_H", 6229 #endif 6230 #if SAFENFSPATHCONF 6231 "SAFENFSPATHCONF", 6232 #endif 6233 #if SECUREWARE 6234 "SECUREWARE", 6235 #endif 6236 #if SFS_TYPE == SFS_4ARGS 6237 "SFS_4ARGS", 6238 #elif SFS_TYPE == SFS_MOUNT 6239 "SFS_MOUNT", 6240 #elif SFS_TYPE == SFS_NONE 6241 "SFS_NONE", 6242 #elif SFS_TYPE == SFS_NT 6243 "SFS_NT", 6244 #elif SFS_TYPE == SFS_STATFS 6245 "SFS_STATFS", 6246 #elif SFS_TYPE == SFS_STATVFS 6247 "SFS_STATVFS", 6248 #elif SFS_TYPE == SFS_USTAT 6249 "SFS_USTAT", 6250 #elif SFS_TYPE == SFS_VFS 6251 "SFS_VFS", 6252 #endif 6253 #if SHARE_V1 6254 "SHARE_V1", 6255 #endif 6256 #if SIOCGIFCONF_IS_BROKEN 6257 "SIOCGIFCONF_IS_BROKEN", 6258 #endif 6259 #if SIOCGIFNUM_IS_BROKEN 6260 "SIOCGIFNUM_IS_BROKEN", 6261 #endif 6262 #if SNPRINTF_IS_BROKEN 6263 "SNPRINTF_IS_BROKEN", 6264 #endif 6265 #if SO_REUSEADDR_IS_BROKEN 6266 "SO_REUSEADDR_IS_BROKEN", 6267 #endif 6268 #if SYS5SETPGRP 6269 "SYS5SETPGRP", 6270 #endif 6271 #if SYSTEM5 6272 "SYSTEM5", 6273 #endif 6274 #if USE_DOUBLE_FORK 6275 "USE_DOUBLE_FORK", 6276 #endif 6277 #if USE_ENVIRON 6278 "USE_ENVIRON", 6279 #endif 6280 #if USE_SA_SIGACTION 6281 "USE_SA_SIGACTION", 6282 #endif 6283 #if USE_SIGLONGJMP 6284 "USE_SIGLONGJMP", 6285 #endif 6286 #if USEGETCONFATTR 6287 "USEGETCONFATTR", 6288 #endif 6289 #if USESETEUID 6290 "USESETEUID", 6291 #endif 6292 #ifdef USESYSCTL 6293 "USESYSCTL", 6294 #endif 6295 #if USE_OPENSSL_ENGINE 6296 /* 6297 ** 0: OpenSSL ENGINE? 6298 ** 1: Support Sun OpenSSL patch for SPARC T4 pkcs11 6299 ** 2: none 6300 */ 6301 # if USE_OPENSSL_ENGINE != 1 6302 "USE_OPENSSL_ENGINE=" SM_XSTR(USE_OPENSSL_ENGINE), 6303 # else 6304 "USE_OPENSSL_ENGINE", 6305 # endif 6306 #endif 6307 #if USING_NETSCAPE_LDAP 6308 "USING_NETSCAPE_LDAP", 6309 #endif 6310 #ifdef WAITUNION 6311 "WAITUNION", 6312 #endif 6313 NULL 6314 }; 6315 6316 /* 6317 ** FFR compile options. 6318 */ 6319 6320 char *FFRCompileOptions[] = 6321 { 6322 #if _FFR_ADD_BCC 6323 /* see cf/feature/bcc.m4 */ 6324 "_FFR_ADD_BCC", 6325 #endif 6326 #if _FFR_ADDR_TYPE_MODES 6327 /* more info in {addr_type}, requires m4 changes! */ 6328 "_FFR_ADDR_TYPE_MODES", 6329 #endif 6330 #if _FFR_ALIAS_DETAIL 6331 /* try to handle +detail for aliases */ 6332 "_FFR_ALIAS_DETAIL", 6333 #endif 6334 #if _FFR_ALLOW_SASLINFO 6335 /* DefaultAuthInfo can be specified by user. */ 6336 /* DefaultAuthInfo doesn't really work in 8.13 anymore. */ 6337 "_FFR_ALLOW_SASLINFO", 6338 #endif 6339 #if _FFR_BADRCPT_SHUTDOWN 6340 /* shut down connection (421) if there are too many bad RCPTs */ 6341 "_FFR_BADRCPT_SHUTDOWN", 6342 #endif 6343 #if _FFR_BESTMX_BETTER_TRUNCATION 6344 /* Better truncation of list of MX records for dns map. */ 6345 "_FFR_BESTMX_BETTER_TRUNCATION", 6346 #endif 6347 #if _FFR_BLANKENV_MACV 6348 /* also look up macros in BlankEnvelope */ 6349 "_FFR_BLANKENV_MACV", 6350 #endif 6351 #if _FFR_BOUNCE_QUEUE 6352 /* Separate, unprocessed queue for DSNs */ 6353 /* John Gardiner Myers of Proofpoint */ 6354 "_FFR_BOUNCE_QUEUE", 6355 #endif 6356 #if _FFR_CATCH_BROKEN_MTAS 6357 /* Deal with MTAs that send a reply during the DATA phase. */ 6358 "_FFR_CATCH_BROKEN_MTAS", 6359 #endif 6360 #if _FFR_CHK_QUEUE 6361 /* Stricter checks about queue directory permissions. */ 6362 "_FFR_CHK_QUEUE", 6363 #endif 6364 #if _FFR_CLIENTCA 6365 /* 6366 ** Allow to set client specific CA values. 6367 ** CACertFile: see doc/op.*: 6368 ** "The DNs of these certificates are sent to the client 6369 ** during the TLS handshake (as part of the CertificateRequest) 6370 ** as the list of acceptable CAs. 6371 ** However, do not list too many root CAs in that file, 6372 ** otherwise the TLS handshake may fail;" 6373 ** In TLSv1.3 the certs in CACertFile are also sent by 6374 ** the client to the server and there is seemingly a 6375 ** 16KB limit (just in OpenSSL?). 6376 ** Having a separate CACertFile for the client 6377 ** helps to avoid this problem. 6378 */ 6379 6380 "_FFR_CLIENTCA", 6381 #endif 6382 #if _FFR_CLIENT_SIZE 6383 /* Don't try to send mail if its size exceeds SIZE= of server. */ 6384 "_FFR_CLIENT_SIZE", 6385 #endif 6386 #if _FFR_DIGUNIX_SAFECHOWN 6387 /* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */ 6388 /* Problem noted by Anne Bennett of Concordia University */ 6389 "_FFR_DIGUNIX_SAFECHOWN", 6390 #endif 6391 #if _FFR_DM_ONE 6392 /* deliver first TA in background, then queue */ 6393 "_FFR_DM_ONE", 6394 #endif 6395 #if _FFR_DMTRIGGER 6396 /* 6397 ** WIP: DeliveryMode=Trigger: queue message and notify 6398 ** some kind of queue manager about it. 6399 */ 6400 6401 "_FFR_DMTRIGGER", 6402 #endif 6403 #if _FFR_DNSMAP_ALIASABLE 6404 /* Allow dns map type to be used for aliases. */ 6405 /* Don Lewis of TDK */ 6406 "_FFR_DNSMAP_ALIASABLE", 6407 #endif 6408 #if _FFR_DONTLOCKFILESFORREAD_OPTION 6409 /* Enable DontLockFilesForRead option. */ 6410 "_FFR_DONTLOCKFILESFORREAD_OPTION", 6411 #endif 6412 #if _FFR_DOTTED_USERNAMES 6413 /* Allow usernames with '.' */ 6414 "_FFR_DOTTED_USERNAMES", 6415 #endif 6416 #if _FFR_DPO_CS 6417 /* 6418 ** Make DaemonPortOptions case sensitive. 6419 ** For some unknown reasons the code converted every option 6420 ** to uppercase (first letter only, as that's the only one that 6421 ** is actually checked). This prevented all new lower case options 6422 ** from working... 6423 ** The documentation doesn't say anything about case (in)sensitivity, 6424 ** which means it should be case sensitive by default, 6425 ** but it's not a good idea to change this within a patch release, 6426 ** so let's delay this to 8.15. 6427 */ 6428 6429 "_FFR_DPO_CS", 6430 #endif 6431 #if _FFR_DPRINTF_MAP 6432 /* dprintf map for logging */ 6433 "_FFR_DPRINTF_MAP", 6434 #endif 6435 #if _FFR_DROP_TRUSTUSER_WARNING 6436 /* 6437 ** Don't issue this warning: 6438 ** "readcf: option TrustedUser may cause problems on systems 6439 ** which do not support fchown() if UseMSP is not set. 6440 */ 6441 6442 "_FFR_DROP_TRUSTUSER_WARNING", 6443 #endif 6444 #if _FFR_EIGHT_BIT_ADDR_OK 6445 /* EightBitAddrOK: allow 8-bit e-mail addresses */ 6446 "_FFR_EIGHT_BIT_ADDR_OK", 6447 #endif 6448 #if _FFR_EXPAND_HELONAME 6449 /* perform macro expansion for heloname */ 6450 "_FFR_EXPAND_HELONAME", 6451 #endif 6452 #if _FFR_EXTRA_MAP_CHECK 6453 /* perform extra checks on $( $) in R lines */ 6454 "_FFR_EXTRA_MAP_CHECK", 6455 #endif 6456 #if _FFR_GETHBN_ExFILE 6457 /* 6458 ** According to Motonori Nakamura some gethostbyname() 6459 ** implementations (TurboLinux?) may (temporarily) fail 6460 ** due to a lack of file descriptors. Enabling this FFR 6461 ** will check errno for EMFILE and ENFILE and in case of a match 6462 ** cause a temporary error instead of a permanent error. 6463 ** The right solution is of course to file a bug against those 6464 ** systems such that they actually set h_errno = TRY_AGAIN. 6465 */ 6466 6467 "_FFR_GETHBN_ExFILE", 6468 #endif 6469 #if _FFR_FIPSMODE 6470 /* FIPSMode (if supported by OpenSSL library) */ 6471 "_FFR_FIPSMODE", 6472 #endif 6473 #if _FFR_FIX_DASHT 6474 /* 6475 ** If using -t, force not sending to argv recipients, even 6476 ** if they are mentioned in the headers. 6477 */ 6478 6479 "_FFR_FIX_DASHT", 6480 #endif 6481 #if _FFR_FORWARD_SYSERR 6482 /* Cause a "syserr" if forward file isn't "safe". */ 6483 "_FFR_FORWARD_SYSERR", 6484 #endif 6485 #if _FFR_GEN_ORCPT 6486 /* Generate a ORCPT DSN arg if not already provided */ 6487 "_FFR_GEN_ORCPT", 6488 #endif 6489 #if _FFR_HANDLE_ISO8859_GECOS 6490 /* 6491 ** Allow ISO 8859 characters in GECOS field: replace them 6492 ** with ASCII "equivalent". 6493 */ 6494 6495 /* Peter Eriksson of Linkopings universitet */ 6496 "_FFR_HANDLE_ISO8859_GECOS", 6497 #endif 6498 #if _FFR_HANDLE_HDR_RW_TEMPFAIL 6499 /* 6500 ** Temporary header rewriting problems from remotename() etc 6501 ** are not "sticky" for mci (e.g., during queue runs). 6502 */ 6503 6504 "_FFR_HANDLE_HDR_RW_TEMPFAIL", 6505 #endif 6506 #if _FFR_HPUX_NSSWITCH 6507 /* Use nsswitch on HP-UX */ 6508 "_FFR_HPUX_NSSWITCH", 6509 #endif 6510 #if _FFR_IGNORE_BOGUS_ADDR 6511 /* Ignore addresses for which prescan() failed */ 6512 "_FFR_IGNORE_BOGUS_ADDR", 6513 #endif 6514 #if _FFR_IGNORE_EXT_ON_HELO 6515 /* Ignore extensions offered in response to HELO */ 6516 "_FFR_IGNORE_EXT_ON_HELO", 6517 #endif 6518 #if _FFR_KEEPBCC 6519 /* Keep Bcc header */ 6520 "_FFR_KEEPBCC", 6521 #endif 6522 #if _FFR_LOCAL_DAEMON 6523 /* Local daemon mode (-bl) which only accepts loopback connections */ 6524 "_FFR_LOCAL_DAEMON", 6525 #endif 6526 #if _FFR_LOG_MORE1 6527 /* log some TLS/AUTH info in from= too */ 6528 "_FFR_LOG_MORE1=" SM_XSTR(_FFR_LOG_MORE1), 6529 #endif 6530 #if _FFR_LOG_MORE2 6531 /* log some TLS info in to= too */ 6532 "_FFR_LOG_MORE2=" SM_XSTR(_FFR_LOG_MORE2), 6533 #endif 6534 #if _FFR_MAIL_MACRO 6535 /* make the "real" sender address available in {mail_from} */ 6536 "_FFR_MAIL_MACRO", 6537 #endif 6538 #if _FFR_MAXDATASIZE 6539 /* 6540 ** It is possible that a header is larger than MILTER_CHUNK_SIZE, 6541 ** hence this shouldn't be used as limit for milter communication. 6542 ** see also libmilter/comm.c 6543 ** Gurusamy Sarathy of ActiveState 6544 */ 6545 6546 "_FFR_MAXDATASIZE", 6547 #endif 6548 #if _FFR_MAX_FORWARD_ENTRIES 6549 /* Try to limit number of .forward entries */ 6550 /* (doesn't work) */ 6551 /* Randall S. Winchester of the University of Maryland */ 6552 "_FFR_MAX_FORWARD_ENTRIES", 6553 #endif 6554 #if _FFR_MAX_SLEEP_TIME 6555 /* Limit sleep(2) time in libsm/clock.c */ 6556 "_FFR_MAX_SLEEP_TIME", 6557 #endif 6558 #if _FFR_MDS_NEGOTIATE 6559 /* MaxDataSize negotiation with libmilter */ 6560 "_FFR_MDS_NEGOTIATE", 6561 #endif 6562 #if _FFR_MEMSTAT 6563 /* Check free memory */ 6564 "_FFR_MEMSTAT", 6565 #endif 6566 #if _FFR_MILTER_CHECK 6567 "_FFR_MILTER_CHECK", 6568 #endif 6569 #if _FFR_MILTER_CONNECT_REPLYCODE 6570 /* milter: propagate replycode returned by connect commands */ 6571 /* John Gardiner Myers of Proofpoint */ 6572 "_FFR_MILTER_CONNECT_REPLYCODE", 6573 #endif 6574 #if _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF 6575 /* 6576 ** milter_body() uses the same conversion algorithm as putbody() 6577 ** to translate the "local" df format (\n) to SMTP format (\r\n). 6578 ** However, putbody() and mime8to7() use different conversion 6579 ** algorithms. 6580 ** If the input date does not follow the SMTP standard 6581 ** (e.g., if it has "naked \r"s), then the output from putbody() 6582 ** and mime8to7() will most likely be different. 6583 ** By turning on this FFR milter_body() will try to "imitate" 6584 ** mime8to7(). 6585 ** Note: there is no (simple) way to deal with both conversions 6586 ** in a consistent manner. Moreover, as the "GiGo" principle applies, 6587 ** it's not really worth to fix it. 6588 */ 6589 6590 "_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF", 6591 #endif 6592 #if _FFR_MILTER_CHECK_REJECTIONS_TOO 6593 /* 6594 ** Also send RCPTs that are rejected by check_rcpt to a milter 6595 ** (if requested during option negotiation). 6596 */ 6597 6598 "_FFR_MILTER_CHECK_REJECTIONS_TOO", 6599 #endif 6600 #if _FFR_MILTER_ENHSC 6601 /* extract enhanced status code from milter replies for dsn= logging */ 6602 "_FFR_MILTER_ENHSC", 6603 #endif 6604 #if _FFR_MIME7TO8_OLD 6605 /* Old mime7to8 code, the new is broken for at least one example. */ 6606 "_FFR_MIME7TO8_OLD", 6607 #endif 6608 #if _FFR_MORE_MACROS 6609 /* allow more long macro names ("unprintable" characters). */ 6610 "_FFR_MORE_MACROS", 6611 #endif 6612 #if _FFR_MSG_ACCEPT 6613 /* allow to override "Message accepted for delivery" */ 6614 "_FFR_MSG_ACCEPT", 6615 #endif 6616 #if _FFR_MTA_MODE 6617 /* do not modify headers -- does NOT (yet) work */ 6618 "_FFR_MTA_MODE", 6619 #endif 6620 #if _FFR_MTA_STS 6621 # if !MAP_REGEX 6622 # ERROR "_FFR_MTA_STS requires MAP_REGEX" 6623 # endif 6624 # if !STARTTLS 6625 # ERROR "_FFR_MTA_STS requires STARTTLS" 6626 # endif 6627 # if !_FFR_TLS_ALTNAMES 6628 # ERROR "_FFR_MTA_STS requires _FFR_TLS_ALTNAMES" 6629 # endif 6630 /* MTA STS support */ 6631 "_FFR_MTA_STS", 6632 #endif /* _FFR_MTA_STS */ 6633 #if _FFR_NODELAYDSN_ON_HOLD 6634 /* Do not issue a DELAY DSN for mailers that use the hold flag. */ 6635 /* Steven Pitzl */ 6636 "_FFR_NODELAYDSN_ON_HOLD", 6637 #endif 6638 #if _FFR_NO_PIPE 6639 /* Disable PIPELINING, delay client if used. */ 6640 "_FFR_NO_PIPE", 6641 #endif 6642 #if _FFR_LDAP_SINGLEDN 6643 /* 6644 ** The LDAP database map code in Sendmail 8.12.10, when 6645 ** given the -1 switch, would match only a single DN, 6646 ** but was able to return multiple attributes for that 6647 ** DN. In Sendmail 8.13 this "bug" was corrected to 6648 ** only return if exactly one attribute matched. 6649 ** 6650 ** Unfortunately, our configuration uses the former 6651 ** behaviour. Attached is a relatively simple patch 6652 ** to 8.13.4 which adds a -2 switch (for lack of a 6653 ** better option) which returns the single dn/multiple 6654 ** attributes. 6655 ** 6656 ** Jeffrey T. Eaton, Carnegie-Mellon University 6657 */ 6658 6659 "_FFR_LDAP_SINGLEDN", 6660 #endif 6661 #if _FFR_LOG_NTRIES 6662 /* log ntries=, from Nik Clayton of FreeBSD */ 6663 "_FFR_LOG_NTRIES", 6664 #endif 6665 #if _FFR_OCC 6666 # if SM_CONF_SHM 6667 /* outgoing connection control (not yet working) */ 6668 "_FFR_OCC", 6669 # else 6670 # ERROR "_FFR_OCC requires SM_CONF_SHM" 6671 # endif 6672 #endif 6673 #if _FFR_PROXY 6674 /* "proxy" (synchronous) delivery mode */ 6675 "_FFR_PROXY", 6676 #endif 6677 #if _FFR_QF_PARANOIA 6678 /* Check to make sure key fields were read from qf */ 6679 "_FFR_QF_PARANOIA", 6680 #endif 6681 #if _FFR_QUEUE_GROUP_SORTORDER 6682 /* Allow QueueSortOrder per queue group. */ 6683 /* XXX: Still need to actually use qgrp->qg_sortorder */ 6684 "_FFR_QUEUE_GROUP_SORTORDER", 6685 #endif 6686 #if _FFR_QUEUE_MACRO 6687 /* Define {queue} macro. */ 6688 "_FFR_QUEUE_MACRO", 6689 #endif 6690 #if _FFR_QUEUE_RUN_PARANOIA 6691 /* Additional checks when doing queue runs; interval of checks */ 6692 "_FFR_QUEUE_RUN_PARANOIA", 6693 #endif 6694 #if _FFR_QUEUE_SCHED_DBG 6695 /* Debug output for the queue scheduler. */ 6696 "_FFR_QUEUE_SCHED_DBG", 6697 #endif 6698 #if _FFR_RCPTFLAGS 6699 /* dynamic mailer modifications via {rcpt_flags}*/ 6700 "_FFR_RCPTFLAGS", 6701 #endif 6702 #if _FFR_RCPTTHROTDELAY 6703 /* configurable delay for BadRcptThrottle */ 6704 "_FFR_RCPTTHROTDELAY", 6705 #endif 6706 #if _FFR_REDIRECTEMPTY 6707 /* 6708 ** envelope <> can't be sent to mailing lists, only owner- 6709 ** send spam of this type to owner- of the list 6710 ** ---- to stop spam from going to mailing lists. 6711 */ 6712 6713 "_FFR_REDIRECTEMPTY", 6714 #endif 6715 #if _FFR_REJECT_NUL_BYTE 6716 /* reject NUL bytes in body */ 6717 "_FFR_REJECT_NUL_BYTE", 6718 #endif 6719 #if _FFR_REPLY_MULTILINE 6720 /* try to gather multi-line replies for reply= logging */ 6721 "_FFR_REPLY_MULTILINE=" SM_XSTR(_FFR_REPLY_MULTILINE), 6722 #endif 6723 #if _FFR_RESET_MACRO_GLOBALS 6724 /* Allow macro 'j' to be set dynamically via rulesets. */ 6725 "_FFR_RESET_MACRO_GLOBALS", 6726 #endif 6727 #if _FFR_RHS 6728 /* Random shuffle for queue sorting. */ 6729 "_FFR_RHS", 6730 #endif 6731 #if _FFR_RUNPQG 6732 /* 6733 ** allow -qGqueue_group -qp to work, i.e., 6734 ** restrict a persistent queue runner to a queue group. 6735 */ 6736 6737 "_FFR_RUNPQG", 6738 #endif 6739 #if _FFR_SESSID 6740 /* session id (for logging): WIP, no logging yet! */ 6741 "_FFR_SESSID", 6742 #endif 6743 #if _FFR_SETANYOPT 6744 "_FFR_SETANYOPT", 6745 #endif 6746 #if _FFR_SETDEBUG_MAP 6747 "_FFR_SETDEBUG_MAP", 6748 #endif 6749 #if _FFR_SETOPT_MAP 6750 "_FFR_SETOPT_MAP", 6751 #endif 6752 #if _FFR_SHM_STATUS 6753 /* Donated code (unused). */ 6754 "_FFR_SHM_STATUS", 6755 #endif 6756 #if _FFR_SKIP_DOMAINS 6757 /* process every N'th domain instead of every N'th message */ 6758 "_FFR_SKIP_DOMAINS", 6759 #endif 6760 #if _FFR_SLEEP_USE_SELECT 6761 /* Use select(2) in libsm/clock.c to emulate sleep(2) */ 6762 "_FFR_SLEEP_USE_SELECT", 6763 #endif 6764 #if _FFR_SM_LDAP_DBG 6765 # if LDAPMAP && defined(LBER_OPT_LOG_PRINT_FN) 6766 /* LDAP debugging */ 6767 "_FFR_SM_LDAP_DBG", 6768 # else 6769 # ERROR "_FFR_SM_LDAP_DBG requires LDAPMAP and LBER_OPT_LOG_PRINT_FN" 6770 # endif 6771 #endif 6772 #if _FFR_SPT_ALIGN 6773 /* 6774 ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64 6775 ** bit alignment, so unless each piece of argv and envp is a multiple 6776 ** of 8 bytes (including terminating NULL), initsetproctitle() won't 6777 ** use any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE 6778 ** if you use this FFR. 6779 */ 6780 6781 /* Chris Adams of HiWAAY Informations Services */ 6782 "_FFR_SPT_ALIGN", 6783 #endif 6784 #if _FFR_SS_PER_DAEMON 6785 /* SuperSafe per DaemonPortOptions: 'T' (better letter?) */ 6786 "_FFR_SS_PER_DAEMON", 6787 #endif 6788 #if _FFR_TESTS 6789 /* enable some test code */ 6790 "_FFR_TESTS", 6791 #endif 6792 #if _FFR_TIMERS 6793 /* Donated code (unused). */ 6794 "_FFR_TIMERS", 6795 #endif 6796 #if _FFR_TLS_ALTNAMES 6797 /* store subjectAltNames in class {cert_altnames} */ 6798 "_FFR_TLS_ALTNAMES", 6799 #endif 6800 #if _FFR_TLSFB2CLEAR 6801 /* set default for TLSFallbacktoClear to true */ 6802 "_FFR_TLSFB2CLEAR", 6803 #endif 6804 #if _FFR_TLS_USE_CERTIFICATE_CHAIN_FILE 6805 /* 6806 ** Use SSL_CTX_use_certificate_chain_file() 6807 ** instead of SSL_CTX_use_certificate_file() 6808 */ 6809 6810 "_FFR_TLS_USE_CERTIFICATE_CHAIN_FILE", 6811 #endif 6812 #if _FFR_TRUSTED_QF 6813 /* 6814 ** If we don't own the file mark it as unsafe. 6815 ** However, allow TrustedUser to own it as well 6816 ** in case TrustedUser manipulates the queue. 6817 */ 6818 6819 "_FFR_TRUSTED_QF", 6820 #endif 6821 #if _FFR_USE_GETPWNAM_ERRNO 6822 /* 6823 ** See libsm/mbdb.c: only enable this on OSs 6824 ** that implement the correct (POSIX) semantics. 6825 ** This will need to become an OS-specific #if enabled 6826 ** in one of the headers files under include/sm/os/ . 6827 */ 6828 6829 "_FFR_USE_GETPWNAM_ERRNO", 6830 #endif 6831 #if _FFR_VRFY_TRUSTED_FIRST 6832 /* 6833 ** Sets X509_V_FLAG_TRUSTED_FIRST if -d88;.101 is used. 6834 ** X509_VERIFY_PARAM_set_flags(3) 6835 ** When X509_V_FLAG_TRUSTED_FIRST is set, construction of the 6836 ** certificate chain in X509_verify_cert(3) will search the trust 6837 ** store for issuer certificates before searching the provided 6838 ** untrusted certificates. Local issuer certificates are often more 6839 ** likely to satisfy local security requirements and lead to a locally 6840 ** trusted root. This is especially important when some certificates 6841 ** in the trust store have explicit trust settings (see "TRUST 6842 ** SETTINGS" in x509(1)). 6843 ** As of OpenSSL 1.1.0 this option is on by default. 6844 */ 6845 6846 # if defined(X509_V_FLAG_TRUSTED_FIRST) 6847 "_FFR_VRFY_TRUSTED_FIRST", 6848 # else 6849 # ERROR "_FFR_VRFY_TRUSTED_FIRST set but X509_V_FLAG_TRUSTED_FIRST not defined" 6850 # endif 6851 #endif 6852 6853 #if _FFR_USE_SEM_LOCKING 6854 /* Use semaphore locking */ 6855 "_FFR_USE_SEM_LOCKING", 6856 #endif 6857 #if _FFR_USE_SETLOGIN 6858 /* Use setlogin() */ 6859 /* Peter Philipp */ 6860 "_FFR_USE_SETLOGIN", 6861 #endif 6862 #if _FFR_XCNCT 6863 /* X-Connect support */ 6864 "_FFR_XCNCT", 6865 #endif 6866 #if _FFR_LOGASIS 6867 "_FFR_LOGASIS=" SM_XSTR(_FFR_LOGASIS), 6868 #endif 6869 #if _FFR_NOREFLECT 6870 /* Don't forget to update docs for "goaway" to include this */ 6871 "_FFR_NOREFLECT", 6872 #endif 6873 #if _FFR_AUTH_PASSING 6874 /* Set the default AUTH= if the sender didn't */ 6875 "_FFR_AUTH_PASSING", 6876 #endif 6877 #if _FFR_HOST_SORT_REVERSE 6878 /* Reverse sort for host for recipient sorting pre-envelope-split */ 6879 "_FFR_HOST_SORT_REVERSE", 6880 #endif 6881 #if _FFR_MSP_PARANOIA 6882 /* 6883 ** Forbid queue groups, multiple queues, and dangerous queue permissions 6884 ** when operating as an MSP 6885 */ 6886 6887 "_FFR_MSP_PARANOIA", 6888 #endif 6889 #if _FFR_ANY_FREE_FS 6890 /* 6891 ** Check whether there is at least one fs with enough space 6892 ** (may not work, needs review) 6893 */ 6894 6895 "_FFR_ANY_FREE_FS", 6896 #endif 6897 #if _FFR_MIME_CR_OK 6898 /* 6899 ** Strip trailing CR in MIME boundaries 6900 ** (may not work, needs review) 6901 */ 6902 6903 "_FFR_MIME_CR_OK", 6904 #endif 6905 NULL 6906 }; 6907