MagickCore  7.0.8
Convert, Edit, Or Compose Bitmap Images
log.c
Go to the documentation of this file.
1 /*
2 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
3 % %
4 % %
5 % %
6 % L OOO GGGG %
7 % L O O G %
8 % L O O G GG %
9 % L O O G G %
10 % LLLLL OOO GGG %
11 % %
12 % %
13 % MagickCore Log Events %
14 % %
15 % Software Design %
16 % Cristy %
17 % September 2002 %
18 % %
19 % %
20 % Copyright 1999-2018 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 /*
40  Include declarations.
41 */
42 #include "MagickCore/studio.h"
43 #include "MagickCore/blob.h"
44 #include "MagickCore/client.h"
45 #include "MagickCore/configure.h"
47 #include "MagickCore/exception.h"
49 #include "MagickCore/linked-list.h"
50 #include "MagickCore/log.h"
51 #include "MagickCore/log-private.h"
52 #include "MagickCore/memory_.h"
55 #include "MagickCore/option.h"
56 #include "MagickCore/semaphore.h"
57 #include "MagickCore/timer.h"
58 #include "MagickCore/string_.h"
60 #include "MagickCore/token.h"
61 #include "MagickCore/thread_.h"
63 #include "MagickCore/utility.h"
65 #include "MagickCore/version.h"
66 #include "MagickCore/xml-tree.h"
68 
69 /*
70  Define declarations.
71 */
72 #define LogFilename "log.xml"
73 
74 /*
75  Typedef declarations.
76 */
77 typedef enum
78 {
79  UndefinedHandler = 0x0000,
80  NoHandler = 0x0000,
81  ConsoleHandler = 0x0001,
82  StdoutHandler = 0x0002,
83  StderrHandler = 0x0004,
84  FileHandler = 0x0008,
85  DebugHandler = 0x0010,
86  EventHandler = 0x0020,
87  MethodHandler = 0x0040
89 
90 typedef struct _EventInfo
91 {
92  char
93  *name;
94 
97 } EventInfo;
98 
99 typedef struct _HandlerInfo
100 {
101  const char
103 
106 } HandlerInfo;
107 
108 struct _LogInfo
109 {
112 
115 
116  char
118  *name,
119  *filename,
120  *format;
121 
122  size_t
124  limit;
125 
126  FILE
128 
129  size_t
131 
134  stealth;
135 
136  TimerInfo
138 
139  size_t
141 
144 };
145 
146 typedef struct _LogMapInfo
147 {
148  const LogEventType
150 
151  const LogHandlerType
153 
154  const char
156  *format;
157 } LogMapInfo;
158 
159 /*
160  Static declarations.
161 */
162 static const HandlerInfo
164  {
165  { "Console", ConsoleHandler },
166  { "Debug", DebugHandler },
167  { "Event", EventHandler },
168  { "File", FileHandler },
169  { "None", NoHandler },
170  { "Stderr", StderrHandler },
171  { "Stdout", StdoutHandler },
172  { (char *) NULL, UndefinedHandler },
173  { (char *) NULL, UndefinedHandler },
174  { (char *) NULL, UndefinedHandler },
175  { (char *) NULL, UndefinedHandler },
176  { (char *) NULL, UndefinedHandler },
177  { (char *) NULL, UndefinedHandler },
178  { (char *) NULL, UndefinedHandler },
179  { (char *) NULL, UndefinedHandler },
180  { (char *) NULL, UndefinedHandler },
181  { (char *) NULL, UndefinedHandler },
182  { (char *) NULL, UndefinedHandler },
183  { (char *) NULL, UndefinedHandler },
184  { (char *) NULL, UndefinedHandler },
185  { (char *) NULL, UndefinedHandler },
186  { (char *) NULL, UndefinedHandler },
187  { (char *) NULL, UndefinedHandler },
188  { (char *) NULL, UndefinedHandler },
189  { (char *) NULL, UndefinedHandler },
190  { (char *) NULL, UndefinedHandler },
191  { (char *) NULL, UndefinedHandler },
192  { (char *) NULL, UndefinedHandler },
193  { (char *) NULL, UndefinedHandler },
194  { (char *) NULL, UndefinedHandler },
195  { (char *) NULL, UndefinedHandler },
196  { (char *) NULL, UndefinedHandler }
197  };
198 
199 static const LogMapInfo
200  LogMap[] =
201  {
202  { NoEvents, ConsoleHandler, "Magick-%g.log",
203  "%t %r %u %v %d %c[%p]: %m/%f/%l/%d\\n %e" }
204  };
205 
206 static char
208 
209 static LinkedListInfo
211 
212 static MagickBooleanType
214 
215 static SemaphoreInfo
218 
219 /*
220  Forward declarations.
221 */
222 static LogHandlerType
223  ParseLogHandlers(const char *);
224 
225 static LogInfo
226  *GetLogInfo(const char *,ExceptionInfo *);
227 
228 static MagickBooleanType
230  LoadLogCache(LinkedListInfo *,const char *,const char *,const size_t,
231  ExceptionInfo *);
232 
233 /*
234 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
235 % %
236 % %
237 % %
238 % A c q u i r e L o g C a c h e %
239 % %
240 % %
241 % %
242 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
243 %
244 % AcquireLogCache() caches one or more log configurations which provides a
245 % mapping between log attributes and log name.
246 %
247 % The format of the AcquireLogCache method is:
248 %
249 % LinkedListInfo *AcquireLogCache(const char *filename,
250 % ExceptionInfo *exception)
251 %
252 % A description of each parameter follows:
253 %
254 % o filename: the log configuration filename.
255 %
256 % o exception: return any errors or warnings in this structure.
257 %
258 */
259 static LinkedListInfo *AcquireLogCache(const char *filename,
260  ExceptionInfo *exception)
261 {
263  *cache;
264 
266  status;
267 
268  register ssize_t
269  i;
270 
271  /*
272  Load external log map.
273  */
274  cache=NewLinkedList(0);
275  status=MagickTrue;
276 #if !defined(MAGICKCORE_ZERO_CONFIGURATION_SUPPORT)
277  {
278  const StringInfo
279  *option;
280 
282  *options;
283 
284  options=GetConfigureOptions(filename,exception);
285  option=(const StringInfo *) GetNextValueInLinkedList(options);
286  while (option != (const StringInfo *) NULL)
287  {
288  status&=LoadLogCache(cache,(const char *) GetStringInfoDatum(option),
289  GetStringInfoPath(option),0,exception);
290  option=(const StringInfo *) GetNextValueInLinkedList(options);
291  }
292  options=DestroyConfigureOptions(options);
293  }
294 #endif
295  /*
296  Load built-in log map.
297  */
298  for (i=0; i < (ssize_t) (sizeof(LogMap)/sizeof(*LogMap)); i++)
299  {
300  LogInfo
301  *log_info;
302 
303  register const LogMapInfo
304  *p;
305 
306  p=LogMap+i;
307  log_info=(LogInfo *) AcquireMagickMemory(sizeof(*log_info));
308  if (log_info == (LogInfo *) NULL)
309  {
310  (void) ThrowMagickException(exception,GetMagickModule(),
311  ResourceLimitError,"MemoryAllocationFailed","`%s'",p->filename);
312  continue;
313  }
314  (void) memset(log_info,0,sizeof(*log_info));
315  log_info->path=ConstantString("[built-in]");
316  GetTimerInfo((TimerInfo *) &log_info->timer);
317  log_info->event_mask=p->event_mask;
318  log_info->handler_mask=p->handler_mask;
319  log_info->filename=ConstantString(p->filename);
320  log_info->format=ConstantString(p->format);
321  log_info->signature=MagickCoreSignature;
322  status&=AppendValueToLinkedList(cache,log_info);
323  if (status == MagickFalse)
324  (void) ThrowMagickException(exception,GetMagickModule(),
325  ResourceLimitError,"MemoryAllocationFailed","`%s'",log_info->name);
326  }
327  return(cache);
328 }
329 
330 /*
331 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
332 % %
333 % %
334 % %
335 % C l o s e M a g i c k L o g %
336 % %
337 % %
338 % %
339 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
340 %
341 % CloseMagickLog() closes the Magick log.
342 %
343 % The format of the CloseMagickLog method is:
344 %
345 % CloseMagickLog(void)
346 %
347 */
349 {
351  *exception;
352 
353  LogInfo
354  *log_info;
355 
356  if (IsEventLogging() == MagickFalse)
357  return;
358  exception=AcquireExceptionInfo();
359  log_info=GetLogInfo("*",exception);
360  exception=DestroyExceptionInfo(exception);
362  if (log_info->file != (FILE *) NULL)
363  {
364  (void) FormatLocaleFile(log_info->file,"</log>\n");
365  (void) fclose(log_info->file);
366  log_info->file=(FILE *) NULL;
367  }
369 }
370 
371 /*
372 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
373 % %
374 % %
375 % %
376 + G e t L o g I n f o %
377 % %
378 % %
379 % %
380 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
381 %
382 % GetLogInfo() searches the log list for the specified name and if found
383 % returns attributes for that log.
384 %
385 % The format of the GetLogInfo method is:
386 %
387 % LogInfo *GetLogInfo(const char *name,ExceptionInfo *exception)
388 %
389 % A description of each parameter follows:
390 %
391 % o name: the log name.
392 %
393 % o exception: return any errors or warnings in this structure.
394 %
395 */
396 static LogInfo *GetLogInfo(const char *name,ExceptionInfo *exception)
397 {
398  register LogInfo
399  *p;
400 
401  assert(exception != (ExceptionInfo *) NULL);
402  if (IsLogCacheInstantiated(exception) == MagickFalse)
403  return((LogInfo *) NULL);
404  /*
405  Search for log tag.
406  */
410  if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0))
411  {
413  return(p);
414  }
415  while (p != (LogInfo *) NULL)
416  {
417  if (LocaleCompare(name,p->name) == 0)
418  break;
420  }
421  if (p != (LogInfo *) NULL)
425  return(p);
426 }
427 
428 /*
429 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
430 % %
431 % %
432 % %
433 % G e t L o g I n f o L i s t %
434 % %
435 % %
436 % %
437 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
438 %
439 % GetLogInfoList() returns any logs that match the specified pattern.
440 %
441 % The format of the GetLogInfoList function is:
442 %
443 % const LogInfo **GetLogInfoList(const char *pattern,
444 % size_t *number_preferences,ExceptionInfo *exception)
445 %
446 % A description of each parameter follows:
447 %
448 % o pattern: Specifies a pointer to a text string containing a pattern.
449 %
450 % o number_preferences: This integer returns the number of logs in the list.
451 %
452 % o exception: return any errors or warnings in this structure.
453 %
454 */
455 #if defined(__cplusplus) || defined(c_plusplus)
456 extern "C" {
457 #endif
458 
459 static int LogInfoCompare(const void *x,const void *y)
460 {
461  const LogInfo
462  **p,
463  **q;
464 
465  p=(const LogInfo **) x,
466  q=(const LogInfo **) y;
467  if (LocaleCompare((*p)->path,(*q)->path) == 0)
468  return(LocaleCompare((*p)->name,(*q)->name));
469  return(LocaleCompare((*p)->path,(*q)->path));
470 }
471 
472 #if defined(__cplusplus) || defined(c_plusplus)
473 }
474 #endif
475 
476 MagickExport const LogInfo **GetLogInfoList(const char *pattern,
477  size_t *number_preferences,ExceptionInfo *exception)
478 {
479  const LogInfo
480  **preferences;
481 
482  register const LogInfo
483  *p;
484 
485  register ssize_t
486  i;
487 
488  /*
489  Allocate log list.
490  */
491  assert(pattern != (char *) NULL);
492  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
493  assert(number_preferences != (size_t *) NULL);
494  *number_preferences=0;
495  p=GetLogInfo("*",exception);
496  if (p == (const LogInfo *) NULL)
497  return((const LogInfo **) NULL);
498  preferences=(const LogInfo **) AcquireQuantumMemory((size_t)
499  GetNumberOfElementsInLinkedList(log_cache)+1UL,sizeof(*preferences));
500  if (preferences == (const LogInfo **) NULL)
501  return((const LogInfo **) NULL);
502  /*
503  Generate log list.
504  */
508  for (i=0; p != (const LogInfo *) NULL; )
509  {
510  if ((p->stealth == MagickFalse) &&
511  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
512  preferences[i++]=p;
514  }
516  qsort((void *) preferences,(size_t) i,sizeof(*preferences),LogInfoCompare);
517  preferences[i]=(LogInfo *) NULL;
518  *number_preferences=(size_t) i;
519  return(preferences);
520 }
521 
522 /*
523 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
524 % %
525 % %
526 % %
527 % G e t L o g L i s t %
528 % %
529 % %
530 % %
531 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
532 %
533 % GetLogList() returns any logs that match the specified pattern.
534 %
535 % The format of the GetLogList function is:
536 %
537 % char **GetLogList(const char *pattern,size_t *number_preferences,
538 % ExceptionInfo *exception)
539 %
540 % A description of each parameter follows:
541 %
542 % o pattern: Specifies a pointer to a text string containing a pattern.
543 %
544 % o number_preferences: This integer returns the number of logs in the list.
545 %
546 % o exception: return any errors or warnings in this structure.
547 %
548 */
549 
550 #if defined(__cplusplus) || defined(c_plusplus)
551 extern "C" {
552 #endif
553 
554 static int LogCompare(const void *x,const void *y)
555 {
556  register const char
557  **p,
558  **q;
559 
560  p=(const char **) x;
561  q=(const char **) y;
562  return(LocaleCompare(*p,*q));
563 }
564 
565 #if defined(__cplusplus) || defined(c_plusplus)
566 }
567 #endif
568 
569 MagickExport char **GetLogList(const char *pattern,size_t *number_preferences,
570  ExceptionInfo *exception)
571 {
572  char
573  **preferences;
574 
575  register const LogInfo
576  *p;
577 
578  register ssize_t
579  i;
580 
581  /*
582  Allocate log list.
583  */
584  assert(pattern != (char *) NULL);
585  (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern);
586  assert(number_preferences != (size_t *) NULL);
587  *number_preferences=0;
588  p=GetLogInfo("*",exception);
589  if (p == (const LogInfo *) NULL)
590  return((char **) NULL);
591  preferences=(char **) AcquireQuantumMemory((size_t)
592  GetNumberOfElementsInLinkedList(log_cache)+1UL,sizeof(*preferences));
593  if (preferences == (char **) NULL)
594  return((char **) NULL);
595  /*
596  Generate log list.
597  */
601  for (i=0; p != (const LogInfo *) NULL; )
602  {
603  if ((p->stealth == MagickFalse) &&
604  (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse))
605  preferences[i++]=ConstantString(p->name);
607  }
609  qsort((void *) preferences,(size_t) i,sizeof(*preferences),LogCompare);
610  preferences[i]=(char *) NULL;
611  *number_preferences=(size_t) i;
612  return(preferences);
613 }
614 
615 /*
616 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
617 % %
618 % %
619 % %
620 % G e t L o g N a m e %
621 % %
622 % %
623 % %
624 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
625 %
626 % GetLogName() returns the current log name.
627 %
628 % The format of the GetLogName method is:
629 %
630 % const char *GetLogName(void)
631 %
632 */
633 MagickExport const char *GetLogName(void)
634 {
635  return(log_name);
636 }
637 
638 /*
639 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
640 % %
641 % %
642 % %
643 + I s L o g C a c h e I n s t a n t i a t e d %
644 % %
645 % %
646 % %
647 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
648 %
649 % IsLogCacheInstantiated() determines if the log list is instantiated. If
650 % not, it instantiates the list and returns it.
651 %
652 % The format of the IsLogInstantiated method is:
653 %
654 % MagickBooleanType IsLogCacheInstantiated(ExceptionInfo *exception)
655 %
656 % A description of each parameter follows.
657 %
658 % o exception: return any errors or warnings in this structure.
659 %
660 */
661 
662 static inline void CheckEventLogging()
663 {
664  /*
665  Are we logging events?
666  */
669  else
670  {
671  LogInfo
672  *p;
673 
676  event_logging=(p != (LogInfo *) NULL) && (p->event_mask != NoEvents) ?
678  }
679 }
680 
682 {
683  if (log_cache == (LinkedListInfo *) NULL)
684  {
685  if (log_semaphore == (SemaphoreInfo *) NULL)
688  if (log_cache == (LinkedListInfo *) NULL)
689  {
692  }
694  }
695  return(log_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
696 }
697 
698 /*
699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
700 % %
701 % %
702 % %
703 % I s E v e n t L o g g i n g %
704 % %
705 % %
706 % %
707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
708 %
709 % IsEventLogging() returns MagickTrue if debug of events is enabled otherwise
710 % MagickFalse.
711 %
712 % The format of the IsEventLogging method is:
713 %
714 % MagickBooleanType IsEventLogging(void)
715 %
716 */
718 {
719  return(event_logging);
720 }
721 
722 /*
723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
724 % %
725 % %
726 % %
727 % L i s t L o g I n f o %
728 % %
729 % %
730 % %
731 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
732 %
733 % ListLogInfo() lists the log info to a file.
734 %
735 % The format of the ListLogInfo method is:
736 %
737 % MagickBooleanType ListLogInfo(FILE *file,ExceptionInfo *exception)
738 %
739 % A description of each parameter follows.
740 %
741 % o file: An pointer to a FILE.
742 %
743 % o exception: return any errors or warnings in this structure.
744 %
745 */
747 {
748 #define MegabytesToBytes(value) ((MagickSizeType) (value)*1024*1024)
749 
750  const char
751  *path;
752 
753  const LogInfo
754  **log_info;
755 
756  register ssize_t
757  i;
758 
759  size_t
760  number_aliases;
761 
762  ssize_t
763  j;
764 
765  if (file == (const FILE *) NULL)
766  file=stdout;
767  log_info=GetLogInfoList("*",&number_aliases,exception);
768  if (log_info == (const LogInfo **) NULL)
769  return(MagickFalse);
770  j=0;
771  path=(const char *) NULL;
772  for (i=0; i < (ssize_t) number_aliases; i++)
773  {
774  if (log_info[i]->stealth != MagickFalse)
775  continue;
776  if ((path == (const char *) NULL) ||
777  (LocaleCompare(path,log_info[i]->path) != 0))
778  {
779  size_t
780  length;
781 
782  if (log_info[i]->path != (char *) NULL)
783  (void) FormatLocaleFile(file,"\nPath: %s\n\n",log_info[i]->path);
784  length=0;
785  for (j=0; j < (ssize_t) (8*sizeof(LogHandlerType)); j++)
786  {
787  size_t
788  mask;
789 
790  if (LogHandlers[j].name == (const char *) NULL)
791  break;
792  mask=1;
793  mask<<=j;
794  if ((log_info[i]->handler_mask & mask) != 0)
795  {
796  (void) FormatLocaleFile(file,"%s ",LogHandlers[j].name);
797  length+=strlen(LogHandlers[j].name);
798  }
799  }
800  for (j=(ssize_t) length; j <= 12; j++)
801  (void) FormatLocaleFile(file," ");
802  (void) FormatLocaleFile(file," Generations Limit Format\n");
803  (void) FormatLocaleFile(file,"-----------------------------------------"
804  "--------------------------------------\n");
805  }
806  path=log_info[i]->path;
807  if (log_info[i]->filename != (char *) NULL)
808  {
809  (void) FormatLocaleFile(file,"%s",log_info[i]->filename);
810  for (j=(ssize_t) strlen(log_info[i]->filename); j <= 16; j++)
811  (void) FormatLocaleFile(file," ");
812  }
813  (void) FormatLocaleFile(file,"%9g ",(double) log_info[i]->generations);
814  (void) FormatLocaleFile(file,"%8g ",(double) log_info[i]->limit);
815  if (log_info[i]->format != (char *) NULL)
816  (void) FormatLocaleFile(file,"%s",log_info[i]->format);
817  (void) FormatLocaleFile(file,"\n");
818  }
819  (void) fflush(file);
820  log_info=(const LogInfo **) RelinquishMagickMemory((void *) log_info);
821  return(MagickTrue);
822 }
823 
824 /*
825 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
826 % %
827 % %
828 % %
829 + L o g C o m p o n e n t G e n e s i s %
830 % %
831 % %
832 % %
833 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
834 %
835 % LogComponentGenesis() instantiates the log component.
836 %
837 % The format of the LogComponentGenesis method is:
838 %
839 % MagickBooleanType LogComponentGenesis(void)
840 %
841 */
843 {
845  *exception;
846 
847  if (log_semaphore == (SemaphoreInfo *) NULL)
849  exception=AcquireExceptionInfo();
850  (void) GetLogInfo("*",exception);
851  exception=DestroyExceptionInfo(exception);
853  return(MagickTrue);
854 }
855 
856 /*
857 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
858 % %
859 % %
860 % %
861 + L o g C o m p o n e n t T e r m i n u s %
862 % %
863 % %
864 % %
865 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
866 %
867 % LogComponentTerminus() destroys the logging component.
868 %
869 % The format of the LogComponentTerminus method is:
870 %
871 % LogComponentTerminus(void)
872 %
873 */
874 
875 static void *DestroyLogElement(void *log_info)
876 {
877  register LogInfo
878  *p;
879 
880  p=(LogInfo *) log_info;
881  if (p->file != (FILE *) NULL)
882  {
883  (void) FormatLocaleFile(p->file,"</log>\n");
884  (void) fclose(p->file);
885  p->file=(FILE *) NULL;
886  }
887  if (p->format != (char *) NULL)
888  p->format=DestroyString(p->format);
889  if (p->path != (char *) NULL)
890  p->path=DestroyString(p->path);
891  if (p->filename != (char *) NULL)
894  return((void *) NULL);
895 }
896 
898 {
899  if (event_semaphore == (SemaphoreInfo *) NULL)
904  if (log_semaphore == (SemaphoreInfo *) NULL)
907  if (log_cache != (LinkedListInfo *) NULL)
912 }
913 
914 /*
915 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
916 % %
917 % %
918 % %
919 % L o g M a g i c k E v e n t %
920 % %
921 % %
922 % %
923 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
924 %
925 % LogMagickEvent() logs an event as determined by the log configuration file.
926 % If an error occurs, MagickFalse is returned otherwise MagickTrue.
927 %
928 % The format of the LogMagickEvent method is:
929 %
930 % MagickBooleanType LogMagickEvent(const LogEventType type,
931 % const char *module,const char *function,const size_t line,
932 % const char *format,...)
933 %
934 % A description of each parameter follows:
935 %
936 % o type: the event type.
937 %
938 % o filename: the source module filename.
939 %
940 % o function: the function name.
941 %
942 % o line: the line number of the source module.
943 %
944 % o format: the output format.
945 %
946 */
947 static char *TranslateEvent(const char *module,const char *function,
948  const size_t line,const char *domain,const char *event)
949 {
950  char
951  *text;
952 
953  double
954  elapsed_time,
955  user_time;
956 
958  *exception;
959 
960  LogInfo
961  *log_info;
962 
963  register char
964  *q;
965 
966  register const char
967  *p;
968 
969  size_t
970  extent;
971 
972  time_t
973  seconds;
974 
975  exception=AcquireExceptionInfo();
976  log_info=(LogInfo *) GetLogInfo("*",exception);
977  exception=DestroyExceptionInfo(exception);
978  seconds=time((time_t *) NULL);
979  elapsed_time=GetElapsedTime(&log_info->timer);
980  user_time=GetUserTime(&log_info->timer);
981  text=AcquireString(event);
982  if (log_info->format == (char *) NULL)
983  return(text);
984  extent=strlen(event)+MagickPathExtent;
985  if (LocaleCompare(log_info->format,"xml") == 0)
986  {
987  char
988  timestamp[MagickPathExtent];
989 
990  /*
991  Translate event in "XML" format.
992  */
993  (void) FormatMagickTime(seconds,extent,timestamp);
994  (void) FormatLocaleString(text,extent,
995  "<entry>\n"
996  " <timestamp>%s</timestamp>\n"
997  " <elapsed-time>%lu:%02lu.%03lu</elapsed-time>\n"
998  " <user-time>%0.3f</user-time>\n"
999  " <process-id>%.20g</process-id>\n"
1000  " <thread-id>%.20g</thread-id>\n"
1001  " <module>%s</module>\n"
1002  " <function>%s</function>\n"
1003  " <line>%.20g</line>\n"
1004  " <domain>%s</domain>\n"
1005  " <event>%s</event>\n"
1006  "</entry>",timestamp,(unsigned long) (elapsed_time/60.0),
1007  (unsigned long) floor(fmod(elapsed_time,60.0)),(unsigned long)
1008  (1000.0*(elapsed_time-floor(elapsed_time))+0.5),user_time,
1009  (double) getpid(),(double) GetMagickThreadSignature(),module,function,
1010  (double) line,domain,event);
1011  return(text);
1012  }
1013  /*
1014  Translate event in "human readable" format.
1015  */
1016  q=text;
1017  for (p=log_info->format; *p != '\0'; p++)
1018  {
1019  *q='\0';
1020  if ((size_t) (q-text+MagickPathExtent) >= extent)
1021  {
1022  extent+=MagickPathExtent;
1023  text=(char *) ResizeQuantumMemory(text,extent+MagickPathExtent,
1024  sizeof(*text));
1025  if (text == (char *) NULL)
1026  return((char *) NULL);
1027  q=text+strlen(text);
1028  }
1029  /*
1030  The format of the log is defined by embedding special format characters:
1031 
1032  %c client name
1033  %d domain
1034  %e event
1035  %f function
1036  %g generation
1037  %l line
1038  %m module
1039  %n log name
1040  %p process id
1041  %r real CPU time
1042  %t wall clock time
1043  %u user CPU time
1044  %v version
1045  %% percent sign
1046  \n newline
1047  \r carriage return
1048  */
1049  if ((*p == '\\') && (*(p+1) == 'r'))
1050  {
1051  *q++='\r';
1052  p++;
1053  continue;
1054  }
1055  if ((*p == '\\') && (*(p+1) == 'n'))
1056  {
1057  *q++='\n';
1058  p++;
1059  continue;
1060  }
1061  if (*p != '%')
1062  {
1063  *q++=(*p);
1064  continue;
1065  }
1066  p++;
1067  switch (*p)
1068  {
1069  case 'c':
1070  {
1071  q+=CopyMagickString(q,GetClientName(),extent);
1072  break;
1073  }
1074  case 'd':
1075  {
1076  q+=CopyMagickString(q,domain,extent);
1077  break;
1078  }
1079  case 'e':
1080  {
1081  q+=CopyMagickString(q,event,extent);
1082  break;
1083  }
1084  case 'f':
1085  {
1086  q+=CopyMagickString(q,function,extent);
1087  break;
1088  }
1089  case 'g':
1090  {
1091  if (log_info->generations == 0)
1092  {
1093  (void) CopyMagickString(q,"0",extent);
1094  q++;
1095  break;
1096  }
1097  q+=FormatLocaleString(q,extent,"%.20g",(double) (log_info->generation %
1098  log_info->generations));
1099  break;
1100  }
1101  case 'l':
1102  {
1103  q+=FormatLocaleString(q,extent,"%.20g",(double) line);
1104  break;
1105  }
1106  case 'm':
1107  {
1108  register const char
1109  *r;
1110 
1111  for (r=module+strlen(module)-1; r > module; r--)
1112  if (*r == *DirectorySeparator)
1113  {
1114  r++;
1115  break;
1116  }
1117  q+=CopyMagickString(q,r,extent);
1118  break;
1119  }
1120  case 'n':
1121  {
1122  q+=CopyMagickString(q,GetLogName(),extent);
1123  break;
1124  }
1125  case 'p':
1126  {
1127  q+=FormatLocaleString(q,extent,"%.20g",(double) getpid());
1128  break;
1129  }
1130  case 'r':
1131  {
1132  q+=FormatLocaleString(q,extent,"%lu:%02lu.%03lu",(unsigned long)
1133  (elapsed_time/60.0),(unsigned long) floor(fmod(elapsed_time,60.0)),
1134  (unsigned long) (1000.0*(elapsed_time-floor(elapsed_time))+0.5));
1135  break;
1136  }
1137  case 't':
1138  {
1139  q+=FormatMagickTime(seconds,extent,q);
1140  break;
1141  }
1142  case 'u':
1143  {
1144  q+=FormatLocaleString(q,extent,"%0.3fu",user_time);
1145  break;
1146  }
1147  case 'v':
1148  {
1150  break;
1151  }
1152  case '%':
1153  {
1154  *q++=(*p);
1155  break;
1156  }
1157  default:
1158  {
1159  *q++='%';
1160  *q++=(*p);
1161  break;
1162  }
1163  }
1164  }
1165  *q='\0';
1166  return(text);
1167 }
1168 
1169 static char *TranslateFilename(const LogInfo *log_info)
1170 {
1171  char
1172  *filename;
1173 
1174  register char
1175  *q;
1176 
1177  register const char
1178  *p;
1179 
1180  size_t
1181  extent;
1182 
1183  /*
1184  Translate event in "human readable" format.
1185  */
1186  assert(log_info != (LogInfo *) NULL);
1187  assert(log_info->filename != (char *) NULL);
1188  filename=AcquireString((char *) NULL);
1189  extent=MagickPathExtent;
1190  q=filename;
1191  for (p=log_info->filename; *p != '\0'; p++)
1192  {
1193  *q='\0';
1194  if ((size_t) (q-filename+MagickPathExtent) >= extent)
1195  {
1196  extent+=MagickPathExtent;
1197  filename=(char *) ResizeQuantumMemory(filename,extent+MagickPathExtent,
1198  sizeof(*filename));
1199  if (filename == (char *) NULL)
1200  return((char *) NULL);
1201  q=filename+strlen(filename);
1202  }
1203  /*
1204  The format of the filename is defined by embedding special format
1205  characters:
1206 
1207  %c client name
1208  %n log name
1209  %p process id
1210  %v version
1211  %% percent sign
1212  */
1213  if (*p != '%')
1214  {
1215  *q++=(*p);
1216  continue;
1217  }
1218  p++;
1219  switch (*p)
1220  {
1221  case 'c':
1222  {
1223  q+=CopyMagickString(q,GetClientName(),extent);
1224  break;
1225  }
1226  case 'g':
1227  {
1228  if (log_info->generations == 0)
1229  {
1230  (void) CopyMagickString(q,"0",extent);
1231  q++;
1232  break;
1233  }
1234  q+=FormatLocaleString(q,extent,"%.20g",(double) (log_info->generation %
1235  log_info->generations));
1236  break;
1237  }
1238  case 'n':
1239  {
1240  q+=CopyMagickString(q,GetLogName(),extent);
1241  break;
1242  }
1243  case 'p':
1244  {
1245  q+=FormatLocaleString(q,extent,"%.20g",(double) getpid());
1246  break;
1247  }
1248  case 'v':
1249  {
1251  break;
1252  }
1253  case '%':
1254  {
1255  *q++=(*p);
1256  break;
1257  }
1258  default:
1259  {
1260  *q++='%';
1261  *q++=(*p);
1262  break;
1263  }
1264  }
1265  }
1266  *q='\0';
1267  return(filename);
1268 }
1269 
1271  const char *module,const char *function,const size_t line,const char *format,
1272  va_list operands)
1273 {
1274  char
1275  event[MagickPathExtent],
1276  *text;
1277 
1278  const char
1279  *domain;
1280 
1282  *exception;
1283 
1284  int
1285  n;
1286 
1287  LogInfo
1288  *log_info;
1289 
1290  exception=AcquireExceptionInfo();
1291  log_info=(LogInfo *) GetLogInfo("*",exception);
1292  exception=DestroyExceptionInfo(exception);
1293  if (event_semaphore == (SemaphoreInfo *) NULL)
1296  if ((log_info->event_mask & type) == 0)
1297  {
1299  return(MagickTrue);
1300  }
1302 #if defined(MAGICKCORE_HAVE_VSNPRINTF)
1303  n=vsnprintf(event,MagickPathExtent,format,operands);
1304 #else
1305  n=vsprintf(event,format,operands);
1306 #endif
1307  if (n < 0)
1308  event[MagickPathExtent-1]='\0';
1309  text=TranslateEvent(module,function,line,domain,event);
1310  if (text == (char *) NULL)
1311  {
1312  (void) ContinueTimer((TimerInfo *) &log_info->timer);
1314  return(MagickFalse);
1315  }
1316  if ((log_info->handler_mask & ConsoleHandler) != 0)
1317  {
1318  (void) FormatLocaleFile(stderr,"%s\n",text);
1319  (void) fflush(stderr);
1320  }
1321  if ((log_info->handler_mask & DebugHandler) != 0)
1322  {
1323 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1324  OutputDebugString(text);
1325  OutputDebugString("\n");
1326 #endif
1327  }
1328  if ((log_info->handler_mask & EventHandler) != 0)
1329  {
1330 #if defined(MAGICKCORE_WINDOWS_SUPPORT)
1331  (void) NTReportEvent(text,MagickFalse);
1332 #endif
1333  }
1334  if ((log_info->handler_mask & FileHandler) != 0)
1335  {
1336  struct stat
1337  file_info;
1338 
1339  file_info.st_size=0;
1340  if (log_info->file != (FILE *) NULL)
1341  (void) fstat(fileno(log_info->file),&file_info);
1342  if (file_info.st_size > (ssize_t) (1024*1024*log_info->limit))
1343  {
1344  (void) FormatLocaleFile(log_info->file,"</log>\n");
1345  (void) fclose(log_info->file);
1346  log_info->file=(FILE *) NULL;
1347  }
1348  if (log_info->file == (FILE *) NULL)
1349  {
1350  char
1351  *filename;
1352 
1353  filename=TranslateFilename(log_info);
1354  if (filename == (char *) NULL)
1355  {
1356  (void) ContinueTimer((TimerInfo *) &log_info->timer);
1358  return(MagickFalse);
1359  }
1360  log_info->append=IsPathAccessible(filename);
1361  log_info->file=fopen_utf8(filename,"ab");
1362  filename=(char *) RelinquishMagickMemory(filename);
1363  if (log_info->file == (FILE *) NULL)
1364  {
1366  return(MagickFalse);
1367  }
1368  log_info->generation++;
1369  if (log_info->append == MagickFalse)
1370  (void) FormatLocaleFile(log_info->file,"<?xml version=\"1.0\" "
1371  "encoding=\"UTF-8\" standalone=\"yes\"?>\n");
1372  (void) FormatLocaleFile(log_info->file,"<log>\n");
1373  }
1374  (void) FormatLocaleFile(log_info->file," <event>%s</event>\n",text);
1375  (void) fflush(log_info->file);
1376  }
1377  if ((log_info->handler_mask & MethodHandler) != 0)
1378  {
1379  if (log_info->method != (MagickLogMethod) NULL)
1380  log_info->method(type,text);
1381  }
1382  if ((log_info->handler_mask & StdoutHandler) != 0)
1383  {
1384  (void) FormatLocaleFile(stdout,"%s\n",text);
1385  (void) fflush(stdout);
1386  }
1387  if ((log_info->handler_mask & StderrHandler) != 0)
1388  {
1389  (void) FormatLocaleFile(stderr,"%s\n",text);
1390  (void) fflush(stderr);
1391  }
1392  text=(char *) RelinquishMagickMemory(text);
1393  (void) ContinueTimer((TimerInfo *) &log_info->timer);
1395  return(MagickTrue);
1396 }
1397 
1399  const char *module,const char *function,const size_t line,
1400  const char *format,...)
1401 {
1402  va_list
1403  operands;
1404 
1406  status;
1407 
1408  if (IsEventLogging() == MagickFalse)
1409  return(MagickFalse);
1410  va_start(operands,format);
1411  status=LogMagickEventList(type,module,function,line,format,operands);
1412  va_end(operands);
1413  return(status);
1414 }
1415 
1416 /*
1417 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1418 % %
1419 % %
1420 % %
1421 + L o a d L o g C a c h e %
1422 % %
1423 % %
1424 % %
1425 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1426 %
1427 % LoadLogCache() loads the log configurations which provides a
1428 % mapping between log attributes and log name.
1429 %
1430 % The format of the LoadLogCache method is:
1431 %
1432 % MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
1433 % const char *filename,const size_t depth,ExceptionInfo *exception)
1434 %
1435 % A description of each parameter follows:
1436 %
1437 % o xml: The log list in XML format.
1438 %
1439 % o filename: The log list filename.
1440 %
1441 % o depth: depth of <include /> statements.
1442 %
1443 % o exception: return any errors or warnings in this structure.
1444 %
1445 */
1446 static MagickBooleanType LoadLogCache(LinkedListInfo *cache,const char *xml,
1447  const char *filename,const size_t depth,ExceptionInfo *exception)
1448 {
1449  char
1450  keyword[MagickPathExtent],
1451  *token;
1452 
1453  const char
1454  *q;
1455 
1456  LogInfo
1457  *log_info = (LogInfo *) NULL;
1458 
1460  status;
1461 
1462  size_t
1463  extent;
1464 
1465  /*
1466  Load the log map file.
1467  */
1468  if (xml == (const char *) NULL)
1469  return(MagickFalse);
1470  status=MagickTrue;
1471  token=AcquireString(xml);
1472  extent=strlen(token)+MagickPathExtent;
1473  for (q=(const char *) xml; *q != '\0'; )
1474  {
1475  /*
1476  Interpret XML.
1477  */
1478  GetNextToken(q,&q,extent,token);
1479  if (*token == '\0')
1480  break;
1481  (void) CopyMagickString(keyword,token,MagickPathExtent);
1482  if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0)
1483  {
1484  /*
1485  Doctype element.
1486  */
1487  while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0'))
1488  GetNextToken(q,&q,extent,token);
1489  continue;
1490  }
1491  if (LocaleNCompare(keyword,"<!--",4) == 0)
1492  {
1493  /*
1494  Comment element.
1495  */
1496  while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0'))
1497  GetNextToken(q,&q,extent,token);
1498  continue;
1499  }
1500  if (LocaleCompare(keyword,"<include") == 0)
1501  {
1502  /*
1503  Include element.
1504  */
1505  while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0'))
1506  {
1507  (void) CopyMagickString(keyword,token,MagickPathExtent);
1508  GetNextToken(q,&q,extent,token);
1509  if (*token != '=')
1510  continue;
1511  GetNextToken(q,&q,extent,token);
1512  if (LocaleCompare(keyword,"file") == 0)
1513  {
1514  if (depth > MagickMaxRecursionDepth)
1515  (void) ThrowMagickException(exception,GetMagickModule(),
1516  ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token);
1517  else
1518  {
1519  char
1520  path[MagickPathExtent],
1521  *file_xml;
1522 
1523  GetPathComponent(filename,HeadPath,path);
1524  if (*path != '\0')
1527  if (*token == *DirectorySeparator)
1528  (void) CopyMagickString(path,token,MagickPathExtent);
1529  else
1530  (void) ConcatenateMagickString(path,token,MagickPathExtent);
1531  file_xml=FileToXML(path,~0UL);
1532  if (file_xml != (char *) NULL)
1533  {
1534  status&=LoadLogCache(cache,file_xml,path,depth+1,
1535  exception);
1536  file_xml=DestroyString(file_xml);
1537  }
1538  }
1539  }
1540  }
1541  continue;
1542  }
1543  if (LocaleCompare(keyword,"<logmap>") == 0)
1544  {
1545  /*
1546  Allocate memory for the log list.
1547  */
1548  log_info=(LogInfo *) AcquireCriticalMemory(sizeof(*log_info));
1549  (void) memset(log_info,0,sizeof(*log_info));
1550  log_info->path=ConstantString(filename);
1551  GetTimerInfo((TimerInfo *) &log_info->timer);
1552  log_info->signature=MagickCoreSignature;
1553  continue;
1554  }
1555  if (log_info == (LogInfo *) NULL)
1556  continue;
1557  if (LocaleCompare(keyword,"</logmap>") == 0)
1558  {
1559  status=AppendValueToLinkedList(cache,log_info);
1560  if (status == MagickFalse)
1561  (void) ThrowMagickException(exception,GetMagickModule(),
1562  ResourceLimitError,"MemoryAllocationFailed","`%s'",filename);
1563  log_info=(LogInfo *) NULL;
1564  continue;
1565  }
1566  GetNextToken(q,(const char **) NULL,extent,token);
1567  if (*token != '=')
1568  continue;
1569  GetNextToken(q,&q,extent,token);
1570  GetNextToken(q,&q,extent,token);
1571  switch (*keyword)
1572  {
1573  case 'E':
1574  case 'e':
1575  {
1576  if (LocaleCompare((char *) keyword,"events") == 0)
1577  {
1578  log_info->event_mask=(LogEventType) (log_info->event_mask |
1580  break;
1581  }
1582  break;
1583  }
1584  case 'F':
1585  case 'f':
1586  {
1587  if (LocaleCompare((char *) keyword,"filename") == 0)
1588  {
1589  if (log_info->filename != (char *) NULL)
1590  log_info->filename=(char *)
1591  RelinquishMagickMemory(log_info->filename);
1592  log_info->filename=ConstantString(token);
1593  break;
1594  }
1595  if (LocaleCompare((char *) keyword,"format") == 0)
1596  {
1597  if (log_info->format != (char *) NULL)
1598  log_info->format=(char *)
1599  RelinquishMagickMemory(log_info->format);
1600  log_info->format=ConstantString(token);
1601  break;
1602  }
1603  break;
1604  }
1605  case 'G':
1606  case 'g':
1607  {
1608  if (LocaleCompare((char *) keyword,"generations") == 0)
1609  {
1610  if (LocaleCompare(token,"unlimited") == 0)
1611  {
1612  log_info->generations=(~0UL);
1613  break;
1614  }
1615  log_info->generations=StringToUnsignedLong(token);
1616  break;
1617  }
1618  break;
1619  }
1620  case 'L':
1621  case 'l':
1622  {
1623  if (LocaleCompare((char *) keyword,"limit") == 0)
1624  {
1625  if (LocaleCompare(token,"unlimited") == 0)
1626  {
1627  log_info->limit=(~0UL);
1628  break;
1629  }
1630  log_info->limit=StringToUnsignedLong(token);
1631  break;
1632  }
1633  break;
1634  }
1635  case 'O':
1636  case 'o':
1637  {
1638  if (LocaleCompare((char *) keyword,"output") == 0)
1639  {
1640  log_info->handler_mask=(LogHandlerType)
1641  (log_info->handler_mask | ParseLogHandlers(token));
1642  break;
1643  }
1644  break;
1645  }
1646  default:
1647  break;
1648  }
1649  }
1650  token=DestroyString(token);
1651  if (cache == (LinkedListInfo *) NULL)
1652  return(MagickFalse);
1653  return(status != 0 ? MagickTrue : MagickFalse);
1654 }
1655 
1656 /*
1657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1658 % %
1659 % %
1660 % %
1661 + P a r s e L o g H a n d l e r s %
1662 % %
1663 % %
1664 % %
1665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1666 %
1667 % ParseLogHandlers() parses a string defining which handlers takes a log
1668 % message and exports them.
1669 %
1670 % The format of the ParseLogHandlers method is:
1671 %
1672 % LogHandlerType ParseLogHandlers(const char *handlers)
1673 %
1674 % A description of each parameter follows:
1675 %
1676 % o handlers: one or more handlers separated by commas.
1677 %
1678 */
1679 static LogHandlerType ParseLogHandlers(const char *handlers)
1680 {
1682  handler_mask;
1683 
1684  register const char
1685  *p;
1686 
1687  register ssize_t
1688  i;
1689 
1690  size_t
1691  length;
1692 
1693  handler_mask=NoHandler;
1694  for (p=handlers; p != (char *) NULL; p=strchr(p,','))
1695  {
1696  while ((*p != '\0') && ((isspace((int) ((unsigned char) *p)) != 0) ||
1697  (*p == ',')))
1698  p++;
1699  for (i=0; LogHandlers[i].name != (char *) NULL; i++)
1700  {
1701  length=strlen(LogHandlers[i].name);
1702  if (LocaleNCompare(p,LogHandlers[i].name,length) == 0)
1703  {
1704  handler_mask=(LogHandlerType) (handler_mask | LogHandlers[i].handler);
1705  break;
1706  }
1707  }
1708  if (LogHandlers[i].name == (char *) NULL)
1709  return(UndefinedHandler);
1710  }
1711  return(handler_mask);
1712 }
1713 
1714 /*
1715 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1716 % %
1717 % %
1718 % %
1719 % S e t L o g E v e n t M a s k %
1720 % %
1721 % %
1722 % %
1723 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1724 %
1725 % SetLogEventMask() accepts a list that determines which events to log. All
1726 % other events are ignored. By default, no debug is enabled. This method
1727 % returns the previous log event mask.
1728 %
1729 % The format of the SetLogEventMask method is:
1730 %
1731 % LogEventType SetLogEventMask(const char *events)
1732 %
1733 % A description of each parameter follows:
1734 %
1735 % o events: log these events.
1736 %
1737 */
1739 {
1741  *exception;
1742 
1743  LogInfo
1744  *log_info;
1745 
1746  ssize_t
1747  option;
1748 
1749  exception=AcquireExceptionInfo();
1750  log_info=(LogInfo *) GetLogInfo("*",exception);
1751  exception=DestroyExceptionInfo(exception);
1754  log_info=(LogInfo *) GetValueFromLinkedList(log_cache,0);
1755  log_info->event_mask=(LogEventType) option;
1756  if (option == -1)
1757  log_info->event_mask=UndefinedEvents;
1760  return(log_info->event_mask);
1761 }
1762 
1763 /*
1764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1765 % %
1766 % %
1767 % %
1768 % S e t L o g F o r m a t %
1769 % %
1770 % %
1771 % %
1772 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1773 %
1774 % SetLogFormat() sets the format for the "human readable" log record.
1775 %
1776 % The format of the LogMagickFormat method is:
1777 %
1778 % SetLogFormat(const char *format)
1779 %
1780 % A description of each parameter follows:
1781 %
1782 % o format: the log record format.
1783 %
1784 */
1785 MagickExport void SetLogFormat(const char *format)
1786 {
1787  LogInfo
1788  *log_info;
1789 
1791  *exception;
1792 
1793  exception=AcquireExceptionInfo();
1794  log_info=(LogInfo *) GetLogInfo("*",exception);
1795  exception=DestroyExceptionInfo(exception);
1797  if (log_info->format != (char *) NULL)
1798  log_info->format=DestroyString(log_info->format);
1799  log_info->format=ConstantString(format);
1801 }
1802 
1803 /*
1804 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1805 % %
1806 % %
1807 % %
1808 % S e t L o g M e t h o d %
1809 % %
1810 % %
1811 % %
1812 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1813 %
1814 % SetLogMethod() sets the method that will be called when an event is logged.
1815 %
1816 % The format of the SetLogMethod method is:
1817 %
1818 % void SetLogMethod(MagickLogMethod method)
1819 %
1820 % A description of each parameter follows:
1821 %
1822 % o method: pointer to a method that will be called when LogMagickEvent is
1823 % being called.
1824 %
1825 */
1827 {
1829  *exception;
1830 
1831  LogInfo
1832  *log_info;
1833 
1834  exception=AcquireExceptionInfo();
1835  log_info=(LogInfo *) GetLogInfo("*",exception);
1836  exception=DestroyExceptionInfo(exception);
1838  log_info=(LogInfo *) GetValueFromLinkedList(log_cache,0);
1839  log_info->handler_mask=(LogHandlerType) (log_info->handler_mask |
1840  MethodHandler);
1841  log_info->method=method;
1843 }
1844 
1845 /*
1846 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1847 % %
1848 % %
1849 % %
1850 % S e t L o g N a m e %
1851 % %
1852 % %
1853 % %
1854 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1855 %
1856 % SetLogName() sets the log name and returns it.
1857 %
1858 % The format of the SetLogName method is:
1859 %
1860 % const char *SetLogName(const char *name)
1861 %
1862 % A description of each parameter follows:
1863 %
1864 % o log_name: SetLogName() returns the current client name.
1865 %
1866 % o name: Specifies the new client name.
1867 %
1868 */
1869 MagickExport const char *SetLogName(const char *name)
1870 {
1871  if ((name != (char *) NULL) && (*name != '\0'))
1873  return(log_name);
1874 }
static const HandlerInfo LogHandlers[32]
Definition: log.c:163
MagickExport void * GetValueFromLinkedList(LinkedListInfo *list_info, const size_t index)
Definition: linked-list.c:382
size_t signature
Definition: log.c:140
#define MagickMaxRecursionDepth
Definition: studio.h:344
const char * format
Definition: log.c:155
MagickExport double GetUserTime(TimerInfo *time_info)
Definition: timer.c:316
size_t generations
Definition: log.c:123
MagickExport MagickBooleanType LogMagickEventList(const LogEventType type, const char *module, const char *function, const size_t line, const char *format, va_list operands)
Definition: log.c:1270
MagickExport void UnlockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:450
static unsigned long StringToUnsignedLong(const char *magick_restrict value)
MagickExport void ResetLinkedListIterator(LinkedListInfo *list_info)
Definition: linked-list.c:959
MagickExport ssize_t ParseCommandOption(const CommandOption option, const MagickBooleanType list, const char *options)
Definition: option.c:2965
Definition: log.c:80
LogHandlerType handler
Definition: log.c:105
char * name
Definition: log.c:93
MagickExport LinkedListInfo * DestroyLinkedList(LinkedListInfo *list_info, void *(*relinquish_value)(void *))
Definition: linked-list.c:219
static MagickBooleanType LoadLogCache(LinkedListInfo *, const char *, const char *, const size_t, ExceptionInfo *)
Definition: log.c:1446
MagickExport size_t ConcatenateMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:426
MagickExport SemaphoreInfo * AcquireSemaphoreInfo(void)
Definition: semaphore.c:192
MagickExport MagickBooleanType InsertValueInLinkedList(LinkedListInfo *list_info, const size_t index, const void *value)
Definition: linked-list.c:447
static int LogInfoCompare(const void *x, const void *y)
Definition: log.c:459
LogEventType
Definition: log.h:33
MagickExport ExceptionInfo * AcquireExceptionInfo(void)
Definition: exception.c:108
MagickPrivate MagickBooleanType LogComponentGenesis(void)
Definition: log.c:842
MagickExport MagickBooleanType IsLinkedListEmpty(const LinkedListInfo *list_info)
Definition: linked-list.c:633
MagickExport MagickBooleanType AppendValueToLinkedList(LinkedListInfo *list_info, const void *value)
Definition: linked-list.c:111
MagickExport ssize_t FormatLocaleString(char *magick_restrict string, const size_t length, const char *magick_restrict format,...)
Definition: locale.c:504
static void * AcquireCriticalMemory(const size_t size)
const char * name
Definition: log.c:102
MagickExport void * RemoveElementByValueFromLinkedList(LinkedListInfo *list_info, const void *value)
Definition: linked-list.c:756
MagickLogMethod method
Definition: log.c:143
char * path
Definition: log.c:117
LogHandlerType handler_mask
Definition: log.c:114
MagickExport void * ResizeQuantumMemory(void *memory, const size_t count, const size_t quantum)
Definition: memory.c:1339
MagickExport MagickBooleanType ListLogInfo(FILE *file, ExceptionInfo *exception)
Definition: log.c:746
MagickExport LogEventType SetLogEventMask(const char *events)
Definition: log.c:1738
Definition: log.h:52
struct _EventInfo EventInfo
MagickExport void * GetNextValueInLinkedList(LinkedListInfo *list_info)
Definition: linked-list.c:305
MagickBooleanType append
Definition: log.c:133
#define MagickCoreSignature
MagickExport void LockSemaphoreInfo(SemaphoreInfo *semaphore_info)
Definition: semaphore.c:293
static MagickBooleanType IsLogCacheInstantiated(ExceptionInfo *)
Definition: log.c:681
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1295
MagickExport LinkedListInfo * GetConfigureOptions(const char *filename, ExceptionInfo *exception)
Definition: configure.c:654
static void * DestroyLogElement(void *log_info)
Definition: log.c:875
TimerInfo timer
Definition: log.c:137
MagickExport void GetPathComponent(const char *path, PathType type, char *component)
Definition: utility.c:1213
MagickExport ssize_t FormatLocaleFile(FILE *file, const char *magick_restrict format,...)
Definition: locale.c:409
MagickBooleanType
Definition: magick-type.h:158
MagickExport const LogInfo ** GetLogInfoList(const char *pattern, size_t *number_preferences, ExceptionInfo *exception)
Definition: log.c:476
#define DirectorySeparator
Definition: studio.h:259
unsigned int MagickStatusType
Definition: magick-type.h:121
MagickExport char * AcquireString(const char *source)
Definition: string.c:129
MagickExport char ** GetLogList(const char *pattern, size_t *number_preferences, ExceptionInfo *exception)
Definition: log.c:569
MagickExport const char * CommandOptionToMnemonic(const CommandOption option, const ssize_t type)
Definition: option.c:2678
MagickExport void SetLogFormat(const char *format)
Definition: log.c:1785
#define MagickLibVersionText
Definition: version.h:31
Definition: log.c:108
LogEventType event
Definition: log.c:96
MagickBooleanType stealth
Definition: log.c:133
MagickExport void * AcquireQuantumMemory(const size_t count, const size_t quantum)
Definition: memory.c:533
static FILE * fopen_utf8(const char *path, const char *mode)
MagickExport int LocaleNCompare(const char *p, const char *q, const size_t length)
Definition: locale.c:1540
MagickExport ssize_t FormatMagickTime(const time_t time, const size_t length, char *timestamp)
Definition: string.c:1188
static LogHandlerType ParseLogHandlers(const char *)
Definition: log.c:1679
char * format
Definition: log.c:117
static LinkedListInfo * AcquireLogCache(const char *filename, ExceptionInfo *exception)
Definition: log.c:259
MagickExport MagickBooleanType GlobExpression(const char *expression, const char *pattern, const MagickBooleanType case_insensitive)
Definition: token.c:347
#define MagickPathExtent
MagickExport const char * GetLogName(void)
Definition: log.c:633
const char * filename
Definition: log.c:155
MagickExport MagickBooleanType IsEventLogging(void)
Definition: log.c:717
void(* MagickLogMethod)(const LogEventType, const char *)
Definition: log.h:65
const LogHandlerType handler_mask
Definition: log.c:152
MagickExport void CloseMagickLog(void)
Definition: log.c:348
MagickExport MagickBooleanType ThrowMagickException(ExceptionInfo *exception, const char *module, const char *function, const size_t line, const ExceptionType severity, const char *tag, const char *format,...)
Definition: exception.c:1064
const char * module
Definition: static.c:77
size_t limit
Definition: log.c:123
MagickExport MagickBooleanType LogMagickEvent(const LogEventType type, const char *module, const char *function, const size_t line, const char *format,...)
Definition: log.c:1398
MagickExport MagickBooleanType IsPathAccessible(const char *path)
Definition: utility.c:1462
char * filename
Definition: log.c:117
static void CheckEventLogging()
Definition: log.c:662
MagickExport LinkedListInfo * NewLinkedList(const size_t capacity)
Definition: linked-list.c:713
MagickExport size_t CopyMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:755
MagickExport const char * GetClientName(void)
Definition: client.c:64
static MagickBooleanType event_logging
Definition: log.c:213
struct _HandlerInfo HandlerInfo
static char * TranslateFilename(const LogInfo *log_info)
Definition: log.c:1169
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1440
Definition: log.c:90
#define GetMagickModule()
Definition: log.h:28
MagickExport const char * GetStringInfoPath(const StringInfo *string_info)
Definition: string.c:1382
MagickExport void GetTimerInfo(TimerInfo *time_info)
Definition: timer.c:280
const LogEventType event_mask
Definition: log.c:149
MagickExport void SetLogMethod(MagickLogMethod method)
Definition: log.c:1826
MagickExport void GetNextToken(const char *start, const char **end, const size_t extent, char *token)
Definition: token.c:172
MagickExport char * DestroyString(char *string)
Definition: string.c:823
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:462
LogEventType event_mask
Definition: log.c:111
MagickExport void ActivateSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:97
static LinkedListInfo * log_cache
Definition: log.c:210
MagickExport size_t GetNumberOfElementsInLinkedList(const LinkedListInfo *list_info)
Definition: linked-list.c:348
static char log_name[MagickPathExtent]
Definition: log.c:207
MagickExport double GetElapsedTime(TimerInfo *time_info)
Definition: timer.c:247
FILE * file
Definition: log.c:127
static SemaphoreInfo * log_semaphore
Definition: log.c:217
static const LogMapInfo LogMap[]
Definition: log.c:200
char * name
Definition: log.c:117
static SemaphoreInfo * event_semaphore
Definition: log.c:216
MagickExport void * RelinquishMagickMemory(void *memory)
Definition: memory.c:1054
size_t generation
Definition: log.c:130
static size_t GetMagickThreadSignature(void)
MagickExport const char * SetLogName(const char *name)
Definition: log.c:1869
#define MagickPrivate
MagickPrivate char * FileToXML(const char *, const size_t)
Definition: xml-tree.c:599
Definition: log.h:36
#define MagickExport
static char * TranslateEvent(const char *module, const char *function, const size_t line, const char *domain, const char *event)
Definition: log.c:947
struct _LogMapInfo LogMapInfo
static int LogCompare(const void *x, const void *y)
Definition: log.c:554
static LogInfo * GetLogInfo(const char *, ExceptionInfo *)
Definition: log.c:396
MagickExport void RelinquishSemaphoreInfo(SemaphoreInfo **semaphore_info)
Definition: semaphore.c:351
MagickExport LinkedListInfo * DestroyConfigureOptions(LinkedListInfo *options)
Definition: configure.c:326
MagickExport char * ConstantString(const char *source)
Definition: string.c:700
MagickPrivate void LogComponentTerminus(void)
Definition: log.c:897
MagickExport ExceptionInfo * DestroyExceptionInfo(ExceptionInfo *exception)
Definition: exception.c:411
#define LogFilename
Definition: log.c:72
MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
Definition: timer.c:122
LogHandlerType
Definition: log.c:77