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