#include "pthread.h"
#include <netdb.h>
#include <string.h>
#ifdef __sparc__
#define NEED_ALIGNED_ACCESS
#endif
static pthread_mutex_t gethostby_mutex = PTHREAD_MUTEX_INITIALIZER;
static int
convert (struct hostent *host, struct hostent *result,
char *buf, int buflen, int *h_errnop)
{
int len, i;
if (!buf || !h_errnop) return -1;
*h_errnop = h_errno;
*result = *host;
result->h_name = (char *) buf;
/* This is the size. */
len = strlen (host->h_name) + 1;
if (len > buflen) return -1;
buflen -= len;
buf += len;
strcpy ((char *) result->h_name, host->h_name);
/* How many aliases and how big the buffer should be? There
is always a NULL pointer. */
for (len = sizeof (char *), i = 0; host->h_aliases [i]; i++)
{
/* It should be size of (char *) and the length of string
plus 1. */
len += strlen (host->h_aliases [i]) + 1 + sizeof (char *);
}
if (len > buflen) return -1;
buflen -= len;
/* This is an array of char * for h_aliases. */
#ifdef NEED_ALIGNED_ACCESS
{
int extra;
extra = 4 - (((unsigned long) buf) & 3);
if (extra != 4) {
if (buflen < extra)
return -1;
buf = (char *) buf + extra;
}
}
#endif
result->h_aliases = (char **) buf;
buf += (i + 1) * sizeof (char *);
/* We copy the aliases now. */
for (i = 0; host->h_aliases [i]; i++)
{
result->h_aliases [i] = (char *) buf;
strcpy (result->h_aliases [i], host->h_aliases [i]);
buf += strlen (host->h_aliases [i]) + 1;
}
/* This is the last one */
result->h_aliases [i] = NULL;
#if BSD >= 43 || defined(h_addr)
for (len = sizeof (char *), i = 0; host->h_addr_list [i]; i++)
{
/* It should be size of (char *) and the length of string
plus 1. */
len += host->h_length + sizeof (char *);
}
if (len > buflen) return -1;
/* This is an array of char * for h_addr_list. */
#ifdef NEED_ALIGNED_ACCESS
{
int extra;
extra = 4 - (((unsigned long) buf) & 0x3);
if (extra != 4) {
if (buflen < extra)
return -1;
buf = ((char *) buf) + extra;
}
}
#endif
result->h_addr_list = (char **) buf;
buf += (i + 1) * sizeof (char *);
/* We copy the h_addr_list now. */
for (i = 0; host->h_addr_list [i]; i++)
{
result->h_addr_list [i] = (char *) buf;
memcpy (result->h_addr_list [i], host->h_addr_list [i], host->h_length);
buf += host->h_length;
}
/* This is the last one */
result->h_addr_list [i] = NULL;
#else
len = strlen (host->h_addr) + 1 + sizeof (char *);
if (len > buflen) return -1;
result->h_addr = (char *) buf;
strcpy (result->h_addr, host->h_addr);
#endif
return 0;
}
struct hostent *
gethostbyaddr_r (const char *addr, int length, int type,
struct hostent *result, char *buffer, int buflen,
int *h_errnop)
{
struct hostent *host;
pthread_mutex_lock (&gethostby_mutex);
host = gethostbyaddr (addr, length, type);
if (!host ||
convert (host, result, buffer, buflen, h_errnop) != 0)
{
result = NULL;
}
pthread_mutex_unlock (&gethostby_mutex);
return result;
}
struct hostent *
gethostbyname_r (const char *name,
struct hostent *result, char *buffer, int buflen,
int *h_errnop)
{
struct hostent *host;
pthread_mutex_lock (&gethostby_mutex);
host = gethostbyname (name);
if (!host ||
convert (host, result, buffer, buflen, h_errnop) != 0)
{
result = NULL;
}
pthread_mutex_unlock (&gethostby_mutex);
return result;
}
struct hostent *
gethostent_r (struct hostent *result, char *buffer, int buflen,
int *h_errnop)
{
struct hostent *host;
pthread_mutex_lock (&gethostby_mutex);
host = gethostent ();
if (!host ||
convert (host, result, buffer, buflen, h_errnop) != 0)
{
result = NULL;
}
pthread_mutex_unlock (&gethostby_mutex);
return result;
}