aboutsummaryrefslogtreecommitdiff
path: root/networking/telnetd.c
diff options
context:
space:
mode:
authorDenys Vlasenko <vda.linux@googlemail.com>2009-09-04 02:21:13 +0200
committerDenys Vlasenko <vda.linux@googlemail.com>2009-09-04 02:21:13 +0200
commited1667e8ee91243b77b02cc4f160fe4b80a30385 (patch)
tree54520fc2069e9f8f21a8fad0cfc1de163b5d4017 /networking/telnetd.c
parentcfc216345e18081cba9ac3ed0464abf5d7f40cea (diff)
downloadbusybox-w32-ed1667e8ee91243b77b02cc4f160fe4b80a30385.tar.gz
busybox-w32-ed1667e8ee91243b77b02cc4f160fe4b80a30385.tar.bz2
busybox-w32-ed1667e8ee91243b77b02cc4f160fe4b80a30385.zip
telnetd: add -w ("inetd wait") option. Can be configured off.
gcc fils to fully optimize it out when it's off: function old new delta telnetd_main 1527 1548 +21 packed_usage 26596 26587 -9 but nevertheless it's a useful (and so far single) example how to write "inetd wait" tcp service. Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to '')
-rw-r--r--networking/telnetd.c56
1 files changed, 36 insertions, 20 deletions
diff --git a/networking/telnetd.c b/networking/telnetd.c
index 540387f1a..2a0ace5cb 100644
--- a/networking/telnetd.c
+++ b/networking/telnetd.c
@@ -211,8 +211,10 @@ static size_t iac_safe_write(int fd, const char *buf, size_t count)
211enum { 211enum {
212 OPT_WATCHCHILD = (1 << 2), /* -K */ 212 OPT_WATCHCHILD = (1 << 2), /* -K */
213 OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */ 213 OPT_INETD = (1 << 3) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -i */
214 OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p */ 214 OPT_PORT = (1 << 4) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -p PORT */
215 OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */ 215 OPT_FOREGROUND = (1 << 6) * ENABLE_FEATURE_TELNETD_STANDALONE, /* -F */
216 OPT_SYSLOG = (1 << 7) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -S */
217 OPT_WAIT = (1 << 8) * ENABLE_FEATURE_TELNETD_INETD_WAIT, /* -w SEC */
216}; 218};
217 219
218static struct tsession * 220static struct tsession *
@@ -438,24 +440,29 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv)
438 struct tsession *ts; 440 struct tsession *ts;
439#if ENABLE_FEATURE_TELNETD_STANDALONE 441#if ENABLE_FEATURE_TELNETD_STANDALONE
440#define IS_INETD (opt & OPT_INETD) 442#define IS_INETD (opt & OPT_INETD)
441 int master_fd = master_fd; /* be happy, gcc */ 443 int master_fd = master_fd; /* for compiler */
442 unsigned portnbr = 23; 444 int sec_linger = sec_linger;
443 char *opt_bindaddr = NULL; 445 char *opt_bindaddr = NULL;
444 char *opt_portnbr; 446 char *opt_portnbr;
445#else 447#else
446 enum { 448 enum {
447 IS_INETD = 1, 449 IS_INETD = 1,
448 master_fd = -1, 450 master_fd = -1,
449 portnbr = 23,
450 }; 451 };
451#endif 452#endif
452 INIT_G(); 453 INIT_G();
453 454
455 /* -w NUM, and implies -F. -w and -i don't mix */
456 IF_FEATURE_TELNETD_INETD_WAIT(opt_complementary = "wF:w+:i--w:w--i";)
454 /* Even if !STANDALONE, we accept (and ignore) -i, thus people 457 /* Even if !STANDALONE, we accept (and ignore) -i, thus people
455 * don't need to guess whether it's ok to pass -i to us */ 458 * don't need to guess whether it's ok to pass -i to us */
456 opt = getopt32(argv, "f:l:Ki" IF_FEATURE_TELNETD_STANDALONE("p:b:F"), 459 opt = getopt32(argv, "f:l:Ki"
460 IF_FEATURE_TELNETD_STANDALONE("p:b:F")
461 IF_FEATURE_TELNETD_INETD_WAIT("Sw:"),
457 &G.issuefile, &G.loginpath 462 &G.issuefile, &G.loginpath
458 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr)); 463 IF_FEATURE_TELNETD_STANDALONE(, &opt_portnbr, &opt_bindaddr)
464 IF_FEATURE_TELNETD_INETD_WAIT(, &sec_linger)
465 );
459 if (!IS_INETD /*&& !re_execed*/) { 466 if (!IS_INETD /*&& !re_execed*/) {
460 /* inform that we start in standalone mode? 467 /* inform that we start in standalone mode?
461 * May be useful when people forget to give -i */ 468 * May be useful when people forget to give -i */
@@ -467,32 +474,30 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv)
467 } 474 }
468 } 475 }
469 /* Redirect log to syslog early, if needed */ 476 /* Redirect log to syslog early, if needed */
470 if (IS_INETD || !(opt & OPT_FOREGROUND)) { 477 if (IS_INETD || (opt & OPT_SYSLOG) || !(opt & OPT_FOREGROUND)) {
471 openlog(applet_name, LOG_PID, LOG_DAEMON); 478 openlog(applet_name, LOG_PID, LOG_DAEMON);
472 logmode = LOGMODE_SYSLOG; 479 logmode = LOGMODE_SYSLOG;
473 } 480 }
474 IF_FEATURE_TELNETD_STANDALONE(
475 if (opt & OPT_PORT)
476 portnbr = xatou16(opt_portnbr);
477 );
478
479 /* Used to check access(G.loginpath, X_OK) here. Pointless.
480 * exec will do this for us for free later. */
481
482#if ENABLE_FEATURE_TELNETD_STANDALONE 481#if ENABLE_FEATURE_TELNETD_STANDALONE
483 if (IS_INETD) { 482 if (IS_INETD) {
484 G.sessions = make_new_session(0); 483 G.sessions = make_new_session(0);
485 if (!G.sessions) /* pty opening or vfork problem, exit */ 484 if (!G.sessions) /* pty opening or vfork problem, exit */
486 return 1; /* make_new_session prints error message */ 485 return 1; /* make_new_session printed error message */
487 } else { 486 } else {
488 master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr); 487 master_fd = 0;
489 xlisten(master_fd, 1); 488 if (!(opt & OPT_WAIT)) {
489 unsigned portnbr = 23;
490 if (opt & OPT_PORT)
491 portnbr = xatou16(opt_portnbr);
492 master_fd = create_and_bind_stream_or_die(opt_bindaddr, portnbr);
493 xlisten(master_fd, 1);
494 }
490 close_on_exec_on(master_fd); 495 close_on_exec_on(master_fd);
491 } 496 }
492#else 497#else
493 G.sessions = make_new_session(); 498 G.sessions = make_new_session();
494 if (!G.sessions) /* pty opening or vfork problem, exit */ 499 if (!G.sessions) /* pty opening or vfork problem, exit */
495 return 1; /* make_new_session prints error message */ 500 return 1; /* make_new_session printed error message */
496#endif 501#endif
497 502
498 /* We don't want to die if just one session is broken */ 503 /* We don't want to die if just one session is broken */
@@ -556,7 +561,18 @@ int telnetd_main(int argc UNUSED_PARAM, char **argv)
556 G.maxfd = master_fd; 561 G.maxfd = master_fd;
557 } 562 }
558 563
559 count = select(G.maxfd + 1, &rdfdset, &wrfdset, NULL, NULL); 564 {
565 struct timeval tv;
566 struct timeval *tv_ptr = NULL;
567 if ((opt & OPT_WAIT) && !G.sessions) {
568 tv.tv_sec = sec_linger;
569 tv.tv_usec = 0;
570 tv_ptr = &tv;
571 }
572 count = select(G.maxfd + 1, &rdfdset, &wrfdset, NULL, tv_ptr);
573 }
574 if (count == 0) /* "telnetd -w SEC" timed out */
575 return 0;
560 if (count < 0) 576 if (count < 0)
561 goto again; /* EINTR or ENOMEM */ 577 goto again; /* EINTR or ENOMEM */
562 578