diff options
author | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 14:49:57 +0300 |
---|---|---|
committer | Arnold D. Robbins <arnold@skeeve.com> | 2010-07-16 14:49:57 +0300 |
commit | 6a2caf2157d87b4b582b2494bdd7d6a688dd0b1f (patch) | |
tree | 9a2862cc11be4832f188cfbdce175120ceba5024 /missing_d/getaddrinfo.c | |
parent | 315bd501ca696bc3e3c938b4604d8dac7a6f512f (diff) | |
download | egawk-6a2caf2157d87b4b582b2494bdd7d6a688dd0b1f.tar.gz egawk-6a2caf2157d87b4b582b2494bdd7d6a688dd0b1f.tar.bz2 egawk-6a2caf2157d87b4b582b2494bdd7d6a688dd0b1f.zip |
Move to gawk-3.1.6.
Diffstat (limited to 'missing_d/getaddrinfo.c')
-rw-r--r-- | missing_d/getaddrinfo.c | 112 |
1 files changed, 112 insertions, 0 deletions
diff --git a/missing_d/getaddrinfo.c b/missing_d/getaddrinfo.c new file mode 100644 index 00000000..677f27d0 --- /dev/null +++ b/missing_d/getaddrinfo.c @@ -0,0 +1,112 @@ +#ifndef HAVE_SOCKETS +#error getaddrinfo.c included by mistake! no socket support! +#else +#include <sys/types.h> +#include <sys/socket.h> +#ifdef HAVE_NETDB_H +#include <netdb.h> +#endif +#ifdef HAVE_NETINET_IN_H +#include <netinet/in.h> +#endif +#ifdef HAVE_ARPA_INET_H +#include <arpa/inet.h> +#endif + +#include "getaddrinfo.h" + +void +freeaddrinfo(struct addrinfo *res) +{ + if (res->ai_addr != NULL) + free(res->ai_addr); + free(res); +} + +int +getaddrinfo(const char *hostname, const char *portname, + struct addrinfo *hints, struct addrinfo **res) +{ + struct addrinfo *out; + if (res == NULL) + return -1; + + out = (struct addrinfo *) malloc(sizeof(*out)); + if (out == NULL) { + *res = NULL; + return -1; + } + memset(out, '\0', sizeof(*out)); + + out->ai_addr = (struct sockaddr *) malloc(sizeof(struct sockaddr_in)); + if (out->ai_addr == NULL) { + free(out); + *res = NULL; + return -1; + } + + out->ai_socktype = SOCK_STREAM; + if (hints != NULL) { + if (hints->ai_socktype) + out->ai_socktype = hints->ai_socktype; + if (hints->ai_protocol) + out->ai_protocol = hints->ai_protocol; + } + + if (out->ai_protocol == 0) { + switch (out->ai_socktype) { + case SOCK_STREAM: + out->ai_protocol = IPPROTO_TCP; + break; + case SOCK_DGRAM: + out->ai_protocol = IPPROTO_UDP; + break; + case SOCK_RAW: + out->ai_protocol = IPPROTO_RAW; + break; + } + } + + out->ai_addrlen = sizeof(struct sockaddr_in); + memset(out->ai_addr, '\0', sizeof(struct sockaddr_in)); + + if (hostname != NULL) { + struct hostent *he; + he = gethostbyname(hostname); + if (he != NULL && he->h_addr_list != NULL) { + ((struct sockaddr_in *)out->ai_addr)->sin_addr.s_addr + = ((struct in_addr *)he->h_addr_list[0])->s_addr; + } else { + freeaddrinfo(out); + return -1; + } + } else { + if (!(out->ai_flags & AI_PASSIVE)) + ((struct sockaddr_in *)out->ai_addr)->sin_addr.s_addr + = htonl(INADDR_ANY); + } + ((struct sockaddr_in *)out->ai_addr)->sin_family = AF_INET; + out->ai_family = AF_INET; + + if (portname != NULL && *portname) { + long portnum; + char *end; + portnum = strtol(portname, &end, 10); + if (*end == '\0' && portnum > 0 && portnum < 65536) { + ((struct sockaddr_in *)out->ai_addr)->sin_port + = htons(portnum); + } else { + struct servent *se; + se = getservbyname(portname, NULL); + if (se != NULL) { + ((struct sockaddr_in *)out->ai_addr)->sin_port + = se->s_port; + } + } + } + + *res = out; + + return 0; +} +#endif |