Bump version to 1.32.0
[oweals/busybox.git] / networking / nc_bloaty.c
index f01e862ae2b8f34910618f5babc0b4bf4c504a05..034e03d21f6c67c50110716af4d52eb3e9637f73 100644 (file)
@@ -175,9 +175,9 @@ enum {
        OPT_w = (1 << 5),
        OPT_l = (1 << 6) * ENABLE_NC_SERVER,
        OPT_k = (1 << 7) * ENABLE_NC_SERVER,
-       OPT_i = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
-       OPT_o = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
-       OPT_z = (1 << (9+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
+       OPT_i = (1 << (6+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
+       OPT_o = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
+       OPT_z = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
 };
 
 #define o_nflag   (option_mask32 & OPT_n)
@@ -198,8 +198,8 @@ enum {
 #define Debug(...) do { } while (0)
 #endif
 
-#define holler_error(...)  do { if (o_verbose) bb_error_msg(__VA_ARGS__); } while (0)
-#define holler_perror(...) do { if (o_verbose) bb_perror_msg(__VA_ARGS__); } while (0)
+#define holler_error(msg)  do { if (o_verbose) bb_simple_error_msg(msg); } while (0)
+#define holler_perror(msg) do { if (o_verbose) bb_simple_perror_msg(msg); } while (0)
 
 /* catch: no-brainer interrupt handler */
 static void catch(int sig)
@@ -361,10 +361,10 @@ static void dolisten(int is_persistent, char **proggie)
                        rr = recv_from_to(netfd, NULL, 0, MSG_PEEK, /*was bigbuf_net, BIGSIZ*/
                                &remend.u.sa, &ouraddr->u.sa, ouraddr->len);
                        if (rr < 0)
-                               bb_perror_msg_and_die("recvfrom");
+                               bb_simple_perror_msg_and_die("recvfrom");
                        unarm();
                } else
-                       bb_error_msg_and_die("timeout");
+                       bb_simple_error_msg_and_die("timeout");
 /* Now we learned *to which IP* peer has connected, and we want to anchor
 our socket on it, so that our outbound packets will have correct local IP.
 Unfortunately, bind() on already bound socket will fail now (EINVAL):
@@ -382,7 +382,7 @@ create new one, and bind() it. TODO */
                        remend.len = LSA_SIZEOF_SA;
                        rr = accept(netfd, &remend.u.sa, &remend.len);
                        if (rr < 0)
-                               bb_perror_msg_and_die("accept");
+                               bb_simple_perror_msg_and_die("accept");
                        if (themaddr) {
                                int sv_port, port, r;
 
@@ -409,7 +409,7 @@ create new one, and bind() it. TODO */
                        }
                        unarm();
                } else
-                       bb_error_msg_and_die("timeout");
+                       bb_simple_error_msg_and_die("timeout");
 
                if (is_persistent && proggie) {
                        /* -l -k -e PROG */
@@ -459,7 +459,7 @@ create new one, and bind() it. TODO */
         so I don't feel bad.
         The *real* question is why BFD sockets wasn't designed to allow listens for
         connections *from* specific hosts/ports, instead of requiring the caller to
-        accept the connection and then reject undesireable ones by closing.
+        accept the connection and then reject undesirable ones by closing.
         In other words, we need a TCP MSG_PEEK. */
        /* bbox: removed most of it */
                lcladdr = xmalloc_sockaddr2dotted(&ouraddr->u.sa);
@@ -494,7 +494,7 @@ static int udptest(void)
 
        rr = write(netfd, bigbuf_in, 1);
        if (rr != 1)
-               bb_perror_msg("udptest first write");
+               bb_simple_perror_msg("udptest first write");
 
        if (o_wait)
                sleep(o_wait); // can be interrupted! while (t) nanosleep(&t)?
@@ -502,7 +502,7 @@ static int udptest(void)
        /* use the tcp-ping trick: try connecting to a normally refused port, which
         causes us to block for the time that SYN gets there and RST gets back.
         Not completely reliable, but it *does* mostly work. */
-       /* Set a temporary connect timeout, so packet filtration doesnt cause
+       /* Set a temporary connect timeout, so packet filtration doesn't cause
         us to hang forever, and hit it */
                o_wait = 5;                     /* enough that we'll notice?? */
                rr = xsocket(ouraddr->u.sa.sa_family, SOCK_STREAM, 0);
@@ -582,85 +582,71 @@ void oprint(int direction, unsigned char *p, unsigned bc);
 #endif
 
 /* readwrite:
- handle stdin/stdout/network I/O.  Bwahaha!! -- the select loop from hell.
+ handle stdin/stdout/network I/O.  Bwahaha!! -- the i/o loop from hell.
  In this instance, return what might become our exit status. */
 static int readwrite(void)
 {
-       int rr;
        char *zp = zp; /* gcc */  /* stdin buf ptr */
        char *np = np;            /* net-in buf ptr */
        unsigned rzleft;
        unsigned rnleft;
        unsigned netretry;              /* net-read retry counter */
-       unsigned wretry;                /* net-write sanity counter */
-       unsigned wfirst;                /* one-shot flag to skip first net read */
        unsigned fds_open;
 
-       /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
-        either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
-       fd_set ding1;                   /* for select loop */
-       fd_set ding2;
-       FD_ZERO(&ding1);
-       FD_SET(netfd, &ding1);
-       FD_SET(STDIN_FILENO, &ding1);
-       fds_open = 2;
+       struct pollfd pfds[2];
+       pfds[0].fd = STDIN_FILENO;
+       pfds[0].events = POLLIN;
+       pfds[1].fd = netfd;
+       pfds[1].events = POLLIN;
 
+       fds_open = 2;
        netretry = 2;
-       wfirst = 0;
        rzleft = rnleft = 0;
        if (o_interval)
                sleep(o_interval);                /* pause *before* sending stuff, too */
 
-       errno = 0;                        /* clear from sleep, close, whatever */
-       /* and now the big ol' select shoveling loop ... */
+       /* and now the big ol' shoveling loop ... */
        /* nc 1.10 has "while (FD_ISSET(netfd)" here */
        while (fds_open) {
-               wretry = 8200;                        /* more than we'll ever hafta write */
-               if (wfirst) {                        /* any saved stdin buffer? */
-                       wfirst = 0;                        /* clear flag for the duration */
-                       goto shovel;                        /* and go handle it first */
-               }
-               ding2 = ding1;                        /* FD_COPY ain't portable... */
-       /* some systems, notably linux, crap into their select timers on return, so
-        we create a expendable copy and give *that* to select.  */
+               int rr;
+               int poll_tmout_ms;
+               unsigned wretry = 8200;               /* net-write sanity counter */
+
+               poll_tmout_ms = -1;
                if (o_wait) {
-                       struct timeval tmp_timer;
-                       tmp_timer.tv_sec = o_wait;
-                       tmp_timer.tv_usec = 0;
-               /* highest possible fd is netfd (3) */
-                       rr = select(netfd+1, &ding2, NULL, NULL, &tmp_timer);
-               } else
-                       rr = select(netfd+1, &ding2, NULL, NULL, NULL);
+                       poll_tmout_ms = INT_MAX;
+                       if (o_wait < INT_MAX / 1000)
+                               poll_tmout_ms = o_wait * 1000;
+               }
+               rr = poll(pfds, 2, poll_tmout_ms);
                if (rr < 0 && errno != EINTR) {                /* might have gotten ^Zed, etc */
-                       holler_perror("select");
+                       holler_perror("poll");
                        close(netfd);
                        return 1;
                }
        /* if we have a timeout AND stdin is closed AND we haven't heard anything
         from the net during that time, assume it's dead and close it too. */
                if (rr == 0) {
-                       if (!FD_ISSET(STDIN_FILENO, &ding1)) {
+                       if (!pfds[0].revents) {
                                netretry--;                        /* we actually try a coupla times. */
                                if (!netretry) {
                                        if (o_verbose > 1)         /* normally we don't care */
                                                fprintf(stderr, "net timeout\n");
-                                       close(netfd);
+                                       /*close(netfd); - redundant, exit will do it */
                                        return 0;                  /* not an error! */
                                }
                        }
-               } /* select timeout */
-       /* xxx: should we check the exception fds too?  The read fds seem to give
-        us the right info, and none of the examples I found bothered. */
+               } /* timeout */
 
        /* Ding!!  Something arrived, go check all the incoming hoppers, net first */
-               if (FD_ISSET(netfd, &ding2)) {                /* net: ding! */
+               if (pfds[1].revents) {                /* net: ding! */
                        rr = read(netfd, bigbuf_net, BIGSIZ);
                        if (rr <= 0) {
                                if (rr < 0 && o_verbose > 1) {
                                        /* nc 1.10 doesn't do this */
-                                       bb_perror_msg("net read");
+                                       bb_simple_perror_msg("net read");
                                }
-                               FD_CLR(netfd, &ding1);                /* net closed */
+                               pfds[1].fd = -1;                   /* don't poll for netfd anymore */
                                fds_open--;
                                rzleft = 0;                        /* can't write anymore: broken pipe */
                        } else {
@@ -676,13 +662,13 @@ Debug("got %d from the net, errno %d", rr, errno);
                        goto shovel;
 
        /* okay, suck more stdin */
-               if (FD_ISSET(STDIN_FILENO, &ding2)) {                /* stdin: ding! */
+               if (pfds[0].revents) {                /* stdin: ding! */
                        rr = read(STDIN_FILENO, bigbuf_in, BIGSIZ);
        /* Considered making reads here smaller for UDP mode, but 8192-byte
         mobygrams are kinda fun and exercise the reassembler. */
                        if (rr <= 0) {                        /* at end, or fukt, or ... */
-                               FD_CLR(STDIN_FILENO, &ding1);                /* disable and close stdin */
-                               close(STDIN_FILENO);
+                               pfds[0].fd = -1;              /* disable stdin */
+                               /*close(STDIN_FILENO); - not really necessary */
                                /* Let peer know we have no more data */
                                /* nc 1.10 doesn't do this: */
                                shutdown(netfd, SHUT_WR);
@@ -697,24 +683,14 @@ Debug("got %d from the net, errno %d", rr, errno);
         Geez, why does this look an awful lot like the big loop in "rsh"? ...
         not sure if the order of this matters, but write net -> stdout first. */
 
-       /* sanity check.  Works because they're both unsigned... */
-               if ((rzleft > 8200) || (rnleft > 8200)) {
-                       holler_error("bogus buffers: %u, %u", rzleft, rnleft);
-                       rzleft = rnleft = 0;
-               }
-       /* net write retries sometimes happen on UDP connections */
-               if (!wretry) {                        /* is something hung? */
-                       holler_error("too many output retries");
-                       return 1;
-               }
                if (rnleft) {
                        rr = write(STDOUT_FILENO, np, rnleft);
                        if (rr > 0) {
                                if (o_ofile) /* log the stdout */
                                        oprint('<', (unsigned char *)np, rr);
-                               np += rr;                        /* fix up ptrs and whatnot */
-                               rnleft -= rr;                        /* will get sanity-checked above */
-                               wrote_out += rr;                /* global count */
+                               np += rr;
+                               rnleft -= rr;
+                               wrote_out += rr; /* global count */
                        }
 Debug("wrote %d to stdout, errno %d", rr, errno);
                } /* rnleft */
@@ -729,20 +705,24 @@ Debug("wrote %d to stdout, errno %d", rr, errno);
                                        oprint('>', (unsigned char *)zp, rr);
                                zp += rr;
                                rzleft -= rr;
-                               wrote_net += rr;                /* global count */
+                               wrote_net += rr; /* global count */
                        }
 Debug("wrote %d to net, errno %d", rr, errno);
                } /* rzleft */
                if (o_interval) {                        /* cycle between slow lines, or ... */
                        sleep(o_interval);
-                       errno = 0;                        /* clear from sleep */
-                       continue;                        /* ...with hairy select loop... */
+                       continue;                        /* ...with hairy loop... */
                }
                if (rzleft || rnleft) {                  /* shovel that shit till they ain't */
                        wretry--;                        /* none left, and get another load */
+       /* net write retries sometimes happen on UDP connections */
+                       if (!wretry) {                   /* is something hung? */
+                               holler_error("too many output retries");
+                               return 1;
+                       }
                        goto shovel;
                }
-       } /* while ding1:netfd is open */
+       } /* while (fds_open) */
 
        /* XXX: maybe want a more graceful shutdown() here, or screw around with
         linger times??  I suspect that I don't need to since I'm always doing
@@ -807,11 +787,15 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
  e_found:
 
        // -g -G -t -r deleted, unimplemented -a deleted too
-       opt_complementary = "?2:vv:ll:w+"; /* max 2 params; -v and -l are counters; -w N */
-       getopt32(argv, "np:s:uvw:" IF_NC_SERVER("lk")
-                       IF_NC_EXTRA("i:o:z"),
-                       &str_p, &str_s, &o_wait
-                       IF_NC_EXTRA(, &str_i, &str_o), &o_verbose IF_NC_SERVER(, &cnt_l));
+       getopt32(argv, "^"
+               "np:s:uvw:+"/* -w N */ IF_NC_SERVER("lk")
+               IF_NC_EXTRA("i:o:z")
+                       "\0"
+                       "?2:vv"IF_NC_SERVER(":ll"), /* max 2 params; -v and -l are counters */
+               &str_p, &str_s, &o_wait
+               IF_NC_EXTRA(, &str_i, &str_o)
+                       , &o_verbose IF_NC_SERVER(, &cnt_l)
+       );
        argv += optind;
 #if ENABLE_NC_EXTRA
        if (option_mask32 & OPT_i) /* line-interval time */
@@ -876,8 +860,8 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
                xbind(netfd, &ouraddr->u.sa, ouraddr->len);
        }
 #if 0
-       setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
-       setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
+       setsockopt_SOL_SOCKET_int(netfd, SO_RCVBUF, o_rcvbuf);
+       setsockopt_SOL_SOCKET_int(netfd, SO_SNDBUF, o_sndbuf);
 #endif
 
 #ifdef BLOAT
@@ -885,7 +869,7 @@ int nc_main(int argc UNUSED_PARAM, char **argv)
                /* apparently UDP can listen ON "port 0",
                 but that's not useful */
                if (!o_lport)
-                       bb_error_msg_and_die("UDP listen needs nonzero -p port");
+                       bb_simple_error_msg_and_die("UDP listen needs nonzero -p port");
        }
 #endif