BSD 4_4_Lite1 release
[unix-history] / usr / src / usr.sbin / sendmail / src / conf.c
index 06b2f27..4ac109a 100644 (file)
@@ -3,17 +3,44 @@
  * 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.41 (Berkeley) %G%";
+static char sccsid[] = "@(#)conf.c     8.89 (Berkeley) 4/18/94";
 #endif /* not lint */
 
 # include "sendmail.h"
 # include "pathnames.h"
 # include <sys/ioctl.h>
 # include <sys/param.h>
 #endif /* not lint */
 
 # include "sendmail.h"
 # include "pathnames.h"
 # include <sys/ioctl.h>
 # include <sys/param.h>
+# include <netdb.h>
 # include <pwd.h>
 
 /*
 # include <pwd.h>
 
 /*
@@ -40,7 +67,7 @@ static char sccsid[] = "@(#)conf.c    8.41 (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.
 **
@@ -120,6 +147,7 @@ struct prival PrivacyValues[] =
        "restrictmailq",        PRIV_RESTRICTMAILQ,
        "restrictqrun",         PRIV_RESTRICTQRUN,
        "authwarnings",         PRIV_AUTHWARNINGS,
        "restrictmailq",        PRIV_RESTRICTMAILQ,
        "restrictqrun",         PRIV_RESTRICTQRUN,
        "authwarnings",         PRIV_AUTHWARNINGS,
+       "noreceipts",           PRIV_NORECEIPTS,
        "goaway",               PRIV_GOAWAY,
        NULL,                   0,
 };
        "goaway",               PRIV_GOAWAY,
        NULL,                   0,
 };
@@ -571,7 +599,9 @@ rlsesigs()
 # include      <compat.h>
 #endif
 
 # include      <compat.h>
 #endif
 
-init_md()
+init_md(argc, argv)
+       int argc;
+       char **argv;
 {
 #ifdef _AUX_SOURCE
        setcompat(getcompat() | COMPAT_BSDPROT);
 {
 #ifdef _AUX_SOURCE
        setcompat(getcompat() | COMPAT_BSDPROT);
@@ -599,6 +629,7 @@ init_md()
 #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_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 */
 
 /* do guesses based on general OS type */
 #ifndef LA_TYPE
 
 /* do guesses based on general OS type */
 #ifndef LA_TYPE
@@ -638,17 +669,17 @@ struct    nlist Nl[] =
 #  define FSHIFT       5
 # endif
 
 #  define FSHIFT       5
 # endif
 
-# if defined(__alpha)
+# if defined(__alpha) || defined(IRIX)
 #  define FSHIFT       10
 # endif
 #  define FSHIFT       10
 # endif
+#endif
 
 
-# if (LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)
-#  define FSHIFT       8
-# endif
+#ifndef FSHIFT
+# define FSHIFT                8
 #endif
 
 #endif
 
-#if ((LA_TYPE == LA_INT) || (LA_TYPE == LA_SHORT)) && !defined(FSCALE)
-#  define FSCALE       (1 << FSHIFT)
+#ifndef FSCALE
+# define FSCALE                (1 << FSHIFT)
 #endif
 
 getla()
 #endif
 
 getla()
@@ -691,6 +722,9 @@ getla()
                                        _PATH_UNIX, LA_AVENRUN);
                        return (-1);
                }
                                        _PATH_UNIX, LA_AVENRUN);
                        return (-1);
                }
+#ifdef IRIX
+               Nl[X_AVENRUN].n_value &= 0x7fffffff;
+#endif
        }
        if (tTd(3, 20))
                printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value);
        }
        if (tTd(3, 20))
                printf("getla: symbol address = %#x\n", Nl[X_AVENRUN].n_value);
@@ -766,10 +800,14 @@ getla()
 #if LA_TYPE == LA_MACH
 
 /*
 #if LA_TYPE == LA_MACH
 
 /*
-**  This has been tested on NeXT release 2.1.
+**  This has been tested on NEXTSTEP release 2.1/3.X.
 */
 
 */
 
-#include <mach.h>
+#if defined(NX_CURRENT_COMPILER_RELEASE) && NX_CURRENT_COMPILER_RELEASE > NX_COMPILER_RELEASE_3_0
+# include <mach/mach.h>
+#else
+# include <mach.h>
+#endif
 
 getla()
 {
 
 getla()
 {
@@ -793,6 +831,52 @@ getla()
 }
 
 
 }
 
 
+#else
+#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));
+}
+
 #else
 
 getla()
 #else
 
 getla()
@@ -805,6 +889,54 @@ getla()
 #endif
 #endif
 #endif
 #endif
 #endif
 #endif
+#endif
+
+
+/*
+ * 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 */
+#ifndef lint
+static char  rcsid[] = "@(#)$Id: getloadavg.c,v 1.16 1991/06/21 12:51:15 paul Exp $";
+#endif /* !lint */
+
+#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 */
 \f/*
 **  SHOULDQUEUE -- should this message be queued or sent?
 **
 \f/*
 **  SHOULDQUEUE -- should this message be queued or sent?
 **
@@ -864,10 +996,8 @@ refuseconnections()
 **  SETPROCTITLE -- set process title for ps
 **
 **     Parameters:
 **  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.
@@ -878,6 +1008,9 @@ refuseconnections()
 */
 
 #ifdef SETPROCTITLE
 */
 
 #ifdef SETPROCTITLE
+# ifdef HASSETPROCTITLE
+   *** ERROR ***  Cannot have both SETPROCTITLE and HASSETPROCTITLE defined
+# endif
 # ifdef __hpux
 #  include <sys/pstat.h>
 # endif
 # ifdef __hpux
 #  include <sys/pstat.h>
 # endif
@@ -886,6 +1019,7 @@ refuseconnections()
 #  include <sys/exec.h>
 #  ifdef __bsdi__
 #   undef PS_STRINGS   /* BSDI 1.0 doesn't do PS_STRINGS as we expect */
 #  include <sys/exec.h>
 #  ifdef __bsdi__
 #   undef PS_STRINGS   /* BSDI 1.0 doesn't do PS_STRINGS as we expect */
+#   define PROCTITLEPAD        '\0'
 #  endif
 #  ifdef PS_STRINGS
 #   define SETPROC_STATIC static
 #  endif
 #  ifdef PS_STRINGS
 #   define SETPROC_STATIC static
@@ -896,7 +1030,11 @@ refuseconnections()
 # endif
 #endif
 
 # endif
 #endif
 
-char   ProcTitleBuf[MAXLINE];
+#ifndef PROCTITLEPAD
+# define PROCTITLEPAD  ' '
+#endif
+
+#ifndef HASSETPROCTITLE
 
 /*VARARGS1*/
 #ifdef __STDC__
 
 /*VARARGS1*/
 #ifdef __STDC__
@@ -910,6 +1048,7 @@ setproctitle(fmt, va_alist)
 # ifdef SETPROCTITLE
        register char *p;
        register int i;
 # ifdef SETPROCTITLE
        register char *p;
        register int i;
+       SETPROC_STATIC char buf[MAXLINE];
        VA_LOCAL_DECL
 #  ifdef __hpux
        union pstun pst;
        VA_LOCAL_DECL
 #  ifdef __hpux
        union pstun pst;
@@ -917,39 +1056,42 @@ setproctitle(fmt, va_alist)
        extern char **Argv;
        extern char *LastArgv;
 
        extern char **Argv;
        extern char *LastArgv;
 
-       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);
+
+#  ifdef __hpux
+       pst.pst_command = buf;
+       pstat(PSTAT_SETCMD, pst, i, 0, 0);
+#  else
+#   ifdef PS_STRINGS
+       PS_STRINGS->ps_nargvstr = 1;
+       PS_STRINGS->ps_argvstr = buf;
+#   else
        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 = &Argv[0][i];
        while (p < LastArgv)
-               *p++ = ' ';
+               *p++ = PROCTITLEPAD;
 #   endif
 #  endif
 # endif /* SETPROCTITLE */
 }
 #   endif
 #  endif
 # endif /* SETPROCTITLE */
 }
+
+#endif
 \f/*
 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
 **
 \f/*
 **  REAPCHILD -- pick up the body of my child, lest it become a zombie
 **
@@ -966,6 +1108,7 @@ setproctitle(fmt, va_alist)
 void
 reapchild()
 {
 void
 reapchild()
 {
+       int olderrno = errno;
 # ifdef HASWAITPID
        auto int status;
        int count;
 # ifdef HASWAITPID
        auto int status;
        int count;
@@ -976,8 +1119,10 @@ reapchild()
        {
                if (count++ > 1000)
                {
        {
                if (count++ > 1000)
                {
+#ifdef LOG
                        syslog(LOG_ALERT, "reapchild: waitpid loop: pid=%d, status=%x",
                                pid, status);
                        syslog(LOG_ALERT, "reapchild: waitpid loop: pid=%d, status=%x",
                                pid, status);
+#endif
                        break;
                }
        }
                        break;
                }
        }
@@ -997,6 +1142,7 @@ reapchild()
 # ifdef SYS5SIGNALS
        (void) setsignal(SIGCHLD, reapchild);
 # endif
 # ifdef SYS5SIGNALS
        (void) setsignal(SIGCHLD, reapchild);
 # endif
+       errno = olderrno;
 }
 \f/*
 **  UNSETENV -- remove a variable from the environment
 }
 \f/*
 **  UNSETENV -- remove a variable from the environment
@@ -1168,7 +1314,7 @@ setsid __P ((void))
 #ifdef TIOCNOTTY
        int fd;
 
 #ifdef TIOCNOTTY
        int fd;
 
-       fd = open("/dev/tty", 2);
+       fd = open("/dev/tty", O_RDWR, 0);
        if (fd >= 0)
        {
                (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
        if (fd >= 0)
        {
                (void) ioctl(fd, (int) TIOCNOTTY, (char *) 0);
@@ -1182,6 +1328,24 @@ setsid __P ((void))
 # endif
 }
 
 # endif
 }
 
+#endif
+\f/*
+**  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
 \f/*
 **  DGUX_INET_ADDR -- inet_addr for DG/UX
 #endif
 \f/*
 **  DGUX_INET_ADDR -- inet_addr for DG/UX
@@ -1232,9 +1396,13 @@ static char sccsid[] = "@(#)getopt.c     4.3 (Berkeley) 3/9/86";
 /*
  * get option letter from argument vector
  */
 /*
  * get option letter from argument vector
  */
-int    opterr = 1,             /* if error message should be printed */
-       optind = 1,             /* index into parent argv vector */
-       optopt;                 /* character checked for validity */
+#ifdef _CONVEX_SOURCE
+extern int     optind, opterr;
+#else
+int    opterr = 1;             /* if error message should be printed */
+int    optind = 1;             /* index into parent argv vector */
+#endif
+int    optopt;                 /* character checked for validity */
 char   *optarg;                /* argument associated with option */
 
 #define BADCH  (int)'?'
 char   *optarg;                /* argument associated with option */
 
 #define BADCH  (int)'?'
@@ -1243,9 +1411,9 @@ char      *optarg;                /* argument associated with option */
                fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
 
 getopt(nargc,nargv,ostr)
                fputc(optopt,stderr);fputc('\n',stderr);return(BADCH);}
 
 getopt(nargc,nargv,ostr)
-int    nargc;
-char   **nargv,
-       *ostr;
+       int             nargc;
+       char *const     *nargv;
+       const char      *ostr;
 {
        static char     *place = EMSG;  /* option letter processing */
        static char     atend = 0;
 {
        static char     *place = EMSG;  /* option letter processing */
        static char     atend = 0;
@@ -1330,6 +1498,99 @@ vsprintf(s, fmt, ap)
 
 #endif
 \f/*
 
 #endif
 \f/*
+**  USERSHELLOK -- tell if a user's shell is ok for unrestricted use
+**
+**     Parameters:
+**             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
+
+char   *DefaultUserShells[] =
+{
+       "/bin/sh",
+       "/usr/bin/sh",
+       "/bin/csh",
+       "/usr/bin/csh",
+#ifdef __hpux
+       "/bin/rsh",
+       "/bin/ksh",
+       "/bin/rksh",
+       "/bin/pam",
+       "/usr/bin/keysh",
+       "/bin/posix/sh",
+#endif
+       NULL
+};
+
+#endif
+
+#define WILDCARD_SHELL "/SENDMAIL/ANY/SHELL/"
+
+bool
+usershellok(shell)
+       char *shell;
+{
+#if HASGETUSERSHELL
+       register char *p;
+       extern char *getusershell();
+
+       setusershell();
+       while ((p = getusershell()) != NULL)
+               if (strcmp(p, shell) == 0 || strcmp(p, WILDCARD_SHELL) == 0)
+                       break;
+       endusershell();
+       return p != NULL;
+#else
+       register FILE *shellf;
+       char buf[MAXLINE];
+
+       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
+}
+\f/*
 **  FREESPACE -- see how much free space is on the queue filesystem
 **
 **     Only implemented if you have statfs.
 **  FREESPACE -- see how much free space is on the queue filesystem
 **
 **     Only implemented if you have statfs.
@@ -1347,24 +1608,33 @@ vsprintf(s, fmt, ap)
 **             Puts the filesystem block size into bsize.
 */
 
 **             Puts the filesystem block size into bsize.
 */
 
-#ifdef HASSTATFS
-# undef HASUSTAT
+/* 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
 
 #endif
 
-#if defined(HASUSTAT)
+#if SFS_TYPE == SFS_USTAT
 # include <ustat.h>
 #endif
 # include <ustat.h>
 #endif
-
-#ifdef HASSTATFS
-# if defined(IRIX) || defined(apollo) || defined(_SCO_unix_) || defined(UMAXV) || defined(DGUX)
-#  include <sys/statfs.h>
-# else
-#  if (defined(sun) && !defined(BSD)) || defined(__hpux) || defined(_CONVEX_SOURCE) || defined(NeXT) || defined(_AUX_SOURCE)
-#   include <sys/vfs.h>
-#  else
-#   include <sys/mount.h>
-#  endif
-# 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
 #endif
 
 long
@@ -1372,8 +1642,8 @@ freespace(dir, bsize)
        char *dir;
        long *bsize;
 {
        char *dir;
        long *bsize;
 {
-#if defined(HASSTATFS) || defined(HASUSTAT)
-# if defined(HASUSTAT)
+#if SFS_TYPE != SFS_NONE
+# if SFS_TYPE == SFS_USTAT
        struct ustat fs;
        struct stat statbuf;
 #  define FSBLOCKSIZE  DEV_BSIZE
        struct ustat fs;
        struct stat statbuf;
 #  define FSBLOCKSIZE  DEV_BSIZE
@@ -1384,19 +1654,24 @@ freespace(dir, bsize)
 #   define f_bavail    fd_bfreen
 #   define FSBLOCKSIZE fs.fd_bsize
 #  else
 #   define f_bavail    fd_bfreen
 #   define FSBLOCKSIZE fs.fd_bsize
 #  else
+#   if SFS_TYPE == SFS_STATVFS
+       struct statvfs fs;
+#    define FSBLOCKSIZE        fs.f_bsize
+#   else
        struct statfs fs;
        struct statfs fs;
-#   define FSBLOCKSIZE fs.f_bsize
-#   if defined(_SCO_unix_) || defined(IRIX)
-#    define f_bavail f_bfree
+#    define FSBLOCKSIZE        fs.f_bsize
+#    if defined(_SCO_unix_) || defined(IRIX) || defined(apollo)
+#     define f_bavail f_bfree
+#    endif
 #   endif
 #  endif
 # endif
        extern int errno;
 
 #   endif
 #  endif
 # endif
        extern int errno;
 
-# if defined(HASUSTAT)
+# if SFS_TYPE == SFS_USTAT
        if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
 # else
        if (stat(dir, &statbuf) == 0 && ustat(statbuf.st_dev, &fs) == 0)
 # else
-#  if defined(IRIX) || defined(apollo) || defined(UMAXV) || defined(DGUX)
+#  if SFS_TYPE == SFS_4ARGS
        if (statfs(dir, &fs, sizeof fs, 0) == 0)
 #  else
 #   if defined(ultrix)
        if (statfs(dir, &fs, sizeof fs, 0) == 0)
 #  else
 #   if defined(ultrix)
@@ -1561,6 +1836,9 @@ transienterror(err)
 #ifdef EADDRNOTAVAIL
          case EADDRNOTAVAIL:           /* Can't assign requested address */
 #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
 #if defined(ENOSR) && (!defined(ENOBUFS) || (ENOBUFS != ENOSR))
          case ENOSR:                   /* Out of streams resources */
 #endif
@@ -1593,7 +1871,7 @@ lockfile(fd, filename, ext, type)
        char *ext;
        int type;
 {
        char *ext;
        int type;
 {
-# ifndef HASFLOCK
+# if !HASFLOCK
        int action;
        struct flock lfd;
 
        int action;
        struct flock lfd;
 
@@ -1690,6 +1968,65 @@ lockfile(fd, filename, ext, type)
        return FALSE;
 }
 \f/*
        return FALSE;
 }
 \f/*
+**  CHOWNSAFE -- tell if chown is "safe" (executable only by root)
+**
+**     Parameters:
+**             fd -- the file descriptor to check.
+**
+**     Returns:
+**             TRUE -- if only root can chown the file to an arbitrary
+**                     user.
+**             FALSE -- if an arbitrary user can give away a file.
+*/
+
+bool
+chownsafe(fd)
+       int fd;
+{
+#ifdef __hpux
+       char *s;
+       int tfd;
+       uid_t o_uid, o_euid;
+       gid_t o_gid, o_egid;
+       bool rval;
+       struct stat stbuf;
+
+       o_uid = getuid();
+       o_euid = geteuid();
+       o_gid = getgid();
+       o_egid = getegid();
+       fstat(fd, &stbuf);
+       setresuid(stbuf.st_uid, stbuf.st_uid, -1);
+       setresgid(stbuf.st_gid, stbuf.st_gid, -1);
+       s = tmpnam(NULL);
+       tfd = open(s, O_RDONLY|O_CREAT, 0600);
+       rval = fchown(tfd, DefUid, DefGid) != 0;
+       close(tfd);
+       unlink(s);
+       setreuid(o_uid, o_euid);
+       setresgid(o_gid, o_egid, -1);
+       return rval;
+#else
+# ifdef _POSIX_CHOWN_RESTRICTED
+#  if _POSIX_CHOWN_RESTRICTED == -1
+       return FALSE;
+#  else
+       return TRUE;
+#  endif
+# else
+#  ifdef _PC_CHOWN_RESTRICTED
+       return fpathconf(fd, _PC_CHOWN_RESTRICTED) > 0;
+#  else
+#   ifdef BSD
+       return TRUE;
+#   else
+       return FALSE;
+#   endif
+#  endif
+# endif
+#endif
+}
+\f/*
 **  GETCFNAME -- return the name of the .cf file.
 **
 **     Some systems (e.g., NeXT) determine this dynamically.
 **  GETCFNAME -- return the name of the .cf file.
 **
 **     Some systems (e.g., NeXT) determine this dynamically.
@@ -1700,6 +2037,16 @@ getcfname()
 {
        if (ConfFile != NULL)
                return ConfFile;
 {
        if (ConfFile != NULL)
                return ConfFile;
+#ifdef NETINFO
+       {
+               extern char *ni_propval();
+               char *cflocation;
+
+               cflocation = ni_propval("/locations/sendmail", "sendmail.cf");
+               if (cflocation != NULL)
+                       return cflocation;
+       }
+#endif
        return _PATH_SENDMAILCF;
 }
 \f/*
        return _PATH_SENDMAILCF;
 }
 \f/*
@@ -1711,11 +2058,320 @@ getcfname()
 **     Returns:
 **             TRUE -- if ok.
 **             FALSE -- if vendor code could not be processed.
 **     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;
 {
 */
 
 bool
 setvendor(vendor)
        char *vendor;
 {
-       return (strcasecmp(vendor, "Berkeley") == 0);
+       if (strcasecmp(vendor, "Berkeley") == 0)
+               return TRUE;
+
+       /* add vendor extensions here */
+
+       return FALSE;
+}
+\f/*
+**  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
+\f/*
+**  SOLARIS_GETHOSTBY{NAME,ADDR} -- compatibility routines for gethostbyXXX
+**
+**     Solaris versions prior through 2.3 don't properly deliver a
+**     canonical h_name field.  This tries to work around it.
+*/
+
+#ifdef SOLARIS
+
+struct hostent *
+solaris_gethostbyname(name)
+       const char *name;
+{
+# ifdef SOLARIS_2_3
+       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);
+# else
+       extern struct hostent *__switch_gethostbyname();
+
+       return __switch_gethostbyname(name);
+# endif
+}
+
+struct hostent *
+solaris_gethostbyaddr(addr, len, type)
+       const char *addr;
+       int len;
+       int type;
+{
+# ifdef SOLARIS_2_3
+       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
+}
+
+#endif
+\f/*
+**  NI_PROPVAL -- netinfo property value lookup routine
+**
+**     Parameters:
+**             directory -- the Netinfo directory name.
+**             propname -- the Netinfo property name.
+**
+**     Returns:
+**             NULL -- if:
+**                     1. the directory is not found
+**                     2. the property name is not found
+**                     3. the property contains multiple values
+**                     4. some error occured
+**             else -- the location of the config file.
+**
+**     Notes:
+**             Caller should free the return value of ni_proval
+*/
+
+#ifdef NETINFO
+
+# include <netinfo/ni.h>
+
+# define LOCAL_NETINFO_DOMAIN    "."
+# define PARENT_NETINFO_DOMAIN   ".."
+# define MAX_NI_LEVELS           256
+
+char *
+ni_propval(directory, propname)
+       char *directory;
+       char *propname;
+{
+       char *propval = NULL;
+       int i;
+       void *ni = NULL;
+       void *lastni = NULL;
+       ni_status nis;
+       ni_id nid;
+       ni_namelist ninl;
+
+       /*
+       **  If the passed directory and property name are found
+       **  in one of netinfo domains we need to search (starting
+       **  from the local domain moving all the way back to the
+       **  root domain) set propval to the property's value
+       **  and return it.
+       */
+
+       for (i = 0; i < MAX_NI_LEVELS; ++i)
+       {
+               if (i == 0)
+               {
+                       nis = ni_open(NULL, LOCAL_NETINFO_DOMAIN, &ni);
+               }
+               else
+               {
+                       if (lastni != NULL)
+                               ni_free(lastni);
+                       lastni = ni;
+                       nis = ni_open(lastni, PARENT_NETINFO_DOMAIN, &ni);
+               }
+
+               /*
+               **  Don't bother if we didn't get a handle on a
+               **  proper domain.  This is not necessarily an error.
+               **  We would get a positive ni_status if, for instance
+               **  we never found the directory or property and tried
+               **  to open the parent of the root domain!
+               */
+
+               if (nis != 0)
+                       break;
+
+               /*
+               **  Find the path to the server information.
+               */
+
+               if (ni_pathsearch(ni, &nid, directory) != 0)
+                       continue;
+
+               /*
+               **  Find "host" information.
+               */
+
+               if (ni_lookupprop(ni, &nid, propname, &ninl) != 0)
+                       continue;
+
+               /*
+               **  If there's only one name in
+               **  the list, assume we've got
+               **  what we want.
+               */
+
+               if (ninl.ni_namelist_len == 1)
+               {
+                       propval = ni_name_dup(ninl.ni_namelist_val[0]);
+                       break;
+               }
+       }
+
+       /*
+       **  Clean up.
+       */
+
+       if (ni != NULL)
+               ni_free(ni);
+       if (lastni != NULL && ni != lastni)
+               ni_free(lastni);
+
+       return propval;
+}
+
+#endif /* NETINFO */
+\f/*
+**  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 __STDC__
+hard_syslog(int pri, char *msg, ...)
+# else
+hard_syslog(pri, msg, va_alist)
+       int pri;
+       char *msg;
+       va_dcl
+# endif
+{
+       int i;
+       char buf[SYSLOG_BUFSIZE * 2];
+       VA_LOCAL_DECL;
+
+       VA_START(msg);
+       vsprintf(buf, msg, ap);
+       VA_END;
+
+       for (i = MAXSYSLOGTRIES; --i >= 0 && syslog(pri, "%s", buf) < 0; )
+               continue;
+}
+
+#endif