--- a/patches/gdm-06-dbus.diff Fri Nov 21 07:04:34 2008 +0000
+++ b/patches/gdm-06-dbus.diff Fri Nov 21 21:16:14 2008 +0000
@@ -1,18 +1,263 @@
-Index: daemon/gdm.in
+Index: daemon/gdm.c
===================================================================
---- daemon/gdm.in (revision 6546)
-+++ daemon/gdm.in (working copy)
-@@ -30,5 +30,13 @@
- fi
- fi
+--- daemon/gdm.c (revision 6598)
++++ daemon/gdm.c (working copy)
+@@ -147,6 +147,9 @@
+ static gboolean gdm_restart_mode = FALSE;
+ static gboolean monte_carlo_sqrt2 = FALSE;
+
++/* D-Bus PID value */
++static GPid dbus_pid;
++
+ /*
+ * Lookup display number if the display number is
+ * exists then clear the remove flag and return TRUE
+@@ -294,6 +297,7 @@
+ gboolean first;
+ GSList *displays;
+ struct sigaction sig;
++ int res;
+
+ /* Remove all signal handlers, since we are freeing structures used by the handlers */
+ sig.sa_handler = SIG_DFL;
+@@ -310,6 +314,23 @@
+ sigaction (SIGXFSZ, &sig, NULL);
+ #endif
+
++ if (dbus_pid > 0) {
++ gdm_debug ("Stopping D-Bus daemon");
++
++ errno = 0;
++ res = kill (dbus_pid, SIGTERM);
++
++ if (res < 0) {
++ if (errno == ESRCH) {
++ gdm_debug ("Child process %d was already dead.",
++ (int)dbus_pid);
++ } else {
++ gdm_debug ("Couldn't kill child process %d: %s",
++ dbus_pid, g_strerror (errno));
++ }
++ }
++ }
++
+ displays = gdm_daemon_config_get_display_list ();
+
+ gdm_debug ("gdm_final_cleanup");
+@@ -1559,6 +1580,207 @@
+ g_free (file);
+ }
-+# GConf now needs D-Bus, so to launch AT programs it is necessary for D-Bus to
-+# be started with gdm. We start D-Bus as the "gdm" user. We do not do not
-+# need root privilege for this since the GUI and AT programs all run as the
-+# "gdm" user.
-+#
-+eval `/usr/bin/su - gdm -c /usr/bin/dbus-launch --sh-syntax --exit-with-session`
-+export DBUS_SESSION_BUS_ADDRESS
-+export DBUS_SESSION_BUS_PID
- exec @sbindir@/gdm-binary "$@"
++typedef struct {
++ const char *user_name;
++ const char *group_name;
++} SpawnChildData;
++
++static void
++spawn_child_setup (SpawnChildData *data)
++{
++ struct passwd *pwent;
++ struct group *grent;
++
++ if (data->user_name == NULL) {
++ return;
++ }
++
++ pwent = getpwnam (data->user_name);
++ if (pwent == NULL) {
++ g_warning (_("User %s doesn't exist"),
++ data->user_name);
++ _exit (1);
++ }
++
++ grent = getgrnam (data->group_name);
++ if (grent == NULL) {
++ g_warning (_("Group %s doesn't exist"),
++ data->group_name);
++ _exit (1);
++ }
++
++ g_debug ("GdmWelcomeSession: Changing (uid:gid) for child process to (%d:%d)",
++ pwent->pw_uid,
++ grent->gr_gid);
++
++ if (pwent->pw_uid != 0) {
++ if (setgid (grent->gr_gid) < 0) {
++ g_warning (_("Couldn't set groupid to %d"),
++ grent->gr_gid);
++ _exit (1);
++ }
++
++ if (initgroups (pwent->pw_name, pwent->pw_gid) < 0) {
++ g_warning (_("initgroups () failed for %s"),
++ pwent->pw_name);
++ _exit (1);
++ }
++
++ if (setuid (pwent->pw_uid) < 0) {
++ g_warning (_("Couldn't set userid to %d"),
++ (int)pwent->pw_uid);
++ _exit (1);
++ }
++ } else {
++ gid_t groups[1] = { 0 };
++
++ if (setgid (0) < 0) {
++ g_warning (_("Couldn't set groupid to 0"));
++ /* Don't error out, it's not fatal, if it fails we'll
++ * just still be */
++ }
++
++ /* this will get rid of any suplementary groups etc... */
++ setgroups (1, groups);
++ }
++
++ if (setsid () < 0) {
++ g_debug ("GdmWelcomeSession: could not set pid '%u' as leader of new session and process group - %s",
++ (guint) getpid (), g_strerror (errno));
++ _exit (2);
++ }
++}
++
++static gboolean
++parse_value_as_integer (const char *value,
++ int *intval)
++{
++ char *end_of_valid_int;
++ glong long_value;
++ gint int_value;
++
++ errno = 0;
++ long_value = strtol (value, &end_of_valid_int, 10);
++
++ if (*value == '\0' || *end_of_valid_int != '\0') {
++ return FALSE;
++ }
++
++ int_value = long_value;
++ if (int_value != long_value || errno == ERANGE) {
++ return FALSE;
++ }
++
++ *intval = int_value;
++
++ return TRUE;
++}
++
++static gboolean
++parse_dbus_launch_output (const char *output,
++ char **addressp,
++ GPid *pidp)
++{
++ GRegex *re;
++ GMatchInfo *match_info;
++ gboolean ret;
++ gboolean res;
++ GError *error;
++
++ ret = FALSE;
++
++ error = NULL;
++ re = g_regex_new ("DBUS_SESSION_BUS_ADDRESS=(.+)\nDBUS_SESSION_BUS_PID=([0-9]+)", 0, 0, &error);
++ if (re == NULL) {
++ g_critical ("%s", error->message);
++ }
++
++ g_regex_match (re, output, 0, &match_info);
++
++ res = g_match_info_matches (match_info);
++ if (! res) {
++ g_warning ("Unable to parse output: %s", output);
++ goto out;
++ }
++
++ if (addressp != NULL) {
++ *addressp = g_strdup (g_match_info_fetch (match_info, 1));
++ }
++
++ if (pidp != NULL) {
++ int pid;
++ gboolean result;
++ result = parse_value_as_integer (g_match_info_fetch (match_info, 2), &pid);
++ if (result) {
++ *pidp = pid;
++ } else {
++ *pidp = 0;
++ }
++ }
++
++ ret = TRUE;
++
++ out:
++ g_match_info_free (match_info);
++ g_regex_unref (re);
++
++ return ret;
++}
++
++static void
++gdm_start_dbus (void)
++{
++ gboolean res;
++ SpawnChildData data;
++ GError *error;
++ char *std_out;
++ char *std_err;
++ int exit_status;
++ char **argv;
++ char *dbus_bus_address;
++
++ if (! g_shell_parse_argv ("/usr/bin/dbus-launch --exit-with-session", NULL, &argv, &error)) {
++ gdm_debug ("Problem starting D-Bus");
++ }
++
++ data.user_name = "gdm";
++ data.group_name = "gdm";
++
++ res = g_spawn_sync (NULL,
++ argv,
++ NULL,
++ G_SPAWN_SEARCH_PATH,
++ (GSpawnChildSetupFunc)spawn_child_setup,
++ &data,
++ &std_out,
++ &std_err,
++ &exit_status,
++ &error);
++
++ if (! res) {
++ gdm_debug ("Unable to launch D-Bus daemon: %s", error->message);
++ goto out;
++ }
++
++ res = parse_dbus_launch_output (std_out,
++ &dbus_bus_address,
++ &dbus_pid);
++
++ if (! res) {
++ gdm_debug ("Unable to launch D-Bus daemon");
++ goto out;
++ }
++
++ gdm_debug ("Started D-Bus daemon on pid %d", dbus_pid);
++ gdm_debug ("Setting DBUS_SESSION_BUS_ADDRESS to %s", dbus_bus_address);
++
++ g_setenv ("DBUS_SESSION_BUS_ADDRESS", dbus_bus_address, TRUE);
++
++out:
++
++return;
++}
++
+ int
+ main (int argc, char *argv[])
+ {
+@@ -1826,6 +2048,8 @@
+ gdm_xdmcp_run ();
+ }
++ gdm_start_dbus ();
++
+ /* We always exit via exit (), and sadly we need to g_main_quit ()
+ * at times not knowing if it's this main or a recursive one we're
+ * quitting.