blob: 46976cbc4a5537f7d86fee54385b01278327bfc6 [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
cristy0157aea2010-04-24 21:12:18 +0000631#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000632 {
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
cristy0157aea2010-04-24 21:12:18 +0000676#if !defined(MAGICKCORE_CODER_PATH) && !defined(MAGICKCORE_WINDOWS_SUPPORT)
677# error MAGICKCORE_CODER_PATH or MAGICKCORE_WINDOWS_SUPPORT must be defined when MAGICKCORE_INSTALLED_SUPPORT is defined
cristy3ed852e2009-09-05 21:47:34 +0000678#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 }
cristy0157aea2010-04-24 21:12:18 +0000757#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000758 {
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 {
cristya9197f62010-01-12 02:23:34 +0000960 errno=EPERM;
cristy3ed852e2009-09-05 21:47:34 +0000961 (void) ThrowMagickException(exception,GetMagickModule(),PolicyError,
962 "NotAuthorized","`%s'",tag);
963 return(MagickFalse);
964 }
965 TagToFilterModuleName(tag,name);
966 length=GetMagickModulePath(name,MagickImageFilterModule,path,exception);
967 if (length == 0)
968 return(MagickFalse);
969 /*
970 Open the module.
971 */
972 handle=(ModuleHandle) lt_dlopen(path);
973 if (handle == (ModuleHandle) NULL)
974 {
975 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
976 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
977 return(MagickFalse);
978 }
979 /*
980 Locate the module.
981 */
982#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
983 (void) FormatMagickString(name,MaxTextExtent,"%sImage",tag);
984#else
985 (void) FormatMagickString(name,MaxTextExtent,"%s%sImage",
986 MAGICKCORE_NAMESPACE_PREFIX,tag);
987#endif
988 /*
989 Execute the module.
990 */
991 image_filter=(ImageFilterHandler *) lt_dlsym(handle,name);
992 if (image_filter == (ImageFilterHandler *) NULL)
993 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
994 "UnableToLoadModule","`%s': %s",name,lt_dlerror());
995 else
996 {
997 unsigned long
998 signature;
999
1000 if ((*images)->debug != MagickFalse)
1001 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1002 "Invoking \"%s\" dynamic image filter",tag);
1003 signature=image_filter(images,argc,argv,exception);
1004 if ((*images)->debug != MagickFalse)
1005 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),"\"%s\" completes",
1006 tag);
1007 if (signature != MagickImageFilterSignature)
1008 {
1009 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1010 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,signature,
1011 MagickImageFilterSignature);
1012 return(MagickFalse);
1013 }
1014 }
1015 /*
1016 Close the module.
1017 */
1018 if (lt_dlclose(handle) != 0)
1019 {
1020 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1021 "UnableToCloseModule","`%s': %s",name,lt_dlerror());
1022 return(MagickFalse);
1023 }
1024 return(MagickTrue);
1025}
1026
1027/*
1028%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1029% %
1030% %
1031% %
1032% L i s t M o d u l e I n f o %
1033% %
1034% %
1035% %
1036%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1037%
1038% ListModuleInfo() lists the module info to a file.
1039%
1040% The format of the ListModuleInfo module is:
1041%
1042% MagickBooleanType ListModuleInfo(FILE *file,ExceptionInfo *exception)
1043%
1044% A description of each parameter follows.
1045%
1046% o file: An pointer to a FILE.
1047%
1048% o exception: return any errors or warnings in this structure.
1049%
1050*/
1051MagickExport MagickBooleanType ListModuleInfo(FILE *file,
1052 ExceptionInfo *exception)
1053{
1054 const ModuleInfo
1055 **module_info;
1056
1057 register long
1058 i;
1059
1060 unsigned long
1061 number_modules;
1062
1063 if (file == (const FILE *) NULL)
1064 file=stdout;
1065 module_info=GetModuleInfoList("*",&number_modules,exception);
1066 if (module_info == (const ModuleInfo **) NULL)
1067 return(MagickFalse);
1068 if (module_info[0]->path != (char *) NULL)
1069 {
1070 char
1071 path[MaxTextExtent];
1072
1073 GetPathComponent(module_info[0]->path,HeadPath,path);
1074 (void) fprintf(file,"\nPath: %s\n\n",path);
1075 }
1076 (void) fprintf(file,"Module\n");
1077 (void) fprintf(file,"-------------------------------------------------"
1078 "------------------------------\n");
1079 for (i=0; i < (long) number_modules; i++)
1080 {
1081 if (module_info[i]->stealth != MagickFalse)
1082 continue;
1083 (void) fprintf(file,"%s",module_info[i]->tag);
1084 (void) fprintf(file,"\n");
1085 }
1086 (void) fflush(file);
1087 module_info=(const ModuleInfo **)
1088 RelinquishMagickMemory((void *) module_info);
1089 return(MagickTrue);
1090}
1091
1092/*
1093%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1094% %
1095% %
1096% %
cristyf34a1452009-10-24 22:29:27 +00001097+ M o d u l e C o m p o n e n t G e n e s i s %
1098% %
1099% %
1100% %
1101%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1102%
1103% ModuleComponentGenesis() instantiates the module component.
1104%
1105% The format of the ModuleComponentGenesis method is:
1106%
1107% MagickBooleanType ModuleComponentGenesis(void)
1108%
1109*/
1110MagickExport MagickBooleanType ModuleComponentGenesis(void)
1111{
1112 ExceptionInfo
1113 *exception;
1114
cristy165b6092009-10-26 13:52:10 +00001115 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001116 exception=AcquireExceptionInfo();
1117 InitializeModuleList(exception);
1118 exception=DestroyExceptionInfo(exception);
1119 return(MagickTrue);
1120}
1121
1122/*
1123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1124% %
1125% %
1126% %
1127+ M o d u l e C o m p o n e n t T e r m i n u s %
1128% %
1129% %
1130% %
1131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132%
1133% ModuleComponentTerminus() destroys the module component.
1134%
1135% The format of the ModuleComponentTerminus method is:
1136%
1137% ModuleComponentTerminus(void)
1138%
1139*/
1140MagickExport void ModuleComponentTerminus(void)
1141{
cristy18b17442009-10-25 18:36:48 +00001142 if (module_semaphore == (SemaphoreInfo *) NULL)
1143 AcquireSemaphoreInfo(&module_semaphore);
cristyf34a1452009-10-24 22:29:27 +00001144 DestroyModuleList();
1145 DestroySemaphoreInfo(&module_semaphore);
1146}
1147
1148/*
1149%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1150% %
1151% %
1152% %
cristy3ed852e2009-09-05 21:47:34 +00001153% O p e n M o d u l e %
1154% %
1155% %
1156% %
1157%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1158%
1159% OpenModule() loads a module, and invokes its registration module. It
1160% returns MagickTrue on success, and MagickFalse if there is an error.
1161%
1162% The format of the OpenModule module is:
1163%
1164% MagickBooleanType OpenModule(const char *module,ExceptionInfo *exception)
1165%
1166% A description of each parameter follows:
1167%
1168% o module: a character string that indicates the module to load.
1169%
1170% o exception: return any errors or warnings in this structure.
1171%
1172*/
1173MagickExport MagickBooleanType OpenModule(const char *module,
1174 ExceptionInfo *exception)
1175{
1176 char
1177 filename[MaxTextExtent],
1178 module_name[MaxTextExtent],
1179 name[MaxTextExtent],
1180 path[MaxTextExtent];
1181
1182 ModuleHandle
1183 handle;
1184
1185 ModuleInfo
1186 *module_info;
1187
1188 register const CoderInfo
1189 *p;
1190
1191 size_t
1192 length;
1193
1194 unsigned long
1195 signature;
1196
1197 /*
1198 Assign module name from alias.
1199 */
1200 assert(module != (const char *) NULL);
1201 module_info=(ModuleInfo *) GetModuleInfo(module,exception);
1202 if (module_info != (ModuleInfo *) NULL)
1203 return(MagickTrue);
1204 (void) CopyMagickString(module_name,module,MaxTextExtent);
1205 p=GetCoderInfo(module,exception);
1206 if (p != (CoderInfo *) NULL)
1207 (void) CopyMagickString(module_name,p->name,MaxTextExtent);
1208 if (GetValueFromSplayTree(module_list,module_name) != (void *) NULL)
1209 return(MagickTrue); /* module already opened, return */
1210 /*
1211 Locate module.
1212 */
1213 handle=(ModuleHandle) NULL;
1214 TagToCoderModuleName(module_name,filename);
1215 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1216 "Searching for module \"%s\" using filename \"%s\"",module_name,filename);
1217 *path='\0';
1218 length=GetMagickModulePath(filename,MagickImageCoderModule,path,exception);
1219 if (length == 0)
1220 return(MagickFalse);
1221 /*
1222 Load module
1223 */
1224 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1225 "Opening module at path \"%s\"",path);
1226 handle=(ModuleHandle) lt_dlopen(path);
1227 if (handle == (ModuleHandle) NULL)
1228 {
1229 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1230 "UnableToLoadModule","`%s': %s",path,lt_dlerror());
1231 return(MagickFalse);
1232 }
1233 /*
1234 Register module.
1235 */
1236 module_info=AcquireModuleInfo(path,module_name);
1237 module_info->handle=handle;
1238 if (RegisterModule(module_info,exception) == (ModuleInfo *) NULL)
1239 return(MagickFalse);
1240 /*
1241 Define RegisterFORMATImage method.
1242 */
1243 TagToModuleName(module_name,"Register%sImage",name);
1244 module_info->register_module=(unsigned long (*)(void)) lt_dlsym(handle,name);
1245 if (module_info->register_module == (unsigned long (*)(void)) NULL)
1246 {
1247 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1248 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1249 return(MagickFalse);
1250 }
1251 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1252 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1253 (void *) module_info->register_module);
1254 /*
1255 Define UnregisterFORMATImage method.
1256 */
1257 TagToModuleName(module_name,"Unregister%sImage",name);
1258 module_info->unregister_module=(void (*)(void)) lt_dlsym(handle,name);
1259 if (module_info->unregister_module == (void (*)(void)) NULL)
1260 {
1261 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1262 "UnableToRegisterImageFormat","`%s': %s",module_name,lt_dlerror());
1263 return(MagickFalse);
1264 }
1265 (void) LogMagickEvent(ModuleEvent,GetMagickModule(),
1266 "Method \"%s\" in module \"%s\" at address %p",name,module_name,
1267 (void *) module_info->unregister_module);
1268 signature=module_info->register_module();
1269 if (signature != MagickImageCoderSignature)
1270 {
1271 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1272 "ImageCoderSignatureMismatch","`%s': %8lx != %8lx",module_name,
1273 signature,MagickImageCoderSignature);
1274 return(MagickFalse);
1275 }
1276 return(MagickTrue);
1277}
1278
1279/*
1280%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1281% %
1282% %
1283% %
1284% O p e n M o d u l e s %
1285% %
1286% %
1287% %
1288%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1289%
1290% OpenModules() loads all available modules.
1291%
1292% The format of the OpenModules module is:
1293%
1294% MagickBooleanType OpenModules(ExceptionInfo *exception)
1295%
1296% A description of each parameter follows:
1297%
1298% o exception: return any errors or warnings in this structure.
1299%
1300*/
1301MagickExport MagickBooleanType OpenModules(ExceptionInfo *exception)
1302{
1303 char
1304 **modules;
1305
1306 register long
1307 i;
1308
1309 unsigned long
1310 number_modules;
1311
1312 /*
1313 Load all modules.
1314 */
1315 (void) GetMagickInfo((char *) NULL,exception);
1316 number_modules=0;
1317 modules=GetModuleList("*",&number_modules,exception);
1318 if (modules == (char **) NULL)
1319 return(MagickFalse);
1320 for (i=0; i < (long) number_modules; i++)
1321 (void) OpenModule(modules[i],exception);
1322 /*
1323 Relinquish resources.
1324 */
1325 for (i=0; i < (long) number_modules; i++)
1326 modules[i]=DestroyString(modules[i]);
1327 modules=(char **) RelinquishMagickMemory(modules);
1328 return(MagickTrue);
1329}
1330
1331/*
1332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1333% %
1334% %
1335% %
1336% R e g i s t e r M o d u l e %
1337% %
1338% %
1339% %
1340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1341%
1342% RegisterModule() adds an entry to the module list. It returns a pointer to
1343% the registered entry on success.
1344%
1345% The format of the RegisterModule module is:
1346%
1347% ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1348% ExceptionInfo *exception)
1349%
1350% A description of each parameter follows:
1351%
1352% o info: a pointer to the registered entry is returned.
1353%
1354% o module_info: a pointer to the ModuleInfo structure to register.
1355%
1356% o exception: return any errors or warnings in this structure.
1357%
1358*/
1359static const ModuleInfo *RegisterModule(const ModuleInfo *module_info,
1360 ExceptionInfo *exception)
1361{
1362 MagickBooleanType
1363 status;
1364
1365 assert(module_info != (ModuleInfo *) NULL);
1366 assert(module_info->signature == MagickSignature);
1367 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1368 if (module_list == (SplayTreeInfo *) NULL)
1369 return((const ModuleInfo *) NULL);
1370 status=AddValueToSplayTree(module_list,module_info->tag,module_info);
1371 if (status == MagickFalse)
1372 (void) ThrowMagickException(exception,GetMagickModule(),ResourceLimitError,
1373 "MemoryAllocationFailed","`%s'",module_info->tag);
1374 return(module_info);
1375}
1376
1377/*
1378%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1379% %
1380% %
1381% %
1382% T a g T o C o d e r M o d u l e N a m e %
1383% %
1384% %
1385% %
1386%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1387%
1388% TagToCoderModuleName() munges a module tag and obtains the filename of the
1389% corresponding module.
1390%
1391% The format of the TagToCoderModuleName module is:
1392%
1393% char *TagToCoderModuleName(const char *tag,char *name)
1394%
1395% A description of each parameter follows:
1396%
1397% o tag: a character string representing the module tag.
1398%
1399% o name: return the module name here.
1400%
1401*/
1402static void TagToCoderModuleName(const char *tag,char *name)
1403{
1404 assert(tag != (char *) NULL);
1405 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1406 assert(name != (char *) NULL);
1407#if defined(MAGICKCORE_LTDL_DELEGATE)
1408 (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
1409 (void) LocaleLower(name);
1410#else
cristy0157aea2010-04-24 21:12:18 +00001411#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +00001412 if (LocaleNCompare("IM_MOD_",tag,7) == 0)
1413 (void) CopyMagickString(name,tag,MaxTextExtent);
1414 else
1415 {
1416#if defined(_DEBUG)
1417 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_DB_%s_.dll",tag);
1418#else
1419 (void) FormatMagickString(name,MaxTextExtent,"IM_MOD_RL_%s_.dll",tag);
1420#endif
1421 }
1422#endif
1423#endif
1424}
1425
1426/*
1427%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1428% %
1429% %
1430% %
1431% T a g T o F i l t e r M o d u l e N a m e %
1432% %
1433% %
1434% %
1435%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1436%
1437% TagToFilterModuleName() munges a module tag and returns the filename of the
1438% corresponding filter module.
1439%
1440% The format of the TagToFilterModuleName module is:
1441%
1442% void TagToFilterModuleName(const char *tag,char name)
1443%
1444% A description of each parameter follows:
1445%
1446% o tag: a character string representing the module tag.
1447%
1448% o name: return the filter name here.
1449%
1450*/
1451static void TagToFilterModuleName(const char *tag,char *name)
1452{
1453 assert(tag != (char *) NULL);
1454 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1455 assert(name != (char *) NULL);
1456#if !defined(MAGICKCORE_LTDL_DELEGATE)
1457 (void) FormatMagickString(name,MaxTextExtent,"%s.dll",tag);
1458#else
1459 (void) FormatMagickString(name,MaxTextExtent,"%s.la",tag);
1460 (void) LocaleLower(name);
1461#endif
1462}
1463
1464/*
1465%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1466% %
1467% %
1468% %
1469% T a g T o M o d u l e N a m e %
1470% %
1471% %
1472% %
1473%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1474%
1475% TagToModuleName() munges the module tag name and returns an upper-case tag
1476% name as the input string, and a user-provided format.
1477%
1478% The format of the TagToModuleName module is:
1479%
1480% TagToModuleName(const char *tag,const char *format,char *module)
1481%
1482% A description of each parameter follows:
1483%
1484% o tag: the module tag.
1485%
1486% o format: a sprintf-compatible format string containing %s where the
1487% upper-case tag name is to be inserted.
1488%
1489% o module: pointer to a destination buffer for the formatted result.
1490%
1491*/
1492static void TagToModuleName(const char *tag,const char *format,char *module)
1493{
1494 char
1495 name[MaxTextExtent];
1496
1497 assert(tag != (const char *) NULL);
1498 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",tag);
1499 assert(format != (const char *) NULL);
1500 assert(module != (char *) NULL);
1501 (void) CopyMagickString(name,tag,MaxTextExtent);
1502 LocaleUpper(name);
1503#if !defined(MAGICKCORE_NAMESPACE_PREFIX)
1504 (void) FormatMagickString(module,MaxTextExtent,format,name);
1505#else
1506 {
1507 char
1508 prefix_format[MaxTextExtent];
1509
1510 (void) FormatMagickString(prefix_format,MaxTextExtent,"%s%s",
1511 MAGICKCORE_NAMESPACE_PREFIX,format);
1512 (void) FormatMagickString(module,MaxTextExtent,prefix_format,name);
1513 }
1514#endif
1515}
1516
1517/*
1518%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1519% %
1520% %
1521% %
1522% U n r e g i s t e r M o d u l e %
1523% %
1524% %
1525% %
1526%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1527%
1528% UnregisterModule() unloads a module, and invokes its de-registration module.
1529% Returns MagickTrue on success, and MagickFalse if there is an error.
1530%
1531% The format of the UnregisterModule module is:
1532%
1533% MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1534% ExceptionInfo *exception)
1535%
1536% A description of each parameter follows:
1537%
1538% o module_info: the module info.
1539%
1540% o exception: return any errors or warnings in this structure.
1541%
1542*/
1543static MagickBooleanType UnregisterModule(const ModuleInfo *module_info,
1544 ExceptionInfo *exception)
1545{
1546 /*
1547 Locate and execute UnregisterFORMATImage module.
1548 */
1549 assert(module_info != (const ModuleInfo *) NULL);
1550 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",module_info->tag);
1551 assert(exception != (ExceptionInfo *) NULL);
1552 if (module_info->unregister_module == NULL)
1553 return(MagickTrue);
1554 module_info->unregister_module();
1555 if (lt_dlclose((ModuleHandle) module_info->handle) != 0)
1556 {
1557 (void) ThrowMagickException(exception,GetMagickModule(),ModuleWarning,
1558 "UnableToCloseModule","`%s': %s",module_info->tag,lt_dlerror());
1559 return(MagickFalse);
1560 }
1561 return(MagickTrue);
1562}
1563#else
1564MagickExport MagickBooleanType ListModuleInfo(FILE *magick_unused(file),
1565 ExceptionInfo *magick_unused(exception))
1566{
1567 return(MagickTrue);
1568}
1569
1570MagickExport MagickBooleanType InvokeDynamicImageFilter(const char *tag,
1571 Image **image,const int argc,const char **argv,ExceptionInfo *exception)
1572{
1573#if !defined(MAGICKCORE_BUILD_MODULES)
1574 {
1575 extern unsigned long
cristya0b81c32010-01-22 02:54:33 +00001576 analyzeImage(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;
cristy3ed852e2009-09-05 21:47:34 +00001584 if (image_filter != (ImageFilterHandler *) NULL)
1585 {
1586 unsigned long
1587 signature;
1588
1589 signature=image_filter(image,argc,argv,exception);
1590 if (signature != MagickImageFilterSignature)
1591 {
1592 (void) ThrowMagickException(exception,GetMagickModule(),ModuleError,
1593 "ImageFilterSignatureMismatch","`%s': %8lx != %8lx",tag,signature,
1594 MagickImageFilterSignature);
1595 return(MagickFalse);
1596 }
1597 }
1598 }
1599#endif
1600 return(MagickTrue);
1601}
1602#endif