ksgi

Форк
0
/
logging.c 
317 строк · 6.2 Кб
1
/*	$Id$ */
2
/*
3
 * Copyright (c) 2016--2018, 2020 Kristaps Dzonsons <kristaps@bsd.lv>
4
 *
5
 * Permission to use, copy, modify, and distribute this software for any
6
 * purpose with or without fee is hereby granted, provided that the above
7
 * copyright notice and this permission notice appear in all copies.
8
 *
9
 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10
 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11
 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12
 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13
 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14
 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15
 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16
 */
17
#include "config.h"
18

19
#include <ctype.h>
20
#include <errno.h>
21
#include <stdarg.h>
22
#include <stdio.h>
23
#include <stdint.h>
24
#include <stdlib.h>
25
#include <string.h>
26
#include <time.h>
27

28
#include "kcgi.h"
29

30
enum	llevel {
31
	LLEVEL_INFO,
32
	LLEVEL_WARN,
33
	LLEVEL_ERROR,
34
	LLEVEL__MAX
35
};
36

37
static	const char *llevels[LLEVEL__MAX] = {
38
	"INFO", /* LLEVEL_INFO */
39
	"WARN", /* LLEVEL_WARN */
40
	"ERROR", /* LLEVEL_ERROR */
41
};
42

43
/*
44
 * Actual logging function.
45
 * Only the optional error string is trusted to have "good" characters;
46
 * all others may contain anything and are filtered.
47
 */
48
static void
49
logmsg(const struct kreq *r, const char *err, const char *lvl, 
50
	const char *ident, const char *fmt, va_list ap)
51
{
52
	int	 i, cmpsz, sz;
53
	char	 date[64];
54
	char	*msg, *var = NULL, *cmp, *p;
55

56
	/* 
57
	 * Convert to GMT.
58
	 * We can't use localtime because we're probably going to be
59
	 * chrooted, and maybe sandboxed, and touching our timezone
60
	 * files will crash us (or at least not be applicable).
61
	 */
62

63
	khttp_epoch2str(time(NULL), date, sizeof(date));
64

65
	/*
66
	 * Format the variable args, then compose with the log prefix
67
	 * to form the basic message.
68
	 */
69

70
	if (fmt != NULL) {
71
		kvasprintf(&var, fmt, ap);
72
		cmpsz = kasprintf
73
			(&cmp, "%s %s [%s] %s %s",
74
			 r == NULL ? "-" : r->remote, 
75
			 ident == NULL ? "-" : ident, date, 
76
			 lvl == NULL ? "-" : lvl, var);
77
		free(var);
78
	} else
79
		cmpsz = kasprintf
80
			(&cmp, "%s %s [%s] %s -",
81
			 r == NULL ? "-" : r->remote, 
82
			 ident == NULL ? "-" : ident, date, 
83
			 lvl == NULL ? "-" : lvl);
84

85
	/*
86
	 * Allocate the required memory for the message, leaving room
87
	 * for whitespace character expansion and optional error message.
88
	 * Start by buffering for \n\0.
89
	 */
90

91
	sz = cmpsz + 2;
92

93
	for (i = 0; i < cmpsz; i++)
94
		switch (cmp[i]) {
95
		case '\n':
96
		case '\r':
97
		case '\t':
98
			sz++;
99
			break;
100
		default:
101
			break;
102
		}
103

104
	/* Next, buffer for ": ". */
105

106
	if (err != NULL)
107
		sz += 2 + strlen(err);
108

109
	p = msg = kmalloc(sz);
110

111
	/*
112
	 * Copy message into final buffer, filtering unprintables
113
	 * and whitespace.
114
	 * This draws from strvis(3).
115
	 */
116

117
	for (i = 0; i < cmpsz; i++)
118
		switch (cmp[i]) {
119
		case '\a':
120
			*p++ = '\\';
121
			*p++ = 'a';
122
			break;
123
		case '\b':
124
			*p++ = '\\';
125
			*p++ = 'b';
126
			break;
127
		case '\f':
128
			*p++ = '\\';
129
			*p++ = 'f';
130
			break;
131
		case '\n':
132
			*p++ = '\\';
133
			*p++ = 'n';
134
			break;
135
		case '\r':
136
			*p++ = '\\';
137
			*p++ = 'r';
138
			break;
139
		case '\t':
140
			*p++ = '\\';
141
			*p++ = 't';
142
			break;
143
		case '\v':
144
			*p++ = '\\';
145
			*p++ = 'v';
146
			break;
147
		case '\0':
148
			*p++ = '\\';
149
			*p++ = '0';
150
			break;
151
		default:
152
			if (isprint((unsigned char)cmp[i]))
153
				*p++ = cmp[i];
154
			else
155
				*p++ = '?';
156
			break;
157
		}
158
	*p = '\0';
159
	free(cmp);
160

161
	/* Append optional error message, and newline */
162

163
	if (err != NULL) {
164
		(void)strlcat(msg, ": ", sz);
165
		(void)strlcat(msg, err, sz);
166
	}
167
	(void)strlcat(msg, "\n", sz);
168

169
	fputs(msg, stderr);
170
	free(msg);
171
}
172

173
int
174
kutil_openlog(const char *file)
175
{
176

177
	if (file != NULL && freopen(file, "a", stderr) == NULL)
178
		return 0;
179
	return setvbuf(stderr, NULL, _IOLBF, 0) != EOF;
180
}
181

182
void
183
kutil_vlog(const struct kreq *r, const char *lvl,
184
	const char *ident, const char *fmt, va_list ap)
185
{
186

187
	logmsg(r, strerror(errno), lvl, ident, fmt, ap);
188
}
189

190
void
191
kutil_vlogx(const struct kreq *r, const char *lvl,
192
	const char *ident, const char *fmt, va_list ap)
193
{
194

195
	logmsg(r, NULL, lvl, ident, fmt, ap);
196
}
197

198
void
199
kutil_warnx(const struct kreq *r, 
200
	const char *ident, const char *fmt, ...)
201
{
202
	va_list	 ap;
203

204
	va_start(ap, fmt);
205
	kutil_vlogx(r, llevels[LLEVEL_WARN], ident, fmt, ap);
206
	va_end(ap);
207
}
208

209
void
210
kutil_errx(const struct kreq *r, 
211
	const char *ident, const char *fmt, ...)
212
{
213
	va_list	 ap;
214

215
	va_start(ap, fmt);
216
	kutil_vlogx(r, llevels[LLEVEL_ERROR], ident, fmt, ap);
217
	va_end(ap);
218
	exit(EXIT_FAILURE);
219
}
220

221
void
222
kutil_verrx(const struct kreq *r, 
223
	const char *ident, const char *fmt, va_list ap)
224
{
225

226
	kutil_vlogx(r, llevels[LLEVEL_ERROR], ident, fmt, ap);
227
	exit(EXIT_FAILURE);
228
}
229

230
void
231
kutil_vwarnx(const struct kreq *r, 
232
	const char *ident, const char *fmt, va_list ap)
233
{
234

235
	kutil_vlogx(r, llevels[LLEVEL_WARN], ident, fmt, ap);
236
}
237

238
void
239
kutil_err(const struct kreq *r, 
240
	const char *ident, const char *fmt, ...)
241
{
242
	va_list	 ap;
243

244
	va_start(ap, fmt);
245
	kutil_vlog(r, llevels[LLEVEL_ERROR], ident, fmt, ap);
246
	va_end(ap);
247
	exit(EXIT_FAILURE);
248
}
249

250
void
251
kutil_warn(const struct kreq *r, 
252
	const char *ident, const char *fmt, ...)
253
{
254
	va_list	 ap;
255

256
	va_start(ap, fmt);
257
	kutil_vlog(r, llevels[LLEVEL_WARN], ident, fmt, ap);
258
	va_end(ap);
259
}
260

261
void
262
kutil_verr(const struct kreq *r, 
263
	const char *ident, const char *fmt, va_list ap)
264
{
265

266
	kutil_vlog(r, llevels[LLEVEL_ERROR], ident, fmt, ap);
267
	exit(EXIT_FAILURE);
268
}
269

270
void
271
kutil_vwarn(const struct kreq *r, 
272
	const char *ident, const char *fmt, va_list ap)
273
{
274

275
	kutil_vlog(r, llevels[LLEVEL_WARN], ident, fmt, ap);
276
}
277

278
void
279
kutil_info(const struct kreq *r, 
280
	const char *ident, const char *fmt, ...)
281
{
282
	va_list	 ap;
283

284
	va_start(ap, fmt);
285
	kutil_vlogx(r, llevels[LLEVEL_INFO], ident, fmt, ap);
286
	va_end(ap);
287
}
288

289
void
290
kutil_vinfo(const struct kreq *r, 
291
	const char *ident, const char *fmt, va_list ap)
292
{
293

294
	kutil_vlogx(r, llevels[LLEVEL_INFO], ident, fmt, ap);
295
}
296

297
void
298
kutil_logx(const struct kreq *r, const char *lvl,
299
	const char *ident, const char *fmt, ...)
300
{
301
	va_list	 ap;
302

303
	va_start(ap, fmt);
304
	kutil_vlogx(r, lvl, ident, fmt, ap);
305
	va_end(ap);
306
}
307

308
void
309
kutil_log(const struct kreq *r, const char *lvl,
310
	const char *ident, const char *fmt, ...)
311
{
312
	va_list	 ap;
313

314
	va_start(ap, fmt);
315
	kutil_vlog(r, lvl, ident, fmt, ap);
316
	va_end(ap);
317
}
318

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.