$NetBSD: patch-ab,v 1.17 2009/01/09 21:47:32 he Exp $

--- dbus/dbus-sysdeps-unix.c.orig	2008-12-18 22:35:53 +0200
+++ dbus/dbus-sysdeps-unix.c	2009-01-09 13:49:43 +0200
@@ -23,6 +23,7 @@
  */
 
 #define _GNU_SOURCE 
+#define _NETBSD_SOURCE
 
 #include "dbus-internals.h"
 #include "dbus-sysdeps.h"
@@ -35,6 +36,9 @@
 #include "dbus-list.h"
 #include "dbus-credentials.h"
 
+#ifdef HAVE_NETBSD_ATOMIC_OPS
+#include <sys/atomic.h>
+#endif
 #include <sys/types.h>
 #include <stdlib.h>
 #include <string.h>
@@ -71,6 +75,10 @@
 #include <ucred.h>
 #endif
 
+#ifdef __NetBSD__
+#include <sys/un.h>
+#endif
+
 #ifdef HAVE_ADT
 #include <bsm/adt.h>
 #endif
@@ -87,6 +95,32 @@
 #define socklen_t int
 #endif
 
+#ifdef LOCAL_PEEREID
+static dbus_bool_t
+dbus_nb_getpeereid(int fd, pid_t *pid, uid_t *uid, gid_t *gid)
+{
+  struct unpcbid cred;
+  socklen_t len = sizeof(cred);
+
+  _dbus_verbose ("dbus_nb_getpeereid: enter, fd=%d\n");
+  if (getsockopt (fd, 0, LOCAL_PEEREID, &cred, &len) < 0)
+    {
+      _dbus_verbose ("dbus_nb_getpeereid: getsockopt LOCAL_PEEREID failed: %s\n", strerror(errno));
+      return FALSE;
+    }
+  if (pid)
+    *pid = cred.unp_pid;
+  if (uid)
+    *uid = cred.unp_euid;
+  if (gid)
+    *gid = cred.unp_egid;
+
+  _dbus_verbose ("dbus_nb_getpeereid: returning TRUE, pid=%d uid=%d gid=%d\n",
+		 cred.unp_pid, cred.unp_euid, cred.unp_egid);
+  return TRUE;
+}
+#endif
+
 static dbus_bool_t
 _dbus_open_socket (int              *fd_p,
                    int               domain,
@@ -581,7 +615,7 @@ _dbus_set_local_creds (int fd, dbus_bool
 {
   dbus_bool_t retval = TRUE;
 
-#if defined(HAVE_CMSGCRED)
+#if defined(HAVE_CMSGCRED) || defined(LOCAL_PEEREID)
   /* NOOP just to make sure only one codepath is used 
    *      and to prefer CMSGCRED
    */
@@ -1041,9 +1075,9 @@ write_credentials_byte (int             
   int bytes_written;
   char buf[1] = { '\0' };
 #if defined(HAVE_CMSGCRED) 
-  struct {
+  union {
 	  struct cmsghdr hdr;
-	  struct cmsgcred cred;
+	  char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
   } cmsg;
   struct iovec iov;
   struct msghdr msg;
@@ -1054,10 +1088,10 @@ write_credentials_byte (int             
   msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
 
-  msg.msg_control = &cmsg;
-  msg.msg_controllen = sizeof (cmsg);
+  msg.msg_control = (caddr_t) &cmsg;
+  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
   memset (&cmsg, 0, sizeof (cmsg));
-  cmsg.hdr.cmsg_len = sizeof (cmsg);
+  cmsg.hdr.cmsg_len = CMSG_LEN (sizeof (struct cmsgcred));
   cmsg.hdr.cmsg_level = SOL_SOCKET;
   cmsg.hdr.cmsg_type = SCM_CREDS;
 #endif
@@ -1129,15 +1163,15 @@ _dbus_read_credentials_socket  (int     
   dbus_pid_t pid_read;
   int bytes_read;
   
-  uid_read = DBUS_UID_UNSET;
-  pid_read = DBUS_PID_UNSET;
-  
 #ifdef HAVE_CMSGCRED 
-  struct {
+  union {
     struct cmsghdr hdr;
-    struct cmsgcred cred;
+    char cred[CMSG_SPACE (sizeof (struct cmsgcred))];
   } cmsg;
 
+#elif defined(LOCAL_PEEREID)
+  pid_t sockpid, sockuid, sockgid;
+
 #elif defined(LOCAL_CREDS)
   struct {
     struct cmsghdr hdr;
@@ -1145,6 +1179,9 @@ _dbus_read_credentials_socket  (int     
   } cmsg;
 #endif
 
+  uid_read = DBUS_UID_UNSET;
+  pid_read = DBUS_PID_UNSET;
+
   _DBUS_ASSERT_ERROR_IS_CLEAR (error);
   
   /* The POSIX spec certainly doesn't promise this, but
@@ -1170,11 +1207,16 @@ _dbus_read_credentials_socket  (int     
   msg.msg_iov = &iov;
   msg.msg_iovlen = 1;
 
-#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
+#if (defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)) && !defined(LOCAL_PEEREID)
   memset (&cmsg, 0, sizeof (cmsg));
+#ifdef HAVE_CMSGCRED
+  msg.msg_control = (caddr_t) &cmsg;
+  msg.msg_controllen = CMSG_SPACE (sizeof (struct cmsgcred));
+#else /* defined(LOCAL_CREDS) */
   msg.msg_control = &cmsg;
   msg.msg_controllen = sizeof (cmsg);
 #endif
+#endif
 
  again:
   bytes_read = recvmsg (client_fd, &msg, 0);
@@ -1210,8 +1252,12 @@ _dbus_read_credentials_socket  (int     
       return FALSE;
     }
 
-#if defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)
+#if (defined(HAVE_CMSGCRED) || defined(LOCAL_CREDS)) && !defined(LOCAL_PEEREID)
+#ifdef HAVE_CMSGCRED
+  if (cmsg.hdr.cmsg_len < CMSG_LEN (sizeof (struct cmsgcred)) || cmsg.hdr.cmsg_type != SCM_CREDS)
+#else /* defined(LOCAL_CREDS) */
   if (cmsg.hdr.cmsg_len < sizeof (cmsg) || cmsg.hdr.cmsg_type != SCM_CREDS)
+#endif
     {
       dbus_set_error (error, DBUS_ERROR_FAILED,
                       "Message from recvmsg() was not SCM_CREDS");
@@ -1238,8 +1284,21 @@ _dbus_read_credentials_socket  (int     
 		       cr_len, (int) sizeof (cr), _dbus_strerror (errno));
       }
 #elif defined(HAVE_CMSGCRED)
-    pid_read = cmsg.cred.cmcred_pid;
-    uid_read = cmsg.cred.cmcred_euid;
+    struct cmsgcred *cred;
+
+    cred = (struct cmsgcred *) CMSG_DATA (&cmsg);
+    pid_read = cred->cmcred_pid;
+    uid_read = cred->cmcred_euid;
+#elif defined(LOCAL_PEEREID)
+    if (dbus_nb_getpeereid(client_fd, &sockpid, &sockuid, &sockgid) == TRUE)
+      {
+	pid_read = sockpid;
+	uid_read = sockuid;
+      }
+    else
+      {
+        _dbus_verbose ("Failed to dbus_nb_getpeereid() credentials: %s\n", _dbus_strerror (errno));
+      }
 #elif defined(LOCAL_CREDS)
     pid_read = DBUS_PID_UNSET;
     uid_read = cmsg.cred.sc_uid;
@@ -1301,7 +1360,7 @@ _dbus_read_credentials_socket  (int     
       }
     if (ucred != NULL)
       ucred_free (ucred);
-#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED */
+#else /* !SO_PEERCRED && !HAVE_CMSGCRED && !HAVE_GETPEEREID && !HAVE_GETPEERUCRED && !LOCAL_PEEREID*/
     _dbus_verbose ("Socket credentials not supported on this OS\n");
 #endif
   }
@@ -1826,7 +1885,26 @@ _dbus_parse_uid (const DBusString      *
   return TRUE;
 }
 
+#ifdef HAVE_NETBSD_ATOMIC_OPS
+dbus_int32_t
+_dbus_atomic_inc (DBusAtomic *atomic)
+{
+	register dbus_int32_t old = atomic->value;
+
+	atomic_inc_uint((unsigned *)&atomic->value);
+	return old;
+}
+
+dbus_int32_t
+_dbus_atomic_dec (DBusAtomic *atomic)
+{
+	register dbus_int32_t old = atomic->value;
 
+	atomic_dec_uint((unsigned *)&atomic->value);
+  	return old;
+}
+_DBUS_DEFINE_GLOBAL_LOCK (atomic);
+#else
 _DBUS_DEFINE_GLOBAL_LOCK (atomic);
 
 #if DBUS_USE_ATOMIC_INT_486_COND
@@ -1891,6 +1969,7 @@ _dbus_atomic_dec (DBusAtomic *atomic)
   return res;
 #endif
 }
+#endif /* HAVE_NETBSD_ATOMIC_OPS */
 
 #ifdef DBUS_BUILD_TESTS
 /** Gets our GID
@@ -2792,8 +2871,18 @@ int
 _dbus_printf_string_upper_bound (const char *format,
                                  va_list     args)
 {
+#if defined(__hpux) || defined(__sgi)
+/* this code from libnbcompat's vsnprintf */
+  static FILE *devnull = 0;
+  if (!devnull) {
+    devnull = fopen("/dev/null", "w");
+    if (!devnull) return -1;
+  }
+  return vfprintf(devnull, format, args);
+#else
   char c;
   return vsnprintf (&c, 1, format, args);
+#endif
 }
 
 /**
