Merge lp:~ted/ubuntu-app-launch/xdg-autostart into lp:ubuntu-app-launch/14.04

Proposed by Ted Gould
Status: Work in progress
Proposed branch: lp:~ted/ubuntu-app-launch/xdg-autostart
Merge into: lp:ubuntu-app-launch/14.04
Diff against target: 564 lines (+481/-3)
10 files modified
CMakeLists.txt (+34/-0)
debian/control (+9/-0)
debian/upstart-app-launch.install (+10/-2)
debian/upstart-xdg-autostart.install (+4/-0)
helpers.c (+1/-0)
helpers.h (+1/-1)
xdg-autostart-find.c (+141/-0)
xdg-autostart-find.conf.in (+8/-0)
xdg-autostart-parse.c (+258/-0)
xdg-autostart.conf.in (+15/-0)
To merge this branch: bzr merge lp:~ted/ubuntu-app-launch/xdg-autostart
Reviewer Review Type Date Requested Status
Indicator Applet Developers Pending
Review via email: mp+200545@code.launchpad.net

Commit message

Add support for XDG Autostart directories

Description of the change

This branch makes it so there are Upstart jobs that'll read the XDG Autostart directories and start the various desktop files that are located in them. It starts out as entirely benign, for good reason, you can really screw things up. To activate this feature you'll need to modify two Upstart jobs, first make copies in your home directory:

$ mkdir -p ~/.config/upstart
$ cp /usr/share/upstart/sessions/gnome-session.conf ~/.config/upstart/
$ cp /usr/share/upstart/sessions/xdg-autostart.conf ~/.config/upstart/

Then change the gnome-session command line to:

exec gnome-session --session=$DESKTOP_SESSION --autostart=/usr/share/gnome/

And uncomment this line in xdg-autostart.conf:

/usr/lib/$(arch)/upstart-app-launch/exec-line-exec

Then logout and log back in. You should see a new set of tasks in your Upstart task list:

$ initctl list | grep "xdg-autostart "
xdg-autostart (evolution-alarm-notify) start/running, process 8497
xdg-autostart (telepathy-indicator) start/running, process 8485
xdg-autostart (zeitgeist-datahub) start/running, process 8483
xdg-autostart (nautilus-autostart) start/running, process 8484
xdg-autostart (update-notifier) start/running, process 8486
xdg-autostart (gnome-fallback-mount-helper) start/running, process 8488
xdg-autostart (nm-applet) start/running, process 8490
xdg-autostart (gnome-screensaver) start/running, process 8500
xdg-autostart (deja-dup-monitor) start/running, process 8481
xdg-autostart (polkit-gnome-authentication-agent-1) start/running, process 8506

To post a comment you must log in.
128. By Ted Gould

Putting the autostart stuff into it's own package

129. By Ted Gould

TryExec support

130. By Ted Gould

Update to trunk

131. By Ted Gould

Update to trunk

Unmerged revisions

131. By Ted Gould

Update to trunk

130. By Ted Gould

Update to trunk

129. By Ted Gould

TryExec support

128. By Ted Gould

Putting the autostart stuff into it's own package

127. By Ted Gould

Dropping a TODO here

126. By Ted Gould

Adding autostart condition checking for booleans

125. By Ted Gould

Adding a callback parameter so that we can ensure the environment variable is set even with async calls

124. By Ted Gould

No, that was right before

123. By Ted Gould

Make the call synchronous so we know the environment variable got set

122. By Ted Gould

Wrong key

Preview Diff

[H/L] Next/Prev Comment, [J/K] Next/Prev File, [N/P] Next/Prev Hunk
1=== modified file 'CMakeLists.txt'
2--- CMakeLists.txt 2014-02-13 22:43:55 +0000
3+++ CMakeLists.txt 2014-02-26 14:46:02 +0000
4@@ -96,6 +96,24 @@
5 install(TARGETS click-exec RUNTIME DESTINATION "${pkglibexecdir}")
6
7 ####################
8+# xdg-autostart-find
9+####################
10+
11+add_executable(xdg-autostart-find xdg-autostart-find.c)
12+set_target_properties(xdg-autostart-find PROPERTIES OUTPUT_NAME "xdg-autostart-find")
13+target_link_libraries(xdg-autostart-find ${GIO2_LIBRARIES})
14+install(TARGETS xdg-autostart-find RUNTIME DESTINATION "${pkglibexecdir}")
15+
16+####################
17+# xdg-autostart-parse
18+####################
19+
20+add_executable(xdg-autostart-parse xdg-autostart-parse.c)
21+set_target_properties(xdg-autostart-parse PROPERTIES OUTPUT_NAME "xdg-autostart-parse")
22+target_link_libraries(xdg-autostart-parse helpers)
23+install(TARGETS xdg-autostart-parse RUNTIME DESTINATION "${pkglibexecdir}")
24+
25+####################
26 # desktop-hook
27 ####################
28
29@@ -152,6 +170,22 @@
30 install(TARGETS untrusted-helper-type-end RUNTIME DESTINATION "${pkglibexecdir}")
31
32 ####################
33+# xdg-autostart-find.conf
34+####################
35+
36+configure_file("xdg-autostart-find.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/xdg-autostart-find.conf" @ONLY)
37+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/xdg-autostart-find.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions")
38+add_test(xdg-autostart-find.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/xdg-autostart-find.conf")
39+
40+####################
41+# xdg-autostart.conf
42+####################
43+
44+configure_file("xdg-autostart.conf.in" "${CMAKE_CURRENT_BINARY_DIR}/xdg-autostart.conf" @ONLY)
45+install(FILES "${CMAKE_CURRENT_BINARY_DIR}/xdg-autostart.conf" DESTINATION "${CMAKE_INSTALL_DATADIR}/upstart/sessions")
46+add_test(xdg-autostart.conf.test "${CMAKE_SOURCE_DIR}/test-conffile.sh" "${CMAKE_CURRENT_BINARY_DIR}/xdg-autostart.conf")
47+
48+####################
49 # upstart-app-launch-desktop.click-hook
50 ####################
51
52
53=== modified file 'debian/control'
54--- debian/control 2014-02-11 03:14:30 +0000
55+++ debian/control 2014-02-26 14:46:02 +0000
56@@ -40,6 +40,15 @@
57 Upstart Job file and associated utilities that is used to launch
58 applications in a standard and confined way.
59
60+Package: upstart-xdg-autostart
61+Architecture: any
62+Depends: ${shlibs:Depends},
63+ ${misc:Depends},
64+ upstart-app-launch (= ${binary:Version}),
65+Description: Upstart Job for Launching XDG Autostart Files
66+ Upstart Job file and associated utilities that is used to launch
67+ applications defined with XDG Autostart files.
68+
69 Package: upstart-app-launch-tools
70 Architecture: any
71 Depends: ${shlibs:Depends},
72
73=== modified file 'debian/upstart-app-launch.install'
74--- debian/upstart-app-launch.install 2013-07-28 18:12:55 +0000
75+++ debian/upstart-app-launch.install 2014-02-26 14:46:02 +0000
76@@ -1,2 +1,10 @@
77-usr/share/upstart/sessions/*
78-usr/lib/*/upstart-app-launch/*
79+usr/share/upstart/sessions/application.conf
80+usr/share/upstart/sessions/application-click.conf
81+usr/share/upstart/sessions/application-legacy.conf
82+usr/lib/*/upstart-app-launch/click-exec
83+usr/lib/*/upstart-app-launch/desktop-exec
84+usr/lib/*/upstart-app-launch/desktop-hook
85+usr/lib/*/upstart-app-launch/desktop-single
86+usr/lib/*/upstart-app-launch/exec-line-exec
87+usr/lib/*/upstart-app-launch/second-exec
88+usr/lib/*/upstart-app-launch/zg-report-app
89
90=== added file 'debian/upstart-xdg-autostart.install'
91--- debian/upstart-xdg-autostart.install 1970-01-01 00:00:00 +0000
92+++ debian/upstart-xdg-autostart.install 2014-02-26 14:46:02 +0000
93@@ -0,0 +1,4 @@
94+usr/share/upstart/sessions/xdg-autostart-find.conf
95+usr/share/upstart/sessions/xdg-autostart.conf
96+usr/lib/*/upstart-app-launch/xdg-autostart-find
97+usr/lib/*/upstart-app-launch/xdg-autostart-parse
98
99=== modified file 'helpers.c'
100--- helpers.c 2014-02-07 14:56:27 +0000
101+++ helpers.c 2014-02-26 14:46:02 +0000
102@@ -531,6 +531,7 @@
103 gchar * tmpdir = g_strdup_printf("%s/confined/%s", g_get_user_runtime_dir(), package);
104 g_debug("Setting 'TMPDIR' to '%s'", tmpdir);
105 set_upstart_variable("TMPDIR", tmpdir, FALSE);
106+
107 g_debug("Creating '%s'", tmpdir);
108 g_mkdir_with_parents(tmpdir, 0700);
109 g_free(tmpdir);
110
111=== modified file 'helpers.h'
112--- helpers.h 2014-02-03 18:27:58 +0000
113+++ helpers.h 2014-02-26 14:46:02 +0000
114@@ -17,7 +17,7 @@
115 * Ted Gould <ted.gould@canonical.com>
116 */
117
118-#include <glib.h>
119+#include <gio/gio.h>
120
121 gboolean app_id_to_triplet (const gchar * app_id,
122 gchar ** package,
123
124=== added file 'xdg-autostart-find.c'
125--- xdg-autostart-find.c 1970-01-01 00:00:00 +0000
126+++ xdg-autostart-find.c 2014-02-26 14:46:02 +0000
127@@ -0,0 +1,141 @@
128+/*
129+ * Copyright © 2014 Canonical Ltd.
130+ *
131+ * This program is free software: you can redistribute it and/or modify it
132+ * under the terms of the GNU General Public License version 3, as published
133+ * by the Free Software Foundation.
134+ *
135+ * This program is distributed in the hope that it will be useful, but
136+ * WITHOUT ANY WARRANTY; without even the implied warranties of
137+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
138+ * PURPOSE. See the GNU General Public License for more details.
139+ *
140+ * You should have received a copy of the GNU General Public License along
141+ * with this program. If not, see <http://www.gnu.org/licenses/>.
142+ *
143+ * Authors:
144+ * Ted Gould <ted.gould@canonical.com>
145+ */
146+
147+
148+#include <gio/gio.h>
149+
150+GDBusConnection * bus = NULL;
151+
152+/* Emit an event to get Upstart to create a job instance with the XDG
153+ key that we've found */
154+static void
155+emit_start (const gchar * xdg_autostart_instance)
156+{
157+ g_debug("Emiting start for: %s", xdg_autostart_instance);
158+
159+ GVariantBuilder tuple;
160+ g_variant_builder_init(&tuple, G_VARIANT_TYPE_TUPLE);
161+
162+ /* building the "sasb" for Upstart */
163+ g_variant_builder_add_value(&tuple, g_variant_new_string("xdg-autostart-start")); /* event */
164+ g_variant_builder_open(&tuple, G_VARIANT_TYPE_ARRAY); /* environment */
165+ g_variant_builder_add_value(&tuple, g_variant_new_take_string(g_strdup_printf("XDG_AUTOSTART_NAME=%s", xdg_autostart_instance)));
166+ g_variant_builder_close(&tuple);
167+ g_variant_builder_add_value(&tuple, g_variant_new_boolean(FALSE)); /* wait */
168+
169+ /* Call it */
170+ g_dbus_connection_call(bus,
171+ "com.ubuntu.Upstart",
172+ "/com/ubuntu/Upstart",
173+ "com.ubuntu.Upstart0_6",
174+ "EmitEvent",
175+ g_variant_builder_end(&tuple),
176+ NULL, /* reply type */
177+ G_DBUS_CALL_FLAGS_NONE,
178+ -1, /* default timeout */
179+ NULL, /* cancellable */
180+ NULL, NULL); /* callback */
181+}
182+
183+/* Look at a directory, ensure it exists and then start looking for
184+ new autostart keys we can launch */
185+static void
186+check_dir (gpointer pdirname, gpointer pkeyhash)
187+{
188+ const gchar * dirname = (const gchar *)pdirname;
189+ GHashTable * keyhash = (GHashTable *)pkeyhash;
190+
191+ g_debug("Looking at directory: %s", dirname);
192+
193+ if (!g_file_test(dirname, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_DIR)) {
194+ return;
195+ }
196+
197+ GDir * dir = g_dir_open(dirname, 0, NULL);
198+ g_return_if_fail(dir != NULL); /* Shouldn't be NULL considering the check above */
199+
200+ const gchar * filename = NULL;
201+
202+ while ((filename = g_dir_read_name(dir)) != NULL) {
203+ if (!g_str_has_suffix(filename, ".desktop")) {
204+ continue;
205+ }
206+
207+ g_debug("Desktop file: %s", filename);
208+
209+ gchar * mutablename = g_strdup(filename);
210+ gchar * start_desktop = g_strrstr(mutablename, ".desktop");
211+ start_desktop[0] = '\0';
212+
213+ if (g_hash_table_contains(keyhash, mutablename)) {
214+ g_free(mutablename);
215+ continue;
216+ }
217+
218+ g_hash_table_add(keyhash, mutablename);
219+ emit_start(mutablename);
220+ }
221+
222+ g_dir_close(dir);
223+}
224+
225+/* Enumerates all the different autostart directories we can have */
226+static GList *
227+find_autostart_dirs (void)
228+{
229+ GList * retval = NULL;
230+
231+ retval = g_list_prepend(retval, g_build_filename(g_get_user_config_dir(), "autostart", NULL));
232+
233+ const char * const * system_conf_dir = g_get_system_config_dirs();
234+ int i;
235+
236+ for (i = 0; system_conf_dir[i] != NULL; i++) {
237+ retval = g_list_prepend(retval, g_build_filename(system_conf_dir[i], "autostart", NULL));
238+ }
239+
240+ return retval;
241+}
242+
243+int
244+main (int argc, gchar * argv[])
245+{
246+ /* Allocate resources */
247+ GList * autostart_dirs = NULL;
248+ GHashTable * autostart_keys = g_hash_table_new_full(g_str_hash, g_str_equal, g_free, NULL);
249+ bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
250+
251+ /* Make sure we got a bus */
252+ g_return_val_if_fail(bus != NULL, -1);
253+
254+ /* Find all the directories we need */
255+ autostart_dirs = find_autostart_dirs();
256+
257+ /* For each one look at the entries */
258+ g_list_foreach(autostart_dirs, check_dir, autostart_keys);
259+
260+ /* Clean up */
261+ g_hash_table_destroy(autostart_keys);
262+ g_list_free_full(autostart_dirs, g_free);
263+
264+ g_dbus_connection_flush_sync(bus, NULL, NULL);
265+ g_object_unref(bus);
266+
267+ return 0;
268+}
269
270=== added file 'xdg-autostart-find.conf.in'
271--- xdg-autostart-find.conf.in 1970-01-01 00:00:00 +0000
272+++ xdg-autostart-find.conf.in 2014-02-26 14:46:02 +0000
273@@ -0,0 +1,8 @@
274+description "Look through the XDG data directories to find things to autostart"
275+
276+start on desktop-start
277+task
278+
279+emits xdg-autostart-start
280+
281+exec @pkglibexecdir@/xdg-autostart-find
282
283=== added file 'xdg-autostart-parse.c'
284--- xdg-autostart-parse.c 1970-01-01 00:00:00 +0000
285+++ xdg-autostart-parse.c 2014-02-26 14:46:02 +0000
286@@ -0,0 +1,258 @@
287+/*
288+ * Copyright © 2014 Canonical Ltd.
289+ *
290+ * This program is free software: you can redistribute it and/or modify it
291+ * under the terms of the GNU General Public License version 3, as published
292+ * by the Free Software Foundation.
293+ *
294+ * This program is distributed in the hope that it will be useful, but
295+ * WITHOUT ANY WARRANTY; without even the implied warranties of
296+ * MERCHANTABILITY, SATISFACTORY QUALITY, or FITNESS FOR A PARTICULAR
297+ * PURPOSE. See the GNU General Public License for more details.
298+ *
299+ * You should have received a copy of the GNU General Public License along
300+ * with this program. If not, see <http://www.gnu.org/licenses/>.
301+ *
302+ * Authors:
303+ * Ted Gould <ted.gould@canonical.com>
304+ */
305+
306+#include <gio/gio.h>
307+#include "helpers.h"
308+
309+/* Look in a directory for a desktop file of task_name and if
310+ it's there return it. */
311+static GKeyFile *
312+check_dir (const gchar * directory, const gchar * task_name)
313+{
314+ gchar * filename = g_strdup_printf("%s.desktop", task_name);
315+ gchar * pathname = g_build_filename(directory, "autostart", filename, NULL);
316+ g_free(filename);
317+
318+ /* If it doesn't exist, let's just move on */
319+ if (!g_file_test(pathname, G_FILE_TEST_EXISTS)) {
320+ g_free(pathname);
321+ return NULL;
322+ }
323+
324+ GError * error = NULL;
325+ GKeyFile * keyfile = g_key_file_new();
326+ g_key_file_load_from_file(keyfile, pathname, G_KEY_FILE_NONE, &error);
327+ g_free(pathname);
328+
329+ if (error != NULL) {
330+ g_debug("Unable to load keyfile for '%s' in directory '%s'", task_name, directory);
331+ g_key_file_free(keyfile);
332+ g_error_free(error);
333+ return NULL;
334+ }
335+
336+ g_debug("Found keyfile for '%s' in '%s'", task_name, directory);
337+ return keyfile;
338+}
339+
340+/* Check a list of strings for one */
341+static inline gboolean
342+string_in_list (gchar ** list, gsize length, const gchar * test)
343+{
344+ int i;
345+ for (i = 0; i < length; i++) {
346+ if (g_strcmp0(list[i], test) == 0) {
347+ break;
348+ }
349+ }
350+
351+ if (i == length) {
352+ return FALSE;
353+ }
354+
355+ return TRUE;
356+}
357+
358+/* Check the value of a Gsettings key */
359+static gboolean
360+gsettings_condition_check (const gchar * condition)
361+{
362+ gchar ** split = g_strsplit(condition, " ", -1);
363+ g_debug("Finding Gsettings key '%s' in schema '%s'", split[2], split[1]);
364+
365+ GSettingsSchema * schema = g_settings_schema_source_lookup(g_settings_schema_source_get_default(), split[1], FALSE);
366+ if (schema == NULL) {
367+ g_debug("Unable to find schema '%s'", split[1]);
368+ g_strfreev(split);
369+ return FALSE;
370+ }
371+
372+ if (!g_settings_schema_has_key(schema, split[2])) {
373+ g_debug("Schema '%s' doesn't have a key '%s'", split[1], split[2]);
374+ g_object_unref(schema);
375+ g_strfreev(split);
376+ return FALSE;
377+ }
378+
379+ GSettingsSchemaKey * key = g_settings_schema_get_key(schema, split[2]);
380+ if (!g_variant_type_equal(G_VARIANT_TYPE_BOOLEAN, g_settings_schema_key_get_value_type(key))) {
381+ g_debug("Schema '%s' key '%s' isn't a boolean", split[1], split[2]);
382+ g_settings_schema_key_unref(key);
383+ g_object_unref(schema);
384+ g_strfreev(split);
385+ return FALSE;
386+ }
387+
388+ g_settings_schema_key_unref(key);
389+ g_clear_object(&schema);
390+
391+ GSettings * settings = g_settings_new(split[1]);
392+ gboolean retval = g_settings_get_boolean(settings, split[2]);
393+ g_object_unref(settings);
394+
395+ g_strfreev(split);
396+ return retval;
397+}
398+
399+/* Check to see if an autostart keyfile should be run in this context */
400+static gboolean
401+valid_keyfile (GKeyFile * keyfile)
402+{
403+ if (g_key_file_has_key(keyfile, "Desktop Entry", "Hidden", NULL)) {
404+ if (g_key_file_get_boolean(keyfile, "Desktop Entry", "Hidden", NULL)) {
405+ return FALSE;
406+ }
407+ }
408+
409+ const gchar * desktop = g_getenv("XDG_CURRENT_DESKTOP");
410+ if (desktop == NULL) {
411+ return TRUE;
412+ }
413+
414+ if (g_key_file_has_key(keyfile, "Desktop Entry", "OnlyShowIn", NULL)) {
415+ gsize length = 0;
416+ gchar ** list = g_key_file_get_string_list(keyfile, "Desktop Entry", "OnlyShowIn", &length, NULL);
417+
418+ gboolean inlist = string_in_list(list, length, desktop);
419+ g_strfreev(list);
420+
421+ if (!inlist) {
422+ return FALSE;
423+ }
424+ }
425+
426+ if (g_key_file_has_key(keyfile, "Desktop Entry", "NotShowIn", NULL)) {
427+ gsize length = 0;
428+ gchar ** list = g_key_file_get_string_list(keyfile, "Desktop Entry", "NotShowIn", &length, NULL);
429+
430+ gboolean inlist = string_in_list(list, length, desktop);
431+ g_strfreev(list);
432+
433+ if (inlist) {
434+ return FALSE;
435+ }
436+ }
437+
438+ if (g_key_file_has_key(keyfile, "Desktop Entry", "TryExec", NULL)) {
439+ gchar * tryexec = g_key_file_get_string(keyfile, "Desktop Entry", "TryExec", NULL);
440+ gchar * inpath = g_find_program_in_path(tryexec);
441+
442+ /* If we can't find it in the standard path, look for a Path */
443+ if (inpath == NULL) {
444+ gboolean foundinpath = FALSE;
445+
446+ if (g_key_file_has_key(keyfile, "Desktop Entry", "Path", NULL)) {
447+ gchar * desktoppath = g_key_file_get_string(keyfile, "Desktop Entry", "Path", NULL);
448+ gchar * fullpath = g_build_filename(desktoppath, tryexec, NULL);
449+
450+ foundinpath = g_file_test(fullpath, G_FILE_TEST_EXISTS | G_FILE_TEST_IS_EXECUTABLE);
451+
452+ g_free(fullpath);
453+ g_free(desktoppath);
454+ }
455+
456+ if (!foundinpath) {
457+ g_free(tryexec);
458+ return FALSE;
459+ }
460+ } else {
461+ g_free(inpath);
462+ }
463+
464+ g_free(tryexec);
465+ }
466+
467+ if (g_key_file_has_key(keyfile, "Desktop Entry", "AutostartCondition", NULL)) {
468+ gchar * condition = g_key_file_get_string(keyfile, "Desktop Entry", "AutostartCondition", NULL);
469+
470+ if (g_str_has_prefix(condition, "GSettings")) {
471+ if (!gsettings_condition_check(condition)) {
472+ g_free(condition);
473+ return FALSE;
474+ }
475+ }
476+
477+ g_free(condition);
478+ }
479+
480+ return TRUE;
481+}
482+
483+/* See if we can find a keyfile for this task, and if it's valid, then
484+ return it for further processing. */
485+static GKeyFile *
486+find_keyfile (const gchar * task_name)
487+{
488+ GKeyFile * keyfile = NULL;
489+
490+ keyfile = check_dir(g_get_user_config_dir(), task_name);
491+
492+ if (keyfile == NULL) {
493+ const char * const * system_conf_dirs = g_get_system_config_dirs();
494+ int i;
495+
496+ for (i = 0; keyfile == NULL && system_conf_dirs[i] != NULL; i++) {
497+ keyfile = check_dir(system_conf_dirs[i], task_name);
498+ }
499+ }
500+
501+ if (keyfile == NULL) {
502+ g_debug("Couldn't find desktop file for '%s'", task_name);
503+ return NULL;
504+ }
505+
506+ if (valid_keyfile(keyfile)) {
507+ return keyfile;
508+ }
509+
510+ g_key_file_free(keyfile);
511+ return NULL;
512+}
513+
514+int
515+main (int argc, gchar * argv[])
516+{
517+ const gchar * task_name = g_getenv("XDG_AUTOSTART_NAME");
518+ g_return_val_if_fail(task_name != NULL, -1);
519+
520+ GDBusConnection * bus = g_bus_get_sync(G_BUS_TYPE_SESSION, NULL, NULL);
521+ g_return_val_if_fail(bus != NULL, -1);
522+
523+ GKeyFile * keyfile = find_keyfile(task_name);
524+
525+ if (keyfile == NULL) {
526+ return -1;
527+ }
528+
529+ gchar * execline = g_key_file_get_string(keyfile, "Desktop Entry", "Exec", NULL);
530+ g_debug("Exec Key is: %s", execline);
531+ g_return_val_if_fail(execline != NULL, -1);
532+
533+ GMainLoop * loop = g_main_loop_new(NULL, FALSE);
534+ set_upstart_variable("APP_EXEC", execline, TRUE);
535+ g_free(execline);
536+
537+ g_main_loop_run(loop);
538+ g_main_loop_unref(loop);
539+
540+ g_dbus_connection_flush_sync(bus, NULL, NULL);
541+ g_object_unref(bus);
542+
543+ return 0;
544+}
545
546=== added file 'xdg-autostart.conf.in'
547--- xdg-autostart.conf.in 1970-01-01 00:00:00 +0000
548+++ xdg-autostart.conf.in 2014-02-26 14:46:02 +0000
549@@ -0,0 +1,15 @@
550+description "A process defined by an XDG Autostart file"
551+
552+start on xdg-autostart-start
553+stop on desktop-end
554+
555+instance $XDG_AUTOSTART_NAME
556+
557+env APP_EXEC="echo Error"
558+export APP_EXEC
559+
560+pre-start exec @pkglibexecdir@/xdg-autostart-parse
561+script
562+ echo $XDG_AUTOSTART_NAME
563+# @pkglibexecdir@/exec-line-exec
564+end script

Subscribers

People subscribed via source and target branches