diff options
author | Denys Vlasenko <vda.linux@googlemail.com> | 2013-07-28 22:23:12 +0200 |
---|---|---|
committer | Denys Vlasenko <vda.linux@googlemail.com> | 2013-07-28 22:23:12 +0200 |
commit | ffeeb7a96c74f1f001495c2311526681e2271a77 (patch) | |
tree | 72ebc9e50c877f83069fea5cc12633a860dc9c3b /networking/nc_bloaty.c | |
parent | ca54b662e7a058a1f687da2eac6752590a9ed2ee (diff) | |
download | busybox-w32-ffeeb7a96c74f1f001495c2311526681e2271a77.tar.gz busybox-w32-ffeeb7a96c74f1f001495c2311526681e2271a77.tar.bz2 busybox-w32-ffeeb7a96c74f1f001495c2311526681e2271a77.zip |
nc: exit when both stdin and network are closed.
function old new delta
nc_main 1051 1042 -9
readwrite 943 887 -56
Signed-off-by: Denys Vlasenko <vda.linux@googlemail.com>
Diffstat (limited to 'networking/nc_bloaty.c')
-rw-r--r-- | networking/nc_bloaty.c | 50 |
1 files changed, 31 insertions, 19 deletions
diff --git a/networking/nc_bloaty.c b/networking/nc_bloaty.c index 00ba6f114..f01e862ae 100644 --- a/networking/nc_bloaty.c +++ b/networking/nc_bloaty.c | |||
@@ -48,6 +48,12 @@ | |||
48 | * - TCP connects from wrong ip/ports (if peer ip:port is specified | 48 | * - TCP connects from wrong ip/ports (if peer ip:port is specified |
49 | * on the command line, but accept() says that it came from different addr) | 49 | * on the command line, but accept() says that it came from different addr) |
50 | * are closed, but we don't exit - we continue to listen/accept. | 50 | * are closed, but we don't exit - we continue to listen/accept. |
51 | * Since bbox 1.22: | ||
52 | * - nc exits when _both_ stdin and network are closed. | ||
53 | * This makes these two commands: | ||
54 | * echo "Yes" | nc 127.0.0.1 1234 | ||
55 | * echo "no" | nc -lp 1234 | ||
56 | * exchange their data _and exit_ instead of being stuck. | ||
51 | */ | 57 | */ |
52 | 58 | ||
53 | /* done in nc.c: #include "libbb.h" */ | 59 | /* done in nc.c: #include "libbb.h" */ |
@@ -134,8 +140,6 @@ struct globals { | |||
134 | 140 | ||
135 | jmp_buf jbuf; /* timer crud */ | 141 | jmp_buf jbuf; /* timer crud */ |
136 | 142 | ||
137 | fd_set ding1; /* for select loop */ | ||
138 | fd_set ding2; | ||
139 | char bigbuf_in[BIGSIZ]; /* data buffers */ | 143 | char bigbuf_in[BIGSIZ]; /* data buffers */ |
140 | char bigbuf_net[BIGSIZ]; | 144 | char bigbuf_net[BIGSIZ]; |
141 | }; | 145 | }; |
@@ -147,8 +151,6 @@ struct globals { | |||
147 | #define themaddr (G.themaddr ) | 151 | #define themaddr (G.themaddr ) |
148 | #define remend (G.remend ) | 152 | #define remend (G.remend ) |
149 | #define jbuf (G.jbuf ) | 153 | #define jbuf (G.jbuf ) |
150 | #define ding1 (G.ding1 ) | ||
151 | #define ding2 (G.ding2 ) | ||
152 | #define bigbuf_in (G.bigbuf_in ) | 154 | #define bigbuf_in (G.bigbuf_in ) |
153 | #define bigbuf_net (G.bigbuf_net) | 155 | #define bigbuf_net (G.bigbuf_net) |
154 | #define o_verbose (G.o_verbose ) | 156 | #define o_verbose (G.o_verbose ) |
@@ -592,10 +594,17 @@ static int readwrite(void) | |||
592 | unsigned netretry; /* net-read retry counter */ | 594 | unsigned netretry; /* net-read retry counter */ |
593 | unsigned wretry; /* net-write sanity counter */ | 595 | unsigned wretry; /* net-write sanity counter */ |
594 | unsigned wfirst; /* one-shot flag to skip first net read */ | 596 | unsigned wfirst; /* one-shot flag to skip first net read */ |
597 | unsigned fds_open; | ||
595 | 598 | ||
596 | /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to | 599 | /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to |
597 | either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */ | 600 | either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */ |
598 | FD_SET(netfd, &ding1); /* global: the net is open */ | 601 | fd_set ding1; /* for select loop */ |
602 | fd_set ding2; | ||
603 | FD_ZERO(&ding1); | ||
604 | FD_SET(netfd, &ding1); | ||
605 | FD_SET(STDIN_FILENO, &ding1); | ||
606 | fds_open = 2; | ||
607 | |||
599 | netretry = 2; | 608 | netretry = 2; |
600 | wfirst = 0; | 609 | wfirst = 0; |
601 | rzleft = rnleft = 0; | 610 | rzleft = rnleft = 0; |
@@ -604,7 +613,8 @@ static int readwrite(void) | |||
604 | 613 | ||
605 | errno = 0; /* clear from sleep, close, whatever */ | 614 | errno = 0; /* clear from sleep, close, whatever */ |
606 | /* and now the big ol' select shoveling loop ... */ | 615 | /* and now the big ol' select shoveling loop ... */ |
607 | while (FD_ISSET(netfd, &ding1)) { /* i.e. till the *net* closes! */ | 616 | /* nc 1.10 has "while (FD_ISSET(netfd)" here */ |
617 | while (fds_open) { | ||
608 | wretry = 8200; /* more than we'll ever hafta write */ | 618 | wretry = 8200; /* more than we'll ever hafta write */ |
609 | if (wfirst) { /* any saved stdin buffer? */ | 619 | if (wfirst) { /* any saved stdin buffer? */ |
610 | wfirst = 0; /* clear flag for the duration */ | 620 | wfirst = 0; /* clear flag for the duration */ |
@@ -629,13 +639,14 @@ static int readwrite(void) | |||
629 | /* if we have a timeout AND stdin is closed AND we haven't heard anything | 639 | /* if we have a timeout AND stdin is closed AND we haven't heard anything |
630 | from the net during that time, assume it's dead and close it too. */ | 640 | from the net during that time, assume it's dead and close it too. */ |
631 | if (rr == 0) { | 641 | if (rr == 0) { |
632 | if (!FD_ISSET(STDIN_FILENO, &ding1)) | 642 | if (!FD_ISSET(STDIN_FILENO, &ding1)) { |
633 | netretry--; /* we actually try a coupla times. */ | 643 | netretry--; /* we actually try a coupla times. */ |
634 | if (!netretry) { | 644 | if (!netretry) { |
635 | if (o_verbose > 1) /* normally we don't care */ | 645 | if (o_verbose > 1) /* normally we don't care */ |
636 | fprintf(stderr, "net timeout\n"); | 646 | fprintf(stderr, "net timeout\n"); |
637 | close(netfd); | 647 | close(netfd); |
638 | return 0; /* not an error! */ | 648 | return 0; /* not an error! */ |
649 | } | ||
639 | } | 650 | } |
640 | } /* select timeout */ | 651 | } /* select timeout */ |
641 | /* xxx: should we check the exception fds too? The read fds seem to give | 652 | /* xxx: should we check the exception fds too? The read fds seem to give |
@@ -649,7 +660,8 @@ static int readwrite(void) | |||
649 | /* nc 1.10 doesn't do this */ | 660 | /* nc 1.10 doesn't do this */ |
650 | bb_perror_msg("net read"); | 661 | bb_perror_msg("net read"); |
651 | } | 662 | } |
652 | FD_CLR(netfd, &ding1); /* net closed, we'll finish up... */ | 663 | FD_CLR(netfd, &ding1); /* net closed */ |
664 | fds_open--; | ||
653 | rzleft = 0; /* can't write anymore: broken pipe */ | 665 | rzleft = 0; /* can't write anymore: broken pipe */ |
654 | } else { | 666 | } else { |
655 | rnleft = rr; | 667 | rnleft = rr; |
@@ -671,9 +683,10 @@ Debug("got %d from the net, errno %d", rr, errno); | |||
671 | if (rr <= 0) { /* at end, or fukt, or ... */ | 683 | if (rr <= 0) { /* at end, or fukt, or ... */ |
672 | FD_CLR(STDIN_FILENO, &ding1); /* disable and close stdin */ | 684 | FD_CLR(STDIN_FILENO, &ding1); /* disable and close stdin */ |
673 | close(STDIN_FILENO); | 685 | close(STDIN_FILENO); |
674 | // Does it make sense to shutdown(net_fd, SHUT_WR) | 686 | /* Let peer know we have no more data */ |
675 | // to let other side know that we won't write anything anymore? | 687 | /* nc 1.10 doesn't do this: */ |
676 | // (and what about keeping compat if we do that?) | 688 | shutdown(netfd, SHUT_WR); |
689 | fds_open--; | ||
677 | } else { | 690 | } else { |
678 | rzleft = rr; | 691 | rzleft = rr; |
679 | zp = bigbuf_in; | 692 | zp = bigbuf_in; |
@@ -725,7 +738,7 @@ Debug("wrote %d to net, errno %d", rr, errno); | |||
725 | errno = 0; /* clear from sleep */ | 738 | errno = 0; /* clear from sleep */ |
726 | continue; /* ...with hairy select loop... */ | 739 | continue; /* ...with hairy select loop... */ |
727 | } | 740 | } |
728 | if ((rzleft) || (rnleft)) { /* shovel that shit till they ain't */ | 741 | if (rzleft || rnleft) { /* shovel that shit till they ain't */ |
729 | wretry--; /* none left, and get another load */ | 742 | wretry--; /* none left, and get another load */ |
730 | goto shovel; | 743 | goto shovel; |
731 | } | 744 | } |
@@ -876,9 +889,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv) | |||
876 | } | 889 | } |
877 | #endif | 890 | #endif |
878 | 891 | ||
879 | FD_SET(STDIN_FILENO, &ding1); /* stdin *is* initially open */ | ||
880 | if (proggie) { | 892 | if (proggie) { |
881 | close(0); /* won't need stdin */ | 893 | close(STDIN_FILENO); /* won't need stdin */ |
882 | option_mask32 &= ~OPT_o; /* -o with -e is meaningless! */ | 894 | option_mask32 &= ~OPT_o; /* -o with -e is meaningless! */ |
883 | } | 895 | } |
884 | #if ENABLE_NC_EXTRA | 896 | #if ENABLE_NC_EXTRA |