2 Copyright (C) 2002-2005 Thomas Ries <tries@gmx.net>
4 This file is part of Siproxd.
6 Siproxd is free software; you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation; either version 2 of the License, or
9 (at your option) any later version.
11 Siproxd is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
16 You should have received a copy of the GNU General Public License
17 along with Siproxd; if not, write to the Free Software
18 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
36 #include <sys/types.h>
37 #include <sys/socket.h>
38 #include <netinet/in.h>
42 static char const ident[]="$Id: log.c,v 1.18 2005/01/08 10:41:46 hb9xar Exp $";
44 /* module local variables */
45 static int log_to_stderr=0;
46 static int debug_pattern=0;
48 static int debug_listen_port=0;
49 static int debug_listen_fd=0;
50 static int debug_fd=0;
51 static char outbuf[512];
53 * What shall I log to syslog?
54 * 0 - DEBUGs, INFOs, WARNINGs and ERRORs
55 * 1 - INFOs, WARNINGs and ERRORs (this is the default)
56 * 2 - WARNINGs and ERRORs
58 * 4 - absolutely nothing
60 static int silence_level=1;
63 * Mutex for threat synchronization when writing log data
65 * use a 'fast' mutex for synchronizing - as these are portable...
67 static pthread_mutex_t log_mutex = PTHREAD_MUTEX_INITIALIZER;
69 void log_set_pattern(int pattern) {
70 debug_pattern=pattern;
74 int log_get_pattern(void) {
78 void log_set_stderr(int tostdout) {
79 log_to_stderr=tostdout;
83 void log_set_silence(int level) {
91 void log_set_listen_port(int port){
92 debug_listen_port = port;
97 void log_tcp_listen(void) {
98 struct sockaddr_in my_addr;
102 /* disabled in configuration? */
103 if (debug_listen_port == 0) {
108 /* ignore SIGPIPE of lost TCP connection */
109 signal (SIGPIPE, SIG_IGN);
111 memset(&my_addr, 0, sizeof(my_addr));
112 my_addr.sin_family = AF_INET;
113 my_addr.sin_port = htons(debug_listen_port);
115 debug_listen_fd=socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
116 INFO("DEBUG listener on TCP port %i",debug_listen_port);
117 if (debug_listen_fd < 0) {
118 ERROR("socket returned error [%i:%s]",errno, strerror(errno));
122 if (setsockopt(debug_listen_fd, SOL_SOCKET, SO_REUSEADDR, &on , sizeof(on)) < 0) {
123 ERROR("socket returned error [%i:%s]",errno, strerror(errno));
128 sts=bind(debug_listen_fd, (struct sockaddr *)&my_addr, sizeof(my_addr));
130 ERROR("bind returned error [%i:%s]",errno, strerror(errno));
131 close(debug_listen_fd);
136 /* set non-blocking */
137 flags = fcntl(debug_listen_fd, F_GETFL);
139 ERROR("fcntl returned error [%i:%s]",errno, strerror(errno));
140 close(debug_listen_fd);
144 if (fcntl(debug_listen_fd, F_SETFL, (long) flags | O_NONBLOCK) < 0) {
145 ERROR("fcntl returned error [%i:%s]",errno, strerror(errno));
146 close(debug_listen_fd);
151 listen (debug_listen_fd, 1);
155 void log_tcp_connect(void) {
158 struct timeval timeout;
161 if (debug_listen_fd <= 0) return;
167 FD_SET (debug_listen_fd, &fdset);
169 sts=select(debug_listen_fd+1, &fdset, NULL, NULL, &timeout);
172 tmpfd=accept(debug_listen_fd, NULL, NULL);
174 INFO("Rejected DEBUG TCP connection");
176 debug_fd=accept(debug_listen_fd, NULL, NULL);
177 INFO("Accepted DEBUG TCP connection [fd=%i]", debug_fd);
178 INFO(PACKAGE"-"VERSION"-"BUILDSTR" "UNAME);
182 /* check the TCP connection */
188 FD_SET (debug_fd, &fdset);
190 sts=select(debug_fd+1, &fdset, NULL, NULL, &timeout);
193 sts = recv(debug_fd, buf, sizeof(buf), 0);
194 /* got disconnected? */
197 INFO("Disconnected DEBUG TCP connection [fd=%i]", debug_fd);
206 /* for all the LOGGING routines:
207 They should figure out if we are running as a daemon, then write
208 their stuff to syslog or something like that
212 void log_debug(int class, char *file, int line, const char *format, ...) {
218 if ((debug_pattern & class) == 0) return;
220 va_start(ap, format);
222 pthread_mutex_lock(&log_mutex);
224 * DEBUG output is either STDOUT or SYSLOG, but not both
227 /* not running as daemon - log to STDERR */
230 fprintf(stderr,"%2.2i:%2.2i:%2.2i %s:%i ", tim->tm_hour,
231 tim->tm_min, tim->tm_sec, file, line);
232 vfprintf(stderr, format, ap);
233 fprintf(stderr,"\n");
235 } else if (silence_level < 1) {
236 /* running as daemon - log via SYSLOG facility */
237 vsnprintf(string, sizeof(string), format, ap);
238 syslog(LOG_USER|LOG_DEBUG, "%s:%i %s", file, line, string);
244 /* log to TCP socket */
247 snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i %s:%i ",
248 tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
249 write(debug_fd, outbuf, strlen(outbuf));
250 vsnprintf(outbuf, sizeof(outbuf) , format, ap);
251 write(debug_fd, outbuf, strlen(outbuf));
252 snprintf(outbuf, sizeof(outbuf) ,"\n");
253 write(debug_fd, outbuf, strlen(outbuf));
255 pthread_mutex_unlock(&log_mutex);
263 void log_error(char *file, int line, const char *format, ...) {
269 va_start(ap, format);
271 pthread_mutex_lock(&log_mutex);
273 * INFO, WARN, ERROR output is always to syslog and if not daemonized
277 /* not running as daemon - log to STDERR */
280 fprintf(stderr,"%2.2i:%2.2i:%2.2i ERROR:%s:%i ",tim->tm_hour,
281 tim->tm_min, tim->tm_sec, file, line);
282 vfprintf(stderr, format, ap);
283 fprintf(stderr,"\n");
286 if (silence_level < 4) {
287 /* running as daemon - log via SYSLOG facility */
288 vsnprintf(string, sizeof(string), format, ap);
289 syslog(LOG_USER|LOG_WARNING, "%s:%i ERROR:%s", file, line, string);
295 /* log to TCP socket */
298 snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i ERROR:%s:%i ",
299 tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
300 write(debug_fd, outbuf, strlen(outbuf));
301 vsnprintf(outbuf, sizeof(outbuf) , format, ap);
302 write(debug_fd, outbuf, strlen(outbuf));
303 snprintf(outbuf, sizeof(outbuf) ,"\n");
304 write(debug_fd, outbuf, strlen(outbuf));
306 pthread_mutex_unlock(&log_mutex);
314 void log_warn(char *file, int line, const char *format, ...) {
320 va_start(ap, format);
322 pthread_mutex_lock(&log_mutex);
324 * INFO, WARN, ERROR output is always to syslog and if not daemonized
328 /* not running as daemon - log to STDERR */
331 fprintf(stderr,"%2.2i:%2.2i:%2.2i WARNING:%s:%i ",tim->tm_hour,
332 tim->tm_min, tim->tm_sec,file,line);
333 vfprintf(stderr, format, ap);
334 fprintf(stderr,"\n");
337 if (silence_level < 3) {
338 /* running as daemon - log via SYSLOG facility */
339 vsnprintf(string, sizeof(string), format, ap);
340 syslog(LOG_USER|LOG_NOTICE, "%s:%i WARNING:%s", file, line, string);
346 /* log to TCP socket */
349 snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i WARNING:%s:%i ",
350 tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
351 write(debug_fd, outbuf, strlen(outbuf));
352 vsnprintf(outbuf, sizeof(outbuf) , format, ap);
353 write(debug_fd, outbuf, strlen(outbuf));
354 snprintf(outbuf, sizeof(outbuf) ,"\n");
355 write(debug_fd, outbuf, strlen(outbuf));
357 pthread_mutex_unlock(&log_mutex);
365 void log_info(char *file, int line, const char *format, ...) {
371 va_start(ap, format);
373 pthread_mutex_lock(&log_mutex);
375 * INFO, WARN, ERROR output is always to syslog and if not daemonized
379 /* not running as daemon - log to STDERR */
382 fprintf(stderr,"%2.2i:%2.2i:%2.2i INFO:%s:%i ",tim->tm_hour,
383 tim->tm_min, tim->tm_sec,file,line);
384 vfprintf(stderr, format, ap);
385 fprintf(stderr,"\n");
388 if (silence_level < 2) {
389 /* running as daemon - log via SYSLOG facility */
390 vsnprintf(string, sizeof(string), format, ap);
391 syslog(LOG_USER|LOG_NOTICE, "%s:%i INFO:%s", file, line, string);
397 /* log to TCP socket */
400 snprintf(outbuf, sizeof(outbuf) ,"%2.2i:%2.2i:%2.2i INFO:%s:%i ",
401 tim->tm_hour, tim->tm_min, tim->tm_sec, file, line);
402 write(debug_fd, outbuf, strlen(outbuf));
403 vsnprintf(outbuf, sizeof(outbuf) , format, ap);
404 write(debug_fd, outbuf, strlen(outbuf));
405 snprintf(outbuf, sizeof(outbuf) ,"\n");
406 write(debug_fd, outbuf, strlen(outbuf));
408 pthread_mutex_unlock(&log_mutex);
416 void log_dump_buffer(int class, char *file, int line,
417 char *buffer, int length) {
419 char tmp[8], tmplin1[80], tmplin2[80];
421 if ((debug_pattern & class) == 0) return;
422 if ((!log_to_stderr) && (debug_fd <= 0)) return;
424 pthread_mutex_lock(&log_mutex);
425 if (log_to_stderr) fprintf(stderr, "---BUFFER DUMP follows---\n");
427 snprintf(outbuf, sizeof(outbuf) ,"---BUFFER DUMP follows---\n");
428 write(debug_fd, outbuf, strlen(outbuf));
431 for (i=0; i<length; i+=16) {
434 for (j=0;(j<16) && (i+j)<length ;j++) {
435 sprintf(tmp,"%2.2x ",(unsigned char)buffer[i+j]);
436 strcat(tmplin1, tmp);
437 sprintf(tmp, "%c",(isprint((int)buffer[i+j]))? buffer[i+j]: '.');
438 strcat(tmplin2, tmp);
441 fprintf(stderr, " %-47.47s %-16.16s\n",tmplin1, tmplin2);
444 snprintf(outbuf, sizeof(outbuf) ," %-47.47s %-16.16s\n",
446 write(debug_fd, outbuf, strlen(outbuf));
451 fprintf(stderr,"\n---end of BUFFER DUMP---\n");
455 snprintf(outbuf, sizeof(outbuf) ,"---end of BUFFER DUMP---\n");
456 write(debug_fd, outbuf, strlen(outbuf));
458 pthread_mutex_unlock(&log_mutex);