1/*
2    debug.c: log (or not) messages
3    Copyright (C) 2003-2011   Ludovic Rousseau
4
5    This library is free software; you can redistribute it and/or
6    modify it under the terms of the GNU Lesser General Public
7    License as published by the Free Software Foundation; either
8    version 2.1 of the License, or (at your option) any later version.
9
10    This library is distributed in the hope that it will be useful,
11    but WITHOUT ANY WARRANTY; without even the implied warranty of
12    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
13    Lesser General Public License for more details.
14
15	You should have received a copy of the GNU Lesser General Public License
16	along with this library; if not, write to the Free Software Foundation,
17	Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
18*/
19
20/*
21 * $Id: debug.c 6760 2013-10-01 12:57:50Z rousseau $
22 */
23
24
25#include "config.h"
26#include "misc.h"
27#include "debug.h"
28
29#include <stdarg.h>
30#include <stdio.h>
31#include <string.h>
32#include <sys/time.h>
33#include <stdlib.h>
34
35#include "strlcpycat.h"
36
37#undef LOG_TO_STDERR
38
39#ifdef LOG_TO_STDERR
40#define LOG_STREAM stderr
41#else
42#define LOG_STREAM stdout
43#endif
44
45void log_msg(const int priority, const char *fmt, ...)
46{
47	char debug_buffer[160]; /* up to 2 lines of 80 characters */
48	va_list argptr;
49	static struct timeval last_time = { 0, 0 };
50	struct timeval new_time = { 0, 0 };
51	struct timeval tmp;
52	int delta;
53	const char *color_pfx = "", *color_sfx = "";
54	const char *time_pfx = "", *time_sfx = "";
55	static int initialized = 0;
56	static int LogDoColor = 0;
57
58	if (!initialized)
59	{
60		char *term;
61
62		initialized = 1;
63		term = getenv("TERM");
64		if (term)
65		{
66			const char *terms[] = { "linux", "xterm", "xterm-color", "Eterm", "rxvt", "rxvt-unicode", "xterm-256color" };
67			unsigned int i;
68
69			/* for each known color terminal */
70			for (i = 0; i < COUNT_OF(terms); i++)
71			{
72				/* we found a supported term? */
73				if (0 == strcmp(terms[i], term))
74				{
75					LogDoColor = 1;
76					break;
77				}
78			}
79		}
80	}
81
82	if (LogDoColor)
83	{
84		color_sfx = "\33[0m";
85		time_sfx = color_sfx;
86		time_pfx = "\33[36m"; /* Cyan */
87
88		switch (priority)
89		{
90			case PCSC_LOG_CRITICAL:
91				color_pfx = "\33[01;31m"; /* bright + Red */
92				break;
93
94			case PCSC_LOG_ERROR:
95				color_pfx = "\33[35m"; /* Magenta */
96				break;
97
98			case PCSC_LOG_INFO:
99				color_pfx = "\33[34m"; /* Blue */
100				break;
101
102			case PCSC_LOG_DEBUG:
103				color_pfx = ""; /* normal (black) */
104				color_sfx = "";
105				break;
106		}
107	}
108
109	gettimeofday(&new_time, NULL);
110	if (0 == last_time.tv_sec)
111		last_time = new_time;
112
113	tmp.tv_sec = new_time.tv_sec - last_time.tv_sec;
114	tmp.tv_usec = new_time.tv_usec - last_time.tv_usec;
115	if (tmp.tv_usec < 0)
116	{
117		tmp.tv_sec--;
118		tmp.tv_usec += 1000000;
119	}
120	if (tmp.tv_sec < 100)
121		delta = tmp.tv_sec * 1000000 + tmp.tv_usec;
122	else
123		delta = 99999999;
124
125	last_time = new_time;
126
127	va_start(argptr, fmt);
128	(void)vsnprintf(debug_buffer, sizeof debug_buffer, fmt, argptr);
129	va_end(argptr);
130
131	(void)fprintf(LOG_STREAM, "%s%.8d%s %s%s%s\n", time_pfx, delta, time_sfx,
132		color_pfx, debug_buffer, color_sfx);
133	fflush(LOG_STREAM);
134} /* log_msg */
135
136void log_xxd(const int priority, const char *msg, const unsigned char *buffer,
137	const int len)
138{
139	int i;
140	char *c, debug_buffer[len*3 + strlen(msg) +1];
141	size_t l;
142
143	(void)priority;
144
145	l = strlcpy(debug_buffer, msg, sizeof debug_buffer);
146	c = debug_buffer + l;
147
148	for (i = 0; i < len; ++i)
149	{
150		/* 2 hex characters, 1 space, 1 NUL : total 4 characters */
151		(void)snprintf(c, 4, "%02X ", buffer[i]);
152		c += 3;
153	}
154
155	(void)fprintf(LOG_STREAM, "%s\n", debug_buffer);
156	fflush(LOG_STREAM);
157} /* log_xxd */
158