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