/* * vim:ts=8:sw=3:sts=8:noexpandtab:cino=>5n-3f0^-2{2 */ #include "e.h" struct _E_Config_Dialog_Data { char *label; char *exit; char *signal; }; /* Protos */ static void *_create_data(E_Config_Dialog *cfd); static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata); static Evas_Object *_basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); static Evas_Object *_advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata); static void _dialog_resize(void *data, Evas *e, Evas_Object *obj, void *event_info); static Evas_Object *_dialog_scrolltext_create(Evas *evas, char *title, Ecore_Exe_Event_Data_Line *lines); static void _dialog_save_cb(void *data, void *data2); EAPI void e_app_error_dialog(E_Container *con, E_App_Autopsy *app) { E_Config_Dialog *cfd; E_Config_Dialog_View *v; v = E_NEW(E_Config_Dialog_View, 1); if (v) { v->create_cfdata = _create_data; v->free_cfdata = _free_data; v->basic.create_widgets = _basic_create_widgets; v->advanced.create_widgets = _advanced_create_widgets; /* Create The Dialog */ cfd = e_config_dialog_new(con, _("Application Execution Error"), "E", "_app_exec_error_exit_dialog", NULL, 0, v, app); app->error_dialog = cfd; } } static void _fill_data(E_App_Autopsy *app, E_Config_Dialog_Data *cfdata) { char buf[4096]; if (!cfdata->label) { snprintf(buf, sizeof(buf), _("%s stopped running unexpectedly."), app->app->name); cfdata->label = strdup(buf); } if ((app->del.exited) && (!cfdata->exit)) { snprintf(buf, sizeof(buf), _("An exit code of %i was returned from %s"), app->del.exit_code, app->app->exe); cfdata->exit = strdup(buf); } if ((app->del.signalled) && (!cfdata->signal)) { if (app->del.exit_signal == SIGINT) snprintf(buf, sizeof(buf), _("%s was interrupted by an Interrupt Signal"), app->app->exe); else if (app->del.exit_signal == SIGQUIT) snprintf(buf, sizeof(buf), _("%s was interrupted by a Quit Signal"), app->app->exe); else if (app->del.exit_signal == SIGABRT) snprintf(buf, sizeof(buf), _("%s was interrupted by an Abort Signal"), app->app->exe); else if (app->del.exit_signal == SIGFPE) snprintf(buf, sizeof(buf), _("%s was interrupted by a Floating Point Error"), app->app->exe); else if (app->del.exit_signal == SIGKILL) snprintf(buf, sizeof(buf), _("%s was interrupted by an Uninterruptable Kill Signal"), app->app->exe); else if (app->del.exit_signal == SIGSEGV) snprintf(buf, sizeof(buf), _("%s was interrupted by a Segmentation Fault"), app->app->exe); else if (app->del.exit_signal == SIGPIPE) snprintf(buf, sizeof(buf), _("%s was interrupted by a Broken Pipe"), app->app->exe); else if (app->del.exit_signal == SIGTERM) snprintf(buf, sizeof(buf), _("%s was interrupted by a Termination Singal"), app->app->exe); else if (app->del.exit_signal == SIGBUS) snprintf(buf, sizeof(buf), _("%s was interrupted by a Bus Error"), app->app->exe); else snprintf(buf, sizeof(buf), _("%s was interrupted by the signal number %i"), app->app->exe, app->del.exit_signal); cfdata->signal = strdup(buf); /* FIXME: Add sigchld_info stuff * app->del.data * siginfo_t * { * int si_signo; Signal number * int si_errno; An errno value * int si_code; Signal code * pid_t si_pid; Sending process ID * uid_t si_uid; Real user ID of sending process * int si_status; Exit value or signal * clock_t si_utime; User time consumed * clock_t si_stime; System time consumed * sigval_t si_value; Signal value * int si_int; POSIX.1b signal * void * si_ptr; POSIX.1b signal * void * si_addr; Memory location which caused fault * int si_band; Band event * int si_fd; File descriptor * } */ } } static void * _create_data(E_Config_Dialog *cfd) { E_Config_Dialog_Data *cfdata; E_App_Autopsy *app; app = cfd->data; cfdata = E_NEW(E_Config_Dialog_Data, 1); _fill_data(app, cfdata); return cfdata; } static void _free_data(E_Config_Dialog *cfd, E_Config_Dialog_Data *cfdata) { E_App_Autopsy *app; app = cfd->data; if (app) { app->error_dialog = NULL; if (app->error) ecore_exe_event_data_free(app->error); if (app->read) ecore_exe_event_data_free(app->read); free(app); } if (cfdata->signal) free(cfdata->signal); if (cfdata->exit) free(cfdata->exit); if (cfdata->label) free(cfdata->label); free(cfdata); } static void _dialog_resize(void *data, Evas *e, Evas_Object *obj, void *event_info) { Evas_Coord mw, mh, vw, vh, w, h; e_scrollframe_child_viewport_size_get(obj, &vw, &vh); e_widget_min_size_get(data, &mw, &mh); evas_object_geometry_get(data, NULL, NULL, &w, &h); if (vw >= mw) { if (w != vw) evas_object_resize(data, vw, h); } } static Evas_Object * _dialog_scrolltext_create(Evas *evas, char *title, Ecore_Exe_Event_Data_Line *lines) { int i; Evas_Object *obj, *os; char *text; int tlen; os = e_widget_framelist_add(evas, _(title), 0); obj = e_widget_textblock_add(evas); tlen = 0; for (i = 0; lines[i].line != NULL; i++) tlen += lines[i].size + 1; text = alloca(tlen + 1); if (text) { text[0] = 0; for (i = 0; lines[i].line != NULL; i++) { strcat(text, lines[i].line); strcat(text, "\n"); } e_widget_textblock_plain_set(obj, text); } e_widget_min_size_set(obj, 240, 120); e_widget_framelist_object_append(os, obj); return os; } static Evas_Object * _basic_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) { int error_length = 0; Evas_Object *o, *ob, *os; E_App_Autopsy *app; app = cfd->data; _fill_data(app, cfdata); o = e_widget_list_add(evas, 0, 0); ob = e_widget_label_add(evas, cfdata->label); e_widget_list_object_append(o, ob, 1, 1, 0.5); if (app->error) error_length = app->error->size; if (error_length) { os = _dialog_scrolltext_create(evas, _("Error Logs"), app->error->lines); e_widget_list_object_append(o, os, 1, 1, 0.5); } else { ob = e_widget_label_add(evas, _("There was no error message.")); e_widget_list_object_append(o, ob, 1, 1, 0.5); } ob = e_widget_button_add(evas, _("Save This Message"), "enlightenment/run", _dialog_save_cb, app, cfdata); e_widget_list_object_append(o, ob, 0, 0, 0.5); return o; } static Evas_Object * _advanced_create_widgets(E_Config_Dialog *cfd, Evas *evas, E_Config_Dialog_Data *cfdata) { int read_length = 0; int error_length = 0; Evas_Object *o, *of, *ob, *ot; E_App_Autopsy *app; app = cfd->data; _fill_data(app, cfdata); o = e_widget_list_add(evas, 0, 0); ot = e_widget_table_add(evas, 0); ob = e_widget_label_add(evas, cfdata->label); e_widget_list_object_append(o, ob, 1, 1, 0.5); if (cfdata->exit) { of = e_widget_framelist_add(evas, _("Error Information"), 0); ob = e_widget_label_add(evas, _(cfdata->exit)); e_widget_framelist_object_append(of, ob); e_widget_list_object_append(o, of, 1, 1, 0.5); } if (cfdata->signal) { of = e_widget_framelist_add(evas, _("Error Signal Information"), 0); ob = e_widget_label_add(evas, _(cfdata->signal)); e_widget_framelist_object_append(of, ob); e_widget_list_object_append(o, of, 1, 1, 0.5); } if (app->read) read_length = app->read->size; if (read_length) { of = _dialog_scrolltext_create(evas, _("Output Data"), app->read->lines); /* FIXME: Add stdout "start". */ /* FIXME: Add stdout "end". */ } else { of = e_widget_framelist_add(evas, _("Output Data"), 0); ob = e_widget_label_add(evas, _("There was no output.")); e_widget_framelist_object_append(of, ob); } e_widget_table_object_append(ot, of, 0, 0, 1, 1, 1, 1, 1, 1); if (app->error) error_length = app->error->size; if (error_length) { of = _dialog_scrolltext_create(evas, _("Error Logs"), app->error->lines); /* FIXME: Add stderr "start". */ /* FIXME: Add stderr "end". */ } else { of = e_widget_framelist_add(evas, _("Error Logs"), 0); ob = e_widget_label_add(evas, _("There was no error message.")); e_widget_framelist_object_append(of, ob); } e_widget_table_object_append(ot, of, 1, 0, 1, 1, 1, 1, 1, 1); e_widget_list_object_append(o, ot, 1, 1, 0.5); ob = e_widget_button_add(evas, _("Save This Message"), "enlightenment/run", _dialog_save_cb, app, cfdata); e_widget_list_object_append(o, ob, 0, 0, 0.5); return o; } static void _dialog_save_cb(void *data, void *data2) { E_App_Autopsy *app; E_Config_Dialog_Data *cfdata; FILE *f; char *text; char buf[1024]; char buffer[4096]; int read_length = 0; int i, tlen; app = data; cfdata = data2; snprintf(buf, sizeof(buf), "%s/%s.log", e_user_homedir_get(), app->app->name); f = fopen(buf, "w"); if (!f) return; if (cfdata->exit) { snprintf(buffer, sizeof(buffer), "Error Information:\n\t%s\n\n", cfdata->exit); fwrite(buffer, sizeof(char), strlen(buffer), f); } if (cfdata->signal) { snprintf(buffer, sizeof(buffer), "Error Signal Information:\n\t%s\n\n", cfdata->signal); fwrite(buffer, sizeof(char), strlen(buffer), f); } if (app->read) read_length = app->read->size; if (read_length) { tlen = 0; for (i = 0; app->read->lines[i].line != NULL; i++) tlen += app->read->lines[i].size + 1; text = alloca(tlen + 1); if (text) { text[0] = 0; for (i = 0; app->read->lines[i].line != NULL; i++) { strcat(text, "\t"); strcat(text, app->read->lines[i].line); strcat(text, "\n"); } snprintf(buffer, sizeof(buffer), "Output Data:\n%s\n\n", text); fwrite(buffer, sizeof(char), strlen(buffer), f); } } else { snprintf(buffer, sizeof(buffer), "Output Data:\n\tThere was no output\n\n"); fwrite(buffer, sizeof(char), strlen(buffer), f); } /* Reusing this var */ read_length = 0; if (app->error) read_length = app->error->size; if (read_length) { tlen = 0; for (i = 0; app->error->lines[i].line != NULL; i++) tlen += app->error->lines[i].size + 1; text = alloca(tlen + 1); if (text) { text[0] = 0; for (i = 0; app->error->lines[i].line != NULL; i++) { strcat(text, "\t"); strcat(text, app->error->lines[i].line); strcat(text, "\n"); } snprintf(buffer, sizeof(buffer), "Error Logs:\n%s\n", text); fwrite(buffer, sizeof(char), strlen(buffer), f); } } else { snprintf(buffer, sizeof(buffer), "Error Logs:\n\tThere was no error message\n"); fwrite(buffer, sizeof(char), strlen(buffer), f); } fclose(f); }