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