aboutsummaryrefslogtreecommitdiffstats
path: root/lib-src/pop.c
diff options
context:
space:
mode:
authorEli Zaretskii2016-03-05 12:12:58 +0200
committerEli Zaretskii2016-03-05 12:12:58 +0200
commitbc96f6e827ba079006ae87914395942fc79f3f26 (patch)
treec980a478b0229057db165de1fec6a40fc56b1f0b /lib-src/pop.c
parentac9a931d595dd83ebac61c6c9cf7388985fee277 (diff)
downloademacs-bc96f6e827ba079006ae87914395942fc79f3f26.tar.gz
emacs-bc96f6e827ba079006ae87914395942fc79f3f26.zip
Implement getaddrinfo fallback for MS-Windows
See http://lists.gnu.org/archive/html/emacs-devel/2016-02/msg01602.html for more details. * nt/mingw-cfg.site (ac_cv_func_getaddrinfo) (ac_cv_func_gai_strerror): Set to "yes", as the configure script's test program is not smart enough to auto-detect these. * nt/inc/sys/socket.h (getaddrinfo, freeaddrinfo): Redirect to sys_getaddrinfo and sys_freeaddrinfo. Provide prototypes for sys_getaddrinfo and sys_freeaddrinfo. * src/w32.c (init_winsock): Try loading getaddrinfo and freeaddrinfo from ws2_32.dll. (sys_getaddrinfo, sys_freeaddrinfo): New functions. * lib-src/pop.c [WINDOWSNT]: Include winsock2.h, not winsock.h, and also ws2tcpip.h. (getaddrinfo, freeaddrinfo) [WINDOWSNT]: Redirect to sys_getaddrinfo and sys_freeaddrinfo, respectively. (load_ws2, sys_getaddrinfo, sys_freeaddrinfo) [WINDOWSNT]: New functions.
Diffstat (limited to 'lib-src/pop.c')
-rw-r--r--lib-src/pop.c151
1 files changed, 150 insertions, 1 deletions
diff --git a/lib-src/pop.c b/lib-src/pop.c
index 812bd4ca24c..21d721546b7 100644
--- a/lib-src/pop.c
+++ b/lib-src/pop.c
@@ -28,7 +28,17 @@ along with GNU Emacs. If not, see <http://www.gnu.org/licenses/>. */
28#include <sys/types.h> 28#include <sys/types.h>
29#ifdef WINDOWSNT 29#ifdef WINDOWSNT
30#include "ntlib.h" 30#include "ntlib.h"
31#include <winsock.h> 31#undef _WIN32_WINNT
32#define _WIN32_WINNT 0x0501 /* for getaddrinfo stuff */
33#include <winsock2.h>
34#include <ws2tcpip.h>
35#undef getaddrinfo
36#define getaddrinfo sys_getaddrinfo
37#undef freeaddrinfo
38#define freeaddrinfo sys_freeaddrinfo
39int sys_getaddrinfo (const char * node, const char * service,
40 const struct addrinfo * hints, struct addrinfo ** res);
41void sys_freeaddrinfo (struct addrinfo * ai);
32#undef SOCKET_ERROR 42#undef SOCKET_ERROR
33#define RECV(s,buf,len,flags) recv (s,buf,len,flags) 43#define RECV(s,buf,len,flags) recv (s,buf,len,flags)
34#define SEND(s,buf,len,flags) send (s,buf,len,flags) 44#define SEND(s,buf,len,flags) send (s,buf,len,flags)
@@ -1581,4 +1591,143 @@ find_crlf (char *in_string, int len)
1581 return (0); 1591 return (0);
1582} 1592}
1583 1593
1594#ifdef WINDOWSNT
1595/* The following 2 functions are only available since XP, so we load
1596 them dynamically and provide fallbacks. */
1597
1598int (WINAPI *pfn_getaddrinfo) (const char *, const char *,
1599 const struct addrinfo *, struct addrinfo **);
1600void (WINAPI *pfn_freeaddrinfo) (struct addrinfo *);
1601
1602static int
1603load_ws2 (void)
1604{
1605 static int ws2_loaded = 0;
1606
1607 if (!ws2_loaded)
1608 {
1609 HANDLE ws2_lib = LoadLibrary ("Ws2_32.dll");
1610
1611 if (ws2_lib != NULL)
1612 {
1613 ws2_loaded = 1;
1614 pfn_getaddrinfo = (void *) GetProcAddress (ws2_lib, "getaddrinfo");
1615 pfn_freeaddrinfo = (void *) GetProcAddress (ws2_lib, "freeaddrinfo");
1616 /* Paranoia: these two functions should go together, so if
1617 one is absent, we cannot use the other. */
1618 if (pfn_getaddrinfo == NULL)
1619 pfn_freeaddrinfo = NULL;
1620 else if (pfn_freeaddrinfo == NULL)
1621 pfn_getaddrinfo = NULL;
1622 }
1623 }
1624 if (!ws2_loaded)
1625 {
1626 errno = ENETDOWN;
1627 return -1;
1628 }
1629 return 0;
1630}
1631
1632
1633int
1634sys_getaddrinfo (const char *node, const char *service,
1635 const struct addrinfo *hints, struct addrinfo **res)
1636{
1637 int rc;
1638
1639 if (load_ws2 () != 0)
1640 {
1641 errno = ENETDOWN;
1642 return WSANO_RECOVERY;
1643 }
1644
1645 if (pfn_getaddrinfo)
1646 rc = pfn_getaddrinfo (node, service, hints, res);
1647 else
1648 {
1649 int port = 0;
1650 struct hostent *host_info;
1651 struct gai_storage {
1652 struct addrinfo addrinfo;
1653 struct sockaddr_in sockaddr_in;
1654 } *gai_storage;
1655
1656 /* We don't support any flags besides AI_CANONNAME. */
1657 if (hints && (hints->ai_flags & ~(AI_CANONNAME)) != 0)
1658 return WSAEINVAL;
1659 /* NODE cannot be NULL, since pop.c has fallbacks for that. */
1660 if (!node)
1661 return WSAHOST_NOT_FOUND;
1662
1663 if (service)
1664 {
1665 const char *protocol =
1666 (hints && hints->ai_socktype == SOCK_DGRAM) ? "udp" : "tcp";
1667 struct servent *srv = getservbyname (service, protocol);
1668
1669 if (srv)
1670 port = srv->s_port;
1671 else
1672 return WSAHOST_NOT_FOUND;
1673 }
1674
1675 gai_storage = calloc (1, sizeof *gai_storage);
1676 gai_storage->sockaddr_in.sin_port = port;
1677 host_info = gethostbyname (node);
1678 if (host_info)
1679 {
1680 memcpy (&gai_storage->sockaddr_in.sin_addr,
1681 host_info->h_addr, host_info->h_length);
1682 gai_storage->sockaddr_in.sin_family = host_info->h_addrtype;
1683 }
1684 else
1685 {
1686 free (gai_storage);
1687 return WSAHOST_NOT_FOUND;
1688 }
1689
1690 gai_storage->addrinfo.ai_addr =
1691 (struct sockaddr *)&gai_storage->sockaddr_in;
1692 gai_storage->addrinfo.ai_addrlen = sizeof (gai_storage->sockaddr_in);
1693 if (hints && (hints->ai_flags & AI_CANONNAME) != 0)
1694 {
1695 gai_storage->addrinfo.ai_canonname = strdup (host_info->h_name);
1696 if (!gai_storage->addrinfo.ai_canonname)
1697 {
1698 free (gai_storage);
1699 return WSA_NOT_ENOUGH_MEMORY;
1700 }
1701 }
1702 gai_storage->addrinfo.ai_protocol = (hints) ? hints->ai_protocol : 0;
1703 gai_storage->addrinfo.ai_socktype = (hints) ? hints->ai_socktype : 0;
1704 gai_storage->addrinfo.ai_family = gai_storage->sockaddr_in.sin_family;
1705 gai_storage->addrinfo.ai_next = NULL;
1706
1707 *res = &gai_storage->addrinfo;
1708 rc = 0;
1709 }
1710
1711 return rc;
1712}
1713
1714void
1715sys_freeaddrinfo (struct addrinfo *ai)
1716{
1717 if (load_ws2 () != 0)
1718 {
1719 errno = ENETDOWN;
1720 return;
1721 }
1722
1723 if (pfn_freeaddrinfo)
1724 pfn_freeaddrinfo (ai);
1725 else
1726 {
1727 if (ai->ai_canonname)
1728 free (ai->ai_canonname);
1729 free (ai);
1730 }
1731}
1732#endif /* WINDOWSNT */
1584#endif /* MAIL_USE_POP */ 1733#endif /* MAIL_USE_POP */