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