/* * $Id$ */ #include #include #include #include #include #include #include #include #include #include #include const int BUFSIZE=(4 * 1024); int create_tcp_connection(const char * host, int port, const int timeout) { int s; int c; struct hostent *hent; struct sockaddr_in saddr; memset(&saddr, 0, sizeof(saddr)); saddr.sin_family = AF_INET; if((hent = gethostbyname(host)) == NULL) { fprintf(stderr, "invalid hostname %s\n", host); return -1; } memcpy(&saddr.sin_addr, hent->h_addr, hent->h_length); saddr.sin_port = htons(port); s = socket(AF_INET, SOCK_STREAM, 0); if ( s < 0) { return -1; } if(connect(s, (struct sockaddr *)&saddr, sizeof(saddr)) < 0) { fprintf(stderr, "can't connect to %s %d\n", host, port); return -1; } return s; } int is_ready(int fd, int what, int timeout) { struct pollfd pfd[1]; int res; int now = time(NULL); int endtime = now + timeout; assert(timeout >= 0); do { pfd[0].fd = fd; pfd[0].events = what; res = poll(pfd, 1, (endtime - now) * 1000); if ( res > 0 && (pfd[0].revents | what)) { //fprintf(stderr, "[%d] poll %d is ready\n", getpid(), fd); return 1; } now = time(NULL); } while( now < endtime); return 0; } int copydata(int in_fd, int out_fd, int timeout) { char buffer[BUFSIZE]; int res; long flags = 0; // set nto nonblocking io if ((flags = fcntl(in_fd, F_GETFL)) == -1) { fprintf(stderr, "can't get flags"); return -1; } if( fcntl(in_fd, F_SETFL, flags | O_NONBLOCK) == -1) { fprintf(stderr, "can't set NONBLOCKING IO flags"); return -1; } while(1) { if ( ! is_ready (in_fd, POLLIN, timeout)) { //fprintf(stderr, "is not ready ...."); return -1; } // there are data to read .... res = read(in_fd, buffer, BUFSIZE); if( res < 0) { //fprintf(stderr, "read .... %d\n", res); continue; } if(res == 0) { //fprintf(stderr, "read .... %d\n", res); return res; } if(write(out_fd, buffer, res) != res) { //fprintf(stderr, "write error ...."); return -1; } } } int main(int argc, char *argv[]) { int pid; int s; char * host; int port; int timeout; if (argc != 4) { fprintf(stderr, "usage %s host port timeout\n", argv[0]); exit(1); } host = argv[1]; port = atoi(argv[2]); timeout = atoi(argv[3]); assert( port > 0); assert( port < 65536); assert( timeout > 0); assert( timeout < (24 * 60 * 60)); s = create_tcp_connection(host, port, timeout); if (s < 0) { fprintf(stderr, "can't establich connection to %s %d", host, port); exit(1); } if((pid = fork()) < 0) { fprintf(stderr, "can't fork"); exit(1); } if (pid == 0) { close(1); copydata(0,s, timeout); close(s); kill(getppid(), SIGTERM); } else { close(0); copydata(s, 1, timeout); close(s); kill(pid, SIGTERM); } exit(0); }