1
/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
3
* Copyright (C) 2008 William Jon McCann <jmccann@redhat.com>
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
29
#include <glib/gi18n.h>
32
#define DBUS_API_SUBJECT_TO_CHANGE
33
#include <dbus/dbus-glib.h>
34
#include <dbus/dbus-glib-lowlevel.h>
36
#define GDM_DBUS_NAME "org.gnome.DisplayManager"
37
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH "/org/gnome/DisplayManager/LocalDisplayFactory"
38
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE "org.gnome.DisplayManager.LocalDisplayFactory"
40
#define CK_NAME "org.freedesktop.ConsoleKit"
41
#define CK_PATH "/org/freedesktop/ConsoleKit"
42
#define CK_INTERFACE "org.freedesktop.ConsoleKit"
44
#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
45
#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
46
#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
47
#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
49
static const char *send_command = NULL;
50
static gboolean use_xnest = FALSE;
51
static gboolean no_lock = FALSE;
52
static gboolean debug_in = FALSE;
53
static gboolean authenticate = FALSE;
54
static gboolean startnew = FALSE;
55
static gboolean monte_carlo_pi = FALSE;
56
static gboolean show_version = FALSE;
57
static char **args_remaining = NULL;
59
/* Keep all config options for compatibility even if they are noops */
60
GOptionEntry options [] = {
61
{ "command", 'c', 0, G_OPTION_ARG_STRING, &send_command, N_("Only the VERSION command is supported"), N_("COMMAND") },
62
{ "xnest", 'n', 0, G_OPTION_ARG_NONE, &use_xnest, N_("Ignored - retained for compatibility"), NULL },
63
{ "no-lock", 'l', 0, G_OPTION_ARG_NONE, &no_lock, N_("Ignored - retained for compatibility"), NULL },
64
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_in, N_("Debugging output"), NULL },
65
{ "authenticate", 'a', 0, G_OPTION_ARG_NONE, &authenticate, N_("Ignored - retained for compatibility"), NULL },
66
{ "startnew", 's', 0, G_OPTION_ARG_NONE, &startnew, N_("Ignored - retained for compatibility"), NULL },
67
{ "monte-carlo-pi", 0, 0, G_OPTION_ARG_NONE, &monte_carlo_pi, NULL, NULL },
68
{ "version", 0, 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
69
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, NULL },
73
#define GDM_FLEXISERVER_ERROR gdm_flexiserver_error_quark ()
75
gdm_flexiserver_error_quark (void)
77
static GQuark ret = 0;
79
ret = g_quark_from_static_string ("gdm_flexiserver_error");
86
is_program_in_path (const char *program)
88
char *tmp = g_find_program_in_path (program);
98
maybe_lock_screen (void)
100
gboolean use_gscreensaver = FALSE;
101
GError *error = NULL;
105
if (is_program_in_path ("gnome-screensaver-command")) {
106
use_gscreensaver = TRUE;
107
} else if (! is_program_in_path ("xscreensaver-command")) {
111
if (use_gscreensaver) {
112
command = g_strdup ("gnome-screensaver-command --lock");
114
command = g_strdup ("xscreensaver-command -lock");
117
screen = gdk_screen_get_default ();
119
if (! gdk_spawn_command_line_on_screen (screen, command, &error)) {
120
g_warning ("Cannot lock screen: %s", error->message);
121
g_error_free (error);
126
if (! use_gscreensaver) {
127
command = g_strdup ("xscreensaver-command -throttle");
128
if (! gdk_spawn_command_line_on_screen (screen, command, &error)) {
129
g_warning ("Cannot disable screensaver engines: %s", error->message);
130
g_error_free (error);
140
unsigned long n = 0, h = 0;
144
x = g_random_double ();
145
y = g_random_double ();
150
printf ("pi ~~ %1.10f\t(%lu/%lu * 4) iteration: %lu \r",
151
((double)h)/(double)n * 4.0, h, n, n);
156
create_transient_display (DBusConnection *connection,
159
DBusError local_error;
160
DBusMessage *message;
163
DBusMessageIter iter;
169
dbus_error_init (&local_error);
170
message = dbus_message_new_method_call (GDM_DBUS_NAME,
171
GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
172
GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
173
"CreateTransientDisplay");
174
if (message == NULL) {
175
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "Out of memory.");
179
dbus_error_init (&local_error);
180
reply = dbus_connection_send_with_reply_and_block (connection,
185
if (dbus_error_is_set (&local_error)) {
186
g_warning ("Unable to create transient display: %s", local_error.message);
187
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "%s", local_error.message);
188
dbus_error_free (&local_error);
193
dbus_message_iter_init (reply, &iter);
194
dbus_message_iter_get_basic (&iter, &value);
195
g_debug ("Started %s", value);
199
if (message != NULL) {
200
dbus_message_unref (message);
203
dbus_message_unref (reply);
210
get_current_session_id (DBusConnection *connection,
213
DBusError local_error;
214
DBusMessage *message;
217
DBusMessageIter iter;
223
dbus_error_init (&local_error);
224
message = dbus_message_new_method_call (CK_NAME,
226
CK_MANAGER_INTERFACE,
227
"GetCurrentSession");
228
if (message == NULL) {
232
dbus_error_init (&local_error);
233
reply = dbus_connection_send_with_reply_and_block (connection,
238
if (dbus_error_is_set (&local_error)) {
239
g_warning ("Unable to determine session: %s", local_error.message);
240
dbus_error_free (&local_error);
245
dbus_message_iter_init (reply, &iter);
246
dbus_message_iter_get_basic (&iter, &value);
247
if (session_id != NULL) {
248
*session_id = g_strdup (value);
253
if (message != NULL) {
254
dbus_message_unref (message);
257
dbus_message_unref (reply);
264
get_seat_id_for_session (DBusConnection *connection,
265
const char *session_id,
268
DBusError local_error;
269
DBusMessage *message;
272
DBusMessageIter iter;
278
dbus_error_init (&local_error);
279
message = dbus_message_new_method_call (CK_NAME,
281
CK_SESSION_INTERFACE,
283
if (message == NULL) {
287
dbus_error_init (&local_error);
288
reply = dbus_connection_send_with_reply_and_block (connection,
293
if (dbus_error_is_set (&local_error)) {
294
g_warning ("Unable to determine seat: %s", local_error.message);
295
dbus_error_free (&local_error);
300
dbus_message_iter_init (reply, &iter);
301
dbus_message_iter_get_basic (&iter, &value);
302
if (seat_id != NULL) {
303
*seat_id = g_strdup (value);
308
if (message != NULL) {
309
dbus_message_unref (message);
312
dbus_message_unref (reply);
319
get_current_seat_id (DBusConnection *connection)
328
res = get_current_session_id (connection, &session_id);
330
res = get_seat_id_for_session (connection, session_id, &seat_id);
338
activate_session_id (DBusConnection *connection,
340
const char *session_id)
342
DBusError local_error;
343
DBusMessage *message;
350
g_debug ("Switching to session %s", session_id);
352
dbus_error_init (&local_error);
353
message = dbus_message_new_method_call (CK_NAME,
357
if (message == NULL) {
361
if (! dbus_message_append_args (message,
362
DBUS_TYPE_OBJECT_PATH, &session_id,
363
DBUS_TYPE_INVALID)) {
368
dbus_error_init (&local_error);
369
reply = dbus_connection_send_with_reply_and_block (connection,
374
if (dbus_error_is_set (&local_error)) {
375
g_warning ("Unable to activate session: %s", local_error.message);
376
dbus_error_free (&local_error);
383
if (message != NULL) {
384
dbus_message_unref (message);
387
dbus_message_unref (reply);
394
session_is_login_window (DBusConnection *connection,
395
const char *session_id)
397
DBusError local_error;
398
DBusMessage *message;
401
DBusMessageIter iter;
407
dbus_error_init (&local_error);
408
message = dbus_message_new_method_call (CK_NAME,
410
CK_SESSION_INTERFACE,
412
if (message == NULL) {
416
dbus_error_init (&local_error);
417
reply = dbus_connection_send_with_reply_and_block (connection,
422
if (dbus_error_is_set (&local_error)) {
423
g_warning ("Unable to determine seat: %s", local_error.message);
424
dbus_error_free (&local_error);
429
dbus_message_iter_init (reply, &iter);
430
dbus_message_iter_get_basic (&iter, &value);
432
if (value == NULL || value[0] == '\0' || strcmp (value, "LoginWindow") != 0) {
438
if (message != NULL) {
439
dbus_message_unref (message);
442
dbus_message_unref (reply);
449
seat_can_activate_sessions (DBusConnection *connection,
452
DBusError local_error;
453
DBusMessage *message;
455
DBusMessageIter iter;
456
gboolean can_activate;
458
can_activate = FALSE;
461
dbus_error_init (&local_error);
462
message = dbus_message_new_method_call (CK_NAME,
465
"CanActivateSessions");
466
if (message == NULL) {
470
dbus_error_init (&local_error);
471
reply = dbus_connection_send_with_reply_and_block (connection,
476
if (dbus_error_is_set (&local_error)) {
477
g_warning ("Unable to activate session: %s", local_error.message);
478
dbus_error_free (&local_error);
483
dbus_message_iter_init (reply, &iter);
484
dbus_message_iter_get_basic (&iter, &can_activate);
487
if (message != NULL) {
488
dbus_message_unref (message);
491
dbus_message_unref (reply);
499
get_path_array_from_iter (DBusMessageIter *iter,
506
buffer = (char **)malloc (sizeof (char *) * 8);
512
while (dbus_message_iter_get_arg_type (iter) == DBUS_TYPE_OBJECT_PATH) {
516
if ((count % 8) == 0 && count != 0) {
517
buffer = realloc (buffer, sizeof (char *) * (count + 8));
522
dbus_message_iter_get_basic (iter, &value);
523
str = strdup (value);
529
dbus_message_iter_next (iter);
533
if ((count % 8) == 0) {
534
buffer = realloc (buffer, sizeof (char *) * (count + 1));
539
buffer[count] = NULL;
540
if (num_elements != NULL)
541
*num_elements = count;
545
g_debug ("%s %d : error allocating memory\n", __FILE__, __LINE__);
551
seat_get_sessions (DBusConnection *connection,
555
DBusMessage *message;
557
DBusMessageIter iter_reply;
558
DBusMessageIter iter_array;
565
dbus_error_init (&error);
566
message = dbus_message_new_method_call (CK_NAME,
570
if (message == NULL) {
571
g_debug ("Couldn't allocate the D-Bus message");
575
dbus_error_init (&error);
576
reply = dbus_connection_send_with_reply_and_block (connection,
579
dbus_connection_flush (connection);
581
if (dbus_error_is_set (&error)) {
582
g_debug ("ConsoleKit %s raised:\n %s\n\n", error.name, error.message);
587
g_debug ("ConsoleKit: No reply for GetSessionsForUser");
591
dbus_message_iter_init (reply, &iter_reply);
592
if (dbus_message_iter_get_arg_type (&iter_reply) != DBUS_TYPE_ARRAY) {
593
g_debug ("ConsoleKit Wrong reply for GetSessionsForUser - expecting an array.");
597
dbus_message_iter_recurse (&iter_reply, &iter_array);
598
sessions = get_path_array_from_iter (&iter_array, NULL);
601
if (message != NULL) {
602
dbus_message_unref (message);
605
dbus_message_unref (reply);
612
get_login_window_session_id (DBusConnection *connection,
615
gboolean can_activate_sessions;
623
g_debug ("checking if seat can activate sessions");
625
can_activate_sessions = seat_can_activate_sessions (connection, seat_id);
626
if (! can_activate_sessions) {
627
g_debug ("seat is unable to activate sessions");
631
sessions = seat_get_sessions (connection, seat_id);
632
for (i = 0; sessions [i] != NULL; i++) {
637
if (session_is_login_window (connection, ssid)) {
638
session_id = g_strdup (ssid);
642
g_strfreev (sessions);
649
goto_login_session (GError **error)
655
DBusError local_error;
656
DBusConnection *connection;
660
dbus_error_init (&local_error);
661
connection = dbus_bus_get (DBUS_BUS_SYSTEM, &local_error);
662
if (connection == NULL) {
663
g_debug ("Failed to connect to the D-Bus daemon: %s", local_error.message);
664
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "%s", local_error.message);
665
dbus_error_free (&local_error);
669
/* First look for any existing LoginWindow sessions on the seat.
670
If none are found, create a new one. */
672
seat_id = get_current_seat_id (connection);
673
if (seat_id == NULL || seat_id[0] == '\0') {
674
g_debug ("seat id is not set; can't switch sessions");
675
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, _("Could not identify the current session."));
680
session_id = get_login_window_session_id (connection, seat_id);
681
if (session_id != NULL) {
682
res = activate_session_id (connection, seat_id, session_id);
689
res = create_transient_display (connection, error);
699
main (int argc, char *argv[])
705
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
706
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
707
textdomain (GETTEXT_PACKAGE);
708
setlocale (LC_ALL, "");
711
ctx = g_option_context_new (_("- New GDM login"));
712
g_option_context_set_translation_domain (ctx, GETTEXT_PACKAGE);
713
g_option_context_add_main_entries (ctx, options, NULL);
714
g_option_context_parse (ctx, &argc, &argv, NULL);
715
g_option_context_free (ctx);
719
g_print ("%s %s\n", argv [0], VERSION);
723
/* don't support commands other than VERSION */
724
if (send_command != NULL) {
725
if (strcmp (send_command, "VERSION") == 0) {
726
g_print ("GDM %s \n", VERSION);
729
g_warning ("No longer supported");
734
gtk_init (&argc, &argv);
736
if (monte_carlo_pi) {
741
if (args_remaining != NULL && args_remaining[0] != NULL) {
746
g_warning ("Not yet implemented");
751
res = goto_login_session (&error);
757
message = g_strdup_printf ("%s", error->message);
758
g_error_free (error);
760
message = g_strdup ("");
763
dialog = gtk_message_dialog_new (NULL,
764
GTK_DIALOG_DESTROY_WITH_PARENT,
767
"%s", _("Unable to start new display"));
769
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
773
gtk_window_set_title (GTK_WINDOW (dialog), "");
774
gtk_window_set_icon_name (GTK_WINDOW (dialog), "session-properties");
775
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
776
gtk_box_set_spacing (GTK_BOX (GTK_DIALOG (dialog)->vbox), 14);
778
gtk_dialog_run (GTK_DIALOG (dialog));
779
gtk_widget_destroy (dialog);
781
maybe_lock_screen ();