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