A recently added -F option to the nc (netcat) command to pass a
connected file descriptor to stdout only works for the listen mode
when it passes the accepted descriptor.

The patch below makes -F universal. When given it makes nc to always
pass the socket to stdout rather than performing the copy loop. This
works both in the client and the server modes including -l -k when nc
continuesly passes to stdout all sockets it accepted when listening to
the connection.

The patch aslo updates nc.1 to show how to use nc -F together with
ProxyUseFdPass.

Index: nc.1
===================================================================
RCS file: /cvs/src/usr.bin/nc/nc.1,v
retrieving revision 1.67
diff -U3 -p -r1.67 nc.1
--- nc.1    26 Feb 2014 20:56:11 -0000    1.67
+++ nc.1    2 May 2014 18:18:10 -0000
@@ -103,9 +103,9 @@ Enable debugging on the socket.
 .It Fl d
 Do not attempt to read from stdin.
 .It Fl F
-Pass the first connected socket using
+Pass the connected socket using
 .Xr sendmsg 2
-to stdout and exit.
+to stdout and close own copy.
 This is useful in conjunction with
 .Fl X
 to have
@@ -116,7 +116,14 @@ connection to another program (e.g.\&
 using the
 .Xr ssh_config 5
 .Cm ProxyUseFdPass
-option).
+directive). When this option is specified together with
+.Fl l,
+.Nm
+sends a socket representing the connection it accepted from a client. If the
+.Fl k
+is also given,
+.Nm
+will continue to send all incomming connections indefinitely.
 .It Fl h
 Prints out
 .Nm
@@ -445,16 +452,18 @@ stream socket:
 .Dl $ nc -lU /var/tmp/dsocket
 .Pp
 Connect to port 42 of host.example.com via an HTTP proxy at 10.2.3.4,
-port 8080.
+port 8080, pass the connected socket to stdout and exit.
 This example could also be used by
 .Xr ssh 1 ;
 see the
 .Cm ProxyCommand
-directive in
+and
+.Cm ProxyUseFdPass
+directives in
 .Xr ssh_config 5
 for more information.
 .Pp
-.Dl $ nc -x10.2.3.4:8080 -Xconnect host.example.com 42
+.Dl $ nc -F -x10.2.3.4:8080 -Xconnect host.example.com 42
 .Pp
 The same example again, this time enabling proxy authentication with username
 .Dq ruser
Index: netcat.c
===================================================================
RCS file: /cvs/src/usr.bin/nc/netcat.c,v
retrieving revision 1.118
diff -U3 -p -r1.118 netcat.c
--- netcat.c    12 Mar 2014 10:19:40 -0000    1.118
+++ netcat.c    2 May 2014 18:18:10 -0000
@@ -99,7 +99,7 @@ void    build_ports(char *);
 void    help(void);
 int    local_listen(char *, char *, struct addrinfo);
 void    readwrite(int);
-void    fdpass(int nfd) __attribute__((noreturn));
+void    fdpass(int nfd);
 int    remote_connect(const char *, const char *, struct addrinfo);
 int    timeout_connect(int, const struct sockaddr *, socklen_t);
 int    socks_connect(const char *, const char *, struct addrinfo,
@@ -286,6 +286,15 @@ main(int argc, char *argv[])
     if (!lflag && kflag)
         errx(1, "must use -l with -k");

+    if (Fflag && zflag) {
+        warnx(1, "ignoring -z flag as -F is given");
+        zflag = 0;
+        }
+    if (FFlag && uflag && kflag) {
+        warnx(1, "ignoring -k flag as -F is given together with -u");
+        kflag = 0;
+    }
+
     /* Get name of temporary socket for unix datagram client */
     if ((family == AF_UNIX) && uflag && !lflag) {
         if (sflag) {
@@ -469,9 +478,7 @@ main(int argc, char *argv[])
                     uflag ? "udp" : "tcp",
                     sv ? sv->s_name : "*");
             }
-            if (Fflag)
-                fdpass(s);
-            else if (!zflag)
+            if (!zflag)
                 readwrite(s);
         }
     }
@@ -727,17 +734,25 @@ local_listen(char *host, char *port, str

 /*
  * readwrite()
- * Loop that polls on the network file descriptor and stdin.
+ * Loop that polls on the network file descriptor and stdin, or, when the
+ * FFlag is given, pass the descriptor to stdout.
  */
 void
 readwrite(int nfd)
 {
     struct pollfd pfd[2];
     unsigned char buf[16384];
-    int n, wfd = fileno(stdin);
-    int lfd = fileno(stdout);
+    int n, wfd;
+    int lfd;
     int plen;

+    if (Fflag) {
+        fdpass(nfd);
+        return;
+    }
+
+    lfd = fileno(stdout);
+    wfd = fileno(stdin);
     plen = 2048;

     /* Setup Network FD */
@@ -793,7 +808,7 @@ readwrite(int nfd)

 /*
  * fdpass()
- * Pass the connected file descriptor to stdout and exit.
+ * Pass the connected file descriptor to stdout.
  */
 void
 fdpass(int nfd)
@@ -848,7 +863,6 @@ fdpass(int nfd)
         else
             break;
     }
-    exit(0);
 }

 /* Deal with RFC 854 WILL/WONT DO/DONT negotiation. */

Reply via email to