summaryrefslogtreecommitdiffstats
path: root/usr.sbin/inetd
diff options
context:
space:
mode:
authordelphij <delphij@FreeBSD.org>2006-01-18 07:47:46 +0000
committerdelphij <delphij@FreeBSD.org>2006-01-18 07:47:46 +0000
commit55eb0335a6ca658635fcbceceb48c7173143e1cd (patch)
tree31d4251b33d21cb2fb315ba888e9965790a8a3cf /usr.sbin/inetd
parentf99d64bc8026953fb7714cec81dd7bd7dcf66136 (diff)
downloadFreeBSD-src-55eb0335a6ca658635fcbceceb48c7173143e1cd.zip
FreeBSD-src-55eb0335a6ca658635fcbceceb48c7173143e1cd.tar.gz
Improves and cleanups over inetd(8):
- Teach inetd(8) about kqueue, originally implemented by jmg@[1]. - Use new C99 style function prototypes instead of K&Rs. - Raise WARNS from 2 to 6 Glanced at by: ru MFC After: 2 weeks [1] http://people.freebsd.org/~jmg/inetd.kq.patch, http://people.freebsd.org/~jmg/inetd.kq.html
Diffstat (limited to 'usr.sbin/inetd')
-rw-r--r--usr.sbin/inetd/Makefile2
-rw-r--r--usr.sbin/inetd/inetd.c361
-rw-r--r--usr.sbin/inetd/inetd.h14
3 files changed, 150 insertions, 227 deletions
diff --git a/usr.sbin/inetd/Makefile b/usr.sbin/inetd/Makefile
index afe4c51..c5d86b7 100644
--- a/usr.sbin/inetd/Makefile
+++ b/usr.sbin/inetd/Makefile
@@ -6,7 +6,7 @@ MAN= inetd.8
MLINKS= inetd.8 inetd.conf.5
SRCS= inetd.c builtins.c
-WARNS?= 2
+WARNS?= 6
CFLAGS+= -DLOGIN_CAP
#CFLAGS+= -DSANITY_CHECK
diff --git a/usr.sbin/inetd/inetd.c b/usr.sbin/inetd/inetd.c
index e5f7365..d434616 100644
--- a/usr.sbin/inetd/inetd.c
+++ b/usr.sbin/inetd/inetd.c
@@ -113,6 +113,8 @@ __FBSDID("$FreeBSD$");
#include <sys/wait.h>
#include <sys/time.h>
#include <sys/resource.h>
+#include <sys/types.h>
+#include <sys/event.h>
#include <sys/stat.h>
#include <sys/un.h>
@@ -197,6 +199,7 @@ __FBSDID("$FreeBSD$");
#ifndef TOOMANY
#define TOOMANY 256 /* don't start more than TOOMANY */
#endif
+
#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
#define RETRYTIME (60*10) /* retry after bind or server fail */
#define MAX_MAXCHLD 32767 /* max allowable max children */
@@ -204,8 +207,6 @@ __FBSDID("$FreeBSD$");
#define SIGBLOCK (sigmask(SIGCHLD)|sigmask(SIGHUP)|sigmask(SIGALRM))
void close_sep(struct servtab *);
-void flag_signal(int);
-void flag_config(int);
void config(void);
int cpmip(const struct servtab *, int);
void endconfig(void);
@@ -215,11 +216,8 @@ struct servtab *getconfigent(void);
int matchservent(const char *, const char *, const char *);
char *nextline(FILE *);
void addchild(struct servtab *, int);
-void flag_reapchild(int);
-void reapchild(void);
void enable(struct servtab *);
void disable(struct servtab *);
-void flag_retry(int);
void retry(void);
int setconfig(void);
void setup(struct servtab *);
@@ -230,7 +228,6 @@ void unregisterrpc(register struct servtab *sep);
static struct conninfo *search_conn(struct servtab *sep, int ctrl);
static int room_conn(struct servtab *sep, struct conninfo *conn);
static void addchild_conn(struct conninfo *conn, pid_t pid);
-static void reapchild_conn(pid_t pid);
static void free_conn(struct conninfo *conn);
static void resize_conn(struct servtab *sep, int maxperip);
static void free_connlist(struct servtab *sep);
@@ -245,7 +242,7 @@ int wrap_bi = 0;
int debug = 0;
int dolog = 0;
int maxsock; /* highest-numbered descriptor */
-fd_set allsock;
+int kqsock;
int options;
int timingout;
int toomany = TOOMANY;
@@ -261,7 +258,6 @@ int v4bind_ok = 0;
struct sockaddr_in6 *bind_sa6;
int v6bind_ok = 0;
#endif
-int signalpipe[2];
#ifdef SANITY_CHECK
int nsock;
#endif
@@ -313,6 +309,7 @@ whichaf(struct request_info *req)
int
main(int argc, char **argv)
{
+ struct kevent kqevlist[16];
struct servtab *sep;
struct passwd *pwd;
struct group *grp;
@@ -336,7 +333,11 @@ main(int argc, char **argv)
#define peer4 p_un.peer_un4
#define peer6 p_un.peer_un6
#define peermax p_un.peer_max
- int i;
+ int i, j;
+#ifdef SANITY_CHECK
+ int k;
+#endif
+ int status;
struct addrinfo hints, *res;
const char *servname;
int error;
@@ -519,19 +520,21 @@ main(int argc, char **argv)
}
#endif
+ kqsock = kqueue();
+ if (kqsock < 0)
+ err(EX_OSERR, "ERROR: Cannot allocate kqueue");
+
sa.sa_flags = 0;
sigemptyset(&sa.sa_mask);
sigaddset(&sa.sa_mask, SIGALRM);
sigaddset(&sa.sa_mask, SIGCHLD);
sigaddset(&sa.sa_mask, SIGHUP);
- sa.sa_handler = flag_retry;
+ sa.sa_handler = SIG_IGN;
sigaction(SIGALRM, &sa, &saalrm);
+ WATCH_SIG(SIGALRM, retry);
config();
- sa.sa_handler = flag_config;
sigaction(SIGHUP, &sa, &sahup);
- sa.sa_handler = flag_reapchild;
- sigaction(SIGCHLD, &sa, &sachld);
- sa.sa_handler = SIG_IGN;
+ WATCH_SIG(SIGHUP, config);
sigaction(SIGPIPE, &sa, &sapipe);
{
@@ -544,27 +547,8 @@ main(int argc, char **argv)
(void)setenv("inetd_dummy", dummy, 1);
}
- if (pipe(signalpipe) != 0) {
- syslog(LOG_ERR, "pipe: %m");
- exit(EX_OSERR);
- }
- if (fcntl(signalpipe[0], F_SETFD, FD_CLOEXEC) < 0 ||
- fcntl(signalpipe[1], F_SETFD, FD_CLOEXEC) < 0) {
- syslog(LOG_ERR, "signalpipe: fcntl (F_SETFD, FD_CLOEXEC): %m");
- exit(EX_OSERR);
- }
- FD_SET(signalpipe[0], &allsock);
-#ifdef SANITY_CHECK
- nsock++;
-#endif
- if (signalpipe[0] > maxsock)
- maxsock = signalpipe[0];
- if (signalpipe[1] > maxsock)
- maxsock = signalpipe[1];
-
for (;;) {
int n, ctrl;
- fd_set readable;
#ifdef SANITY_CHECK
if (nsock == 0) {
@@ -572,46 +556,60 @@ main(int argc, char **argv)
exit(EX_SOFTWARE);
}
#endif
- readable = allsock;
- if ((n = select(maxsock + 1, &readable, (fd_set *)0,
- (fd_set *)0, (struct timeval *)0)) <= 0) {
- if (n < 0 && errno != EINTR) {
- syslog(LOG_WARNING, "select: %m");
+
+ if ((n = kevent(kqsock, NULL, 0, kqevlist,
+ sizeof kqevlist / sizeof *kqevlist,
+ (struct timespec *)0)) <= 0) {
+ if (n == -1 && errno != EINTR) {
+ syslog(LOG_WARNING, "kevent: %m");
sleep(1);
}
continue;
}
- /* handle any queued signal flags */
- if (FD_ISSET(signalpipe[0], &readable)) {
- int nsig;
- if (ioctl(signalpipe[0], FIONREAD, &nsig) != 0) {
- syslog(LOG_ERR, "ioctl: %m");
- exit(EX_OSERR);
- }
- while (--nsig >= 0) {
- char c;
- if (read(signalpipe[0], &c, 1) != 1) {
- syslog(LOG_ERR, "read: %m");
- exit(EX_OSERR);
- }
+
+ for (j = 0; j < n; j++) {
+ if (kqevlist[j].filter == EVFILT_SIGNAL) {
+ /* handle any queued signal flags */
if (debug)
- warnx("handling signal flag %c", c);
- switch(c) {
- case 'A': /* sigalrm */
- retry();
- break;
- case 'C': /* sigchld */
- reapchild();
- break;
- case 'H': /* sighup */
- config();
- break;
- }
- }
- }
- for (sep = servtab; n && sep; sep = sep->se_next)
- if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
- n--;
+ warnx("calling signalhandler for sig %td",
+ kqevlist[j].ident);
+ ((void (*)(void))kqevlist[j].udata)();
+ } else if (kqevlist[j].filter == EVFILT_PROC) {
+ sep = (struct servtab *)kqevlist[j].udata;
+ pid = wait4(kqevlist[j].ident, &status, WNOHANG,
+ (struct rusage *)0);
+ if (debug)
+ warnx("%d reaped, status %#x", pid, status);
+ if (pid == 0) {
+ /* XXX - this could leave a zombie */
+ syslog(LOG_WARNING, "can't reap pid %td",
+ kqevlist[j].ident);
+ continue;
+ }
+#ifdef SANITY_CHECK
+ for (k = 0; k < sep->se_numchild; k++)
+ if (sep->se_pids[k] == pid)
+ break;
+ if (k != sep->se_numchild)
+ sep->se_pids[k] =
+ sep->se_pids[sep->se_numchild - 1];
+#endif
+ if (sep->se_maxchild &&
+ sep->se_numchild == sep->se_maxchild)
+ enable(sep);
+ if (status)
+ syslog(LOG_WARNING,
+ "%s[%d]: exit status 0x%x",
+ sep->se_server, pid, status);
+ /* XXX - this should never happen */
+ if (--sep->se_numchild < 0)
+ sep->se_numchild = 0;
+ if (sep->se_free && sep->se_numchild == 0) {
+ freeconfig(sep);
+ free((char *)sep);
+ }
+ } else {
+ sep = (struct servtab *)kqevlist[j].udata;
if (debug)
warnx("someone wants %s", sep->se_service);
dofork = !sep->se_bi || sep->se_bi->bi_fork || ISWRAP(sep);
@@ -882,21 +880,7 @@ main(int argc, char **argv)
if (sep->se_accept && sep->se_socktype == SOCK_STREAM)
close(ctrl);
}
- }
-}
-
-/*
- * Add a signal flag to the signal flag queue for later handling
- */
-
-void
-flag_signal(int c)
-{
- char ch = c;
-
- if (write(signalpipe[1], &ch, 1) != 1) {
- syslog(LOG_ERR, "write: %m");
- _exit(EX_OSERR);
+ }
}
}
@@ -908,72 +892,18 @@ flag_signal(int c)
void
addchild(struct servtab *sep, pid_t pid)
{
- if (sep->se_maxchild <= 0)
- return;
#ifdef SANITY_CHECK
- if (sep->se_numchild >= sep->se_maxchild) {
+ if (sep->se_maxchild && sep->se_numchild >= sep->se_maxchild) {
syslog(LOG_ERR, "%s: %d >= %d",
__func__, sep->se_numchild, sep->se_maxchild);
exit(EX_SOFTWARE);
}
+ sep->se_pids[sep->se_numchild] = pid;
#endif
- sep->se_pids[sep->se_numchild++] = pid;
- if (sep->se_numchild == sep->se_maxchild)
+ sep->se_numchild++;
+ if (sep->se_maxchild && sep->se_numchild == sep->se_maxchild)
disable(sep);
-}
-
-/*
- * Some child process has exited. See if it's on somebody's list.
- */
-
-void
-flag_reapchild(int signo __unused)
-{
- flag_signal('C');
-}
-
-void
-reapchild(void)
-{
- int k, status;
- pid_t pid;
- struct servtab *sep;
-
- for (;;) {
- pid = wait3(&status, WNOHANG, (struct rusage *)0);
- if (pid <= 0)
- break;
- if (debug)
- warnx("%d reaped, %s %u", pid,
- WIFEXITED(status) ? "status" : "signal",
- WIFEXITED(status) ? WEXITSTATUS(status)
- : WTERMSIG(status));
- for (sep = servtab; sep; sep = sep->se_next) {
- for (k = 0; k < sep->se_numchild; k++)
- if (sep->se_pids[k] == pid)
- break;
- if (k == sep->se_numchild)
- continue;
- if (sep->se_numchild == sep->se_maxchild)
- enable(sep);
- sep->se_pids[k] = sep->se_pids[--sep->se_numchild];
- if (WIFSIGNALED(status) || WEXITSTATUS(status))
- syslog(LOG_WARNING,
- "%s[%d]: exited, %s %u",
- sep->se_server, pid,
- WIFEXITED(status) ? "status" : "signal",
- WIFEXITED(status) ? WEXITSTATUS(status)
- : WTERMSIG(status));
- break;
- }
- reapchild_conn(pid);
- }
-}
-
-void
-flag_config(int signo __unused)
-{
- flag_signal('H');
+ WATCH_PROC(pid, sep);
}
void
@@ -990,8 +920,10 @@ config(void)
syslog(LOG_ERR, "%s: %m", CONFIG);
return;
}
- for (sep = servtab; sep; sep = sep->se_next)
+
+ for (sep = servtab; sep != NULL; sep = sep->se_next)
sep->se_checked = 0;
+
while ((new = getconfigent())) {
if (getpwnam(new->se_user) == NULL) {
syslog(LOG_ERR,
@@ -1037,12 +969,17 @@ config(void)
/* copy over outstanding child pids */
if (sep->se_maxchild > 0 && new->se_maxchild > 0) {
new->se_numchild = sep->se_numchild;
+ /* XXX - this can cause problems */
if (new->se_numchild > new->se_maxchild)
new->se_numchild = new->se_maxchild;
+#ifdef SANITY_CHECK
memcpy(new->se_pids, sep->se_pids,
new->se_numchild * sizeof(*new->se_pids));
+#endif
}
+#ifdef SANITY_CHECK
SWAP(pid_t *, sep->se_pids, new->se_pids);
+#endif
sep->se_maxchild = new->se_maxchild;
sep->se_numchild = new->se_numchild;
sep->se_maxcpm = new->se_maxcpm;
@@ -1051,14 +988,11 @@ config(void)
sep->se_bi = new->se_bi;
/* might need to turn on or off service now */
if (sep->se_fd >= 0) {
- if (sep->se_maxchild > 0
- && sep->se_numchild == sep->se_maxchild) {
- if (FD_ISSET(sep->se_fd, &allsock))
- disable(sep);
- } else {
- if (!FD_ISSET(sep->se_fd, &allsock))
- enable(sep);
- }
+ if (sep->se_maxchild
+ && sep->se_numchild == sep->se_maxchild)
+ disable(sep);
+ else
+ enable(sep);
}
sep->se_accept = new->se_accept;
SWAP(char *, sep->se_user, new->se_user);
@@ -1178,8 +1112,11 @@ config(void)
print_service("FREE", sep);
if (sep->se_rpc && sep->se_rpc_prog > 0)
unregisterrpc(sep);
- freeconfig(sep);
- free(sep);
+ if (sep->se_numchild == 0) {
+ freeconfig(sep);
+ free((char *)sep);
+ } else
+ sep->se_free = 1;
}
(void) sigsetmask(omask);
}
@@ -1240,12 +1177,6 @@ unregisterrpc(struct servtab *sep)
}
void
-flag_retry(int signo __unused)
-{
- flag_signal('A');
-}
-
-void
retry(void)
{
struct servtab *sep;
@@ -1279,12 +1210,12 @@ setup(struct servtab *sep)
#define turnon(fd, opt) \
setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
if (strcmp(sep->se_proto, "tcp") == 0 && (options & SO_DEBUG) &&
- turnon(sep->se_fd, SO_DEBUG) < 0)
+ turnon(sep->se_fd, SO_DEBUG) == -1)
syslog(LOG_ERR, "setsockopt (SO_DEBUG): %m");
- if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
+ if (turnon(sep->se_fd, SO_REUSEADDR) == -1)
syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
#ifdef SO_PRIVSTATE
- if (turnon(sep->se_fd, SO_PRIVSTATE) < 0)
+ if (turnon(sep->se_fd, SO_PRIVSTATE) == -1)
syslog(LOG_ERR, "setsockopt (SO_PRIVSTATE): %m");
#endif
/* tftpd opens a new connection then needs more infos */
@@ -1292,7 +1223,7 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
(strcmp(sep->se_proto, "udp") == 0) &&
(sep->se_accept == 0) &&
(setsockopt(sep->se_fd, IPPROTO_IPV6, IPV6_RECVPKTINFO,
- (char *)&on, sizeof (on)) < 0))
+ (char *)&on, sizeof (on)) == -1))
syslog(LOG_ERR, "setsockopt (IPV6_RECVPKTINFO): %m");
if (sep->se_family == AF_INET6) {
int flag = sep->se_nomapped ? 1 : 0;
@@ -1397,8 +1328,7 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
#ifdef IPSEC
void
-ipsecsetup(sep)
- struct servtab *sep;
+ipsecsetup(struct servtab *sep)
{
char *buf;
char *policy_in = NULL;
@@ -1475,8 +1405,7 @@ void
close_sep(struct servtab *sep)
{
if (sep->se_fd >= 0) {
- if (FD_ISSET(sep->se_fd, &allsock))
- disable(sep);
+ disable(sep);
(void) close(sep->se_fd);
sep->se_fd = -1;
}
@@ -1515,7 +1444,7 @@ enter(struct servtab *cp)
long omask;
sep = (struct servtab *)malloc(sizeof (*sep));
- if (sep == (struct servtab *)0) {
+ if (sep == NULL) {
syslog(LOG_ERR, "malloc: %m");
exit(EX_OSERR);
}
@@ -1545,14 +1474,9 @@ enable(struct servtab *sep)
"%s: %s: is mux", __func__, sep->se_service);
exit(EX_SOFTWARE);
}
- if (FD_ISSET(sep->se_fd, &allsock)) {
- syslog(LOG_ERR,
- "%s: %s: not off", __func__, sep->se_service);
- exit(EX_SOFTWARE);
- }
nsock++;
#endif
- FD_SET(sep->se_fd, &allsock);
+ WATCH_SOCK(sep->se_fd, sep);
if (sep->se_fd > maxsock)
maxsock = sep->se_fd;
}
@@ -1574,18 +1498,13 @@ disable(struct servtab *sep)
"%s: %s: is mux", __func__, sep->se_service);
exit(EX_SOFTWARE);
}
- if (!FD_ISSET(sep->se_fd, &allsock)) {
- syslog(LOG_ERR,
- "%s: %s: not on", __func__, sep->se_service);
- exit(EX_SOFTWARE);
- }
if (nsock == 0) {
syslog(LOG_ERR, "%s: nsock=0", __func__);
exit(EX_SOFTWARE);
}
nsock--;
#endif
- FD_CLR(sep->se_fd, &allsock);
+ UNWATCH_SOCK(sep->se_fd, sep);
if (sep->se_fd == maxsock)
maxsock--;
}
@@ -1649,12 +1568,10 @@ more:
for (p = cp + 2; p && *p && isspace(*p); p++)
;
if (*p == '\0') {
- if (policy)
- free(policy);
+ free(policy);
policy = NULL;
} else if (ipsec_get_policylen(p) >= 0) {
- if (policy)
- free(policy);
+ free(policy);
policy = newstr(p);
} else {
syslog(LOG_ERR,
@@ -1970,6 +1887,7 @@ more:
else
sep->se_maxchild = 1;
}
+#ifdef SANITY_CHECK
if (sep->se_maxchild > 0) {
sep->se_pids = malloc(sep->se_maxchild * sizeof(*sep->se_pids));
if (sep->se_pids == NULL) {
@@ -1977,6 +1895,7 @@ more:
exit(EX_OSERR);
}
}
+#endif
argc = 0;
for (arg = skip(&cp); cp; arg = skip(&cp))
if (argc < MAXARGV) {
@@ -2002,29 +1921,22 @@ freeconfig(struct servtab *cp)
{
int i;
- if (cp->se_service)
- free(cp->se_service);
- if (cp->se_proto)
- free(cp->se_proto);
- if (cp->se_user)
- free(cp->se_user);
- if (cp->se_group)
- free(cp->se_group);
+ free(cp->se_service);
+ free(cp->se_proto);
+ free(cp->se_user);
+ free(cp->se_group);
#ifdef LOGIN_CAP
- if (cp->se_class)
- free(cp->se_class);
+ free(cp->se_class);
+#endif
+ free(cp->se_server);
+#ifdef SANITY_CHECK
+ free(cp->se_pids);
#endif
- if (cp->se_server)
- free(cp->se_server);
- if (cp->se_pids)
- free(cp->se_pids);
for (i = 0; i < MAXARGV; i++)
- if (cp->se_argv[i])
- free(cp->se_argv[i]);
+ free(cp->se_argv[i]);
free_connlist(cp);
#ifdef IPSEC
- if (cp->se_policy)
- free(cp->se_policy);
+ free(cp->se_policy);
#endif
}
@@ -2303,8 +2215,7 @@ cpmip(const struct servtab *sep, int ctrl)
strcmp(sep->se_service, chBest->ch_Service) != 0) {
chBest->ch_Family = sin4->sin_family;
chBest->ch_Addr4 = sin4->sin_addr;
- if (chBest->ch_Service)
- free(chBest->ch_Service);
+ free(chBest->ch_Service);
chBest->ch_Service = strdup(sep->se_service);
bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
}
@@ -2317,8 +2228,7 @@ cpmip(const struct servtab *sep, int ctrl)
strcmp(sep->se_service, chBest->ch_Service) != 0) {
chBest->ch_Family = sin6->sin6_family;
chBest->ch_Addr6 = sin6->sin6_addr;
- if (chBest->ch_Service)
- free(chBest->ch_Service);
+ free(chBest->ch_Service);
chBest->ch_Service = strdup(sep->se_service);
bzero(chBest->ch_Times, sizeof(chBest->ch_Times));
}
@@ -2356,6 +2266,25 @@ cpmip(const struct servtab *sep, int ctrl)
return(r);
}
+void
+watch(short filter, uintptr_t ident, void *data, u_int fflags, int addrm)
+{
+ struct kevent kev;
+ int i;
+
+ EV_SET(&kev, ident, filter, addrm? EV_ADD:EV_DELETE,
+ fflags, 0, data);
+
+ i = kevent(kqsock, &kev, 1, NULL, 0, NULL);
+
+ if (i == -1)
+ syslog(LOG_ERR, "kevent failed: %m");
+
+ if (debug) {
+ warnx("kqueue, ident: %td, addrm: %d, ret: %d, data: %p, errno: %s", ident, addrm, i, data, strerror(errno));
+ }
+}
+
static struct conninfo *
search_conn(struct servtab *sep, int ctrl)
{
@@ -2467,26 +2396,6 @@ addchild_conn(struct conninfo *conn, pid_t pid)
}
static void
-reapchild_conn(pid_t pid)
-{
- struct procinfo *proc;
- struct conninfo *conn;
- int i;
-
- if ((proc = search_proc(pid, 0)) == NULL)
- return;
- if ((conn = proc->pr_conn) == NULL)
- return;
- for (i = 0; i < conn->co_numchild; ++i)
- if (conn->co_proc[i] == proc) {
- conn->co_proc[i] = conn->co_proc[--conn->co_numchild];
- break;
- }
- free_proc(proc);
- free_conn(conn);
-}
-
-static void
resize_conn(struct servtab *sep, int maxpip)
{
struct conninfo *conn;
diff --git a/usr.sbin/inetd/inetd.h b/usr.sbin/inetd/inetd.h
index 8c05ed9..e84547c 100644
--- a/usr.sbin/inetd/inetd.h
+++ b/usr.sbin/inetd/inetd.h
@@ -74,7 +74,10 @@ struct servtab {
int se_maxchild; /* max number of children */
int se_maxcpm; /* max connects per IP per minute */
int se_numchild; /* current number of children */
+ int se_free; /* free when numchild == 0 */
+#ifdef SANITY_CHECK
pid_t *se_pids; /* array of child pids */
+#endif
char *se_user; /* user name to run as */
char *se_group; /* group name to run as */
#ifdef LOGIN_CAP
@@ -145,3 +148,14 @@ struct biltin {
int bi_maxchild; /* max number of children, -1=default */
bi_fn_t *bi_fn; /* function which performs it */
};
+
+void watch(short, uintptr_t, void *, u_int, int);
+#define WATCH_SOCK(fd, data) watch(EVFILT_READ, fd, data, 0, 1)
+#define UNWATCH_SOCK(fd, data) watch(EVFILT_READ, fd, data, 0, 0)
+#define WATCH_SIG(sig, data) watch(EVFILT_SIGNAL, sig, data, 0, 1)
+#define UNWATCH_SIG(sig, data) watch(EVFILT_SIGNAL, sig, data, 0, 0)
+#define WATCH_PROC(proc, data) watch(EVFILT_PROC, proc, data, NOTE_EXIT, 1)
+#define UNWATCH_PROC(proc, data) watch(EVFILT_PROC, proc, data, NOTE_EXIT, 0)
+#define WATCH_FD(fd, data) watch(EVFILT_VNODE, fd, data, NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_RENAME, 1)
+#define UNWATCH_FD(fd, data) watch(EVFILT_VNODE, fd, data, NOTE_DELETE|NOTE_WRITE|NOTE_EXTEND|NOTE_RENAME, 0)
+
OpenPOWER on IntegriCloud