summaryrefslogtreecommitdiff
path: root/plugins/pychrysalide/pychrysa.c
diff options
context:
space:
mode:
authorCyrille Bagard <nocbos@gmail.com>2020-08-20 20:46:09 (GMT)
committerCyrille Bagard <nocbos@gmail.com>2020-08-20 20:46:09 (GMT)
commit4ea4054f07ba5fa9be2b9a61ad0ca8f1c11afbd0 (patch)
tree43612d0f0ec50410b88ed1050e8c85183b780b2e /plugins/pychrysalide/pychrysa.c
parentd8e29f090012b99c220acb9fd56fe293e29f7903 (diff)
Renamed the main file of the Python plugin.
Diffstat (limited to 'plugins/pychrysalide/pychrysa.c')
-rw-r--r--plugins/pychrysalide/pychrysa.c1030
1 files changed, 0 insertions, 1030 deletions
diff --git a/plugins/pychrysalide/pychrysa.c b/plugins/pychrysalide/pychrysa.c
deleted file mode 100644
index d1958ee..0000000
--- a/plugins/pychrysalide/pychrysa.c
+++ /dev/null
@@ -1,1030 +0,0 @@
-
-/* Chrysalide - Outil d'analyse de fichiers binaires
- * pychrysa.c - plugin permettant des extensions en Python
- *
- * Copyright (C) 2018-2019 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 Chrysalide. If not, see <http://www.gnu.org/licenses/>.
- */
-
-
-#include "pychrysa.h"
-
-
-#include <assert.h>
-#include <errno.h>
-#include <malloc.h>
-#include <pygobject.h>
-#include <stdarg.h>
-#include <stdio.h>
-#include <stdbool.h>
-#include <string.h>
-#include <unistd.h>
-
-
-#include <config.h>
-#include <i18n.h>
-#include <gleak.h>
-#include <common/cpp.h>
-#include <common/environment.h>
-#include <common/extstr.h>
-#include <core/core.h>
-#include <core/paths.h>
-#include <plugins/pglist.h>
-#include <plugins/self.h>
-
-
-#include "access.h"
-#include "constval.h"
-#include "helpers.h"
-#include "plugin.h"
-#include "star.h"
-#include "strenum.h"
-#include "struct.h"
-#include "analysis/module.h"
-#include "arch/module.h"
-#include "common/module.h"
-#include "core/module.h"
-#include "debug/module.h"
-#include "format/module.h"
-#include "glibext/module.h"
-#include "gtkext/module.h"
-#include "gui/module.h"
-#include "mangling/module.h"
-
-
-
-DEFINE_CHRYSALIDE_CONTAINER_PLUGIN("PyChrysalide", "Chrysalide bindings to Python",
- PACKAGE_VERSION, CHRYSALIDE_WEBSITE("api/python/pychrysalide"),
- NO_REQ, AL(PGA_PLUGIN_INIT, PGA_PLUGIN_EXIT, PGA_NATIVE_LOADED));
-
-
-/* Note la nature du chargement */
-static bool _standalone = true;
-
-/* Réceptacle pour le chargement forcé */
-static PyObject *_chrysalide_module = NULL;
-
-/* Conservation des informations du thread principal */
-static PyThreadState *_main_tstate = NULL;
-
-
-/* Fournit la révision du programme global. */
-static PyObject *py_chrysalide_revision(PyObject *, PyObject *);
-
-/* Fournit la version du programme global. */
-static PyObject *py_chrysalide_version(PyObject *, PyObject *);
-
-/* Fournit la version du greffon pour Python. */
-static PyObject *py_chrysalide_mod_version(PyObject *, PyObject *);
-
-/* Détermine si l'interpréteur lancé est celui pris en compte. */
-static bool is_current_abi_suitable(void);
-
-/* Définit la version attendue de GTK à charger dans Python. */
-static bool set_version_for_gtk_namespace(const char *);
-
-/* Point de sortie pour l'initialisation de Python. */
-static void PyExit_pychrysalide(void);
-
-/* Ajoute le module 'plugins' au module Python. */
-static bool add_plugin_module_to_python_module(PyObject *);
-
-/* Complète les chemins de recherches de Python. */
-static void extend_python_path(const char *);
-
-/* Charge autant de greffons composés en Python que possible. */
-static void load_python_plugins(GPluginModule *);
-
-
-
-/******************************************************************************
-* *
-* Paramètres : self = NULL car méthode statique. *
-* args = non utilisé ici. *
-* *
-* Description : Fournit la révision du programme global. *
-* *
-* Retour : Numéro de révision. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_chrysalide_revision(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Valeur à retourner */
-
-#define PY_CHRYSALIDE_REVISION_METHOD PYTHON_METHOD_DEF \
-( \
- revision, "/", \
- METH_NOARGS, py_chrysalide, \
- "Provide the revision number of Chrysalide.\n" \
- "\n" \
- "The returned value is provided as a string, for instance: 'r1665'." \
-)
-
- result = PyUnicode_FromString("r" XSTR(REVISION));
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = NULL car méthode statique. *
-* args = non utilisé ici. *
-* *
-* Description : Fournit la version du programme global. *
-* *
-* Retour : Numéro de version. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_chrysalide_version(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Valeur à retourner */
- int major; /* Numéro de version majeur */
- int minor; /* Numéro de version mineur */
- int revision; /* Numéro de révision */
- char version[16]; /* Conservation temporaire */
-
-#define PY_CHRYSALIDE_VERSION_METHOD PYTHON_METHOD_DEF \
-( \
- version, "/", \
- METH_NOARGS, py_chrysalide, \
- "Provide the version number of Chrysalide.\n" \
- "\n" \
- "The returned value is provided as a string, for instance: '1.6.65'." \
-)
-
- major = REVISION / 1000;
- minor = (REVISION - (major * 1000)) / 100;
- revision = REVISION % 100;
-
- snprintf(version, sizeof(version), "%d.%d.%d", major, minor, revision);
-
- result = PyUnicode_FromString(version);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : self = NULL car méthode statique. *
-* args = non utilisé ici. *
-* *
-* Description : Fournit la version du greffon pour Python. *
-* *
-* Retour : Numéro de version. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static PyObject *py_chrysalide_mod_version(PyObject *self, PyObject *args)
-{
- PyObject *result; /* Valeur à retourner */
- char version[16]; /* Conservation temporaire */
-
-#define PY_CHRYSALIDE_MOD_VERSION_METHOD PYTHON_METHOD_DEF \
-( \
- mod_version, "/", \
- METH_NOARGS, py_chrysalide, \
- "Provide the version number of Chrysalide module for Python.\n" \
- "\n" \
- "The returned value is provided as a string, for instance: '0.1.0'." \
-)
-
- snprintf(version, sizeof(version), "%s", _chrysalide_plugin.version);
-
- result = PyUnicode_FromString(version);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Détermine si l'interpréteur lancé est celui pris en compte. *
-* *
-* Retour : true si l'exécution peut se poursuivre, false sinon. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool is_current_abi_suitable(void)
-{
- bool result;
- int fds[2];
- int ret;
- char cmds[128];
- char content[64];
- ssize_t got;
-
-#define GRAB_ABI_FLAGS_IN_PYTHON \
- "import sys" "\n" \
- "import os" "\n" \
- "os.write(%d, bytes(sys.abiflags, 'UTF-8'))" "\n"
-
- result = false;
-
- ret = pipe(fds);
- if (ret == -1)
- {
- perror("pipe()");
- return false;
- }
-
- snprintf(cmds, sizeof(cmds), GRAB_ABI_FLAGS_IN_PYTHON, fds[1]);
-
- ret = PyRun_SimpleString(cmds);
- if (ret != 0) goto icas_exit;
-
- got = read(fds[0], content, sizeof(content));
- if (got < 0)
- {
- perror("read()");
- goto icas_exit;
- }
-
- content[got] = '\0';
-
- result = (strcmp(content, LIBPYTHON_ABI_FLAGS) == 0);
-
- icas_exit:
-
- if (!result)
- PyErr_SetString(PyExc_SystemError, "the ABI flags of the current interpreter do not match " \
- "the ones of the Python library used during the module compilation.");
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : version = idenfiant de la version de GTK à stipuler. *
-* *
-* Description : Définit la version attendue de GTK à charger dans Python. *
-* *
-* Retour : Bilan de l'opération. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool set_version_for_gtk_namespace(const char *version)
-{
- bool result; /* Bilan à retourner */
- PyObject *gi_mod; /* Module Python-GObject */
- PyObject *args; /* Arguments à fournir */
-
- result = false;
-
- /**
- * On cherche ici à éviter le message suivant si on charge 'gi.repository.Gtk' directement :
- *
- *
- * PyGIWarning: Gtk was imported without specifying a version first. \
- * Use gi.require_version('Gtk', '3.0') before import to ensure that the right version gets loaded.
- *
- */
-
- gi_mod = PyImport_ImportModule("gi");
-
- if (gi_mod != NULL)
- {
- args = Py_BuildValue("ss", "Gtk", version);
-
- run_python_method(gi_mod, "require_version", args);
-
- result = (PyErr_Occurred() == NULL);
-
- Py_DECREF(args);
- Py_DECREF(gi_mod);
-
- }
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Point de sortie pour l'initialisation de Python. *
-* *
-* Retour : ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void PyExit_pychrysalide(void)
-{
- assert(_standalone);
-
- extern void set_current_project(void *project);
-
- set_current_project(NULL);
-
-#ifdef TRACK_GOBJECT_LEAKS
- remember_gtypes_for_leaks();
-#endif
-
- exit_all_plugins();
-
- unload_all_core_components(true);
-
-#ifdef TRACK_GOBJECT_LEAKS
- dump_remaining_gtypes();
-#endif
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : super = module dont la définition est à compléter. *
-* *
-* Description : Ajoute le module 'plugins' au module Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static bool add_plugin_module_to_python_module(PyObject *super)
-{
- bool result; /* Bilan à retourner */
- PyObject *module; /* Sous-module mis en place */
-
-#define PYCHRYSALIDE_PLUGINS_DOC \
- "Home for all plugins without another home."
-
- static PyModuleDef py_chrysalide_deguard_module = {
-
- .m_base = PyModuleDef_HEAD_INIT,
-
- .m_name = "pychrysalide.plugins",
- .m_doc = PYCHRYSALIDE_PLUGINS_DOC,
-
- .m_size = -1,
-
- };
-
- result = false;
-
- module = build_python_module(super, &py_chrysalide_deguard_module);
-
- result = (module != NULL);
-
- assert(result);
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Point d'entrée pour l'initialisation de Python. *
-* *
-* Retour : ? *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-#define PYCHRYSALIDE_DOC \
- "PyChrysalide is a module containing Chrysalide's features and designed for Python users.\n" \
- "\n" \
- "The whole API is defined in a single library named 'pychrysalide.so' and can be used in two ways:\n" \
- "* either from the Chrysalide's GUI, by registering hooks or GLib signals;\n" \
- "* or from a shell command line, by setting PYTHONPATH to point to the directory containing the library.\n" \
- "\n" \
- "In both cases, this is a good start point to have a look at already existing plugins to quickly learn " \
- "how the API works.\n" \
- "\n" \
- "These plugins are located in the 'plugins/python' directory."
-
-PyMODINIT_FUNC PyInit_pychrysalide(void)
-{
- PyObject *result; /* Module Python à retourner */
- bool status; /* Bilan des inclusions */
- int ret; /* Bilan de préparatifs */
- GPluginModule *self; /* Représentation interne */
- PluginStatusFlags self_flags; /* Fanions à mettre à jour */
-
- static PyMethodDef py_chrysalide_methods[] = {
- PY_CHRYSALIDE_REVISION_METHOD,
- PY_CHRYSALIDE_VERSION_METHOD,
- PY_CHRYSALIDE_MOD_VERSION_METHOD,
- { NULL }
- };
-
- static PyModuleDef py_chrysalide_module = {
-
- .m_base = PyModuleDef_HEAD_INIT,
-
- .m_name = "pychrysalide",
- .m_doc = PYCHRYSALIDE_DOC,
-
- .m_size = -1,
-
- .m_methods = py_chrysalide_methods
-
- };
-
- /**
- * Vérification préalable : dans le cas où on est embarqué directement dans
- * un interpréteur Python, le module se charge et termine par charger à leur
- * tour les différentes extensions trouvées, via load_remaning_plugins() puis
- * chrysalide_plugin_on_native_loaded().
- *
- * Lesquelles vont très probablement charger le module pychrysalide.
- *
- * Comme le chargement de ce dernier n'est alors pas encore terminé,
- * Python va relancer cette procédure, et register_access_to_python_module()
- * va détecter un doublon.
- */
-
- result = get_access_to_python_module(py_chrysalide_module.m_name);
-
- if (result != NULL)
- {
- Py_INCREF(result);
- return result;
- }
-
- if (!is_current_abi_suitable())
- goto exit;
-
- if (pygobject_init(-1, -1, -1) == NULL)
- {
- PyErr_SetString(PyExc_SystemError, "unable to init GObject in Python.");
- goto exit;
- }
-
- if (!set_version_for_gtk_namespace("3.0"))
- goto exit;
-
- if (!load_all_core_components(true))
- {
- PyErr_SetString(PyExc_SystemError, "unable to load all basic components.");
- goto exit;
- }
-
- /* Mise en place des fonctionnalités offertes */
-
- result = PyModule_Create(&py_chrysalide_module);
-
- register_access_to_python_module(py_chrysalide_module.m_name, result);
-
- status = true;
-
- if (status) status = add_features_module(result);
-
- if (status) add_plugin_module_to_python_module(result);
-
- if (status) status = add_analysis_module(result);
- if (status) status = add_arch_module(result);
- if (status) status = add_common_module(result);
- if (status) status = add_core_module(result);
- if (status) status = add_debug_module(result);
- if (status) status = add_format_module(result);
- if (status) status = add_glibext_module(result);
- if (status) status = add_gtkext_module(result);
- if (status) status = add_gui_module(result);
- if (status) status = add_mangling_module(result);
-
- if (status) status = ensure_python_plugin_module_is_registered();
- if (status) status = ensure_python_py_constval_is_registered();
- if (status) status = ensure_python_string_enum_is_registered();
- if (status) status = ensure_python_py_struct_is_registered();
-
- if (status) status = populate_analysis_module();
- if (status) status = populate_arch_module();
- if (status) status = populate_common_module();
- if (status) status = populate_core_module();
- if (status) status = populate_debug_module();
- if (status) status = populate_format_module();
- if (status) status = populate_glibext_module();
- if (status) status = populate_gtkext_module();
- if (status) status = populate_gui_module();
- if (status) status = populate_mangling_module();
-
- if (!status)
- {
- PyErr_SetString(PyExc_SystemError, "failed to load all PyChrysalide components.");
- Py_DECREF(result);
- result = NULL;
- goto exit;
- }
-
- if (_standalone)
- {
- ret = Py_AtExit(PyExit_pychrysalide);
-
- if (ret == -1)
- {
- PyErr_SetString(PyExc_SystemError, "failed to register a cleanup function.");
- Py_DECREF(result);
- result = NULL;
- goto exit;
- }
-
- /**
- * Comme les sources locales sont prioritaires, le fichier "core/global.h"
- * du greffon masque la fonction suivante, issue du corps principal du
- * programme.
- *
- * On la déclare donc à la main.
- */
- extern void set_batch_mode(void);
-
- set_batch_mode();
-
- init_all_plugins(false);
-
- lock_plugin_list_for_reading();
-
- self = get_plugin_by_name("PyChrysalide", NULL);
- assert(self != NULL);
-
- self_flags = g_plugin_module_get_flags(self);
- self_flags &= ~(PSF_FAILURE | PSF_LOADED);
- self_flags |= (status ? PSF_LOADED : PSF_FAILURE);
-
- g_plugin_module_override_flags(self, self_flags);
-
- unlock_plugin_list_for_reading();
-
- load_remaning_plugins();
-
- /**
- * On laisse fuir ici la référence sur self afin d'avoir
- * l'assurance que le greffon se déchargera toujours en dernier.
- *
- * La fuite mémoire est au final évitée dans PyExit_pychrysalide().
- */
-
- }
-
- exit:
-
- if (result == NULL && !_standalone)
- log_pychrysalide_exception("Loading failed");
-
- return result;
-
-}
-
-/******************************************************************************
-* *
-* Paramètres : path = chemin supplémentaire pour l'espace de recherche. *
-* *
-* Description : Complète les chemins de recherches de Python. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void extend_python_path(const char *path)
-{
- PyObject *list; /* Liste de chemins à compléter*/
- PyObject *new; /* Nouveau chemin à intégrer */
-
- list = PySys_GetObject("path");
- assert(list != NULL);
-
- new = PyUnicode_FromString(path);
- assert(new != NULL);
-
- PyList_Append(list, new);
-
- Py_DECREF(new);
-
- add_to_env_var("PYTHONPATH", path, ":");
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = instance représentant le greffon Python d'origine. *
-* *
-* Description : Charge autant de greffons composés en Python que possible. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-static void load_python_plugins(GPluginModule *plugin)
-{
-#ifdef DISCARD_LOCAL
- char *edir; /* Répertoire de base effectif */
-#endif
- DIR *dir; /* Répertoire à parcourir */
- char *paths; /* Emplacements de greffons */
- char *save; /* Sauvegarde pour ré-entrance */
- char *path; /* Chemin à fouiller */
- struct dirent *entry; /* Elément trouvé */
- char *modname; /* Nom du module pour Python */
- char *filename; /* Chemin d'accès reconstruit */
- GPluginModule *pyplugin; /* Lien vers un grffon Python */
-
- /* Définition des zones d'influence */
-
-#ifndef DISCARD_LOCAL
-
- extend_python_path(PACKAGE_SOURCE_DIR G_DIR_SEPARATOR_S "plugins" G_DIR_SEPARATOR_S "python");
-
-#else
-
- edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python");
- dir = opendir(edir);
- free(edir);
-
- if (dir != NULL)
- {
- closedir(dir);
-
- edir = get_effective_directory(PLUGINS_DATA_DIR G_DIR_SEPARATOR_S "python");
- extend_python_path(edir);
- free(edir);
-
- }
-
-#endif
-
- g_plugin_module_log_variadic_message(plugin, LMT_INFO,
- _("PYTHONPATH environment variable set to '%s'"),
- getenv("PYTHONPATH"));
-
- /* Chargements des extensions Python */
-
- paths = get_env_var("PYTHONPATH");
-
- save = NULL; /* gcc... */
-
- for (path = strtok_r(paths, ":", &save);
- path != NULL;
- path = strtok_r(NULL, ":", &save))
- {
- dir = opendir(path);
- if (dir == NULL)
- {
- perror("opendir");
- continue;
- }
-
- g_plugin_module_log_variadic_message(plugin, LMT_INFO,
- _("Looking for Python plugins in '%s'..."),
- path);
-
- while (1)
- {
- errno = 0;
-
- entry = readdir(dir);
-
- if (entry == NULL)
- {
- if (errno != 0)
- perror("readdir");
-
- break;
-
- }
-
- if (entry->d_type != DT_DIR) continue;
- if (entry->d_name[0] == '.') continue;
-
- modname = strdup(entry->d_name);
- modname = stradd(modname, ".");
- modname = stradd(modname, "__init__");
-
- filename = strdup(path);
- filename = stradd(filename, G_DIR_SEPARATOR_S);
- filename = stradd(filename, entry->d_name);
-
- pyplugin = g_python_plugin_new(modname, filename);
-
- if (pyplugin == NULL)
- g_plugin_module_log_variadic_message(plugin, LMT_ERROR,
- _("No suitable Python plugin found in '%s'"),
- filename);
- else
- {
- g_plugin_module_log_variadic_message(plugin, LMT_PROCESS,
- _("Loaded the Python plugin found in the '<b>%s</b>' directory"),
- filename);
-
- /**
- * Comme le greffon n'est pas passé par la résolution des dépendances,
- * on simule l'effet attendu.
- */
- g_object_ref(G_OBJECT(plugin));
-
- _register_plugin(pyplugin);
-
- }
-
- free(filename);
- free(modname);
-
- }
-
- closedir(dir);
-
- }
-
- free(paths);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* *
-* Description : Prend acte du chargement du greffon. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-G_MODULE_EXPORT bool chrysalide_plugin_init(GPluginModule *plugin)
-{
- bool result; /* Bilan à retourner */
- int ret; /* Bilan de préparatifs */
-
- _standalone = false;
-
- /* Chargement du module pour Python */
-
- ret = PyImport_AppendInittab("pychrysalide", &PyInit_pychrysalide);
-
- if (ret == -1)
- {
- log_plugin_simple_message(LMT_ERROR, _("Can not extend the existing table of Python built-in modules."));
- result = false;
- goto cpi_done;
- }
-
- Py_Initialize();
-
- PyEval_InitThreads();
-
- PySys_SetArgv(0, (wchar_t *[]) { NULL });
-
- _chrysalide_module = PyImport_ImportModule("pychrysalide");
-
- /**
- * Pour mémoire, une situation concrête conduisant à un échec :
- * le paquet python3-gi-dbg n'est pas installé alors que le
- * programme est compilé en mode débogage.
- *
- * Dans ce cas, pygobject_init(-1, -1, -1) échoue, et Py_Initialize()
- * le laisse rien filtrer...
- *
- * En mode autonome, le shell Python remonte bien l'erreur par contre.
- */
-
- result = (_chrysalide_module != NULL);
-
- _main_tstate = PyThreadState_Get();
-
- PyEval_ReleaseLock();
-
- cpi_done:
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* *
-* Description : Prend acte du déchargement du greffon. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-G_MODULE_EXPORT void chrysalide_plugin_exit(GPluginModule *plugin)
-{
- clear_all_accesses_to_python_modules();
-
- Py_XDECREF(_chrysalide_module);
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : plugin = greffon à manipuler. *
-* action = type d'action attendue. *
-* *
-* Description : Accompagne la fin du chargement des modules natifs. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-G_MODULE_EXPORT void chrysalide_plugin_on_native_loaded(GPluginModule *plugin, PluginAction action)
-{
- PyThreadState *tstate; /* Contexte d'environnement */
-
- if (!_standalone)
- {
- tstate = get_pychrysalide_main_tstate();
- PyEval_RestoreThread(tstate);
- }
-
- load_python_plugins(plugin);
-
- if (!_standalone)
- PyEval_SaveThread();
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : - *
-* *
-* Description : Fournit les informations du thread principal. *
-* *
-* Retour : Indications utiles à Python. *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-PyThreadState *get_pychrysalide_main_tstate(void)
-{
- PyThreadState *result; /* Indications à retourner */
-
- result = _main_tstate;
-
- return result;
-
-}
-
-
-/******************************************************************************
-* *
-* Paramètres : prefix = message d'introduction à faire apparaître à l'écran.*
-* *
-* Description : Présente dans le journal une exception survenue. *
-* *
-* Retour : - *
-* *
-* Remarques : - *
-* *
-******************************************************************************/
-
-void log_pychrysalide_exception(const char *prefix, ...)
-{
- va_list ap; /* Compléments argumentaires */
- char *msg; /* Message complet à imprimer */
- PyObject *err_type; /* Type d'erreur Python */
- PyObject *err_value; /* Instance Python d'erreur */
- PyObject *err_traceback; /* Trace Python associée */
- PyObject *err_string; /* Description Python d'erreur */
- const char *err_msg; /* Représentation humaine */
-
- if (PyErr_Occurred())
- {
- /* Base de la communication */
-
- va_start(ap, prefix);
-
- vasprintf(&msg, prefix, ap);
-
- va_end(ap);
-
- /* Détails complémentaires */
-
- PyErr_Fetch(&err_type, &err_value, &err_traceback);
-
- PyErr_NormalizeException(&err_type, &err_value, &err_traceback);
-
- if (err_traceback == NULL)
- {
- err_traceback = Py_None;
- Py_INCREF(err_traceback);
- }
-
- PyException_SetTraceback(err_value, err_traceback);
-
- if (err_value == NULL)
- msg = stradd(msg, _(": no extra information is provided..."));
-
- else
- {
- err_string = PyObject_Str(err_value);
- err_msg = PyUnicode_AsUTF8(err_string);
-
- msg = stradd(msg, ": ");
- msg = stradd(msg, err_msg);
-
- Py_DECREF(err_string);
-
- }
-
- /**
- * Bien que la documentation précise que la fonction PyErr_Fetch()
- * transfère la propritété des éléments retournés, la pratique
- * montre que le programme plante à la terminaison en cas d'exception.
- *
- * C'est par exemple le cas quand un greffon Python ne peut se lancer
- * correctement ; l'exception est alors levée à partir de la fonction
- * g_python_plugin_new() et le plantage intervient en sortie d'exécution,
- * au moment de la libération de l'extension Python :
- *
- * ==14939== Jump to the invalid address stated on the next line
- * ==14939== at 0x1A8FCBC9: ???
- * ==14939== by 0x53DCDB2: g_object_unref (in /usr/lib/x86_64-linux-gnu/libgobject-2.0.so.0.5800.3)
- * ==14939== by 0x610F834: on_plugin_ref_toggle (pglist.c:370)
- * ==14939== by 0x610F31A: exit_all_plugins (pglist.c:153)
- * ==14939== by 0x10AD19: main (main.c:440)
- * ==14939== Address 0x1a8fcbc9 is not stack'd, malloc'd or (recently) free'd
- *
- * Curieusement, un appel à PyErr_PrintEx(1) corrige l'effet, alors qu'un
- * appel à PyErr_PrintEx(0) ne change rien.
- *
- * La seule différence de l'instruction set_sys_last_vars réside en quelques
- * lignes dans le code de l'interpréteur Python :
- *
- * if (set_sys_last_vars) {
- * _PySys_SetObjectId(&PyId_last_type, exception);
- * _PySys_SetObjectId(&PyId_last_value, v);
- * _PySys_SetObjectId(&PyId_last_traceback, tb);
- * }
- *
- * L'explication n'est pas encore déterminé : bogue dans Chrysalide ou dans Python ?
- * L'ajout des éléments dans le dictionnaire du module sys ajoute une référence
- * à ces éléments.
- *
- * On reproduit ici le comportement du code correcteur avec PySys_SetObject().
- */
-
- PySys_SetObject("last_type", err_type);
- PySys_SetObject("last_value", err_value);
- PySys_SetObject("last_traceback", err_traceback);
-
- Py_XDECREF(err_traceback);
- Py_XDECREF(err_value);
- Py_XDECREF(err_type);
-
- log_plugin_simple_message(LMT_ERROR, msg);
-
- free(msg);
-
- }
-
-}