0
|
1 |
#include "log.h"
|
|
2 |
|
|
3 |
#include <stdio.h>
|
|
4 |
#include <stdarg.h>
|
|
5 |
#include <string.h>
|
|
6 |
#include <stdlib.h>
|
|
7 |
#include <errno.h>
|
|
8 |
|
|
9 |
/**
|
|
10 |
* The global log level
|
|
11 |
*/
|
|
12 |
static enum log_level _log_level = LOG_LEVEL_DEFAULT;
|
|
13 |
|
|
14 |
/**
|
|
15 |
* List of log level names
|
|
16 |
*/
|
|
17 |
const char *log_level_names[] = {
|
|
18 |
"DEBUG",
|
|
19 |
"INFO",
|
|
20 |
"WARN",
|
|
21 |
"ERROR",
|
|
22 |
"FATAL",
|
|
23 |
NULL
|
|
24 |
};
|
|
25 |
|
|
26 |
#define _LOG_LEVEL_NAME(ll) case LOG_ ## ll: return #ll;
|
|
27 |
const char *log_level_name (enum log_level level)
|
|
28 |
{
|
|
29 |
switch (level) {
|
|
30 |
_LOG_LEVEL_NAME(DEBUG)
|
|
31 |
_LOG_LEVEL_NAME(INFO)
|
|
32 |
_LOG_LEVEL_NAME(WARN)
|
|
33 |
_LOG_LEVEL_NAME(ERROR)
|
|
34 |
_LOG_LEVEL_NAME(FATAL)
|
|
35 |
default: return "???";
|
|
36 |
}
|
|
37 |
}
|
|
38 |
#undef _LOG_LEVEL_NAME
|
|
39 |
|
|
40 |
void set_log_level (enum log_level level)
|
|
41 |
{
|
|
42 |
// meep meep
|
|
43 |
_log_level = level;
|
|
44 |
}
|
|
45 |
|
|
46 |
size_t str_append_fmt_va (char *buf_ptr, size_t *buf_size, const char *fmt, va_list args)
|
|
47 |
{
|
|
48 |
int ret;
|
|
49 |
|
|
50 |
if (*buf_size && (ret = vsnprintf(buf_ptr, *buf_size, fmt, args)) < 0)
|
|
51 |
return 0;
|
|
52 |
|
|
53 |
if (ret > *buf_size)
|
|
54 |
*buf_size = 0;
|
|
55 |
|
|
56 |
else
|
|
57 |
*buf_size -= ret;
|
|
58 |
|
|
59 |
return ret;
|
|
60 |
}
|
|
61 |
|
|
62 |
size_t str_append_fmt (char *buf_ptr, size_t *buf_size, const char *fmt, ...)
|
|
63 |
{
|
|
64 |
va_list vargs;
|
|
65 |
size_t ret;
|
|
66 |
|
|
67 |
va_start(vargs, fmt);
|
|
68 |
ret = str_append_fmt_va(buf_ptr, buf_size, fmt, vargs);
|
|
69 |
va_end(vargs);
|
|
70 |
|
|
71 |
return ret;
|
|
72 |
}
|
|
73 |
|
|
74 |
void log_output_tag_va (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, va_list log_fmtargs)
|
|
75 |
{
|
|
76 |
char buf[LOG_MSG_MAX], *buf_ptr = buf;
|
|
77 |
size_t buf_size = sizeof(buf);
|
|
78 |
|
|
79 |
// filter out?
|
|
80 |
if (level < _log_level)
|
|
81 |
return;
|
|
82 |
|
|
83 |
buf_ptr += str_append_fmt(buf_ptr, &buf_size, "[%5s] %20s : ", tag, func);
|
|
84 |
|
|
85 |
// output the user data
|
|
86 |
if (user_fmt)
|
|
87 |
buf_ptr += str_append_fmt_va(buf_ptr, &buf_size, user_fmt, user_fmtargs);
|
|
88 |
|
|
89 |
// output the suffix
|
|
90 |
if (log_fmt)
|
|
91 |
buf_ptr += str_append_fmt_va(buf_ptr, &buf_size, log_fmt, log_fmtargs);
|
|
92 |
|
|
93 |
// display
|
|
94 |
// XXX: handle SIGINTR?
|
|
95 |
fprintf(stderr, "%s\n", buf);
|
|
96 |
}
|
|
97 |
|
|
98 |
void log_output_tag (enum log_level level, const char *tag, const char *func, const char *user_fmt, va_list user_fmtargs, const char *log_fmt, ...)
|
|
99 |
{
|
|
100 |
va_list vargs;
|
|
101 |
|
|
102 |
va_start(vargs, log_fmt);
|
|
103 |
log_output_tag_va(level, tag, func, user_fmt, user_fmtargs, log_fmt, vargs);
|
|
104 |
va_end(vargs);
|
|
105 |
}
|
|
106 |
|
|
107 |
void _log_msg (enum log_level level, const char *func, const char *format, ...)
|
|
108 |
{
|
|
109 |
va_list vargs;
|
|
110 |
|
|
111 |
// formatted output: no suffix
|
|
112 |
va_start(vargs, format);
|
|
113 |
log_output_tag(level, log_level_name(level), func, format, vargs, NULL);
|
|
114 |
va_end(vargs);
|
|
115 |
}
|
|
116 |
|
|
117 |
void _log_msg_va2 (enum log_level level, const char *func, const char *fmt1, va_list fmtargs1, const char *fmt2, va_list fmtargs2)
|
|
118 |
{
|
|
119 |
log_output_tag_va(level, log_level_name(level), func, fmt1, fmtargs1, fmt2, fmtargs2);
|
|
120 |
}
|
|
121 |
|
|
122 |
void _log_errno (enum log_level level, const char *func, const char *format, ...)
|
|
123 |
{
|
|
124 |
va_list vargs;
|
|
125 |
|
|
126 |
// formatted output: suffix strerror()
|
|
127 |
va_start(vargs, format);
|
|
128 |
log_output_tag(level, log_level_name(level), func, format, vargs, ": %s", strerror(errno));
|
|
129 |
va_end(vargs);
|
|
130 |
}
|
|
131 |
|
|
132 |
void _log_exit (enum log_level level, int exit_code, const char *func, const char *format, ...)
|
|
133 |
{
|
|
134 |
va_list vargs;
|
|
135 |
|
|
136 |
// formatted output without any suffix
|
|
137 |
va_start(vargs, format);
|
|
138 |
log_output_tag(level, "EXIT", func, format, vargs, NULL);
|
|
139 |
va_end(vargs);
|
|
140 |
|
|
141 |
// exit
|
|
142 |
exit(exit_code);
|
|
143 |
}
|
|
144 |
|