From 9b5ce27c3b517c501bb13a534d50476e11751262 Mon Sep 17 00:00:00 2001
From: Max Kellermann <max@duempel.org>
Date: Thu, 16 Oct 2008 14:59:26 +0200
Subject: [PATCH] configure.ac: check if "struct ucred" is available

By default, glibc 2.8 hides struct ucred behind the _GNU_SOURCE
macro.  I don't want to enable that globally, because it may encourage
the use of non-portable functions.  Test if "struct ucred" is
available, and enable _GNU_SOURCE if required.

For details about that issue, see glib's bug database:

 http://sources.redhat.com/bugzilla/show_bug.cgi?id=6545
---
 configure.ac |  1 +
 m4/ucred.m4  | 32 ++++++++++++++++++++++++++++++++
 src/listen.c |  4 ++--
 3 files changed, 35 insertions(+), 2 deletions(-)
 create mode 100644 m4/ucred.m4

diff --git a/configure.ac b/configure.ac
index eceedaf09..ce50de896 100644
--- a/configure.ac
+++ b/configure.ac
@@ -308,6 +308,7 @@ fi
 
 if test x$enable_un = xyes; then
 	AC_DEFINE(HAVE_UN, 1, [Define if unix domain socket support is enabled])
+	STRUCT_UCRED
 fi
 
 enable_osx=no
diff --git a/m4/ucred.m4 b/m4/ucred.m4
new file mode 100644
index 000000000..3a8245245
--- /dev/null
+++ b/m4/ucred.m4
@@ -0,0 +1,32 @@
+# Check if "struct ucred" is available.  If not, try harder with
+# _GNU_SOURCE.
+#
+# Author: Max Kellermann <max@duempel.org>
+
+AC_DEFUN([STRUCT_UCRED],[
+	AC_MSG_CHECKING([for struct ucred])
+	AC_CACHE_VAL(mpd_cv_have_struct_ucred, [
+		AC_TRY_COMPILE([#include <sys/socket.h>],
+			[struct ucred cred;],
+			mpd_cv_have_struct_ucred=yes,
+			mpd_cv_have_struct_ucred=no)
+		if test x$mpd_cv_have_struct_ucred = xno; then
+			# glibc 2.8 forces _GNU_SOURCE on us
+			AC_TRY_COMPILE(
+				[#define _GNU_SOURCE
+				 #include <sys/socket.h>],
+				[struct ucred cred;],
+				mpd_cv_have_struct_ucred=yes,
+				mpd_cv_have_struct_ucred=no)
+			if test x$mpd_cv_have_struct_ucred = xyes; then
+				# :(
+				MPD_CFLAGS="$MPD_CFLAGS -D_GNU_SOURCE"
+			fi
+		fi
+		])
+
+	AC_MSG_RESULT($mpd_cv_have_struct_ucred)
+	if test x$mpd_cv_have_struct_ucred = xyes; then
+		AC_DEFINE(HAVE_STRUCT_UCRED, 1, [Define if struct ucred is present from sys/socket.h])
+	fi
+])
diff --git a/src/listen.c b/src/listen.c
index 1a52202ac..ab74f8d02 100644
--- a/src/listen.c
+++ b/src/listen.c
@@ -97,7 +97,7 @@ static int establishListen(int pf, const struct sockaddr *addrp,
 	if (listen(sock, 5) < 0)
 		FATAL("problems listen'ing: %s\n", strerror(errno));
 
-#if defined(HAVE_UN) && defined(SO_PASSCRED)
+#ifdef HAVE_UCRED
 	setsockopt(sock, SOL_SOCKET, SO_PASSCRED, &passcred, sizeof(passcred));
 #endif
 
@@ -265,7 +265,7 @@ void freeAllListenSockets(void)
 
 static int get_remote_uid(int fd)
 {
-#if defined(HAVE_UN) && defined(SO_PEERCRED)
+#ifdef HAVE_UCRED
 	struct ucred cred;
 	socklen_t len = sizeof (cred);