diff options
-rw-r--r-- | Makefile | 17 | ||||
-rwxr-xr-x | stringbuf.c | 188 | ||||
-rwxr-xr-x | stringbuf.h | 136 | ||||
-rw-r--r-- | syslogd.c | 39 | ||||
-rw-r--r-- | syslogd.h | 5 | ||||
-rw-r--r-- | template.c | 216 | ||||
-rw-r--r-- | template.h | 19 |
7 files changed, 602 insertions, 18 deletions
@@ -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 <rgerhards@adiscon.com>
+ * \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 <malloc.h>
+#include <assert.h>
+#include <string.h>
+#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 <rgerhards@adiscon.com>
+ * \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
@@ -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 *, ...); @@ -5,28 +5,234 @@ */ #include <stdio.h> #include <malloc.h> +#include <string.h> +#include <ctype.h> +#include <assert.h> +#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); } @@ -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: |