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