static gchar * get_session_address_platform_specific (GError **error) { gchar *ret; /* Use XDG_RUNTIME_DIR/bus if it exists and is suitable. This is appropriate * for systems using the "a session is a user-session" model described in * <http://lists.freedesktop.org/archives/dbus/2015-January/016522.html>, * and implemented in dbus >= 1.9.14 and sd-bus. * * On systems following the more traditional "a session is a login-session" * model, this will fail and we'll fall through to X11 autolaunching * (dbus-launch) below. */ ret = get_session_address_xdg (); if (ret != NULL) return ret; /* TODO (#694472): try launchd on OS X, like * _dbus_lookup_session_address_launchd() does, since * 'dbus-launch --autolaunch' probably won't work there */ /* As a last resort, try the "autolaunch:" transport. On Unix this means * X11 autolaunching; on Windows this means a different autolaunching * mechanism based on shared memory. */ return get_session_address_dbus_launch (error); }
static gchar * get_session_address_platform_specific (GError **error) { gchar *ret; #if defined (G_OS_UNIX) || defined(G_OS_WIN32) /* need to handle OS X in a different way since 'dbus-launch --autolaunch' probably won't work there */ ret = get_session_address_dbus_launch (error); #else /* TODO: implement for OS X */ ret = NULL; g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot determine session bus address (not implemented for this OS)")); #endif return ret; }
/* TODO: Declare an extension point called GDBusTransport (or similar) * and move code below to extensions implementing said extension * point. That way we can implement a D-Bus transport over X11 without * making libgio link to libX11... */ static GIOStream * g_dbus_address_connect (const gchar *address_entry, const gchar *transport_name, GHashTable *key_value_pairs, GCancellable *cancellable, GError **error) { GIOStream *ret; GSocketConnectable *connectable; const gchar *nonce_file; connectable = NULL; ret = NULL; nonce_file = NULL; if (FALSE) { } #ifdef G_OS_UNIX else if (g_strcmp0 (transport_name, "unix") == 0) { const gchar *path; const gchar *abstract; path = g_hash_table_lookup (key_value_pairs, "path"); abstract = g_hash_table_lookup (key_value_pairs, "abstract"); if ((path == NULL && abstract == NULL) || (path != NULL && abstract != NULL)) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Error in address '%s' - the unix transport requires exactly one of the " "keys 'path' or 'abstract' to be set"), address_entry); } else if (path != NULL) { connectable = G_SOCKET_CONNECTABLE (g_unix_socket_address_new (path)); } else if (abstract != NULL) { connectable = G_SOCKET_CONNECTABLE (g_unix_socket_address_new_with_type (abstract, -1, G_UNIX_SOCKET_ADDRESS_ABSTRACT)); } else { g_assert_not_reached (); } } #endif else if (g_strcmp0 (transport_name, "tcp") == 0 || g_strcmp0 (transport_name, "nonce-tcp") == 0) { const gchar *s; const gchar *host; glong port; gchar *endp; gboolean is_nonce; is_nonce = (g_strcmp0 (transport_name, "nonce-tcp") == 0); host = g_hash_table_lookup (key_value_pairs, "host"); if (host == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Error in address '%s' - the host attribute is missing or malformed"), address_entry); goto out; } s = g_hash_table_lookup (key_value_pairs, "port"); if (s == NULL) s = "0"; port = strtol (s, &endp, 10); if ((*s == '\0' || *endp != '\0') || port < 0 || port >= 65536) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Error in address '%s' - the port attribute is missing or malformed"), address_entry); goto out; } if (is_nonce) { nonce_file = g_hash_table_lookup (key_value_pairs, "noncefile"); if (nonce_file == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Error in address '%s' - the noncefile attribute is missing or malformed"), address_entry); goto out; } } /* TODO: deal with family key/value-pair */ connectable = g_network_address_new (host, port); } else if (g_strcmp0 (address_entry, "autolaunch:") == 0) { gchar *autolaunch_address; autolaunch_address = get_session_address_dbus_launch (error); if (autolaunch_address != NULL) { ret = g_dbus_address_try_connect_one (autolaunch_address, NULL, cancellable, error); g_free (autolaunch_address); goto out; } else { g_prefix_error (error, _("Error auto-launching: ")); } } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Unknown or unsupported transport '%s' for address '%s'"), transport_name, address_entry); } if (connectable != NULL) { GSocketClient *client; GSocketConnection *connection; g_assert (ret == NULL); client = g_socket_client_new (); connection = g_socket_client_connect (client, connectable, cancellable, error); g_object_unref (connectable); g_object_unref (client); if (connection == NULL) goto out; ret = G_IO_STREAM (connection); if (nonce_file != NULL) { gchar nonce_contents[16 + 1]; size_t num_bytes_read; FILE *f; /* be careful to read only 16 bytes - we also check that the file is only 16 bytes long */ f = fopen (nonce_file, "rb"); if (f == NULL) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Error opening nonce file '%s': %s"), nonce_file, g_strerror (errno)); g_object_unref (ret); ret = NULL; goto out; } num_bytes_read = fread (nonce_contents, sizeof (gchar), 16 + 1, f); if (num_bytes_read != 16) { if (num_bytes_read == 0) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Error reading from nonce file '%s': %s"), nonce_file, g_strerror (errno)); } else { g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, _("Error reading from nonce file '%s', expected 16 bytes, got %d"), nonce_file, (gint) num_bytes_read); } g_object_unref (ret); ret = NULL; fclose (f); goto out; } fclose (f); if (!g_output_stream_write_all (g_io_stream_get_output_stream (ret), nonce_contents, 16, NULL, cancellable, error)) { g_prefix_error (error, _("Error writing contents of nonce file '%s' to stream:"), nonce_file); g_object_unref (ret); ret = NULL; goto out; } } } out: return ret; }