/*-------------------------------------------------------------------------
 *
 * libpq-reentrant.c
 *
 *        Prototypes and macros around system calls, used to help make
 *        libpq reentrant and safe to use from threaded applications.
 *
 * Portions Copyright (c) 1996-2003, PostgreSQL Global Development Group
 *
 * $Id:$
 *
 *-------------------------------------------------------------------------
 */

#include "libpq-reentrant.h"
#include <string.h>

/*
 * Wrapper around strerror and strerror_r to use the former if it is
 * available and also return a more useful value (the error string).
 */
char *pqStrerror(int errnum, char *strerrbuf, size_t buflen)
{
#if defined HAVE_STRERROR_R
  /* reentrant strerror_r is available */
  strerror_r(errnum, strerrbuf, buflen);
  return( strerrbuf );
#elif defined HAVE_NONPOSIX_STRERROR_R
  /* broken (well early POSIX draft) strerror_r() which returns 'char *' */
  return( strerror_r(errnum, strerrbuf, buflen) );
#else
  /* no strerror_r() available, just use strerror */
  return( strerror(errnum) );
#endif
}

/*
 * Wrapper around getpwuid() or getpwuid_r() to mimic POSIX getpwuid_r()
 * behaviour, if it is not available.
 */
#if !defined pqGetpwuid
int pqGetpwuid(uid_t uid, struct passwd *resultbuf, char *buffer,
	       size_t buflen, struct passwd **result)
{
#if defined HAVE_NONPOSIX_GETPWUID_R
  /* broken (well early POSIX draft) getpwuid_r() which returns
   * 'struct passwd *' */
  *result = getpwuid_r(uid, resultbuf, buffer, buflen);
#else
  /* no getpwuid_r() available, just use getpwuid() */
  *result = getpwuid(uid);
#endif /* HAVE_NONPOSIX_GETPWUID_R */
  return( (*result == NULL) ? -1 : 0 );
}
#endif /* !pqGetpwuid */

/*
 * Wrapper around gethostbyname() or gethostbyname_r() to mimic
 * POSIX gethostbyname_r() behaviour, if it is not available.
 */
#if !defined pqGethostbyname
int pqGethostbyname(const char *name,
		    struct hostent *resbuf,
		    char *buf, size_t buflen,
		    struct hostent **result,
		    int *herrno)
{
#if defined HAVE_NONPOSIX_GETHOSTBYNAME_R
  /* broken (well early POSIX draft) gethostbyname_r() which returns
   * 'struct hostent *' */
  *result = gethostbyname_r(name, resbuf, buf, buflen, herrno);
  return( (*result == NULL) ?  -1 : 0 );
#else
  /* no gethostbyname_r(), just use gethostbyname() */
  *result = gethostbyname(name);
  if( *result != NULL )
    return( 0 );
  else
    {
      *herrno = h_errno;
      return( -1 );
    }
#endif /* HAVE_NONPOSIX_GETHOSTBYNAME_R */
}
#endif /* !defined pqGethostbyname */
