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