summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Makefile7
-rwxr-xr-xsrUtils.c99
-rwxr-xr-xsrUtils.h63
-rwxr-xr-xstringbuf.c3
-rw-r--r--syslogd.c210
-rw-r--r--template.c100
-rw-r--r--template.h10
7 files changed, 444 insertions, 48 deletions
diff --git a/Makefile b/Makefile
index 33b7d8ff..02d0394b 100644
--- a/Makefile
+++ b/Makefile
@@ -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)
diff --git a/syslogd.c b/syslogd.c
index b5da3149..595ced88 100644
--- a/syslogd.c
+++ b/syslogd.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 )
diff --git a/template.c b/template.c
index a2ccfbb4..b3c5853a 100644
--- a/template.c
+++ b/template.c
@@ -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:
*/
diff --git a/template.h b/template.h
index e438e988..a3019828 100644
--- a/template.h
+++ b/template.h
@@ -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: