aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--daemon/conf.c134
-rw-r--r--daemon/logrotate.c31
-rw-r--r--daemon/syslogd.c16
-rw-r--r--daemon/syslogd.h112
-rw-r--r--daemon/writer.c81
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( &current_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;
+}