1 /* This file is part of gacopyz.
2    Copyright (C) 2006-2021 Sergey Poznyakoff
3 
4    This program is free software; you can redistribute it and/or modify
5    it under the terms of the GNU General Public License as published by
6    the Free Software Foundation; either version 3, or (at your option)
7    any later version.
8 
9    This program is distributed in the hope that it will be useful,
10    but WITHOUT ANY WARRANTY; without even the implied warranty of
11    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12    GNU General Public License for more details.
13 
14    You should have received a copy of the GNU General Public License
15    along with this program.  If not, see <http://www.gnu.org/licenses/>. */
16 
17 #include <gacopyz_priv.h>
18 
19 void (*__gacopyz_log_printer)(int, char *, va_list) =
20        gacopyz_syslog_log_printer;
21 
22 /* Logging */
23 void
gacopyz_syslog_log_printer(int level,char * fmt,va_list ap)24 gacopyz_syslog_log_printer(int level, char *fmt, va_list ap)
25 {
26 	switch (level) {
27 	case SMI_LOG_PROTO:
28 	case SMI_LOG_DEBUG:
29 		level = LOG_DEBUG;
30 		break;
31 	case SMI_LOG_INFO:
32 		level = LOG_INFO;
33 		break;
34 	case SMI_LOG_WARN:
35 		level = LOG_WARNING;
36 		break;
37 	case SMI_LOG_ERR:
38 		level = LOG_ERR;
39 		break;
40 
41 	case SMI_LOG_FATAL:
42 	default:
43 		level = LOG_EMERG;
44 	}
45 	vsyslog(level, fmt, ap); /* FIXME: if absent? */
46 }
47 
48 static char *level_name[] = {
49 	"PROTO",
50 	"DEBUG",
51 	"INFO",
52 	"WARN",
53 	"ERR",
54 	"FATAL"
55 };
56 
57 int
gacopyz_string_to_log_level(const char * str)58 gacopyz_string_to_log_level(const char *str)
59 {
60 	int i;
61 	for (i = 0; i < sizeof level_name / sizeof level_name[0]; i++)
62 		if (strcasecmp (str, level_name[i]) == 0)
63 			return i;
64 	return -1;
65 }
66 
67 const char *
gacopyz_log_level_to_string(int level)68 gacopyz_log_level_to_string(int level)
69 {
70 	if (level < 0 || level > sizeof level_name / sizeof level_name[0])
71 		return NULL;
72 	return level_name[level];
73 }
74 
75 void
gacopyz_stderr_log_printer(int level,char * fmt,va_list ap)76 gacopyz_stderr_log_printer(int level, char *fmt, va_list ap)
77 {
78 	fprintf(stderr, "Gacopyz %s: ", gacopyz_log_level_to_string(level));
79 	vfprintf(stderr, fmt, ap);
80 	fprintf(stderr, "\n");
81 }
82 
83 
84 void
gacopyz_log(int level,char * fmt,...)85 gacopyz_log(int level, char *fmt, ...)
86 {
87 	va_list ap;
88 	va_start(ap, fmt);
89 	__gacopyz_log_printer(level, fmt, ap);
90 	va_end(ap);
91 }
92 
93 void
gacopyz_io_log(gacopyz_iod_t iod,int level,char * fmt,...)94 gacopyz_io_log(gacopyz_iod_t iod, int level, char *fmt, ...)
95 {
96 	if (iod->logmask & SMI_LOG_MASK(level)) {
97 		va_list ap;
98 		va_start(ap, fmt);
99 		__gacopyz_log_printer(level, fmt, ap);
100 		va_end(ap);
101 	}
102 }
103 
104 size_t
gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE],const char * buf,size_t size)105 gacopyz_format_vbuf(char vbuf[GACOPYZ_VBUFSIZE], const char *buf, size_t size)
106 {
107 	char *p = vbuf;
108 	char *q = vbuf + 51;
109 	int i;
110 	size_t j = 0;
111 
112 	for (i = 0; i < 16; i++) {
113 		unsigned c;
114 		if (j < size) {
115 			c = *(const unsigned char*)buf++;
116 			j++;
117 		} else
118 			c = 0;
119 		sprintf(p, "%02X ", c);
120 		p += 3;
121 		*q++ = isprint(c) ? c : '.';
122 		if (i == 7) {
123 			*p++ = ' ';
124 			*q++ = ' ';
125 		}
126 	}
127 	*p++ = ' ';
128 	*p = ' ';
129 	*q = 0;
130 	return j;
131 }
132 
133 void
gacopyz_logdump(int level,const char * pfx,const char * buf,size_t size)134 gacopyz_logdump(int level, const char *pfx, const char *buf, size_t size)
135 {
136 	char vbuf[GACOPYZ_VBUFSIZE];
137 
138 	while (size) {
139 		size_t rd = gacopyz_format_vbuf(vbuf, buf, size);
140 		gacopyz_log(level, "%s: %s", pfx, vbuf);
141 		size -= rd;
142 		buf += rd;
143 	}
144 }
145 
146 void
gacopyz_io_logdump(gacopyz_iod_t iod,const char * pfx,const char * buf,size_t size)147 gacopyz_io_logdump(gacopyz_iod_t iod, const char *pfx,
148 		   const char *buf, size_t size)
149 {
150 	if (iod->logmask & SMI_LOG_MASK(SMI_LOG_PROTO))
151 		gacopyz_logdump(SMI_LOG_PROTO, pfx, buf, size);
152 	else if (iod->logmask & SMI_LOG_MASK(SMI_LOG_DEBUG))
153 		gacopyz_log(SMI_LOG_DEBUG, "%s", pfx);
154 }
155 
156 void
gacopyz_set_logger(void (* logger)(int,char *,va_list))157 gacopyz_set_logger(void (*logger)(int, char *, va_list))
158 {
159 	__gacopyz_log_printer = logger;
160 }
161