Commit | Line | Data |
---|---|---|
cb69f87a | 1 | /* Time-stamp: <01/08/01 21:01:12 keuchel@w2k> */ |
e1caacb4 JH |
2 | |
3 | /* wincesck.c | |
4 | * | |
f4257e4d | 5 | * (c) 1995 Microsoft Corporation. All rights reserved. |
0d130a44 | 6 | * Developed by hip communications inc. |
e1caacb4 JH |
7 | * Portions (c) 1993 Intergraph Corporation. All rights reserved. |
8 | * | |
9 | * You may distribute under the terms of either the GNU General Public | |
10 | * License or the Artistic License, as specified in the README file. | |
11 | */ | |
12 | ||
cb69f87a | 13 | /* The socket calls use fd functions from celib... */ |
e1caacb4 JH |
14 | |
15 | #define WIN32IO_IS_STDIO | |
16 | #define WIN32SCK_IS_STDSCK | |
17 | #define WIN32_LEAN_AND_MEAN | |
18 | ||
19 | #ifdef __GNUC__ | |
20 | #define Win32_Winsock | |
21 | #endif | |
22 | ||
23 | #include <windows.h> | |
24 | ||
25 | #define wince_private | |
26 | #include "errno.h" | |
27 | ||
28 | #include "EXTERN.h" | |
29 | #include "perl.h" | |
30 | ||
e1caacb4 JH |
31 | #include "Win32iop.h" |
32 | #include <sys/socket.h> | |
33 | ||
34 | #ifndef UNDER_CE | |
35 | #include <fcntl.h> | |
36 | #include <sys/stat.h> | |
37 | #include <assert.h> | |
38 | #include <io.h> | |
39 | #endif | |
40 | ||
41 | #ifdef UNDER_CE | |
42 | ||
43 | XCE_EXPORT struct servent *xcegetservbyname(const char *sname, const char *sproto); | |
44 | XCE_EXPORT struct servent * xcegetservbyport(int aport, const char *sproto); | |
45 | XCE_EXPORT struct protoent *xcegetprotobyname(const char *name); | |
46 | XCE_EXPORT struct protoent *xcegetprotobynumber(int number); | |
47 | ||
48 | #define getservbyname xcegetservbyname | |
49 | #define getservbyport xcegetservbyport | |
50 | #define getprotobyname xcegetprotobyname | |
51 | #define getprotobynumber xcegetprotobynumber | |
52 | ||
cb69f87a | 53 | /* uses fdtab... */ |
e1caacb4 JH |
54 | #include "cesocket2.h" |
55 | ||
56 | #endif | |
57 | ||
58 | #define TO_SOCKET(X) (X) | |
59 | ||
e1caacb4 JH |
60 | #define StartSockets() \ |
61 | STMT_START { \ | |
cf46c829 | 62 | if (!wsock_started) \ |
e1caacb4 | 63 | start_sockets(); \ |
e1caacb4 | 64 | } STMT_END |
e1caacb4 | 65 | |
e1caacb4 JH |
66 | #define SOCKET_TEST(x, y) \ |
67 | STMT_START { \ | |
68 | StartSockets(); \ | |
69 | if((x) == (y)) \ | |
70 | errno = WSAGetLastError(); \ | |
71 | } STMT_END | |
72 | ||
73 | #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) | |
74 | ||
75 | static struct servent* win32_savecopyservent(struct servent*d, | |
76 | struct servent*s, | |
77 | const char *proto); | |
78 | ||
79 | static int wsock_started = 0; | |
80 | ||
f4257e4d YO |
81 | EXTERN_C void |
82 | EndSockets(void) | |
83 | { | |
84 | if (wsock_started) | |
85 | WSACleanup(); | |
86 | } | |
87 | ||
e1caacb4 | 88 | void |
f4257e4d | 89 | start_sockets(void) |
e1caacb4 | 90 | { |
acfe0abc | 91 | dTHX; |
e1caacb4 JH |
92 | unsigned short version; |
93 | WSADATA retdata; | |
94 | int ret; | |
95 | ||
96 | /* | |
97 | * initalize the winsock interface and insure that it is | |
98 | * cleaned up at exit. | |
99 | */ | |
100 | version = 0x101; | |
101 | if(ret = WSAStartup(version, &retdata)) | |
102 | Perl_croak_nocontext("Unable to locate winsock library!\n"); | |
103 | if(retdata.wVersion != version) | |
104 | Perl_croak_nocontext("Could not find version 1.1 of winsock dll\n"); | |
105 | ||
106 | /* atexit((void (*)(void)) EndSockets); */ | |
107 | wsock_started = 1; | |
108 | } | |
109 | ||
e1caacb4 JH |
110 | u_long |
111 | win32_htonl(u_long hostlong) | |
112 | { | |
113 | StartSockets(); | |
114 | return htonl(hostlong); | |
115 | } | |
116 | ||
117 | u_short | |
118 | win32_htons(u_short hostshort) | |
119 | { | |
120 | StartSockets(); | |
121 | return htons(hostshort); | |
122 | } | |
123 | ||
124 | u_long | |
125 | win32_ntohl(u_long netlong) | |
126 | { | |
127 | StartSockets(); | |
128 | return ntohl(netlong); | |
129 | } | |
130 | ||
131 | u_short | |
132 | win32_ntohs(u_short netshort) | |
133 | { | |
134 | StartSockets(); | |
135 | return ntohs(netshort); | |
136 | } | |
137 | ||
138 | SOCKET | |
139 | win32_socket(int af, int type, int protocol) | |
140 | { | |
141 | StartSockets(); | |
142 | return xcesocket(af, type, protocol); | |
143 | } | |
144 | ||
145 | SOCKET | |
146 | win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) | |
147 | { | |
148 | StartSockets(); | |
149 | return xceaccept(s, addr, addrlen); | |
150 | } | |
151 | ||
152 | int | |
153 | win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) | |
154 | { | |
155 | StartSockets(); | |
156 | return xcebind(s, addr, addrlen); | |
157 | } | |
158 | ||
159 | int | |
160 | win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) | |
161 | { | |
162 | StartSockets(); | |
163 | return xceconnect(s, addr, addrlen); | |
164 | } | |
165 | ||
166 | ||
167 | int | |
168 | win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) | |
169 | { | |
170 | StartSockets(); | |
171 | return xcegetpeername(s, addr, addrlen); | |
172 | } | |
173 | ||
174 | int | |
175 | win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) | |
176 | { | |
177 | StartSockets(); | |
178 | return xcegetsockname(s, addr, addrlen); | |
179 | } | |
180 | ||
181 | int | |
182 | win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) | |
183 | { | |
184 | StartSockets(); | |
185 | return xcegetsockopt(s, level, optname, optval, optlen); | |
186 | } | |
187 | ||
188 | int | |
189 | win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) | |
190 | { | |
191 | StartSockets(); | |
192 | return xceioctlsocket(s, cmd, argp); | |
193 | } | |
194 | ||
195 | int | |
196 | win32_listen(SOCKET s, int backlog) | |
197 | { | |
198 | StartSockets(); | |
199 | return xcelisten(s, backlog); | |
200 | } | |
201 | ||
202 | int | |
203 | win32_recv(SOCKET s, char *buf, int len, int flags) | |
204 | { | |
205 | StartSockets(); | |
206 | return xcerecv(s, buf, len, flags); | |
207 | } | |
208 | ||
209 | int | |
f4257e4d | 210 | win32_recvfrom(SOCKET s, char *buf, int len, int flags, |
e1caacb4 JH |
211 | struct sockaddr *from, int *fromlen) |
212 | { | |
213 | StartSockets(); | |
214 | return xcerecvfrom(s, buf, len, flags, from, fromlen); | |
215 | } | |
216 | ||
217 | int | |
f4257e4d | 218 | win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, |
e1caacb4 JH |
219 | Perl_fd_set* ex, const struct timeval* timeout) |
220 | { | |
221 | StartSockets(); | |
cb69f87a | 222 | /* select not yet fixed */ |
e1caacb4 JH |
223 | errno = ENOSYS; |
224 | return -1; | |
225 | } | |
226 | ||
227 | int | |
228 | win32_send(SOCKET s, const char *buf, int len, int flags) | |
229 | { | |
230 | StartSockets(); | |
231 | return xcesend(s, buf, len, flags); | |
232 | } | |
233 | ||
234 | int | |
235 | win32_sendto(SOCKET s, const char *buf, int len, int flags, | |
236 | const struct sockaddr *to, int tolen) | |
237 | { | |
238 | StartSockets(); | |
239 | return xcesendto(s, buf, len, flags, to, tolen); | |
240 | } | |
241 | ||
242 | int | |
f4257e4d | 243 | win32_setsockopt(SOCKET s, int level, int optname, |
e1caacb4 JH |
244 | const char *optval, int optlen) |
245 | { | |
246 | StartSockets(); | |
247 | return xcesetsockopt(s, level, optname, optval, optlen); | |
248 | } | |
f4257e4d | 249 | |
e1caacb4 JH |
250 | int |
251 | win32_shutdown(SOCKET s, int how) | |
252 | { | |
253 | StartSockets(); | |
254 | return xceshutdown(s, how); | |
255 | } | |
256 | ||
257 | int | |
258 | win32_closesocket(SOCKET s) | |
259 | { | |
260 | StartSockets(); | |
261 | return xceclosesocket(s); | |
262 | } | |
263 | ||
264 | struct hostent * | |
265 | win32_gethostbyaddr(const char *addr, int len, int type) | |
266 | { | |
267 | struct hostent *r; | |
268 | ||
269 | SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL); | |
270 | return r; | |
271 | } | |
272 | ||
273 | struct hostent * | |
274 | win32_gethostbyname(const char *name) | |
275 | { | |
276 | struct hostent *r; | |
277 | ||
278 | SOCKET_TEST(r = gethostbyname(name), NULL); | |
279 | return r; | |
280 | } | |
281 | ||
282 | int | |
283 | win32_gethostname(char *name, int len) | |
284 | { | |
285 | int r; | |
286 | ||
287 | SOCKET_TEST_ERROR(r = gethostname(name, len)); | |
288 | return r; | |
289 | } | |
290 | ||
291 | struct protoent * | |
292 | win32_getprotobyname(const char *name) | |
293 | { | |
294 | struct protoent *r; | |
295 | ||
296 | SOCKET_TEST(r = getprotobyname(name), NULL); | |
297 | return r; | |
298 | } | |
299 | ||
300 | struct protoent * | |
301 | win32_getprotobynumber(int num) | |
302 | { | |
303 | struct protoent *r; | |
304 | ||
305 | SOCKET_TEST(r = getprotobynumber(num), NULL); | |
306 | return r; | |
307 | } | |
308 | ||
309 | struct servent * | |
310 | win32_getservbyname(const char *name, const char *proto) | |
311 | { | |
f4257e4d | 312 | dTHX; |
e1caacb4 JH |
313 | struct servent *r; |
314 | ||
315 | SOCKET_TEST(r = getservbyname(name, proto), NULL); | |
316 | if (r) { | |
317 | r = win32_savecopyservent(&w32_servent, r, proto); | |
318 | } | |
319 | return r; | |
320 | } | |
321 | ||
322 | struct servent * | |
323 | win32_getservbyport(int port, const char *proto) | |
324 | { | |
f4257e4d | 325 | dTHX; |
e1caacb4 JH |
326 | struct servent *r; |
327 | ||
328 | SOCKET_TEST(r = getservbyport(port, proto), NULL); | |
329 | if (r) { | |
330 | r = win32_savecopyservent(&w32_servent, r, proto); | |
331 | } | |
332 | return r; | |
333 | } | |
334 | ||
335 | int | |
336 | win32_ioctl(int i, unsigned int u, char *data) | |
337 | { | |
acfe0abc | 338 | dTHX; |
d1b0f603 | 339 | u_long u_long_arg; |
e1caacb4 | 340 | int retval; |
d1b0f603 | 341 | |
e1caacb4 JH |
342 | if (!wsock_started) { |
343 | Perl_croak_nocontext("ioctl implemented only on sockets"); | |
344 | /* NOTREACHED */ | |
345 | } | |
346 | ||
d1b0f603 RGS |
347 | /* mauke says using memcpy avoids alignment issues */ |
348 | memcpy(&u_long_arg, data, sizeof u_long_arg); | |
349 | retval = ioctlsocket(TO_SOCKET(i), (long)u, &u_long_arg); | |
350 | memcpy(data, &u_long_arg, sizeof u_long_arg); | |
351 | ||
e1caacb4 JH |
352 | if (retval == SOCKET_ERROR) { |
353 | if (WSAGetLastError() == WSAENOTSOCK) { | |
354 | Perl_croak_nocontext("ioctl implemented only on sockets"); | |
355 | /* NOTREACHED */ | |
356 | } | |
357 | errno = WSAGetLastError(); | |
358 | } | |
359 | return retval; | |
360 | } | |
361 | ||
362 | char FAR * | |
363 | win32_inet_ntoa(struct in_addr in) | |
364 | { | |
365 | StartSockets(); | |
366 | return inet_ntoa(in); | |
367 | } | |
368 | ||
369 | unsigned long | |
370 | win32_inet_addr(const char FAR *cp) | |
371 | { | |
372 | StartSockets(); | |
373 | return inet_addr(cp); | |
374 | } | |
375 | ||
376 | /* | |
377 | * Networking stubs | |
378 | */ | |
379 | ||
380 | void | |
f4257e4d | 381 | win32_endhostent() |
e1caacb4 | 382 | { |
acfe0abc | 383 | dTHX; |
e1caacb4 JH |
384 | Perl_croak_nocontext("endhostent not implemented!\n"); |
385 | } | |
386 | ||
387 | void | |
388 | win32_endnetent() | |
389 | { | |
acfe0abc | 390 | dTHX; |
e1caacb4 JH |
391 | Perl_croak_nocontext("endnetent not implemented!\n"); |
392 | } | |
393 | ||
394 | void | |
395 | win32_endprotoent() | |
396 | { | |
acfe0abc | 397 | dTHX; |
e1caacb4 JH |
398 | Perl_croak_nocontext("endprotoent not implemented!\n"); |
399 | } | |
400 | ||
401 | void | |
402 | win32_endservent() | |
403 | { | |
acfe0abc | 404 | dTHX; |
e1caacb4 JH |
405 | Perl_croak_nocontext("endservent not implemented!\n"); |
406 | } | |
407 | ||
408 | ||
409 | struct netent * | |
f4257e4d | 410 | win32_getnetent(void) |
e1caacb4 | 411 | { |
acfe0abc | 412 | dTHX; |
e1caacb4 JH |
413 | Perl_croak_nocontext("getnetent not implemented!\n"); |
414 | return (struct netent *) NULL; | |
415 | } | |
416 | ||
417 | struct netent * | |
f4257e4d | 418 | win32_getnetbyname(char *name) |
e1caacb4 | 419 | { |
acfe0abc | 420 | dTHX; |
e1caacb4 JH |
421 | Perl_croak_nocontext("getnetbyname not implemented!\n"); |
422 | return (struct netent *)NULL; | |
423 | } | |
424 | ||
425 | struct netent * | |
f4257e4d | 426 | win32_getnetbyaddr(long net, int type) |
e1caacb4 | 427 | { |
acfe0abc | 428 | dTHX; |
e1caacb4 JH |
429 | Perl_croak_nocontext("getnetbyaddr not implemented!\n"); |
430 | return (struct netent *)NULL; | |
431 | } | |
432 | ||
433 | struct protoent * | |
f4257e4d | 434 | win32_getprotoent(void) |
e1caacb4 | 435 | { |
acfe0abc | 436 | dTHX; |
e1caacb4 JH |
437 | Perl_croak_nocontext("getprotoent not implemented!\n"); |
438 | return (struct protoent *) NULL; | |
439 | } | |
440 | ||
441 | struct servent * | |
f4257e4d | 442 | win32_getservent(void) |
e1caacb4 | 443 | { |
acfe0abc | 444 | dTHX; |
e1caacb4 JH |
445 | Perl_croak_nocontext("getservent not implemented!\n"); |
446 | return (struct servent *) NULL; | |
447 | } | |
448 | ||
449 | void | |
450 | win32_sethostent(int stayopen) | |
451 | { | |
acfe0abc | 452 | dTHX; |
e1caacb4 JH |
453 | Perl_croak_nocontext("sethostent not implemented!\n"); |
454 | } | |
455 | ||
456 | ||
457 | void | |
458 | win32_setnetent(int stayopen) | |
459 | { | |
acfe0abc | 460 | dTHX; |
e1caacb4 JH |
461 | Perl_croak_nocontext("setnetent not implemented!\n"); |
462 | } | |
463 | ||
464 | ||
465 | void | |
466 | win32_setprotoent(int stayopen) | |
467 | { | |
acfe0abc | 468 | dTHX; |
e1caacb4 JH |
469 | Perl_croak_nocontext("setprotoent not implemented!\n"); |
470 | } | |
471 | ||
472 | ||
473 | void | |
474 | win32_setservent(int stayopen) | |
475 | { | |
acfe0abc | 476 | dTHX; |
e1caacb4 JH |
477 | Perl_croak_nocontext("setservent not implemented!\n"); |
478 | } | |
479 | ||
480 | static struct servent* | |
481 | win32_savecopyservent(struct servent*d, struct servent*s, const char *proto) | |
482 | { | |
483 | d->s_name = s->s_name; | |
484 | d->s_aliases = s->s_aliases; | |
485 | d->s_port = s->s_port; | |
e1caacb4 JH |
486 | if (!IsWin95() && s->s_proto && strlen(s->s_proto)) |
487 | d->s_proto = s->s_proto; | |
488 | else | |
e1caacb4 JH |
489 | if (proto && strlen(proto)) |
490 | d->s_proto = (char *)proto; | |
491 | else | |
492 | d->s_proto = "tcp"; | |
f4257e4d | 493 | |
e1caacb4 JH |
494 | return d; |
495 | } |