[gnome-keyring] [daemon] Add --replace option to daemon.



commit 034d6fe69bc91722c242659a9d27c429c85a3fad
Author: Stef Walter <stef memberwebs com>
Date:   Fri Jul 30 10:33:12 2010 +0200

    [daemon] Add --replace option to daemon.
    
     * Allows one gnome-keyring-daemon to replace another, including
       using the same environment variables etc.

 daemon/control/gkd-control-client.c      |   30 +++++++++++++
 daemon/control/gkd-control-codes.h       |    1 +
 daemon/control/gkd-control-server.c      |   13 ++++++
 daemon/control/gkd-control.h             |    2 +
 daemon/control/tests/.gitignore          |    1 +
 daemon/control/tests/Makefile.am         |   12 +++++-
 daemon/control/tests/test-control-quit.c |   25 +++++++++++
 daemon/dbus/gkd-dbus.c                   |    9 ++--
 daemon/gkd-main.c                        |   69 +++++++++++++++++++++---------
 9 files changed, 137 insertions(+), 25 deletions(-)
---
diff --git a/daemon/control/gkd-control-client.c b/daemon/control/gkd-control-client.c
index 58d7d62..a52dc0f 100644
--- a/daemon/control/gkd-control-client.c
+++ b/daemon/control/gkd-control-client.c
@@ -277,3 +277,33 @@ gkd_control_change_lock (const gchar *directory, const gchar *original,
 
 	return TRUE;
 }
+
+gboolean
+gkd_control_quit (const gchar *directory)
+{
+	EggBuffer buffer;
+	gsize offset = 4;
+	gboolean ret;
+	guint32 res;
+
+	egg_buffer_init_full (&buffer, 128, egg_secure_realloc);
+	egg_buffer_add_uint32 (&buffer, 0);
+	egg_buffer_add_uint32 (&buffer, GKD_CONTROL_OP_QUIT);
+	egg_buffer_set_uint32 (&buffer, 0, buffer.len);
+
+	g_return_val_if_fail (!egg_buffer_has_error (&buffer), FALSE);
+
+	ret = control_chat (directory, &buffer);
+
+	if (ret)
+		ret = egg_buffer_get_uint32 (&buffer, offset, &offset, &res);
+
+	egg_buffer_uninit (&buffer);
+
+	if (!ret || res != GKD_CONTROL_RESULT_OK) {
+		g_message ("couldn't quit running keyring daemon");
+		return FALSE;
+	}
+
+	return TRUE;
+}
diff --git a/daemon/control/gkd-control-codes.h b/daemon/control/gkd-control-codes.h
index 159ac48..696200d 100644
--- a/daemon/control/gkd-control-codes.h
+++ b/daemon/control/gkd-control-codes.h
@@ -26,6 +26,7 @@ enum {
 	GKD_CONTROL_OP_INITIALIZE,
 	GKD_CONTROL_OP_UNLOCK,
 	GKD_CONTROL_OP_CHANGE,
+	GKD_CONTROL_OP_QUIT
 };
 
 enum {
diff --git a/daemon/control/gkd-control-server.c b/daemon/control/gkd-control-server.c
index 18d4bf7..8ec34c5 100644
--- a/daemon/control/gkd-control-server.c
+++ b/daemon/control/gkd-control-server.c
@@ -114,6 +114,13 @@ control_change_login (EggBuffer *buffer)
 }
 
 static guint32
+control_quit (EggBuffer *buffer)
+{
+	gkd_main_quit ();
+	return GKD_CONTROL_RESULT_OK;
+}
+
+static guint32
 control_initialize_components (EggBuffer *buffer)
 {
 	gchar *components;
@@ -218,6 +225,12 @@ control_process (EggBuffer *req, GIOChannel *channel)
 		egg_buffer_add_uint32 (&cdata->buffer, res);
 		egg_buffer_add_stringv (&cdata->buffer, gkd_util_get_environment ());
 		break;
+	case GKD_CONTROL_OP_QUIT:
+		res = control_quit (req);
+		cdata = control_data_new ();
+		egg_buffer_add_uint32 (&cdata->buffer, 0);
+		egg_buffer_add_uint32 (&cdata->buffer, res);
+		break;
 	default:
 		g_message ("received unsupported request operation on control socket: %d", (int)op);
 		break;
diff --git a/daemon/control/gkd-control.h b/daemon/control/gkd-control.h
index d7f7e66..17dd028 100644
--- a/daemon/control/gkd-control.h
+++ b/daemon/control/gkd-control.h
@@ -37,4 +37,6 @@ gboolean          gkd_control_change_lock   (const gchar *directory,
                                              const gchar *original,
                                              const gchar *password);
 
+gboolean          gkd_control_quit          (const gchar *directory);
+
 #endif /* __GKD_CONTROL_H__ */
diff --git a/daemon/control/tests/.gitignore b/daemon/control/tests/.gitignore
index 79b439f..cf0cce4 100644
--- a/daemon/control/tests/.gitignore
+++ b/daemon/control/tests/.gitignore
@@ -1,3 +1,4 @@
 /test-control-change
 /test-control-init
 /test-control-unlock
+/test-control-quit
diff --git a/daemon/control/tests/Makefile.am b/daemon/control/tests/Makefile.am
index 78f8ae8..2ab531a 100644
--- a/daemon/control/tests/Makefile.am
+++ b/daemon/control/tests/Makefile.am
@@ -14,7 +14,8 @@ LIBS = \
 noinst_PROGRAMS= \
 	test-control-change \
 	test-control-init \
-	test-control-unlock
+	test-control-unlock \
+	test-control-quit
 
 # ------------------------------------------------------------------------------
 # Test unlocking the login keyring
@@ -37,6 +38,15 @@ test_control_init_LDADD = \
 	$(top_builddir)/egg/libegg-creds.la \
 	$(top_builddir)/egg/libegg-secure.la
 
+test_control_quit_SOURCES = \
+	test-control-quit.c
+
+test_control_quit_LDADD = \
+	$(top_builddir)/daemon/control/libgkd-control-client.la \
+	$(top_builddir)/egg/libegg-buffer.la \
+	$(top_builddir)/egg/libegg-creds.la \
+	$(top_builddir)/egg/libegg-secure.la
+
 test_control_unlock_SOURCES = \
 	test-control-unlock.c
 
diff --git a/daemon/control/tests/test-control-quit.c b/daemon/control/tests/test-control-quit.c
new file mode 100644
index 0000000..f3ec3cc
--- /dev/null
+++ b/daemon/control/tests/test-control-quit.c
@@ -0,0 +1,25 @@
+
+#include "control/gkd-control.h"
+#include "testing/testing.h"
+
+#include <pwd.h>
+#include <stdlib.h>
+#include <unistd.h>
+
+static int
+run (void)
+{
+	const char *directory;
+
+	directory = g_getenv ("GNOME_KEYRING_CONTROL");
+	g_return_val_if_fail (directory, 1);
+
+	if (!gkd_control_quit (directory))
+		return 1;
+
+	g_printerr ("success quitting daemon\n");
+
+	return 0;
+}
+
+#include "testing/testing.c"
diff --git a/daemon/dbus/gkd-dbus.c b/daemon/dbus/gkd-dbus.c
index 4688d18..8461226 100644
--- a/daemon/dbus/gkd-dbus.c
+++ b/daemon/dbus/gkd-dbus.c
@@ -230,11 +230,10 @@ gkd_dbus_singleton_control (void)
 	gchar *control = NULL;
 	const char *path;
 
-	/* Must have tried to aquire the service, and failed */
-	g_return_val_if_fail (acquired_asked, NULL);
+	/* If tried to aquire the service must have failed */
 	g_return_val_if_fail (!acquired_service, NULL);
 
-	if (!connect_to_session_bus())
+	if (!connect_to_session_bus ())
 		return NULL;
 
 	msg = dbus_message_new_method_call (GNOME_KEYRING_DAEMON_SERVICE,
@@ -242,13 +241,15 @@ gkd_dbus_singleton_control (void)
 	                                    GNOME_KEYRING_DAEMON_INTERFACE,
 	                                    "GetControlDirectory");
 	g_return_val_if_fail (msg, NULL);
+	dbus_message_set_auto_start (msg, FALSE);
 
 	/* Send message and get a handle for a reply */
 	reply = dbus_connection_send_with_reply_and_block (dbus_conn, msg, 1000, &derr);
 	dbus_message_unref (msg);
 
 	if (!reply) {
-		g_message ("couldn't communicate with already running daemon: %s", derr.message);
+		if (!dbus_error_has_name (&derr, "org.freedesktop.DBus.Error.NameHasNoOwner"))
+			g_message ("couldn't communicate with already running daemon: %s", derr.message);
 		dbus_error_free (&derr);
 		return NULL;
 	}
diff --git a/daemon/gkd-main.c b/daemon/gkd-main.c
index 8219f19..a19ceef 100644
--- a/daemon/gkd-main.c
+++ b/daemon/gkd-main.c
@@ -100,21 +100,24 @@ static gboolean run_foreground = FALSE;
 static gboolean run_daemonized = FALSE;
 static gboolean run_for_login = FALSE;
 static gboolean run_for_start = FALSE;
+static gboolean run_for_replace = FALSE;
 static gchar* login_password = NULL;
-static const gchar* control_directory = NULL;
+static gchar* control_directory = NULL;
 static gboolean initialization_completed = FALSE;
 static gboolean sig_thread_valid = FALSE;
 static pthread_t sig_thread;
 
 static GOptionEntry option_entries[] = {
+	{ "start", 's', 0, G_OPTION_ARG_NONE, &run_for_start,
+	  "Start a dameon or initialize an already running daemon." },
+	{ "replace", 'r', 0, G_OPTION_ARG_NONE, &run_for_replace,
+	  "Replace the daemon for this desktop login environment." },
 	{ "foreground", 'f', 0, G_OPTION_ARG_NONE, &run_foreground,
 	  "Run in the foreground", NULL },
 	{ "daemonize", 'd', 0, G_OPTION_ARG_NONE, &run_daemonized,
 	  "Run as a daemon", NULL },
 	{ "login", 'l', 0, G_OPTION_ARG_NONE, &run_for_login,
 	  "Run for a user login. Read login password from stdin", NULL },
-	{ "start", 's', 0, G_OPTION_ARG_NONE, &run_for_start,
-	  "Start a dameon or initialize an already running daemon." },
 	{ "components", 'c', 0, G_OPTION_ARG_STRING, &run_components,
 	  "The optional components to run", DEFAULT_COMPONENTS },
 	{ "control-directory", 'l', 0, G_OPTION_ARG_FILENAME, &control_directory,
@@ -149,6 +152,16 @@ parse_arguments (int *argc, char** argv[])
 		run_for_login = FALSE;
 	}
 
+	if (run_for_login && run_for_replace) {
+		g_printerr ("gnome-keyring-daemon: The --replace option is incompatible with --login");
+		run_for_login = FALSE;
+	}
+
+	if (run_for_start && run_for_replace) {
+		g_printerr ("gnome-keyring-daemon: The --replace option is incompatible with --start");
+		run_for_start = FALSE;
+	}
+
 	g_option_context_free (context);
 }
 
@@ -487,42 +500,50 @@ initialize_daemon_at (const gchar *directory)
 }
 
 static gboolean
-initialize_daemon (const gchar *directory)
+replace_daemon_at (const gchar *directory)
 {
+	g_free (control_directory);
+	control_directory = g_strdup (directory);
+	return gkd_control_quit (directory);
+}
+
+typedef gboolean (*DiscoverFunc) (const gchar *control_directory);
+
+static gboolean
+discover_other_daemon (DiscoverFunc callback, gboolean acquire)
+{
+	const gchar *control_env;
 	gchar *control = NULL;
-	gboolean acquired, ret;
+	gboolean acquired = FALSE;
+	gboolean ret;
 
-	/* A pre-specified directory to control at */
-	if (directory) {
-		if (initialize_daemon_at (directory))
-			return TRUE;
-	}
+	/* A pre-specified directory to control at, don't try anything else */
+	if (control_directory)
+		return (callback) (control_directory);
 
 	/* An environment variable from an already running daemon */
-	directory = g_getenv (GKD_UTIL_ENV_CONTROL);
-	if (directory && directory[0]) {
-		if (initialize_daemon_at (directory))
+	control_env = g_getenv (GKD_UTIL_ENV_CONTROL);
+	if (control_env && control_env[0]) {
+		if ((callback)(control_env))
 			return TRUE;
 	}
 
 	/* See if we can contact a daemon running, that didn't set an env variable */
-	if (!gkd_dbus_singleton_acquire (&acquired))
+	if (acquire && !gkd_dbus_singleton_acquire (&acquired))
 		return FALSE;
 
 	/* We're the main daemon */
 	if (acquired)
 		return FALSE;
 
-	/* Figure out the path to the other daemon's control directory */
-	directory = control = gkd_dbus_singleton_control ();
-	if (directory) {
-		ret = initialize_daemon_at (directory);
+	control = gkd_dbus_singleton_control ();
+	if (control) {
+		ret = (callback) (control);
 		g_free (control);
 		if (ret == TRUE)
 			return TRUE;
 	}
 
-	g_message ("couldn't initialize running daemon");
 	return FALSE;
 }
 
@@ -768,7 +789,7 @@ main (int argc, char *argv[])
 
 	/* The --start option */
 	if (run_for_start) {
-		if (initialize_daemon (control_directory)) {
+		if (discover_other_daemon (initialize_daemon_at, TRUE)) {
 			/*
 			 * Another daemon was initialized, print out environment
 			 * for any callers, and quit or go comatose.
@@ -778,6 +799,12 @@ main (int argc, char *argv[])
 				while (sleep(0x08000000) == 0);
 			cleanup_and_exit (0);
 		}
+
+	/* The --replace option */
+	} else if (run_for_replace) {
+		discover_other_daemon (replace_daemon_at, FALSE);
+		if (control_directory)
+			g_message ("replacing daemon at: %s", control_directory);
 	}
 
 	/* Initialize the main directory */
@@ -824,5 +851,7 @@ main (int argc, char *argv[])
 	/* Wrap up signal handling here */
 	cleanup_signal_handling ();
 
+	g_free (control_directory);
+
 	return 0;
 }



[Date Prev][Date Next]   [Thread Prev][Thread Next]   [Thread Index] [Date Index] [Author Index]