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