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