#ifdef HAVE_CONFIG_H # include #endif #include #include #include "efreetd.h" #include "efreetd_cache.h" extern FILE *efreetd_log_file; static int init = 0; static Ecore_Ipc_Server *ipc = NULL; static Ecore_Event_Handler *hnd_add = NULL; static Ecore_Event_Handler *hnd_del = NULL; static Ecore_Event_Handler *hnd_data = NULL; static int clients = 0; static Ecore_Timer *quit_timer_start = NULL; static Ecore_Timer *quit_timer = NULL; static Eina_Bool _cb_quit_timer(void *data EINA_UNUSED) { quit_timer = NULL; quit(); return EINA_FALSE; } static Eina_Bool _cb_quit_timer_start(void *data EINA_UNUSED) { quit_timer_start = NULL; if (quit_timer) ecore_timer_del(quit_timer); quit_timer = ecore_timer_add(10.0, _cb_quit_timer, NULL); return EINA_FALSE; } static void _broadcast(Ecore_Ipc_Server *svr, int major, int minor, void *data, int size) { Eina_List *ipc_clients = ecore_ipc_server_clients_get(svr); Eina_List *l; Ecore_Ipc_Client *cl; EINA_LIST_FOREACH(ipc_clients, l, cl) { fprintf(efreetd_log_file, "[%09.3f] Client broadcast %i.%i\n", ecore_time_get(), major, minor); fflush(efreetd_log_file); ecore_ipc_client_send(cl, major, minor, 0, 0, 0, data, size); } } static char * _parse_str(void *data, int size) { char *str = malloc(size + 1); if (!str) return NULL; memcpy(str, data, size); str[size] = 0; return str; } static Eina_List * _parse_strs(void *data, int size) { Eina_List *list = NULL; char *p, *p0 = NULL, *p1 = NULL, *e = (char *)data + size; for (p = data; p < e; p++) { if (!p0) { if (*p) { p0 = p; p1 = e; } } if ((!*p) && (p0)) { p1 = strdup(p0); if (p1) list = eina_list_append(list, p1); p0 = NULL; } } if (p0) { p = malloc(p1 - p0 + 1); if (p) { memcpy(p, p0, p1 - p0); p[p1 - p0] = 0; list = eina_list_append(list, p); } } return list; } #define IPC_HEAD(_type) \ Ecore_Ipc_Event_Client_##_type *e = event; \ if (ecore_ipc_client_server_get(e->client) != ipc) \ return ECORE_CALLBACK_PASS_ON static Eina_Bool _cb_client_add(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { IPC_HEAD(Add); if (quit_timer) { ecore_timer_del(quit_timer); quit_timer = NULL; } if (quit_timer_start) { ecore_timer_del(quit_timer_start); quit_timer_start = NULL; } clients++; fprintf(efreetd_log_file, "[%09.3f] Add client (count=%i)\n", ecore_time_get(), clients); fflush(efreetd_log_file); return ECORE_CALLBACK_DONE; } static Eina_Bool _cb_client_del(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { IPC_HEAD(Del); clients--; fprintf(efreetd_log_file, "[%09.3f] Del client (count=%i)\n", ecore_time_get(), clients); fflush(efreetd_log_file); if (clients == 0) { if (quit_timer) ecore_timer_del(quit_timer); quit_timer = ecore_timer_add(2.0, _cb_quit_timer, NULL); } return ECORE_CALLBACK_DONE; } static Eina_Bool _cb_client_data(void *data EINA_UNUSED, int type EINA_UNUSED, void *event) { Eina_List *strs; char *s; IPC_HEAD(Data); if (e->major == 1) // register lang { // input: str -> lang fprintf(efreetd_log_file, "[%09.3f] Client register lang\n", ecore_time_get()); fflush(efreetd_log_file); if ((s = _parse_str(e->data, e->size))) { char envlang[128], *env; env = getenv("LANG"); if (!((env) && (!strcmp(env, s)))) { snprintf(envlang, sizeof(envlang), "LANG=%s", s); env = strdup(envlang); putenv(env); /* leak env intentionnally */ } free(s); } // return if desktop cache exists (bool as minor) ecore_ipc_client_send(e->client, 1 /* register reply */, cache_desktop_exists(), 0, 0, 0, NULL, 0); } else if (e->major == 2) // add desktop dirs { // input: array of str -> dirs fprintf(efreetd_log_file, "[%09.3f] Client add desktop dirs\n", ecore_time_get()); fflush(efreetd_log_file); strs = _parse_strs(e->data, e->size); EINA_LIST_FREE(strs, s) { cache_desktop_dir_add(s); free(s); } } else if (e->major == 3) // build desktop cache { // input: str -> lang fprintf(efreetd_log_file, "[%09.3f] Client update desktop cache\n", ecore_time_get()); fflush(efreetd_log_file); if ((s = _parse_str(e->data, e->size))) { char envlang[128], *env; env = getenv("LANG"); if (!((env) && (!strcmp(env, s)))) { snprintf(envlang, sizeof(envlang), "LANG=%s", s); env = strdup(envlang); putenv(env); /* leak env intentionnally */ } free(s); } cache_desktop_update(); } else if (e->major == 4) // add icon dirs { // input: array of str -> dirs fprintf(efreetd_log_file, "[%09.3f] Client add icon dirs\n", ecore_time_get()); fflush(efreetd_log_file); strs = _parse_strs(e->data, e->size); EINA_LIST_FREE(strs, s) { cache_icon_dir_add(s); free(s); } } else if (e->major == 5) // add icon exts { // input: array of str -> exts fprintf(efreetd_log_file, "[%09.3f] Client add icon exts\n", ecore_time_get()); fflush(efreetd_log_file); strs = _parse_strs(e->data, e->size); EINA_LIST_FREE(strs, s) { cache_icon_ext_add(s); free(s); } } return ECORE_CALLBACK_DONE; } /////////////////////////////////////////////////////////////////////////// void send_signal_icon_cache_update(Eina_Bool update) { _broadcast(ipc, 2 /* icon cache update */, update, NULL, 0); } void send_signal_desktop_cache_update(Eina_Bool update) { _broadcast(ipc, 3 /* desktop cache update */, update, NULL, 0); } void send_signal_desktop_cache_build(void) { _broadcast(ipc, 1 /* desktop cache build */, 1, NULL, 0); } void send_signal_mime_cache_build(void) { _broadcast(ipc, 4 /* mime cache build */, 1, NULL, 0); } Eina_Bool ipc_init(void) { if (init > 0) return EINA_TRUE; if (!ecore_ipc_init()) return EINA_FALSE; ipc = ecore_ipc_server_add(ECORE_IPC_LOCAL_USER, "efreetd", 0, NULL); if (!ipc) { ecore_ipc_shutdown(); return EINA_FALSE; } quit_timer_start = ecore_timer_add(10.0, _cb_quit_timer_start, NULL); hnd_add = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_ADD, _cb_client_add, NULL); hnd_del = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DEL, _cb_client_del, NULL); hnd_data = ecore_event_handler_add(ECORE_IPC_EVENT_CLIENT_DATA, _cb_client_data, NULL); init++; return EINA_TRUE; } Eina_Bool ipc_shutdown(void) { if (init <= 0) return EINA_TRUE; init--; if (init > 0) return EINA_TRUE; if (quit_timer) ecore_timer_del(quit_timer); if (quit_timer_start) ecore_timer_del(quit_timer_start); quit_timer = NULL; quit_timer_start = NULL; ecore_ipc_server_del(ipc); ecore_event_handler_del(hnd_add); ecore_event_handler_del(hnd_del); ecore_event_handler_del(hnd_data); ipc = NULL; hnd_add = NULL; hnd_del = NULL; hnd_data = NULL; ecore_ipc_shutdown(); return EINA_TRUE; }