diff --git a/TODO b/TODO index 79d12f6b2..066d0529e 100644 --- a/TODO +++ b/TODO @@ -8,10 +8,11 @@ Some of the things (in very short form) that need to be done to E17... BUGS / FIXES ------------------------------------------------------------------------------- -* apparently with locales other than english/c the about box textblock breaks - newlines on every word (maybe the utf8 decode patch? for evas?) +* sometimes file monitoring for file changes, adds, deletes on a dir stops + working all of a sudden - unknown what causes it and why right now. * e_apps wont pick up changes in favorite menu dirs made by the applications - config dialog after a while (i think once u get 1 app in it stops listening) + config dialog after a while (i think once u get 1 app in it stops listening). + possibly the same bug as above with e_fm... * Need global unique identifier for gadcons, so that their config will move with them from one shelf to another. ]]] diff --git a/data/themes/default_fileman.edc b/data/themes/default_fileman.edc index 2e6ad21bd..640283f6d 100644 --- a/data/themes/default_fileman.edc +++ b/data/themes/default_fileman.edc @@ -5763,6 +5763,7 @@ images image: "e17_icon_fileman_file_clicked.png" COMP; image: "e17_icon_fileman_home.png" COMP; image: "e17_icon_fileman_desktop.png" COMP; + image: "e17_icon_fileman_hd.png" COMP; image: "e17_icon_fileman_pdf.png" COMP; image: "e17_icon_fileman_c.png" COMP; @@ -5816,6 +5817,7 @@ FILEMAN_ICON_CLICKABLE("folder"); FILEMAN_ICON_CLICKABLE("file"); FILEMAN_ICON("home"); FILEMAN_ICON("desktop"); +FILEMAN_ICON("hd"); FILEMAN_MIME("application/pdf","pdf"); FILEMAN_MIME("text/x-csrc","c"); diff --git a/data/themes/images/Makefile.am b/data/themes/images/Makefile.am index 8ccd84f43..1855e8cee 100644 --- a/data/themes/images/Makefile.am +++ b/data/themes/images/Makefile.am @@ -399,6 +399,7 @@ e17_icon_fileman_gz.png \ e17_icon_fileman_zip.png \ e17_icon_fileman_home.png \ e17_icon_fileman_desktop.png \ +e17_icon_fileman_hd.png \ e17_icon_background.png \ e17_icon_font.png \ e17_icon_screen_around.png \ diff --git a/data/themes/images/e17_icon_fileman_hd.png b/data/themes/images/e17_icon_fileman_hd.png new file mode 100644 index 000000000..3cecd4b09 Binary files /dev/null and b/data/themes/images/e17_icon_fileman_hd.png differ diff --git a/src/bin/e.h b/src/bin/e.h index 079558c98..9ef9e670b 100644 --- a/src/bin/e.h +++ b/src/bin/e.h @@ -63,6 +63,7 @@ #include #include #include +#include #include #include diff --git a/src/bin/e_apps.c b/src/bin/e_apps.c index 5c63ffbaa..165fb1246 100644 --- a/src/bin/e_apps.c +++ b/src/bin/e_apps.c @@ -676,7 +676,9 @@ e_app_exec(E_App *a, int launch_id) return 0; } /* We want the stdout and stderr as lines for the error dialog if it exits abnormally. */ + e_util_library_path_strip(); exe = ecore_exe_pipe_run(command, ECORE_EXE_PIPE_AUTO | ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR | ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR_LINE_BUFFERED, inst); + e_util_library_path_restore(); if (!exe) { free(command); diff --git a/src/bin/e_fm.c b/src/bin/e_fm.c index 5db360d5e..8e018098c 100644 --- a/src/bin/e_fm.c +++ b/src/bin/e_fm.c @@ -310,11 +310,32 @@ static int _e_fm2_fop_process(E_Fm2_Fop *fop); static int _e_fm2_cb_fop_idler(void *data); static int _e_fm2_cb_fop_timer(void *data); +static const char *_e_fm2_removable_dev_label_get(const char *uuid); +static void _e_fm2_removable_dev_add(const char *uuid); +static void _e_fm2_removable_dev_del(const char *uuid); +static void _e_fm2_removable_path_mount(const char *path); +static void _e_fm2_removable_path_umount(const char *path); +static void _e_fm2_removable_dev_mount(const char *uuid); +static void _e_fm2_removable_dev_umount(const char *uuid); +static void _e_fm2_removable_dev_label_set(const char *uuid, const char *label); +static int _e_fm2_cb_dbus_event_server_add(void *data, int ev_type, void *ev); +static int _e_fm2_cb_dbus_event_server_del(void *data, int ev_type, void *ev); +static int _e_fm2_cb_dbus_event_server_signal(void *data, int ev_type, void *ev); +static int _e_fm2_cb_dbus_event_child_exit(void *data, int ev_type, void *ev); +static void _e_fm2_cb_dbus_method_name_has_owner(void *data, Ecore_DBus_Method_Return *reply); +static void _e_fm2_cb_dbus_method_add_match(void *data, Ecore_DBus_Method_Return *reply); +static void _e_fm2_cb_dbus_method_error(void *data, const char *error); + +static Ecore_DBus_Server *_e_fm2_dbus = NULL; +static Evas_List *_e_fm2_dbus_handlers = NULL; static char *_e_fm2_meta_path = NULL; static Evas_Smart *_e_fm2_smart = NULL; static Evas_List *_e_fm2_list = NULL; static Evas_List *_e_fm2_fop_list = NULL; +EAPI int E_EVENT_REMOVABLE_ADD = 0; +EAPI int E_EVENT_REMOVABLE_DEL = 0; + /* externally accessible functions */ EAPI E_Fm2_Custom_File * e_fm2_custom_file_get(const char *path) @@ -371,12 +392,47 @@ e_fm2_init(void) _e_fm2_smart_clip_set, /* clip_set */ _e_fm2_smart_clip_unset, /* clip_unset */ NULL); /* data*/ + ecore_dbus_init(); + _e_fm2_dbus = ecore_dbus_server_system_connect(NULL); + if (_e_fm2_dbus) + { + _e_fm2_dbus_handlers = evas_list_append + (_e_fm2_dbus_handlers, + ecore_event_handler_add(ECORE_DBUS_EVENT_SERVER_ADD, + _e_fm2_cb_dbus_event_server_add, NULL)); + _e_fm2_dbus_handlers = evas_list_append + (_e_fm2_dbus_handlers, + ecore_event_handler_add(ECORE_DBUS_EVENT_SERVER_DEL, + _e_fm2_cb_dbus_event_server_del, NULL)); + _e_fm2_dbus_handlers = evas_list_append + (_e_fm2_dbus_handlers, + ecore_event_handler_add(ECORE_DBUS_EVENT_SIGNAL, + _e_fm2_cb_dbus_event_server_signal, NULL)); + _e_fm2_dbus_handlers = evas_list_append + (_e_fm2_dbus_handlers, + ecore_event_handler_add(ECORE_EXE_EVENT_DEL, + _e_fm2_cb_dbus_event_child_exit, NULL)); + + E_EVENT_REMOVABLE_ADD = ecore_event_type_new(); + E_EVENT_REMOVABLE_DEL = ecore_event_type_new(); + } return 1; } EAPI int e_fm2_shutdown(void) { + if (_e_fm2_dbus) + { + while (_e_fm2_dbus_handlers) + { + if (_e_fm2_dbus_handlers->data) ecore_event_handler_del(_e_fm2_dbus_handlers->data); + _e_fm2_dbus_handlers = evas_list_remove_list(_e_fm2_dbus_handlers, _e_fm2_dbus_handlers); + } + ecore_dbus_server_del(_e_fm2_dbus); + _e_fm2_dbus = NULL; + } + ecore_dbus_shutdown(); evas_smart_free(_e_fm2_smart); _e_fm2_smart = NULL; E_FREE(_e_fm2_meta_path); @@ -434,11 +490,16 @@ e_fm2_path_set(Evas_Object *obj, const char *dev, const char *path) if (sd->dev) evas_stringshare_del(sd->dev); if (sd->path) evas_stringshare_del(sd->path); - if (sd->realpath) evas_stringshare_del(sd->realpath); + if (sd->realpath) + { + _e_fm2_removable_path_umount(sd->realpath); + evas_stringshare_del(sd->realpath); + } sd->dev = sd->path = sd->realpath = NULL; if (dev) sd->dev = evas_stringshare_add(dev); sd->path = evas_stringshare_add(path); sd->realpath = _e_fm2_dev_path_map(sd->dev, sd->path); + _e_fm2_removable_path_mount(sd->realpath); _e_fm2_scan_stop(obj); _e_fm2_queue_free(obj); @@ -1979,6 +2040,7 @@ _e_fm2_icon_unfill(E_Fm2_Icon *ic) ic->info.real_link = NULL; ic->info.pseudo_dir = NULL; ic->info.mount = 0; + ic->info.removable = 0; ic->info.pseudo_link = 0; ic->info.deleted = 0; ic->info.broken_link = 0; @@ -2436,6 +2498,12 @@ _e_fm2_icon_desktop_load(E_Fm2_Icon *ic) if (desktop->URL) ic->info.link = _e_fm2_icon_desktop_url_eval(desktop->URL); } + else if (!strcmp(desktop->type, "Removable")) + { + ic->info.removable = 1; + if (desktop->URL) + ic->info.link = _e_fm2_icon_desktop_url_eval(desktop->URL); + } else if (!strcmp(desktop->type, "Link")) { if (desktop->URL) @@ -4327,7 +4395,11 @@ _e_fm2_smart_del(Evas_Object *obj) if (sd->refresh_job) ecore_job_del(sd->refresh_job); if (sd->dev) evas_stringshare_del(sd->dev); if (sd->path) evas_stringshare_del(sd->path); - if (sd->realpath) evas_stringshare_del(sd->realpath); + if (sd->realpath) + { + _e_fm2_removable_path_umount(sd->realpath); + evas_stringshare_del(sd->realpath); + } sd->dev = sd->path = sd->realpath = NULL; if (sd->config) _e_fm2_config_free(sd->config); @@ -5857,3 +5929,414 @@ _e_fm2_cb_fop_timer(void *data) edje_object_part_text_set(sd->overlay, "e.text.busy_label", buf); return 1; } + +typedef struct _E_Fm2_Removable E_Fm2_Removable; + +struct _E_Fm2_Removable +{ + const char *uuid; + const char *label; + const char *mount; + int mounts; +}; + +static Evas_List *_e_fm2_removables = NULL; + +static const char * +_e_fm2_removable_dev_label_get(const char *uuid) +{ + const char *lab = NULL; + char *rp1, *rp2, *file; + char buf[4096]; + Ecore_List *files; + + // FIXME: 1. look in config - is there a mapping from uuid -> label + // FIXME: 2. look at dev info to get its label + snprintf(buf, sizeof(buf), "/dev/disk/by-uuid/%s", uuid); + rp1 = ecore_file_realpath(buf); + files = ecore_file_ls("/dev/disk/by-label"); + if (files) + { + ecore_list_goto_first(files); + while ((file = ecore_list_current(files))) + { + snprintf(buf, sizeof(buf), "/dev/disk/by-label/%s", file); + rp2 = ecore_file_realpath(buf); + printf("%s (%s) == %s\n", rp2, file, rp1); + if ((rp1) && (rp2)) + { + if (!strcmp(rp1, rp2)) + { + lab = evas_stringshare_add(file); + E_FREE(rp2); + break; + } + } + E_FREE(rp2); + ecore_list_next(files); + } + ecore_list_destroy(files); + } + E_FREE(rp1); + if (lab) return lab; + // FIXME: 3. use uuid + return evas_stringshare_add(uuid); +} + +static void +_e_fm2_event_removable_add_free(void *data, void *ev) +{ + E_Fm2_Removable_Add *e; + + e = ev; + evas_stringshare_del(e->uuid); + evas_stringshare_del(e->label); + evas_stringshare_del(e->mount); + free(e); +} + +static void +_e_fm2_event_removable_del_free(void *data, void *ev) +{ + E_Fm2_Removable_Del *e; + + e = ev; + evas_stringshare_del(e->uuid); + evas_stringshare_del(e->label); + evas_stringshare_del(e->mount); + free(e); +} + +static void +_e_fm2_removable_dev_add(const char *uuid) +{ + E_Fm2_Removable *rem; + const char *lab; + FILE *f; + char buf[4096]; + + /* remove it - in case, so we don't add it twice */ + _e_fm2_removable_dev_del(uuid); + printf("ADD DEV ------- %s\n", uuid); + rem = E_NEW(E_Fm2_Removable, 1); + rem->uuid = evas_stringshare_add(uuid); + rem->label = _e_fm2_removable_dev_label_get(uuid); + snprintf(buf, sizeof(buf), "/media/disk_by-uuid_%s", uuid); + rem->mount = evas_stringshare_add(buf); + snprintf(buf, sizeof(buf), "%s/.e/e/fileman/favorites/|%s.desktop", + e_user_homedir_get(), uuid); + _e_fm2_removables = evas_list_append(_e_fm2_removables, rem); + f = fopen(buf, "w"); + if (f) + { + // FIXME: need to be able to find right icon - this means lookup + // custom icon based on uuid, label, etc. in user config + fprintf(f, + "[Desktop Entry]\n" + "Encoding=UTF-8\n" + "Name=Desktop\n" + "Type=Removable\n" + "Name=%s\n" + "X-Enlightenment-IconClass=%s\n" + "Comment=%s\n" + "URL=file:%s" + , + rem->label, + "fileman/hd", + _("Removable Device"), + rem->mount); + fclose(f); + } + // FIXME: need to maybe have some popup, dialog or other indicator pop up + // and maybe allow to click to open new removable device - maybe event + // and broadcast as below then have a module listen and pop up a popup + // like the pager module does - this popup could have a "open device" + // button or something to then browse it... + { + E_Fm2_Removable_Add *ev; + + ev = E_NEW(E_Fm2_Removable_Add, 1); + ev->uuid = evas_stringshare_add(rem->uuid); + ev->label = evas_stringshare_add(rem->label); + ev->mount = evas_stringshare_add(rem->mount); + ecore_event_add(E_EVENT_REMOVABLE_ADD, ev, _e_fm2_event_removable_add_free, NULL); + } +} + +static void +_e_fm2_removable_dev_del(const char *uuid) +{ + E_Fm2_Removable *rem; + Evas_List *l; + char buf[4096]; + + printf("DEL DEV ------- %s\n", uuid); + // FIXME: need to find all fm views for this dev and close them + _e_fm2_removable_dev_umount(uuid); + snprintf(buf, sizeof(buf), "%s/.e/e/fileman/favorites/|%s.desktop", + e_user_homedir_get(), uuid); + ecore_file_unlink(buf); + for (l = _e_fm2_removables; l; l = l->next) + { + rem = l->data; + if (!strcmp(uuid, rem->uuid)) + { + // FIXME: need to display popup or some other status here maybe + // using module to listen to the below event? + { + E_Fm2_Removable_Del *ev; + + ev = E_NEW(E_Fm2_Removable_Del, 1); + ev->uuid = evas_stringshare_add(rem->uuid); + ev->label = evas_stringshare_add(rem->label); + ev->mount = evas_stringshare_add(rem->mount); + ecore_event_add(E_EVENT_REMOVABLE_DEL, ev, _e_fm2_event_removable_del_free, NULL); + } + evas_stringshare_del(rem->uuid); + evas_stringshare_del(rem->label); + evas_stringshare_del(rem->mount); + free(rem); + _e_fm2_removables = evas_list_remove_list(_e_fm2_removables, l); + break; + } + } +} + +static void +_e_fm2_removable_path_mount(const char *path) +{ + E_Fm2_Removable *rem; + Evas_List *l; + + for (l = _e_fm2_removables; l; l = l->next) + { + rem = l->data; + if (!strcmp(path, rem->mount)) + { + _e_fm2_removable_dev_mount(rem->uuid); + break; + } + } +} + +static void +_e_fm2_removable_path_umount(const char *path) +{ + E_Fm2_Removable *rem; + Evas_List *l; + + for (l = _e_fm2_removables; l; l = l->next) + { + rem = l->data; + if (!strcmp(path, rem->mount)) + { + _e_fm2_removable_dev_umount(rem->uuid); + break; + } + } +} + +static void +_e_fm2_removable_dev_mount(const char *uuid) +{ + // FIXME: this is hardcoded to use pmount - maybe allow other methods? + E_Fm2_Removable *rem; + Evas_List *l; + char buf[4096]; + + for (l = _e_fm2_removables; l; l = l->next) + { + rem = l->data; + if (!strcmp(uuid, rem->uuid)) + { + rem->mounts++; + if (rem->mounts == 1) + { + Ecore_Exe *ex; + + snprintf(buf, sizeof(buf), + "pmount -A /dev/disk/by-uuid/%s", uuid); + e_util_library_path_strip(); + ex = ecore_exe_run(buf, NULL); + snprintf(buf, sizeof(buf), "EFM/%s", rem->mount); + ecore_exe_tag_set(ex, buf); + e_util_library_path_restore(); + //// FIXME: set exe child handler - if exe tag is EFM/* + //// then find efm view(s) for the mount path and + //// refresh them + } + break; + } + } +} + +static void +_e_fm2_removable_dev_umount(const char *uuid) +{ + // FIXME: this is hardcoded to use pmount - maybe allow other methods? + E_Fm2_Removable *rem; + Evas_List *l; + char buf[4096]; + + for (l = _e_fm2_removables; l; l = l->next) + { + rem = l->data; + if (!strcmp(uuid, rem->uuid)) + { + if (rem->mounts > 0) rem->mounts--; + if (rem->mounts == 0) + { + snprintf(buf, sizeof(buf), + "pumount /dev/disk/by-uuid/%s", uuid); + e_util_library_path_strip(); + ecore_exe_run(buf, NULL); + e_util_library_path_restore(); + } + break; + } + } +} + +static void +_e_fm2_removable_dev_label_set(const char *uuid, const char *label) +{ + // FIXME: save uuid -> label mapping in config +} + +static int +_e_fm2_cb_dbus_event_server_add(void *data, int ev_type, void *ev) +{ + Ecore_DBus_Event_Server_Add *event; + + event = ev; + if (event->server == _e_fm2_dbus) + { + ecore_dbus_method_name_has_owner(event->server, "org.freedesktop.Hal", + _e_fm2_cb_dbus_method_name_has_owner, + _e_fm2_cb_dbus_method_error, NULL); + } + return 1; +} + +static int +_e_fm2_cb_dbus_event_server_del(void *data, int ev_type, void *ev) +{ + Ecore_DBus_Event_Server_Del *event; + + event = ev; + if (event->server == _e_fm2_dbus) + { + while (_e_fm2_dbus_handlers) + { + if (_e_fm2_dbus_handlers->data) ecore_event_handler_del(_e_fm2_dbus_handlers->data); + _e_fm2_dbus_handlers = evas_list_remove_list(_e_fm2_dbus_handlers, _e_fm2_dbus_handlers); + } + _e_fm2_dbus = NULL; + } + return 1; +} + +static int +_e_fm2_cb_dbus_event_server_signal(void *data, int ev_type, void *ev) +{ + Ecore_DBus_Event_Signal *event; + + event = ev; + if (event->server == _e_fm2_dbus) + { + const char *bstr = "/org/freedesktop/Hal/devices/volume_uuid_"; + int blen; + + blen = strlen(bstr); + if (!strcmp(event->header.member, "DeviceAdded")) + { + printf("E FM: DBus dev add:\n %s\n", + (char *)event->args[0].value); + if (!strncmp((char *)event->args[0].value, bstr, blen)) + { + char *uuid, *p; + + uuid = strdup(((char *)event->args[0].value) + blen); + for (p = uuid; *p; p++) + { + if (*p == '_') *p = '-'; + } + _e_fm2_removable_dev_add(uuid); + free(uuid); + } + } + else if (!strcmp(event->header.member, "DeviceRemoved")) + { + printf("E FM: DBus dev del:\n %s\n", + (char *)event->args[0].value); + if (!strncmp((char *)event->args[0].value, bstr, blen)) + { + char *uuid, *p; + + uuid = strdup(((char *)event->args[0].value) + blen); + for (p = uuid; *p; p++) + { + if (*p == '_') *p = '-'; + } + _e_fm2_removable_dev_del(uuid); + free(uuid); + } + } + } + return 1; +} + +static int +_e_fm2_cb_dbus_event_child_exit(void *data, int ev_type, void *ev) +{ + Ecore_Exe_Event_Del *event; + char *path; + Evas_List *l; + + event = ev; + if (!event->exe) return 1; + if (!(ecore_exe_tag_get(event->exe) && + (!strncmp(ecore_exe_tag_get(event->exe), "EFM/", 4)))) return 1; + path = ecore_exe_tag_get(event->exe) + 4; + for (l = _e_fm2_list; l; l = l->next) + { + if (!strcmp(e_fm2_real_path_get(l->data), path)) + e_fm2_refresh(l->data); + } + return 1; +} + +static void +_e_fm2_cb_dbus_method_name_has_owner(void *data, Ecore_DBus_Method_Return *reply) +{ + unsigned int *exists; + + exists = reply->args[0].value; + if ((!exists) || (!*exists)) + { + printf("E FM: DBus No HAL\n"); + } + else + { + printf("E FM: DBus Add listener for devices\n"); + ecore_dbus_method_add_match(reply->server, + "type='signal'," + "interface='org.freedesktop.Hal.Manager'," + "sender='org.freedesktop.Hal'," + "path='/org/freedesktop/Hal/Manager'", + _e_fm2_cb_dbus_method_add_match, + _e_fm2_cb_dbus_method_error, NULL); + } +} + +static void +_e_fm2_cb_dbus_method_add_match(void *data, Ecore_DBus_Method_Return *reply) +{ + printf("E FM: DBus Should be listening for device changes!\n"); +} + +static void +_e_fm2_cb_dbus_method_error(void *data, const char *error) +{ + printf("E FM: DBus Error: %s\n", error); +} diff --git a/src/bin/e_fm.h b/src/bin/e_fm.h index 5c5cd9c20..dbdefc119 100644 --- a/src/bin/e_fm.h +++ b/src/bin/e_fm.h @@ -30,10 +30,27 @@ typedef struct _E_Fm2_Icon E_Fm2_Icon; typedef struct _E_Fm2_Icon_Info E_Fm2_Icon_Info; typedef struct _E_Fm2_Custom_File E_Fm2_Custom_File; +typedef struct _E_Fm2_Removable_Add E_Fm2_Removable_Add; +typedef struct _E_Fm2_Removable_Del E_Fm2_Removable_Del; + #else #ifndef E_FM_H #define E_FM_H +struct _E_Fm2_Removable_Add +{ + const char *uuid; + const char *label; + const char *mount; +}; + +struct _E_Fm2_Removable_Del +{ + const char *uuid; + const char *label; + const char *mount; +}; + struct _E_Fm2_Config { /* general view mode */ @@ -105,6 +122,7 @@ struct _E_Fm2_Icon_Info struct stat statinfo; unsigned char icon_type; unsigned char mount : 1; + unsigned char removable : 1; unsigned char pseudo_link : 1; unsigned char deleted : 1; unsigned char broken_link : 1; @@ -174,5 +192,8 @@ EAPI Evas_Object * void (*gen_func) (void *data, Evas_Object *obj, void *event_info), void *data, int force_gen, const char **type_ret); +extern EAPI int E_EVENT_REMOVABLE_ADD; +extern EAPI int E_EVENT_REMOVABLE_DEL; + #endif #endif diff --git a/src/bin/e_fwin.c b/src/bin/e_fwin.c index 551a1ec04..f284ab291 100644 --- a/src/bin/e_fwin.c +++ b/src/bin/e_fwin.c @@ -619,6 +619,8 @@ _e_fwin_file_open_dialog(E_Fwin *fwin, Evas_List *files, int always) ici = l->data; if ((ici->link) && (ici->mount)) e_fwin_new(fwin->win->container, ici->link, "/"); + else if ((ici->link) && (ici->removable)) + e_fwin_new(fwin->win->container, ici->link, "/"); else if (ici->link) { if (S_ISDIR(ici->statinfo.st_mode)) diff --git a/src/bin/e_zone.c b/src/bin/e_zone.c index f54693bb3..6e182ae2a 100644 --- a/src/bin/e_zone.c +++ b/src/bin/e_zone.c @@ -651,7 +651,9 @@ e_zone_exec(E_Zone *zone, const char *exe) if (!inst) return 0; } + e_util_library_path_strip(); ex = ecore_exe_pipe_run(exe, ECORE_EXE_PIPE_AUTO | ECORE_EXE_PIPE_READ | ECORE_EXE_PIPE_ERROR | ECORE_EXE_PIPE_READ_LINE_BUFFERED | ECORE_EXE_PIPE_ERROR_LINE_BUFFERED, inst); + e_util_library_path_restore(); if (!ex) { if (inst) free(inst);