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