1/* vi: set sw=4 ts=4: */ 2/* nc: mini-netcat - built from the ground up for LRP 3 Copyright (C) 1998 Charles P. Wright 4 5 0.0.1 6K It works. 6 0.0.2 5K Smaller and you can also check the exit condition if you wish. 7 0.0.3 Uses select() 8 9 19980918 Busy Boxed! Dave Cinege 10 19990512 Uses Select. Charles P. Wright 11 19990513 Fixes stdin stupidity and uses buffers. Charles P. Wright 12 13 This program is free software; you can redistribute it and/or modify 14 it under the terms of the GNU General Public License as published by 15 the Free Software Foundation; either version 2 of the License, or 16 (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, 19 but WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 21 GNU General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 26 27*/ 28 29#include <stdio.h> 30#include <stdlib.h> 31#include <string.h> 32#include <unistd.h> 33 34#include <sys/types.h> 35#include <sys/socket.h> 36#include <netinet/in.h> 37#include <arpa/inet.h> 38#include <netdb.h> 39#include <sys/time.h> 40#include <sys/ioctl.h> 41#include "busybox.h" 42 43int nc_main(int argc, char **argv) 44{ 45 int do_listen = 0, lport = 0, tmpfd, opt, sfd; 46 char buf[BUFSIZ]; 47 48 struct sockaddr_in address; 49 struct hostent *hostinfo; 50 51 fd_set readfds, testfds; 52 53 while ((opt = getopt(argc, argv, "lp:")) > 0) { 54 switch (opt) { 55 case 'l': 56 do_listen++; 57 break; 58 case 'p': 59 lport = atoi(optarg); 60 break; 61 default: 62 show_usage(); 63 } 64 } 65 66 if ((do_listen && optind != argc) || (!do_listen && optind + 2 != argc)) 67 show_usage(); 68 69 if ((sfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) 70 perror_msg_and_die("socket"); 71 72 address.sin_family = AF_INET; 73 74 if (lport != 0) { 75 memset(&address.sin_addr, 0, sizeof(address.sin_addr)); 76 address.sin_port = htons(lport); 77 78 if (bind(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) 79 perror_msg_and_die("bind"); 80 } 81 82 if (do_listen) { 83 socklen_t addrlen = sizeof(address); 84 85 if (listen(sfd, 1) < 0) 86 perror_msg_and_die("listen"); 87 88 if ((tmpfd = accept(sfd, (struct sockaddr *) &address, &addrlen)) < 0) 89 perror_msg_and_die("accept"); 90 91 close(sfd); 92 sfd = tmpfd; 93 } else { 94 hostinfo = xgethostbyname(argv[optind]); 95 96 address.sin_addr = *(struct in_addr *) *hostinfo->h_addr_list; 97 address.sin_port = htons(atoi(argv[optind+1])); 98 99 if (connect(sfd, (struct sockaddr *) &address, sizeof(address)) < 0) 100 perror_msg_and_die("connect"); 101 } 102 103 FD_ZERO(&readfds); 104 FD_SET(sfd, &readfds); 105 FD_SET(STDIN_FILENO, &readfds); 106 107 while (1) { 108 int fd; 109 int ofd; 110 int nread; 111 112 testfds = readfds; 113 114 if (select(FD_SETSIZE, &testfds, NULL, NULL, NULL) < 0) 115 perror_msg_and_die("select"); 116 117 for (fd = 0; fd < FD_SETSIZE; fd++) { 118 if (FD_ISSET(fd, &testfds)) { 119 if ((nread = safe_read(fd, buf, sizeof(buf))) < 0) 120 perror_msg_and_die("read"); 121 122 if (fd == sfd) { 123 if (nread == 0) 124 exit(0); 125 ofd = STDOUT_FILENO; 126 } else { 127 if (nread == 0) 128 shutdown(sfd, 1); 129 ofd = sfd; 130 } 131 132 if (full_write(ofd, buf, nread) < 0) 133 perror_msg_and_die("write"); 134 } 135 } 136 } 137} 138