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