-fix #2122 and #2035
[oweals/gnunet.git] / src / util / common_logging.c
1 /*
2      This file is part of GNUnet.
3      (C) 2006, 2008, 2009 Christian Grothoff (and other contributing authors)
4
5      GNUnet is free software; you can redistribute it and/or modify
6      it under the terms of the GNU General Public License as published
7      by the Free Software Foundation; either version 2, or (at your
8      option) any later version.
9
10      GNUnet is distributed in the hope that it will be useful, but
11      WITHOUT ANY WARRANTY; without even the implied warranty of
12      MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13      General Public License for more details.
14
15      You should have received a copy of the GNU General Public License
16      along with GNUnet; see the file COPYING.  If not, write to the
17      Free Software Foundation, Inc., 59 Temple Place - Suite 330,
18      Boston, MA 02111-1307, USA.
19 */
20
21 /**
22  * @file util/common_logging.c
23  * @brief error handling API
24  *
25  * @author Christian Grothoff
26  */
27 #include "platform.h"
28 #include "gnunet_common.h"
29 #include "gnunet_crypto_lib.h"
30 #include "gnunet_strings_lib.h"
31 #include "gnunet_time_lib.h"
32
33 #include <regex.h>
34
35 /**
36  * After how many milliseconds do we always print
37  * that "message X was repeated N times"?  Use 12h.
38  */
39 #define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000)
40
41 /**
42  * After how many repetitions do we always print
43  * that "message X was repeated N times"? (even if
44  * we have not yet reached the delay threshold)
45  */
46 #define BULK_REPEAT_THRESHOLD 1000
47
48 /**
49  * How many characters do we use for matching of
50  * bulk messages?
51  */
52 #define BULK_TRACK_SIZE 256
53
54 /**
55  * How many characters do we use for matching of
56  * bulk components?
57  */
58 #define COMP_TRACK_SIZE 32
59
60 /**
61  * How many characters can a date/time string
62  * be at most?
63  */
64 #define DATE_STR_SIZE 64
65
66 /**
67  * How many log files to keep?
68  */
69 #define ROTATION_KEEP 3
70
71 #ifndef PATH_MAX
72 /**
73  * Assumed maximum path length (for the log file name).
74  */
75 #define PATH_MAX 4096
76 #endif
77
78
79 /**
80  * Linked list of active loggers.
81  */
82 struct CustomLogger
83 {
84   /**
85    * This is a linked list.
86    */
87   struct CustomLogger *next;
88
89   /**
90    * Log function.
91    */
92   GNUNET_Logger logger;
93
94   /**
95    * Closure for logger.
96    */
97   void *logger_cls;
98 };
99
100 /**
101  * The last "bulk" error message that we have been logging.
102  * Note that this message maybe truncated to the first BULK_TRACK_SIZE
103  * characters, in which case it is NOT 0-terminated!
104  */
105 static char last_bulk[BULK_TRACK_SIZE];
106
107 /**
108  * Type of the last bulk message.
109  */
110 static enum GNUNET_ErrorType last_bulk_kind;
111
112 /**
113  * Time of the last bulk error message (0 for none)
114  */
115 static struct GNUNET_TIME_Absolute last_bulk_time;
116
117 /**
118  * Number of times that bulk message has been repeated since.
119  */
120 static unsigned int last_bulk_repeat;
121
122 /**
123  * Component when the last bulk was logged.  Will be 0-terminated.
124  */
125 static char last_bulk_comp[COMP_TRACK_SIZE + 1];
126
127 /**
128  * Running component.
129  */
130 static char *component;
131
132 /**
133  * Running component (without pid).
134  */
135 static char *component_nopid;
136
137 /**
138  * Format string describing the name of the log file.
139  */
140 static char *log_file_name;
141
142 /**
143  * Minimum log level.
144  */
145 static enum GNUNET_ErrorType min_level;
146
147 /**
148  * Linked list of our custom loggres.
149  */
150 static struct CustomLogger *loggers;
151
152 /**
153  * Number of log calls to ignore.
154  */
155 unsigned int skip_log;
156
157 /**
158  * File descriptor to use for "stderr", or NULL for none.
159  */
160 static FILE *GNUNET_stderr;
161
162 /**
163  * Represents a single logging definition
164  */
165 struct LogDef
166 {
167   /**
168    * Component name regex
169    */
170   regex_t component_regex;
171
172   /**
173    * File name regex
174    */
175   regex_t file_regex;
176
177   /**
178    * Function name regex
179    */
180   regex_t function_regex;
181
182   /**
183    * Lowest line at which this definition matches.
184    * Defaults to 0. Must be <= to_line.
185    */
186   int from_line;
187
188   /**
189    * Highest line at which this definition matches.
190    * Defaults to INT_MAX. Must be >= from_line.
191    */
192   int to_line;
193
194   /**
195    * Maximal log level allowed for calls that match this definition.
196    * Calls with higher log level will be disabled.
197    * Must be >= 0
198    */
199   int level;
200
201   /**
202    * 1 if this definition comes from GNUNET_FORCE_LOG, which means that it
203    * overrides any configuration options. 0 otherwise.
204    */
205   int force;
206 };
207
208 /**
209  * Dynamic array of logging definitions
210  */
211 static struct LogDef *logdefs;
212
213 /**
214  * Allocated size of logdefs array (in units)
215  */
216 static int logdefs_size;
217
218 /**
219  * The number of units used in logdefs array.
220  */
221 static int logdefs_len;
222
223 /**
224  * GNUNET_YES if GNUNET_LOG environment variable is already parsed.
225  */
226 static int gnunet_log_parsed;
227
228 /**
229  * GNUNET_YES if GNUNET_FORCE_LOG environment variable is already parsed.
230  */
231 static int gnunet_force_log_parsed;
232
233 /**
234  * GNUNET_YES if at least one definition with forced == 1 is available.
235  */
236 static int gnunet_force_log_present;
237
238 #ifdef WINDOWS
239 /**
240  * Contains the number of performance counts per second.
241  */
242 static LARGE_INTEGER performance_frequency;
243 #endif
244
245
246 /**
247  * Convert a textual description of a loglevel
248  * to the respective GNUNET_GE_KIND.
249  *
250  * @param log loglevel to parse
251  * @return GNUNET_GE_INVALID if log does not parse
252  */
253 static enum GNUNET_ErrorType
254 get_type (const char *log)
255 {
256   if (NULL == log)
257     return GNUNET_ERROR_TYPE_UNSPECIFIED;
258   if (0 == strcasecmp (log, _("DEBUG")))
259     return GNUNET_ERROR_TYPE_DEBUG;
260   if (0 == strcasecmp (log, _("INFO")))
261     return GNUNET_ERROR_TYPE_INFO;
262   if (0 == strcasecmp (log, _("WARNING")))
263     return GNUNET_ERROR_TYPE_WARNING;
264   if (0 == strcasecmp (log, _("ERROR")))
265     return GNUNET_ERROR_TYPE_ERROR;
266   if (0 == strcasecmp (log, _("NONE")))
267     return GNUNET_ERROR_TYPE_NONE;
268   return GNUNET_ERROR_TYPE_INVALID;
269 }
270
271
272 #if !defined(GNUNET_CULL_LOGGING)
273 /**
274  * Utility function - reallocates logdefs array to be twice as large.
275  */
276 static void
277 resize_logdefs ()
278 {
279   logdefs_size = (logdefs_size + 1) * 2;
280   logdefs = GNUNET_realloc (logdefs, logdefs_size * sizeof (struct LogDef));
281 }
282
283
284 /**
285  * Abort the process, generate a core dump if possible.
286  */
287 void
288 GNUNET_abort ()
289 {
290 #if WINDOWS
291   DebugBreak ();
292 #endif
293   abort ();
294 }
295
296
297 /**
298  * Rotate logs, deleting the oldest log.
299  *
300  * @param new_name new name to add to the rotation
301  */ 
302 static void
303 log_rotate (const char *new_name)
304 {
305   static char *rotation[ROTATION_KEEP];
306   static unsigned int rotation_off;
307   char *discard;
308
309   if ('\0' == *new_name)
310     return; /* not a real log file name */
311   discard = rotation[rotation_off % ROTATION_KEEP];
312   if (NULL != discard)
313   {
314     /* Note: can't log errors during logging (recursion!), so this
315        operation MUST silently fail... */
316     (void) UNLINK (discard);
317     GNUNET_free (discard);
318   }
319   rotation[rotation_off % ROTATION_KEEP] = GNUNET_strdup (new_name);
320   rotation_off++;  
321 }
322
323
324 /**
325  * Setup the log file.
326  *
327  * @param tm timestamp for which we should setup logging
328  * @return GNUNET_OK on success, GNUNET_SYSERR on error
329  */
330 static int
331 setup_log_file (const struct tm *tm)
332 {
333   static char last_fn[PATH_MAX + 1];  
334   char fn[PATH_MAX + 1];
335   int dirwarn;
336   int altlog_fd;
337   int dup_return;
338   FILE *altlog;
339   
340   if (0 == strftime (fn, sizeof (fn), log_file_name, tm))
341     return GNUNET_SYSERR;
342   if (0 == strcmp (fn, last_fn))
343     return GNUNET_OK; /* no change */
344   log_rotate (last_fn);
345   strcpy (last_fn, fn);
346   dirwarn = (GNUNET_OK != GNUNET_DISK_directory_create_for_file (fn));
347 #if WINDOWS
348   altlog_fd = OPEN (fn, O_APPEND |
349                         O_BINARY |
350                         O_WRONLY | O_CREAT,
351                         _S_IREAD | _S_IWRITE);
352 #else
353   altlog_fd = OPEN (fn, O_APPEND |
354                         O_WRONLY | O_CREAT,
355                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
356 #endif
357   if (-1 != altlog_fd)
358   {
359     if (NULL != GNUNET_stderr)
360       fclose (GNUNET_stderr);
361     dup_return = dup2 (altlog_fd, 2);
362     (void) close (altlog_fd);
363     if (-1 != dup_return)
364     {
365       altlog = fdopen (2, "ab");
366       if (NULL == altlog)
367       {
368         (void) close (2);
369         altlog_fd = -1;
370       }
371     }
372     else
373     {
374       altlog_fd = -1;
375     }
376   }
377   if (-1 == altlog_fd)
378   {
379     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn);
380     if (dirwarn)
381       GNUNET_log (GNUNET_ERROR_TYPE_WARNING,
382                   _("Failed to create or access directory for log file `%s'\n"),
383                   fn);
384     return GNUNET_SYSERR;
385   }
386   GNUNET_stderr = altlog; 
387   return GNUNET_OK;
388 }
389
390 /**
391  * Utility function - adds a parsed definition to logdefs array.
392  *
393  * @param component see struct LogDef, can't be NULL
394  * @param file see struct LogDef, can't be NULL
395  * @param function see struct LogDef, can't be NULL
396  * @param from_line see struct LogDef
397  * @param to_line see struct LogDef
398  * @param level see struct LogDef, must be >= 0
399  * @param force see struct LogDef
400  * @return 0 on success, regex-specific error otherwise
401  */
402 static int
403 add_definition (char *component, char *file, char *function, int from_line,
404                 int to_line, int level, int force)
405 {
406   struct LogDef n;
407   int r;
408
409   if (logdefs_size == logdefs_len)
410     resize_logdefs ();
411   memset (&n, 0, sizeof (n));
412   if (0 == strlen (component))
413     component = (char *) ".*";
414   r = regcomp (&n.component_regex, (const char *) component, REG_NOSUB);
415   if (0 != r)
416   {
417     return r;
418   }
419   if (0 == strlen (file))
420     file = (char *) ".*";
421   r = regcomp (&n.file_regex, (const char *) file, REG_NOSUB);
422   if (0 != r)
423   {
424     regfree (&n.component_regex);
425     return r;
426   }
427   if ((NULL == function) || (0 == strlen (function)))
428     function = (char *) ".*";
429   r = regcomp (&n.function_regex, (const char *) function, REG_NOSUB);
430   if (0 != r)
431   {
432     regfree (&n.component_regex);
433     regfree (&n.file_regex);
434     return r;
435   }
436   n.from_line = from_line;
437   n.to_line = to_line;
438   n.level = level;
439   n.force = force;
440   logdefs[logdefs_len++] = n;
441   return 0;
442 }
443
444
445 /**
446  * Decides whether a particular logging call should or should not be allowed
447  * to be made. Used internally by GNUNET_log*()
448  *
449  * @param caller_level loglevel the caller wants to use
450  * @param comp component name the caller uses (NULL means that global
451  *   component name is used)
452  * @param file file name containing the logging call, usually __FILE__
453  * @param function function which tries to make a logging call,
454  *   usually __FUNCTION__
455  * @param line line at which the call is made, usually __LINE__
456  * @return 0 to disallow the call, 1 to allow it
457  */
458 int
459 GNUNET_get_log_call_status (int caller_level, const char *comp,
460                             const char *file, const char *function, int line)
461 {
462   struct LogDef *ld;
463   int i;
464   int force_only;
465
466   if (NULL == comp)
467     /* Use default component */
468     comp = component_nopid;
469
470   /* We have no definitions to override globally configured log level,
471    * so just use it right away.
472    */
473   if ( (min_level >= 0) && (GNUNET_NO == gnunet_force_log_present) )
474     return caller_level <= min_level;
475
476   /* Only look for forced definitions? */
477   force_only = min_level >= 0;
478   for (i = 0; i < logdefs_len; i++)
479   {
480     ld = &logdefs[i];
481     if (( (!force_only) || ld->force) &&
482         (line >= ld->from_line && line <= ld->to_line) &&
483         (0 == regexec (&ld->component_regex, comp, 0, NULL, 0)) &&
484         (0 == regexec (&ld->file_regex, file, 0, NULL, 0)) &&
485         (0 == regexec (&ld->function_regex, function, 0, NULL, 0)))
486     {
487       /* We're finished */
488       return caller_level <= ld->level;
489     }
490   }
491   /* No matches - use global level, if defined */
492   if (min_level >= 0)
493     return caller_level <= min_level;
494   /* All programs/services previously defaulted to WARNING.
495    * Now WE default to WARNING, and THEY default to NULL.
496    */
497   return caller_level <= GNUNET_ERROR_TYPE_WARNING;
498 }
499
500
501 /**
502  * Utility function - parses a definition
503  *
504  * Definition format:
505  * component;file;function;from_line-to_line;level[/component...]
506  * All entries are mandatory, but may be empty.
507  * Empty entries for component, file and function are treated as
508  * "matches anything".
509  * Empty line entry is treated as "from 0 to INT_MAX"
510  * Line entry with only one line is treated as "this line only"
511  * Entry for level MUST NOT be empty.
512  * Entries for component, file and function that consist of a
513  * single character "*" are treated (at the moment) the same way
514  * empty entries are treated (wildcard matching is not implemented (yet?)).
515  * file entry is matched to the end of __FILE__. That is, it might be
516  * a base name, or a base name with leading directory names (some compilers
517  * define __FILE__ to absolute file path).
518  *
519  * @param constname name of the environment variable from which to get the
520  *   string to be parsed
521  * @param force 1 if definitions found in constname are to be forced
522  * @return number of added definitions
523  */
524 static int
525 parse_definitions (const char *constname, int force)
526 {
527   char *def;
528   const char *tmp;
529   char *comp = NULL;
530   char *file = NULL;
531   char *function = NULL;
532   char *p;
533   char *start;
534   char *t;
535   short state;
536   int level;
537   int from_line, to_line;
538   int counter = 0;
539   int keep_looking = 1;
540
541   tmp = getenv (constname);
542   if (NULL == tmp)
543     return 0;
544   def = GNUNET_strdup (tmp);
545   from_line = 0;
546   to_line = INT_MAX;
547   for (p = def, state = 0, start = def; keep_looking; p++)
548   {
549     switch (p[0])
550     {
551     case ';':                  /* found a field separator */
552       p[0] = '\0';
553       switch (state)
554       {
555       case 0:                  /* within a component name */
556         comp = start;
557         break;
558       case 1:                  /* within a file name */
559         file = start;
560         break;
561       case 2:                  /* within a function name */
562         /* after a file name there must be a function name */
563         function = start;
564         break;
565       case 3:                  /* within a from-to line range */
566         if (strlen (start) > 0)
567         {
568           errno = 0;
569           from_line = strtol (start, &t, 10);
570           if ( (0 != errno) || (from_line < 0) )
571           {
572             GNUNET_free (def);
573             return counter;
574           }
575           if ( (t < p) && ('-' == t[0]) )
576           {
577             errno = 0;
578             start = t + 1;
579             to_line = strtol (start, &t, 10);
580             if ( (0 != errno) || (to_line < 0) || (t != p) )
581             {
582               GNUNET_free (def);
583               return counter;
584             }
585           }
586           else                  /* one number means "match this line only" */
587             to_line = from_line;
588         }
589         else                    /* default to 0-max */
590         {
591           from_line = 0;
592           to_line = INT_MAX;
593         }
594         break;
595       }
596       start = p + 1;
597       state++;
598       break;
599     case '\0':                 /* found EOL */
600       keep_looking = 0;
601       /* fall through to '/' */
602     case '/':                  /* found a definition separator */
603       switch (state)
604       {
605       case 4:                  /* within a log level */
606         p[0] = '\0';
607         state = 0;
608         level = get_type ((const char *) start);
609         if ( (GNUNET_ERROR_TYPE_INVALID == level) ||
610              (GNUNET_ERROR_TYPE_UNSPECIFIED == level) ||
611              (0 != add_definition (comp, file, function, from_line, to_line,
612                                    level, force)) )
613         {
614           GNUNET_free (def);
615           return counter;
616         }
617         counter++;
618         start = p + 1;
619         break;
620       default:
621         break;
622       }
623     default:
624       break;
625     }
626   }
627   GNUNET_free (def);
628   return counter;
629 }
630
631
632 /**
633  * Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG.
634  */
635 static void
636 parse_all_definitions ()
637 {
638   if (GNUNET_NO == gnunet_log_parsed)
639     parse_definitions ("GNUNET_LOG", 0);
640   gnunet_log_parsed = GNUNET_YES;
641   if (GNUNET_NO == gnunet_force_log_parsed)
642     gnunet_force_log_present =
643         parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO;
644   gnunet_force_log_parsed = GNUNET_YES;
645 }
646 #endif
647
648
649 /**
650  * Setup logging.
651  *
652  * @param comp default component to use
653  * @param loglevel what types of messages should be logged
654  * @param logfile which file to write log messages to (can be NULL)
655  * @return GNUNET_OK on success
656  */
657 int
658 GNUNET_log_setup (const char *comp, const char *loglevel, const char *logfile)
659 {
660   const char *env_logfile;
661   const struct tm *tm;
662   time_t t;
663
664   min_level = get_type (loglevel);
665 #if !defined(GNUNET_CULL_LOGGING)
666   parse_all_definitions ();
667 #endif
668 #ifdef WINDOWS
669   QueryPerformanceFrequency (&performance_frequency);
670 #endif
671   GNUNET_free_non_null (component);
672   GNUNET_asprintf (&component, "%s-%d", comp, getpid ());
673   GNUNET_free_non_null (component_nopid);
674   component_nopid = GNUNET_strdup (comp);
675
676   env_logfile = getenv ("GNUNET_FORCE_LOGFILE");
677   if ((NULL != env_logfile) && (strlen (env_logfile) > 0))
678     logfile = env_logfile;
679   if (NULL == logfile)
680     return GNUNET_OK;
681   GNUNET_free_non_null (log_file_name);
682   log_file_name = GNUNET_STRINGS_filename_expand (logfile);
683   if (NULL == log_file_name)
684     return GNUNET_SYSERR;
685   t = time (NULL);
686   tm = gmtime (&t);
687   return setup_log_file (tm);
688 }
689
690
691 /**
692  * Add a custom logger.
693  *
694  * @param logger log function
695  * @param logger_cls closure for logger
696  */
697 void
698 GNUNET_logger_add (GNUNET_Logger logger, void *logger_cls)
699 {
700   struct CustomLogger *entry;
701
702   entry = GNUNET_malloc (sizeof (struct CustomLogger));
703   entry->logger = logger;
704   entry->logger_cls = logger_cls;
705   entry->next = loggers;
706   loggers = entry;
707 }
708
709
710 /**
711  * Remove a custom logger.
712  *
713  * @param logger log function
714  * @param logger_cls closure for logger
715  */
716 void
717 GNUNET_logger_remove (GNUNET_Logger logger, void *logger_cls)
718 {
719   struct CustomLogger *pos;
720   struct CustomLogger *prev;
721
722   prev = NULL;
723   pos = loggers;
724   while ((pos != NULL) &&
725          ((pos->logger != logger) || (pos->logger_cls != logger_cls)))
726   {
727     prev = pos;
728     pos = pos->next;
729   }
730   GNUNET_assert (pos != NULL);
731   if (prev == NULL)
732     loggers = pos->next;
733   else
734     prev->next = pos->next;
735   GNUNET_free (pos);
736 }
737
738
739 /**
740  * Actually output the log message.
741  *
742  * @param kind how severe was the issue
743  * @param comp component responsible
744  * @param datestr current date/time
745  * @param msg the actual message
746  */
747 static void
748 output_message (enum GNUNET_ErrorType kind, const char *comp,
749                 const char *datestr, const char *msg)
750 {
751   struct CustomLogger *pos;
752
753   if (NULL != GNUNET_stderr)
754   {
755     FPRINTF (GNUNET_stderr, "%s %s %s %s", datestr, comp,
756              GNUNET_error_type_to_string (kind), msg);
757     fflush (GNUNET_stderr);
758   }
759   pos = loggers;
760   while (pos != NULL)
761   {
762     pos->logger (pos->logger_cls, kind, comp, datestr, msg);
763     pos = pos->next;
764   }
765 }
766
767
768 /**
769  * Flush an existing bulk report to the output.
770  *
771  * @param datestr our current timestamp
772  */
773 static void
774 flush_bulk (const char *datestr)
775 {
776   char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];
777   int rev;
778   char *last;
779   char *ft;
780
781   if ((last_bulk_time.abs_value == 0) || (last_bulk_repeat == 0))
782     return;
783   rev = 0;
784   last = memchr (last_bulk, '\0', BULK_TRACK_SIZE);
785   if (last == NULL)
786     last = &last_bulk[BULK_TRACK_SIZE - 1];
787   else if (last != last_bulk)
788     last--;
789   if (last[0] == '\n')
790   {
791     rev = 1;
792     last[0] = '\0';
793   }
794   ft = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration
795                                                (last_bulk_time));
796   snprintf (msg, sizeof (msg),
797             _("Message `%.*s' repeated %u times in the last %s\n"),
798             BULK_TRACK_SIZE, last_bulk, last_bulk_repeat, ft);
799   GNUNET_free (ft);
800   if (rev == 1)
801     last[0] = '\n';
802   output_message (last_bulk_kind, last_bulk_comp, datestr, msg);
803   last_bulk_time = GNUNET_TIME_absolute_get ();
804   last_bulk_repeat = 0;
805 }
806
807
808 /**
809  * Ignore the next n calls to the log function.
810  *
811  * @param n number of log calls to ignore
812  * @param check_reset GNUNET_YES to assert that the log skip counter is currently zero
813  */
814 void
815 GNUNET_log_skip (unsigned int n, int check_reset)
816 {
817   int ok;
818
819   if (0 == n)
820   {
821     ok = (0 == skip_log);
822     skip_log = 0;
823     if (check_reset)
824       GNUNET_assert (ok);
825   }
826   else
827   {
828     skip_log += n;
829   }
830 }
831
832
833 /**
834  * Output a log message using the default mechanism.
835  *
836  * @param kind how severe was the issue
837  * @param comp component responsible
838  * @param message the actual message
839  * @param va arguments to the format string "message"
840  */
841 static void
842 mylog (enum GNUNET_ErrorType kind, const char *comp, const char *message,
843        va_list va)
844 {
845   char date[DATE_STR_SIZE];
846   char date2[DATE_STR_SIZE];
847   struct tm *tmptr;
848   size_t size;
849   va_list vacp;
850
851   va_copy (vacp, va);
852   size = VSNPRINTF (NULL, 0, message, vacp) + 1;
853   GNUNET_assert (0 != size);
854   va_end (vacp);
855   memset (date, 0, DATE_STR_SIZE);
856   {
857     char buf[size];
858 #ifdef WINDOWS
859     LARGE_INTEGER pc;
860     time_t timetmp;
861
862     time (&timetmp);
863     tmptr = localtime (&timetmp);
864     pc.QuadPart = 0;
865     QueryPerformanceCounter (&pc);
866     if (NULL == tmptr)
867     {
868       strcpy (date, "localtime error");
869     }
870     else
871     {
872       strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%020llu", tmptr);
873       snprintf (date, sizeof (date), date2,
874                 (long long) (pc.QuadPart /
875                              (performance_frequency.QuadPart / 1000)));
876     }
877 #else
878     struct timeval timeofday;
879
880     gettimeofday (&timeofday, NULL);
881     tmptr = localtime (&timeofday.tv_sec);
882     if (NULL == tmptr)
883     {
884       strcpy (date, "localtime error");
885     }
886     else
887     {
888       strftime (date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr);
889       snprintf (date, sizeof (date), date2, timeofday.tv_usec);
890     }
891 #endif  
892     VSNPRINTF (buf, size, message, va);
893     (void) setup_log_file (tmptr);
894     if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) &&
895         (last_bulk_time.abs_value != 0) &&
896         (0 == strncmp (buf, last_bulk, sizeof (last_bulk))))
897     {
898       last_bulk_repeat++;
899       if ((GNUNET_TIME_absolute_get_duration (last_bulk_time).rel_value >
900            BULK_DELAY_THRESHOLD) || (last_bulk_repeat > BULK_REPEAT_THRESHOLD))
901         flush_bulk (date);
902       return;
903     }
904     flush_bulk (date);
905     strncpy (last_bulk, buf, sizeof (last_bulk));
906     last_bulk_repeat = 0;
907     last_bulk_kind = kind;
908     last_bulk_time = GNUNET_TIME_absolute_get ();
909     strncpy (last_bulk_comp, comp, COMP_TRACK_SIZE);
910     output_message (kind, comp, date, buf);
911   }
912 }
913
914
915 /**
916  * Main log function.
917  *
918  * @param kind how serious is the error?
919  * @param message what is the message (format string)
920  * @param ... arguments for format string
921  */
922 void
923 GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...)
924 {
925   va_list va;
926
927   va_start (va, message);
928   mylog (kind, component, message, va);
929   va_end (va);
930 }
931
932
933 /**
934  * Log function that specifies an alternative component.
935  * This function should be used by plugins.
936  *
937  * @param kind how serious is the error?
938  * @param comp component responsible for generating the message
939  * @param message what is the message (format string)
940  * @param ... arguments for format string
941  */
942 void
943 GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp,
944                          const char *message, ...)
945 {
946   va_list va;
947   char comp_w_pid[128];
948
949   if (comp == NULL)
950     comp = component_nopid;
951
952   va_start (va, message);
953   GNUNET_snprintf (comp_w_pid, sizeof (comp_w_pid), "%s-%d", comp, getpid ());
954   mylog (kind, comp_w_pid, message, va);
955   va_end (va);
956 }
957
958
959 /**
960  * Convert error type to string.
961  *
962  * @param kind type to convert
963  * @return string corresponding to the type
964  */
965 const char *
966 GNUNET_error_type_to_string (enum GNUNET_ErrorType kind)
967 {
968   if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0)
969     return _("ERROR");
970   if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0)
971     return _("WARNING");
972   if ((kind & GNUNET_ERROR_TYPE_INFO) > 0)
973     return _("INFO");
974   if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0)
975     return _("DEBUG");
976   if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0)
977     return _("NONE");
978   return _("INVALID");
979 }
980
981
982 /**
983  * Convert a hash to a string (for printing debug messages).
984  * This is one of the very few calls in the entire API that is
985  * NOT reentrant!
986  *
987  * @param hc the hash code
988  * @return string form; will be overwritten by next call to GNUNET_h2s.
989  */
990 const char *
991 GNUNET_h2s (const struct GNUNET_HashCode * hc)
992 {
993   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
994
995   GNUNET_CRYPTO_hash_to_enc (hc, &ret);
996   ret.encoding[8] = '\0';
997   return (const char *) ret.encoding;
998 }
999
1000
1001 /**
1002  * Convert a hash to a string (for printing debug messages).
1003  * This is one of the very few calls in the entire API that is
1004  * NOT reentrant!
1005  *
1006  * @param hc the hash code
1007  * @return string form; will be overwritten by next call to GNUNET_h2s_full.
1008  */
1009 const char *
1010 GNUNET_h2s_full (const struct GNUNET_HashCode * hc)
1011 {
1012   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1013
1014   GNUNET_CRYPTO_hash_to_enc (hc, &ret);
1015   ret.encoding[sizeof (ret) - 1] = '\0';
1016   return (const char *) ret.encoding;
1017 }
1018
1019
1020 /**
1021  * Convert a peer identity to a string (for printing debug messages).
1022  * This is one of the very few calls in the entire API that is
1023  * NOT reentrant!
1024  *
1025  * @param pid the peer identity
1026  * @return string form of the pid; will be overwritten by next
1027  *         call to GNUNET_i2s.
1028  */
1029 const char *
1030 GNUNET_i2s (const struct GNUNET_PeerIdentity *pid)
1031 {
1032   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1033
1034   GNUNET_CRYPTO_hash_to_enc (&pid->hashPubKey, &ret);
1035   ret.encoding[4] = '\0';
1036   return (const char *) ret.encoding;
1037 }
1038
1039
1040 /**
1041  * Convert a peer identity to a string (for printing debug messages).
1042  * This is one of the very few calls in the entire API that is
1043  * NOT reentrant!
1044  *
1045  * @param pid the peer identity
1046  * @return string form of the pid; will be overwritten by next
1047  *         call to GNUNET_i2s.
1048  */
1049 const char *
1050 GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid)
1051 {
1052   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1053
1054   GNUNET_CRYPTO_hash_to_enc (&pid->hashPubKey, &ret);
1055   return (const char *) ret.encoding;
1056 }
1057
1058
1059 /**
1060  * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string
1061  * (for printing debug messages).  This is one of the very few calls
1062  * in the entire API that is NOT reentrant!
1063  *
1064  * @param addr the address
1065  * @param addrlen the length of the address
1066  * @return nicely formatted string for the address
1067  *  will be overwritten by next call to GNUNET_a2s.
1068  */
1069 const char *
1070 GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen)
1071 {
1072   static char buf[INET6_ADDRSTRLEN + 8];
1073   static char b2[6];
1074   const struct sockaddr_in *v4;
1075   const struct sockaddr_un *un;
1076   const struct sockaddr_in6 *v6;
1077   unsigned int off;
1078
1079   if (addr == NULL)
1080     return _("unknown address");
1081   switch (addr->sa_family)
1082   {
1083   case AF_INET:
1084     if (addrlen != sizeof (struct sockaddr_in))
1085       return "<invalid v4 address>";
1086     v4 = (const struct sockaddr_in *) addr;
1087     inet_ntop (AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN);
1088     if (0 == ntohs (v4->sin_port))
1089       return buf;
1090     strcat (buf, ":");
1091     GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v4->sin_port));
1092     strcat (buf, b2);
1093     return buf;
1094   case AF_INET6:
1095     if (addrlen != sizeof (struct sockaddr_in6))
1096       return "<invalid v4 address>";
1097     v6 = (const struct sockaddr_in6 *) addr;
1098     buf[0] = '[';
1099     inet_ntop (AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN);
1100     if (0 == ntohs (v6->sin6_port))
1101       return &buf[1];
1102     strcat (buf, "]:");
1103     GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v6->sin6_port));
1104     strcat (buf, b2);
1105     return buf;
1106   case AF_UNIX:
1107     if (addrlen <= sizeof (sa_family_t))
1108       return "<unbound UNIX client>";
1109     un = (const struct sockaddr_un *) addr;
1110     off = 0;
1111     if (un->sun_path[0] == '\0')
1112       off++;
1113     snprintf (buf, sizeof (buf), "%s%.*s", (off == 1) ? "@" : "",
1114               (int) (addrlen - sizeof (sa_family_t) - 1 - off),
1115               &un->sun_path[off]);
1116     return buf;
1117   default:
1118     return _("invalid address");
1119   }
1120 }
1121
1122
1123 /**
1124  * Initializer
1125  */
1126 void __attribute__ ((constructor)) GNUNET_util_cl_init ()
1127 {
1128   GNUNET_stderr = stderr;
1129 #ifdef MINGW
1130   GNInitWinEnv (NULL);
1131 #endif
1132 }
1133
1134
1135 /**
1136  * Destructor
1137  */
1138 void __attribute__ ((destructor)) GNUNET_util_cl_fini ()
1139 {
1140 #ifdef MINGW
1141   GNShutdownWinEnv ();
1142 #endif
1143 }
1144
1145 /* end of common_logging.c */