diff --git a/configure.ac b/configure.ac
index 117d788..2ff6020 100644
--- a/configure.ac
+++ b/configure.ac
@@ -203,6 +203,18 @@ AM_CONDITIONAL(CK_COMPILE_SOLARIS, test x$CK_BACKEND = xsolaris, [Compiling for
AC_SUBST(CK_BACKEND)
dnl ---------------------------------------------------------------------------
+dnl Check for X11 DIR
+dnl ---------------------------------------------------------------------------
+
+X11_DIR=`$PKG_CONFIG --variable=bindir xorg-server 2>/dev/null`
+if test "x$X11_DIR" = x; then
+ AC_PATH_PROGS([XSERVER], [Xorg X],,[$PATH:/usr/X11/bin:/usr/bin])
+ test "x$XSERVER" != x && X11_DIR=`dirname "$XSERVER"`
+fi
+test "x$X11_DIR" = x && X11_DIR=$bindir
+AC_SUBST([X11_DIR])
+
+dnl ---------------------------------------------------------------------------
dnl Check for PAM
dnl ---------------------------------------------------------------------------
@@ -303,6 +315,14 @@ if test "x$enable_inotify" = "xyes" ; then
fi
dnl ---------------------------------------------------------------------------
+dnl check for strverscmp
+dnl ---------------------------------------------------------------------------
+have_strverscmp=no
+AC_CHECK_FUNCS(strverscmp, [have_strverscmp=yes], [])
+
+AM_CONDITIONAL(USE_SELF_STRVERSCMP, test "x$have_strverscmp" = "xno", [Define if we do not have strverscmp])
+
+dnl ---------------------------------------------------------------------------
dnl check for RBAC
dnl ---------------------------------------------------------------------------
@@ -401,6 +421,8 @@ tools/linux/Makefile
tools/freebsd/Makefile
tools/solaris/Makefile
data/Makefile
+data/displays.d/Makefile
+data/sessions.d/Makefile
doc/Makefile
doc/dbus/ConsoleKit.xml
doc/dbus/Makefile
diff --git a/data/00-primary.seat b/data/00-primary.seat
index 6e61db4..0632382 100644
--- a/data/00-primary.seat
+++ b/data/00-primary.seat
@@ -1,5 +1,26 @@
[Seat Entry]
Version=1.0
Name=Primary seat
+# Specified Seat ID, if this value is NULL, ConsoleKit will decide one.
+# The ID only contain the ASICC characters "[A-Z][a-z][0-9]_"
+ID=StaticSeat1
+Description=start one static local display at :0
+
+# Indicate whether to create this seat or not. If it is set true, then CK will
+# not create this seat. Default value is false.
Hidden=false
-Devices=
\ No newline at end of file
+
+# Indicate input/output devices including keyboard-pointer-video
+# card-monitor-sound-usb devices,
+# This key will not implemented now, it might need be divided into
+# several keys in the future:
+# Pointer=
+# Monitor=
+# VideoCard=
+# Monitor=
+# UsbHub=
+Devices=
+
+# List of sessions to start on the seat, separated by ';'
+# Each session is defined in sessions.d/
+Sessions=Local;
diff --git a/data/ConsoleKit.conf b/data/ConsoleKit.conf
index 948f95f..8cf490a 100644
--- a/data/ConsoleKit.conf
+++ b/data/ConsoleKit.conf
@@ -44,6 +44,9 @@
send_member="CloseSession"/>
+
+
+
+
+
+
+
+
+
-
+
diff --git a/data/Makefile.am b/data/Makefile.am
index 041b431..2054e96 100644
--- a/data/Makefile.am
+++ b/data/Makefile.am
@@ -1,5 +1,10 @@
NULL =
+SUBDIRS = \
+ displays.d \
+ sessions.d \
+ $(NULL)
+
dbusconfdir = $(DBUS_SYS_DIR)
dbusconf_DATA = ConsoleKit.conf
diff --git a/data/displays.d/Headless.display.in b/data/displays.d/Headless.display.in
new file mode 100644
index 0000000..754d2bf
--- /dev/null
+++ b/data/displays.d/Headless.display.in
@@ -0,0 +1,5 @@
+[Display]
+Type=X11
+
+[X11]
+Exec=@X11_DIR@/Xvfb $display -auth $auth
diff --git a/data/displays.d/Local.display.in b/data/displays.d/Local.display.in
new file mode 100644
index 0000000..b845a7b
--- /dev/null
+++ b/data/displays.d/Local.display.in
@@ -0,0 +1,5 @@
+[Display]
+Type=X11
+
+[X11]
+Exec=@X11_DIR@/Xorg $display -br -verbose -auth $auth -nolisten tcp $vt
diff --git a/data/displays.d/LocalVNC.display.in b/data/displays.d/LocalVNC.display.in
new file mode 100644
index 0000000..6ad336b
--- /dev/null
+++ b/data/displays.d/LocalVNC.display.in
@@ -0,0 +1,5 @@
+[Display]
+Type=X11
+
+[X11]
+Exec=@X11_DIR@/Xvnc $display -auth $auth -query localhost
diff --git a/data/displays.d/Makefile.am b/data/displays.d/Makefile.am
new file mode 100644
index 0000000..1fab1d2
--- /dev/null
+++ b/data/displays.d/Makefile.am
@@ -0,0 +1,29 @@
+NULL =
+
+displaydir = $(sysconfdir)/ConsoleKit/displays.d
+display_in_files = \
+ Local.display.in \
+ RemoteMachine.display.in \
+ LocalVNC.display.in \
+ Headless.display.in
+
+display_DATA = $(display_in_files:.display.in=.display)
+
+Local.display: Local.display.in Makefile
+ sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
+RemoteMachine.display: RemoteMachine.display.in Makefile
+ sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
+LocalVNC.display: LocalVNC.display.in Makefile
+ sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
+Headless.display: Headless.display.in Makefile
+ sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
+
+EXTRA_DIST = \
+ $(display_in_files) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+
+CLEANFILES = $(display_DATA)
diff --git a/data/displays.d/RemoteMachine.display.in b/data/displays.d/RemoteMachine.display.in
new file mode 100644
index 0000000..7c69451
--- /dev/null
+++ b/data/displays.d/RemoteMachine.display.in
@@ -0,0 +1,5 @@
+[Display]
+Type=X11
+
+[X11]
+Exec=@X11_DIR@/Xorg $display -br -verbose -auth $auth -indirect $vt
diff --git a/data/sessions.d/Headless.session b/data/sessions.d/Headless.session
new file mode 100644
index 0000000..d376af9
--- /dev/null
+++ b/data/sessions.d/Headless.session
@@ -0,0 +1,8 @@
+[Session Entry]
+Name=Headless
+Type=LoginWindow
+Description=Login Window running on headless display
+DisplayTemplate=Headless
+
+[Headless]
+display=:32
diff --git a/data/sessions.d/Local.session b/data/sessions.d/Local.session
new file mode 100644
index 0000000..9d3b975
--- /dev/null
+++ b/data/sessions.d/Local.session
@@ -0,0 +1,9 @@
+[Session Entry]
+Name=Local
+Type=LoginWindow
+Description=Local Login Screen
+DisplayTemplate=Local
+
+[Local]
+display=:0
+vt=vt1
diff --git a/data/sessions.d/LocalVNC.session b/data/sessions.d/LocalVNC.session
new file mode 100644
index 0000000..c05802f
--- /dev/null
+++ b/data/sessions.d/LocalVNC.session
@@ -0,0 +1,8 @@
+[Session Entry]
+Name=LocalVNC
+Type=LoginWindow
+Description=Connect to local VNC server running on same machine
+DisplayTemplate=LocalVNC
+
+[LocalVNC]
+display=:64
diff --git a/data/sessions.d/Makefile.am b/data/sessions.d/Makefile.am
new file mode 100644
index 0000000..f17ffdc
--- /dev/null
+++ b/data/sessions.d/Makefile.am
@@ -0,0 +1,16 @@
+NULL =
+
+sessiondir = $(sysconfdir)/ConsoleKit/sessions.d
+session_DATA = \
+ Headless.session \
+ Local.session \
+ LocalVNC.session \
+ Remote.session
+
+EXTRA_DIST = \
+ $(session_DATA) \
+ $(NULL)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
diff --git a/data/sessions.d/Remote.session b/data/sessions.d/Remote.session
new file mode 100644
index 0000000..e88f975
--- /dev/null
+++ b/data/sessions.d/Remote.session
@@ -0,0 +1,9 @@
+[Session Entry]
+Name=Remote Chooser
+Type=Remote
+Description=Connect to chooser on nearby remote machine
+DisplayTemplate=RemoteMachine
+
+[RemoteMachine]
+display=:96
+vt=vt10
diff --git a/doc/dbus/ck-terms.xml b/doc/dbus/ck-terms.xml
index d3d544d..1b43ca6 100644
--- a/doc/dbus/ck-terms.xml
+++ b/doc/dbus/ck-terms.xml
@@ -64,4 +64,11 @@ True, hardware, multi-seat capabilities will be added in a later release.
+
+ Seat manager
+
+The seat manager is the process responsible for starting and stopping sessions on a seat.
+
+
+
diff --git a/libck-connector/ck-connector.c b/libck-connector/ck-connector.c
index 7f6f87f..87a7d4a 100644
--- a/libck-connector/ck-connector.c
+++ b/libck-connector/ck-connector.c
@@ -76,8 +76,11 @@ static struct {
{ "display-device", DBUS_TYPE_STRING },
{ "x11-display-device", DBUS_TYPE_STRING },
{ "x11-display", DBUS_TYPE_STRING },
+ { "seat-id", DBUS_TYPE_STRING },
+ { "session", DBUS_TYPE_STRING },
{ "remote-host-name", DBUS_TYPE_STRING },
{ "session-type", DBUS_TYPE_STRING },
+ { "display-type", DBUS_TYPE_STRING },
{ "is-local", DBUS_TYPE_BOOLEAN },
{ "unix-user", DBUS_TYPE_INT32 },
};
diff --git a/src/Makefile.am b/src/Makefile.am
index 6ab05c8..97a59ef 100644
--- a/src/Makefile.am
+++ b/src/Makefile.am
@@ -107,6 +107,8 @@ console_kit_daemon_SOURCES = \
ck-file-monitor.h \
ck-job.h \
ck-job.c \
+ ck-display-template.h \
+ ck-display-template.c \
ck-seat.h \
ck-seat.c \
ck-session-leader.h \
@@ -122,6 +124,13 @@ console_kit_daemon_SOURCES = \
$(BUILT_SOURCES) \
$(NULL)
+if USE_SELF_STRVERSCMP
+console_kit_daemon_SOURCES += \
+ strverscmp.c \
+ strverscmp.h \
+ $(NULL)
+endif
+
if ENABLE_INOTIFY
FILE_MONITOR_BACKEND = ck-file-monitor-inotify.c
else
diff --git a/src/ck-display-template.c b/src/ck-display-template.c
new file mode 100644
index 0000000..9206103
--- /dev/null
+++ b/src/ck-display-template.c
@@ -0,0 +1,341 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Authors: halton.huo@sun.com, Ray Strode
+ * Copyright (C) 2009 Sun Microsystems, Inc.
+ * Red Hat, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+
+#include "ck-display-template.h"
+
+#define CK_DISPLAY_TEMPLATE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplatePrivate))
+
+#define CK_DISPLAY_TEMPLATES_DIR SYSCONFDIR "/ConsoleKit/displays.d"
+
+struct CkDisplayTemplatePrivate
+{
+ char *name;
+ char *type;
+ GHashTable *parameters;
+};
+
+enum {
+ PROP_0,
+ PROP_NAME,
+ PROP_TYPE,
+ PROP_PARAMETERS,
+};
+
+static void ck_display_template_class_init (CkDisplayTemplateClass *klass);
+static void ck_display_template_init (CkDisplayTemplate *display);
+static void ck_display_template_finalize (GObject *object);
+static gboolean ck_display_template_load (CkDisplayTemplate *display);
+
+static GHashTable *ck_display_templates;
+
+G_DEFINE_TYPE (CkDisplayTemplate, ck_display_template, G_TYPE_OBJECT)
+
+static void
+_ck_display_template_set_name (CkDisplayTemplate *display,
+ const char *name)
+{
+ g_free (display->priv->name);
+ display->priv->name = g_strdup (name);
+}
+
+static void
+_ck_display_template_set_type_string (CkDisplayTemplate *display,
+ const char *type)
+{
+ g_free (display->priv->type);
+ display->priv->type = g_strdup (type);
+}
+
+static void
+_ck_display_template_set_parameters (CkDisplayTemplate *display,
+ GHashTable *parameters)
+{
+ if (display->priv->parameters != NULL) {
+ g_hash_table_unref (display->priv->parameters);
+ }
+
+ if (parameters == NULL) {
+ display->priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+ } else {
+ display->priv->parameters = g_hash_table_ref (parameters);
+ }
+}
+
+static void
+ck_display_template_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CkDisplayTemplate *self;
+
+ self = CK_DISPLAY_TEMPLATE (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ _ck_display_template_set_name (self, g_value_get_string (value));
+ break;
+ case PROP_TYPE:
+ _ck_display_template_set_type_string (self, g_value_get_string (value));
+ break;
+ case PROP_PARAMETERS:
+ _ck_display_template_set_parameters (self, g_value_get_boxed (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ck_display_template_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CkDisplayTemplate *self;
+
+ self = CK_DISPLAY_TEMPLATE (object);
+
+ switch (prop_id) {
+ case PROP_NAME:
+ g_value_set_string (value, self->priv->name);
+ break;
+ case PROP_TYPE:
+ g_value_set_string (value, self->priv->type);
+ break;
+ case PROP_PARAMETERS:
+ g_value_set_boxed (value, self->priv->parameters);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ck_display_template_class_init (CkDisplayTemplateClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = ck_display_template_get_property;
+ object_class->set_property = ck_display_template_set_property;
+ object_class->finalize = ck_display_template_finalize;
+
+ g_object_class_install_property (object_class,
+ PROP_NAME,
+ g_param_spec_string ("name",
+ "display type name",
+ "display type name",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_TYPE,
+ g_param_spec_string ("type",
+ "type",
+ "Type",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_PARAMETERS,
+ g_param_spec_boxed ("parameters",
+ "Parameters",
+ "Parameters",
+ G_TYPE_HASH_TABLE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_type_class_add_private (klass, sizeof (CkDisplayTemplatePrivate));
+}
+
+static void
+ck_display_template_init (CkDisplayTemplate *display)
+{
+ display->priv = CK_DISPLAY_TEMPLATE_GET_PRIVATE (display);
+
+ display->priv->name = NULL;
+ display->priv->type = NULL;
+ display->priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+}
+
+static void
+ck_display_template_finalize (GObject *object)
+{
+ CkDisplayTemplate *display;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CK_IS_DISPLAY_TEMPLATE (object));
+
+ display = CK_DISPLAY_TEMPLATE (object);
+
+ g_return_if_fail (display->priv != NULL);
+
+ g_free (display->priv->name);
+ g_free (display->priv->type);
+ g_hash_table_unref (display->priv->parameters);
+
+ G_OBJECT_CLASS (ck_display_template_parent_class)->finalize (object);
+}
+
+static gboolean
+ck_display_template_load (CkDisplayTemplate *display)
+{
+ GKeyFile *key_file;
+ const char *name;
+ char *group;
+ char *filename;
+ gboolean hidden;
+ char *type;
+ gboolean res;
+ GError *error;
+ char **type_keys;
+ GHashTable *parameters;
+
+ name = ck_display_template_get_name (display);
+
+ g_return_val_if_fail (name && !g_str_equal (name, ""), FALSE);
+
+ filename = g_strdup_printf ("%s/%s.display", CK_DISPLAY_TEMPLATES_DIR, name);
+
+ key_file = g_key_file_new ();
+
+ error = NULL;
+ res = g_key_file_load_from_file (key_file,
+ filename,
+ G_KEY_FILE_NONE,
+ &error);
+ if (! res) {
+ g_warning ("Unable to load display from file %s: %s", filename, error->message);
+ g_error_free (error);
+ return FALSE;
+ }
+ g_free (filename);
+
+ group = g_key_file_get_start_group (key_file);
+
+ if (group == NULL || strcmp (group, "Display") != 0) {
+ g_warning ("Not a display type file: %s", filename);
+ g_free (group);
+ g_key_file_free (key_file);
+ return FALSE;
+ }
+
+ hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL);
+
+ type = g_key_file_get_string (key_file, group, "Type", NULL);
+
+ if (type == NULL) {
+ g_warning ("Unable to read type from display file");
+ g_free (group);
+ g_key_file_free (key_file);
+ return FALSE;
+ }
+
+ display->priv->type = type;
+
+ parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+
+ type_keys = g_key_file_get_keys (key_file, type, NULL, NULL);
+
+ if (type_keys != NULL) {
+ int i;
+ for (i = 0; type_keys[i] != NULL; i++) {
+ char *string;
+
+ string = g_key_file_get_string (key_file, type, type_keys[i], NULL);
+ g_hash_table_insert (parameters, g_strdup (type_keys[i]), string);
+ }
+ g_strfreev (type_keys);
+ }
+
+ _ck_display_template_set_parameters (display, parameters);
+ g_hash_table_unref (parameters);
+
+ g_free (group);
+ g_key_file_free (key_file);
+ return TRUE;
+}
+
+CkDisplayTemplate *
+ck_display_template_get_from_name (const char *name)
+{
+ CkDisplayTemplate *display_template;
+
+ if (ck_display_templates == NULL) {
+ ck_display_templates = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_object_unref);
+ }
+
+ display_template = g_hash_table_lookup (ck_display_templates, name);
+
+ if (display_template == NULL) {
+ GObject *object;
+
+ object = g_object_new (CK_TYPE_DISPLAY_TEMPLATE,
+ "name", name,
+ NULL);
+
+ if (!ck_display_template_load (CK_DISPLAY_TEMPLATE (object))) {
+ g_object_unref (object);
+ return NULL;
+ }
+
+ g_hash_table_insert (ck_display_templates, g_strdup (name), object);
+ display_template = CK_DISPLAY_TEMPLATE (object);
+ }
+
+ return g_object_ref (display_template);
+}
+
+G_CONST_RETURN char*
+ck_display_template_get_name (CkDisplayTemplate *display)
+{
+ g_return_val_if_fail (CK_IS_DISPLAY_TEMPLATE (display), NULL);
+
+ return display->priv->name;
+}
+
+G_CONST_RETURN char *
+ck_display_template_get_type_string (CkDisplayTemplate *display)
+{
+ return display->priv->type;
+}
+
+GHashTable *
+ck_display_template_get_parameters (CkDisplayTemplate *display)
+{
+ g_return_val_if_fail (CK_IS_DISPLAY_TEMPLATE (display), NULL);
+
+ return g_hash_table_ref (display->priv->parameters);
+}
+
diff --git a/src/ck-display-template.h b/src/ck-display-template.h
new file mode 100644
index 0000000..fa74e67
--- /dev/null
+++ b/src/ck-display-template.h
@@ -0,0 +1,57 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Authors: halton.huo@sun.com
+ * Copyright (C) 2009 Sun Microsystems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program 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 General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+ *
+ */
+
+#ifndef __CK_DISPLAY_TEMPLATE_H
+#define __CK_DISPLAY_TEMPLATE_H
+
+#include
+
+G_BEGIN_DECLS
+
+#define CK_TYPE_DISPLAY_TEMPLATE (ck_display_template_get_type ())
+#define CK_DISPLAY_TEMPLATE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplate))
+#define CK_DISPLAY_TEMPLATE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplateClass))
+#define CK_IS_DISPLAY_TEMPLATE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_DISPLAY_TEMPLATE))
+#define CK_IS_DISPLAY_TEMPLATE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_DISPLAY_TEMPLATE))
+#define CK_DISPLAY_TEMPLATE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplateClass))
+
+typedef struct CkDisplayTemplatePrivate CkDisplayTemplatePrivate;
+
+typedef struct
+{
+ GObject parent;
+ CkDisplayTemplatePrivate *priv;
+} CkDisplayTemplate;
+
+typedef struct
+{
+ GObjectClass parent_class;
+} CkDisplayTemplateClass;
+
+GType ck_display_template_get_type (void);
+CkDisplayTemplate * ck_display_template_get_from_name (const char *name);
+G_CONST_RETURN char * ck_display_template_get_name (CkDisplayTemplate *display);
+G_CONST_RETURN char * ck_display_template_get_type_string (CkDisplayTemplate *display);
+GHashTable * ck_display_template_get_parameters (CkDisplayTemplate *display);
+
+G_END_DECLS
+
+#endif /* __CK_DISPLAY_TEMPLATE_H */
diff --git a/src/ck-log-event.c b/src/ck-log-event.c
index 66f439c..d13a0f8 100644
--- a/src/ck-log-event.c
+++ b/src/ck-log-event.c
@@ -79,6 +79,8 @@ event_seat_session_added_free (CkLogSeat
event->session_id = NULL;
g_free (event->session_type);
event->session_type = NULL;
+ g_free (event->display_type);
+ event->display_type = NULL;
g_free (event->session_x11_display);
event->session_x11_display = NULL;
g_free (event->session_x11_display_device);
@@ -103,6 +105,8 @@ event_seat_session_removed_free (CkLogSe
event->session_id = NULL;
g_free (event->session_type);
event->session_type = NULL;
+ g_free (event->display_type);
+ event->display_type = NULL;
g_free (event->session_x11_display);
event->session_x11_display = NULL;
g_free (event->session_x11_display_device);
@@ -213,6 +217,7 @@ event_seat_session_added_copy (CkLogSeat
event_copy->seat_id = g_strdup (event->seat_id);
event_copy->session_id = g_strdup (event->session_id);
event_copy->session_type = g_strdup (event->session_type);
+ event_copy->display_type = g_strdup (event->display_type);
event_copy->session_x11_display = g_strdup (event->session_x11_display);
event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device);
event_copy->session_display_device = g_strdup (event->session_display_device);
@@ -232,6 +237,7 @@ event_seat_session_removed_copy (CkLogSe
event_copy->seat_id = g_strdup (event->seat_id);
event_copy->session_id = g_strdup (event->session_id);
event_copy->session_type = g_strdup (event->session_type);
+ event_copy->display_type = g_strdup (event->display_type);
event_copy->session_x11_display = g_strdup (event->session_x11_display);
event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device);
event_copy->session_display_device = g_strdup (event->session_display_device);
@@ -415,10 +421,11 @@ add_log_for_seat_session_added (GString
e = (CkLogSeatSessionAddedEvent *)event;
g_string_append_printf (str,
- "seat-id='%s' session-id='%s' session-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
+ "seat-id='%s' session-id='%s' session-type='%s' display-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
e->seat_id ? e->seat_id : "",
e->session_id ? e->session_id : "",
e->session_type ? e->session_type : "",
+ e->display_type ? e->display_type : "",
e->session_x11_display ? e->session_x11_display : "",
e->session_x11_display_device ? e->session_x11_display_device : "",
e->session_display_device ? e->session_display_device : "",
@@ -436,10 +443,11 @@ add_log_for_seat_session_removed (GStrin
e = (CkLogSeatSessionRemovedEvent *)event;
g_string_append_printf (str,
- "seat-id='%s' session-id='%s' session-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
+ "seat-id='%s' session-id='%s' session-type='%s' display-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
e->seat_id ? e->seat_id : "",
e->session_id ? e->session_id : "",
e->session_type ? e->session_type : "",
+ e->display_type ? e->display_type : "",
e->session_x11_display ? e->session_x11_display : "",
e->session_x11_display_device ? e->session_x11_display_device : "",
e->session_display_device ? e->session_display_device : "",
@@ -939,7 +947,7 @@ parse_log_for_seat_session_added (const
}
error = NULL;
- re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' session-id='(?P[a-zA-Z0-9/]+)' session-type='(?P[a-zA-Z0-9 ]*)' session-x11-display='(?P[0-9a-zA-Z.:]*)' session-x11-display-device='(?P[^']*)' session-display-device='(?P[^']*)' session-remote-host-name='(?P[^']*)' session-is-local=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error);
+ re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' session-id='(?P[a-zA-Z0-9/]+)' session-type='(?P[a-zA-Z0-9 ]*)' display-type='(?P[a-zA-Z0-9 ]*)' session-x11-display='(?P[0-9a-zA-Z.:]*)' session-x11-display-device='(?P[^']*)' session-display-device='(?P[^']*)' session-remote-host-name='(?P[^']*)' session-is-local=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error);
if (re == NULL) {
g_warning ("%s", error->message);
goto out;
@@ -957,6 +965,7 @@ parse_log_for_seat_session_added (const
e->seat_id = g_match_info_fetch_named (match_info, "seatid");
e->session_id = g_match_info_fetch_named (match_info, "sessionid");
e->session_type = g_match_info_fetch_named (match_info, "sessiontype");
+ e->display_type = g_match_info_fetch_named (match_info, "displaytype");
e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display");
e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice");
e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice");
@@ -1014,7 +1023,7 @@ parse_log_for_seat_session_removed (cons
}
error = NULL;
- re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' session-id='(?P[a-zA-Z0-9/]+)' session-type='(?P[a-zA-Z0-9 ]*)' session-x11-display='(?P[0-9a-zA-Z.:]*)' session-x11-display-device='(?P[^']*)' session-display-device='(?P[^']*)' session-remote-host-name='(?P[^']*)' session-is-local=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error);
+ re = g_regex_new ("seat-id='(?P[a-zA-Z0-9/]+)' session-id='(?P[a-zA-Z0-9/]+)' session-type='(?P[a-zA-Z0-9 ]*)' display-type='(?P[a-zA-Z0-9 ]*)' session-x11-display='(?P[0-9a-zA-Z.:]*)' session-x11-display-device='(?P[^']*)' session-display-device='(?P[^']*)' session-remote-host-name='(?P[^']*)' session-is-local=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error);
if (re == NULL) {
g_warning ("%s", error->message);
goto out;
@@ -1032,6 +1041,7 @@ parse_log_for_seat_session_removed (cons
e->seat_id = g_match_info_fetch_named (match_info, "seatid");
e->session_id = g_match_info_fetch_named (match_info, "sessionid");
e->session_type = g_match_info_fetch_named (match_info, "sessiontype");
+ e->display_type = g_match_info_fetch_named (match_info, "displaytype");
e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display");
e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice");
e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice");
diff --git a/src/ck-log-event.h b/src/ck-log-event.h
index 65571f0..2d4ed4e 100644
--- a/src/ck-log-event.h
+++ b/src/ck-log-event.h
@@ -68,6 +68,7 @@ typedef struct
{
char *seat_id;
int seat_kind;
+ char *seat_type;
} CkLogSeatAddedEvent;
typedef struct
@@ -81,11 +82,13 @@ typedef struct
char *seat_id;
char *session_id;
char *session_type;
+ char *display_type;
char *session_x11_display;
char *session_x11_display_device;
char *session_display_device;
char *session_remote_host_name;
gboolean session_is_local;
+ gboolean session_is_dynamic;
guint session_unix_user;
char *session_creation_time;
} CkLogSeatSessionAddedEvent;
@@ -95,11 +98,13 @@ typedef struct
char *seat_id;
char *session_id;
char *session_type;
+ char *display_type;
char *session_x11_display;
char *session_x11_display_device;
char *session_display_device;
char *session_remote_host_name;
gboolean session_is_local;
+ gboolean session_is_dynamic;
guint session_unix_user;
char *session_creation_time;
} CkLogSeatSessionRemovedEvent;
--- ConsoleKit-0.4.1/src/ck-manager.c.orig 2010-09-06 11:20:51.908499864 +0800
+++ ConsoleKit-0.4.1/src/ck-manager.c 2010-09-06 11:20:56.996728793 +0800
@@ -46,9 +46,14 @@
#include
#endif
+#ifndef HAVE_STRVERSCMP
+#include "strverscmp.h"
+#endif
+
#include "ck-manager.h"
#include "ck-manager-glue.h"
#include "ck-seat.h"
+#include "ck-display-template.h"
#include "ck-session-leader.h"
#include "ck-session.h"
#include "ck-marshal.h"
@@ -58,12 +63,19 @@
#define CK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_MANAGER, CkManagerPrivate))
+#define CK_TYPE_PARAMETER_STRUCT (dbus_g_type_get_struct ("GValueArray", \
+ G_TYPE_STRING, \
+ G_TYPE_VALUE, \
+ G_TYPE_INVALID))
+
#define CK_SEAT_DIR SYSCONFDIR "/ConsoleKit/seats.d"
#define LOG_FILE LOCALSTATEDIR "/log/ConsoleKit/history"
#define CK_DBUS_PATH "/org/freedesktop/ConsoleKit"
#define CK_MANAGER_DBUS_PATH CK_DBUS_PATH "/Manager"
#define CK_MANAGER_DBUS_NAME "org.freedesktop.ConsoleKit.Manager"
+#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
+
struct CkManagerPrivate
{
#ifdef HAVE_POLKIT
@@ -392,6 +404,7 @@ log_seat_added_event (CkManager *manage
GError *error;
char *sid;
CkSeatKind seat_kind;
+ char *seat_type;
memset (&event, 0, sizeof (CkLogEvent));
@@ -401,9 +414,11 @@ log_seat_added_event (CkManager *manage
sid = NULL;
ck_seat_get_id (seat, &sid, NULL);
ck_seat_get_kind (seat, &seat_kind, NULL);
+ ck_seat_get_type_string (seat, &seat_type, NULL);
event.event.seat_added.seat_id = (char *)get_object_id_basename (sid);
event.event.seat_added.seat_kind = (int)seat_kind;
+ event.event.seat_added.seat_type = (char *)seat_type;
error = NULL;
res = ck_event_logger_queue_event (manager->priv->logger, &event, &error);
@@ -413,6 +428,7 @@ log_seat_added_event (CkManager *manage
}
g_free (sid);
+ g_free (seat_type);
}
static void
@@ -517,6 +533,7 @@ log_seat_session_added_event (CkManager
if (session != NULL) {
g_object_get (session,
"session-type", &event.event.seat_session_added.session_type,
+ "display-type", &event.event.seat_session_added.display_type,
"x11-display", &event.event.seat_session_added.session_x11_display,
"x11-display-device", &event.event.seat_session_added.session_x11_display_device,
"display-device", &event.event.seat_session_added.session_display_device,
@@ -572,6 +589,7 @@ log_seat_session_removed_event (CkManage
if (session != NULL) {
g_object_get (session,
"session-type", &event.event.seat_session_removed.session_type,
+ "display-type", &event.event.seat_session_removed.display_type,
"x11-display", &event.event.seat_session_removed.session_x11_display,
"x11-display-device", &event.event.seat_session_removed.session_x11_display_device,
"display-device", &event.event.seat_session_removed.session_display_device,
@@ -1330,15 +1348,21 @@ disconnect_seat_signals (CkManager *mana
}
static CkSeat *
-add_new_seat (CkManager *manager,
- CkSeatKind kind)
+add_new_seat (CkManager *manager,
+ const char *give_sid,
+ CkSeatKind kind,
+ const char *type)
{
char *sid;
CkSeat *seat;
- sid = generate_seat_id (manager);
+ if (IS_STR_SET (give_sid)) {
+ sid = g_strdup (give_sid);
+ } else {
+ sid = generate_seat_id (manager);
+ }
- seat = ck_seat_new (sid, kind);
+ seat = ck_seat_new (sid, kind, type);
/* First we connect our own signals to the seat, followed by
* the D-Bus signal hookup to make sure we can first dump the
@@ -1363,7 +1387,7 @@ add_new_seat (CkManager *manager,
ck_seat_run_programs (seat, NULL, NULL, "seat_added");
g_debug ("Emitting seat-added: %s", sid);
- g_signal_emit (manager, signals [SEAT_ADDED], 0, sid);
+ g_signal_emit (manager, signals [SEAT_ADDED], 0, sid, type);
log_seat_added_event (manager, seat);
@@ -1421,64 +1445,22 @@ remove_seat (CkManager *manager,
g_free (sid);
}
-#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
-
static CkSeat *
find_seat_for_session (CkManager *manager,
CkSession *session)
{
CkSeat *seat;
- gboolean is_static_x11;
- gboolean is_static_text;
- char *display_device;
- char *x11_display_device;
- char *x11_display;
- char *remote_host_name;
- gboolean is_local;
-
- is_static_text = FALSE;
- is_static_x11 = FALSE;
-
- seat = NULL;
- display_device = NULL;
- x11_display_device = NULL;
- x11_display = NULL;
- remote_host_name = NULL;
- is_local = FALSE;
-
- /* FIXME: use matching to group entries? */
-
- ck_session_get_display_device (session, &display_device, NULL);
- ck_session_get_x11_display_device (session, &x11_display_device, NULL);
- ck_session_get_x11_display (session, &x11_display, NULL);
- ck_session_get_remote_host_name (session, &remote_host_name, NULL);
- ck_session_is_local (session, &is_local, NULL);
-
- if (IS_STR_SET (x11_display)
- && IS_STR_SET (x11_display_device)
- && ! IS_STR_SET (remote_host_name)
- && is_local == TRUE) {
- is_static_x11 = TRUE;
- } else if (! IS_STR_SET (x11_display)
- && ! IS_STR_SET (x11_display_device)
- && IS_STR_SET (display_device)
- && ! IS_STR_SET (remote_host_name)
- && is_local == TRUE) {
- is_static_text = TRUE;
- }
+ char *sid = NULL;
+
+ ck_session_get_seat_id (session, &sid, NULL);
- if (is_static_x11 || is_static_text) {
- char *sid;
+ if (! IS_STR_SET (sid)) {
sid = g_strdup_printf ("%s/Seat%u", CK_DBUS_PATH, 1);
- seat = g_hash_table_lookup (manager->priv->seats, sid);
- g_free (sid);
}
- g_free (display_device);
- g_free (x11_display_device);
- g_free (x11_display);
- g_free (remote_host_name);
+ seat = g_hash_table_lookup (manager->priv->seats, sid);
+ g_free (sid);
return seat;
}
@@ -1613,36 +1595,49 @@ open_session_for_leader (CkManager
CkSession *session;
CkSeat *seat;
const char *ssid;
+ char *sid;
const char *cookie;
ssid = ck_session_leader_peek_session_id (leader);
cookie = ck_session_leader_peek_cookie (leader);
- session = ck_session_new_with_parameters (ssid,
- cookie,
- parameters);
+ session = g_hash_table_lookup (manager->priv->sessions, ssid);
if (session == NULL) {
- GError *error;
- g_debug ("Unable to create new session");
- error = g_error_new (CK_MANAGER_ERROR,
- CK_MANAGER_ERROR_GENERAL,
- "Unable to create new session");
- dbus_g_method_return_error (context, error);
- g_error_free (error);
+ session = ck_session_new_with_parameters (ssid,
+ parameters);
- return;
+ if (session == NULL) {
+ GError *error;
+ g_debug ("Unable to create new session");
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ "Unable to create new session");
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return;
+ }
+
+ g_hash_table_insert (manager->priv->sessions,
+ g_strdup (ssid),
+ g_object_ref (session));
+
+ } else {
+ ck_session_set_parameters (session, parameters);
}
- g_hash_table_insert (manager->priv->sessions,
- g_strdup (ssid),
- g_object_ref (session));
+ ck_session_set_cookie (session, cookie, NULL);
+ ck_session_set_is_open (session, TRUE, NULL);
/* Add to seat */
seat = find_seat_for_session (manager, session);
if (seat == NULL) {
+ sid = NULL;
+ ck_session_get_seat_id (session, &sid, NULL);
/* create a new seat */
- seat = add_new_seat (manager, CK_SEAT_KIND_DYNAMIC);
+ seat = add_new_seat (manager, sid, CK_SEAT_KIND_DYNAMIC, "Default");
+ g_free (sid);
}
ck_seat_add_session (seat, session, NULL);
@@ -1878,11 +1873,57 @@ generate_session_for_leader (CkManager
}
}
+static char *
+check_parameters_for_ssid (const GPtrArray *parameters)
+{
+ int i;
+
+ if (parameters == NULL) {
+ return NULL;
+ }
+
+ for (i = 0; i < parameters->len; i++) {
+ GValue val_struct = { 0, };
+ char *prop_name;
+ gboolean res;
+
+ g_value_init (&val_struct, CK_TYPE_PARAMETER_STRUCT);
+ g_value_set_static_boxed (&val_struct, g_ptr_array_index (parameters, i));
+
+ res = dbus_g_type_struct_get (&val_struct,
+ 0, &prop_name,
+ G_MAXUINT);
+ if (! res) {
+ g_debug ("Unable to read parameter name");
+ continue;
+ }
+
+ if (prop_name != NULL && strcmp (prop_name, "session") == 0) {
+ GValue prop_val = { 0, };
+ GValue *session_val;
+
+ g_value_init (&prop_val, G_TYPE_VALUE);
+ res = dbus_g_type_struct_get_member (&val_struct, 1, &prop_val);
+
+ if (! res) {
+ g_debug ("Unable to read parameter value");
+ continue;
+ }
+
+ session_val = g_value_get_boxed (&prop_val);
+
+ return g_value_dup_string (session_val);
+ }
+ }
+
+ return NULL;
+}
+
static gboolean
-create_session_for_sender (CkManager *manager,
- const char *sender,
- const GPtrArray *parameters,
- DBusGMethodInvocation *context)
+open_session_for_sender (CkManager *manager,
+ const char *sender,
+ const GPtrArray *parameters,
+ DBusGMethodInvocation *context)
{
pid_t pid;
uid_t uid;
@@ -1890,6 +1931,7 @@ create_session_for_sender (CkManager
char *cookie;
char *ssid;
CkSessionLeader *leader;
+ CkSession *session;
g_debug ("CkManager: create session for sender: %s", sender);
@@ -1908,9 +1950,21 @@ create_session_for_sender (CkManager
}
cookie = generate_session_cookie (manager);
- ssid = generate_session_id (manager);
- g_debug ("Creating new session ssid: %s", ssid);
+ ssid = check_parameters_for_ssid (parameters);
+
+ if (IS_STR_SET (ssid)) {
+ session = g_hash_table_lookup (manager->priv->sessions, ssid);
+
+ /* FIXME: Need to verify that the session belongs to a seat
+ * managed by the sender
+ */
+ g_debug ("Managing existing session ssid: %s", ssid);
+ } else {
+ ssid = generate_session_id (manager);
+ session = NULL;
+ g_debug ("Creating new session ssid: %s", ssid);
+ }
leader = ck_session_leader_new ();
ck_session_leader_set_uid (leader, uid);
@@ -2149,7 +2203,7 @@ ck_manager_open_session (CkManager
gboolean ret;
sender = dbus_g_method_get_sender (context);
- ret = create_session_for_sender (manager, sender, NULL, context);
+ ret = open_session_for_sender (manager, sender, NULL, context);
g_free (sender);
return ret;
@@ -2164,7 +2218,7 @@ ck_manager_open_session_with_parameters
gboolean ret;
sender = dbus_g_method_get_sender (context);
- ret = create_session_for_sender (manager, sender, parameters, context);
+ ret = open_session_for_sender (manager, sender, parameters, context);
g_free (sender);
return ret;
@@ -2181,10 +2235,12 @@ remove_session_for_cookie (CkManager *m
char *sid;
gboolean res;
gboolean ret;
+ gboolean should_remove_session;
ret = FALSE;
orig_ssid = NULL;
orig_session = NULL;
+ should_remove_session = FALSE;
g_debug ("Removing session for cookie: %s", cookie);
@@ -2211,6 +2267,17 @@ remove_session_for_cookie (CkManager *m
goto out;
}
+ ck_session_set_is_open (orig_session, FALSE, NULL);
+ ck_session_set_cookie (orig_session, NULL, NULL);
+ ck_session_set_active (orig_session, FALSE, NULL);
+ ck_session_set_unix_user (orig_session, 0, NULL);
+ ck_session_set_x11_display (orig_session, NULL, NULL);
+ ck_session_set_x11_display_device (orig_session, NULL, NULL);
+ ck_session_set_display_device (orig_session, NULL, NULL);
+ ck_session_set_login_session_id (orig_session, NULL, NULL);
+ ck_session_set_remote_host_name (orig_session, NULL, NULL);
+ ck_session_set_under_request (orig_session, FALSE, NULL);
+
/* Must keep a reference to the session in the manager until
* all events for seats are cleared. So don't remove
* or steal the session from the master list until
@@ -2218,31 +2285,32 @@ remove_session_for_cookie (CkManager *m
* for seat removals doesn't work.
*/
- /* remove from seat */
- sid = NULL;
- ck_session_get_seat_id (orig_session, &sid, NULL);
- if (sid != NULL) {
- CkSeat *seat;
- seat = g_hash_table_lookup (manager->priv->seats, sid);
- if (seat != NULL) {
- CkSeatKind kind;
-
- ck_seat_remove_session (seat, orig_session, NULL);
-
- kind = CK_SEAT_KIND_STATIC;
- /* if dynamic seat has no sessions then remove it */
- ck_seat_get_kind (seat, &kind, NULL);
- if (kind == CK_SEAT_KIND_DYNAMIC) {
- remove_seat (manager, seat);
+ ck_session_get_remove_on_close (orig_session, &should_remove_session, NULL);
+
+ if (should_remove_session) {
+ /* remove from seat */
+ sid = NULL;
+ ck_session_get_seat_id (orig_session, &sid, NULL);
+ if (sid != NULL) {
+ CkSeat *seat;
+ seat = g_hash_table_lookup (manager->priv->seats, sid);
+ if (seat != NULL) {
+ CkSeatKind kind;
+
+ ck_seat_remove_session (seat, orig_session, NULL);
+
+ kind = CK_SEAT_KIND_STATIC;
+ /* if dynamic seat has no sessions then remove it */
+ ck_seat_get_kind (seat, &kind, NULL);
}
}
- }
- g_free (sid);
+ g_free (sid);
- /* Remove the session from the list but don't call
- * unref until we are done with it */
- g_hash_table_steal (manager->priv->sessions,
- ck_session_leader_peek_session_id (leader));
+ /* Remove the session from the list but don't call
+ * unref until we are done with it */
+ g_hash_table_steal (manager->priv->sessions,
+ ck_session_leader_peek_session_id (leader));
+ }
ck_manager_dump (manager);
@@ -2250,11 +2318,13 @@ remove_session_for_cookie (CkManager *m
ret = TRUE;
out:
- if (orig_session != NULL) {
- g_object_unref (orig_session);
- }
- g_free (orig_ssid);
+ if (should_remove_session) {
+ if (orig_session != NULL) {
+ g_object_unref (orig_session);
+ }
+ g_free (orig_ssid);
+ }
return ret;
}
@@ -2472,9 +2542,11 @@ ck_manager_class_init (CkManagerClass *k
G_STRUCT_OFFSET (CkManagerClass, seat_added),
NULL,
NULL,
- g_cclosure_marshal_VOID__BOXED,
+ ck_marshal_VOID__STRING_STRING,
G_TYPE_NONE,
- 1, DBUS_TYPE_G_OBJECT_PATH);
+ 2,
+ G_TYPE_STRING,
+ G_TYPE_STRING);
signals [SEAT_REMOVED] =
g_signal_new ("seat-removed",
G_TYPE_FROM_CLASS (object_class),
@@ -2581,6 +2653,43 @@ ck_manager_get_seats (CkManager *manage
}
static void
+listify_unmanaged_seat_ids (char *id,
+ CkSeat *seat,
+ GPtrArray **array)
+{
+ if (ck_seat_is_managed (seat)) {
+ return;
+ }
+
+ g_ptr_array_add (*array, g_strdup (id));
+}
+
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.GetUnmanagedSeats
+*/
+gboolean
+ck_manager_get_unmanaged_seats (CkManager *manager,
+ GPtrArray **seats,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+ if (seats == NULL) {
+ return FALSE;
+ }
+
+ *seats = g_ptr_array_new ();
+ g_hash_table_foreach (manager->priv->seats, (GHFunc)listify_unmanaged_seat_ids, seats);
+
+ return TRUE;
+}
+
+static void
listify_session_ids (char *id,
CkSession *session,
GPtrArray **array)
@@ -2605,16 +2714,311 @@ ck_manager_get_sessions (CkManager *man
return TRUE;
}
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.AddSeat string:Default
+*/
+gboolean
+ck_manager_add_seat (CkManager *manager,
+ const char *type,
+ char **sid,
+ GError **error)
+{
+ CkSeat *seat;
+
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+ seat = add_new_seat (manager, NULL, CK_SEAT_KIND_DYNAMIC, type);
+
+ if (!ck_seat_get_id (seat, sid, error)) {
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.AddSeatById \
+ objpath:/org/freedesktop/ConsoleKit/SeatTest \
+*/
+gboolean
+ck_manager_add_seat_by_id (CkManager *manager,
+ const char *type,
+ const char *sid,
+ GError **error)
+{
+ CkSeat *seat;
+
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+ seat = add_new_seat (manager, sid, CK_SEAT_KIND_DYNAMIC, type);
+
+ return !(seat == NULL);
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.RemoveSeat \
+ obj:/org/freedesktop/ConsoleKit/Seat2
+*/
+gboolean
+ck_manager_remove_seat (CkManager *manager,
+ const char *sid,
+ DBusGMethodInvocation *context)
+{
+ CkSeat *seat = NULL;
+ CkSeatKind kind;
+
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+ seat = g_hash_table_lookup (manager->priv->seats, sid);
+
+ if (seat == NULL) {
+ GError *error;
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Seat '%s' doesn't exist"),
+ sid);
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ ck_seat_get_kind (seat, &kind, NULL);
+
+ if (kind == CK_SEAT_KIND_STATIC) {
+ GError *error;
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Seat '%s' is static and can't be removed"),
+ sid);
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ if (ck_seat_is_managed (seat)) {
+ ck_seat_request_removal (seat);
+ } else {
+ remove_seat (manager, seat);
+ }
+
+ return TRUE;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.AddSession \
+ objpath:/org/freedesktop/ConsoleKit/Seat2 \
+ string:"LoginWindow" \
+ dict:string:string:"vt","vt9","display",":123"
+*/
+gboolean
+ck_manager_add_session (CkManager *manager,
+ const char *sid,
+ const char *type,
+ const char *display_type,
+ GHashTable *variables,
+ DBusGMethodInvocation *context)
+{
+ CkSeat *seat;
+ CkSession *session;
+ char *ssid;
+
+ seat = g_hash_table_lookup (manager->priv->seats, sid);
+
+ if (seat == NULL) {
+ GError *error;
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Seat '%s' doesn't exist"),
+ sid);
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ ssid = generate_session_id (manager);
+
+ session = ck_session_new (ssid, type, display_type, variables);
+
+ if (session == NULL) {
+ GError *error;
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Session could not be added to seat '%s'"),
+ sid);
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ ck_session_set_seat_id (session, sid, NULL);
+ if (IS_STR_SET (type) && g_str_equal (type, "LoginWindow")) {
+ session_set_remove_on_close (session, FALSE, NULL);
+ } else {
+ session_set_remove_on_close (session, TRUE, NULL);
+ }
+
+ ck_seat_add_session (seat, session, NULL);
+
+ g_hash_table_insert (manager->priv->sessions,
+ ssid,
+ session);
+
+ dbus_g_method_return (context, ssid);
+ return TRUE;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.RemoveSession \
+ objpath:/org/freedesktop/ConsoleKit/Session2
+*/
+gboolean
+ck_manager_remove_session (CkManager *manager,
+ const char *ssid,
+ DBusGMethodInvocation *context)
+{
+ CkSession *session;
+ CkSeat *seat;
+ GError *error;
+ char *sid;
+ gboolean is_open;
+
+ session = g_hash_table_lookup (manager->priv->sessions, ssid);
+
+ if (session == NULL) {
+ GError *error;
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Session '%s' doesn't exist"),
+ ssid);
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ ck_session_get_seat_id (session, &sid, NULL);
+ seat = g_hash_table_lookup (manager->priv->seats, sid);
+ g_free (sid);
+
+ if (seat == NULL) {
+ g_warning ("Session '%s' is not associated with a seat", ssid);
+ g_hash_table_remove (manager->priv->sessions, ssid);
+ return TRUE;
+ }
+
+ error = NULL;
+
+ ck_session_is_open (session, &is_open, NULL);
+ session_set_remove_on_close (session, TRUE, NULL);
+
+ /* We'll let the seat manager close us when it's ready
+ */
+ if (ck_seat_is_managed (seat) && is_open) {
+ ck_seat_request_close_session (seat, session, NULL);
+ dbus_g_method_return (context);
+
+ return TRUE;
+ }
+
+ if (!ck_seat_remove_session (seat, session, &error)) {
+ if (error == NULL) {
+ return TRUE;
+ }
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ g_hash_table_remove (manager->priv->sessions, ssid);
+ dbus_g_method_return (context);
+ return TRUE;
+}
+
+static void
+add_sessions_from_seat (CkManager *manager,
+ CkSeat *seat)
+{
+ GPtrArray *sessions;
+ int i;
+
+ ck_seat_get_sessions (seat, &sessions, NULL);
+
+ for (i = 0; i < sessions->len; i++) {
+ char *ssid;
+ CkSession *session;
+
+ ssid = g_ptr_array_index (sessions, i);
+ session = ck_seat_get_session (seat, ssid);
+
+ g_hash_table_insert (manager->priv->sessions,
+ ssid,
+ session);
+ }
+
+ g_ptr_array_free (sessions, TRUE);
+}
+
static void
add_seat_for_file (CkManager *manager,
const char *filename)
{
char *sid;
+ char *orig_sid;
CkSeat *seat;
sid = generate_seat_id (manager);
+ orig_sid = g_strdup (sid);
+ seat = ck_seat_new_from_file (&sid, filename);
+
+ if (seat == NULL) {
+ /* returns null if connection to bus fails */
+ g_free (sid);
+ g_free (orig_sid);
+ manager->priv->seat_serial--;
+ return;
+ }
+
+ if (!g_str_equal (orig_sid, sid)) {
+ manager->priv->seat_serial--;
+ }
+ g_free (orig_sid);
- seat = ck_seat_new_from_file (sid, filename);
+ add_sessions_from_seat (manager, seat);
if (seat == NULL) {
return;
@@ -2637,7 +3041,7 @@ add_seat_for_file (CkManager *manager,
ck_seat_run_programs (seat, NULL, NULL, "seat_added");
g_debug ("Emitting seat-added: %s", sid);
- g_signal_emit (manager, signals [SEAT_ADDED], 0, sid);
+ g_signal_emit (manager, signals [SEAT_ADDED], 0, sid, "Default");
log_seat_added_event (manager, seat);
}
@@ -2648,6 +3052,7 @@ load_seats_from_dir (CkManager *manager)
GDir *d;
GError *error;
const char *file;
+ GQueue seat_queue;
error = NULL;
d = g_dir_open (CK_SEAT_DIR,
@@ -2659,17 +3064,26 @@ load_seats_from_dir (CkManager *manager)
return FALSE;
}
+ g_queue_init (&seat_queue);
while ((file = g_dir_read_name (d)) != NULL) {
if (g_str_has_suffix (file, ".seat")) {
char *path;
path = g_build_filename (CK_SEAT_DIR, file, NULL);
- add_seat_for_file (manager, path);
- g_free (path);
+ g_queue_push_tail (&seat_queue, path);
}
}
-
g_dir_close (d);
+ g_queue_sort (&seat_queue, (GCompareDataFunc) strverscmp, NULL);
+
+ while (!g_queue_is_empty (&seat_queue)) {
+ char *path;
+
+ path = g_queue_pop_head (&seat_queue);
+ add_seat_for_file (manager, path);
+ g_free (path);
+ }
+
return TRUE;
}
@@ -2705,8 +3119,6 @@ ck_manager_init (CkManager *manager)
(GDestroyNotify) g_object_unref);
manager->priv->logger = ck_event_logger_new (LOG_FILE);
-
- create_seats (manager);
}
static void
@@ -2751,6 +3163,8 @@ ck_manager_new (void)
g_object_unref (manager_object);
return NULL;
}
+
+ create_seats (CK_MANAGER (manager_object));
}
return CK_MANAGER (manager_object);
diff --git a/src/ck-manager.h b/src/ck-manager.h
index 4bd56e8..4304e71 100644
--- a/src/ck-manager.h
+++ b/src/ck-manager.h
@@ -49,7 +49,8 @@ typedef struct
GObjectClass parent_class;
void (* seat_added) (CkManager *manager,
- const char *sid);
+ const char *sid,
+ const char *type);
void (* seat_removed) (CkManager *manager,
const char *sid);
void (* system_idle_hint_changed) (CkManager *manager,
@@ -96,6 +97,9 @@ gboolean ck_manager_get_sessions (CkManager
gboolean ck_manager_get_seats (CkManager *manager,
GPtrArray **seats,
GError **error);
+gboolean ck_manager_get_unmanaged_seats (CkManager *manager,
+ GPtrArray **seats,
+ GError **error);
gboolean ck_manager_close_session (CkManager *manager,
const char *cookie,
DBusGMethodInvocation *context);
@@ -128,6 +132,28 @@ gboolean ck_manager_open_session_with_parameters (CkManager
const GPtrArray *parameters,
DBusGMethodInvocation *context);
+gboolean ck_manager_add_seat (CkManager *manager,
+ const char *type,
+ char **sid,
+ GError **error);
+gboolean ck_manager_add_seat_by_id (CkManager *manager,
+ const char *type,
+ const char *sid,
+ GError **error);
+gboolean ck_manager_remove_seat (CkManager *manager,
+ const char *sid,
+ DBusGMethodInvocation *context);
+
+gboolean ck_manager_add_session (CkManager *manager,
+ const char *sid,
+ const char *type,
+ const char *display_type,
+ GHashTable *parameters,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_remove_session (CkManager *manager,
+ const char *ssid,
+ DBusGMethodInvocation *context);
+
G_END_DECLS
#endif /* __CK_MANAGER_H */
diff --git a/src/ck-marshal.list b/src/ck-marshal.list
index 7f60efc..f8029a6 100644
--- a/src/ck-marshal.list
+++ b/src/ck-marshal.list
@@ -1,3 +1,6 @@
VOID:UINT,STRING
BOOLEAN:POINTER
VOID:OBJECT,OBJECT
+VOID:STRING,STRING
+VOID:STRING,BOOLEAN,STRING,POINTER,STRING,POINTER
+VOID:STRING,STRING,STRING,POINTER,STRING,POINTER
diff --git a/src/ck-seat.c b/src/ck-seat.c
index af7db59..dd2a387 100644
--- a/src/ck-seat.c
+++ b/src/ck-seat.c
@@ -40,21 +40,30 @@
#include "ck-seat-glue.h"
#include "ck-marshal.h"
+#include "ck-display-template.h"
#include "ck-session.h"
#include "ck-vt-monitor.h"
#include "ck-run-programs.h"
#define CK_SEAT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SEAT, CkSeatPrivate))
+#define CK_SESSION_DIR SYSCONFDIR "/ConsoleKit/sessions.d"
+
#define CK_DBUS_PATH "/org/freedesktop/ConsoleKit"
#define CK_DBUS_NAME "org.freedesktop.ConsoleKit"
#define NONULL_STRING(x) ((x) != NULL ? (x) : "")
+#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0]))
+
+#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
+
+#define CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
struct CkSeatPrivate
{
char *id;
CkSeatKind kind;
+ char *type;
GHashTable *sessions;
GPtrArray *devices;
@@ -63,6 +72,8 @@ struct CkSeatPrivate
CkVtMonitor *vt_monitor;
DBusGConnection *connection;
+
+ DBusGProxy *manager_proxy;
};
enum {
@@ -74,6 +85,9 @@ enum {
SESSION_REMOVED_FULL,
DEVICE_ADDED,
DEVICE_REMOVED,
+ REMOVE_REQUEST,
+ OPEN_SESSION_REQUEST,
+ CLOSE_SESSION_REQUEST,
LAST_SIGNAL
};
@@ -81,6 +95,7 @@ enum {
PROP_0,
PROP_ID,
PROP_KIND,
+ PROP_TYPE
};
static guint signals [LAST_SIGNAL] = { 0, };
@@ -287,6 +302,7 @@ ck_seat_activate_session (CkSeat
{
CkSession *session;
gboolean ret;
+ gboolean is_open;
g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
@@ -298,12 +314,390 @@ ck_seat_activate_session (CkSeat
session = g_hash_table_lookup (seat->priv->sessions, ssid);
}
- ret = _seat_activate_session (seat, session, context);
+ ck_session_is_open (session, &is_open, NULL);
+ if (!is_open) {
+ ret = ck_seat_request_open_session (seat, session, NULL);
+ dbus_g_method_return (context, NULL);
+ } else {
+ ret = _seat_activate_session (seat, session, context);
+ }
return ret;
}
static gboolean
+on_substitution_match (const GMatchInfo *match_info,
+ GString *result,
+ GHashTable *substitution_variables)
+{
+ char *match;
+ char *value;
+
+ match = g_match_info_fetch (match_info, 1);
+
+ value = g_hash_table_lookup (substitution_variables, match);
+
+ if (value != NULL) {
+ g_string_append (result, value);
+ } else {
+ char *original_string;
+
+ original_string = g_match_info_fetch (match_info, 0);
+ g_string_append (result, original_string);
+ g_free (original_string);
+ }
+ g_free (match);
+
+ return FALSE;
+}
+
+static char *
+apply_substitutions (const char *value,
+ GHashTable *substitution_variables)
+{
+ GRegex *expression;
+ char *expanded_string;
+
+ expression = g_regex_new ("\\$([^[:space:]]+)", 0, 0, NULL);
+ expanded_string = g_regex_replace_eval (expression,
+ value,
+ -1, 0, 0,
+ (GRegexEvalCallback)
+ on_substitution_match,
+ substitution_variables,
+ NULL);
+
+ if (expanded_string == NULL) {
+ expanded_string = g_strdup (value);
+ }
+
+ return expanded_string;
+}
+
+static GHashTable *
+get_evaluated_parameter_map (GHashTable *parameters,
+ GHashTable *substitution_variables)
+{
+ GHashTable *evaluated_parameters;
+ GHashTableIter iter;
+ gpointer key, value;
+
+ evaluated_parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+
+ g_hash_table_iter_init (&iter, parameters);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ char *expanded_string;
+
+ expanded_string = apply_substitutions ((char *) value,
+ substitution_variables);
+
+ g_hash_table_insert (evaluated_parameters,
+ g_strdup ((char *) key),
+ expanded_string);
+ }
+
+ return evaluated_parameters;
+}
+
+static void
+request_session (gpointer key,
+ gpointer value,
+ gpointer user_data)
+{
+ CkSeat *seat = CK_SEAT (user_data);
+ CkSession *session = (CkSession *) value;
+
+ ck_session_set_ever_open (session, FALSE, NULL);
+ ck_session_set_under_request (session, FALSE, NULL);
+ ck_seat_request_open_session (seat, session, NULL);
+}
+
+static void
+append_hash_table_to_dbus_message_iter (DBusMessageIter *iter,
+ GHashTable *hash_table)
+{
+ GHashTableIter hash_table_iter;
+ gpointer key, value;
+ DBusMessageIter array_iter;
+
+ dbus_message_iter_open_container (iter,
+ DBUS_TYPE_ARRAY,
+ DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_TYPE_STRING_AS_STRING
+ DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
+ &array_iter);
+
+
+ g_hash_table_iter_init (&hash_table_iter, hash_table);
+ while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) {
+ DBusMessageIter dict_iter;
+
+ dbus_message_iter_open_container (&array_iter,
+ DBUS_TYPE_DICT_ENTRY,
+ NULL,
+ &dict_iter);
+
+ dbus_message_iter_append_basic (&dict_iter, DBUS_TYPE_STRING, &key);
+ dbus_message_iter_append_basic (&dict_iter, DBUS_TYPE_STRING, &value);
+ dbus_message_iter_close_container (&array_iter, &dict_iter);
+ }
+ dbus_message_iter_close_container (iter, &array_iter);
+}
+
+static void
+emit_session_open_request (CkSeat *seat,
+ const char *ssid,
+ const char *session_type,
+ const char *display_template_name,
+ GHashTable *display_variables,
+ const char *display_type,
+ GHashTable *evaluated_parameters)
+{
+ DBusMessage *message;
+ DBusConnection *connection;
+ DBusMessageIter iter;
+
+ if (!ck_seat_is_managed (seat))
+ return;
+
+ message = dbus_message_new_signal (seat->priv->id,
+ "org.freedesktop.ConsoleKit.Seat",
+ "OpenSessionRequest");
+
+ dbus_message_set_destination (message,
+ dbus_g_proxy_get_bus_name (seat->priv->manager_proxy));
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &ssid);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session_type);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_template_name);
+ append_hash_table_to_dbus_message_iter (&iter, display_variables);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_type);
+ append_hash_table_to_dbus_message_iter (&iter, evaluated_parameters);
+
+ connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
+ dbus_connection_send (connection, message, NULL);
+ dbus_connection_unref (connection);
+ dbus_message_unref (message);
+}
+
+gboolean
+ck_seat_request_open_session (CkSeat *seat,
+ CkSession *session,
+ GError **error)
+{
+ char *ssid;
+ char *type;
+ CkDisplayTemplate *display_template;
+ GHashTable *display_variables;
+ GHashTable *display_parameters;
+ GHashTable *evaluated_parameters;
+ gboolean is_open;
+ gboolean ever_open;
+ gboolean under_request;
+
+ ck_session_is_open (session, &is_open, NULL);
+
+ if (is_open) {
+ return TRUE;
+ }
+
+ ck_session_get_under_request (session, &under_request, NULL);
+ if (under_request) {
+ return TRUE;
+ }
+
+ ck_session_set_under_request (session, TRUE, NULL);
+
+ ck_session_get_ever_open (session, &ever_open, NULL);
+
+ display_template = ck_session_get_display_template (session);
+
+ if (display_template == NULL) {
+ return TRUE;
+ }
+
+ ck_session_get_session_type (session, &type, NULL);
+
+ if (type == NULL) {
+ g_object_unref (display_template);
+ return TRUE;
+ }
+
+ /* substitute $display $vt etc */
+ display_variables = ck_session_get_display_variables (session);
+ display_parameters = ck_display_template_get_parameters (display_template);
+
+ if (display_parameters == NULL) {
+ g_free (type);
+ g_object_unref (display_template);
+ g_hash_table_unref (display_variables);
+ return TRUE;
+ }
+
+ if (!ever_open) {
+ evaluated_parameters = get_evaluated_parameter_map (display_parameters, display_variables);
+ } else {
+ evaluated_parameters = get_evaluated_parameter_map (display_parameters, NULL);
+ }
+
+ g_hash_table_unref (display_parameters);
+
+ ck_session_get_id (session, &ssid, NULL);
+
+ emit_session_open_request (seat, ssid, type,
+ ck_display_template_get_name (display_template),
+ display_variables,
+ ck_display_template_get_type_string (display_template),
+ evaluated_parameters);
+
+ g_free (ssid);
+ g_free (type);
+ g_hash_table_unref (evaluated_parameters);
+ g_hash_table_unref (display_variables);
+ g_object_unref (display_template);
+
+ return TRUE;
+}
+
+static void
+on_seat_manager_disappeared (CkSeat *seat)
+{
+ g_signal_handlers_disconnect_by_func (seat->priv->manager_proxy,
+ G_CALLBACK (on_seat_manager_disappeared),
+ seat);
+ g_object_unref (seat->priv->manager_proxy);
+ seat->priv->manager_proxy = NULL;
+
+ /* FIXME: should probably emit a signal so a new display manager
+ * knows that the seat is now unmanaged
+ *
+ * (maybe only if its kind is static?)
+ */
+}
+
+gboolean
+ck_seat_manage (CkSeat *seat,
+ DBusGMethodInvocation *context)
+{
+ char *sender_name;
+
+ sender_name = dbus_g_method_get_sender (context);
+
+ if (seat->priv->manager_proxy != NULL) {
+ GError *error;
+ const char *existing_manager_name;
+
+ existing_manager_name = dbus_g_proxy_get_bus_name (seat->priv->manager_proxy);
+
+ if (existing_manager_name == NULL) {
+ g_warning ("Seat manager lacks bus unique name");
+ existing_manager_name = "";
+ }
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Seat already managed (by '%s')"),
+ existing_manager_name);
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ /* FIXME: We pass in a bogus object path (the path we use on this side of
+ * the pipe) and interface here.
+ *
+ * We only use the proxy to watch for when the other side disappears, not
+ * for communicating with it. All communication is one-way using signals.
+ */
+ seat->priv->manager_proxy = dbus_g_proxy_new_for_name (seat->priv->connection,
+
+ sender_name,
+ seat->priv->id,
+ "org.freedesktop.ConsoleKit.SeatManager");
+ g_free (sender_name);
+
+ g_signal_connect_swapped (seat->priv->manager_proxy,
+ "destroy",
+ G_CALLBACK (on_seat_manager_disappeared),
+ seat);
+
+ g_hash_table_foreach (seat->priv->sessions, request_session, seat);
+
+ dbus_g_method_return (context);
+ return TRUE;
+}
+
+gboolean
+ck_seat_unmanage (CkSeat *seat,
+ DBusGMethodInvocation *context)
+{
+ GError *error;
+ const char *existing_manager_name;
+ char *sender_name;
+
+ if (seat->priv->manager_proxy == NULL) {
+ GError *error;
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Seat not managed"));
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ sender_name = dbus_g_method_get_sender (context);
+ existing_manager_name = dbus_g_proxy_get_bus_name (seat->priv->manager_proxy);
+
+ if (strcmp (sender_name, existing_manager_name) != 0) {
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Seat managed by '%s' not '%s'"),
+ existing_manager_name,
+ sender_name);
+
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+
+ return FALSE;
+ }
+
+ on_seat_manager_disappeared (seat);
+
+ dbus_g_method_return (context);
+ return TRUE;
+}
+
+void
+ck_seat_request_removal (CkSeat *seat)
+{
+ DBusMessage *message;
+ DBusConnection *connection;
+
+ g_return_if_fail (CK_IS_SEAT (seat));
+ g_return_if_fail (ck_seat_is_managed (seat));
+
+ message = dbus_message_new_signal (seat->priv->id,
+ "org.freedesktop.ConsoleKit.Seat",
+ "RemoveRequest");
+
+ dbus_message_set_destination (message,
+ dbus_g_proxy_get_bus_name (seat->priv->manager_proxy));
+
+ connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
+ dbus_connection_send (connection, message, NULL);
+ dbus_connection_unref (connection);
+ dbus_message_unref (message);
+}
+
+static gboolean
match_session_display_device (const char *key,
CkSession *session,
const char *display_device)
@@ -526,6 +920,41 @@ change_active_session (CkSeat *seat,
}
static void
+find_possible_session_to_activate (CkSeat *seat)
+{
+ GHashTableIter iter;
+ gpointer key, value;
+ gboolean is_open;
+ char *session_type = NULL;
+ CkSession *login_session = NULL;
+
+ g_hash_table_iter_init (&iter, seat->priv->sessions);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+
+ ck_session_is_open (value, &is_open, NULL);
+
+ if (is_open) {
+ login_session = NULL;
+ change_active_session (seat, value);
+ break;
+ }
+
+ ck_session_get_session_type (value, &session_type, NULL);
+ if (IS_STR_SET (session_type) &&
+ g_str_equal (session_type, "LoginWindow")) {
+ login_session = value;
+ g_free (session_type);
+ }
+ }
+
+ if (login_session != NULL) {
+ ck_session_set_ever_open (login_session, FALSE, NULL);
+ ck_seat_request_open_session (seat, login_session, NULL);
+ }
+
+}
+
+static void
update_active_vt (CkSeat *seat,
guint num)
{
@@ -537,7 +966,12 @@ update_active_vt (CkSeat *seat,
g_debug ("Active device: %s", device);
session = find_session_for_display_device (seat, device);
- change_active_session (seat, session);
+
+ if (session == NULL) {
+ find_possible_session_to_activate (seat);
+ } else {
+ change_active_session (seat, session);
+ }
g_free (device);
}
@@ -547,12 +981,18 @@ maybe_update_active_session (CkSeat *sea
{
guint num;
- if (seat->priv->kind != CK_SEAT_KIND_STATIC) {
- return;
- }
-
- if (ck_vt_monitor_get_active (seat->priv->vt_monitor, &num, NULL)) {
- update_active_vt (seat, num);
+ switch (seat->priv->kind){
+ case CK_SEAT_KIND_STATIC:
+ if (ck_vt_monitor_get_active (seat->priv->vt_monitor,
+ &num, NULL)) {
+ update_active_vt (seat, num);
+ }
+ break;
+ case CK_SEAT_KIND_DYNAMIC:
+ find_possible_session_to_activate (seat);
+ break;
+ default:
+ break;
}
}
@@ -628,18 +1068,77 @@ ck_seat_remove_session (CkSeat *
return ret;
}
+static void
+emit_session_close_request (CkSeat *seat,
+ const char *ssid)
+{
+ DBusMessage *message;
+ DBusConnection *connection;
+ DBusMessageIter iter;
+
+ message = dbus_message_new_signal (seat->priv->id,
+ "org.freedesktop.ConsoleKit.Seat",
+ "CloseSessionRequest");
+
+ dbus_message_set_destination (message,
+ dbus_g_proxy_get_bus_name (seat->priv->manager_proxy));
+
+ dbus_message_iter_init_append (message, &iter);
+ dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &ssid);
+
+ connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
+ dbus_connection_send (connection, message, NULL);
+ dbus_connection_unref (connection);
+ dbus_message_unref (message);
+}
+
+gboolean
+ck_seat_request_close_session (CkSeat *seat,
+ CkSession *session,
+ GError **error)
+{
+ char *ssid;
+
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+ g_return_val_if_fail (ck_seat_is_managed (seat), FALSE);
+
+ ck_session_get_id (session, &ssid, NULL);
+
+ emit_session_close_request (seat, ssid);
+
+ g_free (ssid);
+
+ return FALSE;
+}
+
gboolean
ck_seat_add_session (CkSeat *seat,
CkSession *session,
GError **error)
{
char *ssid;
+ GHashTableIter iter;
+ gpointer key, value;
+ gboolean found;
g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
ck_session_get_id (session, &ssid, NULL);
- g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session));
+ found = FALSE;
+ g_hash_table_iter_init (&iter, seat->priv->sessions);
+ while (g_hash_table_iter_next (&iter, &key, &value)) {
+ if (g_str_equal ((gchar *)key, ssid)) {
+ found = TRUE;
+ break;
+ }
+ }
+
+ if (! found)
+ g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session));
+ else
+ g_object_ref (session);
ck_session_set_seat_id (session, seat->priv->id, NULL);
@@ -656,6 +1155,10 @@ ck_seat_add_session (CkSeat *sea
maybe_update_active_session (seat);
+ if (ck_seat_is_managed (seat)) {
+ ck_seat_request_open_session (seat, session, NULL);
+ }
+
g_free (ssid);
return TRUE;
@@ -742,6 +1245,20 @@ ck_seat_get_kind (CkSeat *seat,
}
gboolean
+ck_seat_get_type_string (CkSeat *seat,
+ char **type,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ if (type != NULL) {
+ *type = g_strdup (seat->priv->type);
+ }
+
+ return TRUE;
+}
+
+gboolean
ck_seat_get_id (CkSeat *seat,
char **id,
GError **error)
@@ -860,6 +1377,14 @@ _ck_seat_set_kind (CkSeat *seat,
}
static void
+_ck_seat_set_type_string (CkSeat *seat,
+ const char *type)
+{
+ g_free (seat->priv->type);
+ seat->priv->type = g_strdup (type);
+}
+
+static void
ck_seat_set_property (GObject *object,
guint prop_id,
const GValue *value,
@@ -876,6 +1401,9 @@ ck_seat_set_property (GObject
case PROP_KIND:
_ck_seat_set_kind (self, g_value_get_enum (value));
break;
+ case PROP_TYPE:
+ _ck_seat_set_type_string (self, g_value_get_string (value));
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -897,7 +1425,10 @@ ck_seat_get_property (GObject *object
g_value_set_string (value, self->priv->id);
break;
case PROP_KIND:
- g_value_set_string (value, self->priv->id);
+ g_value_set_enum (value, self->priv->kind);
+ break;
+ case PROP_TYPE:
+ g_value_set_string (value, self->priv->type);
break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
@@ -1010,6 +1541,43 @@ ck_seat_class_init (CkSeatClass *klass)
G_TYPE_NONE,
1, CK_TYPE_DEVICE);
+ signals [REMOVE_REQUEST] = g_signal_new ("remove-request",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSeatClass, remove_request),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE, 0);
+
+ signals [OPEN_SESSION_REQUEST] = g_signal_new ("open-session-request",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ ck_marshal_VOID__STRING_STRING_STRING_POINTER_STRING_POINTER,
+ G_TYPE_NONE,
+ 6,
+ DBUS_TYPE_G_OBJECT_PATH,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE,
+ G_TYPE_STRING,
+ CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE,
+ G_TYPE_INVALID);
+
+
+ signals [CLOSE_SESSION_REQUEST] = g_signal_new ("close-session-request",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ 0,
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 1, DBUS_TYPE_G_OBJECT_PATH);
+
g_object_class_install_property (object_class,
PROP_ID,
g_param_spec_string ("id",
@@ -1026,6 +1594,13 @@ ck_seat_class_init (CkSeatClass *klass)
CK_SEAT_KIND_DYNAMIC,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_TYPE,
+ g_param_spec_string ("type",
+ "type",
+ "type",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_type_class_add_private (klass, sizeof (CkSeatPrivate));
dbus_g_object_type_install_info (CK_TYPE_SEAT, &dbus_glib_ck_seat_object_info);
@@ -1041,6 +1616,7 @@ ck_seat_init (CkSeat *seat)
g_free,
(GDestroyNotify) g_object_unref);
seat->priv->devices = g_ptr_array_new ();
+ seat->priv->manager_proxy = NULL;
}
static void
@@ -1066,28 +1642,32 @@ ck_seat_finalize (GObject *object)
g_ptr_array_free (seat->priv->devices, TRUE);
g_hash_table_destroy (seat->priv->sessions);
g_free (seat->priv->id);
+ g_free (seat->priv->type);
G_OBJECT_CLASS (ck_seat_parent_class)->finalize (object);
}
CkSeat *
ck_seat_new (const char *sid,
- CkSeatKind kind)
+ CkSeatKind kind,
+ const char *type)
{
GObject *object;
object = g_object_new (CK_TYPE_SEAT,
"id", sid,
"kind", kind,
+ "type", type,
NULL);
return CK_SEAT (object);
}
CkSeat *
-ck_seat_new_with_devices (const char *sid,
- CkSeatKind kind,
- GPtrArray *devices)
+ck_seat_new_with_devices_and_sessions (const char *sid,
+ CkSeatKind kind,
+ GPtrArray *devices,
+ GPtrArray *sessions)
{
GObject *object;
int i;
@@ -1102,24 +1682,57 @@ ck_seat_new_with_devices (const char *si
ck_seat_add_device (CK_SEAT (object), g_ptr_array_index (devices, i), NULL);
}
}
+ if (sessions != NULL) {
+ for (i = 0; i < sessions->len; i++) {
+ ck_seat_add_session (CK_SEAT (object), g_ptr_array_index (sessions, i), NULL);
+ }
+ }
+
return CK_SEAT (object);
}
+static char *
+generate_static_session_id (const char *sid,
+ const char *session_name)
+{
+ const char *seat_name;
+ char *ssid;
+
+ seat_name = strrchr (sid, '/');
+
+ if (seat_name == NULL) {
+ g_warning ("Seat id '%s' lacks a /", sid);
+ seat_name = sid;
+ } else {
+ seat_name++;
+ }
+
+ ssid = g_strdup_printf ("%s/Session%s%s",
+ CK_DBUS_PATH, seat_name,
+ session_name);
+
+ return ssid;
+}
+
CkSeat *
-ck_seat_new_from_file (const char *sid,
+ck_seat_new_from_file (char **sid,
const char *path)
{
- GKeyFile *key_file;
- gboolean res;
- GError *error;
- char *group;
- CkSeat *seat;
- gboolean hidden;
- GPtrArray *devices;
- char **device_list;
- gsize ndevices;
- gsize i;
+ GKeyFile *key_file;
+ gboolean res;
+ GError *error;
+ char *group;
+ CkSeat *seat;
+ char *read_sid;
+ gboolean hidden;
+ GPtrArray *sessions;
+ char **session_list;
+ gsize nsessions;
+ GPtrArray *devices;
+ char **device_list;
+ gsize ndevices;
+ gsize i;
seat = NULL;
@@ -1147,6 +1760,49 @@ ck_seat_new_from_file (const char *sid,
goto out;
}
+ read_sid = g_key_file_get_string (key_file, group, "ID", NULL);
+ if (IS_STR_SET (read_sid)) {
+ g_free (*sid);
+ *sid = g_strdup_printf ("%s/%s", CK_DBUS_PATH, read_sid);
+ } else {
+ g_free (read_sid);
+ }
+
+ session_list = g_key_file_get_string_list (key_file, group, "Sessions", &nsessions, NULL);
+
+ sessions = g_ptr_array_sized_new (nsessions);
+
+ for (i = 0; i < nsessions; i++) {
+ char *path;
+ char *file;
+ char *ssid;
+ CkSession *session;
+
+ file = g_strconcat (session_list[i], ".session", NULL);
+ path = g_build_filename (CK_SESSION_DIR, file, NULL);
+ g_free (file);
+
+ /* FIXME: we should probably use the same naming pool as
+ * sessions generated from ck-manager. We mangle the name
+ * here so we don't clash with names from ck-manager
+ */
+ ssid = generate_static_session_id (*sid, session_list[i]);
+
+ session = ck_session_new_from_file (ssid, path);
+
+ if (session == NULL) {
+ g_warning ("Unable to load session from file %s", path);
+ g_free (path);
+ continue;
+ }
+ g_free (path);
+ ck_session_set_seat_id (session, *sid, NULL);
+
+ g_ptr_array_add (sessions, session);
+ }
+
+ g_strfreev (session_list);
+
device_list = g_key_file_get_string_list (key_file, group, "Devices", &ndevices, NULL);
g_debug ("Creating seat %s with %zd devices", sid, ndevices);
@@ -1178,11 +1834,12 @@ ck_seat_new_from_file (const char *sid,
g_strfreev (split);
}
g_strfreev (device_list);
- g_free (group);
- seat = ck_seat_new_with_devices (sid, CK_SEAT_KIND_STATIC, devices);
+ seat = ck_seat_new_with_devices_and_sessions (*sid, CK_SEAT_KIND_STATIC, devices, sessions);
g_ptr_array_free (devices, TRUE);
+ g_free (group);
+
out:
g_key_file_free (key_file);
@@ -1357,10 +2014,15 @@ ck_seat_dump (CkSeat *seat,
error = NULL;
if (! ck_session_get_id (seat->priv->active_session, &session_id, &error)) {
- g_warning ("Cannot get session id for active session on seat %s: %s",
- seat->priv->id,
- error->message);
- g_error_free (error);
+ if (error) {
+ g_warning ("Cannot get session id for active session on seat %s: %s",
+ seat->priv->id,
+ error->message);
+ g_error_free (error);
+ } else {
+ g_warning ("Cannot get session id for active session on seat %s",
+ seat->priv->id);
+ }
} else {
g_key_file_set_string (key_file,
group_name,
@@ -1372,3 +2034,24 @@ ck_seat_dump (CkSeat *seat,
g_free (group_name);
}
+
+gboolean
+ck_seat_is_managed (CkSeat *seat)
+{
+ return seat->priv->manager_proxy != NULL;
+}
+
+CkSession *
+ck_seat_get_session (CkSeat *seat,
+ const char *ssid)
+{
+ CkSession *session;
+
+ session = g_hash_table_lookup (seat->priv->sessions, ssid);
+
+ if (session == NULL) {
+ return NULL;
+ }
+
+ return g_object_ref (session);
+}
diff --git a/src/ck-seat.h b/src/ck-seat.h
index fb9a955..6276021 100644
--- a/src/ck-seat.h
+++ b/src/ck-seat.h
@@ -47,6 +47,7 @@ typedef struct
{
GObjectClass parent_class;
+ void (* remove_request) (CkSeat *seat);
void (* active_session_changed) (CkSeat *seat,
const char *ssid);
void (* session_added) (CkSeat *seat,
@@ -57,6 +58,11 @@ typedef struct
GValueArray *device);
void (* device_removed) (CkSeat *seat,
GValueArray *device);
+ void (* session_to_add) (CkSeat *seat,
+ gboolean is_dynamic,
+ const char *command);
+ void (* session_to_remove) (CkSeat *seat,
+ int display_number);
} CkSeatClass;
typedef enum
@@ -84,12 +90,14 @@ typedef enum
GQuark ck_seat_error_quark (void);
GType ck_seat_get_type (void);
CkSeat * ck_seat_new (const char *sid,
- CkSeatKind kind);
-CkSeat * ck_seat_new_from_file (const char *sid,
- const char *path);
-CkSeat * ck_seat_new_with_devices (const char *sid,
CkSeatKind kind,
- GPtrArray *devices);
+ const char *type);
+CkSeat * ck_seat_new_from_file (char **sid,
+ const char *path);
+CkSeat * ck_seat_new_with_devices_and_sessions (const char *sid,
+ CkSeatKind kind,
+ GPtrArray *devices,
+ GPtrArray *sessions);
gboolean ck_seat_register (CkSeat *seat);
@@ -104,18 +112,31 @@ void ck_seat_dump (CkSeat *seat,
gboolean ck_seat_get_kind (CkSeat *seat,
CkSeatKind *kind,
GError **error);
+gboolean ck_seat_get_type_string (CkSeat *seat,
+ char **type,
+ GError **error);
gboolean ck_seat_add_session (CkSeat *seat,
CkSession *session,
GError **error);
gboolean ck_seat_remove_session (CkSeat *seat,
CkSession *session,
GError **error);
+gboolean ck_seat_request_open_session (CkSeat *seat,
+ CkSession *session,
+ GError **error);
+gboolean ck_seat_request_close_session (CkSeat *seat,
+ CkSession *session,
+ GError **error);
gboolean ck_seat_add_device (CkSeat *seat,
GValueArray *device,
GError **error);
gboolean ck_seat_remove_device (CkSeat *seat,
GValueArray *device,
GError **error);
+gboolean ck_seat_is_managed (CkSeat *seat);
+CkSession *ck_seat_get_session (CkSeat *seat,
+ const char *ssid);
+void ck_seat_request_removal (CkSeat *seat);
/* exported methods */
gboolean ck_seat_get_id (CkSeat *seat,
@@ -137,6 +158,10 @@ gboolean ck_seat_can_activate_sessions (CkSeat *seat,
gboolean ck_seat_activate_session (CkSeat *seat,
const char *ssid,
DBusGMethodInvocation *context);
+gboolean ck_seat_manage (CkSeat *seat,
+ DBusGMethodInvocation *context);
+gboolean ck_seat_unmanage (CkSeat *seat,
+ DBusGMethodInvocation *context);
G_END_DECLS
diff --git a/src/ck-session-leader.c b/src/ck-session-leader.c
index 3702602..908d2bb 100644
--- a/src/ck-session-leader.c
+++ b/src/ck-session-leader.c
@@ -238,6 +238,7 @@ static struct {
{ "x11-display", add_param_string },
{ "remote-host-name", add_param_string },
{ "session-type", add_param_string },
+ { "display-type", add_param_string },
{ "is-local", add_param_boolean },
{ "unix-user", add_param_int },
};
diff --git a/src/ck-session.c b/src/ck-session.c
index d8db9dd..0354dd5 100644
--- a/src/ck-session.c
+++ b/src/ck-session.c
@@ -41,6 +41,7 @@
#include "ck-session-glue.h"
#include "ck-marshal.h"
#include "ck-run-programs.h"
+#include "ck-display-template.h"
#define CK_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SESSION, CkSessionPrivate))
@@ -58,6 +59,7 @@ struct CkSessionPrivate
char *seat_id;
char *session_type;
+ char *display_type;
char *login_session_id;
char *display_device;
char *x11_display_device;
@@ -65,8 +67,15 @@ struct CkSessionPrivate
char *remote_host_name;
guint uid;
+ CkDisplayTemplate *display_template;
+ GHashTable *display_variables;
+
gboolean active;
gboolean is_local;
+ gboolean is_open;
+ gboolean ever_open;
+ gboolean under_request;
+ GMutex *mutex_under_request;
GTimeVal creation_time;
@@ -75,6 +84,8 @@ struct CkSessionPrivate
gboolean idle_hint;
GTimeVal idle_since_hint;
+ gboolean remove_on_close;
+
DBusGConnection *connection;
DBusGProxy *bus_proxy;
};
@@ -92,17 +103,24 @@ enum {
PROP_0,
PROP_ID,
PROP_COOKIE,
+ PROP_SEAT_ID,
PROP_USER,
PROP_UNIX_USER,
PROP_X11_DISPLAY,
PROP_X11_DISPLAY_DEVICE,
PROP_DISPLAY_DEVICE,
PROP_SESSION_TYPE,
+ PROP_DISPLAY_TYPE,
+ PROP_DISPLAY_TEMPLATE,
+ PROP_DISPLAY_VARIABLES,
PROP_REMOTE_HOST_NAME,
PROP_LOGIN_SESSION_ID,
PROP_IS_LOCAL,
+ PROP_IS_OPEN,
+ PROP_EVER_OPEN,
PROP_ACTIVE,
PROP_IDLE_HINT,
+ PROP_REMOVE_ON_CLOSE,
};
static guint signals [LAST_SIGNAL] = { 0, };
@@ -128,6 +146,7 @@ static gboolean
register_session (CkSession *session)
{
GError *error = NULL;
+ GObject *existing_session;
error = NULL;
session->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
@@ -144,6 +163,15 @@ register_session (CkSession *session)
DBUS_PATH_DBUS,
DBUS_INTERFACE_DBUS);
+ existing_session = dbus_g_connection_lookup_g_object (session->priv->connection,
+ session->priv->id);
+
+ if (existing_session != NULL) {
+ g_warning ("Session '%s' was registered twice!",
+ session->priv->id);
+ return FALSE;
+ }
+
dbus_g_connection_register_g_object (session->priv->connection, session->priv->id, G_OBJECT (session));
return TRUE;
@@ -302,6 +330,35 @@ ck_session_set_idle_hint (CkSession
}
gboolean
+session_set_remove_on_close (CkSession *session,
+ gboolean remove_on_close,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (session->priv->remove_on_close != remove_on_close) {
+ session->priv->remove_on_close = remove_on_close;
+ }
+
+ return TRUE;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Session1 \
+ org.freedesktop.ConsoleKit.Session.SetRemoveOnClose boolean:TRUE
+*/
+gboolean
+ck_session_set_remove_on_close (CkSession *session,
+ gboolean remove_on_close,
+ DBusGMethodInvocation *context)
+{
+ return session_set_remove_on_close (session, remove_on_close, NULL);
+}
+
+gboolean
ck_session_get_idle_hint (CkSession *session,
gboolean *idle_hint,
GError **error)
@@ -420,6 +477,68 @@ ck_session_set_is_local (CkSession
}
gboolean
+ck_session_set_is_open (CkSession *session,
+ gboolean is_open,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (session->priv->is_open != is_open) {
+ session->priv->is_open = is_open;
+ session->priv->ever_open = TRUE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_ever_open (CkSession *session,
+ gboolean ever_open,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (session->priv->ever_open != ever_open) {
+ session->priv->ever_open = ever_open;
+ }
+
+ return TRUE;
+}
+
+static gboolean
+timeout_for_under_request (gpointer data)
+{
+ CkSession *session = CK_SESSION (data);
+ g_mutex_lock (session->priv->mutex_under_request);
+ session->priv->under_request = FALSE;
+ g_mutex_unlock (session->priv->mutex_under_request);
+
+ g_debug ("timeout for under request of session %s", session->priv->id);
+ return FALSE;
+}
+
+gboolean
+ck_session_set_under_request (CkSession *session,
+ gboolean under_request,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_mutex_lock (session->priv->mutex_under_request);
+ if (!under_request) {
+ session->priv->under_request = FALSE;
+ } else {
+ if (!session->priv->under_request) {
+ session->priv->under_request = TRUE;
+ g_timeout_add_seconds (1, timeout_for_under_request, session);
+ }
+ }
+ g_mutex_unlock (session->priv->mutex_under_request);
+
+ return TRUE;
+}
+
+gboolean
ck_session_get_id (CkSession *session,
char **id,
GError **error)
@@ -555,6 +674,20 @@ ck_session_get_creation_time (CkSession
}
gboolean
+ck_session_get_remove_on_close (CkSession *session,
+ gboolean *remove_on_close,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (remove_on_close != NULL) {
+ *remove_on_close = session->priv->remove_on_close;
+ }
+
+ return TRUE;
+}
+
+gboolean
ck_session_get_session_type (CkSession *session,
char **type,
GError **error)
@@ -569,6 +702,20 @@ ck_session_get_session_type (CkSession
}
gboolean
+ck_session_get_display_type (CkSession *session,
+ char **type,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (type != NULL) {
+ *type = g_strdup (session->priv->display_type);
+ }
+
+ return TRUE;
+}
+
+gboolean
ck_session_is_active (CkSession *session,
gboolean *active,
GError **error)
@@ -597,6 +744,50 @@ ck_session_is_local (CkSession *ses
}
gboolean
+ck_session_is_open (CkSession *session,
+ gboolean *open,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (open != NULL) {
+ *open = session->priv->is_open;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_ever_open (CkSession *session,
+ gboolean *open,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (open != NULL) {
+ *open = session->priv->ever_open;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_under_request (CkSession *session,
+ gboolean *under_request,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (under_request != NULL) {
+ g_mutex_lock (session->priv->mutex_under_request);
+ *under_request = session->priv->under_request;
+ g_mutex_unlock (session->priv->mutex_under_request);
+ }
+
+ return TRUE;
+}
+
+gboolean
ck_session_set_id (CkSession *session,
const char *id,
GError **error)
@@ -609,6 +800,21 @@ ck_session_set_id (CkSession *sessi
return TRUE;
}
+static void
+ck_session_set_display_variables (CkSession *session,
+ GHashTable *display_variables)
+{
+ if (session->priv->display_variables != NULL) {
+ g_hash_table_unref (session->priv->display_variables);
+ }
+
+ if (display_variables != NULL) {
+ session->priv->display_variables = g_hash_table_ref (display_variables);
+ } else {
+ session->priv->display_variables = NULL;
+ }
+}
+
gboolean
ck_session_set_cookie (CkSession *session,
const char *cookie,
@@ -725,6 +931,54 @@ ck_session_set_session_type (CkSession
return TRUE;
}
+gboolean
+ck_session_set_display_type (CkSession *session,
+ const char *type,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->display_type);
+ session->priv->display_type = g_strdup (type);
+
+ return TRUE;
+}
+
+static gboolean
+ck_session_set_display_template (CkSession *session,
+ CkDisplayTemplate *display_template,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (session->priv->display_template != NULL) {
+ g_object_unref (session->priv->display_template);
+ }
+
+ if (display_template != NULL) {
+ session->priv->display_template = g_object_ref (display_template);
+ ck_session_set_display_type (session, ck_display_template_get_name (display_template), error);
+ } else {
+ session->priv->display_template = NULL;
+ }
+
+ return TRUE;
+}
+
+GHashTable *
+ck_session_get_display_variables (CkSession *session)
+{
+ return g_hash_table_ref (session->priv->display_variables);
+}
+
+CkDisplayTemplate *
+ck_session_get_display_template (CkSession *session)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ return g_object_ref (session->priv->display_template);
+}
+
static void
ck_session_set_property (GObject *object,
guint prop_id,
@@ -742,15 +996,33 @@ ck_session_set_property (GObject
case PROP_IS_LOCAL:
ck_session_set_is_local (self, g_value_get_boolean (value), NULL);
break;
+ case PROP_IS_OPEN:
+ ck_session_set_is_open (self, g_value_get_boolean (value), NULL);
+ break;
+ case PROP_EVER_OPEN:
+ ck_session_set_ever_open (self, g_value_get_boolean (value), NULL);
+ break;
case PROP_ID:
ck_session_set_id (self, g_value_get_string (value), NULL);
break;
case PROP_COOKIE:
ck_session_set_cookie (self, g_value_get_string (value), NULL);
break;
+ case PROP_SEAT_ID:
+ ck_session_set_seat_id (self, g_value_get_string (value), NULL);
+ break;
case PROP_SESSION_TYPE:
ck_session_set_session_type (self, g_value_get_string (value), NULL);
break;
+ case PROP_DISPLAY_TYPE:
+ ck_session_set_display_type (self, g_value_get_string (value), NULL);
+ break;
+ case PROP_DISPLAY_TEMPLATE:
+ ck_session_set_display_template (self, g_value_get_object (value), NULL);
+ break;
+ case PROP_DISPLAY_VARIABLES:
+ ck_session_set_display_variables (self, g_value_get_boxed (value));
+ break;
case PROP_X11_DISPLAY:
ck_session_set_x11_display (self, g_value_get_string (value), NULL);
break;
@@ -775,6 +1047,9 @@ ck_session_set_property (GObject
case PROP_IDLE_HINT:
session_set_idle_hint_internal (self, g_value_get_boolean (value));
break;
+ case PROP_REMOVE_ON_CLOSE:
+ session_set_remove_on_close (self, g_value_get_boolean (value), NULL);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -798,15 +1073,33 @@ ck_session_get_property (GObject *obj
case PROP_IS_LOCAL:
g_value_set_boolean (value, self->priv->is_local);
break;
+ case PROP_IS_OPEN:
+ g_value_set_boolean (value, self->priv->is_open);
+ break;
+ case PROP_EVER_OPEN:
+ g_value_set_boolean (value, self->priv->ever_open);
+ break;
case PROP_ID:
g_value_set_string (value, self->priv->id);
break;
case PROP_COOKIE:
g_value_set_string (value, self->priv->cookie);
break;
+ case PROP_SEAT_ID:
+ g_value_set_string (value, self->priv->seat_id);
+ break;
case PROP_SESSION_TYPE:
g_value_set_string (value, self->priv->session_type);
break;
+ case PROP_DISPLAY_TYPE:
+ g_value_set_string (value, self->priv->display_type);
+ break;
+ case PROP_DISPLAY_TEMPLATE:
+ g_value_set_object (value, self->priv->display_template);
+ break;
+ case PROP_DISPLAY_VARIABLES:
+ g_value_set_boxed (value, self->priv->display_variables);
+ break;
case PROP_X11_DISPLAY:
g_value_set_string (value, self->priv->x11_display);
break;
@@ -831,6 +1124,9 @@ ck_session_get_property (GObject *obj
case PROP_IDLE_HINT:
g_value_set_boolean (value, self->priv->idle_hint);
break;
+ case PROP_REMOVE_ON_CLOSE:
+ g_value_set_boolean (value, self->priv->remove_on_close);
+ break;
default:
G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
break;
@@ -1000,6 +1296,13 @@ ck_session_class_init (CkSessionClass *k
"cookie",
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_SEAT_ID,
+ g_param_spec_string ("seat-id",
+ "seat id",
+ "seat id",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
g_object_class_install_property (object_class,
PROP_SESSION_TYPE,
@@ -1009,6 +1312,27 @@ ck_session_class_init (CkSessionClass *k
NULL,
G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
g_object_class_install_property (object_class,
+ PROP_DISPLAY_TYPE,
+ g_param_spec_string ("display-type",
+ "session-type",
+ "session type",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_DISPLAY_TEMPLATE,
+ g_param_spec_object ("display-template",
+ "Display Template",
+ "The display template",
+ CK_TYPE_DISPLAY_TEMPLATE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
+ PROP_DISPLAY_VARIABLES,
+ g_param_spec_boxed ("display-variables",
+ "Display Variables",
+ "Display type specific variables",
+ G_TYPE_HASH_TABLE,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+ g_object_class_install_property (object_class,
PROP_LOGIN_SESSION_ID,
g_param_spec_string ("login-session-id",
"login-session-id",
@@ -1071,6 +1395,14 @@ ck_session_class_init (CkSessionClass *k
FALSE,
G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_REMOVE_ON_CLOSE,
+ g_param_spec_boolean ("remove-on-close",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+
g_type_class_add_private (klass, sizeof (CkSessionPrivate));
dbus_g_object_type_install_info (CK_TYPE_SESSION, &dbus_glib_ck_session_object_info);
@@ -1081,8 +1413,16 @@ ck_session_init (CkSession *session)
{
session->priv = CK_SESSION_GET_PRIVATE (session);
+ session->priv->display_variables = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+
/* FIXME: should we have a property for this? */
g_get_current_time (&session->priv->creation_time);
+
+ if (!session->priv->mutex_under_request)
+ session->priv->mutex_under_request = g_mutex_new ();
}
static void
@@ -1105,6 +1445,7 @@ ck_session_finalize (GObject *object)
g_free (session->priv->cookie);
g_free (session->priv->seat_id);
g_free (session->priv->session_type);
+ g_free (session->priv->display_type);
g_free (session->priv->login_session_id);
g_free (session->priv->display_device);
g_free (session->priv->x11_display_device);
@@ -1115,16 +1456,135 @@ ck_session_finalize (GObject *object)
}
CkSession *
+ck_session_new_from_file (const char *ssid,
+ const char *path)
+{
+ GKeyFile *key_file;
+ gboolean res;
+ GError *error;
+ char *group;
+ char *name;
+ gboolean hidden;
+ char *type;
+ char *display_template_string;
+ CkSession *session;
+ GHashTable *display_variables;
+ char **type_keys;
+
+ key_file = g_key_file_new ();
+ error = NULL;
+ res = g_key_file_load_from_file (key_file,
+ path,
+ G_KEY_FILE_NONE,
+ &error);
+
+ if (! res) {
+ g_warning ("Unable to load sessions from file %s: %s",
+ path, error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ group = g_key_file_get_start_group (key_file);
+ if (group == NULL || strcmp (group, "Session Entry") != 0) {
+ g_warning ("Not a session file: %s", path);
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL);
+
+ if (hidden) {
+ g_debug ("Session is hidden");
+ g_free (group);
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ name = g_key_file_get_string (key_file, group, "Name", NULL);
+
+ if (name == NULL) {
+ g_warning ("Session file %s doesn't contain a name", path);
+ g_free (group);
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ type = g_key_file_get_string (key_file, group, "Type", NULL);
+
+ if (type == NULL) {
+ g_warning ("Session file %s doesn't contain a type", path);
+ g_free (group);
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ display_template_string = g_key_file_get_string (key_file, group, "DisplayTemplate", NULL);
+
+ if (display_template_string == NULL) {
+ g_warning ("Session file %s doesn't contain a display type", path);
+ g_free (group);
+ g_key_file_free (key_file);
+ return NULL;
+ }
+
+ /* Find a group in the key file named after the display type and stuff
+ * all its entries into a hash table for later.
+ *
+ * Those keys are for things like the display number and the vt to
+ * run X with.
+ */
+ display_variables = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+ type_keys = g_key_file_get_keys (key_file, display_template_string, NULL, NULL);
+
+ if (type_keys != NULL) {
+ int i;
+ for (i = 0; type_keys[i] != NULL; i++) {
+ char *string;
+ string = g_key_file_get_string (key_file, display_template_string, type_keys[i], NULL);
+
+ g_hash_table_insert (display_variables, g_strdup (type_keys[i]), string);
+ }
+ g_strfreev (type_keys);
+ }
+
+ session = ck_session_new (ssid, type, display_template_string, display_variables);
+
+ g_free (display_template_string);
+ g_free (group);
+ g_free (type);
+ g_hash_table_unref (display_variables);
+
+ return session;
+}
+
+CkSession *
ck_session_new (const char *ssid,
- const char *cookie)
+ const char *type,
+ const char *display_template_string,
+ GHashTable *display_variables)
{
+ CkDisplayTemplate *display_template;
GObject *object;
gboolean res;
+ display_template = ck_display_template_get_from_name (display_template_string);
+
+ if (display_template == NULL) {
+ g_warning ("Unable to load display type %s", display_template_string);
+ return NULL;
+ }
+
object = g_object_new (CK_TYPE_SESSION,
"id", ssid,
- "cookie", cookie,
+ "session-type", type,
+ "display-type", display_template_string,
+ "display-template", display_template,
+ "display-variables", display_variables,
NULL);
+
res = register_session (CK_SESSION (object));
if (! res) {
g_object_unref (object);
@@ -1139,9 +1599,80 @@ ck_session_new (const char *ssid,
G_TYPE_VALUE, \
G_TYPE_INVALID))
+void
+ck_session_set_parameters (CkSession *session,
+ const GPtrArray *parameters)
+{
+ int i;
+ GObjectClass *class;
+ GType object_type;
+
+ object_type = CK_TYPE_SESSION;
+ class = g_type_class_ref (object_type);
+ for (i = 0; i < parameters->len; i++) {
+ gboolean res;
+ GValue val_struct = { 0, };
+ GValue value = { 0, };
+ char *prop_name;
+ GValue *prop_val;
+ GParamSpec *pspec;
+
+ g_value_init (&val_struct, CK_TYPE_PARAMETER_STRUCT);
+ g_value_set_static_boxed (&val_struct, g_ptr_array_index (parameters, i));
+
+ res = dbus_g_type_struct_get (&val_struct,
+ 0, &prop_name,
+ 1, &prop_val,
+ G_MAXUINT);
+ if (! res) {
+ g_debug ("Unable to extract parameter input");
+ goto cont;
+ }
+
+ if (prop_name == NULL) {
+ g_debug ("Skipping NULL parameter");
+ goto cont;
+ }
+
+ if (strcmp (prop_name, "id") == 0
+ || strcmp (prop_name, "cookie") == 0) {
+ g_debug ("Skipping restricted parameter: %s", prop_name);
+ goto cont;
+ }
+
+ pspec = g_object_class_find_property (class, prop_name);
+ if (! pspec) {
+ g_debug ("Skipping unknown parameter: %s", prop_name);
+ goto cont;
+ }
+
+ if (!(pspec->flags & G_PARAM_WRITABLE)) {
+ g_debug ("property '%s' is not writable", pspec->name);
+ goto cont;
+ }
+
+ g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
+ res = g_value_transform (prop_val, &value);
+ if (! res) {
+ g_debug ("unable to transform property value for '%s'", pspec->name);
+ goto cont;
+ }
+
+ g_object_set_property (G_OBJECT (session), prop_name, &value);
+ g_value_unset (&value);
+ cont:
+ g_free (prop_name);
+ if (prop_val != NULL) {
+ g_value_unset (prop_val);
+ g_free (prop_val);
+ }
+ }
+
+ g_type_class_unref (class);
+}
+
CkSession *
ck_session_new_with_parameters (const char *ssid,
- const char *cookie,
const GPtrArray *parameters)
{
GObject *object;
@@ -1170,12 +1701,6 @@ ck_session_new_with_parameters (const ch
g_value_set_string (¶ms[n_params].value, ssid);
n_params++;
- params[n_params].name = g_strdup ("cookie");
- params[n_params].value.g_type = 0;
- g_value_init (¶ms[n_params].value, G_TYPE_STRING);
- g_value_set_string (¶ms[n_params].value, cookie);
- n_params++;
-
if (parameters != NULL) {
for (i = 0; i < parameters->len; i++) {
gboolean res;
@@ -1260,7 +1785,7 @@ ck_session_run_programs (CkSession *ses
const char *action)
{
int n;
- char *extra_env[11]; /* be sure to adjust this as needed */
+ char *extra_env[12]; /* be sure to adjust this as needed */
n = 0;
@@ -1268,6 +1793,9 @@ ck_session_run_programs (CkSession *ses
if (session->priv->session_type != NULL) {
extra_env[n++] = g_strdup_printf ("CK_SESSION_TYPE=%s", session->priv->session_type);
}
+ if (session->priv->display_type != NULL) {
+ extra_env[n++] = g_strdup_printf ("CK_SESSION_DISPLAY_TYPE=%s", session->priv->display_type);
+ }
extra_env[n++] = g_strdup_printf ("CK_SESSION_SEAT_ID=%s", session->priv->seat_id);
extra_env[n++] = g_strdup_printf ("CK_SESSION_USER_UID=%d", session->priv->uid);
if (session->priv->display_device != NULL && strlen (session->priv->display_device) > 0) {
@@ -1302,6 +1830,10 @@ ck_session_dump (CkSession *session,
char *s;
char *group_name;
+ if (!session->priv->is_open) {
+ return;
+ }
+
group_name = g_strdup_printf ("Session %s", session->priv->id);
g_key_file_set_integer (key_file, group_name, "uid", session->priv->uid);
g_key_file_set_string (key_file,
@@ -1314,6 +1846,12 @@ ck_session_dump (CkSession *session,
"type",
NONULL_STRING (session->priv->session_type));
}
+ if (session->priv->display_type != NULL) {
+ g_key_file_set_string (key_file,
+ group_name,
+ "display_type",
+ NONULL_STRING (session->priv->display_type));
+ }
if (session->priv->login_session_id != NULL && strlen (session->priv->login_session_id) > 0) {
g_key_file_set_string (key_file,
group_name,
diff --git a/src/ck-session.h b/src/ck-session.h
index b6b565b..a24d0a8 100644
--- a/src/ck-session.h
+++ b/src/ck-session.h
@@ -25,6 +25,8 @@
#include
#include
+#include "ck-display-template.h"
+
G_BEGIN_DECLS
#define CK_TYPE_SESSION (ck_session_get_type ())
@@ -68,10 +70,15 @@ typedef enum
GQuark ck_session_error_quark (void);
GType ck_session_get_type (void);
+CkSession * ck_session_new_from_file (const char *ssid,
+ const char *path);
CkSession * ck_session_new (const char *ssid,
- const char *cookie);
+ const char *type,
+ const char *display_type_string,
+ GHashTable *display_variables);
CkSession * ck_session_new_with_parameters (const char *ssid,
- const char *cookie,
+ const GPtrArray *parameters);
+void ck_session_set_parameters (CkSession *session,
const GPtrArray *parameters);
void ck_session_dump (CkSession *session,
@@ -86,6 +93,15 @@ gboolean ck_session_set_active (CkSession *se
gboolean ck_session_set_is_local (CkSession *session,
gboolean is_local,
GError **error);
+gboolean ck_session_set_is_open (CkSession *session,
+ gboolean is_open,
+ GError **error);
+gboolean ck_session_set_ever_open (CkSession *session,
+ gboolean ever_open,
+ GError **error);
+gboolean ck_session_set_under_request (CkSession *session,
+ gboolean under_request,
+ GError **error);
gboolean ck_session_set_id (CkSession *session,
const char *ssid,
GError **error);
@@ -116,6 +132,11 @@ gboolean ck_session_set_remote_host_name (CkSession *se
gboolean ck_session_set_session_type (CkSession *session,
const char *type,
GError **error);
+gboolean ck_session_set_display_type (CkSession *session,
+ const char *type,
+ GError **error);
+GHashTable *ck_session_get_display_variables (CkSession *session);
+CkDisplayTemplate *ck_session_get_display_template (CkSession *session);
/* Exported methods */
@@ -132,6 +153,15 @@ gboolean ck_session_is_active (CkSession *se
gboolean ck_session_is_local (CkSession *session,
gboolean *local,
GError **error);
+gboolean ck_session_is_open (CkSession *session,
+ gboolean *open,
+ GError **error);
+gboolean ck_session_get_ever_open (CkSession *session,
+ gboolean *open,
+ GError **error);
+gboolean ck_session_get_under_request (CkSession *session,
+ gboolean *under_request,
+ GError **error);
gboolean ck_session_get_unix_user (CkSession *session,
guint *uid,
GError **error);
@@ -150,12 +180,18 @@ gboolean ck_session_get_login_session_id (CkSession *se
gboolean ck_session_get_session_type (CkSession *session,
char **type,
GError **error);
+gboolean ck_session_get_display_type (CkSession *session,
+ char **type,
+ GError **error);
gboolean ck_session_get_remote_host_name (CkSession *session,
char **host_name,
GError **error);
gboolean ck_session_get_creation_time (CkSession *session,
char **iso8601_datetime,
GError **error);
+gboolean ck_session_get_remove_on_close (CkSession *session,
+ gboolean *remove_on_close,
+ GError **error);
/*deprecated*/
gboolean ck_session_get_user (CkSession *session,
guint *uid,
@@ -171,6 +207,12 @@ gboolean ck_session_get_idle_since_hint (CkSession *se
gboolean ck_session_set_idle_hint (CkSession *session,
gboolean idle_hint,
DBusGMethodInvocation *context);
+gboolean session_set_remove_on_close (CkSession *session,
+ gboolean remove_on_close,
+ GError **error);
+gboolean ck_session_set_remove_on_close (CkSession *session,
+ gboolean remove_on_close,
+ DBusGMethodInvocation *context);
/* Privileged actions */
gboolean ck_session_activate (CkSession *session,
diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml
index f903b55..34a6d04 100644
--- a/src/org.freedesktop.ConsoleKit.Manager.xml
+++ b/src/org.freedesktop.ConsoleKit.Manager.xml
@@ -160,6 +160,23 @@
+
+
+
+ an array of unmanaged Seat IDs
+
+
+
+
+ This gets a list of the unmanaged Seats
+ that are statically configured under /etc/ConsoleKit/seats.d
+ Each Seat ID is an D-Bus object path for the object that implements the
+ Seat interface.
+
+ org.freedesktop.ConsoleKit.Seat
+
+
+
@@ -310,12 +327,115 @@
+
+
+
+ The type of seat to add
+
+
+
+
+ The Seat ID of the added seat
+
+
+
+
+ This method is to create a new seat
+
+
+
+
+
+
+
+ The type of seat to add
+
+
+
+
+ The Seat ID of to be added seat
+
+
+
+
+ This method is to create a new seat by specify given sid
+
+
+
+
+
+
+
+
+ The Seat ID of the seat to remove
+
+
+
+
+ This method is to remove a seat
+
+
+
+
+
+
+
+
+ The seat to add the session to
+
+
+
+
+ The type of session to run (e.g. "LoginWindow", "Chooser", etc)
+
+
+
+
+ The name of the display type to use (defined in displays.d)
+
+
+
+
+ Session type specific parameters
+
+
+
+
+ Session ID
+
+
+
+
+ Request a new session gets added to seat.
+
+
+
+
+
+
+
+ The session id of the session to remove
+
+
+
+
+ This method is to remove a session from a seat
+
+
+
+
+
The Seat ID for the added seat
+
+
+ The type of seat added.
+
+
Emitted when a Seat has been added to the system.
diff --git a/src/org.freedesktop.ConsoleKit.Seat.xml b/src/org.freedesktop.ConsoleKit.Seat.xml
index d95990b..1f6c46f 100644
--- a/src/org.freedesktop.ConsoleKit.Seat.xml
+++ b/src/org.freedesktop.ConsoleKit.Seat.xml
@@ -100,6 +100,24 @@ seat at a time.
+
+
+
+
+ Attempt to create unmanaged sessions for this seat.
+
+
+
+
+
+
+
+
+ Stop managing seat.
+
+
+
+
@@ -160,5 +178,61 @@ seat at a time.
+
+
+
+ The session id of the session to add
+
+
+
+
+ The type of session to run (e.g. "LoginWindow", "Chooser", etc)
+
+
+
+
+ The name of display template
+
+
+
+
+ Session type specific parameters
+
+
+
+
+ The type of display to use (e.g. "X11", "Command", "XDMCP", etc)
+
+
+
+
+ Display type specific parameters
+
+
+
+
+ Emitted when a new session should get added to the seat.
+
+
+
+
+
+
+ The session id of the session to remove
+
+
+
+
+ Emitted when a session with given display number need to be removed.
+
+
+
+
+
+
+ Emitted when seat needs to get removed.
+
+
+
diff --git a/src/org.freedesktop.ConsoleKit.Session.xml b/src/org.freedesktop.ConsoleKit.Session.xml
index b6e1cdb..2652058 100644
--- a/src/org.freedesktop.ConsoleKit.Session.xml
+++ b/src/org.freedesktop.ConsoleKit.Session.xml
@@ -52,6 +52,19 @@
session-type
+
+
+
+ Display type
+
+
+
+
+ Returns the display type of the session.
+
+ display-type
+
+
@@ -174,6 +187,18 @@
is-local
+
+
+
+ TRUE if the session is open, otherwise FALSE
+
+
+
+ Returns whether the session is open
+
+ is-open
+
+
@@ -275,6 +300,21 @@
+
+
+
+
+ boolean value to set the remove-on-close to
+
+
+
+
+ This may be used by the session to indicate that
+ it should be respawn or not when it is closed.
+
+
+
+
@@ -317,6 +357,19 @@
+
+
+
+ The id of the session.
+
+ The object path of the session. Typically this is set by a session leader during a call to the
+ OpenSessionWithParameters method, when
+ opening a session in response to the OpenSessionRequest
+ signal.
+
+
+
+
@@ -342,6 +395,16 @@
+
+
+
+ The display type of the session.
+ Indicate the display template name. All the display template configuration
+ files are under /etc/ConsoleKit/displays.d/.
+
+
+
+
@@ -396,6 +459,19 @@
+
+
+
+
+ Whether the session is open
+ Sessions added from static configuration or in direct response to a call to
+ the AddSession method are initialally
+ closed and aren't open until a call to the OpenSessionWithParameters
+ method.
+
+
+
+
@@ -408,6 +484,14 @@
+
+
+
+
+ Whether the session is dynamic
+
+
+
@@ -430,6 +514,14 @@
+
+
+
+
+ Whether the session respawn when it is closed
+
+
+
diff --git a/src/strverscmp.c b/src/strverscmp.c
new file mode 100644
index 0000000..f077651
--- /dev/null
+++ b/src/strverscmp.c
@@ -0,0 +1,131 @@
+/* Compare strings while treating digits characters numerically.
+ Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jean-François Bignolles , 1997.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#if !_LIBC
+# include
+#endif
+
+#include
+#include
+
+/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
+ fractional parts, S_Z: idem but with leading Zeroes only */
+#define S_N 0x0
+#define S_I 0x4
+#define S_F 0x8
+#define S_Z 0xC
+
+/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
+#define CMP 2
+#define LEN 3
+
+
+/* ISDIGIT differs from isdigit, as follows:
+ - Its arg may be any int or unsigned int; it need not be an unsigned char
+ or EOF.
+ - It's typically faster.
+ POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to
+ isdigit unless it's important to use the locale's definition
+ of `digit' even when the host does not conform to POSIX. */
+#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
+
+#undef __strverscmp
+#undef strverscmp
+
+#ifndef weak_alias
+# define __strverscmp strverscmp
+#endif
+
+/* Compare S1 and S2 as strings holding indices/version numbers,
+ returning less than, equal to or greater than zero if S1 is less than,
+ equal to or greater than S2 (for more info, see the texinfo doc).
+*/
+
+int
+__strverscmp (const char *s1, const char *s2)
+{
+ const unsigned char *p1 = (const unsigned char *) s1;
+ const unsigned char *p2 = (const unsigned char *) s2;
+ unsigned char c1, c2;
+ int state;
+ int diff;
+
+ /* Symbol(s) 0 [1-9] others (padding)
+ Transition (10) 0 (01) d (00) x (11) - */
+ static const unsigned int next_state[] =
+ {
+ /* state x d 0 - */
+ /* S_N */ S_N, S_I, S_Z, S_N,
+ /* S_I */ S_N, S_I, S_I, S_I,
+ /* S_F */ S_N, S_F, S_F, S_F,
+ /* S_Z */ S_N, S_F, S_Z, S_Z
+ };
+
+ static const int result_type[] =
+ {
+ /* state x/x x/d x/0 x/- d/x d/d d/0 d/-
+ 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */
+
+ /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_I */ CMP, -1, -1, CMP, 1, LEN, LEN, CMP,
+ 1, LEN, LEN, CMP, CMP, CMP, CMP, CMP,
+ /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
+ CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
+ /* S_Z */ CMP, 1, 1, CMP, -1, CMP, CMP, CMP,
+ -1, CMP, CMP, CMP
+ };
+
+ if (p1 == p2)
+ return 0;
+
+ c1 = *p1++;
+ c2 = *p2++;
+ /* Hint: '0' is a digit too. */
+ state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0));
+
+ while ((diff = c1 - c2) == 0 && c1 != '\0')
+ {
+ state = next_state[state];
+ c1 = *p1++;
+ c2 = *p2++;
+ state |= (c1 == '0') + (ISDIGIT (c1) != 0);
+ }
+
+ state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))];
+
+ switch (state)
+ {
+ case CMP:
+ return diff;
+
+ case LEN:
+ while (ISDIGIT (*p1++))
+ if (!ISDIGIT (*p2++))
+ return 1;
+
+ return ISDIGIT (*p2) ? -1 : diff;
+
+ default:
+ return state;
+ }
+}
+#ifdef weak_alias
+weak_alias (__strverscmp, strverscmp)
+#endif
diff --git a/src/strverscmp.h b/src/strverscmp.h
new file mode 100644
index 0000000..48670c8
--- /dev/null
+++ b/src/strverscmp.h
@@ -0,0 +1,25 @@
+/* Compare strings while treating digits characters numerically.
+ Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc.
+ This file is part of the GNU C Library.
+ Contributed by Jean-François Bignolles , 1997.
+
+ This program is free software; you can redistribute it and/or modify
+ it under the terms of the GNU General Public License as published by
+ the Free Software Foundation; either version 2, or (at your option)
+ any later version.
+
+ This program 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 General Public License for more details.
+
+ You should have received a copy of the GNU General Public License along
+ with this program; if not, write to the Free Software Foundation,
+ Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */
+
+#ifndef STRVERSCMP_H_
+# define STRVERSCMP_H_
+
+int strverscmp (const char *, const char *);
+
+#endif /* not STRVERSCMP_H_ */
diff --git a/tools/Makefile.am b/tools/Makefile.am
index 13c191f..fa16c68 100644
--- a/tools/Makefile.am
+++ b/tools/Makefile.am
@@ -54,6 +54,7 @@ sbin_PROGRAMS = \
ck-log-system-start \
ck-log-system-restart \
ck-log-system-stop \
+ ck-seat-tool \
$(NULL)
ck_launch_session_SOURCES = \
@@ -83,6 +84,14 @@ ck_history_LDADD = \
$(top_builddir)/src/libck-event-log.la \
$(NULL)
+ck_seat_tool_SOURCES = \
+ ck-seat-tool.c \
+ $(NULL)
+
+ck_seat_tool_LDADD = \
+ $(CONSOLE_KIT_LIBS) \
+ $(NULL)
+
ck_log_system_start_SOURCES = \
ck-log-system-start.c \
$(NULL)
diff --git a/tools/ck-seat-tool.c b/tools/ck-seat-tool.c
new file mode 100644
index 0000000..0879d0d
--- /dev/null
+++ b/tools/ck-seat-tool.c
@@ -0,0 +1,443 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2009 Sun Microsystems, Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License as
+ * published by the Free Software Foundation; either version 2 of the
+ * License, or (at your option) any later version.
+ *
+ * This program 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
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
+ * 02111-1307, USA.
+ *
+ * Authors: Halton Huo
+ *
+ */
+
+#include "config.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#define CK_NAME "org.freedesktop.ConsoleKit"
+#define CK_PATH "/org/freedesktop/ConsoleKit"
+#define CK_INTERFACE "org.freedesktop.ConsoleKit"
+#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager"
+#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
+#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
+#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+
+#define CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
+
+#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
+#define CK_PATH_PREFIX "/org/freedesktop/ConsoleKit/"
+
+static gboolean add = FALSE;
+static gboolean delete = FALSE;
+static gboolean show_version = FALSE;
+static char *session_type = NULL;
+static char *display_type = NULL;
+static char *seat_id = NULL;
+static char *session_id = NULL;
+static gchar **remaining_args = NULL;
+
+static const GOptionEntry options [] = {
+ { "add", 'a', 0, G_OPTION_ARG_NONE, &add, N_("Add a new session"), NULL},
+ { "session-type", '\0', 0, G_OPTION_ARG_STRING, &session_type, N_("Specify session type when adding a session. Default is LoginWindow."), NULL},
+ { "display-type", '\0', 0, G_OPTION_ARG_STRING, &display_type, N_("Specify display type under /ConsoleKit/displays.d/ when adding a session."), NULL},
+ { "seat-id", '\0', 0, G_OPTION_ARG_STRING, &seat_id, N_("Specify seat id when adding a session. If not given, create a new seat."), NULL},
+ { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining_args, N_("Specify values of variables in display type. For example display=:10"), NULL },
+ { "delete", 'd', 0, G_OPTION_ARG_NONE, &delete, N_("Delete a session"), NULL},
+ { "session-id", '\0', 0, G_OPTION_ARG_STRING, &session_id, N_("Specify session id when deleting a session"), NULL},
+ { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
+ { NULL }
+};
+
+static void
+add_session (DBusGConnection *connection)
+{
+ DBusGProxy *mgr_proxy = NULL;
+ DBusGProxy *seat_proxy = NULL;
+ GError *error = NULL;
+ gboolean res;
+ char *sid = NULL;
+ GPtrArray *seats;
+ char *ssid = NULL;
+ int i;
+ gboolean found;
+ char *sstype = NULL;
+ GHashTable *variables = NULL;
+
+ if (! IS_STR_SET (session_type)) {
+ sstype = g_strdup ("LoginWindow");
+ } else {
+ sstype = g_strdup (session_type);
+ }
+
+ mgr_proxy = dbus_g_proxy_new_for_name (connection,
+ CK_NAME,
+ CK_MANAGER_PATH,
+ CK_MANAGER_INTERFACE);
+ if (mgr_proxy == NULL) {
+ return;
+ }
+
+ if (! IS_STR_SET(seat_id)) {
+
+ /* If seat id is not given, create a new seat */
+ error = NULL;
+ res = dbus_g_proxy_call (mgr_proxy,
+ "AddSeat",
+ &error,
+ G_TYPE_STRING, "Default",
+ G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &sid,
+ G_TYPE_INVALID);
+ if (!res) {
+ g_warning ("Unable to add seat: %s", error->message);
+ g_error_free (error);
+ g_object_unref (mgr_proxy);
+ return;
+ }
+
+ } else {
+ if (!g_str_has_prefix (seat_id, CK_PATH_PREFIX)) {
+ sid = g_strdup_printf ("%s%s", CK_PATH_PREFIX, seat_id);
+ } else {
+ sid = g_strdup (seat_id);
+ }
+ /* Check whether seat is existing, if not, try to create it. */
+
+ error = NULL;
+ res = dbus_g_proxy_call (mgr_proxy,
+ "GetSeats",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+ &seats,
+ G_TYPE_INVALID);
+ if (!res) {
+ g_warning ("Unable to get seat list: %s", error->message);
+ g_error_free (error);
+ g_object_unref (mgr_proxy);
+ return;
+ }
+
+ found = FALSE;
+ for (i = 0; i < seats->len; i++) {
+ char *tmp_sid;
+
+ tmp_sid = g_ptr_array_index (seats, i);
+ if (g_str_equal (sid, tmp_sid)) {
+ found = TRUE;
+ g_free (tmp_sid);
+ break;
+ }
+
+ g_free (tmp_sid);
+ }
+
+ if (! found) {
+ error = NULL;
+ res = dbus_g_proxy_call (mgr_proxy,
+ "AddSeatById",
+ &error,
+ G_TYPE_STRING, "Default",
+ DBUS_TYPE_G_OBJECT_PATH, sid,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ if (!res) {
+ g_warning ("Unable to add seat: %s", error->message);
+ g_error_free (error);
+ g_object_unref (mgr_proxy);
+ return;
+ }
+ }
+ }
+
+ seat_proxy = dbus_g_proxy_new_for_name (connection,
+ CK_NAME,
+ sid,
+ CK_SEAT_INTERFACE);
+
+ if (seat_proxy == NULL) {
+ g_warning ("Failed to talk to seat '%s'", sid);
+ g_object_unref (mgr_proxy);
+ return;
+ }
+
+ variables = g_hash_table_new_full (g_str_hash, g_str_equal,
+ (GDestroyNotify) g_free,
+ (GDestroyNotify) g_free);
+
+ if (remaining_args) {
+ for (i = 0; i < G_N_ELEMENTS (remaining_args); i++) {
+ char **arr;
+
+ /* split var=value */
+ arr = g_strsplit (remaining_args [i], "=", 2);
+ if (arr[0] && arr[1]) {
+ g_hash_table_insert (variables,
+ g_strdup(arr[0]),
+ g_strdup (arr[1]));
+ }
+ g_strfreev (arr);
+ }
+ }
+
+ error = NULL;
+ res = dbus_g_proxy_call (mgr_proxy,
+ "AddSession",
+ &error,
+ DBUS_TYPE_G_OBJECT_PATH, sid,
+ G_TYPE_STRING, sstype,
+ G_TYPE_STRING, display_type,
+ CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE, variables,
+ G_TYPE_INVALID,
+ DBUS_TYPE_G_OBJECT_PATH, &ssid,
+ G_TYPE_INVALID);
+
+ if (!res) {
+ g_warning ("Unable to add dynamic session: %s", error->message);
+ g_error_free (error);
+ } else {
+ dbus_g_proxy_call_no_reply (seat_proxy,
+ "Manage",
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ g_print ("Seat %s with session %s has been added\n", sid, ssid);
+ }
+
+ g_object_unref (seat_proxy);
+ g_object_unref (mgr_proxy);
+}
+
+static gboolean
+is_session_on_seat (DBusGConnection *connection,
+ const char *sid,
+ const char *ssid,
+ gboolean *is_last_session)
+{
+
+ DBusGProxy *seat_proxy = NULL;
+ GPtrArray *sessions = NULL;
+ char *ssid_tmp = NULL;
+ gboolean res;
+ gboolean retval = FALSE;
+ int i;
+ GError *error = NULL;
+
+ seat_proxy = dbus_g_proxy_new_for_name (connection,
+ CK_NAME,
+ sid,
+ CK_SEAT_INTERFACE);
+
+ if (seat_proxy == NULL) {
+ g_warning ("Failed to talk to seat '%s'", sid);
+ return FALSE;
+ }
+
+ error = NULL;
+ res = dbus_g_proxy_call (seat_proxy,
+ "GetSessions",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+ &sessions,
+ G_TYPE_INVALID);
+ if (! res) {
+ g_warning ("Failed to get list of sessions for %s: %s", sid, error->message);
+ g_error_free (error);
+ g_object_unref (seat_proxy);
+ return FALSE;
+ }
+
+ for (i = 0; i < sessions->len; i++) {
+
+ ssid_tmp = g_ptr_array_index (sessions, i);
+
+ if (g_str_equal (ssid, ssid_tmp)) {
+ retval = TRUE;
+ break;
+ }
+
+ g_free (ssid_tmp);
+ ssid_tmp = NULL;
+ }
+
+ if (is_last_session != NULL) {
+ *is_last_session = sessions->len == 1;
+ }
+
+ g_ptr_array_free (sessions, TRUE);
+ g_object_unref (seat_proxy);
+
+ return retval;
+}
+
+static char *
+find_seat_id_from_session_id (DBusGConnection *connection,
+ DBusGProxy *proxy,
+ const char *ssid,
+ gboolean *is_last_session)
+{
+ GError *error;
+ GPtrArray *seats;
+ int i;
+ char *sid;
+ gboolean res;
+
+ error = NULL;
+ res = dbus_g_proxy_call (proxy,
+ "GetSeats",
+ &error,
+ G_TYPE_INVALID,
+ dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
+ &seats,
+ G_TYPE_INVALID);
+
+ if (! res) {
+ g_warning ("Failed to get list of seats: %s", error->message);
+ g_error_free (error);
+ return NULL;
+ }
+
+ for (i = 0; i < seats->len; i++) {
+
+ sid = g_ptr_array_index (seats, i);
+ if (is_session_on_seat (connection, sid, ssid, is_last_session)) {
+ break;
+ }
+
+ g_free (sid);
+ }
+ g_ptr_array_free (seats, TRUE);
+
+ return sid;
+}
+
+static void
+delete_session (DBusGConnection *connection)
+{
+ DBusGProxy *proxy;
+ char *ssid;
+ char *sid;
+ gboolean is_last_session;
+
+ if (!g_str_has_prefix (session_id, CK_PATH_PREFIX)) {
+ ssid = g_strdup_printf ("%s%s", CK_PATH_PREFIX, session_id);
+ } else {
+ ssid = g_strdup (session_id);
+ }
+
+ proxy = dbus_g_proxy_new_for_name (connection,
+ CK_NAME,
+ CK_MANAGER_PATH,
+ CK_MANAGER_INTERFACE);
+ if (proxy == NULL) {
+ return;
+ }
+
+ sid = find_seat_id_from_session_id (connection, proxy, ssid, &is_last_session);
+
+ dbus_g_proxy_call_no_reply (proxy,
+ "RemoveSession",
+ DBUS_TYPE_G_OBJECT_PATH, ssid,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+
+ if (is_last_session) {
+ dbus_g_proxy_call_no_reply (proxy,
+ "RemoveSeat",
+ DBUS_TYPE_G_OBJECT_PATH, sid,
+ G_TYPE_INVALID,
+ G_TYPE_INVALID);
+ }
+
+ g_object_unref (proxy);
+}
+
+int
+main (int argc, char *argv[])
+{
+ DBusGConnection *connection;
+ GOptionContext *ctx;
+ GError *error = NULL;
+ gboolean res;
+
+ g_type_init ();
+
+ /* Option parsing */
+ ctx = g_option_context_new (_("- Manage dynamic sessions"));
+ g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
+ res = g_option_context_parse (ctx, &argc, &argv, &error);
+
+ if (!res) {
+ if (error) {
+ g_warning ("%s", error->message);
+ g_error_free (error);
+ }
+ exit (1);
+ }
+
+ g_option_context_free (ctx);
+
+ if (show_version) {
+ g_print ("%s %s\n", argv[0], VERSION);
+ exit (0);
+ }
+
+ if (add && delete) {
+ g_warning ("Can not specify -a and -d at the same time!");
+ exit (1);
+ }
+
+ if (!add && !delete) {
+ g_warning ("Must specify -a, -d!");
+ exit (1);
+ }
+
+ if (delete && (! IS_STR_SET (session_id))) {
+ g_warning ("You must specify session id for deleting a session. You can get all sessions by ck-list-sessions");
+ exit (1);
+ }
+
+ if (add && (! IS_STR_SET (display_type)) ) {
+ g_warning ("You must specify display type for adding a session. You can get all display types under /ConsoleKit/displays.d/");
+ g_warning ("Invalid display type!");
+ exit (1);
+ }
+
+ error = NULL;
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (connection == NULL) {
+ g_message ("Failed to connect to the D-Bus daemon: %s", error->message);
+ g_error_free (error);
+ exit (1);
+ }
+
+
+ if (add) {
+ add_session (connection);
+ } else if (delete) {
+ delete_session (connection);
+ } else {
+ g_warning ("Invaild parameters!");
+ exit (1);
+ }
+
+ return 0;
+}
diff --git a/tools/list-sessions.c b/tools/list-sessions.c
index 3933772..cc69d57 100644
--- a/tools/list-sessions.c
+++ b/tools/list-sessions.c
@@ -46,6 +46,23 @@
#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat"
#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
+
+typedef struct CkSessionOutput {
+ char *prop_name;
+ char *prop_value;
+} CkSessionOutput;
+
+static gboolean do_all = FALSE;
+static gboolean do_version = FALSE;
+static char *do_format = NULL;
+static GOptionEntry entries [] = {
+ { "all", 'a', 0, G_OPTION_ARG_NONE, &do_all, N_("List all sessions. If not given, only list open sessions"), NULL },
+ { "format", 'f', 0, G_OPTION_ARG_STRING, &do_format, N_("Prints information according to the given format"), NULL },
+ { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL },
+ { NULL }
+};
+
static gboolean
get_uint (DBusGProxy *proxy,
const char *method,
@@ -176,6 +193,7 @@ list_session (DBusGConnection *connection,
char *sid;
char *lsid;
char *session_type;
+ char *display_type;
char *x11_display;
char *x11_display_device;
char *display_device;
@@ -184,8 +202,11 @@ list_session (DBusGConnection *connection,
char *idle_since_hint;
gboolean is_active;
gboolean is_local;
+ gboolean is_open;
char *short_sid;
const char *short_ssid;
+ char **format_arr = NULL;
+ int i, j;
proxy = dbus_g_proxy_new_for_name (connection,
CK_NAME,
@@ -198,6 +219,7 @@ list_session (DBusGConnection *connection,
sid = NULL;
lsid = NULL;
session_type = NULL;
+ display_type = NULL;
x11_display = NULL;
x11_display_device = NULL;
display_device = NULL;
@@ -209,15 +231,21 @@ list_session (DBusGConnection *connection,
get_path (proxy, "GetSeatId", &sid);
get_string (proxy, "GetLoginSessionId", &lsid);
get_string (proxy, "GetSessionType", &session_type);
+ get_string (proxy, "GetDisplayType", &display_type);
get_string (proxy, "GetX11Display", &x11_display);
get_string (proxy, "GetX11DisplayDevice", &x11_display_device);
get_string (proxy, "GetDisplayDevice", &display_device);
get_string (proxy, "GetRemoteHostName", &remote_host_name);
+ get_boolean (proxy, "IsOpen", &is_open);
get_boolean (proxy, "IsActive", &is_active);
get_boolean (proxy, "IsLocal", &is_local);
get_string (proxy, "GetCreationTime", &creation_time);
get_string (proxy, "GetIdleSinceHint", &idle_since_hint);
+ if (!do_all && !is_open) {
+ return;
+ }
+
realname = get_real_name (uid);
short_sid = sid;
@@ -230,24 +258,49 @@ list_session (DBusGConnection *connection,
short_ssid = ssid + strlen (CK_PATH) + 1;
}
- printf ("%s:\n\tunix-user = '%d'\n\trealname = '%s'\n\tseat = '%s'\n\tsession-type = '%s'\n\tactive = %s\n\tx11-display = '%s'\n\tx11-display-device = '%s'\n\tdisplay-device = '%s'\n\tremote-host-name = '%s'\n\tis-local = %s\n\ton-since = '%s'\n\tlogin-session-id = '%s'",
- short_ssid,
- uid,
- realname,
- short_sid,
- session_type,
- is_active ? "TRUE" : "FALSE",
- x11_display,
- x11_display_device,
- display_device,
- remote_host_name,
- is_local ? "TRUE" : "FALSE",
- creation_time,
- lsid);
- if (idle_since_hint != NULL && idle_since_hint[0] != '\0') {
- printf ("\n\tidle-since-hint = '%s'", idle_since_hint);
+ CkSessionOutput output[] = {
+ {"session-id", g_strdup (short_ssid)},
+ {"unix-user", g_strdup_printf ("%d", uid)},
+ {"realname", g_strdup (realname)},
+ {"seat", g_strdup (short_sid)},
+ {"session-type", g_strdup (session_type)},
+ {"display-type", g_strdup (display_type)},
+ {"open", is_open ? "TRUE" : "FALSE"},
+ {"active", is_active ? "TRUE" : "FALSE"},
+ {"x11-display", g_strdup (x11_display)},
+ {"x11-display-device", g_strdup (x11_display_device)},
+ {"display-device", g_strdup (display_device)},
+ {"remote-host-name", g_strdup (remote_host_name)},
+ {"is-local", is_local ? "TRUE" : "FALSE"},
+ {"on-since", g_strdup (creation_time)},
+ {"login-session-id", g_strdup (lsid)},
+ {"idle-since-hint", g_strdup (idle_since_hint)},
+ };
+
+ if (IS_STR_SET (do_format)) {
+ format_arr = g_strsplit (do_format, ",", -1);
+
+ for (i = 0; format_arr[i] != NULL; ++i) {
+ for (j = 0; j < G_N_ELEMENTS (output); j++) {
+ if (g_str_equal (format_arr[i], output[j].prop_name)) {
+ printf ("'%s'\t", output[j].prop_value);
+ break;
+ }
+ }
+ }
+ printf ("\n");
+ g_strfreev (format_arr);
+
+ } else {
+ for (j = 0; j < G_N_ELEMENTS (output); j++) {
+ if (g_str_equal (output[j].prop_name, "session-id"))
+ printf ("%s:\n", output[j].prop_value);
+ else
+ printf ("\t%s = '%s'\n",
+ output[j].prop_name,
+ output[j].prop_value);
+ }
}
- printf ("\n");
g_free (idle_since_hint);
g_free (creation_time);
@@ -256,9 +309,11 @@ list_session (DBusGConnection *connection,
g_free (sid);
g_free (lsid);
g_free (session_type);
+ g_free (display_type);
g_free (x11_display);
g_free (x11_display_device);
g_free (display_device);
+
g_object_unref (proxy);
}
@@ -368,11 +423,6 @@ main (int argc,
GOptionContext *context;
gboolean retval;
GError *error = NULL;
- static gboolean do_version = FALSE;
- static GOptionEntry entries [] = {
- { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL },
- { NULL }
- };
g_type_init ();