2 #include <stdarg.h> // va-args
3 #include <stdlib.h> // malloc/free
4 #include <string.h> // strdup
6 #include "pnd_logger.h"
8 static char *log_pretext = NULL;
9 static unsigned char log_filterlevel = 0;
10 static unsigned char log_flushafter = 0;
11 static time_t log_first = 0;
24 pnd_log_callback_f callback;
29 static pnd_log_target_t log_targets [ PND_LOG_MAX ]; // implicitly nil
31 static int pnd_log_empty_slot ( void ) {
34 for ( i = 0; i < PND_LOG_MAX; i++ ) {
35 if ( log_targets [ i ].type == pndl_nil ) {
43 unsigned char pnd_log_set_filter ( unsigned char newlevel ) {
44 unsigned char foo = log_filterlevel;
45 log_filterlevel = newlevel;
49 unsigned char pnd_log_get_filter ( void ) {
50 return ( log_filterlevel );
53 void pnd_log_set_flush ( unsigned char x ) {
58 void pnd_log_set_pretext ( char *pre ) {
66 log_pretext = strdup ( pre );
72 void pnd_log_to_nil ( void ) {
73 memset ( log_targets, '\0', sizeof(pnd_log_target_t) * PND_LOG_MAX );
77 unsigned char pnd_log_to_stream ( FILE *f ) {
78 int i = pnd_log_empty_slot();
81 return ( 0 ); // fail!
84 log_targets [ i ].type = pndl_stream;
85 log_targets [ i ].stream = f;
90 unsigned char pnd_log_to_syslog ( char *facility ) {
94 unsigned char pnd_log_to_callback ( pnd_log_callback_f f, void *userdata ) {
98 unsigned char pnd_log_to_stdout ( void ) {
99 return ( pnd_log_to_stream ( stdout ) );
102 unsigned char pnd_log_to_stderr ( void ) {
103 return ( pnd_log_to_stream ( stderr ) );
106 unsigned char pnd_log_max_targets ( void ) {
107 return ( PND_LOG_MAX );
110 static void pnd_log_emit ( unsigned char level, char *message ) {
113 // iterate across targets and attempt to emit
114 for ( i = 0; i < PND_LOG_MAX; i++ ) {
116 switch ( log_targets [ i ].type ) {
125 fprintf ( log_targets [ i ].stream, "%s ", log_pretext );
128 fprintf ( log_targets [ i ].stream, "%u %u\t", level, (unsigned int) (time ( NULL ) - log_first) );
131 fprintf ( log_targets [ i ].stream, "%s", message );
132 if ( strchr ( message, '\n' ) == NULL ) {
133 fprintf ( log_targets [ i ].stream, "\n" );
135 if ( log_flushafter ) {
136 fflush ( log_targets [ i ].stream );
156 unsigned char pnd_log ( unsigned char level, char *fmt, ... ) {
158 if ( log_first == 0 ) {
159 log_first = time ( NULL );
162 if ( level == PND_LOG_FORCE ) {
164 } else if ( level < log_filterlevel ) {
165 return ( 0 ); // too low level
168 // format the actual log string
173 if ( ( p = malloc ( size ) ) == NULL ) {
174 return ( 0 ); // fail!
179 /* Try to print in the allocated space. */
180 va_start ( ap, fmt );
181 n = vsnprintf ( p, size, fmt, ap );
184 /* If that worked, return the string. */
185 if ( n > -1 && n < size ) {
186 pnd_log_emit ( level, p );
190 /* Else try again with more space. */
191 if ( n > -1 ) /* glibc 2.1 */
192 size = n + 1; /* precisely what is needed */
194 size *= 2; /* twice the old size */
195 if ( ( np = realloc ( p, size ) ) == NULL ) {
197 return ( 0 ); // fail!
212 static unsigned char _do_buried_logging = 0;
213 void pnd_log_set_buried_logging ( unsigned char yesno ) {
214 _do_buried_logging = yesno;
218 unsigned char pnd_log_do_buried_logging ( void ) {
219 if ( _do_buried_logging == 1 ) {