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