/* socket.c Created: Feb 2001 by Philip Homburg Open a TCP connection */ #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #define BUF_SIZE 10240 char *progname; int tcpfd= -1; char buf[BUF_SIZE]; static int bulk= 0; static int push= 0; static int stdout_issocket= 0; static int timeout; static void do_conn(char *hostname, char *portname); static void alrm_conn(int sig); static void alrm_io(int sig); static void fullduplex(void); static void fatal(char *msg, ...); static void usage(void); int main(int argc, char *argv[]) { int c; char *hostname; char *portname; char *check; int B_flag, P_flag, s_flag; char *t_arg; (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]); B_flag= 0; P_flag= 0; s_flag= 0; t_arg= NULL; while (c= getopt(argc, argv, "BPst:?"), c != -1) { switch(c) { case 'B': B_flag= 1; break; case 'P': P_flag= 1; break; case 's': s_flag= 1; break; case 't': t_arg= optarg; break; case '?': usage(); default: fatal("getopt failed: '%c'", c); } } if (t_arg) { timeout= strtol(t_arg, &check, 0); if (check[0] != '\0') fatal("unable to parse timeout '%s'\n", t_arg); if (timeout <= 0) fatal("bad timeout '%d'\n", timeout); } else timeout= 0; if (optind+2 != argc) usage(); hostname= argv[optind++]; portname= argv[optind++]; bulk= B_flag; push= P_flag; stdout_issocket= s_flag; do_conn(hostname, portname); /* XXX */ if (timeout) { signal(SIGALRM, alrm_io); alarm(timeout); } fullduplex(); exit(0); } static void do_conn(char *hostname, char *portname) { ipaddr_t addr; tcpport_t port; struct hostent *he; struct servent *se; char *tcp_device, *check; nwio_tcpconf_t tcpconf; nwio_tcpcl_t tcpcl; nwio_tcpopt_t tcpopt; if (!inet_aton(hostname, (struct in_addr *)&addr)) { he= gethostbyname(hostname); if (he == NULL) fatal("unknown hostname '%s'", hostname); if (he->h_addrtype != AF_INET || he->h_length != sizeof(addr)) fatal("bad address for '%s'", hostname); memcpy(&addr, he->h_addr, sizeof(addr)); } port= strtol(portname, &check, 0); if (check[0] != 0) { se= getservbyname(portname, "tcp"); if (se == NULL) fatal("unkown port '%s'", portname); port= ntohs(se->s_port); } tcp_device= getenv("TCP_DEVICE"); if (tcp_device == NULL) tcp_device= TCP_DEVICE; tcpfd= open(tcp_device, O_RDWR); if (tcpfd == -1) fatal("unable to open '%s': %s", tcp_device, strerror(errno)); tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA | NWTC_SET_RP; tcpconf.nwtc_remaddr= addr; tcpconf.nwtc_remport= htons(port);; if (ioctl(tcpfd, NWIOSTCPCONF, &tcpconf) == -1) fatal("NWIOSTCPCONF failed: %s", strerror(errno)); if (timeout) { signal(SIGALRM, alrm_conn); alarm(timeout); } tcpcl.nwtcl_flags= 0; if (ioctl(tcpfd, NWIOTCPCONN, &tcpcl) == -1) { fatal("unable to connect to %s:%u: %s", inet_ntoa(*(struct in_addr *)&addr), ntohs(tcpconf.nwtc_remport), strerror(errno)); } alarm(0); if (bulk) { tcpopt.nwto_flags= NWTO_BULK; if (ioctl(tcpfd, NWIOSTCPOPT, &tcpopt) == -1) fatal("NWIOSTCPOPT failed: %s", strerror(errno)); } } static void alrm_conn(int sig) { fatal("timeout during connect"); } static void alrm_io(int sig) { fatal("timeout during io"); } static void fullduplex(void) { pid_t cpid; int o, r, s, s_errno, loc; cpid= fork(); switch(cpid) { case -1: fatal("fork failed: %s", strerror(errno)); case 0: /* Read from TCP, write to stdout. */ for (;;) { r= read(tcpfd, buf, BUF_SIZE); if (r == 0) break; if (r == -1) { r= errno; if (stdout_issocket) ioctl(1, NWIOTCPSHUTDOWN, NULL); fatal("error reading from TCP conn.: %s", strerror(errno)); } s= r; for (o= 0; o