diff --git a/bin/check-requirements.c b/bin/check-requirements.c
index a28c252106187ad2995d8f63cbac8e960d5093bb..3f26d11bbcf629d963410d1dbad97fa9c86f4bb1 100644
--- a/bin/check-requirements.c
+++ b/bin/check-requirements.c
@@ -81,56 +81,6 @@ usage (int code)
   exit (code);
 }
 
-static FILE *
-divert_stdout_to_stderr (GError **error)
-{
-  int original_stdout_fd;
-  FILE *original_stdout;
-
-  /* Duplicate the original stdout so that we still have a way to write
-   * machine-readable output. */
-  original_stdout_fd = dup (STDOUT_FILENO);
-
-  if (original_stdout_fd < 0)
-    {
-      int saved_errno = errno;
-
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
-                   "Unable to duplicate fd %d: %s",
-                   STDOUT_FILENO, g_strerror (saved_errno));
-      return NULL;
-    }
-
-  /* If something like g_debug writes to stdout, make it come out of
-   * our original stderr. */
-  if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO)
-    {
-      int saved_errno = errno;
-
-      close (original_stdout_fd);
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
-                   "Unable to make fd %d a copy of fd %d: %s",
-                   STDOUT_FILENO, STDERR_FILENO, g_strerror (saved_errno));
-      return NULL;
-    }
-
-  /* original_stdout takes ownership of original_stdout_fd on success */
-  original_stdout = fdopen (original_stdout_fd, "w");
-
-  if (original_stdout == NULL)
-    {
-      int saved_errno = errno;
-
-      close (original_stdout_fd);
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
-                   "Unable to create a stdio wrapper for fd %d: %s",
-                   original_stdout_fd, g_strerror (saved_errno));
-      return NULL;
-    }
-
-  return original_stdout;
-}
-
 static gboolean
 check_x86_features (SrtX86FeatureFlags features)
 {
@@ -180,7 +130,7 @@ main (int argc,
 
   /* stdout is reserved for machine-readable output, so avoid having
    * things like g_debug() pollute it. */
-  original_stdout = divert_stdout_to_stderr (&error);
+  original_stdout = _srt_divert_stdout_to_stderr (&error);
 
   if (original_stdout == NULL)
     {
diff --git a/bin/system-info.c b/bin/system-info.c
index e4a7bce3316bbd5be3b5baa781e46bdf4bd0cf08..9034e28a1136624757f2b37400f94409fbd27af8 100644
--- a/bin/system-info.c
+++ b/bin/system-info.c
@@ -166,56 +166,6 @@ usage (int code)
   exit (code);
 }
 
-static FILE *
-divert_stdout_to_stderr (GError **error)
-{
-  int original_stdout_fd;
-  FILE *original_stdout;
-
-  /* Duplicate the original stdout so that we still have a way to write
-   * machine-readable output. */
-  original_stdout_fd = dup (STDOUT_FILENO);
-
-  if (original_stdout_fd < 0)
-    {
-      int saved_errno = errno;
-
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
-                   "Unable to duplicate fd %d: %s",
-                   STDOUT_FILENO, g_strerror (saved_errno));
-      return NULL;
-    }
-
-  /* If something like g_debug writes to stdout, make it come out of
-   * our original stderr. */
-  if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO)
-    {
-      int saved_errno = errno;
-
-      close (original_stdout_fd);
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
-                   "Unable to make fd %d a copy of fd %d: %s",
-                   STDOUT_FILENO, STDERR_FILENO, g_strerror (saved_errno));
-      return NULL;
-    }
-
-  /* original_stdout takes ownership of original_stdout_fd on success */
-  original_stdout = fdopen (original_stdout_fd, "w");
-
-  if (original_stdout == NULL)
-    {
-      int saved_errno = errno;
-
-      close (original_stdout_fd);
-      g_set_error (error, G_FILE_ERROR, g_file_error_from_errno (saved_errno),
-                   "Unable to create a stdio wrapper for fd %d: %s",
-                   original_stdout_fd, g_strerror (saved_errno));
-      return NULL;
-    }
-
-  return original_stdout;
-}
-
 static void
 jsonify_flags (JsonBuilder *builder,
                GType flags_type,
@@ -895,7 +845,7 @@ main (int argc,
 
   /* stdout is reserved for machine-readable output, so avoid having
    * things like g_debug() pollute it. */
-  original_stdout = divert_stdout_to_stderr (&error);
+  original_stdout = _srt_divert_stdout_to_stderr (&error);
 
   if (original_stdout == NULL)
     {
diff --git a/pressure-vessel/adverb.c b/pressure-vessel/adverb.c
index acfc40bd8629ff0f03cc06c106b2f2daed21c8cd..7a1e7a2017a4b836d2b8ff018dd2a03910e56e6c 100644
--- a/pressure-vessel/adverb.c
+++ b/pressure-vessel/adverb.c
@@ -678,7 +678,7 @@ main (int argc,
                        G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO,
                        cli_log_func, (void *) g_get_prgname ());
 
-  original_stdout = pv_divert_stdout_to_stderr (error);
+  original_stdout = _srt_divert_stdout_to_stderr (error);
 
   if (original_stdout == NULL)
     {
diff --git a/pressure-vessel/launch.c b/pressure-vessel/launch.c
index 7cdbe216a91e57fe0593312f1d30fa6da18423a1..0015de161910ff8b2a018e58b28d0fd0cddd4b80 100644
--- a/pressure-vessel/launch.c
+++ b/pressure-vessel/launch.c
@@ -40,6 +40,7 @@
 #include <gio/gunixfdlist.h>
 
 #include "steam-runtime-tools/glib-backports-internal.h"
+#include "steam-runtime-tools/utils-internal.h"
 #include "libglnx/libglnx.h"
 
 #include "launcher.h"
@@ -516,7 +517,7 @@ main (int argc,
                        G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO,
                        cli_log_func, (void *) g_get_prgname ());
 
-  original_stdout = pv_divert_stdout_to_stderr (error);
+  original_stdout = _srt_divert_stdout_to_stderr (error);
 
   if (original_stdout == NULL)
     {
diff --git a/pressure-vessel/launcher.c b/pressure-vessel/launcher.c
index a30cdee0f671aab4789539d5383e8bd930d1baaf..dfc3af2ba209ec428f20c88a8707141e005e338c 100644
--- a/pressure-vessel/launcher.c
+++ b/pressure-vessel/launcher.c
@@ -41,6 +41,7 @@
 #include <gio/gunixfdlist.h>
 
 #include "steam-runtime-tools/glib-backports-internal.h"
+#include "steam-runtime-tools/utils-internal.h"
 #include "libglnx/libglnx.h"
 
 #include "flatpak-utils-base-private.h"
@@ -1089,7 +1090,7 @@ main (int argc,
                        G_LOG_LEVEL_DEBUG | G_LOG_LEVEL_INFO,
                        cli_log_func, (void *) g_get_prgname ());
 
-  original_stdout = pv_divert_stdout_to_stderr (error);
+  original_stdout = _srt_divert_stdout_to_stderr (error);
 
   if (original_stdout == NULL)
     {
diff --git a/pressure-vessel/meson.build b/pressure-vessel/meson.build
index ca2d1cc86f6ebd73075f18803cb2ddaac3005f9c..8281b56ddeaf66aaeb37d8ce0c6b46b3d3be143d 100644
--- a/pressure-vessel/meson.build
+++ b/pressure-vessel/meson.build
@@ -157,6 +157,7 @@ executable(
     threads,
     gio_unix,
     libglnx_dep,
+    json_glib,
   ],
   include_directories : pv_include_dirs,
   install : true,
@@ -177,6 +178,7 @@ executable(
     threads,
     gio_unix,
     libglnx_dep,
+    json_glib,
   ],
   include_directories : pv_include_dirs,
   install : true,
@@ -207,6 +209,7 @@ executable(
     gio_unix,
     xau,
     libglnx_dep,
+    json_glib,
   ],
   include_directories : pv_include_dirs,
   install : true,
diff --git a/pressure-vessel/utils.c b/pressure-vessel/utils.c
index ad256557fc50ef9849035a453c0b58ec9a6d06f5..4236f3328078d93194c642dfb3fb6e989fd1a0ad 100644
--- a/pressure-vessel/utils.c
+++ b/pressure-vessel/utils.c
@@ -306,63 +306,6 @@ pv_boolean_environment (const gchar *name,
   return def;
 }
 
-/**
- * pv_divert_stdout_to_stderr:
- * @error: Used to raise an error on failure
- *
- * Duplicate file descriptors so that functions that would write to
- * `stdout` instead write to a copy of the original `stderr`. Return
- * a file handle that can be used to print structured output to the
- * original `stdout`.
- *
- * Returns: (transfer full): A libc file handle for the original `stdout`,
- *  or %NULL on error. Free with `fclose()`.
- */
-FILE *
-pv_divert_stdout_to_stderr (GError **error)
-{
-  g_autoptr(FILE) original_stdout = NULL;
-  glnx_autofd int original_stdout_fd = -1;
-  int flags;
-
-  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
-
-  /* Duplicate the original stdout so that we still have a way to write
-   * machine-readable output. */
-  original_stdout_fd = dup (STDOUT_FILENO);
-
-  if (original_stdout_fd < 0)
-    return glnx_null_throw_errno_prefix (error,
-                                         "Unable to duplicate fd %d",
-                                         STDOUT_FILENO);
-
-  flags = fcntl (original_stdout_fd, F_GETFD, 0);
-
-  if (flags < 0)
-    return glnx_null_throw_errno_prefix (error,
-                                         "Unable to get flags of new fd");
-
-  fcntl (original_stdout_fd, F_SETFD, flags|FD_CLOEXEC);
-
-  /* If something like g_debug writes to stdout, make it come out of
-   * our original stderr. */
-  if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO)
-    return glnx_null_throw_errno_prefix (error,
-                                         "Unable to make fd %d a copy of fd %d",
-                                         STDOUT_FILENO, STDERR_FILENO);
-
-  original_stdout = fdopen (original_stdout_fd, "w");
-
-  if (original_stdout == NULL)
-    return glnx_null_throw_errno_prefix (error,
-                                         "Unable to create a stdio wrapper for fd %d",
-                                         original_stdout_fd);
-  else
-    original_stdout_fd = -1;    /* ownership taken, do not close */
-
-  return g_steal_pointer (&original_stdout);
-}
-
 /**
  * pv_async_signal_safe_error:
  * @message: A human-readable message
diff --git a/pressure-vessel/utils.h b/pressure-vessel/utils.h
index 2e8ec6744027a7f96f5a29866a311563ffd6e694..3809104722f8c3475c3160270e14e5ec695ae9f8 100644
--- a/pressure-vessel/utils.h
+++ b/pressure-vessel/utils.h
@@ -57,8 +57,6 @@ gpointer pv_hash_table_get_arbitrary_key (GHashTable *table);
 gboolean pv_boolean_environment (const gchar *name,
                                  gboolean def);
 
-FILE *pv_divert_stdout_to_stderr (GError **error);
-
 void pv_async_signal_safe_error (const char *message,
                                  int exit_status) G_GNUC_NORETURN;
 
diff --git a/pressure-vessel/wrap.c b/pressure-vessel/wrap.c
index 831dabca34e7d3c2e35dbef34c6a3ca94ad22714..471560de161eeedd9bdad8e5ab7b9cac79876ccc 100644
--- a/pressure-vessel/wrap.c
+++ b/pressure-vessel/wrap.c
@@ -30,6 +30,7 @@
 #include <stdlib.h>
 
 #include "steam-runtime-tools/glib-backports-internal.h"
+#include "steam-runtime-tools/utils-internal.h"
 #include "libglnx/libglnx.h"
 
 #include "bwrap.h"
@@ -1277,7 +1278,7 @@ main (int argc,
       goto out;
     }
 
-  original_stdout = pv_divert_stdout_to_stderr (error);
+  original_stdout = _srt_divert_stdout_to_stderr (error);
 
   if (original_stdout == NULL)
     {
diff --git a/steam-runtime-tools/meson.build b/steam-runtime-tools/meson.build
index eec30738c7f8eea4d68824a23af33ee7d34ce029..86e8b85cceaf0df574ade38a861e36b48931d867 100644
--- a/steam-runtime-tools/meson.build
+++ b/steam-runtime-tools/meson.build
@@ -105,6 +105,7 @@ libsteamrt = library(
     gio_unix,
     glib,
     gobject,
+    libglnx_dep,
     json_glib,
   ],
   objects : [libsteamrt_static.extract_all_objects()],
diff --git a/steam-runtime-tools/utils-internal.h b/steam-runtime-tools/utils-internal.h
index 16bfa423fa1919ff125b9699439b8050d95cc82f..308e60a1b9ec084a34820ab3d0ae549ae775e423 100644
--- a/steam-runtime-tools/utils-internal.h
+++ b/steam-runtime-tools/utils-internal.h
@@ -26,6 +26,8 @@
 
 #pragma once
 
+#include <stdio.h>
+
 #include <glib.h>
 
 #include <json-glib/json-glib.h>
@@ -83,3 +85,5 @@ gchar ** _srt_json_array_to_strv (JsonObject *json_obj,
                                   const gchar *array_member);
 
 gboolean _srt_rm_rf (const char *directory);
+
+FILE *_srt_divert_stdout_to_stderr (GError **error);
diff --git a/steam-runtime-tools/utils.c b/steam-runtime-tools/utils.c
index 425de4faaebe0b61fa4d11f03bc022a5bb71c794..cd059711b13c33d3820ee7a33a99befa83287921 100644
--- a/steam-runtime-tools/utils.c
+++ b/steam-runtime-tools/utils.c
@@ -805,3 +805,60 @@ _srt_json_array_to_strv (JsonObject *json_obj,
 
   return ret;
 }
+
+/*
+ * _srt_divert_stdout_to_stderr:
+ * @error: Used to raise an error on failure
+ *
+ * Duplicate file descriptors so that functions that would write to
+ * `stdout` instead write to a copy of the original `stderr`. Return
+ * a file handle that can be used to print structured output to the
+ * original `stdout`.
+ *
+ * Returns: (transfer full): A libc file handle for the original `stdout`,
+ *  or %NULL on error. Free with `fclose()`.
+ */
+FILE *
+_srt_divert_stdout_to_stderr (GError **error)
+{
+  g_autoptr(FILE) original_stdout = NULL;
+  glnx_autofd int original_stdout_fd = -1;
+  int flags;
+
+  g_return_val_if_fail (error == NULL || *error == NULL, FALSE);
+
+  /* Duplicate the original stdout so that we still have a way to write
+   * machine-readable output. */
+  original_stdout_fd = dup (STDOUT_FILENO);
+
+  if (original_stdout_fd < 0)
+    return glnx_null_throw_errno_prefix (error,
+                                         "Unable to duplicate fd %d",
+                                         STDOUT_FILENO);
+
+  flags = fcntl (original_stdout_fd, F_GETFD, 0);
+
+  if (flags < 0)
+    return glnx_null_throw_errno_prefix (error,
+                                         "Unable to get flags of new fd");
+
+  fcntl (original_stdout_fd, F_SETFD, flags|FD_CLOEXEC);
+
+  /* If something like g_debug writes to stdout, make it come out of
+   * our original stderr. */
+  if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO)
+    return glnx_null_throw_errno_prefix (error,
+                                         "Unable to make fd %d a copy of fd %d",
+                                         STDOUT_FILENO, STDERR_FILENO);
+
+  original_stdout = fdopen (original_stdout_fd, "w");
+
+  if (original_stdout == NULL)
+    return glnx_null_throw_errno_prefix (error,
+                                         "Unable to create a stdio wrapper for fd %d",
+                                         original_stdout_fd);
+  else
+    original_stdout_fd = -1;    /* ownership taken, do not close */
+
+  return g_steal_pointer (&original_stdout);
+}
diff --git a/tests/adverb.c b/tests/adverb.c
index 3928eda843a2a0c327187e35c921bf10ab184d0f..134c0849e5648795459ba86e907eafa33535922c 100644
--- a/tests/adverb.c
+++ b/tests/adverb.c
@@ -34,6 +34,7 @@
 #include <gio/gio.h>
 
 #include "steam-runtime-tools/glib-backports-internal.h"
+#include "steam-runtime-tools/utils-internal.h"
 
 static gboolean opt_print_version = FALSE;
 static gboolean opt_ignore_sigchld = FALSE;
@@ -65,56 +66,20 @@ static GOptionEntry options[] =
   { NULL }
 };
 
-/* Return the original stdout fd. */
-static int
-divert_stdout_to_stderr (GError **error)
+static gboolean
+put_back_original_stdout (FILE *original_stdout,
+                          GError **error)
 {
-  int original_stdout_fd;
-
-  /* Duplicate the original stdout so that we still have a way to write
-   * machine-readable output. */
-  original_stdout_fd = dup (STDOUT_FILENO);
+  int original_stdout_fd = fileno (original_stdout);
 
   if (original_stdout_fd < 0)
-    {
-      int saved_errno = errno;
-
-      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno),
-                   "Unable to duplicate fd %d: %s",
-                   STDOUT_FILENO, g_strerror (saved_errno));
-      return -1;
-    }
-
-  /* If something like g_debug writes to stdout, make it come out of
-   * our original stderr. */
-  if (dup2 (STDERR_FILENO, STDOUT_FILENO) != STDOUT_FILENO)
-    {
-      int saved_errno = errno;
-
-      close (original_stdout_fd);
-      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno),
-                   "Unable to make fd %d a copy of fd %d: %s",
-                   STDOUT_FILENO, STDERR_FILENO, g_strerror (saved_errno));
-      return -1;
-    }
+    return glnx_throw_errno_prefix (error,
+                                    "Unable to get fileno of original stdout");
 
-  return original_stdout_fd;
-}
-
-static gboolean
-put_back_original_stdout (int original_stdout_fd,
-                          GError **error)
-{
   if (dup2 (original_stdout_fd, STDOUT_FILENO) != STDOUT_FILENO)
-    {
-      int saved_errno = errno;
-
-      g_set_error (error, G_IO_ERROR, g_io_error_from_errno (saved_errno),
-                   "Unable to make fd %d a copy of fd %d: %s",
-                   STDOUT_FILENO, original_stdout_fd,
-                   g_strerror (saved_errno));
-      return FALSE;
-    }
+    return glnx_throw_errno_prefix (error,
+                                    "Unable to make fd %d a copy of fd %d",
+                                    STDOUT_FILENO, original_stdout_fd);
 
   return TRUE;
 }
@@ -124,7 +89,7 @@ main (int argc,
       char *argv[])
 {
   GError *local_error = NULL;
-  int original_stdout_fd;
+  FILE *original_stdout = NULL;
   int ret = EX_USAGE;
   char **command_and_args;
   int saved_errno;
@@ -158,9 +123,9 @@ main (int argc,
       goto out;
     }
 
-  original_stdout_fd = divert_stdout_to_stderr (&local_error);
+  original_stdout = _srt_divert_stdout_to_stderr (&local_error);
 
-  if (original_stdout_fd < 0)
+  if (original_stdout == NULL)
     {
       ret = EX_OSERR;
       goto out;
@@ -352,7 +317,7 @@ main (int argc,
         }
     }
 
-  if (!put_back_original_stdout (original_stdout_fd, &local_error))
+  if (!put_back_original_stdout (original_stdout, &local_error))
     goto out;
 
   if (command_and_args == NULL)
diff --git a/tests/meson.build b/tests/meson.build
index 6f08fa9ddfc7ade04bc7ca5f3a6f2057e3bb87be..fbae1660f7930b117c52d7ca0acfb55cf769fb42 100644
--- a/tests/meson.build
+++ b/tests/meson.build
@@ -125,7 +125,7 @@ endforeach
 executable(
   'adverb',
   'adverb.c',
-  dependencies : [glib, gio, gio_unix, libglnx_dep],
+  dependencies : [glib, gio, gio_unix, libglnx_dep, json_glib, libsteamrt_dep],
   include_directories : project_include_dirs,
   install : get_option('installed_tests'),
   install_dir : tests_dir,
diff --git a/tests/pressure-vessel/helper.c b/tests/pressure-vessel/helper.c
index 63ff8b58acd037904d8820d7bc13970db9d2c70e..31a8de2f399b03a49372a7477751faf27255b079 100644
--- a/tests/pressure-vessel/helper.c
+++ b/tests/pressure-vessel/helper.c
@@ -30,6 +30,7 @@
 #include <glib/gstdio.h>
 
 #include "steam-runtime-tools/glib-backports-internal.h"
+#include "steam-runtime-tools/utils-internal.h"
 #include "libglnx/libglnx.h"
 
 #include "utils.h"
@@ -40,7 +41,7 @@ try_divert_stdout (void)
   g_autoptr(GError) error = NULL;
   g_autoptr(FILE) original_stdout = NULL;
 
-  original_stdout = pv_divert_stdout_to_stderr (&error);
+  original_stdout = _srt_divert_stdout_to_stderr (&error);
   g_assert_no_error (error);
 
   g_setenv ("G_MESSAGES_DEBUG", "all", TRUE);
diff --git a/tests/pressure-vessel/meson.build b/tests/pressure-vessel/meson.build
index f60a2e77b5746a9724626ff033d0a304d7a6f67e..9fb290ce73bf461cc0cdcd7b8b0beb715f09bc5a 100644
--- a/tests/pressure-vessel/meson.build
+++ b/tests/pressure-vessel/meson.build
@@ -157,6 +157,7 @@ foreach helper : helpers
     ],
     dependencies : [
       gio_unix,
+      json_glib,
       libglnx_dep,
     ],
     link_with : [