root / ImageMagick / trunk / magick / configure.c

Revision 11753, 39.1 kB (checked in by cristy, 5 weeks ago)
Line 
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%                     ImageMagick Image Configure Methods                     %
14%                                                                             %
15%                              Software Design                                %
16%                                John Cristy                                  %
17%                                 July 2003                                   %
18%                                                                             %
19%                                                                             %
20%  Copyright 1999-2008 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
39/*
40  Include declarations.
41*/
42#include "magick/studio.h"
43#include "magick/blob.h"
44#include "magick/client.h"
45#include "magick/configure.h"
46#include "magick/exception.h"
47#include "magick/exception-private.h"
48#include "magick/hashmap.h"
49#include "magick/log.h"
50#include "magick/memory_.h"
51#include "magick/semaphore.h"
52#include "magick/string_.h"
53#include "magick/token.h"
54#include "magick/utility.h"
55#include "magick/xml-tree.h"
56
57/*
58  Define declarations.
59*/
60#define ConfigureFilename  "configure.xml"
61
62/*
63  Static declarations.
64*/
65static const char
66  *ConfigureMap = (char *)
67    "<?xml version=\"1.0\"?>"
68    "<configuremap>"
69    "  <configure stealth=\"True\" />"
70    "</configuremap>";
71
72static LinkedListInfo
73  *configure_list = (LinkedListInfo *) NULL;
74
75static SemaphoreInfo
76  *configure_semaphore = (SemaphoreInfo *) NULL;
77
78static volatile MagickBooleanType
79  instantiate_configure = MagickFalse;
80
81/*
82  Forward declarations.
83*/
84static MagickBooleanType
85  InitializeConfigureList(ExceptionInfo *),
86  LoadConfigureLists(const char *,ExceptionInfo *);
87
88/*
89%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
90%                                                                             %
91%                                                                             %
92%                                                                             %
93+   D e s t r o y C o n f i g u r e L i s t                                   %
94%                                                                             %
95%                                                                             %
96%                                                                             %
97%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
98%
99%  DestroyConfigureList() deallocates memory associated with the configure list.
100%
101%  The format of the DestroyConfigureList method is:
102%
103%      DestroyConfigureList(void)
104%
105*/
106
107static void *DestroyConfigureElement(void *configure_info)
108{
109  register ConfigureInfo
110    *p;
111
112  p=(ConfigureInfo *) configure_info;
113  if (p->path != (char *) NULL)
114    p->path=DestroyString(p->path);
115  if (p->name != (char *) NULL)
116    p->name=DestroyString(p->name);
117  if (p->value != (char *) NULL)
118    p->value=DestroyString(p->value);
119  p=(ConfigureInfo *) RelinquishMagickMemory(p);
120  return((void *) NULL);
121}
122
123MagickExport void DestroyConfigureList(void)
124{
125  AcquireSemaphoreInfo(&configure_semaphore);
126  if (configure_list != (LinkedListInfo *) NULL)
127    configure_list=DestroyLinkedList(configure_list,DestroyConfigureElement);
128  configure_list=(LinkedListInfo *) NULL;
129  instantiate_configure=MagickFalse;
130  RelinquishSemaphoreInfo(configure_semaphore);
131  DestroySemaphoreInfo(&configure_semaphore);
132}
133
134/*
135%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
136%                                                                             %
137%                                                                             %
138%                                                                             %
139%   D e s t r o y C o n f i g u r e O p t i o n s                             %
140%                                                                             %
141%                                                                             %
142%                                                                             %
143%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
144%
145%  DestroyConfigureOptions() releases memory associated with an configure
146%  options.
147%
148%  The format of the DestroyProfiles method is:
149%
150%      LinkedListInfo *DestroyConfigureOptions(Image *image)
151%
152%  A description of each parameter follows:
153%
154%    o image: the image.
155%
156*/
157
158static void *DestroyOptions(void *option)
159{
160  return(DestroyStringInfo((StringInfo *) option));
161}
162
163MagickExport LinkedListInfo *DestroyConfigureOptions(LinkedListInfo *options)
164{
165  assert(options != (LinkedListInfo *) NULL);
166  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
167  return(DestroyLinkedList(options,DestroyOptions));
168}
169
170/*
171%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
172%                                                                             %
173%                                                                             %
174%                                                                             %
175+   G e t C o n f i g u r e I n f o                                           %
176%                                                                             %
177%                                                                             %
178%                                                                             %
179%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
180%
181%  GetConfigureInfo() searches the configure list for the specified name and if
182%  found returns attributes for that element.
183%
184%  The format of the GetConfigureInfo method is:
185%
186%      const ConfigureInfo *GetConfigureInfo(const char *name,
187%        ExceptionInfo *exception)
188%
189%  A description of each parameter follows:
190%
191%    o configure_info: GetConfigureInfo() searches the configure list for the
192%      specified name and if found returns attributes for that element.
193%
194%    o name: the configure name.
195%
196%    o exception: Return any errors or warnings in this structure.
197%
198*/
199MagickExport const ConfigureInfo *GetConfigureInfo(const char *name,
200  ExceptionInfo *exception)
201{
202  register const ConfigureInfo
203    *p;
204
205  assert(exception != (ExceptionInfo *) NULL);
206  if ((configure_list == (LinkedListInfo *) NULL) ||
207      (instantiate_configure == MagickFalse))
208    if (InitializeConfigureList(exception) == MagickFalse)
209      return((const ConfigureInfo *) NULL);
210  if ((configure_list == (LinkedListInfo *) NULL) ||
211      (IsLinkedListEmpty(configure_list) != MagickFalse))
212    return((const ConfigureInfo *) NULL);
213  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
214    return((const ConfigureInfo *) GetValueFromLinkedList(configure_list,0));
215  /*
216    Search for named configure.
217  */
218  AcquireSemaphoreInfo(&configure_semaphore);
219  ResetLinkedListIterator(configure_list);
220  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
221  while (p != (const ConfigureInfo *) NULL)
222  {
223    if (LocaleCompare(name,p->name) == 0)
224      break;
225    p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
226  }
227  if (p == (ConfigureInfo *) NULL)
228    (void) ThrowMagickException(exception,GetMagickModule(),OptionWarning,
229      "NoSuchElement","`%s'",name);
230  RelinquishSemaphoreInfo(configure_semaphore);
231  return(p);
232}
233
234/*
235%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
236%                                                                             %
237%                                                                             %
238%                                                                             %
239%   G e t C o n f i g u r e I n f o L i s t                                   %
240%                                                                             %
241%                                                                             %
242%                                                                             %
243%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
244%
245%  GetConfigureInfoList() returns any configure options that match the
246%  specified pattern.
247%
248%  The format of the GetConfigureInfoList function is:
249%
250%      const ConfigureInfo **GetConfigureInfoList(const char *pattern,
251%        unsigned long *number_options,ExceptionInfo *exception)
252%
253%  A description of each parameter follows:
254%
255%    o pattern: Specifies a pointer to a text string containing a pattern.
256%
257%    o number_options:  This integer returns the number of configure options in
258%    the list.
259%
260%    o exception: Return any errors or warnings in this structure.
261%
262*/
263
264#if defined(__cplusplus) || defined(c_plusplus)
265extern "C" {
266#endif
267
268static int ConfigureInfoCompare(const void *x,const void *y)
269{
270  const ConfigureInfo
271    **p,
272    **q;
273
274  p=(const ConfigureInfo **) x,
275  q=(const ConfigureInfo **) y;
276  if (LocaleCompare((*p)->path,(*q)->path) == 0)
277    return(LocaleCompare((*p)->name,(*q)->name));
278  return(LocaleCompare((*p)->path,(*q)->path));
279}
280
281#if defined(__cplusplus) || defined(c_plusplus)
282}
283#endif
284
285MagickExport const ConfigureInfo **GetConfigureInfoList(const char *pattern,
286  unsigned long *number_options,ExceptionInfo *exception)
287{
288  const ConfigureInfo
289    **options;
290
291  register const ConfigureInfo
292    *p;
293
294  register long
295    i;
296
297  /*
298    Allocate configure list.
299  */
300  assert(pattern != (char *) NULL);
301  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
302  assert(number_options != (unsigned long *) NULL);
303  *number_options=0;
304  p=GetConfigureInfo("*",exception);
305  if (p == (const ConfigureInfo *) NULL)
306    return((const ConfigureInfo **) NULL);
307  options=(const ConfigureInfo **) AcquireQuantumMemory((size_t)
308    GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
309  if (options == (const ConfigureInfo **) NULL)
310    return((const ConfigureInfo **) NULL);
311  /*
312    Generate configure list.
313  */
314  AcquireSemaphoreInfo(&configure_semaphore);
315  ResetLinkedListIterator(configure_list);
316  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
317  for (i=0; p != (const ConfigureInfo *) NULL; )
318  {
319    if ((p->stealth == MagickFalse) &&
320        (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
321      options[i++]=p;
322    p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
323  }
324  RelinquishSemaphoreInfo(configure_semaphore);
325  qsort((void *) options,(size_t) i,sizeof(*options),ConfigureInfoCompare);
326  options[i]=(ConfigureInfo *) NULL;
327  *number_options=(unsigned long) i;
328  return(options);
329}
330
331/*
332%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
333%                                                                             %
334%                                                                             %
335%                                                                             %
336%   G e t C o n f i g u r e L i s t                                           %
337%                                                                             %
338%                                                                             %
339%                                                                             %
340%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
341%
342%  GetConfigureList() returns any configure options that match the specified
343%  pattern.
344%
345%  The format of the GetConfigureList function is:
346%
347%      char **GetConfigureList(const char *pattern,
348%        unsigned long *number_options,ExceptionInfo *exception)
349%
350%  A description of each parameter follows:
351%
352%    o pattern: Specifies a pointer to a text string containing a pattern.
353%
354%    o number_options:  This integer returns the number of options in the list.
355%
356%    o exception: Return any errors or warnings in this structure.
357%
358*/
359
360#if defined(__cplusplus) || defined(c_plusplus)
361extern "C" {
362#endif
363
364static int ConfigureCompare(const void *x,const void *y)
365{
366  register char
367    **p,
368    **q;
369
370  p=(char **) x;
371  q=(char **) y;
372  return(LocaleCompare(*p,*q));
373}
374
375#if defined(__cplusplus) || defined(c_plusplus)
376}
377#endif
378
379MagickExport char **GetConfigureList(const char *pattern,
380  unsigned long *number_options,ExceptionInfo *exception)
381{
382  char
383    **options;
384
385  register const ConfigureInfo
386    *p;
387
388  register long
389    i;
390
391  /*
392    Allocate configure list.
393  */
394  assert(pattern != (char *) NULL);
395  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
396  assert(number_options != (unsigned long *) NULL);
397  *number_options=0;
398  p=GetConfigureInfo("*",exception);
399  if (p == (const ConfigureInfo *) NULL)
400    return((char **) NULL);
401  AcquireSemaphoreInfo(&configure_semaphore);
402  RelinquishSemaphoreInfo(configure_semaphore);
403  options=(char **) AcquireQuantumMemory((size_t)
404    GetNumberOfElementsInLinkedList(configure_list)+1UL,sizeof(*options));
405  if (options == (char **) NULL)
406    return((char **) NULL);
407  AcquireSemaphoreInfo(&configure_semaphore);
408  ResetLinkedListIterator(configure_list);
409  p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
410  for (i=0; p != (const ConfigureInfo *) NULL; )
411  {
412    if ((p->stealth == MagickFalse) &&
413        (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
414      options[i++]=ConstantString(p->name);
415    p=(const ConfigureInfo *) GetNextValueInLinkedList(configure_list);
416  }
417  RelinquishSemaphoreInfo(configure_semaphore);
418  qsort((void *) options,(size_t) i,sizeof(*options),ConfigureCompare);
419  options[i]=(char *) NULL;
420  *number_options=(unsigned long) i;
421  return(options);
422}
423
424/*
425%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
426%                                                                             %
427%                                                                             %
428%                                                                             %
429%   G e t C o n f i g u r e O p t i o n                                       %
430%                                                                             %
431%                                                                             %
432%                                                                             %
433%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
434%
435%  GetConfigureOption() returns the value associated with the configure option.
436%
437%  The format of the GetConfigureOption method is:
438%
439%      char *GetConfigureOption(const char *option)
440%
441%  A description of each parameter follows:
442%
443%    o configure_info:  The configure info.
444%
445*/
446MagickExport char *GetConfigureOption(const char *option)
447{
448  const char
449    *value;
450
451  const ConfigureInfo
452    *configure_info;
453
454  ExceptionInfo
455    *exception;
456
457  assert(option != (const char *) NULL);
458  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",option);
459  exception=AcquireExceptionInfo();
460  configure_info=GetConfigureInfo(option,exception);
461  exception=DestroyExceptionInfo(exception);
462  if (configure_info == (ConfigureInfo *) NULL)
463    return((char *) NULL);
464  value=GetConfigureValue(configure_info);
465  if ((value == (const char *) NULL) || (*value == '\0'))
466    return((char *) NULL);
467  return(ConstantString(value));
468}
469
470/*
471%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
472%                                                                             %
473%                                                                             %
474%                                                                             %
475%  G e t C o n f i g u r e O p t i o n s                                      %
476%                                                                             %
477%                                                                             %
478%                                                                             %
479%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
480%
481%  GetConfigureOptions() returns any Magick configuration options associated
482%  with the specified filename.
483%
484%  The format of the GetConfigureOptions method is:
485%
486%      LinkedListInfo *GetConfigureOptions(const char *filename,
487%        ExceptionInfo *exception)
488%
489%  A description of each parameter follows:
490%
491%    o filename: the configure file name.
492%
493%    o exception: Return any errors or warnings in this structure.
494%
495*/
496MagickExport LinkedListInfo *GetConfigureOptions(const char *filename,
497  ExceptionInfo *exception)
498{
499  char
500    path[MaxTextExtent];
501
502  const char
503    *element;
504
505  LinkedListInfo
506    *options,
507    *paths;
508
509  StringInfo
510    *xml;
511
512  assert(filename != (const char *) NULL);
513  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
514  assert(exception != (ExceptionInfo *) NULL);
515  (void) CopyMagickString(path,filename,MaxTextExtent);
516  /*
517    Load XML from configuration files to linked-list.
518  */
519  options=NewLinkedList(0);
520  paths=GetConfigurePaths(filename,exception);
521  if (paths != (LinkedListInfo *) NULL)
522    {
523      ResetLinkedListIterator(paths);
524      element=(const char *) GetNextValueInLinkedList(paths);
525      while (element != (const char *) NULL)
526      {
527        (void) FormatMagickString(path,MaxTextExtent,"%s%s",element,filename);
528        (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
529          "Searching for configure file: \"%s\"",path);
530        xml=ConfigureFileToStringInfo(path);
531        if (xml != (StringInfo *) NULL)
532          (void) AppendValueToLinkedList(options,xml);
533        element=(const char *) GetNextValueInLinkedList(paths);
534      }
535      paths=DestroyLinkedList(paths,RelinquishMagickMemory);
536    }
537#if defined(__WINDOWS__)
538  {
539    char
540      *blob;
541
542    blob=(char *) NTResourceToBlob(filename);
543    if (blob != (char *) NULL)
544      {
545        xml=StringToStringInfo(blob);
546        SetStringInfoPath(xml,filename);
547        (void) AppendValueToLinkedList(options,xml);
548        blob=DestroyString(blob);
549      }
550  }
551#endif
552  if (GetNumberOfElementsInLinkedList(options) == 0)
553    (void) ThrowMagickException(exception,GetMagickModule(),ConfigureWarning,
554      "UnableToOpenConfigureFile","`%s'",filename);
555  ResetLinkedListIterator(options);
556  return(options);
557}
558
559/*
560%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
561%                                                                             %
562%                                                                             %
563%                                                                             %
564%  G e t C o n f i g u r e P a t h s                                          %
565%                                                                             %
566%                                                                             %
567%                                                                             %
568%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
569%
570%  GetConfigurePaths() returns any Magick configuration paths associated
571%  with the specified filename.
572%
573%  The format of the GetConfigurePaths method is:
574%
575%      LinkedListInfo *GetConfigurePaths(const char *filename,
576%        ExceptionInfo *exception)
577%
578%  A description of each parameter follows:
579%
580%    o filename: the configure file name.
581%
582%    o exception: Return any errors or warnings in this structure.
583%
584*/
585MagickExport LinkedListInfo *GetConfigurePaths(const char *filename,
586  ExceptionInfo *exception)
587{
588  char
589    path[MaxTextExtent];
590
591  LinkedListInfo
592    *paths;
593
594  assert(filename != (const char *) NULL);
595  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",filename);
596  assert(exception != (ExceptionInfo *) NULL);
597  (void) CopyMagickString(path,filename,MaxTextExtent);
598  paths=NewLinkedList(0);
599  {
600    char
601      *configure_path;
602
603    /*
604      Search $MAGICK_CONFIGURE_PATH.
605    */
606    configure_path=GetEnvironmentValue("MAGICK_CONFIGURE_PATH");
607    if (configure_path != (char *) NULL)
608      {
609        register char
610          *p,
611          *q;
612
613        for (p=configure_path-1; p != (char *) NULL; )
614        {
615          (void) CopyMagickString(path,p+1,MaxTextExtent);
616          q=strchr(path,DirectoryListSeparator);
617          if (q != (char *) NULL)
618            *q='\0';
619          q=path+strlen(path)-1;
620          if ((q >= path) && (*q != *DirectorySeparator))
621            (void) ConcatenateMagickString(path,DirectorySeparator,
622              MaxTextExtent);
623          (void) AppendValueToLinkedList(paths,ConstantString(path));
624          p=strchr(p+1,DirectoryListSeparator);
625        }
626        configure_path=DestroyString(configure_path);
627      }
628  }
629#if defined(MAGICKCORE_INSTALLED_SUPPORT)
630#if defined(MAGICKCORE_SHARE_CONFIGURE_PATH)
631  (void) AppendValueToLinkedList(paths,ConstantString(
632    MAGICKCORE_SHARE_CONFIGURE_PATH));
633#endif
634#if defined(MAGICKCORE_CONFIGURE_PATH)
635  (void) AppendValueToLinkedList(paths,ConstantString(
636    MAGICKCORE_CONFIGURE_PATH));
637#endif
638#if defined(MAGICKCORE_DOCUMENTATION_PATH)
639  (void) AppendValueToLinkedList(paths,ConstantString(
640    MAGICKCORE_DOCUMENTATION_PATH));
641#endif
642#if defined(MAGICKCORE_SHARE_PATH)
643  (void) AppendValueToLinkedList(paths,ConstantString(MAGICKCORE_SHARE_PATH));
644#endif
645#if defined(__WINDOWS__) && !(defined(MAGICKCORE_CONFIGURE_PATH) || defined(MAGICKCORE_SHARE_CONFIGURE_PATH))
646  {
647    char
648      *registry_key;
649
650    unsigned char
651      *key_value;
652
653    /*
654      Locate file via registry key.
655    */
656    registry_key="ConfigurePath";
657    key_value=NTRegistryKeyLookup(registry_key);
658    if (key_value == (unsigned char *) NULL)
659      ThrowMagickException(exception,GetMagickModule(),ConfigureError,
660        "RegistryKeyLookupFailed","`%s'",registry_key);
661    else
662      {
663        (void) FormatMagickString(path,MaxTextExtent,"%s%s",(char *) key_value,
664          DirectorySeparator);
665        (void) AppendValueToLinkedList(paths,ConstantString(path));
666        key_value=(unsigned char *) RelinquishMagickMemory(key_value);
667      }
668  }
669#endif
670#else
671  {
672    char
673      *home;
674
675    /*
676      Search under MAGICK_HOME.
677    */
678    home=GetEnvironmentValue("MAGICK_HOME");
679    if (home != (char *) NULL)
680      {
681#if !defined(MAGICKCORE_POSIX_SUPPORT)
682        (void) FormatMagickString(path,MaxTextExtent,"%s%s",home,
683          DirectorySeparator);
684        (void) AppendValueToLinkedList(paths,ConstantString(path));
685#else
686        (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",home,
687          MAGICKCORE_CONFIGURE_RELATIVE_PATH);
688        (void) AppendValueToLinkedList(paths,ConstantString(path));
689        (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",home,
690          MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
691        (void) AppendValueToLinkedList(paths,ConstantString(path));
692#endif
693        home=DestroyString(home);
694      }
695    }
696  if (*GetClientPath() != '\0')
697    {
698#if !defined(MAGICKCORE_POSIX_SUPPORT)
699      (void) FormatMagickString(path,MaxTextExtent,"%s%s",GetClientPath(),
700        DirectorySeparator);
701      (void) AppendValueToLinkedList(paths,ConstantString(path));
702#else
703      char
704        prefix[MaxTextExtent];
705
706      /*
707        Search based on executable directory if directory is known.
708      */
709      (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
710      ChopPathComponents(prefix,1);
711      (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",prefix,
712        MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
713      (void) AppendValueToLinkedList(paths,ConstantString(path));
714      (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",prefix,
715        MAGICKCORE_CONFIGURE_RELATIVE_PATH);
716      (void) AppendValueToLinkedList(paths,ConstantString(path));
717#endif
718    }
719#endif
720  {
721    char
722      *home;
723
724    home=GetEnvironmentValue("HOME");
725    if (home == (char *) NULL)
726      home=GetEnvironmentValue("USERPROFILE");
727    if (home != (char *) NULL)
728      {
729        /*
730          Search $HOME/.magick.
731        */
732        (void) FormatMagickString(path,MaxTextExtent,"%s%s.magick%s",home,
733          DirectorySeparator,DirectorySeparator);
734        (void) AppendValueToLinkedList(paths,ConstantString(path));
735        home=DestroyString(home);
736      }
737  }
738#if defined(__WINDOWS__)
739  {
740    char
741      module_path[MaxTextExtent];
742
743    if (NTGetModulePath("CORE_RL_magick_.dll",module_path) != MagickFalse)
744      {
745        char
746          *element;
747
748        /*
749          Search module path.
750        */
751        (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
752          DirectorySeparator);
753        element=(char *) RemoveElementByValueFromLinkedList(paths,path);
754        if (element != (char *) NULL)
755          element=DestroyString(element);
756        (void) AppendValueToLinkedList(paths,ConstantString(path));
757      }
758    if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
759      {
760        /*
761          Search PerlMagick module path.
762        */
763        (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
764          DirectorySeparator);
765        (void) AppendValueToLinkedList(paths,ConstantString(path));
766        (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
767          "\\inc\\lib\\auto\\Image\\Magick\\");
768        (void) AppendValueToLinkedList(paths,ConstantString(path));
769      }
770  }
771#endif
772  /*
773    Search current directory.
774  */
775  (void) AppendValueToLinkedList(paths,ConstantString(""));
776  return(paths);
777}
778
779/*
780%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
781%                                                                             %
782%                                                                             %
783%                                                                             %
784%   G e t C o n f i g u r e V a l u e                                         %
785%                                                                             %
786%                                                                             %
787%                                                                             %
788%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
789%
790%  GetConfigureValue() returns the value associated with the configure info.
791%
792%  The format of the GetConfigureValue method is:
793%
794%      const char *GetConfigureValue(const ConfigureInfo *configure_info)
795%
796%  A description of each parameter follows:
797%
798%    o configure_info:  The configure info.
799%
800*/
801MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
802{
803  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
804  assert(configure_info != (ConfigureInfo *) NULL);
805  assert(configure_info->signature == MagickSignature);
806  return(configure_info->value);
807}
808
809/*
810%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
811%                                                                             %
812%                                                                             %
813%                                                                             %
814+   I n i t i a l i z e C o n f i g u r e L i s t                             %
815%                                                                             %
816%                                                                             %
817%                                                                             %
818%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
819%
820%  InitializeConfigureList() initializes the configure list.
821%
822%  The format of the InitializeConfigureList method is:
823%
824%      MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
825%
826%  A description of each parameter follows.
827%
828%    o exception: Return any errors or warnings in this structure.
829%
830*/
831static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
832{
833  if ((configure_list == (LinkedListInfo *) NULL) &&
834      (instantiate_configure == MagickFalse))
835    {
836      AcquireSemaphoreInfo(&configure_semaphore);
837      if ((configure_list == (LinkedListInfo *) NULL) &&
838          (instantiate_configure == MagickFalse))
839        {
840          (void) LoadConfigureLists(ConfigureFilename,exception);
841          instantiate_configure=MagickTrue;
842        }
843      RelinquishSemaphoreInfo(configure_semaphore);
844    }
845  return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
846}
847
848/*
849%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
850%                                                                             %
851%                                                                             %
852%                                                                             %
853%  L i s t C o n f i g u r e I n f o                                          %
854%                                                                             %
855%                                                                             %
856%                                                                             %
857%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858%
859%  ListConfigureInfo() lists the configure info to a file.
860%
861%  The format of the ListConfigureInfo method is:
862%
863%      MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
864%
865%  A description of each parameter follows.
866%
867%    o file:  An pointer to a FILE.
868%
869%    o exception: Return any errors or warnings in this structure.
870%
871*/
872MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
873  ExceptionInfo *exception)
874{
875  const char
876    *name,
877    *path,
878    *value;
879
880  const ConfigureInfo
881    **configure_info;
882
883  long
884    j;
885
886  register long
887    i;
888
889  unsigned long
890    number_options;
891
892  if (file == (const FILE *) NULL)
893    file=stdout;
894  configure_info=GetConfigureInfoList("*",&number_options,exception);
895  if (configure_info == (const ConfigureInfo **) NULL)
896    return(MagickFalse);
897  path=(const char *) NULL;
898  for (i=0; i < (long) number_options; i++)
899  {
900    if (configure_info[i]->stealth != MagickFalse)
901      continue;
902    if ((path == (const char *) NULL) ||
903        (LocaleCompare(path,configure_info[i]->path) != 0))
904      {
905        if (configure_info[i]->path != (char *) NULL)
906          (void) fprintf(file,"\nPath: %s\n\n",configure_info[i]->path);
907        (void) fprintf(file,"Name          Value\n");
908        (void) fprintf(file,"-------------------------------------------------"
909          "------------------------------\n");
910      }
911    path=configure_info[i]->path;
912    name="unknown";
913    if (configure_info[i]->name != (char *) NULL)
914      name=configure_info[i]->name;
915    (void) fprintf(file,"%s",name);
916    for (j=(long) strlen(name); j <= 12; j++)
917      (void) fprintf(file," ");
918    (void) fprintf(file," ");
919    value="unknown";
920    if (co