+ AtkObject *accessible = ATK_OBJECT(socket);
+ gchar *plug_name, *plug_path;
+ AtkObjectClass *klass;
+
+ /* Force registration */
+ gchar *path = spi_register_object_to_path (spi_global_register, G_OBJECT (accessible));
+ /* Let the plug know that it has been embedded */
+ plug_name = g_strdup (plug_id);
+ if (!plug_name)
+ {
+ g_free (path);
+ return;
+ }
+ plug_path = g_utf8_strchr (plug_name + 1, -1, ':');
+ if (plug_path)
+ {
+ DBusMessage *message;
+ *(plug_path++) = '\0';
+ message = dbus_message_new_method_call (plug_name, plug_path, SPI_DBUS_INTERFACE_SOCKET, "Embedded");
+ dbus_message_append_args (message, DBUS_TYPE_STRING, &path, DBUS_TYPE_INVALID);
+ dbus_connection_send (spi_global_app_data->bus, message, NULL);
+ }
+ g_free (plug_name);
+ g_free (path);
+
+ klass = ATK_OBJECT_GET_CLASS (accessible);
+ klass->ref_state_set = socket_ref_state_set;
+}
+
+static void
+install_plug_hooks ()
+{
+ gpointer data;
+
+ data = g_type_class_ref (ATK_TYPE_PLUG);
+ plug_class = ATK_PLUG_CLASS (data);
+ data = g_type_class_ref (ATK_TYPE_SOCKET);
+ socket_class = ATK_SOCKET_CLASS (data);
+ plug_class->get_object_id = get_plug_id;
+ socket_class->embed = socket_embed_hook;
+}
+
+static uint
+get_ancestral_uid (uint pid)
+{
+ FILE *fp;
+ char buf [80];
+ int ppid = 0;
+ int uid = 0;
+ gboolean got_ppid = 0;
+ gboolean got_uid = 0;
+
+ sprintf (buf, "/proc/%d/status", pid);
+ fp = fopen (buf, "r");
+ if (!fp)
+ return 0;
+ while ((!got_ppid || !got_uid) && fgets (buf, sizeof (buf), fp))
+ {
+ if (sscanf (buf, "PPid:\t%d", &ppid) == 1)
+ got_ppid = TRUE;
+ else if (sscanf (buf, "Uid:\t%d", &uid) == 1)
+ got_uid = TRUE;
+ }
+ fclose (fp);
+
+ if (!got_ppid || !got_uid)
+ return 0;
+ if (uid != 0)
+ return uid;
+ if (ppid == 0 || ppid == 1)
+ return 0;
+ return get_ancestral_uid (ppid);
+}
+
+static dbus_bool_t
+user_check (DBusConnection *bus, unsigned long uid)
+{
+ if (uid == getuid () || uid == geteuid ())
+ return TRUE;
+ if (getuid () == 0)
+ return get_ancestral_uid (getpid ()) == uid;
+ return FALSE;
+}
+
+static void
+new_connection_cb (DBusServer *server, DBusConnection *con, void *data)
+{
+ GList *new_list;
+
+ dbus_connection_set_unix_user_function (con, user_check, NULL, NULL);
+ dbus_connection_ref(con);
+ atspi_dbus_connection_setup_with_g_main(con, NULL);
+ droute_intercept_dbus (con);
+ droute_context_register (spi_global_app_data->droute, con);
+
+ new_list = g_list_append (spi_global_app_data->direct_connections, con);
+ if (new_list)
+ spi_global_app_data->direct_connections = new_list;
+}
+
+static int
+setup_bus (void)
+{
+#ifndef DISABLE_P2P
+ DBusServer *server;
+ DBusError err;
+
+ dbus_error_init(&err);
+ server = dbus_server_listen(spi_global_app_data->app_bus_addr, &err);
+ if (server == NULL)
+ {
+ g_warning (_("atk-bridge: Couldn't listen on dbus server: %s"), err.message);
+ dbus_error_init (&err);
+ spi_global_app_data->app_bus_addr [0] = '\0';
+ g_main_context_unref (spi_global_app_data->main_context);
+ spi_global_app_data->main_context = NULL;
+ return -1;
+ }
+
+ atspi_dbus_server_setup_with_g_main(server, NULL);
+ dbus_server_set_new_connection_function(server, new_connection_cb, NULL, NULL);
+
+ spi_global_app_data->server = server;
+#endif
+
+ return 0;
+}
+
+
+gchar *atspi_dbus_name = NULL;
+static gboolean atspi_no_register = FALSE;
+
+static GOptionEntry atspi_option_entries[] = {
+ {"atspi-dbus-name", 0, 0, G_OPTION_ARG_STRING, &atspi_dbus_name,
+ "D-Bus bus name to register as", NULL},
+ {"atspi-no-register", 0, 0, G_OPTION_ARG_NONE, &atspi_no_register,
+ "Do not register with Registry Daemon", NULL},