1 /* 2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 3 % % 4 % % 5 % % 6 % EEEEE X X CCCC EEEEE PPPP TTTTT IIIII OOO N N % 7 % E X X C E P P T I O O NN N % 8 % EEE X C EEE PPPP T I O O N N N % 9 % E X X C E P T I O O N NN % 10 % EEEEE X X CCCC EEEEE P T IIIII OOO N N % 11 % % 12 % % 13 % MagickCore Exception Methods % 14 % % 15 % Software Design % 16 % Cristy % 17 % July 1993 % 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 /* 42 Include declarations. 43 */ 44 #include "MagickCore/studio.h" 45 #include "MagickCore/client.h" 46 #include "MagickCore/exception.h" 47 #include "MagickCore/exception-private.h" 48 #include "MagickCore/linked-list.h" 49 #include "MagickCore/locale_.h" 50 #include "MagickCore/log.h" 51 #include "MagickCore/magick.h" 52 #include "MagickCore/memory_.h" 53 #include "MagickCore/string_.h" 54 #include "MagickCore/utility.h" 55 #include "MagickCore/utility-private.h" 56 57 /* 59 Forward declarations. 60 */ 61 #if defined(__cplusplus) || defined(c_plusplus) 62 extern "C" { 63 #endif 64 65 static void 66 DefaultErrorHandler(const ExceptionType,const char *,const char *), 67 DefaultFatalErrorHandler(const ExceptionType,const char *,const char *), 68 DefaultWarningHandler(const ExceptionType,const char *,const char *); 69 70 #if defined(__cplusplus) || defined(c_plusplus) 71 } 72 #endif 73 74 /* 76 Global declarations. 77 */ 78 #define MaxExceptions 128 79 80 /* 82 Global declarations. 83 */ 84 static ErrorHandler 85 error_handler = DefaultErrorHandler; 86 87 static FatalErrorHandler 88 fatal_error_handler = DefaultFatalErrorHandler; 89 90 static WarningHandler 91 warning_handler = DefaultWarningHandler; 92 93 /* 95 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 96 % % 97 % % 98 % % 99 % A c q u i r e E x c e p t i o n I n f o % 100 % % 101 % % 102 % % 103 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 104 % 105 % AcquireExceptionInfo() allocates the ExceptionInfo structure. 106 % 107 % The format of the AcquireExceptionInfo method is: 108 % 109 % ExceptionInfo *AcquireExceptionInfo(void) 110 % 111 */ 112 MagickExport ExceptionInfo *AcquireExceptionInfo(void) 113 { 114 ExceptionInfo 115 *exception; 116 117 exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception)); 118 if (exception == (ExceptionInfo *) NULL) 119 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 120 InitializeExceptionInfo(exception); 121 exception->relinquish=MagickTrue; 122 return(exception); 123 } 124 125 /*l 127 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 128 % % 129 % % 130 % % 131 % C l e a r M a g i c k E x c e p t i o n % 132 % % 133 % % 134 % % 135 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 136 % 137 % ClearMagickException() clears any exception that may not have been caught 138 % yet. 139 % 140 % The format of the ClearMagickException method is: 141 % 142 % ClearMagickException(ExceptionInfo *exception) 143 % 144 % A description of each parameter follows: 145 % 146 % o exception: the exception info. 147 % 148 */ 149 150 static void *DestroyExceptionElement(void *exception) 151 { 152 register ExceptionInfo 153 *p; 154 155 p=(ExceptionInfo *) exception; 156 if (p->reason != (char *) NULL) 157 p->reason=DestroyString(p->reason); 158 if (p->description != (char *) NULL) 159 p->description=DestroyString(p->description); 160 p=(ExceptionInfo *) RelinquishMagickMemory(p); 161 return((void *) NULL); 162 } 163 164 MagickExport void ClearMagickException(ExceptionInfo *exception) 165 { 166 assert(exception != (ExceptionInfo *) NULL); 167 assert(exception->signature == MagickCoreSignature); 168 if (exception->exceptions == (void *) NULL) 169 return; 170 LockSemaphoreInfo(exception->semaphore); 171 ClearLinkedList((LinkedListInfo *) exception->exceptions, 172 DestroyExceptionElement); 173 exception->severity=UndefinedException; 174 exception->reason=(char *) NULL; 175 exception->description=(char *) NULL; 176 UnlockSemaphoreInfo(exception->semaphore); 177 errno=0; 178 } 179 180 /* 182 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 183 % % 184 % % 185 % % 186 % C a t c h E x c e p t i o n % 187 % % 188 % % 189 % % 190 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 191 % 192 % CatchException() returns if no exceptions is found otherwise it reports 193 % the exception as a warning, error, or fatal depending on the severity. 194 % 195 % The format of the CatchException method is: 196 % 197 % CatchException(ExceptionInfo *exception) 198 % 199 % A description of each parameter follows: 200 % 201 % o exception: the exception info. 202 % 203 */ 204 MagickExport void CatchException(ExceptionInfo *exception) 205 { 206 register const ExceptionInfo 207 *p; 208 209 ssize_t 210 i; 211 212 assert(exception != (ExceptionInfo *) NULL); 213 assert(exception->signature == MagickCoreSignature); 214 if (exception->exceptions == (void *) NULL) 215 return; 216 LockSemaphoreInfo(exception->semaphore); 217 ResetLinkedListIterator((LinkedListInfo *) exception->exceptions); 218 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *) 219 exception->exceptions); 220 for (i=0; p != (const ExceptionInfo *) NULL; i++) 221 { 222 if (i < MaxExceptions) 223 { 224 if ((p->severity >= WarningException) && (p->severity < ErrorException)) 225 MagickWarning(p->severity,p->reason,p->description); 226 if ((p->severity >= ErrorException) && 227 (p->severity < FatalErrorException)) 228 MagickError(p->severity,p->reason,p->description); 229 } 230 else 231 if (i == MaxExceptions) 232 MagickError(ResourceLimitError,"too many exceptions", 233 "exception processing is suspended"); 234 if (p->severity >= FatalErrorException) 235 MagickFatalError(p->severity,p->reason,p->description); 236 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *) 237 exception->exceptions); 238 } 239 UnlockSemaphoreInfo(exception->semaphore); 240 ClearMagickException(exception); 241 } 242 243 /* 245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 246 % % 247 % % 248 % % 249 % C l o n e E x c e p t i o n I n f o % 250 % % 251 % % 252 % % 253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 254 % 255 % CloneExceptionInfo() clones the ExceptionInfo structure. 256 % 257 % The format of the CloneExceptionInfo method is: 258 % 259 % ExceptionInfo *CloneException(ExceptionInfo *exception) 260 % 261 % A description of each parameter follows: 262 % 263 % o exception: the exception info. 264 % 265 */ 266 MagickExport ExceptionInfo *CloneExceptionInfo(ExceptionInfo *exception) 267 { 268 ExceptionInfo 269 *clone_exception; 270 271 clone_exception=(ExceptionInfo *) AcquireMagickMemory(sizeof(*exception)); 272 if (clone_exception == (ExceptionInfo *) NULL) 273 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 274 InitializeExceptionInfo(clone_exception); 275 InheritException(clone_exception,exception); 276 clone_exception->relinquish=MagickTrue; 277 return(clone_exception); 278 } 279 280 /* 282 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 283 % % 284 % % 285 % % 286 + D e f a u l t E r r o r H a n d l e r % 287 % % 288 % % 289 % % 290 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 291 % 292 % DefaultErrorHandler() displays an error reason. 293 % 294 % The format of the DefaultErrorHandler method is: 295 % 296 % void MagickError(const ExceptionType severity,const char *reason, 297 % const char *description) 298 % 299 % A description of each parameter follows: 300 % 301 % o severity: Specifies the numeric error category. 302 % 303 % o reason: Specifies the reason to display before terminating the 304 % program. 305 % 306 % o description: Specifies any description to the reason. 307 % 308 */ 309 static void DefaultErrorHandler(const ExceptionType magick_unused(severity), 310 const char *reason,const char *description) 311 { 312 magick_unreferenced(severity); 313 314 if (reason == (char *) NULL) 315 return; 316 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason); 317 if (description != (char *) NULL) 318 (void) FormatLocaleFile(stderr," (%s)",description); 319 (void) FormatLocaleFile(stderr,".\n"); 320 (void) fflush(stderr); 321 } 322 323 /* 325 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 326 % % 327 % % 328 % % 329 + D e f a u l t F a t a l E r r o r H a n d l e r % 330 % % 331 % % 332 % % 333 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 334 % 335 % DefaultFatalErrorHandler() displays an error reason and then terminates the 336 % program. 337 % 338 % The format of the DefaultFatalErrorHandler method is: 339 % 340 % void MagickFatalError(const ExceptionType severity,const char *reason, 341 % const char *description) 342 % 343 % A description of each parameter follows: 344 % 345 % o severity: Specifies the numeric error category. 346 % 347 % o reason: Specifies the reason to display before terminating the program. 348 % 349 % o description: Specifies any description to the reason. 350 % 351 */ 352 static void DefaultFatalErrorHandler(const ExceptionType severity, 353 const char *reason,const char *description) 354 { 355 if (reason == (char *) NULL) 356 return; 357 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason); 358 if (description != (char *) NULL) 359 (void) FormatLocaleFile(stderr," (%s)",description); 360 (void) FormatLocaleFile(stderr,".\n"); 361 (void) fflush(stderr); 362 MagickCoreTerminus(); 363 exit((int) (severity-FatalErrorException)+1); 364 } 365 366 /* 368 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 369 % % 370 % % 371 % % 372 + D e f a u l t W a r n i n g H a n d l e r % 373 % % 374 % % 375 % % 376 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 377 % 378 % DefaultWarningHandler() displays a warning reason. 379 % 380 % The format of the DefaultWarningHandler method is: 381 % 382 % void DefaultWarningHandler(const ExceptionType severity, 383 % const char *reason,const char *description) 384 % 385 % A description of each parameter follows: 386 % 387 % o severity: Specifies the numeric warning category. 388 % 389 % o reason: Specifies the reason to display before terminating the 390 % program. 391 % 392 % o description: Specifies any description to the reason. 393 % 394 */ 395 static void DefaultWarningHandler(const ExceptionType magick_unused(severity), 396 const char *reason,const char *description) 397 { 398 magick_unreferenced(severity); 399 400 if (reason == (char *) NULL) 401 return; 402 (void) FormatLocaleFile(stderr,"%s: %s",GetClientName(),reason); 403 if (description != (char *) NULL) 404 (void) FormatLocaleFile(stderr," (%s)",description); 405 (void) FormatLocaleFile(stderr,".\n"); 406 (void) fflush(stderr); 407 } 408 409 /* 411 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 412 % % 413 % % 414 % % 415 % D e s t r o y E x c e p t i o n I n f o % 416 % % 417 % % 418 % % 419 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 420 % 421 % DestroyExceptionInfo() deallocates memory associated with an exception. 422 % 423 % The format of the DestroyExceptionInfo method is: 424 % 425 % ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception) 426 % 427 % A description of each parameter follows: 428 % 429 % o exception: the exception info. 430 % 431 */ 432 MagickExport ExceptionInfo *DestroyExceptionInfo(ExceptionInfo *exception) 433 { 434 MagickBooleanType 435 relinquish; 436 437 assert(exception != (ExceptionInfo *) NULL); 438 assert(exception->signature == MagickCoreSignature); 439 if (exception->semaphore == (SemaphoreInfo *) NULL) 440 ActivateSemaphoreInfo(&exception->semaphore); 441 LockSemaphoreInfo(exception->semaphore); 442 exception->severity=UndefinedException; 443 if (exception->relinquish != MagickFalse) 444 { 445 exception->signature=(~MagickCoreSignature); 446 if (exception->exceptions != (void *) NULL) 447 exception->exceptions=(void *) DestroyLinkedList((LinkedListInfo *) 448 exception->exceptions,DestroyExceptionElement); 449 } 450 else if (exception->exceptions != (void *) NULL) 451 ClearLinkedList((LinkedListInfo *) exception->exceptions, 452 DestroyExceptionElement); 453 relinquish=exception->relinquish; 454 UnlockSemaphoreInfo(exception->semaphore); 455 if (relinquish != MagickFalse) 456 { 457 RelinquishSemaphoreInfo(&exception->semaphore); 458 exception=(ExceptionInfo *) RelinquishMagickMemory(exception); 459 } 460 return(exception); 461 } 462 463 /* 465 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 466 % % 467 % % 468 % % 469 % G e t E x c e p t i o n M e s s a g e % 470 % % 471 % % 472 % % 473 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 474 % 475 % GetExceptionMessage() returns the error message defined by the specified 476 % error code. 477 % 478 % The format of the GetExceptionMessage method is: 479 % 480 % char *GetExceptionMessage(const int error) 481 % 482 % A description of each parameter follows: 483 % 484 % o error: the error code. 485 % 486 */ 487 MagickExport char *GetExceptionMessage(const int error) 488 { 489 char 490 exception[MagickPathExtent]; 491 492 *exception='\0'; 493 #if defined(MAGICKCORE_HAVE_STRERROR_R) 494 #if !defined(MAGICKCORE_STRERROR_R_CHAR_P) 495 (void) strerror_r(error,exception,sizeof(exception)); 496 #else 497 (void) CopyMagickString(exception,strerror_r(error,exception, 498 sizeof(exception)),sizeof(exception)); 499 #endif 500 #else 501 (void) CopyMagickString(exception,strerror(error),sizeof(exception)); 502 #endif 503 return(ConstantString(exception)); 504 } 505 506 /* 508 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 509 % % 510 % % 511 % % 512 % G e t L o c a l e E x c e p t i o n M e s s a g e % 513 % % 514 % % 515 % % 516 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 517 % 518 % GetLocaleExceptionMessage() converts a enumerated exception severity and tag 519 % to a message in the current locale. 520 % 521 % The format of the GetLocaleExceptionMessage method is: 522 % 523 % const char *GetLocaleExceptionMessage(const ExceptionType severity, 524 % const char *tag) 525 % 526 % A description of each parameter follows: 527 % 528 % o severity: the severity of the exception. 529 % 530 % o tag: the message tag. 531 % 532 */ 533 534 static const char *ExceptionSeverityToTag(const ExceptionType severity) 535 { 536 switch (severity) 537 { 538 case ResourceLimitWarning: return("Resource/Limit/Warning/"); 539 case TypeWarning: return("Type/Warning/"); 540 case OptionWarning: return("Option/Warning/"); 541 case DelegateWarning: return("Delegate/Warning/"); 542 case MissingDelegateWarning: return("Missing/Delegate/Warning/"); 543 case CorruptImageWarning: return("Corrupt/Image/Warning/"); 544 case FileOpenWarning: return("File/Open/Warning/"); 545 case BlobWarning: return("Blob/Warning/"); 546 case StreamWarning: return("Stream/Warning/"); 547 case CacheWarning: return("Cache/Warning/"); 548 case CoderWarning: return("Coder/Warning/"); 549 case FilterWarning: return("Filter/Warning/"); 550 case ModuleWarning: return("Module/Warning/"); 551 case DrawWarning: return("Draw/Warning/"); 552 case ImageWarning: return("Image/Warning/"); 553 case WandWarning: return("Wand/Warning/"); 554 case XServerWarning: return("XServer/Warning/"); 555 case MonitorWarning: return("Monitor/Warning/"); 556 case RegistryWarning: return("Registry/Warning/"); 557 case ConfigureWarning: return("Configure/Warning/"); 558 case PolicyWarning: return("Policy/Warning/"); 559 case ResourceLimitError: return("Resource/Limit/Error/"); 560 case TypeError: return("Type/Error/"); 561 case OptionError: return("Option/Error/"); 562 case DelegateError: return("Delegate/Error/"); 563 case MissingDelegateError: return("Missing/Delegate/Error/"); 564 case CorruptImageError: return("Corrupt/Image/Error/"); 565 case FileOpenError: return("File/Open/Error/"); 566 case BlobError: return("Blob/Error/"); 567 case StreamError: return("Stream/Error/"); 568 case CacheError: return("Cache/Error/"); 569 case CoderError: return("Coder/Error/"); 570 case FilterError: return("Filter/Error/"); 571 case ModuleError: return("Module/Error/"); 572 case DrawError: return("Draw/Error/"); 573 case ImageError: return("Image/Error/"); 574 case WandError: return("Wand/Error/"); 575 case XServerError: return("XServer/Error/"); 576 case MonitorError: return("Monitor/Error/"); 577 case RegistryError: return("Registry/Error/"); 578 case ConfigureError: return("Configure/Error/"); 579 case PolicyError: return("Policy/Error/"); 580 case ResourceLimitFatalError: return("Resource/Limit/FatalError/"); 581 case TypeFatalError: return("Type/FatalError/"); 582 case OptionFatalError: return("Option/FatalError/"); 583 case DelegateFatalError: return("Delegate/FatalError/"); 584 case MissingDelegateFatalError: return("Missing/Delegate/FatalError/"); 585 case CorruptImageFatalError: return("Corrupt/Image/FatalError/"); 586 case FileOpenFatalError: return("File/Open/FatalError/"); 587 case BlobFatalError: return("Blob/FatalError/"); 588 case StreamFatalError: return("Stream/FatalError/"); 589 case CacheFatalError: return("Cache/FatalError/"); 590 case CoderFatalError: return("Coder/FatalError/"); 591 case FilterFatalError: return("Filter/FatalError/"); 592 case ModuleFatalError: return("Module/FatalError/"); 593 case DrawFatalError: return("Draw/FatalError/"); 594 case ImageFatalError: return("Image/FatalError/"); 595 case WandFatalError: return("Wand/FatalError/"); 596 case XServerFatalError: return("XServer/FatalError/"); 597 case MonitorFatalError: return("Monitor/FatalError/"); 598 case RegistryFatalError: return("Registry/FatalError/"); 599 case ConfigureFatalError: return("Configure/FatalError/"); 600 case PolicyFatalError: return("Policy/FatalError/"); 601 default: break; 602 } 603 return(""); 604 } 605 606 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity, 607 const char *tag) 608 { 609 char 610 message[MagickPathExtent]; 611 612 const char 613 *locale_message; 614 615 assert(tag != (const char *) NULL); 616 (void) FormatLocaleString(message,MagickPathExtent,"Exception/%s%s", 617 ExceptionSeverityToTag(severity),tag); 618 locale_message=GetLocaleMessage(message); 619 if (locale_message == (const char *) NULL) 620 return(tag); 621 if (locale_message == message) 622 return(tag); 623 return(locale_message); 624 } 625 626 /* 628 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 629 % % 630 % % 631 % % 632 % I n h e r i t E x c e p t i o n % 633 % % 634 % % 635 % % 636 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 637 % 638 % InheritException() inherits an exception from a related exception. 639 % 640 % The format of the InheritException method is: 641 % 642 % InheritException(ExceptionInfo *exception,const ExceptionInfo *relative) 643 % 644 % A description of each parameter follows: 645 % 646 % o exception: the exception info. 647 % 648 % o relative: the related exception info. 649 % 650 */ 651 MagickExport void InheritException(ExceptionInfo *exception, 652 const ExceptionInfo *relative) 653 { 654 register const ExceptionInfo 655 *p; 656 657 assert(exception != (ExceptionInfo *) NULL); 658 assert(exception->signature == MagickCoreSignature); 659 assert(relative != (ExceptionInfo *) NULL); 660 assert(relative->signature == MagickCoreSignature); 661 assert(exception != relative); 662 if (relative->exceptions == (void *) NULL) 663 return; 664 LockSemaphoreInfo(relative->semaphore); 665 ResetLinkedListIterator((LinkedListInfo *) relative->exceptions); 666 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *) 667 relative->exceptions); 668 while (p != (const ExceptionInfo *) NULL) 669 { 670 (void) ThrowException(exception,p->severity,p->reason,p->description); 671 p=(const ExceptionInfo *) GetNextValueInLinkedList((LinkedListInfo *) 672 relative->exceptions); 673 } 674 UnlockSemaphoreInfo(relative->semaphore); 675 } 676 677 /* 679 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 680 % % 681 % % 682 % % 683 % I n i t i a l i z e t E x c e p t i o n I n f o % 684 % % 685 % % 686 % % 687 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 688 % 689 % InitializeExceptionInfo() initializes an exception to default values. 690 % 691 % The format of the InitializeExceptionInfo method is: 692 % 693 % InitializeExceptionInfo(ExceptionInfo *exception) 694 % 695 % A description of each parameter follows: 696 % 697 % o exception: the exception info. 698 % 699 */ 700 MagickPrivate void InitializeExceptionInfo(ExceptionInfo *exception) 701 { 702 assert(exception != (ExceptionInfo *) NULL); 703 (void) ResetMagickMemory(exception,0,sizeof(*exception)); 704 exception->severity=UndefinedException; 705 exception->exceptions=(void *) NewLinkedList(0); 706 exception->semaphore=AcquireSemaphoreInfo(); 707 exception->signature=MagickCoreSignature; 708 } 709 710 /* 712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 713 % % 714 % % 715 % % 716 % M a g i c k E r r o r % 717 % % 718 % % 719 % % 720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 721 % 722 % MagickError() calls the exception handler methods with an error reason. 723 % 724 % The format of the MagickError method is: 725 % 726 % void MagickError(const ExceptionType error,const char *reason, 727 % const char *description) 728 % 729 % A description of each parameter follows: 730 % 731 % o exception: Specifies the numeric error category. 732 % 733 % o reason: Specifies the reason to display before terminating the 734 % program. 735 % 736 % o description: Specifies any description to the reason. 737 % 738 */ 739 MagickExport void MagickError(const ExceptionType error,const char *reason, 740 const char *description) 741 { 742 if (error_handler != (ErrorHandler) NULL) 743 (*error_handler)(error,reason,description); 744 } 745 746 /* 748 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 749 % % 750 % % 751 % % 752 % M a g i c k F a t al E r r o r % 753 % % 754 % % 755 % % 756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 757 % 758 % MagickFatalError() calls the fatal exception handler methods with an error 759 % reason. 760 % 761 % The format of the MagickError method is: 762 % 763 % void MagickFatalError(const ExceptionType error,const char *reason, 764 % const char *description) 765 % 766 % A description of each parameter follows: 767 % 768 % o exception: Specifies the numeric error category. 769 % 770 % o reason: Specifies the reason to display before terminating the 771 % program. 772 % 773 % o description: Specifies any description to the reason. 774 % 775 */ 776 MagickExport void MagickFatalError(const ExceptionType error,const char *reason, 777 const char *description) 778 { 779 if (fatal_error_handler != (ErrorHandler) NULL) 780 (*fatal_error_handler)(error,reason,description); 781 } 782 783 /* 785 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 786 % % 787 % % 788 % % 789 % M a g i c k W a r n i n g % 790 % % 791 % % 792 % % 793 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 794 % 795 % MagickWarning() calls the warning handler methods with a warning reason. 796 % 797 % The format of the MagickWarning method is: 798 % 799 % void MagickWarning(const ExceptionType warning,const char *reason, 800 % const char *description) 801 % 802 % A description of each parameter follows: 803 % 804 % o warning: the warning severity. 805 % 806 % o reason: Define the reason for the warning. 807 % 808 % o description: Describe the warning. 809 % 810 */ 811 MagickExport void MagickWarning(const ExceptionType warning,const char *reason, 812 const char *description) 813 { 814 if (warning_handler != (WarningHandler) NULL) 815 (*warning_handler)(warning,reason,description); 816 } 817 818 /* 820 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 821 % % 822 % % 823 % % 824 % S e t E r r o r H a n d l e r % 825 % % 826 % % 827 % % 828 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 829 % 830 % SetErrorHandler() sets the exception handler to the specified method 831 % and returns the previous exception handler. 832 % 833 % The format of the SetErrorHandler method is: 834 % 835 % ErrorHandler SetErrorHandler(ErrorHandler handler) 836 % 837 % A description of each parameter follows: 838 % 839 % o handler: the method to handle errors. 840 % 841 */ 842 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler) 843 { 844 ErrorHandler 845 previous_handler; 846 847 previous_handler=error_handler; 848 error_handler=handler; 849 return(previous_handler); 850 } 851 852 /* 854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 855 % % 856 % % 857 % % 858 % S e t F a t a l E r r o r H a n d l e r % 859 % % 860 % % 861 % % 862 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 863 % 864 % SetFatalErrorHandler() sets the fatal exception handler to the specified 865 % method and returns the previous fatal exception handler. 866 % 867 % The format of the SetErrorHandler method is: 868 % 869 % ErrorHandler SetErrorHandler(ErrorHandler handler) 870 % 871 % A description of each parameter follows: 872 % 873 % o handler: the method to handle errors. 874 % 875 */ 876 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler) 877 { 878 FatalErrorHandler 879 previous_handler; 880 881 previous_handler=fatal_error_handler; 882 fatal_error_handler=handler; 883 return(previous_handler); 884 } 885 886 /* 888 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 889 % % 890 % % 891 % % 892 % S e t W a r n i n g H a n d l e r % 893 % % 894 % % 895 % % 896 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 897 % 898 % SetWarningHandler() sets the warning handler to the specified method 899 % and returns the previous warning handler. 900 % 901 % The format of the SetWarningHandler method is: 902 % 903 % ErrorHandler SetWarningHandler(ErrorHandler handler) 904 % 905 % A description of each parameter follows: 906 % 907 % o handler: the method to handle warnings. 908 % 909 */ 910 MagickExport WarningHandler SetWarningHandler(WarningHandler handler) 911 { 912 WarningHandler 913 previous_handler; 914 915 previous_handler=warning_handler; 916 warning_handler=handler; 917 return(previous_handler); 918 } 919 920 /* 922 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 923 % % 924 % % 925 % % 926 % T h r o w E x c e p t i o n % 927 % % 928 % % 929 % % 930 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 931 % 932 % ThrowException() throws an exception with the specified severity code, 933 % reason, and optional description. 934 % 935 % The format of the ThrowException method is: 936 % 937 % MagickBooleanType ThrowException(ExceptionInfo *exception, 938 % const ExceptionType severity,const char *reason, 939 % const char *description) 940 % 941 % A description of each parameter follows: 942 % 943 % o exception: the exception info. 944 % 945 % o severity: the severity of the exception. 946 % 947 % o reason: the reason for the exception. 948 % 949 % o description: the exception description. 950 % 951 */ 952 MagickExport MagickBooleanType ThrowException(ExceptionInfo *exception, 953 const ExceptionType severity,const char *reason,const char *description) 954 { 955 register ExceptionInfo 956 *p; 957 958 assert(exception != (ExceptionInfo *) NULL); 959 assert(exception->signature == MagickCoreSignature); 960 LockSemaphoreInfo(exception->semaphore); 961 p=(ExceptionInfo *) GetLastValueInLinkedList((LinkedListInfo *) 962 exception->exceptions); 963 if ((p != (ExceptionInfo *) NULL) && (p->severity == severity) && 964 (LocaleCompare(exception->reason,reason) == 0) && 965 (LocaleCompare(exception->description,description) == 0)) 966 { 967 UnlockSemaphoreInfo(exception->semaphore); 968 return(MagickTrue); 969 } 970 p=(ExceptionInfo *) AcquireMagickMemory(sizeof(*p)); 971 if (p == (ExceptionInfo *) NULL) 972 { 973 UnlockSemaphoreInfo(exception->semaphore); 974 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 975 } 976 (void) ResetMagickMemory(p,0,sizeof(*p)); 977 p->severity=severity; 978 if (reason != (const char *) NULL) 979 p->reason=ConstantString(reason); 980 if (description != (const char *) NULL) 981 p->description=ConstantString(description); 982 p->signature=MagickCoreSignature; 983 (void) AppendValueToLinkedList((LinkedListInfo *) exception->exceptions,p); 984 if (p->severity >= exception->severity) 985 { 986 exception->severity=p->severity; 987 exception->reason=p->reason; 988 exception->description=p->description; 989 } 990 UnlockSemaphoreInfo(exception->semaphore); 991 return(MagickTrue); 992 } 993 994 /* 996 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 997 % % 998 % % 999 % % 1000 % T h r o w M a g i c k E x c e p t i o n % 1001 % % 1002 % % 1003 % % 1004 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 1005 % 1006 % ThrowMagickException logs an exception as determined by the log 1007 % configuration file. If an error occurs, MagickFalse is returned 1008 % otherwise MagickTrue. 1009 % 1010 % The format of the ThrowMagickException method is: 1011 % 1012 % MagickBooleanType ThrowFileException(ExceptionInfo *exception, 1013 % const char *module,const char *function,const size_t line, 1014 % const ExceptionType severity,const char *tag,const char *format,...) 1015 % 1016 % A description of each parameter follows: 1017 % 1018 % o exception: the exception info. 1019 % 1020 % o filename: the source module filename. 1021 % 1022 % o function: the function name. 1023 % 1024 % o line: the line number of the source module. 1025 % 1026 % o severity: Specifies the numeric error category. 1027 % 1028 % o tag: the locale tag. 1029 % 1030 % o format: the output format. 1031 % 1032 */ 1033 1034 MagickExport MagickBooleanType ThrowMagickExceptionList( 1035 ExceptionInfo *exception,const char *module,const char *function, 1036 const size_t line,const ExceptionType severity,const char *tag, 1037 const char *format,va_list operands) 1038 { 1039 char 1040 message[MagickPathExtent], 1041 path[MagickPathExtent], 1042 reason[MagickPathExtent]; 1043 1044 const char 1045 *locale, 1046 *type; 1047 1048 int 1049 n; 1050 1051 MagickBooleanType 1052 status; 1053 1054 size_t 1055 length; 1056 1057 assert(exception != (ExceptionInfo *) NULL); 1058 assert(exception->signature == MagickCoreSignature); 1059 locale=GetLocaleExceptionMessage(severity,tag); 1060 (void) CopyMagickString(reason,locale,MagickPathExtent); 1061 (void) ConcatenateMagickString(reason," ",MagickPathExtent); 1062 length=strlen(reason); 1063 #if defined(MAGICKCORE_HAVE_VSNPRINTF) 1064 n=vsnprintf(reason+length,MagickPathExtent-length,format,operands); 1065 #else 1066 n=vsprintf(reason+length,format,operands); 1067 #endif 1068 if (n < 0) 1069 reason[MagickPathExtent-1]='\0'; 1070 status=LogMagickEvent(ExceptionEvent,module,function,line,"%s",reason); 1071 GetPathComponent(module,TailPath,path); 1072 type="undefined"; 1073 if ((severity >= WarningException) && (severity < ErrorException)) 1074 type="warning"; 1075 if ((severity >= ErrorException) && (severity < FatalErrorException)) 1076 type="error"; 1077 if (severity >= FatalErrorException) 1078 type="fatal"; 1079 (void) FormatLocaleString(message,MagickPathExtent,"%s @ %s/%s/%s/%.20g",reason, 1080 type,path,function,(double) line); 1081 (void) ThrowException(exception,severity,message,(char *) NULL); 1082 return(status); 1083 } 1084 1085 MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, 1086 const char *module,const char *function,const size_t line, 1087 const ExceptionType severity,const char *tag,const char *format,...) 1088 { 1089 MagickBooleanType 1090 status; 1091 1092 va_list 1093 operands; 1094 1095 va_start(operands,format); 1096 status=ThrowMagickExceptionList(exception,module,function,line,severity,tag, 1097 format,operands); 1098 va_end(operands); 1099 return(status); 1100 } 1101