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