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