1 diff --git a/configure.ac b/configure.ac 2 index 117d788..2ff6020 100644 3 --- a/configure.ac 4 +++ b/configure.ac 5 @@ -203,6 +203,18 @@ AM_CONDITIONAL(CK_COMPILE_SOLARIS, test x$CK_BACKEND = xsolaris, [Compiling for 6 AC_SUBST(CK_BACKEND) 7 8 dnl --------------------------------------------------------------------------- 9 +dnl Check for X11 DIR 10 +dnl --------------------------------------------------------------------------- 11 + 12 +X11_DIR=`$PKG_CONFIG --variable=bindir xorg-server 2>/dev/null` 13 +if test "x$X11_DIR" = x; then 14 + AC_PATH_PROGS([XSERVER], [Xorg X],,[$PATH:/usr/X11/bin:/usr/bin]) 15 + test "x$XSERVER" != x && X11_DIR=`dirname "$XSERVER"` 16 +fi 17 +test "x$X11_DIR" = x && X11_DIR=$bindir 18 +AC_SUBST([X11_DIR]) 19 + 20 +dnl --------------------------------------------------------------------------- 21 dnl Check for PAM 22 dnl --------------------------------------------------------------------------- 23 24 @@ -303,6 +315,14 @@ if test "x$enable_inotify" = "xyes" ; then 25 fi 26 27 dnl --------------------------------------------------------------------------- 28 +dnl check for strverscmp 29 +dnl --------------------------------------------------------------------------- 30 +have_strverscmp=no 31 +AC_CHECK_FUNCS(strverscmp, [have_strverscmp=yes], []) 32 + 33 +AM_CONDITIONAL(USE_SELF_STRVERSCMP, test "x$have_strverscmp" = "xno", [Define if we do not have strverscmp]) 34 + 35 +dnl --------------------------------------------------------------------------- 36 dnl check for RBAC 37 dnl --------------------------------------------------------------------------- 38 39 @@ -401,6 +421,8 @@ tools/linux/Makefile 40 tools/freebsd/Makefile 41 tools/solaris/Makefile 42 data/Makefile 43 +data/displays.d/Makefile 44 +data/sessions.d/Makefile 45 doc/Makefile 46 doc/dbus/ConsoleKit.xml 47 doc/dbus/Makefile 48 diff --git a/data/00-primary.seat b/data/00-primary.seat 49 index 6e61db4..0632382 100644 50 --- a/data/00-primary.seat 51 +++ b/data/00-primary.seat 52 @@ -1,5 +1,26 @@ 53 [Seat Entry] 54 Version=1.0 55 Name=Primary seat 56 +# Specified Seat ID, if this value is NULL, ConsoleKit will decide one. 57 +# The ID only contain the ASICC characters "[A-Z][a-z][0-9]_" 58 +ID=StaticSeat1 59 +Description=start one static local display at :0 60 + 61 +# Indicate whether to create this seat or not. If it is set true, then CK will 62 +# not create this seat. Default value is false. 63 Hidden=false 64 -Devices= 65 \ No newline at end of file 66 + 67 +# Indicate input/output devices including keyboard-pointer-video 68 +# card-monitor-sound-usb devices, 69 +# This key will not implemented now, it might need be divided into 70 +# several keys in the future: 71 +# Pointer= 72 +# Monitor= 73 +# VideoCard= 74 +# Monitor= 75 +# UsbHub= 76 +Devices= 77 + 78 +# List of sessions to start on the seat, separated by ';' 79 +# Each session is defined in sessions.d/ 80 +Sessions=Local; 81 diff --git a/data/ConsoleKit.conf b/data/ConsoleKit.conf 82 index 948f95f..8cf490a 100644 83 --- a/data/ConsoleKit.conf 84 +++ b/data/ConsoleKit.conf 85 @@ -44,6 +44,9 @@ 86 send_member="CloseSession"/> 87 <allow send_destination="org.freedesktop.ConsoleKit" 88 send_interface="org.freedesktop.ConsoleKit.Manager" 89 + send_member="GetUnmanagedSeats"/> 90 + <allow send_destination="org.freedesktop.ConsoleKit" 91 + send_interface="org.freedesktop.ConsoleKit.Manager" 92 send_member="GetSeats"/> 93 <allow send_destination="org.freedesktop.ConsoleKit" 94 send_interface="org.freedesktop.ConsoleKit.Manager" 95 @@ -69,6 +72,18 @@ 96 <allow send_destination="org.freedesktop.ConsoleKit" 97 send_interface="org.freedesktop.ConsoleKit.Manager" 98 send_member="GetSystemIdleSinceHint"/> 99 + <allow send_destination="org.freedesktop.ConsoleKit" 100 + send_interface="org.freedesktop.ConsoleKit.Manager" 101 + send_member="AddSeat"/> 102 + <allow send_destination="org.freedesktop.ConsoleKit" 103 + send_interface="org.freedesktop.ConsoleKit.Manager" 104 + send_member="RemoveSeat"/> 105 + <allow send_destination="org.freedesktop.ConsoleKit" 106 + send_interface="org.freedesktop.ConsoleKit.Manager" 107 + send_member="AddSession"/> 108 + <allow send_destination="org.freedesktop.ConsoleKit" 109 + send_interface="org.freedesktop.ConsoleKit.Manager" 110 + send_member="RemoveSession"/> 111 112 <allow send_destination="org.freedesktop.ConsoleKit" 113 send_interface="org.freedesktop.ConsoleKit.Seat" 114 @@ -88,6 +103,9 @@ 115 <allow send_destination="org.freedesktop.ConsoleKit" 116 send_interface="org.freedesktop.ConsoleKit.Seat" 117 send_member="ActivateSession"/> 118 + <allow send_destination="org.freedesktop.ConsoleKit" 119 + send_interface="org.freedesktop.ConsoleKit.Seat" 120 + send_member="ManageSeat"/> 121 122 <allow send_destination="org.freedesktop.ConsoleKit" 123 send_interface="org.freedesktop.ConsoleKit.Session" 124 @@ -103,6 +121,9 @@ 125 send_member="GetSessionType"/> 126 <allow send_destination="org.freedesktop.ConsoleKit" 127 send_interface="org.freedesktop.ConsoleKit.Session" 128 + send_member="GetDisplayType"/> 129 + <allow send_destination="org.freedesktop.ConsoleKit" 130 + send_interface="org.freedesktop.ConsoleKit.Session" 131 send_member="GetUser"/> 132 <allow send_destination="org.freedesktop.ConsoleKit" 133 send_interface="org.freedesktop.ConsoleKit.Session" 134 @@ -127,6 +148,12 @@ 135 send_member="IsLocal"/> 136 <allow send_destination="org.freedesktop.ConsoleKit" 137 send_interface="org.freedesktop.ConsoleKit.Session" 138 + send_member="IsDynamic"/> 139 + <allow send_destination="org.freedesktop.ConsoleKit" 140 + send_interface="org.freedesktop.ConsoleKit.Session" 141 + send_member="IsOpen"/> 142 + <allow send_destination="org.freedesktop.ConsoleKit" 143 + send_interface="org.freedesktop.ConsoleKit.Session" 144 send_member="GetCreationTime"/> 145 <allow send_destination="org.freedesktop.ConsoleKit" 146 send_interface="org.freedesktop.ConsoleKit.Session" 147 @@ -136,12 +163,11 @@ 148 send_member="GetIdleHint"/> 149 <allow send_destination="org.freedesktop.ConsoleKit" 150 send_interface="org.freedesktop.ConsoleKit.Session" 151 - send_member="SetIdleHint"/> 152 - <allow send_destination="org.freedesktop.ConsoleKit" 153 - send_interface="org.freedesktop.ConsoleKit.Session" 154 send_member="GetIdleSinceHint"/> 155 <allow send_interface="org.freedesktop.ConsoleKit.Session" 156 send_member="SetIdleHint"/> 157 + <allow send_interface="org.freedesktop.ConsoleKit.Session" 158 + send_member="SetRemoveOnClose"/> 159 </policy> 160 161 </busconfig> 162 diff --git a/data/Makefile.am b/data/Makefile.am 163 index 041b431..2054e96 100644 164 --- a/data/Makefile.am 165 +++ b/data/Makefile.am 166 @@ -1,5 +1,10 @@ 167 NULL = 168 169 +SUBDIRS = \ 170 + displays.d \ 171 + sessions.d \ 172 + $(NULL) 173 + 174 dbusconfdir = $(DBUS_SYS_DIR) 175 dbusconf_DATA = ConsoleKit.conf 176 177 diff --git a/data/displays.d/Headless.display.in b/data/displays.d/Headless.display.in 178 new file mode 100644 179 index 0000000..754d2bf 180 --- /dev/null 181 +++ b/data/displays.d/Headless.display.in 182 @@ -0,0 +1,5 @@ 183 +[Display] 184 +Type=X11 185 + 186 +[X11] 187 +Exec=@X11_DIR@/Xvfb $display -auth $auth 188 diff --git a/data/displays.d/Local.display.in b/data/displays.d/Local.display.in 189 new file mode 100644 190 index 0000000..b845a7b 191 --- /dev/null 192 +++ b/data/displays.d/Local.display.in 193 @@ -0,0 +1,5 @@ 194 +[Display] 195 +Type=X11 196 + 197 +[X11] 198 +Exec=@X11_DIR@/Xorg $display -br -verbose -auth $auth -nolisten tcp $vt 199 diff --git a/data/displays.d/LocalVNC.display.in b/data/displays.d/LocalVNC.display.in 200 new file mode 100644 201 index 0000000..6ad336b 202 --- /dev/null 203 +++ b/data/displays.d/LocalVNC.display.in 204 @@ -0,0 +1,5 @@ 205 +[Display] 206 +Type=X11 207 + 208 +[X11] 209 +Exec=@X11_DIR@/Xvnc $display -auth $auth -query localhost 210 diff --git a/data/displays.d/Makefile.am b/data/displays.d/Makefile.am 211 new file mode 100644 212 index 0000000..1fab1d2 213 --- /dev/null 214 +++ b/data/displays.d/Makefile.am 215 @@ -0,0 +1,29 @@ 216 +NULL = 217 + 218 +displaydir = $(sysconfdir)/ConsoleKit/displays.d 219 +display_in_files = \ 220 + Local.display.in \ 221 + RemoteMachine.display.in \ 222 + LocalVNC.display.in \ 223 + Headless.display.in 224 + 225 +display_DATA = $(display_in_files:.display.in=.display) 226 + 227 +Local.display: Local.display.in Makefile 228 + sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@ 229 +RemoteMachine.display: RemoteMachine.display.in Makefile 230 + sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@ 231 +LocalVNC.display: LocalVNC.display.in Makefile 232 + sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@ 233 +Headless.display: Headless.display.in Makefile 234 + sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@ 235 + 236 +EXTRA_DIST = \ 237 + $(display_in_files) \ 238 + $(NULL) 239 + 240 +MAINTAINERCLEANFILES = \ 241 + *~ \ 242 + Makefile.in 243 + 244 +CLEANFILES = $(display_DATA) 245 diff --git a/data/displays.d/RemoteMachine.display.in b/data/displays.d/RemoteMachine.display.in 246 new file mode 100644 247 index 0000000..7c69451 248 --- /dev/null 249 +++ b/data/displays.d/RemoteMachine.display.in 250 @@ -0,0 +1,5 @@ 251 +[Display] 252 +Type=X11 253 + 254 +[X11] 255 +Exec=@X11_DIR@/Xorg $display -br -verbose -auth $auth -indirect $vt 256 diff --git a/data/sessions.d/Headless.session b/data/sessions.d/Headless.session 257 new file mode 100644 258 index 0000000..d376af9 259 --- /dev/null 260 +++ b/data/sessions.d/Headless.session 261 @@ -0,0 +1,8 @@ 262 +[Session Entry] 263 +Name=Headless 264 +Type=LoginWindow 265 +Description=Login Window running on headless display 266 +DisplayTemplate=Headless 267 + 268 +[Headless] 269 +display=:32 270 diff --git a/data/sessions.d/Local.session b/data/sessions.d/Local.session 271 new file mode 100644 272 index 0000000..9d3b975 273 --- /dev/null 274 +++ b/data/sessions.d/Local.session 275 @@ -0,0 +1,9 @@ 276 +[Session Entry] 277 +Name=Local 278 +Type=LoginWindow 279 +Description=Local Login Screen 280 +DisplayTemplate=Local 281 + 282 +[Local] 283 +display=:0 284 +vt=vt1 285 diff --git a/data/sessions.d/LocalVNC.session b/data/sessions.d/LocalVNC.session 286 new file mode 100644 287 index 0000000..c05802f 288 --- /dev/null 289 +++ b/data/sessions.d/LocalVNC.session 290 @@ -0,0 +1,8 @@ 291 +[Session Entry] 292 +Name=LocalVNC 293 +Type=LoginWindow 294 +Description=Connect to local VNC server running on same machine 295 +DisplayTemplate=LocalVNC 296 + 297 +[LocalVNC] 298 +display=:64 299 diff --git a/data/sessions.d/Makefile.am b/data/sessions.d/Makefile.am 300 new file mode 100644 301 index 0000000..f17ffdc 302 --- /dev/null 303 +++ b/data/sessions.d/Makefile.am 304 @@ -0,0 +1,16 @@ 305 +NULL = 306 + 307 +sessiondir = $(sysconfdir)/ConsoleKit/sessions.d 308 +session_DATA = \ 309 + Headless.session \ 310 + Local.session \ 311 + LocalVNC.session \ 312 + Remote.session 313 + 314 +EXTRA_DIST = \ 315 + $(session_DATA) \ 316 + $(NULL) 317 + 318 +MAINTAINERCLEANFILES = \ 319 + *~ \ 320 + Makefile.in 321 diff --git a/data/sessions.d/Remote.session b/data/sessions.d/Remote.session 322 new file mode 100644 323 index 0000000..e88f975 324 --- /dev/null 325 +++ b/data/sessions.d/Remote.session 326 @@ -0,0 +1,9 @@ 327 +[Session Entry] 328 +Name=Remote Chooser 329 +Type=Remote 330 +Description=Connect to chooser on nearby remote machine 331 +DisplayTemplate=RemoteMachine 332 + 333 +[RemoteMachine] 334 +display=:96 335 +vt=vt10 336 diff --git a/doc/dbus/ck-terms.xml b/doc/dbus/ck-terms.xml 337 index d3d544d..1b43ca6 100644 338 --- a/doc/dbus/ck-terms.xml 339 +++ b/doc/dbus/ck-terms.xml 340 @@ -64,4 +64,11 @@ True, hardware, multi-seat capabilities will be added in a later release. 341 </para> 342 </sect1> 343 344 + <sect1> 345 + <title>Seat manager</title> 346 + <para> 347 +The seat manager is the process responsible for starting and stopping sessions on a seat. 348 + </para> 349 + </sect1> 350 + 351 </chapter> 352 diff --git a/libck-connector/ck-connector.c b/libck-connector/ck-connector.c 353 index 7f6f87f..87a7d4a 100644 354 --- a/libck-connector/ck-connector.c 355 +++ b/libck-connector/ck-connector.c 356 @@ -76,8 +76,11 @@ static struct { 357 { "display-device", DBUS_TYPE_STRING }, 358 { "x11-display-device", DBUS_TYPE_STRING }, 359 { "x11-display", DBUS_TYPE_STRING }, 360 + { "seat-id", DBUS_TYPE_STRING }, 361 + { "session", DBUS_TYPE_STRING }, 362 { "remote-host-name", DBUS_TYPE_STRING }, 363 { "session-type", DBUS_TYPE_STRING }, 364 + { "display-type", DBUS_TYPE_STRING }, 365 { "is-local", DBUS_TYPE_BOOLEAN }, 366 { "unix-user", DBUS_TYPE_INT32 }, 367 }; 368 diff --git a/src/Makefile.am b/src/Makefile.am 369 index 6ab05c8..97a59ef 100644 370 --- a/src/Makefile.am 371 +++ b/src/Makefile.am 372 @@ -107,6 +107,8 @@ console_kit_daemon_SOURCES = \ 373 ck-file-monitor.h \ 374 ck-job.h \ 375 ck-job.c \ 376 + ck-display-template.h \ 377 + ck-display-template.c \ 378 ck-seat.h \ 379 ck-seat.c \ 380 ck-session-leader.h \ 381 @@ -122,6 +124,13 @@ console_kit_daemon_SOURCES = \ 382 $(BUILT_SOURCES) \ 383 $(NULL) 384 385 +if USE_SELF_STRVERSCMP 386 +console_kit_daemon_SOURCES += \ 387 + strverscmp.c \ 388 + strverscmp.h \ 389 + $(NULL) 390 +endif 391 + 392 if ENABLE_INOTIFY 393 FILE_MONITOR_BACKEND = ck-file-monitor-inotify.c 394 else 395 diff --git a/src/ck-display-template.c b/src/ck-display-template.c 396 new file mode 100644 397 index 0000000..9206103 398 --- /dev/null 399 +++ b/src/ck-display-template.c 400 @@ -0,0 +1,341 @@ 401 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 402 + * 403 + * Authors: halton.huo (a] sun.com, Ray Strode <rstrode (a] redhat.com> 404 + * Copyright (C) 2009 Sun Microsystems, Inc. 405 + * Red Hat, Inc. 406 + * 407 + * This program is free software; you can redistribute it and/or modify 408 + * it under the terms of the GNU General Public License as published by 409 + * the Free Software Foundation; either version 2 of the License, or 410 + * (at your option) any later version. 411 + * 412 + * This program is distributed in the hope that it will be useful, 413 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 414 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 415 + * GNU General Public License for more details. 416 + * 417 + * You should have received a copy of the GNU General Public License 418 + * along with this program; if not, write to the Free Software 419 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 420 + * 421 + */ 422 + 423 +#include "config.h" 424 + 425 +#include <string.h> 426 +#include <glib.h> 427 +#include <glib-object.h> 428 + 429 +#include "ck-display-template.h" 430 + 431 +#define CK_DISPLAY_TEMPLATE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplatePrivate)) 432 + 433 +#define CK_DISPLAY_TEMPLATES_DIR SYSCONFDIR "/ConsoleKit/displays.d" 434 + 435 +struct CkDisplayTemplatePrivate 436 +{ 437 + char *name; 438 + char *type; 439 + GHashTable *parameters; 440 +}; 441 + 442 +enum { 443 + PROP_0, 444 + PROP_NAME, 445 + PROP_TYPE, 446 + PROP_PARAMETERS, 447 +}; 448 + 449 +static void ck_display_template_class_init (CkDisplayTemplateClass *klass); 450 +static void ck_display_template_init (CkDisplayTemplate *display); 451 +static void ck_display_template_finalize (GObject *object); 452 +static gboolean ck_display_template_load (CkDisplayTemplate *display); 453 + 454 +static GHashTable *ck_display_templates; 455 + 456 +G_DEFINE_TYPE (CkDisplayTemplate, ck_display_template, G_TYPE_OBJECT) 457 + 458 +static void 459 +_ck_display_template_set_name (CkDisplayTemplate *display, 460 + const char *name) 461 +{ 462 + g_free (display->priv->name); 463 + display->priv->name = g_strdup (name); 464 +} 465 + 466 +static void 467 +_ck_display_template_set_type_string (CkDisplayTemplate *display, 468 + const char *type) 469 +{ 470 + g_free (display->priv->type); 471 + display->priv->type = g_strdup (type); 472 +} 473 + 474 +static void 475 +_ck_display_template_set_parameters (CkDisplayTemplate *display, 476 + GHashTable *parameters) 477 +{ 478 + if (display->priv->parameters != NULL) { 479 + g_hash_table_unref (display->priv->parameters); 480 + } 481 + 482 + if (parameters == NULL) { 483 + display->priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, 484 + (GDestroyNotify) g_free, 485 + (GDestroyNotify) g_free); 486 + } else { 487 + display->priv->parameters = g_hash_table_ref (parameters); 488 + } 489 +} 490 + 491 +static void 492 +ck_display_template_set_property (GObject *object, 493 + guint prop_id, 494 + const GValue *value, 495 + GParamSpec *pspec) 496 +{ 497 + CkDisplayTemplate *self; 498 + 499 + self = CK_DISPLAY_TEMPLATE (object); 500 + 501 + switch (prop_id) { 502 + case PROP_NAME: 503 + _ck_display_template_set_name (self, g_value_get_string (value)); 504 + break; 505 + case PROP_TYPE: 506 + _ck_display_template_set_type_string (self, g_value_get_string (value)); 507 + break; 508 + case PROP_PARAMETERS: 509 + _ck_display_template_set_parameters (self, g_value_get_boxed (value)); 510 + break; 511 + default: 512 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 513 + break; 514 + } 515 +} 516 + 517 +static void 518 +ck_display_template_get_property (GObject *object, 519 + guint prop_id, 520 + GValue *value, 521 + GParamSpec *pspec) 522 +{ 523 + CkDisplayTemplate *self; 524 + 525 + self = CK_DISPLAY_TEMPLATE (object); 526 + 527 + switch (prop_id) { 528 + case PROP_NAME: 529 + g_value_set_string (value, self->priv->name); 530 + break; 531 + case PROP_TYPE: 532 + g_value_set_string (value, self->priv->type); 533 + break; 534 + case PROP_PARAMETERS: 535 + g_value_set_boxed (value, self->priv->parameters); 536 + break; 537 + default: 538 + G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 539 + break; 540 + } 541 +} 542 + 543 +static void 544 +ck_display_template_class_init (CkDisplayTemplateClass *klass) 545 +{ 546 + GObjectClass *object_class = G_OBJECT_CLASS (klass); 547 + 548 + object_class->get_property = ck_display_template_get_property; 549 + object_class->set_property = ck_display_template_set_property; 550 + object_class->finalize = ck_display_template_finalize; 551 + 552 + g_object_class_install_property (object_class, 553 + PROP_NAME, 554 + g_param_spec_string ("name", 555 + "display type name", 556 + "display type name", 557 + NULL, 558 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); 559 + g_object_class_install_property (object_class, 560 + PROP_TYPE, 561 + g_param_spec_string ("type", 562 + "type", 563 + "Type", 564 + NULL, 565 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); 566 + g_object_class_install_property (object_class, 567 + PROP_PARAMETERS, 568 + g_param_spec_boxed ("parameters", 569 + "Parameters", 570 + "Parameters", 571 + G_TYPE_HASH_TABLE, 572 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); 573 + g_type_class_add_private (klass, sizeof (CkDisplayTemplatePrivate)); 574 +} 575 + 576 +static void 577 +ck_display_template_init (CkDisplayTemplate *display) 578 +{ 579 + display->priv = CK_DISPLAY_TEMPLATE_GET_PRIVATE (display); 580 + 581 + display->priv->name = NULL; 582 + display->priv->type = NULL; 583 + display->priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal, 584 + (GDestroyNotify) g_free, 585 + (GDestroyNotify) g_free); 586 +} 587 + 588 +static void 589 +ck_display_template_finalize (GObject *object) 590 +{ 591 + CkDisplayTemplate *display; 592 + 593 + g_return_if_fail (object != NULL); 594 + g_return_if_fail (CK_IS_DISPLAY_TEMPLATE (object)); 595 + 596 + display = CK_DISPLAY_TEMPLATE (object); 597 + 598 + g_return_if_fail (display->priv != NULL); 599 + 600 + g_free (display->priv->name); 601 + g_free (display->priv->type); 602 + g_hash_table_unref (display->priv->parameters); 603 + 604 + G_OBJECT_CLASS (ck_display_template_parent_class)->finalize (object); 605 +} 606 + 607 +static gboolean 608 +ck_display_template_load (CkDisplayTemplate *display) 609 +{ 610 + GKeyFile *key_file; 611 + const char *name; 612 + char *group; 613 + char *filename; 614 + gboolean hidden; 615 + char *type; 616 + gboolean res; 617 + GError *error; 618 + char **type_keys; 619 + GHashTable *parameters; 620 + 621 + name = ck_display_template_get_name (display); 622 + 623 + g_return_val_if_fail (name && !g_str_equal (name, ""), FALSE); 624 + 625 + filename = g_strdup_printf ("%s/%s.display", CK_DISPLAY_TEMPLATES_DIR, name); 626 + 627 + key_file = g_key_file_new (); 628 + 629 + error = NULL; 630 + res = g_key_file_load_from_file (key_file, 631 + filename, 632 + G_KEY_FILE_NONE, 633 + &error); 634 + if (! res) { 635 + g_warning ("Unable to load display from file %s: %s", filename, error->message); 636 + g_error_free (error); 637 + return FALSE; 638 + } 639 + g_free (filename); 640 + 641 + group = g_key_file_get_start_group (key_file); 642 + 643 + if (group == NULL || strcmp (group, "Display") != 0) { 644 + g_warning ("Not a display type file: %s", filename); 645 + g_free (group); 646 + g_key_file_free (key_file); 647 + return FALSE; 648 + } 649 + 650 + hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL); 651 + 652 + type = g_key_file_get_string (key_file, group, "Type", NULL); 653 + 654 + if (type == NULL) { 655 + g_warning ("Unable to read type from display file"); 656 + g_free (group); 657 + g_key_file_free (key_file); 658 + return FALSE; 659 + } 660 + 661 + display->priv->type = type; 662 + 663 + parameters = g_hash_table_new_full (g_str_hash, g_str_equal, 664 + (GDestroyNotify) g_free, 665 + (GDestroyNotify) g_free); 666 + 667 + type_keys = g_key_file_get_keys (key_file, type, NULL, NULL); 668 + 669 + if (type_keys != NULL) { 670 + int i; 671 + for (i = 0; type_keys[i] != NULL; i++) { 672 + char *string; 673 + 674 + string = g_key_file_get_string (key_file, type, type_keys[i], NULL); 675 + g_hash_table_insert (parameters, g_strdup (type_keys[i]), string); 676 + } 677 + g_strfreev (type_keys); 678 + } 679 + 680 + _ck_display_template_set_parameters (display, parameters); 681 + g_hash_table_unref (parameters); 682 + 683 + g_free (group); 684 + g_key_file_free (key_file); 685 + return TRUE; 686 +} 687 + 688 +CkDisplayTemplate * 689 +ck_display_template_get_from_name (const char *name) 690 +{ 691 + CkDisplayTemplate *display_template; 692 + 693 + if (ck_display_templates == NULL) { 694 + ck_display_templates = g_hash_table_new_full (g_str_hash, g_str_equal, 695 + (GDestroyNotify) g_free, 696 + (GDestroyNotify) g_object_unref); 697 + } 698 + 699 + display_template = g_hash_table_lookup (ck_display_templates, name); 700 + 701 + if (display_template == NULL) { 702 + GObject *object; 703 + 704 + object = g_object_new (CK_TYPE_DISPLAY_TEMPLATE, 705 + "name", name, 706 + NULL); 707 + 708 + if (!ck_display_template_load (CK_DISPLAY_TEMPLATE (object))) { 709 + g_object_unref (object); 710 + return NULL; 711 + } 712 + 713 + g_hash_table_insert (ck_display_templates, g_strdup (name), object); 714 + display_template = CK_DISPLAY_TEMPLATE (object); 715 + } 716 + 717 + return g_object_ref (display_template); 718 +} 719 + 720 +G_CONST_RETURN char* 721 +ck_display_template_get_name (CkDisplayTemplate *display) 722 +{ 723 + g_return_val_if_fail (CK_IS_DISPLAY_TEMPLATE (display), NULL); 724 + 725 + return display->priv->name; 726 +} 727 + 728 +G_CONST_RETURN char * 729 +ck_display_template_get_type_string (CkDisplayTemplate *display) 730 +{ 731 + return display->priv->type; 732 +} 733 + 734 +GHashTable * 735 +ck_display_template_get_parameters (CkDisplayTemplate *display) 736 +{ 737 + g_return_val_if_fail (CK_IS_DISPLAY_TEMPLATE (display), NULL); 738 + 739 + return g_hash_table_ref (display->priv->parameters); 740 +} 741 + 742 diff --git a/src/ck-display-template.h b/src/ck-display-template.h 743 new file mode 100644 744 index 0000000..fa74e67 745 --- /dev/null 746 +++ b/src/ck-display-template.h 747 @@ -0,0 +1,57 @@ 748 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 749 + * 750 + * Authors: halton.huo (a] sun.com 751 + * Copyright (C) 2009 Sun Microsystems, Inc. 752 + * 753 + * This program is free software; you can redistribute it and/or modify 754 + * it under the terms of the GNU General Public License as published by 755 + * the Free Software Foundation; either version 2 of the License, or 756 + * (at your option) any later version. 757 + * 758 + * This program is distributed in the hope that it will be useful, 759 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 760 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 761 + * GNU General Public License for more details. 762 + * 763 + * You should have received a copy of the GNU General Public License 764 + * along with this program; if not, write to the Free Software 765 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. 766 + * 767 + */ 768 + 769 +#ifndef __CK_DISPLAY_TEMPLATE_H 770 +#define __CK_DISPLAY_TEMPLATE_H 771 + 772 +#include <glib-object.h> 773 + 774 +G_BEGIN_DECLS 775 + 776 +#define CK_TYPE_DISPLAY_TEMPLATE (ck_display_template_get_type ()) 777 +#define CK_DISPLAY_TEMPLATE(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplate)) 778 +#define CK_DISPLAY_TEMPLATE_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplateClass)) 779 +#define CK_IS_DISPLAY_TEMPLATE(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_DISPLAY_TEMPLATE)) 780 +#define CK_IS_DISPLAY_TEMPLATE_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_DISPLAY_TEMPLATE)) 781 +#define CK_DISPLAY_TEMPLATE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplateClass)) 782 + 783 +typedef struct CkDisplayTemplatePrivate CkDisplayTemplatePrivate; 784 + 785 +typedef struct 786 +{ 787 + GObject parent; 788 + CkDisplayTemplatePrivate *priv; 789 +} CkDisplayTemplate; 790 + 791 +typedef struct 792 +{ 793 + GObjectClass parent_class; 794 +} CkDisplayTemplateClass; 795 + 796 +GType ck_display_template_get_type (void); 797 +CkDisplayTemplate * ck_display_template_get_from_name (const char *name); 798 +G_CONST_RETURN char * ck_display_template_get_name (CkDisplayTemplate *display); 799 +G_CONST_RETURN char * ck_display_template_get_type_string (CkDisplayTemplate *display); 800 +GHashTable * ck_display_template_get_parameters (CkDisplayTemplate *display); 801 + 802 +G_END_DECLS 803 + 804 +#endif /* __CK_DISPLAY_TEMPLATE_H */ 805 diff --git a/src/ck-log-event.c b/src/ck-log-event.c 806 index 66f439c..510b18e 100644 807 --- a/src/ck-log-event.c 808 +++ b/src/ck-log-event.c 809 @@ -79,6 +79,8 @@ event_seat_session_added_free (CkLogSeatSessionAddedEvent *event) 810 event->session_id = NULL; 811 g_free (event->session_type); 812 event->session_type = NULL; 813 + g_free (event->display_type); 814 + event->display_type = NULL; 815 g_free (event->session_x11_display); 816 event->session_x11_display = NULL; 817 g_free (event->session_x11_display_device); 818 @@ -103,6 +105,8 @@ event_seat_session_removed_free (CkLogSeatSessionRemovedEvent *event) 819 event->session_id = NULL; 820 g_free (event->session_type); 821 event->session_type = NULL; 822 + g_free (event->display_type); 823 + event->display_type = NULL; 824 g_free (event->session_x11_display); 825 event->session_x11_display = NULL; 826 g_free (event->session_x11_display_device); 827 @@ -213,6 +217,7 @@ event_seat_session_added_copy (CkLogSeatSessionAddedEvent *event, 828 event_copy->seat_id = g_strdup (event->seat_id); 829 event_copy->session_id = g_strdup (event->session_id); 830 event_copy->session_type = g_strdup (event->session_type); 831 + event_copy->display_type = g_strdup (event->display_type); 832 event_copy->session_x11_display = g_strdup (event->session_x11_display); 833 event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device); 834 event_copy->session_display_device = g_strdup (event->session_display_device); 835 @@ -232,6 +237,7 @@ event_seat_session_removed_copy (CkLogSeatSessionRemovedEvent *event, 836 event_copy->seat_id = g_strdup (event->seat_id); 837 event_copy->session_id = g_strdup (event->session_id); 838 event_copy->session_type = g_strdup (event->session_type); 839 + event_copy->display_type = g_strdup (event->display_type); 840 event_copy->session_x11_display = g_strdup (event->session_x11_display); 841 event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device); 842 event_copy->session_display_device = g_strdup (event->session_display_device); 843 @@ -415,10 +421,11 @@ add_log_for_seat_session_added (GString *str, 844 845 e = (CkLogSeatSessionAddedEvent *)event; 846 g_string_append_printf (str, 847 - "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'", 848 + "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'", 849 e->seat_id ? e->seat_id : "", 850 e->session_id ? e->session_id : "", 851 e->session_type ? e->session_type : "", 852 + e->display_type ? e->display_type : "", 853 e->session_x11_display ? e->session_x11_display : "", 854 e->session_x11_display_device ? e->session_x11_display_device : "", 855 e->session_display_device ? e->session_display_device : "", 856 @@ -436,10 +443,11 @@ add_log_for_seat_session_removed (GString *str, 857 858 e = (CkLogSeatSessionRemovedEvent *)event; 859 g_string_append_printf (str, 860 - "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'", 861 + "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'", 862 e->seat_id ? e->seat_id : "", 863 e->session_id ? e->session_id : "", 864 e->session_type ? e->session_type : "", 865 + e->display_type ? e->display_type : "", 866 e->session_x11_display ? e->session_x11_display : "", 867 e->session_x11_display_device ? e->session_x11_display_device : "", 868 e->session_display_device ? e->session_display_device : "", 869 @@ -939,7 +947,7 @@ parse_log_for_seat_session_added (const GString *str, 870 } 871 872 error = NULL; 873 - re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' session-id='(?P<sessionid>[a-zA-Z0-9/]+)' session-type='(?P<sessiontype>[a-zA-Z0-9 ]*)' session-x11-display='(?P<sessionx11display>[0-9a-zA-Z.:]*)' session-x11-display-device='(?P<sessionx11displaydevice>[^']*)' session-display-device='(?P<sessiondisplaydevice>[^']*)' session-remote-host-name='(?P<sessionremovehostname>[^']*)' session-is-local=(?P<sessionislocal>[a-zA-Z]*) session-unix-user=(?P<sessionunixuser>[0-9]*) session-creation-time='(?P<sessioncreationtime>[^']*)'", 0, 0, &error); 874 + re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' session-id='(?P<sessionid>[a-zA-Z0-9/]+)' session-type='(?P<sessiontype>[a-zA-Z0-9 ]*)' display-type='(?P<displaytype>[a-zA-Z0-9 ]*)' session-x11-display='(?P<sessionx11display>[0-9a-zA-Z.:]*)' session-x11-display-device='(?P<sessionx11displaydevice>[^']*)' session-display-device='(?P<sessiondisplaydevice>[^']*)' session-remote-host-name='(?P<sessionremovehostname>[^']*)' session-is-local=(?P<sessionislocal>[a-zA-Z]*) session-unix-user=(?P<sessionunixuser>[0-9]*) session-creation-time='(?P<sessioncreationtime>[^']*)'", 0, 0, &error); 875 if (re == NULL) { 876 g_warning (error->message); 877 goto out; 878 @@ -957,6 +965,7 @@ parse_log_for_seat_session_added (const GString *str, 879 e->seat_id = g_match_info_fetch_named (match_info, "seatid"); 880 e->session_id = g_match_info_fetch_named (match_info, "sessionid"); 881 e->session_type = g_match_info_fetch_named (match_info, "sessiontype"); 882 + e->display_type = g_match_info_fetch_named (match_info, "displaytype"); 883 e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display"); 884 e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice"); 885 e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice"); 886 @@ -1014,7 +1023,7 @@ parse_log_for_seat_session_removed (const GString *str, 887 } 888 889 error = NULL; 890 - re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' session-id='(?P<sessionid>[a-zA-Z0-9/]+)' session-type='(?P<sessiontype>[a-zA-Z0-9 ]*)' session-x11-display='(?P<sessionx11display>[0-9a-zA-Z.:]*)' session-x11-display-device='(?P<sessionx11displaydevice>[^']*)' session-display-device='(?P<sessiondisplaydevice>[^']*)' session-remote-host-name='(?P<sessionremovehostname>[^']*)' session-is-local=(?P<sessionislocal>[a-zA-Z]*) session-unix-user=(?P<sessionunixuser>[0-9]*) session-creation-time='(?P<sessioncreationtime>[^']*)'", 0, 0, &error); 891 + re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' session-id='(?P<sessionid>[a-zA-Z0-9/]+)' session-type='(?P<sessiontype>[a-zA-Z0-9 ]*)' display-type='(?P<displaytype>[a-zA-Z0-9 ]*)' session-x11-display='(?P<sessionx11display>[0-9a-zA-Z.:]*)' session-x11-display-device='(?P<sessionx11displaydevice>[^']*)' session-display-device='(?P<sessiondisplaydevice>[^']*)' session-remote-host-name='(?P<sessionremovehostname>[^']*)' session-is-local=(?P<sessionislocal>[a-zA-Z]*) session-unix-user=(?P<sessionunixuser>[0-9]*) session-creation-time='(?P<sessioncreationtime>[^']*)'", 0, 0, &error); 892 if (re == NULL) { 893 g_warning (error->message); 894 goto out; 895 @@ -1032,6 +1041,7 @@ parse_log_for_seat_session_removed (const GString *str, 896 e->seat_id = g_match_info_fetch_named (match_info, "seatid"); 897 e->session_id = g_match_info_fetch_named (match_info, "sessionid"); 898 e->session_type = g_match_info_fetch_named (match_info, "sessiontype"); 899 + e->display_type = g_match_info_fetch_named (match_info, "displaytype"); 900 e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display"); 901 e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice"); 902 e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice"); 903 diff --git a/src/ck-log-event.h b/src/ck-log-event.h 904 index 65571f0..2d4ed4e 100644 905 --- a/src/ck-log-event.h 906 +++ b/src/ck-log-event.h 907 @@ -68,6 +68,7 @@ typedef struct 908 { 909 char *seat_id; 910 int seat_kind; 911 + char *seat_type; 912 } CkLogSeatAddedEvent; 913 914 typedef struct 915 @@ -81,11 +82,13 @@ typedef struct 916 char *seat_id; 917 char *session_id; 918 char *session_type; 919 + char *display_type; 920 char *session_x11_display; 921 char *session_x11_display_device; 922 char *session_display_device; 923 char *session_remote_host_name; 924 gboolean session_is_local; 925 + gboolean session_is_dynamic; 926 guint session_unix_user; 927 char *session_creation_time; 928 } CkLogSeatSessionAddedEvent; 929 @@ -95,11 +98,13 @@ typedef struct 930 char *seat_id; 931 char *session_id; 932 char *session_type; 933 + char *display_type; 934 char *session_x11_display; 935 char *session_x11_display_device; 936 char *session_display_device; 937 char *session_remote_host_name; 938 gboolean session_is_local; 939 + gboolean session_is_dynamic; 940 guint session_unix_user; 941 char *session_creation_time; 942 } CkLogSeatSessionRemovedEvent; 943 diff --git a/src/ck-manager.c b/src/ck-manager.c 944 index d436a06..47c1945 100644 945 --- a/src/ck-manager.c 946 +++ b/src/ck-manager.c 947 @@ -46,9 +46,14 @@ 948 #include <secdb.h> 949 #endif 950 951 +#ifndef HAVE_STRVERSCMP 952 +#include "strverscmp.h" 953 +#endif 954 + 955 #include "ck-manager.h" 956 #include "ck-manager-glue.h" 957 #include "ck-seat.h" 958 +#include "ck-display-template.h" 959 #include "ck-session-leader.h" 960 #include "ck-session.h" 961 #include "ck-marshal.h" 962 @@ -58,12 +63,19 @@ 963 964 #define CK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_MANAGER, CkManagerPrivate)) 965 966 +#define CK_TYPE_PARAMETER_STRUCT (dbus_g_type_get_struct ("GValueArray", \ 967 + G_TYPE_STRING, \ 968 + G_TYPE_VALUE, \ 969 + G_TYPE_INVALID)) 970 + 971 #define CK_SEAT_DIR SYSCONFDIR "/ConsoleKit/seats.d" 972 #define LOG_FILE LOCALSTATEDIR "/log/ConsoleKit/history" 973 #define CK_DBUS_PATH "/org/freedesktop/ConsoleKit" 974 #define CK_MANAGER_DBUS_PATH CK_DBUS_PATH "/Manager" 975 #define CK_MANAGER_DBUS_NAME "org.freedesktop.ConsoleKit.Manager" 976 977 +#define IS_STR_SET(x) (x != NULL && x[0] != '\0') 978 + 979 struct CkManagerPrivate 980 { 981 #ifdef HAVE_POLKIT 982 @@ -392,6 +404,7 @@ log_seat_added_event (CkManager *manager, 983 GError *error; 984 char *sid; 985 CkSeatKind seat_kind; 986 + char *seat_type; 987 988 memset (&event, 0, sizeof (CkLogEvent)); 989 990 @@ -401,9 +414,11 @@ log_seat_added_event (CkManager *manager, 991 sid = NULL; 992 ck_seat_get_id (seat, &sid, NULL); 993 ck_seat_get_kind (seat, &seat_kind, NULL); 994 + ck_seat_get_type_string (seat, &seat_type, NULL); 995 996 event.event.seat_added.seat_id = (char *)get_object_id_basename (sid); 997 event.event.seat_added.seat_kind = (int)seat_kind; 998 + event.event.seat_added.seat_type = (char *)seat_type; 999 1000 error = NULL; 1001 res = ck_event_logger_queue_event (manager->priv->logger, &event, &error); 1002 @@ -413,6 +428,7 @@ log_seat_added_event (CkManager *manager, 1003 } 1004 1005 g_free (sid); 1006 + g_free (seat_type); 1007 } 1008 1009 static void 1010 @@ -517,6 +533,7 @@ log_seat_session_added_event (CkManager *manager, 1011 if (session != NULL) { 1012 g_object_get (session, 1013 "session-type", &event.event.seat_session_added.session_type, 1014 + "display-type", &event.event.seat_session_added.display_type, 1015 "x11-display", &event.event.seat_session_added.session_x11_display, 1016 "x11-display-device", &event.event.seat_session_added.session_x11_display_device, 1017 "display-device", &event.event.seat_session_added.session_display_device, 1018 @@ -572,6 +589,7 @@ log_seat_session_removed_event (CkManager *manager, 1019 if (session != NULL) { 1020 g_object_get (session, 1021 "session-type", &event.event.seat_session_removed.session_type, 1022 + "display-type", &event.event.seat_session_removed.display_type, 1023 "x11-display", &event.event.seat_session_removed.session_x11_display, 1024 "x11-display-device", &event.event.seat_session_removed.session_x11_display_device, 1025 "display-device", &event.event.seat_session_removed.session_display_device, 1026 @@ -1324,15 +1342,21 @@ disconnect_seat_signals (CkManager *manager, 1027 } 1028 1029 static CkSeat * 1030 -add_new_seat (CkManager *manager, 1031 - CkSeatKind kind) 1032 +add_new_seat (CkManager *manager, 1033 + const char *give_sid, 1034 + CkSeatKind kind, 1035 + const char *type) 1036 { 1037 char *sid; 1038 CkSeat *seat; 1039 1040 - sid = generate_seat_id (manager); 1041 + if (IS_STR_SET (give_sid)) { 1042 + sid = g_strdup (give_sid); 1043 + } else { 1044 + sid = generate_seat_id (manager); 1045 + } 1046 1047 - seat = ck_seat_new (sid, kind); 1048 + seat = ck_seat_new (sid, kind, type); 1049 1050 /* First we connect our own signals to the seat, followed by 1051 * the D-Bus signal hookup to make sure we can first dump the 1052 @@ -1357,7 +1381,7 @@ add_new_seat (CkManager *manager, 1053 ck_seat_run_programs (seat, NULL, NULL, "seat_added"); 1054 1055 g_debug ("Emitting seat-added: %s", sid); 1056 - g_signal_emit (manager, signals [SEAT_ADDED], 0, sid); 1057 + g_signal_emit (manager, signals [SEAT_ADDED], 0, sid, type); 1058 1059 log_seat_added_event (manager, seat); 1060 1061 @@ -1415,64 +1439,22 @@ remove_seat (CkManager *manager, 1062 g_free (sid); 1063 } 1064 1065 -#define IS_STR_SET(x) (x != NULL && x[0] != '\0') 1066 - 1067 static CkSeat * 1068 find_seat_for_session (CkManager *manager, 1069 CkSession *session) 1070 { 1071 CkSeat *seat; 1072 - gboolean is_static_x11; 1073 - gboolean is_static_text; 1074 - char *display_device; 1075 - char *x11_display_device; 1076 - char *x11_display; 1077 - char *remote_host_name; 1078 - gboolean is_local; 1079 - 1080 - is_static_text = FALSE; 1081 - is_static_x11 = FALSE; 1082 - 1083 - seat = NULL; 1084 - display_device = NULL; 1085 - x11_display_device = NULL; 1086 - x11_display = NULL; 1087 - remote_host_name = NULL; 1088 - is_local = FALSE; 1089 - 1090 - /* FIXME: use matching to group entries? */ 1091 - 1092 - ck_session_get_display_device (session, &display_device, NULL); 1093 - ck_session_get_x11_display_device (session, &x11_display_device, NULL); 1094 - ck_session_get_x11_display (session, &x11_display, NULL); 1095 - ck_session_get_remote_host_name (session, &remote_host_name, NULL); 1096 - ck_session_is_local (session, &is_local, NULL); 1097 - 1098 - if (IS_STR_SET (x11_display) 1099 - && IS_STR_SET (x11_display_device) 1100 - && ! IS_STR_SET (remote_host_name) 1101 - && is_local == TRUE) { 1102 - is_static_x11 = TRUE; 1103 - } else if (! IS_STR_SET (x11_display) 1104 - && ! IS_STR_SET (x11_display_device) 1105 - && IS_STR_SET (display_device) 1106 - && ! IS_STR_SET (remote_host_name) 1107 - && is_local == TRUE) { 1108 - is_static_text = TRUE; 1109 - } 1110 - 1111 - if (is_static_x11 || is_static_text) { 1112 - char *sid; 1113 + char *sid = NULL; 1114 + 1115 + ck_session_get_seat_id (session, &sid, NULL); 1116 + 1117 + if (! IS_STR_SET (sid)) { 1118 sid = g_strdup_printf ("%s/Seat%u", CK_DBUS_PATH, 1); 1119 - seat = g_hash_table_lookup (manager->priv->seats, sid); 1120 - g_free (sid); 1121 } 1122 1123 - g_free (display_device); 1124 - g_free (x11_display_device); 1125 - g_free (x11_display); 1126 - g_free (remote_host_name); 1127 + seat = g_hash_table_lookup (manager->priv->seats, sid); 1128 1129 + g_free (sid); 1130 return seat; 1131 } 1132 1133 @@ -1612,31 +1594,40 @@ open_session_for_leader (CkManager *manager, 1134 ssid = ck_session_leader_peek_session_id (leader); 1135 cookie = ck_session_leader_peek_cookie (leader); 1136 1137 - session = ck_session_new_with_parameters (ssid, 1138 - cookie, 1139 - parameters); 1140 + session = g_hash_table_lookup (manager->priv->sessions, ssid); 1141 1142 if (session == NULL) { 1143 - GError *error; 1144 - g_debug ("Unable to create new session"); 1145 - error = g_error_new (CK_MANAGER_ERROR, 1146 - CK_MANAGER_ERROR_GENERAL, 1147 - "Unable to create new session"); 1148 - dbus_g_method_return_error (context, error); 1149 - g_error_free (error); 1150 + session = ck_session_new_with_parameters (ssid, 1151 + parameters); 1152 + 1153 + if (session == NULL) { 1154 + GError *error; 1155 + g_debug ("Unable to create new session"); 1156 + error = g_error_new (CK_MANAGER_ERROR, 1157 + CK_MANAGER_ERROR_GENERAL, 1158 + "Unable to create new session"); 1159 + dbus_g_method_return_error (context, error); 1160 + g_error_free (error); 1161 1162 - return; 1163 + return; 1164 + } 1165 + 1166 + g_hash_table_insert (manager->priv->sessions, 1167 + g_strdup (ssid), 1168 + g_object_ref (session)); 1169 + 1170 + } else { 1171 + ck_session_set_parameters (session, parameters); 1172 } 1173 1174 - g_hash_table_insert (manager->priv->sessions, 1175 - g_strdup (ssid), 1176 - g_object_ref (session)); 1177 + ck_session_set_cookie (session, cookie, NULL); 1178 + ck_session_set_is_open (session, TRUE, NULL); 1179 1180 /* Add to seat */ 1181 seat = find_seat_for_session (manager, session); 1182 if (seat == NULL) { 1183 /* create a new seat */ 1184 - seat = add_new_seat (manager, CK_SEAT_KIND_DYNAMIC); 1185 + seat = add_new_seat (manager, NULL, CK_SEAT_KIND_DYNAMIC, "Default"); 1186 } 1187 1188 ck_seat_add_session (seat, session, NULL); 1189 @@ -1710,11 +1701,57 @@ generate_session_for_leader (CkManager *manager, 1190 } 1191 } 1192 1193 +static char * 1194 +check_parameters_for_ssid (const GPtrArray *parameters) 1195 +{ 1196 + int i; 1197 + 1198 + if (parameters == NULL) { 1199 + return NULL; 1200 + } 1201 + 1202 + for (i = 0; i < parameters->len; i++) { 1203 + GValue val_struct = { 0, }; 1204 + char *prop_name; 1205 + gboolean res; 1206 + 1207 + g_value_init (&val_struct, CK_TYPE_PARAMETER_STRUCT); 1208 + g_value_set_static_boxed (&val_struct, g_ptr_array_index (parameters, i)); 1209 + 1210 + res = dbus_g_type_struct_get (&val_struct, 1211 + 0, &prop_name, 1212 + G_MAXUINT); 1213 + if (! res) { 1214 + g_debug ("Unable to read parameter name"); 1215 + continue; 1216 + } 1217 + 1218 + if (prop_name != NULL && strcmp (prop_name, "session") == 0) { 1219 + GValue prop_val = { 0, }; 1220 + GValue *session_val; 1221 + 1222 + g_value_init (&prop_val, G_TYPE_VALUE); 1223 + res = dbus_g_type_struct_get_member (&val_struct, 1, &prop_val); 1224 + 1225 + if (! res) { 1226 + g_debug ("Unable to read parameter value"); 1227 + continue; 1228 + } 1229 + 1230 + session_val = g_value_get_boxed (&prop_val); 1231 + 1232 + return g_value_dup_string (session_val); 1233 + } 1234 + } 1235 + 1236 + return NULL; 1237 +} 1238 + 1239 static gboolean 1240 -create_session_for_sender (CkManager *manager, 1241 - const char *sender, 1242 - const GPtrArray *parameters, 1243 - DBusGMethodInvocation *context) 1244 +open_session_for_sender (CkManager *manager, 1245 + const char *sender, 1246 + const GPtrArray *parameters, 1247 + DBusGMethodInvocation *context) 1248 { 1249 pid_t pid; 1250 uid_t uid; 1251 @@ -1722,6 +1759,7 @@ create_session_for_sender (CkManager *manager, 1252 char *cookie; 1253 char *ssid; 1254 CkSessionLeader *leader; 1255 + CkSession *session; 1256 1257 g_debug ("CkManager: create session for sender: %s", sender); 1258 1259 @@ -1740,9 +1778,21 @@ create_session_for_sender (CkManager *manager, 1260 } 1261 1262 cookie = generate_session_cookie (manager); 1263 - ssid = generate_session_id (manager); 1264 1265 - g_debug ("Creating new session ssid: %s", ssid); 1266 + ssid = check_parameters_for_ssid (parameters); 1267 + 1268 + if (IS_STR_SET (ssid)) { 1269 + session = g_hash_table_lookup (manager->priv->sessions, ssid); 1270 + 1271 + /* FIXME: Need to verify that the session belongs to a seat 1272 + * managed by the sender 1273 + */ 1274 + g_debug ("Managing existing session ssid: %s", ssid); 1275 + } else { 1276 + ssid = generate_session_id (manager); 1277 + session = NULL; 1278 + g_debug ("Creating new session ssid: %s", ssid); 1279 + } 1280 1281 leader = ck_session_leader_new (); 1282 ck_session_leader_set_uid (leader, uid); 1283 @@ -1980,7 +2030,7 @@ ck_manager_open_session (CkManager *manager, 1284 gboolean ret; 1285 1286 sender = dbus_g_method_get_sender (context); 1287 - ret = create_session_for_sender (manager, sender, NULL, context); 1288 + ret = open_session_for_sender (manager, sender, NULL, context); 1289 g_free (sender); 1290 1291 return ret; 1292 @@ -1995,7 +2045,7 @@ ck_manager_open_session_with_parameters (CkManager *manager, 1293 gboolean ret; 1294 1295 sender = dbus_g_method_get_sender (context); 1296 - ret = create_session_for_sender (manager, sender, parameters, context); 1297 + ret = open_session_for_sender (manager, sender, parameters, context); 1298 g_free (sender); 1299 1300 return ret; 1301 @@ -2012,10 +2062,12 @@ remove_session_for_cookie (CkManager *manager, 1302 char *sid; 1303 gboolean res; 1304 gboolean ret; 1305 + gboolean should_remove_session; 1306 1307 ret = FALSE; 1308 orig_ssid = NULL; 1309 orig_session = NULL; 1310 + should_remove_session = FALSE; 1311 1312 g_debug ("Removing session for cookie: %s", cookie); 1313 1314 @@ -2042,6 +2094,17 @@ remove_session_for_cookie (CkManager *manager, 1315 goto out; 1316 } 1317 1318 + ck_session_set_is_open (orig_session, FALSE, NULL); 1319 + ck_session_set_cookie (orig_session, NULL, NULL); 1320 + ck_session_set_active (orig_session, FALSE, NULL); 1321 + ck_session_set_unix_user (orig_session, 0, NULL); 1322 + ck_session_set_x11_display (orig_session, NULL, NULL); 1323 + ck_session_set_x11_display_device (orig_session, NULL, NULL); 1324 + ck_session_set_display_device (orig_session, NULL, NULL); 1325 + ck_session_set_login_session_id (orig_session, NULL, NULL); 1326 + ck_session_set_remote_host_name (orig_session, NULL, NULL); 1327 + ck_session_set_under_request (orig_session, FALSE, NULL); 1328 + 1329 /* Must keep a reference to the session in the manager until 1330 * all events for seats are cleared. So don't remove 1331 * or steal the session from the master list until 1332 @@ -2049,31 +2112,35 @@ remove_session_for_cookie (CkManager *manager, 1333 * for seat removals doesn't work. 1334 */ 1335 1336 - /* remove from seat */ 1337 - sid = NULL; 1338 - ck_session_get_seat_id (orig_session, &sid, NULL); 1339 - if (sid != NULL) { 1340 - CkSeat *seat; 1341 - seat = g_hash_table_lookup (manager->priv->seats, sid); 1342 - if (seat != NULL) { 1343 - CkSeatKind kind; 1344 - 1345 - ck_seat_remove_session (seat, orig_session, NULL); 1346 - 1347 - kind = CK_SEAT_KIND_STATIC; 1348 - /* if dynamic seat has no sessions then remove it */ 1349 - ck_seat_get_kind (seat, &kind, NULL); 1350 - if (kind == CK_SEAT_KIND_DYNAMIC) { 1351 - remove_seat (manager, seat); 1352 + ck_session_get_remove_on_close (orig_session, &should_remove_session, NULL); 1353 + 1354 + if (should_remove_session) { 1355 + /* remove from seat */ 1356 + sid = NULL; 1357 + ck_session_get_seat_id (orig_session, &sid, NULL); 1358 + if (sid != NULL) { 1359 + CkSeat *seat; 1360 + seat = g_hash_table_lookup (manager->priv->seats, sid); 1361 + if (seat != NULL) { 1362 + CkSeatKind kind; 1363 + 1364 + ck_seat_remove_session (seat, orig_session, NULL); 1365 + 1366 + kind = CK_SEAT_KIND_STATIC; 1367 + /* if dynamic seat has no sessions then remove it */ 1368 + ck_seat_get_kind (seat, &kind, NULL); 1369 + if (kind == CK_SEAT_KIND_DYNAMIC) { 1370 + g_hash_table_remove (manager->priv->sessions, orig_ssid); 1371 + } 1372 } 1373 } 1374 - } 1375 - g_free (sid); 1376 + g_free (sid); 1377 1378 - /* Remove the session from the list but don't call 1379 - * unref until we are done with it */ 1380 - g_hash_table_steal (manager->priv->sessions, 1381 - ck_session_leader_peek_session_id (leader)); 1382 + /* Remove the session from the list but don't call 1383 + * unref until we are done with it */ 1384 + g_hash_table_steal (manager->priv->sessions, 1385 + ck_session_leader_peek_session_id (leader)); 1386 + } 1387 1388 ck_manager_dump (manager); 1389 1390 @@ -2081,11 +2148,13 @@ remove_session_for_cookie (CkManager *manager, 1391 1392 ret = TRUE; 1393 out: 1394 - if (orig_session != NULL) { 1395 - g_object_unref (orig_session); 1396 - } 1397 - g_free (orig_ssid); 1398 + if (should_remove_session) { 1399 + if (orig_session != NULL) { 1400 + g_object_unref (orig_session); 1401 + } 1402 1403 + g_free (orig_ssid); 1404 + } 1405 return ret; 1406 } 1407 1408 @@ -2303,9 +2372,11 @@ ck_manager_class_init (CkManagerClass *klass) 1409 G_STRUCT_OFFSET (CkManagerClass, seat_added), 1410 NULL, 1411 NULL, 1412 - g_cclosure_marshal_VOID__BOXED, 1413 + ck_marshal_VOID__STRING_STRING, 1414 G_TYPE_NONE, 1415 - 1, DBUS_TYPE_G_OBJECT_PATH); 1416 + 2, 1417 + G_TYPE_STRING, 1418 + G_TYPE_STRING); 1419 signals [SEAT_REMOVED] = 1420 g_signal_new ("seat-removed", 1421 G_TYPE_FROM_CLASS (object_class), 1422 @@ -2412,6 +2483,43 @@ ck_manager_get_seats (CkManager *manager, 1423 } 1424 1425 static void 1426 +listify_unmanaged_seat_ids (char *id, 1427 + CkSeat *seat, 1428 + GPtrArray **array) 1429 +{ 1430 + if (ck_seat_is_managed (seat)) { 1431 + return; 1432 + } 1433 + 1434 + g_ptr_array_add (*array, g_strdup (id)); 1435 +} 1436 + 1437 + 1438 +/* 1439 + Example: 1440 + dbus-send --system --dest=org.freedesktop.ConsoleKit \ 1441 + --type=method_call --print-reply --reply-timeout=2000 \ 1442 + /org/freedesktop/ConsoleKit/Manager \ 1443 + org.freedesktop.ConsoleKit.Manager.GetUnmanagedSeats 1444 +*/ 1445 +gboolean 1446 +ck_manager_get_unmanaged_seats (CkManager *manager, 1447 + GPtrArray **seats, 1448 + GError **error) 1449 +{ 1450 + g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); 1451 + 1452 + if (seats == NULL) { 1453 + return FALSE; 1454 + } 1455 + 1456 + *seats = g_ptr_array_new (); 1457 + g_hash_table_foreach (manager->priv->seats, (GHFunc)listify_unmanaged_seat_ids, seats); 1458 + 1459 + return TRUE; 1460 +} 1461 + 1462 +static void 1463 listify_session_ids (char *id, 1464 CkSession *session, 1465 GPtrArray **array) 1466 @@ -2436,16 +2544,307 @@ ck_manager_get_sessions (CkManager *manager, 1467 return TRUE; 1468 } 1469 1470 +/* 1471 + Example: 1472 + dbus-send --system --dest=org.freedesktop.ConsoleKit \ 1473 + --type=method_call --print-reply --reply-timeout=2000 \ 1474 + /org/freedesktop/ConsoleKit/Manager \ 1475 + org.freedesktop.ConsoleKit.Manager.AddSeat string:Default 1476 +*/ 1477 +gboolean 1478 +ck_manager_add_seat (CkManager *manager, 1479 + const char *type, 1480 + char **sid, 1481 + GError **error) 1482 +{ 1483 + CkSeat *seat; 1484 + 1485 + g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); 1486 + 1487 + seat = add_new_seat (manager, NULL, CK_SEAT_KIND_DYNAMIC, type); 1488 + 1489 + if (!ck_seat_get_id (seat, sid, error)) { 1490 + return FALSE; 1491 + } 1492 + 1493 + return TRUE; 1494 +} 1495 + 1496 +/* 1497 + Example: 1498 + dbus-send --system --dest=org.freedesktop.ConsoleKit \ 1499 + --type=method_call --print-reply --reply-timeout=2000 \ 1500 + /org/freedesktop/ConsoleKit/Manager \ 1501 + org.freedesktop.ConsoleKit.Manager.AddSeatById \ 1502 + objpath:/org/freedesktop/ConsoleKit/SeatTest \ 1503 +*/ 1504 +gboolean 1505 +ck_manager_add_seat_by_id (CkManager *manager, 1506 + const char *type, 1507 + const char *sid, 1508 + GError **error) 1509 +{ 1510 + CkSeat *seat; 1511 + 1512 + g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); 1513 + 1514 + seat = add_new_seat (manager, sid, CK_SEAT_KIND_DYNAMIC, type); 1515 + 1516 + return !(seat == NULL); 1517 +} 1518 + 1519 +/* 1520 + Example: 1521 + dbus-send --system --dest=org.freedesktop.ConsoleKit \ 1522 + --type=method_call --print-reply --reply-timeout=2000 \ 1523 + /org/freedesktop/ConsoleKit/Manager \ 1524 + org.freedesktop.ConsoleKit.Manager.RemoveSeat \ 1525 + obj:/org/freedesktop/ConsoleKit/Seat2 1526 +*/ 1527 +gboolean 1528 +ck_manager_remove_seat (CkManager *manager, 1529 + const char *sid, 1530 + DBusGMethodInvocation *context) 1531 +{ 1532 + CkSeat *seat = NULL; 1533 + CkSeatKind kind; 1534 + 1535 + g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE); 1536 + 1537 + seat = g_hash_table_lookup (manager->priv->seats, sid); 1538 + 1539 + if (seat == NULL) { 1540 + GError *error; 1541 + 1542 + error = g_error_new (CK_SEAT_ERROR, 1543 + CK_SEAT_ERROR_GENERAL, 1544 + _("Seat '%s' doesn't exist"), 1545 + sid); 1546 + 1547 + dbus_g_method_return_error (context, error); 1548 + g_error_free (error); 1549 + 1550 + return FALSE; 1551 + } 1552 + 1553 + ck_seat_get_kind (seat, &kind, NULL); 1554 + 1555 + if (kind == CK_SEAT_KIND_STATIC) { 1556 + GError *error; 1557 + 1558 + error = g_error_new (CK_SEAT_ERROR, 1559 + CK_SEAT_ERROR_GENERAL, 1560 + _("Seat '%s' is static and can't be removed"), 1561 + sid); 1562 + 1563 + dbus_g_method_return_error (context, error); 1564 + g_error_free (error); 1565 + 1566 + return FALSE; 1567 + } 1568 + 1569 + if (ck_seat_is_managed (seat)) { 1570 + ck_seat_request_removal (seat); 1571 + } else { 1572 + remove_seat (manager, seat); 1573 + } 1574 + 1575 + return TRUE; 1576 +} 1577 + 1578 +/* 1579 + Example: 1580 + dbus-send --system --dest=org.freedesktop.ConsoleKit \ 1581 + --type=method_call --print-reply --reply-timeout=2000 \ 1582 + /org/freedesktop/ConsoleKit/Manager \ 1583 + org.freedesktop.ConsoleKit.Manager.AddSession \ 1584 + objpath:/org/freedesktop/ConsoleKit/Seat2 \ 1585 + string:"LoginWindow" \ 1586 + dict:string:string:"vt","vt9","display",":123" 1587 +*/ 1588 +gboolean 1589 +ck_manager_add_session (CkManager *manager, 1590 + const char *sid, 1591 + const char *type, 1592 + const char *display_type, 1593 + GHashTable *variables, 1594 + DBusGMethodInvocation *context) 1595 +{ 1596 + CkSeat *seat; 1597 + CkSession *session; 1598 + char *ssid; 1599 + 1600 + seat = g_hash_table_lookup (manager->priv->seats, sid); 1601 + 1602 + if (seat == NULL) { 1603 + GError *error; 1604 + 1605 + error = g_error_new (CK_SEAT_ERROR, 1606 + CK_SEAT_ERROR_GENERAL, 1607 + _("Seat '%s' doesn't exist"), 1608 + sid); 1609 + 1610 + dbus_g_method_return_error (context, error); 1611 + g_error_free (error); 1612 + 1613 + return FALSE; 1614 + } 1615 + 1616 + ssid = generate_session_id (manager); 1617 + 1618 + session = ck_session_new (ssid, type, display_type, variables); 1619 + 1620 + if (session == NULL) { 1621 + GError *error; 1622 + 1623 + error = g_error_new (CK_SEAT_ERROR, 1624 + CK_SEAT_ERROR_GENERAL, 1625 + _("Session could not be added to seat '%s'"), 1626 + sid); 1627 + 1628 + dbus_g_method_return_error (context, error); 1629 + g_error_free (error); 1630 + 1631 + return FALSE; 1632 + } 1633 + 1634 + ck_session_set_seat_id (session, sid, NULL); 1635 + session_set_remove_on_close (session, TRUE, NULL); 1636 + 1637 + ck_seat_add_session (seat, session, NULL); 1638 + 1639 + g_hash_table_insert (manager->priv->sessions, 1640 + ssid, 1641 + session); 1642 + 1643 + dbus_g_method_return (context, ssid); 1644 + return TRUE; 1645 +} 1646 + 1647 +/* 1648 + Example: 1649 + dbus-send --system --dest=org.freedesktop.ConsoleKit \ 1650 + --type=method_call --print-reply --reply-timeout=2000 \ 1651 + /org/freedesktop/ConsoleKit/Manager \ 1652 + org.freedesktop.ConsoleKit.Manager.RemoveSession \ 1653 + objpath:/org/freedesktop/ConsoleKit/Session2 1654 +*/ 1655 +gboolean 1656 +ck_manager_remove_session (CkManager *manager, 1657 + const char *ssid, 1658 + DBusGMethodInvocation *context) 1659 +{ 1660 + CkSession *session; 1661 + CkSeat *seat; 1662 + GError *error; 1663 + char *sid; 1664 + gboolean is_open; 1665 + 1666 + session = g_hash_table_lookup (manager->priv->sessions, ssid); 1667 + 1668 + if (session == NULL) { 1669 + GError *error; 1670 + 1671 + error = g_error_new (CK_SEAT_ERROR, 1672 + CK_SEAT_ERROR_GENERAL, 1673 + _("Session '%s' doesn't exist"), 1674 + ssid); 1675 + 1676 + dbus_g_method_return_error (context, error); 1677 + g_error_free (error); 1678 + 1679 + return FALSE; 1680 + } 1681 + 1682 + ck_session_get_seat_id (session, &sid, NULL); 1683 + seat = g_hash_table_lookup (manager->priv->seats, sid); 1684 + g_free (sid); 1685 + 1686 + if (seat == NULL) { 1687 + g_warning ("Session '%s' is not associated with a seat", ssid); 1688 + g_hash_table_remove (manager->priv->sessions, ssid); 1689 + return TRUE; 1690 + } 1691 + 1692 + error = NULL; 1693 + 1694 + ck_session_is_open (session, &is_open, NULL); 1695 + session_set_remove_on_close (session, TRUE, NULL); 1696 + 1697 + /* We'll let the seat manager close us when it's ready 1698 + */ 1699 + if (ck_seat_is_managed (seat) && is_open) { 1700 + ck_seat_request_close_session (seat, session, NULL); 1701 + dbus_g_method_return (context); 1702 + 1703 + return TRUE; 1704 + } 1705 + 1706 + if (!ck_seat_remove_session (seat, session, &error)) { 1707 + if (error == NULL) { 1708 + return TRUE; 1709 + } 1710 + 1711 + dbus_g_method_return_error (context, error); 1712 + g_error_free (error); 1713 + return FALSE; 1714 + } 1715 + 1716 + g_hash_table_remove (manager->priv->sessions, ssid); 1717 + dbus_g_method_return (context); 1718 + return TRUE; 1719 +} 1720 + 1721 +static void 1722 +add_sessions_from_seat (CkManager *manager, 1723 + CkSeat *seat) 1724 +{ 1725 + GPtrArray *sessions; 1726 + int i; 1727 + 1728 + ck_seat_get_sessions (seat, &sessions, NULL); 1729 + 1730 + for (i = 0; i < sessions->len; i++) { 1731 + char *ssid; 1732 + CkSession *session; 1733 + 1734 + ssid = g_ptr_array_index (sessions, i); 1735 + session = ck_seat_get_session (seat, ssid); 1736 + 1737 + g_hash_table_insert (manager->priv->sessions, 1738 + ssid, 1739 + session); 1740 + } 1741 + 1742 + g_ptr_array_free (sessions, TRUE); 1743 +} 1744 + 1745 static void 1746 add_seat_for_file (CkManager *manager, 1747 const char *filename) 1748 { 1749 char *sid; 1750 + char *orig_sid; 1751 CkSeat *seat; 1752 1753 sid = generate_seat_id (manager); 1754 + orig_sid = g_strdup (sid); 1755 + seat = ck_seat_new_from_file (&sid, filename); 1756 + 1757 + if (seat == NULL) { 1758 + /* returns null if connection to bus fails */ 1759 + g_free (sid); 1760 + g_free (orig_sid); 1761 + manager->priv->seat_serial--; 1762 + return; 1763 + } 1764 1765 - seat = ck_seat_new_from_file (sid, filename); 1766 + if (!g_str_equal (orig_sid, sid)) { 1767 + manager->priv->seat_serial--; 1768 + } 1769 + g_free (orig_sid); 1770 + 1771 + add_sessions_from_seat (manager, seat); 1772 1773 connect_seat_signals (manager, seat); 1774 if (!ck_seat_register (seat)) { 1775 @@ -2464,7 +2863,7 @@ add_seat_for_file (CkManager *manager, 1776 ck_seat_run_programs (seat, NULL, NULL, "seat_added"); 1777 1778 g_debug ("Emitting seat-added: %s", sid); 1779 - g_signal_emit (manager, signals [SEAT_ADDED], 0, sid); 1780 + g_signal_emit (manager, signals [SEAT_ADDED], 0, sid, "Default"); 1781 1782 log_seat_added_event (manager, seat); 1783 } 1784 @@ -2475,6 +2874,7 @@ load_seats_from_dir (CkManager *manager) 1785 GDir *d; 1786 GError *error; 1787 const char *file; 1788 + GQueue seat_queue; 1789 1790 error = NULL; 1791 d = g_dir_open (CK_SEAT_DIR, 1792 @@ -2486,15 +2886,26 @@ load_seats_from_dir (CkManager *manager) 1793 return FALSE; 1794 } 1795 1796 + g_queue_init (&seat_queue); 1797 while ((file = g_dir_read_name (d)) != NULL) { 1798 char *path; 1799 path = g_build_filename (CK_SEAT_DIR, file, NULL); 1800 + g_queue_push_tail (&seat_queue, path); 1801 + } 1802 + g_dir_close (d); 1803 + 1804 + g_queue_sort (&seat_queue, (GCompareDataFunc) strverscmp, NULL); 1805 + 1806 + while (!g_queue_is_empty (&seat_queue)) { 1807 + char *path; 1808 + 1809 + path = g_queue_pop_head (&seat_queue); 1810 + 1811 add_seat_for_file (manager, path); 1812 + 1813 g_free (path); 1814 } 1815 1816 - g_dir_close (d); 1817 - 1818 return TRUE; 1819 } 1820 1821 @@ -2530,8 +2941,6 @@ ck_manager_init (CkManager *manager) 1822 (GDestroyNotify) g_object_unref); 1823 1824 manager->priv->logger = ck_event_logger_new (LOG_FILE); 1825 - 1826 - create_seats (manager); 1827 } 1828 1829 static void 1830 @@ -2576,6 +2985,8 @@ ck_manager_new (void) 1831 g_object_unref (manager_object); 1832 return NULL; 1833 } 1834 + 1835 + create_seats (CK_MANAGER (manager_object)); 1836 } 1837 1838 return CK_MANAGER (manager_object); 1839 diff --git a/src/ck-manager.h b/src/ck-manager.h 1840 index 4bd56e8..4304e71 100644 1841 --- a/src/ck-manager.h 1842 +++ b/src/ck-manager.h 1843 @@ -49,7 +49,8 @@ typedef struct 1844 GObjectClass parent_class; 1845 1846 void (* seat_added) (CkManager *manager, 1847 - const char *sid); 1848 + const char *sid, 1849 + const char *type); 1850 void (* seat_removed) (CkManager *manager, 1851 const char *sid); 1852 void (* system_idle_hint_changed) (CkManager *manager, 1853 @@ -96,6 +97,9 @@ gboolean ck_manager_get_sessions (CkManager 1854 gboolean ck_manager_get_seats (CkManager *manager, 1855 GPtrArray **seats, 1856 GError **error); 1857 +gboolean ck_manager_get_unmanaged_seats (CkManager *manager, 1858 + GPtrArray **seats, 1859 + GError **error); 1860 gboolean ck_manager_close_session (CkManager *manager, 1861 const char *cookie, 1862 DBusGMethodInvocation *context); 1863 @@ -128,6 +132,28 @@ gboolean ck_manager_open_session_with_parameters (CkManager 1864 const GPtrArray *parameters, 1865 DBusGMethodInvocation *context); 1866 1867 +gboolean ck_manager_add_seat (CkManager *manager, 1868 + const char *type, 1869 + char **sid, 1870 + GError **error); 1871 +gboolean ck_manager_add_seat_by_id (CkManager *manager, 1872 + const char *type, 1873 + const char *sid, 1874 + GError **error); 1875 +gboolean ck_manager_remove_seat (CkManager *manager, 1876 + const char *sid, 1877 + DBusGMethodInvocation *context); 1878 + 1879 +gboolean ck_manager_add_session (CkManager *manager, 1880 + const char *sid, 1881 + const char *type, 1882 + const char *display_type, 1883 + GHashTable *parameters, 1884 + DBusGMethodInvocation *context); 1885 +gboolean ck_manager_remove_session (CkManager *manager, 1886 + const char *ssid, 1887 + DBusGMethodInvocation *context); 1888 + 1889 G_END_DECLS 1890 1891 #endif /* __CK_MANAGER_H */ 1892 diff --git a/src/ck-marshal.list b/src/ck-marshal.list 1893 index 7f60efc..f8029a6 100644 1894 --- a/src/ck-marshal.list 1895 +++ b/src/ck-marshal.list 1896 @@ -1,3 +1,5 @@ 1897 VOID:UINT,STRING 1898 BOOLEAN:POINTER 1899 +VOID:STRING,STRING 1900 +VOID:STRING,BOOLEAN,STRING,POINTER,STRING,POINTER 1901 VOID:OBJECT,OBJECT 1902 diff --git a/src/ck-seat.c b/src/ck-seat.c 1903 index af7db59..c7b725a 100644 1904 --- a/src/ck-seat.c 1905 +++ b/src/ck-seat.c 1906 @@ -40,21 +40,30 @@ 1907 #include "ck-seat-glue.h" 1908 #include "ck-marshal.h" 1909 1910 +#include "ck-display-template.h" 1911 #include "ck-session.h" 1912 #include "ck-vt-monitor.h" 1913 #include "ck-run-programs.h" 1914 1915 #define CK_SEAT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SEAT, CkSeatPrivate)) 1916 1917 +#define CK_SESSION_DIR SYSCONFDIR "/ConsoleKit/sessions.d" 1918 + 1919 #define CK_DBUS_PATH "/org/freedesktop/ConsoleKit" 1920 #define CK_DBUS_NAME "org.freedesktop.ConsoleKit" 1921 1922 #define NONULL_STRING(x) ((x) != NULL ? (x) : "") 1923 +#define N_ELEMENTS(arr) (sizeof (arr) / sizeof ((arr)[0])) 1924 + 1925 +#define IS_STR_SET(x) (x != NULL && x[0] != '\0') 1926 + 1927 +#define CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING)) 1928 1929 struct CkSeatPrivate 1930 { 1931 char *id; 1932 CkSeatKind kind; 1933 + char *type; 1934 GHashTable *sessions; 1935 GPtrArray *devices; 1936 1937 @@ -63,6 +72,8 @@ struct CkSeatPrivate 1938 CkVtMonitor *vt_monitor; 1939 1940 DBusGConnection *connection; 1941 + 1942 + DBusGProxy *manager_proxy; 1943 }; 1944 1945 enum { 1946 @@ -74,6 +85,7 @@ enum { 1947 SESSION_REMOVED_FULL, 1948 DEVICE_ADDED, 1949 DEVICE_REMOVED, 1950 + REMOVE_REQUEST, 1951 LAST_SIGNAL 1952 }; 1953 1954 @@ -81,6 +93,7 @@ enum { 1955 PROP_0, 1956 PROP_ID, 1957 PROP_KIND, 1958 + PROP_TYPE 1959 }; 1960 1961 static guint signals [LAST_SIGNAL] = { 0, }; 1962 @@ -287,6 +300,7 @@ ck_seat_activate_session (CkSeat *seat, 1963 { 1964 CkSession *session; 1965 gboolean ret; 1966 + gboolean is_open; 1967 1968 g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); 1969 1970 @@ -298,12 +312,387 @@ ck_seat_activate_session (CkSeat *seat, 1971 session = g_hash_table_lookup (seat->priv->sessions, ssid); 1972 } 1973 1974 - ret = _seat_activate_session (seat, session, context); 1975 + ck_session_is_open (session, &is_open, NULL); 1976 + if (!is_open) { 1977 + ret = ck_seat_request_open_session (seat, session, NULL); 1978 + dbus_g_method_return (context, NULL); 1979 + } else { 1980 + ret = _seat_activate_session (seat, session, context); 1981 + } 1982 1983 return ret; 1984 } 1985 1986 static gboolean 1987 +on_substitution_match (const GMatchInfo *match_info, 1988 + GString *result, 1989 + GHashTable *substitution_variables) 1990 +{ 1991 + char *match; 1992 + char *value; 1993 + 1994 + match = g_match_info_fetch (match_info, 1); 1995 + 1996 + value = g_hash_table_lookup (substitution_variables, match); 1997 + 1998 + if (value != NULL) { 1999 + g_string_append (result, value); 2000 + } else { 2001 + char *original_string; 2002 + 2003 + original_string = g_match_info_fetch (match_info, 0); 2004 + g_string_append (result, original_string); 2005 + g_free (original_string); 2006 + } 2007 + g_free (match); 2008 + 2009 + return FALSE; 2010 +} 2011 + 2012 +static char * 2013 +apply_substitutions (const char *value, 2014 + GHashTable *substitution_variables) 2015 +{ 2016 + GRegex *expression; 2017 + char *expanded_string; 2018 + 2019 + expression = g_regex_new ("\\$([^[:space:]]+)", 0, 0, NULL); 2020 + expanded_string = g_regex_replace_eval (expression, 2021 + value, 2022 + -1, 0, 0, 2023 + (GRegexEvalCallback) 2024 + on_substitution_match, 2025 + substitution_variables, 2026 + NULL); 2027 + 2028 + if (expanded_string == NULL) { 2029 + expanded_string = g_strdup (value); 2030 + } 2031 + 2032 + return expanded_string; 2033 +} 2034 + 2035 +static GHashTable * 2036 +get_evaluated_parameter_map (GHashTable *parameters, 2037 + GHashTable *substitution_variables) 2038 +{ 2039 + GHashTable *evaluated_parameters; 2040 + GHashTableIter iter; 2041 + gpointer key, value; 2042 + 2043 + evaluated_parameters = g_hash_table_new_full (g_str_hash, g_str_equal, 2044 + (GDestroyNotify) g_free, 2045 + (GDestroyNotify) g_free); 2046 + 2047 + g_hash_table_iter_init (&iter, parameters); 2048 + while (g_hash_table_iter_next (&iter, &key, &value)) { 2049 + char *expanded_string; 2050 + 2051 + expanded_string = apply_substitutions ((char *) value, 2052 + substitution_variables); 2053 + 2054 + g_hash_table_insert (evaluated_parameters, 2055 + g_strdup ((char *) key), 2056 + expanded_string); 2057 + } 2058 + 2059 + return evaluated_parameters; 2060 +} 2061 + 2062 +static void 2063 +request_session (gpointer key, 2064 + gpointer value, 2065 + gpointer user_data) 2066 +{ 2067 + CkSeat *seat = CK_SEAT (user_data); 2068 + CkSession *session = (CkSession *) value; 2069 + 2070 + ck_session_set_ever_open (session, FALSE, NULL); 2071 + ck_session_set_under_request (session, FALSE, NULL); 2072 + ck_seat_request_open_session (seat, session, NULL); 2073 +} 2074 + 2075 +static void 2076 +append_hash_table_to_dbus_message_iter (DBusMessageIter *iter, 2077 + GHashTable *hash_table) 2078 +{ 2079 + GHashTableIter hash_table_iter; 2080 + gpointer key, value; 2081 + DBusMessageIter array_iter; 2082 + 2083 + dbus_message_iter_open_container (iter, 2084 + DBUS_TYPE_ARRAY, 2085 + DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING 2086 + DBUS_TYPE_STRING_AS_STRING 2087 + DBUS_TYPE_STRING_AS_STRING 2088 + DBUS_DICT_ENTRY_END_CHAR_AS_STRING, 2089 + &array_iter); 2090 + 2091 + 2092 + g_hash_table_iter_init (&hash_table_iter, hash_table); 2093 + while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) { 2094 + DBusMessageIter dict_iter; 2095 + 2096 + dbus_message_iter_open_container (&array_iter, 2097 + DBUS_TYPE_DICT_ENTRY, 2098 + NULL, 2099 + &dict_iter); 2100 + 2101 + dbus_message_iter_append_basic (&dict_iter, DBUS_TYPE_STRING, &key); 2102 + dbus_message_iter_append_basic (&dict_iter, DBUS_TYPE_STRING, &value); 2103 + dbus_message_iter_close_container (&array_iter, &dict_iter); 2104 + } 2105 + dbus_message_iter_close_container (iter, &array_iter); 2106 +} 2107 + 2108 +static void 2109 +emit_session_open_request (CkSeat *seat, 2110 + const char *ssid, 2111 + const char *session_type, 2112 + const char *display_template_name, 2113 + GHashTable *display_variables, 2114 + const char *display_type, 2115 + GHashTable *evaluated_parameters) 2116 +{ 2117 + DBusMessage *message; 2118 + DBusConnection *connection; 2119 + DBusMessageIter iter; 2120 + 2121 + message = dbus_message_new_signal (seat->priv->id, 2122 + "org.freedesktop.ConsoleKit.Seat", 2123 + "OpenSessionRequest"); 2124 + 2125 + dbus_message_set_destination (message, 2126 + dbus_g_proxy_get_bus_name (seat->priv->manager_proxy)); 2127 + 2128 + dbus_message_iter_init_append (message, &iter); 2129 + dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &ssid); 2130 + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session_type); 2131 + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_template_name); 2132 + append_hash_table_to_dbus_message_iter (&iter, display_variables); 2133 + dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_type); 2134 + append_hash_table_to_dbus_message_iter (&iter, evaluated_parameters); 2135 + 2136 + connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL); 2137 + dbus_connection_send (connection, message, NULL); 2138 + dbus_connection_unref (connection); 2139 + dbus_message_unref (message); 2140 +} 2141 + 2142 +gboolean 2143 +ck_seat_request_open_session (CkSeat *seat, 2144 + CkSession *session, 2145 + GError **error) 2146 +{ 2147 + char *ssid; 2148 + char *type; 2149 + CkDisplayTemplate *display_template; 2150 + GHashTable *display_variables; 2151 + GHashTable *display_parameters; 2152 + GHashTable *evaluated_parameters; 2153 + gboolean is_open; 2154 + gboolean ever_open; 2155 + gboolean under_request; 2156 + 2157 + ck_session_is_open (session, &is_open, NULL); 2158 + 2159 + if (is_open) { 2160 + return TRUE; 2161 + } 2162 + 2163 + ck_session_get_under_request (session, &under_request, NULL); 2164 + if (under_request) { 2165 + return TRUE; 2166 + } 2167 + 2168 + ck_session_set_under_request (session, TRUE, NULL); 2169 + 2170 + ck_session_get_ever_open (session, &ever_open, NULL); 2171 + 2172 + display_template = ck_session_get_display_template (session); 2173 + 2174 + if (display_template == NULL) { 2175 + return TRUE; 2176 + } 2177 + 2178 + ck_session_get_session_type (session, &type, NULL); 2179 + 2180 + if (type == NULL) { 2181 + g_object_unref (display_template); 2182 + return TRUE; 2183 + } 2184 + 2185 + /* substitute $display $vt etc */ 2186 + display_variables = ck_session_get_display_variables (session); 2187 + display_parameters = ck_display_template_get_parameters (display_template); 2188 + 2189 + if (display_parameters == NULL) { 2190 + g_free (type); 2191 + g_object_unref (display_template); 2192 + g_hash_table_unref (display_variables); 2193 + return TRUE; 2194 + } 2195 + 2196 + if (!ever_open) { 2197 + evaluated_parameters = get_evaluated_parameter_map (display_parameters, display_variables); 2198 + } else { 2199 + evaluated_parameters = get_evaluated_parameter_map (display_parameters, NULL); 2200 + } 2201 + 2202 + g_hash_table_unref (display_parameters); 2203 + 2204 + ck_session_get_id (session, &ssid, NULL); 2205 + 2206 + emit_session_open_request (seat, ssid, type, 2207 + ck_display_template_get_name (display_template), 2208 + display_variables, 2209 + ck_display_template_get_type_string (display_template), 2210 + evaluated_parameters); 2211 + 2212 + g_free (ssid); 2213 + g_free (type); 2214 + g_hash_table_unref (evaluated_parameters); 2215 + g_hash_table_unref (display_variables); 2216 + g_object_unref (display_template); 2217 + 2218 + return TRUE; 2219 +} 2220 + 2221 +static void 2222 +on_seat_manager_disappeared (CkSeat *seat) 2223 +{ 2224 + g_signal_handlers_disconnect_by_func (seat->priv->manager_proxy, 2225 + G_CALLBACK (on_seat_manager_disappeared), 2226 + seat); 2227 + g_object_unref (seat->priv->manager_proxy); 2228 + seat->priv->manager_proxy = NULL; 2229 + 2230 + /* FIXME: should probably emit a signal so a new display manager 2231 + * knows that the seat is now unmanaged 2232 + * 2233 + * (maybe only if its kind is static?) 2234 + */ 2235 +} 2236 + 2237 +gboolean 2238 +ck_seat_manage (CkSeat *seat, 2239 + DBusGMethodInvocation *context) 2240 +{ 2241 + char *sender_name; 2242 + 2243 + sender_name = dbus_g_method_get_sender (context); 2244 + 2245 + if (seat->priv->manager_proxy != NULL) { 2246 + GError *error; 2247 + const char *existing_manager_name; 2248 + 2249 + existing_manager_name = dbus_g_proxy_get_bus_name (seat->priv->manager_proxy); 2250 + 2251 + if (existing_manager_name == NULL) { 2252 + g_warning ("Seat manager lacks bus unique name"); 2253 + existing_manager_name = "<unknown>"; 2254 + } 2255 + 2256 + error = g_error_new (CK_SEAT_ERROR, 2257 + CK_SEAT_ERROR_GENERAL, 2258 + _("Seat already managed (by '%s')"), 2259 + existing_manager_name); 2260 + 2261 + dbus_g_method_return_error (context, error); 2262 + g_error_free (error); 2263 + return FALSE; 2264 + } 2265 + 2266 + /* FIXME: We pass in a bogus object path (the path we use on this side of 2267 + * the pipe) and interface here. 2268 + * 2269 + * We only use the proxy to watch for when the other side disappears, not 2270 + * for communicating with it. All communication is one-way using signals. 2271 + */ 2272 + seat->priv->manager_proxy = dbus_g_proxy_new_for_name (seat->priv->connection, 2273 + 2274 + sender_name, 2275 + seat->priv->id, 2276 + "org.freedesktop.ConsoleKit.SeatManager"); 2277 + g_free (sender_name); 2278 + 2279 + g_signal_connect_swapped (seat->priv->manager_proxy, 2280 + "destroy", 2281 + G_CALLBACK (on_seat_manager_disappeared), 2282 + seat); 2283 + 2284 + g_hash_table_foreach (seat->priv->sessions, request_session, seat); 2285 + 2286 + dbus_g_method_return (context); 2287 + return TRUE; 2288 +} 2289 + 2290 +gboolean 2291 +ck_seat_unmanage (CkSeat *seat, 2292 + DBusGMethodInvocation *context) 2293 +{ 2294 + GError *error; 2295 + const char *existing_manager_name; 2296 + char *sender_name; 2297 + 2298 + if (seat->priv->manager_proxy == NULL) { 2299 + GError *error; 2300 + 2301 + error = g_error_new (CK_SEAT_ERROR, 2302 + CK_SEAT_ERROR_GENERAL, 2303 + _("Seat not managed")); 2304 + 2305 + dbus_g_method_return_error (context, error); 2306 + g_error_free (error); 2307 + return FALSE; 2308 + } 2309 + 2310 + sender_name = dbus_g_method_get_sender (context); 2311 + existing_manager_name = dbus_g_proxy_get_bus_name (seat->priv->manager_proxy); 2312 + 2313 + if (strcmp (sender_name, existing_manager_name) != 0) { 2314 + 2315 + error = g_error_new (CK_SEAT_ERROR, 2316 + CK_SEAT_ERROR_GENERAL, 2317 + _("Seat managed by '%s' not '%s'"), 2318 + existing_manager_name, 2319 + sender_name); 2320 + 2321 + dbus_g_method_return_error (context, error); 2322 + g_error_free (error); 2323 + 2324 + return FALSE; 2325 + } 2326 + 2327 + on_seat_manager_disappeared (seat); 2328 + 2329 + dbus_g_method_return (context); 2330 + return TRUE; 2331 +} 2332 + 2333 +void 2334 +ck_seat_request_removal (CkSeat *seat) 2335 +{ 2336 + DBusMessage *message; 2337 + DBusConnection *connection; 2338 + 2339 + g_return_if_fail (CK_IS_SEAT (seat)); 2340 + g_return_if_fail (ck_seat_is_managed (seat)); 2341 + 2342 + message = dbus_message_new_signal (seat->priv->id, 2343 + "org.freedesktop.ConsoleKit.Seat", 2344 + "RemoveRequest"); 2345 + 2346 + dbus_message_set_destination (message, 2347 + dbus_g_proxy_get_bus_name (seat->priv->manager_proxy)); 2348 + 2349 + connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL); 2350 + dbus_connection_send (connection, message, NULL); 2351 + dbus_connection_unref (connection); 2352 + dbus_message_unref (message); 2353 +} 2354 + 2355 +static gboolean 2356 match_session_display_device (const char *key, 2357 CkSession *session, 2358 const char *display_device) 2359 @@ -526,6 +915,40 @@ change_active_session (CkSeat *seat, 2360 } 2361 2362 static void 2363 +find_possible_session_to_activate (CkSeat *seat) 2364 +{ 2365 + GHashTableIter iter; 2366 + gpointer key, value; 2367 + gboolean is_open; 2368 + char *session_type = NULL; 2369 + CkSession *login_session = NULL; 2370 + 2371 + g_hash_table_iter_init (&iter, seat->priv->sessions); 2372 + while (g_hash_table_iter_next (&iter, &key, &value)) { 2373 + 2374 + ck_session_is_open (value, &is_open, NULL); 2375 + 2376 + if (is_open) { 2377 + change_active_session (seat, value); 2378 + break; 2379 + } 2380 + 2381 + ck_session_get_session_type (value, &session_type, NULL); 2382 + if (IS_STR_SET (session_type) && 2383 + g_str_equal (session_type, "LoginWindow")) { 2384 + login_session = value; 2385 + g_free (session_type); 2386 + } 2387 + } 2388 + 2389 + if (login_session != NULL) { 2390 + ck_session_set_ever_open (login_session, FALSE, NULL); 2391 + ck_seat_request_open_session (seat, login_session, NULL); 2392 + } 2393 + 2394 +} 2395 + 2396 +static void 2397 update_active_vt (CkSeat *seat, 2398 guint num) 2399 { 2400 @@ -537,7 +960,12 @@ update_active_vt (CkSeat *seat, 2401 g_debug ("Active device: %s", device); 2402 2403 session = find_session_for_display_device (seat, device); 2404 - change_active_session (seat, session); 2405 + 2406 + if (session == NULL) { 2407 + find_possible_session_to_activate (seat); 2408 + } else { 2409 + change_active_session (seat, session); 2410 + } 2411 2412 g_free (device); 2413 } 2414 @@ -628,18 +1056,77 @@ ck_seat_remove_session (CkSeat *seat, 2415 return ret; 2416 } 2417 2418 +static void 2419 +emit_session_close_request (CkSeat *seat, 2420 + const char *ssid) 2421 +{ 2422 + DBusMessage *message; 2423 + DBusConnection *connection; 2424 + DBusMessageIter iter; 2425 + 2426 + message = dbus_message_new_signal (seat->priv->id, 2427 + "org.freedesktop.ConsoleKit.Seat", 2428 + "CloseSessionRequest"); 2429 + 2430 + dbus_message_set_destination (message, 2431 + dbus_g_proxy_get_bus_name (seat->priv->manager_proxy)); 2432 + 2433 + dbus_message_iter_init_append (message, &iter); 2434 + dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &ssid); 2435 + 2436 + connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL); 2437 + dbus_connection_send (connection, message, NULL); 2438 + dbus_connection_unref (connection); 2439 + dbus_message_unref (message); 2440 +} 2441 + 2442 +gboolean 2443 +ck_seat_request_close_session (CkSeat *seat, 2444 + CkSession *session, 2445 + GError **error) 2446 +{ 2447 + char *ssid; 2448 + 2449 + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); 2450 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 2451 + g_return_val_if_fail (ck_seat_is_managed (seat), FALSE); 2452 + 2453 + ck_session_get_id (session, &ssid, NULL); 2454 + 2455 + emit_session_close_request (seat, ssid); 2456 + 2457 + g_free (ssid); 2458 + 2459 + return FALSE; 2460 +} 2461 + 2462 gboolean 2463 ck_seat_add_session (CkSeat *seat, 2464 CkSession *session, 2465 GError **error) 2466 { 2467 char *ssid; 2468 + GHashTableIter iter; 2469 + gpointer key, value; 2470 + gboolean found; 2471 2472 g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); 2473 2474 ck_session_get_id (session, &ssid, NULL); 2475 2476 - g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session)); 2477 + found = FALSE; 2478 + g_hash_table_iter_init (&iter, seat->priv->sessions); 2479 + while (g_hash_table_iter_next (&iter, &key, &value)) { 2480 + if (g_str_equal ((gchar *)key, ssid)) { 2481 + found = TRUE; 2482 + break; 2483 + } 2484 + } 2485 + 2486 + if (! found) 2487 + g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session)); 2488 + else 2489 + g_object_ref (session); 2490 2491 ck_session_set_seat_id (session, seat->priv->id, NULL); 2492 2493 @@ -656,6 +1143,10 @@ ck_seat_add_session (CkSeat *seat, 2494 2495 maybe_update_active_session (seat); 2496 2497 + if (ck_seat_is_managed (seat)) { 2498 + ck_seat_request_open_session (seat, session, NULL); 2499 + } 2500 + 2501 g_free (ssid); 2502 2503 return TRUE; 2504 @@ -742,6 +1233,20 @@ ck_seat_get_kind (CkSeat *seat, 2505 } 2506 2507 gboolean 2508 +ck_seat_get_type_string (CkSeat *seat, 2509 + char **type, 2510 + GError **error) 2511 +{ 2512 + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); 2513 + 2514 + if (type != NULL) { 2515 + *type = g_strdup (seat->priv->type); 2516 + } 2517 + 2518 + return TRUE; 2519 +} 2520 + 2521 +gboolean 2522 ck_seat_get_id (CkSeat *seat, 2523 char **id, 2524 GError **error) 2525 @@ -858,6 +1363,14 @@ _ck_seat_set_kind (CkSeat *seat, 2526 } 2527 2528 static void 2529 +_ck_seat_set_type_string (CkSeat *seat, 2530 + const char *type) 2531 +{ 2532 + g_free (seat->priv->type); 2533 + seat->priv->type = g_strdup (type); 2534 +} 2535 + 2536 +static void 2537 ck_seat_set_property (GObject *object, 2538 guint prop_id, 2539 const GValue *value, 2540 @@ -874,6 +1387,9 @@ ck_seat_set_property (GObject *object, 2541 case PROP_KIND: 2542 _ck_seat_set_kind (self, g_value_get_enum (value)); 2543 break; 2544 + case PROP_TYPE: 2545 + _ck_seat_set_type_string (self, g_value_get_string (value)); 2546 + break; 2547 default: 2548 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 2549 break; 2550 @@ -895,7 +1411,10 @@ ck_seat_get_property (GObject *object, 2551 g_value_set_string (value, self->priv->id); 2552 break; 2553 case PROP_KIND: 2554 - g_value_set_string (value, self->priv->id); 2555 + g_value_set_enum (value, self->priv->kind); 2556 + break; 2557 + case PROP_TYPE: 2558 + g_value_set_string (value, self->priv->type); 2559 break; 2560 default: 2561 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 2562 @@ -1008,6 +1527,15 @@ ck_seat_class_init (CkSeatClass *klass) 2563 G_TYPE_NONE, 2564 1, CK_TYPE_DEVICE); 2565 2566 + signals [REMOVE_REQUEST] = g_signal_new ("remove-request", 2567 + G_TYPE_FROM_CLASS (object_class), 2568 + G_SIGNAL_RUN_LAST, 2569 + G_STRUCT_OFFSET (CkSeatClass, remove_request), 2570 + NULL, 2571 + NULL, 2572 + g_cclosure_marshal_VOID__VOID, 2573 + G_TYPE_NONE, 0); 2574 + 2575 g_object_class_install_property (object_class, 2576 PROP_ID, 2577 g_param_spec_string ("id", 2578 @@ -1024,6 +1552,13 @@ ck_seat_class_init (CkSeatClass *klass) 2579 CK_SEAT_KIND_DYNAMIC, 2580 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); 2581 2582 + g_object_class_install_property (object_class, 2583 + PROP_TYPE, 2584 + g_param_spec_string ("type", 2585 + "type", 2586 + "type", 2587 + NULL, 2588 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); 2589 g_type_class_add_private (klass, sizeof (CkSeatPrivate)); 2590 2591 dbus_g_object_type_install_info (CK_TYPE_SEAT, &dbus_glib_ck_seat_object_info); 2592 @@ -1039,6 +1574,7 @@ ck_seat_init (CkSeat *seat) 2593 g_free, 2594 (GDestroyNotify) g_object_unref); 2595 seat->priv->devices = g_ptr_array_new (); 2596 + seat->priv->manager_proxy = NULL; 2597 } 2598 2599 static void 2600 @@ -1064,28 +1600,32 @@ ck_seat_finalize (GObject *object) 2601 g_ptr_array_free (seat->priv->devices, TRUE); 2602 g_hash_table_destroy (seat->priv->sessions); 2603 g_free (seat->priv->id); 2604 + g_free (seat->priv->type); 2605 2606 G_OBJECT_CLASS (ck_seat_parent_class)->finalize (object); 2607 } 2608 2609 CkSeat * 2610 ck_seat_new (const char *sid, 2611 - CkSeatKind kind) 2612 + CkSeatKind kind, 2613 + const char *type) 2614 { 2615 GObject *object; 2616 2617 object = g_object_new (CK_TYPE_SEAT, 2618 "id", sid, 2619 "kind", kind, 2620 + "type", type, 2621 NULL); 2622 2623 return CK_SEAT (object); 2624 } 2625 2626 CkSeat * 2627 -ck_seat_new_with_devices (const char *sid, 2628 - CkSeatKind kind, 2629 - GPtrArray *devices) 2630 +ck_seat_new_with_devices_and_sessions (const char *sid, 2631 + CkSeatKind kind, 2632 + GPtrArray *devices, 2633 + GPtrArray *sessions) 2634 { 2635 GObject *object; 2636 int i; 2637 @@ -1100,24 +1640,57 @@ ck_seat_new_with_devices (const char *sid, 2638 ck_seat_add_device (CK_SEAT (object), g_ptr_array_index (devices, i), NULL); 2639 } 2640 } 2641 + if (sessions != NULL) { 2642 + for (i = 0; i < sessions->len; i++) { 2643 + ck_seat_add_session (CK_SEAT (object), g_ptr_array_index (sessions, i), NULL); 2644 + } 2645 + } 2646 + 2647 2648 return CK_SEAT (object); 2649 } 2650 2651 +static char * 2652 +generate_static_session_id (const char *sid, 2653 + const char *session_name) 2654 +{ 2655 + const char *seat_name; 2656 + char *ssid; 2657 + 2658 + seat_name = strrchr (sid, '/'); 2659 + 2660 + if (seat_name == NULL) { 2661 + g_warning ("Seat id '%s' lacks a /", sid); 2662 + seat_name = sid; 2663 + } else { 2664 + seat_name++; 2665 + } 2666 + 2667 + ssid = g_strdup_printf ("%s/Session%s%s", 2668 + CK_DBUS_PATH, seat_name, 2669 + session_name); 2670 + 2671 + return ssid; 2672 +} 2673 + 2674 CkSeat * 2675 -ck_seat_new_from_file (const char *sid, 2676 +ck_seat_new_from_file (char **sid, 2677 const char *path) 2678 { 2679 - GKeyFile *key_file; 2680 - gboolean res; 2681 - GError *error; 2682 - char *group; 2683 - CkSeat *seat; 2684 - gboolean hidden; 2685 - GPtrArray *devices; 2686 - char **device_list; 2687 - gsize ndevices; 2688 - gsize i; 2689 + GKeyFile *key_file; 2690 + gboolean res; 2691 + GError *error; 2692 + char *group; 2693 + CkSeat *seat; 2694 + char *read_sid; 2695 + gboolean hidden; 2696 + GPtrArray *sessions; 2697 + char **session_list; 2698 + gsize nsessions; 2699 + GPtrArray *devices; 2700 + char **device_list; 2701 + gsize ndevices; 2702 + gsize i; 2703 2704 seat = NULL; 2705 2706 @@ -1145,6 +1718,49 @@ ck_seat_new_from_file (const char *sid, 2707 goto out; 2708 } 2709 2710 + read_sid = g_key_file_get_string (key_file, group, "ID", NULL); 2711 + if (IS_STR_SET (read_sid)) { 2712 + g_free (*sid); 2713 + *sid = g_strdup_printf ("%s/%s", CK_DBUS_PATH, read_sid); 2714 + } else { 2715 + g_free (read_sid); 2716 + } 2717 + 2718 + session_list = g_key_file_get_string_list (key_file, group, "Sessions", &nsessions, NULL); 2719 + 2720 + sessions = g_ptr_array_sized_new (nsessions); 2721 + 2722 + for (i = 0; i < nsessions; i++) { 2723 + char *path; 2724 + char *file; 2725 + char *ssid; 2726 + CkSession *session; 2727 + 2728 + file = g_strconcat (session_list[i], ".session", NULL); 2729 + path = g_build_filename (CK_SESSION_DIR, file, NULL); 2730 + g_free (file); 2731 + 2732 + /* FIXME: we should probably use the same naming pool as 2733 + * sessions generated from ck-manager. We mangle the name 2734 + * here so we don't clash with names from ck-manager 2735 + */ 2736 + ssid = generate_static_session_id (*sid, session_list[i]); 2737 + 2738 + session = ck_session_new_from_file (ssid, path); 2739 + 2740 + if (session == NULL) { 2741 + g_warning ("Unable to load session from file %s", path); 2742 + g_free (path); 2743 + continue; 2744 + } 2745 + g_free (path); 2746 + ck_session_set_seat_id (session, *sid, NULL); 2747 + 2748 + g_ptr_array_add (sessions, session); 2749 + } 2750 + 2751 + g_strfreev (session_list); 2752 + 2753 device_list = g_key_file_get_string_list (key_file, group, "Devices", &ndevices, NULL); 2754 2755 g_debug ("Creating seat %s with %zd devices", sid, ndevices); 2756 @@ -1176,11 +1792,12 @@ ck_seat_new_from_file (const char *sid, 2757 g_strfreev (split); 2758 } 2759 g_strfreev (device_list); 2760 - g_free (group); 2761 2762 - seat = ck_seat_new_with_devices (sid, CK_SEAT_KIND_STATIC, devices); 2763 + seat = ck_seat_new_with_devices_and_sessions (*sid, CK_SEAT_KIND_STATIC, devices, sessions); 2764 g_ptr_array_free (devices, TRUE); 2765 2766 + g_free (group); 2767 + 2768 out: 2769 2770 g_key_file_free (key_file); 2771 @@ -1370,3 +1987,24 @@ ck_seat_dump (CkSeat *seat, 2772 2773 g_free (group_name); 2774 } 2775 + 2776 +gboolean 2777 +ck_seat_is_managed (CkSeat *seat) 2778 +{ 2779 + return seat->priv->manager_proxy != NULL; 2780 +} 2781 + 2782 +CkSession * 2783 +ck_seat_get_session (CkSeat *seat, 2784 + const char *ssid) 2785 +{ 2786 + CkSession *session; 2787 + 2788 + session = g_hash_table_lookup (seat->priv->sessions, ssid); 2789 + 2790 + if (session == NULL) { 2791 + return NULL; 2792 + } 2793 + 2794 + return g_object_ref (session); 2795 +} 2796 diff --git a/src/ck-seat.h b/src/ck-seat.h 2797 index fb9a955..6276021 100644 2798 --- a/src/ck-seat.h 2799 +++ b/src/ck-seat.h 2800 @@ -47,6 +47,7 @@ typedef struct 2801 { 2802 GObjectClass parent_class; 2803 2804 + void (* remove_request) (CkSeat *seat); 2805 void (* active_session_changed) (CkSeat *seat, 2806 const char *ssid); 2807 void (* session_added) (CkSeat *seat, 2808 @@ -57,6 +58,11 @@ typedef struct 2809 GValueArray *device); 2810 void (* device_removed) (CkSeat *seat, 2811 GValueArray *device); 2812 + void (* session_to_add) (CkSeat *seat, 2813 + gboolean is_dynamic, 2814 + const char *command); 2815 + void (* session_to_remove) (CkSeat *seat, 2816 + int display_number); 2817 } CkSeatClass; 2818 2819 typedef enum 2820 @@ -84,12 +90,14 @@ typedef enum 2821 GQuark ck_seat_error_quark (void); 2822 GType ck_seat_get_type (void); 2823 CkSeat * ck_seat_new (const char *sid, 2824 - CkSeatKind kind); 2825 -CkSeat * ck_seat_new_from_file (const char *sid, 2826 - const char *path); 2827 -CkSeat * ck_seat_new_with_devices (const char *sid, 2828 CkSeatKind kind, 2829 - GPtrArray *devices); 2830 + const char *type); 2831 +CkSeat * ck_seat_new_from_file (char **sid, 2832 + const char *path); 2833 +CkSeat * ck_seat_new_with_devices_and_sessions (const char *sid, 2834 + CkSeatKind kind, 2835 + GPtrArray *devices, 2836 + GPtrArray *sessions); 2837 2838 gboolean ck_seat_register (CkSeat *seat); 2839 2840 @@ -104,18 +112,31 @@ void ck_seat_dump (CkSeat *seat, 2841 gboolean ck_seat_get_kind (CkSeat *seat, 2842 CkSeatKind *kind, 2843 GError **error); 2844 +gboolean ck_seat_get_type_string (CkSeat *seat, 2845 + char **type, 2846 + GError **error); 2847 gboolean ck_seat_add_session (CkSeat *seat, 2848 CkSession *session, 2849 GError **error); 2850 gboolean ck_seat_remove_session (CkSeat *seat, 2851 CkSession *session, 2852 GError **error); 2853 +gboolean ck_seat_request_open_session (CkSeat *seat, 2854 + CkSession *session, 2855 + GError **error); 2856 +gboolean ck_seat_request_close_session (CkSeat *seat, 2857 + CkSession *session, 2858 + GError **error); 2859 gboolean ck_seat_add_device (CkSeat *seat, 2860 GValueArray *device, 2861 GError **error); 2862 gboolean ck_seat_remove_device (CkSeat *seat, 2863 GValueArray *device, 2864 GError **error); 2865 +gboolean ck_seat_is_managed (CkSeat *seat); 2866 +CkSession *ck_seat_get_session (CkSeat *seat, 2867 + const char *ssid); 2868 +void ck_seat_request_removal (CkSeat *seat); 2869 2870 /* exported methods */ 2871 gboolean ck_seat_get_id (CkSeat *seat, 2872 @@ -137,6 +158,10 @@ gboolean ck_seat_can_activate_sessions (CkSeat *seat, 2873 gboolean ck_seat_activate_session (CkSeat *seat, 2874 const char *ssid, 2875 DBusGMethodInvocation *context); 2876 +gboolean ck_seat_manage (CkSeat *seat, 2877 + DBusGMethodInvocation *context); 2878 +gboolean ck_seat_unmanage (CkSeat *seat, 2879 + DBusGMethodInvocation *context); 2880 2881 G_END_DECLS 2882 2883 diff --git a/src/ck-session-leader.c b/src/ck-session-leader.c 2884 index 3702602..908d2bb 100644 2885 --- a/src/ck-session-leader.c 2886 +++ b/src/ck-session-leader.c 2887 @@ -238,6 +238,7 @@ static struct { 2888 { "x11-display", add_param_string }, 2889 { "remote-host-name", add_param_string }, 2890 { "session-type", add_param_string }, 2891 + { "display-type", add_param_string }, 2892 { "is-local", add_param_boolean }, 2893 { "unix-user", add_param_int }, 2894 }; 2895 diff --git a/src/ck-session.c b/src/ck-session.c 2896 index d8db9dd..aa53bf0 100644 2897 --- a/src/ck-session.c 2898 +++ b/src/ck-session.c 2899 @@ -41,6 +41,7 @@ 2900 #include "ck-session-glue.h" 2901 #include "ck-marshal.h" 2902 #include "ck-run-programs.h" 2903 +#include "ck-display-template.h" 2904 2905 #define CK_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SESSION, CkSessionPrivate)) 2906 2907 @@ -58,6 +59,7 @@ struct CkSessionPrivate 2908 char *seat_id; 2909 2910 char *session_type; 2911 + char *display_type; 2912 char *login_session_id; 2913 char *display_device; 2914 char *x11_display_device; 2915 @@ -65,8 +67,15 @@ struct CkSessionPrivate 2916 char *remote_host_name; 2917 guint uid; 2918 2919 + CkDisplayTemplate *display_template; 2920 + GHashTable *display_variables; 2921 + 2922 gboolean active; 2923 gboolean is_local; 2924 + gboolean is_open; 2925 + gboolean ever_open; 2926 + gboolean under_request; 2927 + GMutex *mutex_under_request; 2928 2929 GTimeVal creation_time; 2930 2931 @@ -75,6 +84,8 @@ struct CkSessionPrivate 2932 gboolean idle_hint; 2933 GTimeVal idle_since_hint; 2934 2935 + gboolean remove_on_close; 2936 + 2937 DBusGConnection *connection; 2938 DBusGProxy *bus_proxy; 2939 }; 2940 @@ -92,17 +103,24 @@ enum { 2941 PROP_0, 2942 PROP_ID, 2943 PROP_COOKIE, 2944 + PROP_SEAT_ID, 2945 PROP_USER, 2946 PROP_UNIX_USER, 2947 PROP_X11_DISPLAY, 2948 PROP_X11_DISPLAY_DEVICE, 2949 PROP_DISPLAY_DEVICE, 2950 PROP_SESSION_TYPE, 2951 + PROP_DISPLAY_TYPE, 2952 + PROP_DISPLAY_TEMPLATE, 2953 + PROP_DISPLAY_VARIABLES, 2954 PROP_REMOTE_HOST_NAME, 2955 PROP_LOGIN_SESSION_ID, 2956 PROP_IS_LOCAL, 2957 + PROP_IS_OPEN, 2958 + PROP_EVER_OPEN, 2959 PROP_ACTIVE, 2960 PROP_IDLE_HINT, 2961 + PROP_REMOVE_ON_CLOSE, 2962 }; 2963 2964 static guint signals [LAST_SIGNAL] = { 0, }; 2965 @@ -128,6 +146,7 @@ static gboolean 2966 register_session (CkSession *session) 2967 { 2968 GError *error = NULL; 2969 + GObject *existing_session; 2970 2971 error = NULL; 2972 session->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); 2973 @@ -144,6 +163,15 @@ register_session (CkSession *session) 2974 DBUS_PATH_DBUS, 2975 DBUS_INTERFACE_DBUS); 2976 2977 + existing_session = dbus_g_connection_lookup_g_object (session->priv->connection, 2978 + session->priv->id); 2979 + 2980 + if (existing_session != NULL) { 2981 + g_warning ("Session '%s' was registered twice!", 2982 + session->priv->id); 2983 + return FALSE; 2984 + } 2985 + 2986 dbus_g_connection_register_g_object (session->priv->connection, session->priv->id, G_OBJECT (session)); 2987 2988 return TRUE; 2989 @@ -302,6 +330,35 @@ ck_session_set_idle_hint (CkSession *session, 2990 } 2991 2992 gboolean 2993 +session_set_remove_on_close (CkSession *session, 2994 + gboolean remove_on_close, 2995 + GError **error) 2996 +{ 2997 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 2998 + 2999 + if (session->priv->remove_on_close != remove_on_close) { 3000 + session->priv->remove_on_close = remove_on_close; 3001 + } 3002 + 3003 + return TRUE; 3004 +} 3005 + 3006 +/* 3007 + Example: 3008 + dbus-send --system --dest=org.freedesktop.ConsoleKit \ 3009 + --type=method_call --print-reply --reply-timeout=2000 \ 3010 + /org/freedesktop/ConsoleKit/Session1 \ 3011 + org.freedesktop.ConsoleKit.Session.SetRemoveOnClose boolean:TRUE 3012 +*/ 3013 +gboolean 3014 +ck_session_set_remove_on_close (CkSession *session, 3015 + gboolean remove_on_close, 3016 + DBusGMethodInvocation *context) 3017 +{ 3018 + return session_set_remove_on_close (session, remove_on_close, NULL); 3019 +} 3020 + 3021 +gboolean 3022 ck_session_get_idle_hint (CkSession *session, 3023 gboolean *idle_hint, 3024 GError **error) 3025 @@ -420,6 +477,68 @@ ck_session_set_is_local (CkSession *session, 3026 } 3027 3028 gboolean 3029 +ck_session_set_is_open (CkSession *session, 3030 + gboolean is_open, 3031 + GError **error) 3032 +{ 3033 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3034 + 3035 + if (session->priv->is_open != is_open) { 3036 + session->priv->is_open = is_open; 3037 + session->priv->ever_open = TRUE; 3038 + } 3039 + 3040 + return TRUE; 3041 +} 3042 + 3043 +gboolean 3044 +ck_session_set_ever_open (CkSession *session, 3045 + gboolean ever_open, 3046 + GError **error) 3047 +{ 3048 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3049 + 3050 + if (session->priv->ever_open != ever_open) { 3051 + session->priv->ever_open = ever_open; 3052 + } 3053 + 3054 + return TRUE; 3055 +} 3056 + 3057 +static gboolean 3058 +timeout_for_under_request (gpointer data) 3059 +{ 3060 + CkSession *session = CK_SESSION (data); 3061 + g_mutex_lock (session->priv->mutex_under_request); 3062 + session->priv->under_request = FALSE; 3063 + g_mutex_unlock (session->priv->mutex_under_request); 3064 + 3065 + g_debug ("timeout for under request of session %s", session->priv->id); 3066 + return FALSE; 3067 +} 3068 + 3069 +gboolean 3070 +ck_session_set_under_request (CkSession *session, 3071 + gboolean under_request, 3072 + GError **error) 3073 +{ 3074 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3075 + 3076 + g_mutex_lock (session->priv->mutex_under_request); 3077 + if (!under_request) { 3078 + session->priv->under_request = FALSE; 3079 + } else { 3080 + if (!session->priv->under_request) { 3081 + session->priv->under_request = TRUE; 3082 + g_timeout_add_seconds (1, timeout_for_under_request, session); 3083 + } 3084 + } 3085 + g_mutex_unlock (session->priv->mutex_under_request); 3086 + 3087 + return TRUE; 3088 +} 3089 + 3090 +gboolean 3091 ck_session_get_id (CkSession *session, 3092 char **id, 3093 GError **error) 3094 @@ -555,6 +674,20 @@ ck_session_get_creation_time (CkSession *session, 3095 } 3096 3097 gboolean 3098 +ck_session_get_remove_on_close (CkSession *session, 3099 + gboolean *remove_on_close, 3100 + GError **error) 3101 +{ 3102 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3103 + 3104 + if (remove_on_close != NULL) { 3105 + *remove_on_close = session->priv->remove_on_close; 3106 + } 3107 + 3108 + return TRUE; 3109 +} 3110 + 3111 +gboolean 3112 ck_session_get_session_type (CkSession *session, 3113 char **type, 3114 GError **error) 3115 @@ -569,6 +702,20 @@ ck_session_get_session_type (CkSession *session, 3116 } 3117 3118 gboolean 3119 +ck_session_get_display_type (CkSession *session, 3120 + char **type, 3121 + GError **error) 3122 +{ 3123 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3124 + 3125 + if (type != NULL) { 3126 + *type = g_strdup (session->priv->display_type); 3127 + } 3128 + 3129 + return TRUE; 3130 +} 3131 + 3132 +gboolean 3133 ck_session_is_active (CkSession *session, 3134 gboolean *active, 3135 GError **error) 3136 @@ -597,6 +744,50 @@ ck_session_is_local (CkSession *session, 3137 } 3138 3139 gboolean 3140 +ck_session_is_open (CkSession *session, 3141 + gboolean *open, 3142 + GError **error) 3143 +{ 3144 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3145 + 3146 + if (open != NULL) { 3147 + *open = session->priv->is_open; 3148 + } 3149 + 3150 + return TRUE; 3151 +} 3152 + 3153 +gboolean 3154 +ck_session_get_ever_open (CkSession *session, 3155 + gboolean *open, 3156 + GError **error) 3157 +{ 3158 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3159 + 3160 + if (open != NULL) { 3161 + *open = session->priv->ever_open; 3162 + } 3163 + 3164 + return TRUE; 3165 +} 3166 + 3167 +gboolean 3168 +ck_session_get_under_request (CkSession *session, 3169 + gboolean *under_request, 3170 + GError **error) 3171 +{ 3172 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3173 + 3174 + if (under_request != NULL) { 3175 + g_mutex_lock (session->priv->mutex_under_request); 3176 + *under_request = session->priv->under_request; 3177 + g_mutex_unlock (session->priv->mutex_under_request); 3178 + } 3179 + 3180 + return TRUE; 3181 +} 3182 + 3183 +gboolean 3184 ck_session_set_id (CkSession *session, 3185 const char *id, 3186 GError **error) 3187 @@ -609,6 +800,21 @@ ck_session_set_id (CkSession *session, 3188 return TRUE; 3189 } 3190 3191 +static void 3192 +ck_session_set_display_variables (CkSession *session, 3193 + GHashTable *display_variables) 3194 +{ 3195 + if (session->priv->display_variables != NULL) { 3196 + g_hash_table_unref (session->priv->display_variables); 3197 + } 3198 + 3199 + if (display_variables != NULL) { 3200 + session->priv->display_variables = g_hash_table_ref (display_variables); 3201 + } else { 3202 + session->priv->display_variables = NULL; 3203 + } 3204 +} 3205 + 3206 gboolean 3207 ck_session_set_cookie (CkSession *session, 3208 const char *cookie, 3209 @@ -725,6 +931,54 @@ ck_session_set_session_type (CkSession *session, 3210 return TRUE; 3211 } 3212 3213 +gboolean 3214 +ck_session_set_display_type (CkSession *session, 3215 + const char *type, 3216 + GError **error) 3217 +{ 3218 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3219 + 3220 + g_free (session->priv->display_type); 3221 + session->priv->display_type = g_strdup (type); 3222 + 3223 + return TRUE; 3224 +} 3225 + 3226 +static gboolean 3227 +ck_session_set_display_template (CkSession *session, 3228 + CkDisplayTemplate *display_template, 3229 + GError **error) 3230 +{ 3231 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3232 + 3233 + if (session->priv->display_template != NULL) { 3234 + g_object_unref (session->priv->display_template); 3235 + } 3236 + 3237 + if (display_template != NULL) { 3238 + session->priv->display_template = g_object_ref (display_template); 3239 + ck_session_set_display_type (session, ck_display_template_get_name (display_template), error); 3240 + } else { 3241 + session->priv->display_template = NULL; 3242 + } 3243 + 3244 + return TRUE; 3245 +} 3246 + 3247 +GHashTable * 3248 +ck_session_get_display_variables (CkSession *session) 3249 +{ 3250 + return g_hash_table_ref (session->priv->display_variables); 3251 +} 3252 + 3253 +CkDisplayTemplate * 3254 +ck_session_get_display_template (CkSession *session) 3255 +{ 3256 + g_return_val_if_fail (CK_IS_SESSION (session), FALSE); 3257 + 3258 + return g_object_ref (session->priv->display_template); 3259 +} 3260 + 3261 static void 3262 ck_session_set_property (GObject *object, 3263 guint prop_id, 3264 @@ -742,15 +996,33 @@ ck_session_set_property (GObject *object, 3265 case PROP_IS_LOCAL: 3266 ck_session_set_is_local (self, g_value_get_boolean (value), NULL); 3267 break; 3268 + case PROP_IS_OPEN: 3269 + ck_session_set_is_open (self, g_value_get_boolean (value), NULL); 3270 + break; 3271 + case PROP_EVER_OPEN: 3272 + ck_session_set_ever_open (self, g_value_get_boolean (value), NULL); 3273 + break; 3274 case PROP_ID: 3275 ck_session_set_id (self, g_value_get_string (value), NULL); 3276 break; 3277 case PROP_COOKIE: 3278 ck_session_set_cookie (self, g_value_get_string (value), NULL); 3279 break; 3280 + case PROP_SEAT_ID: 3281 + ck_session_set_seat_id (self, g_value_get_string (value), NULL); 3282 + break; 3283 case PROP_SESSION_TYPE: 3284 ck_session_set_session_type (self, g_value_get_string (value), NULL); 3285 break; 3286 + case PROP_DISPLAY_TYPE: 3287 + ck_session_set_display_type (self, g_value_get_string (value), NULL); 3288 + break; 3289 + case PROP_DISPLAY_TEMPLATE: 3290 + ck_session_set_display_template (self, g_value_get_object (value), NULL); 3291 + break; 3292 + case PROP_DISPLAY_VARIABLES: 3293 + ck_session_set_display_variables (self, g_value_get_boxed (value)); 3294 + break; 3295 case PROP_X11_DISPLAY: 3296 ck_session_set_x11_display (self, g_value_get_string (value), NULL); 3297 break; 3298 @@ -775,6 +1047,9 @@ ck_session_set_property (GObject *object, 3299 case PROP_IDLE_HINT: 3300 session_set_idle_hint_internal (self, g_value_get_boolean (value)); 3301 break; 3302 + case PROP_REMOVE_ON_CLOSE: 3303 + session_set_remove_on_close (self, g_value_get_boolean (value), NULL); 3304 + break; 3305 default: 3306 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 3307 break; 3308 @@ -798,15 +1073,33 @@ ck_session_get_property (GObject *object, 3309 case PROP_IS_LOCAL: 3310 g_value_set_boolean (value, self->priv->is_local); 3311 break; 3312 + case PROP_IS_OPEN: 3313 + g_value_set_boolean (value, self->priv->is_open); 3314 + break; 3315 + case PROP_EVER_OPEN: 3316 + g_value_set_boolean (value, self->priv->ever_open); 3317 + break; 3318 case PROP_ID: 3319 g_value_set_string (value, self->priv->id); 3320 break; 3321 case PROP_COOKIE: 3322 g_value_set_string (value, self->priv->cookie); 3323 break; 3324 + case PROP_SEAT_ID: 3325 + g_value_set_string (value, self->priv->seat_id); 3326 + break; 3327 case PROP_SESSION_TYPE: 3328 g_value_set_string (value, self->priv->session_type); 3329 break; 3330 + case PROP_DISPLAY_TYPE: 3331 + g_value_set_string (value, self->priv->display_type); 3332 + break; 3333 + case PROP_DISPLAY_TEMPLATE: 3334 + g_value_set_object (value, self->priv->display_template); 3335 + break; 3336 + case PROP_DISPLAY_VARIABLES: 3337 + g_value_set_boxed (value, self->priv->display_variables); 3338 + break; 3339 case PROP_X11_DISPLAY: 3340 g_value_set_string (value, self->priv->x11_display); 3341 break; 3342 @@ -831,6 +1124,9 @@ ck_session_get_property (GObject *object, 3343 case PROP_IDLE_HINT: 3344 g_value_set_boolean (value, self->priv->idle_hint); 3345 break; 3346 + case PROP_REMOVE_ON_CLOSE: 3347 + g_value_set_boolean (value, self->priv->remove_on_close); 3348 + break; 3349 default: 3350 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec); 3351 break; 3352 @@ -1000,6 +1296,13 @@ ck_session_class_init (CkSessionClass *klass) 3353 "cookie", 3354 NULL, 3355 G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); 3356 + g_object_class_install_property (object_class, 3357 + PROP_SEAT_ID, 3358 + g_param_spec_string ("seat-id", 3359 + "seat id", 3360 + "seat id", 3361 + NULL, 3362 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY)); 3363 3364 g_object_class_install_property (object_class, 3365 PROP_SESSION_TYPE, 3366 @@ -1009,6 +1312,27 @@ ck_session_class_init (CkSessionClass *klass) 3367 NULL, 3368 G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); 3369 g_object_class_install_property (object_class, 3370 + PROP_DISPLAY_TYPE, 3371 + g_param_spec_string ("display-type", 3372 + "session-type", 3373 + "session type", 3374 + NULL, 3375 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); 3376 + g_object_class_install_property (object_class, 3377 + PROP_DISPLAY_TEMPLATE, 3378 + g_param_spec_object ("display-template", 3379 + "Display Template", 3380 + "The display template", 3381 + CK_TYPE_DISPLAY_TEMPLATE, 3382 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); 3383 + g_object_class_install_property (object_class, 3384 + PROP_DISPLAY_VARIABLES, 3385 + g_param_spec_boxed ("display-variables", 3386 + "Display Variables", 3387 + "Display type specific variables", 3388 + G_TYPE_HASH_TABLE, 3389 + G_PARAM_READWRITE | G_PARAM_CONSTRUCT)); 3390 + g_object_class_install_property (object_class, 3391 PROP_LOGIN_SESSION_ID, 3392 g_param_spec_string ("login-session-id", 3393 "login-session-id", 3394 @@ -1070,6 +1394,13 @@ ck_session_class_init (CkSessionClass *klass) 3395 NULL, 3396 FALSE, 3397 G_PARAM_READWRITE)); 3398 + g_object_class_install_property (object_class, 3399 + PROP_REMOVE_ON_CLOSE, 3400 + g_param_spec_boolean ("remove-on-close", 3401 + NULL, 3402 + NULL, 3403 + FALSE, 3404 + G_PARAM_READWRITE)); 3405 3406 g_type_class_add_private (klass, sizeof (CkSessionPrivate)); 3407 3408 @@ -1081,8 +1412,16 @@ ck_session_init (CkSession *session) 3409 { 3410 session->priv = CK_SESSION_GET_PRIVATE (session); 3411 3412 + session->priv->display_variables = g_hash_table_new_full (g_str_hash, 3413 + g_str_equal, 3414 + (GDestroyNotify) g_free, 3415 + (GDestroyNotify) g_free); 3416 + 3417 /* FIXME: should we have a property for this? */ 3418 g_get_current_time (&session->priv->creation_time); 3419 + 3420 + if (!session->priv->mutex_under_request) 3421 + session->priv->mutex_under_request = g_mutex_new (); 3422 } 3423 3424 static void 3425 @@ -1105,6 +1444,7 @@ ck_session_finalize (GObject *object) 3426 g_free (session->priv->cookie); 3427 g_free (session->priv->seat_id); 3428 g_free (session->priv->session_type); 3429 + g_free (session->priv->display_type); 3430 g_free (session->priv->x11_display); 3431 g_free (session->priv->display_device); 3432 g_free (session->priv->x11_display_device); 3433 @@ -1114,16 +1454,135 @@ ck_session_finalize (GObject *object) 3434 } 3435 3436 CkSession * 3437 +ck_session_new_from_file (const char *ssid, 3438 + const char *path) 3439 +{ 3440 + GKeyFile *key_file; 3441 + gboolean res; 3442 + GError *error; 3443 + char *group; 3444 + char *name; 3445 + gboolean hidden; 3446 + char *type; 3447 + char *display_template_string; 3448 + CkSession *session; 3449 + GHashTable *display_variables; 3450 + char **type_keys; 3451 + 3452 + key_file = g_key_file_new (); 3453 + error = NULL; 3454 + res = g_key_file_load_from_file (key_file, 3455 + path, 3456 + G_KEY_FILE_NONE, 3457 + &error); 3458 + 3459 + if (! res) { 3460 + g_warning ("Unable to load sessions from file %s: %s", 3461 + path, error->message); 3462 + g_error_free (error); 3463 + return NULL; 3464 + } 3465 + 3466 + group = g_key_file_get_start_group (key_file); 3467 + if (group == NULL || strcmp (group, "Session Entry") != 0) { 3468 + g_warning ("Not a session file: %s", path); 3469 + g_key_file_free (key_file); 3470 + return NULL; 3471 + } 3472 + 3473 + hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL); 3474 + 3475 + if (hidden) { 3476 + g_debug ("Session is hidden"); 3477 + g_free (group); 3478 + g_key_file_free (key_file); 3479 + return NULL; 3480 + } 3481 + 3482 + name = g_key_file_get_string (key_file, group, "Name", NULL); 3483 + 3484 + if (name == NULL) { 3485 + g_warning ("Session file %s doesn't contain a name", path); 3486 + g_free (group); 3487 + g_key_file_free (key_file); 3488 + return NULL; 3489 + } 3490 + 3491 + type = g_key_file_get_string (key_file, group, "Type", NULL); 3492 + 3493 + if (type == NULL) { 3494 + g_warning ("Session file %s doesn't contain a type", path); 3495 + g_free (group); 3496 + g_key_file_free (key_file); 3497 + return NULL; 3498 + } 3499 + 3500 + display_template_string = g_key_file_get_string (key_file, group, "DisplayTemplate", NULL); 3501 + 3502 + if (display_template_string == NULL) { 3503 + g_warning ("Session file %s doesn't contain a display type", path); 3504 + g_free (group); 3505 + g_key_file_free (key_file); 3506 + return NULL; 3507 + } 3508 + 3509 + /* Find a group in the key file named after the display type and stuff 3510 + * all its entries into a hash table for later. 3511 + * 3512 + * Those keys are for things like the display number and the vt to 3513 + * run X with. 3514 + */ 3515 + display_variables = g_hash_table_new_full (g_str_hash, g_str_equal, 3516 + (GDestroyNotify) g_free, 3517 + (GDestroyNotify) g_free); 3518 + type_keys = g_key_file_get_keys (key_file, display_template_string, NULL, NULL); 3519 + 3520 + if (type_keys != NULL) { 3521 + int i; 3522 + for (i = 0; type_keys[i] != NULL; i++) { 3523 + char *string; 3524 + string = g_key_file_get_string (key_file, display_template_string, type_keys[i], NULL); 3525 + 3526 + g_hash_table_insert (display_variables, g_strdup (type_keys[i]), string); 3527 + } 3528 + g_strfreev (type_keys); 3529 + } 3530 + 3531 + session = ck_session_new (ssid, type, display_template_string, display_variables); 3532 + 3533 + g_free (display_template_string); 3534 + g_free (group); 3535 + g_free (type); 3536 + g_hash_table_unref (display_variables); 3537 + 3538 + return session; 3539 +} 3540 + 3541 +CkSession * 3542 ck_session_new (const char *ssid, 3543 - const char *cookie) 3544 + const char *type, 3545 + const char *display_template_string, 3546 + GHashTable *display_variables) 3547 { 3548 + CkDisplayTemplate *display_template; 3549 GObject *object; 3550 gboolean res; 3551 3552 + display_template = ck_display_template_get_from_name (display_template_string); 3553 + 3554 + if (display_template == NULL) { 3555 + g_warning ("Unable to load display type %s", display_template_string); 3556 + return NULL; 3557 + } 3558 + 3559 object = g_object_new (CK_TYPE_SESSION, 3560 "id", ssid, 3561 - "cookie", cookie, 3562 + "session-type", type, 3563 + "display-type", display_template_string, 3564 + "display-template", display_template, 3565 + "display-variables", display_variables, 3566 NULL); 3567 + 3568 res = register_session (CK_SESSION (object)); 3569 if (! res) { 3570 g_object_unref (object); 3571 @@ -1138,9 +1597,80 @@ ck_session_new (const char *ssid, 3572 G_TYPE_VALUE, \ 3573 G_TYPE_INVALID)) 3574 3575 +void 3576 +ck_session_set_parameters (CkSession *session, 3577 + const GPtrArray *parameters) 3578 +{ 3579 + int i; 3580 + GObjectClass *class; 3581 + GType object_type; 3582 + 3583 + object_type = CK_TYPE_SESSION; 3584 + class = g_type_class_ref (object_type); 3585 + for (i = 0; i < parameters->len; i++) { 3586 + gboolean res; 3587 + GValue val_struct = { 0, }; 3588 + GValue value = { 0, }; 3589 + char *prop_name; 3590 + GValue *prop_val; 3591 + GParamSpec *pspec; 3592 + 3593 + g_value_init (&val_struct, CK_TYPE_PARAMETER_STRUCT); 3594 + g_value_set_static_boxed (&val_struct, g_ptr_array_index (parameters, i)); 3595 + 3596 + res = dbus_g_type_struct_get (&val_struct, 3597 + 0, &prop_name, 3598 + 1, &prop_val, 3599 + G_MAXUINT); 3600 + if (! res) { 3601 + g_debug ("Unable to extract parameter input"); 3602 + goto cont; 3603 + } 3604 + 3605 + if (prop_name == NULL) { 3606 + g_debug ("Skipping NULL parameter"); 3607 + goto cont; 3608 + } 3609 + 3610 + if (strcmp (prop_name, "id") == 0 3611 + || strcmp (prop_name, "cookie") == 0) { 3612 + g_debug ("Skipping restricted parameter: %s", prop_name); 3613 + goto cont; 3614 + } 3615 + 3616 + pspec = g_object_class_find_property (class, prop_name); 3617 + if (! pspec) { 3618 + g_debug ("Skipping unknown parameter: %s", prop_name); 3619 + goto cont; 3620 + } 3621 + 3622 + if (!(pspec->flags & G_PARAM_WRITABLE)) { 3623 + g_debug ("property '%s' is not writable", pspec->name); 3624 + goto cont; 3625 + } 3626 + 3627 + g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec)); 3628 + res = g_value_transform (prop_val, &value); 3629 + if (! res) { 3630 + g_debug ("unable to transform property value for '%s'", pspec->name); 3631 + goto cont; 3632 + } 3633 + 3634 + g_object_set_property (G_OBJECT (session), prop_name, &value); 3635 + g_value_unset (&value); 3636 + cont: 3637 + g_free (prop_name); 3638 + if (prop_val != NULL) { 3639 + g_value_unset (prop_val); 3640 + g_free (prop_val); 3641 + } 3642 + } 3643 + 3644 + g_type_class_unref (class); 3645 +} 3646 + 3647 CkSession * 3648 ck_session_new_with_parameters (const char *ssid, 3649 - const char *cookie, 3650 const GPtrArray *parameters) 3651 { 3652 GObject *object; 3653 @@ -1169,12 +1699,6 @@ ck_session_new_with_parameters (const char *ssid, 3654 g_value_set_string (¶ms[n_params].value, ssid); 3655 n_params++; 3656 3657 - params[n_params].name = g_strdup ("cookie"); 3658 - params[n_params].value.g_type = 0; 3659 - g_value_init (¶ms[n_params].value, G_TYPE_STRING); 3660 - g_value_set_string (¶ms[n_params].value, cookie); 3661 - n_params++; 3662 - 3663 if (parameters != NULL) { 3664 for (i = 0; i < parameters->len; i++) { 3665 gboolean res; 3666 @@ -1259,7 +1783,7 @@ ck_session_run_programs (CkSession *session, 3667 const char *action) 3668 { 3669 int n; 3670 - char *extra_env[11]; /* be sure to adjust this as needed */ 3671 + char *extra_env[12]; /* be sure to adjust this as needed */ 3672 3673 n = 0; 3674 3675 @@ -1267,6 +1791,9 @@ ck_session_run_programs (CkSession *session, 3676 if (session->priv->session_type != NULL) { 3677 extra_env[n++] = g_strdup_printf ("CK_SESSION_TYPE=%s", session->priv->session_type); 3678 } 3679 + if (session->priv->display_type != NULL) { 3680 + extra_env[n++] = g_strdup_printf ("CK_SESSION_DISPLAY_TYPE=%s", session->priv->display_type); 3681 + } 3682 extra_env[n++] = g_strdup_printf ("CK_SESSION_SEAT_ID=%s", session->priv->seat_id); 3683 extra_env[n++] = g_strdup_printf ("CK_SESSION_USER_UID=%d", session->priv->uid); 3684 if (session->priv->display_device != NULL && strlen (session->priv->display_device) > 0) { 3685 @@ -1301,6 +1828,10 @@ ck_session_dump (CkSession *session, 3686 char *s; 3687 char *group_name; 3688 3689 + if (!session->priv->is_open) { 3690 + return; 3691 + } 3692 + 3693 group_name = g_strdup_printf ("Session %s", session->priv->id); 3694 g_key_file_set_integer (key_file, group_name, "uid", session->priv->uid); 3695 g_key_file_set_string (key_file, 3696 @@ -1313,6 +1844,12 @@ ck_session_dump (CkSession *session, 3697 "type", 3698 NONULL_STRING (session->priv->session_type)); 3699 } 3700 + if (session->priv->display_type != NULL) { 3701 + g_key_file_set_string (key_file, 3702 + group_name, 3703 + "display_type", 3704 + NONULL_STRING (session->priv->display_type)); 3705 + } 3706 if (session->priv->login_session_id != NULL && strlen (session->priv->login_session_id) > 0) { 3707 g_key_file_set_string (key_file, 3708 group_name, 3709 diff --git a/src/ck-session.h b/src/ck-session.h 3710 index b6b565b..a24d0a8 100644 3711 --- a/src/ck-session.h 3712 +++ b/src/ck-session.h 3713 @@ -25,6 +25,8 @@ 3714 #include <glib-object.h> 3715 #include <dbus/dbus-glib.h> 3716 3717 +#include "ck-display-template.h" 3718 + 3719 G_BEGIN_DECLS 3720 3721 #define CK_TYPE_SESSION (ck_session_get_type ()) 3722 @@ -68,10 +70,15 @@ typedef enum 3723 3724 GQuark ck_session_error_quark (void); 3725 GType ck_session_get_type (void); 3726 +CkSession * ck_session_new_from_file (const char *ssid, 3727 + const char *path); 3728 CkSession * ck_session_new (const char *ssid, 3729 - const char *cookie); 3730 + const char *type, 3731 + const char *display_type_string, 3732 + GHashTable *display_variables); 3733 CkSession * ck_session_new_with_parameters (const char *ssid, 3734 - const char *cookie, 3735 + const GPtrArray *parameters); 3736 +void ck_session_set_parameters (CkSession *session, 3737 const GPtrArray *parameters); 3738 3739 void ck_session_dump (CkSession *session, 3740 @@ -86,6 +93,15 @@ gboolean ck_session_set_active (CkSession *se 3741 gboolean ck_session_set_is_local (CkSession *session, 3742 gboolean is_local, 3743 GError **error); 3744 +gboolean ck_session_set_is_open (CkSession *session, 3745 + gboolean is_open, 3746 + GError **error); 3747 +gboolean ck_session_set_ever_open (CkSession *session, 3748 + gboolean ever_open, 3749 + GError **error); 3750 +gboolean ck_session_set_under_request (CkSession *session, 3751 + gboolean under_request, 3752 + GError **error); 3753 gboolean ck_session_set_id (CkSession *session, 3754 const char *ssid, 3755 GError **error); 3756 @@ -116,6 +132,11 @@ gboolean ck_session_set_remote_host_name (CkSession *se 3757 gboolean ck_session_set_session_type (CkSession *session, 3758 const char *type, 3759 GError **error); 3760 +gboolean ck_session_set_display_type (CkSession *session, 3761 + const char *type, 3762 + GError **error); 3763 +GHashTable *ck_session_get_display_variables (CkSession *session); 3764 +CkDisplayTemplate *ck_session_get_display_template (CkSession *session); 3765 3766 /* Exported methods */ 3767 3768 @@ -132,6 +153,15 @@ gboolean ck_session_is_active (CkSession *se 3769 gboolean ck_session_is_local (CkSession *session, 3770 gboolean *local, 3771 GError **error); 3772 +gboolean ck_session_is_open (CkSession *session, 3773 + gboolean *open, 3774 + GError **error); 3775 +gboolean ck_session_get_ever_open (CkSession *session, 3776 + gboolean *open, 3777 + GError **error); 3778 +gboolean ck_session_get_under_request (CkSession *session, 3779 + gboolean *under_request, 3780 + GError **error); 3781 gboolean ck_session_get_unix_user (CkSession *session, 3782 guint *uid, 3783 GError **error); 3784 @@ -150,12 +180,18 @@ gboolean ck_session_get_login_session_id (CkSession *se 3785 gboolean ck_session_get_session_type (CkSession *session, 3786 char **type, 3787 GError **error); 3788 +gboolean ck_session_get_display_type (CkSession *session, 3789 + char **type, 3790 + GError **error); 3791 gboolean ck_session_get_remote_host_name (CkSession *session, 3792 char **host_name, 3793 GError **error); 3794 gboolean ck_session_get_creation_time (CkSession *session, 3795 char **iso8601_datetime, 3796 GError **error); 3797 +gboolean ck_session_get_remove_on_close (CkSession *session, 3798 + gboolean *remove_on_close, 3799 + GError **error); 3800 /*deprecated*/ 3801 gboolean ck_session_get_user (CkSession *session, 3802 guint *uid, 3803 @@ -171,6 +207,12 @@ gboolean ck_session_get_idle_since_hint (CkSession *se 3804 gboolean ck_session_set_idle_hint (CkSession *session, 3805 gboolean idle_hint, 3806 DBusGMethodInvocation *context); 3807 +gboolean session_set_remove_on_close (CkSession *session, 3808 + gboolean remove_on_close, 3809 + GError **error); 3810 +gboolean ck_session_set_remove_on_close (CkSession *session, 3811 + gboolean remove_on_close, 3812 + DBusGMethodInvocation *context); 3813 3814 /* Privileged actions */ 3815 gboolean ck_session_activate (CkSession *session, 3816 diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml 3817 index f903b55..34a6d04 100644 3818 --- a/src/org.freedesktop.ConsoleKit.Manager.xml 3819 +++ b/src/org.freedesktop.ConsoleKit.Manager.xml 3820 @@ -160,6 +160,23 @@ 3821 </doc:doc> 3822 </method> 3823 3824 + <method name="GetUnmanagedSeats"> 3825 + <arg name="seats" direction="out" type="ao"> 3826 + <doc:doc> 3827 + <doc:summary>an array of unmanaged Seat IDs</doc:summary> 3828 + </doc:doc> 3829 + </arg> 3830 + <doc:doc> 3831 + <doc:description> 3832 + <doc:para>This gets a list of the unmanaged <doc:ref type="interface" to="Seat">Seats</doc:ref> 3833 + that are statically configured under /etc/ConsoleKit/seats.d</doc:para> 3834 + <doc:para>Each Seat ID is an D-Bus object path for the object that implements the 3835 + <doc:ref type="interface" to="Seat">Seat</doc:ref> interface.</doc:para> 3836 + </doc:description> 3837 + <doc:seealso><doc:ref type="interface" to="Seat">org.freedesktop.ConsoleKit.Seat</doc:ref></doc:seealso> 3838 + </doc:doc> 3839 + </method> 3840 + 3841 <method name="GetSessions"> 3842 <arg name="sessions" direction="out" type="ao"> 3843 <doc:doc> 3844 @@ -310,12 +327,115 @@ 3845 </doc:doc> 3846 </method> 3847 3848 + <method name="AddSeat"> 3849 + <arg name="type" type="s" direction="in"> 3850 + <doc:doc> 3851 + <doc:summary>The type of seat to add</doc:summary> 3852 + </doc:doc> 3853 + </arg> 3854 + <arg name="sid" type="o" direction="out"> 3855 + <doc:doc> 3856 + <doc:summary>The Seat ID of the added seat</doc:summary> 3857 + </doc:doc> 3858 + </arg> 3859 + <doc:doc> 3860 + <doc:description> 3861 + <doc:para>This method is to create a new seat 3862 + </doc:para> 3863 + </doc:description> 3864 + </doc:doc> 3865 + </method> 3866 + <method name="AddSeatById"> 3867 + <arg name="type" type="s" direction="in"> 3868 + <doc:doc> 3869 + <doc:summary>The type of seat to add</doc:summary> 3870 + </doc:doc> 3871 + </arg> 3872 + <arg name="sid" type="o" direction="in"> 3873 + <doc:doc> 3874 + <doc:summary>The Seat ID of to be added seat</doc:summary> 3875 + </doc:doc> 3876 + </arg> 3877 + <doc:doc> 3878 + <doc:description> 3879 + <doc:para>This method is to create a new seat by specify given sid 3880 + </doc:para> 3881 + </doc:description> 3882 + </doc:doc> 3883 + </method> 3884 + <method name="RemoveSeat"> 3885 + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> 3886 + <arg name="sid" type="o" direction="in"> 3887 + <doc:doc> 3888 + <doc:summary>The Seat ID of the seat to remove</doc:summary> 3889 + </doc:doc> 3890 + </arg> 3891 + <doc:doc> 3892 + <doc:description> 3893 + <doc:para>This method is to remove a seat 3894 + </doc:para> 3895 + </doc:description> 3896 + </doc:doc> 3897 + </method> 3898 + <method name="AddSession"> 3899 + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> 3900 + <arg name="sid" type="o"> 3901 + <doc:doc> 3902 + <doc:summary>The seat to add the session to</doc:summary> 3903 + </doc:doc> 3904 + </arg> 3905 + <arg name="type" type="s"> 3906 + <doc:doc> 3907 + <doc:summary>The type of session to run (e.g. "LoginWindow", "Chooser", etc)</doc:summary> 3908 + </doc:doc> 3909 + </arg> 3910 + <arg name="display_type" type="s"> 3911 + <doc:doc> 3912 + <doc:summary>The name of the display type to use (defined in displays.d)</doc:summary> 3913 + </doc:doc> 3914 + </arg> 3915 + <arg name="variables" type="a{ss}"> 3916 + <doc:doc> 3917 + <doc:summary>Session type specific parameters</doc:summary> 3918 + </doc:doc> 3919 + </arg> 3920 + <arg name="ssid" direction="out" type="o"> 3921 + <doc:doc> 3922 + <doc:summary>Session ID</doc:summary> 3923 + </doc:doc> 3924 + </arg> 3925 + <doc:doc> 3926 + <doc:description> 3927 + <doc:para>Request a new session gets added to seat.</doc:para> 3928 + </doc:description> 3929 + </doc:doc> 3930 + </method> 3931 + <method name="RemoveSession"> 3932 + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> 3933 + <arg name="ssid" type="o" direction="in"> 3934 + <doc:doc> 3935 + <doc:summary>The session id of the session to remove</doc:summary> 3936 + </doc:doc> 3937 + </arg> 3938 + <doc:doc> 3939 + <doc:description> 3940 + <doc:para>This method is to remove a session from a seat 3941 + </doc:para> 3942 + </doc:description> 3943 + </doc:doc> 3944 + </method> 3945 + 3946 <signal name="SeatAdded"> 3947 <arg name="sid" type="o"> 3948 <doc:doc> 3949 <doc:summary>The Seat ID for the added seat</doc:summary> 3950 </doc:doc> 3951 </arg> 3952 + <arg name="type" type="s"> 3953 + <doc:doc> 3954 + <doc:summary>The type of seat added.</doc:summary> 3955 + </doc:doc> 3956 + </arg> 3957 <doc:doc> 3958 <doc:description> 3959 <doc:para>Emitted when a Seat has been added to the system. 3960 diff --git a/src/org.freedesktop.ConsoleKit.Seat.xml b/src/org.freedesktop.ConsoleKit.Seat.xml 3961 index d95990b..1f6c46f 100644 3962 --- a/src/org.freedesktop.ConsoleKit.Seat.xml 3963 +++ b/src/org.freedesktop.ConsoleKit.Seat.xml 3964 @@ -100,6 +100,24 @@ seat at a time.</doc:para> 3965 </doc:doc> 3966 </method> 3967 3968 + <method name="Manage"> 3969 + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> 3970 + <doc:doc> 3971 + <doc:description> 3972 + <doc:para>Attempt to create unmanaged sessions for this seat.</doc:para> 3973 + </doc:description> 3974 + </doc:doc> 3975 + </method> 3976 + 3977 + <method name="Unmanage"> 3978 + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> 3979 + <doc:doc> 3980 + <doc:description> 3981 + <doc:para>Stop managing seat.</doc:para> 3982 + </doc:description> 3983 + </doc:doc> 3984 + </method> 3985 + 3986 <signal name="ActiveSessionChanged"> 3987 <arg name="ssid" type="o"> 3988 <doc:doc> 3989 @@ -160,5 +178,61 @@ seat at a time.</doc:para> 3990 </doc:description> 3991 </doc:doc> 3992 </signal> 3993 + <signal name="OpenSessionRequest"> 3994 + <arg name="ssid" type="o"> 3995 + <doc:doc> 3996 + <doc:summary>The session id of the session to add</doc:summary> 3997 + </doc:doc> 3998 + </arg> 3999 + <arg name="session_type" type="s"> 4000 + <doc:doc> 4001 + <doc:summary>The type of session to run (e.g. "LoginWindow", "Chooser", etc)</doc:summary> 4002 + </doc:doc> 4003 + </arg> 4004 + <arg name="display_template_name" type="s"> 4005 + <doc:doc> 4006 + <doc:summary>The name of display template </doc:summary> 4007 + </doc:doc> 4008 + </arg> 4009 + <arg name="parameters" type="a{ss}"> 4010 + <doc:doc> 4011 + <doc:summary>Session type specific parameters</doc:summary> 4012 + </doc:doc> 4013 + </arg> 4014 + <arg name="display_type" type="s"> 4015 + <doc:doc> 4016 + <doc:summary>The type of display to use (e.g. "X11", "Command", "XDMCP", etc)</doc:summary> 4017 + </doc:doc> 4018 + </arg> 4019 + <arg name="display_parameters" type="a{ss}"> 4020 + <doc:doc> 4021 + <doc:summary>Display type specific parameters</doc:summary> 4022 + </doc:doc> 4023 + </arg> 4024 + <doc:doc> 4025 + <doc:description> 4026 + <doc:para>Emitted when a new session should get added to the seat.</doc:para> 4027 + </doc:description> 4028 + </doc:doc> 4029 + </signal> 4030 + <signal name="CloseSessionRequest"> 4031 + <arg name="ssid" type="o"> 4032 + <doc:doc> 4033 + <doc:summary>The session id of the session to remove</doc:summary> 4034 + </doc:doc> 4035 + </arg> 4036 + <doc:doc> 4037 + <doc:description> 4038 + <doc:para>Emitted when a session with given display number need to be removed.</doc:para> 4039 + </doc:description> 4040 + </doc:doc> 4041 + </signal> 4042 + <signal name="RemoveRequest"> 4043 + <doc:doc> 4044 + <doc:description> 4045 + <doc:para>Emitted when seat needs to get removed.</doc:para> 4046 + </doc:description> 4047 + </doc:doc> 4048 + </signal> 4049 </interface> 4050 </node> 4051 diff --git a/src/org.freedesktop.ConsoleKit.Session.xml b/src/org.freedesktop.ConsoleKit.Session.xml 4052 index b6e1cdb..2652058 100644 4053 --- a/src/org.freedesktop.ConsoleKit.Session.xml 4054 +++ b/src/org.freedesktop.ConsoleKit.Session.xml 4055 @@ -52,6 +52,19 @@ 4056 <doc:seealso><doc:ref type="property" to="Session:session-type">session-type</doc:ref></doc:seealso> 4057 </doc:doc> 4058 </method> 4059 + <method name="GetDisplayType"> 4060 + <arg name="type" direction="out" type="s"> 4061 + <doc:doc> 4062 + <doc:summary>Display type</doc:summary> 4063 + </doc:doc> 4064 + </arg> 4065 + <doc:doc> 4066 + <doc:description> 4067 + <doc:para>Returns the display type of the session.</doc:para> 4068 + </doc:description> 4069 + <doc:seealso><doc:ref type="property" to="Session:display-type">display-type</doc:ref></doc:seealso> 4070 + </doc:doc> 4071 + </method> 4072 <method name="GetUser"> 4073 <arg name="uid" direction="out" type="u"> 4074 <doc:doc> 4075 @@ -174,6 +187,18 @@ 4076 <doc:seealso><doc:ref type="property" to="Session:is-local">is-local</doc:ref></doc:seealso> 4077 </doc:doc> 4078 </method> 4079 + <method name="IsOpen"> 4080 + <arg name="open" direction="out" type="b"> 4081 + <doc:doc> 4082 + <doc:summary>TRUE if the session is open, otherwise FALSE</doc:summary> 4083 + </doc:doc> 4084 + </arg> 4085 + <doc:doc> 4086 + <doc:description><doc:para>Returns whether the session is open</doc:para> 4087 + </doc:description> 4088 + <doc:seealso><doc:ref type="property" to="Session:is-open">is-open</doc:ref></doc:seealso> 4089 + </doc:doc> 4090 + </method> 4091 <method name="GetCreationTime"> 4092 <arg name="iso8601_datetime" type="s" direction="out"> 4093 <doc:doc> 4094 @@ -275,6 +300,21 @@ 4095 </doc:description> 4096 </doc:doc> 4097 </method> 4098 + <method name="SetRemoveOnClose"> 4099 + <annotation name="org.freedesktop.DBus.GLib.Async" value=""/> 4100 + <arg name="remove_on_close" type="b" direction="in"> 4101 + <doc:doc> 4102 + <doc:summary>boolean value to set the remove-on-close to</doc:summary> 4103 + </doc:doc> 4104 + </arg> 4105 + <doc:doc> 4106 + <doc:description> 4107 + <doc:para>This may be used by the session to indicate that 4108 + it should be respawn or not when it is closed. 4109 + </doc:para> 4110 + </doc:description> 4111 + </doc:doc> 4112 + </method> 4113 4114 <signal name="ActiveChanged"> 4115 <arg name="is_active" type="b"> 4116 @@ -317,6 +357,19 @@ 4117 </doc:doc> 4118 </signal> 4119 4120 + <property name="session" type="o" access="readwrite"> 4121 + <doc:doc> 4122 + <doc:description> 4123 + <doc:para>The id of the session.</doc:para> 4124 + <doc:para> 4125 + The object path of the session. Typically this is set by a session leader during a call to the 4126 + <doc:ref type="method" to="Manager.OpenSessionWithParameters">OpenSessionWithParameters</doc:ref> method, when 4127 + opening a session in response to the <doc:ref type="signal" to="Seat::OpenSessionRequest">OpenSessionRequest</doc:ref> 4128 + signal. 4129 + </doc:para> 4130 + </doc:description> 4131 + </doc:doc> 4132 + </property> 4133 <property name="unix-user" type="u" access="readwrite"> 4134 <doc:doc> 4135 <doc:description> 4136 @@ -342,6 +395,16 @@ 4137 </doc:description> 4138 </doc:doc> 4139 </property> 4140 + <property name="display-type" type="s" access="readwrite"> 4141 + <doc:doc> 4142 + <doc:description> 4143 + <doc:para>The display type of the session.</doc:para> 4144 + <doc:para>Indicate the display template name. All the display template configuration 4145 + files are under /etc/ConsoleKit/displays.d/. 4146 + </doc:para> 4147 + </doc:description> 4148 + </doc:doc> 4149 + </property> 4150 <property name="remote-host-name" type="s" access="readwrite"> 4151 <doc:doc> 4152 <doc:description> 4153 @@ -396,6 +459,19 @@ 4154 </doc:description> 4155 </doc:doc> 4156 </property> 4157 + <property name="is-open" type="b" access="readwrite"> 4158 + <doc:doc> 4159 + <doc:description> 4160 + <doc:para> 4161 + Whether the session is open</doc:para> 4162 + <doc:para>Sessions added from static configuration or in direct response to a call to 4163 + the <doc:ref type="method" to="Manager.AddSession">AddSession</doc:ref> method are initialally 4164 + closed and aren't open until a call to the <doc:ref type="method" to="Manager.OpenSessionWithParameters">OpenSessionWithParameters</doc:ref> 4165 + method. 4166 + </doc:para> 4167 + </doc:description> 4168 + </doc:doc> 4169 + </property> 4170 <property name="is-local" type="b" access="readwrite"> 4171 <doc:doc> 4172 <doc:description> 4173 @@ -408,6 +484,14 @@ 4174 </doc:description> 4175 </doc:doc> 4176 </property> 4177 + <property name="is-dynamic" type="b" access="readwrite"> 4178 + <doc:doc> 4179 + <doc:description> 4180 + <doc:para> 4181 + Whether the session is dynamic</doc:para> 4182 + </doc:description> 4183 + </doc:doc> 4184 + </property> 4185 <property name="idle-hint" type="b" access="readwrite"> 4186 <doc:doc> 4187 <doc:description> 4188 @@ -430,6 +514,14 @@ 4189 </doc:description> 4190 </doc:doc> 4191 </property> 4192 + <property name="remove-on-close" type="b" access="readwrite"> 4193 + <doc:doc> 4194 + <doc:description> 4195 + <doc:para> 4196 + Whether the session respawn when it is closed</doc:para> 4197 + </doc:description> 4198 + </doc:doc> 4199 + </property> 4200 4201 </interface> 4202 </node> 4203 diff --git a/src/strverscmp.c b/src/strverscmp.c 4204 new file mode 100644 4205 index 0000000..f077651 4206 --- /dev/null 4207 +++ b/src/strverscmp.c 4208 @@ -0,0 +1,131 @@ 4209 +/* Compare strings while treating digits characters numerically. 4210 + Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc. 4211 + This file is part of the GNU C Library. 4212 + Contributed by Jean-Franois Bignolles <bignolle (a] ecoledoc.ibp.fr>, 1997. 4213 + 4214 + This program is free software; you can redistribute it and/or modify 4215 + it under the terms of the GNU General Public License as published by 4216 + the Free Software Foundation; either version 2, or (at your option) 4217 + any later version. 4218 + 4219 + This program is distributed in the hope that it will be useful, 4220 + but WITHOUT ANY WARRANTY; without even the implied warranty of 4221 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 4222 + GNU General Public License for more details. 4223 + 4224 + You should have received a copy of the GNU General Public License along 4225 + with this program; if not, write to the Free Software Foundation, 4226 + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 4227 + 4228 +#if !_LIBC 4229 +# include <config.h> 4230 +#endif 4231 + 4232 +#include <string.h> 4233 +#include <ctype.h> 4234 + 4235 +/* states: S_N: normal, S_I: comparing integral part, S_F: comparing 4236 + fractional parts, S_Z: idem but with leading Zeroes only */ 4237 +#define S_N 0x0 4238 +#define S_I 0x4 4239 +#define S_F 0x8 4240 +#define S_Z 0xC 4241 + 4242 +/* result_type: CMP: return diff; LEN: compare using len_diff/diff */ 4243 +#define CMP 2 4244 +#define LEN 3 4245 + 4246 + 4247 +/* ISDIGIT differs from isdigit, as follows: 4248 + - Its arg may be any int or unsigned int; it need not be an unsigned char 4249 + or EOF. 4250 + - It's typically faster. 4251 + POSIX says that only '0' through '9' are digits. Prefer ISDIGIT to 4252 + isdigit unless it's important to use the locale's definition 4253 + of `digit' even when the host does not conform to POSIX. */ 4254 +#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9) 4255 + 4256 +#undef __strverscmp 4257 +#undef strverscmp 4258 + 4259 +#ifndef weak_alias 4260 +# define __strverscmp strverscmp 4261 +#endif 4262 + 4263 +/* Compare S1 and S2 as strings holding indices/version numbers, 4264 + returning less than, equal to or greater than zero if S1 is less than, 4265 + equal to or greater than S2 (for more info, see the texinfo doc). 4266 +*/ 4267 + 4268 +int 4269 +__strverscmp (const char *s1, const char *s2) 4270 +{ 4271 + const unsigned char *p1 = (const unsigned char *) s1; 4272 + const unsigned char *p2 = (const unsigned char *) s2; 4273 + unsigned char c1, c2; 4274 + int state; 4275 + int diff; 4276 + 4277 + /* Symbol(s) 0 [1-9] others (padding) 4278 + Transition (10) 0 (01) d (00) x (11) - */ 4279 + static const unsigned int next_state[] = 4280 + { 4281 + /* state x d 0 - */ 4282 + /* S_N */ S_N, S_I, S_Z, S_N, 4283 + /* S_I */ S_N, S_I, S_I, S_I, 4284 + /* S_F */ S_N, S_F, S_F, S_F, 4285 + /* S_Z */ S_N, S_F, S_Z, S_Z 4286 + }; 4287 + 4288 + static const int result_type[] = 4289 + { 4290 + /* state x/x x/d x/0 x/- d/x d/d d/0 d/- 4291 + 0/x 0/d 0/0 0/- -/x -/d -/0 -/- */ 4292 + 4293 + /* S_N */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, 4294 + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, 4295 + /* S_I */ CMP, -1, -1, CMP, 1, LEN, LEN, CMP, 4296 + 1, LEN, LEN, CMP, CMP, CMP, CMP, CMP, 4297 + /* S_F */ CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP, 4298 + CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP, 4299 + /* S_Z */ CMP, 1, 1, CMP, -1, CMP, CMP, CMP, 4300 + -1, CMP, CMP, CMP 4301 + }; 4302 + 4303 + if (p1 == p2) 4304 + return 0; 4305 + 4306 + c1 = *p1++; 4307 + c2 = *p2++; 4308 + /* Hint: '0' is a digit too. */ 4309 + state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0)); 4310 + 4311 + while ((diff = c1 - c2) == 0 && c1 != '\0') 4312 + { 4313 + state = next_state[state]; 4314 + c1 = *p1++; 4315 + c2 = *p2++; 4316 + state |= (c1 == '0') + (ISDIGIT (c1) != 0); 4317 + } 4318 + 4319 + state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))]; 4320 + 4321 + switch (state) 4322 + { 4323 + case CMP: 4324 + return diff; 4325 + 4326 + case LEN: 4327 + while (ISDIGIT (*p1++)) 4328 + if (!ISDIGIT (*p2++)) 4329 + return 1; 4330 + 4331 + return ISDIGIT (*p2) ? -1 : diff; 4332 + 4333 + default: 4334 + return state; 4335 + } 4336 +} 4337 +#ifdef weak_alias 4338 +weak_alias (__strverscmp, strverscmp) 4339 +#endif 4340 diff --git a/src/strverscmp.h b/src/strverscmp.h 4341 new file mode 100644 4342 index 0000000..48670c8 4343 --- /dev/null 4344 +++ b/src/strverscmp.h 4345 @@ -0,0 +1,25 @@ 4346 +/* Compare strings while treating digits characters numerically. 4347 + Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc. 4348 + This file is part of the GNU C Library. 4349 + Contributed by Jean-Franois Bignolles <bignolle (a] ecoledoc.ibp.fr>, 1997. 4350 + 4351 + This program is free software; you can redistribute it and/or modify 4352 + it under the terms of the GNU General Public License as published by 4353 + the Free Software Foundation; either version 2, or (at your option) 4354 + any later version. 4355 + 4356 + This program is distributed in the hope that it will be useful, 4357 + but WITHOUT ANY WARRANTY; without even the implied warranty of 4358 + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 4359 + GNU General Public License for more details. 4360 + 4361 + You should have received a copy of the GNU General Public License along 4362 + with this program; if not, write to the Free Software Foundation, 4363 + Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ 4364 + 4365 +#ifndef STRVERSCMP_H_ 4366 +# define STRVERSCMP_H_ 4367 + 4368 +int strverscmp (const char *, const char *); 4369 + 4370 +#endif /* not STRVERSCMP_H_ */ 4371 diff --git a/tools/Makefile.am b/tools/Makefile.am 4372 index 13c191f..fa16c68 100644 4373 --- a/tools/Makefile.am 4374 +++ b/tools/Makefile.am 4375 @@ -54,6 +54,7 @@ sbin_PROGRAMS = \ 4376 ck-log-system-start \ 4377 ck-log-system-restart \ 4378 ck-log-system-stop \ 4379 + ck-seat-tool \ 4380 $(NULL) 4381 4382 ck_launch_session_SOURCES = \ 4383 @@ -83,6 +84,14 @@ ck_history_LDADD = \ 4384 $(top_builddir)/src/libck-event-log.la \ 4385 $(NULL) 4386 4387 +ck_seat_tool_SOURCES = \ 4388 + ck-seat-tool.c \ 4389 + $(NULL) 4390 + 4391 +ck_seat_tool_LDADD = \ 4392 + $(CONSOLE_KIT_LIBS) \ 4393 + $(NULL) 4394 + 4395 ck_log_system_start_SOURCES = \ 4396 ck-log-system-start.c \ 4397 $(NULL) 4398 diff --git a/tools/ck-seat-tool.c b/tools/ck-seat-tool.c 4399 new file mode 100644 4400 index 0000000..810fe14 4401 --- /dev/null 4402 +++ b/tools/ck-seat-tool.c 4403 @@ -0,0 +1,442 @@ 4404 +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- 4405 + * 4406 + * Copyright (C) 2009 Sun Microsystems, Inc. 4407 + * 4408 + * This program is free software; you can redistribute it and/or 4409 + * modify it under the terms of the GNU General Public License as 4410 + * published by the Free Software Foundation; either version 2 of the 4411 + * License, or (at your option) any later version. 4412 + * 4413 + * This program is distributed in the hope that it will be useful, but 4414 + * WITHOUT ANY WARRANTY; without even the implied warranty of 4415 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 4416 + * General Public License for more details. 4417 + * 4418 + * You should have received a copy of the GNU General Public License 4419 + * along with this program; if not, write to the Free Software 4420 + * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 4421 + * 02111-1307, USA. 4422 + * 4423 + * Authors: Halton Huo <halton.huo (a] sun.com> 4424 + * 4425 + */ 4426 + 4427 +#include "config.h" 4428 + 4429 +#include <stdlib.h> 4430 +#include <stdio.h> 4431 +#include <sys/types.h> 4432 +#include <unistd.h> 4433 +#include <strings.h> 4434 +#include <glib/gi18n.h> 4435 +#include <dbus/dbus-glib.h> 4436 +#include <dbus/dbus-glib-lowlevel.h> 4437 + 4438 +#define CK_NAME "org.freedesktop.ConsoleKit" 4439 +#define CK_PATH "/org/freedesktop/ConsoleKit" 4440 +#define CK_INTERFACE "org.freedesktop.ConsoleKit" 4441 +#define CK_MANAGER_PATH "/org/freedesktop/ConsoleKit/Manager" 4442 +#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager" 4443 +#define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" 4444 +#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" 4445 + 4446 +#define CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING)) 4447 + 4448 +#define IS_STR_SET(x) (x != NULL && x[0] != '\0') 4449 +#define CK_PATH_PREFIX "/org/freedesktop/ConsoleKit/" 4450 + 4451 +static gboolean add = FALSE; 4452 +static gboolean delete = FALSE; 4453 +static gboolean show_version = FALSE; 4454 +static char *session_type = NULL; 4455 +static char *display_type = NULL; 4456 +static char *seat_id = NULL; 4457 +static char *session_id = NULL; 4458 +static gchar **remaining_args = NULL; 4459 + 4460 +static const GOptionEntry options [] = { 4461 + { "add", 'a', 0, G_OPTION_ARG_NONE, &add, N_("Add a new session"), NULL}, 4462 + { "session-type", '\0', 0, G_OPTION_ARG_STRING, &session_type, N_("Specify session type when adding a session. Default is LoginWindow."), NULL}, 4463 + { "display-type", '\0', 0, G_OPTION_ARG_STRING, &display_type, N_("Specify display type under <etc>/ConsoleKit/displays.d/ when adding a session."), NULL}, 4464 + { "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}, 4465 + { 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 }, 4466 + { "delete", 'd', 0, G_OPTION_ARG_NONE, &delete, N_("Delete a session"), NULL}, 4467 + { "session-id", '\0', 0, G_OPTION_ARG_STRING, &session_id, N_("Specify session id when deleting a session"), NULL}, 4468 + { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL }, 4469 + { NULL } 4470 +}; 4471 + 4472 +static void 4473 +add_session (DBusGConnection *connection) 4474 +{ 4475 + DBusGProxy *mgr_proxy = NULL; 4476 + DBusGProxy *seat_proxy = NULL; 4477 + GError *error = NULL; 4478 + gboolean res; 4479 + char *sid = NULL; 4480 + GPtrArray *seats; 4481 + char *ssid = NULL; 4482 + int i; 4483 + gboolean found; 4484 + char *sstype = NULL; 4485 + GHashTable *variables = NULL; 4486 + 4487 + if (! IS_STR_SET (session_type)) { 4488 + sstype = g_strdup ("LoginWindow"); 4489 + } else { 4490 + sstype = g_strdup (session_type); 4491 + } 4492 + 4493 + mgr_proxy = dbus_g_proxy_new_for_name (connection, 4494 + CK_NAME, 4495 + CK_MANAGER_PATH, 4496 + CK_MANAGER_INTERFACE); 4497 + if (mgr_proxy == NULL) { 4498 + return; 4499 + } 4500 + 4501 + if (! IS_STR_SET(seat_id)) { 4502 + 4503 + /* If seat id is not given, create a new seat */ 4504 + error = NULL; 4505 + res = dbus_g_proxy_call (mgr_proxy, 4506 + "AddSeat", 4507 + &error, 4508 + G_TYPE_STRING, "Default", 4509 + G_TYPE_INVALID, 4510 + DBUS_TYPE_G_OBJECT_PATH, &sid, 4511 + G_TYPE_INVALID); 4512 + if (!res) { 4513 + g_warning ("Unable to add seat: %s", error->message); 4514 + g_error_free (error); 4515 + g_object_unref (mgr_proxy); 4516 + return; 4517 + } 4518 + 4519 + } else { 4520 + if (!g_str_has_prefix (seat_id, CK_PATH_PREFIX)) { 4521 + sid = g_strdup_printf ("%s%s", CK_PATH_PREFIX, seat_id); 4522 + } else { 4523 + sid = g_strdup (seat_id); 4524 + } 4525 + /* Check whether seat is existing, if not, try to create it. */ 4526 + 4527 + error = NULL; 4528 + res = dbus_g_proxy_call (mgr_proxy, 4529 + "GetSeats", 4530 + &error, 4531 + G_TYPE_INVALID, 4532 + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), 4533 + &seats, 4534 + G_TYPE_INVALID); 4535 + if (!res) { 4536 + g_warning ("Unable to get seat list: %s", error->message); 4537 + g_error_free (error); 4538 + g_object_unref (mgr_proxy); 4539 + return; 4540 + } 4541 + 4542 + found = FALSE; 4543 + for (i = 0; i < seats->len; i++) { 4544 + char *tmp_sid; 4545 + 4546 + tmp_sid = g_ptr_array_index (seats, i); 4547 + if (g_str_equal (sid, tmp_sid)) { 4548 + found = TRUE; 4549 + g_free (tmp_sid); 4550 + break; 4551 + } 4552 + 4553 + g_free (tmp_sid); 4554 + } 4555 + 4556 + if (! found) { 4557 + error = NULL; 4558 + res = dbus_g_proxy_call (mgr_proxy, 4559 + "AddSeatById", 4560 + &error, 4561 + G_TYPE_STRING, "Default", 4562 + DBUS_TYPE_G_OBJECT_PATH, sid, 4563 + G_TYPE_INVALID, 4564 + G_TYPE_INVALID); 4565 + if (!res) { 4566 + g_warning ("Unable to add seat: %s", error->message); 4567 + g_error_free (error); 4568 + g_object_unref (mgr_proxy); 4569 + return; 4570 + } 4571 + } 4572 + } 4573 + 4574 + seat_proxy = dbus_g_proxy_new_for_name (connection, 4575 + CK_NAME, 4576 + sid, 4577 + CK_SEAT_INTERFACE); 4578 + 4579 + if (seat_proxy == NULL) { 4580 + g_warning ("Failed to talk to seat '%s'", sid); 4581 + g_object_unref (mgr_proxy); 4582 + return; 4583 + } 4584 + 4585 + variables = g_hash_table_new_full (g_str_hash, g_str_equal, 4586 + (GDestroyNotify) g_free, 4587 + (GDestroyNotify) g_free); 4588 + 4589 + for (i = 0; i < G_N_ELEMENTS (remaining_args); i++) { 4590 + char **arr; 4591 + 4592 + /* split var=value */ 4593 + arr = g_strsplit (remaining_args[i], "=", 2); 4594 + if (arr[0] && arr[1]) { 4595 + g_hash_table_insert (variables, 4596 + g_strdup(arr[0]), 4597 + g_strdup (arr[1])); 4598 + } 4599 + g_strfreev (arr); 4600 + 4601 + } 4602 + 4603 + error = NULL; 4604 + res = dbus_g_proxy_call (mgr_proxy, 4605 + "AddSession", 4606 + &error, 4607 + DBUS_TYPE_G_OBJECT_PATH, sid, 4608 + G_TYPE_STRING, sstype, 4609 + G_TYPE_STRING, display_type, 4610 + CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE, variables, 4611 + G_TYPE_INVALID, 4612 + DBUS_TYPE_G_OBJECT_PATH, &ssid, 4613 + G_TYPE_INVALID); 4614 + 4615 + if (!res) { 4616 + g_warning ("Unable to add dynamic session: %s", error->message); 4617 + g_error_free (error); 4618 + } else { 4619 + dbus_g_proxy_call_no_reply (seat_proxy, 4620 + "Manage", 4621 + G_TYPE_INVALID, 4622 + G_TYPE_INVALID); 4623 + g_print ("Seat %s with session %s has been added\n", sid, ssid); 4624 + } 4625 + 4626 + g_object_unref (seat_proxy); 4627 + g_object_unref (mgr_proxy); 4628 +} 4629 + 4630 +static gboolean 4631 +is_session_on_seat (DBusGConnection *connection, 4632 + const char *sid, 4633 + const char *ssid, 4634 + gboolean *is_last_session) 4635 +{ 4636 + 4637 + DBusGProxy *seat_proxy = NULL; 4638 + GPtrArray *sessions = NULL; 4639 + char *ssid_tmp = NULL; 4640 + gboolean res; 4641 + gboolean retval = FALSE; 4642 + int i; 4643 + GError *error = NULL; 4644 + 4645 + seat_proxy = dbus_g_proxy_new_for_name (connection, 4646 + CK_NAME, 4647 + sid, 4648 + CK_SEAT_INTERFACE); 4649 + 4650 + if (seat_proxy == NULL) { 4651 + g_warning ("Failed to talk to seat '%s'", sid); 4652 + return FALSE; 4653 + } 4654 + 4655 + error = NULL; 4656 + res = dbus_g_proxy_call (seat_proxy, 4657 + "GetSessions", 4658 + &error, 4659 + G_TYPE_INVALID, 4660 + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), 4661 + &sessions, 4662 + G_TYPE_INVALID); 4663 + if (! res) { 4664 + g_warning ("Failed to get list of sessions for %s: %s", sid, error->message); 4665 + g_error_free (error); 4666 + g_object_unref (seat_proxy); 4667 + return FALSE; 4668 + } 4669 + 4670 + for (i = 0; i < sessions->len; i++) { 4671 + 4672 + ssid_tmp = g_ptr_array_index (sessions, i); 4673 + 4674 + if (g_str_equal (ssid, ssid_tmp)) { 4675 + retval = TRUE; 4676 + break; 4677 + } 4678 + 4679 + g_free (ssid_tmp); 4680 + ssid_tmp = NULL; 4681 + } 4682 + 4683 + if (is_last_session != NULL) { 4684 + *is_last_session = sessions->len == 1; 4685 + } 4686 + 4687 + g_ptr_array_free (sessions, TRUE); 4688 + g_object_unref (seat_proxy); 4689 + 4690 + return retval; 4691 +} 4692 + 4693 +static char * 4694 +find_seat_id_from_session_id (DBusGConnection *connection, 4695 + DBusGProxy *proxy, 4696 + const char *ssid, 4697 + gboolean *is_last_session) 4698 +{ 4699 + GError *error; 4700 + GPtrArray *seats; 4701 + int i; 4702 + char *sid; 4703 + gboolean res; 4704 + 4705 + error = NULL; 4706 + res = dbus_g_proxy_call (proxy, 4707 + "GetSeats", 4708 + &error, 4709 + G_TYPE_INVALID, 4710 + dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH), 4711 + &seats, 4712 + G_TYPE_INVALID); 4713 + 4714 + if (! res) { 4715 + g_warning ("Failed to get list of seats: %s", error->message); 4716 + g_error_free (error); 4717 + return NULL; 4718 + } 4719 + 4720 + for (i = 0; i < seats->len; i++) { 4721 + 4722 + sid = g_ptr_array_index (seats, i); 4723 + if (is_session_on_seat (connection, sid, ssid, is_last_session)) { 4724 + break; 4725 + } 4726 + 4727 + g_free (sid); 4728 + } 4729 + g_ptr_array_free (seats, TRUE); 4730 + 4731 + return sid; 4732 +} 4733 + 4734 +static void 4735 +delete_session (DBusGConnection *connection) 4736 +{ 4737 + DBusGProxy *proxy; 4738 + char *ssid; 4739 + char *sid; 4740 + gboolean is_last_session; 4741 + 4742 + if (!g_str_has_prefix (session_id, CK_PATH_PREFIX)) { 4743 + ssid = g_strdup_printf ("%s%s", CK_PATH_PREFIX, session_id); 4744 + } else { 4745 + ssid = g_strdup (session_id); 4746 + } 4747 + 4748 + proxy = dbus_g_proxy_new_for_name (connection, 4749 + CK_NAME, 4750 + CK_MANAGER_PATH, 4751 + CK_MANAGER_INTERFACE); 4752 + if (proxy == NULL) { 4753 + return; 4754 + } 4755 + 4756 + sid = find_seat_id_from_session_id (connection, proxy, ssid, &is_last_session); 4757 + 4758 + dbus_g_proxy_call_no_reply (proxy, 4759 + "RemoveSession", 4760 + DBUS_TYPE_G_OBJECT_PATH, ssid, 4761 + G_TYPE_INVALID, 4762 + G_TYPE_INVALID); 4763 + 4764 + if (is_last_session) { 4765 + dbus_g_proxy_call_no_reply (proxy, 4766 + "RemoveSeat", 4767 + DBUS_TYPE_G_OBJECT_PATH, sid, 4768 + G_TYPE_INVALID, 4769 + G_TYPE_INVALID); 4770 + } 4771 + 4772 + g_object_unref (proxy); 4773 +} 4774 + 4775 +int 4776 +main (int argc, char *argv[]) 4777 +{ 4778 + DBusGConnection *connection; 4779 + GOptionContext *ctx; 4780 + GError *error = NULL; 4781 + gboolean res; 4782 + 4783 + g_type_init (); 4784 + 4785 + /* Option parsing */ 4786 + ctx = g_option_context_new (_("- Manage dynamic sessions")); 4787 + g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE); 4788 + res = g_option_context_parse (ctx, &argc, &argv, &error); 4789 + 4790 + if (!res) { 4791 + if (error) { 4792 + g_warning ("%s", error->message); 4793 + g_error_free (error); 4794 + } 4795 + exit (1); 4796 + } 4797 + 4798 + g_option_context_free (ctx); 4799 + 4800 + if (show_version) { 4801 + g_print ("%s %s\n", argv[0], VERSION); 4802 + exit (0); 4803 + } 4804 + 4805 + if (add && delete) { 4806 + g_warning ("Can not specify -a and -d at the same time!"); 4807 + exit (1); 4808 + } 4809 + 4810 + if (!add && !delete) { 4811 + g_warning ("Must specify -a, -d!"); 4812 + exit (1); 4813 + } 4814 + 4815 + if (delete && (! IS_STR_SET (session_id))) { 4816 + g_warning ("You must specify session id for deleting a session. You can get all sessions by ck-list-sessions"); 4817 + exit (1); 4818 + } 4819 + 4820 + if (add && (! IS_STR_SET (display_type)) ) { 4821 + g_warning ("You must specify display type for adding a session. You can get all display types under <etc>/ConsoleKit/displays.d/"); 4822 + g_warning ("Invalid display type!"); 4823 + exit (1); 4824 + } 4825 + 4826 + error = NULL; 4827 + connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error); 4828 + if (connection == NULL) { 4829 + g_message ("Failed to connect to the D-Bus daemon: %s", error->message); 4830 + g_error_free (error); 4831 + exit (1); 4832 + } 4833 + 4834 + 4835 + if (add) { 4836 + add_session (connection); 4837 + } else if (delete) { 4838 + delete_session (connection); 4839 + } else { 4840 + g_warning ("Invaild parameters!"); 4841 + exit (1); 4842 + } 4843 + 4844 + return 0; 4845 +} 4846 diff --git a/tools/list-sessions.c b/tools/list-sessions.c 4847 index 3933772..cc69d57 100644 4848 --- a/tools/list-sessions.c 4849 +++ b/tools/list-sessions.c 4850 @@ -46,6 +46,23 @@ 4851 #define CK_SEAT_INTERFACE "org.freedesktop.ConsoleKit.Seat" 4852 #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session" 4853 4854 +#define IS_STR_SET(x) (x != NULL && x[0] != '\0') 4855 + 4856 +typedef struct CkSessionOutput { 4857 + char *prop_name; 4858 + char *prop_value; 4859 +} CkSessionOutput; 4860 + 4861 +static gboolean do_all = FALSE; 4862 +static gboolean do_version = FALSE; 4863 +static char *do_format = NULL; 4864 +static GOptionEntry entries [] = { 4865 + { "all", 'a', 0, G_OPTION_ARG_NONE, &do_all, N_("List all sessions. If not given, only list open sessions"), NULL }, 4866 + { "format", 'f', 0, G_OPTION_ARG_STRING, &do_format, N_("Prints information according to the given format"), NULL }, 4867 + { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL }, 4868 + { NULL } 4869 +}; 4870 + 4871 static gboolean 4872 get_uint (DBusGProxy *proxy, 4873 const char *method, 4874 @@ -176,6 +193,7 @@ list_session (DBusGConnection *connection, 4875 char *sid; 4876 char *lsid; 4877 char *session_type; 4878 + char *display_type; 4879 char *x11_display; 4880 char *x11_display_device; 4881 char *display_device; 4882 @@ -184,8 +202,11 @@ list_session (DBusGConnection *connection, 4883 char *idle_since_hint; 4884 gboolean is_active; 4885 gboolean is_local; 4886 + gboolean is_open; 4887 char *short_sid; 4888 const char *short_ssid; 4889 + char **format_arr = NULL; 4890 + int i, j; 4891 4892 proxy = dbus_g_proxy_new_for_name (connection, 4893 CK_NAME, 4894 @@ -198,6 +219,7 @@ list_session (DBusGConnection *connection, 4895 sid = NULL; 4896 lsid = NULL; 4897 session_type = NULL; 4898 + display_type = NULL; 4899 x11_display = NULL; 4900 x11_display_device = NULL; 4901 display_device = NULL; 4902 @@ -209,15 +231,21 @@ list_session (DBusGConnection *connection, 4903 get_path (proxy, "GetSeatId", &sid); 4904 get_string (proxy, "GetLoginSessionId", &lsid); 4905 get_string (proxy, "GetSessionType", &session_type); 4906 + get_string (proxy, "GetDisplayType", &display_type); 4907 get_string (proxy, "GetX11Display", &x11_display); 4908 get_string (proxy, "GetX11DisplayDevice", &x11_display_device); 4909 get_string (proxy, "GetDisplayDevice", &display_device); 4910 get_string (proxy, "GetRemoteHostName", &remote_host_name); 4911 + get_boolean (proxy, "IsOpen", &is_open); 4912 get_boolean (proxy, "IsActive", &is_active); 4913 get_boolean (proxy, "IsLocal", &is_local); 4914 get_string (proxy, "GetCreationTime", &creation_time); 4915 get_string (proxy, "GetIdleSinceHint", &idle_since_hint); 4916 4917 + if (!do_all && !is_open) { 4918 + return; 4919 + } 4920 + 4921 realname = get_real_name (uid); 4922 4923 short_sid = sid; 4924 @@ -230,24 +258,49 @@ list_session (DBusGConnection *connection, 4925 short_ssid = ssid + strlen (CK_PATH) + 1; 4926 } 4927 4928 - 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'", 4929 - short_ssid, 4930 - uid, 4931 - realname, 4932 - short_sid, 4933 - session_type, 4934 - is_active ? "TRUE" : "FALSE", 4935 - x11_display, 4936 - x11_display_device, 4937 - display_device, 4938 - remote_host_name, 4939 - is_local ? "TRUE" : "FALSE", 4940 - creation_time, 4941 - lsid); 4942 - if (idle_since_hint != NULL && idle_since_hint[0] != '\0') { 4943 - printf ("\n\tidle-since-hint = '%s'", idle_since_hint); 4944 + CkSessionOutput output[] = { 4945 + {"session-id", g_strdup (short_ssid)}, 4946 + {"unix-user", g_strdup_printf ("%d", uid)}, 4947 + {"realname", g_strdup (realname)}, 4948 + {"seat", g_strdup (short_sid)}, 4949 + {"session-type", g_strdup (session_type)}, 4950 + {"display-type", g_strdup (display_type)}, 4951 + {"open", is_open ? "TRUE" : "FALSE"}, 4952 + {"active", is_active ? "TRUE" : "FALSE"}, 4953 + {"x11-display", g_strdup (x11_display)}, 4954 + {"x11-display-device", g_strdup (x11_display_device)}, 4955 + {"display-device", g_strdup (display_device)}, 4956 + {"remote-host-name", g_strdup (remote_host_name)}, 4957 + {"is-local", is_local ? "TRUE" : "FALSE"}, 4958 + {"on-since", g_strdup (creation_time)}, 4959 + {"login-session-id", g_strdup (lsid)}, 4960 + {"idle-since-hint", g_strdup (idle_since_hint)}, 4961 + }; 4962 + 4963 + if (IS_STR_SET (do_format)) { 4964 + format_arr = g_strsplit (do_format, ",", -1); 4965 + 4966 + for (i = 0; format_arr[i] != NULL; ++i) { 4967 + for (j = 0; j < G_N_ELEMENTS (output); j++) { 4968 + if (g_str_equal (format_arr[i], output[j].prop_name)) { 4969 + printf ("'%s'\t", output[j].prop_value); 4970 + break; 4971 + } 4972 + } 4973 + } 4974 + printf ("\n"); 4975 + g_strfreev (format_arr); 4976 + 4977 + } else { 4978 + for (j = 0; j < G_N_ELEMENTS (output); j++) { 4979 + if (g_str_equal (output[j].prop_name, "session-id")) 4980 + printf ("%s:\n", output[j].prop_value); 4981 + else 4982 + printf ("\t%s = '%s'\n", 4983 + output[j].prop_name, 4984 + output[j].prop_value); 4985 + } 4986 } 4987 - printf ("\n"); 4988 4989 g_free (idle_since_hint); 4990 g_free (creation_time); 4991 @@ -256,9 +309,11 @@ list_session (DBusGConnection *connection, 4992 g_free (sid); 4993 g_free (lsid); 4994 g_free (session_type); 4995 + g_free (display_type); 4996 g_free (x11_display); 4997 g_free (x11_display_device); 4998 g_free (display_device); 4999 + 5000 g_object_unref (proxy); 5001 } 5002 5003 @@ -368,11 +423,6 @@ main (int argc, 5004 GOptionContext *context; 5005 gboolean retval; 5006 GError *error = NULL; 5007 - static gboolean do_version = FALSE; 5008 - static GOptionEntry entries [] = { 5009 - { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL }, 5010 - { NULL } 5011 - }; 5012 5013 g_type_init (); 5014 5015