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