diff options
author | Michael Biebl <biebl@debian.org> | 2009-07-14 17:40:56 +0200 |
---|---|---|
committer | Michael Biebl <biebl@debian.org> | 2009-07-14 17:40:56 +0200 |
commit | 517ae9bab3e1aeda58ef4f042fa1346d411a9a4c (patch) | |
tree | 450b1355a1f8138ea9a031bd0653f2c1da9e18d7 /src | |
parent | b4c56fb4b5f0c496b544080c5dd38d3cf93c10e8 (diff) | |
download | consolekit-517ae9bab3e1aeda58ef4f042fa1346d411a9a4c.tar.gz |
Imported Upstream version 0.2.3upstream/0.2.3
Diffstat (limited to 'src')
-rw-r--r-- | src/Makefile.am | 53 | ||||
-rw-r--r-- | src/Makefile.in | 140 | ||||
-rw-r--r-- | src/ck-file-monitor-inotify.c | 2 | ||||
-rw-r--r-- | src/ck-job.c | 23 | ||||
-rw-r--r-- | src/ck-log.c | 8 | ||||
-rw-r--r-- | src/ck-manager-glue.h | 10 | ||||
-rw-r--r-- | src/ck-manager.c | 116 | ||||
-rw-r--r-- | src/ck-seat-glue.h | 17 | ||||
-rw-r--r-- | src/ck-seat.c | 234 | ||||
-rw-r--r-- | src/ck-seat.h | 36 | ||||
-rw-r--r-- | src/ck-seat.xml | 9 | ||||
-rw-r--r-- | src/ck-session-glue.h | 6 | ||||
-rw-r--r-- | src/ck-session.c | 8 | ||||
-rw-r--r-- | src/ck-sysdeps-freebsd.c | 423 | ||||
-rw-r--r-- | src/ck-sysdeps-linux.c (renamed from src/proc-linux.c) | 163 | ||||
-rw-r--r-- | src/ck-sysdeps-solaris.c | 469 | ||||
-rw-r--r-- | src/ck-sysdeps-unix.c | 305 | ||||
-rw-r--r-- | src/ck-sysdeps.h | 75 | ||||
-rw-r--r-- | src/ck-vt-monitor.c | 94 | ||||
-rw-r--r-- | src/getfd.c | 75 | ||||
-rw-r--r-- | src/main.c | 18 | ||||
-rw-r--r-- | src/proc.h | 48 | ||||
-rw-r--r-- | src/test-tty-idle-monitor.c | 39 | ||||
-rw-r--r-- | src/test-vt-monitor.c | 95 |
24 files changed, 2115 insertions, 351 deletions
diff --git a/src/Makefile.am b/src/Makefile.am index 0977591..3f142a3 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -23,6 +23,38 @@ INCLUDES = \ $(DBUS_CFLAGS) \ $(NULL) +noinst_LTLIBRARIES = \ + libck.la \ + $(NULL) + +libck_la_SOURCES = \ + ck-sysdeps.h \ + ck-sysdeps-unix.c \ + $(NULL) + +if CK_COMPILE_LINUX +libck_la_SOURCES += \ + ck-sysdeps-linux.c \ + $(NULL) +endif +if CK_COMPILE_SOLARIS +libck_la_SOURCES += \ + ck-sysdeps-solaris.c \ + $(NULL) +endif +if CK_COMPILE_FREEBSD +libck_la_SOURCES += \ + ck-sysdeps-freebsd.c \ + $(NULL) +libck_la_LIBADD = $(KVM_LIBS) +endif + +EXTRA_libck_la_SOURCES = \ + ck-sysdeps-linux.c \ + ck-sysdeps-solaris.c \ + ck-sysdeps-freebsd.c \ + $(NULL) + sbin_PROGRAMS = \ console-kit-daemon \ $(NULL) @@ -49,10 +81,6 @@ ck-marshal.c: ck-marshal.list 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 \ @@ -70,9 +98,6 @@ console_kit_daemon_SOURCES = \ ck-session.c \ ck-log.h \ ck-log.c \ - getfd.c \ - proc.h \ - $(PLATFORM_SOURCES) \ $(BUILT_SOURCES) \ $(NULL) @@ -91,10 +116,23 @@ EXTRA_console_kit_daemon_SOURCES = \ console_kit_daemon_LDADD = \ $(CONSOLE_KIT_LIBS) \ + libck.la \ $(NULL) noinst_PROGRAMS = \ test-tty-idle-monitor \ + test-vt-monitor \ + $(NULL) + +test_vt_monitor_SOURCES = \ + ck-vt-monitor.h \ + ck-vt-monitor.c \ + test-vt-monitor.c \ + $(NULL) + +test_vt_monitor_LDADD = \ + $(CONSOLE_KIT_LIBS) \ + libck.la \ $(NULL) test_tty_idle_monitor_SOURCES = \ @@ -107,6 +145,7 @@ test_tty_idle_monitor_SOURCES = \ test_tty_idle_monitor_LDADD = \ $(CONSOLE_KIT_LIBS) \ + libck.la \ $(NULL) EXTRA_DIST = \ diff --git a/src/Makefile.in b/src/Makefile.in index 336a570..2e660af 100644 --- a/src/Makefile.in +++ b/src/Makefile.in @@ -14,6 +14,7 @@ @SET_MAKE@ + srcdir = @srcdir@ top_srcdir = @top_srcdir@ VPATH = @srcdir@ @@ -36,8 +37,21 @@ PRE_UNINSTALL = : POST_UNINSTALL = : build_triplet = @build@ host_triplet = @host@ +@CK_COMPILE_LINUX_TRUE@am__append_1 = \ +@CK_COMPILE_LINUX_TRUE@ ck-sysdeps-linux.c \ +@CK_COMPILE_LINUX_TRUE@ $(NULL) + +@CK_COMPILE_SOLARIS_TRUE@am__append_2 = \ +@CK_COMPILE_SOLARIS_TRUE@ ck-sysdeps-solaris.c \ +@CK_COMPILE_SOLARIS_TRUE@ $(NULL) + +@CK_COMPILE_FREEBSD_TRUE@am__append_3 = \ +@CK_COMPILE_FREEBSD_TRUE@ ck-sysdeps-freebsd.c \ +@CK_COMPILE_FREEBSD_TRUE@ $(NULL) + sbin_PROGRAMS = console-kit-daemon$(EXEEXT) $(am__EXEEXT_1) -noinst_PROGRAMS = test-tty-idle-monitor$(EXEEXT) $(am__EXEEXT_1) +noinst_PROGRAMS = test-tty-idle-monitor$(EXEEXT) \ + test-vt-monitor$(EXEEXT) $(am__EXEEXT_1) subdir = src DIST_COMMON = $(srcdir)/Makefile.am $(srcdir)/Makefile.in ACLOCAL_M4 = $(top_srcdir)/aclocal.m4 @@ -48,6 +62,22 @@ am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ mkinstalldirs = $(install_sh) -d CONFIG_HEADER = $(top_builddir)/config.h CONFIG_CLEAN_FILES = +LTLIBRARIES = $(noinst_LTLIBRARIES) +am__DEPENDENCIES_1 = +@CK_COMPILE_FREEBSD_TRUE@libck_la_DEPENDENCIES = \ +@CK_COMPILE_FREEBSD_TRUE@ $(am__DEPENDENCIES_1) +am__libck_la_SOURCES_DIST = ck-sysdeps.h ck-sysdeps-unix.c \ + ck-sysdeps-linux.c ck-sysdeps-solaris.c ck-sysdeps-freebsd.c +am__objects_1 = +@CK_COMPILE_LINUX_TRUE@am__objects_2 = ck-sysdeps-linux.lo \ +@CK_COMPILE_LINUX_TRUE@ $(am__objects_1) +@CK_COMPILE_SOLARIS_TRUE@am__objects_3 = ck-sysdeps-solaris.lo \ +@CK_COMPILE_SOLARIS_TRUE@ $(am__objects_1) +@CK_COMPILE_FREEBSD_TRUE@am__objects_4 = ck-sysdeps-freebsd.lo \ +@CK_COMPILE_FREEBSD_TRUE@ $(am__objects_1) +am_libck_la_OBJECTS = ck-sysdeps-unix.lo $(am__objects_1) \ + $(am__objects_2) $(am__objects_3) $(am__objects_4) +libck_la_OBJECTS = $(am_libck_la_OBJECTS) am__EXEEXT_1 = am__installdirs = "$(DESTDIR)$(sbindir)" sbinPROGRAMS_INSTALL = $(INSTALL_PROGRAM) @@ -56,33 +86,35 @@ am__console_kit_daemon_SOURCES_DIST = main.c ck-manager.h ck-manager.c \ ck-vt-monitor.h ck-vt-monitor.c ck-tty-idle-monitor.h \ ck-tty-idle-monitor.c ck-file-monitor.h ck-job.h ck-job.c \ ck-seat.h ck-seat.c ck-session.h ck-session.c ck-log.h \ - ck-log.c getfd.c proc.h proc-linux.c ck-manager-glue.h \ - ck-seat-glue.h ck-session-glue.h ck-marshal.c ck-marshal.h \ - ck-file-monitor-dummy.c ck-file-monitor-inotify.c -am__objects_1 = -am__objects_2 = proc-linux.$(OBJEXT) $(am__objects_1) -am__objects_3 = ck-marshal.$(OBJEXT) $(am__objects_1) -@ENABLE_INOTIFY_FALSE@am__objects_4 = ck-file-monitor-dummy.$(OBJEXT) -@ENABLE_INOTIFY_TRUE@am__objects_4 = \ + ck-log.c ck-manager-glue.h ck-seat-glue.h ck-session-glue.h \ + ck-marshal.c ck-marshal.h ck-file-monitor-dummy.c \ + ck-file-monitor-inotify.c +am__objects_5 = ck-marshal.$(OBJEXT) $(am__objects_1) +@ENABLE_INOTIFY_FALSE@am__objects_6 = ck-file-monitor-dummy.$(OBJEXT) +@ENABLE_INOTIFY_TRUE@am__objects_6 = \ @ENABLE_INOTIFY_TRUE@ ck-file-monitor-inotify.$(OBJEXT) am_console_kit_daemon_OBJECTS = main.$(OBJEXT) ck-manager.$(OBJEXT) \ ck-vt-monitor.$(OBJEXT) ck-tty-idle-monitor.$(OBJEXT) \ ck-job.$(OBJEXT) ck-seat.$(OBJEXT) ck-session.$(OBJEXT) \ - ck-log.$(OBJEXT) getfd.$(OBJEXT) $(am__objects_2) \ - $(am__objects_3) $(am__objects_1) $(am__objects_4) + ck-log.$(OBJEXT) $(am__objects_5) $(am__objects_1) \ + $(am__objects_6) console_kit_daemon_OBJECTS = $(am_console_kit_daemon_OBJECTS) -am__DEPENDENCIES_1 = -console_kit_daemon_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +console_kit_daemon_DEPENDENCIES = $(am__DEPENDENCIES_1) libck.la \ $(am__DEPENDENCIES_1) am__test_tty_idle_monitor_SOURCES_DIST = ck-tty-idle-monitor.h \ ck-tty-idle-monitor.c ck-file-monitor.h \ ck-file-monitor-dummy.c ck-file-monitor-inotify.c \ test-tty-idle-monitor.c am_test_tty_idle_monitor_OBJECTS = ck-tty-idle-monitor.$(OBJEXT) \ - $(am__objects_4) test-tty-idle-monitor.$(OBJEXT) \ + $(am__objects_6) test-tty-idle-monitor.$(OBJEXT) \ $(am__objects_1) test_tty_idle_monitor_OBJECTS = $(am_test_tty_idle_monitor_OBJECTS) -test_tty_idle_monitor_DEPENDENCIES = $(am__DEPENDENCIES_1) \ +test_tty_idle_monitor_DEPENDENCIES = $(am__DEPENDENCIES_1) libck.la \ + $(am__DEPENDENCIES_1) +am_test_vt_monitor_OBJECTS = ck-vt-monitor.$(OBJEXT) \ + test-vt-monitor.$(OBJEXT) $(am__objects_1) +test_vt_monitor_OBJECTS = $(am_test_vt_monitor_OBJECTS) +test_vt_monitor_DEPENDENCIES = $(am__DEPENDENCIES_1) libck.la \ $(am__DEPENDENCIES_1) DEFAULT_INCLUDES = -I. -I$(srcdir) -I$(top_builddir) depcomp = $(SHELL) $(top_srcdir)/depcomp @@ -95,12 +127,15 @@ LTCOMPILE = $(LIBTOOL) --tag=CC --mode=compile $(CC) $(DEFS) \ CCLD = $(CC) LINK = $(LIBTOOL) --tag=CC --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ $(AM_LDFLAGS) $(LDFLAGS) -o $@ -SOURCES = $(console_kit_daemon_SOURCES) \ +SOURCES = $(libck_la_SOURCES) $(EXTRA_libck_la_SOURCES) \ + $(console_kit_daemon_SOURCES) \ $(EXTRA_console_kit_daemon_SOURCES) \ - $(test_tty_idle_monitor_SOURCES) -DIST_SOURCES = $(am__console_kit_daemon_SOURCES_DIST) \ + $(test_tty_idle_monitor_SOURCES) $(test_vt_monitor_SOURCES) +DIST_SOURCES = $(am__libck_la_SOURCES_DIST) $(EXTRA_libck_la_SOURCES) \ + $(am__console_kit_daemon_SOURCES_DIST) \ $(EXTRA_console_kit_daemon_SOURCES) \ - $(am__test_tty_idle_monitor_SOURCES_DIST) + $(am__test_tty_idle_monitor_SOURCES_DIST) \ + $(test_vt_monitor_SOURCES) RECURSIVE_TARGETS = all-recursive check-recursive dvi-recursive \ html-recursive info-recursive install-data-recursive \ install-exec-recursive install-info-recursive \ @@ -176,6 +211,7 @@ INSTALL_SCRIPT = @INSTALL_SCRIPT@ INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ INSTOBJEXT = @INSTOBJEXT@ INTLLIBS = @INTLLIBS@ +KVM_LIBS = @KVM_LIBS@ LDFLAGS = @LDFLAGS@ LIBDBUS_CFLAGS = @LIBDBUS_CFLAGS@ LIBDBUS_LIBS = @LIBDBUS_LIBS@ @@ -286,6 +322,19 @@ INCLUDES = \ $(DBUS_CFLAGS) \ $(NULL) +noinst_LTLIBRARIES = \ + libck.la \ + $(NULL) + +libck_la_SOURCES = ck-sysdeps.h ck-sysdeps-unix.c $(NULL) \ + $(am__append_1) $(am__append_2) $(am__append_3) +@CK_COMPILE_FREEBSD_TRUE@libck_la_LIBADD = $(KVM_LIBS) +EXTRA_libck_la_SOURCES = \ + ck-sysdeps-linux.c \ + ck-sysdeps-solaris.c \ + ck-sysdeps-freebsd.c \ + $(NULL) + BUILT_SOURCES = \ ck-manager-glue.h \ ck-seat-glue.h \ @@ -294,16 +343,11 @@ BUILT_SOURCES = \ 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-tty-idle-monitor.h \ ck-tty-idle-monitor.c ck-file-monitor.h ck-job.h ck-job.c \ ck-seat.h ck-seat.c ck-session.h ck-session.c ck-log.h \ - ck-log.c getfd.c proc.h $(PLATFORM_SOURCES) $(BUILT_SOURCES) \ - $(NULL) $(FILE_MONITOR_BACKEND) + ck-log.c $(BUILT_SOURCES) $(NULL) $(FILE_MONITOR_BACKEND) @ENABLE_INOTIFY_FALSE@FILE_MONITOR_BACKEND = ck-file-monitor-dummy.c @ENABLE_INOTIFY_TRUE@FILE_MONITOR_BACKEND = ck-file-monitor-inotify.c EXTRA_console_kit_daemon_SOURCES = \ @@ -313,6 +357,18 @@ EXTRA_console_kit_daemon_SOURCES = \ console_kit_daemon_LDADD = \ $(CONSOLE_KIT_LIBS) \ + libck.la \ + $(NULL) + +test_vt_monitor_SOURCES = \ + ck-vt-monitor.h \ + ck-vt-monitor.c \ + test-vt-monitor.c \ + $(NULL) + +test_vt_monitor_LDADD = \ + $(CONSOLE_KIT_LIBS) \ + libck.la \ $(NULL) test_tty_idle_monitor_SOURCES = \ @@ -325,6 +381,7 @@ test_tty_idle_monitor_SOURCES = \ test_tty_idle_monitor_LDADD = \ $(CONSOLE_KIT_LIBS) \ + libck.la \ $(NULL) EXTRA_DIST = \ @@ -377,6 +434,17 @@ $(top_srcdir)/configure: @MAINTAINER_MODE_TRUE@ $(am__configure_deps) $(ACLOCAL_M4): @MAINTAINER_MODE_TRUE@ $(am__aclocal_m4_deps) cd $(top_builddir) && $(MAKE) $(AM_MAKEFLAGS) am--refresh +clean-noinstLTLIBRARIES: + -test -z "$(noinst_LTLIBRARIES)" || rm -f $(noinst_LTLIBRARIES) + @list='$(noinst_LTLIBRARIES)'; for p in $$list; do \ + dir="`echo $$p | sed -e 's|/[^/]*$$||'`"; \ + test "$$dir" != "$$p" || dir=.; \ + echo "rm -f \"$${dir}/so_locations\""; \ + rm -f "$${dir}/so_locations"; \ + done +libck.la: $(libck_la_OBJECTS) $(libck_la_DEPENDENCIES) + $(LINK) $(libck_la_LDFLAGS) $(libck_la_OBJECTS) $(libck_la_LIBADD) $(LIBS) + clean-noinstPROGRAMS: @list='$(noinst_PROGRAMS)'; for p in $$list; do \ f=`echo $$p|sed 's/$(EXEEXT)$$//'`; \ @@ -417,6 +485,9 @@ console-kit-daemon$(EXEEXT): $(console_kit_daemon_OBJECTS) $(console_kit_daemon_ test-tty-idle-monitor$(EXEEXT): $(test_tty_idle_monitor_OBJECTS) $(test_tty_idle_monitor_DEPENDENCIES) @rm -f test-tty-idle-monitor$(EXEEXT) $(LINK) $(test_tty_idle_monitor_LDFLAGS) $(test_tty_idle_monitor_OBJECTS) $(test_tty_idle_monitor_LDADD) $(LIBS) +test-vt-monitor$(EXEEXT): $(test_vt_monitor_OBJECTS) $(test_vt_monitor_DEPENDENCIES) + @rm -f test-vt-monitor$(EXEEXT) + $(LINK) $(test_vt_monitor_LDFLAGS) $(test_vt_monitor_OBJECTS) $(test_vt_monitor_LDADD) $(LIBS) mostlyclean-compile: -rm -f *.$(OBJEXT) @@ -432,12 +503,15 @@ distclean-compile: @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-sysdeps-freebsd.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-sysdeps-linux.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-sysdeps-solaris.Plo@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-sysdeps-unix.Plo@am__quote@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/ck-tty-idle-monitor.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@ @AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-tty-idle-monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/test-vt-monitor.Po@am__quote@ .c.o: @am__fastdepCC_TRUE@ if $(COMPILE) -MT $@ -MD -MP -MF "$(DEPDIR)/$*.Tpo" -c -o $@ $<; \ @@ -647,7 +721,7 @@ distdir: $(DISTFILES) check-am: all-am check: $(BUILT_SOURCES) $(MAKE) $(AM_MAKEFLAGS) check-recursive -all-am: Makefile $(PROGRAMS) +all-am: Makefile $(LTLIBRARIES) $(PROGRAMS) installdirs: installdirs-recursive installdirs-am: for dir in "$(DESTDIR)$(sbindir)"; do \ @@ -683,8 +757,8 @@ maintainer-clean-generic: -test -z "$(MAINTAINERCLEANFILES)" || rm -f $(MAINTAINERCLEANFILES) clean: clean-recursive -clean-am: clean-generic clean-libtool clean-noinstPROGRAMS \ - clean-sbinPROGRAMS mostlyclean-am +clean-am: clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS clean-sbinPROGRAMS mostlyclean-am distclean: distclean-recursive -rm -rf ./$(DEPDIR) @@ -735,9 +809,9 @@ 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-noinstPROGRAMS \ - clean-recursive clean-sbinPROGRAMS ctags ctags-recursive \ - distclean distclean-compile distclean-generic \ + clean clean-generic clean-libtool clean-noinstLTLIBRARIES \ + clean-noinstPROGRAMS 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 \ diff --git a/src/ck-file-monitor-inotify.c b/src/ck-file-monitor-inotify.c index 6e775e2..4fdd6aa 100644 --- a/src/ck-file-monitor-inotify.c +++ b/src/ck-file-monitor-inotify.c @@ -407,7 +407,7 @@ handle_inotify_event (CkFileMonitor *monitor, static gboolean inotify_data_pending (GIOChannel *source, - GIOCondition condition, + GIOCondition condition, CkFileMonitor *monitor) { int len; diff --git a/src/ck-job.c b/src/ck-job.c index 1093629..891c743 100644 --- a/src/ck-job.c +++ b/src/ck-job.c @@ -28,6 +28,7 @@ #include <sys/types.h> #include <sys/wait.h> #include <errno.h> +#include <signal.h> #include <glib.h> #include <glib/gi18n.h> @@ -44,8 +45,8 @@ struct CkJobPrivate guint out_watch_id; char *command; - GString *stdout; - GString *stderr; + GString *std_out; + GString *std_err; GPid child_pid; }; @@ -138,7 +139,7 @@ error_watch (GIOChannel *source, switch (status) { case G_IO_STATUS_NORMAL: g_debug ("command error output: %s", line); - g_string_append (job->priv->stderr, line); + g_string_append (job->priv->std_err, line); break; case G_IO_STATUS_EOF: finished = TRUE; @@ -183,7 +184,7 @@ out_watch (GIOChannel *source, switch (status) { case G_IO_STATUS_NORMAL: g_debug ("command output: %s", line); - g_string_append (job->priv->stdout, line); + g_string_append (job->priv->std_out, line); break; case G_IO_STATUS_EOF: finished = TRUE; @@ -281,10 +282,10 @@ ck_job_execute (CkJob *job, gboolean ck_job_get_stdout (CkJob *job, - char **stdout) + char **std_outp) { - if (stdout != NULL) { - *stdout = g_strdup (job->priv->stdout->str); + if (std_outp != NULL) { + *std_outp = g_strdup (job->priv->std_out->str); } return TRUE; } @@ -335,8 +336,8 @@ ck_job_init (CkJob *job) { job->priv = CK_JOB_GET_PRIVATE (job); - job->priv->stderr = g_string_new (NULL); - job->priv->stdout = g_string_new (NULL); + job->priv->std_err = g_string_new (NULL); + job->priv->std_out = g_string_new (NULL); } gboolean @@ -374,8 +375,8 @@ ck_job_finalize (GObject *object) g_source_remove (job->priv->err_watch_id); } g_free (job->priv->command); - g_string_free (job->priv->stdout, TRUE); - g_string_free (job->priv->stderr, TRUE); + g_string_free (job->priv->std_out, TRUE); + g_string_free (job->priv->std_err, TRUE); G_OBJECT_CLASS (ck_job_parent_class)->finalize (object); } diff --git a/src/ck-log.c b/src/ck-log.c index 9f49352..e7ae05b 100644 --- a/src/ck-log.c +++ b/src/ck-log.c @@ -178,12 +178,18 @@ void ck_log_init (void) { const char *prg_name; + int options; g_log_set_default_handler (ck_log_default_handler, NULL); prg_name = g_get_prgname (); - openlog (prg_name, LOG_PERROR|LOG_PID, LOG_DAEMON); + options = LOG_PID; +#ifdef LOG_PERROR + options |= LOG_PERROR; +#endif + + openlog (prg_name, options, LOG_DAEMON); initialized = TRUE; } diff --git a/src/ck-manager-glue.h b/src/ck-manager-glue.h index 6172f7d..0def872 100644 --- a/src/ck-manager-glue.h +++ b/src/ck-manager-glue.h @@ -53,7 +53,7 @@ G_BEGIN_DECLS #endif /* !G_ENABLE_DEBUG */ -/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.87ODQT:1) */ +/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.2JLIYT:1) */ extern void dbus_glib_marshal_ck_manager_BOOLEAN__POINTER_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -100,11 +100,11 @@ dbus_glib_marshal_ck_manager_BOOLEAN__POINTER_POINTER (GClosure *closure, g_value_set_boolean (return_value, v_return); } -/* NONE:UINT,POINTER (/tmp/dbus-binding-tool-c-marshallers.87ODQT:2) */ +/* NONE:UINT,POINTER (/tmp/dbus-binding-tool-c-marshallers.2JLIYT: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.87ODQT:3) */ +/* NONE:STRING,POINTER (/tmp/dbus-binding-tool-c-marshallers.2JLIYT:3) */ extern void dbus_glib_marshal_ck_manager_VOID__STRING_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -148,11 +148,11 @@ dbus_glib_marshal_ck_manager_VOID__STRING_POINTER (GClosure *closure, } #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.87ODQT:4) */ +/* NONE:POINTER (/tmp/dbus-binding-tool-c-marshallers.2JLIYT: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.87ODQT:5) */ +/* NONE:BOXED,POINTER (/tmp/dbus-binding-tool-c-marshallers.2JLIYT:5) */ extern void dbus_glib_marshal_ck_manager_VOID__BOXED_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, diff --git a/src/ck-manager.c b/src/ck-manager.c index 99eeed6..377cef0 100644 --- a/src/ck-manager.c +++ b/src/ck-manager.c @@ -43,20 +43,22 @@ #include "ck-job.h" #include "ck-marshal.h" -#include "proc.h" +#include "ck-sysdeps.h" #define CK_MANAGER_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_MANAGER, CkManagerPrivate)) +#define CK_SEAT_DIR SYSCONFDIR "/ConsoleKit/seats.d" + #define CK_DBUS_PATH "/org/freedesktop/ConsoleKit" #define CK_MANAGER_DBUS_PATH CK_DBUS_PATH "/Manager" #define CK_MANAGER_DBUS_NAME "org.freedesktop.ConsoleKit.Manager" #define CK_TYPE_PARAMETER_STRUCT (dbus_g_type_get_struct ("GValueArray", \ - G_TYPE_STRING, \ - G_TYPE_VALUE, \ - G_TYPE_INVALID)) + G_TYPE_STRING, \ + G_TYPE_VALUE, \ + G_TYPE_INVALID)) #define CK_TYPE_PARAMETER_LIST (dbus_g_type_get_collection ("GPtrArray", \ - CK_TYPE_PARAMETER_STRUCT)) + CK_TYPE_PARAMETER_STRUCT)) struct CkManagerPrivate { GHashTable *seats; @@ -514,13 +516,13 @@ _g_time_val_to_iso8601 (GTimeVal *time_) g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL); -#define ISO_8601_LEN 21 +#define ISO_8601_LEN 21 #define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ" retval = g_new0 (gchar, ISO_8601_LEN + 1); strftime (retval, ISO_8601_LEN, - ISO_8601_FORMAT, - gmtime (&(time_->tv_sec))); + ISO_8601_FORMAT, + gmtime (&(time_->tv_sec))); return retval; } @@ -694,7 +696,7 @@ typedef void (* CkAddParamFunc) (GPtrArray *arr, const char *value); static struct { - char *key; + char *key; CkAddParamFunc func; } parse_ops[] = { { "display-device", add_param_string }, @@ -931,15 +933,15 @@ 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_stat_t *stat; - char *ssid; - CkSession *session; - LeaderInfo *leader_info; - GError *local_error; + gboolean res; + char *sender; + uid_t calling_uid; + pid_t calling_pid; + CkProcessStat *stat; + char *ssid; + CkSession *session; + LeaderInfo *leader_info; + GError *local_error; ssid = NULL; @@ -962,7 +964,7 @@ ck_manager_get_session_for_cookie (CkManager *manager, } local_error = NULL; - res = proc_stat_new_for_pid (calling_pid, &stat, &local_error); + res = ck_process_stat_new_for_unix_pid (calling_pid, &stat, &local_error); if (! res) { GError *error; error = g_error_new (CK_MANAGER_ERROR, @@ -980,7 +982,7 @@ ck_manager_get_session_for_cookie (CkManager *manager, } /* FIXME: should we restrict this by uid? */ - proc_stat_free (stat); + ck_process_stat_free (stat); leader_info = g_hash_table_lookup (manager->priv->leaders, cookie); if (leader_info == NULL) { @@ -1021,7 +1023,7 @@ get_cookie_for_pid (CkManager *manager, /* FIXME: need a better way to get the cookie */ - cookie = proc_pid_get_env (pid, "XDG_SESSION_COOKIE"); + cookie = ck_unix_pid_get_env (pid, "XDG_SESSION_COOKIE"); return cookie; } @@ -1038,13 +1040,13 @@ 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_stat_t *stat; - char *cookie; - GError *error; + gboolean res; + char *sender; + uid_t calling_uid; + pid_t calling_pid; + CkProcessStat *stat; + char *cookie; + GError *error; sender = dbus_g_method_get_sender (context); @@ -1065,7 +1067,7 @@ ck_manager_get_session_for_unix_process (CkManager *manager, } error = NULL; - res = proc_stat_new_for_pid (calling_pid, &stat, &error); + res = ck_process_stat_new_for_unix_pid (calling_pid, &stat, &error); if (! res) { GError *error; g_debug ("stat on pid %d failed", calling_pid); @@ -1080,7 +1082,7 @@ ck_manager_get_session_for_unix_process (CkManager *manager, /* FIXME: check stuff? */ - proc_stat_free (stat); + ck_process_stat_free (stat); cookie = get_cookie_for_pid (manager, pid); if (cookie == NULL) { @@ -1545,11 +1547,61 @@ ck_manager_get_seats (CkManager *manager, } static void -create_seats (CkManager *manager) +add_seat_for_file (CkManager *manager, + const char *filename) { + char *sid; CkSeat *seat; - seat = add_new_seat (manager, CK_SEAT_KIND_STATIC); + sid = generate_seat_id (manager); + + seat = ck_seat_new_from_file (sid, filename); + if (seat == NULL) { + /* returns null if connection to bus fails */ + g_free (sid); + return; + } + + g_hash_table_insert (manager->priv->seats, sid, seat); + + g_debug ("Added seat: %s", sid); + + g_signal_emit (manager, signals [SEAT_ADDED], 0, sid); +} + +static gboolean +load_seats_from_dir (CkManager *manager) +{ + GDir *d; + GError *error; + const char *file; + + error = NULL; + d = g_dir_open (CK_SEAT_DIR, + 0, + &error); + if (d == NULL) { + g_warning ("Couldn't open seat dir: %s", error->message); + g_error_free (error); + return FALSE; + } + + while ((file = g_dir_read_name (d)) != NULL) { + char *path; + path = g_build_filename (CK_SEAT_DIR, file, NULL); + add_seat_for_file (manager, path); + g_free (path); + } + + g_dir_close (d); + + return TRUE; +} + +static void +create_seats (CkManager *manager) +{ + load_seats_from_dir (manager); } static void diff --git a/src/ck-seat-glue.h b/src/ck-seat-glue.h index af823bc..d6cbca1 100644 --- a/src/ck-seat-glue.h +++ b/src/ck-seat-glue.h @@ -53,7 +53,7 @@ G_BEGIN_DECLS #endif /* !G_ENABLE_DEBUG */ -/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.NT25PT:1) */ +/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.33NIYT:1) */ extern void dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -100,7 +100,7 @@ dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER (GClosure *closure, g_value_set_boolean (return_value, v_return); } -/* NONE:BOXED,POINTER (/tmp/dbus-binding-tool-c-marshallers.NT25PT:2) */ +/* NONE:BOXED,POINTER (/tmp/dbus-binding-tool-c-marshallers.33NIYT:2) */ extern void dbus_glib_marshal_ck_seat_VOID__BOXED_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -152,17 +152,18 @@ G_END_DECLS 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_can_activate_sessions, dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER, 183 }, - { (GCallback) ck_seat_activate_session, dbus_glib_marshal_ck_seat_NONE__BOXED_POINTER, 259 }, + { (GCallback) ck_seat_get_devices, dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER, 118 }, + { (GCallback) ck_seat_get_active_session, dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER, 184 }, + { (GCallback) ck_seat_can_activate_sessions, dbus_glib_marshal_ck_seat_BOOLEAN__POINTER_POINTER, 249 }, + { (GCallback) ck_seat_activate_session, dbus_glib_marshal_ck_seat_NONE__BOXED_POINTER, 325 }, }; const DBusGObjectInfo dbus_glib_ck_seat_object_info = { 0, dbus_glib_ck_seat_methods, - 5, -"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\0CanActivateSessions\0S\0can_activate\0O\0F\0N\0b\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", + 6, +"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\0GetDevices\0S\0devices\0O\0F\0N\0a(ss)\0\0org.freedesktop.ConsoleKit.Seat\0GetActiveSession\0S\0ssid\0O\0F\0N\0o\0\0org.freedesktop.ConsoleKit.Seat\0CanActivateSessions\0S\0can_activate\0O\0F\0N\0b\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\0org.freedesktop.ConsoleKit.Seat\0DeviceAdded\0org.freedesktop.ConsoleKit.Seat\0DeviceRemoved\0\0", "\0" }; diff --git a/src/ck-seat.c b/src/ck-seat.c index a77e0b1..e04b569 100644 --- a/src/ck-seat.c +++ b/src/ck-seat.c @@ -25,13 +25,6 @@ #include <fcntl.h> #include <unistd.h> #include <string.h> -#ifdef HAVE_PATHS_H -#include <paths.h> -#endif /* HAVE_PATHS_H */ - -#ifndef _PATH_TTY -#define _PATH_TTY "/dev/tty" -#endif #include <glib.h> #include <glib/gi18n.h> @@ -41,6 +34,8 @@ #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> +#include "ck-sysdeps.h" + #include "ck-seat.h" #include "ck-seat-glue.h" #include "ck-marshal.h" @@ -53,11 +48,13 @@ #define CK_DBUS_PATH "/org/freedesktop/ConsoleKit" #define CK_DBUS_NAME "org.freedesktop.ConsoleKit" + struct CkSeatPrivate { char *id; CkSeatKind kind; GHashTable *sessions; + GPtrArray *devices; CkSession *active_session; @@ -70,6 +67,8 @@ enum { ACTIVE_SESSION_CHANGED, SESSION_ADDED, SESSION_REMOVED, + DEVICE_ADDED, + DEVICE_REMOVED, LAST_SIGNAL }; @@ -169,6 +168,7 @@ _seat_activate_session (CkSeat *seat, CkSession *session, DBusGMethodInvocation *context) { + gboolean res; gboolean ret; guint num; char *device; @@ -202,7 +202,8 @@ _seat_activate_session (CkSeat *seat, ck_session_get_display_device (session, &device, NULL); - if (device == NULL || (sscanf (device, _PATH_TTY "%u", &num) != 1)) { + res = ck_get_console_num_from_device (device, &num); + if (! res) { GError *error; error = g_error_new (CK_SEAT_ERROR, CK_SEAT_ERROR_GENERAL, @@ -486,7 +487,7 @@ update_active_vt (CkSeat *seat, CkSession *session; char *device; - device = g_strdup_printf (_PATH_TTY "%u", num); + device = ck_get_console_device_for_num (num); g_debug ("Active device: %s", device); @@ -605,6 +606,60 @@ ck_seat_can_activate_sessions (CkSeat *seat, return TRUE; } +static gboolean +ck_seat_has_device (CkSeat *seat, + GValueArray *device, + gboolean *result, + GError *error) +{ + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); + + return TRUE; +} + +gboolean +ck_seat_add_device (CkSeat *seat, + GValueArray *device, + GError **error) +{ + gboolean present; + + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); + + /* FIXME: check if already present */ + present = FALSE; + ck_seat_has_device (seat, device, &present, NULL); + if (present) { + g_set_error (error, CK_SEAT_ERROR, CK_SEAT_ERROR_GENERAL, "%s", "Device already present"); + return FALSE; + } + + g_ptr_array_add (seat->priv->devices, g_boxed_copy (CK_TYPE_DEVICE, device)); + + g_debug ("Emitting device added signal"); + + g_signal_emit (seat, signals [DEVICE_ADDED], 0, device); + + return TRUE; +} + +gboolean +ck_seat_remove_device (CkSeat *seat, + GValueArray *device, + GError **error) +{ + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); + + /* FIXME: check if already present */ + if (0) { + g_debug ("Emitting device removed signal"); + + g_signal_emit (seat, signals [DEVICE_REMOVED], 0, device); + } + + return TRUE; +} + gboolean ck_seat_get_kind (CkSeat *seat, CkSeatKind *kind, @@ -689,6 +744,38 @@ ck_seat_get_sessions (CkSeat *seat, } static void +copy_devices (gpointer data, + GPtrArray **array) +{ + g_ptr_array_add (*array, data); +} + +/* + Example: + dbus-send --system --dest=org.freedesktop.ConsoleKit \ + --type=method_call --print-reply --reply-timeout=2000 \ + /org/freedesktop/ConsoleKit/Seat1 \ + org.freedesktop.ConsoleKit.Seat.GetDevices +*/ + +gboolean +ck_seat_get_devices (CkSeat *seat, + GPtrArray **devices, + GError **error) +{ + g_return_val_if_fail (CK_IS_SEAT (seat), FALSE); + + if (devices == NULL) { + return FALSE; + } + + *devices = g_ptr_array_sized_new (seat->priv->devices->len); + g_ptr_array_foreach (seat->priv->devices, (GFunc)copy_devices, devices); + + return TRUE; +} + +static void _ck_seat_set_id (CkSeat *seat, const char *id) { @@ -809,6 +896,25 @@ ck_seat_class_init (CkSeatClass *klass) G_TYPE_NONE, 1, G_TYPE_STRING); + signals [DEVICE_ADDED] = g_signal_new ("device-added", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CkSeatClass, device_added), + NULL, + NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, CK_TYPE_DEVICE); + signals [DEVICE_REMOVED] = g_signal_new ("device-removed", + G_TYPE_FROM_CLASS (object_class), + G_SIGNAL_RUN_LAST, + G_STRUCT_OFFSET (CkSeatClass, device_removed), + NULL, + NULL, + g_cclosure_marshal_VOID__BOXED, + G_TYPE_NONE, + 1, CK_TYPE_DEVICE); + g_object_class_install_property (object_class, PROP_ID, g_param_spec_string ("id", @@ -839,6 +945,7 @@ ck_seat_init (CkSeat *seat) g_str_equal, g_free, (GDestroyNotify) g_object_unref); + seat->priv->devices = g_ptr_array_new (); } static void @@ -861,6 +968,7 @@ ck_seat_finalize (GObject *object) g_object_unref (seat->priv->active_session); } + g_ptr_array_free (seat->priv->devices, TRUE); g_hash_table_destroy (seat->priv->sessions); g_free (seat->priv->id); @@ -887,3 +995,111 @@ ck_seat_new (const char *sid, return CK_SEAT (object); } + +CkSeat * +ck_seat_new_with_devices (const char *sid, + CkSeatKind kind, + GPtrArray *devices) +{ + GObject *object; + gboolean res; + int i; + + object = g_object_new (CK_TYPE_SEAT, + "id", sid, + "kind", kind, + NULL); + + if (devices != NULL) { + for (i = 0; i < devices->len; i++) { + ck_seat_add_device (CK_SEAT (object), g_ptr_array_index (devices, i), NULL); + } + } + + res = register_seat (CK_SEAT (object)); + if (! res) { + g_object_unref (object); + return NULL; + } + + return CK_SEAT (object); +} + +CkSeat * +ck_seat_new_from_file (const char *sid, + const char *path) +{ + GKeyFile *key_file; + gboolean res; + GError *error; + char *group; + CkSeat *seat; + gboolean hidden; + GPtrArray *devices; + char **device_list; + gsize ndevices; + gsize i; + + key_file = g_key_file_new (); + error = NULL; + res = g_key_file_load_from_file (key_file, + path, + G_KEY_FILE_NONE, + &error); + if (! res) { + g_warning ("Unable to load seats from file %s: %s", path, error->message); + g_error_free (error); + return NULL; + } + + group = g_key_file_get_start_group (key_file); + if (group == NULL || strcmp (group, "Seat Entry") != 0) { + g_warning ("Not a seat file: %s", path); + return NULL; + } + + hidden = g_key_file_get_boolean (key_file, group, "Hidden", NULL); + if (hidden) { + g_debug ("Seat is hidden"); + return NULL; + } + + device_list = g_key_file_get_string_list (key_file, group, "Devices", &ndevices, NULL); + + g_debug ("Creating seat %s with %d devices", sid, ndevices); + + devices = g_ptr_array_sized_new (ndevices); + + for (i = 0; i < ndevices; i++) { + char **split; + GValue device_val = { 0, }; + + split = g_strsplit (device_list[i], ":", 2); + + if (split == NULL) { + continue; + } + + g_debug ("Adding device: %s %s", split[0], split[1]); + + g_value_init (&device_val, CK_TYPE_DEVICE); + g_value_take_boxed (&device_val, + dbus_g_type_specialized_construct (CK_TYPE_DEVICE)); + dbus_g_type_struct_set (&device_val, + 0, split[0], + 1, split[1], + G_MAXUINT); + + g_ptr_array_add (devices, g_value_get_boxed (&device_val)); + + g_strfreev (split); + } + + g_free (group); + + seat = ck_seat_new_with_devices (sid, CK_SEAT_KIND_STATIC, devices); + + g_ptr_array_free (devices, TRUE); + + return seat; +} diff --git a/src/ck-seat.h b/src/ck-seat.h index 4707bf9..63ab3d5 100644 --- a/src/ck-seat.h +++ b/src/ck-seat.h @@ -47,12 +47,16 @@ 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); + 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); + void (* device_added) (CkSeat *seat, + GValueArray *device); + void (* device_removed) (CkSeat *seat, + GValueArray *device); } CkSeatClass; typedef enum @@ -71,10 +75,21 @@ typedef enum #define CK_SEAT_ERROR ck_seat_error_quark () + +#define CK_TYPE_DEVICE (dbus_g_type_get_struct ("GValueArray", \ + G_TYPE_STRING, \ + G_TYPE_STRING, \ + G_TYPE_INVALID)) + GQuark ck_seat_error_quark (void); GType ck_seat_get_type (void); CkSeat * ck_seat_new (const char *sid, CkSeatKind kind); +CkSeat * ck_seat_new_from_file (const char *sid, + const char *path); +CkSeat * ck_seat_new_with_devices (const char *sid, + CkSeatKind kind, + GPtrArray *devices); gboolean ck_seat_get_kind (CkSeat *seat, CkSeatKind *kind, GError **error); @@ -87,6 +102,12 @@ gboolean ck_seat_remove_session (CkSeat *seat, gboolean ck_seat_set_active_session (CkSeat *seat, CkSession *session, GError **error); +gboolean ck_seat_add_device (CkSeat *seat, + GValueArray *device, + GError **error); +gboolean ck_seat_remove_device (CkSeat *seat, + GValueArray *device, + GError **error); /* exported methods */ gboolean ck_seat_get_id (CkSeat *seat, @@ -95,6 +116,9 @@ gboolean ck_seat_get_id (CkSeat *seat, gboolean ck_seat_get_sessions (CkSeat *seat, GPtrArray **sessions, GError **error); +gboolean ck_seat_get_devices (CkSeat *seat, + GPtrArray **devices, + GError **error); gboolean ck_seat_get_active_session (CkSeat *seat, char **ssid, GError **error); diff --git a/src/ck-seat.xml b/src/ck-seat.xml index 5fda057..b66fcaa 100644 --- a/src/ck-seat.xml +++ b/src/ck-seat.xml @@ -7,6 +7,9 @@ <method name="GetSessions"> <arg name="sessions" direction="out" type="ao"/> </method> + <method name="GetDevices"> + <arg name="devices" direction="out" type="a(ss)"/> + </method> <method name="GetActiveSession"> <arg name="ssid" direction="out" type="o"/> </method> @@ -26,5 +29,11 @@ <signal name="SessionRemoved"> <arg name="ssid" type="o"/> </signal> + <signal name="DeviceAdded"> + <arg name="device" type="(ss)"/> + </signal> + <signal name="DeviceRemoved"> + <arg name="device" type="(ss)"/> + </signal> </interface> </node> diff --git a/src/ck-session-glue.h b/src/ck-session-glue.h index 9323c73..cabded2 100644 --- a/src/ck-session-glue.h +++ b/src/ck-session-glue.h @@ -53,7 +53,7 @@ G_BEGIN_DECLS #endif /* !G_ENABLE_DEBUG */ -/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.CVG6PT:1) */ +/* BOOLEAN:POINTER,POINTER (/tmp/dbus-binding-tool-c-marshallers.8HEIYT:1) */ extern void dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -100,7 +100,7 @@ dbus_glib_marshal_ck_session_BOOLEAN__POINTER_POINTER (GClosure *closure, g_value_set_boolean (return_value, v_return); } -/* NONE:BOOLEAN,POINTER (/tmp/dbus-binding-tool-c-marshallers.CVG6PT:2) */ +/* NONE:BOOLEAN,POINTER (/tmp/dbus-binding-tool-c-marshallers.8HEIYT:2) */ extern void dbus_glib_marshal_ck_session_VOID__BOOLEAN_POINTER (GClosure *closure, GValue *return_value, guint n_param_values, @@ -144,7 +144,7 @@ dbus_glib_marshal_ck_session_VOID__BOOLEAN_POINTER (GClosure *closure, } #define dbus_glib_marshal_ck_session_NONE__BOOLEAN_POINTER dbus_glib_marshal_ck_session_VOID__BOOLEAN_POINTER -/* NONE:POINTER (/tmp/dbus-binding-tool-c-marshallers.CVG6PT:3) */ +/* NONE:POINTER (/tmp/dbus-binding-tool-c-marshallers.8HEIYT:3) */ #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 diff --git a/src/ck-session.c b/src/ck-session.c index c4e286a..f136333 100644 --- a/src/ck-session.c +++ b/src/ck-session.c @@ -321,13 +321,13 @@ _g_time_val_to_iso8601 (GTimeVal *time_) g_return_val_if_fail (time_->tv_usec >= 0 && time_->tv_usec < G_USEC_PER_SEC, NULL); -#define ISO_8601_LEN 21 +#define ISO_8601_LEN 21 #define ISO_8601_FORMAT "%Y-%m-%dT%H:%M:%SZ" retval = g_new0 (gchar, ISO_8601_LEN + 1); strftime (retval, ISO_8601_LEN, - ISO_8601_FORMAT, - gmtime (&(time_->tv_sec))); + ISO_8601_FORMAT, + gmtime (&(time_->tv_sec))); return retval; } @@ -1103,7 +1103,7 @@ ck_session_new_with_parameters (const char *ssid, guint n_allocated_params; guint n_params; GObjectClass *class; - GType object_type; + GType object_type; object_type = CK_TYPE_SESSION; class = g_type_class_ref (object_type); diff --git a/src/ck-sysdeps-freebsd.c b/src/ck-sysdeps-freebsd.c new file mode 100644 index 0000000..d7c7c0c --- /dev/null +++ b/src/ck-sysdeps-freebsd.c @@ -0,0 +1,423 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2006 William Jon McCann <mccann@jhu.edu> + * Copyright (C) 2007 Joe Marcus Clarke <marcus@FreeBSD.org> + * + * 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 <paths.h> +#include <ttyent.h> +#include <kvm.h> +#include <sys/param.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <sys/sysctl.h> +#include <sys/user.h> +#include <sys/ioctl.h> + +#include <sys/consio.h> + +#define DEV_ENCODE(M,m) ( \ + ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ +) + +#include "ck-sysdeps.h" + +#ifndef ERROR +#define ERROR -1 +#endif + +/* adapted from procps */ +struct _CkProcessStat +{ + 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 */ + uintptr_t penv; /* stat address of initial environment vector */ + char tty_text[16]; /* stat device name */ + +}; + +pid_t +ck_process_stat_get_ppid (CkProcessStat *stat) +{ + g_return_val_if_fail (stat != NULL, -1); + + return stat->ppid; +} + +char * +ck_process_stat_get_cmd (CkProcessStat *stat) +{ + g_return_val_if_fail (stat != NULL, NULL); + + return g_strdup (stat->cmd); +} + +char * +ck_process_stat_get_tty (CkProcessStat *stat) +{ + g_return_val_if_fail (stat != NULL, NULL); + + return g_strdup (stat->tty_text); +} + +static gboolean +get_kinfo_proc (pid_t pid, + struct kinfo_proc *p) +{ + int mib[4]; + size_t len; + + len = 4; + sysctlnametomib ("kern.proc.pid", mib, &len); + + len = sizeof(struct kinfo_proc); + mib[3] = pid; + + if (sysctl (mib, 4, p, &len, NULL, 0) == -1) { + return FALSE; + } + + return TRUE; +} + +/* return 1 if it works, or 0 for failure */ +static gboolean +stat2proc (pid_t pid, + CkProcessStat *P) +{ + struct kinfo_proc p; + char *ttname; + int num; + int tty_maj; + int tty_min; + + if (! get_kinfo_proc (pid, &p)) { + return FALSE; + } + + num = OCOMMLEN; + if (num >= sizeof P->cmd) { + num = sizeof P->cmd - 1; + } + + memcpy (P->cmd, p.ki_ocomm, num); + + P->cmd[num] = '\0'; + P->pid = p.ki_pid; + P->ppid = p.ki_ppid; + P->pgrp = p.ki_pgid; + P->session = p.ki_sid; + P->rss = p.ki_rssize; + P->vsize = p.ki_size; + P->start_time = p.ki_start.tv_sec; + P->wchan = (unsigned long) p.ki_wchan; + P->state = p.ki_stat; + P->nice = p.ki_nice; + P->flags = p.ki_sflag; + P->tpgid = p.ki_tpgid; + P->processor = p.ki_oncpu; + P->nlwp = p.ki_numthreads; + + /* we like it Linux-encoded :-) */ + tty_maj = major (p.ki_tdev); + tty_min = minor (p.ki_tdev); + P->tty = DEV_ENCODE (tty_maj,tty_min); + + snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min); + + if (p.ki_tdev != NODEV && (ttname = devname (p.ki_tdev, S_IFCHR)) != NULL) { + memcpy (P->tty_text, ttname, sizeof P->tty_text); + } + + if (p.ki_tdev == NODEV) { + memcpy (P->tty_text, " ? ", sizeof P->tty_text); + } + + if (P->pid != pid) { + return FALSE; + } + + return TRUE; +} + +gboolean +ck_process_stat_new_for_unix_pid (pid_t pid, + CkProcessStat **stat, + GError **error) +{ + gboolean res; + GError *local_error; + CkProcessStat *proc; + + g_return_val_if_fail (pid > 1, FALSE); + + if (stat == NULL) { + return FALSE; + } + + proc = g_new0 (CkProcessStat, 1); + proc->pid = pid; + res = stat2proc (pid, proc); + if (res) { + *stat = proc; + } else { + g_propagate_error (error, local_error); + *stat = NULL; + } + + return res; +} + +void +ck_process_stat_free (CkProcessStat *stat) +{ + g_free (stat); +} + +GHashTable * +ck_unix_pid_get_env_hash (pid_t pid) +{ + GHashTable *hash; + char **penv; + kvm_t *kd; + struct kinfo_proc p; + int i; + + kd = kvm_openfiles (_PATH_DEVNULL, _PATH_DEVNULL, NULL, O_RDONLY, NULL); + if (kd == NULL) { + return NULL; + } + + if (! get_kinfo_proc (pid, &p)) { + return NULL; + } + + penv = kvm_getenvv (kd, &p, 0); + if (penv == NULL) { + return NULL; + } + + hash = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + + for (i = 0; penv[i] != NULL; i++) { + char **vals; + + vals = g_strsplit (penv[i], "=", 2); + if (vals != NULL) { + g_hash_table_insert (hash, + g_strdup (vals[0]), + g_strdup (vals[1])); + g_strfreev (vals); + } + } + + kvm_close (kd); + + return hash; +} + +char * +ck_unix_pid_get_env (pid_t pid, + const char *var) +{ + GHashTable *hash; + char *val; + + /* + * Would probably be more efficient to just loop through the + * environment and return the value, avoiding building the hash + * table, but this works for now. + */ + hash = ck_unix_pid_get_env_hash (pid); + val = g_strdup (g_hash_table_lookup (hash, var)); + g_hash_table_destroy (hash); + + return val; +} + +uid_t +ck_unix_pid_get_uid (pid_t pid) +{ + uid_t uid; + gboolean res; + struct kinfo_proc p; + + g_return_val_if_fail (pid > 1, 0); + + uid = -1; + + res = get_kinfo_proc (pid, &p); + + if (res) { + uid = p.ki_uid; + } + + return uid; +} + +gboolean +ck_get_max_num_consoles (guint *num) +{ + int max_consoles; + int res; + gboolean ret; + struct ttyent *t; + + ret = FALSE; + max_consoles = 0; + + res = setttyent (); + if (res == 0) { + goto done; + } + + while ((t = getttyent ()) != NULL) { + if (t->ty_status & TTY_ON && strncmp (t->ty_name, "ttyv", 4) == 0) + max_consoles++; + } + + /* Increment one more so that all consoles are properly counted + * this is arguable a bug in vt_add_watches(). + */ + max_consoles++; + + ret = TRUE; + + endttyent (); + +done: + if (num != NULL) { + *num = max_consoles; + } + + return ret; +} + +char * +ck_get_console_device_for_num (guint num) +{ + char *device; + + /* The device number is always one less than the VT number. */ + num--; + + device = g_strdup_printf ("/dev/ttyv%u", num); + + return device; +} + +gboolean +ck_get_console_num_from_device (const char *device, + guint *num) +{ + guint n; + gboolean ret; + + n = 0; + ret = FALSE; + + if (device == NULL) { + return FALSE; + } + + if (sscanf (device, "/dev/ttyv%u", &n) == 1) { + /* The VT number is always one more than the device number. */ + n++; + ret = TRUE; + } + + if (num != NULL) { + *num = n; + } + + return ret; +} + +gboolean +ck_get_active_console_num (int console_fd, + guint *num) +{ + gboolean ret; + int res; + int active; + + g_assert (console_fd != -1); + + active = 0; + ret = FALSE; + + res = ioctl (console_fd, VT_GETACTIVE, &active); + if (res == ERROR) { + perror ("ioctl VT_GETACTIVE"); + goto out; + } + + g_debug ("Active VT is: %d (ttyv%d)", active, active - 1); + ret = TRUE; + + out: + if (num != NULL) { + *num = active; + } + + return ret; +} diff --git a/src/proc-linux.c b/src/ck-sysdeps-linux.c index d704e18..7dc99f7 100644 --- a/src/proc-linux.c +++ b/src/ck-sysdeps-linux.c @@ -25,17 +25,27 @@ #include <fcntl.h> #include <unistd.h> #include <string.h> +#include <errno.h> #include <sys/types.h> #include <sys/stat.h> +#include <sys/ioctl.h> + +#include <sys/vt.h> +#include <linux/tty.h> +#include <linux/kd.h> #ifdef HAVE_PATHS_H #include <paths.h> #endif /* HAVE_PATHS_H */ -#include "proc.h" +#include "ck-sysdeps.h" + +#ifndef ERROR +#define ERROR -1 +#endif /* adapted from procps */ -struct _proc_stat_t +struct _CkProcessStat { int pid; int ppid; /* stat,status pid of parent process */ @@ -111,7 +121,7 @@ load_drivers (void) buf[bytes] = '\0'; p = buf; - while ((p = strstr (p, " " _PATH_DEV))){ + while ((p = strstr (p, " " _PATH_DEV))) { tty_map_node *tmn; int len; char *end; @@ -263,7 +273,7 @@ link_name (guint maj, } pid_t -proc_stat_get_ppid (proc_stat_t *stat) +ck_process_stat_get_ppid (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, -1); @@ -271,7 +281,7 @@ proc_stat_get_ppid (proc_stat_t *stat) } char * -proc_stat_get_cmd (proc_stat_t *stat) +ck_process_stat_get_cmd (CkProcessStat *stat) { g_return_val_if_fail (stat != NULL, NULL); @@ -280,7 +290,7 @@ proc_stat_get_cmd (proc_stat_t *stat) /* adapted from procps */ char * -proc_stat_get_tty (proc_stat_t *stat) +ck_process_stat_get_tty (CkProcessStat *stat) { guint dev; char *tty; @@ -328,8 +338,8 @@ proc_stat_get_tty (proc_stat_t *stat) #define KLF "l" /* adapted from procps */ static void -stat2proc (const char *S, - proc_stat_t *P) +stat2proc (const char *S, + CkProcessStat *P) { unsigned num; char * tmp; @@ -392,16 +402,16 @@ stat2proc (const char *S, } gboolean -proc_stat_new_for_pid (pid_t pid, - proc_stat_t **stat, - GError **error) +ck_process_stat_new_for_unix_pid (pid_t pid, + CkProcessStat **stat, + GError **error) { - char *path; - char *contents; - gsize length; - gboolean res; - GError *local_error; - proc_stat_t *proc; + char *path; + char *contents; + gsize length; + gboolean res; + GError *local_error; + CkProcessStat *proc; g_return_val_if_fail (pid > 1, FALSE); @@ -418,7 +428,7 @@ proc_stat_new_for_pid (pid_t pid, &length, &local_error); if (res) { - proc = g_new0 (proc_stat_t, 1); + proc = g_new0 (CkProcessStat, 1); proc->pid = pid; stat2proc (contents, proc); *stat = proc; @@ -434,13 +444,13 @@ proc_stat_new_for_pid (pid_t pid, } void -proc_stat_free (proc_stat_t *stat) +ck_process_stat_free (CkProcessStat *stat) { g_free (stat); } GHashTable * -proc_pid_get_env_hash (pid_t pid) +ck_unix_pid_get_env_hash (pid_t pid) { char *path; gboolean res; @@ -484,7 +494,10 @@ proc_pid_get_env_hash (pid_t pid) char **vals; vals = g_strsplit (contents + i, "=", 2); if (vals != NULL) { - g_hash_table_insert (hash, vals[0], vals[1]); + g_hash_table_insert (hash, + g_strdup (vals[0]), + g_strdup (vals[1])); + g_strfreev (vals); } } last_was_null = FALSE; @@ -498,8 +511,8 @@ proc_pid_get_env_hash (pid_t pid) } char * -proc_pid_get_env (pid_t pid, - const char *var) +ck_unix_pid_get_env (pid_t pid, + const char *var) { char *path; gboolean res; @@ -558,7 +571,7 @@ proc_pid_get_env (pid_t pid, } uid_t -proc_pid_get_uid (pid_t pid) +ck_unix_pid_get_uid (pid_t pid) { struct stat st; char *path; @@ -581,25 +594,113 @@ proc_pid_get_uid (pid_t pid) } pid_t -proc_pid_get_ppid (pid_t pid) +ck_unix_pid_get_ppid (pid_t pid) { - int ppid; - gboolean res; - proc_stat_t *stat; + int ppid; + gboolean res; + CkProcessStat *stat; g_return_val_if_fail (pid > 1, 0); ppid = -1; - res = proc_stat_new_for_pid (pid, &stat, NULL); + res = ck_process_stat_new_for_unix_pid (pid, &stat, NULL); if (! res) { goto out; } - ppid = proc_stat_get_ppid (stat); + ppid = ck_process_stat_get_ppid (stat); - proc_stat_free (stat); + ck_process_stat_free (stat); out: return ppid; } + +gboolean +ck_get_max_num_consoles (guint *num) +{ + if (num != NULL) { + *num = MAX_NR_CONSOLES; + } + + return TRUE; +} + +char * +ck_get_console_device_for_num (guint num) +{ + char *device; + + device = g_strdup_printf (_PATH_TTY "%u", num); + + return device; +} + +gboolean +ck_get_console_num_from_device (const char *device, + guint *num) +{ + guint n; + gboolean ret; + + n = 0; + ret = FALSE; + + if (device == NULL) { + return FALSE; + } + + if (sscanf (device, _PATH_TTY "%u", &n) == 1) { + ret = TRUE; + } + + if (num != NULL) { + *num = n; + } + + return ret; +} + +gboolean +ck_get_active_console_num (int console_fd, + guint *num) +{ + gboolean ret; + int res; + guint active; + struct vt_stat stat; + + g_assert (console_fd != -1); + + active = 0; + ret = FALSE; + + res = ioctl (console_fd, VT_GETSTATE, &stat); + if (res == ERROR) { + perror ("ioctl VT_GETSTATE"); + goto out; + } + + { + int i; + + g_debug ("Current VT: tty%d", stat.v_active); + for (i = 1; i <= 16; i++) { + gboolean is_on; + is_on = stat.v_state & (1 << i); + + g_debug ("VT %d:%s", i, is_on ? "on" : "off"); + } + } + + active = stat.v_active; + ret = TRUE; + + out: + if (num != NULL) { + *num = active; + } + + return ret; +} diff --git a/src/ck-sysdeps-solaris.c b/src/ck-sysdeps-solaris.c new file mode 100644 index 0000000..9cfec2e --- /dev/null +++ b/src/ck-sysdeps-solaris.c @@ -0,0 +1,469 @@ +/* -*- 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/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> + +#define DEV_ENCODE(M,m) ( \ + ( (M&0xfff) << 8) | ( (m&0xfff00) << 12) | (m&0xff) \ +) + +#include <sys/int_types.h> +#include <sys/mkdev.h> +#define _STRUCTURED_PROC 1 +#include <sys/procfs.h> +#define NO_TTY_VALUE DEV_ENCODE(-1,-1) + +#include "ck-sysdeps.h" + +#ifndef ERROR +#define ERROR -1 +#endif + +/* adapted from procps */ +struct _CkProcessStat +{ + 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 */ + uintptr_t penv; /* stat address of initial environment vector */ + char tty_text[16]; /* stat device name */ + +}; + +pid_t +ck_process_stat_get_ppid (CkProcessStat *stat) +{ + g_return_val_if_fail (stat != NULL, -1); + + return stat->ppid; +} + +char * +ck_process_stat_get_cmd (CkProcessStat *stat) +{ + g_return_val_if_fail (stat != NULL, NULL); + + return g_strdup (stat->cmd); +} + +/* adapted from procps */ +char * +ck_process_stat_get_tty (CkProcessStat *stat) +{ + guint dev; + char *tty; + guint dev_maj; + guint dev_min; + pid_t pid; + + g_return_val_if_fail (stat != NULL, NULL); + + return g_strdup (stat->tty_text); +} + +/* return 1 if it works, or 0 for failure */ +static gboolean +stat2proc (pid_t pid, + CkProcessStat *P) +{ + struct psinfo p; + char buf[32]; + int num; + int fd; + int tty_maj; + int tty_min; + + snprintf (buf, sizeof buf, "/proc/%d/psinfo", pid); + + if ((fd = open (buf, O_RDONLY, 0) ) == -1 ) { + return FALSE; + } + + num = read (fd, &p, sizeof p); + close (fd); + + if (num != sizeof p) { + return FALSE; + } + + num = PRFNSZ; + if (num >= sizeof P->cmd) { + num = sizeof P->cmd - 1; + } + + memcpy (P->cmd, p.pr_fname, num); /* p.pr_fname or p.pr_lwp.pr_name */ + + P->cmd[num] = '\0'; + P->pid = p.pr_pid; + P->ppid = p.pr_ppid; + P->pgrp = p.pr_pgid; + P->session = p.pr_sid; + P->rss = p.pr_rssize; + P->vsize = p.pr_size; + P->start_time = p.pr_start.tv_sec; + P->wchan = p.pr_lwp.pr_wchan; + P->state = p.pr_lwp.pr_sname; + P->nice = p.pr_lwp.pr_nice; + P->priority = p.pr_lwp.pr_pri; /* or pr_oldpri */ + P->penv = p.pr_envp; + + /* we like it Linux-encoded :-) */ + tty_maj = major (p.pr_ttydev); + tty_min = minor (p.pr_ttydev); + P->tty = DEV_ENCODE (tty_maj,tty_min); + + snprintf (P->tty_text, sizeof P->tty_text, "%3d,%-3d", tty_maj, tty_min); + + if (tty_maj == 24) { + snprintf (P->tty_text, sizeof P->tty_text, "pts/%-3u", tty_min); + } + + if (P->tty == NO_TTY_VALUE) { + memcpy (P->tty_text, " ? ", 8); + } + + if (P->tty == DEV_ENCODE(0,0)) { + memcpy (P->tty_text, "console", 8); + } + + if (P->pid != pid) { + return FALSE; + } + + return TRUE; +} + +gboolean +ck_process_stat_new_for_unix_pid (pid_t pid, + CkProcessStat **stat, + GError **error) +{ + char *path; + char *contents; + gsize length; + gboolean res; + GError *local_error; + CkProcessStat *proc; + + g_return_val_if_fail (pid > 1, FALSE); + + if (stat == NULL) { + return FALSE; + } + + proc = g_new0 (CkProcessStat, 1); + proc->pid = pid; + res = stat2proc (pid, proc); + if (res) { + *stat = proc; + } else { + g_propagate_error (error, local_error); + *stat = NULL; + } + + return res; +} + +void +ck_process_stat_free (CkProcessStat *stat) +{ + g_free (stat); +} + +GHashTable * +ck_unix_pid_get_env_hash (pid_t pid) +{ + GHashTable *hash; + char *cmd; + char buf[BUFSIZ]; + FILE *fp; + int i; + + hash = g_hash_table_new_full (g_str_hash, + g_str_equal, + g_free, + g_free); + + cmd = g_strdup_printf ("pargs -e %d", pid); + fp = popen (cmd, "r"); + g_free (cmd); + + while (fgets (buf, BUFSIZ, fp) != NULL) { + g_strchomp (buf); + if (g_str_has_prefix (buf, "envp[")) { + char *skip_prefix; + + skip_prefix = strstr (buf, " "); + + if (skip_prefix != NULL) { + char **vals; + vals = g_strsplit (buf, "=", 2); + if (vals != NULL) { + g_hash_table_insert (hash, + g_strdup (vals[0]), + g_strdup (vals[1])); + g_strfreev (vals); + } + } + } + } + + out: + return hash; +} + +char * +ck_unix_pid_get_env (pid_t pid, + const char *var) +{ + GHashTable *hash; + char *val; + + /* + * Would probably be more efficient to just loop through the + * environment and return the value, avoiding building the hash + * table, but this works for now. + */ + hash = ck_unix_pid_get_env_hash (pid); + val = g_strdup (g_hash_table_lookup (hash, var)); + g_hash_table_destroy (hash); + + return val; +} + +uid_t +ck_unix_pid_get_uid (pid_t pid) +{ + struct stat st; + char *path; + int uid; + int res; + + g_return_val_if_fail (pid > 1, 0); + + uid = -1; + + path = g_strdup_printf ("/proc/%u", (guint)pid); + res = stat (path, &st); + g_free (path); + + if (res == 0) { + uid = st.st_uid; + } + + return uid; +} + +pid_t +ck_unix_pid_get_ppid (pid_t pid) +{ + int ppid; + gboolean res; + CkProcessStat *stat; + + g_return_val_if_fail (pid > 1, 0); + + ppid = -1; + + res = ck_process_stat_new_for_unix_pid (pid, &stat, NULL); + if (! res) { + goto out; + } + + ppid = ck_process_stat_get_ppid (stat); + + ck_process_stat_free (stat); + + out: + return ppid; +} + +gboolean +ck_get_max_num_consoles (guint *num) +{ + GError *error; + char *svcprop_stdout; + int status; + int max_consoles; + gboolean res; + gboolean ret; + + ret = FALSE; + + /* + * On Solaris, the default number of VT's is determined by + * resources and is stored in the vtdaemon SVC property + * options/vtnodecount. If the svcprop command fails, then it can + * be safely assumed that VT is not supported on this release of + * Solaris. + */ + + error = NULL; + svcprop_stdout = NULL; + status = 0; + res = g_spawn_command_line_sync ("/usr/bin/svcprop -p options/vtnodecount vtdaemon", + &svcprop_stdout, + NULL, + &status, + &error); + + if (res) { + if (error == NULL && svcprop_stdout != NULL) { + char *end; + + end = NULL; + errno = 0; + max_consoles = strtol (svcprop_stdout, &end, 0); + if (end == NULL || end == svcprop_stdout || errno != 0) { + max_consoles = 0; + } else { + ret = TRUE; + } + } + } + + if (num != NULL) { + *num = max_consoles; + } + + g_free (svcprop_stdout); + + return ret; +} + +char * +ck_get_console_device_for_num (guint num) +{ + char *device; + + device = g_strdup_printf ("/dev/vt/%u", num); + + return device; +} + +gboolean +ck_get_console_num_from_device (const char *device, + guint *num) +{ + guint n; + gboolean ret; + + n = 0; + ret = FALSE; + + if (device == NULL) { + return FALSE; + } + + if (sscanf (device, "/dev/vt/%u", &n) == 1) { + ret = TRUE; + } + + if (num != NULL) { + *num = n; + } + + return ret; +} + +gboolean +ck_get_active_console_num (int console_fd, + guint *num) +{ + gboolean ret; + int res; + guint active; + struct vt_stat stat; + + g_assert (console_fd != -1); + + active = 0; + ret = FALSE; + + res = ioctl (console_fd, VT_GETSTATE, &stat); + if (res == ERROR) { + perror ("ioctl VT_GETSTATE"); + goto out; + } + + { + int i; + + g_debug ("Current VT: tty%d", stat.v_active); + for (i = 1; i <= 16; i++) { + gboolean is_on; + is_on = stat.v_state & (1 << i); + + g_debug ("VT %d:%s", i, is_on ? "on" : "off"); + } + } + + active = stat.v_active; + ret = TRUE; + + out: + if (num != NULL) { + *num = active; + } + + return ret; +} diff --git a/src/ck-sysdeps-unix.c b/src/ck-sysdeps-unix.c new file mode 100644 index 0000000..0001b6b --- /dev/null +++ b/src/ck-sysdeps-unix.c @@ -0,0 +1,305 @@ +/* -*- 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/types.h> +#include <sys/stat.h> +#include <sys/socket.h> +#include <sys/ioctl.h> + +#ifdef __linux__ +#include <linux/kd.h> +#include <sys/vt.h> +#endif + +#ifdef __FreeBSD__ +#include <sys/consio.h> +#endif + +#ifdef HAVE_GETPEERUCRED +#include <ucred.h> +#endif + +#include "ck-sysdeps.h" + +#ifndef ERROR +#define ERROR -1 +#endif + +/* Adapted from dbus-sysdeps-unix.c:_dbus_read_credentials_socket() */ +gboolean +ck_get_socket_peer_credentials (int socket_fd, + pid_t *pid, + uid_t *uid, + GError **error) +{ + gboolean ret; + uid_t uid_read; + pid_t pid_read; + + pid_read = -1; + uid_read = -1; + ret = FALSE; + +#ifdef SO_PEERCRED + struct ucred cr; + socklen_t cr_len; + + cr_len = sizeof (cr); + + if (getsockopt (socket_fd, SOL_SOCKET, SO_PEERCRED, &cr, &cr_len) == 0 && cr_len == sizeof (cr)) { + pid_read = cr.pid; + uid_read = cr.uid; + ret = TRUE; + } else { + g_warning ("Failed to getsockopt() credentials, returned len %d/%d: %s\n", + cr_len, + (int) sizeof (cr), + g_strerror (errno)); + } +#elif defined(HAVE_GETPEERUCRED) + ucred_t *ucred; + + ucred = NULL; + if (getpeerucred (socket_fd, &ucred) == 0) { + pid_read = ucred_getpid (ucred); + uid_read = ucred_geteuid (ucred); + ret = TRUE; + } else { + g_warning ("Failed to getpeerucred() credentials: %s\n", + g_strerror (errno)); + } + if (ucred != NULL) { + ucred_free (ucred); + } +#else /* !SO_PEERCRED && !HAVE_GETPEERUCRED */ + g_warning ("Socket credentials not supported on this OS\n"); +#endif + + if (pid != NULL) { + *pid = pid_read; + } + + if (uid != NULL) { + *uid = uid_read; + } + + return ret; +} + + +/* + * 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). + */ + +gboolean +ck_fd_is_a_console (int fd) +{ +#ifdef __linux__ + char arg = 0; +#elif defined(__FreeBSD__) + int vers; +#endif + int kb_ok; + +#ifdef __linux__ + kb_ok = (ioctl (fd, KDGKBTYPE, &arg) == 0 + && ((arg == KB_101) || (arg == KB_84))); +#elif defined(__FreeBSD__) + kb_ok = (ioctl (fd, CONS_GETVERS, &vers) == 0); +#else + kb_ok = 1; +#endif + + return (isatty (fd) && kb_ok); +} + +static int +open_a_console (char *fnam) +{ + int fd; + + fd = open (fnam, O_RDONLY | O_NOCTTY); + if (fd < 0 && errno == EACCES) + fd = open (fnam, O_WRONLY | O_NOCTTY); + + if (fd < 0) + return -1; + + if (! ck_fd_is_a_console (fd)) { + close (fd); + fd = -1; + } + + return fd; +} + +int +ck_get_a_console_fd (void) +{ + int fd; + + fd = -1; + +#ifdef __sun + /* On Solaris, first try Sun VT device. */ + fd = open_a_console ("/dev/vt/active"); + if (fd >= 0) { + goto done; + } + fd = open_a_console ("/dev/vt/0"); + if (fd >= 0) { + goto done; + } +#endif + +#ifdef _PATH_TTY + fd = open_a_console (_PATH_TTY); + if (fd >= 0) { + goto done; + } +#endif + + fd = open_a_console ("/dev/tty"); + if (fd >= 0) { + goto done; + } + +#ifdef _PATH_CONSOLE + fd = open_a_console (_PATH_CONSOLE); + if (fd >= 0) { + goto done; + } +#endif + + fd = open_a_console ("/dev/console"); + if (fd >= 0) { + goto done; + } + + for (fd = 0; fd < 3; fd++) { + if (ck_fd_is_a_console (fd)) { + goto done; + } + } + done: + return fd; +} + +gboolean +ck_is_root_user (void) +{ +#ifndef G_OS_WIN32 + uid_t ruid, euid, suid; /* Real, effective and saved user ID's */ + gid_t rgid, egid, sgid; /* Real, effective and saved group ID's */ + +#ifdef HAVE_GETRESUID + if (getresuid (&ruid, &euid, &suid) != 0 || + getresgid (&rgid, &egid, &sgid) != 0) +#endif /* HAVE_GETRESUID */ + { + suid = ruid = getuid (); + sgid = rgid = getgid (); + euid = geteuid (); + egid = getegid (); + } + + if (ruid == 0) { + return TRUE; + } + +#endif + return FALSE; +} + +gboolean +ck_wait_for_active_console_num (int console_fd, + guint num) +{ + gboolean ret; + int res; + + g_assert (console_fd != -1); + + again: + ret = FALSE; + + g_debug ("VT_WAITACTIVE for vt %d", num); + errno = 0; + res = ioctl (console_fd, VT_WAITACTIVE, num); + + g_debug ("VT_WAITACTIVE for vt %d returned %d", num, ret); + + if (res == ERROR) { + const char *errmsg; + + errmsg = g_strerror (errno); + + if (errno == EINTR) { + g_debug ("Interrupted waiting for native console %d activation: %s", + num, + errmsg); + goto again; + } else { + g_warning ("Error waiting for native console %d activation: %s", + num, + errmsg); + } + goto out; + } + + ret = TRUE; + + out: + return ret; +} + +gboolean +ck_activate_console_num (int console_fd, + guint num) +{ + gboolean ret; + int res; + + g_assert (console_fd != -1); + + ret = FALSE; + + errno = 0; + res = ioctl (console_fd, VT_ACTIVATE, num); + if (res == 0) { + ret = TRUE; + } else { + g_warning ("Unable to activate console: %s", g_strerror (errno)); + } + + return ret; +} diff --git a/src/ck-sysdeps.h b/src/ck-sysdeps.h new file mode 100644 index 0000000..f0fceb7 --- /dev/null +++ b/src/ck-sysdeps.h @@ -0,0 +1,75 @@ +/* -*- 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_SYSDEPS_H +#define __CK_SYSDEPS_H + +#include "config.h" + +#include <glib.h> + +G_BEGIN_DECLS + +typedef struct _CkProcessStat CkProcessStat; + +gboolean ck_process_stat_new_for_unix_pid (pid_t pid, + CkProcessStat **stat, + GError **error); +pid_t ck_process_stat_get_ppid (CkProcessStat *stat); +char *ck_process_stat_get_tty (CkProcessStat *stat); +char *ck_process_stat_get_cmd (CkProcessStat *stat); +void ck_process_stat_free (CkProcessStat *stat); + + +char *ck_unix_pid_get_env (pid_t pid, + const char *var); + +GHashTable *ck_unix_pid_get_env_hash (pid_t pid); + +pid_t ck_unix_pid_get_ppid (pid_t pid); +uid_t ck_unix_pid_get_uid (pid_t pid); + + +gboolean ck_get_socket_peer_credentials (int socket_fd, + pid_t *pid, + uid_t *uid, + GError **error); + +int ck_get_a_console_fd (void); + +gboolean ck_fd_is_a_console (int fd); + +gboolean ck_is_root_user (void); + +gboolean ck_get_max_num_consoles (guint *num); + +char * ck_get_console_device_for_num (guint num); +gboolean ck_get_console_num_from_device (const char *device, + guint *num); +gboolean ck_get_active_console_num (int console_fd, + guint *num); +gboolean ck_activate_console_num (int console_fd, + guint num); +gboolean ck_wait_for_active_console_num (int console_fd, + guint num); + +G_END_DECLS + +#endif /* __CK_SYSDEPS_H */ diff --git a/src/ck-vt-monitor.c b/src/ck-vt-monitor.c index 40f834a..59d3d1c 100644 --- a/src/ck-vt-monitor.c +++ b/src/ck-vt-monitor.c @@ -26,13 +26,6 @@ #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> @@ -44,9 +37,12 @@ #include <dbus/dbus-glib-lowlevel.h> #include "ck-vt-monitor.h" +#include "ck-sysdeps.h" #include "ck-marshal.h" +#ifndef ERROR #define ERROR -1 +#endif #define CK_VT_MONITOR_GET_PRIVATE(o) (G_TYPE_INSTANCE_GET_PRIVATE ((o), CK_TYPE_VT_MONITOR, CkVtMonitorPrivate)) @@ -121,8 +117,8 @@ ck_vt_monitor_set_active (CkVtMonitor *vt_monitor, return FALSE; } - res = ioctl (vt_monitor->priv->vfd, VT_ACTIVATE, num); - if (res == 0) { + res = ck_activate_console_num (vt_monitor->priv->vfd, num); + if (res) { ret = TRUE; } else { g_set_error (error, @@ -272,35 +268,16 @@ static void * vt_thread_start (ThreadData *data) { CkVtMonitor *vt_monitor; + gboolean res; int ret; gint32 num; vt_monitor = data->vt_monitor; num = data->num; - again: - g_debug ("VT_WAITACTIVE for vt %d", num); - ret = ioctl (vt_monitor->priv->vfd, VT_WAITACTIVE, num); - - g_debug ("VT_WAITACTIVE for vt %d returned %d", num, ret); - - if (ret == ERROR) { - const char *errmsg; - - errmsg = g_strerror (errno); - - if (errno == EINTR) { - g_debug ("Interrupted waiting for native console %d activation: %s", - num, - errmsg); - goto again; - } else { - g_warning ("Error waiting for native console %d activation: %s", - num, - errmsg); - } - - g_free (data); + res = ck_wait_for_active_console_num (vt_monitor->priv->vfd, num); + if (! res) { + /* FIXME: what do we do if it fails? */ } else { EventData *event; @@ -357,6 +334,7 @@ vt_add_watch_unlocked (CkVtMonitor *vt_monitor, static void vt_add_watches (CkVtMonitor *vt_monitor) { + guint max_consoles; int i; gint32 current_num; @@ -364,7 +342,13 @@ vt_add_watches (CkVtMonitor *vt_monitor) current_num = vt_monitor->priv->active_num; - for (i = 1; i < MAX_NR_CONSOLES; i++) { + max_consoles = 1; + + if (! ck_get_max_num_consoles (&max_consoles)) { + /* FIXME: this can fail on solaris and freebsd */ + } + + for (i = 1; i < max_consoles; i++) { gpointer id; /* don't wait on the active vc */ @@ -383,33 +367,6 @@ vt_add_watches (CkVtMonitor *vt_monitor) G_UNLOCK (hash_lock); } -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; - - g_debug ("Current VT: tty%d", stat.v_active); - for (i = 1; i <= 16; i++) { - gboolean is_on; - is_on = stat.v_state & (1 << i); - - g_debug ("VT %d:%s", i, is_on ? "on" : "off"); - } - } - - return stat.v_active; -} - static void ck_vt_monitor_class_init (CkVtMonitorClass *klass) { @@ -430,8 +387,6 @@ ck_vt_monitor_class_init (CkVtMonitorClass *klass) g_type_class_add_private (klass, sizeof (CkVtMonitorPrivate)); } -extern int getfd (void); - static void ck_vt_monitor_init (CkVtMonitor *vt_monitor) { @@ -439,7 +394,7 @@ ck_vt_monitor_init (CkVtMonitor *vt_monitor) vt_monitor->priv = CK_VT_MONITOR_GET_PRIVATE (vt_monitor); - fd = getfd (); + fd = ck_get_a_console_fd (); vt_monitor->priv->vfd = fd; if (fd == ERROR) { @@ -447,11 +402,20 @@ ck_vt_monitor_init (CkVtMonitor *vt_monitor) errmsg = g_strerror (errno); g_warning ("Unable to open a console: %s", errmsg); } else { + gboolean res; + guint active; + + res = ck_get_active_console_num (fd, &active); + if (! res) { + /* FIXME: handle failure */ + g_warning ("Could not determine active console"); + active = 0; + } + + vt_monitor->priv->active_num = active; vt_monitor->priv->event_queue = g_async_queue_new (); 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); - vt_add_watches (vt_monitor); } } diff --git a/src/getfd.c b/src/getfd.c deleted file mode 100644 index 69c37a3..0000000 --- a/src/getfd.c +++ /dev/null @@ -1,75 +0,0 @@ -/* - * Adapted from kbd-1.12 - * License: GPL - * - */ - -#include "config.h" - -#include <stdio.h> -#include <fcntl.h> -#include <errno.h> -#include <linux/kd.h> -#include <sys/ioctl.h> - -#ifdef HAVE_PATHS_H -#include <paths.h> -#endif /* HAVE_PATHS_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 (void) -{ - int fd; - - fd = open_a_console (_PATH_TTY); - if (fd >= 0) - return fd; - - fd = open_a_console ("/dev/tty"); - if (fd >= 0) - return fd; - - fd = open_a_console (_PATH_CONSOLE); - 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; -} @@ -38,6 +38,7 @@ #include <dbus/dbus-glib.h> #include <dbus/dbus-glib-lowlevel.h> +#include "ck-sysdeps.h" #include "ck-manager.h" #include "ck-log.h" @@ -49,8 +50,8 @@ static void bus_proxy_destroyed_cb (DBusGProxy *bus_proxy, static gboolean timed_exit_cb (GMainLoop *loop) { - g_main_loop_quit (loop); - return FALSE; + g_main_loop_quit (loop); + return FALSE; } static DBusGProxy * @@ -58,7 +59,7 @@ get_bus_proxy (DBusGConnection *connection) { DBusGProxy *bus_proxy; - bus_proxy = dbus_g_proxy_new_for_name (connection, + bus_proxy = dbus_g_proxy_new_for_name (connection, DBUS_SERVICE_DBUS, DBUS_PATH_DBUS, DBUS_INTERFACE_DBUS); @@ -80,7 +81,7 @@ acquire_name_on_proxy (DBusGProxy *bus_proxy) } error = NULL; - res = dbus_g_proxy_call (bus_proxy, + res = dbus_g_proxy_call (bus_proxy, "RequestName", &error, G_TYPE_STRING, CK_DBUS_NAME, @@ -96,9 +97,9 @@ acquire_name_on_proxy (DBusGProxy *bus_proxy) g_warning ("Failed to acquire %s", CK_DBUS_NAME); } goto out; - } + } - if (result != DBUS_REQUEST_NAME_REPLY_PRIMARY_OWNER) { + 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); @@ -283,6 +284,11 @@ main (int argc, dbus_g_thread_init (); g_type_init (); + if (! ck_is_root_user ()) { + g_warning ("Must be run as root"); + exit (1); + } + 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); diff --git a/src/proc.h b/src/proc.h deleted file mode 100644 index 8c3fc64..0000000 --- a/src/proc.h +++ /dev/null @@ -1,48 +0,0 @@ -/* -*- 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_stat_t proc_stat_t; - -gboolean proc_stat_new_for_pid (pid_t pid, - proc_stat_t **stat, - GError **error); -pid_t proc_stat_get_ppid (proc_stat_t *stat); -char *proc_stat_get_tty (proc_stat_t *stat); -char *proc_stat_get_cmd (proc_stat_t *stat); -void proc_stat_free (proc_stat_t *stat); - -char *proc_pid_get_env (pid_t pid, - const char *var); - -GHashTable *proc_pid_get_env_hash (pid_t pid); - -pid_t proc_pid_get_ppid (pid_t pid); -uid_t proc_pid_get_uid (pid_t pid); - -G_END_DECLS - -#endif /* __PROC_H */ diff --git a/src/test-tty-idle-monitor.c b/src/test-tty-idle-monitor.c index 7d44b26..f56b37f 100644 --- a/src/test-tty-idle-monitor.c +++ b/src/test-tty-idle-monitor.c @@ -23,16 +23,20 @@ #include <stdlib.h> #include <stdio.h> +#include <unistd.h> #include <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> #include <pwd.h> #include <string.h> #include <errno.h> - #include <locale.h> #include <glib.h> #include "ck-tty-idle-monitor.h" +#include "ck-sysdeps.h" static void idle_changed_cb (CkTtyIdleMonitor *monitor, @@ -42,6 +46,26 @@ idle_changed_cb (CkTtyIdleMonitor *monitor, g_message ("idle hint changed: %s", idle_hint ? "idle" : "not idle"); } +static gboolean +is_console (const char *device) +{ + int fd; + gboolean ret; + + ret = FALSE; + fd = open (device, O_RDONLY | O_NOCTTY); + if (fd < 0) { + goto out; + } + + ret = ck_fd_is_a_console (fd); + + close (fd); + + out: + return ret; +} + int main (int argc, char **argv) { @@ -52,15 +76,18 @@ main (int argc, char **argv) g_type_init (); if (argc < 2) { - device = g_file_read_link ("/proc/self/fd/0", NULL); - if (device == NULL) { - g_warning ("%s not a link", "/proc/self/fd/0"); - exit (1); - } + device = ttyname (0); } else { device = g_strdup (argv[1]); } + if (! is_console (device)) { + g_warning ("Device is not a console"); + exit (1); + } + + g_message ("Testing the TTY idle monitor.\n1. Wait for idleness to be detected.\n2. Hit keys on the keyboard to see if activity is noticed."); + monitor = ck_tty_idle_monitor_new (device); g_signal_connect (monitor, diff --git a/src/test-vt-monitor.c b/src/test-vt-monitor.c new file mode 100644 index 0000000..c445865 --- /dev/null +++ b/src/test-vt-monitor.c @@ -0,0 +1,95 @@ +/* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*- + * + * Copyright (C) 2007 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 <sys/types.h> +#include <sys/stat.h> +#include <sys/ioctl.h> +#include <fcntl.h> +#include <pwd.h> +#include <string.h> +#include <errno.h> + +#include <locale.h> + +#include <glib.h> + +#include "ck-vt-monitor.h" +#include "ck-sysdeps.h" + +static void +activated_cb (CkVtMonitor *monitor, + guint num, + gpointer data) +{ + g_message ("VT %u activated", num); +} + +int +main (int argc, char **argv) +{ + GMainLoop *loop; + CkVtMonitor *monitor; + GError *error; + guint num; + gboolean res; + + if (! g_thread_supported ()) { + g_thread_init (NULL); + } + g_type_init (); + + if (! ck_is_root_user ()) { + g_warning ("Must be run as root"); + exit (1); + } + + g_message ("Testing the VT monitor.\n Should print messages when VT is switched."); + + monitor = ck_vt_monitor_new (); + + res = ck_vt_monitor_get_active (monitor, &num, &error); + if (! res) { + g_warning ("Couldn't determine active VT: %s", error->message); + exit (1); + } + + g_message ("VT %u is currently active", num); + + g_signal_connect (monitor, + "active-changed", + G_CALLBACK (activated_cb), + NULL); + + loop = g_main_loop_new (NULL, FALSE); + + g_main_loop_run (loop); + + g_object_unref (monitor); + + g_main_loop_unref (loop); + + return 0; +} |