libgimpprint API Reference: src/main/module.c Source File

Main Page | Modules | Alphabetical List | Data Structures | File List | Data Fields | Globals | Related Pages

# src/main/module.c

Go to the documentation of this file.

    00001 /*
    00002  * "$Id: module_8c-source.html,v 1.1.1.2 2004/12/22 23:49:05 jlovell 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