1 | /*
|
---|
2 | ttn.c
|
---|
3 | */
|
---|
4 |
|
---|
5 | #ifndef _POSIX_SOURCE
|
---|
6 | #define _POSIX_SOURCE 1
|
---|
7 | #endif
|
---|
8 |
|
---|
9 | #include <sys/types.h>
|
---|
10 | #include <sys/ioctl.h>
|
---|
11 | #include <assert.h>
|
---|
12 | #include <errno.h>
|
---|
13 | #include <fcntl.h>
|
---|
14 | #include <termios.h>
|
---|
15 | #include <signal.h>
|
---|
16 | #include <stdarg.h>
|
---|
17 | #include <stdio.h>
|
---|
18 | #include <stdlib.h>
|
---|
19 | #include <string.h>
|
---|
20 | #include <unistd.h>
|
---|
21 | #include <net/hton.h>
|
---|
22 | #include <net/netlib.h>
|
---|
23 | #include <net/gen/in.h>
|
---|
24 | #include <net/gen/inet.h>
|
---|
25 | #include <net/gen/netdb.h>
|
---|
26 | #include <net/gen/tcp.h>
|
---|
27 | #include <net/gen/tcp_io.h>
|
---|
28 | #include "ttn.h"
|
---|
29 |
|
---|
30 | #if __STDC__
|
---|
31 | #define PROTOTYPE(func,args) func args
|
---|
32 | #else
|
---|
33 | #define PROTOTYPE(func,args) func()
|
---|
34 | #endif
|
---|
35 |
|
---|
36 | static int do_read(int fd, char *buf, unsigned len);
|
---|
37 | static void screen(void);
|
---|
38 | static void keyboard(void);
|
---|
39 | static void send_brk(void);
|
---|
40 | static int process_opt (char *bp, int count);
|
---|
41 | static void do_option (int optsrt);
|
---|
42 | static void dont_option (int optsrt);
|
---|
43 | static void will_option (int optsrt);
|
---|
44 | static void wont_option (int optsrt);
|
---|
45 | static int writeall (int fd, char *buffer, int buf_size);
|
---|
46 | static int sb_termtype (char *sb, int count);
|
---|
47 | static void fatal(char *fmt, ...);
|
---|
48 | static void usage(void);
|
---|
49 |
|
---|
50 | #if DEBUG
|
---|
51 | #define where() (fprintf(stderr, "%s %d:", __FILE__, __LINE__))
|
---|
52 | #endif
|
---|
53 |
|
---|
54 | static char *prog_name;
|
---|
55 | static tcp_fd;
|
---|
56 | static char *term_env;
|
---|
57 | static int esc_char= '~';
|
---|
58 | static enum { LS_NORM, LS_BOL, LS_ESC } line_state= LS_BOL;
|
---|
59 |
|
---|
60 | int main(int argc, char *argv[])
|
---|
61 | {
|
---|
62 | struct hostent *hostent;
|
---|
63 | struct servent *servent;
|
---|
64 | ipaddr_t host;
|
---|
65 | tcpport_t port;
|
---|
66 | int pid, ppid;
|
---|
67 | nwio_tcpconf_t tcpconf;
|
---|
68 | int c, r;
|
---|
69 | nwio_tcpcl_t tcpconnopt;
|
---|
70 | struct termios termios;
|
---|
71 | char *tcp_device, *remote_name, *port_name;
|
---|
72 | char *e_arg;
|
---|
73 |
|
---|
74 | (prog_name=strrchr(argv[0],'/')) ? prog_name++ : (prog_name=argv[0]);
|
---|
75 |
|
---|
76 | e_arg= NULL;
|
---|
77 | while (c= getopt(argc, argv, "?e:"), c != -1)
|
---|
78 | {
|
---|
79 | switch(c)
|
---|
80 | {
|
---|
81 | case '?': usage();
|
---|
82 | case 'e': e_arg= optarg; break;
|
---|
83 | default:
|
---|
84 | fatal("Optind failed: '%c'", c);
|
---|
85 | }
|
---|
86 | }
|
---|
87 |
|
---|
88 | if (optind >= argc)
|
---|
89 | usage();
|
---|
90 | remote_name= argv[optind++];
|
---|
91 | if (optind < argc)
|
---|
92 | port_name= argv[optind++];
|
---|
93 | else
|
---|
94 | port_name= NULL;
|
---|
95 | if (optind != argc)
|
---|
96 | usage();
|
---|
97 |
|
---|
98 | if (e_arg)
|
---|
99 | {
|
---|
100 | switch(strlen(e_arg))
|
---|
101 | {
|
---|
102 | case 0: esc_char= -1; break;
|
---|
103 | case 1: esc_char= e_arg[0]; break;
|
---|
104 | default: fatal("Invalid escape character '%s'", e_arg);
|
---|
105 | }
|
---|
106 | }
|
---|
107 |
|
---|
108 | hostent= gethostbyname(remote_name);
|
---|
109 | if (!hostent)
|
---|
110 | fatal("Unknown host %s", remote_name);
|
---|
111 | host= *(ipaddr_t *)(hostent->h_addr);
|
---|
112 |
|
---|
113 | if (!port_name)
|
---|
114 | port= htons(TCPPORT_TELNET);
|
---|
115 | else
|
---|
116 | {
|
---|
117 | servent= getservbyname (port_name, "tcp");
|
---|
118 | if (!servent)
|
---|
119 | {
|
---|
120 | port= htons(strtol(port_name, (char **)0, 0));
|
---|
121 | if (!port)
|
---|
122 | fatal("Unknown port %s", port_name);
|
---|
123 | }
|
---|
124 | else
|
---|
125 | port= (tcpport_t)(servent->s_port);
|
---|
126 | }
|
---|
127 |
|
---|
128 | fprintf(stderr, "Connecting to %s:%u...\n",
|
---|
129 | inet_ntoa(host), ntohs(port));
|
---|
130 |
|
---|
131 | tcp_device= getenv("TCP_DEVICE");
|
---|
132 | if (tcp_device == NULL)
|
---|
133 | tcp_device= TCP_DEVICE;
|
---|
134 | tcp_fd= open (tcp_device, O_RDWR);
|
---|
135 | if (tcp_fd == -1)
|
---|
136 | fatal("Unable to open %s: %s", tcp_device, strerror(errno));
|
---|
137 |
|
---|
138 | tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP;
|
---|
139 | tcpconf.nwtc_remaddr= host;
|
---|
140 | tcpconf.nwtc_remport= port;
|
---|
141 |
|
---|
142 | r= ioctl (tcp_fd, NWIOSTCPCONF, &tcpconf);
|
---|
143 | if (r == -1)
|
---|
144 | fatal("NWIOSTCPCONF failed: %s", strerror(errno));
|
---|
145 |
|
---|
146 | tcpconnopt.nwtcl_flags= 0;
|
---|
147 | do
|
---|
148 | {
|
---|
149 | r= ioctl (tcp_fd, NWIOTCPCONN, &tcpconnopt);
|
---|
150 | if (r == -1 && errno == EAGAIN)
|
---|
151 | {
|
---|
152 | fprintf(stderr, "%s: Got EAGAIN, sleeping(1s)\n",
|
---|
153 | prog_name);
|
---|
154 | sleep(1);
|
---|
155 | }
|
---|
156 | } while (r == -1 && errno == EAGAIN);
|
---|
157 | if (r == -1)
|
---|
158 | fatal("Unable to connect: %s", strerror(errno));
|
---|
159 | printf("Connected\n");
|
---|
160 | ppid= getpid();
|
---|
161 | pid= fork();
|
---|
162 | switch(pid)
|
---|
163 | {
|
---|
164 | case 0:
|
---|
165 | keyboard();
|
---|
166 | #if DEBUG
|
---|
167 | fprintf(stderr, "killing %d with %d\r\n", ppid, SIGKILL);
|
---|
168 | #endif
|
---|
169 | kill(ppid, SIGKILL);
|
---|
170 | break;
|
---|
171 | case -1:
|
---|
172 | fprintf(stderr, "%s: fork failed: %s\r\n", argv[0],
|
---|
173 | strerror(errno));
|
---|
174 | exit(1);
|
---|
175 | break;
|
---|
176 | default:
|
---|
177 | tcgetattr(0, &termios);
|
---|
178 | screen();
|
---|
179 | #if DEBUG
|
---|
180 | fprintf(stderr, "killing %d with %d\r\n", pid, SIGKILL);
|
---|
181 | #endif
|
---|
182 | kill(pid, SIGKILL);
|
---|
183 | tcsetattr(0, TCSANOW, &termios);
|
---|
184 | break;
|
---|
185 | }
|
---|
186 | exit(0);
|
---|
187 | }
|
---|
188 |
|
---|
189 | static int do_read(fd, buf, len)
|
---|
190 | int fd;
|
---|
191 | char *buf;
|
---|
192 | unsigned len;
|
---|
193 | {
|
---|
194 | nwio_tcpopt_t tcpopt;
|
---|
195 | int count;
|
---|
196 |
|
---|
197 | for (;;)
|
---|
198 | {
|
---|
199 | count= read (fd, buf, len);
|
---|
200 | if (count <0)
|
---|
201 | {
|
---|
202 | if (errno == EURG || errno == ENOURG)
|
---|
203 | {
|
---|
204 | /* Toggle urgent mode. */
|
---|
205 | tcpopt.nwto_flags= errno == EURG ?
|
---|
206 | NWTO_RCV_URG : NWTO_RCV_NOTURG;
|
---|
207 | if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) == -1)
|
---|
208 | {
|
---|
209 | return -1;
|
---|
210 | }
|
---|
211 | continue;
|
---|
212 | }
|
---|
213 | return -1;
|
---|
214 | }
|
---|
215 | return count;
|
---|
216 | }
|
---|
217 | }
|
---|
218 |
|
---|
219 | static void screen()
|
---|
220 | {
|
---|
221 | char buffer[1024], *bp, *iacptr;
|
---|
222 | int count, optsize;
|
---|
223 |
|
---|
224 | for (;;)
|
---|
225 | {
|
---|
226 | count= do_read (tcp_fd, buffer, sizeof(buffer));
|
---|
227 | #if DEBUG && 0
|
---|
228 | { where(); fprintf(stderr, "read %d bytes\r\n", count); }
|
---|
229 | #endif
|
---|
230 | if (count <0)
|
---|
231 | {
|
---|
232 | perror ("read");
|
---|
233 | return;
|
---|
234 | }
|
---|
235 | if (!count)
|
---|
236 | return;
|
---|
237 | bp= buffer;
|
---|
238 | do
|
---|
239 | {
|
---|
240 | iacptr= memchr (bp, IAC, count);
|
---|
241 | if (!iacptr)
|
---|
242 | {
|
---|
243 | write(1, bp, count);
|
---|
244 | count= 0;
|
---|
245 | }
|
---|
246 | if (iacptr && iacptr>bp)
|
---|
247 | {
|
---|
248 | #if DEBUG
|
---|
249 | { where(); fprintf(stderr, "iacptr-bp= %d\r\n", iacptr-bp); }
|
---|
250 | #endif
|
---|
251 | write(1, bp, iacptr-bp);
|
---|
252 | count -= (iacptr-bp);
|
---|
253 | bp= iacptr;
|
---|
254 | continue;
|
---|
255 | }
|
---|
256 | if (iacptr)
|
---|
257 | {
|
---|
258 | assert (iacptr == bp);
|
---|
259 | optsize= process_opt(bp, count);
|
---|
260 | #if DEBUG && 0
|
---|
261 | { where(); fprintf(stderr, "process_opt(...)= %d\r\n", optsize); }
|
---|
262 | #endif
|
---|
263 | if (optsize<0)
|
---|
264 | return;
|
---|
265 | assert (optsize);
|
---|
266 | bp += optsize;
|
---|
267 | count -= optsize;
|
---|
268 | }
|
---|
269 | } while (count);
|
---|
270 | }
|
---|
271 | }
|
---|
272 |
|
---|
273 | static void keyboard()
|
---|
274 | {
|
---|
275 | char c, buffer[1024];
|
---|
276 | int count;
|
---|
277 |
|
---|
278 | for (;;)
|
---|
279 | {
|
---|
280 | count= read (0, buffer, 1 /* sizeof(buffer) */);
|
---|
281 | if (count == -1)
|
---|
282 | fatal("Read: %s\r\n", strerror(errno));
|
---|
283 | if (!count)
|
---|
284 | return;
|
---|
285 |
|
---|
286 | if (line_state != LS_NORM)
|
---|
287 | {
|
---|
288 | c= buffer[0];
|
---|
289 | if (line_state == LS_BOL)
|
---|
290 | {
|
---|
291 | if (c == esc_char)
|
---|
292 | {
|
---|
293 | line_state= LS_ESC;
|
---|
294 | continue;
|
---|
295 | }
|
---|
296 | line_state= LS_NORM;
|
---|
297 | }
|
---|
298 | else if (line_state == LS_ESC)
|
---|
299 | {
|
---|
300 | line_state= LS_NORM;
|
---|
301 | if (c == '.')
|
---|
302 | return;
|
---|
303 | if (c == '#')
|
---|
304 | {
|
---|
305 | send_brk();
|
---|
306 | continue;
|
---|
307 | }
|
---|
308 |
|
---|
309 | /* Not a valid command or a repeat of the
|
---|
310 | * escape char
|
---|
311 | */
|
---|
312 | if (c != esc_char)
|
---|
313 | {
|
---|
314 | c= esc_char;
|
---|
315 | write(tcp_fd, &c, 1);
|
---|
316 | }
|
---|
317 | }
|
---|
318 | }
|
---|
319 | if (buffer[0] == '\n')
|
---|
320 | write(tcp_fd, "\r", 1);
|
---|
321 | count= write(tcp_fd, buffer, count);
|
---|
322 | if (buffer[0] == '\r')
|
---|
323 | {
|
---|
324 | line_state= LS_BOL;
|
---|
325 | write(tcp_fd, "\0", 1);
|
---|
326 | }
|
---|
327 | if (count<0)
|
---|
328 | {
|
---|
329 | perror("write");
|
---|
330 | fprintf(stderr, "errno= %d\r\n", errno);
|
---|
331 | return;
|
---|
332 | }
|
---|
333 | if (!count)
|
---|
334 | return;
|
---|
335 | }
|
---|
336 | }
|
---|
337 |
|
---|
338 | static void send_brk(void)
|
---|
339 | {
|
---|
340 | int r;
|
---|
341 | unsigned char buffer[2];
|
---|
342 |
|
---|
343 | buffer[0]= IAC;
|
---|
344 | buffer[1]= IAC_BRK;
|
---|
345 |
|
---|
346 | r= writeall(tcp_fd, (char *)buffer, 2);
|
---|
347 | if (r == -1)
|
---|
348 | fatal("Error writing to TCP connection: %s", strerror(errno));
|
---|
349 | }
|
---|
350 |
|
---|
351 | #define next_char(var) \
|
---|
352 | if (offset<count) { (var) = bp[offset++]; } \
|
---|
353 | else if (do_read(tcp_fd, (char *)&(var), 1) <= 0) \
|
---|
354 | { perror ("read"); return -1; }
|
---|
355 |
|
---|
356 | static int process_opt (char *bp, int count)
|
---|
357 | {
|
---|
358 | unsigned char iac, command, optsrt, sb_command;
|
---|
359 | int offset, result; ;
|
---|
360 | #if DEBUG && 0
|
---|
361 | { where(); fprintf(stderr, "process_opt(bp= 0x%x, count= %d)\r\n",
|
---|
362 | bp, count); }
|
---|
363 | #endif
|
---|
364 |
|
---|
365 | offset= 0;
|
---|
366 | assert (count);
|
---|
367 | next_char(iac);
|
---|
368 | assert (iac == IAC);
|
---|
369 | next_char(command);
|
---|
370 | switch(command)
|
---|
371 | {
|
---|
372 | case IAC_NOP:
|
---|
373 | break;
|
---|
374 | case IAC_DataMark:
|
---|
375 | /* Ought to flush input queue or something. */
|
---|
376 | break;
|
---|
377 | case IAC_BRK:
|
---|
378 | fprintf(stderr, "got a BRK\r\n");
|
---|
379 | break;
|
---|
380 | case IAC_IP:
|
---|
381 | fprintf(stderr, "got a IP\r\n");
|
---|
382 | break;
|
---|
383 | case IAC_AO:
|
---|
384 | fprintf(stderr, "got a AO\r\n");
|
---|
385 | break;
|
---|
386 | case IAC_AYT:
|
---|
387 | fprintf(stderr, "got a AYT\r\n");
|
---|
388 | break;
|
---|
389 | case IAC_EC:
|
---|
390 | fprintf(stderr, "got a EC\r\n");
|
---|
391 | break;
|
---|
392 | case IAC_EL:
|
---|
393 | fprintf(stderr, "got a EL\r\n");
|
---|
394 | break;
|
---|
395 | case IAC_GA:
|
---|
396 | fprintf(stderr, "got a GA\r\n");
|
---|
397 | break;
|
---|
398 | case IAC_SB:
|
---|
399 | next_char(sb_command);
|
---|
400 | switch (sb_command)
|
---|
401 | {
|
---|
402 | case OPT_TERMTYPE:
|
---|
403 | #if DEBUG && 0
|
---|
404 | fprintf(stderr, "got SB TERMINAL-TYPE\r\n");
|
---|
405 | #endif
|
---|
406 | result= sb_termtype(bp+offset, count-offset);
|
---|
407 | if (result<0)
|
---|
408 | return result;
|
---|
409 | else
|
---|
410 | return result+offset;
|
---|
411 | default:
|
---|
412 | fprintf(stderr, "got an unknown SB (skiping)\r\n");
|
---|
413 | for (;;)
|
---|
414 | {
|
---|
415 | next_char(iac);
|
---|
416 | if (iac != IAC)
|
---|
417 | continue;
|
---|
418 | next_char(optsrt);
|
---|
419 | if (optsrt == IAC)
|
---|
420 | continue;
|
---|
421 | if (optsrt != IAC_SE)
|
---|
422 | fprintf(stderr, "got IAC %d\r\n", optsrt);
|
---|
423 | break;
|
---|
424 | }
|
---|
425 | }
|
---|
426 | break;
|
---|
427 | case IAC_WILL:
|
---|
428 | next_char(optsrt);
|
---|
429 | will_option(optsrt);
|
---|
430 | break;
|
---|
431 | case IAC_WONT:
|
---|
432 | next_char(optsrt);
|
---|
433 | wont_option(optsrt);
|
---|
434 | break;
|
---|
435 | case IAC_DO:
|
---|
436 | next_char(optsrt);
|
---|
437 | do_option(optsrt);
|
---|
438 | break;
|
---|
439 | case IAC_DONT:
|
---|
440 | next_char(optsrt);
|
---|
441 | dont_option(optsrt);
|
---|
442 | break;
|
---|
443 | case IAC:
|
---|
444 | fprintf(stderr, "got a IAC\r\n");
|
---|
445 | break;
|
---|
446 | default:
|
---|
447 | fprintf(stderr, "got unknown command (%d)\r\n", command);
|
---|
448 | }
|
---|
449 | return offset;
|
---|
450 | }
|
---|
451 |
|
---|
452 | static void do_option (int optsrt)
|
---|
453 | {
|
---|
454 | unsigned char reply[3];
|
---|
455 | int result;
|
---|
456 |
|
---|
457 | switch (optsrt)
|
---|
458 | {
|
---|
459 | case OPT_TERMTYPE:
|
---|
460 | if (WILL_terminal_type)
|
---|
461 | return;
|
---|
462 | if (!WILL_terminal_type_allowed)
|
---|
463 | {
|
---|
464 | reply[0]= IAC;
|
---|
465 | reply[1]= IAC_WONT;
|
---|
466 | reply[2]= optsrt;
|
---|
467 | }
|
---|
468 | else
|
---|
469 | {
|
---|
470 | WILL_terminal_type= TRUE;
|
---|
471 | term_env= getenv("TERM");
|
---|
472 | if (!term_env)
|
---|
473 | term_env= "unknown";
|
---|
474 | reply[0]= IAC;
|
---|
475 | reply[1]= IAC_WILL;
|
---|
476 | reply[2]= optsrt;
|
---|
477 | }
|
---|
478 | break;
|
---|
479 | default:
|
---|
480 | #if DEBUG
|
---|
481 | fprintf(stderr, "got a DO (%d)\r\n", optsrt);
|
---|
482 | fprintf(stderr, "WONT (%d)\r\n", optsrt);
|
---|
483 | #endif
|
---|
484 | reply[0]= IAC;
|
---|
485 | reply[1]= IAC_WONT;
|
---|
486 | reply[2]= optsrt;
|
---|
487 | break;
|
---|
488 | }
|
---|
489 | result= writeall(tcp_fd, (char *)reply, 3);
|
---|
490 | if (result<0)
|
---|
491 | perror("write");
|
---|
492 | }
|
---|
493 |
|
---|
494 | static void will_option (int optsrt)
|
---|
495 | {
|
---|
496 | unsigned char reply[3];
|
---|
497 | int result;
|
---|
498 |
|
---|
499 | switch (optsrt)
|
---|
500 | {
|
---|
501 | case OPT_ECHO:
|
---|
502 | if (DO_echo)
|
---|
503 | break;
|
---|
504 | if (!DO_echo_allowed)
|
---|
505 | {
|
---|
506 | reply[0]= IAC;
|
---|
507 | reply[1]= IAC_DONT;
|
---|
508 | reply[2]= optsrt;
|
---|
509 | }
|
---|
510 | else
|
---|
511 | {
|
---|
512 | struct termios termios;
|
---|
513 |
|
---|
514 | tcgetattr(0, &termios);
|
---|
515 | termios.c_iflag &= ~(ICRNL|IGNCR|INLCR|IXON|IXOFF);
|
---|
516 | termios.c_oflag &= ~(OPOST);
|
---|
517 | termios.c_lflag &= ~(ECHO|ECHONL|ICANON|IEXTEN|ISIG);
|
---|
518 | tcsetattr(0, TCSANOW, &termios);
|
---|
519 |
|
---|
520 | DO_echo= TRUE;
|
---|
521 | reply[0]= IAC;
|
---|
522 | reply[1]= IAC_DO;
|
---|
523 | reply[2]= optsrt;
|
---|
524 | }
|
---|
525 | result= writeall(tcp_fd, (char *)reply, 3);
|
---|
526 | if (result<0)
|
---|
527 | perror("write");
|
---|
528 | break;
|
---|
529 | case OPT_SUPP_GA:
|
---|
530 | if (DO_suppress_go_ahead)
|
---|
531 | break;
|
---|
532 | if (!DO_suppress_go_ahead_allowed)
|
---|
533 | {
|
---|
534 | reply[0]= IAC;
|
---|
535 | reply[1]= IAC_DONT;
|
---|
536 | reply[2]= optsrt;
|
---|
537 | }
|
---|
538 | else
|
---|
539 | {
|
---|
540 | DO_suppress_go_ahead= TRUE;
|
---|
541 | reply[0]= IAC;
|
---|
542 | reply[1]= IAC_DO;
|
---|
543 | reply[2]= optsrt;
|
---|
544 | }
|
---|
545 | result= writeall(tcp_fd, (char *)reply, 3);
|
---|
546 | if (result<0)
|
---|
547 | perror("write");
|
---|
548 | break;
|
---|
549 | default:
|
---|
550 | #if DEBUG
|
---|
551 | fprintf(stderr, "got a WILL (%d)\r\n", optsrt);
|
---|
552 | fprintf(stderr, "DONT (%d)\r\n", optsrt);
|
---|
553 | #endif
|
---|
554 | reply[0]= IAC;
|
---|
555 | reply[1]= IAC_DONT;
|
---|
556 | reply[2]= optsrt;
|
---|
557 | result= writeall(tcp_fd, (char *)reply, 3);
|
---|
558 | if (result<0)
|
---|
559 | perror("write");
|
---|
560 | break;
|
---|
561 | }
|
---|
562 | }
|
---|
563 |
|
---|
564 | static int writeall (fd, buffer, buf_size)
|
---|
565 | int fd;
|
---|
566 | char *buffer;
|
---|
567 | int buf_size;
|
---|
568 | {
|
---|
569 | int result;
|
---|
570 |
|
---|
571 | while (buf_size)
|
---|
572 | {
|
---|
573 | result= write (fd, buffer, buf_size);
|
---|
574 | if (result <= 0)
|
---|
575 | return -1;
|
---|
576 | assert (result <= buf_size);
|
---|
577 | buffer += result;
|
---|
578 | buf_size -= result;
|
---|
579 | }
|
---|
580 | return 0;
|
---|
581 | }
|
---|
582 |
|
---|
583 | static void dont_option (int optsrt)
|
---|
584 | {
|
---|
585 | switch (optsrt)
|
---|
586 | {
|
---|
587 | default:
|
---|
588 | #if DEBUG
|
---|
589 | fprintf(stderr, "got a DONT (%d)\r\n", optsrt);
|
---|
590 | #endif
|
---|
591 | break;
|
---|
592 | }
|
---|
593 | }
|
---|
594 |
|
---|
595 | static void wont_option (int optsrt)
|
---|
596 | {
|
---|
597 | switch (optsrt)
|
---|
598 | {
|
---|
599 | default:
|
---|
600 | #if DEBUG
|
---|
601 | fprintf(stderr, "got a WONT (%d)\r\n", optsrt);
|
---|
602 | #endif
|
---|
603 | break;
|
---|
604 | }
|
---|
605 | }
|
---|
606 |
|
---|
607 | static int sb_termtype (char *bp, int count)
|
---|
608 | {
|
---|
609 | unsigned char command, iac, optsrt;
|
---|
610 | unsigned char buffer[4];
|
---|
611 | int offset, result;
|
---|
612 |
|
---|
613 | offset= 0;
|
---|
614 | next_char(command);
|
---|
615 | if (command == TERMTYPE_SEND)
|
---|
616 | {
|
---|
617 | buffer[0]= IAC;
|
---|
618 | buffer[1]= IAC_SB;
|
---|
619 | buffer[2]= OPT_TERMTYPE;
|
---|
620 | buffer[3]= TERMTYPE_IS;
|
---|
621 | result= writeall(tcp_fd, (char *)buffer,4);
|
---|
622 | if (result<0)
|
---|
623 | return result;
|
---|
624 | count= strlen(term_env);
|
---|
625 | if (!count)
|
---|
626 | {
|
---|
627 | term_env= "unknown";
|
---|
628 | count= strlen(term_env);
|
---|
629 | }
|
---|
630 | result= writeall(tcp_fd, term_env, count);
|
---|
631 | if (result<0)
|
---|
632 | return result;
|
---|
633 | buffer[0]= IAC;
|
---|
634 | buffer[1]= IAC_SE;
|
---|
635 | result= writeall(tcp_fd, (char *)buffer,2);
|
---|
636 | if (result<0)
|
---|
637 | return result;
|
---|
638 |
|
---|
639 | }
|
---|
640 | else
|
---|
641 | {
|
---|
642 | #if DEBUG
|
---|
643 | where();
|
---|
644 | #endif
|
---|
645 | fprintf(stderr, "got an unknown command (skipping)\r\n");
|
---|
646 | }
|
---|
647 | for (;;)
|
---|
648 | {
|
---|
649 | next_char(iac);
|
---|
650 | if (iac != IAC)
|
---|
651 | continue;
|
---|
652 | next_char(optsrt);
|
---|
653 | if (optsrt == IAC)
|
---|
654 | continue;
|
---|
655 | if (optsrt != IAC_SE)
|
---|
656 | {
|
---|
657 | #if DEBUG
|
---|
658 | where();
|
---|
659 | #endif
|
---|
660 | fprintf(stderr, "got IAC %d\r\n", optsrt);
|
---|
661 | }
|
---|
662 | break;
|
---|
663 | }
|
---|
664 | return offset;
|
---|
665 | }
|
---|
666 |
|
---|
667 | static void fatal(char *fmt, ...)
|
---|
668 | {
|
---|
669 | va_list ap;
|
---|
670 |
|
---|
671 | va_start(ap, fmt);
|
---|
672 | fprintf(stderr, "%s: ", prog_name);
|
---|
673 | vfprintf(stderr, fmt, ap);
|
---|
674 | fprintf(stderr, "\n");
|
---|
675 | va_end(ap);
|
---|
676 |
|
---|
677 | exit(1);
|
---|
678 | }
|
---|
679 |
|
---|
680 | static void usage(void)
|
---|
681 | {
|
---|
682 | fprintf(stderr, "Usage: %s [-e esc-char] host [port]\r\n",
|
---|
683 | prog_name);
|
---|
684 | exit(1);
|
---|
685 | }
|
---|
686 |
|
---|
687 | /*
|
---|
688 | * $PchId: ttn.c,v 1.5 2002/05/07 12:06:41 philip Exp $
|
---|
689 | */
|
---|