MagickCore  7.0.7
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://www.imagemagick.org/script/license.php %
27 % %
28 % Unless required by applicable law or agreed to in writing, software %
29 % distributed under the License is distributed on an "AS IS" BASIS, %
30 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. %
31 % See the License for the specific language governing permissions and %
32 % limitations under the License. %
33 % %
34 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
35 %
36 %
37 */
38 
39 /*
40  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
123  generations,
124  limit;
125 
126  FILE
128 
129  size_t
131 
133  append,
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
155  *filename,
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) ResetMagickMemory(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 
677  }
678 }
679 
681 {
682  if (log_cache == (LinkedListInfo *) NULL)
683  {
684  if (log_semaphore == (SemaphoreInfo *) NULL)
687  if (log_cache == (LinkedListInfo *) NULL)
688  {
691  }
693  }
694  return(log_cache != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse);
695 }
696 
697 /*
698 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
699 % %
700 % %
701 % %
702 % I s E v e n t L o g g i n g %
703 % %
704 % %
705 % %
706 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
707 %
708 % IsEventLogging() returns MagickTrue if debug of events is enabled otherwise
709 % MagickFalse.
710 %
711 % The format of the IsEventLogging method is:
712 %
713 % MagickBooleanType IsEventLogging(void)
714 %
715 */
717 {
718  return(event_logging);
719 }
720 
721 /*
722 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
723 % %
724 % %
725 % %
726 % L i s t L o g I n f o %
727 % %
728 % %
729 % %
730 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
731 %
732 % ListLogInfo() lists the log info to a file.
733 %
734 % The format of the ListLogInfo method is:
735 %
736 % MagickBooleanType ListLogInfo(FILE *file,ExceptionInfo *exception)
737 %
738 % A description of each parameter follows.
739 %
740 % o file: An pointer to a FILE.
741 %
742 % o exception: return any errors or warnings in this structure.
743 %
744 */
746 {
747 #define MegabytesToBytes(value) ((MagickSizeType) (value)*1024*1024)
748 
749  const char
750  *path;
751 
752  const LogInfo
753  **log_info;
754 
755  register ssize_t
756  i;
757 
758  size_t
759  number_aliases;
760 
761  ssize_t
762  j;
763 
764  if (file == (const FILE *) NULL)
765  file=stdout;
766  log_info=GetLogInfoList("*",&number_aliases,exception);
767  if (log_info == (const LogInfo **) NULL)
768  return(MagickFalse);
769  j=0;
770  path=(const char *) NULL;
771  for (i=0; i < (ssize_t) number_aliases; i++)
772  {
773  if (log_info[i]->stealth != MagickFalse)
774  continue;
775  if ((path == (const char *) NULL) ||
776  (LocaleCompare(path,log_info[i]->path) != 0))
777  {
778  size_t
779  length;
780 
781  if (log_info[i]->path != (char *) NULL)
782  (void) FormatLocaleFile(file,"\nPath: %s\n\n",log_info[i]->path);
783  length=0;
784  for (j=0; j < (ssize_t) (8*sizeof(LogHandlerType)); j++)
785  {
786  size_t
787  mask;
788 
789  if (LogHandlers[j].name == (const char *) NULL)
790  break;
791  mask=1;
792  mask<<=j;
793  if ((log_info[i]->handler_mask & mask) != 0)
794  {
795  (void) FormatLocaleFile(file,"%s ",LogHandlers[j].name);
796  length+=strlen(LogHandlers[j].name);
797  }
798  }
799  for (j=(ssize_t) length; j <= 12; j++)
800  (void) FormatLocaleFile(file," ");
801  (void) FormatLocaleFile(file," Generations Limit Format\n");
802  (void) FormatLocaleFile(file,"-----------------------------------------"
803  "--------------------------------------\n");
804  }
805  path=log_info[i]->path;
806  if (log_info[i]->filename != (char *) NULL)
807  {
808  (void) FormatLocaleFile(file,"%s",log_info[i]->filename);
809  for (j=(ssize_t) strlen(log_info[i]->filename); j <= 16; j++)
810  (void) FormatLocaleFile(file," ");
811  }
812  (void) FormatLocaleFile(file,"%9g ",(double) log_info[i]->generations);
813  (void) FormatLocaleFile(file,"%8g ",(double) log_info[i]->limit);
814  if (log_info[i]->format != (char *) NULL)
815  (void) FormatLocaleFile(file,"%s",log_info[i]->format);
816  (void) FormatLocaleFile(file,"\n");
817  }
818  (void) fflush(file);
819  log_info=(const LogInfo **) RelinquishMagickMemory((void *) log_info);
820  return(MagickTrue);
821 }
822 
823 /*
824 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
825 % %
826 % %
827 % %
828 + L o g C o m p o n e n t G e n e s i s %
829 % %
830 % %
831 % %
832 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
833 %
834 % LogComponentGenesis() instantiates the log component.
835 %
836 % The format of the LogComponentGenesis method is:
837 %
838 % MagickBooleanType LogComponentGenesis(void)
839 %
840 */
842 {
844  *exception;
845 
846  if (log_semaphore == (SemaphoreInfo *) NULL)
848  exception=AcquireExceptionInfo();
849  (void) GetLogInfo("*",exception);
850  exception=DestroyExceptionInfo(exception);
852  return(MagickTrue);
853 }
854 
855 /*
856 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
857 % %
858 % %
859 % %
860 + L o g C o m p o n e n t T e r m i n u s %
861 % %
862 % %
863 % %
864 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
865 %
866 % LogComponentTerminus() destroys the logging component.
867 %
868 % The format of the LogComponentTerminus method is:
869 %
870 % LogComponentTerminus(void)
871 %
872 */
873 
874 static void *DestroyLogElement(void *log_info)
875 {
876  register LogInfo
877  *p;
878 
879  p=(LogInfo *) log_info;
880  if (p->file != (FILE *) NULL)
881  {
882  (void) FormatLocaleFile(p->file,"</log>\n");
883  (void) fclose(p->file);
884  p->file=(FILE *) NULL;
885  }
886  if (p->format != (char *) NULL)
887  p->format=DestroyString(p->format);
888  if (p->path != (char *) NULL)
889  p->path=DestroyString(p->path);
890  if (p->filename != (char *) NULL)
893  return((void *) NULL);
894 }
895 
897 {
898  if (event_semaphore == (SemaphoreInfo *) NULL)
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=time((time_t *) NULL);
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 (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 > (ssize_t) (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 > 200)
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) ResetMagickMemory(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 != (char *) NULL; 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 == (char *) NULL)
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:163
MagickExport void * GetValueFromLinkedList(LinkedListInfo *list_info, const size_t index)
Definition: linked-list.c:382
size_t signature
Definition: log.c:140
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: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
MagickExport ssize_t ParseCommandOption(const CommandOption option, const MagickBooleanType list, const char *options)
Definition: option.c:2953
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:1445
MagickExport size_t ConcatenateMagickString(char *destination, const char *source, const size_t length)
Definition: string.c:410
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:841
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:473
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:1277
MagickExport MagickBooleanType ListLogInfo(FILE *file, ExceptionInfo *exception)
Definition: log.c:745
MagickExport LogEventType SetLogEventMask(const char *events)
Definition: log.c:1737
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:680
MagickExport unsigned char * GetStringInfoDatum(const StringInfo *string_info)
Definition: string.c:1283
MagickExport LinkedListInfo * GetConfigureOptions(const char *filename, ExceptionInfo *exception)
Definition: configure.c:654
static void * DestroyLogElement(void *log_info)
Definition: log.c:874
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:378
MagickBooleanType
Definition: magick-type.h:156
MagickExport const LogInfo ** GetLogInfoList(const char *pattern, size_t *number_preferences, ExceptionInfo *exception)
Definition: log.c:476
#define DirectorySeparator
Definition: studio.h:254
unsigned int MagickStatusType
Definition: magick-type.h:119
MagickExport char * AcquireString(const char *source)
Definition: string.c:124
MagickExport char ** GetLogList(const char *pattern, size_t *number_preferences, ExceptionInfo *exception)
Definition: log.c:569
MagickExport void * ResetMagickMemory(void *memory, int byte, const size_t size)
Definition: memory.c:1164
MagickExport const char * CommandOptionToMnemonic(const CommandOption option, const ssize_t type)
Definition: option.c:2666
MagickExport void SetLogFormat(const char *format)
Definition: log.c:1784
#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:529
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:1509
MagickExport ssize_t FormatMagickTime(const time_t time, const size_t length, char *timestamp)
Definition: string.c:1176
static LogHandlerType ParseLogHandlers(const char *)
Definition: log.c:1678
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:349
#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:716
void(* MagickLogMethod)(const LogEventType, const char *)
Definition: log.h:65
MagickExport MagickBooleanType static void * AcquireCriticalMemory(const size_t size)
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:1058
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:1397
MagickExport MagickBooleanType IsPathAccessible(const char *path)
Definition: utility.c:1466
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:742
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:1168
MagickExport int LocaleCompare(const char *p, const char *q)
Definition: locale.c:1409
Definition: log.c:90
#define GetMagickModule()
Definition: log.h:28
MagickExport const char * GetStringInfoPath(const StringInfo *string_info)
Definition: string.c:1341
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:1825
MagickExport void GetNextToken(const char *start, const char **end, const size_t extent, char *token)
Definition: token.c:171
MagickExport char * DestroyString(char *string)
Definition: string.c:810
MagickExport void * AcquireMagickMemory(const size_t size)
Definition: memory.c:458
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:1038
size_t generation
Definition: log.c:130
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:600
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:946
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:687
MagickPrivate void LogComponentTerminus(void)
Definition: log.c:896
MagickExport ExceptionInfo * DestroyExceptionInfo(ExceptionInfo *exception)
Definition: exception.c:417
#define LogFilename
Definition: log.c:72
MagickExport MagickBooleanType ContinueTimer(TimerInfo *time_info)
Definition: timer.c:122
LogHandlerType
Definition: log.c:77