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