hal: Branch 'master' - 2 commits

David Zeuthen david at kemper.freedesktop.org
Thu Feb 15 11:18:12 PST 2007


 configure.in                                |   11 
 fdi/policy/10osvendor/20-acl-management.fdi |   34 +
 fdi/policy/10osvendor/Makefile.am           |    4 
 hald/Makefile.am                            |    3 
 hald/ck-tracker.c                           |  637 ++++++++++++++++++++++++++++
 hald/ck-tracker.h                           |   86 +++
 hald/hald.c                                 |    4 
 hald/hald_dbus.c                            |  110 ++++
 hald/hald_dbus.h                            |    2 
 hald/util.c                                 |    6 
 tools/Makefile.am                           |    9 
 tools/hal-acl-add.c                         |   91 ++++
 tools/hal-acl-remove.c                      |   15 
 13 files changed, 991 insertions(+), 21 deletions(-)

New commits:
diff-tree 24b151cd176dc8b2e53209be24bb64c647e65179 (from parents)
Merge: 7368286927bad8b996a53c3b4985df17c2068bcb 64fc3f3974074ca3424ede4ca82d993d4bb8ad46
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu Feb 15 13:53:17 2007 -0500

    Merge branch 'master' of ssh://david@git.freedesktop.org/git/hal

diff-tree 7368286927bad8b996a53c3b4985df17c2068bcb (from b26ba073131b944b9ad3760ecc7b60834ee585a0)
Author: David Zeuthen <davidz at redhat.com>
Date:   Thu Feb 15 13:52:56 2007 -0500

    make HAL track ConsoleKit seats and sessions and initial work on ACL mgmt
    
    This is just preliminary work; no ACL's are added nor removed just yet.

diff --git a/configure.in b/configure.in
index 5411b18..73bb40b 100644
--- a/configure.in
+++ b/configure.in
@@ -392,6 +392,16 @@ if test "x$enable_console_kit" != "xno";
    msg_conkit=yes
 fi
 
+# check for ACL handling
+AM_CONDITIONAL(HAVE_ACLMGMT, false)
+AC_ARG_ENABLE(acl-management, [  --enable-acl-management ACL management],enable_acl_management=$enableval,enable_acl_management=no)
+msg_aclmgmt=no
+if test "x$enable_acl_management" != "xno"; then
+   AM_CONDITIONAL(HAVE_ACLMGMT, true)
+   AC_DEFINE(HAVE_ACLMGMT, [], [Set if we manage ACL's])
+   msg_aclmgmt=yes
+fi
+
 # what extra hotplug backends to use (ACPI, APM, PMU etc)
 AC_ARG_ENABLE(have_acpi, [  --disable-acpi          Build without ACPI support])
 msg_acpi=no
@@ -783,6 +793,7 @@ echo "
         use libparted:              ${USE_PARTED}
         use PolicyKit:              ${msg_polkit}
         use ConsoleKit:             ${msg_conkit}
+        use ACL management:         ${msg_aclmgmt}
         use ACPI:                   ${msg_acpi}
         use PMU:                    ${msg_pmu}
         use APM:                    ${msg_apm}
diff --git a/fdi/policy/10osvendor/20-acl-management.fdi b/fdi/policy/10osvendor/20-acl-management.fdi
new file mode 100644
index 0000000..23fbe08
--- /dev/null
+++ b/fdi/policy/10osvendor/20-acl-management.fdi
@@ -0,0 +1,34 @@
+<?xml version="1.0" encoding="UTF-8"?>
+
+<deviceinfo version="0.2">
+  <device>
+
+    <!-- allow local sessions to access ALSA device files -->
+    <match key="info.capabilities" contains="alsa">
+      <merge key="acl.is_managed" type="bool">true</merge>
+      <merge key="acl.grant_local_session" type="bool">true</merge>
+      <merge key="acl.file" type="copy_property">alsa.device_file</merge>
+    </match>
+
+    <!-- allow local sessions to access OSS device files -->
+    <match key="info.capabilities" contains="oss">
+      <merge key="acl.is_managed" type="bool">true</merge>
+      <merge key="acl.grant_local_session" type="bool">true</merge>
+      <merge key="acl.file" type="copy_property">oss.device_file</merge>
+    </match>
+
+    <!-- TODO: add more rules for adding/removing ACL's (e.g. webcam, cd drive etc.) -->
+
+    <!-- remove all previously added ACL's on start-up -->
+    <match key="info.udi" string="/org/freedesktop/Hal/devices/computer">
+      <append key="info.callouts.add" type="strlist">hal-acl-remove --remove-all</append>
+    </match>
+
+    <!-- add and remove ACL's when devices are added and removed -->
+    <match key="acl.is_managed" bool="true">
+      <append key="info.callouts.add" type="strlist">hal-acl-add</append>
+      <append key="info.callouts.remove" type="strlist">hal-acl-remove</append>
+    </match>
+
+  </device>
+</deviceinfo>
diff --git a/fdi/policy/10osvendor/Makefile.am b/fdi/policy/10osvendor/Makefile.am
index 734eead..aed14e1 100644
--- a/fdi/policy/10osvendor/Makefile.am
+++ b/fdi/policy/10osvendor/Makefile.am
@@ -29,6 +29,10 @@ if BUILD_DELL
 dist_fdi_DATA += 10-dell-laptop-brightness.fdi
 endif
 
+if HAVE_ACLMGMT
+dist_fdi_DATA += 20-acl-management.fdi
+endif
+
 check:
 	for f in $(dist_fdi_DATA); do \
             echo -n "Validate XML in $$f : "; \
diff --git a/hald/Makefile.am b/hald/Makefile.am
index 589832f..3949a79 100644
--- a/hald/Makefile.am
+++ b/hald/Makefile.am
@@ -62,6 +62,9 @@ hald_SOURCES =                          
 	rule.h				mmap_cache.c			\
 	mmap_cache.h
 
+if HAVE_CONKIT
+hald_SOURCES += ck-tracker.h ck-tracker.c
+endif
 
 
 hald_LDADD = @GLIB_LIBS@ @DBUS_LIBS@ -lm @HALD_OS_LIBS@ $(top_builddir)/hald/$(HALD_BACKEND)/libhald_$(HALD_BACKEND).la
diff --git a/hald/ck-tracker.c b/hald/ck-tracker.c
new file mode 100644
index 0000000..fb8417f
--- /dev/null
+++ b/hald/ck-tracker.c
@@ -0,0 +1,637 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * ck-tracker.c : Track seats and sessions via ConsoleKit
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifdef HAVE_CONFIG_H
+#  include <config.h>
+#endif
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <stdarg.h>
+#include <stdint.h>
+#include <sys/time.h>
+
+#include <dbus/dbus.h>
+#include <glib.h>
+
+#include "logger.h"
+#include "ck-tracker.h"
+
+struct CKSeat_s {
+	int refcount;
+	char *seat_objpath;           /* obj path of ConsoleKit seat */
+	gboolean is_local;            /* whether the seat is local */
+	GSList *sessions;             /* list of sessions on this seat */
+};
+
+struct CKSession_s {
+	int refcount;
+	char *session_objpath;        /* obj path of ConsoleKit session */
+	CKSeat *seat;                 /* seat that session belongs to */
+	gboolean is_active;           /* whether the session is active */
+	uid_t user;                   /* user id of the user the session belongs to */
+};
+
+struct CKTracker_s {
+	int refcount;
+	DBusConnection *dbus_connection;
+	void *user_data;
+	CKSessionAddedCB session_added_cb;
+	CKSessionRemovedCB session_removed_cb;
+	CKSessionActiveChangedCB session_active_changed_cb;
+	GSList *seats;
+	GSList *sessions;
+};
+
+static CKSession *
+ck_session_new (const char *session_objpath)
+{
+	CKSession *session;
+	session = g_new0 (CKSession, 1);
+	session->refcount = 1;
+	session->session_objpath = g_strdup (session_objpath);
+	session->seat = NULL;
+	return session;
+}
+
+static void 
+ck_session_unref (CKSession *session)
+{
+	session->refcount--;
+	if (session->refcount == 0) {
+		g_free (session->session_objpath);
+		g_free (session);
+	}
+}
+
+static void 
+ck_session_ref (CKSession *session)
+{
+	session->refcount++;
+}
+
+static CKSeat *
+ck_seat_new (const char *seat_objpath)
+{
+	CKSeat *seat;
+	seat = g_new0 (CKSeat, 1);
+	seat->refcount = 1;
+	seat->seat_objpath = g_strdup (seat_objpath);
+	seat->sessions = NULL;
+	return seat;
+}
+
+static void
+ck_seat_attach_session (CKSeat *seat, CKSession *session)
+{
+	ck_session_ref (session);
+	session->seat = seat;
+	seat->sessions = g_slist_append (seat->sessions, session);
+}
+
+static void
+ck_seat_detach_session (CKSeat *seat, CKSession *session)
+{
+	seat->sessions = g_slist_remove (seat->sessions, session);
+	session->seat = NULL;
+	ck_session_unref (session);
+}
+
+static void 
+ck_seat_unref (CKSeat *seat)
+{
+	seat->refcount--;
+	if (seat->refcount == 0) {
+		GSList *i;
+
+		/* effictively detach all sessions without manually removing each element */
+		for (i = seat->sessions; i != NULL; i = g_slist_next (i)) {
+			CKSession *session = (CKSession *) i->data;
+			session->seat = NULL;
+			ck_session_unref (session);
+		}
+		g_slist_free (seat->sessions);
+
+		g_free (seat->seat_objpath);	
+		g_free (seat);
+	}
+}
+
+#if 0
+static void 
+ck_seat_ref (CKSeat *seat)
+{
+	seat->refcount++;
+}
+#endif
+
+static gboolean
+ck_seat_get_info (CKTracker *tracker, CKSeat *seat)
+{
+	/* TODO: replace with a D-Bus call to IsLocal() when that appears on ConsoleKit */
+	seat->is_local = TRUE;
+	return TRUE;
+}
+
+static gboolean
+ck_session_get_info (CKTracker *tracker, CKSession *session)
+{
+	gboolean ret;
+	DBusError error;
+	DBusMessage *message;
+	DBusMessage *reply;
+
+	ret = FALSE;
+
+	message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", 
+						session->session_objpath,
+						"org.freedesktop.ConsoleKit.Session",
+						"IsActive");
+	dbus_error_init (&error);
+	reply = dbus_connection_send_with_reply_and_block (tracker->dbus_connection, message, -1, &error);
+	if (reply == NULL || dbus_error_is_set (&error)) {
+		HAL_ERROR (("Error doing Session.IsActive on ConsoleKit: %s: %s", error.name, error.message));
+		dbus_message_unref (message);
+		if (reply != NULL)
+			dbus_message_unref (reply);
+		goto error;
+	}
+	if (!dbus_message_get_args (reply, NULL,
+				    DBUS_TYPE_BOOLEAN, &(session->is_active),
+				    DBUS_TYPE_INVALID)) {
+		HAL_ERROR (("Invalid IsActive reply from CK"));
+		goto error;
+	}
+	dbus_message_unref (message);
+	dbus_message_unref (reply);
+
+	message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", 
+						session->session_objpath,
+						"org.freedesktop.ConsoleKit.Session",
+						"GetUser");
+	dbus_error_init (&error);
+	reply = dbus_connection_send_with_reply_and_block (tracker->dbus_connection, message, -1, &error);
+	if (reply == NULL || dbus_error_is_set (&error)) {
+		HAL_ERROR (("Error doing Session.GetUser on ConsoleKit: %s: %s", error.name, error.message));
+		dbus_message_unref (message);
+		if (reply != NULL)
+			dbus_message_unref (reply);
+		goto error;
+	}
+	if (!dbus_message_get_args (reply, NULL,
+				    DBUS_TYPE_INT32, &(session->user),
+				    DBUS_TYPE_INVALID)) {
+		HAL_ERROR (("Invalid GetUser reply from CK"));
+		goto error;
+	}
+	dbus_message_unref (message);
+	dbus_message_unref (reply);
+
+	HAL_INFO (("Got active state (%s) and uid %d on session '%s'",
+		   session->is_active ? "ACTIVE" : "INACTIVE",
+		   session->user,
+		   session->session_objpath));
+
+	ret = TRUE;
+
+error:
+	return ret;
+}
+
+static gboolean
+ck_tracker_init_get_sessions_for_seat (CKTracker *tracker, CKSeat *seat)
+{
+	gboolean ret;
+	DBusError error;
+	DBusMessage *message;
+	DBusMessage *reply;
+	DBusMessageIter iter;
+	DBusMessageIter iter_array;
+
+	ret = FALSE;
+
+	message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", 
+						seat->seat_objpath,
+						"org.freedesktop.ConsoleKit.Seat",
+						"GetSessions");
+	dbus_error_init (&error);
+	reply = dbus_connection_send_with_reply_and_block (tracker->dbus_connection, message, -1, &error);
+	if (reply == NULL || dbus_error_is_set (&error)) {
+		HAL_ERROR (("Error doing GetSeats on ConsoleKit: %s: %s", error.name, error.message));
+		dbus_message_unref (message);
+		if (reply != NULL)
+			dbus_message_unref (reply);
+		goto error;
+	}
+
+	dbus_message_iter_init (reply, &iter);
+	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
+		HAL_WARNING (("Expecting an array from GetSessions on ConsoleKit."));
+		dbus_message_unref (message);
+		dbus_message_unref (reply);
+		goto error;
+	}
+	dbus_message_iter_recurse (&iter, &iter_array);
+	while (dbus_message_iter_get_arg_type (&iter_array) == DBUS_TYPE_OBJECT_PATH) {
+		const char *session_objpath;
+		CKSession *session;
+
+		dbus_message_iter_get_basic (&iter_array, &session_objpath);
+		HAL_INFO (("got session '%s' for seat '%s'", session_objpath, seat->seat_objpath));
+
+		session = ck_session_new (session_objpath);
+
+		/* get information: is_active etc. */
+		if (!ck_session_get_info (tracker, session)) {
+			HAL_ERROR (("Could not get information for session '%s'", session_objpath));
+			dbus_message_unref (message);
+			dbus_message_unref (reply);
+			goto error;
+		}
+
+		ck_seat_attach_session (seat, session);
+
+		tracker->sessions = g_slist_prepend (tracker->sessions, session);
+
+		dbus_message_iter_next (&iter_array);
+	}
+	dbus_message_unref (message);
+	dbus_message_unref (reply);
+
+	HAL_INFO (("Got all sessions on seat '%s'", seat->seat_objpath));
+
+	ret = TRUE;
+
+error:
+	return ret;
+}
+
+static gboolean
+ck_tracker_init_get_seats_and_sessions (CKTracker *tracker)
+{
+	gboolean ret;
+	DBusError error;
+	DBusMessage *message;
+	DBusMessage *reply;
+	DBusMessageIter iter;
+	DBusMessageIter iter_array;
+
+	ret = FALSE;
+
+	/* first build array of existing seats and sessions */
+
+	message = dbus_message_new_method_call ("org.freedesktop.ConsoleKit", 
+						"/org/freedesktop/ConsoleKit/Manager",
+						"org.freedesktop.ConsoleKit.Manager",
+						"GetSeats");
+	dbus_error_init (&error);
+	reply = dbus_connection_send_with_reply_and_block (tracker->dbus_connection, message, -1, &error);
+	if (reply == NULL || dbus_error_is_set (&error)) {
+		HAL_ERROR (("Error doing GetSeats on ConsoleKit: %s: %s", error.name, error.message));
+		dbus_message_unref (message);
+		if (reply != NULL)
+			dbus_message_unref (reply);
+		goto error;
+	}
+
+	dbus_message_iter_init (reply, &iter);
+	if (dbus_message_iter_get_arg_type (&iter) != DBUS_TYPE_ARRAY) {
+		HAL_WARNING (("Expecting an array from GetSeats on ConsoleKit."));
+		dbus_message_unref (message);
+		dbus_message_unref (reply);
+		goto error;
+	}
+	dbus_message_iter_recurse (&iter, &iter_array);
+	while (dbus_message_iter_get_arg_type (&iter_array) == DBUS_TYPE_OBJECT_PATH) {
+		const char *seat_objpath;
+		CKSeat *seat;
+
+		dbus_message_iter_get_basic (&iter_array, &seat_objpath);
+		HAL_INFO (("got seat '%s'", seat_objpath));
+
+		seat = ck_seat_new (seat_objpath);
+
+		/* get information: is_local etc. */
+		if (!ck_seat_get_info (tracker, seat)) {
+			HAL_ERROR (("Could not get information for seat '%s'", seat_objpath));
+			dbus_message_unref (message);
+			dbus_message_unref (reply);
+			goto error;
+		}
+
+		/* for each seat, get the sessions */
+		if (!ck_tracker_init_get_sessions_for_seat (tracker, seat)) {
+			HAL_ERROR (("Could not get sessions for seat '%s'", seat_objpath));
+			dbus_message_unref (message);
+			dbus_message_unref (reply);
+			goto error;
+		}
+
+		tracker->seats = g_slist_prepend (tracker->seats, seat);
+
+		dbus_message_iter_next (&iter_array);
+	}
+	dbus_message_unref (message);
+	dbus_message_unref (reply);
+
+	HAL_INFO (("Got seats"));
+
+	ret = TRUE;
+error:
+	return ret;
+}
+
+void
+ck_tracker_ref (CKTracker *tracker)
+{
+	tracker->refcount++;
+}
+
+void
+ck_tracker_unref (CKTracker *tracker)
+{
+	tracker->refcount--;
+
+	if (tracker->refcount == 0) {
+		GSList *i;
+
+		for (i = tracker->sessions; i != NULL; i = g_slist_next (i)) {
+			CKSession *session = (CKSession *) i->data;
+			ck_session_unref (session);
+		}
+		
+		for (i = tracker->seats; i != NULL; i = g_slist_next (i)) {
+			CKSeat *seat = (CKSeat *) i->data;
+			ck_seat_unref (seat);
+		}
+		
+		tracker->dbus_connection = NULL;
+	}
+}
+
+void
+ck_tracker_set_system_bus_connection (CKTracker *tracker, DBusConnection *system_bus_connection)
+{
+	tracker->dbus_connection = system_bus_connection;
+}
+
+void
+ck_tracker_set_user_data (CKTracker *tracker, void *user_data)
+{
+	tracker->user_data = user_data;
+}
+
+void
+ck_tracker_set_session_added_cb (CKTracker *tracker, CKSessionAddedCB cb)
+{
+	tracker->session_added_cb = cb;
+}
+
+void
+ck_tracker_set_session_removed_cb (CKTracker *tracker, CKSessionRemovedCB cb)
+{
+	tracker->session_removed_cb = cb;
+}
+
+void
+ck_tracker_set_session_active_changed_cb (CKTracker *tracker, CKSessionActiveChangedCB cb)
+{
+	tracker->session_active_changed_cb = cb;
+}
+
+
+void
+ck_tracker_process_system_bus_message (CKTracker *tracker, DBusMessage *message)
+{
+	const char *seat_objpath;
+	const char *session_objpath;
+	dbus_bool_t session_is_active;
+	GSList *i;
+	CKSeat *seat;
+	CKSession *session;
+
+	HAL_INFO (("In ck_tracker_process_system_bus_message objpath=%s interface=%s method=%s", 
+		   dbus_message_get_path (message), 
+		   dbus_message_get_interface (message),
+		   dbus_message_get_member (message)));
+
+	/* TODO: also handle SeatRemoved and SeatAdded */
+
+	if (dbus_message_is_signal (message, "org.freedesktop.ConsoleKit.Seat", "SessionAdded")) {
+
+		seat_objpath = dbus_message_get_path (message);
+
+		if (!dbus_message_get_args (message, NULL,
+					    DBUS_TYPE_STRING, &session_objpath,
+					    DBUS_TYPE_INVALID)) {
+			HAL_ERROR (("Invalid SessionAdded signal from CK"));
+			goto out;
+		}
+
+		HAL_INFO (("Received SessionAdded '%s' from CK on seat '%s'", session_objpath, seat_objpath));
+
+		for (i = tracker->seats; i != NULL; i = g_slist_next (i)) {
+			seat = (CKSeat *) i->data;
+			if (strcmp (seat->seat_objpath, seat_objpath) == 0) {
+				session = ck_session_new (session_objpath);
+
+				/* get information: is_active etc. */
+				if (!ck_session_get_info (tracker, session)) {
+					HAL_ERROR (("Could not get information for session '%s'", session_objpath));
+					goto out;
+				}
+
+				ck_seat_attach_session (seat, session);
+				tracker->sessions = g_slist_prepend (tracker->sessions, session);
+
+				if (tracker->session_added_cb != NULL) {
+					tracker->session_added_cb (tracker, session, tracker->user_data);
+				}
+				break;
+			}
+		}
+		if (i == NULL) {
+			HAL_ERROR (("No seat '%s for session '%s'", seat_objpath, session_objpath));
+		}
+
+
+	} else if (dbus_message_is_signal (message, "org.freedesktop.ConsoleKit.Seat", "SessionRemoved")) {
+
+		seat_objpath = dbus_message_get_path (message);
+
+		if (!dbus_message_get_args (message, NULL,
+					    DBUS_TYPE_STRING, &session_objpath,
+					    DBUS_TYPE_INVALID)) {
+			HAL_ERROR (("Invalid SessionRemoved signal from CK"));
+			goto out;
+		}
+
+		HAL_INFO (("Received SessionRemoved '%s' from CK on seat '%s'", session_objpath, seat_objpath));
+
+		for (i = tracker->sessions; i != NULL; i = g_slist_next (i)) {
+			session = (CKSession *) i->data;
+			if (strcmp (session->session_objpath, session_objpath) == 0) {
+
+				if (tracker->session_removed_cb != NULL) {
+					tracker->session_removed_cb (tracker, session, tracker->user_data);
+				}
+
+				if (session->seat == NULL) {
+					HAL_ERROR (("Session '%s' to be removed is not attached to a seat", 
+						    session_objpath));
+				} else {
+					ck_seat_detach_session (session->seat, session);
+				}
+				tracker->sessions = g_slist_remove (tracker->sessions, session);
+				ck_session_unref (session);
+
+				break;
+			}
+		}
+		if (i == NULL) {
+			HAL_ERROR (("No such session '%s'", session_objpath));
+		}
+
+	} else if (dbus_message_is_signal (message, "org.freedesktop.ConsoleKit.Session", "ActiveChanged")) {
+
+		session_objpath = dbus_message_get_path (message);
+
+		if (!dbus_message_get_args (message, NULL,
+					    DBUS_TYPE_BOOLEAN, &session_is_active,
+					    DBUS_TYPE_INVALID)) {
+			HAL_ERROR (("Invalid SessionRemoved signal from CK"));
+			goto out;
+		}
+
+		HAL_INFO (("Received ActiveChanged to %s from CK on session '%s'", 
+			   session_is_active ? "ACTIVE" : "INACTIVE", session_objpath));
+
+
+		for (i = tracker->sessions; i != NULL; i = g_slist_next (i)) {
+			session = (CKSession *) i->data;
+			if (strcmp (session->session_objpath, session_objpath) == 0) {
+
+				session->is_active = session_is_active;
+
+				if (tracker->session_active_changed_cb != NULL) {
+					tracker->session_active_changed_cb (tracker, session, tracker->user_data);
+				}
+				break;
+			}
+		}
+		if (i == NULL) {
+			HAL_ERROR (("No such session '%s'", session_objpath));
+		}
+
+	}
+out:
+	;
+}
+
+GSList *
+ck_tracker_get_seats (CKTracker *tracker)
+{
+	return tracker->seats;
+}
+
+GSList *
+ck_tracker_get_sessions (CKTracker *tracker)
+{
+	return tracker->sessions;
+}
+
+gboolean
+ck_seat_is_local (CKSeat *seat)
+{
+	return seat->is_local;
+}
+
+GSList *
+ck_seat_get_sessions (CKSeat *seat)
+{
+	return seat->sessions;
+}
+
+const char *
+ck_seat_get_id (CKSeat *seat)
+{
+	return seat->seat_objpath;
+}
+
+gboolean
+ck_session_is_active (CKSession *session)
+{
+	return session->is_active;
+}
+
+CKSeat *
+ck_session_get_seat (CKSession *session)
+{
+	return session->seat;
+}
+
+const char *
+ck_session_get_id (CKSession *session)
+{
+	return session->session_objpath;
+}
+
+uid_t
+ck_session_get_user (CKSession *session)
+{
+	return session->user;
+}
+
+gboolean
+ck_tracker_init (CKTracker *tracker)
+{
+	dbus_bool_t ret;
+
+	ret = FALSE;
+
+	if (!ck_tracker_init_get_seats_and_sessions (tracker)) {
+		HAL_ERROR (("Could not get seats and sessions"));
+		goto out;
+	}
+	
+	HAL_INFO (("Got seats and sessions"));
+
+	ret = TRUE;
+
+out:
+	return ret;
+}
+
+CKTracker *
+ck_tracker_new (void)
+{
+	CKTracker *tracker;
+
+	tracker = g_new0 (CKTracker, 1);
+	tracker->refcount = 1;
+	return tracker;
+}
diff --git a/hald/ck-tracker.h b/hald/ck-tracker.h
new file mode 100644
index 0000000..6c3147b
--- /dev/null
+++ b/hald/ck-tracker.h
@@ -0,0 +1,86 @@
+/***************************************************************************
+ * CVSID: $Id$
+ *
+ * ck-tracker.h : Track seats and sessions via ConsoleKit
+ *
+ * Copyright (C) 2007 David Zeuthen, <david at fubar.dk>
+ *
+ * Licensed under the Academic Free License version 2.1
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+ *
+ **************************************************************************/
+
+#ifndef CK_TRACKER_H
+#define CK_TRACKER_H
+
+#include <unistd.h>
+#include <sys/types.h>
+#include <dbus/dbus.h>
+#include <glib.h>
+
+struct CKTracker_s;
+typedef struct CKTracker_s CKTracker;
+struct CKSeat_s;
+typedef struct CKSeat_s CKSeat;
+struct CKSession_s;
+typedef struct CKSession_s CKSession;
+
+typedef void (*CKSessionAddedCB) (CKTracker *tracker, CKSession *session, void *user_data);
+typedef void (*CKSessionRemovedCB) (CKTracker *tracker, CKSession *session, void *user_data);
+typedef void (*CKSessionActiveChangedCB) (CKTracker *tracker, CKSession *session, void *user_data);
+
+CKTracker  *ck_tracker_new                        (void);
+void        ck_tracker_set_system_bus_connection     (CKTracker *tracker, DBusConnection *system_bus_connection);
+void        ck_tracker_set_user_data                 (CKTracker *tracker, void *user_data);
+void        ck_tracker_set_session_added_cb          (CKTracker *tracker, CKSessionAddedCB cb);
+void        ck_tracker_set_session_removed_cb        (CKTracker *tracker, CKSessionRemovedCB cb);
+void        ck_tracker_set_session_active_changed_cb (CKTracker *tracker, CKSessionActiveChangedCB cb);
+/* TODO: also handle seat_added, seat_removed */
+gboolean    ck_tracker_init                          (CKTracker *tracker);
+
+/* Forward DBusMessage signals for 
+ *
+ *  org.freedesktop.ConsoleKit.Seat.SessionAdded
+ *  org.freedesktop.ConsoleKit.Seat.SessionRemoved
+ *  org.freedesktop.ConsoleKit.Session.ActiveChanged
+ *
+ * on all objects on ConsoleKit to this function. 
+ *
+ *  TODO: need org.freedesktop.DBus.NameOwnerChanged from D-Bus to notice CK going away
+ *
+ * TODO: provide convenience method for letting CKTracker setup matches
+ * with the bus here via dbus_connection_add_filter() and
+ * dbus_bus_add_match(). E.g. just like libhal.
+ */
+void        ck_tracker_process_system_bus_message (CKTracker *tracker, DBusMessage *message);
+
+void        ck_tracker_ref                        (CKTracker *tracker);
+void        ck_tracker_unref                      (CKTracker *tracker);
+
+GSList     *ck_tracker_get_seats                  (CKTracker *tracker);
+GSList     *ck_tracker_get_sessions               (CKTracker *tracker);
+
+gboolean    ck_seat_is_local                      (CKSeat *seat);
+GSList     *ck_seat_get_sessions                  (CKSeat *seat);
+const char *ck_seat_get_id                        (CKSeat *seat);
+
+gboolean    ck_session_is_active                  (CKSession *session);
+CKSeat     *ck_session_get_seat                   (CKSession *session);
+const char *ck_session_get_id                     (CKSession *session);
+uid_t       ck_session_get_user                   (CKSession *session);
+
+
+#endif /* CK_TRACKER_H */
diff --git a/hald/hald.c b/hald/hald.c
index 4e4f1c6..2918558 100644
--- a/hald/hald.c
+++ b/hald/hald.c
@@ -597,6 +597,10 @@ main (int argc, char *argv[])
 	if (!hald_dbus_local_server_init ())
 		return 1;
 
+	if (!hald_dbus_init_preprobe ()) {
+		return 1;
+	}
+
 	/* Start the runner helper daemon */
 	if (!hald_runner_start_runner ()) {
 		return 1;
diff --git a/hald/hald_dbus.c b/hald/hald_dbus.c
index ddd6b8e..08c5367 100644
--- a/hald/hald_dbus.c
+++ b/hald/hald_dbus.c
@@ -48,9 +48,12 @@
 #include "util.h"
 #include "hald_runner.h"
 
+#include "ck-tracker.h"
+
 #define HALD_DBUS_ADDRESS "unix:tmpdir=" HALD_SOCKET_DIR
 
 static DBusConnection *dbus_connection = NULL;
+static CKTracker *ck_tracker = NULL;
 
 static void
 raise_error (DBusConnection *connection,
@@ -576,7 +579,7 @@ manager_send_signal_device_added (HalDev
 	DBusMessage *message;
 	DBusMessageIter iter;
 
-	if (dbus_connection == NULL)
+	if (dbus_connection == NULL || hald_is_initialising)
 		goto out;
 
 	HAL_TRACE (("entering, udi=%s", udi));
@@ -609,7 +612,7 @@ manager_send_signal_device_removed (HalD
 	DBusMessage *message;
 	DBusMessageIter iter;
 
-	if (dbus_connection == NULL)
+	if (dbus_connection == NULL || hald_is_initialising)
 		goto out;
 
 	HAL_TRACE (("entering, udi=%s", udi));
@@ -644,7 +647,7 @@ manager_send_signal_new_capability (HalD
 	DBusMessage *message;
 	DBusMessageIter iter;
 
-	if (dbus_connection == NULL)
+	if (dbus_connection == NULL || hald_is_initialising)
 		goto out;
 
 	HAL_TRACE (("entering, udi=%s, cap=%s", udi, capability));
@@ -931,7 +934,8 @@ caller_info_free (CallerInfo *ci)
 	g_free (ci);
 }
 
-GHashTable *connection_name_to_caller_info;
+static GHashTable *connection_name_to_caller_info;
+
 
 static void
 ci_tracker_init (void)
@@ -2364,7 +2368,7 @@ device_send_signal_property_modified (Ha
 		DBusMessageIter iter_struct;
 		DBusMessageIter iter_array;
 
-		if (dbus_connection == NULL)
+		if (dbus_connection == NULL || hald_is_initialising)
 			goto out;
 		
 		message = dbus_message_new_signal (udi,
@@ -2431,7 +2435,7 @@ device_send_signal_condition (HalDevice 
 	DBusMessage *message;
 	DBusMessageIter iter;
 
-	if (dbus_connection == NULL)
+	if (dbus_connection == NULL || hald_is_initialising)
 		goto out;
 
 	message = dbus_message_new_signal (udi,
@@ -4159,7 +4163,8 @@ no_caller:
 }
 
 /** Message handler for method invocations. All invocations on any object
- *  or interface is routed through this function.
+ *  or interface is routed through this function. *ONLY* messages from the
+ *  system bus goes through this method.
  *
  *  @param  connection          D-BUS connection
  *  @param  message             Message
@@ -4170,6 +4175,13 @@ DBusHandlerResult
 hald_dbus_filter_function (DBusConnection * connection,
 			   DBusMessage * message, void *user_data)
 {
+#ifdef HAVE_CONKIT
+	/* TODO: only push the appropriate messages to the tracker; see ck-tracker.h */
+	if (ck_tracker != NULL) {
+		ck_tracker_process_system_bus_message (ck_tracker, message);
+	}
+#endif
+
 	if (dbus_message_is_signal (message, DBUS_INTERFACE_LOCAL, "Disconnected") &&
 	    strcmp (dbus_message_get_path (message), DBUS_PATH_LOCAL) == 0) {
 
@@ -4388,12 +4400,37 @@ hald_dbus_local_server_shutdown (void)
 	}
 }
 
+static void 
+hald_dbus_session_added (CKTracker *tracker, CKSession *session, void *user_data)
+{
+	HAL_INFO (("In hald_dbus_session_added for session '%s' on seat '%s'", 
+		   ck_session_get_id (session),
+		   ck_session_get_seat (session) != NULL ? ck_seat_get_id (ck_session_get_seat (session)) : "(NONE)"));
+}
+
+static void 
+hald_dbus_session_removed (CKTracker *tracker, CKSession *session, void *user_data)
+{
+	HAL_INFO (("In hald_dbus_session_removed for session '%s' on seat '%s'", 
+		   ck_session_get_id (session),
+		   ck_session_get_seat (session) != NULL ? ck_seat_get_id (ck_session_get_seat (session)) : "(NONE)"));
+}
+
+static void 
+hald_dbus_session_active_changed (CKTracker *tracker, CKSession *session, void *user_data)
+{
+	HAL_INFO (("In hald_dbus_session_active_changed for session '%s': %s", 
+		   ck_session_get_id (session),
+		   ck_session_is_active (session) ? "ACTIVE" : "INACTIVE"));
+}
+
 gboolean
-hald_dbus_init (void)
+hald_dbus_init_preprobe (void)
 {
+	gboolean ret;
 	DBusError dbus_error;
 
-	HAL_INFO (("entering"));
+	ret = FALSE;
 
 	dbus_connection_set_change_sigpipe (TRUE);
 
@@ -4401,22 +4438,15 @@ hald_dbus_init (void)
 	dbus_connection = dbus_bus_get (DBUS_BUS_SYSTEM, &dbus_error);
 	if (dbus_connection == NULL) {
 		HAL_ERROR (("dbus_bus_get(): %s", dbus_error.message));
-		return FALSE;
+		goto out;
 	}
 
 	dbus_connection_setup_with_g_main (dbus_connection, NULL);
 	dbus_connection_set_exit_on_disconnect (dbus_connection, FALSE);
 
-	dbus_bus_request_name (dbus_connection, "org.freedesktop.Hal",
-				  0, &dbus_error);
-	if (dbus_error_is_set (&dbus_error)) {
-		HAL_ERROR (("dbus_bus_request_name(): %s",
-			    dbus_error.message));
-		return FALSE;
-	}
-
 	dbus_connection_add_filter (dbus_connection, hald_dbus_filter_function, NULL, NULL);
 
+
 	dbus_bus_add_match (dbus_connection,
 			    "type='signal'"
 			    ",interface='"DBUS_INTERFACE_DBUS"'"
@@ -4431,10 +4461,54 @@ hald_dbus_init (void)
 			    ",sender='org.freedesktop.ConsoleKit'"
 			    ",member='ActiveChanged'",
 			    NULL);
+	dbus_bus_add_match (dbus_connection,
+			    "type='signal'"
+			    ",interface='org.freedesktop.ConsoleKit.Seat'"
+			    ",sender='org.freedesktop.ConsoleKit'"
+			    ",member='SessionAdded'",
+			    NULL);
+	dbus_bus_add_match (dbus_connection,
+			    "type='signal'"
+			    ",interface='org.freedesktop.ConsoleKit.Seat'"
+			    ",sender='org.freedesktop.ConsoleKit'"
+			    ",member='SessionRemoved'",
+			    NULL);
+
+	ck_tracker = ck_tracker_new ();
+	ck_tracker_set_system_bus_connection (ck_tracker, dbus_connection);
+	ck_tracker_set_session_added_cb (ck_tracker, hald_dbus_session_added);
+	ck_tracker_set_session_removed_cb (ck_tracker, hald_dbus_session_removed);
+	ck_tracker_set_session_active_changed_cb (ck_tracker, hald_dbus_session_active_changed);
+	if (!ck_tracker_init (ck_tracker)) {
+		ck_tracker_unref (ck_tracker);
+		DIE (("Could not initialize seats and sessions from ConsoleKit"));
+	}
+
 #endif /* HAVE_CONKIT */
 
 	ci_tracker_init ();
 
+	ret = TRUE;
+
+out:
+	return ret;
+}
+
+gboolean
+hald_dbus_init (void)
+{
+	DBusError dbus_error;
+
+	HAL_INFO (("entering"));
+
+	dbus_error_init (&dbus_error);
+	dbus_bus_request_name (dbus_connection, "org.freedesktop.Hal", 0, &dbus_error);
+	if (dbus_error_is_set (&dbus_error)) {
+		HAL_ERROR (("dbus_bus_request_name(): %s",
+			    dbus_error.message));
+		return FALSE;
+	}
+
 	return TRUE;
 }
 
diff --git a/hald/hald_dbus.h b/hald/hald_dbus.h
index 439f451..79442be 100644
--- a/hald/hald_dbus.h
+++ b/hald/hald_dbus.h
@@ -87,6 +87,8 @@ void device_send_signal_condition (HalDe
 void device_property_atomic_update_begin (void);
 void device_property_atomic_update_end   (void);
 
+gboolean hald_dbus_init_preprobe (void);
+
 gboolean hald_dbus_init (void);
 
 gboolean hald_dbus_local_server_init (void);
diff --git a/hald/util.c b/hald/util.c
index 6ad4fcf..eaf3b09 100644
--- a/hald/util.c
+++ b/hald/util.c
@@ -942,9 +942,9 @@ callout_do_next (Callout *c)
 		callback (d, userdata1, userdata2);
 
 	} else {
-    hald_runner_run(c->d, c->programs[c->next_program], c->extra_env,
-                    HAL_HELPER_TIMEOUT, callout_terminated,
-                    (gpointer)c, NULL);
+		hald_runner_run(c->d, c->programs[c->next_program], c->extra_env,
+				HAL_HELPER_TIMEOUT, callout_terminated,
+				(gpointer)c, NULL);
 		c->next_program++;
 	}
 }
diff --git a/tools/Makefile.am b/tools/Makefile.am
index d820cc8..037b4aa 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -58,6 +58,15 @@ libexec_PROGRAMS =                      
 	hal-storage-cleanup-all-mountpoints \
 	hal-system-power-pmu
 
+if HAVE_ACLMGMT
+libexec_PROGRAMS += hal-acl-add hal-acl-remove
+
+hal_acl_add_SOURCES = hal-acl-add.c
+hal_acl_remove_SOURCES = hal-acl-remove.c
+endif
+
+
+
 hal_storage_mount_SOURCES = hal-storage-mount.c hal-storage-shared.c hal-storage-shared.h
 hal_storage_mount_LDADD = @GLIB_LIBS@ @POLKIT_LIBS@ @DBUS_LIBS@ $(top_builddir)/libhal/libhal.la $(top_builddir)/libhal-storage/libhal-storage.la
 
diff --git a/tools/hal-acl-add.c b/tools/hal-acl-add.c
new file mode 100644
index 0000000..2767773
--- /dev/null
+++ b/tools/hal-acl-add.c
@@ -0,0 +1,91 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/file.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <glib.h>
+
+#if 0
+static int lock_acl_fd = -1;
+
+static gboolean
+lock_hal_acl (void)
+{
+	if (lock_acl_fd >= 0)
+		return TRUE;
+
+	printf ("%d: attempting to get lock on /var/lib/hal/acl-list\n", getpid ());
+
+	lock_acl_fd = open ("/var/lib/hal/acl-list", O_CREAT | O_RDWR);
+
+	if (lock_acl_fd < 0)
+		return FALSE;
+
+tryagain:
+#if sun
+	if (lockf (lock_acl_fd, F_LOCK, 0) != 0) {
+#else
+	if (flock (lock_acl_fd, LOCK_EX) != 0) {
+#endif
+		if (errno == EINTR)
+			goto tryagain;
+		return FALSE;
+	}
+	
+	printf ("%d: got lock on /var/lib/hal/acl-list\n", getpid ());
+	
+	
+	return TRUE;
+}
+	
+static void
+unlock_hal_acl (void)
+{
+#if sun
+	lockf (lock_acl_fd, F_ULOCK, 0);
+#else
+	flock (lock_acl_fd, LOCK_UN);
+#endif
+	close (lock_acl_fd);
+	lock_acl_fd = -1;
+	printf ("%d: released lock on /var/lib/hal/acl-list\n", getpid ());
+}
+
+/* Each entry here represents a line in the acl-list file 
+ *
+ *   <device-file>\t<hal-udi>\t<uid-as-number>\t<gid-as-number>\t<session-id>
+ *
+ * example:
+ *
+ *   /dev/snd/controlC0\t/org/freedesktop/Hal/devices/pci_8086_27d8_alsa_control__1\t500\t\t/org/freedesktop/ConsoleKit/Session0
+ *
+ * This means that the 
+ */
+typedef struct HalACL_s {
+	const char *device;
+	const char *uid;
+	uid_t uid;           /* 0 if unset */
+	gid_t gid;           /* 0 if unset */
+	const char *session; /* NULL if unset */
+} HalACL;
+
+/* hal-acl-grant can run in two modes of operation;
+ *
+ * 1) as a hal callout via info.callouts.add - this will set ACL's on the device file pointed to by acl.file
+ *    using the information provided by the other acl.* properties to determine what ACL's to add to the given
+ *    device file
+ *
+ * 2) 
+ *
+ */
+#endif
+
+int 
+main (int argc, char *argv[])
+{
+	fprintf (stderr, "hal-acl-add\n");
+	return 0;
+}
diff --git a/tools/hal-acl-remove.c b/tools/hal-acl-remove.c
new file mode 100644
index 0000000..3f9278b
--- /dev/null
+++ b/tools/hal-acl-remove.c
@@ -0,0 +1,15 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+
+int 
+main (int argc, char *argv[])
+{
+	int i;
+
+	fprintf (stderr, "hal-acl-remove %d\n", argc);
+	for (i = 0; i < argc; i++) {
+		fprintf (stderr, " arg %2d: %s\n", i, argv[i]);		
+	}
+	return 0;
+}


More information about the hal-commit mailing list