blob: 610c597ec9c554ad8cf5637d929b754a0a104452 [file] [log] [blame]
cristy3ed852e2009-09-05 21:47:34 +00001/*
2%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3% %
4% %
5% %
6% CCCC OOO N N FFFFF IIIII GGGG U U RRRR EEEEE %
7% C O O NN N F I G U U R R E %
8% C O O N N N FFF I G GG U U RRRR EEE %
9% C O O N NN F I G G U U R R E %
10% CCCC OOO N N F IIIII GGG UUU R R EEEEE %
11% %
12% %
13% MagickCore Image Configure Methods %
14% %
15% Software Design %
16% John Cristy %
17% July 2003 %
18% %
19% %
20% Copyright 1999-2009 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 configure tag.
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) InsertValueInLinkedList(configure_list,0,
229 RemoveElementByValueFromLinkedList(configure_list,p));
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 {
660 (void) FormatMagickString(path,MaxTextExtent,"%s%s",(char *) key_value,
661 DirectorySeparator);
662 (void) AppendValueToLinkedList(paths,ConstantString(path));
663 key_value=(unsigned char *) RelinquishMagickMemory(key_value);
664 }
665 }
666#endif
667#else
668 {
669 char
670 *home;
671
672 /*
673 Search under MAGICK_HOME.
674 */
675 home=GetEnvironmentValue("MAGICK_HOME");
676 if (home != (char *) NULL)
677 {
678#if !defined(MAGICKCORE_POSIX_SUPPORT)
679 (void) FormatMagickString(path,MaxTextExtent,"%s%s",home,
680 DirectorySeparator);
681 (void) AppendValueToLinkedList(paths,ConstantString(path));
682#else
683 (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",home,
684 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
685 (void) AppendValueToLinkedList(paths,ConstantString(path));
686 (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",home,
687 MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
688 (void) AppendValueToLinkedList(paths,ConstantString(path));
689#endif
690 home=DestroyString(home);
691 }
692 }
693 if (*GetClientPath() != '\0')
694 {
695#if !defined(MAGICKCORE_POSIX_SUPPORT)
696 (void) FormatMagickString(path,MaxTextExtent,"%s%s",GetClientPath(),
697 DirectorySeparator);
698 (void) AppendValueToLinkedList(paths,ConstantString(path));
699#else
700 char
701 prefix[MaxTextExtent];
702
703 /*
704 Search based on executable directory if directory is known.
705 */
706 (void) CopyMagickString(prefix,GetClientPath(),MaxTextExtent);
707 ChopPathComponents(prefix,1);
708 (void) FormatMagickString(path,MaxTextExtent,"%s/share/%s/",prefix,
709 MAGICKCORE_SHARE_CONFIGURE_RELATIVE_PATH);
710 (void) AppendValueToLinkedList(paths,ConstantString(path));
711 (void) FormatMagickString(path,MaxTextExtent,"%s/lib/%s/",prefix,
712 MAGICKCORE_CONFIGURE_RELATIVE_PATH);
713 (void) AppendValueToLinkedList(paths,ConstantString(path));
714#endif
715 }
716#endif
717 {
718 char
719 *home;
720
721 home=GetEnvironmentValue("HOME");
722 if (home == (char *) NULL)
723 home=GetEnvironmentValue("USERPROFILE");
724 if (home != (char *) NULL)
725 {
726 /*
727 Search $HOME/.magick.
728 */
729 (void) FormatMagickString(path,MaxTextExtent,"%s%s.magick%s",home,
730 DirectorySeparator,DirectorySeparator);
731 (void) AppendValueToLinkedList(paths,ConstantString(path));
732 home=DestroyString(home);
733 }
734 }
735#if defined(__WINDOWS__)
736 {
737 char
738 module_path[MaxTextExtent];
739
740 if ((NTGetModulePath("CORE_RL_magick_.dll",module_path) != MagickFalse) ||
741 (NTGetModulePath("CORE_DB_magick_.dll",module_path) != MagickFalse))
742 {
743 char
744 *element;
745
746 /*
747 Search module path.
748 */
749 (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
750 DirectorySeparator);
751 element=(char *) RemoveElementByValueFromLinkedList(paths,path);
752 if (element != (char *) NULL)
753 element=DestroyString(element);
754 (void) AppendValueToLinkedList(paths,ConstantString(path));
755 }
756 if (NTGetModulePath("Magick.dll",module_path) != MagickFalse)
757 {
758 /*
759 Search PerlMagick module path.
760 */
761 (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
762 DirectorySeparator);
763 (void) AppendValueToLinkedList(paths,ConstantString(path));
764 (void) FormatMagickString(path,MaxTextExtent,"%s%s",module_path,
765 "\\inc\\lib\\auto\\Image\\Magick\\");
766 (void) AppendValueToLinkedList(paths,ConstantString(path));
767 }
768 }
769#endif
770 /*
771 Search current directory.
772 */
773 (void) AppendValueToLinkedList(paths,ConstantString(""));
774 return(paths);
775}
776
777/*
778%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
779% %
780% %
781% %
782% G e t C o n f i g u r e V a l u e %
783% %
784% %
785% %
786%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
787%
788% GetConfigureValue() returns the value associated with the configure info.
789%
790% The format of the GetConfigureValue method is:
791%
792% const char *GetConfigureValue(const ConfigureInfo *configure_info)
793%
794% A description of each parameter follows:
795%
796% o configure_info: The configure info.
797%
798*/
799MagickExport const char *GetConfigureValue(const ConfigureInfo *configure_info)
800{
801 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"...");
802 assert(configure_info != (ConfigureInfo *) NULL);
803 assert(configure_info->signature == MagickSignature);
804 return(configure_info->value);
805}
806
807/*
808%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
809% %
810% %
811% %
812+ I n i t i a l i z e C o n f i g u r e L i s t %
813% %
814% %
815% %
816%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
817%
818% InitializeConfigureList() initializes the configure list.
819%
820% The format of the InitializeConfigureList method is:
821%
822% MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
823%
824% A description of each parameter follows.
825%
826% o exception: return any errors or warnings in this structure.
827%
828*/
829static MagickBooleanType InitializeConfigureList(ExceptionInfo *exception)
830{
831 if ((configure_list == (LinkedListInfo *) NULL) &&
832 (instantiate_configure == MagickFalse))
833 {
834 AcquireSemaphoreInfo(&configure_semaphore);
835 if ((configure_list == (LinkedListInfo *) NULL) &&
836 (instantiate_configure == MagickFalse))
837 {
838 (void) LoadConfigureLists(ConfigureFilename,exception);
839 instantiate_configure=MagickTrue;
840 }
841 RelinquishSemaphoreInfo(configure_semaphore);
842 }
843 return(configure_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
844}
845
846/*
847%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
848% %
849% %
850% %
851% L i s t C o n f i g u r e I n f o %
852% %
853% %
854% %
855%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
856%
857% ListConfigureInfo() lists the configure info to a file.
858%
859% The format of the ListConfigureInfo method is:
860%
861% MagickBooleanType ListConfigureInfo(FILE *file,ExceptionInfo *exception)
862%
863% A description of each parameter follows.
864%
865% o file: An pointer to a FILE.
866%
867% o exception: return any errors or warnings in this structure.
868%
869*/
870MagickExport MagickBooleanType ListConfigureInfo(FILE *file,
871 ExceptionInfo *exception)
872{
873 const char
874 *name,
875 *path,
876 *value;
877
878 const ConfigureInfo
879 **configure_info;
880
881 long
882 j;
883
884 register long
885 i;
886
887 unsigned long
888 number_options;
889
890 if (file == (const FILE *) NULL)
891 file=stdout;
892 configure_info=GetConfigureInfoList("*",&number_options,exception);
893 if (configure_info == (const ConfigureInfo **) NULL)
894 return(MagickFalse);
895 path=(const char *) NULL;
896 for (i=0; i < (long) number_options; i++)
897 {
898 if (configure_info[i]->stealth != MagickFalse)
899 continue;
900 if ((path == (const char *) NULL) ||
901 (LocaleCompare(path,configure_info[i]->path) != 0))
902 {
903 if (configure_info[i]->path != (char *) NULL)
904 (void) fprintf(file,"\nPath: %s\n\n",configure_info[i]->path);
905 (void) fprintf(file,"Name Value\n");
906 (void) fprintf(file,"-------------------------------------------------"
907 "------------------------------\n");
908 }
909 path=configure_info[i]->path;
910 name="unknown";
911 if (configure_info[i]->name != (char *) NULL)
912 name=configure_info[i]->name;
913 (void) fprintf(file,"%s",name);
914 for (j=(long) strlen(name); j <= 12; j++)
915 (void) fprintf(file," ");
916 (void) fprintf(file," ");
917 value="unknown";
918 if (configure_info[i]->value != (char *) NULL)
919 value=configure_info[i]->value;
920 (void) fprintf(file,"%s",value);
921 (void) fprintf(file,"\n");
922 }
923 (void) fflush(file);
924 configure_info=(const ConfigureInfo **)
925 RelinquishMagickMemory((void *) configure_info);
926 return(MagickTrue);
927}
928
929/*
930%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
931% %
932% %
933% %
934+ L o a d C o n f i g u r e L i s t %
935% %
936% %
937% %
938%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
939%
940% LoadConfigureList() loads the configure configuration file which provides a
941% mapping between configure attributes and a configure name.
942%
943% The format of the LoadConfigureList method is:
944%
945% MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
946% const unsigned long depth,ExceptionInfo *exception)
947%
948% A description of each parameter follows:
949%
950% o xml: The configure list in XML format.
951%
952% o filename: The configure list filename.
953%
954% o depth: depth of <include /> statements.
955%
956% o exception: return any errors or warnings in this structure.
957%
958*/
959static MagickBooleanType LoadConfigureList(const char *xml,const char *filename,
960 const unsigned long depth,ExceptionInfo *exception)
961{
962 char
963 keyword[MaxTextExtent],
964 *token;
965
966 ConfigureInfo
967 *configure_info;
968
969 const char
970 *q;
971
972 MagickBooleanType
973 status;
974
975 /*
976 Load the configure map file.
977 */
978 (void) LogMagickEvent(ConfigureEvent,GetMagickModule(),
979 "Loading configure file \"%s\" ...",filename);
980 if (configure_list == (LinkedListInfo *) NULL)
981 {
982 configure_list=NewLinkedList(0);
983 if (configure_list == (LinkedListInfo *) NULL)
984 {
985 ThrowFileException(exception,ResourceLimitError,
986 "MemoryAllocationFailed",filename);
987 return(MagickFalse);
988 }
989 }
990 status=MagickTrue;
991 configure_info=(ConfigureInfo *) NULL;
992 if (xml == (char *) NULL)
993 token=AcquireString(ConfigureMap);
994 else
995 token=AcquireString((char *) xml);
996 for (q=(char *) xml; *q != '\0'; )
997 {
998 /*
999 Interpret XML.
1000 */
1001 GetMagickToken(q,&q,token);
1002 if (*token == '\0')
1003 break;
1004 (void) CopyMagickString(keyword,token,MaxTextExtent);
1005 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1006 {
1007 /*
1008 Doctype element.
1009 */
1010 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1011 GetMagickToken(q,&q,token);
1012 continue;
1013 }
1014 if (LocaleNCompare(keyword,"<!--",4) == 0)
1015 {
1016 /*
1017 Comment element.
1018 */
1019 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1020 GetMagickToken(q,&q,token);
1021 continue;
1022 }
1023 if (LocaleCompare(keyword,"<include") == 0)
1024 {
1025 /*
1026 Include element.
1027 */
1028 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1029 {
1030 (void) CopyMagickString(keyword,token,MaxTextExtent);
1031 GetMagickToken(q,&q,token);
1032 if (*token != '=')
1033 continue;
1034 GetMagickToken(q,&q,token);
1035 if (LocaleCompare(keyword,"file") == 0)
1036 {
1037 if (depth > 200)
1038 (void) ThrowMagickException(exception,GetMagickModule(),
1039 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1040 else
1041 {
1042 char
1043 path[MaxTextExtent],
1044 *xml;
1045
1046 GetPathComponent(filename,HeadPath,path);
1047 if (*path != '\0')
1048 (void) ConcatenateMagickString(path,DirectorySeparator,
1049 MaxTextExtent);
1050 if (*token == *DirectorySeparator)
1051 (void) CopyMagickString(path,token,MaxTextExtent);
1052 else
1053 (void) ConcatenateMagickString(path,token,MaxTextExtent);
1054 xml=FileToString(path,~0,exception);
1055 if (xml != (char *) NULL)
1056 {
1057 status=LoadConfigureList(xml,path,depth+1,exception);
1058 xml=(char *) RelinquishMagickMemory(xml);
1059 }
1060 }
1061 }
1062 }
1063 continue;
1064 }
1065 if (LocaleCompare(keyword,"<configure") == 0)
1066 {
1067 /*
1068 Configure element.
1069 */
1070 configure_info=(ConfigureInfo *) AcquireMagickMemory(
1071 sizeof(*configure_info));
1072 if (configure_info == (ConfigureInfo *) NULL)
1073 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed");
1074 (void) ResetMagickMemory(configure_info,0,sizeof(*configure_info));
1075 configure_info->path=ConstantString(filename);
1076 configure_info->signature=MagickSignature;
1077 continue;
1078 }
1079 if (configure_info == (ConfigureInfo *) NULL)
1080 continue;
1081 if (LocaleCompare(keyword,"/>") == 0)
1082 {
1083 status=AppendValueToLinkedList(configure_list,configure_info);
1084 if (status == MagickFalse)
1085 (void) ThrowMagickException(exception,GetMagickModule(),
1086 ResourceLimitError,"MemoryAllocationFailed","`%s'",
1087 configure_info->name);
1088 configure_info=(ConfigureInfo *) NULL;
1089 }
1090 /*
1091 Parse configure element.
1092 */
1093 GetMagickToken(q,(const char **) NULL,token);
1094 if (*token != '=')
1095 continue;
1096 GetMagickToken(q,&q,token);
1097 GetMagickToken(q,&q,token);
1098 switch (*keyword)
1099 {
1100 case 'N':
1101 case 'n':
1102 {
1103 if (LocaleCompare((char *) keyword,"name") == 0)
1104 {
1105 configure_info->name=ConstantString(token);
1106 break;
1107 }
1108 break;
1109 }
1110 case 'S':
1111 case 's':
1112 {
1113 if (LocaleCompare((char *) keyword,"stealth") == 0)
1114 {
1115 configure_info->stealth=IsMagickTrue(token);
1116 break;
1117 }
1118 break;
1119 }
1120 case 'V':
1121 case 'v':
1122 {
1123 if (LocaleCompare((char *) keyword,"value") == 0)
1124 {
1125 configure_info->value=ConstantString(token);
1126 break;
1127 }
1128 break;
1129 }
1130 default:
1131 break;
1132 }
1133 }
1134 token=(char *) RelinquishMagickMemory(token);
1135 return(status);
1136}
1137
1138/*
1139%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1140% %
1141% %
1142% %
1143% L o a d C o n f i g u r e L i s t s %
1144% %
1145% %
1146% %
1147%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1148%
1149% LoadConfigureList() loads one or more configure configuration files which
1150% provides a mapping between configure attributes and a configure name.
1151%
1152% The format of the LoadConfigureLists method is:
1153%
1154% MagickBooleanType LoadConfigureLists(const char *filename,
1155% ExceptionInfo *exception)
1156%
1157% A description of each parameter follows:
1158%
1159% o filename: the font file name.
1160%
1161% o exception: return any errors or warnings in this structure.
1162%
1163*/
1164static MagickBooleanType LoadConfigureLists(const char *filename,
1165 ExceptionInfo *exception)
1166{
1167#if defined(MAGICKCORE_EMBEDDABLE_SUPPORT)
1168 return(LoadConfigureList(ConfigureMap,"built-in",0,exception));
1169#else
1170 const StringInfo
1171 *option;
1172
1173 LinkedListInfo
1174 *options;
1175
1176 MagickStatusType
1177 status;
1178
1179 status=MagickFalse;
1180 options=GetConfigureOptions(filename,exception);
1181 option=(const StringInfo *) GetNextValueInLinkedList(options);
1182 while (option != (const StringInfo *) NULL)
1183 {
1184 status|=LoadConfigureList((const char *) GetStringInfoDatum(option),
1185 GetStringInfoPath(option),0,exception);
1186 option=(const StringInfo *) GetNextValueInLinkedList(options);
1187 }
1188 options=DestroyConfigureOptions(options);
1189 if ((configure_list == (LinkedListInfo *) NULL) ||
1190 (IsLinkedListEmpty(configure_list) != MagickFalse))
1191 status|=LoadConfigureList(ConfigureMap,"built-in",0,exception);
1192 return(status != 0 ? MagickTrue : MagickFalse);
1193#endif
1194}