Package: gvfs-bin Version: 1.12.3-1 Severity: normal Tags: patch upstream -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA1
Hi! gvfs-open allows one to open a file with the "preferred application". Unfortunately, it exits as soon as the application is started. Therefore, it is not usable from another application that provides a temporary file and waits for the application to terminate to delete it (typically, a mail program). This bug has already been reported upstream last year: https://bugzilla.gnome.org/show_bug.cgi?id=652262 I have just provided a patch. Maybe it could go in Debian before being applied upstream (or before the next version with the patch, if applied, hits Debian). It could a solution to people wondering how to solve bug #497779 by adding the appropriate wildcard entry in /etc/mailcap (not a perfect solution, but better than nothing). - -- System Information: Debian Release: wheezy/sid APT prefers unstable APT policy: (500, 'unstable'), (500, 'testing'), (101, 'experimental') Architecture: amd64 (x86_64) Kernel: Linux 3.2.0-2-amd64 (SMP w/2 CPU cores) Locale: LANG=fr_FR.utf8, LC_CTYPE=fr_FR.utf8 (charmap=UTF-8) Shell: /bin/sh linked to /bin/dash Versions of packages gvfs-bin depends on: ii gvfs-common 1.12.3-1 ii libc6 2.13-33 ii libglib2.0-0 2.32.3-1 gvfs-bin recommends no packages. Versions of packages gvfs-bin suggests: ii gvfs 1.12.3-1 - -- no debconf information -----BEGIN PGP SIGNATURE----- Version: GnuPG v1.4.12 (GNU/Linux) iEYEARECAAYFAk/ZE/wACgkQKFvXofIqeU4lXACfTbU0A4tt1R991SMRhBHnN0V+ BDgAn2r6CczANZDH7Tw0sfNmpvyMro8e =luFt -----END PGP SIGNATURE-----
>From 2c8b70b56c51b764997ef052f91bde4a27f6c215 Mon Sep 17 00:00:00 2001 From: Vincent Bernat <ber...@luffy.cx> Date: Wed, 13 Jun 2012 23:17:43 +0200 Subject: [PATCH 1/2] gvfs-open: always use `g_app_info_launch_uris ()` Internally, `g_app_info_launch ()` calls `g_file_get_uri ()` then pass the result to `g_app_info_launch_uris ()`. Therefore, it seems useless to have a special case for a local file. --- programs/gvfs-open.c | 35 ++++++++--------------------------- 1 file changed, 8 insertions(+), 27 deletions(-) diff --git a/programs/gvfs-open.c b/programs/gvfs-open.c index c72a896..063a001 100644 --- a/programs/gvfs-open.c +++ b/programs/gvfs-open.c @@ -39,21 +39,13 @@ static GOptionEntry entries[] = { }; static gboolean -is_file_uri_with_anchor (char *str) -{ - if (g_ascii_strncasecmp (str, "file:", 5) == 0 && - strchr (str, '#') != NULL) - return TRUE; - return FALSE; -} - -static gboolean -open (GFile *file, char *arg_string) +open (GFile *file) { GAppInfo *app; GError *error; GList l = {NULL}; gboolean res; + char *uri = NULL; error = NULL; app = g_file_query_default_handler (file, NULL, &error); @@ -68,22 +60,11 @@ open (GFile *file, char *arg_string) return FALSE; } - if (g_file_is_native (file) && !is_file_uri_with_anchor (arg_string)) - { - /* For normal files, pass in the canonicalized GFile as path */ - l.data = file; - res = g_app_info_launch (app, &l, - NULL, &error); - } - else - { - /* However, for uris, use the original string, as it might be - modified by passing throught GFile (e.g. mailto: links) - */ - l.data = arg_string; - res = g_app_info_launch_uris (app, &l, - NULL, &error); - } + uri = g_file_get_uri (file); + l.data = uri; + res = g_app_info_launch_uris (app, &l, + NULL, &error); + g_free (uri); if (!res) { @@ -163,7 +144,7 @@ main (int argc, char *argv[]) do { file = g_file_new_for_commandline_arg (locations[i]); - res += !open (file, locations[i]); + res += !open (file); g_object_unref (file); } while (locations[++i] != NULL); -- 1.7.10
>From 765ef0612a1f3d0615d4f086c9d93f4c110f8303 Mon Sep 17 00:00:00 2001 From: Vincent Bernat <ber...@luffy.cx> Date: Thu, 14 Jun 2012 00:15:03 +0200 Subject: [PATCH 2/2] gvfs-open: add a `-w` flag to wait for the application to terminate The implementation uses the deprecated function `g_desktop_app_info_launch_uris_as_manager()` to retrieve the PID of the launched application and waits for it to terminate properly. --- programs/gvfs-open.c | 78 ++++++++++++++++++++++++++++++++++++++++++++++++-- 1 file changed, 75 insertions(+), 3 deletions(-) diff --git a/programs/gvfs-open.c b/programs/gvfs-open.c index 063a001..6604409 100644 --- a/programs/gvfs-open.c +++ b/programs/gvfs-open.c @@ -26,18 +26,32 @@ #include <unistd.h> #include <locale.h> #include <errno.h> +#include <sys/types.h> +#include <sys/wait.h> #include <glib.h> #include <glib/gi18n.h> #include <gio/gio.h> +#include <gio/gdesktopappinfo.h> static gchar **locations = NULL; +static gboolean waitfor = FALSE; +static GPid child = 0; static GOptionEntry entries[] = { + { "wait", 'w', 0, G_OPTION_ARG_NONE, &waitfor, + N_("Wait for the launched program to terminate"), NULL }, {G_OPTION_REMAINING, 0, 0, G_OPTION_ARG_FILENAME_ARRAY, &locations, N_("files"), NULL}, {NULL} }; +static void +pid_callback (GDesktopAppInfo *appinfo, GPid pid, gpointer user_data) +{ + /* Remember the PID. */ + child = pid; +} + static gboolean open (GFile *file) { @@ -46,6 +60,7 @@ open (GFile *file) GList l = {NULL}; gboolean res; char *uri = NULL; + int status, ret; error = NULL; app = g_file_query_default_handler (file, NULL, &error); @@ -62,8 +77,33 @@ open (GFile *file) uri = g_file_get_uri (file); l.data = uri; - res = g_app_info_launch_uris (app, &l, - NULL, &error); + if (!waitfor) + { + res = g_app_info_launch_uris (app, &l, + NULL, &error); + } + else + { + /* We need to execute the program manually. We don't do all the + work done by `g_app_info_launch_uris`, only the minimal one + to launch the application and waits for + it. `g_app_info_launch_uris()` is not flexible enough for + this. We use g_desktop_app_info_launch_uris_as_manager()` + instead. */ + child = 0; + res = g_desktop_app_info_launch_uris_as_manager (G_DESKTOP_APP_INFO (app), + &l, + NULL, + G_SPAWN_SEARCH_PATH | + G_SPAWN_DO_NOT_REAP_CHILD, + NULL, NULL, + pid_callback, NULL, + &error); + /* Here, `child` is the PID of the invoked process. We know + there is only one process because we provided only one + URI. `pid_callback` was therefore called only once. */ + } + g_free (uri); if (!res) @@ -77,7 +117,39 @@ open (GFile *file) g_object_unref (app); - return res; + if (!res || !waitfor || !child) + return res; + + again: + /* We cannot use `g_child_watch_add()` since we do not have a loop. */ + ret = waitpid (child, &status, 0); + if (ret < 0) + { + if (errno == EINTR) + goto again; + if (errno == ECHILD) + { + /* Should not happend! */ + g_printerr (_("%s: %s: lost the application...\n"), + g_get_prgname (), g_file_get_uri (file)); + return FALSE; + } + g_printerr (_("%s: %s: error while waiting for the process to terminate: %m\n"), + g_get_prgname (), g_file_get_uri (file)); + return FALSE; + } + if (!WIFEXITED(status)) + { + g_printerr (_("%s: %s: application terminated abnormally.\n"), + g_get_prgname (), g_file_get_uri (file)); + return FALSE; + } + if (WEXITSTATUS(status) == 0) + return TRUE; + + g_printerr (_("%s: %s: application terminated with status %d\n"), + g_get_prgname (), g_file_get_uri (file), WEXITSTATUS(status)); + return FALSE; } int -- 1.7.10