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