ban2fail/timestamp.c

162 lines
4.9 KiB
C

/***************************************************************************
* Copyright (C) 2019 by John D. Robertson *
* john@rrci.com *
* *
* 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 3 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 *
* *
* You should have received a copy of the GNU General Public License *
* along with this program; if not, write to the *
* Free Software Foundation, Inc., *
* 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
***************************************************************************/
#define _GNU_SOURCE
#include "ez_libc.h"
#include "timestamp.h"
#include "util.h"
enum Flags {
GUESS_YR_FLG= 1<<0
};
const static struct bitTuple FlagsBitTupleArr[]= {
{.name= "GUESS_YEAR", .bit= GUESS_YR_FLG},
{/* Terminating member */}
};
int
TS_init(TS *self, CFGMAP *h_map, const char *pfix)
/********************************************************
* Initialize timestamp from config map.
*/
{
int rtn= -1;
memset(self, 0, sizeof(*self));
size_t len= strlen(pfix)+1024;
char symBuf[len];
{ /*--- Check for "REGEX" symbol ---*/
snprintf(symBuf, len, "%s\\REGEX", pfix);
/* CFGMAP is left in place, so we don't need to strdup() */
self->pattern= CFGMAP_find_last_value(h_map, symBuf);
if(!self->pattern) {
eprintf("ERROR: cannot find \"REGEX\" entry for ENTRY_TIMESTAMP %s", pfix);
goto abort;
}
if(regex_compile(&self->re, self->pattern, REG_EXTENDED)) {
eprintf("ERROR: regex_compile(\"%s\") failed.", self->pattern);
goto abort;
}
}
{ /*--- Check for "STRPTIME" symbol ---*/
snprintf(symBuf, len, "%s\\STRPTIME", pfix);
/* CFGMAP is left in place, so we don't need to strdup() */
self->strptime_fmt= CFGMAP_find_last_value(h_map, symBuf);
if(!self->strptime_fmt) {
eprintf("ERROR: cannot find \"STRPTIME\" entry for ENTRY_TIMESTAMP %s", pfix);
goto abort;
}
}
{ /*--- Check for "FLAGS" symbol ---*/
const char *flagStr;
snprintf(symBuf, len, "%s\\FLAGS", pfix);
flagStr= CFGMAP_find_last_value(h_map, symBuf);
/* This is optional */
if(flagStr) {
int rc= str2bits(&self->flags, flagStr, FlagsBitTupleArr);
if(rc) {
eprintf("ERROR: cannot interpret \"FLAGS\" entry for ENTRY_TIMESTAMP %s", pfix);
goto abort;
}
}
}
rtn= 0;
abort:
return rtn;
}
void*
TS_destructor(TS *self)
/********************************************************
* Free resources.
*/
{
if(self->pattern)
regfree(&self->re);
return self;
}
int
TS_scan(const TS *self, time_t *rslt, const char *str, const struct tm *pTmRef)
/********************************************************
* Scan a string to obtain the timestamp.
*/
{
int rtn= -1;
/* If there is no match, continue looking */
regmatch_t matchArr[2];
if(0 != regexec(&self->re, str, 2, matchArr, 0) || -1 == matchArr[1].rm_so) {
eprintf("ERROR: failed to identify date in \"%s\"", str);
goto abort;
}
unsigned len= matchArr[1].rm_eo - matchArr[1].rm_so;
static char date[128];
strncpy(date, str+matchArr[1].rm_so, sizeof(date)-1);
date[MIN(len, sizeof(date)-1)]= '\0';
static struct tm tm;
memset(&tm, 0, sizeof(tm));
tm.tm_isdst= -1;
const char *lc= ez_strptime(date, self->strptime_fmt, &tm);
/* We may have to guess the year */
if(self->flags & GUESS_YR_FLG) {
tm.tm_year= pTmRef->tm_year;
if(tm.tm_mon > pTmRef->tm_mon)
--tm.tm_year;
}
*rslt= mktime(&tm);
//eprintf("Date string= \"%s\", lc= \"%s\", =? \"%s\"", date, lc, ctime(rslt));
rtn= 0;
abort:
return rtn;
}
int
TS_MD5_update(const TS *self, MD5_CTX *ctx)
/********************************************************
* For computing MD5 checksum of config data.
*/
{
if(self->pattern)
MD5_Update(ctx, self->pattern, strlen(self->pattern));
if(self->strptime_fmt)
MD5_Update(ctx, self->strptime_fmt, strlen(self->strptime_fmt));
MD5_Update(ctx, &self->flags, sizeof(self->flags));
return 0;
}