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