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