arm: protect state after signal handler
[minix.git] / commands / swifi / socket.c
blob324b7f11633fd17f58b0c883072e42b1eed9d5a1
1 /*
2 socket.c
4 Created: Feb 2001 by Philip Homburg <philip@f-mnx.phicoh.com>
6 Open a TCP connection
7 */
9 #define _POSIX_C_SOURCE 2
11 #include <errno.h>
12 #include <fcntl.h>
13 #include <stdarg.h>
14 #include <stdio.h>
15 #include <stdlib.h>
16 #include <signal.h>
17 #include <string.h>
18 #include <unistd.h>
20 #include <sys/ioctl.h>
21 #include <sys/wait.h>
23 #include <net/hton.h>
24 #include <net/netlib.h>
25 #include <net/gen/in.h>
26 #include <net/gen/inet.h>
27 #include <net/gen/netdb.h>
28 #include <net/gen/socket.h>
29 #include <net/gen/tcp.h>
30 #include <net/gen/tcp_io.h>
32 #define BUF_SIZE 10240
34 char *progname;
35 int tcpfd= -1;
36 char buf[BUF_SIZE];
37 static int bulk= 0;
38 static int push= 0;
39 static int stdout_issocket= 0;
40 static int timeout;
42 static void do_conn(char *hostname, char *portname);
43 static void alrm_conn(int sig);
44 static void alrm_io(int sig);
45 static void fullduplex(void);
46 static void fatal(char *msg, ...);
47 static void usage(void);
49 int main(int argc, char *argv[])
51 int c;
52 char *hostname;
53 char *portname;
54 char *check;
55 int B_flag, P_flag, s_flag;
56 char *t_arg;
58 (progname=strrchr(argv[0],'/')) ? progname++ : (progname=argv[0]);
60 B_flag= 0;
61 P_flag= 0;
62 s_flag= 0;
63 t_arg= NULL;
64 while (c= getopt(argc, argv, "BPst:?"), c != -1)
66 switch(c)
68 case 'B': B_flag= 1; break;
69 case 'P': P_flag= 1; break;
70 case 's': s_flag= 1; break;
71 case 't': t_arg= optarg; break;
72 case '?': usage();
73 default:
74 fatal("getopt failed: '%c'", c);
77 if (t_arg)
79 timeout= strtol(t_arg, &check, 0);
80 if (check[0] != '\0')
81 fatal("unable to parse timeout '%s'\n", t_arg);
82 if (timeout <= 0)
83 fatal("bad timeout '%d'\n", timeout);
85 else
86 timeout= 0;
88 if (optind+2 != argc)
89 usage();
90 hostname= argv[optind++];
91 portname= argv[optind++];
93 bulk= B_flag;
94 push= P_flag;
95 stdout_issocket= s_flag;
97 do_conn(hostname, portname);
99 /* XXX */
100 if (timeout)
102 signal(SIGALRM, alrm_io);
103 alarm(timeout);
106 fullduplex();
107 exit(0);
110 static void do_conn(char *hostname, char *portname)
112 ipaddr_t addr;
113 tcpport_t port;
114 struct hostent *he;
115 struct servent *se;
116 char *tcp_device, *check;
117 nwio_tcpconf_t tcpconf;
118 nwio_tcpcl_t tcpcl;
119 nwio_tcpopt_t tcpopt;
121 if (!inet_aton(hostname, &addr))
123 he= gethostbyname(hostname);
124 if (he == NULL)
125 fatal("unknown hostname '%s'", hostname);
126 if (he->h_addrtype != AF_INET || he->h_length != sizeof(addr))
127 fatal("bad address for '%s'", hostname);
128 memcpy(&addr, he->h_addr, sizeof(addr));
131 port= strtol(portname, &check, 0);
132 if (check[0] != 0)
134 se= getservbyname(portname, "tcp");
135 if (se == NULL)
136 fatal("unkown port '%s'", portname);
137 port= ntohs(se->s_port);
140 tcp_device= getenv("TCP_DEVICE");
141 if (tcp_device == NULL) tcp_device= TCP_DEVICE;
143 tcpfd= open(tcp_device, O_RDWR);
144 if (tcpfd == -1)
145 fatal("unable to open '%s': %s", tcp_device, strerror(errno));
146 tcpconf.nwtc_flags= NWTC_EXCL | NWTC_LP_SEL | NWTC_SET_RA |
147 NWTC_SET_RP;
148 tcpconf.nwtc_remaddr= addr;
149 tcpconf.nwtc_remport= htons(port);;
150 if (ioctl(tcpfd, NWIOSTCPCONF, &tcpconf) == -1)
151 fatal("NWIOSTCPCONF failed: %s", strerror(errno));
153 if (timeout)
155 signal(SIGALRM, alrm_conn);
156 alarm(timeout);
159 tcpcl.nwtcl_flags= 0;
160 if (ioctl(tcpfd, NWIOTCPCONN, &tcpcl) == -1)
162 fatal("unable to connect to %s:%u: %s", inet_ntoa(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 $