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