Updated licence to GPL v3.
[XDGStart.git] / src / xdgautostart.c
blob65556e2940b4c48131c54b27b038221f06decc8a
1 /*
2 * By Tony Houghton, <h@realh.co.uk>.
3 */
5 #include "config.h"
7 #include <stdlib.h>
8 #include <string.h>
10 #include "xdgautostart.h"
12 #ifndef _DE
13 #define _DE "Desktop Entry"
14 #endif
16 static const char *locale_name = NULL;
17 static const char *short_locale_name = NULL;
19 static void desktop_entry_free_keyfile_mirrors(DesktopEntry *de)
21 g_free(de->name);
22 de->name = NULL;
23 g_free(de->exec);
24 de->exec = NULL;
25 g_free(de->path);
26 de->path = NULL;
27 g_free(de->try_exec);
28 de->try_exec = NULL;
29 g_strfreev(de->only_show_in);
30 de->only_show_in = NULL;
31 g_strfreev(de->not_show_in);
32 de->not_show_in = NULL;
35 static void desktop_entry_read_name_from_keyfile(DesktopEntry *xde)
37 g_free(xde->name);
38 if (locale_name)
40 xde->name = g_key_file_get_locale_string(xde->kf, _DE, "Name",
41 locale_name, NULL);
43 if (!xde->name && short_locale_name)
45 xde->name = g_key_file_get_locale_string(xde->kf, _DE, "Name",
46 short_locale_name, NULL);
48 if (!xde->name)
49 xde->name = g_key_file_get_string(xde->kf, _DE, "Name", NULL);
50 if (!xde->name)
51 xde->name = g_strdup(_("No name"));
54 void desktop_entry_read_keyfile(DesktopEntry *de)
56 GKeyFile *kf = de->kf;
58 desktop_entry_free_keyfile_mirrors(de);
59 desktop_entry_read_name_from_keyfile(de);
60 de->exec = g_key_file_get_string(kf, _DE, "Exec", NULL);
61 de->path = g_key_file_get_string(kf, _DE, "Path", NULL);
62 de->terminal = g_key_file_get_boolean(kf, _DE, "Terminal", NULL);
63 de->try_exec = g_key_file_get_string(kf, _DE, "TryExec", NULL);
64 de->only_show_in = g_key_file_get_string_list(kf, _DE, "OnlyShowIn",
65 NULL, NULL);
66 de->not_show_in = g_key_file_get_string_list(kf, _DE, "NotShowIn",
67 NULL, NULL);
70 gboolean desktop_entry_load(DesktopEntry *de, const char *pathname,
71 const char *basename, gboolean keep_keyfile, gboolean savable)
73 GKeyFile *kf = g_key_file_new();
74 GError *err = NULL;
76 de->kf = kf;
77 if (!g_key_file_load_from_file(kf, pathname,
78 keep_keyfile ?
79 G_KEY_FILE_KEEP_COMMENTS | G_KEY_FILE_KEEP_TRANSLATIONS :
80 G_KEY_FILE_NONE,
81 &err))
83 g_warning(_("Can't load key-file '%s': %s"), pathname,
84 err ? err->message : _("unknown reason"));
85 g_error_free(err);
86 return FALSE;
88 if (!g_key_file_has_group(kf, _DE))
90 g_warning(_("'%s' is not a .desktop file"), pathname);
91 return FALSE;
94 de->pathname = g_strdup(pathname);
95 de->basename = g_strdup(basename);
96 de->savable = savable;
97 de->deletable = savable;
99 desktop_entry_read_keyfile(de);
101 if (!keep_keyfile)
103 g_key_file_free(kf);
104 de->kf = NULL;
106 return TRUE;
109 void desktop_entry_free(DesktopEntry *de)
111 desktop_entry_free_keyfile_mirrors(de);
112 g_free(de->pathname);
113 de->pathname = NULL;
114 g_free(de->basename);
115 de->basename = NULL;
116 if (de->kf)
118 g_key_file_free(de->kf);
119 de->kf = NULL;
123 void desktop_entry_delete(DesktopEntry *de)
125 desktop_entry_free(de);
126 g_free(de);
129 DesktopEntry *desktop_entry_new(const char *pathname, const char *basename,
130 gboolean savable)
132 DesktopEntry *de = g_new0(DesktopEntry, 1);
134 if (!desktop_entry_load(de, pathname, basename, FALSE, savable))
136 desktop_entry_delete(de);
137 de = NULL;
139 return de;
142 gboolean desktop_entry_str_in_strv(char **v, const char *s)
144 for ( ; v && *v; ++v)
146 if (!strcmp(*v, s))
147 return TRUE;
149 return FALSE;
152 gboolean desktop_entry_get_show_in_environ(const DesktopEntry *de,
153 const char *environ)
155 if (de->only_show_in)
157 return desktop_entry_str_in_strv(de->only_show_in, environ);
159 if (de->not_show_in)
161 if (desktop_entry_str_in_strv(de->not_show_in, environ))
162 return FALSE;
164 return TRUE;
167 /* Also checks Exec and TryExec */
168 gboolean desktop_entry_can_start_in_rox(const DesktopEntry *de)
170 if (!desktop_entry_get_show_in_rox(de))
172 return FALSE;
174 if (!de->exec)
176 return FALSE;
178 if (de->try_exec)
180 if (!g_file_test(de->try_exec, G_FILE_TEST_EXISTS))
181 return FALSE;
183 if (de->exec[0] == '/')
185 return g_file_test(de->exec, G_FILE_TEST_IS_EXECUTABLE);
187 else
189 char *exec = g_strdup(de->exec);
190 char *spc = strchr(exec, ' ');
191 char *ef;
192 gboolean result;
194 if (spc)
195 *spc = 0;
196 spc = strchr(exec, '\t');
197 if (spc)
198 *spc = 0;
199 ef = g_find_program_in_path(exec);
200 result = ef != NULL;
202 g_free(exec);
203 g_free(ef);
204 return result;
206 return FALSE;
209 static GList *scan_dir(const char *dir, GList *desl,
210 DesktopEntryConstructor ctor, gboolean savable)
212 char *dir2 = g_build_filename(dir, "autostart", NULL);
213 GDir *dir0;
214 const char *basename;
216 if (!g_file_test(dir2, G_FILE_TEST_IS_DIR))
217 goto no_dir;
218 dir0 = g_dir_open(dir2, 0, NULL);
219 if (!dir0)
220 goto no_dir;
221 while ((basename = g_dir_read_name(dir0)) != NULL)
223 GList *node;
224 gboolean dupl = FALSE;
226 /* Don't add if there's already one with the same basename */
227 for (node = desl; node; node = g_list_next(node))
229 DesktopEntry *de = node->data;
231 if (!strcmp(basename, de->basename))
233 dupl = TRUE;
234 break;
237 if (!dupl)
239 char *pathname = g_build_filename(dir2, basename, NULL);
240 DesktopEntry *de = ctor(pathname, basename, savable);
242 if (de)
243 desl = g_list_append(desl, de);
244 g_free(pathname);
248 g_dir_close(dir0);
249 no_dir:
250 g_free(dir2);
251 return desl;
254 GList *get_desktop_entries(DesktopEntryConstructor ctor)
256 GList *desl = NULL;
257 const char *udir = g_get_user_config_dir();
258 const char * const * sdirs;
260 desl = scan_dir(udir, desl, ctor, TRUE);
261 for (sdirs = g_get_system_config_dirs(); sdirs && *sdirs; ++sdirs)
263 desl = scan_dir(*sdirs, desl, ctor, FALSE);
265 return desl;
268 gboolean str_v_is_empty(char **sv)
270 if (!sv)
271 return TRUE;
272 for ( ; *sv; ++sv)
274 if (*sv)
275 return FALSE;
277 return TRUE;
280 void desktop_entry_set_locale_names(const char *full_name,
281 const char *short_name)
283 locale_name = full_name;
284 short_locale_name = short_name;
287 void desktop_entry_init_locales(char const **long_name, char const **short_name)
289 char *lang = getenv("LANG");
291 if (lang)
293 char *sep = strchr(lang, '.');
294 int l = sep ? sep - lang : strlen(lang);
296 locale_name = g_strdup_printf("%.*s", l, lang);
297 sep = strchr(locale_name, '_');
298 if (sep)
300 short_locale_name = g_strdup_printf("%.*s",
301 (int) (sep - locale_name), locale_name);
304 else
306 locale_name = NULL;
308 if (long_name)
309 *long_name = locale_name;
310 if (short_name)
311 *short_name = short_locale_name;