diff --git a/pressure-vessel/flatpak-run-private.h b/pressure-vessel/flatpak-run-private.h index 67b5cc0adfae025f95182d99dc79fd158ffd3b8e..f128f00c327c3f533d2cac6dff7d9bd59df024eb 100644 --- a/pressure-vessel/flatpak-run-private.h +++ b/pressure-vessel/flatpak-run-private.h @@ -38,6 +38,12 @@ #include "flatpak-utils-private.h" #include "steam-runtime-tools/glib-backports-internal.h" +/* modified for pressure-vessel */ +gboolean flatpak_run_in_transient_unit (const char *owner, + const char *prefix, + const char *appid, + GError **error); + /* See flatpak-metadata(5) */ #define FLATPAK_METADATA_GROUP_APPLICATION "Application" diff --git a/pressure-vessel/flatpak-run.c b/pressure-vessel/flatpak-run.c index a43babb7b9544f70c5f980e7670837406f2eca0f..32b07ae19195e9591cc15bffea74765139fa09e4 100644 --- a/pressure-vessel/flatpak-run.c +++ b/pressure-vessel/flatpak-run.c @@ -48,6 +48,7 @@ #include "flatpak-utils-base-private.h" #include "flatpak-utils-private.h" +#include "flatpak-systemd-dbus-generated.h" /* In Flatpak this is optional, in pressure-vessel not so much */ #define ENABLE_XAUTH @@ -1673,6 +1674,8 @@ flatpak_ensure_data_dir (GFile *app_id_dir, return TRUE; } +#endif + struct JobData { char *job; @@ -1707,8 +1710,16 @@ systemd_unit_name_escape (const gchar *in) return g_string_free (str, FALSE); } +/* + * Modified from Flatpak's version. For simplicity we assume that @owner + * and @prefix are in a form that don't need escaping to be a valid systemd + * scope name. + */ gboolean -flatpak_run_in_transient_unit (const char *appid, GError **error) +flatpak_run_in_transient_unit (const char *owner, + const char *prefix, + const char *appid, + GError **error) { g_autoptr(GDBusConnection) conn = NULL; g_autofree char *path = NULL; @@ -1753,7 +1764,8 @@ flatpak_run_in_transient_unit (const char *appid, GError **error) goto out; appid_escaped = systemd_unit_name_escape (appid); - name = g_strdup_printf ("app-flatpak-%s-%d.scope", appid_escaped, getpid ()); + name = g_strdup_printf ("app-%s-%s%s-%d.scope", + owner, prefix, appid_escaped, getpid ()); g_variant_builder_init (&builder, G_VARIANT_TYPE ("a(sv)")); @@ -1795,8 +1807,6 @@ out: return res; } -#endif - void flatpak_run_add_font_path_args (FlatpakBwrap *bwrap) { diff --git a/pressure-vessel/wrap-setup.c b/pressure-vessel/wrap-setup.c index 98f48ab05f1bf9b5594395db2b360a720bd4f57e..b381bdbe8a1438f589bc4cd20485c2b8631fb3be 100644 --- a/pressure-vessel/wrap-setup.c +++ b/pressure-vessel/wrap-setup.c @@ -287,3 +287,46 @@ pv_wrap_use_host_os (FlatpakExports *exports, return TRUE; } + +const char * +pv_wrap_get_steam_app_id (const char *from_command_line) +{ + const char *value; + + if (from_command_line != NULL) + return from_command_line; + + if ((value = g_getenv ("STEAM_COMPAT_APP_ID")) != NULL) + return value; + + if ((value = g_getenv ("SteamAppId")) != NULL) + return value; + + return NULL; +} + +/* + * Try to move the current process into a scope defined by the given + * Steam app ID. If that's not possible, ignore. + */ +void +pv_wrap_move_into_scope (const char *steam_app_id) +{ + g_autoptr(GError) local_error = NULL; + + if (steam_app_id != NULL) + { + if (steam_app_id[0] == '\0') + steam_app_id = NULL; + else if (strcmp (steam_app_id, "0") == 0) + steam_app_id = NULL; + } + + if (steam_app_id != NULL) + flatpak_run_in_transient_unit ("steam", "app", steam_app_id, &local_error); + else + flatpak_run_in_transient_unit ("steam", "", "unknown", &local_error); + + if (local_error != NULL) + g_debug ("Cannot move into a systemd scope: %s", local_error->message); +} diff --git a/pressure-vessel/wrap-setup.h b/pressure-vessel/wrap-setup.h index aae933076e390fc80124c26236b6d0300d5003ea..cfeef954a5360116cee4cac94eac54ea1287aa2c 100644 --- a/pressure-vessel/wrap-setup.h +++ b/pressure-vessel/wrap-setup.h @@ -36,3 +36,7 @@ void pv_wrap_share_sockets (FlatpakBwrap *bwrap, gboolean pv_wrap_use_host_os (FlatpakExports *exports, FlatpakBwrap *bwrap, GError **error); + +void pv_wrap_move_into_scope (const char *steam_app_id); + +const char *pv_wrap_get_steam_app_id (const char *from_command_line); diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c index 2bcb3d5df2f3bad20ea463d2358241e7c0864acc..d2b352f0d3b148795e9a5a0bb3e40e7d18a4c8d9 100644 --- a/pressure-vessel/wrap.c +++ b/pressure-vessel/wrap.c @@ -703,6 +703,7 @@ static char *opt_runtime_id = NULL; static Tristate opt_share_home = TRISTATE_MAYBE; static gboolean opt_share_pid = TRUE; static gboolean opt_single_thread = FALSE; +static gboolean opt_systemd_scope = FALSE; static double opt_terminate_idle_timeout = 0.0; static double opt_terminate_timeout = -1.0; static char *opt_variable_dir = NULL; @@ -1222,6 +1223,12 @@ static GOptionEntry options[] = G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_single_thread, "Disable multi-threaded code paths, for debugging", NULL }, + { "systemd-scope", '\0', + G_OPTION_FLAG_NONE, G_OPTION_ARG_NONE, &opt_systemd_scope, + "Attempt to run the game in a systemd scope", NULL }, + { "no-systemd-scope", '\0', + G_OPTION_FLAG_REVERSE, G_OPTION_ARG_NONE, &opt_systemd_scope, + "Do not run the game in a systemd scope", NULL }, { "terminal", '\0', G_OPTION_FLAG_NONE, G_OPTION_ARG_CALLBACK, opt_terminal_cb, "none: disable features that would use a terminal; " @@ -1338,6 +1345,7 @@ main (int argc, g_autoptr(PvRuntime) runtime = NULL; g_autoptr(FILE) original_stdout = NULL; g_autoptr(GArray) pass_fds_through_adverb = g_array_new (FALSE, FALSE, sizeof (int)); + const char *steam_app_id; setlocale (LC_ALL, ""); @@ -1399,6 +1407,8 @@ main (int argc, opt_remove_game_overlay = pv_boolean_environment ("PRESSURE_VESSEL_REMOVE_GAME_OVERLAY", FALSE); + opt_systemd_scope = pv_boolean_environment ("PRESSURE_VESSEL_SYSTEMD_SCOPE", + opt_systemd_scope); opt_import_vulkan_layers = pv_boolean_environment ("PRESSURE_VESSEL_IMPORT_VULKAN_LAYERS", TRUE); @@ -1577,6 +1587,8 @@ main (int argc, argc--; } + steam_app_id = pv_wrap_get_steam_app_id (opt_steam_app_id); + home = g_get_home_dir (); if (opt_share_home == TRISTATE_YES) @@ -1598,27 +1610,11 @@ main (int argc, opt_fake_home = g_build_filename (home, ".var", "app", opt_freedesktop_app_id, NULL); } - else if (opt_steam_app_id) - { - is_home_shared = FALSE; - opt_freedesktop_app_id = g_strdup_printf ("com.steampowered.App%s", - opt_steam_app_id); - opt_fake_home = g_build_filename (home, ".var", "app", - opt_freedesktop_app_id, NULL); - } - else if (g_getenv ("STEAM_COMPAT_APP_ID") != NULL) - { - is_home_shared = FALSE; - opt_freedesktop_app_id = g_strdup_printf ("com.steampowered.App%s", - g_getenv ("STEAM_COMPAT_APP_ID")); - opt_fake_home = g_build_filename (home, ".var", "app", - opt_freedesktop_app_id, NULL); - } - else if (g_getenv ("SteamAppId") != NULL) + else if (steam_app_id != NULL) { is_home_shared = FALSE; opt_freedesktop_app_id = g_strdup_printf ("com.steampowered.App%s", - g_getenv ("SteamAppId")); + steam_app_id); opt_fake_home = g_build_filename (home, ".var", "app", opt_freedesktop_app_id, NULL); } @@ -2787,9 +2783,15 @@ main (int argc, } if (opt_only_prepare) - ret = 0; - else - pv_bwrap_execve (final_argv, fileno (original_stdout), error); + { + ret = 0; + goto out; + } + + if (opt_systemd_scope) + pv_wrap_move_into_scope (steam_app_id); + + pv_bwrap_execve (final_argv, fileno (original_stdout), error); out: if (local_error != NULL)