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