BSD 4_3_Net_2 release
[unix-history] / usr / src / usr.sbin / inetd / inetd.c
index 6973d0c..0340273 100644 (file)
@@ -1,20 +1,34 @@
 /*
 /*
- * Copyright (c) 1983 Regents of the University of California.
+ * Copyright (c) 1983,1991 The Regents of the University of California.
  * All rights reserved.
  *
  * All rights reserved.
  *
- * Redistribution and use in source and binary forms are permitted provided
- * that: (1) source distributions retain this entire copyright notice and
- * comment, and (2) distributions including binaries display the following
- * acknowledgement:  ``This product includes software developed by the
- * University of California, Berkeley and its contributors'' in the
- * documentation or other materials provided with the distribution and in
- * all advertising materials mentioning features or use of this software.
- * 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 ``AS IS'' AND WITHOUT ANY EXPRESS OR IMPLIED
- * WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTIES OF
- * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
+ * 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
@@ -24,7 +38,7 @@ char copyright[] =
 #endif /* not lint */
 
 #ifndef lint
 #endif /* not lint */
 
 #ifndef lint
-static char sccsid[] = "@(#)inetd.c    5.25 (Berkeley) 6/29/90";
+static char sccsid[] = "@(#)inetd.c    5.30 (Berkeley) 6/3/91";
 #endif /* not lint */
 
 /*
 #endif /* not lint */
 
 /*
@@ -236,32 +250,33 @@ main(argc, argv, envp)
                    continue;
            }
            for (sep = servtab; n && sep; sep = sep->se_next)
                    continue;
            }
            for (sep = servtab; n && sep; sep = sep->se_next)
-           if (FD_ISSET(sep->se_fd, &readable)) {
-               n--;
-               if (debug)
-                       fprintf(stderr, "someone wants %s\n", sep->se_service);
-               if (sep->se_socktype == SOCK_STREAM) {
-                       ctrl = accept(sep->se_fd, (struct sockaddr *)0,
-                           (int *)0);
-                       if (debug)
-                               fprintf(stderr, "accept, ctrl %d\n", ctrl);
-                       if (ctrl < 0) {
-                               if (errno == EINTR)
-                                       continue;
-                               syslog(LOG_WARNING, "accept (for %s): %m",
-                                       sep->se_service);
-                               continue;
-                       }
-               } else
-                       ctrl = sep->se_fd;
-               (void) sigblock(SIGBLOCK);
-               pid = 0;
-               dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
-               if (dofork) {
-                       if (sep->se_count++ == 0)
-                           (void)gettimeofday(&sep->se_time,
-                               (struct timezone *)0);
-                       else if (sep->se_count >= TOOMANY) {
+               if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
+                   n--;
+                   if (debug)
+                           fprintf(stderr, "someone wants %s\n",
+                               sep->se_service);
+                   if (sep->se_socktype == SOCK_STREAM) {
+                           ctrl = accept(sep->se_fd, (struct sockaddr *)0,
+                               (int *)0);
+                           if (debug)
+                                   fprintf(stderr, "accept, ctrl %d\n", ctrl);
+                           if (ctrl < 0) {
+                                   if (errno == EINTR)
+                                           continue;
+                                   syslog(LOG_WARNING, "accept (for %s): %m",
+                                           sep->se_service);
+                                   continue;
+                           }
+                   } else
+                           ctrl = sep->se_fd;
+                   (void) sigblock(SIGBLOCK);
+                   pid = 0;
+                   dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
+                   if (dofork) {
+                           if (sep->se_count++ == 0)
+                               (void)gettimeofday(&sep->se_time,
+                                   (struct timezone *)0);
+                           else if (sep->se_count >= TOOMANY) {
                                struct timeval now;
 
                                (void)gettimeofday(&now, (struct timezone *)0);
                                struct timeval now;
 
                                (void)gettimeofday(&now, (struct timezone *)0);
@@ -278,47 +293,51 @@ main(argc, argv, envp)
                                        sep->se_fd = -1;
                                        sep->se_count = 0;
                                        nsock--;
                                        sep->se_fd = -1;
                                        sep->se_count = 0;
                                        nsock--;
-                                       sigsetmask(0L);
                                        if (!timingout) {
                                                timingout = 1;
                                                alarm(RETRYTIME);
                                        }
                                        if (!timingout) {
                                                timingout = 1;
                                                alarm(RETRYTIME);
                                        }
-                                       continue;
                                }
                                }
-                       }
-                       pid = fork();
-               }
-               if (pid < 0) {
-                       if (sep->se_socktype == SOCK_STREAM)
-                               close(ctrl);
-                       sigsetmask(0L);
-                       sleep(1);
-                       continue;
-               }
-               if (pid && sep->se_wait) {
-                       sep->se_wait = pid;
-                       FD_CLR(sep->se_fd, &allsock);
-                       nsock--;
-               }
-               sigsetmask(0L);
-               if (pid == 0) {
-                       if (debug && dofork)
+                           }
+                           pid = fork();
+                   }
+                   if (pid < 0) {
+                           syslog(LOG_ERR, "fork: %m");
+                           if (sep->se_socktype == SOCK_STREAM)
+                                   close(ctrl);
+                           sigsetmask(0L);
+                           sleep(1);
+                           continue;
+                   }
+                   if (pid && sep->se_wait) {
+                           sep->se_wait = pid;
+                           if (sep->se_fd >= 0) {
+                               FD_CLR(sep->se_fd, &allsock);
+                               nsock--;
+                           }
+                   }
+                   sigsetmask(0L);
+                   if (pid == 0) {
+                           if (debug && dofork)
                                setsid();
                                setsid();
-                       if (dofork)
-                               for (tmpint = getdtablesize(); --tmpint > 2; )
+                           if (dofork)
+                               for (tmpint = maxsock; --tmpint > 2; )
                                        if (tmpint != ctrl)
                                                close(tmpint);
                                        if (tmpint != ctrl)
                                                close(tmpint);
-                       if (sep->se_bi)
+                           if (sep->se_bi)
                                (*sep->se_bi->bi_fn)(ctrl, sep);
                                (*sep->se_bi->bi_fn)(ctrl, sep);
-                       else {
+                           else {
+                               if (debug)
+                                       fprintf(stderr, "%d execl %s\n",
+                                           getpid(), sep->se_server);
                                dup2(ctrl, 0);
                                close(ctrl);
                                dup2(0, 1);
                                dup2(0, 2);
                                if ((pwd = getpwnam(sep->se_user)) == NULL) {
                                        syslog(LOG_ERR,
                                dup2(ctrl, 0);
                                close(ctrl);
                                dup2(0, 1);
                                dup2(0, 2);
                                if ((pwd = getpwnam(sep->se_user)) == NULL) {
                                        syslog(LOG_ERR,
-                                               "getpwnam: %s: No such user",
-                                               sep->se_user);
+                                           "getpwnam: %s: No such user",
+                                           sep->se_user);
                                        if (sep->se_socktype != SOCK_STREAM)
                                                recv(0, buf, sizeof (buf), 0);
                                        _exit(1);
                                        if (sep->se_socktype != SOCK_STREAM)
                                                recv(0, buf, sizeof (buf), 0);
                                        _exit(1);
@@ -328,26 +347,23 @@ main(argc, argv, envp)
                                        initgroups(pwd->pw_name, pwd->pw_gid);
                                        (void) setuid((uid_t)pwd->pw_uid);
                                }
                                        initgroups(pwd->pw_name, pwd->pw_gid);
                                        (void) setuid((uid_t)pwd->pw_uid);
                                }
-                               if (debug)
-                                       fprintf(stderr, "%d execl %s\n",
-                                           getpid(), sep->se_server);
                                execv(sep->se_server, sep->se_argv);
                                if (sep->se_socktype != SOCK_STREAM)
                                        recv(0, buf, sizeof (buf), 0);
                                syslog(LOG_ERR, "execv %s: %m", sep->se_server);
                                _exit(1);
                                execv(sep->se_server, sep->se_argv);
                                if (sep->se_socktype != SOCK_STREAM)
                                        recv(0, buf, sizeof (buf), 0);
                                syslog(LOG_ERR, "execv %s: %m", sep->se_server);
                                _exit(1);
-                       }
+                           }
+                   }
+                   if (sep->se_socktype == SOCK_STREAM)
+                           close(ctrl);
                }
                }
-               if (sep->se_socktype == SOCK_STREAM)
-                       close(ctrl);
-           }
        }
 }
 
 void
 reapchild()
 {
        }
 }
 
 void
 reapchild()
 {
-       union wait status;
+       int status;
        int pid;
        register struct servtab *sep;
 
        int pid;
        register struct servtab *sep;
 
@@ -359,7 +375,7 @@ reapchild()
                        fprintf(stderr, "%d reaped\n", pid);
                for (sep = servtab; sep; sep = sep->se_next)
                        if (sep->se_wait == pid) {
                        fprintf(stderr, "%d reaped\n", pid);
                for (sep = servtab; sep; sep = sep->se_next)
                        if (sep->se_wait == pid) {
-                               if (status.w_status)
+                               if (status)
                                        syslog(LOG_WARNING,
                                            "%s: exit status 0x%x",
                                            sep->se_server, status);
                                        syslog(LOG_WARNING,
                                            "%s: exit status 0x%x",
                                            sep->se_server, status);
@@ -425,6 +441,9 @@ config()
                if (sp == 0) {
                        syslog(LOG_ERR, "%s/%s: unknown service",
                            sep->se_service, sep->se_proto);
                if (sp == 0) {
                        syslog(LOG_ERR, "%s/%s: unknown service",
                            sep->se_service, sep->se_proto);
+                       if (sep->se_fd != -1)
+                               (void) close(sep->se_fd);
+                       sep->se_fd = -1;
                        continue;
                }
                if (sp->s_port != sep->se_ctrladdr.sin_port) {
                        continue;
                }
                if (sp->s_port != sep->se_ctrladdr.sin_port) {
@@ -490,7 +509,7 @@ setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on))
        if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
                syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
 #undef turnon
        if (turnon(sep->se_fd, SO_REUSEADDR) < 0)
                syslog(LOG_ERR, "setsockopt (SO_REUSEADDR): %m");
 #undef turnon
-       if (bind(sep->se_fd, &sep->se_ctrladdr,
+       if (bind(sep->se_fd, (struct sockaddr *)&sep->se_ctrladdr,
            sizeof (sep->se_ctrladdr)) < 0) {
                syslog(LOG_ERR, "%s/%s: bind: %m",
                    sep->se_service, sep->se_proto);
            sizeof (sep->se_ctrladdr)) < 0) {
                syslog(LOG_ERR, "%s/%s: bind: %m",
                    sep->se_service, sep->se_proto);
@@ -560,14 +579,14 @@ getconfigent()
 {
        register struct servtab *sep = &serv;
        int argc;
 {
        register struct servtab *sep = &serv;
        int argc;
-       char *cp, *arg, *strdup();
+       char *cp, *arg, *newstr();
 
 more:
        while ((cp = nextline(fconfig)) && *cp == '#')
                ;
        if (cp == NULL)
                return ((struct servtab *)0);
 
 more:
        while ((cp = nextline(fconfig)) && *cp == '#')
                ;
        if (cp == NULL)
                return ((struct servtab *)0);
-       sep->se_service = strdup(skip(&cp));
+       sep->se_service = newstr(skip(&cp));
        arg = skip(&cp);
        if (strcmp(arg, "stream") == 0)
                sep->se_socktype = SOCK_STREAM;
        arg = skip(&cp);
        if (strcmp(arg, "stream") == 0)
                sep->se_socktype = SOCK_STREAM;
@@ -581,11 +600,11 @@ more:
                sep->se_socktype = SOCK_RAW;
        else
                sep->se_socktype = -1;
                sep->se_socktype = SOCK_RAW;
        else
                sep->se_socktype = -1;
-       sep->se_proto = strdup(skip(&cp));
+       sep->se_proto = newstr(skip(&cp));
        arg = skip(&cp);
        sep->se_wait = strcmp(arg, "wait") == 0;
        arg = skip(&cp);
        sep->se_wait = strcmp(arg, "wait") == 0;
-       sep->se_user = strdup(skip(&cp));
-       sep->se_server = strdup(skip(&cp));
+       sep->se_user = newstr(skip(&cp));
+       sep->se_server = newstr(skip(&cp));
        if (strcmp(sep->se_server, "internal") == 0) {
                register struct biltin *bi;
 
        if (strcmp(sep->se_server, "internal") == 0) {
                register struct biltin *bi;
 
@@ -605,7 +624,7 @@ more:
        argc = 0;
        for (arg = skip(&cp); cp; arg = skip(&cp))
                if (argc < MAXARGV)
        argc = 0;
        for (arg = skip(&cp); cp; arg = skip(&cp))
                if (argc < MAXARGV)
-                       sep->se_argv[argc++] = strdup(arg);
+                       sep->se_argv[argc++] = newstr(arg);
        while (argc <= MAXARGV)
                sep->se_argv[argc++] = NULL;
        return (sep);
        while (argc <= MAXARGV)
                sep->se_argv[argc++] = NULL;
        return (sep);
@@ -674,20 +693,13 @@ nextline(fd)
 }
 
 char *
 }
 
 char *
-strdup(cp)
+newstr(cp)
        char *cp;
 {
        char *cp;
 {
-       char *new;
-
-       if (cp == NULL)
-               cp = "";
-       new = malloc((unsigned)(strlen(cp) + 1));
-       if (new == (char *)0) {
-               syslog(LOG_ERR, "Out of memory.");
-               exit(-1);
-       }
-       (void)strcpy(new, cp);
-       return (new);
+       if (cp = strdup(cp ? cp : ""))
+               return(cp);
+       syslog(LOG_ERR, "strdup: %m");
+       exit(-1);
 }
 
 setproctitle(a, s)
 }
 
 setproctitle(a, s)
@@ -701,7 +713,7 @@ setproctitle(a, s)
 
        cp = Argv[0];
        size = sizeof(sin);
 
        cp = Argv[0];
        size = sizeof(sin);
-       if (getpeername(s, &sin, &size) == 0)
+       if (getpeername(s, (struct sockaddr *)&sin, &size) == 0)
                (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
        else
                (void) sprintf(buf, "-%s", a); 
                (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
        else
                (void) sprintf(buf, "-%s", a); 
@@ -714,7 +726,7 @@ setproctitle(a, s)
 /*
  * Internet services provided internally by inetd:
  */
 /*
  * Internet services provided internally by inetd:
  */
-#define        BUFSIZE 4096
+#define        BUFSIZE 8192
 
 /* ARGSUSED */
 echo_stream(s, sep)            /* Echo service -- echo data back */
 
 /* ARGSUSED */
 echo_stream(s, sep)            /* Echo service -- echo data back */
@@ -751,13 +763,14 @@ discard_stream(s, sep)            /* Discard service -- ignore data */
        int s;
        struct servtab *sep;
 {
        int s;
        struct servtab *sep;
 {
+       int ret;
        char buffer[BUFSIZE];
 
        setproctitle(sep->se_service, s);
        while (1) {
        char buffer[BUFSIZE];
 
        setproctitle(sep->se_service, s);
        while (1) {
-               while (read(s, buffer, sizeof(buffer)) > 0)
+               while ((ret = read(s, buffer, sizeof(buffer))) > 0)
                        ;
                        ;
-               if (errno != EINTR)
+               if (ret == 0 || errno != EINTR)
                        break;
        }
        exit(0);
                        break;
        }
        exit(0);