diff --git a/configure.ac b/configure.ac index 6dbca0f..4225149 100644 --- a/configure.ac +++ b/configure.ac @@ -45,7 +45,7 @@ AC_CHECK_HEADERS(paths.h) AC_CHECK_HEADERS(sys/vt.h) AC_CHECK_HEADERS(sys/consio.h) -AC_CHECK_FUNCS(getpeerucred getpeereid) +AC_CHECK_FUNCS(getpeerucred getpeereid strrep) AC_TYPE_UID_T @@ -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 --------------------------------------------------------------------------- @@ -398,6 +410,7 @@ tools/linux/Makefile tools/freebsd/Makefile tools/solaris/Makefile data/Makefile +data/displays.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..472fd77 100644 --- a/data/00-primary.seat +++ b/data/00-primary.seat @@ -1,5 +1,35 @@ [Seat Entry] Version=1.0 Name=Primary seat +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 display type which defined in /ConsoleKit/displays-types.conf +DisplayType=Local + +# 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= + +# Display numbers list, separated by a separator character ';'. If want to +# automatically choose next available display number, indicate -1 +DisplayNumbers=0 + +# Values list to indicate whether the give DisplayNumbers are on console +# or not , separated by a separator character ';'. +IsConsoles=true + +# Values list to indicate the tty device number, separated by a separator +# character ';'. +# Zero or negative number or no value means choose next available vt number +TtyDevices= diff --git a/data/ConsoleKit.conf b/data/ConsoleKit.conf index ccbc500..b4e2f37 100644 --- a/data/ConsoleKit.conf +++ b/data/ConsoleKit.conf @@ -118,6 +118,9 @@ send_member="IsLocal"/> + $@ +RemoteMachine.disp: RemoteMachine.disp.in Makefile + sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@ +LocalVNC.disp: LocalVNC.disp.in Makefile + sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@ +Headless.disp: Headless.disp.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.disp.in b/data/displays.d/RemoteMachine.disp.in new file mode 100644 index 0000000..857d21f --- /dev/null +++ b/data/displays.d/RemoteMachine.disp.in @@ -0,0 +1,2 @@ +[Display] +Command=@X11_DIR@/Xorg $display -br -verbose -auth $auth -indirect $vt diff --git a/libck-connector/ck-connector.c b/libck-connector/ck-connector.c index 7f6f87f..ad8a111 100644 --- a/libck-connector/ck-connector.c +++ b/libck-connector/ck-connector.c @@ -76,9 +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 }, { "remote-host-name", DBUS_TYPE_STRING }, { "session-type", DBUS_TYPE_STRING }, { "is-local", DBUS_TYPE_BOOLEAN }, + { "is-dynamic", DBUS_TYPE_BOOLEAN }, { "unix-user", DBUS_TYPE_INT32 }, }; diff --git a/src/Makefile.am b/src/Makefile.am index cbe8a09..bd3ec70 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-type.h \ + ck-display-type.c \ ck-seat.h \ ck-seat.c \ ck-session-leader.h \ diff --git a/src/ck-display-type.c b/src/ck-display-type.c new file mode 100644 index 0000000..c02c1c9 --- /dev/null +++ b/src/ck-display-type.c @@ -0,0 +1,240 @@ +/* -*- 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. + * + */ + +#include "config.h" + +#include +#include + +#include "ck-display-type.h" + +#define CK_DISPLAY_TYPE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_DISPLAY_TYPE, CkDisplayTypePrivate)) + +#define CK_DISPLAY_TYPES_DIR SYSCONFDIR "/ConsoleKit/displays.d" + +struct CkDisplayTypePrivate +{ + char *name; + char *command; +}; + +enum { + PROP_0, + PROP_NAME, + PROP_COMMAND, + PROP_PRIORITY, +}; + +static void ck_display_type_class_init (CkDisplayTypeClass *klass); +static void ck_display_type_init (CkDisplayType *display); +static void ck_display_type_finalize (GObject *object); +static void ck_display_type_load (CkDisplayType *display); + +G_DEFINE_TYPE (CkDisplayType, ck_display_type, G_TYPE_OBJECT) + +static void +_ck_display_type_set_name (CkDisplayType *display, + const char *name) +{ + g_free (display->priv->name); + display->priv->name = g_strdup (name); +} + +static void +_ck_display_type_set_command (CkDisplayType *display, + const char *command) +{ + g_free (display->priv->command); + display->priv->command = g_strdup (command); +} + +static void +ck_display_type_set_property (GObject *object, + guint prop_id, + const GValue *value, + GParamSpec *pspec) +{ + CkDisplayType *self; + + self = CK_DISPLAY_TYPE (object); + + switch (prop_id) { + case PROP_NAME: + _ck_display_type_set_name (self, g_value_get_string (value)); + break; + case PROP_COMMAND: + _ck_display_type_set_command (self, g_value_get_string (value)); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +ck_display_type_get_property (GObject *object, + guint prop_id, + GValue *value, + GParamSpec *pspec) +{ + CkDisplayType *self; + + self = CK_DISPLAY_TYPE (object); + + switch (prop_id) { + case PROP_NAME: + g_value_set_string (value, self->priv->name); + break; + case PROP_COMMAND: + g_value_set_string (value, self->priv->command); + break; + default: + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); + break; + } +} + +static void +ck_display_type_class_init (CkDisplayTypeClass *klass) +{ + GObjectClass *object_class = G_OBJECT_CLASS (klass); + + object_class->get_property = ck_display_type_get_property; + object_class->set_property = ck_display_type_set_property; + object_class->finalize = ck_display_type_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_COMMAND, + g_param_spec_string ("command", + "X11 command", + "X11 command", + NULL, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); + g_type_class_add_private (klass, sizeof (CkDisplayTypePrivate)); +} + +static void +ck_display_type_init (CkDisplayType *display) +{ + display->priv = CK_DISPLAY_TYPE_GET_PRIVATE (display); + + display->priv->name = NULL; + display->priv->command = NULL; +} + +static void +ck_display_type_finalize (GObject *object) +{ + CkDisplayType *display; + + g_return_if_fail (object != NULL); + g_return_if_fail (CK_IS_DISPLAY_TYPE (object)); + + display = CK_DISPLAY_TYPE (object); + + g_return_if_fail (display->priv != NULL); + + g_free (display->priv->name); + g_free (display->priv->command); + + G_OBJECT_CLASS (ck_display_type_parent_class)->finalize (object); +} + +static void +ck_display_type_load (CkDisplayType *display) +{ + GKeyFile *key_file; + const char *name; + char *filename; + char *command; + gboolean res; + GError *error; + + name = ck_display_type_get_name (display); + + g_return_if_fail (name && !g_str_equal (name, "")); + + filename = g_strdup_printf ("%s/%s.disp", CK_DISPLAY_TYPES_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; + } + g_free (filename); + + error = NULL; + command = g_key_file_get_string (key_file, "Display", "Command", &error); + if (error) { + /* Use NULL if key Command is not defined */ + g_warning ("Unable to load key Command for display type %s, use default value NULL: %s", name, error->message); + g_error_free (error); + } + + + _ck_display_type_set_command (display, command); + + g_key_file_free (key_file); +} + +CkDisplayType * +ck_display_type_new (const char *name) +{ + GObject *object; + + object = g_object_new (CK_TYPE_DISPLAY_TYPE, + "name", name, + NULL); + + ck_display_type_load (CK_DISPLAY_TYPE (object)); + + return CK_DISPLAY_TYPE (object); +} + +G_CONST_RETURN char* +ck_display_type_get_name (CkDisplayType *display) +{ + g_return_val_if_fail (CK_IS_DISPLAY_TYPE (display), NULL); + + return display->priv->name; +} + +G_CONST_RETURN char* +ck_display_type_get_command (CkDisplayType *display) +{ + g_return_val_if_fail (CK_IS_DISPLAY_TYPE (display), NULL); + + return display->priv->command; +} diff --git a/src/ck-display-type.h b/src/ck-display-type.h new file mode 100644 index 0000000..1b290f7 --- /dev/null +++ b/src/ck-display-type.h @@ -0,0 +1,56 @@ +/* -*- 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_TYPE_H +#define __CK_DISPLAY_TYPE_H + +#include + +G_BEGIN_DECLS + +#define CK_TYPE_DISPLAY_TYPE (ck_display_type_get_type ()) +#define CK_DISPLAY_TYPE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_DISPLAY_TYPE, CkDisplayType)) +#define CK_DISPLAY_TYPE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_DISPLAY_TYPE, CkDisplayTypeClass)) +#define CK_IS_DISPLAY_TYPE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_DISPLAY_TYPE)) +#define CK_IS_DISPLAY_TYPE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_DISPLAY_TYPE)) +#define CK_DISPLAY_TYPE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_DISPLAY_TYPE, CkDisplayTypeClass)) + +typedef struct CkDisplayTypePrivate CkDisplayTypePrivate; + +typedef struct +{ + GObject parent; + CkDisplayTypePrivate *priv; +} CkDisplayType; + +typedef struct +{ + GObjectClass parent_class; +} CkDisplayTypeClass; + +GType ck_display_type_get_type (void); +CkDisplayType * ck_display_type_new (const char *name); +G_CONST_RETURN char * ck_display_type_get_name (CkDisplayType *display); +G_CONST_RETURN char * ck_display_type_get_command (CkDisplayType *display); + +G_END_DECLS + +#endif /* __CK_DISPLAY_TYPE_H */ diff --git a/src/ck-log-event.c b/src/ck-log-event.c index 965a036..203c058 100644 --- a/src/ck-log-event.c +++ b/src/ck-log-event.c @@ -213,6 +213,7 @@ event_seat_session_added_copy (CkLogSeatSessionAddedEvent *event, event_copy->session_display_device = g_strdup (event->session_display_device); event_copy->session_remote_host_name = g_strdup (event->session_remote_host_name); event_copy->session_is_local = event->session_is_local; + event_copy->session_is_dynamic = event->session_is_dynamic; event_copy->session_unix_user = event->session_unix_user; event_copy->session_creation_time = g_strdup (event->session_creation_time); } @@ -232,6 +233,7 @@ event_seat_session_removed_copy (CkLogSeatSessionRemovedEvent *event, event_copy->session_display_device = g_strdup (event->session_display_device); event_copy->session_remote_host_name = g_strdup (event->session_remote_host_name); event_copy->session_is_local = event->session_is_local; + event_copy->session_is_dynamic = event->session_is_dynamic; event_copy->session_unix_user = event->session_unix_user; event_copy->session_creation_time = g_strdup (event->session_creation_time); } @@ -410,7 +412,7 @@ add_log_for_seat_session_added (GString *str, 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' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-is-dynamic=%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 : "", @@ -419,6 +421,7 @@ add_log_for_seat_session_added (GString *str, e->session_display_device ? e->session_display_device : "", e->session_remote_host_name ? e->session_remote_host_name : "", e->session_is_local ? "TRUE" : "FALSE", + e->session_is_dynamic ? "TRUE" : "FALSE", e->session_unix_user, e->session_creation_time ? e->session_creation_time : ""); } @@ -431,7 +434,7 @@ add_log_for_seat_session_removed (GString *str, 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' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-is-dynamic=%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 : "", @@ -440,6 +443,7 @@ add_log_for_seat_session_removed (GString *str, e->session_display_device ? e->session_display_device : "", e->session_remote_host_name ? e->session_remote_host_name : "", e->session_is_local ? "TRUE" : "FALSE", + e->session_is_dynamic ? "TRUE" : "FALSE", e->session_unix_user, e->session_creation_time ? e->session_creation_time : ""); } @@ -899,7 +903,7 @@ parse_log_for_seat_session_added (const GString *str, } 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 ]*)' 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-is-dynamic=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error); if (re == NULL) { g_warning (error->message); goto out; @@ -931,6 +935,14 @@ parse_log_for_seat_session_added (const GString *str, } g_free (tmp); + tmp = g_match_info_fetch_named (match_info, "sessionisdynamic"); + if (tmp != NULL && strcmp (tmp, "TRUE") == 0) { + e->session_is_dynamic = TRUE; + } else { + e->session_is_dynamic = FALSE; + } + g_free (tmp); + tmp = g_match_info_fetch_named (match_info, "sessionunixuser"); if (tmp != NULL) { gulong l; @@ -974,7 +986,7 @@ parse_log_for_seat_session_removed (const GString *str, } 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 ]*)' 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-is-dynamic=(?P[a-zA-Z]*) session-unix-user=(?P[0-9]*) session-creation-time='(?P[^']*)'", 0, 0, &error); if (re == NULL) { g_warning (error->message); goto out; @@ -1006,6 +1018,14 @@ parse_log_for_seat_session_removed (const GString *str, } g_free (tmp); + tmp = g_match_info_fetch_named (match_info, "sessionisdynamic"); + if (tmp != NULL && strcmp (tmp, "TRUE") == 0) { + e->session_is_dynamic= TRUE; + } else { + e->session_is_dynamic = FALSE; + } + g_free (tmp); + tmp = g_match_info_fetch_named (match_info, "sessionunixuser"); if (tmp != NULL) { gulong l; diff --git a/src/ck-log-event.h b/src/ck-log-event.h index 0c04c1d..6d600b7 100644 --- a/src/ck-log-event.h +++ b/src/ck-log-event.h @@ -85,6 +85,7 @@ typedef struct 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; @@ -99,6 +100,7 @@ typedef struct 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; diff --git a/src/ck-manager.c b/src/ck-manager.c index bcb9350..1119e95 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -49,6 +49,7 @@ #include "ck-manager.h" #include "ck-manager-glue.h" #include "ck-seat.h" +#include "ck-display-type.h" #include "ck-session-leader.h" #include "ck-session.h" #include "ck-marshal.h" @@ -522,6 +523,7 @@ log_seat_session_added_event (CkManager *manager, "display-device", &event.event.seat_session_added.session_display_device, "remote-host-name", &event.event.seat_session_added.session_remote_host_name, "is-local", &event.event.seat_session_added.session_is_local, + "is-dynamic", &event.event.seat_session_added.session_is_dynamic, "unix-user", &event.event.seat_session_added.session_unix_user, NULL); ck_session_get_creation_time (session, &event.event.seat_session_added.session_creation_time, NULL); @@ -577,6 +579,7 @@ log_seat_session_removed_event (CkManager *manager, "display-device", &event.event.seat_session_removed.session_display_device, "remote-host-name", &event.event.seat_session_removed.session_remote_host_name, "is-local", &event.event.seat_session_removed.session_is_local, + "is-dynamic", &event.event.seat_session_removed.session_is_dynamic, "unix-user", &event.event.seat_session_removed.session_unix_user, NULL); ck_session_get_creation_time (session, &event.event.seat_session_removed.session_creation_time, NULL); @@ -779,6 +782,7 @@ new_polkit_session_from_session (CkManager *manager, uid_t uid; gboolean is_active; gboolean is_local; + gboolean is_dynamic; char *sid; char *ssid; char *remote_host; @@ -792,6 +796,7 @@ new_polkit_session_from_session (CkManager *manager, g_object_get (ck_session, "active", &is_active, "is-local", &is_local, + "is-dynamic", &is_dynamic, "id", &ssid, "unix-user", &uid, "remote-host-name", &remote_host, @@ -1596,57 +1601,17 @@ 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; - } - - if (is_static_x11 || is_static_text) { - char *sid; + char *sid = NULL; + + ck_session_get_seat_id (session, &sid, NULL); + + 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; } @@ -2635,6 +2600,30 @@ ck_manager_get_seats (CkManager *manager, 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.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_seat_ids, seats); + + return TRUE; +} + static void listify_session_ids (char *id, CkSession *session, @@ -2660,6 +2649,159 @@ ck_manager_get_sessions (CkManager *manager, return TRUE; } +static gboolean +_find_session_with_num (gpointer key, + gpointer value, + gpointer user_data) +{ + CkSession *session = CK_SESSION (value); + char *x11_display = NULL; + int *num = (int *) user_data; + char *str = NULL; + gboolean ret; + + g_object_get (session, "x11-display", &x11_display, NULL); + + if (! IS_STR_SET (x11_display)) { + g_free (x11_display); + return FALSE; + } + + str = g_strdup_printf (":%d", *num); + ret = g_str_equal (x11_display, str); + + g_free (x11_display); + g_free (str); + + return ret; +} + +/* + Example: + dbus-send --system --dest=org.freedesktop.ConsoleKit \ + --type=method_call --print-reply --reply-timeout=2000 \ + /org/freedesktop/ConsoleKit/Manager \ + org.freedesktop.ConsoleKit.Manager.CreateSession \ + int32:101 string:"Headless" string:"/dev/local" +*/ +gboolean +ck_manager_create_session (CkManager *manager, + gint32 display_number, + char *display_type, + char *tty_device, + DBusGMethodInvocation *context) +{ + CkSeat *seat; + CkSession *session = NULL; + + g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); + + /* Make sure this display_number is not avail */ + session = CK_SESSION (g_hash_table_find (manager->priv->sessions, + _find_session_with_num, + &display_number)); + + if (CK_IS_SESSION (session)) { + return TRUE; + } + + seat = add_new_seat (manager, CK_SEAT_KIND_DYNAMIC); + + ck_seat_set_display_type (seat, display_type); + + ck_seat_add_display (seat, display_number, TRUE, tty_device); + + return TRUE; +} + +static gboolean +_find_dynamic_session_with_num (gpointer key, + gpointer value, + gpointer user_data) +{ + CkSession *session = CK_SESSION (value); + char *x11_display = NULL; + gboolean is_dynamic = FALSE; + int *num = (int *) user_data; + char *str = NULL; + gboolean ret; + + g_object_get (session, "is-dynamic", &is_dynamic, NULL); + + if (is_dynamic == FALSE) + return FALSE; + + g_object_get (session, "x11-display", &x11_display, NULL); + + if (! IS_STR_SET (x11_display)) { + g_free (x11_display); + return FALSE; + } + + str = g_strdup_printf (":%d", *num); + ret = g_str_equal (x11_display, str); + + g_free (x11_display); + g_free (str); + + return ret; +} + +static gboolean +_find_seat_with_sid (gpointer key, + gpointer value, + gpointer user_data) +{ + return g_str_equal ((char* ) user_data, (char *) key); + +} + +/* + 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 \ + int32:101 +*/ +gboolean +ck_manager_remove_session (CkManager *manager, + gint32 display_number, + DBusGMethodInvocation *context) +{ + CkSession *session = NULL; + CkSeat *seat = NULL; + char *sid = NULL; + + g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); + + /* Make sure this display_number is avail and is-dynamic == TRUE */ + session = CK_SESSION (g_hash_table_find (manager->priv->sessions, + _find_dynamic_session_with_num, + &display_number)); + + if (! CK_IS_SESSION (session)) { + return FALSE; + } + + ck_session_get_seat_id (session, &sid, NULL); + if (! IS_STR_SET (sid)) { + return FALSE; + } + seat = CK_SEAT (g_hash_table_find (manager->priv->seats, + _find_seat_with_sid, + sid)); + g_free (sid); + + if (! CK_IS_SEAT (seat)) { + return FALSE; + } + + g_signal_emit_by_name (seat, "session-to-remove", display_number); + + return TRUE; +} + static void add_seat_for_file (CkManager *manager, const char *filename) @@ -2673,6 +2815,7 @@ add_seat_for_file (CkManager *manager, if (seat == NULL) { /* returns null if connection to bus fails */ g_free (sid); + manager->priv->seat_serial--; return; } @@ -2750,8 +2893,6 @@ ck_manager_init (CkManager *manager) (GDestroyNotify) g_object_unref); manager->priv->logger = ck_event_logger_new (LOG_FILE); - - create_seats (manager); } static void @@ -2796,6 +2937,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 45910b7..c4c307d 100644 --- a/src/ck-manager.h +++ b/src/ck-manager.h @@ -91,6 +91,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); @@ -123,6 +126,17 @@ gboolean ck_manager_open_session_with_parameters (CkManager const GPtrArray *parameters, DBusGMethodInvocation *context); +/* Dynamic related */ +gboolean ck_manager_create_session (CkManager *manager, + gint32 display_number, + char *display_type, + char *tty_device, + DBusGMethodInvocation *context); +gboolean ck_manager_remove_session (CkManager *manager, + gint32 display_number, + DBusGMethodInvocation *context); + + G_END_DECLS #endif /* __CK_MANAGER_H */ diff --git a/src/ck-marshal.list b/src/ck-marshal.list index f9eed10..b379620 100644 --- a/src/ck-marshal.list +++ b/src/ck-marshal.list @@ -1,2 +1,3 @@ VOID:UINT,STRING BOOLEAN:POINTER +VOID:BOOLEAN,STRING diff --git a/src/ck-seat.c b/src/ck-seat.c index c2f70da..486eae7 100644 --- a/src/ck-seat.c +++ b/src/ck-seat.c @@ -40,6 +40,7 @@ #include "ck-seat-glue.h" #include "ck-marshal.h" +#include "ck-display-type.h" #include "ck-session.h" #include "ck-vt-monitor.h" #include "ck-run-programs.h" @@ -50,11 +51,23 @@ #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') + +typedef struct +{ + gint num; + gboolean dynamic; + char *tty_device; +} DisplayData; struct CkSeatPrivate { char *id; CkSeatKind kind; + CkDisplayType *display_type; + GSList *displays; /* display_number - tty_device pair */ GHashTable *sessions; GPtrArray *devices; @@ -71,6 +84,8 @@ enum { SESSION_REMOVED, DEVICE_ADDED, DEVICE_REMOVED, + SESSION_TO_ADD, + SESSION_TO_REMOVE, LAST_SIGNAL }; @@ -300,6 +315,113 @@ ck_seat_activate_session (CkSeat *seat, return ret; } +#ifndef HAVE_STRREP +static void +strrep (char* in, char** out, char* old, char* new) +{ + char* temp; + char* orig = strdup(in); + char* found = strstr(orig, old); + if(!found) { + *out = malloc(strlen(orig) + 1); + strcpy(*out, orig); + return; + } + + int idx = found - orig; + + *out = realloc(*out, strlen(orig) - strlen(old) + strlen(new) + 1); + strncpy(*out, orig, idx); + strcpy(*out + idx, new); + strcpy(*out + idx + strlen(new), orig + idx + strlen(old)); + + + temp = malloc(idx+strlen(new)+1); + strncpy(temp,*out,idx+strlen(new)); + temp[idx + strlen(new)] = '\0'; + + strrep(found + strlen(old), out, old, new); + temp = realloc(temp, strlen(temp) + strlen(*out) + 1); + strcat(temp,*out); + free(*out); + *out = temp; +} +#endif + +static void +_create_display (gpointer data, + gpointer user_data) +{ + CkSeat *seat = CK_SEAT (user_data); + DisplayData *disp = (DisplayData *)data; + char *comm = NULL; + char *str = NULL; + + comm = g_strdup (ck_display_type_get_command (seat->priv->display_type)); + + /* subtitute $display */ + if (disp->num >= 0) { + str = g_strdup_printf (":%d", disp->num); + strrep (comm, &comm, "$display", str); + g_free (str); + } + + /* subtitute $vt */ + if (IS_STR_SET (disp->tty_device)) { + str = g_strdup_printf ("%s", disp->tty_device); + strrep (comm, &comm, "$vt", disp->tty_device); + g_free (str); + } else { + strrep (comm, &comm, "$vt", ""); + } + + g_signal_emit (seat, signals [SESSION_TO_ADD], 0, disp->dynamic, comm); + + g_free (comm); + +} + +gboolean +ck_seat_manage_seat (CkSeat *seat, + DBusGMethodInvocation *context) +{ + g_slist_foreach (seat->priv->displays, _create_display, seat); + return TRUE; +} + +gboolean +ck_seat_add_display (CkSeat *seat, + int num, + gboolean dynamic, + const char *tty) +{ + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); + + DisplayData *disp; + + disp = g_new0 (DisplayData, 1); + + disp->num = num; + disp->dynamic = dynamic; + disp->tty_device = g_strdup (tty); + + seat->priv->displays = g_slist_append (seat->priv->displays, disp); + + return TRUE; +} + +gboolean +ck_seat_set_display_type (CkSeat *seat, + char *type) +{ + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); + + g_object_unref (seat->priv->display_type); + seat->priv->display_type = ck_display_type_new (type); + + return TRUE; +} + static gboolean match_session_display_device (const char *key, CkSession *session, @@ -871,7 +993,7 @@ 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; default: G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); @@ -958,6 +1080,25 @@ ck_seat_class_init (CkSeatClass *klass) G_TYPE_NONE, 1, CK_TYPE_DEVICE); + signals [SESSION_TO_ADD] = g_signal_new ("session-to-add", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CkSeatClass, session_to_add), + NULL, + NULL, + ck_marshal_VOID__BOOLEAN_STRING, + G_TYPE_NONE, + 2, G_TYPE_BOOLEAN, G_TYPE_STRING); + signals [SESSION_TO_REMOVE] = g_signal_new ("session-to-remove", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CkSeatClass, session_to_remove), + NULL, + NULL, + g_cclosure_marshal_VOID__INT, + G_TYPE_NONE, + 1, G_TYPE_INT); + g_object_class_install_property (object_class, PROP_ID, g_param_spec_string ("id", @@ -989,6 +1130,16 @@ ck_seat_init (CkSeat *seat) g_free, (GDestroyNotify) g_object_unref); seat->priv->devices = g_ptr_array_new (); + seat->priv->displays = NULL; +} + +static void +free_display_data (gpointer data, + gpointer user_data) +{ + DisplayData *disp = (DisplayData *)data; + + g_free (disp->tty_device); } static void @@ -1011,9 +1162,13 @@ ck_seat_finalize (GObject *object) g_object_unref (seat->priv->active_session); } + g_slist_foreach (seat->priv->displays, free_display_data, NULL); + g_slist_free (seat->priv->displays); + g_ptr_array_free (seat->priv->devices, TRUE); g_hash_table_destroy (seat->priv->sessions); g_free (seat->priv->id); + g_object_unref (seat->priv->display_type); G_OBJECT_CLASS (ck_seat_parent_class)->finalize (object); } @@ -1068,20 +1223,45 @@ ck_seat_new_with_devices (const char *sid, return CK_SEAT (object); } +static char * +generate_new_tty_device (gboolean is_console, + gint vt) +{ + char *res = NULL; + /* if negative or zero means choose next available vt */ + if (vt <= 0) + return NULL; +#ifdef __sun + /* Linux and Solaris using different vt device name */ + res = g_strdup_printf ("/dev/vt/%d", vt); +#else + res = g_strdup_printf ("vt%d", vt); +#endif + return res; +} + CkSeat * ck_seat_new_from_file (const 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; + gboolean hidden; + char *str; + CkDisplayType *display_type; + GPtrArray *devices; + char **device_list; + gsize ndevices; + gint *disp_num_list; + gsize ndisp_num; + gboolean *is_console_list; + gsize nis_console; + gint *tty_device_list; + gsize ntty_device; + gsize i; key_file = g_key_file_new (); error = NULL; @@ -1107,9 +1287,48 @@ ck_seat_new_from_file (const char *sid, return NULL; } + error = NULL; + str = g_key_file_get_string (key_file, group, "DisplayType", &error); + if (error) { + g_warning ("Unable to load key DisplayType in seat file %s: %s", path, error->message); + g_error_free (error); + return NULL; + } + display_type = ck_display_type_new (str); + g_free (str); + + if (!display_type) { + g_debug ("Invalid DisplayType in seat file %s", path); + return NULL; + } + + error = NULL; + disp_num_list = g_key_file_get_integer_list (key_file, group, "DisplayNumbers", &ndisp_num, &error); + if (!disp_num_list) { + g_warning ("Unable to load key DisplayNumbers in seat file %s: %s", path, error->message); + g_error_free (error); + return NULL; + } + + error = NULL; + is_console_list = g_key_file_get_boolean_list (key_file, group, "IsConsoles", &nis_console, &error); + if (!is_console_list) { + g_warning ("Unable to load key IsConsoles in seat file %s: %s", path, error->message); + g_error_free (error); + return NULL; + } + + /* Make sure the numbers of DisplayNumbers, IsConsoles and TtyDevices are same */ + if (ndisp_num != nis_console ) { + g_debug ("Unmatched DisplayNumbers, IsConsoles in seat file %s", path); + return NULL; + } + + tty_device_list = g_key_file_get_integer_list (key_file, group, "TtyDevices", &ntty_device, NULL); + device_list = g_key_file_get_string_list (key_file, group, "Devices", &ndevices, NULL); - g_debug ("Creating seat %s with %d devices", sid, ndevices); + g_debug ("Creating seat %s with %d devices", sid, (int)ndevices); devices = g_ptr_array_sized_new (ndevices); @@ -1137,13 +1356,33 @@ 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); - g_ptr_array_free (devices, TRUE); + g_debug ("Setting seat %s with DisplayType=%s", sid, str); + seat->priv->display_type = display_type; + + for (i = 0; i < ndisp_num; i++) { + + DisplayData *disp; + + disp = g_new0 (DisplayData, 1); + disp->num = -1; + + disp->num = disp_num_list[i]; + disp->dynamic = FALSE; + disp->tty_device = generate_new_tty_device (is_console_list[i], + tty_device_list ? tty_device_list[i]:-1); + + seat->priv->displays = g_slist_append (seat->priv->displays, disp); + + } + + g_free (group); + return seat; } diff --git a/src/ck-seat.h b/src/ck-seat.h index 5977781..2155c62 100644 --- a/src/ck-seat.h +++ b/src/ck-seat.h @@ -57,6 +57,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 @@ -133,6 +138,14 @@ gboolean ck_seat_can_activate_sessions (CkSeat *seat, gboolean ck_seat_activate_session (CkSeat *seat, const char *ssid, DBusGMethodInvocation *context); +gboolean ck_seat_manage_seat (CkSeat *seat, + DBusGMethodInvocation *context); +gboolean ck_seat_add_display (CkSeat *seat, + int num, + gboolean dynamic, + const char *tty); +gboolean ck_seat_set_display_type (CkSeat *seat, + char *type); G_END_DECLS diff --git a/src/ck-session.c b/src/ck-session.c index 4009ee1..c4cc64a 100644 --- a/src/ck-session.c +++ b/src/ck-session.c @@ -67,6 +67,7 @@ struct CkSessionPrivate gboolean active; gboolean is_local; + gboolean is_dynamic; GTimeVal creation_time; @@ -92,6 +93,7 @@ enum { PROP_0, PROP_ID, PROP_COOKIE, + PROP_SEAT_ID, PROP_USER, PROP_UNIX_USER, PROP_X11_DISPLAY, @@ -101,6 +103,7 @@ enum { PROP_REMOTE_HOST_NAME, PROP_LOGIN_SESSION_ID, PROP_IS_LOCAL, + PROP_IS_DYNAMIC, PROP_ACTIVE, PROP_IDLE_HINT, }; @@ -421,6 +424,20 @@ ck_session_set_is_local (CkSession *session, } gboolean +ck_session_set_is_dynamic (CkSession *session, + gboolean is_dynamic, + GError **error) +{ + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); + + if (session->priv->is_dynamic != is_dynamic) { + session->priv->is_dynamic = is_dynamic; + } + + return TRUE; +} + +gboolean ck_session_get_id (CkSession *session, char **id, GError **error) @@ -598,6 +615,20 @@ ck_session_is_local (CkSession *session, } gboolean +ck_session_is_dynamic (CkSession *session, + gboolean *dynamic, + GError **error) +{ + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); + + if (dynamic != NULL) { + *dynamic = session->priv->is_dynamic; + } + + return TRUE; +} + +gboolean ck_session_set_id (CkSession *session, const char *id, GError **error) @@ -743,12 +774,18 @@ ck_session_set_property (GObject *object, case PROP_IS_LOCAL: ck_session_set_is_local (self, g_value_get_boolean (value), NULL); break; + case PROP_IS_DYNAMIC: + ck_session_set_is_dynamic (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; @@ -799,12 +836,18 @@ ck_session_get_property (GObject *object, case PROP_IS_LOCAL: g_value_set_boolean (value, self->priv->is_local); break; + case PROP_IS_DYNAMIC: + g_value_set_boolean (value, self->priv->is_dynamic); + 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; @@ -988,6 +1031,13 @@ ck_session_class_init (CkSessionClass *klass) TRUE, G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); g_object_class_install_property (object_class, + PROP_IS_DYNAMIC, + g_param_spec_boolean ("is-dynamic", + NULL, + NULL, + FALSE, + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); + g_object_class_install_property (object_class, PROP_ID, g_param_spec_string ("id", "id", @@ -1001,6 +1051,13 @@ ck_session_class_init (CkSessionClass *klass) "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, @@ -1283,6 +1340,7 @@ ck_session_run_programs (CkSession *session, } extra_env[n++] = g_strdup_printf ("CK_SESSION_IS_ACTIVE=%s", session->priv->active ? "true" : "false"); extra_env[n++] = g_strdup_printf ("CK_SESSION_IS_LOCAL=%s", session->priv->is_local ? "true" : "false"); + extra_env[n++] = g_strdup_printf ("CK_SESSION_IS_DYNAMIC=%s", session->priv->is_dynamic ? "true" : "false"); extra_env[n++] = NULL; ck_run_programs (SYSCONFDIR "/ConsoleKit/run-session.d", action, extra_env); @@ -1352,6 +1410,7 @@ ck_session_dump (CkSession *session, NONULL_STRING (session->priv->remote_host_name)); g_key_file_set_boolean (key_file, group_name, "is_active", session->priv->active); g_key_file_set_boolean (key_file, group_name, "is_local", session->priv->is_local); + g_key_file_set_boolean (key_file, group_name, "is_dynamic", session->priv->is_dynamic); s = g_time_val_to_iso8601 (&(session->priv->creation_time)); g_key_file_set_string (key_file, diff --git a/src/ck-session.h b/src/ck-session.h index c9ebd08..c288745 100644 --- a/src/ck-session.h +++ b/src/ck-session.h @@ -83,6 +83,9 @@ 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_dynamic (CkSession *session, + gboolean is_dynamic, + GError **error); gboolean ck_session_set_id (CkSession *session, const char *ssid, GError **error); @@ -129,6 +132,9 @@ gboolean ck_session_is_active (CkSession *se gboolean ck_session_is_local (CkSession *session, gboolean *local, GError **error); +gboolean ck_session_is_dynamic (CkSession *session, + gboolean *dynamic, + GError **error); gboolean ck_session_get_unix_user (CkSession *session, guint *uid, GError **error); diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml index f405c25..7d3145b 100644 --- a/src/org.freedesktop.ConsoleKit.Manager.xml +++ b/src/org.freedesktop.ConsoleKit.Manager.xml @@ -150,6 +150,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 + + + @@ -300,6 +317,44 @@ + + + + The display number + + + + + The seat type + + + + + The tty device + + + + + This method is to create a dynamic session with given parameters + + + + + + + + + The display number + + + + + This method is to remove a dynamic session with given display number + + + + + diff --git a/src/org.freedesktop.ConsoleKit.Seat.xml b/src/org.freedesktop.ConsoleKit.Seat.xml index 0e13a0f..b3dd117 100644 --- a/src/org.freedesktop.ConsoleKit.Seat.xml +++ b/src/org.freedesktop.ConsoleKit.Seat.xml @@ -99,6 +99,14 @@ seat at a time. + + + + Attempt to create unmanaged sessions for this seat. + + + + @@ -159,5 +167,34 @@ seat at a time. + + + + TRUE if this session is created dynamicly + + + + + Xserver command + + + + + Emitted when a session with given xserver command. + + + + + + + The display number + + + + + Emitted when a session with given display number need to be removed. + + + diff --git a/src/org.freedesktop.ConsoleKit.Session.xml b/src/org.freedesktop.ConsoleKit.Session.xml index b6e1cdb..8bbb06f 100644 --- a/src/org.freedesktop.ConsoleKit.Session.xml +++ b/src/org.freedesktop.ConsoleKit.Session.xml @@ -174,6 +174,18 @@ is-local + + + + TRUE if the session is dynamic, otherwise FALSE + + + + Returns whether the session is dynamic + + is-dynamic + + @@ -408,6 +420,14 @@ + + + + + Whether the session is dynamic + + + diff --git a/tools/.gitignore b/tools/.gitignore index 19a875c..867ec49 100644 --- a/tools/.gitignore +++ b/tools/.gitignore @@ -14,3 +14,4 @@ ck-list-sessions ck-log-system-start ck-log-system-restart ck-log-system-stop +ck-dynamic diff --git a/tools/Makefile.am b/tools/Makefile.am index 13c191f..6522e91 100644 --- a/tools/Makefile.am +++ b/tools/Makefile.am @@ -48,6 +48,7 @@ bin_PROGRAMS = \ ck-launch-session \ ck-list-sessions \ ck-history \ + ck-dynamic \ $(NULL) sbin_PROGRAMS = \ @@ -83,6 +84,14 @@ ck_history_LDADD = \ $(top_builddir)/src/libck-event-log.la \ $(NULL) +ck_dynamic_SOURCES = \ + ck-dynamic.c \ + $(NULL) + +ck_dynamic_LDADD = \ + $(CONSOLE_KIT_LIBS) \ + $(NULL) + ck_log_system_start_SOURCES = \ ck-log-system-start.c \ $(NULL) diff --git a/tools/ck-dynamic.c b/tools/ck-dynamic.c new file mode 100644 index 0000000..c148c68 --- /dev/null +++ b/tools/ck-dynamic.c @@ -0,0 +1,396 @@ +/* -*- 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" + +static void +create_dynamic_session (DBusGConnection *connection, + gint disp_num, + const char *disp_type, + const char *tty) +{ + gboolean res; + GError *error; + DBusGProxy *proxy; + + proxy = dbus_g_proxy_new_for_name (connection, + CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE); + if (proxy == NULL) { + return; + } + + + res = dbus_g_proxy_call (proxy, + "CreateSession", + &error, + G_TYPE_INT, disp_num, + G_TYPE_STRING, disp_type, + G_TYPE_STRING, tty, + G_TYPE_INVALID, + G_TYPE_INVALID); + if (!res) { + if (error->message) { + g_warning ("Unable to add dynamic display %s(:%d): %s", + disp_type, + disp_num, + error->message); + g_error_free (error); + } else { + g_warning ("Unable to add dynamic display %s(:%d)", + disp_type, + disp_num); + } + } + + g_object_unref (proxy); +} + +static void +remove_dynamic_session (DBusGConnection *connection, + int disp_num) +{ + DBusGProxy *proxy; + + proxy = dbus_g_proxy_new_for_name (connection, + CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE); + if (proxy == NULL) { + return; + } + + dbus_g_proxy_call_no_reply (proxy, + "RemoveSession", + G_TYPE_INT, disp_num, + G_TYPE_INVALID, + G_TYPE_INVALID); + + g_object_unref (proxy); +} + +static gboolean +get_string (DBusGProxy *proxy, + const char *method, + char **str) +{ + GError *error; + gboolean res; + + error = NULL; + res = dbus_g_proxy_call (proxy, + method, + &error, + G_TYPE_INVALID, + G_TYPE_STRING, str, + G_TYPE_INVALID); + if (! res) { + g_warning ("%s failed: %s", method, error->message); + g_error_free (error); + } + + return res; +} + +static gboolean +get_boolean (DBusGProxy *proxy, + const char *method, + gboolean *value) +{ + GError *error; + gboolean res; + + error = NULL; + res = dbus_g_proxy_call (proxy, + method, + &error, + G_TYPE_INVALID, + G_TYPE_BOOLEAN, value, + G_TYPE_INVALID); + if (! res) { + g_warning ("%s failed: %s", method, error->message); + g_error_free (error); + } + + return res; +} + +static void +list_dynamic_session (DBusGConnection *connection, + const char *ssid, + char **disp_list) +{ + DBusGProxy *proxy; + char *x11_display; + gboolean is_dynamic; + + + proxy = dbus_g_proxy_new_for_name (connection, + CK_NAME, + ssid, + CK_SESSION_INTERFACE); + if (proxy == NULL) { + return; + } + + + get_boolean (proxy, "IsDynamic", &is_dynamic); + + if (!is_dynamic) { + return; + } + + x11_display = NULL; + get_string (proxy, "GetX11Display", &x11_display); + + if (!x11_display || (strlen (x11_display) == 0)) { + return; + } + + if (*disp_list == NULL) { + *disp_list = g_strdup (x11_display); + } else { + *disp_list = g_strdup_printf ("%s;%s", *disp_list, x11_display); + } + + g_free (x11_display); +} + +static void +list_created_sessions_per_seat (DBusGConnection *connection, + const char *sid, + char **disp_list) +{ + DBusGProxy *proxy; + GError *error; + gboolean res; + GPtrArray *sessions; + int i; + + proxy = dbus_g_proxy_new_for_name (connection, + CK_NAME, + sid, + CK_SEAT_INTERFACE); + if (proxy == NULL) { + return; + } + + sessions = NULL; + + error = NULL; + res = dbus_g_proxy_call (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); + goto out; + } + + for (i = 0; i < sessions->len; i++) { + char *ssid; + + ssid = g_ptr_array_index (sessions, i); + + list_dynamic_session (connection, ssid, disp_list); + + g_free (ssid); + } + + g_ptr_array_free (sessions, TRUE); + out: + g_object_unref (proxy); + +} + +static void +list_created_sessions (DBusGConnection *connection) +{ + char *disp_list; + DBusGProxy *proxy; + GError *error; + gboolean res; + GPtrArray *seats; + int i; + + disp_list = NULL; + + proxy = dbus_g_proxy_new_for_name (connection, + CK_NAME, + CK_MANAGER_PATH, + CK_MANAGER_INTERFACE); + if (proxy == NULL) { + return; + } + + seats = NULL; + + 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); + goto out; + } + + for (i = 0; i < seats->len; i++) { + char *sid; + + sid = g_ptr_array_index (seats, i); + + list_created_sessions_per_seat (connection, sid, &disp_list); + + g_free (sid); + } + + g_ptr_array_free (seats, TRUE); + + out: + if (disp_list && !g_str_equal (disp_list, "")) { + printf ("%s\n", disp_list); + } else { + printf ("No matching display!\n"); + } + + g_free (disp_list); + + g_object_unref (proxy); + +} + +int +main (int argc, char *argv[]) +{ + DBusGConnection *connection; + GOptionContext *ctx; + GError *error = NULL; + gboolean add = FALSE; + gboolean delete = FALSE; + gboolean list = FALSE; + gboolean show_version = FALSE; + char *type = NULL; + int num = -1; + gboolean res; + + GOptionEntry options [] = { + { "add", 'a', 0, G_OPTION_ARG_NONE, &add, N_("Add a new display"), NULL}, + { "delete", 'd', 0, G_OPTION_ARG_NONE, &delete, N_("Delete a new display"), NULL}, + { "list", 'l', 0, G_OPTION_ARG_NONE, &list, N_("List all attached displays"), NULL}, + { "num", 'n', 0, G_OPTION_ARG_INT, &num, N_("Display number"), NULL}, + { "type", 't', 0, G_OPTION_ARG_STRING, &type, N_("Display type"), NULL}, + { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, + { NULL } + }; + + g_type_init (); + + /* Option parsing */ + ctx = g_option_context_new ("- Manage dynamic displays"); + g_option_context_add_main_entries (ctx, options, _("Main Options")); + 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 && !list) { + g_warning ("Must specify -a, -d or -l!"); + exit (1); + } + + if (delete && num < 0) { + g_warning ("Can not delete a negtive number display (:%d)!", num); + exit (1); + } + + if (add && (!type || (strlen(type) == 0))) { + 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) { + create_dynamic_session (connection, num, type, NULL); + } else if (delete) { + remove_dynamic_session (connection, num); + } else if (list) { + list_created_sessions (connection); + } else { + g_warning ("Invaild parameters!"); + exit (1); + } + + return 0; +} diff --git a/tools/list-sessions.c b/tools/list-sessions.c index 3933772..d7839ab 100644 --- a/tools/list-sessions.c +++ b/tools/list-sessions.c @@ -184,6 +184,7 @@ list_session (DBusGConnection *connection, char *idle_since_hint; gboolean is_active; gboolean is_local; + gboolean is_dynamic; char *short_sid; const char *short_ssid; @@ -215,6 +216,7 @@ list_session (DBusGConnection *connection, get_string (proxy, "GetRemoteHostName", &remote_host_name); get_boolean (proxy, "IsActive", &is_active); get_boolean (proxy, "IsLocal", &is_local); + get_boolean (proxy, "IsDynamic", &is_dynamic); get_string (proxy, "GetCreationTime", &creation_time); get_string (proxy, "GetIdleSinceHint", &idle_since_hint); @@ -230,7 +232,7 @@ 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'", + 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\tis-dynamic = %s\n\ton-since = '%s'\n\tlogin-session-id = '%s'", short_ssid, uid, realname, @@ -242,6 +244,7 @@ list_session (DBusGConnection *connection, display_device, remote_host_name, is_local ? "TRUE" : "FALSE", + is_dynamic ? "TRUE" : "FALSE", creation_time, lsid); if (idle_since_hint != NULL && idle_since_hint[0] != '\0') {