*** a/src/backend/libpq/auth.c
--- b/src/backend/libpq/auth.c
***************
*** 17,28 ****
  
  #include <sys/param.h>
  #include <sys/socket.h>
- #ifdef HAVE_UCRED_H
- #include <ucred.h>
- #endif
- #ifdef HAVE_SYS_UCRED_H
- #include <sys/ucred.h>
- #endif
  #include <netinet/in.h>
  #include <arpa/inet.h>
  #include <unistd.h>
--- 17,22 ----
***************
*** 1757,1839 **** auth_peer(hbaPort *port)
  {
  	char		ident_user[IDENT_USERNAME_MAX + 1];
  	uid_t		uid = 0;
  	struct passwd *pass;
  
! #if defined(HAVE_GETPEEREID)
! 	/* Most BSDen, including OS X: use getpeereid() */
! 	gid_t		gid;
! 
! 	errno = 0;
! 	if (getpeereid(port->sock, &uid, &gid) != 0)
  	{
- 		/* We didn't get a valid credentials struct. */
  		ereport(LOG,
  				(errcode_for_socket_access(),
  				 errmsg("could not get peer credentials: %m")));
  		return STATUS_ERROR;
  	}
- #elif defined(SO_PEERCRED)
- 	/* Linux: use getsockopt(SO_PEERCRED) */
- 	struct ucred peercred;
- 	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
- 
- 	errno = 0;
- 	if (getsockopt(port->sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
- 		so_len != sizeof(peercred))
- 	{
- 		/* We didn't get a valid credentials struct. */
- 		ereport(LOG,
- 				(errcode_for_socket_access(),
- 				 errmsg("could not get peer credentials: %m")));
- 		return STATUS_ERROR;
- 	}
- 	uid = peercred.uid;
- #elif defined(LOCAL_PEERCRED)
- 	/* Debian with FreeBSD kernel: use getsockopt(LOCAL_PEERCRED) */
- 	struct xucred peercred;
- 	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
- 
- 	errno = 0;
- 	if (getsockopt(port->sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
- 		so_len != sizeof(peercred) ||
- 		peercred.cr_version != XUCRED_VERSION)
- 	{
- 		/* We didn't get a valid credentials struct. */
- 		ereport(LOG,
- 				(errcode_for_socket_access(),
- 				 errmsg("could not get peer credentials: %m")));
- 		return STATUS_ERROR;
- 	}
- 	uid = peercred.cr_uid;
- #elif defined(HAVE_GETPEERUCRED)
- 	/* Solaris: use getpeerucred() */
- 	ucred_t    *ucred;
- 
- 	ucred = NULL;				/* must be initialized to NULL */
- 	if (getpeerucred(port->sock, &ucred) == -1)
- 	{
- 		ereport(LOG,
- 				(errcode_for_socket_access(),
- 				 errmsg("could not get peer credentials: %m")));
- 		return STATUS_ERROR;
- 	}
- 
- 	if ((uid = ucred_geteuid(ucred)) == -1)
- 	{
- 		ereport(LOG,
- 				(errcode_for_socket_access(),
- 		   errmsg("could not get effective UID from peer credentials: %m")));
- 		return STATUS_ERROR;
- 	}
- 
- 	ucred_free(ucred);
- #else
- 	ereport(LOG,
- 			(errcode(ERRCODE_FEATURE_NOT_SUPPORTED),
- 			 errmsg("Peer authentication is not supported on local connections on this platform")));
- 
- 	return STATUS_ERROR;
- #endif
  
  	pass = getpwuid(uid);
  
--- 1751,1766 ----
  {
  	char		ident_user[IDENT_USERNAME_MAX + 1];
  	uid_t		uid = 0;
+ 	gid_t		gid = 0;
  	struct passwd *pass;
  
! 	if (pgGetpeereid(port->sock, &uid, &gid) != 0)
  	{
  		ereport(LOG,
  				(errcode_for_socket_access(),
  				 errmsg("could not get peer credentials: %m")));
  		return STATUS_ERROR;
  	}
  
  	pass = getpwuid(uid);
  
*** a/src/include/port.h
--- b/src/include/port.h
***************
*** 470,473 **** extern int	pg_check_dir(const char *dir);
--- 470,476 ----
  /* port/pgmkdirp.c */
  extern int	pg_mkdir_p(char *path, int omode);
  
+ /* port/pggetpeereid.c */
+ extern int pgGetpeereid(int sock, uid_t *uid, gid_t *gid);
+ 
  #endif   /* PG_PORT_H */
*** a/src/interfaces/libpq/fe-connect.c
--- b/src/interfaces/libpq/fe-connect.c
***************
*** 21,32 ****
  #include <ctype.h>
  #include <time.h>
  #include <unistd.h>
- #ifdef HAVE_UCRED_H
- #include <ucred.h>
- #endif
- #ifdef HAVE_SYS_UCRED_H
- #include <sys/ucred.h>
- #endif
  
  #include "libpq-fe.h"
  #include "libpq-int.h"
--- 21,26 ----
***************
*** 1866,1928 **** keep_going:						/* We will come back to here until there is
  				if (conn->requirepeer && conn->requirepeer[0] &&
  					IS_AF_UNIX(conn->raddr.addr.ss_family))
  				{
- #if defined(HAVE_GETPEEREID) || defined(SO_PEERCRED) || defined(LOCAL_PEERCRED) || defined(HAVE_GETPEERUCRED)
  					char		pwdbuf[BUFSIZ];
  					struct passwd pass_buf;
  					struct passwd *pass;
  					uid_t		uid;
- 
- #if defined(HAVE_GETPEEREID)
- 					/* Most BSDen, including OS X: use getpeereid() */
  					gid_t		gid;
  
- 					errno = 0;
- 					if (getpeereid(conn->sock, &uid, &gid) != 0)
- 					{
- 						appendPQExpBuffer(&conn->errorMessage,
- 						libpq_gettext("could not get peer credentials: %s\n"),
- 									pqStrerror(errno, sebuf, sizeof(sebuf)));
- 						goto error_return;
- 					}
- #elif defined(SO_PEERCRED)
- 					/* Linux: use getsockopt(SO_PEERCRED) */
- 					struct ucred peercred;
- 					ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
- 
- 					errno = 0;
- 					if (getsockopt(conn->sock, SOL_SOCKET, SO_PEERCRED,
- 								   &peercred, &so_len) != 0 ||
- 						so_len != sizeof(peercred))
- 					{
- 						appendPQExpBuffer(&conn->errorMessage,
- 						libpq_gettext("could not get peer credentials: %s\n"),
- 									pqStrerror(errno, sebuf, sizeof(sebuf)));
- 						goto error_return;
- 					}
- 					uid = peercred.uid;
- #elif defined(LOCAL_PEERCRED)
- 					/* Debian with FreeBSD kernel: use LOCAL_PEERCRED */
- 					struct xucred peercred;
- 					ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
- 
- 					errno = 0;
- 					if (getsockopt(conn->sock, 0, LOCAL_PEERCRED,
- 								   &peercred, &so_len) != 0 ||
- 						so_len != sizeof(peercred) ||
- 						peercred.cr_version != XUCRED_VERSION)
- 					{
- 						appendPQExpBuffer(&conn->errorMessage,
- 						libpq_gettext("could not get peer credentials: %s\n"),
- 									pqStrerror(errno, sebuf, sizeof(sebuf)));
- 						goto error_return;
- 					}
- 					uid = peercred.cr_uid;
- #elif defined(HAVE_GETPEERUCRED)
- 					/* Solaris: use getpeerucred() */
- 					ucred_t    *ucred;
  
! 					ucred = NULL;		/* must be initialized to NULL */
! 					if (getpeerucred(conn->sock, &ucred) == -1)
  					{
  						appendPQExpBuffer(&conn->errorMessage,
  						libpq_gettext("could not get peer credentials: %s\n"),
--- 1860,1873 ----
  				if (conn->requirepeer && conn->requirepeer[0] &&
  					IS_AF_UNIX(conn->raddr.addr.ss_family))
  				{
  					char		pwdbuf[BUFSIZ];
  					struct passwd pass_buf;
  					struct passwd *pass;
  					uid_t		uid;
  					gid_t		gid;
  
  
! 					if (pgGetpeereid(conn->sock, &uid, &gid) != 0)
  					{
  						appendPQExpBuffer(&conn->errorMessage,
  						libpq_gettext("could not get peer credentials: %s\n"),
***************
*** 1930,1948 **** keep_going:						/* We will come back to here until there is
  						goto error_return;
  					}
  
- 					if ((uid = ucred_geteuid(ucred)) == -1)
- 					{
- 						appendPQExpBuffer(&conn->errorMessage,
- 										  libpq_gettext("could not get effective UID from peer credentials: %s\n"),
- 									pqStrerror(errno, sebuf, sizeof(sebuf)));
- 						ucred_free(ucred);
- 						goto error_return;
- 					}
- 					ucred_free(ucred);
- #else
- #error missing implementation method for requirepeer
- #endif
- 
  					pqGetpwuid(uid, &pass_buf, pwdbuf, sizeof(pwdbuf), &pass);
  
  					if (pass == NULL)
--- 1875,1880 ----
***************
*** 1960,1970 **** keep_going:						/* We will come back to here until there is
  										  conn->requirepeer, pass->pw_name);
  						goto error_return;
  					}
- #else							/* can't support requirepeer */
- 					appendPQExpBuffer(&conn->errorMessage,
- 									  libpq_gettext("requirepeer parameter is not supported on this platform\n"));
- 					goto error_return;
- #endif
  				}
  
  #ifdef USE_SSL
--- 1892,1897 ----
*** a/src/port/Makefile
--- b/src/port/Makefile
***************
*** 31,37 **** override CPPFLAGS := -I$(top_builddir)/src/port -DFRONTEND $(CPPFLAGS)
  LIBS += $(PTHREAD_LIBS)
  
  OBJS = $(LIBOBJS) chklocale.o dirmod.o exec.o inet_net_ntop.o noblock.o \
! 	path.o pgcheckdir.o pgmkdirp.o pgsleep.o pgstrcasecmp.o \
  	qsort.o qsort_arg.o sprompt.o thread.o
  
  # foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND
--- 31,37 ----
  LIBS += $(PTHREAD_LIBS)
  
  OBJS = $(LIBOBJS) chklocale.o dirmod.o exec.o inet_net_ntop.o noblock.o \
! 	path.o pgcheckdir.o pggetpeereid.o pgmkdirp.o pgsleep.o pgstrcasecmp.o \
  	qsort.o qsort_arg.o sprompt.o thread.o
  
  # foo_srv.o and foo.o are both built from foo.c, but only foo.o has -DFRONTEND
*** /dev/null
--- b/src/port/pggetpeereid.c
***************
*** 0 ****
--- 1,80 ----
+ /*-------------------------------------------------------------------------
+  *
+  * pggetpeereid.c
+  *		get peer userid for UNIX socket
+  *
+  * Portions Copyright (c) 1996-2011, PostgreSQL Global Development Group
+  *
+  *
+  * IDENTIFICATION
+  *	  src/port/pggetpeereid.c
+  *
+  *-------------------------------------------------------------------------
+  */
+ 
+ #include "c.h"
+ 
+ #include <sys/param.h>
+ #include <sys/socket.h>
+ #include <unistd.h>
+ #ifdef HAVE_SYS_UN_H
+ #include <sys/un.h>
+ #endif
+ #ifdef HAVE_UCRED_H
+ #include <ucred.h>
+ #endif
+ #ifdef HAVE_SYS_UCRED_H
+ #include <sys/ucred.h>
+ #endif
+ 
+ int pgGetpeereid(int sock, uid_t *uid, gid_t *gid)
+ {
+ #if defined(HAVE_GETPEEREID)
+ 	/* Most BSDen, including OS X: use getpeereid() */
+ 	errno = 0;
+ 	return getpeereid(sock, uid, gid);
+ #elif defined(SO_PEERCRED)
+ 	/* Linux: use getsockopt(SO_PEERCRED) */
+ 	struct ucred peercred;
+ 	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+ 
+ 	errno = 0;
+ 	if (getsockopt(sock, SOL_SOCKET, SO_PEERCRED, &peercred, &so_len) != 0 ||
+ 		so_len != sizeof(peercred))
+ 		return -1;
+ 	*uid = peercred.uid;
+ 	*gid = peercred.gid;
+ 	return 0;
+ #elif defined(LOCAL_PEERCRED)
+ 	/* Debian with FreeBSD kernel: use LOCAL_PEERCRED */
+ 	struct xucred peercred;
+ 	ACCEPT_TYPE_ARG3 so_len = sizeof(peercred);
+ 
+ 	errno = 0;
+ 	if (getsockopt(conn->sock, 0, LOCAL_PEERCRED, &peercred, &so_len) != 0 ||
+ 		so_len != sizeof(peercred) ||
+ 		peercred.cr_version != XUCRED_VERSION)
+ 		return -1;
+ 	*uid = peercred.cr_uid;
+ 	*gid = peercred.cr_gid;
+ 	return 0;
+ #elif defined(HAVE_GETPEERUCRED)
+ 	/* Solaris: use getpeerucred() */
+ 	ucred_t    *ucred;
+ 
+ 	errno = 0;
+ 	ucred = NULL;		/* must be initialized to NULL */
+ 	if (getpeerucred(sock, &ucred) == -1)
+ 		return -1;
+ 
+ 	*uid = ucred_geteuid(ucred);
+ 	*gid = ucred_getegid(ucred);
+ 	ucred_free(ucred);
+ 	if (*uid == (pid_t)(-1) || *gid == (gid_t)(-1))
+ 		return -1;
+ 	return 0;
+ #else
+ 	errno = ENOSYS;
+ 	return -1;
+ #endif
+ }
