Merge branch 'license/spdx'
[oweals/gnunet.git] / src / util / common_logging.c
1 /*
2      This file is part of GNUnet.
3      Copyright (C) 2006-2013 GNUnet e.V.
4
5      GNUnet is free software: you can redistribute it and/or modify it
6      under the terms of the GNU Affero General Public License as published
7      by the Free Software Foundation, either version 3 of the License,
8      or (at your 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      Affero General Public License for more details.
14
15      You should have received a copy of the GNU Affero General Public License
16      along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
18      SPDX-License-Identifier: AGPL3.0-or-later
19 */
20
21 /**
22  * @file util/common_logging.c
23  * @brief error handling API
24  * @author Christian Grothoff
25  */
26 #include "platform.h"
27 #include "gnunet_crypto_lib.h"
28 #include "gnunet_disk_lib.h"
29 #include "gnunet_strings_lib.h"
30 #include <regex.h>
31
32
33 /**
34  * After how many milliseconds do we always print
35  * that "message X was repeated N times"?  Use 12h.
36  */
37 #define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000LL * 1000LL)
38
39 /**
40  * After how many repetitions do we always print
41  * that "message X was repeated N times"? (even if
42  * we have not yet reached the delay threshold)
43  */
44 #define BULK_REPEAT_THRESHOLD 1000
45
46 /**
47  * How many characters do we use for matching of
48  * bulk messages?
49  */
50 #define BULK_TRACK_SIZE 256
51
52 /**
53  * How many characters do we use for matching of
54  * bulk components?
55  */
56 #define COMP_TRACK_SIZE 32
57
58 /**
59  * How many characters can a date/time string
60  * be at most?
61  */
62 #define DATE_STR_SIZE 64
63
64 /**
65  * How many log files to keep?
66  */
67 #define ROTATION_KEEP 3
68
69 #ifndef PATH_MAX
70 /**
71  * Assumed maximum path length (for the log file name).
72  */
73 #define PATH_MAX 4096
74 #endif
75
76
77 /**
78  * Linked list of active loggers.
79  */
80 struct CustomLogger
81 {
82   /**
83    * This is a linked list.
84    */
85   struct CustomLogger *next;
86
87   /**
88    * Log function.
89    */
90   GNUNET_Logger logger;
91
92   /**
93    * Closure for logger.
94    */
95   void *logger_cls;
96 };
97
98 /**
99  * The last "bulk" error message that we have been logging.
100  * Note that this message maybe truncated to the first BULK_TRACK_SIZE
101  * characters, in which case it is NOT 0-terminated!
102  */
103 static char last_bulk[BULK_TRACK_SIZE];
104
105 /**
106  * Type of the last bulk message.
107  */
108 static enum GNUNET_ErrorType last_bulk_kind;
109
110 /**
111  * Time of the last bulk error message (0 for none)
112  */
113 static struct GNUNET_TIME_Absolute last_bulk_time;
114
115 /**
116  * Number of times that bulk message has been repeated since.
117  */
118 static unsigned int last_bulk_repeat;
119
120 /**
121  * Component when the last bulk was logged.  Will be 0-terminated.
122  */
123 static char last_bulk_comp[COMP_TRACK_SIZE + 1];
124
125 /**
126  * Running component.
127  */
128 static char *component;
129
130 /**
131  * Running component (without pid).
132  */
133 static char *component_nopid;
134
135 /**
136  * Format string describing the name of the log file.
137  */
138 static char *log_file_name;
139
140 /**
141  * Minimum log level.
142  */
143 static enum GNUNET_ErrorType min_level;
144
145 /**
146  * Linked list of our custom loggres.
147  */
148 static struct CustomLogger *loggers;
149
150 /**
151  * Number of log calls to ignore.
152  */
153 static int skip_log = 0;
154
155 /**
156  * File descriptor to use for "stderr", or NULL for none.
157  */
158 static FILE *GNUNET_stderr;
159
160 /**
161  * Represents a single logging definition
162  */
163 struct LogDef
164 {
165   /**
166    * Component name regex
167    */
168   regex_t component_regex;
169
170   /**
171    * File name regex
172    */
173   regex_t file_regex;
174
175   /**
176    * Function name regex
177    */
178   regex_t function_regex;
179
180   /**
181    * Lowest line at which this definition matches.
182    * Defaults to 0. Must be <= to_line.
183    */
184   int from_line;
185
186   /**
187    * Highest line at which this definition matches.
188    * Defaults to INT_MAX. Must be >= from_line.
189    */
190   int to_line;
191
192   /**
193    * Maximal log level allowed for calls that match this definition.
194    * Calls with higher log level will be disabled.
195    * Must be >= 0
196    */
197   int level;
198
199   /**
200    * 1 if this definition comes from GNUNET_FORCE_LOG, which means that it
201    * overrides any configuration options. 0 otherwise.
202    */
203   int force;
204 };
205
206
207 #if !defined(GNUNET_CULL_LOGGING)
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 #endif
238
239 #ifdef WINDOWS
240 /**
241  * Contains the number of performance counts per second.
242  */
243 static LARGE_INTEGER performance_frequency;
244 #endif
245
246
247 /**
248  * Convert a textual description of a loglevel
249  * to the respective GNUNET_GE_KIND.
250  *
251  * @param log loglevel to parse
252  * @return GNUNET_GE_INVALID if log does not parse
253  */
254 static enum GNUNET_ErrorType
255 get_type (const char *log)
256 {
257   if (NULL == log)
258     return GNUNET_ERROR_TYPE_UNSPECIFIED;
259   if (0 == strcasecmp (log, _("DEBUG")))
260     return GNUNET_ERROR_TYPE_DEBUG;
261   if (0 == strcasecmp (log, _("INFO")))
262     return GNUNET_ERROR_TYPE_INFO;
263   if (0 == strcasecmp (log, _("MESSAGE")))
264     return GNUNET_ERROR_TYPE_MESSAGE;
265   if (0 == strcasecmp (log, _("WARNING")))
266     return GNUNET_ERROR_TYPE_WARNING;
267   if (0 == strcasecmp (log, _("ERROR")))
268     return GNUNET_ERROR_TYPE_ERROR;
269   if (0 == strcasecmp (log, _("NONE")))
270     return GNUNET_ERROR_TYPE_NONE;
271   return GNUNET_ERROR_TYPE_INVALID;
272 }
273
274
275 /**
276  * Abort the process, generate a core dump if possible.
277  */
278 void
279 GNUNET_abort_ ()
280 {
281 #if WINDOWS
282   DebugBreak ();
283 #endif
284   abort ();
285 }
286
287
288 #if !defined(GNUNET_CULL_LOGGING)
289 /**
290  * Utility function - reallocates logdefs array to be twice as large.
291  */
292 static void
293 resize_logdefs ()
294 {
295   logdefs_size = (logdefs_size + 1) * 2;
296   logdefs = GNUNET_realloc (logdefs, logdefs_size * sizeof (struct LogDef));
297 }
298
299
300 #if ! TALER_WALLET_ONLY
301 /**
302  * Rotate logs, deleting the oldest log.
303  *
304  * @param new_name new name to add to the rotation
305  */
306 static void
307 log_rotate (const char *new_name)
308 {
309   static char *rotation[ROTATION_KEEP];
310   static unsigned int rotation_off;
311   char *discard;
312
313   if ('\0' == *new_name)
314     return; /* not a real log file name */
315   discard = rotation[rotation_off % ROTATION_KEEP];
316   if (NULL != discard)
317   {
318     /* Note: can't log errors during logging (recursion!), so this
319        operation MUST silently fail... */
320     (void) UNLINK (discard);
321     GNUNET_free (discard);
322   }
323   rotation[rotation_off % ROTATION_KEEP] = GNUNET_strdup (new_name);
324   rotation_off++;
325 }
326
327
328 /**
329  * Setup the log file.
330  *
331  * @param tm timestamp for which we should setup logging
332  * @return #GNUNET_OK on success, #GNUNET_SYSERR on error
333  */
334 static int
335 setup_log_file (const struct tm *tm)
336 {
337   static char last_fn[PATH_MAX + 1];
338   char fn[PATH_MAX + 1];
339   int altlog_fd;
340   int dup_return;
341   FILE *altlog;
342   char *leftsquare;
343
344   if (NULL == log_file_name)
345     return GNUNET_SYSERR;
346   if (0 == strftime (fn, sizeof (fn), log_file_name, tm))
347     return GNUNET_SYSERR;
348   leftsquare = strrchr (fn, '[');
349   if ( (NULL != leftsquare) && (']' == leftsquare[1]) )
350   {
351     char *logfile_copy = GNUNET_strdup (fn);
352
353     logfile_copy[leftsquare - fn] = '\0';
354     logfile_copy[leftsquare - fn + 1] = '\0';
355     snprintf (fn,
356               PATH_MAX,
357               "%s%d%s",
358               logfile_copy,
359               getpid (),
360               &logfile_copy[leftsquare - fn + 2]);
361     GNUNET_free (logfile_copy);
362   }
363   if (0 == strcmp (fn, last_fn))
364     return GNUNET_OK; /* no change */
365   log_rotate (last_fn);
366   strcpy (last_fn, fn);
367   if (GNUNET_SYSERR ==
368       GNUNET_DISK_directory_create_for_file (fn))
369   {
370     fprintf (stderr,
371              "Failed to create directory for `%s': %s\n",
372              fn,
373              STRERROR (errno));
374     return GNUNET_SYSERR;
375   }
376 #if WINDOWS
377   altlog_fd = OPEN (fn, O_APPEND |
378                         O_BINARY |
379                         O_WRONLY | O_CREAT,
380                         _S_IREAD | _S_IWRITE);
381 #else
382   altlog_fd = OPEN (fn, O_APPEND |
383                         O_WRONLY | O_CREAT,
384                         S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
385 #endif
386   if (-1 != altlog_fd)
387   {
388     if (NULL != GNUNET_stderr)
389       fclose (GNUNET_stderr);
390     dup_return = dup2 (altlog_fd, 2);
391     (void) close (altlog_fd);
392     if (-1 != dup_return)
393     {
394       altlog = fdopen (2, "ab");
395       if (NULL == altlog)
396       {
397         (void) close (2);
398         altlog_fd = -1;
399       }
400     }
401     else
402     {
403       altlog_fd = -1;
404     }
405   }
406   if (-1 == altlog_fd)
407   {
408     GNUNET_log_strerror_file (GNUNET_ERROR_TYPE_ERROR, "open", fn);
409     return GNUNET_SYSERR;
410   }
411   GNUNET_stderr = altlog;
412   return GNUNET_OK;
413 }
414 #endif
415
416
417 /**
418  * Utility function - adds a parsed definition to logdefs array.
419  *
420  * @param component see struct LogDef, can't be NULL
421  * @param file see struct LogDef, can't be NULL
422  * @param function see struct LogDef, can't be NULL
423  * @param from_line see struct LogDef
424  * @param to_line see struct LogDef
425  * @param level see struct LogDef, must be >= 0
426  * @param force see struct LogDef
427  * @return 0 on success, regex-specific error otherwise
428  */
429 static int
430 add_definition (const char *component,
431                 const char *file,
432                 const char *function,
433                 int from_line,
434                 int to_line,
435                 int level,
436                 int force)
437 {
438   struct LogDef n;
439   int r;
440
441   if (logdefs_size == logdefs_len)
442     resize_logdefs ();
443   memset (&n, 0, sizeof (n));
444   if (0 == strlen (component))
445     component = (char *) ".*";
446   r = regcomp (&n.component_regex, (const char *) component, REG_NOSUB);
447   if (0 != r)
448   {
449     return r;
450   }
451   if (0 == strlen (file))
452     file = (char *) ".*";
453   r = regcomp (&n.file_regex, (const char *) file, REG_NOSUB);
454   if (0 != r)
455   {
456     regfree (&n.component_regex);
457     return r;
458   }
459   if ((NULL == function) || (0 == strlen (function)))
460     function = (char *) ".*";
461   r = regcomp (&n.function_regex, (const char *) function, REG_NOSUB);
462   if (0 != r)
463   {
464     regfree (&n.component_regex);
465     regfree (&n.file_regex);
466     return r;
467   }
468   n.from_line = from_line;
469   n.to_line = to_line;
470   n.level = level;
471   n.force = force;
472   logdefs[logdefs_len++] = n;
473   return 0;
474 }
475
476
477 /**
478  * Decides whether a particular logging call should or should not be allowed
479  * to be made. Used internally by GNUNET_log*()
480  *
481  * @param caller_level loglevel the caller wants to use
482  * @param comp component name the caller uses (NULL means that global
483  *   component name is used)
484  * @param file file name containing the logging call, usually __FILE__
485  * @param function function which tries to make a logging call,
486  *   usually __FUNCTION__
487  * @param line line at which the call is made, usually __LINE__
488  * @return 0 to disallow the call, 1 to allow it
489  */
490 int
491 GNUNET_get_log_call_status (int caller_level,
492                             const char *comp,
493                             const char *file,
494                             const char *function,
495                             int line)
496 {
497   struct LogDef *ld;
498   int i;
499   int force_only;
500
501   if (NULL == comp)
502     /* Use default component */
503     comp = component_nopid;
504
505   /* We have no definitions to override globally configured log level,
506    * so just use it right away.
507    */
508   if ( (min_level >= 0) && (GNUNET_NO == gnunet_force_log_present) )
509     return caller_level <= min_level;
510
511   /* Only look for forced definitions? */
512   force_only = min_level >= 0;
513   for (i = 0; i < logdefs_len; i++)
514   {
515     ld = &logdefs[i];
516     if (( (!force_only) || ld->force) &&
517         (line >= ld->from_line && line <= ld->to_line) &&
518         (0 == regexec (&ld->component_regex, comp, 0, NULL, 0)) &&
519         (0 == regexec (&ld->file_regex, file, 0, NULL, 0)) &&
520         (0 == regexec (&ld->function_regex, function, 0, NULL, 0)))
521     {
522       /* We're finished */
523       return caller_level <= ld->level;
524     }
525   }
526   /* No matches - use global level, if defined */
527   if (min_level >= 0)
528     return caller_level <= min_level;
529   /* All programs/services previously defaulted to WARNING.
530    * Now *we* default to WARNING, and THEY default to NULL.
531    * Or rather we default to MESSAGE, since things aren't always bad.
532    */
533   return caller_level <= GNUNET_ERROR_TYPE_MESSAGE;
534 }
535
536
537 /**
538  * Utility function - parses a definition
539  *
540  * Definition format:
541  * component;file;function;from_line-to_line;level[/component...]
542  * All entries are mandatory, but may be empty.
543  * Empty entries for component, file and function are treated as
544  * "matches anything".
545  * Empty line entry is treated as "from 0 to INT_MAX"
546  * Line entry with only one line is treated as "this line only"
547  * Entry for level MUST NOT be empty.
548  * Entries for component, file and function that consist of a
549  * single character "*" are treated (at the moment) the same way
550  * empty entries are treated (wildcard matching is not implemented (yet?)).
551  * file entry is matched to the end of __FILE__. That is, it might be
552  * a base name, or a base name with leading directory names (some compilers
553  * define __FILE__ to absolute file path).
554  *
555  * @param constname name of the environment variable from which to get the
556  *   string to be parsed
557  * @param force 1 if definitions found in constname are to be forced
558  * @return number of added definitions
559  */
560 static int
561 parse_definitions (const char *constname, int force)
562 {
563   char *def;
564   const char *tmp;
565   char *comp = NULL;
566   char *file = NULL;
567   char *function = NULL;
568   char *p;
569   char *start;
570   char *t;
571   short state;
572   int level;
573   int from_line, to_line;
574   int counter = 0;
575   int keep_looking = 1;
576
577   tmp = getenv (constname);
578   if (NULL == tmp)
579     return 0;
580   def = GNUNET_strdup (tmp);
581   from_line = 0;
582   to_line = INT_MAX;
583   for (p = def, state = 0, start = def; keep_looking; p++)
584   {
585     switch (p[0])
586     {
587     case ';':                  /* found a field separator */
588       p[0] = '\0';
589       switch (state)
590       {
591       case 0:                  /* within a component name */
592         comp = start;
593         break;
594       case 1:                  /* within a file name */
595         file = start;
596         break;
597       case 2:                  /* within a function name */
598         /* after a file name there must be a function name */
599         function = start;
600         break;
601       case 3:                  /* within a from-to line range */
602         if (strlen (start) > 0)
603         {
604           errno = 0;
605           from_line = strtol (start, &t, 10);
606           if ( (0 != errno) || (from_line < 0) )
607           {
608             GNUNET_free (def);
609             return counter;
610           }
611           if ( (t < p) && ('-' == t[0]) )
612           {
613             errno = 0;
614             start = t + 1;
615             to_line = strtol (start, &t, 10);
616             if ( (0 != errno) || (to_line < 0) || (t != p) )
617             {
618               GNUNET_free (def);
619               return counter;
620             }
621           }
622           else                  /* one number means "match this line only" */
623             to_line = from_line;
624         }
625         else                    /* default to 0-max */
626         {
627           from_line = 0;
628           to_line = INT_MAX;
629         }
630         break;
631       default:
632         fprintf(stderr,
633                 _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
634                 p);
635         break;
636       }
637       start = p + 1;
638       state++;
639       break;
640     case '\0':                 /* found EOL */
641       keep_looking = 0;
642       /* fall through to '/' */
643     case '/':                  /* found a definition separator */
644       switch (state)
645       {
646       case 4:                  /* within a log level */
647         p[0] = '\0';
648         state = 0;
649         level = get_type ((const char *) start);
650         if ( (GNUNET_ERROR_TYPE_INVALID == level) ||
651              (GNUNET_ERROR_TYPE_UNSPECIFIED == level) ||
652              (0 != add_definition (comp, file, function, from_line, to_line,
653                                    level, force)) )
654         {
655           GNUNET_free (def);
656           return counter;
657         }
658         counter++;
659         start = p + 1;
660         break;
661       default:
662         fprintf(stderr,
663                 _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
664                 p);
665         break;
666       }
667     default:
668       break;
669     }
670   }
671   GNUNET_free (def);
672   return counter;
673 }
674
675
676 /**
677  * Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG.
678  */
679 static void
680 parse_all_definitions ()
681 {
682   if (GNUNET_NO == gnunet_log_parsed)
683     parse_definitions ("GNUNET_LOG", 0);
684   gnunet_log_parsed = GNUNET_YES;
685   if (GNUNET_NO == gnunet_force_log_parsed)
686     gnunet_force_log_present =
687         parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO;
688   gnunet_force_log_parsed = GNUNET_YES;
689 }
690 #endif
691
692
693 /**
694  * Setup logging.
695  *
696  * @param comp default component to use
697  * @param loglevel what types of messages should be logged
698  * @param logfile which file to write log messages to (can be NULL)
699  * @return #GNUNET_OK on success
700  */
701 int
702 GNUNET_log_setup (const char *comp,
703                   const char *loglevel,
704                   const char *logfile)
705 {
706   const char *env_logfile;
707
708   min_level = get_type (loglevel);
709 #if !defined(GNUNET_CULL_LOGGING)
710   parse_all_definitions ();
711 #endif
712 #ifdef WINDOWS
713   QueryPerformanceFrequency (&performance_frequency);
714 #endif
715   GNUNET_free_non_null (component);
716   GNUNET_asprintf (&component, "%s-%d", comp, getpid ());
717   GNUNET_free_non_null (component_nopid);
718   component_nopid = GNUNET_strdup (comp);
719
720   env_logfile = getenv ("GNUNET_FORCE_LOGFILE");
721   if ((NULL != env_logfile) && (strlen (env_logfile) > 0))
722     logfile = env_logfile;
723   if (NULL == logfile)
724     return GNUNET_OK;
725   GNUNET_free_non_null (log_file_name);
726   log_file_name = GNUNET_STRINGS_filename_expand (logfile);
727   if (NULL == log_file_name)
728     return GNUNET_SYSERR;
729 #if TALER_WALLET_ONLY || defined(GNUNET_CULL_LOGGING)
730   /* log file option not allowed for wallet logic */
731   GNUNET_assert (NULL == logfile);
732   return GNUNET_OK;
733 #else
734   {
735     time_t t;
736     const struct tm *tm;
737
738     t = time (NULL);
739     tm = gmtime (&t);
740     return setup_log_file (tm);
741   }
742 #endif
743 }
744
745
746 /**
747  * Add a custom logger. Note that installing any custom logger
748  * will disable the standard logger.  When multiple custom loggers
749  * are installed, all will be called.  The standard logger will
750  * only be used if no custom loggers are present.
751  *
752  * @param logger log function
753  * @param logger_cls closure for @a logger
754  */
755 void
756 GNUNET_logger_add (GNUNET_Logger logger,
757                    void *logger_cls)
758 {
759   struct CustomLogger *entry;
760
761   entry = GNUNET_new (struct CustomLogger);
762   entry->logger = logger;
763   entry->logger_cls = logger_cls;
764   entry->next = loggers;
765   loggers = entry;
766 }
767
768
769 /**
770  * Remove a custom logger.
771  *
772  * @param logger log function
773  * @param logger_cls closure for @a logger
774  */
775 void
776 GNUNET_logger_remove (GNUNET_Logger logger,
777                       void *logger_cls)
778 {
779   struct CustomLogger *pos;
780   struct CustomLogger *prev;
781
782   prev = NULL;
783   pos = loggers;
784   while ((NULL != pos) &&
785          ((pos->logger != logger) || (pos->logger_cls != logger_cls)))
786   {
787     prev = pos;
788     pos = pos->next;
789   }
790   GNUNET_assert (NULL != pos);
791   if (NULL == prev)
792     loggers = pos->next;
793   else
794     prev->next = pos->next;
795   GNUNET_free (pos);
796 }
797
798 #if WINDOWS
799 CRITICAL_SECTION output_message_cs;
800 #endif
801
802
803 /**
804  * Actually output the log message.
805  *
806  * @param kind how severe was the issue
807  * @param comp component responsible
808  * @param datestr current date/time
809  * @param msg the actual message
810  */
811 static void
812 output_message (enum GNUNET_ErrorType kind,
813                 const char *comp,
814                 const char *datestr,
815                 const char *msg)
816 {
817   struct CustomLogger *pos;
818
819 #if WINDOWS
820   EnterCriticalSection (&output_message_cs);
821 #endif
822   /* only use the standard logger if no custom loggers are present */
823   if ( (NULL != GNUNET_stderr) &&
824        (NULL == loggers) )
825   {
826     if (kind == GNUNET_ERROR_TYPE_MESSAGE)
827     {
828       /* The idea here is to produce "normal" output messages
829        * for end users while still having the power of the
830        * logging engine for developer needs. So ideally this
831        * is what it should look like when CLI tools are used
832        * interactively, yet the same message shouldn't look
833        * this way if the output is going to logfiles or robots
834        * instead.
835        */
836       FPRINTF (GNUNET_stderr,
837                "* %s",
838                msg);
839     }
840     else
841     {
842       FPRINTF (GNUNET_stderr,
843                "%s %s %s %s",
844                datestr,
845                comp,
846                GNUNET_error_type_to_string (kind),
847                msg);
848     }
849     fflush (GNUNET_stderr);
850   }
851   pos = loggers;
852   while (NULL != pos)
853   {
854     pos->logger (pos->logger_cls,
855                  kind,
856                  comp,
857                  datestr,
858                  msg);
859     pos = pos->next;
860   }
861 #if WINDOWS
862   LeaveCriticalSection (&output_message_cs);
863 #endif
864 }
865
866
867 /**
868  * Flush an existing bulk report to the output.
869  *
870  * @param datestr our current timestamp
871  */
872 static void
873 flush_bulk (const char *datestr)
874 {
875   char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];
876   int rev;
877   char *last;
878   const char *ft;
879
880   if ( (0 == last_bulk_time.abs_value_us) ||
881        (0 == last_bulk_repeat) )
882     return;
883   rev = 0;
884   last = memchr (last_bulk, '\0', BULK_TRACK_SIZE);
885   if (last == NULL)
886     last = &last_bulk[BULK_TRACK_SIZE - 1];
887   else if (last != last_bulk)
888     last--;
889   if (last[0] == '\n')
890   {
891     rev = 1;
892     last[0] = '\0';
893   }
894   ft = GNUNET_STRINGS_relative_time_to_string (GNUNET_TIME_absolute_get_duration
895                                                (last_bulk_time), GNUNET_YES);
896   snprintf (msg, sizeof (msg),
897             _("Message `%.*s' repeated %u times in the last %s\n"),
898             BULK_TRACK_SIZE, last_bulk, last_bulk_repeat, ft);
899   if (rev == 1)
900     last[0] = '\n';
901   output_message (last_bulk_kind, last_bulk_comp, datestr, msg);
902   last_bulk_time = GNUNET_TIME_absolute_get ();
903   last_bulk_repeat = 0;
904 }
905
906
907 /**
908  * Ignore the next n calls to the log function.
909  *
910  * @param n number of log calls to ignore (could be negative)
911  * @param check_reset #GNUNET_YES to assert that the log skip counter is currently zero
912  */
913 void
914 GNUNET_log_skip (int n,
915                  int check_reset)
916 {
917   int ok;
918
919   if (0 == n)
920   {
921     ok = (0 == skip_log);
922     skip_log = 0;
923     if (check_reset)
924       GNUNET_break (ok);
925   }
926   else
927   {
928     skip_log += n;
929   }
930 }
931
932
933 /**
934  * Get the number of log calls that are going to be skipped
935  *
936  * @return number of log calls to be ignored
937  */
938 int
939 GNUNET_get_log_skip ()
940 {
941   return skip_log;
942 }
943
944
945 /**
946  * Output a log message using the default mechanism.
947  *
948  * @param kind how severe was the issue
949  * @param comp component responsible
950  * @param message the actual message
951  * @param va arguments to the format string "message"
952  */
953 static void
954 mylog (enum GNUNET_ErrorType kind,
955        const char *comp,
956        const char *message,
957        va_list va)
958 {
959   char date[DATE_STR_SIZE];
960   char date2[DATE_STR_SIZE];
961   struct tm *tmptr;
962   size_t size;
963   va_list vacp;
964
965   va_copy (vacp, va);
966   size = VSNPRINTF (NULL,
967                     0,
968                     message,
969                     vacp) + 1;
970   GNUNET_assert (0 != size);
971   va_end (vacp);
972   memset (date,
973           0,
974           DATE_STR_SIZE);
975   {
976     char buf[size];
977     long long offset;
978 #ifdef WINDOWS
979     LARGE_INTEGER pc;
980     time_t timetmp;
981
982     offset = GNUNET_TIME_get_offset ();
983     time (&timetmp);
984     timetmp += offset / 1000;
985     tmptr = localtime (&timetmp);
986     pc.QuadPart = 0;
987     QueryPerformanceCounter (&pc);
988     if (NULL == tmptr)
989     {
990       strcpy (date, "localtime error");
991     }
992     else
993     {
994       if (0 ==
995           strftime (date2,
996                     DATE_STR_SIZE,
997                     "%b %d %H:%M:%S-%%020llu",
998                     tmptr))
999         abort ();
1000       if (0 >
1001           snprintf (date,
1002                     sizeof (date),
1003                     date2,
1004                     (long long) (pc.QuadPart /
1005                                  (performance_frequency.QuadPart / 1000))))
1006         abort ();
1007     }
1008 #else
1009     struct timeval timeofday;
1010
1011     gettimeofday (&timeofday,
1012                   NULL);
1013     offset = GNUNET_TIME_get_offset ();
1014     if (offset > 0)
1015     {
1016       timeofday.tv_sec += offset / 1000LL;
1017       timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1018       if (timeofday.tv_usec > 1000000LL)
1019       {
1020         timeofday.tv_usec -= 1000000LL;
1021         timeofday.tv_sec++;
1022       }
1023     }
1024     else
1025     {
1026       timeofday.tv_sec += offset / 1000LL;
1027       if (timeofday.tv_usec > - (offset % 1000LL) * 1000LL)
1028       {
1029         timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1030       }
1031       else
1032       {
1033         timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL;
1034         timeofday.tv_sec--;
1035       }
1036     }
1037     tmptr = localtime (&timeofday.tv_sec);
1038     if (NULL == tmptr)
1039     {
1040       strcpy (date,
1041               "localtime error");
1042     }
1043     else
1044     {
1045       if (0 ==
1046           strftime (date2,
1047                     DATE_STR_SIZE,
1048                     "%b %d %H:%M:%S-%%06u",
1049                     tmptr))
1050         abort ();
1051       if (0 >
1052           snprintf (date,
1053                     sizeof (date),
1054                     date2,
1055                     timeofday.tv_usec))
1056         abort ();
1057     }
1058 #endif
1059     VSNPRINTF (buf,
1060                size,
1061                message,
1062                va);
1063 #if ! (defined(GNUNET_CULL_LOGGING) || TALER_WALLET_ONLY)
1064     if (NULL != tmptr)
1065       (void) setup_log_file (tmptr);
1066 #endif
1067     if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) &&
1068         (0 != last_bulk_time.abs_value_us) &&
1069         (0 == strncmp (buf,
1070                        last_bulk,
1071                        sizeof (last_bulk))))
1072     {
1073       last_bulk_repeat++;
1074       if ( (GNUNET_TIME_absolute_get_duration (last_bulk_time).rel_value_us >
1075             BULK_DELAY_THRESHOLD) ||
1076            (last_bulk_repeat > BULK_REPEAT_THRESHOLD) )
1077         flush_bulk (date);
1078       return;
1079     }
1080     flush_bulk (date);
1081     strncpy (last_bulk,
1082              buf,
1083              sizeof (last_bulk));
1084     last_bulk_repeat = 0;
1085     last_bulk_kind = kind;
1086     last_bulk_time = GNUNET_TIME_absolute_get ();
1087     strncpy (last_bulk_comp,
1088              comp,
1089              COMP_TRACK_SIZE);
1090     output_message (kind,
1091                     comp,
1092                     date,
1093                     buf);
1094   }
1095 }
1096
1097
1098 /**
1099  * Main log function.
1100  *
1101  * @param kind how serious is the error?
1102  * @param message what is the message (format string)
1103  * @param ... arguments for format string
1104  */
1105 void
1106 GNUNET_log_nocheck (enum GNUNET_ErrorType kind,
1107                     const char *message, ...)
1108 {
1109   va_list va;
1110
1111   va_start (va, message);
1112   mylog (kind, component, message, va);
1113   va_end (va);
1114 }
1115
1116
1117 /**
1118  * Log function that specifies an alternative component.
1119  * This function should be used by plugins.
1120  *
1121  * @param kind how serious is the error?
1122  * @param comp component responsible for generating the message
1123  * @param message what is the message (format string)
1124  * @param ... arguments for format string
1125  */
1126 void
1127 GNUNET_log_from_nocheck (enum GNUNET_ErrorType kind, const char *comp,
1128                          const char *message, ...)
1129 {
1130   va_list va;
1131   char comp_w_pid[128];
1132
1133   if (comp == NULL)
1134     comp = component_nopid;
1135
1136   va_start (va, message);
1137   GNUNET_snprintf (comp_w_pid, sizeof (comp_w_pid), "%s-%d", comp, getpid ());
1138   mylog (kind, comp_w_pid, message, va);
1139   va_end (va);
1140 }
1141
1142
1143 /**
1144  * Convert error type to string.
1145  *
1146  * @param kind type to convert
1147  * @return string corresponding to the type
1148  */
1149 const char *
1150 GNUNET_error_type_to_string (enum GNUNET_ErrorType kind)
1151 {
1152   if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0)
1153     return _("ERROR");
1154   if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0)
1155     return _("WARNING");
1156   if ((kind & GNUNET_ERROR_TYPE_MESSAGE) > 0)
1157     return _("MESSAGE");
1158   if ((kind & GNUNET_ERROR_TYPE_INFO) > 0)
1159     return _("INFO");
1160   if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0)
1161     return _("DEBUG");
1162   if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0)
1163     return _("NONE");
1164   return _("INVALID");
1165 }
1166
1167
1168 /**
1169  * Convert a hash to a string (for printing debug messages).
1170  * This is one of the very few calls in the entire API that is
1171  * NOT reentrant!
1172  *
1173  * @param hc the hash code
1174  * @return string form; will be overwritten by next call to GNUNET_h2s.
1175  */
1176 const char *
1177 GNUNET_h2s (const struct GNUNET_HashCode * hc)
1178 {
1179   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1180
1181   GNUNET_CRYPTO_hash_to_enc (hc, &ret);
1182   ret.encoding[8] = '\0';
1183   return (const char *) ret.encoding;
1184 }
1185
1186
1187 /**
1188  * Convert a hash to a string (for printing debug messages).
1189  * This is one of the very few calls in the entire API that is
1190  * NOT reentrant! Identical to #GNUNET_h2s(), except that another
1191  * buffer is used so both #GNUNET_h2s() and #GNUNET_h2s2() can be
1192  * used within the same log statement.
1193  *
1194  * @param hc the hash code
1195  * @return string form; will be overwritten by next call to GNUNET_h2s.
1196  */
1197 const char *
1198 GNUNET_h2s2 (const struct GNUNET_HashCode * hc)
1199 {
1200   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1201
1202   GNUNET_CRYPTO_hash_to_enc (hc, &ret);
1203   ret.encoding[8] = '\0';
1204   return (const char *) ret.encoding;
1205 }
1206
1207
1208 /**
1209  * @ingroup logging
1210  * Convert a public key value to a string (for printing debug messages).
1211  * This is one of the very few calls in the entire API that is
1212  * NOT reentrant!
1213  *
1214  * @param hc the hash code
1215  * @return string
1216  */
1217 const char *
1218 GNUNET_p2s (const struct GNUNET_CRYPTO_EddsaPublicKey *p)
1219 {
1220   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1221   struct GNUNET_HashCode hc;
1222
1223   GNUNET_CRYPTO_hash (p,
1224                       sizeof (*p),
1225                       &hc);
1226   GNUNET_CRYPTO_hash_to_enc (&hc,
1227                              &ret);
1228   ret.encoding[6] = '\0';
1229   return (const char *) ret.encoding;
1230 }
1231
1232
1233 /**
1234  * @ingroup logging
1235  * Convert a public key value to a string (for printing debug messages).
1236  * This is one of the very few calls in the entire API that is
1237  * NOT reentrant!
1238  *
1239  * @param hc the hash code
1240  * @return string
1241  */
1242 const char *
1243 GNUNET_p2s2 (const struct GNUNET_CRYPTO_EddsaPublicKey *p)
1244 {
1245   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1246   struct GNUNET_HashCode hc;
1247
1248   GNUNET_CRYPTO_hash (p,
1249                       sizeof (*p),
1250                       &hc);
1251   GNUNET_CRYPTO_hash_to_enc (&hc,
1252                              &ret);
1253   ret.encoding[6] = '\0';
1254   return (const char *) ret.encoding;
1255 }
1256
1257
1258 /**
1259  * @ingroup logging
1260  * Convert a public key value to a string (for printing debug messages).
1261  * This is one of the very few calls in the entire API that is
1262  * NOT reentrant!
1263  *
1264  * @param hc the hash code
1265  * @return string
1266  */
1267 const char *
1268 GNUNET_e2s (const struct GNUNET_CRYPTO_EcdhePublicKey *p)
1269 {
1270   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1271   struct GNUNET_HashCode hc;
1272
1273   GNUNET_CRYPTO_hash (p,
1274                       sizeof (*p),
1275                       &hc);
1276   GNUNET_CRYPTO_hash_to_enc (&hc,
1277                              &ret);
1278   ret.encoding[6] = '\0';
1279   return (const char *) ret.encoding;
1280 }
1281
1282
1283 /**
1284  * @ingroup logging
1285  * Convert a public key value to a string (for printing debug messages).
1286  * This is one of the very few calls in the entire API that is
1287  * NOT reentrant!
1288  *
1289  * @param hc the hash code
1290  * @return string
1291  */
1292 const char *
1293 GNUNET_e2s2 (const struct GNUNET_CRYPTO_EcdhePublicKey *p)
1294 {
1295   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1296   struct GNUNET_HashCode hc;
1297
1298   GNUNET_CRYPTO_hash (p,
1299                       sizeof (*p),
1300                       &hc);
1301   GNUNET_CRYPTO_hash_to_enc (&hc,
1302                              &ret);
1303   ret.encoding[6] = '\0';
1304   return (const char *) ret.encoding;
1305 }
1306
1307
1308 /**
1309  * @ingroup logging
1310  * Convert a short hash value to a string (for printing debug messages).
1311  * This is one of the very few calls in the entire API that is
1312  * NOT reentrant!
1313  *
1314  * @param shc the hash code
1315  * @return string
1316  */
1317 const char *
1318 GNUNET_sh2s (const struct GNUNET_ShortHashCode *shc)
1319 {
1320   static char buf[64];
1321
1322   GNUNET_STRINGS_data_to_string (shc,
1323                                  sizeof (*shc),
1324                                  buf,
1325                                  sizeof (buf));
1326   buf[6] = '\0';
1327   return (const char *) buf;
1328 }
1329
1330
1331 /**
1332  * Convert a hash to a string (for printing debug messages).
1333  * This is one of the very few calls in the entire API that is
1334  * NOT reentrant!
1335  *
1336  * @param hc the hash code
1337  * @return string form; will be overwritten by next call to GNUNET_h2s_full.
1338  */
1339 const char *
1340 GNUNET_h2s_full (const struct GNUNET_HashCode * hc)
1341 {
1342   static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1343
1344   GNUNET_CRYPTO_hash_to_enc (hc, &ret);
1345   ret.encoding[sizeof (ret) - 1] = '\0';
1346   return (const char *) ret.encoding;
1347 }
1348
1349
1350 /**
1351  * Convert a peer identity to a string (for printing debug messages).
1352  * This is one of the very few calls in the entire API that is
1353  * NOT reentrant!
1354  *
1355  * @param pid the peer identity
1356  * @return string form of the pid; will be overwritten by next
1357  *         call to #GNUNET_i2s.
1358  */
1359 const char *
1360 GNUNET_i2s (const struct GNUNET_PeerIdentity *pid)
1361 {
1362   static char buf[5];
1363   char *ret;
1364
1365   if (NULL == pid)
1366     return "NULL";
1367   ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key);
1368   strncpy (buf,
1369            ret,
1370            sizeof (buf) - 1);
1371   GNUNET_free (ret);
1372   buf[4] = '\0';
1373   return buf;
1374 }
1375
1376
1377 /**
1378  * Convert a peer identity to a string (for printing debug messages).
1379  * This is one of the very few calls in the entire API that is
1380  * NOT reentrant!  Identical to #GNUNET_i2s(), except that another
1381  * buffer is used so both #GNUNET_i2s() and #GNUNET_i2s2() can be
1382  * used within the same log statement.
1383  *
1384  * @param pid the peer identity
1385  * @return string form of the pid; will be overwritten by next
1386  *         call to #GNUNET_i2s.
1387  */
1388 const char *
1389 GNUNET_i2s2 (const struct GNUNET_PeerIdentity *pid)
1390 {
1391   static char buf[5];
1392   char *ret;
1393
1394   if (NULL == pid)
1395     return "NULL";
1396   ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key);
1397   strncpy (buf,
1398            ret,
1399            sizeof (buf) - 1);
1400   GNUNET_free (ret);
1401   buf[4] = '\0';
1402   return buf;
1403 }
1404
1405
1406 /**
1407  * Convert a peer identity to a string (for printing debug messages).
1408  * This is one of the very few calls in the entire API that is
1409  * NOT reentrant!
1410  *
1411  * @param pid the peer identity
1412  * @return string form of the pid; will be overwritten by next
1413  *         call to #GNUNET_i2s_full.
1414  */
1415 const char *
1416 GNUNET_i2s_full (const struct GNUNET_PeerIdentity *pid)
1417 {
1418   static char buf[256];
1419   char *ret;
1420
1421   ret = GNUNET_CRYPTO_eddsa_public_key_to_string (&pid->public_key);
1422   strcpy (buf, ret);
1423   GNUNET_free (ret);
1424   return buf;
1425 }
1426
1427
1428 /**
1429  * Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string
1430  * (for printing debug messages).  This is one of the very few calls
1431  * in the entire API that is NOT reentrant!
1432  *
1433  * @param addr the address
1434  * @param addrlen the length of the address in @a addr
1435  * @return nicely formatted string for the address
1436  *  will be overwritten by next call to #GNUNET_a2s.
1437  */
1438 const char *
1439 GNUNET_a2s (const struct sockaddr *addr,
1440             socklen_t addrlen)
1441 {
1442 #ifndef WINDOWS
1443 #define LEN GNUNET_MAX ((INET6_ADDRSTRLEN + 8),         \
1444                         (1 + sizeof (struct sockaddr_un) - sizeof (sa_family_t)))
1445 #else
1446 #define LEN (INET6_ADDRSTRLEN + 8)
1447 #endif
1448   static char buf[LEN];
1449 #undef LEN
1450   static char b2[6];
1451   const struct sockaddr_in *v4;
1452   const struct sockaddr_un *un;
1453   const struct sockaddr_in6 *v6;
1454   unsigned int off;
1455
1456   if (addr == NULL)
1457     return _("unknown address");
1458   switch (addr->sa_family)
1459   {
1460   case AF_INET:
1461     if (addrlen != sizeof (struct sockaddr_in))
1462       return "<invalid v4 address>";
1463     v4 = (const struct sockaddr_in *) addr;
1464     inet_ntop (AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN);
1465     if (0 == ntohs (v4->sin_port))
1466       return buf;
1467     strcat (buf, ":");
1468     GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v4->sin_port));
1469     strcat (buf, b2);
1470     return buf;
1471   case AF_INET6:
1472     if (addrlen != sizeof (struct sockaddr_in6))
1473       return "<invalid v4 address>";
1474     v6 = (const struct sockaddr_in6 *) addr;
1475     buf[0] = '[';
1476     inet_ntop (AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN);
1477     if (0 == ntohs (v6->sin6_port))
1478       return &buf[1];
1479     strcat (buf, "]:");
1480     GNUNET_snprintf (b2, sizeof (b2), "%u", ntohs (v6->sin6_port));
1481     strcat (buf, b2);
1482     return buf;
1483   case AF_UNIX:
1484     if (addrlen <= sizeof (sa_family_t))
1485       return "<unbound UNIX client>";
1486     un = (const struct sockaddr_un *) addr;
1487     off = 0;
1488     if ('\0' == un->sun_path[0])
1489       off++;
1490     memset (buf, 0, sizeof (buf));
1491     GNUNET_snprintf (buf,
1492                      sizeof (buf),
1493                      "%s%.*s",
1494                      (1 == off) ? "@" : "",
1495                      (int) (addrlen - sizeof (sa_family_t) - off),
1496                      &un->sun_path[off]);
1497     return buf;
1498   default:
1499     return _("invalid address");
1500   }
1501 }
1502
1503
1504 /**
1505  * Log error message about missing configuration option.
1506  *
1507  * @param kind log level
1508  * @param section section with missing option
1509  * @param option name of missing option
1510  */
1511 void
1512 GNUNET_log_config_missing (enum GNUNET_ErrorType kind,
1513                            const char *section,
1514                            const char *option)
1515 {
1516   GNUNET_log (kind,
1517               _("Configuration fails to specify option `%s' in section `%s'!\n"),
1518               option,
1519               section);
1520 }
1521
1522
1523 /**
1524  * Log error message about invalid configuration option value.
1525  *
1526  * @param kind log level
1527  * @param section section with invalid option
1528  * @param option name of invalid option
1529  * @param required what is required that is invalid about the option
1530  */
1531 void
1532 GNUNET_log_config_invalid (enum GNUNET_ErrorType kind,
1533                            const char *section,
1534                            const char *option,
1535                            const char *required)
1536 {
1537   GNUNET_log (kind,
1538               _("Configuration specifies invalid value for option `%s' in section `%s': %s\n"),
1539               option, section, required);
1540 }
1541
1542
1543 /**
1544  * Initializer
1545  */
1546 void __attribute__ ((constructor))
1547 GNUNET_util_cl_init ()
1548 {
1549   GNUNET_stderr = stderr;
1550 #ifdef MINGW
1551   GNInitWinEnv (NULL);
1552 #endif
1553 #if WINDOWS
1554   if (!InitializeCriticalSectionAndSpinCount (&output_message_cs, 0x00000400))
1555     GNUNET_abort_ ();
1556 #endif
1557 }
1558
1559
1560 /**
1561  * Destructor
1562  */
1563 void __attribute__ ((destructor))
1564 GNUNET_util_cl_fini ()
1565 {
1566 #if WINDOWS
1567   DeleteCriticalSection (&output_message_cs);
1568 #endif
1569 #ifdef MINGW
1570   GNShutdownWinEnv ();
1571 #endif
1572 }
1573
1574 /* end of common_logging.c */