summaryrefslogtreecommitdiffstats
path: root/sinks/syslog
diff options
context:
space:
mode:
authorDmitri Pal <dpal@dpal.csb>2009-02-23 10:38:06 -0500
committerDmitri Pal <dpal@dpal.csb>2009-02-23 10:38:06 -0500
commitd986aeb99fa33967374290bf7ce75eab76c6d446 (patch)
treee85af838cd95b43c4f1be5bc2203a1a3474ba589 /sinks/syslog
downloadelapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.tar.gz
elapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.tar.xz
elapi_draft-d986aeb99fa33967374290bf7ce75eab76c6d446.zip
Initial commit.
Diffstat (limited to 'sinks/syslog')
-rw-r--r--sinks/syslog/elapi_sink_syslog.c287
1 files changed, 287 insertions, 0 deletions
diff --git a/sinks/syslog/elapi_sink_syslog.c b/sinks/syslog/elapi_sink_syslog.c
new file mode 100644
index 0000000..d3a669d
--- /dev/null
+++ b/sinks/syslog/elapi_sink_syslog.c
@@ -0,0 +1,287 @@
+/* Copyright */
+
+#include <stdio.h>
+#include <errno.h>
+#include <malloc.h>
+#include "elapi_sink.h"
+#include "elapi_collection.h"
+#include "elapi_debug.h"
+#include "elapi_util.h"
+#include "elapi_ini.h"
+
+/* FIXME - this should be taken from the config.h generated by autotools */
+#define SYSLOG_RETRY 60
+#define syslog_audit_config "/home/dpal/IPA/Code/elapi/etc/syslog_defaults.conf"
+#define syslog_audit_dir "/home/dpal/IPA/Code/elapi/etc/syslog_defaults.d"
+
+/* FIXME there is currently no code
+ * to make sure we do not call syslog functions from multiple dispatchers.
+ * We probably should create a mutext at the load of the library and
+ * set a flag when the init function is called the first time
+ * and not call the openlog any more times.
+ * But I guess syslog can deal with this internally.
+ */
+
+
+struct syslog_event {
+ struct serial_data sd;
+ int priority;
+}
+
+
+/* Default conmfiguration for syslog */
+struct syslog_config {
+ int option;
+ int facility;
+ int level;
+ char *ident;
+};
+
+/* Internal function to intialize configuration */
+static int init_config(struct data_descriptor *dblock)
+{
+ struct syslog_conf *conf_data;
+ struct collection_item *file_config = (struct collection_item *)(NULL);
+ int found = 0;
+ int *option_cfg = (int *)(NULL);
+ int *facility_cfg = (int *)(NULL);
+ int *level_cfg = (int *)(NULL);
+ char *ident_cfg = NULL;
+
+ DEBUG_STRING("init_config","Entry");
+
+ /* Allocate configuration data */
+ conf_data = (struct syslog_conf *)(malloc(sizeof(struct syslog_config)));
+ if(conf_data == (struct syslog_conf *)(NULL)) return errno;
+
+ /* Read configuration from the configuration file if any */
+ (void)config_to_collection(dblock->appname, syslog_audit_config, syslog_audit_dir, &file_config);
+
+ conf_data->option = LOG_ODELAY;
+ conf_data->facility = LOG_USER;
+ conf_data->level = LOG_INFO;
+ conf_data->ident = NULL;
+
+ DEBUG_NUMBER("Option",conf_data->option);
+ DEBUG_NUMBER("Facility",conf_data->facility);
+ DEBUG_NUMBER("Level",conf_data->level);
+ DEBUG_STRING("Identity",conf_data->ident);
+
+ /* Update defaults with settings from the file */
+ error = get_value_from_config((void *)(&option_cfg),ELAPI_TYPE_INT, INI_DEFAULT_SECTION,"option",file_config);
+ if(error != EOK) {
+ /* There is fundamentally something wrong */
+ DEBUG_NUMBER("Attempt to get option returned error",error);
+ return error;
+ }
+
+ /* Get the value */
+ if(option_cfg != (int *)(NULL)) {
+ conf_data->option = *option_cfg;
+ free((void *)(option_cfg);
+ }
+
+ error = get_value_from_config((void *)(&facility_cfg),ELAPI_TYPE_INT, INI_DEFAULT_SECTION,"facility",file_config);
+ if(error != EOK) {
+ /* There is fundamentally something wrong */
+ DEBUG_NUMBER("Attempt to get option returned error",error);
+ return error;
+ }
+
+ /* Get the value */
+ if(facility_cfg != (int *)(NULL)) {
+ conf_data->facility = *facility_cfg;
+ free((void *)(facility_cfg);
+ }
+
+ error = get_value_from_config((void *)(&level_cfg),ELAPI_TYPE_INT, INI_DEFAULT_SECTION,"level",file_config);
+ if(error != EOK) {
+ /* There is fundamentally something wrong */
+ DEBUG_NUMBER("Attempt to get option returned error",error);
+ return error;
+ }
+
+ /* Get the value */
+ if(level_cfg != (int *)(NULL)) {
+ conf_data->level = *level_cfg;
+ free((void *)(level_cfg);
+ }
+
+ error = get_value_from_config((void *)(&ident_cfg),ELAPI_TYPE_STRING, INI_DEFAULT_SECTION,"identity",file_config);
+ if(error != EOK) {
+ /* There is fundamentally something wrong */
+ DEBUG_NUMBER("Attempt to get option returned error",error);
+ return error;
+ }
+
+ /* Get the value */
+ if(ident_cfg != (char *)(NULL)) {
+ conf_data->ident = *ident_cfg;
+ free((void *)(ident_cfg);
+ }
+
+
+ DEBUG_NUMBER("Option (after conf file):",conf_data->option);
+ DEBUG_NUMBER("Facility (after conf file):",conf_data->facility);
+ DEBUG_NUMBER("Level (after conf file):",conf_data->level);
+ DEBUG_STRING("Identity (after conf file):",conf_data->ident);
+
+ dblock->config = (void *)(conf_data);
+
+ openlog(conf_data->ident,conf_data->option,conf_data->facility);
+
+ DEBUG_STRING("init_config","Entry");
+ return EOK;
+}
+
+/***** Standard functions each facility has to provide *****/
+/* Initialize facility - open files, establish connnectons, etc... */
+static int syslog_sink_init(struct data_descriptor *dblock)
+{
+ struct syslog_event *event_storage;
+ int error;
+
+ DEBUG_STRING("syslog_sink_init","Entry");
+
+ /* Prepare the block where the format function will store its data */
+ errno = 0;
+ dblock->internal_data = NULL;
+ event_storage = (struct syslog_event *)(malloc(sizeof(struct syslog_event)));
+ if(event_storage == (struct syslog_event *)(NULL)) return errno;
+
+ event_storage->sd.buffer = NULL;
+ event_storage->sd.size = 0;
+ event_storage->sd.length = 0;
+ event_storage->sd.nest_level = 0;
+
+ dblock->internal_data = (void *)(event_storage);
+
+ /* Prepare the configuration data block */
+ if((error = init_config(dblock)) {
+ DEBUG_NUMBER("Failed to init config",error);
+ free(dblock->internal_data);
+ dblock->internal_data = NULL;
+ return error;
+ }
+
+ DEBUG_NUMBER("DBLOCK in init",dblock);
+ DEBUG_NUMBER("internal data in init",dblock->internal_data);
+
+ DEBUG_STRING("syslog_sink_init","Exit");
+ return EOK;
+}
+
+
+/* Formatting calback */
+static int syslog_sink_format(struct data_descriptor *dblock,struct collection_item *event)
+{
+ struct syslog_event *event_storage;
+ struct syslog_config *config;
+
+ int error = EOK;
+
+ DEBUG_STRING("syslog_sink_format","Entry");
+ DEBUG_NUMBER("DBLOCK in format",dblock);
+ DEBUG_NUMBER("internal data in format",dblock->internal_data);
+
+ event_storage = (struct event_storage *)(dblock->internal_data);
+ config = (struct event_storage *)(dblock->config);
+
+ event_storage->priority = config->level | config->facility;
+
+ /* FIXME form priority here */
+
+
+
+
+ /* Traverse collection */
+ error = traverse_collection(event,ELAPI_TRAVERSE_DEFAULT | ELAPI_TRAVERSE_END ,serialize,(void *)(event_storage->sd));
+ if(error) {
+ DEBUG_NUMBER("traverse_collection returned error",error);
+ return error;
+ }
+
+ DEBUG_STRING("syslog_sink_format","Exit");
+ return EOK;
+}
+
+
+/* Cleanup per event internal data after a failure */
+static void syslog_sink_cleanup(struct data_descriptor *dblock)
+{
+ struct syslog_event *event_storage;
+ struct syslog_config *config;
+
+ DEBUG_STRING("syslog_sink_cleanup","Entry");
+
+ event_storage = (struct event_storage *)(dblock->internal_data);
+ config = (struct event_storage *)(dblock->config);
+
+ if(event_storage->sd.buffer != NULL) {
+ free(event_storage->sd.buffer);
+ event_storage->sd.buffer = NULL;
+ event_storage->sd.size = 0;
+ event_storage->sd.length = 0;
+ event_storage->sd.nest_level = 0;
+ event_storage->priority = config->level | config->facility;
+ }
+
+ DEBUG_STRING("syslog_sink_cleanup","Exit");
+}
+
+/* Close facility */
+static void syslog_sink_close(struct data_descriptor *dblock)
+{
+ DEBUG_STRING("syslog_sink_close","Entry");
+
+ if(dblock->internal_data != NULL) {
+ syslog_sink_cleanup(dblock);
+ free(dblock->internal_data);
+ free(dblock->config);
+ dblock->internal_data=NULL;
+ dblock->config=NULL;
+ }
+
+ closelog();
+ DEBUG_STRING("syslog_sink_close","Exit");
+}
+
+
+/* Logging calback */
+static int syslog_sink_submit(struct data_descriptor *dblock)
+{
+ struct syslog_event *event_storage;
+ struct syslog_config *config;
+
+ DEBUG_STRING("syslog_sink_submit","Entry");
+ DEBUG_NUMBER("DBLOCK in submit",dblock);
+ DEBUG_NUMBER("internal data in submit",dblock->internal_data);
+
+ event_storage = (struct serial_data *)(dblock->internal_data);
+ config = (struct event_storage *)(dblock->config);
+
+ DEBUG_STRING("OUTPUT:",event_storage->db.buffer);
+
+ fprintf(stderr,"%s %d %s\n",config->ident, event_storage->priority, event_storage->db.buffer);
+
+ syslog_sink_cleanup(dblock);
+
+ DEBUG_STRING("syslog_sink_submit","Exit");
+ return EOK;
+}
+
+/* Return a filled in structure */
+void get_sink_info(struct sink_capability *sink_cpb_block)
+{
+ DEBUG_STRING("get_sink_info","Entry");
+
+ sink_cpb_block->retry_interval = SYSLOG_RETRY;
+ sink_cpb_block->init_cb = syslog_sink_init;
+ sink_cpb_block->cleanup_cb = syslog_sink_cleanup;
+ sink_cpb_block->format_cb = syslog_sink_format;
+ sink_cpb_block->submit_cb = syslog_sink_submit;
+ sink_cpb_block->close_cb = syslog_sink_close;
+
+ DEBUG_STRING("get_sink_info","Exit");
+}
+