this replaces the use of select with libevent in inetd.

it has been reviewed by a few people, but tests would be appreciated.

if people are still using inetd, could they give this a go and let
us know if it behaves differently than expected?


Index: Makefile
===================================================================
RCS file: /cvs/src/usr.sbin/inetd/Makefile,v
retrieving revision 1.3
diff -u -p -r1.3 Makefile
--- Makefile    31 Mar 2000 01:00:49 -0000      1.3
+++ Makefile    27 Oct 2014 06:25:37 -0000
@@ -1,6 +1,8 @@
 #      $OpenBSD: Makefile,v 1.3 2000/03/31 01:00:49 deraadt Exp $
 
 PROG=  inetd
+LDADD= -levent
+DPADD= ${LIBEVENT}
 MAN=   inetd.8
 MLINKS=        inetd.8 inetd.conf.5
 
Index: inetd.c
===================================================================
RCS file: /cvs/src/usr.sbin/inetd/inetd.c,v
retrieving revision 1.141
diff -u -p -r1.141 inetd.c
--- inetd.c     13 Oct 2014 01:53:14 -0000      1.141
+++ inetd.c     27 Oct 2014 06:25:37 -0000
@@ -151,6 +151,7 @@
 #include <rpc/rpc.h>
 #include <rpc/pmap_clnt.h>
 #include <rpcsvc/nfs_prot.h>
+#include <event.h>
 #include "pathnames.h"
 
 #define        TOOMANY         256             /* don't start more than 
TOOMANY */
@@ -158,15 +159,11 @@
 #define        RETRYTIME       (60*10)         /* retry after bind or server 
fail */
 
 int     debug = 0;
-int     nsock, maxsock;
-fd_set *allsockp;
-int     allsockn;
+int     maxsock;
 int     toomany = TOOMANY;
 int     timingout;
 struct  servent *sp;
 uid_t   uid;
-sigset_t blockmask;
-sigset_t emptymask;
 
 #ifndef OPEN_MAX
 #define OPEN_MAX       64
@@ -214,6 +211,7 @@ struct      servtab {
        int     se_count;               /* number started since se_time */
        struct  timeval se_time;        /* start of se_count */
        struct  servtab *se_next;
+       struct  event se_event;
 } *servtab;
 
 void echo_stream(int, struct servtab *);
@@ -257,21 +255,19 @@ struct biltin {
        { 0 }
 };
 
-volatile sig_atomic_t wantretry;
-volatile sig_atomic_t wantconfig;
-volatile sig_atomic_t wantreap;
-volatile sig_atomic_t wantdie;
-
-void   config(int);
-void   doconfig(void);
-void   reap(int);
-void   doreap(void);
-void   retry(int);
-void   doretry(void);
-void   die(int);
-void   dodie(void);
-void   spawn(struct servtab *, int);
-int    gettcp(struct servtab *);
+struct event evsig_alrm;
+struct event evsig_hup;
+struct event evsig_chld;
+struct event evsig_term;
+struct event evsig_int;
+
+void   config(int, short, void *);
+void   reap(int, short, void *);
+void   retry(int, short, void *);
+void   die(int, short, void *);
+
+void   spawn(int, short, void *);
+void   gettcp(int, short, void *);
 int    setconfig(void);
 void   endconfig(void);
 void   register_rpc(struct servtab *);
@@ -288,40 +284,15 @@ int       dg_broadcast(struct in_addr *in);
 #define NUMINT (sizeof(intab) / sizeof(struct inent))
 char   *CONFIG = _PATH_INETDCONF;
 
-void           fd_grow(fd_set **fdsp, int *bytes, int fd);
 int            dg_badinput(struct sockaddr *sa);
 void           inetd_setproctitle(char *a, int s);
 void           initring(void);
 u_int32_t      machtime(void);
 
-void
-fd_grow(fd_set **fdsp, int *bytes, int fd)
-{
-       caddr_t new;
-       int newbytes;
-
-       newbytes = howmany(fd+1, NFDBITS) * sizeof(fd_mask);
-       if (newbytes > *bytes) {
-               newbytes *= 2;                  /* optimism */
-               new = realloc(*fdsp, newbytes);
-               if (new == NULL) {
-                       syslog(LOG_ERR, "Out of memory.");
-                       exit(1);
-               }
-               memset(new + *bytes, 0, newbytes - *bytes);
-               *fdsp = (fd_set *)new;
-               *bytes = newbytes;
-       }
-}
-
-struct sigaction sa, sapipe;
-
 int
 main(int argc, char *argv[])
 {
-       fd_set *fdsrp = NULL;
-       int readablen = 0, ch;
-       struct servtab *sep;
+       int ch;
        extern char *optarg;
        extern int optind;
        
@@ -391,109 +362,38 @@ main(int argc, char *argv[])
                        rlim_nofile_cur = OPEN_MAX;
        }
 
-       sigemptyset(&emptymask);
-       sigemptyset(&blockmask);
-       sigaddset(&blockmask, SIGCHLD);
-       sigaddset(&blockmask, SIGHUP);
-       sigaddset(&blockmask, SIGALRM);
-
-       memset(&sa, 0, sizeof(sa));
-       sigemptyset(&sa.sa_mask);
-       sigaddset(&sa.sa_mask, SIGALRM);
-       sigaddset(&sa.sa_mask, SIGCHLD);
-       sigaddset(&sa.sa_mask, SIGHUP);
-       sa.sa_handler = retry;
-       sigaction(SIGALRM, &sa, NULL);
-       doconfig();
-       sa.sa_handler = config;
-       sigaction(SIGHUP, &sa, NULL);
-       sa.sa_handler = reap;
-       sigaction(SIGCHLD, &sa, NULL);
-       sa.sa_handler = die;
-       sigaction(SIGTERM, &sa, NULL);
-       sa.sa_handler = die;
-       sigaction(SIGINT, &sa, NULL);
-       sa.sa_handler = SIG_IGN;
-       sigaction(SIGPIPE, &sa, &sapipe);
+       event_init();
 
-       for (;;) {
-               int n, ctrl = -1;
+       signal_set(&evsig_alrm, SIGALRM, retry, NULL);
+       signal_add(&evsig_alrm, NULL);
 
-           restart:
-               if (nsock == 0) {
-                       (void) sigprocmask(SIG_BLOCK, &blockmask, NULL);
-                       while (nsock == 0) {
-                               if (wantretry || wantconfig || wantreap || 
wantdie)
-                                       break;
-                               sigsuspend(&emptymask);
-                       }
-                       (void) sigprocmask(SIG_SETMASK, &emptymask, NULL);
-               }
+       config(0, 0, NULL);
 
-               while (wantretry || wantconfig || wantreap || wantdie) {
-                       if (wantretry) {
-                               wantretry = 0;
-                               doretry();
-                       }
-                       if (wantconfig) {
-                               wantconfig = 0;
-                               doconfig();
-                       }
-                       if (wantreap) {
-                               wantreap = 0;
-                               doreap();
-                       }
-                       if (wantdie)
-                               dodie();
-                       goto restart;
-               }
+       signal_set(&evsig_hup, SIGHUP, config, NULL);
+       signal_add(&evsig_hup, NULL);
+       signal_set(&evsig_chld, SIGCHLD, reap, NULL);
+       signal_add(&evsig_chld, NULL);
+       signal_set(&evsig_term, SIGTERM, die, NULL);
+       signal_add(&evsig_term, NULL);
+       signal_set(&evsig_int, SIGINT, die, NULL);
+       signal_add(&evsig_int, NULL);
 
-               if (readablen != allsockn) {
-                       if (fdsrp)
-                               free(fdsrp);
-                       fdsrp = calloc(allsockn, 1);
-                       if (fdsrp == NULL) {
-                               syslog(LOG_ERR, "Out of memory.");
-                               exit(1);
-                       }
-                       readablen = allsockn;
-               }
-               bcopy(allsockp, fdsrp, allsockn);
+       signal(SIGPIPE, SIG_IGN);
 
-               if ((n = select(maxsock + 1, fdsrp, NULL, NULL, NULL)) <= 0) {
-                       if (n < 0 && errno != EINTR) {
-                               syslog(LOG_WARNING, "select: %m");
-                               sleep(1);
-                       }
-                       continue;
-               }
+       event_dispatch();
 
-               for (sep = servtab; n && sep; sep = sep->se_next) {
-                       if (sep->se_fd != -1 &&
-                           FD_ISSET(sep->se_fd, fdsrp)) {
-                               n--;
-                               if (debug)
-                                       fprintf(stderr, "someone wants %s\n",
-                                           sep->se_service);
-                               if (!sep->se_wait &&
-                                   sep->se_socktype == SOCK_STREAM) {
-                                       ctrl = gettcp(sep);
-                                       if (ctrl == -1)
-                                               continue;
-                               } else
-                                       ctrl = sep->se_fd;
-                               (void) sigprocmask(SIG_BLOCK, &blockmask, NULL);
-                               spawn(sep, ctrl);       /* spawn will unblock */
-                       }
-               }
-       }
+       return (0);
 }
 
-int
-gettcp(struct servtab *sep)
+void
+gettcp(int fd, short events, void *xsep)
 {
+       struct servtab *sep = xsep;
        int ctrl;
 
+       if (debug)
+               fprintf(stderr, "someone wants %s\n", sep->se_service);
+
        ctrl = accept(sep->se_fd, NULL, NULL);
        if (debug)
                fprintf(stderr, "accept, ctrl %d\n", ctrl);
@@ -502,7 +402,7 @@ gettcp(struct servtab *sep)
                    errno != ECONNABORTED)
                        syslog(LOG_WARNING, "accept (for %s): %m",
                            sep->se_service);
-               return -1;
+               return;
        }
        if ((sep->se_family == AF_INET || sep->se_family == AF_INET6) &&
            sep->se_socktype == SOCK_STREAM) {
@@ -513,7 +413,7 @@ gettcp(struct servtab *sep)
                if (getpeername(ctrl, (struct sockaddr *)&peer, &plen) < 0) {
                        syslog(LOG_WARNING, "could not getpeername");
                        close(ctrl);
-                       return -1;
+                       return;
                }
                if (getnameinfo((struct sockaddr *)&peer, plen, NULL, 0,
                    sbuf, sizeof(sbuf), NI_NUMERICSERV) == 0 &&
@@ -522,12 +422,12 @@ gettcp(struct servtab *sep)
                         * ignore things that look like ftp bounce
                         */
                        close(ctrl);
-                       return -1;
+                       return;
                }
        }
-       return (ctrl);
-}
 
+       spawn(ctrl, 0, sep);
+}
 
 int
 dg_badinput(struct sockaddr *sa)
@@ -603,15 +503,8 @@ dg_broadcast(struct in_addr *in)
        return (0);
 }
 
-/* ARGSUSED */
-void
-reap(int sig)
-{
-       wantreap = 1;
-}
-
 void
-doreap(void)
+reap(int sig, short event, void *arg)
 {
        struct servtab *sep;
        int status;
@@ -640,9 +533,7 @@ doreap(void)
                                            "%s: exit signal %d",
                                            sep->se_server, WTERMSIG(status));
                                sep->se_wait = 1;
-                               fd_grow(&allsockp, &allsockn, sep->se_fd);
-                               FD_SET(sep->se_fd, allsockp);
-                               nsock++;
+                               event_add(&sep->se_event, NULL);
                                if (debug)
                                        fprintf(stderr, "restored %s, fd %d\n",
                                            sep->se_service, sep->se_fd);
@@ -650,20 +541,12 @@ doreap(void)
        }
 }
 
-/* ARGSUSED */
-void
-config(int sig)
-{
-       wantconfig = 1;
-}
-
 void
-doconfig(void)
+config(int sig, short event, void *arg)
 {
        struct servtab *sep, *cp, **sepp;
        int add;
        char protoname[10];
-       sigset_t omask;
 
        if (!setconfig()) {
                syslog(LOG_ERR, "%s: %m", CONFIG);
@@ -682,7 +565,6 @@ doconfig(void)
 
 #define SWAP(type, a, b) {type c=(type)a; a=(type)b; b=(type)c;}
 
-                       sigprocmask(SIG_BLOCK, &blockmask, &omask);
                        /*
                         * sep->se_wait may be holding the pid of a daemon
                         * that we're waiting for.  If so, don't overwrite
@@ -703,7 +585,6 @@ doconfig(void)
                                unregister_rpc(sep);
                        sep->se_rpcversl = cp->se_rpcversl;
                        sep->se_rpcversh = cp->se_rpcversh;
-                       sigprocmask(SIG_SETMASK, &omask, NULL);
                        freeconfig(cp);
                        add = 1;
                } else {
@@ -778,8 +659,7 @@ doconfig(void)
                                if (port != sep->se_ctrladdr_in.sin_port) {
                                        sep->se_ctrladdr_in.sin_port = port;
                                        if (sep->se_fd != -1) {
-                                               FD_CLR(sep->se_fd, allsockp);
-                                               nsock--;
+                                               event_del(&sep->se_event);
                                                (void) close(sep->se_fd);
                                        }
                                        sep->se_fd = -1;
@@ -834,8 +714,7 @@ doconfig(void)
                                if (port != sep->se_ctrladdr_in6.sin6_port) {
                                        sep->se_ctrladdr_in6.sin6_port = port;
                                        if (sep->se_fd != -1) {
-                                               FD_CLR(sep->se_fd, allsockp);
-                                               nsock--;
+                                               event_del(&sep->se_event);
                                                (void) close(sep->se_fd);
                                        }
                                        sep->se_fd = -1;
@@ -862,7 +741,6 @@ doconfig(void)
        /*
         * Purge anything not looked at above.
         */
-       sigprocmask(SIG_BLOCK, &blockmask, &omask);
        sepp = &servtab;
        while ((sep = *sepp)) {
                if (sep->se_checked) {
@@ -871,8 +749,7 @@ doconfig(void)
                }
                *sepp = sep->se_next;
                if (sep->se_fd != -1) {
-                       FD_CLR(sep->se_fd, allsockp);
-                       nsock--;
+                       event_del(&sep->se_event);
                        (void) close(sep->se_fd);
                }
                if (isrpcservice(sep))
@@ -884,18 +761,10 @@ doconfig(void)
                freeconfig(sep);
                free(sep);
        }
-       sigprocmask(SIG_SETMASK, &omask, NULL);
-}
-
-/* ARGSUSED */
-void
-retry(int sig)
-{
-       wantretry = 1;
 }
 
 void
-doretry(void)
+retry(int sig, short events, void *arg)
 {
        struct servtab *sep;
 
@@ -915,15 +784,8 @@ doretry(void)
        }
 }
 
-/* ARGSUSED */
-void
-die(int sig)
-{
-       wantdie = 1;
-}
-
 void
-dodie(void)
+die(int sig, short events, void *arg)
 {
        struct servtab *sep;
 
@@ -1015,9 +877,16 @@ setsockopt(fd, SOL_SOCKET, opt, &on, siz
        if (sep->se_socktype == SOCK_STREAM)
                listen(sep->se_fd, 10);
 
-       fd_grow(&allsockp, &allsockn, sep->se_fd);
-       FD_SET(sep->se_fd, allsockp);
-       nsock++;
+       if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+               event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST,
+                   gettcp, sep);
+       } else {
+               event_set(&sep->se_event, sep->se_fd, EV_READ|EV_PERSIST,
+                   spawn, sep);
+       }
+
+       event_add(&sep->se_event, NULL);
+
        if (sep->se_fd > maxsock) {
                maxsock = sep->se_fd;
                if (maxsock > rlim_nofile_cur - FD_MARGIN)
@@ -1078,7 +947,6 @@ struct servtab *
 enter(struct servtab *cp)
 {
        struct servtab *sep;
-       sigset_t omask;
 
        sep = malloc(sizeof (*sep));
        if (sep == NULL) {
@@ -1088,10 +956,8 @@ enter(struct servtab *cp)
        *sep = *cp;
        sep->se_fd = -1;
        sep->se_rpcprog = -1;
-       sigprocmask(SIG_BLOCK, &blockmask, &omask);
        sep->se_next = servtab;
        servtab = sep;
-       sigprocmask(SIG_SETMASK, &omask, NULL);
        return (sep);
 }
 
@@ -1835,14 +1701,18 @@ print_service(char *action, struct servt
 }
 
 void
-spawn(struct servtab *sep, int ctrl)
+spawn(int ctrl, short events, void *xsep)
 {
+       struct servtab *sep = xsep;
        struct passwd *pwd;
        int tmpint, dofork;
        struct group *grp = NULL;
        char buf[50];
        pid_t pid;
 
+       if (debug)
+               fprintf(stderr, "someone wants %s\n", sep->se_service);
+
        pid = 0;
        dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
        if (dofork) {
@@ -1869,8 +1739,6 @@ spawn(struct servtab *sep, int ctrl)
                                         * Simply ignore the connection.
                                         */
                                        --sep->se_count;
-                                       sigprocmask(SIG_SETMASK, &emptymask,
-                                           NULL);
                                        return;
                                }
                                syslog(LOG_ERR,
@@ -1879,13 +1747,11 @@ spawn(struct servtab *sep, int ctrl)
                                if (!sep->se_wait &&
                                    sep->se_socktype == SOCK_STREAM)
                                        close(ctrl);
-                               FD_CLR(sep->se_fd, allsockp);
+                               event_del(&sep->se_event);
                                (void) close(sep->se_fd);
+
                                sep->se_fd = -1;
                                sep->se_count = 0;
-                               nsock--;
-                               sigprocmask(SIG_SETMASK, &emptymask,
-                                   NULL);
                                if (!timingout) {
                                        timingout = 1;
                                        alarm(RETRYTIME);
@@ -1899,16 +1765,13 @@ spawn(struct servtab *sep, int ctrl)
                syslog(LOG_ERR, "fork: %m");
                if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
                        close(ctrl);
-               sigprocmask(SIG_SETMASK, &emptymask, NULL);
                sleep(1);
                return;
        }
        if (pid && sep->se_wait) {
                sep->se_wait = pid;
-               FD_CLR(sep->se_fd, allsockp);
-               nsock--;
+               event_del(&sep->se_event);
        }
-       sigprocmask(SIG_SETMASK, &emptymask, NULL);
        if (pid == 0) {
                if (sep->se_bi)
                        (*sep->se_bi->bi_fn)(ctrl, sep);
@@ -1965,7 +1828,7 @@ spawn(struct servtab *sep, int ctrl)
                        dup2(STDIN_FILENO, STDERR_FILENO);
                        closelog();
                        closefrom(3);
-                       sigaction(SIGPIPE, &sapipe, NULL);
+                       signal(SIGPIPE, SIG_DFL);
                        execv(sep->se_server, sep->se_argv);
                        if (sep->se_socktype != SOCK_STREAM)
                                recv(0, buf, sizeof (buf), 0);

Reply via email to