diff options
-rw-r--r-- | daemon/conf.c | 134 | ||||
-rw-r--r-- | daemon/logrotate.c | 31 | ||||
-rw-r--r-- | daemon/syslogd.c | 16 | ||||
-rw-r--r-- | daemon/syslogd.h | 112 | ||||
-rw-r--r-- | daemon/writer.c | 81 |
5 files changed, 238 insertions, 136 deletions
diff --git a/daemon/conf.c b/daemon/conf.c index 0166712..9dfb248 100644 --- a/daemon/conf.c +++ b/daemon/conf.c @@ -123,90 +123,140 @@ static void create_source( int line_number, } /****************************************************************************** - * create_destination + * init_file_dest * * read attributes of element, initialize destination structure and append * it to the list of destinations */ -static void create_destination( int line_number, +static gboolean init_file_dest( struct destination *dest, + int line_number, const gchar** attribute_names, const gchar** attribute_values ) { const gchar *aname; - struct destination *dest = g_malloc0( sizeof(struct destination) ); - /* at first, we must determine de*/ for( ; (aname = *attribute_names) != NULL; attribute_names++, attribute_values++ ) { const gchar *aval = *attribute_values; - if( strcmp( aname, "name" ) == 0 ) - dest->name = g_locale_from_utf8( aval, -1, NULL, NULL, NULL ); - else if( strcmp( aname, "file" ) == 0 ) - dest->file = normalize_pathname( aval ); + if( strcmp( aname, "file" ) == 0 ) + dest->u.file.name_pattern = normalize_pathname( aval ); else if( strcmp( aname, "rotate" ) == 0 ) { if( strcmp( aval, "daily" ) == 0 ) - dest->rotate = RP_DAILY; + dest->u.file.rotate = RP_DAILY; else if( strcmp( aval, "weekly" ) == 0 ) - dest->rotate = RP_WEEKLY; + dest->u.file.rotate = RP_WEEKLY; else if( strcmp( aval, "monthly" ) == 0 ) - dest->rotate = RP_MONTHLY; + dest->u.file.rotate = RP_MONTHLY; else { ERR( "Invalid rotation period at line %d\n", line_number ); - dest->rotate = RP_INVALID; + dest->u.file.rotate = RP_INVALID; } } else if( strcmp( aname, "size" ) == 0 ) { char *endptr; - dest->size = strtoul( aval, &endptr, 0 ); + dest->u.file.size = strtoul( aval, &endptr, 0 ); if( 'k' == *endptr ) - dest->size *= 1024; + dest->u.file.size *= 1024; else if( 'M' == *endptr ) - dest->size *= 1024 * 1024; + dest->u.file.size *= 1024 * 1024; } else if( strcmp( aname, "backlogs" ) == 0 ) - dest->backlogs = strtoul( aval, NULL, 0 ); + dest->u.file.backlogs = strtoul( aval, NULL, 0 ); else if( strcmp( aname, "ifempty" ) == 0 ) { if( strcmp( aval, "yes" ) == 0 ) - dest->ifempty = TRUE; + dest->u.file.ifempty = TRUE; else if( strcmp( aval, "no" ) == 0 ) - dest->ifempty = FALSE; + dest->u.file.ifempty = FALSE; else { - dest->ifempty = TRUE; + dest->u.file.ifempty = TRUE; ERR( "Invalid value \"%s\" of attribute \"%s\" at line %d; assumed \"yes\"\n", aval, aname, line_number ); } } else if( strcmp( aname, "olddir" ) == 0 ) - dest->olddir = normalize_pathname( aval ); + dest->u.file.olddir = normalize_pathname( aval ); else if( strcmp( aname, "compresscmd" ) == 0 ) - dest->compresscmd = g_locale_from_utf8( aval, -1, NULL, NULL, NULL ); + dest->u.file.compresscmd = g_locale_from_utf8( aval, -1, NULL, NULL, NULL ); else if( strcmp( aname, "compressoptions" ) == 0 ) - dest->compressoptions = g_locale_from_utf8( aval, -1, NULL, NULL, NULL ); + dest->u.file.compressoptions = g_locale_from_utf8( aval, -1, NULL, NULL, NULL ); } - if( !dest->name ) - ERR( "Undefined destination name at line %d\n", line_number ); - if( !dest->file ) + if( !dest->u.file.name_pattern ) ERR( "Undefined destination file at line %d\n", line_number ); - if( (!dest->name) || (!dest->file) || RP_INVALID == dest->rotate ) + if( (!dest->u.file.name_pattern) || RP_INVALID == dest->u.file.rotate ) { - if( dest->name ) g_free( dest->name ); - if( dest->file ) g_free( dest->file ); - if( dest->olddir ) g_free( dest->olddir ); - if( dest->compresscmd ) g_free( dest->compresscmd ); - if( dest->compressoptions ) g_free( dest->compressoptions ); + if( dest->u.file.name_pattern ) g_free( dest->u.file.name_pattern ); + if( dest->u.file.olddir ) g_free( dest->u.file.olddir ); + if( dest->u.file.compresscmd ) g_free( dest->u.file.compresscmd ); + if( dest->u.file.compressoptions ) g_free( dest->u.file.compressoptions ); + return FALSE; + } + + if( dest->u.file.compresscmd && !dest->u.file.compressoptions ) + dest->u.file.compressoptions = g_strdup( "$PATHNAME" ); + + return init_destination_file( dest ); +} + +/****************************************************************************** + * create_destination + * + * read attributes of element, initialize destination structure and append + * it to the list of destinations + */ +static void create_destination( int line_number, + const gchar** attribute_names, + const gchar** attribute_values ) +{ + gboolean r = FALSE; + const gchar *aname; + struct destination *dest = g_malloc0( sizeof(struct destination) ); + + /* at first, we must determine destination type for selection of type-specific + structure that we'll fill later; + also, look for 'name' attribute and set the name of destination */ + dest->type = DT_UNDEFINED; + for( ; (aname = *attribute_names) != NULL; attribute_names++, attribute_values++ ) + { + const gchar *aval = *attribute_values; + + if( strcmp( aname, "name" ) == 0 ) + dest->name = g_locale_from_utf8( aval, -1, NULL, NULL, NULL ); + else if( strcmp( aname, "file" ) == 0 ) + { + dest->type = DT_FILE; + break; + } + } + if( !dest->name ) + { + ERR( "Undefined destination name at line %d\n", line_number ); g_free( dest ); return; } - if( dest->compresscmd && !dest->compressoptions ) - dest->compressoptions = g_strdup( "$PATHNAME" ); - dest->file_writers = NULL; - InitializeCriticalSection( &dest->cs_file_writers ); + switch( dest->type ) + { + case DT_FILE: + r = init_file_dest( dest, line_number, attribute_names, attribute_values ); + break; + + default: + ERR( "Undefined destination type at line %d\n", line_number ); + break; + } + + if( !r ) + { + /* FIXME: call fini method? */ + g_free( dest->name ); + g_free( dest ); + return; + } destinations = g_list_append( destinations, dest ); } @@ -687,14 +737,14 @@ static void dump_configuration() TRACE( "\tname=%s\tfile=%s\n" "\t\trotate=%s size=%d backlogs=%d ifempty=%s\n" "\t\tolddir=%s compresscmd=%s\n", - d->name, d->file, - (d->rotate == RP_DAILY)? "daily" - : (d->rotate == RP_WEEKLY)? "weekly" - : (d->rotate == RP_MONTHLY)? "monthly" + d->name, d->u.file.name_pattern, + (d->u.file.rotate == RP_DAILY)? "daily" + : (d->u.file.rotate == RP_WEEKLY)? "weekly" + : (d->u.file.rotate == RP_MONTHLY)? "monthly" : "undefined", - d->size, d->backlogs, d->ifempty? "yes" : "no", - d->olddir? d->olddir : "NULL", - d->compresscmd? d->compresscmd : "NULL" ); + d->u.file.size, d->u.file.backlogs, d->u.file.ifempty? "yes" : "no", + d->u.file.olddir? d->u.file.olddir : "NULL", + d->u.file.compresscmd? d->u.file.compresscmd : "NULL" ); } TRACE( "Filters:\n" ); for( item = filters; item; item = item->next ) diff --git a/daemon/logrotate.c b/daemon/logrotate.c index d759f10..fdd20d5 100644 --- a/daemon/logrotate.c +++ b/daemon/logrotate.c @@ -133,16 +133,16 @@ static void do_rotate( const gchar* pathname, struct destination* destination ) TRACE_ENTER( "\n" ); /* construct destination pathname for backlogs */ - if( destination->olddir ) + if( destination->u.file.olddir ) { gchar *filename = g_path_get_basename( pathname ); - if( g_path_is_absolute( destination->olddir ) ) - dest_pathname = g_build_filename( destination->olddir, filename, NULL ); + if( g_path_is_absolute( destination->u.file.olddir ) ) + dest_pathname = g_build_filename( destination->u.file.olddir, filename, NULL ); else { gchar *prefix = g_path_get_dirname( __argv[0] ); - dest_pathname = g_build_filename( prefix, destination->olddir, filename, NULL ); + dest_pathname = g_build_filename( prefix, destination->u.file.olddir, filename, NULL ); g_free( prefix ); } g_free( filename ); @@ -151,12 +151,12 @@ static void do_rotate( const gchar* pathname, struct destination* destination ) dest_pathname = g_strdup( pathname ); /* remove earliest backlog */ - backlog = g_strdup_printf( "%s.%d", dest_pathname, destination->backlogs ); + backlog = g_strdup_printf( "%s.%d", dest_pathname, destination->u.file.backlogs ); DeleteFile( backlog ); g_free( backlog ); /* rotate backlogs */ - for( i = destination->backlogs; i > 1; i-- ) + for( i = destination->u.file.backlogs; i > 1; i-- ) { gchar *old_backlog = g_strdup_printf( "%s.%d", dest_pathname, i - 1 ); gchar *new_backlog = g_strdup_printf( "%s.%d", dest_pathname, i ); @@ -178,9 +178,10 @@ static void do_rotate( const gchar* pathname, struct destination* destination ) ERR( "Can't move %s to %s; error %lu\n", pathname, backlog, GetLastError() ); /* compress new backlog */ - if( destination->compresscmd ) + if( destination->u.file.compresscmd ) { - if( compress_backlog( destination->compresscmd, destination->compressoptions, backlog ) ) + if( compress_backlog( destination->u.file.compresscmd, + destination->u.file.compressoptions, backlog ) ) /* remove original uncompressed file */ DeleteFile( backlog ); } @@ -203,8 +204,8 @@ void rotate_logfile( const gchar* pathname, struct destination* destination ) TRACE_ENTER( "pathname=%s\n", pathname ); - if( 0 == destination->backlogs - || (RP_UNDEFINED == destination->rotate && 0 == destination->size) ) + if( 0 == destination->u.file.backlogs + || (RP_UNDEFINED == destination->u.file.rotate && 0 == destination->u.file.size) ) { TRACE_LEAVE( "no conditions for rotation\n" ); return; @@ -217,21 +218,21 @@ void rotate_logfile( const gchar* pathname, struct destination* destination ) goto done; } - if( destination->size ) + if( destination->u.file.size ) { - if( fst.st_size > destination->size ) + if( fst.st_size > destination->u.file.size ) { do_rotate( pathname, destination ); rotated = TRUE; goto done; } - TRACE_2( "checked size: file=%d, max=%d\n", fst.st_size, destination->size ); + TRACE_2( "checked size: file=%d, max=%d\n", fst.st_size, destination->u.file.size ); } current_time = time(NULL); tm = gmtime( ¤t_time ); TRACE_2( "checking time: creation=%d, modification=%d\n", fst.st_ctime, fst.st_mtime ); - switch( destination->rotate ) + switch( destination->u.file.rotate ) { case RP_DAILY: if( fst.st_mtime - (fst.st_ctime - fst.st_ctime % (24 * 3600)) > 24 * 3600 ) @@ -256,7 +257,7 @@ void rotate_logfile( const gchar* pathname, struct destination* destination ) goto done; } - if( fst.st_size || destination->ifempty ) + if( fst.st_size || destination->u.file.ifempty ) { do_rotate( pathname, destination ); rotated = TRUE; diff --git a/daemon/syslogd.c b/daemon/syslogd.c index 59ede6d..8d9f906 100644 --- a/daemon/syslogd.c +++ b/daemon/syslogd.c @@ -165,7 +165,7 @@ static void mux_message( struct message* msg ) if( !filter_message( msg, logpath->filter ) ) continue; - write_message( msg, logpath->destination ); + logpath->destination->put( logpath->destination, msg ); } release_message( msg ); @@ -495,6 +495,18 @@ static unsigned __stdcall message_processor( void* arg ) } /****************************************************************************** + * fini_destinations + * + * for each destination call fini method + */ +static void fini_destinations() +{ + GList *dest; + for( dest = destinations; dest; dest = dest->next ) + ((struct destination*) dest)->fini( (struct destination*) dest ); +} + +/****************************************************************************** * main syslogd function * * global initialization; invoke listener @@ -584,7 +596,7 @@ done: CloseHandle( message_processor_thread ); } - fini_writer(); + fini_destinations(); fini_purger(); free_hostnames(); diff --git a/daemon/syslogd.h b/daemon/syslogd.h index 65dc042..8919ede 100644 --- a/daemon/syslogd.h +++ b/daemon/syslogd.h @@ -51,6 +51,43 @@ extern gchar *mark_message; extern int hold; extern gchar *logdir; +/* listener */ +enum listener_status +{ + LSNR_ERROR, + LSNR_SHUTDOWN, + LSNR_GOT_MESSAGE +}; + +struct raw_message +{ + gchar *msg; + struct sockaddr_in sender_addr; + struct source *source; +}; + +extern gboolean init_listener(); +extern void fini_listener(); +extern enum listener_status listener( struct raw_message** msg ); +extern void log_internal( int pri, char* fmt, ... ); + +/* message */ +struct message +{ + LONG refcount; + struct source *source; + gchar *sender; + int facility; + int priority; + gchar *timestamp; + gchar *hostname; + gchar *program; + gchar *message; +}; + +extern void reference_message( struct message* msg ); +extern void release_message( struct message* msg ); + /* sources, destinations, filters and logpaths */ enum source_type { @@ -66,6 +103,12 @@ struct source struct sockaddr_in udp; }; +enum destination_type +{ + DT_UNDEFINED, + DT_FILE +}; + enum rotation_period { RP_UNDEFINED = 0, @@ -75,12 +118,9 @@ enum rotation_period RP_MONTHLY }; -struct destination +struct destination_file { - gchar *name; - gchar *file; - GList *file_writers; - CRITICAL_SECTION cs_file_writers; + gchar *name_pattern; enum rotation_period rotate; int size; int backlogs; @@ -90,6 +130,25 @@ struct destination gchar *compressoptions; }; +struct destination; + +typedef void (*dest_put)( struct destination* destination, struct message* message ); +typedef void (*dest_finalize)( struct destination* destination ); + +struct destination +{ + gchar *name; + enum destination_type type; + union + { + struct destination_file file; + } u; + void *extra; + /* methods */ + dest_put put; + dest_finalize fini; +}; + struct filter { gchar *name; @@ -111,6 +170,8 @@ extern GList *logpaths; extern gboolean read_configuration(); +extern gboolean init_destination_file( struct destination* destination ); + /* queue */ struct fifo_item { @@ -129,47 +190,6 @@ extern void fifo_destroy( struct fifo* queue ); extern void fifo_push( struct fifo* queue, void* data ); extern void* fifo_pop( struct fifo* queue ); -/* listener */ -enum listener_status -{ - LSNR_ERROR, - LSNR_SHUTDOWN, - LSNR_GOT_MESSAGE -}; - -struct raw_message -{ - gchar *msg; - struct sockaddr_in sender_addr; - struct source *source; -}; - -extern gboolean init_listener(); -extern void fini_listener(); -extern enum listener_status listener( struct raw_message** msg ); -extern void log_internal( int pri, char* fmt, ... ); - -/* message */ -struct message -{ - LONG refcount; - struct source *source; - gchar *sender; - int facility; - int priority; - gchar *timestamp; - gchar *hostname; - gchar *program; - gchar *message; -}; - -extern void reference_message( struct message* msg ); -extern void release_message( struct message* msg ); - -/* writer */ -extern void fini_writer(); -extern void write_message( struct message* msg, struct destination* destination ); - /* logrotate */ extern void rotate_logfile( const gchar* pathname, struct destination* destination ); diff --git a/daemon/writer.c b/daemon/writer.c index e05a2c8..7761bbc 100644 --- a/daemon/writer.c +++ b/daemon/writer.c @@ -47,6 +47,12 @@ struct file_writer time_t max_hold; }; +struct dest_extra +{ + GList *file_writers; + CRITICAL_SECTION cs_file_writers; +}; + /* forward declarations */ static unsigned __stdcall writer_thread_proc( void* arg ); @@ -284,15 +290,18 @@ error: */ static void detach_writer_from_destination( struct file_writer* writer ) { + struct dest_extra *extra; + TRACE_ENTER( "%p\n", writer ); if( !writer->destination ) { TRACE_LEAVE( "done; already detached\n" ); return; } - EnterCriticalSection( &writer->destination->cs_file_writers ); - writer->destination->file_writers = g_list_remove( writer->destination->file_writers, writer ); - LeaveCriticalSection( &writer->destination->cs_file_writers ); + extra = writer->destination->extra; + EnterCriticalSection( &extra->cs_file_writers ); + extra->file_writers = g_list_remove( extra->file_writers, writer ); + LeaveCriticalSection( &extra->cs_file_writers ); writer->destination = NULL; TRACE_LEAVE( "done\n" ); } @@ -429,19 +438,20 @@ static void make_file_name( char* pattern, struct message* message, char* buffer } /****************************************************************************** - * write_message + * put_message_to_file_dest */ -void write_message( struct message* msg, struct destination* destination ) +static void put_message_to_file_dest( struct destination* destination, struct message* msg ) { + struct dest_extra *extra = destination->extra; char file_name[ MAX_PATH ]; GList *item; struct file_writer *writer; TRACE_ENTER( "msg=%p, destination=%s\n", msg, destination->name ); - make_file_name( destination->file, msg, file_name ); - EnterCriticalSection( &destination->cs_file_writers ); + make_file_name( destination->u.file.name_pattern, msg, file_name ); + EnterCriticalSection( &extra->cs_file_writers ); /* find existing writer */ - for( writer = NULL, item = destination->file_writers; item; item = item->next ) + for( writer = NULL, item = extra->file_writers; item; item = item->next ) if( strcmp( ((struct file_writer*) (item->data))->file_name, file_name ) == 0 ) { writer = item->data; @@ -454,7 +464,7 @@ void write_message( struct message* msg, struct destination* destination ) if( !writer ) goto done; /* add writer to destination */ - destination->file_writers = g_list_append( destination->file_writers, writer ); + extra->file_writers = g_list_append( extra->file_writers, writer ); writer->destination = destination; } /* put message into queue */ @@ -463,41 +473,50 @@ void write_message( struct message* msg, struct destination* destination ) ReleaseSemaphore( writer->fifo_semaphore, 1, NULL ); done: - LeaveCriticalSection( &destination->cs_file_writers ); + LeaveCriticalSection( &extra->cs_file_writers ); TRACE_LEAVE( "done\n" ); } /****************************************************************************** - * fini_writer + * finalize_file_dest + * + * stop all writers */ -void fini_writer() +static void finalize_file_dest( struct destination* destination ) { - GList *dest_item; + struct dest_extra *extra = destination->extra; + GList *wr_item; - TRACE_ENTER( "\n" ); + TRACE_ENTER( "destination=%s\n", destination->name ); /* setting shutdown event */ - for( dest_item = destinations; dest_item; dest_item = dest_item->next ) + EnterCriticalSection( &extra->cs_file_writers ); + for( wr_item = extra->file_writers; wr_item; wr_item = wr_item->next ) { - struct destination *destination = dest_item->data; - GList *wr_item; - - EnterCriticalSection( &destination->cs_file_writers ); - for( wr_item = destination->file_writers; wr_item; wr_item = wr_item->next ) - { - struct file_writer *writer = wr_item->data; - SetEvent( writer->shutdown_event ); - } - LeaveCriticalSection( &destination->cs_file_writers ); + struct file_writer *writer = wr_item->data; + SetEvent( writer->shutdown_event ); } + LeaveCriticalSection( &extra->cs_file_writers ); TRACE_2( "waiting for shutdown\n" ); - for(;;) + while( extra->file_writers ) { - for( dest_item = destinations; dest_item; dest_item = dest_item->next ) - if( ((struct destination*) (dest_item->data))->file_writers ) - break; - if( !dest_item ) - break; Sleep( 60 ); } TRACE_LEAVE( "done\n" ); } + +/****************************************************************************** + * init_destination_file + * + * initialize file destination + */ +gboolean init_destination_file( struct destination* destination ) +{ + struct dest_extra *extra = g_malloc( sizeof(struct dest_extra) ); + + destination->extra = extra; + destination->put = put_message_to_file_dest; + destination->fini = finalize_file_dest; + extra->file_writers = NULL; + InitializeCriticalSection( &extra->cs_file_writers ); + return TRUE; +} |