diff options
author | Rainer Gerhards <rgerhards@adiscon.com> | 2008-04-16 10:26:54 +0200 |
---|---|---|
committer | Rainer Gerhards <rgerhards@adiscon.com> | 2008-04-16 10:26:54 +0200 |
commit | 8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc (patch) | |
tree | 8bd92ca19ae3cccd5b160c717960db88bb095e73 /datetime.c | |
parent | 3af28bbd2dc4c79b242aad3b9e3f45cffe0f19d0 (diff) | |
download | rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.gz rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.tar.xz rsyslog-8f8f65abb66d1a7839c30c2d1b4b4d653a8990cc.zip |
moved files to the runtime
there are still some files left which could go into the
runtime, but I think we will delete most of them once we
are done with the full modularization.
Diffstat (limited to 'datetime.c')
-rw-r--r-- | datetime.c | 629 |
1 files changed, 0 insertions, 629 deletions
diff --git a/datetime.c b/datetime.c deleted file mode 100644 index a4817a6d..00000000 --- a/datetime.c +++ /dev/null @@ -1,629 +0,0 @@ -/* The datetime object. It contains date and time related functions. - * - * Module begun 2008-03-05 by Rainer Gerhards, based on some code - * from syslogd.c. The main intension was to move code out of syslogd.c - * in a useful manner. It is still undecided if all functions will continue - * to stay here or some will be moved into parser modules (once we have them). - * - * Copyright 2008 Rainer Gerhards and Adiscon GmbH. - * - * This file is part of rsyslog. - * - * Rsyslog 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. - * - * Rsyslog 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. - * - * You should have received a copy of the GNU General Public License - * along with Rsyslog. If not, see <http://www.gnu.org/licenses/>. - * - * A copy of the GPL can be found in the file "COPYING" in this distribution. - */ - -#include "config.h" -#include <stdio.h> -#include <stdlib.h> -#include <stdarg.h> -#include <ctype.h> -#include <assert.h> -#ifdef HAVE_SYS_TIME_H -# include <sys/time.h> -#endif - -#include "rsyslog.h" -#include "obj.h" -#include "modules.h" -#include "datetime.h" -#include "sysvar.h" -#include "srUtils.h" -#include "stringbuf.h" -#include "errmsg.h" - -/* static data */ -DEFobjStaticHelpers -DEFobjCurrIf(errmsg) - - -/* ------------------------------ methods ------------------------------ */ - - -/** - * Get the current date/time in the best resolution the operating - * system has to offer (well, actually at most down to the milli- - * second level. - * - * The date and time is returned in separate fields as this is - * most portable and removes the need for additional structures - * (but I have to admit it is somewhat "bulky";)). - * - * Obviously, all caller-provided pointers must not be NULL... - */ -static void getCurrTime(struct syslogTime *t) -{ - struct timeval tp; - struct tm *tm; - struct tm tmBuf; - long lBias; -# if defined(__hpux) - struct timezone tz; -# endif - - assert(t != NULL); -# if defined(__hpux) - /* TODO: check this: under HP UX, the tz information is actually valid - * data. So we need to obtain and process it there. - */ - gettimeofday(&tp, &tz); -# else - gettimeofday(&tp, NULL); -# endif - tm = localtime_r((time_t*) &(tp.tv_sec), &tmBuf); - - t->year = tm->tm_year + 1900; - t->month = tm->tm_mon + 1; - t->day = tm->tm_mday; - t->hour = tm->tm_hour; - t->minute = tm->tm_min; - t->second = tm->tm_sec; - t->secfrac = tp.tv_usec; - t->secfracPrecision = 6; - -# if __sun - /* Solaris uses a different method of exporting the time zone. - * It is UTC - localtime, which is the opposite sign of mins east of GMT. - */ - lBias = -(daylight ? altzone : timezone); -# elif defined(__hpux) - lBias = tz.tz_dsttime ? - tz.tz_minuteswest : 0; -# else - lBias = tm->tm_gmtoff; -# endif - if(lBias < 0) - { - t->OffsetMode = '-'; - lBias *= -1; - } - else - t->OffsetMode = '+'; - t->OffsetHour = lBias / 3600; - t->OffsetMinute = lBias % 3600; -} - - - - -/******************************************************************* - * BEGIN CODE-LIBLOGGING * - ******************************************************************* - * Code in this section is borrowed from liblogging. This is an - * interim solution. Once liblogging is fully integrated, this is - * to be removed (see http://www.monitorware.com/liblogging for - * more details. 2004-11-16 rgerhards - * - * Please note that the orginal liblogging code is modified so that - * it fits into the context of the current version of syslogd.c. - * - * DO NOT PUT ANY OTHER CODE IN THIS BEGIN ... END BLOCK!!!! - */ - -/** - * Parse a 32 bit integer number from a string. - * - * \param ppsz Pointer to the Pointer to the string being parsed. It - * must be positioned at the first digit. Will be updated - * so that on return it points to the first character AFTER - * the integer parsed. - * \retval The number parsed. - */ - -static int srSLMGParseInt32(char** ppsz) -{ - int i; - - i = 0; - while(isdigit((int) **ppsz)) - { - i = i * 10 + **ppsz - '0'; - ++(*ppsz); - } - - return i; -} - - -/** - * Parse a TIMESTAMP-3339. - * updates the parse pointer position. - */ -static int -ParseTIMESTAMP3339(struct syslogTime *pTime, char** ppszTS) -{ - char *pszTS = *ppszTS; - - assert(pTime != NULL); - assert(ppszTS != NULL); - assert(pszTS != NULL); - - pTime->year = srSLMGParseInt32(&pszTS); - - /* We take the liberty to accept slightly malformed timestamps e.g. in - * the format of 2003-9-1T1:0:0. This doesn't hurt on receiving. Of course, - * with the current state of affairs, we would never run into this code - * here because at postion 11, there is no "T" in such cases ;) - */ - if(*pszTS++ != '-') - return FALSE; - pTime->month = srSLMGParseInt32(&pszTS); - if(pTime->month < 1 || pTime->month > 12) - return FALSE; - - if(*pszTS++ != '-') - return FALSE; - pTime->day = srSLMGParseInt32(&pszTS); - if(pTime->day < 1 || pTime->day > 31) - return FALSE; - - if(*pszTS++ != 'T') - return FALSE; - - pTime->hour = srSLMGParseInt32(&pszTS); - if(pTime->hour < 0 || pTime->hour > 23) - return FALSE; - - if(*pszTS++ != ':') - return FALSE; - pTime->minute = srSLMGParseInt32(&pszTS); - if(pTime->minute < 0 || pTime->minute > 59) - return FALSE; - - if(*pszTS++ != ':') - return FALSE; - pTime->second = srSLMGParseInt32(&pszTS); - if(pTime->second < 0 || pTime->second > 60) - return FALSE; - - /* Now let's see if we have secfrac */ - if(*pszTS == '.') - { - char *pszStart = ++pszTS; - pTime->secfrac = srSLMGParseInt32(&pszTS); - pTime->secfracPrecision = (int) (pszTS - pszStart); - } - else - { - pTime->secfracPrecision = 0; - pTime->secfrac = 0; - } - - /* check the timezone */ - if(*pszTS == 'Z') - { - pszTS++; /* eat Z */ - pTime->OffsetMode = 'Z'; - pTime->OffsetHour = 0; - pTime->OffsetMinute = 0; - } - else if((*pszTS == '+') || (*pszTS == '-')) - { - pTime->OffsetMode = *pszTS; - pszTS++; - - pTime->OffsetHour = srSLMGParseInt32(&pszTS); - if(pTime->OffsetHour < 0 || pTime->OffsetHour > 23) - return FALSE; - - if(*pszTS++ != ':') - return FALSE; - pTime->OffsetMinute = srSLMGParseInt32(&pszTS); - if(pTime->OffsetMinute < 0 || pTime->OffsetMinute > 59) - return FALSE; - } - else - /* there MUST be TZ information */ - return FALSE; - - /* OK, we actually have a 3339 timestamp, so let's indicated this */ - if(*pszTS == ' ') - ++pszTS; - else - return FALSE; - - /* update parse pointer */ - *ppszTS = pszTS; - - return TRUE; -} - - -/** - * Parse a TIMESTAMP-3164. - * Returns TRUE on parse OK, FALSE on parse error. - */ -static int -ParseTIMESTAMP3164(struct syslogTime *pTime, char* pszTS) -{ - assert(pTime != NULL); - assert(pszTS != NULL); - - getCurrTime(pTime); /* obtain the current year and UTC offsets! */ - - /* If we look at the month (Jan, Feb, Mar, Apr, May, Jun, Jul, Aug, Sep, Oct, Nov, Dec), - * we may see the following character sequences occur: - * - * J(an/u(n/l)), Feb, Ma(r/y), A(pr/ug), Sep, Oct, Nov, Dec - * - * We will use this for parsing, as it probably is the - * fastest way to parse it. - * - * 2005-07-18, well sometimes it pays to be a bit more verbose, even in C... - * Fixed a bug that lead to invalid detection of the data. The issue was that - * we had an if(++pszTS == 'x') inside of some of the consturcts below. However, - * there were also some elseifs (doing the same ++), which than obviously did not - * check the orginal character but the next one. Now removed the ++ and put it - * into the statements below. Was a really nasty bug... I didn't detect it before - * june, when it first manifested. This also lead to invalid parsing of the rest - * of the message, as the time stamp was not detected to be correct. - rgerhards - */ - switch(*pszTS++) - { - case 'J': - if(*pszTS == 'a') { - ++pszTS; - if(*pszTS == 'n') { - ++pszTS; - pTime->month = 1; - } else - return FALSE; - } else if(*pszTS == 'u') { - ++pszTS; - if(*pszTS == 'n') { - ++pszTS; - pTime->month = 6; - } else if(*pszTS == 'l') { - ++pszTS; - pTime->month = 7; - } else - return FALSE; - } else - return FALSE; - break; - case 'F': - if(*pszTS == 'e') { - ++pszTS; - if(*pszTS == 'b') { - ++pszTS; - pTime->month = 2; - } else - return FALSE; - } else - return FALSE; - break; - case 'M': - if(*pszTS == 'a') { - ++pszTS; - if(*pszTS == 'r') { - ++pszTS; - pTime->month = 3; - } else if(*pszTS == 'y') { - ++pszTS; - pTime->month = 5; - } else - return FALSE; - } else - return FALSE; - break; - case 'A': - if(*pszTS == 'p') { - ++pszTS; - if(*pszTS == 'r') { - ++pszTS; - pTime->month = 4; - } else - return FALSE; - } else if(*pszTS == 'u') { - ++pszTS; - if(*pszTS == 'g') { - ++pszTS; - pTime->month = 8; - } else - return FALSE; - } else - return FALSE; - break; - case 'S': - if(*pszTS == 'e') { - ++pszTS; - if(*pszTS == 'p') { - ++pszTS; - pTime->month = 9; - } else - return FALSE; - } else - return FALSE; - break; - case 'O': - if(*pszTS == 'c') { - ++pszTS; - if(*pszTS == 't') { - ++pszTS; - pTime->month = 10; - } else - return FALSE; - } else - return FALSE; - break; - case 'N': - if(*pszTS == 'o') { - ++pszTS; - if(*pszTS == 'v') { - ++pszTS; - pTime->month = 11; - } else - return FALSE; - } else - return FALSE; - break; - case 'D': - if(*pszTS == 'e') { - ++pszTS; - if(*pszTS == 'c') { - ++pszTS; - pTime->month = 12; - } else - return FALSE; - } else - return FALSE; - break; - default: - return FALSE; - } - - /* done month */ - - if(*pszTS++ != ' ') - return FALSE; - - /* we accept a slightly malformed timestamp when receiving. This is - * we accept one-digit days - */ - if(*pszTS == ' ') - ++pszTS; - - pTime->day = srSLMGParseInt32(&pszTS); - if(pTime->day < 1 || pTime->day > 31) - return FALSE; - - if(*pszTS++ != ' ') - return FALSE; - pTime->hour = srSLMGParseInt32(&pszTS); - if(pTime->hour < 0 || pTime->hour > 23) - return FALSE; - - if(*pszTS++ != ':') - return FALSE; - pTime->minute = srSLMGParseInt32(&pszTS); - if(pTime->minute < 0 || pTime->minute > 59) - return FALSE; - - if(*pszTS++ != ':') - return FALSE; - pTime->second = srSLMGParseInt32(&pszTS); - if(pTime->second < 0 || pTime->second > 60) - return FALSE; - if(*pszTS++ != ':') - - /* OK, we actually have a 3164 timestamp, so let's indicate this - * and fill the rest of the properties. */ - pTime->timeType = 1; - pTime->secfracPrecision = 0; - pTime->secfrac = 0; - return TRUE; -} - -/******************************************************************* - * END CODE-LIBLOGGING * - *******************************************************************/ - -/** - * Format a syslogTimestamp into format required by MySQL. - * We are using the 14 digits format. For example 20041111122600 - * is interpreted as '2004-11-11 12:26:00'. - * The caller must provide the timestamp as well as a character - * buffer that will receive the resulting string. The function - * returns the size of the timestamp written in bytes (without - * the string terminator). If 0 is returend, an error occured. - */ -int formatTimestampToMySQL(struct syslogTime *ts, char* pDst, size_t iLenDst) -{ - /* currently we do not consider localtime/utc. This may later be - * added. If so, I recommend using a property replacer option - * and/or a global configuration option. However, we should wait - * on user requests for this feature before doing anything. - * rgerhards, 2007-06-26 - */ - assert(ts != NULL); - assert(pDst != NULL); - - if (iLenDst < 15) /* we need at least 14 bytes - 14 digits for timestamp + '\n' */ - return(0); - - return(snprintf(pDst, iLenDst, "%4.4d%2.2d%2.2d%2.2d%2.2d%2.2d", - ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second)); - -} - -int formatTimestampToPgSQL(struct syslogTime *ts, char *pDst, size_t iLenDst) -{ - /* see note in formatTimestampToMySQL, applies here as well */ - assert(ts != NULL); - assert(pDst != NULL); - - if (iLenDst < 21) /* we need 20 bytes + '\n' */ - return(0); - - return(snprintf(pDst, iLenDst, "%4.4d-%2.2d-%2.2d %2.2d:%2.2d:%2.2d", - ts->year, ts->month, ts->day, ts->hour, ts->minute, ts->second)); -} - -/** - * Format a syslogTimestamp to a RFC3339 timestamp string (as - * specified in syslog-protocol). - * The caller must provide the timestamp as well as a character - * buffer that will receive the resulting string. The function - * returns the size of the timestamp written in bytes (without - * the string terminator). If 0 is returend, an error occured. - */ -int formatTimestamp3339(struct syslogTime *ts, char* pBuf, size_t iLenBuf) -{ - int iRet; - char szTZ[7]; /* buffer for TZ information */ - - assert(ts != NULL); - assert(pBuf != NULL); - - if(iLenBuf < 20) - return(0); /* we NEED at least 20 bytes */ - - /* do TZ information first, this is easier to take care of "Z" zone in rfc3339 */ - if(ts->OffsetMode == 'Z') { - szTZ[0] = 'Z'; - szTZ[1] = '\0'; - } else { - snprintf(szTZ, sizeof(szTZ) / sizeof(char), "%c%2.2d:%2.2d", - ts->OffsetMode, ts->OffsetHour, ts->OffsetMinute); - } - - if(ts->secfracPrecision > 0) - { /* we now need to include fractional seconds. While doing so, we must look at - * the precision specified. For example, if we have millisec precision (3 digits), a - * secFrac value of 12 is not equivalent to ".12" but ".012". Obviously, this - * is a huge difference ;). To avoid this, we first create a format string with - * the specific precision and *then* use that format string to do the actual - * formating (mmmmhhh... kind of self-modifying code... ;)). - */ - char szFmtStr[64]; - /* be careful: there is ONE actual %d in the format string below ;) */ - snprintf(szFmtStr, sizeof(szFmtStr), - "%%04d-%%02d-%%02dT%%02d:%%02d:%%02d.%%0%dd%%s", - ts->secfracPrecision); - iRet = snprintf(pBuf, iLenBuf, szFmtStr, ts->year, ts->month, ts->day, - ts->hour, ts->minute, ts->second, ts->secfrac, szTZ); - } - else - iRet = snprintf(pBuf, iLenBuf, - "%4.4d-%2.2d-%2.2dT%2.2d:%2.2d:%2.2d%s", - ts->year, ts->month, ts->day, - ts->hour, ts->minute, ts->second, szTZ); - return(iRet); -} - -/** - * Format a syslogTimestamp to a RFC3164 timestamp sring. - * The caller must provide the timestamp as well as a character - * buffer that will receive the resulting string. The function - * returns the size of the timestamp written in bytes (without - * the string termnator). If 0 is returend, an error occured. - */ -int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf) -{ - static char* monthNames[13] = {"ERR", "Jan", "Feb", "Mar", - "Apr", "May", "Jun", "Jul", - "Aug", "Sep", "Oct", "Nov", "Dec"}; - assert(ts != NULL); - assert(pBuf != NULL); - - if(iLenBuf < 16) - return(0); /* we NEED 16 bytes */ - return(snprintf(pBuf, iLenBuf, "%s %2d %2.2d:%2.2d:%2.2d", - monthNames[ts->month], ts->day, ts->hour, - ts->minute, ts->second - )); -} - -/** - * Format a syslogTimestamp to a text format. - * The caller must provide the timestamp as well as a character - * buffer that will receive the resulting string. The function - * returns the size of the timestamp written in bytes (without - * the string termnator). If 0 is returend, an error occured. - */ -#if 0 /* This method is currently not called, be we like to preserve it */ -static int formatTimestamp(struct syslogTime *ts, char* pBuf, size_t iLenBuf) -{ - assert(ts != NULL); - assert(pBuf != NULL); - - if(ts->timeType == 1) { - return(formatTimestamp3164(ts, pBuf, iLenBuf)); - } - - if(ts->timeType == 2) { - return(formatTimestamp3339(ts, pBuf, iLenBuf)); - } - - return(0); -} -#endif -/* queryInterface function - * rgerhards, 2008-03-05 - */ -BEGINobjQueryInterface(datetime) -CODESTARTobjQueryInterface(datetime) - if(pIf->ifVersion != datetimeCURR_IF_VERSION) { /* check for current version, increment on each change */ - ABORT_FINALIZE(RS_RET_INTERFACE_NOT_SUPPORTED); - } - - /* ok, we have the right interface, so let's fill it - * Please note that we may also do some backwards-compatibility - * work here (if we can support an older interface version - that, - * of course, also affects the "if" above). - */ - pIf->getCurrTime = getCurrTime; - pIf->ParseTIMESTAMP3339 = ParseTIMESTAMP3339; - pIf->ParseTIMESTAMP3164 = ParseTIMESTAMP3164; - pIf->formatTimestampToMySQL = formatTimestampToMySQL; - pIf->formatTimestampToPgSQL = formatTimestampToPgSQL; - pIf->formatTimestamp3339 = formatTimestamp3339; - pIf->formatTimestamp3164 = formatTimestamp3164; -finalize_it: -ENDobjQueryInterface(datetime) - - -/* Initialize the datetime class. Must be called as the very first method - * before anything else is called inside this class. - * rgerhards, 2008-02-19 - */ -BEGINAbstractObjClassInit(datetime, 1, OBJ_IS_CORE_MODULE) /* class, version */ - /* request objects we use */ - CHKiRet(objUse(errmsg, CORE_COMPONENT)); - -ENDObjClassInit(datetime) - -/* vi:set ai: - */ |