BSD 4_4_Lite2 release
[unix-history] / usr / src / usr.sbin / sendmail / src / conf.c
index 959918e..8467caa 100644 (file)
@@ -3,11 +3,37 @@
  * Copyright (c) 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
  * Copyright (c) 1988, 1993
  *     The Regents of the University of California.  All rights reserved.
  *
- * %sccs.include.redist.c%
+ * 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
  */
 
 #ifndef lint
-static char sccsid[] = "@(#)conf.c     8.174 (Berkeley) %G%";
+static char sccsid[] = "@(#)conf.c     8.203 (Berkeley) 6/20/95";
 #endif /* not lint */
 
 # include "sendmail.h"
 #endif /* not lint */
 
 # include "sendmail.h"
@@ -39,7 +65,7 @@ static char sccsid[] = "@(#)conf.c    8.174 (Berkeley) %G%";
 
 
 
 
 
 
-\f/*
+/*
 **  Header info table
 **     Final (null) entry contains the flags used for any other field.
 **
 **  Header info table
 **     Final (null) entry contains the flags used for any other field.
 **
@@ -262,10 +288,10 @@ setupmailers()
        char buf[100];
        extern void makemailer();
 
        char buf[100];
        extern void makemailer();
 
-       strcpy(buf, "prog, P=/bin/sh, F=lsoD, T=X-Unix, A=sh -c $u");
+       strcpy(buf, "prog, P=/bin/sh, F=lsoD, T=DNS/RFC822/X-Unix, A=sh -c \201u");
        makemailer(buf);
 
        makemailer(buf);
 
-       strcpy(buf, "*file*, P=[FILE], F=lsDFMPEou, T=X-Unix, A=FILE");
+       strcpy(buf, "*file*, P=[FILE], F=lsDFMPEou, T=DNS/RFC822/X-Unix, A=FILE");
        makemailer(buf);
 
        strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE");
        makemailer(buf);
 
        strcpy(buf, "*include*, P=/dev/null, F=su, A=INCLUDE");
@@ -332,7 +358,7 @@ setupmaps()
                hes_map_lookup, null_map_store);
 #endif
 
                hes_map_lookup, null_map_store);
 #endif
 
-#ifdef NETINFO
+#if NETINFO
        MAPDEF("netinfo", NULL, MCF_ALIASOK,
                map_parseargs, ni_map_open, null_map_close,
                ni_map_lookup, null_map_store);
        MAPDEF("netinfo", NULL, MCF_ALIASOK,
                map_parseargs, ni_map_open, null_map_close,
                ni_map_lookup, null_map_store);
@@ -377,7 +403,7 @@ setupmaps()
                dequote_init, null_map_open, null_map_close,
                dequote_map, null_map_store);
 
                dequote_init, null_map_open, null_map_close,
                dequote_map, null_map_store);
 
-#ifdef USERDB
+#if USERDB
        /* user database */
        MAPDEF("userdb", ".db", 0,
                map_parseargs, null_map_open, null_map_close,
        /* user database */
        MAPDEF("userdb", ".db", 0,
                map_parseargs, null_map_open, null_map_close,
@@ -442,14 +468,14 @@ inithostmaps()
                    stab("hosts.files", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts");
                    stab("hosts.files", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "hosts.files text -k 0 -v 1 /etc/hosts");
-                       makemapentry(buf);
+                       (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");
                }
 #if NAMED_BIND
                else if (strcmp(maptype[i], "dns") == 0 &&
                    stab("hosts.dns", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "hosts.dns dns A");
-                       makemapentry(buf);
+                       (void) makemapentry(buf);
                }
 #endif
 #ifdef NISPLUS
                }
 #endif
 #ifdef NISPLUS
@@ -457,7 +483,7 @@ inithostmaps()
                    stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir");
                    stab("hosts.nisplus", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "hosts.nisplus nisplus -k name -v address -d hosts.org_dir");
-                       makemapentry(buf);
+                       (void) makemapentry(buf);
                }
 #endif
 #ifdef NIS
                }
 #endif
 #ifdef NIS
@@ -465,7 +491,7 @@ inithostmaps()
                    stab("hosts.nis", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname");
                    stab("hosts.nis", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "hosts.nis nis -d -k 0 -v 1 hosts.byname");
-                       makemapentry(buf);
+                       (void) makemapentry(buf);
                }
 #endif
        }
                }
 #endif
        }
@@ -483,7 +509,7 @@ inithostmaps()
                if (ConfigLevel >= 2)
                        strcat(buf, " -a.");
 #endif
                if (ConfigLevel >= 2)
                        strcat(buf, " -a.");
 #endif
-               makemapentry(buf);
+               (void) makemapentry(buf);
        }
 
        /*
        }
 
        /*
@@ -497,14 +523,14 @@ inithostmaps()
                    stab("aliases.files", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "aliases.files implicit /etc/aliases");
                    stab("aliases.files", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "aliases.files implicit /etc/aliases");
-                       makemapentry(buf);
+                       (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");
                }
 #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");
-                       makemapentry(buf);
+                       (void) makemapentry(buf);
                }
 #endif
 #ifdef NIS
                }
 #endif
 #ifdef NIS
@@ -512,17 +538,23 @@ inithostmaps()
                    stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "aliases.nis nis -d mail.aliases");
                    stab("aliases.nis", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "aliases.nis nis -d mail.aliases");
-                       makemapentry(buf);
+                       (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");
                }
 #endif
        }
        if (stab("aliases", ST_MAP, ST_FIND) == NULL)
        {
                strcpy(buf, "aliases switch aliases");
-               makemapentry(buf);
+               (void) makemapentry(buf);
        }
        }
-       strcpy(buf, "switch:aliases");
-       setalias(buf);
 
 #if 0          /* "user" map class is a better choice */
        /*
 
 #if 0          /* "user" map class is a better choice */
        /*
@@ -536,14 +568,14 @@ inithostmaps()
                    stab("users.files", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd");
                    stab("users.files", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "users.files text -m -z: -k0 -v6 /etc/passwd");
-                       makemapentry(buf);
+                       (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");
                }
 #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");
-                       makemapentry(buf);
+                       (void) makemapentry(buf);
                }
 #endif
 #ifdef NIS
                }
 #endif
 #ifdef NIS
@@ -551,7 +583,7 @@ inithostmaps()
                    stab("users.nis", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "users.nis nis -m -d passwd.byname");
                    stab("users.nis", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "users.nis nis -m -d passwd.byname");
-                       makemapentry(buf);
+                       (void) makemapentry(buf);
                }
 #endif
 #ifdef HESIOD
                }
 #endif
 #ifdef HESIOD
@@ -559,14 +591,14 @@ inithostmaps()
                    stab("users.hesiod", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "users.hesiod hesiod");
                    stab("users.hesiod", ST_MAP, ST_FIND) == NULL)
                {
                        strcpy(buf, "users.hesiod hesiod");
-                       makemapentry(buf);
+                       (void) makemapentry(buf);
                }
 #endif
        }
        if (stab("users", ST_MAP, ST_FIND) == NULL)
        {
                strcpy(buf, "users switch -m passwd");
                }
 #endif
        }
        if (stab("users", ST_MAP, ST_FIND) == NULL)
        {
                strcpy(buf, "users switch -m passwd");
-               makemapentry(buf);
+               (void) makemapentry(buf);
        }
 #endif
 }
        }
 #endif
 }
@@ -591,7 +623,11 @@ inithostmaps()
 # include <nsswitch.h>
 #endif
 
 # include <nsswitch.h>
 #endif
 
-#if defined(ultrix) || defined(__osf__)
+#if defined(ultrix) || (defined(__osf__) && defined(__alpha))
+# define _USE_DEC_SVC_CONF_
+#endif
+
+#ifdef _USE_DEC_SVC_CONF_
 # include <sys/svcinfo.h>
 #endif
 
 # include <sys/svcinfo.h>
 #endif
 
@@ -635,7 +671,7 @@ switch_map_find(service, maptype, mapreturn)
        return svcno;
 #endif
 
        return svcno;
 #endif
 
-#if defined(ultrix) || defined(__osf__)
+#ifdef _USE_DEC_SVC_CONF_
        struct svcinfo *svcinfo;
        int svc;
 
        struct svcinfo *svcinfo;
        int svc;
 
@@ -682,7 +718,7 @@ switch_map_find(service, maptype, mapreturn)
        return svcno;
 #endif
 
        return svcno;
 #endif
 
-#if !defined(SOLARIS) && !defined(ultrix) && !defined(__osf__)
+#if !defined(SOLARIS) && !defined(_USE_DEC_SVC_CONF_)
        /*
        **  Fall-back mechanism.
        */
        /*
        **  Fall-back mechanism.
        */
@@ -719,10 +755,12 @@ switch_map_find(service, maptype, mapreturn)
                                if (p != NULL)
                                        *p++ = '\0';
                        } while (p != NULL);
                                if (p != NULL)
                                        *p++ = '\0';
                        } while (p != NULL);
-                       break;
+                       fclose(fp);
+                       return svcno;
                }
                }
+
+               /* service was not found -- use compiled in default */
                fclose(fp);
                fclose(fp);
-               return svcno;
        }
 #endif
 
        }
 #endif
 
@@ -937,7 +975,7 @@ setsignal(sig, handler)
        int sig;
        sigfunc_t handler;
 {
        int sig;
        sigfunc_t handler;
 {
-#if defined(SYS5SIGNALS) || defined(BSD4_3) || defined(_AUX_SOURCE)
+#if defined(SYS5SIGNALS) || defined(BSD4_3)
        return signal(sig, handler);
 #else
        struct sigaction n, o;
        return signal(sig, handler);
 #else
        struct sigaction n, o;
@@ -953,6 +991,31 @@ setsignal(sig, handler)
 #endif
 }
 \f/*
 #endif
 }
 \f/*
+**  RELEASESIGNAL -- release a held signal
+**
+**     Parameters:
+**             sig -- the signal to release.
+**
+**     Returns:
+**             0 on success.
+**             -1 on failure.
+*/
+
+int
+releasesignal(sig)
+       int sig;
+{
+#ifdef BSD4_3
+       return sigsetmask(sigblock(0) & ~(1 << sig));
+#else
+       sigset_t sset;
+
+       sigemptyset(&sset);
+       sigaddset(&sset, sig);
+       return sigprocmask(SIG_UNBLOCK, &sset, NULL);
+#endif
+}
+\f/*
 **  HOLDSIGS -- arrange to hold all signals
 **
 **     Parameters:
 **  HOLDSIGS -- arrange to hold all signals
 **
 **     Parameters:
@@ -1113,12 +1176,16 @@ init_vendor_macros(e)
 # endif
 #endif
 
 # endif
 #endif
 
+#ifdef _AUX_SOURCE
+struct nlist   Nl[2];
+#else
 struct nlist   Nl[] =
 {
        { LA_AVENRUN },
 struct nlist   Nl[] =
 {
        { LA_AVENRUN },
-#define        X_AVENRUN       0
        { 0 },
 };
        { 0 },
 };
+#endif
+#define        X_AVENRUN       0
 
 getla()
 {
 
 getla()
 {
@@ -1147,6 +1214,10 @@ getla()
                }
                (void) fcntl(kmem, F_SETFD, 1);
 
                }
                (void) fcntl(kmem, F_SETFD, 1);
 
+#ifdef _AUX_SOURCE
+               strcpy(Nl[X_AVENRUN].n_name, LA_AVENRUN);
+#endif
+
 #ifdef _AIX3
                if (knlist(Nl, 1, sizeof Nl[0]) < 0)
 #else
 #ifdef _AIX3
                if (knlist(Nl, 1, sizeof Nl[0]) < 0)
 #else
@@ -1520,30 +1591,45 @@ shouldqueue(pri, ctime)
 **             FALSE if we should accept new work.
 **
 **     Side Effects:
 **             FALSE if we should accept new work.
 **
 **     Side Effects:
-**             none.
+**             Sets process title when it is rejecting connections.
 */
 
 bool
 refuseconnections()
 {
 */
 
 bool
 refuseconnections()
 {
-       extern bool enoughspace();
+       extern bool enoughdiskspace();
+       extern void setproctitle __P((char *, ...));
 
 #ifdef XLA
        if (!xla_smtp_ok())
                return TRUE;
 #endif
 
 
 #ifdef XLA
        if (!xla_smtp_ok())
                return TRUE;
 #endif
 
-       /* this is probably too simplistic */
-       return CurrentLA >= RefuseLA || !enoughspace(MinBlocksFree + 1);
+       if (CurrentLA >= RefuseLA)
+       {
+               setproctitle("rejecting connections: load average: %d",
+                       CurrentLA);
+       }
+       else if (!enoughdiskspace(MinBlocksFree + 1))
+       {
+               setproctitle("rejecting connections: min free: %d",
+                       MinBlocksFree);
+       }
+       else if (MaxChildren > 0 && CurChildren >= MaxChildren)
+       {
+               setproctitle("rejecting connections: maximum children: %d",
+                       CurChildren);
+       }
+       else
+               return FALSE;
+       return TRUE;
 }
 \f/*
 **  SETPROCTITLE -- set process title for ps
 **
 **     Parameters:
 }
 \f/*
 **  SETPROCTITLE -- set process title for ps
 **
 **     Parameters:
-**             fmt -- a printf style format string.  If NULL, the first
-**                     parameter is a literal proctitle previously
-**                     returned by getproctitle.
-**             va_alist -- possible parameters to fmt.
+**             fmt -- a printf style format string.
+**             a, b, c -- possible parameters to fmt.
 **
 **     Returns:
 **             none.
 **
 **     Returns:
 **             none.
@@ -1602,8 +1688,6 @@ typedef unsigned int      *pt_entry_t;
 
 #if SPT_TYPE != SPT_BUILTIN
 
 
 #if SPT_TYPE != SPT_BUILTIN
 
-char   ProcTitleBuf[MAXLINE];
-
 /*VARARGS1*/
 void
 # ifdef __STDC__
 /*VARARGS1*/
 void
 # ifdef __STDC__
@@ -1617,39 +1701,47 @@ setproctitle(fmt, va_alist)
 # if SPT_TYPE != SPT_NONE
        register char *p;
        register int i;
 # if SPT_TYPE != SPT_NONE
        register char *p;
        register int i;
+       SETPROC_STATIC char buf[MAXLINE];
        VA_LOCAL_DECL
 #  if SPT_TYPE == SPT_PSTAT
        union pstun pst;
 #  endif
        VA_LOCAL_DECL
 #  if SPT_TYPE == SPT_PSTAT
        union pstun pst;
 #  endif
+#  if SPT_TYPE == SPT_REUSEARGV
        extern char **Argv;
        extern char *LastArgv;
        extern char **Argv;
        extern char *LastArgv;
+#  endif
 
 
-       VA_START(fmt);
-       if (fmt == NULL)
-       {
-               /* restore old proctitle */
-               (void) strcpy(ProcTitleBuf, va_arg(ap, char *));
-       }
-       else
-       {
-               p = ProcTitleBuf;
+       p = buf;
 
 
-               /* print sendmail: heading for grep */
-               (void) strcpy(p, "sendmail: ");
-               p += strlen(p);
+       /* print sendmail: heading for grep */
+       (void) strcpy(p, "sendmail: ");
+       p += strlen(p);
 
 
-               /* print the argument string */
-               (void) vsprintf(p, fmt, ap);
-       }
+       /* print the argument string */
+       VA_START(fmt);
+       (void) vsprintf(p, fmt, ap);
        VA_END;
 
        VA_END;
 
-       i = strlen(ProcTitleBuf);
+       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_REUSEARGV
        if (i > LastArgv - Argv[0] - 2)
        {
                i = LastArgv - Argv[0] - 2;
        if (i > LastArgv - Argv[0] - 2)
        {
                i = LastArgv - Argv[0] - 2;
-               ProcTitleBuf[i] = '\0';
+               buf[i] = '\0';
        }
        }
-       (void) strcpy(Argv[0], ProcTitleBuf);
+       (void) strcpy(Argv[0], buf);
        p = &Argv[0][i];
        while (p < LastArgv)
                *p++ = SPT_PADCHAR;
        p = &Argv[0][i];
        while (p < LastArgv)
                *p++ = SPT_PADCHAR;
@@ -1693,18 +1785,19 @@ reapchild(sig)
 #endif
                        break;
                }
 #endif
                        break;
                }
+               CurChildren--;
        }
 # else
 # ifdef WNOHANG
        union wait status;
 
        while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
        }
 # else
 # ifdef WNOHANG
        union wait status;
 
        while (wait3(&status, WNOHANG, (struct rusage *) NULL) > 0)
-               continue;
+               CurChildren--;
 # else /* WNOHANG */
        auto int status;
 
        while (wait(&status) > 0)
 # else /* WNOHANG */
        auto int status;
 
        while (wait(&status) > 0)
-               continue;
+               CurChildren--;
 # endif /* WNOHANG */
 # endif
 # ifdef SYS5SIGNALS
 # endif /* WNOHANG */
 # endif
 # ifdef SYS5SIGNALS
@@ -1728,7 +1821,71 @@ reapchild(sig)
 
 #ifdef NEEDPUTENV
 
 
 #ifdef NEEDPUTENV
 
-void
+# 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 = index(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;
 {
 putenv(env)
        char *env;
 {
@@ -1738,15 +1895,16 @@ putenv(env)
 
        p = strchr(env, '=');
        if (p == NULL)
 
        p = strchr(env, '=');
        if (p == NULL)
-               return;
+               return 0;
        l = p - env;
        if (l > sizeof nbuf - 1)
                l = sizeof nbuf - 1;
        bcopy(env, nbuf, l);
        nbuf[l] = '\0';
        l = p - env;
        if (l > sizeof nbuf - 1)
                l = sizeof nbuf - 1;
        bcopy(env, nbuf, l);
        nbuf[l] = '\0';
-       setenv(nbuf, ++p, 1);
+       return setenv(nbuf, ++p, 1);
 }
 
 }
 
+# endif
 #endif
 \f/*
 **  UNSETENV -- remove a variable from the environment
 #endif
 \f/*
 **  UNSETENV -- remove a variable from the environment
@@ -2107,6 +2265,7 @@ vsprintf(s, fmt, ap)
 **  USERSHELLOK -- tell if a user's shell is ok for unrestricted use
 **
 **     Parameters:
 **  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:
 **             shell -- the user's shell from /etc/passwd
 **
 **     Returns:
@@ -2120,6 +2279,11 @@ vsprintf(s, fmt, ap)
 #  define _PATH_SHELLS "/etc/shells"
 # endif
 
 #  define _PATH_SHELLS "/etc/shells"
 # endif
 
+# ifdef _AIX3
+#  include <userconf.h>
+#  include <usersec.h>
+# endif
+
 char   *DefaultUserShells[] =
 {
        "/bin/sh",              /* standard shell */
 char   *DefaultUserShells[] =
 {
        "/bin/sh",              /* standard shell */
@@ -2159,14 +2323,16 @@ char    *DefaultUserShells[] =
 #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
 
 bool
 #define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
 
 bool
-usershellok(shell)
+usershellok(user, shell)
+       char *user;
        char *shell;
 {
 #if HASGETUSERSHELL
        register char *p;
        extern char *getusershell();
 
        char *shell;
 {
 #if HASGETUSERSHELL
        register char *p;
        extern char *getusershell();
 
-       if (shell == NULL || shell[0] == '\0' || ConfigLevel <= 1)
+       if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't') ||
+           ConfigLevel <= 1)
                return TRUE;
 
        setusershell();
                return TRUE;
 
        setusershell();
@@ -2176,12 +2342,41 @@ usershellok(shell)
        endusershell();
        return p != NULL;
 #else
        endusershell();
        return p != NULL;
 #else
+# if USEGETCONFATTR
+       auto char *v;
+# endif
        register FILE *shellf;
        char buf[MAXLINE];
 
        register FILE *shellf;
        char buf[MAXLINE];
 
-       if (shell == NULL || shell[0] == '\0')
+       if (shell == NULL || shell[0] == '\0' || wordinclass(user, 't'))
                return TRUE;
 
                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)
        {
        shellf = fopen(_PATH_SHELLS, "r");
        if (shellf == NULL)
        {
@@ -2220,7 +2415,7 @@ usershellok(shell)
 #endif
 }
 \f/*
 #endif
 }
 \f/*
-**  FREESPACE -- see how much free space is on the queue filesystem
+**  FREEDISKSPACE -- see how much free space is on the queue filesystem
 **
 **     Only implemented if you have statfs.
 **
 **
 **     Only implemented if you have statfs.
 **
@@ -2267,7 +2462,7 @@ usershellok(shell)
 #endif
 
 long
 #endif
 
 long
-freespace(dir, bsize)
+freediskspace(dir, bsize)
        char *dir;
        long *bsize;
 {
        char *dir;
        long *bsize;
 {
@@ -2322,7 +2517,7 @@ freespace(dir, bsize)
        return (-1);
 }
 \f/*
        return (-1);
 }
 \f/*
-**  ENOUGHSPACE -- check to see if there is enough free space on the queue fs
+**  ENOUGHDISKSPACE -- is there enough free space on the queue fs?
 **
 **     Only implemented if you have statfs.
 **
 **
 **     Only implemented if you have statfs.
 **
@@ -2337,7 +2532,7 @@ freespace(dir, bsize)
 */
 
 bool
 */
 
 bool
-enoughspace(msize)
+enoughdiskspace(msize)
        long msize;
 {
        long bfree, bsize;
        long msize;
 {
        long bfree, bsize;
@@ -2345,14 +2540,14 @@ enoughspace(msize)
        if (MinBlocksFree <= 0 && msize <= 0)
        {
                if (tTd(4, 80))
        if (MinBlocksFree <= 0 && msize <= 0)
        {
                if (tTd(4, 80))
-                       printf("enoughspace: no threshold\n");
+                       printf("enoughdiskspace: no threshold\n");
                return TRUE;
        }
 
                return TRUE;
        }
 
-       if ((bfree = freespace(QueueDir, &bsize)) >= 0)
+       if ((bfree = freediskspace(QueueDir, &bsize)) >= 0)
        {
                if (tTd(4, 80))
        {
                if (tTd(4, 80))
-                       printf("enoughspace: bavail=%ld, need=%ld\n",
+                       printf("enoughdiskspace: bavail=%ld, need=%ld\n",
                                bfree, msize);
 
                /* convert msize to block count */
                                bfree, msize);
 
                /* convert msize to block count */
@@ -2375,7 +2570,7 @@ enoughspace(msize)
                }
        }
        else if (tTd(4, 80))
                }
        }
        else if (tTd(4, 80))
-               printf("enoughspace failure: min=%ld, need=%ld: %s\n",
+               printf("enoughdiskspace failure: min=%ld, need=%ld: %s\n",
                        MinBlocksFree, msize, errstring(errno));
        return TRUE;
 }
                        MinBlocksFree, msize, errstring(errno));
        return TRUE;
 }
@@ -2710,12 +2905,10 @@ resetlimits()
 char *
 getcfname()
 {
 char *
 getcfname()
 {
-       int i;
-       static char cbuf[200];
 
        if (ConfFile != NULL)
                return ConfFile;
 
        if (ConfFile != NULL)
                return ConfFile;
-#ifdef NETINFO
+#if NETINFO
        {
                extern char *ni_propval();
                char *cflocation;
        {
                extern char *ni_propval();
                char *cflocation;
@@ -2727,42 +2920,6 @@ getcfname()
        }
 #endif
 
        }
 #endif
 
-#ifdef TRY_VERSIONED_CF_NAME
-       /*
-       **  Try sendmail.8.6.12.cf, then sendmail.8.6.cf, then
-       **  sendmail.8.cf, and finally sendmail.cf.
-       **
-       **      I suppose it should really try a search path here --
-       **      e.g., /etc/sendmail.cf, /etc/mail/sendmail.cf,
-       **      /usr/lib/sendmail.cf, and so forth.
-       */
-
-       strcpy(cbuf, _PATH_SENDMAILCF);
-       i = strlen(cbuf);
-       if (strcmp(&cbuf[i - 3], ".cf") == 0)
-       {
-               char *p;
-               extern char Version[];
-
-               strcpy(&cbuf[i - 2], Version);
-               p = strchr(&cbuf[i - 2], '/');
-               if (p != NULL)
-                       *p = '\0';
-               p = &cbuf[strlen(cbuf)];
-               do
-               {
-                       int fd;
-
-                       strcpy(p, ".cf");
-                       if ((fd = open(cbuf, O_RDONLY, 0)) >= 0)
-                       {
-                               close(fd);
-                               return cbuf;
-                       }
-                       *p = '\0';
-               } while ((p = strrchr(&cbuf[i - 2], '.')) != NULL);
-       }
-#endif
        return _PATH_SENDMAILCF;
 }
 \f/*
        return _PATH_SENDMAILCF;
 }
 \f/*
@@ -2933,6 +3090,43 @@ strtol(nptr, endptr, base)
        return (acc);
 }
 
        return (acc);
 }
 
+#endif
+\f/*
+**  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
 \f/*
 **  SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
 #endif
 \f/*
 **  SM_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
@@ -2943,29 +3137,72 @@ strtol(nptr, endptr, base)
 **     work around these problems.
 */
 
 **     work around these problems.
 */
 
-extern int     h_errno;
-
 struct hostent *
 sm_gethostbyname(name)
        char *name;
 {
 struct hostent *
 sm_gethostbyname(name)
        char *name;
 {
+       struct hostent *h;
 #if defined(SOLARIS) && SOLARIS < 204 || defined(sony_news) && defined(__svr4)
 #if defined(SOLARIS) && SOLARIS < 204 || defined(sony_news) && defined(__svr4)
-       extern int h_errno;
-
 # if SOLARIS == 203
        static struct hostent hp;
        static char buf[1000];
        extern struct hostent *_switch_gethostbyname_r();
 
 # if SOLARIS == 203
        static struct hostent hp;
        static char buf[1000];
        extern struct hostent *_switch_gethostbyname_r();
 
-       return _switch_gethostbyname_r(name, &hp, buf, sizeof(buf), &h_errno);
+       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();
 
 # else
        extern struct hostent *__switch_gethostbyname();
 
-       return __switch_gethostbyname(name);
+       if (tTd(61, 10))
+               printf("__switch_gethostbyname(%s)... ", name);
+       h = __switch_gethostbyname(name);
 # endif
 #else
 # endif
 #else
-       return gethostbyname(name);
+       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) > 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
 #endif
+       if (tTd(61, 10))
+       {
+               if (h == NULL)
+                       printf("failure\n");
+               else
+                       printf("%s\n", h->h_name);
+       }
+       return h;
 }
 
 struct hostent *
 }
 
 struct hostent *
@@ -2975,8 +3212,6 @@ sm_gethostbyaddr(addr, len, type)
        int type;
 {
 #if defined(SOLARIS) && SOLARIS < 204
        int type;
 {
 #if defined(SOLARIS) && SOLARIS < 204
-       extern int h_errno;
-
 # if SOLARIS == 203
        static struct hostent hp;
        static char buf[1000];
 # if SOLARIS == 203
        static struct hostent hp;
        static char buf[1000];
@@ -3005,7 +3240,7 @@ sm_getpwnam(user)
 
 struct passwd *
 sm_getpwuid(uid)
 
 struct passwd *
 sm_getpwuid(uid)
-       uid_t uid;
+       UID_T uid;
 {
        return getpwuid(uid);
 }
 {
        return getpwuid(uid);
 }
@@ -3056,7 +3291,7 @@ load_if_names()
        close(s);
 
        /* scan the list of IP address */
        close(s);
 
        /* scan the list of IP address */
-       if (tTd(0, 4))
+       if (tTd(0, 40))
                printf("scanning for interface specific names, ifc_len=%d\n",
                        ifc.ifc_len);
 
                printf("scanning for interface specific names, ifc_len=%d\n",
                        ifc.ifc_len);
 
@@ -3162,7 +3397,7 @@ load_if_names()
 **             Caller should free the return value of ni_proval
 */
 
 **             Caller should free the return value of ni_proval
 */
 
-#ifdef NETINFO
+#if NETINFO
 
 # include <netinfo/ni.h>
 
 
 # include <netinfo/ni.h>
 
@@ -3315,6 +3550,7 @@ ni_propval(keydir, keyprop, keyval, valprop, sepchar)
 # undef syslog
 
 # ifdef __STDC__
 # undef syslog
 
 # ifdef __STDC__
+void
 hard_syslog(int pri, char *msg, ...)
 # else
 hard_syslog(pri, msg, va_alist)
 hard_syslog(int pri, char *msg, ...)
 # else
 hard_syslog(pri, msg, va_alist)
@@ -3377,7 +3613,7 @@ char      *CompileOptions[] =
 #if HESIOD
        "HESIOD",
 #endif
 #if HESIOD
        "HESIOD",
 #endif
-#if LOG
+#ifdef LOG
        "LOG",
 #endif
 #if MATCHGECOS
        "LOG",
 #endif
 #if MATCHGECOS
@@ -3433,3 +3669,52 @@ char     *CompileOptions[] =
 #endif
        NULL
 };
 #endif
        NULL
 };
+
+
+/*
+**  OS compile options.
+*/
+
+char   *OsCompileOptions[] =
+{
+#if HASFLOCK
+       "HASFLOCK",
+#endif
+#if HASGETUSERSHELL
+       "HASGETUSERSHELL",
+#endif
+#if HASINITGROUPS
+       "HASINITGROUPS",
+#endif
+#if HASLSTAT
+       "HASLSTAT",
+#endif
+#if HASSETREUID
+       "HASSETREUID",
+#endif
+#if HASSETSID
+       "HASSETSID",
+#endif
+#if HASSETVBUF
+       "HASSETVBUF",
+#endif
+#if HASUNAME
+       "HASUNAME",
+#endif
+#if IDENTPROTO
+       "IDENTPROTO",
+#endif
+#if IP_SRCROUTE
+       "IP_SRCROUTE",
+#endif
+#if SYS5SETPGRP
+       "SYS5SETPGRP",
+#endif
+#if SYSTEM5
+       "SYSTEM5",
+#endif
+#if USESETEUID
+       "USESETEUID",
+#endif
+       NULL
+};