summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--ChangeLog38
-rw-r--r--bus/bus.c47
-rw-r--r--bus/config-parser.c47
-rw-r--r--bus/config-parser.h1
-rwxr-xr-xbus/messagebus.in12
-rw-r--r--bus/system.conf.in5
-rw-r--r--configure.in49
-rw-r--r--dbus/Makefile.am2
-rw-r--r--dbus/dbus-sysdeps.c130
-rw-r--r--dbus/dbus-sysdeps.h15
10 files changed, 294 insertions, 52 deletions
diff --git a/ChangeLog b/ChangeLog
index ede733b3..75eed1b4 100644
--- a/ChangeLog
+++ b/ChangeLog
@@ -1,5 +1,43 @@
2003-04-06 Havoc Pennington <hp@pobox.com>
+ * dbus/dbus-sysdeps.c (_dbus_become_daemon): write the pidfile
+ here in the parent process, so we can return an error if it
+ fails. Also, move some of the code into the child so the parent
+ is less hosed if we fail midway through.
+
+ * bus/bus.c (bus_context_new): move pidfile detection further up
+ in the function, before we start overwriting sockets and such.
+
+ * bus/messagebus.in: adjust this a bit, not sure if it will work.
+
+ * configure.in: add --with-system-pid-file and --with-system-socket
+
+2003-04-06 Colin Walters <walters@verbum.org>
+
+ * configure.in (DBUS_SYSTEM_PID_FILE): New variable.
+
+ * bus/system.conf.in: Declare a pidfile.
+
+ * bus/bus.c (bus_context_new): Test for an existing pid file, and
+ create one (if appropriate).
+
+ * bus/config-parser.c (enum ElementType) [ELEMENT_PIDFILE]: New.
+ (struct BusConfigParser) [pidfile]: New.
+ (element_type_to_name, merge_included, start_busconfig_child)
+ (bus_config_parser_end_element, bus_config_parser_content): Handle it.
+ (bus_config_parser_unref): Free it.
+ (bus_config_parser_get_pidfile): New function.
+
+ * bus/config-parser.h (_dbus_write_pid_file): Prototype.
+
+ * dbus/dbus-errors.h (DBUS_ERROR_PIDFILE_EXISTS): New error.
+
+ * dbus/dbus-sysdeps.c (_dbus_write_pid_file): New function.
+
+ * dbus/dbus-sysdeps.h: Prototype it.
+
+2003-04-06 Havoc Pennington <hp@pobox.com>
+
* bus/bus.c (bus_context_new): print the address in here, rather
than in main(), because we need to do it before forking the daemon
diff --git a/bus/bus.c b/bus/bus.c
index 880f35d1..09a0b5bb 100644
--- a/bus/bus.c
+++ b/bus/bus.c
@@ -306,7 +306,7 @@ bus_context_new (const DBusString *config_file,
DBusList **addresses;
BusConfigParser *parser;
DBusString full_address;
- const char *user;
+ const char *user, *pidfile;
char **auth_mechanisms;
DBusList **auth_mechanisms_list;
int len;
@@ -333,6 +333,31 @@ bus_context_new (const DBusString *config_file,
parser = bus_config_load (config_file, error);
if (parser == NULL)
goto failed;
+
+ /* Check for an existing pid file. Of course this is a race;
+ * we'd have to use fcntl() locks on the pid file to
+ * avoid that. But we want to check for the pid file
+ * before overwriting any existing sockets, etc.
+ */
+ pidfile = bus_config_parser_get_pidfile (parser);
+ if (pidfile != NULL)
+ {
+ DBusString u;
+ DBusStat stbuf;
+ DBusError tmp_error;
+
+ dbus_error_init (&tmp_error);
+ _dbus_string_init_const (&u, pidfile);
+
+ if (_dbus_stat (&u, &stbuf, &tmp_error))
+ {
+ dbus_set_error (error, DBUS_ERROR_FAILED,
+ "The pid file \"%s\" exists, if the message bus is not running, remove this file",
+ pidfile);
+ dbus_error_free (&tmp_error);
+ goto failed;
+ }
+ }
context = dbus_new0 (BusContext, 1);
if (context == NULL)
@@ -587,9 +612,27 @@ bus_context_new (const DBusString *config_file,
/* Now become a daemon if appropriate */
if (bus_config_parser_get_fork (parser))
{
- if (!_dbus_become_daemon (error))
+ DBusString u;
+
+ if (pidfile)
+ _dbus_string_init_const (&u, pidfile);
+
+ if (!_dbus_become_daemon (pidfile ? &u : NULL, error))
goto failed;
}
+ else
+ {
+ /* Need to write PID file for ourselves, not for the child process */
+ if (pidfile != NULL)
+ {
+ DBusString u;
+
+ _dbus_string_init_const (&u, pidfile);
+
+ if (!_dbus_write_pid_file (&u, _dbus_getpid (), error))
+ goto failed;
+ }
+ }
bus_config_parser_unref (parser);
_dbus_string_free (&full_address);
diff --git a/bus/config-parser.c b/bus/config-parser.c
index f9473ff9..1052dc2d 100644
--- a/bus/config-parser.c
+++ b/bus/config-parser.c
@@ -40,6 +40,7 @@ typedef enum
ELEMENT_ALLOW,
ELEMENT_DENY,
ELEMENT_FORK,
+ ELEMENT_PIDFILE,
ELEMENT_SERVICEDIR,
ELEMENT_INCLUDEDIR,
ELEMENT_TYPE
@@ -94,6 +95,8 @@ struct BusConfigParser
DBusList *service_dirs; /**< Directories to look for services in */
unsigned int fork : 1; /**< TRUE to fork into daemon mode */
+
+ char *pidfile;
};
static const char*
@@ -123,6 +126,8 @@ element_type_to_name (ElementType type)
return "deny";
case ELEMENT_FORK:
return "fork";
+ case ELEMENT_PIDFILE:
+ return "pidfile";
case ELEMENT_SERVICEDIR:
return "servicedir";
case ELEMENT_INCLUDEDIR:
@@ -222,6 +227,13 @@ merge_included (BusConfigParser *parser,
if (included->fork)
parser->fork = TRUE;
+
+ if (included->pidfile != NULL)
+ {
+ dbus_free (parser->pidfile);
+ parser->pidfile = included->pidfile;
+ included->pidfile = NULL;
+ }
while ((link = _dbus_list_pop_first_link (&included->listen_on)))
_dbus_list_append_link (&parser->listen_on, link);
@@ -284,6 +296,7 @@ bus_config_parser_unref (BusConfigParser *parser)
dbus_free (parser->user);
dbus_free (parser->bus_type);
+ dbus_free (parser->pidfile);
_dbus_list_foreach (&parser->listen_on,
(DBusForeachFunction) dbus_free,
@@ -499,6 +512,19 @@ start_busconfig_child (BusConfigParser *parser,
return TRUE;
}
+ else if (strcmp (element_name, "pidfile") == 0)
+ {
+ if (!check_no_attributes (parser, "pidfile", attribute_names, attribute_values, error))
+ return FALSE;
+
+ if (push_element (parser, ELEMENT_PIDFILE) == NULL)
+ {
+ BUS_SET_OOM (error);
+ return FALSE;
+ }
+
+ return TRUE;
+ }
else if (strcmp (element_name, "listen") == 0)
{
if (!check_no_attributes (parser, "listen", attribute_names, attribute_values, error))
@@ -770,6 +796,7 @@ bus_config_parser_end_element (BusConfigParser *parser,
case ELEMENT_USER:
case ELEMENT_TYPE:
case ELEMENT_LISTEN:
+ case ELEMENT_PIDFILE:
case ELEMENT_AUTH:
case ELEMENT_SERVICEDIR:
case ELEMENT_INCLUDEDIR:
@@ -1004,6 +1031,20 @@ bus_config_parser_content (BusConfigParser *parser,
return FALSE;
}
+ case ELEMENT_PIDFILE:
+ {
+ char *s;
+
+ e->had_content = TRUE;
+
+ if (!_dbus_string_copy_data (content, &s))
+ goto nomem;
+
+ dbus_free (parser->pidfile);
+ parser->pidfile = s;
+ }
+ break;
+
case ELEMENT_INCLUDE:
{
DBusString full_path;
@@ -1222,6 +1263,12 @@ bus_config_parser_get_fork (BusConfigParser *parser)
return parser->fork;
}
+const char *
+bus_config_parser_get_pidfile (BusConfigParser *parser)
+{
+ return parser->pidfile;
+}
+
#ifdef DBUS_BUILD_TESTS
#include <stdio.h>
diff --git a/bus/config-parser.h b/bus/config-parser.h
index af5c8260..93d41003 100644
--- a/bus/config-parser.h
+++ b/bus/config-parser.h
@@ -60,6 +60,7 @@ const char* bus_config_parser_get_type (BusConfigParser *parser);
DBusList** bus_config_parser_get_addresses (BusConfigParser *parser);
DBusList** bus_config_parser_get_mechanisms (BusConfigParser *parser);
dbus_bool_t bus_config_parser_get_fork (BusConfigParser *parser);
+const char* bus_config_parser_get_pidfile (BusConfigParser *parser);
DBusList** bus_config_parser_get_service_dirs (BusConfigParser *parser);
/* Loader functions (backended off one of the XML parsers). Returns a
diff --git a/bus/messagebus.in b/bus/messagebus.in
index 60c70777..45388a5e 100755
--- a/bus/messagebus.in
+++ b/bus/messagebus.in
@@ -7,7 +7,7 @@
# and other messages. See http://www.freedesktop.org/software/dbus/
#
# processname: dbus-daemon-1
-# pidfile: @EXPANDED_LOCALSTATEDIR@/messagebus.pid
+# pidfile: @DBUS_SYSTEM_PID_FILE@
#
# Sanity checks.
@@ -20,7 +20,7 @@ RETVAL=0
start() {
echo -n $"Starting system message bus: "
- daemon dbus-daemon-1 --system
+ daemon --check messagebus dbus-daemon-1 --system
RETVAL=$?
echo
[ $RETVAL -eq 0 ] && touch @EXPANDED_LOCALSTATEDIR@/lock/subsys/messagebus
@@ -28,7 +28,11 @@ start() {
stop() {
echo -n $"Stopping system message bus: "
- killproc messagebus
+
+ ## we don't want to kill all the per-user dbus-daemon-1, we want
+ ## to use the pid file *only*; because we use the fake nonexistent
+ ## program name "messagebus" that should be safe-ish
+ killproc messagebus -TERM
RETVAL=$?
echo
if [ $RETVAL -eq 0 ]; then
@@ -59,7 +63,7 @@ case "$1" in
fi
;;
reload)
- killproc messagebus -HUP
+ echo "Message bus can't reload its configuration, you have to restart it"
RETVAL=$?
;;
*)
diff --git a/bus/system.conf.in b/bus/system.conf.in
index 15a4972e..0e570575 100644
--- a/bus/system.conf.in
+++ b/bus/system.conf.in
@@ -20,11 +20,14 @@
<!-- Fork into daemon mode -->
<fork/>
+ <!-- Write a pid file -->
+ <pidfile>@DBUS_SYSTEM_PID_FILE@</pidfile>
+
<!-- Only allow socket-credentials-based authentication -->
<auth>EXTERNAL</auth>
<!-- Only listen on a local socket -->
- <listen>unix:path=@EXPANDED_LOCALSTATEDIR@/@DBUS_SYSTEM_SOCKET@</listen>
+ <listen>unix:path=@DBUS_SYSTEM_SOCKET@</listen>
<policy context="default">
<!-- Deny everything then punch holes -->
diff --git a/configure.in b/configure.in
index d37a7c4b..e908d3ee 100644
--- a/configure.in
+++ b/configure.in
@@ -35,6 +35,8 @@ AC_ARG_WITH(xml, [ --with-xml=[libxml/expat] XML library to use]
AC_ARG_WITH(init-scripts, [ --with-init-scripts=[redhat] Style of init scripts to install])
AC_ARG_WITH(session-socket-dir, [ --with-session-socket-dir=[dirname] Where to put sockets for the per-login-session message bus])
AC_ARG_WITH(test-socket-dir, [ --with-test-socket-dir=[dirname] Where to put sockets for make check])
+AC_ARG_WITH(system-pid-file, [ --with-system-pid-file=[pidfile] PID file for systemwide daemon])
+AC_ARG_WITH(system-socket, [ --with-system-socket=[filename] UNIX domain socket for systemwide daemon])
dnl DBUS_BUILD_TESTS controls unit tests built in to .c files
dnl and also some stuff in the test/ subdir
@@ -385,12 +387,9 @@ dnl Qt flags
AC_SUBST(DBUS_QT_CXXFLAGS)
AC_SUBST(DBUS_QT_LIBS)
-##### Set up location for system bus socket
-## name of socket relative to localstatedir
-DBUS_SYSTEM_SOCKET=run/dbus/system_bus_socket
-AC_SUBST(DBUS_SYSTEM_SOCKET)
-
#### find the actual value for $prefix that we'll end up with
+## (I know this is broken and should be done in the Makefile, but
+## that's a major pain and almost nobody actually seems to care)
REAL_PREFIX=
if test "x$prefix" = "xNONE"; then
REAL_PREFIX=$ac_default_prefix
@@ -421,18 +420,45 @@ EXPANDED_BINDIR=`eval echo $BINDIR_TMP`
prefix=$old_prefix
AC_SUBST(EXPANDED_BINDIR)
+#### Check our operating system
+operating_system=unknown
+if test -f /etc/redhat-release || test -f $EXPANDED_SYSCONFDIR/redhat-release ; then
+ operating_system=redhat
+fi
+
#### Sort out init scripts
if test x$with_init_scripts = x; then
- if test -f /etc/redhat-release || test -f $EXPANDED_SYSCONFDIR/redhat-release ; then
- with_init_scripts=redhat
- else
- with_init_scripts=none
- fi
+ if test xredhat = x$operating_system ; then
+ with_init_scripts=redhat
+ else
+ with_init_scripts=none
+ fi
fi
AM_CONDITIONAL(DBUS_INIT_SCRIPTS_RED_HAT, test x$with_init_scripts = xredhat)
+
+##### Set up location for system bus socket
+if ! test -z "$with_system_socket"; then
+ DBUS_SYSTEM_SOCKET=$with_system_socket
+else
+ DBUS_SYSTEM_SOCKET=${EXPANDED_LOCALSTATEDIR}/run/dbus/system_bus_socket
+fi
+
+AC_SUBST(DBUS_SYSTEM_SOCKET)
+
+#### Set up the pid file
+if ! test -z "$with_system_pid_file"; then
+ DBUS_SYSTEM_PID_FILE=$with_system_pid_file
+elif test x$operating_system = xredhat ; then
+ DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/messagebus.pid
+else
+ DBUS_SYSTEM_PID_FILE=${EXPANDED_LOCALSTATEDIR}/run/dbus/pid
+fi
+
+AC_SUBST(DBUS_SYSTEM_PID_FILE)
+
#### Tell tests where to find certain stuff in builddir
ABSOLUTE_TOP_BUILDDIR=`cd ${ac_top_builddir}. && pwd`
@@ -512,7 +538,8 @@ echo "
Building GLib bindings: ${have_glib}
Using XML parser: ${with_xml}
Init scripts style: ${with_init_scripts}
- System bus socket: ${EXPANDED_LOCALSTATEDIR}/${DBUS_SYSTEM_SOCKET}
+ System bus socket: ${DBUS_SYSTEM_SOCKET}
+ System bus PID file: ${DBUS_SYSTEM_PID_FILE}
Session bus socket dir: ${DBUS_SESSION_SOCKET_DIR}
'make check' socket dir: ${TEST_SOCKET_DIR}
"
diff --git a/dbus/Makefile.am b/dbus/Makefile.am
index 2065e75e..7d5ed501 100644
--- a/dbus/Makefile.am
+++ b/dbus/Makefile.am
@@ -1,6 +1,6 @@
INCLUDES=-I$(top_srcdir) $(DBUS_CLIENT_CFLAGS) -DDBUS_COMPILATION \
- -DDBUS_SYSTEM_BUS_PATH=\""@EXPANDED_LOCALSTATEDIR@/@DBUS_SYSTEM_SOCKET@"\"
+ -DDBUS_SYSTEM_BUS_PATH=\""@DBUS_SYSTEM_SOCKET@"\"
dbusincludedir=$(includedir)/dbus-1.0/dbus
diff --git a/dbus/dbus-sysdeps.c b/dbus/dbus-sysdeps.c
index 7a389956..df921b17 100644
--- a/dbus/dbus-sysdeps.c
+++ b/dbus/dbus-sysdeps.c
@@ -1700,6 +1700,15 @@ _dbus_string_append_our_uid (DBusString *str)
return _dbus_string_append_int (str, getuid ());
}
+/**
+ * Gets our process ID
+ * @returns process ID
+ */
+unsigned long
+_dbus_getpid (void)
+{
+ return getpid ();
+}
_DBUS_DEFINE_GLOBAL_LOCK (atomic);
@@ -2930,17 +2939,17 @@ _dbus_print_backtrace (void)
/**
* Does the chdir, fork, setsid, etc. to become a daemon process.
*
+ * @param pidfile #NULL, or pidfile to create
* @param error return location for errors
* @returns #FALSE on failure
*/
dbus_bool_t
-_dbus_become_daemon (DBusError *error)
+_dbus_become_daemon (const DBusString *pidfile,
+ DBusError *error)
{
const char *s;
+ pid_t child_pid;
- /* This is so we don't prevent unmounting of devices. We divert
- * all messages to syslog
- */
if (chdir ("/") < 0)
{
dbus_set_error (error, DBUS_ERROR_FAILED,
@@ -2948,29 +2957,7 @@ _dbus_become_daemon (DBusError *error)
return FALSE;
}
- s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
- if (s == NULL || *s == '\0')
- {
- int dev_null_fd;
-
- /* silently ignore failures here, if someone
- * doesn't have /dev/null we may as well try
- * to continue anyhow
- */
-
- dev_null_fd = open ("/dev/null", O_RDWR);
- if (dev_null_fd >= 0)
- {
- dup2 (dev_null_fd, 0);
- dup2 (dev_null_fd, 1);
- dup2 (dev_null_fd, 2);
- }
- }
-
- /* Get a predictable umask */
- umask (022);
-
- switch (fork ())
+ switch ((child_pid = fork ()))
{
case -1:
dbus_set_error (error, _dbus_error_from_errno (errno),
@@ -2978,10 +2965,41 @@ _dbus_become_daemon (DBusError *error)
return FALSE;
break;
- case 0:
+ case 0:
+ s = _dbus_getenv ("DBUS_DEBUG_OUTPUT");
+ if (s == NULL || *s == '\0')
+ {
+ int dev_null_fd;
+
+ /* silently ignore failures here, if someone
+ * doesn't have /dev/null we may as well try
+ * to continue anyhow
+ */
+
+ dev_null_fd = open ("/dev/null", O_RDWR);
+ if (dev_null_fd >= 0)
+ {
+ dup2 (dev_null_fd, 0);
+ dup2 (dev_null_fd, 1);
+ dup2 (dev_null_fd, 2);
+ }
+ }
+
+ /* Get a predictable umask */
+ umask (022);
break;
default:
+ if (pidfile)
+ {
+ if (!_dbus_write_pid_file (pidfile,
+ child_pid,
+ error))
+ {
+ kill (child_pid, SIGTERM);
+ return FALSE;
+ }
+ }
_exit (0);
break;
}
@@ -2993,6 +3011,62 @@ _dbus_become_daemon (DBusError *error)
}
/**
+ * Creates a file containing the process ID.
+ *
+ * @param filename the filename to write to
+ * @param pid our process ID
+ * @param error return location for errors
+ * @returns #FALSE on failure
+ */
+dbus_bool_t
+_dbus_write_pid_file (const DBusString *filename,
+ unsigned long pid,
+ DBusError *error)
+{
+ const char *cfilename;
+ int fd;
+ FILE *f;
+
+ cfilename = _dbus_string_get_const_data (filename);
+
+ fd = open (cfilename, O_WRONLY|O_CREAT|O_EXCL|O_BINARY, 0644);
+
+ if (fd < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to open \"%s\": %s", cfilename,
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ if ((f = fdopen (fd, "w")) == NULL)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to fdopen fd %d: %s", fd, _dbus_strerror (errno));
+ close (fd);
+ return FALSE;
+ }
+
+ if (fprintf (f, "%lu\n", pid) < 0)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to write to \"%s\": %s", cfilename,
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ if (fclose (f) == EOF)
+ {
+ dbus_set_error (error, _dbus_error_from_errno (errno),
+ "Failed to close \"%s\": %s", cfilename,
+ _dbus_strerror (errno));
+ return FALSE;
+ }
+
+ return TRUE;
+}
+
+/**
* Changes the user and group the bus is running as.
*
* @param uid the new user ID
diff --git a/dbus/dbus-sysdeps.h b/dbus/dbus-sysdeps.h
index 933e2775..0a4a34dd 100644
--- a/dbus/dbus-sysdeps.h
+++ b/dbus/dbus-sysdeps.h
@@ -119,6 +119,8 @@ dbus_bool_t _dbus_get_groups (unsigned long uid,
unsigned long **group_ids,
int *n_group_ids);
+unsigned long _dbus_getpid (void);
+
typedef int dbus_atomic_t;
dbus_atomic_t _dbus_atomic_inc (dbus_atomic_t *atomic);
@@ -216,11 +218,14 @@ dbus_bool_t _dbus_close (int fd,
void _dbus_print_backtrace (void);
-dbus_bool_t _dbus_become_daemon (DBusError *error);
-
-dbus_bool_t _dbus_change_identity (unsigned long uid,
- unsigned long gid,
- DBusError *error);
+dbus_bool_t _dbus_become_daemon (const DBusString *pidfile,
+ DBusError *error);
+dbus_bool_t _dbus_write_pid_file (const DBusString *filename,
+ unsigned long pid,
+ DBusError *error);
+dbus_bool_t _dbus_change_identity (unsigned long uid,
+ unsigned long gid,
+ DBusError *error);
typedef void (* DBusSignalHandler) (int sig);