📄 conf.c
字号:
* 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[] = "@(#)$OrigId: 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 */
/*
** SM_GETLA -- get the current load average and set macro
**
** Parameters:
** e -- the envelope for the load average macro.
**
** Returns:
** The current load average as an integer.
**
** Side Effects:
** Sets the load average macro ({load_avg}) if
** envelope e is not NULL.
*/
int
sm_getla(e)
ENVELOPE *e;
{
register int la;
la = getla();
if (e != NULL)
{
char labuf[8];
snprintf(labuf, sizeof labuf, "%d", la);
define(macid("{load_avg}", NULL), newstr(labuf), e);
}
return la;
}
/*
** 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.
** ct -- 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.
*/
/* ARGSUSED1 */
bool
shouldqueue(pri, ct)
long pri;
time_t ct;
{
bool rval;
if (tTd(3, 30))
dprintf("shouldqueue: CurrentLA=%d, pri=%ld: ",
CurrentLA, pri);
if (CurrentLA < QueueLA)
{
if (tTd(3, 30))
dprintf("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))
dprintf("TRUE (CurrentLA >= RefuseLA)\n");
return TRUE;
}
#endif /* 0 */
rval = pri > (QueueFactor / (CurrentLA - QueueLA + 1));
if (tTd(3, 30))
dprintf("%s (by calculation)\n", rval ? "TRUE" : "FALSE");
return rval;
}
/*
** REFUSECONNECTIONS -- decide if connections should be refused
**
** Parameters:
** name -- daemon name (for error messages only)
** e -- the current envelope.
** d -- number of daemon
**
** 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(name, e, d)
char *name;
ENVELOPE *e;
int d;
{
time_t now;
static time_t lastconn[MAXDAEMONS];
static int conncnt[MAXDAEMONS];
#ifdef XLA
if (!xla_smtp_ok())
return TRUE;
#endif /* XLA */
now = curtime();
if (now != lastconn[d])
{
lastconn[d] = now;
conncnt[d] = 0;
}
else if (conncnt[d]++ > ConnRateThrottle && ConnRateThrottle > 0)
{
/* sleep to flatten out connection load */
sm_setproctitle(TRUE, e, "deferring connections on daemon %s: %d per second",
name, ConnRateThrottle);
if (LogLevel >= 9)
sm_syslog(LOG_INFO, NOQID,
"deferring connections on daemon %s: %d per second",
name, ConnRateThrottle);
(void) sleep(1);
}
CurrentLA = getla();
if (RefuseLA > 0 && CurrentLA >= RefuseLA)
{
sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: load average: %d",
name, CurrentLA);
if (LogLevel >= 9)
sm_syslog(LOG_INFO, NOQID,
"rejecting connections on daemon %s: load average: %d",
name, CurrentLA);
return TRUE;
}
if (MaxChildren > 0 && CurChildren >= MaxChildren)
{
proc_list_probe();
if (CurChildren >= MaxChildren)
{
sm_setproctitle(TRUE, e, "rejecting connections on daemon %s: %d children, max %d",
name, CurChildren, MaxChildren);
if (LogLevel >= 9)
sm_syslog(LOG_INFO, NOQID,
"rejecting connections on daemon %s: %d children, max %d",
name, 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 /* ! SPT_TYPE */
#if SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN
# if SPT_TYPE == SPT_PSTAT
# include <sys/pstat.h>
# endif /* SPT_TYPE == SPT_PSTAT */
# 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 /* ! PS_STRINGS */
# ifndef NKPDE /* FreeBSD 2.0 */
# define NKPDE 63
typedef unsigned int *pt_entry_t;
# endif /* ! NKPDE */
# endif /* ! PS_STRINGS */
# endif /* SPT_TYPE == SPT_PSSTRINGS */
# if SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV
# define SETPROC_STATIC static
# else /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
# define SETPROC_STATIC
# endif /* SPT_TYPE == SPT_PSSTRINGS || SPT_TYPE == SPT_CHANGEARGV */
# if SPT_TYPE == SPT_SYSMIPS
# include <sys/sysmips.h>
# include <sys/sysnews.h>
# endif /* SPT_TYPE == SPT_SYSMIPS */
# 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 /* PSARGSZ > MAXLINE */
# endif /* SPT_TYPE == SPT_SCO */
# ifndef SPT_PADCHAR
# define SPT_PADCHAR ' '
# endif /* ! SPT_PADCHAR */
#endif /* SPT_TYPE != SPT_NONE && SPT_TYPE != SPT_BUILTIN */
#ifndef SPT_BUFSIZE
# define SPT_BUFSIZE MAXLINE
#endif /* ! SPT_BUFSIZE */
/*
** Pointers for setproctitle.
** This allows "ps" listings to give more useful information.
*/
static char **Argv = NULL; /* pointer to argument vector */
static char *LastArgv = NULL; /* end of argv */
#if SPT_TYPE != SPT_BUILTIN
static void setproctitle __P((const char *, ...));
#endif /* SPT_TYPE != SPT_BUILTIN */
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;
/*
** Determine how much space we can use for setproctitle.
** Use all contiguous argv and envp pointers starting at argv[0]
*/
for (i = 0; i < argc; i++)
{
if (i == 0 || LastArgv + 1 == argv[i])
LastArgv = argv[i] + strlen(argv[i]);
}
for (i = 0; LastArgv != NULL && envp[i] != NULL; i++)
{
if (LastArgv + 1 == envp[i])
LastArgv = envp[i] + strlen(envp[i]);
}
}
#if SPT_TYPE != SPT_BUILTIN
/*VARARGS1*/
static void
# ifdef __STDC__
setproctitle(const char *fmt, ...)
# else /* __STDC__ */
setproctitle(fmt, va_alist)
const char *fmt;
va_dcl
# endif /* __STDC__ */
{
# if SPT_TYPE != SPT_NONE
register int i;
register char *p;
SETPROC_STATIC char buf[SPT_BUFSIZE];
VA_LOCAL_DECL
# if SPT_TYPE == SPT_PSTAT
union pstun pst;
# endif /* SPT_TYPE == SPT_PSTAT */
# if SPT_TYPE == SPT_SCO
off_t seek_off;
static int kmem = -1;
static int kmempid = -1;
struct user u;
# endif /* SPT_TYPE == SPT_SCO */
p = buf;
/* print sendmail: heading for grep */
(void) strlcpy(p, "sendmail: ", SPACELEFT(buf, p));
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 /* SPT_TYPE == SPT_PSTAT */
# if SPT_TYPE == SPT_PSSTRINGS
PS_STRINGS->ps_nargvstr = 1;
PS_STRINGS->ps_argvstr = buf;
# endif /* SPT_TYPE == SPT_PSSTRINGS */
# if SPT_TYPE == SPT_SYSMIPS
sysmips(SONY_SYSNEWS, NEWS_SETPSARGS, buf);
# endif /* SPT_TYPE == SPT_SYSMIPS */
# 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, FD_CLOEXEC);
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 /* SPT_TYPE == SPT_SCO */
# if SPT_TYPE == SPT_REUSEARGV
if (LastArgv == NULL)
return;
if (i > LastArgv - Argv[0] - 2)
{
i = LastArgv - Argv[0] - 2;
buf[i] = '\0';
}
(void) strlcpy(Argv[0], buf, i + 1);
p = &Argv[0][i];
while (p < LastArgv)
*p++ = SPT_PADCHAR;
Argv[1] = NULL;
# endif /* SPT_TYPE == SPT_REUSEARGV */
# if SPT_TYPE == SPT_CHANGEARGV
Argv[0] = buf;
Argv[1] = 0;
# endif /* SPT_TYPE == SPT_CHANGEARGV */
# endif /* SPT_TYPE != SPT_NONE */
}
#endif /* SPT_TYPE != SPT_BUILTIN */
/*
** SM_SETPROCTITLE -- set process task and set process title for ps
**
** Possibly set process status and call setproctitle() to
** change the ps display.
**
** Parameters:
** status -- whether or not to store as process status
** e -- the current envelope.
** fmt -- a printf style format string.
** a, b, c -- possible parameters to fmt.
**
** Returns:
** none.
*/
/*VARARGS2*/
void
#ifdef __STDC__
sm_setproctitle(bool status, ENVELOPE *e, const char *fmt, ...)
#else /* __STDC__ */
sm_setproctitle(status, e, fmt, va_alist)
bool status;
ENVELOPE *e;
const char *fmt;
va_dcl
#endif /* __STDC__ */
{
char buf[SPT_BUFSIZE];
VA_LOCAL_DECL
/* print the argument string */
VA_START(fmt);
(void) vsnprintf(buf, sizeof buf, fmt, ap);
VA_END;
if (status)
proc_list_set(getpid(), buf);
if (ProcTitlePrefix != NULL)
{
char prefix[SPT_BUFSIZE];
expand(ProcTitlePrefix, prefix, sizeof prefix, e);
setproctitle("%s: %s", prefix, buf);
}
else
setproctitle("%s", buf);
}
/*
** 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 /* WAITUNION */
auto int st;
# endif /* WAITUNION */
pid_t i;
# if defined(ISC_UNIX) || defined(_SCO_unix_)
int savesig;
# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
do
{
errno = 0;
# if defined(ISC_UNIX) || defined(_SCO_unix_)
savesig = releasesignal(SIGCHLD);
# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
i = wait(&st);
# if defined(ISC_UNIX) || defined(_SCO_unix_)
if (savesig > 0)
blocksignal(SIGCHLD);
# endif /* defined(ISC_UNIX) || defined(_SCO_unix_) */
if (i > 0)
(void) proc_list_drop(i);
} while ((i >= 0 || errno == EINTR) && i != pid);
if (i < 0)
return -1;
# ifdef WAITUNION
return st.w_status;
# else /* WAITUNION */
return st;
# endif /* WAITUNION */
}
/*
** REAPCHILD -- pick up the body of my child, lest it become a zombie
**
** Parameters:
** sig -- the signal that got us here (unused).
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -