1 /* SPDX-License-Identifier: GPL-3.0-or-later
2  * Copyright © 2016-2018 The TokTok team.
3  * Copyright © 2013,2015 Tox project.
4  */
5 
6 /*
7  * Text logging abstraction.
8  */
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12 
13 #include "logger.h"
14 
15 #include <assert.h>
16 #include <stdarg.h>
17 #include <stdio.h>
18 #include <stdlib.h>
19 #include <string.h>
20 
21 
22 struct Logger {
23     logger_cb *callback;
24     void *context;
25     void *userdata;
26 };
27 
28 #ifdef USE_STDERR_LOGGER
logger_level_name(Logger_Level level)29 static const char *logger_level_name(Logger_Level level)
30 {
31     switch (level) {
32         case LOGGER_LEVEL_TRACE:
33             return "TRACE";
34 
35         case LOGGER_LEVEL_DEBUG:
36             return "DEBUG";
37 
38         case LOGGER_LEVEL_INFO:
39             return "INFO";
40 
41         case LOGGER_LEVEL_WARNING:
42             return "WARNING";
43 
44         case LOGGER_LEVEL_ERROR:
45             return "ERROR";
46     }
47 
48     return "<unknown>";
49 }
50 
logger_stderr_handler(void * context,Logger_Level level,const char * file,int line,const char * func,const char * message,void * userdata)51 static void logger_stderr_handler(void *context, Logger_Level level, const char *file, int line, const char *func,
52                                   const char *message, void *userdata)
53 {
54     // GL stands for "global logger".
55     fprintf(stderr, "[GL] %s %s:%d(%s): %s\n", logger_level_name(level), file, line, func, message);
56 }
57 
58 static const Logger logger_stderr = {
59     logger_stderr_handler,
60     nullptr,
61     nullptr,
62 };
63 #endif
64 
65 /**
66  * Public Functions
67  */
logger_new(void)68 Logger *logger_new(void)
69 {
70     return (Logger *)calloc(1, sizeof(Logger));
71 }
72 
logger_kill(Logger * log)73 void logger_kill(Logger *log)
74 {
75     free(log);
76 }
77 
logger_callback_log(Logger * log,logger_cb * function,void * context,void * userdata)78 void logger_callback_log(Logger *log, logger_cb *function, void *context, void *userdata)
79 {
80     log->callback = function;
81     log->context  = context;
82     log->userdata = userdata;
83 }
84 
logger_write(const Logger * log,Logger_Level level,const char * file,int line,const char * func,const char * format,...)85 void logger_write(const Logger *log, Logger_Level level, const char *file, int line, const char *func,
86                   const char *format, ...)
87 {
88     if (!log) {
89 #ifdef USE_STDERR_LOGGER
90         log = &logger_stderr;
91 #else
92         fprintf(stderr, "NULL logger not permitted.\n");
93         abort();
94 #endif
95     }
96 
97     if (!log->callback) {
98         return;
99     }
100 
101     // Only pass the file name, not the entire file path, for privacy reasons.
102     // The full path may contain PII of the person compiling toxcore (their
103     // username and directory layout).
104     const char *filename = strrchr(file, '/');
105     file = filename ? filename + 1 : file;
106 #if defined(_WIN32) || defined(__CYGWIN__)
107     // On Windows, the path separator *may* be a backslash, so we look for that
108     // one too.
109     const char *windows_filename = strrchr(file, '\\');
110     file = windows_filename ? windows_filename + 1 : file;
111 #endif
112 
113     // Format message
114     char msg[1024];
115     va_list args;
116     va_start(args, format);
117     vsnprintf(msg, sizeof(msg), format, args);
118     va_end(args);
119 
120     log->callback(log->context, level, file, line, func, msg, log->userdata);
121 }
122