Initial check-in to git.
[XDGStart.git] / src / xdgautostart.c
blobc5a5a9de5c616af586770ccecdf134bd66863e3f
1 /*
2 * By Tony Houghton, <h@realh.co.uk>.
3 */
5 #include "config.h"
7 #include <string.h>
9 #include "xdgautostart.h"
11 static void desktop_entry_free_keyfile_mirrors(DesktopEntry *de)
13 g_free(de->name);
14 de->name = NULL;
15 g_free(de->exec);
16 de->exec = NULL;
17 g_free(de->path);
18 de->path = NULL;
19 g_free(de->try_exec);
20 de->try_exec = NULL;
21 g_strfreev(de->only_show_in);
22 de->only_show_in = NULL;
23 g_strfreev(de->not_show_in);
24 de->not_show_in = NULL;
27 void desktop_entry_read_keyfile(DesktopEntry *de)
29 GKeyFile *kf = de->kf;
31 desktop_entry_free_keyfile_mirrors(de);
32 de->exec = g_key_file_get_string(kf, _DE, "Exec", NULL);
33 de->path = g_key_file_get_string(kf, _DE, "Path", NULL);
34 de->terminal = g_key_file_get_boolean(kf, _DE, "Terminal", NULL);
35 de->try_exec = g_key_file_get_string(kf, _DE, "TryExec", NULL);
36 de->only_show_in = g_key_file_get_string_list(kf, _DE, "OnlyShowIn",
37 NULL, NULL);
38 de->not_show_in = g_key_file_get_string_list(kf, _DE, "NotShowIn",
39 NULL, NULL);
42 gboolean desktop_entry_load(DesktopEntry *de, const char *pathname,
43 const char *basename, gboolean keep_keyfile, gboolean savable)
45 GKeyFile *kf = g_key_file_new();
46 GError *err = NULL;
48 de->kf = kf;
49 if (!g_key_file_load_from_file(kf, pathname,
50 keep_keyfile ?
51 G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS :
52 G_KEY_FILE_NONE,
53 &err))
55 g_warning(_("Can't load key-file '%s': %s"), pathname,
56 err ? err->message : _("unknown reason"));
57 g_error_free(err);
58 return FALSE;
60 if (!g_key_file_has_group(kf, _DE))
62 g_warning(_("'%s' is not a .desktop file"), pathname);
63 return FALSE;
66 de->pathname = g_strdup(pathname);
67 de->basename = g_strdup(basename);
68 de->savable = savable;
69 de->deletable = savable;
71 desktop_entry_read_keyfile(de);
73 if (!keep_keyfile)
75 g_key_file_free(kf);
76 de->kf = NULL;
78 return TRUE;
81 void desktop_entry_free(DesktopEntry *de)
83 desktop_entry_free_keyfile_mirrors(de);
84 g_free(de->pathname);
85 de->pathname = NULL;
86 g_free(de->basename);
87 de->basename = NULL;
88 if (de->kf)
90 g_key_file_free(de->kf);
91 de->kf = NULL;
95 void desktop_entry_delete(DesktopEntry *de)
97 desktop_entry_free(de);
98 g_free(de);
101 DesktopEntry *desktop_entry_new(const char *pathname, const char *basename,
102 gboolean savable)
104 DesktopEntry *de = g_new0(DesktopEntry, 1);
106 if (!desktop_entry_load(de, pathname, basename, FALSE, savable))
108 desktop_entry_delete(de);
109 de = NULL;
111 return de;
114 gboolean desktop_entry_str_in_strv(char **v, const char *s)
116 for ( ; v && *v; ++v)
118 if (!strcmp(*v, s))
119 return TRUE;
121 return FALSE;
124 gboolean desktop_entry_get_show_in_environ(const DesktopEntry *de,
125 const char *environ)
127 if (de->only_show_in)
129 if (desktop_entry_str_in_strv(de->only_show_in, environ))
130 return TRUE;
132 if (de->not_show_in)
134 if (desktop_entry_str_in_strv(de->not_show_in, environ))
135 return FALSE;
137 return TRUE;
140 /* Also checks Exec and TryExec */
141 gboolean desktop_entry_can_start_in_rox(const DesktopEntry *de)
143 if (!desktop_entry_get_show_in_rox(de))
144 return FALSE;
145 if (!de->exec)
146 return FALSE;
147 if (de->try_exec)
149 if (!g_file_test(de->try_exec, G_FILE_TEST_EXISTS))
150 return FALSE;
152 if (de->exec[0] == '/')
154 return g_file_test(de->exec, G_FILE_TEST_IS_EXECUTABLE);
156 else
158 char *ef = g_find_program_in_path(de->exec);
159 gboolean result = ef != NULL;
161 g_free(ef);
162 return result;
164 return FALSE;
167 static GList *scan_dir(const char *dir, GList *desl,
168 DesktopEntryConstructor ctor, gboolean savable)
170 char *dir2 = g_build_filename(dir, "autostart", NULL);
171 GDir *dir0;
172 const char *basename;
174 if (!g_file_test(dir2, G_FILE_TEST_IS_DIR))
175 goto no_dir;
176 dir0 = g_dir_open(dir2, 0, NULL);
177 if (!dir0)
178 goto no_dir;
179 while ((basename = g_dir_read_name(dir0)) != NULL)
181 GList *node;
182 gboolean dupl = FALSE;
184 /* Don't add if there's already one with the same basename */
185 for (node = desl; node; node = g_list_next(node))
187 DesktopEntry *de = node->data;
189 if (!strcmp(basename, de->basename))
191 dupl = TRUE;
192 break;
195 if (!dupl)
197 char *pathname = g_build_filename(dir2, basename, NULL);
198 DesktopEntry *de = ctor(pathname, basename, savable);
200 if (de)
201 desl = g_list_append(desl, de);
202 g_free(pathname);
206 g_dir_close(dir0);
207 no_dir:
208 g_free(dir2);
209 return desl;
212 GList *get_desktop_entries(DesktopEntryConstructor ctor)
214 GList *desl = NULL;
215 const char *udir = g_get_user_config_dir();
216 const char * const * sdirs;
218 desl = scan_dir(udir, desl, ctor, TRUE);
219 for (sdirs = g_get_system_config_dirs(); sdirs && *sdirs; ++sdirs)
221 desl = scan_dir(*sdirs, desl, ctor, FALSE);
223 return desl;
226 gboolean str_v_is_empty(char **sv)
228 if (!sv)
229 return TRUE;
230 for ( ; *sv; ++sv)
232 if (*sv)
233 return FALSE;
235 return TRUE;