log.c

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

Generated on 19 Nov 2009 for MagickCore by  doxygen 1.6.1