From 9c3eb4b413cc240680d349c9356c8f9c89d5c7aa Mon Sep 17 00:00:00 2001 From: Rob Landley Date: Fri, 17 May 2024 03:34:34 -0500 Subject: [PATCH] netcat: add -o --- lib/lib.h | 4 ++- lib/net.c | 6 ++-- toys/net/netcat.c | 82 ++++++++++++++++++++++++++++++++++++++--------- 3 files changed, 73 insertions(+), 19 deletions(-) diff --git a/lib/lib.h b/lib/lib.h index 4618a2f0..5bc21f01 100644 --- a/lib/lib.h +++ b/lib/lib.h @@ -359,7 +359,9 @@ void xconnect(int fd, const struct sockaddr *sa, socklen_t len); int xconnectany(struct addrinfo *ai); int xbindany(struct addrinfo *ai); int xpoll(struct pollfd *fds, int nfds, int timeout); -int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_timeout); +int pollinate(int in1, int in2, int out1, int out2, + void (*callback)(int fd, void *buf, size_t len), + int timeout, int shutdown_timeout); char *ntop(struct sockaddr *sa); void xsendto(int sockfd, void *buf, size_t len, struct sockaddr *dest); int xrecvwait(int fd, char *buf, int len, union socksaddr *sa, int timeout); diff --git a/lib/net.c b/lib/net.c index 16a110e3..8fe006b6 100644 --- a/lib/net.c +++ b/lib/net.c @@ -96,7 +96,9 @@ int xpoll(struct pollfd *fds, int nfds, int timeout) // Loop forwarding data from in1 to out1 and in2 to out2, handling // half-connection shutdown. timeouts return if no data for X ms. // Returns 0: both closed, 1 shutdown_timeout, 2 timeout -int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_timeout) +int pollinate(int in1, int in2, int out1, int out2, + void (*callback)(int fd, void *buf, size_t len), + int timeout, int shutdown_timeout) { struct pollfd pollfds[2]; int i, pollcount = 2; @@ -115,7 +117,7 @@ int pollinate(int in1, int in2, int out1, int out2, int timeout, int shutdown_ti int len = read(pollfds[i].fd, libbuf, sizeof(libbuf)); if (len<1) pollfds[i].revents = POLLHUP; else { - xwrite(i ? out2 : out1, libbuf, len); + callback(i ? out2 : out1, libbuf, len); continue; } } diff --git a/toys/net/netcat.c b/toys/net/netcat.c index 16cf40f0..7587dac9 100644 --- a/toys/net/netcat.c +++ b/toys/net/netcat.c @@ -2,16 +2,16 @@ * * Copyright 2007 Rob Landley * - * TODO: genericize for telnet/microcom/tail-f, fix -t + * TODO: genericize for telnet/microcom/tail-f, fix -t with login_tty() -USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1s:f:46uUnvz[!tlL][!Lw][!Lu][!46U]", TOYFLAG_BIN)) +USE_NETCAT(NEWTOY(netcat, "^tElLw#<1W#<1p#<1>65535q#<1o:s:f:46uUnz[!tlL][!Lw][!Lu][!46U]", TOYFLAG_BIN)) USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN)) config NETCAT bool "netcat" default y help - usage: netcat [-46ELlntUu] [-pqWw #] [-s addr] {IPADDR PORTNUM|-f FILENAME|COMMAND...} + usage: netcat [-46ELlntUu] [-pqWw #] [-s addr] [-o FILE] {IPADDR PORTNUM|-f FILENAME|COMMAND...} Forward stdin/stdout to a file or network connection. @@ -22,11 +22,11 @@ config NETCAT -L Listen and background each incoming connection (server mode) -l Listen for one incoming connection, then exit -n No DNS lookup + -o Hex dump to FILE (-o- writes hex only to stdout) -p Local port number -q Quit SECONDS after EOF on stdin, even if stdout hasn't closed yet -s Local source address -t Allocate tty - -v Verbose -u Use UDP -U Use a UNIX domain socket -W SECONDS timeout for more data on an idle connection @@ -49,8 +49,11 @@ config NETCAT #include "toys.h" GLOBALS( - char *f, *s; + char *f, *s, *o; long q, p, W, w; + + unsigned ofd, olast, opos, ocount[2]; + char obuf[16]; ) static void timeout(int signum) @@ -78,6 +81,49 @@ static int usock(char *name, int type, int out) return sockfd; } +// Hex dump accumulated buffer data +void oflush(void) +{ + char *s = toybuf; + unsigned *oc = TT.ocount+(TT.olast==1), uu; + + if (!TT.opos) return; + s += sprintf(toybuf, "%c %08x", 60+2*(TT.olast==1), *oc); + for (uu = 0; uu<16; uu++) { + s += sprintf(s, uu95) TT.obuf[uu] = '.'; + } + dprintf(TT.ofd, "%s # %.*s\n", toybuf, TT.opos, TT.obuf); + *oc += TT.opos; + TT.opos = 0; +} + +// Write data to output, and hex dump to -o if enabled. +void ohexwrite(int fd, void *buf, size_t len) +{ + // Hex dump if -o specified. Output is always to fd 1, input != 1. + if (TT.ofd) { + int i = 0, j; + + if (TT.olast != fd) oflush(); + TT.olast = fd; + + while (i