aboutsummaryrefslogtreecommitdiff
path: root/src/log.c
blob: ab18ae12b4faa6892d1e02bfec144de5c2155d6c (plain) (blame)
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
/*
 * Copyright (c) 2018-2021 Yubico AB. All rights reserved.
 * Use of this source code is governed by a BSD-style
 * license that can be found in the LICENSE file.
 */

#undef _GNU_SOURCE /* XSI strerror_r() */

#include <stdarg.h>
#include <stdio.h>

#include "fido.h"

#ifndef FIDO_NO_DIAGNOSTIC

#define XXDLEN	32
#define XXDROW	128
#define LINELEN	256

#ifndef TLS
#define TLS
#endif

static TLS int logging;
static TLS fido_log_handler_t *log_handler;

static void
log_on_stderr(const char *str)
{
	fprintf(stderr, "%s", str);
}

static void
do_log(const char *suffix, const char *fmt, va_list args)
{
	char line[LINELEN], body[LINELEN];

	vsnprintf(body, sizeof(body), fmt, args);

	if (suffix != NULL)
		snprintf(line, sizeof(line), "%.180s: %.70s\n", body, suffix);
	else
		snprintf(line, sizeof(line), "%.180s\n", body);

	log_handler(line);
}

void
fido_log_init(void)
{
	logging = 1;
	log_handler = log_on_stderr;
}

void
fido_log_debug(const char *fmt, ...)
{
	va_list args;

	if (!logging || log_handler == NULL)
		return;

	va_start(args, fmt);
	do_log(NULL, fmt, args);
	va_end(args);
}

void
fido_log_xxd(const void *buf, size_t count, const char *fmt, ...)
{
	const uint8_t *ptr = buf;
	char row[XXDROW], xxd[XXDLEN];
	va_list args;

	if (!logging || log_handler == NULL)
		return;

	snprintf(row, sizeof(row), "buf=%p, len=%zu", buf, count);
	va_start(args, fmt);
	do_log(row, fmt, args);
	va_end(args);
	*row = '\0';

	for (size_t i = 0; i < count; i++) {
		*xxd = '\0';
		if (i % 16 == 0)
			snprintf(xxd, sizeof(xxd), "%04zu: %02x", i, *ptr++);
		else
			snprintf(xxd, sizeof(xxd), " %02x", *ptr++);
		strlcat(row, xxd, sizeof(row));
		if (i % 16 == 15 || i == count - 1) {
			fido_log_debug("%s", row);
			*row = '\0';
		}
	}
}

void
fido_log_error(int errnum, const char *fmt, ...)
{
	char errstr[LINELEN];
	va_list args;

	if (!logging || log_handler == NULL)
		return;
	if (strerror_r(errnum, errstr, sizeof(errstr)) != 0)
		snprintf(errstr, sizeof(errstr), "error %d", errnum);

	va_start(args, fmt);
	do_log(errstr, fmt, args);
	va_end(args);
}

void
fido_set_log_handler(fido_log_handler_t *handler)
{
	if (handler != NULL)
		log_handler = handler;
}

#endif /* !FIDO_NO_DIAGNOSTIC */