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