From 9a7c44921d6d17ae577c854f6c9606d5a1a0189e Mon Sep 17 00:00:00 2001 From: Rainer Gerhards Date: Wed, 17 Nov 2004 17:08:52 +0000 Subject: ComingCloser --- Makefile | 17 +++-- stringbuf.c | 188 ++++++++++++++++++++++++++++++++++++++++++++++++++++ stringbuf.h | 136 ++++++++++++++++++++++++++++++++++++++ syslogd.c | 39 +++++++++-- syslogd.h | 5 ++ template.c | 216 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++-- template.h | 19 +++++- 7 files changed, 602 insertions(+), 18 deletions(-) create mode 100755 stringbuf.c create mode 100755 stringbuf.h create mode 100644 syslogd.h diff --git a/Makefile b/Makefile index 6a31576d..33b7d8ff 100644 --- a/Makefile +++ b/Makefile @@ -2,9 +2,9 @@ CC= gcc #CFLAGS= -g -DSYSV -Wall -#LDFLAGS= -g -#CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce -CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce -DWITH_DB +LDFLAGS= -g +CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce +#CFLAGS= $(RPM_OPT_FLAGS) -O3 -DSYSV -fomit-frame-pointer -Wall -fno-strength-reduce -DWITH_DB LDFLAGS= -s # Look where your install program is. @@ -13,7 +13,7 @@ BINDIR = /usr/sbin MANDIR = /usr/man # Uncommenting the following to use mysql. -LIBS = -lmysqlclient #/var/lib/mysql/mysql +#LIBS = -lmysqlclient #/var/lib/mysql/mysql # There is one report that under an all ELF system there may be a need to # explicilty link with libresolv.a. If linking syslogd fails you may wish @@ -63,8 +63,8 @@ test: syslog_tst ksym oops_test tsyslogd install: install_man install_exec -syslogd: syslogd.o pidfile.o template.o - ${CC} ${LDFLAGS} -o syslogd syslogd.o pidfile.o ${LIBS} +syslogd: syslogd.o pidfile.o template.o stringbuf.o + ${CC} ${LDFLAGS} -o syslogd syslogd.o pidfile.o template.o stringbuf.o ${LIBS} klogd: klogd.o syslog.o pidfile.o ksym.o ksym_mod.o ${CC} ${LDFLAGS} -o klogd klogd.o syslog.o pidfile.o ksym.o \ @@ -79,7 +79,10 @@ tsyslogd: syslogd.c version.h tklogd: klogd.c syslog.c ksym.c ksym_mod.c version.h $(CC) $(CFLAGS) -g -DTESTING $(KLOGD_FLAGS) -o tklogd klogd.c syslog.c ksym.c ksym_mod.c -template.o: template.c template.h +stringbuf.o: stringbuf.c stringbuf.h liblogging-stub.h + ${CC} ${CFLAGS} ${SYSLOGD_FLAGS} $(DEB) -c stringbuf.c + +template.o: template.c template.h stringbuf.h liblogging-stub.h ${CC} ${CFLAGS} ${SYSLOGD_FLAGS} $(DEB) -c template.c syslogd.o: syslogd.c version.h template.h diff --git a/stringbuf.c b/stringbuf.c new file mode 100755 index 00000000..484d0710 --- /dev/null +++ b/stringbuf.c @@ -0,0 +1,188 @@ +/*! \file stringbuf.c + * \brief Implemetation of the dynamic string buffer helper object. + * + * \author Rainer Gerhards + * \date 2003-08-08 + * Initial version begun. + * + * Copyright 2002-2003 + * Rainer Gerhards and Adiscon GmbH. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Adiscon GmbH or Rainer Gerhards + * nor the names of its contributors may be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ + +#include +#include +#include +#include "liblogging-stub.h" +#include "stringbuf.h" + +/* ################################################################# * + * private members * + * ################################################################# */ + + + +/* ################################################################# * + * public members * + * ################################################################# */ + + +sbStrBObj *sbStrBConstruct(void) +{ + sbStrBObj *pThis; + + if((pThis = (sbStrBObj*) calloc(1, sizeof(sbStrBObj))) == NULL) + return NULL; + + pThis->OID = OIDsbStrB; + pThis->pBuf = NULL; + pThis->iBufSize = 0; + pThis->iBufPtr = 0; + pThis->iAllocIncrement = STRINGBUF_ALLOC_INCREMENT; + + return pThis; +} + + +void sbStrBDestruct(sbStrBObj *pThis) +{ +# if STRINGBUF_TRIM_ALLOCSIZE == 1 + /* in this mode, a new buffer already was allocated, + * so we need to free the old one. + */ + if(pThis->pBuf != NULL) + free(pThis->pBuf); +# endif + + SRFREEOBJ(pThis); +} + + +srRetVal sbStrBAppendStr(sbStrBObj *pThis, char* psz) +{ + srRetVal iRet; + + sbSTRBCHECKVALIDOBJECT(pThis); + assert(psz != NULL); + + while(*psz) + if((iRet = sbStrBAppendChar(pThis, *psz++)) != SR_RET_OK) + return iRet; + + return SR_RET_OK; +} + + +#if 0 /* we hope we don't need this ;) */ +srRetVal sbStrBAppendInt(sbStrBObj *pThis, int i) +{ + srRetVal iRet; + char szBuf[32]; + + sbSTRBCHECKVALIDOBJECT(pThis); + + if((iRet = srUtilItoA(szBuf, sizeof(szBuf), i)) != SR_RET_OK) + return iRet; + + return sbStrBAppendStr(pThis, szBuf); +} +#endif + + +srRetVal sbStrBAppendChar(sbStrBObj *pThis, char c) +{ + char* pNewBuf; + + sbSTRBCHECKVALIDOBJECT(pThis); + + if(pThis->iBufPtr >= pThis->iBufSize) + { /* need more memory! */ + if((pNewBuf = (char*) malloc((pThis->iBufSize + pThis->iAllocIncrement) * sizeof(char))) == NULL) + return SR_RET_OUT_OF_MEMORY; + memcpy(pNewBuf, pThis->pBuf, pThis->iBufSize); + pThis->iBufSize += pThis->iAllocIncrement; + if(pThis->pBuf != NULL) + free(pThis->pBuf); + pThis->pBuf = pNewBuf; + } + + /* ok, when we reach this, we have sufficient memory */ + *(pThis->pBuf + pThis->iBufPtr++) = c; + + return SR_RET_OK; +} + + +char* sbStrBFinish(sbStrBObj *pThis) +{ + char* pRetBuf; + + sbSTRBCHECKVALIDOBJECT(pThis); + + sbStrBAppendChar(pThis, '\0'); + +# if STRINGBUF_TRIM_ALLOCSIZE == 1 + /* in this mode, we need to trim the string. To do + * so, we must allocate a new buffer of the exact + * string size, and then copy the old one over. + * This new buffer is then to be returned. + */ + if((pRetBuf = malloc((pThis->iBufSize + 1) * sizeof(char))) == NULL) + { /* OK, in this case we use the previous buffer. At least + * we have it ;) + */ + pRetBuf = pThis->pBuf; + } + else + { /* got the new buffer, so let's use it */ + memcpy(pRetBuf, pThis->pBuf, pThis->iBufPtr + 1); + } +# else + /* here, we can simply return a pointer to the + * currently existing buffer. We don't care about + * the extra memory, as we achieve a big performance + * gain. + */ + pRetBuf = pThis->pBuf; +# endif + + sbStrBDestruct(pThis); + + return(pRetBuf); +} + +void sbStrBSetAllocIncrement(sbStrBObj *pThis, int iNewIncrement) +{ + sbSTRBCHECKVALIDOBJECT(pThis); + assert(iNewIncrement > 0); + + pThis->iAllocIncrement = iNewIncrement; +} diff --git a/stringbuf.h b/stringbuf.h new file mode 100755 index 00000000..f456214b --- /dev/null +++ b/stringbuf.h @@ -0,0 +1,136 @@ +/*! \file stringbuf.h + * \brief The dynamic stringt buffer helper object. + * + * The string buffer object is a slim string handler. It implements + * a dynamically growing string and can be used whereever data needs + * to be appended to a string AND it is not known how large the + * resulting structure is. If you know the string size or can + * retrieve it quickly, you should NOT use the string buffer + * object - because it has some overhead not associated with direct + * string manipulations. + * + * This object is used to grow a string. For performance reasons, + * the termination \0 byte is only written after the caller + * indicates the string is completed. + * + * \author Rainer Gerhards + * \date 2003-08-08 + * Initial version begun. + * + * Copyright 2002-2003 + * Rainer Gerhards and Adiscon GmbH. All Rights Reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are + * met: + * + * * Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * * Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * * Neither the name of Adiscon GmbH or Rainer Gerhards + * nor the names of its contributors may be used to + * endorse or promote products derived from this software without + * specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS + * IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED + * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A + * PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER + * OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, + * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, + * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR + * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF + * LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING + * NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS + * SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + */ +#ifndef __LIB3195_STRINGBUF_H_INCLUDED__ +#define __LIB3195_STRINGBUF_H_INCLUDED__ 1 + +#define sbSTRBCHECKVALIDOBJECT(x) {assert(x != NULL); assert(x->OID == OIDsbStrB);} + + +/** + * The dynamic string buffer object. + * + */ +struct sbStrBObject +{ + srObjID OID; /**< object ID */ + char *pBuf; /**< pointer to the string buffer, may be NULL if string is empty */ + int iBufSize; /**< current maximum size of the string buffer */ + int iBufPtr; /**< pointer (index) of next character position to be written to. */ + int iAllocIncrement; /**< the amount of bytes the string should be expanded if it needs to */ +}; +typedef struct sbStrBObject sbStrBObj; + + +/** + * Construct a sbStrB object. + */ +sbStrBObj *sbStrBConstruct(void); + +/** + * Destruct the string buffer object. + */ +void sbStrBDestruct(sbStrBObj *pThis); + +/** + * Append a character to an existing string. If necessary, the + * method expands the string buffer. + * + * \param c Character to append to string. + */ +srRetVal sbStrBAppendChar(sbStrBObj *pThis, char c); + +/** + * Finish the string buffer. That means, the string + * is returned to the caller and then the string + * buffer is destroyed. The caller is reponsible for + * freeing the returned string pointer. + * + * After calling this method, the string buffer object + * is destroyed and thus the provided handle (pThis) + * can no longer be used. + * + * \retval pointer to \0 terminated string. May be NULL + * (empty string) and MUST be free()ed by caller. + */ +char* sbStrBFinish(sbStrBObj *pThis); + +/** + * Append a string to the buffer. + * + * \param psz pointer to string to be appended. Must not be NULL. + */ +srRetVal sbStrBAppendStr(sbStrBObj *pThis, char* psz); + +/** + * Set a new allocation incremet. This will influence + * the allocation the next time the string will be expanded. + * It can be set and changed at any time. If done immediately + * after custructing the StrB object, this will also be + * the inital allocation. + * + * \param iNewIncrement The new increment size + * + * \note It is possible to use a very low increment, e.g. 1 byte. + * This can generate a considerable overhead. We highly + * advise not to use an increment below 32 bytes, except + * if you are very well aware why you are doing it ;) + */ +void sbStrBSetAllocIncrement(sbStrBObj *pThis, int iNewIncrement); + +/** + * Append an integer to the string. No special formatting is + * done. + */ +srRetVal sbStrBAppendInt(sbStrBObj *pThis, int i); + + +#endif diff --git a/syslogd.c b/syslogd.c index 47c26986..b5da3149 100644 --- a/syslogd.c +++ b/syslogd.c @@ -586,6 +586,7 @@ static char sccsid[] = "@(#)rsyslogd.c 0.1 (Adiscon) 11/08/2004"; #endif #include "template.h" +#include "syslogd.h" #ifdef WITH_DB #define _DB_MAXDBLEN 128 /* maximum number of db */ @@ -950,10 +951,6 @@ void doexit(int sig); void init(); void cfline(char *line, register struct filed *f); int decode(char *name, struct code *codetab); -#if defined(__GLIBC__) -#define dprintf mydprintf -#endif /* __GLIBC__ */ -static void dprintf(char *, ...); static void allocate_log(void); void sighup_handler(); #ifdef WITH_DB @@ -3151,6 +3148,37 @@ void doexit(sig) } #endif +/* parse and interpret a template line. The line is added + * to the deamon's template linked list. + * rgerhards 2004-11-17 + */ +void doTemplateLine(char **pp) +{ + char *p = *pp; + char szName[128]; + + assert(pp != NULL); + assert(p != NULL); + + if(getSubString(&p, szName, sizeof(szName) / sizeof(char), ',') != 0) { + dprintf("Invalid $-configline - could not extract Templatename - line ignored\n"); + return; + } + if(*p == ',') + ++p; /* comma was eaten */ + + /* we got the name - now we pass name & the rest of the string + * to the template creator. It makes no sense to do further + * parsing here, as this is in close interaction with the + * template subsystem. rgerhads 2004-11-17 + */ + tplAddLine(szName, &p); + + *pp = p; + return; +} + + /* Parse and interpret a system-directive in the config line * A system directive is one that starts with a "$" sign. It offers * extended configuration parameters. @@ -3169,6 +3197,7 @@ void cfsysline(char *p) /* check the command and carry out processing */ if(!strcmp(szCmd, "template")) { + doTemplateLine(&p); } else { /* invalid command! */ dprintf("Invalid command in $-configline: '%s' - line ignored\n", szCmd); return; @@ -3763,7 +3792,7 @@ int decode(name, codetab) return (-1); } -static void dprintf(char *fmt, ...) +void dprintf(char *fmt, ...) { va_list ap; diff --git a/syslogd.h b/syslogd.h new file mode 100644 index 00000000..9ff9be9c --- /dev/null +++ b/syslogd.h @@ -0,0 +1,5 @@ +/* common header for syslogd */ +#if defined(__GLIBC__) +#define dprintf mydprintf +#endif /* __GLIBC__ */ +void dprintf(char *, ...); diff --git a/template.c b/template.c index f882ea56..a2ccfbb4 100644 --- a/template.c +++ b/template.c @@ -5,28 +5,234 @@ */ #include #include +#include +#include +#include +#include "liblogging-stub.h" +#include "stringbuf.h" #include "template.h" +#include "syslogd.h" -static struct template *tplRoot = NULL; /* the root of the templat list */ +static struct template *tplRoot = NULL; /* the root of the template list */ static struct template *tplLast = NULL; /* points to the last element of the template list */ -/* Constructs a template entry. Returns pointer to it +/* Constructs a template entry object. Returns pointer to it + * or NULL (if it fails). Pointer to associated template list entry + * must be provided. + */ +struct templateEntry* tpeConstruct(struct template *pTpl) +{ + assert(pTpl != NULL); + + struct templateEntry *pTpe; + if((pTpe = calloc(1, sizeof(struct templateEntry))) == NULL) + return NULL; + + /* basic initialisaion is done via calloc() - need to + * initialize only values != 0. */ + + if(pTpl->pEntryLast == NULL) + { /* we are the first element! */ + pTpl->pEntryRoot = pTpl->pEntryLast = pTpe; + } + else + { + pTpl->pEntryLast->pNext = pTpe; + pTpl->pEntryLast = pTpe; + } + + return(pTpe); +} + + + +/* Constructs a template list object. Returns pointer to it * or NULL (if it fails). */ struct template* tplConstruct(void) { struct template *pTpl; - if((pTpl = malloc(sizeof(struct template))) == NULL) + if((pTpl = calloc(1, sizeof(struct template))) == NULL) return NULL; - pTpl->pszName = NULL; - pTpl->pszTemplate = NULL; + /* basic initialisaion is done via calloc() - need to + * initialize only values != 0. */ if(tplLast == NULL) { /* we are the first element! */ tplRoot = tplLast = pTpl; } + else + { + tplLast->pNext = pTpl; + tplLast = pTpl; + } + + return(pTpl); +} + + +/* helper to tplAddLine. Parses a constant and generates + * the necessary structure. + * returns: 0 - ok, 1 - failure + */ +static int do_Constant(char **pp, struct template *pTpl) +{ + register char *p; + sbStrBObj *pStrB; + + assert(pp != NULL); + assert(*pp != NULL); + assert(pTpl != NULL); + + p = *pp; + + if((pStrB = sbStrBConstruct()) == NULL) + return 1; + sbStrBSetAllocIncrement(pStrB, 32); + /* TODO: implement escape characters! */ + while(*p && *p != '%') { + if(*p == '\\') + if(*++p == '\0') + --p; /* the best we can do - it's invalid anyhow... */ + sbStrBAppendChar(pStrB, *p++); + } + + printf("Constant: '%s'\n", sbStrBFinish(pStrB)); + *pp = p; + + return 0; +} + + +/* helper to tplAddLine. Parses a parameter and generates + * the necessary structure. + * returns: 0 - ok, 1 - failure + */ +static int do_Parameter(char **pp, struct template *pTpl) +{ + register char *p; + sbStrBObj *pStrB; + + assert(pp != NULL); + assert(*pp != NULL); + assert(pTpl != NULL); + + p = *pp; + + if((pStrB = sbStrBConstruct()) == NULL) + return 1; + while(*p && *p != '%') { + sbStrBAppendChar(pStrB, *p++); + } + if(*p) ++p; /* eat '%' */ + printf("Parameter: '%s'\n", sbStrBFinish(pStrB)); + + *pp = p; + return 0; +} + + +/* Add a new template line + * returns pointer to new object if it succeeds, NULL otherwise. + */ +struct template *tplAddLine(char* pName, char** ppRestOfConfLine) +{ + struct template *pTpl; + char *p; + int bDone; + + assert(pName != NULL); + assert(ppRestOfConfLine != NULL); + + if((pTpl = tplConstruct()) == NULL) + return NULL; + + pTpl->iLenName = strlen(pName); + pTpl->pszName = (char*) malloc(sizeof(char) * pTpl->iLenName); + if(pTpl->pszName == NULL) { + dprintf("tplAddLine could not alloc memory for template name!"); + pTpl->iLenName = 0; + return NULL; + /* I know - we create a memory leak here - but I deem + * it acceptable as it is a) a very small leak b) very + * unlikely to happen. rgerhards 2004-11-17 + */ + } + memcpy(pTpl->pszName, pName, pTpl->iLenName + 1); + +#if 0 + pTpl->iLenTemplate = strlen(pName); + pTpl->pszTemplate = (char*) malloc(sizeof(char) * pTpl->iLenTemplate); + if(pTpl->pszTemplate == NULL) { + printf("could not alloc memory Template"); /* TODO: change to dprintf()! */ + free(pTpl->pszName); + pTpl->pszName = NULL; + pTpl->iLenName = 0; + pTpl->iLenTemplate = 0; + return NULL; + /* see note on leak above */ + } +#endif + + p = *ppRestOfConfLine; + assert(p != NULL); + + /* skip whitespace */ + while(isspace(*p)) + ++p; + + if(*p != '"') { + dprintf("Template invalid, does not start with '\"'!\n"); + /* TODO: Free mem! */ + return NULL; + } + ++p; + + /* we finally got to the actual template string - so let's have some fun... */ + bDone = *p ? 0 : 1; + while(!bDone) { + switch(*p) { + case '\0': + bDone = 1; + break; + case '%': /* parameter */ + ++p; /* eat '%' */ + do_Parameter(&p, pTpl); + break; + default: /* constant */ + do_Constant(&p, pTpl); + break; + } + } + +printf("tplAddLine, Name '%s', restOfLine: %s", pTpl->pszName, p); + + *ppRestOfConfLine = p; + return(pTpl); +} + + +/* Find a template object based on name. Search + * currently is case-senstive (should we change?). + * returns pointer to template object if found and + * NULL otherwise. + * rgerhards 2004-11-17 + */ +struct template *tplFind(char *pName, int iLenName) +{ + struct template *pTpl; + + assert(pName != NULL); + pTpl = tplRoot; + while(pTpl != NULL && + !(pTpl->iLenName == iLenName && + !strcmp(pTpl->pszName, pName) + )) + { + pTpl = pTpl->pNext; + } return(pTpl); } diff --git a/template.h b/template.h index 8f96c43b..e438e988 100644 --- a/template.h +++ b/template.h @@ -4,11 +4,28 @@ * begun 2004-11-17 rgerhards */ struct template { + struct template *pNext; char *pszName; - char *pszTemplate; + int iLenName; + struct templateEntry *pEntryRoot; + struct templateEntry *pEntryLast; +}; + +enum EntryTypes { UNDEFINED = 0, CONSTANT = 1, FIELD = 2 }; + +/* a specific parse entry */ +struct templateEntry { + struct templateEntry *pNext; + enum EntryTypes eEntryType; + union { + char *pConstant; /* pointer to constant value */ + char *pPropRepl; /* pointer to property replacer string */ + }; }; struct template* tplConstruct(void); +struct template *tplAddLine(char* pName, char** pRestOfConfLine); +struct template *tplFind(char *pName, int iLenName); /* * vi:set ai: -- cgit v1.2.3