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