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