aboutsummaryrefslogtreecommitdiff
blob: 7ded90d49e9db6ad61ea86fc0ffecbb08a592dde (plain)
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
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
/*
 * sb_efuncs.c
 *
 * Helpers for doing pretty output.
 *
 * Copyright 1999-2012 Gentoo Foundation
 * Licensed under the GPL-2
 */

#include "headers.h"
#include "sbutil.h"

const char *colors[] = {
	"\033[0m",
	"\033[32;01m",
	"\033[33;01m",
	"\033[31;01m",
};
__attribute__((constructor))
static void sbio_init(void)
{
	if (is_env_on(ENV_NOCOLOR)) {
		size_t i;
		for (i = 0; i < ARRAY_SIZE(colors); ++i)
			colors[i] = "";
	}
}

/*
 * First try to write to the known good message log location (which is
 * normally tied to the initial sandbox's stderr).  If that fails, fall
 * back to writing to /dev/tty.  While this might annoy some people,
 * using stderr will break tests that try to validate output. #261957
 * Other related bugs on the topic: #278761
 */
static void sb_vefunc(const char *prog, const char *color, const char *format, va_list args)
{
	bool opened;
	int fd;

	if (likely(sbio_message_path))
		fd = sbio_open(sbio_message_path, O_WRONLY|O_APPEND|O_CLOEXEC, 0);
	else
		fd = -1;
	if (fd == -1)
		fd = sbio_open(sbio_fallback_path, O_WRONLY|O_CLOEXEC, 0);
	opened = (fd != -1);
	if (fd == -1)
		fd = fileno(stderr);

	if (color)
		sb_fdprintf(fd, " %s*%s ", color, COLOR_NORMAL);
	sb_vfdprintf(fd, format, args);

	if (opened)
		close(fd);
}

void sb_einfo(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	sb_vefunc("einfo", COLOR_GREEN, format, args);
	va_end(args);
}

void sb_debug_dyn(const char *format, ...)
{
	if (!is_env_on(ENV_SANDBOX_DEBUG))
		return;

	va_list args;
	va_start(args, format);
	sb_vefunc("einfo", COLOR_GREEN, format, args);
	va_end(args);
}

void sb_ewarn(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	sb_vefunc("ewarn", COLOR_YELLOW, format, args);
	va_end(args);
}

void sb_eerror(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	sb_vefunc("eerror", COLOR_RED, format, args);
	va_end(args);
}

void sb_eqawarn(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	sb_vefunc("eqawarn", COLOR_YELLOW, format, args);
	va_end(args);
}

/* This is a bit of a hack to expose the same file logic to generic printers.
 * Probably want to revisit sb_vefunc and move the guts there to a new func.
 */
void sb_eraw(const char *format, ...)
{
	va_list args;
	va_start(args, format);
	sb_vefunc(NULL, NULL, format, args);
	va_end(args);
}

void sb_dump_backtrace(void)
{
#ifdef HAVE_BACKTRACE
	void *funcs[10];
	int num_funcs;
	num_funcs = backtrace(funcs, ARRAY_SIZE(funcs));
	backtrace_symbols_fd(funcs, num_funcs, STDERR_FILENO);
#endif
	__sb_dump_backtrace();
}

void __sb_ebort(const char *file, const char *func, size_t line_num, const char *format, ...)
{
	va_list args;

	sb_eerror("%s:%s():%zu: failure (%s):\n", file, func, line_num, strerror(errno));

	va_start(args, format);
	sb_vefunc("eerror", COLOR_RED, format, args);
	va_end(args);

	sb_dump_backtrace();

	sb_maybe_gdb();

	abort();
}