blob: b8e1a693248a3b150d82603d0e6c4f60979a6647 [file] [log] [blame]
Sean Middleditchda394be2009-03-15 14:19:40 -04001/*
2 * Sean Middleditch
3 * sean@sourcemud.org
4 *
5 * The author or authors of this code dedicate any and all copyright interest
6 * in this code to the public domain. We make this dedication for the benefit
7 * of the public at large and to the detriment of our heirs and successors. We
8 * intend this dedication to be an overt act of relinquishment in perpetuity of
9 * all present and future rights to this code under copyright law.
10 */
11
12#include <sys/socket.h>
13#include <netinet/in.h>
14#include <arpa/inet.h>
15#include <netdb.h>
16#include <poll.h>
17#include <errno.h>
18#include <stdio.h>
19#include <string.h>
20#include <stdlib.h>
21#include <ctype.h>
22#include <unistd.h>
23
24#ifdef HAVE_ZLIB
25#include "zlib.h"
26#endif
27
28#include "libtelnet.h"
29
30static void _send(int sock, unsigned char *buffer, unsigned int size) {
31 int rs;
32
33 /* send data */
34 while (size > 0) {
35 if ((rs = send(sock, buffer, size, 0)) == -1) {
36 fprintf(stderr, "send() failed: %s\n", strerror(errno));
37 exit(1);
38 } else if (rs == 0) {
39 fprintf(stderr, "send() unexpectedly returned 0\n");
40 exit(1);
41 }
42
43 /* update pointer and size to see if we've got more to send */
44 buffer += rs;
45 size -= rs;
46 }
47}
48
49static void _event_handler(struct libtelnet_t *telnet,
50 struct libtelnet_event_t *ev, void *user_data) {
51 int sock = *(int*)user_data;
52
53 switch (ev->type) {
54 /* data received */
55 case LIBTELNET_EV_DATA:
56 write(STDOUT_FILENO, ev->buffer, ev->size);
57 break;
58 /* data must be sent */
59 case LIBTELNET_EV_SEND:
60 _send(sock, ev->buffer, ev->size);
61 break;
62 /* accept any options we want */
63 case LIBTELNET_EV_NEGOTIATE:
64 /* enable COMPRESS2 */
65 if (ev->command == LIBTELNET_WILL &&
66 ev->telopt == LIBTELNET_TELOPT_COMPRESS2)
67 libtelnet_send_negotiate(telnet, LIBTELNET_DO, ev->telopt);
68 break;
69 /* error */
70 case LIBTELNET_EV_ERROR:
71 fprintf(stderr, "ERROR: %.*s\n", ev->size, ev->buffer);
72 exit(1);
73 default:
74 /* ignore */
75 break;
76 }
77}
78
79int main(int argc, char **argv) {
80 unsigned char buffer[512];
81 int rs;
82 int sock;
83 struct sockaddr_in addr;
84 struct pollfd pfd[2];
85 struct libtelnet_t telnet;
86 struct addrinfo *ai;
87 struct addrinfo hints;
88
89 /* check usage */
90 if (argc != 3) {
91 fprintf(stderr, "Usage:\n ./telnet-client <host> <port>\n");
92 return 1;
93 }
94
95 /* look up server host */
96 memset(&hints, 0, sizeof(hints));
97 hints.ai_family = AF_UNSPEC;
98 hints.ai_socktype = SOCK_STREAM;
99 if ((rs = getaddrinfo(argv[1], argv[2], &hints, &ai)) != 0) {
100 fprintf(stderr, "getaddrinfo() failed for %s: %s\n", argv[1],
101 gai_strerror(rs));
102 return 1;
103 }
104
105 /* create server socket */
106 if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1) {
107 fprintf(stderr, "socket() failed: %s\n", strerror(errno));
108 return 1;
109 }
110
111 /* bind server socket */
112 memset(&addr, 0, sizeof(addr));
113 addr.sin_family = AF_INET;
114 if (bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1) {
115 fprintf(stderr, "bind() failed: %s\n", strerror(errno));
116 return 1;
117 }
118
119 /* connect */
120 if (connect(sock, ai->ai_addr, ai->ai_addrlen) == -1) {
121 fprintf(stderr, "server() failed: %s\n", strerror(errno));
122 return 1;
123 }
124
125 /* free address lookup info */
126 freeaddrinfo(ai);
127
128 /* initialize telnet box */
129 libtelnet_init(&telnet, _event_handler, LIBTELNET_MODE_CLIENT, &sock);
130
131 /* initialize poll descriptors */
132 memset(pfd, 0, sizeof(pfd));
133 pfd[0].fd = STDIN_FILENO;
134 pfd[0].events = POLLIN;
135 pfd[1].fd = sock;
136 pfd[1].events = POLLIN;
137
138 /* loop while both connections are open */
139 while (poll(pfd, 2, -1) != -1) {
140 /* read from stdin */
141 if (pfd[0].revents & POLLIN) {
142 if ((rs = read(STDIN_FILENO, buffer, sizeof(buffer))) > 0) {
143 libtelnet_send_data(&telnet, buffer, rs);
144 } else if (rs == 0) {
145 break;
146 } else {
147 fprintf(stderr, "recv(server) failed: %s\n",
148 strerror(errno));
149 exit(1);
150 }
151 }
152
153 /* read from client */
154 if (pfd[1].revents & POLLIN) {
155 if ((rs = recv(sock, buffer, sizeof(buffer), 0)) > 0) {
156 libtelnet_push(&telnet, buffer, rs);
157 } else if (rs == 0) {
158 break;
159 } else {
160 fprintf(stderr, "recv(client) failed: %s\n",
161 strerror(errno));
162 exit(1);
163 }
164 }
165 }
166
167 /* clean up */
168 libtelnet_free(&telnet);
169 close(sock);
170
171 return 0;
172}