📄 ttn.c
字号:
/*ttn.c*/#ifndef _POSIX_SOURCE#define _POSIX_SOURCE 1#endif#include <sys/types.h>#include <sys/ioctl.h>#include <assert.h>#include <errno.h>#include <fcntl.h>#include <termios.h>#include <signal.h>#include <stdio.h>#include <stdlib.h>#include <string.h>#include <unistd.h>#include <net/hton.h>#include <net/netlib.h>#include <net/gen/in.h>#include <net/gen/inet.h>#include <net/gen/netdb.h>#include <net/gen/tcp.h>#include <net/gen/tcp_io.h>#include "ttn.h"#if __STDC__#define PROTOTYPE(func,args) func args#else#define PROTOTYPE(func,args) func()#endifPROTOTYPE (int main, (int argc, char *argv[]) );static int do_read(int fd, char *buf, unsigned len);static void screen(void);static void keyboard (void);static int process_opt (char *bp, int count);static void do_option (int optsrt);static void dont_option (int optsrt);static void will_option (int optsrt);static void wont_option (int optsrt);static int writeall (int fd, char *buffer, int buf_size);static int sb_termtype (char *sb, int count);#if DEBUG#define where() (fprintf(stderr, "%s %d:", __FILE__, __LINE__))#endifstatic char *prog_name;static tcp_fd;static char *term_env;main(argc, argv)int argc;char *argv[];{ struct hostent *hostent; struct servent *servent; ipaddr_t host; tcpport_t port; int pid, ppid; nwio_tcpconf_t tcpconf; int result, count; nwio_tcpcl_t tcpconnopt; char buffer[1024]; struct termios termios; char *tcp_device; prog_name= argv[0]; if (argc <2 || argc>3) { fprintf(stderr, "Usage: %s host <port>\r\n", argv[0]); exit(1); } hostent= gethostbyname(argv[1]); if (!hostent) { host= inet_addr(argv[1]); if (host == -1) { fprintf(stderr, "%s: unknown host (%s)\r\n", argv[0], argv[1]); exit(1); } } else host= *(ipaddr_t *)(hostent->h_addr); if (argc < 3) port= htons(TCPPORT_TELNET); else { servent= getservbyname (argv[2], "tcp"); if (!servent) { port= htons(strtol (argv[2], (char **)0, 0)); if (!port) { fprintf(stderr, "%s: unknown port (%s)\r\n", argv[0], argv[2]); exit(1); } } else port= (tcpport_t)(servent->s_port); } printf("connecting to %s %u\r\n", inet_ntoa(host), ntohs(port)); tcp_device= getenv("TCP_DEVICE"); if (tcp_device == NULL) tcp_device= TCP_DEVICE; tcp_fd= open (tcp_device, O_RDWR); if (tcp_fd<0) { perror ("unable to open /dev/tcp"); exit(1); } tcpconf.nwtc_flags= NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP; tcpconf.nwtc_remaddr= host; tcpconf.nwtc_remport= port; result= ioctl (tcp_fd, NWIOSTCPCONF, &tcpconf); if (result<0) { perror ("unable to NWIOSTCPCONF"); exit(1); } tcpconnopt.nwtcl_flags= 0; while(1) { result= ioctl (tcp_fd, NWIOTCPCONN, &tcpconnopt); if (result < 0 && errno == EAGAIN) { fprintf(stderr,"%s: got EAGAIN, sleeping(1s)\r\n", prog_name); sleep(1); } else break; } if (result<0) { perror ("unable to NWIOTCPCONN"); exit(1); } printf("Connected\r\n"); ppid= getpid(); pid= fork(); switch(pid) { case 0: keyboard();#if DEBUGfprintf(stderr, "killing %d with %d\r\n", ppid, SIGKILL);#endif kill(ppid, SIGKILL); break; case -1: fprintf(stderr, "%s: fork failed: %s\r\n", argv[0], strerror(errno)); exit(1); break; default: tcgetattr(0, &termios); screen();#if DEBUGfprintf(stderr, "killing %d with %d\r\n", pid, SIGKILL);#endif kill(pid, SIGKILL); tcsetattr(0, TCSANOW, &termios); break; }}static int do_read(fd, buf, len)int fd;char *buf;unsigned len;{#if __minix_vmd nwio_tcpopt_t tcpopt; int count; for (;;) { count= read (fd, buf, len); if (count <0) { if (errno == EURG || errno == ENOURG) { /* Toggle urgent mode. */ tcpopt.nwto_flags= errno == EURG ? NWTO_RCV_URG : NWTO_RCV_NOTURG; if (ioctl(tcp_fd, NWIOSTCPOPT, &tcpopt) == -1) { return -1; } continue; } return -1; } return count; }#else return read(fd, buf, len);#endif}static void screen(){ char buffer[1024], *bp, *iacptr; int count, optsize; for (;;) { count= do_read (tcp_fd, buffer, sizeof(buffer));#if DEBUG && 0 { where(); fprintf(stderr, "read %d bytes\r\n", count); }#endif if (count <0) { perror ("read"); return; } if (!count) return; bp= buffer; do { iacptr= memchr (bp, IAC, count); if (!iacptr) { write(1, bp, count); count= 0; } if (iacptr && iacptr>bp) {#if DEBUG { where(); fprintf(stderr, "iacptr-bp= %d\r\n", iacptr-bp); }#endif write(1, bp, iacptr-bp); count -= (iacptr-bp); bp= iacptr; continue; } if (iacptr) {assert (iacptr == bp); optsize= process_opt(bp, count);#if DEBUG && 0 { where(); fprintf(stderr, "process_opt(...)= %d\r\n", optsize); }#endif if (optsize<0) return;assert (optsize); bp += optsize; count -= optsize; } } while (count); }}static void keyboard(){ nwio_tcpatt_t nwio_tcpatt; char buffer[1024]; int result; int count; nwio_tcpatt.nwta_flags= 0; for (;;) { count= read (0, buffer, sizeof(buffer)); if (count<0) { fprintf(stderr, "%s: read: %s\r\n", prog_name, strerror(errno)); return; } if (!count) return;#if DEBUG && 0 { where(); fprintf(stderr, "writing %d bytes\r\n", count); }#endif count= write(tcp_fd, buffer, count);#if 0 if (buffer[0] == '\r') write(tcp_fd, "\n", 1);#endif if (count<0) { perror("write"); return; } if (!count) return; }}#define next_char(var) \ if (offset<count) { (var) = bp[offset++]; } \ else if (do_read(tcp_fd, (char *)&(var), 1) <= 0) \ { perror ("read"); return -1; }static int process_opt (char *bp, int count){ unsigned char iac, command, optsrt, sb_command; int offset, result; ;#if DEBUG && 0 { where(); fprintf(stderr, "process_opt(bp= 0x%x, count= %d)\r\n", bp, count); }#endif offset= 0;assert (count); next_char(iac);assert (iac == IAC); next_char(command); switch(command) { case IAC_NOP: break; case IAC_DataMark:fprintf(stderr, "got a DataMark\r\n"); break; case IAC_BRK:fprintf(stderr, "got a BRK\r\n"); break; case IAC_IP:fprintf(stderr, "got a IP\r\n"); break; case IAC_AO:fprintf(stderr, "got a AO\r\n"); break; case IAC_AYT:fprintf(stderr, "got a AYT\r\n"); break; case IAC_EC:fprintf(stderr, "got a EC\r\n"); break; case IAC_EL:fprintf(stderr, "got a EL\r\n"); break; case IAC_GA:fprintf(stderr, "got a GA\r\n"); break; case IAC_SB: next_char(sb_command); switch (sb_command) { case OPT_TERMTYPE:#if DEBUG && 0fprintf(stderr, "got SB TERMINAL-TYPE\r\n");#endif result= sb_termtype(bp+offset, count-offset); if (result<0) return result; else return result+offset; default:fprintf(stderr, "got an unknown SB (skiping)\r\n"); for (;;) { next_char(iac); if (iac != IAC) continue; next_char(optsrt); if (optsrt == IAC) continue;if (optsrt != IAC_SE) fprintf(stderr, "got IAC %d\r\n", optsrt); break; } } break; case IAC_WILL: next_char(optsrt); will_option(optsrt); break; case IAC_WONT: next_char(optsrt); wont_option(optsrt); break; case IAC_DO: next_char(optsrt); do_option(optsrt); break; case IAC_DONT: next_char(optsrt); dont_option(optsrt); break; case IAC:fprintf(stderr, "got a IAC\r\n"); break; default:fprintf(stderr, "got unknown command (%d)\r\n", command); } return offset;}static void do_option (int optsrt){ unsigned char reply[3], *rp; int count, result; switch (optsrt) { case OPT_TERMTYPE: if (WILL_terminal_type) return; if (!WILL_terminal_type_allowed) { reply[0]= IAC; reply[1]= IAC_WONT; reply[2]= optsrt; } else { WILL_terminal_type= TRUE; term_env= getenv("TERM"); if (!term_env) term_env= "unknown"; reply[0]= IAC; reply[1]= IAC_WILL; reply[2]= optsrt; } break; default:#if DEBUG { where(); fprintf(stderr, "got a DO (%d)\r\n", optsrt); }#endif#if DEBUG { where(); fprintf(stderr, "WONT (%d)\r\n", optsrt); }#endif reply[0]= IAC; reply[1]= IAC_WONT; reply[2]= optsrt; break; } result= writeall(tcp_fd, (char *)reply, 3); if (result<0) perror("write");}static void will_option (int optsrt){ unsigned char reply[3], *rp; int count, result; switch (optsrt) { case OPT_ECHO: if (DO_echo) break; if (!DO_echo_allowed) { reply[0]= IAC; reply[1]= IAC_DONT; reply[2]= optsrt; } else { struct termios termios; tcgetattr(0, &termios); termios.c_iflag &= ~(ICRNL|IGNCR|INLCR|IXON|IXOFF); termios.c_oflag &= ~(OPOST); termios.c_lflag &= ~(ECHO|ECHONL|ICANON|ISIG); tcsetattr(0, TCSANOW, &termios); DO_echo= TRUE; reply[0]= IAC; reply[1]= IAC_DO; reply[2]= optsrt; } result= writeall(tcp_fd, (char *)reply, 3); if (result<0) perror("write"); break; case OPT_SUPP_GA: if (DO_suppress_go_ahead) break; if (!DO_suppress_go_ahead_allowed) { reply[0]= IAC; reply[1]= IAC_DONT; reply[2]= optsrt; } else { DO_suppress_go_ahead= TRUE; reply[0]= IAC; reply[1]= IAC_DO; reply[2]= optsrt; } result= writeall(tcp_fd, (char *)reply, 3); if (result<0) perror("write"); break; default:#if DEBUG { where(); fprintf(stderr, "got a WILL (%d)\r\n", optsrt); }#endif#if DEBUG { where(); fprintf(stderr, "DONT (%d)\r\n", optsrt); }#endif reply[0]= IAC; reply[1]= IAC_DONT; reply[2]= optsrt; result= writeall(tcp_fd, (char *)reply, 3); if (result<0) perror("write"); break; }}static int writeall (fd, buffer, buf_size)int fd;char *buffer;int buf_size;{ int result; while (buf_size) { result= write (fd, buffer, buf_size); if (result <= 0) return -1;assert (result <= buf_size); buffer += result; buf_size -= result; } return 0;}static void dont_option (int optsrt){ unsigned char reply[3], *rp; int count, result; switch (optsrt) { default:#if DEBUG { where(); fprintf(stderr, "got a DONT (%d)\r\n", optsrt); }#endif break; }}static void wont_option (int optsrt){ unsigned char reply[3], *rp; int count, result; switch (optsrt) { default:#if DEBUG { where(); fprintf(stderr, "got a WONT (%d)\r\n", optsrt); }#endif break; }}static int sb_termtype (char *bp, int count){ unsigned char command, iac, optsrt; unsigned char buffer[4]; int offset, result; offset= 0; next_char(command); if (command == TERMTYPE_SEND) { buffer[0]= IAC; buffer[1]= IAC_SB; buffer[2]= OPT_TERMTYPE; buffer[3]= TERMTYPE_IS; result= writeall(tcp_fd, (char *)buffer,4); if (result<0) return result; count= strlen(term_env); if (!count) { term_env= "unknown"; count= strlen(term_env); } result= writeall(tcp_fd, term_env, count); if (result<0) return result; buffer[0]= IAC; buffer[1]= IAC_SE; result= writeall(tcp_fd, (char *)buffer,2); if (result<0) return result; } else {#if DEBUG where();#endif fprintf(stderr, "got an unknown command (skipping)\r\n"); } for (;;) { next_char(iac); if (iac != IAC) continue; next_char(optsrt); if (optsrt == IAC) continue; if (optsrt != IAC_SE) {#if DEBUG where();#endif fprintf(stderr, "got IAC %d\r\n", optsrt); } break; } return offset;}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -