gst-inspect: Port to Glib's spawn API

Although we support pager just for *nix until now,
this can make more portable to Windows.

Fixes #342
This commit is contained in:
Seungha Yang 2019-01-08 21:23:44 +09:00
parent 6ea4380230
commit 56b4fbef5e

View file

@ -42,10 +42,12 @@
#endif #endif
#define DEFAULT_PAGER "less" #define DEFAULT_PAGER "less"
#define DEFAULT_LESS_OPTS "FXR"
gboolean colored_output = TRUE; gboolean colored_output = TRUE;
GPid child_pid = -1;
GMainLoop *loop = NULL;
/* Console colors */ /* Console colors */
/* Escape values for colors */ /* Escape values for colors */
@ -1865,80 +1867,59 @@ print_all_plugin_automatic_install_info (void)
} }
#ifdef G_OS_UNIX #ifdef G_OS_UNIX
static void static gboolean
redirect_stdout (void) redirect_stdout (void)
{ {
int pipefd[2]; GError *error = NULL;
pid_t child_id; gchar **argv;
const gchar *pager;
if (pipe (pipefd) == -1) { gint stdin_fd;
g_printerr (_("Error creating pipe: %s\n"), g_strerror (errno)); gchar **envp;
exit (-1);
}
child_id = fork ();
if (child_id == -1) {
g_printerr (_("Error forking: %s\n"), g_strerror (errno));
exit (-1);
}
if (child_id == 0) {
char **argv;
const char *pager;
int ret;
pager = g_getenv ("PAGER"); pager = g_getenv ("PAGER");
if (pager == NULL) if (pager == NULL)
pager = DEFAULT_PAGER; pager = DEFAULT_PAGER;
argv = g_strsplit (pager, " ", 0); argv = g_strsplit (pager, " ", 0);
/* Make sure less will show colors, cat and more always show colors */ /* "R" : support color
g_setenv ("LESS", DEFAULT_LESS_OPTS, FALSE); * "X" : Do not init/deinit terminal. Uncleared "inspected output" on terminal
* seems to be more useful
*/
envp = g_get_environ ();
envp = g_environ_setenv (envp, "LESS", "-RX", TRUE);
/* child process */ if (!g_spawn_async_with_pipes (NULL, argv, envp,
close (pipefd[1]); G_SPAWN_DO_NOT_REAP_CHILD | G_SPAWN_SEARCH_PATH,
dup2 (pipefd[0], STDIN_FILENO); NULL, NULL, &child_pid, &stdin_fd,
close (pipefd[0]); /* pass null stdout/stderr to inherit our fds */
NULL, NULL, &error)) {
ret = execvp (argv[0], argv); g_warning ("g_spawn_async_with_pipes() failed: %s\n",
GST_STR_NULL (error->message));
g_strfreev (argv); g_strfreev (argv);
if (ret == -1) { g_strfreev (envp);
/* No less? Let's just dump everything to stdout then */ g_clear_error (&error);
char buffer[1024];
do { return FALSE;
int bytes_written;
if ((ret = read (STDIN_FILENO, buffer, sizeof (buffer))) == -1) {
if (errno == EINTR || errno == EAGAIN) {
continue;
} }
g_printerr (_("Error reading from console: %s\n"), /* redirect our stdout to child stdin */
g_strerror (errno)); dup2 (stdin_fd, STDOUT_FILENO);
exit (-1);
}
do {
bytes_written = write (STDOUT_FILENO, buffer, ret);
} while (bytes_written == -1 && (errno == EINTR || errno == EAGAIN));
if (bytes_written < 0) {
g_printerr (_("Error writing to console: %s\n"), g_strerror (errno));
exit (-1);
}
} while (ret > 0);
exit (0);
}
} else {
close (pipefd[0]);
dup2 (pipefd[1], STDOUT_FILENO);
if (isatty (STDERR_FILENO)) if (isatty (STDERR_FILENO))
dup2 (pipefd[1], STDERR_FILENO); dup2 (stdin_fd, STDERR_FILENO);
close (pipefd[1]); close (stdin_fd);
close (STDIN_FILENO);
g_strfreev (argv);
g_strfreev (envp);
return TRUE;
} }
static void
child_exit_cb (GPid child_pid, gint status, gpointer user_data)
{
g_spawn_close_pid (child_pid);
g_main_loop_quit (loop);
} }
#endif #endif
@ -1957,6 +1938,7 @@ main (int argc, char *argv[])
guint minver_micro = 0; guint minver_micro = 0;
gchar *types = NULL; gchar *types = NULL;
const gchar *no_colors; const gchar *no_colors;
int exit_code = 0;
#ifndef GST_DISABLE_OPTION_PARSING #ifndef GST_DISABLE_OPTION_PARSING
GOptionEntry options[] = { GOptionEntry options[] = {
{"print-all", 'a', 0, G_OPTION_ARG_NONE, &print_all, {"print-all", 'a', 0, G_OPTION_ARG_NONE, &print_all,
@ -2030,7 +2012,8 @@ main (int argc, char *argv[])
#ifdef G_OS_UNIX #ifdef G_OS_UNIX
if (isatty (STDOUT_FILENO)) { if (isatty (STDOUT_FILENO)) {
redirect_stdout (); if (redirect_stdout ())
loop = g_main_loop_new (NULL, FALSE);
} else { } else {
colored_output = FALSE; colored_output = FALSE;
} }
@ -2068,8 +2051,6 @@ main (int argc, char *argv[])
} }
if (check_exists) { if (check_exists) {
int exit_code;
if (argc == 1) { if (argc == 1) {
g_printerr ("--exists requires an extra command line argument\n"); g_printerr ("--exists requires an extra command line argument\n");
exit_code = -1; exit_code = -1;
@ -2145,24 +2126,32 @@ main (int argc, char *argv[])
} else { } else {
g_printerr (_("Could not load plugin file: %s\n"), error->message); g_printerr (_("Could not load plugin file: %s\n"), error->message);
g_clear_error (&error); g_clear_error (&error);
return -1; exit_code = -1;
goto done;
} }
} else { } else {
g_printerr (_("No such element or plugin '%s'\n"), arg); g_printerr (_("No such element or plugin '%s'\n"), arg);
return -1; exit_code = -1;
goto done;
} }
} }
} }
} }
done:
#ifdef G_OS_UNIX #ifdef G_OS_UNIX
if (loop) {
fflush (stdout); fflush (stdout);
fflush (stderr); fflush (stderr);
/* So that the pipe we create in redirect_stdout() is closed */ /* So that the pipe we create in redirect_stdout() is closed */
close (STDOUT_FILENO); close (STDOUT_FILENO);
close (STDERR_FILENO); close (STDERR_FILENO);
wait (NULL); g_child_watch_add (child_pid, child_exit_cb, NULL);
g_main_loop_run (loop);
g_main_loop_unref (loop);
}
#endif #endif
return 0; return exit_code;
} }