summaryrefslogtreecommitdiffstats
path: root/usr.sbin/sendmail/src/conf.c
diff options
context:
space:
mode:
Diffstat (limited to 'usr.sbin/sendmail/src/conf.c')
-rw-r--r--usr.sbin/sendmail/src/conf.c5075
1 files changed, 0 insertions, 5075 deletions
diff --git a/usr.sbin/sendmail/src/conf.c b/usr.sbin/sendmail/src/conf.c
deleted file mode 100644
index f689137..0000000
--- a/usr.sbin/sendmail/src/conf.c
+++ /dev/null
@@ -1,5075 +0,0 @@
-/*
- * Copyright (c) 1983, 1995-1997 Eric P. Allman
- * Copyright (c) 1988, 1993
- * The Regents of the University of California. All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- * 3. All advertising materials mentioning features or use of this software
- * must display the following acknowledgement:
- * This product includes software developed by the University of
- * California, Berkeley and its contributors.
- * 4. Neither the name of the University nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#ifndef lint
-static char sccsid[] = "@(#)conf.c 8.379 (Berkeley) 10/20/97";
-#endif /* not lint */
-
-# include "sendmail.h"
-# include "pathnames.h"
-# include <sys/ioctl.h>
-# include <sys/param.h>
-
-/*
-** CONF.C -- Sendmail Configuration Tables.
-**
-** Defines the configuration of this installation.
-**
-** Configuration Variables:
-** HdrInfo -- a table describing well-known header fields.
-** Each entry has the field name and some flags,
-** which are described in sendmail.h.
-**
-** Notes:
-** I have tried to put almost all the reasonable
-** configuration information into the configuration
-** file read at runtime. My intent is that anything
-** here is a function of the version of UNIX you
-** are running, or is really static -- for example
-** the headers are a superset of widely used
-** protocols. If you find yourself playing with
-** this file too much, you may be making a mistake!
-*/
-
-
-
-
-/*
-** Header info table
-** Final (null) entry contains the flags used for any other field.
-**
-** Not all of these are actually handled specially by sendmail
-** at this time. They are included as placeholders, to let
-** you know that "someday" I intend to have sendmail do
-** something with them.
-*/
-
-struct hdrinfo HdrInfo[] =
-{
- /* originator fields, most to least significant */
- { "resent-sender", H_FROM|H_RESENT },
- { "resent-from", H_FROM|H_RESENT },
- { "resent-reply-to", H_FROM|H_RESENT },
- { "sender", H_FROM },
- { "from", H_FROM },
- { "reply-to", H_FROM },
- { "errors-to", H_FROM|H_ERRORSTO },
- { "full-name", H_ACHECK },
- { "return-receipt-to", H_RECEIPTTO },
-
- /* destination fields */
- { "to", H_RCPT },
- { "resent-to", H_RCPT|H_RESENT },
- { "cc", H_RCPT },
- { "resent-cc", H_RCPT|H_RESENT },
- { "bcc", H_RCPT|H_BCC },
- { "resent-bcc", H_RCPT|H_BCC|H_RESENT },
- { "apparently-to", H_RCPT },
-
- /* message identification and control */
- { "message-id", 0 },
- { "resent-message-id", H_RESENT },
- { "message", H_EOH },
- { "text", H_EOH },
-
- /* date fields */
- { "date", 0 },
- { "resent-date", H_RESENT },
-
- /* trace fields */
- { "received", H_TRACE|H_FORCE },
- { "x400-received", H_TRACE|H_FORCE },
- { "via", H_TRACE|H_FORCE },
- { "mail-from", H_TRACE|H_FORCE },
-
- /* miscellaneous fields */
- { "comments", H_FORCE|H_ENCODABLE },
- { "return-path", H_FORCE|H_ACHECK },
- { "content-transfer-encoding", H_CTE },
- { "content-type", H_CTYPE },
- { "content-length", H_ACHECK },
- { "subject", H_ENCODABLE },
-
- { NULL, 0 }
-};
-
-
-
-/*
-** Privacy values
-*/
-
-struct prival PrivacyValues[] =
-{
- { "public", PRIV_PUBLIC },
- { "needmailhelo", PRIV_NEEDMAILHELO },
- { "needexpnhelo", PRIV_NEEDEXPNHELO },
- { "needvrfyhelo", PRIV_NEEDVRFYHELO },
- { "noexpn", PRIV_NOEXPN },
- { "novrfy", PRIV_NOVRFY },
- { "restrictmailq", PRIV_RESTRICTMAILQ },
- { "restrictqrun", PRIV_RESTRICTQRUN },
-#if _FFR_PRIVACY_NOETRN
- { "noetrn", PRIV_NOETRN },
-#endif
- { "authwarnings", PRIV_AUTHWARNINGS },
- { "noreceipts", PRIV_NORECEIPTS },
- { "goaway", PRIV_GOAWAY },
- { NULL, 0 }
-};
-
-
-
-/*
-** Miscellaneous stuff.
-*/
-
-int DtableSize = 50; /* max open files; reset in 4.2bsd */
- /*
-** SETDEFAULTS -- set default values
-**
-** Because of the way freezing is done, these must be initialized
-** using direct code.
-**
-** Parameters:
-** e -- the default envelope.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Initializes a bunch of global variables to their
-** default values.
-*/
-
-#define MINUTES * 60
-#define HOURS * 60 MINUTES
-#define DAYS * 24 HOURS
-
-#ifndef _PATH_VARTMP
-# define _PATH_VARTMP "/usr/tmp/"
-#endif
-
-#ifndef MAXRULERECURSION
-# define MAXRULERECURSION 50 /* max ruleset recursion depth */
-#endif
-
-void
-setdefaults(e)
- register ENVELOPE *e;
-{
- int i;
- char buf[MAXNAME];
- extern void inittimeouts();
- extern void setdefuser();
- extern void setupmaps();
- extern void setupmailers();
- extern void setupheaders();
-
- SpaceSub = ' '; /* option B */
- QueueLA = 8; /* option x */
- RefuseLA = 12; /* option X */
- WkRecipFact = 30000L; /* option y */
- WkClassFact = 1800L; /* option z */
- WkTimeFact = 90000L; /* option Z */
- QueueFactor = WkRecipFact * 20; /* option q */
- FileMode = (RealUid != geteuid()) ? 0644 : 0600;
- /* option F */
- DefUid = 1; /* option u */
- DefGid = 1; /* option g */
- CheckpointInterval = 10; /* option C */
- MaxHopCount = 25; /* option h */
- e->e_sendmode = SM_FORK; /* option d */
- e->e_errormode = EM_PRINT; /* option e */
- SevenBitInput = FALSE; /* option 7 */
- MaxMciCache = 1; /* option k */
- MciCacheTimeout = 5 MINUTES; /* option K */
- LogLevel = 9; /* option L */
- inittimeouts(NULL); /* option r */
- PrivacyFlags = 0; /* option p */
-#if MIME8TO7
- MimeMode = MM_CVTMIME|MM_PASS8BIT; /* option 8 */
-#else
- MimeMode = MM_PASS8BIT;
-#endif
- for (i = 0; i < MAXTOCLASS; i++)
- {
- TimeOuts.to_q_return[i] = 5 DAYS; /* option T */
- TimeOuts.to_q_warning[i] = 0; /* option T */
- }
- ServiceSwitchFile = "/etc/service.switch";
- ServiceCacheMaxAge = (time_t) 10;
- HostsFile = _PATH_HOSTS;
- PidFile = newstr(_PATH_SENDMAILPID);
- MustQuoteChars = "@,;:\\()[].'";
- MciInfoTimeout = 30 MINUTES;
- MaxRuleRecursion = MAXRULERECURSION;
- MaxAliasRecursion = 10;
- MaxMacroRecursion = 10;
- ColonOkInAddr = TRUE;
- DontLockReadFiles = TRUE;
- DoubleBounceAddr = "postmaster";
- snprintf(buf, sizeof buf, "%s%sdead.letter",
- _PATH_VARTMP,
- _PATH_VARTMP[sizeof _PATH_VARTMP - 2] == '/' ? "" : "/");
- DeadLetterDrop = newstr(buf);
- setdefuser();
- setupmaps();
- setupmailers();
- setupheaders();
-}
-
-
-/*
-** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
-*/
-
-void
-setdefuser()
-{
- struct passwd *defpwent;
- static char defuserbuf[40];
-
- DefUser = defuserbuf;
- defpwent = sm_getpwuid(DefUid);
- snprintf(defuserbuf, sizeof defuserbuf, "%s",
- defpwent == NULL ? "nobody" : defpwent->pw_name);
-}
- /*
-** SETUPMAILERS -- initialize default mailers
-*/
-
-void
-setupmailers()
-{
- char buf[100];
- extern void makemailer();
-
- strcpy(buf, "prog, P=/bin/sh, F=lsoDq9, T=DNS/RFC822/X-Unix, A=sh -c \201u");
- makemailer(buf);
-
- strcpy(buf, "*file*, P=[FILE], F=lsDFMPEouq9, T=DNS/RFC822/X-Unix, A=FILE \201u");
- makemailer(buf);
-
- strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE \201u");
- makemailer(buf);
-}
- /*
-** SETUPMAPS -- set up map classes
-*/
-
-#define MAPDEF(name, ext, flags, parse, open, close, lookup, store) \
- { \
- extern bool parse __P((MAP *, char *)); \
- extern bool open __P((MAP *, int)); \
- extern void close __P((MAP *)); \
- extern char *lookup __P((MAP *, char *, char **, int *)); \
- extern void store __P((MAP *, char *, char *)); \
- s = stab(name, ST_MAPCLASS, ST_ENTER); \
- s->s_mapclass.map_cname = name; \
- s->s_mapclass.map_ext = ext; \
- s->s_mapclass.map_cflags = flags; \
- s->s_mapclass.map_parse = parse; \
- s->s_mapclass.map_open = open; \
- s->s_mapclass.map_close = close; \
- s->s_mapclass.map_lookup = lookup; \
- s->s_mapclass.map_store = store; \
- }
-
-void
-setupmaps()
-{
- register STAB *s;
-
-#ifdef NEWDB
- MAPDEF("hash", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
- map_parseargs, hash_map_open, db_map_close,
- db_map_lookup, db_map_store);
-
- MAPDEF("btree", ".db", MCF_ALIASOK|MCF_REBUILDABLE,
- map_parseargs, bt_map_open, db_map_close,
- db_map_lookup, db_map_store);
-#endif
-
-#ifdef NDBM
- MAPDEF("dbm", ".dir", MCF_ALIASOK|MCF_REBUILDABLE,
- map_parseargs, ndbm_map_open, ndbm_map_close,
- ndbm_map_lookup, ndbm_map_store);
-#endif
-
-#ifdef NIS
- MAPDEF("nis", NULL, MCF_ALIASOK,
- map_parseargs, nis_map_open, null_map_close,
- nis_map_lookup, null_map_store);
-#endif
-
-#ifdef NISPLUS
- MAPDEF("nisplus", NULL, MCF_ALIASOK,
- map_parseargs, nisplus_map_open, null_map_close,
- nisplus_map_lookup, null_map_store);
-#endif
-#ifdef LDAPMAP
- MAPDEF("ldapx", NULL, 0,
- ldap_map_parseargs, ldap_map_open, ldap_map_close,
- ldap_map_lookup, null_map_store);
-#endif
-
-#ifdef HESIOD
- MAPDEF("hesiod", NULL, MCF_ALIASOK|MCF_ALIASONLY,
- map_parseargs, hes_map_open, null_map_close,
- hes_map_lookup, null_map_store);
-#endif
-
-#if NETINFO
- MAPDEF("netinfo", NULL, MCF_ALIASOK,
- map_parseargs, ni_map_open, null_map_close,
- ni_map_lookup, null_map_store);
-#endif
-
-#if 0
- MAPDEF("dns", NULL, 0,
- dns_map_init, null_map_open, null_map_close,
- dns_map_lookup, null_map_store);
-#endif
-
-#if NAMED_BIND
- /* best MX DNS lookup */
- MAPDEF("bestmx", NULL, MCF_OPTFILE,
- map_parseargs, null_map_open, null_map_close,
- bestmx_map_lookup, null_map_store);
-#endif
-
- MAPDEF("host", NULL, 0,
- host_map_init, null_map_open, null_map_close,
- host_map_lookup, null_map_store);
-
- MAPDEF("text", NULL, MCF_ALIASOK,
- map_parseargs, text_map_open, null_map_close,
- text_map_lookup, null_map_store);
-
- MAPDEF("stab", NULL, MCF_ALIASOK|MCF_ALIASONLY,
- map_parseargs, stab_map_open, null_map_close,
- stab_map_lookup, stab_map_store);
-
- MAPDEF("implicit", NULL, MCF_ALIASOK|MCF_ALIASONLY|MCF_REBUILDABLE,
- map_parseargs, impl_map_open, impl_map_close,
- impl_map_lookup, impl_map_store);
-
- /* access to system passwd file */
- MAPDEF("user", NULL, MCF_OPTFILE,
- map_parseargs, user_map_open, null_map_close,
- user_map_lookup, null_map_store);
-
- /* dequote map */
- MAPDEF("dequote", NULL, 0,
- dequote_init, null_map_open, null_map_close,
- dequote_map, null_map_store);
-
-#if USERDB
- /* user database */
- MAPDEF("userdb", ".db", 0,
- map_parseargs, null_map_open, null_map_close,
- udb_map_lookup, null_map_store);
-#endif
-
- /* arbitrary programs */
- MAPDEF("program", NULL, MCF_ALIASOK,
- map_parseargs, null_map_open, null_map_close,
- prog_map_lookup, null_map_store);
-
- /* sequenced maps */
- MAPDEF("sequence", NULL, MCF_ALIASOK,
- seq_map_parse, null_map_open, null_map_close,
- seq_map_lookup, seq_map_store);
-
- /* switched interface to sequenced maps */
- MAPDEF("switch", NULL, MCF_ALIASOK,
- map_parseargs, switch_map_open, null_map_close,
- seq_map_lookup, seq_map_store);
-
- /* null map lookup -- really for internal use only */
- MAPDEF("null", NULL, MCF_ALIASOK|MCF_OPTFILE,
- map_parseargs, null_map_open, null_map_close,
- null_map_lookup, null_map_store);
-
-#if _FFR_SYSLOG_MAP
- /* syslog map -- logs information to syslog */
- MAPDEF("syslog", NULL, 0,
- syslog_map_parseargs, null_map_open, null_map_close,
- syslog_map_lookup, null_map_store);
-#endif
-}
-
-#undef MAPDEF
- /*
-** INITHOSTMAPS -- initial host-dependent maps
-**
-** This should act as an interface to any local service switch
-** provided by the host operating system.
-**
-** Parameters:
-** none
-**
-** Returns:
-** none
-**
-** Side Effects:
-** Should define maps "host" and "users" as necessary
-** for this OS. If they are not defined, they will get
-** a default value later. It should check to make sure
-** they are not defined first, since it's possible that
-** the config file has provided an override.
-*/
-
-void
-inithostmaps()
-{
- register int i;
- int nmaps;
- char *maptype[MAXMAPSTACK];
- short mapreturn[MAXMAPACTIONS];
- char buf[MAXLINE];
-
- /*
- ** Set up default hosts maps.
- */
-
-#if 0
- nmaps = switch_map_find("hosts", maptype, mapreturn);
- for (i = 0; i < nmaps; i++)
- {
- if (strcmp(maptype[i], "files") == 0 &&
- stab("hosts.files", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts");
- (void) makemapentry(buf);
- }
-#if NAMED_BIND
- else if (strcmp(maptype[i], "dns") == 0 &&
- stab("hosts.dns", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "hosts.dns dns A");
- (void) makemapentry(buf);
- }
-#endif
-#ifdef NISPLUS
- else if (strcmp(maptype[i], "nisplus") == 0 &&
- stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir");
- (void) makemapentry(buf);
- }
-#endif
-#ifdef NIS
- else if (strcmp(maptype[i], "nis") == 0 &&
- stab("hosts.nis", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname");
- (void) makemapentry(buf);
- }
-#endif
-#if NETINFO
- else if (strcmp(maptype[i], "netinfo") == 0) &&
- stab("hosts.netinfo", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "hosts.netinfo netinfo -v name /machines");
- (void) makemapentry(buf);
- }
-#endif
- }
-#endif
-
- /*
- ** Make sure we have a host map.
- */
-
- if (stab("host", ST_MAP, ST_FIND) == NULL)
- {
- /* user didn't initialize: set up host map */
- strcpy(buf, "host host");
-#if NAMED_BIND
- if (ConfigLevel >= 2)
- strcat(buf, " -a.");
-#endif
- (void) makemapentry(buf);
- }
-
- /*
- ** Set up default aliases maps
- */
-
- nmaps = switch_map_find("aliases", maptype, mapreturn);
- for (i = 0; i < nmaps; i++)
- {
- if (strcmp(maptype[i], "files") == 0 &&
- stab("aliases.files", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "aliases.files null");
- (void) makemapentry(buf);
- }
-#ifdef NISPLUS
- else if (strcmp(maptype[i], "nisplus") == 0 &&
- stab("aliases.nisplus", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "aliases.nisplus nisplus -kalias -vexpansion -d mail_aliases.org_dir");
- (void) makemapentry(buf);
- }
-#endif
-#ifdef NIS
- else if (strcmp(maptype[i], "nis") == 0 &&
- stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "aliases.nis nis -d mail.aliases");
- (void) makemapentry(buf);
- }
-#endif
-#ifdef NETINFO
- else if (strcmp(maptype[i], "netinfo") == 0 &&
- stab("aliases.netinfo", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "aliases.netinfo netinfo -z, /aliases");
- (void) makemapentry(buf);
- }
-#endif
-#ifdef HESIOD
- else if (strcmp(maptype[i], "hesiod") == 0 &&
- stab("aliases.hesiod", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "aliases.hesiod hesiod aliases");
- (void) makemapentry(buf);
- }
-#endif
- }
- if (stab("aliases", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "aliases switch aliases");
- (void) makemapentry(buf);
- }
-
-#if 0 /* "user" map class is a better choice */
- /*
- ** Set up default users maps.
- */
-
- nmaps = switch_map_find("passwd", maptype, mapreturn);
- for (i = 0; i < nmaps; i++)
- {
- if (strcmp(maptype[i], "files") == 0 &&
- stab("users.files", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd");
- (void) makemapentry(buf);
- }
-#ifdef NISPLUS
- else if (strcmp(maptype[i], "nisplus") == 0 &&
- stab("users.nisplus", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "users.nisplus nisplus -m -kname -vhome -d passwd.org_dir");
- (void) makemapentry(buf);
- }
-#endif
-#ifdef NIS
- else if (strcmp(maptype[i], "nis") == 0 &&
- stab("users.nis", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "users.nis nis -m -d passwd.byname");
- (void) makemapentry(buf);
- }
-#endif
-#ifdef HESIOD
- else if (strcmp(maptype[i], "hesiod") == 0) &&
- stab("users.hesiod", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "users.hesiod hesiod");
- (void) makemapentry(buf);
- }
-#endif
- }
- if (stab("users", ST_MAP, ST_FIND) == NULL)
- {
- strcpy(buf, "users switch -m passwd");
- (void) makemapentry(buf);
- }
-#endif
-}
- /*
-** SWITCH_MAP_FIND -- find the list of types associated with a map
-**
-** This is the system-dependent interface to the service switch.
-**
-** Parameters:
-** service -- the name of the service of interest.
-** maptype -- an out-array of strings containing the types
-** of access to use for this service. There can
-** be at most MAXMAPSTACK types for a single service.
-** mapreturn -- an out-array of return information bitmaps
-** for the map.
-**
-** Returns:
-** The number of map types filled in, or -1 for failure.
-*/
-
-#if defined(SOLARIS) || (defined(sony_news) && defined(__svr4))
-# define _USE_SUN_NSSWITCH_
-#endif
-
-#ifdef _USE_SUN_NSSWITCH_
-# include <nsswitch.h>
-#endif
-
-#if defined(ultrix) || (defined(__osf__) && defined(__alpha))
-# define _USE_DEC_SVC_CONF_
-#endif
-
-#ifdef _USE_DEC_SVC_CONF_
-# include <sys/svcinfo.h>
-#endif
-
-int
-switch_map_find(service, maptype, mapreturn)
- char *service;
- char *maptype[MAXMAPSTACK];
- short mapreturn[MAXMAPACTIONS];
-{
- int svcno;
-
-#ifdef _USE_SUN_NSSWITCH_
- struct __nsw_switchconfig *nsw_conf;
- enum __nsw_parse_err pserr;
- struct __nsw_lookup *lk;
- static struct __nsw_lookup lkp0 =
- { "files", {1, 0, 0, 0}, NULL, NULL };
- static struct __nsw_switchconfig lkp_default =
- { 0, "sendmail", 3, &lkp0 };
-
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
-
- if ((nsw_conf = __nsw_getconfig(service, &pserr)) == NULL)
- lk = lkp_default.lookups;
- else
- lk = nsw_conf->lookups;
- svcno = 0;
- while (lk != NULL)
- {
- maptype[svcno] = lk->service_name;
- if (lk->actions[__NSW_NOTFOUND] == __NSW_RETURN)
- mapreturn[MA_NOTFOUND] |= 1 << svcno;
- if (lk->actions[__NSW_TRYAGAIN] == __NSW_RETURN)
- mapreturn[MA_TRYAGAIN] |= 1 << svcno;
- if (lk->actions[__NSW_UNAVAIL] == __NSW_RETURN)
- mapreturn[MA_TRYAGAIN] |= 1 << svcno;
- svcno++;
- lk = lk->next;
- }
- return svcno;
-#endif
-
-#ifdef _USE_DEC_SVC_CONF_
- struct svcinfo *svcinfo;
- int svc;
-
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
-
- svcinfo = getsvc();
- if (svcinfo == NULL)
- goto punt;
- if (strcmp(service, "hosts") == 0)
- svc = SVC_HOSTS;
- else if (strcmp(service, "aliases") == 0)
- svc = SVC_ALIASES;
- else if (strcmp(service, "passwd") == 0)
- svc = SVC_PASSWD;
- else
- return -1;
- for (svcno = 0; svcno < SVC_PATHSIZE; svcno++)
- {
- switch (svcinfo->svcpath[svc][svcno])
- {
- case SVC_LOCAL:
- maptype[svcno] = "files";
- break;
-
- case SVC_YP:
- maptype[svcno] = "nis";
- break;
-
- case SVC_BIND:
- maptype[svcno] = "dns";
- break;
-
-#ifdef SVC_HESIOD
- case SVC_HESIOD:
- maptype[svcno] = "hesiod";
- break;
-#endif
-
- case SVC_LAST:
- return svcno;
- }
- }
- return svcno;
-#endif
-
-#if !defined(_USE_SUN_NSSWITCH_) && !defined(_USE_DEC_SVC_CONF_)
- /*
- ** Fall-back mechanism.
- */
-
- STAB *st;
- time_t now = curtime();
-
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
-
- if ((now - ServiceCacheTime) > (time_t) ServiceCacheMaxAge)
- {
- /* (re)read service switch */
- register FILE *fp;
-
- if (ConfigFileRead)
- ServiceCacheTime = now;
- fp = fopen(ServiceSwitchFile, "r");
- if (fp != NULL)
- {
- char buf[MAXLINE];
-
- while (fgets(buf, sizeof buf, fp) != NULL)
- {
- register char *p;
-
- p = strpbrk(buf, "#\n");
- if (p != NULL)
- *p = '\0';
- p = strpbrk(buf, " \t");
- if (p != NULL)
- *p++ = '\0';
- if (buf[0] == '\0')
- continue;
- while (isspace(*p))
- p++;
- if (*p == '\0')
- continue;
-
- /*
- ** Find/allocate space for this service entry.
- ** Space for all of the service strings
- ** are allocated at once. This means
- ** that we only have to free the first
- ** one to free all of them.
- */
-
- st = stab(buf, ST_SERVICE, ST_ENTER);
- if (st->s_service[0] != NULL)
- free((void *) st->s_service[0]);
- p = newstr(p);
- for (svcno = 0; svcno < MAXMAPSTACK; )
- {
- if (*p == '\0')
- break;
- st->s_service[svcno++] = p;
- p = strpbrk(p, " \t");
- if (p == NULL)
- break;
- *p++ = '\0';
- while (isspace(*p))
- p++;
- }
- if (svcno < MAXMAPSTACK)
- st->s_service[svcno] = NULL;
- }
- fclose(fp);
- }
- }
-
- /* look up entry in cache */
- st = stab(service, ST_SERVICE, ST_FIND);
- if (st != NULL && st->s_service[0] != NULL)
- {
- /* extract data */
- svcno = 0;
- while (svcno < MAXMAPSTACK)
- {
- maptype[svcno] = st->s_service[svcno];
- if (maptype[svcno++] == NULL)
- break;
- }
- return --svcno;
- }
-#endif
-
- /* if the service file doesn't work, use an absolute fallback */
- punt:
- for (svcno = 0; svcno < MAXMAPACTIONS; svcno++)
- mapreturn[svcno] = 0;
- svcno = 0;
- if (strcmp(service, "aliases") == 0)
- {
- maptype[svcno++] = "files";
-#ifdef AUTO_NIS_ALIASES
-# ifdef NISPLUS
- maptype[svcno++] = "nisplus";
-# endif
-# ifdef NIS
- maptype[svcno++] = "nis";
-# endif
-#endif
- return svcno;
- }
- if (strcmp(service, "hosts") == 0)
- {
-# if NAMED_BIND
- maptype[svcno++] = "dns";
-# else
-# if defined(sun) && !defined(BSD) && !defined(_USE_SUN_NSSWITCH_)
- /* SunOS */
- maptype[svcno++] = "nis";
-# endif
-# endif
- maptype[svcno++] = "files";
- return svcno;
- }
- return -1;
-}
- /*
-** USERNAME -- return the user id of the logged in user.
-**
-** Parameters:
-** none.
-**
-** Returns:
-** The login name of the logged in user.
-**
-** Side Effects:
-** none.
-**
-** Notes:
-** The return value is statically allocated.
-*/
-
-char *
-username()
-{
- static char *myname = NULL;
- extern char *getlogin();
- register struct passwd *pw;
-
- /* cache the result */
- if (myname == NULL)
- {
- myname = getlogin();
- if (myname == NULL || myname[0] == '\0')
- {
- pw = sm_getpwuid(RealUid);
- if (pw != NULL)
- myname = newstr(pw->pw_name);
- }
- else
- {
- uid_t uid = RealUid;
-
- myname = newstr(myname);
- if ((pw = sm_getpwnam(myname)) == NULL ||
- (uid != 0 && uid != pw->pw_uid))
- {
- pw = sm_getpwuid(uid);
- if (pw != NULL)
- myname = newstr(pw->pw_name);
- }
- }
- if (myname == NULL || myname[0] == '\0')
- {
- syserr("554 Who are you?");
- myname = "postmaster";
- }
- }
-
- return (myname);
-}
- /*
-** TTYPATH -- Get the path of the user's tty
-**
-** Returns the pathname of the user's tty. Returns NULL if
-** the user is not logged in or if s/he has write permission
-** denied.
-**
-** Parameters:
-** none
-**
-** Returns:
-** pathname of the user's tty.
-** NULL if not logged in or write permission denied.
-**
-** Side Effects:
-** none.
-**
-** WARNING:
-** Return value is in a local buffer.
-**
-** Called By:
-** savemail
-*/
-
-char *
-ttypath()
-{
- struct stat stbuf;
- register char *pathn;
- extern char *ttyname();
- extern char *getlogin();
-
- /* compute the pathname of the controlling tty */
- if ((pathn = ttyname(2)) == NULL && (pathn = ttyname(1)) == NULL &&
- (pathn = ttyname(0)) == NULL)
- {
- errno = 0;
- return (NULL);
- }
-
- /* see if we have write permission */
- if (stat(pathn, &stbuf) < 0 || !bitset(02, stbuf.st_mode))
- {
- errno = 0;
- return (NULL);
- }
-
- /* see if the user is logged in */
- if (getlogin() == NULL)
- return (NULL);
-
- /* looks good */
- return (pathn);
-}
- /*
-** CHECKCOMPAT -- check for From and To person compatible.
-**
-** This routine can be supplied on a per-installation basis
-** to determine whether a person is allowed to send a message.
-** This allows restriction of certain types of internet
-** forwarding or registration of users.
-**
-** If the hosts are found to be incompatible, an error
-** message should be given using "usrerr" and an EX_ code
-** should be returned. You can also set to->q_status to
-** a DSN-style status code.
-**
-** EF_NO_BODY_RETN can be set in e->e_flags to suppress the
-** body during the return-to-sender function; this should be done
-** on huge messages. This bit may already be set by the ESMTP
-** protocol.
-**
-** Parameters:
-** to -- the person being sent to.
-**
-** Returns:
-** an exit status
-**
-** Side Effects:
-** none (unless you include the usrerr stuff)
-*/
-
-int
-checkcompat(to, e)
- register ADDRESS *to;
- register ENVELOPE *e;
-{
-# ifdef lint
- if (to == NULL)
- to++;
-# endif /* lint */
-
- if (tTd(49, 1))
- printf("checkcompat(to=%s, from=%s)\n",
- to->q_paddr, e->e_from.q_paddr);
-
-# ifdef EXAMPLE_CODE
- /* this code is intended as an example only */
- register STAB *s;
-
- s = stab("arpa", ST_MAILER, ST_FIND);
- if (s != NULL && strcmp(e->e_from.q_mailer->m_name, "local") != 0 &&
- to->q_mailer == s->s_mailer)
- {
- usrerr("553 No ARPA mail through this machine: see your system administration");
- /* e->e_flags |= EF_NO_BODY_RETN; to supress body on return */
- to->q_status = "5.7.1";
- return (EX_UNAVAILABLE);
- }
-# endif /* EXAMPLE_CODE */
- return (EX_OK);
-}
- /*
-** SETSIGNAL -- set a signal handler
-**
-** This is essentially old BSD "signal(3)".
-*/
-
-sigfunc_t
-setsignal(sig, handler)
- int sig;
- sigfunc_t handler;
-{
-#if defined(SYS5SIGNALS) || defined(BSD4_3)
-# ifdef BSD4_3
- return signal(sig, handler);
-# else
- return sigset(sig, handler);
-# endif
-#else
- struct sigaction n, o;
-
- bzero(&n, sizeof n);
-# if USE_SA_SIGACTION
- n.sa_sigaction = (void(*)(int, siginfo_t *, void *)) handler;
- n.sa_flags = SA_RESTART|SA_SIGINFO;
-# else
- n.sa_handler = handler;
-# ifdef SA_RESTART
- n.sa_flags = SA_RESTART;
-# endif
-# endif
- if (sigaction(sig, &n, &o) < 0)
- return SIG_ERR;
- return o.sa_handler;
-#endif
-}
- /*
-** BLOCKSIGNAL -- hold a signal to prevent delivery
-**
-** Parameters:
-** sig -- the signal to block.
-**
-** Returns:
-** 1 signal was previously blocked
-** 0 signal was not previously blocked
-** -1 on failure.
-*/
-
-int
-blocksignal(sig)
- int sig;
-{
-#ifdef BSD4_3
-# ifndef sigmask
-# define sigmask(s) (1 << ((s) - 1))
-# endif
- return (sigblock(sigmask(sig)) & sigmask(sig)) != 0;
-#else
-# ifdef ALTOS_SYSTEM_V
- sigfunc_t handler;
-
- handler = sigset(sig, SIG_HOLD);
- if (handler == SIG_ERR)
- return -1;
- else
- return handler == SIG_HOLD;
-# else
- sigset_t sset, oset;
-
- sigemptyset(&sset);
- sigaddset(&sset, sig);
- if (sigprocmask(SIG_BLOCK, &sset, &oset) < 0)
- return -1;
- else
- return sigismember(&oset, sig);
-# endif
-#endif
-}
- /*
-** RELEASESIGNAL -- release a held signal
-**
-** Parameters:
-** sig -- the signal to release.
-**
-** Returns:
-** 1 signal was previously blocked
-** 0 signal was not previously blocked
-** -1 on failure.
-*/
-
-int
-releasesignal(sig)
- int sig;
-{
-#ifdef BSD4_3
- return (sigsetmask(sigblock(0) & ~sigmask(sig)) & sigmask(sig)) != 0;
-#else
-# ifdef ALTOS_SYSTEM_V
- sigfunc_t handler;
-
- handler = sigset(sig, SIG_HOLD);
- if (sigrelse(sig) < 0)
- return -1;
- else
- return handler == SIG_HOLD;
-# else
- sigset_t sset, oset;
-
- sigemptyset(&sset);
- sigaddset(&sset, sig);
- if (sigprocmask(SIG_UNBLOCK, &sset, &oset) < 0)
- return -1;
- else
- return sigismember(&oset, sig);
-# endif
-#endif
-}
- /*
-** HOLDSIGS -- arrange to hold all signals
-**
-** Parameters:
-** none.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Arranges that signals are held.
-*/
-
-void
-holdsigs()
-{
-}
- /*
-** RLSESIGS -- arrange to release all signals
-**
-** This undoes the effect of holdsigs.
-**
-** Parameters:
-** none.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Arranges that signals are released.
-*/
-
-void
-rlsesigs()
-{
-}
- /*
-** INIT_MD -- do machine dependent initializations
-**
-** Systems that have global modes that should be set should do
-** them here rather than in main.
-*/
-
-#ifdef _AUX_SOURCE
-# include <compat.h>
-#endif
-
-#if SHARE_V1
-# include <shares.h>
-#endif
-
-void
-init_md(argc, argv)
- int argc;
- char **argv;
-{
-#ifdef _AUX_SOURCE
- setcompat(getcompat() | COMPAT_BSDPROT);
-#endif
-
-#ifdef SUN_EXTENSIONS
- init_md_sun();
-#endif
-
-#if _CONVEX_SOURCE
- /* keep gethostby*() from stripping the local domain name */
- set_domain_trim_off();
-#endif
-#if SECUREWARE || defined(_SCO_unix_)
- set_auth_parameters(argc, argv);
-
-# ifdef _SCO_unix_
- /*
- ** This is required for highest security levels (the kernel
- ** won't let it call set*uid() or run setuid binaries without
- ** it). It may be necessary on other SECUREWARE systems.
- */
-
- if (getluid() == -1)
- setluid(0);
-# endif
-#endif
-
-#ifdef VENDOR_DEFAULT
- VendorCode = VENDOR_DEFAULT;
-#else
- VendorCode = VENDOR_BERKELEY;
-#endif
-}
- /*
-** INIT_VENDOR_MACROS -- vendor-dependent macro initializations
-**
-** Called once, on startup.
-**
-** Parameters:
-** e -- the global envelope.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** vendor-dependent.
-*/
-
-void
-init_vendor_macros(e)
- register ENVELOPE *e;
-{
-}
- /*
-** GETLA -- get the current load average
-**
-** This code stolen from la.c.
-**
-** Parameters:
-** none.
-**
-** Returns:
-** The current load average as an integer.
-**
-** Side Effects:
-** none.
-*/
-
-/* try to guess what style of load average we have */
-#define LA_ZERO 1 /* always return load average as zero */
-#define LA_INT 2 /* read kmem for avenrun; interpret as long */
-#define LA_FLOAT 3 /* read kmem for avenrun; interpret as float */
-#define LA_SUBR 4 /* call getloadavg */
-#define LA_MACH 5 /* MACH load averages (as on NeXT boxes) */
-#define LA_SHORT 6 /* read kmem for avenrun; interpret as short */
-#define LA_PROCSTR 7 /* read string ("1.17") from /proc/loadavg */
-#define LA_READKSYM 8 /* SVR4: use MIOC_READKSYM ioctl call */
-#define LA_DGUX 9 /* special DGUX implementation */
-#define LA_HPUX 10 /* special HPUX implementation */
-#define LA_IRIX6 11 /* special IRIX 6.2 implementation */
-#define LA_KSTAT 12 /* special Solaris kstat(3k) implementation */
-#define LA_DEVSHORT 13 /* read short from a device */
-#define LA_ALPHAOSF 14 /* Digital UNIX (OSF/1 on Alpha) table() call */
-
-/* do guesses based on general OS type */
-#ifndef LA_TYPE
-# define LA_TYPE LA_ZERO
-#endif
-
-#ifndef FSHIFT
-# if defined(unixpc)
-# define FSHIFT 5
-# endif
-
-# if defined(__alpha) || defined(IRIX)
-# define FSHIFT 10
-# endif
-
-#endif
-
-#ifndef FSHIFT
-# define FSHIFT 8
-#endif
-
-#ifndef FSCALE
-# define FSCALE (1 << FSHIFT)
-#endif
-
-#ifndef LA_AVENRUN
-# ifdef SYSTEM5
-# define LA_AVENRUN "avenrun"
-# else
-# define LA_AVENRUN "_avenrun"
-# endif
-#endif
-
-/* _PATH_KMEM should be defined in <paths.h> */
-#ifndef _PATH_KMEM
-# define _PATH_KMEM "/dev/kmem"
-#endif
-
-#if (LA_TYPE == LA_INT) || (LA_TYPE == LA_FLOAT) || (LA_TYPE == LA_SHORT)
-
-#include <nlist.h>
-
-#ifdef IRIX64
-# define nlist nlist64
-#endif
-
-/* _PATH_UNIX should be defined in <paths.h> */
-#ifndef _PATH_UNIX
-# if defined(SYSTEM5)
-# define _PATH_UNIX "/unix"
-# else
-# define _PATH_UNIX "/vmunix"
-# endif
-#endif
-
-#ifdef _AUX_SOURCE
-struct nlist Nl[2];
-#else
-struct nlist Nl[] =
-{
- { LA_AVENRUN },
- { 0 },
-};
-#endif
-#define X_AVENRUN 0
-
-int
-getla()
-{
- static int kmem = -1;
-#if LA_TYPE == LA_INT
- long avenrun[3];
-#else
-# if LA_TYPE == LA_SHORT
- short avenrun[3];
-# else
- double avenrun[3];
-# endif
-#endif
- extern int errno;
- extern off_t lseek();
-
- if (kmem < 0)
- {
-#ifdef _AUX_SOURCE
- strcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN);
- Nl[1].n_name[0] = '\0';
-#endif
-
-#if defined(_AIX3) || defined(_AIX4)
- if (knlist(Nl, 1, sizeof Nl[0]) < 0)
-#else
- if (nlist(_PATH_UNIX, Nl) < 0)
-#endif
- {
- if (tTd(3, 1))
- printf("getla: nlist(%s): %s\n", _PATH_UNIX,
- errstring(errno));
- return (-1);
- }
- if (Nl[X_AVENRUN].n_value == 0)
- {
- if (tTd(3, 1))
- printf("getla: nlist(%s, %s) ==> 0\n",
- _PATH_UNIX, LA_AVENRUN);
- return (-1);
- }
-#ifdef NAMELISTMASK
- Nl[X_AVENRUN].n_value &= NAMELISTMASK;
-#endif
-
- kmem = open(_PATH_KMEM, 0, 0);
- if (kmem < 0)
- {
- if (tTd(3, 1))
- printf("getla: open(/dev/kmem): %s\n",
- errstring(errno));
- return (-1);
- }
- (void) fcntl(kmem, F_SETFD, 1);
- }
- if (tTd(3, 20))
- printf("getla: symbol address = %#lx\n",
- (u_long) Nl[X_AVENRUN].n_value);
- if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, SEEK_SET) == -1 ||
- read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
- {
- /* thank you Ian */
- if (tTd(3, 1))
- printf("getla: lseek or read: %s\n", errstring(errno));
- return (-1);
- }
-# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
- if (tTd(3, 5))
- {
-# if LA_TYPE == LA_SHORT
- printf("getla: avenrun = %d", avenrun[0]);
- if (tTd(3, 15))
- printf(", %d, %d", avenrun[1], avenrun[2]);
-# else
- printf("getla: avenrun = %ld", avenrun[0]);
- if (tTd(3, 15))
- printf(", %ld, %ld", avenrun[1], avenrun[2]);
-# endif
- printf("\n");
- }
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
-# else /* LA_TYPE == LA_FLOAT */
- if (tTd(3, 5))
- {
- printf("getla: avenrun = %g", avenrun[0]);
- if (tTd(3, 15))
- printf(", %g, %g", avenrun[1], avenrun[2]);
- printf("\n");
- }
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (avenrun[0] +0.5));
- return ((int) (avenrun[0] + 0.5));
-# endif
-}
-
-#endif /* LA_TYPE == LA_INT or LA_SHORT or LA_FLOAT */
-
-#if LA_TYPE == LA_READKSYM
-
-# include <sys/ksym.h>
-
-getla()
-{
- static int kmem = -1;
- long avenrun[3];
- extern int errno;
- struct mioc_rksym mirk;
-
- if (kmem < 0)
- {
- kmem = open("/dev/kmem", 0, 0);
- if (kmem < 0)
- {
- if (tTd(3, 1))
- printf("getla: open(/dev/kmem): %s\n",
- errstring(errno));
- return (-1);
- }
- (void) fcntl(kmem, F_SETFD, 1);
- }
- mirk.mirk_symname = LA_AVENRUN;
- mirk.mirk_buf = avenrun;
- mirk.mirk_buflen = sizeof(avenrun);
- if (ioctl(kmem, MIOC_READKSYM, &mirk) < 0)
- {
- if (tTd(3, 1))
- printf("getla: ioctl(MIOC_READKSYM) failed: %s\n",
- errstring(errno));
- return -1;
- }
- if (tTd(3, 5))
- {
- printf("getla: avenrun = %d", avenrun[0]);
- if (tTd(3, 15))
- printf(", %d, %d", avenrun[1], avenrun[2]);
- printf("\n");
- }
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
-}
-
-#endif /* LA_TYPE == LA_READKSYM */
-
-#if LA_TYPE == LA_DGUX
-
-# include <sys/dg_sys_info.h>
-
-int
-getla()
-{
- struct dg_sys_info_load_info load_info;
-
- dg_sys_info((long *)&load_info,
- DG_SYS_INFO_LOAD_INFO_TYPE, DG_SYS_INFO_LOAD_VERSION_0);
-
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (load_info.one_minute + 0.5));
-
- return((int) (load_info.one_minute + 0.5));
-}
-
-#endif /* LA_TYPE == LA_DGUX */
-
-#if LA_TYPE == LA_HPUX
-
-/* forward declarations to keep gcc from complaining */
-struct pst_dynamic;
-struct pst_status;
-struct pst_static;
-struct pst_vminfo;
-struct pst_diskinfo;
-struct pst_processor;
-struct pst_lv;
-struct pst_swapinfo;
-
-# include <sys/param.h>
-# include <sys/pstat.h>
-
-int
-getla()
-{
- struct pst_dynamic pstd;
-
- if (pstat_getdynamic(&pstd, sizeof(struct pst_dynamic),
- (size_t) 1, 0) == -1)
- return 0;
-
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (pstd.psd_avg_1_min + 0.5));
-
- return (int) (pstd.psd_avg_1_min + 0.5);
-}
-
-#endif /* LA_TYPE == LA_HPUX */
-
-#if LA_TYPE == LA_SUBR
-
-int
-getla()
-{
- double avenrun[3];
-
- if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
- {
- if (tTd(3, 1))
- perror("getla: getloadavg failed:");
- return (-1);
- }
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (avenrun[0] +0.5));
- return ((int) (avenrun[0] + 0.5));
-}
-
-#endif /* LA_TYPE == LA_SUBR */
-
-#if LA_TYPE == LA_MACH
-
-/*
-** This has been tested on NEXTSTEP release 2.1/3.X.
-*/
-
-#if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
-# include <mach/mach.h>
-#else
-# include <mach.h>
-#endif
-
-int
-getla()
-{
- processor_set_t default_set;
- kern_return_t error;
- unsigned int info_count;
- struct processor_set_basic_info info;
- host_t host;
-
- error = processor_set_default(host_self(), &default_set);
- if (error != KERN_SUCCESS)
- {
- if (tTd(3, 1))
- perror("getla: processor_set_default failed:");
- return -1;
- }
- info_count = PROCESSOR_SET_BASIC_INFO_COUNT;
- if (processor_set_info(default_set, PROCESSOR_SET_BASIC_INFO,
- &host, (processor_set_info_t)&info,
- &info_count) != KERN_SUCCESS)
- {
- if (tTd(3, 1))
- perror("getla: processor_set_info failed:");
- return -1;
- }
- if (tTd(3, 1))
- printf("getla: %d\n", (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE);
- return (int) (info.load_average + (LOAD_SCALE / 2)) / LOAD_SCALE;
-}
-
-#endif /* LA_TYPE == LA_MACH */
-
-#if LA_TYPE == LA_PROCSTR
-
-/*
-** Read /proc/loadavg for the load average. This is assumed to be
-** in a format like "0.15 0.12 0.06".
-**
-** Initially intended for Linux. This has been in the kernel
-** since at least 0.99.15.
-*/
-
-# ifndef _PATH_LOADAVG
-# define _PATH_LOADAVG "/proc/loadavg"
-# endif
-
-int
-getla()
-{
- double avenrun;
- register int result;
- FILE *fp;
-
- fp = fopen(_PATH_LOADAVG, "r");
- if (fp == NULL)
- {
- if (tTd(3, 1))
- printf("getla: fopen(%s): %s\n",
- _PATH_LOADAVG, errstring(errno));
- return -1;
- }
- result = fscanf(fp, "%lf", &avenrun);
- fclose(fp);
- if (result != 1)
- {
- if (tTd(3, 1))
- printf("getla: fscanf() = %d: %s\n",
- result, errstring(errno));
- return -1;
- }
-
- if (tTd(3, 1))
- printf("getla(): %.2f\n", avenrun);
-
- return ((int) (avenrun + 0.5));
-}
-
-#endif /* LA_TYPE == LA_PROCSTR */
-
-#if LA_TYPE == LA_IRIX6
-
-#include <nlist.h>
-#include <sys/types.h>
-#include <unistd.h>
-
-#define X_AVENRUN 0
-struct nlist Nl32[] =
-{
- { LA_AVENRUN },
- { 0 },
-};
-struct nlist64 Nl64[] =
-{
- { LA_AVENRUN },
- { 0 },
-};
-
-int getla(void)
-{
- static int kmem = -1;
- static enum { getla_none, getla_32, getla_64 } kernel_type =
- getla_none;
- uint32_t avenrun[3];
-
- if (kernel_type == getla_none)
- {
- /* Try 32 bit kernel ... */
- errno = 0;
- if (nlist(_PATH_UNIX, Nl32) == 0)
- {
- if (tTd(3, 20))
- printf("getla: Kernel is 32bit\n");
-
- if (Nl32[X_AVENRUN].n_value == 0)
- {
- if (tTd(3, 1))
- printf("getla: nlist(%s, %s) ==> 0\n",
- _PATH_UNIX, LA_AVENRUN);
- }
- else
- kernel_type = getla_32;
- }
- else if (errno != 0)
- {
- if (tTd(3, 1))
- printf("getla: nlist(%s): %s\n",
- _PATH_UNIX, errstring(errno));
- }
- else
- {
- if (tTd(3, 20))
- printf("getla: Kernel is not 32bit\n");
- }
-
- /* Try 64 bit kernel ... */
- errno = 0;
- if (nlist64(_PATH_UNIX, Nl64) == 0)
- {
- if (tTd(3, 20))
- printf("getla: Kernel is 64bit\n");
-
- if (Nl64[X_AVENRUN].n_value == 0)
- {
- if (tTd(3, 1))
- printf("getla: nlist(%s, %s) ==> 0\n",
- _PATH_UNIX, LA_AVENRUN);
- }
- else
- kernel_type = getla_64;
- }
- else if (errno != 0)
- {
- if (tTd(3, 1))
- printf("getla: nlist64(%s): %s\n",
- _PATH_UNIX, errstring(errno));
- }
- else
- {
- if (tTd(3, 20))
- printf("getla: Kernel is not 64bit\n");
- }
- }
-
- if (kernel_type == getla_none)
- {
- if (tTd(3, 1))
- printf("getla: Failed to determine kernel type\n");
- return -1;
- }
-
- if (kmem < 0)
- {
- kmem = open(_PATH_KMEM, 0, 0);
- if (kmem < 0)
- {
- if (tTd(3, 1))
- printf("getla: open(/dev/kmem): %s\n",
- errstring(errno));
- return -1;
- }
- (void) fcntl(kmem, F_SETFD, 1);
- }
-
- switch (kernel_type)
- {
- case getla_none:
- return -1;
-
- case getla_32:
- if (lseek(kmem, (off_t) Nl32[X_AVENRUN].n_value, SEEK_SET) == -1 ||
- read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
- {
- if (tTd(3, 1))
- printf("getla: lseek or read: %s\n",
- errstring(errno));
- return -1;
- }
- break;
-
- case getla_64:
- /* Using of lseek64 is perhaps overkill ... */
- if (lseek64(kmem, (off64_t) Nl64[X_AVENRUN].n_value, SEEK_SET) == -1 ||
- read(kmem, (char *) avenrun, sizeof(avenrun)) <
- sizeof(avenrun))
- {
- if (tTd(3, 1))
- printf("getla: lseek64 or read: %s\n",
- errstring(errno));
- return -1;
- }
- break;
- }
- if (tTd(3, 5))
- {
- printf("getla: avenrun = %ld",
- (long int) avenrun[0]);
- if (tTd(3, 15))
- printf(", %ld, %ld",
- (long int)avenrun[1],
- (long int)avenrun[2]);
- printf("\n");
- }
- if (tTd(3, 1))
- printf("getla: %d\n",
- (int) (avenrun[0] + FSCALE/2) >> FSHIFT);
- return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
-}
-#endif
-
-#if LA_TYPE == LA_KSTAT
-
-#include <kstat.h>
-
-int
-getla()
-{
- static kstat_ctl_t *kc = NULL;
- static kstat_t *ksp = NULL;
- kstat_named_t *ksn;
- int la;
-
- if (kc == NULL) /* if not initialized before */
- kc = kstat_open();
- if (kc == NULL)
- {
- if (tTd(3, 1))
- printf("getla: kstat_open(): %s\n",
- errstring(errno));
- return -1;
- }
- if (ksp == NULL)
- ksp = kstat_lookup(kc, "unix", 0, "system_misc");
- if (ksp == NULL)
- {
- if (tTd(3, 1))
- printf("getla: kstat_lookup(): %s\n",
- errstring(errno));
- return -1;
- }
- if (kstat_read(kc, ksp, NULL) < 0)
- {
- if (tTd(3, 1))
- printf("getla: kstat_read(): %s\n",
- errstring(errno));
- return -1;
- }
- ksn = (kstat_named_t *) kstat_data_lookup(ksp, "avenrun_1min");
- la = ((double)ksn->value.ul + FSCALE/2) / FSCALE;
- /* kstat_close(kc); /o do not close for fast access */
- return la;
-}
-
-#endif /* LA_TYPE == LA_KSTAT */
-
-#if LA_TYPE == LA_DEVSHORT
-
-/*
-** Read /dev/table/avenrun for the load average. This should contain
-** three shorts for the 1, 5, and 15 minute loads. We only read the
-** first, since that's all we care about.
-**
-** Intended for SCO OpenServer 5.
-*/
-
-# ifndef _PATH_AVENRUN
-# define _PATH_AVENRUN "/dev/table/avenrun"
-# endif
-
-int
-getla()
-{
- static int afd = -1;
- short avenrun;
- int loadav;
- int r;
-
- errno = EBADF;
-
- if (afd == -1 || lseek(afd, 0L, SEEK_SET) == -1)
- {
- if (errno != EBADF)
- return -1;
- afd = open(_PATH_AVENRUN, O_RDONLY|O_SYNC);
- if (afd < 0)
- {
- sm_syslog(LOG_ERR, NOQID,
- "can't open %s: %m",
- _PATH_AVENRUN);
- return -1;
- }
- }
-
- r = read(afd, &avenrun, sizeof avenrun);
-
- if (tTd(3, 5))
- printf("getla: avenrun = %d\n", avenrun);
- loadav = (int) (avenrun + FSCALE/2) >> FSHIFT;
- if (tTd(3, 1))
- printf("getla: %d\n", loadav);
- return loadav;
-}
-
-#endif /* LA_TYPE == LA_DEVSHORT */
-
-#if LA_TYPE == LA_ALPHAOSF
-# include <sys/table.h>
-
-int getla()
-{
- int ave = 0;
- struct tbl_loadavg tab;
-
- if (table(TBL_LOADAVG, 0, &tab, 1, sizeof(tab)) == -1)
- {
- if (tTd(3, 1))
- printf("getla: table %s\n", errstring(errno));
- return (-1);
- }
-
- if (tTd(3, 1))
- printf("getla: scale = %d\n", tab.tl_lscale);
-
- if (tab.tl_lscale)
- ave = (tab.tl_avenrun.l[0] + (tab.tl_lscale/2)) / tab.tl_lscale;
- else
- ave = (int) (tab.tl_avenrun.d[0] + 0.5);
-
- if (tTd(3, 1))
- printf("getla: %d\n", ave);
-
- return ave;
-}
-
-#endif
-
-#if LA_TYPE == LA_ZERO
-
-int
-getla()
-{
- if (tTd(3, 1))
- printf("getla: ZERO\n");
- return (0);
-}
-
-#endif /* LA_TYPE == LA_ZERO */
-
-/*
- * Copyright 1989 Massachusetts Institute of Technology
- *
- * Permission to use, copy, modify, distribute, and sell this software and its
- * documentation for any purpose is hereby granted without fee, provided that
- * the above copyright notice appear in all copies and that both that
- * copyright notice and this permission notice appear in supporting
- * documentation, and that the name of M.I.T. not be used in advertising or
- * publicity pertaining to distribution of the software without specific,
- * written prior permission. M.I.T. makes no representations about the
- * suitability of this software for any purpose. It is provided "as is"
- * without express or implied warranty.
- *
- * M.I.T. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL M.I.T.
- * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
- * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
- * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
- * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
- *
- * Authors: Many and varied...
- */
-
-/* Non Apollo stuff removed by Don Lewis 11/15/93 */
-
-#ifdef apollo
-# undef volatile
-# include <apollo/base.h>
-
-/* ARGSUSED */
-int getloadavg( call_data )
- caddr_t call_data; /* pointer to (double) return value */
-{
- double *avenrun = (double *) call_data;
- int i;
- status_$t st;
- long loadav[3];
- proc1_$get_loadav(loadav, &st);
- *avenrun = loadav[0] / (double) (1 << 16);
- return(0);
-}
-# endif /* apollo */
- /*
-** SHOULDQUEUE -- should this message be queued or sent?
-**
-** Compares the message cost to the load average to decide.
-**
-** Parameters:
-** pri -- the priority of the message in question.
-** ctime -- the message creation time.
-**
-** Returns:
-** TRUE -- if this message should be queued up for the
-** time being.
-** FALSE -- if the load is low enough to send this message.
-**
-** Side Effects:
-** none.
-*/
-
-extern int get_num_procs_online __P((void));
-
-bool
-shouldqueue(pri, ctime)
- long pri;
- time_t ctime;
-{
- bool rval;
- int queuela = QueueLA * get_num_procs_online();
-
- if (tTd(3, 30))
- printf("shouldqueue: CurrentLA=%d, pri=%ld: ", CurrentLA, pri);
- if (CurrentLA < queuela)
- {
- if (tTd(3, 30))
- printf("FALSE (CurrentLA < QueueLA)\n");
- return (FALSE);
- }
-#if 0 /* this code is reported to cause oscillation around RefuseLA */
- if (CurrentLA >= RefuseLA && QueueLA < RefuseLA)
- {
- if (tTd(3, 30))
- printf("TRUE (CurrentLA >= RefuseLA)\n");
- return (TRUE);
- }
-#endif
- rval = pri > (QueueFactor / (CurrentLA - queuela + 1));
- if (tTd(3, 30))
- printf("%s (by calculation)\n", rval ? "TRUE" : "FALSE");
- return rval;
-}
- /*
-** REFUSECONNECTIONS -- decide if connections should be refused
-**
-** Parameters:
-** port -- port number (for error messages only)
-**
-** Returns:
-** TRUE if incoming SMTP connections should be refused
-** (for now).
-** FALSE if we should accept new work.
-**
-** Side Effects:
-** Sets process title when it is rejecting connections.
-*/
-
-bool
-refuseconnections(port)
- int port;
-{
- int refusela = RefuseLA * get_num_procs_online();
- time_t now;
- static time_t lastconn = (time_t) 0;
- static int conncnt = 0;
- extern bool enoughdiskspace();
-
-#ifdef XLA
- if (!xla_smtp_ok())
- return TRUE;
-#endif
-
- now = curtime();
- if (now != lastconn)
- {
- lastconn = now;
- conncnt = 0;
- }
- else if (conncnt++ > ConnRateThrottle && ConnRateThrottle > 0)
- {
- /* sleep to flatten out connection load */
- setproctitle("deferring connections on port %d: %d per second",
- port, ConnRateThrottle);
- if (LogLevel >= 14)
- sm_syslog(LOG_INFO, NOQID,
- "deferring connections on port %d: %d per second",
- port, ConnRateThrottle);
- sleep(1);
- }
-
- CurrentLA = getla();
- if (CurrentLA >= refusela)
- {
- setproctitle("rejecting connections on port %d: load average: %d",
- port, CurrentLA);
- if (LogLevel >= 14)
- sm_syslog(LOG_INFO, NOQID,
- "rejecting connections on port %d: load average: %d",
- port, CurrentLA);
- return TRUE;
- }
-
- if (!enoughdiskspace(MinBlocksFree + 1))
- {
- setproctitle("rejecting connections on port %d: min free: %d",
- port, MinBlocksFree);
- if (LogLevel >= 14)
- sm_syslog(LOG_INFO, NOQID,
- "rejecting connections on port %d: min free: %d",
- port, MinBlocksFree);
- return TRUE;
- }
-
- if (MaxChildren > 0 && CurChildren >= MaxChildren)
- {
- extern void proc_list_probe __P((void));
-
- proc_list_probe();
- if (CurChildren >= MaxChildren)
- {
- setproctitle("rejecting connections on port %d: %d children, max %d",
- port, CurChildren, MaxChildren);
- if (LogLevel >= 14)
- sm_syslog(LOG_INFO, NOQID,
- "rejecting connections on port %d: %d children, max %d",
- port, CurChildren, MaxChildren);
- return TRUE;
- }
- }
-
- return FALSE;
-}
- /*
-** SETPROCTITLE -- set process title for ps
-**
-** Parameters:
-** fmt -- a printf style format string.
-** a, b, c -- possible parameters to fmt.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Clobbers argv of our main procedure so ps(1) will
-** display the title.
-*/
-
-#define SPT_NONE 0 /* don't use it at all */
-#define SPT_REUSEARGV 1 /* cover argv with title information */
-#define SPT_BUILTIN 2 /* use libc builtin */
-#define SPT_PSTAT 3 /* use pstat(PSTAT_SETCMD, ...) */
-#define SPT_PSSTRINGS 4 /* use PS_STRINGS->... */
-#define SPT_SYSMIPS 5 /* use sysmips() supported by NEWS-OS 6 */
-#define SPT_SCO 6 /* write kernel u. area */
-#define SPT_CHANGEARGV 7 /* write our own strings into argv[] */
-
-#ifndef SPT_TYPE
-# define SPT_TYPE SPT_REUSEARGV
-#endif
-
-#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
-
-# if SPT_TYPE == SPT_PSTAT
-# include <sys/pstat.h>
-# endif
-# if SPT_TYPE == SPT_PSSTRINGS
-# include <machine/vmparam.h>
-# include <sys/exec.h>
-# ifndef PS_STRINGS /* hmmmm.... apparently not available after all */
-# undef SPT_TYPE
-# define SPT_TYPE SPT_REUSEARGV
-# else
-# ifndef NKPDE /* FreeBSD 2.0 */
-# define NKPDE 63
-typedef unsigned int *pt_entry_t;
-# endif
-# endif
-# endif
-
-# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
-# define SETPROC_STATIC static
-# else
-# define SETPROC_STATIC
-# endif
-
-# if SPT_TYPE == SPT_SYSMIPS
-# include <sys/sysmips.h>
-# include <sys/sysnews.h>
-# endif
-
-# if SPT_TYPE == SPT_SCO
-# include <sys/immu.h>
-# include <sys/dir.h>
-# include <sys/user.h>
-# include <sys/fs/s5param.h>
-# if PSARGSZ > MAXLINE
-# define SPT_BUFSIZE PSARGSZ
-# endif
-# endif
-
-# ifndef SPT_PADCHAR
-# define SPT_PADCHAR ' '
-# endif
-
-# ifndef SPT_BUFSIZE
-# define SPT_BUFSIZE MAXLINE
-# endif
-
-#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
-
-/*
-** Pointers for setproctitle.
-** This allows "ps" listings to give more useful information.
-*/
-
-char **Argv = NULL; /* pointer to argument vector */
-char *LastArgv = NULL; /* end of argv */
-
-void
-initsetproctitle(argc, argv, envp)
- int argc;
- char **argv;
- char **envp;
-{
- register int i, envpsize = 0;
- extern char **environ;
-
- /*
- ** Move the environment so setproctitle can use the space at
- ** the top of memory.
- */
-
- for (i = 0; envp[i] != NULL; i++)
- envpsize += strlen(envp[i]) + 1;
- environ = (char **) xalloc(sizeof (char *) * (i + 1));
- for (i = 0; envp[i] != NULL; i++)
- environ[i] = newstr(envp[i]);
- environ[i] = NULL;
-
- /*
- ** Save start and extent of argv for setproctitle.
- */
-
- Argv = argv;
-
- /*
- ** Find the last environment variable within sendmail's
- ** process memory area.
- */
- while (i > 0 && (envp[i - 1] < argv[0] ||
- envp[i - 1] > (argv[argc - 1] +
- strlen(argv[argc - 1]) + 1 + envpsize)))
- i--;
-
- if (i > 0)
- LastArgv = envp[i - 1] + strlen(envp[i - 1]);
- else
- LastArgv = argv[argc - 1] + strlen(argv[argc - 1]);
-}
-
-#if SPT_TYPE != SPT_BUILTIN
-
-
-/*VARARGS1*/
-void
-# ifdef __STDC__
-setproctitle(const char *fmt, ...)
-# else
-setproctitle(fmt, va_alist)
- const char *fmt;
- va_dcl
-# endif
-{
-# if SPT_TYPE != SPT_NONE
- register char *p;
- register int i;
- SETPROC_STATIC char buf[SPT_BUFSIZE];
- VA_LOCAL_DECL
-# if SPT_TYPE == SPT_PSTAT
- union pstun pst;
-# endif
-# if SPT_TYPE == SPT_SCO
- off_t seek_off;
- static int kmem = -1;
- static int kmempid = -1;
- struct user u;
-# endif
-
- p = buf;
-
- /* print sendmail: heading for grep */
- (void) strcpy(p, "sendmail: ");
- p += strlen(p);
-
- /* print the argument string */
- VA_START(fmt);
- (void) vsnprintf(p, SPACELEFT(buf, p), fmt, ap);
- VA_END;
-
- i = strlen(buf);
-
-# if SPT_TYPE == SPT_PSTAT
- pst.pst_command = buf;
- pstat(PSTAT_SETCMD, pst, i, 0, 0);
-# endif
-# if SPT_TYPE == SPT_PSSTRINGS
- PS_STRINGS->ps_nargvstr = 1;
- PS_STRINGS->ps_argvstr = buf;
-# endif
-# if SPT_TYPE == SPT_SYSMIPS
- sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
-# endif
-# if SPT_TYPE == SPT_SCO
- if (kmem < 0 || kmempid != getpid())
- {
- if (kmem >= 0)
- close(kmem);
- kmem = open(_PATH_KMEM, O_RDWR, 0);
- if (kmem < 0)
- return;
- (void) fcntl(kmem, F_SETFD, 1);
- kmempid = getpid();
- }
- buf[PSARGSZ - 1] = '\0';
- seek_off = UVUBLK + (off_t) u.u_psargs - (off_t) &u;
- if (lseek(kmem, (off_t) seek_off, SEEK_SET) == seek_off)
- (void) write(kmem, buf, PSARGSZ);
-# endif
-# if SPT_TYPE == SPT_REUSEARGV
- if (i > LastArgv - Argv[0] - 2)
- {
- i = LastArgv - Argv[0] - 2;
- buf[i] = '\0';
- }
- (void) strcpy(Argv[0], buf);
- p = &Argv[0][i];
- while (p < LastArgv)
- *p++ = SPT_PADCHAR;
- Argv[1] = NULL;
-# endif
-# if SPT_TYPE == SPT_CHANGEARGV
- Argv[0] = buf;
- Argv[1] = 0;
-# endif
-# endif /* SPT_TYPE != SPT_NONE */
-}
-
-#endif /* SPT_TYPE != SPT_BUILTIN */
- /*
-** WAITFOR -- wait for a particular process id.
-**
-** Parameters:
-** pid -- process id to wait for.
-**
-** Returns:
-** status of pid.
-** -1 if pid never shows up.
-**
-** Side Effects:
-** none.
-*/
-
-int
-waitfor(pid)
- pid_t pid;
-{
-#ifdef WAITUNION
- union wait st;
-#else
- auto int st;
-#endif
- pid_t i;
-#if defined(ISC_UNIX) || defined(_SCO_unix_)
- int savesig;
-#endif
-
- do
- {
- errno = 0;
-#if defined(ISC_UNIX) || defined(_SCO_unix_)
- savesig = releasesignal(SIGCHLD);
-#endif
- i = wait(&st);
-#if defined(ISC_UNIX) || defined(_SCO_unix_)
- if (savesig > 0)
- blocksignal(SIGCHLD);
-#endif
- if (i > 0)
- proc_list_drop(i);
- } while ((i >= 0 || errno == EINTR) && i != pid);
- if (i < 0)
- return -1;
-#ifdef WAITUNION
- return st.w_status;
-#else
- return st;
-#endif
-}
- /*
-** REAPCHILD -- pick up the body of my child, lest it become a zombie
-**
-** Parameters:
-** sig -- the signal that got us here (unused).
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Picks up extant zombies.
-*/
-
-SIGFUNC_DECL
-reapchild(sig)
- int sig;
-{
- int olderrno = errno;
- pid_t pid;
-# ifdef HASWAITPID
- auto int status;
- int count;
-
- count = 0;
- while ((pid = waitpid(-1, &status, WNOHANG)) > 0)
- {
- if (count++ > 1000)
- {
- if (LogLevel > 0)
- sm_syslog(LOG_ALERT, NOQID,
- "reapchild: waitpid loop: pid=%d, status=%x",
- pid, status);
- break;
- }
- proc_list_drop(pid);
- }
-# else
-# ifdef WNOHANG
- union wait status;
-
- while ((pid = wait3(&status, WNOHANG, (struct rusage *) NULL)) > 0)
- proc_list_drop(pid);
-# else /* WNOHANG */
- auto int status;
-
- /*
- ** Catch one zombie -- we will be re-invoked (we hope) if there
- ** are more. Unreliable signals probably break this, but this
- ** is the "old system" situation -- waitpid or wait3 are to be
- ** strongly preferred.
- */
-
- if ((pid = wait(&status)) > 0)
- proc_list_drop(pid);
-# endif /* WNOHANG */
-# endif
-# ifdef SYS5SIGNALS
- (void) setsignal(SIGCHLD, reapchild);
-# endif
- errno = olderrno;
- return SIGFUNC_RETURN;
-}
- /*
-** PUTENV -- emulation of putenv() in terms of setenv()
-**
-** Not needed on Posix-compliant systems.
-** This doesn't have full Posix semantics, but it's good enough
-** for sendmail.
-**
-** Parameter:
-** env -- the environment to put.
-**
-** Returns:
-** none.
-*/
-
-#ifdef NEEDPUTENV
-
-# if NEEDPUTENV == 2 /* no setenv(3) call available */
-
-int
-putenv(str)
- char *str;
-{
- char **current;
- int matchlen, envlen=0;
- char *tmp;
- char **newenv;
- static int first=1;
- extern char **environ;
-
- /*
- * find out how much of str to match when searching
- * for a string to replace.
- */
- if ((tmp = strchr(str, '=')) == NULL || tmp == str)
- matchlen = strlen(str);
- else
- matchlen = (int) (tmp - str);
- ++matchlen;
-
- /*
- * Search for an existing string in the environment and find the
- * length of environ. If found, replace and exit.
- */
- for (current=environ; *current; current++) {
- ++envlen;
-
- if (strncmp(str, *current, matchlen) == 0) {
- /* found it, now insert the new version */
- *current = (char *)str;
- return(0);
- }
- }
-
- /*
- * There wasn't already a slot so add space for a new slot.
- * If this is our first time through, use malloc(), else realloc().
- */
- if (first) {
- newenv = (char **) malloc(sizeof(char *) * (envlen + 2));
- if (newenv == NULL)
- return(-1);
-
- first=0;
- (void) memcpy(newenv, environ, sizeof(char *) * envlen);
- } else {
- newenv = (char **) realloc((char *)environ, sizeof(char *) * (envlen + 2));
- if (newenv == NULL)
- return(-1);
- }
-
- /* actually add in the new entry */
- environ = newenv;
- environ[envlen] = (char *)str;
- environ[envlen+1] = NULL;
-
- return(0);
-}
-
-#else /* implement putenv() in terms of setenv() */
-
-int
-putenv(env)
- char *env;
-{
- char *p;
- int l;
- char nbuf[100];
-
- p = strchr(env, '=');
- if (p == NULL)
- return 0;
- l = p - env;
- if (l > sizeof nbuf - 1)
- l = sizeof nbuf - 1;
- bcopy(env, nbuf, l);
- nbuf[l] = '\0';
- return setenv(nbuf, ++p, 1);
-}
-
-# endif
-#endif
- /*
-** UNSETENV -- remove a variable from the environment
-**
-** Not needed on newer systems.
-**
-** Parameters:
-** name -- the string name of the environment variable to be
-** deleted from the current environment.
-**
-** Returns:
-** none.
-**
-** Globals:
-** environ -- a pointer to the current environment.
-**
-** Side Effects:
-** Modifies environ.
-*/
-
-#ifndef HASUNSETENV
-
-void
-unsetenv(name)
- char *name;
-{
- extern char **environ;
- register char **pp;
- int len = strlen(name);
-
- for (pp = environ; *pp != NULL; pp++)
- {
- if (strncmp(name, *pp, len) == 0 &&
- ((*pp)[len] == '=' || (*pp)[len] == '\0'))
- break;
- }
-
- for (; *pp != NULL; pp++)
- *pp = pp[1];
-}
-
-#endif
- /*
-** GETDTABLESIZE -- return number of file descriptors
-**
-** Only on non-BSD systems
-**
-** Parameters:
-** none
-**
-** Returns:
-** size of file descriptor table
-**
-** Side Effects:
-** none
-*/
-
-#ifdef SOLARIS
-# include <sys/resource.h>
-#endif
-
-int
-getdtsize()
-{
-#ifdef RLIMIT_NOFILE
- struct rlimit rl;
-
- if (getrlimit(RLIMIT_NOFILE, &rl) >= 0)
- return rl.rlim_cur;
-#endif
-
-# ifdef HASGETDTABLESIZE
- return getdtablesize();
-# else
-# ifdef _SC_OPEN_MAX
- return sysconf(_SC_OPEN_MAX);
-# else
- return NOFILE;
-# endif
-# endif
-}
- /*
-** UNAME -- get the UUCP name of this system.
-*/
-
-#ifndef HASUNAME
-
-int
-uname(name)
- struct utsname *name;
-{
- FILE *file;
- char *n;
-
- name->nodename[0] = '\0';
-
- /* try /etc/whoami -- one line with the node name */
- if ((file = fopen("/etc/whoami", "r")) != NULL)
- {
- (void) fgets(name->nodename, NODE_LENGTH + 1, file);
- (void) fclose(file);
- n = strchr(name->nodename, '\n');
- if (n != NULL)
- *n = '\0';
- if (name->nodename[0] != '\0')
- return (0);
- }
-
- /* try /usr/include/whoami.h -- has a #define somewhere */
- if ((file = fopen("/usr/include/whoami.h", "r")) != NULL)
- {
- char buf[MAXLINE];
-
- while (fgets(buf, MAXLINE, file) != NULL)
- if (sscanf(buf, "#define sysname \"%*[^\"]\"",
- NODE_LENGTH, name->nodename) > 0)
- break;
- (void) fclose(file);
- if (name->nodename[0] != '\0')
- return (0);
- }
-
-#ifdef TRUST_POPEN
- /*
- ** Popen is known to have security holes.
- */
-
- /* try uuname -l to return local name */
- if ((file = popen("uuname -l", "r")) != NULL)
- {
- (void) fgets(name, NODE_LENGTH + 1, file);
- (void) pclose(file);
- n = strchr(name, '\n');
- if (n != NULL)
- *n = '\0';
- if (name->nodename[0] != '\0')
- return (0);
- }
-#endif
-
- return (-1);
-}
-#endif /* HASUNAME */
- /*
-** INITGROUPS -- initialize groups
-**
-** Stub implementation for System V style systems
-*/
-
-#ifndef HASINITGROUPS
-
-initgroups(name, basegid)
- char *name;
- int basegid;
-{
- return 0;
-}
-
-#endif
- /*
-** SETSID -- set session id (for non-POSIX systems)
-*/
-
-#ifndef HASSETSID
-
-pid_t
-setsid __P ((void))
-{
-#ifdef TIOCNOTTY
- int fd;
-
- fd = open("/dev/tty", O_RDWR, 0);
- if (fd >= 0)
- {
- (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
- (void) close(fd);
- }
-#endif /* TIOCNOTTY */
-# ifdef SYS5SETPGRP
- return setpgrp();
-# else
- return setpgid(0, getpid());
-# endif
-}
-
-#endif
- /*
-** FSYNC -- dummy fsync
-*/
-
-#ifdef NEEDFSYNC
-
-fsync(fd)
- int fd;
-{
-# ifdef O_SYNC
- return fcntl(fd, F_SETFL, O_SYNC);
-# else
- /* nothing we can do */
- return 0;
-# endif
-}
-
-#endif
- /*
-** DGUX_INET_ADDR -- inet_addr for DG/UX
-**
-** Data General DG/UX version of inet_addr returns a struct in_addr
-** instead of a long. This patches things. Only needed on versions
-** prior to 5.4.3.
-*/
-
-#ifdef DGUX_5_4_2
-
-#undef inet_addr
-
-long
-dgux_inet_addr(host)
- char *host;
-{
- struct in_addr haddr;
-
- haddr = inet_addr(host);
- return haddr.s_addr;
-}
-
-#endif
- /*
-** GETOPT -- for old systems or systems with bogus implementations
-*/
-
-#ifdef NEEDGETOPT
-
-/*
- * Copyright (c) 1985 Regents of the University of California.
- * All rights reserved. The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
- */
-
-
-/*
-** this version hacked to add `atend' flag to allow state machine
-** to reset if invoked by the program to scan args for a 2nd time
-*/
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)getopt.c 4.3 (Berkeley) 3/9/86";
-#endif /* LIBC_SCCS and not lint */
-
-#include <stdio.h>
-
-/*
- * get option letter from argument vector
- */
-#ifdef _CONVEX_SOURCE
-extern int optind, opterr, optopt;
-extern char *optarg;
-#else
-int opterr = 1; /* if error message should be printed */
-int optind = 1; /* index into parent argv vector */
-int optopt = 0; /* character checked for validity */
-char *optarg = NULL; /* argument associated with option */
-#endif
-
-#define BADCH (int)'?'
-#define EMSG ""
-#define tell(s) if (opterr) {fputs(*nargv,stderr);fputs(s,stderr); \
- fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
-
-int
-getopt(nargc,nargv,ostr)
- int nargc;
- char *const *nargv;
- const char *ostr;
-{
- static char *place = EMSG; /* option letter processing */
- static char atend = 0;
- register char *oli = NULL; /* option letter list index */
-
- if (atend) {
- atend = 0;
- place = EMSG;
- }
- if(!*place) { /* update scanning pointer */
- if (optind >= nargc || *(place = nargv[optind]) != '-' || !*++place) {
- atend++;
- return -1;
- }
- if (*place == '-') { /* found "--" */
- ++optind;
- atend++;
- return -1;
- }
- } /* option letter okay? */
- if ((optopt = (int)*place++) == (int)':' || !(oli = strchr(ostr,optopt))) {
- if (!*place) ++optind;
- tell(": illegal option -- ");
- }
- if (oli && *++oli != ':') { /* don't need argument */
- optarg = NULL;
- if (!*place) ++optind;
- }
- else { /* need an argument */
- if (*place) optarg = place; /* no white space */
- else if (nargc <= ++optind) { /* no arg */
- place = EMSG;
- tell(": option requires an argument -- ");
- }
- else optarg = nargv[optind]; /* white space */
- place = EMSG;
- ++optind;
- }
- return(optopt); /* dump back option letter */
-}
-
-#endif
- /*
-** VFPRINTF, VSPRINTF -- for old 4.3 BSD systems missing a real version
-*/
-
-#ifdef NEEDVPRINTF
-
-#define MAXARG 16
-
-vfprintf(fp, fmt, ap)
- FILE *fp;
- char *fmt;
- char **ap;
-{
- char *bp[MAXARG];
- int i = 0;
-
- while (*ap && i < MAXARG)
- bp[i++] = *ap++;
- fprintf(fp, fmt, bp[0], bp[1], bp[2], bp[3],
- bp[4], bp[5], bp[6], bp[7],
- bp[8], bp[9], bp[10], bp[11],
- bp[12], bp[13], bp[14], bp[15]);
-}
-
-vsprintf(s, fmt, ap)
- char *s;
- char *fmt;
- char **ap;
-{
- char *bp[MAXARG];
- int i = 0;
-
- while (*ap && i < MAXARG)
- bp[i++] = *ap++;
- sprintf(s, fmt, bp[0], bp[1], bp[2], bp[3],
- bp[4], bp[5], bp[6], bp[7],
- bp[8], bp[9], bp[10], bp[11],
- bp[12], bp[13], bp[14], bp[15]);
-}
-
-#endif
- /*
-** SNPRINTF, VSNPRINT -- counted versions of printf
-**
-** These versions have been grabbed off the net. They have been
-** cleaned up to compile properly and support for .precision and
-** %lx has been added.
-*/
-
-/**************************************************************
- * Original:
- * Patrick Powell Tue Apr 11 09:48:21 PDT 1995
- * A bombproof version of doprnt (sm_dopr) included.
- * Sigh. This sort of thing is always nasty do deal with. Note that
- * the version here does not include floating point...
- *
- * snprintf() is used instead of sprintf() as it does limit checks
- * for string length. This covers a nasty loophole.
- *
- * The other functions are there to prevent NULL pointers from
- * causing nast effects.
- **************************************************************/
-
-static void sm_dopr();
-static char *DoprEnd;
-static int SnprfOverflow;
-
-#if !HASSNPRINTF
-
-/* VARARGS3 */
-int
-# ifdef __STDC__
-snprintf(char *str, size_t count, const char *fmt, ...)
-# else
-snprintf(str, count, fmt, va_alist)
- char *str;
- size_t count;
- const char *fmt;
- va_dcl
-#endif
-{
- int len;
- VA_LOCAL_DECL
-
- VA_START(fmt);
- len = vsnprintf(str, count, fmt, ap);
- VA_END;
- return len;
-}
-
-
-# ifndef luna2
-int
-vsnprintf(str, count, fmt, args)
- char *str;
- size_t count;
- const char *fmt;
- va_list args;
-{
- str[0] = 0;
- DoprEnd = str + count - 1;
- SnprfOverflow = 0;
- sm_dopr( str, fmt, args );
- if (count > 0)
- DoprEnd[0] = 0;
- if (SnprfOverflow && tTd(57, 2))
- printf("\nvsnprintf overflow, len = %d, str = %s",
- count, shortenstring(str, 203));
- return strlen(str);
-}
-
-# endif /* !luna2 */
-#endif /* !HASSNPRINTF */
-
-/*
- * sm_dopr(): poor man's version of doprintf
- */
-
-static void fmtstr __P((char *value, int ljust, int len, int zpad, int maxwidth));
-static void fmtnum __P((long value, int base, int dosign, int ljust, int len, int zpad));
-static void dostr __P(( char * , int ));
-static char *output;
-static void dopr_outch __P(( int c ));
-static int SyslogErrno;
-
-static void
-sm_dopr( buffer, format, args )
- char *buffer;
- const char *format;
- va_list args;
-{
- int ch;
- long value;
- int longflag = 0;
- int pointflag = 0;
- int maxwidth = 0;
- char *strvalue;
- int ljust;
- int len;
- int zpad;
-# if !HASSTRERROR && !defined(ERRLIST_PREDEFINED)
- extern char *sys_errlist[];
- extern int sys_nerr;
-# endif
-
-
- output = buffer;
- while( (ch = *format++) ){
- switch( ch ){
- case '%':
- ljust = len = zpad = maxwidth = 0;
- longflag = pointflag = 0;
- nextch:
- ch = *format++;
- switch( ch ){
- case 0:
- dostr( "**end of format**" , 0);
- return;
- case '-': ljust = 1; goto nextch;
- case '0': /* set zero padding if len not set */
- if(len==0 && !pointflag) zpad = '0';
- case '1': case '2': case '3':
- case '4': case '5': case '6':
- case '7': case '8': case '9':
- if (pointflag)
- maxwidth = maxwidth*10 + ch - '0';
- else
- len = len*10 + ch - '0';
- goto nextch;
- case '*':
- if (pointflag)
- maxwidth = va_arg( args, int );
- else
- len = va_arg( args, int );
- goto nextch;
- case '.': pointflag = 1; goto nextch;
- case 'l': longflag = 1; goto nextch;
- case 'u': case 'U':
- /*fmtnum(value,base,dosign,ljust,len,zpad) */
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 10,0, ljust, len, zpad ); break;
- case 'o': case 'O':
- /*fmtnum(value,base,dosign,ljust,len,zpad) */
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 8,0, ljust, len, zpad ); break;
- case 'd': case 'D':
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 10,1, ljust, len, zpad ); break;
- case 'x':
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value, 16,0, ljust, len, zpad ); break;
- case 'X':
- if( longflag ){
- value = va_arg( args, long );
- } else {
- value = va_arg( args, int );
- }
- fmtnum( value,-16,0, ljust, len, zpad ); break;
- case 's':
- strvalue = va_arg( args, char *);
- if (maxwidth > 0 || !pointflag) {
- if (pointflag && len > maxwidth)
- len = maxwidth; /* Adjust padding */
- fmtstr( strvalue,ljust,len,zpad, maxwidth);
- }
- break;
- case 'c':
- ch = va_arg( args, int );
- dopr_outch( ch ); break;
- case 'm':
-#if HASSTRERROR
- dostr(strerror(SyslogErrno), 0);
-#else
- if (SyslogErrno < 0 || SyslogErrno > sys_nerr)
- {
- dostr("Error ", 0);
- fmtnum(SyslogErrno, 10, 0, 0, 0, 0);
- }
- else
- dostr(sys_errlist[SyslogErrno], 0);
-#endif
- break;
-
- case '%': dopr_outch( ch ); continue;
- default:
- dostr( "???????" , 0);
- }
- break;
- default:
- dopr_outch( ch );
- break;
- }
- }
- *output = 0;
-}
-
-static void
-fmtstr( value, ljust, len, zpad, maxwidth )
- char *value;
- int ljust, len, zpad, maxwidth;
-{
- int padlen, strlen; /* amount to pad */
-
- if( value == 0 ){
- value = "<NULL>";
- }
- for( strlen = 0; value[strlen]; ++ strlen ); /* strlen */
- if (strlen > maxwidth && maxwidth)
- strlen = maxwidth;
- padlen = len - strlen;
- if( padlen < 0 ) padlen = 0;
- if( ljust ) padlen = -padlen;
- while( padlen > 0 ) {
- dopr_outch( ' ' );
- --padlen;
- }
- dostr( value, maxwidth );
- while( padlen < 0 ) {
- dopr_outch( ' ' );
- ++padlen;
- }
-}
-
-static void
-fmtnum( value, base, dosign, ljust, len, zpad )
- long value;
- int base, dosign, ljust, len, zpad;
-{
- int signvalue = 0;
- unsigned long uvalue;
- char convert[20];
- int place = 0;
- int padlen = 0; /* amount to pad */
- int caps = 0;
-
- /* DEBUGP(("value 0x%x, base %d, dosign %d, ljust %d, len %d, zpad %d\n",
- value, base, dosign, ljust, len, zpad )); */
- uvalue = value;
- if( dosign ){
- if( value < 0 ) {
- signvalue = '-';
- uvalue = -value;
- }
- }
- if( base < 0 ){
- caps = 1;
- base = -base;
- }
- do{
- convert[place++] =
- (caps? "0123456789ABCDEF":"0123456789abcdef")
- [uvalue % (unsigned)base ];
- uvalue = (uvalue / (unsigned)base );
- }while(uvalue);
- convert[place] = 0;
- padlen = len - place;
- if( padlen < 0 ) padlen = 0;
- if( ljust ) padlen = -padlen;
- /* DEBUGP(( "str '%s', place %d, sign %c, padlen %d\n",
- convert,place,signvalue,padlen)); */
- if( zpad && padlen > 0 ){
- if( signvalue ){
- dopr_outch( signvalue );
- --padlen;
- signvalue = 0;
- }
- while( padlen > 0 ){
- dopr_outch( zpad );
- --padlen;
- }
- }
- while( padlen > 0 ) {
- dopr_outch( ' ' );
- --padlen;
- }
- if( signvalue ) dopr_outch( signvalue );
- while( place > 0 ) dopr_outch( convert[--place] );
- while( padlen < 0 ){
- dopr_outch( ' ' );
- ++padlen;
- }
-}
-
-static void
-dostr( str , cut)
- char *str;
- int cut;
-{
- if (cut) {
- while(*str && cut-- > 0) dopr_outch(*str++);
- } else {
- while(*str) dopr_outch(*str++);
- }
-}
-
-static void
-dopr_outch( c )
- int c;
-{
-#if 0
- if( iscntrl(c) && c != '\n' && c != '\t' ){
- c = '@' + (c & 0x1F);
- if( DoprEnd == 0 || output < DoprEnd )
- *output++ = '^';
- }
-#endif
- if( DoprEnd == 0 || output < DoprEnd )
- *output++ = c;
- else
- SnprfOverflow++;
-}
- /*
-** USERSHELLOK -- tell if a user's shell is ok for unrestricted use
-**
-** Parameters:
-** user -- the name of the user we are checking.
-** shell -- the user's shell from /etc/passwd
-**
-** Returns:
-** TRUE -- if it is ok to use this for unrestricted access.
-** FALSE -- if the shell is restricted.
-*/
-
-#if !HASGETUSERSHELL
-
-# ifndef _PATH_SHELLS
-# define _PATH_SHELLS "/etc/shells"
-# endif
-
-# if defined(_AIX3) || defined(_AIX4)
-# include <userconf.h>
-# include <usersec.h>
-# endif
-
-char *DefaultUserShells[] =
-{
- "/bin/sh", /* standard shell */
- "/usr/bin/sh",
- "/bin/csh", /* C shell */
- "/usr/bin/csh",
-#ifdef __hpux
-# ifdef V4FS
- "/usr/bin/rsh", /* restricted Bourne shell */
- "/usr/bin/ksh", /* Korn shell */
- "/usr/bin/rksh", /* restricted Korn shell */
- "/usr/bin/pam",
- "/usr/bin/keysh", /* key shell (extended Korn shell) */
- "/usr/bin/posix/sh",
-# else
- "/bin/rsh", /* restricted Bourne shell */
- "/bin/ksh", /* Korn shell */
- "/bin/rksh", /* restricted Korn shell */
- "/bin/pam",
- "/usr/bin/keysh", /* key shell (extended Korn shell) */
- "/bin/posix/sh",
-# endif
-#endif
-#if defined(_AIX3) || defined(_AIX4)
- "/bin/ksh", /* Korn shell */
- "/usr/bin/ksh",
- "/bin/tsh", /* trusted shell */
- "/usr/bin/tsh",
- "/bin/bsh", /* Bourne shell */
- "/usr/bin/bsh",
-#endif
-#ifdef __svr4__
- "/bin/ksh", /* Korn shell */
- "/usr/bin/ksh",
-#endif
- NULL
-};
-
-#endif
-
-#define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
-
-bool
-usershellok(user, shell)
- char *user;
- char *shell;
-{
-#if HASGETUSERSHELL
- register char *p;
- extern char *getusershell();
-
- if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
- ConfigLevel <= 1)
- return TRUE;
-
- setusershell();
- while ((p = getusershell()) != NULL)
- if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
- break;
- endusershell();
- return p != NULL;
-#else
-# if USEGETCONFATTR
- auto char *v;
-# endif
- register FILE *shellf;
- char buf[MAXLINE];
-
- if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't'))
- return TRUE;
-
-# if USEGETCONFATTR
- /*
- ** Naturally IBM has a "better" idea.....
- **
- ** What a crock. This interface isn't documented, it is
- ** considered part of the security library (-ls), and it
- ** only works if you are running as root (since the list
- ** of valid shells is obviously a source of great concern).
- ** I recommend that you do NOT define USEGETCONFATTR,
- ** especially since you are going to have to set up an
- ** /etc/shells anyhow to handle the cases where getconfattr
- ** fails.
- */
-
- if (getconfattr(SC_SYS_LOGIN, SC_SHELLS, &v, SEC_LIST) == 0 && v != NULL)
- {
- while (*v != '\0')
- {
- if (strcmp(v, shell) == 0 || strcmp(v, WILDCARD_SHELL) == 0)
- return TRUE;
- v += strlen(v) + 1;
- }
- return FALSE;
- }
-# endif
-
- shellf = fopen(_PATH_SHELLS, "r");
- if (shellf == NULL)
- {
- /* no /etc/shells; see if it is one of the std shells */
- char **d;
-
- for (d = DefaultUserShells; *d != NULL; d++)
- {
- if (strcmp(shell, *d) == 0)
- return TRUE;
- }
- return FALSE;
- }
-
- while (fgets(buf, sizeof buf, shellf) != NULL)
- {
- register char *p, *q;
-
- p = buf;
- while (*p != '\0' && *p != '#' && *p != '/')
- p++;
- if (*p == '#' || *p == '\0')
- continue;
- q = p;
- while (*p != '\0' && *p != '#' && !isspace(*p))
- p++;
- *p = '\0';
- if (strcmp(shell, q) == 0 || strcmp(WILDCARD_SHELL, q) == 0)
- {
- fclose(shellf);
- return TRUE;
- }
- }
- fclose(shellf);
- return FALSE;
-#endif
-}
- /*
-** FREEDISKSPACE -- see how much free space is on the queue filesystem
-**
-** Only implemented if you have statfs.
-**
-** Parameters:
-** dir -- the directory in question.
-** bsize -- a variable into which the filesystem
-** block size is stored.
-**
-** Returns:
-** The number of bytes free on the queue filesystem.
-** -1 if the statfs call fails.
-**
-** Side effects:
-** Puts the filesystem block size into bsize.
-*/
-
-/* statfs types */
-#define SFS_NONE 0 /* no statfs implementation */
-#define SFS_USTAT 1 /* use ustat */
-#define SFS_4ARGS 2 /* use four-argument statfs call */
-#define SFS_VFS 3 /* use <sys/vfs.h> implementation */
-#define SFS_MOUNT 4 /* use <sys/mount.h> implementation */
-#define SFS_STATFS 5 /* use <sys/statfs.h> implementation */
-#define SFS_STATVFS 6 /* use <sys/statvfs.h> implementation */
-
-#ifndef SFS_TYPE
-# define SFS_TYPE SFS_NONE
-#endif
-
-#if SFS_TYPE == SFS_USTAT
-# include <ustat.h>
-#endif
-#if SFS_TYPE == SFS_4ARGS || SFS_TYPE == SFS_STATFS
-# include <sys/statfs.h>
-#endif
-#if SFS_TYPE == SFS_VFS
-# include <sys/vfs.h>
-#endif
-#if SFS_TYPE == SFS_MOUNT
-# include <sys/mount.h>
-#endif
-#if SFS_TYPE == SFS_STATVFS
-# include <sys/statvfs.h>
-#endif
-
-long
-freediskspace(dir, bsize)
- char *dir;
- long *bsize;
-{
-#if SFS_TYPE != SFS_NONE
-# if SFS_TYPE == SFS_USTAT
- struct ustat fs;
- struct stat statbuf;
-# define FSBLOCKSIZE DEV_BSIZE
-# define SFS_BAVAIL f_tfree
-# else
-# if defined(ultrix)
- struct fs_data fs;
-# define SFS_BAVAIL fd_bfreen
-# define FSBLOCKSIZE 1024L
-# else
-# if SFS_TYPE == SFS_STATVFS
- struct statvfs fs;
-# define FSBLOCKSIZE fs.f_frsize
-# else
- struct statfs fs;
-# define FSBLOCKSIZE fs.f_bsize
-# endif
-# endif
-# endif
-# ifndef SFS_BAVAIL
-# define SFS_BAVAIL f_bavail
-# endif
-
-# if SFS_TYPE == SFS_USTAT
- if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
-# else
-# if SFS_TYPE == SFS_4ARGS
- if (statfs(dir, &fs, sizeof fs, 0) == 0)
-# else
-# if SFS_TYPE == SFS_STATVFS
- if (statvfs(dir, &fs) == 0)
-# else
-# if defined(ultrix)
- if (statfs(dir, &fs) > 0)
-# else
- if (statfs(dir, &fs) == 0)
-# endif
-# endif
-# endif
-# endif
- {
- if (bsize != NULL)
- *bsize = FSBLOCKSIZE;
- if (fs.SFS_BAVAIL <= 0)
- return 0;
- else
- return fs.SFS_BAVAIL;
- }
-#endif
- return (-1);
-}
- /*
-** ENOUGHDISKSPACE -- is there enough free space on the queue fs?
-**
-** Only implemented if you have statfs.
-**
-** Parameters:
-** msize -- the size to check against. If zero, we don't yet
-** know how big the message will be, so just check for
-** a "reasonable" amount.
-**
-** Returns:
-** TRUE if there is enough space.
-** FALSE otherwise.
-*/
-
-bool
-enoughdiskspace(msize)
- long msize;
-{
- long bfree, bsize;
-
- if (MinBlocksFree <= 0 && msize <= 0)
- {
- if (tTd(4, 80))
- printf("enoughdiskspace: no threshold\n");
- return TRUE;
- }
-
- if ((bfree = freediskspace(QueueDir, &bsize)) >= 0)
- {
- if (tTd(4, 80))
- printf("enoughdiskspace: bavail=%ld, need=%ld\n",
- bfree, msize);
-
- /* convert msize to block count */
- msize = msize / bsize + 1;
- if (MinBlocksFree >= 0)
- msize += MinBlocksFree;
-
- if (bfree < msize)
- {
- if (LogLevel > 0)
- sm_syslog(LOG_ALERT, CurEnv->e_id,
- "low on space (have %ld, %s needs %ld in %s)",
- bfree,
- CurHostName == NULL ? "SMTP-DAEMON" : CurHostName,
- msize, QueueDir);
- return FALSE;
- }
- }
- else if (tTd(4, 80))
- printf("enoughdiskspace failure: min=%ld, need=%ld: %s\n",
- MinBlocksFree, msize, errstring(errno));
- return TRUE;
-}
- /*
-** TRANSIENTERROR -- tell if an error code indicates a transient failure
-**
-** This looks at an errno value and tells if this is likely to
-** go away if retried later.
-**
-** Parameters:
-** err -- the errno code to classify.
-**
-** Returns:
-** TRUE if this is probably transient.
-** FALSE otherwise.
-*/
-
-bool
-transienterror(err)
- int err;
-{
- switch (err)
- {
- case EIO: /* I/O error */
- case ENXIO: /* Device not configured */
- case EAGAIN: /* Resource temporarily unavailable */
- case ENOMEM: /* Cannot allocate memory */
- case ENODEV: /* Operation not supported by device */
- case ENFILE: /* Too many open files in system */
- case EMFILE: /* Too many open files */
- case ENOSPC: /* No space left on device */
-#ifdef ETIMEDOUT
- case ETIMEDOUT: /* Connection timed out */
-#endif
-#ifdef ESTALE
- case ESTALE: /* Stale NFS file handle */
-#endif
-#ifdef ENETDOWN
- case ENETDOWN: /* Network is down */
-#endif
-#ifdef ENETUNREACH
- case ENETUNREACH: /* Network is unreachable */
-#endif
-#ifdef ENETRESET
- case ENETRESET: /* Network dropped connection on reset */
-#endif
-#ifdef ECONNABORTED
- case ECONNABORTED: /* Software caused connection abort */
-#endif
-#ifdef ECONNRESET
- case ECONNRESET: /* Connection reset by peer */
-#endif
-#ifdef ENOBUFS
- case ENOBUFS: /* No buffer space available */
-#endif
-#ifdef ESHUTDOWN
- case ESHUTDOWN: /* Can't send after socket shutdown */
-#endif
-#ifdef ECONNREFUSED
- case ECONNREFUSED: /* Connection refused */
-#endif
-#ifdef EHOSTDOWN
- case EHOSTDOWN: /* Host is down */
-#endif
-#ifdef EHOSTUNREACH
- case EHOSTUNREACH: /* No route to host */
-#endif
-#ifdef EDQUOT
- case EDQUOT: /* Disc quota exceeded */
-#endif
-#ifdef EPROCLIM
- case EPROCLIM: /* Too many processes */
-#endif
-#ifdef EUSERS
- case EUSERS: /* Too many users */
-#endif
-#ifdef EDEADLK
- case EDEADLK: /* Resource deadlock avoided */
-#endif
-#ifdef EISCONN
- case EISCONN: /* Socket already connected */
-#endif
-#ifdef EINPROGRESS
- case EINPROGRESS: /* Operation now in progress */
-#endif
-#ifdef EALREADY
- case EALREADY: /* Operation already in progress */
-#endif
-#ifdef EADDRINUSE
- case EADDRINUSE: /* Address already in use */
-#endif
-#ifdef EADDRNOTAVAIL
- case EADDRNOTAVAIL: /* Can't assign requested address */
-#endif
-#ifdef ETXTBSY
- case ETXTBSY: /* (Apollo) file locked */
-#endif
-#if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
- case ENOSR: /* Out of streams resources */
-#endif
- case E_SM_OPENTIMEOUT: /* PSEUDO: open timed out */
- return TRUE;
- }
-
- /* nope, must be permanent */
- return FALSE;
-}
- /*
-** LOCKFILE -- lock a file using flock or (shudder) fcntl locking
-**
-** Parameters:
-** fd -- the file descriptor of the file.
-** filename -- the file name (for error messages).
-** ext -- the filename extension.
-** type -- type of the lock. Bits can be:
-** LOCK_EX -- exclusive lock.
-** LOCK_NB -- non-blocking.
-**
-** Returns:
-** TRUE if the lock was acquired.
-** FALSE otherwise.
-*/
-
-bool
-lockfile(fd, filename, ext, type)
- int fd;
- char *filename;
- char *ext;
- int type;
-{
- int i;
-# if !HASFLOCK
- int action;
- struct flock lfd;
-
- if (ext == NULL)
- ext = "";
-
- bzero(&lfd, sizeof lfd);
- if (bitset(LOCK_UN, type))
- lfd.l_type = F_UNLCK;
- else if (bitset(LOCK_EX, type))
- lfd.l_type = F_WRLCK;
- else
- lfd.l_type = F_RDLCK;
-
- if (bitset(LOCK_NB, type))
- action = F_SETLK;
- else
- action = F_SETLKW;
-
- if (tTd(55, 60))
- printf("lockfile(%s%s, action=%d, type=%d): ",
- filename, ext, action, lfd.l_type);
-
- while ((i = fcntl(fd, action, &lfd)) < 0 && errno == EINTR)
- continue;
- if (i >= 0)
- {
- if (tTd(55, 60))
- printf("SUCCESS\n");
- return TRUE;
- }
-
- if (tTd(55, 60))
- printf("(%s) ", errstring(errno));
-
- /*
- ** On SunOS, if you are testing using -oQ/tmp/mqueue or
- ** -oA/tmp/aliases or anything like that, and /tmp is mounted
- ** as type "tmp" (that is, served from swap space), the
- ** previous fcntl will fail with "Invalid argument" errors.
- ** Since this is fairly common during testing, we will assume
- ** that this indicates that the lock is successfully grabbed.
- */
-
- if (errno == EINVAL)
- {
- if (tTd(55, 60))
- printf("SUCCESS\n");
- return TRUE;
- }
-
- if (!bitset(LOCK_NB, type) || (errno != EACCES && errno != EAGAIN))
- {
- int omode = -1;
-# ifdef F_GETFL
- int oerrno = errno;
-
- (void) fcntl(fd, F_GETFL, &omode);
- errno = oerrno;
-# endif
- syserr("cannot lockf(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
- filename, ext, fd, type, omode, geteuid());
- dumpfd(fd, TRUE, TRUE);
- }
-# else
- if (ext == NULL)
- ext = "";
-
- if (tTd(55, 60))
- printf("lockfile(%s%s, type=%o): ", filename, ext, type);
-
- while ((i = flock(fd, type)) < 0 && errno == EINTR)
- continue;
- if (i >= 0)
- {
- if (tTd(55, 60))
- printf("SUCCESS\n");
- return TRUE;
- }
-
- if (tTd(55, 60))
- printf("(%s) ", errstring(errno));
-
- if (!bitset(LOCK_NB, type) || errno != EWOULDBLOCK)
- {
- int omode = -1;
-# ifdef F_GETFL
- int oerrno = errno;
-
- (void) fcntl(fd, F_GETFL, &omode);
- errno = oerrno;
-# endif
- syserr("cannot flock(%s%s, fd=%d, type=%o, omode=%o, euid=%d)",
- filename, ext, fd, type, omode, geteuid());
- dumpfd(fd, TRUE, TRUE);
- }
-# endif
- if (tTd(55, 60))
- printf("FAIL\n");
- return FALSE;
-}
- /*
-** CHOWNSAFE -- tell if chown is "safe" (executable only by root)
-**
-** Unfortunately, given that we can't predict other systems on which
-** a remote mounted (NFS) filesystem will be mounted, the answer is
-** almost always that this is unsafe.
-**
-** Note also that many operating systems have non-compliant
-** implementations of the _POSIX_CHOWN_RESTRICTED variable and the
-** fpathconf() routine. According to IEEE 1003.1-1990, if
-** _POSIX_CHOWN_RESTRICTED is defined and not equal to -1, then
-** no non-root process can give away the file. However, vendors
-** don't take NFS into account, so a comfortable value of
-** _POSIX_CHOWN_RESTRICTED tells us nothing.
-**
-** Also, some systems (e.g., IRIX 6.2) return 1 from fpathconf()
-** even on files where chown is not restricted. Many systems get
-** this wrong on NFS-based filesystems (that is, they say that chown
-** is restricted [safe] on NFS filesystems where it may not be, since
-** other systems can access the same filesystem and do file giveaway;
-** only the NFS server knows for sure!) Hence, it is important to
-** get the value of SAFENFSPATHCONF correct -- it should be defined
-** _only_ after testing (see test/t_pathconf.c) a system on an unsafe
-** NFS-based filesystem to ensure that you can get meaningful results.
-** If in doubt, assume unsafe!
-**
-** You may also need to tweak IS_SAFE_CHOWN -- it should be a
-** condition indicating whether the return from pathconf indicates
-** that chown is safe (typically either > 0 or >= 0 -- there isn't
-** even any agreement about whether a zero return means that a file
-** is or is not safe). It defaults to "> 0".
-**
-** If the parent directory is safe (writable only by owner back
-** to the root) then we can relax slightly and trust fpathconf
-** in more circumstances. This is really a crock -- if this is an
-** NFS mounted filesystem then we really know nothing about the
-** underlying implementation. However, most systems pessimize and
-** return an error (EINVAL or EOPNOTSUPP) on NFS filesystems, which
-** we interpret as unsafe, as we should. Thus, this heuristic gets
-** us into a possible problem only on systems that have a broken
-** pathconf implementation and which are also poorly configured
-** (have :include: files in group- or world-writable directories).
-**
-** Parameters:
-** fd -- the file descriptor to check.
-** safedir -- set if the parent directory is safe.
-**
-** Returns:
-** TRUE -- if the chown(2) operation is "safe" -- that is,
-** only root can chown the file to an arbitrary user.
-** FALSE -- if an arbitrary user can give away a file.
-*/
-
-#ifndef IS_SAFE_CHOWN
-# define IS_SAFE_CHOWN > 0
-#endif
-
-bool
-chownsafe(fd, safedir)
- int fd;
- bool safedir;
-{
-#if (!defined(_POSIX_CHOWN_RESTRICTED) || _POSIX_CHOWN_RESTRICTED != -1) && \
- (defined(_PC_CHOWN_RESTRICTED) || defined(_GNU_TYPES_H))
- int rval;
-
- /* give the system administrator a chance to override */
- if (ChownAlwaysSafe)
- return TRUE;
-
- /*
- ** Some systems (e.g., SunOS) seem to have the call and the
- ** #define _PC_CHOWN_RESTRICTED, but don't actually implement
- ** the call. This heuristic checks for that.
- */
-
- errno = 0;
- rval = fpathconf(fd, _PC_CHOWN_RESTRICTED);
-# if SAFENFSPATHCONF
- return errno == 0 && rval IS_SAFE_CHOWN;
-# else
- return safedir && errno == 0 && rval IS_SAFE_CHOWN;
-# endif
-#else
- return ChownAlwaysSafe;
-#endif
-}
- /*
-** RESETLIMITS -- reset system controlled resource limits
-**
-** This is to avoid denial-of-service attacks
-**
-** Parameters:
-** none
-**
-** Returns:
-** none
-*/
-
-#if HASSETRLIMIT
-# ifdef RLIMIT_NEEDS_SYS_TIME_H
-# include <sys/time.h>
-# endif
-# include <sys/resource.h>
-#endif
-#ifndef FD_SETSIZE
-# define FD_SETSIZE 256
-#endif
-
-void
-resetlimits()
-{
-#if HASSETRLIMIT
- struct rlimit lim;
-
- lim.rlim_cur = lim.rlim_max = RLIM_INFINITY;
- (void) setrlimit(RLIMIT_CPU, &lim);
- (void) setrlimit(RLIMIT_FSIZE, &lim);
-# ifdef RLIMIT_NOFILE
- lim.rlim_cur = lim.rlim_max = FD_SETSIZE;
- (void) setrlimit(RLIMIT_NOFILE, &lim);
-# endif
-#else
-# if HASULIMIT
- (void) ulimit(2, 0x3fffff);
- (void) ulimit(4, FD_SETSIZE);
-# endif
-#endif
- errno = 0;
-}
- /*
-** GETCFNAME -- return the name of the .cf file.
-**
-** Some systems (e.g., NeXT) determine this dynamically.
-*/
-
-char *
-getcfname()
-{
-
- if (ConfFile != NULL)
- return ConfFile;
-#if NETINFO
- {
- extern char *ni_propval();
- char *cflocation;
-
- cflocation = ni_propval("/locations", NULL, "sendmail",
- "sendmail.cf", '\0');
- if (cflocation != NULL)
- return cflocation;
- }
-#endif
-
- return _PATH_SENDMAILCF;
-}
- /*
-** SETVENDOR -- process vendor code from V configuration line
-**
-** Parameters:
-** vendor -- string representation of vendor.
-**
-** Returns:
-** TRUE -- if ok.
-** FALSE -- if vendor code could not be processed.
-**
-** Side Effects:
-** It is reasonable to set mode flags here to tweak
-** processing in other parts of the code if necessary.
-** For example, if you are a vendor that uses $%y to
-** indicate YP lookups, you could enable that here.
-*/
-
-bool
-setvendor(vendor)
- char *vendor;
-{
- if (strcasecmp(vendor, "Berkeley") == 0)
- {
- VendorCode = VENDOR_BERKELEY;
- return TRUE;
- }
-
- /* add vendor extensions here */
-
-#ifdef SUN_EXTENSIONS
- if (strcasecmp(vendor, "Sun") == 0)
- {
- VendorCode = VENDOR_SUN;
- return TRUE;
- }
-#endif
-
- return FALSE;
-}
- /*
-** VENDOR_PRE_DEFAULTS, VENDOR_POST_DEFAULTS -- set vendor-specific defaults
-**
-** Vendor_pre_defaults is called before reading the configuration
-** file; vendor_post_defaults is called immediately after.
-**
-** Parameters:
-** e -- the global environment to initialize.
-**
-** Returns:
-** none.
-*/
-
-#if SHARE_V1
-int DefShareUid; /* default share uid to run as -- unused??? */
-#endif
-
-void
-vendor_pre_defaults(e)
- ENVELOPE *e;
-{
-#if SHARE_V1
- /* OTHERUID is defined in shares.h, do not be alarmed */
- DefShareUid = OTHERUID;
-#endif
-#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
- sun_pre_defaults(e);
-#endif
-#ifdef apollo
- /* stupid domain/os can't even open /etc/sendmail.cf without this */
- setuserenv("ISP", NULL);
- setuserenv("SYSTYPE", NULL);
-#endif
-}
-
-
-void
-vendor_post_defaults(e)
- ENVELOPE *e;
-{
-#if defined(SUN_EXTENSIONS) && defined(SUN_DEFAULT_VALUES)
- sun_post_defaults(e);
-#endif
-}
- /*
-** VENDOR_DAEMON_SETUP -- special vendor setup needed for daemon mode
-*/
-
-void
-vendor_daemon_setup(e)
- ENVELOPE *e;
-{
-#if SECUREWARE
- if (getluid() != -1)
- {
- usrerr("Daemon cannot have LUID");
- exit(EX_USAGE);
- }
-#endif /* SECUREWARE */
-}
- /*
-** VENDOR_SET_UID -- do setup for setting a user id
-**
-** This is called when we are still root.
-**
-** Parameters:
-** uid -- the uid we are about to become.
-**
-** Returns:
-** none.
-*/
-
-void
-vendor_set_uid(uid)
- UID_T uid;
-{
- /*
- ** We need to setup the share groups (lnodes)
- ** and and auditing inforation (luid's)
- ** before we loose our ``root''ness.
- */
-#if SHARE_V1
- if (setupshares(uid, syserr) != 0)
- syserr("Unable to set up shares");
-#endif
-#if SECUREWARE
- (void) setup_secure(uid);
-#endif
-}
- /*
-** VALIDATE_CONNECTION -- check connection for rationality
-**
-** If the connection is rejected, this routine should log an
-** appropriate message -- but should never issue any SMTP protocol.
-**
-** Parameters:
-** sap -- a pointer to a SOCKADDR naming the peer.
-** hostname -- the name corresponding to sap.
-** e -- the current envelope.
-**
-** Returns:
-** TRUE -- if the connection should be accepted.
-** FALSE -- if it should be rejected.
-*/
-
-#if TCPWRAPPERS
-# include <tcpd.h>
-
-/* tcpwrappers does no logging, but you still have to declare these -- ugh */
-int allow_severity = LOG_INFO;
-int deny_severity = LOG_NOTICE;
-#endif
-
-#if DAEMON
-bool
-validate_connection(sap, hostname, e)
- SOCKADDR *sap;
- char *hostname;
- ENVELOPE *e;
-{
- if (tTd(48, 3))
- printf("validate_connection(%s, %s)\n",
- hostname, anynet_ntoa(sap));
-
- if (rscheck("check_relay", hostname, anynet_ntoa(sap), e) != EX_OK)
- {
- if (tTd(48, 4))
- printf(" ... validate_connection: BAD (rscheck)\n");
- return FALSE;
- }
-
-#if TCPWRAPPERS
- if (!hosts_ctl("sendmail", hostname, anynet_ntoa(sap), STRING_UNKNOWN))
- {
- if (tTd(48, 4))
- printf(" ... validate_connection: BAD (tcpwrappers)\n");
- if (LogLevel >= 4)
- sm_syslog(LOG_NOTICE, NOQID,
- "tcpwrappers (%s, %s) rejection",
- hostname, anynet_ntoa(sap));
- return FALSE;
- }
-#endif
- if (tTd(48, 4))
- printf(" ... validate_connection: OK\n");
- return TRUE;
-}
-
-#endif
- /*
-** STRTOL -- convert string to long integer
-**
-** For systems that don't have it in the C library.
-**
-** This is taken verbatim from the 4.4-Lite C library.
-*/
-
-#ifdef NEEDSTRTOL
-
-#if defined(LIBC_SCCS) && !defined(lint)
-static char sccsid[] = "@(#)strtol.c 8.1 (Berkeley) 6/4/93";
-#endif /* LIBC_SCCS and not lint */
-
-#include <limits.h>
-
-/*
- * Convert a string to a long integer.
- *
- * Ignores `locale' stuff. Assumes that the upper and lower case
- * alphabets and digits are each contiguous.
- */
-
-long
-strtol(nptr, endptr, base)
- const char *nptr;
- char **endptr;
- register int base;
-{
- register const char *s = nptr;
- register unsigned long acc;
- register int c;
- register unsigned long cutoff;
- register int neg = 0, any, cutlim;
-
- /*
- * Skip white space and pick up leading +/- sign if any.
- * If base is 0, allow 0x for hex and 0 for octal, else
- * assume decimal; if base is already 16, allow 0x.
- */
- do {
- c = *s++;
- } while (isspace(c));
- if (c == '-') {
- neg = 1;
- c = *s++;
- } else if (c == '+')
- c = *s++;
- if ((base == 0 || base == 16) &&
- c == '0' && (*s == 'x' || *s == 'X')) {
- c = s[1];
- s += 2;
- base = 16;
- }
- if (base == 0)
- base = c == '0' ? 8 : 10;
-
- /*
- * Compute the cutoff value between legal numbers and illegal
- * numbers. That is the largest legal value, divided by the
- * base. An input number that is greater than this value, if
- * followed by a legal input character, is too big. One that
- * is equal to this value may be valid or not; the limit
- * between valid and invalid numbers is then based on the last
- * digit. For instance, if the range for longs is
- * [-2147483648..2147483647] and the input base is 10,
- * cutoff will be set to 214748364 and cutlim to either
- * 7 (neg==0) or 8 (neg==1), meaning that if we have accumulated
- * a value > 214748364, or equal but the next digit is > 7 (or 8),
- * the number is too big, and we will return a range error.
- *
- * Set any if any `digits' consumed; make it negative to indicate
- * overflow.
- */
- cutoff = neg ? -(unsigned long)LONG_MIN : LONG_MAX;
- cutlim = cutoff % (unsigned long)base;
- cutoff /= (unsigned long)base;
- for (acc = 0, any = 0;; c = *s++) {
- if (isdigit(c))
- c -= '0';
- else if (isalpha(c))
- c -= isupper(c) ? 'A' - 10 : 'a' - 10;
- else
- break;
- if (c >= base)
- break;
- if (any < 0 || acc > cutoff || acc == cutoff && c > cutlim)
- any = -1;
- else {
- any = 1;
- acc *= base;
- acc += c;
- }
- }
- if (any < 0) {
- acc = neg ? LONG_MIN : LONG_MAX;
- errno = ERANGE;
- } else if (neg)
- acc = -acc;
- if (endptr != 0)
- *endptr = (char *)(any ? s - 1 : nptr);
- return (acc);
-}
-
-#endif
- /*
-** STRSTR -- find first substring in string
-**
-** Parameters:
-** big -- the big (full) string.
-** little -- the little (sub) string.
-**
-** Returns:
-** A pointer to the first instance of little in big.
-** big if little is the null string.
-** NULL if little is not contained in big.
-*/
-
-#ifdef NEEDSTRSTR
-
-char *
-strstr(big, little)
- char *big;
- char *little;
-{
- register char *p = big;
- int l;
-
- if (*little == '\0')
- return big;
- l = strlen(little);
-
- while ((p = strchr(p, *little)) != NULL)
- {
- if (strncmp(p, little, l) == 0)
- return p;
- p++;
- }
- return NULL;
-}
-
-#endif
- /*
-** SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
-**
-** Some operating systems have wierd problems with the gethostbyXXX
-** routines. For example, Solaris versions at least through 2.3
-** don't properly deliver a canonical h_name field. This tries to
-** work around these problems.
-*/
-
-struct hostent *
-sm_gethostbyname(name)
- char *name;
-{
- struct hostent *h;
-#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204) || (defined(sony_news) && defined(__svr4))
-# if SOLARIS == 20300 || SOLARIS == 203
- static struct hostent hp;
- static char buf[1000];
- extern struct hostent *_switch_gethostbyname_r();
-
- if (tTd(61, 10))
- printf("_switch_gethostbyname_r(%s)... ", name);
- h = _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
-# else
- extern struct hostent *__switch_gethostbyname();
-
- if (tTd(61, 10))
- printf("__switch_gethostbyname(%s)... ", name);
- h = __switch_gethostbyname(name);
-# endif
-#else
- int nmaps;
- char *maptype[MAXMAPSTACK];
- short mapreturn[MAXMAPACTIONS];
- char hbuf[MAXNAME];
-
- if (tTd(61, 10))
- printf("gethostbyname(%s)... ", name);
- h = gethostbyname(name);
- if (h == NULL)
- {
- if (tTd(61, 10))
- printf("failure\n");
-
- nmaps = switch_map_find("hosts", maptype, mapreturn);
- while (--nmaps >= 0)
- if (strcmp(maptype[nmaps], "nis") == 0 ||
- strcmp(maptype[nmaps], "files") == 0)
- break;
- if (nmaps >= 0)
- {
- /* try short name */
- if (strlen(name) > (SIZE_T) sizeof hbuf - 1)
- return NULL;
- strcpy(hbuf, name);
- shorten_hostname(hbuf);
-
- /* if it hasn't been shortened, there's no point */
- if (strcmp(hbuf, name) != 0)
- {
- if (tTd(61, 10))
- printf("gethostbyname(%s)... ", hbuf);
- h = gethostbyname(hbuf);
- }
- }
- }
-#endif
- if (tTd(61, 10))
- {
- if (h == NULL)
- printf("failure\n");
- else
- printf("%s\n", h->h_name);
- }
- return h;
-}
-
-struct hostent *
-sm_gethostbyaddr(addr, len, type)
- char *addr;
- int len;
- int type;
-{
-#if (SOLARIS > 10000 && SOLARIS < 20400) || (defined(SOLARIS) && SOLARIS < 204)
-# if SOLARIS == 20300 || SOLARIS == 203
- static struct hostent hp;
- static char buf[1000];
- extern struct hostent *_switch_gethostbyaddr_r();
-
- return _switch_gethostbyaddr_r(addr, len, type, &hp, buf, sizeof(buf), &h_errno);
-# else
- extern struct hostent *__switch_gethostbyaddr();
-
- return __switch_gethostbyaddr(addr, len, type);
-# endif
-#else
- return gethostbyaddr(addr, len, type);
-#endif
-}
- /*
-** SM_GETPW{NAM,UID} -- wrapper for getpwnam and getpwuid
-*/
-
-struct passwd *
-sm_getpwnam(user)
- char *user;
-{
-#ifdef _AIX4
- extern struct passwd *_getpwnam_shadow(const char *, const int);
-
- return _getpwnam_shadow(user, 0);
-#else
- return getpwnam(user);
-#endif
-}
-
-struct passwd *
-sm_getpwuid(uid)
- UID_T uid;
-{
-#if defined(_AIX4) && 0
- extern struct passwd *_getpwuid_shadow(const int, const int);
-
- return _getpwuid_shadow(uid,0);
-#else
- return getpwuid(uid);
-#endif
-}
- /*
-** SECUREWARE_SETUP_SECURE -- Convex SecureWare setup
-**
-** Set up the trusted computing environment for C2 level security
-** under SecureWare.
-**
-** Parameters:
-** uid -- uid of the user to initialize in the TCB
-**
-** Returns:
-** none
-**
-** Side Effects:
-** Initialized the user in the trusted computing base
-*/
-
-#if SECUREWARE
-
-# include <sys/security.h>
-# include <prot.h>
-
-void
-secureware_setup_secure(uid)
- UID_T uid;
-{
- int rc;
-
- if (getluid() != -1)
- return;
-
- if ((rc = set_secure_info(uid)) != SSI_GOOD_RETURN)
- {
- switch (rc)
- {
- case SSI_NO_PRPW_ENTRY:
- syserr("No protected passwd entry, uid = %d", uid);
- break;
-
- case SSI_LOCKED:
- syserr("Account has been disabled, uid = %d", uid);
- break;
-
- case SSI_RETIRED:
- syserr("Account has been retired, uid = %d", uid);
- break;
-
- case SSI_BAD_SET_LUID:
- syserr("Could not set LUID, uid = %d", uid);
- break;
-
- case SSI_BAD_SET_PRIVS:
- syserr("Could not set kernel privs, uid = %d", uid);
-
- default:
- syserr("Unknown return code (%d) from set_secure_info(%d)",
- rc, uid);
- break;
- }
- exit(EX_NOPERM);
- }
-}
-#endif /* SECUREWARE */
- /*
-** LOAD_IF_NAMES -- load interface-specific names into $=w
-**
-** Parameters:
-** none.
-**
-** Returns:
-** none.
-**
-** Side Effects:
-** Loads $=w with the names of all the interfaces.
-*/
-
-#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
-struct rtentry;
-struct mbuf;
-# include <arpa/inet.h>
-# ifndef SUNOS403
-# include <sys/time.h>
-# endif
-# include <net/if.h>
-#endif
-
-void
-load_if_names()
-{
-#if defined(SIOCGIFCONF) && !SIOCGIFCONF_IS_BROKEN
- int s;
- int i;
- struct ifconf ifc;
- int numifs;
-
- s = socket(AF_INET, SOCK_DGRAM, 0);
- if (s == -1)
- return;
-
- /* get the list of known IP address from the kernel */
-# if defined(SIOCGIFNUM) && !SIOCGIFNUM_IS_BROKEN
- if (ioctl(s, SIOCGIFNUM, (char *) &numifs) < 0)
- {
- /* can't get number of interfaces -- fall back */
- if (tTd(0, 4))
- printf("SIOCGIFNUM failed: %s\n", errstring(errno));
- numifs = -1;
- }
- else if (tTd(0, 42))
- printf("system has %d interfaces\n", numifs);
- if (numifs < 0)
-# endif
- numifs = 512;
-
- if (numifs <= 0)
- {
- close(s);
- return;
- }
- ifc.ifc_len = numifs * sizeof (struct ifreq);
- ifc.ifc_buf = xalloc(ifc.ifc_len);
- if (ioctl(s, SIOCGIFCONF, (char *)&ifc) < 0)
- {
- if (tTd(0, 4))
- printf("SIOGIFCONF failed: %s\n", errstring(errno));
- close(s);
- return;
- }
-
- /* scan the list of IP address */
- if (tTd(0, 40))
- printf("scanning for interface specific names, ifc_len=%d\n",
- ifc.ifc_len);
-
- for (i = 0; i < ifc.ifc_len; )
- {
- struct ifreq *ifr = (struct ifreq *) &ifc.ifc_buf[i];
- struct sockaddr *sa = &ifr->ifr_addr;
- struct in_addr ia;
- struct hostent *hp;
-#ifdef SIOCGIFFLAGS
- struct ifreq ifrf;
-#endif
- char ip_addr[256];
- extern char *inet_ntoa();
-
-#ifdef BSD4_4_SOCKADDR
- if (sa->sa_len > sizeof ifr->ifr_addr)
- i += sizeof ifr->ifr_name + sa->sa_len;
- else
-#endif
- i += sizeof *ifr;
-
- if (tTd(0, 20))
- printf("%s\n", anynet_ntoa((SOCKADDR *) sa));
-
- if (ifr->ifr_addr.sa_family != AF_INET)
- continue;
-
-#ifdef SIOCGIFFLAGS
- bzero(&ifrf, sizeof(struct ifreq));
- strncpy(ifrf.ifr_name, ifr->ifr_name, sizeof(ifrf.ifr_name));
- ioctl(s, SIOCGIFFLAGS, (char *) &ifrf);
- if (tTd(0, 41))
- printf("\tflags: %x\n", ifrf.ifr_flags);
-# define IFRFREF ifrf
-#else
-# define IFRFREF (*ifr)
-#endif
- if (!bitset(IFF_UP, IFRFREF.ifr_flags))
- continue;
-
- /* extract IP address from the list*/
- ia = (((struct sockaddr_in *) sa)->sin_addr);
- if (ia.s_addr == INADDR_ANY || ia.s_addr == INADDR_NONE)
- {
- message("WARNING: interface %s is UP with %s address",
- ifr->ifr_name, inet_ntoa(ia));
- continue;
- }
-
- /* save IP address in text from */
- (void) snprintf(ip_addr, sizeof ip_addr, "[%.*s]",
- sizeof ip_addr - 3,
- inet_ntoa(ia));
- if (!wordinclass(ip_addr, 'w'))
- {
- setclass('w', ip_addr);
- if (tTd(0, 4))
- printf("\ta.k.a.: %s\n", ip_addr);
- }
-
- /* skip "loopback" interface "lo" */
- if (bitset(IFF_LOOPBACK, IFRFREF.ifr_flags))
- continue;
-
- /* lookup name with IP address */
- hp = sm_gethostbyaddr((char *) &ia, sizeof(ia), AF_INET);
- if (hp == NULL)
- {
- if (LogLevel > 3)
- sm_syslog(LOG_WARNING, NOQID,
- "gethostbyaddr(%.100s) failed: %d\n",
- inet_ntoa(ia),
-#if NAMED_BIND
- h_errno);
-#else
- -1);
-#endif
- continue;
- }
-
- /* save its cname */
- if (!wordinclass((char *) hp->h_name, 'w'))
- {
- setclass('w', (char *) hp->h_name);
- if (tTd(0, 4))
- printf("\ta.k.a.: %s\n", hp->h_name);
- }
-
- /* save all it aliases name */
- while (*hp->h_aliases)
- {
- if (!wordinclass(*hp->h_aliases, 'w'))
- {
- setclass('w', *hp->h_aliases);
- if (tTd(0, 4))
- printf("\ta.k.a.: %s\n", *hp->h_aliases);
- }
- hp->h_aliases++;
- }
- }
- free(ifc.ifc_buf);
- close(s);
-# undef IFRFREF
-#endif
-}
- /*
-** GET_NUM_PROCS_ONLINE -- return the number of processors currently online
-**
-** Parameters:
-** none.
-**
-** Returns:
-** The number of processors online.
-*/
-
-int
-get_num_procs_online()
-{
- int nproc = 0;
-
-#if _FFR_SCALE_LA_BY_NUM_PROCS
-#ifdef _SC_NPROCESSORS_ONLN
- nproc = (int) sysconf(_SC_NPROCESSORS_ONLN);
-#endif
-#endif
- if (nproc <= 0)
- nproc = 1;
- return nproc;
-}
- /*
-** SM_SYSLOG -- syslog wrapper to keep messages under SYSLOG_BUFSIZE
-**
-** Parameters:
-** level -- syslog level
-** id -- envelope ID or NULL (NOQUEUE)
-** fmt -- format string
-** arg... -- arguments as implied by fmt.
-**
-** Returns:
-** none
-*/
-
-/* VARARGS3 */
-void
-# ifdef __STDC__
-sm_syslog(int level, const char *id, const char *fmt, ...)
-# else
-sm_syslog(level, id, fmt, va_alist)
- int level;
- const char *id;
- const char *fmt;
- va_dcl
-#endif
-{
- static char *buf = NULL;
- static size_t bufsize = MAXLINE;
- char *begin, *end;
- int seq = 1;
- int idlen;
- extern int SnprfOverflow;
- VA_LOCAL_DECL
-
- SyslogErrno = errno;
- if (id == NULL)
- {
- id = "NOQUEUE";
- idlen = 9;
- }
- else if (strcmp(id, NOQID) == 0)
- {
- id = "";
- idlen = 0;
- }
- else
- idlen = strlen(id + 2);
-bufalloc:
- if (buf == NULL)
- buf = (char *) xalloc(sizeof(char) * bufsize);
-
- /* do a virtual vsnprintf into buf */
- VA_START(fmt);
- buf[0] = 0;
- DoprEnd = buf + bufsize - 1;
- SnprfOverflow = 0;
- sm_dopr(buf, fmt, ap);
- *DoprEnd = '\0';
- VA_END;
- /* end of virtual vsnprintf */
-
- if (SnprfOverflow)
- {
- /* String too small, redo with correct size */
- bufsize += SnprfOverflow + 1;
- free(buf);
- buf = NULL;
- goto bufalloc;
- }
- if ((strlen(buf) + idlen + 1) < SYSLOG_BUFSIZE)
- {
-#if LOG
- if (*id == '\0')
- syslog(level, "%s", buf);
- else
- syslog(level, "%s: %s", id, buf);
-#else
- /*XXX should do something more sensible */
- if (*id == '\0')
- fprintf(stderr, "%s\n", buf);
- else
- fprintf(stderr, "%s: %s\n", id, buf);
-#endif
- return;
- }
-
- begin = buf;
- while (*begin != '\0' &&
- (strlen(begin) + idlen + 5) > SYSLOG_BUFSIZE)
- {
- char save;
-
- if (seq == 999)
- {
- /* Too many messages */
- break;
- }
- end = begin + SYSLOG_BUFSIZE - idlen - 12;
- while (end > begin)
- {
- /* Break on comma or space */
- if (*end == ',' || *end == ' ')
- {
- end++; /* Include separator */
- break;
- }
- end--;
- }
- /* No separator, break midstring... */
- if (end == begin)
- end = begin + SYSLOG_BUFSIZE - idlen - 12;
- save = *end;
- *end = 0;
-#if LOG
- syslog(level, "%s[%d]: %s ...", id, seq++, begin);
-#else
- fprintf(stderr, "%s[%d]: %s ...\n", id, seq++, begin);
-#endif
- *end = save;
- begin = end;
- }
- if (seq == 999)
-#if LOG
- syslog(level, "%s[%d]: log terminated, too many parts", id, seq);
-#else
- fprintf(stderr, "%s[%d]: log terminated, too many parts\n", id, seq);
-#endif
- else if (*begin != '\0')
-#if LOG
- syslog(level, "%s[%d]: %s", id, seq, begin);
-#else
- fprintf(stderr, "%s[%d]: %s\n", id, seq, begin);
-#endif
-}
- /*
-** HARD_SYSLOG -- call syslog repeatedly until it works
-**
-** Needed on HP-UX, which apparently doesn't guarantee that
-** syslog succeeds during interrupt handlers.
-*/
-
-#ifdef __hpux
-
-# define MAXSYSLOGTRIES 100
-# undef syslog
-# ifdef V4FS
-# define XCNST const
-# define CAST (const char *)
-# else
-# define XCNST
-# define CAST
-# endif
-
-void
-# ifdef __STDC__
-hard_syslog(int pri, XCNST char *msg, ...)
-# else
-hard_syslog(pri, msg, va_alist)
- int pri;
- XCNST char *msg;
- va_dcl
-# endif
-{
- int i;
- char buf[SYSLOG_BUFSIZE];
- VA_LOCAL_DECL;
-
- VA_START(msg);
- vsnprintf(buf, sizeof buf, msg, ap);
- VA_END;
-
- for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, CAST "%s", buf) < 0; )
- continue;
-}
-
-# undef CAST
-#endif
- /*
-** LOCAL_HOSTNAME_LENGTH
-**
-** This is required to get sendmail to compile against BIND 4.9.x
-** on Ultrix.
-*/
-
-#if defined(ultrix) && NAMED_BIND
-
-# include <resolv.h>
-# if __RES >= 19931104 && __RES < 19950621
-
-int
-local_hostname_length(hostname)
- char *hostname;
-{
- int len_host, len_domain;
-
- if (!*_res.defdname)
- res_init();
- len_host = strlen(hostname);
- len_domain = strlen(_res.defdname);
- if (len_host > len_domain &&
- (strcasecmp(hostname + len_host - len_domain,_res.defdname) == 0) &&
- hostname[len_host - len_domain - 1] == '.')
- return len_host - len_domain - 1;
- else
- return 0;
-}
-
-# endif
-#endif
- /*
-** Compile-Time options
-*/
-
-char *CompileOptions[] =
-{
-#if HESIOD
- "HESIOD",
-#endif
-#if HES_GETMAILHOST
- "HES_GETMAILHOST",
-#endif
-#if LDAPMAP
- "LDAPMAP",
-#endif
-#if LOG
- "LOG",
-#endif
-#if MATCHGECOS
- "MATCHGECOS",
-#endif
-#if MIME7TO8
- "MIME7TO8",
-#endif
-#if MIME8TO7
- "MIME8TO7",
-#endif
-#if NAMED_BIND
- "NAMED_BIND",
-#endif
-#if NDBM
- "NDBM",
-#endif
-#if NETINET
- "NETINET",
-#endif
-#if NETINFO
- "NETINFO",
-#endif
-#if NETISO
- "NETISO",
-#endif
-#if NETNS
- "NETNS",
-#endif
-#if NETUNIX
- "NETUNIX",
-#endif
-#if NETX25
- "NETX25",
-#endif
-#if NEWDB
- "NEWDB",
-#endif
-#if NIS
- "NIS",
-#endif
-#if NISPLUS
- "NISPLUS",
-#endif
-#if QUEUE
- "QUEUE",
-#endif
-#if SCANF
- "SCANF",
-#endif
-#if SMTP
- "SMTP",
-#endif
-#if SMTPDEBUG
- "SMTPDEBUG",
-#endif
-#if SUID_ROOT_FILES_OK
- "SUID_ROOT_FILES_OK",
-#endif
-#if TCPWRAPPERS
- "TCPWRAPPERS",
-#endif
-#if USERDB
- "USERDB",
-#endif
-#if XDEBUG
- "XDEBUG",
-#endif
-#if XLA
- "XLA",
-#endif
- NULL
-};
-
-
-/*
-** OS compile options.
-*/
-
-char *OsCompileOptions[] =
-{
-#if BOGUS_O_EXCL
- "BOGUS_O_EXCL",
-#endif
-#if HASFCHMOD
- "HASFCHMOD",
-#endif
-#if HASFLOCK
- "HASFLOCK",
-#endif
-#if HASGETDTABLESIZE
- "HASGETDTABLESIZE",
-#endif
-#if HASGETUSERSHELL
- "HASGETUSERSHELL",
-#endif
-#if HASINITGROUPS
- "HASINITGROUPS",
-#endif
-#if HASLSTAT
- "HASLSTAT",
-#endif
-#if HASSETREUID
- "HASSETREUID",
-#endif
-#if HASSETRLIMIT
- "HASSETRLIMIT",
-#endif
-#if HASSETSID
- "HASSETSID",
-#endif
-#if HASSETUSERCONTEXT
- "HASSETUSERCONTEXT",
-#endif
-#if HASSETVBUF
- "HASSETVBUF",
-#endif
-#if HASSNPRINTF
- "HASSNPRINTF",
-#endif
-#if HAS_ST_GEN
- "HAS_ST_GEN",
-#endif
-#if HASSTRERROR
- "HASSTRERROR",
-#endif
-#if HASULIMIT
- "HASULIMIT",
-#endif
-#if HASUNAME
- "HASUNAME",
-#endif
-#if HASUNSETENV
- "HASUNSETENV",
-#endif
-#if HASWAITPID
- "HASWAITPID",
-#endif
-#if IDENTPROTO
- "IDENTPROTO",
-#endif
-#if IP_SRCROUTE
- "IP_SRCROUTE",
-#endif
-#if O_EXLOCK && HASFLOCK && !BOGUS_O_EXCL
- "LOCK_ON_OPEN",
-#endif
-#if NEEDFSYNC
- "NEEDFSYNC",
-#endif
-#if NOFTRUNCATE
- "NOFTRUNCATE",
-#endif
-#if RLIMIT_NEEDS_SYS_TIME_H
- "RLIMIT_NEEDS_SYS_TIME_H",
-#endif
-#if SAFENFSPATHCONF
- "SAFENFSPATHCONF",
-#endif
-#if SECUREWARE
- "SECUREWARE",
-#endif
-#if SHARE_V1
- "SHARE_V1",
-#endif
-#if SIOCGIFCONF_IS_BROKEN
- "SIOCGIFCONF_IS_BROKEN",
-#endif
-#if SIOCGIFNUM_IS_BROKEN
- "SIOCGIFNUM_IS_BROKEN",
-#endif
-#if SYS5SETPGRP
- "SYS5SETPGRP",
-#endif
-#if SYSTEM5
- "SYSTEM5",
-#endif
-#if USE_SA_SIGACTION
- "USE_SA_SIGACTION",
-#endif
-#if USE_SIGLONGJMP
- "USE_SIGLONGJMP",
-#endif
-#if USESETEUID
- "USESETEUID",
-#endif
- NULL
-};
OpenPOWER on IntegriCloud