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