Main Page   Modules   Alphabetical List   Data Structures   File List   Data Fields   Globals  

src/main/module.c

Go to the documentation of this file.
00001 /*
00002  * "$Id: module.c,v 1.24 2004/04/25 15:12:06 rleigh Exp $"
00003  *
00004  *   libgimpprint module loader - load modules with libltdl/libdl.
00005  *
00006  *   Copyright 2002 Roger Leigh (rleigh@debian.org)
00007  *
00008  *   This program is free software; you can redistribute it and/or modify it
00009  *   under the terms of the GNU General Public License as published by the Free
00010  *   Software Foundation; either version 2 of the License, or (at your option)
00011  *   any later version.
00012  *
00013  *   This program is distributed in the hope that it will be useful, but
00014  *   WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
00015  *   or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
00016  *   for more details.
00017  *
00018  *   You should have received a copy of the GNU General Public License
00019  *   along with this program; if not, write to the Free Software
00020  *   Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
00021  */
00022 
00023 #ifdef HAVE_CONFIG_H
00024 #include <config.h>
00025 #endif
00026 #include <gimp-print/gimp-print.h>
00027 #include "gimp-print-internal.h"
00028 #include <gimp-print/gimp-print-intl-internal.h>
00029 #include <stdio.h>
00030 #include <stdlib.h>
00031 #include <string.h>
00032 #include <libgen.h>
00033 #include <errno.h>
00034 #include <unistd.h>
00035 
00036 
00037 typedef struct stpi_internal_module_class
00038 {
00039   stp_module_class_t class;
00040   const char *description;
00041 } stpi_internal_module_class_t;
00042 
00043 
00044 static void module_list_freefunc(void *item);
00045 static int stp_module_register(stp_module_t *module);
00046 #ifdef USE_DLOPEN
00047 static void *stp_dlsym(void *handle, const char *symbol, const char *modulename);
00048 #endif
00049 
00050 static const stpi_internal_module_class_t module_classes[] =
00051   {
00052     {STP_MODULE_CLASS_MISC, N_("Miscellaneous (unclassified)")},
00053     {STP_MODULE_CLASS_FAMILY, N_("Family driver")},
00054     {STP_MODULE_CLASS_COLOR, N_("Color conversion module")},
00055     {STP_MODULE_CLASS_DITHER, N_("Dither algorithm")},
00056     {STP_MODULE_CLASS_INVALID, NULL} /* Must be last */
00057   };
00058 
00059 #if !defined(USE_LTDL) && !defined(USE_DLOPEN)
00060 extern stp_module_t print_canon_LTX_stp_module_data;
00061 extern stp_module_t print_escp2_LTX_stp_module_data;
00062 extern stp_module_t print_lexmark_LTX_stp_module_data;
00063 extern stp_module_t print_pcl_LTX_stp_module_data;
00064 extern stp_module_t print_ps_LTX_stp_module_data;
00065 extern stp_module_t print_olympus_LTX_stp_module_data;
00066 extern stp_module_t print_raw_LTX_stp_module_data;
00067 extern stp_module_t color_traditional_LTX_stp_module_data;
00068 
00069 /*
00070  * A list of modules, for use when the modules are linked statically.
00071  */
00072 static stp_module_t *static_modules[] =
00073   {
00074     &print_ps_LTX_stp_module_data,
00075     &print_canon_LTX_stp_module_data,
00076     &print_escp2_LTX_stp_module_data,
00077     &print_pcl_LTX_stp_module_data,
00078     &print_lexmark_LTX_stp_module_data,
00079     &print_olympus_LTX_stp_module_data,
00080     &print_raw_LTX_stp_module_data,
00081     &color_traditional_LTX_stp_module_data,
00082     NULL
00083   };
00084 #endif
00085 
00086 static stp_list_t *module_list = NULL;
00087 
00088 
00089 /*
00090  * Callback for removing a module from stp_module_list.
00091  */
00092 static void
00093 module_list_freefunc(void *item /* module to remove */)
00094 {
00095   stp_module_t *module = (stp_module_t *) item;
00096   if (module && module->fini) /* Call the module exit function */
00097     module->fini();
00098 #if defined(USE_LTDL) || defined(USE_DLOPEN)
00099   DLCLOSE(module->handle); /* Close the module if it's not static */
00100 #endif
00101 }
00102 
00103 
00104 /*
00105  * Load all available modules.  Return nonzero on failure.
00106  */
00107 int stp_module_load(void)
00108 {
00109   /* initialise libltdl */
00110 #ifdef USE_LTDL
00111   static int ltdl_is_initialised = 0;        /* Is libltdl initialised? */
00112 #endif
00113   static int module_list_is_initialised = 0; /* Is the module list initialised? */
00114 #if defined(USE_LTDL) || defined(USE_DLOPEN)
00115   stp_list_t *dir_list;                      /* List of directories to scan */
00116   stp_list_t *file_list;                     /* List of modules to open */
00117   stp_list_item_t *file;                     /* Pointer to current module */
00118 #endif
00119 
00120 #ifdef USE_LTDL
00121   if (!ltdl_is_initialised)
00122     {
00123       if (lt_dlinit())
00124         {
00125           stp_erprintf("Error initialising libltdl: %s\n", DLERROR());
00126           return 1;
00127         }
00128       ltdl_is_initialised = 1;
00129     }
00130   /* set default search paths */
00131   lt_dladdsearchdir(PKGMODULEDIR);
00132 #endif
00133 
00134   /* initialise module_list */
00135   if (!module_list_is_initialised)
00136     {
00137       if (!(module_list = stp_list_create()))
00138         return 1;
00139       stp_list_set_freefunc(module_list, module_list_freefunc);
00140       module_list_is_initialised = 1;
00141     }
00142 
00143   /* search for available modules */
00144 #if defined (USE_LTDL) || defined (USE_DLOPEN)
00145   if (!(dir_list = stp_list_create()))
00146     return 1;
00147   stp_list_set_freefunc(dir_list, stp_list_node_free_data);
00148   if (getenv("STP_MODULE_PATH"))
00149     {
00150       stp_path_split(dir_list, getenv("STP_MODULE_PATH"));
00151     }
00152   else
00153     {
00154 #ifdef USE_LTDL
00155       stp_path_split(dir_list, getenv("LTDL_LIBRARY_PATH"));
00156       stp_path_split(dir_list, lt_dlgetsearchpath());
00157 #else
00158       stp_path_split(dir_list, PKGMODULEDIR);
00159 #endif
00160     }
00161 #ifdef USE_LTDL
00162   file_list = stp_path_search(dir_list, ".la");
00163 #else
00164   file_list = stp_path_search(dir_list, ".so");
00165 #endif
00166   stp_list_destroy(dir_list);
00167 
00168   /* load modules */
00169   file = stp_list_get_start(file_list);
00170   while (file)
00171     {
00172       stp_module_open((const char *) stp_list_item_get_data(file));
00173       file = stp_list_item_next(file);
00174     }
00175 
00176   stp_list_destroy(file_list);
00177 #else /* use a static module list */
00178   {
00179     int i=0;
00180     while (static_modules[i])
00181       {
00182         stp_module_register(static_modules[i]);
00183         i++;
00184       }
00185   }
00186 #endif
00187   return 0;
00188   }
00189 
00190 
00191 /*
00192  * Unload all modules and clean up.
00193  */
00194 int
00195 stp_module_exit(void)
00196 {
00197   /* destroy the module list (modules unloaded by callback) */
00198   if (module_list)
00199     stp_list_destroy(module_list);
00200   /* shut down libltdl (forces close of any unclosed modules) */
00201 #ifdef USE_LTDL
00202   return lt_dlexit();
00203 #else
00204   return 0;
00205 #endif
00206 }
00207 
00208 
00209 /*
00210  * Find all modules in a given class.
00211  */
00212 stp_list_t *
00213 stp_module_get_class(stp_module_class_t class /* Module class */)
00214 {
00215   stp_list_t *list;                           /* List to return */
00216   stp_list_item_t *ln;                        /* Module to check*/
00217 
00218   list = stp_list_create(); /* No freefunc, so it can be destroyed
00219                                without unloading any modules! */
00220   if (!list)
00221     return NULL;
00222 
00223   ln = stp_list_get_start(module_list);
00224   while (ln)
00225     {
00226       /* Add modules of the same class to our list */
00227       if (((stp_module_t *) stp_list_item_get_data(ln))->class == class)
00228         stp_list_item_create(list, NULL, stp_list_item_get_data(ln));
00229       ln = stp_list_item_next(ln);
00230     }
00231   return list;
00232 }
00233 
00234 
00235 /*
00236  * Open a module.
00237  */
00238 int
00239 stp_module_open(const char *modulename /* Module filename */)
00240 {
00241 #if defined(USE_LTDL) || defined(USE_DLOPEN)
00242 #ifdef USE_LTDL
00243   lt_dlhandle module;                  /* Handle for module */
00244 #else
00245   void *module;                        /* Handle for module */
00246 #endif
00247   stp_module_version_t *version;       /* Module version */
00248   stp_module_t *data;                  /* Module data */
00249   stp_list_item_t *reg_module;         /* Pointer to module list nodes */
00250   int error = 0;                       /* Error status */
00251 
00252   stp_deprintf(STP_DBG_MODULE, "stp-module: open: %s\n", modulename);
00253   while(1)
00254     {
00255       module = DLOPEN(modulename);
00256       if (!module)
00257         break;
00258 
00259       /* check version is valid */
00260       version = (stp_module_version_t *) DLSYM(module, "stp_module_version");
00261       if (!version)
00262         break;
00263       if (version->major != 1 && version->minor < 0)
00264         break;
00265 
00266       data = (void *) DLSYM(module, "stp_module_data");
00267       if (!data)
00268         break;
00269       data->handle = module; /* store module handle */
00270 
00271       /* check same module isn't already loaded */
00272       reg_module = stp_list_get_start(module_list);
00273       while (reg_module)
00274         {
00275           if (!strcmp(data->name, ((stp_module_t *)
00276                                    stp_list_item_get_data(reg_module))->name) &&
00277               data->class == ((stp_module_t *)
00278                               stp_list_item_get_data(reg_module))->class)
00279             {
00280               stp_deprintf(STP_DBG_MODULE,
00281                             "stp-module: reject duplicate: %s\n",
00282                             data->name);
00283               error = 1;
00284               break;
00285             }
00286           reg_module = stp_list_item_next(reg_module);
00287         }
00288       if (error)
00289         break;
00290 
00291       /* Register the module */
00292       if (stp_module_register(data))
00293         break;
00294 
00295       return 0;
00296     }
00297 
00298   if (module)
00299     DLCLOSE(module);
00300 #endif
00301   return 1;
00302 }
00303 
00304 
00305 /*
00306  * Register a loaded module.
00307  */
00308 static int stp_module_register(stp_module_t *module /* Module to register */)
00309 {
00310   /* Add to the module list */
00311   if (stp_list_item_create(module_list, NULL, module))
00312     return 1;
00313 
00314   stp_deprintf(STP_DBG_MODULE, "stp-module: register: %s\n", module->name);
00315   return 0;
00316 }
00317 
00318 
00319 /*
00320  * Initialise all loaded modules
00321  */
00322 int stp_module_init(void)
00323 {
00324   stp_list_item_t *module_item; /* Module list pointer */
00325   stp_module_t *module;         /* Module to initialise */
00326 
00327   module_item = stp_list_get_start(module_list);
00328   while (module_item)
00329     {
00330       module = (stp_module_t *) stp_list_item_get_data(module_item);
00331       if (module)
00332         {
00333           stp_deprintf(STP_DBG_MODULE, "stp-module-init: %s\n", module->name);
00334           /* Initialise module */
00335           if (module->init && module->init())
00336             {
00337               stp_deprintf(STP_DBG_MODULE,
00338                            "stp-module-init: %s: Module init failed\n",
00339                            module->name);
00340             }
00341         }
00342       module_item = stp_list_item_next(module_item);
00343     }
00344   return 0;
00345 }
00346 
00347 
00348 
00349 /*
00350  * Close a module.
00351  */
00352 int
00353 stp_module_close(stp_list_item_t *module /* Module to close */)
00354 {
00355   return stp_list_item_destroy(module_list, module);
00356 }
00357 
00358 
00359 /*
00360  * If using dlopen, add modulename_LTX_ to symbol name
00361  */
00362 #ifdef USE_DLOPEN
00363 static void *stp_dlsym(void *handle,           /* Module */
00364                        const char *symbol,     /* Symbol name */
00365                        const char *modulename) /* Module name */
00366 {
00367   int len;                                     /* Length of string */
00368   static char *full_symbol = NULL;             /* Symbol to return */
00369   char *module;                                /* Real module name */
00370   char *tmp = stp_strdup(modulename);          /* Temporary string */
00371 
00372   module = basename(tmp);
00373 
00374   if (full_symbol)
00375     {
00376       stp_free (full_symbol);
00377       full_symbol = NULL;
00378     }
00379 
00380   full_symbol = (char *) stp_malloc(sizeof(char) * (strlen(module) - 2));
00381 
00382   /* "_LTX_" + '\0' - ".so" */
00383   len = strlen(symbol) + strlen(module) + 3;
00384   full_symbol = (char *) stp_malloc(sizeof(char) * len);
00385 
00386   len = 0;
00387   strncpy (full_symbol, module, strlen(module) - 3);
00388   len = strlen(module) - 3;
00389   strcpy (full_symbol+len, "_LTX_");
00390   len += 5;
00391   strcpy (full_symbol+len, symbol);
00392   len += strlen(symbol);
00393   full_symbol[len] = '\0';
00394 
00395 #if defined(__OpenBSD__)
00396 /* OpenBSD needs a prepended underscore to match symbols */
00397  {
00398    char *prefix_symbol = stp_malloc(sizeof(char) * (strlen(full_symbol) + 2));
00399    prefix_symbol[0] = '_';
00400    strcpy(prefix_symbol+1, full_symbol);
00401    stp_free(full_symbol);
00402    full_symbol = prefix_symbol;
00403  }
00404 #endif
00405 
00406  /* Change any hyphens to underscores */
00407  for (len = 0; full_symbol[len] != '\0'; len++)
00408    if (full_symbol[len] == '-')
00409      full_symbol[len] = '_';
00410 
00411  stp_deprintf(STP_DBG_MODULE, "SYMBOL: %s\n", full_symbol);
00412 
00413   return dlsym(handle, full_symbol);
00414 }
00415 #endif

Generated on Wed May 12 20:21:29 2004 for libgimpprint API Reference by doxygen1.2.17