| 1 | /* Time-stamp: <01/08/01 21:01:12 keuchel@w2k> */ |
| 2 | |
| 3 | /* wincesck.c |
| 4 | * |
| 5 | * (c) 1995 Microsoft Corporation. All rights reserved. |
| 6 | * Developed by hip communications inc. |
| 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 | |
| 13 | /* The socket calls use fd functions from celib... */ |
| 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 | |
| 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 | |
| 53 | /* uses fdtab... */ |
| 54 | #include "cesocket2.h" |
| 55 | |
| 56 | #endif |
| 57 | |
| 58 | #define TO_SOCKET(X) (X) |
| 59 | |
| 60 | #define StartSockets() \ |
| 61 | STMT_START { \ |
| 62 | if (!wsock_started) \ |
| 63 | start_sockets(); \ |
| 64 | } STMT_END |
| 65 | |
| 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 | |
| 81 | EXTERN_C void |
| 82 | EndSockets(void) |
| 83 | { |
| 84 | if (wsock_started) |
| 85 | WSACleanup(); |
| 86 | } |
| 87 | |
| 88 | void |
| 89 | start_sockets(void) |
| 90 | { |
| 91 | dTHX; |
| 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 | |
| 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 |
| 210 | win32_recvfrom(SOCKET s, char *buf, int len, int flags, |
| 211 | struct sockaddr *from, int *fromlen) |
| 212 | { |
| 213 | StartSockets(); |
| 214 | return xcerecvfrom(s, buf, len, flags, from, fromlen); |
| 215 | } |
| 216 | |
| 217 | int |
| 218 | win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, |
| 219 | Perl_fd_set* ex, const struct timeval* timeout) |
| 220 | { |
| 221 | StartSockets(); |
| 222 | /* select not yet fixed */ |
| 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 |
| 243 | win32_setsockopt(SOCKET s, int level, int optname, |
| 244 | const char *optval, int optlen) |
| 245 | { |
| 246 | StartSockets(); |
| 247 | return xcesetsockopt(s, level, optname, optval, optlen); |
| 248 | } |
| 249 | |
| 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 | { |
| 312 | dTHX; |
| 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 | { |
| 325 | dTHX; |
| 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 | { |
| 338 | dTHX; |
| 339 | u_long u_long_arg; |
| 340 | int retval; |
| 341 | |
| 342 | if (!wsock_started) { |
| 343 | Perl_croak_nocontext("ioctl implemented only on sockets"); |
| 344 | /* NOTREACHED */ |
| 345 | } |
| 346 | |
| 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 | |
| 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 |
| 381 | win32_endhostent() |
| 382 | { |
| 383 | dTHX; |
| 384 | Perl_croak_nocontext("endhostent not implemented!\n"); |
| 385 | } |
| 386 | |
| 387 | void |
| 388 | win32_endnetent() |
| 389 | { |
| 390 | dTHX; |
| 391 | Perl_croak_nocontext("endnetent not implemented!\n"); |
| 392 | } |
| 393 | |
| 394 | void |
| 395 | win32_endprotoent() |
| 396 | { |
| 397 | dTHX; |
| 398 | Perl_croak_nocontext("endprotoent not implemented!\n"); |
| 399 | } |
| 400 | |
| 401 | void |
| 402 | win32_endservent() |
| 403 | { |
| 404 | dTHX; |
| 405 | Perl_croak_nocontext("endservent not implemented!\n"); |
| 406 | } |
| 407 | |
| 408 | |
| 409 | struct netent * |
| 410 | win32_getnetent(void) |
| 411 | { |
| 412 | dTHX; |
| 413 | Perl_croak_nocontext("getnetent not implemented!\n"); |
| 414 | return (struct netent *) NULL; |
| 415 | } |
| 416 | |
| 417 | struct netent * |
| 418 | win32_getnetbyname(char *name) |
| 419 | { |
| 420 | dTHX; |
| 421 | Perl_croak_nocontext("getnetbyname not implemented!\n"); |
| 422 | return (struct netent *)NULL; |
| 423 | } |
| 424 | |
| 425 | struct netent * |
| 426 | win32_getnetbyaddr(long net, int type) |
| 427 | { |
| 428 | dTHX; |
| 429 | Perl_croak_nocontext("getnetbyaddr not implemented!\n"); |
| 430 | return (struct netent *)NULL; |
| 431 | } |
| 432 | |
| 433 | struct protoent * |
| 434 | win32_getprotoent(void) |
| 435 | { |
| 436 | dTHX; |
| 437 | Perl_croak_nocontext("getprotoent not implemented!\n"); |
| 438 | return (struct protoent *) NULL; |
| 439 | } |
| 440 | |
| 441 | struct servent * |
| 442 | win32_getservent(void) |
| 443 | { |
| 444 | dTHX; |
| 445 | Perl_croak_nocontext("getservent not implemented!\n"); |
| 446 | return (struct servent *) NULL; |
| 447 | } |
| 448 | |
| 449 | void |
| 450 | win32_sethostent(int stayopen) |
| 451 | { |
| 452 | dTHX; |
| 453 | Perl_croak_nocontext("sethostent not implemented!\n"); |
| 454 | } |
| 455 | |
| 456 | |
| 457 | void |
| 458 | win32_setnetent(int stayopen) |
| 459 | { |
| 460 | dTHX; |
| 461 | Perl_croak_nocontext("setnetent not implemented!\n"); |
| 462 | } |
| 463 | |
| 464 | |
| 465 | void |
| 466 | win32_setprotoent(int stayopen) |
| 467 | { |
| 468 | dTHX; |
| 469 | Perl_croak_nocontext("setprotoent not implemented!\n"); |
| 470 | } |
| 471 | |
| 472 | |
| 473 | void |
| 474 | win32_setservent(int stayopen) |
| 475 | { |
| 476 | dTHX; |
| 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; |
| 486 | if (!IsWin95() && s->s_proto && strlen(s->s_proto)) |
| 487 | d->s_proto = s->s_proto; |
| 488 | else |
| 489 | if (proto && strlen(proto)) |
| 490 | d->s_proto = (char *)proto; |
| 491 | else |
| 492 | d->s_proto = "tcp"; |
| 493 | |
| 494 | return d; |
| 495 | } |