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

Reply via email to