GNUnet  0.19.4
common_logging.c
Go to the documentation of this file.
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 
27 #include "platform.h"
28 #include "gnunet_util_lib.h"
29 #include <regex.h>
30 
31 
36 #define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000LL * 1000LL)
37 
43 #define BULK_REPEAT_THRESHOLD 1000
44 
49 #define BULK_TRACK_SIZE 256
50 
55 #define COMP_TRACK_SIZE 32
56 
61 #define DATE_STR_SIZE 64
62 
66 #define ROTATION_KEEP 3
67 
68 #ifndef PATH_MAX
72 #define PATH_MAX 4096
73 #endif
74 
75 
80 {
84  struct CustomLogger *next;
85 
90 
94  void *logger_cls;
95 };
96 
97 
103 
110 
115 
120 
125 
130 
134 static char *component;
135 
139 static char *component_nopid;
140 
144 static char *log_file_name;
145 
149 static enum GNUNET_ErrorType min_level;
150 
154 static struct CustomLogger *loggers;
155 
160 
164 static FILE *GNUNET_stderr;
165 
169 struct LogDef
170 {
175 
179  regex_t file_regex;
180 
184  regex_t function_regex;
185 
191 
196  int to_line;
197 
203  int level;
204 
209  int force;
210 };
211 
212 
213 #if ! defined(GNUNET_CULL_LOGGING)
217 static struct LogDef *logdefs;
218 
222 static int logdefs_size;
223 
227 static int logdefs_len;
228 
232 static int gnunet_log_parsed;
233 
238 
243 #endif
244 
245 
253 static enum GNUNET_ErrorType
254 get_type (const char *log)
255 {
256  if (NULL == log)
258  if (0 == strcasecmp (log, "DEBUG"))
260  if (0 == strcasecmp (log, "INFO"))
261  return GNUNET_ERROR_TYPE_INFO;
262  if (0 == strcasecmp (log, "MESSAGE"))
264  if (0 == strcasecmp (log, "WARNING"))
266  if (0 == strcasecmp (log, "ERROR"))
268  if (0 == strcasecmp (log, "NONE"))
269  return GNUNET_ERROR_TYPE_NONE;
271 }
272 
273 
277 void
279 {
280  abort ();
281 }
282 
283 
284 #if ! defined(GNUNET_CULL_LOGGING)
288 static void
290 {
291  logdefs_size = (logdefs_size + 1) * 2;
292  logdefs = GNUNET_realloc (logdefs, logdefs_size * sizeof(struct LogDef));
293 }
294 
295 
301 static void
302 log_rotate (const char *new_name)
303 {
304  static char *rotation[ROTATION_KEEP];
305  static unsigned int rotation_off;
306  char *discard;
307 
308  if ('\0' == *new_name)
309  return; /* not a real log file name */
310  discard = rotation[rotation_off % ROTATION_KEEP];
311  if (NULL != discard)
312  {
313  /* Note: can't log errors during logging (recursion!), so this
314  operation MUST silently fail... */
315  (void) unlink (discard);
316  GNUNET_free (discard);
317  }
318  rotation[rotation_off % ROTATION_KEEP] = GNUNET_strdup (new_name);
319  rotation_off++;
320 }
321 
322 
323 const char *
324 GNUNET_b2s (const void *buf,
325  size_t buf_size)
326 {
327  static GNUNET_THREAD_LOCAL char ret[9];
328  struct GNUNET_HashCode hc;
329  char *tmp;
330 
332  buf_size,
333  &hc);
335  sizeof (hc));
336  memcpy (ret,
337  tmp,
338  8);
339  GNUNET_free (tmp);
340  ret[8] = '\0';
341  return ret;
342 }
343 
344 
351 static int
352 setup_log_file (const struct tm *tm)
353 {
354  static char last_fn[PATH_MAX + 1];
355  char fn[PATH_MAX + 1];
356  int altlog_fd;
357  int dup_return;
358  FILE *altlog;
359  char *leftsquare;
360 
361  if (NULL == log_file_name)
362  return GNUNET_SYSERR;
363  if (0 == strftime (fn, sizeof(fn), log_file_name, tm))
364  return GNUNET_SYSERR;
365  leftsquare = strrchr (fn, '[');
366  if ((NULL != leftsquare) && (']' == leftsquare[1]))
367  {
368  char *logfile_copy = GNUNET_strdup (fn);
369 
370  logfile_copy[leftsquare - fn] = '\0';
371  logfile_copy[leftsquare - fn + 1] = '\0';
372  snprintf (fn,
373  PATH_MAX,
374  "%s%d%s",
375  logfile_copy,
376  getpid (),
377  &logfile_copy[leftsquare - fn + 2]);
378  GNUNET_free (logfile_copy);
379  }
380  if (0 == strcmp (fn, last_fn))
381  return GNUNET_OK; /* no change */
382  log_rotate (last_fn);
383  strcpy (last_fn, fn);
385  {
386  fprintf (stderr,
387  "Failed to create directory for `%s': %s\n",
388  fn,
389  strerror (errno));
390  return GNUNET_SYSERR;
391  }
392  altlog_fd = open (fn,
393  O_APPEND | O_WRONLY | O_CREAT,
394  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
395 
396  if (-1 != altlog_fd)
397  {
398  if (NULL != GNUNET_stderr)
399  fclose (GNUNET_stderr);
400  dup_return = dup2 (altlog_fd, 2);
401  (void) close (altlog_fd);
402  if (-1 != dup_return)
403  {
404  altlog = fdopen (2, "ab");
405  if (NULL == altlog)
406  {
407  (void) close (2);
408  altlog_fd = -1;
409  }
410  }
411  else
412  {
413  altlog_fd = -1;
414  }
415  }
416  if (-1 == altlog_fd)
417  {
419  return GNUNET_SYSERR;
420  }
421  GNUNET_stderr = altlog;
422  return GNUNET_OK;
423 }
424 
425 
438 static int
440  const char *file,
441  const char *function,
442  int from_line,
443  int to_line,
444  int level,
445  int force)
446 {
447  struct LogDef n;
448  int r;
449 
450  if (logdefs_size == logdefs_len)
451  resize_logdefs ();
452  memset (&n, 0, sizeof(n));
453  if (0 == strlen (component))
454  component = (char *) ".*";
455  r = regcomp (&n.component_regex, (const char *) component, REG_NOSUB);
456  if (0 != r)
457  {
458  return r;
459  }
460  if (0 == strlen (file))
461  file = (char *) ".*";
462  r = regcomp (&n.file_regex, (const char *) file, REG_NOSUB);
463  if (0 != r)
464  {
465  regfree (&n.component_regex);
466  return r;
467  }
468  if ((NULL == function) || (0 == strlen (function)))
469  function = (char *) ".*";
470  r = regcomp (&n.function_regex, (const char *) function, REG_NOSUB);
471  if (0 != r)
472  {
473  regfree (&n.component_regex);
474  regfree (&n.file_regex);
475  return r;
476  }
477  n.from_line = from_line;
478  n.to_line = to_line;
479  n.level = level;
480  n.force = force;
481  logdefs[logdefs_len++] = n;
482  return 0;
483 }
484 
485 
499 int
500 GNUNET_get_log_call_status (int caller_level,
501  const char *comp,
502  const char *file,
503  const char *function,
504  int line)
505 {
506  struct LogDef *ld;
507  int i;
508  int force_only;
509 
510  if (NULL == comp)
511  /* Use default component */
512  comp = component_nopid;
513 
514  /* We have no definitions to override globally configured log level,
515  * so just use it right away.
516  */
517  if ((min_level >= 0) && (GNUNET_NO == gnunet_force_log_present))
518  return caller_level <= min_level;
519 
520  /* Only look for forced definitions? */
521  force_only = min_level >= 0;
522  for (i = 0; i < logdefs_len; i++)
523  {
524  ld = &logdefs[i];
525  if (((! force_only) || ld->force) &&
526  ((line >= ld->from_line) && (line <= ld->to_line) ) &&
527  (0 == regexec (&ld->component_regex, comp, 0, NULL, 0)) &&
528  (0 == regexec (&ld->file_regex, file, 0, NULL, 0)) &&
529  (0 == regexec (&ld->function_regex, function, 0, NULL, 0)))
530  {
531  /* We're finished */
532  return caller_level <= ld->level;
533  }
534  }
535  /* No matches - use global level, if defined */
536  if (min_level >= 0)
537  return caller_level <= min_level;
538  /* All programs/services previously defaulted to WARNING.
539  * Now *we* default to WARNING, and THEY default to NULL.
540  * Or rather we default to MESSAGE, since things aren't always bad.
541  */
542  return caller_level <= GNUNET_ERROR_TYPE_MESSAGE;
543 }
544 
545 
569 static int
570 parse_definitions (const char *constname, int force)
571 {
572  char *def;
573  const char *tmp;
574  char *comp = NULL;
575  char *file = NULL;
576  char *function = NULL;
577  char *p;
578  char *start;
579  char *t;
580  short state;
581  int level;
582  int from_line, to_line;
583  int counter = 0;
584  int keep_looking = 1;
585 
586  tmp = getenv (constname);
587  if (NULL == tmp)
588  return 0;
589  def = GNUNET_strdup (tmp);
590  from_line = 0;
591  to_line = INT_MAX;
592  for (p = def, state = 0, start = def; keep_looking; p++)
593  {
594  switch (p[0])
595  {
596  case ';': /* found a field separator */
597  p[0] = '\0';
598  switch (state)
599  {
600  case 0: /* within a component name */
601  comp = start;
602  break;
603 
604  case 1: /* within a file name */
605  file = start;
606  break;
607 
608  case 2: /* within a function name */
609  /* after a file name there must be a function name */
610  function = start;
611  break;
612 
613  case 3: /* within a from-to line range */
614  if (strlen (start) > 0)
615  {
616  errno = 0;
617  from_line = strtol (start, &t, 10);
618  if ((0 != errno) || (from_line < 0))
619  {
620  GNUNET_free (def);
621  return counter;
622  }
623  if ((t < p) && ('-' == t[0]))
624  {
625  errno = 0;
626  start = t + 1;
627  to_line = strtol (start, &t, 10);
628  if ((0 != errno) || (to_line < 0) || (t != p))
629  {
630  GNUNET_free (def);
631  return counter;
632  }
633  }
634  else /* one number means "match this line only" */
635  to_line = from_line;
636  }
637  else /* default to 0-max */
638  {
639  from_line = 0;
640  to_line = INT_MAX;
641  }
642  break;
643 
644  default:
645  fprintf (
646  stderr,
647  _ ("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
648  p);
649  break;
650  }
651  start = p + 1;
652  state++;
653  break;
654 
655  case '\0': /* found EOL */
656  keep_looking = 0;
657 
658  /* fall through to '/' */
659  case '/': /* found a definition separator */
660  switch (state)
661  {
662  case 4: /* within a log level */
663  p[0] = '\0';
664  state = 0;
665  level = get_type ((const char *) start);
666  if ((GNUNET_ERROR_TYPE_INVALID == level) ||
668  (0 != add_definition (comp,
669  file,
670  function,
671  from_line,
672  to_line,
673  level,
674  force)))
675  {
676  GNUNET_free (def);
677  return counter;
678  }
679  counter++;
680  start = p + 1;
681  break;
682 
683  default:
684  fprintf (
685  stderr,
686  _ ("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
687  p);
688  break;
689  }
690 
691  default:
692  break;
693  }
694  }
695  GNUNET_free (def);
696  return counter;
697 }
698 
699 
703 static void
705 {
708  parse_definitions ("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO;
710 
712  parse_definitions ("GNUNET_LOG", 0);
714 }
715 
716 
717 #endif
718 
719 
728 int
729 GNUNET_log_setup (const char *comp,
730  const char *loglevel,
731  const char *logfile)
732 {
733  const char *env_logfile;
734 
735  min_level = get_type (loglevel);
736 #if ! defined(GNUNET_CULL_LOGGING)
738 #endif
740  GNUNET_asprintf (&component, "%s-%d", comp, getpid ());
743 
744  env_logfile = getenv ("GNUNET_FORCE_LOGFILE");
745  if ((NULL != env_logfile) && (strlen (env_logfile) > 0))
746  logfile = env_logfile;
747  if (NULL == logfile)
748  return GNUNET_OK;
751  if (NULL == log_file_name)
752  return GNUNET_SYSERR;
753 #if defined(GNUNET_CULL_LOGGING)
754  /* log file option not allowed for wallet logic */
755  GNUNET_assert (NULL == logfile);
756  return GNUNET_OK;
757 #else
758  {
759  time_t t;
760  const struct tm *tm;
761 
762  t = time (NULL);
763  tm = gmtime (&t);
764  return setup_log_file (tm);
765  }
766 #endif
767 }
768 
769 
770 void
772 {
773  struct CustomLogger *entry;
774 
775  entry = GNUNET_new (struct CustomLogger);
776  entry->logger = logger;
777  entry->logger_cls = logger_cls;
778  entry->next = loggers;
779  loggers = entry;
780 }
781 
782 
783 void
785 {
786  struct CustomLogger *pos;
787  struct CustomLogger *prev;
788 
789  prev = NULL;
790  pos = loggers;
791  while ((NULL != pos) &&
792  ((pos->logger != logger) || (pos->logger_cls != logger_cls)))
793  {
794  prev = pos;
795  pos = pos->next;
796  }
797  GNUNET_assert (NULL != pos);
798  if (NULL == prev)
799  loggers = pos->next;
800  else
801  prev->next = pos->next;
802  GNUNET_free (pos);
803 }
804 
805 
814 static void
816  const char *comp,
817  const char *datestr,
818  const char *msg)
819 {
820  struct CustomLogger *pos;
821 
822  /* only use the standard logger if no custom loggers are present */
823  if ((NULL != GNUNET_stderr) && (NULL == loggers))
824  {
825  if (kind == GNUNET_ERROR_TYPE_MESSAGE)
826  {
827  /* The idea here is to produce "normal" output messages
828  * for end users while still having the power of the
829  * logging engine for developer needs. So ideally this
830  * is what it should look like when CLI tools are used
831  * interactively, yet the same message shouldn't look
832  * this way if the output is going to logfiles or robots
833  * instead.
834  */fprintf (GNUNET_stderr, "* %s", msg);
835  }
837  {
838  static GNUNET_THREAD_LOCAL char id_buf[27];
839  char *end;
840 
841  /* We're logging, so skip_log must be currently 0. */
842  skip_log = 100;
844  sizeof(struct GNUNET_AsyncScopeId),
845  id_buf,
846  sizeof(id_buf) - 1);
847  GNUNET_assert (NULL != end);
848  *end = '\0';
849  skip_log = 0;
850  fprintf (GNUNET_stderr,
851  "%s %s(%s) %s %s",
852  datestr,
853  comp,
854  id_buf,
856  msg);
857  }
858  else
859  {
860  fprintf (GNUNET_stderr,
861  "%s %s %s %s",
862  datestr,
863  comp,
865  msg);
866  }
867  fflush (GNUNET_stderr);
868  }
869  pos = loggers;
870  while (NULL != pos)
871  {
872  pos->logger (pos->logger_cls, kind, comp, datestr, msg);
873  pos = pos->next;
874  }
875 }
876 
877 
883 static void
884 flush_bulk (const char *datestr)
885 {
886  char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];
887  int rev;
888  char *last;
889  const char *ft;
890 
891  if ((0 == last_bulk_time.abs_value_us) || (0 == last_bulk_repeat))
892  return;
893  rev = 0;
894  last = memchr (last_bulk, '\0', BULK_TRACK_SIZE);
895  if (last == NULL)
896  last = &last_bulk[BULK_TRACK_SIZE - 1];
897  else if (last != last_bulk)
898  last--;
899  if (last[0] == '\n')
900  {
901  rev = 1;
902  last[0] = '\0';
903  }
904  ft =
907  GNUNET_YES);
908  snprintf (msg,
909  sizeof(msg),
910  _ ("Message `%.*s' repeated %u times in the last %s\n"),
912  last_bulk,
914  ft);
915  if (rev == 1)
916  last[0] = '\n';
919  last_bulk_repeat = 0;
920 }
921 
922 
923 void
924 GNUNET_log_skip (int n, int check_reset)
925 {
926  int ok;
927 
928  if (0 == n)
929  {
930  ok = (0 == skip_log);
931  skip_log = 0;
932  if (check_reset)
933  GNUNET_break (ok);
934  }
935  else
936  {
937  skip_log += n;
938  }
939 }
940 
941 
947 int
949 {
950  return skip_log;
951 }
952 
953 
962 static void
964  const char *comp,
965  const char *message,
966  va_list va)
967 {
968  char date[DATE_STR_SIZE];
969  char date2[DATE_STR_SIZE];
970  struct tm *tmptr;
971  size_t size;
972  va_list vacp;
973 
974  va_copy (vacp, va);
975  size = vsnprintf (NULL, 0, message, vacp) + 1;
976  GNUNET_assert (0 != size);
977  va_end (vacp);
978  memset (date, 0, DATE_STR_SIZE);
979  {
980  char buf[size];
981  long long offset;
982 
983  struct timeval timeofday;
984 
985  gettimeofday (&timeofday, NULL);
986  offset = GNUNET_TIME_get_offset ();
987  if (offset > 0)
988  {
989  timeofday.tv_sec += offset / 1000LL;
990  timeofday.tv_usec += (offset % 1000LL) * 1000LL;
991  if (timeofday.tv_usec > 1000000LL)
992  {
993  timeofday.tv_usec -= 1000000LL;
994  timeofday.tv_sec++;
995  }
996  }
997  else
998  {
999  timeofday.tv_sec += offset / 1000LL;
1000  if (timeofday.tv_usec > -(offset % 1000LL) * 1000LL)
1001  {
1002  timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1003  }
1004  else
1005  {
1006  timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL;
1007  timeofday.tv_sec--;
1008  }
1009  }
1010  tmptr = localtime (&timeofday.tv_sec);
1011  if (NULL == tmptr)
1012  {
1013  strcpy (date, "localtime error");
1014  }
1015  else
1016  {
1017  /* RFC 3339 timestamp, with snprintf placeholder for microseconds */
1018  if (0 == strftime (date2, DATE_STR_SIZE, "%Y-%m-%dT%H:%M:%S.%%06u%z",
1019  tmptr))
1020  abort ();
1021  /* Fill in microseconds */
1022  if (0 > snprintf (date, sizeof(date), date2, timeofday.tv_usec))
1023  abort ();
1024  }
1025 
1026  vsnprintf (buf, size, message, va);
1027 #if ! defined(GNUNET_CULL_LOGGING)
1028  if (NULL != tmptr)
1029  (void) setup_log_file (tmptr);
1030 #endif
1031  if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) &&
1032  (0 != last_bulk_time.abs_value_us) &&
1033  (0 == strncmp (buf, last_bulk, sizeof(last_bulk))))
1034  {
1035  last_bulk_repeat++;
1039  flush_bulk (date);
1040  return;
1041  }
1042  flush_bulk (date);
1043  GNUNET_strlcpy (last_bulk, buf, sizeof(last_bulk));
1044  last_bulk_repeat = 0;
1045  last_bulk_kind = kind;
1047  GNUNET_strlcpy (last_bulk_comp, comp, sizeof(last_bulk_comp));
1048  output_message (kind, comp, date, buf);
1049  }
1050 }
1051 
1052 
1060 void
1061 GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...)
1062 {
1063  va_list va;
1064 
1065  va_start (va, message);
1066  mylog (kind, component, message, va);
1067  va_end (va);
1068 }
1069 
1070 
1080 void
1082  const char *comp,
1083  const char *message,
1084  ...)
1085 {
1086  va_list va;
1087  char comp_w_pid[128];
1088 
1089  if (comp == NULL)
1090  comp = component_nopid;
1091 
1092  va_start (va, message);
1093  GNUNET_snprintf (comp_w_pid, sizeof(comp_w_pid), "%s-%d", comp, getpid ());
1094  mylog (kind, comp_w_pid, message, va);
1095  va_end (va);
1096 }
1097 
1098 
1099 const char *
1101 {
1102  if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0)
1103  return _ ("ERROR");
1104  if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0)
1105  return _ ("WARNING");
1106  if ((kind & GNUNET_ERROR_TYPE_MESSAGE) > 0)
1107  return _ ("MESSAGE");
1108  if ((kind & GNUNET_ERROR_TYPE_INFO) > 0)
1109  return _ ("INFO");
1110  if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0)
1111  return _ ("DEBUG");
1112  if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0)
1113  return _ ("NONE");
1114  return _ ("INVALID");
1115 }
1116 
1117 
1124 const char *
1125 GNUNET_h2s (const struct GNUNET_HashCode *hc)
1126 {
1128 
1130  ret.encoding[8] = '\0';
1131  return (const char *) ret.encoding;
1132 }
1133 
1134 
1145 const char *
1146 GNUNET_h2s2 (const struct GNUNET_HashCode *hc)
1147 {
1149 
1151  ret.encoding[8] = '\0';
1152  return (const char *) ret.encoding;
1153 }
1154 
1155 
1156 const char *
1158 {
1160  struct GNUNET_HashCode hc;
1161 
1162  GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1164  ret.encoding[6] = '\0';
1165  return (const char *) ret.encoding;
1166 }
1167 
1168 
1169 const char *
1171 {
1173  struct GNUNET_HashCode hc;
1174 
1175  GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1177  ret.encoding[6] = '\0';
1178  return (const char *) ret.encoding;
1179 }
1180 
1181 
1182 const char *
1184 {
1186  struct GNUNET_HashCode hc;
1187 
1188  GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1190  ret.encoding[6] = '\0';
1191  return (const char *) ret.encoding;
1192 }
1193 
1194 
1195 const char *
1197 {
1199  struct GNUNET_HashCode hc;
1200 
1201  GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1203  ret.encoding[6] = '\0';
1204  return (const char *) ret.encoding;
1205 }
1206 
1207 
1217 const char *
1219 {
1220  static GNUNET_THREAD_LOCAL char buf[64];
1221 
1222  GNUNET_STRINGS_data_to_string (shc, sizeof(*shc), buf, sizeof(buf));
1223  buf[6] = '\0';
1224  return (const char *) buf;
1225 }
1226 
1227 
1237 const char *
1238 GNUNET_uuid2s (const struct GNUNET_Uuid *uuid)
1239 {
1240  static GNUNET_THREAD_LOCAL char buf[32];
1241 
1242  GNUNET_STRINGS_data_to_string (uuid, sizeof(*uuid), buf, sizeof(buf));
1243  buf[6] = '\0';
1244  return (const char *) buf;
1245 }
1246 
1247 
1256 const char *
1258 {
1260 
1262  ret.encoding[sizeof(ret) - 1] = '\0';
1263  return (const char *) ret.encoding;
1264 }
1265 
1266 
1274 const char *
1276 {
1277  static GNUNET_THREAD_LOCAL char buf[5];
1278  char *ret;
1279 
1280  if (NULL == pid)
1281  return "NULL";
1283  GNUNET_strlcpy (buf, ret, sizeof(buf));
1284  GNUNET_free (ret);
1285  return buf;
1286 }
1287 
1288 
1299 const char *
1301 {
1302  static GNUNET_THREAD_LOCAL char buf[5];
1303  char *ret;
1304 
1305  if (NULL == pid)
1306  return "NULL";
1308  GNUNET_strlcpy (buf, ret, sizeof(buf));
1309  GNUNET_free (ret);
1310  return buf;
1311 }
1312 
1313 
1321 const char *
1323 {
1324  static GNUNET_THREAD_LOCAL char buf[256];
1325  char *ret;
1326 
1328  strcpy (buf, ret);
1329  GNUNET_free (ret);
1330  return buf;
1331 }
1332 
1333 
1344 const char *
1345 GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen)
1346 {
1347 #define LEN \
1348  GNUNET_MAX ((INET6_ADDRSTRLEN + 8), \
1349  (1 + sizeof(struct sockaddr_un) - sizeof(sa_family_t)))
1350  static GNUNET_THREAD_LOCAL char buf[LEN];
1351 #undef LEN
1352  static GNUNET_THREAD_LOCAL char b2[6];
1353  const struct sockaddr_in *v4;
1354  const struct sockaddr_un *un;
1355  const struct sockaddr_in6 *v6;
1356  unsigned int off;
1357 
1358  if (addr == NULL)
1359  return _ ("unknown address");
1360  switch (addr->sa_family)
1361  {
1362  case AF_INET:
1363  if (addrlen != sizeof(struct sockaddr_in))
1364  return "<invalid v4 address>";
1365  v4 = (const struct sockaddr_in *) addr;
1366  inet_ntop (AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN);
1367  if (0 == ntohs (v4->sin_port))
1368  return buf;
1369  strcat (buf, ":");
1370  GNUNET_snprintf (b2, sizeof(b2), "%u", ntohs (v4->sin_port));
1371  strcat (buf, b2);
1372  return buf;
1373 
1374  case AF_INET6:
1375  if (addrlen != sizeof(struct sockaddr_in6))
1376  return "<invalid v6 address>";
1377  v6 = (const struct sockaddr_in6 *) addr;
1378  buf[0] = '[';
1379  inet_ntop (AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN);
1380  if (0 == ntohs (v6->sin6_port))
1381  return &buf[1];
1382  strcat (buf, "]:");
1383  GNUNET_snprintf (b2, sizeof(b2), "%u", ntohs (v6->sin6_port));
1384  strcat (buf, b2);
1385  return buf;
1386 
1387  case AF_UNIX:
1388  if (addrlen <= sizeof(sa_family_t))
1389  return "<unbound UNIX client>";
1390  un = (const struct sockaddr_un *) addr;
1391  off = 0;
1392  if ('\0' == un->sun_path[0])
1393  off++;
1394  memset (buf, 0, sizeof(buf));
1396  sizeof(buf),
1397  "%s%.*s",
1398  (1 == off) ? "@" : "",
1399  (int) (addrlen - sizeof(sa_family_t) - off),
1400  &un->sun_path[off]);
1401  return buf;
1402 
1403  default:
1404  return _ ("invalid address");
1405  }
1406 }
1407 
1408 
1409 void
1411  const char *section,
1412  const char *option)
1413 {
1414  GNUNET_log (kind,
1415  _ (
1416  "Configuration fails to specify option `%s' in section `%s'!\n"),
1417  option,
1418  section);
1419 }
1420 
1421 
1422 void
1424  const char *section,
1425  const char *option,
1426  const char *required)
1427 {
1428  GNUNET_log (
1429  kind,
1430  _ (
1431  "Configuration specifies invalid value for option `%s' in section `%s': %s\n"),
1432  option,
1433  section,
1434  required);
1435 }
1436 
1437 
1444 void
1446  struct GNUNET_AsyncScopeSave *old_scope)
1447 {
1448  *old_scope = current_async_scope;
1451 }
1452 
1453 
1459 void
1461 {
1462  current_async_scope = *old_scope;
1463 }
1464 
1465 
1471 void
1473 {
1475  aid_ret,
1476  sizeof(struct GNUNET_AsyncScopeId));
1477 }
1478 
1479 
1485 void
1487 {
1488  *scope_ret = current_async_scope;
1489 }
1490 
1491 
1495 void __attribute__ ((constructor))
1496 GNUNET_util_cl_init ()
1497 {
1498  GNUNET_stderr = stderr;
1499 }
1500 
1501 
1505 void __attribute__ ((destructor))
1506 GNUNET_util_cl_fini ()
1507 {
1508 
1509 }
1510 
1511 
1512 /* end of common_logging.c */
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
#define INT_MAX
static int gnunet_force_log_present
GNUNET_YES if at least one definition with forced == 1 is available.
#define LEN
static void log_rotate(const char *new_name)
Rotate logs, deleting the oldest log.
static GNUNET_THREAD_LOCAL struct GNUNET_TIME_Absolute last_bulk_time
Time of the last bulk error message (0 for none)
static GNUNET_THREAD_LOCAL char last_bulk_comp[32+1]
Component when the last bulk was logged.
static void parse_all_definitions()
Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG.
static int add_definition(const char *component, const char *file, const char *function, int from_line, int to_line, int level, int force)
Utility function - adds a parsed definition to logdefs array.
static int logdefs_len
The number of units used in logdefs array.
#define BULK_DELAY_THRESHOLD
After how many milliseconds do we always print that "message X was repeated N times"?...
static int logdefs_size
Allocated size of logdefs array (in units)
void GNUNET_log_nocheck(enum GNUNET_ErrorType kind, const char *message,...)
Main log function.
static struct LogDef * logdefs
Dynamic array of logging definitions.
static int parse_definitions(const char *constname, int force)
Utility function - parses a definition.
static void mylog(enum GNUNET_ErrorType kind, const char *comp, const char *message, va_list va)
Output a log message using the default mechanism.
static int gnunet_force_log_parsed
GNUNET_YES if GNUNET_FORCE_LOG environment variable is already parsed.
static GNUNET_THREAD_LOCAL enum GNUNET_ErrorType last_bulk_kind
Type of the last bulk message.
#define BULK_REPEAT_THRESHOLD
After how many repetitions do we always print that "message X was repeated N times"?...
static void output_message(enum GNUNET_ErrorType kind, const char *comp, const char *datestr, const char *msg)
Actually output the log message.
static char * log_file_name
Format string describing the name of the log file.
static GNUNET_THREAD_LOCAL unsigned int last_bulk_repeat
Number of times that bulk message has been repeated since.
static char * component_nopid
Running component (without pid).
static FILE * GNUNET_stderr
File descriptor to use for "stderr", or NULL for none.
static int gnunet_log_parsed
GNUNET_YES if GNUNET_LOG environment variable is already parsed.
void GNUNET_log_from_nocheck(enum GNUNET_ErrorType kind, const char *comp, const char *message,...)
Log function that specifies an alternative component.
static enum GNUNET_ErrorType get_type(const char *log)
Convert a textual description of a loglevel to the respective enumeration type.
static GNUNET_THREAD_LOCAL char last_bulk[256] __nonstring
The last "bulk" error message that we have been logging.
#define COMP_TRACK_SIZE
How many characters do we use for matching of bulk components?
static GNUNET_THREAD_LOCAL int skip_log
Number of log calls to ignore.
#define DATE_STR_SIZE
How many characters can a date/time string be at most?
static char * component
Running component.
#define BULK_TRACK_SIZE
How many characters do we use for matching of bulk messages?
static struct CustomLogger * loggers
Linked list of our custom loggres.
#define PATH_MAX
Assumed maximum path length (for the log file name).
static enum GNUNET_ErrorType min_level
Minimum log level.
#define ROTATION_KEEP
How many log files to keep?
static int setup_log_file(const struct tm *tm)
Setup the log file.
static void flush_bulk(const char *datestr)
Flush an existing bulk report to the output.
static GNUNET_THREAD_LOCAL struct GNUNET_AsyncScopeSave current_async_scope
Asynchronous scope of the current thread, or NULL if we have not entered an async scope yet.
static void resize_logdefs(void)
Utility function - reallocates logdefs array to be twice as large.
void __attribute__((constructor))
Initializer.
char * getenv()
static int ret
Return value of the commandline.
Definition: gnunet-abd.c:81
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
static char * line
Desired phone line (string to be converted to a hash).
static int ok
Return value from 'main' (0 == success)
enum State state
current state of profiling
static char buf[2048]
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-uri.c:38
static struct GNUNET_SCHEDULER_Task * t
Main task.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
@ GNUNET_CRYPTO_QUALITY_WEAK
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
enum GNUNET_GenericReturnValue GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:582
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:41
void GNUNET_CRYPTO_hash_to_enc(const struct GNUNET_HashCode *block, struct GNUNET_CRYPTO_HashAsciiEncoded *result)
Convert hash to ASCII encoding.
Definition: crypto_hash.c:55
const char * GNUNET_b2s(const void *buf, size_t buf_size)
Convert a buffer to an 8-character string representative of the contents.
#define GNUNET_log(kind,...)
int GNUNET_get_log_call_status(int caller_level, const char *comp, const char *file, const char *function, int line)
Decides whether a particular logging call should or should not be allowed to be made.
char * GNUNET_CRYPTO_eddsa_public_key_to_string(const struct GNUNET_CRYPTO_EddsaPublicKey *pub)
Convert a public key to a string.
Definition: crypto_ecc.c:251
void GNUNET_async_scope_enter(const struct GNUNET_AsyncScopeId *aid, struct GNUNET_AsyncScopeSave *old_scope)
Set the async scope for the current thread.
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
void GNUNET_async_scope_fresh(struct GNUNET_AsyncScopeId *aid_ret)
Generate a fresh async scope identifier.
void GNUNET_async_scope_restore(struct GNUNET_AsyncScopeSave *old_scope)
Clear the current thread's async scope.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
const char * GNUNET_h2s2(const struct GNUNET_HashCode *hc)
Convert a hash to a string (for printing debug messages).
GNUNET_ErrorType
Types of errors.
const char * GNUNET_p2s2(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
int GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_error_type_to_string(enum GNUNET_ErrorType kind)
Convert error type to string.
int GNUNET_get_log_skip()
Get the number of log calls that are going to be skipped.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
Convert a hash to a string (for printing debug messages).
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur.
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
const char * GNUNET_e2s2(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
void GNUNET_log_skip(int n, int check_reset)
Ignore the next n calls to the log function.
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash to a string (for printing debug messages).
void GNUNET_log_config_invalid(enum GNUNET_ErrorType kind, const char *section, const char *option, const char *required)
Log error message about invalid configuration option value.
void GNUNET_log_config_missing(enum GNUNET_ErrorType kind, const char *section, const char *option)
Log error message about missing configuration option.
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
Convert a "struct sockaddr*" (IPv4 or IPv6 address) to a string (for printing debug messages).
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level 'level' that indicates a failure of the command 'cmd' with the mess...
void GNUNET_abort_()
Abort the process, generate a core dump if possible.
void GNUNET_logger_add(GNUNET_Logger logger, void *logger_cls)
Add a custom logger.
void(* GNUNET_Logger)(void *cls, enum GNUNET_ErrorType kind, const char *component, const char *date, const char *message)
User-defined handler for log messages.
void GNUNET_logger_remove(GNUNET_Logger logger, void *logger_cls)
Remove a custom logger.
@ GNUNET_ERROR_TYPE_UNSPECIFIED
@ GNUNET_ERROR_TYPE_WARNING
@ GNUNET_ERROR_TYPE_ERROR
@ GNUNET_ERROR_TYPE_BULK
@ GNUNET_ERROR_TYPE_NONE
@ GNUNET_ERROR_TYPE_INVALID
@ GNUNET_ERROR_TYPE_MESSAGE
@ GNUNET_ERROR_TYPE_DEBUG
@ GNUNET_ERROR_TYPE_INFO
int int GNUNET_asprintf(char **buf, const char *format,...) __attribute__((format(printf
Like asprintf, just portable.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
int GNUNET_snprintf(char *buf, size_t size, const char *format,...) __attribute__((format(printf
Like snprintf, just aborts if the buffer is of insufficient size.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
#define GNUNET_free(ptr)
Wrapper around free.
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:494
char * GNUNET_STRINGS_data_to_string(const void *data, size_t size, char *out, size_t out_size)
Convert binary data to ASCII encoding using CrockfordBase32.
Definition: strings.c:708
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:763
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:138
struct GNUNET_TIME_Relative GNUNET_TIME_absolute_get_duration(struct GNUNET_TIME_Absolute whence)
Get the duration of an operation as the difference of the current time and the given start time "henc...
Definition: time.c:436
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:111
long long GNUNET_TIME_get_offset(void)
Get the timestamp offset for this instance.
Definition: time.c:56
const char * GNUNET_STRINGS_relative_time_to_string(struct GNUNET_TIME_Relative delta, int do_round)
Give relative time in human-readable fancy format.
Definition: strings.c:569
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:177
#define GNUNET_THREAD_LOCAL
Definition: platform.h:246
Linked list of active loggers.
void * logger_cls
Closure for logger.
struct CustomLogger * next
This is a linked list.
GNUNET_Logger logger
Log function.
Identifier for an asynchronous execution context.
Saved async scope identifier or root scope.
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
struct GNUNET_AsyncScopeId scope_id
Saved scope.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...
0-terminated ASCII encoding of a struct GNUNET_HashCode.
A 512-bit hashcode.
The identity of the host (wraps the signing key of the peer).
struct GNUNET_CRYPTO_EddsaPublicKey public_key
A 256-bit hashcode.
Time for absolute times used by GNUnet, in microseconds.
uint64_t abs_value_us
The actual value.
uint64_t rel_value_us
The actual value.
A UUID, a 128 bit "random" value.
Represents a single logging definition.
int to_line
Highest line at which this definition matches.
int from_line
Lowest line at which this definition matches.
int force
1 if this definition comes from GNUNET_FORCE_LOG, which means that it overrides any configuration opt...
regex_t file_regex
File name regex.
regex_t function_regex
Function name regex.
int level
Maximal log level allowed for calls that match this definition.
regex_t component_regex
Component name regex.