diff options
-rw-r--r-- | Makefile | 7 | ||||
-rwxr-xr-x | srUtils.c | 99 | ||||
-rwxr-xr-x | srUtils.h | 63 | ||||
-rwxr-xr-x | stringbuf.c | 3 | ||||
-rw-r--r-- | syslogd.c | 210 | ||||
-rw-r--r-- | template.c | 100 | ||||
-rw-r--r-- | template.h | 10 |
7 files changed, 444 insertions, 48 deletions
@@ -63,8 +63,8 @@ test: syslog_tst ksym oops_test tsyslogd install: install_man install_exec -syslogd: syslogd.o pidfile.o template.o stringbuf.o - ${CC} ${LDFLAGS} -o syslogd syslogd.o pidfile.o template.o stringbuf.o ${LIBS} +syslogd: syslogd.o pidfile.o template.o stringbuf.o srUtils.o + ${CC} ${LDFLAGS} -o syslogd syslogd.o pidfile.o template.o stringbuf.o srUtils.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,6 +79,9 @@ 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 +srUtils.o: srUtils.c srUtils.h liblogging-stub.h + ${CC} ${CFLAGS} ${SYSLOGD_FLAGS} $(DEB) -c srUtils.c + stringbuf.o: stringbuf.c stringbuf.h liblogging-stub.h ${CC} ${CFLAGS} ${SYSLOGD_FLAGS} $(DEB) -c stringbuf.c diff --git a/srUtils.c b/srUtils.c new file mode 100755 index 00000000..ef8a77c1 --- /dev/null +++ b/srUtils.c @@ -0,0 +1,99 @@ +/**\file srUtils.c
+ * \brief General utilties that fit nowhere else.
+ *
+ * The namespace for this file is "srUtil".
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-09-09
+ * Coding 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 "liblogging-stub.h" /* THIS IS A MODIFICATION FOR RSYSLOG! 2004-11-18 rgerards */
+#define TRUE 1
+#define FALSE 0
+#include "srUtils.h"
+#include "assert.h"
+
+
+/* ################################################################# *
+ * private members *
+ * ################################################################# */
+
+/* As this is not a "real" object, there won't be any private
+ * members in this file.
+ */
+
+/* ################################################################# *
+ * public members *
+ * ################################################################# */
+
+srRetVal srUtilItoA(char *pBuf, int iLenBuf, int iToConv)
+{
+ int i;
+ int bIsNegative;
+ char szBuf[32]; /* sufficiently large for my lifespan and those of my children... ;) */
+
+ assert(pBuf != NULL);
+ assert(iLenBuf > 1); /* This is actually an app error and as thus checked for... */
+
+ if(iToConv < 0)
+ {
+ bIsNegative = TRUE;
+ iToConv *= -1;
+ }
+ else
+ bIsNegative = FALSE;
+
+ /* first generate a string with the digits in the reverse direction */
+ i = 0;
+ do
+ {
+ szBuf[i] = iToConv % 10 + '0';
+ iToConv /= 10;
+ } while(iToConv > 0); /* warning: do...while()! */
+
+ /* make sure we are within bounds... */
+ if(i + 2 > iLenBuf) /* +2 because: a) i starts at zero! b) the \0 byte */
+ return SR_RET_PROVIDED_BUFFER_TOO_SMALL;
+
+ /* then move it to the right direction... */
+ if(bIsNegative == TRUE)
+ *pBuf++ = '-';
+ while(i >= 0)
+ *pBuf++ = szBuf[i--];
+ *pBuf = '\0'; /* terminate it!!! */
+
+ return SR_RET_OK;
+}
diff --git a/srUtils.h b/srUtils.h new file mode 100755 index 00000000..8b9e022f --- /dev/null +++ b/srUtils.h @@ -0,0 +1,63 @@ +/*! \file srUtils.h
+ * \brief General, small utilities that fit nowhere else.
+ *
+ * \author Rainer Gerhards <rgerhards@adiscon.com>
+ * \date 2003-09-09
+ * Coding 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_SRUTILS_H_INCLUDED__
+#define __LIB3195_SRUTILS_H_INCLUDED__ 1
+
+
+/**
+ * A reimplementation of itoa(), as this is not available
+ * on all platforms. We used the chance to make an interface
+ * that fits us well, so it is no longer plain itoa().
+ *
+ * This method works with the US-ASCII alphabet. If you port this
+ * to e.g. EBCDIC, you need to make a small adjustment. Keep in mind,
+ * that on the wire it MUST be US-ASCII, so basically all you need
+ * to do is replace the constant '0' with 0x30 ;).
+ *
+ * \param pBuf Caller-provided buffer that will receive the
+ * generated ASCII string.
+ *
+ * \param iLenBuf Length of the caller-provided buffer.
+ *
+ * \param iToConv The integer to be converted.
+ */
+srRetVal srUtilItoA(char *pBuf, int iLenBuf, int iToConv);
+
+#endif
diff --git a/stringbuf.c b/stringbuf.c index 484d0710..d52c4455 100755 --- a/stringbuf.c +++ b/stringbuf.c @@ -43,6 +43,7 @@ #include <string.h>
#include "liblogging-stub.h"
#include "stringbuf.h"
+#include "srUtils.h"
/* ################################################################# *
* private members *
@@ -101,7 +102,6 @@ srRetVal sbStrBAppendStr(sbStrBObj *pThis, char* psz) }
-#if 0 /* we hope we don't need this ;) */
srRetVal sbStrBAppendInt(sbStrBObj *pThis, int i)
{
srRetVal iRet;
@@ -114,7 +114,6 @@ srRetVal sbStrBAppendInt(sbStrBObj *pThis, int i) return sbStrBAppendStr(pThis, szBuf);
}
-#endif
srRetVal sbStrBAppendChar(sbStrBObj *pThis, char c)
@@ -103,7 +103,7 @@ char copyright2[] = #endif /* not lint */ #if !defined(lint) && !defined(NO_SCCS) -static char sccsid[] = "@(#)rsyslogd.c 0.1 (Adiscon) 11/08/2004"; +static char sccsid[] = "@(#)rsyslogd.c 0.2 (Adiscon) 11/08/2004"; #endif /* not lint */ /* @@ -742,8 +742,12 @@ struct msg { #define SOURCE_STDIN 1 #define SOURCE_UNIXAF 2 #define SOURCE_INET 3 -/**/ short iSeverity; /* the severity 0..7 */ +/**/ short iSeverity; /* the severity 0..7 */ +/**/ char *pszSeverity; /* severity as string... */ +/**/ int iLenSeverity; /* ... and its length. */ /**/ int iFacility; /* Facility code (up to 2^32-1) */ +/**/ char *pszFacility; /* Facility as string... */ +/**/ int iLenFacility; /* ... and its length. */ /**/ char *pszRawMsg; /* message as it was received on the * wire. This is important in case we * need to preserve cryptographic verifiers. @@ -760,6 +764,7 @@ struct msg { /**/ char *pszRcvFrom; /* System message was received from */ /**/ int iLenRcvFrom; /* Length of pszRcvFrom */ /**/ struct syslogTime tRcvdAt;/* time the message entered this program */ +/**/ char *pszRcvdAt3164; /* time as RFC3164 formatted string (always 15 chracters) */ /**/ struct syslogTime tTIMESTAMP;/* (parsed) value of the timestamp */ }; @@ -1163,7 +1168,7 @@ static int srSLMGParseTIMESTAMP3164(struct syslogTime *pTime, unsigned char* psz *******************************************************************/ /** - * Format a syslogTimestamp to a text format. + * 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 @@ -1177,13 +1182,27 @@ int formatTimestamp3164(struct syslogTime *ts, char* pBuf, size_t iLenBuf) 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. + */ +int formatTimestamp(struct syslogTime *ts, char* pBuf, size_t iLenBuf) +{ + assert(ts != NULL); + assert(pBuf != NULL); + if(ts->timeType == 1) { - 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 - )); + return(formatTimestamp3164(ts, pBuf, iLenBuf)); } if(ts->timeType == 2) { @@ -1273,6 +1292,7 @@ struct msg* MsgConstruct() pM->iSyslogVers = -1; pM->iSeverity = -1; pM->iFacility = -1; + pM->pszRcvdAt3164 = NULL; pM->pszRawMsg = NULL; pM->pszUxTradMsg = NULL; pM->pszTAG = NULL; @@ -1290,7 +1310,7 @@ struct msg* MsgConstruct() pM->tTIMESTAMP.timeType = 0; } -printf("MsgConstruct\t0x%x\n", (int)pM); + dprintf("MsgConstruct\t0x%x\n", (int)pM); return(pM); } @@ -1301,10 +1321,11 @@ printf("MsgConstruct\t0x%x\n", (int)pM); */ void MsgDestruct(struct msg * pM) { -printf("MsgDestruct\t0x%x, Ref now: %d\n", (int)pM, pM->iRefCount - 1); + assert(pM != NULL); + dprintf("MsgDestruct\t0x%x, Ref now: %d\n", (int)pM, pM->iRefCount - 1); if(--pM->iRefCount == 0) { -printf("MsgDestruct\t0x%x, RefCount now 0, doing DESTROY\n", (int)pM); + dprintf("MsgDestruct\t0x%x, RefCount now 0, doing DESTROY\n", (int)pM); if(pM->pszRawMsg != NULL) free(pM->pszRawMsg); if(pM->pszTAG != NULL) @@ -1315,6 +1336,12 @@ printf("MsgDestruct\t0x%x, RefCount now 0, doing DESTROY\n", (int)pM); free(pM->pszRcvFrom); if(pM->pszMSG != NULL) free(pM->pszMSG); + if(pM->pszFacility != NULL) + free(pM->pszFacility); + if(pM->pszSeverity != NULL) + free(pM->pszSeverity); + if(pM->pszRcvdAt3164 != NULL) + free(pM->pszRcvdAt3164); free(pM); } } @@ -1330,7 +1357,7 @@ struct msg *MsgAddRef(struct msg *pM) { assert(pM != NULL); pM->iRefCount++; -printf("MsgAddRef\t0x%x done, Ref now: %d\n", (int)pM, pM->iRefCount); + dprintf("MsgAddRef\t0x%x done, Ref now: %d\n", (int)pM, pM->iRefCount); return(pM); } @@ -1342,6 +1369,17 @@ int getMSGLen(struct msg *pM) } +char *getUxTradMsg(struct msg *pM) +{ + if(pM == NULL) + return ""; + else + if(pM->pszUxTradMsg == NULL) + return ""; + else + return pM->pszUxTradMsg; +} + char *getMSG(struct msg *pM) { if(pM == NULL) @@ -1354,6 +1392,18 @@ char *getMSG(struct msg *pM) } +char *getTAG(struct msg *pM) +{ + if(pM == NULL) + return ""; + else + if(pM->pszTAG == NULL) + return ""; + else + return pM->pszTAG; +} + + char *getHOSTNAME(struct msg *pM) { if(pM == NULL) @@ -1486,6 +1536,82 @@ int MsgSetRawMsg(struct msg *pMsg, char* pszRawMsg) return(0); } + +/* This function returns a string-representation of the + * requested message property. This is a generic function used + * to abstract properties so that these can be easier + * queried. Returns NULL if property could not be found. + * Actually, this function is a big if..elseif. What it does + * is simply to map property names (from MonitorWare) to the + * message object data fields. + * + * In case we need string forms of propertis we do not + * yet have in string form, we do a memory allocation that + * is sufficiently large (in all cases). Once the string + * form has been obtained, it is saved until the Msg object + * is finally destroyed. This is so that we save the processing + * time in the (likely) case that this property is requested + * again. It also saves us a lot of dynamic memory management + * issues in the upper layers, because we so can guarantee that + * the buffer will remain static AND available during the lifetime + * of the object. Please note that both the max size allocation as + * well as keeping things in memory might like look like a + * waste of memory (some might say it actually is...) - we + * deliberately accept this because performance is more important + * to us ;) + * rgerhards 2004-11-18 + */ +char *MsgGetProp(struct msg *pMsg, char *pName) +{ + char *pRes; /* result pointer */ + char *pBuf; + static char errMsg[] = "##Can't get property - memory allocation failed!##"; + + assert(pMsg != NULL); + assert(pName != NULL); + + if(!strcmp(pName, "msg")) { + pRes = getMSG(pMsg); + } else if(!strcmp(pName, "UxTradMsg")) { + pRes = getUxTradMsg(pMsg); + } else if(!strcmp(pName, "hostname")) { + pRes = getHOSTNAME(pMsg); + } else if(!strcmp(pName, "syslogtag")) { + pRes = getTAG(pMsg); + } else if(!strcmp(pName, "syslogfacility")) { + if(pMsg->pszFacility == NULL) { + /* we use a 12 byte buffer - as of + * syslog-protocol, facility can go + * up to 2^32 -1 + */ + if((pMsg->pszFacility = malloc(12)) == NULL) return errMsg; + pMsg->iLenFacility = + snprintf(pMsg->pszFacility, 12, "%d", pMsg->iFacility); + } + pRes = pMsg->pszFacility; + } else if(!strcmp(pName, "syslogpriority")) { + if(pMsg->pszSeverity == NULL) { + /* we use a 2 byte buffer - can only be one digit */ + if((pMsg->pszSeverity = malloc(2)) == NULL) return errMsg; + pMsg->iLenSeverity = + snprintf(pMsg->pszSeverity, 2, "%d", pMsg->iSeverity); + } + pRes = pMsg->pszSeverity; + } else if(!strcmp(pName, "timegenerated")) { + if(pMsg->pszRcvdAt3164 == NULL) { + if((pMsg->pszRcvdAt3164 = malloc(16)) == NULL) return errMsg; +printf("fomrat returns %d\n", formatTimestamp3164(&pMsg->tRcvdAt, pMsg->pszRcvdAt3164, 16) +); +printf("Timesamp: '%s'\n", pMsg->pszRcvdAt3164); + } + pRes = pMsg->pszRcvdAt3164; + } else { + pRes = "INVALID PROPERTY NAME"; /* NULL;*/ + } + + return(pRes); +} + /* rgerhards 2004-11-09: end of helper routines. On to the * "real" code ;) */ @@ -2503,9 +2629,13 @@ void logmsg(pri, pMsg, flags) */ void writeFile(struct filed *f) { - struct iovec iov[10]; - register struct iovec *v = iov; - char szTIMESTAMP[40]; + struct iovec *iov; + register struct iovec *v; + int iIOVused; + /*char szTIMESTAMP[40];*/ + struct template *pTpl; + struct templateEntry *pTpe; + struct msg *pMsg; assert(f != NULL); /* f->f_file == -1 is an indicator that the we couldn't @@ -2519,23 +2649,37 @@ void writeFile(struct filed *f) * code this part of the function. rgerhards 2004-11-11 */ - v->iov_base = " "; - v->iov_len = 1; - v++; - v->iov_len = formatTimestamp3164(&f->f_pMsg->tTIMESTAMP, - szTIMESTAMP, sizeof(szTIMESTAMP) / sizeof(char)); - v->iov_base = szTIMESTAMP; - v++; - v->iov_base = " "; - v->iov_len = 1; - v++; + pMsg = f->f_pMsg; - /*v->iov_base = f->f_pMsg->pszRawMsg; - v->iov_len = f->f_pMsg->iLenRawMsg;*/ - v->iov_base = f->f_pMsg->pszMSG; - v->iov_len = f->f_pMsg->iLenMSG; - v++; + /*if((pTpl = tplFind("TraditionalFormat", strlen("TraditionalFormat"))) == NULL) {*/ + if((pTpl = tplFind("precise", strlen("precise"))) == NULL) { + dprintf("Could not find template '%s'\n", "precise"); + return; + } + + /* TODO: allocate iov in struct filed! */ + iov = calloc(tplGetEntryCount(pTpl), sizeof(struct iovec)); + v = iov; + + iIOVused = 0; + pTpe = pTpl->pEntryRoot; + while(pTpe != NULL) { + if(pTpe->eEntryType == CONSTANT) { + v->iov_base = pTpe->data.constant.pConstant; + v->iov_len = pTpe->data.constant.iLenConstant; + ++v; + ++iIOVused; + } else if(pTpe->eEntryType == FIELD) { + v->iov_base = MsgGetProp(pMsg, pTpe->data.pPropRepl); + v->iov_len = strlen(v->iov_base); + /* TODO: performance optimize - can we obtain the length? */ + ++v; + ++iIOVused; + } + pTpe = pTpe->pNext; + } +#if 0 /* almost done - just let's check how we need to terminate * the message. */ @@ -2548,8 +2692,9 @@ void writeFile(struct filed *f) v->iov_len = 1; } +#endif again: - if (writev(f->f_file, iov, v - iov + 1) < 0) { + if (writev(f->f_file, iov, iIOVused) < 0) { int e = errno; /* If a named pipe is full, just ignore it for now @@ -3447,6 +3592,7 @@ void init() printf("\n"); } } + tplPrintList(); } if ( AcceptRemote ) @@ -40,12 +40,12 @@ struct templateEntry* tpeConstruct(struct template *pTpl) pTpl->pEntryLast->pNext = pTpe; pTpl->pEntryLast = pTpe; } + pTpl->tpenElements++; return(pTpe); } - /* Constructs a template list object. Returns pointer to it * or NULL (if it fails). */ @@ -80,6 +80,7 @@ static int do_Constant(char **pp, struct template *pTpl) { register char *p; sbStrBObj *pStrB; + struct templateEntry *pTpe; assert(pp != NULL); assert(*pp != NULL); @@ -91,14 +92,45 @@ static int do_Constant(char **pp, struct template *pTpl) 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++); + while(*p && *p != '%' && *p != '\"') { + if(*p == '\\') { + switch(*++p) { + case '\0': + /* the best we can do - it's invalid anyhow... */ + sbStrBAppendChar(pStrB, *p); + break; + case 'n': + sbStrBAppendChar(pStrB, '\n'); + ++p; + break; + case '\\': + sbStrBAppendChar(pStrB, '\\'); + ++p; + break; + case '%': + sbStrBAppendChar(pStrB, '%'); + ++p; + break; + default: + sbStrBAppendChar(pStrB, *p++); + break; + } + } + else + sbStrBAppendChar(pStrB, *p++); + } + + if((pTpe = tpeConstruct(pTpl)) == NULL) { + /* TODO: add handler */ + return 1; } + pTpe->eEntryType = CONSTANT; + pTpe->data.constant.pConstant = sbStrBFinish(pStrB); + /* we need to call strlen() below because of the escape sequneces. + * due to them p -*pp is NOT the rigt size! + */ + pTpe->data.constant.iLenConstant = strlen(pTpe->data.constant.pConstant); - printf("Constant: '%s'\n", sbStrBFinish(pStrB)); *pp = p; return 0; @@ -113,6 +145,7 @@ static int do_Parameter(char **pp, struct template *pTpl) { register char *p; sbStrBObj *pStrB; + struct templateEntry *pTpe; assert(pp != NULL); assert(*pp != NULL); @@ -126,7 +159,15 @@ static int do_Parameter(char **pp, struct template *pTpl) sbStrBAppendChar(pStrB, *p++); } if(*p) ++p; /* eat '%' */ - printf("Parameter: '%s'\n", sbStrBFinish(pStrB)); + + /* now store param */ + if((pTpe = tpeConstruct(pTpl)) == NULL) { + /* TODO: add handler */ + dprintf("Could not allocate memory for template parameter!\n"); + return 1; + } + pTpe->eEntryType = FIELD; + pTpe->data.pPropRepl = sbStrBFinish(pStrB); *pp = p; return 0; @@ -204,10 +245,12 @@ struct template *tplAddLine(char* pName, char** ppRestOfConfLine) do_Constant(&p, pTpl); break; } + if(*p == '\"') {/* end of template string? */ + ++p; /* eat it! */ + bDone = 1; + } } -printf("tplAddLine, Name '%s', restOfLine: %s", pTpl->pszName, p); - *ppRestOfConfLine = p; return(pTpl); } @@ -236,6 +279,43 @@ struct template *tplFind(char *pName, int iLenName) return(pTpl); } +/* Print the template structure. This is more or less a + * debug or test aid, but anyhow I think it's worth it... + */ +void tplPrintList(void) +{ + struct template *pTpl; + struct templateEntry *pTpe; + + pTpl = tplRoot; + while(pTpl != NULL) { + dprintf("Template: Name='%s'\n", pTpl->pszName == NULL? "NULL" : pTpl->pszName); + pTpe = pTpl->pEntryRoot; + while(pTpe != NULL) { + dprintf("\tEntry: type %d, ", pTpe->eEntryType); + switch(pTpe->eEntryType) { + case UNDEFINED: + dprintf("(UNDEFINED)\n"); + break; + case CONSTANT: + dprintf("(CONSTANT), value: '%s'\n", + pTpe->data.constant.pConstant); + break; + case FIELD: + dprintf("(FIELD), value: '%s'\n", pTpe->data.pPropRepl); + break; + } + pTpe = pTpe->pNext; + } + pTpl = pTpl->pNext; /* done, go next */ + } +} + +int tplGetEntryCount(struct template *pTpl) +{ + assert(pTpl != NULL); + return(pTpl->tpenElements); +} /* * vi:set ai: */ @@ -7,6 +7,7 @@ struct template { struct template *pNext; char *pszName; int iLenName; + int tpenElements; /* number of elements in templateEntry list */ struct templateEntry *pEntryRoot; struct templateEntry *pEntryLast; }; @@ -18,14 +19,19 @@ struct templateEntry { struct templateEntry *pNext; enum EntryTypes eEntryType; union { - char *pConstant; /* pointer to constant value */ + struct { + char *pConstant; /* pointer to constant value */ + int iLenConstant; /* its length */ + } constant; char *pPropRepl; /* pointer to property replacer string */ - }; + } data; }; struct template* tplConstruct(void); struct template *tplAddLine(char* pName, char** pRestOfConfLine); struct template *tplFind(char *pName, int iLenName); +int tplGetEntryCount(struct template *pTpl); +void tplPrintList(void); /* * vi:set ai: |