summaryrefslogtreecommitdiff
path: root/src/app.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/app.c')
-rw-r--r--src/app.c564
1 files changed, 564 insertions, 0 deletions
diff --git a/src/app.c b/src/app.c
new file mode 100644
index 0000000..ef62135
--- /dev/null
+++ b/src/app.c
@@ -0,0 +1,564 @@
+
+/* Chrysalide - Outil d'analyse de fichiers binaires
+ * app.c - fichier d'entrée du programme
+ *
+ * Copyright (C) 2024 Cyrille Bagard
+ *
+ * This file is part of Chrysalide.
+ *
+ * Chrysalide is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 3 of the License, or
+ * (at your option) any later version.
+ *
+ * Chrysalide is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+
+#include <assert.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <libgen.h>
+#include <string.h>
+#include <gio/gdesktopappinfo.h>
+#include <gio/gio.h>
+#include <sys/auxv.h>
+
+
+#include "app.h"
+#include "common/io.h"
+#include "common/xdg.h"
+#include "core/core.h"
+#include "core/logs.h"
+#include "gui/core/core.h"
+#include "gui/window.h"
+#include "plugins/pglist.h"
+
+
+
+/* --------------------- DEFINITION D'APPLICATION PERSONNALISEE --------------------- */
+
+
+/* Définition de l'application principale graphique (instance) */
+struct _GtkChrysalideFramework
+{
+ GtkApplication parent; /* A laisser en premier */
+
+ GtkApplicationWindow *main_window; /* Fenêtre principale */
+
+};
+
+/* Définition de l'application principale graphique (classe) */
+struct _GtkChrysalideFrameworkClass
+{
+ GtkApplicationClass parent; /* A laisser en premier */
+
+};
+
+
+/* Initialise la classe des applications majeures de Chrysalide. */
+static void gtk_chrysalide_framework_class_init(GtkChrysalideFrameworkClass *);
+
+/* Initialise une application principale pour Chrysalide. */
+static void gtk_chrysalide_framework_init(GtkChrysalideFramework *);
+
+/* Supprime toutes les références externes. */
+static void gtk_chrysalide_framework_dispose(GtkChrysalideFramework *);
+
+/* Procède à la libération totale de la mémoire. */
+static void gtk_chrysalide_framework_finalize(GtkChrysalideFramework *);
+
+
+
+/* --------------------- IMPLEMENTATION DES FONCTIONS DE CLASSE --------------------- */
+
+
+/* Réagit à l'activation de l'application. */
+static void gtk_chrysalide_framework_activate(GApplication *);
+
+
+
+/* ---------------------- POINT D'ENTREE PRINCIPAL D'EXECUTION ---------------------- */
+
+
+/* Affiche des indications quant à l'utilisation du programme. */
+static void show_chrysalide_help(const char *);
+
+/* Affiche des indications sur la version courante du programme. */
+static void show_chrysalide_version(void);
+
+/* Installe au besoin une définition locale pour le système. */
+static void ensure_wm_icon_and_name(void);
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* DEFINITION D'APPLICATION PERSONNALISEE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/* Indique le type défini pour une application principale graphique de Chrysalide. */
+G_DEFINE_TYPE(GtkChrysalideFramework, gtk_chrysalide_framework, GTK_TYPE_APPLICATION);
+
+
+/******************************************************************************
+* *
+* Paramètres : klass = classe à initialiser. *
+* *
+* Description : Initialise la classe des applications majeures de Chrysalide.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_chrysalide_framework_class_init(GtkChrysalideFrameworkClass *klass)
+{
+ GObjectClass *object; /* Autre version de la classe */
+ GApplicationClass *app; /* Version parente de la classe*/
+
+ object = G_OBJECT_CLASS(klass);
+
+ object->dispose = (GObjectFinalizeFunc/* ! */)gtk_chrysalide_framework_dispose;
+ object->finalize = (GObjectFinalizeFunc)gtk_chrysalide_framework_finalize;
+
+ app = G_APPLICATION_CLASS(klass);
+
+ app->activate = gtk_chrysalide_framework_activate;
+
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : app = instance à initialiser. *
+* *
+* Description : Initialise une application principale pour Chrysalide. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_chrysalide_framework_init(GtkChrysalideFramework *app)
+{
+ app->main_window = NULL;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : app = instance d'objet GLib à traiter. *
+* *
+* Description : Supprime toutes les références externes. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_chrysalide_framework_dispose(GtkChrysalideFramework *app)
+{
+ g_clear_object(&app->main_window);
+
+ G_OBJECT_CLASS(gtk_chrysalide_framework_parent_class)->dispose(G_OBJECT(app));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : app = instance d'objet GLib à traiter. *
+* *
+* Description : Procède à la libération totale de la mémoire. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_chrysalide_framework_finalize(GtkChrysalideFramework *app)
+{
+ G_OBJECT_CLASS(gtk_chrysalide_framework_parent_class)->finalize(G_OBJECT(app));
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Crée une nouvelle application principale pour Chrysalide. *
+* *
+* Retour : Mécanismes mis en place. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+GtkChrysalideFramework *gtk_chrysalide_framework_new(void)
+{
+ GtkChrysalideFramework *result; /* Instance à retourner */
+
+ result = g_object_new(GTK_TYPE_CHRYSALIDE_FRAMEWORK,
+ "application-id", FRAMEWORK_WINDOW_ID,
+ "flags", G_APPLICATION_DEFAULT_FLAGS,
+ NULL);
+
+ return result;
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* IMPLEMENTATION DES FONCTIONS DE CLASSE */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : app = application concernée par l'événement. *
+* *
+* Description : Réagit à l'activation de l'application. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void gtk_chrysalide_framework_activate(GApplication *app)
+{
+ GtkChrysalideFramework *real_app; /* Version réelle de l'instance*/
+
+ real_app = GTK_CHRYSALIDE_FRAMEWORK(app);
+
+ real_app->main_window = gtk_framework_window_new(GTK_APPLICATION(app));
+ g_object_ref(G_OBJECT(real_app->main_window));
+
+ gtk_window_present(GTK_WINDOW(real_app->main_window));
+
+}
+
+
+
+/* ---------------------------------------------------------------------------------- */
+/* POINT D'ENTREE PRINCIPAL D'EXECUTION */
+/* ---------------------------------------------------------------------------------- */
+
+
+/******************************************************************************
+* *
+* Paramètres : name = nom du programme en question. *
+* *
+* Description : Affiche des indications quant à l'utilisation du programme. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void show_chrysalide_help(const char *name)
+{
+ char *tmp; /* Conservation modifiable */
+ char *base; /* Version courte du nom */
+
+ tmp = strdup(name);
+
+ base = basename(tmp);
+
+ printf("\n");
+
+ printf("Usage: %s [--help] [--version]\n", base);
+ printf(" %s [args] <filename(s)...>\n", base);
+
+ free(tmp);
+
+ printf("\n");
+
+ printf("\t-h --help\t\tShow this help message.\n");
+ printf("\t-v --version\t\tDisplay the program version.\n");
+
+ printf("\n");
+
+ printf("\t-V --verbosity=level\tSet the log level (0 for all messages, %u for none).\n", LMT_COUNT);
+
+ printf("\n");
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Affiche des indications sur la version courante du programme.*
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void show_chrysalide_version(void)
+{
+ printf("\n");
+
+ printf("-o- Chrysalide r%u -o-\n", REVISION);
+ printf(_("Compiled on %s at %s\n"), __DATE__, __TIME__);
+
+ printf("\n");
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : - *
+* *
+* Description : Installe au besoin une définition locale pour le système. *
+* *
+* Retour : - *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+static void ensure_wm_icon_and_name(void)
+{
+ GDesktopAppInfo *info; /* Information du système */
+ GKeyFile *kfile; /* Définition d'application */
+ unsigned long exec_path; /* Chemin du programme */
+ char *filename; /* Nom de fichier à écrire */
+ GBytes *res; /* Données brutes d'une image */
+ gsize size; /* Taille de ces données */
+ gconstpointer data; /* Pointeur vers les données */
+ int fd; /* Flux ouvert en écriture */
+
+ /* Evaluation du besoin */
+
+ info = g_desktop_app_info_new(FRAMEWORK_WINDOW_ID ".desktop");
+
+ /**
+ * Si l'exécutable n'est pas valide (inconnu de $PATH),
+ * la variable info n'est pas initialisée.
+ */
+
+ if (info != NULL)
+ {
+ unref_object(info);
+ goto done;
+ }
+
+ /* Mise en place d'une définition d'application */
+
+ exec_path = getauxval(AT_EXECFN);
+ assert(exec_path != 0);
+
+ kfile = g_key_file_new();
+
+ g_key_file_set_string(kfile, "Desktop Entry", "Name", "Chrysalide");
+ g_key_file_set_string(kfile, "Desktop Entry", "Comment[fr]", "Cadriciel de rétronception ciblant principalement les systèmes embarqués");
+ g_key_file_set_string(kfile, "Desktop Entry", "Comment", "Reverse Engineering Framework focused on embedded systems");
+ g_key_file_set_string(kfile, "Desktop Entry", "Type", "Application");
+ g_key_file_set_string(kfile, "Desktop Entry", "Exec", (const char *)exec_path);
+ g_key_file_set_string(kfile, "Desktop Entry", "Icon", "chrysalide-logo");
+ g_key_file_set_string(kfile, "Desktop Entry", "StartupNotify", "true");
+ g_key_file_set_string(kfile, "Desktop Entry", "MimeType", "application/vnd.android.package-archive");
+
+ filename = get_xdg_data_dir("applications/re.chrysalide.framework.gui.desktop", true);
+
+ g_key_file_save_to_file(kfile, filename, NULL);
+
+ free(filename);
+
+ g_key_file_free(kfile);
+
+ /* Ecriture de l'image */
+
+ res = g_resources_lookup_data("/re/chrysalide/framework/images/chrysalide-logo.svg",
+ G_RESOURCE_LOOKUP_FLAGS_NONE, NULL);
+ assert(res != NULL);
+
+ data = g_bytes_get_data(res, &size);
+
+ filename = get_xdg_data_dir("icons/hicolor/scalable/apps/chrysalide-logo.svg", true);
+
+ fd = open(filename, O_WRONLY | O_CREAT, S_IRUSR | S_IWUSR);
+
+ if (fd == -1)
+ LOG_ERROR_N("open");
+
+ else
+ {
+ safe_write(fd, data, size);
+ close(fd);
+ }
+
+ free(filename);
+
+ g_bytes_unref(res);
+
+ /* Sortie */
+
+ done:
+
+ ;
+
+}
+
+
+/******************************************************************************
+* *
+* Paramètres : argc = nombre d'arguments dans la ligne de commande. *
+* argv = arguments de la ligne de commande. *
+* *
+* Description : Point d'entrée du programme. *
+* *
+* Retour : EXIT_SUCCESS si le prgm s'est déroulé sans encombres. *
+* *
+* Remarques : - *
+* *
+******************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int result; /* Bilan de l'exécution */
+ bool show_help; /* Affichage de l'aide ? */
+ bool show_version; /* Affichage de la version ? */
+ LogMessageType verbosity; /* Niveau de filtre de message */
+ int index; /* Indice d'argument */
+ int ret; /* Bilan d'un appel */
+ GtkChrysalideFramework *app; /* Gestion d'application GTK */
+
+ static struct option long_options[] = {
+ { "help", no_argument, NULL, 'h' },
+ { "version", no_argument, NULL, 'v' },
+ { "verbosity", required_argument, NULL, 'V' },
+ { NULL, 0, NULL, 0 }
+ };
+
+ result = EXIT_FAILURE;
+
+ /* Décodage des options */
+
+ show_help = false;
+ show_version = false;
+
+ verbosity = LMT_COUNT;
+
+ while (true)
+ {
+ ret = getopt_long(argc, argv, "hvV:", long_options, &index);
+ if (ret == -1) break;
+
+ switch (ret)
+ {
+ case 'h':
+ show_help = true;
+ break;
+
+ case 'v':
+ show_version = true;
+ break;
+
+ case 'V':
+ verbosity = strtoul(optarg, NULL, 10);
+ break;
+
+ }
+
+ }
+
+ /* Actions de base */
+
+ if (show_help)
+ {
+ show_chrysalide_help(argv[0]);
+ result = EXIT_SUCCESS;
+ goto exit;
+ }
+
+ if (show_version)
+ {
+ show_chrysalide_version();
+ result = EXIT_SUCCESS;
+ goto exit;
+ }
+
+ /* Lancement des choses sérieuses */
+
+ set_log_verbosity(verbosity);
+
+ /**
+ * Même s'il est dit que l'usage de GtkApplication permet de s'affranchir
+ * d'un appel à gtk_init(), il se trouve que la journalisation en mode
+ * graphique peut solliciter le panneau en GTK pour afficher des messages
+ * avant la mise en place de l'applicatif GTK principal :
+ *
+ * #2 0x00007ffff7b33403 in gtk_css_lookup_resolve (lookup=lookup@entry=0x7fffffff88a0, provider=provider@entry=0x0, sstyle=sstyle@entry=0x7fffe800a730, parent_style=parent_style@entry=0x0) at ../gtk/gtkcssstaticstyle.c:911
+ * #3 0x00007ffff7b3389f in gtk_css_static_style_new_compute (provider=0x0, filter=filter@entry=0x7fffffff8ea0, node=node@entry=0x0, change=<optimized out>, change@entry=0) at ../gtk/gtkcssstaticstyle.c:1026
+ * #4 0x00007ffff7b3392c in gtk_css_static_style_get_default () at ../gtk/gtkcssstaticstyle.c:711
+ * #5 0x00007ffff7b24b09 in gtk_css_node_init (cssnode=0x7fffe800a5b0) at ../gtk/gtkcssnode.c:641
+ * #6 0x00007ffff75d8dab in g_type_create_instance () at /lib/x86_64-linux-gnu/libgobject-2.0.so.0
+ * [...]
+ * #10 0x00007ffff7b3b8fa in gtk_css_widget_node_new (widget=widget@entry=0x5555555bf1b0) at ../gtk/gtkcsswidgetnode.c:160
+ * #11 0x00007ffff7ae4576 in gtk_widget_init (instance=<optimized out>, g_class=0x5555555be380) at ../gtk/gtkwidget.c:2345
+ * [...]
+ * #16 0x00007ffff73fd3f4 in get_framework_panel_singleton (...) at panels.c:329
+ * #17 0x00007ffff73fce35 in do_log_message_alt (...) at logs.c:56
+ * [...]
+ * #23 0x00007ffff74566db in init_all_plugins (load=true) at pglist.c:103
+ * #24 0x0000555555556d44 in main (argc=2, argv=0x7fffffffb568) at app.c:514
+ *
+ * L'initialisation permettant un retour de gtk_settings_get_default() non
+ * nul est ainsi forcée au plus tôt avec un appel à gtk_init() manuel.
+ */
+ gtk_init();
+
+ if (!load_core_components(ACC_GLOBAL_VARS))
+ goto exit;
+
+ if (!load_gui_components(AGC_BUFFER_FEATURES | AGC_PANELS))
+ goto exit_with_core;
+
+ init_all_plugins(true);
+
+ ensure_wm_icon_and_name();
+
+ g_set_prgname("Chrysalide");
+
+ app = gtk_chrysalide_framework_new();
+
+ result = g_application_run(G_APPLICATION(app), 0, NULL);
+
+ g_object_unref(G_OBJECT(app));
+
+ exit_all_plugins();
+
+ unload_gui_components(AGC_BUFFER_FEATURES | AGC_PANELS);
+
+ exit_with_core:
+
+ unload_core_components(ACC_GLOBAL_VARS);
+
+ exit:
+
+ return result;
+
+}