1 /*
2 % Copyright (C) 2003-2019 GraphicsMagick Group
3 % Copyright (C) 2002 ImageMagick Studio
4 % Copyright 1991-1999 E. I. du Pont de Nemours and Company
5 %
6 % This program is covered by multiple licenses, which are described in
7 % Copyright.txt. You should have received a copy of Copyright.txt with this
8 % package; otherwise see http://www.graphicsmagick.org/www/Copyright.html.
9 %
10 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
11 %                                                                             %
12 %                                                                             %
13 %                                                                             %
14 %                      EEEEE  RRRR   RRRR   OOO   RRRR                        %
15 %                      E      R   R  R   R O   O  R   R                       %
16 %                      EEE    RRRR   RRRR  O   O  RRRR                        %
17 %                      E      R R    R R   O   O  R R                         %
18 %                      EEEEE  R  R   R  R   OOO   R  R                        %
19 %                                                                             %
20 %                                                                             %
21 %                      GraphicsMagick Exception Methods                       %
22 %                                                                             %
23 %                                                                             %
24 %                             Software Design                                 %
25 %                               John Cristy                                   %
26 %                                July 1993                                    %
27 %                                                                             %
28 %                                                                             %
29 %                                                                             %
30 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
31 %
32 %
33 %
34 */
35 
36 /*
37   Include declarations.
38 */
39 #include "magick/studio.h"
40 #include "magick/magick.h"
41 #include "magick/semaphore.h"
42 #include "magick/utility.h"
43 
44 /*
45   Forward declarations.
46 */
47 #if defined(__cplusplus) || defined(c_plusplus)
48 extern "C" {
49 #endif
50 
51 static void
52   DefaultErrorHandler(const ExceptionType,const char *,const char *),
53   DefaultFatalErrorHandler(const ExceptionType,const char *,const char *) MAGICK_FUNC_NORETURN,
54   DefaultWarningHandler(const ExceptionType,const char *,const char *);
55 
56 #if defined(__cplusplus) || defined(c_plusplus)
57 }
58 #endif
59 
60 /*
61   Global declarations.
62 */
63 static SemaphoreInfo
64   *error_semaphore = (SemaphoreInfo *) NULL;
65 
66 static ErrorHandler
67   error_handler = DefaultErrorHandler;
68 
69 static FatalErrorHandler
70   fatal_error_handler = DefaultFatalErrorHandler;
71 
72 static WarningHandler
73   warning_handler = DefaultWarningHandler;
74 
75 /*
76 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
77 %                                                                             %
78 %                                                                             %
79 %                                                                             %
80 +   I n i t i a l i z e M a g i c k E x c e p t i o n H a n d l i n g         %
81 %                                                                             %
82 %                                                                             %
83 %                                                                             %
84 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
85 %
86 %  Method InitializeMagickExceptionHandling initializes the exception
87 %  reporting facility so that exception reporting is thread safe.
88 %  This function must be invoked before any exception is thrown.
89 %  A memory-allocation failure in this function results in a fatal
90 %  error for the whole program.  All of the allocations performed by
91 %  this function are released by DestroyMagickExceptionHandling().
92 %
93 %  The format of the InitializeLogInfo method is:
94 %
95 %      MagickPassFail InitializeLogInfo(void)
96 %
97 %
98 */
99 MagickPassFail
InitializeMagickExceptionHandling(void)100 InitializeMagickExceptionHandling(void)
101 {
102   /*
103     Initialize error-reporting semaphore
104   */
105   assert(error_semaphore == (SemaphoreInfo *) NULL);
106   error_semaphore=AllocateSemaphoreInfo();
107   return MagickPass;
108 }
109 
110 /*
111 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
112 %                                                                             %
113 %                                                                             %
114 %                                                                             %
115 +   D e s t r o y M a g i c k E x c e p t i o n H a n d l i n g               %
116 %                                                                             %
117 %                                                                             %
118 %                                                                             %
119 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
120 %
121 %  Method DestroyMagickExceptionHandling deallocates resources allocated
122 %  for exception handling.
123 %
124 %  The format of the DestroyLogInfo method is:
125 %
126 %      DestroyLogInfo(void)
127 %
128 %
129 */
DestroyMagickExceptionHandling(void)130 void DestroyMagickExceptionHandling(void)
131 {
132   /*
133     Destroy error-reporting semaphore
134   */
135   DestroySemaphoreInfo(&error_semaphore);
136 }
137 
138 /*
139 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
140 %                                                                             %
141 %                                                                             %
142 %                                                                             %
143 %   C a t c h E x c e p t i o n                                               %
144 %                                                                             %
145 %                                                                             %
146 %                                                                             %
147 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
148 %
149 %  CatchException() returns if no exceptions is found otherwise it reports
150 %  the exception as a warning, error, or fatal depending on the severity.
151 %
152 %  The format of the CatchException method is:
153 %
154 %      CatchException(const ExceptionInfo *exception)
155 %
156 %  A description of each parameter follows:
157 %
158 %    o exception: The exception info.
159 %
160 %
161 */
CatchException(const ExceptionInfo * exception)162 MagickExport void CatchException(const ExceptionInfo *exception)
163 {
164   assert(exception != (ExceptionInfo *) NULL);
165   assert(exception->signature == MagickSignature);
166 
167   do
168     {
169       if (exception->severity == UndefinedException)
170         break;
171       errno=exception->error_number; /* Shabby work-around for parameter limits */
172       if ((exception->severity >= WarningException) &&
173           (exception->severity < ErrorException))
174         {
175           MagickWarning2(exception->severity,exception->reason,
176                          exception->description);
177           break;
178         }
179       if ((exception->severity >= ErrorException) &&
180           (exception->severity < FatalErrorException))
181         {
182           MagickError2(exception->severity,exception->reason,exception->description);
183           break;
184         }
185       if (exception->severity >= FatalErrorException)
186         {
187           MagickFatalError2(exception->severity,exception->reason,
188                             exception->description);
189           break;
190         }
191     } while(0);
192 }
193 
194 /*
195 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
196 %                                                                             %
197 %                                                                             %
198 %                                                                             %
199 %  C o p y E x c e p t i o n                                                  %
200 %                                                                             %
201 %                                                                             %
202 %                                                                             %
203 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
204 %
205 %  CopyException() copies exception data from one ExceptionInfo structure
206 %  to another.
207 %
208 %  The format of the CopyException method is:
209 %
210 %      void CopyException(ExceptionInfo *copy, const ExceptionInfo *original)
211 %
212 %  A description of each parameter follows:
213 %
214 %    o copy: The exception to copy to.
215 %
216 %    o original: The exception to copy from.
217 %
218 */
CopyException(ExceptionInfo * copy,const ExceptionInfo * original)219 MagickExport void CopyException(ExceptionInfo *copy, const ExceptionInfo *original)
220 {
221   assert(copy != (ExceptionInfo *) NULL);
222   assert(copy->signature == MagickSignature);
223   assert(original != (ExceptionInfo *) NULL);
224   assert(copy != original);
225   assert(original->signature == MagickSignature);
226   copy->severity=original->severity;
227   MagickFreeMemory(copy->reason);
228   if (original->reason)
229     copy->reason=AcquireString(original->reason);
230   MagickFreeMemory(copy->description);
231   if (original->description)
232     copy->description=AcquireString(original->description);
233   copy->error_number=original->error_number;
234   MagickFreeMemory(copy->module);
235   if (original->module)
236     copy->module=AcquireString(original->module);
237   MagickFreeMemory(copy->function);
238   if (original->function)
239     copy->function=AcquireString(original->function);
240   copy->line=original->line;
241   return;
242 }
243 
244 /*
245 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
246 %                                                                             %
247 %                                                                             %
248 %                                                                             %
249 +   D e f a u l t E r r o r H a n d l e r                                     %
250 %                                                                             %
251 %                                                                             %
252 %                                                                             %
253 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
254 %
255 %  Method DefaultErrorHandler displays an error reason.
256 %
257 %  The format of the DefaultErrorHandler method is:
258 %
259 %      void DefaultMagickError(const ExceptionType severity,
260 %        const char *reason, const char *description)
261 %
262 %  A description of each parameter follows:
263 %
264 %    o severity: Specifies the numeric error category.
265 %
266 %    o reason: Specifies the reason to display before terminating the
267 %      program.
268 %
269 %    o description: Specifies any description to the reason.
270 %
271 %
272 */
273 
GetErrorMessageString(const int error_number)274 static const char *GetErrorMessageString(const int error_number)
275 {
276   const char
277     *message;
278 
279   message=strerror(error_number);
280   if (message == (const char *) NULL)
281     return("Error number is out of range");
282   return(message);
283 }
284 
DefaultErrorHandler(const ExceptionType severity,const char * reason,const char * description)285 static void DefaultErrorHandler(const ExceptionType severity,const char *reason,
286   const char *description)
287 {
288   if (reason == (char *) NULL)
289     return;
290 
291   (void) fprintf(stderr,"%.1024s: ",GetClientName());
292   if (strstr(reason,"%s") && description)
293     {
294       /*
295         Reason contains printf specification. %s in reason string
296         is substituted with description.
297       */
298       (void) fprintf(stderr,reason,description);
299     }
300   else
301     {
302       (void) fprintf(stderr,"%.1024s",reason);
303       if (description != (char *) NULL)
304         (void) fprintf(stderr," (%.1024s)",description);
305     }
306   /*
307     FIXME: The following captures a random errno value rather than the
308     errno associated with the actual error.
309   */
310   if ((severity != OptionError) && errno)
311     (void) fprintf(stderr," [%.1024s]",GetErrorMessageString(errno));
312   (void) fprintf(stderr,".\n");
313 }
314 
315 /*
316 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
317 %                                                                             %
318 %                                                                             %
319 %                                                                             %
320 +   D e f a u l t F a t a l E r r o r H a n d l e r                           %
321 %                                                                             %
322 %                                                                             %
323 %                                                                             %
324 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
325 %
326 %  Method DefaultFatalErrorHandler displays an error reason and then terminates
327 %  the program.
328 %
329 %  The format of the DefaultFatalErrorHandler method is:
330 %
331 %      void DefaultMagickFatalError(const ExceptionType severity,
332 %        const char *reason, const char *description)
333 %
334 %  A description of each parameter follows:
335 %
336 %    o severity: Specifies the numeric error category.
337 %
338 %    o reason: Specifies the reason to display before terminating the
339 %      program.
340 %
341 %    o description: Specifies any description to the reason.
342 %
343 %
344 */
DefaultFatalErrorHandler(const ExceptionType severity,const char * reason,const char * description)345 static void DefaultFatalErrorHandler(const ExceptionType severity,
346   const char *reason,const char *description)
347 {
348   if (reason != (char *) NULL)
349     {
350       (void) fprintf(stderr,"%.1024s: %.1024s",GetClientName(),reason);
351       if (description != (char *) NULL)
352         (void) fprintf(stderr," (%.1024s)",description);
353       if ((severity != OptionError) && errno)
354         (void) fprintf(stderr," [%.1024s]",GetErrorMessageString(errno));
355       (void) fprintf(stderr,".\n");
356     }
357   /*
358     Release persistent resources
359   */
360   PanicDestroyMagick();
361   /*
362     Program quits
363   */
364   Exit(severity);
365 }
366 
367 /*
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 %  Method DefaultWarningHandler displays a warning reason.
379 %
380 %  The format of the DefaultWarningHandler method is:
381 %
382 %      void DefaultWarningHandler(const ExceptionType warning,
383 %        const char *reason,const char *description)
384 %
385 %  A description of each parameter follows:
386 %
387 %    o warning: 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 */
DefaultWarningHandler(const ExceptionType severity,const char * reason,const char * description)396 static void DefaultWarningHandler(const ExceptionType severity,
397   const char *reason,const char *description)
398 {
399   if (reason == (char *) NULL)
400     return;
401   (void) fprintf(stderr,"%.1024s: %.1024s",GetClientName(),reason);
402   if (description != (char *) NULL)
403     (void) fprintf(stderr," (%.1024s)",description);
404   if ((severity != OptionWarning) && errno)
405     (void) fprintf(stderr," [%.1024s]",GetErrorMessageString(errno));
406   (void) fprintf(stderr,".\n");
407 }
408 
409 /*
410 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
411 %                                                                             %
412 %                                                                             %
413 %                                                                             %
414 %   D e s t r o y E x c e p t i o n I n f o                                   %
415 %                                                                             %
416 %                                                                             %
417 %                                                                             %
418 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
419 %
420 %  DestroyExceptionInfo() deallocates memory associated with exception.
421 %
422 %  The format of the DestroyExceptionInfo method is:
423 %
424 %      void DestroyExceptionInfo(ExceptionInfo *exception)
425 %
426 %  A description of each parameter follows:
427 %
428 %    o exception: The exception info.
429 %
430 %
431 */
DestroyExceptionInfo(ExceptionInfo * exception)432 MagickExport void DestroyExceptionInfo(ExceptionInfo *exception)
433 {
434   assert(exception != (ExceptionInfo *) NULL);
435   assert(exception->signature == MagickSignature);
436   exception->severity=UndefinedException;
437   MagickFreeMemory(exception->reason);
438   MagickFreeMemory(exception->description);
439   exception->error_number=0;
440   MagickFreeMemory(exception->module);
441   MagickFreeMemory(exception->function);
442   exception->line=0UL;
443   exception->signature=0UL;
444 }
445 
446 /*
447 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
448 %                                                                             %
449 %                                                                             %
450 %                                                                             %
451 %   G e t E x c e p t i o n I n f o                                           %
452 %                                                                             %
453 %                                                                             %
454 %                                                                             %
455 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
456 %
457 %  GetExceptionInfo() initializes an exception to default values.
458 %
459 %  The format of the GetExceptionInfo method is:
460 %
461 %      GetExceptionInfo(ExceptionInfo *exception)
462 %
463 %  A description of each parameter follows:
464 %
465 %    o exception: The exception info.
466 %
467 %
468 */
GetExceptionInfo(ExceptionInfo * exception)469 MagickExport void GetExceptionInfo(ExceptionInfo *exception)
470 {
471   assert(exception != (ExceptionInfo *) NULL);
472   exception->severity=UndefinedException;
473   exception->reason=0;
474   exception->description=0;
475   exception->error_number=0;
476   exception->module=0;
477   exception->function=0;
478   exception->line=0UL;
479   exception->signature=MagickSignature;
480 }
481 
482 /*
483 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
484 %                                                                             %
485 %                                                                             %
486 %                                                                             %
487 %   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                         %
488 %                                                                             %
489 %                                                                             %
490 %                                                                             %
491 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
492 %
493 %  GetLocaleExceptionMessage() converts a enumerated exception severity and tag
494 %  to a message in the current locale.
495 %
496 %  The format of the GetLocaleExceptionMessage method is:
497 %
498 %      const char *GetLocaleExceptionMessage(const ExceptionType severity,
499 %        const char *tag)
500 %
501 %  A description of each parameter follows:
502 %
503 %    o severity: the severity of the exception.
504 %
505 %    o tag: the message tag.
506 %
507 %
508 %
509 */
510 
ExceptionSeverityToTag(const ExceptionType severity)511 static const char *ExceptionSeverityToTag(const ExceptionType severity)
512 {
513   switch (severity)
514   {
515     case UndefinedException: return("Unknown/Error/");
516     case ResourceLimitWarning: return("Resource/Limit/Warning/");
517     case TypeWarning: return("Type/Warning/");
518     case OptionWarning: return("Option/Warning/");
519     case DelegateWarning: return("Delegate/Warning/");
520     case MissingDelegateWarning: return("Missing/Delegate/Warning/");
521     case CorruptImageWarning: return("Corrupt/Image/Warning/");
522     case FileOpenWarning: return("File/Open/Warning/");
523     case BlobWarning: return("Blob/Warning/");
524     case StreamWarning: return("Stream/Warning/");
525     case CacheWarning: return("Cache/Warning/");
526     case CoderWarning: return("Coder/Warning/");
527     case ModuleWarning: return("Module/Warning/");
528     case DrawWarning: return("Draw/Warning/");
529     case ImageWarning: return("Image/Warning/");
530     case WandWarning: return("Wand/Warning/");
531     case XServerWarning: return("XServer/Warning/");
532     case MonitorWarning: return("Monitor/Warning/");
533     case RegistryWarning: return("Registry/Warning/");
534     case ConfigureWarning: return("Configure/Warning/");
535     case ResourceLimitError: return("Resource/Limit/Error/");
536     case TypeError: return("Type/Error/");
537     case OptionError: return("Option/Error/");
538     case DelegateError: return("Delegate/Error/");
539     case MissingDelegateError: return("Missing/Delegate/Error/");
540     case CorruptImageError: return("Corrupt/Image/Error/");
541     case FileOpenError: return("File/Open/Error/");
542     case BlobError: return("Blob/Error/");
543     case StreamError: return("Stream/Error/");
544     case CacheError: return("Cache/Error/");
545     case CoderError: return("Coder/Error/");
546     case ModuleError: return("Module/Error/");
547     case DrawError: return("Draw/Error/");
548     case ImageError: return("Image/Error/");
549     case WandError: return("Wand/Error/");
550     case XServerError: return("XServer/Error/");
551     case MonitorError: return("Monitor/Error/");
552     case RegistryError: return("Registry/Error/");
553     case ConfigureError: return("Configure/Error/");
554     case ResourceLimitFatalError: return("Resource/Limit/FatalError/");
555     case TypeFatalError: return("Type/FatalError/");
556     case OptionFatalError: return("Option/FatalError/");
557     case DelegateFatalError: return("Delegate/FatalError/");
558     case MissingDelegateFatalError: return("Missing/Delegate/FatalError/");
559     case CorruptImageFatalError: return("Corrupt/Image/FatalError/");
560     case FileOpenFatalError: return("File/Open/FatalError/");
561     case BlobFatalError: return("Blob/FatalError/");
562     case StreamFatalError: return("Stream/FatalError/");
563     case CacheFatalError: return("Cache/FatalError/");
564     case CoderFatalError: return("Coder/FatalError/");
565     case ModuleFatalError: return("Module/FatalError/");
566     case DrawFatalError: return("Draw/FatalError/");
567     case ImageFatalError: return("Image/FatalError/");
568     case WandFatalError: return("Wand/FatalError/");
569     case XServerFatalError: return("XServer/FatalError/");
570     case MonitorFatalError: return("Monitor/FatalError/");
571     case RegistryFatalError: return("Registry/FatalError/");
572     case ConfigureFatalError: return("Configure/FatalError/");
573     default: break;
574   }
575   return("");
576 }
577 
GetLocaleExceptionMessage(const ExceptionType severity,const char * tag)578 MagickExport const char *GetLocaleExceptionMessage(const ExceptionType severity,
579   const char *tag)
580 {
581   char
582     message[MaxTextExtent];
583 
584   const char
585     *locale_message;
586 
587   /* protect against NULL lookups */
588   if (tag != (char *) NULL)
589     {
590       /* This is a hack that depends on the fact that tag can never have spaces in
591         them. If a space is found then it means we are being asked to translate a
592         message that has already been translated. A big waste of time. The reason
593         this happens is that messages are translated at the point of an exception
594         and then again when the exception is caught and processed via the default
595         error and warning handlers
596       */
597       if (strrchr(tag, ' '))
598         return tag;
599       FormatString(message,"%.1024s%.1024s",ExceptionSeverityToTag(severity),tag);
600       locale_message=GetLocaleMessage(message);
601       if (locale_message == message)
602         return(tag);
603       return(locale_message);
604    }
605   return(tag);
606 }
607 
608 /*
609 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
610 %                                                                             %
611 %                                                                             %
612 %                                                                             %
613 %   M a g i c k E r r o r                                                     %
614 %                                                                             %
615 %                                                                             %
616 %                                                                             %
617 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
618 %
619 %  Method MagickError calls the error handler methods with an error reason.
620 %
621 %  The format of the MagickError method is:
622 %
623 %      void MagickError(const ExceptionType error,const char *reason,
624 %        const char *description)
625 %
626 %  A description of each parameter follows:
627 %
628 %    o exception: Specifies the numeric error category.
629 %
630 %    o reason: Specifies the reason to display before terminating the
631 %      program.
632 %
633 %    o description: Specifies any description to the reason.
634 %
635 %
636 */
637 #if defined(MagickError)
_MagickError(const ExceptionType error,const char * reason,const char * description)638 MagickExport void _MagickError(const ExceptionType error,const char *reason,
639   const char *description)
640 {
641   if (error_handler != (ErrorHandler) NULL)
642     (*error_handler)(error,GetLocaleExceptionMessage(error,reason),
643       GetLocaleExceptionMessage(error,description));
644 }
645 #endif
646 #if !defined(PREFIX_MAGICK_SYMBOLS)
647 #undef MagickError
MagickError(const ExceptionType error,const char * reason,const char * description)648 MagickExport void MagickError(const ExceptionType error,const char *reason,
649   const char *description)
650 {
651   if (error_handler != (ErrorHandler) NULL)
652     (*error_handler)(error,GetLocaleExceptionMessage(error,reason),
653       GetLocaleExceptionMessage(error,description));
654 }
655 #endif
656 
657 /*
658 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
659 %                                                                             %
660 %                                                                             %
661 %                                                                             %
662 %   M a g i c k F a t a l E r r o r                                           %
663 %                                                                             %
664 %                                                                             %
665 %                                                                             %
666 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
667 %
668 %  MagickFatalError() calls the fatal error handler methods with an error
669 %  reason.  The fatal error handler is not expected to return!
670 %
671 %  The format of the MagickFatalError method is:
672 %
673 %      void MagickFatalError(const ExceptionType error,const char *reason,
674 %        const char *description)
675 %
676 %  A description of each parameter follows:
677 %
678 %    o exception: Specifies the numeric error category.
679 %
680 %    o reason: Specifies the reason to display before terminating the
681 %      program.
682 %
683 %    o description: Specifies any description to the reason.
684 %
685 %
686 */
687 #if defined(MagickFatalError)
_MagickFatalError(const ExceptionType error,const char * reason,const char * description)688 MagickExport void _MagickFatalError(const ExceptionType error,const char *reason,
689   const char *description)
690 {
691   if (fatal_error_handler != (ErrorHandler) NULL)
692     (*fatal_error_handler)(error,GetLocaleExceptionMessage(error,reason),
693       GetLocaleExceptionMessage(error,description));
694   errno=0;
695   abort();
696 }
697 #endif
698 #if !defined(PREFIX_MAGICK_SYMBOLS)
699 #undef MagickFatalError
MagickFatalError(const ExceptionType error,const char * reason,const char * description)700 MagickExport void MagickFatalError(const ExceptionType error,const char *reason,
701   const char *description)
702 {
703   if (fatal_error_handler != (ErrorHandler) NULL)
704     (*fatal_error_handler)(error,GetLocaleExceptionMessage(error,reason),
705       GetLocaleExceptionMessage(error,description));
706   errno=0;
707   abort();
708 }
709 #endif
710 
711 /*
712 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
713 %                                                                             %
714 %                                                                             %
715 %                                                                             %
716 %   M a g i c k W a r n i n g                                                 %
717 %                                                                             %
718 %                                                                             %
719 %                                                                             %
720 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
721 %
722 %  Method MagickWarning calls the warning handler methods with a warning
723 %  reason.
724 %
725 %  The format of the MagickWarning method is:
726 %
727 %      void MagickWarning(const ExceptionType warning,const char *reason,
728 %        const char *description)
729 %
730 %  A description of each parameter follows:
731 %
732 %    o warning: The warning severity.
733 %
734 %    o reason: Define the reason for the warning.
735 %
736 %    o description: Describe the warning.
737 %
738 %
739 */
740 #if defined(MagickWarning)
_MagickWarning(const ExceptionType warning,const char * reason,const char * description)741 MagickExport void _MagickWarning(const ExceptionType warning,const char *reason,
742   const char *description)
743 {
744   if (warning_handler != (WarningHandler) NULL)
745     (*warning_handler)(warning,GetLocaleExceptionMessage(warning,reason),
746       GetLocaleExceptionMessage(warning,description));
747 }
748 #endif
749 #if !defined(PREFIX_MAGICK_SYMBOLS)
750 #undef MagickWarning
MagickWarning(const ExceptionType warning,const char * reason,const char * description)751 MagickExport void MagickWarning(const ExceptionType warning,const char *reason,
752   const char *description)
753 {
754   if (warning_handler != (WarningHandler) NULL)
755     (*warning_handler)(warning,GetLocaleExceptionMessage(warning,reason),
756       GetLocaleExceptionMessage(warning,description));
757 }
758 #endif
759 
760 /*
761 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
762 %                                                                             %
763 %                                                                             %
764 %                                                                             %
765 %   S e t E r r o r H a n d l e r                                             %
766 %                                                                             %
767 %                                                                             %
768 %                                                                             %
769 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
770 %
771 %  SetErrorHandler() sets the error handler to the specified method
772 %  and returns the previous error handler.
773 %
774 %  The format of the SetErrorHandler method is:
775 %
776 %      ErrorHandler SetErrorHandler(ErrorHandler handler)
777 %
778 %  A description of each parameter follows:
779 %
780 %    o handler: The method to handle errors.
781 %
782 %
783 */
SetErrorHandler(ErrorHandler handler)784 MagickExport ErrorHandler SetErrorHandler(ErrorHandler handler)
785 {
786   ErrorHandler
787     previous_handler;
788 
789   LockSemaphoreInfo(error_semaphore);
790   previous_handler=error_handler;
791   error_handler=handler;
792   UnlockSemaphoreInfo(error_semaphore);
793   return(previous_handler);
794 }
795 
796 /*
797 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
798 %                                                                             %
799 %                                                                             %
800 %                                                                             %
801 %   S e t E x c e p t i o n I n f o                                           %
802 %                                                                             %
803 %                                                                             %
804 %                                                                             %
805 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
806 %
807 %  SetExceptionInfo() set the exception severity.
808 %
809 %  The format of the SetExceptionInfo method is:
810 %
811 %      SetExceptionInfo(ExceptionInfo *exception,ExceptionType severity)
812 %
813 %  A description of each parameter follows:
814 %
815 %    o exception: The exception info.
816 %
817 %    o severity: The exception severity.
818 %
819 %
820 */
SetExceptionInfo(ExceptionInfo * exception,ExceptionType severity)821 MagickExport void SetExceptionInfo(ExceptionInfo *exception,
822   ExceptionType severity)
823 {
824   assert(exception != (ExceptionInfo *) NULL);
825   LockSemaphoreInfo(error_semaphore);
826   exception->severity=severity;
827   errno=0;
828   UnlockSemaphoreInfo(error_semaphore);
829 }
830 
831 /*
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 %                                                                             %
834 %                                                                             %
835 %                                                                             %
836 %   S e t F a t a l E r r o r H a n d l e r                                   %
837 %                                                                             %
838 %                                                                             %
839 %                                                                             %
840 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
841 %
842 %  SetFatalErrorHandler() sets the fatal error handler to the specified method
843 %  and returns the previous fatal error handler.
844 %
845 %  The format of the SetFatalErrorHandler method is:
846 %
847 %      FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
848 %
849 %  A description of each parameter follows:
850 %
851 %    o handler: The method to handle errors.
852 %
853 %
854 */
SetFatalErrorHandler(FatalErrorHandler handler)855 MagickExport FatalErrorHandler SetFatalErrorHandler(FatalErrorHandler handler)
856 {
857   FatalErrorHandler
858     previous_handler;
859 
860   LockSemaphoreInfo(error_semaphore);
861   previous_handler=fatal_error_handler;
862   fatal_error_handler=handler;
863   UnlockSemaphoreInfo(error_semaphore);
864   return(previous_handler);
865 }
866 
867 /*
868 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
869 %                                                                             %
870 %                                                                             %
871 %                                                                             %
872 %   S e t W a r n i n g H a n d l e r                                         %
873 %                                                                             %
874 %                                                                             %
875 %                                                                             %
876 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
877 %
878 %  SetWarningHandler() sets the warning handler to the specified method
879 %  and returns the previous warning handler.
880 %
881 %  The format of the SetWarningHandler method is:
882 %
883 %      ErrorHandler SetWarningHandler(ErrorHandler handler)
884 %
885 %  A description of each parameter follows:
886 %
887 %    o handler: The method to handle warnings.
888 %
889 %
890 */
SetWarningHandler(WarningHandler handler)891 MagickExport WarningHandler SetWarningHandler(WarningHandler handler)
892 {
893   WarningHandler
894     previous_handler;
895 
896   LockSemaphoreInfo(error_semaphore);
897   previous_handler=warning_handler;
898   warning_handler=handler;
899   UnlockSemaphoreInfo(error_semaphore);
900   return(previous_handler);
901 }
902 
903 /*
904 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
905 %                                                                             %
906 %                                                                             %
907 %                                                                             %
908 %   T h r o w E x c e p t i o n                                               %
909 %                                                                             %
910 %                                                                             %
911 %                                                                             %
912 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
913 %
914 %  ThrowException() throws an exception with the specified severity code,
915 %  reason, and optional description.
916 %
917 %  The format of the ThrowException method is:
918 %
919 %      void ThrowException(ExceptionInfo *exception,
920 %        const ExceptionType severity,const char *reason,
921 %        const char *description)
922 %
923 %  A description of each parameter follows:
924 %
925 %    o exception: The exception.
926 %
927 %    o severity: The severity of the exception.
928 %
929 %    o reason: The reason of the exception.
930 %
931 %    o description: The exception description.
932 %
933 %
934 */
935 #if !defined(PREFIX_MAGICK_SYMBOLS)
936 #undef ThrowException
ThrowException(ExceptionInfo * exception,const ExceptionType severity,const char * reason,const char * description)937 MagickExport void ThrowException(ExceptionInfo *exception,
938   const ExceptionType severity,const char *reason,const char *description)
939 {
940   const int orig_errno=errno;
941   assert(exception != (ExceptionInfo *) NULL);
942   assert(exception->signature == MagickSignature);
943   LockSemaphoreInfo(error_semaphore);
944   exception->severity=(ExceptionType) severity;
945   {
946     char *new_reason=NULL;
947     if (reason)
948       new_reason=AcquireString(GetLocaleExceptionMessage(severity,reason));
949     MagickFreeMemory(exception->reason);
950     exception->reason=new_reason;
951   }
952   {
953     char *new_description=NULL;
954     if (description)
955       new_description=
956         AcquireString(GetLocaleExceptionMessage(severity,description));
957     MagickFreeMemory(exception->description);
958     exception->description=new_description;
959   }
960   exception->error_number=orig_errno;
961   MagickFreeMemory(exception->module);
962   MagickFreeMemory(exception->function);
963   exception->line=0UL;
964   exception->signature=0UL;
965   UnlockSemaphoreInfo(error_semaphore);
966   return;
967 }
968 #endif
969 
970 /*
971 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
972 %                                                                             %
973 %                                                                             %
974 %                                                                             %
975 %   T h r o w L o g g e d E x c e p t i o n                                   %
976 %                                                                             %
977 %                                                                             %
978 %                                                                             %
979 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
980 %
981 %  ThrowLoggedException() throws an exception with the specified severity code,
982 %  reason, optional description, source filename, function name, and line
983 %  number. If logging is enabled, the exception is also logged.
984 %
985 %  If the exception already contains an ErrorException (or greater) or the
986 %  existing exception is more severe, then it is ignored.
987 %
988 %  The format of the ThrowLoggedException method is:
989 %
990 %      void ThrowLoggedException(ExceptionInfo *exception,
991 %        const ExceptionType severity,const char *reason,
992 %        const char *description,const char *module,
993 %        const char *function,const unsigned long line
994 %
995 %  A description of each parameter follows:
996 %
997 %    o exception: The exception.
998 %
999 %    o severity: The severity of the exception.
1000 %
1001 %    o reason: The reason of the exception.
1002 %
1003 %    o description: The exception description.
1004 %
1005 %    o filename: The source module filename.
1006 %
1007 %    o function: The function name.
1008 %
1009 %    o line: The line number of the source module.
1010 %
1011 %
1012 */
ThrowLoggedException(ExceptionInfo * exception,const ExceptionType severity,const char * reason,const char * description,const char * module,const char * function,const unsigned long line)1013 MagickExport void ThrowLoggedException(ExceptionInfo *exception,
1014                                        const ExceptionType severity,
1015                                        const char *reason,
1016                                        const char *description,
1017                                        const char *module,
1018                                        const char *function,
1019                                        const unsigned long line)
1020 {
1021   const int orig_errno=errno;
1022   MagickBool ignore = MagickFalse;
1023   assert(exception != (ExceptionInfo *) NULL);
1024   assert(function != (const char *) NULL);
1025   assert(exception->signature == MagickSignature);
1026   LockSemaphoreInfo(error_semaphore);
1027   if ((exception->severity > ErrorException) ||
1028       (exception->severity > severity))
1029     {
1030       if (reason)
1031         {
1032           if (description)
1033             (void) LogMagickEvent(severity,module,function,line,"Ignored: %.1024s (%.1024s)",
1034                                   reason,description);
1035           else
1036             (void) LogMagickEvent(severity,module,function,line,"Ignored: %.1024s",
1037                                   reason);
1038         }
1039       else
1040         {
1041           (void) LogMagickEvent(severity,module,function,line,
1042                                 "Ignored: exception contains no reason!");
1043         }
1044       ignore=MagickTrue;
1045     }
1046   if (!ignore)
1047     {
1048       exception->severity=(ExceptionType) severity;
1049 
1050       {
1051         char *new_reason = NULL;
1052         if (reason)
1053           new_reason=AcquireString(GetLocaleExceptionMessage(severity,reason));
1054         MagickFreeMemory(exception->reason);
1055         exception->reason=new_reason;
1056       }
1057 
1058       {
1059         char *new_description = NULL;
1060         if (description)
1061           new_description=AcquireString(GetLocaleExceptionMessage(severity,description));
1062         MagickFreeMemory(exception->description);
1063         exception->description=new_description;
1064       }
1065 
1066       exception->error_number=orig_errno;
1067       {
1068         char *new_module = NULL;
1069         if (module)
1070           new_module=AcquireString(module);
1071         MagickFreeMemory(exception->module);
1072         exception->module=new_module;
1073       }
1074 
1075       {
1076         char *new_function = NULL;
1077         if (function)
1078           new_function=AcquireString(function);
1079         MagickFreeMemory(exception->function);
1080         exception->function=new_function;
1081       }
1082 
1083       exception->line=line;
1084 
1085       if (exception->reason)
1086         {
1087           if (exception->description)
1088             (void) LogMagickEvent(severity,module,function,line,"%.1024s (%.1024s)",
1089                                   exception->reason,exception->description );
1090           else
1091             (void) LogMagickEvent(severity,module,function,line,"%.1024s",
1092                                   exception->reason);
1093         }
1094       else
1095         {
1096           (void) LogMagickEvent(severity,module,function,line,
1097                                 "exception contains no reason!");
1098         }
1099     }
1100   UnlockSemaphoreInfo(error_semaphore);
1101   return;
1102 }
1103