1 diff -bru gawk-3.1.5.orig/io.c gawk-3.1.5/io.c
2 --- gawk-3.1.5.orig/io.c 2006-07-07 16:13:08.000000000 +0200
3 +++ gawk-3.1.5/io.c 2006-07-10 13:18:13.000000000 +0200
8 -enum inet_prot { INET_NONE, INET_TCP, INET_UDP, INET_RAW };
12 @@ -1133,24 +1132,60 @@
13 /* socketopen --- open a socket and set it into connected state */
16 -socketopen(enum inet_prot type, int localport, int remoteport, const char *remotehostname)
17 +socketopen(int type, const char *localpname, const char *remotepname,
18 + const char *remotehostname)
20 - struct hostent *hp = gethostbyname(remotehostname);
21 - struct sockaddr_in local_addr, remote_addr;
22 + struct addrinfo *lres, *lres0;
23 + struct addrinfo lhints;
24 + struct addrinfo *rres, *rres0;
25 + struct addrinfo rhints;
31 int any_remote_host = strcmp(remotehostname, "0");
33 + memset (&lhints, '\0', sizeof (lhints));
34 + lhints.ai_flags = AI_PASSIVE | AI_ADDRCONFIG;
35 + lhints.ai_socktype = type;
37 + lerror = getaddrinfo (NULL, localpname, &lhints, &lres);
39 + if (strcmp(localpname, "0"))
40 + fatal(_("local port invalid in `/inet'"));
47 + memset (&rhints, '\0', sizeof (rhints));
48 + rhints.ai_flags = lhints.ai_flags;
49 + rhints.ai_socktype = lhints.ai_socktype;
50 + rhints.ai_family = lhints.ai_family;
51 + rhints.ai_protocol = lhints.ai_protocol;
53 + rerror = getaddrinfo (remotehostname, remotepname, &rhints, &rres);
56 + freeaddrinfo(lres0);
57 + fatal(_("remote host and port information invalid"));
60 socket_fd = INVALID_HANDLE;
63 - if (localport != 0 || remoteport != 0) {
65 + socket_fd = socket (rres->ai_family,
66 + rres->ai_socktype, rres->ai_protocol);
67 + if (socket_fd < 0 || socket_fd == INVALID_HANDLE)
70 + if (type == SOCK_STREAM) {
75 memset(& linger, '\0', sizeof(linger));
77 - socket_fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
78 setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR,
79 (char *) & on, sizeof(on));
81 @@ -1160,57 +1195,27 @@
82 (char *) & linger, sizeof(linger));
87 - if (localport != 0 || remoteport != 0)
88 - socket_fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
92 - if (localport == 0 && remoteport == 0)
93 - socket_fd = socket(AF_INET, SOCK_RAW, IPPROTO_RAW);
102 + if (bind(socket_fd, lres->ai_addr, lres->ai_addrlen) != 0)
105 - if (socket_fd < 0 || socket_fd == INVALID_HANDLE
106 - || (hp == NULL && any_remote_host != 0))
107 - return INVALID_HANDLE;
109 - local_addr.sin_family = remote_addr.sin_family = AF_INET;
110 - local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
111 - remote_addr.sin_addr.s_addr = htonl(INADDR_ANY);
112 - local_addr.sin_port = htons(localport);
113 - remote_addr.sin_port = htons(remoteport);
114 - if (bind(socket_fd, (struct sockaddr *) &local_addr, sizeof(local_addr)) == 0) {
115 if (any_remote_host != 0) { /* not ANY => create a client */
116 - if (type == INET_TCP || type == INET_UDP) {
117 - memcpy(&remote_addr.sin_addr, hp->h_addr,
118 - sizeof(remote_addr.sin_addr));
119 - if (connect(socket_fd,
120 - (struct sockaddr *) &remote_addr,
121 - sizeof(remote_addr)) != 0) {
123 - if (localport == 0)
124 - socket_fd = INVALID_HANDLE;
126 - socket_fd = socketopen(type, localport, 0, "0");
128 + if (type != SOCK_RAW) {
129 + if (connect(socket_fd, rres->ai_addr,
130 + rres->ai_addrlen) == 0)
133 /* /inet/raw client not ready yet */
134 fatal(_("/inet/raw client not ready yet, sorry"));
136 + /* FIXME: is this second fatal ever reached? */
137 fatal(_("only root may use `/inet/raw'."));
139 } else { /* remote host is ANY => create a server */
140 - if (type == INET_TCP) {
141 + if (type == SOCK_STREAM) {
142 int clientsocket_fd = INVALID_HANDLE;
143 - socklen_t namelen = sizeof(remote_addr);
145 + struct sockaddr_storage remote_addr;
146 + socklen_t namelen = sizeof (remote_addr);
148 if (listen(socket_fd, 1) >= 0
149 && (clientsocket_fd = accept(socket_fd,
150 @@ -1218,25 +1223,22 @@
153 socket_fd = clientsocket_fd;
156 - socket_fd = INVALID_HANDLE;
159 - } else if (type == INET_UDP) {
160 + } else if (type == SOCK_DGRAM) {
163 + struct sockaddr_storage remote_addr;
166 if (recvfrom(socket_fd, buf, 1, MSG_PEEK,
167 (struct sockaddr *) & remote_addr,
169 - || readle != sizeof(remote_addr)
170 - || connect(socket_fd,
173 + && connect(socket_fd,
174 (struct sockaddr *)& remote_addr,
177 - socket_fd = INVALID_HANDLE;
183 /* /inet/raw server not ready yet */
184 @@ -1245,10 +1247,20 @@
185 fatal(_("only root may use `/inet/raw'."));
191 + if (socket_fd != INVALID_HANDLE)
193 socket_fd = INVALID_HANDLE;
194 + rres = rres->ai_next;
196 + freeaddrinfo(rres0);
197 + if (socket_fd != INVALID_HANDLE)
199 + lres = lres->ai_next;
202 + freeaddrinfo(lres0);
206 @@ -1313,30 +1325,24 @@
207 } else if (STREQN(name, "/inet/", 6)) {
209 /* /inet/protocol/localport/hostname/remoteport */
210 - enum inet_prot protocol = INET_NONE;
211 - int localport, remoteport;
214 char *hostnameslastcharp;
217 - struct servent *service;
218 + char *localpnamelastcharp;
220 cp = (char *) name + 6;
221 /* which protocol? */
222 if (STREQN(cp, "tcp/", 4))
223 - protocol = INET_TCP;
224 + protocol = SOCK_STREAM;
225 else if (STREQN(cp, "udp/", 4))
226 - protocol = INET_UDP;
227 + protocol = SOCK_DGRAM;
228 else if (STREQN(cp, "raw/", 4))
229 - protocol = INET_RAW;
230 + protocol = SOCK_RAW;
232 fatal(_("no (known) protocol supplied in special filename `%s'"),
241 /* which localport? */
242 @@ -1354,25 +1360,17 @@
243 * By using atoi() the use of decimal numbers is enforced.
247 - localport = atoi(localpname);
248 - if (strcmp(localpname, "0") != 0
249 - && (localport <= 0 || localport > 65535)) {
250 - service = getservbyname(localpname, proto);
251 - if (service == NULL)
252 - fatal(_("local port invalid in `%s'"), name);
254 - localport = ntohs(service->s_port);
257 + localpnamelastcharp = cp;
259 /* which hostname? */
262 while (*cp != '/' && *cp != '\0')
264 - if (*cp != '/' || cp == hostname)
265 + if (*cp != '/' || cp == hostname) {
266 + *localpnamelastcharp = '/';
267 fatal(_("must supply a remote hostname to `/inet'"));
270 hostnameslastcharp = cp;
272 @@ -1386,22 +1384,15 @@
273 * Here too, require a port, let them explicitly put 0 if
278 + *localpnamelastcharp = '/';
279 + *hostnameslastcharp = '/';
280 fatal(_("must supply a remote port to `/inet'"));
281 - remoteport = atoi(cp);
282 - if (strcmp(cp, "0") != 0
283 - && (remoteport <= 0 || remoteport > 65535)) {
284 - service = getservbyname(cp, proto);
285 - if (service == NULL)
286 - fatal(_("remote port invalid in `%s'"), name);
288 - remoteport = ntohs(service->s_port);
292 - openfd = socketopen(protocol, localport, remoteport, hostname);
293 + openfd = socketopen(protocol, localpname, cp, hostname);
294 + *localpnamelastcharp = '/';
295 *hostnameslastcharp = '/';
297 #else /* ! HAVE_SOCKETS */
298 fatal(_("TCP/IP communications are not supported"));
299 #endif /* HAVE_SOCKETS */