X-Git-Url: https://git.librecmc.org/?a=blobdiff_plain;f=nc.c;h=72439dd85d72c9daa1947824adcc7477861b2810;hb=a283157c3832f151fa9f5abf5f18c56d05e5815d;hp=b6afe6ffad4a80549a5abcae0f5a4a8ca848d690;hpb=be84cd4ef66f8956eb4c7ff0542fd1ba823a70e7;p=oweals%2Fbusybox.git diff --git a/nc.c b/nc.c index b6afe6ffa..72439dd85 100644 --- a/nc.c +++ b/nc.c @@ -25,9 +25,10 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ -#include "internal.h" + #include #include +#include #include #include @@ -37,57 +38,70 @@ #include #include #include - -#define BUFSIZE 100 - -static const char nc_usage[] = "nc [IP] [port]\n" -#ifndef BB_FEATURE_TRIVIAL_HELP - "\nNetcat opens a pipe to IP:port\n" -#endif - ; +#include "busybox.h" int nc_main(int argc, char **argv) { - int sfd; - int result; - int len; - char ch[BUFSIZE]; + int do_listen = 0, lport = 0, tmpfd, opt, sfd; + char buf[BUFSIZ]; struct sockaddr_in address; struct hostent *hostinfo; fd_set readfds, testfds; - argc--; - argv++; - if (argc < 2 || **(argv + 1) == '-') { - usage(nc_usage); + while ((opt = getopt(argc, argv, "lp:")) > 0) { + switch (opt) { + case 'l': + do_listen++; + break; + case 'p': + lport = atoi(optarg); + break; + default: + show_usage(); + } } - sfd = socket(AF_INET, SOCK_STREAM, 0); + if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc)) + show_usage(); - hostinfo = (struct hostent *) gethostbyname(*argv); + if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) + perror_msg_and_die("socket"); - if (!hostinfo) { - fatalError("cannot resolve %s\n", *argv); + address.sin_family = AF_INET; + + if (lport != 0) { + memset(&address.sin_addr, 0, sizeof(address.sin_addr)); + address.sin_port = htons(lport); + + if (bind(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) + perror_msg_and_die("bind"); } - address.sin_family = AF_INET; - address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; - address.sin_port = htons(atoi(*(++argv))); + if (do_listen) { + if (listen(sfd, 1) < 0) + perror_msg_and_die("listen"); - len = sizeof(address); + if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &opt)) < 0) + perror_msg_and_die("accept"); - result = connect(sfd, (struct sockaddr *) &address, len); + close(sfd); + sfd = tmpfd; + } else { + if ((hostinfo = gethostbyname(argv[optind])) == NULL) + error_msg_and_die("cannot resolve %s\n", argv[optind]); - if (result < 0) { - perror("nc: connect"); - exit(2); + address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; + address.sin_port = htons(atoi(argv[optind+1])); + + if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) + perror_msg_and_die("connect"); } FD_ZERO(&readfds); FD_SET(sfd, &readfds); - FD_SET(fileno(stdin), &readfds); + FD_SET(STDIN_FILENO, &readfds); while (1) { int fd; @@ -96,39 +110,26 @@ int nc_main(int argc, char **argv) testfds = readfds; - result = - select(FD_SETSIZE, &testfds, (fd_set *) NULL, (fd_set *) NULL, - (struct timeval *) 0); - - if (result < 1) { - perror("nc: select"); - exit(3); - } + if (select(FD_SETSIZE, &testfds, NULL, NULL, NULL) < 0) + perror_msg_and_die("select"); for (fd = 0; fd < FD_SETSIZE; fd++) { if (FD_ISSET(fd, &testfds)) { - int trn = 0; - int rn; - - ioctl(fd, FIONREAD, &nread); + if ((nread = safe_read(fd, buf, sizeof(buf))) < 0) + perror_msg_and_die("read"); if (fd == sfd) { if (nread == 0) exit(0); - ofd = fileno(stdout); + ofd = STDOUT_FILENO; } else { + if (nread == 0) + shutdown(sfd, 1); ofd = sfd; } - - - do { - rn = (BUFSIZE < nread - trn) ? BUFSIZE : nread - trn; - trn += rn; - read(fd, ch, rn); - write(ofd, ch, rn); - } - while (trn < nread); + if (full_write(ofd, buf, nread) < 0) + perror_msg_and_die("write"); } } }