BSD 4_3_Reno release
[unix-history] / usr / src / usr.sbin / inetd / inetd.c
index 2f2ff70..6973d0c 100644 (file)
@@ -1,18 +1,31 @@
 /*
  * Copyright (c) 1983 Regents of the University of California.
 /*
  * Copyright (c) 1983 Regents of the University of California.
- * All rights reserved.  The Berkeley software License Agreement
- * specifies the terms and conditions for redistribution.
+ * 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.
  */
 
 #ifndef lint
 char copyright[] =
 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  All rights reserved.\n";
  */
 
 #ifndef lint
 char copyright[] =
 "@(#) Copyright (c) 1983 Regents of the University of California.\n\
  All rights reserved.\n";
-#endif not lint
+#endif /* not lint */
 
 #ifndef lint
 
 #ifndef lint
-static char sccsid[] = "@(#)inetd.c    5.8 (Berkeley) %G%";
-#endif not lint
+static char sccsid[] = "@(#)inetd.c    5.25 (Berkeley) 6/29/90";
+#endif /* not lint */
 
 /*
  * Inetd - Internet super-server
 
 /*
  * Inetd - Internet super-server
@@ -45,7 +58,7 @@ static char sccsid[] = "@(#)inetd.c   5.8 (Berkeley) %G%";
  *     wait/nowait                     single-threaded/multi-threaded
  *     user                            user to run daemon as
  *     server program                  full path name
  *     wait/nowait                     single-threaded/multi-threaded
  *     user                            user to run daemon as
  *     server program                  full path name
- *     server program arguments        maximum of MAXARGS (5)
+ *     server program arguments        maximum of MAXARGS (20)
  *
  * Comment lines are indicated by a `#' in column 1.
  */
  *
  * Comment lines are indicated by a `#' in column 1.
  */
@@ -62,11 +75,13 @@ static char sccsid[] = "@(#)inetd.c 5.8 (Berkeley) %G%";
 #include <arpa/inet.h>
 
 #include <errno.h>
 #include <arpa/inet.h>
 
 #include <errno.h>
-#include <stdio.h>
 #include <signal.h>
 #include <netdb.h>
 #include <syslog.h>
 #include <pwd.h>
 #include <signal.h>
 #include <netdb.h>
 #include <syslog.h>
 #include <pwd.h>
+#include <stdio.h>
+#include <string.h>
+#include "pathnames.h"
 
 #define        TOOMANY         40              /* don't start more than TOOMANY */
 #define        CNT_INTVL       60              /* servers in CNT_INTVL sec. */
 
 #define        TOOMANY         40              /* don't start more than TOOMANY */
 #define        CNT_INTVL       60              /* servers in CNT_INTVL sec. */
@@ -76,7 +91,7 @@ static char sccsid[] = "@(#)inetd.c   5.8 (Berkeley) %G%";
 
 extern int errno;
 
 
 extern int errno;
 
-int    reapchild(), retry();
+void   config(), reapchild(), retry();
 char   *index();
 char   *malloc();
 
 char   *index();
 char   *malloc();
 
@@ -96,7 +111,7 @@ struct       servtab {
        char    *se_user;               /* user name to run as */
        struct  biltin *se_bi;          /* if built-in, description */
        char    *se_server;             /* server program */
        char    *se_user;               /* user name to run as */
        struct  biltin *se_bi;          /* if built-in, description */
        char    *se_server;             /* server program */
-#define MAXARGV 5
+#define        MAXARGV 20
        char    *se_argv[MAXARGV+1];    /* program arguments */
        int     se_fd;                  /* open descriptor */
        struct  sockaddr_in se_ctrladdr;/* bound address */
        char    *se_argv[MAXARGV+1];    /* program arguments */
        int     se_fd;                  /* open descriptor */
        struct  sockaddr_in se_ctrladdr;/* bound address */
@@ -139,7 +154,7 @@ struct biltin {
 };
 
 #define NUMINT (sizeof(intab) / sizeof(struct inent))
 };
 
 #define NUMINT (sizeof(intab) / sizeof(struct inent))
-char   *CONFIG = "/etc/inetd.conf";
+char   *CONFIG = _PATH_INETDCONF;
 char   **Argv;
 char   *LastArg;
 
 char   **Argv;
 char   *LastArg;
 
@@ -147,11 +162,14 @@ main(argc, argv, envp)
        int argc;
        char *argv[], *envp[];
 {
        int argc;
        char *argv[], *envp[];
 {
+       extern char *optarg;
+       extern int optind;
        register struct servtab *sep;
        register struct passwd *pwd;
        register struct servtab *sep;
        register struct passwd *pwd;
-       char *cp, buf[50];
-       int pid, i, dofork;
+       register int tmpint;
        struct sigvec sv;
        struct sigvec sv;
+       int ch, pid, dofork;
+       char buf[50];
 
        Argv = argv;
        if (envp == 0 || *envp == 0)
 
        Argv = argv;
        if (envp == 0 || *envp == 0)
@@ -159,42 +177,25 @@ main(argc, argv, envp)
        while (*envp)
                envp++;
        LastArg = envp[-1] + strlen(envp[-1]);
        while (*envp)
                envp++;
        LastArg = envp[-1] + strlen(envp[-1]);
-       argc--, argv++;
-       while (argc > 0 && *argv[0] == '-') {
-               for (cp = &argv[0][1]; *cp; cp++) switch (*cp) {
 
 
+       while ((ch = getopt(argc, argv, "d")) != EOF)
+               switch(ch) {
                case 'd':
                        debug = 1;
                        options |= SO_DEBUG;
                        break;
                case 'd':
                        debug = 1;
                        options |= SO_DEBUG;
                        break;
-
+               case '?':
                default:
                default:
-                       fprintf(stderr,
-                           "inetd: Unknown flag -%c ignored.\n", *cp);
-                       break;
+                       fprintf(stderr, "usage: inetd [-d]");
+                       exit(1);
                }
                }
-nextopt:
-               argc--, argv++;
-       }
+       argc -= optind;
+       argv += optind;
+
        if (argc > 0)
                CONFIG = argv[0];
        if (argc > 0)
                CONFIG = argv[0];
-#ifndef DEBUG
-       if (fork())
-               exit(0);
-       { int s;
-       for (s = 0; s < 10; s++)
-               (void) close(s);
-       }
-       (void) open("/", O_RDONLY);
-       (void) dup2(0, 1);
-       (void) dup2(0, 2);
-       { int tt = open("/dev/tty", O_RDWR);
-         if (tt > 0) {
-               ioctl(tt, TIOCNOTTY, (char *)0);
-               close(tt);
-         }
-       }
-#endif
+       if (debug == 0)
+               daemon(0, 0);
        openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
        bzero((char *)&sv, sizeof(sv));
        sv.sv_mask = SIGBLOCK;
        openlog("inetd", LOG_PID | LOG_NOWAIT, LOG_DAEMON);
        bzero((char *)&sv, sizeof(sv));
        sv.sv_mask = SIGBLOCK;
@@ -206,15 +207,25 @@ nextopt:
        sv.sv_handler = reapchild;
        sigvec(SIGCHLD, &sv, (struct sigvec *)0);
 
        sv.sv_handler = reapchild;
        sigvec(SIGCHLD, &sv, (struct sigvec *)0);
 
+       {
+               /* space for daemons to overwrite environment for ps */
+#define        DUMMYSIZE       100
+               char dummy[DUMMYSIZE];
+
+               (void)memset(dummy, 'x', sizeof(DUMMYSIZE) - 1);
+               dummy[DUMMYSIZE - 1] = '\0';
+               (void)setenv("inetd_dummy", dummy, 1);
+       }
+
        for (;;) {
        for (;;) {
-           int s, ctrl, n;
+           int n, ctrl;
            fd_set readable;
 
            if (nsock == 0) {
                (void) sigblock(SIGBLOCK);
                while (nsock == 0)
            fd_set readable;
 
            if (nsock == 0) {
                (void) sigblock(SIGBLOCK);
                while (nsock == 0)
-                   sigpause(0);
-               (void) sigsetmask(0);
+                   sigpause(0L);
+               (void) sigsetmask(0L);
            }
            readable = allsock;
            if ((n = select(maxsock + 1, &readable, (fd_set *)0,
            }
            readable = allsock;
            if ((n = select(maxsock + 1, &readable, (fd_set *)0,
@@ -229,7 +240,7 @@ nextopt:
                n--;
                if (debug)
                        fprintf(stderr, "someone wants %s\n", sep->se_service);
                n--;
                if (debug)
                        fprintf(stderr, "someone wants %s\n", sep->se_service);
-               if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+               if (sep->se_socktype == SOCK_STREAM) {
                        ctrl = accept(sep->se_fd, (struct sockaddr *)0,
                            (int *)0);
                        if (debug)
                        ctrl = accept(sep->se_fd, (struct sockaddr *)0,
                            (int *)0);
                        if (debug)
@@ -237,7 +248,8 @@ nextopt:
                        if (ctrl < 0) {
                                if (errno == EINTR)
                                        continue;
                        if (ctrl < 0) {
                                if (errno == EINTR)
                                        continue;
-                               syslog(LOG_WARNING, "accept: %m");
+                               syslog(LOG_WARNING, "accept (for %s): %m",
+                                       sep->se_service);
                                continue;
                        }
                } else
                                continue;
                        }
                } else
@@ -266,7 +278,7 @@ nextopt:
                                        sep->se_fd = -1;
                                        sep->se_count = 0;
                                        nsock--;
                                        sep->se_fd = -1;
                                        sep->se_count = 0;
                                        nsock--;
-                                       sigsetmask(0);
+                                       sigsetmask(0L);
                                        if (!timingout) {
                                                timingout = 1;
                                                alarm(RETRYTIME);
                                        if (!timingout) {
                                                timingout = 1;
                                                alarm(RETRYTIME);
@@ -277,9 +289,9 @@ nextopt:
                        pid = fork();
                }
                if (pid < 0) {
                        pid = fork();
                }
                if (pid < 0) {
-                       if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+                       if (sep->se_socktype == SOCK_STREAM)
                                close(ctrl);
                                close(ctrl);
-                       sigsetmask(0);
+                       sigsetmask(0L);
                        sleep(1);
                        continue;
                }
                        sleep(1);
                        continue;
                }
@@ -288,20 +300,14 @@ nextopt:
                        FD_CLR(sep->se_fd, &allsock);
                        nsock--;
                }
                        FD_CLR(sep->se_fd, &allsock);
                        nsock--;
                }
-               sigsetmask(0);
+               sigsetmask(0L);
                if (pid == 0) {
                if (pid == 0) {
-#ifdef DEBUG
-                       int tt;
-
-                       if (dofork && (tt = open("/dev/tty", O_RDWR)) > 0) {
-                               ioctl(tt, TIOCNOTTY, 0);
-                               close(tt);
-                       }
-#endif
+                       if (debug && dofork)
+                               setsid();
                        if (dofork)
                        if (dofork)
-                               for (i = getdtablesize(); --i > 2; )
-                                       if (i != ctrl)
-                                               close(i);
+                               for (tmpint = getdtablesize(); --tmpint > 2; )
+                                       if (tmpint != ctrl)
+                                               close(tmpint);
                        if (sep->se_bi)
                                (*sep->se_bi->bi_fn)(ctrl, sep);
                        else {
                        if (sep->se_bi)
                                (*sep->se_bi->bi_fn)(ctrl, sep);
                        else {
@@ -332,12 +338,13 @@ nextopt:
                                _exit(1);
                        }
                }
                                _exit(1);
                        }
                }
-               if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+               if (sep->se_socktype == SOCK_STREAM)
                        close(ctrl);
            }
        }
 }
 
                        close(ctrl);
            }
        }
 }
 
+void
 reapchild()
 {
        union wait status;
 reapchild()
 {
        union wait status;
@@ -366,11 +373,12 @@ reapchild()
        }
 }
 
        }
 }
 
+void
 config()
 {
        register struct servtab *sep, *cp, **sepp;
        struct servtab *getconfigent(), *enter();
 config()
 {
        register struct servtab *sep, *cp, **sepp;
        struct servtab *getconfigent(), *enter();
-       int omask;
+       long omask;
 
        if (!setconfig()) {
                syslog(LOG_ERR, "%s: %m", CONFIG);
 
        if (!setconfig()) {
                syslog(LOG_ERR, "%s: %m", CONFIG);
@@ -387,7 +395,14 @@ config()
                        int i;
 
                        omask = sigblock(SIGBLOCK);
                        int i;
 
                        omask = sigblock(SIGBLOCK);
-                       if (cp->se_bi == 0)
+                       /*
+                        * sep->se_wait may be holding the pid of a daemon
+                        * that we're waiting for.  If so, don't overwrite
+                        * it unless the config file explicitly says don't 
+                        * wait.
+                        */
+                       if (cp->se_bi == 0 && 
+                           (sep->se_wait == 1 || cp->se_wait == 0))
                                sep->se_wait = cp->se_wait;
 #define SWAP(a, b) { char *c = a; a = b; b = c; }
                        if (cp->se_user)
                                sep->se_wait = cp->se_wait;
 #define SWAP(a, b) { char *c = a; a = b; b = c; }
                        if (cp->se_user)
@@ -446,6 +461,7 @@ config()
        (void) sigsetmask(omask);
 }
 
        (void) sigsetmask(omask);
 }
 
+void
 retry()
 {
        register struct servtab *sep;
 retry()
 {
        register struct servtab *sep;
@@ -499,8 +515,7 @@ enter(cp)
        struct servtab *cp;
 {
        register struct servtab *sep;
        struct servtab *cp;
 {
        register struct servtab *sep;
-       int omask;
-       char *strdup();
+       long omask;
 
        sep = (struct servtab *)malloc(sizeof (*sep));
        if (sep == (struct servtab *)0) {
 
        sep = (struct servtab *)malloc(sizeof (*sep));
        if (sep == (struct servtab *)0) {
@@ -534,19 +549,18 @@ setconfig()
 
 endconfig()
 {
 
 endconfig()
 {
-
-       if (fconfig == NULL)
-               return;
-       fclose(fconfig);
-       fconfig = NULL;
+       if (fconfig) {
+               (void) fclose(fconfig);
+               fconfig = NULL;
+       }
 }
 
 struct servtab *
 getconfigent()
 {
        register struct servtab *sep = &serv;
 }
 
 struct servtab *
 getconfigent()
 {
        register struct servtab *sep = &serv;
-       char *cp, *arg;
        int argc;
        int argc;
+       char *cp, *arg, *strdup();
 
 more:
        while ((cp = nextline(fconfig)) && *cp == '#')
 
 more:
        while ((cp = nextline(fconfig)) && *cp == '#')
@@ -626,10 +640,10 @@ again:
        while (*cp == ' ' || *cp == '\t')
                cp++;
        if (*cp == '\0') {
        while (*cp == ' ' || *cp == '\t')
                cp++;
        if (*cp == '\0') {
-               char c;
+               int c;
 
                c = getc(fconfig);
 
                c = getc(fconfig);
-               ungetc(c, fconfig);
+               (void) ungetc(c, fconfig);
                if (c == ' ' || c == '\t')
                        if (cp = nextline(fconfig))
                                goto again;
                if (c == ' ' || c == '\t')
                        if (cp = nextline(fconfig))
                                goto again;
@@ -672,7 +686,7 @@ strdup(cp)
                syslog(LOG_ERR, "Out of memory.");
                exit(-1);
        }
                syslog(LOG_ERR, "Out of memory.");
                exit(-1);
        }
-       strcpy(new, cp);
+       (void)strcpy(new, cp);
        return (new);
 }
 
        return (new);
 }
 
@@ -688,9 +702,9 @@ setproctitle(a, s)
        cp = Argv[0];
        size = sizeof(sin);
        if (getpeername(s, &sin, &size) == 0)
        cp = Argv[0];
        size = sizeof(sin);
        if (getpeername(s, &sin, &size) == 0)
-               sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
+               (void) sprintf(buf, "-%s [%s]", a, inet_ntoa(sin.sin_addr)); 
        else
        else
-               sprintf(buf, "-%s", a); 
+               (void) sprintf(buf, "-%s", a); 
        strncpy(cp, buf, LastArg - cp);
        cp += strlen(cp);
        while (cp < LastArg)
        strncpy(cp, buf, LastArg - cp);
        cp += strlen(cp);
        while (cp < LastArg)
@@ -700,13 +714,14 @@ setproctitle(a, s)
 /*
  * Internet services provided internally by inetd:
  */
 /*
  * Internet services provided internally by inetd:
  */
+#define        BUFSIZE 4096
 
 /* ARGSUSED */
 echo_stream(s, sep)            /* Echo service -- echo data back */
        int s;
        struct servtab *sep;
 {
 
 /* ARGSUSED */
 echo_stream(s, sep)            /* Echo service -- echo data back */
        int s;
        struct servtab *sep;
 {
-       char buffer[BUFSIZ];
+       char buffer[BUFSIZE];
        int i;
 
        setproctitle(sep->se_service, s);
        int i;
 
        setproctitle(sep->se_service, s);
@@ -721,7 +736,7 @@ echo_dg(s, sep)                     /* Echo service -- echo data back */
        int s;
        struct servtab *sep;
 {
        int s;
        struct servtab *sep;
 {
-       char buffer[BUFSIZ];
+       char buffer[BUFSIZE];
        int i, size;
        struct sockaddr sa;
 
        int i, size;
        struct sockaddr sa;
 
@@ -736,7 +751,7 @@ discard_stream(s, sep)              /* Discard service -- ignore data */
        int s;
        struct servtab *sep;
 {
        int s;
        struct servtab *sep;
 {
-       char buffer[BUFSIZ];
+       char buffer[BUFSIZE];
 
        setproctitle(sep->se_service, s);
        while (1) {
 
        setproctitle(sep->se_service, s);
        while (1) {
@@ -753,7 +768,7 @@ discard_dg(s, sep)          /* Discard service -- ignore data */
        int s;
        struct servtab *sep;
 {
        int s;
        struct servtab *sep;
 {
-       char buffer[BUFSIZ];
+       char buffer[BUFSIZE];
 
        (void) read(s, buffer, sizeof(buffer));
 }
 
        (void) read(s, buffer, sizeof(buffer));
 }
@@ -779,35 +794,29 @@ chargen_stream(s, sep)            /* Character generator */
        int s;
        struct servtab *sep;
 {
        int s;
        struct servtab *sep;
 {
+       register char *rs;
+       int len;
        char text[LINESIZ+2];
        char text[LINESIZ+2];
-       register int i;
-       register char *rp, *rs, *dp;
 
        setproctitle(sep->se_service, s);
 
        setproctitle(sep->se_service, s);
-       if (endring == 0)
+
+       if (!endring) {
                initring();
                initring();
+               rs = ring;
+       }
 
 
-       for (rs = ring; ; ++rs) {
-               if (rs >= endring)
-                       rs = ring;
-               rp = rs;
-               dp = text;
-               i = MIN(LINESIZ, endring - rp);
-               bcopy(rp, dp, i);
-               dp += i;
-               if ((rp += i) >= endring)
-                       rp = ring;
-               if (i < LINESIZ) {
-                       i = LINESIZ - i;
-                       bcopy(rp, dp, i);
-                       dp += i;
-                       if ((rp += i) >= endring)
-                               rp = ring;
+       text[LINESIZ] = '\r';
+       text[LINESIZ + 1] = '\n';
+       for (rs = ring;;) {
+               if ((len = endring - rs) >= LINESIZ)
+                       bcopy(rs, text, LINESIZ);
+               else {
+                       bcopy(rs, text, len);
+                       bcopy(ring, text + len, LINESIZ - len);
                }
                }
-               *dp++ = '\r';
-               *dp++ = '\n';
-
-               if (write(s, text, dp - text) != dp - text)
+               if (++rs == endring)
+                       rs = ring;
+               if (write(s, text, sizeof(text)) != sizeof(text))
                        break;
        }
        exit(0);
                        break;
        }
        exit(0);
@@ -818,34 +827,30 @@ chargen_dg(s, sep)                /* Character generator */
        int s;
        struct servtab *sep;
 {
        int s;
        struct servtab *sep;
 {
-       char text[LINESIZ+2];
-       register int i;
-       register char *rp;
-       static char *rs = ring;
        struct sockaddr sa;
        struct sockaddr sa;
-       int size;
+       static char *rs;
+       int len, size;
+       char text[LINESIZ+2];
 
 
-       if (endring == 0)
+       if (endring == 0) {
                initring();
                initring();
+               rs = ring;
+       }
 
        size = sizeof(sa);
        if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
                return;
 
        size = sizeof(sa);
        if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0)
                return;
-       rp = rs;
-       if (rs++ >= endring)
-               rs = ring;
-       i = MIN(LINESIZ - 2, endring - rp);
-       bcopy(rp, text, i);
-       if ((rp += i) >= endring)
-               rp = ring;
-       if (i < LINESIZ - 2) {
-               bcopy(rp, text, i);
-               if ((rp += i) >= endring)
-                       rp = ring;
-       }
-       text[LINESIZ - 2] = '\r';
-       text[LINESIZ - 1] = '\n';
 
 
+       if ((len = endring - rs) >= LINESIZ)
+               bcopy(rs, text, LINESIZ);
+       else {
+               bcopy(rs, text, len);
+               bcopy(ring, text + len, LINESIZ - len);
+       }
+       if (++rs == endring)
+               rs = ring;
+       text[LINESIZ] = '\r';
+       text[LINESIZ + 1] = '\n';
        (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
 }
 
        (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
 }
 
@@ -907,7 +912,7 @@ daytime_stream(s, sep)              /* Return human-readable time of day */
 
        clock = time((time_t *) 0);
 
 
        clock = time((time_t *) 0);
 
-       sprintf(buffer, "%s\r", ctime(&clock));
+       (void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
        (void) write(s, buffer, strlen(buffer));
 }
 
        (void) write(s, buffer, strlen(buffer));
 }
 
@@ -927,7 +932,7 @@ daytime_dg(s, sep)          /* Return human-readable time of day */
        size = sizeof(sa);
        if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
                return;
        size = sizeof(sa);
        if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0)
                return;
-       sprintf(buffer, "%s\r", ctime(&clock));
+       (void) sprintf(buffer, "%.24s\r\n", ctime(&clock));
        (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
 }
 
        (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
 }
 
@@ -942,5 +947,5 @@ print_service(action, sep)
        fprintf(stderr,
            "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
            action, sep->se_service, sep->se_proto,
        fprintf(stderr,
            "%s: %s proto=%s, wait=%d, user=%s builtin=%x server=%s\n",
            action, sep->se_service, sep->se_proto,
-           sep->se_wait, sep->se_user, sep->se_bi, sep->se_server);
+           sep->se_wait, sep->se_user, (int)sep->se_bi, sep->se_server);
 }
 }