1 /* 2 * Copyright (c) 1998-2004 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 * $FreeBSD$ 13 */ 14 15 #include <sendmail.h> 16 17 SM_RCSID("@(#)$Id: conf.c,v 8.1052 2004/12/15 22:45:55 ca Exp $") 18 19 #include <sendmail/pathnames.h> 20 #if NEWDB 21 # include "sm/bdb.h" 22 #endif /* NEWDB */ 23 24 # include <sys/ioctl.h> 25 # include <sys/param.h> 26 27 #include <limits.h> 28 #if NETINET || NETINET6 29 # include <arpa/inet.h> 30 #endif /* NETINET || NETINET6 */ 31 #if HASULIMIT && defined(HPUX11) 32 # include <ulimit.h> 33 #endif /* HASULIMIT && defined(HPUX11) */ 34 35 static void setupmaps __P((void)); 36 static void setupmailers __P((void)); 37 static void setupqueues __P((void)); 38 static int get_num_procs_online __P((void)); 39 static int add_hostnames __P((SOCKADDR *)); 40 41 #if NETINET6 && NEEDSGETIPNODE 42 static struct hostent *getipnodebyname __P((char *, int, int, int *)); 43 static struct hostent *getipnodebyaddr __P((char *, int, int, int *)); 44 #endif /* NETINET6 && NEEDSGETIPNODE */ 45 46 47 /* 48 ** CONF.C -- Sendmail Configuration Tables. 49 ** 50 ** Defines the configuration of this installation. 51 ** 52 ** Configuration Variables: 53 ** HdrInfo -- a table describing well-known header fields. 54 ** Each entry has the field name and some flags, 55 ** which are described in sendmail.h. 56 ** 57 ** Notes: 58 ** I have tried to put almost all the reasonable 59 ** configuration information into the configuration 60 ** file read at runtime. My intent is that anything 61 ** here is a function of the version of UNIX you 62 ** are running, or is really static -- for example 63 ** the headers are a superset of widely used 64 ** protocols. If you find yourself playing with 65 ** this file too much, you may be making a mistake! 66 */ 67 68 69 /* 70 ** Header info table 71 ** Final (null) entry contains the flags used for any other field. 72 ** 73 ** Not all of these are actually handled specially by sendmail 74 ** at this time. They are included as placeholders, to let 75 ** you know that "someday" I intend to have sendmail do 76 ** something with them. 77 */ 78 79 struct hdrinfo HdrInfo[] = 80 { 81 /* originator fields, most to least significant */ 82 { "resent-sender", H_FROM|H_RESENT, NULL }, 83 { "resent-from", H_FROM|H_RESENT, NULL }, 84 { "resent-reply-to", H_FROM|H_RESENT, NULL }, 85 { "sender", H_FROM, NULL }, 86 { "from", H_FROM, NULL }, 87 { "reply-to", H_FROM, NULL }, 88 { "errors-to", H_FROM|H_ERRORSTO, NULL }, 89 { "full-name", H_ACHECK, NULL }, 90 { "return-receipt-to", H_RECEIPTTO, NULL }, 91 { "delivery-receipt-to", H_RECEIPTTO, NULL }, 92 { "disposition-notification-to", H_FROM, NULL }, 93 94 /* destination fields */ 95 { "to", H_RCPT, NULL }, 96 { "resent-to", H_RCPT|H_RESENT, NULL }, 97 { "cc", H_RCPT, NULL }, 98 { "resent-cc", H_RCPT|H_RESENT, NULL }, 99 { "bcc", H_RCPT|H_BCC, NULL }, 100 { "resent-bcc", H_RCPT|H_BCC|H_RESENT, NULL }, 101 { "apparently-to", H_RCPT, NULL }, 102 103 /* message identification and control */ 104 { "message-id", 0, NULL }, 105 { "resent-message-id", H_RESENT, NULL }, 106 { "message", H_EOH, NULL }, 107 { "text", H_EOH, NULL }, 108 109 /* date fields */ 110 { "date", 0, NULL }, 111 { "resent-date", H_RESENT, NULL }, 112 113 /* trace fields */ 114 { "received", H_TRACE|H_FORCE, NULL }, 115 { "x400-received", H_TRACE|H_FORCE, NULL }, 116 { "via", H_TRACE|H_FORCE, NULL }, 117 { "mail-from", H_TRACE|H_FORCE, NULL }, 118 119 /* miscellaneous fields */ 120 { "comments", H_FORCE|H_ENCODABLE, NULL }, 121 { "return-path", H_FORCE|H_ACHECK|H_BINDLATE, NULL }, 122 { "content-transfer-encoding", H_CTE, NULL }, 123 { "content-type", H_CTYPE, NULL }, 124 { "content-length", H_ACHECK, NULL }, 125 { "subject", H_ENCODABLE, NULL }, 126 { "x-authentication-warning", H_FORCE, NULL }, 127 128 { NULL, 0, NULL } 129 }; 130 131 132 133 /* 134 ** Privacy values 135 */ 136 137 struct prival PrivacyValues[] = 138 { 139 { "public", PRIV_PUBLIC }, 140 { "needmailhelo", PRIV_NEEDMAILHELO }, 141 { "needexpnhelo", PRIV_NEEDEXPNHELO }, 142 { "needvrfyhelo", PRIV_NEEDVRFYHELO }, 143 { "noexpn", PRIV_NOEXPN }, 144 { "novrfy", PRIV_NOVRFY }, 145 { "restrictexpand", PRIV_RESTRICTEXPAND }, 146 { "restrictmailq", PRIV_RESTRICTMAILQ }, 147 { "restrictqrun", PRIV_RESTRICTQRUN }, 148 { "noetrn", PRIV_NOETRN }, 149 { "noverb", PRIV_NOVERB }, 150 { "authwarnings", PRIV_AUTHWARNINGS }, 151 { "noreceipts", PRIV_NORECEIPTS }, 152 { "nobodyreturn", PRIV_NOBODYRETN }, 153 { "goaway", PRIV_GOAWAY }, 154 #if _FFR_PRIV_NOACTUALRECIPIENT 155 { "noactualrecipient", PRIV_NOACTUALRECIPIENT }, 156 #endif /* _FFR_PRIV_NOACTUALRECIPIENT */ 157 { NULL, 0 } 158 }; 159 160 /* 161 ** DontBlameSendmail values 162 */ 163 164 struct dbsval DontBlameSendmailValues[] = 165 { 166 { "safe", DBS_SAFE }, 167 { "assumesafechown", DBS_ASSUMESAFECHOWN }, 168 { "groupwritabledirpathsafe", DBS_GROUPWRITABLEDIRPATHSAFE }, 169 { "groupwritableforwardfilesafe", 170 DBS_GROUPWRITABLEFORWARDFILESAFE }, 171 { "groupwritableincludefilesafe", 172 DBS_GROUPWRITABLEINCLUDEFILESAFE }, 173 { "groupwritablealiasfile", DBS_GROUPWRITABLEALIASFILE }, 174 { "worldwritablealiasfile", DBS_WORLDWRITABLEALIASFILE }, 175 { "forwardfileinunsafedirpath", DBS_FORWARDFILEINUNSAFEDIRPATH }, 176 { "includefileinunsafedirpath", DBS_INCLUDEFILEINUNSAFEDIRPATH }, 177 { "mapinunsafedirpath", DBS_MAPINUNSAFEDIRPATH }, 178 { "linkedaliasfileinwritabledir", 179 DBS_LINKEDALIASFILEINWRITABLEDIR }, 180 { "linkedclassfileinwritabledir", 181 DBS_LINKEDCLASSFILEINWRITABLEDIR }, 182 { "linkedforwardfileinwritabledir", 183 DBS_LINKEDFORWARDFILEINWRITABLEDIR }, 184 { "linkedincludefileinwritabledir", 185 DBS_LINKEDINCLUDEFILEINWRITABLEDIR }, 186 { "linkedmapinwritabledir", DBS_LINKEDMAPINWRITABLEDIR }, 187 { "linkedserviceswitchfileinwritabledir", 188 DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR }, 189 { "filedeliverytohardlink", DBS_FILEDELIVERYTOHARDLINK }, 190 { "filedeliverytosymlink", DBS_FILEDELIVERYTOSYMLINK }, 191 { "writemaptohardlink", DBS_WRITEMAPTOHARDLINK }, 192 { "writemaptosymlink", DBS_WRITEMAPTOSYMLINK }, 193 { "writestatstohardlink", DBS_WRITESTATSTOHARDLINK }, 194 { "writestatstosymlink", DBS_WRITESTATSTOSYMLINK }, 195 { "forwardfileingroupwritabledirpath", 196 DBS_FORWARDFILEINGROUPWRITABLEDIRPATH }, 197 { "includefileingroupwritabledirpath", 198 DBS_INCLUDEFILEINGROUPWRITABLEDIRPATH }, 199 { "classfileinunsafedirpath", DBS_CLASSFILEINUNSAFEDIRPATH }, 200 { "errorheaderinunsafedirpath", DBS_ERRORHEADERINUNSAFEDIRPATH }, 201 { "helpfileinunsafedirpath", DBS_HELPFILEINUNSAFEDIRPATH }, 202 { "forwardfileinunsafedirpathsafe", 203 DBS_FORWARDFILEINUNSAFEDIRPATHSAFE }, 204 { "includefileinunsafedirpathsafe", 205 DBS_INCLUDEFILEINUNSAFEDIRPATHSAFE }, 206 { "runprograminunsafedirpath", DBS_RUNPROGRAMINUNSAFEDIRPATH }, 207 { "runwritableprogram", DBS_RUNWRITABLEPROGRAM }, 208 { "nonrootsafeaddr", DBS_NONROOTSAFEADDR }, 209 { "truststickybit", DBS_TRUSTSTICKYBIT }, 210 { "dontwarnforwardfileinunsafedirpath", 211 DBS_DONTWARNFORWARDFILEINUNSAFEDIRPATH }, 212 { "insufficiententropy", DBS_INSUFFICIENTENTROPY }, 213 { "groupreadablesasldbfile", DBS_GROUPREADABLESASLDBFILE }, 214 { "groupwritablesasldbfile", DBS_GROUPWRITABLESASLDBFILE }, 215 { "groupwritableforwardfile", DBS_GROUPWRITABLEFORWARDFILE }, 216 { "groupwritableincludefile", DBS_GROUPWRITABLEINCLUDEFILE }, 217 { "worldwritableforwardfile", DBS_WORLDWRITABLEFORWARDFILE }, 218 { "worldwritableincludefile", DBS_WORLDWRITABLEINCLUDEFILE }, 219 { "groupreadablekeyfile", DBS_GROUPREADABLEKEYFILE }, 220 #if _FFR_GROUPREADABLEAUTHINFOFILE 221 { "groupreadableadefaultauthinfofile", 222 DBS_GROUPREADABLEAUTHINFOFILE }, 223 #endif /* _FFR_GROUPREADABLEAUTHINFOFILE */ 224 { NULL, 0 } 225 }; 226 227 /* 228 ** Miscellaneous stuff. 229 */ 230 231 int DtableSize = 50; /* max open files; reset in 4.2bsd */ 232 /* 233 ** SETDEFAULTS -- set default values 234 ** 235 ** Some of these must be initialized using direct code since they 236 ** depend on run-time values. So let's do all of them this way. 237 ** 238 ** Parameters: 239 ** e -- the default envelope. 240 ** 241 ** Returns: 242 ** none. 243 ** 244 ** Side Effects: 245 ** Initializes a bunch of global variables to their 246 ** default values. 247 */ 248 249 #define MINUTES * 60 250 #define HOURS * 60 MINUTES 251 #define DAYS * 24 HOURS 252 253 #ifndef MAXRULERECURSION 254 # define MAXRULERECURSION 50 /* max ruleset recursion depth */ 255 #endif /* ! MAXRULERECURSION */ 256 257 void 258 setdefaults(e) 259 register ENVELOPE *e; 260 { 261 int i; 262 int numprocs; 263 struct passwd *pw; 264 265 numprocs = get_num_procs_online(); 266 SpaceSub = ' '; /* option B */ 267 QueueLA = 8 * numprocs; /* option x */ 268 RefuseLA = 12 * numprocs; /* option X */ 269 WkRecipFact = 30000L; /* option y */ 270 WkClassFact = 1800L; /* option z */ 271 WkTimeFact = 90000L; /* option Z */ 272 QueueFactor = WkRecipFact * 20; /* option q */ 273 QueueMode = QM_NORMAL; /* what queue items to act upon */ 274 FileMode = (RealUid != geteuid()) ? 0644 : 0600; 275 /* option F */ 276 QueueFileMode = (RealUid != geteuid()) ? 0644 : 0600; 277 /* option QueueFileMode */ 278 279 if (((pw = sm_getpwnam("mailnull")) != NULL && pw->pw_uid != 0) || 280 ((pw = sm_getpwnam("sendmail")) != NULL && pw->pw_uid != 0) || 281 ((pw = sm_getpwnam("daemon")) != NULL && pw->pw_uid != 0)) 282 { 283 DefUid = pw->pw_uid; /* option u */ 284 DefGid = pw->pw_gid; /* option g */ 285 DefUser = newstr(pw->pw_name); 286 } 287 else 288 { 289 DefUid = 1; /* option u */ 290 DefGid = 1; /* option g */ 291 setdefuser(); 292 } 293 TrustedUid = 0; 294 if (tTd(37, 4)) 295 sm_dprintf("setdefaults: DefUser=%s, DefUid=%d, DefGid=%d\n", 296 DefUser != NULL ? DefUser : "<1:1>", 297 (int) DefUid, (int) DefGid); 298 CheckpointInterval = 10; /* option C */ 299 MaxHopCount = 25; /* option h */ 300 set_delivery_mode(SM_FORK, e); /* option d */ 301 e->e_errormode = EM_PRINT; /* option e */ 302 e->e_qgrp = NOQGRP; 303 e->e_qdir = NOQDIR; 304 e->e_xfqgrp = NOQGRP; 305 e->e_xfqdir = NOQDIR; 306 e->e_ctime = curtime(); 307 SevenBitInput = false; /* option 7 */ 308 MaxMciCache = 1; /* option k */ 309 MciCacheTimeout = 5 MINUTES; /* option K */ 310 LogLevel = 9; /* option L */ 311 #if MILTER 312 MilterLogLevel = -1; 313 #endif /* MILTER */ 314 inittimeouts(NULL, false); /* option r */ 315 PrivacyFlags = PRIV_PUBLIC; /* option p */ 316 MeToo = true; /* option m */ 317 SendMIMEErrors = true; /* option f */ 318 SuperSafe = SAFE_REALLY; /* option s */ 319 clrbitmap(DontBlameSendmail); /* DontBlameSendmail option */ 320 #if MIME8TO7 321 MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */ 322 #else /* MIME8TO7 */ 323 MimeMode = MM_PASS8BIT; 324 #endif /* MIME8TO7 */ 325 for (i = 0; i < MAXTOCLASS; i++) 326 { 327 TimeOuts.to_q_return[i] = 5 DAYS; /* option T */ 328 TimeOuts.to_q_warning[i] = 0; /* option T */ 329 } 330 ServiceSwitchFile = "/etc/mail/service.switch"; 331 ServiceCacheMaxAge = (time_t) 10; 332 HostsFile = _PATH_HOSTS; 333 PidFile = newstr(_PATH_SENDMAILPID); 334 MustQuoteChars = "@,;:\\()[].'"; 335 MciInfoTimeout = 30 MINUTES; 336 MaxRuleRecursion = MAXRULERECURSION; 337 MaxAliasRecursion = 10; 338 MaxMacroRecursion = 10; 339 ColonOkInAddr = true; 340 DontLockReadFiles = true; 341 DontProbeInterfaces = DPI_PROBEALL; 342 DoubleBounceAddr = "postmaster"; 343 MaxHeadersLength = MAXHDRSLEN; 344 MaxMimeHeaderLength = MAXLINE; 345 MaxMimeFieldLength = MaxMimeHeaderLength / 2; 346 MaxForwardEntries = 0; 347 FastSplit = 1; 348 #if SASL 349 AuthMechanisms = newstr(AUTH_MECHANISMS); 350 AuthRealm = NULL; 351 MaxSLBits = INT_MAX; 352 #endif /* SASL */ 353 #if STARTTLS 354 TLS_Srv_Opts = TLS_I_SRV; 355 #endif /* STARTTLS */ 356 #ifdef HESIOD_INIT 357 HesiodContext = NULL; 358 #endif /* HESIOD_INIT */ 359 #if NETINET6 360 /* Detect if IPv6 is available at run time */ 361 i = socket(AF_INET6, SOCK_STREAM, 0); 362 if (i >= 0) 363 { 364 InetMode = AF_INET6; 365 (void) close(i); 366 } 367 else 368 InetMode = AF_INET; 369 #else /* NETINET6 */ 370 InetMode = AF_INET; 371 #endif /* NETINET6 */ 372 ControlSocketName = NULL; 373 memset(&ConnectOnlyTo, '\0', sizeof ConnectOnlyTo); 374 DataFileBufferSize = 4096; 375 XscriptFileBufferSize = 4096; 376 for (i = 0; i < MAXRWSETS; i++) 377 RuleSetNames[i] = NULL; 378 #if MILTER 379 InputFilters[0] = NULL; 380 #endif /* MILTER */ 381 RejectLogInterval = 3 HOURS; 382 #if REQUIRES_DIR_FSYNC 383 RequiresDirfsync = true; 384 #endif /* REQUIRES_DIR_FSYNC */ 385 ConnectionRateWindowSize = 60; 386 setupmaps(); 387 setupqueues(); 388 setupmailers(); 389 setupheaders(); 390 } 391 392 393 /* 394 ** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups()) 395 */ 396 397 void 398 setdefuser() 399 { 400 struct passwd *defpwent; 401 static char defuserbuf[40]; 402 403 DefUser = defuserbuf; 404 defpwent = sm_getpwuid(DefUid); 405 (void) sm_strlcpy(defuserbuf, 406 (defpwent == NULL || defpwent->pw_name == NULL) 407 ? "nobody" : defpwent->pw_name, 408 sizeof defuserbuf); 409 if (tTd(37, 4)) 410 sm_dprintf("setdefuser: DefUid=%d, DefUser=%s\n", 411 (int) DefUid, DefUser); 412 } 413 /* 414 ** SETUPQUEUES -- initialize default queues 415 ** 416 ** The mqueue QUEUE structure gets filled in after readcf() but 417 ** we need something to point to now for the mailer setup, 418 ** which use "mqueue" as default queue. 419 */ 420 421 static void 422 setupqueues() 423 { 424 char buf[100]; 425 426 MaxRunnersPerQueue = 1; 427 (void) sm_strlcpy(buf, "mqueue, P=/var/spool/mqueue", sizeof buf); 428 makequeue(buf, false); 429 } 430 /* 431 ** SETUPMAILERS -- initialize default mailers 432 */ 433 434 static void 435 setupmailers() 436 { 437 char buf[100]; 438 439 (void) sm_strlcpy(buf, "prog, P=/bin/sh, F=lsouDq9, T=X-Unix/X-Unix/X-Unix, A=sh -c \201u", 440 sizeof buf); 441 makemailer(buf); 442 443 (void) sm_strlcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=X-Unix/X-Unix/X-Unix, A=FILE \201u", 444 sizeof buf); 445 makemailer(buf); 446 447 (void) sm_strlcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u", 448 sizeof buf); 449 makemailer(buf); 450 initerrmailers(); 451 } 452 /* 453 ** SETUPMAPS -- set up map classes 454 */ 455 456 #define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \ 457 { \ 458 extern bool parse __P((MAP *, char *)); \ 459 extern bool open __P((MAP *, int)); \ 460 extern void close __P((MAP *)); \ 461 extern char *lookup __P((MAP *, char *, char **, int *)); \ 462 extern void store __P((MAP *, char *, char *)); \ 463 s = stab(name, ST_MAPCLASS, ST_ENTER); \ 464 s->s_mapclass.map_cname = name; \ 465 s->s_mapclass.map_ext = ext; \ 466 s->s_mapclass.map_cflags = flags; \ 467 s->s_mapclass.map_parse = parse; \ 468 s->s_mapclass.map_open = open; \ 469 s->s_mapclass.map_close = close; \ 470 s->s_mapclass.map_lookup = lookup; \ 471 s->s_mapclass.map_store = store; \ 472 } 473 474 static void 475 setupmaps() 476 { 477 register STAB *s; 478 479 #if NEWDB 480 # if DB_VERSION_MAJOR > 1 481 int major_v, minor_v, patch_v; 482 483 (void) db_version(&major_v, &minor_v, &patch_v); 484 if (major_v != DB_VERSION_MAJOR || minor_v != DB_VERSION_MINOR) 485 { 486 errno = 0; 487 syserr("Berkeley DB version mismatch: compiled against %d.%d.%d, run-time linked against %d.%d.%d", 488 DB_VERSION_MAJOR, DB_VERSION_MINOR, DB_VERSION_PATCH, 489 major_v, minor_v, patch_v); 490 } 491 # endif /* DB_VERSION_MAJOR > 1 */ 492 493 MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 494 map_parseargs, hash_map_open, db_map_close, 495 db_map_lookup, db_map_store); 496 497 MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE, 498 map_parseargs, bt_map_open, db_map_close, 499 db_map_lookup, db_map_store); 500 #endif /* NEWDB */ 501 502 #if NDBM 503 MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE, 504 map_parseargs, ndbm_map_open, ndbm_map_close, 505 ndbm_map_lookup, ndbm_map_store); 506 #endif /* NDBM */ 507 508 #if NIS 509 MAPDEF("nis", NULL, MCF_ALIASOK, 510 map_parseargs, nis_map_open, null_map_close, 511 nis_map_lookup, null_map_store); 512 #endif /* NIS */ 513 514 #if NISPLUS 515 MAPDEF("nisplus", NULL, MCF_ALIASOK, 516 map_parseargs, nisplus_map_open, null_map_close, 517 nisplus_map_lookup, null_map_store); 518 #endif /* NISPLUS */ 519 520 #if LDAPMAP 521 MAPDEF("ldap", NULL, MCF_ALIASOK|MCF_NOTPERSIST, 522 ldapmap_parseargs, ldapmap_open, ldapmap_close, 523 ldapmap_lookup, null_map_store); 524 #endif /* LDAPMAP */ 525 526 #if PH_MAP 527 MAPDEF("ph", NULL, MCF_NOTPERSIST, 528 ph_map_parseargs, ph_map_open, ph_map_close, 529 ph_map_lookup, null_map_store); 530 #endif /* PH_MAP */ 531 532 #if MAP_NSD 533 /* IRIX 6.5 nsd support */ 534 MAPDEF("nsd", NULL, MCF_ALIASOK, 535 map_parseargs, null_map_open, null_map_close, 536 nsd_map_lookup, null_map_store); 537 #endif /* MAP_NSD */ 538 539 #if HESIOD 540 MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY, 541 map_parseargs, hes_map_open, hes_map_close, 542 hes_map_lookup, null_map_store); 543 #endif /* HESIOD */ 544 545 #if NETINFO 546 MAPDEF("netinfo", NULL, MCF_ALIASOK, 547 map_parseargs, ni_map_open, null_map_close, 548 ni_map_lookup, null_map_store); 549 #endif /* NETINFO */ 550 551 #if 0 552 MAPDEF("dns", NULL, 0, 553 dns_map_init, null_map_open, null_map_close, 554 dns_map_lookup, null_map_store); 555 #endif /* 0 */ 556 557 #if NAMED_BIND 558 # if DNSMAP 559 # if _FFR_DNSMAP_ALIASABLE 560 MAPDEF("dns", NULL, MCF_ALIASOK, 561 dns_map_parseargs, dns_map_open, null_map_close, 562 dns_map_lookup, null_map_store); 563 # else /* _FFR_DNSMAP_ALIASABLE */ 564 MAPDEF("dns", NULL, 0, 565 dns_map_parseargs, dns_map_open, null_map_close, 566 dns_map_lookup, null_map_store); 567 # endif /* _FFR_DNSMAP_ALIASABLE */ 568 # endif /* DNSMAP */ 569 #endif /* NAMED_BIND */ 570 571 #if NAMED_BIND 572 /* best MX DNS lookup */ 573 MAPDEF("bestmx", NULL, MCF_OPTFILE, 574 map_parseargs, null_map_open, null_map_close, 575 bestmx_map_lookup, null_map_store); 576 #endif /* NAMED_BIND */ 577 578 MAPDEF("host", NULL, 0, 579 host_map_init, null_map_open, null_map_close, 580 host_map_lookup, null_map_store); 581 582 MAPDEF("text", NULL, MCF_ALIASOK, 583 map_parseargs, text_map_open, null_map_close, 584 text_map_lookup, null_map_store); 585 586 MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY, 587 map_parseargs, stab_map_open, null_map_close, 588 stab_map_lookup, stab_map_store); 589 590 MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE, 591 map_parseargs, impl_map_open, impl_map_close, 592 impl_map_lookup, impl_map_store); 593 594 /* access to system passwd file */ 595 MAPDEF("user", NULL, MCF_OPTFILE, 596 map_parseargs, user_map_open, null_map_close, 597 user_map_lookup, null_map_store); 598 599 /* dequote map */ 600 MAPDEF("dequote", NULL, 0, 601 dequote_init, null_map_open, null_map_close, 602 dequote_map, null_map_store); 603 604 #if MAP_REGEX 605 MAPDEF("regex", NULL, 0, 606 regex_map_init, null_map_open, null_map_close, 607 regex_map_lookup, null_map_store); 608 #endif /* MAP_REGEX */ 609 610 #if USERDB 611 /* user database */ 612 MAPDEF("userdb", ".db", 0, 613 map_parseargs, null_map_open, null_map_close, 614 udb_map_lookup, null_map_store); 615 #endif /* USERDB */ 616 617 /* arbitrary programs */ 618 MAPDEF("program", NULL, MCF_ALIASOK, 619 map_parseargs, null_map_open, null_map_close, 620 prog_map_lookup, null_map_store); 621 622 /* sequenced maps */ 623 MAPDEF("sequence", NULL, MCF_ALIASOK, 624 seq_map_parse, null_map_open, null_map_close, 625 seq_map_lookup, seq_map_store); 626 627 /* switched interface to sequenced maps */ 628 MAPDEF("switch", NULL, MCF_ALIASOK, 629 map_parseargs, switch_map_open, null_map_close, 630 seq_map_lookup, seq_map_store); 631 632 /* null map lookup -- really for internal use only */ 633 MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE, 634 map_parseargs, null_map_open, null_map_close, 635 null_map_lookup, null_map_store); 636 637 /* syslog map -- logs information to syslog */ 638 MAPDEF("syslog", NULL, 0, 639 syslog_map_parseargs, null_map_open, null_map_close, 640 syslog_map_lookup, null_map_store); 641 642 /* macro storage map -- rulesets can set macros */ 643 MAPDEF("macro", NULL, 0, 644 dequote_init, null_map_open, null_map_close, 645 macro_map_lookup, null_map_store); 646 647 /* arithmetic map -- add/subtract/compare */ 648 MAPDEF("arith", NULL, 0, 649 dequote_init, null_map_open, null_map_close, 650 arith_map_lookup, null_map_store); 651 652 #if SOCKETMAP 653 /* arbitrary daemons */ 654 MAPDEF("socket", NULL, MCF_ALIASOK, 655 map_parseargs, socket_map_open, socket_map_close, 656 socket_map_lookup, null_map_store); 657 #endif /* SOCKETMAP */ 658 659 if (tTd(38, 2)) 660 { 661 /* bogus map -- always return tempfail */ 662 MAPDEF("bogus", NULL, MCF_ALIASOK|MCF_OPTFILE, 663 map_parseargs, null_map_open, null_map_close, 664 bogus_map_lookup, null_map_store); 665 } 666 } 667 668 #undef MAPDEF 669 /* 670 ** INITHOSTMAPS -- initial host-dependent maps 671 ** 672 ** This should act as an interface to any local service switch 673 ** provided by the host operating system. 674 ** 675 ** Parameters: 676 ** none 677 ** 678 ** Returns: 679 ** none 680 ** 681 ** Side Effects: 682 ** Should define maps "host" and "users" as necessary 683 ** for this OS. If they are not defined, they will get 684 ** a default value later. It should check to make sure 685 ** they are not defined first, since it's possible that 686 ** the config file has provided an override. 687 */ 688 689 void 690 inithostmaps() 691 { 692 register int i; 693 int nmaps; 694 char *maptype[MAXMAPSTACK]; 695 short mapreturn[MAXMAPACTIONS]; 696 char buf[MAXLINE]; 697 698 /* 699 ** Set up default hosts maps. 700 */ 701 702 #if 0 703 nmaps = switch_map_find("hosts", maptype, mapreturn); 704 for (i = 0; i < nmaps; i++) 705 { 706 if (strcmp(maptype[i], "files") == 0 && 707 stab("hosts.files", ST_MAP, ST_FIND) == NULL) 708 { 709 (void) sm_strlcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts", 710 sizeof buf); 711 (void) makemapentry(buf); 712 } 713 # if NAMED_BIND 714 else if (strcmp(maptype[i], "dns") == 0 && 715 stab("hosts.dns", ST_MAP, ST_FIND) == NULL) 716 { 717 (void) sm_strlcpy(buf, "hosts.dns dns A", sizeof buf); 718 (void) makemapentry(buf); 719 } 720 # endif /* NAMED_BIND */ 721 # if NISPLUS 722 else if (strcmp(maptype[i], "nisplus") == 0 && 723 stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL) 724 { 725 (void) sm_strlcpy(buf, "hosts.nisplus nisplus -k name -v address hosts.org_dir", 726 sizeof buf); 727 (void) makemapentry(buf); 728 } 729 # endif /* NISPLUS */ 730 # if NIS 731 else if (strcmp(maptype[i], "nis") == 0 && 732 stab("hosts.nis", ST_MAP, ST_FIND) == NULL) 733 { 734 (void) sm_strlcpy(buf, "hosts.nis nis -k 0 -v 1 hosts.byname", 735 sizeof buf); 736 (void) makemapentry(buf); 737 } 738 # endif /* NIS */ 739 # if NETINFO 740 else if (strcmp(maptype[i], "netinfo") == 0 && 741 stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL) 742 { 743 (void) sm_strlcpy(buf, "hosts.netinfo netinfo -v name /machines", 744 sizeof buf); 745 (void) makemapentry(buf); 746 } 747 # endif /* NETINFO */ 748 } 749 #endif /* 0 */ 750 751 /* 752 ** Make sure we have a host map. 753 */ 754 755 if (stab("host", ST_MAP, ST_FIND) == NULL) 756 { 757 /* user didn't initialize: set up host map */ 758 (void) sm_strlcpy(buf, "host host", sizeof buf); 759 #if NAMED_BIND 760 if (ConfigLevel >= 2) 761 (void) sm_strlcat(buf, " -a. -D", sizeof buf); 762 #endif /* NAMED_BIND */ 763 (void) makemapentry(buf); 764 } 765 766 /* 767 ** Set up default aliases maps 768 */ 769 770 nmaps = switch_map_find("aliases", maptype, mapreturn); 771 for (i = 0; i < nmaps; i++) 772 { 773 if (strcmp(maptype[i], "files") == 0 && 774 stab("aliases.files", ST_MAP, ST_FIND) == NULL) 775 { 776 (void) sm_strlcpy(buf, "aliases.files null", 777 sizeof buf); 778 (void) makemapentry(buf); 779 } 780 #if NISPLUS 781 else if (strcmp(maptype[i], "nisplus") == 0 && 782 stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL) 783 { 784 (void) sm_strlcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion mail_aliases.org_dir", 785 sizeof buf); 786 (void) makemapentry(buf); 787 } 788 #endif /* NISPLUS */ 789 #if NIS 790 else if (strcmp(maptype[i], "nis") == 0 && 791 stab("aliases.nis", ST_MAP, ST_FIND) == NULL) 792 { 793 (void) sm_strlcpy(buf, "aliases.nis nis mail.aliases", 794 sizeof buf); 795 (void) makemapentry(buf); 796 } 797 #endif /* NIS */ 798 #if NETINFO 799 else if (strcmp(maptype[i], "netinfo") == 0 && 800 stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL) 801 { 802 (void) sm_strlcpy(buf, "aliases.netinfo netinfo -z, /aliases", 803 sizeof buf); 804 (void) makemapentry(buf); 805 } 806 #endif /* NETINFO */ 807 #if HESIOD 808 else if (strcmp(maptype[i], "hesiod") == 0 && 809 stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL) 810 { 811 (void) sm_strlcpy(buf, "aliases.hesiod hesiod aliases", 812 sizeof buf); 813 (void) makemapentry(buf); 814 } 815 #endif /* HESIOD */ 816 } 817 if (stab("aliases", ST_MAP, ST_FIND) == NULL) 818 { 819 (void) sm_strlcpy(buf, "aliases switch aliases", sizeof buf); 820 (void) makemapentry(buf); 821 } 822 823 #if 0 /* "user" map class is a better choice */ 824 /* 825 ** Set up default users maps. 826 */ 827 828 nmaps = switch_map_find("passwd", maptype, mapreturn); 829 for (i = 0; i < nmaps; i++) 830 { 831 if (strcmp(maptype[i], "files") == 0 && 832 stab("users.files", ST_MAP, ST_FIND) == NULL) 833 { 834 (void) sm_strlcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd", 835 sizeof buf); 836 (void) makemapentry(buf); 837 } 838 # if NISPLUS 839 else if (strcmp(maptype[i], "nisplus") == 0 && 840 stab("users.nisplus", ST_MAP, ST_FIND) == NULL) 841 { 842 (void) sm_strlcpy(buf, "users.nisplus nisplus -m -kname -vhome passwd.org_dir", 843 sizeof buf); 844 (void) makemapentry(buf); 845 } 846 # endif /* NISPLUS */ 847 # if NIS 848 else if (strcmp(maptype[i], "nis") == 0 && 849 stab("users.nis", ST_MAP, ST_FIND) == NULL) 850 { 851 (void) sm_strlcpy(buf, "users.nis nis -m passwd.byname", 852 sizeof buf); 853 (void) makemapentry(buf); 854 } 855 # endif /* NIS */ 856 # if HESIOD 857 else if (strcmp(maptype[i], "hesiod") == 0 && 858 stab("users.hesiod", ST_MAP, ST_FIND) == NULL) 859 { 860 (void) sm_strlcpy(buf, "users.hesiod hesiod", sizeof buf); 861 (void) makemapentry(buf); 862 } 863 # endif /* HESIOD */ 864 } 865 if (stab("users", ST_MAP, ST_FIND) == NULL) 866 { 867 (void) sm_strlcpy(buf, "users switch -m passwd", sizeof buf); 868 (void) makemapentry(buf); 869 } 870 #endif /* 0 */ 871 } 872 /* 873 ** SWITCH_MAP_FIND -- find the list of types associated with a map 874 ** 875 ** This is the system-dependent interface to the service switch. 876 ** 877 ** Parameters: 878 ** service -- the name of the service of interest. 879 ** maptype -- an out-array of strings containing the types 880 ** of access to use for this service. There can 881 ** be at most MAXMAPSTACK types for a single service. 882 ** mapreturn -- an out-array of return information bitmaps 883 ** for the map. 884 ** 885 ** Returns: 886 ** The number of map types filled in, or -1 for failure. 887 ** 888 ** Side effects: 889 ** Preserves errno so nothing in the routine clobbers it. 890 */ 891 892 #if defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) 893 # define _USE_SUN_NSSWITCH_ 894 #endif /* defined(SOLARIS) || (defined(sony_news) && defined(__svr4)) */ 895 896 #if _FFR_HPUX_NSSWITCH 897 # ifdef __hpux 898 # define _USE_SUN_NSSWITCH_ 899 # endif /* __hpux */ 900 #endif /* _FFR_HPUX_NSSWITCH */ 901 902 #ifdef _USE_SUN_NSSWITCH_ 903 # include <nsswitch.h> 904 #endif /* _USE_SUN_NSSWITCH_ */ 905 906 #if defined(ultrix) || (defined(__osf__) && defined(__alpha)) 907 # define _USE_DEC_SVC_CONF_ 908 #endif /* defined(ultrix) || (defined(__osf__) && defined(__alpha)) */ 909 910 #ifdef _USE_DEC_SVC_CONF_ 911 # include <sys/svcinfo.h> 912 #endif /* _USE_DEC_SVC_CONF_ */ 913 914 int 915 switch_map_find(service, maptype, mapreturn) 916 char *service; 917 char *maptype[MAXMAPSTACK]; 918 short mapreturn[MAXMAPACTIONS]; 919 { 920 int svcno = 0; 921 int save_errno = errno; 922 923 #ifdef _USE_SUN_NSSWITCH_ 924 struct __nsw_switchconfig *nsw_conf; 925 enum __nsw_parse_err pserr; 926 struct __nsw_lookup *lk; 927 static struct __nsw_lookup lkp0 = 928 { "files", {1, 0, 0, 0}, NULL, NULL }; 929 static struct __nsw_switchconfig lkp_default = 930 { 0, "sendmail", 3, &lkp0 }; 931 932 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 933 mapreturn[svcno] = 0; 934 935 if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL) 936 lk = lkp_default.lookups; 937 else 938 lk = nsw_conf->lookups; 939 svcno = 0; 940 while (lk != NULL && svcno < MAXMAPSTACK) 941 { 942 maptype[svcno] = lk->service_name; 943 if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN) 944 mapreturn[MA_NOTFOUND] |= 1 << svcno; 945 if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN) 946 mapreturn[MA_TRYAGAIN] |= 1 << svcno; 947 if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN) 948 mapreturn[MA_TRYAGAIN] |= 1 << svcno; 949 svcno++; 950 lk = lk->next; 951 } 952 errno = save_errno; 953 return svcno; 954 #endif /* _USE_SUN_NSSWITCH_ */ 955 956 #ifdef _USE_DEC_SVC_CONF_ 957 struct svcinfo *svcinfo; 958 int svc; 959 960 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 961 mapreturn[svcno] = 0; 962 963 svcinfo = getsvc(); 964 if (svcinfo == NULL) 965 goto punt; 966 if (strcmp(service, "hosts") == 0) 967 svc = SVC_HOSTS; 968 else if (strcmp(service, "aliases") == 0) 969 svc = SVC_ALIASES; 970 else if (strcmp(service, "passwd") == 0) 971 svc = SVC_PASSWD; 972 else 973 { 974 errno = save_errno; 975 return -1; 976 } 977 for (svcno = 0; svcno < SVC_PATHSIZE && svcno < MAXMAPSTACK; svcno++) 978 { 979 switch (svcinfo->svcpath[svc][svcno]) 980 { 981 case SVC_LOCAL: 982 maptype[svcno] = "files"; 983 break; 984 985 case SVC_YP: 986 maptype[svcno] = "nis"; 987 break; 988 989 case SVC_BIND: 990 maptype[svcno] = "dns"; 991 break; 992 993 # ifdef SVC_HESIOD 994 case SVC_HESIOD: 995 maptype[svcno] = "hesiod"; 996 break; 997 # endif /* SVC_HESIOD */ 998 999 case SVC_LAST: 1000 errno = save_errno; 1001 return svcno; 1002 } 1003 } 1004 errno = save_errno; 1005 return svcno; 1006 #endif /* _USE_DEC_SVC_CONF_ */ 1007 1008 #if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) 1009 /* 1010 ** Fall-back mechanism. 1011 */ 1012 1013 STAB *st; 1014 static time_t servicecachetime; /* time service switch was cached */ 1015 time_t now = curtime(); 1016 1017 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 1018 mapreturn[svcno] = 0; 1019 1020 if ((now - servicecachetime) > (time_t) ServiceCacheMaxAge) 1021 { 1022 /* (re)read service switch */ 1023 register SM_FILE_T *fp; 1024 long sff = SFF_REGONLY|SFF_OPENASROOT|SFF_NOLOCK; 1025 1026 if (!bitnset(DBS_LINKEDSERVICESWITCHFILEINWRITABLEDIR, 1027 DontBlameSendmail)) 1028 sff |= SFF_NOWLINK; 1029 1030 if (ConfigFileRead) 1031 servicecachetime = now; 1032 fp = safefopen(ServiceSwitchFile, O_RDONLY, 0, sff); 1033 if (fp != NULL) 1034 { 1035 char buf[MAXLINE]; 1036 1037 while (sm_io_fgets(fp, SM_TIME_DEFAULT, buf, 1038 sizeof buf) != NULL) 1039 { 1040 register char *p; 1041 1042 p = strpbrk(buf, "#\n"); 1043 if (p != NULL) 1044 *p = '\0'; 1045 p = strpbrk(buf, " \t"); 1046 if (p != NULL) 1047 *p++ = '\0'; 1048 if (buf[0] == '\0') 1049 continue; 1050 if (p == NULL) 1051 { 1052 sm_syslog(LOG_ERR, NOQID, 1053 "Bad line on %.100s: %.100s", 1054 ServiceSwitchFile, 1055 buf); 1056 continue; 1057 } 1058 while (isspace(*p)) 1059 p++; 1060 if (*p == '\0') 1061 continue; 1062 1063 /* 1064 ** Find/allocate space for this service entry. 1065 ** Space for all of the service strings 1066 ** are allocated at once. This means 1067 ** that we only have to free the first 1068 ** one to free all of them. 1069 */ 1070 1071 st = stab(buf, ST_SERVICE, ST_ENTER); 1072 if (st->s_service[0] != NULL) 1073 sm_free((void *) st->s_service[0]); /* XXX */ 1074 p = newstr(p); 1075 for (svcno = 0; svcno < MAXMAPSTACK; ) 1076 { 1077 if (*p == '\0') 1078 break; 1079 st->s_service[svcno++] = p; 1080 p = strpbrk(p, " \t"); 1081 if (p == NULL) 1082 break; 1083 *p++ = '\0'; 1084 while (isspace(*p)) 1085 p++; 1086 } 1087 if (svcno < MAXMAPSTACK) 1088 st->s_service[svcno] = NULL; 1089 } 1090 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1091 } 1092 } 1093 1094 /* look up entry in cache */ 1095 st = stab(service, ST_SERVICE, ST_FIND); 1096 if (st != NULL && st->s_service[0] != NULL) 1097 { 1098 /* extract data */ 1099 svcno = 0; 1100 while (svcno < MAXMAPSTACK) 1101 { 1102 maptype[svcno] = st->s_service[svcno]; 1103 if (maptype[svcno++] == NULL) 1104 break; 1105 } 1106 errno = save_errno; 1107 return --svcno; 1108 } 1109 #endif /* !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_) */ 1110 1111 #if !defined(_USE_SUN_NSSWITCH_) 1112 /* if the service file doesn't work, use an absolute fallback */ 1113 # ifdef _USE_DEC_SVC_CONF_ 1114 punt: 1115 # endif /* _USE_DEC_SVC_CONF_ */ 1116 for (svcno = 0; svcno < MAXMAPACTIONS; svcno++) 1117 mapreturn[svcno] = 0; 1118 svcno = 0; 1119 if (strcmp(service, "aliases") == 0) 1120 { 1121 maptype[svcno++] = "files"; 1122 # if defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) 1123 maptype[svcno++] = "netinfo"; 1124 # endif /* defined(AUTO_NETINFO_ALIASES) && defined (NETINFO) */ 1125 # ifdef AUTO_NIS_ALIASES 1126 # if NISPLUS 1127 maptype[svcno++] = "nisplus"; 1128 # endif /* NISPLUS */ 1129 # if NIS 1130 maptype[svcno++] = "nis"; 1131 # endif /* NIS */ 1132 # endif /* AUTO_NIS_ALIASES */ 1133 errno = save_errno; 1134 return svcno; 1135 } 1136 if (strcmp(service, "hosts") == 0) 1137 { 1138 # if NAMED_BIND 1139 maptype[svcno++] = "dns"; 1140 # else /* NAMED_BIND */ 1141 # if defined(sun) && !defined(BSD) 1142 /* SunOS */ 1143 maptype[svcno++] = "nis"; 1144 # endif /* defined(sun) && !defined(BSD) */ 1145 # endif /* NAMED_BIND */ 1146 # if defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) 1147 maptype[svcno++] = "netinfo"; 1148 # endif /* defined(AUTO_NETINFO_HOSTS) && defined (NETINFO) */ 1149 maptype[svcno++] = "files"; 1150 errno = save_errno; 1151 return svcno; 1152 } 1153 errno = save_errno; 1154 return -1; 1155 #endif /* !defined(_USE_SUN_NSSWITCH_) */ 1156 } 1157 /* 1158 ** USERNAME -- return the user id of the logged in user. 1159 ** 1160 ** Parameters: 1161 ** none. 1162 ** 1163 ** Returns: 1164 ** The login name of the logged in user. 1165 ** 1166 ** Side Effects: 1167 ** none. 1168 ** 1169 ** Notes: 1170 ** The return value is statically allocated. 1171 */ 1172 1173 char * 1174 username() 1175 { 1176 static char *myname = NULL; 1177 extern char *getlogin(); 1178 register struct passwd *pw; 1179 1180 /* cache the result */ 1181 if (myname == NULL) 1182 { 1183 myname = getlogin(); 1184 if (myname == NULL || myname[0] == '\0') 1185 { 1186 pw = sm_getpwuid(RealUid); 1187 if (pw != NULL) 1188 myname = pw->pw_name; 1189 } 1190 else 1191 { 1192 uid_t uid = RealUid; 1193 1194 if ((pw = sm_getpwnam(myname)) == NULL || 1195 (uid != 0 && uid != pw->pw_uid)) 1196 { 1197 pw = sm_getpwuid(uid); 1198 if (pw != NULL) 1199 myname = pw->pw_name; 1200 } 1201 } 1202 if (myname == NULL || myname[0] == '\0') 1203 { 1204 syserr("554 5.3.0 Who are you?"); 1205 myname = "postmaster"; 1206 } 1207 else if (strpbrk(myname, ",;:/|\"\\") != NULL) 1208 myname = addquotes(myname, NULL); 1209 else 1210 myname = sm_pstrdup_x(myname); 1211 } 1212 return myname; 1213 } 1214 /* 1215 ** TTYPATH -- Get the path of the user's tty 1216 ** 1217 ** Returns the pathname of the user's tty. Returns NULL if 1218 ** the user is not logged in or if s/he has write permission 1219 ** denied. 1220 ** 1221 ** Parameters: 1222 ** none 1223 ** 1224 ** Returns: 1225 ** pathname of the user's tty. 1226 ** NULL if not logged in or write permission denied. 1227 ** 1228 ** Side Effects: 1229 ** none. 1230 ** 1231 ** WARNING: 1232 ** Return value is in a local buffer. 1233 ** 1234 ** Called By: 1235 ** savemail 1236 */ 1237 1238 char * 1239 ttypath() 1240 { 1241 struct stat stbuf; 1242 register char *pathn; 1243 extern char *ttyname(); 1244 extern char *getlogin(); 1245 1246 /* compute the pathname of the controlling tty */ 1247 if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL && 1248 (pathn = ttyname(0)) == NULL) 1249 { 1250 errno = 0; 1251 return NULL; 1252 } 1253 1254 /* see if we have write permission */ 1255 if (stat(pathn, &stbuf) < 0 || !bitset(S_IWOTH, stbuf.st_mode)) 1256 { 1257 errno = 0; 1258 return NULL; 1259 } 1260 1261 /* see if the user is logged in */ 1262 if (getlogin() == NULL) 1263 return NULL; 1264 1265 /* looks good */ 1266 return pathn; 1267 } 1268 /* 1269 ** CHECKCOMPAT -- check for From and To person compatible. 1270 ** 1271 ** This routine can be supplied on a per-installation basis 1272 ** to determine whether a person is allowed to send a message. 1273 ** This allows restriction of certain types of internet 1274 ** forwarding or registration of users. 1275 ** 1276 ** If the hosts are found to be incompatible, an error 1277 ** message should be given using "usrerr" and an EX_ code 1278 ** should be returned. You can also set to->q_status to 1279 ** a DSN-style status code. 1280 ** 1281 ** EF_NO_BODY_RETN can be set in e->e_flags to suppress the 1282 ** body during the return-to-sender function; this should be done 1283 ** on huge messages. This bit may already be set by the ESMTP 1284 ** protocol. 1285 ** 1286 ** Parameters: 1287 ** to -- the person being sent to. 1288 ** 1289 ** Returns: 1290 ** an exit status 1291 ** 1292 ** Side Effects: 1293 ** none (unless you include the usrerr stuff) 1294 */ 1295 1296 int 1297 checkcompat(to, e) 1298 register ADDRESS *to; 1299 register ENVELOPE *e; 1300 { 1301 if (tTd(49, 1)) 1302 sm_dprintf("checkcompat(to=%s, from=%s)\n", 1303 to->q_paddr, e->e_from.q_paddr); 1304 1305 #ifdef EXAMPLE_CODE 1306 /* this code is intended as an example only */ 1307 register STAB *s; 1308 1309 s = stab("arpa", ST_MAILER, ST_FIND); 1310 if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 && 1311 to->q_mailer == s->s_mailer) 1312 { 1313 usrerr("553 No ARPA mail through this machine: see your system administration"); 1314 /* e->e_flags |= EF_NO_BODY_RETN; to suppress body on return */ 1315 to->q_status = "5.7.1"; 1316 return EX_UNAVAILABLE; 1317 } 1318 #endif /* EXAMPLE_CODE */ 1319 return EX_OK; 1320 } 1321 /* 1322 ** INIT_MD -- do machine dependent initializations 1323 ** 1324 ** Systems that have global modes that should be set should do 1325 ** them here rather than in main. 1326 */ 1327 1328 #ifdef _AUX_SOURCE 1329 # include <compat.h> 1330 #endif /* _AUX_SOURCE */ 1331 1332 #if SHARE_V1 1333 # include <shares.h> 1334 #endif /* SHARE_V1 */ 1335 1336 void 1337 init_md(argc, argv) 1338 int argc; 1339 char **argv; 1340 { 1341 #ifdef _AUX_SOURCE 1342 setcompat(getcompat() | COMPAT_BSDPROT); 1343 #endif /* _AUX_SOURCE */ 1344 1345 #ifdef SUN_EXTENSIONS 1346 init_md_sun(); 1347 #endif /* SUN_EXTENSIONS */ 1348 1349 #if _CONVEX_SOURCE 1350 /* keep gethostby*() from stripping the local domain name */ 1351 set_domain_trim_off(); 1352 #endif /* _CONVEX_SOURCE */ 1353 #ifdef __QNX__ 1354 /* 1355 ** Due to QNX's network distributed nature, you can target a tcpip 1356 ** stack on a different node in the qnx network; this patch lets 1357 ** this feature work. The __sock_locate() must be done before the 1358 ** environment is clear. 1359 */ 1360 __sock_locate(); 1361 #endif /* __QNX__ */ 1362 #if SECUREWARE || defined(_SCO_unix_) 1363 set_auth_parameters(argc, argv); 1364 1365 # ifdef _SCO_unix_ 1366 /* 1367 ** This is required for highest security levels (the kernel 1368 ** won't let it call set*uid() or run setuid binaries without 1369 ** it). It may be necessary on other SECUREWARE systems. 1370 */ 1371 1372 if (getluid() == -1) 1373 setluid(0); 1374 # endif /* _SCO_unix_ */ 1375 #endif /* SECUREWARE || defined(_SCO_unix_) */ 1376 1377 1378 #ifdef VENDOR_DEFAULT 1379 VendorCode = VENDOR_DEFAULT; 1380 #else /* VENDOR_DEFAULT */ 1381 VendorCode = VENDOR_BERKELEY; 1382 #endif /* VENDOR_DEFAULT */ 1383 } 1384 /* 1385 ** INIT_VENDOR_MACROS -- vendor-dependent macro initializations 1386 ** 1387 ** Called once, on startup. 1388 ** 1389 ** Parameters: 1390 ** e -- the global envelope. 1391 ** 1392 ** Returns: 1393 ** none. 1394 ** 1395 ** Side Effects: 1396 ** vendor-dependent. 1397 */ 1398 1399 void 1400 init_vendor_macros(e) 1401 register ENVELOPE *e; 1402 { 1403 } 1404 /* 1405 ** GETLA -- get the current load average 1406 ** 1407 ** This code stolen from la.c. 1408 ** 1409 ** Parameters: 1410 ** none. 1411 ** 1412 ** Returns: 1413 ** The current load average as an integer. 1414 ** 1415 ** Side Effects: 1416 ** none. 1417 */ 1418 1419 /* try to guess what style of load average we have */ 1420 #define LA_ZERO 1 /* always return load average as zero */ 1421 #define LA_INT 2 /* read kmem for avenrun; interpret as long */ 1422 #define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */ 1423 #define LA_SUBR 4 /* call getloadavg */ 1424 #define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */ 1425 #define LA_SHORT 6 /* read kmem for avenrun; interpret as short */ 1426 #define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */ 1427 #define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */ 1428 #define LA_DGUX 9 /* special DGUX implementation */ 1429 #define LA_HPUX 10 /* special HPUX implementation */ 1430 #define LA_IRIX6 11 /* special IRIX 6.2 implementation */ 1431 #define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */ 1432 #define LA_DEVSHORT 13 /* read short from a device */ 1433 #define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */ 1434 #define LA_PSET 15 /* Solaris per-processor-set load average */ 1435 1436 /* do guesses based on general OS type */ 1437 #ifndef LA_TYPE 1438 # define LA_TYPE LA_ZERO 1439 #endif /* ! LA_TYPE */ 1440 1441 #ifndef FSHIFT 1442 # if defined(unixpc) 1443 # define FSHIFT 5 1444 # endif /* defined(unixpc) */ 1445 1446 # if defined(__alpha) || defined(IRIX) 1447 # define FSHIFT 10 1448 # endif /* defined(__alpha) || defined(IRIX) */ 1449 1450 #endif /* ! FSHIFT */ 1451 1452 #ifndef FSHIFT 1453 # define FSHIFT 8 1454 #endif /* ! FSHIFT */ 1455 1456 #ifndef FSCALE 1457 # define FSCALE (1 << FSHIFT) 1458 #endif /* ! FSCALE */ 1459 1460 #ifndef LA_AVENRUN 1461 # ifdef SYSTEM5 1462 # define LA_AVENRUN "avenrun" 1463 # else /* SYSTEM5 */ 1464 # define LA_AVENRUN "_avenrun" 1465 # endif /* SYSTEM5 */ 1466 #endif /* ! LA_AVENRUN */ 1467 1468 /* _PATH_KMEM should be defined in <paths.h> */ 1469 #ifndef _PATH_KMEM 1470 # define _PATH_KMEM "/dev/kmem" 1471 #endif /* ! _PATH_KMEM */ 1472 1473 #if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) 1474 1475 # include <nlist.h> 1476 1477 /* _PATH_UNIX should be defined in <paths.h> */ 1478 # ifndef _PATH_UNIX 1479 # if defined(SYSTEM5) 1480 # define _PATH_UNIX "/unix" 1481 # else /* defined(SYSTEM5) */ 1482 # define _PATH_UNIX "/vmunix" 1483 # endif /* defined(SYSTEM5) */ 1484 # endif /* ! _PATH_UNIX */ 1485 1486 # ifdef _AUX_SOURCE 1487 struct nlist Nl[2]; 1488 # else /* _AUX_SOURCE */ 1489 struct nlist Nl[] = 1490 { 1491 { LA_AVENRUN }, 1492 { 0 }, 1493 }; 1494 # endif /* _AUX_SOURCE */ 1495 # define X_AVENRUN 0 1496 1497 int 1498 getla() 1499 { 1500 int j; 1501 static int kmem = -1; 1502 # if LA_TYPE == LA_INT 1503 long avenrun[3]; 1504 # else /* LA_TYPE == LA_INT */ 1505 # if LA_TYPE == LA_SHORT 1506 short avenrun[3]; 1507 # else /* LA_TYPE == LA_SHORT */ 1508 double avenrun[3]; 1509 # endif /* LA_TYPE == LA_SHORT */ 1510 # endif /* LA_TYPE == LA_INT */ 1511 extern off_t lseek(); 1512 1513 if (kmem < 0) 1514 { 1515 # ifdef _AUX_SOURCE 1516 (void) sm_strlcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN, 1517 sizeof Nl[X_AVENRUN].n_name); 1518 Nl[1].n_name[0] = '\0'; 1519 # endif /* _AUX_SOURCE */ 1520 1521 # if defined(_AIX3) || defined(_AIX4) 1522 if (knlist(Nl, 1, sizeof Nl[0]) < 0) 1523 # else /* defined(_AIX3) || defined(_AIX4) */ 1524 if (nlist(_PATH_UNIX, Nl) < 0) 1525 # endif /* defined(_AIX3) || defined(_AIX4) */ 1526 { 1527 if (tTd(3, 1)) 1528 sm_dprintf("getla: nlist(%s): %s\n", _PATH_UNIX, 1529 sm_errstring(errno)); 1530 return -1; 1531 } 1532 if (Nl[X_AVENRUN].n_value == 0) 1533 { 1534 if (tTd(3, 1)) 1535 sm_dprintf("getla: nlist(%s, %s) ==> 0\n", 1536 _PATH_UNIX, LA_AVENRUN); 1537 return -1; 1538 } 1539 # ifdef NAMELISTMASK 1540 Nl[X_AVENRUN].n_value &= NAMELISTMASK; 1541 # endif /* NAMELISTMASK */ 1542 1543 kmem = open(_PATH_KMEM, 0, 0); 1544 if (kmem < 0) 1545 { 1546 if (tTd(3, 1)) 1547 sm_dprintf("getla: open(/dev/kmem): %s\n", 1548 sm_errstring(errno)); 1549 return -1; 1550 } 1551 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1552 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1553 { 1554 if (tTd(3, 1)) 1555 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1556 sm_errstring(errno)); 1557 (void) close(kmem); 1558 kmem = -1; 1559 return -1; 1560 } 1561 } 1562 if (tTd(3, 20)) 1563 sm_dprintf("getla: symbol address = %#lx\n", 1564 (unsigned long) Nl[X_AVENRUN].n_value); 1565 if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 || 1566 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 1567 { 1568 /* thank you Ian */ 1569 if (tTd(3, 1)) 1570 sm_dprintf("getla: lseek or read: %s\n", 1571 sm_errstring(errno)); 1572 return -1; 1573 } 1574 # if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) 1575 if (tTd(3, 5)) 1576 { 1577 # if LA_TYPE == LA_SHORT 1578 sm_dprintf("getla: avenrun = %d", avenrun[0]); 1579 if (tTd(3, 15)) 1580 sm_dprintf(", %d, %d", avenrun[1], avenrun[2]); 1581 # else /* LA_TYPE == LA_SHORT */ 1582 sm_dprintf("getla: avenrun = %ld", avenrun[0]); 1583 if (tTd(3, 15)) 1584 sm_dprintf(", %ld, %ld", avenrun[1], avenrun[2]); 1585 # endif /* LA_TYPE == LA_SHORT */ 1586 sm_dprintf("\n"); 1587 } 1588 if (tTd(3, 1)) 1589 sm_dprintf("getla: %d\n", 1590 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1591 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1592 # else /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */ 1593 if (tTd(3, 5)) 1594 { 1595 sm_dprintf("getla: avenrun = %g", avenrun[0]); 1596 if (tTd(3, 15)) 1597 sm_dprintf(", %g, %g", avenrun[1], avenrun[2]); 1598 sm_dprintf("\n"); 1599 } 1600 if (tTd(3, 1)) 1601 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 1602 return ((int) (avenrun[0] + 0.5)); 1603 # endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT) */ 1604 } 1605 1606 #endif /* (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT) */ 1607 1608 #if LA_TYPE == LA_READKSYM 1609 1610 # include <sys/ksym.h> 1611 1612 int 1613 getla() 1614 { 1615 int j; 1616 static int kmem = -1; 1617 long avenrun[3]; 1618 struct mioc_rksym mirk; 1619 1620 if (kmem < 0) 1621 { 1622 kmem = open("/dev/kmem", 0, 0); 1623 if (kmem < 0) 1624 { 1625 if (tTd(3, 1)) 1626 sm_dprintf("getla: open(/dev/kmem): %s\n", 1627 sm_errstring(errno)); 1628 return -1; 1629 } 1630 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1631 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1632 { 1633 if (tTd(3, 1)) 1634 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1635 sm_errstring(errno)); 1636 (void) close(kmem); 1637 kmem = -1; 1638 return -1; 1639 } 1640 } 1641 mirk.mirk_symname = LA_AVENRUN; 1642 mirk.mirk_buf = avenrun; 1643 mirk.mirk_buflen = sizeof(avenrun); 1644 if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0) 1645 { 1646 if (tTd(3, 1)) 1647 sm_dprintf("getla: ioctl(MIOC_READKSYM) failed: %s\n", 1648 sm_errstring(errno)); 1649 return -1; 1650 } 1651 if (tTd(3, 5)) 1652 { 1653 sm_dprintf("getla: avenrun = %d", avenrun[0]); 1654 if (tTd(3, 15)) 1655 sm_dprintf(", %d, %d", avenrun[1], avenrun[2]); 1656 sm_dprintf("\n"); 1657 } 1658 if (tTd(3, 1)) 1659 sm_dprintf("getla: %d\n", 1660 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1661 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1662 } 1663 1664 #endif /* LA_TYPE == LA_READKSYM */ 1665 1666 #if LA_TYPE == LA_DGUX 1667 1668 # include <sys/dg_sys_info.h> 1669 1670 int 1671 getla() 1672 { 1673 struct dg_sys_info_load_info load_info; 1674 1675 dg_sys_info((long *)&load_info, 1676 DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0); 1677 1678 if (tTd(3, 1)) 1679 sm_dprintf("getla: %d\n", (int) (load_info.one_minute + 0.5)); 1680 1681 return ((int) (load_info.one_minute + 0.5)); 1682 } 1683 1684 #endif /* LA_TYPE == LA_DGUX */ 1685 1686 #if LA_TYPE == LA_HPUX 1687 1688 /* forward declarations to keep gcc from complaining */ 1689 struct pst_dynamic; 1690 struct pst_status; 1691 struct pst_static; 1692 struct pst_vminfo; 1693 struct pst_diskinfo; 1694 struct pst_processor; 1695 struct pst_lv; 1696 struct pst_swapinfo; 1697 1698 # include <sys/param.h> 1699 # include <sys/pstat.h> 1700 1701 int 1702 getla() 1703 { 1704 struct pst_dynamic pstd; 1705 1706 if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic), 1707 (size_t) 1, 0) == -1) 1708 return 0; 1709 1710 if (tTd(3, 1)) 1711 sm_dprintf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5)); 1712 1713 return (int) (pstd.psd_avg_1_min + 0.5); 1714 } 1715 1716 #endif /* LA_TYPE == LA_HPUX */ 1717 1718 #if LA_TYPE == LA_SUBR 1719 1720 int 1721 getla() 1722 { 1723 double avenrun[3]; 1724 1725 if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0) 1726 { 1727 if (tTd(3, 1)) 1728 sm_dprintf("getla: getloadavg failed: %s", 1729 sm_errstring(errno)); 1730 return -1; 1731 } 1732 if (tTd(3, 1)) 1733 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 1734 return ((int) (avenrun[0] + 0.5)); 1735 } 1736 1737 #endif /* LA_TYPE == LA_SUBR */ 1738 1739 #if LA_TYPE == LA_MACH 1740 1741 /* 1742 ** This has been tested on NEXTSTEP release 2.1/3.X. 1743 */ 1744 1745 # if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 1746 # include <mach/mach.h> 1747 # else /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ 1748 # include <mach.h> 1749 # endif /* defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0 */ 1750 1751 int 1752 getla() 1753 { 1754 processor_set_t default_set; 1755 kern_return_t error; 1756 unsigned int info_count; 1757 struct processor_set_basic_info info; 1758 host_t host; 1759 1760 error = processor_set_default(host_self(), &default_set); 1761 if (error != KERN_SUCCESS) 1762 { 1763 if (tTd(3, 1)) 1764 sm_dprintf("getla: processor_set_default failed: %s", 1765 sm_errstring(errno)); 1766 return -1; 1767 } 1768 info_count = PROCESSOR_SET_BASIC_INFO_COUNT; 1769 if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO, 1770 &host, (processor_set_info_t)&info, 1771 &info_count) != KERN_SUCCESS) 1772 { 1773 if (tTd(3, 1)) 1774 sm_dprintf("getla: processor_set_info failed: %s", 1775 sm_errstring(errno)); 1776 return -1; 1777 } 1778 if (tTd(3, 1)) 1779 sm_dprintf("getla: %d\n", 1780 (int) ((info.load_average + (LOAD_SCALE / 2)) / 1781 LOAD_SCALE)); 1782 return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE; 1783 } 1784 1785 #endif /* LA_TYPE == LA_MACH */ 1786 1787 #if LA_TYPE == LA_PROCSTR 1788 # if SM_CONF_BROKEN_STRTOD 1789 ERROR: This OS has most likely a broken strtod() implemenentation. 1790 ERROR: The function is required for getla(). 1791 ERROR: Check the compilation options _LA_PROCSTR and 1792 ERROR: _SM_CONF_BROKEN_STRTOD (without the leading _). 1793 # endif /* SM_CONF_BROKEN_STRTOD */ 1794 1795 /* 1796 ** Read /proc/loadavg for the load average. This is assumed to be 1797 ** in a format like "0.15 0.12 0.06". 1798 ** 1799 ** Initially intended for Linux. This has been in the kernel 1800 ** since at least 0.99.15. 1801 */ 1802 1803 # ifndef _PATH_LOADAVG 1804 # define _PATH_LOADAVG "/proc/loadavg" 1805 # endif /* ! _PATH_LOADAVG */ 1806 1807 int 1808 getla() 1809 { 1810 double avenrun; 1811 register int result; 1812 SM_FILE_T *fp; 1813 1814 fp = sm_io_open(SmFtStdio, SM_TIME_DEFAULT, _PATH_LOADAVG, SM_IO_RDONLY, 1815 NULL); 1816 if (fp == NULL) 1817 { 1818 if (tTd(3, 1)) 1819 sm_dprintf("getla: sm_io_open(%s): %s\n", 1820 _PATH_LOADAVG, sm_errstring(errno)); 1821 return -1; 1822 } 1823 result = sm_io_fscanf(fp, SM_TIME_DEFAULT, "%lf", &avenrun); 1824 (void) sm_io_close(fp, SM_TIME_DEFAULT); 1825 if (result != 1) 1826 { 1827 if (tTd(3, 1)) 1828 sm_dprintf("getla: sm_io_fscanf() = %d: %s\n", 1829 result, sm_errstring(errno)); 1830 return -1; 1831 } 1832 1833 if (tTd(3, 1)) 1834 sm_dprintf("getla(): %.2f\n", avenrun); 1835 1836 return ((int) (avenrun + 0.5)); 1837 } 1838 1839 #endif /* LA_TYPE == LA_PROCSTR */ 1840 1841 #if LA_TYPE == LA_IRIX6 1842 1843 # include <sys/sysmp.h> 1844 1845 # ifdef _UNICOSMP 1846 # define CAST_SYSMP(x) (x) 1847 # else /* _UNICOSMP */ 1848 # define CAST_SYSMP(x) ((x) & 0x7fffffff) 1849 # endif /* _UNICOSMP */ 1850 1851 int 1852 getla(void) 1853 { 1854 int j; 1855 static int kmem = -1; 1856 int avenrun[3]; 1857 1858 if (kmem < 0) 1859 { 1860 kmem = open(_PATH_KMEM, 0, 0); 1861 if (kmem < 0) 1862 { 1863 if (tTd(3, 1)) 1864 sm_dprintf("getla: open(%s): %s\n", _PATH_KMEM, 1865 sm_errstring(errno)); 1866 return -1; 1867 } 1868 if ((j = fcntl(kmem, F_GETFD, 0)) < 0 || 1869 fcntl(kmem, F_SETFD, j | FD_CLOEXEC) < 0) 1870 { 1871 if (tTd(3, 1)) 1872 sm_dprintf("getla: fcntl(/dev/kmem, FD_CLOEXEC): %s\n", 1873 sm_errstring(errno)); 1874 (void) close(kmem); 1875 kmem = -1; 1876 return -1; 1877 } 1878 } 1879 1880 if (lseek(kmem, CAST_SYSMP(sysmp(MP_KERNADDR, MPKA_AVENRUN)), SEEK_SET) 1881 == -1 || 1882 read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun)) 1883 { 1884 if (tTd(3, 1)) 1885 sm_dprintf("getla: lseek or read: %s\n", 1886 sm_errstring(errno)); 1887 return -1; 1888 } 1889 if (tTd(3, 5)) 1890 { 1891 sm_dprintf("getla: avenrun = %ld", (long int) avenrun[0]); 1892 if (tTd(3, 15)) 1893 sm_dprintf(", %ld, %ld", 1894 (long int) avenrun[1], (long int) avenrun[2]); 1895 sm_dprintf("\n"); 1896 } 1897 1898 if (tTd(3, 1)) 1899 sm_dprintf("getla: %d\n", 1900 (int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1901 return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT); 1902 1903 } 1904 #endif /* LA_TYPE == LA_IRIX6 */ 1905 1906 #if LA_TYPE == LA_KSTAT 1907 1908 # include <kstat.h> 1909 1910 int 1911 getla() 1912 { 1913 static kstat_ctl_t *kc = NULL; 1914 static kstat_t *ksp = NULL; 1915 kstat_named_t *ksn; 1916 int la; 1917 1918 if (kc == NULL) /* if not initialized before */ 1919 kc = kstat_open(); 1920 if (kc == NULL) 1921 { 1922 if (tTd(3, 1)) 1923 sm_dprintf("getla: kstat_open(): %s\n", 1924 sm_errstring(errno)); 1925 return -1; 1926 } 1927 if (ksp == NULL) 1928 ksp = kstat_lookup(kc, "unix", 0, "system_misc"); 1929 if (ksp == NULL) 1930 { 1931 if (tTd(3, 1)) 1932 sm_dprintf("getla: kstat_lookup(): %s\n", 1933 sm_errstring(errno)); 1934 return -1; 1935 } 1936 if (kstat_read(kc, ksp, NULL) < 0) 1937 { 1938 if (tTd(3, 1)) 1939 sm_dprintf("getla: kstat_read(): %s\n", 1940 sm_errstring(errno)); 1941 return -1; 1942 } 1943 ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min"); 1944 la = ((double) ksn->value.ul + FSCALE/2) / FSCALE; 1945 /* kstat_close(kc); /o do not close for fast access */ 1946 return la; 1947 } 1948 1949 #endif /* LA_TYPE == LA_KSTAT */ 1950 1951 #if LA_TYPE == LA_DEVSHORT 1952 1953 /* 1954 ** Read /dev/table/avenrun for the load average. This should contain 1955 ** three shorts for the 1, 5, and 15 minute loads. We only read the 1956 ** first, since that's all we care about. 1957 ** 1958 ** Intended for SCO OpenServer 5. 1959 */ 1960 1961 # ifndef _PATH_AVENRUN 1962 # define _PATH_AVENRUN "/dev/table/avenrun" 1963 # endif /* ! _PATH_AVENRUN */ 1964 1965 int 1966 getla() 1967 { 1968 static int afd = -1; 1969 short avenrun; 1970 int loadav; 1971 int r; 1972 1973 errno = EBADF; 1974 1975 if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1) 1976 { 1977 if (errno != EBADF) 1978 return -1; 1979 afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC); 1980 if (afd < 0) 1981 { 1982 sm_syslog(LOG_ERR, NOQID, 1983 "can't open %s: %s", 1984 _PATH_AVENRUN, sm_errstring(errno)); 1985 return -1; 1986 } 1987 } 1988 1989 r = read(afd, &avenrun, sizeof avenrun); 1990 1991 if (tTd(3, 5)) 1992 sm_dprintf("getla: avenrun = %d\n", avenrun); 1993 loadav = (int) (avenrun + FSCALE/2) >> FSHIFT; 1994 if (tTd(3, 1)) 1995 sm_dprintf("getla: %d\n", loadav); 1996 return loadav; 1997 } 1998 1999 #endif /* LA_TYPE == LA_DEVSHORT */ 2000 2001 #if LA_TYPE == LA_ALPHAOSF 2002 struct rtentry; 2003 struct mbuf; 2004 # include <sys/table.h> 2005 2006 int 2007 getla() 2008 { 2009 int ave = 0; 2010 struct tbl_loadavg tab; 2011 2012 if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1) 2013 { 2014 if (tTd(3, 1)) 2015 sm_dprintf("getla: table %s\n", sm_errstring(errno)); 2016 return -1; 2017 } 2018 2019 if (tTd(3, 1)) 2020 sm_dprintf("getla: scale = %d\n", tab.tl_lscale); 2021 2022 if (tab.tl_lscale) 2023 ave = ((tab.tl_avenrun.l[2] + (tab.tl_lscale/2)) / 2024 tab.tl_lscale); 2025 else 2026 ave = (int) (tab.tl_avenrun.d[2] + 0.5); 2027 2028 if (tTd(3, 1)) 2029 sm_dprintf("getla: %d\n", ave); 2030 2031 return ave; 2032 } 2033 2034 #endif /* LA_TYPE == LA_ALPHAOSF */ 2035 2036 #if LA_TYPE == LA_PSET 2037 2038 int 2039 getla() 2040 { 2041 double avenrun[3]; 2042 2043 if (pset_getloadavg(PS_MYID, avenrun, 2044 sizeof(avenrun) / sizeof(avenrun[0])) < 0) 2045 { 2046 if (tTd(3, 1)) 2047 sm_dprintf("getla: pset_getloadavg failed: %s", 2048 sm_errstring(errno)); 2049 return -1; 2050 } 2051 if (tTd(3, 1)) 2052 sm_dprintf("getla: %d\n", (int) (avenrun[0] +0.5)); 2053 return ((int) (avenrun[0] + 0.5)); 2054 } 2055 2056 #endif /* LA_TYPE == LA_PSET */ 2057 2058 #if LA_TYPE == LA_ZERO 2059 2060 int 2061 getla() 2062 { 2063 if (tTd(3, 1)) 2064 sm_dprintf("getla: ZERO\n"); 2065 return 0; 2066 } 2067 2068 #endif /* LA_TYPE == LA_ZERO */ 2069 2070 /* 2071 * Copyright 1989 Massachusetts Institute of Technology 2072 * 2073 * Permission to use, copy, modify, distribute, and sell this software and its 2074 * documentation for any purpose is hereby granted without fee, provided that 2075 * the above copyright notice appear in all copies and that both that 2076 * copyright notice and this permission notice appear in supporting 2077 * documentation, and that the name of M.I.T. not be used in advertising or 2078 * publicity pertaining to distribution of the software without specific, 2079 * written prior permission. M.I.T. makes no representations about the 2080 * suitability of this software for any purpose. It is provided "as is" 2081 * without express or implied warranty. 2082 * 2083 * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL 2084 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T. 2085 * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 2086 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION 2087 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN 2088 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 2089 * 2090 * Authors: Many and varied... 2091 */ 2092 2093 /* Non Apollo stuff removed by Don Lewis 11/15/93 */ 2094 #ifndef lint 2095 SM_UNUSED(static char rcsid[]) = "@(#)$OrigId: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $"; 2096 #endif /* ! lint */ 2097 2098 #ifdef apollo 2099 # undef volatile 2100 # include <apollo/base.h> 2101 2102 /* ARGSUSED */ 2103 int getloadavg( call_data ) 2104 caddr_t call_data; /* pointer to (double) return value */ 2105 { 2106 double *avenrun = (double *) call_data; 2107 int i; 2108 status_$t st; 2109 long loadav[3]; 2110 2111 proc1_$get_loadav(loadav, &st); 2112 *avenrun = loadav[0] / (double) (1 << 16); 2113 return 0; 2114 } 2115 #endif /* apollo */ 2116 /* 2117 ** SM_GETLA -- get the current load average 2118 ** 2119 ** Parameters: 2120 ** none 2121 ** 2122 ** Returns: 2123 ** none 2124 ** 2125 ** Side Effects: 2126 ** Set CurrentLA to the current load average. 2127 ** Set {load_avg} in GlobalMacros to the current load average. 2128 */ 2129 2130 void 2131 sm_getla() 2132 { 2133 char labuf[8]; 2134 2135 CurrentLA = getla(); 2136 (void) sm_snprintf(labuf, sizeof labuf, "%d", CurrentLA); 2137 macdefine(&GlobalMacros, A_TEMP, macid("{load_avg}"), labuf); 2138 } 2139 /* 2140 ** SHOULDQUEUE -- should this message be queued or sent? 2141 ** 2142 ** Compares the message cost to the load average to decide. 2143 ** 2144 ** Note: Do NOT change this API! It is documented in op.me 2145 ** and theoretically the user can change this function... 2146 ** 2147 ** Parameters: 2148 ** pri -- the priority of the message in question. 2149 ** ct -- the message creation time (unused, but see above). 2150 ** 2151 ** Returns: 2152 ** true -- if this message should be queued up for the 2153 ** time being. 2154 ** false -- if the load is low enough to send this message. 2155 ** 2156 ** Side Effects: 2157 ** none. 2158 */ 2159 2160 /* ARGSUSED1 */ 2161 bool 2162 shouldqueue(pri, ct) 2163 long pri; 2164 time_t ct; 2165 { 2166 bool rval; 2167 2168 if (tTd(3, 30)) 2169 sm_dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ", 2170 CurrentLA, pri); 2171 if (CurrentLA < QueueLA) 2172 { 2173 if (tTd(3, 30)) 2174 sm_dprintf("false (CurrentLA < QueueLA)\n"); 2175 return false; 2176 } 2177 # if 0 /* this code is reported to cause oscillation around RefuseLA */ 2178 if (CurrentLA >= RefuseLA && QueueLA < RefuseLA) 2179 { 2180 if (tTd(3, 30)) 2181 sm_dprintf("TRUE (CurrentLA >= RefuseLA)\n"); 2182 return true; 2183 } 2184 # endif /* 0 */ 2185 rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1)); 2186 if (tTd(3, 30)) 2187 sm_dprintf("%s (by calculation)\n", rval ? "true" : "false"); 2188 return rval; 2189 } 2190 /* 2191 ** REFUSECONNECTIONS -- decide if connections should be refused 2192 ** 2193 ** Parameters: 2194 ** name -- daemon name (for error messages only) 2195 ** e -- the current envelope. 2196 ** d -- number of daemon 2197 ** active -- was this daemon actually active? 2198 ** 2199 ** Returns: 2200 ** true if incoming SMTP connections should be refused 2201 ** (for now). 2202 ** false if we should accept new work. 2203 ** 2204 ** Side Effects: 2205 ** Sets process title when it is rejecting connections. 2206 */ 2207 2208 bool 2209 refuseconnections(name, e, d, active) 2210 char *name; 2211 ENVELOPE *e; 2212 int d; 2213 bool active; 2214 { 2215 static time_t lastconn[MAXDAEMONS]; 2216 static int conncnt[MAXDAEMONS]; 2217 static time_t firstrejtime[MAXDAEMONS]; 2218 static time_t nextlogtime[MAXDAEMONS]; 2219 2220 #if XLA 2221 if (!xla_smtp_ok()) 2222 return true; 2223 #endif /* XLA */ 2224 2225 SM_ASSERT(d >= 0); 2226 SM_ASSERT(d < MAXDAEMONS); 2227 if (ConnRateThrottle > 0) 2228 { 2229 time_t now; 2230 2231 now = curtime(); 2232 if (active) 2233 { 2234 if (now != lastconn[d]) 2235 { 2236 lastconn[d] = now; 2237 conncnt[d] = 1; 2238 } 2239 else if (conncnt[d]++ > ConnRateThrottle) 2240 { 2241 #define D_MSG_CRT "deferring connections on daemon %s: %d per second" 2242 /* sleep to flatten out connection load */ 2243 sm_setproctitle(true, e, D_MSG_CRT, 2244 name, ConnRateThrottle); 2245 if (LogLevel > 8) 2246 sm_syslog(LOG_INFO, NOQID, D_MSG_CRT, 2247 name, ConnRateThrottle); 2248 (void) sleep(1); 2249 } 2250 } 2251 else if (now != lastconn[d]) 2252 conncnt[d] = 0; 2253 } 2254 2255 sm_getla(); 2256 if (RefuseLA > 0 && CurrentLA >= RefuseLA) 2257 { 2258 time_t now; 2259 2260 # define R_MSG_LA "rejecting connections on daemon %s: load average: %d" 2261 # define R2_MSG_LA "have been rejecting connections on daemon %s for %s" 2262 sm_setproctitle(true, e, R_MSG_LA, name, CurrentLA); 2263 if (LogLevel > 8) 2264 sm_syslog(LOG_NOTICE, NOQID, R_MSG_LA, name, CurrentLA); 2265 now = curtime(); 2266 if (firstrejtime[d] == 0) 2267 { 2268 firstrejtime[d] = now; 2269 nextlogtime[d] = now + RejectLogInterval; 2270 } 2271 else if (nextlogtime[d] < now) 2272 { 2273 sm_syslog(LOG_ERR, NOQID, R2_MSG_LA, name, 2274 pintvl(now - firstrejtime[d], true)); 2275 nextlogtime[d] = now + RejectLogInterval; 2276 } 2277 return true; 2278 } 2279 else 2280 firstrejtime[d] = 0; 2281 2282 if (DelayLA > 0 && CurrentLA >= DelayLA) 2283 { 2284 time_t now; 2285 static time_t log_delay = (time_t) 0; 2286 2287 # define MIN_DELAY_LOG 90 /* wait before logging this again */ 2288 # define D_MSG_LA "delaying connections on daemon %s: load average=%d >= %d" 2289 /* sleep to flatten out connection load */ 2290 sm_setproctitle(true, e, D_MSG_LA, name, DelayLA); 2291 if (LogLevel > 8 && (now = curtime()) > log_delay) 2292 { 2293 sm_syslog(LOG_INFO, NOQID, D_MSG_LA, 2294 name, CurrentLA, DelayLA); 2295 log_delay = now + MIN_DELAY_LOG; 2296 } 2297 (void) sleep(1); 2298 } 2299 2300 if (MaxChildren > 0 && CurChildren >= MaxChildren) 2301 { 2302 proc_list_probe(); 2303 if (CurChildren >= MaxChildren) 2304 { 2305 #define R_MSG_CHILD "rejecting connections on daemon %s: %d children, max %d" 2306 sm_setproctitle(true, e, R_MSG_CHILD, 2307 name, CurChildren, MaxChildren); 2308 if (LogLevel > 8) 2309 sm_syslog(LOG_INFO, NOQID, R_MSG_CHILD, 2310 name, CurChildren, MaxChildren); 2311 return true; 2312 } 2313 } 2314 return false; 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 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 <sys/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 3787 #if defined(VENDOR_NAME) && defined(VENDOR_CODE) 3788 if (sm_strcasecmp(vendor, VENDOR_NAME) == 0) 3789 { 3790 VendorCode = VENDOR_CODE; 3791 return true; 3792 } 3793 #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ 3794 3795 return false; 3796 } 3797 /* 3798 ** GETVENDOR -- return vendor name based on vendor code 3799 ** 3800 ** Parameters: 3801 ** vendorcode -- numeric representation of vendor. 3802 ** 3803 ** Returns: 3804 ** string containing vendor name. 3805 */ 3806 3807 char * 3808 getvendor(vendorcode) 3809 int vendorcode; 3810 { 3811 #if defined(VENDOR_NAME) && defined(VENDOR_CODE) 3812 /* 3813 ** Can't have the same switch case twice so need to 3814 ** handle VENDOR_CODE outside of switch. It might 3815 ** match one of the existing VENDOR_* codes. 3816 */ 3817 3818 if (vendorcode == VENDOR_CODE) 3819 return VENDOR_NAME; 3820 #endif /* defined(VENDOR_NAME) && defined(VENDOR_CODE) */ 3821 3822 switch (vendorcode) 3823 { 3824 case VENDOR_BERKELEY: 3825 return "Berkeley"; 3826 3827 case VENDOR_SUN: 3828 return "Sun"; 3829 3830 case VENDOR_HP: 3831 return "HP"; 3832 3833 case VENDOR_IBM: 3834 return "IBM"; 3835 3836 case VENDOR_SENDMAIL: 3837 return "Sendmail"; 3838 3839 default: 3840 return "Unknown"; 3841 } 3842 } 3843 /* 3844 ** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults 3845 ** 3846 ** Vendor_pre_defaults is called before reading the configuration 3847 ** file; vendor_post_defaults is called immediately after. 3848 ** 3849 ** Parameters: 3850 ** e -- the global environment to initialize. 3851 ** 3852 ** Returns: 3853 ** none. 3854 */ 3855 3856 #if SHARE_V1 3857 int DefShareUid; /* default share uid to run as -- unused??? */ 3858 #endif /* SHARE_V1 */ 3859 3860 void 3861 vendor_pre_defaults(e) 3862 ENVELOPE *e; 3863 { 3864 #if SHARE_V1 3865 /* OTHERUID is defined in shares.h, do not be alarmed */ 3866 DefShareUid = OTHERUID; 3867 #endif /* SHARE_V1 */ 3868 #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) 3869 sun_pre_defaults(e); 3870 #endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ 3871 #ifdef apollo 3872 /* 3873 ** stupid domain/os can't even open 3874 ** /etc/mail/sendmail.cf without this 3875 */ 3876 3877 setuserenv("ISP", NULL); 3878 setuserenv("SYSTYPE", NULL); 3879 #endif /* apollo */ 3880 } 3881 3882 3883 void 3884 vendor_post_defaults(e) 3885 ENVELOPE *e; 3886 { 3887 #ifdef __QNX__ 3888 char *p; 3889 3890 /* Makes sure the SOCK environment variable remains */ 3891 if (p = getextenv("SOCK")) 3892 setuserenv("SOCK", p); 3893 #endif /* __QNX__ */ 3894 #if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) 3895 sun_post_defaults(e); 3896 #endif /* defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES) */ 3897 } 3898 /* 3899 ** VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode 3900 */ 3901 3902 void 3903 vendor_daemon_setup(e) 3904 ENVELOPE *e; 3905 { 3906 #if HASSETLOGIN 3907 (void) setlogin(RunAsUserName); 3908 #endif /* HASSETLOGIN */ 3909 #if SECUREWARE 3910 if (getluid() != -1) 3911 { 3912 usrerr("Daemon cannot have LUID"); 3913 finis(false, true, EX_USAGE); 3914 } 3915 #endif /* SECUREWARE */ 3916 } 3917 /* 3918 ** VENDOR_SET_UID -- do setup for setting a user id 3919 ** 3920 ** This is called when we are still root. 3921 ** 3922 ** Parameters: 3923 ** uid -- the uid we are about to become. 3924 ** 3925 ** Returns: 3926 ** none. 3927 */ 3928 3929 void 3930 vendor_set_uid(uid) 3931 UID_T uid; 3932 { 3933 /* 3934 ** We need to setup the share groups (lnodes) 3935 ** and add auditing information (luid's) 3936 ** before we loose our ``root''ness. 3937 */ 3938 #if SHARE_V1 3939 if (setupshares(uid, syserr) != 0) 3940 syserr("Unable to set up shares"); 3941 #endif /* SHARE_V1 */ 3942 #if SECUREWARE 3943 (void) setup_secure(uid); 3944 #endif /* SECUREWARE */ 3945 } 3946 /* 3947 ** VALIDATE_CONNECTION -- check connection for rationality 3948 ** 3949 ** If the connection is rejected, this routine should log an 3950 ** appropriate message -- but should never issue any SMTP protocol. 3951 ** 3952 ** Parameters: 3953 ** sap -- a pointer to a SOCKADDR naming the peer. 3954 ** hostname -- the name corresponding to sap. 3955 ** e -- the current envelope. 3956 ** 3957 ** Returns: 3958 ** error message from rejection. 3959 ** NULL if not rejected. 3960 */ 3961 3962 #if TCPWRAPPERS 3963 # include <tcpd.h> 3964 3965 /* tcpwrappers does no logging, but you still have to declare these -- ugh */ 3966 int allow_severity = LOG_INFO; 3967 int deny_severity = LOG_NOTICE; 3968 #endif /* TCPWRAPPERS */ 3969 3970 char * 3971 validate_connection(sap, hostname, e) 3972 SOCKADDR *sap; 3973 char *hostname; 3974 ENVELOPE *e; 3975 { 3976 #if TCPWRAPPERS 3977 char *host; 3978 char *addr; 3979 extern int hosts_ctl(); 3980 #endif /* TCPWRAPPERS */ 3981 3982 if (tTd(48, 3)) 3983 sm_dprintf("validate_connection(%s, %s)\n", 3984 hostname, anynet_ntoa(sap)); 3985 3986 connection_rate_check(sap, e); 3987 if (rscheck("check_relay", hostname, anynet_ntoa(sap), 3988 e, RSF_RMCOMM|RSF_COUNT, 3, NULL, NOQID) != EX_OK) 3989 { 3990 static char reject[BUFSIZ*2]; 3991 extern char MsgBuf[]; 3992 3993 if (tTd(48, 4)) 3994 sm_dprintf(" ... validate_connection: BAD (rscheck)\n"); 3995 3996 if (strlen(MsgBuf) >= 3) 3997 (void) sm_strlcpy(reject, MsgBuf, sizeof reject); 3998 else 3999 (void) sm_strlcpy(reject, "Access denied", sizeof reject); 4000 4001 return reject; 4002 } 4003 4004 #if TCPWRAPPERS 4005 if (hostname[0] == '[' && hostname[strlen(hostname) - 1] == ']') 4006 host = "unknown"; 4007 else 4008 host = hostname; 4009 addr = anynet_ntoa(sap); 4010 4011 # if NETINET6 4012 /* TCP/Wrappers don't want the IPv6: protocol label */ 4013 if (addr != NULL && sm_strncasecmp(addr, "IPv6:", 5) == 0) 4014 addr += 5; 4015 # endif /* NETINET6 */ 4016 4017 if (!hosts_ctl("sendmail", host, addr, STRING_UNKNOWN)) 4018 { 4019 if (tTd(48, 4)) 4020 sm_dprintf(" ... validate_connection: BAD (tcpwrappers)\n"); 4021 if (LogLevel > 3) 4022 sm_syslog(LOG_NOTICE, e->e_id, 4023 "tcpwrappers (%s, %s) rejection", 4024 host, addr); 4025 return "Access denied"; 4026 } 4027 #endif /* TCPWRAPPERS */ 4028 if (tTd(48, 4)) 4029 sm_dprintf(" ... validate_connection: OK\n"); 4030 return NULL; 4031 } 4032 4033 /* 4034 ** STRTOL -- convert string to long integer 4035 ** 4036 ** For systems that don't have it in the C library. 4037 ** 4038 ** This is taken verbatim from the 4.4-Lite C library. 4039 */ 4040 4041 #if NEEDSTRTOL 4042 4043 # if defined(LIBC_SCCS) && !defined(lint) 4044 static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93"; 4045 # endif /* defined(LIBC_SCCS) && !defined(lint) */ 4046 4047 /* 4048 ** Convert a string to a long integer. 4049 ** 4050 ** Ignores `locale' stuff. Assumes that the upper and lower case 4051 ** alphabets and digits are each contiguous. 4052 */ 4053 4054 long 4055 strtol(nptr, endptr, base) 4056 const char *nptr; 4057 char **endptr; 4058 register int base; 4059 { 4060 register const char *s = nptr; 4061 register unsigned long acc; 4062 register int c; 4063 register unsigned long cutoff; 4064 register int neg = 0, any, cutlim; 4065 4066 /* 4067 ** Skip white space and pick up leading +/- sign if any. 4068 ** If base is 0, allow 0x for hex and 0 for octal, else 4069 ** assume decimal; if base is already 16, allow 0x. 4070 */ 4071 do { 4072 c = *s++; 4073 } while (isspace(c)); 4074 if (c == '-') { 4075 neg = 1; 4076 c = *s++; 4077 } else if (c == '+') 4078 c = *s++; 4079 if ((base == 0 || base == 16) && 4080 c == '0' && (*s == 'x' || *s == 'X')) { 4081 c = s[1]; 4082 s += 2; 4083 base = 16; 4084 } 4085 if (base == 0) 4086 base = c == '0' ? 8 : 10; 4087 4088 /* 4089 ** Compute the cutoff value between legal numbers and illegal 4090 ** numbers. That is the largest legal value, divided by the 4091 ** base. An input number that is greater than this value, if 4092 ** followed by a legal input character, is too big. One that 4093 ** is equal to this value may be valid or not; the limit 4094 ** between valid and invalid numbers is then based on the last 4095 ** digit. For instance, if the range for longs is 4096 ** [-2147483648..2147483647] and the input base is 10, 4097 ** cutoff will be set to 214748364 and cutlim to either 4098 ** 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated 4099 ** a value > 214748364, or equal but the next digit is > 7 (or 8), 4100 ** the number is too big, and we will return a range error. 4101 ** 4102 ** Set any if any `digits' consumed; make it negative to indicate 4103 ** overflow. 4104 */ 4105 cutoff = neg ? -(unsigned long) LONG_MIN : LONG_MAX; 4106 cutlim = cutoff % (unsigned long) base; 4107 cutoff /= (unsigned long) base; 4108 for (acc = 0, any = 0;; c = *s++) { 4109 if (isdigit(c)) 4110 c -= '0'; 4111 else if (isalpha(c)) 4112 c -= isupper(c) ? 'A' - 10 : 'a' - 10; 4113 else 4114 break; 4115 if (c >= base) 4116 break; 4117 if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim) 4118 any = -1; 4119 else { 4120 any = 1; 4121 acc *= base; 4122 acc += c; 4123 } 4124 } 4125 if (any < 0) { 4126 acc = neg ? LONG_MIN : LONG_MAX; 4127 errno = ERANGE; 4128 } else if (neg) 4129 acc = -acc; 4130 if (endptr != 0) 4131 *endptr = (char *)(any ? s - 1 : nptr); 4132 return acc; 4133 } 4134 4135 #endif /* NEEDSTRTOL */ 4136 /* 4137 ** STRSTR -- find first substring in string 4138 ** 4139 ** Parameters: 4140 ** big -- the big (full) string. 4141 ** little -- the little (sub) string. 4142 ** 4143 ** Returns: 4144 ** A pointer to the first instance of little in big. 4145 ** big if little is the null string. 4146 ** NULL if little is not contained in big. 4147 */ 4148 4149 #if NEEDSTRSTR 4150 4151 char * 4152 strstr(big, little) 4153 char *big; 4154 char *little; 4155 { 4156 register char *p = big; 4157 int l; 4158 4159 if (*little == '\0') 4160 return big; 4161 l = strlen(little); 4162 4163 while ((p = strchr(p, *little)) != NULL) 4164 { 4165 if (strncmp(p, little, l) == 0) 4166 return p; 4167 p++; 4168 } 4169 return NULL; 4170 } 4171 4172 #endif /* NEEDSTRSTR */ 4173 /* 4174 ** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX 4175 ** 4176 ** Some operating systems have wierd problems with the gethostbyXXX 4177 ** routines. For example, Solaris versions at least through 2.3 4178 ** don't properly deliver a canonical h_name field. This tries to 4179 ** work around these problems. 4180 ** 4181 ** Support IPv6 as well as IPv4. 4182 */ 4183 4184 #if NETINET6 && NEEDSGETIPNODE 4185 4186 # ifndef AI_DEFAULT 4187 # define AI_DEFAULT 0 /* dummy */ 4188 # endif /* ! AI_DEFAULT */ 4189 # ifndef AI_ADDRCONFIG 4190 # define AI_ADDRCONFIG 0 /* dummy */ 4191 # endif /* ! AI_ADDRCONFIG */ 4192 # ifndef AI_V4MAPPED 4193 # define AI_V4MAPPED 0 /* dummy */ 4194 # endif /* ! AI_V4MAPPED */ 4195 # ifndef AI_ALL 4196 # define AI_ALL 0 /* dummy */ 4197 # endif /* ! AI_ALL */ 4198 4199 static struct hostent * 4200 getipnodebyname(name, family, flags, err) 4201 char *name; 4202 int family; 4203 int flags; 4204 int *err; 4205 { 4206 bool resv6 = true; 4207 struct hostent *h; 4208 4209 if (family == AF_INET6) 4210 { 4211 /* From RFC2133, section 6.1 */ 4212 resv6 = bitset(RES_USE_INET6, _res.options); 4213 _res.options |= RES_USE_INET6; 4214 } 4215 SM_SET_H_ERRNO(0); 4216 h = gethostbyname(name); 4217 if (!resv6) 4218 _res.options &= ~RES_USE_INET6; 4219 *err = h_errno; 4220 return h; 4221 } 4222 4223 static struct hostent * 4224 getipnodebyaddr(addr, len, family, err) 4225 char *addr; 4226 int len; 4227 int family; 4228 int *err; 4229 { 4230 struct hostent *h; 4231 4232 SM_SET_H_ERRNO(0); 4233 h = gethostbyaddr(addr, len, family); 4234 *err = h_errno; 4235 return h; 4236 } 4237 4238 void 4239 freehostent(h) 4240 struct hostent *h; 4241 { 4242 /* 4243 ** Stub routine -- if they don't have getipnodeby*(), 4244 ** they probably don't have the free routine either. 4245 */ 4246 4247 return; 4248 } 4249 #endif /* NETINET6 && NEEDSGETIPNODE */ 4250 4251 struct hostent * 4252 sm_gethostbyname(name, family) 4253 char *name; 4254 int family; 4255 { 4256 int save_errno; 4257 struct hostent *h = NULL; 4258 #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) 4259 # if SOLARIS == 20300 || SOLARIS == 203 4260 static struct hostent hp; 4261 static char buf[1000]; 4262 extern struct hostent *_switch_gethostbyname_r(); 4263 4264 if (tTd(61, 10)) 4265 sm_dprintf("_switch_gethostbyname_r(%s)... ", name); 4266 h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno); 4267 save_errno = errno; 4268 # else /* SOLARIS == 20300 || SOLARIS == 203 */ 4269 extern struct hostent *__switch_gethostbyname(); 4270 4271 if (tTd(61, 10)) 4272 sm_dprintf("__switch_gethostbyname(%s)... ", name); 4273 h = __switch_gethostbyname(name); 4274 save_errno = errno; 4275 # endif /* SOLARIS == 20300 || SOLARIS == 203 */ 4276 #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ 4277 int nmaps; 4278 # if NETINET6 4279 int flags = AI_DEFAULT|AI_ALL; 4280 int err; 4281 # endif /* NETINET6 */ 4282 char *maptype[MAXMAPSTACK]; 4283 short mapreturn[MAXMAPACTIONS]; 4284 char hbuf[MAXNAME]; 4285 4286 if (tTd(61, 10)) 4287 sm_dprintf("sm_gethostbyname(%s, %d)... ", name, family); 4288 4289 # if NETINET6 4290 # if ADDRCONFIG_IS_BROKEN 4291 flags &= ~AI_ADDRCONFIG; 4292 # endif /* ADDRCONFIG_IS_BROKEN */ 4293 h = getipnodebyname(name, family, flags, &err); 4294 SM_SET_H_ERRNO(err); 4295 # else /* NETINET6 */ 4296 h = gethostbyname(name); 4297 # endif /* NETINET6 */ 4298 4299 save_errno = errno; 4300 if (h == NULL) 4301 { 4302 if (tTd(61, 10)) 4303 sm_dprintf("failure\n"); 4304 4305 nmaps = switch_map_find("hosts", maptype, mapreturn); 4306 while (--nmaps >= 0) 4307 { 4308 if (strcmp(maptype[nmaps], "nis") == 0 || 4309 strcmp(maptype[nmaps], "files") == 0) 4310 break; 4311 } 4312 4313 if (nmaps >= 0) 4314 { 4315 /* try short name */ 4316 if (strlen(name) > sizeof hbuf - 1) 4317 { 4318 errno = save_errno; 4319 return NULL; 4320 } 4321 (void) sm_strlcpy(hbuf, name, sizeof hbuf); 4322 (void) shorten_hostname(hbuf); 4323 4324 /* if it hasn't been shortened, there's no point */ 4325 if (strcmp(hbuf, name) != 0) 4326 { 4327 if (tTd(61, 10)) 4328 sm_dprintf("sm_gethostbyname(%s, %d)... ", 4329 hbuf, family); 4330 4331 # if NETINET6 4332 h = getipnodebyname(hbuf, family, flags, &err); 4333 SM_SET_H_ERRNO(err); 4334 save_errno = errno; 4335 # else /* NETINET6 */ 4336 h = gethostbyname(hbuf); 4337 save_errno = errno; 4338 # endif /* NETINET6 */ 4339 } 4340 } 4341 } 4342 #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4)) */ 4343 if (tTd(61, 10)) 4344 { 4345 if (h == NULL) 4346 sm_dprintf("failure\n"); 4347 else 4348 { 4349 sm_dprintf("%s\n", h->h_name); 4350 if (tTd(61, 11)) 4351 { 4352 #if NETINET6 4353 struct in6_addr ia6; 4354 char buf6[INET6_ADDRSTRLEN]; 4355 #else /* NETINET6 */ 4356 struct in_addr ia; 4357 #endif /* NETINET6 */ 4358 size_t i; 4359 4360 if (h->h_aliases != NULL) 4361 for (i = 0; h->h_aliases[i] != NULL; 4362 i++) 4363 sm_dprintf("\talias: %s\n", 4364 h->h_aliases[i]); 4365 for (i = 0; h->h_addr_list[i] != NULL; i++) 4366 { 4367 char *addr; 4368 4369 #if NETINET6 4370 memmove(&ia6, h->h_addr_list[i], 4371 IN6ADDRSZ); 4372 addr = anynet_ntop(&ia6, 4373 buf6, sizeof buf6); 4374 #else /* NETINET6 */ 4375 memmove(&ia, h->h_addr_list[i], 4376 INADDRSZ); 4377 addr = (char *) inet_ntoa(ia); 4378 #endif /* NETINET6 */ 4379 if (addr != NULL) 4380 sm_dprintf("\taddr: %s\n", addr); 4381 } 4382 } 4383 } 4384 } 4385 errno = save_errno; 4386 return h; 4387 } 4388 4389 struct hostent * 4390 sm_gethostbyaddr(addr, len, type) 4391 char *addr; 4392 int len; 4393 int type; 4394 { 4395 struct hostent *hp; 4396 4397 #if NETINET6 4398 if (type == AF_INET6 && 4399 IN6_IS_ADDR_UNSPECIFIED((struct in6_addr *) addr)) 4400 { 4401 /* Avoid reverse lookup for IPv6 unspecified address */ 4402 SM_SET_H_ERRNO(HOST_NOT_FOUND); 4403 return NULL; 4404 } 4405 #endif /* NETINET6 */ 4406 4407 #if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) 4408 # if SOLARIS == 20300 || SOLARIS == 203 4409 { 4410 static struct hostent he; 4411 static char buf[1000]; 4412 extern struct hostent *_switch_gethostbyaddr_r(); 4413 4414 hp = _switch_gethostbyaddr_r(addr, len, type, &he, 4415 buf, sizeof(buf), &h_errno); 4416 } 4417 # else /* SOLARIS == 20300 || SOLARIS == 203 */ 4418 { 4419 extern struct hostent *__switch_gethostbyaddr(); 4420 4421 hp = __switch_gethostbyaddr(addr, len, type); 4422 } 4423 # endif /* SOLARIS == 20300 || SOLARIS == 203 */ 4424 #else /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ 4425 # if NETINET6 4426 { 4427 int err; 4428 4429 hp = getipnodebyaddr(addr, len, type, &err); 4430 SM_SET_H_ERRNO(err); 4431 } 4432 # else /* NETINET6 */ 4433 hp = gethostbyaddr(addr, len, type); 4434 # endif /* NETINET6 */ 4435 #endif /* (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) */ 4436 return hp; 4437 } 4438 /* 4439 ** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid 4440 */ 4441 4442 struct passwd * 4443 sm_getpwnam(user) 4444 char *user; 4445 { 4446 #ifdef _AIX4 4447 extern struct passwd *_getpwnam_shadow(const char *, const int); 4448 4449 return _getpwnam_shadow(user, 0); 4450 #else /* _AIX4 */ 4451 return getpwnam(user); 4452 #endif /* _AIX4 */ 4453 } 4454 4455 struct passwd * 4456 sm_getpwuid(uid) 4457 UID_T uid; 4458 { 4459 #if defined(_AIX4) && 0 4460 extern struct passwd *_getpwuid_shadow(const int, const int); 4461 4462 return _getpwuid_shadow(uid,0); 4463 #else /* defined(_AIX4) && 0 */ 4464 return getpwuid(uid); 4465 #endif /* defined(_AIX4) && 0 */ 4466 } 4467 /* 4468 ** SECUREWARE_SETUP_SECURE -- Convex SecureWare setup 4469 ** 4470 ** Set up the trusted computing environment for C2 level security 4471 ** under SecureWare. 4472 ** 4473 ** Parameters: 4474 ** uid -- uid of the user to initialize in the TCB 4475 ** 4476 ** Returns: 4477 ** none 4478 ** 4479 ** Side Effects: 4480 ** Initialized the user in the trusted computing base 4481 */ 4482 4483 #if SECUREWARE 4484 4485 # include <sys/security.h> 4486 # include <prot.h> 4487 4488 void 4489 secureware_setup_secure(uid) 4490 UID_T uid; 4491 { 4492 int rc; 4493 4494 if (getluid() != -1) 4495 return; 4496 4497 if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN) 4498 { 4499 switch (rc) 4500 { 4501 case SSI_NO_PRPW_ENTRY: 4502 syserr("No protected passwd entry, uid = %d", 4503 (int) uid); 4504 break; 4505 4506 case SSI_LOCKED: 4507 syserr("Account has been disabled, uid = %d", 4508 (int) uid); 4509 break; 4510 4511 case SSI_RETIRED: 4512 syserr("Account has been retired, uid = %d", 4513 (int) uid); 4514 break; 4515 4516 case SSI_BAD_SET_LUID: 4517 syserr("Could not set LUID, uid = %d", (int) uid); 4518 break; 4519 4520 case SSI_BAD_SET_PRIVS: 4521 syserr("Could not set kernel privs, uid = %d", 4522 (int) uid); 4523 4524 default: 4525 syserr("Unknown return code (%d) from set_secure_info(%d)", 4526 rc, (int) uid); 4527 break; 4528 } 4529 finis(false, true, EX_NOPERM); 4530 } 4531 } 4532 #endif /* SECUREWARE */ 4533 /* 4534 ** ADD_HOSTNAMES -- Add a hostname to class 'w' based on IP address 4535 ** 4536 ** Add hostnames to class 'w' based on the IP address read from 4537 ** the network interface. 4538 ** 4539 ** Parameters: 4540 ** sa -- a pointer to a SOCKADDR containing the address 4541 ** 4542 ** Returns: 4543 ** 0 if successful, -1 if host lookup fails. 4544 */ 4545 4546 static int 4547 add_hostnames(sa) 4548 SOCKADDR *sa; 4549 { 4550 struct hostent *hp; 4551 char **ha; 4552 char hnb[MAXHOSTNAMELEN]; 4553 4554 /* lookup name with IP address */ 4555 switch (sa->sa.sa_family) 4556 { 4557 #if NETINET 4558 case AF_INET: 4559 hp = sm_gethostbyaddr((char *) &sa->sin.sin_addr, 4560 sizeof(sa->sin.sin_addr), 4561 sa->sa.sa_family); 4562 break; 4563 #endif /* NETINET */ 4564 4565 #if NETINET6 4566 case AF_INET6: 4567 hp = sm_gethostbyaddr((char *) &sa->sin6.sin6_addr, 4568 sizeof(sa->sin6.sin6_addr), 4569 sa->sa.sa_family); 4570 break; 4571 #endif /* NETINET6 */ 4572 4573 default: 4574 /* Give warning about unsupported family */ 4575 if (LogLevel > 3) 4576 sm_syslog(LOG_WARNING, NOQID, 4577 "Unsupported address family %d: %.100s", 4578 sa->sa.sa_family, anynet_ntoa(sa)); 4579 return -1; 4580 } 4581 4582 if (hp == NULL) 4583 { 4584 int save_errno = errno; 4585 4586 if (LogLevel > 3 && 4587 #if NETINET6 4588 !(sa->sa.sa_family == AF_INET6 && 4589 IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr)) && 4590 #endif /* NETINET6 */ 4591 true) 4592 sm_syslog(LOG_WARNING, NOQID, 4593 "gethostbyaddr(%.100s) failed: %d", 4594 anynet_ntoa(sa), 4595 #if NAMED_BIND 4596 h_errno 4597 #else /* NAMED_BIND */ 4598 -1 4599 #endif /* NAMED_BIND */ 4600 ); 4601 errno = save_errno; 4602 return -1; 4603 } 4604 4605 /* save its cname */ 4606 if (!wordinclass((char *) hp->h_name, 'w')) 4607 { 4608 setclass('w', (char *) hp->h_name); 4609 if (tTd(0, 4)) 4610 sm_dprintf("\ta.k.a.: %s\n", hp->h_name); 4611 4612 if (sm_snprintf(hnb, sizeof hnb, "[%s]", hp->h_name) < sizeof hnb 4613 && !wordinclass((char *) hnb, 'w')) 4614 setclass('w', hnb); 4615 } 4616 else 4617 { 4618 if (tTd(0, 43)) 4619 sm_dprintf("\ta.k.a.: %s (already in $=w)\n", hp->h_name); 4620 } 4621 4622 /* save all it aliases name */ 4623 for (ha = hp->h_aliases; ha != NULL && *ha != NULL; ha++) 4624 { 4625 if (!wordinclass(*ha, 'w')) 4626 { 4627 setclass('w', *ha); 4628 if (tTd(0, 4)) 4629 sm_dprintf("\ta.k.a.: %s\n", *ha); 4630 if (sm_snprintf(hnb, sizeof hnb, 4631 "[%s]", *ha) < sizeof hnb && 4632 !wordinclass((char *) hnb, 'w')) 4633 setclass('w', hnb); 4634 } 4635 else 4636 { 4637 if (tTd(0, 43)) 4638 sm_dprintf("\ta.k.a.: %s (already in $=w)\n", 4639 *ha); 4640 } 4641 } 4642 #if NETINET6 4643 freehostent(hp); 4644 #endif /* NETINET6 */ 4645 return 0; 4646 } 4647 /* 4648 ** LOAD_IF_NAMES -- load interface-specific names into $=w 4649 ** 4650 ** Parameters: 4651 ** none. 4652 ** 4653 ** Returns: 4654 ** none. 4655 ** 4656 ** Side Effects: 4657 ** Loads $=w with the names of all the interfaces. 4658 */ 4659 4660 #if !NETINET 4661 # define SIOCGIFCONF_IS_BROKEN 1 /* XXX */ 4662 #endif /* !NETINET */ 4663 4664 #if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN 4665 struct rtentry; 4666 struct mbuf; 4667 # ifndef SUNOS403 4668 # include <sys/time.h> 4669 # endif /* ! SUNOS403 */ 4670 # if (_AIX4 >= 40300) && !defined(_NET_IF_H) 4671 # undef __P 4672 # endif /* (_AIX4 >= 40300) && !defined(_NET_IF_H) */ 4673 # include <net/if.h> 4674 #endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ 4675 4676 void 4677 load_if_names() 4678 { 4679 # if NETINET6 && defined(SIOCGLIFCONF) 4680 # ifdef __hpux 4681 4682 /* 4683 ** Unfortunately, HP has changed all of the structures, 4684 ** making life difficult for implementors. 4685 */ 4686 4687 # define lifconf if_laddrconf 4688 # define lifc_len iflc_len 4689 # define lifc_buf iflc_buf 4690 # define lifreq if_laddrreq 4691 # define lifr_addr iflr_addr 4692 # define lifr_name iflr_name 4693 # define lifr_flags iflr_flags 4694 # define ss_family sa_family 4695 # undef SIOCGLIFNUM 4696 # endif /* __hpux */ 4697 4698 int s; 4699 int i; 4700 size_t len; 4701 int numifs; 4702 char *buf; 4703 struct lifconf lifc; 4704 # ifdef SIOCGLIFNUM 4705 struct lifnum lifn; 4706 # endif /* SIOCGLIFNUM */ 4707 4708 s = socket(InetMode, SOCK_DGRAM, 0); 4709 if (s == -1) 4710 return; 4711 4712 /* get the list of known IP address from the kernel */ 4713 # ifdef __hpux 4714 i = ioctl(s, SIOCGIFNUM, (char *) &numifs); 4715 # endif /* __hpux */ 4716 # ifdef SIOCGLIFNUM 4717 lifn.lifn_family = AF_UNSPEC; 4718 lifn.lifn_flags = 0; 4719 i = ioctl(s, SIOCGLIFNUM, (char *)&lifn); 4720 numifs = lifn.lifn_count; 4721 # endif /* SIOCGLIFNUM */ 4722 4723 # if defined(__hpux) || defined(SIOCGLIFNUM) 4724 if (i < 0) 4725 { 4726 /* can't get number of interfaces -- fall back */ 4727 if (tTd(0, 4)) 4728 sm_dprintf("SIOCGLIFNUM failed: %s\n", 4729 sm_errstring(errno)); 4730 numifs = -1; 4731 } 4732 else if (tTd(0, 42)) 4733 sm_dprintf("system has %d interfaces\n", numifs); 4734 if (numifs < 0) 4735 # endif /* defined(__hpux) || defined(SIOCGLIFNUM) */ 4736 numifs = MAXINTERFACES; 4737 4738 if (numifs <= 0) 4739 { 4740 (void) close(s); 4741 return; 4742 } 4743 4744 len = lifc.lifc_len = numifs * sizeof (struct lifreq); 4745 buf = lifc.lifc_buf = xalloc(lifc.lifc_len); 4746 # ifndef __hpux 4747 lifc.lifc_family = AF_UNSPEC; 4748 lifc.lifc_flags = 0; 4749 # endif /* ! __hpux */ 4750 if (ioctl(s, SIOCGLIFCONF, (char *)&lifc) < 0) 4751 { 4752 if (tTd(0, 4)) 4753 sm_dprintf("SIOCGLIFCONF failed: %s\n", 4754 sm_errstring(errno)); 4755 (void) close(s); 4756 sm_free(buf); 4757 return; 4758 } 4759 4760 /* scan the list of IP address */ 4761 if (tTd(0, 40)) 4762 sm_dprintf("scanning for interface specific names, lifc_len=%ld\n", 4763 (long) len); 4764 4765 for (i = 0; i < len && i >= 0; ) 4766 { 4767 int flags; 4768 struct lifreq *ifr = (struct lifreq *)&buf[i]; 4769 SOCKADDR *sa = (SOCKADDR *) &ifr->lifr_addr; 4770 int af = ifr->lifr_addr.ss_family; 4771 char *addr; 4772 char *name; 4773 struct in6_addr ia6; 4774 struct in_addr ia; 4775 # ifdef SIOCGLIFFLAGS 4776 struct lifreq ifrf; 4777 # endif /* SIOCGLIFFLAGS */ 4778 char ip_addr[256]; 4779 char buf6[INET6_ADDRSTRLEN]; 4780 4781 /* 4782 ** We must close and recreate the socket each time 4783 ** since we don't know what type of socket it is now 4784 ** (each status function may change it). 4785 */ 4786 4787 (void) close(s); 4788 4789 s = socket(af, SOCK_DGRAM, 0); 4790 if (s == -1) 4791 { 4792 sm_free(buf); /* XXX */ 4793 return; 4794 } 4795 4796 /* 4797 ** If we don't have a complete ifr structure, 4798 ** don't try to use it. 4799 */ 4800 4801 if ((len - i) < sizeof *ifr) 4802 break; 4803 4804 # ifdef BSD4_4_SOCKADDR 4805 if (sa->sa.sa_len > sizeof ifr->lifr_addr) 4806 i += sizeof ifr->lifr_name + sa->sa.sa_len; 4807 else 4808 # endif /* BSD4_4_SOCKADDR */ 4809 i += sizeof *ifr; 4810 4811 if (tTd(0, 20)) 4812 sm_dprintf("%s\n", anynet_ntoa(sa)); 4813 4814 if (af != AF_INET && af != AF_INET6) 4815 continue; 4816 4817 # ifdef SIOCGLIFFLAGS 4818 memset(&ifrf, '\0', sizeof(struct lifreq)); 4819 (void) sm_strlcpy(ifrf.lifr_name, ifr->lifr_name, 4820 sizeof(ifrf.lifr_name)); 4821 if (ioctl(s, SIOCGLIFFLAGS, (char *) &ifrf) < 0) 4822 { 4823 if (tTd(0, 4)) 4824 sm_dprintf("SIOCGLIFFLAGS failed: %s\n", 4825 sm_errstring(errno)); 4826 continue; 4827 } 4828 4829 name = ifr->lifr_name; 4830 flags = ifrf.lifr_flags; 4831 4832 if (tTd(0, 41)) 4833 sm_dprintf("\tflags: %lx\n", (unsigned long) flags); 4834 4835 if (!bitset(IFF_UP, flags)) 4836 continue; 4837 # endif /* SIOCGLIFFLAGS */ 4838 4839 ip_addr[0] = '\0'; 4840 4841 /* extract IP address from the list*/ 4842 switch (af) 4843 { 4844 case AF_INET6: 4845 # ifdef __KAME__ 4846 /* convert into proper scoped address */ 4847 if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || 4848 IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && 4849 sa->sin6.sin6_scope_id == 0) 4850 { 4851 struct in6_addr *ia6p; 4852 4853 ia6p = &sa->sin6.sin6_addr; 4854 sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | 4855 ((unsigned int)ia6p->s6_addr[2] << 8)); 4856 ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; 4857 } 4858 # endif /* __KAME__ */ 4859 ia6 = sa->sin6.sin6_addr; 4860 if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) 4861 { 4862 addr = anynet_ntop(&ia6, buf6, sizeof buf6); 4863 message("WARNING: interface %s is UP with %s address", 4864 name, addr == NULL ? "(NULL)" : addr); 4865 continue; 4866 } 4867 4868 /* save IP address in text from */ 4869 addr = anynet_ntop(&ia6, buf6, sizeof buf6); 4870 if (addr != NULL) 4871 (void) sm_snprintf(ip_addr, sizeof ip_addr, 4872 "[%.*s]", 4873 (int) sizeof ip_addr - 3, 4874 addr); 4875 break; 4876 4877 case AF_INET: 4878 ia = sa->sin.sin_addr; 4879 if (ia.s_addr == INADDR_ANY || 4880 ia.s_addr == INADDR_NONE) 4881 { 4882 message("WARNING: interface %s is UP with %s address", 4883 name, inet_ntoa(ia)); 4884 continue; 4885 } 4886 4887 /* save IP address in text from */ 4888 (void) sm_snprintf(ip_addr, sizeof ip_addr, "[%.*s]", 4889 (int) sizeof ip_addr - 3, inet_ntoa(ia)); 4890 break; 4891 } 4892 4893 if (*ip_addr == '\0') 4894 continue; 4895 4896 if (!wordinclass(ip_addr, 'w')) 4897 { 4898 setclass('w', ip_addr); 4899 if (tTd(0, 4)) 4900 sm_dprintf("\ta.k.a.: %s\n", ip_addr); 4901 } 4902 4903 # ifdef SIOCGLIFFLAGS 4904 /* skip "loopback" interface "lo" */ 4905 if (DontProbeInterfaces == DPI_SKIPLOOPBACK && 4906 bitset(IFF_LOOPBACK, flags)) 4907 continue; 4908 # endif /* SIOCGLIFFLAGS */ 4909 (void) add_hostnames(sa); 4910 } 4911 sm_free(buf); /* XXX */ 4912 (void) close(s); 4913 # else /* NETINET6 && defined(SIOCGLIFCONF) */ 4914 # if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN 4915 int s; 4916 int i; 4917 struct ifconf ifc; 4918 int numifs; 4919 4920 s = socket(AF_INET, SOCK_DGRAM, 0); 4921 if (s == -1) 4922 return; 4923 4924 /* get the list of known IP address from the kernel */ 4925 # if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN 4926 if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0) 4927 { 4928 /* can't get number of interfaces -- fall back */ 4929 if (tTd(0, 4)) 4930 sm_dprintf("SIOCGIFNUM failed: %s\n", 4931 sm_errstring(errno)); 4932 numifs = -1; 4933 } 4934 else if (tTd(0, 42)) 4935 sm_dprintf("system has %d interfaces\n", numifs); 4936 if (numifs < 0) 4937 # endif /* defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN */ 4938 numifs = MAXINTERFACES; 4939 4940 if (numifs <= 0) 4941 { 4942 (void) close(s); 4943 return; 4944 } 4945 ifc.ifc_len = numifs * sizeof (struct ifreq); 4946 ifc.ifc_buf = xalloc(ifc.ifc_len); 4947 if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0) 4948 { 4949 if (tTd(0, 4)) 4950 sm_dprintf("SIOCGIFCONF failed: %s\n", 4951 sm_errstring(errno)); 4952 (void) close(s); 4953 return; 4954 } 4955 4956 /* scan the list of IP address */ 4957 if (tTd(0, 40)) 4958 sm_dprintf("scanning for interface specific names, ifc_len=%d\n", 4959 ifc.ifc_len); 4960 4961 for (i = 0; i < ifc.ifc_len && i >= 0; ) 4962 { 4963 int af; 4964 struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i]; 4965 SOCKADDR *sa = (SOCKADDR *) &ifr->ifr_addr; 4966 # if NETINET6 4967 char *addr; 4968 struct in6_addr ia6; 4969 # endif /* NETINET6 */ 4970 struct in_addr ia; 4971 # ifdef SIOCGIFFLAGS 4972 struct ifreq ifrf; 4973 # endif /* SIOCGIFFLAGS */ 4974 char ip_addr[256]; 4975 # if NETINET6 4976 char buf6[INET6_ADDRSTRLEN]; 4977 # endif /* NETINET6 */ 4978 4979 /* 4980 ** If we don't have a complete ifr structure, 4981 ** don't try to use it. 4982 */ 4983 4984 if ((ifc.ifc_len - i) < sizeof *ifr) 4985 break; 4986 4987 # ifdef BSD4_4_SOCKADDR 4988 if (sa->sa.sa_len > sizeof ifr->ifr_addr) 4989 i += sizeof ifr->ifr_name + sa->sa.sa_len; 4990 else 4991 # endif /* BSD4_4_SOCKADDR */ 4992 i += sizeof *ifr; 4993 4994 if (tTd(0, 20)) 4995 sm_dprintf("%s\n", anynet_ntoa(sa)); 4996 4997 af = ifr->ifr_addr.sa_family; 4998 if (af != AF_INET 4999 # if NETINET6 5000 && af != AF_INET6 5001 # endif /* NETINET6 */ 5002 ) 5003 continue; 5004 5005 # ifdef SIOCGIFFLAGS 5006 memset(&ifrf, '\0', sizeof(struct ifreq)); 5007 (void) sm_strlcpy(ifrf.ifr_name, ifr->ifr_name, 5008 sizeof(ifrf.ifr_name)); 5009 (void) ioctl(s, SIOCGIFFLAGS, (char *) &ifrf); 5010 if (tTd(0, 41)) 5011 sm_dprintf("\tflags: %lx\n", 5012 (unsigned long) ifrf.ifr_flags); 5013 # define IFRFREF ifrf 5014 # else /* SIOCGIFFLAGS */ 5015 # define IFRFREF (*ifr) 5016 # endif /* SIOCGIFFLAGS */ 5017 5018 if (!bitset(IFF_UP, IFRFREF.ifr_flags)) 5019 continue; 5020 5021 ip_addr[0] = '\0'; 5022 5023 /* extract IP address from the list*/ 5024 switch (af) 5025 { 5026 case AF_INET: 5027 ia = sa->sin.sin_addr; 5028 if (ia.s_addr == INADDR_ANY || 5029 ia.s_addr == INADDR_NONE) 5030 { 5031 message("WARNING: interface %s is UP with %s address", 5032 ifr->ifr_name, inet_ntoa(ia)); 5033 continue; 5034 } 5035 5036 /* save IP address in text from */ 5037 (void) sm_snprintf(ip_addr, sizeof ip_addr, "[%.*s]", 5038 (int) sizeof ip_addr - 3, 5039 inet_ntoa(ia)); 5040 break; 5041 5042 # if NETINET6 5043 case AF_INET6: 5044 # ifdef __KAME__ 5045 /* convert into proper scoped address */ 5046 if ((IN6_IS_ADDR_LINKLOCAL(&sa->sin6.sin6_addr) || 5047 IN6_IS_ADDR_SITELOCAL(&sa->sin6.sin6_addr)) && 5048 sa->sin6.sin6_scope_id == 0) 5049 { 5050 struct in6_addr *ia6p; 5051 5052 ia6p = &sa->sin6.sin6_addr; 5053 sa->sin6.sin6_scope_id = ntohs(ia6p->s6_addr[3] | 5054 ((unsigned int)ia6p->s6_addr[2] << 8)); 5055 ia6p->s6_addr[2] = ia6p->s6_addr[3] = 0; 5056 } 5057 # endif /* __KAME__ */ 5058 ia6 = sa->sin6.sin6_addr; 5059 if (IN6_IS_ADDR_UNSPECIFIED(&ia6)) 5060 { 5061 addr = anynet_ntop(&ia6, buf6, sizeof buf6); 5062 message("WARNING: interface %s is UP with %s address", 5063 ifr->ifr_name, 5064 addr == NULL ? "(NULL)" : addr); 5065 continue; 5066 } 5067 5068 /* save IP address in text from */ 5069 addr = anynet_ntop(&ia6, buf6, sizeof buf6); 5070 if (addr != NULL) 5071 (void) sm_snprintf(ip_addr, sizeof ip_addr, 5072 "[%.*s]", 5073 (int) sizeof ip_addr - 3, 5074 addr); 5075 break; 5076 5077 # endif /* NETINET6 */ 5078 } 5079 5080 if (ip_addr[0] == '\0') 5081 continue; 5082 5083 if (!wordinclass(ip_addr, 'w')) 5084 { 5085 setclass('w', ip_addr); 5086 if (tTd(0, 4)) 5087 sm_dprintf("\ta.k.a.: %s\n", ip_addr); 5088 } 5089 5090 /* skip "loopback" interface "lo" */ 5091 if (DontProbeInterfaces == DPI_SKIPLOOPBACK && 5092 bitset(IFF_LOOPBACK, IFRFREF.ifr_flags)) 5093 continue; 5094 5095 (void) add_hostnames(sa); 5096 } 5097 sm_free(ifc.ifc_buf); /* XXX */ 5098 (void) close(s); 5099 # undef IFRFREF 5100 # endif /* defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN */ 5101 # endif /* NETINET6 && defined(SIOCGLIFCONF) */ 5102 } 5103 /* 5104 ** ISLOOPBACK -- is socket address in the loopback net? 5105 ** 5106 ** Parameters: 5107 ** sa -- socket address. 5108 ** 5109 ** Returns: 5110 ** true -- is socket address in the loopback net? 5111 ** false -- otherwise 5112 ** 5113 */ 5114 5115 bool 5116 isloopback(sa) 5117 SOCKADDR sa; 5118 { 5119 #if NETINET6 5120 if (IN6_IS_ADDR_LOOPBACK(&sa.sin6.sin6_addr)) 5121 return true; 5122 #else /* NETINET6 */ 5123 /* XXX how to correctly extract IN_LOOPBACKNET part? */ 5124 if (((ntohl(sa.sin.sin_addr.s_addr) & IN_CLASSA_NET) 5125 >> IN_CLASSA_NSHIFT) == IN_LOOPBACKNET) 5126 return true; 5127 #endif /* NETINET6 */ 5128 return false; 5129 } 5130 /* 5131 ** GET_NUM_PROCS_ONLINE -- return the number of processors currently online 5132 ** 5133 ** Parameters: 5134 ** none. 5135 ** 5136 ** Returns: 5137 ** The number of processors online. 5138 */ 5139 5140 static int 5141 get_num_procs_online() 5142 { 5143 int nproc = 0; 5144 5145 #ifdef USESYSCTL 5146 # if defined(CTL_HW) && defined(HW_NCPU) 5147 size_t sz; 5148 int mib[2]; 5149 5150 mib[0] = CTL_HW; 5151 mib[1] = HW_NCPU; 5152 sz = (size_t) sizeof nproc; 5153 (void) sysctl(mib, 2, &nproc, &sz, NULL, 0); 5154 # endif /* defined(CTL_HW) && defined(HW_NCPU) */ 5155 #else /* USESYSCTL */ 5156 # ifdef _SC_NPROCESSORS_ONLN 5157 nproc = (int) sysconf(_SC_NPROCESSORS_ONLN); 5158 # else /* _SC_NPROCESSORS_ONLN */ 5159 # ifdef __hpux 5160 # include <sys/pstat.h> 5161 struct pst_dynamic psd; 5162 5163 if (pstat_getdynamic(&psd, sizeof(psd), (size_t)1, 0) != -1) 5164 nproc = psd.psd_proc_cnt; 5165 # endif /* __hpux */ 5166 # endif /* _SC_NPROCESSORS_ONLN */ 5167 #endif /* USESYSCTL */ 5168 5169 if (nproc <= 0) 5170 nproc = 1; 5171 return nproc; 5172 } 5173 /* 5174 ** SM_CLOSEFROM -- close file descriptors 5175 ** 5176 ** Parameters: 5177 ** lowest -- first fd to close 5178 ** highest -- last fd + 1 to close 5179 ** 5180 ** Returns: 5181 ** none 5182 */ 5183 5184 void 5185 sm_closefrom(lowest, highest) 5186 int lowest, highest; 5187 { 5188 #if HASCLOSEFROM 5189 closefrom(lowest); 5190 #else /* HASCLOSEFROM */ 5191 int i; 5192 5193 for (i = lowest; i < highest; i++) 5194 (void) close(i); 5195 #endif /* HASCLOSEFROM */ 5196 } 5197 #if HASFDWALK 5198 /* 5199 ** CLOSEFD_WALK -- walk fd's arranging to close them 5200 ** Callback for fdwalk() 5201 ** 5202 ** Parameters: 5203 ** lowest -- first fd to arrange to be closed 5204 ** fd -- fd to arrange to be closed 5205 ** 5206 ** Returns: 5207 ** zero 5208 */ 5209 5210 static int 5211 closefd_walk(lowest, fd) 5212 void *lowest; 5213 int fd; 5214 { 5215 if (fd >= *(int *)lowest) 5216 (void) fcntl(fd, F_SETFD, FD_CLOEXEC); 5217 return 0; 5218 } 5219 #endif /* HASFDWALK */ 5220 /* 5221 ** SM_CLOSE_ON_EXEC -- arrange for file descriptors to be closed 5222 ** 5223 ** Parameters: 5224 ** lowest -- first fd to arrange to be closed 5225 ** highest -- last fd + 1 to arrange to be closed 5226 ** 5227 ** Returns: 5228 ** none 5229 */ 5230 5231 void 5232 sm_close_on_exec(highest, lowest) 5233 int highest, lowest; 5234 { 5235 #if HASFDWALK 5236 (void) fdwalk(closefd_walk, &lowest); 5237 #else /* HASFDWALK */ 5238 int i, j; 5239 5240 for (i = lowest; i < highest; i++) 5241 { 5242 if ((j = fcntl(i, F_GETFD, 0)) != -1) 5243 (void) fcntl(i, F_SETFD, j | FD_CLOEXEC); 5244 } 5245 #endif /* HASFDWALK */ 5246 } 5247 /* 5248 ** SEED_RANDOM -- seed the random number generator 5249 ** 5250 ** Parameters: 5251 ** none 5252 ** 5253 ** Returns: 5254 ** none 5255 */ 5256 5257 void 5258 seed_random() 5259 { 5260 #if HASSRANDOMDEV 5261 srandomdev(); 5262 #else /* HASSRANDOMDEV */ 5263 long seed; 5264 struct timeval t; 5265 5266 seed = (long) CurrentPid; 5267 if (gettimeofday(&t, NULL) >= 0) 5268 seed += t.tv_sec + t.tv_usec; 5269 5270 # if HASRANDOM 5271 (void) srandom(seed); 5272 # else /* HASRANDOM */ 5273 (void) srand((unsigned int) seed); 5274 # endif /* HASRANDOM */ 5275 #endif /* HASSRANDOMDEV */ 5276 } 5277 /* 5278 ** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE 5279 ** 5280 ** Parameters: 5281 ** level -- syslog level 5282 ** id -- envelope ID or NULL (NOQUEUE) 5283 ** fmt -- format string 5284 ** arg... -- arguments as implied by fmt. 5285 ** 5286 ** Returns: 5287 ** none 5288 */ 5289 5290 /* VARARGS3 */ 5291 void 5292 #ifdef __STDC__ 5293 sm_syslog(int level, const char *id, const char *fmt, ...) 5294 #else /* __STDC__ */ 5295 sm_syslog(level, id, fmt, va_alist) 5296 int level; 5297 const char *id; 5298 const char *fmt; 5299 va_dcl 5300 #endif /* __STDC__ */ 5301 { 5302 static char *buf = NULL; 5303 static size_t bufsize; 5304 char *begin, *end; 5305 int save_errno; 5306 int seq = 1; 5307 int idlen; 5308 char buf0[MAXLINE]; 5309 char *newstring; 5310 extern int SyslogPrefixLen; 5311 SM_VA_LOCAL_DECL 5312 5313 save_errno = errno; 5314 if (id == NULL) 5315 { 5316 id = "NOQUEUE"; 5317 idlen = strlen(id) + SyslogPrefixLen; 5318 } 5319 else if (strcmp(id, NOQID) == 0) 5320 { 5321 id = ""; 5322 idlen = SyslogPrefixLen; 5323 } 5324 else 5325 idlen = strlen(id) + SyslogPrefixLen; 5326 5327 if (buf == NULL) 5328 { 5329 buf = buf0; 5330 bufsize = sizeof buf0; 5331 } 5332 5333 for (;;) 5334 { 5335 int n; 5336 5337 /* print log message into buf */ 5338 SM_VA_START(ap, fmt); 5339 n = sm_vsnprintf(buf, bufsize, fmt, ap); 5340 SM_VA_END(ap); 5341 SM_ASSERT(n > 0); 5342 if (n < bufsize) 5343 break; 5344 5345 /* String too small, redo with correct size */ 5346 bufsize = n + 1; 5347 if (buf != buf0) 5348 { 5349 sm_free(buf); 5350 buf = NULL; 5351 } 5352 buf = sm_malloc_x(bufsize); 5353 } 5354 5355 /* clean up buf after it has been expanded with args */ 5356 newstring = str2prt(buf); 5357 if ((strlen(newstring) + idlen + 1) < SYSLOG_BUFSIZE) 5358 { 5359 #if LOG 5360 if (*id == '\0') 5361 syslog(level, "%s", newstring); 5362 else 5363 syslog(level, "%s: %s", id, newstring); 5364 #else /* LOG */ 5365 /*XXX should do something more sensible */ 5366 if (*id == '\0') 5367 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, "%s\n", 5368 newstring); 5369 else 5370 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5371 "%s: %s\n", id, newstring); 5372 #endif /* LOG */ 5373 if (buf == buf0) 5374 buf = NULL; 5375 errno = save_errno; 5376 return; 5377 } 5378 5379 /* 5380 ** additional length for splitting: " ..." + 3, where 3 is magic to 5381 ** have some data for the next entry. 5382 */ 5383 5384 #define SL_SPLIT 7 5385 5386 begin = newstring; 5387 idlen += 5; /* strlen("[999]"), see below */ 5388 while (*begin != '\0' && 5389 (strlen(begin) + idlen) > SYSLOG_BUFSIZE) 5390 { 5391 char save; 5392 5393 if (seq >= 999) 5394 { 5395 /* Too many messages */ 5396 break; 5397 } 5398 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5399 while (end > begin) 5400 { 5401 /* Break on comma or space */ 5402 if (*end == ',' || *end == ' ') 5403 { 5404 end++; /* Include separator */ 5405 break; 5406 } 5407 end--; 5408 } 5409 /* No separator, break midstring... */ 5410 if (end == begin) 5411 end = begin + SYSLOG_BUFSIZE - idlen - SL_SPLIT; 5412 save = *end; 5413 *end = 0; 5414 #if LOG 5415 syslog(level, "%s[%d]: %s ...", id, seq++, begin); 5416 #else /* LOG */ 5417 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5418 "%s[%d]: %s ...\n", id, seq++, begin); 5419 #endif /* LOG */ 5420 *end = save; 5421 begin = end; 5422 } 5423 if (seq >= 999) 5424 #if LOG 5425 syslog(level, "%s[%d]: log terminated, too many parts", 5426 id, seq); 5427 #else /* LOG */ 5428 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5429 "%s[%d]: log terminated, too many parts\n", id, seq); 5430 #endif /* LOG */ 5431 else if (*begin != '\0') 5432 #if LOG 5433 syslog(level, "%s[%d]: %s", id, seq, begin); 5434 #else /* LOG */ 5435 (void) sm_io_fprintf(smioerr, SM_TIME_DEFAULT, 5436 "%s[%d]: %s\n", id, seq, begin); 5437 #endif /* LOG */ 5438 if (buf == buf0) 5439 buf = NULL; 5440 errno = save_errno; 5441 } 5442 /* 5443 ** HARD_SYSLOG -- call syslog repeatedly until it works 5444 ** 5445 ** Needed on HP-UX, which apparently doesn't guarantee that 5446 ** syslog succeeds during interrupt handlers. 5447 */ 5448 5449 #if defined(__hpux) && !defined(HPUX11) 5450 5451 # define MAXSYSLOGTRIES 100 5452 # undef syslog 5453 # ifdef V4FS 5454 # define XCNST const 5455 # define CAST (const char *) 5456 # else /* V4FS */ 5457 # define XCNST 5458 # define CAST 5459 # endif /* V4FS */ 5460 5461 void 5462 # ifdef __STDC__ 5463 hard_syslog(int pri, XCNST char *msg, ...) 5464 # else /* __STDC__ */ 5465 hard_syslog(pri, msg, va_alist) 5466 int pri; 5467 XCNST char *msg; 5468 va_dcl 5469 # endif /* __STDC__ */ 5470 { 5471 int i; 5472 char buf[SYSLOG_BUFSIZE]; 5473 SM_VA_LOCAL_DECL 5474 5475 SM_VA_START(ap, msg); 5476 (void) sm_vsnprintf(buf, sizeof buf, msg, ap); 5477 SM_VA_END(ap); 5478 5479 for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; ) 5480 continue; 5481 } 5482 5483 # undef CAST 5484 #endif /* defined(__hpux) && !defined(HPUX11) */ 5485 #if NEEDLOCAL_HOSTNAME_LENGTH 5486 /* 5487 ** LOCAL_HOSTNAME_LENGTH 5488 ** 5489 ** This is required to get sendmail to compile against BIND 4.9.x 5490 ** on Ultrix. 5491 ** 5492 ** Unfortunately, a Compaq Y2K patch kit provides it without 5493 ** bumping __RES in /usr/include/resolv.h so we can't automatically 5494 ** figure out whether it is needed. 5495 */ 5496 5497 int 5498 local_hostname_length(hostname) 5499 char *hostname; 5500 { 5501 size_t len_host, len_domain; 5502 5503 if (!*_res.defdname) 5504 res_init(); 5505 len_host = strlen(hostname); 5506 len_domain = strlen(_res.defdname); 5507 if (len_host > len_domain && 5508 (sm_strcasecmp(hostname + len_host - len_domain, 5509 _res.defdname) == 0) && 5510 hostname[len_host - len_domain - 1] == '.') 5511 return len_host - len_domain - 1; 5512 else 5513 return 0; 5514 } 5515 #endif /* NEEDLOCAL_HOSTNAME_LENGTH */ 5516 5517 #if NEEDLINK 5518 /* 5519 ** LINK -- clone a file 5520 ** 5521 ** Some OS's lacks link() and hard links. Since sendmail is using 5522 ** link() as an efficient way to clone files, this implementation 5523 ** will simply do a file copy. 5524 ** 5525 ** NOTE: This link() replacement is not a generic replacement as it 5526 ** does not handle all of the semantics of the real link(2). 5527 ** 5528 ** Parameters: 5529 ** source -- pathname of existing file. 5530 ** target -- pathname of link (clone) to be created. 5531 ** 5532 ** Returns: 5533 ** 0 -- success. 5534 ** -1 -- failure, see errno for details. 5535 */ 5536 5537 int 5538 link(source, target) 5539 const char *source; 5540 const char *target; 5541 { 5542 int save_errno; 5543 int sff; 5544 int src = -1, dst = -1; 5545 ssize_t readlen; 5546 ssize_t writelen; 5547 char buf[BUFSIZ]; 5548 struct stat st; 5549 5550 sff = SFF_REGONLY|SFF_OPENASROOT; 5551 if (DontLockReadFiles) 5552 sff |= SFF_NOLOCK; 5553 5554 /* Open the original file */ 5555 src = safeopen((char *)source, O_RDONLY, 0, sff); 5556 if (src < 0) 5557 goto fail; 5558 5559 /* Obtain the size and the mode */ 5560 if (fstat(src, &st) < 0) 5561 goto fail; 5562 5563 /* Create the duplicate copy */ 5564 sff &= ~SFF_NOLOCK; 5565 sff |= SFF_CREAT; 5566 dst = safeopen((char *)target, O_CREAT|O_EXCL|O_WRONLY, 5567 st.st_mode, sff); 5568 if (dst < 0) 5569 goto fail; 5570 5571 /* Copy all of the bytes one buffer at a time */ 5572 while ((readlen = read(src, &buf, sizeof(buf))) > 0) 5573 { 5574 ssize_t left = readlen; 5575 char *p = buf; 5576 5577 while (left > 0 && 5578 (writelen = write(dst, p, (size_t) left)) >= 0) 5579 { 5580 left -= writelen; 5581 p += writelen; 5582 } 5583 if (writelen < 0) 5584 break; 5585 } 5586 5587 /* Any trouble reading? */ 5588 if (readlen < 0 || writelen < 0) 5589 goto fail; 5590 5591 /* Close the input file */ 5592 if (close(src) < 0) 5593 { 5594 src = -1; 5595 goto fail; 5596 } 5597 src = -1; 5598 5599 /* Close the output file */ 5600 if (close(dst) < 0) 5601 { 5602 /* don't set dst = -1 here so we unlink the file */ 5603 goto fail; 5604 } 5605 5606 /* Success */ 5607 return 0; 5608 5609 fail: 5610 save_errno = errno; 5611 if (src >= 0) 5612 (void) close(src); 5613 if (dst >= 0) 5614 { 5615 (void) unlink(target); 5616 (void) close(dst); 5617 } 5618 errno = save_errno; 5619 return -1; 5620 } 5621 #endif /* NEEDLINK */ 5622 5623 /* 5624 ** Compile-Time options 5625 */ 5626 5627 char *CompileOptions[] = 5628 { 5629 #if ALLOW_255 5630 "ALLOW_255", 5631 #endif /* ALLOW_255 */ 5632 #if NAMED_BIND 5633 # if DNSMAP 5634 "DNSMAP", 5635 # endif /* DNSMAP */ 5636 #endif /* NAMED_BIND */ 5637 #if EGD 5638 "EGD", 5639 #endif /* EGD */ 5640 #if HESIOD 5641 "HESIOD", 5642 #endif /* HESIOD */ 5643 #if HES_GETMAILHOST 5644 "HES_GETMAILHOST", 5645 #endif /* HES_GETMAILHOST */ 5646 #if LDAPMAP 5647 "LDAPMAP", 5648 #endif /* LDAPMAP */ 5649 #if LOG 5650 "LOG", 5651 #endif /* LOG */ 5652 #if MAP_NSD 5653 "MAP_NSD", 5654 #endif /* MAP_NSD */ 5655 #if MAP_REGEX 5656 "MAP_REGEX", 5657 #endif /* MAP_REGEX */ 5658 #if MATCHGECOS 5659 "MATCHGECOS", 5660 #endif /* MATCHGECOS */ 5661 #if MILTER 5662 "MILTER", 5663 #endif /* MILTER */ 5664 #if MIME7TO8 5665 "MIME7TO8", 5666 #endif /* MIME7TO8 */ 5667 #if MIME7TO8_OLD 5668 "MIME7TO8_OLD", 5669 #endif /* MIME7TO8_OLD */ 5670 #if MIME8TO7 5671 "MIME8TO7", 5672 #endif /* MIME8TO7 */ 5673 #if NAMED_BIND 5674 "NAMED_BIND", 5675 #endif /* NAMED_BIND */ 5676 #if NDBM 5677 "NDBM", 5678 #endif /* NDBM */ 5679 #if NETINET 5680 "NETINET", 5681 #endif /* NETINET */ 5682 #if NETINET6 5683 "NETINET6", 5684 #endif /* NETINET6 */ 5685 #if NETINFO 5686 "NETINFO", 5687 #endif /* NETINFO */ 5688 #if NETISO 5689 "NETISO", 5690 #endif /* NETISO */ 5691 #if NETNS 5692 "NETNS", 5693 #endif /* NETNS */ 5694 #if NETUNIX 5695 "NETUNIX", 5696 #endif /* NETUNIX */ 5697 #if NETX25 5698 "NETX25", 5699 #endif /* NETX25 */ 5700 #if NEWDB 5701 "NEWDB", 5702 #endif /* NEWDB */ 5703 #if NIS 5704 "NIS", 5705 #endif /* NIS */ 5706 #if NISPLUS 5707 "NISPLUS", 5708 #endif /* NISPLUS */ 5709 #if NO_DH 5710 "NO_DH", 5711 #endif /* NO_DH */ 5712 #if PH_MAP 5713 "PH_MAP", 5714 #endif /* PH_MAP */ 5715 #ifdef PICKY_HELO_CHECK 5716 "PICKY_HELO_CHECK", 5717 #endif /* PICKY_HELO_CHECK */ 5718 #if PIPELINING 5719 "PIPELINING", 5720 #endif /* PIPELINING */ 5721 #if SASL 5722 # if SASL >= 20000 5723 "SASLv2", 5724 # else /* SASL >= 20000 */ 5725 "SASL", 5726 # endif /* SASL >= 20000 */ 5727 #endif /* SASL */ 5728 #if SCANF 5729 "SCANF", 5730 #endif /* SCANF */ 5731 #if SMTPDEBUG 5732 "SMTPDEBUG", 5733 #endif /* SMTPDEBUG */ 5734 #if SOCKETMAP 5735 "SOCKETMAP", 5736 #endif /* SOCKETMAP */ 5737 #if STARTTLS 5738 "STARTTLS", 5739 #endif /* STARTTLS */ 5740 #if SUID_ROOT_FILES_OK 5741 "SUID_ROOT_FILES_OK", 5742 #endif /* SUID_ROOT_FILES_OK */ 5743 #if TCPWRAPPERS 5744 "TCPWRAPPERS", 5745 #endif /* TCPWRAPPERS */ 5746 #if TLS_NO_RSA 5747 "TLS_NO_RSA", 5748 #endif /* TLS_NO_RSA */ 5749 #if TLS_VRFY_PER_CTX 5750 "TLS_VRFY_PER_CTX", 5751 #endif /* TLS_VRFY_PER_CTX */ 5752 #if USERDB 5753 "USERDB", 5754 #endif /* USERDB */ 5755 #if USE_LDAP_INIT 5756 "USE_LDAP_INIT", 5757 #endif /* USE_LDAP_INIT */ 5758 #if USE_TTYPATH 5759 "USE_TTYPATH", 5760 #endif /* USE_TTYPATH */ 5761 #if XDEBUG 5762 "XDEBUG", 5763 #endif /* XDEBUG */ 5764 #if XLA 5765 "XLA", 5766 #endif /* XLA */ 5767 NULL 5768 }; 5769 5770 5771 /* 5772 ** OS compile options. 5773 */ 5774 5775 char *OsCompileOptions[] = 5776 { 5777 #if ADDRCONFIG_IS_BROKEN 5778 "ADDRCONFIG_IS_BROKEN", 5779 #endif /* ADDRCONFIG_IS_BROKEN */ 5780 #ifdef AUTO_NETINFO_HOSTS 5781 "AUTO_NETINFO_HOSTS", 5782 #endif /* AUTO_NETINFO_HOSTS */ 5783 #ifdef AUTO_NIS_ALIASES 5784 "AUTO_NIS_ALIASES", 5785 #endif /* AUTO_NIS_ALIASES */ 5786 #if BROKEN_RES_SEARCH 5787 "BROKEN_RES_SEARCH", 5788 #endif /* BROKEN_RES_SEARCH */ 5789 #ifdef BSD4_4_SOCKADDR 5790 "BSD4_4_SOCKADDR", 5791 #endif /* BSD4_4_SOCKADDR */ 5792 #if BOGUS_O_EXCL 5793 "BOGUS_O_EXCL", 5794 #endif /* BOGUS_O_EXCL */ 5795 #if DEC_OSF_BROKEN_GETPWENT 5796 "DEC_OSF_BROKEN_GETPWENT", 5797 #endif /* DEC_OSF_BROKEN_GETPWENT */ 5798 #if FAST_PID_RECYCLE 5799 "FAST_PID_RECYCLE", 5800 #endif /* FAST_PID_RECYCLE */ 5801 #if HASCLOSEFROM 5802 "HASCLOSEFROM", 5803 #endif /* HASCLOSEFROM */ 5804 #if HASFCHOWN 5805 "HASFCHOWN", 5806 #endif /* HASFCHOWN */ 5807 #if HASFCHMOD 5808 "HASFCHMOD", 5809 #endif /* HASFCHMOD */ 5810 #if HASFDWALK 5811 "HASFDWALK", 5812 #endif /* HASFDWALK */ 5813 #if HASFLOCK 5814 "HASFLOCK", 5815 #endif /* HASFLOCK */ 5816 #if HASGETDTABLESIZE 5817 "HASGETDTABLESIZE", 5818 #endif /* HASGETDTABLESIZE */ 5819 #if HASGETUSERSHELL 5820 "HASGETUSERSHELL", 5821 #endif /* HASGETUSERSHELL */ 5822 #if HASINITGROUPS 5823 "HASINITGROUPS", 5824 #endif /* HASINITGROUPS */ 5825 #if HASLSTAT 5826 "HASLSTAT", 5827 #endif /* HASLSTAT */ 5828 #if HASNICE 5829 "HASNICE", 5830 #endif /* HASNICE */ 5831 #if HASRANDOM 5832 "HASRANDOM", 5833 #endif /* HASRANDOM */ 5834 #if HASRRESVPORT 5835 "HASRRESVPORT", 5836 #endif /* HASRRESVPORT */ 5837 #if HASSETEGID 5838 "HASSETEGID", 5839 #endif /* HASSETEGID */ 5840 #if HASSETLOGIN 5841 "HASSETLOGIN", 5842 #endif /* HASSETLOGIN */ 5843 #if HASSETREGID 5844 "HASSETREGID", 5845 #endif /* HASSETREGID */ 5846 #if HASSETRESGID 5847 "HASSETRESGID", 5848 #endif /* HASSETRESGID */ 5849 #if HASSETREUID 5850 "HASSETREUID", 5851 #endif /* HASSETREUID */ 5852 #if HASSETRLIMIT 5853 "HASSETRLIMIT", 5854 #endif /* HASSETRLIMIT */ 5855 #if HASSETSID 5856 "HASSETSID", 5857 #endif /* HASSETSID */ 5858 #if HASSETUSERCONTEXT 5859 "HASSETUSERCONTEXT", 5860 #endif /* HASSETUSERCONTEXT */ 5861 #if HASSETVBUF 5862 "HASSETVBUF", 5863 #endif /* HASSETVBUF */ 5864 #if HAS_ST_GEN 5865 "HAS_ST_GEN", 5866 #endif /* HAS_ST_GEN */ 5867 #if HASSRANDOMDEV 5868 "HASSRANDOMDEV", 5869 #endif /* HASSRANDOMDEV */ 5870 #if HASURANDOMDEV 5871 "HASURANDOMDEV", 5872 #endif /* HASURANDOMDEV */ 5873 #if HASSTRERROR 5874 "HASSTRERROR", 5875 #endif /* HASSTRERROR */ 5876 #if HASULIMIT 5877 "HASULIMIT", 5878 #endif /* HASULIMIT */ 5879 #if HASUNAME 5880 "HASUNAME", 5881 #endif /* HASUNAME */ 5882 #if HASUNSETENV 5883 "HASUNSETENV", 5884 #endif /* HASUNSETENV */ 5885 #if HASWAITPID 5886 "HASWAITPID", 5887 #endif /* HASWAITPID */ 5888 #if IDENTPROTO 5889 "IDENTPROTO", 5890 #endif /* IDENTPROTO */ 5891 #if IP_SRCROUTE 5892 "IP_SRCROUTE", 5893 #endif /* IP_SRCROUTE */ 5894 #if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL 5895 "LOCK_ON_OPEN", 5896 #endif /* O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL */ 5897 #if NEEDFSYNC 5898 "NEEDFSYNC", 5899 #endif /* NEEDFSYNC */ 5900 #if NEEDLINK 5901 "NEEDLINK", 5902 #endif /* NEEDLINK */ 5903 #if NEEDLOCAL_HOSTNAME_LENGTH 5904 "NEEDLOCAL_HOSTNAME_LENGTH", 5905 #endif /* NEEDLOCAL_HOSTNAME_LENGTH */ 5906 #if NEEDSGETIPNODE 5907 "NEEDSGETIPNODE", 5908 #endif /* NEEDSGETIPNODE */ 5909 #if NEEDSTRSTR 5910 "NEEDSTRSTR", 5911 #endif /* NEEDSTRSTR */ 5912 #if NEEDSTRTOL 5913 "NEEDSTRTOL", 5914 #endif /* NEEDSTRTOL */ 5915 #ifdef NO_GETSERVBYNAME 5916 "NO_GETSERVBYNAME", 5917 #endif /* NO_GETSERVBYNAME */ 5918 #if NOFTRUNCATE 5919 "NOFTRUNCATE", 5920 #endif /* NOFTRUNCATE */ 5921 #if REQUIRES_DIR_FSYNC 5922 "REQUIRES_DIR_FSYNC", 5923 #endif /* REQUIRES_DIR_FSYNC */ 5924 #if RLIMIT_NEEDS_SYS_TIME_H 5925 "RLIMIT_NEEDS_SYS_TIME_H", 5926 #endif /* RLIMIT_NEEDS_SYS_TIME_H */ 5927 #if SAFENFSPATHCONF 5928 "SAFENFSPATHCONF", 5929 #endif /* SAFENFSPATHCONF */ 5930 #if SECUREWARE 5931 "SECUREWARE", 5932 #endif /* SECUREWARE */ 5933 #if SHARE_V1 5934 "SHARE_V1", 5935 #endif /* SHARE_V1 */ 5936 #if SIOCGIFCONF_IS_BROKEN 5937 "SIOCGIFCONF_IS_BROKEN", 5938 #endif /* SIOCGIFCONF_IS_BROKEN */ 5939 #if SIOCGIFNUM_IS_BROKEN 5940 "SIOCGIFNUM_IS_BROKEN", 5941 #endif /* SIOCGIFNUM_IS_BROKEN */ 5942 #if SNPRINTF_IS_BROKEN 5943 "SNPRINTF_IS_BROKEN", 5944 #endif /* SNPRINTF_IS_BROKEN */ 5945 #if SO_REUSEADDR_IS_BROKEN 5946 "SO_REUSEADDR_IS_BROKEN", 5947 #endif /* SO_REUSEADDR_IS_BROKEN */ 5948 #if SYS5SETPGRP 5949 "SYS5SETPGRP", 5950 #endif /* SYS5SETPGRP */ 5951 #if SYSTEM5 5952 "SYSTEM5", 5953 #endif /* SYSTEM5 */ 5954 #if USE_DOUBLE_FORK 5955 "USE_DOUBLE_FORK", 5956 #endif /* USE_DOUBLE_FORK */ 5957 #if USE_ENVIRON 5958 "USE_ENVIRON", 5959 #endif /* USE_ENVIRON */ 5960 #if USE_SA_SIGACTION 5961 "USE_SA_SIGACTION", 5962 #endif /* USE_SA_SIGACTION */ 5963 #if USE_SIGLONGJMP 5964 "USE_SIGLONGJMP", 5965 #endif /* USE_SIGLONGJMP */ 5966 #if USEGETCONFATTR 5967 "USEGETCONFATTR", 5968 #endif /* USEGETCONFATTR */ 5969 #if USESETEUID 5970 "USESETEUID", 5971 #endif /* USESETEUID */ 5972 #ifdef USESYSCTL 5973 "USESYSCTL", 5974 #endif /* USESYSCTL */ 5975 #if USING_NETSCAPE_LDAP 5976 "USING_NETSCAPE_LDAP", 5977 #endif /* USING_NETSCAPE_LDAP */ 5978 #ifdef WAITUNION 5979 "WAITUNION", 5980 #endif /* WAITUNION */ 5981 NULL 5982 }; 5983 5984 /* 5985 ** FFR compile options. 5986 */ 5987 5988 char *FFRCompileOptions[] = 5989 { 5990 #if _FFR_ALLOW_SASLINFO 5991 /* DefaultAuthInfo can be specified by user. */ 5992 /* DefaultAuthInfo doesn't really work in 8.13 anymore. */ 5993 "_FFR_ALLOW_SASLINFO", 5994 #endif /* _FFR_ALLOW_SASLINFO */ 5995 #if _FFR_BESTMX_BETTER_TRUNCATION 5996 /* Better truncation of list of MX records for dns map. */ 5997 "_FFR_BESTMX_BETTER_TRUNCATION", 5998 #endif /* _FFR_BESTMX_BETTER_TRUNCATION */ 5999 #if _FFR_BLOCK_PROXIES 6000 /* 6001 ** Try to deal with open HTTP proxies that are used to send spam 6002 ** by recognizing some commands from them. 6003 */ 6004 6005 "_FFR_BLOCK_PROXIES", 6006 #endif /* _FFR_BLOCK_PROXIES */ 6007 #if _FFR_CATCH_BROKEN_MTAS 6008 /* Deal with MTAs that send a reply during the DATA phase. */ 6009 "_FFR_CATCH_BROKEN_MTAS", 6010 #endif /* _FFR_CATCH_BROKEN_MTAS */ 6011 #if _FFR_CHECK_EOM 6012 /* Enable check_eom ruleset */ 6013 "_FFR_CHECK_EOM", 6014 #endif /* _FFR_CHECK_EOM */ 6015 #if _FFR_CHK_QUEUE 6016 /* Stricter checks about queue directory permissions. */ 6017 "_FFR_CHK_QUEUE", 6018 #endif /* _FFR_CHK_QUEUE */ 6019 #if _FFR_CLIENT_SIZE 6020 /* Don't try to send mail if its size exceeds SIZE= of server. */ 6021 "_FFR_CLIENT_SIZE", 6022 #endif /* _FFR_CLIENT_SIZE */ 6023 #if _FFR_CONTROL_MSTAT 6024 /* Extended daemon status. */ 6025 "_FFR_CONTROL_MSTAT", 6026 #endif /* _FFR_CONTROL_MSTAT */ 6027 #if _FFR_CRLPATH 6028 /* CRLPath; needs documentation; Al Smith */ 6029 "_FFR_CRLPATH", 6030 #endif /* _FFR_CRLPATH */ 6031 #if _FFR_DAEMON_NETUNIX 6032 /* Allow local (not just TCP) socket connection to server. */ 6033 "_FFR_DAEMON_NETUNIX", 6034 #endif /* _FFR_DAEMON_NETUNIX */ 6035 #if _FFR_DEPRECATE_MAILER_FLAG_I 6036 /* What it says :-) */ 6037 "_FFR_DEPRECATE_MAILER_FLAG_I", 6038 #endif /* _FFR_DEPRECATE_MAILER_FLAG_I */ 6039 #if _FFR_DIGUNIX_SAFECHOWN 6040 /* Properly set SAFECHOWN (include/sm/conf.h) for Digital UNIX */ 6041 /* Problem noted by Anne Bennett of Concordia University */ 6042 "_FFR_DIGUNIX_SAFECHOWN", 6043 #endif /* _FFR_DIGUNIX_SAFECHOWN */ 6044 #if _FFR_DNSMAP_ALIASABLE 6045 /* Allow dns map type to be used for aliases. */ 6046 /* Don Lewis of TDK */ 6047 "_FFR_DNSMAP_ALIASABLE", 6048 #endif /* _FFR_DNSMAP_ALIASABLE */ 6049 #if _FFR_DNSMAP_BASE 6050 /* Specify a "base" domain for DNS lookups. */ 6051 "_FFR_DNSMAP_BASE", 6052 #endif /* _FFR_DNSMAP_BASE */ 6053 #if _FFR_DNSMAP_MULTI 6054 /* Allow multiple return values for DNS map. */ 6055 "_FFR_DNSMAP_MULTI", 6056 # if _FFR_DNSMAP_MULTILIMIT 6057 /* Limit number of return values for DNS map. */ 6058 "_FFR_DNSMAP_MULTILIMIT", 6059 # endif /* _FFR_DNSMAP_MULTILIMIT */ 6060 #endif /* _FFR_DNSMAP_MULTI */ 6061 #if _FFR_DONTLOCKFILESFORREAD_OPTION 6062 /* Enable DontLockFilesForRead option. */ 6063 "_FFR_DONTLOCKFILESFORREAD_OPTION", 6064 #endif /* _FFR_DONTLOCKFILESFORREAD_OPTION */ 6065 #if _FFR_DOTTED_USERNAMES 6066 /* Allow usernames with '.' */ 6067 "_FFR_DOTTED_USERNAMES", 6068 #endif /* _FFR_DOTTED_USERNAMES */ 6069 #if _FFR_DROP_TRUSTUSER_WARNING 6070 /* 6071 ** Don't issue this warning: 6072 ** "readcf: option TrustedUser may cause problems on systems 6073 ** which do not support fchown() if UseMSP is not set. 6074 */ 6075 6076 "_FFR_DROP_TRUSTUSER_WARNING", 6077 #endif /* _FFR_DROP_TRUSTUSER_WARNING */ 6078 #if _FFR_EXTRA_MAP_CHECK 6079 /* perform extra checks on $( $) in R lines */ 6080 "_FFR_EXTRA_MAP_CHECK", 6081 #endif /* _FFR_EXTRA_MAP_CHECK */ 6082 #if _FFR_FIX_DASHT 6083 /* 6084 ** If using -t, force not sending to argv recipients, even 6085 ** if they are mentioned in the headers. 6086 */ 6087 6088 "_FFR_FIX_DASHT", 6089 #endif /* _FFR_FIX_DASHT */ 6090 #if _FFR_FORWARD_SYSERR 6091 /* Cause a "syserr" if forward file isn't "safe". */ 6092 "_FFR_FORWARD_SYSERR", 6093 #endif /* _FFR_FORWARD_SYSERR */ 6094 #if _FFR_GEN_ORCPT 6095 /* Generate a ORCPT DSN arg if not already provided */ 6096 "_FFR_GEN_ORCPT", 6097 #endif /* _FFR_GEN_ORCPT */ 6098 #if _FFR_GROUPREADABLEAUTHINFOFILE 6099 /* Allow group readable DefaultAuthInfo file. */ 6100 "_FFR_GROUPREADABLEAUTHINFOFILE", 6101 #endif /* _FFR_GROUPREADABLEAUTHINFOFILE */ 6102 #if _FFR_HANDLE_ISO8859_GECOS 6103 /* 6104 ** Allow ISO 8859 characters in GECOS field: replace them 6105 ** ith ASCII "equivalent". 6106 */ 6107 6108 /* Peter Eriksson of Linkopings universitet */ 6109 "_FFR_HANDLE_ISO8859_GECOS", 6110 #endif /* _FFR_HANDLE_ISO8859_GECOS */ 6111 #if _FFR_HDR_TYPE 6112 /* Set 'h' in {addr_type} for headers. */ 6113 "_FFR_HDR_TYPE", 6114 #endif /* _FFR_HDR_TYPE */ 6115 #if _FFR_HELONAME 6116 /* option to set heloname; Nik Clayton of FreeBSD */ 6117 "_FFR_HELONAME", 6118 #endif /* _FFR_HELONAME */ 6119 #if _FFR_HPUX_NSSWITCH 6120 /* Use nsswitch on HP-UX */ 6121 "_FFR_HPUX_NSSWITCH", 6122 #endif /* _FFR_HPUX_NSSWITCH */ 6123 #if _FFR_IGNORE_BOGUS_ADDR 6124 /* Ignore addresses for which prescan() failed */ 6125 "_FFR_IGNORE_BOGUS_ADDR", 6126 #endif /* _FFR_IGNORE_BOGUS_ADDR */ 6127 #if _FFR_IGNORE_EXT_ON_HELO 6128 /* Ignore extensions offered in response to HELO */ 6129 "_FFR_IGNORE_EXT_ON_HELO", 6130 #endif /* _FFR_IGNORE_EXT_ON_HELO */ 6131 #if _FFR_MAXDATASIZE 6132 /* 6133 ** It is possible that a header is larger than MILTER_CHUNK_SIZE, 6134 ** hence this shouldn't be used as limit for milter communication. 6135 ** see also libmilter/comm.c 6136 ** Gurusamy Sarathy of ActiveState 6137 */ 6138 6139 "_FFR_MAXDATASIZE", 6140 #endif /* _FFR_MAXDATASIZE */ 6141 #if _FFR_MAX_FORWARD_ENTRIES 6142 /* Try to limit number of .forward entries */ 6143 /* (doesn't work) */ 6144 /* Randall S. Winchester of the University of Maryland */ 6145 "_FFR_MAX_FORWARD_ENTRIES", 6146 #endif /* _FFR_MAX_FORWARD_ENTRIES */ 6147 #if _FFR_MAX_SLEEP_TIME 6148 /* Limit sleep(2) time in libsm/clock.c */ 6149 "_FFR_MAX_SLEEP_TIME", 6150 #endif /* _FFR_MAX_SLEEP_TIME */ 6151 #if _FFR_MILTER_NAGLE 6152 /* milter: turn off Nagle ("cork" on Linux) */ 6153 /* John Gardiner Myers of Proofpoint */ 6154 "_FFR_MILTER_NAGLE ", 6155 #endif /* _FFR_MILTER_NAGLE */ 6156 #if _FFR_MILTER_NOHDR_RESP 6157 /* milter: no response expected when sending headers */ 6158 /* John Gardiner Myers of Proofpoint */ 6159 "_FFR_MILTER_NOHDR_RESP", 6160 #endif /* _FFR_MILTER_NOHDR_RESP */ 6161 #if _FFR_MIME7TO8_OLD 6162 /* Old mime7to8 code, the new is broken for at least one example. */ 6163 "_FFR_MIME7TO8_OLD", 6164 #endif /* _FFR_MAX_SLEEP_TIME */ 6165 #if _FFR_NODELAYDSN_ON_HOLD 6166 /* Do not issue a DELAY DSN for mailers that use the hold flag. */ 6167 /* Steven Pitzl */ 6168 "_FFR_NODELAYDSN_ON_HOLD", 6169 #endif /* _FFR_NODELAYDSN_ON_HOLD */ 6170 #if _FFR_NO_PIPE 6171 /* Disable PIPELINING, delay client if used. */ 6172 "_FFR_NO_PIPE", 6173 #endif /* _FFR_NO_PIPE */ 6174 #if _FFR_PRIV_NOACTUALRECIPIENT 6175 /* 6176 ** PrivacyOptions=noactualrecipient stops sendmail from putting 6177 ** X-Actual-Recipient lines in DSNs revealing the actual 6178 ** account that addresses map to. Patch from Dan Harkless. 6179 */ 6180 6181 "_FFR_PRIV_NOACTUALRECIPIENT" 6182 #endif /* _FFR_PRIV_NOACTUALRECIPIENT */ 6183 #if _FFR_QUEUEDELAY 6184 /* Exponential queue delay; disabled in 8.13 since it isn't used. */ 6185 "_FFR_QUEUEDELAY", 6186 #endif /* _FFR_QUEUEDELAY */ 6187 #if _FFR_QUEUE_GROUP_SORTORDER 6188 /* Allow QueueSortOrder per queue group. */ 6189 /* XXX: Still need to actually use qgrp->qg_sortorder */ 6190 "_FFR_QUEUE_GROUP_SORTORDER", 6191 #endif /* _FFR_QUEUE_GROUP_SORTORDER */ 6192 #if _FFR_QUEUE_MACRO 6193 /* Define {queue} macro. */ 6194 "_FFR_QUEUE_MACRO", 6195 #endif /* _FFR_QUEUE_MACRO */ 6196 #if _FFR_QUEUE_RUN_PARANOIA 6197 /* Additional checks when doing queue runs. */ 6198 "_FFR_QUEUE_RUN_PARANOIA", 6199 #endif /* _FFR_QUEUE_RUN_PARANOIA */ 6200 #if _FFR_QUEUE_SCHED_DBG 6201 /* Debug output for the queue scheduler. */ 6202 "_FFR_QUEUE_SCHED_DBG", 6203 #endif /* _FFR_QUEUE_SCHED_DBG */ 6204 #if _FFR_REDIRECTEMPTY 6205 /* 6206 ** envelope <> can't be sent to mailing lists, only owner- 6207 ** send spam of this type to owner- of the list 6208 ** ---- to stop spam from going to mailing lists. 6209 */ 6210 6211 "_FFR_REDIRECTEMPTY", 6212 #endif /* _FFR_REDIRECTEMPTY */ 6213 #if _FFR_RESET_MACRO_GLOBALS 6214 /* Allow macro 'j' to be set dynamically via rulesets. */ 6215 "_FFR_RESET_MACRO_GLOBALS", 6216 #endif /* _FFR_RESET_MACRO_GLOBALS */ 6217 #if _FFR_RHS 6218 /* Random shuffle for queue sorting. */ 6219 "_FFR_RHS", 6220 #endif /* _FFR_RHS */ 6221 #if _FFR_SELECT_SHM 6222 /* Auto-select of shared memory key */ 6223 "_FFR_SELECT_SHM", 6224 #endif /* _FFR_SELECT_SHM */ 6225 #if _FFR_SHM_STATUS 6226 /* Donated code (unused). */ 6227 "_FFR_SHM_STATUS", 6228 #endif /* _FFR_SHM_STATUS */ 6229 #if _FFR_SKIP_DOMAINS 6230 /* process every N'th domain instead of every N'th message */ 6231 "_FFR_SKIP_DOMAINS", 6232 #endif /* _FFR_SKIP_DOMAINS */ 6233 #if _FFR_SLEEP_USE_SELECT 6234 /* Use select(2) in libsm/clock.c to emulate sleep(2) */ 6235 "_FFR_SLEEP_USE_SELECT ", 6236 #endif /* _FFR_SLEEP_USE_SELECT */ 6237 #if _FFR_SOFT_BOUNCE 6238 /* Turn all errors into temporary errors. */ 6239 "_FFR_SOFT_BOUNCE", 6240 #endif /* _FFR_SOFT_BOUNCE */ 6241 #if _FFR_SPT_ALIGN 6242 /* 6243 ** It looks like the Compaq Tru64 5.1A now aligns argv and envp to 64 6244 ** bit alignment, so unless each piece of argv and envp is a multiple 6245 ** of 8 bytes (including terminating NULL), initsetproctitle() won't 6246 ** use any of the space beyond argv[0]. Be sure to set SPT_ALIGN_SIZE 6247 ** if you use this FFR. 6248 */ 6249 6250 /* Chris Adams of HiWAAY Informations Services */ 6251 "_FFR_SPT_ALIGN", 6252 #endif /* _FFR_SPT_ALIGN */ 6253 #if _FFR_TIMERS 6254 /* Donated code (unused). */ 6255 "_FFR_TIMERS", 6256 #endif /* _FFR_TIMERS */ 6257 #if _FFR_TLS_1 6258 /* More STARTTLS options, e.g., secondary certs. */ 6259 "_FFR_TLS_1", 6260 #endif /* _FFR_TLS_1 */ 6261 #if _FFR_TRUSTED_QF 6262 /* 6263 ** If we don't own the file mark it as unsafe. 6264 ** However, allow TrustedUser to own it as well 6265 ** in case TrustedUser manipulates the queue. 6266 */ 6267 6268 "_FFR_TRUSTED_QF", 6269 #endif /* _FFR_TRUSTED_QF */ 6270 #if _FFR_USE_SETLOGIN 6271 /* Use setlogin() */ 6272 /* Peter Philipp */ 6273 "_FFR_USE_SETLOGIN", 6274 #endif /* _FFR_USE_SETLOGIN */ 6275 NULL 6276 }; 6277 6278