Skip to content
Snippets Groups Projects
wrap.c 66.6 KiB
Newer Older
                          "--chdir", cwd_p,
                          "--unsetenv", "PWD",
                          NULL);

  /* TODO: Potential future expansion: use --unshare-pid for more isolation */

  /* Put Steam Runtime environment variables back, if /usr is mounted
   * from the host. */
  if (opt_runtime == NULL)
    {
      g_debug ("Making Steam Runtime available...");

      /* We need libraries from the Steam Runtime, so make sure that's
       * visible (it should never need to be read/write though) */
      if (opt_env_if_host != NULL)
        {
          for (i = 0; opt_env_if_host[i] != NULL; i++)
            {
              char *equals = strchr (opt_env_if_host[i], '=');

              g_assert (equals != NULL);

              if (g_str_has_prefix (opt_env_if_host[i], "STEAM_RUNTIME=/"))
                {
                  flatpak_bwrap_add_args (bwrap,
                                          "--ro-bind", equals + 1,
                                          equals + 1,
                                          NULL);
                }

              *equals = '\0';
              /* We do this via --setenv instead of flatpak_bwrap_set_env()
               * to make sure they aren't filtered out by a setuid bwrap. */
              flatpak_bwrap_add_args (bwrap,
                                      "--setenv", opt_env_if_host[i],
                                      equals + 1,
                                      NULL);
              *equals = '=';
            }
        }
    }

  g_debug ("Adding wrapped command...");
  flatpak_bwrap_append_args (bwrap, wrapped_command->argv);
  flatpak_bwrap_finish (bwrap);

  if (opt_verbose)
    {
      g_message ("%s options:", bwrap_executable);

      for (i = 0; i < bwrap->argv->len - 1; i++)
        {
          g_autofree gchar *quoted = NULL;

          quoted = g_shell_quote (g_ptr_array_index (bwrap->argv, i));
          g_message ("\t%s", quoted);
        }

      g_message ("%s environment:", bwrap_executable);

      for (i = 0; bwrap->envp != NULL && bwrap->envp[i] != NULL; i++)
        {
          g_autofree gchar *quoted = NULL;

          quoted = g_shell_quote (bwrap->envp[i]);
          g_message ("\t%s", quoted);
        }
    }

  /* flatpak_bwrap_finish did this */
  g_assert (g_ptr_array_index (bwrap->argv, bwrap->argv->len - 1) == NULL);

  g_debug ("Launching child process...");

  if (opt_interactive)
    spawn_flags |= G_SPAWN_CHILD_INHERITS_STDIN;

  if (!g_spawn_async (NULL,   /* cwd */
                      (gchar **) bwrap->argv->pdata,
                      bwrap->envp,
                      spawn_flags,
                      flatpak_bwrap_child_setup_cb,
                      bwrap->fds,
                      &child_pid,
                      error))
    {
      ret = 127;
      goto out;
    }

  g_child_watch_add (child_pid, child_exited_cb, &child_exited_closure);

  while (!child_exited_closure.exited)
    g_main_context_iteration (NULL, TRUE);

  if (opt_verbose)
    {
      if (WIFEXITED (child_exited_closure.wait_status))
        g_message ("Command exited with status %d",
                    WEXITSTATUS (child_exited_closure.wait_status));
      else if (WIFSIGNALED (child_exited_closure.wait_status))
        g_message ("Command killed by signal %d",
                   WTERMSIG (child_exited_closure.wait_status));
      else
        g_message ("Command terminated in an unknown way");
    }

  if (WIFEXITED (child_exited_closure.wait_status))
    ret = WEXITSTATUS (child_exited_closure.wait_status);
  else if (WIFSIGNALED (child_exited_closure.wait_status))
    ret = 128 + WTERMSIG (child_exited_closure.wait_status);
  else
    ret = 126;

out:
  if (local_error != NULL)
    g_warning ("%s", local_error->message);

  if (tmpdir != NULL &&
      !glnx_shutil_rm_rf_at (-1, tmpdir, NULL, error))
    {
      g_warning ("Unable to delete temporary directory: %s",
                 local_error->message);
      g_clear_error (&local_error);
    }

  g_clear_pointer (&opt_ld_preload, g_ptr_array_unref);
  g_clear_pointer (&opt_env_if_host, g_strfreev);
  g_clear_pointer (&opt_freedesktop_app_id, g_free);
  g_clear_pointer (&opt_steam_app_id, g_free);
  g_clear_pointer (&opt_home, g_free);
  g_clear_pointer (&opt_fake_home, g_free);
  g_clear_pointer (&opt_runtime, g_free);

  return ret;
}