--- src/usr.bin/nc/netcat.c.7-execcmd 2005-10-12 19:24:33 +0400 +++ src/usr.bin/nc/netcat.c 2005-11-07 22:44:03 +0300 @@ -90,11 +90,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 @@ 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; @@ -158,6 +160,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; @@ -257,6 +264,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"); @@ -426,6 +435,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. @@ -629,6 +677,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 @@ -856,7 +910,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) --- src/usr.bin/nc/nc.1.7-execcmd 2006-07-25 15:33:54 +0400 +++ src/usr.bin/nc/nc.1 2006-07-25 15:34:49 +0400 @@ -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 @@ 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 @@ 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