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