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

Generated on Thu Jul 2 12:03:20 2009 for MagickCore by  doxygen 1.5.8