/*
* counter.c: repeated message counters
*
* Copyright(c) 1998-2000 - All Rights Reserved
*
* See the COPYRIGHT file.
*/
#ifndef lint
static char rcsid[] = "@(#)$Id: counter.c,v 1.5 2000/07/31 22:33:55 kalt Exp $";
#endif
#include "os.h"
#include "struct.h"
#include "option.h"
#include "term.h"
#include "utils.h"
#include "window.h"
extern struct server_ *server;
#if defined(HAVE_REGEXP)
struct counter_
{
void *reference;
char *string;
struct server_ *server;
regmatch_t pmatch[20];
time_t vfirst, first, last;
int tcount, count;
char ematch; /* exact matches */
};
static struct counter_ *counters;
static unsigned int cnt_max, cnt_inuse = 0;
# define CNT_PERIOD 600
# define CNT_EXPIRE 120
#endif
void
counter_init()
{
#if defined(HAVE_REGEXP)
cnt_max = 100;
counters = (struct counter_ *) malloc(cnt_max*sizeof(struct counter_));
bzero(counters, cnt_max*sizeof(struct counter_));
#endif
}
#if defined(HAVE_REGEXP)
/* counter_expire: expires entries in counters array */
void
counter_expire(entry)
int entry;
{
if (entry >= 0)
{
time_t now = time(NULL);
if (now - counters[entry].last > CNT_EXPIRE)
{
free(counters[entry].string);
counters[entry].string = NULL;
cnt_inuse--;
}
}
else
{
vsic_slog(LOG_DEBUG, "counter_expire(-1): cnt_inuse = %d / cnt_max = %d",
cnt_inuse, cnt_max);
for (entry = 0; entry < cnt_max; entry++)
if (counters[entry].string != NULL)
counter_expire(entry);
vsic_slog(LOG_DEBUG, "finished: cnt_inuse = %d / cnt_max = %d",
cnt_inuse, cnt_max);
}
}
/* counter_check: is it time to display something? */
static void
counter_check(entry)
int entry;
{
time_t now = time(NULL);
if (now - counters[entry].first > CNT_PERIOD)
{
char tbuf[40];
counters[entry].tcount += counters[entry].count;
if (counters[entry].vfirst == counters[entry].first)
vsic_slog(LOG_CLIENT,
"--- Next message repeated %d time%s over last %d seconds.",
counters[entry].count,
(counters[entry].count > 1) ? "s" : "",
counters[entry].last - counters[entry].first);
else
vsic_slog(LOG_CLIENT, "--- Next message repeated %d time%s over last %d seconds (%d times since %s).",
counters[entry].count,
(counters[entry].count > 1) ? "s" : "",
counters[entry].last - counters[entry].first,
counters[entry].tcount,
my_cftime(tbuf, 40, "%x %X", counters[entry].vfirst));
counters[entry].count = 0;
counters[entry].ematch = 1;
}
}
/* counter_add: count */
int
counter_add(ref, string, attributes, pmatch, flags, channel)
void *ref;
char *string, *channel;
char *attributes;
regmatch_t *pmatch;
unsigned int *flags;
{
int i, j;
for (i = 0; i < cnt_max; i++)
{
if (counters[i].reference != ref)
continue;
if (counters[i].string == NULL)
continue;
for (j = 1; pmatch[j].rm_so != -1; j++)
if (counters[i].server == server
&& !strncasecmp(string + pmatch[j].rm_so,
counters[i].string + counters[i].pmatch[j].rm_so,
pmatch[j].rm_eo - pmatch[j].rm_so))
break;
if (pmatch[j].rm_so != -1)
break;
}
if (i == cnt_max)
{
for (i = 0; i < cnt_max; i++)
if (counters[i].string == NULL)
break;
if (i == cnt_max)
{
counters = realloc(counters,
sizeof(struct counter_)*(cnt_max += 100));
bzero(counters+cnt_max-100, 100*sizeof(struct counter_));
}
cnt_inuse++;
counters[i].reference = ref;
counters[i].string = strdup(string);
counters[i].server = server;
counters[i].vfirst = counters[i].first = counters[i].last = time(NULL);
bcopy(pmatch, counters[i].pmatch, 20*sizeof(regmatch_t));
counters[i].tcount = counters[i].count = 1;
counters[i].ematch = 1;
}
else
{
counters[i].last = time(NULL);
if (counters[i].count++ == 0)
counters[i].first = counters[i].last;
if (counters[i].ematch == 1 && strcasecmp(string, counters[i].string))
counters[i].ematch = 0;
}
j = counters[i].ematch;
counter_check(i);
if (counters[i].count > 0
&& !(counters[i].count == 1 && counters[i].vfirst == counters[i].first))
/* ignore,
** unless do_repeat() just reseted the count (displaying a message),
** or this is the very first message of this kind received.
*/
*flags |= LOG_IGNORE;
if (j == 0
&& !(counters[i].count == 1 && counters[i].vfirst == counters[i].first)
&& get_option(Z_VCOUNT, channel))
{
for (j = 1; pmatch[j].rm_so != -1; j++)
{
char *ch = attributes + pmatch[j].rm_so;
while (ch < attributes + pmatch[j].rm_eo)
*ch++ |= TERM_UNDERLINE;
}
return 1;
}
return 0;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1