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)
#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)
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):
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;
}
unarm();
} else
- bb_error_msg_and_die("timeout");
+ bb_simple_error_msg_and_die("timeout");
if (is_persistent && proggie) {
/* -l -k -e PROG */
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);
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)?
/* 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);
#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 {
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);
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 */
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
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 */
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
/* 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