Drop main() prototype. Syncs with NetBSD-8
[minix.git] / minix / commands / swifi / tests / socket.c
blob87e5c1a8b04f4a1cd0d065037a0ad762bf3d7474
1 /*
2 socket.c
4 Created: Feb 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
6 Open a TCP connection
7 */
9 #include <errno.h>
10 #include <fcntl.h>
11 #include <stdarg.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <signal.h>
15 #include <string.h>
16 #include <unistd.h>
18 #include <sys/ioctl.h>
19 #include <sys/wait.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 <netdb.h>
26 #include <net/gen/socket.h>
27 #include <net/gen/tcp.h>
28 #include <net/gen/tcp_io.h>
29 #include <arpa/inet.h>
31 #define BUF_SIZE 10240
33 char *progname;
34 int tcpfd= -1;
35 char buf[BUF_SIZE];
36 static int bulk= 0;
37 static int push= 0;
38 static int stdout_issocket= 0;
39 static int timeout;
41 static void do_conn(char *hostname, char *portname);
42 static void alrm_conn(int sig);
43 static void alrm_io(int sig);
44 static void fullduplex(void);
45 static void fatal(char *msg, ...);
46 static void usage(void);
48 int main(int argc, char *argv[])
50 int c;
51 char *hostname;
52 char *portname;
53 char *check;
54 int B_flag, P_flag, s_flag;
55 char *t_arg;
57 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
59 B_flag= 0;
60 P_flag= 0;
61 s_flag= 0;
62 t_arg= NULL;
63 while (c= getopt(argc, argv, "BPst:?"), c != -1)
65 switch(c)
67 case 'B': B_flag= 1; break;
68 case 'P': P_flag= 1; break;
69 case 's': s_flag= 1; break;
70 case 't': t_arg= optarg; break;
71 case '?': usage();
72 default:
73 fatal("getopt failed: '%c'", c);
76 if (t_arg)
78 timeout= strtol(t_arg, &check, 0);
79 if (check[0] != '\0')
80 fatal("unable to parse timeout '%s'\n", t_arg);
81 if (timeout <= 0)
82 fatal("bad timeout '%d'\n", timeout);
84 else
85 timeout= 0;
87 if (optind+2 != argc)
88 usage();
89 hostname= argv[optind++];
90 portname= argv[optind++];
92 bulk= B_flag;
93 push= P_flag;
94 stdout_issocket= s_flag;
96 do_conn(hostname, portname);
98 /* XXX */
99 if (timeout)
101 signal(SIGALRM, alrm_io);
102 alarm(timeout);
105 fullduplex();
106 exit(0);
109 static void do_conn(char *hostname, char *portname)
111 ipaddr_t addr;
112 tcpport_t port;
113 struct hostent *he;
114 struct servent *se;
115 char *tcp_device, *check;
116 nwio_tcpconf_t tcpconf;
117 nwio_tcpcl_t tcpcl;
118 nwio_tcpopt_t tcpopt;
120 if (!inet_aton(hostname, (struct in_addr *)&addr))
122 he= gethostbyname(hostname);
123 if (he == NULL)
124 fatal("unknown hostname '%s'", hostname);
125 if (he->h_addrtype != AF_INET || he->h_length != sizeof(addr))
126 fatal("bad address for '%s'", hostname);
127 memcpy(&addr, he->h_addr, sizeof(addr));
130 port= strtol(portname, &check, 0);
131 if (check[0] != 0)
133 se= getservbyname(portname, "tcp");
134 if (se == NULL)
135 fatal("unkown port '%s'", portname);
136 port= ntohs(se->s_port);
139 tcp_device= getenv("TCP_DEVICE");
140 if (tcp_device == NULL) tcp_device= TCP_DEVICE;
142 tcpfd= open(tcp_device, O_RDWR);
143 if (tcpfd == -1)
144 fatal("unable to open '%s': %s", tcp_device, strerror(errno));
145 tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA |
146 NWTC_SET_RP;
147 tcpconf.nwtc_remaddr= addr;
148 tcpconf.nwtc_remport= htons(port);;
149 if (ioctl(tcpfd, NWIOSTCPCONF, &tcpconf) == -1)
150 fatal("NWIOSTCPCONF failed: %s", strerror(errno));
152 if (timeout)
154 signal(SIGALRM, alrm_conn);
155 alarm(timeout);
158 tcpcl.nwtcl_flags= 0;
159 if (ioctl(tcpfd, NWIOTCPCONN, &tcpcl) == -1)
161 fatal("unable to connect to %s:%u: %s",
162 inet_ntoa(*(struct in_addr *)&addr),
163 ntohs(tcpconf.nwtc_remport), strerror(errno));
166 alarm(0);
168 if (bulk)
170 tcpopt.nwto_flags= NWTO_BULK;
171 if (ioctl(tcpfd, NWIOSTCPOPT, &tcpopt) == -1)
172 fatal("NWIOSTCPOPT failed: %s", strerror(errno));
176 static void alrm_conn(int sig)
178 fatal("timeout during connect");
181 static void alrm_io(int sig)
183 fatal("timeout during io");
186 static void fullduplex(void)
188 pid_t cpid;
189 int o, r, s, s_errno, loc;
191 cpid= fork();
192 switch(cpid)
194 case -1: fatal("fork failed: %s", strerror(errno));
195 case 0:
196 /* Read from TCP, write to stdout. */
197 for (;;)
199 r= read(tcpfd, buf, BUF_SIZE);
200 if (r == 0)
201 break;
202 if (r == -1)
204 r= errno;
205 if (stdout_issocket)
206 ioctl(1, NWIOTCPSHUTDOWN, NULL);
207 fatal("error reading from TCP conn.: %s",
208 strerror(errno));
210 s= r;
211 for (o= 0; o<s; o += r)
213 r= write(1, buf+o, s-o);
214 if (r <= 0)
216 fatal("error writing to stdout: %s",
217 r == 0 ? "EOF" :
218 strerror(errno));
222 if (stdout_issocket)
224 r= ioctl(1, NWIOTCPSHUTDOWN, NULL);
225 if (r == -1)
227 fatal("NWIOTCPSHUTDOWN failed on stdout: %s",
228 strerror(errno));
231 exit(0);
232 default:
233 break;
236 /* Read from stdin, write to TCP. */
237 for (;;)
239 r= read(0, buf, BUF_SIZE);
240 if (r == 0)
241 break;
242 if (r == -1)
244 s_errno= errno;
245 kill(cpid, SIGTERM);
246 fatal("error reading from stdin: %s",
247 strerror(s_errno));
249 s= r;
250 for (o= 0; o<s; o += r)
252 r= write(tcpfd, buf+o, s-o);
253 if (r <= 0)
255 s_errno= errno;
256 kill(cpid, SIGTERM);
257 fatal("error writing to TCP conn.: %s",
258 r == 0 ? "EOF" :
259 strerror(s_errno));
262 if (push)
263 ioctl(tcpfd, NWIOTCPPUSH, NULL);
265 if (ioctl(tcpfd, NWIOTCPSHUTDOWN, NULL) == -1)
267 s_errno= errno;
268 kill(cpid, SIGTERM);
269 fatal("unable to shut down TCP conn.: %s", strerror(s_errno));
272 r= waitpid(cpid, &loc, 0);
273 if (r == -1)
275 s_errno= errno;
276 kill(cpid, SIGTERM);
277 fatal("waitpid failed: %s", strerror(s_errno));
279 if (WIFEXITED(loc))
280 exit(WEXITSTATUS(loc));
281 kill(getpid(), WTERMSIG(loc));
282 exit(1);
285 static void fatal(char *fmt, ...)
287 va_list ap;
289 va_start(ap, fmt);
290 fprintf(stderr, "%s: ", progname);
291 vfprintf(stderr, fmt, ap);
292 fprintf(stderr, "\n");
293 va_end(ap);
294 exit(1);
297 static void usage(void)
299 fprintf(stderr, "Usage: %s [-BPs] [-t timeout] hostname portname\n",
300 progname);
301 exit(1);
305 * $PchId: socket.c,v 1.3 2005/01/31 22:33:20 philip Exp $