// Simple wrapper for a common D-Bus pattern. GVariant * g_dbus_simple_send(GDBusConnection *bus, GDBusMessage *msg, const gchar *type) { GDBusMessage *reply; GVariant *body; gchar *fmt; if (!(reply = g_dbus_send(bus, msg, 0, -1, 0, 0, 0))) { g_object_unref(msg); return NULL; } body = g_dbus_message_get_body(reply); fmt = g_dbus_message_print(reply, 0); g_variant_ref(body); if (g_strcmp0(g_variant_type_peek_string(g_variant_get_type(body)), type) != 0) { g_message("body type %s does not match expected type %s, message: %s", g_variant_type_peek_string(g_variant_get_type(body)), type, fmt); g_variant_unref(body); // return error body = NULL; } g_free(fmt); g_object_unref(reply); g_object_unref(msg); return body; }
// returns object path of default adapter or NULL if failed // this object path must be freed with g_free() gchar* bluez_get_default_adapter(GDBusConnection* conn) { GError* error = NULL; GDBusMessage* call_message = g_dbus_message_new_method_call("org.bluez", "/", "org.bluez.Manager", "DefaultAdapter"); if(call_message == NULL) { g_printf("g_dbus_message_new_method_call failed\n"); return NULL; } GDBusMessage* reply_message = g_dbus_connection_send_message_with_reply_sync(conn, call_message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &error); if(reply_message == NULL) { g_printf("g_dbus_connection_send_message_with_reply_sync failed\n"); return NULL; } if(g_dbus_message_get_message_type(reply_message) == G_DBUS_MESSAGE_TYPE_ERROR) { printf("Error occured\n"); g_dbus_message_to_gerror(reply_message, &error); g_printerr("Error invoking g_dbus_connection_send_message_with_reply_sync: %s\n", error->message); g_error_free(error); return NULL; } GVariant* variant = g_dbus_message_get_body(reply_message); // get first child, as this is the object path of the default interface of bluez GVariant* var_child = g_variant_get_child_value(variant, 0); const gchar* tmp_path = g_variant_get_string(var_child, NULL); // copy content of tmp_path to obj_path, as tmp_path gets freed after unref of the variant gchar* obj_path = g_strdup(tmp_path); // cleanup g_variant_unref(var_child); g_object_unref(call_message); g_object_unref(reply_message); return obj_path; }
static GDBusMessage * on_filter_func (GDBusConnection *connection, GDBusMessage *message, gboolean incoming, gpointer user_data) { GError *error = NULL; GDBusMessage *reply; if (incoming && g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL && g_str_equal (g_dbus_message_get_path (message), "/bork") && g_str_equal (g_dbus_message_get_interface (message), "borkety.Bork") && g_str_equal (g_dbus_message_get_member (message), "Echo")) { reply = g_dbus_message_new_method_reply (message); g_dbus_message_set_body (reply, g_dbus_message_get_body (message)); g_dbus_connection_send_message (connection, reply, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, &error); if (error != NULL) { g_warning ("Couldn't send DBus message: %s", error->message); g_error_free (error); } g_object_unref (reply); g_object_unref (message); return NULL; } return message; }
static char * xdp_connection_lookup_app_id_sync (GDBusConnection *connection, const char *sender, GCancellable *cancellable, GError **error) { g_autoptr(GDBusMessage) msg = NULL; g_autoptr(GDBusMessage) reply = NULL; char *app_id = NULL; GVariant *body; guint32 pid; G_LOCK (app_ids); if (app_ids) app_id = g_strdup (g_hash_table_lookup (app_ids, sender)); G_UNLOCK (app_ids); if (app_id != NULL) return app_id; msg = g_dbus_message_new_method_call ("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "GetConnectionUnixProcessID"); g_dbus_message_set_body (msg, g_variant_new ("(s)", sender)); reply = g_dbus_connection_send_message_with_reply_sync (connection, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 30000, NULL, cancellable, error); if (reply == NULL) return NULL; if (g_dbus_message_get_message_type (reply) == G_DBUS_MESSAGE_TYPE_ERROR) { g_set_error (error, G_IO_ERROR, G_IO_ERROR_FAILED, "Can't find peer app id"); return NULL; } body = g_dbus_message_get_body (reply); g_variant_get (body, "(u)", &pid); app_id = get_app_id_from_pid (pid, error); if (app_id) { G_LOCK (app_ids); ensure_app_ids (); g_hash_table_insert (app_ids, g_strdup (sender), g_strdup (app_id)); G_UNLOCK (app_ids); } return app_id; }
GVariant* bluez_characteristic_get_value(GDBusConnection* conn, const gchar* char_path) { GError* error = NULL; GDBusMessage* call_message = g_dbus_message_new_method_call("org.bluez", char_path, "org.bluez.Characteristic", "GetProperties"); if(call_message == NULL) { g_printf("g_dbus_message_new_method_call failed\n"); return NULL; } GDBusMessage* reply_message = g_dbus_connection_send_message_with_reply_sync(conn, call_message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &error); if(reply_message == NULL) { g_printf("g_dbus_connection_send_message_with_reply_sync failed\n"); return NULL; } if(g_dbus_message_get_message_type(reply_message) == G_DBUS_MESSAGE_TYPE_ERROR) { g_printf("Error occured\n"); g_dbus_message_to_gerror(reply_message, &error); g_printerr("Error invoking g_dbus_connection_send_message_with_reply_sync: %s\n", error->message); g_error_free(error); return NULL; } GVariant* var_body = g_dbus_message_get_body(reply_message); g_variant_ref(var_body); // cleanup g_object_unref(call_message); g_object_unref(reply_message); return var_body; }
// returns the object path to a given device or NULL if failed // object path has to be freed with g_free() gchar* bluez_find_device(GDBusConnection* conn, const gchar* adapter_path, const char* bt_addr) { GError* error = NULL; GDBusMessage* call_message = g_dbus_message_new_method_call("org.bluez", adapter_path, "org.bluez.Adapter", "FindDevice"); if(call_message == NULL) { return NULL; } GVariant* variant_addr = g_variant_new_string(bt_addr); GVariant* variant_body = g_variant_new_tuple(&variant_addr, 1); g_dbus_message_set_body(call_message, variant_body); GDBusMessage* reply_message = g_dbus_connection_send_message_with_reply_sync(conn, call_message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &error); if(reply_message == NULL) { return NULL; } if(g_dbus_message_get_message_type(reply_message) == G_DBUS_MESSAGE_TYPE_ERROR) { return NULL; } GVariant* variant = g_dbus_message_get_body(reply_message); // get first child, as this is the object path of the default interface of bluez GVariant* var_child = g_variant_get_child_value(variant, 0); const gchar* tmp_path = g_variant_get_string(var_child, NULL); // copy content of tmp_path to obj_path, as tmp_path gets freed after unref of the variant gchar* obj_path = g_strdup(tmp_path); // cleanup g_variant_unref(var_child); g_object_unref(call_message); g_object_unref(reply_message); return obj_path; }
static void open_file_msg_cb (GObject *source_object, GAsyncResult *res, gpointer user_data) { FilechooserPortalData *data = user_data; GtkFileChooserNative *self = data->self; GDBusMessage *reply; GError *error = NULL; reply = g_dbus_connection_send_message_with_reply_finish (data->connection, res, &error); if (reply && g_dbus_message_to_gerror (reply, &error)) g_clear_object (&reply); if (reply == NULL) { if (!data->hidden) _gtk_native_dialog_emit_response (GTK_NATIVE_DIALOG (self), GTK_RESPONSE_DELETE_EVENT); g_warning ("Can't open portal file chooser: %s", error->message); g_error_free (error); filechooser_portal_data_free (data); self->mode_data = NULL; return; } g_variant_get_child (g_dbus_message_get_body (reply), 0, "o", &data->portal_handle); if (data->hidden) { /* The dialog was hidden before we got the handle, close it now */ send_close (data); filechooser_portal_data_free (data); self->mode_data = NULL; } else { data->portal_response_signal_id = g_dbus_connection_signal_subscribe (data->connection, "org.freedesktop.portal.Desktop", "org.freedesktop.portal.Request", "Response", data->portal_handle, NULL, G_DBUS_SIGNAL_FLAGS_NO_MATCH_RULE, response_cb, self, NULL); } g_object_unref (reply); }
static int is_dbus_based_screensaver_active(const char *d_service, const char *d_path, const char *d_interface) { GDBusMessage *msg = NULL; GDBusMessage *reply = NULL; uint32_t ret = 0; assert(connection); // detect is screen saver already active msg = g_dbus_message_new_method_call(d_service, d_path, d_interface, "GetActive"); if (!msg) { trace_error("%s, can't allocate GDBusMessage\n", __func__); goto err; } GError *error = NULL; reply = g_dbus_connection_send_message_with_reply_sync(connection, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &error); if (error) { trace_error("%s, can't send message, %s\n", __func__, error->message); g_clear_error(&error); goto err; } g_dbus_connection_flush_sync(connection, NULL, &error); if (error != NULL) { trace_error("%s, can't flush dbus connection, %s\n", __func__, error->message); g_clear_error(&error); goto err; } GVariant *v = g_dbus_message_get_body(reply); v = g_variant_get_child_value(v, 0); if (g_variant_is_of_type(v, G_VARIANT_TYPE_BOOLEAN)) ret = g_variant_get_boolean(v); else ret = 0; err: if (reply) g_object_unref(reply); if (msg) g_object_unref(msg); return ret; }
static gboolean cloud_spy_dispatcher_connection_send_message (GDBusConnection * connection, GDBusMessage * message, GDBusSendMessageFlags flags, volatile guint32 * out_serial, GError ** error) { CloudSpyDispatcherInvocation * self = (CloudSpyDispatcherInvocation *) connection; GVariant * result; (void) flags; (void) out_serial; (void) error; result = g_variant_ref (g_dbus_message_get_body (message)); g_simple_async_result_set_op_res_gpointer (self->res, result, g_variant_unref); g_simple_async_result_complete (self->res); return TRUE; }
static gint64 arv_rtkit_get_int_property (GDBusConnection *connection, const char* propname, GError **error) { GDBusMessage *message; GDBusMessage *reply; GError *local_error = NULL; GVariant *body; GVariant *parameter; GVariant *variant; const GVariantType *variant_type; gint64 value; message = g_dbus_message_new_method_call (RTKIT_SERVICE_NAME, RTKIT_OBJECT_PATH, "org.freedesktop.DBus.Properties", "Get"); g_dbus_message_set_body (message, g_variant_new ("(ss)", "org.freedesktop.RealtimeKit1", propname)); reply = g_dbus_connection_send_message_with_reply_sync (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 1000, NULL, NULL, &local_error); g_object_unref (message); if (local_error != NULL) { g_propagate_error (error, local_error); return 0; } if (g_dbus_message_get_message_type (reply) != G_DBUS_MESSAGE_TYPE_METHOD_RETURN) { local_error = g_error_new (ARV_RTKIT_ERROR, ARV_RTKIT_ERROR_PERMISSION_DENIED, "%s", g_dbus_message_get_error_name (reply)); g_propagate_error (error, local_error); g_object_unref (reply); return 0; } if (!g_variant_type_equal ("v", g_dbus_message_get_signature (reply))) { local_error = g_error_new (ARV_RTKIT_ERROR, ARV_RTKIT_ERROR_WRONG_REPLY, "Invalid reply signature"); g_propagate_error (error, local_error); g_object_unref (reply); return 0; } body = g_dbus_message_get_body (reply); parameter = g_variant_get_child_value (body, 0); variant = g_variant_get_variant (parameter); variant_type = g_variant_get_type (variant); if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT32)) value = g_variant_get_int32 (variant); else if (g_variant_type_equal (variant_type, G_VARIANT_TYPE_INT64)) value = g_variant_get_int64 (variant); else value = 0; g_variant_unref (parameter); g_variant_unref (variant); g_object_unref (reply); return value; }
gboolean eas_gdbus_call_finish (struct eas_gdbus_client *client, GAsyncResult *result, guint cancel_serial, const gchar *out_params, va_list *ap, GError **error) { GDBusMessage *reply; gchar *out_params_type = (gchar *) out_params; gboolean success = FALSE; GVariant *v; reply = g_dbus_connection_send_message_with_reply_finish(client->connection, result, error); if (cancel_serial) { GDBusMessage *message; message = g_dbus_message_new_method_call (EAS_SERVICE_NAME, EAS_SERVICE_COMMON_OBJECT_PATH, EAS_SERVICE_COMMON_INTERFACE, "cancel_request"); g_dbus_message_set_body (message, g_variant_new ("(su)", client->account_uid, cancel_serial)); g_dbus_connection_send_message (client->connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, NULL, NULL); g_object_unref (message); } if (!reply) return FALSE; /* g_variant_is_of_type() will fail to match a DBus return of (sas) with a format string of (s^as), where the ^ is required to make it convert to a strv instead of something more complicated. So we remove all ^ characters from the string that we show to g_variant_is_of_type(). Ick. */ if (out_params && strchr (out_params, '^')) { gchar *x, *y; out_params_type = g_strdup (out_params); x = y = strchr (out_params_type, '^'); y++; while (*y) { if (*y == '^') y++; else *(x++) = *(y++); } *x = 0; } switch (g_dbus_message_get_message_type (reply)) { case G_DBUS_MESSAGE_TYPE_METHOD_RETURN: /* An empty (successful) response will give a NULL GVariant here */ v = g_dbus_message_get_body (reply); if (!out_params) { if (v) goto inval; else { success = TRUE; break; } } if (!g_variant_is_of_type (v, G_VARIANT_TYPE (out_params_type))) { inval: g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, "ActiveSync DBus call returned invalid response type %s", v?g_variant_get_type_string (v):"()"); goto out; g_object_unref (reply); } g_variant_get_va (v, out_params, NULL, ap); success = TRUE; break; case G_DBUS_MESSAGE_TYPE_ERROR: g_dbus_message_to_gerror (reply, error); break; default: g_set_error (error, G_IO_ERROR, G_IO_ERROR_INVALID_ARGUMENT, "EAS DBus call returned weird message type %d", g_dbus_message_get_message_type (reply)); break; } out: if (out_params_type != out_params) g_free (out_params_type); g_object_unref (reply); return success; }
static GDBusMessage * notification_filter_func (GDBusConnection *connection, GDBusMessage *message, gboolean *incoming, gpointer user_data) { GDBusMessage *ret = NULL; gboolean transient = FALSE; gchar *sender_str = NULL; CsNotificationWatcher *watcher = CS_NOTIFICATION_WATCHER (user_data); if (incoming && g_dbus_message_get_message_type (message) == G_DBUS_MESSAGE_TYPE_METHOD_CALL && g_strcmp0 (g_dbus_message_get_interface (message), NOTIFICATIONS_INTERFACE) == 0 && g_strcmp0 (g_dbus_message_get_member (message), NOTIFY_METHOD) == 0) { GVariant *body = g_dbus_message_get_body (message); if (body != NULL && g_variant_is_of_type (body, G_VARIANT_TYPE_TUPLE) && g_variant_n_children (body) >= 7) { GVariant *hints, *sender; if (debug_mode) { GVariant *dbg_var = NULL; const gchar *dbg_str; g_printerr ("Notification received...\n"); dbg_var = g_variant_get_child_value (body, 0); if (dbg_var != NULL && g_variant_is_of_type (dbg_var, G_VARIANT_TYPE_STRING)) { dbg_str = g_variant_get_string (dbg_var, NULL); if (dbg_str != NULL) { g_printerr ("Sender: %s\n", dbg_str); } } g_clear_pointer (&dbg_var, g_variant_unref); dbg_var = g_variant_get_child_value (body, 3); if (dbg_var != NULL && g_variant_is_of_type (dbg_var, G_VARIANT_TYPE_STRING)) { dbg_str = g_variant_get_string (dbg_var, NULL); if (dbg_str != NULL) { g_printerr ("Summary: %s\n", dbg_str); } } g_clear_pointer (&dbg_var, g_variant_unref); dbg_var = g_variant_get_child_value (body, 4); if (dbg_var != NULL && g_variant_is_of_type (dbg_var, G_VARIANT_TYPE_STRING)) { dbg_str = g_variant_get_string (dbg_var, NULL); if (dbg_str != NULL) { g_printerr ("Body: %s\n", dbg_str); } } g_clear_pointer (&dbg_var, g_variant_unref); } hints = g_variant_get_child_value (body, 6); if (hints != NULL && g_variant_is_of_type (hints, G_VARIANT_TYPE_DICTIONARY)) { GVariant *transient_hint; transient_hint = g_variant_lookup_value (hints, "transient", NULL); if (transient_hint) { transient = g_variant_get_boolean (transient_hint); } g_clear_pointer (&transient_hint, g_variant_unref); } g_clear_pointer (&hints, g_variant_unref); sender = g_variant_get_child_value (body, 0); if (sender) { sender_str = g_variant_dup_string (sender, NULL); } g_clear_pointer (&sender, g_variant_unref); } } else { ret = message; } if (ret == NULL && !transient) { NotificationIdleData *data = g_slice_new0 (NotificationIdleData); data->watcher = watcher; data->sender = sender_str; g_idle_add (idle_notify_received, data); } return ret; }
gboolean e_mapi_util_trigger_krb_auth (const EMapiProfileData *empd, GError **error) { gint success = FALSE; GError *local_error = NULL; GDBusConnection *connection; GDBusMessage *message, *reply; gchar *name; connection = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, &local_error); if (local_error) { g_warning ("could not get system bus: %s\n", local_error->message); g_propagate_error (error, local_error); return FALSE; } g_dbus_connection_set_exit_on_close (connection, FALSE); /* Create a new message on the KRB_DBUS_INTERFACE */ message = g_dbus_message_new_method_call (KRB_DBUS_INTERFACE, KRB_DBUS_PATH, KRB_DBUS_INTERFACE, "acquireTgt"); if (!message) { g_object_unref (connection); return FALSE; } /* Appends the data as an argument to the message */ name = g_strdup_printf ("%s@%s", empd->username, empd->krb_realm); g_dbus_message_set_body (message, g_variant_new ("(s)", name)); /* Sends the message: Have a 300 sec wait timeout */ reply = g_dbus_connection_send_message_with_reply_sync (connection, message, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 300 * 1000, NULL, NULL, &local_error); g_free (name); if (!local_error && reply) { if (g_dbus_message_to_gerror (reply, &local_error)) { g_object_unref (reply); reply = NULL; } } if (local_error) { g_dbus_error_strip_remote_error (local_error); g_propagate_error (error, local_error); } if (reply) { GVariant *body = g_dbus_message_get_body (reply); if (body) { g_variant_get (body, "(b)", &success); } g_object_unref (reply); } /* Free the message */ g_object_unref (message); g_object_unref (connection); return success && !local_error; }
static gboolean do_command (GDBusConnection *connection) { GDBusMessage *reply; if (do_quit) { reply = screensaver_send_message_void (connection, "Quit", FALSE); goto done; } if (do_query) { GVariant *body; gboolean v; if (! screensaver_is_running (connection)) { g_message ("Screensaver is not running!"); goto done; } reply = screensaver_send_message_void (connection, "GetActive", TRUE); if (reply == NULL) { g_message ("Did not receive a reply from the screensaver."); goto done; } body = g_dbus_message_get_body (reply); g_variant_get (body, "(b)", &v); g_object_unref (reply); if (v) { g_print (_("The screensaver is active\n")); } else { g_print (_("The screensaver is inactive\n")); } } if (do_time) { GVariant *body; gboolean v; gint32 t; reply = screensaver_send_message_void (connection, "GetActive", TRUE); if (reply == NULL) { g_message ("Did not receive a reply from the screensaver."); goto done; } body = g_dbus_message_get_body (reply); g_variant_get (body, "(b)", &v); g_object_unref (reply); if (v) { reply = screensaver_send_message_void (connection, "GetActiveTime", TRUE); if (reply == NULL) { g_message ("Did not receive a reply from the screensaver."); goto done; } body = g_dbus_message_get_body (reply); g_variant_get (body, "(u)", &t); g_object_unref (reply); g_print (ngettext ("The screensaver has been active for %d second.\n", "The screensaver has been active for %d seconds.\n", t), t); } else { g_print (_("The screensaver is not currently active.\n")); } } if (do_lock) { if (g_strcmp0 (away_message, "DEFAULT") == 0) { reply = screensaver_send_message_string (connection, "Lock", away_message); } else { gchar * custom_message = g_strdup_printf("CUSTOM###%s", away_message); reply = screensaver_send_message_string (connection, "Lock", custom_message); g_free (custom_message); } if (reply == NULL) { g_message ("Did not receive a reply from the screensaver."); goto done; } g_object_unref (reply); } if (do_activate) { reply = screensaver_send_message_bool (connection, "SetActive", TRUE); if (reply == NULL) { g_message ("Did not receive a reply from the screensaver."); goto done; } g_object_unref (reply); } if (do_deactivate) { reply = screensaver_send_message_bool (connection, "SetActive", FALSE); if (reply == NULL) { g_message ("Did not receive a reply from the screensaver."); goto done; } g_object_unref (reply); } done: g_main_loop_quit (loop); return FALSE; }
/** * fu_util_get_details: **/ static gboolean fu_util_get_details (FuUtilPrivate *priv, gchar **values, GError **error) { GVariant *body; GVariant *val; gint fd; gint retval; _cleanup_object_unref_ GDBusMessage *message = NULL; _cleanup_object_unref_ GDBusMessage *request = NULL; _cleanup_object_unref_ GUnixFDList *fd_list = NULL; /* check args */ if (g_strv_length (values) != 1) { g_set_error_literal (error, FWUPD_ERROR, FWUPD_ERROR_INTERNAL, "Invalid arguments: expected 'filename'"); return FALSE; } /* open file */ fd = open (values[0], O_RDONLY); if (fd < 0) { g_set_error (error, FWUPD_ERROR, FWUPD_ERROR_INVALID_FILE, "failed to open %s", values[0]); return FALSE; } /* set out of band file descriptor */ fd_list = g_unix_fd_list_new (); retval = g_unix_fd_list_append (fd_list, fd, NULL); g_assert (retval != -1); request = g_dbus_message_new_method_call (FWUPD_DBUS_SERVICE, FWUPD_DBUS_PATH, FWUPD_DBUS_INTERFACE, "GetDetails"); g_dbus_message_set_unix_fd_list (request, fd_list); /* g_unix_fd_list_append did a dup() already */ close (fd); /* send message */ body = g_variant_new ("(h)", fd > -1 ? 0 : -1); g_dbus_message_set_body (request, body); message = g_dbus_connection_send_message_with_reply_sync (priv->conn, request, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, error); if (message == NULL) { g_dbus_error_strip_remote_error (*error); return FALSE; } if (g_dbus_message_to_gerror (message, error)) { g_dbus_error_strip_remote_error (*error); return FALSE; } /* print results */ val = g_dbus_message_get_body (message); fu_util_print_metadata (val); return TRUE; }
static uint32_t detect_dbus_based_screensavers(void) { GDBusMessage *msg, *reply; uint32_t ret; assert(connection); // enumerate all services msg = g_dbus_message_new_method_call("org.freedesktop.DBus", "/org/freedesktop/DBus", "org.freedesktop.DBus", "ListNames"); if (!msg) { trace_error("%s, can't allocate GDBusMessage\n", __func__); ret = 0; goto err_1; } GError *error = NULL; reply = g_dbus_connection_send_message_with_reply_sync(connection, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, -1, NULL, NULL, &error); if (error != NULL) { trace_error("%s, can't send message, %s\n", __func__, error->message); g_clear_error(&error); ret = 0; goto err_2; } g_dbus_connection_flush_sync(connection, NULL, &error); if (error != NULL) { trace_error("%s, can't flush dbus connection, %s\n", __func__, error->message); g_clear_error(&error); ret = 0; goto err_3; } // iterate over the list GVariant *v = g_dbus_message_get_body(reply); GVariantIter *iter; gchar *str; uint32_t flags = 0; g_variant_get(v, "(as)", &iter); while (g_variant_iter_loop(iter, "s", &str)) { if (strcmp(str, GS_SERVICE) == 0) flags |= SST_GNOME_SCREENSAVER; if (strcmp(str, KS_SERVICE) == 0) flags |= SST_KDE_SCREENSAVER; if (strcmp(str, FDOS_SERVICE) == 0) flags |= SST_FDO_SCREENSAVER; if (strcmp(str, CINNAMON_SERVICE) == 0) flags |= SST_CINNAMON_SCREENSAVER; } g_variant_iter_free(iter); ret = flags; err_3: g_object_unref(reply); err_2: g_object_unref(msg); err_1: return ret; }
gboolean xdg_app_builtin_run (int argc, char **argv, GCancellable *cancellable, GError **error) { g_autoptr(GOptionContext) context = NULL; g_autoptr(XdgAppDeploy) app_deploy = NULL; g_autoptr(XdgAppDeploy) runtime_deploy = NULL; g_autoptr(GFile) app_files = NULL; g_autoptr(GFile) runtime_files = NULL; g_autoptr(GFile) app_id_dir = NULL; g_autoptr(GFile) app_cache_dir = NULL; g_autoptr(GFile) app_data_dir = NULL; g_autoptr(GFile) app_config_dir = NULL; g_autoptr(GFile) home = NULL; g_autoptr(GFile) user_font1 = NULL; g_autoptr(GFile) user_font2 = NULL; g_autoptr(XdgAppSessionHelper) session_helper = NULL; g_autofree char *runtime = NULL; g_autofree char *default_command = NULL; g_autofree char *runtime_ref = NULL; g_autofree char *app_ref = NULL; g_autofree char *doc_mount_path = NULL; g_autoptr(GKeyFile) metakey = NULL; g_autoptr(GKeyFile) runtime_metakey = NULL; g_autoptr(GPtrArray) argv_array = NULL; g_auto(GStrv) envp = NULL; g_autoptr(GPtrArray) dbus_proxy_argv = NULL; g_autofree char *monitor_path = NULL; const char *app; const char *branch = "master"; const char *command = "/bin/sh"; int i; int rest_argv_start, rest_argc; int sync_proxy_pipes[2]; g_autoptr(XdgAppContext) arg_context = NULL; g_autoptr(XdgAppContext) app_context = NULL; g_autoptr(XdgAppContext) overrides = NULL; g_autoptr(GDBusConnection) session_bus = NULL; context = g_option_context_new ("APP [args...] - Run an app"); rest_argc = 0; for (i = 1; i < argc; i++) { /* The non-option is the command, take it out of the arguments */ if (argv[i][0] != '-') { rest_argv_start = i; rest_argc = argc - i; argc = i; break; } } arg_context = xdg_app_context_new (); g_option_context_add_group (context, xdg_app_context_get_options (arg_context)); if (!xdg_app_option_context_parse (context, options, &argc, &argv, XDG_APP_BUILTIN_FLAG_NO_DIR, NULL, cancellable, error)) return FALSE; if (rest_argc == 0) return usage_error (context, "APP must be specified", error); app = argv[rest_argv_start]; if (opt_branch) branch = opt_branch; if (!xdg_app_is_valid_name (app)) return xdg_app_fail (error, "'%s' is not a valid application name", app); if (!xdg_app_is_valid_branch (branch)) return xdg_app_fail (error, "'%s' is not a valid branch name", branch); app_ref = xdg_app_build_app_ref (app, branch, opt_arch); app_deploy = xdg_app_find_deploy_for_ref (app_ref, cancellable, error); if (app_deploy == NULL) return FALSE; metakey = xdg_app_deploy_get_metadata (app_deploy); argv_array = g_ptr_array_new_with_free_func (g_free); dbus_proxy_argv = g_ptr_array_new_with_free_func (g_free); g_ptr_array_add (argv_array, g_strdup (HELPER)); g_ptr_array_add (argv_array, g_strdup ("-l")); if (!xdg_app_run_add_extension_args (argv_array, metakey, app_ref, cancellable, error)) return FALSE; if (opt_runtime) runtime = opt_runtime; else { runtime = g_key_file_get_string (metakey, "Application", opt_devel ? "sdk" : "runtime", error); if (*error) return FALSE; } runtime_ref = g_build_filename ("runtime", runtime, NULL); runtime_deploy = xdg_app_find_deploy_for_ref (runtime_ref, cancellable, error); if (runtime_deploy == NULL) return FALSE; runtime_metakey = xdg_app_deploy_get_metadata (runtime_deploy); app_context = xdg_app_context_new (); if (!xdg_app_context_load_metadata (app_context, runtime_metakey, error)) return FALSE; if (!xdg_app_context_load_metadata (app_context, metakey, error)) return FALSE; overrides = xdg_app_deploy_get_overrides (app_deploy); xdg_app_context_merge (app_context, overrides); xdg_app_context_merge (app_context, arg_context); if (!xdg_app_run_add_extension_args (argv_array, runtime_metakey, runtime_ref, cancellable, error)) return FALSE; if ((app_id_dir = xdg_app_ensure_data_dir (app, cancellable, error)) == NULL) return FALSE; app_cache_dir = g_file_get_child (app_id_dir, "cache"); g_ptr_array_add (argv_array, g_strdup ("-B")); g_ptr_array_add (argv_array, g_strdup_printf ("/var/cache=%s", gs_file_get_path_cached (app_cache_dir))); app_data_dir = g_file_get_child (app_id_dir, "data"); g_ptr_array_add (argv_array, g_strdup ("-B")); g_ptr_array_add (argv_array, g_strdup_printf ("/var/data=%s", gs_file_get_path_cached (app_data_dir))); app_config_dir = g_file_get_child (app_id_dir, "config"); g_ptr_array_add (argv_array, g_strdup ("-B")); g_ptr_array_add (argv_array, g_strdup_printf ("/var/config=%s", gs_file_get_path_cached (app_config_dir))); app_files = xdg_app_deploy_get_files (app_deploy); runtime_files = xdg_app_deploy_get_files (runtime_deploy); default_command = g_key_file_get_string (metakey, "Application", "command", error); if (*error) return FALSE; if (opt_command) command = opt_command; else command = default_command; session_helper = xdg_app_session_helper_proxy_new_for_bus_sync (G_BUS_TYPE_SESSION, G_DBUS_PROXY_FLAGS_DO_NOT_LOAD_PROPERTIES | G_DBUS_PROXY_FLAGS_DO_NOT_CONNECT_SIGNALS, "org.freedesktop.XdgApp", "/org/freedesktop/XdgApp/SessionHelper", NULL, NULL); if (session_helper && xdg_app_session_helper_call_request_monitor_sync (session_helper, &monitor_path, NULL, NULL)) { g_ptr_array_add (argv_array, g_strdup ("-m")); g_ptr_array_add (argv_array, monitor_path); } else g_ptr_array_add (argv_array, g_strdup ("-r")); session_bus = g_bus_get_sync (G_BUS_TYPE_SESSION, NULL, NULL); if (session_bus) { g_autoptr (GError) local_error = NULL; g_autoptr (GDBusMessage) reply = NULL; g_autoptr (GDBusMessage) msg = g_dbus_message_new_method_call ("org.freedesktop.portal.Documents", "/org/freedesktop/portal/documents", "org.freedesktop.portal.Documents", "GetMountPoint"); g_dbus_message_set_body (msg, g_variant_new ("()")); reply = g_dbus_connection_send_message_with_reply_sync (session_bus, msg, G_DBUS_SEND_MESSAGE_FLAGS_NONE, 30000, NULL, NULL, NULL); if (reply) { if (g_dbus_message_to_gerror (reply, &local_error)) { g_warning ("Can't get document portal: %s\n", local_error->message); } else g_variant_get (g_dbus_message_get_body (reply), "(^ay)", &doc_mount_path); } } xdg_app_run_add_environment_args (argv_array, dbus_proxy_argv, doc_mount_path, app, app_context, app_id_dir); g_ptr_array_add (argv_array, g_strdup ("-b")); g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/fonts=%s", SYSTEM_FONTS_DIR)); if (opt_devel) g_ptr_array_add (argv_array, g_strdup ("-c")); home = g_file_new_for_path (g_get_home_dir ()); user_font1 = g_file_resolve_relative_path (home, ".local/share/fonts"); user_font2 = g_file_resolve_relative_path (home, ".fonts"); if (g_file_query_exists (user_font1, NULL)) { g_autofree char *path = g_file_get_path (user_font1); g_ptr_array_add (argv_array, g_strdup ("-b")); g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/user-fonts=%s", path)); } else if (g_file_query_exists (user_font2, NULL)) { g_autofree char *path = g_file_get_path (user_font2); g_ptr_array_add (argv_array, g_strdup ("-b")); g_ptr_array_add (argv_array, g_strdup_printf ("/run/host/user-fonts=%s", path)); } /* Must run this before spawning the dbus proxy, to ensure it ends up in the app cgroup */ xdg_app_run_in_transient_unit (app); if (dbus_proxy_argv->len > 0) { char x; if (pipe (sync_proxy_pipes) < 0) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to create sync pipe"); return FALSE; } g_ptr_array_insert (dbus_proxy_argv, 0, g_strdup (DBUSPROXY)); g_ptr_array_insert (dbus_proxy_argv, 1, g_strdup_printf ("--fd=%d", sync_proxy_pipes[1])); g_ptr_array_add (dbus_proxy_argv, NULL); /* NULL terminate */ if (!g_spawn_async (NULL, (char **)dbus_proxy_argv->pdata, NULL, G_SPAWN_SEARCH_PATH, dbus_spawn_child_setup, GINT_TO_POINTER (sync_proxy_pipes[1]), NULL, error)) return FALSE; close (sync_proxy_pipes[1]); /* Sync with proxy, i.e. wait until its listening on the sockets */ if (read (sync_proxy_pipes[0], &x, 1) != 1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Failed to sync with dbus proxy"); return FALSE; } g_ptr_array_add (argv_array, g_strdup ("-S")); g_ptr_array_add (argv_array, g_strdup_printf ("%d", sync_proxy_pipes[0])); } g_ptr_array_add (argv_array, g_strdup ("-a")); g_ptr_array_add (argv_array, g_file_get_path (app_files)); g_ptr_array_add (argv_array, g_strdup ("-I")); g_ptr_array_add (argv_array, g_strdup (app)); g_ptr_array_add (argv_array, g_file_get_path (runtime_files)); g_ptr_array_add (argv_array, g_strdup (command)); for (i = 1; i < rest_argc; i++) g_ptr_array_add (argv_array, g_strdup (argv[rest_argv_start + i])); g_ptr_array_add (argv_array, NULL); envp = g_get_environ (); envp = xdg_app_run_apply_env_default (envp); envp = xdg_app_run_apply_env_vars (envp, app_context); envp = xdg_app_run_apply_env_appid (envp, app_id_dir); if (execvpe (HELPER, (char **)argv_array->pdata, envp) == -1) { g_set_error (error, G_IO_ERROR, g_io_error_from_errno (errno), "Unable to start app"); return FALSE; } /* Not actually reached... */ return TRUE; }