/*
 * log.cpp - log files handling functions
 * $Id: log.cpp,v 1.3 2004/06/05 15:15:17 rdenisc Exp $
 */

/***********************************************************************
 *  Copyright (C) 2002-2004 Remi Denis-Courmont.                       *
 *  This program is free software; you can redistribute and/or modify  *
 *  it under the terms of the GNU General Public License as published  *
 *  by the Free Software Foundation; version 2 of the license.         *
 *                                                                     *
 *  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, you can get it from:              *
 *  http://www.gnu.org/copyleft/gpl.html                               *
 ***********************************************************************/

#ifdef HAVE_CONFIG_H
# include <config.h>
#endif

#include "secstdio.h"
#include <string.h>

#include "log.h"


/*** DataLog class implementation ***/
DataLog::~DataLog (void)
{
	if ((out != NULL) && close_out)
		fclose (out);
}


void
DataLog::Connect (const char *, const char *,
			const char *, const char *)
{
}


int
DataLog::WriteServerData (const void *, int length, int)
{
	return length;
}


int
DataLog::WriteClientData (const void *, int length, int)
{
	return length;
}


void
DataLog::ShutdownServer (void)
{
}


void
DataLog::ShutdownClient (void)
{
}


/*** DataLogList implementation ***/
int
DataLogList::AddLog (DataLog *log)
{
	if (log == NULL)
		return -1;
	
	struct listnode *node;

	try
	{
		node = new listnode;
	}
	catch (...)
	{
		return -1;
	}

	node->log = log;
	node->next = head;
	head = node;
	return 0;
}


DataLogList::~DataLogList (void)
{
	for (struct listnode *node = head; node != NULL; node = head)
	{
		head = node->next;
		delete node->log;
		delete node;
	}
}


int
DataLogList::WriteServerData (const void *data, int length, int oob)
{
	for (struct listnode *node = head; node != NULL; node = node->next)
		if (node->log->WriteServerData (data, length, oob) != length)
			return -1;

	return length;
}


int
DataLogList::WriteClientData (const void *data, int length, int oob)
{
	for (struct listnode *node = head; node != NULL; node = node->next)
		if (node->log->WriteClientData (data, length, oob) != length)
			return -1;

	return length;
}


void
DataLogList::ShutdownServer (void)
{
	for (struct listnode *node = head; node != NULL; node = node->next)
		node->log->ShutdownServer ();
}


void
DataLogList::ShutdownClient (void)
{
	for (struct listnode *node = head; node != NULL; node = node->next)
		node->log->ShutdownClient ();
}


void
DataLogList::Connect (const char *server, const char *service,
			const char *client, const char *port)
{
	for (struct listnode *node = head; node != NULL; node = node->next)
		node->log->Connect (server, service, client, port);
}


/*** DataLogListMaker implementation ***/
int
DataLogListMaker::AddLogMaker (DataLog *(*maker) (void), FILE *stream)
{
	struct listnode *node;

	try
	{
		node = new struct listnode;
	}
	catch (...)
	{
		return -1;
	}

	node->maker = maker;
	node->next = head;
	node->basename = NULL;
	node->stream = stream;
	head = node;
	return 0;
}


int
DataLogListMaker::AddLogMaker (DataLog *(*maker) (void), const char *prefix)
{
	struct listnode *node;

	try
	{
		node = new struct listnode;
	}
	catch (...)
	{
		return -1;
	}

	node->maker = maker;
	node->next = head;

	node->basename = strdup (prefix);
	if (node->basename == NULL)
	{
		delete node;
		return -1;
	}

	node->stream = NULL;
	head = node;
	return 0;
}


DataLogListMaker::~DataLogListMaker (void)
{
	for (struct listnode *node = head; node != NULL; node = head)
	{
		head = node->next;
		if (node->basename != NULL)
			delete node->basename;
		delete node;
	}
}


DataLogList *
DataLogListMaker::MakeLogList (const char *addr, const char *port) const
{
	DataLogList *list;

	try
	{
		list = new DataLogList;
	}
	catch (...)
	{
		return NULL;
	}

	// Creates a log for each maker in the list
	for (struct listnode *node = head; node != NULL; node = node->next)
	{
		DataLog *log;

		try
		{
			log = node->maker ();
		}
		catch (...)
		{
			delete list;
			return NULL;
		}

		if (log != NULL)
		{
			// Adds a log in the list
			if (list->AddLog (log))
			{
				delete log;
				delete list;
				return NULL;
			}

			// Attaches a stream to the new log
			if (node->stream != NULL)
				log->SetStream (node->stream, 0);
			else
			{	// Do we need more abstraction?
				const char *prefix = node->basename;
				if (prefix == NULL)
					prefix = "";
				if (addr == NULL)
					addr = "";
				if (port == NULL)
					port = "";

				char *filename;

				int len = strlen (prefix) + strlen (addr)
						+ strlen (port) + 3;

				try
				{
					filename = new char[len];
				}
				catch (...)
				{
					delete list;
					return NULL;
				}
				snprintf (filename, len, "%s-%s-%s",
						prefix, addr, port);

				FILE *stream = secure_fopen (filename, "a");
				delete filename;

				if (stream == NULL)
				{
					delete list;
					return NULL;
				}
				log->SetStream (stream);
			}
		}
	}

	return list;
}


syntax highlighted by Code2HTML, v. 0.9.1