* 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
+ * 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
* SUCH DAMAGE.
*/
-/*
- * Inetd - Internet super-server
+/* Inetd - Internet super-server
*
* This program invokes all internet services as needed.
* connection-oriented services are invoked each time a
* arrives; a process is created and passed a pending message
* on file descriptor 0. Datagram servers may either connect
* to their peer, freeing up the original socket for inetd
- * to receive further messages on, or ``take over the socket'',
+ * to receive further messages on, or "take over the socket",
* processing all arriving datagrams and, eventually, timing
- * out. The first type of server is said to be ``multi-threaded'';
- * the second type of server ``single-threaded''.
+ * out. The first type of server is said to be "multi-threaded";
+ * the second type of server "single-threaded".
*
* Inetd uses a configuration file which is read at startup
* and, possibly, at some later time in response to a hangup signal.
- * The configuration file is ``free format'' with fields given in the
+ * The configuration file is "free format" with fields given in the
* order shown below. Continuation lines for an entry must begin with
* a space or tab. All fields must be present in each entry.
*
* Comment lines are indicated by a `#' in column 1.
*/
-/*
- * Here's the scoop concerning the user[.:]group feature:
+/* inetd rules for passing file descriptors to children
+ * (http://www.freebsd.org/cgi/man.cgi?query=inetd):
+ *
+ * The wait/nowait entry specifies whether the server that is invoked by
+ * inetd will take over the socket associated with the service access point,
+ * and thus whether inetd should wait for the server to exit before listen-
+ * ing for new service requests. Datagram servers must use "wait", as
+ * they are always invoked with the original datagram socket bound to the
+ * specified service address. These servers must read at least one datagram
+ * from the socket before exiting. If a datagram server connects to its
+ * peer, freeing the socket so inetd can receive further messages on the
+ * socket, it is said to be a "multi-threaded" server; it should read one
+ * datagram from the socket and create a new socket connected to the peer.
+ * It should fork, and the parent should then exit to allow inetd to check
+ * for new service requests to spawn new servers. Datagram servers which
+ * process all incoming datagrams on a socket and eventually time out are
+ * said to be "single-threaded". The comsat(8), (biff(1)) and talkd(8)
+ * utilities are both examples of the latter type of datagram server. The
+ * tftpd(8) utility is an example of a multi-threaded datagram server.
+ *
+ * Servers using stream sockets generally are multi-threaded and use the
+ * "nowait" entry. Connection requests for these services are accepted by
+ * inetd, and the server is given only the newly-accepted socket connected
+ * to a client of the service. Most stream-based services operate in this
+ * manner. Stream-based servers that use "wait" are started with the lis-
+ * tening service socket, and must accept at least one connection request
+ * before exiting. Such a server would normally accept and process incoming
+ * connection requests until a timeout.
+ */
+
+/* Here's the scoop concerning the user[.:]group feature:
*
* 1) set-group-option off.
*
* b) other: setgid(specified group)
* initgroups(name, specified group)
* setuid()
- *
*/
-#include "busybox.h"
+#include "libbb.h"
#include <syslog.h>
#include <sys/un.h>
-//#define CONFIG_FEATURE_INETD_RPC
-//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
-//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
-//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
-//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
-//#define CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
-//#define CONFIG_FEATURE_IPV6
+//#define ENABLE_FEATURE_INETD_RPC 1
+//#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO 1
+//#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD 1
+//#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME 1
+//#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME 1
+//#define ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN 1
+//#define ENABLE_FEATURE_IPV6 1
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
#include <rpc/rpc.h>
#include <rpc/pmap_clnt.h>
#endif
-#define _PATH_INETDCONF "/etc/inetd.conf"
-#define _PATH_INETDPID "/var/run/inetd.pid"
+extern char **environ;
+#define _PATH_INETDPID "/var/run/inetd.pid"
+
#define CNT_INTVL 60 /* servers in CNT_INTVL sec. */
#define RETRYTIME (60*10) /* retry after bind or server fail */
#endif
/* Reserve some descriptors, 3 stdio + at least: 1 log, 1 conf. file */
-#define FD_MARGIN (8)
-static rlim_t rlim_ofile_cur = OPEN_MAX;
-static struct rlimit rlim_ofile;
-
+#define FD_MARGIN 8
/* Check unsupporting builtin */
-#if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \
- defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \
- defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME || \
- defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME || \
- defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
# define INETD_FEATURE_ENABLED
#endif
-#if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \
- defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \
- defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
# define INETD_SETPROCTITLE
#endif
-typedef struct servtab {
+typedef int8_t socktype_t;
+typedef int8_t family_t;
+struct BUG_too_small {
+ char BUG_socktype_t_too_small[(0
+ | SOCK_STREAM
+ | SOCK_DGRAM
+ | SOCK_RDM
+ | SOCK_SEQPACKET
+ | SOCK_RAW) <= 127 ? 1 : -1];
+ char BUG_family_t_too_small[(0
+ | AF_INET
+ | AF_INET6
+ | AF_UNIX) <= 127 ? 1 : -1];
+};
+
+typedef struct servtab_t {
+ /* The most frequently referenced one: */
+ int se_fd; /* open descriptor */
+ /* NB: 'biggest fields last' saves on code size (~250 bytes) */
char *se_hostaddr; /* host address to listen on */
char *se_service; /* name of service */
- int se_socktype; /* type of socket to use */
- int se_family; /* address family */
char *se_proto; /* protocol used */
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
int se_rpcprog; /* rpc program number */
int se_rpcversl; /* rpc program lowest version */
int se_rpcversh; /* rpc program highest version */
#define isrpcservice(sep) 0
#endif
pid_t se_wait; /* single threaded server */
- short se_checked; /* looked at during merge */
+ socktype_t se_socktype; /* type of socket to use */
+ family_t se_family; /* address family */
+ smallint se_checked; /* looked at during merge */
char *se_user; /* user name to run as */
char *se_group; /* group name to run as */
#ifdef INETD_FEATURE_ENABLED
const struct builtin *se_bi; /* if built-in, description */
#endif
+ int se_ctrladdr_size;
+ int se_max; /* max # of instances of this service */
+ int se_count; /* number started since se_time */
+ struct servtab_t *se_next;
+ struct timeval se_time; /* start of se_count */
char *se_server; /* server program */
#define MAXARGV 20
char *se_argv[MAXARGV + 1]; /* program arguments */
- int se_fd; /* open descriptor */
union {
struct sockaddr se_un_ctrladdr;
struct sockaddr_in se_un_ctrladdr_in;
-#ifdef CONFIG_FEATURE_IPV6
+#if ENABLE_FEATURE_IPV6
struct sockaddr_in6 se_un_ctrladdr_in6;
#endif
struct sockaddr_un se_un_ctrladdr_un;
#define se_ctrladdr_in se_un.se_un_ctrladdr_in
#define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6
#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_t;
-static servtab_t *servtab;
-
#ifdef INETD_FEATURE_ENABLED
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 */
- short bi_wait; /* 1 if should wait for child */
+ socktype_t bi_socktype; /* type of socket supported */
+ uint8_t bi_fork; /* 1 if should fork before call */
+// Commented since it is always 0
+// uint8_t bi_wait; /* 1 if should wait for child */
void (*bi_fn) (int, servtab_t *);
};
/* Echo received data */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
static void echo_stream(int, servtab_t *);
static void echo_dg(int, servtab_t *);
#endif
/* Internet /dev/null */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
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_BUILTIN_TIME
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME
static void machtime_stream(int, servtab_t *);
static void machtime_dg(int, servtab_t *);
#endif
/* Return human-readable time */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
static void daytime_stream(int, servtab_t *);
static void daytime_dg(int, servtab_t *);
#endif
/* Familiar character generator */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
static void chargen_stream(int, servtab_t *);
static void chargen_dg(int, servtab_t *);
#endif
static const struct builtin builtins[] = {
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
/* Echo received data */
- {"echo", SOCK_STREAM, 1, 0, echo_stream,},
- {"echo", SOCK_DGRAM, 0, 0, echo_dg,},
+ {"echo", SOCK_STREAM, 1, echo_stream,},
+ {"echo", SOCK_DGRAM, 0, echo_dg,},
#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
/* Internet /dev/null */
- {"discard", SOCK_STREAM, 1, 0, discard_stream,},
- {"discard", SOCK_DGRAM, 0, 0, discard_dg,},
+ {"discard", SOCK_STREAM, 1, discard_stream,},
+ {"discard", SOCK_DGRAM, 0, discard_dg,},
#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME
/* Return 32 bit time since 1900 */
- {"time", SOCK_STREAM, 0, 0, machtime_stream,},
- {"time", SOCK_DGRAM, 0, 0, machtime_dg,},
+ {"time", SOCK_STREAM, 0, machtime_stream,},
+ {"time", SOCK_DGRAM, 0, machtime_dg,},
#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
/* Return human-readable time */
- {"daytime", SOCK_STREAM, 0, 0, daytime_stream,},
- {"daytime", SOCK_DGRAM, 0, 0, daytime_dg,},
+ {"daytime", SOCK_STREAM, 0, daytime_stream,},
+ {"daytime", SOCK_DGRAM, 0, daytime_dg,},
#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
/* Familiar character generator */
- {"chargen", SOCK_STREAM, 1, 0, chargen_stream,},
- {"chargen", SOCK_DGRAM, 0, 0, chargen_dg,},
+ {"chargen", SOCK_STREAM, 1, chargen_stream,},
+ {"chargen", SOCK_DGRAM, 0, chargen_dg,},
#endif
- {NULL, 0, 0, 0, NULL}
+ { /* zero filled */ }
};
#endif /* INETD_FEATURE_ENABLED */
-static int global_queuelen = 128;
-static int nsock, maxsock;
-static fd_set allsock;
-static int toomany;
-static int timingout;
-static struct servent *sp;
-static uid_t uid;
-
-static char *CONFIG = _PATH_INETDCONF;
-
-static FILE *fconfig;
-static char line[1024];
-static char *defhost;
+struct globals {
+ rlim_t rlim_ofile_cur;
+ struct rlimit rlim_ofile;
+ servtab_t *servtab;
+ int global_queuelen;
+ int nsock;
+ int maxsock;
+ int toomany;
+ int timingout;
+ struct servent *sp;
+ uid_t uid;
+ const char *config_filename;
+ FILE *fconfig;
+ char *defhost;
+#ifdef INETD_SETPROCTITLE
+ char **Argv;
+ char *LastArg;
+#endif
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+ char *endring;
+ char *ringpos;
+ char ring[128];
+#endif
+ fd_set allsock;
+ /* Used only in nextline() */
+ char line[80]; /* at least 80, see LINE_SIZE */
+};
+#define G (*(struct globals*)&bb_common_bufsiz1)
+enum { LINE_SIZE = COMMON_BUFSIZE - offsetof(struct globals, line) };
+struct BUG_G_too_big {
+ char BUG_G_too_big[sizeof(G) <= COMMON_BUFSIZE ? 1 : -1];
+};
+#define rlim_ofile_cur (G.rlim_ofile_cur )
+#define rlim_ofile (G.rlim_ofile )
+#define servtab (G.servtab )
+#define global_queuelen (G.global_queuelen)
+#define nsock (G.nsock )
+#define maxsock (G.maxsock )
+#define toomany (G.toomany )
+#define timingout (G.timingout )
+#define sp (G.sp )
+#define uid (G.uid )
+#define config_filename (G.config_filename)
+#define fconfig (G.fconfig )
+#define defhost (G.defhost )
+#define Argv (G.Argv )
+#define LastArg (G.LastArg )
+#define endring (G.endring )
+#define ringpos (G.ringpos )
+#define ring (G.ring )
+#define allsock (G.allsock )
+#define line (G.line )
+#define INIT_G() do { \
+ rlim_ofile_cur = OPEN_MAX; \
+ global_queuelen = 128; \
+ config_filename = "/etc/inetd.conf"; \
+} while (0)
/* xstrdup(NULL) returns NULL, but this one
* will return newly-allocated "" if called with NULL arg
fseek(fconfig, 0L, SEEK_SET);
return 1;
}
- fconfig = fopen(CONFIG, "r");
+ fconfig = fopen(config_filename, "r");
return (fconfig != NULL);
}
defhost = 0;
}
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
static void register_rpc(servtab_t *sep)
{
int n;
bb_error_msg("pmap_unset(%u, %u)", sep->se_rpcprog, n);
}
}
-#endif /* CONFIG_FEATURE_INETD_RPC */
+#endif /* FEATURE_INETD_RPC */
static void freeconfig(servtab_t *cp)
{
free(cp->se_argv[i]);
}
-static int bump_nofile (void)
+static int bump_nofile(void)
{
#define FD_CHUNK 32
struct rlimit rl;
- if (getrlimit (RLIMIT_NOFILE, &rl) < 0) {
+ if (getrlimit(RLIMIT_NOFILE, &rl) < 0) {
bb_perror_msg("getrlimit");
return -1;
}
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)");
+ setsockopt_reuseaddr(sep->se_fd);
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
if (isrpcservice(sep)) {
struct passwd *pwd;
char *cp;
FILE *fd = fconfig;
- if (fgets(line, sizeof(line), fd) == NULL)
+ if (fgets(line, LINE_SIZE, fd) == NULL)
return NULL;
cp = strchr(line, '\n');
if (cp)
return NULL;
}
-again:
+ 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()))
+ ungetc(c, fconfig);
+ if (c == ' ' || c == '\t') {
+ cp = nextline();
+ if (cp)
goto again;
+ }
*cpp = NULL;
/* goto erp; */
return NULL;
newtab->se_socktype = sep->se_socktype;
newtab->se_family = sep->se_family;
newtab->se_proto = xstrdup(sep->se_proto);
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
newtab->se_rpcprog = sep->se_rpcprog;
newtab->se_rpcversl = sep->se_rpcversl;
newtab->se_rpcversh = sep->se_rpcversh;
} else {
sep->se_family = AF_INET;
if (sep->se_proto[strlen(sep->se_proto) - 1] == '6')
-#ifdef CONFIG_FEATURE_IPV6
+#if ENABLE_FEATURE_IPV6
sep->se_family = AF_INET6;
#else
bb_error_msg("%s: IPV6 not supported", sep->se_proto);
#endif
if (strncmp(sep->se_proto, "rpc/", 4) == 0) {
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
char *p, *ccp;
long l;
*p++ = '\0';
l = strtol(p, &ccp, 0);
if (ccp == p || l < 0 || l > INT_MAX) {
- badafterall:
+ badafterall:
bb_error_msg("%s/%s: bad rpc version", sep->se_service, p);
goto more;
}
const struct builtin *bi;
for (bi = builtins; bi->bi_service; bi++)
- if (bi->bi_socktype == sep->se_socktype &&
- strcmp(bi->bi_service, sep->se_service) == 0)
+ if (bi->bi_socktype == sep->se_socktype
+ && strcmp(bi->bi_service, sep->se_service) == 0)
break;
if (bi->bi_service == 0) {
bb_error_msg("internal service %s unknown", sep->se_service);
goto more;
}
sep->se_bi = bi;
- sep->se_wait = bi->bi_wait;
+ sep->se_wait = 0; /* = bi->bi_wait; - always 0 */
#else
bb_perror_msg("internal service %s unknown", sep->se_service);
goto more;
if (LONE_CHAR(nsep->se_hostaddr, '*'))
nsep->se_ctrladdr_in.sin_addr.s_addr = INADDR_ANY;
else if (!inet_aton(nsep->se_hostaddr, &nsep->se_ctrladdr_in.sin_addr)) {
+ int i;
struct hostent *hp;
hp = gethostbyname(nsep->se_hostaddr);
- if (hp == 0) {
+ if (hp == NULL) {
bb_error_msg("%s: unknown host", nsep->se_hostaddr);
nsep->se_checked = 0;
goto skip;
- } else if (hp->h_addrtype != AF_INET) {
+ }
+ if (hp->h_addrtype != AF_INET) {
bb_error_msg("%s: address isn't an Internet "
"address", nsep->se_hostaddr);
nsep->se_checked = 0;
goto skip;
- } else {
- int i = 1;
-
- memmove(&nsep->se_ctrladdr_in.sin_addr,
- hp->h_addr_list[0], sizeof(struct in_addr));
- while (hp->h_addr_list[i] != NULL) {
- psep = dupconfig(nsep);
- psep->se_hostaddr = xxstrdup(nsep->se_hostaddr);
- psep->se_checked = 1;
- memmove(&psep->se_ctrladdr_in.sin_addr,
- hp->h_addr_list[i], sizeof(struct in_addr));
- psep->se_ctrladdr_size = sizeof(psep->se_ctrladdr_in);
- i++;
- /* Prepend to list, don't want to look up */
- /* its hostname again. */
- psep->se_next = sep;
- sep = psep;
- }
+ }
+ i = 1;
+ memmove(&nsep->se_ctrladdr_in.sin_addr,
+ hp->h_addr_list[0], sizeof(struct in_addr));
+ while (hp->h_addr_list[i] != NULL) {
+ psep = dupconfig(nsep);
+ psep->se_hostaddr = xxstrdup(nsep->se_hostaddr);
+ psep->se_checked = 1;
+ memmove(&psep->se_ctrladdr_in.sin_addr,
+ hp->h_addr_list[i], sizeof(struct in_addr));
+ psep->se_ctrladdr_size = sizeof(psep->se_ctrladdr_in);
+ i++;
+ /* Prepend to list, don't want to look up */
+ /* its hostname again. */
+ psep->se_next = sep;
+ sep = psep;
}
}
}
/* XXX BUG?: is this skip: label supposed to remain? */
- skip:
+ skip:
nsep = nsep->se_next;
}
sigaddset(&m, SIGHUP); \
sigaddset(&m, SIGALRM); \
sigprocmask(SIG_BLOCK, &m, NULL); \
-} while(0)
+} while (0)
static servtab_t *enter(servtab_t *cp)
{
sep = new_servtab();
*sep = *cp;
sep->se_fd = -1;
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
sep->se_rpcprog = -1;
#endif
Block_Using_Signals(omask);
sizeof(new->se_ctrladdr_in.sin_addr)) != 0)
return 0;
-#ifdef CONFIG_FEATURE_IPV6
+#if ENABLE_FEATURE_IPV6
if (old->se_family == AF_INET6 && new->se_family == AF_INET6 &&
memcmp(&old->se_ctrladdr_in6.sin6_addr,
&new->se_ctrladdr_in6.sin6_addr,
char protoname[10];
if (!setconfig()) {
- bb_perror_msg("%s", CONFIG);
+ bb_perror_msg("%s", config_filename);
return;
}
for (sep = servtab; sep; sep = sep->se_next)
SWAP(char *, sep->se_argv[i], cp->se_argv[i]);
#undef SWAP
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
if (isrpcservice(sep))
unregister_rpc(sep);
sep->se_rpcversl = cp->se_rpcversl;
/* se_ctrladdr_in was set in getconfigent */
sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in;
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
if (isrpcservice(sep)) {
struct rpcent *rp;
// FIXME: atoi_or_else(str, 0) would be handy here
setup(sep);
}
break;
-#ifdef CONFIG_FEATURE_IPV6
+#if ENABLE_FEATURE_IPV6
case AF_INET6:
sep->se_ctrladdr_in6.sin6_family = AF_INET6;
/* se_ctrladdr_in was set in getconfigent */
sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6;
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
if (isrpcservice(sep)) {
struct rpcent *rp;
setup(sep);
}
break;
-#endif /* CONFIG_FEATURE_IPV6 */
+#endif /* FEATURE_IPV6 */
}
- serv_unknown:
+ serv_unknown:
if (cp->se_next != NULL) {
servtab_t *tmp = cp;
nsock--;
(void) close(sep->se_fd);
}
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
if (isrpcservice(sep))
unregister_rpc(sep);
#endif
switch (sep->se_family) {
case AF_UNIX:
case AF_INET:
-#ifdef CONFIG_FEATURE_IPV6
+#if ENABLE_FEATURE_IPV6
case AF_INET6:
#endif
setup(sep);
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
if (sep->se_fd != -1 && isrpcservice(sep))
register_rpc(sep);
#endif
(void) unlink(sep->se_service);
break;
case AF_INET:
-#ifdef CONFIG_FEATURE_IPV6
+#if ENABLE_FEATURE_IPV6
case AF_INET6:
#endif
-#ifdef CONFIG_FEATURE_INETD_RPC
+#if ENABLE_FEATURE_INETD_RPC
if (sep->se_wait == 1 && isrpcservice(sep))
unregister_rpc(sep); /* XXX signal race */
#endif
}
(void) close(sep->se_fd);
}
- (void) unlink(_PATH_INETDPID);
+ remove_pidfile(_PATH_INETDPID);
exit(0);
}
#ifdef INETD_SETPROCTITLE
-static char **Argv;
-static char *LastArg;
static void
inetd_setproctitle(char *a, int s)
#endif
-int
-inetd_main(int argc, char *argv[])
+int inetd_main(int argc, char **argv);
+int inetd_main(int argc, char **argv)
{
servtab_t *sep;
struct passwd *pwd;
char buf[50];
char *stoomany;
sigset_t omask, wait_mask;
-
#ifdef INETD_SETPROCTITLE
- extern char **environ;
- char **envp = environ;
+ char **envp;
+#endif
+
+ INIT_G();
+#ifdef INETD_SETPROCTITLE
+ envp = environ;
Argv = argv;
if (envp == 0 || *envp == 0)
envp = argv;
LastArg = envp[-1] + strlen(envp[-1]);
#endif
- openlog(applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
+ uid = getuid();
+ if (uid != 0)
+ config_filename = NULL;
- opt = getopt32(argc, argv, "R:f", &stoomany);
- if(opt & 1) {
+ opt = getopt32(argv, "R:f", &stoomany);
+ if (opt & 1)
toomany = xatoi_u(stoomany);
- }
- argc -= optind;
argv += optind;
-
- uid = getuid();
- if (uid != 0)
- CONFIG = NULL;
- if (argc > 0)
- CONFIG = argv[0];
- if (CONFIG == NULL)
+ argc -= optind;
+ if (argc)
+ config_filename = argv[0];
+ if (config_filename == NULL)
bb_error_msg_and_die("non-root must specify a config file");
- if (!(opt & 2)) {
-#ifdef BB_NOMMU
- /* reexec for vfork() do continue parent */
- vfork_daemon_rexec(0, 0, argc, argv, "-f");
-#else
- xdaemon(0, 0);
-#endif
- } else {
- setsid();
- }
+ if (!(opt & 2))
+ bb_daemonize_or_rexec(0, argv - optind);
+ else
+ bb_sanitize_stdio();
+ openlog(applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON);
logmode = LOGMODE_SYSLOG;
if (uid == 0) {
- gid_t gid = getgid();
-
/* If run by hand, ensure groups vector gets trashed */
+ gid_t gid = getgid();
setgroups(1, &gid);
}
- {
- FILE *fp = fopen(_PATH_INETDPID, "w");
-
- if (fp != NULL) {
- fprintf(fp, "%u\n", getpid());
- (void) fclose(fp);
- }
- }
+ write_pidfile(_PATH_INETDPID);
if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) {
bb_perror_msg("getrlimit");
(*sep->se_bi->bi_fn)(ctrl, sep);
} else
#endif
- {
+ {
pwd = getpwnam(sep->se_user);
if (pwd == NULL) {
bb_error_msg("getpwnam: %s: no such user", sep->se_user);
sigaction(SIGPIPE, &sapipe, NULL);
execv(sep->se_server, sep->se_argv);
bb_perror_msg("execv %s", sep->se_server);
-do_exit1:
+ 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);
} /* for (sep = servtab...) */
- } /* for(;;) */
+ } /* for (;;) */
}
/*
*/
#define BUFSIZE 4096
-#if defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO) || \
- defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN) || \
- defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME)
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN || \
+ ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
static int dg_badinput(struct sockaddr_in *dg_sin)
{
if (ntohs(dg_sin->sin_port) < IPPORT_RESERVED)
}
#endif
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_ECHO
/* Echo service -- echo data back */
/* ARGSUSED */
static void
return;
(void) sendto(s, buffer, i, 0, &sa, sizeof(sa));
}
-#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO */
+#endif /* FEATURE_INETD_SUPPORT_BUILTIN_ECHO */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD
/* Discard service -- ignore data */
/* ARGSUSED */
static void
(void) read(s, buffer, sizeof(buffer));
}
-#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD */
+#endif /* FEATURE_INETD_SUPPORT_BUILTIN_DISCARD */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN
#define LINESIZ 72
-static char ring[128];
-static char *endring;
static void
initring(void)
int i;
endring = ring;
-
for (i = 0; i <= 128; ++i)
if (isprint(i))
*endring++ = i;
{
/* struct sockaddr_storage ss; */
struct sockaddr sa;
- static char *rs;
int len;
char text[LINESIZ + 2];
socklen_t size;
- if (endring == 0) {
+ if (!endring) {
initring();
- rs = ring;
+ ringpos = ring;
}
size = sizeof(sa);
if (dg_badinput((struct sockaddr_in *) &sa))
return;
- if ((len = endring - rs) >= LINESIZ)
- memmove(text, rs, LINESIZ);
+ len = endring - ringpos;
+ if (len >= LINESIZ)
+ memmove(text, ringpos, LINESIZ);
else {
- memmove(text, rs, len);
+ memmove(text, ringpos, len);
memmove(text + len, ring, LINESIZ - len);
}
- if (++rs == endring)
- rs = ring;
+ if (++ringpos == endring)
+ ringpos = ring;
text[LINESIZ] = '\r';
text[LINESIZ + 1] = '\n';
(void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa));
}
-#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN */
+#endif /* FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_TIME
/*
* Return a machine readable date and time, in the form of the
* number of seconds since midnight, Jan 1, 1900. Since gettimeofday
* some seventy years Bell Labs was asleep.
*/
-static u_int machtime(void)
+static unsigned machtime(void)
{
struct timeval tv;
fprintf(stderr, "Unable to get time of day\n");
return 0L;
}
- return htonl((u_int) tv.tv_sec + 2208988800UL);
+ return htonl((unsigned) tv.tv_sec + 2208988800UL);
}
/* ARGSUSED */
static void
machtime_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED)
{
- u_int result;
+ unsigned result;
result = machtime();
(void) write(s, (char *) &result, sizeof(result));
static void
machtime_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED)
{
- u_int result;
+ unsigned result;
/* struct sockaddr_storage ss; */
struct sockaddr sa;
struct sockaddr_in *dg_sin;
result = machtime();
(void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa));
}
-#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME */
+#endif /* FEATURE_INETD_SUPPORT_BUILTIN_TIME */
-#ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
+#if ENABLE_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME
/* Return human-readable time of day */
/* ARGSUSED */
static void daytime_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED)
{
- char buffer[256];
+ char buffer[32];
time_t t;
t = time(NULL);
+// fdprintf instead?
(void) sprintf(buffer, "%.24s\r\n", ctime(&t));
(void) write(s, buffer, strlen(buffer));
}
(void) sprintf(buffer, "%.24s\r\n", ctime(&t));
(void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa));
}
-#endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME */
+#endif /* FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME */