18 #include <net/netlib.h>
19 #include <net/gen/in.h>
20 #include <net/gen/inet.h>
22 #include <net/gen/tcp.h>
23 #include <net/gen/tcp_io.h>
27 #define PROTOTYPE(func,args) func args
29 #define PROTOTYPE(func,args) func()
32 static int do_read(int fd
, char *buf
, unsigned len
);
33 static void screen(void);
34 static void keyboard(void);
35 static void send_brk(void);
36 static int process_opt (char *bp
, int count
);
37 static void do_option (int optsrt
);
38 static void dont_option (int optsrt
);
39 static void will_option (int optsrt
);
40 static void wont_option (int optsrt
);
41 static int writeall (int fd
, char *buffer
, int buf_size
);
42 static int sb_termtype (char *sb
, int count
);
43 static void fatal(char *fmt
, ...);
44 static void usage(void);
47 #define where() (fprintf(stderr, "%s %d:", __FILE__, __LINE__))
50 static char *prog_name
;
52 static char *term_env
;
53 static int esc_char
= '~';
54 static enum { LS_NORM
, LS_BOL
, LS_ESC
} line_state
= LS_BOL
;
56 int main(int argc
, char *argv
[])
58 struct hostent
*hostent
;
59 struct servent
*servent
;
63 nwio_tcpconf_t tcpconf
;
65 nwio_tcpcl_t tcpconnopt
;
66 struct termios termios
;
67 char *tcp_device
, *remote_name
, *port_name
;
70 (prog_name
=strrchr(argv
[0],'/')) ? prog_name
++ : (prog_name
=argv
[0]);
73 while (c
= getopt(argc
, argv
, "?e:"), c
!= -1)
78 case 'e': e_arg
= optarg
; break;
80 fatal("Optind failed: '%c'", c
);
86 remote_name
= argv
[optind
++];
88 port_name
= argv
[optind
++];
98 case 0: esc_char
= -1; break;
99 case 1: esc_char
= e_arg
[0]; break;
100 default: fatal("Invalid escape character '%s'", e_arg
);
104 hostent
= gethostbyname(remote_name
);
106 fatal("Unknown host %s", remote_name
);
107 host
= *(ipaddr_t
*)(hostent
->h_addr
);
110 port
= htons(TCPPORT_TELNET
);
113 servent
= getservbyname (port_name
, "tcp");
116 port
= htons(strtol(port_name
, (char **)0, 0));
118 fatal("Unknown port %s", port_name
);
121 port
= (tcpport_t
)(servent
->s_port
);
124 fprintf(stderr
, "Connecting to %s:%u...\n",
125 inet_ntoa(host
), ntohs(port
));
127 tcp_device
= getenv("TCP_DEVICE");
128 if (tcp_device
== NULL
)
129 tcp_device
= TCP_DEVICE
;
130 tcp_fd
= open (tcp_device
, O_RDWR
);
132 fatal("Unable to open %s: %s", tcp_device
, strerror(errno
));
134 tcpconf
.nwtc_flags
= NWTC_LP_SEL
| NWTC_SET_RA
| NWTC_SET_RP
;
135 tcpconf
.nwtc_remaddr
= host
;
136 tcpconf
.nwtc_remport
= port
;
138 r
= ioctl (tcp_fd
, NWIOSTCPCONF
, &tcpconf
);
140 fatal("NWIOSTCPCONF failed: %s", strerror(errno
));
142 tcpconnopt
.nwtcl_flags
= 0;
145 r
= ioctl (tcp_fd
, NWIOTCPCONN
, &tcpconnopt
);
146 if (r
== -1 && errno
== EAGAIN
)
148 fprintf(stderr
, "%s: Got EAGAIN, sleeping(1s)\n",
152 } while (r
== -1 && errno
== EAGAIN
);
154 fatal("Unable to connect: %s", strerror(errno
));
155 printf("Connected\n");
163 fprintf(stderr
, "killing %d with %d\r\n", ppid
, SIGKILL
);
168 fprintf(stderr
, "%s: fork failed: %s\r\n", argv
[0],
173 tcgetattr(0, &termios
);
176 fprintf(stderr
, "killing %d with %d\r\n", pid
, SIGKILL
);
179 tcsetattr(0, TCSANOW
, &termios
);
185 static int do_read(fd
, buf
, len
)
190 nwio_tcpopt_t tcpopt
;
195 count
= read (fd
, buf
, len
);
198 if (errno
== EURG
|| errno
== ENOURG
)
200 /* Toggle urgent mode. */
201 tcpopt
.nwto_flags
= errno
== EURG
?
202 NWTO_RCV_URG
: NWTO_RCV_NOTURG
;
203 if (ioctl(tcp_fd
, NWIOSTCPOPT
, &tcpopt
) == -1)
217 char buffer
[1024], *bp
, *iacptr
;
222 count
= do_read (tcp_fd
, buffer
, sizeof(buffer
));
224 { where(); fprintf(stderr
, "read %d bytes\r\n", count
); }
236 iacptr
= memchr (bp
, IAC
, count
);
242 if (iacptr
&& iacptr
>bp
)
245 { where(); fprintf(stderr
, "iacptr-bp= %d\r\n", iacptr
-bp
); }
247 write(1, bp
, iacptr
-bp
);
248 count
-= (iacptr
-bp
);
254 assert (iacptr
== bp
);
255 optsize
= process_opt(bp
, count
);
257 { where(); fprintf(stderr
, "process_opt(...)= %d\r\n", optsize
); }
269 static void keyboard()
271 char c
, buffer
[1024];
276 count
= read (0, buffer
, 1 /* sizeof(buffer) */);
278 fatal("Read: %s\r\n", strerror(errno
));
282 if (line_state
!= LS_NORM
)
285 if (line_state
== LS_BOL
)
294 else if (line_state
== LS_ESC
)
305 /* Not a valid command or a repeat of the
311 write(tcp_fd
, &c
, 1);
315 if (buffer
[0] == '\n')
316 write(tcp_fd
, "\r", 1);
317 count
= write(tcp_fd
, buffer
, count
);
318 if (buffer
[0] == '\r')
321 write(tcp_fd
, "\0", 1);
326 fprintf(stderr
, "errno= %d\r\n", errno
);
334 static void send_brk(void)
337 unsigned char buffer
[2];
342 r
= writeall(tcp_fd
, (char *)buffer
, 2);
344 fatal("Error writing to TCP connection: %s", strerror(errno
));
347 #define next_char(var) \
348 if (offset<count) { (var) = bp[offset++]; } \
349 else if (do_read(tcp_fd, (char *)&(var), 1) <= 0) \
350 { perror ("read"); return -1; }
352 static int process_opt (char *bp
, int count
)
354 unsigned char iac
, command
, optsrt
, sb_command
;
355 int offset
, result
; ;
357 { where(); fprintf(stderr
, "process_opt(bp= 0x%x, count= %d)\r\n",
371 /* Ought to flush input queue or something. */
374 fprintf(stderr
, "got a BRK\r\n");
377 fprintf(stderr
, "got a IP\r\n");
380 fprintf(stderr
, "got a AO\r\n");
383 fprintf(stderr
, "got a AYT\r\n");
386 fprintf(stderr
, "got a EC\r\n");
389 fprintf(stderr
, "got a EL\r\n");
392 fprintf(stderr
, "got a GA\r\n");
395 next_char(sb_command
);
400 fprintf(stderr
, "got SB TERMINAL-TYPE\r\n");
402 result
= sb_termtype(bp
+offset
, count
-offset
);
406 return result
+offset
;
408 fprintf(stderr
, "got an unknown SB (skiping)\r\n");
417 if (optsrt
!= IAC_SE
)
418 fprintf(stderr
, "got IAC %d\r\n", optsrt
);
440 fprintf(stderr
, "got a IAC\r\n");
443 fprintf(stderr
, "got unknown command (%d)\r\n", command
);
448 static void do_option (int optsrt
)
450 unsigned char reply
[3];
456 if (WILL_terminal_type
)
458 if (!WILL_terminal_type_allowed
)
466 WILL_terminal_type
= TRUE
;
467 term_env
= getenv("TERM");
477 fprintf(stderr
, "got a DO (%d)\r\n", optsrt
);
478 fprintf(stderr
, "WONT (%d)\r\n", optsrt
);
485 result
= writeall(tcp_fd
, (char *)reply
, 3);
490 static void will_option (int optsrt
)
492 unsigned char reply
[3];
500 if (!DO_echo_allowed
)
508 struct termios termios
;
510 tcgetattr(0, &termios
);
511 termios
.c_iflag
&= ~(ICRNL
|IGNCR
|INLCR
|IXON
|IXOFF
);
512 termios
.c_oflag
&= ~(OPOST
);
513 termios
.c_lflag
&= ~(ECHO
|ECHONL
|ICANON
|IEXTEN
|ISIG
);
514 tcsetattr(0, TCSANOW
, &termios
);
521 result
= writeall(tcp_fd
, (char *)reply
, 3);
526 if (DO_suppress_go_ahead
)
528 if (!DO_suppress_go_ahead_allowed
)
536 DO_suppress_go_ahead
= TRUE
;
541 result
= writeall(tcp_fd
, (char *)reply
, 3);
547 fprintf(stderr
, "got a WILL (%d)\r\n", optsrt
);
548 fprintf(stderr
, "DONT (%d)\r\n", optsrt
);
553 result
= writeall(tcp_fd
, (char *)reply
, 3);
560 static int writeall (fd
, buffer
, buf_size
)
569 result
= write (fd
, buffer
, buf_size
);
572 assert (result
<= buf_size
);
579 static void dont_option (int optsrt
)
585 fprintf(stderr
, "got a DONT (%d)\r\n", optsrt
);
591 static void wont_option (int optsrt
)
597 fprintf(stderr
, "got a WONT (%d)\r\n", optsrt
);
603 static int sb_termtype (char *bp
, int count
)
605 unsigned char command
, iac
, optsrt
;
606 unsigned char buffer
[4];
611 if (command
== TERMTYPE_SEND
)
615 buffer
[2]= OPT_TERMTYPE
;
616 buffer
[3]= TERMTYPE_IS
;
617 result
= writeall(tcp_fd
, (char *)buffer
,4);
620 count
= strlen(term_env
);
624 count
= strlen(term_env
);
626 result
= writeall(tcp_fd
, term_env
, count
);
631 result
= writeall(tcp_fd
, (char *)buffer
,2);
641 fprintf(stderr
, "got an unknown command (skipping)\r\n");
651 if (optsrt
!= IAC_SE
)
656 fprintf(stderr
, "got IAC %d\r\n", optsrt
);
663 static void fatal(char *fmt
, ...)
668 fprintf(stderr
, "%s: ", prog_name
);
669 vfprintf(stderr
, fmt
, ap
);
670 fprintf(stderr
, "\n");
676 static void usage(void)
678 fprintf(stderr
, "Usage: %s [-e esc-char] host [port]\r\n",
684 * $PchId: ttn.c,v 1.5 2002/05/07 12:06:41 philip Exp $