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