+/*
+ * Copyright (c) 1983 Eric P. Allman
+ * Copyright (c) 1988 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 5.28 (Berkeley) 3/12/91";
+#endif /* not lint */
+
+# include <sys/ioctl.h>
+# include <sys/param.h>
+# include <pwd.h>
+# include "sendmail.h"
+# include "pathnames.h"
+
+/*
+** CONF.C -- Sendmail Configuration Tables.
+**
+** Defines the configuration of this installation.
+**
+** Compilation Flags:
+** VMUNIX -- running on a Berkeley UNIX system.
+**
+** 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,
+ "full-name", H_ACHECK,
+ "return-receipt-to", H_FROM,
+ "errors-to", H_FROM,
+ /* destination fields */
+ "to", H_RCPT,
+ "resent-to", H_RCPT|H_RESENT,
+ "cc", H_RCPT,
+ "resent-cc", H_RCPT|H_RESENT,
+ "bcc", H_RCPT|H_ACHECK,
+ "resent-bcc", H_RCPT|H_ACHECK|H_RESENT,
+ /* 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,
+ "via", H_TRACE|H_FORCE,
+ "mail-from", H_TRACE|H_FORCE,
+
+ NULL, 0,
+};
+
+
+/*
+** ARPANET error message numbers.
+*/
+
+char Arpa_Info[] = "050"; /* arbitrary info */
+char Arpa_TSyserr[] = "451"; /* some (transient) system error */
+char Arpa_PSyserr[] = "554"; /* some (permanent) system error */
+char Arpa_Usrerr[] = "554"; /* some (fatal) user error */
+
+
+
+/*
+** Location of system files/databases/etc.
+*/
+
+char *ConfFile = _PATH_SENDMAILCF; /* runtime configuration */
+char *FreezeFile = _PATH_SENDMAILFC; /* frozen version of above */
+
+
+
+/*
+** Miscellaneous stuff.
+*/
+
+int DtableSize = 50; /* max open files; reset in 4.2bsd */
+extern int la; /* load average */
+\f/*
+** SETDEFAULTS -- set default values
+**
+** Because of the way freezing is done, these must be initialized
+** using direct code.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Initializes a bunch of global variables to their
+** default values.
+*/
+
+setdefaults()
+{
+ QueueLA = 8;
+ QueueFactor = 10000;
+ RefuseLA = 12;
+ SpaceSub = ' ';
+ WkRecipFact = 1000;
+ WkClassFact = 1800;
+ WkTimeFact = 9000;
+ FileMode = 0644;
+ DefUid = 1;
+ DefGid = 1;
+ CheckpointInterval = 10;
+ setdefuser();
+}
+
+
+/*
+** SETDEFUSER -- set/reset DefUser using DefUid (for initgroups())
+*/
+
+setdefuser()
+{
+ struct passwd *defpwent;
+
+ if (DefUser != NULL)
+ free(DefUser);
+ if ((defpwent = getpwuid(DefUid)) != NULL)
+ DefUser = newstr(defpwent->pw_name);
+ else
+ DefUser = newstr("nobody");
+}
+
+
+/*
+** GETRUID -- get real user id (V7)
+*/
+
+getruid()
+{
+ if (OpMode == MD_DAEMON)
+ return (RealUid);
+ else
+ return (getuid());
+}
+
+
+/*
+** GETRGID -- get real group id (V7).
+*/
+
+getrgid()
+{
+ if (OpMode == MD_DAEMON)
+ return (RealGid);
+ else
+ return (getgid());
+}
+
+/*
+** 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 = getpwuid(getruid());
+ if (pw != NULL)
+ myname = newstr(pw->pw_name);
+ }
+ else
+ {
+
+ myname = newstr(myname);
+ if ((pw = getpwnam(myname)) == NULL ||
+ getuid() != pw->pw_uid)
+ {
+ pw = getpwuid(getuid());
+ if (pw != NULL)
+ myname = newstr(pw->pw_name);
+ }
+ }
+ if (myname == NULL || myname[0] == '\0')
+ {
+ syserr("Who are you?");
+ myname = "postmaster";
+ }
+ }
+
+ return (myname);
+}
+\f/*
+** 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
+*/
+
+# include <sys/stat.h>
+
+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);
+}
+\f/*
+** 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 FALSE should
+** be returned.
+**
+** 'NoReturn' can be set to suppress the return-to-sender
+** function; this should be done on huge messages.
+**
+** Parameters:
+** to -- the person being sent to.
+**
+** Returns:
+** TRUE -- ok to send.
+** FALSE -- not ok.
+**
+** Side Effects:
+** none (unless you include the usrerr stuff)
+*/
+
+bool
+checkcompat(to)
+ register ADDRESS *to;
+{
+# ifdef lint
+ if (to == NULL)
+ to++;
+# endif lint
+# ifdef EXAMPLE_CODE
+ /* this code is intended as an example only */
+ register STAB *s;
+
+ s = stab("arpa", ST_MAILER, ST_FIND);
+ if (s != NULL && CurEnv->e_from.q_mailer != LocalMailer &&
+ to->q_mailer == s->s_mailer)
+ {
+ usrerr("No ARPA mail through this machine: see your system administration");
+ /* NoReturn = TRUE; to supress return copy */
+ return (FALSE);
+ }
+# endif EXAMPLE_CODE
+ return (TRUE);
+}
+\f/*
+** HOLDSIGS -- arrange to hold all signals
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Arranges that signals are held.
+*/
+
+holdsigs()
+{
+}
+\f/*
+** RLSESIGS -- arrange to release all signals
+**
+** This undoes the effect of holdsigs.
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Arranges that signals are released.
+*/
+
+rlsesigs()
+{
+}
+\f/*
+** 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.
+*/
+
+#ifndef sun
+
+getla()
+{
+ double avenrun[3];
+
+#ifdef notyet
+ if (getloadavg(avenrun, sizeof(avenrun) / sizeof(avenrun[0])) < 0)
+ return (0);
+ return ((int) (avenrun[0] + 0.5));
+#else
+ return (1);
+#endif
+}
+
+#else /* sun */
+
+#include <nlist.h>
+
+struct nlist Nl[] =
+{
+ { "_avenrun" },
+#define X_AVENRUN 0
+ { 0 },
+};
+
+
+extern int la;
+
+getla()
+{
+ static int kmem = -1;
+ long avenrun[3];
+ extern off_t lseek();
+
+ if (kmem < 0)
+ {
+ kmem = open("/dev/kmem", 0, 0);
+ if (kmem < 0)
+ return (-1);
+ (void) ioctl(kmem, (int) FIOCLEX, (char *) 0);
+ nlist("/vmunix", Nl);
+ if (Nl[0].n_type == 0)
+ return (-1);
+ }
+ if (lseek(kmem, (off_t) Nl[X_AVENRUN].n_value, 0) == -1 ||
+ read(kmem, (char *) avenrun, sizeof(avenrun)) < sizeof(avenrun))
+ {
+ /* thank you Ian */
+ return (-1);
+ }
+ return ((int) (avenrun[0] + FSCALE/2) >> FSHIFT);
+}
+
+#endif /* sun */
+\f/*
+** 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.
+**
+** 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.
+*/
+
+bool
+shouldqueue(pri)
+ long pri;
+{
+ if (la < QueueLA)
+ return (FALSE);
+ return (pri > (QueueFactor / (la - QueueLA + 1)));
+}
+\f/*
+** 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.
+*/
+
+/*VARARGS1*/
+setproctitle(fmt, a, b, c)
+ char *fmt;
+{
+# ifdef SETPROCTITLE
+ register char *p;
+ register int i;
+ extern char **Argv;
+ extern char *LastArgv;
+ char buf[MAXLINE];
+
+ (void) sprintf(buf, fmt, a, b, c);
+
+ /* make ps print "(sendmail)" */
+ p = Argv[0];
+ *p++ = '-';
+
+ i = strlen(buf);
+ if (i > LastArgv - p - 2)
+ {
+ i = LastArgv - p - 2;
+ buf[i] = '\0';
+ }
+ (void) strcpy(p, buf);
+ p += i;
+ while (p < LastArgv)
+ *p++ = ' ';
+# endif SETPROCTITLE
+}
+\f/*
+** REAPCHILD -- pick up the body of my child, lest it become a zombie
+**
+** Parameters:
+** none.
+**
+** Returns:
+** none.
+**
+** Side Effects:
+** Picks up extant zombies.
+*/
+
+# ifdef VMUNIX
+# include <sys/wait.h>
+# endif VMUNIX
+
+void
+reapchild()
+{
+# ifdef WNOHANG
+ union wait status;
+
+ while (wait3((int *)&status, WNOHANG, (struct rusage *) NULL) > 0)
+ continue;
+# else WNOHANG
+ auto int status;
+
+ while (wait((int *)&status) > 0)
+ continue;
+# endif WNOHANG
+}