+ rlim_ofile_cur = rl.rlim_cur;
+ return 0;
+}
+
+static void setup(servtab_t *sep)
+{
+ int r;
+
+ 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;
+ }
+ if (setsockopt_reuseaddr(sep->se_fd) < 0)
+ bb_perror_msg("setsockopt(SO_REUSEADDR)");
+
+#if ENABLE_FEATURE_INETD_RPC
+ if (isrpcservice(sep)) {
+ struct passwd *pwd;
+
+ /*
+ * for RPC services, attempt to use a reserved port
+ * if they are going to be running as root.
+ *
+ * Also, zero out the port for all RPC services; let bind()
+ * find one.
+ */
+ sep->se_ctrladdr_in.sin_port = 0;
+ if (sep->se_user && (pwd = getpwnam(sep->se_user)) &&
+ pwd->pw_uid == 0 && uid == 0)
+ r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in);
+ else {
+ r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size);
+ if (r == 0) {
+ socklen_t len = sep->se_ctrladdr_size;
+ int saveerrno = errno;
+
+ /* update se_ctrladdr_in.sin_port */
+ r = getsockname(sep->se_fd, &sep->se_ctrladdr, &len);
+ if (r <= 0)
+ errno = saveerrno;
+ }
+ }
+ } else
+#endif
+ r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size);
+ if (r < 0) {
+ bb_perror_msg("%s/%s (%d): bind",
+ sep->se_service, sep->se_proto, sep->se_ctrladdr.sa_family);
+ close(sep->se_fd);
+ sep->se_fd = -1;
+ if (!timingout) {
+ timingout = 1;
+ alarm(RETRYTIME);
+ }
+ return;
+ }
+ if (sep->se_socktype == SOCK_STREAM)
+ listen(sep->se_fd, global_queuelen);
+
+ FD_SET(sep->se_fd, &allsock);
+ nsock++;
+ if (sep->se_fd > maxsock) {
+ maxsock = sep->se_fd;
+ if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN)
+ bump_nofile();
+ }
+}
+
+static char *nextline(void)
+{
+#define line bb_common_bufsiz1
+
+ char *cp;
+ FILE *fd = fconfig;
+
+ if (fgets(line, sizeof(line), fd) == NULL)
+ return NULL;
+ cp = strchr(line, '\n');
+ if (cp)
+ *cp = '\0';
+ return line;
+}
+
+static char *skip(char **cpp) /* int report; */
+{
+ char *cp = *cpp;
+ char *start;
+
+/* erp: */
+ if (*cpp == NULL) {
+ /* if (report) */
+ /* bb_error_msg("syntax error in inetd config file"); */
+ return NULL;
+ }
+
+ again:
+ while (*cp == ' ' || *cp == '\t')
+ cp++;
+ if (*cp == '\0') {
+ int c;
+
+ c = getc(fconfig);
+ ungetc(c, fconfig);
+ if (c == ' ' || c == '\t') {
+ cp = nextline();
+ if (cp)
+ goto again;
+ }
+ *cpp = NULL;
+ /* goto erp; */
+ return NULL;
+ }
+ start = cp;
+ while (*cp && *cp != ' ' && *cp != '\t')
+ cp++;
+ if (*cp != '\0')
+ *cp++ = '\0';
+ /* if ((*cpp = cp) == NULL) */
+ /* goto erp; */
+
+ *cpp = cp;
+ return start;
+}
+
+static servtab_t *new_servtab(void)
+{
+ return xmalloc(sizeof(servtab_t));
+}
+
+static servtab_t *dupconfig(servtab_t *sep)
+{
+ servtab_t *newtab;
+ int argc;
+
+ newtab = new_servtab();
+ memset(newtab, 0, sizeof(servtab_t));
+ newtab->se_service = xstrdup(sep->se_service);
+ newtab->se_socktype = sep->se_socktype;
+ newtab->se_family = sep->se_family;
+ newtab->se_proto = xstrdup(sep->se_proto);
+#if ENABLE_FEATURE_INETD_RPC
+ newtab->se_rpcprog = sep->se_rpcprog;
+ newtab->se_rpcversl = sep->se_rpcversl;
+ newtab->se_rpcversh = sep->se_rpcversh;
+#endif
+ newtab->se_wait = sep->se_wait;
+ newtab->se_user = xstrdup(sep->se_user);
+ newtab->se_group = xstrdup(sep->se_group);
+#ifdef INETD_FEATURE_ENABLED
+ newtab->se_bi = sep->se_bi;
+#endif
+ newtab->se_server = xstrdup(sep->se_server);
+
+ for (argc = 0; argc <= MAXARGV; argc++)
+ newtab->se_argv[argc] = xstrdup(sep->se_argv[argc]);
+ newtab->se_max = sep->se_max;
+
+ return newtab;
+}
+
+static servtab_t *getconfigent(void)
+{
+ servtab_t *sep;
+ int argc;
+ char *cp, *arg;
+ char *hostdelim;
+ servtab_t *nsep;
+ servtab_t *psep;
+
+ sep = new_servtab();
+
+ /* memset(sep, 0, sizeof *sep); */
+ more:
+ /* freeconfig(sep); */
+
+ while ((cp = nextline()) && *cp == '#') /* skip comment line */;
+ if (cp == NULL) {
+ /* free(sep); */
+ return NULL;
+ }
+
+ memset((char *) sep, 0, sizeof *sep);
+ arg = skip(&cp);
+ if (arg == NULL) {
+ /* A blank line. */