|
MagickCore
6.7.5
|
00001 /* 00002 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00003 % % 00004 % % 00005 % % 00006 % L OOO GGGG % 00007 % L O O G % 00008 % L O O G GG % 00009 % L O O G G % 00010 % LLLLL OOO GGG % 00011 % % 00012 % % 00013 % MagickCore Log Events % 00014 % % 00015 % Software Design % 00016 % John Cristy % 00017 % September 2002 % 00018 % % 00019 % % 00020 % Copyright 1999-2012 ImageMagick Studio LLC, a non-profit organization % 00021 % dedicated to making software imaging solutions freely available. % 00022 % % 00023 % You may not use this file except in compliance with the License. You may % 00024 % obtain a copy of the License at % 00025 % % 00026 % http://www.imagemagick.org/script/license.php % 00027 % % 00028 % Unless required by applicable law or agreed to in writing, software % 00029 % distributed under the License is distributed on an "AS IS" BASIS, % 00030 % WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. % 00031 % See the License for the specific language governing permissions and % 00032 % limitations under the License. % 00033 % % 00034 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00035 % 00036 % 00037 */ 00038 00039 /* 00040 Include declarations. 00041 */ 00042 #include "MagickCore/studio.h" 00043 #include "MagickCore/blob.h" 00044 #include "MagickCore/client.h" 00045 #include "MagickCore/configure.h" 00046 #include "MagickCore/configure-private.h" 00047 #include "MagickCore/exception.h" 00048 #include "MagickCore/exception-private.h" 00049 #include "MagickCore/hashmap.h" 00050 #include "MagickCore/log.h" 00051 #include "MagickCore/log-private.h" 00052 #include "MagickCore/memory_.h" 00053 #include "MagickCore/option.h" 00054 #include "MagickCore/semaphore.h" 00055 #include "MagickCore/timer.h" 00056 #include "MagickCore/string_.h" 00057 #include "MagickCore/string-private.h" 00058 #include "MagickCore/token.h" 00059 #include "MagickCore/thread_.h" 00060 #include "MagickCore/thread-private.h" 00061 #include "MagickCore/utility.h" 00062 #include "MagickCore/utility-private.h" 00063 #include "MagickCore/version.h" 00064 #include "MagickCore/xml-tree.h" 00065 00066 /* 00067 Define declarations. 00068 */ 00069 #define LogFilename "log.xml" 00070 00071 /* 00072 Typedef declarations. 00073 */ 00074 typedef enum 00075 { 00076 UndefinedHandler = 0x0000, 00077 NoHandler = 0x0000, 00078 ConsoleHandler = 0x0001, 00079 StdoutHandler = 0x0002, 00080 StderrHandler = 0x0004, 00081 FileHandler = 0x0008, 00082 DebugHandler = 0x0010, 00083 EventHandler = 0x0020 00084 } LogHandlerType; 00085 00086 typedef struct _EventInfo 00087 { 00088 char 00089 *name; 00090 00091 LogEventType 00092 event; 00093 } EventInfo; 00094 00095 typedef struct _HandlerInfo 00096 { 00097 const char 00098 *name; 00099 00100 LogHandlerType 00101 handler; 00102 } HandlerInfo; 00103 00104 struct _LogInfo 00105 { 00106 LogEventType 00107 event_mask; 00108 00109 LogHandlerType 00110 handler_mask; 00111 00112 char 00113 *path, 00114 *name, 00115 *filename, 00116 *format; 00117 00118 size_t 00119 generations, 00120 limit; 00121 00122 FILE 00123 *file; 00124 00125 size_t 00126 generation; 00127 00128 MagickBooleanType 00129 append, 00130 exempt, 00131 stealth; 00132 00133 TimerInfo 00134 timer; 00135 00136 size_t 00137 signature; 00138 }; 00139 00140 typedef struct _LogMapInfo 00141 { 00142 const LogEventType 00143 event_mask; 00144 00145 const LogHandlerType 00146 handler_mask; 00147 00148 const char 00149 *filename, 00150 *format; 00151 } LogMapInfo; 00152 00153 /* 00154 Static declarations. 00155 */ 00156 static const HandlerInfo 00157 LogHandlers[] = 00158 { 00159 { "console", ConsoleHandler }, 00160 { "debug", DebugHandler }, 00161 { "event", EventHandler }, 00162 { "file", FileHandler }, 00163 { "none", NoHandler }, 00164 { "stderr", StderrHandler }, 00165 { "stdout", StdoutHandler }, 00166 { (char *) NULL, UndefinedHandler } 00167 }; 00168 00169 static const LogMapInfo 00170 LogMap[] = 00171 { 00172 { NoEvents, ConsoleHandler, "Magick-%d.log", 00173 "%t %r %u %v %d %c[%p]: %m/%f/%l/%d\n %e" } 00174 }; 00175 00176 static char 00177 log_name[MaxTextExtent] = "Magick"; 00178 00179 static LinkedListInfo 00180 *log_list = (LinkedListInfo *) NULL; 00181 00182 static SemaphoreInfo 00183 *log_semaphore = (SemaphoreInfo *) NULL; 00184 00185 static volatile MagickBooleanType 00186 instantiate_log = MagickFalse; 00187 00188 /* 00189 Forward declarations. 00190 */ 00191 static LogHandlerType 00192 ParseLogHandlers(const char *); 00193 00194 static LogInfo 00195 *GetLogInfo(const char *,ExceptionInfo *); 00196 00197 static MagickBooleanType 00198 InitializeLogList(ExceptionInfo *), 00199 LoadLogLists(const char *,ExceptionInfo *); 00200 00201 /* 00202 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00203 % % 00204 % % 00205 % % 00206 % C l o s e M a g i c k L o g % 00207 % % 00208 % % 00209 % % 00210 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00211 % 00212 % CloseMagickLog() closes the Magick log. 00213 % 00214 % The format of the CloseMagickLog method is: 00215 % 00216 % CloseMagickLog(void) 00217 % 00218 */ 00219 MagickExport void CloseMagickLog(void) 00220 { 00221 ExceptionInfo 00222 *exception; 00223 00224 LogInfo 00225 *log_info; 00226 00227 if (IsEventLogging() == MagickFalse) 00228 return; 00229 exception=AcquireExceptionInfo(); 00230 log_info=GetLogInfo("*",exception); 00231 exception=DestroyExceptionInfo(exception); 00232 LockSemaphoreInfo(log_semaphore); 00233 if (log_info->file != (FILE *) NULL) 00234 { 00235 if (log_info->append == MagickFalse) 00236 (void) FormatLocaleFile(log_info->file,"</log>\n"); 00237 (void) fclose(log_info->file); 00238 log_info->file=(FILE *) NULL; 00239 } 00240 UnlockSemaphoreInfo(log_semaphore); 00241 } 00242 00243 /* 00244 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00245 % % 00246 % % 00247 % % 00248 + G e t L o g I n f o % 00249 % % 00250 % % 00251 % % 00252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00253 % 00254 % GetLogInfo() searches the log list for the specified name and if found 00255 % returns attributes for that log. 00256 % 00257 % The format of the GetLogInfo method is: 00258 % 00259 % LogInfo *GetLogInfo(const char *name,ExceptionInfo *exception) 00260 % 00261 % A description of each parameter follows: 00262 % 00263 % o name: the log name. 00264 % 00265 % o exception: return any errors or warnings in this structure. 00266 % 00267 */ 00268 static LogInfo *GetLogInfo(const char *name,ExceptionInfo *exception) 00269 { 00270 register LogInfo 00271 *p; 00272 00273 assert(exception != (ExceptionInfo *) NULL); 00274 if ((log_list == (LinkedListInfo *) NULL) || (instantiate_log == MagickFalse)) 00275 if (InitializeLogList(exception) == MagickFalse) 00276 return((LogInfo *) NULL); 00277 if ((log_list == (LinkedListInfo *) NULL) || 00278 (IsLinkedListEmpty(log_list) != MagickFalse)) 00279 return((LogInfo *) NULL); 00280 if ((name == (const char *) NULL) || (LocaleCompare(name,"*") == 0)) 00281 return((LogInfo *) GetValueFromLinkedList(log_list,0)); 00282 /* 00283 Search for log tag. 00284 */ 00285 LockSemaphoreInfo(log_semaphore); 00286 ResetLinkedListIterator(log_list); 00287 p=(LogInfo *) GetNextValueInLinkedList(log_list); 00288 while (p != (LogInfo *) NULL) 00289 { 00290 if (LocaleCompare(name,p->name) == 0) 00291 break; 00292 p=(LogInfo *) GetNextValueInLinkedList(log_list); 00293 } 00294 if (p != (LogInfo *) NULL) 00295 (void) InsertValueInLinkedList(log_list,0, 00296 RemoveElementByValueFromLinkedList(log_list,p)); 00297 UnlockSemaphoreInfo(log_semaphore); 00298 return(p); 00299 } 00300 00301 /* 00302 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00303 % % 00304 % % 00305 % % 00306 % G e t L o g I n f o L i s t % 00307 % % 00308 % % 00309 % % 00310 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00311 % 00312 % GetLogInfoList() returns any logs that match the specified pattern. 00313 % 00314 % The format of the GetLogInfoList function is: 00315 % 00316 % const LogInfo **GetLogInfoList(const char *pattern, 00317 % size_t *number_preferences,ExceptionInfo *exception) 00318 % 00319 % A description of each parameter follows: 00320 % 00321 % o pattern: Specifies a pointer to a text string containing a pattern. 00322 % 00323 % o number_preferences: This integer returns the number of logs in the list. 00324 % 00325 % o exception: return any errors or warnings in this structure. 00326 % 00327 */ 00328 #if defined(__cplusplus) || defined(c_plusplus) 00329 extern "C" { 00330 #endif 00331 00332 static int LogInfoCompare(const void *x,const void *y) 00333 { 00334 const LogInfo 00335 **p, 00336 **q; 00337 00338 p=(const LogInfo **) x, 00339 q=(const LogInfo **) y; 00340 if (LocaleCompare((*p)->path,(*q)->path) == 0) 00341 return(LocaleCompare((*p)->name,(*q)->name)); 00342 return(LocaleCompare((*p)->path,(*q)->path)); 00343 } 00344 00345 #if defined(__cplusplus) || defined(c_plusplus) 00346 } 00347 #endif 00348 00349 MagickExport const LogInfo **GetLogInfoList(const char *pattern, 00350 size_t *number_preferences,ExceptionInfo *exception) 00351 { 00352 const LogInfo 00353 **preferences; 00354 00355 register const LogInfo 00356 *p; 00357 00358 register ssize_t 00359 i; 00360 00361 /* 00362 Allocate log list. 00363 */ 00364 assert(pattern != (char *) NULL); 00365 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 00366 assert(number_preferences != (size_t *) NULL); 00367 *number_preferences=0; 00368 p=GetLogInfo("*",exception); 00369 if (p == (const LogInfo *) NULL) 00370 return((const LogInfo **) NULL); 00371 preferences=(const LogInfo **) AcquireQuantumMemory((size_t) 00372 GetNumberOfElementsInLinkedList(log_list)+1UL,sizeof(*preferences)); 00373 if (preferences == (const LogInfo **) NULL) 00374 return((const LogInfo **) NULL); 00375 /* 00376 Generate log list. 00377 */ 00378 LockSemaphoreInfo(log_semaphore); 00379 ResetLinkedListIterator(log_list); 00380 p=(const LogInfo *) GetNextValueInLinkedList(log_list); 00381 for (i=0; p != (const LogInfo *) NULL; ) 00382 { 00383 if ((p->stealth == MagickFalse) && 00384 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)) 00385 preferences[i++]=p; 00386 p=(const LogInfo *) GetNextValueInLinkedList(log_list); 00387 } 00388 UnlockSemaphoreInfo(log_semaphore); 00389 qsort((void *) preferences,(size_t) i,sizeof(*preferences),LogInfoCompare); 00390 preferences[i]=(LogInfo *) NULL; 00391 *number_preferences=(size_t) i; 00392 return(preferences); 00393 } 00394 00395 /* 00396 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00397 % % 00398 % % 00399 % % 00400 % G e t L o g L i s t % 00401 % % 00402 % % 00403 % % 00404 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00405 % 00406 % GetLogList() returns any logs that match the specified pattern. 00407 % 00408 % The format of the GetLogList function is: 00409 % 00410 % char **GetLogList(const char *pattern,size_t *number_preferences, 00411 % ExceptionInfo *exception) 00412 % 00413 % A description of each parameter follows: 00414 % 00415 % o pattern: Specifies a pointer to a text string containing a pattern. 00416 % 00417 % o number_preferences: This integer returns the number of logs in the list. 00418 % 00419 % o exception: return any errors or warnings in this structure. 00420 % 00421 */ 00422 00423 #if defined(__cplusplus) || defined(c_plusplus) 00424 extern "C" { 00425 #endif 00426 00427 static int LogCompare(const void *x,const void *y) 00428 { 00429 register const char 00430 **p, 00431 **q; 00432 00433 p=(const char **) x; 00434 q=(const char **) y; 00435 return(LocaleCompare(*p,*q)); 00436 } 00437 00438 #if defined(__cplusplus) || defined(c_plusplus) 00439 } 00440 #endif 00441 00442 MagickExport char **GetLogList(const char *pattern, 00443 size_t *number_preferences,ExceptionInfo *exception) 00444 { 00445 char 00446 **preferences; 00447 00448 register const LogInfo 00449 *p; 00450 00451 register ssize_t 00452 i; 00453 00454 /* 00455 Allocate log list. 00456 */ 00457 assert(pattern != (char *) NULL); 00458 (void) LogMagickEvent(TraceEvent,GetMagickModule(),"%s",pattern); 00459 assert(number_preferences != (size_t *) NULL); 00460 *number_preferences=0; 00461 p=GetLogInfo("*",exception); 00462 if (p == (const LogInfo *) NULL) 00463 return((char **) NULL); 00464 preferences=(char **) AcquireQuantumMemory((size_t) 00465 GetNumberOfElementsInLinkedList(log_list)+1UL,sizeof(*preferences)); 00466 if (preferences == (char **) NULL) 00467 return((char **) NULL); 00468 /* 00469 Generate log list. 00470 */ 00471 LockSemaphoreInfo(log_semaphore); 00472 ResetLinkedListIterator(log_list); 00473 p=(const LogInfo *) GetNextValueInLinkedList(log_list); 00474 for (i=0; p != (const LogInfo *) NULL; ) 00475 { 00476 if ((p->stealth == MagickFalse) && 00477 (GlobExpression(p->name,pattern,MagickFalse) != MagickFalse)) 00478 preferences[i++]=ConstantString(p->name); 00479 p=(const LogInfo *) GetNextValueInLinkedList(log_list); 00480 } 00481 UnlockSemaphoreInfo(log_semaphore); 00482 qsort((void *) preferences,(size_t) i,sizeof(*preferences),LogCompare); 00483 preferences[i]=(char *) NULL; 00484 *number_preferences=(size_t) i; 00485 return(preferences); 00486 } 00487 00488 /* 00489 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00490 % % 00491 % % 00492 % % 00493 % G e t L o g N a m e % 00494 % % 00495 % % 00496 % % 00497 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00498 % 00499 % GetLogName() returns the current log name. 00500 % 00501 % The format of the GetLogName method is: 00502 % 00503 % const char *GetLogName(void) 00504 % 00505 */ 00506 MagickExport const char *GetLogName(void) 00507 { 00508 return(log_name); 00509 } 00510 00511 /* 00512 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00513 % % 00514 % % 00515 % % 00516 + I n i t i a l i z e L o g L i s t % 00517 % % 00518 % % 00519 % % 00520 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00521 % 00522 % InitializeLogList() initialize the log list. 00523 % 00524 % The format of the InitializeLogList method is: 00525 % 00526 % MagickBooleanType InitializeLogList(ExceptionInfo *exception) 00527 % 00528 % A description of each parameter follows. 00529 % 00530 % o exception: return any errors or warnings in this structure. 00531 % 00532 */ 00533 static MagickBooleanType InitializeLogList(ExceptionInfo *exception) 00534 { 00535 if ((log_list == (LinkedListInfo *) NULL) && (instantiate_log == MagickFalse)) 00536 { 00537 if (log_semaphore == (SemaphoreInfo *) NULL) 00538 AcquireSemaphoreInfo(&log_semaphore); 00539 LockSemaphoreInfo(log_semaphore); 00540 if ((log_list == (LinkedListInfo *) NULL) && 00541 (instantiate_log == MagickFalse)) 00542 { 00543 (void) LoadLogLists(LogFilename,exception); 00544 instantiate_log=MagickTrue; 00545 } 00546 UnlockSemaphoreInfo(log_semaphore); 00547 } 00548 return(log_list != (LinkedListInfo *) NULL ? MagickTrue : MagickFalse); 00549 } 00550 00551 /* 00552 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00553 % % 00554 % % 00555 % % 00556 % I s E v e n t L o g g i n g % 00557 % % 00558 % % 00559 % % 00560 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00561 % 00562 % IsEventLogging() returns MagickTrue if debug of events is enabled otherwise 00563 % MagickFalse. 00564 % 00565 % The format of the IsEventLogging method is: 00566 % 00567 % MagickBooleanType IsEventLogging(void) 00568 % 00569 */ 00570 MagickExport MagickBooleanType IsEventLogging(void) 00571 { 00572 const LogInfo 00573 *log_info; 00574 00575 ExceptionInfo 00576 *exception; 00577 00578 if ((log_list == (LinkedListInfo *) NULL) || 00579 (IsLinkedListEmpty(log_list) != MagickFalse)) 00580 return(MagickFalse); 00581 exception=AcquireExceptionInfo(); 00582 log_info=GetLogInfo("*",exception); 00583 exception=DestroyExceptionInfo(exception); 00584 return(log_info->event_mask != NoEvents ? MagickTrue : MagickFalse); 00585 } 00586 /* 00587 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00588 % % 00589 % % 00590 % % 00591 % L i s t L o g I n f o % 00592 % % 00593 % % 00594 % % 00595 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00596 % 00597 % ListLogInfo() lists the log info to a file. 00598 % 00599 % The format of the ListLogInfo method is: 00600 % 00601 % MagickBooleanType ListLogInfo(FILE *file,ExceptionInfo *exception) 00602 % 00603 % A description of each parameter follows. 00604 % 00605 % o file: An pointer to a FILE. 00606 % 00607 % o exception: return any errors or warnings in this structure. 00608 % 00609 */ 00610 MagickExport MagickBooleanType ListLogInfo(FILE *file,ExceptionInfo *exception) 00611 { 00612 #define MegabytesToBytes(value) ((MagickSizeType) (value)*1024*1024) 00613 00614 char 00615 limit[MaxTextExtent]; 00616 00617 const char 00618 *path; 00619 00620 const LogInfo 00621 **log_info; 00622 00623 register ssize_t 00624 i; 00625 00626 size_t 00627 number_aliases; 00628 00629 ssize_t 00630 j; 00631 00632 if (file == (const FILE *) NULL) 00633 file=stdout; 00634 log_info=GetLogInfoList("*",&number_aliases,exception); 00635 if (log_info == (const LogInfo **) NULL) 00636 return(MagickFalse); 00637 j=0; 00638 path=(const char *) NULL; 00639 for (i=0; i < (ssize_t) number_aliases; i++) 00640 { 00641 if (log_info[i]->stealth != MagickFalse) 00642 continue; 00643 if ((path == (const char *) NULL) || 00644 (LocaleCompare(path,log_info[i]->path) != 0)) 00645 { 00646 if (log_info[i]->path != (char *) NULL) 00647 (void) FormatLocaleFile(file,"\nPath: %s\n\n",log_info[i]->path); 00648 (void) FormatLocaleFile(file, 00649 "Filename Generations Limit Format\n"); 00650 (void) FormatLocaleFile(file, 00651 "-------------------------------------------------" 00652 "------------------------------\n"); 00653 } 00654 path=log_info[i]->path; 00655 if (log_info[i]->filename != (char *) NULL) 00656 { 00657 (void) FormatLocaleFile(file,"%s",log_info[i]->filename); 00658 for (j=(ssize_t) strlen(log_info[i]->filename); j <= 16; j++) 00659 (void) FormatLocaleFile(file," "); 00660 } 00661 (void) FormatLocaleFile(file,"%9g ",(double) log_info[i]->generations); 00662 (void) FormatMagickSize(MegabytesToBytes(log_info[i]->limit),MagickFalse, 00663 limit); 00664 (void) FormatLocaleFile(file,"%8sB ",limit); 00665 if (log_info[i]->format != (char *) NULL) 00666 (void) FormatLocaleFile(file,"%s",log_info[i]->format); 00667 (void) FormatLocaleFile(file,"\n"); 00668 } 00669 (void) fflush(file); 00670 log_info=(const LogInfo **) RelinquishMagickMemory((void *) log_info); 00671 return(MagickTrue); 00672 } 00673 00674 /* 00675 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00676 % % 00677 % % 00678 % % 00679 + L o g C o m p o n e n t G e n e s i s % 00680 % % 00681 % % 00682 % % 00683 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00684 % 00685 % LogComponentGenesis() instantiates the log component. 00686 % 00687 % The format of the LogComponentGenesis method is: 00688 % 00689 % MagickBooleanType LogComponentGenesis(void) 00690 % 00691 */ 00692 MagickPrivate MagickBooleanType LogComponentGenesis(void) 00693 { 00694 AcquireSemaphoreInfo(&log_semaphore); 00695 return(MagickTrue); 00696 } 00697 00698 /* 00699 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00700 % % 00701 % % 00702 % % 00703 + L o g C o m p o n e n t T e r m i n u s % 00704 % % 00705 % % 00706 % % 00707 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00708 % 00709 % LogComponentTerminus() destroys the logging component. 00710 % 00711 % The format of the LogComponentTerminus method is: 00712 % 00713 % LogComponentTerminus(void) 00714 % 00715 */ 00716 00717 static void *DestroyLogElement(void *log_info) 00718 { 00719 register LogInfo 00720 *p; 00721 00722 p=(LogInfo *) log_info; 00723 if (p->file != (FILE *) NULL) 00724 { 00725 if (p->append == MagickFalse) 00726 (void) FormatLocaleFile(p->file,"</log>\n"); 00727 (void) fclose(p->file); 00728 p->file=(FILE *) NULL; 00729 } 00730 if (p->exempt == MagickFalse) 00731 { 00732 if (p->format != (char *) NULL) 00733 p->format=DestroyString(p->format); 00734 if (p->path != (char *) NULL) 00735 p->path=DestroyString(p->path); 00736 if (p->filename != (char *) NULL) 00737 p->filename=DestroyString(p->filename); 00738 } 00739 p=(LogInfo *) RelinquishMagickMemory(p); 00740 return((void *) NULL); 00741 } 00742 00743 MagickPrivate void LogComponentTerminus(void) 00744 { 00745 if (log_semaphore == (SemaphoreInfo *) NULL) 00746 AcquireSemaphoreInfo(&log_semaphore); 00747 LockSemaphoreInfo(log_semaphore); 00748 if (log_list != (LinkedListInfo *) NULL) 00749 log_list=DestroyLinkedList(log_list,DestroyLogElement); 00750 instantiate_log=MagickFalse; 00751 UnlockSemaphoreInfo(log_semaphore); 00752 DestroySemaphoreInfo(&log_semaphore); 00753 } 00754 00755 /* 00756 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00757 % % 00758 % % 00759 % % 00760 % L o g M a g i c k E v e n t % 00761 % % 00762 % % 00763 % % 00764 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 00765 % 00766 % LogMagickEvent() logs an event as determined by the log configuration file. 00767 % If an error occurs, MagickFalse is returned otherwise MagickTrue. 00768 % 00769 % The format of the LogMagickEvent method is: 00770 % 00771 % MagickBooleanType LogMagickEvent(const LogEventType type, 00772 % const char *module,const char *function,const size_t line, 00773 % const char *format,...) 00774 % 00775 % A description of each parameter follows: 00776 % 00777 % o type: the event type. 00778 % 00779 % o filename: the source module filename. 00780 % 00781 % o function: the function name. 00782 % 00783 % o line: the line number of the source module. 00784 % 00785 % o format: the output format. 00786 % 00787 */ 00788 static char *TranslateEvent(const LogEventType magick_unused(type), 00789 const char *module,const char *function,const size_t line, 00790 const char *domain,const char *event) 00791 { 00792 char 00793 *text; 00794 00795 double 00796 elapsed_time, 00797 user_time; 00798 00799 ExceptionInfo 00800 *exception; 00801 00802 LogInfo 00803 *log_info; 00804 00805 register char 00806 *q; 00807 00808 register const char 00809 *p; 00810 00811 size_t 00812 extent; 00813 00814 time_t 00815 seconds; 00816 00817 exception=AcquireExceptionInfo(); 00818 log_info=(LogInfo *) GetLogInfo("*",exception); 00819 exception=DestroyExceptionInfo(exception); 00820 seconds=time((time_t *) NULL); 00821 elapsed_time=GetElapsedTime(&log_info->timer); 00822 user_time=GetUserTime(&log_info->timer); 00823 text=AcquireString(event); 00824 if (log_info->format == (char *) NULL) 00825 return(text); 00826 extent=strlen(event)+MaxTextExtent; 00827 if (LocaleCompare(log_info->format,"xml") == 0) 00828 { 00829 char 00830 timestamp[MaxTextExtent]; 00831 00832 /* 00833 Translate event in "XML" format. 00834 */ 00835 (void) FormatMagickTime(seconds,extent,timestamp); 00836 (void) FormatLocaleString(text,extent, 00837 "<entry>\n" 00838 " <timestamp>%s</timestamp>\n" 00839 " <elapsed-time>%lu:%02lu.%03lu</elapsed-time>\n" 00840 " <user-time>%0.3f</user-time>\n" 00841 " <process-id>%.20g</process-id>\n" 00842 " <thread-id>%.20g</thread-id>\n" 00843 " <module>%s</module>\n" 00844 " <function>%s</function>\n" 00845 " <line>%.20g</line>\n" 00846 " <domain>%s</domain>\n" 00847 " <event>%s</event>\n" 00848 "</entry>",timestamp,(unsigned long) (elapsed_time/60.0), 00849 (unsigned long) floor(fmod(elapsed_time,60.0)),(unsigned long) 00850 (1000.0*(elapsed_time-floor(elapsed_time))+0.5),user_time, 00851 (double) getpid(),(double) GetMagickThreadSignature(),module,function, 00852 (double) line,domain,event); 00853 return(text); 00854 } 00855 /* 00856 Translate event in "human readable" format. 00857 */ 00858 q=text; 00859 for (p=log_info->format; *p != '\0'; p++) 00860 { 00861 *q='\0'; 00862 if ((size_t) (q-text+MaxTextExtent) >= extent) 00863 { 00864 extent+=MaxTextExtent; 00865 text=(char *) ResizeQuantumMemory(text,extent+MaxTextExtent, 00866 sizeof(*text)); 00867 if (text == (char *) NULL) 00868 return((char *) NULL); 00869 q=text+strlen(text); 00870 } 00871 /* 00872 The format of the log is defined by embedding special format characters: 00873 00874 %c client name 00875 %d domain 00876 %e event 00877 %f function 00878 %g generation 00879 %l line 00880 %m module 00881 %n log name 00882 %p process id 00883 %r real CPU time 00884 %t wall clock time 00885 %u user CPU time 00886 %v version 00887 %% percent sign 00888 \n newline 00889 \r carriage return 00890 */ 00891 if ((*p == '\\') && (*(p+1) == 'r')) 00892 { 00893 *q++='\r'; 00894 p++; 00895 continue; 00896 } 00897 if ((*p == '\\') && (*(p+1) == 'n')) 00898 { 00899 *q++='\n'; 00900 p++; 00901 continue; 00902 } 00903 if (*p != '%') 00904 { 00905 *q++=(*p); 00906 continue; 00907 } 00908 p++; 00909 switch (*p) 00910 { 00911 case 'c': 00912 { 00913 q+=CopyMagickString(q,GetClientName(),extent); 00914 break; 00915 } 00916 case 'd': 00917 { 00918 q+=CopyMagickString(q,domain,extent); 00919 break; 00920 } 00921 case 'e': 00922 { 00923 q+=CopyMagickString(q,event,extent); 00924 break; 00925 } 00926 case 'f': 00927 { 00928 q+=CopyMagickString(q,function,extent); 00929 break; 00930 } 00931 case 'g': 00932 { 00933 if (log_info->generations == 0) 00934 { 00935 (void) CopyMagickString(q,"0",extent); 00936 q++; 00937 break; 00938 } 00939 q+=FormatLocaleString(q,extent,"%.20g",(double) (log_info->generation % 00940 log_info->generations)); 00941 break; 00942 } 00943 case 'l': 00944 { 00945 q+=FormatLocaleString(q,extent,"%.20g",(double) line); 00946 break; 00947 } 00948 case 'm': 00949 { 00950 register const char 00951 *p; 00952 00953 for (p=module+strlen(module)-1; p > module; p--) 00954 if (*p == *DirectorySeparator) 00955 { 00956 p++; 00957 break; 00958 } 00959 q+=CopyMagickString(q,p,extent); 00960 break; 00961 } 00962 case 'n': 00963 { 00964 q+=CopyMagickString(q,GetLogName(),extent); 00965 break; 00966 } 00967 case 'p': 00968 { 00969 q+=FormatLocaleString(q,extent,"%.20g",(double) getpid()); 00970 break; 00971 } 00972 case 'r': 00973 { 00974 q+=FormatLocaleString(q,extent,"%lu:%02lu.%03lu",(unsigned long) 00975 (elapsed_time/60.0),(unsigned long) floor(fmod(elapsed_time,60.0)), 00976 (unsigned long) (1000.0*(elapsed_time-floor(elapsed_time))+0.5)); 00977 break; 00978 } 00979 case 't': 00980 { 00981 q+=FormatMagickTime(seconds,extent,q); 00982 break; 00983 } 00984 case 'u': 00985 { 00986 q+=FormatLocaleString(q,extent,"%0.3fu",user_time); 00987 break; 00988 } 00989 case 'v': 00990 { 00991 q+=CopyMagickString(q,MagickLibVersionText,extent); 00992 break; 00993 } 00994 case '%': 00995 { 00996 *q++=(*p); 00997 break; 00998 } 00999 default: 01000 { 01001 *q++='%'; 01002 *q++=(*p); 01003 break; 01004 } 01005 } 01006 } 01007 *q='\0'; 01008 return(text); 01009 } 01010 01011 static char *TranslateFilename(const LogInfo *log_info) 01012 { 01013 char 01014 *filename; 01015 01016 register char 01017 *q; 01018 01019 register const char 01020 *p; 01021 01022 size_t 01023 extent; 01024 01025 /* 01026 Translate event in "human readable" format. 01027 */ 01028 assert(log_info != (LogInfo *) NULL); 01029 assert(log_info->filename != (char *) NULL); 01030 filename=AcquireString((char *) NULL); 01031 extent=MaxTextExtent; 01032 q=filename; 01033 for (p=log_info->filename; *p != '\0'; p++) 01034 { 01035 *q='\0'; 01036 if ((size_t) (q-filename+MaxTextExtent) >= extent) 01037 { 01038 extent+=MaxTextExtent; 01039 filename=(char *) ResizeQuantumMemory(filename,extent+MaxTextExtent, 01040 sizeof(*filename)); 01041 if (filename == (char *) NULL) 01042 return((char *) NULL); 01043 q=filename+strlen(filename); 01044 } 01045 /* 01046 The format of the filename is defined by embedding special format 01047 characters: 01048 01049 %c client name 01050 %n log name 01051 %p process id 01052 %v version 01053 %% percent sign 01054 */ 01055 if (*p != '%') 01056 { 01057 *q++=(*p); 01058 continue; 01059 } 01060 p++; 01061 switch (*p) 01062 { 01063 case 'c': 01064 { 01065 q+=CopyMagickString(q,GetClientName(),extent); 01066 break; 01067 } 01068 case 'g': 01069 { 01070 if (log_info->generations == 0) 01071 { 01072 (void) CopyMagickString(q,"0",extent); 01073 q++; 01074 break; 01075 } 01076 q+=FormatLocaleString(q,extent,"%.20g",(double) (log_info->generation % 01077 log_info->generations)); 01078 break; 01079 } 01080 case 'n': 01081 { 01082 q+=CopyMagickString(q,GetLogName(),extent); 01083 break; 01084 } 01085 case 'p': 01086 { 01087 q+=FormatLocaleString(q,extent,"%.20g",(double) getpid()); 01088 break; 01089 } 01090 case 'v': 01091 { 01092 q+=CopyMagickString(q,MagickLibVersionText,extent); 01093 break; 01094 } 01095 case '%': 01096 { 01097 *q++=(*p); 01098 break; 01099 } 01100 default: 01101 { 01102 *q++='%'; 01103 *q++=(*p); 01104 break; 01105 } 01106 } 01107 } 01108 *q='\0'; 01109 return(filename); 01110 } 01111 01112 MagickBooleanType LogMagickEventList(const LogEventType type,const char *module, 01113 const char *function,const size_t line,const char *format, 01114 va_list operands) 01115 { 01116 char 01117 event[MaxTextExtent], 01118 *text; 01119 01120 const char 01121 *domain; 01122 01123 ExceptionInfo 01124 *exception; 01125 01126 int 01127 n; 01128 01129 LogInfo 01130 *log_info; 01131 01132 if (IsEventLogging() == MagickFalse) 01133 return(MagickFalse); 01134 exception=AcquireExceptionInfo(); 01135 log_info=(LogInfo *) GetLogInfo("*",exception); 01136 exception=DestroyExceptionInfo(exception); 01137 LockSemaphoreInfo(log_semaphore); 01138 if ((log_info->event_mask & type) == 0) 01139 { 01140 UnlockSemaphoreInfo(log_semaphore); 01141 return(MagickTrue); 01142 } 01143 domain=CommandOptionToMnemonic(MagickLogEventOptions,type); 01144 #if defined(MAGICKCORE_HAVE_VSNPRINTF) 01145 n=vsnprintf(event,MaxTextExtent,format,operands); 01146 #else 01147 n=vsprintf(event,format,operands); 01148 #endif 01149 if (n < 0) 01150 event[MaxTextExtent-1]='\0'; 01151 text=TranslateEvent(type,module,function,line,domain,event); 01152 if (text == (char *) NULL) 01153 { 01154 (void) ContinueTimer((TimerInfo *) &log_info->timer); 01155 UnlockSemaphoreInfo(log_semaphore); 01156 return(MagickFalse); 01157 } 01158 if ((log_info->handler_mask & ConsoleHandler) != 0) 01159 { 01160 (void) FormatLocaleFile(stderr,"%s\n",text); 01161 (void) fflush(stderr); 01162 } 01163 if ((log_info->handler_mask & DebugHandler) != 0) 01164 { 01165 #if defined(MAGICKCORE_WINDOWS_SUPPORT) 01166 OutputDebugString(text); 01167 #endif 01168 } 01169 if ((log_info->handler_mask & EventHandler) != 0) 01170 { 01171 #if defined(MAGICKCORE_WINDOWS_SUPPORT) 01172 (void) NTReportEvent(text,MagickFalse); 01173 #endif 01174 } 01175 if ((log_info->handler_mask & FileHandler) != 0) 01176 { 01177 struct stat 01178 file_info; 01179 01180 file_info.st_size=0; 01181 if (log_info->file != (FILE *) NULL) 01182 (void) fstat(fileno(log_info->file),&file_info); 01183 if (file_info.st_size > (ssize_t) (1024*1024*log_info->limit)) 01184 { 01185 (void) FormatLocaleFile(log_info->file,"</log>\n"); 01186 (void) fclose(log_info->file); 01187 log_info->file=(FILE *) NULL; 01188 } 01189 if (log_info->file == (FILE *) NULL) 01190 { 01191 char 01192 *filename; 01193 01194 filename=TranslateFilename(log_info); 01195 if (filename == (char *) NULL) 01196 { 01197 (void) ContinueTimer((TimerInfo *) &log_info->timer); 01198 UnlockSemaphoreInfo(log_semaphore); 01199 return(MagickFalse); 01200 } 01201 log_info->append=IsPathAccessible(filename); 01202 log_info->file=fopen_utf8(filename,"ab"); 01203 filename=(char *) RelinquishMagickMemory(filename); 01204 if (log_info->file == (FILE *) NULL) 01205 { 01206 UnlockSemaphoreInfo(log_semaphore); 01207 return(MagickFalse); 01208 } 01209 log_info->generation++; 01210 if (log_info->append == MagickFalse) 01211 { 01212 (void) FormatLocaleFile(log_info->file,"<?xml version=\"1.0\" " 01213 "encoding=\"UTF-8\" standalone=\"yes\"?>\n"); 01214 (void) FormatLocaleFile(log_info->file,"<log>\n"); 01215 } 01216 } 01217 (void) FormatLocaleFile(log_info->file,"%s\n",text); 01218 (void) fflush(log_info->file); 01219 } 01220 if ((log_info->handler_mask & StdoutHandler) != 0) 01221 { 01222 (void) FormatLocaleFile(stdout,"%s\n",text); 01223 (void) fflush(stdout); 01224 } 01225 if ((log_info->handler_mask & StderrHandler) != 0) 01226 { 01227 (void) FormatLocaleFile(stderr,"%s\n",text); 01228 (void) fflush(stderr); 01229 } 01230 text=(char *) RelinquishMagickMemory(text); 01231 (void) ContinueTimer((TimerInfo *) &log_info->timer); 01232 UnlockSemaphoreInfo(log_semaphore); 01233 return(MagickTrue); 01234 } 01235 01236 MagickBooleanType LogMagickEvent(const LogEventType type,const char *module, 01237 const char *function,const size_t line,const char *format,...) 01238 { 01239 va_list 01240 operands; 01241 01242 MagickBooleanType 01243 status; 01244 01245 va_start(operands,format); 01246 status=LogMagickEventList(type,module,function,line,format,operands); 01247 va_end(operands); 01248 return(status); 01249 } 01250 01251 /* 01252 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01253 % % 01254 % % 01255 % % 01256 + L o a d L o g L i s t % 01257 % % 01258 % % 01259 % % 01260 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01261 % 01262 % LoadLogList() loads the log configuration file which provides a 01263 % mapping between log attributes and log name. 01264 % 01265 % The format of the LoadLogList method is: 01266 % 01267 % MagickBooleanType LoadLogList(const char *xml,const char *filename, 01268 % const size_t depth,ExceptionInfo *exception) 01269 % 01270 % A description of each parameter follows: 01271 % 01272 % o xml: The log list in XML format. 01273 % 01274 % o filename: The log list filename. 01275 % 01276 % o depth: depth of <include /> statements. 01277 % 01278 % o exception: return any errors or warnings in this structure. 01279 % 01280 */ 01281 static MagickBooleanType LoadLogList(const char *xml,const char *filename, 01282 const size_t depth,ExceptionInfo *exception) 01283 { 01284 char 01285 keyword[MaxTextExtent], 01286 *token; 01287 01288 const char 01289 *q; 01290 01291 LogInfo 01292 *log_info = (LogInfo *) NULL; 01293 01294 MagickStatusType 01295 status; 01296 01297 /* 01298 Load the log map file. 01299 */ 01300 if (xml == (const char *) NULL) 01301 return(MagickFalse); 01302 if (log_list == (LinkedListInfo *) NULL) 01303 { 01304 log_list=NewLinkedList(0); 01305 if (log_list == (LinkedListInfo *) NULL) 01306 { 01307 ThrowFileException(exception,ResourceLimitError, 01308 "MemoryAllocationFailed",filename); 01309 return(MagickFalse); 01310 } 01311 } 01312 status=MagickTrue; 01313 token=AcquireString((const char *) xml); 01314 for (q=(const char *) xml; *q != '\0'; ) 01315 { 01316 /* 01317 Interpret XML. 01318 */ 01319 GetMagickToken(q,&q,token); 01320 if (*token == '\0') 01321 break; 01322 (void) CopyMagickString(keyword,token,MaxTextExtent); 01323 if (LocaleNCompare(keyword,"<!DOCTYPE",9) == 0) 01324 { 01325 /* 01326 Doctype element. 01327 */ 01328 while ((LocaleNCompare(q,"]>",2) != 0) && (*q != '\0')) 01329 GetMagickToken(q,&q,token); 01330 continue; 01331 } 01332 if (LocaleNCompare(keyword,"<!--",4) == 0) 01333 { 01334 /* 01335 Comment element. 01336 */ 01337 while ((LocaleNCompare(q,"->",2) != 0) && (*q != '\0')) 01338 GetMagickToken(q,&q,token); 01339 continue; 01340 } 01341 if (LocaleCompare(keyword,"<include") == 0) 01342 { 01343 /* 01344 Include element. 01345 */ 01346 while (((*token != '/') && (*(token+1) != '>')) && (*q != '\0')) 01347 { 01348 (void) CopyMagickString(keyword,token,MaxTextExtent); 01349 GetMagickToken(q,&q,token); 01350 if (*token != '=') 01351 continue; 01352 GetMagickToken(q,&q,token); 01353 if (LocaleCompare(keyword,"file") == 0) 01354 { 01355 if (depth > 200) 01356 (void) ThrowMagickException(exception,GetMagickModule(), 01357 ConfigureError,"IncludeElementNestedTooDeeply","`%s'",token); 01358 else 01359 { 01360 char 01361 path[MaxTextExtent], 01362 *xml; 01363 01364 GetPathComponent(filename,HeadPath,path); 01365 if (*path != '\0') 01366 (void) ConcatenateMagickString(path,DirectorySeparator, 01367 MaxTextExtent); 01368 if (*token == *DirectorySeparator) 01369 (void) CopyMagickString(path,token,MaxTextExtent); 01370 else 01371 (void) ConcatenateMagickString(path,token,MaxTextExtent); 01372 xml=FileToString(path,~0,exception); 01373 if (xml != (char *) NULL) 01374 { 01375 status|=LoadLogList(xml,path,depth+1,exception); 01376 xml=DestroyString(xml); 01377 } 01378 } 01379 } 01380 } 01381 continue; 01382 } 01383 if (LocaleCompare(keyword,"<logmap>") == 0) 01384 { 01385 /* 01386 Allocate memory for the log list. 01387 */ 01388 log_info=(LogInfo *) AcquireMagickMemory(sizeof(*log_info)); 01389 if (log_info == (LogInfo *) NULL) 01390 ThrowFatalException(ResourceLimitFatalError,"MemoryAllocationFailed"); 01391 (void) ResetMagickMemory(log_info,0,sizeof(*log_info)); 01392 log_info->path=ConstantString(filename); 01393 GetTimerInfo((TimerInfo *) &log_info->timer); 01394 log_info->exempt=MagickFalse; 01395 log_info->signature=MagickSignature; 01396 continue; 01397 } 01398 if (log_info == (LogInfo *) NULL) 01399 continue; 01400 if (LocaleCompare(keyword,"</logmap>") == 0) 01401 { 01402 status=AppendValueToLinkedList(log_list,log_info); 01403 if (status == MagickFalse) 01404 (void) ThrowMagickException(exception,GetMagickModule(), 01405 ResourceLimitError,"MemoryAllocationFailed","`%s'",filename); 01406 log_info=(LogInfo *) NULL; 01407 } 01408 GetMagickToken(q,(const char **) NULL,token); 01409 if (*token != '=') 01410 continue; 01411 GetMagickToken(q,&q,token); 01412 GetMagickToken(q,&q,token); 01413 switch (*keyword) 01414 { 01415 case 'E': 01416 case 'e': 01417 { 01418 if (LocaleCompare((char *) keyword,"events") == 0) 01419 { 01420 log_info->event_mask=(LogEventType) (log_info->event_mask | 01421 ParseCommandOption(MagickLogEventOptions,MagickTrue,token)); 01422 break; 01423 } 01424 break; 01425 } 01426 case 'F': 01427 case 'f': 01428 { 01429 if (LocaleCompare((char *) keyword,"filename") == 0) 01430 { 01431 if (log_info->filename != (char *) NULL) 01432 log_info->filename=(char *) 01433 RelinquishMagickMemory(log_info->filename); 01434 log_info->filename=ConstantString(token); 01435 break; 01436 } 01437 if (LocaleCompare((char *) keyword,"format") == 0) 01438 { 01439 if (log_info->format != (char *) NULL) 01440 log_info->format=(char *) 01441 RelinquishMagickMemory(log_info->format); 01442 log_info->format=ConstantString(token); 01443 break; 01444 } 01445 break; 01446 } 01447 case 'G': 01448 case 'g': 01449 { 01450 if (LocaleCompare((char *) keyword,"generations") == 0) 01451 { 01452 if (LocaleCompare(token,"unlimited") == 0) 01453 { 01454 log_info->generations=(~0UL); 01455 break; 01456 } 01457 log_info->generations=StringToUnsignedLong(token); 01458 break; 01459 } 01460 break; 01461 } 01462 case 'L': 01463 case 'l': 01464 { 01465 if (LocaleCompare((char *) keyword,"limit") == 0) 01466 { 01467 if (LocaleCompare(token,"unlimited") == 0) 01468 { 01469 log_info->limit=(~0UL); 01470 break; 01471 } 01472 log_info->limit=StringToUnsignedLong(token); 01473 break; 01474 } 01475 break; 01476 } 01477 case 'O': 01478 case 'o': 01479 { 01480 if (LocaleCompare((char *) keyword,"output") == 0) 01481 { 01482 log_info->handler_mask=(LogHandlerType) 01483 (log_info->handler_mask | ParseLogHandlers(token)); 01484 break; 01485 } 01486 break; 01487 } 01488 default: 01489 break; 01490 } 01491 } 01492 token=DestroyString(token); 01493 if (log_list == (LinkedListInfo *) NULL) 01494 return(MagickFalse); 01495 return(status != 0 ? MagickTrue : MagickFalse); 01496 } 01497 01498 /* 01499 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01500 % % 01501 % % 01502 % % 01503 % L o a d L o g L i s t s % 01504 % % 01505 % % 01506 % % 01507 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01508 % 01509 % LoadLogLists() loads one or more log configuration file which provides a 01510 % mapping between log attributes and log name. 01511 % 01512 % The format of the LoadLogLists method is: 01513 % 01514 % MagickBooleanType LoadLogLists(const char *filename, 01515 % ExceptionInfo *exception) 01516 % 01517 % A description of each parameter follows: 01518 % 01519 % o filename: the log configuration filename. 01520 % 01521 % o exception: return any errors or warnings in this structure. 01522 % 01523 */ 01524 static MagickBooleanType LoadLogLists(const char *filename, 01525 ExceptionInfo *exception) 01526 { 01527 const StringInfo 01528 *option; 01529 01530 LinkedListInfo 01531 *options; 01532 01533 MagickStatusType 01534 status; 01535 01536 register ssize_t 01537 i; 01538 01539 /* 01540 Load built-in log map. 01541 */ 01542 status=MagickFalse; 01543 if (log_list == (LinkedListInfo *) NULL) 01544 { 01545 log_list=NewLinkedList(0); 01546 if (log_list == (LinkedListInfo *) NULL) 01547 { 01548 ThrowFileException(exception,ResourceLimitError, 01549 "MemoryAllocationFailed",filename); 01550 return(MagickFalse); 01551 } 01552 } 01553 for (i=0; i < (ssize_t) (sizeof(LogMap)/sizeof(*LogMap)); i++) 01554 { 01555 LogInfo 01556 *log_info; 01557 01558 register const LogMapInfo 01559 *p; 01560 01561 p=LogMap+i; 01562 log_info=(LogInfo *) AcquireMagickMemory(sizeof(*log_info)); 01563 if (log_info == (LogInfo *) NULL) 01564 { 01565 (void) ThrowMagickException(exception,GetMagickModule(), 01566 ResourceLimitError,"MemoryAllocationFailed","`%s'",log_info->name); 01567 continue; 01568 } 01569 (void) ResetMagickMemory(log_info,0,sizeof(*log_info)); 01570 log_info->path=(char *) "[built-in]"; 01571 GetTimerInfo((TimerInfo *) &log_info->timer); 01572 log_info->event_mask=p->event_mask; 01573 log_info->handler_mask=p->handler_mask; 01574 log_info->filename=ConstantString(p->filename); 01575 log_info->format=ConstantString(p->format); 01576 log_info->exempt=MagickTrue; 01577 log_info->signature=MagickSignature; 01578 status=AppendValueToLinkedList(log_list,log_info); 01579 if (status == MagickFalse) 01580 (void) ThrowMagickException(exception,GetMagickModule(), 01581 ResourceLimitError,"MemoryAllocationFailed","`%s'",log_info->name); 01582 } 01583 /* 01584 Load external log map. 01585 */ 01586 options=GetConfigureOptions(filename,exception); 01587 option=(const StringInfo *) GetNextValueInLinkedList(options); 01588 while (option != (const StringInfo *) NULL) 01589 { 01590 status|=LoadLogList((const char *) GetStringInfoDatum(option), 01591 GetStringInfoPath(option),0,exception); 01592 option=(const StringInfo *) GetNextValueInLinkedList(options); 01593 } 01594 options=DestroyConfigureOptions(options); 01595 return(status != 0 ? MagickTrue : MagickFalse); 01596 } 01597 01598 /* 01599 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01600 % % 01601 % % 01602 % % 01603 + P a r s e L o g H a n d l e r s % 01604 % % 01605 % % 01606 % % 01607 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01608 % 01609 % ParseLogHandlers() parses a string defining which handlers takes a log 01610 % message and exports them. 01611 % 01612 % The format of the ParseLogHandlers method is: 01613 % 01614 % LogHandlerType ParseLogHandlers(const char *handlers) 01615 % 01616 % A description of each parameter follows: 01617 % 01618 % o handlers: one or more handlers separated by commas. 01619 % 01620 */ 01621 static LogHandlerType ParseLogHandlers(const char *handlers) 01622 { 01623 LogHandlerType 01624 handler_mask; 01625 01626 register const char 01627 *p; 01628 01629 register ssize_t 01630 i; 01631 01632 size_t 01633 length; 01634 01635 handler_mask=NoHandler; 01636 for (p=handlers; p != (char *) NULL; p=strchr(p,',')) 01637 { 01638 while ((*p != '\0') && ((isspace((int) ((unsigned char) *p)) != 0) || 01639 (*p == ','))) 01640 p++; 01641 for (i=0; LogHandlers[i].name != (char *) NULL; i++) 01642 { 01643 length=strlen(LogHandlers[i].name); 01644 if (LocaleNCompare(p,LogHandlers[i].name,length) == 0) 01645 { 01646 handler_mask=(LogHandlerType) (handler_mask | LogHandlers[i].handler); 01647 break; 01648 } 01649 } 01650 if (LogHandlers[i].name == (char *) NULL) 01651 return(UndefinedHandler); 01652 } 01653 return(handler_mask); 01654 } 01655 01656 /* 01657 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01658 % % 01659 % % 01660 % % 01661 % S e t L o g E v e n t M a s k % 01662 % % 01663 % % 01664 % % 01665 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01666 % 01667 % SetLogEventMask() accepts a list that determines which events to log. All 01668 % other events are ignored. By default, no debug is enabled. This method 01669 % returns the previous log event mask. 01670 % 01671 % The format of the SetLogEventMask method is: 01672 % 01673 % LogEventType SetLogEventMask(const char *events) 01674 % 01675 % A description of each parameter follows: 01676 % 01677 % o events: log these events. 01678 % 01679 */ 01680 MagickExport LogEventType SetLogEventMask(const char *events) 01681 { 01682 ExceptionInfo 01683 *exception; 01684 01685 LogInfo 01686 *log_info; 01687 01688 ssize_t 01689 option; 01690 01691 exception=AcquireExceptionInfo(); 01692 log_info=(LogInfo *) GetLogInfo("*",exception); 01693 exception=DestroyExceptionInfo(exception); 01694 option=ParseCommandOption(MagickLogEventOptions,MagickTrue,events); 01695 LockSemaphoreInfo(log_semaphore); 01696 log_info=(LogInfo *) GetValueFromLinkedList(log_list,0); 01697 log_info->event_mask=(LogEventType) option; 01698 if (option == -1) 01699 log_info->event_mask=UndefinedEvents; 01700 UnlockSemaphoreInfo(log_semaphore); 01701 return(log_info->event_mask); 01702 } 01703 01704 /* 01705 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01706 % % 01707 % % 01708 % % 01709 % S e t L o g F o r m a t % 01710 % % 01711 % % 01712 % % 01713 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01714 % 01715 % SetLogFormat() sets the format for the "human readable" log record. 01716 % 01717 % The format of the LogMagickFormat method is: 01718 % 01719 % SetLogFormat(const char *format) 01720 % 01721 % A description of each parameter follows: 01722 % 01723 % o format: the log record format. 01724 % 01725 */ 01726 MagickExport void SetLogFormat(const char *format) 01727 { 01728 LogInfo 01729 *log_info; 01730 01731 ExceptionInfo 01732 *exception; 01733 01734 exception=AcquireExceptionInfo(); 01735 log_info=(LogInfo *) GetLogInfo("*",exception); 01736 exception=DestroyExceptionInfo(exception); 01737 LockSemaphoreInfo(log_semaphore); 01738 if (log_info->format != (char *) NULL) 01739 log_info->format=DestroyString(log_info->format); 01740 log_info->format=ConstantString(format); 01741 UnlockSemaphoreInfo(log_semaphore); 01742 } 01743 01744 /* 01745 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01746 % % 01747 % % 01748 % % 01749 % S e t L o g N a m e % 01750 % % 01751 % % 01752 % % 01753 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% 01754 % 01755 % SetLogName() sets the log name and returns it. 01756 % 01757 % The format of the SetLogName method is: 01758 % 01759 % const char *SetLogName(const char *name) 01760 % 01761 % A description of each parameter follows: 01762 % 01763 % o log_name: SetLogName() returns the current client name. 01764 % 01765 % o name: Specifies the new client name. 01766 % 01767 */ 01768 MagickExport const char *SetLogName(const char *name) 01769 { 01770 if ((name != (char *) NULL) && (*name != '\0')) 01771 (void) CopyMagickString(log_name,name,MaxTextExtent); 01772 return(log_name); 01773 }