$OpenBSD: patch-src_daemon_c,v 1.18 2012/07/08 16:35:19 ajacoutot Exp $

In default_excludes[], add any ports and system users that has a login
shell.

Revert the following commit:
This reverts commit dfa1a6239b01c823ce0fec781c6c9541c988f56e.
The commit is wrong, since we're only interested in local users.
http://bugs.freedesktop.org/show_bug.cgi?id=41747
(XXX we need a way to only get local users)

--- src/daemon.c.orig	Thu Jun 28 17:24:55 2012
+++ src/daemon.c	Sun Jul  8 18:33:40 2012
@@ -35,6 +35,10 @@
 #include <utmpx.h>
 #endif
 
+#ifdef __OpenBSD__
+#include <grp.h> /* getgrnam */
+#endif
+
 #include <glib.h>
 #include <glib/gi18n.h>
 #include <glib-object.h>
@@ -77,6 +81,17 @@ static const char *default_excludes[] = {
         "games",
         "man",
         "at",
+        "_couchdb",
+        "_ejabberd",
+        "_jabberd",
+        "_mediatomb",
+        "_mon",
+        "_openfire",
+        "_postgresql",
+        "_rancid",
+        "_rocrail",
+        "_sogo",
+        "_varnish",
         NULL
 };
 
@@ -300,22 +315,32 @@ reload_passwd (Daemon *daemon)
         GSList *old_users;
         GSList *new_users;
         GSList *list;
+#ifdef HAVE_FGETPWENT
         FILE *fp;
+#endif
         User *user = NULL;
 
         old_users = NULL;
         new_users = NULL;
 
+#ifdef HAVE_FGETPWENT
         errno = 0;
         fp = fopen (PATH_PASSWD, "r");
         if (fp == NULL) {
                 g_warning ("Unable to open %s: %s", PATH_PASSWD, g_strerror (errno));
                 goto out;
         }
+#else
+        setpwent();
+#endif
         g_hash_table_foreach (daemon->priv->users, listify_hash_values_hfunc, &old_users);
         g_slist_foreach (old_users, (GFunc) g_object_ref, NULL);
 
+#ifdef HAVE_FGETPWENT
         while ((pwent = fgetpwent (fp)) != NULL) {
+#else
+        while ((pwent = getpwent ()) != NULL) {
+#endif
                 /* Skip system users... */
                 if (daemon_local_user_is_excluded (daemon, pwent->pw_name, pwent->pw_shell)) {
                         g_debug ("skipping user: %s", pwent->pw_name);
@@ -365,10 +390,12 @@ reload_passwd (Daemon *daemon)
                 }
         }
 
+#ifdef HAVE_FGETPWENT
  out:
         /* Cleanup */
 
         fclose (fp);
+#endif
 
         g_slist_foreach (new_users, (GFunc) g_object_thaw_notify, NULL);
         g_slist_foreach (new_users, (GFunc) g_object_unref, NULL);
@@ -922,7 +949,11 @@ daemon_create_user_authorized_cb (Daemon              
         CreateUserData *cd = data;
         User *user;
         GError *error;
+#ifndef __OpenBSD__
         const gchar *argv[9];
+#else
+	const gchar *argv[13];
+#endif
 
         if (getpwnam (cd->user_name) != NULL) {
                 throw_error (context, ERROR_USER_EXISTS, "A user with name '%s' already exists", cd->user_name);
@@ -939,14 +970,31 @@ daemon_create_user_authorized_cb (Daemon              
         if (cd->account_type == ACCOUNT_TYPE_ADMINISTRATOR) {
                 argv[4] = "-G";
                 argv[5] = "wheel";
+#ifdef __OpenBSD__
+                argv[6] = "-g";
+                argv[7] = "=uid";
+                argv[8] = "-L";
+                argv[9] = "staff";
+                argv[10] = "--";
+                argv[11] = cd->user_name;
+                argv[12] = NULL;
+#else
                 argv[6] = "--";
                 argv[7] = cd->user_name;
                 argv[8] = NULL;
+#endif
         }
         else if (cd->account_type == ACCOUNT_TYPE_STANDARD) {
+#ifdef __OpenBSD__
+                argv[4] = "-g";
+                argv[5] = "=uid";
+                argv[6] = cd->user_name;
+                argv[7] = NULL;
+#else
                 argv[4] = "--";
                 argv[5] = cd->user_name;
                 argv[6] = NULL;
+#endif
         }
         else {
                 throw_error (context, ERROR_FAILED, "Don't know how to add user of type %d", cd->account_type);
@@ -1018,15 +1066,49 @@ daemon_delete_user_authorized_cb (Daemon              
                 return;
         }
 
+/*
+ * Under OpenBSD there is no /etc/login.defs (for USERGROUPS_ENAB), so
+ * we need to explicitely remove the user's group if it contains no more
+ * members and matches the username.
+ */
+#ifdef __OpenBSD__
+        struct group *grp;
+        GError *grperror;
+        const gchar *grpargv[2];
+
+        grp = getgrnam (pwent->pw_name);
+
+        if ((grp != NULL) && (*grp->gr_name == *pwent->pw_name) && (*grp->gr_mem == NULL)) {
+                sys_log (context, "delete group '%d'", pwent->pw_gid);
+
+                grpargv[0] = "/usr/sbin/groupdel";
+                grpargv[1] = pwent->pw_name;
+
+                grperror = NULL;
+                if (!spawn_with_login_uid (context, grpargv, &grperror)) {
+                    throw_error (context, ERROR_FAILED, "running '%s' failed: %s", grpargv[0], grperror->message);
+                    g_error_free (grperror);
+                    return;
+                }
+        }
+#endif
+
         sys_log (context, "delete user '%s' (%d)", pwent->pw_name, ud->uid);
 
         argv[0] = "/usr/sbin/userdel";
         if (ud->remove_files) {
+#ifdef __OpenBSD__
+                argv[1] = "-r";
+                argv[2] = "--";
+                argv[3] = pwent->pw_name;
+                argv[4] = NULL;
+#else
                 argv[1] = "-f";
                 argv[2] = "-r";
                 argv[3] = "--";
                 argv[4] = pwent->pw_name;
                 argv[5] = NULL;
+#endif
         }
         else {
                 argv[1] = "--";
