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