aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorDenis Vlasenko <vda.linux@googlemail.com>2007-01-14 01:29:06 +0000
committerDenis Vlasenko <vda.linux@googlemail.com>2007-01-14 01:29:06 +0000
commit7a431b3715299854fb423ec00d5fafc0e2c7f07b (patch)
tree4e90c9d364485ef13c2e429ab22b9b925d50ea04
parent150f402b36197d822f8a7dd835231cd67b77e959 (diff)
downloadbusybox-w32-7a431b3715299854fb423ec00d5fafc0e2c7f07b.tar.gz
busybox-w32-7a431b3715299854fb423ec00d5fafc0e2c7f07b.tar.bz2
busybox-w32-7a431b3715299854fb423ec00d5fafc0e2c7f07b.zip
By popular request reinstate fakeidentd's standalone mode.
Since this is also needed for other applets like telnetd, introduce generic driver for such things. It even supports inetd-wait ('linger') mode, when inetd hands out listen socket to child and waits to it to die, instead of handing out accepted socket and continuing listening itself (nowait mode). Code growth ~200 bytes. NB: our inetd doesn't support wait mode yet (or mabe it is buggy).
-rw-r--r--include/libbb.h2
-rw-r--r--include/usage.h22
-rw-r--r--libbb/xfuncs.c24
-rw-r--r--networking/Kbuild3
-rw-r--r--networking/inetd.c15
-rw-r--r--networking/isrv.c337
-rw-r--r--networking/isrv_identd.c144
7 files changed, 523 insertions, 24 deletions
diff --git a/include/libbb.h b/include/libbb.h
index 4060498b8..c191dc2a0 100644
--- a/include/libbb.h
+++ b/include/libbb.h
@@ -278,6 +278,8 @@ extern int wait4pid(int pid);
278extern void xsetgid(gid_t gid); 278extern void xsetgid(gid_t gid);
279extern void xsetuid(uid_t uid); 279extern void xsetuid(uid_t uid);
280extern void xdaemon(int nochdir, int noclose); 280extern void xdaemon(int nochdir, int noclose);
281/* More clever/thorough xdaemon */
282extern void bb_sanitize_stdio(int daemonize);
281extern void xchdir(const char *path); 283extern void xchdir(const char *path);
282extern void xsetenv(const char *key, const char *value); 284extern void xsetenv(const char *key, const char *value);
283extern int xopen(const char *pathname, int flags); 285extern int xopen(const char *pathname, int flags);
diff --git a/include/usage.h b/include/usage.h
index 0275df3f0..2b51fad72 100644
--- a/include/usage.h
+++ b/include/usage.h
@@ -826,22 +826,16 @@
826 "\\( and \\) or null; if \\( and \\) are not used, they return the number\n" \ 826 "\\( and \\) or null; if \\( and \\) are not used, they return the number\n" \
827 "of characters matched or 0." 827 "of characters matched or 0."
828 828
829#if 0 /* bloaty */
830#define fakeidentd_trivial_usage \ 829#define fakeidentd_trivial_usage \
831 "[-b ip] [STRING]" 830 "[-fiw] [-b ADDR] [STRING]"
832#define fakeidentd_full_usage \ 831#define fakeidentd_full_usage \
833 "Return a set string to auth requests" \ 832 "Provide fake ident (auth) service" \
834 "\n\nOptions:\n" \ 833 "\n\nOptions:" \
835 " -b Bind to ip address\n" \ 834 "\n -f Run in foreground" \
836 " STRING The ident answer string (default is nobody)" 835 "\n -i Inetd mode" \
837#else /* inetd-only */ 836 "\n -w Inetd 'wait' mode" \
838#define fakeidentd_trivial_usage \ 837 "\n -b ADDR Bind to specified address" \
839 "[username]" 838 "\n STRING Ident answer string (default is 'nobody')"
840#define fakeidentd_full_usage \
841 "Return a (faked) ident response.\n" \
842 "This applet is meant to run from inetd.\n" \
843 "Optional argument is the username to return (default is 'nobody')."
844#endif
845 839
846#define false_trivial_usage \ 840#define false_trivial_usage \
847 "" 841 ""
diff --git a/libbb/xfuncs.c b/libbb/xfuncs.c
index 207537929..6a6bdced3 100644
--- a/libbb/xfuncs.c
+++ b/libbb/xfuncs.c
@@ -509,6 +509,30 @@ void xdaemon(int nochdir, int noclose)
509} 509}
510#endif 510#endif
511 511
512void bb_sanitize_stdio(int daemonize)
513{
514 int fd;
515 /* Mega-paranoid */
516 fd = xopen(bb_dev_null, O_RDWR);
517 while (fd < 2)
518 fd = dup(fd); /* have 0,1,2 open at least to /dev/null */
519 if (daemonize) {
520 pid_t pid = fork();
521 if (pid < 0) /* wtf? */
522 bb_perror_msg_and_die("fork");
523 if (pid) /* parent */
524 exit(0);
525 /* child */
526 setsid();
527 /* if daemonizing, make sure we detach from stdio */
528 dup2(fd, 0);
529 dup2(fd, 1);
530 dup2(fd, 2);
531 }
532 while (fd > 2)
533 close(fd--); /* close everything after fd#2 */
534}
535
512// Die with an error message if we can't open a new socket. 536// Die with an error message if we can't open a new socket.
513int xsocket(int domain, int type, int protocol) 537int xsocket(int domain, int type, int protocol)
514{ 538{
diff --git a/networking/Kbuild b/networking/Kbuild
index 4c29e45a8..bb024c9b7 100644
--- a/networking/Kbuild
+++ b/networking/Kbuild
@@ -9,7 +9,8 @@ lib-$(CONFIG_ARP) += arp.o interface.o
9lib-$(CONFIG_ARPING) += arping.o 9lib-$(CONFIG_ARPING) += arping.o
10lib-$(CONFIG_DNSD) += dnsd.o 10lib-$(CONFIG_DNSD) += dnsd.o
11lib-$(CONFIG_ETHER_WAKE) += ether-wake.o 11lib-$(CONFIG_ETHER_WAKE) += ether-wake.o
12lib-$(CONFIG_FAKEIDENTD) += fakeidentd.o 12#lib-$(CONFIG_FAKEIDENTD) += fakeidentd.o
13lib-$(CONFIG_FAKEIDENTD) += isrv_identd.o isrv.o
13lib-$(CONFIG_FTPGET) += ftpgetput.o 14lib-$(CONFIG_FTPGET) += ftpgetput.o
14lib-$(CONFIG_FTPPUT) += ftpgetput.o 15lib-$(CONFIG_FTPPUT) += ftpgetput.o
15lib-$(CONFIG_HOSTNAME) += hostname.o 16lib-$(CONFIG_HOSTNAME) += hostname.o
diff --git a/networking/inetd.c b/networking/inetd.c
index 93c16bf60..f9f3b51b6 100644
--- a/networking/inetd.c
+++ b/networking/inetd.c
@@ -1289,31 +1289,28 @@ inetd_main(int argc, char *argv[])
1289 if (CONFIG == NULL) 1289 if (CONFIG == NULL)
1290 bb_error_msg_and_die("non-root must specify a config file"); 1290 bb_error_msg_and_die("non-root must specify a config file");
1291 1291
1292 if (!(opt & 2)) {
1293#ifdef BB_NOMMU 1292#ifdef BB_NOMMU
1293 if (!(opt & 2)) {
1294 /* reexec for vfork() do continue parent */ 1294 /* reexec for vfork() do continue parent */
1295 vfork_daemon_rexec(0, 0, argc, argv, "-f"); 1295 vfork_daemon_rexec(0, 0, argc, argv, "-f");
1296 }
1297 bb_sanitize_stdio(0);
1296#else 1298#else
1297 xdaemon(0, 0); 1299 bb_sanitize_stdio(!(opt & 2));
1298#endif 1300#endif
1299 } else {
1300 setsid();
1301 }
1302 logmode = LOGMODE_SYSLOG; 1301 logmode = LOGMODE_SYSLOG;
1303 1302
1304 if (uid == 0) { 1303 if (uid == 0) {
1305 gid_t gid = getgid();
1306
1307 /* If run by hand, ensure groups vector gets trashed */ 1304 /* If run by hand, ensure groups vector gets trashed */
1305 gid_t gid = getgid();
1308 setgroups(1, &gid); 1306 setgroups(1, &gid);
1309 } 1307 }
1310 1308
1311 { 1309 {
1312 FILE *fp = fopen(_PATH_INETDPID, "w"); 1310 FILE *fp = fopen(_PATH_INETDPID, "w");
1313
1314 if (fp != NULL) { 1311 if (fp != NULL) {
1315 fprintf(fp, "%u\n", getpid()); 1312 fprintf(fp, "%u\n", getpid());
1316 (void) fclose(fp); 1313 fclose(fp);
1317 } 1314 }
1318 } 1315 }
1319 1316
diff --git a/networking/isrv.c b/networking/isrv.c
new file mode 100644
index 000000000..02ca1d787
--- /dev/null
+++ b/networking/isrv.c
@@ -0,0 +1,337 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Generic non-forking server infrastructure.
4 * Intended to make writing telnetd-type servers easier.
5 *
6 * Copyright (C) 2007 Denis Vlasenko
7 *
8 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
9 */
10
11#include "busybox.h"
12#include "isrv.h"
13
14#define DEBUG 0
15
16#if DEBUG
17#define DPRINTF(args...) bb_error_msg(args)
18#else
19#define DPRINTF(args...) ((void)0)
20#endif
21
22/* Helpers */
23
24#if 0 /*def _POSIX_MONOTONIC_CLOCK*/
25static time_t monotonic_time(void)
26{
27 struct timespec ts;
28 if (clock_gettime(CLOCK_MONOTONIC, &ts) != 0)
29 time(&ts.tv_sec);
30 return ts.tv_sec;
31}
32#else
33#define monotonic_time() (time(NULL))
34#endif
35
36/* Opaque structure */
37
38struct isrv_state_t {
39 short *fd2peer; /* one per registered fd */
40 void **param_tbl; /* one per registered peer */
41 /* one per registered peer; doesn't exist if !timeout */
42 time_t *timeo_tbl;
43 int (*new_peer)(isrv_state_t *state, int fd);
44 time_t curtime;
45 int timeout;
46 int fd_count;
47 int peer_count;
48 int wr_count;
49 fd_set rd;
50 fd_set wr;
51};
52#define FD2PEER (state->fd2peer)
53#define PARAM_TBL (state->param_tbl)
54#define TIMEO_TBL (state->timeo_tbl)
55#define CURTIME (state->curtime)
56#define TIMEOUT (state->timeout)
57#define FD_COUNT (state->fd_count)
58#define PEER_COUNT (state->peer_count)
59#define WR_COUNT (state->wr_count)
60
61/* callback */
62void isrv_want_rd(isrv_state_t *state, int fd)
63{
64 FD_SET(fd, &state->rd);
65}
66
67/* callback */
68void isrv_want_wr(isrv_state_t *state, int fd)
69{
70 if (!FD_ISSET(fd, &state->wr)) {
71 WR_COUNT++;
72 FD_SET(fd, &state->wr);
73 }
74}
75
76/* callback */
77void isrv_dont_want_rd(isrv_state_t *state, int fd)
78{
79 FD_CLR(fd, &state->rd);
80}
81
82/* callback */
83void isrv_dont_want_wr(isrv_state_t *state, int fd)
84{
85 if (FD_ISSET(fd, &state->wr)) {
86 WR_COUNT--;
87 FD_CLR(fd, &state->wr);
88 }
89}
90
91/* callback */
92int isrv_register_fd(isrv_state_t *state, int peer, int fd)
93{
94 int n;
95
96 DPRINTF("register_fd(peer:%d,fd:%d)", peer, fd);
97
98 if (FD_COUNT >= FD_SETSIZE) return -1;
99 if (FD_COUNT <= fd) {
100 n = FD_COUNT;
101 FD_COUNT = fd + 1;
102
103 DPRINTF("register_fd: FD_COUNT %d", FD_COUNT);
104
105 FD2PEER = xrealloc(FD2PEER, FD_COUNT * sizeof(FD2PEER[0]));
106 while (n < fd) FD2PEER[n++] = -1;
107 }
108
109 DPRINTF("register_fd: FD2PEER[%d] = %d", fd, peer);
110
111 FD2PEER[fd] = peer;
112 return 0;
113}
114
115/* callback */
116void isrv_close_fd(isrv_state_t *state, int fd)
117{
118 DPRINTF("close_fd(%d)", fd);
119
120 close(fd);
121 isrv_dont_want_rd(state, fd);
122 if (WR_COUNT) isrv_dont_want_wr(state, fd);
123
124 FD2PEER[fd] = -1;
125 if (fd == FD_COUNT-1) {
126 do fd--; while (fd >= 0 && FD2PEER[fd] == -1);
127 FD_COUNT = fd + 1;
128
129 DPRINTF("close_fd: FD_COUNT %d", FD_COUNT);
130
131 FD2PEER = xrealloc(FD2PEER, FD_COUNT * sizeof(FD2PEER[0]));
132 }
133}
134
135/* callback */
136int isrv_register_peer(isrv_state_t *state, void *param)
137{
138 int n;
139
140 if (PEER_COUNT >= FD_SETSIZE) return -1;
141 n = PEER_COUNT++;
142
143 DPRINTF("register_peer: PEER_COUNT %d", PEER_COUNT);
144
145 PARAM_TBL = xrealloc(PARAM_TBL, PEER_COUNT * sizeof(PARAM_TBL[0]));
146 PARAM_TBL[n] = param;
147 if (TIMEOUT) {
148 TIMEO_TBL = xrealloc(TIMEO_TBL, PEER_COUNT * sizeof(TIMEO_TBL[0]));
149 TIMEO_TBL[n] = CURTIME;
150 }
151 return n;
152}
153
154static void remove_peer(isrv_state_t *state, int peer)
155{
156 int movesize;
157 int fd;
158
159 DPRINTF("remove_peer(%d)", peer);
160
161 fd = FD_COUNT - 1;
162 while (fd >= 0) {
163 if (FD2PEER[fd] == peer) {
164 isrv_close_fd(state, fd);
165 fd--;
166 continue;
167 }
168 if (FD2PEER[fd] > peer)
169 FD2PEER[fd]--;
170 fd--;
171 }
172
173 PEER_COUNT--;
174 DPRINTF("remove_peer: PEER_COUNT %d", PEER_COUNT);
175
176 movesize = (PEER_COUNT - peer) * sizeof(void*);
177 if (movesize > 0) {
178 memcpy(&PARAM_TBL[peer], &PARAM_TBL[peer+1], movesize);
179 if (TIMEOUT)
180 memcpy(&TIMEO_TBL[peer], &TIMEO_TBL[peer+1], movesize);
181 }
182 PARAM_TBL = xrealloc(PARAM_TBL, PEER_COUNT * sizeof(PARAM_TBL[0]));
183 if (TIMEOUT)
184 TIMEO_TBL = xrealloc(TIMEO_TBL, PEER_COUNT * sizeof(TIMEO_TBL[0]));
185}
186
187static void handle_accept(isrv_state_t *state, int fd)
188{
189 int n, newfd;
190
191 fcntl(fd, F_SETFL, (int)(PARAM_TBL[0]) | O_NONBLOCK);
192 newfd = accept(fd, NULL, 0);
193 fcntl(fd, F_SETFL, (int)(PARAM_TBL[0]));
194 if (newfd < 0) {
195 if (errno == EAGAIN) return;
196 /* Most probably someone gave us wrong fd type
197 * (for example, non-socket) */
198 bb_perror_msg_and_die("accept");
199 }
200
201 DPRINTF("new_peer(%d)", newfd);
202 n = state->new_peer(state, newfd);
203 if (n)
204 remove_peer(state, n); /* unsuccesful peer start */
205}
206
207void BUG_sizeof_fd_set_is_strange(void);
208static void handle_fd_set(isrv_state_t *state, fd_set *fds, int (*h)(int, void **))
209{
210 enum { LONG_CNT = sizeof(fd_set) / sizeof(long) };
211 int fds_pos;
212 int fd, peer;
213 int fd_cnt = FD_COUNT;
214
215 if (LONG_CNT * sizeof(long) != sizeof(fd_set))
216 BUG_sizeof_fd_set_is_strange();
217
218 fds_pos = 0;
219 while (1) {
220 /* Find next nonzero bit */
221 while (fds_pos < LONG_CNT) {
222 if (((long*)fds)[fds_pos] == 0) {
223 fds_pos++;
224 continue;
225 }
226 /* Found non-zero word */
227 fd = fds_pos * sizeof(long)*8; /* word# -> bit# */
228 while (1) {
229 if (FD_ISSET(fd, fds)) {
230 FD_CLR(fd, fds);
231 goto found_fd;
232 }
233 fd++;
234 }
235 }
236 break; /* all words are zero */
237 found_fd:
238 if (fd >= fd_cnt) /* paranoia */
239 break;
240 DPRINTF("handle_fd_set: fd %d is active", fd);
241 peer = FD2PEER[fd];
242 if (peer == 0) {
243 handle_accept(state, fd);
244 continue;
245 }
246 DPRINTF("h(fd:%d)", fd);
247 if (h(fd, &PARAM_TBL[peer])) {
248 /* this peer is gone */
249 remove_peer(state, peer);
250 } else if (TIMEOUT) {
251 TIMEO_TBL[peer] = monotonic_time();
252 }
253 }
254}
255
256static void handle_timeout(isrv_state_t *state, int (*do_timeout)(void **))
257{
258 int n, peer;
259 peer = PEER_COUNT-1;
260 /* peer 0 is not checked */
261 while (peer > 0) {
262 DPRINTF("peer %d: time diff %d", peer, (int)(CURTIME - TIMEO_TBL[peer]));
263
264 if ((CURTIME - TIMEO_TBL[peer]) > TIMEOUT) {
265 DPRINTF("peer %d: do_timeout()", peer);
266 n = do_timeout(&PARAM_TBL[peer]);
267 if (n)
268 remove_peer(state, peer);
269 }
270 peer--;
271 }
272}
273
274/* Driver */
275void isrv_run(
276 int listen_fd,
277 int (*new_peer)(isrv_state_t *state, int fd),
278 int (*do_rd)(int fd, void **),
279 int (*do_wr)(int fd, void **),
280 int (*do_timeout)(void **),
281 int timeout,
282 int exit_if_no_clients)
283{
284 isrv_state_t *state = xzalloc(sizeof(*state));
285 state->new_peer = new_peer;
286 state->timeout = timeout;
287
288 /* register "peer" #0 - it will accept new connections */
289 isrv_register_peer(state, NULL);
290 isrv_register_fd(state, /*peer:*/ 0, listen_fd);
291 isrv_want_rd(state, listen_fd);
292 /* remember flags to make blocking<->nonblocking switch faster */
293 PARAM_TBL[0] = (void*) (fcntl(listen_fd, F_GETFL, 0));
294
295 while (1) {
296 struct timeval tv;
297 fd_set rd;
298 fd_set wr;
299 fd_set *wrp = NULL;
300 int n;
301
302 tv.tv_sec = timeout;
303 tv.tv_usec = 0;
304 rd = state->rd;
305 if (WR_COUNT) {
306 wr = state->wr;
307 wrp = &wr;
308 }
309
310 DPRINTF("run: select(FD_COUNT:%d,timeout:%d)...", FD_COUNT, timeout);
311 n = select(FD_COUNT, &rd, wrp, NULL, timeout ? &tv : NULL);
312 DPRINTF("run: ...select:%d", n);
313
314 if (n < 0) {
315 if (errno != EINTR)
316 bb_perror_msg("select");
317 continue;
318 }
319
320 if (exit_if_no_clients && n == 0 && PEER_COUNT <= 1)
321 break;
322
323 if (timeout) {
324 time_t t = monotonic_time();
325 if (t != CURTIME) {
326 CURTIME = t;
327 handle_timeout(state, do_timeout);
328 }
329 }
330 if (n > 0) {
331 handle_fd_set(state, &rd, do_rd);
332 if (wrp)
333 handle_fd_set(state, wrp, do_wr);
334 }
335 }
336 DPRINTF("run: bailout");
337}
diff --git a/networking/isrv_identd.c b/networking/isrv_identd.c
new file mode 100644
index 000000000..b9481f8d3
--- /dev/null
+++ b/networking/isrv_identd.c
@@ -0,0 +1,144 @@
1/* vi: set sw=4 ts=4: */
2/*
3 * Fake identd server.
4 *
5 * Copyright (C) 2007 Denis Vlasenko
6 *
7 * Licensed under GPL version 2, see file LICENSE in this tarball for details.
8 */
9
10#include <syslog.h>
11#include "busybox.h"
12#include "isrv.h"
13
14enum { TIMEOUT = 20 };
15
16/* Why use alarm(TIMEOUT-1)?
17 * isrv's internal select() will run with timeout=TIMEOUT.
18 * If nothing happens during TIMEOUT-1 seconds (no accept/read),
19 * then ALL sessions timed out by now. Instead of closing them one-by-one
20 * (isrv calls do_timeout for each 'stale' session),
21 * SIGALRM triggered by alarm(TIMEOUT-1) will kill us, terminating them all.
22 */
23
24typedef struct identd_buf_t {
25 int pos;
26 int fd_flag;
27 char buf[64 - 2*sizeof(int)];
28} identd_buf_t;
29
30static const char *bogouser = "nobody";
31
32static int new_peer(isrv_state_t *state, int fd)
33{
34 int peer;
35 identd_buf_t *buf = xzalloc(sizeof(*buf));
36
37 alarm(TIMEOUT - 1);
38
39 peer = isrv_register_peer(state, buf);
40 if (peer < 0)
41 return 0; /* failure */
42 if (isrv_register_fd(state, peer, fd) < 0)
43 return peer; /* failure, unregister peer */
44
45 buf->fd_flag = fcntl(fd, F_GETFL, 0) | O_NONBLOCK;
46 isrv_want_rd(state, fd);
47 return 0;
48}
49
50static int do_rd(int fd, void **paramp)
51{
52 identd_buf_t *buf = *paramp;
53 char *cur, *p;
54 int sz;
55
56 alarm(TIMEOUT - 1);
57
58 cur = buf->buf + buf->pos;
59
60 fcntl(fd, F_SETFL, buf->fd_flag | O_NONBLOCK);
61 sz = safe_read(fd, cur, sizeof(buf->buf) - buf->pos);
62
63 if (sz < 0) {
64 if (errno != EAGAIN)
65 goto term; /* terminate this session if !EAGAIN */
66 goto ok;
67 }
68
69 buf->pos += sz;
70 buf->buf[buf->pos] = '\0';
71 p = strpbrk(cur, "\r\n");
72 if (p)
73 *p = '\0';
74 if (p || !sz || buf->pos == sizeof(buf->buf)) {
75 /* fd is still in nonblocking mode - we never block here */
76 fdprintf(fd, "%s : USERID : UNIX : %s\r\n", buf->buf, bogouser);
77 goto term;
78 }
79 ok:
80 fcntl(fd, F_SETFL, buf->fd_flag & ~O_NONBLOCK);
81 return 0;
82 term:
83 fcntl(fd, F_SETFL, buf->fd_flag & ~O_NONBLOCK);
84 free(buf);
85 return 1;
86}
87
88static int do_timeout(void **paramp)
89{
90 return 1; /* terminate session */
91}
92
93static void inetd_mode(void)
94{
95 identd_buf_t *buf = xzalloc(sizeof(*buf));
96 /* We do NOT want nonblocking I/O here! */
97 buf->fd_flag = fcntl(0, F_GETFL, 0);
98 while (do_rd(0, (void*)&buf) == 0) /* repeat */;
99}
100
101int fakeidentd_main(int argc, char **argv)
102{
103 enum {
104 OPT_foreground = 0x1,
105 OPT_inetd = 0x2,
106 OPT_inetdwait = 0x4,
107 OPT_nodeamon = 0x7,
108 OPT_bindaddr = 0x8,
109 };
110
111 const char *bind_address = NULL;
112 unsigned opt;
113 int fd;
114
115 opt = getopt32(argc, argv, "fiwb:", &bind_address);
116 if (optind < argc)
117 bogouser = argv[optind];
118
119 /* Daemonize if no -f or -i or -w */
120 bb_sanitize_stdio(!(opt & OPT_nodeamon));
121 if (!(opt & OPT_nodeamon)) {
122 openlog(applet_name, 0, LOG_DAEMON);
123 logmode = LOGMODE_SYSLOG;
124 }
125
126 if (opt & OPT_inetd) {
127 inetd_mode();
128 return 0;
129 }
130
131 /* Ignore closed connections when writing */
132 signal(SIGPIPE, SIG_IGN);
133
134 if (opt & OPT_inetdwait) {
135 fd = 0;
136 } else {
137 fd = create_and_bind_stream_or_die(bind_address,
138 bb_lookup_port("identd", "tcp", 113));
139 xlisten(fd, 5);
140 }
141
142 isrv_run(fd, new_peer, do_rd, NULL, do_timeout, TIMEOUT, 1);
143 return 0;
144}