Coverage Report

Created: 2026-05-16 07:22

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