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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
29
#include <glib/gi18n.h>
33
#include <systemd/sd-daemon.h>
34
#include <systemd/sd-login.h>
37
#define GDM_DBUS_NAME "org.gnome.DisplayManager"
38
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH "/org/gnome/DisplayManager/LocalDisplayFactory"
39
#define GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE "org.gnome.DisplayManager.LocalDisplayFactory"
41
#ifdef WITH_CONSOLE_KIT
42
#define CK_NAME "org.freedesktop.ConsoleKit"
43
#define CK_PATH "/org/freedesktop/ConsoleKit"
44
#define CK_INTERFACE "org.freedesktop.ConsoleKit"
46
#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
47
#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
48
#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
49
#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
52
static const char *send_command = NULL;
53
static gboolean use_xnest = FALSE;
54
static gboolean no_lock = FALSE;
55
static gboolean debug_in = FALSE;
56
static gboolean authenticate = FALSE;
57
static gboolean startnew = FALSE;
58
static gboolean monte_carlo_pi = FALSE;
59
static gboolean show_version = FALSE;
60
static char **args_remaining = NULL;
62
/* Keep all config options for compatibility even if they are noops */
63
GOptionEntry options [] = {
64
{ "command", 'c', 0, G_OPTION_ARG_STRING, &send_command, "Only the VERSION command is supported", "COMMAND" },
65
{ "xnest", 'n', 0, G_OPTION_ARG_NONE, &use_xnest, "Ignored — retained for compatibility", NULL },
66
{ "no-lock", 'l', 0, G_OPTION_ARG_NONE, &no_lock, "Ignored — retained for compatibility", NULL },
67
{ "debug", 'd', 0, G_OPTION_ARG_NONE, &debug_in, "Debugging output", NULL },
68
{ "authenticate", 'a', 0, G_OPTION_ARG_NONE, &authenticate, "Ignored — retained for compatibility", NULL },
69
{ "startnew", 's', 0, G_OPTION_ARG_NONE, &startnew, "Ignored — retained for compatibility", NULL },
70
{ "monte-carlo-pi", 0, 0, G_OPTION_ARG_NONE, &monte_carlo_pi, NULL, NULL },
71
{ "version", 0, 0, G_OPTION_ARG_NONE, &show_version, "Version of this application", NULL },
72
{ G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_STRING_ARRAY, &args_remaining, NULL, NULL },
76
#define GDM_FLEXISERVER_ERROR gdm_flexiserver_error_quark ()
78
gdm_flexiserver_error_quark (void)
80
static GQuark ret = 0;
82
ret = g_quark_from_static_string ("gdm_flexiserver_error");
89
is_program_in_path (const char *program)
91
char *tmp = g_find_program_in_path (program);
101
maybe_lock_screen (void)
103
gboolean use_gscreensaver = FALSE;
104
GError *error = NULL;
107
if (is_program_in_path ("gnome-screensaver-command")) {
108
use_gscreensaver = TRUE;
109
} else if (! is_program_in_path ("xscreensaver-command")) {
113
if (use_gscreensaver) {
114
command = g_strdup ("gnome-screensaver-command --lock");
116
command = g_strdup ("xscreensaver-command -lock");
119
if (! g_spawn_command_line_async (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 (! g_spawn_command_line_async (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 (GDBusConnection *connection,
159
GError *local_error = NULL;
163
reply = g_dbus_connection_call_sync (connection,
165
GDM_DBUS_LOCAL_DISPLAY_FACTORY_PATH,
166
GDM_DBUS_LOCAL_DISPLAY_FACTORY_INTERFACE,
167
"CreateTransientDisplay",
168
NULL, /* parameters */
169
G_VARIANT_TYPE ("(o)"),
170
G_DBUS_CALL_FLAGS_NONE,
174
g_warning ("Unable to create transient display: %s", local_error->message);
175
g_propagate_error (error, local_error);
179
g_variant_get (reply, "(&o)", &value);
180
g_debug ("Started %s", value);
182
g_variant_unref (reply);
186
#ifdef WITH_CONSOLE_KIT
189
get_current_session_id (GDBusConnection *connection,
192
GError *local_error = NULL;
195
reply = g_dbus_connection_call_sync (connection,
198
CK_MANAGER_INTERFACE,
200
NULL, /* parameters */
201
G_VARIANT_TYPE ("(o)"),
202
G_DBUS_CALL_FLAGS_NONE,
206
g_warning ("Unable to determine session: %s", local_error->message);
207
g_error_free (local_error);
211
g_variant_get (reply, "(o)", session_id);
212
g_variant_unref (reply);
218
get_seat_id_for_session (GDBusConnection *connection,
219
const char *session_id,
222
GError *local_error = NULL;
225
reply = g_dbus_connection_call_sync (connection,
228
CK_SESSION_INTERFACE,
230
NULL, /* parameters */
231
G_VARIANT_TYPE ("(o)"),
232
G_DBUS_CALL_FLAGS_NONE,
236
g_warning ("Unable to determine seat: %s", local_error->message);
237
g_error_free (local_error);
241
g_variant_get (reply, "(o)", seat_id);
242
g_variant_unref (reply);
248
get_current_seat_id (GDBusConnection *connection)
257
res = get_current_session_id (connection, &session_id);
259
res = get_seat_id_for_session (connection, session_id, &seat_id);
267
activate_session_id_for_ck (GDBusConnection *connection,
269
const char *session_id)
271
GError *local_error = NULL;
274
reply = g_dbus_connection_call_sync (connection,
279
g_variant_new ("(o)", session_id),
281
G_DBUS_CALL_FLAGS_NONE,
285
g_warning ("Unable to activate session: %s", local_error->message);
286
g_error_free (local_error);
290
g_variant_unref (reply);
296
session_is_login_window (GDBusConnection *connection,
297
const char *session_id)
299
GError *local_error = NULL;
304
reply = g_dbus_connection_call_sync (connection,
307
CK_SESSION_INTERFACE,
310
G_VARIANT_TYPE ("(s)"),
311
G_DBUS_CALL_FLAGS_NONE,
315
g_warning ("Unable to determine session type: %s", local_error->message);
316
g_error_free (local_error);
320
g_variant_get (reply, "(&s)", &value);
322
if (value == NULL || value[0] == '\0' || strcmp (value, "LoginWindow") != 0) {
328
g_variant_unref (reply);
334
seat_can_activate_sessions (GDBusConnection *connection,
337
GError *local_error = NULL;
341
reply = g_dbus_connection_call_sync (connection,
345
"CanActivateSessions",
347
G_VARIANT_TYPE ("(b)"),
348
G_DBUS_CALL_FLAGS_NONE,
352
g_warning ("Unable to determine if can activate sessions: %s", local_error->message);
353
g_error_free (local_error);
357
g_variant_get (reply, "(b)", &ret);
358
g_variant_unref (reply);
364
seat_get_sessions (GDBusConnection *connection,
367
GError *local_error = NULL;
371
reply = g_dbus_connection_call_sync (connection,
377
G_VARIANT_TYPE ("(ao)"),
378
G_DBUS_CALL_FLAGS_NONE,
382
g_warning ("Unable to list sessions: %s", local_error->message);
383
g_error_free (local_error);
387
g_variant_get (reply, "(^ao)", &value);
388
g_variant_unref (reply);
394
get_login_window_session_id_for_ck (GDBusConnection *connection,
398
gboolean can_activate_sessions;
399
const char **sessions;
405
g_debug ("checking if seat can activate sessions");
407
can_activate_sessions = seat_can_activate_sessions (connection, seat_id);
408
if (! can_activate_sessions) {
409
g_debug ("seat is unable to activate sessions");
413
sessions = seat_get_sessions (connection, seat_id);
414
for (i = 0; sessions [i] != NULL; i++) {
419
if (session_is_login_window (connection, ssid)) {
420
*session_id = g_strdup (ssid);
430
goto_login_session_for_ck (GDBusConnection *connection,
440
/* First look for any existing LoginWindow sessions on the seat.
441
If none are found, create a new one. */
443
seat_id = get_current_seat_id (connection);
444
if (seat_id == NULL || seat_id[0] == '\0') {
445
g_debug ("seat id is not set; can't switch sessions");
446
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "Could not identify the current session.");
451
res = get_login_window_session_id_for_ck (connection, seat_id, &session_id);
453
g_set_error (error, GDM_FLEXISERVER_ERROR, 1, "User unable to switch sessions.");
457
if (session_id != NULL) {
458
res = activate_session_id_for_ck (connection, seat_id, session_id);
464
if (! ret && g_strcmp0 (seat_id, "/org/freedesktop/ConsoleKit/Seat1") == 0) {
465
res = create_transient_display (connection, error);
478
activate_session_id_for_systemd (GDBusConnection *connection,
480
const char *session_id)
482
GError *local_error = NULL;
485
reply = g_dbus_connection_call_sync (connection,
486
"org.freedesktop.login1",
487
"/org/freedesktop/login1",
488
"org.freedesktop.login1.Manager",
489
"ActivateSessionOnSeat",
490
g_variant_new ("(ss)", session_id, seat_id),
492
G_DBUS_CALL_FLAGS_NONE,
496
g_warning ("Unable to activate session: %s", local_error->message);
497
g_error_free (local_error);
501
g_variant_unref (reply);
507
get_login_window_session_id_for_systemd (const char *seat_id,
517
res = sd_seat_get_sessions (seat_id, &sessions, NULL, NULL);
519
g_debug ("Failed to determine sessions: %s", strerror (-res));
523
if (sessions == NULL || sessions[0] == NULL) {
529
for (i = 0; sessions[i]; i ++) {
531
res = sd_session_get_class (sessions[i], &service_class);
533
g_debug ("failed to determine class of session %s: %s", sessions[i], strerror (-res));
538
if (strcmp (service_class, "greeter") != 0) {
539
free (service_class);
543
free (service_class);
545
ret = sd_session_get_state (sessions[i], &state);
547
g_debug ("failed to determine state of session %s: %s", sessions[i], strerror (-res));
552
if (g_strcmp0 (state, "closing") == 0) {
558
res = sd_session_get_service (sessions[i], &service_id);
560
g_debug ("failed to determine service of session %s: %s", sessions[i], strerror (-res));
565
if (strcmp (service_id, "gdm-welcome") == 0) {
566
*session_id = g_strdup (sessions[i]);
580
for (i = 0; sessions[i]; i ++) {
590
goto_login_session_for_systemd (GDBusConnection *connection,
603
/* First look for any existing LoginWindow sessions on the seat.
604
If none are found, create a new one. */
606
/* Note that we mostly use free () here, instead of g_free ()
607
* since the data allocated is from libsystemd-logind, which
608
* does not use GLib's g_malloc (). */
610
res = sd_pid_get_session (0, &our_session);
612
g_debug ("failed to determine own session: %s", strerror (-res));
613
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "Could not identify the current session.");
618
res = sd_session_get_seat (our_session, &seat_id);
621
g_debug ("failed to determine own seat: %s", strerror (-res));
622
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "Could not identify the current seat.");
627
res = sd_seat_can_multi_session (seat_id);
631
g_debug ("failed to determine whether seat can do multi session: %s", strerror (-res));
632
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "The system is unable to determine whether to switch to an existing login screen or start up a new login screen.");
640
g_set_error (error, GDM_FLEXISERVER_ERROR, 0, "The system is unable to start up a new login screen.");
645
res = get_login_window_session_id_for_systemd (seat_id, &session_id);
646
if (res && session_id != NULL) {
647
res = activate_session_id_for_systemd (connection, seat_id, session_id);
654
if (! ret && g_strcmp0 (seat_id, "seat0") == 0) {
655
res = create_transient_display (connection, error);
669
goto_login_session (GError **error)
672
GDBusConnection *connection;
675
connection = g_bus_get_sync (G_BUS_TYPE_SYSTEM, NULL, &local_error);
676
if (connection == NULL) {
677
g_debug ("Failed to connect to the D-Bus daemon: %s", local_error->message);
678
g_propagate_error (error, local_error);
683
if (sd_booted () > 0) {
684
return goto_login_session_for_systemd (connection, error);
688
#ifdef WITH_CONSOLE_KIT
689
return goto_login_session_for_ck (connection, error);
694
main (int argc, char *argv[])
700
bindtextdomain (GETTEXT_PACKAGE, GNOMELOCALEDIR);
701
bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8");
702
textdomain (GETTEXT_PACKAGE);
703
setlocale (LC_ALL, "");
706
ctx = g_option_context_new ("- New GDM login");
707
g_option_context_set_translation_domain (ctx, GETTEXT_PACKAGE);
708
g_option_context_add_main_entries (ctx, options, NULL);
709
g_option_context_parse (ctx, &argc, &argv, NULL);
710
g_option_context_free (ctx);
714
g_print ("%s %s\n", argv [0], VERSION);
718
/* don't support commands other than VERSION */
719
if (send_command != NULL) {
720
if (strcmp (send_command, "VERSION") == 0) {
721
g_print ("GDM %s \n", VERSION);
724
g_warning ("No longer supported");
729
gtk_init (&argc, &argv);
731
if (monte_carlo_pi) {
736
if (args_remaining != NULL && args_remaining[0] != NULL) {
741
g_warning ("Not yet implemented");
746
res = goto_login_session (&error);
752
message = g_strdup_printf ("%s", error->message);
753
g_error_free (error);
755
message = g_strdup ("");
758
dialog = gtk_message_dialog_new (NULL,
759
GTK_DIALOG_DESTROY_WITH_PARENT,
762
"%s", "Unable to start new display");
764
gtk_message_dialog_format_secondary_text (GTK_MESSAGE_DIALOG (dialog),
768
gtk_window_set_title (GTK_WINDOW (dialog), "");
769
gtk_window_set_icon_name (GTK_WINDOW (dialog), "session-properties");
770
gtk_container_set_border_width (GTK_CONTAINER (dialog), 5);
771
gtk_box_set_spacing (GTK_BOX (gtk_dialog_get_content_area (GTK_DIALOG (dialog))), 14);
773
gtk_dialog_run (GTK_DIALOG (dialog));
774
gtk_widget_destroy (dialog);
776
maybe_lock_screen ();