* server program full path name
* server program arguments maximum of MAXARGS (20)
*
- * RPC services unsuported
+ * RPC services unsupported
*
* Comment lines are indicated by a `#' in column 1.
*/
#include "busybox.h"
-#include <sys/param.h>
-#include <sys/stat.h>
-#include <sys/ioctl.h>
-#include <sys/socket.h>
-#include <sys/un.h>
-#include <sys/file.h>
-#include <sys/wait.h>
-#include <sys/time.h>
-#include <sys/resource.h>
#ifndef __linux__
#ifndef RLIMIT_NOFILE
#endif
#endif
-#include <sys/param.h>
-#include <sys/stat.h>
+#include <sys/file.h>
#include <sys/ioctl.h>
+#include <sys/param.h>
+#include <sys/resource.h>
#include <sys/socket.h>
-#include <sys/file.h>
-#include <sys/wait.h>
+#include <sys/stat.h>
#include <sys/time.h>
-#include <sys/resource.h>
+#include <sys/un.h>
+#include <sys/wait.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <stdarg.h>
#include <time.h>
-#define _PATH_INETDCONF "/etc/inetd.conf"
-#define _PATH_INETDPID "/var/run/inetd.pid"
-
-#ifndef MIN
-#define MIN(a, b) ((a) < (b) ? (a) : (b))
-#endif
-
-#define TOOMANY 40 /* don't start more than TOOMANY */
-#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
-#define RETRYTIME (60*10) /* retry after bind or server fail */
-
#ifndef OPEN_MAX
-#define OPEN_MAX 64
+#define OPEN_MAX 64
#endif
+#define _PATH_INETDCONF "/etc/inetd.conf"
+#define _PATH_INETDPID "/var/run/inetd.pid"
-/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
-#define FD_MARGIN (8)
-static int rlim_ofile_cur = OPEN_MAX;
+#define TOOMANY 40 /* don't start more than TOOMANY */
+#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
+#define RETRYTIME (60*10) /* retry after bind or server fail */
+#define MAXARGV 20
-#ifdef RLIMIT_NOFILE
-static struct rlimit rlim_ofile;
-#endif
+#define se_ctrladdr se_un.se_un_ctrladdr
+#define se_ctrladdr_in se_un.se_un_ctrladdr_in
+#define se_ctrladdr_un se_un.se_un_ctrladdr_un
-#define INETD_UNSUPPORT_BILTIN 1
+/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
+#define FD_MARGIN (8)
/* Check unsupporting builtin */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
-#undef INETD_UNSUPPORT_BILTIN
-#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
-#undef INETD_UNSUPPORT_BILTIN
-#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
-#undef INETD_UNSUPPORT_BILTIN
-#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
-#undef INETD_UNSUPPORT_BILTIN
-#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
-#undef INETD_UNSUPPORT_BILTIN
+#if defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO || \
+ defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD || \
+ defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME || \
+ defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME || \
+ defined CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
+# define INETD_FEATURE_ENABLED
#endif
-static struct servtab {
+typedef struct servtab_s {
char *se_service; /* name of service */
int se_socktype; /* type of socket to use */
int se_family; /* address family */
short se_checked; /* looked at during merge */
char *se_user; /* user name to run as */
char *se_group; /* group name to run as */
-#ifndef INETD_UNSUPPORT_BILTIN
+#ifdef INETD_FEATURE_ENABLED
const struct biltin *se_bi; /* if built-in, description */
#endif
char *se_server; /* server program */
-#define MAXARGV 20
char *se_argv[MAXARGV+1]; /* program arguments */
int se_fd; /* open descriptor */
union {
struct sockaddr_in se_un_ctrladdr_in;
struct sockaddr_un se_un_ctrladdr_un;
} se_un; /* bound address */
-#define se_ctrladdr se_un.se_un_ctrladdr
-#define se_ctrladdr_in se_un.se_un_ctrladdr_in
-#define se_ctrladdr_un se_un.se_un_ctrladdr_un
int se_ctrladdr_size;
int se_max; /* max # of instances of this service */
int se_count; /* number started since se_time */
struct timeval se_time; /* start of se_count */
- struct servtab *se_next;
-} *servtab;
+ struct servtab_s *se_next;
+} servtab_t;
-/* Length of socket listen queue. Should be per-service probably. */
-static int global_queuelen = 128;
-
-static int nsock, maxsock;
-static fd_set allsock;
-static int timingout;
-static sigset_t blockmask, emptymask;
+static servtab_t *servtab;
+#ifdef INETD_FEATURE_ENABLED
+struct biltin {
+ const char *bi_service; /* internally provided service name */
+ int bi_socktype; /* type of socket supported */
+ short bi_fork; /* 1 if should fork before call */
+ short bi_wait; /* 1 if should wait for child */
+ void (*bi_fn)(int, servtab_t *); /* fn which performs it */
+};
- /* Echo received data */
+ /* Echo received data */
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
-static void echo_stream(int, struct servtab *);
-static void echo_dg(int, struct servtab *);
+static void echo_stream(int, servtab_t *);
+static void echo_dg(int, servtab_t *);
#endif
- /* Internet /dev/null */
+ /* Internet /dev/null */
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
-static void discard_stream(int, struct servtab *);
-static void discard_dg(int, struct servtab *);
+static void discard_stream(int, servtab_t *);
+static void discard_dg(int, servtab_t *);
#endif
/* Return 32 bit time since 1900 */
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_TIME
-static void machtime_stream(int, struct servtab *);
-static void machtime_dg(int, struct servtab *);
+static void machtime_stream(int, servtab_t *);
+static void machtime_dg(int, servtab_t *);
#endif
/* Return human-readable time */
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
-static void daytime_stream(int, struct servtab *);
-static void daytime_dg(int, struct servtab *);
+static void daytime_stream(int, servtab_t *);
+static void daytime_dg(int, servtab_t *);
#endif
/* Familiar character generator */
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_CHARGEN
-static void chargen_stream(int, struct servtab *);
-static void chargen_dg(int, struct servtab *);
+static void chargen_stream(int, servtab_t *);
+static void chargen_dg(int, servtab_t *);
#endif
-#ifndef INETD_UNSUPPORT_BILTIN
-struct biltin {
- const char *bi_service; /* internally provided service name */
- int bi_socktype; /* type of socket supported */
- short bi_fork; /* 1 if should fork before call */
- short bi_wait; /* 1 if should wait for child */
- void (*bi_fn)(int, struct servtab *); /* fn which performs it */
-};
-
static const struct biltin biltins[] = {
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
/* Echo received data */
#endif
{ NULL, 0, 0, 0, NULL }
};
-#endif /* INETD_UNSUPPORT_BILTIN */
+#endif /* INETD_FEATURE_ENABLED */
-#define NUMINT (sizeof(intab) / sizeof(struct inent))
-static const char *CONFIG = _PATH_INETDCONF;
+#ifdef RLIMIT_NOFILE
+static struct rlimit rlim_ofile;
+#endif
-#define BCOPY(s, d, z) memcpy(d, s, z)
+/* Length of socket listen queue. Should be per-service probably. */
+static int global_queuelen = 128;
+
+static FILE *fconfig;
+static sigset_t blockmask;
+static sigset_t emptymask;
+static fd_set allsock;
+static int nsock;
+static int maxsock;
+static int timingout;
+static int rlim_ofile_cur = OPEN_MAX;
+static const char *CONFIG = _PATH_INETDCONF;
static void
syslog_err_and_discard_dg(int se_socktype, const char *msg, ...)
_exit(1);
}
-static FILE *fconfig;
-static char line[256];
-
-static FILE *
-setconfig(void)
+static char * inetd_strdup(const char *s)
{
- FILE *f = fconfig;
+ char *ms = strdup(s);
- if (f != NULL) {
- fseek(f, 0L, L_SET);
- } else {
- f = fconfig = fopen(CONFIG, "r");
- if(f == NULL)
- syslog(LOG_ERR, "%s: %m", CONFIG);
- }
- return f;
+ if(ms == NULL)
+ syslog_err_and_discard_dg(SOCK_STREAM, "strdup: %m");
+ return ms;
}
-static char *
-nextline(void)
-{
- char *cp;
- FILE *fd = fconfig;
-
- if (fgets(line, sizeof (line), fd) == NULL)
- return ((char *)0);
- cp = strchr(line, '\n');
- if (cp)
- *cp = '\0';
- return (line);
-}
-
-static char *
-skip(char **cpp)
-{
- char *cp = *cpp;
- char *start;
-
- if (*cpp == NULL)
- return ((char *)0);
-
-again:
- while (*cp == ' ' || *cp == '\t')
- cp++;
- if (*cp == '\0') {
- int c;
-
- c = getc(fconfig);
- (void) ungetc(c, fconfig);
- if (c == ' ' || c == '\t')
- if ((cp = nextline()) != NULL)
- goto again;
- *cpp = NULL;
- return NULL;
- }
- start = cp;
- while (*cp && *cp != ' ' && *cp != '\t')
- cp++;
- if (*cp != '\0')
- *cp++ = '\0';
- *cpp = cp;
- return (start);
-}
-static char *
-newstr(char *cp)
+static servtab_t *getconfigent(void)
{
- cp = strdup(cp ? cp : "");
- if (cp)
- return(cp);
-
- syslog_err_and_discard_dg(SOCK_STREAM, "strdup: %m");
-}
-
-
-static struct servtab *
-getconfigent(void)
-{
- static struct servtab serv;
- struct servtab *sep = &serv;
+ static servtab_t serv;
+ servtab_t *sep = &serv;
int argc;
- char *cp, *arg;
+ char *cp = NULL;
+ char *cp_ptr;
+ char *cp_ptr_ptr = NULL;
more:
- while ((cp = nextline()) && *cp == '#')
- ;
- if (cp == NULL)
- return ((struct servtab *)0);
+ free(cp);
+ cp = bb_get_chomped_line_from_file(fconfig);
+ if (feof(fconfig)) {
+ free(cp);
+ return (NULL);
+ }
+ if ((cp == NULL) || (*cp == '#')) {
+ goto more;
+ }
+ /* make bind 0.0.0.0 and other zero default */
memset((char *)sep, 0, sizeof *sep);
- sep->se_service = newstr(skip(&cp));
- arg = skip(&cp);
- if (arg == NULL)
+
+ cp_ptr = strtok_r(cp, " \t", &cp_ptr_ptr);
+ if (cp_ptr == NULL) {
+ /* Error */
goto more;
+ }
+ sep->se_service = inetd_strdup(cp_ptr);
- if (strcmp(arg, "stream") == 0)
+ cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
+ if (cp_ptr == NULL) {
+ /* Error */
+ goto more;
+ }
+ if (strcmp(cp_ptr, "stream") == 0)
sep->se_socktype = SOCK_STREAM;
- else if (strcmp(arg, "dgram") == 0)
+ else if (strcmp(cp_ptr, "dgram") == 0)
sep->se_socktype = SOCK_DGRAM;
- else if (strcmp(arg, "rdm") == 0)
+ else if (strcmp(cp_ptr, "rdm") == 0)
sep->se_socktype = SOCK_RDM;
- else if (strcmp(arg, "seqpacket") == 0)
+ else if (strcmp(cp_ptr, "seqpacket") == 0)
sep->se_socktype = SOCK_SEQPACKET;
- else if (strcmp(arg, "raw") == 0)
+ else if (strcmp(cp_ptr, "raw") == 0)
sep->se_socktype = SOCK_RAW;
else
sep->se_socktype = -1;
- sep->se_proto = newstr(skip(&cp));
- if (strcmp(sep->se_proto, "unix") == 0) {
+ cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
+ if (cp_ptr == NULL) {
+ /* error */
+ goto more;
+ }
+ if (strcmp(cp_ptr, "unix") == 0) {
sep->se_family = AF_UNIX;
} else {
- sep->se_family = AF_INET;
- if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
- syslog(LOG_ERR, "%s: rpc services not suported",
+ if (strncmp(cp_ptr, "rpc/", 4) == 0) {
+ syslog(LOG_ERR, "%s: rpc services not supported",
sep->se_service);
goto more;
}
+ sep->se_family = AF_INET;
}
- arg = skip(&cp);
- if (arg == NULL)
+ sep->se_proto = inetd_strdup(cp_ptr);
+
+ cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
+ if (cp_ptr == NULL) {
+ /* error */
goto more;
+ }
{
- char *s = strchr(arg, '.');
+ char *s = strchr(cp_ptr, '.');
if (s) {
*s++ = '\0';
sep->se_max = atoi(s);
} else
sep->se_max = TOOMANY;
}
- sep->se_wait = strcmp(arg, "wait") == 0;
- sep->se_user = newstr(skip(&cp));
- sep->se_group = strchr(sep->se_user, '.');
- if (sep->se_group) {
- *sep->se_group++ = '\0';
+ sep->se_wait = strcmp(cp_ptr, "wait") == 0;
+
+ cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
+ if (cp_ptr == NULL) {
+ /* error */
+ goto more;
+ }
+
+ sep->se_user = inetd_strdup(cp_ptr);
+ {
+ char *cp_ptr2 = strchr(sep->se_user, '.');
+
+ if (cp_ptr2) {
+ *cp_ptr2++ = '\0';
+ }
+ sep->se_group = cp_ptr2;
+ }
+
+ cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr);
+ if (cp_ptr == NULL) {
+ /* error */
+ goto more;
}
- sep->se_server = newstr(skip(&cp));
- if (strcmp(sep->se_server, "internal") == 0) {
-#ifndef INETD_UNSUPPORT_BILTIN
+ if (strcmp(cp_ptr, "internal") == 0) {
+#ifdef INETD_FEATURE_ENABLED
const struct biltin *bi;
- for (bi = biltins; bi->bi_service; bi++)
- if (bi->bi_socktype == sep->se_socktype &&
- strcmp(bi->bi_service, sep->se_service) == 0)
+ for (bi = biltins; bi->bi_service; bi++) {
+ if ((bi->bi_socktype == sep->se_socktype) &&
+ (strcmp(bi->bi_service, sep->se_service) == 0)) {
break;
+ }
+ }
if (bi->bi_service == 0) {
- syslog(LOG_ERR, "internal service %s unknown",
- sep->se_service);
+ syslog(LOG_ERR, "internal service %s unknown", sep->se_service);
goto more;
}
sep->se_bi = bi;
sep->se_wait = bi->bi_wait;
#else
- syslog(LOG_ERR, "internal service %s unknown",
- sep->se_service);
- goto more;
+ syslog(LOG_ERR, "internal service %s unknown", cp_ptr);
+ goto more;
#endif
- } else
-#ifndef INETD_UNSUPPORT_BILTIN
- sep->se_bi = NULL
+ }
+#ifdef INETD_FEATURE_ENABLED
+ else {
+ sep->se_bi = NULL;
+ }
#endif
- ;
+ sep->se_server = inetd_strdup(cp_ptr);
+
argc = 0;
- for (arg = skip(&cp); cp; arg = skip(&cp)) {
- if (argc < MAXARGV)
- sep->se_argv[argc++] = newstr(arg);
+ while ((cp_ptr = strtok_r(NULL, " \t", &cp_ptr_ptr)) != NULL) {
+ if (argc < MAXARGV) {
+ sep->se_argv[argc++] = inetd_strdup(cp_ptr);
+ }
}
- while (argc <= MAXARGV)
- sep->se_argv[argc++] = NULL;
+ free(cp);
+
return (sep);
}
-static void
-freeconfig(struct servtab *cp)
+static void freeconfig(servtab_t *cp)
{
int i;
free(cp->se_argv[i]);
}
-#ifndef INETD_UNSUPPORT_BILTIN
+#ifdef INETD_FEATURE_ENABLED
static char **Argv;
static char *LastArg;
-static void
-setproctitle(char *a, int s)
+static void setproctitle(char *a, int s)
{
size_t size;
char *cp;
while (cp < LastArg)
*cp++ = ' ';
}
-#endif /* INETD_UNSUPPORT_BILTIN */
+#endif /* INETD_FEATURE_ENABLED */
-static struct servtab *
-enter(struct servtab *cp)
-{
- struct servtab *sep;
- sigset_t oldmask;
- sep = (struct servtab *)malloc(sizeof (*sep));
- if (sep == NULL) {
- syslog_err_and_discard_dg(SOCK_STREAM, bb_msg_memory_exhausted);
- }
- *sep = *cp;
- sep->se_fd = -1;
- sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
- sep->se_next = servtab;
- servtab = sep;
- sigprocmask(SIG_SETMASK, &oldmask, NULL);
- return (sep);
-}
-
-static int
-bump_nofile(void)
-{
-#ifdef RLIMIT_NOFILE
-
-#define FD_CHUNK 32
-
- struct rlimit rl;
-
- if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
- syslog(LOG_ERR, "getrlimit: %m");
- return -1;
- }
- rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK);
- if (rl.rlim_cur <= rlim_ofile_cur) {
- syslog(LOG_ERR,
-#if _FILE_OFFSET_BITS == 64
- "bump_nofile: cannot extend file limit, max = %lld",
-#else
- "bump_nofile: cannot extend file limit, max = %ld",
-#endif
- rl.rlim_cur);
- return -1;
- }
-
- if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
- syslog(LOG_ERR, "setrlimit: %m");
- return -1;
- }
-
- rlim_ofile_cur = rl.rlim_cur;
- return 0;
-
-#else
- syslog(LOG_ERR, "bump_nofile: cannot extend file limit");
- return -1;
-#endif
-}
-
-
-static void
-setup(struct servtab *sep)
+static void setup(servtab_t *sep)
{
int on = 1;
nsock++;
if (sep->se_fd > maxsock) {
maxsock = sep->se_fd;
- if (maxsock > rlim_ofile_cur - FD_MARGIN)
- bump_nofile();
+ if (maxsock > rlim_ofile_cur - FD_MARGIN) {
+#ifdef RLIMIT_NOFILE
+# define FD_CHUNK 32
+ struct rlimit rl;
+
+ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
+ syslog(LOG_ERR, "getrlimit: %m");
+ return;
+ }
+ rl.rlim_cur = rl.rlim_max < (rl.rlim_cur + FD_CHUNK) ? rl.rlim_max : (rl.rlim_cur + FD_CHUNK);
+ if (rl.rlim_cur <= rlim_ofile_cur) {
+ syslog(LOG_ERR,
+# if _FILE_OFFSET_BITS == 64
+ "bump_nofile: cannot extend file limit, max = %lld",
+# else
+ "bump_nofile: cannot extend file limit, max = %ld",
+# endif
+ rl.rlim_cur);
+ return;
+ }
+
+ if (setrlimit(RLIMIT_NOFILE, &rl) < 0) {
+ syslog(LOG_ERR, "setrlimit: %m");
+ return;
+ }
+
+ rlim_ofile_cur = rl.rlim_cur;
+ return;
+#else
+ syslog(LOG_ERR, "bump_nofile: cannot extend file limit");
+ return;
+#endif /* RLIMIT_NOFILE */
+ }
}
}
-static void
-config(int signum)
+static void config(int signum)
{
- struct servtab *sep, *cp, **sepp;
+ servtab_t *sep, *cp, **sepp;
sigset_t oldmask;
unsigned n;
(void)signum;
- if (setconfig() == NULL)
- return;
+
+ if (fconfig != NULL) {
+ fseek(fconfig, 0L, L_SET);
+ } else {
+ fconfig = fopen(CONFIG, "r");
+ if (fconfig == NULL) {
+ syslog(LOG_ERR, "%s: %m", CONFIG);
+ return;
+ }
+ }
for (sep = servtab; sep; sep = sep->se_next)
sep->se_checked = 0;
* wait.
*/
if (
-#ifndef INETD_UNSUPPORT_BILTIN
+#ifdef INETD_FEATURE_ENABLED
cp->se_bi == 0 &&
#endif
(sep->se_wait == 1 || cp->se_wait == 0))
SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
#undef SWAP
sigprocmask(SIG_SETMASK, &oldmask, NULL);
- freeconfig(cp);
+ // This freeconfig() is probably a bug, since it will try and free()
+ // each of the argv[] values, which are really just pointers
+ // into the middle of a single line buffer for the config file.
+ //freeconfig(cp); // BUG?
} else {
- sep = enter(cp);
+ sep = (servtab_t *)xmalloc(sizeof (*sep));
+ *sep = *cp;
+ sep->se_fd = -1;
+ sigprocmask(SIG_BLOCK, &blockmask, &oldmask);
+ sep->se_next = servtab;
+ servtab = sep;
+ sigprocmask(SIG_SETMASK, &oldmask, NULL);
}
sep->se_checked = 1;
sep->se_ctrladdr_in.sin_family = AF_INET;
sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
{
- u_short port = htons(atoi(sep->se_service));
-
- if (!port) {
- struct servent *sp;
- sp = getservbyname(sep->se_service,
- sep->se_proto);
- if (sp == 0) {
- syslog(LOG_ERR,
- "%s/%s: unknown service",
- sep->se_service, sep->se_proto);
- continue;
- }
- port = sp->s_port;
+ u_short port = bb_lookup_port(sep->se_service, sep->se_proto, 0);
+
+ if (port == 0) {
+ syslog(LOG_ERR,
+ "%s/%s: unknown service",
+ sep->se_service, sep->se_proto);
+ continue;
}
if (port != sep->se_ctrladdr_in.sin_port) {
sep->se_ctrladdr_in.sin_port = port;
-static void
-reapchild(int signum)
+static void reapchild(int signum)
{
int status;
int pid;
- struct servtab *sep;
+ servtab_t *sep;
(void)signum;
for (;;) {
}
}
-static void
-retry(int signum)
+static void retry(int signum)
{
- struct servtab *sep;
+ servtab_t *sep;
(void)signum;
timingout = 0;
}
}
-static void
-goaway(int signum)
+static void goaway(int signum)
{
- struct servtab *sep;
+ servtab_t *sep;
(void)signum;
for (sep = servtab; sep; sep = sep->se_next)
-extern int
-inetd_main(int argc, char *argv[])
+extern int inetd_main(int argc, char *argv[])
{
- struct servtab *sep;
- struct passwd *pwd;
+ servtab_t *sep;
struct group *grp = NULL;
struct sigaction sa;
int pid;
char *sq;
gid_t gid;
-#ifdef INETD_UNSUPPORT_BILTIN
-# define dofork 1
-#else
- int dofork;
+#ifdef INETD_FEATURE_ENABLED
extern char **environ;
#endif
gid = getgid();
setgroups(1, &gid);
-#ifndef INETD_UNSUPPORT_BILTIN
+#ifdef INETD_FEATURE_ENABLED
Argv = argv;
if (environ == 0 || *environ == 0)
environ = argv;
#endif /* uClinux */
if(opt & 1) {
- global_queuelen = atoi(optarg);
+ global_queuelen = atoi(sq);
if (global_queuelen < 8) global_queuelen=8;
}
argc -= optind;
}
for (;;) {
- int n, ctrl;
- fd_set readable;
-
- if (nsock == 0) {
- sigprocmask(SIG_BLOCK, &blockmask, NULL);
- while (nsock == 0)
- sigsuspend(&emptymask);
- sigprocmask(SIG_SETMASK, &emptymask, NULL);
- }
- readable = allsock;
- if ((n = select(maxsock + 1, &readable, (fd_set *)0,
- (fd_set *)0, (struct timeval *)0)) <= 0) {
- if (n < 0 && errno != EINTR)
- syslog(LOG_WARNING, "select: %m");
- sleep(1);
- continue;
- }
- for (sep = servtab; n && sep; sep = sep->se_next)
- if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
- n--;
- if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
- /* Fixed AGC */
- fcntl(sep->se_fd, F_SETFL, O_NDELAY);
- /* --------- */
- ctrl = accept(sep->se_fd, NULL, NULL);
- fcntl(sep->se_fd, F_SETFL, 0);
- if (ctrl < 0) {
- if (errno == EINTR || errno == EWOULDBLOCK)
- continue;
- syslog(LOG_WARNING, "accept (for %s): %m",
- sep->se_service);
- continue;
+ fd_set readable;
+ int ctrl;
+ int n;
+
+ if (nsock == 0) {
+ sigprocmask(SIG_BLOCK, &blockmask, NULL);
+ while (nsock == 0) {
+ sigsuspend(&emptymask);
}
- } else
- ctrl = sep->se_fd;
- sigprocmask(SIG_BLOCK, &blockmask, NULL);
- pid = 0;
-#ifndef INETD_UNSUPPORT_BILTIN
- dofork = (sep->se_bi == 0 || sep->se_bi->bi_fork);
-#endif
- if (dofork) {
- if (sep->se_count++ == 0)
- (void)gettimeofday(&sep->se_time,
- (struct timezone *)0);
- else if (sep->se_count >= sep->se_max) {
- struct timeval now;
-
- (void)gettimeofday(&now, (struct timezone *)0);
- if (now.tv_sec - sep->se_time.tv_sec >
- CNT_INTVL) {
- sep->se_time = now;
- sep->se_count = 1;
- } else {
- syslog(LOG_ERR,
- "%s/%s server failing (looping), service terminated",
- sep->se_service, sep->se_proto);
- FD_CLR(sep->se_fd, &allsock);
- (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);
- }
- continue;
- }
- }
- pid = fork();
- }
- if (pid < 0) {
- syslog(LOG_ERR, "fork: %m");
- if (sep->se_socktype == SOCK_STREAM)
- close(ctrl);
sigprocmask(SIG_SETMASK, &emptymask, NULL);
+ }
+ readable = allsock;
+ n = select(maxsock + 1, &readable, (fd_set *)0, (fd_set *)0, (struct timeval *)0);
+ if (n <= 0) {
+ if (n < 0 && errno != EINTR) {
+ syslog(LOG_WARNING, "select: %m");
+ }
sleep(1);
continue;
- }
- if (pid && sep->se_wait) {
- sep->se_wait = pid;
- FD_CLR(sep->se_fd, &allsock);
- nsock--;
- }
- sigprocmask(SIG_SETMASK, &emptymask, NULL);
- if (pid == 0) {
-#ifndef INETD_UNSUPPORT_BILTIN
- if (sep->se_bi)
- (*sep->se_bi->bi_fn)(ctrl, sep);
- else
-#endif
- {
- if ((pwd = getpwnam(sep->se_user)) == NULL) {
- syslog_err_and_discard_dg(
- sep->se_socktype,
- "getpwnam: %s: No such user",
- sep->se_user);
- }
- if (sep->se_group &&
- (grp = getgrnam(sep->se_group)) == NULL) {
- syslog_err_and_discard_dg(
- sep->se_socktype,
- "getgrnam: %s: No such group",
- sep->se_group);
+ }
+ for (sep = servtab; n && sep; sep = sep->se_next) {
+ if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) {
+ n--;
+ if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+ /* Fixed AGC */
+ fcntl(sep->se_fd, F_SETFL, O_NDELAY);
+ /* --------- */
+ ctrl = accept(sep->se_fd, NULL, NULL);
+ fcntl(sep->se_fd, F_SETFL, 0);
+ if (ctrl < 0) {
+ if (errno == EINTR || errno == EWOULDBLOCK) {
+ continue;
+ }
+ syslog(LOG_WARNING, "accept (for %s): %m",
+ sep->se_service);
+ continue;
+ }
+ } else {
+ ctrl = sep->se_fd;
}
- /*
- * Ok. There are four cases here:
- * 1. nonroot user, no group specified
- * 2. nonroot user, some group specified
- * 3. root user, no group specified
- * 4. root user, some group specified
- * In cases 2 and 4 we setgid to the specified
- * group. In cases 1 and 2 we run initgroups
- * to run with the groups of the given user.
- * In case 4 we do setgroups to run with the
- * given group. In case 3 we do nothing.
- */
- if (pwd->pw_uid) {
- if (sep->se_group)
- pwd->pw_gid = grp->gr_gid;
- setgid((gid_t)pwd->pw_gid);
- initgroups(pwd->pw_name, pwd->pw_gid);
- setuid((uid_t)pwd->pw_uid);
- } else if (sep->se_group) {
- setgid((gid_t)grp->gr_gid);
- setgroups(1, &grp->gr_gid);
+ sigprocmask(SIG_BLOCK, &blockmask, NULL);
+ pid = 0;
+#ifdef INETD_FEATURE_ENABLED
+ if (sep->se_bi == 0 || sep->se_bi->bi_fork)
+#endif
+ {
+ if (sep->se_count++ == 0) {
+ gettimeofday(&sep->se_time, (struct timezone *)0);
+ }
+ else if (sep->se_count >= sep->se_max) {
+ struct timeval now;
+
+ gettimeofday(&now, (struct timezone *)0);
+ if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) {
+ sep->se_time = now;
+ sep->se_count = 1;
+ } else {
+ syslog(LOG_ERR,
+ "%s/%s server failing (looping), service terminated",
+ sep->se_service, sep->se_proto);
+ FD_CLR(sep->se_fd, &allsock);
+ close(sep->se_fd);
+ sep->se_fd = -1;
+ sep->se_count = 0;
+ nsock--;
+ sigprocmask(SIG_SETMASK, &emptymask, NULL);
+ if (!timingout) {
+ timingout = 1;
+ alarm(RETRYTIME);
+ }
+ continue;
+ }
+ }
+ pid = fork();
+ if (pid < 0) {
+ syslog(LOG_ERR, "fork: %m");
+ if (sep->se_socktype == SOCK_STREAM) {
+ close(ctrl);
+ }
+ sigprocmask(SIG_SETMASK, &emptymask, NULL);
+ sleep(1);
+ continue;
+ }
+ if (pid && sep->se_wait) {
+ sep->se_wait = pid;
+ FD_CLR(sep->se_fd, &allsock);
+ nsock--;
+ }
}
- dup2(ctrl, 0);
- close(ctrl);
- dup2(0, 1);
- dup2(0, 2);
+ sigprocmask(SIG_SETMASK, &emptymask, NULL);
+ if (pid == 0) {
+#ifdef INETD_FEATURE_ENABLED
+ if (sep->se_bi) {
+ (*sep->se_bi->bi_fn)(ctrl, sep);
+ } else
+#endif
+ {
+ struct passwd *pwd = getpwnam(sep->se_user);
+ if (pwd == NULL) {
+ syslog_err_and_discard_dg(
+ sep->se_socktype,
+ "getpwnam: %s: No such user",
+ sep->se_user);
+ }
+ if (sep->se_group && (grp = getgrnam(sep->se_group)) == NULL) {
+ syslog_err_and_discard_dg(sep->se_socktype,
+ "getgrnam: %s: No such group", sep->se_group);
+ }
+ /*
+ * Ok. There are four cases here:
+ * 1. nonroot user, no group specified
+ * 2. nonroot user, some group specified
+ * 3. root user, no group specified
+ * 4. root user, some group specified
+ * In cases 2 and 4 we setgid to the specified
+ * group. In cases 1 and 2 we run initgroups
+ * to run with the groups of the given user.
+ * In case 4 we do setgroups to run with the
+ * given group. In case 3 we do nothing.
+ */
+ if (pwd->pw_uid) {
+ if (sep->se_group) {
+ pwd->pw_gid = grp->gr_gid;
+ }
+ setgid((gid_t)pwd->pw_gid);
+ initgroups(pwd->pw_name, pwd->pw_gid);
+ setuid((uid_t)pwd->pw_uid);
+ } else if (sep->se_group) {
+ setgid((gid_t)grp->gr_gid);
+ setgroups(1, &grp->gr_gid);
+ }
+ dup2(ctrl, 0);
+ close(ctrl);
+ dup2(0, 1);
+ dup2(0, 2);
#ifdef RLIMIT_NOFILE
- if (rlim_ofile.rlim_cur != rlim_ofile_cur) {
- if (setrlimit(RLIMIT_NOFILE,
- &rlim_ofile) < 0)
- syslog(LOG_ERR,"setrlimit: %m");
- }
+ if (rlim_ofile.rlim_cur != rlim_ofile_cur) {
+ if (setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
+ syslog(LOG_ERR,"setrlimit: %m");
+ }
+ }
#endif
- for (ctrl = rlim_ofile_cur-1; --ctrl > 2; )
- (void)close(ctrl);
-
- memset(&sa, 0, sizeof(sa));
- sa.sa_handler = SIG_DFL;
- sigaction(SIGPIPE, &sa, NULL);
-
- execv(sep->se_server, sep->se_argv);
- syslog_err_and_discard_dg(sep->se_socktype,
- "execv %s: %m", sep->se_server);
+ for (ctrl = rlim_ofile_cur-1; --ctrl > 2; ) {
+ (void)close(ctrl);
+ }
+ memset(&sa, 0, sizeof(sa));
+ sa.sa_handler = SIG_DFL;
+ sigaction(SIGPIPE, &sa, NULL);
+
+ execv(sep->se_server, sep->se_argv);
+ syslog_err_and_discard_dg(sep->se_socktype, "execv %s: %m", sep->se_server);
+ }
+ }
+ if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) {
+ close(ctrl);
+ }
}
}
- if (!sep->se_wait && sep->se_socktype == SOCK_STREAM)
- close(ctrl);
- }
}
}
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_ECHO
/* Echo service -- echo data back */
-static void
-echo_stream(int s, struct servtab *sep)
+static void echo_stream(int s, servtab_t *sep)
{
char buffer[BUFSIZE];
int i;
}
/* Echo service -- echo data back */
-static void
-echo_dg(int s, struct servtab *sep)
+static void echo_dg(int s, servtab_t *sep)
{
char buffer[BUFSIZE];
int i;
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DISCARD
/* Discard service -- ignore data */
-static void
-discard_stream(int s, struct servtab *sep)
+static void discard_stream(int s, servtab_t *sep)
{
char buffer[BUFSIZE];
}
/* Discard service -- ignore data */
-static void
-discard_dg(int s, struct servtab *sep)
+static void discard_dg(int s, servtab_t *sep)
{
char buffer[BUFSIZE];
(void)sep;
static char ring[128];
static char *endring;
-static void
-initring(void)
+static void initring(void)
{
int i;
}
/* Character generator */
-static void
-chargen_stream(int s, struct servtab *sep)
+static void chargen_stream(int s, servtab_t *sep)
{
char *rs;
int len;
text[LINESIZ + 1] = '\n';
for (rs = ring;;) {
if ((len = endring - rs) >= LINESIZ)
- BCOPY(rs, text, LINESIZ);
+ memcpy(rs, text, LINESIZ);
else {
- BCOPY(rs, text, len);
- BCOPY(ring, text + len, LINESIZ - len);
+ memcpy(rs, text, len);
+ memcpy(ring, text + len, LINESIZ - len);
}
if (++rs == endring)
rs = ring;
}
/* Character generator */
-static void
-chargen_dg(int s, struct servtab *sep)
+static void chargen_dg(int s, servtab_t *sep)
{
struct sockaddr sa;
static char *rs;
return;
if ((len = endring - rs) >= LINESIZ)
- BCOPY(rs, text, LINESIZ);
+ memcpy(rs, text, LINESIZ);
else {
- BCOPY(rs, text, len);
- BCOPY(ring, text + len, LINESIZ - len);
+ memcpy(rs, text, len);
+ memcpy(ring, text + len, LINESIZ - len);
}
if (++rs == endring)
rs = ring;
* some seventy years Bell Labs was asleep.
*/
-static long
-machtime(void)
+static long machtime(void)
{
struct timeval tv;
return (htonl((long)tv.tv_sec + 2208988800UL));
}
-static void
-machtime_stream(int s, struct servtab *sep)
+static void machtime_stream(int s, servtab_t *sep)
{
long result;
(void)sep;
write(s, (char *) &result, sizeof(result));
}
-static void
-machtime_dg(int s, struct servtab *sep)
+static void machtime_dg(int s, servtab_t *sep)
{
long result;
struct sockaddr sa;
#ifdef CONFIG_FEATURE_INETD_SUPPORT_BILTIN_DAYTIME
/* Return human-readable time of day */
-static int
-human_readable_time_sprintf(char *buffer)
+static int human_readable_time_sprintf(char *buffer)
{
time_t clocc = time(NULL);
return sprintf(buffer, "%.24s\r\n", ctime(&clocc));
}
-static void
-daytime_stream(int s, struct servtab *sep)
+static void daytime_stream(int s, servtab_t *sep)
{
char buffer[256];
size_t st = human_readable_time_sprintf(buffer);
}
/* Return human-readable time of day */
-static void
-daytime_dg(int s, struct servtab *sep)
+static void daytime_dg(int s, servtab_t *sep)
{
char buffer[256];
struct sockaddr sa;