efreet: Improve language reset
[framework/uifw/efreet.git] / src / lib / efreet.c
1 #ifdef HAVE_CONFIG_H
2 # include <config.h>
3 #endif
4
5 #undef alloca
6 #ifdef HAVE_ALLOCA_H
7 # include <alloca.h>
8 #elif defined __GNUC__
9 # define alloca __builtin_alloca
10 #elif defined _AIX
11 # define alloca __alloca
12 #elif defined _MSC_VER
13 # include <malloc.h>
14 # define alloca _alloca
15 #else
16 # include <stddef.h>
17 # ifdef  __cplusplus
18 extern "C"
19 # endif
20 void *alloca (size_t);
21 #endif
22
23 #include <unistd.h>
24 #include <sys/stat.h>
25 #include <fcntl.h>
26
27 #include <Eet.h>
28 #include <Ecore.h>
29 #include <Ecore_File.h>
30
31 /* define macros and variable for using the eina logging system  */
32 #define EFREET_MODULE_LOG_DOM /* no logging in this file */
33
34 #include "Efreet.h"
35 #include "efreet_private.h"
36 #include "efreet_xml.h"
37
38 /*
39  * Needs EAPI because of helper binaries
40  */
41 EAPI int efreet_cache_update = 1;
42
43 static int _efreet_init_count = 0;
44 static int efreet_parsed_locale = 0;
45 static const char *efreet_lang = NULL;
46 static const char *efreet_lang_country = NULL;
47 static const char *efreet_lang_modifier = NULL;
48 static void efreet_parse_locale(void);
49 static int efreet_parse_locale_setting(const char *env);
50
51 static uid_t ruid;
52 static uid_t rgid;
53
54 EAPI int
55 efreet_init(void)
56 {
57     char *tmp;
58
59     if (++_efreet_init_count != 1)
60         return _efreet_init_count;
61
62     /* Find users real uid and gid */
63     tmp = getenv("SUDO_UID");
64     if (tmp)
65         ruid = strtoul(tmp, NULL, 10);
66     else
67         ruid = getuid();
68
69     tmp = getenv("SUDO_GID");
70     if (tmp)
71         rgid = strtoul(tmp, NULL, 10);
72     else
73         rgid = getgid();
74
75     if (!eina_init())
76         return --_efreet_init_count;
77     if (!eet_init())
78         goto shutdown_eina;
79     if (!ecore_init())
80         goto shutdown_eet;
81     if (!ecore_file_init())
82         goto shutdown_ecore;
83
84     if (!efreet_base_init())
85         goto shutdown_ecore_file;
86
87     if (!efreet_cache_init())
88         goto shutdown_efreet_base;
89
90     if (!efreet_xml_init())
91         goto shutdown_efreet_cache;
92
93     if (!efreet_icon_init())
94         goto shutdown_efreet_xml;
95
96     if (!efreet_ini_init())
97         goto shutdown_efreet_icon;
98
99     if (!efreet_desktop_init())
100         goto shutdown_efreet_ini;
101
102     if (!efreet_menu_init())
103         goto shutdown_efreet_desktop;
104
105     if (!efreet_util_init())
106         goto shutdown_efreet_menu;
107
108     return _efreet_init_count;
109
110 shutdown_efreet_menu:
111     efreet_menu_shutdown();
112 shutdown_efreet_desktop:
113     efreet_desktop_shutdown();
114 shutdown_efreet_ini:
115     efreet_ini_shutdown();
116 shutdown_efreet_icon:
117     efreet_icon_shutdown();
118 shutdown_efreet_xml:
119     efreet_xml_shutdown();
120 shutdown_efreet_cache:
121     efreet_cache_shutdown();
122 shutdown_efreet_base:
123     efreet_base_shutdown();
124 shutdown_ecore_file:
125     ecore_file_shutdown();
126 shutdown_ecore:
127     ecore_shutdown();
128 shutdown_eet:
129     eet_shutdown();
130 shutdown_eina:
131     eina_shutdown();
132
133     return --_efreet_init_count;
134 }
135
136 EAPI int
137 efreet_shutdown(void)
138 {
139     if (_efreet_init_count <= 0)
140       {
141          EINA_LOG_ERR("Init count not greater than 0 in shutdown.");
142          return 0;
143       }
144     if (--_efreet_init_count != 0)
145         return _efreet_init_count;
146
147     efreet_util_shutdown();
148     efreet_menu_shutdown();
149     efreet_desktop_shutdown();
150     efreet_ini_shutdown();
151     efreet_icon_shutdown();
152     efreet_xml_shutdown();
153     efreet_cache_shutdown();
154     efreet_base_shutdown();
155
156     IF_RELEASE(efreet_lang);
157     IF_RELEASE(efreet_lang_country);
158     IF_RELEASE(efreet_lang_modifier);
159     efreet_parsed_locale = 0;  /* reset this in case they init efreet again */
160
161     ecore_file_shutdown();
162     ecore_shutdown();
163     eet_shutdown();
164     eina_shutdown();
165
166     return _efreet_init_count;
167 }
168
169 EAPI void
170 efreet_lang_reset(void)
171 {
172     IF_RELEASE(efreet_lang);
173     IF_RELEASE(efreet_lang_country);
174     IF_RELEASE(efreet_lang_modifier);
175     efreet_parsed_locale = 0;  /* reset this in case they init efreet again */
176
177     efreet_dirs_reset();
178     efreet_cache_desktop_reset();
179 }
180
181  /**
182  * @internal
183  * @return Returns the current users language setting or NULL if none set
184  * @brief Retrieves the current language setting
185  */
186 const char *
187 efreet_lang_get(void)
188 {
189     if (efreet_parsed_locale) return efreet_lang;
190
191     efreet_parse_locale();
192     return efreet_lang;
193 }
194
195 /**
196  * @internal
197  * @return Returns the current language country setting or NULL if none set
198  * @brief Retrieves the current country setting for the current language or
199  */
200 const char *
201 efreet_lang_country_get(void)
202 {
203     if (efreet_parsed_locale) return efreet_lang_country;
204
205     efreet_parse_locale();
206     return efreet_lang_country;
207 }
208
209 /**
210  * @internal
211  * @return Returns the current language modifier setting or NULL if none
212  * set.
213  * @brief Retrieves the modifier setting for the language.
214  */
215 const char *
216 efreet_lang_modifier_get(void)
217 {
218     if (efreet_parsed_locale) return efreet_lang_modifier;
219
220     efreet_parse_locale();
221     return efreet_lang_modifier;
222 }
223
224 /**
225  * @internal
226  * @return Returns no value
227  * @brief Parses out the language, country and modifer setting from the
228  * LC_MESSAGES environment variable
229  */
230 static void
231 efreet_parse_locale(void)
232 {
233     efreet_parsed_locale = 1;
234
235     if (efreet_parse_locale_setting("LANG"))
236         return;
237
238     if (efreet_parse_locale_setting("LC_ALL"))
239         return;
240
241     efreet_parse_locale_setting("LC_MESSAGES");
242 }
243
244 /**
245  * @internal
246  * @param env The environment variable to grab
247  * @return Returns 1 if we parsed something of @a env, 0 otherwise
248  * @brief Tries to parse the lang settings out of the given environment
249  * variable
250  */
251 static int
252 efreet_parse_locale_setting(const char *env)
253 {
254     int found = 0;
255     char *setting;
256     char *p;
257     size_t len;
258
259     p = getenv(env);
260     if (!p) return 0;
261     len = strlen(p) + 1;
262     setting = alloca(len);
263     memcpy(setting, p, len);
264
265     /* pull the modifier off the end */
266     p = strrchr(setting, '@');
267     if (p)
268     {
269         *p = '\0';
270         efreet_lang_modifier = eina_stringshare_add(p + 1);
271         found = 1;
272     }
273
274     /* if there is an encoding we ignore it */
275     p = strrchr(setting, '.');
276     if (p) *p = '\0';
277
278     /* get the country if available */
279     p = strrchr(setting, '_');
280     if (p)
281     {
282         *p = '\0';
283         efreet_lang_country = eina_stringshare_add(p + 1);
284         found = 1;
285     }
286
287     if (*setting != '\0')
288     {
289         efreet_lang = eina_stringshare_add(setting);
290         found = 1;
291     }
292
293     return found;
294 }
295
296 /**
297  * @internal
298  * @param buffer The destination buffer
299  * @param size The destination buffer size
300  * @param strs The strings to concatenate together
301  * @return Returns the size of the string in @a buffer
302  * @brief Concatenates the strings in @a strs into the given @a buffer not
303  * exceeding the given @a size.
304  */
305 size_t
306 efreet_array_cat(char *buffer, size_t size, const char *strs[])
307 {
308     int i;
309     size_t n;
310     for (i = 0, n = 0; n < size && strs[i]; i++)
311     {
312         n += eina_strlcpy(buffer + n, strs[i], size - n);
313     }
314     return n;
315 }
316
317 EAPI void
318 efreet_fsetowner(int fd)
319 {
320     struct stat st;
321
322     if (fd < 0) return;
323     if (fstat(fd, &st) < 0) return;
324     if (st.st_uid == ruid) return;
325
326     if (fchown(fd, ruid, rgid) != 0) return;
327 }
328
329 EAPI void
330 efreet_setowner(const char *path)
331 {
332     EINA_SAFETY_ON_NULL_RETURN(path);
333
334     int fd;
335
336     fd = open(path, O_RDONLY);
337     if (fd < 0) return;
338     efreet_fsetowner(fd);
339     close(fd);
340 }