Home | History | Annotate | Download | only in MagickCore
      1 /*
      2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
      3 %                                                                             %
      4 %                                                                             %
      5 %                                                                             %
      6 %                  M   M   OOO   DDDD   U   U  L      EEEEE                   %
      7 %                  MM MM  O   O  D   D  U   U  L      E                       %
      8 %                  M M M  O   O  D   D  U   U  L      EEE                     %
      9 %                  M   M  O   O  D   D  U   U  L      E                       %
     10 %                  M   M   OOO   DDDD    UUU   LLLLL  EEEEE                   %
     11 %                                                                             %
     12 %                                                                             %
     13 %                          MagickCore Module Methods                          %
     14 %                                                                             %
     15 %                              Software Design                                %
     16 %                              Bob Friesenhahn                                %
     17 %                                March 2000                                   %
     18 %                                                                             %
     19 %                                                                             %
     20 %  Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization      %
     21 %  dedicated to making software imaging solutions freely available.           %
     22 %                                                                             %
     23 %  You may not use this file except in compliance with the License.  You may  %
     24 %  obtain a copy of the License at                                            %
     25 %                                                                             %
     26 %    http://www.imagemagick.org/script/license.php                            %
     27 %                                                                             %
     28 %  Unless required by applicable law or agreed to in writing, software        %
     29 %  distributed under the License is distributed on an "AS IS" BASIS,          %
     30 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
     31 %  See the License for the specific language governing permissions and        %
     32 %  limitations under the License.                                             %
     33 %                                                                             %
     34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
     35 %
     36 %
     37 %
     38 */
     39 
     40 /*
     42   Include declarations.
     43 */
     44 #include "MagickCore/studio.h"
     45 #include "MagickCore/blob.h"
     46 #include "MagickCore/coder.h"
     47 #include "MagickCore/client.h"
     48 #include "MagickCore/configure.h"
     49 #include "MagickCore/exception.h"
     50 #include "MagickCore/exception-private.h"
     51 #include "MagickCore/log.h"
     52 #include "MagickCore/linked-list.h"
     53 #include "MagickCore/magic.h"
     54 #include "MagickCore/magick.h"
     55 #include "MagickCore/memory_.h"
     56 #include "MagickCore/module.h"
     57 #include "MagickCore/module-private.h"
     58 #include "MagickCore/nt-base-private.h"
     59 #include "MagickCore/policy.h"
     60 #include "MagickCore/semaphore.h"
     61 #include "MagickCore/splay-tree.h"
     62 #include "MagickCore/static.h"
     63 #include "MagickCore/string_.h"
     64 #include "MagickCore/string-private.h"
     65 #include "MagickCore/token.h"
     66 #include "MagickCore/utility.h"
     67 #include "MagickCore/utility-private.h"
     68 #if defined(MAGICKCORE_MODULES_SUPPORT)
     69 #if defined(MAGICKCORE_LTDL_DELEGATE)
     70 #include "ltdl.h"
     71 typedef lt_dlhandle ModuleHandle;
     72 #else
     73 typedef void *ModuleHandle;
     74 #endif
     75 
     76 /*
     78   Define declarations.
     79 */
     80 #if defined(MAGICKCORE_LTDL_DELEGATE)
     81 #  define ModuleGlobExpression "*.la"
     82 #else
     83 #  if defined(_DEBUG)
     84 #    define ModuleGlobExpression "IM_MOD_DB_*.dll"
     85 #  else
     86 #    define ModuleGlobExpression "IM_MOD_RL_*.dll"
     87 #  endif
     88 #endif
     89 
     90 /*
     92   Global declarations.
     93 */
     94 static SemaphoreInfo
     95   *module_semaphore = (SemaphoreInfo *) NULL;
     96 
     97 static SplayTreeInfo
     98   *module_list = (SplayTreeInfo *) NULL;
     99 
    100 /*
    102   Forward declarations.
    103 */
    104 static const ModuleInfo
    105   *RegisterModule(const ModuleInfo *,ExceptionInfo *);
    106 
    107 static MagickBooleanType
    108   GetMagickModulePath(const char *,MagickModuleType,char *,ExceptionInfo *),
    109   IsModuleTreeInstantiated(),
    110   UnregisterModule(const ModuleInfo *,ExceptionInfo *);
    111 
    112 static void
    113   TagToCoderModuleName(const char *,char *),
    114   TagToFilterModuleName(const char *,char *),
    115   TagToModuleName(const char *,const char *,char *);
    116 
    117 /*
    119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    120 %                                                                             %
    121 %                                                                             %
    122 %                                                                             %
    123 %   A c q u i r e M o d u l e I n f o                                         %
    124 %                                                                             %
    125 %                                                                             %
    126 %                                                                             %
    127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    128 %
    129 %  AcquireModuleInfo() allocates the ModuleInfo structure.
    130 %
    131 %  The format of the AcquireModuleInfo method is:
    132 %
    133 %      ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
    134 %
    135 %  A description of each parameter follows:
    136 %
    137 %    o path: the path associated with the tag.
    138 %
    139 %    o tag: a character string that represents the image format we are
    140 %      looking for.
    141 %
    142 */
    143 MagickExport ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
    144 {
    145   ModuleInfo
    146     *module_info;
    147 
    148   module_info=(ModuleInfo *) AcquireMagickMemory(sizeof(*module_info));
    149   if (module_info == (ModuleInfo *) NULL)
    150     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    151   (void) ResetMagickMemory(module_info,0,sizeof(*module_info));
    152   if (path != (const char *) NULL)
    153     module_info->path=ConstantString(path);
    154   if (tag != (const char *) NULL)
    155     module_info->tag=ConstantString(tag);
    156   module_info->timestamp=time(0);
    157   module_info->signature=MagickCoreSignature;
    158   return(module_info);
    159 }
    160 
    161 /*
    163 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    164 %                                                                             %
    165 %                                                                             %
    166 %                                                                             %
    167 %   D e s t r o y M o d u l e L i s t                                         %
    168 %                                                                             %
    169 %                                                                             %
    170 %                                                                             %
    171 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    172 %
    173 %  DestroyModuleList() unregisters any previously loaded modules and exits
    174 %  the module loaded environment.
    175 %
    176 %  The format of the DestroyModuleList module is:
    177 %
    178 %      void DestroyModuleList(void)
    179 %
    180 */
    181 MagickExport void DestroyModuleList(void)
    182 {
    183   /*
    184     Destroy magick modules.
    185   */
    186   LockSemaphoreInfo(module_semaphore);
    187 #if defined(MAGICKCORE_MODULES_SUPPORT)
    188   if (module_list != (SplayTreeInfo *) NULL)
    189     module_list=DestroySplayTree(module_list);
    190 #endif
    191   UnlockSemaphoreInfo(module_semaphore);
    192 }
    193 
    194 /*
    196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    197 %                                                                             %
    198 %                                                                             %
    199 %                                                                             %
    200 %   G e t M o d u l e I n f o                                                 %
    201 %                                                                             %
    202 %                                                                             %
    203 %                                                                             %
    204 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    205 %
    206 %  GetModuleInfo() returns a pointer to a ModuleInfo structure that matches the
    207 %  specified tag.  If tag is NULL, the head of the module list is returned. If
    208 %  no modules are loaded, or the requested module is not found, NULL is
    209 %  returned.
    210 %
    211 %  The format of the GetModuleInfo module is:
    212 %
    213 %      ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
    214 %
    215 %  A description of each parameter follows:
    216 %
    217 %    o tag: a character string that represents the image format we are
    218 %      looking for.
    219 %
    220 %    o exception: return any errors or warnings in this structure.
    221 %
    222 */
    223 MagickExport ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
    224 {
    225   ModuleInfo
    226     *module_info;
    227 
    228   if (IsModuleTreeInstantiated() == MagickFalse)
    229     return((ModuleInfo *) NULL);
    230   LockSemaphoreInfo(module_semaphore);
    231   ResetSplayTreeIterator(module_list);
    232   if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0))
    233     {
    234 #if defined(MAGICKCORE_MODULES_SUPPORT)
    235       if (LocaleCompare(tag,"*") == 0)
    236         (void) OpenModules(exception);
    237 #endif
    238       module_info=(ModuleInfo *) GetNextValueInSplayTree(module_list);
    239       UnlockSemaphoreInfo(module_semaphore);
    240       return(module_info);
    241     }
    242   module_info=(ModuleInfo *) GetValueFromSplayTree(module_list,tag);
    243   UnlockSemaphoreInfo(module_semaphore);
    244   return(module_info);
    245 }
    246 
    247 /*
    249 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    250 %                                                                             %
    251 %                                                                             %
    252 %                                                                             %
    253 %   G e t M o d u l e I n f o L i s t                                         %
    254 %                                                                             %
    255 %                                                                             %
    256 %                                                                             %
    257 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    258 %
    259 %  GetModuleInfoList() returns any modules that match the specified pattern.
    260 %
    261 %  The format of the GetModuleInfoList function is:
    262 %
    263 %      const ModuleInfo **GetModuleInfoList(const char *pattern,
    264 %        size_t *number_modules,ExceptionInfo *exception)
    265 %
    266 %  A description of each parameter follows:
    267 %
    268 %    o pattern: Specifies a pointer to a text string containing a pattern.
    269 %
    270 %    o number_modules:  This integer returns the number of modules in the list.
    271 %
    272 %    o exception: return any errors or warnings in this structure.
    273 %
    274 */
    275 
    276 #if defined(__cplusplus) || defined(c_plusplus)
    277 extern "C" {
    278 #endif
    279 
    280 static int ModuleInfoCompare(const void *x,const void *y)
    281 {
    282   const ModuleInfo
    283     **p,
    284     **q;
    285 
    286   p=(const ModuleInfo **) x,
    287   q=(const ModuleInfo **) y;
    288   if (LocaleCompare((*p)->path,(*q)->path) == 0)
    289     return(LocaleCompare((*p)->tag,(*q)->tag));
    290   return(LocaleCompare((*p)->path,(*q)->path));
    291 }
    292 
    293 #if defined(__cplusplus) || defined(c_plusplus)
    294 }
    295 #endif
    296 
    297 MagickExport const ModuleInfo **GetModuleInfoList(const char *pattern,
    298   size_t *number_modules,ExceptionInfo *exception)
    299 {
    300   const ModuleInfo
    301     **modules;
    302 
    303   register const ModuleInfo
    304     *p;
    305 
    306   register ssize_t
    307     i;
    308 
    309   /*
    310     Allocate module list.
    311   */
    312   assert(pattern != (char *) NULL);
    313   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
    314   assert(number_modules != (size_t *) NULL);
    315   *number_modules=0;
    316   p=GetModuleInfo("*",exception);
    317   if (p == (const ModuleInfo *) NULL)
    318     return((const ModuleInfo **) NULL);
    319   modules=(const ModuleInfo **) AcquireQuantumMemory((size_t)
    320     GetNumberOfNodesInSplayTree(module_list)+1UL,sizeof(*modules));
    321   if (modules == (const ModuleInfo **) NULL)
    322     return((const ModuleInfo **) NULL);
    323   /*
    324     Generate module list.
    325   */
    326   LockSemaphoreInfo(module_semaphore);
    327   ResetSplayTreeIterator(module_list);
    328   p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
    329   for (i=0; p != (const ModuleInfo *) NULL; )
    330   {
    331     if ((p->stealth == MagickFalse) &&
    332         (GlobExpression(p->tag,pattern,MagickFalse) != MagickFalse))
    333       modules[i++]=p;
    334     p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
    335   }
    336   UnlockSemaphoreInfo(module_semaphore);
    337   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleInfoCompare);
    338   modules[i]=(ModuleInfo *) NULL;
    339   *number_modules=(size_t) i;
    340   return(modules);
    341 }
    342 
    343 /*
    345 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    346 %                                                                             %
    347 %                                                                             %
    348 %                                                                             %
    349 %   G e t M o d u l e L i s t                                                 %
    350 %                                                                             %
    351 %                                                                             %
    352 %                                                                             %
    353 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    354 %
    355 %  GetModuleList() returns any image format modules that match the specified
    356 %  pattern.
    357 %
    358 %  The format of the GetModuleList function is:
    359 %
    360 %      char **GetModuleList(const char *pattern,const MagickModuleType type,
    361 %        size_t *number_modules,ExceptionInfo *exception)
    362 %
    363 %  A description of each parameter follows:
    364 %
    365 %    o pattern: Specifies a pointer to a text string containing a pattern.
    366 %
    367 %    o type: choose from MagickImageCoderModule or MagickImageFilterModule.
    368 %
    369 %    o number_modules:  This integer returns the number of modules in the
    370 %      list.
    371 %
    372 %    o exception: return any errors or warnings in this structure.
    373 %
    374 */
    375 
    376 #if defined(__cplusplus) || defined(c_plusplus)
    377 extern "C" {
    378 #endif
    379 
    380 static int ModuleCompare(const void *x,const void *y)
    381 {
    382   register const char
    383     **p,
    384     **q;
    385 
    386    p=(const char **) x;
    387   q=(const char **) y;
    388   return(LocaleCompare(*p,*q));
    389 }
    390 
    391 #if defined(__cplusplus) || defined(c_plusplus)
    392 }
    393 #endif
    394 
    395 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
    396   struct dirent **result)
    397 {
    398 #if defined(MAGICKCORE_HAVE_READDIR_R)
    399   return(readdir_r(directory,entry,result));
    400 #else
    401   (void) entry;
    402   errno=0;
    403   *result=readdir(directory);
    404   return(errno);
    405 #endif
    406 }
    407 
    408 MagickExport char **GetModuleList(const char *pattern,
    409   const MagickModuleType type,size_t *number_modules,ExceptionInfo *exception)
    410 {
    411 #define MaxModules  511
    412 
    413   char
    414     **modules,
    415     filename[MagickPathExtent],
    416     module_path[MagickPathExtent],
    417     path[MagickPathExtent];
    418 
    419   DIR
    420     *directory;
    421 
    422   MagickBooleanType
    423     status;
    424 
    425   register ssize_t
    426     i;
    427 
    428   size_t
    429     max_entries;
    430 
    431   struct dirent
    432     *buffer,
    433     *entry;
    434 
    435   /*
    436     Locate all modules in the image coder or filter path.
    437   */
    438   switch (type)
    439   {
    440     case MagickImageCoderModule:
    441     default:
    442     {
    443       TagToCoderModuleName("magick",filename);
    444       status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
    445         exception);
    446       break;
    447     }
    448     case MagickImageFilterModule:
    449     {
    450       TagToFilterModuleName("analyze",filename);
    451       status=GetMagickModulePath(filename,MagickImageFilterModule,module_path,
    452         exception);
    453       break;
    454     }
    455   }
    456   if (status == MagickFalse)
    457     return((char **) NULL);
    458   GetPathComponent(module_path,HeadPath,path);
    459   max_entries=MaxModules;
    460   modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
    461     sizeof(*modules));
    462   if (modules == (char **) NULL)
    463     return((char **) NULL);
    464   *modules=(char *) NULL;
    465   directory=opendir(path);
    466   if (directory == (DIR *) NULL)
    467     {
    468       modules=(char **) RelinquishMagickMemory(modules);
    469       return((char **) NULL);
    470     }
    471   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+FILENAME_MAX+1);
    472   if (buffer == (struct dirent *) NULL)
    473     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
    474   i=0;
    475   while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
    476          (entry != (struct dirent *) NULL))
    477   {
    478     status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
    479     if (status == MagickFalse)
    480       continue;
    481     if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
    482       continue;
    483     if (i >= (ssize_t) max_entries)
    484       {
    485         modules=(char **) NULL;
    486         if (~max_entries > max_entries)
    487           modules=(char **) ResizeQuantumMemory(modules,(size_t)
    488             (max_entries << 1),sizeof(*modules));
    489         max_entries<<=1;
    490         if (modules == (char **) NULL)
    491           break;
    492       }
    493     /*
    494       Add new module name to list.
    495     */
    496     modules[i]=AcquireString((char *) NULL);
    497     GetPathComponent(entry->d_name,BasePath,modules[i]);
    498     if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
    499       {
    500         (void) CopyMagickString(modules[i],modules[i]+10,MagickPathExtent);
    501         modules[i][strlen(modules[i])-1]='\0';
    502       }
    503     i++;
    504   }
    505   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
    506   (void) closedir(directory);
    507   if (modules == (char **) NULL)
    508     {
    509       (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
    510         "MemoryAllocationFailed","`%s'",pattern);
    511       return((char **) NULL);
    512     }
    513   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
    514   modules[i]=(char *) NULL;
    515   *number_modules=(size_t) i;
    516   return(modules);
    517 }
    518 
    519 /*
    521 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    522 %                                                                             %
    523 %                                                                             %
    524 %                                                                             %
    525 %  G e t M a g i c k M o d u l e P a t h                                      %
    526 %                                                                             %
    527 %                                                                             %
    528 %                                                                             %
    529 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    530 %
    531 %  GetMagickModulePath() finds a module with the specified module type and
    532 %  filename.
    533 %
    534 %  The format of the GetMagickModulePath module is:
    535 %
    536 %      MagickBooleanType GetMagickModulePath(const char *filename,
    537 %        MagickModuleType module_type,char *path,ExceptionInfo *exception)
    538 %
    539 %  A description of each parameter follows:
    540 %
    541 %    o filename: the module file name.
    542 %
    543 %    o module_type: the module type: MagickImageCoderModule or
    544 %      MagickImageFilterModule.
    545 %
    546 %    o path: the path associated with the filename.
    547 %
    548 %    o exception: return any errors or warnings in this structure.
    549 %
    550 */
    551 static MagickBooleanType GetMagickModulePath(const char *filename,
    552   MagickModuleType module_type,char *path,ExceptionInfo *exception)
    553 {
    554   char
    555     *module_path;
    556 
    557   assert(filename != (const char *) NULL);
    558   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
    559   assert(path != (char *) NULL);
    560   assert(exception != (ExceptionInfo *) NULL);
    561   if (strchr(filename,'/') != (char *) NULL)
    562     return(MagickFalse);
    563   (void) CopyMagickString(path,filename,MagickPathExtent);
    564   module_path=(char *) NULL;
    565   switch (module_type)
    566   {
    567     case MagickImageCoderModule:
    568     default:
    569     {
    570       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
    571         "Searching for coder module file \"%s\" ...",filename);
    572       module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
    573 #if defined(MAGICKCORE_CODER_PATH)
    574       if (module_path == (char *) NULL)
    575         module_path=AcquireString(MAGICKCORE_CODER_PATH);
    576 #endif
    577       break;
    578     }
    579     case MagickImageFilterModule:
    580     {
    581       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
    582         "Searching for filter module file \"%s\" ...",filename);
    583       module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
    584 #if defined(MAGICKCORE_FILTER_PATH)
    585       if (module_path == (char *) NULL)
    586         module_path=AcquireString(MAGICKCORE_FILTER_PATH);
    587 #endif
    588       break;
    589     }
    590   }
    591   if (module_path != (char *) NULL)
    592     {
    593       register char
    594         *p,
    595         *q;
    596 
    597       for (p=module_path-1; p != (char *) NULL; )
    598       {
    599         (void) CopyMagickString(path,p+1,MagickPathExtent);
    600         q=strchr(path,DirectoryListSeparator);
    601         if (q != (char *) NULL)
    602           *q='\0';
    603         q=path+strlen(path)-1;
    604         if ((q >= path) && (*q != *DirectorySeparator))
    605           (void) ConcatenateMagickString(path,DirectorySeparator,
    606             MagickPathExtent);
    607         (void) ConcatenateMagickString(path,filename,MagickPathExtent);
    608         if (IsPathAccessible(path) != MagickFalse)
    609           {
    610             module_path=DestroyString(module_path);
    611             return(MagickTrue);
    612           }
    613         p=strchr(p+1,DirectoryListSeparator);
    614       }
    615       module_path=DestroyString(module_path);
    616     }
    617 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
    618   else
    619 #if defined(MAGICKCORE_CODER_PATH)
    620     {
    621       const char
    622         *directory;
    623 
    624       /*
    625         Search hard coded paths.
    626       */
    627       switch (module_type)
    628       {
    629         case MagickImageCoderModule:
    630         default:
    631         {
    632           directory=MAGICKCORE_CODER_PATH;
    633           break;
    634         }
    635         case MagickImageFilterModule:
    636         {
    637           directory=MAGICKCORE_FILTER_PATH;
    638           break;
    639         }
    640       }
    641       (void) FormatLocaleString(path,MagickPathExtent,"%s%s",directory,
    642         filename);
    643       if (IsPathAccessible(path) == MagickFalse)
    644         {
    645           ThrowFileException(exception,ConfigureWarning,
    646             "UnableToOpenModuleFile",path);
    647           return(MagickFalse);
    648         }
    649       return(MagickTrue);
    650     }
    651 #else
    652 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
    653     {
    654       const char
    655         *registery_key;
    656 
    657       unsigned char
    658         *key_value;
    659 
    660       /*
    661         Locate path via registry key.
    662       */
    663       switch (module_type)
    664       {
    665         case MagickImageCoderModule:
    666         default:
    667         {
    668           registery_key="CoderModulesPath";
    669           break;
    670         }
    671         case MagickImageFilterModule:
    672         {
    673           registery_key="FilterModulesPath";
    674           break;
    675         }
    676       }
    677       key_value=NTRegistryKeyLookup(registery_key);
    678       if (key_value == (unsigned char *) NULL)
    679         {
    680           ThrowMagickException(exception,GetMagickModule(),ConfigureError,
    681             "RegistryKeyLookupFailed","`%s'",registery_key);
    682           return(MagickFalse);
    683         }
    684       (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",(char *)
    685         key_value,DirectorySeparator,filename);
    686       key_value=(unsigned char *) RelinquishMagickMemory(key_value);
    687       if (IsPathAccessible(path) == MagickFalse)
    688         {
    689           ThrowFileException(exception,ConfigureWarning,
    690             "UnableToOpenModuleFile",path);
    691           return(MagickFalse);
    692         }
    693       return(MagickTrue);
    694     }
    695 #endif
    696 #endif
    697 #if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
    698 # error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
    699 #endif
    700 #else
    701   {
    702     char
    703       *home;
    704 
    705     home=GetEnvironmentValue("MAGICK_HOME");
    706     if (home != (char *) NULL)
    707       {
    708         /*
    709           Search MAGICK_HOME.
    710         */
    711 #if !defined(MAGICKCORE_POSIX_SUPPORT)
    712         (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",home,
    713           DirectorySeparator,filename);
    714 #else
    715         const char
    716           *directory;
    717 
    718         switch (module_type)
    719         {
    720           case MagickImageCoderModule:
    721           default:
    722           {
    723             directory=MAGICKCORE_CODER_RELATIVE_PATH;
    724             break;
    725           }
    726           case MagickImageFilterModule:
    727           {
    728             directory=MAGICKCORE_FILTER_RELATIVE_PATH;
    729             break;
    730           }
    731         }
    732         (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s",home,
    733           directory,filename);
    734 #endif
    735         home=DestroyString(home);
    736         if (IsPathAccessible(path) != MagickFalse)
    737           return(MagickTrue);
    738       }
    739   }
    740   if (*GetClientPath() != '\0')
    741     {
    742       /*
    743         Search based on executable directory.
    744       */
    745 #if !defined(MAGICKCORE_POSIX_SUPPORT)
    746       (void) FormatLocaleString(path,MagickPathExtent,"%s%s%s",GetClientPath(),
    747         DirectorySeparator,filename);
    748 #else
    749       char
    750         prefix[MagickPathExtent];
    751 
    752       const char
    753         *directory;
    754 
    755       switch (module_type)
    756       {
    757         case MagickImageCoderModule:
    758         default:
    759         {
    760           directory="coders";
    761           break;
    762         }
    763         case MagickImageFilterModule:
    764         {
    765           directory="filters";
    766           break;
    767         }
    768       }
    769       (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
    770       ChopPathComponents(prefix,1);
    771       (void) FormatLocaleString(path,MagickPathExtent,"%s/lib/%s/%s/%s",prefix,
    772         MAGICKCORE_MODULES_RELATIVE_PATH,directory,filename);
    773 #endif
    774       if (IsPathAccessible(path) != MagickFalse)
    775         return(MagickTrue);
    776     }
    777 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
    778   {
    779     /*
    780       Search module path.
    781     */
    782     if ((NTGetModulePath("CORE_RL_MagickCore_.dll",path) != MagickFalse) ||
    783         (NTGetModulePath("CORE_DB_MagickCore_.dll",path) != MagickFalse))
    784       {
    785         (void) ConcatenateMagickString(path,DirectorySeparator,
    786           MagickPathExtent);
    787         (void) ConcatenateMagickString(path,filename,MagickPathExtent);
    788         if (IsPathAccessible(path) != MagickFalse)
    789           return(MagickTrue);
    790       }
    791   }
    792 #endif
    793   {
    794     char
    795       *home;
    796 
    797     home=GetEnvironmentValue("XDG_CONFIG_HOME");
    798     if (home == (char *) NULL)
    799       home=GetEnvironmentValue("LOCALAPPDATA");
    800     if (home == (char *) NULL)
    801       home=GetEnvironmentValue("APPDATA");
    802     if (home == (char *) NULL)
    803       home=GetEnvironmentValue("USERPROFILE");
    804     if (home != (char *) NULL)
    805       {
    806         /*
    807           Search $XDG_CONFIG_HOME/ImageMagick.
    808         */
    809         (void) FormatLocaleString(path,MagickPathExtent,"%s%sImageMagick%s%s",
    810           home,DirectorySeparator,DirectorySeparator,filename);
    811         home=DestroyString(home);
    812         if (IsPathAccessible(path) != MagickFalse)
    813           return(MagickTrue);
    814       }
    815     home=GetEnvironmentValue("HOME");
    816     if (home != (char *) NULL)
    817       {
    818         /*
    819           Search $HOME/.config/ImageMagick.
    820         */
    821         (void) FormatLocaleString(path,MagickPathExtent,
    822           "%s%s.config%sImageMagick%s%s",home,DirectorySeparator,
    823           DirectorySeparator,DirectorySeparator,filename);
    824         home=DestroyString(home);
    825         if (IsPathAccessible(path) != MagickFalse)
    826           return(MagickTrue);
    827       }
    828   }
    829   /*
    830     Search current directory.
    831   */
    832   if (IsPathAccessible(path) != MagickFalse)
    833     return(MagickTrue);
    834   if (exception->severity < ConfigureError)
    835     ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
    836       path);
    837 #endif
    838   return(MagickFalse);
    839 }
    840 
    841 /*
    843 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    844 %                                                                             %
    845 %                                                                             %
    846 %                                                                             %
    847 %   I s M o d u l e T r e e I n s t a n t i a t e d                           %
    848 %                                                                             %
    849 %                                                                             %
    850 %                                                                             %
    851 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    852 %
    853 %  IsModuleTreeInstantiated() determines if the module tree is instantiated.
    854 %  If not, it instantiates the tree and returns it.
    855 %
    856 %  The format of the IsModuleTreeInstantiated() method is:
    857 %
    858 %      IsModuleTreeInstantiated()
    859 %
    860 */
    861 
    862 static void *DestroyModuleNode(void *module_info)
    863 {
    864   ExceptionInfo
    865     *exception;
    866 
    867   register ModuleInfo
    868     *p;
    869 
    870   exception=AcquireExceptionInfo();
    871   p=(ModuleInfo *) module_info;
    872   if (UnregisterModule(p,exception) == MagickFalse)
    873     CatchException(exception);
    874   if (p->tag != (char *) NULL)
    875     p->tag=DestroyString(p->tag);
    876   if (p->path != (char *) NULL)
    877     p->path=DestroyString(p->path);
    878   exception=DestroyExceptionInfo(exception);
    879   return(RelinquishMagickMemory(p));
    880 }
    881 
    882 static MagickBooleanType IsModuleTreeInstantiated()
    883 {
    884   if (module_list == (SplayTreeInfo *) NULL)
    885     {
    886       if (module_semaphore == (SemaphoreInfo *) NULL)
    887         ActivateSemaphoreInfo(&module_semaphore);
    888       LockSemaphoreInfo(module_semaphore);
    889       if (module_list == (SplayTreeInfo *) NULL)
    890         {
    891           MagickBooleanType
    892             status;
    893 
    894           ModuleInfo
    895             *module_info;
    896 
    897           module_list=NewSplayTree(CompareSplayTreeString,
    898             (void *(*)(void *)) NULL,DestroyModuleNode);
    899           if (module_list == (SplayTreeInfo *) NULL)
    900             ThrowFatalException(ResourceLimitFatalError,
    901               "MemoryAllocationFailed");
    902           module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
    903           module_info->stealth=MagickTrue;
    904           status=AddValueToSplayTree(module_list,module_info->tag,module_info);
    905           if (status == MagickFalse)
    906             ThrowFatalException(ResourceLimitFatalError,
    907               "MemoryAllocationFailed");
    908           if (lt_dlinit() != 0)
    909             ThrowFatalException(ModuleFatalError,
    910               "UnableToInitializeModuleLoader");
    911         }
    912       UnlockSemaphoreInfo(module_semaphore);
    913     }
    914   return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
    915 }
    916 
    917 /*
    919 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    920 %                                                                             %
    921 %                                                                             %
    922 %                                                                             %
    923 %   I n v o k e D y n a m i c I m a g e F i l t e r                           %
    924 %                                                                             %
    925 %                                                                             %
    926 %                                                                             %
    927 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    928 %
    929 %  InvokeDynamicImageFilter() invokes a dynamic image filter.
    930 %
    931 %  The format of the InvokeDynamicImageFilter module is:
    932 %
    933 %      MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
    934 %        const int argc,const char **argv,ExceptionInfo *exception)
    935 %
    936 %  A description of each parameter follows:
    937 %
    938 %    o tag: a character string that represents the name of the particular
    939 %      module.
    940 %
    941 %    o image: the image.
    942 %
    943 %    o argc: a pointer to an integer describing the number of elements in the
    944 %      argument vector.
    945 %
    946 %    o argv: a pointer to a text array containing the command line arguments.
    947 %
    948 %    o exception: return any errors or warnings in this structure.
    949 %
    950 */
    951 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
    952   Image **images,const int argc,const char **argv,ExceptionInfo *exception)
    953 {
    954   char
    955     name[MagickPathExtent],
    956     path[MagickPathExtent];
    957 
    958   ImageFilterHandler
    959     *image_filter;
    960 
    961   MagickBooleanType
    962     status;
    963 
    964   ModuleHandle
    965     handle;
    966 
    967   PolicyRights
    968     rights;
    969 
    970   /*
    971     Find the module.
    972   */
    973   assert(images != (Image **) NULL);
    974   assert((*images)->signature == MagickCoreSignature);
    975   if ((*images)->debug != MagickFalse)
    976     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
    977       (*images)->filename);
    978 #if !defined(MAGICKCORE_BUILD_MODULES)
    979   {
    980     MagickBooleanType
    981       status;
    982 
    983     status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
    984     if (status != MagickFalse)
    985       return(status);
    986   }
    987 #endif
    988   rights=ReadPolicyRights;
    989   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
    990     {
    991       errno=EPERM;
    992       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
    993         "NotAuthorized","`%s'",tag);
    994       return(MagickFalse);
    995     }
    996   TagToFilterModuleName(tag,name);
    997   status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
    998   if (status == MagickFalse)
    999     {
   1000       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1001         "UnableToLoadModule","'%s': %s",name,path);
   1002       return(MagickFalse);
   1003     }
   1004   /*
   1005     Open the module.
   1006   */
   1007   handle=(ModuleHandle) lt_dlopen(path);
   1008   if (handle == (ModuleHandle) NULL)
   1009     {
   1010       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1011         "UnableToLoadModule","'%s': %s",name,lt_dlerror());
   1012       return(MagickFalse);
   1013     }
   1014   /*
   1015     Locate the module.
   1016   */
   1017 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
   1018   (void) FormatLocaleString(name,MagickPathExtent,"%sImage",tag);
   1019 #else
   1020   (void) FormatLocaleString(name,MagickPathExtent,"%s%sImage",
   1021     MAGICKCORE_NAMESPACE_PREFIX,tag);
   1022 #endif
   1023   /*
   1024     Execute the module.
   1025   */
   1026   ClearMagickException(exception);
   1027   image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
   1028   if (image_filter == (ImageFilterHandler *) NULL)
   1029     (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1030       "UnableToLoadModule","'%s': %s",name,lt_dlerror());
   1031   else
   1032     {
   1033       size_t
   1034         signature;
   1035 
   1036       if ((*images)->debug != MagickFalse)
   1037         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
   1038           "Invoking \"%s\" dynamic image filter",tag);
   1039       signature=image_filter(images,argc,argv,exception);
   1040       if ((*images)->debug != MagickFalse)
   1041         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
   1042           tag);
   1043       if (signature != MagickImageFilterSignature)
   1044         (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1045           "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
   1046           (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
   1047     }
   1048   /*
   1049     Close the module.
   1050   */
   1051   if (lt_dlclose(handle) != 0)
   1052     (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
   1053       "UnableToCloseModule","'%s': %s",name,lt_dlerror());
   1054   return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
   1055 }
   1056 
   1057 /*
   1059 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1060 %                                                                             %
   1061 %                                                                             %
   1062 %                                                                             %
   1063 %  L i s t M o d u l e I n f o                                                %
   1064 %                                                                             %
   1065 %                                                                             %
   1066 %                                                                             %
   1067 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1068 %
   1069 %  ListModuleInfo() lists the module info to a file.
   1070 %
   1071 %  The format of the ListModuleInfo module is:
   1072 %
   1073 %      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
   1074 %
   1075 %  A description of each parameter follows.
   1076 %
   1077 %    o file:  An pointer to a FILE.
   1078 %
   1079 %    o exception: return any errors or warnings in this structure.
   1080 %
   1081 */
   1082 MagickExport MagickBooleanType ListModuleInfo(FILE *file,
   1083   ExceptionInfo *exception)
   1084 {
   1085   char
   1086     filename[MagickPathExtent],
   1087     module_path[MagickPathExtent],
   1088     **modules,
   1089     path[MagickPathExtent];
   1090 
   1091   register ssize_t
   1092     i;
   1093 
   1094   size_t
   1095     number_modules;
   1096 
   1097   if (file == (const FILE *) NULL)
   1098     file=stdout;
   1099   /*
   1100     List image coders.
   1101   */
   1102   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
   1103   if (modules == (char **) NULL)
   1104     return(MagickFalse);
   1105   TagToCoderModuleName("magick",filename);
   1106   (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
   1107     exception);
   1108   GetPathComponent(module_path,HeadPath,path);
   1109   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
   1110   (void) FormatLocaleFile(file,"Image Coder\n");
   1111   (void) FormatLocaleFile(file,
   1112     "-------------------------------------------------"
   1113     "------------------------------\n");
   1114   for (i=0; i < (ssize_t) number_modules; i++)
   1115   {
   1116     (void) FormatLocaleFile(file,"%s",modules[i]);
   1117     (void) FormatLocaleFile(file,"\n");
   1118   }
   1119   (void) fflush(file);
   1120   /*
   1121     Relinquish resources.
   1122   */
   1123   for (i=0; i < (ssize_t) number_modules; i++)
   1124     modules[i]=DestroyString(modules[i]);
   1125   modules=(char **) RelinquishMagickMemory(modules);
   1126   /*
   1127     List image filters.
   1128   */
   1129   modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
   1130   if (modules == (char **) NULL)
   1131     return(MagickFalse);
   1132   TagToFilterModuleName("analyze",filename);
   1133   (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
   1134     exception);
   1135   GetPathComponent(module_path,HeadPath,path);
   1136   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
   1137   (void) FormatLocaleFile(file,"Image Filter\n");
   1138   (void) FormatLocaleFile(file,
   1139     "-------------------------------------------------"
   1140     "------------------------------\n");
   1141   for (i=0; i < (ssize_t) number_modules; i++)
   1142   {
   1143     (void) FormatLocaleFile(file,"%s",modules[i]);
   1144     (void) FormatLocaleFile(file,"\n");
   1145   }
   1146   (void) fflush(file);
   1147   /*
   1148     Relinquish resources.
   1149   */
   1150   for (i=0; i < (ssize_t) number_modules; i++)
   1151     modules[i]=DestroyString(modules[i]);
   1152   modules=(char **) RelinquishMagickMemory(modules);
   1153   return(MagickTrue);
   1154 }
   1155 
   1156 /*
   1158 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1159 %                                                                             %
   1160 %                                                                             %
   1161 %                                                                             %
   1162 +   M o d u l e C o m p o n e n t G e n e s i s                               %
   1163 %                                                                             %
   1164 %                                                                             %
   1165 %                                                                             %
   1166 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1167 %
   1168 %  ModuleComponentGenesis() instantiates the module component.
   1169 %
   1170 %  The format of the ModuleComponentGenesis method is:
   1171 %
   1172 %      MagickBooleanType ModuleComponentGenesis(void)
   1173 %
   1174 */
   1175 MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
   1176 {
   1177   MagickBooleanType
   1178     status;
   1179 
   1180   if (module_semaphore == (SemaphoreInfo *) NULL)
   1181     module_semaphore=AcquireSemaphoreInfo();
   1182   status=IsModuleTreeInstantiated();
   1183   return(status);
   1184 }
   1185 
   1186 /*
   1188 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1189 %                                                                             %
   1190 %                                                                             %
   1191 %                                                                             %
   1192 +   M o d u l e C o m p o n e n t T e r m i n u s                             %
   1193 %                                                                             %
   1194 %                                                                             %
   1195 %                                                                             %
   1196 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1197 %
   1198 %  ModuleComponentTerminus() destroys the module component.
   1199 %
   1200 %  The format of the ModuleComponentTerminus method is:
   1201 %
   1202 %      ModuleComponentTerminus(void)
   1203 %
   1204 */
   1205 MagickPrivate void ModuleComponentTerminus(void)
   1206 {
   1207   if (module_semaphore == (SemaphoreInfo *) NULL)
   1208     ActivateSemaphoreInfo(&module_semaphore);
   1209   DestroyModuleList();
   1210   RelinquishSemaphoreInfo(&module_semaphore);
   1211 }
   1212 
   1213 /*
   1215 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1216 %                                                                             %
   1217 %                                                                             %
   1218 %                                                                             %
   1219 %   O p e n M o d u l e                                                       %
   1220 %                                                                             %
   1221 %                                                                             %
   1222 %                                                                             %
   1223 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1224 %
   1225 %  OpenModule() loads a module, and invokes its registration module.  It
   1226 %  returns MagickTrue on success, and MagickFalse if there is an error.
   1227 %
   1228 %  The format of the OpenModule module is:
   1229 %
   1230 %      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
   1231 %
   1232 %  A description of each parameter follows:
   1233 %
   1234 %    o module: a character string that indicates the module to load.
   1235 %
   1236 %    o exception: return any errors or warnings in this structure.
   1237 %
   1238 */
   1239 MagickPrivate MagickBooleanType OpenModule(const char *module,
   1240   ExceptionInfo *exception)
   1241 {
   1242   char
   1243     filename[MagickPathExtent],
   1244     module_name[MagickPathExtent],
   1245     name[MagickPathExtent],
   1246     path[MagickPathExtent];
   1247 
   1248   MagickBooleanType
   1249     status;
   1250 
   1251   ModuleHandle
   1252     handle;
   1253 
   1254   ModuleInfo
   1255     *module_info;
   1256 
   1257   register const CoderInfo
   1258     *p;
   1259 
   1260   size_t
   1261     signature;
   1262 
   1263   /*
   1264     Assign module name from alias.
   1265   */
   1266   assert(module != (const char *) NULL);
   1267   module_info=(ModuleInfo *) GetModuleInfo(module,exception);
   1268   if (module_info != (ModuleInfo *) NULL)
   1269     return(MagickTrue);
   1270   (void) CopyMagickString(module_name,module,MagickPathExtent);
   1271   p=GetCoderInfo(module,exception);
   1272   if (p != (CoderInfo *) NULL)
   1273     (void) CopyMagickString(module_name,p->name,MagickPathExtent);
   1274   if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
   1275     return(MagickTrue);  /* module already opened, return */
   1276   /*
   1277     Locate module.
   1278   */
   1279   handle=(ModuleHandle) NULL;
   1280   TagToCoderModuleName(module_name,filename);
   1281   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
   1282     "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
   1283   *path='\0';
   1284   status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
   1285   if (status == MagickFalse)
   1286     return(MagickFalse);
   1287   /*
   1288     Load module
   1289   */
   1290   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
   1291     "Opening module at path \"%s\"",path);
   1292   handle=(ModuleHandle) lt_dlopen(path);
   1293   if (handle == (ModuleHandle) NULL)
   1294     {
   1295       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1296         "UnableToLoadModule","'%s': %s",path,lt_dlerror());
   1297       return(MagickFalse);
   1298     }
   1299   /*
   1300     Register module.
   1301   */
   1302   module_info=AcquireModuleInfo(path,module_name);
   1303   module_info->handle=handle;
   1304   if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
   1305     return(MagickFalse);
   1306   /*
   1307     Define RegisterFORMATImage method.
   1308   */
   1309   TagToModuleName(module_name,"Register%sImage",name);
   1310   module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
   1311   if (module_info->register_module == (size_t (*)(void)) NULL)
   1312     {
   1313       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1314         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
   1315       return(MagickFalse);
   1316     }
   1317   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
   1318     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
   1319     (void *) module_info->register_module);
   1320   /*
   1321     Define UnregisterFORMATImage method.
   1322   */
   1323   TagToModuleName(module_name,"Unregister%sImage",name);
   1324   module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
   1325   if (module_info->unregister_module == (void (*)(void)) NULL)
   1326     {
   1327       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1328         "UnableToRegisterImageFormat","'%s': %s",module_name,lt_dlerror());
   1329       return(MagickFalse);
   1330     }
   1331   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
   1332     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
   1333     (void *) module_info->unregister_module);
   1334   signature=module_info->register_module();
   1335   if (signature != MagickImageCoderSignature)
   1336     {
   1337       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1338         "ImageCoderSignatureMismatch","'%s': %8lx != %8lx",module_name,
   1339         (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
   1340       return(MagickFalse);
   1341     }
   1342   return(MagickTrue);
   1343 }
   1344 
   1345 /*
   1347 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1348 %                                                                             %
   1349 %                                                                             %
   1350 %                                                                             %
   1351 %   O p e n M o d u l e s                                                     %
   1352 %                                                                             %
   1353 %                                                                             %
   1354 %                                                                             %
   1355 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1356 %
   1357 %  OpenModules() loads all available modules.
   1358 %
   1359 %  The format of the OpenModules module is:
   1360 %
   1361 %      MagickBooleanType OpenModules(ExceptionInfo *exception)
   1362 %
   1363 %  A description of each parameter follows:
   1364 %
   1365 %    o exception: return any errors or warnings in this structure.
   1366 %
   1367 */
   1368 MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
   1369 {
   1370   char
   1371     **modules;
   1372 
   1373   register ssize_t
   1374     i;
   1375 
   1376   size_t
   1377     number_modules;
   1378 
   1379   /*
   1380     Load all modules.
   1381   */
   1382   (void) GetMagickInfo((char *) NULL,exception);
   1383   number_modules=0;
   1384   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
   1385   if ((modules == (char **) NULL) || (*modules == (char *) NULL))
   1386     {
   1387       if (modules != (char **) NULL)
   1388         modules=(char **) RelinquishMagickMemory(modules);
   1389       return(MagickFalse);
   1390     }
   1391   for (i=0; i < (ssize_t) number_modules; i++)
   1392     (void) OpenModule(modules[i],exception);
   1393   /*
   1394     Relinquish resources.
   1395   */
   1396   for (i=0; i < (ssize_t) number_modules; i++)
   1397     modules[i]=DestroyString(modules[i]);
   1398   modules=(char **) RelinquishMagickMemory(modules);
   1399   return(MagickTrue);
   1400 }
   1401 
   1402 /*
   1404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1405 %                                                                             %
   1406 %                                                                             %
   1407 %                                                                             %
   1408 %   R e g i s t e r M o d u l e                                               %
   1409 %                                                                             %
   1410 %                                                                             %
   1411 %                                                                             %
   1412 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1413 %
   1414 %  RegisterModule() adds an entry to the module list.  It returns a pointer to
   1415 %  the registered entry on success.
   1416 %
   1417 %  The format of the RegisterModule module is:
   1418 %
   1419 %      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
   1420 %        ExceptionInfo *exception)
   1421 %
   1422 %  A description of each parameter follows:
   1423 %
   1424 %    o info: a pointer to the registered entry is returned.
   1425 %
   1426 %    o module_info: a pointer to the ModuleInfo structure to register.
   1427 %
   1428 %    o exception: return any errors or warnings in this structure.
   1429 %
   1430 */
   1431 static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
   1432   ExceptionInfo *exception)
   1433 {
   1434   MagickBooleanType
   1435     status;
   1436 
   1437   assert(module_info != (ModuleInfo *) NULL);
   1438   assert(module_info->signature == MagickCoreSignature);
   1439   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
   1440   if (module_list == (SplayTreeInfo *) NULL)
   1441     return((const ModuleInfo *) NULL);
   1442   status=AddValueToSplayTree(module_list,module_info->tag,module_info);
   1443   if (status == MagickFalse)
   1444     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
   1445       "MemoryAllocationFailed","`%s'",module_info->tag);
   1446   return(module_info);
   1447 }
   1448 
   1449 /*
   1451 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1452 %                                                                             %
   1453 %                                                                             %
   1454 %                                                                             %
   1455 %  T a g T o C o d e r M o d u l e N a m e                                    %
   1456 %                                                                             %
   1457 %                                                                             %
   1458 %                                                                             %
   1459 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1460 %
   1461 %  TagToCoderModuleName() munges a module tag and obtains the filename of the
   1462 %  corresponding module.
   1463 %
   1464 %  The format of the TagToCoderModuleName module is:
   1465 %
   1466 %      char *TagToCoderModuleName(const char *tag,char *name)
   1467 %
   1468 %  A description of each parameter follows:
   1469 %
   1470 %    o tag: a character string representing the module tag.
   1471 %
   1472 %    o name: return the module name here.
   1473 %
   1474 */
   1475 static void TagToCoderModuleName(const char *tag,char *name)
   1476 {
   1477   assert(tag != (char *) NULL);
   1478   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
   1479   assert(name != (char *) NULL);
   1480 #if defined(MAGICKCORE_LTDL_DELEGATE)
   1481   (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
   1482   (void) LocaleLower(name);
   1483 #else
   1484 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
   1485   if (LocaleNCompare("IM_MOD_",tag,7) == 0)
   1486     (void) CopyMagickString(name,tag,MagickPathExtent);
   1487   else
   1488     {
   1489 #if defined(_DEBUG)
   1490       (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_DB_%s_.dll",tag);
   1491 #else
   1492       (void) FormatLocaleString(name,MagickPathExtent,"IM_MOD_RL_%s_.dll",tag);
   1493 #endif
   1494     }
   1495 #endif
   1496 #endif
   1497 }
   1498 
   1499 /*
   1501 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1502 %                                                                             %
   1503 %                                                                             %
   1504 %                                                                             %
   1505 %  T a g T o F i l t e r M o d u l e N a m e                                  %
   1506 %                                                                             %
   1507 %                                                                             %
   1508 %                                                                             %
   1509 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1510 %
   1511 %  TagToFilterModuleName() munges a module tag and returns the filename of the
   1512 %  corresponding filter module.
   1513 %
   1514 %  The format of the TagToFilterModuleName module is:
   1515 %
   1516 %      void TagToFilterModuleName(const char *tag,char name)
   1517 %
   1518 %  A description of each parameter follows:
   1519 %
   1520 %    o tag: a character string representing the module tag.
   1521 %
   1522 %    o name: return the filter name here.
   1523 %
   1524 */
   1525 static void TagToFilterModuleName(const char *tag,char *name)
   1526 {
   1527   assert(tag != (char *) NULL);
   1528   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
   1529   assert(name != (char *) NULL);
   1530 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
   1531   (void) FormatLocaleString(name,MagickPathExtent,"FILTER_%s_.dll",tag);
   1532 #elif !defined(MAGICKCORE_LTDL_DELEGATE)
   1533   (void) FormatLocaleString(name,MagickPathExtent,"%s.dll",tag);
   1534 #else
   1535   (void) FormatLocaleString(name,MagickPathExtent,"%s.la",tag);
   1536 #endif
   1537 }
   1538 
   1539 /*
   1541 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1542 %                                                                             %
   1543 %                                                                             %
   1544 %                                                                             %
   1545 %   T a g T o M o d u l e N a m e                                             %
   1546 %                                                                             %
   1547 %                                                                             %
   1548 %                                                                             %
   1549 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1550 %
   1551 %  TagToModuleName() munges the module tag name and returns an upper-case tag
   1552 %  name as the input string, and a user-provided format.
   1553 %
   1554 %  The format of the TagToModuleName module is:
   1555 %
   1556 %      TagToModuleName(const char *tag,const char *format,char *module)
   1557 %
   1558 %  A description of each parameter follows:
   1559 %
   1560 %    o tag: the module tag.
   1561 %
   1562 %    o format: a sprintf-compatible format string containing %s where the
   1563 %      upper-case tag name is to be inserted.
   1564 %
   1565 %    o module: pointer to a destination buffer for the formatted result.
   1566 %
   1567 */
   1568 static void TagToModuleName(const char *tag,const char *format,char *module)
   1569 {
   1570   char
   1571     name[MagickPathExtent];
   1572 
   1573   assert(tag != (const char *) NULL);
   1574   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
   1575   assert(format != (const char *) NULL);
   1576   assert(module != (char *) NULL);
   1577   (void) CopyMagickString(name,tag,MagickPathExtent);
   1578   LocaleUpper(name);
   1579 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
   1580   (void) FormatLocaleString(module,MagickPathExtent,format,name);
   1581 #else
   1582   {
   1583     char
   1584       prefix_format[MagickPathExtent];
   1585 
   1586     (void) FormatLocaleString(prefix_format,MagickPathExtent,"%s%s",
   1587       MAGICKCORE_NAMESPACE_PREFIX,format);
   1588     (void) FormatLocaleString(module,MagickPathExtent,prefix_format,name);
   1589   }
   1590 #endif
   1591 }
   1592 
   1593 /*
   1595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1596 %                                                                             %
   1597 %                                                                             %
   1598 %                                                                             %
   1599 %   U n r e g i s t e r M o d u l e                                           %
   1600 %                                                                             %
   1601 %                                                                             %
   1602 %                                                                             %
   1603 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
   1604 %
   1605 %  UnregisterModule() unloads a module, and invokes its de-registration module.
   1606 %  Returns MagickTrue on success, and MagickFalse if there is an error.
   1607 %
   1608 %  The format of the UnregisterModule module is:
   1609 %
   1610 %      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
   1611 %        ExceptionInfo *exception)
   1612 %
   1613 %  A description of each parameter follows:
   1614 %
   1615 %    o module_info: the module info.
   1616 %
   1617 %    o exception: return any errors or warnings in this structure.
   1618 %
   1619 */
   1620 static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
   1621   ExceptionInfo *exception)
   1622 {
   1623   /*
   1624     Locate and execute UnregisterFORMATImage module.
   1625   */
   1626   assert(module_info != (const ModuleInfo *) NULL);
   1627   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
   1628   assert(exception != (ExceptionInfo *) NULL);
   1629   if (module_info->unregister_module == NULL)
   1630     return(MagickTrue);
   1631   module_info->unregister_module();
   1632   if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
   1633     {
   1634       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
   1635         "UnableToCloseModule","'%s': %s",module_info->tag,lt_dlerror());
   1636       return(MagickFalse);
   1637     }
   1638   return(MagickTrue);
   1639 }
   1640 #else
   1641 
   1642 #if !defined(MAGICKCORE_BUILD_MODULES)
   1643 extern size_t
   1644   analyzeImage(Image **,const int,const char **,ExceptionInfo *);
   1645 #endif
   1646 
   1647 MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
   1648   ExceptionInfo *magick_unused(exception))
   1649 {
   1650   return(MagickTrue);
   1651 }
   1652 
   1653 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
   1654   Image **image,const int argc,const char **argv,ExceptionInfo *exception)
   1655 {
   1656   PolicyRights
   1657     rights;
   1658 
   1659   assert(image != (Image **) NULL);
   1660   assert((*image)->signature == MagickCoreSignature);
   1661   if ((*image)->debug != MagickFalse)
   1662     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
   1663   rights=ReadPolicyRights;
   1664   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
   1665     {
   1666       errno=EPERM;
   1667       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
   1668         "NotAuthorized","`%s'",tag);
   1669       return(MagickFalse);
   1670     }
   1671 #if defined(MAGICKCORE_BUILD_MODULES)
   1672   (void) tag;
   1673   (void) argc;
   1674   (void) argv;
   1675   (void) exception;
   1676 #else
   1677   {
   1678     ImageFilterHandler
   1679       *image_filter;
   1680 
   1681     image_filter=(ImageFilterHandler *) NULL;
   1682     if (LocaleCompare("analyze",tag) == 0)
   1683       image_filter=(ImageFilterHandler *) analyzeImage;
   1684     if (image_filter == (ImageFilterHandler *) NULL)
   1685       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1686         "UnableToLoadModule","`%s'",tag);
   1687     else
   1688       {
   1689         size_t
   1690           signature;
   1691 
   1692         if ((*image)->debug != MagickFalse)
   1693           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
   1694             "Invoking \"%s\" static image filter",tag);
   1695         signature=image_filter(image,argc,argv,exception);
   1696         if ((*image)->debug != MagickFalse)
   1697           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
   1698             tag);
   1699         if (signature != MagickImageFilterSignature)
   1700           {
   1701             (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
   1702               "ImageFilterSignatureMismatch","'%s': %8lx != %8lx",tag,
   1703               (unsigned long) signature,(unsigned long)
   1704               MagickImageFilterSignature);
   1705             return(MagickFalse);
   1706           }
   1707       }
   1708   }
   1709 #endif
   1710   return(MagickTrue);
   1711 }
   1712 #endif
   1713