Declare libdconf_service as a dependency
[dconf.git] / service / dconf-blame.c
blob5084ef15a450bd7edb7fab71142e52d1b7dadf48
1 /*
2 * Copyright © 2012 Canonical Limited
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2 of the licence, or (at your option) any later version.
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
17 * Author: Ryan Lortie <desrt@desrt.ca>
20 #include "config.h"
22 #include "dconf-blame.h"
24 #include "dconf-generated.h"
26 #include <string.h>
27 #include <stdlib.h>
28 #include <fcntl.h>
30 typedef DConfDBusServiceInfoSkeletonClass DConfBlameClass;
31 struct _DConfBlame
33 DConfDBusServiceInfoSkeleton parent_instance;
35 GString *blame_info;
38 static void dconf_blame_iface_init (DConfDBusServiceInfoIface *iface);
39 G_DEFINE_TYPE_WITH_CODE (DConfBlame, dconf_blame, DCONF_DBUS_TYPE_SERVICE_INFO_SKELETON,
40 G_IMPLEMENT_INTERFACE (DCONF_DBUS_TYPE_SERVICE_INFO, dconf_blame_iface_init))
42 #include "../common/dconf-changeset.h"
43 #include "dconf-writer.h"
45 void
46 dconf_blame_record (GDBusMethodInvocation *invocation)
48 DConfBlame *blame = dconf_blame_get ();
49 GError *error = NULL;
50 GVariant *parameters;
51 GVariant *reply;
52 GString *info;
54 if (!blame)
55 return;
57 if (blame->blame_info->len)
58 g_string_append (blame->blame_info, "\n====================================================================\n");
60 info = blame->blame_info;
62 g_string_append_printf (info, "Sender: %s\n", g_dbus_method_invocation_get_sender (invocation));
63 g_string_append_printf (info, "Object path: %s\n", g_dbus_method_invocation_get_object_path (invocation));
64 g_string_append_printf (info, "Method: %s\n", g_dbus_method_invocation_get_method_name (invocation));
66 if ((parameters = g_dbus_method_invocation_get_parameters (invocation)))
68 gchar *tmp;
70 tmp = g_variant_print (parameters, FALSE);
71 g_string_append_printf (info, "Parameters: %s\n", tmp);
72 g_free (tmp);
75 reply = g_dbus_connection_call_sync (g_dbus_method_invocation_get_connection (invocation),
76 "org.freedesktop.DBus", "/", "org.freedesktop.DBus",
77 "GetConnectionUnixProcessID",
78 g_variant_new ("(s)", g_dbus_method_invocation_get_sender (invocation)),
79 G_VARIANT_TYPE ("(u)"), G_DBUS_CALL_FLAGS_NONE, -1, NULL, &error);
81 if (reply != NULL)
83 guint pid;
85 g_variant_get (reply, "(u)", &pid);
86 g_string_append_printf (info, "PID: %u\n", pid);
87 g_variant_unref (reply);
89 else
91 g_string_append_printf (info, "Unable to acquire PID: %s\n", error->message);
92 g_error_free (error);
96 const gchar * const ps_fx[] = { "ps", "fx", NULL };
97 gchar *result_out;
98 gchar *result_err;
99 gint status;
101 if (g_spawn_sync (NULL, (gchar **) ps_fx, NULL, G_SPAWN_SEARCH_PATH, NULL, NULL,
102 &result_out, &result_err, &status, &error))
104 g_string_append (info, "\n=== Process table from time of call follows ('ps fx') ===\n");
105 g_string_append (info, result_out);
106 g_string_append (info, result_err);
107 g_string_append_printf (info, "\nps exit status: %u\n", status);
109 else
111 g_string_append_printf (info, "\nUnable to spawn 'ps fx': %s\n", error->message);
112 g_error_free (error);
117 static gboolean
118 dconf_blame_handle_blame (DConfDBusServiceInfo *info,
119 GDBusMethodInvocation *invocation)
121 DConfBlame *blame = DCONF_BLAME (info);
123 dconf_blame_record (invocation);
125 g_dbus_method_invocation_return_value (invocation, g_variant_new ("(s)", blame->blame_info->str));
127 return TRUE;
130 static void
131 dconf_blame_init (DConfBlame *blame)
133 blame->blame_info = g_string_new (NULL);
136 static void
137 dconf_blame_class_init (DConfBlameClass *class)
141 static void
142 dconf_blame_iface_init (DConfDBusServiceInfoIface *iface)
144 iface->handle_blame = dconf_blame_handle_blame;
147 static gboolean
148 dconf_blame_enabled (void)
150 gint fd;
152 if (getenv ("DCONF_BLAME"))
153 return TRUE;
155 fd = open ("/proc/cmdline", O_RDONLY);
156 if (fd != -1)
158 gchar buffer[1024];
159 gssize s;
161 s = read (fd, buffer, sizeof buffer - 1);
162 close (fd);
164 if (0 < s && s < sizeof buffer)
166 buffer[s] = '\0';
167 if (strstr (buffer, "DCONF_BLAME"))
168 return TRUE;
172 return FALSE;
175 DConfBlame *
176 dconf_blame_get (void)
178 static DConfBlame *blame;
179 static gboolean checked;
181 if (!checked)
183 if (dconf_blame_enabled ())
184 blame = g_object_new (DCONF_TYPE_BLAME, NULL);
186 checked = TRUE;
189 return blame;