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