nc: fix nc -ll; report vfork errors; make select loop faster

function                                             old     new   delta
nc_main                                              933     946     +13

Signed-off-by: Tomoya Adachi <adachi@il.is.s.u-tokyo.ac.jp>
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
This commit is contained in:
Tomoya Adachi 2009-08-03 02:59:22 +02:00 committed by Denys Vlasenko
parent dc9495df03
commit 63416cc57d

View File

@ -135,29 +135,27 @@ int nc_main(int argc, char **argv)
/* -e given? */ /* -e given? */
if (execparam) { if (execparam) {
signal(SIGCHLD, SIG_IGN); pid_t pid;
// With more than one -l, repeatedly act as server. /* With more than one -l, repeatedly act as server */
if (do_listen > 1 && vfork()) { if (do_listen > 1 && (pid = vfork()) != 0) {
/* parent */ /* parent or error */
// This is a bit weird as cleanup goes, since we wind up with no if (pid < 0)
// stdin/stdout/stderr. But it's small and shouldn't hurt anything. bb_perror_msg_and_die("vfork");
// We check for cfd == 0 above. /* prevent zombies */
logmode = LOGMODE_NONE; signal(SIGCHLD, SIG_IGN);
close(0); close(cfd);
close(1);
close(2);
goto accept_again; goto accept_again;
} }
/* child (or main thread if no multiple -l) */ /* child, or main thread if only one -l */
xmove_fd(cfd, 0); xmove_fd(cfd, 0);
xdup2(0, 1); xdup2(0, 1);
xdup2(0, 2); xdup2(0, 2);
IF_NC_EXTRA(BB_EXECVP(execparam[0], execparam);) IF_NC_EXTRA(BB_EXECVP(execparam[0], execparam);)
/* Don't print stuff or it will go over the wire.... */ /* Don't print stuff or it will go over the wire... */
_exit(127); _exit(127);
} }
// Select loop copying stdin to cfd, and cfd to stdout. /* Select loop copying stdin to cfd, and cfd to stdout */
FD_ZERO(&readfds); FD_ZERO(&readfds);
FD_SET(cfd, &readfds); FD_SET(cfd, &readfds);
@ -170,11 +168,12 @@ int nc_main(int argc, char **argv)
testfds = readfds; testfds = readfds;
if (select(FD_SETSIZE, &testfds, NULL, NULL, NULL) < 0) if (select(cfd + 1, &testfds, NULL, NULL, NULL) < 0)
bb_perror_msg_and_die("select"); bb_perror_msg_and_die("select");
#define iobuf bb_common_bufsiz1 #define iobuf bb_common_bufsiz1
for (fd = 0; fd < FD_SETSIZE; fd++) { fd = STDIN_FILENO;
while (1) {
if (FD_ISSET(fd, &testfds)) { if (FD_ISSET(fd, &testfds)) {
nread = safe_read(fd, iobuf, sizeof(iobuf)); nread = safe_read(fd, iobuf, sizeof(iobuf));
if (fd == cfd) { if (fd == cfd) {
@ -182,17 +181,21 @@ int nc_main(int argc, char **argv)
exit(EXIT_SUCCESS); exit(EXIT_SUCCESS);
ofd = STDOUT_FILENO; ofd = STDOUT_FILENO;
} else { } else {
if (nread<1) { if (nread < 1) {
// Close outgoing half-connection so they get EOF, but /* Close outgoing half-connection so they get EOF,
// leave incoming alone so we can see response. * but leave incoming alone so we can see response */
shutdown(cfd, 1); shutdown(cfd, 1);
FD_CLR(STDIN_FILENO, &readfds); FD_CLR(STDIN_FILENO, &readfds);
} }
ofd = cfd; ofd = cfd;
} }
xwrite(ofd, iobuf, nread); xwrite(ofd, iobuf, nread);
if (delay > 0) sleep(delay); if (delay > 0)
sleep(delay);
} }
if (fd == cfd)
break;
fd = cfd;
} }
} }
} }