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