summaryrefslogtreecommitdiff
path: root/service/dconf-blame.c
diff options
context:
space:
mode:
authorRyan Lortie <desrt@desrt.ca>2012-10-23 10:11:08 +0200
committerRyan Lortie <desrt@desrt.ca>2012-10-23 10:19:32 +0200
commit324df561617b777848b149416f0f6c0c3801b2d8 (patch)
treecf03127a19de5ace0f6d0976975bbe055455a36f /service/dconf-blame.c
parent004f135e50164dc409bd6de74bc9ee3fe61da3e9 (diff)
downloaddconf-324df561617b777848b149416f0f6c0c3801b2d8.tar.gz
service: rewrite
Rewrite the dconf-service using gdbus-codegen and generally cleaning things up a lot. The DConfWriter class can now be reasonably subclassed to create more complex types of dconf databases (such as ones that are stored in the local runtime dir and synced up with an NFS home directory). Keep a cache of the keys in the database (instead of re-reading it every time we try to make a change). Drop support for the old D-Bus interface (now that we are two stable releases since it was used). Modify the commandline tool for 'dconf blame' to call the new interface.
Diffstat (limited to 'service/dconf-blame.c')
-rw-r--r--service/dconf-blame.c189
1 files changed, 189 insertions, 0 deletions
diff --git a/service/dconf-blame.c b/service/dconf-blame.c
new file mode 100644
index 0000000..920ef08
--- /dev/null
+++ b/service/dconf-blame.c
@@ -0,0 +1,189 @@
+/*
+ * Copyright © 2012 Canonical Limited
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2 of the licence, or (at your option) any later version.
+ *
+ * This library 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
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library; if not, write to the
+ * Free Software Foundation, Inc., 59 Temple Place - Suite 330,
+ * Boston, MA 02111-1307, USA.
+ *
+ * Author: Ryan Lortie <desrt@desrt.ca>
+ */
+
+#include "dconf-blame.h"
+
+#include "dconf-generated.h"
+
+#include <string.h>
+#include <fcntl.h>
+
+typedef DConfDBusServiceInfoSkeletonClass DConfBlameClass;
+struct _DConfBlame
+{
+ DConfDBusServiceInfoSkeleton parent_instance;
+
+ GString *blame_info;
+};
+
+static void dconf_blame_iface_init (DConfDBusServiceInfoIface *iface);
+G_DEFINE_TYPE_WITH_CODE (DConfBlame, dconf_blame, DCONF_DBUS_TYPE_SERVICE_INFO_SKELETON,
+ G_IMPLEMENT_INTERFACE (DCONF_DBUS_TYPE_SERVICE_INFO, dconf_blame_iface_init))
+
+#include "../common/dconf-changeset.h"
+#include "dconf-writer.h"
+
+void
+dconf_blame_record (GDBusMethodInvocation *invocation)
+{
+ DConfBlame *blame = dconf_blame_get ();
+ GError *error = NULL;
+ GVariant *parameters;
+ GVariant *reply;
+ GString *info;
+
+ if (!blame)
+ return;
+
+ if (blame->blame_info->len)
+ g_string_append (blame->blame_info, "\n====================================================================\n");
+
+ info = blame->blame_info;
+
+ g_string_append_printf (info, "Sender: %s\n", g_dbus_method_invocation_get_sender (invocation));
+ g_string_append_printf (info, "Object path: %s\n", g_dbus_method_invocation_get_object_path (invocation));
+ g_string_append_printf (info, "Method: %s\n", g_dbus_method_invocation_get_method_name (invocation));
+
+ if ((parameters = g_dbus_method_invocation_get_parameters (invocation)))
+ {
+ gchar *tmp;
+
+ tmp = g_variant_print (parameters, FALSE);
+ g_string_append_printf (info, "Parameters: %s\n", tmp);
+ g_free (tmp);
+ }
+
+ reply = g_dbus_connection_call_sync (g_dbus_method_invocation_get_connection (invocation),
+ "org.freedesktop.DBus", "/", "org.freedesktop.DBus",
+ "GetConnectionUnixProcessID",
+ g_variant_new ("(s)", g_dbus_method_invocation_get_sender (invocation)),
+ G_VARIANT_TYPE ("(u)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
+
+ if (reply != NULL)
+ {
+ guint pid;
+
+ g_variant_get (reply, "(u)", &pid);
+ g_string_append_printf (info, "PID: %u\n", pid);
+ g_variant_unref (reply);
+ }
+ else
+ {
+ g_string_append_printf (info, "Unable to acquire PID: %s\n", error->message);
+ g_error_free (error);
+ }
+
+ {
+ const gchar * const ps_fx[] = { "ps", "fx", NULL };
+ gchar *result_out;
+ gchar *result_err;
+ gint status;
+
+ if (g_spawn_sync (NULL, (gchar **) ps_fx, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
+ &result_out, &result_err, &status, &error))
+ {
+ g_string_append (info, "\n=== Process table from time of call follows ('ps fx') ===\n");
+ g_string_append (info, result_out);
+ g_string_append (info, result_err);
+ g_string_append_printf (info, "\nps exit status: %u\n", status);
+ }
+ else
+ {
+ g_string_append_printf (info, "\nUnable to spawn 'ps fx': %s\n", error->message);
+ g_error_free (error);
+ }
+ }
+}
+
+static gboolean
+dconf_blame_handle_blame (DConfDBusServiceInfo *info,
+ GDBusMethodInvocation *invocation)
+{
+ DConfBlame *blame = DCONF_BLAME (info);
+
+ dconf_blame_record (invocation);
+
+ g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", blame->blame_info->str));
+
+ return TRUE;
+}
+
+static void
+dconf_blame_init (DConfBlame *blame)
+{
+ blame->blame_info = g_string_new (NULL);
+}
+
+static void
+dconf_blame_class_init (DConfBlameClass *class)
+{
+}
+
+static void
+dconf_blame_iface_init (DConfDBusServiceInfoIface *iface)
+{
+ iface->handle_blame = dconf_blame_handle_blame;
+}
+
+static gboolean
+dconf_blame_enabled (void)
+{
+ gint fd;
+
+ if (getenv ("DCONF_BLAME"))
+ return TRUE;
+
+ fd = open ("/proc/cmdline", O_RDONLY);
+ if (fd != -1)
+ {
+ gchar buffer[1024];
+ gssize s;
+
+ s = read (fd, buffer, sizeof buffer - 1);
+ close (fd);
+
+ if (0 < s && s < sizeof buffer)
+ {
+ buffer[s] = '\0';
+ if (strstr (buffer, "DCONF_BLAME"))
+ return TRUE;
+ }
+ }
+
+ return FALSE;
+}
+
+DConfBlame *
+dconf_blame_get (void)
+{
+ static DConfBlame *blame;
+ static gboolean checked;
+
+ if (!checked)
+ {
+ if (dconf_blame_enabled ())
+ blame = g_object_new (DCONF_TYPE_BLAME, NULL);
+
+ checked = TRUE;
+ }
+
+ return blame;
+}