wget: don't be careless with xstrdup'ing
[oweals/busybox.git] / networking / inetd.c
index d6265d8755f77af91dea01580cc95d485bf9427f..e22115a5cb3c6b24c9ed9f69bfd7f2b401eefafd 100644 (file)
@@ -183,8 +183,7 @@ static struct rlimit rlim_ofile;
 # define INETD_SETPROCTITLE
 #endif
 
-typedef struct servtab
-{
+typedef struct servtab {
        char *se_hostaddr;                    /* host address to listen on */
        char *se_service;                     /* name of service */
        int se_socktype;                      /* type of socket to use */
@@ -209,8 +208,7 @@ typedef struct servtab
 #define MAXARGV 20
        char *se_argv[MAXARGV + 1];           /* program arguments */
        int se_fd;                            /* open descriptor */
-       union
-       {
+       union {
                struct sockaddr se_un_ctrladdr;
                struct sockaddr_in se_un_ctrladdr_in;
 #ifdef CONFIG_FEATURE_IPV6
@@ -232,8 +230,7 @@ typedef struct servtab
 static servtab_t *servtab;
 
 #ifdef INETD_FEATURE_ENABLED
-struct builtin
-{
+struct builtin {
        const char *bi_service;               /* internally provided service name */
        int bi_socktype;                      /* type of socket supported */
        short bi_fork;                        /* 1 if should fork before call */
@@ -427,7 +424,8 @@ static void setup(servtab_t *sep)
        int on = 1;
        int r;
 
-       if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) {
+       sep->se_fd = socket(sep->se_family, sep->se_socktype, 0);
+       if (sep->se_fd < 0) {
                bb_perror_msg("%s/%s: socket", sep->se_service, sep->se_proto);
                return;
        }
@@ -1253,9 +1251,9 @@ inetd_main(int argc, char *argv[])
        LastArg = envp[-1] + strlen(envp[-1]);
 #endif
 
-       openlog(bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
+       openlog(applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
 
-       opt = bb_getopt_ulflags(argc, argv, "R:f", &stoomany);
+       opt = getopt32(argc, argv, "R:f", &stoomany);
        if(opt & 1) {
                char *e;
 
@@ -1355,7 +1353,7 @@ inetd_main(int argc, char *argv[])
                }
 
                readable = allsock;
-               n = select(maxsock + 1, &readable, NULL, NULL, NULL)
+               n = select(maxsock + 1, &readable, NULL, NULL, NULL);
                if (n <= 0) {
                        if (n < 0 && errno != EINTR) {
                                bb_perror_msg("select");
@@ -1363,154 +1361,154 @@ inetd_main(int argc, char *argv[])
                        }
                        continue;
                }
+
                for (sep = servtab; n && sep; sep = sep->se_next) {
-                       // TODO: undo this unholy mess
-                       if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
-                               n--;
-                               if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
-                                       ctrl = accept(sep->se_fd, NULL, NULL);
-                                       if (ctrl < 0) {
-                                               if (errno == EINTR)
-                                                       continue;
-                                               bb_perror_msg("accept (for %s)", sep->se_service);
+                       if (sep->se_fd == -1 || !FD_ISSET(sep->se_fd, &readable))
+                               continue;
+
+                       n--;
+                       if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+                               ctrl = accept(sep->se_fd, NULL, NULL);
+                               if (ctrl < 0) {
+                                       if (errno == EINTR)
+                                               continue;
+                                       bb_perror_msg("accept (for %s)", sep->se_service);
+                                       continue;
+                               }
+                               if (sep->se_family == AF_INET && sep->se_socktype == SOCK_STREAM) {
+                                       struct sockaddr_in peer;
+                                       socklen_t plen = sizeof(peer);
+
+                                       if (getpeername(ctrl, (struct sockaddr *) &peer, &plen) < 0) {
+                                               bb_error_msg("could not getpeername");
+                                               close(ctrl);
                                                continue;
                                        }
-                                       if (sep->se_family == AF_INET && sep->se_socktype == SOCK_STREAM) {
-                                               struct sockaddr_in peer;
-                                               socklen_t plen = sizeof(peer);
+                                       if (ntohs(peer.sin_port) == 20) {
+                                               /* XXX ftp bounce */
+                                               close(ctrl);
+                                               continue;
+                                       }
+                               }
+                       } else
+                               ctrl = sep->se_fd;
 
-                                               if (getpeername(ctrl, (struct sockaddr *) &peer, &plen) < 0) {
-                                                       bb_error_msg("could not getpeername");
+                       Block_Using_Signals(omask);
+                       pid = 0;
+#ifdef INETD_FEATURE_ENABLED
+                       if (sep->se_bi == 0 || sep->se_bi->bi_fork)
+#endif
+                       {
+                               if (sep->se_count++ == 0)
+                                       (void) gettimeofday(&sep->se_time, NULL);
+                               else if (toomany > 0 && sep->se_count >= sep->se_max) {
+                                       struct timeval now;
+
+                                       (void) gettimeofday(&now, NULL);
+                                       if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
+                                               sep->se_time = now;
+                                               sep->se_count = 1;
+                                       } else {
+                                               if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
                                                        close(ctrl);
+                                               if (sep->se_family == AF_INET &&
+                                                         ntohs(sep->se_ctrladdr_in.sin_port) >= IPPORT_RESERVED) {
+                                                       /*
+                                                        * Cannot close it -- there are
+                                                        * thieves on the system.
+                                                        * Simply ignore the connection.
+                                                        */
+                                                       --sep->se_count;
                                                        continue;
                                                }
-                                               if (ntohs(peer.sin_port) == 20) {
-                                                       /* XXX ftp bounce */
+                                               bb_error_msg("%s/%s server failing (looping), service terminated",
+                                                             sep->se_service, sep->se_proto);
+                                               if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
                                                        close(ctrl);
-                                                       continue;
-                                               }
-                                       }
-                               } else
-                                       ctrl = sep->se_fd;
-                               Block_Using_Signals(omask);
-                               pid = 0;
-#ifdef INETD_FEATURE_ENABLED
-                               if (sep->se_bi == 0 || sep->se_bi->bi_fork)
-#endif
-                               {
-                                       if (sep->se_count++ == 0)
-                                               (void) gettimeofday(&sep->se_time, NULL);
-                                       else if (toomany > 0 && sep->se_count >= sep->se_max) {
-                                               struct timeval now;
-
-                                               (void) gettimeofday(&now, NULL);
-                                               if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
-                                                       sep->se_time = now;
-                                                       sep->se_count = 1;
-                                               } else {
-                                                       if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
-                                                               close(ctrl);
-                                                       if (sep->se_family == AF_INET &&
-                                                                 ntohs(sep->se_ctrladdr_in.sin_port) >= IPPORT_RESERVED) {
-                                                               /*
-                                                                * Cannot close it -- there are
-                                                                * thieves on the system.
-                                                                * Simply ignore the connection.
-                                                                */
-                                                               --sep->se_count;
-                                                               continue;
-                                                       }
-                                                       bb_error_msg("%s/%s server failing (looping), service terminated",
-                                                                     sep->se_service, sep->se_proto);
-                                                       if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
-                                                               close(ctrl);
-                                                       FD_CLR(sep->se_fd, &allsock);
-                                                       (void) close(sep->se_fd);
-                                                       sep->se_fd = -1;
-                                                       sep->se_count = 0;
-                                                       nsock--;
-                                                       sigprocmask(SIG_UNBLOCK, &omask, NULL);
-                                                       if (!timingout) {
-                                                               timingout = 1;
-                                                               alarm(RETRYTIME);
-                                                       }
-                                                       continue;
+                                               FD_CLR(sep->se_fd, &allsock);
+                                               (void) close(sep->se_fd);
+                                               sep->se_fd = -1;
+                                               sep->se_count = 0;
+                                               nsock--;
+                                               sigprocmask(SIG_UNBLOCK, &omask, NULL);
+                                               if (!timingout) {
+                                                       timingout = 1;
+                                                       alarm(RETRYTIME);
                                                }
+                                               continue;
                                        }
-                                       pid = fork();
-                               }
-                               if (pid < 0) {
-                                       bb_perror_msg("fork");
-                                       if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
-                                               close(ctrl);
-                                       sigprocmask(SIG_UNBLOCK, &omask, NULL);
-                                       sleep(1);
-                                       continue;
-                               }
-                               if (pid && sep->se_wait) {
-                                       sep->se_wait = pid;
-                                       FD_CLR(sep->se_fd, &allsock);
-                                       nsock--;
                                }
+                               pid = fork();
+                       }
+                       if (pid < 0) {
+                               bb_perror_msg("fork");
+                               if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+                                       close(ctrl);
                                sigprocmask(SIG_UNBLOCK, &omask, NULL);
-                               if (pid == 0) {
+                               sleep(1);
+                               continue;
+                       }
+                       if (pid && sep->se_wait) {
+                               sep->se_wait = pid;
+                               FD_CLR(sep->se_fd, &allsock);
+                               nsock--;
+                       }
+                       sigprocmask(SIG_UNBLOCK, &omask, NULL);
+                       if (pid == 0) {
 #ifdef INETD_FEATURE_ENABLED
-                                       if (sep->se_bi) {
-                                               (*sep->se_bi->bi_fn)(ctrl, sep);
-                                       } else
+                               if (sep->se_bi) {
+                                       (*sep->se_bi->bi_fn)(ctrl, sep);
+                               } else
 #endif
-                                               {
-                                               if ((pwd = getpwnam(sep->se_user)) == NULL) {
-                                                       bb_error_msg("getpwnam: %s: no such user", sep->se_user);
-                                                       if (sep->se_socktype != SOCK_STREAM)
-                                                               recv(0, buf, sizeof(buf), 0);
-                                                       _exit(1);
-                                               }
-                                               if (setsid() < 0)
-                                                       bb_perror_msg("%s: setsid", sep->se_service);
-                                               if (sep->se_group && (grp = getgrnam(sep->se_group)) == NULL) {
-                                                       bb_error_msg("getgrnam: %s: no such group", sep->se_group);
-                                                       if (sep->se_socktype != SOCK_STREAM)
-                                                               recv(0, buf, sizeof(buf), 0);
+                                       {
+                                       pwd = getpwnam(sep->se_user);
+                                       if (pwd == NULL) {
+                                               bb_error_msg("getpwnam: %s: no such user", sep->se_user);
+                                               goto do_exit1;
+                                       }
+                                       if (setsid() < 0)
+                                               bb_perror_msg("%s: setsid", sep->se_service);
+                                       if (sep->se_group && (grp = getgrnam(sep->se_group)) == NULL) {
+                                               bb_error_msg("getgrnam: %s: no such group", sep->se_group);
+                                               goto do_exit1;
+                                       }
+                                       if (uid != 0) {
+                                               /* a user running private inetd */
+                                               if (uid != pwd->pw_uid)
                                                        _exit(1);
-                                               }
-                                               if (uid != 0) {
-                                                       /* a user running private inetd */
-                                                       if (uid != pwd->pw_uid)
-                                                               _exit(1);
-                                               } else if (pwd->pw_uid) {
-                                                       if (sep->se_group)
-                                                               pwd->pw_gid = grp->gr_gid;
-                                                       xsetgid((gid_t) pwd->pw_gid);
-                                                       initgroups(pwd->pw_name, pwd->pw_gid);
-                                                       xsetuid((uid_t) pwd->pw_uid);
-                                               } else if (sep->se_group) {
-                                                       xsetgid(grp->gr_gid);
-                                                       setgroups(1, &grp->gr_gid);
-                                               }
-                                               dup2(ctrl, 0);
-                                               close(ctrl);
-                                               dup2(0, 1);
-                                               dup2(0, 2);
-                                               if (rlim_ofile.rlim_cur != rlim_ofile_cur)
-                                                       if (setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0)
-                                                               bb_perror_msg("setrlimit");
-                                               closelog();
-                                               for (tmpint = rlim_ofile_cur - 1; --tmpint > 2;)
-                                                       (void) close(tmpint);
-                                               sigaction(SIGPIPE, &sapipe, NULL);
-                                               execv(sep->se_server, sep->se_argv);
-                                               if (sep->se_socktype != SOCK_STREAM)
-                                                       recv(0, buf, sizeof(buf), 0);
-                                               bb_perror_msg("execv %s", sep->se_server);
-                                               _exit(1);
+                                       } else if (pwd->pw_uid) {
+                                               if (sep->se_group)
+                                                       pwd->pw_gid = grp->gr_gid;
+                                               xsetgid((gid_t) pwd->pw_gid);
+                                               initgroups(pwd->pw_name, pwd->pw_gid);
+                                               xsetuid((uid_t) pwd->pw_uid);
+                                       } else if (sep->se_group) {
+                                               xsetgid(grp->gr_gid);
+                                               setgroups(1, &grp->gr_gid);
                                        }
+                                       dup2(ctrl, 0);
+                                       if (ctrl) close(ctrl);
+                                       dup2(0, 1);
+                                       dup2(0, 2);
+                                       if (rlim_ofile.rlim_cur != rlim_ofile_cur)
+                                               if (setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0)
+                                                       bb_perror_msg("setrlimit");
+                                       closelog();
+                                       for (tmpint = rlim_ofile_cur - 1; --tmpint > 2;)
+                                               (void) close(tmpint);
+                                       sigaction(SIGPIPE, &sapipe, NULL);
+                                       execv(sep->se_server, sep->se_argv);
+                                       bb_perror_msg("execv %s", sep->se_server);
+do_exit1:
+                                       if (sep->se_socktype != SOCK_STREAM)
+                                               recv(0, buf, sizeof(buf), 0);
+                                       _exit(1);
                                }
-                               if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
-                                       close(ctrl);
                        }
-               }
-       }
+                       if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
+                               close(ctrl);
+               } /* for (sep = servtab...) */
+       } /* for(;;) */
 }
 
 /*
@@ -1542,8 +1540,12 @@ echo_stream(int s, servtab_t *sep)
        int i;
 
        inetd_setproctitle(sep->se_service, s);
-       while ((i = read(s, buffer, sizeof(buffer))) > 0 &&
-                                write(s, buffer, i) > 0);
+       while (1) {
+               i = read(s, buffer, sizeof(buffer));
+               if (i <= 0) break;
+               /* FIXME: this isnt correct - safe_write()? */
+               if (write(s, buffer, i) <= 0) break;
+       }
        exit(0);
 }
 
@@ -1577,9 +1579,11 @@ discard_stream(int s, servtab_t *sep)
        char buffer[BUFSIZE];
 
        inetd_setproctitle(sep->se_service, s);
-       while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) ||
-                                errno == EINTR);
-       exit(0);
+       while (1) {
+               errno = 0;
+               if (read(s, buffer, sizeof(buffer)) <= 0 && errno != EINTR)
+                       exit(0);
+       }
 }
 
 /* Discard service -- ignore data */
@@ -1629,8 +1633,10 @@ chargen_stream(int s, servtab_t *sep)
 
        text[LINESIZ] = '\r';
        text[LINESIZ + 1] = '\n';
-       for (rs = ring;;) {
-               if ((len = endring - rs) >= LINESIZ)
+       rs = ring;
+       for (;;) {
+               len = endring - rs;
+               if (len >= LINESIZ)
                        memmove(text, rs, LINESIZ);
                else {
                        memmove(text, rs, len);