1 #include "generic_utils.h"
13 void get_timestamp( char buf_25chars[]) {
14 time_t epoch = time(NULL);
15 char* localtime = strdup( ctime( &epoch ) );
16 strcpy( buf_25chars, localtime );
17 buf_25chars[ strlen(localtime)-1] = '\0'; // remove newline
22 inline void* safe_malloc( int size ) {
23 void* ptr = (void*) malloc( size );
25 fatal_handler("safe_malloc(): Out of Memory" );
26 memset( ptr, 0, size );
30 // ---------------------------------------------------------------------------------
31 // Here we define how we want to handle various error levels.
32 // ---------------------------------------------------------------------------------
35 static FILE* log_file = NULL;
36 static int log_level = -1;
37 pthread_mutex_t mutex;
39 void log_free() { if( log_file != NULL ) fclose(log_file ); }
41 void fatal_handler( char* msg, ... ) {
51 if( log_level < LOG_ERROR )
54 pthread_mutex_lock( &(mutex) );
55 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "ERR " );
58 vfprintf(log_file, msg, args);
61 fprintf(log_file, "\n");
63 pthread_mutex_unlock( &(mutex) );
67 /* also log to stderr for ERRORS*/
68 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "ERR " );
70 vfprintf(stderr, msg, args);
72 fprintf( stderr, "\n" );
77 void warning_handler( char* msg, ... ) {
87 if( log_level < LOG_WARNING )
90 pthread_mutex_lock( &(mutex) );
91 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "WARN" );
94 vfprintf(log_file, msg, args);
97 fprintf(log_file, "\n");
99 pthread_mutex_unlock( &(mutex) );
103 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "WARN" );
105 vfprintf(stderr, msg, args);
107 fprintf( stderr, "\n" );
112 void info_handler( char* msg, ... ) {
115 memset( buf, 0, 25 );
116 get_timestamp( buf );
117 pid_t pid = getpid();
122 if( log_level < LOG_INFO )
124 pthread_mutex_lock( &(mutex) );
125 fprintf( log_file, "[%s %d] [%s] ", buf, pid, "INFO" );
128 vfprintf(log_file, msg, args);
131 fprintf(log_file, "\n");
133 pthread_mutex_unlock( &(mutex) );
137 fprintf( stderr, "[%s %d] [%s] ", buf, pid, "INFO" );
139 vfprintf(stderr, msg, args);
141 fprintf( stderr, "\n" );
150 if( log_level != -1 )
154 pthread_mutex_init( &(mutex), NULL );
156 /* load the log level setting if we haven't already */
158 if( conf_reader == NULL ) {
160 //fprintf( stderr, "No config file specified" );
163 char* log_level_str = config_value( "//router/log/level");
164 if( log_level_str == NULL ) {
165 // fprintf( stderr, "No log level specified" );
168 log_level = atoi(log_level_str);
171 /* see if we have a log file yet */
172 char* f = config_value("//router/log/file");
175 // fprintf( stderr, "No log file specified" );
179 log_file = fopen( f, "a" );
180 if( log_file == NULL ) {
181 fprintf( stderr, "Unable to open log file %s for appending\n", f );
191 // ---------------------------------------------------------------------------------
192 // Flesh out a ubiqitous growing string buffer
193 // ---------------------------------------------------------------------------------
195 growing_buffer* buffer_init(int num_initial_bytes) {
197 if( num_initial_bytes > BUFFER_MAX_SIZE ) {
202 size_t len = sizeof(growing_buffer);
204 growing_buffer* gb = (growing_buffer*) safe_malloc(len);
206 gb->n_used = 0;/* nothing stored so far */
207 gb->size = num_initial_bytes;
208 gb->buf = (char *) safe_malloc(gb->size + 1);
213 int buffer_add(growing_buffer* gb, char* data) {
216 if( ! gb || ! data ) { return 0; }
217 int data_len = strlen( data );
219 if( data_len == 0 ) { return 0; }
220 int total_len = data_len + gb->n_used;
222 while( total_len >= gb->size ) {
226 if( gb->size > BUFFER_MAX_SIZE ) {
227 warning_handler( "Buffer reached MAX_SIZE of %d", BUFFER_MAX_SIZE );
232 char* new_data = (char*) safe_malloc( gb->size );
234 strcpy( new_data, gb->buf );
238 strcat( gb->buf, data );
239 gb->n_used = total_len;
244 int buffer_reset( growing_buffer *gb){
245 if( gb == NULL ) { return 0; }
246 if( gb->buf == NULL ) { return 0; }
247 memset( gb->buf, 0, gb->size );
252 int buffer_free( growing_buffer* gb ) {
260 char* buffer_data( growing_buffer *gb) {
261 return strdup( gb->buf );
268 // ---------------------------------------------------------------------------------
270 // ---------------------------------------------------------------------------------
273 // ---------------------------------------------------------------------------------
274 // Allocate and build the conf_reader. This only has to happen once in a given
275 // system. Repeated calls are ignored.
276 // ---------------------------------------------------------------------------------
277 void config_reader_init( char* config_file ) {
278 if( conf_reader == NULL ) {
280 if( config_file == NULL || strlen(config_file) == 0 ) {
281 fatal_handler( "config_reader_init(): No config file specified" );
285 size_t len = sizeof( config_reader );
286 conf_reader = (config_reader*) safe_malloc( len );
288 conf_reader->config_doc = xmlParseFile( config_file );
289 conf_reader->xpathCx = xmlXPathNewContext( conf_reader->config_doc );
290 if( conf_reader->xpathCx == NULL ) {
291 fatal_handler( "config_reader_init(): Unable to create xpath context");
297 char* config_value( const char* xp_query, ... ) {
299 if( conf_reader == NULL || xp_query == NULL ) {
300 fatal_handler( "config_value(): NULL param(s)" );
304 int slen = strlen(xp_query) + 512;/* this is unsafe ... */
305 char xpath_query[ slen ];
306 memset( xpath_query, 0, slen );
308 va_start(va_args, xp_query);
309 vsprintf(xpath_query, xp_query, va_args);
314 int len = strlen(xpath_query) + 100;
315 char alert_buffer[len];
316 memset( alert_buffer, 0, len );
318 // build the xpath object
319 xmlXPathObjectPtr xpathObj = xmlXPathEvalExpression( BAD_CAST xpath_query, conf_reader->xpathCx );
321 if( xpathObj == NULL ) {
322 sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
323 fatal_handler( alert_buffer );
328 if( xpathObj->type == XPATH_NODESET ) {
330 // ----------------------------------------------------------------------------
331 // Grab nodeset from xpath query, then first node, then first text node and
332 // finaly the text node's value
333 // ----------------------------------------------------------------------------
334 xmlNodeSet* node_list = xpathObj->nodesetval;
335 if( node_list == NULL ) {
336 sprintf( alert_buffer, "Could not build xpath object: %s", xpath_query );
337 warning_handler(alert_buffer);
341 if( node_list->nodeNr == 0 ) {
342 sprintf( alert_buffer, "Config XPATH query returned 0 results: %s", xpath_query );
343 warning_handler(alert_buffer);
348 xmlNodePtr element_node = *(node_list)->nodeTab;
349 if( element_node == NULL ) {
350 sprintf( alert_buffer, "Config XPATH query returned 0 results: %s", xpath_query );
351 warning_handler(alert_buffer);
355 xmlNodePtr text_node = element_node->children;
356 if( text_node == NULL ) {
357 sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
358 warning_handler(alert_buffer);
362 val = text_node->content;
364 sprintf( alert_buffer, "Config variable has no value: %s", xpath_query );
365 warning_handler(alert_buffer);
371 sprintf( alert_buffer, "Xpath evaluation failed: %s", xpath_query );
372 warning_handler(alert_buffer);
376 char* value = strdup(val);
377 if( value == NULL ) { fatal_handler( "config_value(): Out of Memory!" ); }
379 // Free XPATH structures
380 if( xpathObj != NULL ) xmlXPathFreeObject( xpathObj );
386 void config_reader_free() {
387 if( conf_reader == NULL ) { return; }
388 xmlXPathFreeContext( conf_reader->xpathCx );
389 xmlFreeDoc( conf_reader->config_doc );