1 /*************************************************************************
3 * Copyright 2020 highstreet technologies GmbH and others
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 ***************************************************************************/
20 #include "log_utils.h"
28 #include <sys/types.h>
30 #include <sys/types.h>
35 #include <core/framework.h>
37 static int instances = 0;
38 static FILE* logfile = 0;
40 static int file_no = 0;
41 static int line_no = 0;
42 static const char *filename;
44 static char *extract_format(const char *format);
46 void log_init(const char *logfilename) {
47 assert(instances == 0);
50 logfile = fopen(logfilename, "w");
55 filename = logfilename;
58 void log__message(char const * const fname, uint32_t location, int verbose_level, const char *format, ...) {
59 if(verbose_level >= 0) {
65 char logfilename[512];
66 sprintf(logfilename, "%s.%d", filename, file_no);
67 logfile = fopen(logfilename, "w");
74 char *verbose_file = 0;
75 int free_verbose_file = 0;
77 char *verbose_screen = 0;
78 int free_verbose_screen = 0;
80 if(verbose_level < 0) {
81 //when verbose negative, treat as add (no filename, line, time, etc)
82 verbose_level = -verbose_level;
83 verbose_file = (char *)format;
84 verbose_screen = (char *)format;
87 //extract just the filename, no path
88 const char *filename = fname + strlen(fname) - 1;
89 while((filename != fname) && (*filename != '/')) {
92 if(*filename == '/') {
96 time_t t = time(NULL);
97 struct tm tm = *localtime(&t);
99 asprintf(&verbose_file, "[%d-%02d-%02d|%02d:%02d:%02d|%s:%u] %s", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, filename, location, format);
100 if(verbose_file == 0) {
101 verbose_file = (char *)format;
104 free_verbose_file = 1;
107 if(verbose_level != 0) {
108 asprintf(&verbose_screen, "[%d-%02d-%02d|%02d:%02d:%02d] %s", tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday, tm.tm_hour, tm.tm_min, tm.tm_sec, format);
111 verbose_screen = strdup(verbose_file);
114 if(verbose_screen == 0) {
115 verbose_screen = (char *)format;
118 free_verbose_screen = 1;
122 //log to file in an uncolored format (simple format)
123 va_start(arg, format);
124 char *simple_format = extract_format(verbose_file);
125 vfprintf(logfile, simple_format, arg);
127 if(simple_format != verbose_file) {
133 if(free_verbose_file) {
137 if(verbose_level <= framework_arguments.verbosity_level) {
139 if(verbose_level == 0) {
140 fprintf(stderr, LOG_COLOR_BOLD_RED);
141 va_start(arg, format);
142 vfprintf(stderr, verbose_screen, arg);
144 fprintf(stderr, LOG_COLOR_RESET);
146 fprintf(stdout, LOG_COLOR_BOLD_RED);
149 va_start(arg, format);
150 vfprintf(stdout, verbose_screen, arg);
153 if(verbose_level == 0) {
154 fprintf(stdout, LOG_COLOR_RESET);
158 if(free_verbose_screen) {
159 free(verbose_screen);
163 void log_close(void) {
168 static char *extract_format(const char *format) {
171 int l = strlen(format);
172 char *ret = (char *)malloc(sizeof(char) * (l + 1));
174 fprintf(stderr, LOG_COLOR_BOLD_RED"bad malloc in log system\n"LOG_COLOR_RESET);
175 return (char *)format;
180 bool in_escape = false;
185 if(format[s] == 27) {
191 if(format[s] == 'm') {
199 ret[d++] = format[s];
210 void log_redirect_stderr(const char *stderrfilename) {
211 remove(stderrfilename);
212 int stderr_fd = open(stderrfilename, O_WRONLY | O_CREAT | O_TRUNC, 0666);
213 dup2(stderr_fd, STDERR_FILENO);