diff options
author | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-23 15:18:38 +0000 |
---|---|---|
committer | Denis Vlasenko <vda.linux@googlemail.com> | 2006-09-23 15:18:38 +0000 |
commit | ec17d437ab8042a5ad9e7c836f01b56c8795d80b (patch) | |
tree | 76f567ed83867c1d711f3bf8ee9208e13ba47477 | |
parent | 2dbeaa95ca2c22c5e37f62b01e4324a308f0140f (diff) | |
download | busybox-w32-ec17d437ab8042a5ad9e7c836f01b56c8795d80b.tar.gz busybox-w32-ec17d437ab8042a5ad9e7c836f01b56c8795d80b.tar.bz2 busybox-w32-ec17d437ab8042a5ad9e7c836f01b56c8795d80b.zip |
inetd: reformat with tabs for indentation
-rw-r--r-- | networking/inetd.c | 2437 |
1 files changed, 1220 insertions, 1217 deletions
diff --git a/networking/inetd.c b/networking/inetd.c index e47022350..d6265d875 100644 --- a/networking/inetd.c +++ b/networking/inetd.c | |||
@@ -170,63 +170,63 @@ static struct rlimit rlim_ofile; | |||
170 | 170 | ||
171 | /* Check unsupporting builtin */ | 171 | /* Check unsupporting builtin */ |
172 | #if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \ | 172 | #if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \ |
173 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \ | 173 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \ |
174 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME || \ | 174 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME || \ |
175 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME || \ | 175 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME || \ |
176 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 176 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
177 | # define INETD_FEATURE_ENABLED | 177 | # define INETD_FEATURE_ENABLED |
178 | #endif | 178 | #endif |
179 | 179 | ||
180 | #if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \ | 180 | #if defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO || \ |
181 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \ | 181 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD || \ |
182 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 182 | defined CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
183 | # define INETD_SETPROCTITLE | 183 | # define INETD_SETPROCTITLE |
184 | #endif | 184 | #endif |
185 | 185 | ||
186 | typedef struct servtab | 186 | typedef struct servtab |
187 | { | 187 | { |
188 | char *se_hostaddr; /* host address to listen on */ | 188 | char *se_hostaddr; /* host address to listen on */ |
189 | char *se_service; /* name of service */ | 189 | char *se_service; /* name of service */ |
190 | int se_socktype; /* type of socket to use */ | 190 | int se_socktype; /* type of socket to use */ |
191 | int se_family; /* address family */ | 191 | int se_family; /* address family */ |
192 | char *se_proto; /* protocol used */ | 192 | char *se_proto; /* protocol used */ |
193 | #ifdef CONFIG_FEATURE_INETD_RPC | 193 | #ifdef CONFIG_FEATURE_INETD_RPC |
194 | int se_rpcprog; /* rpc program number */ | 194 | int se_rpcprog; /* rpc program number */ |
195 | int se_rpcversl; /* rpc program lowest version */ | 195 | int se_rpcversl; /* rpc program lowest version */ |
196 | int se_rpcversh; /* rpc program highest version */ | 196 | int se_rpcversh; /* rpc program highest version */ |
197 | #define isrpcservice(sep) ((sep)->se_rpcversl != 0) | 197 | #define isrpcservice(sep) ((sep)->se_rpcversl != 0) |
198 | #else | 198 | #else |
199 | #define isrpcservice(sep) 0 | 199 | #define isrpcservice(sep) 0 |
200 | #endif | 200 | #endif |
201 | pid_t se_wait; /* single threaded server */ | 201 | pid_t se_wait; /* single threaded server */ |
202 | short se_checked; /* looked at during merge */ | 202 | short se_checked; /* looked at during merge */ |
203 | char *se_user; /* user name to run as */ | 203 | char *se_user; /* user name to run as */ |
204 | char *se_group; /* group name to run as */ | 204 | char *se_group; /* group name to run as */ |
205 | #ifdef INETD_FEATURE_ENABLED | 205 | #ifdef INETD_FEATURE_ENABLED |
206 | const struct builtin *se_bi; /* if built-in, description */ | 206 | const struct builtin *se_bi; /* if built-in, description */ |
207 | #endif | 207 | #endif |
208 | char *se_server; /* server program */ | 208 | char *se_server; /* server program */ |
209 | #define MAXARGV 20 | 209 | #define MAXARGV 20 |
210 | char *se_argv[MAXARGV + 1]; /* program arguments */ | 210 | char *se_argv[MAXARGV + 1]; /* program arguments */ |
211 | int se_fd; /* open descriptor */ | 211 | int se_fd; /* open descriptor */ |
212 | union | 212 | union |
213 | { | 213 | { |
214 | struct sockaddr se_un_ctrladdr; | 214 | struct sockaddr se_un_ctrladdr; |
215 | struct sockaddr_in se_un_ctrladdr_in; | 215 | struct sockaddr_in se_un_ctrladdr_in; |
216 | #ifdef CONFIG_FEATURE_IPV6 | 216 | #ifdef CONFIG_FEATURE_IPV6 |
217 | struct sockaddr_in6 se_un_ctrladdr_in6; | 217 | struct sockaddr_in6 se_un_ctrladdr_in6; |
218 | #endif | 218 | #endif |
219 | struct sockaddr_un se_un_ctrladdr_un; | 219 | struct sockaddr_un se_un_ctrladdr_un; |
220 | } se_un; /* bound address */ | 220 | } se_un; /* bound address */ |
221 | #define se_ctrladdr se_un.se_un_ctrladdr | 221 | #define se_ctrladdr se_un.se_un_ctrladdr |
222 | #define se_ctrladdr_in se_un.se_un_ctrladdr_in | 222 | #define se_ctrladdr_in se_un.se_un_ctrladdr_in |
223 | #define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6 | 223 | #define se_ctrladdr_in6 se_un.se_un_ctrladdr_in6 |
224 | #define se_ctrladdr_un se_un.se_un_ctrladdr_un | 224 | #define se_ctrladdr_un se_un.se_un_ctrladdr_un |
225 | int se_ctrladdr_size; | 225 | int se_ctrladdr_size; |
226 | int se_max; /* max # of instances of this service */ | 226 | int se_max; /* max # of instances of this service */ |
227 | int se_count; /* number started since se_time */ | 227 | int se_count; /* number started since se_time */ |
228 | struct timeval se_time; /* start of se_count */ | 228 | struct timeval se_time; /* start of se_count */ |
229 | struct servtab *se_next; | 229 | struct servtab *se_next; |
230 | } servtab_t; | 230 | } servtab_t; |
231 | 231 | ||
232 | static servtab_t *servtab; | 232 | static servtab_t *servtab; |
@@ -234,66 +234,66 @@ static servtab_t *servtab; | |||
234 | #ifdef INETD_FEATURE_ENABLED | 234 | #ifdef INETD_FEATURE_ENABLED |
235 | struct builtin | 235 | struct builtin |
236 | { | 236 | { |
237 | const char *bi_service; /* internally provided service name */ | 237 | const char *bi_service; /* internally provided service name */ |
238 | int bi_socktype; /* type of socket supported */ | 238 | int bi_socktype; /* type of socket supported */ |
239 | short bi_fork; /* 1 if should fork before call */ | 239 | short bi_fork; /* 1 if should fork before call */ |
240 | short bi_wait; /* 1 if should wait for child */ | 240 | short bi_wait; /* 1 if should wait for child */ |
241 | void (*bi_fn) (int, servtab_t *); | 241 | void (*bi_fn) (int, servtab_t *); |
242 | }; | 242 | }; |
243 | 243 | ||
244 | /* Echo received data */ | 244 | /* Echo received data */ |
245 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 245 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
246 | static void echo_stream (int, servtab_t *); | 246 | static void echo_stream(int, servtab_t *); |
247 | static void echo_dg (int, servtab_t *); | 247 | static void echo_dg(int, servtab_t *); |
248 | #endif | 248 | #endif |
249 | /* Internet /dev/null */ | 249 | /* Internet /dev/null */ |
250 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | 250 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD |
251 | static void discard_stream (int, servtab_t *); | 251 | static void discard_stream(int, servtab_t *); |
252 | static void discard_dg (int, servtab_t *); | 252 | static void discard_dg(int, servtab_t *); |
253 | #endif | 253 | #endif |
254 | /* Return 32 bit time since 1900 */ | 254 | /* Return 32 bit time since 1900 */ |
255 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME | 255 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME |
256 | static void machtime_stream (int, servtab_t *); | 256 | static void machtime_stream(int, servtab_t *); |
257 | static void machtime_dg (int, servtab_t *); | 257 | static void machtime_dg(int, servtab_t *); |
258 | #endif | 258 | #endif |
259 | /* Return human-readable time */ | 259 | /* Return human-readable time */ |
260 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 260 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
261 | static void daytime_stream (int, servtab_t *); | 261 | static void daytime_stream(int, servtab_t *); |
262 | static void daytime_dg (int, servtab_t *); | 262 | static void daytime_dg(int, servtab_t *); |
263 | #endif | 263 | #endif |
264 | /* Familiar character generator */ | 264 | /* Familiar character generator */ |
265 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 265 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
266 | static void chargen_stream (int, servtab_t *); | 266 | static void chargen_stream(int, servtab_t *); |
267 | static void chargen_dg (int, servtab_t *); | 267 | static void chargen_dg(int, servtab_t *); |
268 | #endif | 268 | #endif |
269 | 269 | ||
270 | static const struct builtin builtins[] = { | 270 | static const struct builtin builtins[] = { |
271 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO | 271 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO |
272 | /* Echo received data */ | 272 | /* Echo received data */ |
273 | {"echo", SOCK_STREAM, 1, 0, echo_stream,}, | 273 | {"echo", SOCK_STREAM, 1, 0, echo_stream,}, |
274 | {"echo", SOCK_DGRAM, 0, 0, echo_dg,}, | 274 | {"echo", SOCK_DGRAM, 0, 0, echo_dg,}, |
275 | #endif | 275 | #endif |
276 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD | 276 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD |
277 | /* Internet /dev/null */ | 277 | /* Internet /dev/null */ |
278 | {"discard", SOCK_STREAM, 1, 0, discard_stream,}, | 278 | {"discard", SOCK_STREAM, 1, 0, discard_stream,}, |
279 | {"discard", SOCK_DGRAM, 0, 0, discard_dg,}, | 279 | {"discard", SOCK_DGRAM, 0, 0, discard_dg,}, |
280 | #endif | 280 | #endif |
281 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME | 281 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME |
282 | /* Return 32 bit time since 1900 */ | 282 | /* Return 32 bit time since 1900 */ |
283 | {"time", SOCK_STREAM, 0, 0, machtime_stream,}, | 283 | {"time", SOCK_STREAM, 0, 0, machtime_stream,}, |
284 | {"time", SOCK_DGRAM, 0, 0, machtime_dg,}, | 284 | {"time", SOCK_DGRAM, 0, 0, machtime_dg,}, |
285 | #endif | 285 | #endif |
286 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 286 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
287 | /* Return human-readable time */ | 287 | /* Return human-readable time */ |
288 | {"daytime", SOCK_STREAM, 0, 0, daytime_stream,}, | 288 | {"daytime", SOCK_STREAM, 0, 0, daytime_stream,}, |
289 | {"daytime", SOCK_DGRAM, 0, 0, daytime_dg,}, | 289 | {"daytime", SOCK_DGRAM, 0, 0, daytime_dg,}, |
290 | #endif | 290 | #endif |
291 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN | 291 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN |
292 | /* Familiar character generator */ | 292 | /* Familiar character generator */ |
293 | {"chargen", SOCK_STREAM, 1, 0, chargen_stream,}, | 293 | {"chargen", SOCK_STREAM, 1, 0, chargen_stream,}, |
294 | {"chargen", SOCK_DGRAM, 0, 0, chargen_dg,}, | 294 | {"chargen", SOCK_DGRAM, 0, 0, chargen_dg,}, |
295 | #endif | 295 | #endif |
296 | {NULL, 0, 0, 0, NULL} | 296 | {NULL, 0, 0, 0, NULL} |
297 | }; | 297 | }; |
298 | #endif /* INETD_FEATURE_ENABLED */ | 298 | #endif /* INETD_FEATURE_ENABLED */ |
299 | 299 | ||
@@ -315,884 +315,884 @@ static char *defhost; | |||
315 | * will return newly-allocated "" if called with NULL arg | 315 | * will return newly-allocated "" if called with NULL arg |
316 | * TODO: audit whether this makes any real difference | 316 | * TODO: audit whether this makes any real difference |
317 | */ | 317 | */ |
318 | static char *xxstrdup (char *cp) | 318 | static char *xxstrdup(char *cp) |
319 | { | 319 | { |
320 | return xstrdup (cp ? cp : ""); | 320 | return xstrdup(cp ? cp : ""); |
321 | } | 321 | } |
322 | 322 | ||
323 | static int setconfig (void) | 323 | static int setconfig(void) |
324 | { | 324 | { |
325 | free (defhost); | 325 | free(defhost); |
326 | defhost = xstrdup ("*"); | 326 | defhost = xstrdup("*"); |
327 | if (fconfig != NULL) { | 327 | if (fconfig != NULL) { |
328 | fseek (fconfig, 0L, SEEK_SET); | 328 | fseek(fconfig, 0L, SEEK_SET); |
329 | return (1); | 329 | return 1; |
330 | } | 330 | } |
331 | fconfig = fopen (CONFIG, "r"); | 331 | fconfig = fopen(CONFIG, "r"); |
332 | return (fconfig != NULL); | 332 | return (fconfig != NULL); |
333 | } | 333 | } |
334 | 334 | ||
335 | static void endconfig (void) | 335 | static void endconfig(void) |
336 | { | 336 | { |
337 | if (fconfig) { | 337 | if (fconfig) { |
338 | (void) fclose (fconfig); | 338 | (void) fclose(fconfig); |
339 | fconfig = NULL; | 339 | fconfig = NULL; |
340 | } | 340 | } |
341 | free (defhost); | 341 | free(defhost); |
342 | defhost = 0; | 342 | defhost = 0; |
343 | } | 343 | } |
344 | 344 | ||
345 | #ifdef CONFIG_FEATURE_INETD_RPC | 345 | #ifdef CONFIG_FEATURE_INETD_RPC |
346 | static void register_rpc (servtab_t *sep) | 346 | static void register_rpc(servtab_t *sep) |
347 | { | 347 | { |
348 | int n; | 348 | int n; |
349 | struct sockaddr_in ir_sin; | 349 | struct sockaddr_in ir_sin; |
350 | struct protoent *pp; | 350 | struct protoent *pp; |
351 | socklen_t size; | 351 | socklen_t size; |
352 | 352 | ||
353 | if ((pp = getprotobyname (sep->se_proto + 4)) == NULL) { | 353 | if ((pp = getprotobyname(sep->se_proto + 4)) == NULL) { |
354 | bb_perror_msg ("%s: getproto", sep->se_proto); | 354 | bb_perror_msg("%s: getproto", sep->se_proto); |
355 | return; | 355 | return; |
356 | } | 356 | } |
357 | size = sizeof ir_sin; | 357 | size = sizeof ir_sin; |
358 | if (getsockname (sep->se_fd, (struct sockaddr *) &ir_sin, &size) < 0) { | 358 | if (getsockname(sep->se_fd, (struct sockaddr *) &ir_sin, &size) < 0) { |
359 | bb_perror_msg ("%s/%s: getsockname", | 359 | bb_perror_msg("%s/%s: getsockname", |
360 | sep->se_service, sep->se_proto); | 360 | sep->se_service, sep->se_proto); |
361 | return; | 361 | return; |
362 | } | 362 | } |
363 | 363 | ||
364 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { | 364 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { |
365 | (void) pmap_unset (sep->se_rpcprog, n); | 365 | (void) pmap_unset(sep->se_rpcprog, n); |
366 | if (!pmap_set (sep->se_rpcprog, n, pp->p_proto, ntohs (ir_sin.sin_port))) | 366 | if (!pmap_set(sep->se_rpcprog, n, pp->p_proto, ntohs(ir_sin.sin_port))) |
367 | bb_perror_msg ("%s %s: pmap_set: %u %u %u %u", | 367 | bb_perror_msg("%s %s: pmap_set: %u %u %u %u", |
368 | sep->se_service, sep->se_proto, | 368 | sep->se_service, sep->se_proto, |
369 | sep->se_rpcprog, n, pp->p_proto, ntohs (ir_sin.sin_port)); | 369 | sep->se_rpcprog, n, pp->p_proto, ntohs(ir_sin.sin_port)); |
370 | } | 370 | } |
371 | } | 371 | } |
372 | 372 | ||
373 | static void unregister_rpc (servtab_t *sep) | 373 | static void unregister_rpc(servtab_t *sep) |
374 | { | 374 | { |
375 | int n; | 375 | int n; |
376 | 376 | ||
377 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { | 377 | for (n = sep->se_rpcversl; n <= sep->se_rpcversh; n++) { |
378 | if (!pmap_unset (sep->se_rpcprog, n)) | 378 | if (!pmap_unset(sep->se_rpcprog, n)) |
379 | bb_error_msg ("pmap_unset(%u, %u)", sep->se_rpcprog, n); | 379 | bb_error_msg("pmap_unset(%u, %u)", sep->se_rpcprog, n); |
380 | } | 380 | } |
381 | } | 381 | } |
382 | #endif /* CONFIG_FEATURE_INETD_RPC */ | 382 | #endif /* CONFIG_FEATURE_INETD_RPC */ |
383 | 383 | ||
384 | static void freeconfig (servtab_t *cp) | 384 | static void freeconfig(servtab_t *cp) |
385 | { | 385 | { |
386 | int i; | 386 | int i; |
387 | 387 | ||
388 | free (cp->se_hostaddr); | 388 | free(cp->se_hostaddr); |
389 | free (cp->se_service); | 389 | free(cp->se_service); |
390 | free (cp->se_proto); | 390 | free(cp->se_proto); |
391 | free (cp->se_user); | 391 | free(cp->se_user); |
392 | free (cp->se_group); | 392 | free(cp->se_group); |
393 | free (cp->se_server); | 393 | free(cp->se_server); |
394 | for (i = 0; i < MAXARGV; i++) | 394 | for (i = 0; i < MAXARGV; i++) |
395 | free (cp->se_argv[i]); | 395 | free(cp->se_argv[i]); |
396 | } | 396 | } |
397 | 397 | ||
398 | static int bump_nofile (void) | 398 | static int bump_nofile (void) |
399 | { | 399 | { |
400 | #define FD_CHUNK 32 | 400 | #define FD_CHUNK 32 |
401 | 401 | ||
402 | struct rlimit rl; | 402 | struct rlimit rl; |
403 | 403 | ||
404 | if (getrlimit (RLIMIT_NOFILE, &rl) < 0) { | 404 | if (getrlimit (RLIMIT_NOFILE, &rl) < 0) { |
405 | bb_perror_msg ("getrlimit"); | 405 | bb_perror_msg("getrlimit"); |
406 | return -1; | 406 | return -1; |
407 | } | 407 | } |
408 | rl.rlim_cur = MIN (rl.rlim_max, rl.rlim_cur + FD_CHUNK); | 408 | rl.rlim_cur = MIN(rl.rlim_max, rl.rlim_cur + FD_CHUNK); |
409 | rl.rlim_cur = MIN (FD_SETSIZE, rl.rlim_cur + FD_CHUNK); | 409 | rl.rlim_cur = MIN(FD_SETSIZE, rl.rlim_cur + FD_CHUNK); |
410 | if (rl.rlim_cur <= rlim_ofile_cur) { | 410 | if (rl.rlim_cur <= rlim_ofile_cur) { |
411 | bb_error_msg ("bump_nofile: cannot extend file limit, max = %d", | 411 | bb_error_msg("bump_nofile: cannot extend file limit, max = %d", |
412 | (int) rl.rlim_cur); | 412 | (int) rl.rlim_cur); |
413 | return -1; | 413 | return -1; |
414 | } | 414 | } |
415 | 415 | ||
416 | if (setrlimit (RLIMIT_NOFILE, &rl) < 0) { | 416 | if (setrlimit(RLIMIT_NOFILE, &rl) < 0) { |
417 | bb_perror_msg ("setrlimit"); | 417 | bb_perror_msg("setrlimit"); |
418 | return -1; | 418 | return -1; |
419 | } | 419 | } |
420 | 420 | ||
421 | rlim_ofile_cur = rl.rlim_cur; | 421 | rlim_ofile_cur = rl.rlim_cur; |
422 | return 0; | 422 | return 0; |
423 | } | 423 | } |
424 | 424 | ||
425 | static void setup (servtab_t *sep) | 425 | static void setup(servtab_t *sep) |
426 | { | 426 | { |
427 | int on = 1; | 427 | int on = 1; |
428 | int r; | 428 | int r; |
429 | 429 | ||
430 | if ((sep->se_fd = socket (sep->se_family, sep->se_socktype, 0)) < 0) { | 430 | if ((sep->se_fd = socket(sep->se_family, sep->se_socktype, 0)) < 0) { |
431 | bb_perror_msg ("%s/%s: socket", sep->se_service, sep->se_proto); | 431 | bb_perror_msg("%s/%s: socket", sep->se_service, sep->se_proto); |
432 | return; | 432 | return; |
433 | } | 433 | } |
434 | #define turnon(fd, opt) \ | 434 | #define turnon(fd, opt) \ |
435 | setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof (on)) | 435 | setsockopt(fd, SOL_SOCKET, opt, (char *)&on, sizeof(on)) |
436 | if (turnon (sep->se_fd, SO_REUSEADDR) < 0) | 436 | if (turnon(sep->se_fd, SO_REUSEADDR) < 0) |
437 | bb_perror_msg ("setsockopt (SO_REUSEADDR)"); | 437 | bb_perror_msg("setsockopt(SO_REUSEADDR)"); |
438 | #undef turnon | 438 | #undef turnon |
439 | 439 | ||
440 | #ifdef CONFIG_FEATURE_INETD_RPC | 440 | #ifdef CONFIG_FEATURE_INETD_RPC |
441 | if (isrpcservice (sep)) { | 441 | if (isrpcservice(sep)) { |
442 | struct passwd *pwd; | 442 | struct passwd *pwd; |
443 | 443 | ||
444 | /* | 444 | /* |
445 | * for RPC services, attempt to use a reserved port | 445 | * for RPC services, attempt to use a reserved port |
446 | * if they are going to be running as root. | 446 | * if they are going to be running as root. |
447 | * | 447 | * |
448 | * Also, zero out the port for all RPC services; let bind() | 448 | * Also, zero out the port for all RPC services; let bind() |
449 | * find one. | 449 | * find one. |
450 | */ | 450 | */ |
451 | sep->se_ctrladdr_in.sin_port = 0; | 451 | sep->se_ctrladdr_in.sin_port = 0; |
452 | if (sep->se_user && (pwd = getpwnam (sep->se_user)) && | 452 | if (sep->se_user && (pwd = getpwnam(sep->se_user)) && |
453 | pwd->pw_uid == 0 && uid == 0) | 453 | pwd->pw_uid == 0 && uid == 0) |
454 | r = bindresvport (sep->se_fd, &sep->se_ctrladdr_in); | 454 | r = bindresvport(sep->se_fd, &sep->se_ctrladdr_in); |
455 | else { | 455 | else { |
456 | r = bind (sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); | 456 | r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); |
457 | if (r == 0) { | 457 | if (r == 0) { |
458 | socklen_t len = sep->se_ctrladdr_size; | 458 | socklen_t len = sep->se_ctrladdr_size; |
459 | int saveerrno = errno; | 459 | int saveerrno = errno; |
460 | 460 | ||
461 | /* update se_ctrladdr_in.sin_port */ | 461 | /* update se_ctrladdr_in.sin_port */ |
462 | r = getsockname (sep->se_fd, &sep->se_ctrladdr, &len); | 462 | r = getsockname(sep->se_fd, &sep->se_ctrladdr, &len); |
463 | if (r <= 0) | 463 | if (r <= 0) |
464 | errno = saveerrno; | 464 | errno = saveerrno; |
465 | } | 465 | } |
466 | } | 466 | } |
467 | } else | 467 | } else |
468 | #endif | 468 | #endif |
469 | r = bind (sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); | 469 | r = bind(sep->se_fd, &sep->se_ctrladdr, sep->se_ctrladdr_size); |
470 | if (r < 0) { | 470 | if (r < 0) { |
471 | bb_perror_msg ("%s/%s (%d): bind", | 471 | bb_perror_msg("%s/%s (%d): bind", |
472 | sep->se_service, sep->se_proto, sep->se_ctrladdr.sa_family); | 472 | sep->se_service, sep->se_proto, sep->se_ctrladdr.sa_family); |
473 | close (sep->se_fd); | 473 | close(sep->se_fd); |
474 | sep->se_fd = -1; | 474 | sep->se_fd = -1; |
475 | if (!timingout) { | 475 | if (!timingout) { |
476 | timingout = 1; | 476 | timingout = 1; |
477 | alarm (RETRYTIME); | 477 | alarm(RETRYTIME); |
478 | } | ||
479 | return; | ||
480 | } | ||
481 | if (sep->se_socktype == SOCK_STREAM) | ||
482 | listen(sep->se_fd, global_queuelen); | ||
483 | |||
484 | FD_SET(sep->se_fd, &allsock); | ||
485 | nsock++; | ||
486 | if (sep->se_fd > maxsock) { | ||
487 | maxsock = sep->se_fd; | ||
488 | if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN) | ||
489 | bump_nofile(); | ||
478 | } | 490 | } |
479 | return; | ||
480 | } | ||
481 | if (sep->se_socktype == SOCK_STREAM) | ||
482 | listen (sep->se_fd, global_queuelen); | ||
483 | |||
484 | FD_SET (sep->se_fd, &allsock); | ||
485 | nsock++; | ||
486 | if (sep->se_fd > maxsock) { | ||
487 | maxsock = sep->se_fd; | ||
488 | if ((rlim_t)maxsock > rlim_ofile_cur - FD_MARGIN) | ||
489 | bump_nofile (); | ||
490 | } | ||
491 | } | 491 | } |
492 | 492 | ||
493 | static char *nextline (void) | 493 | static char *nextline(void) |
494 | { | 494 | { |
495 | char *cp; | 495 | char *cp; |
496 | FILE *fd = fconfig; | 496 | FILE *fd = fconfig; |
497 | 497 | ||
498 | if (fgets (line, sizeof (line), fd) == NULL) | 498 | if (fgets(line, sizeof(line), fd) == NULL) |
499 | return (NULL); | 499 | return NULL; |
500 | cp = strchr (line, '\n'); | 500 | cp = strchr(line, '\n'); |
501 | if (cp) | 501 | if (cp) |
502 | *cp = '\0'; | 502 | *cp = '\0'; |
503 | return (line); | 503 | return line; |
504 | } | 504 | } |
505 | 505 | ||
506 | static char *skip (char **cpp) /* int report; */ | 506 | static char *skip(char **cpp) /* int report; */ |
507 | { | 507 | { |
508 | char *cp = *cpp; | 508 | char *cp = *cpp; |
509 | char *start; | 509 | char *start; |
510 | 510 | ||
511 | /* erp: */ | 511 | /* erp: */ |
512 | if (*cpp == NULL) { | 512 | if (*cpp == NULL) { |
513 | /* if (report) */ | 513 | /* if (report) */ |
514 | /* bb_error_msg ("syntax error in inetd config file"); */ | 514 | /* bb_error_msg("syntax error in inetd config file"); */ |
515 | return (NULL); | 515 | return NULL; |
516 | } | 516 | } |
517 | 517 | ||
518 | again: | 518 | again: |
519 | while (*cp == ' ' || *cp == '\t') | 519 | while (*cp == ' ' || *cp == '\t') |
520 | cp++; | 520 | cp++; |
521 | if (*cp == '\0') { | 521 | if (*cp == '\0') { |
522 | int c; | 522 | int c; |
523 | 523 | ||
524 | c = getc (fconfig); | 524 | c = getc(fconfig); |
525 | (void) ungetc (c, fconfig); | 525 | (void) ungetc(c, fconfig); |
526 | if (c == ' ' || c == '\t') | 526 | if (c == ' ' || c == '\t') |
527 | if ((cp = nextline ())) | 527 | if ((cp = nextline())) |
528 | goto again; | 528 | goto again; |
529 | *cpp = NULL; | 529 | *cpp = NULL; |
530 | /* goto erp; */ | ||
531 | return NULL; | ||
532 | } | ||
533 | start = cp; | ||
534 | while (*cp && *cp != ' ' && *cp != '\t') | ||
535 | cp++; | ||
536 | if (*cp != '\0') | ||
537 | *cp++ = '\0'; | ||
538 | /* if ((*cpp = cp) == NULL) */ | ||
530 | /* goto erp; */ | 539 | /* goto erp; */ |
531 | return (NULL); | 540 | |
532 | } | 541 | *cpp = cp; |
533 | start = cp; | 542 | return start; |
534 | while (*cp && *cp != ' ' && *cp != '\t') | ||
535 | cp++; | ||
536 | if (*cp != '\0') | ||
537 | *cp++ = '\0'; | ||
538 | /* if ((*cpp = cp) == NULL) */ | ||
539 | /* goto erp; */ | ||
540 | |||
541 | *cpp = cp; | ||
542 | return (start); | ||
543 | } | 543 | } |
544 | 544 | ||
545 | static servtab_t *new_servtab(void) | 545 | static servtab_t *new_servtab(void) |
546 | { | 546 | { |
547 | return xmalloc (sizeof (servtab_t)); | 547 | return xmalloc(sizeof(servtab_t)); |
548 | } | 548 | } |
549 | 549 | ||
550 | static servtab_t *dupconfig (servtab_t *sep) | 550 | static servtab_t *dupconfig(servtab_t *sep) |
551 | { | 551 | { |
552 | servtab_t *newtab; | 552 | servtab_t *newtab; |
553 | int argc; | 553 | int argc; |
554 | 554 | ||
555 | newtab = new_servtab(); | 555 | newtab = new_servtab(); |
556 | memset (newtab, 0, sizeof (servtab_t)); | 556 | memset(newtab, 0, sizeof(servtab_t)); |
557 | newtab->se_service = xstrdup (sep->se_service); | 557 | newtab->se_service = xstrdup(sep->se_service); |
558 | newtab->se_socktype = sep->se_socktype; | 558 | newtab->se_socktype = sep->se_socktype; |
559 | newtab->se_family = sep->se_family; | 559 | newtab->se_family = sep->se_family; |
560 | newtab->se_proto = xstrdup (sep->se_proto); | 560 | newtab->se_proto = xstrdup(sep->se_proto); |
561 | #ifdef CONFIG_FEATURE_INETD_RPC | 561 | #ifdef CONFIG_FEATURE_INETD_RPC |
562 | newtab->se_rpcprog = sep->se_rpcprog; | 562 | newtab->se_rpcprog = sep->se_rpcprog; |
563 | newtab->se_rpcversl = sep->se_rpcversl; | 563 | newtab->se_rpcversl = sep->se_rpcversl; |
564 | newtab->se_rpcversh = sep->se_rpcversh; | 564 | newtab->se_rpcversh = sep->se_rpcversh; |
565 | #endif | 565 | #endif |
566 | newtab->se_wait = sep->se_wait; | 566 | newtab->se_wait = sep->se_wait; |
567 | newtab->se_user = xstrdup (sep->se_user); | 567 | newtab->se_user = xstrdup(sep->se_user); |
568 | newtab->se_group = xstrdup (sep->se_group); | 568 | newtab->se_group = xstrdup(sep->se_group); |
569 | #ifdef INETD_FEATURE_ENABLED | 569 | #ifdef INETD_FEATURE_ENABLED |
570 | newtab->se_bi = sep->se_bi; | 570 | newtab->se_bi = sep->se_bi; |
571 | #endif | 571 | #endif |
572 | newtab->se_server = xstrdup (sep->se_server); | 572 | newtab->se_server = xstrdup(sep->se_server); |
573 | 573 | ||
574 | for (argc = 0; argc <= MAXARGV; argc++) | 574 | for (argc = 0; argc <= MAXARGV; argc++) |
575 | newtab->se_argv[argc] = xstrdup (sep->se_argv[argc]); | 575 | newtab->se_argv[argc] = xstrdup(sep->se_argv[argc]); |
576 | newtab->se_max = sep->se_max; | 576 | newtab->se_max = sep->se_max; |
577 | 577 | ||
578 | return (newtab); | 578 | return newtab; |
579 | } | 579 | } |
580 | 580 | ||
581 | static servtab_t *getconfigent (void) | 581 | static servtab_t *getconfigent(void) |
582 | { | 582 | { |
583 | servtab_t *sep; | 583 | servtab_t *sep; |
584 | int argc; | 584 | int argc; |
585 | char *cp, *arg; | 585 | char *cp, *arg; |
586 | char *hostdelim; | 586 | char *hostdelim; |
587 | servtab_t *nsep; | 587 | servtab_t *nsep; |
588 | servtab_t *psep; | 588 | servtab_t *psep; |
589 | 589 | ||
590 | sep = new_servtab(); | 590 | sep = new_servtab(); |
591 | 591 | ||
592 | /* memset(sep, 0, sizeof *sep); */ | 592 | /* memset(sep, 0, sizeof *sep); */ |
593 | more: | 593 | more: |
594 | /* freeconfig(sep); */ | 594 | /* freeconfig(sep); */ |
595 | 595 | ||
596 | while ((cp = nextline ()) && *cp == '#'); | 596 | while ((cp = nextline()) && *cp == '#'); |
597 | if (cp == NULL) { | 597 | if (cp == NULL) { |
598 | /* free(sep); */ | 598 | /* free(sep); */ |
599 | return (NULL); | 599 | return NULL; |
600 | } | 600 | } |
601 | 601 | ||
602 | memset ((char *) sep, 0, sizeof *sep); | 602 | memset((char *) sep, 0, sizeof *sep); |
603 | arg = skip (&cp); | 603 | arg = skip(&cp); |
604 | if (arg == NULL) { | 604 | if (arg == NULL) { |
605 | /* A blank line. */ | 605 | /* A blank line. */ |
606 | goto more; | ||
607 | } | ||
608 | |||
609 | /* Check for a host name. */ | ||
610 | hostdelim = strrchr (arg, ':'); | ||
611 | if (hostdelim) { | ||
612 | *hostdelim = '\0'; | ||
613 | sep->se_hostaddr = xstrdup (arg); | ||
614 | arg = hostdelim + 1; | ||
615 | /* | ||
616 | * If the line is of the form `host:', then just change the | ||
617 | * default host for the following lines. | ||
618 | */ | ||
619 | if (*arg == '\0') { | ||
620 | arg = skip (&cp); | ||
621 | if (cp == NULL) { | ||
622 | free (defhost); | ||
623 | defhost = sep->se_hostaddr; | ||
624 | goto more; | 606 | goto more; |
625 | } | ||
626 | } | 607 | } |
627 | } else | 608 | |
628 | sep->se_hostaddr = xxstrdup (defhost); | 609 | /* Check for a host name. */ |
629 | 610 | hostdelim = strrchr(arg, ':'); | |
630 | sep->se_service = xxstrdup (arg); | 611 | if (hostdelim) { |
631 | arg = skip (&cp); | 612 | *hostdelim = '\0'; |
632 | 613 | sep->se_hostaddr = xstrdup(arg); | |
633 | if (strcmp (arg, "stream") == 0) | 614 | arg = hostdelim + 1; |
634 | sep->se_socktype = SOCK_STREAM; | 615 | /* |
635 | else if (strcmp (arg, "dgram") == 0) | 616 | * If the line is of the form `host:', then just change the |
636 | sep->se_socktype = SOCK_DGRAM; | 617 | * default host for the following lines. |
637 | else if (strcmp (arg, "rdm") == 0) | 618 | */ |
638 | sep->se_socktype = SOCK_RDM; | 619 | if (*arg == '\0') { |
639 | else if (strcmp (arg, "seqpacket") == 0) | 620 | arg = skip(&cp); |
640 | sep->se_socktype = SOCK_SEQPACKET; | 621 | if (cp == NULL) { |
641 | else if (strcmp (arg, "raw") == 0) | 622 | free(defhost); |
642 | sep->se_socktype = SOCK_RAW; | 623 | defhost = sep->se_hostaddr; |
643 | else | 624 | goto more; |
644 | sep->se_socktype = -1; | 625 | } |
645 | 626 | } | |
646 | sep->se_proto = xxstrdup (skip (&cp)); | 627 | } else |
647 | 628 | sep->se_hostaddr = xxstrdup(defhost); | |
648 | if (strcmp (sep->se_proto, "unix") == 0) { | 629 | |
649 | sep->se_family = AF_UNIX; | 630 | sep->se_service = xxstrdup(arg); |
650 | } else { | 631 | arg = skip(&cp); |
651 | sep->se_family = AF_INET; | 632 | |
652 | if (sep->se_proto[strlen (sep->se_proto) - 1] == '6') | 633 | if (strcmp(arg, "stream") == 0) |
634 | sep->se_socktype = SOCK_STREAM; | ||
635 | else if (strcmp(arg, "dgram") == 0) | ||
636 | sep->se_socktype = SOCK_DGRAM; | ||
637 | else if (strcmp(arg, "rdm") == 0) | ||
638 | sep->se_socktype = SOCK_RDM; | ||
639 | else if (strcmp(arg, "seqpacket") == 0) | ||
640 | sep->se_socktype = SOCK_SEQPACKET; | ||
641 | else if (strcmp(arg, "raw") == 0) | ||
642 | sep->se_socktype = SOCK_RAW; | ||
643 | else | ||
644 | sep->se_socktype = -1; | ||
645 | |||
646 | sep->se_proto = xxstrdup(skip(&cp)); | ||
647 | |||
648 | if (strcmp(sep->se_proto, "unix") == 0) { | ||
649 | sep->se_family = AF_UNIX; | ||
650 | } else { | ||
651 | sep->se_family = AF_INET; | ||
652 | if (sep->se_proto[strlen(sep->se_proto) - 1] == '6') | ||
653 | #ifdef CONFIG_FEATURE_IPV6 | 653 | #ifdef CONFIG_FEATURE_IPV6 |
654 | sep->se_family = AF_INET6; | 654 | sep->se_family = AF_INET6; |
655 | #else | 655 | #else |
656 | bb_error_msg ("%s: IPV6 not supported", sep->se_proto); | 656 | bb_error_msg("%s: IPV6 not supported", sep->se_proto); |
657 | #endif | 657 | #endif |
658 | if (strncmp (sep->se_proto, "rpc/", 4) == 0) { | 658 | if (strncmp(sep->se_proto, "rpc/", 4) == 0) { |
659 | #ifdef CONFIG_FEATURE_INETD_RPC | 659 | #ifdef CONFIG_FEATURE_INETD_RPC |
660 | char *p, *ccp; | 660 | char *p, *ccp; |
661 | long l; | 661 | long l; |
662 | 662 | ||
663 | p = strchr (sep->se_service, '/'); | 663 | p = strchr(sep->se_service, '/'); |
664 | if (p == 0) { | 664 | if (p == 0) { |
665 | bb_error_msg ("%s: no rpc version", sep->se_service); | 665 | bb_error_msg("%s: no rpc version", sep->se_service); |
666 | goto more; | 666 | goto more; |
667 | } | 667 | } |
668 | *p++ = '\0'; | 668 | *p++ = '\0'; |
669 | l = strtol (p, &ccp, 0); | 669 | l = strtol(p, &ccp, 0); |
670 | if (ccp == p || l < 0 || l > INT_MAX) { | 670 | if (ccp == p || l < 0 || l > INT_MAX) { |
671 | badafterall: | 671 | badafterall: |
672 | bb_error_msg ("%s/%s: bad rpc version", sep->se_service, p); | 672 | bb_error_msg("%s/%s: bad rpc version", sep->se_service, p); |
673 | goto more; | 673 | goto more; |
674 | } | 674 | } |
675 | sep->se_rpcversl = sep->se_rpcversh = l; | 675 | sep->se_rpcversl = sep->se_rpcversh = l; |
676 | if (*ccp == '-') { | 676 | if (*ccp == '-') { |
677 | p = ccp + 1; | 677 | p = ccp + 1; |
678 | l = strtol (p, &ccp, 0); | 678 | l = strtol(p, &ccp, 0); |
679 | if (ccp == p || l < 0 || l > INT_MAX || l < sep->se_rpcversl || *ccp) | 679 | if (ccp == p || l < 0 || l > INT_MAX || l < sep->se_rpcversl || *ccp) |
680 | goto badafterall; | 680 | goto badafterall; |
681 | sep->se_rpcversh = l; | 681 | sep->se_rpcversh = l; |
682 | } else if (*ccp != '\0') | 682 | } else if (*ccp != '\0') |
683 | goto badafterall; | 683 | goto badafterall; |
684 | #else | 684 | #else |
685 | bb_error_msg ("%s: rpc services not supported", sep->se_service); | 685 | bb_error_msg("%s: rpc services not supported", sep->se_service); |
686 | #endif | 686 | #endif |
687 | } | ||
687 | } | 688 | } |
688 | } | 689 | arg = skip(&cp); |
689 | arg = skip (&cp); | 690 | if (arg == NULL) |
690 | if (arg == NULL) | 691 | goto more; |
691 | goto more; | 692 | |
692 | 693 | { | |
693 | { | 694 | char *s = strchr(arg, '.'); |
694 | char *s = strchr (arg, '.'); | 695 | if (s) { |
695 | if (s) { | 696 | *s++ = '\0'; |
696 | *s++ = '\0'; | 697 | sep->se_max = atoi(s); |
697 | sep->se_max = atoi (s); | 698 | } else |
698 | } else | 699 | sep->se_max = toomany; |
699 | sep->se_max = toomany; | ||
700 | } | ||
701 | sep->se_wait = strcmp (arg, "wait") == 0; | ||
702 | /* if ((arg = skip(&cp, 1)) == NULL) */ | ||
703 | /* goto more; */ | ||
704 | sep->se_user = xxstrdup (skip (&cp)); | ||
705 | arg = strchr (sep->se_user, '.'); | ||
706 | if (arg == NULL) | ||
707 | arg = strchr (sep->se_user, ':'); | ||
708 | if (arg) { | ||
709 | *arg++ = '\0'; | ||
710 | sep->se_group = xstrdup (arg); | ||
711 | } | ||
712 | /* if ((arg = skip(&cp, 1)) == NULL) */ | ||
713 | /* goto more; */ | ||
714 | |||
715 | sep->se_server = xxstrdup (skip (&cp)); | ||
716 | if (strcmp (sep->se_server, "internal") == 0) { | ||
717 | #ifdef INETD_FEATURE_ENABLED | ||
718 | const struct builtin *bi; | ||
719 | |||
720 | for (bi = builtins; bi->bi_service; bi++) | ||
721 | if (bi->bi_socktype == sep->se_socktype && | ||
722 | strcmp (bi->bi_service, sep->se_service) == 0) | ||
723 | break; | ||
724 | if (bi->bi_service == 0) { | ||
725 | bb_error_msg ("internal service %s unknown", sep->se_service); | ||
726 | goto more; | ||
727 | } | 700 | } |
728 | sep->se_bi = bi; | 701 | sep->se_wait = strcmp(arg, "wait") == 0; |
729 | sep->se_wait = bi->bi_wait; | 702 | /* if ((arg = skip(&cp, 1)) == NULL) */ |
703 | /* goto more; */ | ||
704 | sep->se_user = xxstrdup(skip(&cp)); | ||
705 | arg = strchr(sep->se_user, '.'); | ||
706 | if (arg == NULL) | ||
707 | arg = strchr(sep->se_user, ':'); | ||
708 | if (arg) { | ||
709 | *arg++ = '\0'; | ||
710 | sep->se_group = xstrdup(arg); | ||
711 | } | ||
712 | /* if ((arg = skip(&cp, 1)) == NULL) */ | ||
713 | /* goto more; */ | ||
714 | |||
715 | sep->se_server = xxstrdup(skip(&cp)); | ||
716 | if (strcmp(sep->se_server, "internal") == 0) { | ||
717 | #ifdef INETD_FEATURE_ENABLED | ||
718 | const struct builtin *bi; | ||
719 | |||
720 | for (bi = builtins; bi->bi_service; bi++) | ||
721 | if (bi->bi_socktype == sep->se_socktype && | ||
722 | strcmp(bi->bi_service, sep->se_service) == 0) | ||
723 | break; | ||
724 | if (bi->bi_service == 0) { | ||
725 | bb_error_msg("internal service %s unknown", sep->se_service); | ||
726 | goto more; | ||
727 | } | ||
728 | sep->se_bi = bi; | ||
729 | sep->se_wait = bi->bi_wait; | ||
730 | #else | 730 | #else |
731 | bb_perror_msg ("internal service %s unknown", sep->se_service); | 731 | bb_perror_msg("internal service %s unknown", sep->se_service); |
732 | goto more; | 732 | goto more; |
733 | #endif | 733 | #endif |
734 | } | 734 | } |
735 | #ifdef INETD_FEATURE_ENABLED | 735 | #ifdef INETD_FEATURE_ENABLED |
736 | else | 736 | else |
737 | sep->se_bi = NULL; | 737 | sep->se_bi = NULL; |
738 | #endif | 738 | #endif |
739 | argc = 0; | 739 | argc = 0; |
740 | for (arg = skip (&cp); cp; arg = skip (&cp)) { | 740 | for (arg = skip(&cp); cp; arg = skip(&cp)) { |
741 | if (argc < MAXARGV) | 741 | if (argc < MAXARGV) |
742 | sep->se_argv[argc++] = xxstrdup (arg); | 742 | sep->se_argv[argc++] = xxstrdup(arg); |
743 | } | 743 | } |
744 | while (argc <= MAXARGV) | 744 | while (argc <= MAXARGV) |
745 | sep->se_argv[argc++] = NULL; | 745 | sep->se_argv[argc++] = NULL; |
746 | |||
747 | /* | ||
748 | * Now that we've processed the entire line, check if the hostname | ||
749 | * specifier was a comma separated list of hostnames. If so | ||
750 | * we'll make new entries for each address. | ||
751 | */ | ||
752 | while ((hostdelim = strrchr (sep->se_hostaddr, ',')) != NULL) { | ||
753 | nsep = dupconfig (sep); | ||
754 | 746 | ||
755 | /* | 747 | /* |
756 | * NULL terminate the hostname field of the existing entry, | 748 | * Now that we've processed the entire line, check if the hostname |
757 | * and make a dup for the new entry. | 749 | * specifier was a comma separated list of hostnames. If so |
750 | * we'll make new entries for each address. | ||
758 | */ | 751 | */ |
759 | *hostdelim++ = '\0'; | 752 | while ((hostdelim = strrchr(sep->se_hostaddr, ',')) != NULL) { |
760 | nsep->se_hostaddr = xstrdup (hostdelim); | 753 | nsep = dupconfig(sep); |
761 | 754 | ||
762 | nsep->se_next = sep->se_next; | 755 | /* |
763 | sep->se_next = nsep; | 756 | * NULL terminate the hostname field of the existing entry, |
764 | } | 757 | * and make a dup for the new entry. |
765 | 758 | */ | |
766 | nsep = sep; | 759 | *hostdelim++ = '\0'; |
767 | while (nsep != NULL) { | 760 | nsep->se_hostaddr = xstrdup(hostdelim); |
768 | nsep->se_checked = 1; | 761 | |
769 | if (nsep->se_family == AF_INET) { | 762 | nsep->se_next = sep->se_next; |
770 | if (!strcmp (nsep->se_hostaddr, "*")) | 763 | sep->se_next = nsep; |
771 | nsep->se_ctrladdr_in.sin_addr.s_addr = INADDR_ANY; | ||
772 | else if (!inet_aton (nsep->se_hostaddr, &nsep->se_ctrladdr_in.sin_addr)) { | ||
773 | struct hostent *hp; | ||
774 | |||
775 | hp = gethostbyname (nsep->se_hostaddr); | ||
776 | if (hp == 0) { | ||
777 | bb_error_msg ("%s: unknown host", nsep->se_hostaddr); | ||
778 | nsep->se_checked = 0; | ||
779 | goto skip; | ||
780 | } else if (hp->h_addrtype != AF_INET) { | ||
781 | bb_error_msg ("%s: address isn't an Internet " | ||
782 | "address", nsep->se_hostaddr); | ||
783 | nsep->se_checked = 0; | ||
784 | goto skip; | ||
785 | } else { | ||
786 | int i = 1; | ||
787 | |||
788 | memmove (&nsep->se_ctrladdr_in.sin_addr, | ||
789 | hp->h_addr_list[0], sizeof (struct in_addr)); | ||
790 | while (hp->h_addr_list[i] != NULL) { | ||
791 | psep = dupconfig (nsep); | ||
792 | psep->se_hostaddr = xxstrdup (nsep->se_hostaddr); | ||
793 | psep->se_checked = 1; | ||
794 | memmove (&psep->se_ctrladdr_in.sin_addr, | ||
795 | hp->h_addr_list[i], sizeof (struct in_addr)); | ||
796 | psep->se_ctrladdr_size = sizeof (psep->se_ctrladdr_in); | ||
797 | i++; | ||
798 | /* Prepend to list, don't want to look up its */ | ||
799 | /* hostname again. */ | ||
800 | psep->se_next = sep; | ||
801 | sep = psep; | ||
802 | } | ||
803 | } | ||
804 | } | ||
805 | } | 764 | } |
765 | |||
766 | nsep = sep; | ||
767 | while (nsep != NULL) { | ||
768 | nsep->se_checked = 1; | ||
769 | if (nsep->se_family == AF_INET) { | ||
770 | if (!strcmp(nsep->se_hostaddr, "*")) | ||
771 | nsep->se_ctrladdr_in.sin_addr.s_addr = INADDR_ANY; | ||
772 | else if (!inet_aton(nsep->se_hostaddr, &nsep->se_ctrladdr_in.sin_addr)) { | ||
773 | struct hostent *hp; | ||
774 | |||
775 | hp = gethostbyname(nsep->se_hostaddr); | ||
776 | if (hp == 0) { | ||
777 | bb_error_msg("%s: unknown host", nsep->se_hostaddr); | ||
778 | nsep->se_checked = 0; | ||
779 | goto skip; | ||
780 | } else if (hp->h_addrtype != AF_INET) { | ||
781 | bb_error_msg("%s: address isn't an Internet " | ||
782 | "address", nsep->se_hostaddr); | ||
783 | nsep->se_checked = 0; | ||
784 | goto skip; | ||
785 | } else { | ||
786 | int i = 1; | ||
787 | |||
788 | memmove(&nsep->se_ctrladdr_in.sin_addr, | ||
789 | hp->h_addr_list[0], sizeof(struct in_addr)); | ||
790 | while (hp->h_addr_list[i] != NULL) { | ||
791 | psep = dupconfig(nsep); | ||
792 | psep->se_hostaddr = xxstrdup(nsep->se_hostaddr); | ||
793 | psep->se_checked = 1; | ||
794 | memmove(&psep->se_ctrladdr_in.sin_addr, | ||
795 | hp->h_addr_list[i], sizeof(struct in_addr)); | ||
796 | psep->se_ctrladdr_size = sizeof(psep->se_ctrladdr_in); | ||
797 | i++; | ||
798 | /* Prepend to list, don't want to look up */ | ||
799 | /* its hostname again. */ | ||
800 | psep->se_next = sep; | ||
801 | sep = psep; | ||
802 | } | ||
803 | } | ||
804 | } | ||
805 | } | ||
806 | /* XXX BUG?: is this skip: label supposed to remain? */ | 806 | /* XXX BUG?: is this skip: label supposed to remain? */ |
807 | skip: | 807 | skip: |
808 | nsep = nsep->se_next; | ||
809 | } | ||
810 | |||
811 | /* | ||
812 | * Finally, free any entries which failed the gethostbyname | ||
813 | * check. | ||
814 | */ | ||
815 | psep = NULL; | ||
816 | nsep = sep; | ||
817 | while (nsep != NULL) { | ||
818 | servtab_t *tsep; | ||
819 | |||
820 | if (nsep->se_checked == 0) { | ||
821 | tsep = nsep; | ||
822 | if (psep == NULL) { | ||
823 | sep = nsep->se_next; | ||
824 | nsep = sep; | ||
825 | } else { | ||
826 | nsep = nsep->se_next; | 808 | nsep = nsep->se_next; |
827 | psep->se_next = nsep; | ||
828 | } | ||
829 | freeconfig (tsep); | ||
830 | } else { | ||
831 | nsep->se_checked = 0; | ||
832 | psep = nsep; | ||
833 | nsep = nsep->se_next; | ||
834 | } | 809 | } |
835 | } | ||
836 | 810 | ||
837 | return (sep); | 811 | /* |
838 | } | 812 | * Finally, free any entries which failed the gethostbyname |
813 | * check. | ||
814 | */ | ||
815 | psep = NULL; | ||
816 | nsep = sep; | ||
817 | while (nsep != NULL) { | ||
818 | servtab_t *tsep; | ||
819 | |||
820 | if (nsep->se_checked == 0) { | ||
821 | tsep = nsep; | ||
822 | if (psep == NULL) { | ||
823 | sep = nsep->se_next; | ||
824 | nsep = sep; | ||
825 | } else { | ||
826 | nsep = nsep->se_next; | ||
827 | psep->se_next = nsep; | ||
828 | } | ||
829 | freeconfig(tsep); | ||
830 | } else { | ||
831 | nsep->se_checked = 0; | ||
832 | psep = nsep; | ||
833 | nsep = nsep->se_next; | ||
834 | } | ||
835 | } | ||
839 | 836 | ||
840 | #define Block_Using_Signals(m) do { sigemptyset(&m); \ | 837 | return sep; |
841 | sigaddset(&m, SIGCHLD); \ | 838 | } |
842 | sigaddset(&m, SIGHUP); \ | ||
843 | sigaddset(&m, SIGALRM); \ | ||
844 | sigprocmask(SIG_BLOCK, &m, NULL); \ | ||
845 | } while(0) | ||
846 | 839 | ||
840 | #define Block_Using_Signals(m) do { \ | ||
841 | sigemptyset(&m); \ | ||
842 | sigaddset(&m, SIGCHLD); \ | ||
843 | sigaddset(&m, SIGHUP); \ | ||
844 | sigaddset(&m, SIGALRM); \ | ||
845 | sigprocmask(SIG_BLOCK, &m, NULL); \ | ||
846 | } while(0) | ||
847 | 847 | ||
848 | static servtab_t *enter (servtab_t *cp) | 848 | static servtab_t *enter(servtab_t *cp) |
849 | { | 849 | { |
850 | servtab_t *sep; | 850 | servtab_t *sep; |
851 | sigset_t omask; | 851 | sigset_t omask; |
852 | 852 | ||
853 | sep = new_servtab(); | 853 | sep = new_servtab(); |
854 | *sep = *cp; | 854 | *sep = *cp; |
855 | sep->se_fd = -1; | 855 | sep->se_fd = -1; |
856 | #ifdef CONFIG_FEATURE_INETD_RPC | 856 | #ifdef CONFIG_FEATURE_INETD_RPC |
857 | sep->se_rpcprog = -1; | 857 | sep->se_rpcprog = -1; |
858 | #endif | 858 | #endif |
859 | Block_Using_Signals(omask); | 859 | Block_Using_Signals(omask); |
860 | sep->se_next = servtab; | 860 | sep->se_next = servtab; |
861 | servtab = sep; | 861 | servtab = sep; |
862 | sigprocmask(SIG_UNBLOCK, &omask, NULL); | 862 | sigprocmask(SIG_UNBLOCK, &omask, NULL); |
863 | return (sep); | 863 | return sep; |
864 | } | 864 | } |
865 | 865 | ||
866 | static int matchconf (servtab_t *old, servtab_t *new) | 866 | static int matchconf(servtab_t *old, servtab_t *new) |
867 | { | 867 | { |
868 | if (strcmp (old->se_service, new->se_service) != 0) | 868 | if (strcmp(old->se_service, new->se_service) != 0) |
869 | return (0); | 869 | return 0; |
870 | 870 | ||
871 | if (strcmp (old->se_hostaddr, new->se_hostaddr) != 0) | 871 | if (strcmp(old->se_hostaddr, new->se_hostaddr) != 0) |
872 | return (0); | 872 | return 0; |
873 | 873 | ||
874 | if (strcmp (old->se_proto, new->se_proto) != 0) | 874 | if (strcmp(old->se_proto, new->se_proto) != 0) |
875 | return (0); | 875 | return 0; |
876 | 876 | ||
877 | /* | 877 | /* |
878 | * If the new servtab is bound to a specific address, check that the | 878 | * If the new servtab is bound to a specific address, check that the |
879 | * old servtab is bound to the same entry. If the new service is not | 879 | * old servtab is bound to the same entry. If the new service is not |
880 | * bound to a specific address then the check of se_hostaddr above | 880 | * bound to a specific address then the check of se_hostaddr above |
881 | * is sufficient. | 881 | * is sufficient. |
882 | */ | 882 | */ |
883 | 883 | ||
884 | if (old->se_family == AF_INET && new->se_family == AF_INET && | 884 | if (old->se_family == AF_INET && new->se_family == AF_INET && |
885 | memcmp (&old->se_ctrladdr_in.sin_addr, | 885 | memcmp(&old->se_ctrladdr_in.sin_addr, |
886 | &new->se_ctrladdr_in.sin_addr, | 886 | &new->se_ctrladdr_in.sin_addr, |
887 | sizeof (new->se_ctrladdr_in.sin_addr)) != 0) | 887 | sizeof(new->se_ctrladdr_in.sin_addr)) != 0) |
888 | return (0); | 888 | return 0; |
889 | 889 | ||
890 | #ifdef CONFIG_FEATURE_IPV6 | 890 | #ifdef CONFIG_FEATURE_IPV6 |
891 | if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && | 891 | if (old->se_family == AF_INET6 && new->se_family == AF_INET6 && |
892 | memcmp (&old->se_ctrladdr_in6.sin6_addr, | 892 | memcmp(&old->se_ctrladdr_in6.sin6_addr, |
893 | &new->se_ctrladdr_in6.sin6_addr, | 893 | &new->se_ctrladdr_in6.sin6_addr, |
894 | sizeof (new->se_ctrladdr_in6.sin6_addr)) != 0) | 894 | sizeof(new->se_ctrladdr_in6.sin6_addr)) != 0) |
895 | return (0); | 895 | return 0; |
896 | #endif | 896 | #endif |
897 | return (1); | 897 | return 1; |
898 | } | 898 | } |
899 | 899 | ||
900 | static void config (int sig ATTRIBUTE_UNUSED) | 900 | static void config(int sig ATTRIBUTE_UNUSED) |
901 | { | 901 | { |
902 | servtab_t *sep, *cp, **sepp; | 902 | servtab_t *sep, *cp, **sepp; |
903 | sigset_t omask; | 903 | sigset_t omask; |
904 | size_t n; | 904 | size_t n; |
905 | char protoname[10]; | 905 | char protoname[10]; |
906 | 906 | ||
907 | if (!setconfig ()) { | 907 | if (!setconfig()) { |
908 | bb_perror_msg ("%s", CONFIG); | 908 | bb_perror_msg("%s", CONFIG); |
909 | return; | 909 | return; |
910 | } | 910 | } |
911 | for (sep = servtab; sep; sep = sep->se_next) | ||
912 | sep->se_checked = 0; | ||
913 | cp = getconfigent (); | ||
914 | while (cp != NULL) { | ||
915 | for (sep = servtab; sep; sep = sep->se_next) | 911 | for (sep = servtab; sep; sep = sep->se_next) |
916 | if (matchconf (sep, cp)) | 912 | sep->se_checked = 0; |
917 | break; | 913 | cp = getconfigent(); |
914 | while (cp != NULL) { | ||
915 | for (sep = servtab; sep; sep = sep->se_next) | ||
916 | if (matchconf(sep, cp)) | ||
917 | break; | ||
918 | 918 | ||
919 | if (sep != 0) { | 919 | if (sep != 0) { |
920 | int i; | 920 | int i; |
921 | 921 | ||
922 | #define SWAP(type, a, b) do {type c=(type)a; a=(type)b; b=(type)c;} while (0) | 922 | #define SWAP(type, a, b) do {type c=(type)a; a=(type)b; b=(type)c;} while (0) |
923 | 923 | ||
924 | Block_Using_Signals(omask); | 924 | Block_Using_Signals(omask); |
925 | /* | 925 | /* |
926 | * sep->se_wait may be holding the pid of a daemon | 926 | * sep->se_wait may be holding the pid of a daemon |
927 | * that we're waiting for. If so, don't overwrite | 927 | * that we're waiting for. If so, don't overwrite |
928 | * it unless the config file explicitly says don't | 928 | * it unless the config file explicitly says don't |
929 | * wait. | 929 | * wait. |
930 | */ | 930 | */ |
931 | if ( | 931 | if ( |
932 | #ifdef INETD_FEATURE_ENABLED | 932 | #ifdef INETD_FEATURE_ENABLED |
933 | cp->se_bi == 0 && | 933 | cp->se_bi == 0 && |
934 | #endif | 934 | #endif |
935 | (sep->se_wait == 1 || cp->se_wait == 0)) | 935 | (sep->se_wait == 1 || cp->se_wait == 0)) |
936 | sep->se_wait = cp->se_wait; | 936 | sep->se_wait = cp->se_wait; |
937 | SWAP (int, cp->se_max, sep->se_max); | 937 | SWAP(int, cp->se_max, sep->se_max); |
938 | SWAP (char *, sep->se_user, cp->se_user); | 938 | SWAP(char *, sep->se_user, cp->se_user); |
939 | SWAP (char *, sep->se_group, cp->se_group); | 939 | SWAP(char *, sep->se_group, cp->se_group); |
940 | SWAP (char *, sep->se_server, cp->se_server); | 940 | SWAP(char *, sep->se_server, cp->se_server); |
941 | for (i = 0; i < MAXARGV; i++) | 941 | for (i = 0; i < MAXARGV; i++) |
942 | SWAP (char *, sep->se_argv[i], cp->se_argv[i]); | 942 | SWAP(char *, sep->se_argv[i], cp->se_argv[i]); |
943 | #undef SWAP | 943 | #undef SWAP |
944 | 944 | ||
945 | #ifdef CONFIG_FEATURE_INETD_RPC | 945 | #ifdef CONFIG_FEATURE_INETD_RPC |
946 | if (isrpcservice (sep)) | 946 | if (isrpcservice(sep)) |
947 | unregister_rpc (sep); | 947 | unregister_rpc(sep); |
948 | sep->se_rpcversl = cp->se_rpcversl; | 948 | sep->se_rpcversl = cp->se_rpcversl; |
949 | sep->se_rpcversh = cp->se_rpcversh; | 949 | sep->se_rpcversh = cp->se_rpcversh; |
950 | #endif | 950 | #endif |
951 | sigprocmask(SIG_UNBLOCK, &omask, NULL); | 951 | sigprocmask(SIG_UNBLOCK, &omask, NULL); |
952 | freeconfig (cp); | 952 | freeconfig(cp); |
953 | } else { | 953 | } else { |
954 | sep = enter (cp); | 954 | sep = enter(cp); |
955 | } | 955 | } |
956 | sep->se_checked = 1; | 956 | sep->se_checked = 1; |
957 | 957 | ||
958 | switch (sep->se_family) { | 958 | switch (sep->se_family) { |
959 | case AF_UNIX: | 959 | case AF_UNIX: |
960 | if (sep->se_fd != -1) | 960 | if (sep->se_fd != -1) |
961 | break; | 961 | break; |
962 | (void) unlink (sep->se_service); | 962 | (void) unlink(sep->se_service); |
963 | n = strlen (sep->se_service); | 963 | n = strlen(sep->se_service); |
964 | if (n > sizeof sep->se_ctrladdr_un.sun_path - 1) | 964 | if (n > sizeof sep->se_ctrladdr_un.sun_path - 1) |
965 | n = sizeof sep->se_ctrladdr_un.sun_path - 1; | 965 | n = sizeof sep->se_ctrladdr_un.sun_path - 1; |
966 | safe_strncpy (sep->se_ctrladdr_un.sun_path, sep->se_service, n + 1); | 966 | safe_strncpy(sep->se_ctrladdr_un.sun_path, sep->se_service, n + 1); |
967 | sep->se_ctrladdr_un.sun_family = AF_UNIX; | 967 | sep->se_ctrladdr_un.sun_family = AF_UNIX; |
968 | sep->se_ctrladdr_size = n + sizeof sep->se_ctrladdr_un.sun_family; | 968 | sep->se_ctrladdr_size = n + sizeof sep->se_ctrladdr_un.sun_family; |
969 | setup (sep); | 969 | setup(sep); |
970 | break; | 970 | break; |
971 | case AF_INET: | 971 | case AF_INET: |
972 | sep->se_ctrladdr_in.sin_family = AF_INET; | 972 | sep->se_ctrladdr_in.sin_family = AF_INET; |
973 | /* se_ctrladdr_in was set in getconfigent */ | 973 | /* se_ctrladdr_in was set in getconfigent */ |
974 | sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; | 974 | sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in; |
975 | 975 | ||
976 | #ifdef CONFIG_FEATURE_INETD_RPC | 976 | #ifdef CONFIG_FEATURE_INETD_RPC |
977 | if (isrpcservice (sep)) { | 977 | if (isrpcservice(sep)) { |
978 | struct rpcent *rp; | 978 | struct rpcent *rp; |
979 | 979 | ||
980 | sep->se_rpcprog = atoi (sep->se_service); | 980 | sep->se_rpcprog = atoi(sep->se_service); |
981 | if (sep->se_rpcprog == 0) { | 981 | if (sep->se_rpcprog == 0) { |
982 | rp = getrpcbyname (sep->se_service); | 982 | rp = getrpcbyname(sep->se_service); |
983 | if (rp == 0) { | 983 | if (rp == 0) { |
984 | bb_error_msg ("%s: unknown rpc service", sep->se_service); | 984 | bb_error_msg("%s: unknown rpc service", sep->se_service); |
985 | goto serv_unknown; | 985 | goto serv_unknown; |
986 | } | 986 | } |
987 | sep->se_rpcprog = rp->r_number; | 987 | sep->se_rpcprog = rp->r_number; |
988 | } | 988 | } |
989 | if (sep->se_fd == -1) | 989 | if (sep->se_fd == -1) |
990 | setup (sep); | 990 | setup(sep); |
991 | if (sep->se_fd != -1) | 991 | if (sep->se_fd != -1) |
992 | register_rpc (sep); | 992 | register_rpc(sep); |
993 | } else | 993 | } else |
994 | #endif | 994 | #endif |
995 | { | 995 | { |
996 | u_short port = htons (atoi (sep->se_service)); | 996 | u_short port = htons(atoi(sep->se_service)); |
997 | 997 | ||
998 | if (!port) { | 998 | if (!port) { |
999 | /*XXX*/ strncpy (protoname, sep->se_proto, sizeof (protoname)); | 999 | /*XXX*/ strncpy(protoname, sep->se_proto, sizeof(protoname)); |
1000 | if (isdigit (protoname[strlen (protoname) - 1])) | 1000 | if (isdigit(protoname[strlen(protoname) - 1])) |
1001 | protoname[strlen (protoname) - 1] = '\0'; | 1001 | protoname[strlen(protoname) - 1] = '\0'; |
1002 | sp = getservbyname (sep->se_service, protoname); | 1002 | sp = getservbyname(sep->se_service, protoname); |
1003 | if (sp == 0) { | 1003 | if (sp == 0) { |
1004 | bb_error_msg ("%s/%s: unknown service", | 1004 | bb_error_msg("%s/%s: unknown service", |
1005 | sep->se_service, sep->se_proto); | 1005 | sep->se_service, sep->se_proto); |
1006 | goto serv_unknown; | 1006 | goto serv_unknown; |
1007 | } | 1007 | } |
1008 | port = sp->s_port; | 1008 | port = sp->s_port; |
1009 | } | 1009 | } |
1010 | if (port != sep->se_ctrladdr_in.sin_port) { | 1010 | if (port != sep->se_ctrladdr_in.sin_port) { |
1011 | sep->se_ctrladdr_in.sin_port = port; | 1011 | sep->se_ctrladdr_in.sin_port = port; |
1012 | if (sep->se_fd != -1) { | 1012 | if (sep->se_fd != -1) { |
1013 | FD_CLR (sep->se_fd, &allsock); | 1013 | FD_CLR(sep->se_fd, &allsock); |
1014 | nsock--; | 1014 | nsock--; |
1015 | (void) close (sep->se_fd); | 1015 | (void) close(sep->se_fd); |
1016 | } | 1016 | } |
1017 | sep->se_fd = -1; | 1017 | sep->se_fd = -1; |
1018 | } | 1018 | } |
1019 | if (sep->se_fd == -1) | 1019 | if (sep->se_fd == -1) |
1020 | setup (sep); | 1020 | setup(sep); |
1021 | } | 1021 | } |
1022 | break; | 1022 | break; |
1023 | #ifdef CONFIG_FEATURE_IPV6 | 1023 | #ifdef CONFIG_FEATURE_IPV6 |
1024 | case AF_INET6: | 1024 | case AF_INET6: |
1025 | sep->se_ctrladdr_in6.sin6_family = AF_INET6; | 1025 | sep->se_ctrladdr_in6.sin6_family = AF_INET6; |
1026 | /* se_ctrladdr_in was set in getconfigent */ | 1026 | /* se_ctrladdr_in was set in getconfigent */ |
1027 | sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6; | 1027 | sep->se_ctrladdr_size = sizeof sep->se_ctrladdr_in6; |
1028 | 1028 | ||
1029 | #ifdef CONFIG_FEATURE_INETD_RPC | 1029 | #ifdef CONFIG_FEATURE_INETD_RPC |
1030 | if (isrpcservice (sep)) { | 1030 | if (isrpcservice(sep)) { |
1031 | struct rpcent *rp; | 1031 | struct rpcent *rp; |
1032 | 1032 | ||
1033 | sep->se_rpcprog = atoi (sep->se_service); | 1033 | sep->se_rpcprog = atoi(sep->se_service); |
1034 | if (sep->se_rpcprog == 0) { | 1034 | if (sep->se_rpcprog == 0) { |
1035 | rp = getrpcbyname (sep->se_service); | 1035 | rp = getrpcbyname(sep->se_service); |
1036 | if (rp == 0) { | 1036 | if (rp == 0) { |
1037 | bb_error_msg ("%s: unknown rpc service", sep->se_service); | 1037 | bb_error_msg("%s: unknown rpc service", sep->se_service); |
1038 | goto serv_unknown; | 1038 | goto serv_unknown; |
1039 | } | 1039 | } |
1040 | sep->se_rpcprog = rp->r_number; | 1040 | sep->se_rpcprog = rp->r_number; |
1041 | } | 1041 | } |
1042 | if (sep->se_fd == -1) | 1042 | if (sep->se_fd == -1) |
1043 | setup (sep); | 1043 | setup(sep); |
1044 | if (sep->se_fd != -1) | 1044 | if (sep->se_fd != -1) |
1045 | register_rpc (sep); | 1045 | register_rpc(sep); |
1046 | } else | 1046 | } else |
1047 | #endif | 1047 | #endif |
1048 | { | 1048 | { |
1049 | u_short port = htons (atoi (sep->se_service)); | 1049 | u_short port = htons(atoi(sep->se_service)); |
1050 | 1050 | ||
1051 | if (!port) { | 1051 | if (!port) { |
1052 | /*XXX*/ strncpy (protoname, sep->se_proto, sizeof (protoname)); | 1052 | /*XXX*/ strncpy(protoname, sep->se_proto, sizeof(protoname)); |
1053 | if (isdigit (protoname[strlen (protoname) - 1])) | 1053 | if (isdigit(protoname[strlen(protoname) - 1])) |
1054 | protoname[strlen (protoname) - 1] = '\0'; | 1054 | protoname[strlen(protoname) - 1] = '\0'; |
1055 | sp = getservbyname (sep->se_service, protoname); | 1055 | sp = getservbyname(sep->se_service, protoname); |
1056 | if (sp == 0) { | 1056 | if (sp == 0) { |
1057 | bb_error_msg ("%s/%s: unknown service", | 1057 | bb_error_msg("%s/%s: unknown service", |
1058 | sep->se_service, sep->se_proto); | 1058 | sep->se_service, sep->se_proto); |
1059 | goto serv_unknown; | 1059 | goto serv_unknown; |
1060 | } | 1060 | } |
1061 | port = sp->s_port; | 1061 | port = sp->s_port; |
1062 | } | 1062 | } |
1063 | if (port != sep->se_ctrladdr_in6.sin6_port) { | 1063 | if (port != sep->se_ctrladdr_in6.sin6_port) { |
1064 | sep->se_ctrladdr_in6.sin6_port = port; | 1064 | sep->se_ctrladdr_in6.sin6_port = port; |
1065 | if (sep->se_fd != -1) { | 1065 | if (sep->se_fd != -1) { |
1066 | FD_CLR (sep->se_fd, &allsock); | 1066 | FD_CLR(sep->se_fd, &allsock); |
1067 | nsock--; | 1067 | nsock--; |
1068 | (void) close (sep->se_fd); | 1068 | (void) close(sep->se_fd); |
1069 | } | 1069 | } |
1070 | sep->se_fd = -1; | 1070 | sep->se_fd = -1; |
1071 | } | 1071 | } |
1072 | if (sep->se_fd == -1) | 1072 | if (sep->se_fd == -1) |
1073 | setup (sep); | 1073 | setup(sep); |
1074 | } | 1074 | } |
1075 | break; | 1075 | break; |
1076 | #endif /* CONFIG_FEATURE_IPV6 */ | 1076 | #endif /* CONFIG_FEATURE_IPV6 */ |
1077 | } | 1077 | } |
1078 | serv_unknown: | 1078 | serv_unknown: |
1079 | if (cp->se_next != NULL) { | 1079 | if (cp->se_next != NULL) { |
1080 | servtab_t *tmp = cp; | 1080 | servtab_t *tmp = cp; |
1081 | 1081 | ||
1082 | cp = cp->se_next; | 1082 | cp = cp->se_next; |
1083 | free (tmp); | 1083 | free(tmp); |
1084 | } else { | 1084 | } else { |
1085 | free (cp); | 1085 | free(cp); |
1086 | cp = getconfigent (); | 1086 | cp = getconfigent(); |
1087 | } | 1087 | } |
1088 | } | ||
1089 | endconfig (); | ||
1090 | /* | ||
1091 | * Purge anything not looked at above. | ||
1092 | */ | ||
1093 | Block_Using_Signals(omask); | ||
1094 | sepp = &servtab; | ||
1095 | while ((sep = *sepp)) { | ||
1096 | if (sep->se_checked) { | ||
1097 | sepp = &sep->se_next; | ||
1098 | continue; | ||
1099 | } | ||
1100 | *sepp = sep->se_next; | ||
1101 | if (sep->se_fd != -1) { | ||
1102 | FD_CLR (sep->se_fd, &allsock); | ||
1103 | nsock--; | ||
1104 | (void) close (sep->se_fd); | ||
1105 | } | 1088 | } |
1089 | endconfig(); | ||
1090 | /* | ||
1091 | * Purge anything not looked at above. | ||
1092 | */ | ||
1093 | Block_Using_Signals(omask); | ||
1094 | sepp = &servtab; | ||
1095 | while ((sep = *sepp)) { | ||
1096 | if (sep->se_checked) { | ||
1097 | sepp = &sep->se_next; | ||
1098 | continue; | ||
1099 | } | ||
1100 | *sepp = sep->se_next; | ||
1101 | if (sep->se_fd != -1) { | ||
1102 | FD_CLR(sep->se_fd, &allsock); | ||
1103 | nsock--; | ||
1104 | (void) close(sep->se_fd); | ||
1105 | } | ||
1106 | #ifdef CONFIG_FEATURE_INETD_RPC | 1106 | #ifdef CONFIG_FEATURE_INETD_RPC |
1107 | if (isrpcservice (sep)) | 1107 | if (isrpcservice(sep)) |
1108 | unregister_rpc (sep); | 1108 | unregister_rpc(sep); |
1109 | #endif | 1109 | #endif |
1110 | if (sep->se_family == AF_UNIX) | 1110 | if (sep->se_family == AF_UNIX) |
1111 | (void) unlink (sep->se_service); | 1111 | (void) unlink(sep->se_service); |
1112 | freeconfig (sep); | 1112 | freeconfig(sep); |
1113 | free (sep); | 1113 | free(sep); |
1114 | } | 1114 | } |
1115 | sigprocmask(SIG_UNBLOCK, &omask, NULL); | 1115 | sigprocmask(SIG_UNBLOCK, &omask, NULL); |
1116 | } | 1116 | } |
1117 | 1117 | ||
1118 | 1118 | ||
1119 | static void reapchild (int sig ATTRIBUTE_UNUSED) | 1119 | static void reapchild(int sig ATTRIBUTE_UNUSED) |
1120 | { | 1120 | { |
1121 | pid_t pid; | 1121 | pid_t pid; |
1122 | int save_errno = errno, status; | 1122 | int save_errno = errno, status; |
1123 | servtab_t *sep; | 1123 | servtab_t *sep; |
1124 | 1124 | ||
1125 | for (;;) { | 1125 | for (;;) { |
1126 | pid = wait3 (&status, WNOHANG, NULL); | 1126 | pid = wait3(&status, WNOHANG, NULL); |
1127 | if (pid <= 0) | 1127 | if (pid <= 0) |
1128 | break; | 1128 | break; |
1129 | for (sep = servtab; sep; sep = sep->se_next) | 1129 | for (sep = servtab; sep; sep = sep->se_next) |
1130 | if (sep->se_wait == pid) { | 1130 | if (sep->se_wait == pid) { |
1131 | if (WIFEXITED (status) && WEXITSTATUS (status)) | 1131 | if (WIFEXITED(status) && WEXITSTATUS(status)) |
1132 | bb_error_msg("%s: exit status 0x%x", | 1132 | bb_error_msg("%s: exit status 0x%x", |
1133 | sep->se_server, WEXITSTATUS (status)); | 1133 | sep->se_server, WEXITSTATUS(status)); |
1134 | else if (WIFSIGNALED (status)) | 1134 | else if (WIFSIGNALED(status)) |
1135 | bb_error_msg("%s: exit signal 0x%x", | 1135 | bb_error_msg("%s: exit signal 0x%x", |
1136 | sep->se_server, WTERMSIG (status)); | 1136 | sep->se_server, WTERMSIG(status)); |
1137 | sep->se_wait = 1; | 1137 | sep->se_wait = 1; |
1138 | FD_SET (sep->se_fd, &allsock); | 1138 | FD_SET(sep->se_fd, &allsock); |
1139 | nsock++; | 1139 | nsock++; |
1140 | } | 1140 | } |
1141 | } | 1141 | } |
1142 | errno = save_errno; | 1142 | errno = save_errno; |
1143 | } | 1143 | } |
1144 | 1144 | ||
1145 | static void retry (int sig ATTRIBUTE_UNUSED) | 1145 | static void retry(int sig ATTRIBUTE_UNUSED) |
1146 | { | 1146 | { |
1147 | servtab_t *sep; | 1147 | servtab_t *sep; |
1148 | 1148 | ||
1149 | timingout = 0; | 1149 | timingout = 0; |
1150 | for (sep = servtab; sep; sep = sep->se_next) { | 1150 | for (sep = servtab; sep; sep = sep->se_next) { |
1151 | if (sep->se_fd == -1) { | 1151 | if (sep->se_fd == -1) { |
1152 | switch (sep->se_family) { | 1152 | switch (sep->se_family) { |
1153 | case AF_UNIX: | 1153 | case AF_UNIX: |
1154 | case AF_INET: | 1154 | case AF_INET: |
1155 | #ifdef CONFIG_FEATURE_IPV6 | 1155 | #ifdef CONFIG_FEATURE_IPV6 |
1156 | case AF_INET6: | 1156 | case AF_INET6: |
1157 | #endif | 1157 | #endif |
1158 | setup (sep); | 1158 | setup(sep); |
1159 | #ifdef CONFIG_FEATURE_INETD_RPC | 1159 | #ifdef CONFIG_FEATURE_INETD_RPC |
1160 | if (sep->se_fd != -1 && isrpcservice (sep)) | 1160 | if (sep->se_fd != -1 && isrpcservice(sep)) |
1161 | register_rpc (sep); | 1161 | register_rpc(sep); |
1162 | #endif | 1162 | #endif |
1163 | break; | 1163 | break; |
1164 | } | 1164 | } |
1165 | } | ||
1165 | } | 1166 | } |
1166 | } | ||
1167 | } | 1167 | } |
1168 | 1168 | ||
1169 | static void goaway (int sig ATTRIBUTE_UNUSED) | 1169 | static void goaway(int sig ATTRIBUTE_UNUSED) |
1170 | { | 1170 | { |
1171 | servtab_t *sep; | 1171 | servtab_t *sep; |
1172 | 1172 | ||
1173 | /* XXX signal race walking sep list */ | 1173 | /* XXX signal race walking sep list */ |
1174 | for (sep = servtab; sep; sep = sep->se_next) { | 1174 | for (sep = servtab; sep; sep = sep->se_next) { |
1175 | if (sep->se_fd == -1) | 1175 | if (sep->se_fd == -1) |
1176 | continue; | 1176 | continue; |
1177 | 1177 | ||
1178 | switch (sep->se_family) { | 1178 | switch (sep->se_family) { |
1179 | case AF_UNIX: | 1179 | case AF_UNIX: |
1180 | (void) unlink (sep->se_service); | 1180 | (void) unlink(sep->se_service); |
1181 | break; | 1181 | break; |
1182 | case AF_INET: | 1182 | case AF_INET: |
1183 | #ifdef CONFIG_FEATURE_IPV6 | 1183 | #ifdef CONFIG_FEATURE_IPV6 |
1184 | case AF_INET6: | 1184 | case AF_INET6: |
1185 | #endif | 1185 | #endif |
1186 | #ifdef CONFIG_FEATURE_INETD_RPC | 1186 | #ifdef CONFIG_FEATURE_INETD_RPC |
1187 | if (sep->se_wait == 1 && isrpcservice (sep)) | 1187 | if (sep->se_wait == 1 && isrpcservice(sep)) |
1188 | unregister_rpc (sep); /* XXX signal race */ | 1188 | unregister_rpc(sep); /* XXX signal race */ |
1189 | #endif | 1189 | #endif |
1190 | break; | 1190 | break; |
1191 | } | ||
1192 | (void) close(sep->se_fd); | ||
1191 | } | 1193 | } |
1192 | (void) close (sep->se_fd); | 1194 | (void) unlink(_PATH_INETDPID); |
1193 | } | 1195 | exit(0); |
1194 | (void) unlink (_PATH_INETDPID); | ||
1195 | exit (0); | ||
1196 | } | 1196 | } |
1197 | 1197 | ||
1198 | 1198 | ||
@@ -1201,314 +1201,316 @@ static char **Argv; | |||
1201 | static char *LastArg; | 1201 | static char *LastArg; |
1202 | 1202 | ||
1203 | static void | 1203 | static void |
1204 | inetd_setproctitle (char *a, int s) | 1204 | inetd_setproctitle(char *a, int s) |
1205 | { | 1205 | { |
1206 | socklen_t size; | 1206 | socklen_t size; |
1207 | char *cp; | 1207 | char *cp; |
1208 | struct sockaddr_in prt_sin; | 1208 | struct sockaddr_in prt_sin; |
1209 | char buf[80]; | 1209 | char buf[80]; |
1210 | 1210 | ||
1211 | cp = Argv[0]; | 1211 | cp = Argv[0]; |
1212 | size = sizeof (prt_sin); | 1212 | size = sizeof(prt_sin); |
1213 | (void) snprintf (buf, sizeof buf, "-%s", a); | 1213 | (void) snprintf(buf, sizeof buf, "-%s", a); |
1214 | if (getpeername (s, (struct sockaddr *) &prt_sin, &size) == 0) { | 1214 | if (getpeername(s, (struct sockaddr *) &prt_sin, &size) == 0) { |
1215 | char *sa = inet_ntoa (prt_sin.sin_addr); | 1215 | char *sa = inet_ntoa(prt_sin.sin_addr); |
1216 | 1216 | ||
1217 | buf[sizeof (buf) - 1 - strlen (sa) - 3] = '\0'; | 1217 | buf[sizeof(buf) - 1 - strlen(sa) - 3] = '\0'; |
1218 | strcat (buf, " ["); | 1218 | strcat(buf, " ["); |
1219 | strcat (buf, sa); | 1219 | strcat(buf, sa); |
1220 | strcat (buf, "]"); | 1220 | strcat(buf, "]"); |
1221 | } | 1221 | } |
1222 | strncpy (cp, buf, LastArg - cp); | 1222 | strncpy(cp, buf, LastArg - cp); |
1223 | cp += strlen (cp); | 1223 | cp += strlen(cp); |
1224 | while (cp < LastArg) | 1224 | while (cp < LastArg) |
1225 | *cp++ = ' '; | 1225 | *cp++ = ' '; |
1226 | } | 1226 | } |
1227 | #endif | 1227 | #endif |
1228 | 1228 | ||
1229 | 1229 | ||
1230 | int | 1230 | int |
1231 | inetd_main (int argc, char *argv[]) | 1231 | inetd_main(int argc, char *argv[]) |
1232 | { | 1232 | { |
1233 | servtab_t *sep; | 1233 | servtab_t *sep; |
1234 | struct passwd *pwd; | 1234 | struct passwd *pwd; |
1235 | struct group *grp = NULL; | 1235 | struct group *grp = NULL; |
1236 | int tmpint; | 1236 | int tmpint; |
1237 | struct sigaction sa, sapipe; | 1237 | struct sigaction sa, sapipe; |
1238 | int opt; | 1238 | int opt; |
1239 | pid_t pid; | 1239 | pid_t pid; |
1240 | char buf[50]; | 1240 | char buf[50]; |
1241 | char *stoomany; | 1241 | char *stoomany; |
1242 | sigset_t omask, wait_mask; | 1242 | sigset_t omask, wait_mask; |
1243 | 1243 | ||
1244 | #ifdef INETD_SETPROCTITLE | 1244 | #ifdef INETD_SETPROCTITLE |
1245 | extern char **environ; | 1245 | extern char **environ; |
1246 | char **envp = environ; | 1246 | char **envp = environ; |
1247 | 1247 | ||
1248 | Argv = argv; | 1248 | Argv = argv; |
1249 | if (envp == 0 || *envp == 0) | 1249 | if (envp == 0 || *envp == 0) |
1250 | envp = argv; | 1250 | envp = argv; |
1251 | while (*envp) | 1251 | while (*envp) |
1252 | envp++; | 1252 | envp++; |
1253 | LastArg = envp[-1] + strlen (envp[-1]); | 1253 | LastArg = envp[-1] + strlen(envp[-1]); |
1254 | #endif | 1254 | #endif |
1255 | 1255 | ||
1256 | openlog (bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON); | 1256 | openlog(bb_applet_name, LOG_PID | LOG_NOWAIT, LOG_DAEMON); |
1257 | 1257 | ||
1258 | opt = bb_getopt_ulflags (argc, argv, "R:f", &stoomany); | 1258 | opt = bb_getopt_ulflags(argc, argv, "R:f", &stoomany); |
1259 | if(opt & 1) { | 1259 | if(opt & 1) { |
1260 | char *e; | 1260 | char *e; |
1261 | 1261 | ||
1262 | toomany = strtoul (stoomany, &e, 0); | 1262 | toomany = strtoul(stoomany, &e, 0); |
1263 | if (!(toomany >= 0 && *e == '\0')) { | 1263 | if (!(toomany >= 0 && *e == '\0')) { |
1264 | toomany = TOOMANY; | 1264 | toomany = TOOMANY; |
1265 | bb_perror_msg ("-R %s: bad value for service invocation rate", stoomany); | 1265 | bb_perror_msg("-R %s: bad value for service invocation rate", stoomany); |
1266 | } | ||
1266 | } | 1267 | } |
1267 | } | 1268 | argc -= optind; |
1268 | argc -= optind; | 1269 | argv += optind; |
1269 | argv += optind; | 1270 | |
1270 | 1271 | uid = getuid(); | |
1271 | uid = getuid (); | 1272 | if (uid != 0) |
1272 | if (uid != 0) | 1273 | CONFIG = NULL; |
1273 | CONFIG = NULL; | 1274 | if (argc > 0) |
1274 | if (argc > 0) | 1275 | CONFIG = argv[0]; |
1275 | CONFIG = argv[0]; | 1276 | if (CONFIG == NULL) |
1276 | if (CONFIG == NULL) | 1277 | bb_error_msg_and_die("non-root must specify a config file"); |
1277 | bb_error_msg_and_die ("non-root must specify a config file"); | 1278 | |
1278 | 1279 | if (!(opt & 2)) { | |
1279 | if (!(opt & 2)) { | ||
1280 | #ifdef BB_NOMMU | 1280 | #ifdef BB_NOMMU |
1281 | /* reexec for vfork() do continue parent */ | 1281 | /* reexec for vfork() do continue parent */ |
1282 | vfork_daemon_rexec (0, 0, argc, argv, "-f"); | 1282 | vfork_daemon_rexec(0, 0, argc, argv, "-f"); |
1283 | #else | 1283 | #else |
1284 | xdaemon (0, 0); | 1284 | xdaemon(0, 0); |
1285 | #endif | 1285 | #endif |
1286 | } else { | 1286 | } else { |
1287 | setsid (); | 1287 | setsid(); |
1288 | } | 1288 | } |
1289 | logmode = LOGMODE_SYSLOG; | 1289 | logmode = LOGMODE_SYSLOG; |
1290 | 1290 | ||
1291 | if (uid == 0) { | 1291 | if (uid == 0) { |
1292 | gid_t gid = getgid (); | 1292 | gid_t gid = getgid(); |
1293 | 1293 | ||
1294 | /* If run by hand, ensure groups vector gets trashed */ | 1294 | /* If run by hand, ensure groups vector gets trashed */ |
1295 | setgroups (1, &gid); | 1295 | setgroups(1, &gid); |
1296 | } | 1296 | } |
1297 | 1297 | ||
1298 | { | 1298 | { |
1299 | FILE *fp; | 1299 | FILE *fp = fopen(_PATH_INETDPID, "w"); |
1300 | 1300 | ||
1301 | if ((fp = fopen (_PATH_INETDPID, "w")) != NULL) { | 1301 | if (fp != NULL) { |
1302 | fprintf (fp, "%u\n", getpid ()); | 1302 | fprintf(fp, "%u\n", getpid()); |
1303 | (void) fclose (fp); | 1303 | (void) fclose(fp); |
1304 | } | ||
1304 | } | 1305 | } |
1305 | } | ||
1306 | |||
1307 | if (getrlimit (RLIMIT_NOFILE, &rlim_ofile) < 0) { | ||
1308 | bb_perror_msg ("getrlimit"); | ||
1309 | } else { | ||
1310 | rlim_ofile_cur = rlim_ofile.rlim_cur; | ||
1311 | if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ | ||
1312 | rlim_ofile_cur = OPEN_MAX; | ||
1313 | } | ||
1314 | |||
1315 | memset ((char *) &sa, 0, sizeof (sa)); | ||
1316 | sigemptyset (&sa.sa_mask); | ||
1317 | sigaddset (&sa.sa_mask, SIGALRM); | ||
1318 | sigaddset (&sa.sa_mask, SIGCHLD); | ||
1319 | sigaddset (&sa.sa_mask, SIGHUP); | ||
1320 | sa.sa_handler = retry; | ||
1321 | sigaction (SIGALRM, &sa, NULL); | ||
1322 | /* doconfig(); */ | ||
1323 | config (SIGHUP); | ||
1324 | sa.sa_handler = config; | ||
1325 | sigaction (SIGHUP, &sa, NULL); | ||
1326 | sa.sa_handler = reapchild; | ||
1327 | sigaction (SIGCHLD, &sa, NULL); | ||
1328 | sa.sa_handler = goaway; | ||
1329 | sigaction (SIGTERM, &sa, NULL); | ||
1330 | sa.sa_handler = goaway; | ||
1331 | sigaction (SIGINT, &sa, NULL); | ||
1332 | sa.sa_handler = SIG_IGN; | ||
1333 | sigaction (SIGPIPE, &sa, &sapipe); | ||
1334 | memset(&wait_mask, 0, sizeof(wait_mask)); | ||
1335 | { | ||
1336 | /* space for daemons to overwrite environment for ps */ | ||
1337 | #define DUMMYSIZE 100 | ||
1338 | char dummy[DUMMYSIZE]; | ||
1339 | 1306 | ||
1340 | (void) memset (dummy, 'x', DUMMYSIZE - 1); | 1307 | if (getrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) { |
1341 | dummy[DUMMYSIZE - 1] = '\0'; | 1308 | bb_perror_msg("getrlimit"); |
1309 | } else { | ||
1310 | rlim_ofile_cur = rlim_ofile.rlim_cur; | ||
1311 | if (rlim_ofile_cur == RLIM_INFINITY) /* ! */ | ||
1312 | rlim_ofile_cur = OPEN_MAX; | ||
1313 | } | ||
1342 | 1314 | ||
1343 | (void) setenv ("inetd_dummy", dummy, 1); | 1315 | memset((char *) &sa, 0, sizeof(sa)); |
1344 | } | 1316 | sigemptyset(&sa.sa_mask); |
1317 | sigaddset(&sa.sa_mask, SIGALRM); | ||
1318 | sigaddset(&sa.sa_mask, SIGCHLD); | ||
1319 | sigaddset(&sa.sa_mask, SIGHUP); | ||
1320 | sa.sa_handler = retry; | ||
1321 | sigaction(SIGALRM, &sa, NULL); | ||
1322 | /* doconfig(); */ | ||
1323 | config(SIGHUP); | ||
1324 | sa.sa_handler = config; | ||
1325 | sigaction(SIGHUP, &sa, NULL); | ||
1326 | sa.sa_handler = reapchild; | ||
1327 | sigaction(SIGCHLD, &sa, NULL); | ||
1328 | sa.sa_handler = goaway; | ||
1329 | sigaction(SIGTERM, &sa, NULL); | ||
1330 | sa.sa_handler = goaway; | ||
1331 | sigaction(SIGINT, &sa, NULL); | ||
1332 | sa.sa_handler = SIG_IGN; | ||
1333 | sigaction(SIGPIPE, &sa, &sapipe); | ||
1334 | memset(&wait_mask, 0, sizeof(wait_mask)); | ||
1335 | { | ||
1336 | /* space for daemons to overwrite environment for ps */ | ||
1337 | #define DUMMYSIZE 100 | ||
1338 | char dummy[DUMMYSIZE]; | ||
1345 | 1339 | ||
1346 | for (;;) { | 1340 | (void) memset(dummy, 'x', DUMMYSIZE - 1); |
1347 | int n, ctrl = -1; | 1341 | dummy[DUMMYSIZE - 1] = '\0'; |
1348 | fd_set readable; | ||
1349 | 1342 | ||
1350 | if (nsock == 0) { | 1343 | (void) setenv("inetd_dummy", dummy, 1); |
1351 | Block_Using_Signals(omask); | ||
1352 | while (nsock == 0) | ||
1353 | sigsuspend (&wait_mask); | ||
1354 | sigprocmask(SIG_UNBLOCK, &omask, NULL); | ||
1355 | } | 1344 | } |
1356 | 1345 | ||
1357 | readable = allsock; | 1346 | for (;;) { |
1358 | if ((n = select (maxsock + 1, &readable, NULL, NULL, NULL)) <= 0) { | 1347 | int n, ctrl = -1; |
1359 | if (n < 0 && errno != EINTR) { | 1348 | fd_set readable; |
1360 | bb_perror_msg("select"); | 1349 | |
1361 | sleep (1); | 1350 | if (nsock == 0) { |
1362 | } | 1351 | Block_Using_Signals(omask); |
1363 | continue; | 1352 | while (nsock == 0) |
1364 | } | 1353 | sigsuspend(&wait_mask); |
1365 | for (sep = servtab; n && sep; sep = sep->se_next) | 1354 | sigprocmask(SIG_UNBLOCK, &omask, NULL); |
1366 | if (sep->se_fd != -1 && FD_ISSET (sep->se_fd, &readable)) { | 1355 | } |
1367 | n--; | 1356 | |
1368 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { | 1357 | readable = allsock; |
1369 | ctrl = accept (sep->se_fd, NULL, NULL); | 1358 | n = select(maxsock + 1, &readable, NULL, NULL, NULL) |
1370 | if (ctrl < 0) { | 1359 | if (n <= 0) { |
1371 | if (errno == EINTR) | 1360 | if (n < 0 && errno != EINTR) { |
1372 | continue; | 1361 | bb_perror_msg("select"); |
1373 | bb_perror_msg("accept (for %s)", sep->se_service); | 1362 | sleep(1); |
1374 | continue; | ||
1375 | } | ||
1376 | if (sep->se_family == AF_INET && sep->se_socktype == SOCK_STREAM) { | ||
1377 | struct sockaddr_in peer; | ||
1378 | socklen_t plen = sizeof (peer); | ||
1379 | |||
1380 | if (getpeername (ctrl, (struct sockaddr *) &peer, &plen) < 0) { | ||
1381 | bb_error_msg("could not getpeername"); | ||
1382 | close (ctrl); | ||
1383 | continue; | ||
1384 | } | ||
1385 | if (ntohs (peer.sin_port) == 20) { | ||
1386 | /* XXX ftp bounce */ | ||
1387 | close (ctrl); | ||
1388 | continue; | ||
1389 | } | 1363 | } |
1390 | } | 1364 | continue; |
1391 | } else | 1365 | } |
1392 | ctrl = sep->se_fd; | 1366 | for (sep = servtab; n && sep; sep = sep->se_next) { |
1393 | Block_Using_Signals(omask); | 1367 | // TODO: undo this unholy mess |
1394 | pid = 0; | 1368 | if (sep->se_fd != -1 && FD_ISSET(sep->se_fd, &readable)) { |
1369 | n--; | ||
1370 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) { | ||
1371 | ctrl = accept(sep->se_fd, NULL, NULL); | ||
1372 | if (ctrl < 0) { | ||
1373 | if (errno == EINTR) | ||
1374 | continue; | ||
1375 | bb_perror_msg("accept (for %s)", sep->se_service); | ||
1376 | continue; | ||
1377 | } | ||
1378 | if (sep->se_family == AF_INET && sep->se_socktype == SOCK_STREAM) { | ||
1379 | struct sockaddr_in peer; | ||
1380 | socklen_t plen = sizeof(peer); | ||
1381 | |||
1382 | if (getpeername(ctrl, (struct sockaddr *) &peer, &plen) < 0) { | ||
1383 | bb_error_msg("could not getpeername"); | ||
1384 | close(ctrl); | ||
1385 | continue; | ||
1386 | } | ||
1387 | if (ntohs(peer.sin_port) == 20) { | ||
1388 | /* XXX ftp bounce */ | ||
1389 | close(ctrl); | ||
1390 | continue; | ||
1391 | } | ||
1392 | } | ||
1393 | } else | ||
1394 | ctrl = sep->se_fd; | ||
1395 | Block_Using_Signals(omask); | ||
1396 | pid = 0; | ||
1395 | #ifdef INETD_FEATURE_ENABLED | 1397 | #ifdef INETD_FEATURE_ENABLED |
1396 | if (sep->se_bi == 0 || sep->se_bi->bi_fork) | 1398 | if (sep->se_bi == 0 || sep->se_bi->bi_fork) |
1397 | #endif | 1399 | #endif |
1398 | { | 1400 | { |
1399 | if (sep->se_count++ == 0) | 1401 | if (sep->se_count++ == 0) |
1400 | (void) gettimeofday (&sep->se_time, NULL); | 1402 | (void) gettimeofday(&sep->se_time, NULL); |
1401 | else if (toomany > 0 && sep->se_count >= sep->se_max) { | 1403 | else if (toomany > 0 && sep->se_count >= sep->se_max) { |
1402 | struct timeval now; | 1404 | struct timeval now; |
1403 | 1405 | ||
1404 | (void) gettimeofday (&now, NULL); | 1406 | (void) gettimeofday(&now, NULL); |
1405 | if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) { | 1407 | if (now.tv_sec - sep->se_time.tv_sec > CNT_INTVL) { |
1406 | sep->se_time = now; | 1408 | sep->se_time = now; |
1407 | sep->se_count = 1; | 1409 | sep->se_count = 1; |
1408 | } else { | 1410 | } else { |
1409 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) | 1411 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) |
1410 | close (ctrl); | 1412 | close(ctrl); |
1411 | if (sep->se_family == AF_INET && | 1413 | if (sep->se_family == AF_INET && |
1412 | ntohs (sep->se_ctrladdr_in.sin_port) >= IPPORT_RESERVED) { | 1414 | ntohs(sep->se_ctrladdr_in.sin_port) >= IPPORT_RESERVED) { |
1413 | /* | 1415 | /* |
1414 | * Cannot close it -- there are | 1416 | * Cannot close it -- there are |
1415 | * thieves on the system. | 1417 | * thieves on the system. |
1416 | * Simply ignore the connection. | 1418 | * Simply ignore the connection. |
1417 | */ | 1419 | */ |
1418 | --sep->se_count; | 1420 | --sep->se_count; |
1419 | continue; | 1421 | continue; |
1420 | } | 1422 | } |
1421 | bb_error_msg ("%s/%s server failing (looping), service terminated", | 1423 | bb_error_msg("%s/%s server failing (looping), service terminated", |
1422 | sep->se_service, sep->se_proto); | 1424 | sep->se_service, sep->se_proto); |
1423 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) | 1425 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) |
1424 | close (ctrl); | 1426 | close(ctrl); |
1425 | FD_CLR (sep->se_fd, &allsock); | 1427 | FD_CLR(sep->se_fd, &allsock); |
1426 | (void) close (sep->se_fd); | 1428 | (void) close(sep->se_fd); |
1427 | sep->se_fd = -1; | 1429 | sep->se_fd = -1; |
1428 | sep->se_count = 0; | 1430 | sep->se_count = 0; |
1429 | nsock--; | 1431 | nsock--; |
1430 | sigprocmask(SIG_UNBLOCK, &omask, NULL); | 1432 | sigprocmask(SIG_UNBLOCK, &omask, NULL); |
1431 | if (!timingout) { | 1433 | if (!timingout) { |
1432 | timingout = 1; | 1434 | timingout = 1; |
1433 | alarm (RETRYTIME); | 1435 | alarm(RETRYTIME); |
1434 | } | 1436 | } |
1435 | continue; | 1437 | continue; |
1436 | } | 1438 | } |
1437 | } | 1439 | } |
1438 | pid = fork (); | 1440 | pid = fork(); |
1439 | } | 1441 | } |
1440 | if (pid < 0) { | 1442 | if (pid < 0) { |
1441 | bb_perror_msg ("fork"); | 1443 | bb_perror_msg("fork"); |
1442 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) | 1444 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) |
1443 | close (ctrl); | 1445 | close(ctrl); |
1444 | sigprocmask(SIG_UNBLOCK, &omask, NULL); | 1446 | sigprocmask(SIG_UNBLOCK, &omask, NULL); |
1445 | sleep (1); | 1447 | sleep(1); |
1446 | continue; | 1448 | continue; |
1447 | } | 1449 | } |
1448 | if (pid && sep->se_wait) { | 1450 | if (pid && sep->se_wait) { |
1449 | sep->se_wait = pid; | 1451 | sep->se_wait = pid; |
1450 | FD_CLR (sep->se_fd, &allsock); | 1452 | FD_CLR(sep->se_fd, &allsock); |
1451 | nsock--; | 1453 | nsock--; |
1452 | } | 1454 | } |
1453 | sigprocmask(SIG_UNBLOCK, &omask, NULL); | 1455 | sigprocmask(SIG_UNBLOCK, &omask, NULL); |
1454 | if (pid == 0) { | 1456 | if (pid == 0) { |
1455 | #ifdef INETD_FEATURE_ENABLED | 1457 | #ifdef INETD_FEATURE_ENABLED |
1456 | if (sep->se_bi) { | 1458 | if (sep->se_bi) { |
1457 | (*sep->se_bi->bi_fn) (ctrl, sep); | 1459 | (*sep->se_bi->bi_fn)(ctrl, sep); |
1458 | } else | 1460 | } else |
1459 | #endif | 1461 | #endif |
1460 | { | 1462 | { |
1461 | if ((pwd = getpwnam (sep->se_user)) == NULL) { | 1463 | if ((pwd = getpwnam(sep->se_user)) == NULL) { |
1462 | bb_error_msg ("getpwnam: %s: no such user", sep->se_user); | 1464 | bb_error_msg("getpwnam: %s: no such user", sep->se_user); |
1463 | if (sep->se_socktype != SOCK_STREAM) | 1465 | if (sep->se_socktype != SOCK_STREAM) |
1464 | recv (0, buf, sizeof (buf), 0); | 1466 | recv(0, buf, sizeof(buf), 0); |
1465 | _exit (1); | 1467 | _exit(1); |
1466 | } | 1468 | } |
1467 | if (setsid () < 0) | 1469 | if (setsid() < 0) |
1468 | bb_perror_msg ("%s: setsid", sep->se_service); | 1470 | bb_perror_msg("%s: setsid", sep->se_service); |
1469 | if (sep->se_group && (grp = getgrnam (sep->se_group)) == NULL) { | 1471 | if (sep->se_group && (grp = getgrnam(sep->se_group)) == NULL) { |
1470 | bb_error_msg ("getgrnam: %s: no such group", sep->se_group); | 1472 | bb_error_msg("getgrnam: %s: no such group", sep->se_group); |
1471 | if (sep->se_socktype != SOCK_STREAM) | 1473 | if (sep->se_socktype != SOCK_STREAM) |
1472 | recv (0, buf, sizeof (buf), 0); | 1474 | recv(0, buf, sizeof(buf), 0); |
1473 | _exit (1); | 1475 | _exit(1); |
1476 | } | ||
1477 | if (uid != 0) { | ||
1478 | /* a user running private inetd */ | ||
1479 | if (uid != pwd->pw_uid) | ||
1480 | _exit(1); | ||
1481 | } else if (pwd->pw_uid) { | ||
1482 | if (sep->se_group) | ||
1483 | pwd->pw_gid = grp->gr_gid; | ||
1484 | xsetgid((gid_t) pwd->pw_gid); | ||
1485 | initgroups(pwd->pw_name, pwd->pw_gid); | ||
1486 | xsetuid((uid_t) pwd->pw_uid); | ||
1487 | } else if (sep->se_group) { | ||
1488 | xsetgid(grp->gr_gid); | ||
1489 | setgroups(1, &grp->gr_gid); | ||
1490 | } | ||
1491 | dup2(ctrl, 0); | ||
1492 | close(ctrl); | ||
1493 | dup2(0, 1); | ||
1494 | dup2(0, 2); | ||
1495 | if (rlim_ofile.rlim_cur != rlim_ofile_cur) | ||
1496 | if (setrlimit(RLIMIT_NOFILE, &rlim_ofile) < 0) | ||
1497 | bb_perror_msg("setrlimit"); | ||
1498 | closelog(); | ||
1499 | for (tmpint = rlim_ofile_cur - 1; --tmpint > 2;) | ||
1500 | (void) close(tmpint); | ||
1501 | sigaction(SIGPIPE, &sapipe, NULL); | ||
1502 | execv(sep->se_server, sep->se_argv); | ||
1503 | if (sep->se_socktype != SOCK_STREAM) | ||
1504 | recv(0, buf, sizeof(buf), 0); | ||
1505 | bb_perror_msg("execv %s", sep->se_server); | ||
1506 | _exit(1); | ||
1507 | } | ||
1508 | } | ||
1509 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) | ||
1510 | close(ctrl); | ||
1474 | } | 1511 | } |
1475 | if (uid != 0) { | ||
1476 | /* a user running private inetd */ | ||
1477 | if (uid != pwd->pw_uid) | ||
1478 | _exit (1); | ||
1479 | } else if (pwd->pw_uid) { | ||
1480 | if (sep->se_group) { | ||
1481 | pwd->pw_gid = grp->gr_gid; | ||
1482 | } | ||
1483 | xsetgid ((gid_t) pwd->pw_gid); | ||
1484 | initgroups (pwd->pw_name, pwd->pw_gid); | ||
1485 | xsetuid((uid_t) pwd->pw_uid); | ||
1486 | } else if (sep->se_group) { | ||
1487 | xsetgid(grp->gr_gid); | ||
1488 | setgroups (1, &grp->gr_gid); | ||
1489 | } | ||
1490 | dup2 (ctrl, 0); | ||
1491 | close (ctrl); | ||
1492 | dup2 (0, 1); | ||
1493 | dup2 (0, 2); | ||
1494 | if (rlim_ofile.rlim_cur != rlim_ofile_cur) | ||
1495 | if (setrlimit (RLIMIT_NOFILE, &rlim_ofile) < 0) | ||
1496 | bb_perror_msg ("setrlimit"); | ||
1497 | closelog (); | ||
1498 | for (tmpint = rlim_ofile_cur - 1; --tmpint > 2;) | ||
1499 | (void) close (tmpint); | ||
1500 | sigaction (SIGPIPE, &sapipe, NULL); | ||
1501 | execv (sep->se_server, sep->se_argv); | ||
1502 | if (sep->se_socktype != SOCK_STREAM) | ||
1503 | recv (0, buf, sizeof (buf), 0); | ||
1504 | bb_perror_msg ("execv %s", sep->se_server); | ||
1505 | _exit (1); | ||
1506 | } | ||
1507 | } | 1512 | } |
1508 | if (!sep->se_wait && sep->se_socktype == SOCK_STREAM) | 1513 | } |
1509 | close (ctrl); | ||
1510 | } | ||
1511 | } | ||
1512 | } | 1514 | } |
1513 | 1515 | ||
1514 | /* | 1516 | /* |
@@ -1517,16 +1519,16 @@ inetd_main (int argc, char *argv[]) | |||
1517 | #define BUFSIZE 4096 | 1519 | #define BUFSIZE 4096 |
1518 | 1520 | ||
1519 | #if defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO) || \ | 1521 | #if defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO) || \ |
1520 | defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN) || \ | 1522 | defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN) || \ |
1521 | defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME) | 1523 | defined(CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME) |
1522 | static int dg_badinput (struct sockaddr_in *dg_sin) | 1524 | static int dg_badinput(struct sockaddr_in *dg_sin) |
1523 | { | 1525 | { |
1524 | if (ntohs (dg_sin->sin_port) < IPPORT_RESERVED) | 1526 | if (ntohs(dg_sin->sin_port) < IPPORT_RESERVED) |
1525 | return (1); | 1527 | return 1; |
1526 | if (dg_sin->sin_addr.s_addr == htonl (INADDR_BROADCAST)) | 1528 | if (dg_sin->sin_addr.s_addr == htonl(INADDR_BROADCAST)) |
1527 | return (1); | 1529 | return 1; |
1528 | /* XXX compare against broadcast addresses in SIOCGIFCONF list? */ | 1530 | /* XXX compare against broadcast addresses in SIOCGIFCONF list? */ |
1529 | return (0); | 1531 | return 0; |
1530 | } | 1532 | } |
1531 | #endif | 1533 | #endif |
1532 | 1534 | ||
@@ -1534,34 +1536,35 @@ static int dg_badinput (struct sockaddr_in *dg_sin) | |||
1534 | /* Echo service -- echo data back */ | 1536 | /* Echo service -- echo data back */ |
1535 | /* ARGSUSED */ | 1537 | /* ARGSUSED */ |
1536 | static void | 1538 | static void |
1537 | echo_stream (int s, servtab_t *sep) | 1539 | echo_stream(int s, servtab_t *sep) |
1538 | { | 1540 | { |
1539 | char buffer[BUFSIZE]; | 1541 | char buffer[BUFSIZE]; |
1540 | int i; | 1542 | int i; |
1541 | 1543 | ||
1542 | inetd_setproctitle (sep->se_service, s); | 1544 | inetd_setproctitle(sep->se_service, s); |
1543 | while ((i = read (s, buffer, sizeof (buffer))) > 0 && | 1545 | while ((i = read(s, buffer, sizeof(buffer))) > 0 && |
1544 | write (s, buffer, i) > 0); | 1546 | write(s, buffer, i) > 0); |
1545 | exit (0); | 1547 | exit(0); |
1546 | } | 1548 | } |
1547 | 1549 | ||
1548 | /* Echo service -- echo data back */ | 1550 | /* Echo service -- echo data back */ |
1549 | /* ARGSUSED */ | 1551 | /* ARGSUSED */ |
1550 | static void | 1552 | static void |
1551 | echo_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1553 | echo_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1552 | { | 1554 | { |
1553 | char buffer[BUFSIZE]; | 1555 | char buffer[BUFSIZE]; |
1554 | int i; | 1556 | int i; |
1555 | socklen_t size; | 1557 | socklen_t size; |
1556 | /* struct sockaddr_storage ss; */ | 1558 | /* struct sockaddr_storage ss; */ |
1557 | struct sockaddr sa; | 1559 | struct sockaddr sa; |
1558 | 1560 | ||
1559 | size = sizeof (sa); | 1561 | size = sizeof(sa); |
1560 | if ((i = recvfrom (s, buffer, sizeof (buffer), 0, &sa, &size)) < 0) | 1562 | i = recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size); |
1561 | return; | 1563 | if (i < 0) |
1562 | if (dg_badinput ((struct sockaddr_in *) &sa)) | 1564 | return; |
1563 | return; | 1565 | if (dg_badinput((struct sockaddr_in *) &sa)) |
1564 | (void) sendto (s, buffer, i, 0, &sa, sizeof (sa)); | 1566 | return; |
1567 | (void) sendto(s, buffer, i, 0, &sa, sizeof(sa)); | ||
1565 | } | 1568 | } |
1566 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO */ | 1569 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_ECHO */ |
1567 | 1570 | ||
@@ -1569,24 +1572,24 @@ echo_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1569 | /* Discard service -- ignore data */ | 1572 | /* Discard service -- ignore data */ |
1570 | /* ARGSUSED */ | 1573 | /* ARGSUSED */ |
1571 | static void | 1574 | static void |
1572 | discard_stream (int s, servtab_t *sep) | 1575 | discard_stream(int s, servtab_t *sep) |
1573 | { | 1576 | { |
1574 | char buffer[BUFSIZE]; | 1577 | char buffer[BUFSIZE]; |
1575 | 1578 | ||
1576 | inetd_setproctitle (sep->se_service, s); | 1579 | inetd_setproctitle(sep->se_service, s); |
1577 | while ((errno = 0, read (s, buffer, sizeof (buffer)) > 0) || | 1580 | while ((errno = 0, read(s, buffer, sizeof(buffer)) > 0) || |
1578 | errno == EINTR); | 1581 | errno == EINTR); |
1579 | exit (0); | 1582 | exit(0); |
1580 | } | 1583 | } |
1581 | 1584 | ||
1582 | /* Discard service -- ignore data */ | 1585 | /* Discard service -- ignore data */ |
1583 | /* ARGSUSED */ | 1586 | /* ARGSUSED */ |
1584 | static void | 1587 | static void |
1585 | discard_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1588 | discard_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1586 | { | 1589 | { |
1587 | char buffer[BUFSIZE]; | 1590 | char buffer[BUFSIZE]; |
1588 | 1591 | ||
1589 | (void) read (s, buffer, sizeof (buffer)); | 1592 | (void) read(s, buffer, sizeof(buffer)); |
1590 | } | 1593 | } |
1591 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD */ | 1594 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DISCARD */ |
1592 | 1595 | ||
@@ -1597,84 +1600,84 @@ static char ring[128]; | |||
1597 | static char *endring; | 1600 | static char *endring; |
1598 | 1601 | ||
1599 | static void | 1602 | static void |
1600 | initring (void) | 1603 | initring(void) |
1601 | { | 1604 | { |
1602 | int i; | 1605 | int i; |
1603 | 1606 | ||
1604 | endring = ring; | 1607 | endring = ring; |
1605 | 1608 | ||
1606 | for (i = 0; i <= 128; ++i) | 1609 | for (i = 0; i <= 128; ++i) |
1607 | if (isprint (i)) | 1610 | if (isprint(i)) |
1608 | *endring++ = i; | 1611 | *endring++ = i; |
1609 | } | 1612 | } |
1610 | 1613 | ||
1611 | /* Character generator */ | 1614 | /* Character generator */ |
1612 | /* ARGSUSED */ | 1615 | /* ARGSUSED */ |
1613 | static void | 1616 | static void |
1614 | chargen_stream (int s, servtab_t *sep) | 1617 | chargen_stream(int s, servtab_t *sep) |
1615 | { | 1618 | { |
1616 | char *rs; | 1619 | char *rs; |
1617 | int len; | 1620 | int len; |
1618 | char text[LINESIZ + 2]; | 1621 | char text[LINESIZ + 2]; |
1619 | 1622 | ||
1620 | inetd_setproctitle (sep->se_service, s); | 1623 | inetd_setproctitle(sep->se_service, s); |
1621 | 1624 | ||
1622 | if (!endring) { | 1625 | if (!endring) { |
1623 | initring (); | 1626 | initring(); |
1624 | rs = ring; | 1627 | rs = ring; |
1625 | } | 1628 | } |
1626 | 1629 | ||
1627 | text[LINESIZ] = '\r'; | 1630 | text[LINESIZ] = '\r'; |
1628 | text[LINESIZ + 1] = '\n'; | 1631 | text[LINESIZ + 1] = '\n'; |
1629 | for (rs = ring;;) { | 1632 | for (rs = ring;;) { |
1630 | if ((len = endring - rs) >= LINESIZ) | 1633 | if ((len = endring - rs) >= LINESIZ) |
1631 | memmove (text, rs, LINESIZ); | 1634 | memmove(text, rs, LINESIZ); |
1632 | else { | 1635 | else { |
1633 | memmove (text, rs, len); | 1636 | memmove(text, rs, len); |
1634 | memmove (text + len, ring, LINESIZ - len); | 1637 | memmove(text + len, ring, LINESIZ - len); |
1638 | } | ||
1639 | if (++rs == endring) | ||
1640 | rs = ring; | ||
1641 | if (write(s, text, sizeof(text)) != sizeof(text)) | ||
1642 | break; | ||
1635 | } | 1643 | } |
1636 | if (++rs == endring) | 1644 | exit(0); |
1637 | rs = ring; | ||
1638 | if (write (s, text, sizeof (text)) != sizeof (text)) | ||
1639 | break; | ||
1640 | } | ||
1641 | exit (0); | ||
1642 | } | 1645 | } |
1643 | 1646 | ||
1644 | /* Character generator */ | 1647 | /* Character generator */ |
1645 | /* ARGSUSED */ | 1648 | /* ARGSUSED */ |
1646 | static void | 1649 | static void |
1647 | chargen_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1650 | chargen_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1648 | { | 1651 | { |
1649 | /* struct sockaddr_storage ss; */ | 1652 | /* struct sockaddr_storage ss; */ |
1650 | struct sockaddr sa; | 1653 | struct sockaddr sa; |
1651 | static char *rs; | 1654 | static char *rs; |
1652 | int len; | 1655 | int len; |
1653 | char text[LINESIZ + 2]; | 1656 | char text[LINESIZ + 2]; |
1654 | socklen_t size; | 1657 | socklen_t size; |
1655 | 1658 | ||
1656 | if (endring == 0) { | 1659 | if (endring == 0) { |
1657 | initring (); | 1660 | initring(); |
1658 | rs = ring; | 1661 | rs = ring; |
1659 | } | 1662 | } |
1660 | 1663 | ||
1661 | size = sizeof (sa); | 1664 | size = sizeof(sa); |
1662 | if (recvfrom (s, text, sizeof (text), 0, &sa, &size) < 0) | 1665 | if (recvfrom(s, text, sizeof(text), 0, &sa, &size) < 0) |
1663 | return; | 1666 | return; |
1664 | if (dg_badinput ((struct sockaddr_in *) &sa)) | 1667 | if (dg_badinput((struct sockaddr_in *) &sa)) |
1665 | return; | 1668 | return; |
1666 | 1669 | ||
1667 | if ((len = endring - rs) >= LINESIZ) | 1670 | if ((len = endring - rs) >= LINESIZ) |
1668 | memmove (text, rs, LINESIZ); | 1671 | memmove(text, rs, LINESIZ); |
1669 | else { | 1672 | else { |
1670 | memmove (text, rs, len); | 1673 | memmove(text, rs, len); |
1671 | memmove (text + len, ring, LINESIZ - len); | 1674 | memmove(text + len, ring, LINESIZ - len); |
1672 | } | 1675 | } |
1673 | if (++rs == endring) | 1676 | if (++rs == endring) |
1674 | rs = ring; | 1677 | rs = ring; |
1675 | text[LINESIZ] = '\r'; | 1678 | text[LINESIZ] = '\r'; |
1676 | text[LINESIZ + 1] = '\n'; | 1679 | text[LINESIZ + 1] = '\n'; |
1677 | (void) sendto (s, text, sizeof (text), 0, &sa, sizeof (sa)); | 1680 | (void) sendto(s, text, sizeof(text), 0, &sa, sizeof(sa)); |
1678 | } | 1681 | } |
1679 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN */ | 1682 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_CHARGEN */ |
1680 | 1683 | ||
@@ -1688,47 +1691,47 @@ chargen_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1688 | * some seventy years Bell Labs was asleep. | 1691 | * some seventy years Bell Labs was asleep. |
1689 | */ | 1692 | */ |
1690 | 1693 | ||
1691 | static u_int machtime (void) | 1694 | static u_int machtime(void) |
1692 | { | 1695 | { |
1693 | struct timeval tv; | 1696 | struct timeval tv; |
1694 | 1697 | ||
1695 | if (gettimeofday (&tv, NULL) < 0) { | 1698 | if (gettimeofday(&tv, NULL) < 0) { |
1696 | fprintf (stderr, "Unable to get time of day\n"); | 1699 | fprintf(stderr, "Unable to get time of day\n"); |
1697 | return (0L); | 1700 | return 0L; |
1698 | } | 1701 | } |
1699 | return (htonl ((u_int) tv.tv_sec + 2208988800UL)); | 1702 | return htonl((u_int) tv.tv_sec + 2208988800UL); |
1700 | } | 1703 | } |
1701 | 1704 | ||
1702 | /* ARGSUSED */ | 1705 | /* ARGSUSED */ |
1703 | static void | 1706 | static void |
1704 | machtime_stream (int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1707 | machtime_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1705 | { | 1708 | { |
1706 | u_int result; | 1709 | u_int result; |
1707 | 1710 | ||
1708 | result = machtime (); | 1711 | result = machtime(); |
1709 | (void) write (s, (char *) &result, sizeof (result)); | 1712 | (void) write(s, (char *) &result, sizeof(result)); |
1710 | } | 1713 | } |
1711 | 1714 | ||
1712 | /* ARGSUSED */ | 1715 | /* ARGSUSED */ |
1713 | static void | 1716 | static void |
1714 | machtime_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1717 | machtime_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1715 | { | 1718 | { |
1716 | u_int result; | 1719 | u_int result; |
1717 | /* struct sockaddr_storage ss; */ | 1720 | /* struct sockaddr_storage ss; */ |
1718 | struct sockaddr sa; | 1721 | struct sockaddr sa; |
1719 | struct sockaddr_in *dg_sin; | 1722 | struct sockaddr_in *dg_sin; |
1720 | socklen_t size; | 1723 | socklen_t size; |
1721 | 1724 | ||
1722 | size = sizeof (sa); | 1725 | size = sizeof(sa); |
1723 | if (recvfrom (s, (char *) &result, sizeof (result), 0, &sa, &size) < 0) | 1726 | if (recvfrom(s, (char *) &result, sizeof(result), 0, &sa, &size) < 0) |
1724 | return; | 1727 | return; |
1725 | /* if (dg_badinput((struct sockaddr *)&ss)) */ | 1728 | /* if (dg_badinput((struct sockaddr *)&ss)) */ |
1726 | dg_sin = (struct sockaddr_in *) &sa; | 1729 | dg_sin = (struct sockaddr_in *) &sa; |
1727 | if (dg_sin->sin_addr.s_addr == htonl (INADDR_BROADCAST) || | 1730 | if (dg_sin->sin_addr.s_addr == htonl(INADDR_BROADCAST) || |
1728 | ntohs (dg_sin->sin_port) < IPPORT_RESERVED / 2) | 1731 | ntohs(dg_sin->sin_port) < IPPORT_RESERVED / 2) |
1729 | return; | 1732 | return; |
1730 | result = machtime (); | 1733 | result = machtime(); |
1731 | (void) sendto (s, (char *) &result, sizeof (result), 0, &sa, sizeof (sa)); | 1734 | (void) sendto(s, (char *) &result, sizeof(result), 0, &sa, sizeof(sa)); |
1732 | } | 1735 | } |
1733 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME */ | 1736 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_TIME */ |
1734 | 1737 | ||
@@ -1736,36 +1739,36 @@ machtime_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | |||
1736 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME | 1739 | #ifdef CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME |
1737 | /* Return human-readable time of day */ | 1740 | /* Return human-readable time of day */ |
1738 | /* ARGSUSED */ | 1741 | /* ARGSUSED */ |
1739 | static void daytime_stream (int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1742 | static void daytime_stream(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1740 | { | 1743 | { |
1741 | char buffer[256]; | 1744 | char buffer[256]; |
1742 | time_t t; | 1745 | time_t t; |
1743 | 1746 | ||
1744 | t = time (NULL); | 1747 | t = time(NULL); |
1745 | 1748 | ||
1746 | (void) sprintf (buffer, "%.24s\r\n", ctime (&t)); | 1749 | (void) sprintf(buffer, "%.24s\r\n", ctime(&t)); |
1747 | (void) write (s, buffer, strlen (buffer)); | 1750 | (void) write(s, buffer, strlen(buffer)); |
1748 | } | 1751 | } |
1749 | 1752 | ||
1750 | /* Return human-readable time of day */ | 1753 | /* Return human-readable time of day */ |
1751 | /* ARGSUSED */ | 1754 | /* ARGSUSED */ |
1752 | void | 1755 | void |
1753 | daytime_dg (int s, servtab_t *sep ATTRIBUTE_UNUSED) | 1756 | daytime_dg(int s, servtab_t *sep ATTRIBUTE_UNUSED) |
1754 | { | 1757 | { |
1755 | char buffer[256]; | 1758 | char buffer[256]; |
1756 | time_t t; | 1759 | time_t t; |
1757 | /* struct sockaddr_storage ss; */ | 1760 | /* struct sockaddr_storage ss; */ |
1758 | struct sockaddr sa; | 1761 | struct sockaddr sa; |
1759 | socklen_t size; | 1762 | socklen_t size; |
1760 | 1763 | ||
1761 | t = time ((time_t *) 0); | 1764 | t = time(NULL); |
1762 | 1765 | ||
1763 | size = sizeof (sa); | 1766 | size = sizeof(sa); |
1764 | if (recvfrom (s, buffer, sizeof (buffer), 0, &sa, &size) < 0) | 1767 | if (recvfrom(s, buffer, sizeof(buffer), 0, &sa, &size) < 0) |
1765 | return; | 1768 | return; |
1766 | if (dg_badinput ((struct sockaddr_in *) &sa)) | 1769 | if (dg_badinput((struct sockaddr_in *) &sa)) |
1767 | return; | 1770 | return; |
1768 | (void) sprintf (buffer, "%.24s\r\n", ctime (&t)); | 1771 | (void) sprintf(buffer, "%.24s\r\n", ctime(&t)); |
1769 | (void) sendto (s, buffer, strlen (buffer), 0, &sa, sizeof (sa)); | 1772 | (void) sendto(s, buffer, strlen(buffer), 0, &sa, sizeof(sa)); |
1770 | } | 1773 | } |
1771 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME */ | 1774 | #endif /* CONFIG_FEATURE_INETD_SUPPORT_BUILTIN_DAYTIME */ |