GNUnet 0.22.0
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{
85
90
95};
96
97
103
110
115
120
125
130
134static char *component;
135
139static char *component_nopid;
140
144static char *log_file_name;
145
150
154static struct CustomLogger *loggers;
155
160
164static FILE *GNUNET_stderr;
165
169struct LogDef
170{
175
179 regex_t file_regex;
180
185
191
197
203 int level;
204
209 int force;
210};
211
212
213#if ! defined(GNUNET_CULL_LOGGING)
217static struct LogDef *logdefs;
218
222static int logdefs_size;
223
227static int logdefs_len;
228
233
238
243#endif
244
245
253static enum GNUNET_ErrorType
254get_type (const char *log)
255{
256 if (NULL == log)
258 if (0 == strcasecmp (log, "DEBUG"))
260 if (0 == strcasecmp (log, "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"))
271}
272
273
277void
279{
280 abort ();
281}
282
283
284#if ! defined(GNUNET_CULL_LOGGING)
288static void
290{
291 logdefs_size = (logdefs_size + 1) * 2;
292 logdefs = GNUNET_realloc (logdefs, logdefs_size * sizeof(struct LogDef));
293}
294
295
301static void
302log_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
323const char *
324GNUNET_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
352setup_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
438static int
439add_definition (const char *lcomponent,
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
452 memset (&n, 0, sizeof(n));
453 if (0 == strlen (lcomponent))
454 lcomponent = (char *) ".*";
455 r = regcomp (&n.component_regex, (const char *) lcomponent, 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 }
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
499int
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 */
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
569static int
570parse_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;
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" */
636 }
637 else /* default to 0-max */
638 {
639 from_line = 0;
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);
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
703static 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
729GNUNET_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
741 "%s-%d",
742 comp,
743 getpid ());
746
747 env_logfile = getenv ("GNUNET_FORCE_LOGFILE");
748 if ((NULL != env_logfile) && (strlen (env_logfile) > 0))
749 logfile = env_logfile;
750 if (NULL == logfile)
751 return GNUNET_OK;
754 if (NULL == log_file_name)
755 return GNUNET_SYSERR;
756#if defined(GNUNET_CULL_LOGGING)
757 /* log file option not allowed for wallet logic */
758 GNUNET_assert (NULL == logfile);
759 return GNUNET_OK;
760#else
761 {
762 time_t t;
763 const struct tm *tm;
764
765 t = time (NULL);
766 tm = gmtime (&t);
767 return setup_log_file (tm);
768 }
769#endif
770}
771
772
773void
775 void *logger_cls)
776{
777 struct CustomLogger *entry;
778
779 entry = GNUNET_new (struct CustomLogger);
780 entry->logger = logger;
781 entry->logger_cls = logger_cls;
782 entry->next = loggers;
783 loggers = entry;
784}
785
786
787void
789 void *logger_cls)
790{
791 struct CustomLogger *pos;
792 struct CustomLogger *prev;
793
794 prev = NULL;
795 pos = loggers;
796 while ((NULL != pos) &&
797 ((pos->logger != logger) || (pos->logger_cls != logger_cls)))
798 {
799 prev = pos;
800 pos = pos->next;
801 }
802 GNUNET_assert (NULL != pos);
803 if (NULL == prev)
804 loggers = pos->next;
805 else
806 prev->next = pos->next;
807 GNUNET_free (pos);
808}
809
810
819static void
821 const char *comp,
822 const char *datestr,
823 const char *msg)
824{
825 static int have_journald = -1;
826 struct CustomLogger *pos;
827
828 if (-1 == have_journald)
829 {
830 /* systemd after version 231 sets this environment
831 variable if we are logging to journald. In this
832 case, skip outputting our component name, PID
833 and timestamp as journald already adds those. (#8032) */
834 if (NULL != getenv ("JOURNAL_STREAM"))
835 have_journald = 1;
836 else
837 have_journald = 0;
838 }
839
840 /* only use the standard logger if no custom loggers are present */
841 if ((NULL != GNUNET_stderr) && (NULL == loggers))
842 {
843 if (kind == GNUNET_ERROR_TYPE_MESSAGE)
844 {
845 /* The idea here is to produce "normal" output messages
846 * for end users while still having the power of the
847 * logging engine for developer needs. So ideally this
848 * is what it should look like when CLI tools are used
849 * interactively, yet the same message shouldn't look
850 * this way if the output is going to logfiles or robots
851 * instead.
852 */
853 fprintf (GNUNET_stderr, "* %s", msg);
854 }
856 {
857 static GNUNET_THREAD_LOCAL char id_buf[27];
858 char *end;
859
860 /* We're logging, so skip_log must be currently 0. */
861 skip_log = 100;
863 sizeof(struct GNUNET_AsyncScopeId),
864 id_buf,
865 sizeof(id_buf) - 1);
866 GNUNET_assert (NULL != end);
867 *end = '\0';
868 skip_log = 0;
869 if (have_journald)
870 fprintf (GNUNET_stderr,
871 "(%s) %s %s",
872 id_buf,
874 msg);
875 else
876 fprintf (GNUNET_stderr,
877 "%s %s(%s) %s %s",
878 datestr,
879 comp,
880 id_buf,
882 msg);
883 }
884 else
885 {
886 if (have_journald)
887 fprintf (GNUNET_stderr,
888 "%s %s",
890 msg);
891 else
892 fprintf (GNUNET_stderr,
893 "%s %s %s %s",
894 datestr,
895 comp,
897 msg);
898 }
899 fflush (GNUNET_stderr);
900 }
901 pos = loggers;
902 while (NULL != pos)
903 {
904 pos->logger (pos->logger_cls, kind, comp, datestr, msg);
905 pos = pos->next;
906 }
907}
908
909
915static void
916flush_bulk (const char *datestr)
917{
918 char msg[DATE_STR_SIZE + BULK_TRACK_SIZE + 256];
919 int rev;
920 char *last;
921 const char *ft;
922
923 if ((0 == last_bulk_time.abs_value_us) || (0 == last_bulk_repeat))
924 return;
925 rev = 0;
926 last = memchr (last_bulk, '\0', BULK_TRACK_SIZE);
927 if (last == NULL)
928 last = &last_bulk[BULK_TRACK_SIZE - 1];
929 else if (last != last_bulk)
930 last--;
931 if (last[0] == '\n')
932 {
933 rev = 1;
934 last[0] = '\0';
935 }
936 ft =
939 GNUNET_YES);
940 snprintf (msg,
941 sizeof(msg),
942 _ ("Message `%.*s' repeated %u times in the last %s\n"),
944 last_bulk,
946 ft);
947 if (rev == 1)
948 last[0] = '\n';
952}
953
954
955void
956GNUNET_log_skip (int n, int check_reset)
957{
958 int ok;
959
960 if (0 == n)
961 {
962 ok = (0 == skip_log);
963 skip_log = 0;
964 if (check_reset)
965 GNUNET_break (ok);
966 }
967 else
968 {
969 skip_log += n;
970 }
971}
972
973
979int
981{
982 return skip_log;
983}
984
985
994static void
996 const char *comp,
997 const char *message,
998 va_list va)
999{
1000 char date[DATE_STR_SIZE];
1001 char date2[DATE_STR_SIZE];
1002 struct tm *tmptr;
1003 size_t size;
1004 va_list vacp;
1005
1006 va_copy (vacp, va);
1007 size = vsnprintf (NULL, 0, message, vacp) + 1;
1008 GNUNET_assert (0 != size);
1009 va_end (vacp);
1010 memset (date, 0, DATE_STR_SIZE);
1011 {
1012 char buf[size];
1013 long long offset;
1014
1015 struct timeval timeofday;
1016
1017 gettimeofday (&timeofday, NULL);
1018 offset = GNUNET_TIME_get_offset ();
1019 if (offset > 0)
1020 {
1021 timeofday.tv_sec += offset / 1000LL;
1022 timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1023 if (timeofday.tv_usec > 1000000LL)
1024 {
1025 timeofday.tv_usec -= 1000000LL;
1026 timeofday.tv_sec++;
1027 }
1028 }
1029 else
1030 {
1031 timeofday.tv_sec += offset / 1000LL;
1032 if (timeofday.tv_usec > -(offset % 1000LL) * 1000LL)
1033 {
1034 timeofday.tv_usec += (offset % 1000LL) * 1000LL;
1035 }
1036 else
1037 {
1038 timeofday.tv_usec += 1000000LL + (offset % 1000LL) * 1000LL;
1039 timeofday.tv_sec--;
1040 }
1041 }
1042 tmptr = localtime (&timeofday.tv_sec);
1043 if (NULL == tmptr)
1044 {
1045 strcpy (date, "localtime error");
1046 }
1047 else
1048 {
1049 /* RFC 3339 timestamp, with snprintf placeholder for microseconds */
1050 if (0 == strftime (date2, DATE_STR_SIZE, "%Y-%m-%dT%H:%M:%S.%%06u%z",
1051 tmptr))
1052 abort ();
1053 /* Fill in microseconds */
1054 if (0 > snprintf (date, sizeof(date), date2, timeofday.tv_usec))
1055 abort ();
1056 }
1057
1058 vsnprintf (buf, size, message, va);
1059#if ! defined(GNUNET_CULL_LOGGING)
1060 if (NULL != tmptr)
1061 (void) setup_log_file (tmptr);
1062#endif
1063 if ((0 != (kind & GNUNET_ERROR_TYPE_BULK)) &&
1065 (0 == strncmp (buf, last_bulk, sizeof(last_bulk))))
1066 {
1071 flush_bulk (date);
1072 return;
1073 }
1074 flush_bulk (date);
1075 GNUNET_strlcpy (last_bulk, buf, sizeof(last_bulk));
1076 last_bulk_repeat = 0;
1077 last_bulk_kind = kind;
1080 output_message (kind, comp, date, buf);
1081 }
1082}
1083
1084
1092void
1093GNUNET_log_nocheck (enum GNUNET_ErrorType kind, const char *message, ...)
1094{
1095 va_list va;
1096
1097 va_start (va, message);
1098 mylog (kind, component, message, va);
1099 va_end (va);
1100}
1101
1102
1112void
1114 const char *comp,
1115 const char *message,
1116 ...)
1117{
1118 va_list va;
1119 char comp_w_pid[128];
1120
1121 if (comp == NULL)
1122 comp = component_nopid;
1123
1124 va_start (va, message);
1125 GNUNET_snprintf (comp_w_pid, sizeof(comp_w_pid), "%s-%d", comp, getpid ());
1126 mylog (kind, comp_w_pid, message, va);
1127 va_end (va);
1128}
1129
1130
1131const char *
1133{
1134 if ((kind & GNUNET_ERROR_TYPE_ERROR) > 0)
1135 return _ ("ERROR");
1136 if ((kind & GNUNET_ERROR_TYPE_WARNING) > 0)
1137 return _ ("WARNING");
1138 if ((kind & GNUNET_ERROR_TYPE_MESSAGE) > 0)
1139 return _ ("MESSAGE");
1140 if ((kind & GNUNET_ERROR_TYPE_INFO) > 0)
1141 return _ ("INFO");
1142 if ((kind & GNUNET_ERROR_TYPE_DEBUG) > 0)
1143 return _ ("DEBUG");
1144 if ((kind & ~GNUNET_ERROR_TYPE_BULK) == 0)
1145 return _ ("NONE");
1146 return _ ("INVALID");
1147}
1148
1149
1156const char *
1157GNUNET_h2s (const struct GNUNET_HashCode *hc)
1158{
1160
1162 ret.encoding[8] = '\0';
1163 return (const char *) ret.encoding;
1164}
1165
1166
1177const char *
1179{
1181
1183 ret.encoding[8] = '\0';
1184 return (const char *) ret.encoding;
1185}
1186
1187
1188const char *
1190{
1192 struct GNUNET_HashCode hc;
1193
1194 GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1196 ret.encoding[6] = '\0';
1197 return (const char *) ret.encoding;
1198}
1199
1200
1201const char *
1203{
1205 struct GNUNET_HashCode hc;
1206
1207 GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1209 ret.encoding[6] = '\0';
1210 return (const char *) ret.encoding;
1211}
1212
1213
1214const char *
1216{
1218 struct GNUNET_HashCode hc;
1219
1220 GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1222 ret.encoding[6] = '\0';
1223 return (const char *) ret.encoding;
1224}
1225
1226
1227const char *
1229{
1231 struct GNUNET_HashCode hc;
1232
1233 GNUNET_CRYPTO_hash (p, sizeof(*p), &hc);
1235 ret.encoding[6] = '\0';
1236 return (const char *) ret.encoding;
1237}
1238
1239
1249const char *
1251{
1252 static GNUNET_THREAD_LOCAL char buf[64];
1253
1254 GNUNET_STRINGS_data_to_string (shc, sizeof(*shc), buf, sizeof(buf));
1255 buf[6] = '\0';
1256 return (const char *) buf;
1257}
1258
1259
1269const char *
1270GNUNET_uuid2s (const struct GNUNET_Uuid *uuid)
1271{
1272 static GNUNET_THREAD_LOCAL char buf[32];
1273
1274 GNUNET_STRINGS_data_to_string (uuid, sizeof(*uuid), buf, sizeof(buf));
1275 buf[6] = '\0';
1276 return (const char *) buf;
1277}
1278
1279
1288const char *
1290{
1292
1294 ret.encoding[sizeof(ret) - 1] = '\0';
1295 return (const char *) ret.encoding;
1296}
1297
1298
1306const char *
1308{
1309 static GNUNET_THREAD_LOCAL char buf[5];
1310 char *ret;
1311
1312 if (NULL == pid)
1313 return "NULL";
1315 GNUNET_strlcpy (buf, ret, sizeof(buf));
1316 GNUNET_free (ret);
1317 return buf;
1318}
1319
1320
1331const char *
1333{
1334 static GNUNET_THREAD_LOCAL char buf[5];
1335 char *ret;
1336
1337 if (NULL == pid)
1338 return "NULL";
1340 GNUNET_strlcpy (buf, ret, sizeof(buf));
1341 GNUNET_free (ret);
1342 return buf;
1343}
1344
1345
1353const char *
1355{
1356 static GNUNET_THREAD_LOCAL char buf[256];
1357 char *ret;
1358
1360 strcpy (buf, ret);
1361 GNUNET_free (ret);
1362 return buf;
1363}
1364
1365
1376const char *
1377GNUNET_a2s (const struct sockaddr *addr, socklen_t addrlen)
1378{
1379#define LEN \
1380 GNUNET_MAX ((INET6_ADDRSTRLEN + 8), \
1381 (1 + sizeof(struct sockaddr_un) - sizeof(sa_family_t)))
1382 static GNUNET_THREAD_LOCAL char buf[LEN];
1383#undef LEN
1384 static GNUNET_THREAD_LOCAL char b2[6];
1385 const struct sockaddr_in *v4;
1386 const struct sockaddr_un *un;
1387 const struct sockaddr_in6 *v6;
1388 unsigned int off;
1389
1390 if (addr == NULL)
1391 return _ ("unknown address");
1392 switch (addr->sa_family)
1393 {
1394 case AF_INET:
1395 if (addrlen != sizeof(struct sockaddr_in))
1396 return "<invalid v4 address>";
1397 v4 = (const struct sockaddr_in *) addr;
1398 inet_ntop (AF_INET, &v4->sin_addr, buf, INET_ADDRSTRLEN);
1399 if (0 == ntohs (v4->sin_port))
1400 return buf;
1401 strcat (buf, ":");
1402 GNUNET_snprintf (b2, sizeof(b2), "%u", ntohs (v4->sin_port));
1403 strcat (buf, b2);
1404 return buf;
1405
1406 case AF_INET6:
1407 if (addrlen != sizeof(struct sockaddr_in6))
1408 return "<invalid v6 address>";
1409 v6 = (const struct sockaddr_in6 *) addr;
1410 buf[0] = '[';
1411 inet_ntop (AF_INET6, &v6->sin6_addr, &buf[1], INET6_ADDRSTRLEN);
1412 if (0 == ntohs (v6->sin6_port))
1413 return &buf[1];
1414 strcat (buf, "]:");
1415 GNUNET_snprintf (b2, sizeof(b2), "%u", ntohs (v6->sin6_port));
1416 strcat (buf, b2);
1417 return buf;
1418
1419 case AF_UNIX:
1420 if (addrlen <= sizeof(sa_family_t))
1421 return "<unbound UNIX client>";
1422 un = (const struct sockaddr_un *) addr;
1423 off = 0;
1424 if ('\0' == un->sun_path[0])
1425 off++;
1426 memset (buf, 0, sizeof(buf));
1427 GNUNET_snprintf (buf,
1428 sizeof(buf),
1429 "%s%.*s",
1430 (1 == off) ? "@" : "",
1431 (int) (addrlen - sizeof(sa_family_t) - off),
1432 &un->sun_path[off]);
1433 return buf;
1434
1435 default:
1436 return _ ("invalid address");
1437 }
1438}
1439
1440
1441void
1443 const char *section,
1444 const char *option)
1445{
1446 GNUNET_log (kind,
1447 _ (
1448 "Configuration fails to specify option `%s' in section `%s'!\n")
1449 ,
1450 option,
1451 section);
1452}
1453
1454
1455void
1457 const char *section,
1458 const char *option,
1459 const char *required)
1460{
1461 GNUNET_log (
1462 kind,
1463 _ (
1464 "Configuration specifies invalid value for option `%s' in section `%s': %s\n"),
1465 option,
1466 section,
1467 required);
1468}
1469
1470
1477void
1479 struct GNUNET_AsyncScopeSave *old_scope)
1480{
1481 *old_scope = current_async_scope;
1484}
1485
1486
1492void
1494{
1495 current_async_scope = *old_scope;
1496}
1497
1498
1504void
1506{
1508 aid_ret,
1509 sizeof(struct GNUNET_AsyncScopeId));
1510}
1511
1512
1518void
1520{
1521 *scope_ret = current_async_scope;
1522}
1523
1524
1525size_t
1526GNUNET_hex2b (const char *src, void *dst, size_t dstlen, int invert)
1527{
1528 const char *line = src;
1529 const char *data = line;
1530 uint8_t *buf = dst;
1531 int off;
1532 int read_byte;
1533 int data_len = 0;
1534
1535 while (sscanf (data, " %02x%n", &read_byte, &off) == 1)
1536 {
1537 if (invert)
1538 buf[dstlen - 1 - data_len++] = read_byte;
1539 else
1540 buf[data_len++] = read_byte;
1541 data += off;
1542 }
1543 return data_len;
1544}
1545
1546
1547void
1548GNUNET_print_bytes (const void *buf, size_t buf_len, int fold, int in_be)
1549{
1550 int i;
1551
1552 for (i = 0; i < buf_len; i++)
1553 {
1554 if (0 != i)
1555 {
1556 if ((0 != fold) && (i % fold == 0))
1557 printf ("\n");
1558 }
1559 if (in_be)
1560 printf ("%02x", ((unsigned char*) buf)[buf_len - 1 - i]);
1561 else
1562 printf ("%02x", ((unsigned char*) buf)[i]);
1563 }
1564 printf ("\n");
1565}
1566
1567void
1569
1573void __attribute__ ((constructor))
1575{
1576 GNUNET_stderr = stderr;
1577}
1578
1579
1580void
1582
1586void __attribute__ ((destructor))
1588{
1589
1590}
1591
1592
1593/* 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 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.
void GNUNET_util_cl_fini(void)
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).
void GNUNET_util_cl_init(void)
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.
static enum GNUNET_GenericReturnValue setup_log_file(const struct tm *tm)
Setup the log file.
#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 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.
static int add_definition(const char *lcomponent, 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 * getenv()
static int start
Set if we are to start default services (including ARM).
Definition: gnunet-arm.c:38
static int ret
Final status code.
Definition: gnunet-arm.c:93
static int end
Set if we are to shutdown all services (including ARM).
Definition: gnunet-arm.c:33
static char * line
Desired phone line (string to be converted to a hash).
static char * data
The data to insert into the dht.
static struct GNUNET_PEERSTORE_StoreHelloContext * shc
HELLO store context handle.
Definition: gnunet-hello.c:52
enum State state
current state of profiling
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:583
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
#define GNUNET_log(kind,...)
const char * GNUNET_b2s(const void *buf, size_t buf_size)
Convert a buffer to an 8-character string representative of the contents.
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:255
void GNUNET_async_scope_enter(const struct GNUNET_AsyncScopeId *aid, struct GNUNET_AsyncScopeSave *old_scope)
Set the async scope for the current thread.
int have_scope
GNUNET_YES unless this saved scope is the unnamed root scope.
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_GenericReturnValue
Named constants for return values.
struct GNUNET_AsyncScopeId scope_id
Saved scope.
@ GNUNET_OK
@ GNUNET_YES
@ GNUNET_NO
@ GNUNET_SYSERR
GNUNET_ErrorType
Types of errors.
const char * GNUNET_e2s2(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
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).
void GNUNET_print_bytes(const void *buf, size_t buf_len, int fold, int in_be)
Print a byte string in hexadecimal ascii notation.
const char * GNUNET_i2s(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_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.
const char * GNUNET_e2s(const struct GNUNET_CRYPTO_EcdhePublicKey *p)
Convert a public key value to a string (for printing debug messages).
size_t GNUNET_hex2b(const char *src, void *dst, size_t dstlen, int invert)
Parse an ascii-encoded hexadecimal string into the buffer.
#define GNUNET_assert(cond)
Use this for fatal errors that cannot be handled.
const char * GNUNET_sh2s(const struct GNUNET_ShortHashCode *shc)
Convert a short hash value to a string (for printing debug messages).
const char * GNUNET_i2s_full(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity 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_h2s(const struct GNUNET_HashCode *hc)
Convert a hash to a string (for printing debug messages).
enum GNUNET_GenericReturnValue GNUNET_log_setup(const char *comp, const char *loglevel, const char *logfile)
Setup logging.
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).
void GNUNET_log_skip(int n, int check_reset)
Ignore the next n calls to the log function.
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_h2s2(const struct GNUNET_HashCode *hc)
Convert a hash 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.
const char * GNUNET_i2s2(const struct GNUNET_PeerIdentity *pid)
Convert a peer identity to a string (for printing debug messages).
const char * GNUNET_p2s(const struct GNUNET_CRYPTO_EddsaPublicKey *p)
Convert a public key value to a string (for printing debug 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_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:732
char * GNUNET_STRINGS_data_to_string_alloc(const void *buf, size_t size)
Return the base32crockford encoding of the given buffer.
Definition: strings.c:787
char * GNUNET_STRINGS_filename_expand(const char *fil)
Complete filename (a la shell) from abbrevition.
Definition: strings.c:504
size_t GNUNET_strlcpy(char *dst, const char *src, size_t n)
Like strlcpy but portable.
Definition: strings.c:137
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:438
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:579
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
static unsigned int size
Size of the "table".
Definition: peer.c:68
#define _(String)
GNU gettext support macro.
Definition: platform.h:178
#define GNUNET_THREAD_LOCAL
Definition: platform.h:247
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.
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.