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