2005-04-28 10:26:44 +02:00
|
|
|
|
/*
|
|
|
|
|
* $Id: log.c,v 1.56 2005/04/21 06:58:50 nohar Exp $
|
|
|
|
|
*
|
|
|
|
|
* This file is part of the bip project
|
|
|
|
|
* Copyright (C) 2004 Arnaud Cornet and Lo<EFBFBD>c Gomez
|
|
|
|
|
*
|
|
|
|
|
* 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.
|
|
|
|
|
* See the file "COPYING" for the exact licensing terms.
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
#include "config.h"
|
|
|
|
|
#include "log.h"
|
|
|
|
|
#include "irc.h"
|
|
|
|
|
#include "util.h"
|
|
|
|
|
|
|
|
|
|
extern int errno;
|
|
|
|
|
extern int log_level;
|
|
|
|
|
extern char *conf_log_root;
|
|
|
|
|
extern char *conf_log_format;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
extern int conf_log;
|
|
|
|
|
|
|
|
|
|
int conf_memlog = 1;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
|
|
|
|
/* conf_always_backlog => conf_backlog_lines != 0 */
|
2005-05-19 22:55:11 +02:00
|
|
|
|
extern int conf_backlog;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
extern int conf_backlog_lines;
|
|
|
|
|
extern int conf_always_backlog;
|
2006-10-21 14:06:31 +02:00
|
|
|
|
extern int conf_bl_msg_only;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
|
|
|
|
int log_set_backlog_offset(log_t *logdata, char *dest);
|
2005-05-19 22:55:11 +02:00
|
|
|
|
static int _log_write(log_t *logdata, logfilegroup_t *lf, char *d, char *str);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
void logfile_free(logfile_t *lf);
|
2005-05-21 15:44:09 +02:00
|
|
|
|
static char *_log_wrap(char *dest, char *line);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
|
|
|
|
/* TODO: change fatal("out of memory") to cleanup & return NULL */
|
|
|
|
|
|
|
|
|
|
int check_dir(char *filename)
|
|
|
|
|
{
|
|
|
|
|
int err;
|
|
|
|
|
struct stat statbuf;
|
|
|
|
|
|
|
|
|
|
err = stat(filename, &statbuf);
|
|
|
|
|
if (err && errno == ENOENT) {
|
|
|
|
|
err = mkdir(filename, 0750);
|
|
|
|
|
if (err) {
|
|
|
|
|
mylog(LOG_ERROR, "mkdir(%s) %s", filename,
|
|
|
|
|
strerror(errno));
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
} else if (err) {
|
|
|
|
|
mylog(LOG_ERROR, "stat(%s) %s", filename,
|
|
|
|
|
strerror(errno));
|
|
|
|
|
return 1;
|
|
|
|
|
} else if (!(statbuf.st_mode & S_IFDIR)) {
|
|
|
|
|
mylog(LOG_ERROR, "%s is not a directory", filename);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int check_dir_r(char *dirname)
|
|
|
|
|
{
|
|
|
|
|
int pos, count = 0;
|
|
|
|
|
char *dir, *tmp;
|
|
|
|
|
int len = strlen(dirname);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
mylog(LOG_DEBUGVERB, "Recursive check of %s engaged", dirname);
|
|
|
|
|
tmp = dirname;
|
|
|
|
|
dir = (char *)malloc(sizeof(char) * (len + 1));
|
|
|
|
|
while (*tmp) {
|
|
|
|
|
int slash_ok = 1;
|
|
|
|
|
while (*tmp == '/') {
|
|
|
|
|
if (slash_ok) {
|
|
|
|
|
strncpy(dir + count, "/", 1);
|
|
|
|
|
count++;
|
|
|
|
|
slash_ok = 0;
|
|
|
|
|
}
|
|
|
|
|
tmp++;
|
|
|
|
|
}
|
|
|
|
|
pos = strcspn(tmp, "/");
|
|
|
|
|
strncpy(dir + count, tmp, pos);
|
|
|
|
|
tmp += pos;
|
|
|
|
|
count += pos;
|
|
|
|
|
*(dir + count) = '\0';
|
|
|
|
|
mylog(LOG_DEBUGVERB,"check_dir_r: %s", dir);
|
|
|
|
|
if (check_dir(dir)) {
|
|
|
|
|
free(dir);
|
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
free(dir);
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void strtolower(char *str)
|
|
|
|
|
{
|
|
|
|
|
char *c;
|
|
|
|
|
|
|
|
|
|
for (c = str; *c != '\0'; c++)
|
|
|
|
|
*c = tolower(*c);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Replace all occurences of var in str by value.
|
|
|
|
|
* This function modifies its first argument!
|
|
|
|
|
* Truncate the string after max characters.
|
|
|
|
|
*/
|
|
|
|
|
void replace_var(char *str, char *var, char *value, unsigned int max)
|
|
|
|
|
{
|
|
|
|
|
char *pos;
|
|
|
|
|
unsigned int lenvar = strlen(var);
|
|
|
|
|
unsigned int lenval = strlen(value);
|
|
|
|
|
while((pos = strstr(str, var))) {
|
|
|
|
|
/* Make room */
|
|
|
|
|
if (strlen(str) + (lenval - lenvar) >= max)
|
|
|
|
|
return;
|
|
|
|
|
memmove(pos + lenval, pos + lenvar,
|
|
|
|
|
(strlen(pos + lenvar) + 1)*sizeof(char));
|
|
|
|
|
memcpy(pos, value, lenval*sizeof(char));
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
char *log_build_filename(log_t *logdata, char *destination)
|
|
|
|
|
{
|
|
|
|
|
char *logfile, year[5], day[3], month[3], *tmp, *logdir;
|
|
|
|
|
int log_format_len;
|
|
|
|
|
struct tm *now;
|
|
|
|
|
time_t s;
|
|
|
|
|
char *dest = strdup(destination);
|
|
|
|
|
strtolower(dest);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
log_format_len = strlen(conf_log_format);
|
|
|
|
|
logfile = (char*)malloc((MAX_PATH_LEN + 1)*sizeof(char));
|
|
|
|
|
if (!logfile)
|
|
|
|
|
fatal("out of memory");
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
time(&s);
|
|
|
|
|
now = localtime(&s);
|
|
|
|
|
snprintf(year, 5, "%04d", now->tm_year + 1900);
|
|
|
|
|
snprintf(day, 3, "%02d", now->tm_mday);
|
|
|
|
|
snprintf(month, 3, "%02d", now->tm_mon + 1);
|
|
|
|
|
snprintf(logfile, MAX_PATH_LEN, "%s/%s", conf_log_root,
|
|
|
|
|
conf_log_format);
|
|
|
|
|
replace_var(logfile, "%u", logdata->user, MAX_PATH_LEN);
|
|
|
|
|
replace_var(logfile, "%n", logdata->network, MAX_PATH_LEN);
|
|
|
|
|
replace_var(logfile, "%c", dest, MAX_PATH_LEN);
|
|
|
|
|
replace_var(logfile, "%Y", year, MAX_PATH_LEN);
|
|
|
|
|
replace_var(logfile, "%d", day, MAX_PATH_LEN);
|
|
|
|
|
replace_var(logfile, "%m", month, MAX_PATH_LEN);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
logdir = strdup(logfile);
|
|
|
|
|
if (!logdir)
|
|
|
|
|
fatal("out of memory");
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
/* strrchr works on bytes, not on char (if sizeof(char) != 1) */
|
|
|
|
|
tmp = strrchr(logdir, '/');
|
|
|
|
|
if (tmp)
|
|
|
|
|
*tmp = '\0';
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
free(dest);
|
|
|
|
|
if (check_dir_r(logdir)) {
|
|
|
|
|
free(logfile);
|
|
|
|
|
free(logdir);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
free(logdir);
|
|
|
|
|
return logfile;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_updatelast(logfile_t *lf)
|
|
|
|
|
{
|
|
|
|
|
time_t t;
|
|
|
|
|
|
|
|
|
|
time(&t);
|
|
|
|
|
localtime_r(&t, &lf->last_log);
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-30 01:00:30 +02:00
|
|
|
|
void log_reset(logfilegroup_t *lfg)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
{
|
|
|
|
|
logfile_t *olf;
|
2005-05-30 20:01:00 +02:00
|
|
|
|
lfg->skip_advance = 0;
|
2005-05-30 01:00:30 +02:00
|
|
|
|
|
|
|
|
|
if (lfg->memlog) {
|
|
|
|
|
while (!list_is_empty(lfg->memlog))
|
|
|
|
|
free(list_remove_first(lfg->memlog));
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
while ((olf = list_get_first(&lfg->file_group)) !=
|
|
|
|
|
list_get_last(&lfg->file_group)) {
|
|
|
|
|
logfile_free(olf);
|
|
|
|
|
list_remove_first(&lfg->file_group);
|
|
|
|
|
}
|
2005-05-30 01:00:30 +02:00
|
|
|
|
if (!olf)
|
|
|
|
|
return;
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!olf->file)
|
|
|
|
|
fatal("internal, (NULL logfile)");
|
|
|
|
|
fseek(olf->file, 0, SEEK_END);
|
|
|
|
|
olf->len = ftell(olf->file);
|
|
|
|
|
olf->backlog_offset = olf->len;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-30 01:00:30 +02:00
|
|
|
|
void log_reinit(logfilegroup_t *lfg)
|
|
|
|
|
{
|
|
|
|
|
mylog(LOG_ERROR, "%s is inconsistant, droping backlog info",
|
|
|
|
|
lfg->name);
|
|
|
|
|
log_reset(lfg);
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
static int log_add_file(log_t *logdata, char *destination, char *filename)
|
|
|
|
|
{
|
|
|
|
|
FILE *f;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
logfile_t *lf = NULL;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
logfilegroup_t *lfg;
|
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (conf_log) {
|
|
|
|
|
f = fopen(filename, "a+");
|
|
|
|
|
if (!f) {
|
|
|
|
|
mylog(LOG_ERROR, "fopen(%s) %s", filename,
|
|
|
|
|
strerror(errno));
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
lf = malloc(sizeof(logfile_t));
|
|
|
|
|
if (!lf)
|
|
|
|
|
fatal("out of memory");
|
|
|
|
|
lf->file = f;
|
|
|
|
|
lf->filename = strdup(filename);
|
|
|
|
|
if (!lf->filename)
|
|
|
|
|
fatal("out of memory");
|
|
|
|
|
|
|
|
|
|
fseek(lf->file, 0, SEEK_END);
|
|
|
|
|
if (ftell(f) < 0)
|
|
|
|
|
fatal("ftell");
|
|
|
|
|
lf->len = ftell(f);
|
|
|
|
|
lf->backlog_offset = lf->len;
|
|
|
|
|
log_updatelast(lf);
|
|
|
|
|
}
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
|
|
|
|
lfg = hash_get(&logdata->logfgs, destination);
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!lfg) {
|
2005-05-19 22:55:11 +02:00
|
|
|
|
lfg = calloc(sizeof(logfilegroup_t), 1);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!lfg)
|
|
|
|
|
fatal("out of memory");
|
|
|
|
|
list_init(&lfg->file_group, NULL);
|
|
|
|
|
lfg->name = strdup(destination);
|
|
|
|
|
if (!lfg->name)
|
|
|
|
|
fatal("out of memory");
|
|
|
|
|
lfg->skip_advance = 0;
|
|
|
|
|
hash_insert(&logdata->logfgs, destination, lfg);
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
|
|
|
|
if (conf_memlog) {
|
|
|
|
|
if (!lfg->memlog)
|
|
|
|
|
lfg->memlog = list_new(NULL);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (lf)
|
|
|
|
|
list_add_last(&lfg->file_group, lf);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
return 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* XXX: must not free file_group
|
|
|
|
|
*/
|
|
|
|
|
void logfile_free(logfile_t *lf)
|
|
|
|
|
{
|
|
|
|
|
if (!lf)
|
|
|
|
|
return;
|
|
|
|
|
if (lf->file)
|
|
|
|
|
fclose(lf->file);
|
|
|
|
|
if (lf->filename)
|
|
|
|
|
free(lf->filename);
|
|
|
|
|
free(lf);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logfilegroup_t *log_find_file(log_t *logdata, char *destination)
|
|
|
|
|
{
|
|
|
|
|
logfile_t *lf;
|
|
|
|
|
logfilegroup_t *lfg;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
char *filename = NULL;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
time_t t;
|
|
|
|
|
struct tm *ltime;
|
|
|
|
|
|
|
|
|
|
if (!ischannel(*destination))
|
|
|
|
|
destination = "privates";
|
|
|
|
|
|
|
|
|
|
lfg = hash_get(&logdata->logfgs, destination);
|
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (lfg && !conf_log)
|
|
|
|
|
return lfg;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (!lfg) {
|
|
|
|
|
if (conf_log) {
|
|
|
|
|
filename = log_build_filename(logdata, destination);
|
|
|
|
|
if (!filename)
|
|
|
|
|
return NULL;
|
|
|
|
|
mylog(LOG_DEBUG, "Creating new logfile for %s: %s",
|
|
|
|
|
destination, filename);
|
|
|
|
|
}
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!log_add_file(logdata, destination, filename)) {
|
|
|
|
|
free(filename);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
lfg = hash_get(&logdata->logfgs, destination);
|
|
|
|
|
if (!lfg)
|
|
|
|
|
fatal("internal log_find_file");
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (filename)
|
|
|
|
|
free(filename);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
return lfg;
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
/* This is reached if lfg already exists */
|
|
|
|
|
time(&t);
|
|
|
|
|
ltime = localtime(&t);
|
|
|
|
|
lf = list_get_last(&lfg->file_group);
|
|
|
|
|
if (ltime->tm_mday != lf->last_log.tm_mday) {
|
|
|
|
|
logfile_t *oldlf;
|
|
|
|
|
|
|
|
|
|
/* day changed, we might want to rotate logfile */
|
|
|
|
|
filename = log_build_filename(logdata, destination);
|
|
|
|
|
if (!filename)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (strcmp(lf->filename, filename) == 0) {
|
|
|
|
|
/* finally we don't */
|
|
|
|
|
free(filename);
|
|
|
|
|
return lfg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* we do want do rotate logfiles */
|
|
|
|
|
mylog(LOG_DEBUG, "Rotating logfile for %s from", destination);
|
|
|
|
|
oldlf = list_get_last(&lfg->file_group);
|
|
|
|
|
if (!log_add_file(logdata, destination, filename)) {
|
|
|
|
|
free(filename);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
free(filename);
|
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (!conf_backlog) {
|
2005-04-28 10:26:44 +02:00
|
|
|
|
/* remove oldlf from file_group */
|
|
|
|
|
if (list_remove_first(&lfg->file_group) != oldlf)
|
|
|
|
|
fatal("internal log_find_file 2");
|
|
|
|
|
logfile_free(oldlf);
|
|
|
|
|
if (list_get_first(&lfg->file_group)
|
|
|
|
|
!= list_get_last(&lfg->file_group))
|
|
|
|
|
fatal("internal log_find_file 3");
|
|
|
|
|
} else {
|
|
|
|
|
fclose(oldlf->file);
|
|
|
|
|
oldlf->file = NULL;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return lfg;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Da log routines
|
|
|
|
|
*/
|
|
|
|
|
void log_join(log_t *logdata, char *ircmask, char *channel)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- %s has joined %s", timestamp(), ircmask,
|
2005-04-28 10:26:44 +02:00
|
|
|
|
channel);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_part(log_t *logdata, char *ircmask, char *channel,
|
|
|
|
|
char *message)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- %s has left %s [%s]", timestamp(), ircmask,
|
2005-04-28 10:26:44 +02:00
|
|
|
|
channel, message);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_kick(log_t *logdata, char *ircmask, char *channel,
|
|
|
|
|
char *who, char *message)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- %s has been kicked by %s [%s]", timestamp(),
|
2005-04-28 10:26:44 +02:00
|
|
|
|
who, ircmask, message);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_quit(log_t *logdata, char *ircmask, char *channel, char *message)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- %s has quit [%s]", timestamp(), ircmask,
|
2005-04-28 10:26:44 +02:00
|
|
|
|
message);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_nick(log_t *logdata, char *ircmask, char *channel, char *newnick)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- %s is now known as %s",
|
2005-04-28 10:26:44 +02:00
|
|
|
|
timestamp(), ircmask, newnick);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
static void _log_privmsg(log_t *logdata, char *ircmask, int src,
|
|
|
|
|
char *destination, char *message)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
{
|
2005-05-19 22:55:11 +02:00
|
|
|
|
char dir = '<';
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!ircmask)
|
|
|
|
|
ircmask = "Server message";
|
2005-05-13 10:43:50 +02:00
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (src)
|
|
|
|
|
dir = '>';
|
|
|
|
|
|
2005-08-01 11:15:25 +02:00
|
|
|
|
if (strlen(message) > 8 && ((*message == '\001' ||
|
2005-06-04 12:39:04 +02:00
|
|
|
|
((*message == '+' || *message == '-') &&
|
|
|
|
|
(*(message + 1) == '\001'))) &&
|
|
|
|
|
(*(message + strlen(message) - 1) == '\001'))) {
|
|
|
|
|
char *msg;
|
|
|
|
|
/* hack for freenode and the like */
|
|
|
|
|
char *real_message = message;
|
|
|
|
|
|
|
|
|
|
if (*message == '+' || *message == '-')
|
|
|
|
|
real_message++;
|
|
|
|
|
|
|
|
|
|
if (strncmp(real_message, "\001ACTION ", 8) != 0)
|
|
|
|
|
return;
|
|
|
|
|
msg = strdup(real_message);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!msg)
|
|
|
|
|
fatal("out of memory");
|
|
|
|
|
*(msg + strlen(msg) - 1) = '\0';
|
2005-05-13 10:43:50 +02:00
|
|
|
|
if (ischannel(*destination) || strchr(destination, '@')) {
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-06-04 12:39:04 +02:00
|
|
|
|
"%s %c * %s %s", timestamp(), dir,
|
2005-05-19 22:55:11 +02:00
|
|
|
|
ircmask, msg + 8);
|
2005-05-13 10:43:50 +02:00
|
|
|
|
} else {
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-06-04 12:39:04 +02:00
|
|
|
|
"%s (%s) %c * %s %s", timestamp(),
|
2005-05-19 22:55:11 +02:00
|
|
|
|
destination, dir, ircmask, msg + 8);
|
2005-05-13 10:43:50 +02:00
|
|
|
|
}
|
2005-04-28 10:26:44 +02:00
|
|
|
|
free(msg);
|
|
|
|
|
} else {
|
2005-05-13 10:43:50 +02:00
|
|
|
|
if (ischannel(*destination) || strchr(destination, '@')) {
|
2005-05-19 22:55:11 +02:00
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s %c %s: %s", timestamp(), dir,
|
2005-05-19 22:55:11 +02:00
|
|
|
|
ircmask, message);
|
2005-05-13 10:43:50 +02:00
|
|
|
|
} else {
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s %c %s (%s): %s", timestamp(),
|
2005-05-19 22:55:11 +02:00
|
|
|
|
dir, ircmask, destination, message);
|
2005-05-13 10:43:50 +02:00
|
|
|
|
}
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
log_write(logdata, destination, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
void log_privmsg(log_t *logdata, char *ircmask, char *destination,
|
|
|
|
|
char *message)
|
|
|
|
|
{
|
|
|
|
|
_log_privmsg(logdata, ircmask, 0, destination, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_cli_privmsg(log_t *logdata, char *ircmask, char *destination,
|
|
|
|
|
char *message)
|
|
|
|
|
{
|
|
|
|
|
_log_privmsg(logdata, ircmask, 1, destination, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void _log_notice(log_t *logdata, char *ircmask, int src,
|
|
|
|
|
char *destination, char *message)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
{
|
2005-05-19 22:55:11 +02:00
|
|
|
|
char dir = '<';
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!ircmask)
|
|
|
|
|
ircmask = "Server message";
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (src)
|
|
|
|
|
dir = '>';
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (*message == '\001' && *(message + strlen(message) - 1) == '\001')
|
|
|
|
|
return;
|
2005-05-14 10:08:37 +02:00
|
|
|
|
if (ischannel(*destination) || strchr(destination, '@')) {
|
2005-05-21 15:44:09 +02:00
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s %c %s: %s",
|
2005-05-19 22:55:11 +02:00
|
|
|
|
timestamp(), dir, ircmask, message);
|
2005-05-14 10:08:37 +02:00
|
|
|
|
} else {
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s %c %s (%s): %s", timestamp(),
|
2005-05-19 22:55:11 +02:00
|
|
|
|
dir, ircmask, destination, message);
|
2005-05-14 10:08:37 +02:00
|
|
|
|
}
|
|
|
|
|
log_write(logdata, destination, logdata->buffer);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
void log_notice(log_t *logdata, char *ircmask, char *destination,
|
|
|
|
|
char *message)
|
|
|
|
|
{
|
|
|
|
|
_log_notice(logdata, ircmask, 0, destination, message);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_cli_notice(log_t *logdata, char *ircmask, char *destination,
|
|
|
|
|
char *message)
|
|
|
|
|
{
|
|
|
|
|
_log_notice(logdata, ircmask, 1, destination, message);
|
|
|
|
|
}
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
void log_topic(log_t *logdata, char *ircmask, char *channel, char *message)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- %s changed topic of %s to: %s", timestamp(),
|
2005-04-28 10:26:44 +02:00
|
|
|
|
ircmask, channel, message);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_init_topic(log_t *logdata, char *channel, char *message)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- Topic for %s: %s", timestamp(), channel,
|
2005-04-28 10:26:44 +02:00
|
|
|
|
message);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_init_topic_time(log_t *logdata, char *channel, char *who, char *when)
|
|
|
|
|
{
|
|
|
|
|
struct tm *time;
|
|
|
|
|
char *timestr;
|
|
|
|
|
time_t seconds;
|
|
|
|
|
|
|
|
|
|
seconds = atoi(when);
|
|
|
|
|
time = localtime(&seconds);
|
|
|
|
|
timestr = (char*)malloc(sizeof(char) * (50 + 1));
|
|
|
|
|
timestr[0] = '\0';
|
|
|
|
|
if (time)
|
|
|
|
|
strftime(timestr, 50, "%A %d %B %Y, %H:%M:%S", time);
|
|
|
|
|
timestr[50] = '\0';
|
|
|
|
|
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- Topic set by %s [%s]", timestamp(), who,
|
2005-04-28 10:26:44 +02:00
|
|
|
|
timestr);
|
|
|
|
|
free(timestr);
|
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_mode(log_t *logdata, char *ircmask, char *channel, char *modes,
|
|
|
|
|
char **modargv, unsigned modargc)
|
|
|
|
|
{
|
|
|
|
|
unsigned i;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
char *tmpbuf = malloc(LOGLINE_MAXLEN + 1);
|
|
|
|
|
char *tmpbuf2 = malloc(LOGLINE_MAXLEN + 1);
|
|
|
|
|
char *tmp;
|
2005-05-21 15:44:09 +02:00
|
|
|
|
snprintf(tmpbuf, LOGLINE_MAXLEN, "%s -!- mode/%s [%s", timestamp(),
|
2005-05-19 22:55:11 +02:00
|
|
|
|
channel, modes);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
for (i = 0; i < modargc; i++) {
|
2005-05-21 15:44:09 +02:00
|
|
|
|
snprintf(tmpbuf2, LOGLINE_MAXLEN, "%s %s", tmpbuf, modargv[i]);
|
2005-05-19 22:55:11 +02:00
|
|
|
|
tmp = tmpbuf;
|
|
|
|
|
tmpbuf = tmpbuf2;
|
|
|
|
|
tmpbuf2 = tmp;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
2005-05-21 15:44:09 +02:00
|
|
|
|
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s] by %s", tmpbuf,
|
2005-05-19 22:55:11 +02:00
|
|
|
|
ircmask);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
log_write(logdata, channel, logdata->buffer);
|
2005-05-21 15:44:09 +02:00
|
|
|
|
|
|
|
|
|
free(tmpbuf);
|
|
|
|
|
free(tmpbuf2);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_disconnected(log_t *logdata)
|
|
|
|
|
{
|
|
|
|
|
logfilegroup_t *lfg;
|
|
|
|
|
hash_iterator_t hi;
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s -!- Disconnected"
|
2005-05-21 15:44:09 +02:00
|
|
|
|
" from server...", timestamp());
|
2005-04-28 10:26:44 +02:00
|
|
|
|
for (hash_it_init(&logdata->logfgs, &hi); hash_it_item(&hi);
|
|
|
|
|
hash_it_next(&hi)) {
|
|
|
|
|
lfg = hash_it_item(&hi);
|
2005-05-19 22:55:11 +02:00
|
|
|
|
_log_write(logdata, lfg, hash_it_key(&hi), logdata->buffer);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_ping_timeout(log_t *logdata)
|
|
|
|
|
{
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
"%s -!- Ping timeout with server...", timestamp());
|
2005-04-28 10:26:44 +02:00
|
|
|
|
log_write(logdata, "privates", logdata->buffer);
|
|
|
|
|
log_disconnected(logdata);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_connected(log_t *logdata)
|
|
|
|
|
{
|
|
|
|
|
logfilegroup_t *lfg;
|
|
|
|
|
hash_iterator_t hi;
|
|
|
|
|
snprintf(logdata->buffer, LOGLINE_MAXLEN, "%s -!- Connected to"
|
2005-05-21 15:44:09 +02:00
|
|
|
|
" server...", timestamp());
|
2005-04-28 10:26:44 +02:00
|
|
|
|
for (hash_it_init(&logdata->logfgs, &hi); hash_it_item(&hi);
|
|
|
|
|
hash_it_next(&hi)) {
|
|
|
|
|
lfg = hash_it_item(&hi);
|
2005-05-19 22:55:11 +02:00
|
|
|
|
_log_write(logdata, lfg, hash_it_key(&hi), logdata->buffer);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_client_disconnected(log_t *logdata)
|
|
|
|
|
{
|
2005-08-01 13:24:10 +02:00
|
|
|
|
(void)logdata;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
mylog(LOG_DEBUG, "A client disconnected");
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_client_none_connected(log_t *logdata)
|
|
|
|
|
{
|
|
|
|
|
logfilegroup_t *lfg;
|
|
|
|
|
hash_iterator_t hi;
|
|
|
|
|
|
|
|
|
|
logdata->connected = 0;
|
|
|
|
|
|
|
|
|
|
if (conf_always_backlog)
|
|
|
|
|
return;
|
2005-06-04 12:39:04 +02:00
|
|
|
|
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
for (hash_it_init(&logdata->logfgs, &hi); hash_it_item(&hi);
|
|
|
|
|
hash_it_next(&hi)) {
|
|
|
|
|
lfg = hash_it_item(&hi);
|
2005-06-04 12:39:04 +02:00
|
|
|
|
log_reset(lfg);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_client_connected(log_t *logdata)
|
|
|
|
|
{
|
|
|
|
|
mylog(LOG_DEBUG, "A client connected");
|
|
|
|
|
logdata->connected = 1;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_advance_backlogs(log_t* ld, logfilegroup_t *lfg)
|
|
|
|
|
{
|
|
|
|
|
int c;
|
2005-08-01 13:24:10 +02:00
|
|
|
|
(void)ld;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (!conf_backlog || conf_backlog_lines == 0)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (lfg->skip_advance < conf_backlog_lines) {
|
|
|
|
|
lfg->skip_advance++;
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
logfile_t *lf;
|
|
|
|
|
while ((lf = list_get_first(&lfg->file_group))) {
|
|
|
|
|
if (!lf->file) {
|
|
|
|
|
lf->file = fopen(lf->filename, "r");
|
|
|
|
|
if (!lf->file) {
|
|
|
|
|
mylog(LOG_ERROR, "Can't open %s for reading",
|
|
|
|
|
lf->filename);
|
|
|
|
|
log_reinit(lfg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if (fseek(lf->file, lf->backlog_offset, SEEK_SET)) {
|
|
|
|
|
log_reinit(lfg);
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
while ((c = fgetc(lf->file)) != EOF) {
|
|
|
|
|
lf->backlog_offset++;
|
|
|
|
|
if (c == '\n')
|
|
|
|
|
return;
|
|
|
|
|
}
|
|
|
|
|
if (lf == list_get_last(&lfg->file_group))
|
|
|
|
|
return;
|
|
|
|
|
fclose(lf->file);
|
|
|
|
|
lf->file = NULL;
|
|
|
|
|
list_remove_first(&lfg->file_group);
|
|
|
|
|
logfile_free(lf);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int log_has_backlog(log_t *logdata, char *destination)
|
|
|
|
|
{
|
|
|
|
|
logfilegroup_t *lfg = hash_get(&logdata->logfgs, destination);
|
|
|
|
|
|
|
|
|
|
if (!lfg)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (lfg->memlog)
|
|
|
|
|
return !list_is_empty(lfg->memlog);
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
logfile_t *lf;
|
|
|
|
|
lf = list_get_first(&lfg->file_group);
|
|
|
|
|
if (lf != list_get_last(&lfg->file_group))
|
|
|
|
|
return 1;
|
|
|
|
|
|
|
|
|
|
return lf->backlog_offset != lf->len;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define BOLD_CHAR 0x02
|
|
|
|
|
#define LAMESTRING "!bip@bip.bip.bip PRIVMSG "
|
|
|
|
|
|
2005-05-13 12:28:15 +02:00
|
|
|
|
/*
|
2005-07-13 00:24:04 +02:00
|
|
|
|
* chan:
|
|
|
|
|
* 13-05-2005 12:14:29 > nohar: coucou
|
|
|
|
|
* 13-05-2005 12:14:30 < nohar!~nohar@je.suis.t1r.net: coucou
|
|
|
|
|
*
|
|
|
|
|
* private:
|
|
|
|
|
* 13-05-2005 12:14:53 > nohar (jj): 1 luv PHP
|
|
|
|
|
* 13-05-2005 12:14:55 < jj!john@thebox.ofjj.net (nohar): t00 s3xy
|
2005-08-01 11:15:25 +02:00
|
|
|
|
* 01-08-2005 10:46:11 < * jj!john@thebox.ofjj.net
|
2005-05-13 12:28:15 +02:00
|
|
|
|
*/
|
|
|
|
|
|
2005-05-21 15:44:09 +02:00
|
|
|
|
char *log_beautify(char *buf, char *dest)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
{
|
|
|
|
|
int action = 0;
|
|
|
|
|
char *p;
|
|
|
|
|
/*
|
2005-07-13 00:24:04 +02:00
|
|
|
|
* so = startov, lo = lengthov
|
2005-04-28 10:26:44 +02:00
|
|
|
|
* ts = timestamp, n = sender nick, m = message or action
|
|
|
|
|
*/
|
2005-05-13 12:28:15 +02:00
|
|
|
|
char *sots, *son, *som, *sod = NULL;
|
|
|
|
|
size_t lots, lon, lom, lod;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
char *ret;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
int out;
|
2005-06-23 10:01:54 +02:00
|
|
|
|
int done;
|
2005-05-17 11:27:09 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!buf)
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "BUG!");
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
|
|
|
|
p = strchr(buf, ' ');
|
|
|
|
|
if (!p || !p[0] || !p[1])
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
p++;
|
|
|
|
|
sots = p;
|
|
|
|
|
p = strchr(p, ' ');
|
|
|
|
|
if (!p || !p[0] || !p[1])
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
lots = p - sots;
|
|
|
|
|
p++;
|
2006-10-21 14:06:31 +02:00
|
|
|
|
if (strncmp(p, "-!-", 3) == 0) {
|
|
|
|
|
if (conf_bl_msg_only)
|
|
|
|
|
return NULL;
|
|
|
|
|
else
|
|
|
|
|
return _log_wrap(dest, buf);
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
|
|
|
|
if (*p == '>')
|
|
|
|
|
out = 1;
|
|
|
|
|
else if (*p == '<')
|
|
|
|
|
out = 0;
|
|
|
|
|
else
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-05-19 22:55:11 +02:00
|
|
|
|
p++;
|
|
|
|
|
if (*p != ' ')
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2005-05-19 22:55:11 +02:00
|
|
|
|
p++;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (*p == '*') {
|
|
|
|
|
action = 1;
|
|
|
|
|
if (!p[1] || !p[2])
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
p += 2;
|
|
|
|
|
}
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
son = p;
|
2005-05-12 10:29:27 +02:00
|
|
|
|
while (*p && *p != '!' && *p != ' ' && *p != ':')
|
2005-05-02 00:29:31 +02:00
|
|
|
|
p++;
|
2005-08-01 11:15:25 +02:00
|
|
|
|
if (!p[0])
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
lon = p - son;
|
2005-06-23 10:01:54 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
p = strchr(p, ' ');
|
2005-08-01 11:15:25 +02:00
|
|
|
|
if (!p || !p[0])
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-07-13 00:24:04 +02:00
|
|
|
|
done = ((p[-1] == ':') || (action && (p[1] != '(')));
|
2005-04-28 10:26:44 +02:00
|
|
|
|
p++;
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-07-13 00:24:04 +02:00
|
|
|
|
/*
|
|
|
|
|
* TODO add a : before the action text in the log files
|
|
|
|
|
* otherwise "/me (bla) blabla" on a chan is logged exactly as
|
|
|
|
|
* "/me blabla" in a query with bla.
|
|
|
|
|
*/
|
|
|
|
|
if (!done) {
|
2005-05-14 10:08:37 +02:00
|
|
|
|
p++;
|
|
|
|
|
if (!p[0] || !p[1] || p[0] == ')')
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2005-05-13 12:28:15 +02:00
|
|
|
|
sod = p;
|
2005-07-13 00:24:04 +02:00
|
|
|
|
while (*p && *p != ')' && *p != ' ' && *p != '!')
|
2005-05-13 12:28:15 +02:00
|
|
|
|
p++;
|
|
|
|
|
lod = p - sod;
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-07-13 00:24:04 +02:00
|
|
|
|
if (*p == '!')
|
|
|
|
|
while (*p && *p != ')' && *p != ' ')
|
|
|
|
|
p++;
|
|
|
|
|
|
|
|
|
|
if (!p[0] || p[0] != ')' || !p[1] || p[1] != ':' ||
|
|
|
|
|
!p[2] || p[2] != ' ' || !p[3] || !p[4])
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap(dest, buf);
|
2005-07-13 00:24:04 +02:00
|
|
|
|
p += 3;
|
2005-05-13 12:28:15 +02:00
|
|
|
|
} else {
|
|
|
|
|
sod = dest;
|
|
|
|
|
lod = strlen(dest);
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
|
|
|
|
if (out && strcmp(dest, "privates") == 0) {
|
2005-05-29 01:08:54 +02:00
|
|
|
|
char *stmp;
|
|
|
|
|
size_t ltmp;
|
2005-06-23 10:01:54 +02:00
|
|
|
|
|
2005-05-29 01:08:54 +02:00
|
|
|
|
stmp = sod;
|
|
|
|
|
ltmp = lod;
|
|
|
|
|
|
|
|
|
|
sod = son;
|
|
|
|
|
lod = lon;
|
|
|
|
|
|
|
|
|
|
son = stmp;
|
|
|
|
|
lon = ltmp;
|
2005-05-14 10:08:37 +02:00
|
|
|
|
}
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
som = p;
|
|
|
|
|
lom = strlen(p);
|
2005-05-21 15:44:09 +02:00
|
|
|
|
if (lom == 0)
|
|
|
|
|
return _log_wrap(dest, buf);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
|
|
|
|
p = ret = (char *)malloc(
|
2005-07-13 00:24:04 +02:00
|
|
|
|
1 + lon + strlen(LAMESTRING) + lod + 2 + lots + 1 + lom + 3
|
|
|
|
|
+ action * (2 + strlen("ACTION ")) + out * strlen(" -> "));
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!p)
|
|
|
|
|
fatal("out of memory");
|
2005-07-13 00:24:04 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
*p++ = ':';
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
memcpy(p, son, lon);
|
|
|
|
|
p += lon;
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
strcpy(p, LAMESTRING);
|
|
|
|
|
p += strlen(LAMESTRING);
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
|
|
|
|
memcpy(p, sod, lod);
|
|
|
|
|
p += lod;
|
|
|
|
|
|
2005-07-13 00:24:04 +02:00
|
|
|
|
*p++ = ' ';
|
|
|
|
|
*p++ = ':';
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (action) {
|
|
|
|
|
*p++ = 1;
|
2005-07-13 00:24:04 +02:00
|
|
|
|
strcpy(p, "ACTION ");
|
2005-05-08 23:09:11 +02:00
|
|
|
|
p += strlen("ACTION ");
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (out) {
|
2005-07-13 00:24:04 +02:00
|
|
|
|
strcpy(p, " -> ");
|
|
|
|
|
p += strlen(" -> ");
|
2005-05-14 10:08:37 +02:00
|
|
|
|
}
|
2005-04-28 10:26:44 +02:00
|
|
|
|
memcpy(p, sots, lots);
|
2005-05-02 00:29:31 +02:00
|
|
|
|
p += lots;
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
*p++ = ' ';
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
memcpy(p, som, lom);
|
|
|
|
|
p += lom;
|
2005-05-13 12:28:15 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (action)
|
|
|
|
|
*p++ = 1;
|
2006-10-21 14:06:31 +02:00
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
*p++ = '\r';
|
|
|
|
|
*p++ = '\n';
|
|
|
|
|
*p = 0;
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-12 14:22:32 +01:00
|
|
|
|
char *log_backread(log_t *logdata, char *destination, int *skip)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
{
|
|
|
|
|
char *buf;
|
|
|
|
|
size_t pos = 0;
|
|
|
|
|
logfile_t *lf;
|
|
|
|
|
logfilegroup_t *lfg;
|
|
|
|
|
int c;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
char *ret;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
|
2006-11-12 14:22:32 +01:00
|
|
|
|
*skip = 0;
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!conf_always_backlog && logdata->connected)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
lfg = hash_get(&logdata->logfgs, destination);
|
|
|
|
|
if (!lfg)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
if (!logdata->backlogging) {
|
|
|
|
|
logdata->backlogging = 1;
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "backlogging!");
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (lfg->memlog)
|
|
|
|
|
list_it_init(lfg->memlog, &lfg->backlog_it);
|
|
|
|
|
else
|
|
|
|
|
list_it_init(&lfg->file_group, &logdata->file_it);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
|
|
|
|
if (lfg->memlog) {
|
|
|
|
|
char *ptr;
|
|
|
|
|
ptr = list_it_item(&lfg->backlog_it);
|
|
|
|
|
if (!ptr) {
|
|
|
|
|
logdata->backlogging = 0;
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
list_it_next(&lfg->backlog_it);
|
|
|
|
|
return strdup(ptr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!conf_log)
|
|
|
|
|
return NULL;
|
|
|
|
|
|
|
|
|
|
buf = (char *)malloc((LOGLINE_MAXLEN + 1) * sizeof(char));
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
next_file:
|
|
|
|
|
/* check the files containing data to backlog */
|
|
|
|
|
lf = list_it_item(&logdata->file_it);
|
|
|
|
|
if (lf != list_get_last(&lfg->file_group)) {
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "%s not last file!", lf->filename);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
/* if the file is not the current open for logging
|
|
|
|
|
* (it is an old file that has been rotated)
|
|
|
|
|
* open if necessary, backlog line per line, and close */
|
|
|
|
|
if (!lf->file) {
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "opening: %s!", lf->filename);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
lf->file = fopen(lf->filename, "r");
|
|
|
|
|
if (!lf->file) {
|
|
|
|
|
mylog(LOG_ERROR, "Can't open %s for reading",
|
|
|
|
|
lf->filename);
|
|
|
|
|
log_reinit(lfg);
|
2005-05-13 10:43:50 +02:00
|
|
|
|
free(buf);
|
2005-05-21 15:44:09 +02:00
|
|
|
|
return _log_wrap("Error reading logfile",
|
|
|
|
|
destination);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "seeking: %d!", lf->backlog_offset);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (fseek(lf->file, lf->backlog_offset, SEEK_SET)) {
|
|
|
|
|
log_reinit(lfg);
|
2005-05-13 10:43:50 +02:00
|
|
|
|
free(buf);
|
2006-11-22 23:06:06 +01:00
|
|
|
|
return _log_wrap(destination,
|
|
|
|
|
"Error reading in logfile");
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
for(;;) {
|
|
|
|
|
c = fgetc(lf->file);
|
|
|
|
|
if (!conf_always_backlog)
|
|
|
|
|
lf->backlog_offset++;
|
2005-05-13 10:43:50 +02:00
|
|
|
|
if (c == EOF || c == '\n' || pos == LOGLINE_MAXLEN) {
|
|
|
|
|
/* change file if we reach EOF, if pos == maxlen
|
|
|
|
|
* then the log file is corrupted so we also
|
|
|
|
|
* drop this file */
|
|
|
|
|
if (pos == LOGLINE_MAXLEN)
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "logline too long");
|
2005-05-13 10:43:50 +02:00
|
|
|
|
if (c == EOF || pos == LOGLINE_MAXLEN) {
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "EOF: %s (%d)!",
|
2005-05-13 10:43:50 +02:00
|
|
|
|
lf->filename,
|
|
|
|
|
conf_always_backlog);
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
list_it_next(&logdata->file_it);
|
|
|
|
|
if (!conf_always_backlog) {
|
|
|
|
|
list_remove_first(
|
|
|
|
|
&lfg->file_group);
|
|
|
|
|
logfile_free(lf);
|
|
|
|
|
} else {
|
|
|
|
|
fclose(lf->file);
|
|
|
|
|
lf->file = NULL;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
pos = 0;
|
|
|
|
|
goto next_file;
|
|
|
|
|
}
|
|
|
|
|
buf[pos] = 0;
|
2006-11-12 14:22:32 +01:00
|
|
|
|
if (pos == 0) {
|
|
|
|
|
*skip = 1;
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
2005-05-21 15:44:09 +02:00
|
|
|
|
ret = log_beautify(buf, destination);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
if (ret == NULL) {
|
|
|
|
|
pos = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
free(buf);
|
|
|
|
|
return ret;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
buf[pos++] = c;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* the logfile to read is the one open for writing */
|
|
|
|
|
if (!logdata->lastfile_seeked) {
|
|
|
|
|
if (fseek(lf->file, lf->backlog_offset, SEEK_SET)) {
|
|
|
|
|
log_reinit(lfg);
|
2006-11-22 23:06:06 +01:00
|
|
|
|
return _log_wrap(destination,
|
|
|
|
|
"Error reading in logfile");
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
logdata->lastfile_seeked = 1;
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "last file seedked!");
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
c = fgetc(lf->file);
|
|
|
|
|
if (c == EOF) {
|
|
|
|
|
logdata->lastfile_seeked = 0;
|
|
|
|
|
logdata->backlogging = 0;
|
|
|
|
|
free(buf);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
if (!conf_always_backlog)
|
|
|
|
|
lf->backlog_offset++;
|
|
|
|
|
|
|
|
|
|
if (c != '\n')
|
|
|
|
|
buf[pos++] = c;
|
|
|
|
|
for(;;) {
|
|
|
|
|
c = fgetc(lf->file);
|
|
|
|
|
if (!conf_always_backlog)
|
|
|
|
|
lf->backlog_offset++;
|
2005-05-13 10:43:50 +02:00
|
|
|
|
if (c == EOF || c == '\n' || pos == LOGLINE_MAXLEN) {
|
|
|
|
|
if (pos == LOGLINE_MAXLEN) {
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "logline too long");
|
2005-05-13 10:43:50 +02:00
|
|
|
|
fseek(lf->file, 0, SEEK_END);
|
|
|
|
|
/* in the corruption case we alwayse reset
|
|
|
|
|
* backlog offset */
|
|
|
|
|
lf->backlog_offset = ftell(lf->file);
|
|
|
|
|
free(buf);
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2006-11-16 15:34:28 +01:00
|
|
|
|
if (!conf_always_backlog && c == EOF)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
lf->backlog_offset--;
|
|
|
|
|
buf[pos] = 0;
|
2006-11-12 14:22:32 +01:00
|
|
|
|
if (pos == 0) {
|
|
|
|
|
*skip = 1;
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
2005-05-21 15:44:09 +02:00
|
|
|
|
ret = log_beautify(buf, destination);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
if (ret == NULL) {
|
|
|
|
|
pos = 0;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
free(buf);
|
|
|
|
|
return ret;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
buf[pos++] = c;
|
|
|
|
|
}
|
|
|
|
|
/* unreachable */
|
|
|
|
|
fatal("internal error 12");
|
|
|
|
|
return NULL;
|
|
|
|
|
}
|
|
|
|
|
|
2005-05-21 15:44:09 +02:00
|
|
|
|
static char *_log_wrap(char *dest, char *line)
|
2005-05-19 22:55:11 +02:00
|
|
|
|
{
|
|
|
|
|
char *buf;
|
2005-05-21 15:44:09 +02:00
|
|
|
|
size_t count;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
|
|
|
|
buf = malloc(LOGLINE_MAXLEN + 1);
|
|
|
|
|
count = snprintf(buf, LOGLINE_MAXLEN + 1,
|
2005-05-21 15:44:09 +02:00
|
|
|
|
":" P_IRCMASK " PRIVMSG %s :%s\r\n", dest, line);
|
2005-05-19 22:55:11 +02:00
|
|
|
|
if (count >= LOGLINE_MAXLEN + 1) {
|
2005-11-17 18:55:12 +01:00
|
|
|
|
mylog(LOG_DEBUG, "line too long");
|
2005-05-19 22:55:11 +02:00
|
|
|
|
buf[LOGLINE_MAXLEN - 2] = '\r';
|
|
|
|
|
buf[LOGLINE_MAXLEN - 1] = '\n';
|
|
|
|
|
buf[LOGLINE_MAXLEN] = 0;
|
|
|
|
|
}
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int _log_write(log_t *logdata, logfilegroup_t *lfg, char *destination,
|
2006-10-21 14:06:31 +02:00
|
|
|
|
char *str)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
{
|
|
|
|
|
size_t nbwrite;
|
|
|
|
|
size_t len;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
2005-05-21 15:44:09 +02:00
|
|
|
|
str[LOGLINE_MAXLEN] = 0;
|
2005-05-19 22:55:11 +02:00
|
|
|
|
|
|
|
|
|
if (lfg->memlog) {
|
2005-05-21 15:44:09 +02:00
|
|
|
|
char *r = log_beautify(str, destination);
|
2006-10-21 14:06:31 +02:00
|
|
|
|
if (r != NULL) {
|
|
|
|
|
list_add_last(lfg->memlog, r);
|
|
|
|
|
if (lfg->memc == conf_backlog_lines)
|
|
|
|
|
free(list_remove_first(lfg->memlog));
|
|
|
|
|
else
|
|
|
|
|
lfg->memc++;
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (!conf_log)
|
|
|
|
|
return 0;
|
|
|
|
|
|
2005-04-28 10:26:44 +02:00
|
|
|
|
logfile_t *lf = list_get_last(&lfg->file_group);
|
|
|
|
|
|
|
|
|
|
len = strlen(str);
|
|
|
|
|
nbwrite = fwrite(str, sizeof(char), len, lf->file);
|
2005-05-21 15:44:09 +02:00
|
|
|
|
nbwrite += fwrite("\n", sizeof(char), 1, lf->file);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
log_updatelast(lf);
|
2005-05-21 15:44:09 +02:00
|
|
|
|
if (nbwrite != len + 1)
|
2005-04-28 10:26:44 +02:00
|
|
|
|
mylog(LOG_ERROR, "Error writing to %s logfile", lf->filename);
|
|
|
|
|
lf->len += nbwrite;
|
|
|
|
|
if (!logdata->connected || conf_always_backlog)
|
|
|
|
|
log_advance_backlogs(logdata, lfg);
|
|
|
|
|
return nbwrite;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void log_write(log_t *logdata, char *destination, char *str)
|
|
|
|
|
{
|
|
|
|
|
logfilegroup_t *lfg = log_find_file(logdata, destination);
|
|
|
|
|
if (!lfg) {
|
|
|
|
|
mylog(LOG_ERROR, "Unable to find/create logfile for '%s'",
|
|
|
|
|
destination);
|
|
|
|
|
return;
|
|
|
|
|
}
|
2005-05-19 22:55:11 +02:00
|
|
|
|
_log_write(logdata, lfg, destination, str);
|
2005-04-28 10:26:44 +02:00
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static list_t *log_all_logs = NULL;
|
|
|
|
|
|
|
|
|
|
void log_flush_all(void)
|
|
|
|
|
{
|
|
|
|
|
list_iterator_t li;
|
|
|
|
|
if (!log_all_logs)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (list_it_init(log_all_logs, &li); list_it_item(&li);
|
|
|
|
|
list_it_next(&li)) {
|
|
|
|
|
log_t *log = list_it_item(&li);
|
|
|
|
|
hash_iterator_t hi;
|
|
|
|
|
for (hash_it_init(&log->logfgs, &hi); hash_it_item(&hi);
|
|
|
|
|
hash_it_next(&hi)) {
|
|
|
|
|
logfilegroup_t *lfg = hash_it_item(&hi);
|
|
|
|
|
list_iterator_t lj;
|
|
|
|
|
for (list_it_init(&lfg->file_group, &lj);
|
|
|
|
|
list_it_item(&lj); list_it_next(&lj)) {
|
|
|
|
|
logfile_t *lf = list_it_item(&lj);
|
|
|
|
|
if (lf->file)
|
|
|
|
|
fflush(lf->file);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
log_t *log_new(char *user, char *network)
|
|
|
|
|
{
|
|
|
|
|
log_t *logdata;
|
|
|
|
|
|
|
|
|
|
logdata = (log_t*)calloc(sizeof(log_t), 1);
|
|
|
|
|
if (!logdata)
|
|
|
|
|
fatal("out of memory");
|
|
|
|
|
logdata->user = strdup(user);
|
|
|
|
|
logdata->network = strdup(network);
|
|
|
|
|
hash_init(&logdata->logfgs, HASH_NOCASE);
|
2005-05-13 10:43:50 +02:00
|
|
|
|
logdata->buffer = (char *)malloc((LOGLINE_MAXLEN + 1) * sizeof(char));
|
2005-05-21 15:44:09 +02:00
|
|
|
|
logdata->buffer[LOGLINE_MAXLEN - 1] = 0; // debug
|
|
|
|
|
logdata->buffer[LOGLINE_MAXLEN] = 0;
|
2005-04-28 10:26:44 +02:00
|
|
|
|
if (!logdata->user || !logdata->network || !logdata->buffer)
|
|
|
|
|
fatal("out of memory");
|
|
|
|
|
logdata->connected = 0;
|
|
|
|
|
if (!log_all_logs)
|
|
|
|
|
log_all_logs = list_new(NULL);
|
|
|
|
|
list_add_last(log_all_logs, logdata);
|
|
|
|
|
return logdata;
|
|
|
|
|
}
|