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