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