blob: 02d2daa0d5a1aa37e552fdd5bc338c498d5a5973 [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% %
Cristyd8420112021-01-01 14:52:00 -050020% Copyright 1999-2021 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% %
Cristy9ddfcca2018-09-09 19:46:34 -040026% https://imagemagick.org/script/license.php %
cristy3ed852e2009-09-05 21:47:34 +000027% %
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"
Dirk Lemstra0816fc32019-01-13 12:38:59 +010058#include "MagickCore/version.h"
cristy4c08aed2011-07-01 19:47:50 +000059#include "MagickCore/xml-tree.h"
cristy3291f512014-03-16 22:16:22 +000060#include "MagickCore/xml-tree-private.h"
cristy3ed852e2009-09-05 21:47:34 +000061
62/*
63 Define declarations.
64*/
65#define ConfigureFilename "configure.xml"
66
67/*
cristy54a531d2009-10-21 17:58:01 +000068 Typedef declarations.
69*/
70typedef struct _ConfigureMapInfo
71{
72 const char
73 *name,
74 *value;
75} ConfigureMapInfo;
76
77/*
cristy3ed852e2009-09-05 21:47:34 +000078 Static declarations.
79*/
cristy3ed852e2009-09-05 21:47:34 +000080
81static LinkedListInfo
cristy86e5ac92014-03-16 19:27:39 +000082 *configure_cache = (LinkedListInfo *) NULL;
cristy3ed852e2009-09-05 21:47:34 +000083
84static SemaphoreInfo
85 *configure_semaphore = (SemaphoreInfo *) NULL;
cristy3ed852e2009-09-05 21:47:34 +000086
87/*
88 Forward declarations.
89*/
90static MagickBooleanType
Cristyd1e7b762019-12-07 19:00:20 -050091 IsConfigureCacheInstantiated(ExceptionInfo *);
92
93#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
94static MagickBooleanType
cristycd2cd182014-03-18 12:10:55 +000095 LoadConfigureCache(LinkedListInfo *,const char *,const char *,const size_t,
96 ExceptionInfo *);
Cristyd1e7b762019-12-07 19:00:20 -050097#endif
cristy86e5ac92014-03-16 19:27:39 +000098
99/*
100%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
101% %
102% %
103% %
104% A c q u i r e C o n f i g u r e C a c h e %
105% %
106% %
107% %
108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
109%
cristycd2cd182014-03-18 12:10:55 +0000110% AcquireConfigureCache() caches one or more configure configurations which
cristy86e5ac92014-03-16 19:27:39 +0000111% provides a mapping between configure attributes and a configure name.
112%
113% The format of the AcquireConfigureCache method is:
114%
115% LinkedListInfo *AcquireConfigureCache(const char *filename,
116% ExceptionInfo *exception)
117%
118% A description of each parameter follows:
119%
120% o filename: the font file name.
121%
122% o exception: return any errors or warnings in this structure.
123%
124*/
Dirk Lemstra0816fc32019-01-13 12:38:59 +0100125static inline void AddConfigureKey(LinkedListInfo *cache,const char *path,
Dirk Lemstrae8342ff2019-01-13 13:07:18 +0100126 const char *name,const char *value,MagickBooleanType exempt)
Cristy1af75e52018-11-15 07:59:32 -0500127{
128 ConfigureInfo
129 *configure_info;
130
Cristy8357b5d2020-11-22 12:39:10 +0000131 configure_info=(ConfigureInfo *) AcquireMagickMemory(sizeof(*configure_info));
Cristy1af75e52018-11-15 07:59:32 -0500132 if (configure_info == (ConfigureInfo *) NULL)
Dirk Lemstra0816fc32019-01-13 12:38:59 +0100133 return;
Cristy1af75e52018-11-15 07:59:32 -0500134 (void) memset(configure_info,0,sizeof(*configure_info));
Dirk Lemstrae8342ff2019-01-13 13:07:18 +0100135 if (exempt == MagickTrue)
136 {
137 configure_info->path=(char *) path;
138 configure_info->name=(char *) name;
139 configure_info->value=(char *) value;
140 }
141 else
142 {
143 configure_info->path=ConstantString(path);
144 configure_info->name=ConstantString(name);
145 configure_info->value=ConstantString(value);
146 }
147 configure_info->exempt=exempt;
Cristy1af75e52018-11-15 07:59:32 -0500148 configure_info->signature=MagickCoreSignature;
Dirk Lemstra0816fc32019-01-13 12:38:59 +0100149 (void) AppendValueToLinkedList(cache,configure_info);
Cristy1af75e52018-11-15 07:59:32 -0500150}
151
cristy86e5ac92014-03-16 19:27:39 +0000152static LinkedListInfo *AcquireConfigureCache(const char *filename,
153 ExceptionInfo *exception)
154{
Cristy1af75e52018-11-15 07:59:32 -0500155 char
156 head_path[MagickPathExtent],
157 path[MagickPathExtent];
158
cristy86e5ac92014-03-16 19:27:39 +0000159 LinkedListInfo
dirkb18d8642016-07-17 19:32:43 +0200160 *cache;
cristy86e5ac92014-03-16 19:27:39 +0000161
cristy86e5ac92014-03-16 19:27:39 +0000162 /*
163 Load external configure map.
164 */
dirkb18d8642016-07-17 19:32:43 +0200165 cache=NewLinkedList(0);
Cristyd1e7b762019-12-07 19:00:20 -0500166#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
cristy86e5ac92014-03-16 19:27:39 +0000167 {
dirkb18d8642016-07-17 19:32:43 +0200168 const StringInfo
169 *option;
170
171 LinkedListInfo
172 *options;
173
Dirk Lemstra2ae30a52019-01-13 12:42:45 +0100174 MagickBooleanType
175 status;
176
dirkb18d8642016-07-17 19:32:43 +0200177 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 {
Dirk Lemstra2ae30a52019-01-13 12:42:45 +0100181 status=LoadConfigureCache(cache,(const char *)
dirkb18d8642016-07-17 19:32:43 +0200182 GetStringInfoDatum(option),GetStringInfoPath(option),0,exception);
Dirk Lemstra2ae30a52019-01-13 12:42:45 +0100183 if (status == MagickTrue)
184 break;
dirkb18d8642016-07-17 19:32:43 +0200185 option=(const StringInfo *) GetNextValueInLinkedList(options);
186 }
187 options=DestroyConfigureOptions(options);
cristy86e5ac92014-03-16 19:27:39 +0000188 }
dirkb18d8642016-07-17 19:32:43 +0200189#endif
cristy86e5ac92014-03-16 19:27:39 +0000190 /*
Dirk Lemstra0816fc32019-01-13 12:38:59 +0100191 Load built-in configure.
cristy86e5ac92014-03-16 19:27:39 +0000192 */
Dirk Lemstrae8342ff2019-01-13 13:07:18 +0100193 AddConfigureKey(cache,"[built-in]","NAME","ImageMagick",MagickTrue);
Cristy1af75e52018-11-15 07:59:32 -0500194 /*
195 Load runtime configuration.
196 */
Dirk Lemstra0816fc32019-01-13 12:38:59 +0100197 AddConfigureKey(cache,"[built-in]","QuantumDepth",GetMagickQuantumDepth(
Dirk Lemstrae8342ff2019-01-13 13:07:18 +0100198 (size_t *)NULL),MagickTrue);
199 AddConfigureKey(cache,"[built-in]","FEATURES",GetMagickFeatures(),
200 MagickTrue);
201 AddConfigureKey(cache,"[built-in]","DELEGATES",GetMagickDelegates(),
202 MagickTrue);
Cristy1af75e52018-11-15 07:59:32 -0500203 (void) AcquireUniqueFilename(path);
204 GetPathComponent(path,HeadPath,head_path);
Dirk Lemstrae8342ff2019-01-13 13:07:18 +0100205 AddConfigureKey(cache,"[built-in]","MAGICK_TEMPORARY_PATH",head_path,
206 MagickFalse);
dirkb18d8642016-07-17 19:32:43 +0200207 return(cache);
cristy86e5ac92014-03-16 19:27:39 +0000208}
cristy3ed852e2009-09-05 21:47:34 +0000209
210/*
211%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
212% %
213% %
214% %
cristyf34a1452009-10-24 22:29:27 +0000215+ 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 +0000216% %
217% %
218% %
219%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
220%
cristyf34a1452009-10-24 22:29:27 +0000221% ConfigureComponentGenesis() instantiates the configure component.
cristy3ed852e2009-09-05 21:47:34 +0000222%
cristyf34a1452009-10-24 22:29:27 +0000223% The format of the ConfigureComponentGenesis method is:
cristy3ed852e2009-09-05 21:47:34 +0000224%
cristyf34a1452009-10-24 22:29:27 +0000225% MagickBooleanType ConfigureComponentGenesis(void)
226%
227*/
cristy5ff4eaf2011-09-03 01:38:02 +0000228MagickPrivate MagickBooleanType ConfigureComponentGenesis(void)
cristyf34a1452009-10-24 22:29:27 +0000229{
cristy7c977062014-04-04 14:05:53 +0000230 if (configure_semaphore == (SemaphoreInfo *) NULL)
231 configure_semaphore=AcquireSemaphoreInfo();
cristyf34a1452009-10-24 22:29:27 +0000232 return(MagickTrue);
233}
234
235/*
236%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
237% %
238% %
239% %
240+ C o n f i g u r e C o m p o n e n t T e r m i n u s %
241% %
242% %
243% %
244%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
245%
246% ConfigureComponentTerminus() destroys the configure component.
247%
248% The format of the ConfigureComponentTerminus method is:
249%
250% ConfigureComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000251%
252*/
253
254static void *DestroyConfigureElement(void *configure_info)
255{
Cristyf2dc1dd2020-12-28 13:59:26 -0500256 ConfigureInfo
cristy3ed852e2009-09-05 21:47:34 +0000257 *p;
258
259 p=(ConfigureInfo *) configure_info;
cristy54a531d2009-10-21 17:58:01 +0000260 if (p->exempt == MagickFalse)
261 {
262 if (p->value != (char *) NULL)
263 p->value=DestroyString(p->value);
264 if (p->name != (char *) NULL)
265 p->name=DestroyString(p->name);
266 if (p->path != (char *) NULL)
267 p->path=DestroyString(p->path);
268 }
cristy3ed852e2009-09-05 21:47:34 +0000269 p=(ConfigureInfo *) RelinquishMagickMemory(p);
270 return((void *) NULL);
271}
272
cristy5ff4eaf2011-09-03 01:38:02 +0000273MagickPrivate void ConfigureComponentTerminus(void)
cristy3ed852e2009-09-05 21:47:34 +0000274{
cristy18b17442009-10-25 18:36:48 +0000275 if (configure_semaphore == (SemaphoreInfo *) NULL)
cristy04b11db2014-02-16 15:10:39 +0000276 ActivateSemaphoreInfo(&configure_semaphore);
cristyf84a1932010-01-03 18:00:18 +0000277 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000278 if (configure_cache != (LinkedListInfo *) NULL)
279 configure_cache=DestroyLinkedList(configure_cache,DestroyConfigureElement);
280 configure_cache=(LinkedListInfo *) NULL;
cristyf84a1932010-01-03 18:00:18 +0000281 UnlockSemaphoreInfo(configure_semaphore);
cristy3d162a92014-02-16 14:05:06 +0000282 RelinquishSemaphoreInfo(&configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000283}
284
285/*
286%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
287% %
288% %
289% %
290% D e s t r o y C o n f i g u r e O p t i o n s %
291% %
292% %
293% %
294%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
295%
296% DestroyConfigureOptions() releases memory associated with an configure
297% options.
298%
299% The format of the DestroyProfiles method is:
300%
301% LinkedListInfo *DestroyConfigureOptions(Image *image)
302%
303% A description of each parameter follows:
304%
305% o image: the image.
306%
307*/
308
309static void *DestroyOptions(void *option)
310{
311 return(DestroyStringInfo((StringInfo *) option));
312}
313
314MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
315{
316 assert(options != (LinkedListInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000317 return(DestroyLinkedList(options,DestroyOptions));
318}
319
320/*
321%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
322% %
323% %
324% %
325+ G e t C o n f i g u r e I n f o %
326% %
327% %
328% %
329%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
330%
331% GetConfigureInfo() searches the configure list for the specified name and if
332% found returns attributes for that element.
333%
334% The format of the GetConfigureInfo method is:
335%
336% const ConfigureInfo *GetConfigureInfo(const char *name,
337% ExceptionInfo *exception)
338%
339% A description of each parameter follows:
340%
341% o configure_info: GetConfigureInfo() searches the configure list for the
342% specified name and if found returns attributes for that element.
343%
344% o name: the configure name.
345%
346% o exception: return any errors or warnings in this structure.
347%
348*/
349MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
350 ExceptionInfo *exception)
351{
Cristyf2dc1dd2020-12-28 13:59:26 -0500352 const ConfigureInfo
cristy3ed852e2009-09-05 21:47:34 +0000353 *p;
354
355 assert(exception != (ExceptionInfo *) NULL);
cristy86e5ac92014-03-16 19:27:39 +0000356 if (IsConfigureCacheInstantiated(exception) == MagickFalse)
cristy904e5912014-03-15 19:53:14 +0000357 return((const ConfigureInfo *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000358 /*
359 Search for configure tag.
360 */
cristyf84a1932010-01-03 18:00:18 +0000361 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000362 ResetLinkedListIterator(configure_cache);
363 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy49d4d222014-03-16 00:37:58 +0000364 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
365 {
366 UnlockSemaphoreInfo(configure_semaphore);
367 return(p);
368 }
cristy3ed852e2009-09-05 21:47:34 +0000369 while (p != (const ConfigureInfo *) NULL)
370 {
371 if (LocaleCompare(name,p->name) == 0)
372 break;
cristy86e5ac92014-03-16 19:27:39 +0000373 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000374 }
375 if (p != (ConfigureInfo *) NULL)
cristy86e5ac92014-03-16 19:27:39 +0000376 (void) InsertValueInLinkedList(configure_cache,0,
377 RemoveElementByValueFromLinkedList(configure_cache,p));
cristyf84a1932010-01-03 18:00:18 +0000378 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000379 return(p);
380}
381
382/*
383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384% %
385% %
386% %
387% G e t C o n f i g u r e I n f o L i s t %
388% %
389% %
390% %
391%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
392%
393% GetConfigureInfoList() returns any configure options that match the
394% specified pattern.
395%
396% The format of the GetConfigureInfoList function is:
397%
398% const ConfigureInfo **GetConfigureInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000399% size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000400%
401% A description of each parameter follows:
402%
403% o pattern: Specifies a pointer to a text string containing a pattern.
404%
405% o number_options: This integer returns the number of configure options in
406% the list.
407%
408% o exception: return any errors or warnings in this structure.
409%
410*/
411
412#if defined(__cplusplus) || defined(c_plusplus)
413extern "C" {
414#endif
415
416static int ConfigureInfoCompare(const void *x,const void *y)
417{
418 const ConfigureInfo
419 **p,
420 **q;
421
422 p=(const ConfigureInfo **) x,
423 q=(const ConfigureInfo **) y;
424 if (LocaleCompare((*p)->path,(*q)->path) == 0)
425 return(LocaleCompare((*p)->name,(*q)->name));
426 return(LocaleCompare((*p)->path,(*q)->path));
427}
428
429#if defined(__cplusplus) || defined(c_plusplus)
430}
431#endif
432
433MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000434 size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000435{
436 const ConfigureInfo
437 **options;
438
Cristyf2dc1dd2020-12-28 13:59:26 -0500439 const ConfigureInfo
cristy3ed852e2009-09-05 21:47:34 +0000440 *p;
441
Cristyf2dc1dd2020-12-28 13:59:26 -0500442 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000443 i;
444
445 /*
446 Allocate configure list.
447 */
448 assert(pattern != (char *) NULL);
449 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000450 assert(number_options != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000451 *number_options=0;
452 p=GetConfigureInfo("*",exception);
453 if (p == (const ConfigureInfo *) NULL)
454 return((const ConfigureInfo **) NULL);
455 options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
cristy86e5ac92014-03-16 19:27:39 +0000456 GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
cristy3ed852e2009-09-05 21:47:34 +0000457 if (options == (const ConfigureInfo **) NULL)
458 return((const ConfigureInfo **) NULL);
459 /*
460 Generate configure list.
461 */
cristyf84a1932010-01-03 18:00:18 +0000462 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000463 ResetLinkedListIterator(configure_cache);
464 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000465 for (i=0; p != (const ConfigureInfo *) NULL; )
466 {
467 if ((p->stealth == MagickFalse) &&
468 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
469 options[i++]=p;
cristy86e5ac92014-03-16 19:27:39 +0000470 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000471 }
cristyf84a1932010-01-03 18:00:18 +0000472 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000473 qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
474 options[i]=(ConfigureInfo *) NULL;
cristybb503372010-05-27 20:51:26 +0000475 *number_options=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000476 return(options);
477}
478
479/*
480%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
481% %
482% %
483% %
484% G e t C o n f i g u r e L i s t %
485% %
486% %
487% %
488%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
489%
490% GetConfigureList() returns any configure options that match the specified
491% pattern.
492%
493% The format of the GetConfigureList function is:
494%
495% char **GetConfigureList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000496% size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000497%
498% A description of each parameter follows:
499%
500% o pattern: Specifies a pointer to a text string containing a pattern.
501%
502% o number_options: This integer returns the number of options in the list.
503%
504% o exception: return any errors or warnings in this structure.
505%
506*/
507
508#if defined(__cplusplus) || defined(c_plusplus)
509extern "C" {
510#endif
511
512static int ConfigureCompare(const void *x,const void *y)
513{
Cristyf2dc1dd2020-12-28 13:59:26 -0500514 char
cristy3ed852e2009-09-05 21:47:34 +0000515 **p,
516 **q;
517
518 p=(char **) x;
519 q=(char **) y;
520 return(LocaleCompare(*p,*q));
521}
522
523#if defined(__cplusplus) || defined(c_plusplus)
524}
525#endif
526
527MagickExport char **GetConfigureList(const char *pattern,
cristybb503372010-05-27 20:51:26 +0000528 size_t *number_options,ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +0000529{
530 char
531 **options;
532
Cristyf2dc1dd2020-12-28 13:59:26 -0500533 const ConfigureInfo
cristy3ed852e2009-09-05 21:47:34 +0000534 *p;
535
Cristyf2dc1dd2020-12-28 13:59:26 -0500536 ssize_t
cristy3ed852e2009-09-05 21:47:34 +0000537 i;
538
539 /*
540 Allocate configure list.
541 */
542 assert(pattern != (char *) NULL);
543 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
cristybb503372010-05-27 20:51:26 +0000544 assert(number_options != (size_t *) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000545 *number_options=0;
546 p=GetConfigureInfo("*",exception);
547 if (p == (const ConfigureInfo *) NULL)
548 return((char **) NULL);
cristy3ed852e2009-09-05 21:47:34 +0000549 options=(char **) AcquireQuantumMemory((size_t)
cristy86e5ac92014-03-16 19:27:39 +0000550 GetNumberOfElementsInLinkedList(configure_cache)+1UL,sizeof(*options));
cristy3ed852e2009-09-05 21:47:34 +0000551 if (options == (char **) NULL)
552 return((char **) NULL);
cristyf84a1932010-01-03 18:00:18 +0000553 LockSemaphoreInfo(configure_semaphore);
cristy86e5ac92014-03-16 19:27:39 +0000554 ResetLinkedListIterator(configure_cache);
555 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000556 for (i=0; p != (const ConfigureInfo *) NULL; )
557 {
558 if ((p->stealth == MagickFalse) &&
559 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
560 options[i++]=ConstantString(p->name);
cristy86e5ac92014-03-16 19:27:39 +0000561 p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_cache);
cristy3ed852e2009-09-05 21:47:34 +0000562 }
cristyf84a1932010-01-03 18:00:18 +0000563 UnlockSemaphoreInfo(configure_semaphore);
cristy3ed852e2009-09-05 21:47:34 +0000564 qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
565 options[i]=(char *) NULL;
cristybb503372010-05-27 20:51:26 +0000566 *number_options=(size_t) i;
cristy3ed852e2009-09-05 21:47:34 +0000567 return(options);
568}
569
570/*
571%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
572% %
573% %
574% %
575% G e t C o n f i g u r e O p t i o n %
576% %
577% %
578% %
579%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
580%
581% GetConfigureOption() returns the value associated with the configure option.
582%
583% The format of the GetConfigureOption method is:
584%
585% char *GetConfigureOption(const char *option)
586%
587% A description of each parameter follows:
588%
589% o configure_info: The configure info.
590%
591*/
592MagickExport char *GetConfigureOption(const char *option)
593{
594 const char
595 *value;
596
597 const ConfigureInfo
598 *configure_info;
599
600 ExceptionInfo
601 *exception;
602
603 assert(option != (const char *) NULL);
604 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
605 exception=AcquireExceptionInfo();
606 configure_info=GetConfigureInfo(option,exception);
607 exception=DestroyExceptionInfo(exception);
608 if (configure_info == (ConfigureInfo *) NULL)
609 return((char *) NULL);
610 value=GetConfigureValue(configure_info);
611 if ((value == (const char *) NULL) || (*value == '\0'))
612 return((char *) NULL);
613 return(ConstantString(value));
614}
615
616/*
617%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618% %
619% %
620% %
621% G e t C o n f i g u r e O p t i o n s %
622% %
623% %
624% %
625%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
626%
627% GetConfigureOptions() returns any Magick configuration options associated
628% with the specified filename.
629%
630% The format of the GetConfigureOptions method is:
631%
632% LinkedListInfo *GetConfigureOptions(const char *filename,
633% ExceptionInfo *exception)
634%
635% A description of each parameter follows:
636%
637% o filename: the configure file name.
638%
639% o exception: return any errors or warnings in this structure.
640%
641*/
642MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
643 ExceptionInfo *exception)
644{
645 char
cristy151b66d2015-04-15 10:50:31 +0000646 path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000647
648 const char
649 *element;
650
651 LinkedListInfo
652 *options,
653 *paths;
654
655 StringInfo
656 *xml;
657
658 assert(filename != (const char *) NULL);
659 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
660 assert(exception != (ExceptionInfo *) NULL);
cristy151b66d2015-04-15 10:50:31 +0000661 (void) CopyMagickString(path,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000662 /*
663 Load XML from configuration files to linked-list.
664 */
665 options=NewLinkedList(0);
666 paths=GetConfigurePaths(filename,exception);
667 if (paths != (LinkedListInfo *) NULL)
668 {
669 ResetLinkedListIterator(paths);
670 element=(const char *) GetNextValueInLinkedList(paths);
671 while (element != (const char *) NULL)
672 {
Cristyf4a35c32016-06-02 13:45:36 -0400673 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",element,
674 filename);
cristy3ed852e2009-09-05 21:47:34 +0000675 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
676 "Searching for configure file: \"%s\"",path);
677 xml=ConfigureFileToStringInfo(path);
678 if (xml != (StringInfo *) NULL)
679 (void) AppendValueToLinkedList(options,xml);
680 element=(const char *) GetNextValueInLinkedList(paths);
681 }
682 paths=DestroyLinkedList(paths,RelinquishMagickMemory);
683 }
cristy0157aea2010-04-24 21:12:18 +0000684#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy7e247522011-11-29 14:59:23 +0000685 if (GetNumberOfElementsInLinkedList(options) == 0)
686 {
687 char
688 *blob;
cristy3ed852e2009-09-05 21:47:34 +0000689
cristy7e247522011-11-29 14:59:23 +0000690 blob=(char *) NTResourceToBlob(filename);
691 if (blob != (char *) NULL)
692 {
693 xml=AcquireStringInfo(0);
694 SetStringInfoLength(xml,strlen(blob)+1);
cristy52070b42012-02-19 22:03:21 +0000695 SetStringInfoDatum(xml,(unsigned char *) blob);
cristy7e247522011-11-29 14:59:23 +0000696 SetStringInfoPath(xml,filename);
697 (void) AppendValueToLinkedList(options,xml);
698 }
699 }
cristy3ed852e2009-09-05 21:47:34 +0000700#endif
701 if (GetNumberOfElementsInLinkedList(options) == 0)
702 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
cristyefe601c2013-01-05 17:51:12 +0000703 "UnableToOpenConfigureFile","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +0000704 ResetLinkedListIterator(options);
705 return(options);
706}
707
708/*
709%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
710% %
711% %
712% %
713% G e t C o n f i g u r e P a t h s %
714% %
715% %
716% %
717%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
718%
719% GetConfigurePaths() returns any Magick configuration paths associated
720% with the specified filename.
721%
722% The format of the GetConfigurePaths method is:
723%
724% LinkedListInfo *GetConfigurePaths(const char *filename,
725% ExceptionInfo *exception)
726%
727% A description of each parameter follows:
728%
729% o filename: the configure file name.
730%
731% o exception: return any errors or warnings in this structure.
732%
733*/
734MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
735 ExceptionInfo *exception)
736{
cristy7e247522011-11-29 14:59:23 +0000737#define RegistryKey "ConfigurePath"
cristy6c28ec02011-10-28 11:37:57 +0000738#define MagickCoreDLL "CORE_RL_MagickCore_.dll"
739#define MagickCoreDebugDLL "CORE_DB_MagickCore_.dll"
740
cristy3ed852e2009-09-05 21:47:34 +0000741 char
cristy151b66d2015-04-15 10:50:31 +0000742 path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000743
744 LinkedListInfo
745 *paths;
746
747 assert(filename != (const char *) NULL);
748 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
749 assert(exception != (ExceptionInfo *) NULL);
cristy151b66d2015-04-15 10:50:31 +0000750 (void) CopyMagickString(path,filename,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000751 paths=NewLinkedList(0);
752 {
753 char
754 *configure_path;
755
756 /*
757 Search $MAGICK_CONFIGURE_PATH.
758 */
759 configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
760 if (configure_path != (char *) NULL)
761 {
Cristyf2dc1dd2020-12-28 13:59:26 -0500762 char
cristy3ed852e2009-09-05 21:47:34 +0000763 *p,
764 *q;
765
766 for (p=configure_path-1; p != (char *) NULL; )
767 {
cristy151b66d2015-04-15 10:50:31 +0000768 (void) CopyMagickString(path,p+1,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000769 q=strchr(path,DirectoryListSeparator);
770 if (q != (char *) NULL)
771 *q='\0';
772 q=path+strlen(path)-1;
773 if ((q >= path) && (*q != *DirectorySeparator))
774 (void) ConcatenateMagickString(path,DirectorySeparator,
cristy151b66d2015-04-15 10:50:31 +0000775 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000776 (void) AppendValueToLinkedList(paths,ConstantString(path));
777 p=strchr(p+1,DirectoryListSeparator);
778 }
779 configure_path=DestroyString(configure_path);
780 }
781 }
782#if defined(MAGICKCORE_INSTALLED_SUPPORT)
cristy4f820712011-04-01 12:35:43 +0000783#if defined(MAGICKCORE_SHARE_PATH)
cristy6c28ec02011-10-28 11:37:57 +0000784 (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
cristy3ed852e2009-09-05 21:47:34 +0000785#endif
cristy670aa3c2011-11-03 00:54:00 +0000786#if defined(MAGICKCORE_SHAREARCH_PATH)
787 (void) AppendValueToLinkedList(paths,ConstantString(
788 MAGICKCORE_SHAREARCH_PATH));
789#endif
cristy3ed852e2009-09-05 21:47:34 +0000790#if defined(MAGICKCORE_CONFIGURE_PATH)
791 (void) AppendValueToLinkedList(paths,ConstantString(
792 MAGICKCORE_CONFIGURE_PATH));
793#endif
794#if defined(MAGICKCORE_DOCUMENTATION_PATH)
795 (void) AppendValueToLinkedList(paths,ConstantString(
796 MAGICKCORE_DOCUMENTATION_PATH));
797#endif
cristy4f820712011-04-01 12:35:43 +0000798#if defined(MAGICKCORE_WINDOWS_SUPPORT) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_PATH))
cristy3ed852e2009-09-05 21:47:34 +0000799 {
cristy3ed852e2009-09-05 21:47:34 +0000800 unsigned char
801 *key_value;
802
803 /*
804 Locate file via registry key.
805 */
cristy7e247522011-11-29 14:59:23 +0000806 key_value=NTRegistryKeyLookup(RegistryKey);
cristy3ed852e2009-09-05 21:47:34 +0000807 if (key_value != (unsigned char *) NULL)
808 {
Cristy9799a842015-10-04 19:44:36 -0400809 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",(char *)
810 key_value,DirectorySeparator);
cristy3ed852e2009-09-05 21:47:34 +0000811 (void) AppendValueToLinkedList(paths,ConstantString(path));
812 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
813 }
814 }
815#endif
816#else
817 {
818 char
819 *home;
820
821 /*
822 Search under MAGICK_HOME.
823 */
824 home=GetEnvironmentValue("MAGICK_HOME");
825 if (home != (char *) NULL)
826 {
Cristy9125cd52015-09-17 20:16:13 -0400827#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
cristy151b66d2015-04-15 10:50:31 +0000828 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",home,
cristy3ed852e2009-09-05 21:47:34 +0000829 DirectorySeparator);
830 (void) AppendValueToLinkedList(paths,ConstantString(path));
831#else
cristy151b66d2015-04-15 10:50:31 +0000832 (void) FormatLocaleString(path,MagickPathExtent,"%s/etc/%s/",home,
cristy3ed852e2009-09-05 21:47:34 +0000833 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
834 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000835 (void) FormatLocaleString(path,MagickPathExtent,"%s/share/%s/",home,
cristy4f820712011-04-01 12:35:43 +0000836 MAGICKCORE_SHARE_RELATIVE_PATH);
cristy3ed852e2009-09-05 21:47:34 +0000837 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000838 (void) FormatLocaleString(path,MagickPathExtent,"%s",
cristy780d58c2013-05-03 13:49:00 +0000839 MAGICKCORE_SHAREARCH_PATH);
840 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy3ed852e2009-09-05 21:47:34 +0000841#endif
842 home=DestroyString(home);
843 }
844 }
845 if (*GetClientPath() != '\0')
846 {
Cristy9125cd52015-09-17 20:16:13 -0400847#if !defined(MAGICKCORE_POSIX_SUPPORT) || defined( __VMS )
cristy151b66d2015-04-15 10:50:31 +0000848 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",GetClientPath(),
cristy3ed852e2009-09-05 21:47:34 +0000849 DirectorySeparator);
850 (void) AppendValueToLinkedList(paths,ConstantString(path));
851#else
852 char
cristy151b66d2015-04-15 10:50:31 +0000853 prefix[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000854
855 /*
856 Search based on executable directory if directory is known.
857 */
cristy151b66d2015-04-15 10:50:31 +0000858 (void) CopyMagickString(prefix,GetClientPath(),MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +0000859 ChopPathComponents(prefix,1);
cristy151b66d2015-04-15 10:50:31 +0000860 (void) FormatLocaleString(path,MagickPathExtent,"%s/etc/%s/",prefix,
cristy3ed852e2009-09-05 21:47:34 +0000861 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
862 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000863 (void) FormatLocaleString(path,MagickPathExtent,"%s/share/%s/",prefix,
cristy4f820712011-04-01 12:35:43 +0000864 MAGICKCORE_SHARE_RELATIVE_PATH);
865 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000866 (void) FormatLocaleString(path,MagickPathExtent,"%s",
cristy780d58c2013-05-03 13:49:00 +0000867 MAGICKCORE_SHAREARCH_PATH);
868 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy3ed852e2009-09-05 21:47:34 +0000869#endif
870 }
cristy51b1ac52010-10-30 02:27:14 +0000871 /*
872 Search current directory.
873 */
874 (void) AppendValueToLinkedList(paths,ConstantString(""));
cristy3ed852e2009-09-05 21:47:34 +0000875#endif
876 {
877 char
878 *home;
879
Cristy9799a842015-10-04 19:44:36 -0400880 home=GetEnvironmentValue("XDG_CONFIG_HOME");
Dirk Lemstradfb9ecb2019-04-12 22:24:33 +0200881#if defined(MAGICKCORE_WINDOWS_SUPPORT) || defined(__MINGW32__)
Cristy1dd96da2015-10-06 07:52:01 -0400882 if (home == (char *) NULL)
883 home=GetEnvironmentValue("LOCALAPPDATA");
884 if (home == (char *) NULL)
885 home=GetEnvironmentValue("APPDATA");
886 if (home == (char *) NULL)
887 home=GetEnvironmentValue("USERPROFILE");
Dirk Lemstradfb9ecb2019-04-12 22:24:33 +0200888#endif
Cristy9799a842015-10-04 19:44:36 -0400889 if (home != (char *) NULL)
Cristy1dd96da2015-10-06 07:52:01 -0400890 {
Cristy9799a842015-10-04 19:44:36 -0400891 /*
892 Search $XDG_CONFIG_HOME/ImageMagick.
893 */
Cristya8b2bb22016-03-25 10:39:01 -0400894 (void) FormatLocaleString(path,MagickPathExtent,"%s%sImageMagick%s",
dirka4bed212015-11-09 13:02:16 +0100895 home,DirectorySeparator,DirectorySeparator);
Cristy9799a842015-10-04 19:44:36 -0400896 (void) AppendValueToLinkedList(paths,ConstantString(path));
897 home=DestroyString(home);
898 }
cristy3ed852e2009-09-05 21:47:34 +0000899 home=GetEnvironmentValue("HOME");
cristy3ed852e2009-09-05 21:47:34 +0000900 if (home != (char *) NULL)
901 {
902 /*
cristy9f3b4fc2014-02-08 14:56:20 +0000903 Search $HOME/.config/ImageMagick.
cristy3ed852e2009-09-05 21:47:34 +0000904 */
cristy151b66d2015-04-15 10:50:31 +0000905 (void) FormatLocaleString(path,MagickPathExtent,
cristy9f3b4fc2014-02-08 14:56:20 +0000906 "%s%s.config%sImageMagick%s",home,DirectorySeparator,
cristy3ed852e2009-09-05 21:47:34 +0000907 DirectorySeparator,DirectorySeparator);
908 (void) AppendValueToLinkedList(paths,ConstantString(path));
909 home=DestroyString(home);
910 }
911 }
cristy0157aea2010-04-24 21:12:18 +0000912#if defined(MAGICKCORE_WINDOWS_SUPPORT)
cristy3ed852e2009-09-05 21:47:34 +0000913 {
914 char
cristy151b66d2015-04-15 10:50:31 +0000915 module_path[MagickPathExtent];
cristy3ed852e2009-09-05 21:47:34 +0000916
cristy6c28ec02011-10-28 11:37:57 +0000917 if ((NTGetModulePath(MagickCoreDLL,module_path) != MagickFalse) ||
918 (NTGetModulePath(MagickCoreDebugDLL,module_path) != MagickFalse))
cristy3ed852e2009-09-05 21:47:34 +0000919 {
cristy7e247522011-11-29 14:59:23 +0000920 unsigned char
921 *key_value;
cristy3ed852e2009-09-05 21:47:34 +0000922
923 /*
924 Search module path.
925 */
cristy151b66d2015-04-15 10:50:31 +0000926 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000927 DirectorySeparator);
cristy7e247522011-11-29 14:59:23 +0000928 key_value=NTRegistryKeyLookup(RegistryKey);
929 if (key_value == (unsigned char *) NULL)
930 (void) AppendValueToLinkedList(paths,ConstantString(path));
931 else
932 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
cristy3ed852e2009-09-05 21:47:34 +0000933 }
934 if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
935 {
936 /*
937 Search PerlMagick module path.
938 */
cristy151b66d2015-04-15 10:50:31 +0000939 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000940 DirectorySeparator);
941 (void) AppendValueToLinkedList(paths,ConstantString(path));
cristy151b66d2015-04-15 10:50:31 +0000942 (void) FormatLocaleString(path,MagickPathExtent,"%s%s",module_path,
cristy3ed852e2009-09-05 21:47:34 +0000943 "\\inc\\lib\\auto\\Image\\Magick\\");
944 (void) AppendValueToLinkedList(paths,ConstantString(path));
945 }
946 }
947#endif
Cristy76039492018-01-21 14:49:02 -0500948 if (GetNumberOfElementsInLinkedList(paths) == 0)
949 (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
950 "no configuration paths found","`%s'",filename);
cristy3ed852e2009-09-05 21:47:34 +0000951 return(paths);
952}
953
954/*
955%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
956% %
957% %
958% %
959% G e t C o n f i g u r e V a l u e %
960% %
961% %
962% %
963%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
964%
965% GetConfigureValue() returns the value associated with the configure info.
966%
967% The format of the GetConfigureValue method is:
968%
969% const char *GetConfigureValue(const ConfigureInfo *configure_info)
970%
971% A description of each parameter follows:
972%
973% o configure_info: The configure info.
974%
975*/
976MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
977{
978 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
979 assert(configure_info != (ConfigureInfo *) NULL);
cristye1c94d92015-06-28 12:16:33 +0000980 assert(configure_info->signature == MagickCoreSignature);
cristy3ed852e2009-09-05 21:47:34 +0000981 return(configure_info->value);
982}
983
984/*
985%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
986% %
987% %
988% %
cristy86e5ac92014-03-16 19:27:39 +0000989+ 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 +0000990% %
991% %
992% %
993%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
994%
cristy86e5ac92014-03-16 19:27:39 +0000995% IsConfigureCacheInstantiated() determines if the configure list is
cristy904e5912014-03-15 19:53:14 +0000996% instantiated. If not, it instantiates the list and returns it.
cristy3ed852e2009-09-05 21:47:34 +0000997%
cristy904e5912014-03-15 19:53:14 +0000998% The format of the IsConfigureInstantiated method is:
cristy3ed852e2009-09-05 21:47:34 +0000999%
cristy86e5ac92014-03-16 19:27:39 +00001000% MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001001%
1002% A description of each parameter follows.
1003%
1004% o exception: return any errors or warnings in this structure.
1005%
1006*/
cristy86e5ac92014-03-16 19:27:39 +00001007static MagickBooleanType IsConfigureCacheInstantiated(ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001008{
cristy86e5ac92014-03-16 19:27:39 +00001009 if (configure_cache == (LinkedListInfo *) NULL)
1010 {
1011 if (configure_semaphore == (SemaphoreInfo *) NULL)
1012 ActivateSemaphoreInfo(&configure_semaphore);
1013 LockSemaphoreInfo(configure_semaphore);
1014 if (configure_cache == (LinkedListInfo *) NULL)
1015 configure_cache=AcquireConfigureCache(ConfigureFilename,exception);
1016 UnlockSemaphoreInfo(configure_semaphore);
1017 }
1018 return(configure_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001019}
1020
1021/*
1022%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1023% %
1024% %
1025% %
cristy3ed852e2009-09-05 21:47:34 +00001026% L i s t C o n f i g u r e I n f o %
1027% %
1028% %
1029% %
1030%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1031%
1032% ListConfigureInfo() lists the configure info to a file.
1033%
1034% The format of the ListConfigureInfo method is:
1035%
1036% MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
1037%
1038% A description of each parameter follows.
1039%
1040% o file: An pointer to a FILE.
1041%
1042% o exception: return any errors or warnings in this structure.
1043%
1044*/
1045MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
1046 ExceptionInfo *exception)
1047{
1048 const char
1049 *name,
1050 *path,
1051 *value;
1052
1053 const ConfigureInfo
1054 **configure_info;
1055
Cristyf2dc1dd2020-12-28 13:59:26 -05001056 ssize_t
cristy3ed852e2009-09-05 21:47:34 +00001057 i;
1058
cristybb503372010-05-27 20:51:26 +00001059 size_t
cristy3ed852e2009-09-05 21:47:34 +00001060 number_options;
1061
cristy9d314ff2011-03-09 01:30:28 +00001062 ssize_t
1063 j;
1064
cristy3ed852e2009-09-05 21:47:34 +00001065 if (file == (const FILE *) NULL)
1066 file=stdout;
1067 configure_info=GetConfigureInfoList("*",&number_options,exception);
1068 if (configure_info == (const ConfigureInfo **) NULL)
1069 return(MagickFalse);
1070 path=(const char *) NULL;
cristybb503372010-05-27 20:51:26 +00001071 for (i=0; i < (ssize_t) number_options; i++)
cristy3ed852e2009-09-05 21:47:34 +00001072 {
1073 if (configure_info[i]->stealth != MagickFalse)
1074 continue;
1075 if ((path == (const char *) NULL) ||
1076 (LocaleCompare(path,configure_info[i]->path) != 0))
1077 {
1078 if (configure_info[i]->path != (char *) NULL)
cristy1e604812011-05-19 18:07:50 +00001079 (void) FormatLocaleFile(file,"\nPath: %s\n\n",
1080 configure_info[i]->path);
Cristy1af75e52018-11-15 07:59:32 -05001081 (void) FormatLocaleFile(file,"Name Value\n");
cristy1e604812011-05-19 18:07:50 +00001082 (void) FormatLocaleFile(file,
1083 "-------------------------------------------------"
cristy3ed852e2009-09-05 21:47:34 +00001084 "------------------------------\n");
1085 }
1086 path=configure_info[i]->path;
1087 name="unknown";
1088 if (configure_info[i]->name != (char *) NULL)
1089 name=configure_info[i]->name;
cristyb51dff52011-05-19 16:55:47 +00001090 (void) FormatLocaleFile(file,"%s",name);
Cristy1af75e52018-11-15 07:59:32 -05001091 for (j=(ssize_t) strlen(name); j <= 20; j++)
cristyb51dff52011-05-19 16:55:47 +00001092 (void) FormatLocaleFile(file," ");
1093 (void) FormatLocaleFile(file," ");
cristy3ed852e2009-09-05 21:47:34 +00001094 value="unknown";
1095 if (configure_info[i]->value != (char *) NULL)
1096 value=configure_info[i]->value;
cristyb51dff52011-05-19 16:55:47 +00001097 (void) FormatLocaleFile(file,"%s",value);
1098 (void) FormatLocaleFile(file,"\n");
cristy3ed852e2009-09-05 21:47:34 +00001099 }
1100 (void) fflush(file);
cristycd2cd182014-03-18 12:10:55 +00001101 configure_info=(const ConfigureInfo **) RelinquishMagickMemory((void *)
1102 configure_info);
cristy3ed852e2009-09-05 21:47:34 +00001103 return(MagickTrue);
1104}
1105
Cristyd1e7b762019-12-07 19:00:20 -05001106#if !MAGICKCORE_ZERO_CONFIGURATION_SUPPORT
cristy3ed852e2009-09-05 21:47:34 +00001107/*
1108%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1109% %
1110% %
1111% %
dirkfc0f1242016-03-26 00:36:39 +01001112+ L o a d C o n f i g u r e C a c h e %
cristy3ed852e2009-09-05 21:47:34 +00001113% %
1114% %
1115% %
1116%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1117%
cristy86e5ac92014-03-16 19:27:39 +00001118% LoadConfigureCache() loads the configure configurations which provides a
cristy3ed852e2009-09-05 21:47:34 +00001119% mapping between configure attributes and a configure name.
1120%
cristy86e5ac92014-03-16 19:27:39 +00001121% The format of the LoadConfigureCache method is:
cristy3ed852e2009-09-05 21:47:34 +00001122%
dirkb18d8642016-07-17 19:32:43 +02001123% MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
cristy0d8101e2014-04-10 00:13:05 +00001124% const char *xml,const char *filename,const size_t depth,
1125% ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001126%
1127% A description of each parameter follows:
1128%
1129% o xml: The configure list in XML format.
1130%
1131% o filename: The configure list filename.
1132%
1133% o depth: depth of <include /> statements.
1134%
1135% o exception: return any errors or warnings in this structure.
1136%
1137*/
dirkb18d8642016-07-17 19:32:43 +02001138static MagickBooleanType LoadConfigureCache(LinkedListInfo *cache,
cristycd2cd182014-03-18 12:10:55 +00001139 const char *xml,const char *filename,const size_t depth,
1140 ExceptionInfo *exception)
cristy3ed852e2009-09-05 21:47:34 +00001141{
1142 char
cristy151b66d2015-04-15 10:50:31 +00001143 keyword[MagickPathExtent],
cristy3ed852e2009-09-05 21:47:34 +00001144 *token;
1145
1146 ConfigureInfo
1147 *configure_info;
1148
1149 const char
1150 *q;
1151
cristy759ba912014-06-26 11:59:43 +00001152 MagickStatusType
cristy3ed852e2009-09-05 21:47:34 +00001153 status;
1154
dirkfc0f1242016-03-26 00:36:39 +01001155 size_t
1156 extent;
1157
cristy3ed852e2009-09-05 21:47:34 +00001158 /*
1159 Load the configure map file.
1160 */
1161 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
1162 "Loading configure file \"%s\" ...",filename);
cristy3ed852e2009-09-05 21:47:34 +00001163 status=MagickTrue;
1164 configure_info=(ConfigureInfo *) NULL;
dirkfc0f1242016-03-26 00:36:39 +01001165 token=AcquireString(xml);
1166 extent=strlen(token)+MagickPathExtent;
cristy3ed852e2009-09-05 21:47:34 +00001167 for (q=(char *) xml; *q != '\0'; )
1168 {
1169 /*
1170 Interpret XML.
1171 */
Cristy448fd182019-07-27 16:26:38 -04001172 (void) GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001173 if (*token == '\0')
1174 break;
cristy151b66d2015-04-15 10:50:31 +00001175 (void) CopyMagickString(keyword,token,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001176 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1177 {
1178 /*
1179 Doctype element.
1180 */
1181 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
Cristy448fd182019-07-27 16:26:38 -04001182 (void) GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001183 continue;
1184 }
1185 if (LocaleNCompare(keyword,"<!--",4) == 0)
1186 {
1187 /*
1188 Comment element.
1189 */
1190 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
Cristy448fd182019-07-27 16:26:38 -04001191 (void) GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001192 continue;
1193 }
1194 if (LocaleCompare(keyword,"<include") == 0)
1195 {
1196 /*
1197 Include element.
1198 */
1199 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1200 {
cristy151b66d2015-04-15 10:50:31 +00001201 (void) CopyMagickString(keyword,token,MagickPathExtent);
Cristy448fd182019-07-27 16:26:38 -04001202 (void) GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001203 if (*token != '=')
1204 continue;
Cristy448fd182019-07-27 16:26:38 -04001205 (void) GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001206 if (LocaleCompare(keyword,"file") == 0)
1207 {
Cristy8a4029f2018-02-05 07:35:07 -05001208 if (depth > MagickMaxRecursionDepth)
cristy3ed852e2009-09-05 21:47:34 +00001209 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001210 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
cristy3ed852e2009-09-05 21:47:34 +00001211 else
1212 {
1213 char
cristy151b66d2015-04-15 10:50:31 +00001214 path[MagickPathExtent],
dirkb81f0ab2015-10-20 23:01:53 +02001215 *file_xml;
cristy3ed852e2009-09-05 21:47:34 +00001216
1217 GetPathComponent(filename,HeadPath,path);
1218 if (*path != '\0')
1219 (void) ConcatenateMagickString(path,DirectorySeparator,
cristy151b66d2015-04-15 10:50:31 +00001220 MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001221 if (*token == *DirectorySeparator)
cristy151b66d2015-04-15 10:50:31 +00001222 (void) CopyMagickString(path,token,MagickPathExtent);
cristy3ed852e2009-09-05 21:47:34 +00001223 else
cristy151b66d2015-04-15 10:50:31 +00001224 (void) ConcatenateMagickString(path,token,MagickPathExtent);
dirkb81f0ab2015-10-20 23:01:53 +02001225 file_xml=FileToXML(path,~0UL);
1226 if (file_xml != (char *) NULL)
cristy3ed852e2009-09-05 21:47:34 +00001227 {
dirkb18d8642016-07-17 19:32:43 +02001228 status&=LoadConfigureCache(cache,file_xml,path,depth+1,
1229 exception);
dirkb81f0ab2015-10-20 23:01:53 +02001230 file_xml=DestroyString(file_xml);
cristy3ed852e2009-09-05 21:47:34 +00001231 }
1232 }
1233 }
1234 }
1235 continue;
1236 }
1237 if (LocaleCompare(keyword,"<configure") == 0)
1238 {
1239 /*
1240 Configure element.
1241 */
Dirk Lemstra06344a02017-10-15 10:10:01 +02001242 configure_info=(ConfigureInfo *) AcquireCriticalMemory(
cristy3ed852e2009-09-05 21:47:34 +00001243 sizeof(*configure_info));
Cristy81bfff22018-03-10 07:58:31 -05001244 (void) memset(configure_info,0,sizeof(*configure_info));
cristy3ed852e2009-09-05 21:47:34 +00001245 configure_info->path=ConstantString(filename);
cristy54a531d2009-10-21 17:58:01 +00001246 configure_info->exempt=MagickFalse;
cristye1c94d92015-06-28 12:16:33 +00001247 configure_info->signature=MagickCoreSignature;
cristy3ed852e2009-09-05 21:47:34 +00001248 continue;
1249 }
1250 if (configure_info == (ConfigureInfo *) NULL)
1251 continue;
Cristyfed111e2017-01-09 07:22:16 -05001252 if ((LocaleCompare(keyword,"/>") == 0) ||
1253 (LocaleCompare(keyword,"</policy>") == 0))
cristy3ed852e2009-09-05 21:47:34 +00001254 {
dirkb18d8642016-07-17 19:32:43 +02001255 status=AppendValueToLinkedList(cache,configure_info);
cristy3ed852e2009-09-05 21:47:34 +00001256 if (status == MagickFalse)
1257 (void) ThrowMagickException(exception,GetMagickModule(),
cristyefe601c2013-01-05 17:51:12 +00001258 ResourceLimitError,"MemoryAllocationFailed","`%s'",
cristy3ed852e2009-09-05 21:47:34 +00001259 configure_info->name);
1260 configure_info=(ConfigureInfo *) NULL;
cristyd45122f2014-01-14 23:46:16 +00001261 continue;
cristy3ed852e2009-09-05 21:47:34 +00001262 }
1263 /*
1264 Parse configure element.
1265 */
Cristy448fd182019-07-27 16:26:38 -04001266 (void) GetNextToken(q,(const char **) NULL,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001267 if (*token != '=')
1268 continue;
Cristy448fd182019-07-27 16:26:38 -04001269 (void) GetNextToken(q,&q,extent,token);
1270 (void) GetNextToken(q,&q,extent,token);
cristy3ed852e2009-09-05 21:47:34 +00001271 switch (*keyword)
1272 {
1273 case 'N':
1274 case 'n':
1275 {
1276 if (LocaleCompare((char *) keyword,"name") == 0)
1277 {
1278 configure_info->name=ConstantString(token);
1279 break;
1280 }
1281 break;
1282 }
1283 case 'S':
1284 case 's':
1285 {
1286 if (LocaleCompare((char *) keyword,"stealth") == 0)
1287 {
anthony6f201312012-03-30 04:08:15 +00001288 configure_info->stealth=IsStringTrue(token);
cristy3ed852e2009-09-05 21:47:34 +00001289 break;
1290 }
1291 break;
1292 }
1293 case 'V':
1294 case 'v':
1295 {
1296 if (LocaleCompare((char *) keyword,"value") == 0)
1297 {
1298 configure_info->value=ConstantString(token);
1299 break;
1300 }
1301 break;
1302 }
1303 default:
1304 break;
1305 }
1306 }
1307 token=(char *) RelinquishMagickMemory(token);
cristy759ba912014-06-26 11:59:43 +00001308 return(status != 0 ? MagickTrue : MagickFalse);
cristy3ed852e2009-09-05 21:47:34 +00001309}
Cristyd1e7b762019-12-07 19:00:20 -05001310#endif