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