Ignore:
Timestamp:
Dec 20, 2016, 4:07:32 PM (7 years ago)
Author:
Bruno Cornec
Message:

New 3?3 banch for incorporation of latest busybox 1.25. Changing minor version to handle potential incompatibilities.

Location:
branches/3.3
Files:
1 edited
1 copied

Legend:

Unmodified
Added
Removed
  • branches/3.3/mindi-busybox/networking/nc_bloaty.c

    r3232 r3621  
    4949 *   on the command line, but accept() says that it came from different addr)
    5050 *   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.
    5157 */
    5258
     
    6470//usage:    IF_NC_SERVER(
    6571//usage:     "\n    -l  Listen mode, for inbound connects"
     72//usage:     "\n    -lk With -e, provides persistent server"
     73/* -ll does the same as -lk, but its our extension, while -k is BSD'd,
     74 * presumably more widely known. Therefore we advertise it, not -ll.
     75 * I would like to drop -ll support, but our "small" nc supports it,
     76 * and Rob uses it.
     77 */
    6678//usage:    )
    6779//usage:     "\n    -p PORT Local port"
     
    129141    jmp_buf jbuf;                /* timer crud */
    130142
    131     fd_set ding1;                /* for select loop */
    132     fd_set ding2;
    133143    char bigbuf_in[BIGSIZ];      /* data buffers */
    134144    char bigbuf_net[BIGSIZ];
     
    142152#define remend     (G.remend    )
    143153#define jbuf       (G.jbuf      )
    144 #define ding1      (G.ding1     )
    145 #define ding2      (G.ding2     )
    146154#define bigbuf_in  (G.bigbuf_in )
    147155#define bigbuf_net (G.bigbuf_net)
     
    167175    OPT_w = (1 << 5),
    168176    OPT_l = (1 << 6) * ENABLE_NC_SERVER,
    169     OPT_i = (1 << (6+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
    170     OPT_o = (1 << (7+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
    171     OPT_z = (1 << (8+ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     177    OPT_k = (1 << 7) * ENABLE_NC_SERVER,
     178    OPT_i = (1 << (6+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     179    OPT_o = (1 << (7+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
     180    OPT_z = (1 << (8+2*ENABLE_NC_SERVER)) * ENABLE_NC_EXTRA,
    172181};
    173182
    174183#define o_nflag   (option_mask32 & OPT_n)
    175184#define o_udpmode (option_mask32 & OPT_u)
    176 #if ENABLE_NC_SERVER
    177 #define o_listen  (option_mask32 & OPT_l)
    178 #else
    179 #define o_listen  0
    180 #endif
    181185#if ENABLE_NC_EXTRA
    182186#define o_ofile   (option_mask32 & OPT_o)
     
    299303 given host/port args, any connections from elsewhere are rejected.  This
    300304 in conjunction with local-address binding should limit things nicely... */
    301 static void dolisten(void)
     305static void dolisten(int is_persistent, char **proggie)
    302306{
    303307    int rr;
     
    372376    } else {
    373377        /* TCP */
     378 another:
    374379        arm(o_wait); /* wrap this in a timer, too; 0 = forever */
    375380        if (setjmp(jbuf) == 0) {
     
    406411        } else
    407412            bb_error_msg_and_die("timeout");
     413
     414        if (is_persistent && proggie) {
     415            /* -l -k -e PROG */
     416            signal(SIGCHLD, SIG_IGN); /* no zombies please */
     417            if (xvfork() != 0) {
     418                /* parent: go back and accept more connections */
     419                close(rr);
     420                goto another;
     421            }
     422            /* child */
     423            signal(SIGCHLD, SIG_DFL);
     424        }
     425
    408426        xmove_fd(rr, netfd); /* dump the old socket, here's our new one */
    409427        /* find out what address the connection was *to* on our end, in case we're
     
    455473            free(remhostname);
    456474    }
     475
     476    if (proggie)
     477        doexec(proggie);
    457478}
    458479
     
    572593    unsigned rnleft;
    573594    unsigned netretry;              /* net-read retry counter */
    574     unsigned wretry;                /* net-write sanity counter */
    575     unsigned wfirst;                /* one-shot flag to skip first net read */
     595    unsigned fds_open;
    576596
    577597    /* if you don't have all this FD_* macro hair in sys/types.h, you'll have to
    578598     either find it or do your own bit-bashing: *ding1 |= (1 << fd), etc... */
    579     FD_SET(netfd, &ding1);                /* global: the net is open */
     599    fd_set ding1;                   /* for select loop */
     600    fd_set ding2;
     601    FD_ZERO(&ding1);
     602    FD_SET(netfd, &ding1);
     603    FD_SET(STDIN_FILENO, &ding1);
     604    fds_open = 2;
     605
    580606    netretry = 2;
    581     wfirst = 0;
    582607    rzleft = rnleft = 0;
    583608    if (o_interval)
    584609        sleep(o_interval);                /* pause *before* sending stuff, too */
    585610
    586     errno = 0;                        /* clear from sleep, close, whatever */
    587611    /* and now the big ol' select shoveling loop ... */
    588     while (FD_ISSET(netfd, &ding1)) {        /* i.e. till the *net* closes! */
    589         wretry = 8200;                        /* more than we'll ever hafta write */
    590         if (wfirst) {                        /* any saved stdin buffer? */
    591             wfirst = 0;                        /* clear flag for the duration */
    592             goto shovel;                        /* and go handle it first */
    593         }
     612    /* nc 1.10 has "while (FD_ISSET(netfd)" here */
     613    while (fds_open) {
     614        unsigned wretry = 8200;               /* net-write sanity counter */
     615
    594616        ding2 = ding1;                        /* FD_COPY ain't portable... */
    595617    /* some systems, notably linux, crap into their select timers on return, so
     
    611633     from the net during that time, assume it's dead and close it too. */
    612634        if (rr == 0) {
    613             if (!FD_ISSET(STDIN_FILENO, &ding1))
     635            if (!FD_ISSET(STDIN_FILENO, &ding1)) {
    614636                netretry--;                        /* we actually try a coupla times. */
    615             if (!netretry) {
    616                 if (o_verbose > 1)                /* normally we don't care */
    617                     fprintf(stderr, "net timeout\n");
    618                 close(netfd);
    619                 return 0;                        /* not an error! */
     637                if (!netretry) {
     638                    if (o_verbose > 1)         /* normally we don't care */
     639                        fprintf(stderr, "net timeout\n");
     640                    /*close(netfd); - redundant, exit will do it */
     641                    return 0;                  /* not an error! */
     642                }
    620643            }
    621644        } /* select timeout */
     
    631654                    bb_perror_msg("net read");
    632655                }
    633                 FD_CLR(netfd, &ding1);                /* net closed, we'll finish up... */
     656                FD_CLR(netfd, &ding1);                /* net closed */
     657                fds_open--;
    634658                rzleft = 0;                        /* can't write anymore: broken pipe */
    635659            } else {
     
    651675     mobygrams are kinda fun and exercise the reassembler. */
    652676            if (rr <= 0) {                        /* at end, or fukt, or ... */
    653                 FD_CLR(STDIN_FILENO, &ding1);                /* disable and close stdin */
    654                 close(STDIN_FILENO);
    655 // Does it make sense to shutdown(net_fd, SHUT_WR)
    656 // to let other side know that we won't write anything anymore?
    657 // (and what about keeping compat if we do that?)
     677                FD_CLR(STDIN_FILENO, &ding1); /* disable stdin */
     678                /*close(STDIN_FILENO); - not really necessary */
     679                /* Let peer know we have no more data */
     680                /* nc 1.10 doesn't do this: */
     681                shutdown(netfd, SHUT_WR);
     682                fds_open--;
    658683            } else {
    659684                rzleft = rr;
     
    666691     not sure if the order of this matters, but write net -> stdout first. */
    667692
    668     /* sanity check.  Works because they're both unsigned... */
    669         if ((rzleft > 8200) || (rnleft > 8200)) {
    670             holler_error("bogus buffers: %u, %u", rzleft, rnleft);
    671             rzleft = rnleft = 0;
    672         }
    673     /* net write retries sometimes happen on UDP connections */
    674         if (!wretry) {                        /* is something hung? */
    675             holler_error("too many output retries");
    676             return 1;
    677         }
    678693        if (rnleft) {
    679694            rr = write(STDOUT_FILENO, np, rnleft);
     
    681696                if (o_ofile) /* log the stdout */
    682697                    oprint('<', (unsigned char *)np, rr);
    683                 np += rr;                        /* fix up ptrs and whatnot */
    684                 rnleft -= rr;                        /* will get sanity-checked above */
    685                 wrote_out += rr;                /* global count */
     698                np += rr;
     699                rnleft -= rr;
     700                wrote_out += rr; /* global count */
    686701            }
    687702Debug("wrote %d to stdout, errno %d", rr, errno);
     
    698713                zp += rr;
    699714                rzleft -= rr;
    700                 wrote_net += rr;                /* global count */
     715                wrote_net += rr; /* global count */
    701716            }
    702717Debug("wrote %d to net, errno %d", rr, errno);
     
    704719        if (o_interval) {                        /* cycle between slow lines, or ... */
    705720            sleep(o_interval);
    706             errno = 0;                        /* clear from sleep */
    707721            continue;                        /* ...with hairy select loop... */
    708722        }
    709         if ((rzleft) || (rnleft)) {                /* shovel that shit till they ain't */
     723        if (rzleft || rnleft) {                  /* shovel that shit till they ain't */
    710724            wretry--;                        /* none left, and get another load */
     725    /* net write retries sometimes happen on UDP connections */
     726            if (!wretry) {                   /* is something hung? */
     727                holler_error("too many output retries");
     728                return 1;
     729            }
    711730            goto shovel;
    712731        }
    713     } /* while ding1:netfd is open */
     732    } /* while (fds_open) */
    714733
    715734    /* XXX: maybe want a more graceful shutdown() here, or screw around with
     
    731750    char **proggie;
    732751    int x;
     752    unsigned cnt_l = 0;
    733753    unsigned o_lport = 0;
    734754
     
    761781            char *optpos = *proggie + 1;
    762782            /* Skip all valid opts w/o params */
    763             optpos = optpos + strspn(optpos, "nuv"IF_NC_SERVER("l")IF_NC_EXTRA("z"));
     783            optpos = optpos + strspn(optpos, "nuv"IF_NC_SERVER("lk")IF_NC_EXTRA("z"));
    764784            if (*optpos == 'e' && !optpos[1]) {
    765785                *optpos = '\0';
     
    775795
    776796    // -g -G -t -r deleted, unimplemented -a deleted too
    777     opt_complementary = "?2:vv:w+"; /* max 2 params; -v is a counter; -w N */
    778     getopt32(argv, "np:s:uvw:" IF_NC_SERVER("l")
     797    opt_complementary = "?2:vv:ll:w+"; /* max 2 params; -v and -l are counters; -w N */
     798    getopt32(argv, "np:s:uvw:" IF_NC_SERVER("lk")
    779799            IF_NC_EXTRA("i:o:z"),
    780800            &str_p, &str_s, &o_wait
    781             IF_NC_EXTRA(, &str_i, &str_o), &o_verbose);
     801            IF_NC_EXTRA(, &str_i, &str_o), &o_verbose IF_NC_SERVER(, &cnt_l));
    782802    argv += optind;
    783803#if ENABLE_NC_EXTRA
     
    785805        o_interval = xatou_range(str_i, 1, 0xffff);
    786806#endif
     807#if ENABLE_NC_SERVER
    787808    //if (option_mask32 & OPT_l) /* listen mode */
     809    if (option_mask32 & OPT_k) /* persistent server mode */
     810        cnt_l = 2;
     811#endif
    788812    //if (option_mask32 & OPT_n) /* numeric-only, no DNS lookups */
    789813    //if (option_mask32 & OPT_o) /* hexdump log */
     
    834858        socket_want_pktinfo(netfd);
    835859    if (!ENABLE_FEATURE_UNIX_LOCAL
    836      || o_listen
     860     || cnt_l != 0 /* listen */
    837861     || ouraddr->u.sa.sa_family != AF_UNIX
    838862    ) {
     
    840864    }
    841865#if 0
    842     setsockopt(netfd, SOL_SOCKET, SO_RCVBUF, &o_rcvbuf, sizeof o_rcvbuf);
    843     setsockopt(netfd, SOL_SOCKET, SO_SNDBUF, &o_sndbuf, sizeof o_sndbuf);
     866    setsockopt_SOL_SOCKET_int(netfd, SO_RCVBUF, o_rcvbuf);
     867    setsockopt_SOL_SOCKET_int(netfd, SO_SNDBUF, o_sndbuf);
    844868#endif
    845869
     
    853877#endif
    854878
    855     FD_SET(STDIN_FILENO, &ding1);                        /* stdin *is* initially open */
    856879    if (proggie) {
    857         close(0); /* won't need stdin */
     880        close(STDIN_FILENO); /* won't need stdin */
    858881        option_mask32 &= ~OPT_o; /* -o with -e is meaningless! */
    859882    }
     
    863886#endif
    864887
    865     if (o_listen) {
    866         dolisten();
     888    if (cnt_l != 0) {
     889        dolisten((cnt_l - 1), proggie);
    867890        /* dolisten does its own connect reporting */
    868         if (proggie) /* -e given? */
    869             doexec(proggie);
    870891        x = readwrite(); /* it even works with UDP! */
    871892    } else {
Note: See TracChangeset for help on using the changeset viewer.