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