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