1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
|
#include <errno.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>
#include "error.h"
#include "command/run.h"
#include "config.h"
#include "util/log.h"
#include "util/xstdio.h"
static char error_buf[512];
static unsigned int nr_errors;
static bool msg_is_error;
static bool print_errors_to_stderr;
void clear_error(void)
{
error_buf[0] = '\0';
}
bool error_msg(const char *format, ...)
{
const char *cmd = current_command ? current_command->name : NULL;
const char *file = current_config.file;
const unsigned int line = current_config.line;
const size_t size = sizeof(error_buf);
int pos = 0;
if (file && cmd) {
pos = snprintf(error_buf, size, "%s:%u: %s: ", file, line, cmd);
} else if (file) {
pos = snprintf(error_buf, size, "%s:%u: ", file, line);
} else if (cmd) {
pos = snprintf(error_buf, size, "%s: ", cmd);
}
if (unlikely(pos < 0)) {
// Note: POSIX snprintf(3) *does* set errno on failure (unlike ISO C)
LOG_ERRNO("snprintf");
pos = 0;
}
if (likely(pos < (size - 3))) {
va_list ap;
va_start(ap, format);
vsnprintf(error_buf + pos, size - pos, format, ap);
va_end(ap);
} else {
LOG_WARNING("no buffer space left for error message");
}
msg_is_error = true;
nr_errors++;
if (print_errors_to_stderr) {
xfputs(error_buf, stderr);
xfputc('\n', stderr);
}
LOG_INFO("%s", error_buf);
// Always return false, to allow tail-calling as `return error_msg(...);`
// from command handlers, instead of `error_msg(...); return false;`
return false;
}
bool error_msg_errno(const char *prefix)
{
return error_msg("%s: %s", prefix, strerror(errno));
}
void info_msg(const char *format, ...)
{
va_list ap;
va_start(ap, format);
vsnprintf(error_buf, sizeof(error_buf), format, ap);
va_end(ap);
msg_is_error = false;
}
const char *get_msg(bool *is_error)
{
*is_error = msg_is_error;
return error_buf;
}
unsigned int get_nr_errors(void)
{
return nr_errors;
}
void set_print_errors_to_stderr(bool enable)
{
print_errors_to_stderr = enable;
}
|