1 /* 2 * Copyright (c) 1998-2013 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.1182 2013/04/05 17:39:09 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)) >= 0) 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)) >= 0) 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)) >= 0) 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 # ifndef SM_IPNODEBYNAME_FLAGS 4298 /* For IPv4-mapped addresses, use: AI_DEFAULT|AI_ALL */ 4299 # define SM_IPNODEBYNAME_FLAGS AI_ADDRCONFIG 4300 # endif /* SM_IPNODEBYNAME_FLAGS */ 4301 4302 int flags = SM_IPNODEBYNAME_FLAGS; 4303 int err; 4304 # endif /* NETINET6 */ 4305 char *maptype[MAXMAPSTACK]; 4306 short mapreturn[MAXMAPACTIONS]; 4307 char hbuf[MAXNAME]; 4308 4309 if (tTd(61, 10)) 4310 sm_dprintf("sm_gethostbyname(%s, %d)... ", name, family); 4311 4312 # if NETINET6 4313 # if ADDRCONFIG_IS_BROKEN 4314 flags &= ~AI_ADDRCONFIG; 4315 # endif /* ADDRCONFIG_IS_BROKEN */ 4316 h = sm_getipnodebyname(name, family, flags, &err); 4317 SM_SET_H_ERRNO(err); 4318 # else /* NETINET6 */ 4319 h = gethostbyname(name); 4320 # endif /* NETINET6 */ 4321 4322 save_errno = errno; 4323 if (h == NULL) 4324 { 4325 if (tTd(61, 10)) 4326 sm_dprintf("failure\n"); 4327 4328 nmaps = switch_map_find("hosts", maptype, mapreturn); 4329 while (--nmaps >= 0) 4330 { 4331 if (strcmp(maptype[nmaps], "nis") == 0 || 4332 strcmp(maptype[nmaps], "files") == 0) 4333 break; 4334 } 4335 4336 if (nmaps >= 0) 4337 { 4338 /* try short name */ 4339 if (strlen(name) > sizeof(hbuf) - 1) 4340 { 4341 errno = save_errno; 4342 return NULL; 4343 } 4344 (void) sm_strlcpy(hbuf, name, sizeof(hbuf)); 4345 (void) shorten_hostname(hbuf); 4346 4347 /* if it hasn't been shortened, there's no point */ 4348 if (strcmp(hbuf, name) != 0) 4349 { 4350 if (tTd(61, 10)) 4351 sm_dprintf("sm_gethostbyname(%s, %d)... ", 4352 hbuf, family); 4353 4354 # if NETINET6 4355 h = sm_getipnodebyname(hbuf, family, flags, &err); 4356 SM_SET_H_ERRNO(err); 4357 save_errno = errno; 4358 # else /* NETINET6 */ 4359 h = gethostbyname(hbuf); 4360 save_errno = errno; 4361 # endif /* NETINET6 */ 4362 } 4363 } 4364 } 4365 #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ 4366 if (tTd(61, 10)) 4367 { 4368 if (h == NULL) 4369 sm_dprintf("failure\n"); 4370 else 4371 { 4372 sm_dprintf("%s\n", h->h_name); 4373 if (tTd(61, 11)) 4374 { 4375 #if NETINET6 4376 struct in6_addr ia6; 4377 char buf6[INET6_ADDRSTRLEN]; 4378 #else /* NETINET6 */ 4379 struct in_addr ia; 4380 #endif /* NETINET6 */ 4381 size_t i; 4382 4383 if (h->h_aliases != NULL) 4384 for (i = 0; h->h_aliases[i] != NULL; 4385 i++) 4386 sm_dprintf("\talias: %s\n", 4387 h->h_aliases[i]); 4388 for (i = 0; h->h_addr_list[i] != NULL; i++) 4389 { 4390 char *addr; 4391 4392 #if NETINET6 4393 memmove(&ia6, h->h_addr_list[i], 4394 IN6ADDRSZ); 4395 addr = anynet_ntop(&ia6, 4396 buf6, sizeof(buf6)); 4397 #else /* NETINET6 */ 4398 memmove(&ia, h->h_addr_list[i], 4399 INADDRSZ); 4400 addr = (char *) inet_ntoa(ia); 4401 #endif /* NETINET6 */ 4402 if (addr != NULL) 4403 sm_dprintf("\taddr: %s\n", addr); 4404 } 4405 } 4406 } 4407 } 4408 errno = save_errno; 4409 return h; 4410 } 4411 4412 struct hostent * 4413 sm_gethostbyaddr(addr, len, type) 4414 char *addr; 4415 int len; 4416 int type; 4417 { 4418 struct hostent *hp; 4419 4420 #if NETINET6 4421 if (type == AF_INET6 && 4422 IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *) addr)) 4423 { 4424 /* Avoid reverse lookup for IPv6 unspecified address */ 4425 SM_SET_H_ERRNO(HOST_NOT_FOUND); 4426 return NULL; 4427 } 4428 #endif /* NETINET6 */ 4429 4430 #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) 4431 # if SOLARIS == 20300 || SOLARIS == 203 4432 { 4433 static struct hostent he; 4434 static char buf[1000]; 4435 extern struct hostent *_switch_gethostbyaddr_r(); 4436 4437 hp = _switch_gethostbyaddr_r(addr, len, type, &he, 4438 buf, sizeof(buf), &h_errno); 4439 } 4440 # else /* SOLARIS == 20300 || SOLARIS == 203 */ 4441 { 4442 extern struct hostent *__switch_gethostbyaddr(); 4443 4444 hp = __switch_gethostbyaddr(addr, len, type); 4445 } 4446 # endif /* SOLARIS == 20300 || SOLARIS == 203 */ 4447 #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ 4448 # if NETINET6 4449 { 4450 int err; 4451 4452 hp = sm_getipnodebyaddr(addr, len, type, &err); 4453 SM_SET_H_ERRNO(err); 4454 } 4455 # else /* NETINET6 */ 4456 hp = gethostbyaddr(addr, len, type); 4457 # endif /* NETINET6 */ 4458 #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ 4459 return hp; 4460 } 4461 /* 4462 ** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid 4463 */ 4464 4465 struct passwd * 4466 sm_getpwnam(user) 4467 char *user; 4468 { 4469 #ifdef _AIX4 4470 extern struct passwd *_getpwnam_shadow(const char *, const int); 4471 4472 return _getpwnam_shadow(user, 0); 4473 #else /* _AIX4 */ 4474 return getpwnam(user); 4475 #endif /* _AIX4 */ 4476 } 4477 4478 struct passwd * 4479 sm_getpwuid(uid) 4480 UID_T uid; 4481 { 4482 #if defined(_AIX4) && 0 4483 extern struct passwd *_getpwuid_shadow(const int, const int); 4484 4485 return _getpwuid_shadow(uid,0); 4486 #else /* defined(_AIX4) && 0 */ 4487 return getpwuid(uid); 4488 #endif /* defined(_AIX4) && 0 */ 4489 } 4490 /* 4491 ** SECUREWARE_SETUP_SECURE -- Convex SecureWare setup 4492 ** 4493 ** Set up the trusted computing environment for C2 level security 4494 ** under SecureWare. 4495 ** 4496 ** Parameters: 4497 ** uid -- uid of the user to initialize in the TCB 4498 ** 4499 ** Returns: 4500 ** none 4501 ** 4502 ** Side Effects: 4503 ** Initialized the user in the trusted computing base 4504 */ 4505 4506 #if SECUREWARE 4507 4508 # include <sys/security.h> 4509 # include <prot.h> 4510 4511 void 4512 secureware_setup_secure(uid) 4513 UID_T uid; 4514 { 4515 int rc; 4516 4517 if (getluid() != -1) 4518 return; 4519 4520 if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN) 4521 { 4522 switch (rc) 4523 { 4524 case SSI_NO_PRPW_ENTRY: 4525 syserr("No protected passwd entry, uid = %d", 4526 (int) uid); 4527 break; 4528 4529 case SSI_LOCKED: 4530 syserr("Account has been disabled, uid = %d", 4531 (int) uid); 4532 break; 4533 4534 case SSI_RETIRED: 4535 syserr("Account has been retired, uid = %d", 4536 (int) uid); 4537 break; 4538 4539 case SSI_BAD_SET_LUID: 4540 syserr("Could not set LUID, uid = %d", (int) uid); 4541 break; 4542 4543 case SSI_BAD_SET_PRIVS: 4544 syserr("Could not set kernel privs, uid = %d", 4545 (int) uid); 4546 4547 default: 4548 syserr("Unknown return code (%d) from set_secure_info(%d)", 4549 rc, (int) uid); 4550 break; 4551 } 4552 finis(false, true, EX_NOPERM); 4553 } 4554 } 4555 #endif /* SECUREWARE */ 4556 /* 4557 ** ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address 4558 ** 4559 ** Add hostnames to class 'w' based on the IP address read from 4560 ** the network interface. 4561 ** 4562 ** Parameters: 4563 ** sa -- a pointer to a SOCKADDR containing the address 4564 ** 4565 ** Returns: 4566 ** 0 if successful, -1 if host lookup fails. 4567 */ 4568 4569 static int 4570 add_hostnames(sa) 4571 SOCKADDR *sa; 4572 { 4573 struct hostent *hp; 4574 char **ha; 4575 char hnb[MAXHOSTNAMELEN]; 4576 4577 /* lookup name with IP address */ 4578 switch (sa->sa.sa_family) 4579 { 4580 #if NETINET 4581 case AF_INET: 4582 hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr, 4583 sizeof(sa->sin.sin_addr), 4584 sa->sa.sa_family); 4585 break; 4586 #endif /* NETINET */ 4587 4588 #if NETINET6 4589 case AF_INET6: 4590 hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr, 4591 sizeof(sa->sin6.sin6_addr), 4592 sa->sa.sa_family); 4593 break; 4594 #endif /* NETINET6 */ 4595 4596 default: 4597 /* Give warning about unsupported family */ 4598 if (LogLevel > 3) 4599 sm_syslog(LOG_WARNING, NOQID, 4600 "Unsupported address family %d: %.100s", 4601 sa->sa.sa_family, anynet_ntoa(sa)); 4602 return -1; 4603 } 4604 4605 if (hp == NULL) 4606 { 4607 int save_errno = errno; 4608 4609 if (LogLevel > 3 && 4610 #if NETINET && defined(IN_LINKLOCAL) 4611 !(sa->sa.sa_family == AF_INET && 4612 IN_LINKLOCAL(ntohl(sa->sin.sin_addr.s_addr))) && 4613 #endif /* NETINET && defined(IN_LINKLOCAL) */ 4614 #if NETINET6 4615 !(sa->sa.sa_family == AF_INET6 && 4616 IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) && 4617 #endif /* NETINET6 */ 4618 true) 4619 sm_syslog(LOG_WARNING, NOQID, 4620 "gethostbyaddr(%.100s) failed: %d", 4621 anynet_ntoa(sa), 4622 #if NAMED_BIND 4623 h_errno 4624 #else /* NAMED_BIND */ 4625 -1 4626 #endif /* NAMED_BIND */ 4627 ); 4628 errno = save_errno; 4629 return -1; 4630 } 4631 4632 /* save its cname */ 4633 if (!wordinclass((char *) hp->h_name, 'w')) 4634 { 4635 setclass('w', (char *) hp->h_name); 4636 if (tTd(0, 4)) 4637 sm_dprintf("\ta.k.a.: %s\n", hp->h_name); 4638 4639 if (sm_snprintf(hnb, sizeof(hnb), "[%s]", hp->h_name) < 4640 sizeof(hnb) 4641 && !wordinclass((char *) hnb, 'w')) 4642 setclass('w', hnb); 4643 } 4644 else 4645 { 4646 if (tTd(0, 43)) 4647 sm_dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name); 4648 } 4649 4650 /* save all it aliases name */ 4651 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 4652 { 4653 if (!wordinclass(*ha, 'w')) 4654 { 4655 setclass('w', *ha); 4656 if (tTd(0, 4)) 4657 sm_dprintf("\ta.k.a.: %s\n", *ha); 4658 if (sm_snprintf(hnb, sizeof(hnb), 4659 "[%s]", *ha) < sizeof(hnb) && 4660 !wordinclass((char *) hnb, 'w')) 4661 setclass('w', hnb); 4662 } 4663 else 4664 { 4665 if (tTd(0, 43)) 4666 sm_dprintf("\ta.k.a.: %s (already in $=w)\n", 4667 *ha); 4668 } 4669 } 4670 #if NETINET6 4671 freehostent(hp); 4672 #endif /* NETINET6 */ 4673 return 0; 4674 } 4675 /* 4676 ** LOAD_IF_NAMES -- load interface-specific names into $=w 4677 ** 4678 ** Parameters: 4679 ** none. 4680 ** 4681 ** Returns: 4682 ** none. 4683 ** 4684 ** Side Effects: 4685 ** Loads $=w with the names of all the interfaces. 4686 */ 4687 4688 #if !NETINET 4689 # define SIOCGIFCONF_IS_BROKEN 1 /* XXX */ 4690 #endif /* !NETINET */ 4691 4692 #if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN 4693 struct rtentry; 4694 struct mbuf; 4695 # ifndef SUNOS403 4696 # include <sm/time.h> 4697 # endif /* ! SUNOS403 */ 4698 # if (_AIX4 >= 40300) && !defined(_NET_IF_H) 4699 # undef __P 4700 # endif /* (_AIX4 >= 40300) && !defined(_NET_IF_H) */ 4701 # include <net/if.h> 4702 #endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ 4703 4704 void 4705 load_if_names() 4706 { 4707 # if NETINET6 && defined(SIOCGLIFCONF) 4708 # ifdef __hpux 4709 4710 /* 4711 ** Unfortunately, HP has changed all of the structures, 4712 ** making life difficult for implementors. 4713 */ 4714 4715 # define lifconf if_laddrconf 4716 # define lifc_len iflc_len 4717 # define lifc_buf iflc_buf 4718 # define lifreq if_laddrreq 4719 # define lifr_addr iflr_addr 4720 # define lifr_name iflr_name 4721 # define lifr_flags iflr_flags 4722 # define ss_family sa_family 4723 # undef SIOCGLIFNUM 4724 # endif /* __hpux */ 4725 4726 int s; 4727 int i; 4728 size_t len; 4729 int numifs; 4730 char *buf; 4731 struct lifconf lifc; 4732 # ifdef SIOCGLIFNUM 4733 struct lifnum lifn; 4734 # endif /* SIOCGLIFNUM */ 4735 4736 s = socket(InetMode, SOCK_DGRAM, 0); 4737 if (s == -1) 4738 return; 4739 4740 /* get the list of known IP address from the kernel */ 4741 # ifdef __hpux 4742 i = ioctl(s, SIOCGIFNUM, (char *) &numifs); 4743 # endif /* __hpux */ 4744 # ifdef SIOCGLIFNUM 4745 lifn.lifn_family = AF_UNSPEC; 4746 lifn.lifn_flags = 0; 4747 i = ioctl(s, SIOCGLIFNUM, (char *)&lifn); 4748 numifs = lifn.lifn_count; 4749 # endif /* SIOCGLIFNUM */ 4750 4751 # if defined(__hpux) || defined(SIOCGLIFNUM) 4752 if (i < 0) 4753 { 4754 /* can't get number of interfaces -- fall back */ 4755 if (tTd(0, 4)) 4756 sm_dprintf("SIOCGLIFNUM failed: %s\n", 4757 sm_errstring(errno)); 4758 numifs = -1; 4759 } 4760 else if (tTd(0, 42)) 4761 sm_dprintf("system has %d interfaces\n", numifs); 4762 if (numifs < 0) 4763 # endif /* defined(__hpux) || defined(SIOCGLIFNUM) */ 4764 numifs = MAXINTERFACES; 4765 4766 if (numifs <= 0) 4767 { 4768 (void) close(s); 4769 return; 4770 } 4771 4772 len = lifc.lifc_len = numifs * sizeof(struct lifreq); 4773 buf = lifc.lifc_buf = xalloc(lifc.lifc_len); 4774 # ifndef __hpux 4775 lifc.lifc_family = AF_UNSPEC; 4776 lifc.lifc_flags = 0; 4777 # endif /* ! __hpux */ 4778 if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) 4779 { 4780 if (tTd(0, 4)) 4781 sm_dprintf("SIOCGLIFCONF failed: %s\n", 4782 sm_errstring(errno)); 4783 (void) close(s); 4784 sm_free(buf); 4785 return; 4786 } 4787 4788 /* scan the list of IP address */ 4789 if (tTd(0, 40)) 4790 sm_dprintf("scanning for interface specific names, lifc_len=%ld\n", 4791 (long) len); 4792 4793 for (i = 0; i < len && i >= 0; ) 4794 { 4795 int flags; 4796 struct lifreq *ifr = (struct lifreq *)&buf[i]; 4797 SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr; 4798 int af = ifr->lifr_addr.ss_family; 4799 char *addr; 4800 char *name; 4801 struct in6_addr ia6; 4802 struct in_addr ia; 4803 # ifdef SIOCGLIFFLAGS 4804 struct lifreq ifrf; 4805 # endif /* SIOCGLIFFLAGS */ 4806 char ip_addr[256]; 4807 char buf6[INET6_ADDRSTRLEN]; 4808 4809 /* 4810 ** We must close and recreate the socket each time 4811 ** since we don't know what type of socket it is now 4812 ** (each status function may change it). 4813 */ 4814 4815 (void) close(s); 4816 4817 s = socket(af, SOCK_DGRAM, 0); 4818 if (s == -1) 4819 { 4820 sm_free(buf); /* XXX */ 4821 return; 4822 } 4823 4824 /* 4825 ** If we don't have a complete ifr structure, 4826 ** don't try to use it. 4827 */ 4828 4829 if ((len - i) < sizeof(*ifr)) 4830 break; 4831 4832 # ifdef BSD4_4_SOCKADDR 4833 if (sa->sa.sa_len > sizeof(ifr->lifr_addr)) 4834 i += sizeof(ifr->lifr_name) + sa->sa.sa_len; 4835 else 4836 # endif /* BSD4_4_SOCKADDR */ 4837 # ifdef DEC 4838 /* fix for IPv6 size differences */ 4839 i += sizeof(ifr->ifr_name) + 4840 max(sizeof(ifr->ifr_addr), ifr->ifr_addr.sa_len); 4841 # else /* DEC */ 4842 i += sizeof(*ifr); 4843 # endif /* DEC */ 4844 4845 if (tTd(0, 20)) 4846 sm_dprintf("%s\n", anynet_ntoa(sa)); 4847 4848 if (af != AF_INET && af != AF_INET6) 4849 continue; 4850 4851 # ifdef SIOCGLIFFLAGS 4852 memset(&ifrf, '\0', sizeof(struct lifreq)); 4853 (void) sm_strlcpy(ifrf.lifr_name, ifr->lifr_name, 4854 sizeof(ifrf.lifr_name)); 4855 if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0) 4856 { 4857 if (tTd(0, 4)) 4858 sm_dprintf("SIOCGLIFFLAGS failed: %s\n", 4859 sm_errstring(errno)); 4860 continue; 4861 } 4862 4863 name = ifr->lifr_name; 4864 flags = ifrf.lifr_flags; 4865 4866 if (tTd(0, 41)) 4867 sm_dprintf("\tflags: %lx\n", (unsigned long) flags); 4868 4869 if (!bitset(IFF_UP, flags)) 4870 continue; 4871 # endif /* SIOCGLIFFLAGS */ 4872 4873 ip_addr[0] = '\0'; 4874 4875 /* extract IP address from the list*/ 4876 switch (af) 4877 { 4878 case AF_INET6: 4879 SETV6LOOPBACKADDRFOUND(*sa); 4880 # ifdef __KAME__ 4881 /* convert into proper scoped address */ 4882 if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || 4883 IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && 4884 sa->sin6.sin6_scope_id == 0) 4885 { 4886 struct in6_addr *ia6p; 4887 4888 ia6p = &sa->sin6.sin6_addr; 4889 sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | 4890 ((unsigned int)ia6p->s6_addr[2] << 8)); 4891 ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; 4892 } 4893 # endif /* __KAME__ */ 4894 ia6 = sa->sin6.sin6_addr; 4895 if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) 4896 { 4897 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 4898 message("WARNING: interface %s is UP with %s address", 4899 name, addr == NULL ? "(NULL)" : addr); 4900 continue; 4901 } 4902 4903 /* save IP address in text from */ 4904 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 4905 if (addr != NULL) 4906 (void) sm_snprintf(ip_addr, sizeof(ip_addr), 4907 "[%.*s]", 4908 (int) sizeof(ip_addr) - 3, 4909 addr); 4910 break; 4911 4912 case AF_INET: 4913 ia = sa->sin.sin_addr; 4914 if (ia.s_addr == INADDR_ANY || 4915 ia.s_addr == INADDR_NONE) 4916 { 4917 message("WARNING: interface %s is UP with %s address", 4918 name, inet_ntoa(ia)); 4919 continue; 4920 } 4921 4922 /* save IP address in text from */ 4923 (void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]", 4924 (int) sizeof(ip_addr) - 3, inet_ntoa(ia)); 4925 break; 4926 } 4927 4928 if (*ip_addr == '\0') 4929 continue; 4930 4931 if (!wordinclass(ip_addr, 'w')) 4932 { 4933 setclass('w', ip_addr); 4934 if (tTd(0, 4)) 4935 sm_dprintf("\ta.k.a.: %s\n", ip_addr); 4936 } 4937 4938 # ifdef SIOCGLIFFLAGS 4939 /* skip "loopback" interface "lo" */ 4940 if (DontProbeInterfaces == DPI_SKIPLOOPBACK && 4941 bitset(IFF_LOOPBACK, flags)) 4942 continue; 4943 # endif /* SIOCGLIFFLAGS */ 4944 (void) add_hostnames(sa); 4945 } 4946 sm_free(buf); /* XXX */ 4947 (void) close(s); 4948 # else /* NETINET6 && defined(SIOCGLIFCONF) */ 4949 # if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN 4950 int s; 4951 int i; 4952 struct ifconf ifc; 4953 int numifs; 4954 4955 s = socket(AF_INET, SOCK_DGRAM, 0); 4956 if (s == -1) 4957 return; 4958 4959 /* get the list of known IP address from the kernel */ 4960 # if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN 4961 if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) 4962 { 4963 /* can't get number of interfaces -- fall back */ 4964 if (tTd(0, 4)) 4965 sm_dprintf("SIOCGIFNUM failed: %s\n", 4966 sm_errstring(errno)); 4967 numifs = -1; 4968 } 4969 else if (tTd(0, 42)) 4970 sm_dprintf("system has %d interfaces\n", numifs); 4971 if (numifs < 0) 4972 # endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */ 4973 numifs = MAXINTERFACES; 4974 4975 if (numifs <= 0) 4976 { 4977 (void) close(s); 4978 return; 4979 } 4980 ifc.ifc_len = numifs * sizeof(struct ifreq); 4981 ifc.ifc_buf = xalloc(ifc.ifc_len); 4982 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 4983 { 4984 if (tTd(0, 4)) 4985 sm_dprintf("SIOCGIFCONF failed: %s\n", 4986 sm_errstring(errno)); 4987 (void) close(s); 4988 return; 4989 } 4990 4991 /* scan the list of IP address */ 4992 if (tTd(0, 40)) 4993 sm_dprintf("scanning for interface specific names, ifc_len=%d\n", 4994 ifc.ifc_len); 4995 4996 for (i = 0; i < ifc.ifc_len && i >= 0; ) 4997 { 4998 int af; 4999 struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i]; 5000 SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr; 5001 # if NETINET6 5002 char *addr; 5003 struct in6_addr ia6; 5004 # endif /* NETINET6 */ 5005 struct in_addr ia; 5006 # ifdef SIOCGIFFLAGS 5007 struct ifreq ifrf; 5008 # endif /* SIOCGIFFLAGS */ 5009 char ip_addr[256]; 5010 # if NETINET6 5011 char buf6[INET6_ADDRSTRLEN]; 5012 # endif /* NETINET6 */ 5013 5014 /* 5015 ** If we don't have a complete ifr structure, 5016 ** don't try to use it. 5017 */ 5018 5019 if ((ifc.ifc_len - i) < sizeof(*ifr)) 5020 break; 5021 5022 # ifdef BSD4_4_SOCKADDR 5023 if (sa->sa.sa_len > sizeof(ifr->ifr_addr)) 5024 i += sizeof(ifr->ifr_name) + sa->sa.sa_len; 5025 else 5026 # endif /* BSD4_4_SOCKADDR */ 5027 i += sizeof(*ifr); 5028 5029 if (tTd(0, 20)) 5030 sm_dprintf("%s\n", anynet_ntoa(sa)); 5031 5032 af = ifr->ifr_addr.sa_family; 5033 if (af != AF_INET 5034 # if NETINET6 5035 && af != AF_INET6 5036 # endif /* NETINET6 */ 5037 ) 5038 continue; 5039 5040 # ifdef SIOCGIFFLAGS 5041 memset(&ifrf, '\0', sizeof(struct ifreq)); 5042 (void) sm_strlcpy(ifrf.ifr_name, ifr->ifr_name, 5043 sizeof(ifrf.ifr_name)); 5044 (void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf); 5045 if (tTd(0, 41)) 5046 sm_dprintf("\tflags: %lx\n", 5047 (unsigned long) ifrf.ifr_flags); 5048 # define IFRFREF ifrf 5049 # else /* SIOCGIFFLAGS */ 5050 # define IFRFREF (*ifr) 5051 # endif /* SIOCGIFFLAGS */ 5052 5053 if (!bitset(IFF_UP, IFRFREF.ifr_flags)) 5054 continue; 5055 5056 ip_addr[0] = '\0'; 5057 5058 /* extract IP address from the list*/ 5059 switch (af) 5060 { 5061 case AF_INET: 5062 ia = sa->sin.sin_addr; 5063 if (ia.s_addr == INADDR_ANY || 5064 ia.s_addr == INADDR_NONE) 5065 { 5066 message("WARNING: interface %s is UP with %s address", 5067 ifr->ifr_name, inet_ntoa(ia)); 5068 continue; 5069 } 5070 5071 /* save IP address in text from */ 5072 (void) sm_snprintf(ip_addr, sizeof(ip_addr), "[%.*s]", 5073 (int) sizeof(ip_addr) - 3, 5074 inet_ntoa(ia)); 5075 break; 5076 5077 # if NETINET6 5078 case AF_INET6: 5079 SETV6LOOPBACKADDRFOUND(*sa); 5080 # ifdef __KAME__ 5081 /* convert into proper scoped address */ 5082 if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || 5083 IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && 5084 sa->sin6.sin6_scope_id == 0) 5085 { 5086 struct in6_addr *ia6p; 5087 5088 ia6p = &sa->sin6.sin6_addr; 5089 sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | 5090 ((unsigned int)ia6p->s6_addr[2] << 8)); 5091 ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; 5092 } 5093 # endif /* __KAME__ */ 5094 ia6 = sa->sin6.sin6_addr; 5095 if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) 5096 { 5097 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 5098 message("WARNING: interface %s is UP with %s address", 5099 ifr->ifr_name, 5100 addr == NULL ? "(NULL)" : addr); 5101 continue; 5102 } 5103 5104 /* save IP address in text from */ 5105 addr = anynet_ntop(&ia6, buf6, sizeof(buf6)); 5106 if (addr != NULL) 5107 (void) sm_snprintf(ip_addr, sizeof(ip_addr), 5108 "[%.*s]", 5109 (int) sizeof(ip_addr) - 3, 5110 addr); 5111 break; 5112 5113 # endif /* NETINET6 */ 5114 } 5115 5116 if (ip_addr[0] == '\0') 5117 continue; 5118 5119 if (!wordinclass(ip_addr, 'w')) 5120 { 5121 setclass('w', ip_addr); 5122 if (tTd(0, 4)) 5123 sm_dprintf("\ta.k.a.: %s\n", ip_addr); 5124 } 5125 5126 /* skip "loopback" interface "lo" */ 5127 if (DontProbeInterfaces == DPI_SKIPLOOPBACK && 5128 bitset(IFF_LOOPBACK, IFRFREF.ifr_flags)) 5129 continue; 5130 5131 (void) add_hostnames(sa); 5132 } 5133 sm_free(ifc.ifc_buf); /* XXX */ 5134 (void) close(s); 5135 # undef IFRFREF 5136 # endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ 5137 # endif /* NETINET6 && defined(SIOCGLIFCONF) */ 5138 } 5139 /* 5140 ** ISLOOPBACK -- is socket address in the loopback net? 5141 ** 5142 ** Parameters: 5143 ** sa -- socket address. 5144 ** 5145 ** Returns: 5146 ** true -- is socket address in the loopback net? 5147 ** false -- otherwise 5148 ** 5149 */ 5150 5151 bool 5152 isloopback(sa) 5153 SOCKADDR sa; 5154 { 5155 #if NETINET6 5156 if (IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr)) 5157 return true; 5158 #else /* NETINET6 */ 5159 /* XXX how to correctly extract IN_LOOPBACKNET part? */ 5160 if (((ntohl(sa.sin.sin_addr.s_addr) & IN_CLASSA_NET) 5161 >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 5162 return true; 5163 #endif /* NETINET6 */ 5164 return false; 5165 } 5166 /* 5167 ** GET_NUM_PROCS_ONLINE -- return the number of processors currently online 5168 ** 5169 ** Parameters: 5170 ** none. 5171 ** 5172 ** Returns: 5173 ** The number of processors online. 5174 */ 5175 5176 static int 5177 get_num_procs_online() 5178 { 5179 int nproc = 0; 5180 5181 #ifdef USESYSCTL 5182 # if defined(CTL_HW) && defined(HW_NCPU) 5183 size_t sz; 5184 int mib[2]; 5185 5186 mib[0] = CTL_HW; 5187 mib[1] = HW_NCPU; 5188 sz = (size_t) sizeof(nproc); 5189 (void) sysctl(mib, 2, &nproc, &sz, NULL, 0); 5190 # endif /* defined(CTL_HW) && defined(HW_NCPU) */ 5191 #else /* USESYSCTL */ 5192 # ifdef _SC_NPROCESSORS_ONLN 5193 nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); 5194 # else /* _SC_NPROCESSORS_ONLN */ 5195 # ifdef __hpux 5196 # include <sys/pstat.h> 5197 struct pst_dynamic psd; 5198 5199 if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) 5200 nproc = psd.psd_proc_cnt; 5201 # endif /* __hpux */ 5202 # endif /* _SC_NPROCESSORS_ONLN */ 5203 #endif /* USESYSCTL */ 5204 5205 if (nproc <= 0) 5206 nproc = 1; 5207 return nproc; 5208 } 5209 /* 5210 ** SM_CLOSEFROM -- close file descriptors 5211 ** 5212 ** Parameters: 5213 ** lowest -- first fd to close 5214 ** highest -- last fd + 1 to close 5215 ** 5216 ** Returns: 5217 ** none 5218 */ 5219 5220 void 5221 sm_closefrom(lowest, highest) 5222 int lowest, highest; 5223 { 5224 #if HASCLOSEFROM 5225 closefrom(lowest); 5226 #else /* HASCLOSEFROM */ 5227 int i; 5228 5229 for (i = lowest; i < highest; i++) 5230 (void) close(i); 5231 #endif /* HASCLOSEFROM */ 5232 } 5233 #if HASFDWALK 5234 /* 5235 ** CLOSEFD_WALK -- walk fd's arranging to close them 5236 ** Callback for fdwalk() 5237 ** 5238 ** Parameters: 5239 ** lowest -- first fd to arrange to be closed 5240 ** fd -- fd to arrange to be closed 5241 ** 5242 ** Returns: 5243 ** zero 5244 */ 5245 5246 static int 5247 closefd_walk(lowest, fd) 5248 void *lowest; 5249 int fd; 5250 { 5251 if (fd >= *(int *)lowest) 5252 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 5253 return 0; 5254 } 5255 #endif /* HASFDWALK */ 5256 /* 5257 ** SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed 5258 ** 5259 ** Parameters: 5260 ** lowest -- first fd to arrange to be closed 5261 ** highest -- last fd + 1 to arrange to be closed 5262 ** 5263 ** Returns: 5264 ** none 5265 */ 5266 5267 void 5268 sm_close_on_exec(highest, lowest) 5269 int highest, lowest; 5270 { 5271 #if HASFDWALK 5272 (void) fdwalk(closefd_walk, &lowest); 5273 #else /* HASFDWALK */ 5274 int i, j; 5275 5276 for (i = lowest; i < highest; i++) 5277 { 5278 if ((j = fcntl(i, F_GETFD, 0)) != -1) 5279 (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 5280 } 5281 #endif /* HASFDWALK */ 5282 } 5283 /* 5284 ** SEED_RANDOM -- seed the random number generator 5285 ** 5286 ** Parameters: 5287 ** none 5288 ** 5289 ** Returns: 5290 ** none 5291 */ 5292 5293 void 5294 seed_random() 5295 { 5296 #if HASSRANDOMDEV 5297 srandomdev(); 5298 #else /* HASSRANDOMDEV */ 5299 long seed; 5300 struct timeval t; 5301 5302 seed = (long) CurrentPid; 5303 if (gettimeofday(&t, NULL) >= 0) 5304 seed += t.tv_sec + t.tv_usec; 5305 5306 # if HASRANDOM 5307 (void) srandom(seed); 5308 # else /* HASRANDOM */ 5309 (void) srand((unsigned int) seed); 5310 # endif /* HASRANDOM */ 5311 #endif /* HASSRANDOMDEV */ 5312 } 5313 /* 5314 ** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE 5315 ** 5316 ** Parameters: 5317 ** level -- syslog level 5318 ** id -- envelope ID or NULL (NOQUEUE) 5319 ** fmt -- format string 5320 ** arg... -- arguments as implied by fmt. 5321 ** 5322 ** Returns: 5323 ** none 5324 */ 5325 5326 /* VARARGS3 */ 5327 void 5328 #ifdef __STDC__ 5329 sm_syslog(int level, const char *id, const char *fmt, ...) 5330 #else /* __STDC__ */ 5331 sm_syslog(level, id, fmt, va_alist) 5332 int level; 5333 const char *id; 5334 const char *fmt; 5335 va_dcl 5336 #endif /* __STDC__ */ 5337 { 5338 char *buf; 5339 size_t bufsize; 5340 char *begin, *end; 5341 int save_errno; 5342 int seq = 1; 5343 int idlen; 5344 char buf0[MAXLINE]; 5345 char *newstring; 5346 extern int SyslogPrefixLen; 5347 SM_VA_LOCAL_DECL 5348 5349 save_errno = errno; 5350 if (id == NULL) 5351 id = "NOQUEUE"; 5352 idlen = strlen(id) + SyslogPrefixLen; 5353 5354 buf = buf0; 5355 bufsize = sizeof(buf0); 5356 5357 for (;;) 5358 { 5359 int n; 5360 5361 /* print log message into buf */ 5362 SM_VA_START(ap, fmt); 5363 n = sm_vsnprintf(buf, bufsize, fmt, ap); 5364 SM_VA_END(ap); 5365 SM_ASSERT(n > 0); 5366 if (n < bufsize) 5367 break; 5368 5369 /* String too small, redo with correct size */ 5370 bufsize = n + 1; 5371 if (buf != buf0) 5372 { 5373 sm_free(buf); 5374 buf = NULL; 5375 } 5376 buf = sm_malloc_x(bufsize); 5377 } 5378 5379 /* clean up buf after it has been expanded with args */ 5380 newstring = str2prt(buf); 5381 if ((strlen(newstring) + idlen + 1) < SYSLOG_BUFSIZE) 5382 { 5383 #if LOG 5384 if (*id == '\0') 5385 { 5386 if (tTd(89, 10)) 5387 { 5388 struct timeval tv; 5389 5390 gettimeofday(&tv, NULL); 5391 sm_dprintf("%ld.%06ld %s\n", (long) tv.tv_sec, 5392 (long) tv.tv_usec, newstring); 5393 } 5394 else if (tTd(89, 8)) 5395 sm_dprintf("%s\n", newstring); 5396 else 5397 syslog(level, "%s", newstring); 5398 } 5399 else 5400 { 5401 if (tTd(89, 10)) 5402 { 5403 struct timeval tv; 5404 5405 gettimeofday(&tv, NULL); 5406 sm_dprintf("%ld.%06ld %s: %s\n", (long) tv.tv_sec, 5407 (long) tv.tv_usec, id, newstring); 5408 } 5409 else if (tTd(89, 8)) 5410 sm_dprintf("%s: %s\n", id, newstring); 5411 else 5412 syslog(level, "%s: %s", id, newstring); 5413 } 5414 #else /* LOG */ 5415 /*XXX should do something more sensible */ 5416 if (*id == '\0') 5417 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", 5418 newstring); 5419 else 5420 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5421 "%s: %s\n", id, newstring); 5422 #endif /* LOG */ 5423 if (buf != buf0) 5424 sm_free(buf); 5425 errno = save_errno; 5426 return; 5427 } 5428 5429 /* 5430 ** additional length for splitting: " ..." + 3, where 3 is magic to 5431 ** have some data for the next entry. 5432 */ 5433 5434 #define SL_SPLIT 7 5435 5436 begin = newstring; 5437 idlen += 5; /* strlen("[999]"), see below */ 5438 while (*begin != '\0' && 5439 (strlen(begin) + idlen) > SYSLOG_BUFSIZE) 5440 { 5441 char save; 5442 5443 if (seq >= 999) 5444 { 5445 /* Too many messages */ 5446 break; 5447 } 5448 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5449 while (end > begin) 5450 { 5451 /* Break on comma or space */ 5452 if (*end == ',' || *end == ' ') 5453 { 5454 end++; /* Include separator */ 5455 break; 5456 } 5457 end--; 5458 } 5459 /* No separator, break midstring... */ 5460 if (end == begin) 5461 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5462 save = *end; 5463 *end = 0; 5464 #if LOG 5465 if (tTd(89, 8)) 5466 sm_dprintf("%s[%d]: %s ...\n", id, seq++, begin); 5467 else 5468 syslog(level, "%s[%d]: %s ...", id, seq++, begin); 5469 #else /* LOG */ 5470 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5471 "%s[%d]: %s ...\n", id, seq++, begin); 5472 #endif /* LOG */ 5473 *end = save; 5474 begin = end; 5475 } 5476 if (seq >= 999) 5477 { 5478 #if LOG 5479 if (tTd(89, 8)) 5480 sm_dprintf("%s[%d]: log terminated, too many parts\n", 5481 id, seq); 5482 else 5483 syslog(level, "%s[%d]: log terminated, too many parts", 5484 id, seq); 5485 #else /* LOG */ 5486 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5487 "%s[%d]: log terminated, too many parts\n", id, seq); 5488 #endif /* LOG */ 5489 } 5490 else if (*begin != '\0') 5491 { 5492 #if LOG 5493 if (tTd(89, 8)) 5494 sm_dprintf("%s[%d]: %s\n", id, seq, begin); 5495 else 5496 syslog(level, "%s[%d]: %s", id, seq, begin); 5497 #else /* LOG */ 5498 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5499 "%s[%d]: %s\n", id, seq, begin); 5500 #endif /* LOG */ 5501 } 5502 if (buf != buf0) 5503 sm_free(buf); 5504 errno = save_errno; 5505 } 5506 /* 5507 ** HARD_SYSLOG -- call syslog repeatedly until it works 5508 ** 5509 ** Needed on HP-UX, which apparently doesn't guarantee that 5510 ** syslog succeeds during interrupt handlers. 5511 */ 5512 5513 #if defined(__hpux) && !defined(HPUX11) 5514 5515 # define MAXSYSLOGTRIES 100 5516 # undef syslog 5517 # ifdef V4FS 5518 # define XCNST const 5519 # define CAST (const char *) 5520 # else /* V4FS */ 5521 # define XCNST 5522 # define CAST 5523 # endif /* V4FS */ 5524 5525 void 5526 # ifdef __STDC__ 5527 hard_syslog(int pri, XCNST char *msg, ...) 5528 # else /* __STDC__ */ 5529 hard_syslog(pri, msg, va_alist) 5530 int pri; 5531 XCNST char *msg; 5532 va_dcl 5533 # endif /* __STDC__ */ 5534 { 5535 int i; 5536 char buf[SYSLOG_BUFSIZE]; 5537 SM_VA_LOCAL_DECL 5538 5539 SM_VA_START(ap, msg); 5540 (void) sm_vsnprintf(buf, sizeof(buf), msg, ap); 5541 SM_VA_END(ap); 5542 5543 for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; ) 5544 continue; 5545 } 5546 5547 # undef CAST 5548 #endif /* defined(__hpux) && !defined(HPUX11) */ 5549 #if NEEDLOCAL_HOSTNAME_LENGTH 5550 /* 5551 ** LOCAL_HOSTNAME_LENGTH 5552 ** 5553 ** This is required to get sendmail to compile against BIND 4.9.x 5554 ** on Ultrix. 5555 ** 5556 ** Unfortunately, a Compaq Y2K patch kit provides it without 5557 ** bumping __RES in /usr/include/resolv.h so we can't automatically 5558 ** figure out whether it is needed. 5559 */ 5560 5561 int 5562 local_hostname_length(hostname) 5563 char *hostname; 5564 { 5565 size_t len_host, len_domain; 5566 5567 if (!*_res.defdname) 5568 res_init(); 5569 len_host = strlen(hostname); 5570 len_domain = strlen(_res.defdname); 5571 if (len_host > len_domain && 5572 (sm_strcasecmp(hostname + len_host - len_domain, 5573 _res.defdname) == 0) && 5574 hostname[len_host - len_domain - 1] == '.') 5575 return len_host - len_domain - 1; 5576 else 5577 return 0; 5578 } 5579 #endif /* NEEDLOCAL_HOSTNAME_LENGTH */ 5580 5581 #if NEEDLINK 5582 /* 5583 ** LINK -- clone a file 5584 ** 5585 ** Some OS's lacks link() and hard links. Since sendmail is using 5586 ** link() as an efficient way to clone files, this implementation 5587 ** will simply do a file copy. 5588 ** 5589 ** NOTE: This link() replacement is not a generic replacement as it 5590 ** does not handle all of the semantics of the real link(2). 5591 ** 5592 ** Parameters: 5593 ** source -- pathname of existing file. 5594 ** target -- pathname of link (clone) to be created. 5595 ** 5596 ** Returns: 5597 ** 0 -- success. 5598 ** -1 -- failure, see errno for details. 5599 */ 5600 5601 int 5602 link(source, target) 5603 const char *source; 5604 const char *target; 5605 { 5606 int save_errno; 5607 int sff; 5608 int src = -1, dst = -1; 5609 ssize_t readlen; 5610 ssize_t writelen; 5611 char buf[BUFSIZ]; 5612 struct stat st; 5613 5614 sff = SFF_REGONLY|SFF_OPENASROOT; 5615 if (DontLockReadFiles) 5616 sff |= SFF_NOLOCK; 5617 5618 /* Open the original file */ 5619 src = safeopen((char *)source, O_RDONLY, 0, sff); 5620 if (src < 0) 5621 goto fail; 5622 5623 /* Obtain the size and the mode */ 5624 if (fstat(src, &st) < 0) 5625 goto fail; 5626 5627 /* Create the duplicate copy */ 5628 sff &= ~SFF_NOLOCK; 5629 sff |= SFF_CREAT; 5630 dst = safeopen((char *)target, O_CREAT|O_EXCL|O_WRONLY, 5631 st.st_mode, sff); 5632 if (dst < 0) 5633 goto fail; 5634 5635 /* Copy all of the bytes one buffer at a time */ 5636 while ((readlen = read(src, &buf, sizeof(buf))) > 0) 5637 { 5638 ssize_t left = readlen; 5639 char *p = buf; 5640 5641 while (left > 0 && 5642 (writelen = write(dst, p, (size_t) left)) >= 0) 5643 { 5644 left -= writelen; 5645 p += writelen; 5646 } 5647 if (writelen < 0) 5648 break; 5649 } 5650 5651 /* Any trouble reading? */ 5652 if (readlen < 0 || writelen < 0) 5653 goto fail; 5654 5655 /* Close the input file */ 5656 if (close(src) < 0) 5657 { 5658 src = -1; 5659 goto fail; 5660 } 5661 src = -1; 5662 5663 /* Close the output file */ 5664 if (close(dst) < 0) 5665 { 5666 /* don't set dst = -1 here so we unlink the file */ 5667 goto fail; 5668 } 5669 5670 /* Success */ 5671 return 0; 5672 5673 fail: 5674 save_errno = errno; 5675 if (src >= 0) 5676 (void) close(src); 5677 if (dst >= 0) 5678 { 5679 (void) unlink(target); 5680 (void) close(dst); 5681 } 5682 errno = save_errno; 5683 return -1; 5684 } 5685 #endif /* NEEDLINK */ 5686 5687 /* 5688 ** Compile-Time options 5689 */ 5690 5691 char *CompileOptions[] = 5692 { 5693 #if ALLOW_255 5694 "ALLOW_255", 5695 #endif /* ALLOW_255 */ 5696 #if NAMED_BIND 5697 # if DNSMAP 5698 "DNSMAP", 5699 # endif /* DNSMAP */ 5700 #endif /* NAMED_BIND */ 5701 #if EGD 5702 "EGD", 5703 #endif /* EGD */ 5704 #if HESIOD 5705 "HESIOD", 5706 #endif /* HESIOD */ 5707 #if HES_GETMAILHOST 5708 "HES_GETMAILHOST", 5709 #endif /* HES_GETMAILHOST */ 5710 #if LDAPMAP 5711 "LDAPMAP", 5712 #endif /* LDAPMAP */ 5713 #if LDAP_REFERRALS 5714 "LDAP_REFERRALS", 5715 #endif /* LDAP_REFERRALS */ 5716 #if LOG 5717 "LOG", 5718 #endif /* LOG */ 5719 #if MAP_NSD 5720 "MAP_NSD", 5721 #endif /* MAP_NSD */ 5722 #if MAP_REGEX 5723 "MAP_REGEX", 5724 #endif /* MAP_REGEX */ 5725 #if MATCHGECOS 5726 "MATCHGECOS", 5727 #endif /* MATCHGECOS */ 5728 #if MILTER 5729 "MILTER", 5730 #endif /* MILTER */ 5731 #if MIME7TO8 5732 "MIME7TO8", 5733 #endif /* MIME7TO8 */ 5734 #if MIME7TO8_OLD 5735 "MIME7TO8_OLD", 5736 #endif /* MIME7TO8_OLD */ 5737 #if MIME8TO7 5738 "MIME8TO7", 5739 #endif /* MIME8TO7 */ 5740 #if NAMED_BIND 5741 "NAMED_BIND", 5742 #endif /* NAMED_BIND */ 5743 #if NDBM 5744 "NDBM", 5745 #endif /* NDBM */ 5746 #if NETINET 5747 "NETINET", 5748 #endif /* NETINET */ 5749 #if NETINET6 5750 "NETINET6", 5751 #endif /* NETINET6 */ 5752 #if NETINFO 5753 "NETINFO", 5754 #endif /* NETINFO */ 5755 #if NETISO 5756 "NETISO", 5757 #endif /* NETISO */ 5758 #if NETNS 5759 "NETNS", 5760 #endif /* NETNS */ 5761 #if NETUNIX 5762 "NETUNIX", 5763 #endif /* NETUNIX */ 5764 #if NETX25 5765 "NETX25", 5766 #endif /* NETX25 */ 5767 #if NEWDB 5768 "NEWDB", 5769 #endif /* NEWDB */ 5770 #if NIS 5771 "NIS", 5772 #endif /* NIS */ 5773 #if NISPLUS 5774 "NISPLUS", 5775 #endif /* NISPLUS */ 5776 #if NO_DH 5777 "NO_DH", 5778 #endif /* NO_DH */ 5779 #if PH_MAP 5780 "PH_MAP", 5781 #endif /* PH_MAP */ 5782 #ifdef PICKY_HELO_CHECK 5783 "PICKY_HELO_CHECK", 5784 #endif /* PICKY_HELO_CHECK */ 5785 #if PIPELINING 5786 "PIPELINING", 5787 #endif /* PIPELINING */ 5788 #if SASL 5789 # if SASL >= 20000 5790 "SASLv2", 5791 # else /* SASL >= 20000 */ 5792 "SASL", 5793 # endif /* SASL >= 20000 */ 5794 #endif /* SASL */ 5795 #if SCANF 5796 "SCANF", 5797 #endif /* SCANF */ 5798 #if SM_LDAP_ERROR_ON_MISSING_ARGS 5799 "SM_LDAP_ERROR_ON_MISSING_ARGS", 5800 #endif /* SM_LDAP_ERROR_ON_MISSING_ARGS */ 5801 #if SMTPDEBUG 5802 "SMTPDEBUG", 5803 #endif /* SMTPDEBUG */ 5804 #if SOCKETMAP 5805 "SOCKETMAP", 5806 #endif /* SOCKETMAP */ 5807 #if STARTTLS 5808 "STARTTLS", 5809 #endif /* STARTTLS */ 5810 #if SUID_ROOT_FILES_OK 5811 "SUID_ROOT_FILES_OK", 5812 #endif /* SUID_ROOT_FILES_OK */ 5813 #if TCPWRAPPERS 5814 "TCPWRAPPERS", 5815 #endif /* TCPWRAPPERS */ 5816 #if TLS_NO_RSA 5817 "TLS_NO_RSA", 5818 #endif /* TLS_NO_RSA */ 5819 #if TLS_VRFY_PER_CTX 5820 "TLS_VRFY_PER_CTX", 5821 #endif /* TLS_VRFY_PER_CTX */ 5822 #if USERDB 5823 "USERDB", 5824 #endif /* USERDB */ 5825 #if USE_LDAP_INIT 5826 "USE_LDAP_INIT", 5827 #endif /* USE_LDAP_INIT */ 5828 #if USE_TTYPATH 5829 "USE_TTYPATH", 5830 #endif /* USE_TTYPATH */ 5831 #if XDEBUG 5832 "XDEBUG", 5833 #endif /* XDEBUG */ 5834 #if XLA 5835 "XLA", 5836 #endif /* XLA */ 5837 NULL 5838 }; 5839 5840 5841 /* 5842 ** OS compile options. 5843 */ 5844 5845 char *OsCompileOptions[] = 5846 { 5847 #if ADDRCONFIG_IS_BROKEN 5848 "ADDRCONFIG_IS_BROKEN", 5849 #endif /* ADDRCONFIG_IS_BROKEN */ 5850 #ifdef AUTO_NETINFO_HOSTS 5851 "AUTO_NETINFO_HOSTS", 5852 #endif /* AUTO_NETINFO_HOSTS */ 5853 #ifdef AUTO_NIS_ALIASES 5854 "AUTO_NIS_ALIASES", 5855 #endif /* AUTO_NIS_ALIASES */ 5856 #if BROKEN_RES_SEARCH 5857 "BROKEN_RES_SEARCH", 5858 #endif /* BROKEN_RES_SEARCH */ 5859 #ifdef BSD4_4_SOCKADDR 5860 "BSD4_4_SOCKADDR", 5861 #endif /* BSD4_4_SOCKADDR */ 5862 #if BOGUS_O_EXCL 5863 "BOGUS_O_EXCL", 5864 #endif /* BOGUS_O_EXCL */ 5865 #if DEC_OSF_BROKEN_GETPWENT 5866 "DEC_OSF_BROKEN_GETPWENT", 5867 #endif /* DEC_OSF_BROKEN_GETPWENT */ 5868 #if FAST_PID_RECYCLE 5869 "FAST_PID_RECYCLE", 5870 #endif /* FAST_PID_RECYCLE */ 5871 #if HASCLOSEFROM 5872 "HASCLOSEFROM", 5873 #endif /* HASCLOSEFROM */ 5874 #if HASFCHOWN 5875 "HASFCHOWN", 5876 #endif /* HASFCHOWN */ 5877 #if HASFCHMOD 5878 "HASFCHMOD", 5879 #endif /* HASFCHMOD */ 5880 #if HASFDWALK 5881 "HASFDWALK", 5882 #endif /* HASFDWALK */ 5883 #if HASFLOCK 5884 "HASFLOCK", 5885 #endif /* HASFLOCK */ 5886 #if HASGETDTABLESIZE 5887 "HASGETDTABLESIZE", 5888 #endif /* HASGETDTABLESIZE */ 5889 #if HASGETUSERSHELL 5890 "HASGETUSERSHELL", 5891 #endif /* HASGETUSERSHELL */ 5892 #if HASINITGROUPS 5893 "HASINITGROUPS", 5894 #endif /* HASINITGROUPS */ 5895 #if HASLDAPGETALIASBYNAME 5896 "HASLDAPGETALIASBYNAME", 5897 #endif /* HASLDAPGETALIASBYNAME */ 5898 #if HASLSTAT 5899 "HASLSTAT", 5900 #endif /* HASLSTAT */ 5901 #if HASNICE 5902 "HASNICE", 5903 #endif /* HASNICE */ 5904 #if HASRANDOM 5905 "HASRANDOM", 5906 #endif /* HASRANDOM */ 5907 #if HASRRESVPORT 5908 "HASRRESVPORT", 5909 #endif /* HASRRESVPORT */ 5910 #if HASSETEGID 5911 "HASSETEGID", 5912 #endif /* HASSETEGID */ 5913 #if HASSETLOGIN 5914 "HASSETLOGIN", 5915 #endif /* HASSETLOGIN */ 5916 #if HASSETREGID 5917 "HASSETREGID", 5918 #endif /* HASSETREGID */ 5919 #if HASSETRESGID 5920 "HASSETRESGID", 5921 #endif /* HASSETRESGID */ 5922 #if HASSETREUID 5923 "HASSETREUID", 5924 #endif /* HASSETREUID */ 5925 #if HASSETRLIMIT 5926 "HASSETRLIMIT", 5927 #endif /* HASSETRLIMIT */ 5928 #if HASSETSID 5929 "HASSETSID", 5930 #endif /* HASSETSID */ 5931 #if HASSETUSERCONTEXT 5932 "HASSETUSERCONTEXT", 5933 #endif /* HASSETUSERCONTEXT */ 5934 #if HASSETVBUF 5935 "HASSETVBUF", 5936 #endif /* HASSETVBUF */ 5937 #if HAS_ST_GEN 5938 "HAS_ST_GEN", 5939 #endif /* HAS_ST_GEN */ 5940 #if HASSRANDOMDEV 5941 "HASSRANDOMDEV", 5942 #endif /* HASSRANDOMDEV */ 5943 #if HASURANDOMDEV 5944 "HASURANDOMDEV", 5945 #endif /* HASURANDOMDEV */ 5946 #if HASSTRERROR 5947 "HASSTRERROR", 5948 #endif /* HASSTRERROR */ 5949 #if HASULIMIT 5950 "HASULIMIT", 5951 #endif /* HASULIMIT */ 5952 #if HASUNAME 5953 "HASUNAME", 5954 #endif /* HASUNAME */ 5955 #if HASUNSETENV 5956 "HASUNSETENV", 5957 #endif /* HASUNSETENV */ 5958 #if HASWAITPID 5959 "HASWAITPID", 5960 #endif /* HASWAITPID */ 5961 #if HAVE_NANOSLEEP 5962 "HAVE_NANOSLEEP", 5963 #endif /* HAVE_NANOSLEEP */ 5964 #if IDENTPROTO 5965 "IDENTPROTO", 5966 #endif /* IDENTPROTO */ 5967 #if IP_SRCROUTE 5968 "IP_SRCROUTE", 5969 #endif /* IP_SRCROUTE */ 5970 #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 5971 "LOCK_ON_OPEN", 5972 #endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 5973 #if MILTER_NO_NAGLE 5974 "MILTER_NO_NAGLE ", 5975 #endif /* MILTER_NO_NAGLE */ 5976 #if NEEDFSYNC 5977 "NEEDFSYNC", 5978 #endif /* NEEDFSYNC */ 5979 #if NEEDLINK 5980 "NEEDLINK", 5981 #endif /* NEEDLINK */ 5982 #if NEEDLOCAL_HOSTNAME_LENGTH 5983 "NEEDLOCAL_HOSTNAME_LENGTH", 5984 #endif /* NEEDLOCAL_HOSTNAME_LENGTH */ 5985 #if NEEDSGETIPNODE 5986 "NEEDSGETIPNODE", 5987 #endif /* NEEDSGETIPNODE */ 5988 #if NEEDSTRSTR 5989 "NEEDSTRSTR", 5990 #endif /* NEEDSTRSTR */ 5991 #if NEEDSTRTOL 5992 "NEEDSTRTOL", 5993 #endif /* NEEDSTRTOL */ 5994 #ifdef NO_GETSERVBYNAME 5995 "NO_GETSERVBYNAME", 5996 #endif /* NO_GETSERVBYNAME */ 5997 #if NOFTRUNCATE 5998 "NOFTRUNCATE", 5999 #endif /* NOFTRUNCATE */ 6000 #if REQUIRES_DIR_FSYNC 6001 "REQUIRES_DIR_FSYNC", 6002 #endif /* REQUIRES_DIR_FSYNC */ 6003 #if RLIMIT_NEEDS_SYS_TIME_H 6004 "RLIMIT_NEEDS_SYS_TIME_H", 6005 #endif /* RLIMIT_NEEDS_SYS_TIME_H */ 6006 #if SAFENFSPATHCONF 6007 "SAFENFSPATHCONF", 6008 #endif /* SAFENFSPATHCONF */ 6009 #if SECUREWARE 6010 "SECUREWARE", 6011 #endif /* SECUREWARE */ 6012 #if SFS_TYPE == SFS_4ARGS 6013 "SFS_4ARGS", 6014 #elif SFS_TYPE == SFS_MOUNT 6015 "SFS_MOUNT", 6016 #elif SFS_TYPE == SFS_NONE 6017 "SFS_NONE", 6018 #elif SFS_TYPE == SFS_NT 6019 "SFS_NT", 6020 #elif SFS_TYPE == SFS_STATFS 6021 "SFS_STATFS", 6022 #elif SFS_TYPE == SFS_STATVFS 6023 "SFS_STATVFS", 6024 #elif SFS_TYPE == SFS_USTAT 6025 "SFS_USTAT", 6026 #elif SFS_TYPE == SFS_VFS 6027 "SFS_VFS", 6028 #endif 6029 #if SHARE_V1 6030 "SHARE_V1", 6031 #endif /* SHARE_V1 */ 6032 #if SIOCGIFCONF_IS_BROKEN 6033 "SIOCGIFCONF_IS_BROKEN", 6034 #endif /* SIOCGIFCONF_IS_BROKEN */ 6035 #if SIOCGIFNUM_IS_BROKEN 6036 "SIOCGIFNUM_IS_BROKEN", 6037 #endif /* SIOCGIFNUM_IS_BROKEN */ 6038 #if SNPRINTF_IS_BROKEN 6039 "SNPRINTF_IS_BROKEN", 6040 #endif /* SNPRINTF_IS_BROKEN */ 6041 #if SO_REUSEADDR_IS_BROKEN 6042 "SO_REUSEADDR_IS_BROKEN", 6043 #endif /* SO_REUSEADDR_IS_BROKEN */ 6044 #if SYS5SETPGRP 6045 "SYS5SETPGRP", 6046 #endif /* SYS5SETPGRP */ 6047 #if SYSTEM5 6048 "SYSTEM5", 6049 #endif /* SYSTEM5 */ 6050 #if USE_DOUBLE_FORK 6051 "USE_DOUBLE_FORK", 6052 #endif /* USE_DOUBLE_FORK */ 6053 #if USE_ENVIRON 6054 "USE_ENVIRON", 6055 #endif /* USE_ENVIRON */ 6056 #if USE_SA_SIGACTION 6057 "USE_SA_SIGACTION", 6058 #endif /* USE_SA_SIGACTION */ 6059 #if USE_SIGLONGJMP 6060 "USE_SIGLONGJMP", 6061 #endif /* USE_SIGLONGJMP */ 6062 #if USEGETCONFATTR 6063 "USEGETCONFATTR", 6064 #endif /* USEGETCONFATTR */ 6065 #if USESETEUID 6066 "USESETEUID", 6067 #endif /* USESETEUID */ 6068 #ifdef USESYSCTL 6069 "USESYSCTL", 6070 #endif /* USESYSCTL */ 6071 #if USE_OPENSSL_ENGINE 6072 "USE_OPENSSL_ENGINE", 6073 #endif /* USE_OPENSSL_ENGINE */ 6074 #if USING_NETSCAPE_LDAP 6075 "USING_NETSCAPE_LDAP", 6076 #endif /* USING_NETSCAPE_LDAP */ 6077 #ifdef WAITUNION 6078 "WAITUNION", 6079 #endif /* WAITUNION */ 6080 NULL 6081 }; 6082 6083 /* 6084 ** FFR compile options. 6085 */ 6086 6087 char *FFRCompileOptions[] = 6088 { 6089 #if _FFR_ADDR_TYPE_MODES 6090 /* more info in {addr_type}, requires m4 changes! */ 6091 "_FFR_ADDR_TYPE_MODES", 6092 #endif /* _FFR_ADDR_TYPE_MODES */ 6093 #if _FFR_ALLOW_SASLINFO 6094 /* DefaultAuthInfo can be specified by user. */ 6095 /* DefaultAuthInfo doesn't really work in 8.13 anymore. */ 6096 "_FFR_ALLOW_SASLINFO", 6097 #endif /* _FFR_ALLOW_SASLINFO */ 6098 #if _FFR_BADRCPT_SHUTDOWN 6099 /* shut down connection (421) if there are too many bad RCPTs */ 6100 "_FFR_BADRCPT_SHUTDOWN", 6101 #endif /* _FFR_BADRCPT_SHUTDOWN */ 6102 #if _FFR_BESTMX_BETTER_TRUNCATION 6103 /* Better truncation of list of MX records for dns map. */ 6104 "_FFR_BESTMX_BETTER_TRUNCATION", 6105 #endif /* _FFR_BESTMX_BETTER_TRUNCATION */ 6106 #if _FFR_CATCH_BROKEN_MTAS 6107 /* Deal with MTAs that send a reply during the DATA phase. */ 6108 "_FFR_CATCH_BROKEN_MTAS", 6109 #endif /* _FFR_CATCH_BROKEN_MTAS */ 6110 #if _FFR_CHECKCONFIG 6111 /* New OpMode to check the configuration file */ 6112 "_FFR_CHECKCONFIG", 6113 #endif /* _FFR_CHECKCONFIG */ 6114 #if _FFR_CHK_QUEUE 6115 /* Stricter checks about queue directory permissions. */ 6116 "_FFR_CHK_QUEUE", 6117 #endif /* _FFR_CHK_QUEUE */ 6118 #if _FFR_CLIENT_SIZE 6119 /* Don't try to send mail if its size exceeds SIZE= of server. */ 6120 "_FFR_CLIENT_SIZE", 6121 #endif /* _FFR_CLIENT_SIZE */ 6122 #if _FFR_CRLPATH 6123 /* CRLPath; needs documentation; Al Smith */ 6124 "_FFR_CRLPATH", 6125 #endif /* _FFR_CRLPATH */ 6126 #if _FFR_DAEMON_NETUNIX 6127 /* Allow local (not just TCP) socket connection to server. */ 6128 "_FFR_DAEMON_NETUNIX", 6129 #endif /* _FFR_DAEMON_NETUNIX */ 6130 #if _FFR_DEPRECATE_MAILER_FLAG_I 6131 /* What it says :-) */ 6132 "_FFR_DEPRECATE_MAILER_FLAG_I", 6133 #endif /* _FFR_DEPRECATE_MAILER_FLAG_I */ 6134 #if _FFR_DM_ONE 6135 /* deliver first TA in background, then queue */ 6136 "_FFR_DM_ONE", 6137 #endif /* _FFR_DM_ONE */ 6138 #if _FFR_DIGUNIX_SAFECHOWN 6139 /* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */ 6140 /* Problem noted by Anne Bennett of Concordia University */ 6141 "_FFR_DIGUNIX_SAFECHOWN", 6142 #endif /* _FFR_DIGUNIX_SAFECHOWN */ 6143 #if _FFR_DNSMAP_ALIASABLE 6144 /* Allow dns map type to be used for aliases. */ 6145 /* Don Lewis of TDK */ 6146 "_FFR_DNSMAP_ALIASABLE", 6147 #endif /* _FFR_DNSMAP_ALIASABLE */ 6148 #if _FFR_DONTLOCKFILESFORREAD_OPTION 6149 /* Enable DontLockFilesForRead option. */ 6150 "_FFR_DONTLOCKFILESFORREAD_OPTION", 6151 #endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ 6152 #if _FFR_DOTTED_USERNAMES 6153 /* Allow usernames with '.' */ 6154 "_FFR_DOTTED_USERNAMES", 6155 #endif /* _FFR_DOTTED_USERNAMES */ 6156 #if _FFR_DPO_CS 6157 /* 6158 ** Make DaemonPortOptions case sensitive. 6159 ** For some unknown reasons the code converted every option 6160 ** to uppercase (first letter only, as that's the only one that 6161 ** is actually checked). This prevented all new lower case options 6162 ** from working... 6163 ** The documentation doesn't say anything about case (in)sensitivity, 6164 ** which means it should be case sensitive by default, 6165 ** but it's not a good idea to change this within a patch release, 6166 ** so let's delay this to 8.15. 6167 */ 6168 6169 "_FFR_DPO_CS", 6170 #endif /* _FFR_DPO_CS */ 6171 #if _FFR_DPRINTF_MAP 6172 /* dprintf map for logging */ 6173 "_FFR_DPRINTF_MAP", 6174 #endif /* _FFR_DPRINTF_MAP */ 6175 #if _FFR_DROP_TRUSTUSER_WARNING 6176 /* 6177 ** Don't issue this warning: 6178 ** "readcf: option TrustedUser may cause problems on systems 6179 ** which do not support fchown() if UseMSP is not set. 6180 */ 6181 6182 "_FFR_DROP_TRUSTUSER_WARNING", 6183 #endif /* _FFR_DROP_TRUSTUSER_WARNING */ 6184 #if _FFR_EIGHT_BIT_ADDR_OK 6185 /* EightBitAddrOK: allow 8-bit e-mail addresses */ 6186 "_FFR_EIGHT_BIT_ADDR_OK", 6187 #endif /* _FFR_EIGHT_BIT_ADDR_OK */ 6188 #if _FFR_EXPDELAY 6189 /* exponential queue delay */ 6190 "_FFR_EXPDELAY", 6191 #endif /* _FFR_EXPDELAY */ 6192 #if _FFR_EXTRA_MAP_CHECK 6193 /* perform extra checks on $( $) in R lines */ 6194 "_FFR_EXTRA_MAP_CHECK", 6195 #endif /* _FFR_EXTRA_MAP_CHECK */ 6196 #if _FFR_GETHBN_ExFILE 6197 /* 6198 ** According to Motonori Nakamura some gethostbyname() 6199 ** implementations (TurboLinux?) may (temporarily) fail 6200 ** due to a lack of file discriptors. Enabling this FFR 6201 ** will check errno for EMFILE and ENFILE and in case of a match 6202 ** cause a temporary error instead of a permanent error. 6203 ** The right solution is of course to file a bug against those 6204 ** systems such that they actually set h_errno = TRY_AGAIN. 6205 */ 6206 6207 "_FFR_GETHBN_ExFILE", 6208 #endif /* _FFR_GETHBN_ExFILE */ 6209 #if _FFR_FIPSMODE 6210 /* FIPSMode (if supported by OpenSSL library) */ 6211 "_FFR_FIPSMODE", 6212 #endif /* _FFR_FIPSMODE */ 6213 #if _FFR_FIX_DASHT 6214 /* 6215 ** If using -t, force not sending to argv recipients, even 6216 ** if they are mentioned in the headers. 6217 */ 6218 6219 "_FFR_FIX_DASHT", 6220 #endif /* _FFR_FIX_DASHT */ 6221 #if _FFR_FORWARD_SYSERR 6222 /* Cause a "syserr" if forward file isn't "safe". */ 6223 "_FFR_FORWARD_SYSERR", 6224 #endif /* _FFR_FORWARD_SYSERR */ 6225 #if _FFR_GEN_ORCPT 6226 /* Generate a ORCPT DSN arg if not already provided */ 6227 "_FFR_GEN_ORCPT", 6228 #endif /* _FFR_GEN_ORCPT */ 6229 #if _FFR_GROUPREADABLEAUTHINFOFILE 6230 /* Allow group readable DefaultAuthInfo file. */ 6231 "_FFR_GROUPREADABLEAUTHINFOFILE", 6232 #endif /* _FFR_GROUPREADABLEAUTHINFOFILE */ 6233 #if _FFR_HANDLE_ISO8859_GECOS 6234 /* 6235 ** Allow ISO 8859 characters in GECOS field: replace them 6236 ** ith ASCII "equivalent". 6237 */ 6238 6239 /* Peter Eriksson of Linkopings universitet */ 6240 "_FFR_HANDLE_ISO8859_GECOS", 6241 #endif /* _FFR_HANDLE_ISO8859_GECOS */ 6242 #if _FFR_HPUX_NSSWITCH 6243 /* Use nsswitch on HP-UX */ 6244 "_FFR_HPUX_NSSWITCH", 6245 #endif /* _FFR_HPUX_NSSWITCH */ 6246 #if _FFR_IGNORE_BOGUS_ADDR 6247 /* Ignore addresses for which prescan() failed */ 6248 "_FFR_IGNORE_BOGUS_ADDR", 6249 #endif /* _FFR_IGNORE_BOGUS_ADDR */ 6250 #if _FFR_IGNORE_EXT_ON_HELO 6251 /* Ignore extensions offered in response to HELO */ 6252 "_FFR_IGNORE_EXT_ON_HELO", 6253 #endif /* _FFR_IGNORE_EXT_ON_HELO */ 6254 #if _FFR_LINUX_MHNL 6255 /* Set MAXHOSTNAMELEN to 256 (Linux) */ 6256 "_FFR_LINUX_MHNL", 6257 #endif /* _FFR_LINUX_MHNL */ 6258 #if _FFR_LOCAL_DAEMON 6259 /* Local daemon mode (-bl) which only accepts loopback connections */ 6260 "_FFR_LOCAL_DAEMON", 6261 #endif /* _FFR_LOCAL_DAEMON */ 6262 #if _FFR_MAIL_MACRO 6263 "_FFR_MAIL_MACRO", 6264 #endif /* _FFR_MAIL_MACRO */ 6265 #if _FFR_MAXDATASIZE 6266 /* 6267 ** It is possible that a header is larger than MILTER_CHUNK_SIZE, 6268 ** hence this shouldn't be used as limit for milter communication. 6269 ** see also libmilter/comm.c 6270 ** Gurusamy Sarathy of ActiveState 6271 */ 6272 6273 "_FFR_MAXDATASIZE", 6274 #endif /* _FFR_MAXDATASIZE */ 6275 #if _FFR_MAX_FORWARD_ENTRIES 6276 /* Try to limit number of .forward entries */ 6277 /* (doesn't work) */ 6278 /* Randall S. Winchester of the University of Maryland */ 6279 "_FFR_MAX_FORWARD_ENTRIES", 6280 #endif /* _FFR_MAX_FORWARD_ENTRIES */ 6281 #if _FFR_MAX_SLEEP_TIME 6282 /* Limit sleep(2) time in libsm/clock.c */ 6283 "_FFR_MAX_SLEEP_TIME", 6284 #endif /* _FFR_MAX_SLEEP_TIME */ 6285 #if _FFR_MDS_NEGOTIATE 6286 /* MaxDataSize negotation with libmilter */ 6287 "_FFR_MDS_NEGOTIATE", 6288 #endif /* _FFR_MDS_NEGOTIATE */ 6289 #if _FFR_MEMSTAT 6290 /* Check free memory */ 6291 "_FFR_MEMSTAT", 6292 #endif /* _FFR_MEMSTAT */ 6293 #if _FFR_MILTER_CHECK 6294 "_FFR_MILTER_CHECK", 6295 #endif /* _FFR_MILTER_CHECK */ 6296 #if _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF 6297 /* 6298 ** milter_body() uses the same conversion algorithm as putbody() 6299 ** to translate the "local" df format (\n) to SMTP format (\r\n). 6300 ** However, putbody() and mime8to7() use different conversion 6301 ** algorithms. 6302 ** If the input date does not follow the SMTP standard 6303 ** (e.g., if it has "naked \r"s), then the output from putbody() 6304 ** and mime8to7() will most likely be different. 6305 ** By turning on this FFR milter_body() will try to "imitate" 6306 ** mime8to7(). 6307 ** Note: there is no (simple) way to deal with both conversions 6308 ** in a consistent manner. Moreover, as the "GiGo" principle applies, 6309 ** it's not really worth to fix it. 6310 */ 6311 6312 "_FFR_MILTER_CONVERT_ALL_LF_TO_CRLF", 6313 #endif /* _FFR_MILTER_CONVERT_ALL_LF_TO_CRLF */ 6314 #if _FFR_MILTER_CHECK_REJECTIONS_TOO 6315 /* 6316 ** Also send RCPTs that are rejected by check_rcpt to a milter 6317 ** (if requested during option negotiation). 6318 */ 6319 6320 "_FFR_MILTER_CHECK_REJECTIONS_TOO", 6321 #endif /* _FFR_MILTER_CHECK_REJECTIONS_TOO */ 6322 #if _FFR_MILTER_ENHSC 6323 /* extract enhanced status code from milter replies for dsn= logging */ 6324 "_FFR_MILTER_ENHSC", 6325 #endif /* _FFR_MILTER_ENHSC */ 6326 #if _FFR_MIME7TO8_OLD 6327 /* Old mime7to8 code, the new is broken for at least one example. */ 6328 "_FFR_MIME7TO8_OLD", 6329 #endif /* _FFR_MAX_SLEEP_TIME */ 6330 #if _FFR_MORE_MACROS 6331 /* allow more long macro names ("unprintable" characters). */ 6332 "_FFR_MORE_MACROS", 6333 #endif /* _FFR_MORE_MACROS */ 6334 #if _FFR_MSG_ACCEPT 6335 /* allow to override "Message accepted for delivery" */ 6336 "_FFR_MSG_ACCEPT", 6337 #endif /* _FFR_MSG_ACCEPT */ 6338 #if _FFR_NODELAYDSN_ON_HOLD 6339 /* Do not issue a DELAY DSN for mailers that use the hold flag. */ 6340 /* Steven Pitzl */ 6341 "_FFR_NODELAYDSN_ON_HOLD", 6342 #endif /* _FFR_NODELAYDSN_ON_HOLD */ 6343 #if _FFR_NO_PIPE 6344 /* Disable PIPELINING, delay client if used. */ 6345 "_FFR_NO_PIPE", 6346 #endif /* _FFR_NO_PIPE */ 6347 #if _FFR_LDAP_NETWORK_TIMEOUT 6348 /* set LDAP_OPT_NETWORK_TIMEOUT if available (-c) */ 6349 "_FFR_LDAP_NETWORK_TIMEOUT", 6350 #endif /* _FFR_LDAP_NETWORK_TIMEOUT */ 6351 #if _FFR_LOG_NTRIES 6352 /* log ntries=, from Nik Clayton of FreeBSD */ 6353 "_FFR_LOG_NTRIES", 6354 #endif /* _FFR_LOG_NTRIES */ 6355 #if _FFR_QF_PARANOIA 6356 "_FFR_QF_PARANOIA", 6357 #endif /* _FFR_QF_PARANOIA */ 6358 #if _FFR_QUEUEDELAY 6359 /* Exponential queue delay; disabled in 8.13 since it isn't used. */ 6360 "_FFR_QUEUEDELAY", 6361 #endif /* _FFR_QUEUEDELAY */ 6362 #if _FFR_QUEUE_GROUP_SORTORDER 6363 /* Allow QueueSortOrder per queue group. */ 6364 /* XXX: Still need to actually use qgrp->qg_sortorder */ 6365 "_FFR_QUEUE_GROUP_SORTORDER", 6366 #endif /* _FFR_QUEUE_GROUP_SORTORDER */ 6367 #if _FFR_QUEUE_MACRO 6368 /* Define {queue} macro. */ 6369 "_FFR_QUEUE_MACRO", 6370 #endif /* _FFR_QUEUE_MACRO */ 6371 #if _FFR_QUEUE_RUN_PARANOIA 6372 /* Additional checks when doing queue runs; interval of checks */ 6373 "_FFR_QUEUE_RUN_PARANOIA", 6374 #endif /* _FFR_QUEUE_RUN_PARANOIA */ 6375 #if _FFR_QUEUE_SCHED_DBG 6376 /* Debug output for the queue scheduler. */ 6377 "_FFR_QUEUE_SCHED_DBG", 6378 #endif /* _FFR_QUEUE_SCHED_DBG */ 6379 #if _FFR_RCPTTHROTDELAY 6380 /* configurable delay for BadRcptThrottle */ 6381 "_FFR_RCPTTHROTDELAY", 6382 #endif /* _FFR_RCPTTHROTDELAY */ 6383 #if _FFR_REDIRECTEMPTY 6384 /* 6385 ** envelope <> can't be sent to mailing lists, only owner- 6386 ** send spam of this type to owner- of the list 6387 ** ---- to stop spam from going to mailing lists. 6388 */ 6389 6390 "_FFR_REDIRECTEMPTY", 6391 #endif /* _FFR_REDIRECTEMPTY */ 6392 #if _FFR_REJECT_NUL_BYTE 6393 /* reject NUL bytes in body */ 6394 "_FFR_REJECT_NUL_BYTE", 6395 #endif /* _FFR_REJECT_NUL_BYTE */ 6396 #if _FFR_RESET_MACRO_GLOBALS 6397 /* Allow macro 'j' to be set dynamically via rulesets. */ 6398 "_FFR_RESET_MACRO_GLOBALS", 6399 #endif /* _FFR_RESET_MACRO_GLOBALS */ 6400 #if _FFR_RHS 6401 /* Random shuffle for queue sorting. */ 6402 "_FFR_RHS", 6403 #endif /* _FFR_RHS */ 6404 #if _FFR_RUNPQG 6405 /* 6406 ** allow -qGqueue_group -qp to work, i.e., 6407 ** restrict a persistent queue runner to a queue group. 6408 */ 6409 6410 "_FFR_RUNPQG", 6411 #endif /* _FFR_RUNPQG */ 6412 #if _FFR_SESSID 6413 /* session id (for logging) */ 6414 "_FFR_SESSID", 6415 #endif /* _FFR_SESSID */ 6416 #if _FFR_SHM_STATUS 6417 /* Donated code (unused). */ 6418 "_FFR_SHM_STATUS", 6419 #endif /* _FFR_SHM_STATUS */ 6420 #if _FFR_LDAP_SINGLEDN 6421 /* 6422 ** The LDAP database map code in Sendmail 8.12.10, when 6423 ** given the -1 switch, would match only a single DN, 6424 ** but was able to return multiple attributes for that 6425 ** DN. In Sendmail 8.13 this "bug" was corrected to 6426 ** only return if exactly one attribute matched. 6427 ** 6428 ** Unfortunately, our configuration uses the former 6429 ** behaviour. Attached is a relatively simple patch 6430 ** to 8.13.4 which adds a -2 switch (for lack of a 6431 ** better option) which returns the single dn/multiple 6432 ** attributes. 6433 ** 6434 ** Jeffrey T. Eaton, Carnegie-Mellon University 6435 */ 6436 6437 "_FFR_LDAP_SINGLEDN", 6438 #endif /* _FFR_LDAP_SINGLEDN */ 6439 #if _FFR_SKIP_DOMAINS 6440 /* process every N'th domain instead of every N'th message */ 6441 "_FFR_SKIP_DOMAINS", 6442 #endif /* _FFR_SKIP_DOMAINS */ 6443 #if _FFR_SLEEP_USE_SELECT 6444 /* Use select(2) in libsm/clock.c to emulate sleep(2) */ 6445 "_FFR_SLEEP_USE_SELECT ", 6446 #endif /* _FFR_SLEEP_USE_SELECT */ 6447 #if _FFR_SPT_ALIGN 6448 /* 6449 ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64 6450 ** bit alignment, so unless each piece of argv and envp is a multiple 6451 ** of 8 bytes (including terminating NULL), initsetproctitle() won't 6452 ** use any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE 6453 ** if you use this FFR. 6454 */ 6455 6456 /* Chris Adams of HiWAAY Informations Services */ 6457 "_FFR_SPT_ALIGN", 6458 #endif /* _FFR_SPT_ALIGN */ 6459 #if _FFR_SS_PER_DAEMON 6460 /* SuperSafe per DaemonPortOptions: 'T' (better letter?) */ 6461 "_FFR_SS_PER_DAEMON", 6462 #endif /* _FFR_SS_PER_DAEMON */ 6463 #if _FFR_TESTS 6464 /* enable some test code */ 6465 "_FFR_TESTS", 6466 #endif /* _FFR_TESTS */ 6467 #if _FFR_TIMERS 6468 /* Donated code (unused). */ 6469 "_FFR_TIMERS", 6470 #endif /* _FFR_TIMERS */ 6471 #if _FFR_TLS_1 6472 /* More STARTTLS options, e.g., secondary certs. */ 6473 "_FFR_TLS_1", 6474 #endif /* _FFR_TLS_1 */ 6475 #if _FFR_TRUSTED_QF 6476 /* 6477 ** If we don't own the file mark it as unsafe. 6478 ** However, allow TrustedUser to own it as well 6479 ** in case TrustedUser manipulates the queue. 6480 */ 6481 6482 "_FFR_TRUSTED_QF", 6483 #endif /* _FFR_TRUSTED_QF */ 6484 #if _FFR_USE_SEM_LOCKING 6485 "_FFR_USE_SEM_LOCKING", 6486 #endif /* _FFR_USE_SEM_LOCKING */ 6487 #if _FFR_USE_SETLOGIN 6488 /* Use setlogin() */ 6489 /* Peter Philipp */ 6490 "_FFR_USE_SETLOGIN", 6491 #endif /* _FFR_USE_SETLOGIN */ 6492 NULL 6493 }; 6494 6495