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