/* * Sean Middleditch * sean@sourcemud.org * * The author or authors of this code dedicate any and all copyright interest * in this code to the public domain. We make this dedication for the benefit * of the public at large and to the detriment of our heirs and successors. We * intend this dedication to be an overt act of relinquishment in perpetuity of * all present and future rights to this code under copyright law. */ #include #include #include #include #include #include #include #include #include #include #include #ifdef HAVE_ZLIB #include "zlib.h" #endif #include "libtelnet.h" static void _send(int sock, unsigned char *buffer, unsigned int size) { int rs; /* send data */ while (size > 0) { if ((rs = send(sock, buffer, size, 0)) == -1) { fprintf(stderr, "send() failed: %s\n", strerror(errno)); exit(1); } else if (rs == 0) { fprintf(stderr, "send() unexpectedly returned 0\n"); exit(1); } /* update pointer and size to see if we've got more to send */ buffer += rs; size -= rs; } } static void _event_handler(struct libtelnet_t *telnet, struct libtelnet_event_t *ev, void *user_data) { int sock = *(int*)user_data; switch (ev->type) { /* data received */ case LIBTELNET_EV_DATA: write(STDOUT_FILENO, ev->buffer, ev->size); break; /* data must be sent */ case LIBTELNET_EV_SEND: _send(sock, ev->buffer, ev->size); break; /* accept any options we want */ case LIBTELNET_EV_NEGOTIATE: /* enable COMPRESS2 */ if (ev->command == LIBTELNET_WILL && ev->telopt == LIBTELNET_TELOPT_COMPRESS2) libtelnet_send_negotiate(telnet, LIBTELNET_DO, ev->telopt); break; /* error */ case LIBTELNET_EV_ERROR: fprintf(stderr, "ERROR: %.*s\n", ev->size, ev->buffer); exit(1); default: /* ignore */ break; } } int main(int argc, char **argv) { unsigned char buffer[512]; int rs; int sock; struct sockaddr_in addr; struct pollfd pfd[2]; struct libtelnet_t telnet; struct addrinfo *ai; struct addrinfo hints; /* check usage */ if (argc != 3) { fprintf(stderr, "Usage:\n ./telnet-client \n"); return 1; } /* look up server host */ memset(&hints, 0, sizeof(hints)); hints.ai_family = AF_UNSPEC; hints.ai_socktype = SOCK_STREAM; if ((rs = getaddrinfo(argv[1], argv[2], &hints, &ai)) != 0) { fprintf(stderr, "getaddrinfo() failed for %s: %s\n", argv[1], gai_strerror(rs)); return 1; } /* create server socket */ if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) { fprintf(stderr, "socket() failed: %s\n", strerror(errno)); return 1; } /* bind server socket */ memset(&addr, 0, sizeof(addr)); addr.sin_family = AF_INET; if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) { fprintf(stderr, "bind() failed: %s\n", strerror(errno)); return 1; } /* connect */ if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) { fprintf(stderr, "server() failed: %s\n", strerror(errno)); return 1; } /* free address lookup info */ freeaddrinfo(ai); /* initialize telnet box */ libtelnet_init(&telnet, _event_handler, LIBTELNET_MODE_CLIENT, &sock); /* initialize poll descriptors */ memset(pfd, 0, sizeof(pfd)); pfd[0].fd = STDIN_FILENO; pfd[0].events = POLLIN; pfd[1].fd = sock; pfd[1].events = POLLIN; /* loop while both connections are open */ while (poll(pfd, 2, -1) != -1) { /* read from stdin */ if (pfd[0].revents & POLLIN) { if ((rs = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) { libtelnet_send_data(&telnet, buffer, rs); } else if (rs == 0) { break; } else { fprintf(stderr, "recv(server) failed: %s\n", strerror(errno)); exit(1); } } /* read from client */ if (pfd[1].revents & POLLIN) { if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) { libtelnet_push(&telnet, buffer, rs); } else if (rs == 0) { break; } else { fprintf(stderr, "recv(client) failed: %s\n", strerror(errno)); exit(1); } } } /* clean up */ libtelnet_free(&telnet); close(sock); return 0; }