1 /*
2  * Copyright (C) 2004 Nathan Lutchansky <lutchann@litech.org>
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 2 of the License, or
7  * (at your option) 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, write to the Free Software Foundation,
16  * Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
17  */
18 
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <stdarg.h>
23 #include <time.h>
24 #include <pthread.h>
25 
26 #define LOG_BUFFER_SIZE		4096
27 
28 static int spookpid, minlevel;
29 static const char *month[] = {	"Jan", "Feb", "Mar", "Apr", "May", "Jun",
30 				"Jul", "Aug", "Sep", "Oct", "Nov", "Dec" };
31 static char *rb_data;
32 static int rb_in, rb_out, rb_size;
33 static pthread_mutex_t log_mutex;
34 
spook_log_init(int min)35 int spook_log_init( int min )
36 {
37 	pthread_mutex_init( &log_mutex, NULL );
38 	spookpid = getpid();
39 	minlevel = min;
40 	rb_in = 0;
41 	rb_out = 0;
42 	rb_size = LOG_BUFFER_SIZE;
43 	rb_data = (char *)malloc( rb_size );
44 	return 0;
45 }
46 
spook_log(int level,char * fmt,...)47 void spook_log( int level, char *fmt, ... )
48 {
49 	va_list ap;
50 	char newfmt[512], line[1024];
51 	struct tm tm;
52 	time_t t;
53 	int i, len, overwrite = 0;
54 
55 	va_start( ap, fmt );
56 	if( level < minlevel )
57 	{
58 		va_end( ap );
59 		return;
60 	}
61 	time( &t );
62 	localtime_r( &t, &tm );
63 	sprintf( newfmt, "%s %2d %02d:%02d:%02d spook[%d]: %s\n",
64 			month[tm.tm_mon], tm.tm_mday,
65 			tm.tm_hour, tm.tm_min, tm.tm_sec,
66 			spookpid, fmt );
67 	len = vsnprintf( line, sizeof( line ), newfmt, ap );
68 	va_end( ap );
69 	fputs( line, stderr );
70 	pthread_mutex_lock( &log_mutex );
71 	for( i = 0; i < len; ++i )
72 	{
73 		rb_data[rb_in++] = line[i];
74 		if( rb_in == rb_size ) rb_in = 0;
75 		if( rb_in == rb_out ) overwrite = 1;
76 	}
77 	if( overwrite )
78 	{
79 		rb_out = rb_in;
80 		while( rb_data[rb_out] != '\n' )
81 			if( ++rb_out == rb_size ) rb_out = 0;
82 		if( ++rb_out == rb_size ) rb_out = 0;
83 	}
84 	pthread_mutex_unlock( &log_mutex );
85 }
86 
send_log_buffer(int fd)87 void send_log_buffer( int fd )
88 {
89 	pthread_mutex_lock( &log_mutex );
90 	if( rb_in < rb_out )
91 	{
92 		write( fd, rb_data + rb_out, rb_size - rb_out );
93 		write( fd, rb_data, rb_in );
94 	} else if( rb_in > rb_out )
95 		write( fd, rb_data + rb_out, rb_in - rb_out );
96 	pthread_mutex_unlock( &log_mutex );
97 }
98