summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorWilliam Jon McCann <mccannwj@acsnb12.pha.jhu.edu>2006-10-25 14:38:19 -0400
committerWilliam Jon McCann <mccannwj@acsnb12.pha.jhu.edu>2006-10-25 14:38:19 -0400
commita08530e838218b3c5859550058e78b8f1abee434 (patch)
treec54037c29cd86ebbecf6d9e10eb86da1ba657c9e /src
Initial import
Diffstat (limited to 'src')
-rw-r--r--src/Makefile.am90
-rw-r--r--src/Makefile.in724
-rw-r--r--src/ck-debug.c153
-rw-r--r--src/ck-debug.h72
-rw-r--r--src/ck-manager-glue.h223
-rw-r--r--src/ck-manager.c1017
-rw-r--r--src/ck-manager.h97
-rw-r--r--src/ck-manager.xml48
-rw-r--r--src/ck-marshal.c126
-rw-r--r--src/ck-marshal.h28
-rw-r--r--src/ck-marshal.list2
-rw-r--r--src/ck-seat-glue.h167
-rw-r--r--src/ck-seat.c724
-rw-r--r--src/ck-seat.h111
-rw-r--r--src/ck-seat.xml27
-rw-r--r--src/ck-session-glue.h135
-rw-r--r--src/ck-session.c744
-rw-r--r--src/ck-session.h156
-rw-r--r--src/ck-session.xml49
-rw-r--r--src/ck-vt-monitor.c360
-rw-r--r--src/ck-vt-monitor.h71
-rw-r--r--src/getfd.c52
-rw-r--r--src/main.c141
-rw-r--r--src/proc-linux.c473
-rw-r--r--src/proc.h41
-rwxr-xr-xsrc/test-session51
-rwxr-xr-xsrc/valgrind.sh12
27 files changed, 5894 insertions, 0 deletions
diff --git a/src/Makefile.am b/src/Makefile.am
new file mode 100644
index 0000000..cbeb646
--- /dev/null
+++ b/src/Makefile.am
@@ -0,0 +1,90 @@
+## We require new-style dependency handling.
+AUTOMAKE_OPTIONS = 1.7
+
+NULL =
+
+SUBDIRS = \
+ $(NULL)
+
+INCLUDES = \
+ -I. \
+ -I$(srcdir) \
+ $(CONSOLE_KIT_CFLAGS) \
+ $(DISABLE_DEPRECATED_CFLAGS) \
+ -DPREFIX=\""$(prefix)"\" \
+ -DBINDIR=\""$(bindir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DDATADIR=\""$(datadir)"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ $(WARN_CFLAGS) \
+ $(DEBUG_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(NULL)
+
+sbin_PROGRAMS = \
+ console-kit-daemon \
+ $(NULL)
+
+BUILT_SOURCES = \
+ ck-manager-glue.h \
+ ck-seat-glue.h \
+ ck-session-glue.h \
+ ck-marshal.c \
+ ck-marshal.h \
+ $(NULL)
+
+ck-manager-glue.h: ck-manager.xml Makefile.am
+ dbus-binding-tool --prefix=ck_manager --mode=glib-server --output=ck-manager-glue.h ck-manager.xml
+ck-seat-glue.h: ck-seat.xml Makefile.am
+ dbus-binding-tool --prefix=ck_seat --mode=glib-server --output=ck-seat-glue.h ck-seat.xml
+ck-session-glue.h: ck-session.xml Makefile.am
+ dbus-binding-tool --prefix=ck_session --mode=glib-server --output=ck-session-glue.h ck-session.xml
+
+ck-marshal.c: ck-marshal.list
+ echo "#include \"ck-marshal.h\"" > $@ && \
+ @GLIB_GENMARSHAL@ $< --prefix=ck_marshal --body >> $@
+
+ck-marshal.h: ck-marshal.list
+ @GLIB_GENMARSHAL@ $< --prefix=ck_marshal --header > $@
+
+PLATFORM_SOURCES = \
+ proc-linux.c \
+ $(NULL)
+
+console_kit_daemon_SOURCES = \
+ main.c \
+ ck-manager.h \
+ ck-manager.c \
+ ck-vt-monitor.h \
+ ck-vt-monitor.c \
+ ck-seat.h \
+ ck-seat.c \
+ ck-session.h \
+ ck-session.c \
+ ck-debug.h \
+ ck-debug.c \
+ getfd.c \
+ proc.h \
+ $(PLATFORM_SOURCES) \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+console_kit_daemon_LDADD = \
+ $(CONSOLE_KIT_LIBS) \
+ $(NULL)
+
+EXTRA_DIST = \
+ ck-marshal.list \
+ ck-manager.xml \
+ ck-seat.xml \
+ ck-session.xml \
+ valgrind.sh \
+ test-session \
+ $(NULL)
+
+CLEANFILES = $(BUILT_SOURCES)
+
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
diff --git a/src/Makefile.in b/src/Makefile.in
new file mode 100644
index 0000000..7329245
--- /dev/null
+++ b/src/Makefile.in
@@ -0,0 +1,724 @@
+# Makefile.in generated by automake 1.9.6 from Makefile.am.
+# @configure_input@
+
+# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002,
+# 2003, 2004, 2005 Free Software Foundation, Inc.
+# This Makefile.in is free software; the Free Software Foundation
+# gives unlimited permission to copy and/or distribute it,
+# with or without modifications, as long as this notice is preserved.
+
+# This program is distributed in the hope that it will be useful,
+# but WITHOUT ANY WARRANTY, to the extent permitted by law; without
+# even the implied warranty of MERCHANTABILITY or FITNESS FOR A
+# PARTICULAR PURPOSE.
+
+@SET_MAKE@
+
+srcdir = @srcdir@
+top_srcdir = @top_srcdir@
+VPATH = @srcdir@
+pkgdatadir = $(datadir)/@PACKAGE@
+pkglibdir = $(libdir)/@PACKAGE@
+pkgincludedir = $(includedir)/@PACKAGE@
+top_builddir = ..
+am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd
+INSTALL = @INSTALL@
+install_sh_DATA = $(install_sh) -c -m 644
+install_sh_PROGRAM = $(install_sh) -c
+install_sh_SCRIPT = $(install_sh) -c
+INSTALL_HEADER = $(INSTALL_DATA)
+transform = $(program_transform_name)
+NORMAL_INSTALL = :
+PRE_INSTALL = :
+POST_INSTALL = :
+NORMAL_UNINSTALL = :
+PRE_UNINSTALL = :
+POST_UNINSTALL = :
+build_triplet = @build@
+host_triplet = @host@
+sbin_PROGRAMS = console-kit-daemon$(EXEEXT) $(am__EXEEXT_1)
+subdir = src
+DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in
+ACLOCAL_M4 = $(top_srcdir)/aclocal.m4
+am__aclocal_m4_deps = $(top_srcdir)/acinclude.m4 \
+ $(top_srcdir)/configure.ac
+am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \
+ $(ACLOCAL_M4)
+mkinstalldirs = $(SHELL) $(top_srcdir)/mkinstalldirs
+CONFIG_HEADER = $(top_builddir)/config.h
+CONFIG_CLEAN_FILES =
+am__EXEEXT_1 =
+am__installdirs = "$(DESTDIR)$(sbindir)"
+sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM)
+PROGRAMS = $(sbin_PROGRAMS)
+am__objects_1 =
+am__objects_2 = proc-linux.$(OBJEXT) $(am__objects_1)
+am__objects_3 = ck-marshal.$(OBJEXT) $(am__objects_1)
+am_console_kit_daemon_OBJECTS = main.$(OBJEXT) ck-manager.$(OBJEXT) \
+ ck-vt-monitor.$(OBJEXT) ck-seat.$(OBJEXT) ck-session.$(OBJEXT) \
+ ck-debug.$(OBJEXT) getfd.$(OBJEXT) $(am__objects_2) \
+ $(am__objects_3) $(am__objects_1)
+console_kit_daemon_OBJECTS = $(am_console_kit_daemon_OBJECTS)
+am__DEPENDENCIES_1 =
+console_kit_daemon_DEPENDENCIES = $(am__DEPENDENCIES_1) \
+ $(am__DEPENDENCIES_1)
+DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir)
+depcomp = $(SHELL) $(top_srcdir)/depcomp
+am__depfiles_maybe = depfiles
+COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \
+ $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS)
+LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \
+ $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \
+ $(AM_CFLAGS) $(CFLAGS)
+CCLD = $(CC)
+LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \
+ $(AM_LDFLAGS) $(LDFLAGS) -o $@
+SOURCES = $(console_kit_daemon_SOURCES)
+DIST_SOURCES = $(console_kit_daemon_SOURCES)
+RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \
+ html-recursive info-recursive install-data-recursive \
+ install-exec-recursive install-info-recursive \
+ install-recursive installcheck-recursive installdirs-recursive \
+ pdf-recursive ps-recursive uninstall-info-recursive \
+ uninstall-recursive
+ETAGS = etags
+CTAGS = ctags
+DIST_SUBDIRS = $(SUBDIRS)
+DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST)
+ACLOCAL = @ACLOCAL@
+ALL_LINGUAS = @ALL_LINGUAS@
+AMDEP_FALSE = @AMDEP_FALSE@
+AMDEP_TRUE = @AMDEP_TRUE@
+AMTAR = @AMTAR@
+AR = @AR@
+AUTOCONF = @AUTOCONF@
+AUTOHEADER = @AUTOHEADER@
+AUTOMAKE = @AUTOMAKE@
+AWK = @AWK@
+BINDIR = @BINDIR@
+CATALOGS = @CATALOGS@
+CATOBJEXT = @CATOBJEXT@
+CC = @CC@
+CCDEPMODE = @CCDEPMODE@
+CFLAGS = @CFLAGS@
+CONSOLE_KIT_CFLAGS = @CONSOLE_KIT_CFLAGS@
+CONSOLE_KIT_LIBS = @CONSOLE_KIT_LIBS@
+CONSOLE_KIT_PID_FILE = @CONSOLE_KIT_PID_FILE@
+CPP = @CPP@
+CPPFLAGS = @CPPFLAGS@
+CXX = @CXX@
+CXXCPP = @CXXCPP@
+CXXDEPMODE = @CXXDEPMODE@
+CXXFLAGS = @CXXFLAGS@
+CYGPATH_W = @CYGPATH_W@
+DATADIR = @DATADIR@
+DATADIRNAME = @DATADIRNAME@
+DBUS_CFLAGS = @DBUS_CFLAGS@
+DBUS_SYS_DIR = @DBUS_SYS_DIR@
+DEBUG_CFLAGS = @DEBUG_CFLAGS@
+DEFS = @DEFS@
+DEPDIR = @DEPDIR@
+ECHO = @ECHO@
+ECHO_C = @ECHO_C@
+ECHO_N = @ECHO_N@
+ECHO_T = @ECHO_T@
+EGREP = @EGREP@
+EXEEXT = @EXEEXT@
+F77 = @F77@
+FFLAGS = @FFLAGS@
+GETTEXT_PACKAGE = @GETTEXT_PACKAGE@
+GLIB_GENMARSHAL = @GLIB_GENMARSHAL@
+GMOFILES = @GMOFILES@
+GMSGFMT = @GMSGFMT@
+INSTALL_DATA = @INSTALL_DATA@
+INSTALL_PROGRAM = @INSTALL_PROGRAM@
+INSTALL_SCRIPT = @INSTALL_SCRIPT@
+INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@
+INSTOBJEXT = @INSTOBJEXT@
+INTLLIBS = @INTLLIBS@
+INTLTOOL_CAVES_RULE = @INTLTOOL_CAVES_RULE@
+INTLTOOL_DESKTOP_RULE = @INTLTOOL_DESKTOP_RULE@
+INTLTOOL_DIRECTORY_RULE = @INTLTOOL_DIRECTORY_RULE@
+INTLTOOL_EXTRACT = @INTLTOOL_EXTRACT@
+INTLTOOL_ICONV = @INTLTOOL_ICONV@
+INTLTOOL_KBD_RULE = @INTLTOOL_KBD_RULE@
+INTLTOOL_KEYS_RULE = @INTLTOOL_KEYS_RULE@
+INTLTOOL_MERGE = @INTLTOOL_MERGE@
+INTLTOOL_MSGFMT = @INTLTOOL_MSGFMT@
+INTLTOOL_MSGMERGE = @INTLTOOL_MSGMERGE@
+INTLTOOL_OAF_RULE = @INTLTOOL_OAF_RULE@
+INTLTOOL_PERL = @INTLTOOL_PERL@
+INTLTOOL_PONG_RULE = @INTLTOOL_PONG_RULE@
+INTLTOOL_PROP_RULE = @INTLTOOL_PROP_RULE@
+INTLTOOL_SCHEMAS_RULE = @INTLTOOL_SCHEMAS_RULE@
+INTLTOOL_SERVER_RULE = @INTLTOOL_SERVER_RULE@
+INTLTOOL_SERVICE_RULE = @INTLTOOL_SERVICE_RULE@
+INTLTOOL_SHEET_RULE = @INTLTOOL_SHEET_RULE@
+INTLTOOL_SOUNDLIST_RULE = @INTLTOOL_SOUNDLIST_RULE@
+INTLTOOL_THEME_RULE = @INTLTOOL_THEME_RULE@
+INTLTOOL_UI_RULE = @INTLTOOL_UI_RULE@
+INTLTOOL_UPDATE = @INTLTOOL_UPDATE@
+INTLTOOL_XAM_RULE = @INTLTOOL_XAM_RULE@
+INTLTOOL_XGETTEXT = @INTLTOOL_XGETTEXT@
+INTLTOOL_XML_NOMERGE_RULE = @INTLTOOL_XML_NOMERGE_RULE@
+INTLTOOL_XML_RULE = @INTLTOOL_XML_RULE@
+LDFLAGS = @LDFLAGS@
+LIBDIR = @LIBDIR@
+LIBEXECDIR = @LIBEXECDIR@
+LIBOBJS = @LIBOBJS@
+LIBS = @LIBS@
+LIBTOOL = @LIBTOOL@
+LN_S = @LN_S@
+LOCALSTATEDIR = @LOCALSTATEDIR@
+LTLIBOBJS = @LTLIBOBJS@
+MAINT = @MAINT@
+MAINTAINER_MODE_FALSE = @MAINTAINER_MODE_FALSE@
+MAINTAINER_MODE_TRUE = @MAINTAINER_MODE_TRUE@
+MAKEINFO = @MAKEINFO@
+MKINSTALLDIRS = @MKINSTALLDIRS@
+MSGFMT = @MSGFMT@
+OBJEXT = @OBJEXT@
+PACKAGE = @PACKAGE@
+PACKAGE_BUGREPORT = @PACKAGE_BUGREPORT@
+PACKAGE_NAME = @PACKAGE_NAME@
+PACKAGE_STRING = @PACKAGE_STRING@
+PACKAGE_TARNAME = @PACKAGE_TARNAME@
+PACKAGE_VERSION = @PACKAGE_VERSION@
+PATH_SEPARATOR = @PATH_SEPARATOR@
+PKG_CONFIG = @PKG_CONFIG@
+POFILES = @POFILES@
+POSUB = @POSUB@
+PO_IN_DATADIR_FALSE = @PO_IN_DATADIR_FALSE@
+PO_IN_DATADIR_TRUE = @PO_IN_DATADIR_TRUE@
+RANLIB = @RANLIB@
+SBINDIR = @SBINDIR@
+SET_MAKE = @SET_MAKE@
+SHELL = @SHELL@
+STRIP = @STRIP@
+SYSCONFDIR = @SYSCONFDIR@
+USE_NLS = @USE_NLS@
+VERSION = @VERSION@
+WARN_CFLAGS = @WARN_CFLAGS@
+XGETTEXT = @XGETTEXT@
+ac_ct_AR = @ac_ct_AR@
+ac_ct_CC = @ac_ct_CC@
+ac_ct_CXX = @ac_ct_CXX@
+ac_ct_F77 = @ac_ct_F77@
+ac_ct_RANLIB = @ac_ct_RANLIB@
+ac_ct_STRIP = @ac_ct_STRIP@
+ac_pt_PKG_CONFIG = @ac_pt_PKG_CONFIG@
+am__fastdepCC_FALSE = @am__fastdepCC_FALSE@
+am__fastdepCC_TRUE = @am__fastdepCC_TRUE@
+am__fastdepCXX_FALSE = @am__fastdepCXX_FALSE@
+am__fastdepCXX_TRUE = @am__fastdepCXX_TRUE@
+am__include = @am__include@
+am__leading_dot = @am__leading_dot@
+am__quote = @am__quote@
+am__tar = @am__tar@
+am__untar = @am__untar@
+bindir = @bindir@
+build = @build@
+build_alias = @build_alias@
+build_cpu = @build_cpu@
+build_os = @build_os@
+build_vendor = @build_vendor@
+datadir = @datadir@
+exec_prefix = @exec_prefix@
+host = @host@
+host_alias = @host_alias@
+host_cpu = @host_cpu@
+host_os = @host_os@
+host_vendor = @host_vendor@
+includedir = @includedir@
+infodir = @infodir@
+install_sh = @install_sh@
+libdir = @libdir@
+libexecdir = @libexecdir@
+localstatedir = @localstatedir@
+mandir = @mandir@
+mkdir_p = @mkdir_p@
+oldincludedir = @oldincludedir@
+prefix = @prefix@
+program_transform_name = @program_transform_name@
+sbindir = @sbindir@
+sharedstatedir = @sharedstatedir@
+sysconfdir = @sysconfdir@
+target_alias = @target_alias@
+AUTOMAKE_OPTIONS = 1.7
+NULL =
+SUBDIRS = \
+ $(NULL)
+
+INCLUDES = \
+ -I. \
+ -I$(srcdir) \
+ $(CONSOLE_KIT_CFLAGS) \
+ $(DISABLE_DEPRECATED_CFLAGS) \
+ -DPREFIX=\""$(prefix)"\" \
+ -DBINDIR=\""$(bindir)"\" \
+ -DLIBDIR=\""$(libdir)"\" \
+ -DLIBEXECDIR=\""$(libexecdir)"\" \
+ -DDATADIR=\""$(datadir)"\" \
+ -DSYSCONFDIR=\""$(sysconfdir)"\" \
+ $(WARN_CFLAGS) \
+ $(DEBUG_CFLAGS) \
+ $(DBUS_CFLAGS) \
+ $(NULL)
+
+BUILT_SOURCES = \
+ ck-manager-glue.h \
+ ck-seat-glue.h \
+ ck-session-glue.h \
+ ck-marshal.c \
+ ck-marshal.h \
+ $(NULL)
+
+PLATFORM_SOURCES = \
+ proc-linux.c \
+ $(NULL)
+
+console_kit_daemon_SOURCES = \
+ main.c \
+ ck-manager.h \
+ ck-manager.c \
+ ck-vt-monitor.h \
+ ck-vt-monitor.c \
+ ck-seat.h \
+ ck-seat.c \
+ ck-session.h \
+ ck-session.c \
+ ck-debug.h \
+ ck-debug.c \
+ getfd.c \
+ proc.h \
+ $(PLATFORM_SOURCES) \
+ $(BUILT_SOURCES) \
+ $(NULL)
+
+console_kit_daemon_LDADD = \
+ $(CONSOLE_KIT_LIBS) \
+ $(NULL)
+
+EXTRA_DIST = \
+ ck-marshal.list \
+ ck-manager.xml \
+ ck-seat.xml \
+ ck-session.xml \
+ valgrind.sh \
+ test-session \
+ $(NULL)
+
+CLEANFILES = $(BUILT_SOURCES)
+MAINTAINERCLEANFILES = \
+ *~ \
+ Makefile.in
+
+all: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) all-recursive
+
+.SUFFIXES:
+.SUFFIXES: .c .lo .o .obj
+$(srcdir)/Makefile.in: @MAINTAINER_MODE_TRUE@ $(srcdir)/Makefile.am $(am__configure_deps)
+ @for dep in $?; do \
+ case '$(am__configure_deps)' in \
+ *$$dep*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh \
+ && exit 0; \
+ exit 1;; \
+ esac; \
+ done; \
+ echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu src/Makefile'; \
+ cd $(top_srcdir) && \
+ $(AUTOMAKE) --gnu src/Makefile
+.PRECIOUS: Makefile
+Makefile: $(srcdir)/Makefile.in $(top_builddir)/config.status
+ @case '$?' in \
+ *config.status*) \
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh;; \
+ *) \
+ echo ' cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe)'; \
+ cd $(top_builddir) && $(SHELL) ./config.status $(subdir)/$@ $(am__depfiles_maybe);; \
+ esac;
+
+$(top_builddir)/config.status: $(top_srcdir)/configure $(CONFIG_STATUS_DEPENDENCIES)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+
+$(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+$(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps)
+ cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh
+install-sbinPROGRAMS: $(sbin_PROGRAMS)
+ @$(NORMAL_INSTALL)
+ test -z "$(sbindir)" || $(mkdir_p) "$(DESTDIR)$(sbindir)"
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ p1=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ if test -f $$p \
+ || test -f $$p1 \
+ ; then \
+ f=`echo "$$p1" | sed 's,^.*/,,;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) '$$p' '$(DESTDIR)$(sbindir)/$$f'"; \
+ $(INSTALL_PROGRAM_ENV) $(LIBTOOL) --mode=install $(sbinPROGRAMS_INSTALL) "$$p" "$(DESTDIR)$(sbindir)/$$f" || exit 1; \
+ else :; fi; \
+ done
+
+uninstall-sbinPROGRAMS:
+ @$(NORMAL_UNINSTALL)
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ f=`echo "$$p" | sed 's,^.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/'`; \
+ echo " rm -f '$(DESTDIR)$(sbindir)/$$f'"; \
+ rm -f "$(DESTDIR)$(sbindir)/$$f"; \
+ done
+
+clean-sbinPROGRAMS:
+ @list='$(sbin_PROGRAMS)'; for p in $$list; do \
+ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \
+ echo " rm -f $$p $$f"; \
+ rm -f $$p $$f ; \
+ done
+console-kit-daemon$(EXEEXT): $(console_kit_daemon_OBJECTS) $(console_kit_daemon_DEPENDENCIES)
+ @rm -f console-kit-daemon$(EXEEXT)
+ $(LINK) $(console_kit_daemon_LDFLAGS) $(console_kit_daemon_OBJECTS) $(console_kit_daemon_LDADD) $(LIBS)
+
+mostlyclean-compile:
+ -rm -f *.$(OBJEXT)
+
+distclean-compile:
+ -rm -f *.tab.c
+
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-debug.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-manager.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-marshal.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-seat.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-session.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-vt-monitor.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/getfd.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/main.Po@am__quote@
+@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/proc-linux.Po@am__quote@
+
+.c.o:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c $<
+
+.c.obj:
+@am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ `$(CYGPATH_W) '$<'`; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Po"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=no @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(COMPILE) -c `$(CYGPATH_W) '$<'`
+
+.c.lo:
+@am__fastdepCC_TRUE@ if $(LTCOMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \
+@am__fastdepCC_TRUE@ then mv -f "$(DEPDIR)/$*.Tpo" "$(DEPDIR)/$*.Plo"; else rm -f "$(DEPDIR)/$*.Tpo"; exit 1; fi
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ source='$<' object='$@' libtool=yes @AMDEPBACKSLASH@
+@AMDEP_TRUE@@am__fastdepCC_FALSE@ DEPDIR=$(DEPDIR) $(CCDEPMODE) $(depcomp) @AMDEPBACKSLASH@
+@am__fastdepCC_FALSE@ $(LTCOMPILE) -c -o $@ $<
+
+mostlyclean-libtool:
+ -rm -f *.lo
+
+clean-libtool:
+ -rm -rf .libs _libs
+
+distclean-libtool:
+ -rm -f libtool
+uninstall-info-am:
+
+# This directory's subdirectories are mostly independent; you can cd
+# into them and run `make' without going through this Makefile.
+# To change the values of `make' variables: instead of editing Makefiles,
+# (1) if the variable is set in `config.status', edit `config.status'
+# (which will cause the Makefiles to be regenerated when you run `make');
+# (2) otherwise, pass the desired values on the `make' command line.
+$(RECURSIVE_TARGETS):
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ target=`echo $@ | sed s/-recursive//`; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ dot_seen=yes; \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done; \
+ if test "$$dot_seen" = "no"; then \
+ $(MAKE) $(AM_MAKEFLAGS) "$$target-am" || exit 1; \
+ fi; test -z "$$fail"
+
+mostlyclean-recursive clean-recursive distclean-recursive \
+maintainer-clean-recursive:
+ @failcom='exit 1'; \
+ for f in x $$MAKEFLAGS; do \
+ case $$f in \
+ *=* | --[!k]*);; \
+ *k*) failcom='fail=yes';; \
+ esac; \
+ done; \
+ dot_seen=no; \
+ case "$@" in \
+ distclean-* | maintainer-clean-*) list='$(DIST_SUBDIRS)' ;; \
+ *) list='$(SUBDIRS)' ;; \
+ esac; \
+ rev=''; for subdir in $$list; do \
+ if test "$$subdir" = "."; then :; else \
+ rev="$$subdir $$rev"; \
+ fi; \
+ done; \
+ rev="$$rev ."; \
+ target=`echo $@ | sed s/-recursive//`; \
+ for subdir in $$rev; do \
+ echo "Making $$target in $$subdir"; \
+ if test "$$subdir" = "."; then \
+ local_target="$$target-am"; \
+ else \
+ local_target="$$target"; \
+ fi; \
+ (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) $$local_target) \
+ || eval $$failcom; \
+ done && test -z "$$fail"
+tags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) tags); \
+ done
+ctags-recursive:
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ test "$$subdir" = . || (cd $$subdir && $(MAKE) $(AM_MAKEFLAGS) ctags); \
+ done
+
+ID: $(HEADERS) $(SOURCES) $(LISP) $(TAGS_FILES)
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ mkid -fID $$unique
+tags: TAGS
+
+TAGS: tags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ if ($(ETAGS) --etags-include --version) >/dev/null 2>&1; then \
+ include_option=--etags-include; \
+ empty_fix=.; \
+ else \
+ include_option=--include; \
+ empty_fix=; \
+ fi; \
+ list='$(SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test ! -f $$subdir/TAGS || \
+ tags="$$tags $$include_option=$$here/$$subdir/TAGS"; \
+ fi; \
+ done; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ if test -z "$(ETAGS_ARGS)$$tags$$unique"; then :; else \
+ test -n "$$unique" || unique=$$empty_fix; \
+ $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \
+ $$tags $$unique; \
+ fi
+ctags: CTAGS
+CTAGS: ctags-recursive $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \
+ $(TAGS_FILES) $(LISP)
+ tags=; \
+ here=`pwd`; \
+ list='$(SOURCES) $(HEADERS) $(LISP) $(TAGS_FILES)'; \
+ unique=`for i in $$list; do \
+ if test -f "$$i"; then echo $$i; else echo $(srcdir)/$$i; fi; \
+ done | \
+ $(AWK) ' { files[$$0] = 1; } \
+ END { for (i in files) print i; }'`; \
+ test -z "$(CTAGS_ARGS)$$tags$$unique" \
+ || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \
+ $$tags $$unique
+
+GTAGS:
+ here=`$(am__cd) $(top_builddir) && pwd` \
+ && cd $(top_srcdir) \
+ && gtags -i $(GTAGS_ARGS) $$here
+
+distclean-tags:
+ -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags
+
+distdir: $(DISTFILES)
+ @srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; \
+ topsrcdirstrip=`echo "$(top_srcdir)" | sed 's|.|.|g'`; \
+ list='$(DISTFILES)'; for file in $$list; do \
+ case $$file in \
+ $(srcdir)/*) file=`echo "$$file" | sed "s|^$$srcdirstrip/||"`;; \
+ $(top_srcdir)/*) file=`echo "$$file" | sed "s|^$$topsrcdirstrip/|$(top_builddir)/|"`;; \
+ esac; \
+ if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \
+ dir=`echo "$$file" | sed -e 's,/[^/]*$$,,'`; \
+ if test "$$dir" != "$$file" && test "$$dir" != "."; then \
+ dir="/$$dir"; \
+ $(mkdir_p) "$(distdir)$$dir"; \
+ else \
+ dir=''; \
+ fi; \
+ if test -d $$d/$$file; then \
+ if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \
+ cp -pR $(srcdir)/$$file $(distdir)$$dir || exit 1; \
+ fi; \
+ cp -pR $$d/$$file $(distdir)$$dir || exit 1; \
+ else \
+ test -f $(distdir)/$$file \
+ || cp -p $$d/$$file $(distdir)/$$file \
+ || exit 1; \
+ fi; \
+ done
+ list='$(DIST_SUBDIRS)'; for subdir in $$list; do \
+ if test "$$subdir" = .; then :; else \
+ test -d "$(distdir)/$$subdir" \
+ || $(mkdir_p) "$(distdir)/$$subdir" \
+ || exit 1; \
+ distdir=`$(am__cd) $(distdir) && pwd`; \
+ top_distdir=`$(am__cd) $(top_distdir) && pwd`; \
+ (cd $$subdir && \
+ $(MAKE) $(AM_MAKEFLAGS) \
+ top_distdir="$$top_distdir" \
+ distdir="$$distdir/$$subdir" \
+ distdir) \
+ || exit 1; \
+ fi; \
+ done
+check-am: all-am
+check: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) check-recursive
+all-am: Makefile $(PROGRAMS)
+installdirs: installdirs-recursive
+installdirs-am:
+ for dir in "$(DESTDIR)$(sbindir)"; do \
+ test -z "$$dir" || $(mkdir_p) "$$dir"; \
+ done
+install: $(BUILT_SOURCES)
+ $(MAKE) $(AM_MAKEFLAGS) install-recursive
+install-exec: install-exec-recursive
+install-data: install-data-recursive
+uninstall: uninstall-recursive
+
+install-am: all-am
+ @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am
+
+installcheck: installcheck-recursive
+install-strip:
+ $(MAKE) $(AM_MAKEFLAGS) INSTALL_PROGRAM="$(INSTALL_STRIP_PROGRAM)" \
+ install_sh_PROGRAM="$(INSTALL_STRIP_PROGRAM)" INSTALL_STRIP_FLAG=-s \
+ `test -z '$(STRIP)' || \
+ echo "INSTALL_PROGRAM_ENV=STRIPPROG='$(STRIP)'"` install
+mostlyclean-generic:
+
+clean-generic:
+ -test -z "$(CLEANFILES)" || rm -f $(CLEANFILES)
+
+distclean-generic:
+ -test -z "$(CONFIG_CLEAN_FILES)" || rm -f $(CONFIG_CLEAN_FILES)
+
+maintainer-clean-generic:
+ @echo "This command is intended for maintainers to use"
+ @echo "it deletes files that may require special tools to rebuild."
+ -test -z "$(BUILT_SOURCES)" || rm -f $(BUILT_SOURCES)
+ -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES)
+clean: clean-recursive
+
+clean-am: clean-generic clean-libtool clean-sbinPROGRAMS \
+ mostlyclean-am
+
+distclean: distclean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+distclean-am: clean-am distclean-compile distclean-generic \
+ distclean-libtool distclean-tags
+
+dvi: dvi-recursive
+
+dvi-am:
+
+html: html-recursive
+
+info: info-recursive
+
+info-am:
+
+install-data-am:
+
+install-exec-am: install-sbinPROGRAMS
+
+install-info: install-info-recursive
+
+install-man:
+
+installcheck-am:
+
+maintainer-clean: maintainer-clean-recursive
+ -rm -rf ./$(DEPDIR)
+ -rm -f Makefile
+maintainer-clean-am: distclean-am maintainer-clean-generic
+
+mostlyclean: mostlyclean-recursive
+
+mostlyclean-am: mostlyclean-compile mostlyclean-generic \
+ mostlyclean-libtool
+
+pdf: pdf-recursive
+
+pdf-am:
+
+ps: ps-recursive
+
+ps-am:
+
+uninstall-am: uninstall-info-am uninstall-sbinPROGRAMS
+
+uninstall-info: uninstall-info-recursive
+
+.PHONY: $(RECURSIVE_TARGETS) CTAGS GTAGS all all-am check check-am \
+ clean clean-generic clean-libtool clean-recursive \
+ clean-sbinPROGRAMS ctags ctags-recursive distclean \
+ distclean-compile distclean-generic distclean-libtool \
+ distclean-recursive distclean-tags distdir dvi dvi-am html \
+ html-am info info-am install install-am install-data \
+ install-data-am install-exec install-exec-am install-info \
+ install-info-am install-man install-sbinPROGRAMS install-strip \
+ installcheck installcheck-am installdirs installdirs-am \
+ maintainer-clean maintainer-clean-generic \
+ maintainer-clean-recursive mostlyclean mostlyclean-compile \
+ mostlyclean-generic mostlyclean-libtool mostlyclean-recursive \
+ pdf pdf-am ps ps-am tags tags-recursive uninstall uninstall-am \
+ uninstall-info-am uninstall-sbinPROGRAMS
+
+
+ck-manager-glue.h: ck-manager.xml Makefile.am
+ dbus-binding-tool --prefix=ck_manager --mode=glib-server --output=ck-manager-glue.h ck-manager.xml
+ck-seat-glue.h: ck-seat.xml Makefile.am
+ dbus-binding-tool --prefix=ck_seat --mode=glib-server --output=ck-seat-glue.h ck-seat.xml
+ck-session-glue.h: ck-session.xml Makefile.am
+ dbus-binding-tool --prefix=ck_session --mode=glib-server --output=ck-session-glue.h ck-session.xml
+
+ck-marshal.c: ck-marshal.list
+ echo "#include \"ck-marshal.h\"" > $@ && \
+ @GLIB_GENMARSHAL@ $< --prefix=ck_marshal --body >> $@
+
+ck-marshal.h: ck-marshal.list
+ @GLIB_GENMARSHAL@ $< --prefix=ck_marshal --header > $@
+# Tell versions [3.59,3.63) of GNU make to not export all variables.
+# Otherwise a system limit (for SysV at least) may be exceeded.
+.NOEXPORT:
diff --git a/src/ck-debug.c b/src/ck-debug.c
new file mode 100644
index 0000000..458b467
--- /dev/null
+++ b/src/ck-debug.c
@@ -0,0 +1,153 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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: William Jon McCann <mccann@jhu.edu>
+ *
+ */
+
+#include "config.h"
+
+#include <stdio.h>
+#include <string.h>
+#include <stdarg.h>
+#include <signal.h>
+#include <time.h>
+#include <unistd.h>
+
+#include <glib.h>
+#include <glib/gstdio.h>
+
+#include "ck-debug.h"
+
+static gboolean debugging = FALSE;
+static FILE *debug_out = NULL;
+
+/* Based on rhythmbox/lib/rb-debug.c */
+/* Our own funky debugging function, should only be used when something
+ * is not going wrong, if something *is* wrong use g_warning.
+ */
+void
+ck_debug_real (const char *func,
+ const char *file,
+ const int line,
+ const char *format, ...)
+{
+ va_list args;
+ char buffer [1025];
+ char *str_time;
+ time_t the_time;
+
+ if (debugging == FALSE)
+ return;
+
+ va_start (args, format);
+
+ g_vsnprintf (buffer, 1024, format, args);
+
+ va_end (args);
+
+ time (&the_time);
+ str_time = g_new0 (char, 255);
+ strftime (str_time, 254, "%H:%M:%S", localtime (&the_time));
+
+ fprintf ((debug_out ? debug_out : stderr),
+ "[%s] %s:%d (%s):\t %s\n",
+ func, file, line, str_time, buffer);
+
+ if (debug_out)
+ fflush (debug_out);
+
+ g_free (str_time);
+}
+
+gboolean
+ck_debug_enabled (void)
+{
+ return debugging;
+}
+
+void
+ck_debug_init (gboolean debug,
+ gboolean to_file)
+{
+ /* return if already initialized */
+ if (debugging == TRUE) {
+ return;
+ }
+
+ debugging = debug;
+
+ if (debug && to_file) {
+ const char path [50] = "ck_debug_XXXXXX";
+ int fd;
+
+ fd = g_file_open_tmp (path, NULL, NULL);
+
+ if (fd >= 0) {
+ debug_out = fdopen (fd, "a");
+ }
+ }
+
+ ck_debug ("Debugging %s", (debug) ? "enabled" : "disabled");
+}
+
+void
+ck_debug_shutdown (void)
+{
+ if (! debugging)
+ return;
+
+ ck_debug ("Shutting down debugging");
+
+ debugging = FALSE;
+
+ if (debug_out != NULL) {
+ fclose (debug_out);
+ debug_out = NULL;
+ }
+}
+
+void
+_ck_profile_log (const char *func,
+ const char *note,
+ const char *format,
+ ...)
+{
+ va_list args;
+ char *str;
+ char *formatted;
+
+ if (format == NULL) {
+ formatted = g_strdup ("");
+ } else {
+ va_start (args, format);
+ formatted = g_strdup_vprintf (format, args);
+ va_end (args);
+ }
+
+ if (func != NULL) {
+ str = g_strdup_printf ("MARK: %s %s: %s %s", g_get_prgname(), func, note ? note : "", formatted);
+ } else {
+ str = g_strdup_printf ("MARK: %s: %s %s", g_get_prgname(), note ? note : "", formatted);
+ }
+
+ g_free (formatted);
+
+ g_access (str, F_OK);
+ g_free (str);
+}
diff --git a/src/ck-debug.h b/src/ck-debug.h
new file mode 100644
index 0000000..88ff9e1
--- /dev/null
+++ b/src/ck-debug.h
@@ -0,0 +1,72 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2005-2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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: William Jon McCann <mccann@jhu.edu>
+ *
+ */
+
+#ifndef __CK_DEBUG_H
+#define __CK_DEBUG_H
+
+#include <stdarg.h>
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+#if defined(__STDC_VERSION__) && __STDC_VERSION__ >= 199901L
+#define ck_debug(...) ck_debug_real (__func__, __FILE__, __LINE__, __VA_ARGS__)
+#elif defined(__GNUC__) && __GNUC__ >= 3
+#define ck_debug(...) ck_debug_real (__FUNCTION__, __FILE__, __LINE__, __VA_ARGS__)
+#else
+#define ck_debug(...)
+#endif
+
+void ck_debug_init (gboolean debug,
+ gboolean to_file);
+gboolean ck_debug_enabled (void);
+void ck_debug_shutdown (void);
+void ck_debug_real (const char *func,
+ const char *file,
+ int line,
+ const char *format, ...);
+
+#define ENABLE_PROFILING 1
+#ifdef ENABLE_PROFILING
+#ifdef G_HAVE_ISO_VARARGS
+#define ck_profile_start(...) _ck_profile_log (G_STRFUNC, "start", __VA_ARGS__)
+#define ck_profile_end(...) _ck_profile_log (G_STRFUNC, "end", __VA_ARGS__)
+#define ck_profile_msg(...) _ck_profile_log (NULL, NULL, __VA_ARGS__)
+#elif defined(G_HAVE_GNUC_VARARGS)
+#define ck_profile_start(format...) _ck_profile_log (G_STRFUNC, "start", format)
+#define ck_profile_end(format...) _ck_profile_log (G_STRFUNC, "end", format)
+#define ck_profile_msg(format...) _ck_profile_log (NULL, NULL, format)
+#endif
+#else
+#define ck_profile_start(...)
+#define ck_profile_end(...)
+#define ck_profile_msg(...)
+#endif
+
+void _ck_profile_log (const char *func,
+ const char *note,
+ const char *format,
+ ...) G_GNUC_PRINTF (3, 4);
+
+G_END_DECLS
+
+#endif /* __CK_DEBUG_H */
diff --git a/src/ck-manager-glue.h b/src/ck-manager-glue.h
new file mode 100644
index 0000000..e70d233
--- /dev/null
+++ b/src/ck-manager-glue.h
@@ -0,0 +1,223 @@
+/* Generated by dbus-binding-tool; do not edit! */
+
+
+#ifndef __dbus_glib_marshal_ck_manager_MARSHAL_H__
+#define __dbus_glib_marshal_ck_manager_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.OC3GHT:1) */
+extern void dbus_glib_marshal_ck_manager_BOOLEAN__POINTER_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+dbus_glib_marshal_ck_manager_BOOLEAN__POINTER_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_pointer (param_values + 1),
+ g_marshal_value_peek_pointer (param_values + 2),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* NONE:UINT,POINTER (/tmp/dbus-binding-tool-c-marshallers.OC3GHT:2) */
+#define dbus_glib_marshal_ck_manager_VOID__UINT_POINTER g_cclosure_marshal_VOID__UINT_POINTER
+#define dbus_glib_marshal_ck_manager_NONE__UINT_POINTER dbus_glib_marshal_ck_manager_VOID__UINT_POINTER
+
+/* NONE:STRING,POINTER (/tmp/dbus-binding-tool-c-marshallers.OC3GHT:3) */
+extern void dbus_glib_marshal_ck_manager_VOID__STRING_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+dbus_glib_marshal_ck_manager_VOID__STRING_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__STRING_POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__STRING_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__STRING_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_string (param_values + 1),
+ g_marshal_value_peek_pointer (param_values + 2),
+ data2);
+}
+#define dbus_glib_marshal_ck_manager_NONE__STRING_POINTER dbus_glib_marshal_ck_manager_VOID__STRING_POINTER
+
+/* NONE:POINTER (/tmp/dbus-binding-tool-c-marshallers.OC3GHT:4) */
+#define dbus_glib_marshal_ck_manager_VOID__POINTER g_cclosure_marshal_VOID__POINTER
+#define dbus_glib_marshal_ck_manager_NONE__POINTER dbus_glib_marshal_ck_manager_VOID__POINTER
+
+/* NONE:BOXED,POINTER (/tmp/dbus-binding-tool-c-marshallers.OC3GHT:5) */
+extern void dbus_glib_marshal_ck_manager_VOID__BOXED_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+dbus_glib_marshal_ck_manager_VOID__BOXED_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__BOXED_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_boxed (param_values + 1),
+ g_marshal_value_peek_pointer (param_values + 2),
+ data2);
+}
+#define dbus_glib_marshal_ck_manager_NONE__BOXED_POINTER dbus_glib_marshal_ck_manager_VOID__BOXED_POINTER
+
+G_END_DECLS
+
+#endif /* __dbus_glib_marshal_ck_manager_MARSHAL_H__ */
+
+#include <dbus/dbus-glib.h>
+static const DBusGMethodInfo dbus_glib_ck_manager_methods[] = {
+ { (GCallback) ck_manager_open_session, dbus_glib_marshal_ck_manager_NONE__POINTER, 0 },
+ { (GCallback) ck_manager_open_session_with_parameters, dbus_glib_marshal_ck_manager_NONE__BOXED_POINTER, 65 },
+ { (GCallback) ck_manager_close_session, dbus_glib_marshal_ck_manager_NONE__STRING_POINTER, 163 },
+ { (GCallback) ck_manager_get_seats, dbus_glib_marshal_ck_manager_BOOLEAN__POINTER_POINTER, 240 },
+ { (GCallback) ck_manager_get_current_session, dbus_glib_marshal_ck_manager_NONE__POINTER, 302 },
+ { (GCallback) ck_manager_get_session_for_cookie, dbus_glib_marshal_ck_manager_NONE__STRING_POINTER, 371 },
+ { (GCallback) ck_manager_get_session_for_unix_process, dbus_glib_marshal_ck_manager_NONE__UINT_POINTER, 453 },
+ { (GCallback) ck_manager_get_sessions_for_user, dbus_glib_marshal_ck_manager_NONE__UINT_POINTER, 537 },
+};
+
+const DBusGObjectInfo dbus_glib_ck_manager_object_info = {
+ 0,
+ dbus_glib_ck_manager_methods,
+ 8,
+"org.freedesktop.ConsoleKit.Manager\0OpenSession\0A\0cookie\0O\0F\0N\0s\0\0org.freedesktop.ConsoleKit.Manager\0OpenSessionWithParameters\0A\0parameters\0I\0a(sv)\0cookie\0O\0F\0N\0s\0\0org.freedesktop.ConsoleKit.Manager\0CloseSession\0A\0cookie\0I\0s\0result\0O\0F\0N\0b\0\0org.freedesktop.ConsoleKit.Manager\0GetSeats\0S\0seats\0O\0F\0N\0ao\0\0org.freedesktop.ConsoleKit.Manager\0GetCurrentSession\0A\0ssid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Manager\0GetSessionForCookie\0A\0cookie\0I\0s\0ssid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Manager\0GetSessionForUnixProcess\0A\0pid\0I\0u\0ssid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Manager\0GetSessionsForUser\0A\0uid\0I\0u\0sessions\0O\0F\0N\0ao\0\0\0",
+"org.freedesktop.ConsoleKit.Manager\0SeatAdded\0org.freedesktop.ConsoleKit.Manager\0SeatRemoved\0\0",
+"\0"
+};
+
diff --git a/src/ck-manager.c b/src/ck-manager.c
new file mode 100644
index 0000000..8ebd1b8
--- /dev/null
+++ b/src/ck-manager.c
@@ -0,0 +1,1017 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <signal.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "ck-manager.h"
+#include "ck-manager-glue.h"
+#include "ck-seat.h"
+#include "ck-session.h"
+#include "ck-marshal.h"
+
+#include "ck-debug.h"
+#include "proc.h"
+
+#define CK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_MANAGER, CkManagerPrivate))
+
+#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"
+
+struct CkManagerPrivate
+{
+ GHashTable *seats;
+ GHashTable *sessions;
+ GHashTable *leaders;
+
+ DBusGProxy *bus_proxy;
+ DBusGConnection *connection;
+
+ guint32 session_serial;
+ guint32 seat_serial;
+};
+
+
+typedef struct {
+ uid_t uid;
+ pid_t pid;
+ char *service_name;
+ char *ssid;
+ char *cookie;
+} LeaderInfo;
+
+enum {
+ SEAT_ADDED,
+ SEAT_REMOVED,
+ LAST_SIGNAL
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void ck_manager_class_init (CkManagerClass *klass);
+static void ck_manager_init (CkManager *manager);
+static void ck_manager_finalize (GObject *object);
+
+static gpointer manager_object = NULL;
+
+G_DEFINE_TYPE (CkManager, ck_manager, G_TYPE_OBJECT)
+
+static void
+leader_info_free (LeaderInfo *info)
+{
+ g_free (info->ssid);
+ g_free (info->cookie);
+ g_free (info->service_name);
+ g_free (info);
+}
+
+GQuark
+ck_manager_error_quark (void)
+{
+ static GQuark ret = 0;
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("ck_manager_error");
+ }
+
+ return ret;
+}
+
+static guint32
+get_next_session_serial (CkManager *manager)
+{
+ guint32 serial;
+
+ serial = manager->priv->session_serial++;
+
+ if ((gint32)manager->priv->session_serial < 0) {
+ manager->priv->session_serial = 1;
+ }
+
+ return serial;
+}
+
+static guint32
+get_next_seat_serial (CkManager *manager)
+{
+ guint32 serial;
+
+ serial = manager->priv->seat_serial++;
+
+ if ((gint32)manager->priv->seat_serial < 0) {
+ manager->priv->seat_serial = 1;
+ }
+
+ return serial;
+}
+
+static char *
+generate_session_cookie (CkManager *manager)
+{
+ guint32 num;
+ char *cookie;
+ GTimeVal tv;
+
+ /* We want this to be globally unique
+ or at least such that it won't cycle when there
+ may be orphan processes in a dead session. */
+
+ cookie = NULL;
+ again:
+ num = (guint32)g_random_int_range (1, G_MAXINT32);
+
+ g_get_current_time (&tv);
+
+ g_free (cookie);
+ cookie = g_strdup_printf ("%ld.%ld-%u", tv.tv_sec, tv.tv_usec, num);
+
+ if (g_hash_table_lookup (manager->priv->leaders, cookie)) {
+ goto again;
+ }
+
+ return cookie;
+}
+
+static char *
+generate_session_id (CkManager *manager)
+{
+ guint32 serial;
+ char *id;
+
+ id = NULL;
+ again:
+ serial = get_next_session_serial (manager);
+ g_free (id);
+ id = g_strdup_printf ("%s/Session%u", CK_DBUS_PATH, serial);
+
+ if (g_hash_table_lookup (manager->priv->sessions, id)) {
+ goto again;
+ }
+
+ return id;
+}
+
+static char *
+generate_seat_id (CkManager *manager)
+{
+ guint32 serial;
+ char *id;
+
+ id = NULL;
+ again:
+ serial = get_next_seat_serial (manager);
+ g_free (id);
+ id = g_strdup_printf ("%s/Seat%u", CK_DBUS_PATH, serial);
+
+ if (g_hash_table_lookup (manager->priv->seats, id)) {
+ goto again;
+ }
+
+ return id;
+}
+
+static CkSeat *
+add_new_seat (CkManager *manager,
+ CkSeatKind kind)
+{
+ char *sid;
+ CkSeat *seat;
+
+ sid = generate_seat_id (manager);
+
+ seat = ck_seat_new (sid, kind);
+ if (seat == NULL) {
+ /* returns null if connection to bus fails */
+ g_free (sid);
+ goto out;
+ }
+
+ g_hash_table_insert (manager->priv->seats, sid, seat);
+
+ ck_debug ("Added seat: %s kind:%d", sid, kind);
+
+ g_signal_emit (manager, signals [SEAT_ADDED], 0, sid);
+
+ out:
+ return seat;
+}
+
+static void
+remove_seat (CkManager *manager,
+ CkSeat *seat)
+{
+ char *sid;
+
+ sid = NULL;
+ ck_seat_get_id (seat, &sid, NULL);
+
+ if (sid != NULL) {
+ g_hash_table_remove (manager->priv->seats, sid);
+ }
+
+ g_signal_emit (manager, signals [SEAT_REMOVED], 0, sid);
+
+ ck_debug ("Removed seat: %s", sid);
+
+ g_free (sid);
+}
+
+static CkSeat *
+find_seat_for_session (CkManager *manager,
+ CkSession *session)
+{
+ CkSeat *seat;
+ gboolean is_static;
+ gboolean is_local;
+
+ seat = NULL;
+ is_local = TRUE;
+
+ /* FIXME: use matching to group entries? */
+
+ /* for now group all local entries */
+ ck_session_is_local (session, &is_local, NULL);
+ is_static = is_local;
+
+ if (is_static) {
+ char *sid;
+ sid = g_strdup_printf ("%s/Seat%u", CK_DBUS_PATH, 1);
+ seat = g_hash_table_lookup (manager->priv->seats, sid);
+ }
+
+ return seat;
+}
+
+/* adapted from PolicyKit */
+static gboolean
+get_caller_info (CkManager *manager,
+ const char *sender,
+ uid_t *calling_uid,
+ pid_t *calling_pid)
+{
+ gboolean res;
+ GError *error = NULL;
+
+ res = FALSE;
+
+ if (sender == NULL) {
+ goto out;
+ }
+
+ if (! dbus_g_proxy_call (manager->priv->bus_proxy, "GetConnectionUnixUser", &error,
+ G_TYPE_STRING, sender,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, calling_uid,
+ G_TYPE_INVALID)) {
+ g_warning ("GetConnectionUnixUser() failed: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ if (! dbus_g_proxy_call (manager->priv->bus_proxy, "GetConnectionUnixProcessID", &error,
+ G_TYPE_STRING, sender,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, calling_pid,
+ G_TYPE_INVALID)) {
+ g_warning ("GetConnectionUnixProcessID() failed: %s", error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+ res = TRUE;
+
+ ck_debug ("uid = %d", *calling_uid);
+ ck_debug ("pid = %d", *calling_pid);
+
+out:
+ return res;
+}
+
+static char *
+create_session_for_caller (CkManager *manager,
+ const char *sender,
+ const GPtrArray *parameters,
+ GError **error)
+{
+ char *ssid;
+ proc_t *stat;
+ char *cmd;
+ char *xdisplay;
+ char *tty;
+ CkSession *session;
+ CkSeat *seat;
+ char *cookie;
+ pid_t pid;
+ uid_t uid;
+ gboolean res;
+ LeaderInfo *leader_info;
+
+ res = get_caller_info (manager,
+ sender,
+ &uid,
+ &pid);
+ if (! res) {
+ g_set_error (error,
+ CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ "Unable to get information about the calling process");
+
+ return NULL;
+ }
+
+ cookie = generate_session_cookie (manager);
+ ssid = generate_session_id (manager);
+
+ ck_debug ("Creating new session ssid: %s", ssid);
+
+ session = ck_session_new_with_parameters (ssid,
+ cookie,
+ parameters);
+
+ if (session == NULL) {
+ g_warning ("Unable to create new session");
+ g_free (cookie);
+ cookie = NULL;
+ g_set_error (error,
+ CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ "Unable to create new session");
+ goto out;
+ }
+
+ proc_stat_pid (pid, &stat);
+ tty = proc_get_tty (stat);
+ cmd = proc_get_cmd (stat);
+ xdisplay = NULL;
+ proc_free (stat);
+
+ /* If the parameters are not set then try to get them */
+ if (parameters == NULL) {
+ ck_session_set_user (session, uid, NULL);
+ ck_session_set_session_type (session, cmd, NULL);
+ ck_session_set_display_device (session, tty, NULL);
+ ck_session_set_x11_display (session, xdisplay, NULL);
+ }
+
+ g_free (xdisplay);
+ g_free (cmd);
+ g_free (tty);
+
+ leader_info = g_new0 (LeaderInfo, 1);
+ leader_info->uid = uid;
+ leader_info->pid = pid;
+ leader_info->service_name = g_strdup (sender);
+ leader_info->ssid = g_strdup (ssid);
+ leader_info->cookie = g_strdup (cookie);
+
+ g_hash_table_insert (manager->priv->leaders, g_strdup (cookie), leader_info);
+ g_hash_table_insert (manager->priv->sessions, g_strdup (ssid), g_object_ref (session));
+
+ /* Add to seat */
+ seat = find_seat_for_session (manager, session);
+ if (seat == NULL) {
+ /* create a new seat */
+ seat = add_new_seat (manager, CK_SEAT_KIND_DYNAMIC);
+ }
+
+ ck_seat_add_session (seat, session, NULL);
+
+ /* FIXME: connect to signals */
+ /* FIXME: add weak ref */
+
+ g_object_unref (session);
+
+ out:
+
+ g_free (ssid);
+
+ return cookie;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.GetSessionForCookie string:$XDG_SESSION_COOKIE
+*/
+gboolean
+ck_manager_get_session_for_cookie (CkManager *manager,
+ const char *cookie,
+ DBusGMethodInvocation *context)
+{
+ gboolean res;
+ char *sender;
+ uid_t calling_uid;
+ pid_t calling_pid;
+ proc_t *stat;
+ char *ssid;
+ CkSession *session;
+ LeaderInfo *leader_info;
+
+ ssid = NULL;
+
+ sender = dbus_g_method_get_sender (context);
+
+ res = get_caller_info (manager,
+ sender,
+ &calling_uid,
+ &calling_pid);
+ g_free (sender);
+
+ if (! res) {
+ GError *error;
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to get information about the calling process"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ res = proc_stat_pid (calling_pid, &stat);
+ if (! res) {
+ GError *error;
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to lookup information about calling process '%d'"),
+ calling_pid);
+ g_warning ("stat on pid %d failed", calling_pid);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ /* FIXME: should we restrict this by uid? */
+
+ leader_info = g_hash_table_lookup (manager->priv->leaders, cookie);
+ if (leader_info == NULL) {
+ GError *error;
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to find session for cookie"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ session = g_hash_table_lookup (manager->priv->sessions, leader_info->ssid);
+ if (session == NULL) {
+ GError *error;
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to find session for cookie"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ ck_session_get_id (session, &ssid, NULL);
+
+ dbus_g_method_return (context, g_strdup (ssid));
+
+ g_free (ssid);
+
+ return TRUE;
+}
+
+static char *
+get_cookie_for_pid (CkManager *manager,
+ guint pid)
+{
+ char *cookie;
+
+ /* FIXME: need a better way to get the cookie */
+
+ cookie = proc_get_env (pid, "XDG_SESSION_COOKIE");
+
+ return cookie;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.GetSessionForUnixProcess uint32:`/sbin/pidof -s bash`
+*/
+gboolean
+ck_manager_get_session_for_unix_process (CkManager *manager,
+ guint pid,
+ DBusGMethodInvocation *context)
+{
+ gboolean res;
+ char *sender;
+ uid_t calling_uid;
+ pid_t calling_pid;
+ proc_t *stat;
+ char *cookie;
+
+ sender = dbus_g_method_get_sender (context);
+
+ res = get_caller_info (manager,
+ sender,
+ &calling_uid,
+ &calling_pid);
+ g_free (sender);
+
+ if (! res) {
+ GError *error;
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to get information about the calling process"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ res = proc_stat_pid (calling_pid, &stat);
+ if (! res) {
+ GError *error;
+ g_warning ("stat on pid %d failed", calling_pid);
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to lookup information about calling process '%d'"),
+ calling_pid);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ cookie = get_cookie_for_pid (manager, pid);
+ if (cookie == NULL) {
+ GError *error;
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to lookup session information for process '%d'"),
+ pid);
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ res = ck_manager_get_session_for_cookie (manager, cookie, context);
+ g_free (cookie);
+
+ return res;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Manager \
+ org.freedesktop.ConsoleKit.Manager.GetCurrentSession
+*/
+gboolean
+ck_manager_get_current_session (CkManager *manager,
+ DBusGMethodInvocation *context)
+{
+ gboolean res;
+ char *sender;
+ uid_t calling_uid;
+ pid_t calling_pid;
+
+ sender = dbus_g_method_get_sender (context);
+
+ res = get_caller_info (manager,
+ sender,
+ &calling_uid,
+ &calling_pid);
+ g_free (sender);
+
+ if (! res) {
+ GError *error;
+ error = g_error_new (CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ _("Unable to get information about the calling process"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ res = ck_manager_get_session_for_unix_process (manager, calling_pid, context);
+
+ return res;
+}
+
+gboolean
+ck_manager_open_session (CkManager *manager,
+ DBusGMethodInvocation *context)
+{
+ char *sender;
+ char *cookie;
+ GError *error;
+
+ sender = dbus_g_method_get_sender (context);
+
+ error = NULL;
+ cookie = create_session_for_caller (manager, sender, NULL, &error);
+ if (cookie == NULL) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ dbus_g_method_return (context, cookie);
+
+ return TRUE;
+}
+
+gboolean
+ck_manager_open_session_with_parameters (CkManager *manager,
+ const GPtrArray *parameters,
+ DBusGMethodInvocation *context)
+{
+ char *sender;
+ char *cookie;
+ GError *error;
+
+ sender = dbus_g_method_get_sender (context);
+
+ error = NULL;
+ cookie = create_session_for_caller (manager, sender, parameters, &error);
+ if (cookie == NULL) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ dbus_g_method_return (context, cookie);
+
+ return TRUE;
+}
+
+static gboolean
+remove_session_for_cookie (CkManager *manager,
+ const char *cookie,
+ GError **error)
+{
+ CkSession *session;
+ LeaderInfo *leader_info;
+ char *ssid;
+ char *sid;
+
+ leader_info = g_hash_table_lookup (manager->priv->leaders, cookie);
+
+ if (leader_info == NULL) {
+ g_set_error (error,
+ CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ "Unable to find session for cookie");
+ return FALSE;
+ }
+
+ session = g_hash_table_lookup (manager->priv->sessions, leader_info->ssid);
+ if (session == NULL) {
+ g_set_error (error,
+ CK_MANAGER_ERROR,
+ CK_MANAGER_ERROR_GENERAL,
+ "Unable to find session for cookie");
+ return FALSE;
+ }
+
+ ssid = g_strdup (leader_info->ssid);
+
+ /* remove from seat */
+ ck_session_get_seat_id (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, 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);
+ }
+ }
+ }
+
+ g_hash_table_remove (manager->priv->sessions, ssid);
+
+ g_free (ssid);
+
+ return TRUE;
+}
+
+gboolean
+ck_manager_close_session (CkManager *manager,
+ const char *cookie,
+ DBusGMethodInvocation *context)
+{
+ gboolean res;
+ GError *error;
+
+ error = NULL;
+ res = remove_session_for_cookie (manager, cookie, &error);
+ if (! res) {
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ } else {
+ g_hash_table_remove (manager->priv->leaders, cookie);
+ }
+
+ dbus_g_method_return (context, res);
+
+ return TRUE;
+}
+
+typedef struct {
+ const char *service_name;
+ CkManager *manager;
+} RemoveLeaderData;
+
+static gboolean
+remove_leader_for_connection (const char *cookie,
+ LeaderInfo *info,
+ RemoveLeaderData *data)
+{
+ g_assert (info != NULL);
+ g_assert (data->service_name != NULL);
+
+ if (strcmp (info->service_name, data->service_name) == 0) {
+ remove_session_for_cookie (data->manager, cookie, NULL);
+ return TRUE;
+ }
+
+ return FALSE;
+}
+
+static void
+remove_sessions_for_connection (CkManager *manager,
+ const char *service_name)
+{
+ guint n_removed;
+ RemoveLeaderData data;
+
+ data.service_name = service_name;
+ data.manager = manager;
+
+ n_removed = g_hash_table_foreach_remove (manager->priv->leaders,
+ (GHRFunc)remove_leader_for_connection,
+ &data);
+
+}
+
+static void
+bus_name_owner_changed (DBusGProxy *bus_proxy,
+ const char *service_name,
+ const char *old_service_name,
+ const char *new_service_name,
+ CkManager *manager)
+{
+ if (strlen (new_service_name) == 0) {
+ remove_sessions_for_connection (manager, old_service_name);
+ }
+
+ ck_debug ("NameOwnerChanged: service_name='%s', old_service_name='%s' new_service_name='%s'",
+ service_name, old_service_name, new_service_name);
+}
+
+static gboolean
+register_manager (CkManager *manager)
+{
+ GError *error = NULL;
+
+ error = NULL;
+ manager->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (manager->priv->connection == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+ exit (1);
+ }
+
+
+ manager->priv->bus_proxy = dbus_g_proxy_new_for_name (manager->priv->connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+ dbus_g_proxy_add_signal (manager->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_STRING,
+ G_TYPE_INVALID);
+ dbus_g_proxy_connect_signal (manager->priv->bus_proxy,
+ "NameOwnerChanged",
+ G_CALLBACK (bus_name_owner_changed),
+ manager,
+ NULL);
+
+ dbus_g_connection_register_g_object (manager->priv->connection, CK_MANAGER_DBUS_PATH, G_OBJECT (manager));
+
+ return TRUE;
+}
+
+static void
+ck_manager_class_init (CkManagerClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ck_manager_finalize;
+
+ signals [SEAT_ADDED] = g_signal_new ("seat-added",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkManagerClass, seat_added),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+ signals [SEAT_REMOVED] = g_signal_new ("seat-removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkManagerClass, seat_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ dbus_g_object_type_install_info (CK_TYPE_MANAGER, &dbus_glib_ck_manager_object_info);
+
+ g_type_class_add_private (klass, sizeof (CkManagerPrivate));
+}
+
+typedef struct {
+ guint uid;
+ GPtrArray *sessions;
+} GetSessionsData;
+
+static void
+get_sessions_for_user_iter (char *id,
+ CkSession *session,
+ GetSessionsData *data)
+{
+ guint uid;
+ gboolean res;
+
+ res = ck_session_get_user (session, &uid, NULL);
+
+ if (res && uid == data->uid) {
+ g_ptr_array_add (data->sessions, g_strdup (id));
+ }
+}
+
+gboolean
+ck_manager_get_sessions_for_user (CkManager *manager,
+ guint uid,
+ DBusGMethodInvocation *context)
+{
+ GetSessionsData *data;
+
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+ data = g_new0 (GetSessionsData, 1);
+ data->uid = uid;
+ data->sessions = g_ptr_array_new ();
+
+ g_hash_table_foreach (manager->priv->sessions, (GHFunc)get_sessions_for_user_iter, data);
+
+ dbus_g_method_return (context, data->sessions);
+
+ g_free (data);
+
+ return TRUE;
+}
+
+static void
+listify_seat_ids (char *id,
+ CkSeat *seat,
+ GPtrArray **array)
+{
+ g_ptr_array_add (*array, g_strdup (id));
+}
+
+gboolean
+ck_manager_get_seats (CkManager *manager,
+ GPtrArray **seats,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_MANAGER (manager), FALSE);
+
+ if (seats == NULL) {
+ return FALSE;
+ }
+
+ *seats = g_ptr_array_new ();
+ g_hash_table_foreach (manager->priv->seats, (GHFunc)listify_seat_ids, seats);
+
+ return TRUE;
+}
+
+static void
+create_seats (CkManager *manager)
+{
+ CkSeat *seat;
+
+ seat = add_new_seat (manager, CK_SEAT_KIND_STATIC);
+}
+
+static void
+ck_manager_init (CkManager *manager)
+{
+
+ manager->priv = CK_MANAGER_GET_PRIVATE (manager);
+
+ /* reserve zero */
+ manager->priv->session_serial = 1;
+ manager->priv->seat_serial = 1;
+
+ manager->priv->seats = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) g_object_unref);
+ manager->priv->sessions = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) g_object_unref);
+ manager->priv->leaders = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) leader_info_free);
+
+ create_seats (manager);
+}
+
+static void
+ck_manager_finalize (GObject *object)
+{
+ CkManager *manager;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CK_IS_MANAGER (object));
+
+ manager = CK_MANAGER (object);
+
+ g_return_if_fail (manager->priv != NULL);
+
+ g_hash_table_destroy (manager->priv->seats);
+ g_hash_table_destroy (manager->priv->sessions);
+ g_hash_table_destroy (manager->priv->leaders);
+ g_object_unref (manager->priv->bus_proxy);
+
+ G_OBJECT_CLASS (ck_manager_parent_class)->finalize (object);
+}
+
+CkManager *
+ck_manager_new (void)
+{
+ if (manager_object != NULL) {
+ g_object_ref (manager_object);
+ } else {
+ gboolean res;
+
+ manager_object = g_object_new (CK_TYPE_MANAGER, NULL);
+ g_object_add_weak_pointer (manager_object,
+ (gpointer *) &manager_object);
+ res = register_manager (manager_object);
+ if (! res) {
+ g_object_unref (manager_object);
+ return NULL;
+ }
+ }
+
+ return CK_MANAGER (manager_object);
+}
diff --git a/src/ck-manager.h b/src/ck-manager.h
new file mode 100644
index 0000000..0834d9f
--- /dev/null
+++ b/src/ck-manager.h
@@ -0,0 +1,97 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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_MANAGER_H
+#define __CK_MANAGER_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include "ck-seat.h"
+
+G_BEGIN_DECLS
+
+#define CK_TYPE_MANAGER (ck_manager_get_type ())
+#define CK_MANAGER(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_MANAGER, CkManager))
+#define CK_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_MANAGER, CkManagerClass))
+#define CK_IS_MANAGER(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_MANAGER))
+#define CK_IS_MANAGER_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_MANAGER))
+#define CK_MANAGER_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_MANAGER, CkManagerClass))
+
+typedef struct CkManagerPrivate CkManagerPrivate;
+
+typedef struct
+{
+ GObject parent;
+ CkManagerPrivate *priv;
+} CkManager;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (* seat_added) (CkManager *manager,
+ const char *sid);
+ void (* seat_removed) (CkManager *manager,
+ const char *sid);
+} CkManagerClass;
+
+typedef enum
+{
+ CK_MANAGER_ERROR_GENERAL
+} CkManagerError;
+
+#define CK_MANAGER_ERROR ck_manager_error_quark ()
+
+GQuark ck_manager_error_quark (void);
+GType ck_manager_get_type (void);
+
+CkManager * ck_manager_new (void);
+
+/* unprivileged methods */
+gboolean ck_manager_open_session (CkManager *manager,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_get_seats (CkManager *manager,
+ GPtrArray **seats,
+ GError **error);
+gboolean ck_manager_close_session (CkManager *manager,
+ const char *cookie,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_get_current_session (CkManager *manager,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_get_session_for_cookie (CkManager *manager,
+ const char *cookie,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_get_session_for_unix_process (CkManager *manager,
+ guint pid,
+ DBusGMethodInvocation *context);
+gboolean ck_manager_get_sessions_for_user (CkManager *manager,
+ guint uid,
+ DBusGMethodInvocation *context);
+
+/* privileged methods - should be protected by D-Bus policy */
+gboolean ck_manager_open_session_with_parameters (CkManager *manager,
+ const GPtrArray *parameters,
+ DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __CK_MANAGER_H */
diff --git a/src/ck-manager.xml b/src/ck-manager.xml
new file mode 100644
index 0000000..8512046
--- /dev/null
+++ b/src/ck-manager.xml
@@ -0,0 +1,48 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node name="/org/freedesktop/ConsoleKit/Manager">
+
+ <interface name="org.freedesktop.ConsoleKit.Manager">
+
+ <method name="OpenSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cookie" direction="out" type="s"/>
+ </method>
+ <method name="OpenSessionWithParameters">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="parameters" direction="in" type="a(sv)"/>
+ <arg name="cookie" direction="out" type="s"/>
+ </method>
+ <method name="CloseSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cookie" direction="in" type="s"/>
+ <arg name="result" direction="out" type="b"/>
+ </method>
+
+ <method name="GetSeats">
+ <arg name="seats" direction="out" type="ao"/>
+ </method>
+
+ <method name="GetCurrentSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="ssid" direction="out" type="o"/>
+ </method>
+ <method name="GetSessionForCookie">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="cookie" direction="in" type="s"/>
+ <arg name="ssid" direction="out" type="o"/>
+ </method>
+ <method name="GetSessionForUnixProcess">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="pid" direction="in" type="u"/>
+ <arg name="ssid" direction="out" type="o"/>
+ </method>
+ <method name="GetSessionsForUser">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="uid" direction="in" type="u"/>
+ <arg name="sessions" direction="out" type="ao"/>
+ </method>
+
+ <signal name="SeatAdded"/>
+ <signal name="SeatRemoved"/>
+ </interface>
+</node>
diff --git a/src/ck-marshal.c b/src/ck-marshal.c
new file mode 100644
index 0000000..6b77b77
--- /dev/null
+++ b/src/ck-marshal.c
@@ -0,0 +1,126 @@
+#include "ck-marshal.h"
+
+#include <glib-object.h>
+
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* VOID:UINT,STRING (ck-marshal.list:1) */
+void
+ck_marshal_VOID__UINT_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__UINT_STRING) (gpointer data1,
+ guint arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__UINT_STRING callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__UINT_STRING) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_uint (param_values + 1),
+ g_marshal_value_peek_string (param_values + 2),
+ data2);
+}
+
+/* BOOLEAN:POINTER (ck-marshal.list:2) */
+void
+ck_marshal_BOOLEAN__POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 2);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_pointer (param_values + 1),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
diff --git a/src/ck-marshal.h b/src/ck-marshal.h
new file mode 100644
index 0000000..7553810
--- /dev/null
+++ b/src/ck-marshal.h
@@ -0,0 +1,28 @@
+
+#ifndef __ck_marshal_MARSHAL_H__
+#define __ck_marshal_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+/* VOID:UINT,STRING (ck-marshal.list:1) */
+extern void ck_marshal_VOID__UINT_STRING (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+/* BOOLEAN:POINTER (ck-marshal.list:2) */
+extern void ck_marshal_BOOLEAN__POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+
+G_END_DECLS
+
+#endif /* __ck_marshal_MARSHAL_H__ */
+
diff --git a/src/ck-marshal.list b/src/ck-marshal.list
new file mode 100644
index 0000000..f9eed10
--- /dev/null
+++ b/src/ck-marshal.list
@@ -0,0 +1,2 @@
+VOID:UINT,STRING
+BOOLEAN:POINTER
diff --git a/src/ck-seat-glue.h b/src/ck-seat-glue.h
new file mode 100644
index 0000000..426b2f9
--- /dev/null
+++ b/src/ck-seat-glue.h
@@ -0,0 +1,167 @@
+/* Generated by dbus-binding-tool; do not edit! */
+
+
+#ifndef __dbus_glib_marshal_ck_seat_MARSHAL_H__
+#define __dbus_glib_marshal_ck_seat_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.S4XJHT:1) */
+extern void dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_pointer (param_values + 1),
+ g_marshal_value_peek_pointer (param_values + 2),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* NONE:BOXED,POINTER (/tmp/dbus-binding-tool-c-marshallers.S4XJHT:2) */
+extern void dbus_glib_marshal_ck_seat_VOID__BOXED_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+dbus_glib_marshal_ck_seat_VOID__BOXED_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef void (*GMarshalFunc_VOID__BOXED_POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_VOID__BOXED_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_VOID__BOXED_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ callback (data1,
+ g_marshal_value_peek_boxed (param_values + 1),
+ g_marshal_value_peek_pointer (param_values + 2),
+ data2);
+}
+#define dbus_glib_marshal_ck_seat_NONE__BOXED_POINTER dbus_glib_marshal_ck_seat_VOID__BOXED_POINTER
+
+G_END_DECLS
+
+#endif /* __dbus_glib_marshal_ck_seat_MARSHAL_H__ */
+
+#include <dbus/dbus-glib.h>
+static const DBusGMethodInfo dbus_glib_ck_seat_methods[] = {
+ { (GCallback) ck_seat_get_id, dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER, 0 },
+ { (GCallback) ck_seat_get_sessions, dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER, 53 },
+ { (GCallback) ck_seat_get_active_session, dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER, 118 },
+ { (GCallback) ck_seat_activate_session, dbus_glib_marshal_ck_seat_NONE__BOXED_POINTER, 183 },
+};
+
+const DBusGObjectInfo dbus_glib_ck_seat_object_info = {
+ 0,
+ dbus_glib_ck_seat_methods,
+ 4,
+"org.freedesktop.ConsoleKit.Seat\0GetId\0S\0sid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Seat\0GetSessions\0S\0sessions\0O\0F\0N\0ao\0\0org.freedesktop.ConsoleKit.Seat\0GetActiveSession\0S\0ssid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Seat\0ActivateSession\0A\0ssid\0I\0o\0\0\0",
+"org.freedesktop.ConsoleKit.Seat\0ActiveSessionChanged\0org.freedesktop.ConsoleKit.Seat\0SessionAdded\0org.freedesktop.ConsoleKit.Seat\0SessionRemoved\0\0",
+"\0"
+};
+
diff --git a/src/ck-seat.c b/src/ck-seat.c
new file mode 100644
index 0000000..fa73c40
--- /dev/null
+++ b/src/ck-seat.c
@@ -0,0 +1,724 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "ck-seat.h"
+#include "ck-seat-glue.h"
+#include "ck-marshal.h"
+
+#include "ck-session.h"
+#include "ck-vt-monitor.h"
+#include "ck-debug.h"
+
+#define CK_SEAT_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SEAT, CkSeatPrivate))
+
+#define CK_DBUS_PATH "/org/freedesktop/ConsoleKit"
+#define CK_DBUS_NAME "org.freedesktop.ConsoleKit"
+
+struct CkSeatPrivate
+{
+ char *id;
+ CkSeatKind kind;
+ GHashTable *sessions;
+
+ CkSession *active_session;
+
+ CkVtMonitor *vt_monitor;
+
+ DBusGConnection *connection;
+};
+
+enum {
+ ACTIVE_SESSION_CHANGED,
+ SESSION_ADDED,
+ SESSION_REMOVED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_ID,
+ PROP_KIND,
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void ck_seat_class_init (CkSeatClass *klass);
+static void ck_seat_init (CkSeat *seat);
+static void ck_seat_finalize (GObject *object);
+
+G_DEFINE_TYPE (CkSeat, ck_seat, G_TYPE_OBJECT)
+
+GQuark
+ck_seat_error_quark (void)
+{
+ static GQuark ret = 0;
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("ck_seat_error");
+ }
+
+ return ret;
+}
+
+#define ENUM_ENTRY(NAME, DESC) { NAME, "" #NAME "", DESC }
+
+GType
+ck_seat_kind_get_type (void)
+{
+ static GType etype = 0;
+
+ if (etype == 0) {
+ static const GEnumValue values[] = {
+ ENUM_ENTRY (CK_SEAT_KIND_STATIC, "Fixed single instance local seat"),
+ ENUM_ENTRY (CK_SEAT_KIND_DYNAMIC, "Transient seat"),
+ { 0, 0, 0 }
+ };
+
+ etype = g_enum_register_static ("CkSeatKindType", values);
+ }
+
+ return etype;
+}
+
+gboolean
+ck_seat_get_active_session (CkSeat *seat,
+ char **ssid,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ if (seat->priv->active_session != NULL) {
+ ck_session_get_id (seat->priv->active_session, ssid, NULL);
+ } else {
+ if (ssid != NULL) {
+ *ssid = NULL;
+ }
+ }
+
+ return TRUE;
+}
+
+typedef struct
+{
+ gulong handler_id;
+ CkSeat *seat;
+ guint num;
+ DBusGMethodInvocation *context;
+} ActivateData;
+
+static void
+activated_cb (CkVtMonitor *vt_monitor,
+ guint num,
+ ActivateData *adata)
+{
+ if (adata->num == num) {
+ dbus_g_method_return (adata->context, TRUE);
+ } else {
+ GError *error;
+
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Another session was activated while waiting"));
+ dbus_g_method_return_error (adata->context, error);
+ g_error_free (error);
+ }
+
+ g_signal_handler_disconnect (vt_monitor, adata->handler_id);
+}
+
+static gboolean
+_seat_activate_session (CkSeat *seat,
+ CkSession *session,
+ DBusGMethodInvocation *context)
+{
+ gboolean ret;
+ guint num;
+ char *device;
+ ActivateData *adata;
+ GError *vt_error;
+
+ device = NULL;
+ adata = NULL;
+ ret = FALSE;
+
+ /* for now, only support switching on static seat */
+ if (seat->priv->kind != CK_SEAT_KIND_STATIC) {
+ GError *error;
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Activation is not supported for this kind of seat"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ if (session == NULL) {
+ GError *error;
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Unknown session id"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ ck_session_get_display_device (session, &device, NULL);
+
+ if (device == NULL || (sscanf (device, "/dev/tty%u", &num) != 1)) {
+ GError *error;
+ error = g_error_new (CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Unable to activate session"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ goto out;
+ }
+
+ adata = g_new0 (ActivateData, 1);
+ adata->context = context;
+ adata->seat = seat;
+ adata->num = num;
+ adata->handler_id = g_signal_connect_data (seat->priv->vt_monitor,
+ "active-changed",
+ G_CALLBACK (activated_cb),
+ adata,
+ (GClosureNotify)g_free,
+ 0);
+
+
+ ck_debug ("Attempting to activate VT %u", num);
+
+ vt_error = NULL;
+ ret = ck_vt_monitor_set_active (seat->priv->vt_monitor, num, &vt_error);
+ if (! ret) {
+ ck_debug ("Unable to activate session: %s", vt_error->message);
+ dbus_g_method_return_error (context, vt_error);
+ g_signal_handler_disconnect (seat->priv->vt_monitor, adata->handler_id);
+ g_error_free (vt_error);
+ goto out;
+ }
+
+ out:
+ g_free (device);
+
+ return ret;
+}
+
+/*
+ Example:
+ dbus-send --system --dest=org.freedesktop.ConsoleKit \
+ --type=method_call --print-reply --reply-timeout=2000 \
+ /org/freedesktop/ConsoleKit/Seat1 \
+ org.freedesktop.ConsoleKit.Seat.ActivateSession \
+ objpath:/org/freedesktop/ConsoleKit/Session2
+*/
+
+gboolean
+ck_seat_activate_session (CkSeat *seat,
+ const char *ssid,
+ DBusGMethodInvocation *context)
+{
+ CkSession *session;
+ gboolean ret;
+
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ session = NULL;
+
+ if (ssid != NULL) {
+ session = g_hash_table_lookup (seat->priv->sessions, ssid);
+ }
+
+ ret = _seat_activate_session (seat, session, context);
+
+ return ret;
+}
+
+static gboolean
+match_session_display_device (const char *key,
+ CkSession *session,
+ const char *display_device)
+{
+ char *device;
+ gboolean ret;
+
+ device = NULL;
+ ret = FALSE;
+
+ if (session == NULL) {
+ goto out;
+ }
+
+ ck_session_get_display_device (session, &device, NULL);
+
+ if (device != NULL
+ && display_device != NULL
+ && strcmp (device, display_device) == 0) {
+ ret = TRUE;
+ }
+out:
+
+ g_free (device);
+
+ return ret;
+}
+
+static CkSession *
+find_session_for_display_device (CkSeat *seat,
+ const char *device)
+{
+ CkSession *session;
+
+ session = g_hash_table_find (seat->priv->sessions,
+ (GHRFunc) match_session_display_device,
+ (gpointer)device);
+ return session;
+}
+
+static void
+change_active_session (CkSeat *seat,
+ CkSession *session)
+{
+ char *ssid;
+
+ if (seat->priv->active_session == session) {
+ return;
+ }
+
+ if (seat->priv->active_session != NULL) {
+ ck_session_set_active (seat->priv->active_session, FALSE, NULL);
+ g_object_unref (seat->priv->active_session);
+ }
+
+ seat->priv->active_session = session;
+
+ ssid = NULL;
+ if (session != NULL) {
+ g_object_ref (session);
+ ck_session_get_id (session, &ssid, NULL);
+ ck_session_set_active (session, TRUE, NULL);
+ }
+
+ ck_debug ("Active session changed: %s", ssid);
+
+ g_signal_emit (seat, signals [ACTIVE_SESSION_CHANGED], 0, ssid);
+
+ g_free (ssid);
+}
+
+static void
+maybe_update_active_session (CkSeat *seat)
+{
+ guint num;
+
+ if (seat->priv->kind != CK_SEAT_KIND_STATIC) {
+ return;
+ }
+
+ if (ck_vt_monitor_get_active (seat->priv->vt_monitor, &num, NULL)) {
+ CkSession *session;
+ char *device;
+
+ device = g_strdup_printf ("/dev/tty%u", num);
+
+ ck_debug ("Active device: %s", device);
+
+ session = find_session_for_display_device (seat, device);
+ if (session != NULL) {
+ change_active_session (seat, session);
+ }
+
+ g_free (device);
+ }
+}
+
+static gboolean
+session_activate (CkSession *session,
+ DBusGMethodInvocation *context,
+ CkSeat *seat)
+{
+ return _seat_activate_session (seat, session, context);
+}
+
+gboolean
+ck_seat_remove_session (CkSeat *seat,
+ CkSession *session,
+ GError **error)
+{
+ char *ssid;
+
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ ssid = NULL;
+ ck_session_get_id (session, &ssid, NULL);
+
+ if (g_hash_table_lookup (seat->priv->sessions, ssid) == NULL) {
+ ck_debug ("Session %s is not attached to seat %s", ssid, seat->priv->id);
+ g_set_error (error,
+ CK_SEAT_ERROR,
+ CK_SEAT_ERROR_GENERAL,
+ _("Session is not attached to this seat"));
+ g_free (ssid);
+ return FALSE;
+ }
+
+ g_signal_handlers_disconnect_by_func (session, session_activate, seat);
+
+ ck_debug ("Emitting removed signal: %s", ssid);
+
+ g_signal_emit (seat, signals [SESSION_REMOVED], 0, ssid);
+
+ /* try to change the active session */
+ maybe_update_active_session (seat);
+
+ /* if the active session is still the one to be removed, unset it */
+ if (seat->priv->active_session == session) {
+ change_active_session (seat, NULL);
+ }
+
+ g_hash_table_remove (seat->priv->sessions, ssid);
+
+ return TRUE;
+}
+
+gboolean
+ck_seat_add_session (CkSeat *seat,
+ CkSession *session,
+ GError **error)
+{
+ char *ssid;
+
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ ck_session_get_id (session, &ssid, NULL);
+
+ g_hash_table_insert (seat->priv->sessions, g_strdup (ssid), g_object_ref (session));
+
+ ck_session_set_seat_id (session, seat->priv->id, NULL);
+
+ g_signal_connect_object (session, "activate", G_CALLBACK (session_activate), seat, 0);
+ /* FIXME: attach to property notify signals? */
+
+ ck_debug ("Emitting added signal: %s", ssid);
+
+ g_signal_emit (seat, signals [SESSION_ADDED], 0, ssid);
+
+ maybe_update_active_session (seat);
+
+ return TRUE;
+}
+
+gboolean
+ck_seat_get_kind (CkSeat *seat,
+ CkSeatKind *kind,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ if (kind != NULL) {
+ *kind = seat->priv->kind;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_seat_get_id (CkSeat *seat,
+ char **id,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ if (id != NULL) {
+ *id = g_strdup (seat->priv->id);
+ }
+
+ return TRUE;
+}
+
+static void
+active_vt_changed (CkVtMonitor *vt_monitor,
+ guint num,
+ CkSeat *seat)
+{
+ ck_debug ("Active vt changed: %u", num);
+
+ maybe_update_active_session (seat);
+}
+
+static gboolean
+register_seat (CkSeat *seat)
+{
+ GError *error = NULL;
+
+ error = NULL;
+ seat->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (seat->priv->connection == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+ return FALSE;
+ }
+
+ dbus_g_connection_register_g_object (seat->priv->connection, seat->priv->id, G_OBJECT (seat));
+
+ return TRUE;
+}
+
+static void
+listify_session_ids (char *id,
+ CkSession *session,
+ GPtrArray **array)
+{
+ g_ptr_array_add (*array, g_strdup (id));
+}
+
+gboolean
+ck_seat_get_sessions (CkSeat *seat,
+ GPtrArray **sessions,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SEAT (seat), FALSE);
+
+ if (sessions == NULL) {
+ return FALSE;
+ }
+
+ *sessions = g_ptr_array_new ();
+ g_hash_table_foreach (seat->priv->sessions, (GHFunc)listify_session_ids, sessions);
+
+ return TRUE;
+}
+
+static void
+_ck_seat_set_id (CkSeat *seat,
+ const char *id)
+{
+ g_free (seat->priv->id);
+ seat->priv->id = g_strdup (id);
+}
+
+static void
+_ck_seat_set_kind (CkSeat *seat,
+ CkSeatKind kind)
+{
+ seat->priv->kind = kind;
+}
+
+static void
+ck_seat_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CkSeat *self;
+
+ self = CK_SEAT (object);
+
+ switch (prop_id) {
+ case PROP_ID:
+ _ck_seat_set_id (self, g_value_get_string (value));
+ break;
+ case PROP_KIND:
+ _ck_seat_set_kind (self, g_value_get_enum (value));
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ck_seat_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CkSeat *self;
+
+ self = CK_SEAT (object);
+
+ switch (prop_id) {
+ case PROP_ID:
+ g_value_set_string (value, self->priv->id);
+ break;
+ case PROP_KIND:
+ g_value_set_string (value, self->priv->id);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static GObject *
+ck_seat_constructor (GType type,
+ guint n_construct_properties,
+ GObjectConstructParam *construct_properties)
+{
+ CkSeat *seat;
+ CkSeatClass *klass;
+
+ klass = CK_SEAT_CLASS (g_type_class_peek (CK_TYPE_SEAT));
+
+ seat = CK_SEAT (G_OBJECT_CLASS (ck_seat_parent_class)->constructor (type,
+ n_construct_properties,
+ construct_properties));
+
+ if (seat->priv->kind == CK_SEAT_KIND_STATIC) {
+ seat->priv->vt_monitor = ck_vt_monitor_new ();
+ g_signal_connect (seat->priv->vt_monitor, "active-changed", G_CALLBACK (active_vt_changed), seat);
+ }
+
+ return G_OBJECT (seat);
+}
+
+static void
+ck_seat_class_init (CkSeatClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = ck_seat_get_property;
+ object_class->set_property = ck_seat_set_property;
+ object_class->constructor = ck_seat_constructor;
+ object_class->finalize = ck_seat_finalize;
+
+ signals [ACTIVE_SESSION_CHANGED] = g_signal_new ("active-session-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSeatClass, active_session_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+ signals [SESSION_ADDED] = g_signal_new ("session-added",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSeatClass, session_added),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+ signals [SESSION_REMOVED] = g_signal_new ("session-removed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSeatClass, session_removed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__STRING,
+ G_TYPE_NONE,
+ 1, G_TYPE_STRING);
+
+ g_object_class_install_property (object_class,
+ PROP_ID,
+ g_param_spec_string ("id",
+ "id",
+ "id",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_KIND,
+ g_param_spec_enum ("kind",
+ "kind",
+ "kind",
+ CK_TYPE_SEAT_KIND,
+ CK_SEAT_KIND_DYNAMIC,
+ 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);
+}
+
+static void
+ck_seat_init (CkSeat *seat)
+{
+ seat->priv = CK_SEAT_GET_PRIVATE (seat);
+
+ seat->priv->sessions = g_hash_table_new_full (g_str_hash,
+ g_str_equal,
+ g_free,
+ (GDestroyNotify) g_object_unref);
+}
+
+static void
+ck_seat_finalize (GObject *object)
+{
+ CkSeat *seat;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CK_IS_SEAT (object));
+
+ seat = CK_SEAT (object);
+
+ g_return_if_fail (seat->priv != NULL);
+
+ if (seat->priv->vt_monitor != NULL) {
+ g_object_unref (seat->priv->vt_monitor);
+ }
+
+ if (seat->priv->active_session != NULL) {
+ g_object_unref (seat->priv->active_session);
+ }
+
+ g_hash_table_destroy (seat->priv->sessions);
+ g_free (seat->priv->id);
+
+ G_OBJECT_CLASS (ck_seat_parent_class)->finalize (object);
+}
+
+CkSeat *
+ck_seat_new (const char *sid,
+ CkSeatKind kind)
+{
+ GObject *object;
+ gboolean res;
+
+ object = g_object_new (CK_TYPE_SEAT,
+ "id", sid,
+ "kind", kind,
+ NULL);
+
+ res = register_seat (CK_SEAT (object));
+ if (! res) {
+ g_object_unref (object);
+ return NULL;
+ }
+
+ return CK_SEAT (object);
+}
diff --git a/src/ck-seat.h b/src/ck-seat.h
new file mode 100644
index 0000000..0b13eb4
--- /dev/null
+++ b/src/ck-seat.h
@@ -0,0 +1,111 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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_SEAT_H
+#define __CK_SEAT_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+#include "ck-session.h"
+
+G_BEGIN_DECLS
+
+#define CK_TYPE_SEAT (ck_seat_get_type ())
+#define CK_SEAT(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_SEAT, CkSeat))
+#define CK_SEAT_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_SEAT, CkSeatClass))
+#define CK_IS_SEAT(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_SEAT))
+#define CK_IS_SEAT_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_SEAT))
+#define CK_SEAT_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_SEAT, CkSeatClass))
+
+typedef struct CkSeatPrivate CkSeatPrivate;
+
+typedef struct
+{
+ GObject parent;
+ CkSeatPrivate *priv;
+} CkSeat;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (* active_session_changed) (CkSeat *seat,
+ const char *ssid);
+ void (* session_added) (CkSeat *seat,
+ const char *ssid);
+ void (* session_removed) (CkSeat *seat,
+ const char *ssid);
+} CkSeatClass;
+
+typedef enum
+{
+ CK_SEAT_KIND_STATIC,
+ CK_SEAT_KIND_DYNAMIC,
+} CkSeatKind;
+
+GType ck_seat_kind_get_type (void);
+#define CK_TYPE_SEAT_KIND (ck_seat_kind_get_type ())
+
+typedef enum
+{
+ CK_SEAT_ERROR_GENERAL
+} CkSeatError;
+
+#define CK_SEAT_ERROR ck_seat_error_quark ()
+
+GQuark ck_seat_error_quark (void);
+GType ck_seat_get_type (void);
+CkSeat * ck_seat_new (const char *sid,
+ CkSeatKind kind);
+gboolean ck_seat_get_kind (CkSeat *seat,
+ CkSeatKind *kind,
+ 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_set_active_session (CkSeat *seat,
+ CkSession *session,
+ GError **error);
+
+/* exported methods */
+gboolean ck_seat_get_id (CkSeat *seat,
+ char **sid,
+ GError **error);
+gboolean ck_seat_get_seat_type (CkSeat *seat,
+ char **type,
+ GError **error);
+gboolean ck_seat_get_sessions (CkSeat *seat,
+ GPtrArray **sessions,
+ GError **error);
+gboolean ck_seat_get_active_session (CkSeat *seat,
+ char **ssid,
+ GError **error);
+
+gboolean ck_seat_activate_session (CkSeat *seat,
+ const char *ssid,
+ DBusGMethodInvocation *context);
+
+G_END_DECLS
+
+#endif /* __CK_SEAT_H */
diff --git a/src/ck-seat.xml b/src/ck-seat.xml
new file mode 100644
index 0000000..9a32e57
--- /dev/null
+++ b/src/ck-seat.xml
@@ -0,0 +1,27 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node>
+
+ <interface name="org.freedesktop.ConsoleKit.Seat">
+
+ <method name="GetId">
+ <arg name="sid" direction="out" type="o"/>
+ </method>
+
+ <method name="GetSessions">
+ <arg name="sessions" direction="out" type="ao"/>
+ </method>
+
+ <method name="GetActiveSession">
+ <arg name="ssid" direction="out" type="o"/>
+ </method>
+
+ <method name="ActivateSession">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ <arg name="ssid" direction="in" type="o"/>
+ </method>
+
+ <signal name="ActiveSessionChanged"/>
+ <signal name="SessionAdded"/>
+ <signal name="SessionRemoved"/>
+ </interface>
+</node>
diff --git a/src/ck-session-glue.h b/src/ck-session-glue.h
new file mode 100644
index 0000000..ba4e14a
--- /dev/null
+++ b/src/ck-session-glue.h
@@ -0,0 +1,135 @@
+/* Generated by dbus-binding-tool; do not edit! */
+
+
+#ifndef __dbus_glib_marshal_ck_session_MARSHAL_H__
+#define __dbus_glib_marshal_ck_session_MARSHAL_H__
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#ifdef G_ENABLE_DEBUG
+#define g_marshal_value_peek_boolean(v) g_value_get_boolean (v)
+#define g_marshal_value_peek_char(v) g_value_get_char (v)
+#define g_marshal_value_peek_uchar(v) g_value_get_uchar (v)
+#define g_marshal_value_peek_int(v) g_value_get_int (v)
+#define g_marshal_value_peek_uint(v) g_value_get_uint (v)
+#define g_marshal_value_peek_long(v) g_value_get_long (v)
+#define g_marshal_value_peek_ulong(v) g_value_get_ulong (v)
+#define g_marshal_value_peek_int64(v) g_value_get_int64 (v)
+#define g_marshal_value_peek_uint64(v) g_value_get_uint64 (v)
+#define g_marshal_value_peek_enum(v) g_value_get_enum (v)
+#define g_marshal_value_peek_flags(v) g_value_get_flags (v)
+#define g_marshal_value_peek_float(v) g_value_get_float (v)
+#define g_marshal_value_peek_double(v) g_value_get_double (v)
+#define g_marshal_value_peek_string(v) (char*) g_value_get_string (v)
+#define g_marshal_value_peek_param(v) g_value_get_param (v)
+#define g_marshal_value_peek_boxed(v) g_value_get_boxed (v)
+#define g_marshal_value_peek_pointer(v) g_value_get_pointer (v)
+#define g_marshal_value_peek_object(v) g_value_get_object (v)
+#else /* !G_ENABLE_DEBUG */
+/* WARNING: This code accesses GValues directly, which is UNSUPPORTED API.
+ * Do not access GValues directly in your code. Instead, use the
+ * g_value_get_*() functions
+ */
+#define g_marshal_value_peek_boolean(v) (v)->data[0].v_int
+#define g_marshal_value_peek_char(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uchar(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_int(v) (v)->data[0].v_int
+#define g_marshal_value_peek_uint(v) (v)->data[0].v_uint
+#define g_marshal_value_peek_long(v) (v)->data[0].v_long
+#define g_marshal_value_peek_ulong(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_int64(v) (v)->data[0].v_int64
+#define g_marshal_value_peek_uint64(v) (v)->data[0].v_uint64
+#define g_marshal_value_peek_enum(v) (v)->data[0].v_long
+#define g_marshal_value_peek_flags(v) (v)->data[0].v_ulong
+#define g_marshal_value_peek_float(v) (v)->data[0].v_float
+#define g_marshal_value_peek_double(v) (v)->data[0].v_double
+#define g_marshal_value_peek_string(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_param(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_boxed(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_pointer(v) (v)->data[0].v_pointer
+#define g_marshal_value_peek_object(v) (v)->data[0].v_pointer
+#endif /* !G_ENABLE_DEBUG */
+
+
+/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.FCHLHT:1) */
+extern void dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data);
+void
+dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER (GClosure *closure,
+ GValue *return_value,
+ guint n_param_values,
+ const GValue *param_values,
+ gpointer invocation_hint,
+ gpointer marshal_data)
+{
+ typedef gboolean (*GMarshalFunc_BOOLEAN__POINTER_POINTER) (gpointer data1,
+ gpointer arg_1,
+ gpointer arg_2,
+ gpointer data2);
+ register GMarshalFunc_BOOLEAN__POINTER_POINTER callback;
+ register GCClosure *cc = (GCClosure*) closure;
+ register gpointer data1, data2;
+ gboolean v_return;
+
+ g_return_if_fail (return_value != NULL);
+ g_return_if_fail (n_param_values == 3);
+
+ if (G_CCLOSURE_SWAP_DATA (closure))
+ {
+ data1 = closure->data;
+ data2 = g_value_peek_pointer (param_values + 0);
+ }
+ else
+ {
+ data1 = g_value_peek_pointer (param_values + 0);
+ data2 = closure->data;
+ }
+ callback = (GMarshalFunc_BOOLEAN__POINTER_POINTER) (marshal_data ? marshal_data : cc->callback);
+
+ v_return = callback (data1,
+ g_marshal_value_peek_pointer (param_values + 1),
+ g_marshal_value_peek_pointer (param_values + 2),
+ data2);
+
+ g_value_set_boolean (return_value, v_return);
+}
+
+/* NONE:POINTER (/tmp/dbus-binding-tool-c-marshallers.FCHLHT:2) */
+#define dbus_glib_marshal_ck_session_VOID__POINTER g_cclosure_marshal_VOID__POINTER
+#define dbus_glib_marshal_ck_session_NONE__POINTER dbus_glib_marshal_ck_session_VOID__POINTER
+
+G_END_DECLS
+
+#endif /* __dbus_glib_marshal_ck_session_MARSHAL_H__ */
+
+#include <dbus/dbus-glib.h>
+static const DBusGMethodInfo dbus_glib_ck_session_methods[] = {
+ { (GCallback) ck_session_get_id, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 0 },
+ { (GCallback) ck_session_get_seat_id, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 57 },
+ { (GCallback) ck_session_get_session_type, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 117 },
+ { (GCallback) ck_session_get_user, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 183 },
+ { (GCallback) ck_session_get_x11_display, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 241 },
+ { (GCallback) ck_session_get_display_device, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 309 },
+ { (GCallback) ck_session_get_host_name, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 387 },
+ { (GCallback) ck_session_is_active, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 455 },
+ { (GCallback) ck_session_is_local, dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER, 517 },
+ { (GCallback) ck_session_activate, dbus_glib_marshal_ck_session_NONE__POINTER, 577 },
+ { (GCallback) ck_session_lock, dbus_glib_marshal_ck_session_NONE__POINTER, 624 },
+ { (GCallback) ck_session_unlock, dbus_glib_marshal_ck_session_NONE__POINTER, 667 },
+};
+
+const DBusGObjectInfo dbus_glib_ck_session_object_info = {
+ 0,
+ dbus_glib_ck_session_methods,
+ 12,
+"org.freedesktop.ConsoleKit.Session\0GetId\0S\0ssid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Session\0GetSeatId\0S\0sid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Session\0GetSessionType\0S\0type\0O\0F\0N\0s\0\0org.freedesktop.ConsoleKit.Session\0GetUser\0S\0uid\0O\0F\0N\0i\0\0org.freedesktop.ConsoleKit.Session\0GetX11Display\0S\0display\0O\0F\0N\0s\0\0org.freedesktop.ConsoleKit.Session\0GetDisplayDevice\0S\0display_device\0O\0F\0N\0s\0\0org.freedesktop.ConsoleKit.Session\0GetHostName\0S\0host_name\0O\0F\0N\0s\0\0org.freedesktop.ConsoleKit.Session\0IsActive\0S\0active\0O\0F\0N\0b\0\0org.freedesktop.ConsoleKit.Session\0IsLocal\0S\0local\0O\0F\0N\0b\0\0org.freedesktop.ConsoleKit.Session\0Activate\0A\0\0org.freedesktop.ConsoleKit.Session\0Lock\0A\0\0org.freedesktop.ConsoleKit.Session\0Unlock\0A\0\0\0",
+"org.freedesktop.ConsoleKit.Session\0ActiveChanged\0org.freedesktop.ConsoleKit.Session\0Lock\0org.freedesktop.ConsoleKit.Session\0Unlock\0\0",
+"\0"
+};
+
diff --git a/src/ck-session.c b/src/ck-session.c
new file mode 100644
index 0000000..278d7bc
--- /dev/null
+++ b/src/ck-session.c
@@ -0,0 +1,744 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <signal.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "ck-session.h"
+#include "ck-session-glue.h"
+#include "ck-marshal.h"
+#include "ck-debug.h"
+
+#define CK_SESSION_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_SESSION, CkSessionPrivate))
+
+#define CK_DBUS_PATH "/org/freedesktop/ConsoleKit"
+#define CK_DBUS_NAME "org.freedesktop.ConsoleKit"
+
+struct CkSessionPrivate
+{
+ char *id;
+ char *cookie;
+ char *seat_id;
+
+ char *session_type;
+ char *display_device;
+ char *xdisplay;
+ char *host_name;
+ guint uid;
+
+ gboolean active;
+ gboolean is_local;
+
+ DBusGConnection *connection;
+};
+
+enum {
+ ACTIVATE,
+ LOCK,
+ UNLOCK,
+ ACTIVE_CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+ PROP_ID,
+ PROP_COOKIE,
+ PROP_USER,
+ PROP_X11_DISPLAY,
+ PROP_DISPLAY_DEVICE,
+ PROP_SESSION_TYPE,
+ PROP_HOST_NAME,
+ PROP_IS_LOCAL,
+ PROP_ACTIVE,
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void ck_session_class_init (CkSessionClass *klass);
+static void ck_session_init (CkSession *session);
+static void ck_session_finalize (GObject *object);
+
+G_DEFINE_TYPE (CkSession, ck_session, G_TYPE_OBJECT)
+
+GQuark
+ck_session_error_quark (void)
+{
+ static GQuark ret = 0;
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("ck_session_error");
+ }
+
+ return ret;
+}
+
+static gboolean
+register_session (CkSession *session)
+{
+ GError *error = NULL;
+
+ error = NULL;
+ session->priv->connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (session->priv->connection == NULL) {
+ if (error != NULL) {
+ g_critical ("error getting system bus: %s", error->message);
+ g_error_free (error);
+ }
+ return FALSE;
+ }
+
+ dbus_g_connection_register_g_object (session->priv->connection, session->priv->id, G_OBJECT (session));
+
+ return TRUE;
+}
+
+
+/*
+ lock and unlock are separate functions because:
+ 1. we don't maintain state for locked
+ 2. so security policy can be handled separately
+*/
+gboolean
+ck_session_lock (CkSession *session,
+ DBusGMethodInvocation *context)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_signal_emit (session, signals [LOCK], 0);
+
+ dbus_g_method_return (context, TRUE);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_unlock (CkSession *session,
+ DBusGMethodInvocation *context)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_signal_emit (session, signals [UNLOCK], 0);
+
+ dbus_g_method_return (context, TRUE);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_activate (CkSession *session,
+ DBusGMethodInvocation *context)
+{
+ gboolean res;
+
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ res = FALSE;
+ g_signal_emit (session, signals [ACTIVATE], 0, context, &res);
+ if (! res) {
+ GError *error;
+
+ /* if the signal is not handled then either:
+ a) aren't attached to seat
+ b) seat doesn't support activation changes */
+ ck_debug ("Activate signal not handled");
+
+ error = g_error_new (CK_SESSION_ERROR,
+ CK_SESSION_ERROR_GENERAL,
+ _("Unable to activate session"));
+ dbus_g_method_return_error (context, error);
+ g_error_free (error);
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_active (CkSession *session,
+ gboolean active,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (session->priv->active != active) {
+ session->priv->active = active;
+ g_signal_emit (session, signals [ACTIVE_CHANGED], 0, active);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_is_local (CkSession *session,
+ gboolean is_local,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (session->priv->is_local != is_local) {
+ session->priv->is_local = is_local;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_id (CkSession *session,
+ char **id,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (id != NULL) {
+ *id = g_strdup (session->priv->id);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_seat_id (CkSession *session,
+ char **id,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (id != NULL) {
+ *id = g_strdup (session->priv->seat_id);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_user (CkSession *session,
+ guint *uid,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (uid != NULL) {
+ *uid = session->priv->uid;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_x11_display (CkSession *session,
+ char **xdisplay,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (xdisplay != NULL) {
+ *xdisplay = g_strdup (session->priv->xdisplay);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_display_device (CkSession *session,
+ char **display_device,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (display_device != NULL) {
+ *display_device = g_strdup (session->priv->display_device);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_host_name (CkSession *session,
+ char **host_name,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (host_name != NULL) {
+ *host_name = g_strdup (session->priv->host_name);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_get_session_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->session_type);
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_is_active (CkSession *session,
+ gboolean *active,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (active != NULL) {
+ *active = session->priv->active;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_is_local (CkSession *session,
+ gboolean *local,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ if (local != NULL) {
+ *local = session->priv->is_local;
+ }
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_id (CkSession *session,
+ const char *id,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->id);
+ session->priv->id = g_strdup (id);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_cookie (CkSession *session,
+ const char *cookie,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->cookie);
+ session->priv->cookie = g_strdup (cookie);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_seat_id (CkSession *session,
+ const char *id,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->seat_id);
+ session->priv->seat_id = g_strdup (id);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_user (CkSession *session,
+ guint uid,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ session->priv->uid = uid;
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_x11_display (CkSession *session,
+ const char *xdisplay,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->xdisplay);
+ session->priv->xdisplay = g_strdup (xdisplay);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_display_device (CkSession *session,
+ const char *display_device,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->display_device);
+ session->priv->display_device = g_strdup (display_device);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_host_name (CkSession *session,
+ const char *host_name,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->host_name);
+ session->priv->host_name = g_strdup (host_name);
+
+ return TRUE;
+}
+
+gboolean
+ck_session_set_session_type (CkSession *session,
+ const char *type,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_SESSION (session), FALSE);
+
+ g_free (session->priv->session_type);
+ session->priv->session_type = g_strdup (type);
+
+ return TRUE;
+}
+
+static void
+ck_session_set_property (GObject *object,
+ guint prop_id,
+ const GValue *value,
+ GParamSpec *pspec)
+{
+ CkSession *self;
+
+ self = CK_SESSION (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE:
+ ck_session_set_active (self, g_value_get_boolean (value), NULL);
+ break;
+ case PROP_IS_LOCAL:
+ ck_session_set_is_local (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_SESSION_TYPE:
+ ck_session_set_session_type (self, g_value_get_string (value), NULL);
+ break;
+ case PROP_X11_DISPLAY:
+ ck_session_set_x11_display (self, g_value_get_string (value), NULL);
+ break;
+ case PROP_DISPLAY_DEVICE:
+ ck_session_set_display_device (self, g_value_get_string (value), NULL);
+ break;
+ case PROP_USER:
+ ck_session_set_user (self, g_value_get_uint (value), NULL);
+ break;
+ case PROP_HOST_NAME:
+ ck_session_set_host_name (self, g_value_get_string (value), NULL);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ck_session_get_property (GObject *object,
+ guint prop_id,
+ GValue *value,
+ GParamSpec *pspec)
+{
+ CkSession *self;
+
+ self = CK_SESSION (object);
+
+ switch (prop_id) {
+ case PROP_ACTIVE:
+ g_value_set_boolean (value, self->priv->active);
+ break;
+ case PROP_IS_LOCAL:
+ g_value_set_boolean (value, self->priv->is_local);
+ 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_SESSION_TYPE:
+ g_value_set_string (value, self->priv->session_type);
+ break;
+ case PROP_X11_DISPLAY:
+ g_value_set_string (value, self->priv->xdisplay);
+ break;
+ case PROP_DISPLAY_DEVICE:
+ g_value_set_string (value, self->priv->display_device);
+ break;
+ case PROP_USER:
+ g_value_set_uint (value, self->priv->uid);
+ break;
+ case PROP_HOST_NAME:
+ g_value_set_string (value, self->priv->host_name);
+ break;
+ default:
+ G_OBJECT_WARN_INVALID_PROPERTY_ID (object, prop_id, pspec);
+ break;
+ }
+}
+
+static void
+ck_session_class_init (CkSessionClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->get_property = ck_session_get_property;
+ object_class->set_property = ck_session_set_property;
+ object_class->finalize = ck_session_finalize;
+
+ signals [ACTIVE_CHANGED] =
+ g_signal_new ("active-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSessionClass, active_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__BOOLEAN,
+ G_TYPE_NONE,
+ 1, G_TYPE_BOOLEAN);
+ signals [ACTIVATE] =
+ g_signal_new ("activate",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSessionClass, activate),
+ NULL,
+ NULL,
+ ck_marshal_BOOLEAN__POINTER,
+ G_TYPE_BOOLEAN,
+ 1, G_TYPE_POINTER);
+ signals [LOCK] =
+ g_signal_new ("lock",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSessionClass, lock),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+ signals [UNLOCK] =
+ g_signal_new ("unlock",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkSessionClass, unlock),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__VOID,
+ G_TYPE_NONE,
+ 0);
+
+ g_object_class_install_property (object_class,
+ PROP_ACTIVE,
+ g_param_spec_boolean ("active",
+ NULL,
+ NULL,
+ FALSE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_IS_LOCAL,
+ g_param_spec_boolean ("is-local",
+ NULL,
+ NULL,
+ TRUE,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_ID,
+ g_param_spec_string ("id",
+ "id",
+ "id",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+ g_object_class_install_property (object_class,
+ PROP_COOKIE,
+ g_param_spec_string ("cookie",
+ "cookie",
+ "cookie",
+ NULL,
+ G_PARAM_READWRITE | G_PARAM_CONSTRUCT_ONLY));
+
+ g_object_class_install_property (object_class,
+ PROP_SESSION_TYPE,
+ g_param_spec_string ("session-type",
+ "session-type",
+ "session type",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_X11_DISPLAY,
+ g_param_spec_string ("x11-display",
+ "x11-display",
+ "X11 Display",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_DISPLAY_DEVICE,
+ g_param_spec_string ("display-device",
+ "display-device",
+ "Display device",
+ NULL,
+ G_PARAM_READWRITE));
+ g_object_class_install_property (object_class,
+ PROP_HOST_NAME,
+ g_param_spec_string ("host-name",
+ "host-name",
+ "Host name",
+ NULL,
+ G_PARAM_READWRITE));
+
+ g_object_class_install_property (object_class,
+ PROP_USER,
+ g_param_spec_uint ("user",
+ "User Id",
+ "User Id",
+ 0,
+ G_MAXINT,
+ 0,
+ G_PARAM_READWRITE));
+
+ g_type_class_add_private (klass, sizeof (CkSessionPrivate));
+
+ dbus_g_object_type_install_info (CK_TYPE_SESSION, &dbus_glib_ck_session_object_info);
+}
+
+static void
+ck_session_init (CkSession *session)
+{
+ session->priv = CK_SESSION_GET_PRIVATE (session);
+
+}
+
+static void
+ck_session_finalize (GObject *object)
+{
+ CkSession *session;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CK_IS_SESSION (object));
+
+ session = CK_SESSION (object);
+
+ g_return_if_fail (session->priv != NULL);
+
+ g_free (session->priv->id);
+ g_free (session->priv->seat_id);
+ g_free (session->priv->session_type);
+ g_free (session->priv->xdisplay);
+ g_free (session->priv->host_name);
+
+ G_OBJECT_CLASS (ck_session_parent_class)->finalize (object);
+}
+
+CkSession *
+ck_session_new (const char *ssid,
+ const char *cookie)
+{
+ GObject *object;
+ gboolean res;
+
+ object = g_object_new (CK_TYPE_SESSION,
+ "id", ssid,
+ "cookie", cookie,
+ NULL);
+ res = register_session (CK_SESSION (object));
+ if (! res) {
+ g_object_unref (object);
+ return NULL;
+ }
+
+ return CK_SESSION (object);
+}
+
+#define CK_TYPE_PARAMETER_STRUCT (dbus_g_type_get_struct ("GValueArray", \
+ G_TYPE_STRING, \
+ G_TYPE_VALUE, \
+ G_TYPE_INVALID))
+
+CkSession *
+ck_session_new_with_parameters (const char *ssid,
+ const char *cookie,
+ const GPtrArray *parameters)
+{
+ GObject *object;
+ gboolean res;
+ int i;
+
+ object = g_object_new (CK_TYPE_SESSION,
+ "id", ssid,
+ "cookie", cookie,
+ NULL);
+
+ for (i = 0; i < parameters->len; i++) {
+ GValue val_struct = { 0, };
+ const char *prop_name;
+ GValue *prop_val;
+
+ g_value_init (&val_struct, CK_TYPE_PARAMETER_STRUCT);
+ g_value_set_static_boxed (&val_struct, g_ptr_array_index (parameters, i));
+
+ dbus_g_type_struct_get (&val_struct,
+ 0, &prop_name,
+ 1, &prop_val,
+ G_MAXUINT);
+
+ g_object_set_property (object, prop_name, prop_val);
+ }
+
+ res = register_session (CK_SESSION (object));
+ if (! res) {
+ g_object_unref (object);
+ return NULL;
+ }
+
+ return CK_SESSION (object);
+}
diff --git a/src/ck-session.h b/src/ck-session.h
new file mode 100644
index 0000000..761edc9
--- /dev/null
+++ b/src/ck-session.h
@@ -0,0 +1,156 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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_SESSION_H
+#define __CK_SESSION_H
+
+#include <glib-object.h>
+#include <dbus/dbus-glib.h>
+
+G_BEGIN_DECLS
+
+#define CK_TYPE_SESSION (ck_session_get_type ())
+#define CK_SESSION(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_SESSION, CkSession))
+#define CK_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_SESSION, CkSessionClass))
+#define CK_IS_SESSION(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_SESSION))
+#define CK_IS_SESSION_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_SESSION))
+#define CK_SESSION_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_SESSION, CkSessionClass))
+
+typedef struct CkSessionPrivate CkSessionPrivate;
+
+typedef struct
+{
+ GObject parent;
+ CkSessionPrivate *priv;
+} CkSession;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ /* internal signals */
+ void (* activate) (CkSession *session,
+ DBusGMethodInvocation *context);
+
+ /* exported signals */
+ void (* lock) (CkSession *session);
+ void (* unlock) (CkSession *session);
+ void (* active_changed) (CkSession *session,
+ gboolean active);
+} CkSessionClass;
+
+typedef enum
+{
+ CK_SESSION_ERROR_GENERAL
+} CkSessionError;
+
+#define CK_SESSION_ERROR ck_session_error_quark ()
+
+GQuark ck_session_error_quark (void);
+GType ck_session_get_type (void);
+CkSession * ck_session_new (const char *ssid,
+ const char *cookie);
+CkSession * ck_session_new_with_parameters (const char *ssid,
+ const char *cookie,
+ const GPtrArray *parameters);
+
+gboolean ck_session_set_active (CkSession *session,
+ gboolean active,
+ GError **error);
+gboolean ck_session_set_is_local (CkSession *session,
+ gboolean is_local,
+ GError **error);
+gboolean ck_session_set_id (CkSession *session,
+ const char *ssid,
+ GError **error);
+gboolean ck_session_set_cookie (CkSession *session,
+ const char *cookie,
+ GError **error);
+gboolean ck_session_set_seat_id (CkSession *session,
+ const char *sid,
+ GError **error);
+gboolean ck_session_set_user (CkSession *session,
+ guint uid,
+ GError **error);
+gboolean ck_session_set_x11_display (CkSession *session,
+ const char *xdisplay,
+ GError **error);
+gboolean ck_session_set_display_device (CkSession *session,
+ const char *device,
+ GError **error);
+gboolean ck_session_set_host_name (CkSession *session,
+ const char *host_name,
+ GError **error);
+gboolean ck_session_set_session_type (CkSession *session,
+ const char *type,
+ GError **error);
+
+/* Exported methods */
+
+/* Authoritative properties */
+gboolean ck_session_get_id (CkSession *session,
+ char **ssid,
+ GError **error);
+gboolean ck_session_get_seat_id (CkSession *session,
+ char **sid,
+ GError **error);
+gboolean ck_session_is_active (CkSession *session,
+ gboolean *active,
+ GError **error);
+gboolean ck_session_is_local (CkSession *session,
+ gboolean *local,
+ GError **error);
+gboolean ck_session_get_user (CkSession *session,
+ guint *uid,
+ GError **error);
+gboolean ck_session_get_x11_display (CkSession *session,
+ char **display,
+ GError **error);
+gboolean ck_session_get_display_device (CkSession *session,
+ char **display,
+ GError **error);
+gboolean ck_session_get_session_type (CkSession *session,
+ char **type,
+ GError **error);
+gboolean ck_session_get_host_name (CkSession *session,
+ char **host_name,
+ GError **error);
+
+/* Non-authoritative properties */
+gboolean ck_session_get_idle (CkSession *session,
+ gboolean *idle,
+ GError **error);
+gboolean ck_session_set_idle (CkSession *session,
+ gboolean idle,
+ GError **error);
+
+/* Privileged actions */
+gboolean ck_session_activate (CkSession *session,
+ DBusGMethodInvocation *context);
+gboolean ck_session_lock (CkSession *session,
+ DBusGMethodInvocation *context);
+gboolean ck_session_unlock (CkSession *session,
+ DBusGMethodInvocation *context);
+
+
+G_END_DECLS
+
+#endif /* __CK_SESSION_H */
diff --git a/src/ck-session.xml b/src/ck-session.xml
new file mode 100644
index 0000000..668d1b2
--- /dev/null
+++ b/src/ck-session.xml
@@ -0,0 +1,49 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<node>
+
+ <interface name="org.freedesktop.ConsoleKit.Session">
+
+ <method name="GetId">
+ <arg name="ssid" direction="out" type="o"/>
+ </method>
+ <method name="GetSeatId">
+ <arg name="sid" direction="out" type="o"/>
+ </method>
+ <method name="GetSessionType">
+ <arg name="type" direction="out" type="s"/>
+ </method>
+ <method name="GetUser">
+ <arg name="uid" direction="out" type="i"/>
+ </method>
+ <method name="GetX11Display">
+ <arg name="display" direction="out" type="s"/>
+ </method>
+ <method name="GetDisplayDevice">
+ <arg name="display_device" direction="out" type="s"/>
+ </method>
+ <method name="GetHostName">
+ <arg name="host_name" direction="out" type="s"/>
+ </method>
+ <method name="IsActive">
+ <arg name="active" direction="out" type="b"/>
+ </method>
+ <method name="IsLocal">
+ <arg name="local" direction="out" type="b"/>
+ </method>
+
+ <method name="Activate">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ </method>
+ <method name="Lock">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ </method>
+ <method name="Unlock">
+ <annotation name="org.freedesktop.DBus.GLib.Async" value=""/>
+ </method>
+
+ <signal name="ActiveChanged"/>
+ <signal name="Lock"/>
+ <signal name="Unlock"/>
+
+ </interface>
+</node>
diff --git a/src/ck-vt-monitor.c b/src/ck-vt-monitor.c
new file mode 100644
index 0000000..eaaa9f4
--- /dev/null
+++ b/src/ck-vt-monitor.c
@@ -0,0 +1,360 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include <sys/ioctl.h>
+#include <sys/vt.h>
+
+#if defined (__linux__)
+#include <linux/tty.h>
+#include <linux/kd.h>
+#endif /* linux */
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib/gstdio.h>
+#include <glib-object.h>
+
+#define DBUS_API_SUBJECT_TO_CHANGE
+#include <dbus/dbus-glib.h>
+#include <dbus/dbus-glib-lowlevel.h>
+
+#include "ck-vt-monitor.h"
+#include "ck-marshal.h"
+#include "ck-debug.h"
+
+#define ERROR -1
+#define DEBUG_ENABLED 1
+
+#define CK_VT_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_VT_MONITOR, CkVtMonitorPrivate))
+
+struct CkVtMonitorPrivate
+{
+ int vfd;
+ GHashTable *vt_thread_hash;
+ guint active_num;
+};
+
+enum {
+ ACTIVE_CHANGED,
+ LAST_SIGNAL
+};
+
+enum {
+ PROP_0,
+};
+
+static guint signals [LAST_SIGNAL] = { 0, };
+
+static void ck_vt_monitor_class_init (CkVtMonitorClass *klass);
+static void ck_vt_monitor_init (CkVtMonitor *vt_monitor);
+static void ck_vt_monitor_finalize (GObject *object);
+
+G_DEFINE_TYPE (CkVtMonitor, ck_vt_monitor, G_TYPE_OBJECT)
+
+static void watch_vts (CkVtMonitor *vt_monitor);
+
+static gpointer vt_object = NULL;
+
+GQuark
+ck_vt_monitor_error_quark (void)
+{
+ static GQuark ret = 0;
+ if (ret == 0) {
+ ret = g_quark_from_static_string ("ck_vt_monitor_error");
+ }
+
+ return ret;
+}
+
+gboolean
+ck_vt_monitor_set_active (CkVtMonitor *vt_monitor,
+ guint32 num,
+ GError **error)
+{
+ gboolean ret;
+ int res;
+
+ g_return_val_if_fail (CK_IS_VT_MONITOR (vt_monitor), FALSE);
+
+ if (num == vt_monitor->priv->active_num) {
+ g_set_error (error,
+ CK_VT_MONITOR_ERROR,
+ CK_VT_MONITOR_ERROR_GENERAL,
+ _("Session is already active"));
+ return FALSE;
+ }
+
+ res = ioctl (vt_monitor->priv->vfd, VT_ACTIVATE, num);
+ if (res == 0) {
+ ret = TRUE;
+ } else {
+ g_set_error (error,
+ CK_VT_MONITOR_ERROR,
+ CK_VT_MONITOR_ERROR_GENERAL,
+ _("Unable to activate session"));
+ ret = FALSE;
+ }
+
+ return ret;
+}
+
+gboolean
+ck_vt_monitor_get_active (CkVtMonitor *vt_monitor,
+ guint32 *num,
+ GError **error)
+{
+ g_return_val_if_fail (CK_IS_VT_MONITOR (vt_monitor), FALSE);
+
+ if (num != NULL) {
+ *num = vt_monitor->priv->active_num;
+ }
+
+ return TRUE;
+}
+
+static void
+change_active_num (CkVtMonitor *vt_monitor,
+ guint num)
+{
+
+ if (vt_monitor->priv->active_num != num) {
+
+ vt_monitor->priv->active_num = num;
+
+ g_hash_table_remove (vt_monitor->priv->vt_thread_hash, GUINT_TO_POINTER (num));
+ watch_vts (vt_monitor);
+
+ g_signal_emit (vt_monitor, signals[ACTIVE_CHANGED], 0, num);
+ }
+}
+
+typedef struct {
+ gint32 num;
+ CkVtMonitor *vt_monitor;
+} ThreadData;
+
+static gboolean
+vt_activated (ThreadData *data)
+{
+ change_active_num (data->vt_monitor, data->num);
+
+ g_free (data);
+
+ return FALSE;
+}
+
+static void *
+vt_thread_start (ThreadData *data)
+{
+ CkVtMonitor *vt_monitor;
+ int ret;
+ gint32 num;
+
+ vt_monitor = data->vt_monitor;
+ num = data->num;
+
+ again:
+ ck_debug ("VT_WAITACTIVE for vt %d", num);
+ ret = ioctl (vt_monitor->priv->vfd, VT_WAITACTIVE, num);
+
+ ck_debug ("VT_WAITACTIVE returned %d", ret);
+
+ if (ret == ERROR) {
+
+ if (errno == EINTR) {
+ ck_debug ("Interrupted waiting for native console %d activation: %s",
+ num,
+ g_strerror (errno));
+ goto again;
+ } else {
+ ck_debug ("Error waiting for native console %d activation: %s",
+ num,
+ g_strerror (errno));
+
+ g_warning ("Error waiting for native console %d activation: %s",
+ num,
+ g_strerror (errno));
+ }
+
+ g_free (data);
+
+ if (vt_monitor->priv->vt_thread_hash != NULL) {
+ g_hash_table_remove (vt_monitor->priv->vt_thread_hash, GUINT_TO_POINTER (num));
+ }
+ } else {
+ g_idle_add ((GSourceFunc)vt_activated, data);
+ }
+
+ g_thread_exit (NULL);
+
+ return NULL;
+}
+
+static guint
+get_active_native (CkVtMonitor *vt_monitor)
+{
+ int ret;
+ struct vt_stat stat;
+
+ ret = ioctl (vt_monitor->priv->vfd, VT_GETSTATE, &stat);
+ if (ret == ERROR) {
+ perror ("ioctl VT_GETSTATE");
+ return -1;
+ }
+
+ {
+ int i;
+
+ ck_debug ("Current VT: tty%d", stat.v_active);
+ for (i = 1; i <= 16; i++) {
+ gboolean is_on;
+ is_on = stat.v_state & (1 << i);
+
+ ck_debug ("VT %d:%s", i, is_on ? "on" : "off");
+ }
+ }
+
+ return stat.v_active;
+}
+
+static void
+watch_vts (CkVtMonitor *vt_monitor)
+{
+ int i;
+ gint32 current_num;
+
+ current_num = vt_monitor->priv->active_num;
+
+ for (i = 1; i < MAX_NR_CONSOLES; i++) {
+ gpointer id;
+
+ /* don't wait on the active vc */
+ if (i == current_num) {
+ continue;
+ }
+
+ id = GINT_TO_POINTER (i);
+ if (g_hash_table_lookup (vt_monitor->priv->vt_thread_hash, id) == NULL) {
+ GThread *thread;
+ GError *error;
+ ThreadData *data;
+
+ data = g_new0 (ThreadData, 1);
+ data->num = i;
+ data->vt_monitor = vt_monitor;
+
+ ck_debug ("Creating thread for vt %d", i);
+
+ error = NULL;
+ thread = g_thread_create ((GThreadFunc)vt_thread_start, data, FALSE, &error);
+ if (thread == NULL) {
+ ck_debug ("Unable to create thread: %s", error->message);
+ g_error_free (error);
+ } else {
+ g_hash_table_insert (vt_monitor->priv->vt_thread_hash, id, thread);
+ }
+ }
+ }
+}
+
+static void
+ck_vt_monitor_class_init (CkVtMonitorClass *klass)
+{
+ GObjectClass *object_class = G_OBJECT_CLASS (klass);
+
+ object_class->finalize = ck_vt_monitor_finalize;
+
+ signals [ACTIVE_CHANGED] = g_signal_new ("active-changed",
+ G_TYPE_FROM_CLASS (object_class),
+ G_SIGNAL_RUN_LAST,
+ G_STRUCT_OFFSET (CkVtMonitorClass, active_changed),
+ NULL,
+ NULL,
+ g_cclosure_marshal_VOID__UINT,
+ G_TYPE_NONE,
+ 1, G_TYPE_UINT);
+
+ g_type_class_add_private (klass, sizeof (CkVtMonitorPrivate));
+}
+
+extern int getfd (void);
+
+static void
+ck_vt_monitor_init (CkVtMonitor *vt_monitor)
+{
+ int fd;
+
+ vt_monitor->priv = CK_VT_MONITOR_GET_PRIVATE (vt_monitor);
+
+ fd = getfd ();
+ if (fd == ERROR) {
+ ck_debug ("Unable to open console: %s", g_strerror (errno));
+ g_critical ("Unable to open console: %s", g_strerror (errno));
+ }
+
+ vt_monitor->priv->vfd = fd;
+ vt_monitor->priv->vt_thread_hash = g_hash_table_new (g_direct_hash, g_direct_equal);
+
+ vt_monitor->priv->active_num = get_active_native (vt_monitor);
+
+ watch_vts (vt_monitor);
+}
+
+static void
+ck_vt_monitor_finalize (GObject *object)
+{
+ CkVtMonitor *vt_monitor;
+
+ g_return_if_fail (object != NULL);
+ g_return_if_fail (CK_IS_VT_MONITOR (object));
+
+ vt_monitor = CK_VT_MONITOR (object);
+
+ g_return_if_fail (vt_monitor->priv != NULL);
+
+ g_hash_table_destroy (vt_monitor->priv->vt_thread_hash);
+
+ close (vt_monitor->priv->vfd);
+
+ G_OBJECT_CLASS (ck_vt_monitor_parent_class)->finalize (object);
+}
+
+CkVtMonitor *
+ck_vt_monitor_new (void)
+{
+ if (vt_object != NULL) {
+ g_object_ref (vt_object);
+ } else {
+ vt_object = g_object_new (CK_TYPE_VT_MONITOR, NULL);
+
+ g_object_add_weak_pointer (vt_object,
+ (gpointer *) &vt_object);
+ }
+
+ return CK_VT_MONITOR (vt_object);
+}
diff --git a/src/ck-vt-monitor.h b/src/ck-vt-monitor.h
new file mode 100644
index 0000000..621be80
--- /dev/null
+++ b/src/ck-vt-monitor.h
@@ -0,0 +1,71 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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_VT_MONITOR_H
+#define __CK_VT_MONITOR_H
+
+#include <glib-object.h>
+
+G_BEGIN_DECLS
+
+#define CK_TYPE_VT_MONITOR (ck_vt_monitor_get_type ())
+#define CK_VT_MONITOR(o) (G_TYPE_CHECK_INSTANCE_CAST ((o), CK_TYPE_VT_MONITOR, CkVtMonitor))
+#define CK_VT_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_CAST((k), CK_TYPE_VT_MONITOR, CkVtMonitorClass))
+#define CK_IS_VT_MONITOR(o) (G_TYPE_CHECK_INSTANCE_TYPE ((o), CK_TYPE_VT_MONITOR))
+#define CK_IS_VT_MONITOR_CLASS(k) (G_TYPE_CHECK_CLASS_TYPE ((k), CK_TYPE_VT_MONITOR))
+#define CK_VT_MONITOR_GET_CLASS(o) (G_TYPE_INSTANCE_GET_CLASS ((o), CK_TYPE_VT_MONITOR, CkVtMonitorClass))
+
+typedef struct CkVtMonitorPrivate CkVtMonitorPrivate;
+
+typedef struct
+{
+ GObject parent;
+ CkVtMonitorPrivate *priv;
+} CkVtMonitor;
+
+typedef struct
+{
+ GObjectClass parent_class;
+
+ void (* active_changed) (CkVtMonitor *vt_monitor,
+ guint num);
+} CkVtMonitorClass;
+
+typedef enum
+{
+ CK_VT_MONITOR_ERROR_GENERAL
+} CkVtMonitorError;
+
+#define CK_VT_MONITOR_ERROR ck_vt_monitor_error_quark ()
+
+GQuark ck_vt_monitor_error_quark (void);
+GType ck_vt_monitor_get_type (void);
+CkVtMonitor * ck_vt_monitor_new (void);
+
+gboolean ck_vt_monitor_set_active (CkVtMonitor *vt_monitor,
+ guint32 num,
+ GError **error);
+gboolean ck_vt_monitor_get_active (CkVtMonitor *vt_monitor,
+ guint32 *num,
+ GError **error);
+
+G_END_DECLS
+
+#endif /* __CK_VT_MONITOR_H */
diff --git a/src/getfd.c b/src/getfd.c
new file mode 100644
index 0000000..9dbe15c
--- /dev/null
+++ b/src/getfd.c
@@ -0,0 +1,52 @@
+#include <stdio.h>
+#include <fcntl.h>
+#include <errno.h>
+#include <linux/kd.h>
+#include <sys/ioctl.h>
+
+/*
+ * getfd.c
+ *
+ * Get an fd for use with kbd/console ioctls.
+ * We try several things because opening /dev/console will fail
+ * if someone else used X (which does a chown on /dev/console).
+ */
+
+static int
+is_a_console(int fd) {
+ char arg;
+
+ arg = 0;
+ return (ioctl(fd, KDGKBTYPE, &arg) == 0
+ && ((arg == KB_101) || (arg == KB_84)));
+}
+
+static int
+open_a_console(char *fnam) {
+ int fd;
+
+ fd = open(fnam, O_RDONLY);
+ if (fd < 0 && errno == EACCES)
+ fd = open(fnam, O_WRONLY);
+ if (fd < 0 || ! is_a_console(fd))
+ return -1;
+ return fd;
+}
+
+int getfd() {
+ int fd;
+
+ fd = open_a_console("/dev/tty");
+ if (fd >= 0)
+ return fd;
+
+ fd = open_a_console("/dev/console");
+ if (fd >= 0)
+ return fd;
+
+ for (fd = 0; fd < 3; fd++)
+ if (is_a_console(fd))
+ return fd;
+
+ return -1;
+}
diff --git a/src/main.c b/src/main.c
new file mode 100644
index 0000000..683d394
--- /dev/null
+++ b/src/main.c
@@ -0,0 +1,141 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <unistd.h>
+#include <errno.h>
+
+#include <glib.h>
+#include <glib/gi18n.h>
+#include <glib-object.h>
+
+#include "ck-manager.h"
+#include "ck-debug.h"
+
+#define CK_DBUS_NAME "org.freedesktop.ConsoleKit"
+
+static gboolean
+timed_exit_cb (GMainLoop *loop)
+{
+ g_main_loop_quit (loop);
+ return FALSE;
+}
+
+int
+main (int argc,
+ char **argv)
+{
+ GMainLoop *loop;
+ CkManager *manager;
+ GOptionContext *context;
+ GError *error;
+ DBusGProxy *bus_proxy;
+ DBusGConnection *connection;
+ gboolean res;
+ guint result;
+
+ static gboolean debug = FALSE;
+ static gboolean no_daemon = FALSE;
+ static gboolean do_timed_exit = FALSE;
+ static GOptionEntry entries [] = {
+ { "debug", 0, 0, G_OPTION_ARG_NONE, &debug, N_("Enable debugging code"), NULL },
+ { "no-daemon", 0, 0, G_OPTION_ARG_NONE, &no_daemon, N_("Don't become a daemon"), NULL },
+ { NULL }
+ };
+
+
+ g_type_init ();
+ g_thread_init (NULL);
+ dbus_g_thread_init ();
+
+ context = g_option_context_new (_("Console kit daemon"));
+ g_option_context_add_main_entries (context, entries, NULL);
+ g_option_context_parse (context, &argc, &argv, NULL);
+ g_option_context_free (context);
+
+ error = NULL;
+ connection = dbus_g_bus_get (DBUS_BUS_SYSTEM, &error);
+ if (connection == NULL) {
+ g_warning ("Couldn't connect to system bus: %s", error->message);
+ g_error_free (error);
+ exit (1);
+ }
+
+ bus_proxy = dbus_g_proxy_new_for_name (connection,
+ DBUS_SERVICE_DBUS,
+ DBUS_PATH_DBUS,
+ DBUS_INTERFACE_DBUS);
+
+ error = NULL;
+ res = dbus_g_proxy_call (bus_proxy,
+ "RequestName",
+ &error,
+ G_TYPE_STRING, CK_DBUS_NAME,
+ G_TYPE_UINT, 0,
+ G_TYPE_INVALID,
+ G_TYPE_UINT, &result,
+ G_TYPE_INVALID);
+ if (! res) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", CK_DBUS_NAME, error->message);
+ g_error_free (error);
+ }
+ exit (1);
+ }
+
+ if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) {
+ if (error != NULL) {
+ g_warning ("Failed to acquire %s: %s", CK_DBUS_NAME, error->message);
+ g_error_free (error);
+ }
+ exit (1);
+ }
+
+ /* debug to a file if in deamon mode */
+ ck_debug_init (debug, ! no_daemon);
+ ck_debug ("initializing console-kit-daemon %s", VERSION);
+
+ /* Don't close stdout and stderr for now */
+ if (! no_daemon && daemon (0, 1)) {
+ g_error ("Could not daemonize: %s", g_strerror (errno));
+ }
+
+ manager = ck_manager_new ();
+
+ if (manager == NULL) {
+ exit (1);
+ }
+
+ loop = g_main_loop_new (NULL, FALSE);
+
+ if (do_timed_exit) {
+ g_timeout_add (1000 * 60, (GSourceFunc) timed_exit_cb, loop);
+ }
+
+ g_main_loop_run (loop);
+
+ g_object_unref (manager);
+
+ return 0;
+}
+
diff --git a/src/proc-linux.c b/src/proc-linux.c
new file mode 100644
index 0000000..997825e
--- /dev/null
+++ b/src/proc-linux.c
@@ -0,0 +1,473 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 <stdlib.h>
+#include <stdio.h>
+#include <fcntl.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+
+#include "proc.h"
+
+struct _proc_t
+{
+ int pid;
+ int ppid; /* stat,status pid of parent process */
+ char state; /* stat,status single-char code for process state (S=sleeping) */
+ char cmd[16]; /* stat,status basename of executable file in call to exec(2) */
+ unsigned long long utime; /* stat user-mode CPU time accumulated by process */
+ unsigned long long stime; /* stat kernel-mode CPU time accumulated by process */
+ unsigned long long cutime; /* stat cumulative utime of process and reaped children */
+ unsigned long long cstime; /* stat cumulative stime of process and reaped children */
+ unsigned long long start_time; /* stat start time of process -- seconds since 1-1-70 */
+ unsigned long start_code; /* stat address of beginning of code segment */
+ unsigned long end_code; /* stat address of end of code segment */
+ unsigned long start_stack; /* stat address of the bottom of stack for the process */
+ unsigned long kstk_esp; /* stat kernel stack pointer */
+ unsigned long kstk_eip; /* stat kernel instruction pointer */
+ unsigned long wchan; /* stat (special) address of kernel wait channel proc is sleeping in */
+ long priority; /* stat kernel scheduling priority */
+ long nice; /* stat standard unix nice level of process */
+ long rss; /* stat resident set size from /proc/#/stat (pages) */
+ long alarm; /* stat ? */
+ unsigned long rtprio; /* stat real-time priority */
+ unsigned long sched; /* stat scheduling class */
+ unsigned long vsize; /* stat number of pages of virtual memory ... */
+ unsigned long rss_rlim; /* stat resident set size limit? */
+ unsigned long flags; /* stat kernel flags for the process */
+ unsigned long min_flt; /* stat number of minor page faults since process start */
+ unsigned long maj_flt; /* stat number of major page faults since process start */
+ unsigned long cmin_flt; /* stat cumulative min_flt of process and child processes */
+ unsigned long cmaj_flt; /* stat cumulative maj_flt of process and child processes */
+ int pgrp; /* stat process group id */
+ int session; /* stat session id */
+ int nlwp; /* stat number of threads, or 0 if no clue */
+ int tty; /* stat full device number of controlling terminal */
+ int tpgid; /* stat terminal process group id */
+ int exit_signal; /* stat might not be SIGCHLD */
+ int processor; /* stat current (or most recent?) CPU */
+};
+
+/* adapted from procps */
+#define MAJOR_OF(d) ( ((unsigned)(d)>>8u) & 0xfffu )
+#define MINOR_OF(d) ( ((unsigned)(d)&0xffu) | (((unsigned)(d)&0xfff00000u)>>12u) )
+
+typedef struct tty_map_node {
+ struct tty_map_node *next;
+ guint major_number;
+ guint minor_first;
+ guint minor_last;
+ char name[16];
+ char devfs_type;
+} tty_map_node;
+
+static tty_map_node *tty_map = NULL;
+
+/* adapted from procps */
+/* Load /proc/tty/drivers for device name mapping use. */
+static void
+load_drivers (void)
+{
+ char buf[10000];
+ char *p;
+ int fd;
+ int bytes;
+
+ fd = open ("/proc/tty/drivers", O_RDONLY);
+ if (fd == -1) {
+ goto fail;
+ }
+
+ bytes = read (fd, buf, sizeof (buf) - 1);
+ if (bytes == -1) {
+ goto fail;
+ }
+
+ buf[bytes] = '\0';
+ p = buf;
+ while ((p = strstr (p, " /dev/"))){
+ tty_map_node *tmn;
+ int len;
+ char *end;
+
+ p += 6;
+ end = strchr (p, ' ');
+ if (! end) {
+ continue;
+ }
+ len = end - p;
+ tmn = calloc (1, sizeof (tty_map_node));
+ tmn->next = tty_map;
+ tty_map = tmn;
+ /* if we have a devfs type name such as /dev/tts/%d then strip the %d but
+ keep a flag. */
+ if (len >= 3 && !strncmp (end - 2, "%d", 2)) {
+ len -= 2;
+ tmn->devfs_type = 1;
+ }
+ strncpy (tmn->name, p, len);
+ p = end; /* set p to point past the %d as well if there is one */
+ while (*p == ' ') {
+ p++;
+ }
+
+ tmn->major_number = atoi (p);
+ p += strspn (p, "0123456789");
+ while (*p == ' ') {
+ p++;
+ }
+ switch (sscanf (p, "%u-%u", &tmn->minor_first, &tmn->minor_last)) {
+ default:
+ /* Can't finish parsing this line so we remove it from the list */
+ tty_map = tty_map->next;
+ free (tmn);
+ break;
+ case 1:
+ tmn->minor_last = tmn->minor_first;
+ break;
+ case 2:
+ break;
+ }
+ }
+ fail:
+ if (fd != -1) {
+ close (fd);
+ }
+ if(! tty_map) {
+ tty_map = (tty_map_node *)-1;
+ }
+}
+
+/* adapted from procps */
+/* Try to guess the device name from /proc/tty/drivers info. */
+static char *
+driver_name (guint maj,
+ guint min)
+{
+ struct stat sbuf;
+ tty_map_node *tmn;
+ char *tty;
+
+ if (! tty_map) {
+ load_drivers ();
+ }
+ if (tty_map == (tty_map_node *) - 1) {
+ return 0;
+ }
+
+ tmn = tty_map;
+ for (;;) {
+ if (! tmn) {
+ return 0;
+ }
+ if (tmn->major_number == maj && tmn->minor_first <= min && tmn->minor_last >= min) {
+ break;
+ }
+ tmn = tmn->next;
+ }
+
+ tty = g_strdup_printf ("/dev/%s%d", tmn->name, min); /* like "/dev/ttyZZ255" */
+ if (stat (tty, &sbuf) < 0){
+ g_free (tty);
+
+ if (tmn->devfs_type) {
+ return NULL;
+ }
+
+ tty = g_strdup_printf ("/dev/%s", tmn->name); /* like "/dev/ttyZZ255" */
+
+ if (stat (tty, &sbuf) < 0) {
+ g_free (tty);
+ return NULL;
+ }
+ }
+
+ if (min != MINOR_OF (sbuf.st_rdev)) {
+ g_free (tty);
+ return NULL;
+ }
+
+ if (maj != MAJOR_OF (sbuf.st_rdev)) {
+ g_free (tty);
+ return NULL;
+ }
+
+ return tty;
+}
+
+/* adapted from procps */
+static char *
+link_name (guint maj,
+ guint min,
+ int pid,
+ const char *name)
+{
+ struct stat sbuf;
+ char *path;
+ char *tty;
+
+ path = g_strdup_printf ("/proc/%d/%s", pid, name);
+ tty = g_file_read_link (path, NULL);
+ g_free (path);
+
+ if (tty == NULL) {
+ goto out;
+ }
+
+ if (stat (tty, &sbuf) < 0) {
+ g_free (tty);
+ tty = NULL;
+ goto out;
+ }
+
+ if (min != MINOR_OF (sbuf.st_rdev)) {
+ g_free (tty);
+ tty = NULL;
+ goto out;
+
+ }
+ if (maj != MAJOR_OF (sbuf.st_rdev)) {
+ g_free (tty);
+ tty = NULL;
+ goto out;
+ }
+
+ out:
+ return tty;
+}
+
+char *
+proc_get_cmd (proc_t *stat)
+{
+ return g_strdup (stat->cmd);
+}
+
+/* adapted from procps */
+char *
+proc_get_tty (proc_t *stat)
+{
+ guint dev;
+ char *tty;
+ guint dev_maj;
+ guint dev_min;
+ pid_t pid;
+
+ pid = stat->pid;
+ dev = stat->tty;
+
+ if (dev == 0u) {
+ return NULL;
+ }
+
+ dev_maj = MAJOR_OF (dev);
+ dev_min = MINOR_OF (dev);
+
+ tty = link_name (dev_maj, dev_min, pid, "tty");
+ if (tty != NULL) {
+ goto out;
+ }
+
+ tty = driver_name (dev_maj, dev_min);
+ if (tty != NULL) {
+ goto out;
+ }
+
+ tty = link_name (dev_maj, dev_min, pid, "fd/2");
+ if (tty != NULL) {
+ goto out;
+ }
+
+ tty = link_name (dev_maj, dev_min, pid, "fd/255");
+ if (tty != NULL) {
+ goto out;
+ }
+
+ out:
+
+ return tty;
+}
+
+#define KLF "l"
+/* adapted from procps */
+static void
+stat2proc (const char *S,
+ proc_t *P)
+{
+ unsigned num;
+ char * tmp;
+
+ /* fill in default values for older kernels */
+ P->processor = 0;
+ P->rtprio = -1;
+ P->sched = -1;
+ P->nlwp = 0;
+
+ S = strchr (S, '(') + 1;
+ tmp = strrchr (S, ')');
+ num = tmp - S;
+ if (G_UNLIKELY (num >= sizeof P->cmd)) {
+ num = sizeof P->cmd - 1;
+ }
+
+ memcpy (P->cmd, S, num);
+ P->cmd[num] = '\0';
+ S = tmp + 2; /* skip ") " */
+
+ num = sscanf (S,
+ "%c "
+ "%d %d %d %d %d "
+ "%lu %lu %lu %lu %lu "
+ "%Lu %Lu %Lu %Lu " /* utime stime cutime cstime */
+ "%ld %ld "
+ "%d "
+ "%ld "
+ "%Lu " /* start_time */
+ "%lu "
+ "%ld "
+ "%lu %"KLF"u %"KLF"u %"KLF"u %"KLF"u %"KLF"u "
+ "%*s %*s %*s %*s " /* discard, no RT signals & Linux 2.1 used hex */
+ "%"KLF"u %*lu %*lu "
+ "%d %d "
+ "%lu %lu",
+ &P->state,
+ &P->ppid, &P->pgrp, &P->session, &P->tty, &P->tpgid,
+ &P->flags, &P->min_flt, &P->cmin_flt, &P->maj_flt, &P->cmaj_flt,
+ &P->utime, &P->stime, &P->cutime, &P->cstime,
+ &P->priority, &P->nice,
+ &P->nlwp,
+ &P->alarm,
+ &P->start_time,
+ &P->vsize,
+ &P->rss,
+ &P->rss_rlim, &P->start_code, &P->end_code, &P->start_stack, &P->kstk_esp, &P->kstk_eip,
+ /* P->signal, P->blocked, P->sigignore, P->sigcatch, */ /* can't use */
+ &P->wchan, /* &P->nswap, &P->cnswap, */ /* nswap and cnswap dead for 2.4.xx and up */
+ /* -- Linux 2.0.35 ends here -- */
+ &P->exit_signal, &P->processor, /* 2.2.1 ends with "exit_signal" */
+ /* -- Linux 2.2.8 to 2.5.17 end here -- */
+ &P->rtprio, &P->sched /* both added to 2.5.18 */
+ );
+
+ if (!P->nlwp){
+ P->nlwp = 1;
+ }
+}
+
+gboolean
+proc_stat_pid (pid_t pid,
+ proc_t **stat)
+{
+ char *path;
+ char *contents;
+ gsize length;
+ gboolean res;
+ GError *error;
+ proc_t *proc;
+
+ if (stat == NULL) {
+ return FALSE;
+ }
+
+ path = g_strdup_printf ("/proc/%d/stat", pid);
+
+ contents = NULL;
+ res = g_file_get_contents (path,
+ &contents,
+ &length,
+ &error);
+ if (res) {
+ proc = g_new0 (proc_t, 1);
+ proc->pid = pid;
+ stat2proc (contents, proc);
+ *stat = proc;
+ }
+
+ g_free (contents);
+ g_free (path);
+
+ return res;
+}
+
+void
+proc_free (proc_t *stat)
+{
+ g_free (stat);
+}
+
+char *
+proc_get_env (pid_t pid,
+ const char *var)
+{
+ char *path;
+ gboolean res;
+ char *contents;
+ char *val;
+ gsize length;
+ GError *error;
+ int i;
+ char *prefix;
+ int prefix_len;
+ gboolean last_was_null;
+
+ val = NULL;
+ contents = NULL;
+ prefix = NULL;
+
+ path = g_strdup_printf ("/proc/%u/environ", (guint)pid);
+
+ error = NULL;
+ res = g_file_get_contents (path,
+ &contents,
+ &length,
+ &error);
+ if (! res) {
+ g_warning ("Couldn't read %s: %s", path, error->message);
+ g_error_free (error);
+ goto out;
+ }
+
+
+ prefix = g_strdup_printf ("%s=", var);
+ prefix_len = strlen (prefix);
+
+ /* FIXME: make more robust */
+ last_was_null = TRUE;
+ for (i = 0; i < length; i++) {
+ if (contents[i] == '\0') {
+ last_was_null = TRUE;
+ continue;
+ }
+ if (last_was_null && g_str_has_prefix (contents + i, prefix)) {
+ val = g_strdup (contents + i + prefix_len);
+ break;
+ }
+ }
+
+ out:
+ g_free (prefix);
+ g_free (contents);
+ g_free (path);
+
+ return val;
+}
diff --git a/src/proc.h b/src/proc.h
new file mode 100644
index 0000000..fb7ee94
--- /dev/null
+++ b/src/proc.h
@@ -0,0 +1,41 @@
+/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
+ *
+ * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu>
+ *
+ * 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 __PROC_H
+#define __PROC_H
+
+#include <glib.h>
+
+G_BEGIN_DECLS
+
+typedef struct _proc_t proc_t;
+
+gboolean proc_stat_pid (pid_t pid,
+ proc_t **stat);
+char *proc_get_tty (proc_t *stat);
+char *proc_get_cmd (proc_t *stat);
+void proc_free (proc_t *stat);
+
+char *proc_get_env (pid_t pid,
+ const char *var);
+
+G_END_DECLS
+
+#endif /* __PROC_H */
diff --git a/src/test-session b/src/test-session
new file mode 100755
index 0000000..d77c5f1
--- /dev/null
+++ b/src/test-session
@@ -0,0 +1,51 @@
+#!/usr/bin/env python
+
+import os
+import gobject
+import dbus
+
+def activate_reply (res):
+ print "session activated"
+
+def activate_error (e):
+ print str (e)
+
+
+bus = dbus.SystemBus ()
+
+manager_obj = bus.get_object ('org.freedesktop.ConsoleKit', '/org/freedesktop/ConsoleKit/Manager')
+
+manager = dbus.Interface (manager_obj, 'org.freedesktop.ConsoleKit.Manager')
+
+params = dbus.Array ([], signature = "sv")
+params.append (("user", dbus.Variant (730)))
+params.append (("session-type", dbus.Variant ("gnome-session")))
+params.append (("x11-display", dbus.Variant (":0.0")))
+params.append (("display-device", dbus.Variant ("/dev/tty8")))
+
+cookie = manager.OpenSessionWithParameters (params)
+os.environ['XDG_SESSION_COOKIE'] = cookie
+
+seats = manager.GetSeats ()
+for sid in seats:
+ seat_obj = bus.get_object ('org.freedesktop.ConsoleKit', sid)
+ seat = dbus.Interface (seat_obj, 'org.freedesktop.ConsoleKit.Seat')
+ sessions = seat.GetSessions ()
+ for ssid in sessions:
+ session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid)
+ session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session')
+ uid = session.GetUser ()
+
+current_session = manager.GetSession (cookie)
+print "Current session: %s" % current_session
+
+session_obj = bus.get_object ('org.freedesktop.ConsoleKit', ssid)
+session = dbus.Interface (session_obj, 'org.freedesktop.ConsoleKit.Session')
+
+session.Activate (reply_handler = activate_reply, error_handler = activate_error)
+
+mainloop = gobject.MainLoop ()
+
+gobject.timeout_add (30000, mainloop.quit)
+
+mainloop.run()
diff --git a/src/valgrind.sh b/src/valgrind.sh
new file mode 100755
index 0000000..a11a1f0
--- /dev/null
+++ b/src/valgrind.sh
@@ -0,0 +1,12 @@
+#!/bin/sh
+
+export G_DEBUG=gc-friendly
+export G_SLICE=always-malloc
+
+#valgrind --tool=massif --depth=5 --alloc-fn=g_malloc \
+# --alloc-fn=g_realloc --alloc-fn=g_try_malloc \
+# --alloc-fn=g_malloc0 --alloc-fn=g_mem_chunk_alloc \
+# console-manager --no-daemon
+
+valgrind --tool=memcheck --leak-check=full --show-reachable=yes \
+ console-manager --no-daemon