MagickCore  6.7.5
module.c
Go to the documentation of this file.
00001 /*
00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00003 %                                                                             %
00004 %                                                                             %
00005 %                                                                             %
00006 %                  M   M   OOO   DDDD   U   U  L      EEEEE                   %
00007 %                  MM MM  O   O  D   D  U   U  L      E                       %
00008 %                  M M M  O   O  D   D  U   U  L      EEE                     %
00009 %                  M   M  O   O  D   D  U   U  L      E                       %
00010 %                  M   M   OOO   DDDD    UUU   LLLLL  EEEEE                   %
00011 %                                                                             %
00012 %                                                                             %
00013 %                          MagickCore Module Methods                          %
00014 %                                                                             %
00015 %                              Software Design                                %
00016 %                              Bob Friesenhahn                                %
00017 %                                March 2000                                   %
00018 %                                                                             %
00019 %                                                                             %
00020 %  Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization      %
00021 %  dedicated to making software imaging solutions freely available.           %
00022 %                                                                             %
00023 %  You may not use this file except in compliance with the License.  You may  %
00024 %  obtain a copy of the License at                                            %
00025 %                                                                             %
00026 %    http://www.imagemagick.org/script/license.php                            %
00027 %                                                                             %
00028 %  Unless required by applicable law or agreed to in writing, software        %
00029 %  distributed under the License is distributed on an "AS IS" BASIS,          %
00030 %  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.   %
00031 %  See the License for the specific language governing permissions and        %
00032 %  limitations under the License.                                             %
00033 %                                                                             %
00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00035 %
00036 %
00037 %
00038 */
00039 
00040 /*
00041   Include declarations.
00042 */
00043 #include "MagickCore/studio.h"
00044 #include "MagickCore/blob.h"
00045 #include "MagickCore/coder.h"
00046 #include "MagickCore/client.h"
00047 #include "MagickCore/configure.h"
00048 #include "MagickCore/exception.h"
00049 #include "MagickCore/exception-private.h"
00050 #include "MagickCore/log.h"
00051 #include "MagickCore/hashmap.h"
00052 #include "MagickCore/magic.h"
00053 #include "MagickCore/magick.h"
00054 #include "MagickCore/memory_.h"
00055 #include "MagickCore/module.h"
00056 #include "MagickCore/module-private.h"
00057 #include "MagickCore/policy.h"
00058 #include "MagickCore/semaphore.h"
00059 #include "MagickCore/splay-tree.h"
00060 #include "MagickCore/static.h"
00061 #include "MagickCore/string_.h"
00062 #include "MagickCore/string-private.h"
00063 #include "MagickCore/token.h"
00064 #include "MagickCore/utility.h"
00065 #include "MagickCore/utility-private.h"
00066 #if defined(MAGICKCORE_MODULES_SUPPORT)
00067 #if defined(MAGICKCORE_LTDL_DELEGATE)
00068 #include "ltdl.h"
00069 typedef lt_dlhandle ModuleHandle;
00070 #else
00071 typedef void *ModuleHandle;
00072 #endif
00073 
00074 /*
00075   Define declarations.
00076 */
00077 #if defined(MAGICKCORE_LTDL_DELEGATE)
00078 #  define ModuleGlobExpression "*.la"
00079 #else
00080 #  if defined(_DEBUG)
00081 #    define ModuleGlobExpression "IM_MOD_DB_*.dll"
00082 #  else
00083 #    define ModuleGlobExpression "IM_MOD_RL_*.dll"
00084 #  endif
00085 #endif
00086 
00087 /*
00088   Global declarations.
00089 */
00090 static SemaphoreInfo
00091   *module_semaphore = (SemaphoreInfo *) NULL;
00092 
00093 static SplayTreeInfo
00094   *module_list = (SplayTreeInfo *) NULL;
00095 
00096 static volatile MagickBooleanType
00097   instantiate_module = MagickFalse;
00098 
00099 /*
00100   Forward declarations.
00101 */
00102 static const ModuleInfo
00103   *RegisterModule(const ModuleInfo *,ExceptionInfo *);
00104 
00105 static MagickBooleanType
00106   GetMagickModulePath(const char *,MagickModuleType,char *,ExceptionInfo *),
00107   InitializeModuleList(ExceptionInfo *),
00108   UnregisterModule(const ModuleInfo *,ExceptionInfo *);
00109 
00110 static void
00111   TagToCoderModuleName(const char *,char *),
00112   TagToFilterModuleName(const char *,char *),
00113   TagToModuleName(const char *,const char *,char *);
00114 
00115 /*
00116 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00117 %                                                                             %
00118 %                                                                             %
00119 %                                                                             %
00120 %   A c q u i r e M o d u l e I n f o                                         %
00121 %                                                                             %
00122 %                                                                             %
00123 %                                                                             %
00124 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00125 %
00126 %  AcquireModuleInfo() allocates the ModuleInfo structure.
00127 %
00128 %  The format of the AcquireModuleInfo method is:
00129 %
00130 %      ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
00131 %
00132 %  A description of each parameter follows:
00133 %
00134 %    o path: the path associated with the tag.
00135 %
00136 %    o tag: a character string that represents the image format we are
00137 %      looking for.
00138 %
00139 */
00140 MagickExport ModuleInfo *AcquireModuleInfo(const char *path,const char *tag)
00141 {
00142   ModuleInfo
00143     *module_info;
00144 
00145   module_info=(ModuleInfo *) AcquireMagickMemory(sizeof(*module_info));
00146   if (module_info == (ModuleInfo *) NULL)
00147     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00148   (void) ResetMagickMemory(module_info,0,sizeof(*module_info));
00149   if (path != (const char *) NULL)
00150     module_info->path=ConstantString(path);
00151   if (tag != (const char *) NULL)
00152     module_info->tag=ConstantString(tag);
00153   module_info->timestamp=time(0);
00154   module_info->signature=MagickSignature;
00155   return(module_info);
00156 }
00157 
00158 /*
00159 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00160 %                                                                             %
00161 %                                                                             %
00162 %                                                                             %
00163 %   D e s t r o y M o d u l e L i s t                                         %
00164 %                                                                             %
00165 %                                                                             %
00166 %                                                                             %
00167 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00168 %
00169 %  DestroyModuleList() unregisters any previously loaded modules and exits
00170 %  the module loaded environment.
00171 %
00172 %  The format of the DestroyModuleList module is:
00173 %
00174 %      void DestroyModuleList(void)
00175 %
00176 */
00177 MagickExport void DestroyModuleList(void)
00178 {
00179   /*
00180     Destroy magick modules.
00181   */
00182   LockSemaphoreInfo(module_semaphore);
00183 #if defined(MAGICKCORE_MODULES_SUPPORT)
00184   if (module_list != (SplayTreeInfo *) NULL)
00185     module_list=DestroySplayTree(module_list);
00186   if (instantiate_module != MagickFalse)
00187     {
00188 #if !defined(MAGICKCORE_JP2_DELEGATE)
00189       (void) lt_dlexit();  /* Jasper has an errant atexit() handler */
00190 #endif
00191       instantiate_module=MagickFalse;
00192     }
00193 #endif
00194   UnlockSemaphoreInfo(module_semaphore);
00195 }
00196 
00197 /*
00198 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00199 %                                                                             %
00200 %                                                                             %
00201 %                                                                             %
00202 %   G e t M o d u l e I n f o                                                 %
00203 %                                                                             %
00204 %                                                                             %
00205 %                                                                             %
00206 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00207 %
00208 %  GetModuleInfo() returns a pointer to a ModuleInfo structure that matches the
00209 %  specified tag.  If tag is NULL, the head of the module list is returned. If
00210 %  no modules are loaded, or the requested module is not found, NULL is
00211 %  returned.
00212 %
00213 %  The format of the GetModuleInfo module is:
00214 %
00215 %      ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
00216 %
00217 %  A description of each parameter follows:
00218 %
00219 %    o tag: a character string that represents the image format we are
00220 %      looking for.
00221 %
00222 %    o exception: return any errors or warnings in this structure.
00223 %
00224 */
00225 MagickExport ModuleInfo *GetModuleInfo(const char *tag,ExceptionInfo *exception)
00226 {
00227   if ((module_list == (SplayTreeInfo *) NULL) ||
00228       (instantiate_module == MagickFalse))
00229     if (InitializeModuleList(exception) == MagickFalse)
00230       return((ModuleInfo *) NULL);
00231   if ((module_list == (SplayTreeInfo *) NULL) ||
00232       (GetNumberOfNodesInSplayTree(module_list) == 0))
00233     return((ModuleInfo *) NULL);
00234   if ((tag == (const char *) NULL) || (LocaleCompare(tag,"*") == 0))
00235     {
00236       ModuleInfo
00237         *p;
00238 
00239 #if defined(MAGICKCORE_MODULES_SUPPORT)
00240       if (LocaleCompare(tag,"*") == 0)
00241         (void) OpenModules(exception);
00242 #endif
00243       LockSemaphoreInfo(module_semaphore);
00244       ResetSplayTreeIterator(module_list);
00245       p=(ModuleInfo *) GetNextValueInSplayTree(module_list);
00246       UnlockSemaphoreInfo(module_semaphore);
00247       return(p);
00248     }
00249   return((ModuleInfo *) GetValueFromSplayTree(module_list,tag));
00250 }
00251 
00252 /*
00253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00254 %                                                                             %
00255 %                                                                             %
00256 %                                                                             %
00257 %   G e t M o d u l e I n f o L i s t                                         %
00258 %                                                                             %
00259 %                                                                             %
00260 %                                                                             %
00261 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00262 %
00263 %  GetModuleInfoList() returns any modules that match the specified pattern.
00264 %
00265 %  The format of the GetModuleInfoList function is:
00266 %
00267 %      const ModuleInfo **GetModuleInfoList(const char *pattern,
00268 %        size_t *number_modules,ExceptionInfo *exception)
00269 %
00270 %  A description of each parameter follows:
00271 %
00272 %    o pattern: Specifies a pointer to a text string containing a pattern.
00273 %
00274 %    o number_modules:  This integer returns the number of modules in the list.
00275 %
00276 %    o exception: return any errors or warnings in this structure.
00277 %
00278 */
00279 
00280 #if defined(__cplusplus) || defined(c_plusplus)
00281 extern "C" {
00282 #endif
00283 
00284 static int ModuleInfoCompare(const void *x,const void *y)
00285 {
00286   const ModuleInfo
00287     **p,
00288     **q;
00289 
00290   p=(const ModuleInfo **) x,
00291   q=(const ModuleInfo **) y;
00292   if (LocaleCompare((*p)->path,(*q)->path) == 0)
00293     return(LocaleCompare((*p)->tag,(*q)->tag));
00294   return(LocaleCompare((*p)->path,(*q)->path));
00295 }
00296 
00297 #if defined(__cplusplus) || defined(c_plusplus)
00298 }
00299 #endif
00300 
00301 MagickExport const ModuleInfo **GetModuleInfoList(const char *pattern,
00302   size_t *number_modules,ExceptionInfo *exception)
00303 {
00304   const ModuleInfo
00305     **modules;
00306 
00307   register const ModuleInfo
00308     *p;
00309 
00310   register ssize_t
00311     i;
00312 
00313   /*
00314     Allocate module list.
00315   */
00316   assert(pattern != (char *) NULL);
00317   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
00318   assert(number_modules != (size_t *) NULL);
00319   *number_modules=0;
00320   p=GetModuleInfo("*",exception);
00321   if (p == (const ModuleInfo *) NULL)
00322     return((const ModuleInfo **) NULL);
00323   modules=(const ModuleInfo **) AcquireQuantumMemory((size_t)
00324     GetNumberOfNodesInSplayTree(module_list)+1UL,sizeof(*modules));
00325   if (modules == (const ModuleInfo **) NULL)
00326     return((const ModuleInfo **) NULL);
00327   /*
00328     Generate module list.
00329   */
00330   LockSemaphoreInfo(module_semaphore);
00331   ResetSplayTreeIterator(module_list);
00332   p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
00333   for (i=0; p != (const ModuleInfo *) NULL; )
00334   {
00335     if ((p->stealth == MagickFalse) &&
00336         (GlobExpression(p->tag,pattern,MagickFalse) != MagickFalse))
00337       modules[i++]=p;
00338     p=(const ModuleInfo *) GetNextValueInSplayTree(module_list);
00339   }
00340   UnlockSemaphoreInfo(module_semaphore);
00341   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleInfoCompare);
00342   modules[i]=(ModuleInfo *) NULL;
00343   *number_modules=(size_t) i;
00344   return(modules);
00345 }
00346 
00347 /*
00348 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00349 %                                                                             %
00350 %                                                                             %
00351 %                                                                             %
00352 %   G e t M o d u l e L i s t                                                 %
00353 %                                                                             %
00354 %                                                                             %
00355 %                                                                             %
00356 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00357 %
00358 %  GetModuleList() returns any image format modules that match the specified
00359 %  pattern.
00360 %
00361 %  The format of the GetModuleList function is:
00362 %
00363 %      char **GetModuleList(const char *pattern,const MagickModuleType type,
00364 %        size_t *number_modules,ExceptionInfo *exception)
00365 %
00366 %  A description of each parameter follows:
00367 %
00368 %    o pattern: Specifies a pointer to a text string containing a pattern.
00369 %
00370 %    o type: choose from MagickImageCoderModule or MagickImageFilterModule.
00371 %
00372 %    o number_modules:  This integer returns the number of modules in the
00373 %      list.
00374 %
00375 %    o exception: return any errors or warnings in this structure.
00376 %
00377 */
00378 
00379 #if defined(__cplusplus) || defined(c_plusplus)
00380 extern "C" {
00381 #endif
00382 
00383 static int ModuleCompare(const void *x,const void *y)
00384 {
00385   register const char
00386     **p,
00387     **q;
00388 
00389    p=(const char **) x;
00390   q=(const char **) y;
00391   return(LocaleCompare(*p,*q));
00392 }
00393 
00394 #if defined(__cplusplus) || defined(c_plusplus)
00395 }
00396 #endif
00397 
00398 static inline int MagickReadDirectory(DIR *directory,struct dirent *entry,
00399   struct dirent **result)
00400 {
00401 #if defined(MAGICKCORE_HAVE_READDIR_R)
00402   return(readdir_r(directory,entry,result));
00403 #else
00404   (void) entry;
00405   errno=0;
00406   *result=readdir(directory);
00407   return(errno);
00408 #endif
00409 }
00410 
00411 MagickExport char **GetModuleList(const char *pattern,
00412   const MagickModuleType type,size_t *number_modules,ExceptionInfo *exception)
00413 {
00414   char
00415     **modules,
00416     filename[MaxTextExtent],
00417     module_path[MaxTextExtent],
00418     path[MaxTextExtent];
00419 
00420   DIR
00421     *directory;
00422 
00423   MagickBooleanType
00424     status;
00425 
00426   register ssize_t
00427     i;
00428 
00429   size_t
00430     max_entries;
00431 
00432   struct dirent
00433     *buffer,
00434     *entry;
00435 
00436   /*
00437     Locate all modules in the image coder or filter path.
00438   */
00439   switch (type)
00440   {
00441     case MagickImageCoderModule:
00442     default:
00443     {
00444       TagToCoderModuleName("magick",filename);
00445       status=GetMagickModulePath(filename,MagickImageCoderModule,module_path,
00446         exception);
00447       break;
00448     }
00449     case MagickImageFilterModule:
00450     {
00451       TagToFilterModuleName("analyze",filename);
00452       status=GetMagickModulePath(filename,MagickImageFilterModule,module_path,
00453         exception);
00454       break;
00455     }
00456   }
00457   if (status == MagickFalse)
00458     return((char **) NULL);
00459   GetPathComponent(module_path,HeadPath,path);
00460   max_entries=255;
00461   modules=(char **) AcquireQuantumMemory((size_t) max_entries+1UL,
00462     sizeof(*modules));
00463   if (modules == (char **) NULL)
00464     return((char **) NULL);
00465   *modules=(char *) NULL;
00466   directory=opendir(path);
00467   if (directory == (DIR *) NULL)
00468     {
00469       modules=(char **) RelinquishMagickMemory(modules);
00470       return((char **) NULL);
00471     }
00472   buffer=(struct dirent *) AcquireMagickMemory(sizeof(*buffer)+
00473     FILENAME_MAX+1);
00474   if (buffer == (struct dirent *) NULL)
00475     ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
00476   i=0;
00477   while ((MagickReadDirectory(directory,buffer,&entry) == 0) &&
00478          (entry != (struct dirent *) NULL))
00479   {
00480     status=GlobExpression(entry->d_name,ModuleGlobExpression,MagickFalse);
00481     if (status == MagickFalse)
00482       continue;
00483     if (GlobExpression(entry->d_name,pattern,MagickFalse) == MagickFalse)
00484       continue;
00485     if (i >= (ssize_t) max_entries)
00486       {
00487         modules=(char **) NULL;
00488         if (~max_entries > max_entries)
00489           modules=(char **) ResizeQuantumMemory(modules,(size_t)
00490             (max_entries << 1),sizeof(*modules));
00491         max_entries<<=1;
00492         if (modules == (char **) NULL)
00493           break;
00494       }
00495     /*
00496       Add new module name to list.
00497     */
00498     modules[i]=AcquireString((char *) NULL);
00499     GetPathComponent(entry->d_name,BasePath,modules[i]);
00500     if (LocaleNCompare("IM_MOD_",modules[i],7) == 0)
00501       {
00502         (void) CopyMagickString(modules[i],modules[i]+10,MaxTextExtent);
00503         modules[i][strlen(modules[i])-1]='\0';
00504       }
00505     i++;
00506   }
00507   buffer=(struct dirent *) RelinquishMagickMemory(buffer);
00508   (void) closedir(directory);
00509   if (modules == (char **) NULL)
00510     {
00511       (void) ThrowMagickException(exception,GetMagickModule(),ConfigureError,
00512         "MemoryAllocationFailed","`%s'",pattern);
00513       return((char **) NULL);
00514     }
00515   qsort((void *) modules,(size_t) i,sizeof(*modules),ModuleCompare);
00516   modules[i]=(char *) NULL;
00517   *number_modules=(size_t) i;
00518   return(modules);
00519 }
00520 
00521 /*
00522 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00523 %                                                                             %
00524 %                                                                             %
00525 %                                                                             %
00526 %  G e t M a g i c k M o d u l e P a t h                                      %
00527 %                                                                             %
00528 %                                                                             %
00529 %                                                                             %
00530 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00531 %
00532 %  GetMagickModulePath() finds a module with the specified module type and
00533 %  filename.
00534 %
00535 %  The format of the GetMagickModulePath module is:
00536 %
00537 %      MagickBooleanType GetMagickModulePath(const char *filename,
00538 %        MagickModuleType module_type,char *path,ExceptionInfo *exception)
00539 %
00540 %  A description of each parameter follows:
00541 %
00542 %    o filename: the module file name.
00543 %
00544 %    o module_type: the module type: MagickImageCoderModule or
00545 %      MagickImageFilterModule.
00546 %
00547 %    o path: the path associated with the filename.
00548 %
00549 %    o exception: return any errors or warnings in this structure.
00550 %
00551 */
00552 static MagickBooleanType GetMagickModulePath(const char *filename,
00553   MagickModuleType module_type,char *path,ExceptionInfo *exception)
00554 {
00555   char
00556     *module_path;
00557 
00558   assert(filename != (const char *) NULL);
00559   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
00560   assert(path != (char *) NULL);
00561   assert(exception != (ExceptionInfo *) NULL);
00562   (void) CopyMagickString(path,filename,MaxTextExtent);
00563   module_path=(char *) NULL;
00564   switch (module_type)
00565   {
00566     case MagickImageCoderModule:
00567     default:
00568     {
00569       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
00570         "Searching for coder module file \"%s\" ...",filename);
00571       module_path=GetEnvironmentValue("MAGICK_CODER_MODULE_PATH");
00572 #if defined(MAGICKCORE_CODER_PATH)
00573       if (module_path == (char *) NULL)
00574         module_path=AcquireString(MAGICKCORE_CODER_PATH);
00575 #endif
00576       break;
00577     }
00578     case MagickImageFilterModule:
00579     {
00580       (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
00581         "Searching for filter module file \"%s\" ...",filename);
00582       module_path=GetEnvironmentValue("MAGICK_CODER_FILTER_PATH");
00583 #if defined(MAGICKCORE_FILTER_PATH)
00584       if (module_path == (char *) NULL)
00585         module_path=AcquireString(MAGICKCORE_FILTER_PATH);
00586 #endif
00587       break;
00588     }
00589   }
00590   if (module_path != (char *) NULL)
00591     {
00592       register char
00593         *p,
00594         *q;
00595 
00596       for (p=module_path-1; p != (char *) NULL; )
00597       {
00598         (void) CopyMagickString(path,p+1,MaxTextExtent);
00599         q=strchr(path,DirectoryListSeparator);
00600         if (q != (char *) NULL)
00601           *q='\0';
00602         q=path+strlen(path)-1;
00603         if ((q >= path) && (*q != *DirectorySeparator))
00604           (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
00605         (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00606         if (IsPathAccessible(path) != MagickFalse)
00607           {
00608             module_path=DestroyString(module_path);
00609             return(MagickTrue);
00610           }
00611         p=strchr(p+1,DirectoryListSeparator);
00612       }
00613       module_path=DestroyString(module_path);
00614     }
00615 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
00616   else
00617 #if defined(MAGICKCORE_CODER_PATH)
00618     {
00619       const char
00620         *directory;
00621 
00622       /*
00623         Search hard coded paths.
00624       */
00625       switch (module_type)
00626       {
00627         case MagickImageCoderModule:
00628         default:
00629         {
00630           directory=MAGICKCORE_CODER_PATH;
00631           break;
00632         }
00633         case MagickImageFilterModule:
00634         {
00635           directory=MAGICKCORE_FILTER_PATH;
00636           break;
00637         }
00638       }
00639       (void) FormatLocaleString(path,MaxTextExtent,"%s%s",directory,filename);
00640       if (IsPathAccessible(path) == MagickFalse)
00641         {
00642           ThrowFileException(exception,ConfigureWarning,
00643             "UnableToOpenModuleFile",path);
00644           return(MagickFalse);
00645         }
00646       return(MagickTrue);
00647     }
00648 #else
00649 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
00650     {
00651       const char
00652         *registery_key;
00653 
00654       unsigned char
00655         *key_value;
00656 
00657       /*
00658         Locate path via registry key.
00659       */
00660       switch (module_type)
00661       {
00662         case MagickImageCoderModule:
00663         default:
00664         {
00665           registery_key="CoderModulesPath";
00666           break;
00667         }
00668         case MagickImageFilterModule:
00669         {
00670           registery_key="FilterModulesPath";
00671           break;
00672         }
00673       }
00674       key_value=NTRegistryKeyLookup(registery_key);
00675       if (key_value == (unsigned char *) NULL)
00676         {
00677           ThrowMagickException(exception,GetMagickModule(),ConfigureError,
00678             "RegistryKeyLookupFailed","`%s'",registery_key);
00679           return(MagickFalse);
00680         }
00681       (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",(char *) key_value,
00682         DirectorySeparator,filename);
00683       key_value=(unsigned char *) RelinquishMagickMemory(key_value);
00684       if (IsPathAccessible(path) == MagickFalse)
00685         {
00686           ThrowFileException(exception,ConfigureWarning,
00687             "UnableToOpenModuleFile",path);
00688           return(MagickFalse);
00689         }
00690       return(MagickTrue);
00691     }
00692 #endif
00693 #endif
00694 #if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
00695 # error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
00696 #endif
00697 #else
00698   {
00699     char
00700       *home;
00701 
00702     home=GetEnvironmentValue("MAGICK_HOME");
00703     if (home != (char *) NULL)
00704       {
00705         /*
00706           Search MAGICK_HOME.
00707         */
00708 #if !defined(MAGICKCORE_POSIX_SUPPORT)
00709         (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",home,
00710           DirectorySeparator,filename);
00711 #else
00712         const char
00713           *directory;
00714 
00715         switch (module_type)
00716         {
00717           case MagickImageCoderModule:
00718           default:
00719           {
00720             directory=MAGICKCORE_CODER_RELATIVE_PATH;
00721             break;
00722           }
00723           case MagickImageFilterModule:
00724           {
00725             directory=MAGICKCORE_FILTER_RELATIVE_PATH;
00726             break;
00727           }
00728         }
00729         (void) FormatLocaleString(path,MaxTextExtent,"%s/lib/%s/%s",home,
00730           directory,filename);
00731 #endif
00732         home=DestroyString(home);
00733         if (IsPathAccessible(path) != MagickFalse)
00734           return(MagickTrue);
00735       }
00736   }
00737   if (*GetClientPath() != '\0')
00738     {
00739       /*
00740         Search based on executable directory.
00741       */
00742 #if !defined(MAGICKCORE_POSIX_SUPPORT)
00743       (void) FormatLocaleString(path,MaxTextExtent,"%s%s%s",GetClientPath(),
00744         DirectorySeparator,filename);
00745 #else
00746       char
00747         prefix[MaxTextExtent];
00748 
00749       const char
00750         *directory;
00751 
00752       switch (module_type)
00753       {
00754         case MagickImageCoderModule:
00755         default:
00756         {
00757           directory="coders";
00758           break;
00759         }
00760         case MagickImageFilterModule:
00761         {
00762           directory="filters";
00763           break;
00764         }
00765       }
00766       (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
00767       ChopPathComponents(prefix,1);
00768       (void) FormatLocaleString(path,MaxTextExtent,
00769         "%s/lib/%s/modules-Q%d/%s/%s",prefix,MAGICKCORE_LIBRARY_RELATIVE_PATH,
00770         MAGICKCORE_QUANTUM_DEPTH,directory,filename);
00771 #endif
00772       if (IsPathAccessible(path) != MagickFalse)
00773         return(MagickTrue);
00774     }
00775 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
00776   {
00777     /*
00778       Search module path.
00779     */
00780     if ((NTGetModulePath("CORE_RL_magick_.dll",path) != MagickFalse) ||
00781         (NTGetModulePath("CORE_DB_magick_.dll",path) != MagickFalse) ||
00782         (NTGetModulePath("Magick.dll",path) != MagickFalse))
00783       {
00784         (void) ConcatenateMagickString(path,DirectorySeparator,MaxTextExtent);
00785         (void) ConcatenateMagickString(path,filename,MaxTextExtent);
00786         if (IsPathAccessible(path) != MagickFalse)
00787           return(MagickTrue);
00788       }
00789   }
00790 #endif
00791   {
00792     char
00793       *home;
00794 
00795     home=GetEnvironmentValue("HOME");
00796     if (home == (char *) NULL)
00797       home=GetEnvironmentValue("USERPROFILE");
00798     if (home != (char *) NULL)
00799       {
00800         /*
00801           Search $HOME/.magick.
00802         */
00803         (void) FormatLocaleString(path,MaxTextExtent,"%s%s.magick%s%s",home,
00804           DirectorySeparator,DirectorySeparator,filename);
00805         home=DestroyString(home);
00806         if (IsPathAccessible(path) != MagickFalse)
00807           return(MagickTrue);
00808       }
00809   }
00810   /*
00811     Search current directory.
00812   */
00813   if (IsPathAccessible(path) != MagickFalse)
00814     return(MagickTrue);
00815   if (exception->severity < ConfigureError)
00816     ThrowFileException(exception,ConfigureWarning,"UnableToOpenModuleFile",
00817       path);
00818   return(MagickFalse);
00819 #endif
00820   return(MagickFalse);
00821 }
00822 
00823 /*
00824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00825 %                                                                             %
00826 %                                                                             %
00827 %                                                                             %
00828 %   I n i t i a l i z e M o d u l e L i s t                                   %
00829 %                                                                             %
00830 %                                                                             %
00831 %                                                                             %
00832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00833 %
00834 %  InitializeModuleList() initializes the module loader.
00835 %
00836 %  The format of the InitializeModuleList() method is:
00837 %
00838 %      InitializeModuleList(Exceptioninfo *exception)
00839 %
00840 %  A description of each parameter follows.
00841 %
00842 %    o exception: return any errors or warnings in this structure.
00843 %
00844 */
00845 
00846 static void *DestroyModuleNode(void *module_info)
00847 {
00848   ExceptionInfo
00849     *exception;
00850 
00851   register ModuleInfo
00852     *p;
00853 
00854   exception=AcquireExceptionInfo();
00855   p=(ModuleInfo *) module_info;
00856   if (UnregisterModule(p,exception) == MagickFalse)
00857     CatchException(exception);
00858   if (p->tag != (char *) NULL)
00859     p->tag=DestroyString(p->tag);
00860   if (p->path != (char *) NULL)
00861     p->path=DestroyString(p->path);
00862   exception=DestroyExceptionInfo(exception);
00863   return(RelinquishMagickMemory(p));
00864 }
00865 
00866 static MagickBooleanType InitializeModuleList(
00867   ExceptionInfo *magick_unused(exception))
00868 {
00869   if ((module_list == (SplayTreeInfo *) NULL) &&
00870       (instantiate_module == MagickFalse))
00871     {
00872       if (module_semaphore == (SemaphoreInfo *) NULL)
00873         AcquireSemaphoreInfo(&module_semaphore);
00874       LockSemaphoreInfo(module_semaphore);
00875       if ((module_list == (SplayTreeInfo *) NULL) &&
00876           (instantiate_module == MagickFalse))
00877         {
00878           MagickBooleanType
00879             status;
00880 
00881           ModuleInfo
00882             *module_info;
00883 
00884           module_list=NewSplayTree(CompareSplayTreeString,
00885             (void *(*)(void *)) NULL,DestroyModuleNode);
00886           if (module_list == (SplayTreeInfo *) NULL)
00887             ThrowFatalException(ResourceLimitFatalError,
00888               "MemoryAllocationFailed");
00889           module_info=AcquireModuleInfo((const char *) NULL,"[boot-strap]");
00890           module_info->stealth=MagickTrue;
00891           status=AddValueToSplayTree(module_list,module_info->tag,module_info);
00892           if (status == MagickFalse)
00893             ThrowFatalException(ResourceLimitFatalError,
00894               "MemoryAllocationFailed");
00895           if (lt_dlinit() != 0)
00896             ThrowFatalException(ModuleFatalError,
00897               "UnableToInitializeModuleLoader");
00898           instantiate_module=MagickTrue;
00899         }
00900       UnlockSemaphoreInfo(module_semaphore);
00901     }
00902   return(module_list != (SplayTreeInfo *) NULL ? MagickTrue : MagickFalse);
00903 }
00904 
00905 /*
00906 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00907 %                                                                             %
00908 %                                                                             %
00909 %                                                                             %
00910 %   I n v o k e D y n a m i c I m a g e F i l t e r                           %
00911 %                                                                             %
00912 %                                                                             %
00913 %                                                                             %
00914 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
00915 %
00916 %  InvokeDynamicImageFilter() invokes a dynamic image filter.
00917 %
00918 %  The format of the InvokeDynamicImageFilter module is:
00919 %
00920 %      MagickBooleanType InvokeDynamicImageFilter(const char *tag,Image **image,
00921 %        const int argc,const char **argv,ExceptionInfo *exception)
00922 %
00923 %  A description of each parameter follows:
00924 %
00925 %    o tag: a character string that represents the name of the particular
00926 %      module.
00927 %
00928 %    o image: the image.
00929 %
00930 %    o argc: a pointer to an integer describing the number of elements in the
00931 %      argument vector.
00932 %
00933 %    o argv: a pointer to a text array containing the command line arguments.
00934 %
00935 %    o exception: return any errors or warnings in this structure.
00936 %
00937 */
00938 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
00939   Image **images,const int argc,const char **argv,ExceptionInfo *exception)
00940 {
00941   char
00942     name[MaxTextExtent],
00943     path[MaxTextExtent];
00944 
00945   ImageFilterHandler
00946     *image_filter;
00947 
00948   MagickBooleanType
00949     status;
00950 
00951   ModuleHandle
00952     handle;
00953 
00954   PolicyRights
00955     rights;
00956 
00957   /*
00958     Find the module.
00959   */
00960   assert(images != (Image **) NULL);
00961   assert((*images)->signature == MagickSignature);
00962   if ((*images)->debug != MagickFalse)
00963     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",
00964       (*images)->filename);
00965 #if !defined(MAGICKCORE_BUILD_MODULES)
00966   {
00967     MagickBooleanType
00968       status;
00969 
00970     status=InvokeStaticImageFilter(tag,images,argc,argv,exception);
00971     if (status != MagickFalse)
00972       return(status);
00973   }
00974 #endif
00975   rights=ReadPolicyRights;
00976   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
00977     {
00978       errno=EPERM;
00979       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
00980         "NotAuthorized","`%s'",tag);
00981       return(MagickFalse);
00982     }
00983   TagToFilterModuleName(tag,name);
00984   status=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
00985   if (status == MagickFalse)
00986     {
00987       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
00988         "UnableToLoadModule","`%s': %s",name,path);
00989       return(MagickFalse);
00990     }
00991   /*
00992     Open the module.
00993   */
00994   handle=(ModuleHandle) lt_dlopen(path);
00995   if (handle == (ModuleHandle) NULL)
00996     {
00997       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
00998         "UnableToLoadModule","`%s': %s",name,lt_dlerror());
00999       return(MagickFalse);
01000     }
01001   /*
01002     Locate the module.
01003   */
01004 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
01005   (void) FormatLocaleString(name,MaxTextExtent,"%sImage",tag);
01006 #else
01007   (void) FormatLocaleString(name,MaxTextExtent,"%s%sImage",
01008     MAGICKCORE_NAMESPACE_PREFIX,tag);
01009 #endif
01010   /*
01011     Execute the module.
01012   */
01013   ClearMagickException(exception);
01014   image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
01015   if (image_filter == (ImageFilterHandler *) NULL)
01016     (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01017       "UnableToLoadModule","`%s': %s",name,lt_dlerror());
01018   else
01019     {
01020       size_t
01021         signature;
01022 
01023       if ((*images)->debug != MagickFalse)
01024         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
01025           "Invoking \"%s\" dynamic image filter",tag);
01026       signature=image_filter(images,argc,argv,exception);
01027       if ((*images)->debug != MagickFalse)
01028         (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
01029           tag);
01030       if (signature != MagickImageFilterSignature)
01031         (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01032           "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,
01033           (unsigned long) signature,(unsigned long) MagickImageFilterSignature);
01034     }
01035   /*
01036     Close the module.
01037   */
01038   if (lt_dlclose(handle) != 0)
01039     (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
01040       "UnableToCloseModule","`%s': %s",name,lt_dlerror());
01041   return(exception->severity < ErrorException ? MagickTrue : MagickFalse);
01042 }
01043 
01044 /*
01045 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01046 %                                                                             %
01047 %                                                                             %
01048 %                                                                             %
01049 %  L i s t M o d u l e I n f o                                                %
01050 %                                                                             %
01051 %                                                                             %
01052 %                                                                             %
01053 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01054 %
01055 %  ListModuleInfo() lists the module info to a file.
01056 %
01057 %  The format of the ListModuleInfo module is:
01058 %
01059 %      MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
01060 %
01061 %  A description of each parameter follows.
01062 %
01063 %    o file:  An pointer to a FILE.
01064 %
01065 %    o exception: return any errors or warnings in this structure.
01066 %
01067 */
01068 MagickExport MagickBooleanType ListModuleInfo(FILE *file,
01069   ExceptionInfo *exception)
01070 {
01071   char
01072     filename[MaxTextExtent],
01073     module_path[MaxTextExtent],
01074     **modules,
01075     path[MaxTextExtent];
01076 
01077   register ssize_t
01078     i;
01079 
01080   size_t
01081     number_modules;
01082 
01083   if (file == (const FILE *) NULL)
01084     file=stdout;
01085   /*
01086     List image coders.
01087   */
01088   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
01089   if (modules == (char **) NULL)
01090     return(MagickFalse);
01091   TagToCoderModuleName("magick",filename);
01092   (void) GetMagickModulePath(filename,MagickImageCoderModule,module_path,
01093     exception);
01094   GetPathComponent(module_path,HeadPath,path);
01095   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
01096   (void) FormatLocaleFile(file,"Image Coder\n");
01097   (void) FormatLocaleFile(file,
01098     "-------------------------------------------------"
01099     "------------------------------\n");
01100   for (i=0; i < (ssize_t) number_modules; i++)
01101   {
01102     (void) FormatLocaleFile(file,"%s",modules[i]);
01103     (void) FormatLocaleFile(file,"\n");
01104   }
01105   (void) fflush(file);
01106   /*
01107     Relinquish resources.
01108   */
01109   for (i=0; i < (ssize_t) number_modules; i++)
01110     modules[i]=DestroyString(modules[i]);
01111   modules=(char **) RelinquishMagickMemory(modules);
01112   /*
01113     List image filters.
01114   */
01115   modules=GetModuleList("*",MagickImageFilterModule,&number_modules,exception);
01116   if (modules == (char **) NULL)
01117     return(MagickFalse);
01118   TagToFilterModuleName("analyze",filename);
01119   (void) GetMagickModulePath(filename,MagickImageFilterModule,module_path,
01120     exception);
01121   GetPathComponent(module_path,HeadPath,path);
01122   (void) FormatLocaleFile(file,"\nPath: %s\n\n",path);
01123   (void) FormatLocaleFile(file,"Image Filter\n");
01124   (void) FormatLocaleFile(file,
01125     "-------------------------------------------------"
01126     "------------------------------\n");
01127   for (i=0; i < (ssize_t) number_modules; i++)
01128   {
01129     (void) FormatLocaleFile(file,"%s",modules[i]);
01130     (void) FormatLocaleFile(file,"\n");
01131   }
01132   (void) fflush(file);
01133   /*
01134     Relinquish resources.
01135   */
01136   for (i=0; i < (ssize_t) number_modules; i++)
01137     modules[i]=DestroyString(modules[i]);
01138   modules=(char **) RelinquishMagickMemory(modules);
01139   return(MagickTrue);
01140 }
01141 
01142 /*
01143 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01144 %                                                                             %
01145 %                                                                             %
01146 %                                                                             %
01147 +   M o d u l e C o m p o n e n t G e n e s i s                               %
01148 %                                                                             %
01149 %                                                                             %
01150 %                                                                             %
01151 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01152 %
01153 %  ModuleComponentGenesis() instantiates the module component.
01154 %
01155 %  The format of the ModuleComponentGenesis method is:
01156 %
01157 %      MagickBooleanType ModuleComponentGenesis(void)
01158 %
01159 */
01160 MagickPrivate MagickBooleanType ModuleComponentGenesis(void)
01161 {
01162   ExceptionInfo
01163     *exception;
01164 
01165   MagickBooleanType
01166     status;
01167 
01168   AcquireSemaphoreInfo(&module_semaphore);
01169   exception=AcquireExceptionInfo();
01170   status=InitializeModuleList(exception);
01171   exception=DestroyExceptionInfo(exception);
01172   return(status);
01173 }
01174 
01175 /*
01176 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01177 %                                                                             %
01178 %                                                                             %
01179 %                                                                             %
01180 +   M o d u l e C o m p o n e n t T e r m i n u s                             %
01181 %                                                                             %
01182 %                                                                             %
01183 %                                                                             %
01184 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01185 %
01186 %  ModuleComponentTerminus() destroys the module component.
01187 %
01188 %  The format of the ModuleComponentTerminus method is:
01189 %
01190 %      ModuleComponentTerminus(void)
01191 %
01192 */
01193 MagickPrivate void ModuleComponentTerminus(void)
01194 {
01195   if (module_semaphore == (SemaphoreInfo *) NULL)
01196     AcquireSemaphoreInfo(&module_semaphore);
01197   DestroyModuleList();
01198   DestroySemaphoreInfo(&module_semaphore);
01199 }
01200 
01201 /*
01202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01203 %                                                                             %
01204 %                                                                             %
01205 %                                                                             %
01206 %   O p e n M o d u l e                                                       %
01207 %                                                                             %
01208 %                                                                             %
01209 %                                                                             %
01210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01211 %
01212 %  OpenModule() loads a module, and invokes its registration module.  It
01213 %  returns MagickTrue on success, and MagickFalse if there is an error.
01214 %
01215 %  The format of the OpenModule module is:
01216 %
01217 %      MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
01218 %
01219 %  A description of each parameter follows:
01220 %
01221 %    o module: a character string that indicates the module to load.
01222 %
01223 %    o exception: return any errors or warnings in this structure.
01224 %
01225 */
01226 MagickPrivate MagickBooleanType OpenModule(const char *module,
01227   ExceptionInfo *exception)
01228 {
01229   char
01230     filename[MaxTextExtent],
01231     module_name[MaxTextExtent],
01232     name[MaxTextExtent],
01233     path[MaxTextExtent];
01234 
01235   MagickBooleanType
01236     status;
01237 
01238   ModuleHandle
01239     handle;
01240 
01241   ModuleInfo
01242     *module_info;
01243 
01244   register const CoderInfo
01245     *p;
01246 
01247   size_t
01248     signature;
01249 
01250   /*
01251     Assign module name from alias.
01252   */
01253   assert(module != (const char *) NULL);
01254   module_info=(ModuleInfo *) GetModuleInfo(module,exception);
01255   if (module_info != (ModuleInfo *) NULL)
01256     return(MagickTrue);
01257   (void) CopyMagickString(module_name,module,MaxTextExtent);
01258   p=GetCoderInfo(module,exception);
01259   if (p != (CoderInfo *) NULL)
01260     (void) CopyMagickString(module_name,p->name,MaxTextExtent);
01261   if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
01262     return(MagickTrue);  /* module already opened, return */
01263   /*
01264     Locate module.
01265   */
01266   handle=(ModuleHandle) NULL;
01267   TagToCoderModuleName(module_name,filename);
01268   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
01269     "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
01270   *path='\0';
01271   status=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
01272   if (status == MagickFalse)
01273     return(MagickFalse);
01274   /*
01275     Load module
01276   */
01277   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
01278     "Opening module at path \"%s\"",path);
01279   handle=(ModuleHandle) lt_dlopen(path);
01280   if (handle == (ModuleHandle) NULL)
01281     {
01282       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01283         "UnableToLoadModule","`%s': %s",path,lt_dlerror());
01284       return(MagickFalse);
01285     }
01286   /*
01287     Register module.
01288   */
01289   module_info=AcquireModuleInfo(path,module_name);
01290   module_info->handle=handle;
01291   if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
01292     return(MagickFalse);
01293   /*
01294     Define RegisterFORMATImage method.
01295   */
01296   TagToModuleName(module_name,"Register%sImage",name);
01297   module_info->register_module=(size_t (*)(void)) lt_dlsym(handle,name);
01298   if (module_info->register_module == (size_t (*)(void)) NULL)
01299     {
01300       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01301         "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
01302       return(MagickFalse);
01303     }
01304   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
01305     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
01306     (void *) module_info->register_module);
01307   /*
01308     Define UnregisterFORMATImage method.
01309   */
01310   TagToModuleName(module_name,"Unregister%sImage",name);
01311   module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
01312   if (module_info->unregister_module == (void (*)(void)) NULL)
01313     {
01314       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01315         "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
01316       return(MagickFalse);
01317     }
01318   (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
01319     "Method \"%s\" in module \"%s\" at address %p",name,module_name,
01320     (void *) module_info->unregister_module);
01321   signature=module_info->register_module();
01322   if (signature != MagickImageCoderSignature)
01323     {
01324       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01325         "ImageCoderSignatureMismatch","`%s': %8lx != %8lx",module_name,
01326         (unsigned long) signature,(unsigned long) MagickImageCoderSignature);
01327       return(MagickFalse);
01328     }
01329   return(MagickTrue);
01330 }
01331 
01332 /*
01333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01334 %                                                                             %
01335 %                                                                             %
01336 %                                                                             %
01337 %   O p e n M o d u l e s                                                     %
01338 %                                                                             %
01339 %                                                                             %
01340 %                                                                             %
01341 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01342 %
01343 %  OpenModules() loads all available modules.
01344 %
01345 %  The format of the OpenModules module is:
01346 %
01347 %      MagickBooleanType OpenModules(ExceptionInfo *exception)
01348 %
01349 %  A description of each parameter follows:
01350 %
01351 %    o exception: return any errors or warnings in this structure.
01352 %
01353 */
01354 MagickPrivate MagickBooleanType OpenModules(ExceptionInfo *exception)
01355 {
01356   char
01357     **modules;
01358 
01359   register ssize_t
01360     i;
01361 
01362   size_t
01363     number_modules;
01364 
01365   /*
01366     Load all modules.
01367   */
01368   (void) GetMagickInfo((char *) NULL,exception);
01369   number_modules=0;
01370   modules=GetModuleList("*",MagickImageCoderModule,&number_modules,exception);
01371   if (modules == (char **) NULL)
01372     return(MagickFalse);
01373   for (i=0; i < (ssize_t) number_modules; i++)
01374     (void) OpenModule(modules[i],exception);
01375   /*
01376     Relinquish resources.
01377   */
01378   for (i=0; i < (ssize_t) number_modules; i++)
01379     modules[i]=DestroyString(modules[i]);
01380   modules=(char **) RelinquishMagickMemory(modules);
01381   return(MagickTrue);
01382 }
01383 
01384 /*
01385 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01386 %                                                                             %
01387 %                                                                             %
01388 %                                                                             %
01389 %   R e g i s t e r M o d u l e                                               %
01390 %                                                                             %
01391 %                                                                             %
01392 %                                                                             %
01393 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01394 %
01395 %  RegisterModule() adds an entry to the module list.  It returns a pointer to
01396 %  the registered entry on success.
01397 %
01398 %  The format of the RegisterModule module is:
01399 %
01400 %      ModuleInfo *RegisterModule(const ModuleInfo *module_info,
01401 %        ExceptionInfo *exception)
01402 %
01403 %  A description of each parameter follows:
01404 %
01405 %    o info: a pointer to the registered entry is returned.
01406 %
01407 %    o module_info: a pointer to the ModuleInfo structure to register.
01408 %
01409 %    o exception: return any errors or warnings in this structure.
01410 %
01411 */
01412 static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
01413   ExceptionInfo *exception)
01414 {
01415   MagickBooleanType
01416     status;
01417 
01418   assert(module_info != (ModuleInfo *) NULL);
01419   assert(module_info->signature == MagickSignature);
01420   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
01421   if (module_list == (SplayTreeInfo *) NULL)
01422     return((const ModuleInfo *) NULL);
01423   status=AddValueToSplayTree(module_list,module_info->tag,module_info);
01424   if (status == MagickFalse)
01425     (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
01426       "MemoryAllocationFailed","`%s'",module_info->tag);
01427   return(module_info);
01428 }
01429 
01430 /*
01431 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01432 %                                                                             %
01433 %                                                                             %
01434 %                                                                             %
01435 %  T a g T o C o d e r M o d u l e N a m e                                    %
01436 %                                                                             %
01437 %                                                                             %
01438 %                                                                             %
01439 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01440 %
01441 %  TagToCoderModuleName() munges a module tag and obtains the filename of the
01442 %  corresponding module.
01443 %
01444 %  The format of the TagToCoderModuleName module is:
01445 %
01446 %      char *TagToCoderModuleName(const char *tag,char *name)
01447 %
01448 %  A description of each parameter follows:
01449 %
01450 %    o tag: a character string representing the module tag.
01451 %
01452 %    o name: return the module name here.
01453 %
01454 */
01455 static void TagToCoderModuleName(const char *tag,char *name)
01456 {
01457   assert(tag != (char *) NULL);
01458   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
01459   assert(name != (char *) NULL);
01460 #if defined(MAGICKCORE_LTDL_DELEGATE)
01461   (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
01462   (void) LocaleLower(name);
01463 #else
01464 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
01465   if (LocaleNCompare("IM_MOD_",tag,7) == 0)
01466     (void) CopyMagickString(name,tag,MaxTextExtent);
01467   else
01468     {
01469 #if defined(_DEBUG)
01470       (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
01471 #else
01472       (void) FormatLocaleString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
01473 #endif
01474     }
01475 #endif
01476 #endif
01477 }
01478 
01479 /*
01480 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01481 %                                                                             %
01482 %                                                                             %
01483 %                                                                             %
01484 %  T a g T o F i l t e r M o d u l e N a m e                                  %
01485 %                                                                             %
01486 %                                                                             %
01487 %                                                                             %
01488 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01489 %
01490 %  TagToFilterModuleName() munges a module tag and returns the filename of the
01491 %  corresponding filter module.
01492 %
01493 %  The format of the TagToFilterModuleName module is:
01494 %
01495 %      void TagToFilterModuleName(const char *tag,char name)
01496 %
01497 %  A description of each parameter follows:
01498 %
01499 %    o tag: a character string representing the module tag.
01500 %
01501 %    o name: return the filter name here.
01502 %
01503 */
01504 static void TagToFilterModuleName(const char *tag,char *name)
01505 {
01506   assert(tag != (char *) NULL);
01507   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
01508   assert(name != (char *) NULL);
01509 #if !defined(MAGICKCORE_LTDL_DELEGATE)
01510   (void) FormatLocaleString(name,MaxTextExtent,"%s.dll",tag);
01511 #else
01512   (void) FormatLocaleString(name,MaxTextExtent,"%s.la",tag);
01513 #endif
01514 }
01515 
01516 /*
01517 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01518 %                                                                             %
01519 %                                                                             %
01520 %                                                                             %
01521 %   T a g T o M o d u l e N a m e                                             %
01522 %                                                                             %
01523 %                                                                             %
01524 %                                                                             %
01525 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01526 %
01527 %  TagToModuleName() munges the module tag name and returns an upper-case tag
01528 %  name as the input string, and a user-provided format.
01529 %
01530 %  The format of the TagToModuleName module is:
01531 %
01532 %      TagToModuleName(const char *tag,const char *format,char *module)
01533 %
01534 %  A description of each parameter follows:
01535 %
01536 %    o tag: the module tag.
01537 %
01538 %    o format: a sprintf-compatible format string containing %s where the
01539 %      upper-case tag name is to be inserted.
01540 %
01541 %    o module: pointer to a destination buffer for the formatted result.
01542 %
01543 */
01544 static void TagToModuleName(const char *tag,const char *format,char *module)
01545 {
01546   char
01547     name[MaxTextExtent];
01548 
01549   assert(tag != (const char *) NULL);
01550   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
01551   assert(format != (const char *) NULL);
01552   assert(module != (char *) NULL);
01553   (void) CopyMagickString(name,tag,MaxTextExtent);
01554   LocaleUpper(name);
01555 #if !defined(MAGICKCORE_NAMESPACE_PREFIX)
01556   (void) FormatLocaleString(module,MaxTextExtent,format,name);
01557 #else
01558   {
01559     char
01560       prefix_format[MaxTextExtent];
01561 
01562     (void) FormatLocaleString(prefix_format,MaxTextExtent,"%s%s",
01563       MAGICKCORE_NAMESPACE_PREFIX,format);
01564     (void) FormatLocaleString(module,MaxTextExtent,prefix_format,name);
01565   }
01566 #endif
01567 }
01568 
01569 /*
01570 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01571 %                                                                             %
01572 %                                                                             %
01573 %                                                                             %
01574 %   U n r e g i s t e r M o d u l e                                           %
01575 %                                                                             %
01576 %                                                                             %
01577 %                                                                             %
01578 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
01579 %
01580 %  UnregisterModule() unloads a module, and invokes its de-registration module.
01581 %  Returns MagickTrue on success, and MagickFalse if there is an error.
01582 %
01583 %  The format of the UnregisterModule module is:
01584 %
01585 %      MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
01586 %        ExceptionInfo *exception)
01587 %
01588 %  A description of each parameter follows:
01589 %
01590 %    o module_info: the module info.
01591 %
01592 %    o exception: return any errors or warnings in this structure.
01593 %
01594 */
01595 static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
01596   ExceptionInfo *exception)
01597 {
01598   /*
01599     Locate and execute UnregisterFORMATImage module.
01600   */
01601   assert(module_info != (const ModuleInfo *) NULL);
01602   (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
01603   assert(exception != (ExceptionInfo *) NULL);
01604   if (module_info->unregister_module == NULL)
01605     return(MagickTrue);
01606   module_info->unregister_module();
01607   if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
01608     {
01609       (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
01610         "UnableToCloseModule","`%s': %s",module_info->tag,lt_dlerror());
01611       return(MagickFalse);
01612     }
01613   return(MagickTrue);
01614 }
01615 #else
01616 MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
01617   ExceptionInfo *magick_unused(exception))
01618 {
01619   return(MagickTrue);
01620 }
01621 
01622 MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
01623   Image **image,const int argc,const char **argv,ExceptionInfo *exception)
01624 {
01625   PolicyRights
01626     rights;
01627 
01628   assert(image != (Image **) NULL);
01629   assert((*image)->signature == MagickSignature);
01630   if ((*image)->debug != MagickFalse)
01631     (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",(*image)->filename);
01632   rights=ReadPolicyRights;
01633   if (IsRightsAuthorized(FilterPolicyDomain,rights,tag) == MagickFalse)
01634     {
01635       errno=EPERM;
01636       (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
01637         "NotAuthorized","`%s'",tag);
01638       return(MagickFalse);
01639     }
01640 #if defined(MAGICKCORE_BUILD_MODULES)
01641   (void) tag;
01642   (void) argc;
01643   (void) argv;
01644   (void) exception;
01645 #else
01646   {
01647     extern size_t
01648       analyzeImage(Image **,const int,const char **,ExceptionInfo *);
01649 
01650     ImageFilterHandler
01651       *image_filter;
01652 
01653     image_filter=(ImageFilterHandler *) NULL;
01654     if (LocaleCompare("analyze",tag) == 0)
01655       image_filter=(ImageFilterHandler *) analyzeImage;
01656     if (image_filter == (ImageFilterHandler *) NULL)
01657       (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01658         "UnableToLoadModule","`%s'",tag);
01659     else
01660       {
01661         size_t
01662           signature;
01663 
01664         if ((*image)->debug != MagickFalse)
01665           (void) LogMagickEvent(CoderEvent,GetMagickModule(),
01666             "Invoking \"%s\" static image filter",tag);
01667         signature=image_filter(image,argc,argv,exception);
01668         if ((*image)->debug != MagickFalse)
01669           (void) LogMagickEvent(CoderEvent,GetMagickModule(),"\"%s\" completes",
01670             tag);
01671         if (signature != MagickImageFilterSignature)
01672           {
01673             (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
01674               "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,
01675               (unsigned long) signature,(unsigned long)
01676               MagickImageFilterSignature);
01677             return(MagickFalse);
01678           }
01679       }
01680   }
01681 #endif
01682   return(MagickTrue);
01683 }
01684 #endif