--- netcat-4.0.20061122/usr.bin/nc/nc.1 +++ netcat-4.0.20061122/usr.bin/nc/nc.1 @@ -35,6 +35,7 @@ .Nm nc .Bk -words .Op Fl 46DdhklnrStUuvz +.Op Fl e Ar command .Op Fl i Ar interval .Op Fl P Ar proxy_username .Op Fl p Ar source_port @@ -97,6 +98,9 @@ to use IPv6 addresses only. Enable debugging on the socket. .It Fl d Do not attempt to read from stdin. +.It Fl e Ar command +Starts specified command for communicating with remote side +after connection is established. .It Fl h Prints out .Nm @@ -399,6 +403,11 @@ The same example again, this time enabling proxy authentication with username if the proxy requires it: .Pp .Dl $ nc -x10.2.3.4:8080 -Xconnect -Pruser host.example.com 42 +.Pp +Listen on port 1234, send system name to connected client and exit: +.Pp +.Dl $ nc -l -v -e 'cat /etc/altlinux-release; uname -a' 1234 +.Pp .Sh SEE ALSO .Xr cat 1 , .Xr ssh 1 --- netcat-4.0.20061122/usr.bin/nc/netcat.c +++ netcat-4.0.20061122/usr.bin/nc/netcat.c @@ -95,11 +95,13 @@ int Dflag; /* sodebug */ int Sflag; /* TCP MD5 signature option */ #endif int Tflag = -1; /* IP Type of Service */ +char *opt_exec = NULL; /* program to exec after connecting */ int timeout = -1; int family = AF_INET; char *portlist[PORT_MAX+1]; +void execcmd(int fd); void atelnet(int, unsigned char *, unsigned int); void build_ports(char *); void help(void); @@ -139,7 +141,7 @@ main(int argc, char *argv[]) usage(1); while ((ch = getopt(argc, argv, - "46Ddhi:jklnP:p:rSs:tT:Uuvw:X:x:z")) != -1) { + "46Dde:hi:jklnP:p:rSs:tT:Uuvw:X:x:z")) != -1) { switch (ch) { case '4': family = AF_INET; @@ -163,6 +165,11 @@ main(int argc, char *argv[]) case 'd': dflag = 1; break; + case 'e': /* prog to exec */ + if (opt_exec) + errx(1, "cannot specify `-e' option double"); + opt_exec = strdup(optarg); + break; case 'h': help(); break; @@ -266,6 +273,8 @@ main(int argc, char *argv[]) errx(1, "cannot use -p and -l"); if (lflag && zflag) errx(1, "cannot use -z and -l"); + if (zflag && opt_exec) + errx(1, "cannot use -z and -e"); if (!lflag && kflag) errx(1, "must use -l with -k"); @@ -436,6 +445,45 @@ main(int argc, char *argv[]) exit(ret); } + +/* + * execcmd() + * Execute an external file making its stdin/stdout/stderr + * the actual socket. Returns never. + */ +void +execcmd(int fd) +{ + int saved_stderr; + char *p; + + /* save the stderr fd because we may need it later */ + saved_stderr = dup(STDERR_FILENO); + + /* duplicate the socket for the child program */ + dup2(fd, STDIN_FILENO); /* the precise order of fiddlage */ + close(fd); /* is apparently crucial; this is */ + dup2(STDIN_FILENO, STDOUT_FILENO); /* swiped directly out of "inetd". */ + dup2(STDIN_FILENO, STDERR_FILENO); /* also duplicate the stderr channel */ + + /* change the label for the executed program */ + if ((p = strrchr(opt_exec, '/'))) { + p++; /* shorter argv[0] */ + } else { + p = opt_exec; + } + + /* replace this process with the new one */ +#ifndef USE_OLD_COMPAT + execl("/bin/sh", p, "-c", opt_exec, NULL); +#else + execl(opt_exec, p, NULL); +#endif + dup2(saved_stderr, STDERR_FILENO); + err(1, "couldn't execute %s ", opt_exec); +} + + /* * unix_connect() * Returns a socket connected to a local unix socket. Returns -1 on failure. @@ -632,6 +680,12 @@ readwrite(int nfd) int lfd = fileno(stdout); int plen; + if (opt_exec) { + if (vflag) + printf("Call sub-process %s\n", opt_exec); + execcmd(nfd); + } + #if defined(HAVE_SO_JUMBO) plen = jflag ? 8192 : 1024; #else @@ -884,7 +938,7 @@ help(void) void usage(int ret) { - fprintf(stderr, "usage: netcat [-46DdhklnrStUuvz] [-i interval] [-p source_port]\n"); + fprintf(stderr, "usage: netcat [-46DdhklnrStUuvz] [-e cmd] [-i interval] [-p source_port]\n"); fprintf(stderr, " [-s source_ip_address] [-w timeout] [-X proxy_version]\n"); fprintf(stderr, " [-x proxy_address[:port]] [hostname] [port[s]]\n"); if (ret)