diff options
author | Simon McVittie <smcv@debian.org> | 2011-01-31 17:37:59 +0000 |
---|---|---|
committer | Simon McVittie <smcv@debian.org> | 2011-01-31 17:37:59 +0000 |
commit | 24fbe571516161d48b499d587f9adb3e683dbf88 (patch) | |
tree | 7d70909156dcf587d91f693b8e1216eb4e0465e1 /tools | |
parent | 9b72896b3730a9fceb961be28bb95762a7b4e9d6 (diff) | |
download | dbus-24fbe571516161d48b499d587f9adb3e683dbf88.tar.gz |
Imported Upstream version 1.2.24upstream/1.2.24
Diffstat (limited to 'tools')
-rw-r--r-- | tools/Makefile.am | 47 | ||||
-rw-r--r-- | tools/Makefile.in | 797 | ||||
-rw-r--r-- | tools/dbus-cleanup-sockets.1 | 43 | ||||
-rw-r--r-- | tools/dbus-cleanup-sockets.c | 431 | ||||
-rw-r--r-- | tools/dbus-launch-x11.c | 463 | ||||
-rw-r--r-- | tools/dbus-launch.1 | 183 | ||||
-rw-r--r-- | tools/dbus-launch.c | 1214 | ||||
-rw-r--r-- | tools/dbus-launch.h | 58 | ||||
-rw-r--r-- | tools/dbus-monitor.1 | 78 | ||||
-rw-r--r-- | tools/dbus-monitor.c | 354 | ||||
-rw-r--r-- | tools/dbus-print-message.c | 407 | ||||
-rw-r--r-- | tools/dbus-print-message.h | 31 | ||||
-rw-r--r-- | tools/dbus-send.1 | 95 | ||||
-rw-r--r-- | tools/dbus-send.c | 526 | ||||
-rw-r--r-- | tools/dbus-uuidgen.1 | 89 | ||||
-rw-r--r-- | tools/dbus-uuidgen.c | 161 | ||||
-rwxr-xr-x | tools/run-with-tmp-session-bus.sh | 76 |
17 files changed, 5053 insertions, 0 deletions
diff --git a/tools/Makefile.am b/tools/Makefile.am new file mode 100644 index 00000000..9fad7a78 --- /dev/null +++ b/tools/Makefile.am @@ -0,0 +1,47 @@ +configdir=$(sysconfdir)/dbus-1 + +INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"@EXPANDED_DATADIR@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\" -DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" + +bin_PROGRAMS=dbus-send dbus-monitor dbus-launch dbus-cleanup-sockets dbus-uuidgen + +dbus_send_SOURCES= \ + dbus-print-message.c \ + dbus-print-message.h \ + dbus-send.c + +dbus_monitor_SOURCES= \ + dbus-monitor.c \ + dbus-print-message.c \ + dbus-print-message.h + +dbus_launch_SOURCES= \ + dbus-launch.c \ + dbus-launch-x11.c \ + dbus-launch.h + +dbus_cleanup_sockets_SOURCES= \ + dbus-cleanup-sockets.c + +dbus_uuidgen_SOURCES= \ + dbus-uuidgen.c + +dbus_send_LDADD= $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS) +dbus_send_LDFLAGS=@R_DYNAMIC_LDFLAG@ + +dbus_monitor_LDADD= $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS) +dbus_monitor_LDFLAGS=@R_DYNAMIC_LDFLAG@ + +dbus_uuidgen_LDADD= $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS) +dbus_uuidgen_LDFLAGS=@R_DYNAMIC_LDFLAG@ + +dbus_launch_LDADD= $(DBUS_X_LIBS) $(DBUS_CLIENT_LIBS) +dbus_launch_LDFLAGS=@R_DYNAMIC_LDFLAG@ + +man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1 dbus-uuidgen.1 +EXTRA_DIST = $(man_MANS) run-with-tmp-session-bus.sh +CLEANFILES = \ + run-with-tmp-session-bus.conf + +#create the /var/lib/data directory for dbus-uuidgen +localstatelibdir = $(localstatedir)/lib/dbus +localstatelib_DATA = diff --git a/tools/Makefile.in b/tools/Makefile.in new file mode 100644 index 00000000..14d048bc --- /dev/null +++ b/tools/Makefile.in @@ -0,0 +1,797 @@ +# Makefile.in generated by automake 1.11.1 from Makefile.am. +# @configure_input@ + +# Copyright (C) 1994, 1995, 1996, 1997, 1998, 1999, 2000, 2001, 2002, +# 2003, 2004, 2005, 2006, 2007, 2008, 2009 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@ + + +VPATH = @srcdir@ +pkgdatadir = $(datadir)/@PACKAGE@ +pkgincludedir = $(includedir)/@PACKAGE@ +pkglibdir = $(libdir)/@PACKAGE@ +pkglibexecdir = $(libexecdir)/@PACKAGE@ +am__cd = CDPATH="$${ZSH_VERSION+.}$(PATH_SEPARATOR)" && cd +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@ +bin_PROGRAMS = dbus-send$(EXEEXT) dbus-monitor$(EXEEXT) \ + dbus-launch$(EXEEXT) dbus-cleanup-sockets$(EXEEXT) \ + dbus-uuidgen$(EXEEXT) +subdir = tools +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.in +am__configure_deps = $(am__aclocal_m4_deps) $(CONFIGURE_DEPENDENCIES) \ + $(ACLOCAL_M4) +mkinstalldirs = $(install_sh) -d +CONFIG_HEADER = $(top_builddir)/config.h +CONFIG_CLEAN_FILES = +CONFIG_CLEAN_VPATH_FILES = +am__installdirs = "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" \ + "$(DESTDIR)$(localstatelibdir)" +PROGRAMS = $(bin_PROGRAMS) +am_dbus_cleanup_sockets_OBJECTS = dbus-cleanup-sockets.$(OBJEXT) +dbus_cleanup_sockets_OBJECTS = $(am_dbus_cleanup_sockets_OBJECTS) +dbus_cleanup_sockets_LDADD = $(LDADD) +AM_V_lt = $(am__v_lt_$(V)) +am__v_lt_ = $(am__v_lt_$(AM_DEFAULT_VERBOSITY)) +am__v_lt_0 = --silent +am_dbus_launch_OBJECTS = dbus-launch.$(OBJEXT) \ + dbus-launch-x11.$(OBJEXT) +dbus_launch_OBJECTS = $(am_dbus_launch_OBJECTS) +am__DEPENDENCIES_1 = +dbus_launch_DEPENDENCIES = $(am__DEPENDENCIES_1) $(am__DEPENDENCIES_1) +dbus_launch_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(dbus_launch_LDFLAGS) $(LDFLAGS) -o $@ +am_dbus_monitor_OBJECTS = dbus-monitor.$(OBJEXT) \ + dbus-print-message.$(OBJEXT) +dbus_monitor_OBJECTS = $(am_dbus_monitor_OBJECTS) +dbus_monitor_DEPENDENCIES = $(top_builddir)/dbus/libdbus-1.la \ + $(am__DEPENDENCIES_1) +dbus_monitor_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(dbus_monitor_LDFLAGS) $(LDFLAGS) -o $@ +am_dbus_send_OBJECTS = dbus-print-message.$(OBJEXT) \ + dbus-send.$(OBJEXT) +dbus_send_OBJECTS = $(am_dbus_send_OBJECTS) +dbus_send_DEPENDENCIES = $(top_builddir)/dbus/libdbus-1.la \ + $(am__DEPENDENCIES_1) +dbus_send_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(dbus_send_LDFLAGS) $(LDFLAGS) -o $@ +am_dbus_uuidgen_OBJECTS = dbus-uuidgen.$(OBJEXT) +dbus_uuidgen_OBJECTS = $(am_dbus_uuidgen_OBJECTS) +dbus_uuidgen_DEPENDENCIES = $(top_builddir)/dbus/libdbus-1.la \ + $(am__DEPENDENCIES_1) +dbus_uuidgen_LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(dbus_uuidgen_LDFLAGS) $(LDFLAGS) -o $@ +DEFAULT_INCLUDES = -I.@am__isrc@ -I$(top_builddir) +depcomp = $(SHELL) $(top_srcdir)/depcomp +am__depfiles_maybe = depfiles +am__mv = mv -f +COMPILE = $(CC) $(DEFS) $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) \ + $(CPPFLAGS) $(AM_CFLAGS) $(CFLAGS) +LTCOMPILE = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=compile $(CC) $(DEFS) \ + $(DEFAULT_INCLUDES) $(INCLUDES) $(AM_CPPFLAGS) $(CPPFLAGS) \ + $(AM_CFLAGS) $(CFLAGS) +AM_V_CC = $(am__v_CC_$(V)) +am__v_CC_ = $(am__v_CC_$(AM_DEFAULT_VERBOSITY)) +am__v_CC_0 = @echo " CC " $@; +AM_V_at = $(am__v_at_$(V)) +am__v_at_ = $(am__v_at_$(AM_DEFAULT_VERBOSITY)) +am__v_at_0 = @ +CCLD = $(CC) +LINK = $(LIBTOOL) $(AM_V_lt) --tag=CC $(AM_LIBTOOLFLAGS) \ + $(LIBTOOLFLAGS) --mode=link $(CCLD) $(AM_CFLAGS) $(CFLAGS) \ + $(AM_LDFLAGS) $(LDFLAGS) -o $@ +AM_V_CCLD = $(am__v_CCLD_$(V)) +am__v_CCLD_ = $(am__v_CCLD_$(AM_DEFAULT_VERBOSITY)) +am__v_CCLD_0 = @echo " CCLD " $@; +AM_V_GEN = $(am__v_GEN_$(V)) +am__v_GEN_ = $(am__v_GEN_$(AM_DEFAULT_VERBOSITY)) +am__v_GEN_0 = @echo " GEN " $@; +SOURCES = $(dbus_cleanup_sockets_SOURCES) $(dbus_launch_SOURCES) \ + $(dbus_monitor_SOURCES) $(dbus_send_SOURCES) \ + $(dbus_uuidgen_SOURCES) +DIST_SOURCES = $(dbus_cleanup_sockets_SOURCES) $(dbus_launch_SOURCES) \ + $(dbus_monitor_SOURCES) $(dbus_send_SOURCES) \ + $(dbus_uuidgen_SOURCES) +am__vpath_adj_setup = srcdirstrip=`echo "$(srcdir)" | sed 's|.|.|g'`; +am__vpath_adj = case $$p in \ + $(srcdir)/*) f=`echo "$$p" | sed "s|^$$srcdirstrip/||"`;; \ + *) f=$$p;; \ + esac; +am__strip_dir = f=`echo $$p | sed -e 's|^.*/||'`; +am__install_max = 40 +am__nobase_strip_setup = \ + srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*|]/\\\\&/g'` +am__nobase_strip = \ + for p in $$list; do echo "$$p"; done | sed -e "s|$$srcdirstrip/||" +am__nobase_list = $(am__nobase_strip_setup); \ + for p in $$list; do echo "$$p $$p"; done | \ + sed "s| $$srcdirstrip/| |;"' / .*\//!s/ .*/ ./; s,\( .*\)/[^/]*$$,\1,' | \ + $(AWK) 'BEGIN { files["."] = "" } { files[$$2] = files[$$2] " " $$1; \ + if (++n[$$2] == $(am__install_max)) \ + { print $$2, files[$$2]; n[$$2] = 0; files[$$2] = "" } } \ + END { for (dir in files) print dir, files[dir] }' +am__base_list = \ + sed '$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;$$!N;s/\n/ /g' | \ + sed '$$!N;$$!N;$$!N;$$!N;s/\n/ /g' +man1dir = $(mandir)/man1 +NROFF = nroff +MANS = $(man_MANS) +DATA = $(localstatelib_DATA) +ETAGS = etags +CTAGS = ctags +DISTFILES = $(DIST_COMMON) $(DIST_SOURCES) $(TEXINFOS) $(EXTRA_DIST) +ACLOCAL = @ACLOCAL@ +AMTAR = @AMTAR@ +AM_DEFAULT_VERBOSITY = @AM_DEFAULT_VERBOSITY@ +AR = @AR@ +AUTOCONF = @AUTOCONF@ +AUTOHEADER = @AUTOHEADER@ +AUTOMAKE = @AUTOMAKE@ +AWK = @AWK@ +CC = @CC@ +CCDEPMODE = @CCDEPMODE@ +CFLAGS = @CFLAGS@ +CPP = @CPP@ +CPPFLAGS = @CPPFLAGS@ +CXX = @CXX@ +CXXCPP = @CXXCPP@ +CXXDEPMODE = @CXXDEPMODE@ +CXXFLAGS = @CXXFLAGS@ +CYGPATH_W = @CYGPATH_W@ +DBUS_BINDIR = @DBUS_BINDIR@ +DBUS_BUS_CFLAGS = @DBUS_BUS_CFLAGS@ +DBUS_BUS_LIBS = @DBUS_BUS_LIBS@ +DBUS_CLIENT_CFLAGS = @DBUS_CLIENT_CFLAGS@ +DBUS_CLIENT_LIBS = @DBUS_CLIENT_LIBS@ +DBUS_CONSOLE_AUTH_DIR = @DBUS_CONSOLE_AUTH_DIR@ +DBUS_CONSOLE_OWNER_FILE = @DBUS_CONSOLE_OWNER_FILE@ +DBUS_DAEMONDIR = @DBUS_DAEMONDIR@ +DBUS_DATADIR = @DBUS_DATADIR@ +DBUS_HAVE_INT64 = @DBUS_HAVE_INT64@ +DBUS_INT16_TYPE = @DBUS_INT16_TYPE@ +DBUS_INT32_TYPE = @DBUS_INT32_TYPE@ +DBUS_INT64_CONSTANT = @DBUS_INT64_CONSTANT@ +DBUS_INT64_TYPE = @DBUS_INT64_TYPE@ +DBUS_LAUNCHER_CFLAGS = @DBUS_LAUNCHER_CFLAGS@ +DBUS_LAUNCHER_LIBS = @DBUS_LAUNCHER_LIBS@ +DBUS_LIBEXECDIR = @DBUS_LIBEXECDIR@ +DBUS_MAJOR_VERSION = @DBUS_MAJOR_VERSION@ +DBUS_MICRO_VERSION = @DBUS_MICRO_VERSION@ +DBUS_MINOR_VERSION = @DBUS_MINOR_VERSION@ +DBUS_PATH_OR_ABSTRACT = @DBUS_PATH_OR_ABSTRACT@ +DBUS_SESSION_SOCKET_DIR = @DBUS_SESSION_SOCKET_DIR@ +DBUS_SYSTEM_BUS_DEFAULT_ADDRESS = @DBUS_SYSTEM_BUS_DEFAULT_ADDRESS@ +DBUS_SYSTEM_PID_FILE = @DBUS_SYSTEM_PID_FILE@ +DBUS_SYSTEM_SOCKET = @DBUS_SYSTEM_SOCKET@ +DBUS_TEST_CFLAGS = @DBUS_TEST_CFLAGS@ +DBUS_TEST_LIBS = @DBUS_TEST_LIBS@ +DBUS_UINT64_CONSTANT = @DBUS_UINT64_CONSTANT@ +DBUS_USER = @DBUS_USER@ +DBUS_VERSION = @DBUS_VERSION@ +DBUS_X_CFLAGS = @DBUS_X_CFLAGS@ +DBUS_X_LIBS = @DBUS_X_LIBS@ +DEFS = @DEFS@ +DEPDIR = @DEPDIR@ +DOXYGEN = @DOXYGEN@ +DSYMUTIL = @DSYMUTIL@ +DUMPBIN = @DUMPBIN@ +ECHO_C = @ECHO_C@ +ECHO_N = @ECHO_N@ +ECHO_T = @ECHO_T@ +EGREP = @EGREP@ +EXEEXT = @EXEEXT@ +EXPANDED_BINDIR = @EXPANDED_BINDIR@ +EXPANDED_DATADIR = @EXPANDED_DATADIR@ +EXPANDED_LIBDIR = @EXPANDED_LIBDIR@ +EXPANDED_LIBEXECDIR = @EXPANDED_LIBEXECDIR@ +EXPANDED_LOCALSTATEDIR = @EXPANDED_LOCALSTATEDIR@ +EXPANDED_SYSCONFDIR = @EXPANDED_SYSCONFDIR@ +FGREP = @FGREP@ +GETTEXT_PACKAGE = @GETTEXT_PACKAGE@ +GREP = @GREP@ +INSTALL = @INSTALL@ +INSTALL_DATA = @INSTALL_DATA@ +INSTALL_PROGRAM = @INSTALL_PROGRAM@ +INSTALL_SCRIPT = @INSTALL_SCRIPT@ +INSTALL_STRIP_PROGRAM = @INSTALL_STRIP_PROGRAM@ +LD = @LD@ +LDFLAGS = @LDFLAGS@ +LIBOBJS = @LIBOBJS@ +LIBS = @LIBS@ +LIBTOOL = @LIBTOOL@ +LIBXML_CFLAGS = @LIBXML_CFLAGS@ +LIBXML_LIBS = @LIBXML_LIBS@ +LIPO = @LIPO@ +LN_S = @LN_S@ +LTLIBOBJS = @LTLIBOBJS@ +LT_AGE = @LT_AGE@ +LT_CURRENT = @LT_CURRENT@ +LT_REVISION = @LT_REVISION@ +MAINT = @MAINT@ +MAKEINFO = @MAKEINFO@ +MKDIR_P = @MKDIR_P@ +NM = @NM@ +NMEDIT = @NMEDIT@ +OBJDUMP = @OBJDUMP@ +OBJEXT = @OBJEXT@ +OTOOL = @OTOOL@ +OTOOL64 = @OTOOL64@ +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@ +PIC_CFLAGS = @PIC_CFLAGS@ +PIC_LDFLAGS = @PIC_LDFLAGS@ +PIE_CFLAGS = @PIE_CFLAGS@ +PIE_LDFLAGS = @PIE_LDFLAGS@ +PKG_CONFIG = @PKG_CONFIG@ +RANLIB = @RANLIB@ +R_DYNAMIC_LDFLAG = @R_DYNAMIC_LDFLAG@ +SECTION_FLAGS = @SECTION_FLAGS@ +SECTION_LDFLAGS = @SECTION_LDFLAGS@ +SED = @SED@ +SET_MAKE = @SET_MAKE@ +SHELL = @SHELL@ +STRIP = @STRIP@ +TEST_BUS_BINARY = @TEST_BUS_BINARY@ +TEST_EXIT_BINARY = @TEST_EXIT_BINARY@ +TEST_INVALID_SERVICE_DIR = @TEST_INVALID_SERVICE_DIR@ +TEST_INVALID_SERVICE_SYSTEM_DIR = @TEST_INVALID_SERVICE_SYSTEM_DIR@ +TEST_LAUNCH_HELPER_BINARY = @TEST_LAUNCH_HELPER_BINARY@ +TEST_PRIVSERVER_BINARY = @TEST_PRIVSERVER_BINARY@ +TEST_SEGFAULT_BINARY = @TEST_SEGFAULT_BINARY@ +TEST_SERVICE_BINARY = @TEST_SERVICE_BINARY@ +TEST_SHELL_SERVICE_BINARY = @TEST_SHELL_SERVICE_BINARY@ +TEST_SLEEP_FOREVER_BINARY = @TEST_SLEEP_FOREVER_BINARY@ +TEST_SOCKET_DIR = @TEST_SOCKET_DIR@ +TEST_VALID_SERVICE_DIR = @TEST_VALID_SERVICE_DIR@ +TEST_VALID_SERVICE_SYSTEM_DIR = @TEST_VALID_SERVICE_SYSTEM_DIR@ +VERSION = @VERSION@ +XMKMF = @XMKMF@ +XMLTO = @XMLTO@ +X_CFLAGS = @X_CFLAGS@ +X_EXTRA_LIBS = @X_EXTRA_LIBS@ +X_LIBS = @X_LIBS@ +X_PRE_LIBS = @X_PRE_LIBS@ +abs_builddir = @abs_builddir@ +abs_srcdir = @abs_srcdir@ +abs_top_builddir = @abs_top_builddir@ +abs_top_srcdir = @abs_top_srcdir@ +ac_ct_CC = @ac_ct_CC@ +ac_ct_CXX = @ac_ct_CXX@ +ac_ct_DUMPBIN = @ac_ct_DUMPBIN@ +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@ +builddir = @builddir@ +datadir = @datadir@ +datarootdir = @datarootdir@ +docdir = @docdir@ +dvidir = @dvidir@ +exec_prefix = @exec_prefix@ +host = @host@ +host_alias = @host_alias@ +host_cpu = @host_cpu@ +host_os = @host_os@ +host_vendor = @host_vendor@ +htmldir = @htmldir@ +includedir = @includedir@ +infodir = @infodir@ +install_sh = @install_sh@ +libdir = @libdir@ +libexecdir = @libexecdir@ +localedir = @localedir@ +localstatedir = @localstatedir@ +lt_ECHO = @lt_ECHO@ +mandir = @mandir@ +mkdir_p = @mkdir_p@ +oldincludedir = @oldincludedir@ +pdfdir = @pdfdir@ +prefix = @prefix@ +program_transform_name = @program_transform_name@ +psdir = @psdir@ +sbindir = @sbindir@ +sharedstatedir = @sharedstatedir@ +srcdir = @srcdir@ +sysconfdir = @sysconfdir@ +target_alias = @target_alias@ +top_build_prefix = @top_build_prefix@ +top_builddir = @top_builddir@ +top_srcdir = @top_srcdir@ +configdir = $(sysconfdir)/dbus-1 +INCLUDES = -I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) $(DBUS_X_CFLAGS) -DDBUS_LOCALEDIR=\"@EXPANDED_DATADIR@/locale\" -DDBUS_COMPILATION -DDBUS_DAEMONDIR=\"@DBUS_DAEMONDIR@\" -DDBUS_MACHINE_UUID_FILE=\""$(localstatedir)/lib/dbus/machine-id"\" +dbus_send_SOURCES = \ + dbus-print-message.c \ + dbus-print-message.h \ + dbus-send.c + +dbus_monitor_SOURCES = \ + dbus-monitor.c \ + dbus-print-message.c \ + dbus-print-message.h + +dbus_launch_SOURCES = \ + dbus-launch.c \ + dbus-launch-x11.c \ + dbus-launch.h + +dbus_cleanup_sockets_SOURCES = \ + dbus-cleanup-sockets.c + +dbus_uuidgen_SOURCES = \ + dbus-uuidgen.c + +dbus_send_LDADD = $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS) +dbus_send_LDFLAGS = @R_DYNAMIC_LDFLAG@ +dbus_monitor_LDADD = $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS) +dbus_monitor_LDFLAGS = @R_DYNAMIC_LDFLAG@ +dbus_uuidgen_LDADD = $(top_builddir)/dbus/libdbus-1.la $(DBUS_CLIENT_LIBS) +dbus_uuidgen_LDFLAGS = @R_DYNAMIC_LDFLAG@ +dbus_launch_LDADD = $(DBUS_X_LIBS) $(DBUS_CLIENT_LIBS) +dbus_launch_LDFLAGS = @R_DYNAMIC_LDFLAG@ +man_MANS = dbus-send.1 dbus-monitor.1 dbus-launch.1 dbus-cleanup-sockets.1 dbus-uuidgen.1 +EXTRA_DIST = $(man_MANS) run-with-tmp-session-bus.sh +CLEANFILES = \ + run-with-tmp-session-bus.conf + + +#create the /var/lib/data directory for dbus-uuidgen +localstatelibdir = $(localstatedir)/lib/dbus +localstatelib_DATA = +all: all-am + +.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 ) \ + && { if test -f $@; then exit 0; else break; fi; }; \ + exit 1;; \ + esac; \ + done; \ + echo ' cd $(top_srcdir) && $(AUTOMAKE) --gnu tools/Makefile'; \ + $(am__cd) $(top_srcdir) && \ + $(AUTOMAKE) --gnu tools/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 +$(am__aclocal_m4_deps): +install-binPROGRAMS: $(bin_PROGRAMS) + @$(NORMAL_INSTALL) + test -z "$(bindir)" || $(MKDIR_P) "$(DESTDIR)$(bindir)" + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + for p in $$list; do echo "$$p $$p"; done | \ + sed 's/$(EXEEXT)$$//' | \ + while read p p1; do if test -f $$p || test -f $$p1; \ + then echo "$$p"; echo "$$p"; else :; fi; \ + done | \ + sed -e 'p;s,.*/,,;n;h' -e 's|.*|.|' \ + -e 'p;x;s,.*/,,;s/$(EXEEXT)$$//;$(transform);s/$$/$(EXEEXT)/' | \ + sed 'N;N;N;s,\n, ,g' | \ + $(AWK) 'BEGIN { files["."] = ""; dirs["."] = 1 } \ + { d=$$3; if (dirs[d] != 1) { print "d", d; dirs[d] = 1 } \ + if ($$2 == $$4) files[d] = files[d] " " $$1; \ + else { print "f", $$3 "/" $$4, $$1; } } \ + END { for (d in files) print "f", d, files[d] }' | \ + while read type dir files; do \ + if test "$$dir" = .; then dir=; else dir=/$$dir; fi; \ + test -z "$$files" || { \ + echo " $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files '$(DESTDIR)$(bindir)$$dir'"; \ + $(INSTALL_PROGRAM_ENV) $(LIBTOOL) $(AM_LIBTOOLFLAGS) $(LIBTOOLFLAGS) --mode=install $(INSTALL_PROGRAM) $$files "$(DESTDIR)$(bindir)$$dir" || exit $$?; \ + } \ + ; done + +uninstall-binPROGRAMS: + @$(NORMAL_UNINSTALL) + @list='$(bin_PROGRAMS)'; test -n "$(bindir)" || list=; \ + files=`for p in $$list; do echo "$$p"; done | \ + sed -e 'h;s,^.*/,,;s/$(EXEEXT)$$//;$(transform)' \ + -e 's/$$/$(EXEEXT)/' `; \ + test -n "$$list" || exit 0; \ + echo " ( cd '$(DESTDIR)$(bindir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(bindir)" && rm -f $$files + +clean-binPROGRAMS: + @list='$(bin_PROGRAMS)'; test -n "$$list" || exit 0; \ + echo " rm -f" $$list; \ + rm -f $$list || exit $$?; \ + test -n "$(EXEEXT)" || exit 0; \ + list=`for p in $$list; do echo "$$p"; done | sed 's/$(EXEEXT)$$//'`; \ + echo " rm -f" $$list; \ + rm -f $$list +dbus-cleanup-sockets$(EXEEXT): $(dbus_cleanup_sockets_OBJECTS) $(dbus_cleanup_sockets_DEPENDENCIES) + @rm -f dbus-cleanup-sockets$(EXEEXT) + $(AM_V_CCLD)$(LINK) $(dbus_cleanup_sockets_OBJECTS) $(dbus_cleanup_sockets_LDADD) $(LIBS) +dbus-launch$(EXEEXT): $(dbus_launch_OBJECTS) $(dbus_launch_DEPENDENCIES) + @rm -f dbus-launch$(EXEEXT) + $(AM_V_CCLD)$(dbus_launch_LINK) $(dbus_launch_OBJECTS) $(dbus_launch_LDADD) $(LIBS) +dbus-monitor$(EXEEXT): $(dbus_monitor_OBJECTS) $(dbus_monitor_DEPENDENCIES) + @rm -f dbus-monitor$(EXEEXT) + $(AM_V_CCLD)$(dbus_monitor_LINK) $(dbus_monitor_OBJECTS) $(dbus_monitor_LDADD) $(LIBS) +dbus-send$(EXEEXT): $(dbus_send_OBJECTS) $(dbus_send_DEPENDENCIES) + @rm -f dbus-send$(EXEEXT) + $(AM_V_CCLD)$(dbus_send_LINK) $(dbus_send_OBJECTS) $(dbus_send_LDADD) $(LIBS) +dbus-uuidgen$(EXEEXT): $(dbus_uuidgen_OBJECTS) $(dbus_uuidgen_DEPENDENCIES) + @rm -f dbus-uuidgen$(EXEEXT) + $(AM_V_CCLD)$(dbus_uuidgen_LINK) $(dbus_uuidgen_OBJECTS) $(dbus_uuidgen_LDADD) $(LIBS) + +mostlyclean-compile: + -rm -f *.$(OBJEXT) + +distclean-compile: + -rm -f *.tab.c + +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-cleanup-sockets.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-launch-x11.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-launch.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-monitor.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-print-message.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-send.Po@am__quote@ +@AMDEP_TRUE@@am__include@ @am__quote@./$(DEPDIR)/dbus-uuidgen.Po@am__quote@ + +.c.o: +@am__fastdepCC_TRUE@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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@ $(AM_V_CC)$(COMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ `$(CYGPATH_W) '$<'` +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Po +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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@ $(AM_V_CC)$(LTCOMPILE) -MT $@ -MD -MP -MF $(DEPDIR)/$*.Tpo -c -o $@ $< +@am__fastdepCC_TRUE@ $(AM_V_at)$(am__mv) $(DEPDIR)/$*.Tpo $(DEPDIR)/$*.Plo +@am__fastdepCC_FALSE@ $(AM_V_CC) @AM_BACKSLASH@ +@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 +install-man1: $(man_MANS) + @$(NORMAL_INSTALL) + test -z "$(man1dir)" || $(MKDIR_P) "$(DESTDIR)$(man1dir)" + @list=''; test -n "$(man1dir)" || exit 0; \ + { for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | while read p; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; echo "$$p"; \ + done | \ + sed -e 'n;s,.*/,,;p;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,' | \ + sed 'N;N;s,\n, ,g' | { \ + list=; while read file base inst; do \ + if test "$$base" = "$$inst"; then list="$$list $$file"; else \ + echo " $(INSTALL_DATA) '$$file' '$(DESTDIR)$(man1dir)/$$inst'"; \ + $(INSTALL_DATA) "$$file" "$(DESTDIR)$(man1dir)/$$inst" || exit $$?; \ + fi; \ + done; \ + for i in $$list; do echo "$$i"; done | $(am__base_list) | \ + while read files; do \ + test -z "$$files" || { \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(man1dir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(man1dir)" || exit $$?; }; \ + done; } + +uninstall-man1: + @$(NORMAL_UNINSTALL) + @list=''; test -n "$(man1dir)" || exit 0; \ + files=`{ for i in $$list; do echo "$$i"; done; \ + l2='$(man_MANS)'; for i in $$l2; do echo "$$i"; done | \ + sed -n '/\.1[a-z]*$$/p'; \ + } | sed -e 's,.*/,,;h;s,.*\.,,;s,^[^1][0-9a-z]*$$,1,;x' \ + -e 's,\.[0-9a-z]*$$,,;$(transform);G;s,\n,.,'`; \ + test -z "$$files" || { \ + echo " ( cd '$(DESTDIR)$(man1dir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(man1dir)" && rm -f $$files; } +install-localstatelibDATA: $(localstatelib_DATA) + @$(NORMAL_INSTALL) + test -z "$(localstatelibdir)" || $(MKDIR_P) "$(DESTDIR)$(localstatelibdir)" + @list='$(localstatelib_DATA)'; test -n "$(localstatelibdir)" || list=; \ + for p in $$list; do \ + if test -f "$$p"; then d=; else d="$(srcdir)/"; fi; \ + echo "$$d$$p"; \ + done | $(am__base_list) | \ + while read files; do \ + echo " $(INSTALL_DATA) $$files '$(DESTDIR)$(localstatelibdir)'"; \ + $(INSTALL_DATA) $$files "$(DESTDIR)$(localstatelibdir)" || exit $$?; \ + done + +uninstall-localstatelibDATA: + @$(NORMAL_UNINSTALL) + @list='$(localstatelib_DATA)'; test -n "$(localstatelibdir)" || list=; \ + files=`for p in $$list; do echo $$p; done | sed -e 's|^.*/||'`; \ + test -n "$$files" || exit 0; \ + echo " ( cd '$(DESTDIR)$(localstatelibdir)' && rm -f" $$files ")"; \ + cd "$(DESTDIR)$(localstatelibdir)" && rm -f $$files + +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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + mkid -fID $$unique +tags: TAGS + +TAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + set x; \ + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + shift; \ + if test -z "$(ETAGS_ARGS)$$*$$unique"; then :; else \ + test -n "$$unique" || unique=$$empty_fix; \ + if test $$# -gt 0; then \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + "$$@" $$unique; \ + else \ + $(ETAGS) $(ETAGSFLAGS) $(AM_ETAGSFLAGS) $(ETAGS_ARGS) \ + $$unique; \ + fi; \ + fi +ctags: CTAGS +CTAGS: $(HEADERS) $(SOURCES) $(TAGS_DEPENDENCIES) \ + $(TAGS_FILES) $(LISP) + 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; nonempty = 1; } \ + END { if (nonempty) { for (i in files) print i; }; }'`; \ + test -z "$(CTAGS_ARGS)$$unique" \ + || $(CTAGS) $(CTAGSFLAGS) $(AM_CTAGSFLAGS) $(CTAGS_ARGS) \ + $$unique + +GTAGS: + here=`$(am__cd) $(top_builddir) && pwd` \ + && $(am__cd) $(top_srcdir) \ + && gtags -i $(GTAGS_ARGS) "$$here" + +distclean-tags: + -rm -f TAGS ID GTAGS GRTAGS GSYMS GPATH tags + +distdir: $(DISTFILES) + @list='$(MANS)'; if test -n "$$list"; then \ + list=`for p in $$list; do \ + if test -f $$p; then d=; else d="$(srcdir)/"; fi; \ + if test -f "$$d$$p"; then echo "$$d$$p"; else :; fi; done`; \ + if test -n "$$list" && \ + grep 'ab help2man is required to generate this page' $$list >/dev/null; then \ + echo "error: found man pages containing the \`missing help2man' replacement text:" >&2; \ + grep -l 'ab help2man is required to generate this page' $$list | sed 's/^/ /' >&2; \ + echo " to fix them, install help2man, remove and regenerate the man pages;" >&2; \ + echo " typically \`make maintainer-clean' will remove them" >&2; \ + exit 1; \ + else :; fi; \ + else :; fi + @srcdirstrip=`echo "$(srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + topsrcdirstrip=`echo "$(top_srcdir)" | sed 's/[].[^$$\\*]/\\\\&/g'`; \ + list='$(DISTFILES)'; \ + dist_files=`for file in $$list; do echo $$file; done | \ + sed -e "s|^$$srcdirstrip/||;t" \ + -e "s|^$$topsrcdirstrip/|$(top_builddir)/|;t"`; \ + case $$dist_files in \ + */*) $(MKDIR_P) `echo "$$dist_files" | \ + sed '/\//!d;s|^|$(distdir)/|;s,/[^/]*$$,,' | \ + sort -u` ;; \ + esac; \ + for file in $$dist_files; do \ + if test -f $$file || test -d $$file; then d=.; else d=$(srcdir); fi; \ + if test -d $$d/$$file; then \ + dir=`echo "/$$file" | sed -e 's,/[^/]*$$,,'`; \ + if test -d "$(distdir)/$$file"; then \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + if test -d $(srcdir)/$$file && test $$d != $(srcdir); then \ + cp -fpR $(srcdir)/$$file "$(distdir)$$dir" || exit 1; \ + find "$(distdir)/$$file" -type d ! -perm -700 -exec chmod u+rwx {} \;; \ + fi; \ + cp -fpR $$d/$$file "$(distdir)$$dir" || exit 1; \ + else \ + test -f "$(distdir)/$$file" \ + || cp -p $$d/$$file "$(distdir)/$$file" \ + || exit 1; \ + fi; \ + done +check-am: all-am +check: check-am +all-am: Makefile $(PROGRAMS) $(MANS) $(DATA) +installdirs: + for dir in "$(DESTDIR)$(bindir)" "$(DESTDIR)$(man1dir)" "$(DESTDIR)$(localstatelibdir)"; do \ + test -z "$$dir" || $(MKDIR_P) "$$dir"; \ + done +install: install-am +install-exec: install-exec-am +install-data: install-data-am +uninstall: uninstall-am + +install-am: all-am + @$(MAKE) $(AM_MAKEFLAGS) install-exec-am install-data-am + +installcheck: installcheck-am +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) + -test . = "$(srcdir)" || test -z "$(CONFIG_CLEAN_VPATH_FILES)" || rm -f $(CONFIG_CLEAN_VPATH_FILES) + +maintainer-clean-generic: + @echo "This command is intended for maintainers to use" + @echo "it deletes files that may require special tools to rebuild." +clean: clean-am + +clean-am: clean-binPROGRAMS clean-generic clean-libtool mostlyclean-am + +distclean: distclean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +distclean-am: clean-am distclean-compile distclean-generic \ + distclean-tags + +dvi: dvi-am + +dvi-am: + +html: html-am + +html-am: + +info: info-am + +info-am: + +install-data-am: install-localstatelibDATA install-man + +install-dvi: install-dvi-am + +install-dvi-am: + +install-exec-am: install-binPROGRAMS + +install-html: install-html-am + +install-html-am: + +install-info: install-info-am + +install-info-am: + +install-man: install-man1 + +install-pdf: install-pdf-am + +install-pdf-am: + +install-ps: install-ps-am + +install-ps-am: + +installcheck-am: + +maintainer-clean: maintainer-clean-am + -rm -rf ./$(DEPDIR) + -rm -f Makefile +maintainer-clean-am: distclean-am maintainer-clean-generic + +mostlyclean: mostlyclean-am + +mostlyclean-am: mostlyclean-compile mostlyclean-generic \ + mostlyclean-libtool + +pdf: pdf-am + +pdf-am: + +ps: ps-am + +ps-am: + +uninstall-am: uninstall-binPROGRAMS uninstall-localstatelibDATA \ + uninstall-man + +uninstall-man: uninstall-man1 + +.MAKE: install-am install-strip + +.PHONY: CTAGS GTAGS all all-am check check-am clean clean-binPROGRAMS \ + clean-generic clean-libtool ctags distclean distclean-compile \ + distclean-generic distclean-libtool distclean-tags distdir dvi \ + dvi-am html html-am info info-am install install-am \ + install-binPROGRAMS install-data install-data-am install-dvi \ + install-dvi-am install-exec install-exec-am install-html \ + install-html-am install-info install-info-am \ + install-localstatelibDATA install-man install-man1 install-pdf \ + install-pdf-am install-ps install-ps-am install-strip \ + installcheck installcheck-am installdirs maintainer-clean \ + maintainer-clean-generic mostlyclean mostlyclean-compile \ + mostlyclean-generic mostlyclean-libtool pdf pdf-am ps ps-am \ + tags uninstall uninstall-am uninstall-binPROGRAMS \ + uninstall-localstatelibDATA uninstall-man uninstall-man1 + + +# 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/tools/dbus-cleanup-sockets.1 b/tools/dbus-cleanup-sockets.1 new file mode 100644 index 00000000..ca669f49 --- /dev/null +++ b/tools/dbus-cleanup-sockets.1 @@ -0,0 +1,43 @@ +.\" +.\" dbus-cleanup-sockets manual page. +.\" Copyright (C) 2003 Red Hat, Inc. +.\" +.TH dbus-cleanup-sockets 1 +.SH NAME +dbus-cleanup-sockets \- clean up leftover sockets in a directory +.SH SYNOPSIS +.PP +.B dbus-cleanup-sockets [DIRECTORY] + +.SH DESCRIPTION + +The \fIdbus-cleanup-sockets\fP command cleans up unused D-Bus +connection sockets. See http://www.freedesktop.org/software/dbus/ for +more information about the big picture. + +.PP +If given no arguments, \fIdbus-cleanup-sockets\fP cleans up sockets +in the standard default socket directory for the +per-user-login-session message bus; this is usually /tmp. +Optionally, you can pass a different directory on the command line. + +.PP +On Linux, this program is essentially useless, because D-Bus defaults +to using "abstract sockets" that exist only in memory and don't have a +corresponding file in /tmp. + +.PP +On most other flavors of UNIX, it's possible for the socket files to +leak when programs using D-Bus exit abnormally or without closing +their D-Bus connections. Thus, it might be interesting to run +dbus-cleanup-sockets in a cron job to mop up any leaked sockets. +Or you can just ignore the leaked sockets, they aren't really hurting +anything, other than cluttering the output of "ls /tmp" + +.SH AUTHOR +dbus-cleanup-sockets was adapted by Havoc Pennington from +linc-cleanup-sockets written by Michael Meeks. + +.SH BUGS +Please send bug reports to the D-Bus mailing list or bug tracker, +see http://www.freedesktop.org/software/dbus/ diff --git a/tools/dbus-cleanup-sockets.c b/tools/dbus-cleanup-sockets.c new file mode 100644 index 00000000..487c4b07 --- /dev/null +++ b/tools/dbus-cleanup-sockets.c @@ -0,0 +1,431 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-cleanup-sockets.c dbus-cleanup-sockets utility + * + * Copyright (C) 2003 Red Hat, Inc. + * Copyright (C) 2002 Michael Meeks + * + * Note that this file is NOT licensed under the Academic Free License, + * as it is based on linc-cleanup-sockets which is LGPL. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include <config.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <stdio.h> +#include <fcntl.h> +#include <unistd.h> +#include <dirent.h> +#include <sys/socket.h> +#include <sys/un.h> +#include <errno.h> +#include <stdlib.h> +#include <string.h> + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#ifndef NULL +#define NULL ((void*) 0) +#endif + +static void* +xmalloc (size_t bytes) +{ + void *mem; + + if (bytes == 0) + return NULL; + + mem = malloc (bytes); + + if (mem == NULL) + { + fprintf (stderr, "Allocation of %d bytes failed\n", + (int) bytes); + exit (1); + } + + return mem; +} + +static void* +xrealloc (void *old, size_t bytes) +{ + void *mem; + + if (bytes == 0) + { + free (old); + return NULL; + } + + mem = realloc (old, bytes); + + if (mem == NULL) + { + fprintf (stderr, "Reallocation of %d bytes failed\n", + (int) bytes); + exit (1); + } + + return mem; +} + +#ifdef AF_UNIX + +typedef enum + { + SOCKET_UNKNOWN, + SOCKET_FAILED_TO_HANDLE, + SOCKET_DEAD, + SOCKET_ALIVE, + SOCKET_UNLINKED + } SocketStatus; + +static int alive_count = 0; +static int cleaned_count = 0; +static int unhandled_count = 0; + +typedef struct +{ + char *name; + int fd; + SocketStatus status; + int n_retries; +} SocketEntry; + +static SocketEntry* +socket_entry_new (const char *dir, + const char *fname) +{ + SocketEntry *se; + int len; + + se = xmalloc (sizeof (SocketEntry)); + + len = strlen (dir) + strlen (fname) + 2; /* 2 = nul and '/' */ + se->name = xmalloc (len); + + strcpy (se->name, dir); + strcat (se->name, "/"); + strcat (se->name, fname); + + se->fd = -1; + + se->status = SOCKET_UNKNOWN; + + se->n_retries = 0; + + return se; +} + +#if 0 +static void +free_socket_entry (SocketEntry *se) +{ + free (se->name); + if (se->fd >= 0) + close (se->fd); + free (se); +} +#endif + +static void +read_sockets (const char *dir, + SocketEntry ***entries_p, + int *n_entries_p) +{ + DIR *dirh; + struct dirent *dent; + SocketEntry **entries; + int n_entries; + int allocated; + + n_entries = 0; + allocated = 2; + entries = xmalloc (sizeof (SocketEntry*) * allocated); + + dirh = opendir (dir); + if (dirh == NULL) + { + fprintf (stderr, "Failed to open directory %s: %s\n", + dir, strerror (errno)); + exit (1); + } + + while ((dent = readdir (dirh))) + { + SocketEntry *se; + + if (strncmp (dent->d_name, "dbus-", 5) != 0) + continue; + + se = socket_entry_new (dir, dent->d_name); + + if (n_entries == allocated) + { + allocated *= 2; + entries = xrealloc (entries, sizeof (SocketEntry*) * allocated); + } + + entries[n_entries] = se; + n_entries += 1; + } + + closedir (dirh); + + *entries_p = entries; + *n_entries_p = n_entries; +} + +static SocketStatus +open_socket (SocketEntry *se) +{ + int ret; + struct sockaddr_un saddr; + + if (se->n_retries > 5) + { + fprintf (stderr, "Warning: giving up on socket %s after several retries; unable to determine socket's status\n", + se->name); + return SOCKET_FAILED_TO_HANDLE; + } + + se->n_retries += 1; + + se->fd = socket (AF_UNIX, SOCK_STREAM, 0); + if (se->fd < 0) + { + fprintf (stderr, "Warning: failed to open a socket to use for connecting: %s\n", + strerror (errno)); + return SOCKET_UNKNOWN; + } + + if (fcntl (se->fd, F_SETFL, O_NONBLOCK) < 0) + { + fprintf (stderr, "Warning: failed set socket %s nonblocking: %s\n", + se->name, strerror (errno)); + return SOCKET_UNKNOWN; + } + + + memset (&saddr, '\0', sizeof (saddr)); /* nul-terminates the sun_path */ + + saddr.sun_family = AF_UNIX; + strncpy (saddr.sun_path, se->name, sizeof (saddr.sun_path) - 1); + + do + { + ret = connect (se->fd, (struct sockaddr*) &saddr, sizeof (saddr)); + } + while (ret < 0 && errno == EINTR); + + if (ret >= 0) + return SOCKET_ALIVE; + else + { + switch (errno) + { + case EINPROGRESS: + case EAGAIN: + return SOCKET_UNKNOWN; + case ECONNREFUSED: + return SOCKET_DEAD; + default: + fprintf (stderr, "Warning: unexpected error connecting to socket %s: %s\n", + se->name, strerror (errno)); + return SOCKET_FAILED_TO_HANDLE; + } + } +} + +static int +handle_sockets (SocketEntry **entries, + int n_entries) +{ + int i; + int n_unknown; + + n_unknown = 0; + + i = 0; + while (i < n_entries) + { + SocketEntry *se; + SocketStatus status; + + se = entries[i]; + ++i; + + if (se->fd >= 0) + { + fprintf (stderr, "Internal error, socket has fd kept open while status = %d\n", + se->status); + exit (1); + } + + if (se->status != SOCKET_UNKNOWN) + continue; + + status = open_socket (se); + + switch (status) + { + case SOCKET_DEAD: + cleaned_count += 1; + if (unlink (se->name) < 0) + { + fprintf (stderr, "Warning: Failed to delete %s: %s\n", + se->name, strerror (errno)); + + se->status = SOCKET_FAILED_TO_HANDLE; + } + else + se->status = SOCKET_UNLINKED; + break; + + case SOCKET_ALIVE: + alive_count += 1; + /* FALL THRU */ + + case SOCKET_FAILED_TO_HANDLE: + case SOCKET_UNKNOWN: + se->status = status; + break; + + case SOCKET_UNLINKED: + fprintf (stderr, "Bad status from open_socket(), should not happen\n"); + exit (1); + break; + } + + if (se->fd >= 0) + { + close (se->fd); + se->fd = -1; + } + + if (se->status == SOCKET_UNKNOWN) + n_unknown += 1; + } + + return n_unknown == 0; +} + +static void +clean_dir (const char *dir) +{ + SocketEntry **entries; + int n_entries; + + read_sockets (dir, &entries, &n_entries); + + /* open_socket() will fail conclusively after + * several retries, so this loop is guaranteed + * to terminate eventually + */ + while (!handle_sockets (entries, n_entries)) + { + fprintf (stderr, "Unable to determine state of some sockets, retrying in 2 seconds\n"); + sleep (2); + } + + unhandled_count += (n_entries - alive_count - cleaned_count); +} + +#endif /* AF_UNIX */ + +static void +usage (int ecode) +{ + fprintf (stderr, "dbus-cleanup-sockets [--version] [--help] <socketdir>\n"); + exit (ecode); +} + +static void +version (void) +{ + printf ("D-Bus Socket Cleanup Utility %s\n" + "Copyright (C) 2003 Red Hat, Inc.\n" + "Copyright (C) 2002 Michael Meeks\n" + "This is free software; see the source for copying conditions.\n" + "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", + VERSION); + exit (0); +} + +int +main (int argc, char **argv) +{ + int i; + int saw_doubledash; + const char *dirname; + + saw_doubledash = FALSE; + dirname = NULL; + i = 1; + while (i < argc) + { + const char *arg = argv[i]; + + if (strcmp (arg, "--help") == 0 || + strcmp (arg, "-h") == 0 || + strcmp (arg, "-?") == 0) + usage (0); + else if (strcmp (arg, "--version") == 0) + version (); + else if (!saw_doubledash) + { + if (strcmp (arg, "--") == 0) + saw_doubledash = TRUE; + else if (*arg == '-') + usage (1); + } + else + { + if (dirname != NULL) + { + fprintf (stderr, "dbus-cleanup-sockets only supports a single directory name\n"); + exit (1); + } + + dirname = arg; + } + + ++i; + } + + /* Default to session socket dir, usually /tmp */ + if (dirname == NULL) + dirname = DBUS_SESSION_SOCKET_DIR; + +#ifdef AF_UNIX + clean_dir (dirname); + + printf ("Cleaned up %d sockets in %s; %d sockets are still in use; %d in unknown state\n", + cleaned_count, dirname, alive_count, unhandled_count); +#else + printf ("This system does not support UNIX domain sockets, so dbus-cleanup-sockets does nothing\n"); +#endif + + return 0; +} diff --git a/tools/dbus-launch-x11.c b/tools/dbus-launch-x11.c new file mode 100644 index 00000000..56d7f744 --- /dev/null +++ b/tools/dbus-launch-x11.c @@ -0,0 +1,463 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-launch.h dbus-launch utility + * + * Copyright (C) 2006 Thiago Macieira <thiago@kde.org> + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include "dbus-launch.h" + +#ifdef DBUS_BUILD_X11 +#include <stdlib.h> +#include <sys/types.h> +#include <sys/stat.h> +#include <unistd.h> +#include <fcntl.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <pwd.h> +#include <X11/Xlib.h> +#include <X11/Xatom.h> + +Display *xdisplay = NULL; +static Atom selection_atom; +static Atom address_atom; +static Atom pid_atom; + +static int +x_io_error_handler (Display *xdisplay) +{ + verbose ("X IO error\n"); + kill_bus_and_exit (0); + return 0; +} + +static void +remove_prefix (char *s, + char *prefix) +{ + int plen; + + plen = strlen (prefix); + + if (strncmp (s, prefix, plen) == 0) + { + memmove (s, s + plen, strlen (s) - plen + 1); + } +} + +static const char* +get_homedir (void) +{ + const char *home; + + home = getenv ("HOME"); + if (home == NULL) + { + /* try from the user database */ + struct passwd *user = getpwuid (getuid()); + if (user != NULL) + home = user->pw_dir; + } + + if (home == NULL) + { + fprintf (stderr, "Can't get user home directory\n"); + exit (1); + } + + return home; +} + +#define DBUS_DIR ".dbus" +#define DBUS_SESSION_BUS_DIR "session-bus" + +static char * +get_session_file (void) +{ + static const char prefix[] = "/" DBUS_DIR "/" DBUS_SESSION_BUS_DIR "/"; + const char *machine; + const char *home; + char *display; + char *result; + char *p; + + machine = get_machine_uuid (); + if (machine == NULL) + return NULL; + + display = xstrdup (getenv ("DISPLAY")); + if (display == NULL) + { + verbose ("X11 integration disabled because X11 is not running\n"); + return NULL; + } + + /* remove the screen part of the display name */ + p = strrchr (display, ':'); + if (p != NULL) + { + for ( ; *p; ++p) + { + if (*p == '.') + { + *p = '\0'; + break; + } + } + } + + /* Note that we leave the hostname in the display most of the + * time. The idea is that we want to be per-(machine,display,user) + * triplet to be extra-sure we get a bus we can connect to. Ideally + * we'd recognize when the hostname matches the machine we're on in + * all cases; we do try to drop localhost and localhost.localdomain + * as a special common case so that alternate spellings of DISPLAY + * don't result in extra bus instances. + * + * We also kill the ":" if there's nothing in front of it. This + * avoids an ugly double underscore in the filename. + */ + remove_prefix (display, "localhost.localdomain:"); + remove_prefix (display, "localhost:"); + remove_prefix (display, ":"); + + /* replace the : in the display with _ if the : is still there. + * use _ instead of - since it can't be in hostnames. + */ + for (p = display; *p; ++p) + { + if (*p == ':') + *p = '_'; + } + + home = get_homedir (); + + result = malloc (strlen (home) + strlen (prefix) + strlen (machine) + + strlen (display) + 2); + if (result == NULL) + { + /* out of memory */ + free (display); + return NULL; + } + + strcpy (result, home); + strcat (result, prefix); + strcat (result, machine); + strcat (result, "-"); + strcat (result, display); + free (display); + + verbose ("session file: %s\n", result); + return result; +} + +static void +ensure_session_directory (void) +{ + const char *home; + char *dir; + + home = get_homedir (); + + /* be sure we have space for / and nul */ + dir = malloc (strlen (home) + strlen (DBUS_DIR) + strlen (DBUS_SESSION_BUS_DIR) + 3); + if (dir == NULL) + { + fprintf (stderr, "no memory\n"); + exit (1); + } + + strcpy (dir, home); + strcat (dir, "/"); + strcat (dir, DBUS_DIR); + + if (mkdir (dir, 0700) < 0) + { + /* only print a warning here, writing the session file itself will fail later */ + if (errno != EEXIST) + fprintf (stderr, "Unable to create %s\n", dir); + } + + strcat (dir, "/"); + strcat (dir, DBUS_SESSION_BUS_DIR); + + if (mkdir (dir, 0700) < 0) + { + /* only print a warning here, writing the session file itself will fail later */ + if (errno != EEXIST) + fprintf (stderr, "Unable to create %s\n", dir); + } + + free (dir); +} + +static Display * +open_x11 (void) +{ + if (xdisplay != NULL) + return xdisplay; + + xdisplay = XOpenDisplay (NULL); + if (xdisplay != NULL) + { + verbose ("Connected to X11 display '%s'\n", DisplayString (xdisplay)); + XSetIOErrorHandler (x_io_error_handler); + } + return xdisplay; +} + +static int +init_x_atoms (Display *display) +{ + static const char selection_prefix[] = "_DBUS_SESSION_BUS_SELECTION_"; + static const char address_prefix[] = "_DBUS_SESSION_BUS_ADDRESS"; + static const char pid_prefix[] = "_DBUS_SESSION_BUS_PID"; + static int init = FALSE; + char *atom_name; + const char *machine; + char *user_name; + struct passwd *user; + + if (init) + return TRUE; + + machine = get_machine_uuid (); + if (machine == NULL) + return FALSE; + + user = getpwuid (getuid ()); + if (user == NULL) + { + verbose ("Could not determine the user informations; aborting X11 integration.\n"); + return FALSE; + } + user_name = xstrdup(user->pw_name); + + atom_name = malloc (strlen (machine) + strlen (user_name) + 2 + + MAX (strlen (selection_prefix), + MAX (strlen (address_prefix), + strlen (pid_prefix)))); + if (atom_name == NULL) + { + verbose ("Could not create X11 atoms; aborting X11 integration.\n"); + free (user_name); + return FALSE; + } + + /* create the selection atom */ + strcpy (atom_name, selection_prefix); + strcat (atom_name, user_name); + strcat (atom_name, "_"); + strcat (atom_name, machine); + selection_atom = XInternAtom (display, atom_name, FALSE); + + /* create the address property atom */ + strcpy (atom_name, address_prefix); + address_atom = XInternAtom (display, atom_name, FALSE); + + /* create the PID property atom */ + strcpy (atom_name, pid_prefix); + pid_atom = XInternAtom (display, atom_name, FALSE); + + free (atom_name); + free (user_name); + init = TRUE; + return TRUE; +} + +/* + * Gets the daemon address from the X11 display. + * Returns FALSE if there was an error. Returning + * TRUE does not mean the address exists. + */ +int +x11_get_address (char **paddress, pid_t *pid, long *wid) +{ + Atom type; + Window owner; + int format; + unsigned long items; + unsigned long after; + char *data; + + *paddress = NULL; + + /* locate the selection owner */ + owner = XGetSelectionOwner (xdisplay, selection_atom); + if (owner == None) + return TRUE; /* no owner */ + if (wid != NULL) + *wid = (long) owner; + + /* get the bus address */ + XGetWindowProperty (xdisplay, owner, address_atom, 0, 1024, False, + XA_STRING, &type, &format, &items, &after, + (unsigned char **) &data); + if (type == None || after != 0 || data == NULL || format != 8) + return FALSE; /* error */ + + *paddress = xstrdup (data); + XFree (data); + + /* get the PID */ + if (pid != NULL) + { + *pid = 0; + XGetWindowProperty (xdisplay, owner, pid_atom, 0, sizeof pid, False, + XA_CARDINAL, &type, &format, &items, &after, + (unsigned char **) &data); + if (type != None && after == 0 && data != NULL && format == 32) + *pid = (pid_t) *(long*) data; + XFree (data); + } + + return TRUE; /* success */ +} + +/* + * Saves the address in the X11 display. Returns 0 on success. + * If an error occurs, returns -1. If the selection already exists, + * returns 1. (i.e. another daemon is already running) + */ +static Window +set_address_in_x11(char *address, pid_t pid) +{ + char *current_address; + Window wid = None; + unsigned long pid32; /* Xlib property functions want _long_ not 32-bit for format "32" */ + + /* lock the X11 display to make sure we're doing this atomically */ + XGrabServer (xdisplay); + + if (!x11_get_address (¤t_address, NULL, NULL)) + { + /* error! */ + goto out; + } + + if (current_address != NULL) + { + /* someone saved the address in the meantime */ + free (current_address); + goto out; + } + + /* Create our window */ + wid = XCreateWindow (xdisplay, RootWindow (xdisplay, 0), -20, -20, 10, 10, + 0, CopyFromParent, InputOnly, CopyFromParent, + 0, NULL); + verbose ("Created window %d\n", wid); + + /* Save the property in the window */ + XChangeProperty (xdisplay, wid, address_atom, XA_STRING, 8, PropModeReplace, + (unsigned char *)address, strlen (address)); + pid32 = pid; + XChangeProperty (xdisplay, wid, pid_atom, XA_CARDINAL, 32, PropModeReplace, + (unsigned char *)&pid32, 1); + + /* Now grab the selection */ + XSetSelectionOwner (xdisplay, selection_atom, wid, CurrentTime); + + out: + /* Ungrab the server to let other people use it too */ + XUngrabServer (xdisplay); + + /* And make sure that the ungrab gets sent to X11 */ + XFlush (xdisplay); + + return wid; +} + +/* + * Saves the session address in session file. Returns TRUE on + * success, FALSE if an error occurs. + */ +static int +set_address_in_file (char *address, pid_t pid, Window wid) +{ + char *session_file; + FILE *f; + + ensure_session_directory (); + session_file = get_session_file(); + if (session_file == NULL) + return FALSE; + + f = fopen (session_file, "w"); + if (f == NULL) + return FALSE; /* some kind of error */ + fprintf (f, + "# This file allows processes on the machine with id %s using \n" + "# display %s to find the D-Bus session bus with the below address.\n" + "# If the DBUS_SESSION_BUS_ADDRESS environment variable is set, it will\n" + "# be used rather than this file.\n" + "# See \"man dbus-launch\" for more details.\n" + "DBUS_SESSION_BUS_ADDRESS=%s\n" + "DBUS_SESSION_BUS_PID=%ld\n" + "DBUS_SESSION_BUS_WINDOWID=%ld\n", + get_machine_uuid (), + getenv ("DISPLAY"), + address, (long)pid, (long)wid); + + fclose (f); + free (session_file); + + return TRUE; +} + +int +x11_save_address (char *address, pid_t pid, long *wid) +{ + Window id = set_address_in_x11 (address, pid); + if (id != None) + { + if (!set_address_in_file (address, pid, id)) + return FALSE; + + if (wid != NULL) + *wid = (long) id; + return TRUE; + } + return FALSE; +} + +int +x11_init (void) +{ + return open_x11 () != NULL && init_x_atoms (xdisplay); +} + +void +x11_handle_event (void) +{ + if (xdisplay != NULL) + { + while (XPending (xdisplay)) + { + XEvent ignored; + XNextEvent (xdisplay, &ignored); + } + } +} + +#else +void dummy_dbus_launch_x11 (void) { } +#endif diff --git a/tools/dbus-launch.1 b/tools/dbus-launch.1 new file mode 100644 index 00000000..0ea19495 --- /dev/null +++ b/tools/dbus-launch.1 @@ -0,0 +1,183 @@ +.\" +.\" dbus-launch manual page. +.\" Copyright (C) 2003 Red Hat, Inc. +.\" +.TH dbus-launch 1 +.SH NAME +dbus-launch \- Utility to start a message bus from a shell script +.SH SYNOPSIS +.PP +.B dbus-launch [\-\-version] [\-\-sh-syntax] [\-\-csh-syntax] [\-\-auto-syntax] [\-\-exit-with-session] [\-\-autolaunch=MACHINEID] [\-\-config-file=FILENAME] [PROGRAM] [ARGS...] + +.SH DESCRIPTION + +The \fIdbus-launch\fP command is used to start a session bus +instance of \fIdbus-daemon\fP from a shell script. +It would normally be called from a user's login +scripts. Unlike the daemon itself, \fIdbus-launch\fP exits, so +backticks or the $() construct can be used to read information from +\fIdbus-launch\fP. + +With no arguments, \fIdbus-launch\fP will launch a session bus +instance and print the address and pid of that instance to standard +output. + +You may specify a program to be run; in this case, \fIdbus-launch\fP +will launch a session bus instance, set the appropriate environment +variables so the specified program can find the bus, and then execute the +specified program, with the specified arguments. See below for +examples. + +If you launch a program, \fIdbus-launch\fP will not print the +information about the new bus to standard output. + +When \fIdbus-launch\fP prints bus information to standard output, by +default it is in a simple key-value pairs format. However, you may +request several alternate syntaxes using the \-\-sh-syntax, \-\-csh-syntax, +\-\-binary-syntax, or +\-\-auto-syntax options. Several of these cause \fIdbus-launch\fP to emit shell code +to set up the environment. + +With the \-\-auto-syntax option, \fIdbus-launch\fP looks at the value +of the SHELL environment variable to determine which shell syntax +should be used. If SHELL ends in "csh", then csh-compatible code is +emitted; otherwise Bourne shell code is emitted. Instead of passing +\-\-auto-syntax, you may explicity specify a particular one by using +\-\-sh-syntax for Bourne syntax, or \-\-csh-syntax for csh syntax. +In scripts, it's more robust to avoid \-\-auto-syntax and you hopefully +know which shell your script is written in. + +.PP +See http://www.freedesktop.org/software/dbus/ for more information +about D-Bus. See also the man page for \fIdbus-daemon\fP. + +.PP +Here is an example of how to use \fIdbus-launch\fP with an +sh-compatible shell to start the per-session bus daemon: +.nf + + ## test for an existing bus daemon, just to be safe + if test -z "$DBUS_SESSION_BUS_ADDRESS" ; then + ## if not found, launch a new one + eval `dbus-launch --sh-syntax --exit-with-session` + echo "D-Bus per-session daemon address is: $DBUS_SESSION_BUS_ADDRESS" + fi + +.fi +You might run something like that in your login scripts. + +.PP +Another way to use \fIdbus-launch\fP is to run your main session +program, like so: +.nf + +dbus-launch gnome-session + +.fi +The above would likely be appropriate for ~/.xsession or ~/.Xclients. + +.SH AUTOMATIC LAUNCHING + +.PP +If DBUS_SESSION_BUS_ADDRESS is not set for a process that tries to use +D-Bus, by default the process will attempt to invoke dbus-launch with +the --autolaunch option to start up a new session bus or find the +existing bus address on the X display or in a file in +~/.dbus/session-bus/ + +.PP +Whenever an autolaunch occurs, the application that had to +start a new bus will be in its own little world; it can effectively +end up starting a whole new session if it tries to use a lot of +bus services. This can be suboptimal or even totally broken, depending +on the app and what it tries to do. + +.PP +There are two common reasons for autolaunch. One is ssh to a remote +machine. The ideal fix for that would be forwarding of +DBUS_SESSION_BUS_ADDRESS in the same way that DISPLAY is forwarded. +In the meantime, you can edit the session.conf config file to +have your session bus listen on TCP, and manually set +DBUS_SESSION_BUS_ADDRESS, if you like. + +.PP +The second common reason for autolaunch is an su to another user, and +display of X applications running as the second user on the display +belonging to the first user. Perhaps the ideal fix in this case +would be to allow the second user to connect to the session bus of the +first user, just as they can connect to the first user's display. +However, a mechanism for that has not been coded. + +.PP +You can always avoid autolaunch by manually setting +DBUS_SESSION_BUS_ADDRESS. Autolaunch happens because the default +address if none is set is "autolaunch:", so if any other address is +set there will be no autolaunch. You can however include autolaunch in +an explicit session bus address as a fallback, for example +DBUS_SESSION_BUS_ADDRESS="something:,autolaunch:" - in that case if +the first address doesn't work, processes will autolaunch. (The bus +address variable contains a comma-separated list of addresses to try.) + +.PP +The --autolaunch option is considered an internal implementation +detail of libdbus, and in fact there are plans to change it. There's +no real reason to use it outside of the libdbus implementation anyhow. + +.SH OPTIONS +The following options are supported: +.TP +.I "--auto-syntax" +Choose \-\-csh-syntax or \-\-sh-syntax based on the SHELL environment variable. + +.I "--binary-syntax" +Write to stdout a nul-terminated bus address, then the bus PID as a +binary integer of size sizeof(pid_t), then the bus X window ID as a +binary integer of size sizeof(long). Integers are in the machine's +byte order, not network byte order or any other canonical byte order. + +.TP +.I "--close-stderr" +Close the standard error output stream before starting the D-Bus +daemon. This is useful if you want to capture dbus-launch error +messages but you don't want dbus-daemon to keep the stream open to +your application. + +.TP +.I "--config-file=FILENAME" +Pass \-\-config-file=FILENAME to the bus daemon, instead of passing it +the \-\-session argument. See the man page for dbus-daemon + +.TP +.I "--csh-syntax" +Emit csh compatible code to set up environment variables. + +.TP +.I "--exit-with-session" +If this option is provided, a persistent "babysitter" process will be +created that watches stdin for HUP and tries to connect to the X +server. If this process gets a HUP on stdin or loses its X connection, +it kills the message bus daemon. + +.TP +.I "--autolaunch=MACHINEID" +This option implies that \fIdbus-launch\fP should scan for a +previously-started session and reuse the values found there. If no +session is found, it will start a new session. The +\-\-exit-with-session option is implied if \-\-autolaunch is given. +This option is for the exclusive use of libdbus, you do not want to +use it manually. It may change in the future. + +.TP +.I "--sh-syntax" +Emit Bourne-shell compatible code to set up environment variables. + +.TP +.I "--version" +Print the version of dbus-launch + +.SH AUTHOR +See http://www.freedesktop.org/software/dbus/doc/AUTHORS + +.SH BUGS +Please send bug reports to the D-Bus mailing list or bug tracker, +see http://www.freedesktop.org/software/dbus/ diff --git a/tools/dbus-launch.c b/tools/dbus-launch.c new file mode 100644 index 00000000..d3553e81 --- /dev/null +++ b/tools/dbus-launch.c @@ -0,0 +1,1214 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-launch.c dbus-launch utility + * + * Copyright (C) 2003, 2006 Red Hat, Inc. + * Copyright (C) 2006 Thiago Macieira <thiago@kde.org> + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include "dbus-launch.h" +#include <stdlib.h> +#include <ctype.h> +#include <unistd.h> +#include <fcntl.h> +#include <signal.h> +#include <sys/wait.h> +#include <errno.h> +#include <stdio.h> +#include <string.h> +#include <signal.h> +#include <stdarg.h> +#include <sys/select.h> +#include <time.h> + +#ifdef DBUS_BUILD_X11 +#include <X11/Xlib.h> +extern Display *xdisplay; +#endif + +static char* machine_uuid = NULL; + +const char* +get_machine_uuid (void) +{ + return machine_uuid; +} + +static void +save_machine_uuid (const char *uuid_arg) +{ + if (strlen (uuid_arg) != 32) + { + fprintf (stderr, "machine ID '%s' looks like it's the wrong length, should be 32 hex digits", + uuid_arg); + exit (1); + } + + machine_uuid = xstrdup (uuid_arg); +} + +#define UUID_MAXLEN 40 +/* Read the machine uuid from file if needed. Returns TRUE if machine_uuid is + * set after this function */ +static int +read_machine_uuid_if_needed (void) +{ + FILE *f; + char uuid[UUID_MAXLEN]; + size_t len; + int ret = FALSE; + + if (machine_uuid != NULL) + return TRUE; + + f = fopen (DBUS_MACHINE_UUID_FILE, "r"); + if (f == NULL) + return FALSE; + + if (fgets (uuid, UUID_MAXLEN, f) == NULL) + goto out; + + len = strlen (uuid); + if (len < 32) + goto out; + + /* rstrip the read uuid */ + while (len > 31 && isspace(uuid[len - 1])) + len--; + + if (len != 32) + goto out; + + uuid[len] = '\0'; + machine_uuid = xstrdup (uuid); + verbose ("UID: %s\n", machine_uuid); + ret = TRUE; + +out: + fclose(f); + return ret; +} + + +void +verbose (const char *format, + ...) +{ + va_list args; + static int verbose = TRUE; + static int verbose_initted = FALSE; + + /* things are written a bit oddly here so that + * in the non-verbose case we just have the one + * conditional and return immediately. + */ + if (!verbose) + return; + + if (!verbose_initted) + { + verbose = getenv ("DBUS_VERBOSE") != NULL; + verbose_initted = TRUE; + if (!verbose) + return; + } + + fprintf (stderr, "%lu: ", (unsigned long) getpid ()); + + va_start (args, format); + vfprintf (stderr, format, args); + va_end (args); +} + +static void +usage (int ecode) +{ + fprintf (stderr, "dbus-launch [--version] [--help] [--sh-syntax] [--csh-syntax] [--auto-syntax] [--exit-with-session]\n"); + exit (ecode); +} + +static void +version (void) +{ + printf ("D-Bus Message Bus Launcher %s\n" + "Copyright (C) 2003 Red Hat, Inc.\n" + "This is free software; see the source for copying conditions.\n" + "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", + VERSION); + exit (0); +} + +char * +xstrdup (const char *str) +{ + int len; + char *copy; + + if (str == NULL) + return NULL; + + len = strlen (str); + + copy = malloc (len + 1); + if (copy == NULL) + return NULL; + + memcpy (copy, str, len + 1); + + return copy; +} + +typedef enum +{ + READ_STATUS_OK, /**< Read succeeded */ + READ_STATUS_ERROR, /**< Some kind of error */ + READ_STATUS_EOF /**< EOF returned */ +} ReadStatus; + +static ReadStatus +read_line (int fd, + char *buf, + size_t maxlen) +{ + size_t bytes = 0; + ReadStatus retval; + + memset (buf, '\0', maxlen); + maxlen -= 1; /* ensure nul term */ + + retval = READ_STATUS_OK; + + while (TRUE) + { + ssize_t chunk; + size_t to_read; + + again: + to_read = maxlen - bytes; + + if (to_read == 0) + break; + + chunk = read (fd, + buf + bytes, + to_read); + if (chunk < 0 && errno == EINTR) + goto again; + + if (chunk < 0) + { + retval = READ_STATUS_ERROR; + break; + } + else if (chunk == 0) + { + retval = READ_STATUS_EOF; + break; /* EOF */ + } + else /* chunk > 0 */ + bytes += chunk; + } + + if (retval == READ_STATUS_EOF && + bytes > 0) + retval = READ_STATUS_OK; + + /* whack newline */ + if (retval != READ_STATUS_ERROR && + bytes > 0 && + buf[bytes-1] == '\n') + buf[bytes-1] = '\0'; + + return retval; +} + +static ReadStatus +read_pid (int fd, + pid_t *buf) +{ + size_t bytes = 0; + ReadStatus retval; + + retval = READ_STATUS_OK; + + while (TRUE) + { + ssize_t chunk; + size_t to_read; + + again: + to_read = sizeof (pid_t) - bytes; + + if (to_read == 0) + break; + + chunk = read (fd, + ((char*)buf) + bytes, + to_read); + if (chunk < 0 && errno == EINTR) + goto again; + + if (chunk < 0) + { + retval = READ_STATUS_ERROR; + break; + } + else if (chunk == 0) + { + retval = READ_STATUS_EOF; + break; /* EOF */ + } + else /* chunk > 0 */ + bytes += chunk; + } + + return retval; +} + +static void +do_write (int fd, const void *buf, size_t count) +{ + size_t bytes_written; + int ret; + + bytes_written = 0; + + again: + + ret = write (fd, ((const char*)buf) + bytes_written, count - bytes_written); + + if (ret < 0) + { + if (errno == EINTR) + goto again; + else + { + fprintf (stderr, "Failed to write data to pipe! %s\n", + strerror (errno)); + exit (1); /* give up, we suck */ + } + } + else + bytes_written += ret; + + if (bytes_written < count) + goto again; +} + +static void +write_pid (int fd, + pid_t pid) +{ + do_write (fd, &pid, sizeof (pid)); +} + +static int +do_waitpid (pid_t pid) +{ + int ret; + + again: + ret = waitpid (pid, NULL, 0); + + if (ret < 0 && + errno == EINTR) + goto again; + + return ret; +} + +static pid_t bus_pid_to_kill = -1; + +static void +kill_bus(void) +{ + verbose ("Killing message bus and exiting babysitter\n"); + kill (bus_pid_to_kill, SIGTERM); + sleep (3); + kill (bus_pid_to_kill, SIGKILL); +} + +void +kill_bus_and_exit (int exitcode) +{ + /* in case these point to any NFS mounts, get rid of them immediately */ + close (0); + close (1); + close (2); + + kill_bus(); + + exit (exitcode); +} + +static void +print_variables (const char *bus_address, pid_t bus_pid, long bus_wid, + int c_shell_syntax, int bourne_shell_syntax, + int binary_syntax) +{ + if (binary_syntax) + { + write (1, bus_address, strlen (bus_address) + 1); + write (1, &bus_pid, sizeof bus_pid); + write (1, &bus_wid, sizeof bus_wid); + return; + } + else if (c_shell_syntax) + { + printf ("setenv DBUS_SESSION_BUS_ADDRESS '%s';\n", bus_address); + printf ("set DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid); + if (bus_wid) + printf ("set DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid); + fflush (stdout); + } + else if (bourne_shell_syntax) + { + printf ("DBUS_SESSION_BUS_ADDRESS='%s';\n", bus_address); + printf ("export DBUS_SESSION_BUS_ADDRESS;\n"); + printf ("DBUS_SESSION_BUS_PID=%ld;\n", (long) bus_pid); + if (bus_wid) + printf ("DBUS_SESSION_BUS_WINDOWID=%ld;\n", (long) bus_wid); + fflush (stdout); + } + else + { + printf ("DBUS_SESSION_BUS_ADDRESS=%s\n", bus_address); + printf ("DBUS_SESSION_BUS_PID=%ld\n", (long) bus_pid); + if (bus_wid) + printf ("DBUS_SESSION_BUS_WINDOWID=%ld\n", (long) bus_wid); + fflush (stdout); + } +} + +static int got_sighup = FALSE; + +static void +signal_handler (int sig) +{ + switch (sig) + { +#ifdef SIGHUP + case SIGHUP: +#endif + case SIGINT: + case SIGTERM: + got_sighup = TRUE; + break; + } +} + +static void +kill_bus_when_session_ends (void) +{ + int tty_fd; + int x_fd; + fd_set read_set; + fd_set err_set; + struct sigaction act; + sigset_t empty_mask; + + /* install SIGHUP handler */ + got_sighup = FALSE; + sigemptyset (&empty_mask); + act.sa_handler = signal_handler; + act.sa_mask = empty_mask; + act.sa_flags = 0; + sigaction (SIGHUP, &act, NULL); + sigaction (SIGTERM, &act, NULL); + sigaction (SIGINT, &act, NULL); + +#ifdef DBUS_BUILD_X11 + x11_init(); + if (xdisplay != NULL) + { + x_fd = ConnectionNumber (xdisplay); + } + else + x_fd = -1; +#else + x_fd = -1; +#endif + + if (isatty (0)) + tty_fd = 0; + else + tty_fd = -1; + + if (tty_fd >= 0) + verbose ("stdin isatty(), monitoring it\n"); + else + verbose ("stdin was not a TTY, not monitoring it\n"); + + if (tty_fd < 0 && x_fd < 0) + { + fprintf (stderr, "No terminal on standard input and no X display; cannot attach message bus to session lifetime\n"); + exit (1); + } + + while (TRUE) + { +#ifdef DBUS_BUILD_X11 + /* Dump events on the floor, and let + * IO error handler run if we lose + * the X connection. It's important to + * run this before going into select() since + * we might have queued outgoing messages or + * events. + */ + x11_handle_event (); +#endif + + FD_ZERO (&read_set); + FD_ZERO (&err_set); + + if (tty_fd >= 0) + { + FD_SET (tty_fd, &read_set); + FD_SET (tty_fd, &err_set); + } + + if (x_fd >= 0) + { + FD_SET (x_fd, &read_set); + FD_SET (x_fd, &err_set); + } + + select (MAX (tty_fd, x_fd) + 1, + &read_set, NULL, &err_set, NULL); + + if (got_sighup) + { + verbose ("Got SIGHUP, exiting\n"); + kill_bus_and_exit (0); + } + +#ifdef DBUS_BUILD_X11 + /* Events will be processed before we select again + */ + if (x_fd >= 0) + verbose ("X fd condition reading = %d error = %d\n", + FD_ISSET (x_fd, &read_set), + FD_ISSET (x_fd, &err_set)); +#endif + + if (tty_fd >= 0) + { + if (FD_ISSET (tty_fd, &read_set)) + { + int bytes_read; + char discard[512]; + + verbose ("TTY ready for reading\n"); + + bytes_read = read (tty_fd, discard, sizeof (discard)); + + verbose ("Read %d bytes from TTY errno = %d\n", + bytes_read, errno); + + if (bytes_read == 0) + kill_bus_and_exit (0); /* EOF */ + else if (bytes_read < 0 && errno != EINTR) + { + /* This shouldn't happen I don't think; to avoid + * spinning on the fd forever we exit. + */ + fprintf (stderr, "dbus-launch: error reading from stdin: %s\n", + strerror (errno)); + kill_bus_and_exit (0); + } + } + else if (FD_ISSET (tty_fd, &err_set)) + { + verbose ("TTY has error condition\n"); + + kill_bus_and_exit (0); + } + } + } +} + +static void +babysit (int exit_with_session, + pid_t child_pid, + int read_bus_pid_fd) /* read pid from here */ +{ + int ret; + int dev_null_fd; + const char *s; + + verbose ("babysitting, exit_with_session = %d, child_pid = %ld, read_bus_pid_fd = %d\n", + exit_with_session, (long) child_pid, read_bus_pid_fd); + + /* We chdir ("/") since we are persistent and daemon-like, and fork + * again so dbus-launch can reap the parent. However, we don't + * setsid() or close fd 0 because the idea is to remain attached + * to the tty and the X server in order to kill the message bus + * when the session ends. + */ + + if (chdir ("/") < 0) + { + fprintf (stderr, "Could not change to root directory: %s\n", + strerror (errno)); + exit (1); + } + + /* Close stdout/stderr so we don't block an "eval" or otherwise + * lock up. stdout is still chaining through to dbus-launch + * and in turn to the parent shell. + */ + dev_null_fd = open ("/dev/null", O_RDWR); + if (dev_null_fd >= 0) + { + if (!exit_with_session) + dup2 (dev_null_fd, 0); + dup2 (dev_null_fd, 1); + s = getenv ("DBUS_DEBUG_OUTPUT"); + if (s == NULL || *s == '\0') + dup2 (dev_null_fd, 2); + } + else + { + fprintf (stderr, "Failed to open /dev/null: %s\n", + strerror (errno)); + /* continue, why not */ + } + + ret = fork (); + + if (ret < 0) + { + fprintf (stderr, "fork() failed in babysitter: %s\n", + strerror (errno)); + exit (1); + } + + if (ret > 0) + { + /* Parent reaps pre-fork part of bus daemon, then exits and is + * reaped so the babysitter isn't a zombie + */ + + verbose ("=== Babysitter's intermediate parent continues again\n"); + + if (do_waitpid (child_pid) < 0) + { + /* shouldn't happen */ + fprintf (stderr, "Failed waitpid() waiting for bus daemon's parent\n"); + exit (1); + } + + verbose ("Babysitter's intermediate parent exiting\n"); + + exit (0); + } + + /* Child continues */ + verbose ("=== Babysitter process created\n"); + + verbose ("Reading PID from bus\n"); + + switch (read_pid (read_bus_pid_fd, &bus_pid_to_kill)) + { + case READ_STATUS_OK: + break; + case READ_STATUS_EOF: + fprintf (stderr, "EOF in dbus-launch reading PID from bus daemon\n"); + exit (1); + break; + case READ_STATUS_ERROR: + fprintf (stderr, "Error in dbus-launch reading PID from bus daemon: %s\n", + strerror (errno)); + exit (1); + break; + } + + verbose ("Got PID %ld from daemon\n", + (long) bus_pid_to_kill); + + if (exit_with_session) + { + /* Bus is now started and launcher has needed info; + * we connect to X display and tty and wait to + * kill bus if requested. + */ + + kill_bus_when_session_ends (); + } + + verbose ("Babysitter exiting\n"); + + exit (0); +} + +static void +do_close_stderr (void) +{ + int fd; + + fflush (stderr); + + /* dbus-launch is a Unix-only program, so we can rely on /dev/null being there. + * We're including unistd.h and we're dealing with sh/csh launch sequences... + */ + fd = open ("/dev/null", O_RDWR); + if (fd == -1) + { + fprintf (stderr, "Internal error: cannot open /dev/null: %s", strerror (errno)); + exit (1); + } + + close (2); + if (dup2 (fd, 2) == -1) + { + /* error; we can't report an error anymore... */ + exit (1); + } + close (fd); +} + +static void +pass_info (const char *runprog, const char *bus_address, pid_t bus_pid, + long bus_wid, int c_shell_syntax, int bourne_shell_syntax, + int binary_syntax, + int argc, char **argv, int remaining_args) +{ + if (runprog) + { + char *envvar; + char **args; + int i; + + envvar = malloc (strlen ("DBUS_SESSION_BUS_ADDRESS=") + + strlen (bus_address) + 1); + args = malloc (sizeof (char *) * ((argc-remaining_args)+2)); + + if (envvar == NULL || args == NULL) + goto oom; + + args[0] = xstrdup (runprog); + if (!args[0]) + goto oom; + for (i = 1; i <= (argc-remaining_args); i++) + { + size_t len = strlen (argv[remaining_args+i-1])+1; + args[i] = malloc (len); + if (!args[i]) + goto oom; + strncpy (args[i], argv[remaining_args+i-1], len); + } + args[i] = NULL; + + strcpy (envvar, "DBUS_SESSION_BUS_ADDRESS="); + strcat (envvar, bus_address); + putenv (envvar); + + execvp (runprog, args); + fprintf (stderr, "Couldn't exec %s: %s\n", runprog, strerror (errno)); + exit (1); + } + else + { + print_variables (bus_address, bus_pid, bus_wid, c_shell_syntax, + bourne_shell_syntax, binary_syntax); + } + verbose ("dbus-launch exiting\n"); + + fflush (stdout); + fflush (stderr); + close (1); + close (2); + exit (0); +oom: + fprintf (stderr, "Out of memory!"); + exit (1); +} + +#define READ_END 0 +#define WRITE_END 1 + +int +main (int argc, char **argv) +{ + const char *prev_arg; + const char *shname; + const char *runprog = NULL; + int remaining_args = 0; + int exit_with_session; + int binary_syntax = FALSE; + int c_shell_syntax = FALSE; + int bourne_shell_syntax = FALSE; + int auto_shell_syntax = FALSE; + int autolaunch = FALSE; + int requires_arg = FALSE; + int close_stderr = FALSE; + int i; + int ret; + int bus_pid_to_launcher_pipe[2]; + int bus_pid_to_babysitter_pipe[2]; + int bus_address_to_launcher_pipe[2]; + char *config_file; + + exit_with_session = FALSE; + config_file = NULL; + + prev_arg = NULL; + i = 1; + while (i < argc) + { + const char *arg = argv[i]; + + if (strcmp (arg, "--help") == 0 || + strcmp (arg, "-h") == 0 || + strcmp (arg, "-?") == 0) + usage (0); + else if (strcmp (arg, "--auto-syntax") == 0) + auto_shell_syntax = TRUE; + else if (strcmp (arg, "-c") == 0 || + strcmp (arg, "--csh-syntax") == 0) + c_shell_syntax = TRUE; + else if (strcmp (arg, "-s") == 0 || + strcmp (arg, "--sh-syntax") == 0) + bourne_shell_syntax = TRUE; + else if (strcmp (arg, "--binary-syntax") == 0) + binary_syntax = TRUE; + else if (strcmp (arg, "--version") == 0) + version (); + else if (strcmp (arg, "--exit-with-session") == 0) + exit_with_session = TRUE; + else if (strcmp (arg, "--close-stderr") == 0) + close_stderr = TRUE; + else if (strstr (arg, "--autolaunch=") == arg) + { + const char *s; + + if (autolaunch) + { + fprintf (stderr, "--autolaunch given twice\n"); + exit (1); + } + + autolaunch = TRUE; + + s = strchr (arg, '='); + ++s; + + save_machine_uuid (s); + } + else if (prev_arg && + strcmp (prev_arg, "--autolaunch") == 0) + { + if (autolaunch) + { + fprintf (stderr, "--autolaunch given twice\n"); + exit (1); + } + + autolaunch = TRUE; + + save_machine_uuid (arg); + requires_arg = FALSE; + } + else if (strcmp (arg, "--autolaunch") == 0) + requires_arg = TRUE; + else if (strstr (arg, "--config-file=") == arg) + { + const char *file; + + if (config_file != NULL) + { + fprintf (stderr, "--config-file given twice\n"); + exit (1); + } + + file = strchr (arg, '='); + ++file; + + config_file = xstrdup (file); + } + else if (prev_arg && + strcmp (prev_arg, "--config-file") == 0) + { + if (config_file != NULL) + { + fprintf (stderr, "--config-file given twice\n"); + exit (1); + } + + config_file = xstrdup (arg); + requires_arg = FALSE; + } + else if (strcmp (arg, "--config-file") == 0) + requires_arg = TRUE; + else if (arg[0] == '-') + { + if (strcmp (arg, "--") != 0) + { + fprintf (stderr, "Option `%s' is unknown.\n", arg); + exit (1); + } + else + { + runprog = argv[i+1]; + remaining_args = i+2; + break; + } + } + else + { + runprog = arg; + remaining_args = i+1; + break; + } + + prev_arg = arg; + + ++i; + } + if (requires_arg) + { + fprintf (stderr, "Option `%s' requires an argument.\n", prev_arg); + exit (1); + } + + if (auto_shell_syntax) + { + if ((shname = getenv ("SHELL")) != NULL) + { + if (!strncmp (shname + strlen (shname) - 3, "csh", 3)) + c_shell_syntax = TRUE; + else + bourne_shell_syntax = TRUE; + } + else + bourne_shell_syntax = TRUE; + } + + if (exit_with_session) + verbose ("--exit-with-session enabled\n"); + + if (autolaunch) + { +#ifndef DBUS_BUILD_X11 + fprintf (stderr, "Autolaunch requested, but X11 support not compiled in.\n" + "Cannot continue.\n"); + exit (1); +#else + char *address; + pid_t pid; + long wid; + + if (get_machine_uuid () == NULL) + { + fprintf (stderr, "Machine UUID not provided as arg to --autolaunch\n"); + exit (1); + } + + verbose ("Autolaunch enabled (using X11).\n"); + if (!exit_with_session) + { + verbose ("--exit-with-session automatically enabled\n"); + exit_with_session = TRUE; + } + + if (!x11_init ()) + { + fprintf (stderr, "Autolaunch error: X11 initialization failed.\n"); + exit (1); + } + + if (!x11_get_address (&address, &pid, &wid)) + { + fprintf (stderr, "Autolaunch error: X11 communication error.\n"); + exit (1); + } + + if (address != NULL) + { + verbose ("dbus-daemon is already running. Returning existing parameters.\n"); + pass_info (runprog, address, pid, wid, c_shell_syntax, + bourne_shell_syntax, binary_syntax, argc, argv, remaining_args); + exit (0); + } + } + else if (read_machine_uuid_if_needed()) + { + x11_init(); +#endif + } + + + if (pipe (bus_pid_to_launcher_pipe) < 0 || + pipe (bus_address_to_launcher_pipe) < 0 || + pipe (bus_pid_to_babysitter_pipe) < 0) + { + fprintf (stderr, + "Failed to create pipe: %s\n", + strerror (errno)); + exit (1); + } + + ret = fork (); + if (ret < 0) + { + fprintf (stderr, "Failed to fork: %s\n", + strerror (errno)); + exit (1); + } + + if (ret == 0) + { + /* Child */ +#define MAX_FD_LEN 64 + char write_pid_fd_as_string[MAX_FD_LEN]; + char write_address_fd_as_string[MAX_FD_LEN]; + +#ifdef DBUS_BUILD_X11 + xdisplay = NULL; +#endif + + if (close_stderr) + do_close_stderr (); + + verbose ("=== Babysitter's intermediate parent created\n"); + + /* Fork once more to create babysitter */ + + ret = fork (); + if (ret < 0) + { + fprintf (stderr, "Failed to fork: %s\n", + strerror (errno)); + exit (1); + } + + if (ret > 0) + { + /* In babysitter */ + verbose ("=== Babysitter's intermediate parent continues\n"); + + close (bus_pid_to_launcher_pipe[READ_END]); + close (bus_pid_to_launcher_pipe[WRITE_END]); + close (bus_address_to_launcher_pipe[READ_END]); + close (bus_address_to_launcher_pipe[WRITE_END]); + close (bus_pid_to_babysitter_pipe[WRITE_END]); + + /* babysit() will fork *again* + * and will also reap the pre-forked bus + * daemon + */ + babysit (exit_with_session, ret, + bus_pid_to_babysitter_pipe[READ_END]); + exit (0); + } + + verbose ("=== Bus exec process created\n"); + + /* Now we are the bus process (well, almost; + * dbus-daemon itself forks again) + */ + close (bus_pid_to_launcher_pipe[READ_END]); + close (bus_address_to_launcher_pipe[READ_END]); + close (bus_pid_to_babysitter_pipe[READ_END]); + close (bus_pid_to_babysitter_pipe[WRITE_END]); + + sprintf (write_pid_fd_as_string, + "%d", bus_pid_to_launcher_pipe[WRITE_END]); + + sprintf (write_address_fd_as_string, + "%d", bus_address_to_launcher_pipe[WRITE_END]); + + verbose ("Calling exec()\n"); + +#ifdef DBUS_BUILD_TESTS + /* exec from testdir */ + if (getenv("DBUS_USE_TEST_BINARY") != NULL) + { + execl (TEST_BUS_BINARY, + TEST_BUS_BINARY, + "--fork", + "--print-pid", write_pid_fd_as_string, + "--print-address", write_address_fd_as_string, + config_file ? "--config-file" : "--session", + config_file, /* has to be last in this varargs list */ + NULL); + + fprintf (stderr, + "Failed to execute test message bus daemon %s: %s. Will try again with the system path.\n", + TEST_BUS_BINARY, strerror (errno)); + } + #endif /* DBUS_BUILD_TESTS */ + + execl (DBUS_DAEMONDIR"/dbus-daemon", + DBUS_DAEMONDIR"/dbus-daemon", + "--fork", + "--print-pid", write_pid_fd_as_string, + "--print-address", write_address_fd_as_string, + config_file ? "--config-file" : "--session", + config_file, /* has to be last in this varargs list */ + NULL); + + fprintf (stderr, + "Failed to execute message bus daemon %s: %s. Will try again without full path.\n", + DBUS_DAEMONDIR"/dbus-daemon", strerror (errno)); + + /* + * If it failed, try running without full PATH. Note this is needed + * because the build process builds the run-with-tmp-session-bus.conf + * file and the dbus-daemon will not be in the install location during + * build time. + */ + execlp ("dbus-daemon", + "dbus-daemon", + "--fork", + "--print-pid", write_pid_fd_as_string, + "--print-address", write_address_fd_as_string, + config_file ? "--config-file" : "--session", + config_file, /* has to be last in this varargs list */ + NULL); + + fprintf (stderr, + "Failed to execute message bus daemon: %s\n", + strerror (errno)); + exit (1); + } + else + { + /* Parent */ +#define MAX_PID_LEN 64 + pid_t bus_pid; + char bus_address[MAX_ADDR_LEN]; + char buf[MAX_PID_LEN]; + char *end; + long wid = 0; + long val; + int ret2; + + verbose ("=== Parent dbus-launch continues\n"); + + close (bus_pid_to_launcher_pipe[WRITE_END]); + close (bus_address_to_launcher_pipe[WRITE_END]); + close (bus_pid_to_babysitter_pipe[READ_END]); + + verbose ("Waiting for babysitter's intermediate parent\n"); + + /* Immediately reap parent of babysitter + * (which was created just for us to reap) + */ + if (do_waitpid (ret) < 0) + { + fprintf (stderr, "Failed to waitpid() for babysitter intermediate process: %s\n", + strerror (errno)); + exit (1); + } + + verbose ("Reading address from bus\n"); + + /* Read the pipe data, print, and exit */ + switch (read_line (bus_address_to_launcher_pipe[READ_END], + bus_address, MAX_ADDR_LEN)) + { + case READ_STATUS_OK: + break; + case READ_STATUS_EOF: + fprintf (stderr, "EOF in dbus-launch reading address from bus daemon\n"); + exit (1); + break; + case READ_STATUS_ERROR: + fprintf (stderr, "Error in dbus-launch reading address from bus daemon: %s\n", + strerror (errno)); + exit (1); + break; + } + + close (bus_address_to_launcher_pipe[READ_END]); + + verbose ("Reading PID from daemon\n"); + /* Now read data */ + switch (read_line (bus_pid_to_launcher_pipe[READ_END], buf, MAX_PID_LEN)) + { + case READ_STATUS_OK: + break; + case READ_STATUS_EOF: + fprintf (stderr, "EOF reading PID from bus daemon\n"); + exit (1); + break; + case READ_STATUS_ERROR: + fprintf (stderr, "Error reading PID from bus daemon: %s\n", + strerror (errno)); + exit (1); + break; + } + + end = NULL; + val = strtol (buf, &end, 0); + if (buf == end || end == NULL) + { + fprintf (stderr, "Failed to parse bus PID \"%s\": %s\n", + buf, strerror (errno)); + exit (1); + } + + bus_pid = val; + + close (bus_pid_to_launcher_pipe[READ_END]); + +#ifdef DBUS_BUILD_X11 + if (xdisplay != NULL) + { + verbose("Saving x11 address\n"); + ret2 = x11_save_address (bus_address, bus_pid, &wid); + /* Only get an existing dbus session when autolaunching */ + if (autolaunch) + { + if (ret2 == 0) + { + char *address = NULL; + /* another window got added. Return its address */ + bus_pid_to_kill = bus_pid; + if (x11_get_address (&address, &bus_pid, &wid) + && address != NULL) + { + verbose ("dbus-daemon is already running. Returning existing parameters.\n"); + /* Kill the old bus */ + kill_bus(); + pass_info (runprog, address, bus_pid, wid, + c_shell_syntax, bourne_shell_syntax, binary_syntax, + argc, argv, remaining_args); + } + } + if (ret2 < 0) + { + fprintf (stderr, "Error saving bus information.\n"); + bus_pid_to_kill = bus_pid; + kill_bus_and_exit (1); + } + } + } +#endif + + /* Forward the pid to the babysitter */ + write_pid (bus_pid_to_babysitter_pipe[WRITE_END], bus_pid); + close (bus_pid_to_babysitter_pipe[WRITE_END]); + + pass_info (runprog, bus_address, bus_pid, wid, c_shell_syntax, + bourne_shell_syntax, binary_syntax, argc, argv, remaining_args); + } + + return 0; +} diff --git a/tools/dbus-launch.h b/tools/dbus-launch.h new file mode 100644 index 00000000..d0d0617d --- /dev/null +++ b/tools/dbus-launch.h @@ -0,0 +1,58 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-launch.h dbus-launch utility + * + * Copyright (C) 2006 Thiago Macieira <thiago@kde.org> + * + * Licensed under the Academic Free License version 2.1 + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#ifndef DBUS_LAUNCH_H +#define DBUS_LAUNCH_H + +#include <config.h> +#include <sys/types.h> + +#ifndef TRUE +#define TRUE (1) +#endif + +#ifndef FALSE +#define FALSE (0) +#endif + +#undef MAX +#define MAX(a, b) (((a) > (b)) ? (a) : (b)) + +#define MAX_ADDR_LEN 512 + +/* defined in dbus-launch.c */ +void verbose (const char *format, ...); +char *xstrdup (const char *str); +void kill_bus_and_exit (int exitcode); + +const char* get_machine_uuid (void); + +#ifdef DBUS_BUILD_X11 +/* defined in dbus-launch-x11.c */ +int x11_init (void); +int x11_get_address (char **paddress, pid_t *pid, long *wid); +int x11_save_address (char *address, pid_t pid, long *wid); +void x11_handle_event (void); +#endif + +#endif diff --git a/tools/dbus-monitor.1 b/tools/dbus-monitor.1 new file mode 100644 index 00000000..c24c14d9 --- /dev/null +++ b/tools/dbus-monitor.1 @@ -0,0 +1,78 @@ +.\" +.\" dbus-monitor manual page. +.\" Copyright (C) 2003 Red Hat, Inc. +.\" +.TH dbus-monitor 1 +.SH NAME +dbus-monitor \- debug probe to print message bus messages +.SH SYNOPSIS +.PP +.B dbus-monitor +[\-\-system | \-\-session | \-\-address ADDRESS] [\-\-profile | \-\-monitor] +[watch expressions] + +.SH DESCRIPTION + +The \fIdbus-monitor\fP command is used to monitor messages going +through a D-Bus message bus. See +http://www.freedesktop.org/software/dbus/ for more information about +the big picture. + +.PP +There are two well-known message buses: the systemwide message bus +(installed on many systems as the "messagebus" service) and the +per-user-login-session message bus (started each time a user logs in). +The \-\-system and \-\-session options direct \fIdbus-monitor\fP to +monitor the system or session buses respectively. If neither is +specified, \fIdbus-monitor\fP monitors the session bus. + +.PP +\fIdbus-monitor\fP has two different output modes, the 'classic'-style +monitoring mode and profiling mode. The profiling format is a compact +format with a single line per message and microsecond-resolution timing +information. The \-\-profile and \-\-monitor options select the profiling +and monitoring output format respectively. If neither is specified, +\fIdbus-monitor\fP uses the monitoring output format. + +.PP +In order to get \fIdbus-monitor\fP to see the messages you are interested +in, you should specify a set of watch expressions as you would expect to +be passed to the \fIdbus_bus_add_match\fP function. + +.PP +The message bus configuration may keep \fIdbus-monitor\fP from seeing +all messages, especially if you run the monitor as a non-root user. + +.SH OPTIONS +.TP +.I "--system" +Monitor the system message bus. +.TP +.I "--session" +Monitor the session message bus. (This is the default.) +.TP +.I "--address ADDRESS" +Monitor an arbitrary message bus given at ADDRESS. +.TP +.I "--profile" +Use the profiling output format. +.TP +.I "--monitor" +Use the monitoring output format. (This is the default.) + +.SH EXAMPLE +Here is an example of using dbus-monitor to watch for the gnome typing +monitor to say things +.nf + + dbus-monitor "type='signal',sender='org.gnome.TypingMonitor',interface='org.gnome.TypingMonitor'" + +.fi + +.SH AUTHOR +dbus-monitor was written by Philip Blundell. +The profiling output mode was added by Olli Salli. + +.SH BUGS +Please send bug reports to the D-Bus mailing list or bug tracker, +see http://www.freedesktop.org/software/dbus/ diff --git a/tools/dbus-monitor.c b/tools/dbus-monitor.c new file mode 100644 index 00000000..c3681289 --- /dev/null +++ b/tools/dbus-monitor.c @@ -0,0 +1,354 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-monitor.c Utility program to monitor messages on the bus + * + * Copyright (C) 2003 Philip Blundell <philb@gnu.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#ifdef DBUS_WIN +#include <winsock2.h> +#undef interface +#else +#include <sys/time.h> +#endif + +#include <time.h> + +#include "dbus-print-message.h" + +#ifdef DBUS_WIN + +/* gettimeofday is not defined on windows */ +#define DBUS_SECONDS_SINCE_1601 11644473600LL +#define DBUS_USEC_IN_SEC 1000000LL + +static int +gettimeofday (struct timeval *__p, + void *__t) +{ + union { + unsigned long long ns100; /*time since 1 Jan 1601 in 100ns units */ + FILETIME ft; + } now; + + GetSystemTimeAsFileTime (&now.ft); + __p->tv_usec = (long) ((now.ns100 / 10LL) % DBUS_USEC_IN_SEC); + __p->tv_sec = (long)(((now.ns100 / 10LL) / DBUS_SECONDS_SINCE_1601) - DBUS_SECONDS_SINCE_1601); + + return 0; +} +#endif + +static DBusHandlerResult +monitor_filter_func (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + print_message (message, FALSE); + + if (dbus_message_is_signal (message, + DBUS_INTERFACE_LOCAL, + "Disconnected")) + exit (0); + + /* Conceptually we want this to be + * DBUS_HANDLER_RESULT_NOT_YET_HANDLED, but this raises + * some problems. See bug 1719. + */ + return DBUS_HANDLER_RESULT_HANDLED; +} + +#define PROFILE_TIMED_FORMAT "%s\t%lu\t%lu" +#define TRAP_NULL_STRING(str) ((str) ? (str) : "<none>") + +typedef enum +{ + PROFILE_ATTRIBUTE_FLAG_SERIAL = 1, + PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL = 2, + PROFILE_ATTRIBUTE_FLAG_SENDER = 4, + PROFILE_ATTRIBUTE_FLAG_DESTINATION = 8, + PROFILE_ATTRIBUTE_FLAG_PATH = 16, + PROFILE_ATTRIBUTE_FLAG_INTERFACE = 32, + PROFILE_ATTRIBUTE_FLAG_MEMBER = 64, + PROFILE_ATTRIBUTE_FLAG_ERROR_NAME = 128 +} ProfileAttributeFlags; + +static void +profile_print_with_attrs (const char *type, DBusMessage *message, + struct timeval *t, ProfileAttributeFlags attrs) +{ + printf (PROFILE_TIMED_FORMAT, type, t->tv_sec, t->tv_usec); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_SERIAL) + printf ("\t%u", dbus_message_get_serial (message)); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL) + printf ("\t%u", dbus_message_get_reply_serial (message)); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_SENDER) + printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_sender (message))); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_DESTINATION) + printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_destination (message))); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_PATH) + printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_path (message))); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_INTERFACE) + printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_interface (message))); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_MEMBER) + printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_member (message))); + + if (attrs & PROFILE_ATTRIBUTE_FLAG_ERROR_NAME) + printf ("\t%s", TRAP_NULL_STRING (dbus_message_get_error_name (message))); + + printf ("\n"); +} + +static void +print_message_profile (DBusMessage *message) +{ + struct timeval t; + + if (gettimeofday (&t, NULL) < 0) + { + printf ("un\n"); + return; + } + + switch (dbus_message_get_type (message)) + { + case DBUS_MESSAGE_TYPE_METHOD_CALL: + profile_print_with_attrs ("mc", message, &t, + PROFILE_ATTRIBUTE_FLAG_SERIAL | + PROFILE_ATTRIBUTE_FLAG_SENDER | + PROFILE_ATTRIBUTE_FLAG_PATH | + PROFILE_ATTRIBUTE_FLAG_INTERFACE | + PROFILE_ATTRIBUTE_FLAG_MEMBER); + break; + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + profile_print_with_attrs ("mr", message, &t, + PROFILE_ATTRIBUTE_FLAG_SERIAL | + PROFILE_ATTRIBUTE_FLAG_DESTINATION | + PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL); + break; + case DBUS_MESSAGE_TYPE_ERROR: + profile_print_with_attrs ("err", message, &t, + PROFILE_ATTRIBUTE_FLAG_SERIAL | + PROFILE_ATTRIBUTE_FLAG_DESTINATION | + PROFILE_ATTRIBUTE_FLAG_REPLY_SERIAL); + break; + case DBUS_MESSAGE_TYPE_SIGNAL: + profile_print_with_attrs ("sig", message, &t, + PROFILE_ATTRIBUTE_FLAG_SERIAL | + PROFILE_ATTRIBUTE_FLAG_PATH | + PROFILE_ATTRIBUTE_FLAG_INTERFACE | + PROFILE_ATTRIBUTE_FLAG_MEMBER); + break; + default: + printf (PROFILE_TIMED_FORMAT "\n", "tun", t.tv_sec, t.tv_usec); + break; + } +} + +static DBusHandlerResult +profile_filter_func (DBusConnection *connection, + DBusMessage *message, + void *user_data) +{ + print_message_profile (message); + + if (dbus_message_is_signal (message, + DBUS_INTERFACE_LOCAL, + "Disconnected")) + exit (0); + + return DBUS_HANDLER_RESULT_HANDLED; +} + +static void +usage (char *name, int ecode) +{ + fprintf (stderr, "Usage: %s [--system | --session | --address ADDRESS] [--monitor | --profile ] [watch expressions]\n", name); + exit (ecode); +} + +static dbus_bool_t sigint_received = FALSE; + +static void +sigint_handler (int signum) +{ + sigint_received = TRUE; +} + +int +main (int argc, char *argv[]) +{ + DBusConnection *connection; + DBusError error; + DBusBusType type = DBUS_BUS_SESSION; + DBusHandleMessageFunction filter_func = monitor_filter_func; + char *address = NULL; + + int i = 0, j = 0, numFilters = 0; + char **filters = NULL; + + /* Set stdout to be unbuffered; this is basically so that if people + * do dbus-monitor > file, then send SIGINT via Control-C, they + * don't lose the last chunk of messages. + */ + setvbuf (stdout, NULL, _IOLBF, 0); + + for (i = 1; i < argc; i++) + { + char *arg = argv[i]; + + if (!strcmp (arg, "--system")) + type = DBUS_BUS_SYSTEM; + else if (!strcmp (arg, "--session")) + type = DBUS_BUS_SESSION; + else if (!strcmp (arg, "--address")) + { + if (i+1 < argc) + { + address = argv[i+1]; + i++; + } + else + usage (argv[0], 1); + } + else if (!strcmp (arg, "--help")) + usage (argv[0], 0); + else if (!strcmp (arg, "--monitor")) + filter_func = monitor_filter_func; + else if (!strcmp (arg, "--profile")) + filter_func = profile_filter_func; + else if (!strcmp (arg, "--")) + continue; + else if (arg[0] == '-') + usage (argv[0], 1); + else { + numFilters++; + filters = (char **)realloc(filters, numFilters * sizeof(char *)); + filters[j] = (char *)malloc((strlen(arg) + 1) * sizeof(char *)); + snprintf(filters[j], strlen(arg) + 1, "%s", arg); + j++; + } + } + + dbus_error_init (&error); + + if (address != NULL) + { + connection = dbus_connection_open (address, &error); + if (connection) + { + if (!dbus_bus_register (connection, &error)) + { + fprintf (stderr, "Failed to register connection to bus at %s: %s\n", + address, error.message); + dbus_error_free (&error); + exit (1); + } + } + } + else + connection = dbus_bus_get (type, &error); + if (connection == NULL) + { + const char *where; + if (address != NULL) + where = address; + else + { + switch (type) + { + case DBUS_BUS_SYSTEM: + where = "system bus"; + break; + case DBUS_BUS_SESSION: + where = "session bus"; + break; + default: + where = ""; + } + } + fprintf (stderr, "Failed to open connection to %s: %s\n", + where, + error.message); + dbus_error_free (&error); + exit (1); + } + + if (numFilters) + { + for (i = 0; i < j; i++) + { + dbus_bus_add_match (connection, filters[i], &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "Failed to setup match \"%s\": %s\n", + filters[i], error.message); + dbus_error_free (&error); + exit (1); + } + free(filters[i]); + } + } + else + { + dbus_bus_add_match (connection, + "type='signal'", + &error); + if (dbus_error_is_set (&error)) + goto lose; + dbus_bus_add_match (connection, + "type='method_call'", + &error); + if (dbus_error_is_set (&error)) + goto lose; + dbus_bus_add_match (connection, + "type='method_return'", + &error); + if (dbus_error_is_set (&error)) + goto lose; + dbus_bus_add_match (connection, + "type='error'", + &error); + if (dbus_error_is_set (&error)) + goto lose; + } + + if (!dbus_connection_add_filter (connection, filter_func, NULL, NULL)) { + fprintf (stderr, "Couldn't add filter!\n"); + exit (1); + } + + while (dbus_connection_read_write_dispatch(connection, -1)) + ; + exit (0); + lose: + fprintf (stderr, "Error: %s\n", error.message); + exit (1); +} + diff --git a/tools/dbus-print-message.c b/tools/dbus-print-message.c new file mode 100644 index 00000000..fac5cc1f --- /dev/null +++ b/tools/dbus-print-message.c @@ -0,0 +1,407 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-print-message.h Utility function to print out a message + * + * Copyright (C) 2003 Philip Blundell <philb@gnu.org> + * Copyright (C) 2003 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#include "dbus-print-message.h" + +#include <stdlib.h> +#include "config.h" + +static const char* +type_to_name (int message_type) +{ + switch (message_type) + { + case DBUS_MESSAGE_TYPE_SIGNAL: + return "signal"; + case DBUS_MESSAGE_TYPE_METHOD_CALL: + return "method call"; + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + return "method return"; + case DBUS_MESSAGE_TYPE_ERROR: + return "error"; + default: + return "(unknown message type)"; + } +} + +#define INDENT 3 + +static void +indent (int depth) +{ + while (depth-- > 0) + printf (" "); /* INDENT spaces. */ +} + +static void +print_hex (unsigned char *bytes, unsigned int len, int depth) +{ + int i, columns; + + printf ("array of bytes [\n"); + + indent (depth + 1); + + /* Each byte takes 3 cells (two hexits, and a space), except the last one. */ + columns = (80 - ((depth + 1) * INDENT)) / 3; + + if (columns < 8) + columns = 8; + + i = 0; + + while (i < len) + { + printf ("%02x", bytes[i]); + i++; + + if (i != len) + { + if (i % columns == 0) + { + printf ("\n"); + indent (depth + 1); + } + else + { + printf (" "); + } + } + } + + printf ("\n"); + indent (depth); + printf ("]\n"); +} + +#define DEFAULT_SIZE 100 + +static void +print_ay (DBusMessageIter *iter, int depth) +{ + /* Not using DBusString because it's not public API. It's 2009, and I'm + * manually growing a string chunk by chunk. + */ + unsigned char *bytes = malloc (DEFAULT_SIZE + 1); + unsigned int len = 0; + unsigned int max = DEFAULT_SIZE; + dbus_bool_t all_ascii = TRUE; + int current_type; + + while ((current_type = dbus_message_iter_get_arg_type (iter)) + != DBUS_TYPE_INVALID) + { + unsigned char val; + + dbus_message_iter_get_basic (iter, &val); + bytes[len] = val; + len++; + + if (val < 32 || val > 126) + all_ascii = FALSE; + + if (len == max) + { + max *= 2; + bytes = realloc (bytes, max + 1); + } + + dbus_message_iter_next (iter); + } + + if (all_ascii) + { + bytes[len] = '\0'; + printf ("array of bytes \"%s\"\n", bytes); + } + else + { + print_hex (bytes, len, depth); + } + + free (bytes); +} + +static void +print_iter (DBusMessageIter *iter, dbus_bool_t literal, int depth) +{ + do + { + int type = dbus_message_iter_get_arg_type (iter); + + if (type == DBUS_TYPE_INVALID) + break; + + indent(depth); + + switch (type) + { + case DBUS_TYPE_STRING: + { + char *val; + dbus_message_iter_get_basic (iter, &val); + if (!literal) + printf ("string \""); + printf ("%s", val); + if (!literal) + printf ("\"\n"); + break; + } + + case DBUS_TYPE_SIGNATURE: + { + char *val; + dbus_message_iter_get_basic (iter, &val); + if (!literal) + printf ("signature \""); + printf ("%s", val); + if (!literal) + printf ("\"\n"); + break; + } + + case DBUS_TYPE_OBJECT_PATH: + { + char *val; + dbus_message_iter_get_basic (iter, &val); + if (!literal) + printf ("object path \""); + printf ("%s", val); + if (!literal) + printf ("\"\n"); + break; + } + + case DBUS_TYPE_INT16: + { + dbus_int16_t val; + dbus_message_iter_get_basic (iter, &val); + printf ("int16 %d\n", val); + break; + } + + case DBUS_TYPE_UINT16: + { + dbus_uint16_t val; + dbus_message_iter_get_basic (iter, &val); + printf ("uint16 %u\n", val); + break; + } + + case DBUS_TYPE_INT32: + { + dbus_int32_t val; + dbus_message_iter_get_basic (iter, &val); + printf ("int32 %d\n", val); + break; + } + + case DBUS_TYPE_UINT32: + { + dbus_uint32_t val; + dbus_message_iter_get_basic (iter, &val); + printf ("uint32 %u\n", val); + break; + } + + case DBUS_TYPE_INT64: + { + dbus_int64_t val; + dbus_message_iter_get_basic (iter, &val); +#ifdef DBUS_INT64_PRINTF_MODIFIER + printf ("int64 %" DBUS_INT64_PRINTF_MODIFIER "d\n", val); +#else + printf ("int64 (omitted)\n"); +#endif + break; + } + + case DBUS_TYPE_UINT64: + { + dbus_uint64_t val; + dbus_message_iter_get_basic (iter, &val); +#ifdef DBUS_INT64_PRINTF_MODIFIER + printf ("uint64 %" DBUS_INT64_PRINTF_MODIFIER "u\n", val); +#else + printf ("uint64 (omitted)\n"); +#endif + break; + } + + case DBUS_TYPE_DOUBLE: + { + double val; + dbus_message_iter_get_basic (iter, &val); + printf ("double %g\n", val); + break; + } + + case DBUS_TYPE_BYTE: + { + unsigned char val; + dbus_message_iter_get_basic (iter, &val); + printf ("byte %d\n", val); + break; + } + + case DBUS_TYPE_BOOLEAN: + { + dbus_bool_t val; + dbus_message_iter_get_basic (iter, &val); + printf ("boolean %s\n", val ? "true" : "false"); + break; + } + + case DBUS_TYPE_VARIANT: + { + DBusMessageIter subiter; + + dbus_message_iter_recurse (iter, &subiter); + + printf ("variant "); + print_iter (&subiter, literal, depth+1); + break; + } + case DBUS_TYPE_ARRAY: + { + int current_type; + DBusMessageIter subiter; + + dbus_message_iter_recurse (iter, &subiter); + + current_type = dbus_message_iter_get_arg_type (&subiter); + + if (current_type == DBUS_TYPE_BYTE) + { + print_ay (&subiter, depth); + break; + } + + printf("array [\n"); + while (current_type != DBUS_TYPE_INVALID) + { + print_iter (&subiter, literal, depth+1); + + dbus_message_iter_next (&subiter); + current_type = dbus_message_iter_get_arg_type (&subiter); + + if (current_type != DBUS_TYPE_INVALID) + printf (","); + } + indent(depth); + printf("]\n"); + break; + } + case DBUS_TYPE_DICT_ENTRY: + { + DBusMessageIter subiter; + + dbus_message_iter_recurse (iter, &subiter); + + printf("dict entry(\n"); + print_iter (&subiter, literal, depth+1); + dbus_message_iter_next (&subiter); + print_iter (&subiter, literal, depth+1); + indent(depth); + printf(")\n"); + break; + } + + case DBUS_TYPE_STRUCT: + { + int current_type; + DBusMessageIter subiter; + + dbus_message_iter_recurse (iter, &subiter); + + printf("struct {\n"); + while ((current_type = dbus_message_iter_get_arg_type (&subiter)) != DBUS_TYPE_INVALID) + { + print_iter (&subiter, literal, depth+1); + dbus_message_iter_next (&subiter); + if (dbus_message_iter_get_arg_type (&subiter) != DBUS_TYPE_INVALID) + printf (","); + } + indent(depth); + printf("}\n"); + break; + } + + default: + printf (" (dbus-monitor too dumb to decipher arg type '%c')\n", type); + break; + } + } while (dbus_message_iter_next (iter)); +} + +void +print_message (DBusMessage *message, dbus_bool_t literal) +{ + DBusMessageIter iter; + const char *sender; + const char *destination; + int message_type; + + message_type = dbus_message_get_type (message); + sender = dbus_message_get_sender (message); + destination = dbus_message_get_destination (message); + + if (!literal) + { + printf ("%s sender=%s -> dest=%s", + type_to_name (message_type), + sender ? sender : "(null sender)", + destination ? destination : "(null destination)"); + + switch (message_type) + { + case DBUS_MESSAGE_TYPE_METHOD_CALL: + case DBUS_MESSAGE_TYPE_SIGNAL: + printf (" serial=%u path=%s; interface=%s; member=%s\n", + dbus_message_get_serial (message), + dbus_message_get_path (message), + dbus_message_get_interface (message), + dbus_message_get_member (message)); + break; + + case DBUS_MESSAGE_TYPE_METHOD_RETURN: + printf (" reply_serial=%u\n", + dbus_message_get_reply_serial (message)); + break; + + case DBUS_MESSAGE_TYPE_ERROR: + printf (" error_name=%s reply_serial=%u\n", + dbus_message_get_error_name (message), + dbus_message_get_reply_serial (message)); + break; + + default: + printf ("\n"); + break; + } + } + + dbus_message_iter_init (message, &iter); + print_iter (&iter, literal, 1); + fflush (stdout); + +} + diff --git a/tools/dbus-print-message.h b/tools/dbus-print-message.h new file mode 100644 index 00000000..26700d84 --- /dev/null +++ b/tools/dbus-print-message.h @@ -0,0 +1,31 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-print-message.h Utility function to print out a message + * + * Copyright (C) 2003 Philip Blundell <philb@gnu.org> + * Copyright (C) 2003 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ +#ifndef DBUS_PRINT_MESSAGE_H +#define DBUS_PRINT_MESSAGE_H + +#include <stdio.h> +#include <string.h> +#include <dbus/dbus.h> + +void print_message (DBusMessage *message, dbus_bool_t literal); + +#endif /* DBUS_PRINT_MESSAGE_H */ diff --git a/tools/dbus-send.1 b/tools/dbus-send.1 new file mode 100644 index 00000000..4878c3d9 --- /dev/null +++ b/tools/dbus-send.1 @@ -0,0 +1,95 @@ +.\" +.\" dbus-send manual page. +.\" Copyright (C) 2003 Red Hat, Inc. +.\" +.TH dbus-send 1 +.SH NAME +dbus-send \- Send a message to a message bus +.SH SYNOPSIS +.PP +.B dbus-send +[\-\-system | \-\-session] [\-\-dest=NAME] [\-\-print-reply] +[\-\-type=TYPE] <destination object path> <message name> [contents ...] + +.SH DESCRIPTION + +The \fIdbus-send\fP command is used to send a message to a D-Bus message +bus. See http://www.freedesktop.org/software/dbus/ for more +information about the big picture. + +.PP +There are two well-known message buses: the systemwide message bus +(installed on many systems as the "messagebus" service) and the +per-user-login-session message bus (started each time a user logs in). +The \-\-system and \-\-session options direct \fIdbus-send\fP to send +messages to the system or session buses respectively. If neither is +specified, \fIdbus-send\fP sends to the session bus. + +.PP +Nearly all uses of \fIdbus-send\fP must provide the \-\-dest argument +which is the name of a connection on the bus to send the message to. If +\-\-dest is omitted, no destination is set. + +.PP +The object path and the name of the message to send must always be +specified. Following arguments, if any, are the message contents +(message arguments). These are given as type-specified values and +may include containers (arrays, dicts, and variants) as described below. + +.nf +<contents> ::= <item> | <container> [ <item> | <container>...] +<item> ::= <type>:<value> +<container> ::= <array> | <dict> | <variant> +<array> ::= array:<type>:<value>[,<value>...] +<dict> ::= dict:<type>:<type>:<key>,<value>[,<key>,<value>...] +<variant> ::= variant:<type>:<value> +<type> ::= string | int16 | uint 16 | int32 | uint32 | int64 | uint64 | double | byte | boolean | objpath +.fi + +D-Bus supports more types than these, but \fIdbus-send\fP currently +does not. Also, \fIdbus-send\fP does not permit empty containers +or nested containers (e.g. arrays of variants). + +.PP +Here is an example invocation: +.nf + + dbus-send \-\-dest=org.freedesktop.ExampleName \\ + /org/freedesktop/sample/object/name \\ + org.freedesktop.ExampleInterface.ExampleMethod \\ + int32:47 string:'hello world' double:65.32 \\ + array:string:"1st item","next item","last item" \\ + dict:string:int32:"one",1,"two",2,"three",3 \\ + variant:int32:-8 \\ + objpath:/org/freedesktop/sample/object/name + +.fi + +Note that the interface is separated from a method or signal +name by a dot, though in the actual protocol the interface +and the interface member are separate fields. + +.SH OPTIONS +The following options are supported: +.TP +.I "--dest=NAME" +Specify the name of the connection to receive the message. +.TP +.I "--print-reply" +Block for a reply to the message sent, and print any reply received. +.TP +.I "--system" +Send to the system message bus. +.TP +.I "--session" +Send to the session message bus. (This is the default.) +.TP +.I "--type=TYPE" +Specify "method_call" or "signal" (defaults to "signal"). + +.SH AUTHOR +dbus-send was written by Philip Blundell. + +.SH BUGS +Please send bug reports to the D-Bus mailing list or bug tracker, +see http://www.freedesktop.org/software/dbus/ diff --git a/tools/dbus-send.c b/tools/dbus-send.c new file mode 100644 index 00000000..c9c9be27 --- /dev/null +++ b/tools/dbus-send.c @@ -0,0 +1,526 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-send.c Utility program to send messages from the command line + * + * Copyright (C) 2003 Philip Blundell <philb@gnu.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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <dbus/dbus.h> + +#include "dbus-print-message.h" + +static const char *appname; + +static void +usage (int ecode) +{ + fprintf (stderr, "Usage: %s [--help] [--system | --session | --address=ADDRESS] [--dest=NAME] [--type=TYPE] [--print-reply=(literal)] [--reply-timeout=MSEC] <destination object path> <message name> [contents ...]\n", appname); + exit (ecode); +} + +static void +append_arg (DBusMessageIter *iter, int type, const char *value) +{ + dbus_uint16_t uint16; + dbus_int16_t int16; + dbus_uint32_t uint32; + dbus_int32_t int32; + dbus_uint64_t uint64; + dbus_int64_t int64; + double d; + unsigned char byte; + dbus_bool_t v_BOOLEAN; + + /* FIXME - we are ignoring OOM returns on all these functions */ + switch (type) + { + case DBUS_TYPE_BYTE: + byte = strtoul (value, NULL, 0); + dbus_message_iter_append_basic (iter, DBUS_TYPE_BYTE, &byte); + break; + + case DBUS_TYPE_DOUBLE: + d = strtod (value, NULL); + dbus_message_iter_append_basic (iter, DBUS_TYPE_DOUBLE, &d); + break; + + case DBUS_TYPE_INT16: + int16 = strtol (value, NULL, 0); + dbus_message_iter_append_basic (iter, DBUS_TYPE_INT16, &int16); + break; + + case DBUS_TYPE_UINT16: + uint16 = strtoul (value, NULL, 0); + dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT16, &uint16); + break; + + case DBUS_TYPE_INT32: + int32 = strtol (value, NULL, 0); + dbus_message_iter_append_basic (iter, DBUS_TYPE_INT32, &int32); + break; + + case DBUS_TYPE_UINT32: + uint32 = strtoul (value, NULL, 0); + dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT32, &uint32); + break; + + case DBUS_TYPE_INT64: + int64 = strtoll (value, NULL, 0); + dbus_message_iter_append_basic (iter, DBUS_TYPE_INT64, &int64); + break; + + case DBUS_TYPE_UINT64: + uint64 = strtoull (value, NULL, 0); + dbus_message_iter_append_basic (iter, DBUS_TYPE_UINT64, &uint64); + break; + + case DBUS_TYPE_STRING: + dbus_message_iter_append_basic (iter, DBUS_TYPE_STRING, &value); + break; + + case DBUS_TYPE_OBJECT_PATH: + dbus_message_iter_append_basic (iter, DBUS_TYPE_OBJECT_PATH, &value); + break; + + case DBUS_TYPE_BOOLEAN: + if (strcmp (value, "true") == 0) + { + v_BOOLEAN = TRUE; + dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN); + } + else if (strcmp (value, "false") == 0) + { + v_BOOLEAN = FALSE; + dbus_message_iter_append_basic (iter, DBUS_TYPE_BOOLEAN, &v_BOOLEAN); + } + else + { + fprintf (stderr, "%s: Expected \"true\" or \"false\" instead of \"%s\"\n", appname, value); + exit (1); + } + break; + + default: + fprintf (stderr, "%s: Unsupported data type %c\n", appname, (char) type); + exit (1); + } +} + +static void +append_array (DBusMessageIter *iter, int type, const char *value) +{ + const char *val; + char *dupval = strdup (value); + + val = strtok (dupval, ","); + while (val != NULL) + { + append_arg (iter, type, val); + val = strtok (NULL, ","); + } + free (dupval); +} + +static void +append_dict (DBusMessageIter *iter, int keytype, int valtype, const char *value) +{ + const char *val; + char *dupval = strdup (value); + + val = strtok (dupval, ","); + while (val != NULL) + { + DBusMessageIter subiter; + + dbus_message_iter_open_container (iter, + DBUS_TYPE_DICT_ENTRY, + NULL, + &subiter); + + append_arg (&subiter, keytype, val); + val = strtok (NULL, ","); + if (val == NULL) + { + fprintf (stderr, "%s: Malformed dictionary\n", appname); + exit (1); + } + append_arg (&subiter, valtype, val); + + dbus_message_iter_close_container (iter, &subiter); + val = strtok (NULL, ","); + } + free (dupval); +} + +static int +type_from_name (const char *arg) +{ + int type; + if (!strcmp (arg, "string")) + type = DBUS_TYPE_STRING; + else if (!strcmp (arg, "int16")) + type = DBUS_TYPE_INT16; + else if (!strcmp (arg, "uint16")) + type = DBUS_TYPE_UINT16; + else if (!strcmp (arg, "int32")) + type = DBUS_TYPE_INT32; + else if (!strcmp (arg, "uint32")) + type = DBUS_TYPE_UINT32; + else if (!strcmp (arg, "int64")) + type = DBUS_TYPE_INT64; + else if (!strcmp (arg, "uint64")) + type = DBUS_TYPE_UINT64; + else if (!strcmp (arg, "double")) + type = DBUS_TYPE_DOUBLE; + else if (!strcmp (arg, "byte")) + type = DBUS_TYPE_BYTE; + else if (!strcmp (arg, "boolean")) + type = DBUS_TYPE_BOOLEAN; + else if (!strcmp (arg, "objpath")) + type = DBUS_TYPE_OBJECT_PATH; + else + { + fprintf (stderr, "%s: Unknown type \"%s\"\n", appname, arg); + exit (1); + } + return type; +} + +int +main (int argc, char *argv[]) +{ + DBusConnection *connection; + DBusError error; + DBusMessage *message; + int print_reply; + int print_reply_literal; + int reply_timeout; + DBusMessageIter iter; + int i; + DBusBusType type = DBUS_BUS_SESSION; + const char *dest = NULL; + const char *name = NULL; + const char *path = NULL; + int message_type = DBUS_MESSAGE_TYPE_SIGNAL; + const char *type_str = NULL; + const char *address = NULL; + int session_or_system = FALSE; + + appname = argv[0]; + + if (argc < 3) + usage (1); + + print_reply = FALSE; + print_reply_literal = FALSE; + reply_timeout = -1; + + for (i = 1; i < argc && name == NULL; i++) + { + char *arg = argv[i]; + + if (strcmp (arg, "--system") == 0) + { + type = DBUS_BUS_SYSTEM; + session_or_system = TRUE; + } + else if (strcmp (arg, "--session") == 0) + { + type = DBUS_BUS_SESSION; + session_or_system = TRUE; + } + else if (strstr (arg, "--address") == arg) + { + address = strchr (arg, '='); + + if (address == NULL) + { + fprintf (stderr, "\"--address=\" requires an ADDRESS\n"); + usage (1); + } + else + { + address = address + 1; + } + } + else if (strncmp (arg, "--print-reply", 13) == 0) + { + print_reply = TRUE; + message_type = DBUS_MESSAGE_TYPE_METHOD_CALL; + if (*(arg + 13) != '\0') + print_reply_literal = TRUE; + } + else if (strstr (arg, "--reply-timeout=") == arg) + { + reply_timeout = strtol (strchr (arg, '=') + 1, + NULL, 10); + } + else if (strstr (arg, "--dest=") == arg) + dest = strchr (arg, '=') + 1; + else if (strstr (arg, "--type=") == arg) + type_str = strchr (arg, '=') + 1; + else if (!strcmp(arg, "--help")) + usage (0); + else if (arg[0] == '-') + usage (1); + else if (path == NULL) + path = arg; + else if (name == NULL) + name = arg; + else + usage (1); + } + + if (name == NULL) + usage (1); + + if (session_or_system && + (address != NULL)) + { + fprintf (stderr, "\"--address\" may not be used with \"--system\" or \"--session\"\n"); + usage (1); + } + + if (type_str != NULL) + { + message_type = dbus_message_type_from_string (type_str); + if (!(message_type == DBUS_MESSAGE_TYPE_METHOD_CALL || + message_type == DBUS_MESSAGE_TYPE_SIGNAL)) + { + fprintf (stderr, "Message type \"%s\" is not supported\n", + type_str); + exit (1); + } + } + + dbus_error_init (&error); + + if (address != NULL) + { + connection = dbus_connection_open (address, &error); + } + else + { + connection = dbus_bus_get (type, &error); + } + + if (connection == NULL) + { + fprintf (stderr, "Failed to open connection to \"%s\" message bus: %s\n", + (address != NULL) ? address : + ((type == DBUS_BUS_SYSTEM) ? "system" : "session"), + error.message); + dbus_error_free (&error); + exit (1); + } + + if (message_type == DBUS_MESSAGE_TYPE_METHOD_CALL) + { + char *last_dot; + + last_dot = strrchr (name, '.'); + if (last_dot == NULL) + { + fprintf (stderr, "Must use org.mydomain.Interface.Method notation, no dot in \"%s\"\n", + name); + exit (1); + } + *last_dot = '\0'; + + message = dbus_message_new_method_call (NULL, + path, + name, + last_dot + 1); + dbus_message_set_auto_start (message, TRUE); + } + else if (message_type == DBUS_MESSAGE_TYPE_SIGNAL) + { + char *last_dot; + + last_dot = strrchr (name, '.'); + if (last_dot == NULL) + { + fprintf (stderr, "Must use org.mydomain.Interface.Signal notation, no dot in \"%s\"\n", + name); + exit (1); + } + *last_dot = '\0'; + + message = dbus_message_new_signal (path, name, last_dot + 1); + } + else + { + fprintf (stderr, "Internal error, unknown message type\n"); + exit (1); + } + + if (message == NULL) + { + fprintf (stderr, "Couldn't allocate D-Bus message\n"); + exit (1); + } + + if (dest && !dbus_message_set_destination (message, dest)) + { + fprintf (stderr, "Not enough memory\n"); + exit (1); + } + + dbus_message_iter_init_append (message, &iter); + + while (i < argc) + { + char *arg; + char *c; + int type; + int secondary_type; + int container_type; + DBusMessageIter *target_iter; + DBusMessageIter container_iter; + + type = DBUS_TYPE_INVALID; + arg = argv[i++]; + c = strchr (arg, ':'); + + if (c == NULL) + { + fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg); + exit (1); + } + + *(c++) = 0; + + container_type = DBUS_TYPE_INVALID; + + if (strcmp (arg, "variant") == 0) + container_type = DBUS_TYPE_VARIANT; + else if (strcmp (arg, "array") == 0) + container_type = DBUS_TYPE_ARRAY; + else if (strcmp (arg, "dict") == 0) + container_type = DBUS_TYPE_DICT_ENTRY; + + if (container_type != DBUS_TYPE_INVALID) + { + arg = c; + c = strchr (arg, ':'); + if (c == NULL) + { + fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg); + exit (1); + } + *(c++) = 0; + } + + if (arg[0] == 0) + type = DBUS_TYPE_STRING; + else + type = type_from_name (arg); + + if (container_type == DBUS_TYPE_DICT_ENTRY) + { + char sig[5]; + arg = c; + c = strchr (c, ':'); + if (c == NULL) + { + fprintf (stderr, "%s: Data item \"%s\" is badly formed\n", argv[0], arg); + exit (1); + } + *(c++) = 0; + secondary_type = type_from_name (arg); + sig[0] = DBUS_DICT_ENTRY_BEGIN_CHAR; + sig[1] = type; + sig[2] = secondary_type; + sig[3] = DBUS_DICT_ENTRY_END_CHAR; + sig[4] = '\0'; + dbus_message_iter_open_container (&iter, + DBUS_TYPE_ARRAY, + sig, + &container_iter); + target_iter = &container_iter; + } + else if (container_type != DBUS_TYPE_INVALID) + { + char sig[2]; + sig[0] = type; + sig[1] = '\0'; + dbus_message_iter_open_container (&iter, + container_type, + sig, + &container_iter); + target_iter = &container_iter; + } + else + target_iter = &iter; + + if (container_type == DBUS_TYPE_ARRAY) + { + append_array (target_iter, type, c); + } + else if (container_type == DBUS_TYPE_DICT_ENTRY) + { + append_dict (target_iter, type, secondary_type, c); + } + else + append_arg (target_iter, type, c); + + if (container_type != DBUS_TYPE_INVALID) + { + dbus_message_iter_close_container (&iter, + &container_iter); + } + } + + if (print_reply) + { + DBusMessage *reply; + + dbus_error_init (&error); + reply = dbus_connection_send_with_reply_and_block (connection, + message, reply_timeout, + &error); + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "Error %s: %s\n", + error.name, + error.message); + exit (1); + } + + if (reply) + { + print_message (reply, print_reply_literal); + dbus_message_unref (reply); + } + } + else + { + dbus_connection_send (connection, message, NULL); + dbus_connection_flush (connection); + } + + dbus_message_unref (message); + + dbus_connection_unref (connection); + + exit (0); +} diff --git a/tools/dbus-uuidgen.1 b/tools/dbus-uuidgen.1 new file mode 100644 index 00000000..480fd18f --- /dev/null +++ b/tools/dbus-uuidgen.1 @@ -0,0 +1,89 @@ +.\" +.\" dbus-uuidgen manual page. +.\" Copyright (C) 2006 Red Hat, Inc. +.\" +.TH dbus-uuidgen 1 +.SH NAME +dbus-uuidgen \- Utility to generate UUIDs +.SH SYNOPSIS +.PP +.B dbus-uuidgen [\-\-version] [\-\-ensure[=FILENAME]] [\-\-get[=FILENAME]] + +.SH DESCRIPTION + +The \fIdbus-uuidgen\fP command generates or reads a universally unique ID. + +.PP +Note that the D-Bus UUID has no relationship to RFC 4122 and does not generate +UUIDs compatible with that spec. Many systems have a separate command +for that (often called "uuidgen"). + +.PP +See http://www.freedesktop.org/software/dbus/ for more information +about D-Bus. + +.PP +The primary usage of \fIdbus-uuidgen\fP is to run in the post-install +script of a D-Bus package like this: +.nf + dbus-uuidgen --ensure +.fi + +.PP +This will ensure that /var/lib/dbus/machine-id exists and has the uuid in it. +It won't overwrite an existing uuid, since this id should remain fixed +for a single machine until the next reboot at least. + +.PP +The important properties of the machine UUID are that 1) it remains +unchanged until the next reboot and 2) it is different for any two +running instances of the OS kernel. That is, if two processes see the +same UUID, they should also see the same shared memory, UNIX domain +sockets, local X displays, localhost.localdomain resolution, process +IDs, and so forth. + +.PP +If you run \fIdbus-uuidgen\fP with no options it just prints a new uuid made +up out of thin air. + +.PP +If you run it with --get, it prints the machine UUID by default, or +the UUID in the specified file if you specify a file. + +.PP +If you try to change an existing machine-id on a running system, it will +probably result in bad things happening. Don't try to change this file. Also, +don't make it the same on two different systems; it needs to be different +anytime there are two different kernels running. + +.PP +The UUID should be different on two different virtual machines, +because there are two different kernels. + +.SH OPTIONS +The following options are supported: +.TP +.I "--get[=FILENAME]" +If a filename is not given, defaults to localstatedir/lib/dbus/machine-id +(localstatedir is usually /var). If this file exists and is valid, the +uuid in the file is printed on stdout. Otherwise, the command exits +with a nonzero status. + +.TP +.I "--ensure[=FILENAME]" +If a filename is not given, defaults to localstatedir/lib/dbus/machine-id +(localstatedir is usually /var). If this file exists then it will be +validated, and a failure code returned if it contains the wrong thing. +If the file does not exist, it will be created with a new uuid in it. +On success, prints no output. + +.TP +.I "--version" +Print the version of dbus-uuidgen + +.SH AUTHOR +See http://www.freedesktop.org/software/dbus/doc/AUTHORS + +.SH BUGS +Please send bug reports to the D-Bus mailing list or bug tracker, +see http://www.freedesktop.org/software/dbus/ diff --git a/tools/dbus-uuidgen.c b/tools/dbus-uuidgen.c new file mode 100644 index 00000000..c8ba1cf7 --- /dev/null +++ b/tools/dbus-uuidgen.c @@ -0,0 +1,161 @@ +/* -*- mode: C; c-file-style: "gnu"; indent-tabs-mode: nil; -*- */ +/* dbus-uuidgen.c Utility program to create UUIDs + * + * Copyright (C) 2006 Red Hat, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA + * + */ + +#include <config.h> +#include <stdio.h> +#include <stdlib.h> +#include <string.h> + +#include <dbus/dbus-uuidgen.h> +#include <dbus/dbus.h> + +static void +usage (char *name, int ecode) +{ + if (name == NULL) + name = "dbus-uuidgen"; + + fprintf (stderr, "Usage: %s [--ensure[=FILENAME]] [--get[=FILENAME]]\n", name); + exit (ecode); +} + +static void +version (void) +{ + printf ("D-Bus UUID Generator %s\n" + "Copyright (C) 2006 Red Hat, Inc.\n" + "This is free software; see the source for copying conditions.\n" + "There is NO warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n", + VERSION); + exit (0); +} + +static dbus_bool_t +get_arg (const char *arg, + const char *option, + const char **value_p) +{ + const char *fn; + + if (strlen(arg) < strlen(option)) + return FALSE; + + fn = arg + strlen(option); + + if (!(*fn == '=' || *fn == ' ' || *fn == '\0')) + { + usage (NULL, 1); + } + + if (*fn == '=') + ++fn; + + while (*fn == ' ' && *fn != '\0') + ++fn; + + if (*fn != '\0') + { + *value_p = fn; + return TRUE; + } + + return FALSE; +} + +int +main (int argc, char *argv[]) +{ + int i; + const char *filename; + dbus_bool_t ensure_uuid; + dbus_bool_t get_uuid; + DBusError error; + + ensure_uuid = FALSE; + get_uuid = FALSE; + + filename = NULL; + + for (i = 1; i < argc; i++) + { + char *arg = argv[i]; + + if (strncmp (arg, "--ensure", strlen("--ensure")) == 0) + { + get_arg (arg, "--ensure", &filename); + ensure_uuid = TRUE; + } + else if (strncmp (arg, "--get", strlen("--get")) == 0) + { + get_arg (arg, "--get", &filename); + get_uuid = TRUE; + } + else if (strcmp (arg, "--help") == 0) + usage (argv[0], 0); + else if (strcmp (arg, "--version") == 0) + version (); + else + usage (argv[0], 1); + } + + if (get_uuid && ensure_uuid) + { + fprintf (stderr, "Can't specify both --get and --ensure\n"); + exit (1); + } + + dbus_error_init (&error); + + if (get_uuid || ensure_uuid) + { + char *uuid; + if (dbus_internal_do_not_use_get_uuid (filename, &uuid, ensure_uuid, &error)) + { + if (get_uuid) /* print nothing on --ensure */ + printf ("%s\n", uuid); + dbus_free (uuid); + } + } + else + { + char *uuid; + if (dbus_internal_do_not_use_create_uuid (&uuid)) + { + printf ("%s\n", uuid); + dbus_free (uuid); + } + else + { + dbus_set_error (&error, DBUS_ERROR_NO_MEMORY, "No memory"); + } + } + + if (dbus_error_is_set (&error)) + { + fprintf (stderr, "%s\n", error.message); + dbus_error_free (&error); + exit (1); + } + else + { + exit (0); + } +} diff --git a/tools/run-with-tmp-session-bus.sh b/tools/run-with-tmp-session-bus.sh new file mode 100755 index 00000000..982184a2 --- /dev/null +++ b/tools/run-with-tmp-session-bus.sh @@ -0,0 +1,76 @@ +#! /bin/bash + +SCRIPTNAME=$0 +WRAPPED_SCRIPT=$1 +shift + +die() +{ + if ! test -z "$DBUS_SESSION_BUS_PID" ; then + echo "killing message bus "$DBUS_SESSION_BUS_PID >&2 + kill -9 $DBUS_SESSION_BUS_PID + fi + echo $SCRIPTNAME: $* >&2 + exit 1 +} + +if test -z "$DBUS_TOP_BUILDDIR" ; then + die "Must set DBUS_TOP_BUILDDIR" +fi + +## convenient to be able to ctrl+C without leaking the message bus process +trap 'die "Received SIGINT"' INT + +CONFIG_FILE=./run-with-tmp-session-bus.conf +SERVICE_DIR="$DBUS_TOP_BUILDDIR/test/data/valid-service-files" +ESCAPED_SERVICE_DIR=`echo $SERVICE_DIR | sed -e 's/\//\\\\\\//g'` +echo "escaped service dir is: $ESCAPED_SERVICE_DIR" >&2 + +if test -z "$SOURCE_CONFIG_FILE"; then + SOURCE_CONFIG_FILE="$DBUS_TOP_BUILDDIR/bus/session.conf"; +fi +## create a configuration file based on the standard session.conf +cat $SOURCE_CONFIG_FILE | \ + sed -e 's/<standard_session_servicedirs.*$/<servicedir>'$ESCAPED_SERVICE_DIR'<\/servicedir>/g' | \ + sed -e 's/<include.*$//g' \ + > $CONFIG_FILE + +echo "Created configuration file $CONFIG_FILE" >&2 + +if ! test -e "$DBUS_TOP_BUILDDIR"/bus/dbus-daemon ; then + die "$DBUS_TOP_BUILDDIR/bus/dbus-daemon does not exist" +fi + +PATH="$DBUS_TOP_BUILDDIR"/bus:$PATH +export PATH + +## the libtool script found by the path search should already do this, but +LD_LIBRARY_PATH=$DBUS_TOP_BUILDDIR/dbus/.libs:$LD_LIBRARY_PATH +export LD_LIBRARY_PATH +unset DBUS_SESSION_BUS_ADDRESS +unset DBUS_SESSION_BUS_PID + +echo "Running $DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE" >&2 + +DBUS_USE_TEST_BINARY=1 +export DBUS_USE_TEST_BINARY +eval `$DBUS_TOP_BUILDDIR/tools/dbus-launch --sh-syntax --config-file=$CONFIG_FILE` + +if test -z "$DBUS_SESSION_BUS_PID" ; then + die "Failed to launch message bus for test script to run" +fi + +echo "Started bus pid $DBUS_SESSION_BUS_PID at $DBUS_SESSION_BUS_ADDRESS" >&2 + +# Execute wrapped script +echo "Running $WRAPPED_SCRIPT $@" >&2 +$WRAPPED_SCRIPT "$@" || die "script \"$WRAPPED_SCRIPT\" failed" + +kill -TERM $DBUS_SESSION_BUS_PID || die "Message bus vanished! should not have happened" && echo "Killed daemon $DBUS_SESSION_BUS_PID" >&2 + +sleep 2 + +## be sure it really died +kill -9 $DBUS_SESSION_BUS_PID > /dev/null 2>&1 || true + +exit 0 |