6 #define _POSIX_SOURCE 1
10 #include <sys/ioctl.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>
31 #define PROTOTYPE(func,args) func args
33 #define PROTOTYPE(func,args) func()
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);
51 #define where() (fprintf(stderr, "%s %d:", __FILE__, __LINE__))
54 static char *prog_name
;
56 static char *term_env
;
57 static int esc_char
= '~';
58 static enum { LS_NORM
, LS_BOL
, LS_ESC
} line_state
= LS_BOL
;
60 int main(int argc
, char *argv
[])
62 struct hostent
*hostent
;
63 struct servent
*servent
;
67 nwio_tcpconf_t tcpconf
;
69 nwio_tcpcl_t tcpconnopt
;
70 struct termios termios
;
71 char *tcp_device
, *remote_name
, *port_name
;
74 (prog_name
=strrchr(argv
[0],'/')) ? prog_name
++ : (prog_name
=argv
[0]);
77 while (c
= getopt(argc
, argv
, "?e:"), c
!= -1)
82 case 'e': e_arg
= optarg
; break;
84 fatal("Optind failed: '%c'", c
);
90 remote_name
= argv
[optind
++];
92 port_name
= argv
[optind
++];
100 switch(strlen(e_arg
))
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
);
108 hostent
= gethostbyname(remote_name
);
110 fatal("Unknown host %s", remote_name
);
111 host
= *(ipaddr_t
*)(hostent
->h_addr
);
114 port
= htons(TCPPORT_TELNET
);
117 servent
= getservbyname (port_name
, "tcp");
120 port
= htons(strtol(port_name
, (char **)0, 0));
122 fatal("Unknown port %s", port_name
);
125 port
= (tcpport_t
)(servent
->s_port
);
128 fprintf(stderr
, "Connecting to %s:%u...\n",
129 inet_ntoa(host
), ntohs(port
));
131 tcp_device
= getenv("TCP_DEVICE");
132 if (tcp_device
== NULL
)
133 tcp_device
= TCP_DEVICE
;
134 tcp_fd
= open (tcp_device
, O_RDWR
);
136 fatal("Unable to open %s: %s", tcp_device
, strerror(errno
));
138 tcpconf
.nwtc_flags
= NWTC_LP_SEL
| NWTC_SET_RA
| NWTC_SET_RP
;
139 tcpconf
.nwtc_remaddr
= host
;
140 tcpconf
.nwtc_remport
= port
;
142 r
= ioctl (tcp_fd
, NWIOSTCPCONF
, &tcpconf
);
144 fatal("NWIOSTCPCONF failed: %s", strerror(errno
));
146 tcpconnopt
.nwtcl_flags
= 0;
149 r
= ioctl (tcp_fd
, NWIOTCPCONN
, &tcpconnopt
);
150 if (r
== -1 && errno
== EAGAIN
)
152 fprintf(stderr
, "%s: Got EAGAIN, sleeping(1s)\n",
156 } while (r
== -1 && errno
== EAGAIN
);
158 fatal("Unable to connect: %s", strerror(errno
));
159 printf("Connected\n");
167 fprintf(stderr
, "killing %d with %d\r\n", ppid
, SIGKILL
);
172 fprintf(stderr
, "%s: fork failed: %s\r\n", argv
[0],
177 tcgetattr(0, &termios
);
180 fprintf(stderr
, "killing %d with %d\r\n", pid
, SIGKILL
);
183 tcsetattr(0, TCSANOW
, &termios
);
189 static int do_read(fd
, buf
, len
)
194 nwio_tcpopt_t tcpopt
;
199 count
= read (fd
, buf
, len
);
202 if (errno
== EURG
|| errno
== ENOURG
)
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)
221 char buffer
[1024], *bp
, *iacptr
;
226 count
= do_read (tcp_fd
, buffer
, sizeof(buffer
));
228 { where(); fprintf(stderr
, "read %d bytes\r\n", count
); }
240 iacptr
= memchr (bp
, IAC
, count
);
246 if (iacptr
&& iacptr
>bp
)
249 { where(); fprintf(stderr
, "iacptr-bp= %d\r\n", iacptr
-bp
); }
251 write(1, bp
, iacptr
-bp
);
252 count
-= (iacptr
-bp
);
258 assert (iacptr
== bp
);
259 optsize
= process_opt(bp
, count
);
261 { where(); fprintf(stderr
, "process_opt(...)= %d\r\n", optsize
); }
273 static void keyboard()
275 char c
, buffer
[1024];
280 count
= read (0, buffer
, 1 /* sizeof(buffer) */);
282 fatal("Read: %s\r\n", strerror(errno
));
286 if (line_state
!= LS_NORM
)
289 if (line_state
== LS_BOL
)
298 else if (line_state
== LS_ESC
)
309 /* Not a valid command or a repeat of the
315 write(tcp_fd
, &c
, 1);
319 if (buffer
[0] == '\n')
320 write(tcp_fd
, "\r", 1);
321 count
= write(tcp_fd
, buffer
, count
);
322 if (buffer
[0] == '\r')
325 write(tcp_fd
, "\0", 1);
330 fprintf(stderr
, "errno= %d\r\n", errno
);
338 static void send_brk(void)
341 unsigned char buffer
[2];
346 r
= writeall(tcp_fd
, (char *)buffer
, 2);
348 fatal("Error writing to TCP connection: %s", strerror(errno
));
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; }
356 static int process_opt (char *bp
, int count
)
358 unsigned char iac
, command
, optsrt
, sb_command
;
359 int offset
, result
; ;
361 { where(); fprintf(stderr
, "process_opt(bp= 0x%x, count= %d)\r\n",
375 /* Ought to flush input queue or something. */
378 fprintf(stderr
, "got a BRK\r\n");
381 fprintf(stderr
, "got a IP\r\n");
384 fprintf(stderr
, "got a AO\r\n");
387 fprintf(stderr
, "got a AYT\r\n");
390 fprintf(stderr
, "got a EC\r\n");
393 fprintf(stderr
, "got a EL\r\n");
396 fprintf(stderr
, "got a GA\r\n");
399 next_char(sb_command
);
404 fprintf(stderr
, "got SB TERMINAL-TYPE\r\n");
406 result
= sb_termtype(bp
+offset
, count
-offset
);
410 return result
+offset
;
412 fprintf(stderr
, "got an unknown SB (skiping)\r\n");
421 if (optsrt
!= IAC_SE
)
422 fprintf(stderr
, "got IAC %d\r\n", optsrt
);
444 fprintf(stderr
, "got a IAC\r\n");
447 fprintf(stderr
, "got unknown command (%d)\r\n", command
);
452 static void do_option (int optsrt
)
454 unsigned char reply
[3];
460 if (WILL_terminal_type
)
462 if (!WILL_terminal_type_allowed
)
470 WILL_terminal_type
= TRUE
;
471 term_env
= getenv("TERM");
481 fprintf(stderr
, "got a DO (%d)\r\n", optsrt
);
482 fprintf(stderr
, "WONT (%d)\r\n", optsrt
);
489 result
= writeall(tcp_fd
, (char *)reply
, 3);
494 static void will_option (int optsrt
)
496 unsigned char reply
[3];
504 if (!DO_echo_allowed
)
512 struct termios termios
;
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
);
525 result
= writeall(tcp_fd
, (char *)reply
, 3);
530 if (DO_suppress_go_ahead
)
532 if (!DO_suppress_go_ahead_allowed
)
540 DO_suppress_go_ahead
= TRUE
;
545 result
= writeall(tcp_fd
, (char *)reply
, 3);
551 fprintf(stderr
, "got a WILL (%d)\r\n", optsrt
);
552 fprintf(stderr
, "DONT (%d)\r\n", optsrt
);
557 result
= writeall(tcp_fd
, (char *)reply
, 3);
564 static int writeall (fd
, buffer
, buf_size
)
573 result
= write (fd
, buffer
, buf_size
);
576 assert (result
<= buf_size
);
583 static void dont_option (int optsrt
)
589 fprintf(stderr
, "got a DONT (%d)\r\n", optsrt
);
595 static void wont_option (int optsrt
)
601 fprintf(stderr
, "got a WONT (%d)\r\n", optsrt
);
607 static int sb_termtype (char *bp
, int count
)
609 unsigned char command
, iac
, optsrt
;
610 unsigned char buffer
[4];
615 if (command
== TERMTYPE_SEND
)
619 buffer
[2]= OPT_TERMTYPE
;
620 buffer
[3]= TERMTYPE_IS
;
621 result
= writeall(tcp_fd
, (char *)buffer
,4);
624 count
= strlen(term_env
);
628 count
= strlen(term_env
);
630 result
= writeall(tcp_fd
, term_env
, count
);
635 result
= writeall(tcp_fd
, (char *)buffer
,2);
645 fprintf(stderr
, "got an unknown command (skipping)\r\n");
655 if (optsrt
!= IAC_SE
)
660 fprintf(stderr
, "got IAC %d\r\n", optsrt
);
667 static void fatal(char *fmt
, ...)
672 fprintf(stderr
, "%s: ", prog_name
);
673 vfprintf(stderr
, fmt
, ap
);
674 fprintf(stderr
, "\n");
680 static void usage(void)
682 fprintf(stderr
, "Usage: %s [-e esc-char] host [port]\r\n",
688 * $PchId: ttn.c,v 1.5 2002/05/07 12:06:41 philip Exp $