dbus_bool_t _dbus_user_at_console (const char *username, DBusError *error) { DBusString f; dbus_bool_t result; result = FALSE; if (!_dbus_string_init (&f)) { _DBUS_SET_OOM (error); return FALSE; } if (!_dbus_string_append (&f, DBUS_CONSOLE_AUTH_DIR)) { _DBUS_SET_OOM (error); goto out; } if (!_dbus_string_append (&f, username)) { _DBUS_SET_OOM (error); goto out; } result = _dbus_file_exists (_dbus_string_get_const_data (&f)); out: _dbus_string_free (&f); return result; }
static dbus_bool_t create_unique_client_name (BusRegistry *registry, DBusString *str) { /* We never want to use the same unique client name twice, because * we want to guarantee that if you send a message to a given unique * name, you always get the same application. So we use two numbers * for INT_MAX * INT_MAX combinations, should be pretty safe against * wraparound. */ /* FIXME these should be in BusRegistry rather than static vars */ static int next_major_number = 0; static int next_minor_number = 0; int len; len = _dbus_string_get_length (str); while (TRUE) { /* start out with 1-0, go to 1-1, 1-2, 1-3, * up to 1-MAXINT, then 2-0, 2-1, etc. */ if (next_minor_number <= 0) { next_major_number += 1; next_minor_number = 0; if (next_major_number <= 0) _dbus_assert_not_reached ("INT_MAX * INT_MAX clients were added"); } _dbus_assert (next_major_number > 0); _dbus_assert (next_minor_number >= 0); /* appname:MAJOR-MINOR */ if (!_dbus_string_append (str, ":")) return FALSE; if (!_dbus_string_append_int (str, next_major_number)) return FALSE; if (!_dbus_string_append (str, ".")) return FALSE; if (!_dbus_string_append_int (str, next_minor_number)) return FALSE; next_minor_number += 1; /* Check if a client with the name exists */ if (bus_registry_lookup (registry, str) == NULL) break; /* drop the number again, try the next one. */ _dbus_string_set_length (str, len); } return TRUE; }
static dbus_bool_t _dbus_append_pair_str (DBusString *auxdata, const char *name, const char *value) { return _dbus_string_append (auxdata, " ") && _dbus_string_append (auxdata, name) && _dbus_string_append (auxdata, "=\"") && _dbus_string_append (auxdata, value) && _dbus_string_append (auxdata, "\""); }
static dbus_bool_t _dbus_append_pair_uint (DBusString *auxdata, const char *name, unsigned long value) { return _dbus_string_append (auxdata, " ") && _dbus_string_append (auxdata, name) && _dbus_string_append (auxdata, "=") && _dbus_string_append_uint (auxdata, value); }
/** * Creates a new transport for the given Unix domain socket * path. This creates a client-side of a transport. * * @todo once we add a way to escape paths in a dbus * address, this function needs to do escaping. * * @param path the path to the domain socket. * @param abstract #TRUE to use abstract socket namespace * @param error address where an error can be returned. * @returns a new transport, or #NULL on failure. */ DBusTransport* _dbus_transport_new_for_domain_socket (const char *path, dbus_bool_t abstract, DBusError *error) { int fd; DBusTransport *transport; DBusString address; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!_dbus_string_init (&address)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } fd = -1; if ((abstract && !_dbus_string_append (&address, "unix:abstract=")) || (!abstract && !_dbus_string_append (&address, "unix:path=")) || !_dbus_string_append (&address, path)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed_0; } fd = _dbus_connect_unix_socket (path, abstract, error); if (fd < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); goto failed_0; } _dbus_verbose ("Successfully connected to unix socket %s\n", path); transport = _dbus_transport_new_for_socket (fd, NULL, &address); if (transport == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed_1; } _dbus_string_free (&address); return transport; failed_1: _dbus_close_socket (fd, NULL); failed_0: _dbus_string_free (&address); return NULL; }
/** * Creates a new transport for the given VMWare Communication Interface * CID and port. This creates a client-side of a transport. * * @param cid the virtual machine context ID to connect to * @param port the port to connect to * @param error address where an error can be returned. * @returns a new transport, or #NULL on failure. */ static DBusTransport* _dbus_transport_new_for_vmci (const char *cid, const char *port, DBusError *error) { int fd; DBusTransport *transport; DBusString address; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!_dbus_string_init (&address)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } fd = -1; if (!_dbus_string_append (&address, "vmci:cid=") || !_dbus_string_append(&address, cid) || !_dbus_string_append(&address, "port=") || !_dbus_string_append(&address, port)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed_0; } fd = _dbus_connect_vmci (cid, port, error); if (fd < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); goto failed_0; } _dbus_verbose ("Successfully connected to vmci stream socket %s:%s\n", cid, port); transport = _dbus_transport_new_for_socket (fd, NULL, &address); if (transport == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed_1; } _dbus_string_free (&address); return transport; failed_1: _dbus_close_socket (fd, NULL); failed_0: _dbus_string_free (&address); return NULL; }
static dbus_bool_t build_common_query (DBusString *query, const char *con, const char *bustype) { /** * libapparmor's aa_query_label() function scribbles over the first * AA_QUERY_CMD_LABEL_SIZE bytes of the query string with a private value. */ return _dbus_string_insert_bytes (query, 0, AA_QUERY_CMD_LABEL_SIZE, 0) && _dbus_string_append (query, con) && _dbus_string_append_byte (query, '\0') && _dbus_string_append_byte (query, AA_CLASS_DBUS) && _dbus_string_append (query, bustype ? bustype : ""); }
int main (int argc, char **argv) { #ifdef DBUS_BUILD_TESTS const char *dir; DBusString config_file; if (argc > 1) dir = argv[1]; else dir = _dbus_getenv ("DBUS_TEST_DATA"); if (dir == NULL) { fprintf (stderr, "Must specify test data directory as argv[1] or in DBUS_TEST_DATA env variable\n"); return 1; } printf ("%s: Running launch helper OOM checks\n", argv[0]); if (!_dbus_string_init (&config_file)) return 1; if (!_dbus_string_append (&config_file, dir)) return 1; if (!_dbus_string_append (&config_file, "/valid-config-files-system/debug-allow-all-pass.conf")) return 1; /* use a config file that will actually work... */ _dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG", _dbus_string_get_const_data (&config_file)); _dbus_string_free (&config_file); if (!_dbus_test_oom_handling ("dbus-daemon-launch-helper", bus_activation_helper_oom_test, "org.freedesktop.DBus.TestSuiteEchoService")) die ("OOM failed"); test_post_hook (argv[0]); printf ("%s: Success\n", argv[0]); return 0; #else /* DBUS_BUILD_TESTS */ printf ("Not compiled with test support\n"); return 0; #endif }
/* * Return TRUE on successful check, FALSE on OOM. * Set *is_supported to whether AA has D-Bus features. */ static dbus_bool_t _bus_apparmor_detect_aa_dbus_support (dbus_bool_t *is_supported) { int mask_file; DBusString aa_dbus; char *aa_securityfs = NULL; dbus_bool_t retval = FALSE; *is_supported = FALSE; if (!_dbus_string_init (&aa_dbus)) return FALSE; if (aa_find_mountpoint (&aa_securityfs) != 0) goto out; /* * John Johansen has confirmed that the mainline kernel will not have * the apparmorfs/features/dbus/mask file until the mainline kernel * has AppArmor getpeersec support. */ if (!_dbus_string_append (&aa_dbus, aa_securityfs) || !_dbus_string_append (&aa_dbus, "/features/dbus/mask")) goto out; /* We need to open() the flag file, not just stat() it, because AppArmor * does not mediate stat() in the apparmorfs. If you have a * dbus-daemon inside an LXC container, with insufficiently broad * AppArmor privileges to do its own AppArmor mediation, the desired * result is that it behaves as if AppArmor was not present; but a stat() * here would succeed, and result in it trying and failing to do full * mediation. https://bugs.launchpad.net/ubuntu/+source/dbus/+bug/1238267 */ mask_file = open (_dbus_string_get_const_data (&aa_dbus), O_RDONLY | O_CLOEXEC); if (mask_file != -1) { *is_supported = TRUE; close (mask_file); } retval = TRUE; out: free (aa_securityfs); _dbus_string_free (&aa_dbus); return retval; }
static dbus_bool_t write_args_for_direction (DBusString *xml, const char *signature, dbus_bool_t in) { DBusTypeReader typereader; DBusString sigstr; int current_type; _dbus_string_init_const (&sigstr, signature); _dbus_type_reader_init_types_only (&typereader, &sigstr, 0); while ((current_type = _dbus_type_reader_get_current_type (&typereader)) != DBUS_TYPE_INVALID) { const DBusString *subsig; int start, len; _dbus_type_reader_get_signature (&typereader, &subsig, &start, &len); if (!_dbus_string_append_printf (xml, " <arg direction=\"%s\" type=\"", in ? "in" : "out")) goto oom; if (!_dbus_string_append_len (xml, _dbus_string_get_const_data (subsig) + start, len)) goto oom; if (!_dbus_string_append (xml, "\"/>\n")) goto oom; _dbus_type_reader_next (&typereader); } return TRUE; oom: return FALSE; }
dbus_bool_t _dbus_homedir_from_username (const DBusString *username, DBusString *homedir) { DBusUserDatabase *db; const DBusUserInfo *info; _dbus_user_database_lock_system (); db = _dbus_user_database_get_system (); if (db == NULL) { _dbus_user_database_unlock_system (); return FALSE; } if (!_dbus_user_database_get_username (db, username, &info, NULL)) { _dbus_user_database_unlock_system (); return FALSE; } if (!_dbus_string_append (homedir, info->homedir)) { _dbus_user_database_unlock_system (); return FALSE; } _dbus_user_database_unlock_system (); return TRUE; }
/* this is a little fragile since it assumes the address doesn't * already have a guid, but it shouldn't */ static char* copy_address_with_guid_appended (const DBusString *address, const DBusString *guid_hex) { DBusString with_guid; char *retval; if (!_dbus_string_init (&with_guid)) return NULL; if (!_dbus_string_copy (address, 0, &with_guid, _dbus_string_get_length (&with_guid)) || !_dbus_string_append (&with_guid, ",guid=") || !_dbus_string_copy (guid_hex, 0, &with_guid, _dbus_string_get_length (&with_guid))) { _dbus_string_free (&with_guid); return NULL; } retval = NULL; _dbus_string_steal_data (&with_guid, &retval); _dbus_string_free (&with_guid); return retval; /* may be NULL if steal_data failed */ }
/** * Gets the home directory for the given user. * * @param uid the uid * @param homedir string to append home directory to * @returns #TRUE if user existed and we appended their homedir */ dbus_bool_t _dbus_homedir_from_uid (dbus_uid_t uid, DBusString *homedir) { DBusUserDatabase *db; const DBusUserInfo *info; /* FIXME: this can't distinguish ENOMEM from other errors */ if (!_dbus_user_database_lock_system ()) return FALSE; db = _dbus_user_database_get_system (); if (db == NULL) { _dbus_user_database_unlock_system (); return FALSE; } if (!_dbus_user_database_get_uid (db, uid, &info, NULL)) { _dbus_user_database_unlock_system (); return FALSE; } if (!_dbus_string_append (homedir, info->homedir)) { _dbus_user_database_unlock_system (); return FALSE; } _dbus_user_database_unlock_system (); return TRUE; }
dbus_bool_t _dbus_directory_get_next_file (DBusDirIter *iter, DBusString *filename, DBusError *error) { struct dirent *d, *ent; size_t buf_size; int err; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!dirent_buf_size (iter->d, &buf_size)) { dbus_set_error (error, DBUS_ERROR_FAILED, "Can't calculate buffer size when reading directory"); return FALSE; } d = (struct dirent *)dbus_malloc (buf_size); if (!d) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "No memory to read directory entry"); return FALSE; } again: err = readdir_r (iter->d, d, &ent); if (err || !ent) { if (err != 0) dbus_set_error (error, _dbus_error_from_errno (err), "%s", _dbus_strerror (err)); dbus_free (d); return FALSE; } else if (ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) goto again; else { _dbus_string_set_length (filename, 0); if (!_dbus_string_append (filename, ent->d_name)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "No memory to read directory entry"); dbus_free (d); return FALSE; } else { dbus_free (d); return TRUE; } } }
static dbus_bool_t query_append (DBusString *query, const char *buffer) { if (!_dbus_string_append_byte (query, '\0')) return FALSE; if (buffer && !_dbus_string_append (query, buffer)) return FALSE; return TRUE; }
dbus_bool_t _dbus_string_get_dirname (const DBusString *filename, DBusString *dirname) { int sep; _dbus_assert (filename != dirname); _dbus_assert (filename != NULL); _dbus_assert (dirname != NULL); /* Ignore any separators on the end */ sep = _dbus_string_get_length (filename); if (sep == 0) return _dbus_string_append (dirname, "."); /* empty string passed in */ while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') --sep; _dbus_assert (sep >= 0); if (sep == 0) return _dbus_string_append (dirname, "/"); /* Now find the previous separator */ _dbus_string_find_byte_backward (filename, sep, '/', &sep); if (sep < 0) return _dbus_string_append (dirname, "."); /* skip multiple separators */ while (sep > 0 && _dbus_string_get_byte (filename, sep - 1) == '/') --sep; _dbus_assert (sep >= 0); if (sep == 0 && _dbus_string_get_byte (filename, 0) == '/') return _dbus_string_append (dirname, "/"); else return _dbus_string_copy_len (filename, 0, sep - 0, dirname, _dbus_string_get_length (dirname)); }
int main (int argc, char **argv) { const char *dir; DBusString config_file; if (argc > 1 && strcmp (argv[1], "--tap") != 0) dir = argv[1]; else dir = _dbus_getenv ("DBUS_TEST_DATA"); if (dir == NULL) _dbus_test_fatal ("Must specify test data directory as argv[1] or in DBUS_TEST_DATA env variable"); _dbus_test_diag ("%s: Running launch helper OOM checks", argv[0]); if (!_dbus_string_init (&config_file) || !_dbus_string_append (&config_file, dir) || !_dbus_string_append (&config_file, "/valid-config-files-system/debug-allow-all-pass.conf")) _dbus_test_fatal ("OOM during initialization"); /* use a config file that will actually work... */ dbus_setenv ("TEST_LAUNCH_HELPER_CONFIG", _dbus_string_get_const_data (&config_file)); _dbus_string_free (&config_file); if (!_dbus_test_oom_handling ("dbus-daemon-launch-helper", bus_activation_helper_oom_test, (char *) "org.freedesktop.DBus.TestSuiteEchoService")) _dbus_test_fatal ("OOM test failed"); /* ... otherwise it must have passed */ _dbus_test_ok ("%s", argv[0]); _dbus_test_check_memleaks (argv[0]); return _dbus_test_done_testing (); }
/** * Get next file in the directory. Will not return "." or ".." on * UNIX. If an error occurs, the contents of "filename" are * undefined. The error is never set if the function succeeds. * * This function is not re-entrant, and not necessarily thread-safe. * Only use it for test code or single-threaded utilities. * * @param iter the iterator * @param filename string to be set to the next file in the dir * @param error return location for error * @returns #TRUE if filename was filled in with a new filename */ dbus_bool_t _dbus_directory_get_next_file (DBusDirIter *iter, DBusString *filename, DBusError *error) { struct dirent *ent; int err; _DBUS_ASSERT_ERROR_IS_CLEAR (error); again: errno = 0; ent = readdir (iter->d); if (!ent) { err = errno; if (err != 0) dbus_set_error (error, _dbus_error_from_errno (err), "%s", _dbus_strerror (err)); return FALSE; } else if (ent->d_name[0] == '.' && (ent->d_name[1] == '\0' || (ent->d_name[1] == '.' && ent->d_name[2] == '\0'))) goto again; else { _dbus_string_set_length (filename, 0); if (!_dbus_string_append (filename, ent->d_name)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "No memory to read directory entry"); return FALSE; } else { return TRUE; } } }
static dbus_bool_t print_replace_install_prefix(const char *s) { DBusString str; if (!_dbus_string_init (&str)) { _dbus_assert_not_reached ("out of memory"); return FALSE; } if (!_dbus_string_append (&str, s) || !_dbus_replace_install_prefix (&str)) { _dbus_assert_not_reached ("out of memory"); _dbus_string_free (&str); return FALSE; } fprintf(stdout, "replaced '%s' by '%s'\n", s, _dbus_string_get_const_data (&str)); _dbus_string_free (&str); return TRUE; }
int main (int argc, char **argv) { DBusError error; DBusString config_file; DBusString address; DBusString addr_fd; DBusString pid_fd; const char *prev_arg; DBusPipe print_addr_pipe; DBusPipe print_pid_pipe; int i; dbus_bool_t print_address; dbus_bool_t print_pid; BusContextFlags flags; if (!_dbus_string_init (&config_file)) return 1; if (!_dbus_string_init (&address)) return 1; if (!_dbus_string_init (&addr_fd)) return 1; if (!_dbus_string_init (&pid_fd)) return 1; print_address = FALSE; print_pid = FALSE; flags = BUS_CONTEXT_FLAG_WRITE_PID_FILE; 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 (); } else if (strcmp (arg, "--version") == 0) { version (); } else if (strcmp (arg, "--introspect") == 0) { introspect (); } else if (strcmp (arg, "--nofork") == 0) { flags &= ~BUS_CONTEXT_FLAG_FORK_ALWAYS; flags |= BUS_CONTEXT_FLAG_FORK_NEVER; } #ifdef DBUS_UNIX else if (strcmp (arg, "--fork") == 0) { flags &= ~BUS_CONTEXT_FLAG_FORK_NEVER; flags |= BUS_CONTEXT_FLAG_FORK_ALWAYS; } else if (strcmp (arg, "--systemd-activation") == 0) { flags |= BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION; } #endif else if (strcmp (arg, "--nopidfile") == 0) { flags &= ~BUS_CONTEXT_FLAG_WRITE_PID_FILE; } else if (strcmp (arg, "--system") == 0) { check_two_config_files (&config_file, "system"); if (!_dbus_append_system_config_file (&config_file)) exit (1); } else if (strcmp (arg, "--session") == 0) { check_two_config_files (&config_file, "session"); if (!_dbus_append_session_config_file (&config_file)) exit (1); } else if (strstr (arg, "--config-file=") == arg) { const char *file; check_two_config_files (&config_file, "config-file"); file = strchr (arg, '='); ++file; if (!_dbus_string_append (&config_file, file)) exit (1); } else if (prev_arg && strcmp (prev_arg, "--config-file") == 0) { check_two_config_files (&config_file, "config-file"); if (!_dbus_string_append (&config_file, arg)) exit (1); } else if (strcmp (arg, "--config-file") == 0) { /* wait for next arg */ } else if (strstr (arg, "--address=") == arg) { const char *file; check_two_addresses (&address, "address"); file = strchr (arg, '='); ++file; if (!_dbus_string_append (&address, file)) exit (1); } else if (prev_arg && strcmp (prev_arg, "--address") == 0) { check_two_addresses (&address, "address"); if (!_dbus_string_append (&address, arg)) exit (1); } else if (strcmp (arg, "--address") == 0) { /* wait for next arg */ } else if (strstr (arg, "--print-address=") == arg) { const char *desc; check_two_addr_descriptors (&addr_fd, "print-address"); desc = strchr (arg, '='); ++desc; if (!_dbus_string_append (&addr_fd, desc)) exit (1); print_address = TRUE; } else if (prev_arg && strcmp (prev_arg, "--print-address") == 0) { check_two_addr_descriptors (&addr_fd, "print-address"); if (!_dbus_string_append (&addr_fd, arg)) exit (1); print_address = TRUE; } else if (strcmp (arg, "--print-address") == 0) { print_address = TRUE; /* and we'll get the next arg if appropriate */ } else if (strstr (arg, "--print-pid=") == arg) { const char *desc; check_two_pid_descriptors (&pid_fd, "print-pid"); desc = strchr (arg, '='); ++desc; if (!_dbus_string_append (&pid_fd, desc)) exit (1); print_pid = TRUE; } else if (prev_arg && strcmp (prev_arg, "--print-pid") == 0) { check_two_pid_descriptors (&pid_fd, "print-pid"); if (!_dbus_string_append (&pid_fd, arg)) exit (1); print_pid = TRUE; } else if (strcmp (arg, "--print-pid") == 0) { print_pid = TRUE; /* and we'll get the next arg if appropriate */ } else { usage (); } prev_arg = arg; ++i; } if (_dbus_string_get_length (&config_file) == 0) { fprintf (stderr, "No configuration file specified.\n"); usage (); } _dbus_pipe_invalidate (&print_addr_pipe); if (print_address) { _dbus_pipe_init_stdout (&print_addr_pipe); if (_dbus_string_get_length (&addr_fd) > 0) { long val; int end; if (!_dbus_string_parse_int (&addr_fd, 0, &val, &end) || end != _dbus_string_get_length (&addr_fd) || val < 0 || val > _DBUS_INT_MAX) { fprintf (stderr, "Invalid file descriptor: \"%s\"\n", _dbus_string_get_const_data (&addr_fd)); exit (1); } _dbus_pipe_init (&print_addr_pipe, val); } } _dbus_string_free (&addr_fd); _dbus_pipe_invalidate (&print_pid_pipe); if (print_pid) { _dbus_pipe_init_stdout (&print_pid_pipe); if (_dbus_string_get_length (&pid_fd) > 0) { long val; int end; if (!_dbus_string_parse_int (&pid_fd, 0, &val, &end) || end != _dbus_string_get_length (&pid_fd) || val < 0 || val > _DBUS_INT_MAX) { fprintf (stderr, "Invalid file descriptor: \"%s\"\n", _dbus_string_get_const_data (&pid_fd)); exit (1); } _dbus_pipe_init (&print_pid_pipe, val); } } _dbus_string_free (&pid_fd); if (!bus_selinux_pre_init ()) { _dbus_warn ("SELinux pre-initialization failed\n"); exit (1); } dbus_error_init (&error); context = bus_context_new (&config_file, flags, &print_addr_pipe, &print_pid_pipe, _dbus_string_get_length(&address) > 0 ? &address : NULL, &error); _dbus_string_free (&config_file); if (context == NULL) { _dbus_warn ("Failed to start message bus: %s\n", error.message); dbus_error_free (&error); exit (1); } /* bus_context_new() closes the print_addr_pipe and * print_pid_pipe */ #ifdef DBUS_UNIX setup_reload_pipe (bus_context_get_loop (context)); /* POSIX signals are Unix-specific, and _dbus_set_signal_handler is * unimplemented (and probably unimplementable) on Windows, so there's * no point in trying to make the handler portable to non-Unix. */ _dbus_set_signal_handler (SIGTERM, signal_handler); _dbus_set_signal_handler (SIGHUP, signal_handler); #endif /* DBUS_UNIX */ _dbus_verbose ("We are on D-Bus...\n"); _dbus_loop_run (bus_context_get_loop (context)); bus_context_shutdown (context); bus_context_unref (context); bus_selinux_shutdown (); return 0; }
static dbus_bool_t do_noncefile_create (DBusNonceFile *noncefile, DBusError *error, dbus_bool_t use_subdir) { dbus_bool_t ret; DBusString randomStr; _DBUS_ASSERT_ERROR_IS_CLEAR (error); _dbus_assert (noncefile); if (!_dbus_string_init (&randomStr)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto on_error; } if (!_dbus_generate_random_ascii (&randomStr, 8)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto on_error; } if (!_dbus_string_init (&noncefile->dir) || !_dbus_string_append (&noncefile->dir, _dbus_get_tmpdir())) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto on_error; } if (use_subdir) { if (!_dbus_string_append (&noncefile->dir, "/dbus_nonce-") || !_dbus_string_append (&noncefile->dir, _dbus_string_get_const_data (&randomStr)) ) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto on_error; } if (!_dbus_string_init (&noncefile->path) || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0) || !_dbus_string_append (&noncefile->dir, "/nonce")) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto on_error; } if (!_dbus_create_directory (&noncefile->dir, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); goto on_error; } _DBUS_ASSERT_ERROR_IS_CLEAR (error); } else { if (!_dbus_string_init (&noncefile->path) || !_dbus_string_copy (&noncefile->dir, 0, &noncefile->path, 0) || !_dbus_string_append (&noncefile->path, "/dbus_nonce-") || !_dbus_string_append (&noncefile->path, _dbus_string_get_const_data (&randomStr))) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto on_error; } } if (!generate_and_write_nonce (&noncefile->path, error)) { _DBUS_ASSERT_ERROR_IS_SET (error); if (use_subdir) _dbus_delete_directory (&noncefile->dir, NULL); //we ignore possible errors deleting the dir and return the write error instead goto on_error; } _DBUS_ASSERT_ERROR_IS_CLEAR (error); _dbus_string_free (&randomStr); return TRUE; on_error: if (use_subdir) _dbus_delete_directory (&noncefile->dir, NULL); _dbus_string_free (&noncefile->dir); _dbus_string_free (&noncefile->path); _dbus_string_free (&randomStr); return FALSE; }
/** * Creates a new transport for the given hostname and port. * If host is NULL, it will default to localhost * * @param host the host to connect to * @param port the port to connect to * @param family the address family to connect to * @param noncefile path to nonce file * @param error location to store reason for failure. * @returns a new transport, or #NULL on failure. */ DBusTransport* _dbus_transport_new_for_tcp_socket (const char *host, const char *port, const char *family, const char *noncefile, DBusError *error) { DBusSocket fd; DBusTransport *transport; DBusString address; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!_dbus_string_init (&address)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } if (host == NULL) host = "localhost"; if (!_dbus_string_append (&address, noncefile ? "nonce-tcp:" : "tcp:")) goto error; if (!_dbus_string_append (&address, "host=") || !_dbus_string_append (&address, host)) goto error; if (!_dbus_string_append (&address, ",port=") || !_dbus_string_append (&address, port)) goto error; if (family != NULL && (!_dbus_string_append (&address, ",family=") || !_dbus_string_append (&address, family))) goto error; if (noncefile != NULL && (!_dbus_string_append (&address, ",noncefile=") || !_dbus_string_append (&address, noncefile))) goto error; fd = _dbus_connect_tcp_socket_with_nonce (host, port, family, noncefile, error); if (!_dbus_socket_is_valid (fd)) { _DBUS_ASSERT_ERROR_IS_SET (error); _dbus_string_free (&address); return NULL; } _dbus_verbose ("Successfully connected to tcp socket %s:%s\n", host, port); transport = _dbus_transport_new_for_socket (fd, NULL, &address); _dbus_string_free (&address); if (transport == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); _dbus_close_socket (fd, NULL); _dbus_socket_invalidate (&fd); } return transport; error: _dbus_string_free (&address); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; }
/** * Checks to see if the UID sent in is the console user * * @param uid UID of person to check * @param error return location for errors * @returns #TRUE if the UID is the same as the console user and there are no errors */ dbus_bool_t _dbus_is_console_user (dbus_uid_t uid, DBusError *error) { DBusUserDatabase *db; const DBusUserInfo *info; dbus_bool_t result = FALSE; #ifdef HAVE_CONSOLE_OWNER_FILE DBusString f; DBusStat st; if (!_dbus_string_init (&f)) { _DBUS_SET_OOM (error); return FALSE; } if (!_dbus_string_append(&f, DBUS_CONSOLE_OWNER_FILE)) { _dbus_string_free(&f); _DBUS_SET_OOM (error); return FALSE; } if (_dbus_stat(&f, &st, NULL) && (st.uid == uid)) { _dbus_string_free(&f); return TRUE; } _dbus_string_free(&f); #endif /* HAVE_CONSOLE_OWNER_FILE */ _dbus_user_database_lock_system (); db = _dbus_user_database_get_system (); if (db == NULL) { dbus_set_error (error, DBUS_ERROR_FAILED, "Could not get system database."); _dbus_user_database_unlock_system (); return FALSE; } /* TPTD: this should be cache-safe, we've locked the DB and _dbus_user_at_console doesn't pass it on. */ info = _dbus_user_database_lookup (db, uid, NULL, error); if (info == NULL) { _dbus_user_database_unlock_system (); return FALSE; } result = _dbus_user_at_console (info->username, error); _dbus_user_database_unlock_system (); return result; }
static dbus_bool_t init_system_db (void) { _dbus_assert (database_locked); if (system_db == NULL) { DBusError error; const DBusUserInfo *info; system_db = _dbus_user_database_new (); if (system_db == NULL) return FALSE; dbus_error_init (&error); if (!_dbus_user_database_get_uid (system_db, _dbus_getuid (), &info, &error)) { _dbus_user_database_unref (system_db); system_db = NULL; if (dbus_error_has_name (&error, DBUS_ERROR_NO_MEMORY)) { dbus_error_free (&error); return FALSE; } else { /* This really should not happen. */ _dbus_warn ("Could not get password database information for UID of current process: %s\n", error.message); dbus_error_free (&error); return FALSE; } } if (!_dbus_string_init (&process_username)) { _dbus_user_database_unref (system_db); system_db = NULL; return FALSE; } if (!_dbus_string_init (&process_homedir)) { _dbus_string_free (&process_username); _dbus_user_database_unref (system_db); system_db = NULL; return FALSE; } if (!_dbus_string_append (&process_username, info->username) || !_dbus_string_append (&process_homedir, info->homedir) || !_dbus_register_shutdown_func (shutdown_system_db, NULL)) { _dbus_string_free (&process_username); _dbus_string_free (&process_homedir); _dbus_user_database_unref (system_db); system_db = NULL; return FALSE; } } return TRUE; }
/** * Tries to interpret the address entry in a platform-specific * way, creating a platform-specific server type if appropriate. * Sets error if the result is not OK. * * @param entry an address entry * @param server_p location to store a new DBusServer, or #NULL on failure. * @param error location to store rationale for failure on bad address * @returns the outcome * */ DBusServerListenResult _dbus_server_listen_platform_specific (DBusAddressEntry *entry, DBusServer **server_p, DBusError *error) { const char *method; *server_p = NULL; method = dbus_address_entry_get_method (entry); if (strcmp (method, "unix") == 0) { const char *path = dbus_address_entry_get_value (entry, "path"); const char *tmpdir = dbus_address_entry_get_value (entry, "tmpdir"); const char *abstract = dbus_address_entry_get_value (entry, "abstract"); if (path == NULL && tmpdir == NULL && abstract == NULL) { _dbus_set_bad_address(error, "unix", "path or tmpdir or abstract", NULL); return DBUS_SERVER_LISTEN_BAD_ADDRESS; } if ((path && tmpdir) || (path && abstract) || (tmpdir && abstract)) { _dbus_set_bad_address(error, NULL, NULL, "cannot specify two of \"path\" and \"tmpdir\" and \"abstract\" at the same time"); return DBUS_SERVER_LISTEN_BAD_ADDRESS; } if (tmpdir != NULL) { DBusString full_path; DBusString filename; if (!_dbus_string_init (&full_path)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } if (!_dbus_string_init (&filename)) { _dbus_string_free (&full_path); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } if (!_dbus_string_append (&filename, "dbus-") || !_dbus_generate_random_ascii (&filename, 10) || !_dbus_string_append (&full_path, tmpdir) || !_dbus_concat_dir_and_file (&full_path, &filename)) { _dbus_string_free (&full_path); _dbus_string_free (&filename); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } /* Always use abstract namespace if possible with tmpdir */ *server_p = _dbus_server_new_for_domain_socket (_dbus_string_get_const_data (&full_path), #ifdef HAVE_ABSTRACT_SOCKETS TRUE, #else FALSE, #endif error); _dbus_string_free (&full_path); _dbus_string_free (&filename); } else { if (path) *server_p = _dbus_server_new_for_domain_socket (path, FALSE, error); else *server_p = _dbus_server_new_for_domain_socket (abstract, TRUE, error); } if (*server_p != NULL) { _DBUS_ASSERT_ERROR_IS_CLEAR(error); return DBUS_SERVER_LISTEN_OK; } else { _DBUS_ASSERT_ERROR_IS_SET(error); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } } else if (strcmp (method, "systemd") == 0) { int i, n, *fds; DBusString address; n = _dbus_listen_systemd_sockets (&fds, error); if (n < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } if(!_dbus_string_init(&address)) goto oom; for (i = 0; i < n; i++) { if ( i > 0) { if(!_dbus_string_append (&address, ";")) goto oom; } if(!_dbus_append_address_from_socket (fds[i], &address)) goto oom; } *server_p = _dbus_server_new_for_socket (fds, n, &address, NULL); if (*server_p == NULL) goto oom; dbus_free (fds); return DBUS_SERVER_LISTEN_OK; oom: dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); for (i = 0; i < n; i++) { _dbus_close_socket (fds[i], NULL); } dbus_free (fds); _dbus_string_free (&address); dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } #ifdef DBUS_ENABLE_LAUNCHD else if (strcmp (method, "launchd") == 0) { const char *launchd_env_var = dbus_address_entry_get_value (entry, "env"); if (launchd_env_var == NULL) { _dbus_set_bad_address (error, "launchd", "env", NULL); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } *server_p = _dbus_server_new_for_launchd (launchd_env_var, error); if (*server_p != NULL) { _DBUS_ASSERT_ERROR_IS_CLEAR(error); return DBUS_SERVER_LISTEN_OK; } else { _DBUS_ASSERT_ERROR_IS_SET(error); return DBUS_SERVER_LISTEN_DID_NOT_CONNECT; } } #endif else { /* If we don't handle the method, we return NULL with the * error unset */ _DBUS_ASSERT_ERROR_IS_CLEAR(error); return DBUS_SERVER_LISTEN_NOT_HANDLED; } }
/** * Creates a new server listening on the given Unix domain socket. * * @param path the path for the domain socket. * @param abstract #TRUE to use abstract socket namespace * @param error location to store reason for failure. * @returns the new server, or #NULL on failure. */ DBusServer* _dbus_server_new_for_domain_socket (const char *path, dbus_bool_t abstract, DBusError *error) { DBusServer *server; int listen_fd; DBusString address; char *path_copy; DBusString path_str; _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (!_dbus_string_init (&address)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } _dbus_string_init_const (&path_str, path); if ((abstract && !_dbus_string_append (&address, "unix:abstract=")) || (!abstract && !_dbus_string_append (&address, "unix:path=")) || !_dbus_address_append_escaped (&address, &path_str)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed_0; } if (abstract) { path_copy = NULL; } else { path_copy = _dbus_strdup (path); if (path_copy == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed_0; } } listen_fd = _dbus_listen_unix_socket (path, abstract, error); if (listen_fd < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); goto failed_1; } server = _dbus_server_new_for_socket (&listen_fd, 1, &address, 0); if (server == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto failed_2; } if (path_copy != NULL) _dbus_server_socket_own_filename(server, path_copy); _dbus_string_free (&address); return server; failed_2: _dbus_close_socket (listen_fd, NULL); failed_1: dbus_free (path_copy); failed_0: _dbus_string_free (&address); return NULL; }
/* This code only gets executed the first time the * config files are parsed. It is not executed * when config files are reloaded. */ static dbus_bool_t process_config_first_time_only (BusContext *context, BusConfigParser *parser, const DBusString *address, BusContextFlags flags, DBusError *error) { DBusString log_prefix; DBusList *link; DBusList **addresses; const char *user, *pidfile; char **auth_mechanisms; DBusList **auth_mechanisms_list; int len; dbus_bool_t retval; _DBUS_ASSERT_ERROR_IS_CLEAR (error); retval = FALSE; auth_mechanisms = NULL; pidfile = NULL; _dbus_init_system_log (TRUE); if (flags & BUS_CONTEXT_FLAG_SYSTEMD_ACTIVATION) context->systemd_activation = TRUE; else context->systemd_activation = FALSE; /* 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. */ if (flags & BUS_CONTEXT_FLAG_WRITE_PID_FILE) pidfile = bus_config_parser_get_pidfile (parser); if (pidfile != NULL) { DBusString u; DBusStat stbuf; _dbus_string_init_const (&u, pidfile); if (_dbus_stat (&u, &stbuf, NULL)) { #ifdef DBUS_CYGWIN DBusString p; long /* int */ pid; _dbus_string_init (&p); _dbus_file_get_contents(&p, &u, NULL); _dbus_string_parse_int(&p, 0, &pid, NULL); _dbus_string_free(&p); if ((kill((int)pid, 0))) { dbus_set_error(NULL, DBUS_ERROR_FILE_EXISTS, "pid %ld not running, removing stale pid file\n", pid); _dbus_delete_file(&u, NULL); } else { #endif dbus_set_error (error, DBUS_ERROR_FAILED, "The pid file \"%s\" exists, if the message bus is not running, remove this file", pidfile); goto failed; #ifdef DBUS_CYGWIN } #endif } } /* keep around the pid filename so we can delete it later */ context->pidfile = _dbus_strdup (pidfile); /* note that type may be NULL */ context->type = _dbus_strdup (bus_config_parser_get_type (parser)); if (bus_config_parser_get_type (parser) != NULL && context->type == NULL) goto oom; user = bus_config_parser_get_user (parser); if (user != NULL) { context->user = _dbus_strdup (user); if (context->user == NULL) goto oom; } /* Set up the prefix for syslog messages */ if (!_dbus_string_init (&log_prefix)) goto oom; if (context->type && !strcmp (context->type, "system")) { if (!_dbus_string_append (&log_prefix, "[system] ")) goto oom; } else if (context->type && !strcmp (context->type, "session")) { DBusCredentials *credentials; credentials = _dbus_credentials_new_from_current_process (); if (!credentials) goto oom; if (!_dbus_string_append (&log_prefix, "[session ")) { _dbus_credentials_unref (credentials); goto oom; } if (!_dbus_credentials_to_string_append (credentials, &log_prefix)) { _dbus_credentials_unref (credentials); goto oom; } if (!_dbus_string_append (&log_prefix, "] ")) { _dbus_credentials_unref (credentials); goto oom; } _dbus_credentials_unref (credentials); } if (!_dbus_string_steal_data (&log_prefix, &context->log_prefix)) goto oom; _dbus_string_free (&log_prefix); /* Build an array of auth mechanisms */ auth_mechanisms_list = bus_config_parser_get_mechanisms (parser); len = _dbus_list_get_length (auth_mechanisms_list); if (len > 0) { int i; auth_mechanisms = dbus_new0 (char*, len + 1); if (auth_mechanisms == NULL) goto oom; i = 0; link = _dbus_list_get_first_link (auth_mechanisms_list); while (link != NULL) { auth_mechanisms[i] = _dbus_strdup (link->data); if (auth_mechanisms[i] == NULL) goto oom; link = _dbus_list_get_next_link (auth_mechanisms_list, link); i += 1; } }
static BusDesktopFile * desktop_file_for_name (BusConfigParser *parser, const char *name, DBusError *error) { BusDesktopFile *desktop_file; DBusList **service_dirs; DBusList *link; DBusError tmp_error; DBusString full_path; DBusString filename; const char *dir; _DBUS_ASSERT_ERROR_IS_CLEAR (error); desktop_file = NULL; if (!_dbus_string_init (&filename)) { BUS_SET_OOM (error); goto out_all; } if (!_dbus_string_init (&full_path)) { BUS_SET_OOM (error); goto out_filename; } if (!_dbus_string_append (&filename, name) || !_dbus_string_append (&filename, ".service")) { BUS_SET_OOM (error); goto out; } service_dirs = bus_config_parser_get_service_dirs (parser); for (link = _dbus_list_get_first_link (service_dirs); link != NULL; link = _dbus_list_get_next_link (service_dirs, link)) { dir = link->data; _dbus_verbose ("Looking at '%s'\n", dir); dbus_error_init (&tmp_error); /* clear the path from last time */ _dbus_string_set_length (&full_path, 0); /* build the full path */ if (!_dbus_string_append (&full_path, dir) || !_dbus_concat_dir_and_file (&full_path, &filename)) { BUS_SET_OOM (error); goto out; } _dbus_verbose ("Trying to load file '%s'\n", _dbus_string_get_data (&full_path)); desktop_file = bus_desktop_file_load (&full_path, &tmp_error); if (desktop_file == NULL) { _DBUS_ASSERT_ERROR_IS_SET (&tmp_error); _dbus_verbose ("Could not load %s: %s: %s\n", _dbus_string_get_const_data (&full_path), tmp_error.name, tmp_error.message); /* we may have failed if the file is not found; this is not fatal */ if (dbus_error_has_name (&tmp_error, DBUS_ERROR_NO_MEMORY)) { dbus_move_error (&tmp_error, error); /* we only bail out on OOM */ goto out; } dbus_error_free (&tmp_error); } /* did we find the desktop file we want? */ if (desktop_file != NULL) break; } /* Didn't find desktop file; set error */ if (desktop_file == NULL) { dbus_set_error (error, DBUS_ERROR_SPAWN_SERVICE_NOT_FOUND, "The name %s was not provided by any .service files", name); } out: _dbus_string_free (&full_path); out_filename: _dbus_string_free (&filename); out_all: return desktop_file; }
static dbus_bool_t bus_driver_handle_introspect (DBusConnection *connection, BusTransaction *transaction, DBusMessage *message, DBusError *error) { DBusString xml; DBusMessage *reply; const char *v_STRING; int i; _dbus_verbose ("Introspect() on bus driver\n"); _DBUS_ASSERT_ERROR_IS_CLEAR (error); reply = NULL; if (! dbus_message_get_args (message, error, DBUS_TYPE_INVALID)) { _DBUS_ASSERT_ERROR_IS_SET (error); return FALSE; } if (!_dbus_string_init (&xml)) { BUS_SET_OOM (error); return FALSE; } if (!_dbus_string_append (&xml, DBUS_INTROSPECT_1_0_XML_DOCTYPE_DECL_NODE)) goto oom; if (!_dbus_string_append (&xml, "<node>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_INTROSPECTABLE)) goto oom; if (!_dbus_string_append (&xml, " <method name=\"Introspect\">\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <arg name=\"data\" direction=\"out\" type=\"%s\"/>\n", DBUS_TYPE_STRING_AS_STRING)) goto oom; if (!_dbus_string_append (&xml, " </method>\n")) goto oom; if (!_dbus_string_append (&xml, " </interface>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <interface name=\"%s\">\n", DBUS_INTERFACE_DBUS)) goto oom; i = 0; while (i < _DBUS_N_ELEMENTS (message_handlers)) { if (!_dbus_string_append_printf (&xml, " <method name=\"%s\">\n", message_handlers[i].name)) goto oom; if (!write_args_for_direction (&xml, message_handlers[i].in_args, TRUE)) goto oom; if (!write_args_for_direction (&xml, message_handlers[i].out_args, FALSE)) goto oom; if (!_dbus_string_append (&xml, " </method>\n")) goto oom; ++i; } if (!_dbus_string_append_printf (&xml, " <signal name=\"NameOwnerChanged\">\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " </signal>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <signal name=\"NameLost\">\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " </signal>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <signal name=\"NameAcquired\">\n")) goto oom; if (!_dbus_string_append_printf (&xml, " <arg type=\"s\"/>\n")) goto oom; if (!_dbus_string_append_printf (&xml, " </signal>\n")) goto oom; if (!_dbus_string_append (&xml, " </interface>\n")) goto oom; if (!_dbus_string_append (&xml, "</node>\n")) goto oom; reply = dbus_message_new_method_return (message); if (reply == NULL) goto oom; v_STRING = _dbus_string_get_const_data (&xml); if (! dbus_message_append_args (reply, DBUS_TYPE_STRING, &v_STRING, DBUS_TYPE_INVALID)) goto oom; if (! bus_transaction_send_from_driver (transaction, connection, reply)) goto oom; dbus_message_unref (reply); _dbus_string_free (&xml); return TRUE; oom: BUS_SET_OOM (error); if (reply) dbus_message_unref (reply); _dbus_string_free (&xml); return FALSE; }
dbus_bool_t _dbus_become_daemon (const DBusString *pidfile, int print_pid_fd, DBusError *error) { const char *s; pid_t child_pid; int dev_null_fd; _dbus_verbose ("Becoming a daemon...\n"); _dbus_verbose ("chdir to /\n"); if (chdir ("/") < 0) { dbus_set_error (error, DBUS_ERROR_FAILED, "Could not chdir() to root directory"); return FALSE; } _dbus_verbose ("forking...\n"); switch ((child_pid = fork ())) { case -1: _dbus_verbose ("fork failed\n"); dbus_set_error (error, _dbus_error_from_errno (errno), "Failed to fork daemon: %s", _dbus_strerror (errno)); return FALSE; break; case 0: _dbus_verbose ("in child, closing std file descriptors\n"); /* 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); s = _dbus_getenv ("DBUS_DEBUG_OUTPUT"); if (s == NULL || *s == '\0') dup2 (dev_null_fd, 2); else _dbus_verbose ("keeping stderr open due to DBUS_DEBUG_OUTPUT\n"); } /* Get a predictable umask */ _dbus_verbose ("setting umask\n"); umask (022); break; default: if (pidfile) { _dbus_verbose ("parent writing pid file\n"); if (!_dbus_write_pid_file (pidfile, child_pid, error)) { _dbus_verbose ("pid file write failed, killing child\n"); kill (child_pid, SIGTERM); return FALSE; } } /* Write PID if requested */ if (print_pid_fd >= 0) { DBusString pid; int bytes; if (!_dbus_string_init (&pid)) { _DBUS_SET_OOM (error); kill (child_pid, SIGTERM); return FALSE; } if (!_dbus_string_append_int (&pid, child_pid) || !_dbus_string_append (&pid, "\n")) { _dbus_string_free (&pid); _DBUS_SET_OOM (error); kill (child_pid, SIGTERM); return FALSE; } bytes = _dbus_string_get_length (&pid); if (_dbus_write_socket (print_pid_fd, &pid, 0, bytes) != bytes) { dbus_set_error (error, DBUS_ERROR_FAILED, "Printing message bus PID: %s\n", _dbus_strerror (errno)); _dbus_string_free (&pid); kill (child_pid, SIGTERM); return FALSE; } _dbus_string_free (&pid); } _dbus_verbose ("parent exiting\n"); _exit (0); break; } _dbus_verbose ("calling setsid()\n"); if (setsid () == -1) _dbus_assert_not_reached ("setsid() failed"); return TRUE; }