GNUnet  0.10.x
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 
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 
37 #define BULK_DELAY_THRESHOLD (12 * 60 * 60 * 1000LL * 1000LL)
38 
44 #define BULK_REPEAT_THRESHOLD 1000
45 
50 #define BULK_TRACK_SIZE 256
51 
56 #define COMP_TRACK_SIZE 32
57 
62 #define DATE_STR_SIZE 64
63 
67 #define ROTATION_KEEP 3
68 
69 #ifndef PATH_MAX
70 
73 #define PATH_MAX 4096
74 #endif
75 
76 
80 struct CustomLogger {
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 
150 
154 static struct CustomLogger *loggers;
155 
160 
164 static FILE *GNUNET_stderr;
165 
169 struct LogDef {
174 
178  regex_t file_regex;
179 
183  regex_t function_regex;
184 
190 
195  int to_line;
196 
202  int level;
203 
208  int force;
209 };
210 
211 
212 #if !defined(GNUNET_CULL_LOGGING)
213 
216 static struct LogDef *logdefs;
217 
221 static int logdefs_size;
222 
226 static int logdefs_len;
227 
231 static int gnunet_log_parsed;
232 
237 
242 #endif
243 
244 
252 static enum GNUNET_ErrorType
253 get_type(const char *log)
254 {
255  if (NULL == log)
257  if (0 == strcasecmp(log, _("DEBUG")))
259  if (0 == strcasecmp(log, _("INFO")))
260  return GNUNET_ERROR_TYPE_INFO;
261  if (0 == strcasecmp(log, _("MESSAGE")))
263  if (0 == strcasecmp(log, _("WARNING")))
265  if (0 == strcasecmp(log, _("ERROR")))
267  if (0 == strcasecmp(log, _("NONE")))
268  return GNUNET_ERROR_TYPE_NONE;
270 }
271 
272 
276 void
278 {
279  abort();
280 }
281 
282 
283 #if !defined(GNUNET_CULL_LOGGING)
284 
287 static void
289 {
290  logdefs_size = (logdefs_size + 1) * 2;
291  logdefs = GNUNET_realloc(logdefs, logdefs_size * sizeof(struct LogDef));
292 }
293 
294 
295 #if !TALER_WALLET_ONLY
296 
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 
329 static int
330 setup_log_file(const struct tm *tm)
331 {
332  static char last_fn[PATH_MAX + 1];
333  char fn[PATH_MAX + 1];
334  int altlog_fd;
335  int dup_return;
336  FILE *altlog;
337  char *leftsquare;
338 
339  if (NULL == log_file_name)
340  return GNUNET_SYSERR;
341  if (0 == strftime(fn, sizeof(fn), log_file_name, tm))
342  return GNUNET_SYSERR;
343  leftsquare = strrchr(fn, '[');
344  if ((NULL != leftsquare) && (']' == leftsquare[1]))
345  {
346  char *logfile_copy = GNUNET_strdup(fn);
347 
348  logfile_copy[leftsquare - fn] = '\0';
349  logfile_copy[leftsquare - fn + 1] = '\0';
350  snprintf(fn,
351  PATH_MAX,
352  "%s%d%s",
353  logfile_copy,
354  getpid(),
355  &logfile_copy[leftsquare - fn + 2]);
356  GNUNET_free(logfile_copy);
357  }
358  if (0 == strcmp(fn, last_fn))
359  return GNUNET_OK; /* no change */
360  log_rotate(last_fn);
361  strcpy(last_fn, fn);
363  {
364  fprintf(stderr,
365  "Failed to create directory for `%s': %s\n",
366  fn,
367  strerror(errno));
368  return GNUNET_SYSERR;
369  }
370  altlog_fd = open(fn,
371  O_APPEND | O_WRONLY | O_CREAT,
372  S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH);
373 
374  if (-1 != altlog_fd)
375  {
376  if (NULL != GNUNET_stderr)
377  fclose(GNUNET_stderr);
378  dup_return = dup2(altlog_fd, 2);
379  (void)close(altlog_fd);
380  if (-1 != dup_return)
381  {
382  altlog = fdopen(2, "ab");
383  if (NULL == altlog)
384  {
385  (void)close(2);
386  altlog_fd = -1;
387  }
388  }
389  else
390  {
391  altlog_fd = -1;
392  }
393  }
394  if (-1 == altlog_fd)
395  {
397  return GNUNET_SYSERR;
398  }
399  GNUNET_stderr = altlog;
400  return GNUNET_OK;
401 }
402 #endif
403 
404 
417 static int
419  const char *file,
420  const char *function,
421  int from_line,
422  int to_line,
423  int level,
424  int force)
425 {
426  struct LogDef n;
427  int r;
428 
429  if (logdefs_size == logdefs_len)
430  resize_logdefs();
431  memset(&n, 0, sizeof(n));
432  if (0 == strlen(component))
433  component = (char *)".*";
434  r = regcomp(&n.component_regex, (const char *)component, REG_NOSUB);
435  if (0 != r)
436  {
437  return r;
438  }
439  if (0 == strlen(file))
440  file = (char *)".*";
441  r = regcomp(&n.file_regex, (const char *)file, REG_NOSUB);
442  if (0 != r)
443  {
444  regfree(&n.component_regex);
445  return r;
446  }
447  if ((NULL == function) || (0 == strlen(function)))
448  function = (char *)".*";
449  r = regcomp(&n.function_regex, (const char *)function, REG_NOSUB);
450  if (0 != r)
451  {
452  regfree(&n.component_regex);
453  regfree(&n.file_regex);
454  return r;
455  }
456  n.from_line = from_line;
457  n.to_line = to_line;
458  n.level = level;
459  n.force = force;
460  logdefs[logdefs_len++] = n;
461  return 0;
462 }
463 
464 
478 int
479 GNUNET_get_log_call_status(int caller_level,
480  const char *comp,
481  const char *file,
482  const char *function,
483  int line)
484 {
485  struct LogDef *ld;
486  int i;
487  int force_only;
488 
489  if (NULL == comp)
490  /* Use default component */
491  comp = component_nopid;
492 
493  /* We have no definitions to override globally configured log level,
494  * so just use it right away.
495  */
496  if ((min_level >= 0) && (GNUNET_NO == gnunet_force_log_present))
497  return caller_level <= min_level;
498 
499  /* Only look for forced definitions? */
500  force_only = min_level >= 0;
501  for (i = 0; i < logdefs_len; i++)
502  {
503  ld = &logdefs[i];
504  if (((!force_only) || ld->force) &&
505  (line >= ld->from_line && line <= ld->to_line) &&
506  (0 == regexec(&ld->component_regex, comp, 0, NULL, 0)) &&
507  (0 == regexec(&ld->file_regex, file, 0, NULL, 0)) &&
508  (0 == regexec(&ld->function_regex, function, 0, NULL, 0)))
509  {
510  /* We're finished */
511  return caller_level <= ld->level;
512  }
513  }
514  /* No matches - use global level, if defined */
515  if (min_level >= 0)
516  return caller_level <= min_level;
517  /* All programs/services previously defaulted to WARNING.
518  * Now *we* default to WARNING, and THEY default to NULL.
519  * Or rather we default to MESSAGE, since things aren't always bad.
520  */
521  return caller_level <= GNUNET_ERROR_TYPE_MESSAGE;
522 }
523 
524 
548 static int
549 parse_definitions(const char *constname, int force)
550 {
551  char *def;
552  const char *tmp;
553  char *comp = NULL;
554  char *file = NULL;
555  char *function = NULL;
556  char *p;
557  char *start;
558  char *t;
559  short state;
560  int level;
561  int from_line, to_line;
562  int counter = 0;
563  int keep_looking = 1;
564 
565  tmp = getenv(constname);
566  if (NULL == tmp)
567  return 0;
568  def = GNUNET_strdup(tmp);
569  from_line = 0;
570  to_line = INT_MAX;
571  for (p = def, state = 0, start = def; keep_looking; p++)
572  {
573  switch (p[0])
574  {
575  case ';': /* found a field separator */
576  p[0] = '\0';
577  switch (state)
578  {
579  case 0: /* within a component name */
580  comp = start;
581  break;
582 
583  case 1: /* within a file name */
584  file = start;
585  break;
586 
587  case 2: /* within a function name */
588  /* after a file name there must be a function name */
589  function = start;
590  break;
591 
592  case 3: /* within a from-to line range */
593  if (strlen(start) > 0)
594  {
595  errno = 0;
596  from_line = strtol(start, &t, 10);
597  if ((0 != errno) || (from_line < 0))
598  {
599  GNUNET_free(def);
600  return counter;
601  }
602  if ((t < p) && ('-' == t[0]))
603  {
604  errno = 0;
605  start = t + 1;
606  to_line = strtol(start, &t, 10);
607  if ((0 != errno) || (to_line < 0) || (t != p))
608  {
609  GNUNET_free(def);
610  return counter;
611  }
612  }
613  else /* one number means "match this line only" */
614  to_line = from_line;
615  }
616  else /* default to 0-max */
617  {
618  from_line = 0;
619  to_line = INT_MAX;
620  }
621  break;
622 
623  default:
624  fprintf(
625  stderr,
626  _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
627  p);
628  break;
629  }
630  start = p + 1;
631  state++;
632  break;
633 
634  case '\0': /* found EOL */
635  keep_looking = 0;
636 
637  /* fall through to '/' */
638  case '/': /* found a definition separator */
639  switch (state)
640  {
641  case 4: /* within a log level */
642  p[0] = '\0';
643  state = 0;
644  level = get_type((const char *)start);
645  if ((GNUNET_ERROR_TYPE_INVALID == level) ||
646  (GNUNET_ERROR_TYPE_UNSPECIFIED == level) ||
647  (0 != add_definition(comp,
648  file,
649  function,
650  from_line,
651  to_line,
652  level,
653  force)))
654  {
655  GNUNET_free(def);
656  return counter;
657  }
658  counter++;
659  start = p + 1;
660  break;
661 
662  default:
663  fprintf(
664  stderr,
665  _("ERROR: Unable to parse log definition: Syntax error at `%s'.\n"),
666  p);
667  break;
668  }
669 
670  default:
671  break;
672  }
673  }
674  GNUNET_free(def);
675  return counter;
676 }
677 
678 
682 static void
684 {
687  parse_definitions("GNUNET_FORCE_LOG", 1) > 0 ? GNUNET_YES : GNUNET_NO;
689 
691  parse_definitions("GNUNET_LOG", 0);
693 }
694 #endif
695 
696 
705 int
706 GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
707 {
708  const char *env_logfile;
709 
710  min_level = get_type(loglevel);
711 #if !defined(GNUNET_CULL_LOGGING)
713 #endif
715  GNUNET_asprintf(&component, "%s-%d", comp, getpid());
718 
719  env_logfile = getenv("GNUNET_FORCE_LOGFILE");
720  if ((NULL != env_logfile) && (strlen(env_logfile) > 0))
721  logfile = env_logfile;
722  if (NULL == logfile)
723  return GNUNET_OK;
726  if (NULL == log_file_name)
727  return GNUNET_SYSERR;
728 #if TALER_WALLET_ONLY || defined(GNUNET_CULL_LOGGING)
729  /* log file option not allowed for wallet logic */
730  GNUNET_assert(NULL == logfile);
731  return GNUNET_OK;
732 #else
733  {
734  time_t t;
735  const struct tm *tm;
736 
737  t = time(NULL);
738  tm = gmtime(&t);
739  return setup_log_file(tm);
740  }
741 #endif
742 }
743 
744 
754 void
756 {
757  struct CustomLogger *entry;
758 
759  entry = GNUNET_new(struct CustomLogger);
760  entry->logger = logger;
761  entry->logger_cls = logger_cls;
762  entry->next = loggers;
763  loggers = entry;
764 }
765 
766 
773 void
775 {
776  struct CustomLogger *pos;
777  struct CustomLogger *prev;
778 
779  prev = NULL;
780  pos = loggers;
781  while ((NULL != pos) &&
782  ((pos->logger != logger) || (pos->logger_cls != logger_cls)))
783  {
784  prev = pos;
785  pos = pos->next;
786  }
787  GNUNET_assert(NULL != pos);
788  if (NULL == prev)
789  loggers = pos->next;
790  else
791  prev->next = pos->next;
792  GNUNET_free(pos);
793 }
794 
795 
804 static void
806  const char *comp,
807  const char *datestr,
808  const char *msg)
809 {
810  struct CustomLogger *pos;
811 
812  /* only use the standard logger if no custom loggers are present */
813  if ((NULL != GNUNET_stderr) && (NULL == loggers))
814  {
815  if (kind == GNUNET_ERROR_TYPE_MESSAGE)
816  {
817  /* The idea here is to produce "normal" output messages
818  * for end users while still having the power of the
819  * logging engine for developer needs. So ideally this
820  * is what it should look like when CLI tools are used
821  * interactively, yet the same message shouldn't look
822  * this way if the output is going to logfiles or robots
823  * instead.
824  */
825  fprintf(GNUNET_stderr, "* %s", msg);
826  }
828  {
829  static GNUNET_THREAD_LOCAL char id_buf[27];
830  char *end;
831 
832  /* We're logging, so skip_log must be currently 0. */
833  skip_log = 100;
835  sizeof(struct GNUNET_AsyncScopeId),
836  id_buf,
837  sizeof(id_buf) - 1);
838  GNUNET_assert(NULL != end);
839  *end = '\0';
840  skip_log = 0;
841  fprintf(GNUNET_stderr,
842  "%s %s(%s) %s %s",
843  datestr,
844  comp,
845  id_buf,
847  msg);
848  }
849  else
850  {
851  fprintf(GNUNET_stderr,
852  "%s %s %s %s",
853  datestr,
854  comp,
856  msg);
857  }
858  fflush(GNUNET_stderr);
859  }
860  pos = loggers;
861  while (NULL != pos)
862  {
863  pos->logger(pos->logger_cls, kind, comp, datestr, msg);
864  pos = pos->next;
865  }
866 }
867 
868 
874 static void
875 flush_bulk(const char *datestr)
876 {
877  char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];
878  int rev;
879  char *last;
880  const char *ft;
881 
882  if ((0 == last_bulk_time.abs_value_us) || (0 == last_bulk_repeat))
883  return;
884  rev = 0;
885  last = memchr(last_bulk, '\0', BULK_TRACK_SIZE);
886  if (last == NULL)
887  last = &last_bulk[BULK_TRACK_SIZE - 1];
888  else if (last != last_bulk)
889  last--;
890  if (last[0] == '\n')
891  {
892  rev = 1;
893  last[0] = '\0';
894  }
895  ft =
898  GNUNET_YES);
899  snprintf(msg,
900  sizeof(msg),
901  _("Message `%.*s' repeated %u times in the last %s\n"),
903  last_bulk,
905  ft);
906  if (rev == 1)
907  last[0] = '\n';
910  last_bulk_repeat = 0;
911 }
912 
913 
920 void
921 GNUNET_log_skip(int n, int check_reset)
922 {
923  int ok;
924 
925  if (0 == n)
926  {
927  ok = (0 == skip_log);
928  skip_log = 0;
929  if (check_reset)
930  GNUNET_break(ok);
931  }
932  else
933  {
934  skip_log += n;
935  }
936 }
937 
938 
944 int
946 {
947  return skip_log;
948 }
949 
950 
959 static void
961  const char *comp,
962  const char *message,
963  va_list va)
964 {
965  char date[DATE_STR_SIZE];
966  char date2[DATE_STR_SIZE];
967  struct tm *tmptr;
968  size_t size;
969  va_list vacp;
970 
971  va_copy(vacp, va);
972  size = vsnprintf(NULL, 0, message, vacp) + 1;
973  GNUNET_assert(0 != size);
974  va_end(vacp);
975  memset(date, 0, DATE_STR_SIZE);
976  {
977  char buf[size];
978  long long offset;
979 
980  struct timeval timeofday;
981 
982  gettimeofday(&timeofday, NULL);
983  offset = GNUNET_TIME_get_offset();
984  if (offset > 0)
985  {
986  timeofday.tv_sec += offset / 1000LL;
987  timeofday.tv_usec += (offset % 1000LL) * 1000LL;
988  if (timeofday.tv_usec > 1000000LL)
989  {
990  timeofday.tv_usec -= 1000000LL;
991  timeofday.tv_sec++;
992  }
993  }
994  else
995  {
996  timeofday.tv_sec += offset / 1000LL;
997  if (timeofday.tv_usec > -(offset % 1000LL) * 1000LL)
998  {
999  timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1000  }
1001  else
1002  {
1003  timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL;
1004  timeofday.tv_sec--;
1005  }
1006  }
1007  tmptr = localtime(&timeofday.tv_sec);
1008  if (NULL == tmptr)
1009  {
1010  strcpy(date, "localtime error");
1011  }
1012  else
1013  {
1014  if (0 == strftime(date2, DATE_STR_SIZE, "%b %d %H:%M:%S-%%06u", tmptr))
1015  abort();
1016  if (0 > snprintf(date, sizeof(date), date2, timeofday.tv_usec))
1017  abort();
1018  }
1019 
1020  vsnprintf(buf, size, message, va);
1021 #if !(defined(GNUNET_CULL_LOGGING) || TALER_WALLET_ONLY)
1022  if (NULL != tmptr)
1023  (void)setup_log_file(tmptr);
1024 #endif
1025  if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) &&
1026  (0 != last_bulk_time.abs_value_us) &&
1027  (0 == strncmp(buf, last_bulk, sizeof(last_bulk))))
1028  {
1029  last_bulk_repeat++;
1033  flush_bulk(date);
1034  return;
1035  }
1036  flush_bulk(date);
1037  GNUNET_strlcpy(last_bulk, buf, sizeof(last_bulk));
1038  last_bulk_repeat = 0;
1039  last_bulk_kind = kind;
1042  output_message(kind, comp, date, buf);
1043  }
1044 }
1045 
1046 
1054 void
1055 GNUNET_log_nocheck(enum GNUNET_ErrorType kind, const char *message, ...)
1056 {
1057  va_list va;
1058 
1059  va_start(va, message);
1060  mylog(kind, component, message, va);
1061  va_end(va);
1062 }
1063 
1064 
1074 void
1076  const char *comp,
1077  const char *message,
1078  ...)
1079 {
1080  va_list va;
1081  char comp_w_pid[128];
1082 
1083  if (comp == NULL)
1084  comp = component_nopid;
1085 
1086  va_start(va, message);
1087  GNUNET_snprintf(comp_w_pid, sizeof(comp_w_pid), "%s-%d", comp, getpid());
1088  mylog(kind, comp_w_pid, message, va);
1089  va_end(va);
1090 }
1091 
1092 
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 
1129  GNUNET_CRYPTO_hash_to_enc(hc, &ret);
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 {
1148  static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1149 
1150  GNUNET_CRYPTO_hash_to_enc(hc, &ret);
1151  ret.encoding[8] = '\0';
1152  return (const char *)ret.encoding;
1153 }
1154 
1155 
1165 const char *
1167 {
1168  static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1169  struct GNUNET_HashCode hc;
1170 
1171  GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1172  GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1173  ret.encoding[6] = '\0';
1174  return (const char *)ret.encoding;
1175 }
1176 
1177 
1187 const char *
1189 {
1190  static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1191  struct GNUNET_HashCode hc;
1192 
1193  GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1194  GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1195  ret.encoding[6] = '\0';
1196  return (const char *)ret.encoding;
1197 }
1198 
1199 
1209 const char *
1211 {
1212  static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1213  struct GNUNET_HashCode hc;
1214 
1215  GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1216  GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1217  ret.encoding[6] = '\0';
1218  return (const char *)ret.encoding;
1219 }
1220 
1221 
1231 const char *
1233 {
1234  static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1235  struct GNUNET_HashCode hc;
1236 
1237  GNUNET_CRYPTO_hash(p, sizeof(*p), &hc);
1238  GNUNET_CRYPTO_hash_to_enc(&hc, &ret);
1239  ret.encoding[6] = '\0';
1240  return (const char *)ret.encoding;
1241 }
1242 
1243 
1253 const char *
1255 {
1256  static char buf[64];
1257 
1258  GNUNET_STRINGS_data_to_string(shc, sizeof(*shc), buf, sizeof(buf));
1259  buf[6] = '\0';
1260  return (const char *)buf;
1261 }
1262 
1263 
1273 const char *
1274 GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
1275 {
1276  static char buf[32];
1277 
1278  GNUNET_STRINGS_data_to_string(uuid, sizeof(*uuid), buf, sizeof(buf));
1279  buf[6] = '\0';
1280  return (const char *)buf;
1281 }
1282 
1283 
1292 const char *
1294 {
1295  static struct GNUNET_CRYPTO_HashAsciiEncoded ret;
1296 
1297  GNUNET_CRYPTO_hash_to_enc(hc, &ret);
1298  ret.encoding[sizeof(ret) - 1] = '\0';
1299  return (const char *)ret.encoding;
1300 }
1301 
1302 
1310 const char *
1312 {
1313  static GNUNET_THREAD_LOCAL char buf[5];
1314  char *ret;
1315 
1316  if (NULL == pid)
1317  return "NULL";
1319  GNUNET_strlcpy(buf, ret, sizeof(buf));
1320  GNUNET_free(ret);
1321  return buf;
1322 }
1323 
1324 
1335 const char *
1337 {
1338  static GNUNET_THREAD_LOCAL char buf[5];
1339  char *ret;
1340 
1341  if (NULL == pid)
1342  return "NULL";
1344  GNUNET_strlcpy(buf, ret, sizeof(buf));
1345  GNUNET_free(ret);
1346  return buf;
1347 }
1348 
1349 
1357 const char *
1359 {
1360  static GNUNET_THREAD_LOCAL char buf[256];
1361  char *ret;
1362 
1364  strcpy(buf, ret);
1365  GNUNET_free(ret);
1366  return buf;
1367 }
1368 
1369 
1380 const char *
1381 GNUNET_a2s(const struct sockaddr *addr, socklen_t addrlen)
1382 {
1383 #define LEN \
1384  GNUNET_MAX((INET6_ADDRSTRLEN + 8), \
1385  (1 + sizeof(struct sockaddr_un) - sizeof(sa_family_t)))
1386  static char buf[LEN];
1387 #undef LEN
1388  static char b2[6];
1389  const struct sockaddr_in *v4;
1390  const struct sockaddr_un *un;
1391  const struct sockaddr_in6 *v6;
1392  unsigned int off;
1393 
1394  if (addr == NULL)
1395  return _("unknown address");
1396  switch (addr->sa_family)
1397  {
1398  case AF_INET:
1399  if (addrlen != sizeof(struct sockaddr_in))
1400  return "<invalid v4 address>";
1401  v4 = (const struct sockaddr_in *)addr;
1402  inet_ntop(AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN);
1403  if (0 == ntohs(v4->sin_port))
1404  return buf;
1405  strcat(buf, ":");
1406  GNUNET_snprintf(b2, sizeof(b2), "%u", ntohs(v4->sin_port));
1407  strcat(buf, b2);
1408  return buf;
1409 
1410  case AF_INET6:
1411  if (addrlen != sizeof(struct sockaddr_in6))
1412  return "<invalid v4 address>";
1413  v6 = (const struct sockaddr_in6 *)addr;
1414  buf[0] = '[';
1415  inet_ntop(AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN);
1416  if (0 == ntohs(v6->sin6_port))
1417  return &buf[1];
1418  strcat(buf, "]:");
1419  GNUNET_snprintf(b2, sizeof(b2), "%u", ntohs(v6->sin6_port));
1420  strcat(buf, b2);
1421  return buf;
1422 
1423  case AF_UNIX:
1424  if (addrlen <= sizeof(sa_family_t))
1425  return "<unbound UNIX client>";
1426  un = (const struct sockaddr_un *)addr;
1427  off = 0;
1428  if ('\0' == un->sun_path[0])
1429  off++;
1430  memset(buf, 0, sizeof(buf));
1431  GNUNET_snprintf(buf,
1432  sizeof(buf),
1433  "%s%.*s",
1434  (1 == off) ? "@" : "",
1435  (int)(addrlen - sizeof(sa_family_t) - off),
1436  &un->sun_path[off]);
1437  return buf;
1438 
1439  default:
1440  return _("invalid address");
1441  }
1442 }
1443 
1444 
1452 void
1454  const char *section,
1455  const char *option)
1456 {
1457  GNUNET_log(kind,
1458  _(
1459  "Configuration fails to specify option `%s' in section `%s'!\n"),
1460  option,
1461  section);
1462 }
1463 
1464 
1473 void
1475  const char *section,
1476  const char *option,
1477  const char *required)
1478 {
1479  GNUNET_log(
1480  kind,
1481  _(
1482  "Configuration specifies invalid value for option `%s' in section `%s': %s\n"),
1483  option,
1484  section,
1485  required);
1486 }
1487 
1488 
1495 void
1497  struct GNUNET_AsyncScopeSave *old_scope)
1498 {
1499  *old_scope = current_async_scope;
1502 }
1503 
1504 
1510 void
1512 {
1513  current_async_scope = *old_scope;
1514 }
1515 
1516 
1522 void
1524 {
1526  aid_ret,
1527  sizeof(struct GNUNET_AsyncScopeId));
1528 }
1529 
1530 
1536 void
1538 {
1539  *scope_ret = current_async_scope;
1540 }
1541 
1542 
1546 void __attribute__ ((constructor)) GNUNET_util_cl_init()
1547 {
1548  GNUNET_stderr = stderr;
1549 }
1550 
1551 
1555 void __attribute__ ((destructor)) GNUNET_util_cl_fini()
1556 {
1557 
1558 }
1559 
1560 /* end of common_logging.c */
void GNUNET_logger_add(GNUNET_Logger logger, void *logger_cls)
Add a custom logger.
#define DATE_STR_SIZE
How many characters can a date/time string be at most?
static int logdefs_len
The number of units used in logdefs array.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
static GNUNET_THREAD_LOCAL struct GNUNET_TIME_Absolute last_bulk_time
Time of the last bulk error message (0 for none)
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
struct GNUNET_MessageHeader * msg
Definition: 005.c:2
uint64_t rel_value_us
The actual value.
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:34
#define COMP_TRACK_SIZE
How many characters do we use for matching of bulk components?
struct CustomLogger * next
This is a linked list.
void GNUNET_logger_remove(GNUNET_Logger logger, void *logger_cls)
Remove a custom logger.
static int parse_definitions(const char *constname, int force)
Utility function - parses a definition.
#define GNUNET_THREAD_LOCAL
Definition: platform.h:255
int GNUNET_snprintf(char *buf, size_t size, const char *format,...)
Like snprintf, just aborts if the buffer is of insufficient size.
const char * GNUNET_error_type_to_string(enum GNUNET_ErrorType kind)
Convert error type to string.
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:39
#define BULK_TRACK_SIZE
How many characters do we use for matching of bulk messages?
const char * GNUNET_e2s2(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
static char * log_file_name
Format string describing the name of the log file.
static int logdefs_size
Allocated size of logdefs array (in units)
static FILE * GNUNET_stderr
File descriptor to use for "stderr", or NULL for none.
static int ok
Return value from &#39;main&#39; (0 == success)
const char * GNUNET_p2s2(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
void * logger_cls
Closure for logger.
int GNUNET_DISK_directory_create_for_file(const char *filename)
Create the directory structure for storing a file.
Definition: disk.c:681
static struct LogDef * logdefs
Dynamic array of logging definitions.
#define GNUNET_NO
Definition: gnunet_common.h:78
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_h2s(const struct GNUNET_HashCode *hc)
Convert a hash to a string (for printing debug messages).
#define GNUNET_OK
Named constants for return values.
Definition: gnunet_common.h:75
#define GNUNET_free_non_null(ptr)
Free the memory pointed to by ptr if ptr is not NULL.
GNUNET_ErrorType
Types of errors.
#define GNUNET_new(type)
Allocate a struct or union of the given type.
int force
1 if this definition comes from GNUNET_FORCE_LOG, which means that it overrides any configuration opt...
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.
Identifier for an asynchronous execution context.
#define BULK_DELAY_THRESHOLD
After how many milliseconds do we always print that "message X was repeated N times"? Use 12h.
static struct GNUNET_SCHEDULER_Task * t
Main task.
static int ret
Final status code.
Definition: gnunet-arm.c:89
int to_line
Highest line at which this definition matches.
#define GNUNET_strdup(a)
Wrapper around GNUNET_xstrdup_.
#define PATH_MAX
Assumed maximum path length (for the log file name).
int from_line
Lowest line at which this definition matches.
uint64_t abs_value_us
The actual value.
#define GNUNET_break(cond)
Use this for internal assertion violations that are not fatal (can be handled) but should not occur...
static char * component
Running component.
A 256-bit hashcode.
#define _(String)
GNU gettext support macro.
Definition: platform.h:181
static char * section
Name of the section.
Definition: gnunet-config.c:33
void GNUNET_abort_()
Abort the process, generate a core dump if possible.
static void parse_all_definitions()
Utility function - parses GNUNET_LOG and GNUNET_FORCE_LOG.
static GNUNET_THREAD_LOCAL char last_bulk_comp[32+1]
Component when the last bulk was logged.
#define INT_MAX
cryptographic primitives for GNUnet
int GNUNET_asprintf(char **buf, const char *format,...)
Like asprintf, just portable.
const char * GNUNET_h2s2(const struct GNUNET_HashCode *hc)
Convert a hash to a string (for printing debug messages).
Linked list of active loggers.
enum State state
current state of profiling
static struct GNUNET_OS_Process * p
Helper process we started.
Definition: gnunet-qr.c:59
static char * line
Desired phone line (string to be converted to a hash).
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_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug messages).
static struct CustomLogger * loggers
Linked list of our custom loggres.
const char * GNUNET_uuid2s(const struct GNUNET_Uuid *uuid)
Convert a UUID to a string (for printing debug messages).
#define GNUNET_log_strerror_file(level, cmd, filename)
Log an error message at log-level &#39;level&#39; that indicates a failure of the command &#39;cmd&#39; with the mess...
static char * fn
Filename of the unique file.
#define GNUNET_realloc(ptr, size)
Wrapper around realloc.
void GNUNET_CRYPTO_hash(const void *block, size_t size, struct GNUNET_HashCode *ret)
Compute hash of a given block.
Definition: crypto_hash.c:44
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:367
void GNUNET_log_nocheck(enum GNUNET_ErrorType kind, const char *message,...)
Main log function.
static void resize_logdefs()
Utility function - reallocates logdefs array to be twice as large.
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:686
static char * option
Name of the option.
Definition: gnunet-config.c:38
static char buf[2048]
static int gnunet_force_log_present
GNUNET_YES if at least one definition with forced == 1 is available.
#define ROTATION_KEEP
How many log files to keep?
A UUID, a 128 bit random value.
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)...
regex_t function_regex
Function name regex.
static int gnunet_log_parsed
GNUNET_YES if GNUNET_LOG environment variable is already parsed.
A 512-bit hashcode.
struct GNUNET_TIME_Absolute GNUNET_TIME_absolute_get(void)
Get the current time.
Definition: time.c:118
regex_t component_regex
Component name regex.
void GNUNET_log_from_nocheck(enum GNUNET_ErrorType kind, const char *comp, const char *message,...)
Log function that specifies an alternative component.
void __attribute__((constructor))
Initializer.
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.
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:69
#define GNUNET_SYSERR
Definition: gnunet_common.h:76
static unsigned int size
Size of the "table".
Definition: peer.c:66
static void log_rotate(const char *new_name)
Rotate logs, deleting the oldest log.
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
Saved async scope identifier or root scope.
#define LEN
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.
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:602
Represents a single logging definition.
char * getenv()
const char * GNUNET_h2s_full(const struct GNUNET_HashCode *hc)
Convert a hash to a string (for printing debug messages).
void GNUNET_async_scope_restore(struct GNUNET_AsyncScopeSave *old_scope)
Clear the current thread&#39;s async scope.
long long GNUNET_TIME_get_offset(void)
Get the timestamp offset for this instance.
Definition: time.c:65
0-terminated ASCII encoding of a struct GNUNET_HashCode.
static void mylog(enum GNUNET_ErrorType kind, const char *comp, const char *message, va_list va)
Output a log message using the default mechanism.
void GNUNET_async_scope_enter(const struct GNUNET_AsyncScopeId *aid, struct GNUNET_AsyncScopeSave *old_scope)
Set the async scope for the current thread.
static void output_message(enum GNUNET_ErrorType kind, const char *comp, const char *datestr, const char *msg)
Actually output the log message.
The identity of the host (wraps the signing key of the peer).
void GNUNET_async_scope_fresh(struct GNUNET_AsyncScopeId *aid_ret)
Generate a fresh async scope identifier.
struct GNUNET_AsyncScopeId scope_id
Saved scope.
#define BULK_REPEAT_THRESHOLD
After how many repetitions do we always print that "message X was repeated N times"? (even if we have not yet reached the delay threshold)
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:373
static GNUNET_THREAD_LOCAL unsigned int last_bulk_repeat
Number of times that bulk message has been repeated since.
void GNUNET_async_scope_get(struct GNUNET_AsyncScopeSave *scope_ret)
Get the current async scope.
void GNUNET_log_skip(int n, int check_reset)
Ignore the next n calls to the log function.
Public ECC key (always for Curve25519) encoded in a format suitable for network transmission and encr...
#define GNUNET_log(kind,...)
regex_t file_regex
File name regex.
void GNUNET_CRYPTO_random_block(enum GNUNET_CRYPTO_Quality mode, void *buffer, size_t length)
Fill block with a random values.
static GNUNET_THREAD_LOCAL char last_bulk [256] __nonstring
The last "bulk" error message that we have been logging.
static int setup_log_file(const struct tm *tm)
Setup the log file.
Time for absolute times used by GNUnet, in microseconds.
#define GNUNET_YES
Definition: gnunet_common.h:77
static enum GNUNET_ErrorType get_type(const char *log)
Convert a textual description of a loglevel to the respective GNUNET_GE_KIND.
int GNUNET_get_log_skip()
Get the number of log calls that are going to be skipped.
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).
static GNUNET_THREAD_LOCAL int skip_log
Number of log calls to ignore.
static struct GNUNET_PeerIdentity pid
Identity of the peer we transmit to / connect to.
void(* GNUNET_Logger)(void *cls, enum GNUNET_ErrorType kind, const char *component, const char *date, const char *message)
User-defined handler for log messages.
static void flush_bulk(const char *datestr)
Flush an existing bulk report to the output.
static enum GNUNET_ErrorType min_level
Minimum log level.
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:219
const char * GNUNET_i2s(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
int level
Maximal log level allowed for calls that match this definition.
static __thread struct GNUNET_AsyncScopeSave current_async_scope
Asynchronous scope of the current thread, or NULL if we have not entered an async scope yet...
No good quality of the operation is needed (i.e., random numbers can be pseudo-random).
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:857
static char * component_nopid
Running component (without pid).
#define GNUNET_free(ptr)
Wrapper around free.
GNUNET_Logger logger
Log function.
struct GNUNET_CRYPTO_EddsaPublicKey public_key
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.
Public ECC key (always for curve Ed25519) encoded in a format suitable for network transmission and E...