25080962 Move consolekit and pam-consolekit 0.4.1 to Userland
authorNiveditha Rau <Niveditha.Rau@Oracle.COM>
Wed, 16 Nov 2016 18:51:32 -0800
changeset 7331 a36c61e047b0
parent 7330 e40cd9caccc7
child 7332 50a475baa0cd
25080962 Move consolekit and pam-consolekit 0.4.1 to Userland 15784276 SUNBT7159820 consolekit does not have 64bit libraries
components/desktop/consolekit/ConsoleKit.license
components/desktop/consolekit/ConsoleKit.p5m
components/desktop/consolekit/Makefile
components/desktop/consolekit/files/ck-history.1
components/desktop/consolekit/files/ck-launch-session.1
components/desktop/consolekit/files/ck-list-sessions.1
components/desktop/consolekit/files/ck-seat-tool.8
components/desktop/consolekit/files/console-kit-daemon.8
components/desktop/consolekit/files/consolekit.xml
components/desktop/consolekit/files/svc-consolekit
components/desktop/consolekit/pam-ConsoleKit.p5m
components/desktop/consolekit/patches/ConsoleKit-01-ck-dynamic.patch
components/desktop/consolekit/patches/ConsoleKit-04-sol-tty.patch
components/desktop/consolekit/patches/ConsoleKit-05-sol-sigpoll.patch
components/desktop/consolekit/patches/ConsoleKit-06-sol-xserver.patch
components/desktop/consolekit/patches/ConsoleKit-07-sol-vt-major.patch
components/desktop/consolekit/patches/ConsoleKit-08-can-stop.patch
components/desktop/consolekit/patches/ConsoleKit-09-fastreboot.patch
components/desktop/consolekit/patches/ConsoleKit-10-ck-history.patch
components/desktop/consolekit/patches/ConsoleKit-11-sol-vtdaemon.patch
components/desktop/consolekit/patches/ConsoleKit-12-suppress-warning.patch
components/desktop/consolekit/patches/ConsoleKit-13-vt-switch.patch
components/desktop/consolekit/patches/ConsoleKit-14-shutdown.patch
components/desktop/consolekit/patches/ConsoleKit-15-bootadm-parse.patch
components/desktop/consolekit/patches/ConsoleKit-16-multidcu.patch
components/desktop/consolekit/patches/ConsoleKit-17-multisession.patch
components/desktop/consolekit/patches/ConsoleKit-18-seattool.patch
components/desktop/consolekit/patches/ConsoleKit-19-listsessions.patch
components/desktop/consolekit/patches/ConsoleKit-20-seattool-2.patch
components/meta-packages/incorporation-cache
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/ConsoleKit.license	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,409 @@
+Copyright (c) 2010, 2014, Oracle and/or its affiliates. All rights reserved.
+
+		    GNU GENERAL PUBLIC LICENSE 
+		       Version 2, June 1991 
+
+ Copyright (C) 1989, 1991 Free Software Foundation, Inc. 
+     51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
+ Everyone is permitted to copy and distribute verbatim copies 
+ of this license document, but changing it is not allowed. 
+ 
+			    Preamble 
+
+  The licenses for most software are designed to take away your 
+freedom to share and change it.  By contrast, the GNU General Public 
+License is intended to guarantee your freedom to share and change free 
+software--to make sure the software is free for all its users.  This 
+General Public License applies to most of the Free Software 
+Foundation's software and to any other program whose authors commit to 
+using it.  (Some other Free Software Foundation software is covered by 
+the GNU Library General Public License instead.)  You can apply it to 
+your programs, too. 
+
+  When we speak of free software, we are referring to freedom, not 
+price.  Our General Public Licenses are designed to make sure that you 
+have the freedom to distribute copies of free software (and charge for 
+this service if you wish), that you receive source code or can get it 
+if you want it, that you can change the software or use pieces of it 
+in new free programs; and that you know you can do these things. 
+
+  To protect your rights, we need to make restrictions that forbid 
+anyone to deny you these rights or to ask you to surrender the rights. 
+These restrictions translate to certain responsibilities for you if you 
+distribute copies of the software, or if you modify it. 
+
+  For example, if you distribute copies of such a program, whether 
+gratis or for a fee, you must give the recipients all the rights that 
+you have.  You must make sure that they, too, receive or can get the 
+source code.  And you must show them these terms so they know their 
+rights. 
+
+  We protect your rights with two steps: (1) copyright the software, and 
+(2) offer you this license which gives you legal permission to copy, 
+distribute and/or modify the software. 
+
+  Also, for each author's protection and ours, we want to make certain 
+that everyone understands that there is no warranty for this free 
+software.  If the software is modified by someone else and passed on, we 
+want its recipients to know that what they have is not the original, so 
+that any problems introduced by others will not reflect on the original 
+authors' reputations. 
+
+  Finally, any free program is threatened constantly by software 
+patents.  We wish to avoid the danger that redistributors of a free 
+program will individually obtain patent licenses, in effect making the 
+program proprietary.  To prevent this, we have made it clear that any 
+patent must be licensed for everyone's free use or not licensed at all. 
+
+  The precise terms and conditions for copying, distribution and 
+modification follow. 
+
+
+		    GNU GENERAL PUBLIC LICENSE 
+   TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION 
+
+  0. This License applies to any program or other work which contains 
+a notice placed by the copyright holder saying it may be distributed 
+under the terms of this General Public License.  The "Program", below, 
+refers to any such program or work, and a "work based on the Program" 
+means either the Program or any derivative work under copyright law: 
+that is to say, a work containing the Program or a portion of it, 
+either verbatim or with modifications and/or translated into another 
+language.  (Hereinafter, translation is included without limitation in 
+the term "modification".)  Each licensee is addressed as "you". 
+
+Activities other than copying, distribution and modification are not 
+covered by this License; they are outside its scope.  The act of 
+running the Program is not restricted, and the output from the Program 
+is covered only if its contents constitute a work based on the 
+Program (independent of having been made by running the Program). 
+Whether that is true depends on what the Program does. 
+
+  1. You may copy and distribute verbatim copies of the Program's 
+source code as you receive it, in any medium, provided that you 
+conspicuously and appropriately publish on each copy an appropriate 
+copyright notice and disclaimer of warranty; keep intact all the 
+notices that refer to this License and to the absence of any warranty; 
+and give any other recipients of the Program a copy of this License 
+along with the Program. 
+
+You may charge a fee for the physical act of transferring a copy, and 
+you may at your option offer warranty protection in exchange for a fee. 
+
+  2. You may modify your copy or copies of the Program or any portion 
+of it, thus forming a work based on the Program, and copy and 
+distribute such modifications or work under the terms of Section 1 
+above, provided that you also meet all of these conditions: 
+
+    a) You must cause the modified files to carry prominent notices 
+    stating that you changed the files and the date of any change. 
+
+    b) You must cause any work that you distribute or publish, that in 
+    whole or in part contains or is derived from the Program or any 
+    part thereof, to be licensed as a whole at no charge to all third 
+    parties under the terms of this License. 
+
+    c) If the modified program normally reads commands interactively 
+    when run, you must cause it, when started running for such 
+    interactive use in the most ordinary way, to print or display an 
+    announcement including an appropriate copyright notice and a 
+    notice that there is no warranty (or else, saying that you provide 
+    a warranty) and that users may redistribute the program under 
+    these conditions, and telling the user how to view a copy of this 
+    License.  (Exception: if the Program itself is interactive but 
+    does not normally print such an announcement, your work based on 
+    the Program is not required to print an announcement.) 
+
+
+These requirements apply to the modified work as a whole.  If 
+identifiable sections of that work are not derived from the Program, 
+and can be reasonably considered independent and separate works in 
+themselves, then this License, and its terms, do not apply to those 
+sections when you distribute them as separate works.  But when you 
+distribute the same sections as part of a whole which is a work based 
+on the Program, the distribution of the whole must be on the terms of 
+this License, whose permissions for other licensees extend to the 
+entire whole, and thus to each and every part regardless of who wrote it. 
+
+Thus, it is not the intent of this section to claim rights or contest 
+your rights to work written entirely by you; rather, the intent is to 
+exercise the right to control the distribution of derivative or 
+collective works based on the Program. 
+
+In addition, mere aggregation of another work not based on the Program 
+with the Program (or with a work based on the Program) on a volume of 
+a storage or distribution medium does not bring the other work under 
+the scope of this License. 
+
+  3. You may copy and distribute the Program (or a work based on it, 
+under Section 2) in object code or executable form under the terms of 
+Sections 1 and 2 above provided that you also do one of the following: 
+
+    a) Accompany it with the complete corresponding machine-readable 
+    source code, which must be distributed under the terms of Sections 
+    1 and 2 above on a medium customarily used for software interchange; or, 
+
+    b) Accompany it with a written offer, valid for at least three 
+    years, to give any third party, for a charge no more than your 
+    cost of physically performing source distribution, a complete 
+    machine-readable copy of the corresponding source code, to be 
+    distributed under the terms of Sections 1 and 2 above on a medium 
+    customarily used for software interchange; or, 
+
+    c) Accompany it with the information you received as to the offer 
+    to distribute corresponding source code.  (This alternative is 
+    allowed only for noncommercial distribution and only if you 
+    received the program in object code or executable form with such 
+    an offer, in accord with Subsection b above.) 
+
+The source code for a work means the preferred form of the work for 
+making modifications to it.  For an executable work, complete source 
+code means all the source code for all modules it contains, plus any 
+associated interface definition files, plus the scripts used to 
+control compilation and installation of the executable.  However, as a 
+special exception, the source code distributed need not include 
+anything that is normally distributed (in either source or binary 
+form) with the major components (compiler, kernel, and so on) of the 
+operating system on which the executable runs, unless that component 
+itself accompanies the executable. 
+
+If distribution of executable or object code is made by offering 
+access to copy from a designated place, then offering equivalent 
+access to copy the source code from the same place counts as 
+distribution of the source code, even though third parties are not 
+compelled to copy the source along with the object code. 
+
+
+  4. You may not copy, modify, sublicense, or distribute the Program 
+except as expressly provided under this License.  Any attempt 
+otherwise to copy, modify, sublicense or distribute the Program is 
+void, and will automatically terminate your rights under this License. 
+However, parties who have received copies, or rights, from you under 
+this License will not have their licenses terminated so long as such 
+parties remain in full compliance. 
+
+  5. You are not required to accept this License, since you have not 
+signed it.  However, nothing else grants you permission to modify or 
+distribute the Program or its derivative works.  These actions are 
+prohibited by law if you do not accept this License.  Therefore, by 
+modifying or distributing the Program (or any work based on the 
+Program), you indicate your acceptance of this License to do so, and 
+all its terms and conditions for copying, distributing or modifying 
+the Program or works based on it. 
+
+  6. Each time you redistribute the Program (or any work based on the 
+Program), the recipient automatically receives a license from the 
+original licensor to copy, distribute or modify the Program subject to 
+these terms and conditions.  You may not impose any further 
+restrictions on the recipients' exercise of the rights granted herein. 
+You are not responsible for enforcing compliance by third parties to 
+this License. 
+
+  7. If, as a consequence of a court judgment or allegation of patent 
+infringement or for any other reason (not limited to patent issues), 
+conditions are imposed on you (whether by court order, agreement or 
+otherwise) that contradict the conditions of this License, they do not 
+excuse you from the conditions of this License.  If you cannot 
+distribute so as to satisfy simultaneously your obligations under this 
+License and any other pertinent obligations, then as a consequence you 
+may not distribute the Program at all.  For example, if a patent 
+license would not permit royalty-free redistribution of the Program by 
+all those who receive copies directly or indirectly through you, then 
+the only way you could satisfy both it and this License would be to 
+refrain entirely from distribution of the Program. 
+
+If any portion of this section is held invalid or unenforceable under 
+any particular circumstance, the balance of the section is intended to 
+apply and the section as a whole is intended to apply in other 
+circumstances. 
+ 
+It is not the purpose of this section to induce you to infringe any 
+patents or other property right claims or to contest validity of any 
+such claims; this section has the sole purpose of protecting the 
+integrity of the free software distribution system, which is 
+implemented by public license practices.  Many people have made 
+generous contributions to the wide range of software distributed 
+through that system in reliance on consistent application of that 
+system; it is up to the author/donor to decide if he or she is willing 
+to distribute software through any other system and a licensee cannot 
+impose that choice. 
+
+This section is intended to make thoroughly clear what is believed to 
+be a consequence of the rest of this License. 
+
+
+  8. If the distribution and/or use of the Program is restricted in 
+certain countries either by patents or by copyrighted interfaces, the 
+original copyright holder who places the Program under this License 
+may add an explicit geographical distribution limitation excluding 
+those countries, so that distribution is permitted only in or among 
+countries not thus excluded.  In such case, this License incorporates 
+the limitation as if written in the body of this License. 
+
+  9. The Free Software Foundation may publish revised and/or new versions 
+of the General Public License from time to time.  Such new versions will 
+be similar in spirit to the present version, but may differ in detail to 
+address new problems or concerns. 
+
+Each version is given a distinguishing version number.  If the Program 
+specifies a version number of this License which applies to it and "any 
+later version", you have the option of following the terms and conditions 
+either of that version or of any later version published by the Free 
+Software Foundation.  If the Program does not specify a version number of 
+this License, you may choose any version ever published by the Free Software 
+Foundation. 
+
+  10. If you wish to incorporate parts of the Program into other free 
+programs whose distribution conditions are different, write to the author 
+to ask for permission.  For software which is copyrighted by the Free 
+Software Foundation, write to the Free Software Foundation; we sometimes 
+make exceptions for this.  Our decision will be guided by the two goals 
+of preserving the free status of all derivatives of our free software and 
+of promoting the sharing and reuse of software generally. 
+
+			    NO WARRANTY 
+
+  11. BECAUSE THE PROGRAM IS LICENSED FREE OF CHARGE, THERE IS NO WARRANTY 
+FOR THE PROGRAM, TO THE EXTENT PERMITTED BY APPLICABLE LAW.  EXCEPT WHEN 
+OTHERWISE STATED IN WRITING THE COPYRIGHT HOLDERS AND/OR OTHER PARTIES 
+PROVIDE THE PROGRAM "AS IS" WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESSED 
+OR IMPLIED, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF 
+MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.  THE ENTIRE RISK AS 
+TO THE QUALITY AND PERFORMANCE OF THE PROGRAM IS WITH YOU.  SHOULD THE 
+PROGRAM PROVE DEFECTIVE, YOU ASSUME THE COST OF ALL NECESSARY SERVICING, 
+REPAIR OR CORRECTION. 
+
+  12. IN NO EVENT UNLESS REQUIRED BY APPLICABLE LAW OR AGREED TO IN WRITING 
+WILL ANY COPYRIGHT HOLDER, OR ANY OTHER PARTY WHO MAY MODIFY AND/OR 
+REDISTRIBUTE THE PROGRAM AS PERMITTED ABOVE, BE LIABLE TO YOU FOR DAMAGES, 
+INCLUDING ANY GENERAL, SPECIAL, INCIDENTAL OR CONSEQUENTIAL DAMAGES ARISING 
+OUT OF THE USE OR INABILITY TO USE THE PROGRAM (INCLUDING BUT NOT LIMITED 
+TO LOSS OF DATA OR DATA BEING RENDERED INACCURATE OR LOSSES SUSTAINED BY 
+YOU OR THIRD PARTIES OR A FAILURE OF THE PROGRAM TO OPERATE WITH ANY OTHER 
+PROGRAMS), EVEN IF SUCH HOLDER OR OTHER PARTY HAS BEEN ADVISED OF THE 
+POSSIBILITY OF SUCH DAMAGES. 
+
+		     END OF TERMS AND CONDITIONS 
+ 
+
+	    How to Apply These Terms to Your New Programs 
+
+  If you develop a new program, and you want it to be of the greatest 
+possible use to the public, the best way to achieve this is to make it 
+free software which everyone can redistribute and change under these terms. 
+
+  To do so, attach the following notices to the program.  It is safest 
+to attach them to the start of each source file to most effectively 
+convey the exclusion of warranty; and each file should have at least 
+the "copyright" line and a pointer to where the full notice is found. 
+
+    <one line to give the program's name and a brief idea of what it does.> 
+    Copyright (C) <year>  <name of author> 
+
+    This program is free software; you can redistribute it and/or modify 
+    it under the terms of the GNU General Public License as published by 
+    the Free Software Foundation; either version 2 of the License, or 
+    (at your option) any later version. 
+
+    This program is distributed in the hope that it will be useful, 
+    but WITHOUT ANY WARRANTY; without even the implied warranty of 
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
+    GNU General Public License for more details. 
+
+    You should have received a copy of the GNU General Public License 
+    along with this program; if not, write to the Free Software 
+    Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301  USA 
+
+
+Also add information on how to contact you by electronic and paper mail. 
+
+If the program is interactive, make it output a short notice like this 
+when it starts in an interactive mode: 
+
+    Gnomovision version 69, Copyright (C) year  name of author 
+    Gnomovision comes with ABSOLUTELY NO WARRANTY; for details type `show w'. 
+    This is free software, and you are welcome to redistribute it 
+    under certain conditions; type `show c' for details. 
+ 
+The hypothetical commands `show w' and `show c' should show the appropriate 
+parts of the General Public License.  Of course, the commands you use may 
+be called something other than `show w' and `show c'; they could even be 
+mouse-clicks or menu items--whatever suits your program. 
+
+You should also get your employer (if you work as a programmer) or your 
+school, if any, to sign a "copyright disclaimer" for the program, if 
+necessary.  Here is a sample; alter the names: 
+
+  Yoyodyne, Inc., hereby disclaims all copyright interest in the program 
+  `Gnomovision' (which makes passes at compilers) written by James Hacker. 
+
+  <signature of Ty Coon>, 1 April 1989 
+  Ty Coon, President of Vice 
+
+This General Public License does not permit incorporating your program into 
+proprietary programs.  If your program is a subroutine library, you may 
+consider it more useful to permit linking proprietary applications with the 
+library.  If this is what you want to do, use the GNU Library General 
+Public License instead of this License. 
+
+
+The ck-launch-session executable has this BSD license:
+
+ConsoleKit-0.4.1/tools/ck-launch-session.c: 
+ Copyright Red Hat, Inc. 2007-2008. 
+ All rights reserved. 
+
+ Redistribution and use in source and binary forms, with or without 
+ modification, are permitted provided that the following conditions are met: 
+
+  * Redistributions of source code must retain the above copyright 
+    notice, this list of conditions and the following disclaimer. 
+  * Redistributions in binary form must reproduce the above copyright 
+    notice, this list of conditions and the following disclaimer in 
+    the documentation and/or other materials provided with the 
+    distribution. 
+  * Neither the name of Red Hat, Inc., nor the names of its 
+    contributors may be used to endorse or promote products derived 
+    from this software without specific prior written permission. 
+
+ THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS 
+ IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 
+ TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A 
+ PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER 
+ OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, 
+ EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, 
+ PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR 
+ PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF 
+ LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING 
+ NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS 
+ SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. 
+
+ Gate a process inside of a ConsoleKit session. 
+
+
+Some ConsoleKit code uses this MIT license:
+
+ * Copyright (c) 2007 David Zeuthen <[email protected]> 
+ * Copyright (c) 2007 William Jon McCann <[email protected]> 
+ * 
+ * Permission is hereby granted, free of charge, to any person 
+ * obtaining a copy of this software and associated documentation 
+ * files (the "Software"), to deal in the Software without 
+ * restriction, including without limitation the rights to use, 
+ * copy, modify, merge, publish, distribute, sublicense, and/or sell 
+ * copies of the Software, and to permit persons to whom the 
+ * Software is furnished to do so, subject to the following 
+ * conditions: 
+ * 
+ * The above copyright notice and this permission notice shall be 
+ * included in all copies or substantial portions of the Software. 
+ * 
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 
+ * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 
+ * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 
+ * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 
+ * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 
+ * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
+ * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 
+ * OTHER DEALINGS IN THE SOFTWARE. 
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/ConsoleKit.p5m	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,95 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+#
+
+<transform file path=usr.*/man/.+ -> default mangler.man.stability uncommitted>
+<transform file path=etc/ConsoleKit/.*\.d/.* -> default preserve true>
+<transform file path=etc/ConsoleKit/.*\.d/.* -> default overlay allow>
+set name=pkg.fmri \
+    value=pkg:/library/xdg/consolekit@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
+set name=pkg.summary \
+    value="Framework for tracking users, login sessions and seats"
+set name=com.oracle.info.description value=ConsoleKit
+set name=com.oracle.info.tpno value=$(TPNO)
+set name=info.classification \
+    value="org.opensolaris.category.2008:Desktop (GNOME)/Sessions"
+set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
+set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
+set name=org.opensolaris.arc-caseid value=LSARC/2009/432
+set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
+dir  path=etc/ConsoleKit group=sys
+file path=etc/ConsoleKit/displays.d/Headless.display
+file path=etc/ConsoleKit/displays.d/HotPlug.display
+file path=etc/ConsoleKit/displays.d/Local.display
+file path=etc/ConsoleKit/displays.d/LocalVNC.display
+file path=etc/ConsoleKit/displays.d/MultiDCU.display
+file path=etc/ConsoleKit/displays.d/RemoteMachine.display
+dir  path=etc/ConsoleKit/run-seat.d group=sys
+dir  path=etc/ConsoleKit/run-session.d group=sys
+file path=etc/ConsoleKit/seats.d/00-primary.seat
+file path=etc/ConsoleKit/sessions.d/Headless.session
+file path=etc/ConsoleKit/sessions.d/Local.session
+file path=etc/ConsoleKit/sessions.d/LocalVNC.session
+file path=etc/ConsoleKit/sessions.d/MultiDCU0.session
+file path=etc/ConsoleKit/sessions.d/MultiDCU1.session
+file path=etc/ConsoleKit/sessions.d/MultiDCU2.session
+file path=etc/ConsoleKit/sessions.d/MultiDCU3.session
+file path=etc/ConsoleKit/sessions.d/Remote.session
+file path=etc/dbus-1/system.d/ConsoleKit.conf
+file files/consolekit.xml path=lib/svc/manifest/system/consolekit.xml
+file files/svc-consolekit path=lib/svc/method/svc-consolekit
+file path=usr/bin/ck-history
+file path=usr/bin/ck-launch-session
+file path=usr/bin/ck-list-sessions
+file path=usr/include/ConsoleKit/ck-connector/ck-connector.h
+link path=usr/lib/$(MACH64)/libck-connector.so target=libck-connector.so.0.0.0
+link path=usr/lib/$(MACH64)/libck-connector.so.0 target=libck-connector.so.0.0.0
+file path=usr/lib/$(MACH64)/libck-connector.so.0.0.0
+dir  path=usr/lib/ConsoleKit/run-seat.d mode=0555
+dir  path=usr/lib/ConsoleKit/run-session.d mode=0555
+file path=usr/lib/ConsoleKit/scripts/ck-system-restart mode=0555
+file path=usr/lib/ConsoleKit/scripts/ck-system-stop mode=0555
+file path=usr/lib/ck-collect-session-info mode=0555
+file path=usr/lib/ck-get-x11-display-device mode=0555
+file path=usr/lib/ck-get-x11-server-pid mode=0555
+link path=usr/lib/libck-connector.so target=libck-connector.so.0.0.0
+link path=usr/lib/libck-connector.so.0 target=libck-connector.so.0.0.0
+file path=usr/lib/libck-connector.so.0.0.0
+file path=usr/lib/pkgconfig/ck-connector.pc
+file path=usr/sbin/ck-log-system-restart
+file path=usr/sbin/ck-log-system-start
+file path=usr/sbin/ck-log-system-stop
+file path=usr/sbin/ck-seat-tool
+file path=usr/sbin/console-kit-daemon
+file path=usr/share/dbus-1/interfaces/org.freedesktop.ConsoleKit.Manager.xml
+file path=usr/share/dbus-1/interfaces/org.freedesktop.ConsoleKit.Seat.xml
+file path=usr/share/dbus-1/interfaces/org.freedesktop.ConsoleKit.Session.xml
+file path=usr/share/dbus-1/system-services/org.freedesktop.ConsoleKit.service
+file files/ck-history.1 path=usr/share/man/man1/ck-history.1
+file files/ck-launch-session.1 path=usr/share/man/man1/ck-launch-session.1
+file files/ck-list-sessions.1 path=usr/share/man/man1/ck-list-sessions.1
+file files/ck-seat-tool.8 path=usr/share/man/man8/ck-seat-tool.8
+file files/console-kit-daemon.8 path=usr/share/man/man8/console-kit-daemon.8
+dir  path=var/log/ConsoleKit group=root
+license ConsoleKit.license license="GPLv2+, BSD, MIT"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/Makefile	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,70 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+#
+
+BUILD_BITS=		64_and_32
+include ../../../make-rules/shared-macros.mk
+
+COMPONENT_NAME=		ConsoleKit
+COMPONENT_VERSION=	0.4.1
+COMPONENT_PROJECT_URL=	http://www.freedesktop.org/software/ConsoleKit
+COMPONENT_ARCHIVE=	$(COMPONENT_SRC).tar.bz2
+COMPONENT_ARCHIVE_HASH= \
+    sha256:f032adc6146d745034315054c5822a7a09f30e20a40d6e802221fa977354403e
+COMPONENT_ARCHIVE_URL=	$(COMPONENT_PROJECT_URL)/dist/$(COMPONENT_ARCHIVE)
+COMPONENT_BUGDB=	library/consolekit
+
+TPNO=			7882
+
+TEST_TARGET = $(NO_TESTS)
+
+include $(WS_MAKE_RULES)/common.mk
+
+COMPONENT_PRE_CONFIGURE_ACTION = ($(CLONEY) $(SOURCE_DIR) $(@D))
+
+COMPONENT_PREP_ACTION = \
+	(cd $(@D) ; \
+	aclocal -I . ; \
+	libtoolize --force ; \
+	autoheader ; \
+	automake -a -c -f ; \
+	autoconf )
+
+CONFIGURE_OPTIONS +=	CFLAGS="$(CFLAGS)"
+CONFIGURE_OPTIONS +=	--sysconfdir=/etc
+CONFIGURE_OPTIONS +=	--enable-pam-module
+CONFIGURE_OPTIONS.32 +=	--with-pam-module-dir=/usr/lib/security
+CONFIGURE_OPTIONS.64 +=	--with-pam-module-dir=/usr/lib/security/$(MACH64)
+CONFIGURE_OPTIONS +=	--libexecdir="$(USRLIB)"
+CONFIGURE_OPTIONS +=	--localstatedir="$(VARDIR)"
+CONFIGURE_OPTIONS +=	--enable-rbac-shutdown=solaris.system.shutdown
+
+REQUIRED_PACKAGES += library/glib2
+REQUIRED_PACKAGES += library/zlib
+REQUIRED_PACKAGES += x11/library/libx11
+REQUIRED_PACKAGES += x11/xserver/xorg
+REQUIRED_PACKAGES += shell/bash
+REQUIRED_PACKAGES += system/core-os
+REQUIRED_PACKAGES += system/library/dbus
+REQUIRED_PACKAGES += system/library/libdbus
+REQUIRED_PACKAGES += system/library/libdbus-glib
+REQUIRED_PACKAGES += system/library/polkit
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/files/ck-history.1	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,80 @@
+.TH ck-history 1 "12 Sep 2016"
+.SH "NAME"
+ck-history \- ConsoleKit history
+.SH "SYNOPSIS"
+.PP
+\fBck-history\fR [-\fB-frequent\fR] [-\fB-help\fR] [-\fB-last\fR] [-\fB-last-compat\fR] [-\fB-log\fR] [-\fB-seat=\fIseat\fR\fR] [-\fB-session-type=\fItype\fR\fR] [-\fB-user=\fIuser\fR\fR] [-\fB-version\fR]
+.SH "DESCRIPTION"
+.PP
+\fBck-history\fR is a utility that provides information from the
+ConsoleKit database about what users have logged into the system\&.  It supports
+options to specify whether to provide information about users who have logged
+in most frequently or most recently\&.
+.PP
+The \fBck-history\fR utility is used by \fBgdm\fR(8)
+when the GDM Face Browser is enabled to display users in the order of
+frequency\&.
+.SH "OPTIONS"
+.PP
+The following options are supported:
+.TP 30
+.B --frequent
+Show listing of logged-in users in the most frequent order\&.
+.TP 30
+\fB-h\fR, \fB--help\fR
+Display detailed usage message\&.
+.TP 30
+.B --last
+Show listing of all user logins since ConsoleKit began logging, in the most
+recent order\&.
+.TP 30
+.B --last-compat
+Show listing of logged-in users in the most-recent order\&.  The output is
+displayed in
+\fBlast\fR(1)
+compatible format\&.
+.TP 30
+.B --log
+Show full ConsoleKit event log\&.
+.TP 30
+\fB-s\fR, \fB--seat=\fR\fIseat\fR
+Show entries for the specified \fIseat\fR\&.
+.TP 30
+\fB-t\fR, \fB--session-type=\fR\fItype\fR
+Show entries for the specified session \fItype\fR\&.
+.TP 30
+\fB-u\fR, \fB--user=\fR\fIuser\fR
+Show entries for the specified \fIuser\fR\&.
+.TP 30
+\fB-V\fR, \fB--version\fR
+Display the version of the \fBck-history\fR application\&.
+.SH "EXAMPLES"
+.PP
+\fBExample 1: Show most frequently logged in users\fR
+.PP
+.nf
+example% \fBck-history -\fB-frequent\fR\fR
+.fi
+.PP
+\fBExample 2: Show the entire ConsoleKit log\&.\fR
+.PP
+.nf
+example% \fBck-history -\fB-log\fR\fR
+.fi
+.SH "FILES"
+.PP
+The following files are used by this application:
+.TP 30
+.B /usr/bin/ck-history
+Executable for ConsoleKit history\&.
+.TP 30
+.B /var/log/ConsoleKit/history
+ConsoleKit history database\&.
+.SH "SEE ALSO"
+.PP
+\fBck-launch-session\fR(1),
+\fBck-list-sessions\fR(1),
+\fBck-seat-tool\fR(8),
+\fBconsole-kit-daemon\fR(8),
+\fBgdm\fR(8),
+\fBattributes\fR(7)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/files/ck-launch-session.1	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,42 @@
+.TH ck-launch-session 1 "12 Sep 2016"
+.SH "NAME"
+ck-launch-session \- ConsoleKit session launcher
+.SH "SYNOPSIS"
+.PP
+\fBck-launch-session\fR \fB\fIcommand\fR\fR
+.SH "DESCRIPTION"
+.PP
+\fBck-launch-session\fR is a utility for starting a command in its own
+ConsoleKit session\&.  This would be useful if a user wanted to start their own
+session via a \fBstartx\fR script and have it registered with
+ConsoleKit, for example\&.
+.SH "OPERANDS"
+.PP
+The following operands are supported:
+.TP 10
+.I command
+Start the specified \fIcommand\fR in its own ConsoleKit
+session\&.
+.SH "EXAMPLES"
+.PP
+\fBExample 1: Launch the \fBstartx\fR command in its own ConsoleKit
+session\fR
+.PP
+.PP
+.nf
+example% \fBck-launch-session \fBstartx\fR\fR
+.fi
+.SH "FILES"
+.PP
+The following files are used by this application:
+.TP 10
+.B /usr/bin/ck-launch-session
+Executable for ConsoleKit session launcher\&.
+.SH "SEE ALSO"
+.PP
+\fBck-history\fR(1),
+\fBck-list-sessions\fR(1),
+\fBck-seat-tool\fR(8),
+\fBconsole-kit-daemon\fR(8),
+\fBgdm\fR(8),
+\fBattributes\fR(7)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/files/ck-list-sessions.1	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,166 @@
+.TH ck-list-sessions 1 "12 Sep 2016"
+.SH "NAME"
+ck-list-sessions \- Show ConsoleKit Session Information
+.SH "SYNOPSIS"
+.PP
+\fBck-list-sessions\fR [-\fB-all\fR] [-\fB-sid=\fIsid\fR\fR] [-\fB-format=\fIformat\fR\fR] [-\fB-help\fR] [-\fB-version\fR]
+.SH "DESCRIPTION"
+.PP
+\fBck-list-sessions\fR is a utility that displays information from the
+ConsoleKit database\&.  By default, only open sessions are shown\&.  The
+-\fB-all\fR option can be used to display all existing sessions on
+the system\&.  \fBck-list-sessions\fR returns information about each ConsoleKit
+session\&.  Users can specify which properties to display via the
+-\fB-format\fR option\&.
+.PP
+The following properties can be displayed for each session:
+.SH "OPTIONS"
+.PP
+The following options are supported:
+.TP 20
+\fB-a\fR, \fB--all\fR
+Show all ConsoleKit sessions\&.  If this option is not provided, only open
+sessions are shown\&.
+.TP 20
+\fB-s\fR, \fB--sid=\fR\fIsid\fR
+Show one ConsoleKit session with session id \fIsid\fR\&.  
+.TP 20
+\fB-f\fR, \fB--format=\fR\fIformat\fR
+Display information using the specified \fIformat\fR\&.  The
+\fIformat\fR value is a list of properties to display
+separated by commas\&.
+.TP 20
+\fB-h\fR, \fB--help\fR
+Display detailed usage message\&.
+.TP 20
+\fB-V\fR, \fB--version\fR
+Display the version of the \fBck-list-sessions\fR application\&.
+.SH "EXTENDED DESCRIPTION"
+.SS "ConsoleKit session properties"
+.PP
+For each session, the following session properties are displayed:
+.TP 20
+\fBunix-user\fR
+The user id value associated with the session\&.
+.TP 20
+\fBrealname\fR
+The name of the user associated with the session\&.
+.TP 20
+\fBseat\fR
+The ID for the ConsoleKit Seat associated with the session\&.
+.TP 20
+\fBsession-type\fR
+The ConsoleKit session type\&.  This value is specified by the "Type"
+key in the ConsoleKit session configuration file associated with this session\&. 
+.TP 20
+\fBdisplay-type\fR
+The ConsoleKit display type\&.  This value is specified by the
+"DisplayTemplate" key in the ConsoleKit session configuration file
+associated with this session\&. 
+.TP 20
+\fBopen\fR
+The value is "TRUE" if the session is open, and "FALSE"
+otherwise\&.
+.TP 20
+\fBactive\fR
+The value is "TRUE" if the session is active on the seat to which it
+is attached, and "FALSE" otherwise\&.
+.TP 20
+\fBx11-display\fR
+The value of the X11 DISPLAY environment variable for this session if one is
+present\&.
+.TP 20
+\fBx11-display-device\fR
+The value of the display device that the X11 display for the session is
+connected to\&.  If there is no x11-display set, then this value is undefined\&.
+.TP 20
+\fBdisplay-device\fR
+The display device associated with the session\&.
+.TP 20
+\fBremote-host\fR
+If the session is not local, the value is the host name associated with the
+session\&.  If the session is local, the value is empty\&.
+.TP 20
+\fBis-local\fR
+The value is "TRUE" if the session is local, and "FALSE"
+if remote\&.
+.TP 20
+\fBon-since\fR
+An ISO 8601 date-time string that corresponds to the time the session started\&.
+.TP 20
+\fBlogin-session-id\fR
+The value of the login session ID that the underlying system uses to enforce
+session boundaries\&. If there is no login session ID set then this value is an
+empty string\&.
+.TP 20
+\fBidle-since-hint\fR
+An ISO 8601 date-time string that corresponds to the time of the last change of
+the idle-hint\&.  This is a hint used to indicate that the session may be idle\&.
+For sessions with a x11-display set (ie\&. graphical sessions), it is up to each
+session to delegate the responsibility for updating this value\&. Typically, the
+screensaver will set this\&.
+.sp
+However, for non-graphical sessions with a display-device set the Session
+object itself will periodically update this value based on the activity
+detected on the display-device itself\&.
+.sp
+This should not be considered authoritative\&. 
+.SH "EXAMPLES"
+.PP
+\fBExample 1: Show running sessions\&.\fR
+.PP
+.PP
+.nf
+example% \fBck-list-sessions\fR
+.fi
+.PP
+This command would generate output like the following for each session:
+.PP
+.nf
+SessionSeat1Local:
+        unix-user = \&'50\&'
+        realname = \&'GDM Reserved UID\&'
+        seat = \&'Seat1\&'
+        session-type = \&'LoginWindow\&'
+        display-type = \&'Local\&'
+        open = \&'TRUE\&'
+        active = \&'TRUE\&'
+        x11-display = \&':0\&'
+        x11-display-device = \&'/dev/console\&'
+        display-device = \&'/dev/console\&'
+        remote-host-name = \&'\&'
+        is-local = \&'TRUE\&'
+        on-since = \&'2009-08-11T06:46:42\&.941134Z\&'
+        login-session-id = \&'\&'
+        idle-since-hint = \&'\&'
+.fi
+.PP
+\fBExample 2: Show only the session-id, unix-user, and display-type properties\&.\fR
+.PP
+.nf
+example% \fBck-list-sessions -\fB-format="session-id,unix-user,display-type"\fR\fR
+.fi
+.PP
+This command would generate output like the following for each session:
+.PP
+.nf
+SessionSeat1Local       50      Local
+.fi
+.SH "FILES"
+.PP
+The following files are used by this application:
+.TP 20
+.B /usr/bin/ck-list-sessions
+Executable for Show ConsoleKit Session Information\&.
+.TP 20
+.B /etc/ConsoleKit/session\&.d
+ConsoleKit session configuration files\&.
+.SH "SEE ALSO"
+.PP
+\fBck-history\fR(1),
+\fBck-launch-session\fR(1),
+\fBck-seat-tool\fR(8),
+\fBconsole-kit-daemon\fR(8),
+\fBgdm\fR(8),
+\fBattributes\fR(7)
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/files/ck-seat-tool.8	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,166 @@
+.TH ck-seat-tool 8 "12 Sep 2016"
+.SH "NAME"
+ck-seat-tool \- ConsoleKit seat tool
+.SH "SYNOPSIS"
+.PP
+\fBck-seat-tool\fR \fB--add\fR \fB--display-type=\fItype\fR\fR [\fB--seat-id=\fIid\fR\fR] [\fB--session-type=\fItype\fR\fR] [\fB\fIvariable\fR \fIvariable\fR\fR\&...]
+.PP
+\fBck-seat-tool\fR \fB--delete\fR \fB--session-id=\fIid\fR\fR
+.PP
+\fBck-seat-tool\fR [\fB--help\fR] [\fB--version\fR]
+.SH "DESCRIPTION"
+.PP
+\fBck-seat-tool\fR is a utility that causes ConsoleKit to add or delete
+a ConsoleKit session in a dymanic fashion\&.  When adding a session, the
+\fB--display-type\fR option must be specified\&.  When deleting a
+session, the \fB--session-id\fR option must be specified\&.
+.PP
+To use \fBck-seat-tool\fR, it must be run as the same user which is
+running the main ConsoleKit daemon, which is normally the root user\&.  Otherwise
+the request is ignored\&.
+.PP
+When adding a session, the \fB--seat-id\fR option works as follows:
+.sp
+.in +2
+\(bu
+.mk
+.in +3
+.rt
+If \fB--seat-id=\fIid\fR\fR is provided and this
+seat exists, then a new session will be added to that seat\&.
+.sp
+.in -3
+\(bu
+.mk
+.in +3
+.rt
+If \fB--seat-id=\fIid\fR\fR is provided, but
+this seat does not exist, then a new seat with the specified seat\&.
+\fIid\fR is created, and a new session added to that seat\&.
+.sp
+.in -3
+\(bu
+.mk
+.in +3
+.rt
+If \fB--seat-id=\fIid\fR\fR is not given, a new
+seat \fIid\fR (Seat#) will be generated, and a new session
+added to that seat\&. 
+.sp
+.in -3
+.in -2
+.PP
+When adding a session, if session is successfully added, the session ID is
+printed in the standard output\&.
+.PP
+Note that to delete a session which is running on a particular DISPLAY, it
+may be necessary to run the 
+\fBck\-list\-sessions\fR(1)
+command to find the corresponding session ID for a given DISPLAY\&.
+.SH "OPTIONS"
+.PP
+The following options are supported:
+.TP
+\fB-a\fR, \fB--add\fR
+Add the specified session\&.
+.TP
+\fB-d\fR, \fB--delete\fR
+Delete the specified session\&.
+.TP
+\fB--display-type=\fR\fItype\fR
+This option is only available when adding a session\&.  Specifies the display
+\fItype\fR in the ConsoleKit display configuration that
+will be associated with the session\&.
+.TP
+\fB-h\fR, \fB--help\fR
+Display detailed usage message\&.
+.TP
+\fB--seat-id=\fR\fIid\fR
+This option is only available when adding a session\&. Specifies the seat
+\fIid\fR that will be associated with the session\&.
+.TP
+\fB--session-id=\fR\fIid\fR
+This option is only available when deleting a session\&.  Specifies the session
+\fIid\fR associated with session that will be deleted\&.
+.TP
+\fB--session-type=\fR\fItype\fR
+This option is only available when adding a session\&.  Specifies the session
+\fItype\fR that will be associated with the session\&.  The
+default value is "LoginWindow"\&.
+.TP
+\fB-V\fR, \fB--version\fR
+Display the version of the \fBck-seat-tool\fR application\&.
+.SH "OPERANDS"
+.PP
+The following operand is supported only when adding a session:
+.TP
+\fIvariable\fR
+The \fIvariable\fR operand is only available when adding a
+sesssion\&.  The command to run when starting a session is specified in a
+ConsoleKit display configuration file named
+\fB/etc/ConsoleKit/displays\&.d/\fIdisplay_type\fR\&.display\fR,
+where \fIdisplay_type\fR is specified by the
+\fB--display-type\fR option\&.  This file is in standard INI format\&.
+The command is specified by the key "X11/Exec"\&.  For example:
+.sp
+.nf
+.sp
+[X11]
+Exec=/usr/X11/bin/Xorg $display -br -verbose $vt
+.fi
+.sp
+Arguments that start with the "$" sign are variables\&.  The values
+for these variables can be specified with the
+\fIvariable\fR operand\&.  For example, if this value is
+"display=:0 vt=vt9", this would set the "$display"
+argument to ":0" and the "$vt" argument to "vt9"\&.
+.SH "EXAMPLES"
+.PP
+\fBExample 1: To add a session to the next available seat with a display type of
+"Local" and start it on display ":20"\fR
+.PP
+.nf
+example% \fBck-seat-tool -\fBa\fR \fB--display-type=Local\fR display=:20\fR
+.fi
+.PP
+\fBExample 2: To add a session to Seat10 with a session type of
+"LoginWindow", a display type of "Local", and
+start it on display ":20"\fR
+.PP
+.nf
+example% \fBck-seat-tool -\fBa\fR \fB--session-type=LoginWindow\fR \fB--display-type=Local\fR \fB--seat-id=Seat10\fR display=:20\fR
+.fi
+.PP
+\fBExample 3: To remove the session with session ID
+"/org/freedesktop/ConsoleKit/Session2"\fR
+.PP
+.nf
+example% \fBck-seat-tool \fB--d\fR \fB--session-id=/org/freedesktop/ConsoleKit/Session2\fR\fR
+.fi
+.SH "EXIT STATUS"
+.PP
+The following exit values are returned:
+.TP
+.B 0
+Application exited successfully
+.TP
+.B 1
+Application exited with failure
+.SH "FILES"
+.PP
+The following files are used by this application:
+.TP
+.B /usr/sbin/ck-seat-tool
+Executable for ConsoleKit seat tool\&.
+.TP
+.B /etc/ConsoleKit/displays\&.d
+ConsoleKit display configuration files\&.
+.SH "SEE ALSO"
+.PP
+\fBck-history\fR(1),
+\fBck-launch-session\fR(1),
+\fBck-list-sessions\fR(1),
+\fBgdmdynamic\fR(1),
+\fBconsole-kit-daemon\fR(8),
+\fBgdm\fR(8),
+\fBattributes\fR(7)
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/files/console-kit-daemon.8	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,458 @@
+.TH console-kit-daemon 1m "12 Sep 2016"
+.SH "NAME"
+console-kit-daemon \- ConsoleKit daemon
+.SH "SYNOPSIS"
+.PP
+\fBconsole-kit-daemon\fR [\fB--debug\fR] [\fB--help\fR] [\fB--no-daemon\fR] [\fB--timed-exit\fR]
+.SH "DESCRIPTION"
+.PP
+\fBconsole-kit-daemon\fR is a service for defining and tracking users, login
+sessions and seats\&.  It provides interfaces for managing switching sessions
+and session migration when using mechanisms such as Virtual Terminals (VT)\&.
+ConsoleKit provides a number of interfaces to specify what displays are managed
+by the display manager, and how\&.
+.PP
+ConsoleKit maintains a database of which users are logged into the system and
+a history of all user logins\&.  ConsoleKit groups sessions by seats which
+represent a set of hardware (usually a keyboard and mouse)\&.  Other process
+communicate with ConsoleKit via D-Bus\&.
+.PP
+One session leader process is responsible for asking \fBconsole-kit-daemon\fR
+to open a new session\&.  In the typical case, the session leader would be a
+ConsoleKit enabled display manager, such as GDM\&.  This leader makes a
+connection to the D-Bus system bus and asks \fBconsole-kit-daemon\fR to open a
+session when needed\&.
+.PP
+If the operation succeeds, \fBconsole-kit-daemon\fR will return a cookie to the
+session leader\&. The session leader should store this variable in the
+environment as XDG_SESSION_COOKIE so that it may be shared with its child
+processes\&.  The environment variable contains the UUID used to tie processes to
+a session\&.
+.PP
+At this point the session will be registered with ConsoleKit and a particular
+set of information about the session will be stored along with it\&.
+.PP
+The Session will remain open until the Session Leader disconnects from the
+D-Bus system bus\&. The session will be removed from its seat, and deregistered\&.
+.PP
+Various other programs need to know information about running user sessions,
+such as the Fast User Switch Applet and other mechanisms for switching the
+console to use a different VT display\&.  Such programs make use of ConsoleKit
+interfaces to determine if user switching is supported and to manage the
+switching of different sessions on the same seat\&.
+.PP
+On Solaris, the ConsoleKit service is managed by the
+\fBsmf\fR(7)
+service management facility under the service identifier
+\fIsvc:/system/consolekit\fR\&.  On Solaris, it is
+recommended that you use the
+\fBsvcadm\fR(8) utility to start and stop the
+ConsoleKit service\&.
+.PP
+ConsoleKit provides a pam_ck_connector so that non-graphical logins (e\&.g\&.
+telnet, ssh, etc\&.) are registered with ConsoleKit\&.  This functionality works
+if this PAM module is enabled in the
+\fBpam\&.conf\fR(4) configuration\&.  Thus ConsoleKit can be
+used as a utmp/wtmp replacement since it stores a superset of the information
+as in the utmp/wtmp database\&.
+.PP
+The ConsoleKit database is stored in the file
+\fB/var/run/ConsoleKit/database\fR\&.  It stores information about
+active Seats, Sessions, and the current SessionLeader\&.
+.SH "OPTIONS"
+.PP
+The following options are supported:
+.TP
+.B --debug
+Enable debug output\&.
+.TP
+\fB-h\fR, \fB--help\fR
+Display detailed usage message\&.
+.TP
+.B --no-daemon
+Avoid starting \fBconsole-kit-daemon\fR as a daemon\&.  Useful for debugging\&.
+.TP
+.B --timed-exit
+Exit after 30 seconds\&.	Useful for debugging\&.
+.SH "ENVIRONMENT VARIABLES"
+.PP
+See
+\fBenviron\fR(7)
+for descriptions of environment variables\&.
+.TP
+.B DISPLAY
+This environment variable corresponds to the Xserver display value associated
+with the ConsoleKit session\&.
+.TP
+.B XDG_SESSION_COOKIE
+ConsoleKit provides this environment variable to the session leader\&.  The
+session leader is expected to ensure this is set for the session process
+started\&.  It contains a UUID used to tie the processes to the session\&.  This is
+used to support user switching on displays that support it (currently only
+graphical VT displays on the console)\&.
+.PP
+The following environment variables are set when \fBconsole-kit-daemon\fR
+runs the \fBrun-session\&.d\fR and \fBrun-seat\&.d\fR
+scripts\&.  These values correspond to those values returned by the
+\fBck-list-session\fR(1) utility\&.
+.TP
+.B CK_SESSION_SEAT_ID
+The seat ID associated with the session\&.
+.TP
+.B CK_SESSION_SEAT_UID
+The user id associated with the session
+.TP
+.B CK_SESSION_DISPLAY_DEVICE
+The display device associated with the session\&.
+.TP
+.B CK_SESSION_DISPLAY_TYPE
+The display configuration file associated with the session\&.  This is a file
+located in the \fB/etc/ConsoleKit/displays\&.d\fR directory\&.
+.TP
+.B CK_SESSION_X11_DISPLAY_DEVICE
+The value of the display device that the X11 display for the session is
+connected to\&.  If there is no x11-display set, then this value is undefined\&.
+.TP
+.B CK_SESSION_X11_DISPLAY
+The value of the X11 DISPLAY environment variable for this session if one is
+present\&.
+.TP
+.B CK_SESSION_REMOTE_HOST_NAME
+If the session is not local, the value is the host name associated with the
+session\&.  If the session is local, the value is empty\&.
+.TP
+.B CK_SESSION_IS_ACTIVE
+The value is "TRUE" if the session is active on the seat to which it
+is attached, and "FALSE" otherwise\&.
+.TP
+.B CK_SESSION_IS_LOCAL
+The value is "TRUE" if the session is local, and "FALSE"
+if remote\&.
+.SH "EXTENDED DESCRIPTION"
+.SS "ConsoleKit Seat Configuration"
+.PP
+ConsoleKit seat configuration files are located in the
+/etc/ConsoleKit/seats\&.d directory\&.  Each seat
+configuration file ends with the \fB\&.seat\fR suffix\&.  ConsoleKit
+provides a default seat file named \fB00-primary\&.seat\fR\&.
+Additional seat configuration files may be added\&.  These files are in standard
+INI format\&.
+.PP
+The settings below are in
+"group/key=\fIdefault_value\fR" format, and show
+the default values of the \fB00-primary\&.seat\fR file\&.  For
+example, to specify a different "Seat Entry/Name" value, you would
+modify the this file so it contains these lines:
+.PP
+.nf
+[Seat Entry]
+[\&.\&.\&.]
+Name=Customized seat name
+.fi
+.PP
+The following keys are supported for configuring ConsoleKit seats:
+.TP
+\fBSeat Entry/Version=1\&.0\fR
+Version number of the seat file\&.  This specifies the version number of the
+configuration file format used\&.  Currently only the value "1\&.0" is
+supported\&.
+.TP
+\fBSeat Entry/Name=Primary seat\fR
+Name of the seat\&.
+.TP
+\fBSeat Entry/ID=StaticSeat\fR
+Specifies the unique ID of the seat\&.  If the value is NULL, then
+\fBconsole-kit-daemon\fR will provide a value\&.  The ID may only contain the
+ASCII characters [A-Z][a=z][0-9]_"\&.
+.TP
+\fBSeat Entry/Hidden=false\fR
+If this value is set to "false", then ConsoleKit will create this
+seat\&.  Otherwise, the seat will not be created\&.
+.TP
+\fBSeat Entry/Devices\fR
+This value is not currently supported\&.  In the future, it is planned that
+ConsoleKit will provide the ability to manage how device permissions are
+managed, and this key is a placeholder\&.
+.TP
+\fBSeat Entry/Sessions=Local\fR
+List of sessions to start on the seat, separated by the ";"
+character\&.  Each session must be defined in a ConsoleKit session configuration
+file named
+\fB/etc/ConsoleKit/sessions\&.d/\fIsessions\fR\&.session\fR where \fIsessions\fR is the value of this key\&.
+.SS "ConsoleKit Display Configuration"
+.PP
+ConsoleKit display configuration files are located in the
+/etc/ConsoleKit/displays\&.d directory\&.  Each session
+configuration file ends with the \fB\&.display\fR suffix\&.
+Additional seat configuration files may be added\&.  These files are in standard
+INI format\&.
+.PP
+The settings below are in
+"group/key" format, so to specify the "X11/Display"
+value, the file should contain these lines:
+.PP
+.nf
+[X11]
+[\&.\&.\&.]
+Exec=/usr/X11/bin/Xserver $display -br -auth $auth $vt
+.fi
+.PP
+The following keys are supported for configuring ConsoleKit displays:
+.TP
+\fBDisplay/Type\fR
+The type of the display\&.  Currently only the value "X11" is
+supported\&.  This indicates that the display will be managed by an Xserver
+that sends a SIGUSR1 signal to its parent pid when it is ready\&.  This is
+standard for all Xservers, such as the
+\fBXorg\fR(1) Xserver\&.
+.TP
+\fBX11/Exec\fR
+The command to run to launch the session\&.  This command supports variables
+that start with the "$" character, like "$display"\&.
+The values to use for these variables can either be specified in the
+ConsoleKit session configuration file in the "[Local]" section, or
+via the \fBck-seat-tool\fR(1) application\&.
+.sp
+Administrator can customize the X11/Exec command as required\&. For example, to enable xkb and accessibility extensions for Xserver, edit \fB/etc/ConsoleKit/displays\&.d/Local\&.display\fR
+.sp
+.nf
+.sp
+[X11]
+[\&.\&.\&.]
+Exec=/usr/X11/bin/Xserver $display -br -auth $auth $vt +kb +accessx
+.fi
+.SS "ConsoleKit Session Configuration"
+.PP
+ConsoleKit session configuration files are located in the
+/etc/ConsoleKit/sessions\&.d directory\&.  Each session
+configuration file ends with the \fB\&.session\fR suffix\&.
+Additional seat configuration files may be added\&.  These files are in standard
+INI format\&.
+.PP
+The settings below are in
+"group/key" format, so to specify the "Session Entry/Name"
+value, the file should contain these lines:
+.PP
+.nf
+[Session Entry]
+[\&.\&.\&.]
+Name=Customized Session
+.fi
+.PP
+The following keys are supported for configuring ConsoleKit sessions:
+.TP
+\fBSession Entry/Name\fR
+Unique name of the session\&.
+.TP
+\fBSession Entry/Type\fR
+Type of the session
+.TP
+\fBSession Entry/Description\fR
+Description of the session\&.
+.TP
+\fBSession Entry/DisplayTemplate\fR
+This specifies the display type to be used with the session\&.  This corresponds
+to the file
+\fB/etc/ConsoleKit/displays\&.d/\fIdisplay_template\fR\&.display\fR
+where \fIdisplay_template\fR is the value of this key\&.
+.TP
+\fBLocal/\fIvariable\fR\fR
+The ConsoleKit display configuration file associated with the
+"Entry/DisplayTemplate" key specifies the command to run to launch
+the display\&.  This command is defined in the ConsoleKit display configuration
+file in the key "X11/Exec"\&.  This command can include variables that
+begin with the "$" character, such as "$display"\&.  The
+values to be used for these variables can be defined in this section\&.  So if
+the session configuration file contains the value
+"Local/display=:0", this will cause the variable used when launching
+the command to be replaced with the value ":0"\&.
+.SS "ConsoleKit Session Script Interfaces"
+.PP
+The following interfaces are provided so that system administrators can
+configure that certain actions happen when ConsoleKit responds to certain
+events\&.
+.PP
+When a ConsoleKit session is started or removed, then \fBconsole-kit-daemon\fR
+will first run any scripts found in the
+\fB/etc/ConsoleKit/run-session\&.d\fR directory and then run any
+scripts in the
+\fB/usr/lib/ConsoleKit/run-session\&.d\fR directory\&.
+.PP
+When certain seat events, such as "seat_added",
+"seat_removed" or "seat_active_session_changed" occur,
+then \fBconsole-kit-daemon\fR will first run any script in the
+\fB/etc/ConsoleKit/run-seat\&.d\fR directory and  then run any
+scripts in the
+\fB/usr/lib/ConsoleKit/run-seat\&.d\fR directory\&.
+.SS "ConsoleKit System Restart and Stop"
+.PP
+\fBconsole-kit-daemon\fR provides D-Bus interfaces that will restart or stop
+the system\&.  When \fBconsole-kit-daemon\fR receives a D-Bus request to restart
+the system, it will run the
+\fB/usr/lib/ConsoleKit/scripts/ck-system-restart\fR script if
+the user has privilege to do this operation\&.  When \fBconsole-kit-daemon\fR
+receives a D-Bus request to stop the system, it will run the
+\fB/usr/lib/ConsoleKit/scripts/ck-system-stop\fR script if the
+user has privilege to do this operation\&.
+.SH "EXAMPLES"
+.PP
+\fBExample 1: To start the ConsoleKit daemon\fR
+.PP
+.PP
+.nf
+example% \fBconsole-kit-daemon\fR
+.fi
+.PP
+\fBExample 2: To configure ConsoleKit to not start a seat\fR
+.PP
+To disable a seat, the administrator can set Hidden=true in the \&.seat file\&.
+Edit the \fB00-primary\&.seat\fR file as follows to disable
+the default primary seat which normally runs on the system console\&.
+
+For example, disabling the primary seat on the console is useful if the
+administrator wishes to run GDM in headless mode\&. This can be
+useful if the administrator wants GDM to accept XDMCP remote displays
+but the server does not actually have a console\&.
+.PP
+.nf
+[Seat Entry]
+Version=1\&.0
+Name=Primary seat
+ID=StaticSeat1
+Description=start one static local display at :0
+Hidden=true
+Devices=
+Sessions=Local;
+.fi
+.PP
+\fBExample 3: To configure ConsoleKit to start multiple sessions on a single seat\fR
+.PP
+To start two local displays: DISPLAY ":0" on vt7 and DISPLAY
+":1" on "vt8",
+edit the \fB00-primary\&.seat\fR file as follows:
+.PP
+.nf
+[Seat Entry]
+Version=1\&.0
+Name=Primary seat
+Description=start static displays :0 on vt7 and :1 on vt8
+Hidden=false
+Devices=
+Sessions=Local;Local2;
+.fi
+.PP
+Then, in addition to the original
+\fB/etc/ConsoleKit/sessions\&.d/Local\&.session\fR file, add the
+following \fB/etc/ConsoleKit/sessions\&.d/Local2\&.session\fR file:
+.PP
+.nf
+[Session Entry]
+Name=Local
+Type=LoginWindow
+Description=Local Login Screen
+DisplayTemplate=Local
+
+[Local]
+display=:1
+vt=vt8
+.fi
+.PP
+\fBExample 4: To configure ConsoleKit to start multiple seat\fR
+.PP
+To start two seats: a local session on DISPLAY ":0" using
+"vt7" and another seat using a VNC session on DISPLAY ":64",
+add a file \fB/etc/ConsoleKit/seats\&.d/01-vnc\&.seat\fR as
+follows:
+.PP
+.nf
+[Seat Entry]
+Version=1\&.0
+Name=VNC seat
+Description=start one VNC display on :64
+Hidden=false
+Devices=
+Sessions=LocalVNC;
+.fi
+.PP
+Add the
+\fB/etc/ConsoleKit/sessions\&.d/LocalVNC\&.session\fR file as
+follows:
+.PP
+.nf
+[Session Entry]
+Name=LocalVNC
+Type=LoginWindow
+Description=Connect to local VNC server running on same machine
+DisplayTemplate=LocalVNC
+
+[LocalVNC]
+display=:64
+.fi
+.PP
+Finally, add the
+\fB/etc/ConsoleKit/displays\&.d/LocalVNC\&.display\fR file as
+follows:
+.PP
+.nf
+[Display]
+Type=X11
+
+[X11]
+Exec=/usr/X11/bin/Xvnc $display -auth $auth -query localhost
+.fi
+.SH "FILES"
+.PP
+The following files are used by this application:
+.TP
+.B /usr/sbin/console-kit-daemon
+Executable for the ConsoleKit daemon\&.
+.TP
+.B /usr/lib/ConsoleKit/run-seat\&.d
+Any scripts in this directory are run when a ConsoleKit seat event happens\&.
+.TP
+.B /usr/lib/ConsoleKit/run-session\&.d
+Any scripts in this directory are run when a ConsoleKit session event happens\&.
+.TP
+.B /usr/lib/ConsoleKit/scripts/ck-system-restart
+Script to run when ConsoleKit receives a D-Bus request to restart the system\&.
+.TP
+.B /usr/lib/ConsoleKit/scripts/ck-system-stop
+Script to run when ConsoleKit receives a D-Bus request to stop the system\&.
+.TP
+.B /etc/ConsoleKit/seats\&.d
+ConsoleKit seat configuration files\&.
+.TP
+.B /etc/ConsoleKit/session\&.d
+ConsoleKit session configuration files\&.
+.TP
+.B /etc/ConsoleKit/run-seat\&.d
+Any scripts in this directory are run when a ConsoleKit seat event happens\&.
+.TP
+.B /etc/ConsoleKit/run-session\&.d
+Any scripts in this directory are run when a ConsoleKit seat event happens\&.
+.TP
+.B /var/run/ConsoleKit/database
+ConsoleKit database\&.
+.TP
+.B /var/log/ConsoleKit/history
+ConsoleKit history database\&.
+.SH "SEE ALSO"
+.PP
+More information can be found at:
+.PP
+\fBhttp://www\&.freedesktop\&.org/wiki/Software/ConsoleKit\fR
+.PP
+\fBck-history\fR(1),
+\fBck-launch-session\fR(1),
+\fBck-list-sessions\fR(1),
+\fBdbus-daemon\fR(1),
+\fBck-seat-tool\fR(8),
+\fBgdm\fR(8),
+\fBsvcadm\fR(8),
+\fBattributes\fR(7),
+\fBenviron\fR(7),
+\fBsmf\fR(7)
+.SH "NOTES"
+.PP
+Some of the documentation in this manpage is from the ConsoleKit documentation
+written by William Jon McCann\&.
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/files/consolekit.xml	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,66 @@
+<?xml version="1.0"?>
+<!DOCTYPE service_bundle SYSTEM "/usr/share/lib/xml/dtd/service_bundle.dtd.1">
+<!--
+    Copyright 2009, 2013, Oracle and/or its affiliates. All rights reserved.
+    Use is subject to license terms.
+-->
+
+<service_bundle type='manifest' name='SUNWconsolekit:consolekit'>
+
+<service
+    name='system/consolekit'
+    type='service'
+    version='1'>
+
+	<dependency
+	    name='filesystem'
+	    grouping='require_all'
+	    restart_on='none'
+	    type='service'>
+		<service_fmri value='svc:/system/filesystem/local'/>
+	</dependency>
+
+        <dependency
+            name='dbus'
+            type='service'
+            grouping='require_all'
+            restart_on='none'>
+                <service_fmri value='svc:/system/dbus' />
+        </dependency>
+
+	<exec_method
+	    type='method'
+	    name='start'
+	    exec='/lib/svc/method/svc-consolekit start'
+	    timeout_seconds='60' />
+
+	<exec_method
+	    type='method'
+	    name='stop'
+	    exec=':kill'
+	    timeout_seconds='60' />
+
+	<!-- these are passed to gdm in the method script -->
+	<property_group name='consolekit' type='application'>
+		<propval name='args' type='astring' value='' />
+		<propval name='sessions' type='astring' value='Local' />
+	</property_group>
+
+	<instance name='default' enabled='true' />
+
+	<stability value='Unstable' />
+
+	<template>
+		<common_name>
+			<loctext xml:lang='C'>
+				ConsoleKit
+			</loctext>
+		</common_name>
+		<documentation>
+			<manpage title='console-kit-daemon' section='1m'
+				manpath='/usr/share/man' />
+		</documentation>
+	</template>
+</service>
+
+</service_bundle>
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/files/svc-consolekit	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,45 @@
+#!/sbin/sh
+#
+# Copyright 2011, 2016, Oracle and/or its affiliates. All rights reserved.
+#
+
+. /lib/svc/share/smf_include.sh
+
+case "$1" in
+'start')
+	FMRI=svc:/system/consolekit
+
+	arg=`eval "echo \`svcprop -p consolekit/args $FMRI\`"`
+
+	SEATFILE=/etc/ConsoleKit/seats.d/00-primary.seat
+
+	rep=`eval "echo \`svcprop -p consolekit/sessions $FMRI\`"`
+
+	curline=`sed -n "/Sessions=/p" $SEATFILE`
+	cur=`expr $curline : "Sessions=\(.*\);"`
+
+	if [[ $cur != $rep ]];  then
+		/usr/bin/ex $SEATFILE << EOF
+/$curline
+s/$curline/Sessions=$rep;/
+w
+q
+EOF
+	fi
+		
+	/usr/sbin/console-kit-daemon $arg
+
+	rc=$?
+	if [ $rc -ne 0 ]; then
+		echo "$0: consolekit failed with $rc"
+		exit $SMF_EXIT_ERR_FATAL 
+	fi
+	;;
+
+*)
+	echo "Usage: $0 { start }"
+	exit $SMF_EXIT_ERR_FATAL
+	;;
+esac
+
+exit $SMF_EXIT_OK
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/pam-ConsoleKit.p5m	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,42 @@
+#
+# CDDL HEADER START
+#
+# The contents of this file are subject to the terms of the
+# Common Development and Distribution License (the "License").
+# You may not use this file except in compliance with the License.
+#
+# You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+# or http://www.opensolaris.org/os/licensing.
+# See the License for the specific language governing permissions
+# and limitations under the License.
+#
+# When distributing Covered Code, include this CDDL HEADER in each
+# file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+# If applicable, add the following below this CDDL HEADER, with the
+# fields enclosed by brackets "[]" replaced with your own identifying
+# information: Portions Copyright [yyyy] [name of copyright owner]
+#
+# CDDL HEADER END
+#
+
+#
+# Copyright (c) 2016, Oracle and/or its affiliates. All rights reserved.
+#
+
+<transform file path=usr.*/man/.+ -> default mangler.man.stability uncommitted>
+set name=pkg.fmri \
+    value=pkg:/library/security/pam/module/pam-consolekit@$(IPS_COMPONENT_VERSION),$(BUILD_VERSION)
+set name=pkg.summary \
+    value="Framework for tracking users, login sessions and seats"
+set name=com.oracle.info.description value="ConsoleKit - PAM module"
+set name=com.oracle.info.tpno value=$(TPNO)
+set name=info.classification \
+    value="org.opensolaris.category.2008:Desktop (GNOME)/Sessions"
+set name=info.source-url value=$(COMPONENT_ARCHIVE_URL)
+set name=info.upstream-url value=$(COMPONENT_PROJECT_URL)
+set name=org.opensolaris.arc-caseid value=LSARC/2009/432
+set name=org.opensolaris.consolidation value=$(CONSOLIDATION)
+file path=usr/lib/security/$(MACH64)/pam_ck_connector.so
+file path=usr/lib/security/pam_ck_connector.so
+file path=usr/share/man/man8/pam_ck_connector.8
+license ConsoleKit.license license="GPLv2+, BSD, MIT"
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-01-ck-dynamic.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,5594 @@
+Patch migrated from Desktop, where it was listed as:
+# date:2008-12-30 owner:yippi type:bug bugzilla:19333
+https://bugzilla.freedesktop.org/show_bug.cgi?id=19333
+
+diff --git a/configure.ac b/configure.ac
+index 117d788..2ff6020 100644
+--- a/configure.ac
++++ b/configure.ac
+@@ -203,6 +203,18 @@ AM_CONDITIONAL(CK_COMPILE_SOLARIS, test x$CK_BACKEND = xsolaris, [Compiling for
+ AC_SUBST(CK_BACKEND)
+ 
+ dnl ---------------------------------------------------------------------------
++dnl Check for X11 DIR
++dnl ---------------------------------------------------------------------------
++
++X11_DIR=`$PKG_CONFIG --variable=bindir xorg-server 2>/dev/null`
++if test "x$X11_DIR" = x; then
++    AC_PATH_PROGS([XSERVER], [Xorg X],,[$PATH:/usr/X11/bin:/usr/bin])
++    test "x$XSERVER" != x && X11_DIR=`dirname "$XSERVER"`
++fi
++test "x$X11_DIR" = x && X11_DIR=$bindir
++AC_SUBST([X11_DIR])
++
++dnl ---------------------------------------------------------------------------
+ dnl Check for PAM
+ dnl ---------------------------------------------------------------------------
+ 
+@@ -303,6 +315,14 @@ if test "x$enable_inotify" = "xyes" ; then
+ fi
+ 
+ dnl ---------------------------------------------------------------------------
++dnl check for strverscmp
++dnl ---------------------------------------------------------------------------
++have_strverscmp=no
++AC_CHECK_FUNCS(strverscmp, [have_strverscmp=yes], [])
++
++AM_CONDITIONAL(USE_SELF_STRVERSCMP, test "x$have_strverscmp" = "xno", [Define if we do not have strverscmp])
++
++dnl ---------------------------------------------------------------------------
+ dnl check for RBAC
+ dnl ---------------------------------------------------------------------------
+ 
+@@ -401,6 +421,8 @@ tools/linux/Makefile
+ tools/freebsd/Makefile
+ tools/solaris/Makefile
+ data/Makefile
++data/displays.d/Makefile
++data/sessions.d/Makefile
+ doc/Makefile
+ doc/dbus/ConsoleKit.xml
+ doc/dbus/Makefile
+diff --git a/data/00-primary.seat b/data/00-primary.seat
+index 6e61db4..0632382 100644
+--- a/data/00-primary.seat
++++ b/data/00-primary.seat
+@@ -1,5 +1,26 @@
+ [Seat Entry]
+ Version=1.0
+ Name=Primary seat
++# Specified Seat ID, if this value is NULL, ConsoleKit will decide one.
++# The ID only contain the ASICC characters "[A-Z][a-z][0-9]_" 
++ID=StaticSeat1
++Description=start one static local display at :0
++
++# Indicate whether to create this seat or not. If it is set true, then CK will
++# not create this seat. Default value is false.
+ Hidden=false
+-Devices=
+\ No newline at end of file
++
++# Indicate input/output devices including keyboard-pointer-video
++# card-monitor-sound-usb devices,
++# This key will not implemented now, it might need be divided into
++# several keys in the future:
++# Pointer=
++# Monitor=
++# VideoCard=
++# Monitor=
++# UsbHub=
++Devices=
++
++# List of sessions to start on the seat, separated by ';'
++# Each session is defined in sessions.d/
++Sessions=Local;
+diff --git a/data/ConsoleKit.conf b/data/ConsoleKit.conf
+index 948f95f..8cf490a 100644
+--- a/data/ConsoleKit.conf
++++ b/data/ConsoleKit.conf
+@@ -44,6 +44,9 @@
+            send_member="CloseSession"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Manager"
++           send_member="GetUnmanagedSeats"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Manager"
+            send_member="GetSeats"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Manager"
+@@ -69,6 +72,18 @@
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Manager"
+            send_member="GetSystemIdleSinceHint"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Manager"
++           send_member="AddSeat"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Manager"
++           send_member="RemoveSeat"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Manager"
++           send_member="AddSession"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Manager"
++           send_member="RemoveSession"/>
+ 
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Seat"
+@@ -88,6 +103,9 @@
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Seat"
+            send_member="ActivateSession"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Seat"
++           send_member="ManageSeat"/>
+ 
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Session"
+@@ -103,6 +121,9 @@
+            send_member="GetSessionType"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Session"
++           send_member="GetDisplayType"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Session"
+            send_member="GetUser"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Session"
+@@ -127,6 +148,12 @@
+            send_member="IsLocal"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Session"
++           send_member="IsDynamic"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Session"
++           send_member="IsOpen"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Session"
+            send_member="GetCreationTime"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Session"
+@@ -136,12 +163,11 @@
+            send_member="GetIdleHint"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Session"
+-           send_member="SetIdleHint"/>
+-    <allow send_destination="org.freedesktop.ConsoleKit"
+-           send_interface="org.freedesktop.ConsoleKit.Session"
+            send_member="GetIdleSinceHint"/>
+     <allow send_interface="org.freedesktop.ConsoleKit.Session"
+            send_member="SetIdleHint"/>
++    <allow send_interface="org.freedesktop.ConsoleKit.Session"
++           send_member="SetRemoveOnClose"/>
+   </policy>
+ 
+ </busconfig>
+diff --git a/data/Makefile.am b/data/Makefile.am
+index 041b431..2054e96 100644
+--- a/data/Makefile.am
++++ b/data/Makefile.am
+@@ -1,5 +1,10 @@
+ NULL =
+ 
++SUBDIRS = \
++	displays.d	\
++	sessions.d	\
++        $(NULL)
++
+ dbusconfdir = $(DBUS_SYS_DIR)
+ dbusconf_DATA = ConsoleKit.conf
+ 
+diff --git a/data/displays.d/Headless.display.in b/data/displays.d/Headless.display.in
+new file mode 100644
+index 0000000..754d2bf
+--- /dev/null
++++ b/data/displays.d/Headless.display.in
+@@ -0,0 +1,5 @@
++[Display]
++Type=X11
++
++[X11]
++Exec=@X11_DIR@/Xvfb $display -auth $auth
+diff --git a/data/displays.d/Local.display.in b/data/displays.d/Local.display.in
+new file mode 100644
+index 0000000..b845a7b
+--- /dev/null
++++ b/data/displays.d/Local.display.in
+@@ -0,0 +1,5 @@
++[Display]
++Type=X11
++
++[X11]
++Exec=@X11_DIR@/Xorg $display -br -verbose -auth $auth -nolisten tcp $vt
+diff --git a/data/displays.d/LocalVNC.display.in b/data/displays.d/LocalVNC.display.in
+new file mode 100644
+index 0000000..6ad336b
+--- /dev/null
++++ b/data/displays.d/LocalVNC.display.in
+@@ -0,0 +1,5 @@
++[Display]
++Type=X11
++
++[X11]
++Exec=@X11_DIR@/Xvnc $display -auth $auth -query localhost
+diff --git a/data/displays.d/Makefile.am b/data/displays.d/Makefile.am
+new file mode 100644
+index 0000000..1fab1d2
+--- /dev/null
++++ b/data/displays.d/Makefile.am
+@@ -0,0 +1,29 @@
++NULL =
++
++displaydir = $(sysconfdir)/ConsoleKit/displays.d
++display_in_files = \
++	Local.display.in \
++	RemoteMachine.display.in \
++	LocalVNC.display.in \
++	Headless.display.in
++
++display_DATA = $(display_in_files:.display.in=.display)
++
++Local.display: Local.display.in Makefile
++	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
++RemoteMachine.display: RemoteMachine.display.in Makefile
++	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
++LocalVNC.display: LocalVNC.display.in Makefile
++	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
++Headless.display: Headless.display.in Makefile
++	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
++
++EXTRA_DIST =						\
++	$(display_in_files)				\
++	$(NULL)
++
++MAINTAINERCLEANFILES =			\
++	*~				\
++	Makefile.in
++
++CLEANFILES = $(display_DATA)
+diff --git a/data/displays.d/RemoteMachine.display.in b/data/displays.d/RemoteMachine.display.in
+new file mode 100644
+index 0000000..7c69451
+--- /dev/null
++++ b/data/displays.d/RemoteMachine.display.in
+@@ -0,0 +1,5 @@
++[Display]
++Type=X11
++
++[X11]
++Exec=@X11_DIR@/Xorg $display -br -verbose -auth $auth -indirect $vt
+diff --git a/data/sessions.d/Headless.session b/data/sessions.d/Headless.session
+new file mode 100644
+index 0000000..d376af9
+--- /dev/null
++++ b/data/sessions.d/Headless.session
+@@ -0,0 +1,8 @@
++[Session Entry]
++Name=Headless
++Type=LoginWindow
++Description=Login Window running on headless display
++DisplayTemplate=Headless
++
++[Headless]
++display=:32
+diff --git a/data/sessions.d/Local.session b/data/sessions.d/Local.session
+new file mode 100644
+index 0000000..9d3b975
+--- /dev/null
++++ b/data/sessions.d/Local.session
+@@ -0,0 +1,9 @@
++[Session Entry]
++Name=Local
++Type=LoginWindow
++Description=Local Login Screen
++DisplayTemplate=Local
++
++[Local]
++display=:0
++vt=vt7
+diff --git a/data/sessions.d/LocalVNC.session b/data/sessions.d/LocalVNC.session
+new file mode 100644
+index 0000000..c05802f
+--- /dev/null
++++ b/data/sessions.d/LocalVNC.session
+@@ -0,0 +1,8 @@
++[Session Entry]
++Name=LocalVNC
++Type=LoginWindow
++Description=Connect to local VNC server running on same machine
++DisplayTemplate=LocalVNC
++
++[LocalVNC]
++display=:64
+diff --git a/data/sessions.d/Makefile.am b/data/sessions.d/Makefile.am
+new file mode 100644
+index 0000000..f17ffdc
+--- /dev/null
++++ b/data/sessions.d/Makefile.am
+@@ -0,0 +1,16 @@
++NULL =
++
++sessiondir = $(sysconfdir)/ConsoleKit/sessions.d
++session_DATA = \
++	Headless.session		\
++	Local.session			\
++	LocalVNC.session		\
++	Remote.session
++
++EXTRA_DIST =				\
++	$(session_DATA)			\
++	$(NULL)
++
++MAINTAINERCLEANFILES =			\
++	*~				\
++	Makefile.in
+diff --git a/data/sessions.d/Remote.session b/data/sessions.d/Remote.session
+new file mode 100644
+index 0000000..e88f975
+--- /dev/null
++++ b/data/sessions.d/Remote.session
+@@ -0,0 +1,9 @@
++[Session Entry]
++Name=Remote Chooser
++Type=Remote
++Description=Connect to chooser on nearby remote machine
++DisplayTemplate=RemoteMachine
++
++[RemoteMachine]
++display=:96
++vt=vt10
+diff --git a/doc/dbus/ck-terms.xml b/doc/dbus/ck-terms.xml
+index d3d544d..1b43ca6 100644
+--- a/doc/dbus/ck-terms.xml
++++ b/doc/dbus/ck-terms.xml
+@@ -64,4 +64,11 @@ True, hardware, multi-seat capabilities will be added in a later release.
+     </para>
+   </sect1>
+ 
++  <sect1>
++    <title>Seat manager</title>
++    <para>
++The seat manager is the process responsible for starting and stopping sessions on a seat.
++    </para>
++  </sect1>
++
+ </chapter>
+diff --git a/libck-connector/ck-connector.c b/libck-connector/ck-connector.c
+index 7f6f87f..87a7d4a 100644
+--- a/libck-connector/ck-connector.c
++++ b/libck-connector/ck-connector.c
+@@ -76,8 +76,11 @@ static struct {
+         { "display-device",     DBUS_TYPE_STRING },
+         { "x11-display-device", DBUS_TYPE_STRING },
+         { "x11-display",        DBUS_TYPE_STRING },
++        { "seat-id",            DBUS_TYPE_STRING },
++        { "session",            DBUS_TYPE_STRING },
+         { "remote-host-name",   DBUS_TYPE_STRING },
+         { "session-type",       DBUS_TYPE_STRING },
++        { "display-type",       DBUS_TYPE_STRING },
+         { "is-local",           DBUS_TYPE_BOOLEAN },
+         { "unix-user",          DBUS_TYPE_INT32 },
+ };
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 6ab05c8..97a59ef 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -107,6 +107,8 @@ console_kit_daemon_SOURCES =	\
+ 	ck-file-monitor.h	\
+ 	ck-job.h		\
+ 	ck-job.c		\
++	ck-display-template.h	\
++	ck-display-template.c	\
+ 	ck-seat.h		\
+ 	ck-seat.c		\
+ 	ck-session-leader.h	\
+@@ -122,6 +124,13 @@ console_kit_daemon_SOURCES =	\
+ 	$(BUILT_SOURCES)	\
+ 	$(NULL)
+ 
++if USE_SELF_STRVERSCMP
++console_kit_daemon_SOURCES +=	\
++	strverscmp.c		\
++	strverscmp.h		\
++	$(NULL)
++endif
++
+ if ENABLE_INOTIFY
+ FILE_MONITOR_BACKEND = ck-file-monitor-inotify.c
+ else
+diff --git a/src/ck-display-template.c b/src/ck-display-template.c
+new file mode 100644
+index 0000000..9206103
+--- /dev/null
++++ b/src/ck-display-template.c
+@@ -0,0 +1,341 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Authors: [email protected], Ray Strode <[email protected]>
++ * Copyright (C) 2009 Sun Microsystems, Inc.
++ *                    Red Hat, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#include "config.h"
++
++#include <string.h>
++#include <glib.h>
++#include <glib-object.h>
++
++#include "ck-display-template.h"
++
++#define CK_DISPLAY_TEMPLATE_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplatePrivate))
++
++#define CK_DISPLAY_TEMPLATES_DIR     SYSCONFDIR "/ConsoleKit/displays.d"
++
++struct CkDisplayTemplatePrivate
++{
++        char            *name;
++        char            *type;
++        GHashTable      *parameters;
++};
++
++enum {
++        PROP_0,
++        PROP_NAME,
++        PROP_TYPE,
++        PROP_PARAMETERS,
++};
++
++static void     ck_display_template_class_init  (CkDisplayTemplateClass *klass);
++static void     ck_display_template_init        (CkDisplayTemplate      *display);
++static void     ck_display_template_finalize    (GObject            *object);
++static gboolean ck_display_template_load        (CkDisplayTemplate      *display);
++
++static GHashTable *ck_display_templates;
++
++G_DEFINE_TYPE (CkDisplayTemplate, ck_display_template, G_TYPE_OBJECT)
++
++static void
++_ck_display_template_set_name (CkDisplayTemplate  *display,
++                               const char     *name)
++{
++        g_free (display->priv->name);
++        display->priv->name = g_strdup (name);
++}
++
++static void
++_ck_display_template_set_type_string (CkDisplayTemplate  *display,
++                                      const char     *type)
++{
++        g_free (display->priv->type);
++        display->priv->type = g_strdup (type);
++}
++
++static void
++_ck_display_template_set_parameters (CkDisplayTemplate  *display,
++                                     GHashTable     *parameters)
++{
++        if (display->priv->parameters != NULL) {
++                g_hash_table_unref (display->priv->parameters);
++        }
++
++        if (parameters == NULL) {
++                display->priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
++                                                                   (GDestroyNotify) g_free,
++                                                                   (GDestroyNotify) g_free);
++        } else {
++                display->priv->parameters = g_hash_table_ref (parameters);
++        }
++}
++
++static void
++ck_display_template_set_property (GObject      *object,
++                                  guint         prop_id,
++                                  const GValue *value,
++                                  GParamSpec   *pspec)
++{
++        CkDisplayTemplate *self;
++
++        self = CK_DISPLAY_TEMPLATE (object);
++
++        switch (prop_id) {
++        case PROP_NAME:
++                _ck_display_template_set_name (self, g_value_get_string (value));
++                break;
++        case PROP_TYPE:
++                _ck_display_template_set_type_string (self, g_value_get_string (value));
++                break;
++        case PROP_PARAMETERS:
++                _ck_display_template_set_parameters (self, g_value_get_boxed (value));
++                break;
++        default:
++                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++                break;
++        }
++}
++
++static void
++ck_display_template_get_property (GObject    *object,
++                                  guint       prop_id,
++                                  GValue     *value,
++                                  GParamSpec *pspec)
++{
++        CkDisplayTemplate *self;
++
++        self = CK_DISPLAY_TEMPLATE (object);
++
++        switch (prop_id) {
++        case PROP_NAME:
++                g_value_set_string (value, self->priv->name);
++                break;
++        case PROP_TYPE:
++                g_value_set_string (value, self->priv->type);
++                break;
++        case PROP_PARAMETERS:
++                g_value_set_boxed (value, self->priv->parameters);
++                break;
++        default:
++                G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
++                break;
++        }
++}
++
++static void
++ck_display_template_class_init (CkDisplayTemplateClass *klass)
++{
++        GObjectClass   *object_class = G_OBJECT_CLASS (klass);
++
++        object_class->get_property = ck_display_template_get_property;
++        object_class->set_property = ck_display_template_set_property;
++        object_class->finalize = ck_display_template_finalize;
++
++        g_object_class_install_property (object_class,
++                                         PROP_NAME,
++                                         g_param_spec_string ("name",
++                                                              "display type name",
++                                                              "display type name",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
++        g_object_class_install_property (object_class,
++                                         PROP_TYPE,
++                                         g_param_spec_string ("type",
++                                                              "type",
++                                                              "Type",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++        g_object_class_install_property (object_class,
++                                         PROP_PARAMETERS,
++                                         g_param_spec_boxed ("parameters",
++                                                              "Parameters",
++                                                              "Parameters",
++                                                              G_TYPE_HASH_TABLE,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++        g_type_class_add_private (klass, sizeof (CkDisplayTemplatePrivate));
++}
++
++static void
++ck_display_template_init (CkDisplayTemplate *display)
++{
++        display->priv = CK_DISPLAY_TEMPLATE_GET_PRIVATE (display);
++
++        display->priv->name = NULL;
++        display->priv->type = NULL;
++        display->priv->parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
++                                                           (GDestroyNotify) g_free,
++                                                           (GDestroyNotify) g_free);
++}
++
++static void
++ck_display_template_finalize (GObject *object)
++{
++        CkDisplayTemplate *display;
++
++        g_return_if_fail (object != NULL);
++        g_return_if_fail (CK_IS_DISPLAY_TEMPLATE (object));
++
++        display = CK_DISPLAY_TEMPLATE (object);
++
++        g_return_if_fail (display->priv != NULL);
++
++        g_free (display->priv->name);
++        g_free (display->priv->type);
++        g_hash_table_unref (display->priv->parameters);
++
++        G_OBJECT_CLASS (ck_display_template_parent_class)->finalize (object);
++}
++
++static gboolean
++ck_display_template_load (CkDisplayTemplate *display)
++{
++        GKeyFile   *key_file;
++        const char *name;
++        char       *group;
++        char       *filename;
++        gboolean    hidden;
++        char       *type;
++        gboolean    res;
++        GError     *error;
++        char      **type_keys;
++        GHashTable *parameters;
++
++        name = ck_display_template_get_name (display);
++
++        g_return_val_if_fail (name && !g_str_equal (name, ""), FALSE);
++
++        filename = g_strdup_printf ("%s/%s.display", CK_DISPLAY_TEMPLATES_DIR, name);
++
++        key_file = g_key_file_new ();
++
++        error = NULL;
++        res = g_key_file_load_from_file (key_file,
++                                         filename,
++                                         G_KEY_FILE_NONE,
++                                         &error);
++        if (! res) {
++                g_warning ("Unable to load display from file %s: %s", filename, error->message);
++                g_error_free (error);
++                return FALSE;
++        }
++        g_free (filename);
++
++        group = g_key_file_get_start_group (key_file);
++
++        if (group == NULL || strcmp (group, "Display") != 0) {
++                g_warning ("Not a display type file: %s", filename);
++                g_free (group);
++                g_key_file_free (key_file);
++                return FALSE;
++        }
++
++        hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL);
++
++        type = g_key_file_get_string (key_file, group, "Type", NULL);
++
++        if (type == NULL) {
++                g_warning ("Unable to read type from display file");
++                g_free (group);
++                g_key_file_free (key_file);
++                return FALSE;
++        }
++
++        display->priv->type = type;
++
++        parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
++                                            (GDestroyNotify) g_free,
++                                            (GDestroyNotify) g_free);
++
++        type_keys = g_key_file_get_keys (key_file, type, NULL, NULL);
++
++        if (type_keys != NULL) {
++                int        i;
++                for (i = 0; type_keys[i] != NULL; i++) {
++                        char   *string;
++
++                        string = g_key_file_get_string (key_file, type, type_keys[i], NULL);
++                        g_hash_table_insert (parameters, g_strdup (type_keys[i]), string);
++                }
++                g_strfreev (type_keys);
++        }
++
++        _ck_display_template_set_parameters (display, parameters);
++        g_hash_table_unref (parameters);
++
++        g_free (group);
++        g_key_file_free (key_file);
++        return TRUE;
++}
++
++CkDisplayTemplate *
++ck_display_template_get_from_name (const char *name)
++{
++        CkDisplayTemplate *display_template;
++
++        if (ck_display_templates == NULL) {
++                ck_display_templates = g_hash_table_new_full (g_str_hash, g_str_equal,
++                                                          (GDestroyNotify) g_free,
++                                                          (GDestroyNotify) g_object_unref);
++        }
++
++        display_template = g_hash_table_lookup (ck_display_templates, name);
++
++        if (display_template == NULL) {
++                GObject *object;
++
++                object = g_object_new (CK_TYPE_DISPLAY_TEMPLATE,
++                                       "name", name,
++                                       NULL);
++
++                if (!ck_display_template_load (CK_DISPLAY_TEMPLATE (object))) {
++                        g_object_unref (object);
++                        return NULL;
++                }
++
++                g_hash_table_insert (ck_display_templates, g_strdup (name), object);
++                display_template = CK_DISPLAY_TEMPLATE (object);
++        }
++
++        return g_object_ref (display_template);
++}
++
++G_CONST_RETURN char*
++ck_display_template_get_name (CkDisplayTemplate   *display)
++{
++        g_return_val_if_fail (CK_IS_DISPLAY_TEMPLATE (display), NULL);
++
++        return display->priv->name;
++}
++
++G_CONST_RETURN char *
++ck_display_template_get_type_string (CkDisplayTemplate  *display)
++{
++        return display->priv->type;
++}
++
++GHashTable *
++ck_display_template_get_parameters (CkDisplayTemplate   *display)
++{
++        g_return_val_if_fail (CK_IS_DISPLAY_TEMPLATE (display), NULL);
++
++        return g_hash_table_ref (display->priv->parameters);
++}
++
+diff --git a/src/ck-display-template.h b/src/ck-display-template.h
+new file mode 100644
+index 0000000..fa74e67
+--- /dev/null
++++ b/src/ck-display-template.h
+@@ -0,0 +1,57 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Authors: [email protected]
++ * Copyright (C) 2009 Sun Microsystems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
++ *
++ */
++
++#ifndef __CK_DISPLAY_TEMPLATE_H
++#define __CK_DISPLAY_TEMPLATE_H
++
++#include <glib-object.h>
++
++G_BEGIN_DECLS
++
++#define CK_TYPE_DISPLAY_TEMPLATE         (ck_display_template_get_type ())
++#define CK_DISPLAY_TEMPLATE(o)           (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplate))
++#define CK_DISPLAY_TEMPLATE_CLASS(k)     (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplateClass))
++#define CK_IS_DISPLAY_TEMPLATE(o)        (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_DISPLAY_TEMPLATE))
++#define CK_IS_DISPLAY_TEMPLATE_CLASS(k)  (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_DISPLAY_TEMPLATE))
++#define CK_DISPLAY_TEMPLATE_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_DISPLAY_TEMPLATE, CkDisplayTemplateClass))
++
++typedef struct CkDisplayTemplatePrivate CkDisplayTemplatePrivate;
++
++typedef struct
++{
++        GObject        parent;
++        CkDisplayTemplatePrivate *priv;
++} CkDisplayTemplate;
++
++typedef struct
++{
++        GObjectClass   parent_class;
++} CkDisplayTemplateClass;
++
++GType                 ck_display_template_get_type            (void);
++CkDisplayTemplate   * ck_display_template_get_from_name       (const char      *name);
++G_CONST_RETURN char * ck_display_template_get_name            (CkDisplayTemplate   *display);
++G_CONST_RETURN char * ck_display_template_get_type_string     (CkDisplayTemplate   *display);
++GHashTable          * ck_display_template_get_parameters      (CkDisplayTemplate   *display);
++
++G_END_DECLS
++
++#endif /* __CK_DISPLAY_TEMPLATE_H */
+diff --git a/src/ck-log-event.c b/src/ck-log-event.c
+index 66f439c..d13a0f8 100644
+--- a/src/ck-log-event.c
++++ b/src/ck-log-event.c
+@@ -79,6 +79,8 @@ event_seat_session_added_free (CkLogSeatSessionAddedEvent *event)
+         event->session_id = NULL;
+         g_free (event->session_type);
+         event->session_type = NULL;
++        g_free (event->display_type);
++        event->display_type = NULL;
+         g_free (event->session_x11_display);
+         event->session_x11_display = NULL;
+         g_free (event->session_x11_display_device);
+@@ -103,6 +105,8 @@ event_seat_session_removed_free (CkLogSeatSessionRemovedEvent *event)
+         event->session_id = NULL;
+         g_free (event->session_type);
+         event->session_type = NULL;
++        g_free (event->display_type);
++        event->display_type = NULL;
+         g_free (event->session_x11_display);
+         event->session_x11_display = NULL;
+         g_free (event->session_x11_display_device);
+@@ -213,6 +217,7 @@ event_seat_session_added_copy (CkLogSeatSessionAddedEvent *event,
+         event_copy->seat_id = g_strdup (event->seat_id);
+         event_copy->session_id = g_strdup (event->session_id);
+         event_copy->session_type = g_strdup (event->session_type);
++        event_copy->display_type = g_strdup (event->display_type);
+         event_copy->session_x11_display = g_strdup (event->session_x11_display);
+         event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device);
+         event_copy->session_display_device = g_strdup (event->session_display_device);
+@@ -232,6 +237,7 @@ event_seat_session_removed_copy (CkLogSeatSessionRemovedEvent *event,
+         event_copy->seat_id = g_strdup (event->seat_id);
+         event_copy->session_id = g_strdup (event->session_id);
+         event_copy->session_type = g_strdup (event->session_type);
++        event_copy->display_type = g_strdup (event->display_type);
+         event_copy->session_x11_display = g_strdup (event->session_x11_display);
+         event_copy->session_x11_display_device = g_strdup (event->session_x11_display_device);
+         event_copy->session_display_device = g_strdup (event->session_display_device);
+@@ -415,10 +421,11 @@ add_log_for_seat_session_added (GString    *str,
+ 
+         e = (CkLogSeatSessionAddedEvent *)event;
+         g_string_append_printf (str,
+-                                "seat-id='%s' session-id='%s' session-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
++                                "seat-id='%s' session-id='%s' session-type='%s' display-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
+                                 e->seat_id ? e->seat_id : "",
+                                 e->session_id ? e->session_id : "",
+                                 e->session_type ? e->session_type : "",
++                                e->display_type ? e->display_type : "",
+                                 e->session_x11_display ? e->session_x11_display : "",
+                                 e->session_x11_display_device ? e->session_x11_display_device : "",
+                                 e->session_display_device ? e->session_display_device : "",
+@@ -436,10 +443,11 @@ add_log_for_seat_session_removed (GString    *str,
+ 
+         e = (CkLogSeatSessionRemovedEvent *)event;
+         g_string_append_printf (str,
+-                                "seat-id='%s' session-id='%s' session-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
++                                "seat-id='%s' session-id='%s' session-type='%s' display-type='%s' session-x11-display='%s' session-x11-display-device='%s' session-display-device='%s' session-remote-host-name='%s' session-is-local=%s session-unix-user=%u session-creation-time='%s'",
+                                 e->seat_id ? e->seat_id : "",
+                                 e->session_id ? e->session_id : "",
+                                 e->session_type ? e->session_type : "",
++                                e->display_type ? e->display_type : "",
+                                 e->session_x11_display ? e->session_x11_display : "",
+                                 e->session_x11_display_device ? e->session_x11_display_device : "",
+                                 e->session_display_device ? e->session_display_device : "",
+@@ -721,7 +729,7 @@ parse_log_for_seat_added (const GString *str,
+         error = NULL;
+         re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' seat-kind=(?P<sessionid>[0-9]*)", 0, 0, &error);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+@@ -781,7 +789,7 @@ parse_log_for_seat_removed (const GString *str,
+         error = NULL;
+         re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' seat-kind=(?P<sessionid>[0-9]*)", 0, 0, &error);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+@@ -887,7 +895,7 @@ parse_log_for_system_start (const GString *str,
+         error = NULL;
+         re = g_regex_new ("(kernel-release='(?P<release>[^']+)')?[ ]?(boot-arguments='(?P<arguments>.*)')?", 0, 0, &error);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+@@ -939,9 +947,9 @@ parse_log_for_seat_session_added (const GString *str,
+         }
+ 
+         error = NULL;
+-        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);
++        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);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+@@ -957,6 +965,7 @@ parse_log_for_seat_session_added (const GString *str,
+         e->seat_id = g_match_info_fetch_named (match_info, "seatid");
+         e->session_id = g_match_info_fetch_named (match_info, "sessionid");
+         e->session_type = g_match_info_fetch_named (match_info, "sessiontype");
++        e->display_type = g_match_info_fetch_named (match_info, "displaytype");
+         e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display");
+         e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice");
+         e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice");
+@@ -1014,9 +1023,9 @@ parse_log_for_seat_session_removed (const GString *str,
+         }
+ 
+         error = NULL;
+-        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);
++        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);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+@@ -1032,6 +1041,7 @@ parse_log_for_seat_session_removed (const GString *str,
+         e->seat_id = g_match_info_fetch_named (match_info, "seatid");
+         e->session_id = g_match_info_fetch_named (match_info, "sessionid");
+         e->session_type = g_match_info_fetch_named (match_info, "sessiontype");
++        e->display_type = g_match_info_fetch_named (match_info, "displaytype");
+         e->session_x11_display = g_match_info_fetch_named (match_info, "sessionx11display");
+         e->session_x11_display_device = g_match_info_fetch_named (match_info, "sessionx11displaydevice");
+         e->session_display_device = g_match_info_fetch_named (match_info, "sessiondisplaydevice");
+@@ -1090,7 +1100,7 @@ parse_log_for_seat_active_session_changed (const GString *str,
+         error = NULL;
+         re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' session-id='(?P<sessionid>[a-zA-Z0-9/]*)'", 0, 0, &error);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+@@ -1142,7 +1152,7 @@ parse_log_for_seat_device_added (const GString *str,
+         error = NULL;
+         re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' device-id='(?P<deviceid>[^']+)' device-type='(?P<devicetype>[^']+)'", 0, 0, &error);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+@@ -1195,7 +1205,7 @@ parse_log_for_seat_device_removed (const GString *str,
+         error = NULL;
+         re = g_regex_new ("seat-id='(?P<seatid>[a-zA-Z0-9/]+)' device-id='(?P<deviceid>[^']+)' device-type='(?P<devicetype>[^']+)'", 0, 0, &error);
+         if (re == NULL) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 goto out;
+         }
+ 
+diff --git a/src/ck-log-event.h b/src/ck-log-event.h
+index 65571f0..2d4ed4e 100644
+--- a/src/ck-log-event.h
++++ b/src/ck-log-event.h
+@@ -68,6 +68,7 @@ typedef struct
+ {
+         char *seat_id;
+         int   seat_kind;
++        char *seat_type;
+ } CkLogSeatAddedEvent;
+ 
+ typedef struct
+@@ -81,11 +82,13 @@ typedef struct
+         char    *seat_id;
+         char    *session_id;
+         char    *session_type;
++        char    *display_type;
+         char    *session_x11_display;
+         char    *session_x11_display_device;
+         char    *session_display_device;
+         char    *session_remote_host_name;
+         gboolean session_is_local;
++        gboolean session_is_dynamic;
+         guint    session_unix_user;
+         char    *session_creation_time;
+ } CkLogSeatSessionAddedEvent;
+@@ -95,11 +98,13 @@ typedef struct
+         char    *seat_id;
+         char    *session_id;
+         char    *session_type;
++        char    *display_type;
+         char    *session_x11_display;
+         char    *session_x11_display_device;
+         char    *session_display_device;
+         char    *session_remote_host_name;
+         gboolean session_is_local;
++        gboolean session_is_dynamic;
+         guint    session_unix_user;
+         char    *session_creation_time;
+ } CkLogSeatSessionRemovedEvent;
+--- ConsoleKit-0.4.1/src/ck-manager.c.1	2010-09-06 17:41:32.942210394 +0800
++++ ConsoleKit-0.4.1/src/ck-manager.c	2010-09-06 17:41:56.671280731 +0800
+@@ -46,9 +46,14 @@
+ #include <secdb.h>
+ #endif
+ 
++#ifndef HAVE_STRVERSCMP
++#include "strverscmp.h"
++#endif
++
+ #include "ck-manager.h"
+ #include "ck-manager-glue.h"
+ #include "ck-seat.h"
++#include "ck-display-template.h"
+ #include "ck-session-leader.h"
+ #include "ck-session.h"
+ #include "ck-marshal.h"
+@@ -58,12 +63,19 @@
+ 
+ #define CK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_MANAGER, CkManagerPrivate))
+ 
++#define CK_TYPE_PARAMETER_STRUCT (dbus_g_type_get_struct ("GValueArray", \
++                                                          G_TYPE_STRING, \
++                                                          G_TYPE_VALUE, \
++                                                          G_TYPE_INVALID))
++
+ #define CK_SEAT_DIR          SYSCONFDIR "/ConsoleKit/seats.d"
+ #define LOG_FILE             LOCALSTATEDIR "/log/ConsoleKit/history"
+ #define CK_DBUS_PATH         "/org/freedesktop/ConsoleKit"
+ #define CK_MANAGER_DBUS_PATH CK_DBUS_PATH "/Manager"
+ #define CK_MANAGER_DBUS_NAME "org.freedesktop.ConsoleKit.Manager"
+ 
++#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
++
+ struct CkManagerPrivate
+ {
+ #ifdef HAVE_POLKIT
+@@ -392,6 +404,7 @@ log_seat_added_event (CkManager  *manage
+         GError            *error;
+         char              *sid;
+         CkSeatKind         seat_kind;
++        char              *seat_type;
+ 
+         memset (&event, 0, sizeof (CkLogEvent));
+ 
+@@ -401,9 +414,11 @@ log_seat_added_event (CkManager  *manage
+         sid = NULL;
+         ck_seat_get_id (seat, &sid, NULL);
+         ck_seat_get_kind (seat, &seat_kind, NULL);
++        ck_seat_get_type_string (seat, &seat_type, NULL);
+ 
+         event.event.seat_added.seat_id = (char *)get_object_id_basename (sid);
+         event.event.seat_added.seat_kind = (int)seat_kind;
++        event.event.seat_added.seat_type = (char *)seat_type;
+ 
+         error = NULL;
+         res = ck_event_logger_queue_event (manager->priv->logger, &event, &error);
+@@ -413,6 +428,7 @@ log_seat_added_event (CkManager  *manage
+         }
+ 
+         g_free (sid);
++        g_free (seat_type);
+ }
+ 
+ static void
+@@ -517,6 +533,7 @@ log_seat_session_added_event (CkManager 
+         if (session != NULL) {
+                 g_object_get (session,
+                               "session-type", &event.event.seat_session_added.session_type,
++                              "display-type", &event.event.seat_session_added.display_type,
+                               "x11-display", &event.event.seat_session_added.session_x11_display,
+                               "x11-display-device", &event.event.seat_session_added.session_x11_display_device,
+                               "display-device", &event.event.seat_session_added.session_display_device,
+@@ -572,6 +589,7 @@ log_seat_session_removed_event (CkManage
+         if (session != NULL) {
+                 g_object_get (session,
+                               "session-type", &event.event.seat_session_removed.session_type,
++                              "display-type", &event.event.seat_session_removed.display_type,
+                               "x11-display", &event.event.seat_session_removed.session_x11_display,
+                               "x11-display-device", &event.event.seat_session_removed.session_x11_display_device,
+                               "display-device", &event.event.seat_session_removed.session_display_device,
+@@ -845,6 +863,8 @@ ready_cb (PolkitAuthority *authority,
+         PolkitAuthorizationResult *ret;
+         GError *error;
+ 
++        g_debug ("CkManager: Ready.");
++
+         error = NULL;
+         ret = polkit_authority_check_authorization_finish (authority, res, &error);
+         if (error != NULL) {
+@@ -975,6 +995,7 @@ session_is_real_user (CkSession *session
+ 
+         /* filter out GDM user */
+         if (username != NULL && strcmp (username, "gdm") == 0) {
++                g_debug ("CkManager: Session is not real user");
+                 ret = FALSE;
+                 goto out;
+         }
+@@ -983,6 +1004,7 @@ session_is_real_user (CkSession *session
+                 *userp = g_strdup (username);
+         }
+ 
++        g_debug ("CkManager: Session is real user");
+         ret = TRUE;
+ 
+  out:
+@@ -1230,6 +1252,7 @@ on_seat_active_session_changed_full (CkS
+ {
+         char *ssid = NULL;
+ 
++        g_debug ("CkManager: Active session changed.");
+         if (session != NULL) {
+                 ck_session_get_id (session, &ssid, NULL);
+         }
+@@ -1247,6 +1270,7 @@ on_seat_session_added_full (CkSeat     *
+ {
+         char *ssid = NULL;
+ 
++        g_debug ("CkManager: Session added.");
+         ck_session_get_id (session, &ssid, NULL);
+ 
+         ck_manager_dump (manager);
+@@ -1262,6 +1286,7 @@ on_seat_session_removed_full (CkSeat    
+ {
+         char *ssid = NULL;
+ 
++        g_debug ("CkManager: Seat Session removed.");
+         ck_session_get_id (session, &ssid, NULL);
+ 
+         ck_manager_dump (manager);
+@@ -1275,6 +1300,7 @@ on_seat_device_added (CkSeat      *seat,
+                       GValueArray *device,
+                       CkManager   *manager)
+ {
++        g_debug ("CkManager: Seat device added.");
+         ck_manager_dump (manager);
+         log_seat_device_added_event (manager, seat, device);
+ }
+@@ -1284,6 +1310,7 @@ on_seat_device_removed (CkSeat      *sea
+                         GValueArray *device,
+                         CkManager   *manager)
+ {
++        g_debug ("CkManager: Seat device removed.");
+         ck_manager_dump (manager);
+         log_seat_device_removed_event (manager, seat, device);
+ }
+@@ -1311,15 +1338,23 @@ disconnect_seat_signals (CkManager *mana
+ }
+ 
+ static CkSeat *
+-add_new_seat (CkManager *manager,
+-              CkSeatKind kind)
++add_new_seat (CkManager  *manager,
++              const char *give_sid,
++              CkSeatKind  kind,
++              const char *type)
+ {
+         char   *sid;
+         CkSeat *seat;
+ 
+-        sid = generate_seat_id (manager);
++        if (IS_STR_SET (give_sid)) {
++                sid = g_strdup (give_sid);
++        } else {
++                sid = generate_seat_id (manager);
++        }
+ 
+-        seat = ck_seat_new (sid, kind);
++        g_debug ("CkManager: Add new seat '%s'.", sid);
++
++        seat = ck_seat_new (sid, kind, type);
+ 
+         /* First we connect our own signals to the seat, followed by
+          * the D-Bus signal hookup to make sure we can first dump the
+@@ -1344,7 +1379,7 @@ add_new_seat (CkManager *manager,
+         ck_seat_run_programs (seat, NULL, NULL, "seat_added");
+ 
+         g_debug ("Emitting seat-added: %s", sid);
+-        g_signal_emit (manager, signals [SEAT_ADDED], 0, sid);
++        g_signal_emit (manager, signals [SEAT_ADDED], 0, sid, type);
+ 
+         log_seat_added_event (manager, seat);
+ 
+@@ -1363,6 +1398,8 @@ remove_seat (CkManager *manager,
+         sid = NULL;
+         ck_seat_get_id (seat, &sid, NULL);
+ 
++        g_debug ("CkManager: Remove seat '%s'", sid);
++
+         /* Need to get the original key/value */
+         res = g_hash_table_lookup_extended (manager->priv->seats,
+                                             sid,
+@@ -1402,64 +1439,22 @@ remove_seat (CkManager *manager,
+         g_free (sid);
+ }
+ 
+-#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
+-
+ static CkSeat *
+ find_seat_for_session (CkManager *manager,
+                        CkSession *session)
+ {
+         CkSeat  *seat;
+-        gboolean is_static_x11;
+-        gboolean is_static_text;
+-        char    *display_device;
+-        char    *x11_display_device;
+-        char    *x11_display;
+-        char    *remote_host_name;
+-        gboolean is_local;
+-
+-        is_static_text = FALSE;
+-        is_static_x11 = FALSE;
+-
+-        seat = NULL;
+-        display_device = NULL;
+-        x11_display_device = NULL;
+-        x11_display = NULL;
+-        remote_host_name = NULL;
+-        is_local = FALSE;
+-
+-        /* FIXME: use matching to group entries? */
+-
+-        ck_session_get_display_device (session, &display_device, NULL);
+-        ck_session_get_x11_display_device (session, &x11_display_device, NULL);
+-        ck_session_get_x11_display (session, &x11_display, NULL);
+-        ck_session_get_remote_host_name (session, &remote_host_name, NULL);
+-        ck_session_is_local (session, &is_local, NULL);
+-
+-        if (IS_STR_SET (x11_display)
+-            && IS_STR_SET (x11_display_device)
+-            && ! IS_STR_SET (remote_host_name)
+-            && is_local == TRUE) {
+-                is_static_x11 = TRUE;
+-        } else if (! IS_STR_SET (x11_display)
+-                   && ! IS_STR_SET (x11_display_device)
+-                   && IS_STR_SET (display_device)
+-                   && ! IS_STR_SET (remote_host_name)
+-                   && is_local == TRUE) {
+-                is_static_text = TRUE;
+-        }
++        char    *sid = NULL;
+ 
+-        if (is_static_x11 || is_static_text) {
+-                char *sid;
++        ck_session_get_seat_id (session, &sid, NULL);
++
++        if (! IS_STR_SET (sid)) {
+                 sid = g_strdup_printf ("%s/Seat%u", CK_DBUS_PATH, 1);
+-                seat = g_hash_table_lookup (manager->priv->seats, sid);
+-                g_free (sid);
+         }
+ 
+-        g_free (display_device);
+-        g_free (x11_display_device);
+-        g_free (x11_display);
+-        g_free (remote_host_name);
++        seat = g_hash_table_lookup (manager->priv->seats, sid);
+ 
++        g_free (sid);
+         return seat;
+ }
+ 
+@@ -1594,36 +1589,52 @@ open_session_for_leader (CkManager      
+         CkSession   *session;
+         CkSeat      *seat;
+         const char  *ssid;
++        char        *sid;
+         const char  *cookie;
+ 
++        g_debug ("CkManager: Open session for leader.");
+         ssid = ck_session_leader_peek_session_id (leader);
+         cookie = ck_session_leader_peek_cookie (leader);
+ 
+-        session = ck_session_new_with_parameters (ssid,
+-                                                  cookie,
+-                                                  parameters);
++        session = g_hash_table_lookup (manager->priv->sessions, ssid);
+ 
+         if (session == NULL) {
+-                GError *error;
+-                g_debug ("Unable to create new session");
+-                error = g_error_new (CK_MANAGER_ERROR,
+-                                     CK_MANAGER_ERROR_GENERAL,
+-                                     "Unable to create new session");
+-                dbus_g_method_return_error (context, error);
+-                g_error_free (error);
++                g_debug ("CkManager: Creating new session.");
++                session = ck_session_new_with_parameters (ssid,
++                                                          parameters);
++
++                if (session == NULL) {
++                        GError *error;
++                        g_debug ("CkManager: Unable to create new session");
++                        error = g_error_new (CK_MANAGER_ERROR,
++                                             CK_MANAGER_ERROR_GENERAL,
++                                             "Unable to create new session");
++                        dbus_g_method_return_error (context, error);
++                        g_error_free (error);
+ 
+-                return;
++                        return;
++                }
++
++                g_hash_table_insert (manager->priv->sessions,
++                                     g_strdup (ssid),
++                                     g_object_ref (session));
++
++        } else {
++                g_debug ("CkManager: Using found session.");
++                ck_session_set_parameters (session, parameters);
+         }
+ 
+-        g_hash_table_insert (manager->priv->sessions,
+-                             g_strdup (ssid),
+-                             g_object_ref (session));
++        ck_session_set_cookie (session, cookie, NULL);
++        ck_session_set_is_open (session, TRUE, NULL);
+ 
+         /* Add to seat */
+         seat = find_seat_for_session (manager, session);
+         if (seat == NULL) {
++                sid = NULL;
++                ck_session_get_seat_id (session, &sid, NULL);
+                 /* create a new seat */
+-                seat = add_new_seat (manager, CK_SEAT_KIND_DYNAMIC);
++                seat = add_new_seat (manager, sid, CK_SEAT_KIND_DYNAMIC, "Default");
++                g_free (sid);
+         }
+ 
+         ck_seat_add_session (seat, session, NULL);
+@@ -1683,6 +1694,7 @@ generate_session_for_leader (CkManager  
+ {
+         gboolean res;
+ 
++        g_debug ("CkManager: Generate session for leader.");
+         res = ck_session_leader_collect_parameters (leader,
+                                                     context,
+                                                     (CkSessionLeaderDoneFunc)collect_parameters_cb,
+@@ -1697,11 +1709,57 @@ generate_session_for_leader (CkManager  
+         }
+ }
+ 
++static char *
++check_parameters_for_ssid (const GPtrArray *parameters)
++{
++        int i;
++
++        if (parameters == NULL) {
++                return NULL;
++        }
++
++        for (i = 0; i < parameters->len; i++) {
++                GValue   val_struct = { 0, };
++                char    *prop_name;
++                gboolean res;
++
++                g_value_init (&val_struct, CK_TYPE_PARAMETER_STRUCT);
++                g_value_set_static_boxed (&val_struct, g_ptr_array_index (parameters, i));
++
++                res = dbus_g_type_struct_get (&val_struct,
++                                              0, &prop_name,
++                                              G_MAXUINT);
++                if (! res) {
++                        g_debug ("CkManager: Unable to read parameter name");
++                        continue;
++                }
++
++                if (prop_name != NULL && strcmp (prop_name, "session") == 0) {
++                        GValue   prop_val = { 0, };
++                        GValue  *session_val;
++
++                        g_value_init (&prop_val, G_TYPE_VALUE);
++                        res = dbus_g_type_struct_get_member (&val_struct, 1, &prop_val);
++
++                        if (! res) {
++                                g_debug ("CkManager: Unable to read parameter value");
++                                continue;
++                        }
++
++                        session_val = g_value_get_boxed (&prop_val);
++
++                        return g_value_dup_string (session_val);
++                }
++        }
++
++        return NULL;
++}
++
+ static gboolean
+-create_session_for_sender (CkManager             *manager,
+-                           const char            *sender,
+-                           const GPtrArray       *parameters,
+-                           DBusGMethodInvocation *context)
++open_session_for_sender (CkManager             *manager,
++                         const char            *sender,
++                         const GPtrArray       *parameters,
++                         DBusGMethodInvocation *context)
+ {
+         pid_t           pid;
+         uid_t           uid;
+@@ -1709,6 +1767,7 @@ create_session_for_sender (CkManager    
+         char            *cookie;
+         char            *ssid;
+         CkSessionLeader *leader;
++        CkSession       *session;
+ 
+         g_debug ("CkManager: create session for sender: %s", sender);
+ 
+@@ -1727,9 +1786,21 @@ create_session_for_sender (CkManager    
+         }
+ 
+         cookie = generate_session_cookie (manager);
+-        ssid = generate_session_id (manager);
+ 
+-        g_debug ("Creating new session ssid: %s", ssid);
++        ssid = check_parameters_for_ssid (parameters);
++
++        if (IS_STR_SET (ssid)) {
++                session = g_hash_table_lookup (manager->priv->sessions, ssid);
++
++                /* FIXME: Need to verify that the session belongs to a seat
++                 * managed by the sender
++                 */
++                g_debug ("CkManager: Managing existing session ssid: %s", ssid);
++        } else {
++                ssid = generate_session_id (manager);
++                session = NULL;
++                g_debug ("CkManager: Creating new session ssid: %s", ssid);
++        }
+ 
+         leader = ck_session_leader_new ();
+         ck_session_leader_set_uid (leader, uid);
+@@ -1967,7 +2038,7 @@ ck_manager_open_session (CkManager      
+         gboolean ret;
+ 
+         sender = dbus_g_method_get_sender (context);
+-        ret = create_session_for_sender (manager, sender, NULL, context);
++        ret = open_session_for_sender (manager, sender, NULL, context);
+         g_free (sender);
+ 
+         return ret;
+@@ -1982,7 +2053,7 @@ ck_manager_open_session_with_parameters 
+         gboolean ret;
+ 
+         sender = dbus_g_method_get_sender (context);
+-        ret = create_session_for_sender (manager, sender, parameters, context);
++        ret = open_session_for_sender (manager, sender, parameters, context);
+         g_free (sender);
+ 
+         return ret;
+@@ -1999,10 +2070,12 @@ remove_session_for_cookie (CkManager  *m
+         char            *sid;
+         gboolean         res;
+         gboolean         ret;
++        gboolean         should_remove_session;
+ 
+         ret = FALSE;
+         orig_ssid = NULL;
+         orig_session = NULL;
++        should_remove_session = FALSE;
+ 
+         g_debug ("Removing session for cookie: %s", cookie);
+ 
+@@ -2029,6 +2102,17 @@ remove_session_for_cookie (CkManager  *m
+                 goto out;
+         }
+ 
++        ck_session_set_is_open (orig_session, FALSE, NULL);
++        ck_session_set_cookie (orig_session, NULL, NULL);
++        ck_session_set_active (orig_session, FALSE, NULL);
++        ck_session_set_unix_user (orig_session, 0, NULL);
++        ck_session_set_x11_display (orig_session, NULL, NULL);
++        ck_session_set_x11_display_device (orig_session, NULL, NULL);
++        ck_session_set_display_device (orig_session, NULL, NULL);
++        ck_session_set_login_session_id (orig_session, NULL, NULL);
++        ck_session_set_remote_host_name (orig_session, NULL, NULL);
++        ck_session_set_under_request (orig_session, FALSE, NULL);
++
+         /* Must keep a reference to the session in the manager until
+          * all events for seats are cleared.  So don't remove
+          * or steal the session from the master list until
+@@ -2036,31 +2120,33 @@ remove_session_for_cookie (CkManager  *m
+          * for seat removals doesn't work.
+          */
+ 
+-        /* remove from seat */
+-        sid = NULL;
+-        ck_session_get_seat_id (orig_session, &sid, NULL);
+-        if (sid != NULL) {
+-                CkSeat *seat;
+-                seat = g_hash_table_lookup (manager->priv->seats, sid);
+-                if (seat != NULL) {
+-                        CkSeatKind kind;
+-
+-                        ck_seat_remove_session (seat, orig_session, NULL);
+-
+-                        kind = CK_SEAT_KIND_STATIC;
+-                        /* if dynamic seat has no sessions then remove it */
+-                        ck_seat_get_kind (seat, &kind, NULL);
+-                        if (kind == CK_SEAT_KIND_DYNAMIC) {
+-                                remove_seat (manager, seat);
++        ck_session_get_remove_on_close (orig_session, &should_remove_session, NULL);
++
++        if (should_remove_session) {
++                /* remove from seat */
++                g_debug ("CkManager: Should remove session");
++                sid = NULL;
++                ck_session_get_seat_id (orig_session, &sid, NULL);
++                if (sid != NULL) {
++                        CkSeat *seat;
++                        seat = g_hash_table_lookup (manager->priv->seats, sid);
++                        if (seat != NULL) {
++                                CkSeatKind kind;
++
++                                ck_seat_remove_session (seat, orig_session, NULL);
++
++                                kind = CK_SEAT_KIND_STATIC;
++                                /* if dynamic seat has no sessions then remove it */
++                                ck_seat_get_kind (seat, &kind, NULL);
+                         }
+                 }
+-        }
+-        g_free (sid);
++                g_free (sid);
+ 
+-        /* Remove the session from the list but don't call
+-         * unref until we are done with it */
+-        g_hash_table_steal (manager->priv->sessions,
+-                            ck_session_leader_peek_session_id (leader));
++                /* Remove the session from the list but don't call
++                 * unref until we are done with it */
++                g_hash_table_steal (manager->priv->sessions,
++                                    ck_session_leader_peek_session_id (leader));
++        }
+ 
+         ck_manager_dump (manager);
+ 
+@@ -2068,11 +2154,13 @@ remove_session_for_cookie (CkManager  *m
+ 
+         ret = TRUE;
+  out:
+-        if (orig_session != NULL) {
+-                g_object_unref (orig_session);
+-        }
+-        g_free (orig_ssid);
++        if (should_remove_session) {
++                if (orig_session != NULL) {
++                        g_object_unref (orig_session);
++                }
+ 
++                g_free (orig_ssid);
++        }
+         return ret;
+ }
+ 
+@@ -2193,6 +2281,7 @@ remove_leader_for_connection (const char
+         g_assert (leader != NULL);
+         g_assert (data->service_name != NULL);
+ 
++        g_debug ("CkManager: Remove leader for connection");
+         name = ck_session_leader_peek_service_name (leader);
+         if (strcmp (name, data->service_name) == 0) {
+                 remove_session_for_cookie (data->manager, cookie, NULL);
+@@ -2210,6 +2299,8 @@ remove_sessions_for_connection (CkManage
+         guint            n_removed;
+         RemoveLeaderData data;
+ 
++        g_debug ("CkManager: Remove sessions for connection");
++
+         data.service_name = service_name;
+         data.manager = manager;
+ 
+@@ -2245,6 +2336,8 @@ register_manager (CkManager *manager)
+         manager->priv->pol_ctx = polkit_authority_get ();
+ #endif
+ 
++        g_debug ("CkManager: Registering manager");
++
+         error = NULL;
+         manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+         if (manager->priv->connection == NULL) {
+@@ -2290,9 +2383,11 @@ ck_manager_class_init (CkManagerClass *k
+                               G_STRUCT_OFFSET (CkManagerClass, seat_added),
+                               NULL,
+                               NULL,
+-                              g_cclosure_marshal_VOID__BOXED,
++                              ck_marshal_VOID__STRING_STRING,
+                               G_TYPE_NONE,
+-                              1, DBUS_TYPE_G_OBJECT_PATH);
++                              2,
++                              G_TYPE_STRING,
++                              G_TYPE_STRING);
+         signals [SEAT_REMOVED] =
+                 g_signal_new ("seat-removed",
+                               G_TYPE_FROM_CLASS (object_class),
+@@ -2399,6 +2494,43 @@ ck_manager_get_seats (CkManager  *manage
+ }
+ 
+ static void
++listify_unmanaged_seat_ids (char       *id,
++                            CkSeat     *seat,
++                            GPtrArray **array)
++{
++        if (ck_seat_is_managed (seat)) {
++                return;
++        }
++
++        g_ptr_array_add (*array, g_strdup (id));
++}
++
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.GetUnmanagedSeats
++*/
++gboolean
++ck_manager_get_unmanaged_seats (CkManager  *manager,
++                                GPtrArray **seats,
++                                GError    **error)
++{
++        g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
++
++        if (seats == NULL) {
++                return FALSE;
++        }
++
++        *seats = g_ptr_array_new ();
++        g_hash_table_foreach (manager->priv->seats, (GHFunc)listify_unmanaged_seat_ids, seats);
++
++        return TRUE;
++}
++
++static void
+ listify_session_ids (char       *id,
+                      CkSession  *session,
+                      GPtrArray **array)
+@@ -2423,16 +2555,321 @@ ck_manager_get_sessions (CkManager  *man
+         return TRUE;
+ }
+ 
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.AddSeat string:Default
++*/
++gboolean
++ck_manager_add_seat (CkManager  *manager,
++                     const char *type,
++                     char      **sid,
++                     GError    **error)
++{
++        CkSeat    *seat;
++                
++        g_debug ("CkManager: Add seat '%s'.", *sid);
++        g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
++
++        seat = add_new_seat (manager, NULL, CK_SEAT_KIND_DYNAMIC, type);
++
++        if (!ck_seat_get_id (seat, sid, error)) {
++                return FALSE;
++        }
++
++        return TRUE;
++}
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.AddSeatById \
++  objpath:/org/freedesktop/ConsoleKit/SeatTest \
++*/
++gboolean
++ck_manager_add_seat_by_id (CkManager  *manager,
++                           const char *type,
++                           const char *sid,
++                           GError    **error) 
++{
++        CkSeat    *seat;
++
++        g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
++
++        seat = add_new_seat (manager, sid, CK_SEAT_KIND_DYNAMIC, type);
++
++        return !(seat == NULL);
++}
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.RemoveSeat \
++  obj:/org/freedesktop/ConsoleKit/Seat2
++*/
++gboolean
++ck_manager_remove_seat (CkManager             *manager,
++                        const char            *sid,
++                        DBusGMethodInvocation *context)
++{
++        CkSeat     *seat = NULL;
++        CkSeatKind kind;
++
++        g_debug ("CkManager: Remove seat '%s'.", sid);
++        g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
++
++        seat = g_hash_table_lookup (manager->priv->seats, sid);
++
++        if (seat == NULL) {
++                GError *error;
++
++                error = g_error_new (CK_SEAT_ERROR,
++                                     CK_SEAT_ERROR_GENERAL,
++                                     _("Seat '%s' doesn't exist"),
++                                     sid);
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++
++                return FALSE;
++        }
++
++        ck_seat_get_kind (seat, &kind, NULL);
++
++        if (kind == CK_SEAT_KIND_STATIC) {
++                GError *error;
++
++                error = g_error_new (CK_SEAT_ERROR,
++                                     CK_SEAT_ERROR_GENERAL,
++                                     _("Seat '%s' is static and can't be removed"),
++                                     sid);
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++
++                return FALSE;
++        }
++
++        if (ck_seat_is_managed (seat)) {
++                ck_seat_request_removal (seat);
++        } else {
++                remove_seat (manager, seat);
++        }
++
++        return TRUE;
++}
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.AddSession \
++  objpath:/org/freedesktop/ConsoleKit/Seat2 \
++  string:"LoginWindow" \
++  dict:string:string:"vt","vt9","display",":123"
++*/
++gboolean
++ck_manager_add_session (CkManager             *manager,
++                        const char            *sid,
++                        const char            *type,
++                        const char            *display_type,
++                        GHashTable            *variables,
++                        DBusGMethodInvocation *context)
++{
++        CkSeat    *seat;
++        CkSession *session;
++        char      *ssid;
++
++        g_debug ("CkManager: Add session");
++        seat = g_hash_table_lookup (manager->priv->seats, sid);
++
++        if (seat == NULL) {
++                GError *error;
++
++                error = g_error_new (CK_SEAT_ERROR,
++                                     CK_SEAT_ERROR_GENERAL, 
++                                     _("Seat '%s' doesn't exist"),
++                                     sid);
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++
++                return FALSE;
++        }
++
++        ssid = generate_session_id (manager);
++
++        session = ck_session_new (ssid, type, display_type, variables);
++
++        if (session == NULL) {
++                GError *error;
++
++                error = g_error_new (CK_SEAT_ERROR, 
++                                     CK_SEAT_ERROR_GENERAL,
++                                     _("Session could not be added to seat '%s'"),
++                                     sid);
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++
++                return FALSE;
++        }
++
++        ck_session_set_seat_id (session, sid, NULL);
++        if (IS_STR_SET (type) && g_str_equal (type, "LoginWindow")) {
++                session_set_remove_on_close (session, FALSE, NULL);
++        } else {
++                session_set_remove_on_close (session, TRUE, NULL);
++        }
++
++        ck_seat_add_session (seat, session, NULL);
++
++        g_hash_table_insert (manager->priv->sessions,
++                             ssid,
++                             session);
++
++        dbus_g_method_return (context, ssid);
++        return TRUE;
++}
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.RemoveSession \
++  objpath:/org/freedesktop/ConsoleKit/Session2
++*/
++gboolean
++ck_manager_remove_session (CkManager             *manager,
++                           const char            *ssid,
++                           DBusGMethodInvocation *context)
++{
++        CkSession *session;
++        CkSeat *seat;
++        GError *error; 
++        char *sid;
++        gboolean is_open;
++
++        g_debug ("CkManager: Remove session.");
++        session = g_hash_table_lookup (manager->priv->sessions, ssid);
++
++        if (session == NULL) {
++                GError *error;
++
++                error = g_error_new (CK_SEAT_ERROR,
++                                     CK_SEAT_ERROR_GENERAL,
++                                     _("Session '%s' doesn't exist"),
++                                     ssid);
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++
++                return FALSE;
++        }
++
++        ck_session_get_seat_id (session, &sid, NULL);
++        seat = g_hash_table_lookup (manager->priv->seats, sid);
++        g_free (sid);
++
++        if (seat == NULL) {
++                g_warning ("Session '%s' is not associated with a seat", ssid);
++                g_hash_table_remove (manager->priv->sessions, ssid);
++                return TRUE;
++        }
++
++        error = NULL;
++
++        ck_session_is_open (session, &is_open, NULL);
++        session_set_remove_on_close (session, TRUE, NULL);
++
++        /* We'll let the seat manager close us when it's ready
++         */
++        if (ck_seat_is_managed (seat) && is_open) {
++                ck_seat_request_close_session (seat, session, NULL);
++                dbus_g_method_return (context);
++
++                return TRUE;
++        }
++
++        if (!ck_seat_remove_session (seat, session, &error)) {
++                if (error == NULL) {
++                        return TRUE;
++                }
++                
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++                return FALSE;
++        }
++        
++        g_hash_table_remove (manager->priv->sessions, ssid);
++        dbus_g_method_return (context);
++        return TRUE;
++}
++ 
++static void
++add_sessions_from_seat (CkManager *manager,
++                        CkSeat    *seat)
++{
++        GPtrArray *sessions;
++        int i;
++
++        g_debug ("CkManager: Add session from seat.");
++        ck_seat_get_sessions (seat, &sessions, NULL);
++
++        for (i = 0; i < sessions->len; i++) {
++                char *ssid;
++                CkSession *session; 
++
++                ssid = g_ptr_array_index (sessions, i);
++                session = ck_seat_get_session (seat, ssid);
++
++                g_hash_table_insert (manager->priv->sessions,
++                                     ssid,
++                                     session);
++        }
++
++        g_ptr_array_free (sessions, TRUE);
++}
++
+ static void
+ add_seat_for_file (CkManager  *manager,
+                    const char *filename)
+ {
+         char   *sid;
++        char   *orig_sid;
+         CkSeat *seat;
+ 
++        g_debug ("CkManager: Add seat for file.");
+         sid = generate_seat_id (manager);
++        orig_sid = g_strdup (sid);
++        seat = ck_seat_new_from_file (&sid, filename);
++
++        if (seat == NULL) {
++                /* returns null if connection to bus fails */
++                g_free (sid);
++                g_free (orig_sid);
++                manager->priv->seat_serial--;
++                return;
++        }
+ 
+-        seat = ck_seat_new_from_file (sid, filename);
++        if (!g_str_equal (orig_sid, sid)) {
++                manager->priv->seat_serial--;
++        }
++        g_free (orig_sid);
++
++        add_sessions_from_seat (manager, seat);
++
++        if (seat == NULL) {
++                return;
++        }
+ 
+         connect_seat_signals (manager, seat);
+         if (!ck_seat_register (seat)) {
+@@ -2451,7 +2888,7 @@ add_seat_for_file (CkManager  *manager,
+         ck_seat_run_programs (seat, NULL, NULL, "seat_added");
+ 
+         g_debug ("Emitting seat-added: %s", sid);
+-        g_signal_emit (manager, signals [SEAT_ADDED], 0, sid);
++        g_signal_emit (manager, signals [SEAT_ADDED], 0, sid, "Default");
+ 
+         log_seat_added_event (manager, seat);
+ }
+@@ -2462,6 +2899,7 @@ load_seats_from_dir (CkManager *manager)
+         GDir       *d;
+         GError     *error;
+         const char *file;
++        GQueue      seat_queue;
+ 
+         error = NULL;
+         d = g_dir_open (CK_SEAT_DIR,
+@@ -2473,15 +2911,26 @@ load_seats_from_dir (CkManager *manager)
+                 return FALSE;
+         }
+ 
++        g_queue_init (&seat_queue);
+         while ((file = g_dir_read_name (d)) != NULL) {
+                 char *path;
+                 path = g_build_filename (CK_SEAT_DIR, file, NULL);
++                g_queue_push_tail (&seat_queue, path);
++        }
++        g_dir_close (d);
++
++        g_queue_sort (&seat_queue, (GCompareDataFunc) strverscmp, NULL);
++
++        while (!g_queue_is_empty (&seat_queue)) {
++                char *path;
++
++                path = g_queue_pop_head (&seat_queue);
++
+                 add_seat_for_file (manager, path);
++
+                 g_free (path);
+         }
+ 
+-        g_dir_close (d);
+-
+         return TRUE;
+ }
+ 
+@@ -2517,8 +2966,6 @@ ck_manager_init (CkManager *manager)
+                                                         (GDestroyNotify) g_object_unref);
+ 
+         manager->priv->logger = ck_event_logger_new (LOG_FILE);
+-
+-        create_seats (manager);
+ }
+ 
+ static void
+@@ -2563,7 +3010,48 @@ ck_manager_new (void)
+                         g_object_unref (manager_object);
+                         return NULL;
+                 }
++
++                create_seats (CK_MANAGER (manager_object));
+         }
+ 
+         return CK_MANAGER (manager_object);
+ }
++
++gboolean
++ck_manager_will_not_respawn (CkManager             *manager,
++                             const char            *ssid,
++                             DBusGMethodInvocation *context)
++{
++        GError *error; 
++        CkSeat *seat;
++        CkSession *session;
++        char *sid;
++
++        g_debug ("CkManager: Will not respawn: '%s'.", ssid);
++        session = g_hash_table_lookup (manager->priv->sessions, ssid);
++
++        if (session == NULL) {
++                GError *error;
++
++                error = g_error_new (CK_SEAT_ERROR,
++                                     CK_SEAT_ERROR_GENERAL,
++                                     _("Session '%s' doesn't exist"),
++                                     ssid);
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++
++                return FALSE;
++        }
++
++        session_set_remove_on_close (session, FALSE, NULL);
++        ck_session_get_seat_id (session, &sid, NULL);
++        seat = g_hash_table_lookup (manager->priv->seats, sid);
++        g_free (sid);
++
++        ck_seat_no_respawn (seat, session, &error);
++
++        dbus_g_method_return (context);
++        return TRUE;
++}
++
+diff --git a/src/ck-manager.h b/src/ck-manager.h
+index 4bd56e8..4304e71 100644
+--- a/src/ck-manager.h
++++ b/src/ck-manager.h
+@@ -49,7 +49,8 @@ typedef struct
+         GObjectClass   parent_class;
+ 
+         void          (* seat_added)               (CkManager  *manager,
+-                                                    const char *sid);
++                                                    const char *sid,
++                                                    const char *type);
+         void          (* seat_removed)             (CkManager  *manager,
+                                                     const char *sid);
+         void          (* system_idle_hint_changed) (CkManager  *manager,
+@@ -96,6 +97,9 @@ gboolean            ck_manager_get_sessi
+ gboolean            ck_manager_get_seats                      (CkManager             *manager,
+                                                                GPtrArray            **seats,
+                                                                GError               **error);
++gboolean            ck_manager_get_unmanaged_seats            (CkManager             *manager,
++                                                               GPtrArray            **seats,
++                                                               GError               **error);
+ gboolean            ck_manager_close_session                  (CkManager             *manager,
+                                                                const char            *cookie,
+                                                                DBusGMethodInvocation *context);
+@@ -128,6 +132,31 @@ gboolean            ck_manager_open_sess
+                                                                const GPtrArray       *parameters,
+                                                                DBusGMethodInvocation *context);
+ 
++gboolean            ck_manager_add_seat                       (CkManager             *manager,
++                                                               const char            *type,
++                                                               char                 **sid,
++                                                               GError               **error);
++gboolean            ck_manager_add_seat_by_id                 (CkManager             *manager,
++                                                               const char            *type,
++                                                               const char            *sid,
++                                                               GError               **error);
++gboolean            ck_manager_remove_seat                    (CkManager             *manager,
++                                                               const char            *sid,
++                                                               DBusGMethodInvocation *context);
++
++gboolean            ck_manager_add_session                    (CkManager             *manager,
++                                                               const char            *sid,
++                                                               const char            *type,
++                                                               const char            *display_type,
++                                                               GHashTable            *parameters,
++                                                               DBusGMethodInvocation *context);
++gboolean            ck_manager_remove_session                  (CkManager             *manager,
++                                                                const char            *ssid,
++                                                                DBusGMethodInvocation *context);
++gboolean            ck_manager_will_not_respawn               (CkManager             *manager,
++                                                               const char            *cookie,
++                                                               DBusGMethodInvocation *context);
++
+ G_END_DECLS
+ 
+ #endif /* __CK_MANAGER_H */
+diff --git a/src/ck-marshal.list b/src/ck-marshal.list
+index 7f60efc..f8029a6 100644
+--- a/src/ck-marshal.list
++++ b/src/ck-marshal.list
+@@ -1,3 +1,6 @@
+ VOID:UINT,STRING
+ BOOLEAN:POINTER
+ VOID:OBJECT,OBJECT
++VOID:STRING,STRING
++VOID:STRING,BOOLEAN,STRING,POINTER,STRING,POINTER
++VOID:STRING,STRING,STRING,POINTER,STRING,POINTER
+diff --git a/src/ck-seat.c b/src/ck-seat.c
+index af7db59..dd2a387 100644
+--- a/src/ck-seat.c
++++ b/src/ck-seat.c
+@@ -40,21 +40,30 @@
+ #include "ck-seat-glue.h"
+ #include "ck-marshal.h"
+ 
++#include "ck-display-template.h"
+ #include "ck-session.h"
+ #include "ck-vt-monitor.h"
+ #include "ck-run-programs.h"
+ 
+ #define CK_SEAT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SEAT, CkSeatPrivate))
+ 
++#define CK_SESSION_DIR SYSCONFDIR "/ConsoleKit/sessions.d"
++
+ #define CK_DBUS_PATH "/org/freedesktop/ConsoleKit"
+ #define CK_DBUS_NAME "org.freedesktop.ConsoleKit"
+ 
+ #define NONULL_STRING(x) ((x) != NULL ? (x) : "")
++#define N_ELEMENTS(arr)  (sizeof (arr) / sizeof ((arr)[0]))
++
++#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
++
++#define CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
+ 
+ struct CkSeatPrivate
+ {
+         char            *id;
+         CkSeatKind       kind;
++        char            *type;
+         GHashTable      *sessions;
+         GPtrArray       *devices;
+ 
+@@ -63,6 +72,8 @@ struct CkSeatPrivate
+         CkVtMonitor     *vt_monitor;
+ 
+         DBusGConnection *connection;
++
++        DBusGProxy      *manager_proxy;
+ };
+ 
+ enum {
+@@ -74,6 +85,10 @@ enum {
+         SESSION_REMOVED_FULL,
+         DEVICE_ADDED,
+         DEVICE_REMOVED,
++        REMOVE_REQUEST,
++        OPEN_SESSION_REQUEST,
++        CLOSE_SESSION_REQUEST,
++        NO_RESPAWN,
+         LAST_SIGNAL
+ };
+ 
+@@ -81,6 +96,7 @@ enum {
+         PROP_0,
+         PROP_ID,
+         PROP_KIND,
++        PROP_TYPE
+ };
+ 
+ static guint signals [LAST_SIGNAL] = { 0, };
+@@ -287,6 +303,7 @@ ck_seat_activate_session (CkSeat        
+ {
+         CkSession *session;
+         gboolean   ret;
++        gboolean   is_open;
+ 
+         g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+ 
+@@ -298,12 +315,410 @@ ck_seat_activate_session (CkSeat        
+                 session = g_hash_table_lookup (seat->priv->sessions, ssid);
+         }
+ 
+-        ret = _seat_activate_session (seat, session, context);
++        ck_session_is_open (session, &is_open, NULL);
++        if (!is_open) {
++                g_debug ("CkSeat: session is not open.  Request open session");
++                ret = ck_seat_request_open_session (seat, session, NULL);
++                dbus_g_method_return (context, NULL);
++        } else {
++                g_debug ("CkSeat: session is open.  Activate session");
++                ret = _seat_activate_session (seat, session, context);
++        }
+ 
+         return ret;
+ }
+ 
+ static gboolean
++on_substitution_match (const GMatchInfo *match_info,
++                       GString          *result,
++                       GHashTable       *substitution_variables)
++{
++        char *match;
++        char *value = NULL;
++
++        match = g_match_info_fetch (match_info, 1);
++
++        if (substitution_variables != NULL)
++                value = g_hash_table_lookup (substitution_variables, match);
++
++        if (value != NULL) {
++                g_string_append (result, value);
++        } else {
++                char *original_string;
++
++                original_string = g_match_info_fetch (match_info, 0);
++                g_string_append (result, original_string);
++                g_free (original_string);
++        }
++        g_free (match);
++
++        return FALSE;
++}
++
++static char *
++apply_substitutions (const char *value,
++                     GHashTable *substitution_variables)
++{
++        GRegex *expression;
++        char *expanded_string;
++
++        expression = g_regex_new ("\\$([^[:space:]]+)", 0, 0, NULL);
++        expanded_string = g_regex_replace_eval (expression,
++                                                value,
++                                                -1, 0, 0,
++                                                (GRegexEvalCallback)
++                                                on_substitution_match,
++                                                substitution_variables,
++                                                NULL);
++
++        if (expanded_string == NULL) {
++                expanded_string = g_strdup (value);
++        }
++
++        return expanded_string;
++}
++
++static GHashTable *
++get_evaluated_parameter_map (GHashTable    *parameters,
++                             GHashTable    *substitution_variables)
++{
++        GHashTable *evaluated_parameters;
++        GHashTableIter iter;
++        gpointer key, value;
++
++        evaluated_parameters = g_hash_table_new_full (g_str_hash, g_str_equal,
++                                                      (GDestroyNotify) g_free,
++                                                      (GDestroyNotify) g_free);
++
++        g_hash_table_iter_init (&iter, parameters);
++        while (g_hash_table_iter_next (&iter, &key, &value)) {
++                char *expanded_string;
++
++                expanded_string = apply_substitutions ((char *) value,
++                                                       substitution_variables);
++
++                g_hash_table_insert (evaluated_parameters,
++                                     g_strdup ((char *) key),
++                                     expanded_string);
++        }
++
++        return evaluated_parameters;
++}
++
++static void
++request_session (gpointer key,
++                 gpointer value,
++                 gpointer user_data)
++{
++        CkSeat      *seat = CK_SEAT (user_data);
++        CkSession   *session = (CkSession *) value;
++
++        g_debug ("CkSeat: Request session");
++        ck_session_set_ever_open (session, FALSE, NULL);
++        ck_session_set_under_request (session, FALSE, NULL);
++        ck_seat_request_open_session (seat, session, NULL);
++}
++
++static void
++append_hash_table_to_dbus_message_iter (DBusMessageIter *iter,
++                                        GHashTable      *hash_table)
++{
++        GHashTableIter hash_table_iter;
++        gpointer key, value;
++        DBusMessageIter array_iter;
++
++        dbus_message_iter_open_container (iter,
++                                          DBUS_TYPE_ARRAY,
++                                          DBUS_DICT_ENTRY_BEGIN_CHAR_AS_STRING
++                                          DBUS_TYPE_STRING_AS_STRING
++                                          DBUS_TYPE_STRING_AS_STRING
++                                          DBUS_DICT_ENTRY_END_CHAR_AS_STRING,
++                                          &array_iter);
++
++
++        g_hash_table_iter_init (&hash_table_iter, hash_table);
++        while (g_hash_table_iter_next (&hash_table_iter, &key, &value)) {
++                DBusMessageIter dict_iter;
++
++                dbus_message_iter_open_container (&array_iter,
++                                                  DBUS_TYPE_DICT_ENTRY,
++                                                  NULL,
++                                                  &dict_iter);
++
++                dbus_message_iter_append_basic (&dict_iter, DBUS_TYPE_STRING, &key);
++                dbus_message_iter_append_basic (&dict_iter, DBUS_TYPE_STRING, &value);
++                dbus_message_iter_close_container (&array_iter, &dict_iter);
++        }
++        dbus_message_iter_close_container (iter, &array_iter);
++}
++
++static void
++emit_session_open_request (CkSeat     *seat,
++                          const char *ssid,
++                          const char *session_type,
++                          const char *display_template_name,
++                          GHashTable *display_variables,
++                          const char *display_type,
++                          GHashTable *evaluated_parameters)
++{
++        DBusMessage    *message;
++        DBusConnection *connection;
++        DBusMessageIter iter;
++
++        if (!ck_seat_is_managed (seat))
++                return;
++
++        g_debug ("CkSeat: Open Session Request");
++
++        message = dbus_message_new_signal (seat->priv->id,
++                                           "org.freedesktop.ConsoleKit.Seat",
++                                           "OpenSessionRequest");
++
++        dbus_message_set_destination (message,
++                                      dbus_g_proxy_get_bus_name (seat->priv->manager_proxy));
++
++        dbus_message_iter_init_append (message, &iter);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &ssid);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &session_type);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_template_name);
++        append_hash_table_to_dbus_message_iter (&iter, display_variables);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_STRING, &display_type);
++        append_hash_table_to_dbus_message_iter (&iter, evaluated_parameters);
++
++        connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
++        dbus_connection_send (connection, message, NULL);
++        dbus_connection_unref (connection);
++        dbus_message_unref (message);
++}
++
++gboolean
++ck_seat_request_open_session (CkSeat                *seat,
++                              CkSession             *session,
++                              GError               **error)
++{
++        char        *ssid;
++        char        *type;
++        CkDisplayTemplate *display_template;
++        GHashTable  *display_variables;
++        GHashTable  *display_parameters;
++        GHashTable  *evaluated_parameters;
++        gboolean    is_open;
++        gboolean    ever_open;
++        gboolean    under_request;
++
++        g_debug ("CkSeat: Request Open Session");
++
++        ck_session_is_open (session, &is_open, NULL);
++
++        if (is_open) {
++                g_debug ("CkSeat: Is Open");
++                return TRUE;
++        }
++
++        ck_session_get_under_request (session, &under_request, NULL);
++        if (under_request) {
++                g_debug ("CkSeat: Is Under");
++                return TRUE;
++        }
++
++        ck_session_set_under_request (session, TRUE, NULL);
++
++        ck_session_get_ever_open (session, &ever_open, NULL);
++
++        display_template = ck_session_get_display_template (session);
++
++        if (display_template == NULL) {
++                g_debug ("CkSeat: Is Display Template");
++                return TRUE;
++        }
++
++        ck_session_get_session_type (session, &type, NULL);
++
++        if (type == NULL) {
++                g_debug ("CkSeat: Type Is NULL");
++                g_object_unref (display_template);
++                return TRUE;
++        }
++
++        /* substitute $display $vt etc */
++        display_variables = ck_session_get_display_variables (session);
++        display_parameters = ck_display_template_get_parameters (display_template);
++
++        if (display_parameters == NULL) {
++                g_debug ("CkSeat: Display Parms Are NULL");
++                g_free (type);
++                g_object_unref (display_template);
++                g_hash_table_unref (display_variables);
++                return TRUE;
++        }
++
++        if (!ever_open) {
++                evaluated_parameters = get_evaluated_parameter_map (display_parameters, display_variables);
++        } else {
++                evaluated_parameters = get_evaluated_parameter_map (display_parameters, NULL);
++        }
++
++        g_hash_table_unref (display_parameters);
++
++        ck_session_get_id (session, &ssid, NULL);
++
++        g_debug ("CkSeat: Emitting Open Request");
++        emit_session_open_request (seat, ssid, type,
++                                   ck_display_template_get_name (display_template),
++                                   display_variables,
++                                   ck_display_template_get_type_string (display_template),
++                                   evaluated_parameters);
++
++        g_free (ssid);
++        g_free (type);
++        g_hash_table_unref (evaluated_parameters);
++        g_hash_table_unref (display_variables);
++        g_object_unref (display_template);
++
++        return TRUE;
++}
++
++static void
++on_seat_manager_disappeared (CkSeat *seat)
++{
++        g_debug ("CkSeat: Seat Manager Disappeared.");
++
++        g_signal_handlers_disconnect_by_func (seat->priv->manager_proxy,
++                                              G_CALLBACK (on_seat_manager_disappeared),
++                                              seat);
++        g_object_unref (seat->priv->manager_proxy);
++        seat->priv->manager_proxy = NULL;
++
++        /* FIXME: should probably emit a signal so a new display manager
++         * knows that the seat is now unmanaged
++         *
++         * (maybe only if its kind is static?)
++         */
++}
++
++gboolean
++ck_seat_manage (CkSeat                *seat,
++                DBusGMethodInvocation *context)
++{
++        char *sender_name;
++
++        g_debug ("CkSeat: Seat manage.");
++        sender_name = dbus_g_method_get_sender (context);
++
++        if (seat->priv->manager_proxy != NULL) {
++                GError *error;
++                const char   *existing_manager_name;
++
++                existing_manager_name = dbus_g_proxy_get_bus_name (seat->priv->manager_proxy);
++
++                if (existing_manager_name == NULL) {
++                        g_warning ("Seat manager lacks bus unique name");
++                        existing_manager_name = "<unknown>";
++                }
++
++                error = g_error_new (CK_SEAT_ERROR,
++                                     CK_SEAT_ERROR_GENERAL,
++                                     _("Seat already managed (by '%s')"),
++                                     existing_manager_name);
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++                return FALSE;
++        }
++
++        /* FIXME: We pass in a bogus object path (the path we use on this side of
++         * the pipe) and interface here.
++         *
++         * We only use the proxy to watch for when the other side disappears, not
++         * for communicating with it.  All communication is one-way using signals.
++         */
++        seat->priv->manager_proxy = dbus_g_proxy_new_for_name (seat->priv->connection,
++
++                                                               sender_name,
++                                                               seat->priv->id,
++                                                               "org.freedesktop.ConsoleKit.SeatManager");
++        g_free (sender_name);
++
++        g_signal_connect_swapped (seat->priv->manager_proxy,
++                                  "destroy",
++                                  G_CALLBACK (on_seat_manager_disappeared),
++                                  seat);
++
++        g_hash_table_foreach (seat->priv->sessions, request_session, seat);
++
++        dbus_g_method_return (context);
++        return TRUE;
++}
++
++gboolean
++ck_seat_unmanage (CkSeat                *seat,
++                  DBusGMethodInvocation *context)
++{
++        GError *error;
++        const char   *existing_manager_name;
++        char *sender_name;
++
++        g_debug ("CkSeat: Seat unmanage.");
++        if (seat->priv->manager_proxy == NULL) {
++                GError *error;
++
++                error = g_error_new (CK_SEAT_ERROR,
++                                     CK_SEAT_ERROR_GENERAL,
++                                     _("Seat not managed"));
++
++                dbus_g_method_return_error (context, error);
++                g_error_free (error);
++                return FALSE;
++        }
++
++        sender_name = dbus_g_method_get_sender (context);
++        existing_manager_name = dbus_g_proxy_get_bus_name (seat->priv->manager_proxy);
++
++        if (strcmp (sender_name, existing_manager_name) != 0) {
++
++            error = g_error_new (CK_SEAT_ERROR,
++                                 CK_SEAT_ERROR_GENERAL,
++                                 _("Seat managed by '%s' not '%s'"),
++                                 existing_manager_name,
++                                 sender_name);
++
++            dbus_g_method_return_error (context, error);
++            g_error_free (error);
++
++            return FALSE;
++        }
++
++        on_seat_manager_disappeared (seat);
++
++        dbus_g_method_return (context);
++        return TRUE;
++}
++
++void
++ck_seat_request_removal (CkSeat *seat)
++{
++        DBusMessage    *message;
++        DBusConnection *connection;
++
++        g_return_if_fail (CK_IS_SEAT (seat));
++        g_return_if_fail (ck_seat_is_managed (seat));
++
++        g_debug ("CkSeat: Seat request removal.");
++
++        message = dbus_message_new_signal (seat->priv->id,
++                                           "org.freedesktop.ConsoleKit.Seat",
++                                           "RemoveRequest");
++
++        dbus_message_set_destination (message,
++                                      dbus_g_proxy_get_bus_name (seat->priv->manager_proxy));
++
++        connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
++        dbus_connection_send (connection, message, NULL);
++        dbus_connection_unref (connection);
++        dbus_message_unref (message);
++}
++
++static gboolean
+ match_session_display_device (const char *key,
+                               CkSession  *session,
+                               const char *display_device)
+@@ -314,6 +729,8 @@ match_session_display_device (const char
+         device = NULL;
+         ret = FALSE;
+ 
++        g_debug ("CkSeat: Session display device.");
++
+         if (session == NULL) {
+                 goto out;
+         }
+@@ -486,6 +903,8 @@ change_active_session (CkSeat    *seat,
+         char      *ssid;
+         CkSession *old_session;
+ 
++        g_debug ("CkSeat: Change active session.");
++
+         if (seat->priv->active_session == session) {
+                 return;
+         }
+@@ -515,7 +934,10 @@ change_active_session (CkSeat    *seat,
+          * must be sent when the database dump is finished it is
+          * important that the '-full' signalled is emitted first. */
+ 
+-        g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED_FULL], 0, old_session, session);
++        if (CK_IS_SESSION (old_session)) {
++                g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED_FULL], 0, old_session, session);
++        }
++
+         g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED], 0, ssid);
+ 
+         if (old_session != NULL) {
+@@ -526,6 +948,47 @@ change_active_session (CkSeat    *seat,
+ }
+ 
+ static void
++find_possible_session_to_activate (CkSeat *seat)
++{
++        GHashTableIter iter;
++        gpointer       key, value;
++        gboolean       is_open;
++        char          *session_type = NULL;
++        CkSession     *login_session = NULL;
++
++        g_debug ("CkSeat: Find possible session to activate");
++        g_hash_table_iter_init (&iter, seat->priv->sessions);
++        while (g_hash_table_iter_next (&iter, &key, &value)) {
++
++                ck_session_is_open (value, &is_open, NULL);
++
++                if (is_open) {
++                        login_session = NULL;
++                        change_active_session (seat, value);
++                        break;
++                }
++
++                ck_session_get_session_type (value, &session_type, NULL);
++
++                g_debug ("CkSeat: Session Type %s", session_type);
++
++                if (IS_STR_SET (session_type) &&
++                    g_str_equal (session_type, "LoginWindow")) {
++                        login_session = value;
++                        g_debug ("CkSeat: Setting login_session");
++                        g_free (session_type);
++                }
++        }
++
++        if (login_session != NULL) {
++                g_debug ("CkSeat: Login Session is not NULL");
++                ck_session_set_ever_open (login_session, FALSE, NULL);
++                ck_seat_request_open_session (seat, login_session, NULL);
++        }
++
++}
++
++static void
+ update_active_vt (CkSeat *seat,
+                   guint   num)
+ {
+@@ -537,7 +1000,12 @@ update_active_vt (CkSeat *seat,
+         g_debug ("Active device: %s", device);
+ 
+         session = find_session_for_display_device (seat, device);
+-        change_active_session (seat, session);
++
++        if (session == NULL) {
++                find_possible_session_to_activate (seat);
++        } else {
++                change_active_session (seat, session);
++        }
+ 
+         g_free (device);
+ }
+@@ -547,12 +1015,18 @@ maybe_update_active_session (CkSeat *sea
+ {
+         guint num;
+ 
+-        if (seat->priv->kind != CK_SEAT_KIND_STATIC) {
+-                return;
+-        }
+-
+-        if (ck_vt_monitor_get_active (seat->priv->vt_monitor, &num, NULL)) {
+-                update_active_vt (seat, num);
++        switch (seat->priv->kind){
++        case CK_SEAT_KIND_STATIC:
++                if (ck_vt_monitor_get_active (seat->priv->vt_monitor,
++                                              &num, NULL)) {
++                        update_active_vt (seat, num);
++                }
++                break;
++        case CK_SEAT_KIND_DYNAMIC:
++                find_possible_session_to_activate (seat);
++                break;
++        default:
++                break;
+         }
+ }
+ 
+@@ -561,6 +1035,7 @@ session_activate (CkSession             
+                   DBusGMethodInvocation *context,
+                   CkSeat                *seat)
+ {
++        g_debug ("CkSeat: Session activate.");
+         _seat_activate_session (seat, session, context);
+ 
+         /* always return TRUE to indicate that the signal was handled */
+@@ -584,6 +1059,8 @@ ck_seat_remove_session (CkSeat         *
+         ssid = NULL;
+         ck_session_get_id (session, &ssid, NULL);
+ 
++        g_debug ("CkSeat: Removing session '%s'", ssid);
++
+         /* Need to get the original key/value */
+         res = g_hash_table_lookup_extended (seat->priv->sessions,
+                                             ssid,
+@@ -628,18 +1105,118 @@ ck_seat_remove_session (CkSeat         *
+         return ret;
+ }
+ 
++static void
++emit_session_close_request (CkSeat     *seat,
++                            const char *ssid)
++{
++        DBusMessage    *message;
++        DBusConnection *connection;
++        DBusMessageIter iter;
++
++        g_debug ("CkSeat: Emit Session Close request");
++
++        message = dbus_message_new_signal (seat->priv->id,
++                                           "org.freedesktop.ConsoleKit.Seat",
++                                           "CloseSessionRequest");
++
++        dbus_message_set_destination (message,
++                                      dbus_g_proxy_get_bus_name (seat->priv->manager_proxy));
++
++        dbus_message_iter_init_append (message, &iter);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &ssid);
++
++        connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
++        dbus_connection_send (connection, message, NULL);
++        dbus_connection_unref (connection);
++        dbus_message_unref (message);
++}
++
++gboolean
++ck_seat_request_close_session (CkSeat                *seat,
++                               CkSession             *session,
++                               GError               **error)
++{
++        char      *ssid;
++
++        g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++        g_return_val_if_fail (ck_seat_is_managed (seat), FALSE);
++
++        g_debug ("CkSeat: Request close session.");
++        ck_session_get_id (session, &ssid, NULL);
++
++        emit_session_close_request (seat, ssid);
++
++        g_free (ssid);
++
++        return FALSE;
++}
++
++gboolean
++ck_seat_no_respawn (CkSeat                *seat,
++                    CkSession             *session,
++                    GError               **error)
++{
++        DBusMessage    *message;
++        DBusConnection *connection;
++        DBusMessageIter iter;
++        char           *ssid;
++
++        g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++        g_return_val_if_fail (ck_seat_is_managed (seat), FALSE);
++
++        g_debug ("CkSeat: No Respawn.");
++        ck_session_get_id (session, &ssid, NULL);
++
++        message = dbus_message_new_signal (seat->priv->id,
++                                           "org.freedesktop.ConsoleKit.Seat",
++                                           "NoRespawn");
++
++        dbus_message_set_destination (message,
++                                      dbus_g_proxy_get_bus_name (seat->priv->manager_proxy));
++
++        dbus_message_iter_init_append (message, &iter);
++        dbus_message_iter_append_basic (&iter, DBUS_TYPE_OBJECT_PATH, &ssid);
++
++        connection = dbus_bus_get (DBUS_BUS_SYSTEM, NULL);
++        dbus_connection_send (connection, message, NULL);
++        dbus_connection_unref (connection);
++        dbus_message_unref (message);
++
++        g_free (ssid);
++
++        return FALSE;
++}
++
+ gboolean
+ ck_seat_add_session (CkSeat         *seat,
+                      CkSession      *session,
+                      GError        **error)
+ {
+         char *ssid;
++        GHashTableIter iter;
++        gpointer key, value;
++        gboolean found;
+ 
+         g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+ 
++        g_debug ("CkSeat: Add session.");
+         ck_session_get_id (session, &ssid, NULL);
+ 
+-        g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session));
++        found = FALSE;
++        g_hash_table_iter_init (&iter, seat->priv->sessions);
++        while (g_hash_table_iter_next (&iter, &key, &value)) {
++                if (g_str_equal ((gchar *)key, ssid)) {
++                        found = TRUE;
++                        break;
++                }
++        }
++
++        if (! found)
++                g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session));
++        else
++                g_object_ref (session);
+ 
+         ck_session_set_seat_id (session, seat->priv->id, NULL);
+ 
+@@ -654,7 +1231,13 @@ ck_seat_add_session (CkSeat         *sea
+         g_signal_emit (seat, signals [SESSION_ADDED_FULL], 0, session);
+         g_signal_emit (seat, signals [SESSION_ADDED], 0, ssid);
+ 
+-        maybe_update_active_session (seat);
++        if (ck_seat_is_managed (seat)) {
++                g_debug ("CkSeat: Seat is managed.  Request open session");
++                ck_seat_request_open_session (seat, session, NULL);
++        } else {
++                g_debug ("CkSeat: Seat is not managed.  Maybe update active session");
++                maybe_update_active_session (seat);
++        }
+ 
+         g_free (ssid);
+ 
+@@ -742,6 +1325,20 @@ ck_seat_get_kind (CkSeat        *seat,
+ }
+ 
+ gboolean
++ck_seat_get_type_string (CkSeat                *seat,
++                         char                 **type,
++                         GError               **error)
++{
++        g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
++
++        if (type != NULL) {
++                *type = g_strdup (seat->priv->type);
++        }
++
++        return TRUE;
++}
++
++gboolean
+ ck_seat_get_id (CkSeat         *seat,
+                 char          **id,
+                 GError        **error)
+@@ -771,6 +1368,7 @@ ck_seat_register (CkSeat *seat)
+         GError *error = NULL;
+ 
+         error = NULL;
++        g_debug ("CkSeat: Register seat.");
+         seat->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+         if (seat->priv->connection == NULL) {
+                 if (error != NULL) {
+@@ -858,6 +1456,14 @@ _ck_seat_set_kind (CkSeat    *seat,
+ }
+ 
+ static void
++_ck_seat_set_type_string (CkSeat         *seat,
++                          const char     *type)
++{
++        g_free (seat->priv->type);
++        seat->priv->type = g_strdup (type);
++}
++
++static void
+ ck_seat_set_property (GObject            *object,
+                       guint               prop_id,
+                       const GValue       *value,
+@@ -874,6 +1480,9 @@ ck_seat_set_property (GObject           
+         case PROP_KIND:
+                 _ck_seat_set_kind (self, g_value_get_enum (value));
+                 break;
++        case PROP_TYPE:
++                _ck_seat_set_type_string (self, g_value_get_string (value));
++                break;
+         default:
+                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                 break;
+@@ -895,7 +1504,10 @@ ck_seat_get_property (GObject    *object
+                 g_value_set_string (value, self->priv->id);
+                 break;
+         case PROP_KIND:
+-                g_value_set_string (value, self->priv->id);
++                g_value_set_enum (value, self->priv->kind);
++                break;
++        case PROP_TYPE:
++                g_value_set_string (value, self->priv->type);
+                 break;
+         default:
+                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+@@ -1007,6 +1619,47 @@ ck_seat_class_init (CkSeatClass *klass)
+                                                  g_cclosure_marshal_VOID__BOXED,
+                                                  G_TYPE_NONE,
+                                                  1, CK_TYPE_DEVICE);
++        signals [REMOVE_REQUEST] = g_signal_new ("remove-request",
++                                                  G_TYPE_FROM_CLASS (object_class),
++                                                  G_SIGNAL_RUN_LAST,
++                                                  G_STRUCT_OFFSET (CkSeatClass, remove_request),
++                                                  NULL,
++                                                  NULL,
++                                                  g_cclosure_marshal_VOID__VOID,
++                                                  G_TYPE_NONE, 0);
++        signals [OPEN_SESSION_REQUEST] = g_signal_new ("open-session-request",
++                                                 G_TYPE_FROM_CLASS (object_class),
++                                                 G_SIGNAL_RUN_LAST,
++                                                 G_STRUCT_OFFSET (CkSeatClass, open_session_request),
++                                                 NULL,
++                                                 NULL,
++                                                 ck_marshal_VOID__STRING_STRING_STRING_POINTER_STRING_POINTER,
++                                                 G_TYPE_NONE,
++                                                 6,
++                                                 DBUS_TYPE_G_OBJECT_PATH,
++                                                 G_TYPE_STRING,
++                                                 G_TYPE_STRING,
++                                                 CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE,
++                                                 G_TYPE_STRING,
++                                                 CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE,
++                                                 G_TYPE_INVALID);
++        signals [CLOSE_SESSION_REQUEST] = g_signal_new ("close-session-request",
++                                                  G_TYPE_FROM_CLASS (object_class),
++                                                  G_SIGNAL_RUN_LAST,
++                                                  G_STRUCT_OFFSET (CkSeatClass, close_session_request),
++                                                  NULL,
++                                                  NULL,
++                                                  g_cclosure_marshal_VOID__VOID,
++                                                  G_TYPE_NONE,
++                                                  1, DBUS_TYPE_G_OBJECT_PATH);
++        signals [NO_RESPAWN] = g_signal_new ("no-respawn",
++                                                  G_TYPE_FROM_CLASS (object_class),
++                                                  G_SIGNAL_RUN_LAST,
++                                                  G_STRUCT_OFFSET (CkSeatClass, no_respawn),
++                                                  NULL,
++                                                  NULL,
++                                                  g_cclosure_marshal_VOID__VOID,
++                                                  G_TYPE_NONE, 0);
+ 
+         g_object_class_install_property (object_class,
+                                          PROP_ID,
+@@ -1024,6 +1677,13 @@ ck_seat_class_init (CkSeatClass *klass)
+                                                             CK_SEAT_KIND_DYNAMIC,
+                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ 
++        g_object_class_install_property (object_class,
++                                         PROP_TYPE,
++                                         g_param_spec_string ("type",
++                                                              "type",
++                                                              "type",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+         g_type_class_add_private (klass, sizeof (CkSeatPrivate));
+ 
+         dbus_g_object_type_install_info (CK_TYPE_SEAT, &dbus_glib_ck_seat_object_info);
+@@ -1039,6 +1699,7 @@ ck_seat_init (CkSeat *seat)
+                                                       g_free,
+                                                       (GDestroyNotify) g_object_unref);
+         seat->priv->devices = g_ptr_array_new ();
++        seat->priv->manager_proxy = NULL;
+ }
+ 
+ static void
+@@ -1064,28 +1725,32 @@ ck_seat_finalize (GObject *object)
+         g_ptr_array_free (seat->priv->devices, TRUE);
+         g_hash_table_destroy (seat->priv->sessions);
+         g_free (seat->priv->id);
++        g_free (seat->priv->type);
+ 
+         G_OBJECT_CLASS (ck_seat_parent_class)->finalize (object);
+ }
+ 
+ CkSeat *
+ ck_seat_new (const char *sid,
+-             CkSeatKind  kind)
++             CkSeatKind  kind,
++             const char *type)
+ {
+         GObject *object;
+ 
+         object = g_object_new (CK_TYPE_SEAT,
+                                "id", sid,
+                                "kind", kind,
++                               "type", type,
+                                NULL);
+ 
+         return CK_SEAT (object);
+ }
+ 
+ CkSeat *
+-ck_seat_new_with_devices (const char *sid,
+-                          CkSeatKind  kind,
+-                          GPtrArray  *devices)
++ck_seat_new_with_devices_and_sessions (const char *sid,
++                                       CkSeatKind  kind,
++                                       GPtrArray  *devices,
++                                       GPtrArray  *sessions)
+ {
+         GObject *object;
+         int      i;
+@@ -1100,27 +1765,62 @@ ck_seat_new_with_devices (const char *si
+                         ck_seat_add_device (CK_SEAT (object), g_ptr_array_index (devices, i), NULL);
+                 }
+         }
++        if (sessions != NULL) {
++                for (i = 0; i < sessions->len; i++) {
++                        ck_seat_add_session (CK_SEAT (object), g_ptr_array_index (sessions, i), NULL);
++                }
++        }
++
+ 
+         return CK_SEAT (object);
+ }
+ 
++static char *
++generate_static_session_id (const char *sid,
++                            const char *session_name)
++{
++        const char *seat_name;
++        char *ssid;
++
++        seat_name = strrchr (sid, '/');
++
++        if (seat_name == NULL) {
++                g_warning ("Seat id '%s' lacks a /", sid);
++                seat_name = sid;
++        } else {
++                seat_name++;
++        }
++
++        ssid = g_strdup_printf ("%s/Session%s%s",
++                                CK_DBUS_PATH, seat_name,
++                                session_name);
++
++        return ssid;
++}
++
+ CkSeat *
+-ck_seat_new_from_file (const char *sid,
++ck_seat_new_from_file (char       **sid,
+                        const char *path)
+ {
+-        GKeyFile  *key_file;
+-        gboolean   res;
+-        GError    *error;
+-        char      *group;
+-        CkSeat    *seat;
+-        gboolean   hidden;
+-        GPtrArray *devices;
+-        char     **device_list;
+-        gsize      ndevices;
+-        gsize      i;
++        GKeyFile      *key_file;
++        gboolean       res;
++        GError        *error;
++        char          *group;
++        CkSeat        *seat;
++        char          *read_sid;
++        gboolean       hidden;
++        GPtrArray     *sessions;
++        char         **session_list;
++        gsize          nsessions;
++        GPtrArray     *devices;
++        char         **device_list;
++        gsize          ndevices;
++        gsize          i;
+ 
+         seat = NULL;
+ 
++        g_debug ("CkSeat: New seat from file.");
++
+         key_file = g_key_file_new ();
+         error = NULL;
+         res = g_key_file_load_from_file (key_file,
+@@ -1145,9 +1845,52 @@ ck_seat_new_from_file (const char *sid,
+                 goto out;
+         }
+ 
++        read_sid = g_key_file_get_string (key_file, group, "ID", NULL);
++        if (IS_STR_SET (read_sid)) {
++                g_free (*sid);
++                *sid = g_strdup_printf ("%s/%s", CK_DBUS_PATH, read_sid);
++        } else {
++                g_free (read_sid);
++        }
++
++        session_list = g_key_file_get_string_list (key_file, group, "Sessions", &nsessions, NULL);
++
++        sessions = g_ptr_array_sized_new (nsessions);
++
++        for (i = 0; i < nsessions; i++) {
++                char *path;
++                char *file;
++                char *ssid;
++                CkSession *session;
++
++                file = g_strconcat (session_list[i], ".session", NULL);
++                path = g_build_filename (CK_SESSION_DIR, file, NULL);
++                g_free (file);
++
++                /* FIXME: we should probably use the same naming pool as
++                 * sessions generated from ck-manager.  We mangle the name
++                 * here so we don't clash with names from ck-manager
++                 */
++                ssid = generate_static_session_id (*sid, session_list[i]);
++
++                session = ck_session_new_from_file (ssid, path);
++
++                if (session == NULL) {
++                        g_warning ("Unable to load session from file %s", path);
++                        g_free (path);
++                        continue;
++                }
++                g_free (path);
++                ck_session_set_seat_id (session, *sid, NULL);
++
++                g_ptr_array_add (sessions, session);
++        }
++
++        g_strfreev (session_list);
++
+         device_list = g_key_file_get_string_list (key_file, group, "Devices", &ndevices, NULL);
+ 
+-        g_debug ("Creating seat %s with %zd devices", sid, ndevices);
++        g_debug ("CkSeat: Creating seat %s with %zd devices", *sid, ndevices);
+ 
+         devices = g_ptr_array_sized_new (ndevices);
+ 
+@@ -1176,11 +1919,12 @@ ck_seat_new_from_file (const char *sid,
+                 g_strfreev (split);
+         }
+         g_strfreev (device_list);
+-        g_free (group);
+ 
+-        seat = ck_seat_new_with_devices (sid, CK_SEAT_KIND_STATIC, devices);
++        seat = ck_seat_new_with_devices_and_sessions (*sid, CK_SEAT_KIND_STATIC, devices, sessions);
+         g_ptr_array_free (devices, TRUE);
+ 
++        g_free (group);
++
+ out:
+ 
+         g_key_file_free (key_file);
+@@ -1348,10 +2092,15 @@ ck_seat_dump (CkSeat   *seat,
+ 
+                 error = NULL;
+                 if (! ck_session_get_id (seat->priv->active_session, &session_id, &error)) {
+-                        g_warning ("Cannot get session id for active session on seat %s: %s",
+-                                   seat->priv->id,
+-                                   error->message);
+-                        g_error_free (error);
++                        if (error) {
++                                g_warning ("Cannot get session id for active session on seat %s: %s",
++                                           seat->priv->id,
++                                           error->message);
++                                g_error_free (error);
++                        } else {
++                                g_warning ("Cannot get session id for active session on seat %s",
++                                           seat->priv->id);
++                        }
+                 } else {
+                         g_key_file_set_string (key_file,
+                                                group_name,
+@@ -1363,3 +2112,24 @@ ck_seat_dump (CkSeat   *seat,
+ 
+         g_free (group_name);
+ }
++
++gboolean
++ck_seat_is_managed (CkSeat *seat)
++{
++        return seat->priv->manager_proxy != NULL;
++}
++
++CkSession *
++ck_seat_get_session (CkSeat                *seat,
++                     const char            *ssid)
++{
++        CkSession *session;
++
++        session = g_hash_table_lookup (seat->priv->sessions, ssid);
++
++        if (session == NULL) {
++                return NULL;
++        }
++
++        return g_object_ref (session);
++}
+diff --git a/src/ck-seat.h b/src/ck-seat.h
+index fb9a955..6276021 100644
+--- a/src/ck-seat.h
++++ b/src/ck-seat.h
+@@ -47,6 +47,18 @@ typedef struct
+ {
+         GObjectClass   parent_class;
+ 
++        void          (* remove_request)         (CkSeat      *seat);
++        void          (* open_session_request)   (CkSeat      *seat,
++                                                  const char  *ssid,
++                                                  const char  *session_type,
++                                                  const char  *display_template_name,
++                                                  GHashTable  *display_variables,
++                                                  const char  *display_type,
++                                                  GHashTable  *parameters);
++        void          (* close_session_request)  (CkSeat      *seat,
++                                                  const char  *ssid);
++        void          (* no_respawn)             (CkSeat      *seat,
++                                                  const char  *ssid);
+         void          (* active_session_changed) (CkSeat      *seat,
+                                                   const char  *ssid);
+         void          (* session_added)          (CkSeat      *seat,
+@@ -57,6 +69,11 @@ typedef struct
+                                                   GValueArray *device);
+         void          (* device_removed)         (CkSeat      *seat,
+                                                   GValueArray *device);
++        void          (* session_to_add)         (CkSeat      *seat,
++                                                  gboolean     is_dynamic,
++                                                  const char  *command);
++        void          (* session_to_remove)      (CkSeat      *seat,
++                                                  int          display_number);
+ } CkSeatClass;
+ 
+ typedef enum
+@@ -84,12 +101,14 @@ typedef enum
+ GQuark              ck_seat_error_quark         (void);
+ GType               ck_seat_get_type            (void);
+ CkSeat            * ck_seat_new                 (const char            *sid,
+-                                                 CkSeatKind             kind);
+-CkSeat            * ck_seat_new_from_file       (const char            *sid,
+-                                                 const char            *path);
+-CkSeat            * ck_seat_new_with_devices    (const char            *sid,
+                                                  CkSeatKind             kind,
+-                                                 GPtrArray             *devices);
++                                                 const char            *type);
++CkSeat            * ck_seat_new_from_file       (char                 **sid,
++                                                 const char            *path);
++CkSeat            * ck_seat_new_with_devices_and_sessions    (const char            *sid,
++                                                              CkSeatKind             kind,
++                                                              GPtrArray             *devices,
++                                                              GPtrArray             *sessions);
+ 
+ gboolean            ck_seat_register            (CkSeat                *seat);
+ 
+@@ -104,18 +123,31 @@ void                ck_seat_dump        
+ gboolean            ck_seat_get_kind            (CkSeat                *seat,
+                                                  CkSeatKind            *kind,
+                                                  GError               **error);
++gboolean            ck_seat_get_type_string     (CkSeat                *seat,
++                                                 char                 **type,
++                                                 GError               **error);
+ gboolean            ck_seat_add_session         (CkSeat                *seat,
+                                                  CkSession             *session,
+                                                  GError               **error);
+ gboolean            ck_seat_remove_session      (CkSeat                *seat,
+                                                  CkSession             *session,
+                                                  GError               **error);
++gboolean            ck_seat_request_open_session (CkSeat                *seat,
++                                                  CkSession             *session,
++                                                  GError               **error);
++gboolean            ck_seat_request_close_session (CkSeat                *seat,
++                                                   CkSession             *session,
++                                                   GError               **error);
+ gboolean            ck_seat_add_device          (CkSeat                *seat,
+                                                  GValueArray           *device,
+                                                  GError               **error);
+ gboolean            ck_seat_remove_device       (CkSeat                *seat,
+                                                  GValueArray           *device,
+                                                  GError               **error);
++gboolean            ck_seat_is_managed          (CkSeat                *seat);
++CkSession          *ck_seat_get_session         (CkSeat                *seat,
++                                                 const char            *ssid);
++void                ck_seat_request_removal     (CkSeat                *seat);
+ 
+ /* exported methods */
+ gboolean            ck_seat_get_id                (CkSeat                *seat,
+@@ -137,6 +169,14 @@ gboolean            ck_seat_can_activate
+ gboolean            ck_seat_activate_session      (CkSeat                *seat,
+                                                    const char            *ssid,
+                                                    DBusGMethodInvocation *context);
++gboolean            ck_seat_manage                (CkSeat                *seat,
++                                                   DBusGMethodInvocation *context);
++gboolean            ck_seat_unmanage              (CkSeat                *seat,
++                                                   DBusGMethodInvocation *context);
++
++gboolean            ck_seat_no_respawn            (CkSeat                *seat,
++                                                   CkSession             *session,
++                                                   GError               **error);
+ 
+ G_END_DECLS
+ 
+diff --git a/src/ck-session-leader.c b/src/ck-session-leader.c
+index 3702602..908d2bb 100644
+--- a/src/ck-session-leader.c
++++ b/src/ck-session-leader.c
+@@ -238,6 +238,7 @@ static struct {
+         { "x11-display",        add_param_string },
+         { "remote-host-name",   add_param_string },
+         { "session-type",       add_param_string },
++        { "display-type",       add_param_string },
+         { "is-local",           add_param_boolean },
+         { "unix-user",          add_param_int },
+ };
+diff --git a/src/ck-session.c b/src/ck-session.c
+index d8db9dd..0354dd5 100644
+--- a/src/ck-session.c
++++ b/src/ck-session.c
+@@ -41,6 +41,7 @@
+ #include "ck-session-glue.h"
+ #include "ck-marshal.h"
+ #include "ck-run-programs.h"
++#include "ck-display-template.h"
+ 
+ #define CK_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SESSION, CkSessionPrivate))
+ 
+@@ -58,6 +59,7 @@ struct CkSessionPrivate
+         char            *seat_id;
+ 
+         char            *session_type;
++        char            *display_type;
+         char            *login_session_id;
+         char            *display_device;
+         char            *x11_display_device;
+@@ -65,8 +67,15 @@ struct CkSessionPrivate
+         char            *remote_host_name;
+         guint            uid;
+ 
++        CkDisplayTemplate *display_template;
++        GHashTable      *display_variables;
++
+         gboolean         active;
+         gboolean         is_local;
++        gboolean         is_open;
++        gboolean         ever_open;
++        gboolean         under_request;
++        GMutex          *mutex_under_request;
+ 
+         GTimeVal         creation_time;
+ 
+@@ -75,6 +84,8 @@ struct CkSessionPrivate
+         gboolean         idle_hint;
+         GTimeVal         idle_since_hint;
+ 
++        gboolean         remove_on_close;
++
+         DBusGConnection *connection;
+         DBusGProxy      *bus_proxy;
+ };
+@@ -92,17 +103,24 @@ enum {
+         PROP_0,
+         PROP_ID,
+         PROP_COOKIE,
++        PROP_SEAT_ID,
+         PROP_USER,
+         PROP_UNIX_USER,
+         PROP_X11_DISPLAY,
+         PROP_X11_DISPLAY_DEVICE,
+         PROP_DISPLAY_DEVICE,
+         PROP_SESSION_TYPE,
++        PROP_DISPLAY_TYPE,
++        PROP_DISPLAY_TEMPLATE,
++        PROP_DISPLAY_VARIABLES,
+         PROP_REMOTE_HOST_NAME,
+         PROP_LOGIN_SESSION_ID,
+         PROP_IS_LOCAL,
++        PROP_IS_OPEN,
++        PROP_EVER_OPEN,
+         PROP_ACTIVE,
+         PROP_IDLE_HINT,
++        PROP_REMOVE_ON_CLOSE,
+ };
+ 
+ static guint signals [LAST_SIGNAL] = { 0, };
+@@ -128,7 +146,9 @@ static gboolean
+ register_session (CkSession *session)
+ {
+         GError *error = NULL;
++        GObject *existing_session;
+ 
++        g_debug ("CkSession: Register session.");
+         error = NULL;
+         session->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+         if (session->priv->connection == NULL) {
+@@ -144,6 +164,15 @@ register_session (CkSession *session)
+                                                               DBUS_PATH_DBUS,
+                                                               DBUS_INTERFACE_DBUS);
+ 
++        existing_session = dbus_g_connection_lookup_g_object (session->priv->connection,
++                                                              session->priv->id);
++
++        if (existing_session != NULL) {
++                g_warning ("Session '%s' was registered twice!",
++                           session->priv->id);
++                return FALSE;
++        }
++
+         dbus_g_connection_register_g_object (session->priv->connection, session->priv->id, G_OBJECT (session));
+ 
+         return TRUE;
+@@ -302,6 +331,40 @@ ck_session_set_idle_hint (CkSession     
+ }
+ 
+ gboolean
++session_set_remove_on_close (CkSession      *session,
++                             gboolean        remove_on_close,
++                             GError        **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (session->priv->remove_on_close != remove_on_close) {
++                session->priv->remove_on_close = remove_on_close;
++        }
++
++        if (session->priv->remove_on_close == TRUE)
++                g_debug ("CkSession: Setting remove on close to true.");
++        else
++                g_debug ("CkSession: Setting remove on close to false.");
++
++        return TRUE;
++}
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Session1 \
++  org.freedesktop.ConsoleKit.Session.SetRemoveOnClose boolean:TRUE
++*/
++gboolean
++ck_session_set_remove_on_close (CkSession             *session,
++                                gboolean               remove_on_close,
++                                DBusGMethodInvocation *context)
++{
++        return session_set_remove_on_close (session, remove_on_close, NULL);
++}
++
++gboolean
+ ck_session_get_idle_hint (CkSession *session,
+                           gboolean  *idle_hint,
+                           GError   **error)
+@@ -367,6 +430,7 @@ ck_session_activate (CkSession          
+ {
+         gboolean res;
+ 
++        g_debug ("CkSession: Session activate.");
+         g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+ 
+         res = FALSE;
+@@ -397,6 +461,8 @@ ck_session_set_active (CkSession      *s
+ {
+         g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+ 
++        g_debug ("CkSession: Session set active.");
++
+         if (session->priv->active != active) {
+                 session->priv->active = active;
+                 g_signal_emit (session, signals [ACTIVE_CHANGED], 0, active);
+@@ -420,6 +486,68 @@ ck_session_set_is_local (CkSession      
+ }
+ 
+ gboolean
++ck_session_set_is_open (CkSession    *session,
++                        gboolean      is_open,
++                        GError      **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (session->priv->is_open != is_open) {
++                session->priv->is_open = is_open;
++                session->priv->ever_open = TRUE;
++        }
++
++        return TRUE;
++}
++
++gboolean
++ck_session_set_ever_open (CkSession    *session,
++                          gboolean      ever_open,
++                          GError      **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (session->priv->ever_open != ever_open) {
++                session->priv->ever_open = ever_open;
++        }
++
++        return TRUE;
++}
++
++static gboolean
++timeout_for_under_request (gpointer data)
++{
++        CkSession *session = CK_SESSION (data);
++        g_mutex_lock (session->priv->mutex_under_request);
++        session->priv->under_request = FALSE;
++        g_mutex_unlock (session->priv->mutex_under_request);
++
++        g_debug ("CkSession: timeout for under request of session %s", session->priv->id);
++        return FALSE;
++}
++
++gboolean
++ck_session_set_under_request (CkSession    *session,
++                              gboolean      under_request,
++                              GError      **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        g_mutex_lock (session->priv->mutex_under_request);
++        if (!under_request) {
++                session->priv->under_request = FALSE;
++        } else {
++                if (!session->priv->under_request) {
++                        session->priv->under_request = TRUE;
++                        g_timeout_add_seconds (1, timeout_for_under_request, session);
++                }
++        }
++        g_mutex_unlock (session->priv->mutex_under_request);
++
++        return TRUE;
++}
++
++gboolean
+ ck_session_get_id (CkSession      *session,
+                    char          **id,
+                    GError        **error)
+@@ -555,6 +683,20 @@ ck_session_get_creation_time (CkSession 
+ }
+ 
+ gboolean
++ck_session_get_remove_on_close (CkSession   *session,
++                                gboolean    *remove_on_close,
++                                GError     **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (remove_on_close != NULL) {
++                *remove_on_close = session->priv->remove_on_close;
++        }
++
++        return TRUE;
++}
++
++gboolean
+ ck_session_get_session_type (CkSession      *session,
+                              char          **type,
+                              GError        **error)
+@@ -569,6 +711,20 @@ ck_session_get_session_type (CkSession  
+ }
+ 
+ gboolean
++ck_session_get_display_type (CkSession      *session,
++                             char          **type,
++                             GError        **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (type != NULL) {
++                *type = g_strdup (session->priv->display_type);
++        }
++
++        return TRUE;
++}
++
++gboolean
+ ck_session_is_active (CkSession      *session,
+                       gboolean       *active,
+                       GError        **error)
+@@ -597,6 +753,50 @@ ck_session_is_local (CkSession      *ses
+ }
+ 
+ gboolean
++ck_session_is_open (CkSession      *session,
++                    gboolean       *open,
++                    GError        **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (open != NULL) {
++                *open = session->priv->is_open;
++        }
++
++        return TRUE;
++}
++
++gboolean
++ck_session_get_ever_open (CkSession      *session,
++                          gboolean       *open,
++                          GError        **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (open != NULL) {
++                *open = session->priv->ever_open;
++        }
++
++        return TRUE;
++}
++
++gboolean
++ck_session_get_under_request (CkSession      *session,
++                              gboolean       *under_request,
++                              GError        **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (under_request != NULL) {
++                g_mutex_lock (session->priv->mutex_under_request);
++                *under_request = session->priv->under_request;
++                g_mutex_unlock (session->priv->mutex_under_request);
++        }
++
++        return TRUE;
++}
++
++gboolean
+ ck_session_set_id (CkSession      *session,
+                    const char     *id,
+                    GError        **error)
+@@ -609,6 +809,21 @@ ck_session_set_id (CkSession      *sessi
+         return TRUE;
+ }
+ 
++static void
++ck_session_set_display_variables (CkSession  *session,
++                                  GHashTable *display_variables)
++{
++        if (session->priv->display_variables != NULL) {
++                g_hash_table_unref (session->priv->display_variables);
++        }
++
++        if (display_variables != NULL) {
++                session->priv->display_variables = g_hash_table_ref (display_variables);
++        } else {
++                session->priv->display_variables = NULL;
++        }
++}
++
+ gboolean
+ ck_session_set_cookie (CkSession      *session,
+                        const char     *cookie,
+@@ -725,6 +940,54 @@ ck_session_set_session_type (CkSession  
+         return TRUE;
+ }
+ 
++gboolean
++ck_session_set_display_type (CkSession      *session,
++                             const char     *type,
++                             GError        **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        g_free (session->priv->display_type);
++        session->priv->display_type = g_strdup (type);
++
++        return TRUE;
++}
++
++static gboolean
++ck_session_set_display_template (CkSession      *session,
++                             CkDisplayTemplate  *display_template,
++                             GError        **error)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        if (session->priv->display_template != NULL) {
++                g_object_unref (session->priv->display_template);
++        }
++
++        if (display_template != NULL) {
++                session->priv->display_template = g_object_ref (display_template);
++                ck_session_set_display_type (session, ck_display_template_get_name (display_template), error);
++        } else {
++                session->priv->display_template = NULL;
++        }
++
++        return TRUE;
++}
++
++GHashTable *
++ck_session_get_display_variables (CkSession *session)
++{
++        return g_hash_table_ref (session->priv->display_variables);
++}
++
++CkDisplayTemplate *
++ck_session_get_display_template (CkSession      *session)
++{
++        g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
++
++        return g_object_ref (session->priv->display_template);
++}
++
+ static void
+ ck_session_set_property (GObject            *object,
+                          guint               prop_id,
+@@ -742,15 +1005,33 @@ ck_session_set_property (GObject        
+         case PROP_IS_LOCAL:
+                 ck_session_set_is_local (self, g_value_get_boolean (value), NULL);
+                 break;
++        case PROP_IS_OPEN:
++                ck_session_set_is_open (self, g_value_get_boolean (value), NULL);
++                break;
++        case PROP_EVER_OPEN:
++                ck_session_set_ever_open (self, g_value_get_boolean (value), NULL);
++                break;
+         case PROP_ID:
+                 ck_session_set_id (self, g_value_get_string (value), NULL);
+                 break;
+         case PROP_COOKIE:
+                 ck_session_set_cookie (self, g_value_get_string (value), NULL);
+                 break;
++        case PROP_SEAT_ID:
++                ck_session_set_seat_id (self, g_value_get_string (value), NULL);
++                break;
+         case PROP_SESSION_TYPE:
+                 ck_session_set_session_type (self, g_value_get_string (value), NULL);
+                 break;
++        case PROP_DISPLAY_TYPE:
++                ck_session_set_display_type (self, g_value_get_string (value), NULL);
++                break;
++        case PROP_DISPLAY_TEMPLATE:
++                ck_session_set_display_template (self, g_value_get_object (value), NULL);
++                break;
++        case PROP_DISPLAY_VARIABLES:
++                ck_session_set_display_variables (self, g_value_get_boxed (value));
++                break;
+         case PROP_X11_DISPLAY:
+                 ck_session_set_x11_display (self, g_value_get_string (value), NULL);
+                 break;
+@@ -775,6 +1056,9 @@ ck_session_set_property (GObject        
+         case PROP_IDLE_HINT:
+                 session_set_idle_hint_internal (self, g_value_get_boolean (value));
+                 break;
++        case PROP_REMOVE_ON_CLOSE:
++                session_set_remove_on_close (self, g_value_get_boolean (value), NULL);
++                break;
+         default:
+                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                 break;
+@@ -798,15 +1082,33 @@ ck_session_get_property (GObject    *obj
+         case PROP_IS_LOCAL:
+                 g_value_set_boolean (value, self->priv->is_local);
+                 break;
++        case PROP_IS_OPEN:
++                g_value_set_boolean (value, self->priv->is_open);
++                break;
++        case PROP_EVER_OPEN:
++                g_value_set_boolean (value, self->priv->ever_open);
++                break;
+         case PROP_ID:
+                 g_value_set_string (value, self->priv->id);
+                 break;
+         case PROP_COOKIE:
+                 g_value_set_string (value, self->priv->cookie);
+                 break;
++        case PROP_SEAT_ID:
++                g_value_set_string (value, self->priv->seat_id);
++                break;
+         case PROP_SESSION_TYPE:
+                 g_value_set_string (value, self->priv->session_type);
+                 break;
++        case PROP_DISPLAY_TYPE:
++                g_value_set_string (value, self->priv->display_type);
++                break;
++        case PROP_DISPLAY_TEMPLATE:
++                g_value_set_object (value, self->priv->display_template);
++                break;
++        case PROP_DISPLAY_VARIABLES:
++                g_value_set_boxed (value, self->priv->display_variables);
++                break;
+         case PROP_X11_DISPLAY:
+                 g_value_set_string (value, self->priv->x11_display);
+                 break;
+@@ -831,6 +1133,9 @@ ck_session_get_property (GObject    *obj
+         case PROP_IDLE_HINT:
+                 g_value_set_boolean (value, self->priv->idle_hint);
+                 break;
++        case PROP_REMOVE_ON_CLOSE:
++                g_value_set_boolean (value, self->priv->remove_on_close);
++                break;
+         default:
+                 G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+                 break;
+@@ -882,6 +1187,8 @@ session_add_activity_watch (CkSession *s
+ static void
+ session_remove_activity_watch (CkSession *session)
+ {
++        g_debug ("CkSession: Remove activity watch.");
++
+         if (session->priv->idle_monitor == NULL) {
+                 return;
+         }
+@@ -1000,6 +1307,13 @@ ck_session_class_init (CkSessionClass *k
+                                                               "cookie",
+                                                               NULL,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
++        g_object_class_install_property (object_class,
++                                         PROP_SEAT_ID,
++                                         g_param_spec_string ("seat-id",
++                                                              "seat id",
++                                                              "seat id",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ 
+         g_object_class_install_property (object_class,
+                                          PROP_SESSION_TYPE,
+@@ -1009,6 +1323,27 @@ ck_session_class_init (CkSessionClass *k
+                                                               NULL,
+                                                               G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
+         g_object_class_install_property (object_class,
++                                         PROP_DISPLAY_TYPE,
++                                         g_param_spec_string ("display-type",
++                                                              "session-type",
++                                                              "session type",
++                                                              NULL,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++        g_object_class_install_property (object_class,
++                                         PROP_DISPLAY_TEMPLATE,
++                                         g_param_spec_object ("display-template",
++                                                              "Display Template",
++                                                              "The display template",
++                                                              CK_TYPE_DISPLAY_TEMPLATE,
++                                                              G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++        g_object_class_install_property (object_class,
++                                         PROP_DISPLAY_VARIABLES,
++                                         g_param_spec_boxed ("display-variables",
++                                                             "Display Variables",
++                                                             "Display type specific variables",
++                                                             G_TYPE_HASH_TABLE,
++                                                             G_PARAM_READWRITE | G_PARAM_CONSTRUCT));
++        g_object_class_install_property (object_class,
+                                          PROP_LOGIN_SESSION_ID,
+                                          g_param_spec_string ("login-session-id",
+                                                               "login-session-id",
+@@ -1064,12 +1399,19 @@ ck_session_class_init (CkSessionClass *k
+                                                             0,
+                                                             G_PARAM_READWRITE));
+         g_object_class_install_property (object_class,
+-                                         PROP_ACTIVE,
++                                         PROP_IDLE_HINT,
+                                          g_param_spec_boolean ("idle-hint",
+                                                                NULL,
+                                                                NULL,
+                                                                FALSE,
+                                                                G_PARAM_READWRITE));
++        g_object_class_install_property (object_class,
++                                         PROP_REMOVE_ON_CLOSE,
++                                         g_param_spec_boolean ("remove-on-close",
++                                                               NULL,
++                                                               NULL,
++                                                               FALSE,
++                                                               G_PARAM_READWRITE));
+ 
+         g_type_class_add_private (klass, sizeof (CkSessionPrivate));
+ 
+@@ -1081,8 +1423,16 @@ ck_session_init (CkSession *session)
+ {
+         session->priv = CK_SESSION_GET_PRIVATE (session);
+ 
++        session->priv->display_variables = g_hash_table_new_full (g_str_hash,
++                                                                  g_str_equal,
++                                                                  (GDestroyNotify) g_free,
++                                                                  (GDestroyNotify) g_free);
++
+         /* FIXME: should we have a property for this? */
+         g_get_current_time (&session->priv->creation_time);
++
++        if (!session->priv->mutex_under_request)
++                session->priv->mutex_under_request = g_mutex_new ();
+ }
+ 
+ static void
+@@ -1105,6 +1455,7 @@ ck_session_finalize (GObject *object)
+         g_free (session->priv->cookie);
+         g_free (session->priv->seat_id);
+         g_free (session->priv->session_type);
++        g_free (session->priv->display_type);
+         g_free (session->priv->x11_display);
+         g_free (session->priv->display_device);
+         g_free (session->priv->x11_display_device);
+@@ -1114,16 +1465,138 @@ ck_session_finalize (GObject *object)
+ }
+ 
+ CkSession *
++ck_session_new_from_file (const char *ssid,
++                          const char *path)
++{
++        GKeyFile  *key_file;
++        gboolean   res;
++        GError    *error;
++        char      *group;
++        char      *name;
++        gboolean   hidden;
++        char      *type;
++        char      *display_template_string;
++        CkSession *session;
++        GHashTable *display_variables;
++        char     **type_keys;
++
++        g_debug ("CkSession: New session from file.");
++        key_file = g_key_file_new ();
++        error = NULL;
++        res = g_key_file_load_from_file (key_file,
++                                         path,
++                                         G_KEY_FILE_NONE,
++                                         &error);
++
++        if (! res) {
++                g_warning ("Unable to load sessions from file %s: %s",
++                           path, error->message);
++                g_error_free (error);
++                return NULL;
++        }
++
++        group = g_key_file_get_start_group (key_file);
++        if (group == NULL || strcmp (group, "Session Entry") != 0) {
++                g_warning ("Not a session file: %s", path);
++                g_key_file_free (key_file);
++                return NULL;
++        }
++
++        hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL);
++
++        if (hidden) {
++                g_debug ("CkSession: Session is hidden");
++                g_free (group);
++                g_key_file_free (key_file);
++                return NULL;
++        }
++
++        name = g_key_file_get_string (key_file, group, "Name", NULL);
++
++        if (name == NULL) {
++                g_warning ("Session file %s doesn't contain a name", path);
++                g_free (group);
++                g_key_file_free (key_file);
++                return NULL;
++        }
++
++        type = g_key_file_get_string (key_file, group, "Type", NULL);
++
++        if (type == NULL) {
++                g_warning ("Session file %s doesn't contain a type", path);
++                g_free (group);
++                g_key_file_free (key_file);
++                return NULL;
++        }
++
++        display_template_string = g_key_file_get_string (key_file, group, "DisplayTemplate", NULL);
++
++        if (display_template_string == NULL) {
++                g_warning ("Session file %s doesn't contain a display type", path);
++                g_free (group);
++                g_key_file_free (key_file);
++                return NULL;
++        }
++
++        /* Find a group in the key file named after the display type and stuff
++         * all its entries into a hash table for later.
++         *
++         * Those keys are for things like the display number and the vt to
++         * run X with.
++         */
++        display_variables = g_hash_table_new_full (g_str_hash, g_str_equal,
++                                                   (GDestroyNotify) g_free,
++                                                   (GDestroyNotify) g_free);
++        type_keys = g_key_file_get_keys (key_file, display_template_string, NULL, NULL);
++
++        if (type_keys != NULL) {
++                int i;
++                for (i = 0; type_keys[i] != NULL; i++) {
++                        char    *string;
++                        string = g_key_file_get_string (key_file, display_template_string, type_keys[i], NULL);
++
++                        g_hash_table_insert (display_variables, g_strdup (type_keys[i]), string);
++                }
++                g_strfreev (type_keys);
++        }
++
++        session = ck_session_new (ssid, type, display_template_string, display_variables);
++
++        g_free (display_template_string);
++        g_free (group);
++        g_free (type);
++        g_hash_table_unref (display_variables);
++
++        return session;
++}
++
++CkSession *
+ ck_session_new (const char *ssid,
+-                const char *cookie)
++                const char *type,
++                const char *display_template_string,
++                GHashTable *display_variables)
+ {
++        CkDisplayTemplate *display_template;
+         GObject *object;
+         gboolean res;
+ 
++        g_debug ("CkSession: New Session.");
++
++        display_template = ck_display_template_get_from_name (display_template_string);
++
++        if (display_template == NULL) {
++                g_warning ("Unable to load display type %s", display_template_string);
++                return NULL;
++        }
++
+         object = g_object_new (CK_TYPE_SESSION,
+                                "id", ssid,
+-                               "cookie", cookie,
++                               "session-type", type,
++                               "display-type", display_template_string,
++                               "display-template", display_template,
++                               "display-variables", display_variables,
+                                NULL);
++
+         res = register_session (CK_SESSION (object));
+         if (! res) {
+                 g_object_unref (object);
+@@ -1138,9 +1611,80 @@ ck_session_new (const char *ssid,
+                                                           G_TYPE_VALUE, \
+                                                           G_TYPE_INVALID))
+ 
++void
++ck_session_set_parameters (CkSession       *session,
++                           const GPtrArray *parameters)
++{
++        int           i;
++        GObjectClass *class;
++        GType         object_type;
++
++        object_type = CK_TYPE_SESSION;
++        class = g_type_class_ref (object_type);
++        for (i = 0; i < parameters->len; i++) {
++                gboolean    res;
++                GValue      val_struct = { 0, };
++                GValue      value = { 0, };
++                char       *prop_name;
++                GValue     *prop_val;
++                GParamSpec *pspec;
++
++                g_value_init (&val_struct, CK_TYPE_PARAMETER_STRUCT);
++                g_value_set_static_boxed (&val_struct, g_ptr_array_index (parameters, i));
++
++                res = dbus_g_type_struct_get (&val_struct,
++                                              0, &prop_name,
++                                              1, &prop_val,
++                                              G_MAXUINT);
++                if (! res) {
++                        g_debug ("CkSession: Unable to extract parameter input");
++                        goto cont;
++                }
++
++                if (prop_name == NULL) {
++                        g_debug ("CkSession: Skipping NULL parameter");
++                        goto cont;
++                }
++
++                if (strcmp (prop_name, "id") == 0
++                    || strcmp (prop_name, "cookie") == 0) {
++                        g_debug ("CkSession: Skipping restricted parameter: %s", prop_name);
++                        goto cont;
++                }
++
++                pspec = g_object_class_find_property (class, prop_name);
++                if (! pspec) {
++                        g_debug ("CkSession: Skipping unknown parameter: %s", prop_name);
++                        goto cont;
++                }
++
++                if (!(pspec->flags & G_PARAM_WRITABLE)) {
++                        g_debug ("CkSession: property '%s' is not writable", pspec->name);
++                        goto cont;
++                }
++
++                g_value_init (&value, G_PARAM_SPEC_VALUE_TYPE (pspec));
++                res = g_value_transform (prop_val, &value);
++                if (! res) {
++                        g_debug ("CkSession: unable to transform property value for '%s'", pspec->name);
++                        goto cont;
++                }
++
++                g_object_set_property (G_OBJECT (session), prop_name, &value);
++                g_value_unset (&value);
++        cont:
++                g_free (prop_name);
++                if (prop_val != NULL) {
++                        g_value_unset (prop_val);
++                        g_free (prop_val);
++                }
++        }
++
++        g_type_class_unref (class);
++}
++
+ CkSession *
+ ck_session_new_with_parameters (const char      *ssid,
+-                                const char      *cookie,
+                                 const GPtrArray *parameters)
+ {
+         GObject      *object;
+@@ -1152,6 +1696,8 @@ ck_session_new_with_parameters (const ch
+         GObjectClass *class;
+         GType         object_type;
+ 
++        g_debug ("CkSession: New session with parameters");
++
+         object_type = CK_TYPE_SESSION;
+         class = g_type_class_ref (object_type);
+ 
+@@ -1169,12 +1715,6 @@ ck_session_new_with_parameters (const ch
+         g_value_set_string (&params[n_params].value, ssid);
+         n_params++;
+ 
+-        params[n_params].name = g_strdup ("cookie");
+-        params[n_params].value.g_type = 0;
+-        g_value_init (&params[n_params].value, G_TYPE_STRING);
+-        g_value_set_string (&params[n_params].value, cookie);
+-        n_params++;
+-
+         if (parameters != NULL) {
+                 for (i = 0; i < parameters->len; i++) {
+                         gboolean    res;
+@@ -1259,7 +1799,7 @@ ck_session_run_programs (CkSession  *ses
+                          const char *action)
+ {
+         int   n;
+-        char *extra_env[11]; /* be sure to adjust this as needed */
++        char *extra_env[12]; /* be sure to adjust this as needed */
+ 
+         n = 0;
+ 
+@@ -1267,6 +1807,9 @@ ck_session_run_programs (CkSession  *ses
+         if (session->priv->session_type != NULL) {
+                 extra_env[n++] = g_strdup_printf ("CK_SESSION_TYPE=%s", session->priv->session_type);
+         }
++        if (session->priv->display_type != NULL) {
++                extra_env[n++] = g_strdup_printf ("CK_SESSION_DISPLAY_TYPE=%s", session->priv->display_type);
++        }
+         extra_env[n++] = g_strdup_printf ("CK_SESSION_SEAT_ID=%s", session->priv->seat_id);
+         extra_env[n++] = g_strdup_printf ("CK_SESSION_USER_UID=%d", session->priv->uid);
+         if (session->priv->display_device != NULL && strlen (session->priv->display_device) > 0) {
+@@ -1301,6 +1844,10 @@ ck_session_dump (CkSession *session,
+         char *s;
+         char *group_name;
+ 
++        if (!session->priv->is_open) {
++                return;
++        }
++
+         group_name = g_strdup_printf ("Session %s", session->priv->id);
+         g_key_file_set_integer (key_file, group_name, "uid", session->priv->uid);
+         g_key_file_set_string (key_file,
+@@ -1313,6 +1860,12 @@ ck_session_dump (CkSession *session,
+                                        "type",
+                                        NONULL_STRING (session->priv->session_type));
+         }
++        if (session->priv->display_type != NULL) {
++                g_key_file_set_string (key_file,
++                                       group_name,
++                                       "display_type",
++                                       NONULL_STRING (session->priv->display_type));
++        }
+         if (session->priv->login_session_id != NULL && strlen (session->priv->login_session_id) > 0) {
+                 g_key_file_set_string (key_file,
+                                        group_name,
+diff --git a/src/ck-session.h b/src/ck-session.h
+index b6b565b..a24d0a8 100644
+--- a/src/ck-session.h
++++ b/src/ck-session.h
+@@ -25,6 +25,8 @@
+ #include <glib-object.h>
+ #include <dbus/dbus-glib.h>
+ 
++#include "ck-display-template.h"
++
+ G_BEGIN_DECLS
+ 
+ #define CK_TYPE_SESSION         (ck_session_get_type ())
+@@ -68,10 +70,15 @@ typedef enum
+ 
+ GQuark              ck_session_error_quark            (void);
+ GType               ck_session_get_type               (void);
++CkSession         * ck_session_new_from_file          (const char            *ssid,
++                                                       const char            *path);
+ CkSession         * ck_session_new                    (const char            *ssid,
+-                                                       const char            *cookie);
++                                                       const char            *type,
++                                                       const char            *display_type_string,
++                                                       GHashTable            *display_variables);
+ CkSession         * ck_session_new_with_parameters    (const char            *ssid,
+-                                                       const char            *cookie,
++                                                       const GPtrArray       *parameters);
++void                ck_session_set_parameters         (CkSession             *session,
+                                                        const GPtrArray       *parameters);
+ 
+ void                ck_session_dump                   (CkSession             *session,
+@@ -86,6 +93,15 @@ gboolean            ck_session_set_active             (CkSession             *se
+ gboolean            ck_session_set_is_local           (CkSession             *session,
+                                                        gboolean               is_local,
+                                                        GError               **error);
++gboolean            ck_session_set_is_open            (CkSession             *session,
++                                                       gboolean               is_open,
++                                                       GError               **error);
++gboolean            ck_session_set_ever_open          (CkSession             *session,
++                                                       gboolean               ever_open,
++                                                       GError               **error);
++gboolean            ck_session_set_under_request      (CkSession             *session,
++                                                       gboolean               under_request,
++                                                       GError               **error);
+ gboolean            ck_session_set_id                 (CkSession             *session,
+                                                        const char            *ssid,
+                                                        GError               **error);
+@@ -116,6 +132,11 @@ gboolean            ck_session_set_remote_host_name   (CkSession             *se
+ gboolean            ck_session_set_session_type       (CkSession             *session,
+                                                        const char            *type,
+                                                        GError               **error);
++gboolean            ck_session_set_display_type       (CkSession             *session,
++                                                       const char            *type,
++                                                       GError               **error);
++GHashTable         *ck_session_get_display_variables  (CkSession             *session);
++CkDisplayTemplate  *ck_session_get_display_template   (CkSession             *session);
+ 
+ /* Exported methods */
+ 
+@@ -132,6 +153,15 @@ gboolean            ck_session_is_active              (CkSession             *se
+ gboolean            ck_session_is_local               (CkSession             *session,
+                                                        gboolean              *local,
+                                                        GError               **error);
++gboolean            ck_session_is_open                (CkSession             *session,
++                                                       gboolean              *open,
++                                                       GError               **error);
++gboolean            ck_session_get_ever_open          (CkSession             *session,
++                                                       gboolean              *open,
++                                                       GError               **error);
++gboolean            ck_session_get_under_request      (CkSession             *session,
++                                                       gboolean              *under_request,
++                                                       GError               **error);
+ gboolean            ck_session_get_unix_user          (CkSession             *session,
+                                                        guint                 *uid,
+                                                        GError               **error);
+@@ -150,12 +180,18 @@ gboolean            ck_session_get_login_session_id   (CkSession             *se
+ gboolean            ck_session_get_session_type       (CkSession             *session,
+                                                        char                 **type,
+                                                        GError               **error);
++gboolean            ck_session_get_display_type       (CkSession             *session,
++                                                       char                 **type,
++                                                       GError               **error);
+ gboolean            ck_session_get_remote_host_name   (CkSession             *session,
+                                                        char                 **host_name,
+                                                        GError               **error);
+ gboolean            ck_session_get_creation_time      (CkSession             *session,
+                                                        char                 **iso8601_datetime,
+                                                        GError               **error);
++gboolean            ck_session_get_remove_on_close    (CkSession             *session,
++                                                       gboolean              *remove_on_close,
++                                                       GError               **error);
+ /*deprecated*/
+ gboolean            ck_session_get_user               (CkSession             *session,
+                                                        guint                 *uid,
+@@ -171,6 +207,12 @@ gboolean            ck_session_get_idle_since_hint    (CkSession             *se
+ gboolean            ck_session_set_idle_hint          (CkSession             *session,
+                                                        gboolean               idle_hint,
+                                                        DBusGMethodInvocation *context);
++gboolean            session_set_remove_on_close       (CkSession             *session,
++                                                       gboolean               remove_on_close,
++                                                       GError               **error);
++gboolean            ck_session_set_remove_on_close    (CkSession             *session,
++                                                       gboolean               remove_on_close,
++                                                       DBusGMethodInvocation *context);
+ 
+ /* Privileged actions */
+ gboolean            ck_session_activate               (CkSession             *session,
+diff --git a/src/main.c b/src/main.c
+index b8f698f..f685026 100644
+--- a/src/main.c
++++ b/src/main.c
+@@ -283,7 +283,7 @@ main (int    argc,
+         res = g_option_context_parse (context, &argc, &argv, &error);
+         g_option_context_free (context);
+         if (! res) {
+-                g_warning (error->message);
++                g_warning ("%s", error->message);
+                 g_error_free (error);
+                 goto out;
+         }
+diff --git a/src/org.freedesktop.ConsoleKit.Manager.xml b/src/org.freedesktop.ConsoleKit.Manager.xml
+--- a/src/org.freedesktop.ConsoleKit.Manager.xml
++++ b/src/org.freedesktop.ConsoleKit.Manager.xml
+index f903b55..34a6d04 100644
+@@ -160,6 +160,23 @@
+       </doc:doc>
+     </method>
+ 
++    <method name="GetUnmanagedSeats">
++      <arg name="seats" direction="out" type="ao">
++        <doc:doc>
++          <doc:summary>an array of unmanaged Seat IDs</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This gets a list of the unmanaged <doc:ref type="interface" to="Seat">Seats</doc:ref>
++          that are statically configured under /etc/ConsoleKit/seats.d</doc:para>
++          <doc:para>Each Seat ID is an D-Bus object path for the object that implements the
++          <doc:ref type="interface" to="Seat">Seat</doc:ref> interface.</doc:para>
++        </doc:description>
++        <doc:seealso><doc:ref type="interface" to="Seat">org.freedesktop.ConsoleKit.Seat</doc:ref></doc:seealso>
++      </doc:doc>
++    </method>
++
+     <method name="GetSessions">
+       <arg name="sessions" direction="out" type="ao">
+         <doc:doc>
+@@ -196,6 +213,22 @@
+         </doc:description>
+       </doc:doc>
+     </method>
++
++    <method name="WillNotRespawn">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg name="ssid" type="o" direction="in">
++        <doc:doc>
++          <doc:summary>The session id of the session</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This may be used to set Remove On Close for a Session.
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++
+     <method name="GetSessionForUnixProcess">
+       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+       <arg name="pid" direction="in" type="u">
+@@ -310,12 +343,115 @@
+       </doc:doc>
+     </method>
+ 
++    <method name="AddSeat">
++      <arg name="type" type="s" direction="in">
++        <doc:doc>
++          <doc:summary>The type of seat to add</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="sid" type="o" direction="out">
++        <doc:doc>
++          <doc:summary>The Seat ID of the added seat</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This method is to create a new seat
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++    <method name="AddSeatById">
++      <arg name="type" type="s" direction="in">
++        <doc:doc>
++          <doc:summary>The type of seat to add</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="sid" type="o" direction="in">
++        <doc:doc>
++          <doc:summary>The Seat ID of to be added seat</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This method is to create a new seat by specify given sid
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++    <method name="RemoveSeat">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg name="sid" type="o" direction="in">
++        <doc:doc>
++          <doc:summary>The Seat ID of the seat to remove</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This method is to remove a seat
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++    <method name="AddSession">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg name="sid" type="o">
++        <doc:doc>
++          <doc:summary>The seat to add the session to</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="type" type="s">
++        <doc:doc>
++          <doc:summary>The type of session to run (e.g. "LoginWindow", "Chooser", etc)</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="display_type" type="s">
++        <doc:doc>
++          <doc:summary>The name of the display type to use (defined in displays.d)</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="variables" type="a{ss}">
++        <doc:doc>
++          <doc:summary>Session type specific parameters</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="ssid" direction="out" type="o">
++        <doc:doc>
++          <doc:summary>Session ID</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>Request a new session gets added to seat.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++    <method name="RemoveSession">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg name="ssid" type="o" direction="in">
++        <doc:doc>
++          <doc:summary>The session id of the session to remove</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This method is to remove a session from a seat
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++
+     <signal name="SeatAdded">
+       <arg name="sid" type="o">
+         <doc:doc>
+           <doc:summary>The Seat ID for the added seat</doc:summary>
+         </doc:doc>
+       </arg>
++      <arg name="type" type="s">
++        <doc:doc>
++          <doc:summary>The type of seat added.</doc:summary>
++        </doc:doc>
++      </arg>
+       <doc:doc>
+         <doc:description>
+           <doc:para>Emitted when a Seat has been added to the system.
+diff --git a/src/org.freedesktop.ConsoleKit.Seat.xml b/src/org.freedesktop.ConsoleKit.Seat.xml
+index d95990b..1f6c46f 100644
+--- a/src/org.freedesktop.ConsoleKit.Seat.xml
++++ b/src/org.freedesktop.ConsoleKit.Seat.xml
+@@ -100,6 +100,24 @@ seat at a time.</doc:para>
+       </doc:doc>
+     </method>
+ 
++    <method name="Manage">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <doc:doc>
++        <doc:description>
++          <doc:para>Attempt to create unmanaged sessions for this seat.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++
++    <method name="Unmanage">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <doc:doc>
++        <doc:description>
++          <doc:para>Stop managing seat.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++
+     <signal name="ActiveSessionChanged">
+       <arg name="ssid" type="o">
+         <doc:doc>
+@@ -160,5 +178,73 @@ seat at a time.</doc:para>
+         </doc:description>
+       </doc:doc>
+     </signal>
++    <signal name="OpenSessionRequest">
++      <arg name="ssid" type="o">
++        <doc:doc>
++          <doc:summary>The session id of the session to add</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="session_type" type="s">
++        <doc:doc>
++          <doc:summary>The type of session to run (e.g. "LoginWindow", "Chooser", etc)</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="display_template_name" type="s">
++        <doc:doc>
++          <doc:summary>The name of display template </doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="parameters" type="a{ss}">
++        <doc:doc>
++          <doc:summary>Session type specific parameters</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="display_type" type="s">
++        <doc:doc>
++          <doc:summary>The type of display to use (e.g. "X11", "Command", "XDMCP", etc)</doc:summary>
++        </doc:doc>
++      </arg>
++      <arg name="display_parameters" type="a{ss}">
++        <doc:doc>
++          <doc:summary>Display type specific parameters</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>Emitted when a new session should get added to the seat.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </signal>
++    <signal name="CloseSessionRequest">
++      <arg name="ssid" type="o">
++        <doc:doc>
++          <doc:summary>The session id of the session to remove</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>Emitted when a session with given display number need to be removed.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </signal>
++    <signal name="NoRespawn">
++      <arg name="ssid" type="o">
++        <doc:doc>
++          <doc:summary>The session id of the session to not respawn</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>Emitted when ck-seat-tool indicates a session is to be removed.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </signal>
++    <signal name="RemoveRequest">
++      <doc:doc>
++        <doc:description>
++          <doc:para>Emitted when seat needs to get removed.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </signal>
+   </interface>
+ </node>
+diff --git a/src/org.freedesktop.ConsoleKit.Session.xml b/src/org.freedesktop.ConsoleKit.Session.xml
+index b6e1cdb..2652058 100644
+--- a/src/org.freedesktop.ConsoleKit.Session.xml
++++ b/src/org.freedesktop.ConsoleKit.Session.xml
+@@ -52,6 +52,19 @@
+         <doc:seealso><doc:ref type="property" to="Session:session-type">session-type</doc:ref></doc:seealso>
+       </doc:doc>
+     </method>
++    <method name="GetDisplayType">
++      <arg name="type" direction="out" type="s">
++        <doc:doc>
++          <doc:summary>Display type</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>Returns the display type of the session.</doc:para>
++        </doc:description>
++        <doc:seealso><doc:ref type="property" to="Session:display-type">display-type</doc:ref></doc:seealso>
++      </doc:doc>
++    </method>
+     <method name="GetUser">
+       <arg name="uid" direction="out" type="u">
+         <doc:doc>
+@@ -174,6 +187,18 @@
+         <doc:seealso><doc:ref type="property" to="Session:is-local">is-local</doc:ref></doc:seealso>
+       </doc:doc>
+     </method>
++    <method name="IsOpen">
++      <arg name="open" direction="out" type="b">
++        <doc:doc>
++          <doc:summary>TRUE if the session is open, otherwise FALSE</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description><doc:para>Returns whether the session is open</doc:para>
++        </doc:description>
++        <doc:seealso><doc:ref type="property" to="Session:is-open">is-open</doc:ref></doc:seealso>
++      </doc:doc>
++    </method>
+     <method name="GetCreationTime">
+       <arg name="iso8601_datetime" type="s" direction="out">
+         <doc:doc>
+@@ -275,6 +300,21 @@
+         </doc:description>
+       </doc:doc>
+     </method>
++    <method name="SetRemoveOnClose">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg name="remove_on_close" type="b" direction="in">
++        <doc:doc>
++          <doc:summary>boolean value to set the remove-on-close to</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This may be used by the session to indicate that
++          it should be respawn or not when it is closed.
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
+ 
+     <signal name="ActiveChanged">
+       <arg name="is_active" type="b">
+@@ -317,6 +357,19 @@
+       </doc:doc>
+     </signal>
+ 
++    <property name="session" type="o" access="readwrite">
++      <doc:doc>
++        <doc:description>
++          <doc:para>The id of the session.</doc:para>
++          <doc:para>
++          The object path of the session.  Typically this is set by a session leader during a call to the
++          <doc:ref type="method" to="Manager.OpenSessionWithParameters">OpenSessionWithParameters</doc:ref> method, when
++          opening a session in response to the <doc:ref type="signal" to="Seat::OpenSessionRequest">OpenSessionRequest</doc:ref>
++          signal.
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </property>
+     <property name="unix-user" type="u" access="readwrite">
+       <doc:doc>
+         <doc:description>
+@@ -342,6 +395,16 @@
+         </doc:description>
+       </doc:doc>
+     </property>
++    <property name="display-type" type="s" access="readwrite">
++      <doc:doc>
++        <doc:description>
++          <doc:para>The display type of the session.</doc:para>
++          <doc:para>Indicate the display template name. All the display template configuration
++          files are under /etc/ConsoleKit/displays.d/.
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </property>
+     <property name="remote-host-name" type="s" access="readwrite">
+       <doc:doc>
+         <doc:description>
+@@ -396,6 +459,19 @@
+         </doc:description>
+       </doc:doc>
+     </property>
++    <property name="is-open" type="b" access="readwrite">
++      <doc:doc>
++        <doc:description>
++          <doc:para>
++          Whether the session is open</doc:para>
++          <doc:para>Sessions added from static configuration or in direct response to a call to
++          the <doc:ref type="method" to="Manager.AddSession">AddSession</doc:ref> method are initialally
++          closed and aren't open until a call to the <doc:ref type="method" to="Manager.OpenSessionWithParameters">OpenSessionWithParameters</doc:ref>
++          method.
++          </doc:para>
++        </doc:description>
++      </doc:doc>
++    </property>
+     <property name="is-local" type="b" access="readwrite">
+       <doc:doc>
+         <doc:description>
+@@ -408,6 +484,14 @@
+         </doc:description>
+       </doc:doc>
+     </property>
++    <property name="is-dynamic" type="b" access="readwrite">
++      <doc:doc>
++        <doc:description>
++          <doc:para>
++          Whether the session is dynamic</doc:para>
++        </doc:description>
++      </doc:doc>
++    </property>
+     <property name="idle-hint" type="b" access="readwrite">
+       <doc:doc>
+         <doc:description>
+@@ -430,6 +514,14 @@
+         </doc:description>
+       </doc:doc>
+     </property>
++    <property name="remove-on-close" type="b" access="readwrite">
++      <doc:doc>
++        <doc:description>
++          <doc:para>
++          Whether the session respawn when it is closed</doc:para>
++        </doc:description>
++      </doc:doc>
++    </property>
+ 
+   </interface>
+ </node>
+diff --git a/src/strverscmp.c b/src/strverscmp.c
+new file mode 100644
+index 0000000..f077651
+--- /dev/null
++++ b/src/strverscmp.c
+@@ -0,0 +1,131 @@
++/* Compare strings while treating digits characters numerically.
++   Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jean-François Bignolles <[email protected]>, 1997.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2, or (at your option)
++   any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License along
++   with this program; if not, write to the Free Software Foundation,
++   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
++
++#if !_LIBC
++# include <config.h>
++#endif
++
++#include <string.h>
++#include <ctype.h>
++
++/* states: S_N: normal, S_I: comparing integral part, S_F: comparing
++           fractional parts, S_Z: idem but with leading Zeroes only */
++#define S_N    0x0
++#define S_I    0x4
++#define S_F    0x8
++#define S_Z    0xC
++
++/* result_type: CMP: return diff; LEN: compare using len_diff/diff */
++#define CMP    2
++#define LEN    3
++
++
++/* ISDIGIT differs from isdigit, as follows:
++   - Its arg may be any int or unsigned int; it need not be an unsigned char
++     or EOF.
++   - It's typically faster.
++   POSIX says that only '0' through '9' are digits.  Prefer ISDIGIT to
++   isdigit unless it's important to use the locale's definition
++   of `digit' even when the host does not conform to POSIX.  */
++#define ISDIGIT(c) ((unsigned int) (c) - '0' <= 9)
++
++#undef __strverscmp
++#undef strverscmp
++
++#ifndef weak_alias
++# define __strverscmp strverscmp
++#endif
++
++/* Compare S1 and S2 as strings holding indices/version numbers,
++   returning less than, equal to or greater than zero if S1 is less than,
++   equal to or greater than S2 (for more info, see the texinfo doc).
++*/
++
++int
++__strverscmp (const char *s1, const char *s2)
++{
++  const unsigned char *p1 = (const unsigned char *) s1;
++  const unsigned char *p2 = (const unsigned char *) s2;
++  unsigned char c1, c2;
++  int state;
++  int diff;
++
++  /* Symbol(s)    0       [1-9]   others  (padding)
++     Transition   (10) 0  (01) d  (00) x  (11) -   */
++  static const unsigned int next_state[] =
++  {
++      /* state    x    d    0    - */
++      /* S_N */  S_N, S_I, S_Z, S_N,
++      /* S_I */  S_N, S_I, S_I, S_I,
++      /* S_F */  S_N, S_F, S_F, S_F,
++      /* S_Z */  S_N, S_F, S_Z, S_Z
++  };
++
++  static const int result_type[] =
++  {
++      /* state   x/x  x/d  x/0  x/-  d/x  d/d  d/0  d/-
++                 0/x  0/d  0/0  0/-  -/x  -/d  -/0  -/- */
++
++      /* S_N */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
++                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
++      /* S_I */  CMP, -1,  -1,  CMP,  1,  LEN, LEN, CMP,
++                  1,  LEN, LEN, CMP, CMP, CMP, CMP, CMP,
++      /* S_F */  CMP, CMP, CMP, CMP, CMP, LEN, CMP, CMP,
++                 CMP, CMP, CMP, CMP, CMP, CMP, CMP, CMP,
++      /* S_Z */  CMP,  1,   1,  CMP, -1,  CMP, CMP, CMP,
++                 -1,  CMP, CMP, CMP
++  };
++
++  if (p1 == p2)
++    return 0;
++
++  c1 = *p1++;
++  c2 = *p2++;
++  /* Hint: '0' is a digit too.  */
++  state = S_N | ((c1 == '0') + (ISDIGIT (c1) != 0));
++
++  while ((diff = c1 - c2) == 0 && c1 != '\0')
++    {
++      state = next_state[state];
++      c1 = *p1++;
++      c2 = *p2++;
++      state |= (c1 == '0') + (ISDIGIT (c1) != 0);
++    }
++
++  state = result_type[state << 2 | ((c2 == '0') + (ISDIGIT (c2) != 0))];
++
++  switch (state)
++    {
++    case CMP:
++      return diff;
++
++    case LEN:
++      while (ISDIGIT (*p1++))
++	if (!ISDIGIT (*p2++))
++	  return 1;
++
++      return ISDIGIT (*p2) ? -1 : diff;
++
++    default:
++      return state;
++    }
++}
++#ifdef weak_alias
++weak_alias (__strverscmp, strverscmp)
++#endif
+diff --git a/src/strverscmp.h b/src/strverscmp.h
+new file mode 100644
+index 0000000..48670c8
+--- /dev/null
++++ b/src/strverscmp.h
+@@ -0,0 +1,25 @@
++/* Compare strings while treating digits characters numerically.
++   Copyright (C) 1997, 2000, 2002, 2004, 2006 Free Software Foundation, Inc.
++   This file is part of the GNU C Library.
++   Contributed by Jean-François Bignolles <[email protected]>, 1997.
++
++   This program is free software; you can redistribute it and/or modify
++   it under the terms of the GNU General Public License as published by
++   the Free Software Foundation; either version 2, or (at your option)
++   any later version.
++
++   This program is distributed in the hope that it will be useful,
++   but WITHOUT ANY WARRANTY; without even the implied warranty of
++   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
++   GNU General Public License for more details.
++
++   You should have received a copy of the GNU General Public License along
++   with this program; if not, write to the Free Software Foundation,
++   Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.  */
++
++#ifndef STRVERSCMP_H_
++# define STRVERSCMP_H_
++
++int strverscmp (const char *, const char *);
++
++#endif /* not STRVERSCMP_H_ */
+diff --git a/tools/Makefile.am b/tools/Makefile.am
+index 13c191f..fa16c68 100644
+--- a/tools/Makefile.am
++++ b/tools/Makefile.am
+@@ -54,6 +54,7 @@ sbin_PROGRAMS = \
+ 	ck-log-system-start		\
+ 	ck-log-system-restart		\
+ 	ck-log-system-stop		\
++	ck-seat-tool			\
+ 	$(NULL)
+ 
+ ck_launch_session_SOURCES =		\
+@@ -83,6 +84,14 @@ ck_history_LDADD =			\
+ 	$(top_builddir)/src/libck-event-log.la	\
+ 	$(NULL)
+ 
++ck_seat_tool_SOURCES =			\
++	ck-seat-tool.c			\
++	$(NULL)
++
++ck_seat_tool_LDADD =			\
++	$(CONSOLE_KIT_LIBS)		\
++	$(NULL)
++
+ ck_log_system_start_SOURCES =		\
+ 	ck-log-system-start.c		\
+ 	$(NULL)
+diff --git a/tools/ck-seat-tool.c b/tools/ck-seat-tool.c
+new file mode 100644
+index 0000000..0879d0d
+--- /dev/null
++++ b/tools/ck-seat-tool.c
+@@ -0,0 +1,449 @@
++/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
++ *
++ * Copyright (C) 2009 Sun Microsystems, Inc.
++ *
++ * This program is free software; you can redistribute it and/or
++ * modify it under the terms of the GNU General Public License as
++ * published by the Free Software Foundation; either version 2 of the
++ * License, or (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful, but
++ * WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
++ * General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA
++ * 02111-1307, USA.
++ *
++ * Authors: Halton Huo <[email protected]>
++ *
++ */
++
++#include "config.h"
++
++#include <stdlib.h>
++#include <stdio.h>
++#include <sys/types.h>
++#include <unistd.h>
++#include <strings.h>
++#include <glib/gi18n.h>
++#include <dbus/dbus-glib.h>
++#include <dbus/dbus-glib-lowlevel.h>
++
++#define CK_NAME              "org.freedesktop.ConsoleKit"
++#define CK_PATH              "/org/freedesktop/ConsoleKit"
++#define CK_INTERFACE         "org.freedesktop.ConsoleKit"
++#define CK_MANAGER_PATH      "/org/freedesktop/ConsoleKit/Manager"
++#define CK_MANAGER_INTERFACE "org.freedesktop.ConsoleKit.Manager"
++#define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
++#define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
++
++#define CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE (dbus_g_type_get_map ("GHashTable", G_TYPE_STRING, G_TYPE_STRING))
++
++#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
++#define CK_PATH_PREFIX       "/org/freedesktop/ConsoleKit/"
++
++static gboolean  add = FALSE;
++static gboolean  delete = FALSE;
++static gboolean  show_version = FALSE;
++static char     *session_type = NULL;
++static char     *display_type = NULL;
++static char     *seat_id = NULL;
++static char     *session_id = NULL;
++static gchar   **remaining_args = NULL;
++
++static const GOptionEntry options [] = {
++        { "add", 'a', 0, G_OPTION_ARG_NONE, &add, N_("Add a new session"), NULL},
++        { "session-type", '\0', 0, G_OPTION_ARG_STRING, &session_type, N_("Specify session type when adding a session. Default is LoginWindow."), NULL},
++        { "display-type", '\0', 0, G_OPTION_ARG_STRING, &display_type, N_("Specify display type under <etc>/ConsoleKit/displays.d/ when adding a session."), NULL},
++        { "seat-id", '\0', 0, G_OPTION_ARG_STRING, &seat_id, N_("Specify seat id when adding a session. If not given, create a new seat."), NULL},
++        { G_OPTION_REMAINING, '\0', 0, G_OPTION_ARG_STRING_ARRAY, &remaining_args, N_("Specify values of variables in display type. For example display=:10"), NULL },
++        { "delete", 'd', 0, G_OPTION_ARG_NONE, &delete, N_("Delete a session"), NULL},
++        { "session-id", '\0', 0, G_OPTION_ARG_STRING, &session_id, N_("Specify session id when deleting a session"), NULL},
++        { "version", 'V', 0, G_OPTION_ARG_NONE, &show_version, N_("Version of this application"), NULL },
++        { NULL }
++};
++
++static void
++add_session (DBusGConnection  *connection)
++{
++        DBusGProxy *mgr_proxy = NULL;
++        DBusGProxy *seat_proxy = NULL;
++        GError     *error = NULL;
++        gboolean    res;
++        char       *sid = NULL;
++        GPtrArray  *seats;
++        char       *ssid = NULL;
++        int         i;
++        gboolean    found;
++        char       *sstype = NULL;
++        GHashTable *variables = NULL;
++
++        if (! IS_STR_SET (session_type)) {
++                sstype = g_strdup ("LoginWindow");
++        } else {
++                sstype = g_strdup (session_type);
++        }
++
++        mgr_proxy = dbus_g_proxy_new_for_name (connection,
++                                               CK_NAME,
++                                               CK_MANAGER_PATH,
++                                               CK_MANAGER_INTERFACE);
++        if (mgr_proxy == NULL) {
++                return;
++        }
++
++        if (! IS_STR_SET(seat_id)) {
++
++                /* If seat id is not given, create a new seat */
++                error = NULL;
++                res = dbus_g_proxy_call (mgr_proxy,
++                                         "AddSeat",
++                                         &error,
++                                         G_TYPE_STRING, "Default",
++                                         G_TYPE_INVALID,
++                                         DBUS_TYPE_G_OBJECT_PATH, &sid,
++                                         G_TYPE_INVALID);
++                if (!res) {
++                        g_warning ("Unable to add seat: %s", error->message);
++                        g_error_free (error);
++                        g_object_unref (mgr_proxy);
++                        return;
++                }
++
++        } else {
++                if (!g_str_has_prefix (seat_id, CK_PATH_PREFIX)) {
++                        sid = g_strdup_printf ("%s%s", CK_PATH_PREFIX, seat_id);
++                } else {
++                        sid = g_strdup (seat_id);
++                }
++                /* Check whether seat is existing, if not, try to create it. */
++
++                error = NULL;
++                res = dbus_g_proxy_call (mgr_proxy,
++                                         "GetSeats",
++                                         &error,
++                                         G_TYPE_INVALID,
++                                         dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
++                                         &seats,
++                                         G_TYPE_INVALID);
++                if (!res) {
++                        g_warning ("Unable to get seat list: %s", error->message);
++                        g_error_free (error);
++                        g_object_unref (mgr_proxy);
++                        return;
++                }
++
++                found = FALSE;
++                for (i = 0; i < seats->len; i++) {
++                        char *tmp_sid;
++
++                        tmp_sid = g_ptr_array_index (seats, i);
++                        if (g_str_equal (sid, tmp_sid)) {
++                                found = TRUE;
++                                g_free (tmp_sid);
++                                break;
++                        }
++
++                        g_free (tmp_sid);
++                }
++
++                if (! found) {
++                        error = NULL;
++                        res = dbus_g_proxy_call (mgr_proxy,
++                                                 "AddSeatById",
++                                                 &error,
++                                                 G_TYPE_STRING, "Default",
++                                                 DBUS_TYPE_G_OBJECT_PATH, sid,
++                                                 G_TYPE_INVALID,
++                                                 G_TYPE_INVALID);
++                        if (!res) {
++                                g_warning ("Unable to add seat: %s", error->message);
++                                g_error_free (error);
++                                g_object_unref (mgr_proxy);
++                                return;
++                        }
++                }
++        }
++
++        seat_proxy = dbus_g_proxy_new_for_name (connection,
++                                                CK_NAME,
++                                                sid,
++                                                CK_SEAT_INTERFACE);
++
++        if (seat_proxy == NULL) {
++                g_warning ("Failed to talk to seat '%s'", sid);
++                g_object_unref (mgr_proxy);
++                return;
++        }
++
++        variables = g_hash_table_new_full (g_str_hash, g_str_equal,
++                                           (GDestroyNotify) g_free,
++                                           (GDestroyNotify) g_free);
++
++        if (remaining_args) {
++                for (i = 0; i < G_N_ELEMENTS (remaining_args); i++) {
++                        char **arr;
++
++                        /* split var=value */
++                        arr = g_strsplit (remaining_args [i], "=", 2);
++                        if (arr[0] && arr[1]) {
++                                g_hash_table_insert (variables,
++                                                     g_strdup(arr[0]),
++                                                     g_strdup (arr[1]));
++                        }
++                        g_strfreev (arr);
++                }
++        }
++
++        error = NULL;
++        res = dbus_g_proxy_call (mgr_proxy,
++                                 "AddSession",
++                                 &error,
++                                 DBUS_TYPE_G_OBJECT_PATH, sid,
++                                 G_TYPE_STRING, sstype,
++                                 G_TYPE_STRING, display_type,
++                                 CK_DBUS_TYPE_G_STRING_STRING_HASHTABLE, variables,
++                                 G_TYPE_INVALID,
++                                 DBUS_TYPE_G_OBJECT_PATH, &ssid,
++                                 G_TYPE_INVALID);
++
++        if (!res) {
++                g_warning ("Unable to add dynamic session: %s", error->message);
++                g_error_free (error);
++        } else {
++                dbus_g_proxy_call_no_reply (seat_proxy,
++                                            "Manage",
++                                            G_TYPE_INVALID,
++                                            G_TYPE_INVALID);
++                g_print ("Seat %s with session %s has been added\n", sid, ssid);
++        }
++
++        g_object_unref (seat_proxy);
++        g_object_unref (mgr_proxy);
++}
++
++static gboolean
++is_session_on_seat (DBusGConnection *connection,
++                    const char      *sid,
++                    const char      *ssid,
++                    gboolean        *is_last_session)
++{
++
++        DBusGProxy *seat_proxy = NULL;
++        GPtrArray  *sessions = NULL;
++        char       *ssid_tmp = NULL;
++        gboolean    res;
++        gboolean    retval = FALSE;
++        int         i;
++        GError     *error = NULL;
++
++        seat_proxy = dbus_g_proxy_new_for_name (connection,
++                                                CK_NAME,
++                                                sid,
++                                                CK_SEAT_INTERFACE);
++
++        if (seat_proxy == NULL) {
++                g_warning ("Failed to talk to seat '%s'", sid);
++                return FALSE;
++        }
++
++        error = NULL;
++        res = dbus_g_proxy_call (seat_proxy,
++                                 "GetSessions",
++                                 &error,
++                                 G_TYPE_INVALID,
++                                 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
++                                 &sessions,
++                                 G_TYPE_INVALID);
++        if (! res) {
++                g_warning ("Failed to get list of sessions for %s: %s", sid, error->message);
++                g_error_free (error);
++                g_object_unref (seat_proxy);
++                return FALSE;
++        }
++
++        for (i = 0; i < sessions->len; i++) {
++
++                ssid_tmp = g_ptr_array_index (sessions, i);
++
++                if (g_str_equal (ssid, ssid_tmp)) {
++                        retval = TRUE;
++                        break;
++                }
++
++                g_free (ssid_tmp);
++                ssid_tmp = NULL;
++        }
++
++        if (is_last_session != NULL) {
++                *is_last_session = sessions->len == 1;
++        }
++
++        g_ptr_array_free (sessions, TRUE);
++        g_object_unref (seat_proxy);
++
++        return retval;
++}
++
++static char *
++find_seat_id_from_session_id (DBusGConnection *connection,
++                              DBusGProxy      *proxy,
++                              const char      *ssid,
++                              gboolean        *is_last_session)
++{
++        GError     *error;
++        GPtrArray  *seats;
++        int         i;
++        char       *sid;
++        gboolean    res;
++
++        error = NULL;
++        res = dbus_g_proxy_call (proxy,
++                                 "GetSeats",
++                                 &error,
++                                 G_TYPE_INVALID,
++                                 dbus_g_type_get_collection ("GPtrArray", DBUS_TYPE_G_OBJECT_PATH),
++                                 &seats,
++                                 G_TYPE_INVALID);
++
++        if (! res) {
++                g_warning ("Failed to get list of seats: %s", error->message);
++                g_error_free (error);
++                return NULL;
++        }
++
++        for (i = 0; i < seats->len; i++) {
++
++                sid = g_ptr_array_index (seats, i);
++                if (is_session_on_seat (connection, sid, ssid, is_last_session)) {
++                        break;
++                }
++
++                g_free (sid);
++        }
++        g_ptr_array_free (seats, TRUE);
++
++        return sid;
++}
++
++static void
++delete_session (DBusGConnection *connection)
++{
++        DBusGProxy *proxy;
++        char       *ssid;
++        char       *sid;
++        gboolean    is_last_session;
++
++        if (!g_str_has_prefix (session_id, CK_PATH_PREFIX)) {
++                ssid = g_strdup_printf ("%s%s", CK_PATH_PREFIX, session_id);
++        } else {
++                ssid = g_strdup (session_id);
++        }
++
++        proxy = dbus_g_proxy_new_for_name (connection,
++                                           CK_NAME,
++                                           CK_MANAGER_PATH,
++                                           CK_MANAGER_INTERFACE);
++        if (proxy == NULL) {
++                return;
++        }
++
++        sid = find_seat_id_from_session_id (connection, proxy, ssid, &is_last_session);
++
++        dbus_g_proxy_call_no_reply (proxy,
++                                   "WillNotRespawn",
++                                   DBUS_TYPE_G_OBJECT_PATH, ssid,
++                                   G_TYPE_INVALID,
++                                   G_TYPE_INVALID);
++
++        dbus_g_proxy_call_no_reply (proxy,
++                                   "RemoveSession",
++                                   DBUS_TYPE_G_OBJECT_PATH, ssid,
++                                   G_TYPE_INVALID,
++                                   G_TYPE_INVALID);
++
++        if (is_last_session) {
++                dbus_g_proxy_call_no_reply (proxy,
++                                           "RemoveSeat",
++                                           DBUS_TYPE_G_OBJECT_PATH, sid,
++                                           G_TYPE_INVALID,
++                                           G_TYPE_INVALID);
++        }
++
++        g_object_unref (proxy);
++}
++
++int
++main (int argc, char *argv[])
++{
++        DBusGConnection *connection;
++        GOptionContext  *ctx;
++        GError          *error = NULL;
++        gboolean         res;
++
++        g_type_init ();
++
++        /* Option parsing */
++        ctx = g_option_context_new (_("- Manage dynamic sessions"));
++        g_option_context_add_main_entries (ctx, options, GETTEXT_PACKAGE);
++        res = g_option_context_parse (ctx, &argc, &argv, &error);
++
++        if (!res) {
++                if (error) {
++                        g_warning ("%s", error->message);
++                        g_error_free (error);
++                }
++                exit (1);
++        }
++
++        g_option_context_free (ctx);    
++
++        if (show_version) {
++                g_print ("%s %s\n", argv[0], VERSION);
++                exit (0);
++        }
++
++        if (add && delete) {
++                g_warning ("Can not specify -a and -d at the same time!");
++                exit (1);
++        }
++
++        if (!add && !delete) {
++                g_warning ("Must specify -a, -d!");
++                exit (1);
++        }
++
++        if (delete && (! IS_STR_SET (session_id))) {
++                g_warning ("You must specify session id for deleting a session. You can get all sessions by ck-list-sessions");
++                exit (1);
++        }
++
++        if (add && (! IS_STR_SET (display_type)) ) {
++                g_warning ("You must specify display type for adding a session. You can get all display types under <etc>/ConsoleKit/displays.d/");
++                g_warning ("Invalid display type!");
++                exit (1);
++        }
++
++        error = NULL;
++        connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
++        if (connection == NULL) {
++                g_message ("Failed to connect to the D-Bus daemon: %s", error->message);
++                g_error_free (error);
++                exit (1);
++        }
++
++
++        if (add) {
++                add_session (connection);
++        } else if (delete) {
++                delete_session (connection);
++        } else {
++                g_warning ("Invaild parameters!");
++                exit (1);
++        }
++
++        return 0;
++}
+diff --git a/tools/list-sessions.c b/tools/list-sessions.c
+index 3933772..cc69d57 100644
+--- a/tools/list-sessions.c
++++ b/tools/list-sessions.c
+@@ -46,6 +46,23 @@
+ #define CK_SEAT_INTERFACE    "org.freedesktop.ConsoleKit.Seat"
+ #define CK_SESSION_INTERFACE "org.freedesktop.ConsoleKit.Session"
+ 
++#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
++
++typedef struct CkSessionOutput {
++        char    *prop_name;
++        char    *prop_value;
++} CkSessionOutput;
++
++static gboolean do_all = FALSE;
++static gboolean do_version = FALSE;
++static char *do_format = NULL;
++static GOptionEntry entries [] = {
++        { "all", 'a', 0, G_OPTION_ARG_NONE, &do_all, N_("List all sessions. If not given, only list open sessions"), NULL },
++        { "format", 'f', 0, G_OPTION_ARG_STRING, &do_format, N_("Prints information according to the given format"), NULL },
++        { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL },
++        { NULL }
++};
++
+ static gboolean
+ get_uint (DBusGProxy *proxy,
+           const char *method,
+@@ -176,6 +193,7 @@ list_session (DBusGConnection *connection,
+         char       *sid;
+         char       *lsid;
+         char       *session_type;
++        char       *display_type;
+         char       *x11_display;
+         char       *x11_display_device;
+         char       *display_device;
+@@ -184,8 +202,11 @@ list_session (DBusGConnection *connection,
+         char       *idle_since_hint;
+         gboolean    is_active;
+         gboolean    is_local;
++        gboolean    is_open;
+         char       *short_sid;
+         const char *short_ssid;
++        char      **format_arr = NULL;
++        int         i, j;
+ 
+         proxy = dbus_g_proxy_new_for_name (connection,
+                                            CK_NAME,
+@@ -198,6 +219,7 @@ list_session (DBusGConnection *connection,
+         sid = NULL;
+         lsid = NULL;
+         session_type = NULL;
++        display_type = NULL;
+         x11_display = NULL;
+         x11_display_device = NULL;
+         display_device = NULL;
+@@ -209,15 +231,21 @@ list_session (DBusGConnection *connection,
+         get_path (proxy, "GetSeatId", &sid);
+         get_string (proxy, "GetLoginSessionId", &lsid);
+         get_string (proxy, "GetSessionType", &session_type);
++        get_string (proxy, "GetDisplayType", &display_type);
+         get_string (proxy, "GetX11Display", &x11_display);
+         get_string (proxy, "GetX11DisplayDevice", &x11_display_device);
+         get_string (proxy, "GetDisplayDevice", &display_device);
+         get_string (proxy, "GetRemoteHostName", &remote_host_name);
++        get_boolean (proxy, "IsOpen", &is_open);
+         get_boolean (proxy, "IsActive", &is_active);
+         get_boolean (proxy, "IsLocal", &is_local);
+         get_string (proxy, "GetCreationTime", &creation_time);
+         get_string (proxy, "GetIdleSinceHint", &idle_since_hint);
+ 
++        if (!do_all && !is_open) {
++                return;
++        }
++
+         realname = get_real_name (uid);
+ 
+         short_sid = sid;
+@@ -230,24 +258,49 @@ list_session (DBusGConnection *connection,
+                 short_ssid = ssid + strlen (CK_PATH) + 1;
+         }
+ 
+-        printf ("%s:\n\tunix-user = '%d'\n\trealname = '%s'\n\tseat = '%s'\n\tsession-type = '%s'\n\tactive = %s\n\tx11-display = '%s'\n\tx11-display-device = '%s'\n\tdisplay-device = '%s'\n\tremote-host-name = '%s'\n\tis-local = %s\n\ton-since = '%s'\n\tlogin-session-id = '%s'",
+-                short_ssid,
+-                uid,
+-                realname,
+-                short_sid,
+-                session_type,
+-                is_active ? "TRUE" : "FALSE",
+-                x11_display,
+-                x11_display_device,
+-                display_device,
+-                remote_host_name,
+-                is_local ? "TRUE" : "FALSE",
+-                creation_time,
+-                lsid);
+-        if (idle_since_hint != NULL && idle_since_hint[0] != '\0') {
+-                printf ("\n\tidle-since-hint = '%s'", idle_since_hint);
++        CkSessionOutput output[] = {
++                {"session-id", g_strdup (short_ssid)},
++                {"unix-user", g_strdup_printf ("%d", uid)},
++                {"realname", g_strdup (realname)},
++                {"seat", g_strdup (short_sid)},
++                {"session-type", g_strdup (session_type)},
++                {"display-type", g_strdup (display_type)},
++                {"open", is_open ? "TRUE" : "FALSE"},
++                {"active", is_active ? "TRUE" : "FALSE"},
++                {"x11-display", g_strdup (x11_display)},
++                {"x11-display-device", g_strdup (x11_display_device)},
++                {"display-device", g_strdup (display_device)},
++                {"remote-host-name", g_strdup (remote_host_name)},
++                {"is-local", is_local ? "TRUE" : "FALSE"},
++                {"on-since", g_strdup (creation_time)},
++                {"login-session-id", g_strdup (lsid)},
++                {"idle-since-hint", g_strdup (idle_since_hint)},
++        };
++
++        if (IS_STR_SET (do_format)) {
++                format_arr = g_strsplit (do_format, ",", -1);
++
++                for (i = 0; format_arr[i] != NULL; ++i) {
++                        for (j = 0; j < G_N_ELEMENTS (output); j++) {
++                                if (g_str_equal (format_arr[i], output[j].prop_name)) {
++                                        printf ("'%s'\t", output[j].prop_value);
++                                        break;
++                                }
++                        }
++                }
++                printf ("\n");
++                g_strfreev (format_arr);
++
++        } else {
++                for (j = 0; j < G_N_ELEMENTS (output); j++) {
++                        if (g_str_equal (output[j].prop_name, "session-id"))
++                                printf ("%s:\n", output[j].prop_value);
++                        else
++                                printf ("\t%s = '%s'\n",
++                                        output[j].prop_name,
++                                        output[j].prop_value);
++                }
+         }
+-        printf ("\n");
+ 
+         g_free (idle_since_hint);
+         g_free (creation_time);
+@@ -256,9 +309,11 @@ list_session (DBusGConnection *connection,
+         g_free (sid);
+         g_free (lsid);
+         g_free (session_type);
++        g_free (display_type);
+         g_free (x11_display);
+         g_free (x11_display_device);
+         g_free (display_device);
++
+         g_object_unref (proxy);
+ }
+ 
+@@ -368,11 +423,6 @@ main (int    argc,
+         GOptionContext *context;
+         gboolean        retval;
+         GError         *error = NULL;
+-        static gboolean do_version = FALSE;
+-        static GOptionEntry entries [] = {
+-                { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL },
+-                { NULL }
+-        };
+ 
+         g_type_init ();
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-04-sol-tty.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,38 @@
+commit dcd505d9801990781123093de5913f365b94782f
+Author: Halton Huo <[email protected]>
+Date:   Fri Sep 25 14:46:27 2009 +0800
+
+    Correct tty return value after VT support is integrated in Solaris.
+
+diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c
+index bc3b695..607a3ae 100644
+--- a/src/ck-sysdeps-solaris.c
++++ b/src/ck-sysdeps-solaris.c
+@@ -180,27 +180,8 @@ stat2proc (pid_t        pid,
+ 	if (tty_maj == 15) {
+ 		snprintf (P->tty_text, sizeof P->tty_text, "/dev/vt/%u", tty_min);
+         }
+-        if (tty_maj == 24) {
+-                snprintf (P->tty_text, sizeof P->tty_text, "/dev/pts/%u", tty_min);
+-        }
+-
+         if (P->tty == NO_TTY_VALUE) {
+-#ifdef HAVE_SYS_VT_H
+                 memcpy (P->tty_text, "   ?   ", 8);
+-#else
+-                /*
+-                 * This is a bit of a hack.  On Solaris, pre-VT integration, the
+-                 * Xorg process is not assigned a TTY.  So, just assign the value
+-                 * to "/dev/console" if running without VT support.  This will
+-                 * allow people using Solaris pre-VT integration to use
+-                 * ConsoleKit.
+-                 */
+-                memcpy (P->tty_text, "/dev/console", 12);
+-#endif
+-        }
+-
+-        if (P->tty == DEV_ENCODE(0,0)) {
+-                memcpy (P->tty_text, "/dev/console", 12);
+         }
+ 
+         if (P->pid != pid) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-05-sol-sigpoll.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,20 @@
+commit b00450b3f9284d997e2e25fd470e7df7336f03ec
+Author: Halton Huo <[email protected]>
+Date:   Fri Oct 16 11:10:37 2009 +0800
+
+    Fix bug console-kit-daemon exit when receiving  SIGPOLL on Solaris.
+    Refer to bug http://defect.opensolaris.org/bz/show_bug.cgi?id=11612
+
+diff --git a/src/ck-vt-monitor.c b/src/ck-vt-monitor.c
+index 17b8299..67a1f49 100644
+--- a/src/ck-vt-monitor.c
++++ b/src/ck-vt-monitor.c
+@@ -393,6 +393,8 @@ vt_add_watches (CkVtMonitor *vt_monitor)
+          */
+         struct sigaction act;
+         act.sa_handler = handle_vt_active;
++        sigemptyset (&act.sa_mask);
++        act.sa_flags = 0;
+         sigaction (SIGPOLL, &act, NULL);
+ 
+         ioctl (vt_monitor->priv->vfd, I_SETSIG, S_MSG);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-06-sol-xserver.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,13 @@
+Patch migrated from Desktop, where it was listed as:
+# date:2009-11-03 owner:yippi type:branding doo:12395
+
+diff --git a/data/displays.d/Local.display.in b/data/displays.d/Local.display.in
+index b845a7b..b65b3e4 100644
+--- a/data/displays.d/Local.display.in
++++ b/data/displays.d/Local.display.in
+@@ -2,4 +2,4 @@
+ Type=X11
+ 
+ [X11]
+-Exec=@X11_DIR@/Xorg $display -br -verbose -auth $auth -nolisten tcp $vt
++Exec=@X11_DIR@/Xserver $display -br -novtswitch -auth $auth $vt
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-07-sol-vt-major.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,48 @@
+commit 42a909bbc8ede5c27e3d40606a98ab1251511dfc
+Author: Halton Huo <[email protected]>
+Date:   Tue Nov 3 11:42:07 2009 +0800
+
+    Identify major device number for vt rather than hard code as 15.
+    Fixes bug http://defect.opensolaris.org/bz/show_bug.cgi?id=12322
+    This is solaris only bug, won't affect other platform.
+
+diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c
+index 607a3ae..335ab8b 100644
+--- a/src/ck-sysdeps-solaris.c
++++ b/src/ck-sysdeps-solaris.c
+@@ -124,6 +124,26 @@ ck_process_stat_get_tty (CkProcessStat *stat)
+         return g_strdup (stat->tty_text);
+ }
+ 
++#define VT0_FILE "/dev/vt/0"
++static int
++get_system_vt_major ()
++{
++        static      ret = -1;
++        struct stat st;
++        int         res;
++
++        if (ret >= 0)
++                return ret;
++
++        res = stat (VT0_FILE, &st);
++
++        if (res == 0) {
++                ret = major (st.st_rdev);
++        }
++        
++        return ret;
++}
++
+ /* return 1 if it works, or 0 for failure */
+ static gboolean
+ stat2proc (pid_t        pid,
+@@ -177,7 +197,7 @@ stat2proc (pid_t        pid,
+ 
+         snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min);
+ 
+-	if (tty_maj == 15) {
++	if (tty_maj == get_system_vt_major ()) {
+ 		snprintf (P->tty_text, sizeof P->tty_text, "/dev/vt/%u", tty_min);
+         }
+         if (P->tty == NO_TTY_VALUE) {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-08-can-stop.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,88 @@
+Patch migrated from Desktop, where it was listed as:
+# date:2009-11-10 owner:jedy type:bug bugzilla:24992
+
+
+diff --git a/src/ck-manager.c b/src/ck-manager.c
+index 99693a3..6bda488 100644
+--- a/src/ck-manager.c
++++ b/src/ck-manager.c
+@@ -1026,9 +1026,10 @@ get_system_num_users (CkManager *manager)
+ }
+ 
+ #ifdef ENABLE_RBAC_SHUTDOWN
+-static void
++static gboolean
+ check_rbac_permissions (CkManager             *manager,
+                         DBusGMethodInvocation *context,
++                        const char            *action,
+                         AuthorizedCallback     callback)
+ {
+         const char *sender;
+@@ -1050,7 +1051,7 @@ check_rbac_permissions (CkManager             *manager,
+         username = get_user_name (uid);
+ 
+         if (username == NULL ||
+-            !chkauthattr (RBAC_SHUTDOWN_KEY, username)) {
++            !chkauthattr (action, username)) {
+                 res = FALSE;
+                 goto out;
+         }
+@@ -1065,9 +1066,11 @@ out:
+ 
+         g_free (username);
+ 
+-        if (res) {
++        if (res && callback) {
+                 callback (manager, context);
+         }
++
++        return res;
+ }
+ #endif
+ 
+@@ -1126,7 +1129,7 @@ ck_manager_restart (CkManager             *manager,
+ #if defined HAVE_POLKIT
+         check_polkit_permissions (manager, context, action, do_restart);
+ #elif defined ENABLE_RBAC_SHUTDOWN
+-        check_rbac_permissions (manager, context, do_restart);
++        check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_restart);
+ #else
+         g_warning ("Compiled without PolicyKit or RBAC support!");
+ #endif
+@@ -1146,7 +1149,12 @@ ck_manager_can_restart (CkManager  *manager,
+ #if defined HAVE_POLKIT
+         get_polkit_permissions (manager, action, context);
+ #else
+-        dbus_g_method_return (context, TRUE);
++        if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY,
++                                        NULL)) {
++                dbus_g_method_return (context, TRUE);
++        } else {
++                dbus_g_method_return (context, FALSE);
++        }
+ #endif
+ 
+         return TRUE;
+@@ -1197,7 +1205,7 @@ ck_manager_stop (CkManager             *manager,
+ #if defined HAVE_POLKIT
+         check_polkit_permissions (manager, context, action, do_stop);
+ #elif defined  ENABLE_RBAC_SHUTDOWN
+-        check_rbac_permissions (manager, context, do_stop);
++        check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_stop);
+ #else
+         g_warning ("Compiled without PolicyKit or RBAC support!");
+ #endif
+@@ -1216,7 +1224,12 @@ ck_manager_can_stop (CkManager  *manager,
+ #if defined HAVE_POLKIT
+         get_polkit_permissions (manager, action, context);
+ #else
+-        dbus_g_method_return (context, TRUE);
++        if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY,
++                                        NULL)) {
++                dbus_g_method_return (context, TRUE);
++        } else {
++                dbus_g_method_return (context, FALSE);
++        }
+ #endif
+ 
+         return TRUE;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-09-fastreboot.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,450 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2009-11-10 owner:jedy type:bug bugzilla:24749
+
+Provides Solaris-specific support for fast reboot.
+
+diff -uprN ConsoleKit-0.4.1-backup/configure.ac ConsoleKit-0.4.1/configure.ac
+--- ConsoleKit-0.4.1-backup/configure.ac	2009-11-10 15:28:55.524301156 +0800
++++ ConsoleKit-0.4.1/configure.ac	2009-11-10 15:31:24.985394958 +0800
+@@ -81,10 +81,10 @@ AC_PATH_PROG(GLIB_GENMARSHAL, glib-genma
+ 
+ EXTRA_COMPILE_WARNINGS(yes)
+ 
+-# Solaris requires libresolv for daemon()
++# Solaris requires libscf
+ case "$host" in
+ 	*-*-solaris*)
+-		AC_CHECK_LIB(resolv, daemon, [CONSOLE_KIT_LIBS="$CONSOLE_KIT_LIBS -lresolv"])
++		AC_CHECK_LIB(scf, daemon, [CONSOLE_KIT_LIBS="$CONSOLE_KIT_LIBS -lscf"])
+ 	;;
+ esac
+ 
+diff -uprN ConsoleKit-0.4.1-backup/data/ConsoleKit.conf ConsoleKit-0.4.1/data/ConsoleKit.conf
+--- ConsoleKit-0.4.1-backup/data/ConsoleKit.conf	2009-11-10 15:28:55.525135254 +0800
++++ ConsoleKit-0.4.1/data/ConsoleKit.conf	2009-11-10 15:31:24.985644376 +0800
+@@ -38,6 +38,12 @@
+            send_member="CanStop"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Manager"
++           send_member="GetAvailableOperatingSystems"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Manager"
++           send_member="RestartWithParameters"/>
++    <allow send_destination="org.freedesktop.ConsoleKit"
++           send_interface="org.freedesktop.ConsoleKit.Manager"
+            send_member="OpenSession"/>
+     <allow send_destination="org.freedesktop.ConsoleKit"
+            send_interface="org.freedesktop.ConsoleKit.Manager"
+diff -uprN ConsoleKit-0.4.1-backup/src/ck-manager.c ConsoleKit-0.4.1/src/ck-manager.c
+--- ConsoleKit-0.4.1-backup/src/ck-manager.c	2009-11-10 15:28:55.561041146 +0800
++++ ConsoleKit-0.4.1/src/ck-manager.c	2009-11-10 15:32:06.905204994 +0800
+@@ -39,6 +39,10 @@
+ #include <dbus/dbus-glib.h>
+ #include <dbus/dbus-glib-lowlevel.h>
+ 
++#if (defined(sun) && defined(__SVR4))
++#include <libscf_priv.h>
++#endif
++
+ #if defined HAVE_POLKIT
+ #include <polkit/polkit.h>
+ #elif defined ENABLE_RBAC_SHUTDOWN
+@@ -759,13 +763,15 @@ get_cookie_for_pid (CkManager *manager,
+ }
+ 
+ typedef void (*AuthorizedCallback) (CkManager             *manager,
+-                                    DBusGMethodInvocation *context);
++                                    DBusGMethodInvocation *context,
++                                    void                  *arg);
+ 
+ typedef struct
+ {
+         CkManager             *manager;
+         DBusGMethodInvocation *context;
+         AuthorizedCallback     callback;
++        void                  *arg;
+ } AuthorizedCallbackData;
+ 
+ static void
+@@ -799,7 +805,7 @@ auth_ready_callback (PolkitAuthority    
+                 g_error_free (error);
+         }
+         else if (polkit_authorization_result_get_is_authorized (result)) {
+-                data->callback (data->manager, data->context);
++                data->callback (data->manager, data->context, data->arg);
+         }
+         else if (polkit_authorization_result_get_is_challenge (result)) {
+                 error = g_error_new (CK_MANAGER_ERROR,
+@@ -825,7 +831,8 @@ static void
+ check_polkit_permissions (CkManager             *manager,
+                           DBusGMethodInvocation *context,
+                           const char            *action,
+-                          AuthorizedCallback     callback)
++                          AuthorizedCallback     callback,
++                          void                  *arg)
+ {
+         const char    *sender;
+         PolkitSubject *subject;
+@@ -843,6 +850,7 @@ check_polkit_permissions (CkManager     
+         data->manager = g_object_ref (manager);
+         data->context = context;
+         data->callback = callback;
++        data->arg = arg;
+ 
+         polkit_authority_check_authorization (manager->priv->pol_ctx,
+                                               subject,
+@@ -1048,7 +1056,8 @@ static gboolean
+ check_rbac_permissions (CkManager             *manager,
+                         DBusGMethodInvocation *context,
+                         const char            *action,
+-                        AuthorizedCallback     callback)
++                        AuthorizedCallback     callback,
++                        void                  *arg)
+ {
+         const char *sender;
+         char       *username;
+@@ -1085,7 +1094,7 @@ out:
+         g_free (username);
+ 
+         if (res && callback) {
+-                callback (manager, context);
++                callback (manager, context, arg);
+         }
+ 
+         return res;
+@@ -1094,7 +1103,8 @@ out:
+ 
+ static void
+ do_restart (CkManager             *manager,
+-            DBusGMethodInvocation *context)
++            DBusGMethodInvocation *context,
++            void                  *arg)
+ {
+         GError *error;
+         gboolean res;
+@@ -1145,9 +1155,10 @@ ck_manager_restart (CkManager           
+         g_debug ("ConsoleKit Restart: %s", action);
+ 
+ #if defined HAVE_POLKIT
+-        check_polkit_permissions (manager, context, action, do_restart);
++        check_polkit_permissions (manager, context, action, do_restart, NULL);
+ #elif defined ENABLE_RBAC_SHUTDOWN
+-        check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_restart);
++        check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_restart,
++                                NULL);
+ #else
+         g_warning ("Compiled without PolicyKit or RBAC support!");
+ #endif
+@@ -1168,7 +1179,7 @@ ck_manager_can_restart (CkManager  *mana
+         get_polkit_permissions (manager, action, context);
+ #else
+         if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY,
+-                                        NULL)) {
++                                        NULL, NULL)) {
+                 dbus_g_method_return (context, TRUE);
+         } else {
+                 dbus_g_method_return (context, FALSE);
+@@ -1180,7 +1191,8 @@ ck_manager_can_restart (CkManager  *mana
+ 
+ static void
+ do_stop (CkManager             *manager,
+-         DBusGMethodInvocation *context)
++         DBusGMethodInvocation *context,
++         void                  *arg)
+ {
+         GError *error;
+         gboolean res;
+@@ -1221,9 +1233,10 @@ ck_manager_stop (CkManager             *
+         }
+ 
+ #if defined HAVE_POLKIT
+-        check_polkit_permissions (manager, context, action, do_stop);
++        check_polkit_permissions (manager, context, action, do_stop, NULL);
+ #elif defined  ENABLE_RBAC_SHUTDOWN
+-        check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_stop);
++        check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY, do_stop,
++                                NULL);
+ #else
+         g_warning ("Compiled without PolicyKit or RBAC support!");
+ #endif
+@@ -1243,7 +1256,7 @@ ck_manager_can_stop (CkManager  *manager
+         get_polkit_permissions (manager, action, context);
+ #else
+         if (check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY,
+-                                        NULL)) {
++                                        NULL, NULL)) {
+                 dbus_g_method_return (context, TRUE);
+         } else {
+                 dbus_g_method_return (context, FALSE);
+@@ -1253,6 +1266,218 @@ ck_manager_can_stop (CkManager  *manager
+         return TRUE;
+ }
+ 
++#define OS_STRUCT_TYPE (dbus_g_type_get_struct ("GValueArray",   \
++                                                        G_TYPE_INT, \
++                                                        G_TYPE_STRING, \
++                                                        G_TYPE_STRING, \
++                                                        G_TYPE_STRING, \
++                                                        G_TYPE_BOOLEAN, \
++                                                        G_TYPE_INVALID))
++
++#if (defined(sun) && defined(__SVR4))
++static gint
++parse_output (const gchar *output, GPtrArray **systems)
++{
++        gchar **lines;
++        gint default_id = -1;
++
++        if (output == NULL)
++                return default_id;
++
++        lines = g_strsplit (output, "\n", 0);
++        for (int i = 0; lines[i] != NULL; i++) {
++                gchar *index;
++
++                if (i == 0 || i == 2) {
++                        /* We do not care 1st & 2nd line. */
++                        continue;
++                } else if (i == 1) {
++                        /* default boot menu entry */
++                        index = strchr (lines[i], ' ');
++                        if (index && (index + 1)) {
++                                default_id = atol (index + 1);
++                        } else {
++                                continue;
++                        }
++                } else if (lines[i][0] != NULL && systems) {
++                        /* boot menu entries */
++                        GValue elem = {0};
++
++                        index = strchr (lines[i], ' ');
++                        if (index && (index + 1)) {
++                                gint id;
++
++                                *index = '\0';
++                                id = atoi (lines[i]);
++                                g_value_init (&elem, OS_STRUCT_TYPE);
++                                g_value_take_boxed (&elem,
++                                        dbus_g_type_specialized_construct (OS_STRUCT_TYPE));
++                                dbus_g_type_struct_set (&elem,
++                                                0, id,
++                                                1, "",
++                                                2, "",
++                                                3, (index + 1),
++                                                4, (default_id == id),
++                                                G_MAXUINT);
++                                g_ptr_array_add (*systems,
++                                        g_value_get_boxed (&elem));
++                        } else {
++                                continue;
++                        }
++                }
++        }
++        g_strfreev (lines);
++        return default_id;
++}
++
++static gint
++get_available_boot_environment (CkManager *manager,
++                                GPtrArray **systems,
++                                DBusGMethodInvocation *context)
++{
++        gchar *cmd[] = {"/usr/sbin/bootadm", "list-menu", NULL};
++        gchar *output = NULL;
++        GError *err = NULL;
++        gint status;
++        gint ret = -1;
++
++        g_spawn_sync (NULL, cmd, NULL,
++                G_SPAWN_STDERR_TO_DEV_NULL, NULL,
++                NULL, &output, NULL,
++               &status, &err);
++        if (err) {
++                g_error_free (err);
++                return ret;
++        }
++
++        if (status == 0) {
++                ret = parse_output (output, systems);
++        }
++        if (output)
++                g_free (output);
++        return ret;
++}
++#endif
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.GetAvailableOperatingSystems
++*/
++gboolean
++ck_manager_get_available_operating_systems (CkManager *manager,
++                                           DBusGMethodInvocation *context)
++{
++        GPtrArray *systems;
++
++        g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
++
++        systems = g_ptr_array_new ();
++#if (defined(sun) && defined(__SVR4))
++        get_available_boot_environment (manager, &systems, context);
++#endif
++        dbus_g_method_return (context, systems);
++
++        return TRUE;
++}
++
++#if (defined(sun) && defined(__SVR4))
++static void
++set_default_boot_entry (CkManager *manager,
++                        gint id,
++                        DBusGMethodInvocation *context)
++{
++        gint default_id;
++
++        default_id = get_available_boot_environment (manager, NULL, context);
++        if (default_id != id) {
++                gchar *cmd;
++
++                g_debug ("Set default boot entry from %d to %d",
++                                default_id, id);
++                cmd = g_strdup_printf ("/usr/sbin/bootadm set-menu default=%d",
++                                        id);
++                if (g_spawn_command_line_async (cmd, NULL) == FALSE) {
++                        g_warning ("Unable to set default boot entry");
++                }
++                g_free (cmd);
++        }
++}
++#endif
++
++static void
++do_restart_with_parameters (CkManager *manager,
++                            DBusGMethodInvocation *context,
++                            void *parameters)
++{
++#if (defined(sun) && defined(__SVR4))
++        gchar **param;
++
++        if (parameters == NULL)
++                return;
++
++        param = g_strsplit ((gchar*)parameters, " ", 0);
++        for (int i = 0; param[i] != NULL; i++) {
++                if (strncmp (param[i], "id:", 3) == 0) {
++                        if (g_ascii_isdigit(param[i][3])) {
++                                gint id;
++
++                                id = atoi (&param[i][3]);
++                                set_default_boot_entry (manager, id, context);
++                        }
++#if defined(__x86__) || defined(__x86)
++                } else if (strncmp (param[i], "fast:", 5) == 0) {
++                        if (g_ascii_isdigit(param[i][5])) {
++                                gint val;
++
++                                val = atoi (&param[i][5]);
++                                if (val == 1)
++                                        scf_fastreboot_default_set_transient (1);
++                                else if (val == 0)
++                                        scf_fastreboot_default_set_transient (0);
++                        }
++#endif
++                }
++        }
++        g_strfreev (param);
++#endif
++        do_restart (manager, context, NULL);
++}
++
++/*
++  Example:
++  dbus-send --system --dest=org.freedesktop.ConsoleKit \
++  --type=method_call --print-reply --reply-timeout=2000 \
++  /org/freedesktop/ConsoleKit/Manager \
++  org.freedesktop.ConsoleKit.Manager.RestartWithParameters \
++  string:"id:0 fast:1"
++*/
++gboolean
++ck_manager_restart_with_parameters (CkManager *manager,
++                                    const gchar *parameters,
++                                    DBusGMethodInvocation *context)
++{
++        const char *action;
++
++        g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
++
++#if defined HAVE_POLKIT
++        if (get_system_num_users (manager) > 1) {
++                action = "org.freedesktop.consolekit.system.restart-multiple-users";
++        } else {
++                action = "org.freedesktop.consolekit.system.restart";
++        }
++        check_polkit_permissions (manager, context, action,
++                                do_restart_with_parameters, (void *)parameters);
++#elif defined ENABLE_RBAC_SHUTDOWN
++        check_rbac_permissions (manager, context, RBAC_SHUTDOWN_KEY,
++                                do_restart_with_parameters, (void *)parameters);
++#endif
++        return TRUE;
++}
++
+ static void
+ on_seat_active_session_changed_full (CkSeat     *seat,
+                                      CkSession  *old_session,
+diff -uprN ConsoleKit-0.4.1-backup/src/ck-manager.h ConsoleKit-0.4.1/src/ck-manager.h
+--- ConsoleKit-0.4.1-backup/src/ck-manager.h	2009-11-10 15:28:55.534101649 +0800
++++ ConsoleKit-0.4.1/src/ck-manager.h	2009-11-10 15:31:24.987857782 +0800
+@@ -88,6 +88,11 @@ gboolean            ck_manager_can_stop 
+                                                                 DBusGMethodInvocation *context);
+ gboolean            ck_manager_can_restart                    (CkManager *manager,
+                                                                DBusGMethodInvocation *context);
++gboolean             ck_manager_get_available_operating_systems (CkManager *manager,
++                                                                 DBusGMethodInvocation *context);
++gboolean             ck_manager_restart_with_parameters       (CkManager *manager,
++                                                               const gchar *parameters,
++                                                               DBusGMethodInvocation *context);
+ /* Authoritative properties */
+ gboolean            ck_manager_open_session                   (CkManager             *manager,
+                                                                DBusGMethodInvocation *context);
+diff -uprN ConsoleKit-0.4.1-backup/src/org.freedesktop.ConsoleKit.Manager.xml ConsoleKit-0.4.1/src/org.freedesktop.ConsoleKit.Manager.xml
+--- ConsoleKit-0.4.1-backup/src/org.freedesktop.ConsoleKit.Manager.xml	2009-11-10 15:28:55.540314508 +0800
++++ ConsoleKit-0.4.1/src/org.freedesktop.ConsoleKit.Manager.xml	2009-11-10 15:31:24.988157959 +0800
+@@ -32,6 +32,34 @@
+       <arg name="can_stop" type="b" direction="out"/>
+     </method>
+ 
++    <method name="GetAvailableOperatingSystems">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg name="systems" direction="out" type="a(isssb)">
++        <doc:doc>
++          <doc:summary>An array of available operating systems</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This method returns an array of available operating systems.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++
++    <method name="RestartWithParameters">
++      <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
++      <arg name="parameters" direction="in" type="s">
++        <doc:doc>
++          <doc:summary>The parameeters used to restart.</doc:summary>
++        </doc:doc>
++      </arg>
++      <doc:doc>
++        <doc:description>
++          <doc:para>This method initiates a request to restart (ie. reboot) with system specific parameters.</doc:para>
++        </doc:description>
++      </doc:doc>
++    </method>
++
+     <method name="OpenSession">
+       <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+       <arg name="cookie" direction="out" type="s">
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-10-ck-history.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,64 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2009-12-04 owner:yippi type:bug bugzilla:25436
+
+diff --git a/tools/ck-history.c b/tools/ck-history.c
+index 606106c..e7659d1 100644
+--- a/tools/ck-history.c
++++ b/tools/ck-history.c
+@@ -60,6 +60,8 @@ typedef enum {
+ #define DEFAULT_LOG_FILENAME LOCALSTATEDIR "/log/ConsoleKit/history"
+ #define MAX_LINE_LEN 2048
+ 
++#define IS_STR_SET(x) (x != NULL && x[0] != '\0')
++
+ static GList *all_events = NULL;
+ 
+ static gboolean
+@@ -515,21 +517,21 @@ print_last_report_record (GList      *list,
+ 
+         if (legacy_compat) {
+                 g_string_printf (str,
+-                                 "%-8.8s %-12.12s %-16.16s %-16.16s",
+-                                 username,
+-                                 utline != NULL ? utline : "",
+-                                 host != NULL ? host : "",
+-                                 addedtime);
++                                 "%s\t%s\t%s\t%s",
++                                 IS_STR_SET (username) ? username : "NULL",
++                                 IS_STR_SET (utline) ? utline : "NULL",
++                                 IS_STR_SET (host) ? host : "NULL",
++                                 IS_STR_SET (addedtime) ? addedtime : "NULL");
+         } else {
+                 g_string_printf (str,
+-                                 "%-8.8s %12s %-10.10s %-7.7s %-12.12s %-28.28s %-16.16s",
+-                                 username,
+-                                 session_type,
+-                                 session_id,
+-                                 seat_id,
+-                                 utline,
+-                                 host != NULL ? host : "",
+-                                 addedtime);
++                                 "%s\t%s\t%s\t%s\t%s\t%s\t%s",
++                                 IS_STR_SET (username) ? username : "NULL",
++                                 IS_STR_SET (session_type) ? session_type : "NULL",
++                                 IS_STR_SET (session_id) ? session_id : "NULL",
++                                 IS_STR_SET (seat_id) ? seat_id : "NULL",
++                                 IS_STR_SET (utline) ? utline : "NULL",
++                                 IS_STR_SET (host) ? host : "NULL",
++                                 IS_STR_SET (addedtime) ? addedtime : "NULL");
+         }
+ 
+         g_free (username);
+@@ -576,9 +578,9 @@ print_last_report_record (GList      *list,
+         }
+ 
+         g_string_append_printf (str,
+-                                " %-7.7s %-12.12s",
+-                                removedtime,
+-                                duration);
++                                "\t%s\t%s",
++                                IS_STR_SET (removedtime) ? removedtime : "NULL",
++                                IS_STR_SET (duration) ? duration : "NULL");
+ 
+         g_print ("%s\n", str->str);
+         g_string_free (str, TRUE);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-11-sol-vtdaemon.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,128 @@
+From c2e317911f2fae424ec9a121f267e4a83efcf1c5 Mon Sep 17 00:00:00 2001
+From: Halton Huo <[email protected]>
+Date: Wed, 19 May 2010 12:46:25 +0800
+Subject: [PATCH] Enhancement CanActivateSessions for OpenSolaris.
+
+VT switching is always enabled on Linux, but for OpenSolaris VT switching
+can be truned of by 'svcadm disable vtdaemon'. So we should also check
+whether the service vtdaemon is online on OpenSolaris.
+
+https://bugs.freedesktop.org/show_bug.cgi?id=26055
+---
+ src/Makefile.am          |    1 +
+ src/ck-sysdeps-freebsd.c |    6 ++++++
+ src/ck-sysdeps-linux.c   |    6 ++++++
+ src/ck-sysdeps-solaris.c |   18 ++++++++++++++++++
+ src/ck-sysdeps.h         |    1 +
+ 5 files changed, 32 insertions(+), 0 deletions(-)
+
+diff --git a/src/Makefile.am b/src/Makefile.am
+index 6ab05c8..869decd 100644
+--- a/src/Makefile.am
++++ b/src/Makefile.am
+@@ -49,6 +49,7 @@ if CK_COMPILE_SOLARIS
+ libck_la_SOURCES +=		\
+ 	ck-sysdeps-solaris.c	\
+ 	$(NULL)
++libck_la_LIBADD = -lscf
+ endif
+ if CK_COMPILE_FREEBSD
+ libck_la_SOURCES +=		\
+diff --git a/src/ck-sysdeps-freebsd.c b/src/ck-sysdeps-freebsd.c
+index a30c380..df2b0f4 100644
+--- a/src/ck-sysdeps-freebsd.c
++++ b/src/ck-sysdeps-freebsd.c
+@@ -361,6 +361,12 @@ done:
+         return ret;
+ }
+ 
++gboolean
++ck_supports_activatable_consoles (void)
++{
++        return TRUE;
++}
++
+ char *
+ ck_get_console_device_for_num (guint num)
+ {
+diff --git a/src/ck-sysdeps-linux.c b/src/ck-sysdeps-linux.c
+index 09db310..a95272e 100644
+--- a/src/ck-sysdeps-linux.c
++++ b/src/ck-sysdeps-linux.c
+@@ -693,6 +693,12 @@ ck_get_max_num_consoles (guint *num)
+         return TRUE;
+ }
+ 
++gboolean
++ck_supports_activatable_consoles (void)
++{
++        return TRUE;
++}
++
+ char *
+ ck_get_console_device_for_num (guint num)
+ {
+diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c
+index 335ab8b..bb37e1e 100644
+--- a/src/ck-sysdeps-solaris.c
++++ b/src/ck-sysdeps-solaris.c
+@@ -33,6 +33,7 @@
+ #ifdef HAVE_SYS_VT_H
+ #include <sys/vt.h>
+ #endif
++#include <libscf.h>
+ 
+ #define DEV_ENCODE(M,m) ( \
+   ( (M&0xfff) << 8)   |   ( (m&0xfff00) << 12)   |   (m&0xff)   \
+@@ -419,6 +420,23 @@ ck_get_max_num_consoles (guint *num)
+         return ret;
+ }
+ 
++gboolean
++ck_supports_activatable_consoles (void)
++{
++        char *state = NULL;
++        gboolean vt_enabled;
++                               
++        state = smf_get_state ("svc:/system/vtdaemon:default");
++        if (state && g_str_equal (state, SCF_STATE_STRING_ONLINE)) {
++                vt_enabled = TRUE;
++        } else {
++                vt_enabled = FALSE;
++        }           
++                    
++        g_free (state);
++        return vt_enabled;
++}
++
+ char *
+ ck_get_console_device_for_num (guint num)
+ {
+diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h
+index c3f3756..8f22d52 100644
+--- a/src/ck-sysdeps.h
++++ b/src/ck-sysdeps.h
+@@ -61,6 +61,7 @@ gboolean     ck_fd_is_a_console               (int             fd);
+ gboolean     ck_is_root_user                  (void);
+ 
+ gboolean     ck_get_max_num_consoles          (guint          *num);
++gboolean     ck_supports_activatable_consoles (void);
+ 
+ char *       ck_get_console_device_for_num    (guint           num);
+ gboolean     ck_get_console_num_from_device   (const char     *device,
+-- 
+1.5.6.5
+
+--- ConsoleKit-0.4.1/src/ck-seat.c-orig	2011-02-07 22:09:46.085393510 -0600
++++ ConsoleKit-0.4.1/src/ck-seat.c	2011-02-07 22:10:58.766029875 -0600
+@@ -1172,6 +1172,10 @@ ck_seat_can_activate_sessions (CkSeat   
+ {
+         g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+ 
++        if (ck_supports_activatable_consoles () == FALSE) {
++                return FALSE; 
++        }
++
+         if (can_activate != NULL) {
+                 *can_activate = (seat->priv->kind == CK_SEAT_KIND_STATIC);
+         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-12-suppress-warning.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,13 @@
+Existing set of desktop patches
+
+--- ConsoleKit-0.4.1/src/ck-vt-monitor.c-orig	2011-02-23 15:43:10.541619433 -0600
++++ ConsoleKit-0.4.1/src/ck-vt-monitor.c	2011-02-23 15:43:21.779875852 -0600
+@@ -470,7 +470,7 @@ ck_vt_monitor_init (CkVtMonitor *vt_moni
+                 res = ck_get_active_console_num (fd, &active);
+                 if (! res) {
+                         /* FIXME: handle failure */
+-                        g_warning ("Could not determine active console");
++                        g_debug ("Could not determine active console");
+                         active = 0;
+                 }
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-13-vt-switch.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,116 @@
+Patch migrated from desktop gate, where it was listed as:
+# This relates to GDM upstream bugzilla bug #618047.
+# date:2010-07-20 owner:yippi type:bug bugster:7032861
+
+which corresponds to:
+Bug 15706421 - SUNBT7032861 exit as first logged in user during console
+ switching dumps user to command line
+
+--- ConsoleKit-0.4.1/src/ck-seat.c-orig	2011-07-28 01:25:03.688403859 -0500
++++ ConsoleKit-0.4.1/src/ck-seat.c	2011-07-28 01:27:24.076536756 -0500
+@@ -951,9 +951,32 @@ find_possible_session_to_activate (CkSea
+                 ck_session_is_open (value, &is_open, NULL);
+ 
+                 if (is_open) {
++                        GError  *vt_error = NULL;
++                        char    *device;
++                        guint    num;
++                        gboolean ret;
++
+                         login_session = NULL;
+-                        change_active_session (seat, value);
+-                        break;
++
++                        g_debug ("Found open session.");
++
++                        switch (seat->priv->kind) {
++                           case CK_SEAT_KIND_STATIC:
++                                device = NULL;
++                                ck_session_get_x11_display_device (value, &device, NULL);
++
++                                if (device != NULL) {
++                                   ret = ck_get_console_num_from_device (device, &num);
++                                   if (ret) {
++                                           g_debug ("Activating VT %d", num);
++                                           ck_vt_monitor_set_active (seat->priv->vt_monitor, num, &vt_error);
++                                   }
++                                }
++                                break;
++                            case CK_SEAT_KIND_DYNAMIC:
++                                change_active_session (seat, value);
++                                break;
++                        }
+                 }
+ 
+                 ck_session_get_session_type (value, &session_type, NULL);
+@@ -1037,6 +1060,11 @@ ck_seat_remove_session (CkSeat         *
+         CkSession *orig_session;
+         gboolean   res;
+         gboolean   ret;
++        GHashTableIter iter;
++        gpointer       key, value;
++        gboolean       found_login = FALSE;
++        gboolean       is_open;
++        char          *session_type = NULL;
+ 
+         g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+ 
+@@ -1076,7 +1104,48 @@ ck_seat_remove_session (CkSeat         *
+         g_signal_emit (seat, signals [SESSION_REMOVED], 0, ssid);
+ 
+         /* try to change the active session */
+-        maybe_update_active_session (seat);
++
++        /* On session exit, first try to switch to any active login sessions */
++        g_hash_table_iter_init (&iter, seat->priv->sessions);
++        if (seat->priv->kind == CK_SEAT_KIND_STATIC) {
++                while (seat->priv->kind == CK_SEAT_KIND_STATIC && g_hash_table_iter_next (&iter, &key, &value)) {
++                        CkSession *login_session = value;
++                        ck_session_get_session_type (login_session, &session_type, NULL);
++                        ck_session_is_open (login_session, &is_open, NULL);
++
++                        if (is_open && IS_STR_SET (session_type) &&
++                            g_str_equal (session_type, "LoginWindow")) {
++                                GError    *vt_error = NULL;
++                                char      *device;
++                                guint      num;
++
++                                g_debug ("Found a LoginWindow");
++                                device = NULL;
++                                ck_session_get_x11_display_device (login_session, &device, NULL);
++
++                                if (device != NULL) {
++                                        ret = ck_get_console_num_from_device (device, &num);
++                                        if (ret) {
++                                                g_debug ("Setting active to %d", num);
++                                                found_login = TRUE;
++                                                ck_vt_monitor_set_active (seat->priv->vt_monitor, num, &vt_error);
++                                        } else {
++                                               g_debug ("The LoginWindow device has no console number, not using.");
++                                        }
++                                } else {
++                                       g_debug ("The LoginWindow display has no x11 display device, not using.");
++                                }
++                        }
++                        if (session_type != NULL)
++                                g_free (session_type);
++                }
++        }
++
++        /* Otherwise, look for an active session */
++        if (found_login == FALSE) {
++                g_debug ("Login not found.  Maybe update active session");
++                maybe_update_active_session (seat);
++        }
+ 
+         if (orig_session != NULL) {
+                 g_object_unref (orig_session);
+@@ -1345,8 +1412,6 @@ active_vt_changed (CkVtMonitor    *vt_mo
+                    CkSeat         *seat)
+ {
+         g_debug ("Active vt changed: %u", num);
+-
+-        update_active_vt (seat, num);
+ }
+ 
+ gboolean
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-14-shutdown.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,70 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2012-06-02 owner:yippi type:bug bugster:7165738
+
+which corresponds to:
+Bug 15789123 - SUNBT7165738 gdm-session-worker too noisy on system shutdown
+
+
+--- ConsoleKit-0.4.1/src/ck-seat.c-orig	2012-06-01 23:28:22.322398818 -0500
++++ ConsoleKit-0.4.1/src/ck-seat.c	2012-06-01 23:37:52.032208906 -0500
+@@ -101,6 +101,8 @@ enum {
+ 
+ static guint signals [LAST_SIGNAL] = { 0, };
+ 
++static gboolean ck_seat_shutdown = FALSE;
++
+ static void     ck_seat_class_init  (CkSeatClass *klass);
+ static void     ck_seat_init        (CkSeat      *seat);
+ static void     ck_seat_finalize    (GObject     *object);
+@@ -120,6 +122,13 @@ ck_seat_error_quark (void)
+ 
+ #define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+ 
++void
++ck_seat_set_shutdown (void)
++{
++   g_debug ("CkSeat: setting shutdown, will stop restarting displays");
++   ck_seat_shutdown = TRUE;
++}
++
+ GType
+ ck_seat_kind_get_type (void)
+ {
+@@ -1157,7 +1166,7 @@ ck_seat_remove_session (CkSeat         *
+         }
+ 
+         /* Otherwise, look for an active session */
+-        if (found_login == FALSE) {
++        if (!ck_seat_shutdown && found_login == FALSE) {
+                 g_debug ("Login not found.  Maybe update active session");
+                 maybe_update_active_session (seat);
+         }
+--- ConsoleKit-0.4.1/src/ck-manager.c-orig	2012-06-01 23:27:14.221278799 -0500
++++ ConsoleKit-0.4.1/src/ck-manager.c	2012-06-01 23:36:43.104682051 -0500
+@@ -1133,6 +1133,7 @@ do_restart (CkManager             *manag
+ 
+                 g_error_free (error);
+         } else {
++                ck_seat_set_shutdown ();
+                 dbus_g_method_return (context);
+         }
+ }
+@@ -1220,6 +1221,7 @@ do_stop (CkManager             *manager,
+                 g_error_free (new_error);
+                 g_error_free (error);
+         } else {
++                ck_seat_set_shutdown ();
+                 dbus_g_method_return (context);
+         }
+ }
+--- ConsoleKit-0.4.1/src/ck-seat.h-orig	2012-06-01 23:34:08.023566142 -0500
++++ ConsoleKit-0.4.1/src/ck-seat.h	2012-06-01 23:34:42.825581256 -0500
+@@ -178,6 +178,8 @@ gboolean            ck_seat_no_respawn  
+                                                    CkSession             *session,
+                                                    GError               **error);
+ 
++void                ck_seat_set_shutdown          (void);
++
+ G_END_DECLS
+ 
+ #endif /* __CK_SEAT_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-15-bootadm-parse.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,126 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2012-06-08 owner:sethg type:bug bugster:7175632
+
+which corresponds to:
+Bug 15797081 - SUNBT7175632 ConsoleKit's bootadm list-menu parser needs to be
+ much more robust
+
+--- ConsoleKit-0.4.1/src/ck-manager.c-orig	Fri Jun 15 10:43:58 2012
++++ ConsoleKit-0.4.1/src/ck-manager.c	Fri Jun 15 10:44:03 2012
+@@ -41,6 +41,7 @@
+ 
+ #if (defined(sun) && defined(__SVR4))
+ #include <libscf_priv.h>
++#include <ctype.h>
+ #endif
+ 
+ #if defined HAVE_POLKIT
+@@ -1282,10 +1283,36 @@
+ 
+ #if (defined(sun) && defined(__SVR4))
+ static gint
++is_decimal_string(gchar *token, gint *indexp)
++{
++	gint i;
++
++	for (i = 0; token[i] != 0; i++)
++		if (!isdigit(token[i]))
++			return (0);
++
++	if (i > 0) {
++		if (indexp)
++			*indexp = strtol(token, 0, 10);
++		return (1);
++	}
++
++	/* If the string is empty, return failure */
++	return (0);
++}
++
++/*
++ * The output of bootadm should be parsed intelligently; not based on
++ * the order of lines, but based on the line semantics.  We look for
++ * the keyword "default" when looking for the default entry.  Lines
++ * that start with a number specify boot entries that should be
++ * captured for display in the dialog's boot entry list.
++ */
++static gint
+ parse_output (const gchar *output, GPtrArray **systems)
+ {
+         gchar **lines;
+-        gint default_id = -1;
++        gint id, default_id = -1;
+ 
+         if (output == NULL)
+                 return default_id;
+@@ -1292,45 +1319,40 @@
+ 
+         lines = g_strsplit (output, "\n", 0);
+         for (int i = 0; lines[i] != NULL; i++) {
+-                gchar *index;
++		gchar **tokens;
+ 
+-                if (i == 0 || i == 2) {
+-                        /* We do not care 1st & 2nd line. */
+-                        continue;
+-                } else if (i == 1) {
+-                        /* default boot menu entry */
+-                        index = strchr (lines[i], ' ');
+-                        if (index && (index + 1)) {
+-                                default_id = atol (index + 1);
+-                        } else {
+-                                continue;
+-                        }
+-                } else if (lines[i][0] != NULL && systems) {
+-                        /* boot menu entries */
+-                        GValue elem = {0};
++		/* Split lines into 2 tokens maximum */
++		tokens = g_strsplit_set(lines[i], " \t", 2);
++		if (tokens == 0) {
++			continue;
++		} else if (tokens[0] == 0) {
++			g_strfreev(tokens);
++			continue;
++		}
+ 
+-                        index = strchr (lines[i], ' ');
+-                        if (index && (index + 1)) {
+-                                gint id;
++                if (tokens[1] != 0 && strcmp(tokens[0], "default") == 0) {
++			errno = 0;
++			default_id = strtol (tokens[1], 0, 10);
++			if (errno != 0)
++				default_id = 0;
++                } else if (is_decimal_string(tokens[0], &id) && systems) {
+ 
+-                                *index = '\0';
+-                                id = atoi (lines[i]);
+-                                g_value_init (&elem, OS_STRUCT_TYPE);
+-                                g_value_take_boxed (&elem,
+-                                        dbus_g_type_specialized_construct (OS_STRUCT_TYPE));
+-                                dbus_g_type_struct_set (&elem,
++			/* boot menu entries */
++			GValue elem = {0};
++
++			g_value_init (&elem, OS_STRUCT_TYPE);
++			g_value_take_boxed (&elem,
++			    dbus_g_type_specialized_construct (OS_STRUCT_TYPE));
++			dbus_g_type_struct_set (&elem,
+                                                 0, id,
+                                                 1, "",
+                                                 2, "",
+-                                                3, (index + 1),
++                                                3, (tokens[1] && tokens[1][0]) ? tokens[1] : "<no title specified>",
+                                                 4, (default_id == id),
+                                                 G_MAXUINT);
+-                                g_ptr_array_add (*systems,
+-                                        g_value_get_boxed (&elem));
+-                        } else {
+-                                continue;
+-                        }
++			g_ptr_array_add (*systems, g_value_get_boxed (&elem));
+                 }
++		g_strfreev(tokens);
+         }
+         g_strfreev (lines);
+         return default_id;
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-16-multidcu.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,124 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2013-10-21 owner:rohini type:bug 
+
+The hg log for it lists it in the putback of:
+17019578 SPARC M series: gdm's ConsoleKit support for multi-session
+
+
+--- ConsoleKit-0.4.1/data/displays.d/Makefile.am	2016-11-10 20:23:27.545681109 -0800
++++ ConsoleKit-0.4.1/data/displays.d/Makefile.am	2016-11-10 20:28:46.404776728 -0800
+@@ -5,7 +5,9 @@
+ 	Local.display.in \
+ 	RemoteMachine.display.in \
+ 	LocalVNC.display.in \
+-	Headless.display.in
++	Headless.display.in \
++	MultiDCU.display.in \
++	HotPlug.display.in
+ 
+ display_DATA = $(display_in_files:.display.in=.display)
+ 
+@@ -17,6 +19,10 @@
+ 	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
+ Headless.display: Headless.display.in Makefile
+ 	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
++MultiDCU.display: MultiDCU.display.in Makefile
++	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
++HotPlug.display: HotPlug.display.in Makefile
++	sed -e "s|\@X11_DIR\@|$(X11_DIR)|" $< > $@
+ 
+ EXTRA_DIST =						\
+ 	$(display_in_files)				\
+
+diff -urpN ConsoleKit-0.4.1.orig/data/displays.d/MultiDCU.display.in ConsoleKit-0.4.1/data/displays.d/MultiDCU.display.in
+--- ConsoleKit-0.4.1.orig/data/displays.d/MultiDCU.display.in	1970-01-01 05:30:00.000000000 +0530
++++ ConsoleKit-0.4.1/data/displays.d/MultiDCU.display.in	2013-10-21 11:49:46.380264327 +0530
+@@ -0,0 +1,6 @@
++[Display]
++Type=X11
++
++[X11]
++Exec=@X11_DIR@/Xserver $display -layout $xsession -br -novtswitch -auth $auth
++
+diff -urpN ConsoleKit-0.4.1.orig/data/displays.d/HotPlug.display.in ConsoleKit-0.4.1/data/displays.d/HotPlug.display.in
+--- ConsoleKit-0.4.1.orig/data/displays.d/HotPlug.display.in	1970-01-01 05:30:00.000000000 +0530
++++ ConsoleKit-0.4.1/data/displays.d/HotPlug.display.in	2013-10-21 11:49:46.380264327 +0530
+@@ -0,0 +1,6 @@
++[Display]
++Type=X11
++
++[X11]
++Exec=@X11_DIR@/Xserver $display -isolateDevice $busid -br -novtswitch -auth $auth
++
+diff -urpN ConsoleKit-0.4.1.orig/data/sessions.d/Makefile.am ConsoleKit-0.4.1/data/sessions.d/Makefile.am
+--- ConsoleKit-0.4.1.orig/data/sessions.d/Makefile.am	2013-10-21 11:07:48.647060294 +0530
++++ ConsoleKit-0.4.1/data/sessions.d/Makefile.am	2013-10-21 11:10:46.711157036 +0530
+@@ -5,7 +5,11 @@ session_DATA = \
+ 	Headless.session		\
+ 	Local.session			\
+ 	LocalVNC.session		\
+-	Remote.session
++	Remote.session			\
++	MultiDCU0.session		\
++	MultiDCU1.session		\
++	MultiDCU2.session		\
++	MultiDCU3.session
+ 
+ EXTRA_DIST =				\
+ 	$(session_DATA)			\
+diff -urpN ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU0.session ConsoleKit-0.4.1/data/sessions.d/MultiDCU0.session
+--- ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU0.session	1970-01-01 05:30:00.000000000 +0530
++++ ConsoleKit-0.4.1/data/sessions.d/MultiDCU0.session	2013-10-21 11:08:15.415087346 +0530
+@@ -0,0 +1,10 @@
++[Session Entry]
++Name=MultiDCU0
++Type=LoginWindow
++Description=Multi-DCU Session Login Screen
++DisplayTemplate=MultiDCU
++
++[MultiDCU]
++display=:0
++xsession=Xsession0
++
+diff -urpN ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU1.session ConsoleKit-0.4.1/data/sessions.d/MultiDCU1.session
+--- ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU1.session	1970-01-01 05:30:00.000000000 +0530
++++ ConsoleKit-0.4.1/data/sessions.d/MultiDCU1.session	2013-10-21 11:08:15.415350056 +0530
+@@ -0,0 +1,10 @@
++[Session Entry]
++Name=MultiDCU1
++Type=LoginWindow
++Description=Multi-DCU Session Login Screen
++DisplayTemplate=MultiDCU
++
++[MultiDCU]
++display=:1
++xsession=Xsession1
++
+diff -urpN ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU2.session ConsoleKit-0.4.1/data/sessions.d/MultiDCU2.session
+--- ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU2.session	1970-01-01 05:30:00.000000000 +0530
++++ ConsoleKit-0.4.1/data/sessions.d/MultiDCU2.session	2013-10-21 11:08:15.415560561 +0530
+@@ -0,0 +1,10 @@
++[Session Entry]
++Name=MultiDCU2
++Type=LoginWindow
++Description=Multi-DCU Session Login Screen
++DisplayTemplate=MultiDCU
++
++[MultiDCU]
++display=:2
++xsession=Xsession2
++
+diff -urpN ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU3.session ConsoleKit-0.4.1/data/sessions.d/MultiDCU3.session
+--- ConsoleKit-0.4.1.orig/data/sessions.d/MultiDCU3.session	1970-01-01 05:30:00.000000000 +0530
++++ ConsoleKit-0.4.1/data/sessions.d/MultiDCU3.session	2013-10-21 11:08:15.415749387 +0530
+@@ -0,0 +1,10 @@
++[Session Entry]
++Name=MultiDCU3
++Type=LoginWindow
++Description=Multi-DCU Session Login Screen
++DisplayTemplate=MultiDCU
++
++[MultiDCU]
++display=:3
++xsession=Xsession3
++
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-17-multisession.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,50 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2014-06-04 owner:henzhao type:bug bug:18554239
+
+which corresponds to:
+        18554239 gdm fails to spawn new Xorg when killed by SIGTERM
+
+
+
+diff --git a/ck-seat.c.old b/ck-seat.c
+index 9981e53..e9d954f 100644
+--- a/src/ck-seat.c.old
++++ b/src/ck-seat.c
+@@ -964,6 +964,7 @@ find_possible_session_to_activate (CkSeat *seat)
+         gboolean       is_open;
+         char          *session_type = NULL;
+         CkSession     *login_session = NULL;
++	gboolean       done = FALSE;
+ 
+         g_debug ("CkSeat: Find possible session to activate");
+         g_hash_table_iter_init (&iter, seat->priv->sessions);
+@@ -977,7 +978,8 @@ find_possible_session_to_activate (CkSeat *seat)
+                         guint    num;
+                         gboolean ret;
+ 
+-                        login_session = NULL;
++			if (!done)
++				login_session = NULL;
+ 
+                         g_debug ("Found open session.");
+ 
+@@ -1006,9 +1008,16 @@ find_possible_session_to_activate (CkSeat *seat)
+ 
+                 if (IS_STR_SET (session_type) &&
+                     g_str_equal (session_type, "LoginWindow")) {
+-                        login_session = value;
+-                        g_debug ("CkSeat: Setting login_session");
+-                        g_free (session_type);
++
++			if (!done) {
++				login_session = value;
++				/* Give non-open session a precedence */
++				if (!is_open)
++					done = TRUE;
++                        	g_debug ("CkSeat: Setting login_session");
++			}
++
++			g_free (session_type);
+                 }
+         }
+ 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-18-seattool.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,20 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2014-06-04 owner:henzhao type:bug bugdb:18057681
+
+which corresponds to:
+18057681 ck-seat-tool -a only accepts one variable
+
+diff --git a/tools/ck-seat-tool.c.orig b/tools/ck-seat-tool.c
+index 347c81c..773afb7 100644
+--- a/tools/ck-seat-tool.c.orig
++++ b/tools/ck-seat-tool.c
+@@ -184,7 +184,7 @@ add_session (DBusGConnection  *connection)
+                                            (GDestroyNotify) g_free);
+ 
+         if (remaining_args) {
+-                for (i = 0; i < G_N_ELEMENTS (remaining_args); i++) {
++                for (i = 0; i < g_strv_length (remaining_args); i++) {
+                         char **arr;
+ 
+                         /* split var=value */
+
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-19-listsessions.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,56 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2014-06-18 owner:henzhao type:bug bugdb:17902662
+
+which corresponds to:
+17902662 ConsoleKit improvement on ck-list-sessions
+
+diff --git a/tools/list-sessions.c.orig b/tools/list-sessions.c
+index cc69d57..be35ecf 100644
+--- a/tools/list-sessions.c.orig
++++ b/tools/list-sessions.c
+@@ -56,8 +56,10 @@ typedef struct CkSessionOutput {
+ static gboolean do_all = FALSE;
+ static gboolean do_version = FALSE;
+ static char *do_format = NULL;
++static char *session_id = NULL;
+ static GOptionEntry entries [] = {
+         { "all", 'a', 0, G_OPTION_ARG_NONE, &do_all, N_("List all sessions. If not given, only list open sessions"), NULL },
++        { "sid", 's', 0, G_OPTION_ARG_STRING, &session_id, N_("List one sessions."), NULL },
+         { "format", 'f', 0, G_OPTION_ARG_STRING, &do_format, N_("Prints information according to the given format"), NULL },
+         { "version", 'V', 0, G_OPTION_ARG_NONE, &do_version, N_("Version of this application"), NULL },
+         { NULL }
+@@ -242,7 +244,7 @@ list_session (DBusGConnection *connection,
+         get_string (proxy, "GetCreationTime", &creation_time);
+         get_string (proxy, "GetIdleSinceHint", &idle_since_hint);
+ 
+-        if (!do_all && !is_open) {
++        if (!do_all && !is_open && !session_id) {
+                 return;
+         }
+ 
+@@ -352,11 +354,23 @@ list_sessions (DBusGConnection *connection,
+         }
+ 
+         for (i = 0; i < sessions->len; i++) {
+-                char *ssid;
++		char 		*ssid;
++		gboolean	do_it = TRUE;
+ 
+                 ssid = g_ptr_array_index (sessions, i);
+ 
+-                list_session (connection, ssid);
++		if (session_id) {
++			do_it = FALSE;
++
++			if (!g_strcmp0(session_id, ssid))
++				do_it = TRUE;
++
++			else if (!g_strcmp0(session_id, g_basename(ssid)))
++					do_it = TRUE;
++		}
++
++		if (do_it)
++                	list_session (connection, ssid);
+ 
+                 g_free (ssid);
+         }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/components/desktop/consolekit/patches/ConsoleKit-20-seattool-2.patch	Wed Nov 16 18:51:32 2016 -0800
@@ -0,0 +1,126 @@
+Patch migrated from desktop gate, where it was listed as:
+# date:2014-06-18 owner:henzhao type:bug bugdb:17902324
+
+which corresponds to:
+17902324 ConsoleKit improvement on ck-seat-tool -a ...
+
+diff --git a/tools/ck-seat-tool.c.old b/tools/ck-seat-tool.c
+index 773afb7..8a0bdd5 100644
+--- a/tools/ck-seat-tool.c.old
++++ b/tools/ck-seat-tool.c
+@@ -66,7 +66,7 @@ static const GOptionEntry options [] = {
+         { NULL }
+ };
+ 
+-static void
++static gboolean
+ add_session (DBusGConnection  *connection)
+ {
+         DBusGProxy *mgr_proxy = NULL;
+@@ -92,7 +92,7 @@ add_session (DBusGConnection  *connection)
+                                                CK_MANAGER_PATH,
+                                                CK_MANAGER_INTERFACE);
+         if (mgr_proxy == NULL) {
+-                return;
++                return FALSE;
+         }
+ 
+         if (! IS_STR_SET(seat_id)) {
+@@ -110,7 +110,7 @@ add_session (DBusGConnection  *connection)
+                         g_warning ("Unable to add seat: %s", error->message);
+                         g_error_free (error);
+                         g_object_unref (mgr_proxy);
+-                        return;
++                        return FALSE;
+                 }
+ 
+         } else {
+@@ -133,7 +133,7 @@ add_session (DBusGConnection  *connection)
+                         g_warning ("Unable to get seat list: %s", error->message);
+                         g_error_free (error);
+                         g_object_unref (mgr_proxy);
+-                        return;
++                        return FALSE;
+                 }
+ 
+                 found = FALSE;
+@@ -163,7 +163,7 @@ add_session (DBusGConnection  *connection)
+                                 g_warning ("Unable to add seat: %s", error->message);
+                                 g_error_free (error);
+                                 g_object_unref (mgr_proxy);
+-                                return;
++                                return FALSE;
+                         }
+                 }
+         }
+@@ -176,7 +176,7 @@ add_session (DBusGConnection  *connection)
+         if (seat_proxy == NULL) {
+                 g_warning ("Failed to talk to seat '%s'", sid);
+                 g_object_unref (mgr_proxy);
+-                return;
++                return FALSE;
+         }
+ 
+         variables = g_hash_table_new_full (g_str_hash, g_str_equal,
+@@ -218,11 +218,15 @@ add_session (DBusGConnection  *connection)
+                                             "Manage",
+                                             G_TYPE_INVALID,
+                                             G_TYPE_INVALID);
+-                g_print ("Seat %s with session %s has been added\n", sid, ssid);
++		 /* If a session is successfully added, print sessionid to stdout. 
++		    dsession uses the output of "ck-seat-tool -a" to obtain session ID */
++		 g_print ("%s\n", g_basename (ssid)); 
+         }
+ 
+         g_object_unref (seat_proxy);
+         g_object_unref (mgr_proxy);
++
++	return res;
+ }
+ 
+ static gboolean
+@@ -329,7 +332,7 @@ find_seat_id_from_session_id (DBusGConnection *connection,
+         return sid;
+ }
+ 
+-static void
++static gboolean
+ delete_session (DBusGConnection *connection)
+ {
+         DBusGProxy *proxy;
+@@ -348,7 +351,7 @@ delete_session (DBusGConnection *connection)
+                                            CK_MANAGER_PATH,
+                                            CK_MANAGER_INTERFACE);
+         if (proxy == NULL) {
+-                return;
++                return FALSE;
+         }
+ 
+         sid = find_seat_id_from_session_id (connection, proxy, ssid, &is_last_session);
+@@ -374,6 +377,8 @@ delete_session (DBusGConnection *connection)
+         }
+ 
+         g_object_unref (proxy);
++
++	return TRUE;
+ }
+ 
+ int
+@@ -437,9 +442,15 @@ main (int argc, char *argv[])
+ 
+ 
+         if (add) {
+-                add_session (connection);
++                if (add_session (connection))
++			return 0;
++		else
++			exit (1);
+         } else if (delete) {
+-                delete_session (connection);
++                if (delete_session (connection))
++			return 0;
++		else
++			exit (1);
+         } else {
+                 g_warning ("Invaild parameters!");
+                 exit (1);
--- a/components/meta-packages/incorporation-cache	Wed Nov 16 18:51:09 2016 -0800
+++ b/components/meta-packages/incorporation-cache	Wed Nov 16 18:51:32 2016 -0800
@@ -67,7 +67,5 @@
 consolidation/userland/userland-incorporation:library/python/[email protected]
 consolidation/userland/userland-incorporation:library/python/[email protected]
 consolidation/userland/userland-incorporation:library/python/[email protected]
-consolidation/userland/userland-incorporation:library/security/pam/module/[email protected]
 consolidation/userland/userland-incorporation:library/speech/[email protected]
-consolidation/userland/userland-incorporation:library/xdg/[email protected]
 consolidation/userland/userland-incorporation:service/[email protected]