1 /* Taken from LightDM and modified.
2  * Copyright (C) 2012 Fabrice THIROUX <fabrice.thiroux@free.fr>.
3  *
4  **** License from former file (power.c) ****
5  *
6  * Copyright (C) 2010-2011 Robert Ancell.
7  * Author: Robert Ancell <robert.ancell@canonical.com>
8  *
9  * This library is free software; you can redistribute it and/or modify it under
10  * the terms of the GNU Lesser General Public License as published by the Free
11  * Software Foundation; either version 3 of the License, or (at your option) any
12  * later version. See http://www.gnu.org/copyleft/lgpl.html the full text of the
13  * license.
14  */
15 #include <config.h>
16 #include <glib.h>
17 #include <string.h>
18 #include <gio/gio.h>
19 
20 /*** Mechanism independent ***/
21 
22 static GDBusProxy *upower_proxy = NULL;
23 static GDBusProxy *ck_proxy = NULL;
24 static GDBusProxy *systemd_proxy = NULL;
25 static GDBusProxy *lightdm_proxy = NULL;
26 static GDBusProxy *lxde_proxy = NULL;
27 
28 
29 /*** UPower mechanism ***/
30 
31 static gboolean
upower_call_function(const gchar * function,gboolean default_result,GError ** error)32 upower_call_function (const gchar *function, gboolean default_result, GError **error)
33 {
34     GVariant *result;
35     gboolean function_result = FALSE;
36 
37     if (!upower_proxy)
38     {
39         upower_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
40                                                       G_DBUS_PROXY_FLAGS_NONE,
41                                                       NULL,
42                                                       "org.freedesktop.UPower",
43                                                       "/org/freedesktop/UPower",
44                                                       "org.freedesktop.UPower",
45                                                       NULL,
46                                                       error);
47         if (!upower_proxy)
48             return FALSE;
49     }
50 
51     result = g_dbus_proxy_call_sync (upower_proxy,
52                                      function,
53                                      NULL,
54                                      G_DBUS_CALL_FLAGS_NONE,
55                                      -1,
56                                      NULL,
57                                      error);
58     if (!result)
59         return default_result;
60 
61     if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
62         g_variant_get (result, "(b)", &function_result);
63 
64     g_variant_unref (result);
65     return function_result;
66 }
67 
68 gboolean
dbus_UPower_CanSuspend(void)69 dbus_UPower_CanSuspend (void)
70 {
71     return upower_call_function ("SuspendAllowed", FALSE, NULL);
72 }
73 
74 gboolean
dbus_UPower_Suspend(GError ** error)75 dbus_UPower_Suspend (GError **error)
76 {
77     return upower_call_function ("Suspend", TRUE, error);
78 }
79 
80 gboolean
dbus_UPower_CanHibernate(void)81 dbus_UPower_CanHibernate (void)
82 {
83     return upower_call_function ("HibernateAllowed", FALSE, NULL);
84 }
85 
86 gboolean
dbus_UPower_Hibernate(GError ** error)87 dbus_UPower_Hibernate (GError **error)
88 {
89     return upower_call_function ("Hibernate", TRUE, error);
90 }
91 
92 /*** ConsoleKit mechanism ***/
93 
94 static gboolean
ck_query(const gchar * function,gboolean default_result,GError ** error)95 ck_query (const gchar *function, gboolean default_result, GError **error)
96 {
97     GVariant *result;
98     gboolean function_result = FALSE;
99     const gchar *str;
100 
101     if (!ck_proxy)
102     {
103         ck_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
104                                                       G_DBUS_PROXY_FLAGS_NONE,
105                                                       NULL,
106                                                       "org.freedesktop.ConsoleKit",
107                                                       "/org/freedesktop/ConsoleKit/Manager",
108                                                       "org.freedesktop.ConsoleKit.Manager",
109                                                       NULL,
110                                                       error);
111         if (!ck_proxy)
112             return FALSE;
113     }
114 
115     result = g_dbus_proxy_call_sync (ck_proxy,
116                                      function,
117                                      NULL,
118                                      G_DBUS_CALL_FLAGS_NONE,
119                                      -1,
120                                      NULL,
121                                      error);
122     if (!result)
123         return default_result;
124 
125     if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(s)")))
126     {
127 			g_variant_get (result, "(s)", &str);
128 			if ( g_strcmp0 (str, "yes") == 0 || g_strcmp0 (str, "challenge") == 0 )
129 				function_result = TRUE;
130 			else
131 				function_result = default_result;
132 		}
133 
134     g_variant_unref (result);
135     return function_result;
136 }
137 
138 static void
ck_call_function(const gchar * function,gboolean value,GError ** error)139 ck_call_function (const gchar *function, gboolean value, GError **error)
140 {
141     GVariant *result;
142 
143     if (!ck_proxy)
144     {
145         ck_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
146                                                       G_DBUS_PROXY_FLAGS_NONE,
147                                                       NULL,
148                                                       "org.freedesktop.ConsoleKit",
149                                                       "/org/freedesktop/ConsoleKit",
150                                                       "org.freedesktop.ConsoleKit.Manager",
151                                                       NULL,
152                                                       error);
153         if (!ck_proxy)
154             return;
155     }
156 
157     result = g_dbus_proxy_call_sync (ck_proxy,
158                                      function,
159                                      g_variant_new ("(b)", value),
160                                      G_DBUS_CALL_FLAGS_NONE,
161                                      -1,
162                                      NULL,
163                                      error);
164     g_variant_unref (result);
165     return;
166 }
167 
168 gboolean
dbus_ConsoleKit_CanPowerOff(void)169 dbus_ConsoleKit_CanPowerOff (void)
170 {
171     return ck_query ("CanPowerOff", FALSE, NULL);
172 }
173 
174 void
dbus_ConsoleKit_PowerOff(GError ** error)175 dbus_ConsoleKit_PowerOff (GError **error)
176 {
177     ck_call_function ("PowerOff", TRUE, error);
178 }
179 
180 gboolean
dbus_ConsoleKit_CanReboot(void)181 dbus_ConsoleKit_CanReboot (void)
182 {
183     return ck_query ("CanReboot", FALSE, NULL);
184 }
185 
186 void
dbus_ConsoleKit_Reboot(GError ** error)187 dbus_ConsoleKit_Reboot (GError **error)
188 {
189     ck_call_function ("Reboot", TRUE, error);
190 }
191 
192 gboolean
dbus_ConsoleKit_CanSuspend(void)193 dbus_ConsoleKit_CanSuspend (void)
194 {
195     return ck_query ("CanSuspend", FALSE, NULL);
196 }
197 
198 void
dbus_ConsoleKit_Suspend(GError ** error)199 dbus_ConsoleKit_Suspend (GError **error)
200 {
201     ck_call_function ("Suspend", TRUE, error);
202 }
203 
204 gboolean
dbus_ConsoleKit_CanHibernate(void)205 dbus_ConsoleKit_CanHibernate (void)
206 {
207     return ck_query ("CanHibernate", FALSE, NULL);
208 }
209 
210 void
dbus_ConsoleKit_Hibernate(GError ** error)211 dbus_ConsoleKit_Hibernate (GError **error)
212 {
213     ck_call_function ("Hibernate", TRUE, error);
214 }
215 
216 /*** Systemd mechanism ***/
217 
218 static gboolean
systemd_query(const gchar * function,gboolean default_result,GError ** error)219 systemd_query (const gchar *function, gboolean default_result, GError **error)
220 {
221     GVariant *result;
222     gboolean function_result = FALSE;
223     const gchar *str;
224 
225     if (!systemd_proxy)
226     {
227         systemd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
228                                                       G_DBUS_PROXY_FLAGS_NONE,
229                                                       NULL,
230                                                       "org.freedesktop.login1",
231                                                       "/org/freedesktop/login1",
232                                                       "org.freedesktop.login1.Manager",
233                                                       NULL,
234                                                       error);
235         if (!systemd_proxy)
236             return FALSE;
237     }
238 
239     result = g_dbus_proxy_call_sync (systemd_proxy,
240                                      function,
241                                      NULL,
242                                      G_DBUS_CALL_FLAGS_NONE,
243                                      -1,
244                                      NULL,
245                                      error);
246     if (!result)
247         return default_result;
248 
249     if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(s)")))
250     {
251 			g_variant_get (result, "(s)", &str);
252 			if ( g_strcmp0 (str, "yes") == 0 || g_strcmp0 (str, "challenge") == 0 )
253 				function_result = TRUE;
254 			else
255 				function_result = default_result;
256 		}
257 
258     g_variant_unref (result);
259     return function_result;
260 }
261 
262 static void
systemd_call_function(const gchar * function,gboolean value,GError ** error)263 systemd_call_function (const gchar *function, gboolean value, GError **error)
264 {
265     GVariant *result;
266 
267     if (!systemd_proxy)
268     {
269         systemd_proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
270                                                       G_DBUS_PROXY_FLAGS_NONE,
271                                                       NULL,
272                                                       "org.freedesktop.login1",
273                                                       "/org/freedesktop/login1",
274                                                       "org.freedesktop.login1.Manager",
275                                                       NULL,
276                                                       error);
277         if (!systemd_proxy)
278             return;
279     }
280 
281     result = g_dbus_proxy_call_sync (systemd_proxy,
282                                      function,
283                                      g_variant_new ("(b)", value),
284                                      G_DBUS_CALL_FLAGS_NONE,
285                                      -1,
286                                      NULL,
287                                      error);
288     g_variant_unref (result);
289     return;
290 }
291 
292 gboolean
dbus_systemd_CanPowerOff(void)293 dbus_systemd_CanPowerOff (void)
294 {
295     return systemd_query ("CanPowerOff", FALSE, NULL);
296 }
297 
298 void
dbus_systemd_PowerOff(GError ** error)299 dbus_systemd_PowerOff (GError **error)
300 {
301     systemd_call_function ("PowerOff", TRUE, error);
302 }
303 
304 gboolean
dbus_systemd_CanReboot(void)305 dbus_systemd_CanReboot (void)
306 {
307     return systemd_query ("CanReboot", FALSE, NULL);
308 }
309 
310 void
dbus_systemd_Reboot(GError ** error)311 dbus_systemd_Reboot (GError **error)
312 {
313     systemd_call_function ("Reboot", TRUE, error);
314 }
315 
316 gboolean
dbus_systemd_CanSuspend(void)317 dbus_systemd_CanSuspend (void)
318 {
319     return systemd_query ("CanSuspend", FALSE, NULL);
320 }
321 
322 void
dbus_systemd_Suspend(GError ** error)323 dbus_systemd_Suspend (GError **error)
324 {
325     systemd_call_function ("Suspend", TRUE, error);
326 }
327 
328 gboolean
dbus_systemd_CanHibernate(void)329 dbus_systemd_CanHibernate (void)
330 {
331     return systemd_query ("CanHibernate", FALSE, NULL);
332 }
333 
334 void
dbus_systemd_Hibernate(GError ** error)335 dbus_systemd_Hibernate (GError **error)
336 {
337     systemd_call_function ("Hibernate", TRUE, error);
338 }
339 
340 /*** Lightdm mechanism ***/
341 
342 static gboolean
lightdm_call_function(const gchar * function,gboolean default_result,GError ** error)343 lightdm_call_function (const gchar *function, gboolean default_result, GError **error)
344 {
345     GVariant *result;
346     gboolean function_result = FALSE;
347 
348     if (!lightdm_proxy)
349     {
350         lightdm_proxy = g_dbus_proxy_new_for_bus_sync ( G_BUS_TYPE_SYSTEM,
351                                                         G_DBUS_PROXY_FLAGS_NONE,
352                                                         NULL,
353                                                         "org.freedesktop.DisplayManager",
354                                                         g_getenv ("XDG_SEAT_PATH"),
355                                                         "org.freedesktop.DisplayManager.Seat",
356                                                         NULL,
357                                                         error);
358         if (!lightdm_proxy)
359             return FALSE;
360     }
361 
362     result = g_dbus_proxy_call_sync (lightdm_proxy,
363                                      function,
364                                      NULL,
365                                      G_DBUS_CALL_FLAGS_NONE,
366                                      -1,
367                                      NULL,
368                                      error);
369     if (!result)
370         return default_result;
371 
372     if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
373         g_variant_get (result, "(b)", &function_result);
374 
375     g_variant_unref (result);
376     return function_result;
377 }
378 
379 gboolean
dbus_Lightdm_SwitchToGreeter(GError ** error)380 dbus_Lightdm_SwitchToGreeter (GError **error)
381 {
382     return lightdm_call_function ("SwitchToGreeter", TRUE, error);
383 }
384 
385 /*** LXDE mechanism ***/
386 
387 static gboolean
lxde_call_function(const gchar * function,gboolean default_result,GError ** error)388 lxde_call_function (const gchar *function, gboolean default_result, GError **error)
389 {
390     GVariant *result;
391     gboolean function_result = FALSE;
392 
393     if (!lxde_proxy)
394     {
395         lxde_proxy = g_dbus_proxy_new_for_bus_sync (    G_BUS_TYPE_SYSTEM,
396                                                         G_DBUS_PROXY_FLAGS_NONE,
397                                                         NULL,
398                                                         "org.lxde.SessionManager",
399                                                         "/org/lxde/SessionManager",
400                                                         "org.lxde.SessionManager",
401                                                         NULL,
402                                                         error);
403         if (!lxde_proxy)
404             return FALSE;
405     }
406 
407     result = g_dbus_proxy_call_sync (lxde_proxy,
408                                      function,
409                                      NULL,
410                                      G_DBUS_CALL_FLAGS_NONE,
411                                      -1,
412                                      NULL,
413                                      error);
414     if (!result)
415         return default_result;
416 
417     if (g_variant_is_of_type (result, G_VARIANT_TYPE ("(b)")))
418         g_variant_get (result, "(b)", &function_result);
419 
420     g_variant_unref (result);
421     return function_result;
422 }
423 
424 gboolean
dbus_LXDE_Logout(GError ** error)425 dbus_LXDE_Logout (GError **error)
426 {
427     return lxde_call_function ("Restart", TRUE, error);
428 }
429