view src/syslogconfig.cpp @ 2:6e88da080f08

initial coding
author carl
date Thu, 24 Nov 2005 10:31:09 -0800
parents 551433a01cab
children 8fe310e5cd44
line wrap: on
line source

/***************************************************************************
 *	 Copyright (C) 2005 by 510 Software Group							   *
 *																		   *
 *																		   *
 *	 This program is free software; you can redistribute it and/or modify  *
 *	 it under the terms of the GNU General Public License as published by  *
 *	 the Free Software Foundation; either version 2 of the License, or	   *
 *	 (at your option) any later version.								   *
 *																		   *
 *	 This program is distributed in the hope that it will be useful,	   *
 *	 but WITHOUT ANY WARRANTY; without even the implied warranty of 	   *
 *	 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the		   *
 *	 GNU General Public License for more details.						   *
 *																		   *
 *	 You should have received a copy of the GNU General Public License	   *
 *	 along with this program; if not, write to the						   *
 *	 Free Software Foundation, Inc.,									   *
 *	 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.			   *
 ***************************************************************************/

#include "includes.h"
#include <fcntl.h>

static char* syslogconfig_version="$Id$";

char *token_cisco;
char *token_file;
char *token_include;
char *token_lbrace;
char *token_parser;
char *token_rbrace;
char *token_semi;
char *token_ssh;

string_set	all_strings;	// owns all the strings, only modified by the config loader thread
const int maxlen = 1000;	// used for snprintf buffers


CONFIG::CONFIG() {
	reference_count    = 0;
	generation		   = 0;
	load_time		   = 0;
}


CONFIG::~CONFIG() {
	for (syslogconfig_list::iterator i=syslogconfigs.begin(); i!=syslogconfigs.end(); i++) {
		SYSLOGCONFIG *c = *i;
		delete c;
	}
}


void CONFIG::add_syslogconfig(SYSLOGCONFIGP con) {
	syslogconfigs.push_back(con);
}


void CONFIG::dump() {
	for (syslogconfig_list::iterator i=syslogconfigs.begin(); i!=syslogconfigs.end(); i++) {
		SYSLOGCONFIGP c = *i;
		c->dump(0);
	}
}


void CONFIG::read() {
	for (syslogconfig_list::iterator i=syslogconfigs.begin(); i!=syslogconfigs.end(); i++) {
		SYSLOGCONFIGP c = *i;
		c->read();
	}
}


SYSLOGCONFIG::SYSLOGCONFIG(TOKEN &tok, char *file_name_, parser_style parser_) {
	file_name = file_name_;
	parser	  = parser_;
	fd		  = open(file_name, O_RDONLY);
	len 	  = 0;
	if (fd == -1) {
		char buf[maxlen];
		snprintf(buf, sizeof(buf), "syslog file %s not readable", file_name);
		tok.token_error(buf);
	}
	else {
		lseek(fd, 0, SEEK_END);
	}
}


SYSLOGCONFIG::~SYSLOGCONFIG() {
	if (fd != -1) close(fd);
	fd = -1;
}


void SYSLOGCONFIG::read() {
	if (failed()) return;
	int n = ::read(fd, buf, buflen-len);
	if (n > 0) {
		len += n;
		while (true) {
			char *p = (char*)memchr(buf, '\n', len);
			if (!p) break;
			n = p-buf;
			*p = '\0';
			process();	// process null terminated string
			len -= n+1;
			memmove(buf, p+1, len);
		}
		// no <lf> in a full buffer
		if (len == buflen) len = 0;
	}
}


void SYSLOGCONFIG::process() {
	my_syslog(buf);
}


void SYSLOGCONFIG::dump(int level) {
	char indent[maxlen];
	int i = min(maxlen-1, level*4);
	memset(indent, ' ', i);
	indent[i] = '\0';
	char buf[maxlen];
	printf("%s file \"%s\" {\n", indent, file_name);
		switch (parser) {
			case cisco:
				printf("%s     parser cisco; \n", indent);
				break;
			case ssh:
				printf("%s     parser ssh; \n", indent);
				break;
		}
	printf("%s }; \n", indent);
}


////////////////////////////////////////////////
// helper to discard the strings held by a string_set
//
void discard(string_set &s) {
	for (string_set::iterator i=s.begin(); i!=s.end(); i++) {
		free(*i);
	}
	s.clear();
}


////////////////////////////////////////////////
// helper to register a string in a string set
//
char* register_string(string_set &s, char *name) {
	string_set::iterator i = s.find(name);
	if (i != s.end()) return *i;
	char *x = strdup(name);
	s.insert(x);
	return x;
}


////////////////////////////////////////////////
// register a global string
//
char* register_string(char *name) {
	return register_string(all_strings, name);
}


////////////////////////////////////////////////
//
bool tsa(TOKEN &tok, char *token);
bool tsa(TOKEN &tok, char *token) {
	char *have = tok.next();
	if (have == token) return true;
	tok.token_error(token, have);
	return false;
}


////////////////////////////////////////////////
//
bool parse_syslogconfig(TOKEN &tok, CONFIG &dc);
bool parse_syslogconfig(TOKEN &tok, CONFIG &dc) {
	char *name = tok.next();
	parser_style parser;
	if (!tsa(tok, token_lbrace)) return false;
	while (true) {
		char *have = tok.next();
		if (have == token_parser) {
			have = tok.next();
				 if (have == token_cisco) parser = cisco;
			else if (have == token_ssh)   parser = ssh;
			else {
				tok.token_error("cisco/ssh", have);
				return false;
			}
			if (!tsa(tok, token_semi)) return false;
		}
		else if (have == token_rbrace) {
			break;	// done
		}
		else {
			tok.token_error("file keyword", have);
			return false;
		}
	}
	if (!tsa(tok, token_semi)) return false;
	SYSLOGCONFIGP con = new SYSLOGCONFIG(tok, name, parser);
	if (con->failed()) {
		delete con;
		return false;
	}
	dc.add_syslogconfig(con);
	return true;
}


////////////////////////////////////////////////
// parse a config file
//
bool load_conf(CONFIG &dc, char *fn) {
	int count = 0;
	TOKEN tok(fn, &dc.config_files);
	while (true) {
		char *have = tok.next();
		if (!have) break;
		if (have == token_file) {
			if (!parse_syslogconfig(tok, dc)) {
				tok.token_error("load_conf() failed to parse syslogconfig");
				return false;
			}
			else count++;
		}
		else {
			tok.token_error(token_file, have);
			return false;
		}
	}
	tok.token_error("load_conf() found %d syslog files in %s", count, fn);
	return (!dc.syslogconfigs.empty());
}


////////////////////////////////////////////////
// init the tokens
//
void token_init() {
	token_cisco 	 = register_string("cisco");
	token_file		 = register_string("file");
	token_include	 = register_string("include");
	token_lbrace	 = register_string("{");
	token_parser	 = register_string("parser");
	token_rbrace	 = register_string("}");
	token_semi		 = register_string(";");
	token_ssh		 = register_string("ssh");
}