home *** CD-ROM | disk | FTP | other *** search
/ OS/2 Shareware BBS: 10 Tools / 10-Tools.zip / perl560.zip / win32 / win32sck.c < prev    next >
C/C++ Source or Header  |  1999-11-08  |  13KB  |  670 lines

  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. #ifdef __GNUC__
  15. #define Win32_Winsock
  16. #endif
  17. #include <windows.h>
  18. #include "EXTERN.h"
  19. #include "perl.h"
  20.  
  21. #if defined(PERL_OBJECT)
  22. #define NO_XSLOCKS
  23. #include "XSUB.h"
  24. #endif
  25.  
  26. #include "Win32iop.h"
  27. #include <sys/socket.h>
  28. #include <fcntl.h>
  29. #include <sys/stat.h>
  30. #include <assert.h>
  31. #include <io.h>
  32.  
  33. /* thanks to Beverly Brown    (beverly@datacube.com) */
  34. #ifdef USE_SOCKETS_AS_HANDLES
  35. #    define OPEN_SOCKET(x)    win32_open_osfhandle(x,O_RDWR|O_BINARY)
  36. #    define TO_SOCKET(x)    _get_osfhandle(x)
  37. #else
  38. #    define OPEN_SOCKET(x)    (x)
  39. #    define TO_SOCKET(x)    (x)
  40. #endif    /* USE_SOCKETS_AS_HANDLES */
  41.  
  42. #ifdef USE_THREADS
  43. #define StartSockets() \
  44.     STMT_START {                    \
  45.     if (!wsock_started)                \
  46.         start_sockets();                \
  47.        set_socktype();                         \
  48.     } STMT_END
  49. #else
  50. #define StartSockets() \
  51.     STMT_START {                    \
  52.     if (!wsock_started) {                \
  53.         start_sockets();                \
  54.         set_socktype();                \
  55.     }                        \
  56.     } STMT_END
  57. #endif
  58.  
  59. #define EndSockets() \
  60.     STMT_START {                    \
  61.     if (wsock_started)                \
  62.         WSACleanup();                \
  63.     } STMT_END
  64.  
  65. #define SOCKET_TEST(x, y) \
  66.     STMT_START {                    \
  67.     StartSockets();                    \
  68.     if((x) == (y))                    \
  69.         errno = WSAGetLastError();            \
  70.     } STMT_END
  71.  
  72. #define SOCKET_TEST_ERROR(x) SOCKET_TEST(x, SOCKET_ERROR)
  73.  
  74. static struct servent* win32_savecopyservent(struct servent*d,
  75.                                              struct servent*s,
  76.                                              const char *proto);
  77.  
  78. static int wsock_started = 0;
  79.  
  80. void
  81. start_sockets(void) 
  82. {
  83.     dTHXo;
  84.     unsigned short version;
  85.     WSADATA retdata;
  86.     int ret;
  87.  
  88.     /*
  89.      * initalize the winsock interface and insure that it is
  90.      * cleaned up at exit.
  91.      */
  92.     version = 0x101;
  93.     if(ret = WSAStartup(version, &retdata))
  94.     Perl_croak_nocontext("Unable to locate winsock library!\n");
  95.     if(retdata.wVersion != version)
  96.     Perl_croak_nocontext("Could not find version 1.1 of winsock dll\n");
  97.  
  98.     /* atexit((void (*)(void)) EndSockets); */
  99.     wsock_started = 1;
  100. }
  101.  
  102. void
  103. set_socktype(void)
  104. {
  105. #ifdef USE_SOCKETS_AS_HANDLES
  106. #ifdef USE_THREADS
  107.     dTHX;
  108.     if (!w32_init_socktype) {
  109. #endif
  110.     int iSockOpt = SO_SYNCHRONOUS_NONALERT;
  111.     /*
  112.      * Enable the use of sockets as filehandles
  113.      */
  114.     setsockopt(INVALID_SOCKET, SOL_SOCKET, SO_OPENTYPE,
  115.             (char *)&iSockOpt, sizeof(iSockOpt));
  116. #ifdef USE_THREADS
  117.     w32_init_socktype = 1;
  118.     }
  119. #endif
  120. #endif    /* USE_SOCKETS_AS_HANDLES */
  121. }
  122.  
  123.  
  124. #ifndef USE_SOCKETS_AS_HANDLES
  125. #undef fdopen
  126. FILE *
  127. my_fdopen(int fd, char *mode)
  128. {
  129.     FILE *fp;
  130.     char sockbuf[256];
  131.     int optlen = sizeof(sockbuf);
  132.     int retval;
  133.  
  134.     if (!wsock_started)
  135.     return(fdopen(fd, mode));
  136.  
  137.     retval = getsockopt((SOCKET)fd, SOL_SOCKET, SO_TYPE, sockbuf, &optlen);
  138.     if(retval == SOCKET_ERROR && WSAGetLastError() == WSAENOTSOCK) {
  139.     return(fdopen(fd, mode));
  140.     }
  141.  
  142.     /*
  143.      * If we get here, then fd is actually a socket.
  144.      */
  145.     Newz(1310, fp, 1, FILE);
  146.     if(fp == NULL) {
  147.     errno = ENOMEM;
  148.     return NULL;
  149.     }
  150.  
  151.     fp->_file = fd;
  152.     if(*mode == 'r')
  153.     fp->_flag = _IOREAD;
  154.     else
  155.     fp->_flag = _IOWRT;
  156.    
  157.     return fp;
  158. }
  159. #endif    /* USE_SOCKETS_AS_HANDLES */
  160.  
  161.  
  162. u_long
  163. win32_htonl(u_long hostlong)
  164. {
  165.     StartSockets();
  166.     return htonl(hostlong);
  167. }
  168.  
  169. u_short
  170. win32_htons(u_short hostshort)
  171. {
  172.     StartSockets();
  173.     return htons(hostshort);
  174. }
  175.  
  176. u_long
  177. win32_ntohl(u_long netlong)
  178. {
  179.     StartSockets();
  180.     return ntohl(netlong);
  181. }
  182.  
  183. u_short
  184. win32_ntohs(u_short netshort)
  185. {
  186.     StartSockets();
  187.     return ntohs(netshort);
  188. }
  189.  
  190.  
  191.  
  192. SOCKET
  193. win32_accept(SOCKET s, struct sockaddr *addr, int *addrlen)
  194. {
  195.     SOCKET r;
  196.  
  197.     SOCKET_TEST((r = accept(TO_SOCKET(s), addr, addrlen)), INVALID_SOCKET);
  198.     return OPEN_SOCKET(r);
  199. }
  200.  
  201. int
  202. win32_bind(SOCKET s, const struct sockaddr *addr, int addrlen)
  203. {
  204.     int r;
  205.  
  206.     SOCKET_TEST_ERROR(r = bind(TO_SOCKET(s), addr, addrlen));
  207.     return r;
  208. }
  209.  
  210. int
  211. win32_connect(SOCKET s, const struct sockaddr *addr, int addrlen)
  212. {
  213.     int r;
  214.  
  215.     SOCKET_TEST_ERROR(r = connect(TO_SOCKET(s), addr, addrlen));
  216.     return r;
  217. }
  218.  
  219.  
  220. int
  221. win32_getpeername(SOCKET s, struct sockaddr *addr, int *addrlen)
  222. {
  223.     int r;
  224.  
  225.     SOCKET_TEST_ERROR(r = getpeername(TO_SOCKET(s), addr, addrlen));
  226.     return r;
  227. }
  228.  
  229. int
  230. win32_getsockname(SOCKET s, struct sockaddr *addr, int *addrlen)
  231. {
  232.     int r;
  233.  
  234.     SOCKET_TEST_ERROR(r = getsockname(TO_SOCKET(s), addr, addrlen));
  235.     return r;
  236. }
  237.  
  238. int
  239. win32_getsockopt(SOCKET s, int level, int optname, char *optval, int *optlen)
  240. {
  241.     int r;
  242.  
  243.     SOCKET_TEST_ERROR(r = getsockopt(TO_SOCKET(s), level, optname, optval, optlen));
  244.     return r;
  245. }
  246.  
  247. int
  248. win32_ioctlsocket(SOCKET s, long cmd, u_long *argp)
  249. {
  250.     int r;
  251.  
  252.     SOCKET_TEST_ERROR(r = ioctlsocket(TO_SOCKET(s), cmd, argp));
  253.     return r;
  254. }
  255.  
  256. int
  257. win32_listen(SOCKET s, int backlog)
  258. {
  259.     int r;
  260.  
  261.     SOCKET_TEST_ERROR(r = listen(TO_SOCKET(s), backlog));
  262.     return r;
  263. }
  264.  
  265. int
  266. win32_recv(SOCKET s, char *buf, int len, int flags)
  267. {
  268.     int r;
  269.  
  270.     SOCKET_TEST_ERROR(r = recv(TO_SOCKET(s), buf, len, flags));
  271.     return r;
  272. }
  273.  
  274. int
  275. win32_recvfrom(SOCKET s, char *buf, int len, int flags, struct sockaddr *from, int *fromlen)
  276. {
  277.     int r;
  278.     int frombufsize = *fromlen;
  279.  
  280.     SOCKET_TEST_ERROR(r = recvfrom(TO_SOCKET(s), buf, len, flags, from, fromlen));
  281.     /* Winsock's recvfrom() only returns a valid 'from' when the socket
  282.      * is connectionless.  Perl expects a valid 'from' for all types
  283.      * of sockets, so go the extra mile.
  284.      */
  285.     if (r != SOCKET_ERROR && frombufsize == *fromlen)
  286.     (void)win32_getpeername(s, from, fromlen);
  287.     return r;
  288. }
  289.  
  290. /* select contributed by Vincent R. Slyngstad (vrs@ibeam.intel.com) */
  291. int
  292. win32_select(int nfds, Perl_fd_set* rd, Perl_fd_set* wr, Perl_fd_set* ex, const struct timeval* timeout)
  293. {
  294.     int r;
  295. #ifdef USE_SOCKETS_AS_HANDLES
  296.     Perl_fd_set dummy;
  297.     int i, fd, bit, offset;
  298.     FD_SET nrd, nwr, nex, *prd, *pwr, *pex;
  299.  
  300.     /* winsock seems incapable of dealing with all three null fd_sets,
  301.      * so do the (millisecond) sleep as a special case
  302.      */
  303.     if (!(rd || wr || ex)) {
  304.     if (timeout)
  305.         Sleep(timeout->tv_sec  * 1000 +
  306.           timeout->tv_usec / 1000);    /* do the best we can */
  307.     else
  308.         Sleep(UINT_MAX);
  309.     return 0;
  310.     }
  311.     StartSockets();
  312.     PERL_FD_ZERO(&dummy);
  313.     if (!rd)
  314.     rd = &dummy, prd = NULL;
  315.     else
  316.     prd = &nrd;
  317.     if (!wr)
  318.     wr = &dummy, pwr = NULL;
  319.     else
  320.     pwr = &nwr;
  321.     if (!ex)
  322.     ex = &dummy, pex = NULL;
  323.     else
  324.     pex = &nex;
  325.  
  326.     FD_ZERO(&nrd);
  327.     FD_ZERO(&nwr);
  328.     FD_ZERO(&nex);
  329.     for (i = 0; i < nfds; i++) {
  330.     fd = TO_SOCKET(i);
  331.     if (PERL_FD_ISSET(i,rd))
  332.         FD_SET(fd, &nrd);
  333.     if (PERL_FD_ISSET(i,wr))
  334.         FD_SET(fd, &nwr);
  335.     if (PERL_FD_ISSET(i,ex))
  336.         FD_SET(fd, &nex);
  337.     }
  338.  
  339.     SOCKET_TEST_ERROR(r = select(nfds, prd, pwr, pex, timeout));
  340.  
  341.     for (i = 0; i < nfds; i++) {
  342.     fd = TO_SOCKET(i);
  343.     if (PERL_FD_ISSET(i,rd) && !FD_ISSET(fd, &nrd))
  344.         PERL_FD_CLR(i,rd);
  345.     if (PERL_FD_ISSET(i,wr) && !FD_ISSET(fd, &nwr))
  346.         PERL_FD_CLR(i,wr);
  347.     if (PERL_FD_ISSET(i,ex) && !FD_ISSET(fd, &nex))
  348.         PERL_FD_CLR(i,ex);
  349.     }
  350. #else
  351.     SOCKET_TEST_ERROR(r = select(nfds, rd, wr, ex, timeout));
  352. #endif
  353.     return r;
  354. }
  355.  
  356. int
  357. win32_send(SOCKET s, const char *buf, int len, int flags)
  358. {
  359.     int r;
  360.  
  361.     SOCKET_TEST_ERROR(r = send(TO_SOCKET(s), buf, len, flags));
  362.     return r;
  363. }
  364.  
  365. int
  366. win32_sendto(SOCKET s, const char *buf, int len, int flags,
  367.          const struct sockaddr *to, int tolen)
  368. {
  369.     int r;
  370.  
  371.     SOCKET_TEST_ERROR(r = sendto(TO_SOCKET(s), buf, len, flags, to, tolen));
  372.     return r;
  373. }
  374.  
  375. int
  376. win32_setsockopt(SOCKET s, int level, int optname, const char *optval, int optlen)
  377. {
  378.     int r;
  379.  
  380.     SOCKET_TEST_ERROR(r = setsockopt(TO_SOCKET(s), level, optname, optval, optlen));
  381.     return r;
  382. }
  383.     
  384. int
  385. win32_shutdown(SOCKET s, int how)
  386. {
  387.     int r;
  388.  
  389.     SOCKET_TEST_ERROR(r = shutdown(TO_SOCKET(s), how));
  390.     return r;
  391. }
  392.  
  393. int
  394. win32_closesocket(SOCKET s)
  395. {
  396.     int r;
  397.  
  398.     SOCKET_TEST_ERROR(r = closesocket(TO_SOCKET(s)));
  399.     return r;
  400. }
  401.  
  402. SOCKET
  403. win32_socket(int af, int type, int protocol)
  404. {
  405.     SOCKET s;
  406.  
  407. #ifndef USE_SOCKETS_AS_HANDLES
  408.     SOCKET_TEST(s = socket(af, type, protocol), INVALID_SOCKET);
  409. #else
  410.     StartSockets();
  411.     if((s = socket(af, type, protocol)) == INVALID_SOCKET)
  412.     errno = WSAGetLastError();
  413.     else
  414.     s = OPEN_SOCKET(s);
  415. #endif    /* USE_SOCKETS_AS_HANDLES */
  416.  
  417.     return s;
  418. }
  419.  
  420. #undef fclose
  421. int
  422. my_fclose (FILE *pf)
  423. {
  424.     int osf, retval;
  425.     if (!wsock_started)        /* No WinSock? */
  426.     return(fclose(pf));    /* Then not a socket. */
  427.     osf = TO_SOCKET(fileno(pf));/* Get it now before it's gone! */
  428.     retval = fclose(pf);    /* Must fclose() before closesocket() */
  429.     if (osf != -1
  430.     && closesocket(osf) == SOCKET_ERROR
  431.     && WSAGetLastError() != WSAENOTSOCK)
  432.     {
  433.     return EOF;
  434.     }
  435.     return retval;
  436. }
  437.  
  438. struct hostent *
  439. win32_gethostbyaddr(const char *addr, int len, int type)
  440. {
  441.     struct hostent *r;
  442.  
  443.     SOCKET_TEST(r = gethostbyaddr(addr, len, type), NULL);
  444.     return r;
  445. }
  446.  
  447. struct hostent *
  448. win32_gethostbyname(const char *name)
  449. {
  450.     struct hostent *r;
  451.  
  452.     SOCKET_TEST(r = gethostbyname(name), NULL);
  453.     return r;
  454. }
  455.  
  456. int
  457. win32_gethostname(char *name, int len)
  458. {
  459.     int r;
  460.  
  461.     SOCKET_TEST_ERROR(r = gethostname(name, len));
  462.     return r;
  463. }
  464.  
  465. struct protoent *
  466. win32_getprotobyname(const char *name)
  467. {
  468.     struct protoent *r;
  469.  
  470.     SOCKET_TEST(r = getprotobyname(name), NULL);
  471.     return r;
  472. }
  473.  
  474. struct protoent *
  475. win32_getprotobynumber(int num)
  476. {
  477.     struct protoent *r;
  478.  
  479.     SOCKET_TEST(r = getprotobynumber(num), NULL);
  480.     return r;
  481. }
  482.  
  483. struct servent *
  484. win32_getservbyname(const char *name, const char *proto)
  485. {
  486.     dTHXo;    
  487.     struct servent *r;
  488.  
  489.     SOCKET_TEST(r = getservbyname(name, proto), NULL);
  490.     if (r) {
  491.     r = win32_savecopyservent(&w32_servent, r, proto);
  492.     }
  493.     return r;
  494. }
  495.  
  496. struct servent *
  497. win32_getservbyport(int port, const char *proto)
  498. {
  499.     dTHXo; 
  500.     struct servent *r;
  501.  
  502.     SOCKET_TEST(r = getservbyport(port, proto), NULL);
  503.     if (r) {
  504.     r = win32_savecopyservent(&w32_servent, r, proto);
  505.     }
  506.     return r;
  507. }
  508.  
  509. int
  510. win32_ioctl(int i, unsigned int u, char *data)
  511. {
  512.     dTHXo;
  513.     u_long argp = (u_long)data;
  514.     int retval;
  515.  
  516.     if (!wsock_started) {
  517.     Perl_croak_nocontext("ioctl implemented only on sockets");
  518.     /* NOTREACHED */
  519.     }
  520.  
  521.     retval = ioctlsocket(TO_SOCKET(i), (long)u, &argp);
  522.     if (retval == SOCKET_ERROR) {
  523.     if (WSAGetLastError() == WSAENOTSOCK) {
  524.         Perl_croak_nocontext("ioctl implemented only on sockets");
  525.         /* NOTREACHED */
  526.     }
  527.     errno = WSAGetLastError();
  528.     }
  529.     return retval;
  530. }
  531.  
  532. char FAR *
  533. win32_inet_ntoa(struct in_addr in)
  534. {
  535.     StartSockets();
  536.     return inet_ntoa(in);
  537. }
  538.  
  539. unsigned long
  540. win32_inet_addr(const char FAR *cp)
  541. {
  542.     StartSockets();
  543.     return inet_addr(cp);
  544. }
  545.  
  546. /*
  547.  * Networking stubs
  548.  */
  549.  
  550. void
  551. win32_endhostent() 
  552. {
  553.     dTHXo;
  554.     Perl_croak_nocontext("endhostent not implemented!\n");
  555. }
  556.  
  557. void
  558. win32_endnetent()
  559. {
  560.     dTHXo;
  561.     Perl_croak_nocontext("endnetent not implemented!\n");
  562. }
  563.  
  564. void
  565. win32_endprotoent()
  566. {
  567.     dTHXo;
  568.     Perl_croak_nocontext("endprotoent not implemented!\n");
  569. }
  570.  
  571. void
  572. win32_endservent()
  573. {
  574.     dTHXo;
  575.     Perl_croak_nocontext("endservent not implemented!\n");
  576. }
  577.  
  578.  
  579. struct netent *
  580. win32_getnetent(void) 
  581. {
  582.     dTHXo;
  583.     Perl_croak_nocontext("getnetent not implemented!\n");
  584.     return (struct netent *) NULL;
  585. }
  586.  
  587. struct netent *
  588. win32_getnetbyname(char *name) 
  589. {
  590.     dTHXo;
  591.     Perl_croak_nocontext("getnetbyname not implemented!\n");
  592.     return (struct netent *)NULL;
  593. }
  594.  
  595. struct netent *
  596. win32_getnetbyaddr(long net, int type) 
  597. {
  598.     dTHXo;
  599.     Perl_croak_nocontext("getnetbyaddr not implemented!\n");
  600.     return (struct netent *)NULL;
  601. }
  602.  
  603. struct protoent *
  604. win32_getprotoent(void) 
  605. {
  606.     dTHXo;
  607.     Perl_croak_nocontext("getprotoent not implemented!\n");
  608.     return (struct protoent *) NULL;
  609. }
  610.  
  611. struct servent *
  612. win32_getservent(void) 
  613. {
  614.     dTHXo;
  615.     Perl_croak_nocontext("getservent not implemented!\n");
  616.     return (struct servent *) NULL;
  617. }
  618.  
  619. void
  620. win32_sethostent(int stayopen)
  621. {
  622.     dTHXo;
  623.     Perl_croak_nocontext("sethostent not implemented!\n");
  624. }
  625.  
  626.  
  627. void
  628. win32_setnetent(int stayopen)
  629. {
  630.     dTHXo;
  631.     Perl_croak_nocontext("setnetent not implemented!\n");
  632. }
  633.  
  634.  
  635. void
  636. win32_setprotoent(int stayopen)
  637. {
  638.     dTHXo;
  639.     Perl_croak_nocontext("setprotoent not implemented!\n");
  640. }
  641.  
  642.  
  643. void
  644. win32_setservent(int stayopen)
  645. {
  646.     dTHXo;
  647.     Perl_croak_nocontext("setservent not implemented!\n");
  648. }
  649.  
  650. static struct servent*
  651. win32_savecopyservent(struct servent*d, struct servent*s, const char *proto)
  652. {
  653.     d->s_name = s->s_name;
  654.     d->s_aliases = s->s_aliases;
  655.     d->s_port = s->s_port;
  656. #ifndef __BORLANDC__    /* Buggy on Win95 and WinNT-with-Borland-WSOCK */
  657.     if (!IsWin95() && s->s_proto && strlen(s->s_proto))
  658.     d->s_proto = s->s_proto;
  659.     else
  660. #endif
  661.     if (proto && strlen(proto))
  662.     d->s_proto = (char *)proto;
  663.     else
  664.     d->s_proto = "tcp";
  665.    
  666.     return d;
  667. }
  668.  
  669.  
  670.