summaryrefslogtreecommitdiffstats
path: root/dbus/dbus-sysdeps.c
diff options
context:
space:
mode:
Diffstat (limited to 'dbus/dbus-sysdeps.c')
-rw-r--r--dbus/dbus-sysdeps.c130
1 files changed, 102 insertions, 28 deletions
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