diff options
author | William Jon McCann <mccannwj@acsnb12.pha.jhu.edu> | 2006-10-25 14:38:19 -0400 |
---|---|---|
committer | William Jon McCann <mccannwj@acsnb12.pha.jhu.edu> | 2006-10-25 14:38:19 -0400 |
commit | a08530e838218b3c5859550058e78b8f1abee434 (patch) | |
tree | c54037c29cd86ebbecf6d9e10eb86da1ba657c9e /src |
Initial import
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 90 | ||||
-rw-r--r-- | src/Makefile.in | 724 | ||||
-rw-r--r-- | src/ck-debug.c | 153 | ||||
-rw-r--r-- | src/ck-debug.h | 72 | ||||
-rw-r--r-- | src/ck-manager-glue.h | 223 | ||||
-rw-r--r-- | src/ck-manager.c | 1017 | ||||
-rw-r--r-- | src/ck-manager.h | 97 | ||||
-rw-r--r-- | src/ck-manager.xml | 48 | ||||
-rw-r--r-- | src/ck-marshal.c | 126 | ||||
-rw-r--r-- | src/ck-marshal.h | 28 | ||||
-rw-r--r-- | src/ck-marshal.list | 2 | ||||
-rw-r--r-- | src/ck-seat-glue.h | 167 | ||||
-rw-r--r-- | src/ck-seat.c | 724 | ||||
-rw-r--r-- | src/ck-seat.h | 111 | ||||
-rw-r--r-- | src/ck-seat.xml | 27 | ||||
-rw-r--r-- | src/ck-session-glue.h | 135 | ||||
-rw-r--r-- | src/ck-session.c | 744 | ||||
-rw-r--r-- | src/ck-session.h | 156 | ||||
-rw-r--r-- | src/ck-session.xml | 49 | ||||
-rw-r--r-- | src/ck-vt-monitor.c | 360 | ||||
-rw-r--r-- | src/ck-vt-monitor.h | 71 | ||||
-rw-r--r-- | src/getfd.c | 52 | ||||
-rw-r--r-- | src/main.c | 141 | ||||
-rw-r--r-- | src/proc-linux.c | 473 | ||||
-rw-r--r-- | src/proc.h | 41 | ||||
-rwxr-xr-x | src/test-session | 51 | ||||
-rwxr-xr-x | src/valgrind.sh | 12 |
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 |