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