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