Updated the original patch to just jump to cleanup, instead of rearranging
things.

Also, polished up the proof of concept xgetaddrinfo (this needs a better
name)
patch, and used it to implement -4, -6 (plus another patch to do -u).

On Thu, Jun 29, 2017 at 6:59 PM, enh <e...@google.com> wrote:

> ping? various networking folks are looking to add tests that use
> netcat, and i'd rather start them off on toybox netcat rather than BSD
> and then have to move them across to toybox later. (obviously there's
> other missing stuff in toybox, but these patches are the only things
> they actually need right now.)
>
> On Wed, Jun 28, 2017 at 3:47 PM, Josh Gao <jm...@google.com> wrote:
> > On Sun, Jun 25, 2017 at 12:14 PM, Rob Landley <r...@landley.net> wrote:
> >>
> >> 1) switching it to use xconnect() which it predates, and which is hard
> >> because the various users in tree all want slighty different things out
> >> of the getaddrinfo() plumbing and I've made a couple attempts to
> >> unify/genericize it but keep getting pulled alway by $DAYJOB crisis du
> >> jour halfway through and forgetting what design problem details I was
> >> halfway through solving and have to start over again...
> >
> >
> > BTW, I took a quick look at this because we have users that want -4/-6
> (and
> > IPv6 support in general). `nc -s` makes it so that you can't use xconnect
> > because you don't know what to bind to until after you've resolved the
> > target
> > address. Something like xbind_and_connect might work, but there's also
> > things
> > that we might want to do in between socket and bind (e.g. setting
> > SO_REUSEADDR).
> >
> > The thing that everyone really wants is a way to iterate over getaddrinfo
> > results;
> > maybe that's what should be exposed? I have a rough proof of concept
> patch
> > attached that implements this and uses it in netcat.
> >
> > (There's also another edge case with -s: what happens if the host you
> pass
> > in
> > resolves to multiple addresses? OpenBSD's netcat seems to just bind the
> > first
> > compatible address it resolves to, so we can maybe just ignore this.)
> >
> > -Josh
> >
> > _______________________________________________
> > Toybox mailing list
> > Toybox@lists.landley.net
> > http://lists.landley.net/listinfo.cgi/toybox-landley.net
> >
>
>
>
> --
> Elliott Hughes - http://who/enh - http://jessies.org/~enh/
> Android native code/tools questions? Mail me/drop by/add me as a reviewer.
>
From bebee0943874f77bb4a7ff7126ba13738e50a3e3 Mon Sep 17 00:00:00 2001
From: Josh Gao <jm...@google.com>
Date: Wed, 28 Jun 2017 15:41:56 -0700
Subject: [PATCH 1/4] Add xgetaddrinfo, use it in netcat.

Add a helper function that iterates over getaddrinfo results with a
callback, and switch netcat over to it to add support for IPv6.
---
 lib/lib.h         |   2 +
 lib/net.c         |  53 ++++++++++-----
 toys/net/netcat.c | 191 ++++++++++++++++++++++++++++++------------------------
 3 files changed, 144 insertions(+), 102 deletions(-)

diff --git a/lib/lib.h b/lib/lib.h
index 0b93bde..7d12233 100644
--- a/lib/lib.h
+++ b/lib/lib.h
@@ -284,6 +284,8 @@ void tty_sigreset(int i);
 // net.c
 int xsocket(int domain, int type, int protocol);
 void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len);
+int xgetaddrinfo(char *host, char *port, int family, int socktype, int protocol,
+                 int flags, int (*cb)(struct addrinfo*, void*), void *cookie);
 int xconnect(char *host, char *port, int family, int socktype, int protocol,
   int flags);
 int xpoll(struct pollfd *fds, int nfds, int timeout);
diff --git a/lib/net.c b/lib/net.c
index df2551f..b4f5f65 100644
--- a/lib/net.c
+++ b/lib/net.c
@@ -15,36 +15,55 @@ void xsetsockopt(int fd, int level, int opt, void *val, socklen_t len)
   if (-1 == setsockopt(fd, level, opt, val, len)) perror_exit("setsockopt");
 }
 
-int xconnect(char *host, char *port, int family, int socktype, int protocol,
-             int flags)
+int xgetaddrinfo(char *host, char *port, int family, int socktype, int protocol,
+                 int flags, int (*cb)(struct addrinfo*, void*), void *cookie)
 {
-  struct addrinfo info, *ai, *ai2;
-  int fd;
+  int rc;
+  struct addrinfo info, *ai, *ai_head;
 
-  memset(&info, 0, sizeof(struct addrinfo));
+  memset(&info, 0, sizeof(info));
   info.ai_family = family;
   info.ai_socktype = socktype;
   info.ai_protocol = protocol;
   info.ai_flags = flags;
 
-  fd = getaddrinfo(host, port, &info, &ai);
-  if (fd || !ai)
-    error_exit("Connect '%s%s%s': %s", host, port ? ":" : "", port ? port : "",
-      fd ? gai_strerror(fd) : "not found");
-
-  // Try all the returned addresses. Report errors if last entry can't connect.
-  for (ai2 = ai; ai; ai = ai->ai_next) {
-    fd = (ai->ai_next ? socket : xsocket)(ai->ai_family, ai->ai_socktype,
-      ai->ai_protocol);
-    if (!connect(fd, ai->ai_addr, ai->ai_addrlen)) break;
-    else if (!ai->ai_next) perror_exit("connect");
+  rc = getaddrinfo(host, port, &info, &ai);
+  if (rc || !ai) {
+    error_exit("getaddrinfo '%s%s%s': %s", host, port ? ":" : "", port ? port : "",
+      rc ? gai_strerror(rc) : "not found");
+  }
+
+  for (ai_head = ai; ai; ai = ai->ai_next) {
+    rc = cb(ai, cookie);
+    if (rc != -1) break;
+  }
+  freeaddrinfo(ai_head);
+
+  return rc;
+}
+
+static int _xconnect(struct addrinfo* ai, void *unused) {
+  int fd;
+
+  fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+  if (fd == -1) {
+    return -1;
+  } else if (!connect(fd, ai->ai_addr, ai->ai_addrlen)) {
     close(fd);
+    return -1;
   }
-  freeaddrinfo(ai2);
 
   return fd;
 }
 
+int xconnect(char *host, char *port, int family, int socktype, int protocol,
+             int flags)
+{
+  int rc = xgetaddrinfo(host, port, family, socktype, protocol, flags, _xconnect, 0);
+  if (rc == -1) perror_exit("connect");
+  return rc;
+}
+
 int xpoll(struct pollfd *fds, int nfds, int timeout)
 {
   int i;
diff --git a/toys/net/netcat.c b/toys/net/netcat.c
index 13ba311..1ad8b19 100644
--- a/toys/net/netcat.c
+++ b/toys/net/netcat.c
@@ -5,7 +5,7 @@
  * TODO: udp, ipv6, genericize for telnet/microcom/tail-f
 
 USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#W#p#s:q#f:"USE_NETCAT_LISTEN("[!tlL][!Lw]"), TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#W#p:s:q#f:"USE_NETCAT_LISTEN("[!tlL][!Lw]"), TOYFLAG_BIN))
 
 config NETCAT
   bool "netcat"
@@ -50,7 +50,7 @@ GLOBALS(
   char *filename;        // -f read from filename instead of network
   long quit_delay;       // -q Exit after EOF from stdin after # seconds.
   char *source_address;  // -s Bind to a specific source address.
-  long port;             // -p Bind to a specific source port.
+  char *port;            // -p Bind to a specific source port.
   long idle;             // -W Wait # seconds for more data
   long wait;             // -w Wait # seconds for a connection.
 )
@@ -68,26 +68,59 @@ static void set_alarm(int seconds)
   alarm(seconds);
 }
 
-// Translate x.x.x.x numeric IPv4 address, or else DNS lookup an IPv4 name.
-static void lookup_name(char *name, uint32_t *result)
-{
-  struct hostent *hostbyname;
-
-  hostbyname = gethostbyname(name); // getaddrinfo
-  if (!hostbyname) error_exit("no host '%s'", name);
-  *result = *(uint32_t *)*hostbyname->h_addr_list;
+static int socket_bind(struct addrinfo *ai, void *fd_) {
+  int fd = *(int*)fd_;
+  return bind(fd, ai->ai_addr, ai->ai_addrlen);
 }
 
-// Worry about a fancy lookup later.
-static void lookup_port(char *str, uint16_t *port)
-{
-  *port = SWAP_BE16(atoi(str));
+static int socket_connect(struct addrinfo *ai, void *unused) {
+  int fd, rc;
+
+  fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+  if (fd == -1) return -1;
+
+  fcntl(fd, F_SETFD, FD_CLOEXEC);
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof(rc));
+
+  if (TT.source_address || TT.port) {
+    rc = xgetaddrinfo(TT.source_address, TT.port, ai->ai_family,
+      ai->ai_socktype, ai->ai_protocol, ai->ai_flags, socket_bind, &fd);
+    if (rc != 0) {
+      close(fd);
+      return -1;
+    }
+  }
+
+  rc = connect(fd, ai->ai_addr, ai->ai_addrlen);
+  if (rc == -1) {
+    close(fd);
+    return -1;
+  }
+  return fd;
+}
+
+static int socket_server(struct addrinfo *ai, void *unused) {
+  int fd, rc;
+
+  fd = socket(ai->ai_family, ai->ai_socktype, ai->ai_protocol);
+  if (fd == -1) return -1;
+
+  fcntl(fd, F_SETFD, FD_CLOEXEC);
+  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof(rc));
+
+  if (bind(fd, ai->ai_addr, ai->ai_addrlen)) {
+    close(fd);
+    return -1;
+  }
+
+  return fd;
 }
 
 void netcat_main(void)
 {
   struct sockaddr_in *address = (void *)toybuf;
-  int sockfd=-1, in1 = 0, in2 = 0, out1 = 1, out2 = 1;
+  int sockfd = -1, in1 = 0, in2 = 0, out1 = 1, out2 = 1;
+  int family = 0; // TODO: -4, -6
   pid_t child;
 
   // Addjust idle and quit_delay to miliseconds or -1 for no timeout
@@ -103,93 +136,81 @@ void netcat_main(void)
         help_exit("bad argument count");
 
   if (TT.filename) in1 = out2 = xopen(TT.filename, O_RDWR);
-  else {
-    // Setup socket
-    sockfd = xsocket(AF_INET, SOCK_STREAM, 0);
-    fcntl(sockfd, F_SETFD, FD_CLOEXEC);
-    setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &out1, sizeof(out1));
-    address->sin_family = AF_INET;
-    if (TT.source_address || TT.port) {
-      address->sin_port = SWAP_BE16(TT.port);
-      if (TT.source_address)
-        lookup_name(TT.source_address, (uint32_t *)&(address->sin_addr));
-      if (bind(sockfd, (struct sockaddr *)address, sizeof(*address)))
-        perror_exit("bind");
-    }
-
+  else if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) {
     // Dial out
+    sockfd = xgetaddrinfo(toys.optargs[0], toys.optargs[1], family,
+      SOCK_STREAM, 0, 0, socket_connect, 0);
+    if (sockfd < 0) perror_exit("connect");
 
-    if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) {
-      // Figure out where to dial out to.
-      lookup_name(*toys.optargs, (uint32_t *)&(address->sin_addr));
-      lookup_port(toys.optargs[1], &(address->sin_port));
-// TODO xconnect
-      if (connect(sockfd, (struct sockaddr *)address, sizeof(*address))<0)
-        perror_exit("connect");
-      in1 = out2 = sockfd;
-
-    // Listen for incoming connections
+    in1 = out2 = sockfd;
+  } else {
+    socklen_t len = sizeof(*address);
 
+    if (TT.source_address || TT.port) {
+      sockfd = xgetaddrinfo(TT.source_address, TT.port, family, SOCK_STREAM, 0, 0,
+        socket_server, &sockfd);
     } else {
-      socklen_t len = sizeof(*address);
+      sockfd = xsocket(family ? family : AF_INET, SOCK_STREAM, 0);
+    }
 
-      if (listen(sockfd, 5)) error_exit("listen");
-      if (!TT.port) {
-        getsockname(sockfd, (struct sockaddr *)address, &len);
-        printf("%d\n", SWAP_BE16(address->sin_port));
-        fflush(stdout);
-        // Return immediately if no -p and -Ll has arguments, so wrapper
-        // script can use port number.
-        if (CFG_TOYBOX_FORK && toys.optc && xfork()) goto cleanup;
-      }
+    if (sockfd == -1) perror_exit("bind");
 
-      for (;;) {
-        child = 0;
-        len = sizeof(*address); // gcc's insane optimizer can overwrite this
-        in1 = out2 = accept(sockfd, (struct sockaddr *)address, &len);
+    if (listen(sockfd, 5)) error_exit("listen");
+    if (!TT.port) {
+      getsockname(sockfd, (struct sockaddr *)address, &len);
+      printf("%d\n", SWAP_BE16(address->sin_port));
+      fflush(stdout);
+      // Return immediately if no -p and -Ll has arguments, so wrapper
+      // script can use port number.
+      if (CFG_TOYBOX_FORK && toys.optc && xfork()) goto cleanup;
+    }
 
-        if (in1<0) perror_exit("accept");
+    for (;;) {
+      child = 0;
+      len = sizeof(*address); // gcc's insane optimizer can overwrite this
+      in1 = out2 = accept(sockfd, (struct sockaddr *)address, &len);
 
-        // We can't exit this loop or the optimizer's "liveness analysis"
-        // combines badly with vfork() to corrupt or local variables
-        // (the child's call stack gets trimmed and the next function call
-        // stops the variables the parent tries to re-use next loop)
-        // So there's a bit of redundancy here
+      if (in1<0) perror_exit("accept");
 
-        // We have a connection. Disarm timeout.
-        set_alarm(0);
+      // We can't exit this loop or the optimizer's "liveness analysis"
+      // combines badly with vfork() to corrupt or local variables
+      // (the child's call stack gets trimmed and the next function call
+      // stops the variables the parent tries to re-use next loop)
+      // So there's a bit of redundancy here
 
-        if (toys.optc) {
-          // Do we need a tty?
+      // We have a connection. Disarm timeout.
+      set_alarm(0);
+
+      if (toys.optc) {
+        // Do we need a tty?
 
 // TODO nommu, and -t only affects server mode...? Only do -t with optc
-//        if (CFG_TOYBOX_FORK && (toys.optflags&FLAG_t))
-//          child = forkpty(&fdout, NULL, NULL, NULL);
-//        else
+//      if (CFG_TOYBOX_FORK && (toys.optflags&FLAG_t))
+//        child = forkpty(&fdout, NULL, NULL, NULL);
+//      else
 
-          // Do we need to fork and/or redirect for exec?
+        // Do we need to fork and/or redirect for exec?
 
-          if (toys.optflags&FLAG_L) {
-            toys.stacktop = 0;
-            child = vfork();
-          }
-          if (child<0) error_msg("vfork failed\n");
-          else {
-            if (child) {
-              close(in1);
-              continue;
-            }
-            dup2(in1, 0);
-            dup2(in1, 1);
-            if (toys.optflags&FLAG_L) dup2(in1, 2);
-            if (in1>2) close(in1);
-            xexec(toys.optargs);
+        if (toys.optflags&FLAG_L) {
+          toys.stacktop = 0;
+          child = vfork();
+        }
+        if (child<0) error_msg("vfork failed\n");
+        else {
+          if (child) {
+            close(in1);
+            continue;
           }
+          dup2(in1, 0);
+          dup2(in1, 1);
+          if (toys.optflags&FLAG_L) dup2(in1, 2);
+          if (in1>2) close(in1);
+          xexec(toys.optargs);
         }
-
-        pollinate(in1, in2, out1, out2, TT.idle, TT.quit_delay);
-        close(in1);
       }
+
+      pollinate(in1, in2, out1, out2, TT.idle, TT.quit_delay);
+      close(in1);
     }
   }
 
-- 
2.13.2.725.g09c95d1e9-goog

From 82223a53be96f57de34591f4ed3694e0a0cdc6f6 Mon Sep 17 00:00:00 2001
From: Josh Gao <jm...@google.com>
Date: Wed, 28 Jun 2017 15:53:16 -0700
Subject: [PATCH 2/4] Add -4, -6 to netcat.

---
 toys/net/netcat.c | 8 ++++++--
 1 file changed, 6 insertions(+), 2 deletions(-)

diff --git a/toys/net/netcat.c b/toys/net/netcat.c
index 1ad8b19..cbfa875 100644
--- a/toys/net/netcat.c
+++ b/toys/net/netcat.c
@@ -5,7 +5,7 @@
  * TODO: udp, ipv6, genericize for telnet/microcom/tail-f
 
 USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#W#p:s:q#f:"USE_NETCAT_LISTEN("[!tlL][!Lw]"), TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#W#p:s:q#f:46"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46]", TOYFLAG_BIN))
 
 config NETCAT
   bool "netcat"
@@ -13,6 +13,7 @@ config NETCAT
   help
     usage: netcat [-u] [-wpq #] [-s addr] {IPADDR PORTNUM|-f FILENAME}
 
+    -4, -6	force IPv4, IPv6
     -f	use FILENAME (ala /dev/ttyS0) instead of network
     -p	local port number
     -q	quit SECONDS after EOF on stdin, even if stdout hasn't closed yet
@@ -120,9 +121,12 @@ void netcat_main(void)
 {
   struct sockaddr_in *address = (void *)toybuf;
   int sockfd = -1, in1 = 0, in2 = 0, out1 = 1, out2 = 1;
-  int family = 0; // TODO: -4, -6
+  int family = 0;
   pid_t child;
 
+  if (toys.optflags&FLAG_4) family = AF_INET;
+  if (toys.optflags&FLAG_6) family = AF_INET6;
+
   // Addjust idle and quit_delay to miliseconds or -1 for no timeout
   TT.idle = TT.idle ? TT.idle*1000 : -1;
   TT.quit_delay = TT.quit_delay ? TT.quit_delay*1000 : -1;
-- 
2.13.2.725.g09c95d1e9-goog

From 1cb43b4c8e793f37db3708c8eed887f504e8e1a1 Mon Sep 17 00:00:00 2001
From: Josh Gao <jm...@google.com>
Date: Thu, 29 Jun 2017 13:39:55 -0700
Subject: [PATCH 3/4] Add UDP support to netcat.

---
 toys/net/netcat.c | 42 +++++++++++++++++++++++++++++++++---------
 1 file changed, 33 insertions(+), 9 deletions(-)

diff --git a/toys/net/netcat.c b/toys/net/netcat.c
index cbfa875..b3a0c05 100644
--- a/toys/net/netcat.c
+++ b/toys/net/netcat.c
@@ -5,7 +5,7 @@
  * TODO: udp, ipv6, genericize for telnet/microcom/tail-f
 
 USE_NETCAT(OLDTOY(nc, netcat, TOYFLAG_USR|TOYFLAG_BIN))
-USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#W#p:s:q#f:46"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46]", TOYFLAG_BIN))
+USE_NETCAT(NEWTOY(netcat, USE_NETCAT_LISTEN("^tlL")"w#W#p:s:uq#f:46"USE_NETCAT_LISTEN("[!tlL][!Lw]")"[!46][!fu]", TOYFLAG_BIN))
 
 config NETCAT
   bool "netcat"
@@ -18,6 +18,7 @@ config NETCAT
     -p	local port number
     -q	quit SECONDS after EOF on stdin, even if stdout hasn't closed yet
     -s	local source address
+    -u	use UDP instead of TCP
     -w	SECONDS timeout to establish connection
     -W	SECONDS timeout for idle connection
 
@@ -81,7 +82,10 @@ static int socket_connect(struct addrinfo *ai, void *unused) {
   if (fd == -1) return -1;
 
   fcntl(fd, F_SETFD, FD_CLOEXEC);
-  setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof(rc));
+
+  if (!(toys.optflags&FLAG_u)) {
+    setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, &rc, sizeof(rc));
+  }
 
   if (TT.source_address || TT.port) {
     rc = xgetaddrinfo(TT.source_address, TT.port, ai->ai_family,
@@ -121,11 +125,13 @@ void netcat_main(void)
 {
   struct sockaddr_in *address = (void *)toybuf;
   int sockfd = -1, in1 = 0, in2 = 0, out1 = 1, out2 = 1;
+  int socktype = SOCK_STREAM;
   int family = 0;
   pid_t child;
 
-  if (toys.optflags&FLAG_4) family = AF_INET;
-  if (toys.optflags&FLAG_6) family = AF_INET6;
+  if ((toys.optflags&FLAG_u)) socktype = SOCK_DGRAM;
+  if ((toys.optflags&FLAG_4)) family = AF_INET;
+  if ((toys.optflags&FLAG_6)) family = AF_INET6;
 
   // Addjust idle and quit_delay to miliseconds or -1 for no timeout
   TT.idle = TT.idle ? TT.idle*1000 : -1;
@@ -143,7 +149,7 @@ void netcat_main(void)
   else if (!CFG_NETCAT_LISTEN || !(toys.optflags&(FLAG_L|FLAG_l))) {
     // Dial out
     sockfd = xgetaddrinfo(toys.optargs[0], toys.optargs[1], family,
-      SOCK_STREAM, 0, 0, socket_connect, 0);
+      socktype, 0, 0, socket_connect, 0);
     if (sockfd < 0) perror_exit("connect");
 
     in1 = out2 = sockfd;
@@ -151,15 +157,29 @@ void netcat_main(void)
     socklen_t len = sizeof(*address);
 
     if (TT.source_address || TT.port) {
-      sockfd = xgetaddrinfo(TT.source_address, TT.port, family, SOCK_STREAM, 0, 0,
+      sockfd = xgetaddrinfo(TT.source_address, TT.port, family, socktype, 0, 0,
         socket_server, &sockfd);
     } else {
-      sockfd = xsocket(family ? family : AF_INET, SOCK_STREAM, 0);
+      sockfd = xsocket(family ? family : AF_INET, socktype, 0);
     }
 
     if (sockfd == -1) perror_exit("bind");
 
-    if (listen(sockfd, 5)) error_exit("listen");
+    if ((toys.optflags&FLAG_u)) {
+      struct sockaddr_storage ss;
+      socklen_t socklen = sizeof(ss);
+
+      if (recvfrom(sockfd, 0, 0, MSG_PEEK, (struct sockaddr*)&ss, &socklen) == -1) {
+        perror_exit("recvfrom");
+      }
+
+      if (connect(sockfd, (struct sockaddr*)&ss, socklen) == -1) {
+        perror_exit("connect");
+      }
+    } else {
+      if (listen(sockfd, 5)) perror_exit("listen");
+    }
+
     if (!TT.port) {
       getsockname(sockfd, (struct sockaddr *)address, &len);
       printf("%d\n", SWAP_BE16(address->sin_port));
@@ -172,7 +192,11 @@ void netcat_main(void)
     for (;;) {
       child = 0;
       len = sizeof(*address); // gcc's insane optimizer can overwrite this
-      in1 = out2 = accept(sockfd, (struct sockaddr *)address, &len);
+      if ((toys.optflags&FLAG_u)) {
+        in1 = out2 = sockfd;
+      } else {
+        in1 = out2 = accept(sockfd, (struct sockaddr *)address, &len);
+      }
 
       if (in1<0) perror_exit("accept");
 
-- 
2.13.2.725.g09c95d1e9-goog

From 39d8a2cde7e11f26bfd91b201a4dcf169159b216 Mon Sep 17 00:00:00 2001
From: Josh Gao <jm...@google.com>
Date: Fri, 30 Jun 2017 11:31:28 -0700
Subject: [PATCH 4/4] netcat: make -l exit after handling a request.

---
 toys/net/netcat.c | 6 ++++--
 1 file changed, 4 insertions(+), 2 deletions(-)

diff --git a/toys/net/netcat.c b/toys/net/netcat.c
index b3a0c05..2464ad8 100644
--- a/toys/net/netcat.c
+++ b/toys/net/netcat.c
@@ -189,7 +189,7 @@ void netcat_main(void)
       if (CFG_TOYBOX_FORK && toys.optc && xfork()) goto cleanup;
     }
 
-    for (;;) {
+    do {
       child = 0;
       len = sizeof(*address); // gcc's insane optimizer can overwrite this
       if ((toys.optflags&FLAG_u)) {
@@ -239,7 +239,9 @@ void netcat_main(void)
 
       pollinate(in1, in2, out1, out2, TT.idle, TT.quit_delay);
       close(in1);
-    }
+    } while (!(toys.optflags&FLAG_l));
+
+    goto cleanup;
   }
 
   // We have a connection. Disarm timeout.
-- 
2.13.2.725.g09c95d1e9-goog

_______________________________________________
Toybox mailing list
Toybox@lists.landley.net
http://lists.landley.net/listinfo.cgi/toybox-landley.net

Reply via email to