1 /* win32sck.c 2 * 3 * (c) 1995 Microsoft Corporation. All rights reserved. 4 * Developed by hip communications inc., http://info.hip.com/info/ 5 * Portions (c) 1993 Intergraph Corporation. All rights reserved. 6 * 7 * You may distribute under the terms of either the GNU General Public 8 * License or the Artistic License, as specified in the README file. 9 */ 10 11 #define WIN32IO_IS_STDIO 12 #define WIN32SCK_IS_STDSCK 13 #define WIN32_LEAN_AND_MEAN 14 #define PERLIO_NOT_STDIO 0 15 #ifdef __GNUC__ 16 #define Win32_Winsock 17 #endif 18 #include <windows.h> 19 #include <ws2spi.h> 20 21 #include "EXTERN.h" 22 #include "perl.h" 23 24 #include "Win32iop.h" 25 #include <sys/socket.h> 26 #include <fcntl.h> 27 #include <sys/stat.h> 28 #include <assert.h> 29 #include <io.h> 30 31 /* thanks to Beverly Brown (beverly@datacube.com) */ 32 #ifdef USE_SOCKETS_AS_HANDLES 33 # define OPEN_SOCKET(x) win32_open_osfhandle(x,O_RDWR|O_BINARY) 34 # define TO_SOCKET(x) _get_osfhandle(x) 35 #else 36 # define OPEN_SOCKET(x) (x) 37 # define TO_SOCKET(x) (x) 38 #endif /* USE_SOCKETS_AS_HANDLES */ 39 40 #if defined(USE_5005THREADS) || defined(USE_ITHREADS) 41 #define StartSockets() \ 42 STMT_START { \ 43 if (!wsock_started) \ 44 start_sockets(); \ 45 set_socktype(); \ 46 } STMT_END 47 #else 48 #define StartSockets() \ 49 STMT_START { \ 50 if (!wsock_started) { \ 51 start_sockets(); \ 52 set_socktype(); \ 53 } \ 54 } STMT_END 55 #endif 56 57 #define SOCKET_TEST(x, y) \ 58 STMT_START { \ 59 StartSockets(); \ 60 if((x) == (y)) \ 61 errno = WSAGetLastError(); \ 62 } STMT_END 63 64 #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR) 65 66 static struct servent* win32_savecopyservent(struct servent*d, 67 struct servent*s, 68 const char *proto); 69 70 static int wsock_started = 0; 71 72 EXTERN_C void 73 EndSockets(void) 74 { 75 if (wsock_started) 76 WSACleanup(); 77 } 78 79 void 80 start_sockets(void) 81 { 82 dTHX; 83 unsigned short version; 84 WSADATA retdata; 85 int ret; 86 87 /* 88 * initalize the winsock interface and insure that it is 89 * cleaned up at exit. 90 */ 91 version = 0x2; 92 if(ret = WSAStartup(version, &retdata)) 93 Perl_croak_nocontext("Unable to locate winsock library!\n"); 94 if(retdata.wVersion != version) 95 Perl_croak_nocontext("Could not find version 2.0 of winsock dll\n"); 96 97 /* atexit((void (*)(void)) EndSockets); */ 98 wsock_started = 1; 99 } 100 101 void 102 set_socktype(void) 103 { 104 #ifdef USE_SOCKETS_AS_HANDLES 105 #if defined(USE_5005THREADS) || defined(USE_ITHREADS) 106 dTHX; 107 if (!w32_init_socktype) { 108 w32_init_socktype = 1; 109 } 110 #endif 111 #endif /* USE_SOCKETS_AS_HANDLES */ 112 } 113 114 115 #ifndef USE_SOCKETS_AS_HANDLES 116 #undef fdopen 117 FILE * 118 my_fdopen(int fd, char *mode) 119 { 120 FILE *fp; 121 char sockbuf[256]; 122 int optlen = sizeof(sockbuf); 123 int retval; 124 125 if (!wsock_started) 126 return(fdopen(fd, mode)); 127 128 retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen); 129 if(retval == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) { 130 return(fdopen(fd, mode)); 131 } 132 133 /* 134 * If we get here, then fd is actually a socket. 135 */ 136 Newxz(fp, 1, FILE); /* XXX leak, good thing this code isn't used */ 137 if(fp == NULL) { 138 errno = ENOMEM; 139 return NULL; 140 } 141 142 fp->_file = fd; 143 if(*mode == 'r') 144 fp->_flag = _IOREAD; 145 else 146 fp->_flag = _IOWRT; 147 148 return fp; 149 } 150 #endif /* USE_SOCKETS_AS_HANDLES */ 151 152 153 u_long 154 win32_htonl(u_long hostlong) 155 { 156 StartSockets(); 157 return htonl(hostlong); 158 } 159 160 u_short 161 win32_htons(u_short hostshort) 162 { 163 StartSockets(); 164 return htons(hostshort); 165 } 166 167 u_long 168 win32_ntohl(u_long netlong) 169 { 170 StartSockets(); 171 return ntohl(netlong); 172 } 173 174 u_short 175 win32_ntohs(u_short netshort) 176 { 177 StartSockets(); 178 return ntohs(netshort); 179 } 180 181 182 183 SOCKET 184 win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen) 185 { 186 SOCKET r; 187 188 SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET); 189 return OPEN_SOCKET(r); 190 } 191 192 int 193 win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen) 194 { 195 int r; 196 197 SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen)); 198 return r; 199 } 200 201 int 202 win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen) 203 { 204 int r; 205 206 SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen)); 207 return r; 208 } 209 210 211 int 212 win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen) 213 { 214 int r; 215 216 SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen)); 217 return r; 218 } 219 220 int 221 win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen) 222 { 223 int r; 224 225 SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen)); 226 return r; 227 } 228 229 int 230 win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen) 231 { 232 int r; 233 234 SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen)); 235 return r; 236 } 237 238 int 239 win32_ioctlsocket(SOCKET s, long cmd, u_long *argp) 240 { 241 int r; 242 243 SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp)); 244 return r; 245 } 246 247 int 248 win32_listen(SOCKET s, int backlog) 249 { 250 int r; 251 252 SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog)); 253 return r; 254 } 255 256 int 257 win32_recv(SOCKET s, char *buf, int len, int flags) 258 { 259 int r; 260 261 SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags)); 262 return r; 263 } 264 265 int 266 win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen) 267 { 268 int r; 269 int frombufsize = *fromlen; 270 271 SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen)); 272 /* Winsock's recvfrom() only returns a valid 'from' when the socket 273 * is connectionless. Perl expects a valid 'from' for all types 274 * of sockets, so go the extra mile. 275 */ 276 if (r != SOCKET_ERROR && frombufsize == *fromlen) 277 (void)win32_getpeername(s, from, fromlen); 278 return r; 279 } 280 281 /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */ 282 int 283 win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout) 284 { 285 int r; 286 #ifdef USE_SOCKETS_AS_HANDLES 287 Perl_fd_set dummy; 288 int i, fd, save_errno = errno; 289 FD_SET nrd, nwr, nex, *prd, *pwr, *pex; 290 291 /* winsock seems incapable of dealing with all three null fd_sets, 292 * so do the (millisecond) sleep as a special case 293 */ 294 if (!(rd || wr || ex)) { 295 if (timeout) 296 Sleep(timeout->tv_sec * 1000 + 297 timeout->tv_usec / 1000); /* do the best we can */ 298 else 299 Sleep(UINT_MAX); 300 return 0; 301 } 302 StartSockets(); 303 PERL_FD_ZERO(&dummy); 304 if (!rd) 305 rd = &dummy, prd = NULL; 306 else 307 prd = &nrd; 308 if (!wr) 309 wr = &dummy, pwr = NULL; 310 else 311 pwr = &nwr; 312 if (!ex) 313 ex = &dummy, pex = NULL; 314 else 315 pex = &nex; 316 317 FD_ZERO(&nrd); 318 FD_ZERO(&nwr); 319 FD_ZERO(&nex); 320 for (i = 0; i < nfds; i++) { 321 fd = TO_SOCKET(i); 322 if (PERL_FD_ISSET(i,rd)) 323 FD_SET((unsigned)fd, &nrd); 324 if (PERL_FD_ISSET(i,wr)) 325 FD_SET((unsigned)fd, &nwr); 326 if (PERL_FD_ISSET(i,ex)) 327 FD_SET((unsigned)fd, &nex); 328 } 329 330 errno = save_errno; 331 SOCKET_TEST_ERROR(r = select(nfds, prd, pwr, pex, timeout)); 332 save_errno = errno; 333 334 for (i = 0; i < nfds; i++) { 335 fd = TO_SOCKET(i); 336 if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd)) 337 PERL_FD_CLR(i,rd); 338 if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr)) 339 PERL_FD_CLR(i,wr); 340 if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex)) 341 PERL_FD_CLR(i,ex); 342 } 343 errno = save_errno; 344 #else 345 SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout)); 346 #endif 347 return r; 348 } 349 350 int 351 win32_send(SOCKET s, const char *buf, int len, int flags) 352 { 353 int r; 354 355 SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags)); 356 return r; 357 } 358 359 int 360 win32_sendto(SOCKET s, const char *buf, int len, int flags, 361 const struct sockaddr *to, int tolen) 362 { 363 int r; 364 365 SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen)); 366 return r; 367 } 368 369 int 370 win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen) 371 { 372 int r; 373 374 SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen)); 375 return r; 376 } 377 378 int 379 win32_shutdown(SOCKET s, int how) 380 { 381 int r; 382 383 SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how)); 384 return r; 385 } 386 387 int 388 win32_closesocket(SOCKET s) 389 { 390 int r; 391 392 SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s))); 393 return r; 394 } 395 396 #ifdef USE_SOCKETS_AS_HANDLES 397 #define WIN32_OPEN_SOCKET(af, type, protocol) open_ifs_socket(af, type, protocol) 398 399 void 400 convert_proto_info_w2a(WSAPROTOCOL_INFOW *in, WSAPROTOCOL_INFOA *out) 401 { 402 Copy(in, out, 1, WSAPROTOCOL_INFOA); 403 wcstombs(out->szProtocol, in->szProtocol, sizeof(out->szProtocol)); 404 } 405 406 SOCKET 407 open_ifs_socket(int af, int type, int protocol) 408 { 409 dTHX; 410 char *s; 411 unsigned long proto_buffers_len = 0; 412 int error_code; 413 SOCKET out = INVALID_SOCKET; 414 415 if ((s = PerlEnv_getenv("PERL_ALLOW_NON_IFS_LSP")) && atoi(s)) 416 return WSASocket(af, type, protocol, NULL, 0, 0); 417 418 if (WSCEnumProtocols(NULL, NULL, &proto_buffers_len, &error_code) == SOCKET_ERROR 419 && error_code == WSAENOBUFS) 420 { 421 WSAPROTOCOL_INFOW *proto_buffers; 422 int protocols_available = 0; 423 424 Newx(proto_buffers, proto_buffers_len / sizeof(WSAPROTOCOL_INFOW), 425 WSAPROTOCOL_INFOW); 426 427 if ((protocols_available = WSCEnumProtocols(NULL, proto_buffers, 428 &proto_buffers_len, &error_code)) != SOCKET_ERROR) 429 { 430 int i; 431 for (i = 0; i < protocols_available; i++) 432 { 433 WSAPROTOCOL_INFOA proto_info; 434 435 if ((af != AF_UNSPEC && af != proto_buffers[i].iAddressFamily) 436 || (type != proto_buffers[i].iSocketType) 437 || (protocol != 0 && proto_buffers[i].iProtocol != 0 && 438 protocol != proto_buffers[i].iProtocol)) 439 continue; 440 441 if ((proto_buffers[i].dwServiceFlags1 & XP1_IFS_HANDLES) == 0) 442 continue; 443 444 convert_proto_info_w2a(&(proto_buffers[i]), &proto_info); 445 446 out = WSASocket(af, type, protocol, &proto_info, 0, 0); 447 break; 448 } 449 } 450 451 Safefree(proto_buffers); 452 } 453 454 return out; 455 } 456 457 #else 458 #define WIN32_OPEN_SOCKET(af, type, protocol) socket(af, type, protocol) 459 #endif 460 461 SOCKET 462 win32_socket(int af, int type, int protocol) 463 { 464 SOCKET s; 465 466 #ifndef USE_SOCKETS_AS_HANDLES 467 SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET); 468 #else 469 StartSockets(); 470 471 if((s = WIN32_OPEN_SOCKET(af, type, protocol)) == INVALID_SOCKET) 472 errno = WSAGetLastError(); 473 else 474 s = OPEN_SOCKET(s); 475 #endif /* USE_SOCKETS_AS_HANDLES */ 476 477 return s; 478 } 479 480 /* 481 * close RTL fd while respecting sockets 482 * added as temporary measure until PerlIO has real 483 * Win32 native layer 484 * -- BKS, 11-11-2000 485 */ 486 487 int my_close(int fd) 488 { 489 int osf; 490 if (!wsock_started) /* No WinSock? */ 491 return(close(fd)); /* Then not a socket. */ 492 osf = TO_SOCKET(fd);/* Get it now before it's gone! */ 493 if (osf != -1) { 494 int err; 495 err = closesocket(osf); 496 if (err == 0) { 497 #if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX) 498 _set_osfhnd(fd, INVALID_HANDLE_VALUE); 499 #endif 500 (void)close(fd); /* handle already closed, ignore error */ 501 return 0; 502 } 503 else if (err == SOCKET_ERROR) { 504 err = WSAGetLastError(); 505 if (err != WSAENOTSOCK) { 506 (void)close(fd); 507 errno = err; 508 return EOF; 509 } 510 } 511 } 512 return close(fd); 513 } 514 515 #undef fclose 516 int 517 my_fclose (FILE *pf) 518 { 519 int osf; 520 if (!wsock_started) /* No WinSock? */ 521 return(fclose(pf)); /* Then not a socket. */ 522 osf = TO_SOCKET(win32_fileno(pf));/* Get it now before it's gone! */ 523 if (osf != -1) { 524 int err; 525 win32_fflush(pf); 526 err = closesocket(osf); 527 if (err == 0) { 528 #if defined(USE_FIXED_OSFHANDLE) || defined(PERL_MSVCRT_READFIX) 529 _set_osfhnd(win32_fileno(pf), INVALID_HANDLE_VALUE); 530 #endif 531 (void)fclose(pf); /* handle already closed, ignore error */ 532 return 0; 533 } 534 else if (err == SOCKET_ERROR) { 535 err = WSAGetLastError(); 536 if (err != WSAENOTSOCK) { 537 (void)fclose(pf); 538 errno = err; 539 return EOF; 540 } 541 } 542 } 543 return fclose(pf); 544 } 545 546 #undef fstat 547 int 548 my_fstat(int fd, Stat_t *sbufptr) 549 { 550 /* This fixes a bug in fstat() on Windows 9x. fstat() uses the 551 * GetFileType() win32 syscall, which will fail on Windows 9x. 552 * So if we recognize a socket on Windows 9x, we return the 553 * same results as on Windows NT/2000. 554 * XXX this should be extended further to set S_IFSOCK on 555 * sbufptr->st_mode. 556 */ 557 int osf; 558 if (!wsock_started || IsWinNT()) { 559 #if defined(WIN64) || defined(USE_LARGE_FILES) 560 #if defined(__BORLANDC__) /* buk */ 561 return win32_fstat(fd, sbufptr ); 562 #else 563 return _fstati64(fd, sbufptr); 564 #endif 565 #else 566 return fstat(fd, sbufptr); 567 #endif 568 } 569 570 osf = TO_SOCKET(fd); 571 if (osf != -1) { 572 char sockbuf[256]; 573 int optlen = sizeof(sockbuf); 574 int retval; 575 576 retval = getsockopt((SOCKET)osf, SOL_SOCKET, SO_TYPE, sockbuf, &optlen); 577 if (retval != SOCKET_ERROR || WSAGetLastError() != WSAENOTSOCK) { 578 #if defined(__BORLANDC__)&&(__BORLANDC__<=0x520) 579 sbufptr->st_mode = S_IFIFO; 580 #else 581 sbufptr->st_mode = _S_IFIFO; 582 #endif 583 sbufptr->st_rdev = sbufptr->st_dev = (dev_t)fd; 584 sbufptr->st_nlink = 1; 585 sbufptr->st_uid = sbufptr->st_gid = sbufptr->st_ino = 0; 586 sbufptr->st_atime = sbufptr->st_mtime = sbufptr->st_ctime = 0; 587 sbufptr->st_size = (Off_t)0; 588 return 0; 589 } 590 } 591 #if defined(WIN64) || defined(USE_LARGE_FILES) 592 #if defined(__BORLANDC__) /* buk */ 593 return win32_fstat(fd, sbufptr ); 594 #else 595 return _fstati64(fd, sbufptr); 596 #endif 597 #else 598 return fstat(fd, sbufptr); 599 #endif 600 } 601 602 struct hostent * 603 win32_gethostbyaddr(const char *addr, int len, int type) 604 { 605 struct hostent *r; 606 607 SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL); 608 return r; 609 } 610 611 struct hostent * 612 win32_gethostbyname(const char *name) 613 { 614 struct hostent *r; 615 616 SOCKET_TEST(r = gethostbyname(name), NULL); 617 return r; 618 } 619 620 int 621 win32_gethostname(char *name, int len) 622 { 623 int r; 624 625 SOCKET_TEST_ERROR(r = gethostname(name, len)); 626 return r; 627 } 628 629 struct protoent * 630 win32_getprotobyname(const char *name) 631 { 632 struct protoent *r; 633 634 SOCKET_TEST(r = getprotobyname(name), NULL); 635 return r; 636 } 637 638 struct protoent * 639 win32_getprotobynumber(int num) 640 { 641 struct protoent *r; 642 643 SOCKET_TEST(r = getprotobynumber(num), NULL); 644 return r; 645 } 646 647 struct servent * 648 win32_getservbyname(const char *name, const char *proto) 649 { 650 dTHX; 651 struct servent *r; 652 653 SOCKET_TEST(r = getservbyname(name, proto), NULL); 654 if (r) { 655 r = win32_savecopyservent(&w32_servent, r, proto); 656 } 657 return r; 658 } 659 660 struct servent * 661 win32_getservbyport(int port, const char *proto) 662 { 663 dTHX; 664 struct servent *r; 665 666 SOCKET_TEST(r = getservbyport(port, proto), NULL); 667 if (r) { 668 r = win32_savecopyservent(&w32_servent, r, proto); 669 } 670 return r; 671 } 672 673 int 674 win32_ioctl(int i, unsigned int u, char *data) 675 { 676 dTHX; 677 u_long argp = (u_long)data; 678 int retval; 679 680 if (!wsock_started) { 681 Perl_croak_nocontext("ioctl implemented only on sockets"); 682 /* NOTREACHED */ 683 } 684 685 retval = ioctlsocket(TO_SOCKET(i), (long)u, &argp); 686 if (retval == SOCKET_ERROR) { 687 if (WSAGetLastError() == WSAENOTSOCK) { 688 Perl_croak_nocontext("ioctl implemented only on sockets"); 689 /* NOTREACHED */ 690 } 691 errno = WSAGetLastError(); 692 } 693 return retval; 694 } 695 696 char FAR * 697 win32_inet_ntoa(struct in_addr in) 698 { 699 StartSockets(); 700 return inet_ntoa(in); 701 } 702 703 unsigned long 704 win32_inet_addr(const char FAR *cp) 705 { 706 StartSockets(); 707 return inet_addr(cp); 708 } 709 710 /* 711 * Networking stubs 712 */ 713 714 void 715 win32_endhostent() 716 { 717 dTHX; 718 Perl_croak_nocontext("endhostent not implemented!\n"); 719 } 720 721 void 722 win32_endnetent() 723 { 724 dTHX; 725 Perl_croak_nocontext("endnetent not implemented!\n"); 726 } 727 728 void 729 win32_endprotoent() 730 { 731 dTHX; 732 Perl_croak_nocontext("endprotoent not implemented!\n"); 733 } 734 735 void 736 win32_endservent() 737 { 738 dTHX; 739 Perl_croak_nocontext("endservent not implemented!\n"); 740 } 741 742 743 struct netent * 744 win32_getnetent(void) 745 { 746 dTHX; 747 Perl_croak_nocontext("getnetent not implemented!\n"); 748 return (struct netent *) NULL; 749 } 750 751 struct netent * 752 win32_getnetbyname(char *name) 753 { 754 dTHX; 755 Perl_croak_nocontext("getnetbyname not implemented!\n"); 756 return (struct netent *)NULL; 757 } 758 759 struct netent * 760 win32_getnetbyaddr(long net, int type) 761 { 762 dTHX; 763 Perl_croak_nocontext("getnetbyaddr not implemented!\n"); 764 return (struct netent *)NULL; 765 } 766 767 struct protoent * 768 win32_getprotoent(void) 769 { 770 dTHX; 771 Perl_croak_nocontext("getprotoent not implemented!\n"); 772 return (struct protoent *) NULL; 773 } 774 775 struct servent * 776 win32_getservent(void) 777 { 778 dTHX; 779 Perl_croak_nocontext("getservent not implemented!\n"); 780 return (struct servent *) NULL; 781 } 782 783 void 784 win32_sethostent(int stayopen) 785 { 786 dTHX; 787 Perl_croak_nocontext("sethostent not implemented!\n"); 788 } 789 790 791 void 792 win32_setnetent(int stayopen) 793 { 794 dTHX; 795 Perl_croak_nocontext("setnetent not implemented!\n"); 796 } 797 798 799 void 800 win32_setprotoent(int stayopen) 801 { 802 dTHX; 803 Perl_croak_nocontext("setprotoent not implemented!\n"); 804 } 805 806 807 void 808 win32_setservent(int stayopen) 809 { 810 dTHX; 811 Perl_croak_nocontext("setservent not implemented!\n"); 812 } 813 814 static struct servent* 815 win32_savecopyservent(struct servent*d, struct servent*s, const char *proto) 816 { 817 d->s_name = s->s_name; 818 d->s_aliases = s->s_aliases; 819 d->s_port = s->s_port; 820 #ifndef __BORLANDC__ /* Buggy on Win95 and WinNT-with-Borland-WSOCK */ 821 if (!IsWin95() && s->s_proto && strlen(s->s_proto)) 822 d->s_proto = s->s_proto; 823 else 824 #endif 825 if (proto && strlen(proto)) 826 d->s_proto = (char *)proto; 827 else 828 d->s_proto = "tcp"; 829 830 return d; 831 } 832 833 834