/*
* -------------------------------------------------------
* Copyright (C) 2004-2007 Tommi Saviranta <wnd@iki.fi>
* -------------------------------------------------------
* 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.
*/
#ifdef HAVE_CONFIG_H
#include <config.h>
#endif /* ifdef HAVE_CONFIG_H */
#ifdef PRIVLOG
#include "privlog.h"
#include "llist.h"
#include "common.h"
#include "tools.h"
#include "miau.h"
#include "messages.h"
#include "log.h"
#include "commands.h"
#include <string.h>
llist_list open_logs;
static int open_log(privlog_type *log);
static void finalize_log(privlog_type *log);
static int
open_log(privlog_type *log)
{
char *lownick;
size_t fsize;
/* Get nick in lowercase. */
/* We could use filename as temporary buffer but that isn't safe. */
lownick = xstrdup(log->nick);
lowcase(lownick);
xfree(log->filename); /* make sure */
/* termination and validity guaranteed */
fsize = strlen(LOGDIR) + strlen(lownick) + strlen(cfg.logsuffix) + 3;
log->filename = (char *) xmalloc(fsize);
snprintf(log->filename, fsize, LOGDIR"/%s%s", lownick, cfg.logsuffix);
log->filename[fsize - 1] = '\0';
log->file = fopen(log->filename, "a+");
xfree(lownick);
if (log->file == NULL) {
return -1;
} else {
return 0;
}
} /* static int open_file(privlog_type *log) */
/*
* Writes entry in logfile.
*
* "nick" declares who we are talking with.
*
* If file isn't open already, open file first.
* (Logfiles are closed periodically in miau.c)
*/
int
privlog_write(const char *nick, int in_out, int cmd, const char *message)
{
const char *active;
char *t;
int newentry;
privlog_type *line;
newentry = 0;
line = NULL;
/* First see if log is already open. */
LLIST_WALK_H(open_logs.head, privlog_type *);
if (xstrcasecmp(data->nick, nick) == 0) {
line = data;
LLIST_WALK_BREAK;
}
LLIST_WALK_F;
if (line == NULL) {
/* Create new entry. */
newentry = 1;
line = (privlog_type *) xmalloc(sizeof(privlog_type));
line->nick = xstrdup(nick);
line->file = NULL;
line->filename = NULL;
}
/* If file is closed, open it. */
if (line->file == NULL) {
open_log(line);
}
if (line->file == NULL) {
log_cannot_write(line->filename);
xfree(line->nick);
xfree(line);
return -1;
}
if (newentry == 1) {
/* Newly created is likely to be needed first. I think. */
llist_add(llist_create(line), &open_logs);
}
/* Update timestamp. */
time(&line->updated);
/* New entry? Write header. */
if (newentry == 1) {
/* termination guaranteed in get_timestamp() */
fprintf(line->file, LOGM_LOGOPEN,
get_timestamp(NULL, TIMESTAMP_LONG));
}
/* Write log. */
active = (in_out == PRIVLOG_IN) ? nick : status.nickname;
t = log_prepare_entry(active, message);
if (t == NULL) {
if (cmd == CMD_PRIVMSG + MINCOMMANDVALUE) {
fprintf(line->file, LOGM_MESSAGE, get_short_localtime(),
active, message);
} else {
fprintf(line->file, LOGM_NOTICE, get_short_localtime(),
active, message);
}
} else {
/* termination guaranteed in log_prepare_entry() */
fprintf(line->file, "%s", t);
}
fflush(line->file);
return 0;
} /* int privlog_write(const char *nick, int in_out, int cmd,
const char *message) */
/*
* Close all logfiles.
*/
void
privlog_close_all(void)
{
LLIST_WALK_H(open_logs.head, privlog_type *);
finalize_log(data);
llist_delete(node, &open_logs);
LLIST_WALK_F;
} /* void privlog_close_all(void) */
/*
* Finalize log.
*
* Reopen file for writing footer, then close file and free resources -
* including structure for logfile.
*/
static void
finalize_log(privlog_type *log)
{
/*
* Remove entry from list. This allows writing new headers into file
* when conversation continues.
*/
/* Reopen closed file for writing footer. */
if (log->file == NULL) {
open_log(log);
}
if (log->file != NULL) {
/* termination guaranteed in get_timestamp() */
fprintf(log->file, LOGM_LOGCLOSE, get_timestamp(
&log->updated, TIMESTAMP_LONG));
fclose(log->file);
}
xfree(log->nick);
xfree(log->filename);
xfree(log);
} /* static void finalize_log(privlog_type *log) */
/*
* Close logfile.
*/
void
privlog_close_old(void)
{
time_t close;
time_t loggrace;
close = time(NULL) - PRIVLOG_TIME_OPEN;
loggrace = time(NULL) - PRIVLOG_TIME_GRACE;
LLIST_WALK_H(open_logs.head, privlog_type *);
if (data->updated < loggrace) {
finalize_log(data);
llist_delete(node, &open_logs);
} else if (data->updated < close && data->file != NULL) {
/*
* Close file but remember it. If converastion continues
* in a while, new headers will not be written.
*/
fclose(data->file);
data->file = NULL;
}
LLIST_WALK_F;
} /* void privlog_close_old(void) */
int
privlog_has_open(void)
{
return open_logs.head != NULL;
} /* int privlog_has_open(void) */
#ifdef DUMPSTATUS
llist_list *
privlog_get_list(void)
{
return &open_logs;
} /* privlog_get_list(void) */
#endif /* ifdef DUMPSTATUS */
#endif /* ifdef PRIVLOG */
syntax highlighted by Code2HTML, v. 0.9.1