MagickCore  6.9.12-53
Convert, Edit, Or Compose Bitmap Images
 All Data Structures
configure.c
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % CCCC OOO N N FFFFF IIIII GGGG U U RRRR EEEEE %
7 % C O O NN N F I G U U R R E %
8 % C O O N N N FFF I G GG U U RRRR EEE %
9 % C O O N NN F I G G U U R R E %
10 % CCCC OOO N N F IIIII GGG UUU R R EEEEE %
11 % %
12 % %
13 % MagickCore Image Configure Methods %
14 % %
15 % Software Design %
16 % Cristy %
17 % July 2003 %
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  Include declarations.
41 */
42 #include "magick/studio.h"
43 #include "magick/blob.h"
44 #include "magick/client.h"
45 #include "magick/configure.h"
46 #include "magick/exception.h"
47 #include "magick/exception-private.h"
48 #include "magick/hashmap.h"
49 #include "magick/log.h"
50 #include "magick/memory_.h"
51 #include "magick/nt-base-private.h"
52 #include "magick/semaphore.h"
53 #include "magick/string_.h"
54 #include "magick/token.h"
55 #include "magick/utility.h"
56 #include "magick/version.h"
57 #include "magick/xml-tree.h"
58 #include "magick/xml-tree-private.h"
59 
60 /*
61  Define declarations.
62 */
63 #define ConfigureFilename "configure.xml"
64 
65 /*
66  Typedef declarations.
67 */
68 typedef struct _ConfigureMapInfo
69 {
70  const char
71  *name,
72  *value;
74 
75 /*
76  Static declarations.
77 */
78 static LinkedListInfo
79  *configure_cache = (LinkedListInfo *) NULL;
80 
81 static SemaphoreInfo
82  *configure_semaphore = (SemaphoreInfo *) NULL;
83 
84 /*
85  Forward declarations.
86 */
87 static MagickBooleanType
88  IsConfigureCacheInstantiated(ExceptionInfo *);
89 
90 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
91 static MagickBooleanType
92  LoadConfigureCache(LinkedListInfo *,const char *,const char *,const size_t,
93  ExceptionInfo *);
94 #endif
95 
96 /*
97 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98 % %
99 % %
100 % %
101 % A c q u i r e C o n f i g u r e C a c h e %
102 % %
103 % %
104 % %
105 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
106 %
107 % AcquireConfigureCache() caches one or more configure configurations which
108 % provides a mapping between configure attributes and a configure name.
109 %
110 % The format of the AcquireConfigureCache method is:
111 %
112 % LinkedListInfo *AcquireConfigureCache(const char *filename,
113 % ExceptionInfo *exception)
114 %
115 % A description of each parameter follows:
116 %
117 % o filename: the font file name.
118 %
119 % o exception: return any errors or warnings in this structure.
120 %
121 */
122 static inline void AddConfigureKey(LinkedListInfo *cache,const char *path,
123  const char *name,const char *value)
124 {
126  *configure_info;
127 
128  configure_info=(ConfigureInfo *) AcquireMagickMemory(sizeof(*configure_info));
129  if (configure_info == (ConfigureInfo *) NULL)
130  return;
131  (void) memset(configure_info,0,sizeof(*configure_info));
132  configure_info->path=(char *) path;
133  configure_info->name=(char *) name;
134  configure_info->value=(char *) value;
135  configure_info->exempt=MagickTrue;
136  configure_info->signature=MagickCoreSignature;
137  (void) AppendValueToLinkedList(cache,configure_info);
138 }
139 
140 static LinkedListInfo *AcquireConfigureCache(const char *filename,
141  ExceptionInfo *exception)
142 {
144  *cache;
145 
146  /*
147  Load external configure map.
148  */
149  cache=NewLinkedList(0);
150  if (cache == (LinkedListInfo *) NULL)
151  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
152 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
153  {
154  const StringInfo
155  *option;
156 
158  *options;
159 
160  MagickBooleanType
161  status;
162 
163  options=GetConfigureOptions(filename,exception);
164  option=(const StringInfo *) GetNextValueInLinkedList(options);
165  while (option != (const StringInfo *) NULL)
166  {
167  status=LoadConfigureCache(cache,(const char *)
168  GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
169  if (status == MagickTrue)
170  break;
171  option=(const StringInfo *) GetNextValueInLinkedList(options);
172  }
173  options=DestroyConfigureOptions(options);
174  }
175 #endif
176  /*
177  Load built-in configure.
178  */
179  AddConfigureKey(cache,"[built-in]","NAME","ImageMagick");
180  /*
181  Load runtime configuration.
182  */
183  AddConfigureKey(cache,"[built-in]","QuantumDepth",GetMagickQuantumDepth(
184  (size_t *)NULL));
185  AddConfigureKey(cache,"[built-in]","FEATURES",GetMagickFeatures());
186  AddConfigureKey(cache,"[built-in]","DELEGATES",GetMagickDelegates());
187  return(cache);
188 }
189 
190 /*
191 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
192 % %
193 % %
194 % %
195 + C o n f i g u r e C o m p o n e n t G e n e s i s %
196 % %
197 % %
198 % %
199 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
200 %
201 % ConfigureComponentGenesis() instantiates the configure component.
202 %
203 % The format of the ConfigureComponentGenesis method is:
204 %
205 % MagickBooleanType ConfigureComponentGenesis(void)
206 %
207 */
208 MagickExport MagickBooleanType ConfigureComponentGenesis(void)
209 {
210  if (configure_semaphore == (SemaphoreInfo *) NULL)
211  configure_semaphore=AllocateSemaphoreInfo();
212  return(MagickTrue);
213 }
214 
215 /*
216 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
217 % %
218 % %
219 % %
220 + C o n f i g u r e C o m p o n e n t T e r m i n u s %
221 % %
222 % %
223 % %
224 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225 %
226 % ConfigureComponentTerminus() destroys the configure component.
227 %
228 % The format of the ConfigureComponentTerminus method is:
229 %
230 % ConfigureComponentTerminus(void)
231 %
232 */
233 
234 static void *DestroyConfigureElement(void *configure_info)
235 {
237  *p;
238 
239  p=(ConfigureInfo *) configure_info;
240  if (p->exempt == MagickFalse)
241  {
242  if (p->value != (char *) NULL)
243  p->value=DestroyString(p->value);
244  if (p->name != (char *) NULL)
245  p->name=DestroyString(p->name);
246  if (p->path != (char *) NULL)
247  p->path=DestroyString(p->path);
248  }
249  p=(ConfigureInfo *) RelinquishMagickMemory(p);
250  return((void *) NULL);
251 }
252 
253 MagickExport void ConfigureComponentTerminus(void)
254 {
255  if (configure_semaphore == (SemaphoreInfo *) NULL)
256  ActivateSemaphoreInfo(&configure_semaphore);
257  LockSemaphoreInfo(configure_semaphore);
258  if (configure_cache != (LinkedListInfo *) NULL)
259  configure_cache=DestroyLinkedList(configure_cache,DestroyConfigureElement);
260  configure_cache=(LinkedListInfo *) NULL;
261  UnlockSemaphoreInfo(configure_semaphore);
262  DestroySemaphoreInfo(&configure_semaphore);
263 }
264 
265 /*
266 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
267 % %
268 % %
269 % %
270 % D e s t r o y C o n f i g u r e O p t i o n s %
271 % %
272 % %
273 % %
274 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
275 %
276 % DestroyConfigureOptions() releases memory associated with an configure
277 % options.
278 %
279 % The format of the DestroyProfiles method is:
280 %
281 % LinkedListInfo *DestroyConfigureOptions(Image *image)
282 %
283 % A description of each parameter follows:
284 %
285 % o image: the image.
286 %
287 */
288 
289 static void *DestroyOptions(void *option)
290 {
291  return(DestroyStringInfo((StringInfo *) option));
292 }
293 
294 MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
295 {
296  assert(options != (LinkedListInfo *) NULL);
297  return(DestroyLinkedList(options,DestroyOptions));
298 }
299 
300 /*
301 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
302 % %
303 % %
304 % %
305 + G e t C o n f i g u r e I n f o %
306 % %
307 % %
308 % %
309 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
310 %
311 % GetConfigureInfo() searches the configure list for the specified name and if
312 % found returns attributes for that element.
313 %
314 % The format of the GetConfigureInfo method is:
315 %
316 % const ConfigureInfo *GetConfigureInfo(const char *name,
317 % ExceptionInfo *exception)
318 %
319 % A description of each parameter follows:
320 %
321 % o configure_info: GetConfigureInfo() searches the configure list for the
322 % specified name and if found returns attributes for that element.
323 %
324 % o name: the configure name.
325 %
326 % o exception: return any errors or warnings in this structure.
327 %
328 */
329 MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
330  ExceptionInfo *exception)
331 {
332  const ConfigureInfo
333  *p;
334 
335  assert(exception != (ExceptionInfo *) NULL);
336  if (IsConfigureCacheInstantiated(exception) == MagickFalse)
337  return((const ConfigureInfo *) NULL);
338  /*
339  Search for configure tag.
340  */
341  LockSemaphoreInfo(configure_semaphore);
342  ResetLinkedListIterator(configure_cache);
343  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
344  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
345  {
346  UnlockSemaphoreInfo(configure_semaphore);
347  return(p);
348  }
349  while (p != (const ConfigureInfo *) NULL)
350  {
351  if (LocaleCompare(name,p->name) == 0)
352  break;
353  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
354  }
355  if (p != (ConfigureInfo *) NULL)
356  (void) InsertValueInLinkedList(configure_cache,0,
357  RemoveElementByValueFromLinkedList(configure_cache,p));
358  UnlockSemaphoreInfo(configure_semaphore);
359  return(p);
360 }
361 
362 /*
363 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
364 % %
365 % %
366 % %
367 % G e t C o n f i g u r e I n f o L i s t %
368 % %
369 % %
370 % %
371 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
372 %
373 % GetConfigureInfoList() returns any configure options that match the
374 % specified pattern.
375 %
376 % The format of the GetConfigureInfoList function is:
377 %
378 % const ConfigureInfo **GetConfigureInfoList(const char *pattern,
379 % size_t *number_options,ExceptionInfo *exception)
380 %
381 % A description of each parameter follows:
382 %
383 % o pattern: Specifies a pointer to a text string containing a pattern.
384 %
385 % o number_options: This integer returns the number of configure options in
386 % the list.
387 %
388 % o exception: return any errors or warnings in this structure.
389 %
390 */
391 
392 #if defined(__cplusplus) || defined(c_plusplus)
393 extern "C" {
394 #endif
395 
396 static int ConfigureInfoCompare(const void *x,const void *y)
397 {
398  const ConfigureInfo
399  **p,
400  **q;
401 
402  p=(const ConfigureInfo **) x,
403  q=(const ConfigureInfo **) y;
404  if (LocaleCompare((*p)->path,(*q)->path) == 0)
405  return(LocaleCompare((*p)->name,(*q)->name));
406  return(LocaleCompare((*p)->path,(*q)->path));
407 }
408 
409 #if defined(__cplusplus) || defined(c_plusplus)
410 }
411 #endif
412 
413 MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
414  size_t *number_options,ExceptionInfo *exception)
415 {
416  const ConfigureInfo
417  **options;
418 
419  const ConfigureInfo
420  *p;
421 
422  ssize_t
423  i;
424 
425  /*
426  Allocate configure list.
427  */
428  assert(pattern != (char *) NULL);
429  assert(number_options != (size_t *) NULL);
430  if (IsEventLogging() != MagickFalse)
431  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
432  *number_options=0;
433  p=GetConfigureInfo("*",exception);
434  if (p == (const ConfigureInfo *) NULL)
435  return((const ConfigureInfo **) NULL);
436  options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
437  GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
438  if (options == (const ConfigureInfo **) NULL)
439  return((const ConfigureInfo **) NULL);
440  /*
441  Generate configure list.
442  */
443  LockSemaphoreInfo(configure_semaphore);
444  ResetLinkedListIterator(configure_cache);
445  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
446  for (i=0; p != (const ConfigureInfo *) NULL; )
447  {
448  if ((p->stealth == MagickFalse) &&
449  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
450  options[i++]=p;
451  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
452  }
453  UnlockSemaphoreInfo(configure_semaphore);
454  qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
455  options[i]=(ConfigureInfo *) NULL;
456  *number_options=(size_t) i;
457  return(options);
458 }
459 
460 /*
461 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
462 % %
463 % %
464 % %
465 % G e t C o n f i g u r e L i s t %
466 % %
467 % %
468 % %
469 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
470 %
471 % GetConfigureList() returns any configure options that match the specified
472 % pattern.
473 %
474 % The format of the GetConfigureList function is:
475 %
476 % char **GetConfigureList(const char *pattern,
477 % size_t *number_options,ExceptionInfo *exception)
478 %
479 % A description of each parameter follows:
480 %
481 % o pattern: Specifies a pointer to a text string containing a pattern.
482 %
483 % o number_options: This integer returns the number of options in the list.
484 %
485 % o exception: return any errors or warnings in this structure.
486 %
487 */
488 
489 #if defined(__cplusplus) || defined(c_plusplus)
490 extern "C" {
491 #endif
492 
493 static int ConfigureCompare(const void *x,const void *y)
494 {
495  char
496  **p,
497  **q;
498 
499  p=(char **) x;
500  q=(char **) y;
501  return(LocaleCompare(*p,*q));
502 }
503 
504 #if defined(__cplusplus) || defined(c_plusplus)
505 }
506 #endif
507 
508 MagickExport char **GetConfigureList(const char *pattern,
509  size_t *number_options,ExceptionInfo *exception)
510 {
511  char
512  **options;
513 
514  const ConfigureInfo
515  *p;
516 
517  ssize_t
518  i;
519 
520  /*
521  Allocate configure list.
522  */
523  assert(pattern != (char *) NULL);
524  assert(number_options != (size_t *) NULL);
525  if (IsEventLogging() != MagickFalse)
526  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
527  *number_options=0;
528  p=GetConfigureInfo("*",exception);
529  if (p == (const ConfigureInfo *) NULL)
530  return((char **) NULL);
531  options=(char **) AcquireQuantumMemory((size_t)
532  GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
533  if (options == (char **) NULL)
534  return((char **) NULL);
535  LockSemaphoreInfo(configure_semaphore);
536  ResetLinkedListIterator(configure_cache);
537  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
538  for (i=0; p != (const ConfigureInfo *) NULL; )
539  {
540  if ((p->stealth == MagickFalse) &&
541  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
542  options[i++]=ConstantString(p->name);
543  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
544  }
545  UnlockSemaphoreInfo(configure_semaphore);
546  qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
547  options[i]=(char *) NULL;
548  *number_options=(size_t) i;
549  return(options);
550 }
551 
552 /*
553 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
554 % %
555 % %
556 % %
557 % G e t C o n f i g u r e O p t i o n %
558 % %
559 % %
560 % %
561 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
562 %
563 % GetConfigureOption() returns the value associated with the configure option.
564 %
565 % The format of the GetConfigureOption method is:
566 %
567 % char *GetConfigureOption(const char *option)
568 %
569 % A description of each parameter follows:
570 %
571 % o configure_info: The configure info.
572 %
573 */
574 MagickExport char *GetConfigureOption(const char *option)
575 {
576  const char
577  *value;
578 
579  const ConfigureInfo
580  *configure_info;
581 
583  *exception;
584 
585  assert(option != (const char *) NULL);
586  if (IsEventLogging() != MagickFalse)
587  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
588  exception=AcquireExceptionInfo();
589  configure_info=GetConfigureInfo(option,exception);
590  exception=DestroyExceptionInfo(exception);
591  if (configure_info == (ConfigureInfo *) NULL)
592  return((char *) NULL);
593  value=GetConfigureValue(configure_info);
594  if ((value == (const char *) NULL) || (*value == '\0'))
595  return((char *) NULL);
596  return(ConstantString(value));
597 }
598 
599 /*
600 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
601 % %
602 % %
603 % %
604 % G e t C o n f i g u r e O p t i o n s %
605 % %
606 % %
607 % %
608 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
609 %
610 % GetConfigureOptions() returns any Magick configuration options associated
611 % with the specified filename.
612 %
613 % The format of the GetConfigureOptions method is:
614 %
615 % LinkedListInfo *GetConfigureOptions(const char *filename,
616 % ExceptionInfo *exception)
617 %
618 % A description of each parameter follows:
619 %
620 % o filename: the configure file name.
621 %
622 % o exception: return any errors or warnings in this structure.
623 %
624 */
625 MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
626  ExceptionInfo *exception)
627 {
628  char
629  path[MaxTextExtent];
630 
631  const char
632  *element;
633 
635  *options,
636  *paths;
637 
638  StringInfo
639  *xml;
640 
641  assert(filename != (const char *) NULL);
642  assert(exception != (ExceptionInfo *) NULL);
643  if (IsEventLogging() != MagickFalse)
644  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
645  (void) CopyMagickString(path,filename,MaxTextExtent);
646  /*
647  Load XML from configuration files to linked-list.
648  */
649  options=NewLinkedList(0);
650  paths=GetConfigurePaths(filename,exception);
651  if (paths != (LinkedListInfo *) NULL)
652  {
653  ResetLinkedListIterator(paths);
654  element=(const char *) GetNextValueInLinkedList(paths);
655  while (element != (const char *) NULL)
656  {
657  (void) FormatLocaleString(path,MaxTextExtent,"%s%s",element,filename);
658  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
659  "Searching for configure file: \"%s\"",path);
660  xml=ConfigureFileToStringInfo(path);
661  if (xml != (StringInfo *) NULL)
662  (void) AppendValueToLinkedList(options,xml);
663  element=(const char *) GetNextValueInLinkedList(paths);
664  }
665  paths=DestroyLinkedList(paths,RelinquishMagickMemory);
666  }
667 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
668  if (GetNumberOfElementsInLinkedList(options) == 0)
669  {
670  char
671  *blob;
672 
673  blob=(char *) NTResourceToBlob(filename);
674  if (blob != (char *) NULL)
675  {
676  xml=AcquireStringInfo(0);
677  SetStringInfoLength(xml,strlen(blob)+1);
678  SetStringInfoDatum(xml,(unsigned char *) blob);
679  SetStringInfoPath(xml,filename);
680  (void) AppendValueToLinkedList(options,xml);
681  }
682  }
683 #endif
684  if (GetNumberOfElementsInLinkedList(options) == 0)
685  (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
686  "UnableToOpenConfigureFile","`%s'",filename);
687  ResetLinkedListIterator(options);
688  return(options);
689 }
690 
691 /*
692 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
693 % %
694 % %
695 % %
696 % G e t C o n f i g u r e P a t h s %
697 % %
698 % %
699 % %
700 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
701 %
702 % GetConfigurePaths() returns any Magick configuration paths associated
703 % with the specified filename.
704 %
705 % The format of the GetConfigurePaths method is:
706 %
707 % LinkedListInfo *GetConfigurePaths(const char *filename,
708 % ExceptionInfo *exception)
709 %
710 % A description of each parameter follows:
711 %
712 % o filename: the configure file name.
713 %
714 % o exception: return any errors or warnings in this structure.
715 %
716 */
717 MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
718  ExceptionInfo *exception)
719 {
720 #define RegistryKey "ConfigurePath"
721 #define MagickCoreDLL "CORE_RL_magick_.dll"
722 #define MagickCoreDebugDLL "CORE_DB_magick_.dll"
723 
724  char
725  path[MaxTextExtent];
726 
728  *paths;
729 
730  assert(filename != (const char *) NULL);
731  assert(exception != (ExceptionInfo *) NULL);
732  if (IsEventLogging() != MagickFalse)
733  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
734  (void) exception;
735  (void) CopyMagickString(path,filename,MaxTextExtent);
736  paths=NewLinkedList(0);
737  {
738  char
739  *configure_path;
740 
741  /*
742  Search $MAGICK_CONFIGURE_PATH.
743  */
744  configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
745  if (configure_path != (char *) NULL)
746  {
747  char
748  *p,
749  *q;
750 
751  for (p=configure_path-1; p != (char *) NULL; )
752  {
753  (void) CopyMagickString(path,p+1,MaxTextExtent);
754  q=strchr(path,DirectoryListSeparator);
755  if (q != (char *) NULL)
756  *q='\0';
757  q=path+strlen(path)-1;
758  if ((q >= path) && (*q != *DirectorySeparator))
759  (void) ConcatenateMagickString(path,DirectorySeparator,
760  MaxTextExtent);
761  (void) AppendValueToLinkedList(paths,ConstantString(path));
762  p=strchr(p+1,DirectoryListSeparator);
763  }
764  configure_path=DestroyString(configure_path);
765  }
766  }
767 #if defined(MAGICKCORE_INSTALLED_SUPPORT)
768 #if defined(MAGICKCORE_SHARE_PATH)
769  (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
770 #endif
771 #if defined(MAGICKCORE_SHAREARCH_PATH)
772  (void) AppendValueToLinkedList(paths,ConstantString(
773  MAGICKCORE_SHAREARCH_PATH));
774 #endif
775 #if defined(MAGICKCORE_CONFIGURE_PATH)
776  (void) AppendValueToLinkedList(paths,ConstantString(
777  MAGICKCORE_CONFIGURE_PATH));
778 #endif
779 #if defined(MAGICKCORE_DOCUMENTATION_PATH)
780  (void) AppendValueToLinkedList(paths,ConstantString(
781  MAGICKCORE_DOCUMENTATION_PATH));
782 #endif
783 #if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
784  {
785  unsigned char
786  *key_value;
787 
788  /*
789  Locate file via registry key.
790  */
791  key_value=NTRegistryKeyLookup(RegistryKey);
792  if (key_value != (unsigned char *) NULL)
793  {
794  (void) FormatLocaleString(path,MaxTextExtent,"%s%s",(char *) key_value,
795  DirectorySeparator);
796  (void) AppendValueToLinkedList(paths,ConstantString(path));
797  key_value=(unsigned char *) RelinquishMagickMemory(key_value);
798  }
799  }
800 #endif
801 #else
802  {
803  char
804  *home;
805 
806  /*
807  Search under MAGICK_HOME.
808  */
809  home=GetEnvironmentValue("MAGICK_HOME");
810  if (home != (char *) NULL)
811  {
812 #if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
813  (void) FormatLocaleString(path,MaxTextExtent,"%s%s",home,
814  DirectorySeparator);
815  (void) AppendValueToLinkedList(paths,ConstantString(path));
816 #else
817  (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",home,
818  MAGICKCORE_CONFIGURE_RELATIVE_PATH);
819  (void) AppendValueToLinkedList(paths,ConstantString(path));
820  (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",home,
821  MAGICKCORE_SHARE_RELATIVE_PATH);
822  (void) AppendValueToLinkedList(paths,ConstantString(path));
823  (void) FormatLocaleString(path,MaxTextExtent,"%s",
824  MAGICKCORE_SHAREARCH_PATH);
825  (void) AppendValueToLinkedList(paths,ConstantString(path));
826 #endif
827  home=DestroyString(home);
828  }
829  }
830  if (*GetClientPath() != '\0')
831  {
832 #if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
833  (void) FormatLocaleString(path,MaxTextExtent,"%s%s",GetClientPath(),
834  DirectorySeparator);
835  (void) AppendValueToLinkedList(paths,ConstantString(path));
836 #else
837  char
838  prefix[MaxTextExtent];
839 
840  /*
841  Search based on executable directory if directory is known.
842  */
843  (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
844  ChopPathComponents(prefix,1);
845  (void) FormatLocaleString(path,MaxTextExtent,"%s/etc/%s/",prefix,
846  MAGICKCORE_CONFIGURE_RELATIVE_PATH);
847  (void) AppendValueToLinkedList(paths,ConstantString(path));
848  (void) FormatLocaleString(path,MaxTextExtent,"%s/share/%s/",prefix,
849  MAGICKCORE_SHARE_RELATIVE_PATH);
850  (void) AppendValueToLinkedList(paths,ConstantString(path));
851  (void) FormatLocaleString(path,MaxTextExtent,"%s",
852  MAGICKCORE_SHAREARCH_PATH);
853  (void) AppendValueToLinkedList(paths,ConstantString(path));
854 #endif
855  }
856  /*
857  Search current directory.
858  */
859  (void) AppendValueToLinkedList(paths,ConstantString(""));
860 #endif
861  {
862  char
863  *home;
864 
865  home=GetEnvironmentValue("XDG_CONFIG_HOME");
866 #if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
867  if (home == (char *) NULL)
868  home=GetEnvironmentValue("LOCALAPPDATA");
869  if (home == (char *) NULL)
870  home=GetEnvironmentValue("APPDATA");
871  if (home == (char *) NULL)
872  home=GetEnvironmentValue("USERPROFILE");
873 #endif
874  if (home != (char *) NULL)
875  {
876  /*
877  Search $XDG_CONFIG_HOME/ImageMagick.
878  */
879  (void) FormatLocaleString(path,MaxTextExtent,"%s%sImageMagick%s",
880  home,DirectorySeparator,DirectorySeparator);
881  (void) AppendValueToLinkedList(paths,ConstantString(path));
882  home=DestroyString(home);
883  }
884  home=GetEnvironmentValue("HOME");
885  if (home != (char *) NULL)
886  {
887  /*
888  Search $HOME/.config/ImageMagick.
889  */
890  (void) FormatLocaleString(path,MaxTextExtent,
891  "%s%s.config%sImageMagick%s",home,DirectorySeparator,
892  DirectorySeparator,DirectorySeparator);
893  (void) AppendValueToLinkedList(paths,ConstantString(path));
894  /*
895  Search $HOME/.magick.
896  */
897  (void) FormatLocaleString(path,MaxTextExtent,"%s%s.magick%s",home,
898  DirectorySeparator,DirectorySeparator);
899  (void) AppendValueToLinkedList(paths,ConstantString(path));
900  home=DestroyString(home);
901  }
902  }
903 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
904  {
905  char
906  module_path[MaxTextExtent];
907 
908  if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
909  (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
910  {
911  unsigned char
912  *key_value;
913 
914  /*
915  Search module path.
916  */
917  (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
918  DirectorySeparator);
919  key_value=NTRegistryKeyLookup(RegistryKey);
920  if (key_value == (unsigned char *) NULL)
921  (void) AppendValueToLinkedList(paths,ConstantString(path));
922  else
923  key_value=(unsigned char *) RelinquishMagickMemory(key_value);
924  }
925  if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
926  {
927  /*
928  Search PerlMagick module path.
929  */
930  (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
931  DirectorySeparator);
932  (void) AppendValueToLinkedList(paths,ConstantString(path));
933  (void) FormatLocaleString(path,MaxTextExtent,"%s%s",module_path,
934  "\\inc\\lib\\auto\\Image\\Magick\\");
935  (void) AppendValueToLinkedList(paths,ConstantString(path));
936  }
937  }
938 #endif
939  if (GetNumberOfElementsInLinkedList(paths) == 0)
940  (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
941  "no configuration paths found","`%s'",filename);
942  return(paths);
943 }
944 
945 /*
946 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
947 % %
948 % %
949 % %
950 % G e t C o n f i g u r e V a l u e %
951 % %
952 % %
953 % %
954 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
955 %
956 % GetConfigureValue() returns the value associated with the configure info.
957 %
958 % The format of the GetConfigureValue method is:
959 %
960 % const char *GetConfigureValue(const ConfigureInfo *configure_info)
961 %
962 % A description of each parameter follows:
963 %
964 % o configure_info: The configure info.
965 %
966 */
967 MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
968 {
969  if (IsEventLogging() != MagickFalse)
970  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
971  assert(configure_info != (ConfigureInfo *) NULL);
972  assert(configure_info->signature == MagickCoreSignature);
973  return(configure_info->value);
974 }
975 
976 /*
977 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978 % %
979 % %
980 % %
981 + I s C o n f i g u r e C a c h e I n s t a n t i a t e d %
982 % %
983 % %
984 % %
985 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986 %
987 % IsConfigureCacheInstantiated() determines if the configure list is
988 % instantiated. If not, it instantiates the list and returns it.
989 %
990 % The format of the IsConfigureInstantiated method is:
991 %
992 % MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
993 %
994 % A description of each parameter follows.
995 %
996 % o exception: return any errors or warnings in this structure.
997 %
998 */
999 static MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
1000 {
1001  if (configure_cache == (LinkedListInfo *) NULL)
1002  {
1003  if (configure_semaphore == (SemaphoreInfo *) NULL)
1004  ActivateSemaphoreInfo(&configure_semaphore);
1005  LockSemaphoreInfo(configure_semaphore);
1006  if (configure_cache == (LinkedListInfo *) NULL)
1007  configure_cache=AcquireConfigureCache(ConfigureFilename,exception);
1008  UnlockSemaphoreInfo(configure_semaphore);
1009  }
1010  return(configure_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
1011 }
1012 
1013 /*
1014 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1015 % %
1016 % %
1017 % %
1018 % L i s t C o n f i g u r e I n f o %
1019 % %
1020 % %
1021 % %
1022 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1023 %
1024 % ListConfigureInfo() lists the configure info to a file.
1025 %
1026 % The format of the ListConfigureInfo method is:
1027 %
1028 % MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
1029 %
1030 % A description of each parameter follows.
1031 %
1032 % o file: An pointer to a FILE.
1033 %
1034 % o exception: return any errors or warnings in this structure.
1035 %
1036 */
1037 MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
1038  ExceptionInfo *exception)
1039 {
1040  const char
1041  *name,
1042  *path,
1043  *value;
1044 
1045  const ConfigureInfo
1046  **configure_info;
1047 
1048  ssize_t
1049  i;
1050 
1051  size_t
1052  number_options;
1053 
1054  ssize_t
1055  j;
1056 
1057  if (file == (const FILE *) NULL)
1058  file=stdout;
1059  configure_info=GetConfigureInfoList("*",&number_options,exception);
1060  if (configure_info == (const ConfigureInfo **) NULL)
1061  return(MagickFalse);
1062  path=(const char *) NULL;
1063  for (i=0; i < (ssize_t) number_options; i++)
1064  {
1065  if (configure_info[i]->stealth != MagickFalse)
1066  continue;
1067  if ((path == (const char *) NULL) ||
1068  (LocaleCompare(path,configure_info[i]->path) != 0))
1069  {
1070  if (configure_info[i]->path != (char *) NULL)
1071  (void) FormatLocaleFile(file,"\nPath: %s\n\n",
1072  configure_info[i]->path);
1073  (void) FormatLocaleFile(file,"Name Value\n");
1074  (void) FormatLocaleFile(file,
1075  "-------------------------------------------------"
1076  "------------------------------\n");
1077  }
1078  path=configure_info[i]->path;
1079  name="unknown";
1080  if (configure_info[i]->name != (char *) NULL)
1081  name=configure_info[i]->name;
1082  (void) FormatLocaleFile(file,"%s",name);
1083  for (j=(ssize_t) strlen(name); j <= 13; j++)
1084  (void) FormatLocaleFile(file," ");
1085  (void) FormatLocaleFile(file," ");
1086  value="unknown";
1087  if (configure_info[i]->value != (char *) NULL)
1088  value=configure_info[i]->value;
1089  (void) FormatLocaleFile(file,"%s",value);
1090  (void) FormatLocaleFile(file,"\n");
1091  }
1092  (void) fflush(file);
1093  configure_info=(const ConfigureInfo **) RelinquishMagickMemory((void *)
1094  configure_info);
1095  return(MagickTrue);
1096 }
1097 
1098 #if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
1099 /*
1100 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1101 % %
1102 % %
1103 % %
1104 + L o a d C o n f i g u r e C a c h e %
1105 % %
1106 % %
1107 % %
1108 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109 %
1110 % LoadConfigureCache() loads the configure configurations which provides a
1111 % mapping between configure attributes and a configure name.
1112 %
1113 % The format of the LoadConfigureCache method is:
1114 %
1115 % MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
1116 % const char *xml,const char *filename,const size_t depth,
1117 % ExceptionInfo *exception)
1118 %
1119 % A description of each parameter follows:
1120 %
1121 % o xml: The configure list in XML format.
1122 %
1123 % o filename: The configure list filename.
1124 %
1125 % o depth: depth of <include /> statements.
1126 %
1127 % o exception: return any errors or warnings in this structure.
1128 %
1129 */
1130 static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
1131  const char *xml,const char *filename,const size_t depth,
1132  ExceptionInfo *exception)
1133 {
1134  char
1135  keyword[MaxTextExtent],
1136  *token;
1137 
1139  *configure_info;
1140 
1141  const char
1142  *q;
1143 
1144  MagickStatusType
1145  status;
1146 
1147  size_t
1148  extent;
1149 
1150  /*
1151  Load the configure map file.
1152  */
1153  (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1154  "Loading configure file \"%s\" ...",filename);
1155  status=MagickTrue;
1156  configure_info=(ConfigureInfo *) NULL;
1157  token=AcquireString(xml);
1158  extent=strlen(token)+MaxTextExtent;
1159  for (q=(char *) xml; *q != '\0'; )
1160  {
1161  /*
1162  Interpret XML.
1163  */
1164  (void) GetNextToken(q,&q,extent,token);
1165  if (*token == '\0')
1166  break;
1167  (void) CopyMagickString(keyword,token,MaxTextExtent);
1168  if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1169  {
1170  /*
1171  Doctype element.
1172  */
1173  while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1174  (void) GetNextToken(q,&q,extent,token);
1175  continue;
1176  }
1177  if (LocaleNCompare(keyword,"<!--",4) == 0)
1178  {
1179  /*
1180  Comment element.
1181  */
1182  while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1183  (void) GetNextToken(q,&q,extent,token);
1184  continue;
1185  }
1186  if (LocaleCompare(keyword,"<include") == 0)
1187  {
1188  /*
1189  Include element.
1190  */
1191  while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1192  {
1193  (void) CopyMagickString(keyword,token,MaxTextExtent);
1194  (void) GetNextToken(q,&q,extent,token);
1195  if (*token != '=')
1196  continue;
1197  (void) GetNextToken(q,&q,extent,token);
1198  if (LocaleCompare(keyword,"file") == 0)
1199  {
1200  if (depth > MagickMaxRecursionDepth)
1201  (void) ThrowMagickException(exception,GetMagickModule(),
1202  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1203  else
1204  {
1205  char
1206  path[MaxTextExtent],
1207  *xml;
1208 
1209  GetPathComponent(filename,HeadPath,path);
1210  if (*path != '\0')
1211  (void) ConcatenateMagickString(path,DirectorySeparator,
1212  MaxTextExtent);
1213  if (*token == *DirectorySeparator)
1214  (void) CopyMagickString(path,token,MaxTextExtent);
1215  else
1216  (void) ConcatenateMagickString(path,token,MaxTextExtent);
1217  xml=FileToXML(path,~0UL);
1218  if (xml != (char *) NULL)
1219  {
1220  status&=LoadConfigureCache(cache,xml,path,
1221  depth+1,exception);
1222  xml=(char *) RelinquishMagickMemory(xml);
1223  }
1224  }
1225  }
1226  }
1227  continue;
1228  }
1229  if (LocaleCompare(keyword,"<configure") == 0)
1230  {
1231  /*
1232  Configure element.
1233  */
1234  configure_info=(ConfigureInfo *) AcquireQuantumMemory(1,
1235  sizeof(*configure_info));
1236  if (configure_info == (ConfigureInfo *) NULL)
1237  ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1238  (void) memset(configure_info,0,sizeof(*configure_info));
1239  configure_info->path=ConstantString(filename);
1240  configure_info->exempt=MagickFalse;
1241  configure_info->signature=MagickCoreSignature;
1242  continue;
1243  }
1244  if (configure_info == (ConfigureInfo *) NULL)
1245  continue;
1246  if ((LocaleCompare(keyword,"/>") == 0) ||
1247  (LocaleCompare(keyword,"</policy>") == 0))
1248  {
1249  status=AppendValueToLinkedList(cache,configure_info);
1250  if (status == MagickFalse)
1251  (void) ThrowMagickException(exception,GetMagickModule(),
1252  ResourceLimitError,"MemoryAllocationFailed","`%s'",
1253  configure_info->name);
1254  configure_info=(ConfigureInfo *) NULL;
1255  continue;
1256  }
1257  /*
1258  Parse configure element.
1259  */
1260  (void) GetNextToken(q,(const char **) NULL,extent,token);
1261  if (*token != '=')
1262  continue;
1263  (void) GetNextToken(q,&q,extent,token);
1264  (void) GetNextToken(q,&q,extent,token);
1265  switch (*keyword)
1266  {
1267  case 'N':
1268  case 'n':
1269  {
1270  if (LocaleCompare((char *) keyword,"name") == 0)
1271  {
1272  configure_info->name=ConstantString(token);
1273  break;
1274  }
1275  break;
1276  }
1277  case 'S':
1278  case 's':
1279  {
1280  if (LocaleCompare((char *) keyword,"stealth") == 0)
1281  {
1282  configure_info->stealth=IsMagickTrue(token);
1283  break;
1284  }
1285  break;
1286  }
1287  case 'V':
1288  case 'v':
1289  {
1290  if (LocaleCompare((char *) keyword,"value") == 0)
1291  {
1292  configure_info->value=ConstantString(token);
1293  break;
1294  }
1295  break;
1296  }
1297  default:
1298  break;
1299  }
1300  }
1301  token=(char *) RelinquishMagickMemory(token);
1302  return(status != 0 ? MagickTrue : MagickFalse);
1303 }
1304 #endif