static void debug_print (const gchar *message, ...) { if (G_UNLIKELY (_g_dbus_debug_authentication ())) { gchar *s; GString *str; va_list var_args; guint n; _g_dbus_debug_print_lock (); va_start (var_args, message); s = g_strdup_vprintf (message, var_args); va_end (var_args); str = g_string_new (NULL); for (n = 0; s[n] != '\0'; n++) { if (G_UNLIKELY (s[n] == '\r')) g_string_append (str, "\\r"); else if (G_UNLIKELY (s[n] == '\n')) g_string_append (str, "\\n"); else g_string_append_c (str, s[n]); } g_print ("GDBus-debug:Auth: %s\n", str->str); g_string_free (str, TRUE); g_free (s); _g_dbus_debug_print_unlock (); } }
/** * g_dbus_method_invocation_return_dbus_error: * @invocation: A #GDBusMethodInvocation. * @error_name: A valid D-Bus error name. * @error_message: A valid D-Bus error message. * * Finishes handling a D-Bus method call by returning an error. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_dbus_error (GDBusMethodInvocation *invocation, const gchar *error_name, const gchar *error_message) { GDBusMessage *reply; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail (error_name != NULL && g_dbus_is_name (error_name)); g_return_if_fail (error_message != NULL); if (G_UNLIKELY (_g_dbus_debug_return ())) { _g_dbus_debug_print_lock (); g_print ("========================================================================\n" "GDBus-debug:Return:\n" " >>>> METHOD ERROR %s\n" " message `%s'\n" " in response to %s.%s()\n" " on object %s\n" " to name %s\n" " reply-serial %d\n", error_name, error_message, invocation->interface_name, invocation->method_name, invocation->object_path, invocation->sender, g_dbus_message_get_serial (invocation->message)); _g_dbus_debug_print_unlock (); } reply = g_dbus_message_new_method_error_literal (invocation->message, error_name, error_message); g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (reply); g_object_unref (invocation); }
/** * g_dbus_method_invocation_return_value: * @invocation: A #GDBusMethodInvocation. * @parameters: A #GVariant tuple with out parameters for the method or %NULL if not passing any parameters. * * Finishes handling a D-Bus method call by returning @parameters. * If the @parameters GVariant is floating, it is consumed. * * It is an error if @parameters is not of the right format. * * This method will free @invocation, you cannot use it afterwards. * * Since: 2.26 */ void g_dbus_method_invocation_return_value (GDBusMethodInvocation *invocation, GVariant *parameters) { GDBusMessage *reply; GError *error; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE)); if (parameters == NULL) parameters = g_variant_new_tuple (NULL, 0); /* if we have introspection data, check that the signature of @parameters is correct */ if (invocation->method_info != NULL) { GVariantType *type; type = _g_dbus_compute_complete_signature (invocation->method_info->out_args); if (!g_variant_is_of_type (parameters, type)) { gchar *type_string = g_variant_type_dup_string (type); g_warning (_("Type of return value is incorrect, got `%s', expected `%s'"), g_variant_get_type_string (parameters), type_string); g_variant_type_free (type); g_free (type_string); goto out; } g_variant_type_free (type); } if (G_UNLIKELY (_g_dbus_debug_return ())) { _g_dbus_debug_print_lock (); g_print ("========================================================================\n" "GDBus-debug:Return:\n" " >>>> METHOD RETURN\n" " in response to %s.%s()\n" " on object %s\n" " to name %s\n" " reply-serial %d\n", invocation->interface_name, invocation->method_name, invocation->object_path, invocation->sender, g_dbus_message_get_serial (invocation->message)); _g_dbus_debug_print_unlock (); } reply = g_dbus_message_new_method_reply (invocation->message); g_dbus_message_set_body (reply, parameters); error = NULL; if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error)) { g_warning (_("Error sending message: %s"), error->message); g_error_free (error); } g_object_unref (reply); out: g_object_unref (invocation); }
static void g_dbus_method_invocation_return_value_internal (GDBusMethodInvocation *invocation, GVariant *parameters, GUnixFDList *fd_list) { GDBusMessage *reply; GError *error; g_return_if_fail (G_IS_DBUS_METHOD_INVOCATION (invocation)); g_return_if_fail ((parameters == NULL) || g_variant_is_of_type (parameters, G_VARIANT_TYPE_TUPLE)); if (parameters == NULL) parameters = g_variant_new_tuple (NULL, 0); /* if we have introspection data, check that the signature of @parameters is correct */ if (invocation->method_info != NULL) { GVariantType *type; type = _g_dbus_compute_complete_signature (invocation->method_info->out_args); if (!g_variant_is_of_type (parameters, type)) { gchar *type_string = g_variant_type_dup_string (type); g_warning ("Type of return value is incorrect: expected '%s', got '%s''", type_string, g_variant_get_type_string (parameters)); g_variant_type_free (type); g_free (type_string); goto out; } g_variant_type_free (type); } /* property_info is only non-NULL if set that way from * GDBusConnection, so this must be the case of async property * handling on either 'Get', 'Set' or 'GetAll'. */ if (invocation->property_info != NULL) { if (g_str_equal (invocation->method_name, "Get")) { GVariant *nested; if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(v)"))) { g_warning ("Type of return value for property 'Get' call should be '(v)' but got '%s'", g_variant_get_type_string (parameters)); goto out; } /* Go deeper and make sure that the value inside of the * variant matches the property type. */ g_variant_get (parameters, "(v)", &nested); if (!g_str_equal (g_variant_get_type_string (nested), invocation->property_info->signature)) { g_warning ("Value returned from property 'Get' call for '%s' should be '%s' but is '%s'", invocation->property_info->name, invocation->property_info->signature, g_variant_get_type_string (nested)); g_variant_unref (nested); goto out; } g_variant_unref (nested); } else if (g_str_equal (invocation->method_name, "GetAll")) { if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE ("(a{sv})"))) { g_warning ("Type of return value for property 'GetAll' call should be '(a{sv})' but got '%s'", g_variant_get_type_string (parameters)); goto out; } /* Could iterate the list of properties and make sure that all * of them are actually on the interface and with the correct * types, but let's not do that for now... */ } else if (g_str_equal (invocation->method_name, "Set")) { if (!g_variant_is_of_type (parameters, G_VARIANT_TYPE_UNIT)) { g_warning ("Type of return value for property 'Set' call should be '()' but got '%s'", g_variant_get_type_string (parameters)); goto out; } } else g_assert_not_reached (); } if (G_UNLIKELY (_g_dbus_debug_return ())) { _g_dbus_debug_print_lock (); g_print ("========================================================================\n" "GDBus-debug:Return:\n" " >>>> METHOD RETURN\n" " in response to %s.%s()\n" " on object %s\n" " to name %s\n" " reply-serial %d\n", invocation->interface_name, invocation->method_name, invocation->object_path, invocation->sender, g_dbus_message_get_serial (invocation->message)); _g_dbus_debug_print_unlock (); } reply = g_dbus_message_new_method_reply (invocation->message); g_dbus_message_set_body (reply, parameters); #ifdef G_OS_UNIX if (fd_list != NULL) g_dbus_message_set_unix_fd_list (reply, fd_list); #endif error = NULL; if (!g_dbus_connection_send_message (g_dbus_method_invocation_get_connection (invocation), reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error)) { g_warning ("Error sending message: %s", error->message); g_error_free (error); } g_object_unref (reply); out: g_object_unref (invocation); }
static gchar * get_session_address_dbus_launch (GError **error) { gchar *ret; gchar *machine_id; gchar *command_line; gchar *launch_stdout; gchar *launch_stderr; gint exit_status; gchar *old_dbus_verbose; gboolean restore_dbus_verbose; ret = NULL; machine_id = NULL; command_line = NULL; launch_stdout = NULL; launch_stderr = NULL; restore_dbus_verbose = FALSE; old_dbus_verbose = NULL; /* Don't run binaries as root if we're setuid. */ if (GLIB_PRIVATE_CALL (g_check_setuid) ()) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot spawn a message bus when setuid")); goto out; } machine_id = _g_dbus_get_machine_id (error); if (machine_id == NULL) { g_prefix_error (error, _("Cannot spawn a message bus without a machine-id: ")); goto out; } /* We're using private libdbus facilities here. When everything * (X11, Mac OS X, Windows) is spec'ed out correctly (not even the * X11 property is correctly documented right now) we should * consider using the spec instead of dbus-launch. * * --autolaunch=MACHINEID * This option implies that dbus-launch should scan for a previ‐ * ously-started session and reuse the values found there. If no * session is found, it will start a new session. The --exit-with- * session option is implied if --autolaunch is given. This option * is for the exclusive use of libdbus, you do not want to use it * manually. It may change in the future. */ /* TODO: maybe provide a variable for where to look for the dbus-launch binary? */ command_line = g_strdup_printf ("dbus-launch --autolaunch=%s --binary-syntax --close-stderr", machine_id); if (G_UNLIKELY (_g_dbus_debug_address ())) { _g_dbus_debug_print_lock (); g_print ("GDBus-debug:Address: Running '%s' to get bus address (possibly autolaunching)\n", command_line); old_dbus_verbose = g_strdup (g_getenv ("DBUS_VERBOSE")); restore_dbus_verbose = TRUE; g_setenv ("DBUS_VERBOSE", "1", TRUE); _g_dbus_debug_print_unlock (); } if (!g_spawn_command_line_sync (command_line, &launch_stdout, &launch_stderr, &exit_status, error)) { goto out; } if (!g_spawn_check_exit_status (exit_status, error)) { g_prefix_error (error, _("Error spawning command line '%s': "), command_line); goto out; } /* From the dbus-launch(1) man page: * * --binary-syntax Write to stdout a nul-terminated bus address, * then the bus PID as a binary integer of size sizeof(pid_t), * then the bus X window ID as a binary integer of size * sizeof(long). Integers are in the machine's byte order, not * network byte order or any other canonical byte order. */ ret = g_strdup (launch_stdout); out: if (G_UNLIKELY (_g_dbus_debug_address ())) { gchar *s; _g_dbus_debug_print_lock (); g_print ("GDBus-debug:Address: dbus-launch output:"); if (launch_stdout != NULL) { s = _g_dbus_hexdump (launch_stdout, strlen (launch_stdout) + 1 + sizeof (pid_t) + sizeof (long), 2); g_print ("\n%s", s); g_free (s); } else { g_print (" (none)\n"); } g_print ("GDBus-debug:Address: dbus-launch stderr output:"); if (launch_stderr != NULL) g_print ("\n%s", launch_stderr); else g_print (" (none)\n"); _g_dbus_debug_print_unlock (); } g_free (machine_id); g_free (command_line); g_free (launch_stdout); g_free (launch_stderr); if (G_UNLIKELY (restore_dbus_verbose)) { if (old_dbus_verbose != NULL) g_setenv ("DBUS_VERBOSE", old_dbus_verbose, TRUE); else g_unsetenv ("DBUS_VERBOSE"); } g_free (old_dbus_verbose); return ret; }
/** * g_dbus_address_get_for_bus_sync: * @bus_type: a #GBusType * @cancellable: (allow-none): a #GCancellable or %NULL * @error: return location for error or %NULL * * Synchronously looks up the D-Bus address for the well-known message * bus instance specified by @bus_type. This may involve using various * platform specific mechanisms. * * Returns: a valid D-Bus address string for @bus_type or %NULL if * @error is set * * Since: 2.26 */ gchar * g_dbus_address_get_for_bus_sync (GBusType bus_type, GCancellable *cancellable, GError **error) { gchar *ret; const gchar *starter_bus; GError *local_error; g_return_val_if_fail (error == NULL || *error == NULL, NULL); ret = NULL; local_error = NULL; if (G_UNLIKELY (_g_dbus_debug_address ())) { guint n; _g_dbus_debug_print_lock (); g_print ("GDBus-debug:Address: In g_dbus_address_get_for_bus_sync() for bus type '%s'\n", _g_dbus_enum_to_string (G_TYPE_BUS_TYPE, bus_type)); for (n = 0; n < 3; n++) { const gchar *k; const gchar *v; switch (n) { case 0: k = "DBUS_SESSION_BUS_ADDRESS"; break; case 1: k = "DBUS_SYSTEM_BUS_ADDRESS"; break; case 2: k = "DBUS_STARTER_BUS_TYPE"; break; default: g_assert_not_reached (); } v = g_getenv (k); g_print ("GDBus-debug:Address: env var %s", k); if (v != NULL) g_print ("='%s'\n", v); else g_print (" is not set\n"); } _g_dbus_debug_print_unlock (); } switch (bus_type) { case G_BUS_TYPE_SYSTEM: ret = g_strdup (g_getenv ("DBUS_SYSTEM_BUS_ADDRESS")); if (ret == NULL) { ret = g_strdup ("unix:path=/var/run/dbus/system_bus_socket"); } break; case G_BUS_TYPE_SESSION: ret = g_strdup (g_getenv ("DBUS_SESSION_BUS_ADDRESS")); if (ret == NULL) { ret = get_session_address_platform_specific (&local_error); } break; case G_BUS_TYPE_STARTER: starter_bus = g_getenv ("DBUS_STARTER_BUS_TYPE"); if (g_strcmp0 (starter_bus, "session") == 0) { ret = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SESSION, cancellable, &local_error); goto out; } else if (g_strcmp0 (starter_bus, "system") == 0) { ret = g_dbus_address_get_for_bus_sync (G_BUS_TYPE_SYSTEM, cancellable, &local_error); goto out; } else { if (starter_bus != NULL) { g_set_error (&local_error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot determine bus address from DBUS_STARTER_BUS_TYPE environment variable" " - unknown value '%s'"), starter_bus); } else { g_set_error_literal (&local_error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Cannot determine bus address because the DBUS_STARTER_BUS_TYPE environment " "variable is not set")); } } break; default: g_set_error (&local_error, G_IO_ERROR, G_IO_ERROR_FAILED, _("Unknown bus type %d"), bus_type); break; } out: if (G_UNLIKELY (_g_dbus_debug_address ())) { _g_dbus_debug_print_lock (); if (ret != NULL) { g_print ("GDBus-debug:Address: Returning address '%s' for bus type '%s'\n", ret, _g_dbus_enum_to_string (G_TYPE_BUS_TYPE, bus_type)); } else { g_print ("GDBus-debug:Address: Cannot look-up address bus type '%s': %s\n", _g_dbus_enum_to_string (G_TYPE_BUS_TYPE, bus_type), local_error ? local_error->message : ""); } _g_dbus_debug_print_unlock (); } if (local_error != NULL) g_propagate_error (error, local_error); return ret; }