Attached is a patch showing how we can run executable files using g_spawn_async. Using g_app_info_new_from_commandline is unworkable because it needs escaping a general filename into a command-line. The only real solution is to completely cut out such escaping and parsing and pass the filename directly to g_spawn_async.
Only the first hunk of the patch is relevant. The rest of the patch was only needed to actually build the package (as it is currently FTBFS).
Description: Illustrative only patch for Bug#624015 Run executable files using g_spawn_async. Using g_app_info_new_from_commandline is unworkable and needs escaping a general filename into a command-line. The only real solution is to completely cut out such escaping and parsing and pass the filename directly to g_spawn_async. . The person named in the Author field signed this changelog entry. Author: ulrik Bug-Debian: http://bugs.debian.org/624015 --- The information above should follow the Patch Tagging Guidelines, please checkout http://dep.debian.net/deps/dep3/ to learn about the format. Here are templates for supplementary fields that you might want to add: Origin: <vendor|upstream|other>, <url of original patch> Bug: <url in upstream bugtracker> Bug-Debian: http://bugs.debian.org/<bugnumber> Bug-Ubuntu: https://launchpad.net/bugs/<bugnumber> Forwarded: <no|not-needed|url proving that it has been forwarded> Reviewed-By: <name and email of someone who approved the patch> Last-Update: <YYYY-MM-DD> --- libfm-0.1.14.orig/src/base/fm-file-launcher.c +++ libfm-0.1.14/src/base/fm-file-launcher.c @@ -172,19 +172,18 @@ gboolean fm_launch_files(GAppLaunchConte /* FIXME: we need to use eaccess/euidaccess here. */ if(g_file_test(filename, G_FILE_TEST_IS_EXECUTABLE)) { - app = g_app_info_create_from_commandline(filename, NULL, 0, NULL); - if(app) - { - if(!g_app_info_launch(app, NULL, ctx, &err)) - { - if(launcher->error) - launcher->error(ctx, err, user_data); - g_error_free(err); - err = NULL; - } - g_object_unref(app); - continue; + gchar *appargv[] = { filename, NULL }; + + if(!g_spawn_async(NULL, appargv, NULL, 0, NULL, NULL, + NULL, &err)) { + /* XXX: NULL app launch ctx */ + if(launcher->error) + launcher->error(NULL, err, user_data); + g_error_free(err); + err = NULL; } + + continue; } g_free(filename); } --- libfm-0.1.14.orig/src/gio/fm-app-lookup.c +++ libfm-0.1.14/src/gio/fm-app-lookup.c @@ -25,151 +25,3 @@ #include "fm-app-lookup.h" #include <gio/gdesktopappinfo.h> - -#ifndef G_IMPLEMENT_INTERFACE_DYNAMIC /* this macro is only provided in glib > 2.24 */ - #define G_IMPLEMENT_INTERFACE_DYNAMIC(TYPE_IFACE, iface_init) { \ - const GInterfaceInfo g_implement_interface_info = { \ - (GInterfaceInitFunc) iface_init, NULL, NULL \ - }; \ - g_type_module_add_interface (type_module, g_define_type_id, TYPE_IFACE, &g_implement_interface_info); \ - } -#endif - -static void app_lookup_iface_init(GDesktopAppInfoLookupIface *iface); -static GObject* fm_app_lookup_constructor(GType type, guint n_props, GObjectConstructParam *props); -static void fm_app_lookup_finalize (GObject *object); -static GAppInfo *get_default_for_uri_scheme(GDesktopAppInfoLookup *lookup, const char *scheme); - -G_DEFINE_DYNAMIC_TYPE_EXTENDED(FmAppLookup, fm_app_lookup, G_TYPE_OBJECT, 0, - G_IMPLEMENT_INTERFACE_DYNAMIC(G_TYPE_DESKTOP_APP_INFO_LOOKUP, app_lookup_iface_init)) - - -static void fm_app_lookup_class_init(FmAppLookupClass *klass) -{ - GObjectClass *g_object_class; - g_object_class = G_OBJECT_CLASS(klass); - g_object_class->constructor = fm_app_lookup_constructor; - g_object_class->finalize = fm_app_lookup_finalize; -} - -static void fm_app_lookup_class_finalize(FmAppLookupClass *klass) -{ -} - -GObject* fm_app_lookup_constructor(GType type, guint n_props, GObjectConstructParam *props) -{ - GObject* obj; - /* call parent constructor. */ - obj = G_OBJECT_CLASS(fm_app_lookup_parent_class)->constructor(type, n_props, props); - return obj; -} - -static void fm_app_lookup_finalize(GObject *object) -{ - FmAppLookup *self; - - g_return_if_fail(object != NULL); - g_return_if_fail(FM_IS_APP_LOOKUP(object)); - - self = FM_APP_LOOKUP(object); - G_OBJECT_CLASS(fm_app_lookup_parent_class)->finalize(object); -} - - -static void fm_app_lookup_init(FmAppLookup *self) -{ - -} - -void fm_app_lookup_register(GIOModule *module) -{ - gint priority; - fm_app_lookup_register_type(G_TYPE_MODULE (module)); - /* check if we're in gnome, if true, use lower priority. - * otherwise, use a high priority to override gvfs gconf module. - * priority of the gconf module of gvfs is 10. */ - if(G_UNLIKELY(g_getenv("GNOME_DESKTOP_SESSION_ID"))) /* we're in Gnome */ - priority = 9; - else /* we're in other desktop envionments */ - priority = 90; - - g_io_extension_point_implement(G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME, - FM_TYPE_APP_LOOKUP, "libfm-applookup", priority); - - /* TODO: implement our own G_NATIVE_VOLUME_MONITOR_EXTENSION_POINT_NAME */ -} - -static void app_lookup_iface_init(GDesktopAppInfoLookupIface *iface) -{ - iface->get_default_for_uri_scheme = get_default_for_uri_scheme; -} - -/* FIXME: implement our own browser lookup method not depending on gconf. */ -GAppInfo *get_default_for_uri_scheme(GDesktopAppInfoLookup *lookup, const char *scheme) -{ - GAppInfo* app; - GKeyFile* kf; - const char* key; - char* fname; - char* desktop_id = NULL; - - /* web browser */ - if(g_ascii_strcasecmp(scheme, "http")==0 || g_ascii_strcasecmp(scheme, "https")==0) - key = "WebBrowser"; - else if(g_ascii_strcasecmp(scheme, "mailto")==0) - key = "MailClient"; - else /* we don't know this */ - return NULL; - - kf = g_key_file_new(); - - /* try user config first */ - fname = g_build_filename(g_get_user_config_dir(), "libfm/pref-apps.conf", NULL); - if(g_key_file_load_from_file(kf, fname, 0, NULL)) - { - desktop_id = g_key_file_get_string(kf, "Preferred Applications", key, NULL); - if(desktop_id && !*desktop_id) - { - g_free(desktop_id); - desktop_id = NULL; - } - } - g_free(fname); - - if(!desktop_id) /* system-wide */ - { - const gchar* const *dirs = g_get_system_config_dirs(); - int i, n; - if(g_key_file_load_from_file(kf, fname, 0, NULL)) - desktop_id = g_key_file_get_string(kf, "Preferred Applications", key, NULL); - n = g_strv_length(dirs); - for( i = n - 1; i > 0; --i ) - { - fname = g_build_filename(dirs[i], "libfm/pref-apps.conf", NULL); - if( g_key_file_load_from_file(kf, fname, 0, NULL) ) - desktop_id = g_key_file_get_string(kf, "Preferred Applications", key, NULL); - g_free(fname); - if(desktop_id) - { - if(*desktop_id) - break; - else - { - g_free(desktop_id); - desktop_id = NULL; - } - } - } - } - - g_key_file_free(kf); - - if(!desktop_id) - return NULL; - - app = g_desktop_app_info_new(desktop_id); - - g_free(desktop_id); - - return app; -} --- libfm-0.1.14.orig/src/gio/fm-app-lookup.h +++ libfm-0.1.14/src/gio/fm-app-lookup.h @@ -24,34 +24,10 @@ #define __FM_APP_LOOKUP_H__ #include <gio/gio.h> +#include <gio/gdesktopappinfo.h> G_BEGIN_DECLS -#define FM_TYPE_APP_LOOKUP (fm_app_lookup_get_type()) -#define FM_APP_LOOKUP(obj) (G_TYPE_CHECK_INSTANCE_CAST((obj),\ - FM_TYPE_APP_LOOKUP, FmAppLookup)) -#define FM_APP_LOOKUP_CLASS(klass) (G_TYPE_CHECK_CLASS_CAST((klass),\ - FM_TYPE_APP_LOOKUP, FmAppLookupClass)) -#define FM_IS_APP_LOOKUP(obj) (G_TYPE_CHECK_INSTANCE_TYPE((obj),\ - FM_TYPE_APP_LOOKUP)) -#define FM_IS_APP_LOOKUP_CLASS(klass) (G_TYPE_CHECK_CLASS_TYPE((klass),\ - FM_TYPE_APP_LOOKUP)) - -typedef struct _FmAppLookup FmAppLookup; -typedef struct _FmAppLookupClass FmAppLookupClass; - -struct _FmAppLookup -{ - GObject parent; -}; - -struct _FmAppLookupClass -{ - GObjectClass parent_class; -}; - -GType fm_app_lookup_get_type(void); -void fm_app_lookup_register(GIOModule *module); G_END_DECLS --- libfm-0.1.14.orig/src/gio/module.c +++ libfm-0.1.14/src/gio/module.c @@ -33,19 +33,9 @@ void g_io_module_load (GIOModule *module) { - bindtextdomain (GETTEXT_PACKAGE, PACKAGE_LOCALE_DIR); - bind_textdomain_codeset (GETTEXT_PACKAGE, "UTF-8"); - fm_app_lookup_register (module); } void g_io_module_unload (GIOModule *module) { } -char** g_io_module_query (void) -{ - char** eps = g_new(char*, 2); - eps[0] = g_strdup(G_DESKTOP_APP_INFO_LOOKUP_EXTENSION_POINT_NAME); - eps[1] = NULL; - return eps; -} --- libfm-0.1.14.orig/src/tests/Makefile.in +++ libfm-0.1.14/src/tests/Makefile.in @@ -130,7 +130,7 @@ INTLTOOL_MERGE = @INTLTOOL_MERGE@ INTLTOOL_PERL = @INTLTOOL_PERL@ INTLTOOL_UPDATE = @INTLTOOL_UPDATE@ LD = @LD@ -LDFLAGS = @LDFLAGS@ +LDFLAGS = @LDFLAGS@ -lgobject-2.0 LIBOBJS = @LIBOBJS@ LIBS = @LIBS@ LIBTOOL = @LIBTOOL@ --- libfm-0.1.14.orig/src/tests/test-fm-path.c +++ libfm-0.1.14/src/tests/test-fm-path.c @@ -7,7 +7,7 @@ #define TEST_PARSING(func, str_to_parse, ...) \ G_STMT_START { \ - char* expected[] = {__VA_ARGS__}; \ + const char* expected[] = {__VA_ARGS__}; \ test_parsing(func, str_to_parse, expected, G_N_ELEMENTS(expected)); \ } G_STMT_END