heraia.c

Go to the documentation of this file.
00001 /* -*- Mode: C; tab-width: 4; indent-tabs-mode: t; c-basic-offset: 4 -*- */
00002 /*
00003  *  heraia.c
00004  *  heraia - an hexadecimal file editor and analyser based on ghex
00005  *
00006  *  (C) Copyright 2005 - 2011 Olivier Delhomme
00007  *  e-mail : heraia@delhomme.org
00008  *  URL    : http://heraia.tuxfamily.org
00009  *
00010  *  This program is free software; you can redistribute it and/or modify
00011  *  it under the terms of the GNU General Public License as published by
00012  *  the Free Software Foundation; either version 2, or  (at your option)
00013  *  any later version.
00014  *
00015  *  This program is distributed in the hope that it will be useful,
00016  *  but WITHOUT ANY WARRANTY;  without even the implied warranty of
00017  *  MERCHANTABILITY  or  FITNESS FOR A PARTICULAR PURPOSE.  See the
00018  *  GNU General Public License for more details.
00019  *
00020  *  You should have received a copy of the GNU General Public License
00021  *  along with this program; if not, write to the Free Software
00022  *  Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00023  */
00024 /** @file heraia.c
00025  * This is the main program file.
00026  * Initialization is done here and then hand is passed to gtk's main thread
00027  */
00028 /**
00029  * @author Olivier DELHOMME,
00030  *         Sébastien TRICAUD,
00031  *         Grégory AUDET,
00032  *         Aurélie DERAISME.
00033  * @version 0.1.7
00034  * @date 2005-2011
00035  */
00036 
00037 
00038 #include "heraia_types.h"
00039 
00040 
00041 static gboolean version(void);
00042 static gboolean usage(int status);
00043 static window_prop_t *init_window_properties(gint x, gint y, guint height, guint width, gboolean displayed);
00044 static heraia_struct_t *init_window_property_struct(heraia_struct_t *main_struct);
00045 static heraia_struct_t *heraia_init_main_struct(gchar *heraia_path);
00046 static HERAIA_ERROR init_heraia_plugin_system(heraia_struct_t *main_struct);
00047 static GList *init_heraia_location_list(gchar *heraia_path);
00048 static gboolean manage_command_line_options(Options *opt, int argc, char **argv);
00049 
00050 /**
00051  *  libheraia_main_struct is a global variable that points
00052  *  to the main structure and is intended for the library use ONLY !
00053  *  It should not be used anywhere else or for any other purpose
00054  */
00055 static heraia_struct_t *libheraia_main_struct = NULL;
00056 
00057 
00058 /**
00059  *  This is intended to be called by the library or any program that will use
00060  *  the library in order to get the pointer to the main structure heraia_struct_t.
00061  *  @return heraia_struct_t *, a pointer to the main structure
00062  */
00063 heraia_struct_t *get_main_struct(void)
00064 {
00065     return libheraia_main_struct;
00066 }
00067 
00068 
00069 /**
00070  *  prints program name, version, author, date and licence
00071  *  to the standard output
00072  */
00073 static gboolean version(void)
00074 {
00075     fprintf (stdout, Q_("heraia written by %s\n   %s - Version %s\n   License %s\n"), HERAIA_AUTHORS, HERAIA_DATE, HERAIA_VERSION, HERAIA_LICENSE);
00076     return TRUE;
00077 }
00078 
00079 
00080 /**
00081  *  Function that informs the user about the command line options
00082  *  available with heraia
00083  *  @param status : integer that indicate wether to display help (!=0) or
00084  *                  an error message (0)
00085  *  @return
00086  *          - TRUE -> help message has been printed
00087  *          - FALSE -> error message has been printed
00088  */
00089 static gboolean usage(int status)
00090 {
00091     if (status == 0)
00092         {
00093             fprintf (stderr, Q_("Try `heraia --help' for more information.\n"));
00094 
00095             return FALSE;
00096         }
00097     else
00098         {
00099             version();
00100             fprintf(stdout, Q_("\nheraia is a simple hexadecimal file editor and file analyser"));
00101             fprintf(stdout, Q_("\nUsage :\n  heraia [options] filename(s)\n"));
00102             fprintf(stdout, Q_("\nOptions :\n"));
00103             fprintf(stdout, Q_("  -h, --help\tThis help.\n"));
00104             fprintf(stdout, Q_("  -v, --version\tProgram version information.\n"));
00105             fprintf(stdout, Q_("  -t, --tests=TESTS\tRuns some tests.\n"));
00106             fprintf(stdout, Q_("     TESTS might be :\n"));
00107             fprintf(stdout, Q_("     %d for coverage tests\n"), COVERAGE_TESTS);
00108             fprintf(stdout, Q_("     %d for loading files tests\n"), LOADING_TESTS);
00109 
00110             return TRUE;
00111         }
00112 }
00113 
00114 
00115 /**
00116  *  Inits the properties of a window with defined values
00117  *  @param  x,y are x,y coordinates on the screen
00118  *  @param  height represents the height of the window
00119  *  @param  width represents the width of the window. x+height,y+width is
00120  *          window's right bottom corner
00121  *  @param  displayed says wether the window is displayed or not
00122  *  @return a new allocated window_prop_t * structure.
00123  */
00124 static window_prop_t *init_window_properties(gint x, gint y, guint height, guint width, gboolean displayed)
00125 {
00126     window_prop_t *window_p;
00127 
00128     /* Malloc the window properties struct */
00129     window_p = (window_prop_t *) g_malloc0(sizeof(window_prop_t));
00130 
00131     /* Sets the default values */
00132     window_p->x = x;
00133     window_p->y = y;
00134     window_p->height = height;
00135     window_p->width = width;
00136     window_p->displayed = displayed;
00137 
00138     return window_p;
00139 }
00140 
00141 
00142 /**
00143  *  Inits the window property structure
00144  *  @param main_struct : main structure
00145  *  @return main structure with an initiated window property structure
00146  */
00147 static heraia_struct_t *init_window_property_struct(heraia_struct_t *main_struct)
00148 {
00149     all_window_prop_t *win_prop = NULL;
00150     window_prop_t *about_box = NULL;
00151     window_prop_t *data_interpretor = NULL;
00152     window_prop_t *log_box = NULL;
00153     window_prop_t *main_dialog = NULL;
00154     window_prop_t *plugin_list = NULL;
00155     window_prop_t *ldt = NULL;
00156     window_prop_t *main_pref_window = NULL;
00157     window_prop_t *goto_window = NULL;
00158     window_prop_t *result_window = NULL;
00159     window_prop_t *find_window = NULL;
00160     window_prop_t *fr_window = NULL;
00161     window_prop_t *fdft_window = NULL;
00162 
00163     /* Global struct */
00164     win_prop = (all_window_prop_t *) g_malloc0(sizeof(all_window_prop_t));
00165 
00166     /* Initial states for the dialog boxes (default values) */
00167     about_box = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00168     data_interpretor = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, H_DI_DISPLAYED);
00169     log_box = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00170     main_dialog = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, TRUE);
00171     plugin_list = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00172     ldt = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00173     main_pref_window = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00174     goto_window = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00175     result_window = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00176     find_window = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00177     fr_window = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00178     fdft_window = init_window_properties(0, 0, WPT_DEFAULT_HEIGHT, WPT_DEFAULT_WIDTH, FALSE);
00179 
00180     /* Attach to the struct */
00181     win_prop->about_box = about_box;
00182     win_prop->data_interpretor = data_interpretor;
00183     win_prop->log_box = log_box;
00184     win_prop->main_dialog = main_dialog;
00185     win_prop->plugin_list = plugin_list;
00186     win_prop->ldt = ldt;
00187     win_prop->main_pref_window = main_pref_window;
00188     win_prop->goto_window = goto_window;
00189     win_prop->result_window = result_window;
00190     win_prop->find_window = find_window;
00191     win_prop->fr_window = fr_window;
00192     win_prop->fdft_window = fdft_window;
00193 
00194     /* attach it to the main struct so that it can be read everywhere */
00195     main_struct->win_prop = win_prop;
00196 
00197     return main_struct;
00198 }
00199 
00200 
00201 /**
00202  * Initialize the main structure (main_struct)
00203  * @param heraia_path is the path used to invoke heraia : '/usr/bin/heraia'
00204  *        invocation would lead to '/usr/bin'
00205  * @return a pointer to a newly initialized main structure
00206  */
00207 static heraia_struct_t *heraia_init_main_struct(gchar *heraia_path)
00208 {
00209     heraia_struct_t *main_struct = NULL;
00210     xml_t *xmls = NULL;
00211 
00212     main_struct = (heraia_struct_t *) g_malloc0(sizeof(heraia_struct_t));
00213 
00214     if (main_struct == NULL)
00215         {
00216             fprintf(stderr, Q_("Main structure could not be initialiazed !"));
00217             fprintf(stderr, Q_("Do you have a memory problem ?\n"));
00218             return NULL;
00219         }
00220 
00221     /* preference file name initialisation */
00222     main_struct->prefs = init_preference_struct(g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), "heraia", NULL), "main_preferences");
00223     verify_preference_file(main_struct->prefs);
00224 
00225     /**
00226      * First, in this early stage of the development we want to toggle debugging
00227      *  mode ON which is enabled by default in the configure.ac file !
00228      */
00229     main_struct->debug = ENABLE_DEBUG;
00230 
00231     main_struct->current_doc = NULL;
00232     main_struct->plugins_list = NULL;
00233     main_struct->location_list = init_heraia_location_list(heraia_path); /* location list initilization */
00234 
00235     /* xml_t structure initialisation */
00236     xmls = (xml_t *) g_malloc0(sizeof(xml_t));
00237     xmls->main = NULL;
00238     main_struct->xmls = xmls;
00239 
00240     /* data interpretor structure initialization */
00241     main_struct->current_DW = (data_window_t *) g_malloc0 (sizeof(data_window_t));
00242     main_struct->current_DW->diw = NULL;
00243     main_struct->current_DW->tab_displayed = 0;  /* the first tab */
00244 
00245     /* init window property structure */
00246     main_struct = init_window_property_struct(main_struct);
00247 
00248     /* documents */
00249     main_struct->documents = g_ptr_array_new();
00250 
00251     /* find and replace stuff */
00252     main_struct->find_doc = NULL;
00253     main_struct->fr_find_doc = NULL;
00254     main_struct->fr_replace_doc = NULL;
00255     main_struct->results = g_ptr_array_new();
00256     main_struct->fdft = NULL;
00257 
00258     /* init global variable for the library */
00259     libheraia_main_struct = main_struct;
00260 
00261     return main_struct;
00262 }
00263 
00264 
00265 /**
00266  *  Function that initializes the plugin system if any :
00267  *   - loads any plugin where expected to be found
00268  *   - inits the plugin window
00269  * @param main_struct : main structure (heraia_struct_t *)
00270  * @return HERAIA_NO_PLUGINS if no plugins where found or HERAIA_NOERR in
00271  *         case of no errors
00272  */
00273 static HERAIA_ERROR init_heraia_plugin_system(heraia_struct_t *main_struct)
00274 {
00275 
00276     /* Checking for plugins */
00277     if (plugin_capable() == TRUE)
00278         {
00279             log_message(main_struct, G_LOG_LEVEL_INFO, Q_("Enabling plugins"));
00280             load_plugins(main_struct);
00281 
00282             /* the plugin_list_window (here the plugins may be loaded !) */
00283             log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("Inits the plugin list window"));
00284             plugin_list_window_init_interface(main_struct);
00285 
00286             return HERAIA_NOERR;
00287         }
00288     else
00289         {
00290             log_message(main_struct, G_LOG_LEVEL_WARNING, Q_("Plugins will be disabled"));
00291             return HERAIA_NO_PLUGINS;
00292         }
00293 }
00294 
00295 
00296 /**
00297  *  Here we want to init the location list where we might look for
00298  *  in the future. These can be viewed as default paths
00299  *  @warning when adding new locations, keep in ming that the list is a
00300              prepended list in reverse order.
00301  *  @return a new allocatde GList containing all locations
00302  */
00303 static GList *init_heraia_location_list(gchar *heraia_path)
00304 {
00305     gchar *path = NULL;
00306     const gchar* const *system_dirs;
00307     guint i = 0;
00308     GList *location_list = NULL;
00309 
00310     /* Heraia's binary path */
00311     path = g_get_current_dir();
00312     location_list = g_list_prepend(location_list, path);
00313 
00314     /* System data dirs */
00315     system_dirs = g_get_system_data_dirs();
00316     i = 0;
00317     while(system_dirs[i] != NULL)
00318         {
00319             path = g_build_path(G_DIR_SEPARATOR_S, system_dirs[i], "heraia", NULL);
00320             location_list = g_list_prepend(location_list, path);
00321             i++;
00322         }
00323 
00324     /* System config dirs */
00325     system_dirs = g_get_system_config_dirs();
00326     i = 0;
00327     while(system_dirs[i] != NULL)
00328         {
00329             path = g_build_path(G_DIR_SEPARATOR_S, system_dirs[i], "heraia", NULL);
00330             location_list = g_list_prepend(location_list, path);
00331             i++;
00332         }
00333 
00334     /* The user path */
00335     path =  g_build_path(G_DIR_SEPARATOR_S, g_get_home_dir(), "heraia", NULL);
00336     location_list = g_list_prepend(location_list, path);
00337 
00338     /* A global user data path */
00339     path = g_build_path(G_DIR_SEPARATOR_S, g_get_user_data_dir(), "heraia", NULL);
00340     location_list = g_list_prepend(location_list, path);
00341 
00342     /* A global config data path */
00343     path = g_build_path(G_DIR_SEPARATOR_S, g_get_user_config_dir(), "heraia", NULL);
00344     location_list = g_list_prepend(location_list, path);
00345 
00346     /* An absolute path (from where is executed heraia itself) */
00347     path = g_build_path(G_DIR_SEPARATOR_S, heraia_path, "..", "share", "heraia", NULL);
00348     location_list = g_list_prepend(location_list, path);
00349 
00350     return location_list;
00351 }
00352 
00353 
00354 /**
00355  *  Inits internationalisation (don't know wether it works or not!)
00356  */
00357 static void init_international_languages(void)
00358 {
00359     gchar *result = NULL;
00360     gchar *codeset = NULL;
00361     gchar *text_domain = NULL;
00362 
00363     /* gtk_set_locale(); */
00364     result = bindtextdomain(GETTEXT_PACKAGE, LOCALEDIR);
00365     codeset = bind_textdomain_codeset(GETTEXT_PACKAGE, "UTF-8");
00366     text_domain = textdomain(GETTEXT_PACKAGE);
00367 
00368     if (ENABLE_DEBUG == TRUE)
00369         {
00370             fprintf(stdout, Q_("Gettext package : %s\n"), GETTEXT_PACKAGE);
00371             fprintf(stdout, Q_("Locale dir : %s\n"), LOCALEDIR);
00372             fprintf(stdout, Q_("Bindtextdomain : %s\n"), result);
00373             fprintf(stdout, Q_("Code set : %s\n"), codeset);
00374             fprintf(stdout, Q_("Text domain : %s\n"), text_domain);
00375         }
00376 }
00377 
00378 
00379 /**
00380  * Does some self tests for code coverage in heraia
00381  *
00382  * This function does some calls to functions that are not called
00383  * on a normal test procedure
00384  *
00385  * @param main_struct : main structure (heraia_struct_t *)
00386  * @return gboolean as an exit value for the program
00387  */
00388 static gboolean do_heraia_coverage_tests(heraia_struct_t *main_struct)
00389 {
00390     heraia_struct_t *tmp_struct;
00391     gboolean exit_value = FALSE;
00392 
00393     exit_value = version();
00394     exit_value = usage(0);
00395     exit_value = usage(1);
00396 
00397     tmp_struct = get_main_struct();
00398     if (tmp_struct != main_struct)
00399         {
00400             fprintf(stderr, Q_("WARNING : tmp_struct is not equal to main_struct!\n"));
00401         }
00402 
00403     exit_value = test_decode_functions();
00404     if (exit_value != TRUE)
00405         {
00406             fprintf(stderr, Q_("WARNING : Error while testing decode functions\n"));
00407         }
00408 
00409     return TRUE;
00410 }
00411 
00412 
00413 /**
00414  * Does some loading tests in heraia
00415  * @param main_struct : main structure (heraia_struct_t *)
00416  * @return gboolean as an exit value for the program
00417  */
00418 static gboolean do_heraia_loading_tests(heraia_struct_t *main_struct)
00419 {
00420     return TRUE;
00421 }
00422 
00423 
00424 /**
00425  *  Manages all the command line options and populates the
00426  *  Options *opt structure accordingly
00427  *  @param opt (Options *opt) filled here with the parameters found in **argv
00428  *  @param argc : number of command line arguments
00429  *  @param argv : array of string (char *) that contains arguments
00430  *  @return gboolean that seems to always be TRUE
00431  */
00432 static gboolean manage_command_line_options(Options *opt, int argc, char **argv)
00433 {
00434     int exit_value = TRUE;
00435     int c = 0;
00436     gchar *filename = NULL;
00437     int tests = 0;
00438 
00439     while ((c = getopt_long(argc, argv, "vht", long_options, NULL)) != -1)
00440         {
00441             switch (c)
00442                 {
00443                     case 0:         /* long options handler */
00444                         break;
00445 
00446                     case 'v':
00447                         exit_value = version();
00448                         opt->usage = TRUE;  /* We do not want to continue after */
00449                         break;
00450 
00451                     case 'h':
00452                         exit_value = usage(1);
00453                         opt->usage = TRUE;
00454                         break;
00455 
00456                     case 't':
00457                         if (optarg)
00458                             {
00459                                 if (sscanf(optarg, "%d", &tests) < 1)
00460                                     {
00461                                         /* Tests done by default */
00462                                         opt->tests = COVERAGE_TESTS;
00463                                     }
00464                                 else
00465                                     {
00466                                         opt->tests = tests;
00467                                     }
00468                             }
00469                         else
00470                             {
00471                                 opt->tests = COVERAGE_TESTS;
00472                             }
00473                          exit_value = TRUE;
00474                         break;
00475 
00476                     default:
00477                         exit_value = usage(0);
00478                         opt->usage = TRUE;
00479                 }
00480         }
00481 
00482     while (optind < argc)
00483         {
00484             filename = (char *) malloc (sizeof(char) * strlen(argv[optind]) + 1);
00485             strcpy(filename, argv[optind]);
00486             opt->filenames = g_list_prepend(opt->filenames, filename);
00487             optind++;
00488         }
00489 
00490     return exit_value;
00491 }
00492 
00493 
00494 /**
00495  * Inits the Options struct that contains all
00496  * stuff needed to managed command line options
00497  * within heraia
00498  * @return returns a newly allocated Options structure
00499  *         initialized to default values
00500  */
00501 static Options *init_options_struct(void)
00502 {
00503     Options *opt = NULL; /**< Structure to manage prgram's options */
00504 
00505     opt = (Options *) g_malloc0(sizeof(Options));
00506 
00507     opt->filenames = NULL;  /* At first we do not have any filename */
00508     opt->usage = FALSE;
00509     opt->tests = NO_TESTS;
00510 
00511     return opt;
00512 }
00513 
00514 
00515 /**
00516  *  main program
00517  *  options :
00518  *   - --version
00519  *   - --help
00520  *   - --tests
00521  */
00522 int main(int argc, char **argv)
00523 {
00524     Options *opt; /**< A structure to manage the command line options  */
00525     gboolean exit_value = TRUE;
00526     heraia_struct_t *main_struct = NULL;
00527     GList *list = NULL;
00528     gchar *heraia_path = NULL;
00529 
00530     if (argv != NULL && argv[0] != NULL)
00531         {
00532             heraia_path = g_path_get_dirname(argv[0]);
00533         }
00534     else
00535         {
00536             return -1;
00537         }
00538 
00539     init_international_languages();
00540 
00541     /* init of gtk */
00542     exit_value = gtk_init_check(&argc, &argv);
00543 
00544     opt = init_options_struct();
00545 
00546     main_struct = heraia_init_main_struct(heraia_path);
00547 
00548     libheraia_initialize();
00549 
00550     if (main_struct->debug == TRUE)
00551         {
00552             fprintf(stdout, Q_("Main struct initialized !\n"));
00553         }
00554 
00555     /* Command line options evaluation */
00556     exit_value = manage_command_line_options(opt, argc, argv);
00557 
00558     if (opt->usage != TRUE)
00559         {
00560             if (main_struct->debug == TRUE)
00561                 {
00562                     fprintf(stderr, Q_("Beginning things\n"));
00563                     libheraia_test(); /* testing libheraia */
00564                 }
00565 
00566 
00567 
00568             if (load_heraia_ui(main_struct) == TRUE)
00569                 {
00570 
00571                     log_message(main_struct, G_LOG_LEVEL_INFO, Q_("Main interface loaded"));
00572                     log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("Preference file is %s"), main_struct->prefs->filename);
00573                     log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("data interpretor's tab is %d"), main_struct->current_DW->tab_displayed);
00574 
00575                     init_heraia_plugin_system(main_struct);
00576 
00577                     if (opt->filenames != NULL)
00578                         {
00579                             list = g_list_first(opt->filenames);
00580                             while (list != NULL)
00581                                 {
00582                                     load_file_to_analyse(main_struct, list->data);
00583                                     list = g_list_next(list);
00584                                 }
00585                         }
00586 
00587                     log_message(main_struct, G_LOG_LEVEL_DEBUG, Q_("main_struct : %p"), main_struct);
00588 
00589                     init_heraia_interface(main_struct);
00590 
00591                     /* tests or main loop */
00592                     switch (opt->tests)
00593                             {
00594                                 case COVERAGE_TESTS:
00595                                     exit_value = do_heraia_coverage_tests(main_struct);
00596                                 break;
00597 
00598                                 case LOADING_TESTS:
00599                                     exit_value = do_heraia_loading_tests(main_struct);
00600                                 break;
00601 
00602                                 default:
00603                                     /* gtk main loop */
00604                                     gtk_main();
00605                                     exit_value = TRUE;
00606                             }
00607                 }
00608             else
00609                 {
00610                     fprintf(stderr, Q_("File heraia.gtkbuilder not found !\n"));
00611                     if (main_struct->debug == TRUE)
00612                         {
00613                             list = main_struct->location_list;
00614                             while (list)
00615                                 {
00616                                     /* here heraia_path is used only as a normal gchar*  */
00617                                     heraia_path = (gchar *) list->data;
00618                                     fprintf(stdout, "\t%s\n", heraia_path);
00619                                     list = g_list_next(list);
00620                                 }
00621                         }
00622                 }
00623         }
00624 
00625     libheraia_finalize();
00626 
00627     return !exit_value; /* Apparently gtk TRUE and FALSE are inverted compared to bash ! */
00628 }
Generated on Mon May 2 21:04:49 2011 for Heraia by  doxygen 1.6.3