Upgrade netcat a lot. Make -e able to take the rest of the command line as what to exec. Add -f mode and a brief explanation of how to use it to replace minicom. Add -l -l mode so you can turn any command into a server. And group all of netcat's command line options under two CONFIG entries, so
This commit was genuinely broken at the time (not related to our build system): scripts/config/mkconfigs.c (2005-08-01 - 2006-10-05 arasi) uretilen bbconfigopts.h icine .config satirlarini kacissiz, ham newline'larla gömüyordu - gecerli C degildi, busybox'un kendi bb_mkdep araci bile parse edemiyordu (7d219aab7 ile duzeltildi, mkconfigs shell scripte cevrildi)
No binary (build failed)
—
(log yok)
| @@ -19,6 +19,7 @@ | |
| #include <fcntl.h> | |
| #include <inttypes.h> | |
| #include <netdb.h> | |
| + | #include <signal.h> |
| #include <stdio.h> | |
| #include <stdlib.h> | |
| #include <stdarg.h> | |
| @@ -2105,23 +2105,41 @@ USE_FEATURE_MDEV_CONFIG( \ | |
| " or\n" \ | |
| "$ nameif -c /etc/my_mactab_file\n" \ | |
| - | #ifdef CONFIG_NC_GAPING_SECURITY_HOLE |
| - | # define USAGE_NC_EXEC(a) a |
| + | #if ENABLE_NC_SERVER || ENABLE_NC_EXTRA |
| + | #define NC_BR1 "[" |
| + | #define NC_BR2 "]" |
| #else | |
| - | # define USAGE_NC_EXEC(a) |
| + | #define NC_BR1 |
| + | #define NC_BR2 |
| #endif | |
| + | |
| #define nc_trivial_usage \ | |
| - | "[OPTIONS] [IP] [port]" |
| + | "[" \ |
| + | NC_BR1 USE_NC_SERVER("-lp")USE_NC_EXTRA("iwf") NC_BR2 \ |
| + | " ["USE_NC_EXTRA("FILENAME|")"{IPADDR PORTNUM}]"USE_NC_EXTRA(" [-e COMMAND]") |
| #define nc_full_usage \ | |
| - | "Netcat opens a pipe to IP:port\n\n" \ |
| - | "Options:\n" \ |
| - | "\t-l\t\tlisten mode, for inbound connects\n" \ |
| - | "\t-p PORT\t\tlocal port number\n" \ |
| - | "\t-i SECS\t\tdelay interval for lines sent\n" \ |
| - | USAGE_NC_EXEC( \ |
| - | "\t-e PROG\t\tprogram to exec after connect (dangerous!)\n" \ |
| + | "Netcat opens a pipe, either to IP:port\n\n" \ |
| + | "Options:" \ |
| + | USE_NC_EXTRA( \ |
| + | "\n\t-e\t\texec rest of command line after connect\n" \ |
| + | "\t-i SECS\t\tdelay interval for lines sent\n" \ |
| + | "\t-w SECS\t\ttimeout for connect\n" \ |
| + | "\t-f filename\tuse file (ala /dev/ttyS0) instead of network" \ |
| ) \ | |
| - | "\t-w SECS\t\ttimeout for connects and final net reads" |
| + | USE_NC_SERVER( \ |
| + | "\n\t-l\t\tlisten mode, for inbound connects\n" \ |
| + | USE_NC_EXTRA("\t\t\t(use -l twice with -e for persistent server)\n") \ |
| + | "\t-p PORT\t\tlocal port number" \ |
| + | ) |
| + | |
| + | |
| + | #define nc_notes_usage "" \ |
| + | USE_NC_EXTRA( \ |
| + | "To use netcat as a terminal emulator on a serial port:\n\n" \ |
| + | "$ stty 115200 -F /dev/ttyS0\n" \ |
| + | "$ stty raw -echo -ctlecho && nc -f /dev/ttyS0\n" \ |
| + | ) "" |
| + | |
| #define nc_example_usage \ | |
| "$ nc foobar.somedomain.com 25\n" \ | |
| "220 foobar ESMTP Exim 3.12 #1 Sat, 15 Apr 2000 00:03:02 -0600\n" \ | |
| @@ -446,13 +446,21 @@ config CONFIG_NC | |
| A simple Unix utility which reads and writes data across network | |
| connections. | |
| - | config CONFIG_NC_GAPING_SECURITY_HOLE |
| - | bool "gaping security hole" |
| + | config CONFIG_NC_SERVER |
| + | bool "Netcat server options (-lp)" |
| default n | |
| depends on CONFIG_NC | |
| help | |
| - | Add support for executing a program after making or receiving a |
| - | successful connection (-e option). |
| + | Allow netcat to act as a server. |
| + | |
| + | config CONFIG_NC_EXTRA |
| + | bool "Netcat extensions (-eiw and filename)" |
| + | default n |
| + | depends on CONFIG_NC |
| + | help |
| + | Add -e (support for executing the rest of the command line after |
| + | making or receiving a successful connection), -i (delay interval for |
| + | lines sent), -w (timeout for initial connection). |
| config CONFIG_NETSTAT | |
| bool "netstat" | |
| @@ -1,32 +1,16 @@ | |
| /* vi: set sw=4 ts=4: */ | |
| /* nc: mini-netcat - built from the ground up for LRP | |
| - | Copyright (C) 1998 Charles P. Wright |
| - | |
| - | 0.0.1 6K It works. |
| - | 0.0.2 5K Smaller and you can also check the exit condition if you wish. |
| - | 0.0.3 Uses select() |
| - | |
| - | 19980918 Busy Boxed! Dave Cinege |
| - | 19990512 Uses Select. Charles P. Wright |
| - | 19990513 Fixes stdin stupidity and uses buffers. Charles P. Wright |
| - | |
| - | Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
| - | */ |
| - | |
| - | #include <stdio.h> |
| - | #include <stdlib.h> |
| - | #include <string.h> |
| - | #include <unistd.h> |
| - | #include <signal.h> |
| - | |
| - | #include <sys/types.h> |
| - | #include <sys/socket.h> |
| - | #include <netinet/in.h> |
| - | #include <arpa/inet.h> |
| - | #include <netdb.h> |
| - | #include <sys/ioctl.h> |
| + | * |
| + | * Copyright (C) 1998, 1999 Charles P. Wright |
| + | * Copyright (C) 1998 Dave Cinege |
| + | * |
| + | * Licensed under GPLv2 or later, see file LICENSE in this tarball for details. |
| + | */ |
| + | |
| #include "busybox.h" | |
| + | #define xread bb_xread |
| + | |
| static void timeout(int signum) | |
| { | |
| bb_error_msg_and_die("Timed out"); | |
| @@ -34,79 +18,87 @@ static void timeout(int signum) | |
| int nc_main(int argc, char **argv) | |
| { | |
| - | int do_listen = 0, lport = 0, delay = 0, wsecs = 0, tmpfd, opt, sfd, x; |
| - | |
| - | #ifdef CONFIG_NC_GAPING_SECURITY_HOLE |
| - | char *pr00gie = NULL; |
| - | #endif |
| - | |
| + | int do_listen = 0, lport = 0, delay = 0, wsecs = 0, execflag = 0, opt, |
| + | sfd = 0, cfd; |
| struct sockaddr_in address; | |
| struct hostent *hostinfo; | |
| - | |
| fd_set readfds, testfds; | |
| + | char *infile = NULL; |
| - | while ((opt = getopt(argc, argv, "lp:i:e:w:")) > 0) { |
| - | switch (opt) { |
| - | case 'l': |
| - | do_listen++; |
| - | break; |
| - | case 'p': |
| + | memset(&address, 0, sizeof(address)); |
| + | |
| + | if (ENABLE_NC_SERVER || ENABLE_NC_EXTRA) { |
| + | while ((opt = getopt(argc, argv, "lp:" USE_NC_EXTRA("i:ew:f:"))) > 0) { |
| + | if (ENABLE_NC_SERVER && opt=='l') do_listen++; |
| + | else if (ENABLE_NC_SERVER && opt=='p') |
| lport = bb_lookup_port(optarg, "tcp", 0); | |
| + | else if (ENABLE_NC_EXTRA && opt=='w') wsecs = atoi(optarg); |
| + | else if (ENABLE_NC_EXTRA && opt=='i') delay = atoi(optarg); |
| + | else if (ENABLE_NC_EXTRA && opt=='f') infile = optarg; |
| + | else if (ENABLE_NC_EXTRA && opt=='e' && optind!=argc) { |
| + | execflag++; |
| break; | |
| - | case 'i': |
| - | delay = atoi(optarg); |
| - | break; |
| - | #ifdef CONFIG_NC_GAPING_SECURITY_HOLE |
| - | case 'e': |
| - | pr00gie = optarg; |
| - | break; |
| - | #endif |
| - | case 'w': |
| - | wsecs = atoi(optarg); |
| - | break; |
| - | default: |
| - | bb_show_usage(); |
| + | } else bb_show_usage(); |
| } | |
| } | |
| - | if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc)) |
| - | bb_show_usage(); |
| + | |
| + | // For listen or file we need zero arguments, dialout is 2. |
| + | // For exec we need at least one more argument at the end, more ok |
| - | sfd = bb_xsocket(AF_INET, SOCK_STREAM, 0); |
| - | x = 1; |
| - | if (setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &x, sizeof (x)) == -1) |
| - | bb_perror_msg_and_die("reuseaddr"); |
| - | address.sin_family = AF_INET; |
| + | opt = (do_listen || infile) ? 0 : 2 + execflag; |
| + | if (execflag ? argc-optind < opt : argc-optind!=opt || |
| + | (infile && do_listen)) |
| + | bb_show_usage(); |
| if (wsecs) { | |
| signal(SIGALRM, timeout); | |
| alarm(wsecs); | |
| } | |
| + | |
| + | if (infile) cfd = bb_xopen(infile, O_RDWR); |
| + | else { |
| + | opt = 1; |
| + | sfd = bb_xsocket(AF_INET, SOCK_STREAM, 0); |
| + | fcntl(sfd, F_SETFD, FD_CLOEXEC); |
| + | setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof (opt)); |
| + | address.sin_family = AF_INET; |
| - | if (lport != 0) { |
| - | memset(&address.sin_addr, 0, sizeof(address.sin_addr)); |
| - | address.sin_port = lport; |
| + | // Set local port. |
| - | bb_xbind(sfd, (struct sockaddr *) &address, sizeof(address)); |
| - | } |
| + | if (lport != 0) { |
| + | address.sin_port = lport; |
| + | |
| + | bb_xbind(sfd, (struct sockaddr *) &address, sizeof(address)); |
| + | } |
| + | |
| + | if (do_listen) { |
| + | socklen_t addrlen = sizeof(address); |
| + | |
| + | bb_xlisten(sfd, do_listen); |
| - | if (do_listen) { |
| - | socklen_t addrlen = sizeof(address); |
| + | // If we didn't specify a port number, query and print it to stderr. |
| - | bb_xlisten(sfd, 1); |
| - | if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0) |
| - | bb_perror_msg_and_die("accept"); |
| + | if (!lport) { |
| + | socklen_t len = sizeof(address); |
| + | getsockname(sfd, &address, &len); |
| + | fdprintf(2, "%d\n", SWAP_BE16(address.sin_port)); |
| + | } |
| + | repeatyness: |
| + | if ((cfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0) |
| + | bb_perror_msg_and_die("accept"); |
| - | close(sfd); |
| - | sfd = tmpfd; |
| - | } else { |
| - | hostinfo = xgethostbyname(argv[optind]); |
| + | if (!execflag) close(sfd); |
| + | } else { |
| + | hostinfo = xgethostbyname(argv[optind]); |
| - | address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; |
| - | address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0); |
| + | address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; |
| + | address.sin_port = bb_lookup_port(argv[optind+1], "tcp", 0); |
| - | if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) |
| - | bb_perror_msg_and_die("connect"); |
| + | if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) |
| + | bb_perror_msg_and_die("connect"); |
| + | cfd = sfd; |
| + | } |
| } | |
| if (wsecs) { | |
| @@ -114,24 +106,40 @@ int nc_main(int argc, char **argv) | |
| signal(SIGALRM, SIG_DFL); | |
| } | |
| - | #ifdef CONFIG_NC_GAPING_SECURITY_HOLE |
| /* -e given? */ | |
| - | if (pr00gie) { |
| - | dup2(sfd, 0); |
| - | close(sfd); |
| + | if (execflag) { |
| + | if(cfd) { |
| + | signal(SIGCHLD, SIG_IGN); |
| + | dup2(cfd, 0); |
| + | close(cfd); |
| + | } |
| dup2(0, 1); | |
| dup2(0, 2); | |
| - | execl(pr00gie, pr00gie, NULL); |
| + | |
| + | // With more than one -l, repeatedly act as server. |
| + | |
| + | if (do_listen>1 && vfork()) { |
| + | // This is a bit weird as cleanup goes, since we wind up with no |
| + | // stdin/stdout/stderr. But it's small and shouldn't hurt anything. |
| + | // We check for cfd == 0 above. |
| + | close(0); |
| + | close(1); |
| + | close(2); |
| + | |
| + | goto repeatyness; |
| + | } |
| + | execvp(argv[optind], argv+optind); |
| /* Don't print stuff or it will go over the wire.... */ | |
| - | _exit(-1); |
| + | _exit(127); |
| } | |
| - | #endif /* CONFIG_NC_GAPING_SECURITY_HOLE */ |
| + | // Select loop copying stdin to cfd, and cfd to stdout. |
| + | |
| FD_ZERO(&readfds); | |
| - | FD_SET(sfd, &readfds); |
| + | FD_SET(cfd, &readfds); |
| FD_SET(STDIN_FILENO, &readfds); | |
| - | while (1) { |
| + | for (;;) { |
| int fd; | |
| int ofd; | |
| int nread; | |
| @@ -143,30 +151,24 @@ int nc_main(int argc, char **argv) | |
| for (fd = 0; fd < FD_SETSIZE; fd++) { | |
| if (FD_ISSET(fd, &testfds)) { | |
| - | if ((nread = safe_read(fd, bb_common_bufsiz1, |
| - | sizeof(bb_common_bufsiz1))) < 0) |
| - | { |
| - | bb_perror_msg_and_die(bb_msg_read_error); |
| - | } |
| + | nread = xread(fd, bb_common_bufsiz1, sizeof(bb_common_bufsiz1)); |
| - | if (fd == sfd) { |
| - | if (nread == 0) |
| - | exit(0); |
| + | if (fd == cfd) { |
| + | if (!nread) exit(0); |
| ofd = STDOUT_FILENO; | |
| } else { | |
| - | if (nread <= 0) { |
| - | shutdown(sfd, 1 /* send */ ); |
| - | close(STDIN_FILENO); |
| + | if (!nread) { |
| + | // Close outgoing half-connection so they get EOF, but |
| + | // leave incoming alone so we can see response. |
| + | shutdown(cfd, 1); |
| FD_CLR(STDIN_FILENO, &readfds); | |
| } | |
| - | ofd = sfd; |
| + | ofd = cfd; |
| } | |
| if (bb_full_write(ofd, bb_common_bufsiz1, nread) < 0) | |
| bb_perror_msg_and_die(bb_msg_write_error); | |
| - | if (delay > 0) { |
| - | sleep(delay); |
| - | } |
| + | if (delay > 0) sleep(delay); |
| } | |
| } | |
| } | |