diff options
| -rw-r--r-- | ChangeLog | 38 | ||||
| -rw-r--r-- | bus/bus.c | 47 | ||||
| -rw-r--r-- | bus/config-parser.c | 47 | ||||
| -rw-r--r-- | bus/config-parser.h | 1 | ||||
| -rwxr-xr-x | bus/messagebus.in | 12 | ||||
| -rw-r--r-- | bus/system.conf.in | 5 | ||||
| -rw-r--r-- | configure.in | 49 | ||||
| -rw-r--r-- | dbus/Makefile.am | 2 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.c | 130 | ||||
| -rw-r--r-- | dbus/dbus-sysdeps.h | 15 | 
10 files changed, 294 insertions, 52 deletions
@@ -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 @@ -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);  | 
