e_main: fix secure coding getenv
[platform/upstream/enlightenment.git] / src / bin / e_main.c
1 #include "e.h"
2 #ifdef __linux__
3 # include <sys/prctl.h>
4 #endif
5
6 #define MAX_LEVEL 80
7
8 #define TS_DO
9 #ifdef TS_DO
10 # define TS(x)                                                    \
11   {                                                               \
12      t1 = ecore_time_unix_get();                                  \
13      printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, x); \
14      t2 = t1;                                                     \
15   }
16 static double t0, t1, t2;
17 #else
18 # define TS(x)
19 #endif
20
21 /*
22  * i need to make more use of these when i'm baffled as to when something is
23  * up. other hooks:
24  *
25  *      void *(*__malloc_hook)(size_t size, const void *caller);
26  *
27  *      void *(*__realloc_hook)(void *ptr, size_t size, const void *caller);
28  *
29  *      void *(*__memalign_hook)(size_t alignment, size_t size,
30  *                               const void *caller);
31  *
32  *      void (*__free_hook)(void *ptr, const void *caller);
33  *
34  *      void (*__malloc_initialize_hook)(void);
35  *
36  *      void (*__after_morecore_hook)(void);
37  *
38
39    static void my_init_hook(void);
40    static void my_free_hook(void *p, const void *caller);
41
42    static void (*old_free_hook)(void *ptr, const void *caller) = NULL;
43    void (*__free_hook)(void *ptr, const void *caller);
44
45    void (*__malloc_initialize_hook) (void) = my_init_hook;
46    static void
47    my_init_hook(void)
48    {
49    old_free_hook = __free_hook;
50    __free_hook = my_free_hook;
51    }
52
53    //void *magicfree = NULL;
54
55    static void
56    my_free_hook(void *p, const void *caller)
57    {
58    __free_hook = old_free_hook;
59    //   if ((p) && (p == magicfree))
60    //     {
61    //   printf("CAUGHT!!!!! %p ...\n", p);
62    //   abort();
63    //     }
64    free(p);
65    __free_hook = my_free_hook;
66    }
67  */
68
69 /* local function prototypes */
70 static void      _e_main_shutdown(int errcode);
71 static void      _e_main_shutdown_push(int (*func)(void));
72 static void      _e_main_parse_arguments(int argc, char **argv);
73 static Eina_Bool _e_main_cb_signal_exit(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__);
74 static Eina_Bool _e_main_cb_signal_hup(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__);
75 static Eina_Bool _e_main_cb_signal_user(void *data __UNUSED__, int ev_type __UNUSED__, void *ev);
76 static int       _e_main_dirs_init(void);
77 static int       _e_main_dirs_shutdown(void);
78 static int       _e_main_path_init(void);
79 static int       _e_main_path_shutdown(void);
80 static void      _e_main_test_formats(void);
81 static int       _e_main_screens_init(void);
82 static int       _e_main_screens_shutdown(void);
83 static void      _e_main_desk_save(void);
84 static void      _e_main_desk_restore(void);
85 static void      _e_main_efreet_paths_init(void);
86 static void      _e_main_modules_load(Eina_Bool safe_mode);
87 static Eina_Bool _e_main_cb_x_flusher(void *data __UNUSED__);
88 static Eina_Bool _e_main_cb_idle_before(void *data __UNUSED__);
89 static Eina_Bool _e_main_cb_idle_after(void *data __UNUSED__);
90 static Eina_Bool _e_main_cb_startup_fake_end(void *data __UNUSED__);
91
92 /* local variables */
93 static Eina_Bool really_know = EINA_FALSE;
94 static Eina_Bool locked = EINA_FALSE;
95 static Eina_Bool inloop = EINA_FALSE;
96 static jmp_buf x_fatal_buff;
97
98 static int _e_main_lvl = 0;
99 static int(*_e_main_shutdown_func[MAX_LEVEL]) (void);
100
101 static Ecore_Idle_Enterer *_idle_before = NULL;
102 static Ecore_Idle_Enterer *_idle_after = NULL;
103 static Ecore_Idle_Enterer *_idle_flush = NULL;
104
105 static Ecore_Event_Handler *mod_init_end = NULL;
106
107 /* external variables */
108 EAPI Eina_Bool e_precache_end = EINA_FALSE;
109 EAPI Eina_Bool x_fatal = EINA_FALSE;
110 EAPI Eina_Bool good = EINA_FALSE;
111 EAPI Eina_Bool evil = EINA_FALSE;
112 EAPI Eina_Bool starting = EINA_TRUE;
113 EAPI Eina_Bool stopping = EINA_FALSE;
114 EAPI Eina_Bool restart = EINA_FALSE;
115 EAPI Eina_Bool e_nopause = EINA_FALSE;
116 EINTERN const char *e_first_frame = NULL;
117 EINTERN double e_first_frame_start_time = -1;
118
119 static Eina_Bool
120 _xdg_check_str(const char *env, const char *str)
121 {
122    const char *p;
123    size_t len;
124
125    len = strlen(str);
126    for (p = strstr(env, str); p; p++, p = strstr(p, str))
127      {
128         if ((!p[len]) || (p[len] == ':')) return EINA_TRUE;
129      }
130    return EINA_FALSE;
131 }
132
133 static void
134 _xdg_data_dirs_augment(void)
135 {
136    const char *s;
137    const char *p = e_prefix_get();
138    char newpath[4096], buf[4096];
139
140    if (!p) return;
141
142    s = getenv("XDG_DATA_DIRS");
143    if (s)
144      {
145         Eina_Bool pfxdata, pfx;
146
147         pfxdata = !_xdg_check_str(s, e_prefix_data_get());
148         snprintf(newpath, sizeof(newpath), "%s/share", p);
149         pfx = !_xdg_check_str(s, newpath);
150         if (pfxdata || pfx)
151           {
152              snprintf(buf, sizeof(buf), "%s%s%s%s%s",
153                pfxdata ? e_prefix_data_get() : "",
154                pfxdata ? ":" : "",
155                pfx ? newpath : "",
156                pfx ? ":" : "",
157                s);
158              e_util_env_set("XDG_DATA_DIRS", buf);
159           }
160      }
161    else
162      {
163         snprintf(buf, sizeof(buf), "%s:%s/share:/usr/local/share:/usr/share", e_prefix_data_get(), p);
164         e_util_env_set("XDG_DATA_DIRS", buf);
165      }
166
167    s = getenv("XDG_CONFIG_DIRS");
168    snprintf(newpath, sizeof(newpath), "%s/etc/xdg", p);
169    if (s)
170      {
171         if (!_xdg_check_str(s, newpath))
172           {
173              snprintf(buf, sizeof(buf), "%s:%s", newpath, s);
174              e_util_env_set("XDG_CONFIG_DIRS", buf);
175           }
176      }
177    else
178      {
179         snprintf(buf, sizeof(buf), "%s:/etc/xdg", newpath);
180         e_util_env_set("XDG_CONFIG_DIRS", buf);
181      }
182
183    if (!getenv("XDG_RUNTIME_DIR"))
184      {
185         const char *dir;
186
187         snprintf(buf, sizeof(buf), "/tmp/xdg-XXXXXX");
188         dir = mkdtemp(buf);
189         if (!dir) dir = "/tmp";
190         else
191           {
192              e_util_env_set("XDG_RUNTIME_DIR", dir);
193              snprintf(buf, sizeof(buf), "%s/.e-deleteme", dir);
194              ecore_file_mkdir(buf);
195           }
196      }
197
198    /* set menu prefix so we get our e menu */
199    if (!getenv("XDG_MENU_PREFIX"))
200      {
201         e_util_env_set("XDG_MENU_PREFIX", "e-");
202      }
203 }
204
205 static Eina_Bool
206 _e_main_shelf_init_job(void *data EINA_UNUSED)
207 {
208    e_shelf_config_update();
209    return ECORE_CALLBACK_CANCEL;
210 }
211
212 /* externally accessible functions */
213 int
214 main(int argc, char **argv)
215 {
216    Eina_Bool nostartup = EINA_FALSE;
217    Eina_Bool safe_mode = EINA_FALSE;
218    Eina_Bool after_restart = EINA_FALSE;
219    Eina_Bool waslocked = EINA_FALSE;
220    double t = 0.0, tstart = 0.0;
221    char *s = NULL, buff[32];
222    struct sigaction action;
223
224 #ifdef __linux__
225 # ifdef PR_SET_PTRACER
226 #  ifdef PR_SET_PTRACER_ANY
227    prctl(PR_SET_PTRACER, PR_SET_PTRACER_ANY);
228 #  endif
229 # endif
230 #endif
231    
232 #ifdef TS_DO
233    t0 = t1 = t2 = ecore_time_unix_get();
234 #endif
235    TS("Begin Startup");
236
237    /* trap deadly bug signals and allow some form of sane recovery */
238    /* or ability to gdb attach and debug at this point - better than your */
239    /* wm/desktop vanishing and not knowing what happened */
240    if (!getenv("NOTIFY_SOCKET"))
241      {
242         TS("Signal Trap");
243         action.sa_sigaction = e_sigseg_act;
244         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
245         sigemptyset(&action.sa_mask);
246         sigaction(SIGSEGV, &action, NULL);
247
248         action.sa_sigaction = e_sigill_act;
249         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
250         sigemptyset(&action.sa_mask);
251         sigaction(SIGILL, &action, NULL);
252
253         action.sa_sigaction = e_sigfpe_act;
254         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
255         sigemptyset(&action.sa_mask);
256         sigaction(SIGFPE, &action, NULL);
257
258 #ifndef HAVE_WAYLAND_ONLY
259         action.sa_sigaction = e_sigbus_act;
260         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
261         sigemptyset(&action.sa_mask);
262         sigaction(SIGBUS, &action, NULL);
263 #endif
264
265         action.sa_sigaction = e_sigabrt_act;
266         action.sa_flags = SA_NODEFER | SA_RESETHAND | SA_SIGINFO;
267         sigemptyset(&action.sa_mask);
268         sigaction(SIGABRT, &action, NULL);
269         TS("Signal Trap Done");
270      }
271
272    t = ecore_time_unix_get();
273    s = getenv("E_START_TIME");
274    if ((s) && (!getenv("E_RESTART_OK")))
275      {
276         tstart = atof(s);
277         if ((t - tstart) < 5.0) safe_mode = EINA_TRUE;
278      }
279    tstart = t;
280    snprintf(buff, sizeof(buff), "%1.1f", tstart);
281    e_util_env_set("E_START_TIME", buff);
282
283    if (getenv("E_START_MTRACK"))
284      e_util_env_set("MTRACK", NULL);
285    TS("Eina Init");
286    if (!eina_init())
287      {
288         e_error_message_show(_("Enlightenment cannot initialize Eina!\n"));
289         _e_main_shutdown(-1);
290      }
291    _e_main_shutdown_push(eina_shutdown);
292 #ifdef OBJECT_HASH_CHECK
293    e_object_hash_init();
294 #endif
295    if (!e_log_init())
296      {
297         e_error_message_show(_("Enlightenment could not create a logging domain!\n"));
298         _e_main_shutdown(-1);
299      }
300 #ifdef TS_DO
301 #undef TS
302 # define TS(x)                                                    \
303   {                                                               \
304      t1 = ecore_time_unix_get();                                  \
305      printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, x); \
306      t2 = t1;                                                     \
307   }
308 #endif
309    TS("Eina Init Done");
310    _e_main_shutdown_push(e_log_shutdown);
311
312    TS("Determine Prefix");
313    if (!e_prefix_determine(argv[0]))
314      {
315         fprintf(stderr,
316                 "ERROR: Enlightenment cannot determine it's installed\n"
317                 "       prefix from the system or argv[0].\n"
318                 "       This is because it is not on Linux AND has been\n"
319                 "       executed strangely. This is unusual.\n");
320      }
321    TS("Determine Prefix Done");
322
323    /* for debugging by redirecting stdout of e to a log file to tail */
324    setvbuf(stdout, NULL, _IONBF, 0);
325
326    TS("Environment Variables");
327    if (getenv("E_RESTART")) after_restart = EINA_TRUE;
328    if (getenv("DESKTOP_STARTUP_ID"))
329      e_util_env_set("DESKTOP_STARTUP_ID", NULL);
330    e_util_env_set("E_RESTART_OK", NULL);
331    e_util_env_set("PANTS", "ON");
332    e_util_env_set("DESKTOP", "Enlightenment-0.17.0");
333    TS("Environment Variables Done");
334
335    TS("Parse Arguments");
336    _e_main_parse_arguments(argc, argv);
337    TS("Parse Arguments Done");
338
339    /*** Initialize Core EFL Libraries We Need ***/
340
341    TS("Eet Init");
342    if (!eet_init())
343      {
344         e_error_message_show(_("Enlightenment cannot initialize Eet!\n"));
345         _e_main_shutdown(-1);
346      }
347    TS("Eet Init Done");
348    _e_main_shutdown_push(eet_shutdown);
349
350    TS("Ecore Init");
351    if (!ecore_init())
352      {
353         e_error_message_show(_("Enlightenment cannot initialize Ecore!\n"));
354         _e_main_shutdown(-1);
355      }
356    TS("Ecore Init Done");
357    _e_main_shutdown_push(ecore_shutdown);
358
359    e_first_frame = getenv("E_FIRST_FRAME");
360    if (e_first_frame && (!e_first_frame[0]))
361      e_first_frame = NULL;
362    else
363      e_first_frame_start_time = ecore_time_get();
364
365    TS("EIO Init");
366    if (!eio_init())
367      {
368         e_error_message_show(_("Enlightenment cannot initialize EIO!\n"));
369         _e_main_shutdown(-1);
370      }
371    TS("EIO Init Done");
372    _e_main_shutdown_push(eio_shutdown);
373
374    ecore_app_args_set(argc, (const char **)argv);
375
376    TS("Ecore Event Handlers");
377    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_EXIT,
378                                 _e_main_cb_signal_exit, NULL))
379      {
380         e_error_message_show(_("Enlightenment cannot set up an exit signal handler.\n"
381                                "Perhaps you are out of memory?"));
382         _e_main_shutdown(-1);
383      }
384    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_HUP,
385                                 _e_main_cb_signal_hup, NULL))
386      {
387         e_error_message_show(_("Enlightenment cannot set up a HUP signal handler.\n"
388                                "Perhaps you are out of memory?"));
389         _e_main_shutdown(-1);
390      }
391    if (!ecore_event_handler_add(ECORE_EVENT_SIGNAL_USER,
392                                 _e_main_cb_signal_user, NULL))
393      {
394         e_error_message_show(_("Enlightenment cannot set up a USER signal handler.\n"
395                                "Perhaps you are out of memory?"));
396         _e_main_shutdown(-1);
397      }
398    TS("Ecore Event Handlers Done");
399
400    TS("Ecore_File Init");
401    if (!ecore_file_init())
402      {
403         e_error_message_show(_("Enlightenment cannot initialize Ecore_File!\n"));
404         _e_main_shutdown(-1);
405      }
406    TS("Ecore_File Init Done");
407    _e_main_shutdown_push(ecore_file_shutdown);
408
409    TS("Ecore_Con Init");
410    if (!ecore_con_init())
411      {
412         e_error_message_show(_("Enlightenment cannot initialize Ecore_Con!\n"));
413         _e_main_shutdown(-1);
414      }
415    TS("Ecore_Con Init Done");
416    _e_main_shutdown_push(ecore_con_shutdown);
417
418    TS("Ecore_Ipc Init");
419    if (!ecore_ipc_init())
420      {
421         e_error_message_show(_("Enlightenment cannot initialize Ecore_Ipc!\n"));
422         _e_main_shutdown(-1);
423      }
424    TS("Ecore_Ipc Init Done");
425    _e_main_shutdown_push(ecore_ipc_shutdown);
426
427    _idle_before = ecore_idle_enterer_before_add(_e_main_cb_idle_before, NULL);
428
429    _xdg_data_dirs_augment();
430
431    TS("Ecore_Evas Init");
432    if (!ecore_evas_init())
433      {
434         e_error_message_show(_("Enlightenment cannot initialize Ecore_Evas!\n"));
435         _e_main_shutdown(-1);
436      }
437    TS("Ecore_Evas Init Done");
438 //   _e_main_shutdown_push(ecore_evas_shutdown);
439
440    TS("Elementary Init");
441    if (!elm_init(argc, argv))
442      {
443         e_error_message_show(_("Enlightenment cannot initialize Elementary!\n"));
444         _e_main_shutdown(-1);
445      }
446    TS("Elementary Init Done");
447    //_e_main_shutdown_push(elm_shutdown);
448
449    TS("Emotion Init");
450    if (!emotion_init())
451      {
452         e_error_message_show(_("Enlightenment cannot initialize Emotion!\n"));
453         _e_main_shutdown(-1);
454      }
455    TS("Emotion Init Done");
456    _e_main_shutdown_push((void *)emotion_shutdown);
457
458    /* e doesn't sync to compositor - it should be one */
459    ecore_evas_app_comp_sync_set(0);
460
461    TS("Ecore_Evas Engine Check");
462 #ifdef HAVE_WAYLAND_ONLY
463    if (!ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_WAYLAND_SHM))
464      {
465         e_error_message_show(_("Enlightenment found ecore_evas doesn't support the Wayland SHM\n"
466                                "rendering in Evas. Please check your installation of Evas and\n"
467                                 "Ecore and check they support the Wayland SHM rendering engine."));
468         _e_main_shutdown(-1);
469      }
470 #else
471    if (!ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_SOFTWARE_XCB))
472      {
473         if (!ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_SOFTWARE_XLIB))
474           {
475              e_error_message_show(_("Enlightenment found ecore_evas doesn't support the Software X11\n"
476                                     "rendering in Evas. Please check your installation of Evas and\n"
477                                     "Ecore and check they support the Software X11 rendering engine."));
478              _e_main_shutdown(-1);
479           }
480      }
481 #endif
482    if (!ecore_evas_engine_type_supported_get(ECORE_EVAS_ENGINE_SOFTWARE_BUFFER))
483      {
484         e_error_message_show(_("Enlightenment found ecore_evas doesn't support the Software Buffer\n"
485                                "rendering in Evas. Please check your installation of Evas and\n"
486                                "Ecore and check they support the Software Buffer rendering engine."));
487         _e_main_shutdown(-1);
488      }
489    TS("Ecore_Evas Engine Check Done");
490
491    TS("Edje Init");
492    if (!edje_init())
493      {
494         e_error_message_show(_("Enlightenment cannot initialize Edje!\n"));
495         _e_main_shutdown(-1);
496      }
497    TS("Edje Init Done");
498    _e_main_shutdown_push(edje_shutdown);
499    edje_freeze();
500
501    /*** Initialize E Subsystems We Need ***/
502
503    TS("E Intl Init");
504    if (!e_intl_init())
505      {
506         e_error_message_show(_("Enlightenment cannot initialize E_Intl!\n"));
507         _e_main_shutdown(-1);
508      }
509    TS("E Intl Init Done");
510    _e_main_shutdown_push(e_intl_shutdown);
511
512 #ifndef HAVE_WAYLAND_ONLY
513    /* init white box of death alert */
514    TS("E_Alert Init");
515    if (!e_alert_init())
516      {
517         e_error_message_show(_("Enlightenment cannot initialize its emergency alert system.\n"
518                                "Have you set your DISPLAY variable?"));
519         _e_main_shutdown(-1);
520      }
521    TS("E_Alert Init Done");
522    _e_main_shutdown_push(e_alert_shutdown);
523 #endif
524
525    TS("E_Configure Init");
526    e_configure_init();
527    TS("E_Configure Init Done");
528
529    TS("E Directories Init");
530    /* setup directories we will be using for configurations storage etc. */
531    if (!_e_main_dirs_init())
532      {
533         e_error_message_show(_("Enlightenment cannot create directories in your home directory.\n"
534                                "Perhaps you have no home directory or the disk is full?"));
535         _e_main_shutdown(-1);
536      }
537    TS("E Directories Init Done");
538    _e_main_shutdown_push(_e_main_dirs_shutdown);
539
540    TS("E_Filereg Init");
541    if (!e_filereg_init())
542      {
543         e_error_message_show(_("Enlightenment cannot set up its file registry system.\n"));
544         _e_main_shutdown(-1);
545      }
546    TS("E_Filereg Init Done");
547    _e_main_shutdown_push(e_filereg_shutdown);
548
549    TS("E_Config Init");
550    if (!e_config_init())
551      {
552         e_error_message_show(_("Enlightenment cannot set up its config system.\n"));
553         _e_main_shutdown(-1);
554      }
555    TS("E_Config Init Done");
556    _e_main_shutdown_push(e_config_shutdown);
557
558    TS("E_Env Init");
559    if (!e_env_init())
560      {
561         e_error_message_show(_("Enlightenment cannot set up its environment.\n"));
562         _e_main_shutdown(-1);
563      }
564    TS("E_Env Init Done");
565    _e_main_shutdown_push(e_env_shutdown);
566
567    efreet_desktop_environment_set(e_config->desktop_environment);
568    e_util_env_set("E_ICON_THEME", e_config->icon_theme);
569    ecore_exe_run_priority_set(e_config->priority);
570    locked |= e_config->desklock_start_locked;
571
572    s = getenv("E_DESKLOCK_LOCKED");
573    if ((s) && (!strcmp(s, "locked"))) waslocked = EINA_TRUE;
574
575    TS("E Paths Init");
576    if (!_e_main_path_init())
577      {
578         e_error_message_show(_("Enlightenment cannot set up paths for finding files.\n"
579                                "Perhaps you are out of memory?"));
580         _e_main_shutdown(-1);
581      }
582    TS("E Paths Init Done");
583    _e_main_shutdown_push(_e_main_path_shutdown);
584
585    TS("E_Ipc Init");
586    if (!e_ipc_init()) _e_main_shutdown(-1);
587    TS("E_Ipc Init Done");
588    _e_main_shutdown_push(e_ipc_shutdown);
589
590    edje_frametime_set(1.0 / e_config->framerate);
591
592    TS("E_Font Init");
593    if (!e_font_init())
594      {
595         e_error_message_show(_("Enlightenment cannot set up its font system.\n"));
596         _e_main_shutdown(-1);
597      }
598    TS("E_Font Init Done");
599    _e_main_shutdown_push(e_font_shutdown);
600
601    TS("E_Font Apply");
602    e_font_apply();
603    TS("E_Font Apply Done");
604
605    TS("E_Theme Init");
606    if (!e_theme_init())
607      {
608         e_error_message_show(_("Enlightenment cannot set up its theme system.\n"));
609         _e_main_shutdown(-1);
610      }
611    TS("E_Theme Init Done");
612    _e_main_shutdown_push(e_theme_shutdown);
613
614    TS("E_Moveresize Init");
615    e_moveresize_init();
616    TS("E_Moveresize Init Done");
617    _e_main_shutdown_push(e_moveresize_shutdown);
618
619    if (e_config->show_splash)
620      e_init_status_set(_("Setup Message Bus"));
621    TS("E_Msgbus Init");
622    if (e_msgbus_init())
623      _e_main_shutdown_push(e_msgbus_shutdown);
624    TS("E_Msgbus Init Done");
625
626    TS("Efreet Init");
627    if (!efreet_init())
628      {
629         e_error_message_show(_("Enlightenment cannot initialize the FDO desktop system.\n"
630                                "Perhaps you lack permissions on ~/.cache/efreet or are\n"
631                                "out of memory or disk space?"));
632         _e_main_shutdown(-1);
633      }
634    TS("Efreet Init Done");
635    _e_main_shutdown_push(efreet_shutdown);
636
637    if (e_config->show_splash)
638      e_init_status_set(_("Starting International Support"));
639    TS("E_Intl Post Init");
640    if (!e_intl_post_init())
641      {
642         e_error_message_show(_("Enlightenment cannot set up its intl system.\n"));
643         _e_main_shutdown(-1);
644      }
645    TS("E_Intl Post Init Done");
646    _e_main_shutdown_push(e_intl_post_shutdown);
647
648    e_screensaver_preinit();
649
650    if (e_config->show_splash)
651      e_init_status_set(_("Setup Actions"));
652    TS("E_Actions Init");
653    if (!e_actions_init())
654      {
655         e_error_message_show(_("Enlightenment cannot set up its actions system.\n"));
656         _e_main_shutdown(-1);
657      }
658    TS("E_Actions Init Done");
659    _e_main_shutdown_push(e_actions_shutdown);
660
661    /* these just add event handlers and can't fail
662     * timestamping them is dumb.
663     */
664    e_zone_init();
665    e_desk_init();
666    e_exehist_init();
667
668    if (e_config->show_splash)
669      e_init_status_set(_("Setup Powersave Modes"));
670    TS("E_Powersave Init");
671    if (!e_powersave_init())
672      {
673         e_error_message_show(_("Enlightenment cannot set up its powersave modes.\n"));
674         _e_main_shutdown(-1);
675      }
676    TS("E_Powersave Init Done");
677    _e_main_shutdown_push(e_powersave_shutdown);
678
679    if (e_config->show_splash)
680      e_init_status_set(_("Setup Screensaver"));
681    TS("E_Screensaver Init");
682    if (!e_screensaver_init())
683      {
684         e_error_message_show(_("Enlightenment cannot configure the X screensaver.\n"));
685         _e_main_shutdown(-1);
686      }
687    TS("E_Screensaver Init Done");
688    _e_main_shutdown_push(e_screensaver_shutdown);
689
690    if (e_config->show_splash)
691      e_init_status_set(_("Setup Screens"));
692    TS("Screens Init");
693    if (!_e_main_screens_init())
694      {
695         e_error_message_show(_("Enlightenment set up window management for all the screens on your system\n"
696                                "failed. Perhaps another window manager is running?\n"));
697         _e_main_shutdown(-1);
698      }
699    TS("Screens Init Done");
700    _e_main_shutdown_push(_e_main_screens_shutdown);
701    e_screensaver_force_update();
702
703    TS("E_Pointer Init");
704    if (!e_pointer_init())
705      {
706         e_error_message_show(_("Enlightenment cannot set up its pointer system.\n"));
707         _e_main_shutdown(-1);
708      }
709    TS("E_Pointer Init Done");
710    _e_main_shutdown_push(e_pointer_shutdown);
711    e_menu_init();
712
713    TS("E_Scale Init");
714    if (!e_scale_init())
715      {
716         e_error_message_show(_("Enlightenment cannot set up its scale system.\n"));
717         _e_main_shutdown(-1);
718      }
719    TS("E_Scale Init Done");
720    _e_main_shutdown_push(e_scale_shutdown);
721
722    if (e_config->show_splash)
723      {
724         TS("E_Splash Init");
725         if (!e_init_init())
726           {
727              e_error_message_show(_("Enlightenment cannot set up its init screen.\n"));
728              _e_main_shutdown(-1);
729           }
730         TS("E_Splash Init Done");
731         _e_main_shutdown_push(e_init_shutdown);
732      }
733    if (!((!e_config->show_splash) || (after_restart)))
734      e_init_show();
735
736    if (!really_know)
737      {
738         TS("Test File Format Support");
739         _e_main_test_formats();
740         TS("Test File Format Support Done");
741      }
742    else
743      {
744         efreet_icon_extension_add(".svg");
745         efreet_icon_extension_add(".jpg");
746         efreet_icon_extension_add(".png");
747         efreet_icon_extension_add(".edj");
748      }
749
750    if (e_config->show_splash)
751      e_init_status_set(_("Setup ACPI"));
752    TS("E_Acpi Init");
753    e_acpi_init();
754    TS("E_Acpi Init Done");
755    _e_main_shutdown_push(e_acpi_shutdown);
756
757    if (e_config->show_splash)
758      e_init_status_set(_("Setup Backlight"));
759    TS("E_Backlight Init");
760    if (!e_backlight_init())
761      {
762         e_error_message_show(_("Enlightenment cannot configure the backlight.\n"));
763         _e_main_shutdown(-1);
764      }
765    TS("E_Backlight Init Done");
766
767    if (e_config->show_splash)
768      e_init_status_set(_("Setup DPMS"));
769    TS("E_Dpms Init");
770    if (!e_dpms_init())
771      {
772         e_error_message_show(_("Enlightenment cannot configure the DPMS settings.\n"));
773         _e_main_shutdown(-1);
774      }
775    TS("E_Dpms Init Done");
776    _e_main_shutdown_push(e_dpms_shutdown);
777
778    if (e_config->show_splash)
779      e_init_status_set(_("Setup Desklock"));
780    TS("E_Desklock Init");
781    if (!e_desklock_init())
782      {
783         e_error_message_show(_("Enlightenment cannot set up its desk locking system.\n"));
784         _e_main_shutdown(-1);
785      }
786    TS("E_Desklock Init Done");
787    _e_main_shutdown_push(e_desklock_shutdown);
788
789    if (waslocked || (locked && ((!after_restart) || (!getenv("E_DESKLOCK_UNLOCKED")))))
790      e_desklock_show(EINA_TRUE);
791
792    if (e_config->show_splash)
793      e_init_status_set(_("Setup Paths"));
794    TS("Efreet Paths");
795    _e_main_efreet_paths_init();
796    TS("Efreet Paths Done");
797
798    if (e_config->show_splash)
799      e_init_status_set(_("Setup System Controls"));
800    TS("E_Sys Init");
801    if (!e_sys_init())
802      {
803         e_error_message_show(_("Enlightenment cannot initialize the System Command system.\n"));
804         _e_main_shutdown(-1);
805      }
806    TS("E_Sys Init Done");
807    _e_main_shutdown_push(e_sys_shutdown);
808
809    if (e_config->show_splash)
810      e_init_status_set(_("Setup Execution System"));
811    TS("E_Exec Init");
812    if (!e_exec_init())
813      {
814         e_error_message_show(_("Enlightenment cannot set up its exec system.\n"));
815         _e_main_shutdown(-1);
816      }
817    TS("E_Exec Init Done");
818
819    TS("E_Comp Freeze");
820    e_comp_all_freeze();
821    TS("E_Comp Freeze Done");
822
823    if (e_config->show_splash)
824      e_init_status_set(_("Setup Filemanager"));
825    TS("E_Fm2 Init");
826    if (!e_fm2_init())
827      {
828         e_error_message_show(_("Enlightenment cannot initialize the File manager.\n"));
829         _e_main_shutdown(-1);
830      }
831    TS("E_Fm2 Init Done");
832    _e_main_shutdown_push(e_fm2_shutdown);
833
834    if (e_config->show_splash)
835      e_init_status_set(_("Setup Message System"));
836    TS("E_Msg Init");
837    if (!e_msg_init())
838      {
839         e_error_message_show(_("Enlightenment cannot set up its msg system.\n"));
840         _e_main_shutdown(-1);
841      }
842    TS("E_Msg Init Done");
843    _e_main_shutdown_push(e_msg_shutdown);
844
845    if (e_config->show_splash)
846      e_init_status_set(_("Setup Grab Input Handling"));
847    TS("E_Grabinput Init");
848    if (!e_grabinput_init())
849      {
850         e_error_message_show(_("Enlightenment cannot set up its grab input handling system.\n"));
851         _e_main_shutdown(-1);
852      }
853    TS("E_Grabinput Init Done");
854    _e_main_shutdown_push(e_grabinput_shutdown);
855
856    if (e_config->show_splash)
857      e_init_status_set(_("Setup Modules"));
858    TS("E_Module Init");
859    if (!e_module_init())
860      {
861         e_error_message_show(_("Enlightenment cannot set up its module system.\n"));
862         _e_main_shutdown(-1);
863      }
864    TS("E_Module Init Done");
865    _e_main_shutdown_push(e_module_shutdown);
866
867    if (e_config->show_splash)
868      e_init_status_set(_("Setup Remembers"));
869    TS("E_Remember Init");
870    if (!e_remember_init(after_restart ? E_STARTUP_RESTART : E_STARTUP_START))
871      {
872         e_error_message_show(_("Enlightenment cannot setup remember settings.\n"));
873         _e_main_shutdown(-1);
874      }
875    TS("E_Remember Init Done");
876    _e_main_shutdown_push(e_remember_shutdown);
877
878    if (e_config->show_splash)
879      e_init_status_set(_("Setup Color Classes"));
880    TS("E_Color_Class Init");
881    if (!e_color_class_init())
882      {
883         e_error_message_show(_("Enlightenment cannot set up its color class system.\n"));
884         _e_main_shutdown(-1);
885      }
886    TS("E_Color_Class Init Done");
887    _e_main_shutdown_push(e_color_class_shutdown);
888
889    if (e_config->show_splash)
890      e_init_status_set(_("Setup Gadcon"));
891    TS("E_Gadcon Init");
892    if (!e_gadcon_init())
893      {
894         e_error_message_show(_("Enlightenment cannot set up its gadget control system.\n"));
895         _e_main_shutdown(-1);
896      }
897    TS("E_Gadcon Init Done");
898    _e_main_shutdown_push(e_gadcon_shutdown);
899
900    if (e_config->show_splash)
901      e_init_status_set(_("Setup Toolbars"));
902    TS("E_Toolbar Init");
903    if (!e_toolbar_init())
904      {
905         e_error_message_show(_("Enlightenment cannot set up its toolbars.\n"));
906         _e_main_shutdown(-1);
907      }
908    TS("E_Toolbar Init Done");
909    _e_main_shutdown_push(e_toolbar_shutdown);
910
911    if (e_config->show_splash)
912      e_init_status_set(_("Setup Wallpaper"));
913    TS("E_Bg Init");
914    if (!e_bg_init())
915      {
916         e_error_message_show(_("Enlightenment cannot set up its desktop background system.\n"));
917         _e_main_shutdown(-1);
918      }
919    TS("E_Bg Init Done");
920    _e_main_shutdown_push(e_bg_shutdown);
921
922    if (e_config->show_splash)
923      e_init_status_set(_("Setup Mouse"));
924    TS("E_Mouse Init");
925    if (!e_mouse_update())
926      {
927         e_error_message_show(_("Enlightenment cannot configure the mouse settings.\n"));
928         _e_main_shutdown(-1);
929      }
930    TS("E_Mouse Init Done");
931
932    if (e_config->show_splash)
933      e_init_status_set(_("Setup Bindings"));
934    TS("E_Bindings Init");
935    if (!e_bindings_init())
936      {
937         e_error_message_show(_("Enlightenment cannot set up its bindings system.\n"));
938         _e_main_shutdown(-1);
939      }
940    TS("E_Bindings Init Done");
941    _e_main_shutdown_push(e_bindings_shutdown);
942
943    if (e_config->show_splash)
944      e_init_status_set(_("Setup Thumbnailer"));
945    TS("E_Thumb Init");
946    if (!e_thumb_init())
947      {
948         e_error_message_show(_("Enlightenment cannot initialize the Thumbnailing system.\n"));
949         _e_main_shutdown(-1);
950      }
951    TS("E_Thumb Init Done");
952    _e_main_shutdown_push(e_thumb_shutdown);
953
954    TS("E_Icon Init");
955    if (!e_icon_init())
956      {
957         e_error_message_show(_("Enlightenment cannot initialize the Icon Cache system.\n"));
958         _e_main_shutdown(-1);
959      }
960    TS("E_Icon Init Done");
961    _e_main_shutdown_push(e_icon_shutdown);
962
963    TS("E_Update Init");
964    if (!e_update_init())
965      {
966         e_error_message_show(_("Enlightenment cannot initialize the Update system.\n"));
967         _e_main_shutdown(-1);
968      }
969    TS("E_Update Init Done");
970    _e_main_shutdown_push(e_update_shutdown);
971
972    if (e_config->show_splash)
973      e_init_status_set(_("Setup Desktop Environment"));
974    TS("E_Deskenv Init");
975    if (!e_deskenv_init())
976      {
977         e_error_message_show(_("Enlightenment cannot initialize its desktop environment.\n"));
978         _e_main_shutdown(-1);
979      }
980    TS("E_Deskenv Init Done");
981    _e_main_shutdown_push(e_deskenv_shutdown);
982
983    if (e_config->show_splash)
984      e_init_status_set(_("Setup File Ordering"));
985    TS("E_Order Init");
986    if (!e_order_init())
987      {
988         e_error_message_show(_("Enlightenment cannot set up its order file system.\n"));
989         _e_main_shutdown(-1);
990      }
991    TS("E_Order Init Done");
992    _e_main_shutdown_push(e_order_shutdown);
993
994    TS("Add Idler For X Flush");
995    _idle_flush = ecore_idle_enterer_add(_e_main_cb_x_flusher, NULL);
996    TS("Add Idler For X Flush Done");
997
998    TS("E_Manager Keys Grab");
999    e_managers_keys_grab();
1000    TS("E_Manager Keys Grab Done");
1001
1002    if (e_config->show_splash)
1003      e_init_status_set(_("Load Modules"));
1004    TS("Load Modules");
1005    _e_main_modules_load(safe_mode);
1006    TS("Load Modules Done");
1007
1008    TS("Run Startup Apps");
1009    if (!nostartup)
1010      {
1011         if (after_restart)
1012           e_startup(E_STARTUP_RESTART);
1013         else
1014           e_startup(E_STARTUP_START);
1015      }
1016    TS("Run Startup Apps Done");
1017
1018    if (e_config->show_splash && (!after_restart))
1019      ecore_timer_add(2.0, _e_main_cb_startup_fake_end, NULL);
1020
1021    TS("E_Comp Thaw");
1022    e_comp_all_thaw();
1023    TS("E_Comp Thaw Done");
1024
1025    TS("E_Test Init");
1026    e_test();
1027    TS("E_Test Done");
1028
1029    TS("E_Test_Helper Init");
1030    e_test_helper_init();
1031    _e_main_shutdown_push(e_test_helper_shutdown);
1032    TS("E_Test_Helper Done");
1033
1034    TS("E_INFO_SERVER Init");
1035    e_info_server_init();
1036    _e_main_shutdown_push(e_info_server_shutdown);
1037    TS("E_INFO_SERVER Done");
1038
1039    if (e_config->show_splash)
1040      e_init_status_set(_("Setup Shelves"));
1041    TS("E_Shelf Init");
1042    if (!e_shelf_init())
1043      {
1044         e_error_message_show(_("Enlightenment cannot set up its module system.\n"));
1045         _e_main_shutdown(-1);
1046      }
1047    TS("E_Shelf Init Done");
1048
1049    ecore_idle_enterer_before_add(_e_main_shelf_init_job, NULL);
1050
1051    _idle_after = ecore_idle_enterer_add(_e_main_cb_idle_after, NULL);
1052
1053    if (e_config->show_splash)
1054      e_init_status_set(_("Almost Done"));
1055
1056    starting = EINA_FALSE;
1057    inloop = EINA_TRUE;
1058
1059    e_util_env_set("E_RESTART", "1");
1060
1061    TS("MAIN LOOP AT LAST");
1062    if (!setjmp(x_fatal_buff))
1063      ecore_main_loop_begin();
1064    else
1065      CRI("FATAL: X Died. Connection gone. Abbreviated Shutdown\n");
1066
1067    inloop = EINA_FALSE;
1068    stopping = EINA_TRUE;
1069
1070    //if (!x_fatal) e_canvas_idle_flush();
1071
1072    e_config_save_flush();
1073    _e_main_desk_save();
1074    e_remember_internal_save();
1075    e_comp_internal_save();
1076
1077    _e_main_shutdown(0);
1078
1079    if (restart)
1080      {
1081         e_util_env_set("E_RESTART_OK", "1");
1082         if (getenv("E_START_MTRACK"))
1083           e_util_env_set("MTRACK", "track");
1084         ecore_app_restart();
1085      }
1086
1087    e_prefix_shutdown();
1088
1089    return 0;
1090 }
1091
1092 EAPI double
1093 e_main_ts(const char *str)
1094 {
1095    double ret;
1096    t1 = ecore_time_unix_get();
1097    printf("ESTART: %1.5f [%1.5f] - %s\n", t1 - t0, t1 - t2, str);
1098    ret = t1 - t2;
1099    t2 = t1;
1100    return ret;
1101 }
1102
1103 /* local functions */
1104 static void
1105 _e_main_shutdown(int errcode)
1106 {
1107    int i = 0;
1108    char buf[PATH_MAX];
1109    const char *dir;
1110
1111    printf("E: Begin Shutdown Procedure!\n");
1112
1113    if (_idle_before) ecore_idle_enterer_del(_idle_before);
1114    _idle_before = NULL;
1115    if (_idle_after) ecore_idle_enterer_del(_idle_after);
1116    _idle_after = NULL;
1117    if (_idle_flush) ecore_idle_enterer_del(_idle_flush);
1118    _idle_flush = NULL;
1119
1120    dir = getenv("XDG_RUNTIME_DIR");
1121    if (dir)
1122      {
1123         char buf_env[PATH_MAX];
1124         snprintf(buf_env, sizeof(buf_env), "%s", dir);
1125         snprintf(buf, sizeof(buf), "%s/.e-deleteme", buf_env);
1126         if (ecore_file_exists(buf)) ecore_file_recursive_rm(buf_env);
1127      }
1128    for (i = (_e_main_lvl - 1); i >= 0; i--)
1129      (*_e_main_shutdown_func[i])();
1130 #ifdef OBJECT_HASH_CHECK
1131    e_object_hash_shutdown();
1132 #endif
1133    if (errcode < 0) exit(errcode);
1134 }
1135
1136 static void
1137 _e_main_shutdown_push(int (*func)(void))
1138 {
1139    _e_main_lvl++;
1140    if (_e_main_lvl > MAX_LEVEL)
1141      {
1142         _e_main_lvl--;
1143         e_error_message_show("WARNING: too many init levels. MAX = %i\n",
1144                              MAX_LEVEL);
1145         return;
1146      }
1147    _e_main_shutdown_func[_e_main_lvl - 1] = func;
1148 }
1149
1150 static void
1151 _e_main_parse_arguments(int argc, char **argv)
1152 {
1153    char *s = NULL;
1154    int i = 0;
1155
1156    /* handle some command-line parameters */
1157    for (i = 1; i < argc; i++)
1158      {
1159         if ((!strcmp(argv[i], "-display")) && (i < (argc - 1)))
1160           {
1161              i++;
1162              e_util_env_set("DISPLAY", argv[i]);
1163           }
1164         else if ((!strcmp(argv[i], "-fake-xinerama-screen")) && (i < (argc - 1)))
1165           {
1166              int x, y, w, h;
1167
1168              i++;
1169              if (sscanf(argv[i], "%ix%i+%i+%i", &w, &h, &x, &y) == 4)
1170                e_xinerama_fake_screen_add(x, y, w, h);
1171           }
1172         else if (!strcmp(argv[i], "-good"))
1173           {
1174              good = EINA_TRUE;
1175              evil = EINA_FALSE;
1176              printf("LA LA LA\n");
1177           }
1178         else if (!strcmp(argv[i], "-evil"))
1179           {
1180              good = EINA_FALSE;
1181              evil = EINA_TRUE;
1182              printf("MUHAHAHAHHAHAHAHAHA\n");
1183           }
1184         else if (!strcmp(argv[i], "-psychotic"))
1185           {
1186              good = EINA_TRUE;
1187              evil = EINA_TRUE;
1188              printf("MUHAHALALALALALALALA\n");
1189           }
1190         else if ((!strcmp(argv[i], "-profile")) && (i < (argc - 1)))
1191           {
1192              i++;
1193              if (!getenv("E_CONF_PROFILE"))
1194                e_util_env_set("E_CONF_PROFILE", argv[i]);
1195           }
1196         else if (!strcmp(argv[i], "-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it"))
1197           really_know = EINA_TRUE;
1198         else if (!strcmp(argv[i], "-locked"))
1199           locked = EINA_TRUE;
1200         else if (!strcmp(argv[i], "-nopause"))
1201           e_nopause = EINA_TRUE;
1202         else if ((!strcmp(argv[i], "-h")) ||
1203                  (!strcmp(argv[i], "-help")) ||
1204                  (!strcmp(argv[i], "--help")))
1205           {
1206              printf
1207                (_(
1208                  "Options:\n"
1209                  "\t-display DISPLAY\n"
1210                  "\t\tConnect to display named DISPLAY.\n"
1211                  "\t\tEG: -display :1.0\n"
1212                  "\t-fake-xinerama-screen WxH+X+Y\n"
1213                  "\t\tAdd a FAKE xinerama screen (instead of the real ones)\n"
1214                  "\t\tgiven the geometry. Add as many as you like. They all\n"
1215                  "\t\treplace the real xinerama screens, if any. This can\n"
1216                  "\t\tbe used to simulate xinerama.\n"
1217                  "\t\tEG: -fake-xinerama-screen 800x600+0+0 -fake-xinerama-screen 800x600+800+0\n"
1218                  "\t-profile CONF_PROFILE\n"
1219                  "\t\tUse the configuration profile CONF_PROFILE instead of the user selected default or just \"default\".\n"
1220                  "\t-good\n"
1221                  "\t\tBe good.\n"
1222                  "\t-evil\n"
1223                  "\t\tBe evil.\n"
1224                  "\t-psychotic\n"
1225                  "\t\tBe psychotic.\n"
1226                  "\t-locked\n"
1227                  "\t\tStart with desklock on, so password will be asked.\n"
1228                  "\t-i-really-know-what-i-am-doing-and-accept-full-responsibility-for-it\n"
1229                  "\t\tIf you need this help, you don't need this option.\n"
1230                  )
1231                );
1232              _e_main_shutdown(-1);
1233           }
1234      }
1235
1236    /* fix up DISPLAY to be :N.0 if no .screen is in it */
1237    s = getenv("DISPLAY");
1238    if (s)
1239      {
1240         char *p, buff[4096];
1241
1242         if (!(p = strrchr(s, ':')))
1243           {
1244              snprintf(buff, sizeof(buff), "%s:0.0", s);
1245              e_util_env_set("DISPLAY", buff);
1246           }
1247         else
1248           {
1249              if (!strrchr(p, '.'))
1250                {
1251                   snprintf(buff, sizeof(buff), "%s.0", s);
1252                   e_util_env_set("DISPLAY", buff);
1253                }
1254           }
1255      }
1256
1257    /* we want to have been launched by enlightenment_start. there is a very */
1258    /* good reason we want to have been launched this way, thus check */
1259    if (!getenv("E_START"))
1260      {
1261         e_error_message_show(_("You are executing enlightenment directly. This is\n"
1262                                "bad. Please do not execute the \"enlightenment\"\n"
1263                                "binary. Use the \"enlightenment_start\" launcher. It\n"
1264                                "will handle setting up environment variables, paths,\n"
1265                                "and launching any other required services etc.\n"
1266                                "before enlightenment itself begins running.\n"));
1267         _e_main_shutdown(-1);
1268      }
1269 }
1270
1271 EINTERN void
1272 _e_main_cb_x_fatal(void *data __UNUSED__)
1273 {
1274    e_error_message_show("Lost X Connection.\n");
1275    ecore_main_loop_quit();
1276    if (!x_fatal)
1277      {
1278         x_fatal = EINA_TRUE;
1279         if (inloop) longjmp(x_fatal_buff, -99);
1280      }
1281 }
1282
1283 static Eina_Bool
1284 _e_main_cb_signal_exit(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__)
1285 {
1286    /* called on ctrl-c, kill (pid) (also SIGINT, SIGTERM and SIGQIT) */
1287    e_sys_action_do(E_SYS_EXIT, NULL);
1288    return ECORE_CALLBACK_RENEW;
1289 }
1290
1291 static Eina_Bool
1292 _e_main_cb_signal_hup(void *data __UNUSED__, int ev_type __UNUSED__, void *ev __UNUSED__)
1293 {
1294    e_sys_action_do(E_SYS_RESTART, NULL);
1295    return ECORE_CALLBACK_RENEW;
1296 }
1297
1298 static Eina_Bool
1299 _e_main_cb_signal_user(void *data __UNUSED__, int ev_type __UNUSED__, void *ev)
1300 {
1301    Ecore_Event_Signal_User *e = ev;
1302
1303    if (e->number == 1)
1304      {
1305 //        E_Action *a = e_action_find("configuration");
1306 //        if ((a) && (a->func.go)) a->func.go(NULL, NULL);
1307      }
1308    else if (e->number == 2)
1309      {
1310         // comp module has its own handler for this for enabling/disabling fps debug
1311      }
1312    return ECORE_CALLBACK_RENEW;
1313
1314 }
1315
1316 static int
1317 _e_main_dirs_init(void)
1318 {
1319    const char *base;
1320    const char *dirs[] =
1321    {
1322       "images",
1323       "fonts",
1324       "themes",
1325       "icons",
1326       "backgrounds",
1327       "applications",
1328       "applications/menu",
1329       "applications/menu/favorite",
1330       "applications/menu/all",
1331       "applications/bar",
1332       "applications/bar/default",
1333       "applications/startup",
1334       "applications/restart",
1335       "applications/trash",
1336       "applications/desk-lock",
1337       "applications/desk-unlock",
1338       "modules",
1339       "config",
1340       "locale",
1341       "input_methods",
1342       NULL
1343    };
1344
1345    base = e_user_dir_get();
1346    if (ecore_file_mksubdirs(base, dirs) != sizeof(dirs) / sizeof(dirs[0]) - 1)
1347      {
1348         e_error_message_show("Could not create one of the required "
1349                              "subdirectories of '%s'\n", base);
1350         return 0;
1351      }
1352
1353    return 1;
1354 }
1355
1356 static int
1357 _e_main_dirs_shutdown(void)
1358 {
1359    return 1;
1360 }
1361
1362 static int
1363 _e_main_path_init(void)
1364 {
1365    char buf[PATH_MAX];
1366
1367    /* setup data paths */
1368    path_data = e_path_new();
1369    if (!path_data)
1370      {
1371         e_error_message_show("Cannot allocate path for path_data\n");
1372         return 0;
1373      }
1374    e_prefix_data_concat_static(buf, "data");
1375    e_path_default_path_append(path_data, buf);
1376    e_path_user_path_set(path_data, &(e_config->path_append_data));
1377
1378    /* setup image paths */
1379    path_images = e_path_new();
1380    if (!path_images)
1381      {
1382         e_error_message_show("Cannot allocate path for path_images\n");
1383         return 0;
1384      }
1385    e_user_dir_concat_static(buf, "/images");
1386    e_path_default_path_append(path_images, buf);
1387    e_prefix_data_concat_static(buf, "data/images");
1388    e_path_default_path_append(path_images, buf);
1389    e_path_user_path_set(path_images, &(e_config->path_append_images));
1390
1391    /* setup font paths */
1392    path_fonts = e_path_new();
1393    if (!path_fonts)
1394      {
1395         e_error_message_show("Cannot allocate path for path_fonts\n");
1396         return 0;
1397      }
1398    e_user_dir_concat_static(buf, "/fonts");
1399    e_path_default_path_append(path_fonts, buf);
1400    e_prefix_data_concat_static(buf, "data/fonts");
1401    e_path_default_path_append(path_fonts, buf);
1402    e_path_user_path_set(path_fonts, &(e_config->path_append_fonts));
1403
1404    /* setup icon paths */
1405    path_icons = e_path_new();
1406    if (!path_icons)
1407      {
1408         e_error_message_show("Cannot allocate path for path_icons\n");
1409         return 0;
1410      }
1411    e_user_dir_concat_static(buf, "/icons");
1412    e_path_default_path_append(path_icons, buf);
1413    e_prefix_data_concat_static(buf, "data/icons");
1414    e_path_default_path_append(path_icons, buf);
1415    e_path_user_path_set(path_icons, &(e_config->path_append_icons));
1416
1417    /* setup module paths */
1418    path_modules = e_path_new();
1419    if (!path_modules)
1420      {
1421         e_error_message_show("Cannot allocate path for path_modules\n");
1422         return 0;
1423      }
1424    e_user_dir_concat_static(buf, "/modules");
1425    e_path_default_path_append(path_modules, buf);
1426    snprintf(buf, sizeof(buf), "%s/enlightenment/modules", e_prefix_lib_get());
1427    e_path_default_path_append(path_modules, buf);
1428    /* FIXME: eventually this has to go - moduels should have installers that
1429     * add appropriate install paths (if not installed to user homedir) to
1430     * e's module search dirs
1431     */
1432    snprintf(buf, sizeof(buf), "%s/enlightenment/modules_extra", e_prefix_lib_get());
1433    e_path_default_path_append(path_modules, buf);
1434    e_path_user_path_set(path_modules, &(e_config->path_append_modules));
1435
1436    /* setup background paths */
1437    path_backgrounds = e_path_new();
1438    if (!path_backgrounds)
1439      {
1440         e_error_message_show("Cannot allocate path for path_backgrounds\n");
1441         return 0;
1442      }
1443    e_user_dir_concat_static(buf, "/backgrounds");
1444    e_path_default_path_append(path_backgrounds, buf);
1445    e_prefix_data_concat_static(buf, "data/backgrounds");
1446    e_path_default_path_append(path_backgrounds, buf);
1447    e_path_user_path_set(path_backgrounds, &(e_config->path_append_backgrounds));
1448
1449    path_messages = e_path_new();
1450    if (!path_messages)
1451      {
1452         e_error_message_show("Cannot allocate path for path_messages\n");
1453         return 0;
1454      }
1455    e_user_dir_concat_static(buf, "/locale");
1456    e_path_default_path_append(path_messages, buf);
1457    e_path_default_path_append(path_messages, e_prefix_locale_get());
1458    e_path_user_path_set(path_messages, &(e_config->path_append_messages));
1459
1460    return 1;
1461 }
1462
1463 static int
1464 _e_main_path_shutdown(void)
1465 {
1466    if (path_data)
1467      {
1468         e_object_del(E_OBJECT(path_data));
1469         path_data = NULL;
1470      }
1471    if (path_images)
1472      {
1473         e_object_del(E_OBJECT(path_images));
1474         path_images = NULL;
1475      }
1476    if (path_fonts)
1477      {
1478         e_object_del(E_OBJECT(path_fonts));
1479         path_fonts = NULL;
1480      }
1481    if (path_icons)
1482      {
1483         e_object_del(E_OBJECT(path_icons));
1484         path_icons = NULL;
1485      }
1486    if (path_modules)
1487      {
1488         e_object_del(E_OBJECT(path_modules));
1489         path_modules = NULL;
1490      }
1491    if (path_backgrounds)
1492      {
1493         e_object_del(E_OBJECT(path_backgrounds));
1494         path_backgrounds = NULL;
1495      }
1496    if (path_messages)
1497      {
1498         e_object_del(E_OBJECT(path_messages));
1499         path_messages = NULL;
1500      }
1501    return 1;
1502 }
1503
1504 static void
1505 _e_main_test_formats(void)
1506 {
1507    Evas *evas;
1508    Ecore_Evas *ee;
1509    Evas_Object *im, *txt;
1510    Evas_Coord tw, th;
1511    char buff[PATH_MAX];
1512
1513    if (e_config->show_splash)
1514      e_init_status_set(_("Testing Format Support"));
1515
1516    if (!(ee = ecore_evas_buffer_new(1, 1)))
1517      {
1518         e_error_message_show(_("Enlightenment found Evas can't create a buffer canvas. Please check\n"
1519                                "Evas has Software Buffer engine support.\n"));
1520         _e_main_shutdown(-1);
1521      }
1522    evas = ecore_evas_get(ee);
1523    im = evas_object_image_add(evas);
1524
1525    e_prefix_data_concat_static(buff, "data/images/test.svg");
1526    evas_object_image_file_set(im, buff, NULL);
1527    if (evas_object_image_load_error_get(im) != EVAS_LOAD_ERROR_NONE)
1528      {
1529         e_error_message_show(_("Enlightenment found Evas can't load SVG files. "
1530                                "Check Evas has SVG loader support.\n"));
1531      }
1532    else
1533      efreet_icon_extension_add(".svg");
1534
1535    e_prefix_data_concat_static(buff, "data/images/test.jpg");
1536    evas_object_image_file_set(im, buff, NULL);
1537    if (evas_object_image_load_error_get(im) != EVAS_LOAD_ERROR_NONE)
1538      {
1539         e_error_message_show(_("Enlightenment found Evas can't load JPEG files. "
1540                                "Check Evas has JPEG loader support.\n"));
1541         _e_main_shutdown(-1);
1542      }
1543    efreet_icon_extension_add(".jpg");
1544
1545    e_prefix_data_concat_static(buff, "data/images/test.png");
1546    evas_object_image_file_set(im, buff, NULL);
1547    if (evas_object_image_load_error_get(im) != EVAS_LOAD_ERROR_NONE)
1548      {
1549         e_error_message_show(_("Enlightenment found Evas can't load PNG files. "
1550                                "Check Evas has PNG loader support.\n"));
1551         _e_main_shutdown(-1);
1552      }
1553    efreet_icon_extension_add(".png");
1554
1555    e_prefix_data_concat_static(buff, "data/images/test.edj");
1556    evas_object_image_file_set(im, buff, "images/0");
1557    if (evas_object_image_load_error_get(im) != EVAS_LOAD_ERROR_NONE)
1558      {
1559         e_error_message_show(_("Enlightenment found Evas can't load EET files. "
1560                                "Check Evas has EET loader support.\n"));
1561         _e_main_shutdown(-1);
1562      }
1563    efreet_icon_extension_add(".edj");
1564
1565    evas_object_del(im);
1566
1567    txt = evas_object_text_add(evas);
1568    evas_object_text_font_set(txt, "Sans", 10);
1569    evas_object_text_text_set(txt, "Hello");
1570    evas_object_geometry_get(txt, NULL, NULL, &tw, &th);
1571    if ((tw <= 0) && (th <= 0))
1572      {
1573         e_error_message_show(_("Enlightenment found Evas can't load the 'Sans' font. Check Evas has fontconfig\n"
1574                                "support and system fontconfig defines a 'Sans' font.\n"));
1575         _e_main_shutdown(-1);
1576      }
1577    evas_object_del(txt);
1578    ecore_evas_free(ee);
1579 }
1580
1581 static int
1582 _e_main_screens_init(void)
1583 {
1584    TS("\tscreens: manager");
1585    if (!e_manager_init()) return 0;
1586
1587    TS("\tscreens: client");
1588    if (!e_client_init()) return 0;
1589    TS("\tscreens: win");
1590    if (!e_win_init()) return 0;
1591 #ifndef HAVE_WAYLAND_ONLY
1592    TS("E_Xkb Init");
1593    if (!e_xkb_init())
1594      {
1595         e_error_message_show(_("Enlightenment cannot setup XKB Keyboard layouts.\n"));
1596         _e_main_shutdown(-1);
1597      }
1598    TS("E_Xkb Init Done");
1599 #endif
1600
1601    TS("Compositor Init");
1602    if (!e_comp_init())
1603      {
1604         e_error_message_show(_("Enlightenment cannot create a compositor.\n"));
1605         _e_main_shutdown(-1);
1606      }
1607
1608    _e_main_desk_restore();
1609
1610 #ifndef HAVE_WAYLAND_ONLY
1611    if (e_config->show_splash)
1612      e_init_status_set(_("Setup DND"));
1613    TS("E_Dnd Init");
1614    if (!e_dnd_init())
1615      {
1616         e_error_message_show(_("Enlightenment cannot set up its dnd system.\n"));
1617         _e_main_shutdown(-1);
1618      }
1619    TS("E_Dnd Init Done");
1620    _e_main_shutdown_push(e_dnd_shutdown);
1621 #endif
1622
1623    return 1;
1624 }
1625
1626 static int
1627 _e_main_screens_shutdown(void)
1628 {
1629    e_win_shutdown();
1630    e_menu_shutdown();
1631    e_shelf_shutdown();
1632    e_comp_shutdown();
1633    e_client_shutdown();
1634    e_exehist_shutdown();
1635    e_backlight_shutdown();
1636    e_exec_shutdown();
1637
1638    e_desk_shutdown();
1639    e_zone_shutdown();
1640    e_manager_shutdown();
1641    return 1;
1642 }
1643
1644 static void
1645 _e_main_desk_save(void)
1646 {
1647    const Eina_List *l;
1648    char env[1024], name[1024];
1649    E_Zone *zone;
1650
1651    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1652      {
1653         snprintf(name, sizeof(name), "DESK_%d_%d", e_comp->num, zone->num);
1654         snprintf(env, sizeof(env), "%d,%d", zone->desk_x_current, zone->desk_y_current);
1655         e_util_env_set(name, env);
1656      }
1657 }
1658
1659 static void
1660 _e_main_desk_restore(void)
1661 {
1662    const Eina_List *l;
1663    E_Zone *zone;
1664    const char *env;
1665    char name[1024];
1666
1667    EINA_LIST_FOREACH(e_comp->zones, l, zone)
1668      {
1669         E_Desk *desk;
1670         int desk_x, desk_y;
1671         char buf_e[64];
1672
1673         snprintf(name, sizeof(name), "DESK_%d_%d", e_comp->num, zone->num);
1674         env = getenv(name);
1675         if (!env) continue;
1676         snprintf(buf_e, sizeof(buf_e), "%s", env);
1677         if (!sscanf(buf_e, "%d,%d", &desk_x, &desk_y)) continue;
1678         desk = e_desk_at_xy_get(zone, desk_x, desk_y);
1679         if (!desk) continue;
1680         e_desk_show(desk);
1681      }
1682 }
1683
1684 static void
1685 _e_main_efreet_paths_init(void)
1686 {
1687    Eina_List **list;
1688
1689    if ((list = efreet_icon_extra_list_get()))
1690      {
1691         char buff[PATH_MAX];
1692
1693         e_user_dir_concat_static(buff, "icons");
1694         *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buff));
1695         e_prefix_data_concat_static(buff, "data/icons");
1696         *list = eina_list_prepend(*list, (void *)eina_stringshare_add(buff));
1697      }
1698 }
1699
1700 static Eina_Bool
1701 _e_main_modules_load_after(void *d EINA_UNUSED, int type EINA_UNUSED, void *ev EINA_UNUSED)
1702 {
1703    e_int_config_modules(NULL, NULL);
1704    E_FREE_FUNC(mod_init_end, ecore_event_handler_del);
1705    return ECORE_CALLBACK_RENEW;
1706 }
1707
1708 static void
1709 _e_main_modules_load(Eina_Bool safe_mode)
1710 {
1711    if (!safe_mode)
1712      e_module_all_load();
1713    else
1714      {
1715         E_Module *m;
1716         char *crashmodule;
1717
1718         crashmodule = getenv("E_MODULE_LOAD");
1719         if (crashmodule) m = e_module_new(crashmodule);
1720
1721         if ((crashmodule) && (m))
1722           {
1723              e_module_disable(m);
1724              e_object_del(E_OBJECT(m));
1725
1726              e_error_message_show
1727                (_("Enlightenment crashed early on start and has<br>"
1728                   "been restarted. There was an error loading the<br>"
1729                   "module named: %s. This module has been disabled<br>"
1730                   "and will not be loaded."), crashmodule);
1731              e_util_dialog_show
1732                (_("Enlightenment crashed early on start and has been restarted"),
1733                _("Enlightenment crashed early on start and has been restarted.<br>"
1734                  "There was an error loading the module named: %s<br><br>"
1735                  "This module has been disabled and will not be loaded."), crashmodule);
1736              e_module_all_load();
1737           }
1738         else
1739           {
1740              e_error_message_show
1741                (_("Enlightenment crashed early on start and has<br>"
1742                   "been restarted. All modules have been disabled<br>"
1743                   "and will not be loaded to help remove any problem<br>"
1744                   "modules from your configuration. The module<br>"
1745                   "configuration dialog should let you select your<br>"
1746                   "modules again.\n"));
1747              e_util_dialog_show
1748                (_("Enlightenment crashed early on start and has been restarted"),
1749                _("Enlightenment crashed early on start and has been restarted.<br>"
1750                  "All modules have been disabled and will not be loaded to help<br>"
1751                  "remove any problem modules from your configuration.<br><br>"
1752                  "The module configuration dialog should let you select your<br>"
1753                  "modules again."));
1754           }
1755         mod_init_end = ecore_event_handler_add(E_EVENT_MODULE_INIT_END, _e_main_modules_load_after, NULL);
1756      }
1757 }
1758
1759 static Eina_Bool
1760 _e_main_cb_idle_before(void *data __UNUSED__)
1761 {
1762    e_menu_idler_before();
1763    e_client_idler_before();
1764    e_pointer_idler_before();
1765    edje_thaw();
1766    return ECORE_CALLBACK_RENEW;
1767 }
1768
1769 static Eina_Bool
1770 _e_main_cb_idle_after(void *data __UNUSED__)
1771 {
1772    static int first_idle = 1;
1773
1774    edje_freeze();
1775
1776 #ifdef E_RELEASE_BUILD
1777    if (first_idle)
1778      {
1779         TS("SLEEP");
1780         first_idle = 0;
1781         e_precache_end = EINA_TRUE;
1782      }
1783 #else
1784    if (first_idle++ < 60)
1785      {
1786         TS("SLEEP");
1787         if (!first_idle)
1788           e_precache_end = EINA_TRUE;
1789      }
1790 #endif
1791
1792    return ECORE_CALLBACK_RENEW;
1793 }
1794
1795 static Eina_Bool
1796 _e_main_cb_x_flusher(void *data __UNUSED__)
1797 {
1798    eet_clearcache();
1799 #ifndef HAVE_WAYLAND_ONLY
1800    if (e_comp->comp_type == E_PIXMAP_TYPE_X)
1801      ecore_x_flush();
1802 #endif
1803    return ECORE_CALLBACK_RENEW;
1804 }
1805
1806 static Eina_Bool
1807 _e_main_cb_startup_fake_end(void *data __UNUSED__)
1808 {
1809    e_init_hide();
1810    return ECORE_CALLBACK_CANCEL;
1811 }