blob: d1cae883104daf234ce8c6810d7167e563add1ca [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
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 %
cristyde984cd2013-12-01 14:49:27 +000016% Cristy %
cristy3ed852e2009-09-05 21:47:34 +000017% July 2003 %
18% %
19% %
Cristy7ce65e72015-12-12 18:03:16 -050020% Copyright 1999-2016 ImageMagick Studio LLC, a non-profit organization %
cristy3ed852e2009-09-05 21:47:34 +000021% 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*/
cristy4c08aed2011-07-01 19:47:50 +000042#include "MagickCore/studio.h"
43#include "MagickCore/blob.h"
44#include "MagickCore/client.h"
45#include "MagickCore/configure.h"
cristy5ff4eaf2011-09-03 01:38:02 +000046#include "MagickCore/configure-private.h"
cristy4c08aed2011-07-01 19:47:50 +000047#include "MagickCore/exception.h"
48#include "MagickCore/exception-private.h"
dirkabed7e22016-01-31 17:10:21 +010049#include "MagickCore/linked-list.h"
cristy4c08aed2011-07-01 19:47:50 +000050#include "MagickCore/log.h"
51#include "MagickCore/memory_.h"
52#include "MagickCore/semaphore.h"
53#include "MagickCore/string_.h"
cristy7832dc22011-09-05 01:21:53 +000054#include "MagickCore/string-private.h"
cristy4c08aed2011-07-01 19:47:50 +000055#include "MagickCore/token.h"
56#include "MagickCore/utility.h"
cristyd1dd6e42011-09-04 01:46:08 +000057#include "MagickCore/utility-private.h"
cristy4c08aed2011-07-01 19:47:50 +000058#include "MagickCore/xml-tree.h"
cristy3291f512014-03-16 22:16:22 +000059#include "MagickCore/xml-tree-private.h"
cristy3ed852e2009-09-05 21:47:34 +000060
61/*
62 Define declarations.
63*/
64#define ConfigureFilename "configure.xml"
cristy154f9fa2012-12-05 19:30:42 +000065
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 "
Cristy1dd96da2015-10-06 07:52:01 -040078#else
cristy154f9fa2012-12-05 19:30:42 +000079#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
cristy3ed852e2009-09-05 21:47:34 +000088
89/*
cristy54a531d2009-10-21 17:58:01 +000090 Typedef declarations.
91*/
92typedef struct _ConfigureMapInfo
93{
94 const char
95 *name,
96 *value;
97} ConfigureMapInfo;
98
99/*
cristy3ed852e2009-09-05 21:47:34 +0000100 Static declarations.
101*/
cristy54a531d2009-10-21 17:58:01 +0000102static const ConfigureMapInfo
103 ConfigureMap[] =
104 {
cristy154f9fa2012-12-05 19:30:42 +0000105 { "NAME", "ImageMagick" },
106 { "QuantumDepth", MAGICKCORE_STRING_XQUOTE(MAGICKCORE_QUANTUM_DEPTH) } ,
cristybb017a02012-12-07 00:43:45 +0000107 { "FEATURES", MAGICKCORE_FEATURES_STR }
cristy54a531d2009-10-21 17:58:01 +0000108 };
cristy3ed852e2009-09-05 21:47:34 +0000109
110static LinkedListInfo
cristy86e5ac92014-03-16 19:27:39 +0000111 *configure_cache = (LinkedListInfo *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000112
113static SemaphoreInfo
114 *configure_semaphore = (SemaphoreInfo *) NULL;
cristy3ed852e2009-09-05 21:47:34 +0000115
116/*
117 Forward declarations.
118*/
119static MagickBooleanType
cristy86e5ac92014-03-16 19:27:39 +0000120 IsConfigureCacheInstantiated(ExceptionInfo *),
cristycd2cd182014-03-18 12:10:55 +0000121 LoadConfigureCache(LinkedListInfo *,const char *,const char *,const size_t,
122 ExceptionInfo *);
cristy86e5ac92014-03-16 19:27:39 +0000123
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%
cristycd2cd182014-03-18 12:10:55 +0000135% AcquireConfigureCache() caches one or more configure configurations which
cristy86e5ac92014-03-16 19:27:39 +0000136% 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*/
150static LinkedListInfo *AcquireConfigureCache(const char *filename,
151 ExceptionInfo *exception)
152{
cristy86e5ac92014-03-16 19:27:39 +0000153 LinkedListInfo
dirkb18d8642016-07-17 19:32:43 +0200154 *cache;
cristy86e5ac92014-03-16 19:27:39 +0000155
156 MagickStatusType
157 status;
158
159 register ssize_t
160 i;
161
162 /*
163 Load external configure map.
164 */
dirkb18d8642016-07-17 19:32:43 +0200165 cache=NewLinkedList(0);
166 if (cache == (LinkedListInfo *) NULL)
cristy86e5ac92014-03-16 19:27:39 +0000167 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
168 status=MagickTrue;
dirkb18d8642016-07-17 19:32:43 +0200169#if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
cristy86e5ac92014-03-16 19:27:39 +0000170 {
dirkb18d8642016-07-17 19:32:43 +0200171 const StringInfo
172 *option;
173
174 LinkedListInfo
175 *options;
176
177 options=GetConfigureOptions(filename,exception);
cristy86e5ac92014-03-16 19:27:39 +0000178 option=(const StringInfo *) GetNextValueInLinkedList(options);
dirkb18d8642016-07-17 19:32:43 +0200179 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);
cristy86e5ac92014-03-16 19:27:39 +0000186 }
dirkb18d8642016-07-17 19:32:43 +0200187#endif
cristy86e5ac92014-03-16 19:27:39 +0000188 /*
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;
cristye1c94d92015-06-28 12:16:33 +0000213 configure_info->signature=MagickCoreSignature;
dirkb18d8642016-07-17 19:32:43 +0200214 status&=AppendValueToLinkedList(cache,configure_info);
cristy86e5ac92014-03-16 19:27:39 +0000215 if (status == MagickFalse)
216 (void) ThrowMagickException(exception,GetMagickModule(),
217 ResourceLimitError,"MemoryAllocationFailed","`%s'",
218 configure_info->name);
219 }
dirkb18d8642016-07-17 19:32:43 +0200220 return(cache);
cristy86e5ac92014-03-16 19:27:39 +0000221}
cristy3ed852e2009-09-05 21:47:34 +0000222
223/*
224%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
225% %
226% %
227% %
cristyf34a1452009-10-24 22:29:27 +0000228+ 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 %
cristy3ed852e2009-09-05 21:47:34 +0000229% %
230% %
231% %
232%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
233%
cristyf34a1452009-10-24 22:29:27 +0000234% ConfigureComponentGenesis() instantiates the configure component.
cristy3ed852e2009-09-05 21:47:34 +0000235%
cristyf34a1452009-10-24 22:29:27 +0000236% The format of the ConfigureComponentGenesis method is:
cristy3ed852e2009-09-05 21:47:34 +0000237%
cristyf34a1452009-10-24 22:29:27 +0000238% MagickBooleanType ConfigureComponentGenesis(void)
239%
240*/
cristy5ff4eaf2011-09-03 01:38:02 +0000241MagickPrivate MagickBooleanType ConfigureComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000242{
cristy7c977062014-04-04 14:05:53 +0000243 if (configure_semaphore == (SemaphoreInfo *) NULL)
244 configure_semaphore=AcquireSemaphoreInfo();
cristyf34a1452009-10-24 22:29:27 +0000245 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)
cristy3ed852e2009-09-05 21:47:34 +0000264%
265*/
266
267static void *DestroyConfigureElement(void *configure_info)
268{
269 register ConfigureInfo
270 *p;
271
272 p=(ConfigureInfo *) configure_info;
cristy54a531d2009-10-21 17:58:01 +0000273 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 }
cristy3ed852e2009-09-05 21:47:34 +0000282 p=(ConfigureInfo *) RelinquishMagickMemory(p);
283 return((void *) NULL);
284}
285
cristy5ff4eaf2011-09-03 01:38:02 +0000286MagickPrivate void ConfigureComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000287{
cristy18b17442009-10-25 18:36:48 +0000288 if (configure_semaphore == (SemaphoreInfo *) NULL)
cristy04b11db2014-02-16 15:10:39 +0000289 ActivateSemaphoreInfo(&configure_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000290 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000291 if (configure_cache != (LinkedListInfo *) NULL)
292 configure_cache=DestroyLinkedList(configure_cache,DestroyConfigureElement);
293 configure_cache=(LinkedListInfo *) NULL;
cristyf84a1932010-01-03 18:00:18 +0000294 UnlockSemaphoreInfo(configure_semaphore);
cristy3d162a92014-02-16 14:05:06 +0000295 RelinquishSemaphoreInfo(&configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000296}
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
322static void *DestroyOptions(void *option)
323{
324 return(DestroyStringInfo((StringInfo *) option));
325}
326
327MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
328{
329 assert(options != (LinkedListInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000330 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*/
362MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
363 ExceptionInfo *exception)
364{
365 register const ConfigureInfo
366 *p;
367
368 assert(exception != (ExceptionInfo *) NULL);
cristy86e5ac92014-03-16 19:27:39 +0000369 if (IsConfigureCacheInstantiated(exception) == MagickFalse)
cristy904e5912014-03-15 19:53:14 +0000370 return((const ConfigureInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000371 /*
372 Search for configure tag.
373 */
cristyf84a1932010-01-03 18:00:18 +0000374 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000375 ResetLinkedListIterator(configure_cache);
376 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy49d4d222014-03-16 00:37:58 +0000377 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
378 {
379 UnlockSemaphoreInfo(configure_semaphore);
380 return(p);
381 }
cristy3ed852e2009-09-05 21:47:34 +0000382 while (p != (const ConfigureInfo *) NULL)
383 {
384 if (LocaleCompare(name,p->name) == 0)
385 break;
cristy86e5ac92014-03-16 19:27:39 +0000386 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000387 }
388 if (p != (ConfigureInfo *) NULL)
cristy86e5ac92014-03-16 19:27:39 +0000389 (void) InsertValueInLinkedList(configure_cache,0,
390 RemoveElementByValueFromLinkedList(configure_cache,p));
cristyf84a1932010-01-03 18:00:18 +0000391 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000392 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,
cristybb503372010-05-27 20:51:26 +0000412% size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000413%
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)
426extern "C" {
427#endif
428
429static 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
446MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000447 size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000448{
449 const ConfigureInfo
450 **options;
451
452 register const ConfigureInfo
453 *p;
454
cristybb503372010-05-27 20:51:26 +0000455 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000456 i;
457
458 /*
459 Allocate configure list.
460 */
461 assert(pattern != (char *) NULL);
462 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000463 assert(number_options != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000464 *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)
cristy86e5ac92014-03-16 19:27:39 +0000469 GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
cristy3ed852e2009-09-05 21:47:34 +0000470 if (options == (const ConfigureInfo **) NULL)
471 return((const ConfigureInfo **) NULL);
472 /*
473 Generate configure list.
474 */
cristyf84a1932010-01-03 18:00:18 +0000475 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000476 ResetLinkedListIterator(configure_cache);
477 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000478 for (i=0; p != (const ConfigureInfo *) NULL; )
479 {
480 if ((p->stealth == MagickFalse) &&
481 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
482 options[i++]=p;
cristy86e5ac92014-03-16 19:27:39 +0000483 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000484 }
cristyf84a1932010-01-03 18:00:18 +0000485 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000486 qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
487 options[i]=(ConfigureInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000488 *number_options=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000489 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,
cristybb503372010-05-27 20:51:26 +0000509% size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000510%
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 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
540MagickExport char **GetConfigureList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000541 size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000542{
543 char
544 **options;
545
546 register const ConfigureInfo
547 *p;
548
cristybb503372010-05-27 20:51:26 +0000549 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000550 i;
551
552 /*
553 Allocate configure list.
554 */
555 assert(pattern != (char *) NULL);
556 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000557 assert(number_options != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000558 *number_options=0;
559 p=GetConfigureInfo("*",exception);
560 if (p == (const ConfigureInfo *) NULL)
561 return((char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000562 options=(char **) AcquireQuantumMemory((size_t)
cristy86e5ac92014-03-16 19:27:39 +0000563 GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
cristy3ed852e2009-09-05 21:47:34 +0000564 if (options == (char **) NULL)
565 return((char **) NULL);
cristyf84a1932010-01-03 18:00:18 +0000566 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000567 ResetLinkedListIterator(configure_cache);
568 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000569 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);
cristy86e5ac92014-03-16 19:27:39 +0000574 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000575 }
cristyf84a1932010-01-03 18:00:18 +0000576 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000577 qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
578 options[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000579 *number_options=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000580 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*/
605MagickExport 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*/
655MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
656 ExceptionInfo *exception)
657{
658 char
cristy151b66d2015-04-15 10:50:31 +0000659 path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000660
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);
cristy151b66d2015-04-15 10:50:31 +0000674 (void) CopyMagickString(path,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000675 /*
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 {
Cristyf4a35c32016-06-02 13:45:36 -0400686 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",element,
687 filename);
cristy3ed852e2009-09-05 21:47:34 +0000688 (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 }
cristy0157aea2010-04-24 21:12:18 +0000697#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy7e247522011-11-29 14:59:23 +0000698 if (GetNumberOfElementsInLinkedList(options) == 0)
699 {
700 char
701 *blob;
cristy3ed852e2009-09-05 21:47:34 +0000702
cristy7e247522011-11-29 14:59:23 +0000703 blob=(char *) NTResourceToBlob(filename);
704 if (blob != (char *) NULL)
705 {
706 xml=AcquireStringInfo(0);
707 SetStringInfoLength(xml,strlen(blob)+1);
cristy52070b42012-02-19 22:03:21 +0000708 SetStringInfoDatum(xml,(unsigned char *) blob);
cristy7e247522011-11-29 14:59:23 +0000709 SetStringInfoPath(xml,filename);
710 (void) AppendValueToLinkedList(options,xml);
711 }
712 }
cristy3ed852e2009-09-05 21:47:34 +0000713#endif
714 if (GetNumberOfElementsInLinkedList(options) == 0)
715 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
cristyefe601c2013-01-05 17:51:12 +0000716 "UnableToOpenConfigureFile","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +0000717 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*/
747MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
748 ExceptionInfo *exception)
749{
cristy7e247522011-11-29 14:59:23 +0000750#define RegistryKey "ConfigurePath"
cristy6c28ec02011-10-28 11:37:57 +0000751#define MagickCoreDLL "CORE_RL_MagickCore_.dll"
752#define MagickCoreDebugDLL "CORE_DB_MagickCore_.dll"
753
cristy3ed852e2009-09-05 21:47:34 +0000754 char
cristy151b66d2015-04-15 10:50:31 +0000755 path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000756
757 LinkedListInfo
758 *paths;
759
760 assert(filename != (const char *) NULL);
761 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
762 assert(exception != (ExceptionInfo *) NULL);
cristy151b66d2015-04-15 10:50:31 +0000763 (void) CopyMagickString(path,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000764 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 {
cristy151b66d2015-04-15 10:50:31 +0000781 (void) CopyMagickString(path,p+1,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000782 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,
cristy151b66d2015-04-15 10:50:31 +0000788 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000789 (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)
cristy4f820712011-04-01 12:35:43 +0000796#if defined(MAGICKCORE_SHARE_PATH)
cristy6c28ec02011-10-28 11:37:57 +0000797 (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
cristy3ed852e2009-09-05 21:47:34 +0000798#endif
cristy670aa3c2011-11-03 00:54:00 +0000799#if defined(MAGICKCORE_SHAREARCH_PATH)
800 (void) AppendValueToLinkedList(paths,ConstantString(
801 MAGICKCORE_SHAREARCH_PATH));
802#endif
cristy3ed852e2009-09-05 21:47:34 +0000803#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
cristy4f820712011-04-01 12:35:43 +0000811#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
cristy3ed852e2009-09-05 21:47:34 +0000812 {
cristy3ed852e2009-09-05 21:47:34 +0000813 unsigned char
814 *key_value;
815
816 /*
817 Locate file via registry key.
818 */
cristy7e247522011-11-29 14:59:23 +0000819 key_value=NTRegistryKeyLookup(RegistryKey);
cristy3ed852e2009-09-05 21:47:34 +0000820 if (key_value != (unsigned char *) NULL)
821 {
Cristy9799a842015-10-04 19:44:36 -0400822 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",(char *)
823 key_value,DirectorySeparator);
cristy3ed852e2009-09-05 21:47:34 +0000824 (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 {
Cristy9125cd52015-09-17 20:16:13 -0400840#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
cristy151b66d2015-04-15 10:50:31 +0000841 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",home,
cristy3ed852e2009-09-05 21:47:34 +0000842 DirectorySeparator);
843 (void) AppendValueToLinkedList(paths,ConstantString(path));
844#else
cristy151b66d2015-04-15 10:50:31 +0000845 (void) FormatLocaleString(path,MagickPathExtent,"%s/etc/%s/",home,
cristy3ed852e2009-09-05 21:47:34 +0000846 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
847 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000848 (void) FormatLocaleString(path,MagickPathExtent,"%s/share/%s/",home,
cristy4f820712011-04-01 12:35:43 +0000849 MAGICKCORE_SHARE_RELATIVE_PATH);
cristy3ed852e2009-09-05 21:47:34 +0000850 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000851 (void) FormatLocaleString(path,MagickPathExtent,"%s",
cristy780d58c2013-05-03 13:49:00 +0000852 MAGICKCORE_SHAREARCH_PATH);
853 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy3ed852e2009-09-05 21:47:34 +0000854#endif
855 home=DestroyString(home);
856 }
857 }
858 if (*GetClientPath() != '\0')
859 {
Cristy9125cd52015-09-17 20:16:13 -0400860#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
cristy151b66d2015-04-15 10:50:31 +0000861 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",GetClientPath(),
cristy3ed852e2009-09-05 21:47:34 +0000862 DirectorySeparator);
863 (void) AppendValueToLinkedList(paths,ConstantString(path));
864#else
865 char
cristy151b66d2015-04-15 10:50:31 +0000866 prefix[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000867
868 /*
869 Search based on executable directory if directory is known.
870 */
cristy151b66d2015-04-15 10:50:31 +0000871 (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000872 ChopPathComponents(prefix,1);
cristy151b66d2015-04-15 10:50:31 +0000873 (void) FormatLocaleString(path,MagickPathExtent,"%s/etc/%s/",prefix,
cristy3ed852e2009-09-05 21:47:34 +0000874 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
875 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000876 (void) FormatLocaleString(path,MagickPathExtent,"%s/share/%s/",prefix,
cristy4f820712011-04-01 12:35:43 +0000877 MAGICKCORE_SHARE_RELATIVE_PATH);
878 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000879 (void) FormatLocaleString(path,MagickPathExtent,"%s",
cristy780d58c2013-05-03 13:49:00 +0000880 MAGICKCORE_SHAREARCH_PATH);
881 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy3ed852e2009-09-05 21:47:34 +0000882#endif
883 }
cristy51b1ac52010-10-30 02:27:14 +0000884 /*
885 Search current directory.
886 */
887 (void) AppendValueToLinkedList(paths,ConstantString(""));
cristy3ed852e2009-09-05 21:47:34 +0000888#endif
889 {
890 char
891 *home;
892
Cristy9799a842015-10-04 19:44:36 -0400893 home=GetEnvironmentValue("XDG_CONFIG_HOME");
Cristy1dd96da2015-10-06 07:52:01 -0400894 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");
Cristy9799a842015-10-04 19:44:36 -0400900 if (home != (char *) NULL)
Cristy1dd96da2015-10-06 07:52:01 -0400901 {
Cristy9799a842015-10-04 19:44:36 -0400902 /*
903 Search $XDG_CONFIG_HOME/ImageMagick.
904 */
Cristya8b2bb22016-03-25 10:39:01 -0400905 (void) FormatLocaleString(path,MagickPathExtent,"%s%sImageMagick%s",
dirka4bed212015-11-09 13:02:16 +0100906 home,DirectorySeparator,DirectorySeparator);
Cristy9799a842015-10-04 19:44:36 -0400907 (void) AppendValueToLinkedList(paths,ConstantString(path));
908 home=DestroyString(home);
909 }
cristy3ed852e2009-09-05 21:47:34 +0000910 home=GetEnvironmentValue("HOME");
cristy3ed852e2009-09-05 21:47:34 +0000911 if (home != (char *) NULL)
912 {
913 /*
cristy9f3b4fc2014-02-08 14:56:20 +0000914 Search $HOME/.config/ImageMagick.
cristy3ed852e2009-09-05 21:47:34 +0000915 */
cristy151b66d2015-04-15 10:50:31 +0000916 (void) FormatLocaleString(path,MagickPathExtent,
cristy9f3b4fc2014-02-08 14:56:20 +0000917 "%s%s.config%sImageMagick%s",home,DirectorySeparator,
cristy3ed852e2009-09-05 21:47:34 +0000918 DirectorySeparator,DirectorySeparator);
919 (void) AppendValueToLinkedList(paths,ConstantString(path));
920 home=DestroyString(home);
921 }
922 }
cristy0157aea2010-04-24 21:12:18 +0000923#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000924 {
925 char
cristy151b66d2015-04-15 10:50:31 +0000926 module_path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000927
cristy6c28ec02011-10-28 11:37:57 +0000928 if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
929 (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +0000930 {
cristy7e247522011-11-29 14:59:23 +0000931 unsigned char
932 *key_value;
cristy3ed852e2009-09-05 21:47:34 +0000933
934 /*
935 Search module path.
936 */
cristy151b66d2015-04-15 10:50:31 +0000937 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000938 DirectorySeparator);
cristy7e247522011-11-29 14:59:23 +0000939 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);
cristy3ed852e2009-09-05 21:47:34 +0000944 }
945 if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
946 {
947 /*
948 Search PerlMagick module path.
949 */
cristy151b66d2015-04-15 10:50:31 +0000950 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000951 DirectorySeparator);
952 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000953 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000954 "\\inc\\lib\\auto\\Image\\Magick\\");
955 (void) AppendValueToLinkedList(paths,ConstantString(path));
956 }
957 }
958#endif
cristy3ed852e2009-09-05 21:47:34 +0000959 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*/
984MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
985{
986 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
987 assert(configure_info != (ConfigureInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000988 assert(configure_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000989 return(configure_info->value);
990}
991
992/*
993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994% %
995% %
996% %
cristy86e5ac92014-03-16 19:27:39 +0000997+ 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 %
cristy3ed852e2009-09-05 21:47:34 +0000998% %
999% %
1000% %
1001%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1002%
cristy86e5ac92014-03-16 19:27:39 +00001003% IsConfigureCacheInstantiated() determines if the configure list is
cristy904e5912014-03-15 19:53:14 +00001004% instantiated. If not, it instantiates the list and returns it.
cristy3ed852e2009-09-05 21:47:34 +00001005%
cristy904e5912014-03-15 19:53:14 +00001006% The format of the IsConfigureInstantiated method is:
cristy3ed852e2009-09-05 21:47:34 +00001007%
cristy86e5ac92014-03-16 19:27:39 +00001008% MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001009%
1010% A description of each parameter follows.
1011%
1012% o exception: return any errors or warnings in this structure.
1013%
1014*/
cristy86e5ac92014-03-16 19:27:39 +00001015static MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001016{
cristy86e5ac92014-03-16 19:27:39 +00001017 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);
cristy3ed852e2009-09-05 21:47:34 +00001027}
1028
1029/*
1030%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031% %
1032% %
1033% %
cristy3ed852e2009-09-05 21:47:34 +00001034% 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*/
1053MagickExport 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
cristybb503372010-05-27 20:51:26 +00001064 register ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001065 i;
1066
cristybb503372010-05-27 20:51:26 +00001067 size_t
cristy3ed852e2009-09-05 21:47:34 +00001068 number_options;
1069
cristy9d314ff2011-03-09 01:30:28 +00001070 ssize_t
1071 j;
1072
cristy3ed852e2009-09-05 21:47:34 +00001073 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;
cristybb503372010-05-27 20:51:26 +00001079 for (i=0; i < (ssize_t) number_options; i++)
cristy3ed852e2009-09-05 21:47:34 +00001080 {
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)
cristy1e604812011-05-19 18:07:50 +00001087 (void) FormatLocaleFile(file,"\nPath: %s\n\n",
1088 configure_info[i]->path);
cristy9f973042012-12-06 01:28:59 +00001089 (void) FormatLocaleFile(file,"Name Value\n");
cristy1e604812011-05-19 18:07:50 +00001090 (void) FormatLocaleFile(file,
1091 "-------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +00001092 "------------------------------\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;
cristyb51dff52011-05-19 16:55:47 +00001098 (void) FormatLocaleFile(file,"%s",name);
cristy9f973042012-12-06 01:28:59 +00001099 for (j=(ssize_t) strlen(name); j <= 13; j++)
cristyb51dff52011-05-19 16:55:47 +00001100 (void) FormatLocaleFile(file," ");
1101 (void) FormatLocaleFile(file," ");
cristy3ed852e2009-09-05 21:47:34 +00001102 value="unknown";
1103 if (configure_info[i]->value != (char *) NULL)
1104 value=configure_info[i]->value;
cristyb51dff52011-05-19 16:55:47 +00001105 (void) FormatLocaleFile(file,"%s",value);
1106 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00001107 }
1108 (void) fflush(file);
cristycd2cd182014-03-18 12:10:55 +00001109 configure_info=(const ConfigureInfo **) RelinquishMagickMemory((void *)
1110 configure_info);
cristy3ed852e2009-09-05 21:47:34 +00001111 return(MagickTrue);
1112}
1113
1114/*
1115%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1116% %
1117% %
1118% %
dirkfc0f1242016-03-26 00:36:39 +01001119+ L o a d C o n f i g u r e C a c h e %
cristy3ed852e2009-09-05 21:47:34 +00001120% %
1121% %
1122% %
1123%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1124%
cristy86e5ac92014-03-16 19:27:39 +00001125% LoadConfigureCache() loads the configure configurations which provides a
cristy3ed852e2009-09-05 21:47:34 +00001126% mapping between configure attributes and a configure name.
1127%
cristy86e5ac92014-03-16 19:27:39 +00001128% The format of the LoadConfigureCache method is:
cristy3ed852e2009-09-05 21:47:34 +00001129%
dirkb18d8642016-07-17 19:32:43 +02001130% MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
cristy0d8101e2014-04-10 00:13:05 +00001131% const char *xml,const char *filename,const size_t depth,
1132% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001133%
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*/
dirkb18d8642016-07-17 19:32:43 +02001145static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
cristycd2cd182014-03-18 12:10:55 +00001146 const char *xml,const char *filename,const size_t depth,
1147 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001148{
1149 char
cristy151b66d2015-04-15 10:50:31 +00001150 keyword[MagickPathExtent],
cristy3ed852e2009-09-05 21:47:34 +00001151 *token;
1152
1153 ConfigureInfo
1154 *configure_info;
1155
1156 const char
1157 *q;
1158
cristy759ba912014-06-26 11:59:43 +00001159 MagickStatusType
cristy3ed852e2009-09-05 21:47:34 +00001160 status;
1161
dirkfc0f1242016-03-26 00:36:39 +01001162 size_t
1163 extent;
1164
cristy3ed852e2009-09-05 21:47:34 +00001165 /*
1166 Load the configure map file.
1167 */
1168 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1169 "Loading configure file \"%s\" ...",filename);
cristy3ed852e2009-09-05 21:47:34 +00001170 status=MagickTrue;
1171 configure_info=(ConfigureInfo *) NULL;
dirkfc0f1242016-03-26 00:36:39 +01001172 token=AcquireString(xml);
1173 extent=strlen(token)+MagickPathExtent;
cristy3ed852e2009-09-05 21:47:34 +00001174 for (q=(char *) xml; *q != '\0'; )
1175 {
1176 /*
1177 Interpret XML.
1178 */
Cristy8bedb4e2016-03-25 19:54:25 -04001179 GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001180 if (*token == '\0')
1181 break;
cristy151b66d2015-04-15 10:50:31 +00001182 (void) CopyMagickString(keyword,token,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001183 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1184 {
1185 /*
1186 Doctype element.
1187 */
1188 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
Cristy8bedb4e2016-03-25 19:54:25 -04001189 GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001190 continue;
1191 }
1192 if (LocaleNCompare(keyword,"<!--",4) == 0)
1193 {
1194 /*
1195 Comment element.
1196 */
1197 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
Cristy8bedb4e2016-03-25 19:54:25 -04001198 GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001199 continue;
1200 }
1201 if (LocaleCompare(keyword,"<include") == 0)
1202 {
1203 /*
1204 Include element.
1205 */
1206 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1207 {
cristy151b66d2015-04-15 10:50:31 +00001208 (void) CopyMagickString(keyword,token,MagickPathExtent);
Cristy8bedb4e2016-03-25 19:54:25 -04001209 GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001210 if (*token != '=')
1211 continue;
Cristy8bedb4e2016-03-25 19:54:25 -04001212 GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001213 if (LocaleCompare(keyword,"file") == 0)
1214 {
1215 if (depth > 200)
1216 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001217 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
cristy3ed852e2009-09-05 21:47:34 +00001218 else
1219 {
1220 char
cristy151b66d2015-04-15 10:50:31 +00001221 path[MagickPathExtent],
dirkb81f0ab2015-10-20 23:01:53 +02001222 *file_xml;
cristy3ed852e2009-09-05 21:47:34 +00001223
1224 GetPathComponent(filename,HeadPath,path);
1225 if (*path != '\0')
1226 (void) ConcatenateMagickString(path,DirectorySeparator,
cristy151b66d2015-04-15 10:50:31 +00001227 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001228 if (*token == *DirectorySeparator)
cristy151b66d2015-04-15 10:50:31 +00001229 (void) CopyMagickString(path,token,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001230 else
cristy151b66d2015-04-15 10:50:31 +00001231 (void) ConcatenateMagickString(path,token,MagickPathExtent);
dirkb81f0ab2015-10-20 23:01:53 +02001232 file_xml=FileToXML(path,~0UL);
1233 if (file_xml != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001234 {
dirkb18d8642016-07-17 19:32:43 +02001235 status&=LoadConfigureCache(cache,file_xml,path,depth+1,
1236 exception);
dirkb81f0ab2015-10-20 23:01:53 +02001237 file_xml=DestroyString(file_xml);
cristy3ed852e2009-09-05 21:47:34 +00001238 }
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);
cristy54a531d2009-10-21 17:58:01 +00001255 configure_info->exempt=MagickFalse;
cristye1c94d92015-06-28 12:16:33 +00001256 configure_info->signature=MagickCoreSignature;
cristy3ed852e2009-09-05 21:47:34 +00001257 continue;
1258 }
1259 if (configure_info == (ConfigureInfo *) NULL)
1260 continue;
1261 if (LocaleCompare(keyword,"/>") == 0)
1262 {
dirkb18d8642016-07-17 19:32:43 +02001263 status=AppendValueToLinkedList(cache,configure_info);
cristy3ed852e2009-09-05 21:47:34 +00001264 if (status == MagickFalse)
1265 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001266 ResourceLimitError,"MemoryAllocationFailed","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001267 configure_info->name);
1268 configure_info=(ConfigureInfo *) NULL;
cristyd45122f2014-01-14 23:46:16 +00001269 continue;
cristy3ed852e2009-09-05 21:47:34 +00001270 }
1271 /*
1272 Parse configure element.
1273 */
Cristy8bedb4e2016-03-25 19:54:25 -04001274 GetNextToken(q,(const char **) NULL,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001275 if (*token != '=')
1276 continue;
Cristy8bedb4e2016-03-25 19:54:25 -04001277 GetNextToken(q,&q,extent,token);
1278 GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001279 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 {
anthony6f201312012-03-30 04:08:15 +00001296 configure_info->stealth=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +00001297 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);
cristy759ba912014-06-26 11:59:43 +00001316 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001317}