#ifdef HAVE_CONFIG_H
#include "config.h"
#endif
#ifdef HAVE_PRINTF_H
#ifdef HAVE_STDIO_H
#include <stdio.h>
#endif
#include <stdlib.h>
#ifdef HAVE_TIME_H
#include <time.h>
#endif
#ifdef HAVE_SYSLOG_H
#include <syslog.h>
#endif
#include <wchar.h>
#include "sigparams.h"
#include "util.h"
/*
signature parameters: custom printf conversion codes that can be
used to add computed information to a signature block
by MAtteo HCE Valsasna <valsasna@uninsubria.it>
*/
extern int debug;
/*
add to this array the conversion functions to be registered */
static struct param_info {
int conv_specifier;
int (*print_fun) (FILE *stream,
const struct printf_info *info,
const void *const *args);
} conversions[] =
{
{'R', print_count },
{'D', print_delta },
{'T', print_time },
{'Y', print_daycount },
{'H', print_first_in_day },
/* terminator ;) */
{'0', NULL }
};
/* global vars used to create a process status informations an user
could find useful
*/
/* process fire count*/
int count;
/* daily fire count */
int day_count;
int first_in_day;
time_t current_time, last_eval_time, process_start_time;
/* used to detect day change */
int last_eval_day;
int last_eval_month;
char * first_in_day_msg;
#define init_sigparams_BUFSIZE 256
/* module initialization */
void init_sigparams()
{
int rv = 0;
char errmsg[init_sigparams_BUFSIZE];
int ii;
count = 0;
day_count = 0;
/* TODO: should be customizable */
first_in_day_msg =
"you are my first mail recipient of the day, congratulations!\n";
first_in_day = 1;
time(& process_start_time);
current_time = process_start_time;
/* register conversion functions */
for (ii = 0; conversions[ii].print_fun; ii ++)
{
rv = register_printf_function (conversions[ii].conv_specifier,
conversions[ii].print_fun,
print_arginfo);
if (rv != 0) {
snprintf(errmsg, init_sigparams_BUFSIZE,
"sigparams.c: initializing %c (%d) conversion",
conversions[ii].conv_specifier,
conversions[ii].conv_specifier);
perror(errmsg);
exit(1);
}
}
}
/*
this function gets called at every read of .signature, before the
actual signature printig happens.
all status collecting code should go here - NOT in print_*
functions - so that if conversion specifiers are added or removed
from .signature.tmpl without restarting gensig, status is still
computed correctly
*/
void foreach_sigparams()
{
int current_day, current_month;
count ++;
day_count ++;
last_eval_time = current_time;
time(& current_time);
current_day = localtime(& current_time) -> tm_mday;
current_month = localtime(& current_time) -> tm_mon;
/* see if this is the first run in a new day, taking care of
februaries (if we just compared days, an user reading a signature
on the Nth of february and doing the next read on the Nth of
march would not get the first_in_day message) */
if (current_day != last_eval_day ||
current_month != last_eval_month)
{
last_eval_day = current_day;
last_eval_month = current_month;
day_count = 1;
first_in_day = 1;
}
else first_in_day = 0;
/* we are computing time differencies, a good position to detect
clock skews */
if (difftime(current_time, last_eval_time) < 0)
{
if (debug)
{
fprintf(stderr, "time warp? wonderful!\n");
fprintf(stderr, "last time run: %s\n", ctime(&last_eval_time));
fprintf(stderr, "current time: %s\n", ctime(¤t_time));
}
else
{
openlog("gensig", LOG_PID, LOG_USER);
syslog(LOG_WARNING, "time warp? wonderful!");
syslog(LOG_WARNING, "last time run: %s", ctime(&last_eval_time));
syslog(LOG_WARNING, "current time: %s", ctime(¤t_time));
}
}
}
/*
print_arginfo:
this is called by *printf to know how many arguments to pass to
print_* when a %? conversion specifier is found in the format
string
since we are printing values that depend on program state and not
on user input, we always return 0
*/
int print_arginfo (const struct printf_info *info, size_t n,
int *argtypes)
{
return 0;
}
/*
TODO: print_* functions could consider the info parameter they
receive (it contains formatting instructions)
*/
/* count: number of times .signature was read in process life */
int print_count(FILE *stream,
const struct printf_info *info,
const void *const *args)
{
return fprintf(stream, "%d", count);
}
/* delta: time elapsed since last read */
int print_delta(FILE *stream,
const struct printf_info *info,
const void *const *args)
{
int seconds = (int) difftime(current_time, last_eval_time);
return fprint_delta(stream, seconds);
}
/* time: time elapsed since process start */
int print_time(FILE *stream,
const struct printf_info *info,
const void *const *args)
{
int seconds = (int) difftime(current_time, process_start_time);
return fprint_delta(stream, seconds);
}
/* day count: number of reads in a day */
int print_daycount(FILE *stream,
const struct printf_info *info,
const void *const *args)
{
return fprintf(stream, "%d", day_count);
}
/* first in day: pring a message for the first read in a day */
int print_first_in_day(FILE *stream,
const struct printf_info *info,
const void *const *args)
{
if (first_in_day)
{
return fprintf(stream, "%s", first_in_day_msg);
}
else return 0;
}
#endif
syntax highlighted by Code2HTML, v. 0.9.1