/* Clears the environment, except for DBUS_STARTER_x, * which we hardcode to the system bus. */ static dbus_bool_t clear_environment (DBusError *error) { #ifndef ACTIVATION_LAUNCHER_TEST /* totally clear the environment */ if (!_dbus_clearenv ()) { dbus_set_error (error, DBUS_ERROR_SPAWN_SETUP_FAILED, "could not clear environment\n"); return FALSE; } /* Ensure the bus is set to system */ dbus_setenv ("DBUS_STARTER_ADDRESS", DBUS_SYSTEM_BUS_DEFAULT_ADDRESS); dbus_setenv ("DBUS_STARTER_BUS_TYPE", "system"); #endif return TRUE; }
int main (int argc, char **argv) { #ifdef DBUS_ENABLE_EMBEDDED_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_ENABLE_EMBEDDED_TESTS */ printf ("Not compiled with test support\n"); return 0; #endif }
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 (); }
DBusServer * _dbus_server_new_for_launchd (const char *launchd_env_var, DBusError * error) { #ifdef DBUS_ENABLE_LAUNCHD DBusServer *server; DBusString address; int launchd_fd; launch_data_t sockets_dict, checkin_response; launch_data_t checkin_request; launch_data_t listening_fd_array, listening_fd; launch_data_t environment_dict, environment_param; const char *launchd_socket_path, *display; launchd_socket_path = _dbus_getenv (launchd_env_var); display = _dbus_getenv ("DISPLAY"); _DBUS_ASSERT_ERROR_IS_CLEAR (error); if (launchd_socket_path == NULL || *launchd_socket_path == '\0') { dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "launchd's environment variable %s is empty, but should contain a socket path.\n", launchd_env_var); return NULL; } if (!_dbus_string_init (&address)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); return NULL; } if (!_dbus_string_append (&address, "unix:path=")) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto l_failed_0; } if (!_dbus_string_append (&address, launchd_socket_path)) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, NULL); goto l_failed_0; } if ((checkin_request = launch_data_new_string (LAUNCH_KEY_CHECKIN)) == NULL) { dbus_set_error (error, DBUS_ERROR_NO_MEMORY, "launch_data_new_string(\"%s\") Unable to create string.\n", LAUNCH_KEY_CHECKIN); goto l_failed_0; } if ((checkin_response = launch_msg (checkin_request)) == NULL) { dbus_set_error (error, DBUS_ERROR_IO_ERROR, "launch_msg(\"%s\") IPC failure: %s\n", LAUNCH_KEY_CHECKIN, strerror (errno)); goto l_failed_0; } if (LAUNCH_DATA_ERRNO == launch_data_get_type (checkin_response)) { dbus_set_error (error, DBUS_ERROR_FAILED, "Check-in failed: %s\n", strerror (launch_data_get_errno (checkin_response))); goto l_failed_0; } sockets_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_SOCKETS); if (NULL == sockets_dict) { dbus_set_error (error, DBUS_ERROR_IO_ERROR, "No sockets found to answer requests on!\n"); goto l_failed_0; } listening_fd_array = launch_data_dict_lookup (sockets_dict, "unix_domain_listener"); if (NULL == listening_fd_array) { dbus_set_error (error, DBUS_ERROR_IO_ERROR, "No known sockets found to answer requests on!\n"); goto l_failed_0; } if (launch_data_array_get_count (listening_fd_array) != 1) { dbus_set_error (error, DBUS_ERROR_LIMITS_EXCEEDED, "Expected 1 socket from launchd, got %d.\n", launch_data_array_get_count (listening_fd_array)); goto l_failed_0; } listening_fd = launch_data_array_get_index (listening_fd_array, 0); launchd_fd = launch_data_get_fd (listening_fd); _dbus_fd_set_close_on_exec (launchd_fd); if (launchd_fd < 0) { _DBUS_ASSERT_ERROR_IS_SET (error); goto l_failed_0; if (display == NULL || *display == '\0') { environment_dict = launch_data_dict_lookup (checkin_response, LAUNCH_JOBKEY_USERENVIRONMENTVARIABLES); if (NULL == environment_dict) { _dbus_warn ("Unable to retrieve user environment from launchd."); } else { environment_param = launch_data_dict_lookup (environment_dict, "DISPLAY"); if (NULL == environment_param) { _dbus_warn ("Unable to retrieve DISPLAY from launchd."); } else { display = launch_data_get_string(environment_param); dbus_setenv ("DISPLAY", display); } } } } server = _dbus_server_new_for_socket (&launchd_fd, 1, &address, 0); if (server == NULL) { dbus_set_error (error, DBUS_ERROR_NO_SERVER, "Unable to listen on launchd fd %d.", launchd_fd); goto l_failed_0; } _dbus_string_free (&address); return server; l_failed_0: _dbus_string_free (&address); return NULL; #else /* DBUS_ENABLE_LAUNCHD */ dbus_set_error (error, DBUS_ERROR_BAD_ADDRESS, "address type 'launchd' requested, but launchd support not compiled in"); return NULL; #endif }
static int run_session (const char *dbus_daemon, const char *config_file, char *bus_address, char **argv, int prog_arg) { pid_t bus_pid; pid_t app_pid; int bus_address_pipe[2] = { 0, 0 }; if (pipe (bus_address_pipe) < 0) { fprintf (stderr, "%s: failed to create pipe: %s\n", me, strerror (errno)); return 127; } /* Make sure our output buffers aren't redundantly printed by both the * parent and the child */ fflush (stdout); fflush (stderr); bus_pid = fork (); if (bus_pid < 0) { fprintf (stderr, "%s: failed to fork: %s\n", me, strerror (errno)); return 127; } if (bus_pid == 0) { /* child */ exec_dbus_daemon (dbus_daemon, bus_address_pipe, config_file); /* not reached */ return 127; } close (bus_address_pipe[PIPE_WRITE_END]); switch (read_line (bus_address_pipe[PIPE_READ_END], bus_address, MAX_ADDR_LEN)) { case READ_STATUS_OK: break; case READ_STATUS_EOF: fprintf (stderr, "%s: EOF reading address from bus daemon\n", me); return 127; break; case READ_STATUS_ERROR: fprintf (stderr, "%s: error reading address from bus daemon: %s\n", me, strerror (errno)); return 127; break; default: _dbus_assert_not_reached ("invalid read result"); } close (bus_address_pipe[PIPE_READ_END]); if (!dbus_setenv ("DBUS_SESSION_BUS_ADDRESS", bus_address) || !dbus_setenv ("DBUS_SESSION_BUS_PID", NULL) || !dbus_setenv ("DBUS_SESSION_BUS_WINDOWID", NULL) || !dbus_setenv ("DBUS_STARTER_ADDRESS", NULL) || !dbus_setenv ("DBUS_STARTER_BUS_TYPE", NULL)) oom (); fflush (stdout); fflush (stderr); app_pid = fork (); if (app_pid < 0) { fprintf (stderr, "%s: failed to fork: %s\n", me, strerror (errno)); return 127; } if (app_pid == 0) { /* child */ exec_app (prog_arg, argv); /* not reached */ return 127; } while (1) { int child_status; pid_t child_pid = waitpid (-1, &child_status, 0); if (child_pid == (pid_t) -1) { int errsv = errno; if (errsv == EINTR) continue; /* shouldn't happen: the only other documented errors are ECHILD, * which shouldn't happen because we terminate when all our children * have died, and EINVAL, which would indicate programming error */ fprintf (stderr, "%s: waitpid() failed: %s\n", me, strerror (errsv)); return 127; } else if (child_pid == bus_pid) { /* no need to kill it, now */ bus_pid = 0; if (WIFEXITED (child_status)) fprintf (stderr, "%s: dbus-daemon exited with code %d\n", me, WEXITSTATUS (child_status)); else if (WIFSIGNALED (child_status)) fprintf (stderr, "%s: dbus-daemon terminated by signal %d\n", me, WTERMSIG (child_status)); else fprintf (stderr, "%s: dbus-daemon died or something\n", me); } else if (child_pid == app_pid) { if (bus_pid != 0) kill (bus_pid, SIGTERM); if (WIFEXITED (child_status)) return WEXITSTATUS (child_status); /* if it died from a signal, behave like sh(1) */ if (WIFSIGNALED (child_status)) return 128 + WTERMSIG (child_status); /* I give up (this should never be reached) */ fprintf (stderr, "%s: child process died or something\n", me); return 127; } else { fprintf (stderr, "%s: ignoring unknown child process %ld\n", me, (long) child_pid); } } return 0; }