summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2008-01-07 17:26:49 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2008-01-07 17:26:49 +0000
commit571d21a33a46707deabc80769b4c8cb7d0f7c161 (patch)
treebab2d123fb14afa219f841cc41d809d541b57dc2
parent918f281d8226689f5c997a07c0bcd9a691ddb178 (diff)
downloadrsyslog-571d21a33a46707deabc80769b4c8cb7d0f7c161.tar.gz
rsyslog-571d21a33a46707deabc80769b4c8cb7d0f7c161.tar.xz
rsyslog-571d21a33a46707deabc80769b4c8cb7d0f7c161.zip
- MsgSetProperty() implemented
- defined a property class - implemented deserializer (needs some more work)
-rw-r--r--msg.c67
-rw-r--r--msg.h2
-rw-r--r--obj.c282
-rw-r--r--obj.h43
-rw-r--r--plugins/imklog/imklog.c10
-rw-r--r--queue.c50
-rw-r--r--queue.h2
-rw-r--r--rsyslog.h9
-rw-r--r--syslogd.c42
-rw-r--r--syslogd.h3
10 files changed, 435 insertions, 75 deletions
diff --git a/msg.c b/msg.c
index 7c17f8ce..3e34ac1c 100644
--- a/msg.c
+++ b/msg.c
@@ -38,6 +38,7 @@
#include <ctype.h>
#include "syslogd.h"
#include "srUtils.h"
+#include "stringbuf.h"
#include "template.h"
#include "msg.h"
@@ -203,22 +204,28 @@ rsRetVal MsgEnableThreadSafety(void)
* An object constructed via this function should only be destroyed
* via "MsgDestruct()".
*/
-msg_t* MsgConstruct(void)
+rsRetVal MsgConstruct(msg_t **ppThis)
{
+ DEFiRet;
msg_t *pM;
- if((pM = calloc(1, sizeof(msg_t))) != NULL)
- { /* initialize members that are non-zero */
- pM->iRefCount = 1;
- pM->iSeverity = -1;
- pM->iFacility = -1;
- getCurrTime(&(pM->tRcvdAt));
- objConstructSetObjInfo(pM);
- }
+ assert(ppThis != NULL);
+ if((pM = calloc(1, sizeof(msg_t))) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ /* initialize members that are non-zero */
+ pM->iRefCount = 1;
+ pM->iSeverity = -1;
+ pM->iFacility = -1;
+ getCurrTime(&(pM->tRcvdAt));
+ objConstructSetObjInfo(pM);
/* DEV debugging only! dbgprintf("MsgConstruct\t0x%x, ref 1\n", (int)pM);*/
- return(pM);
+ *ppThis = pM;
+
+finalize_it:
+ return iRet;
}
@@ -2076,12 +2083,52 @@ char *MsgGetProp(msg_t *pMsg, struct templateEntry *pTpe,
}
+/* This function can be used as a generic way to set properties.
+ * We have to handle a lot of legacy, so our return value is not always
+ * 100% correct (called functions do not always provide one, should
+ * change over time).
+ * rgerhards, 2008-01-07
+ */
+#define isProp(name) !rsCStrSzStrCmp(pProp->pcsName, (uchar*) name, sizeof(name) - 1)
+rsRetVal MsgSetProperty(msg_t *pThis, property_t *pProp)
+{
+ DEFiRet;
+
+ assert(pThis != NULL);
+ assert(pProp != NULL);
+
+ if(isProp("iProtocolVersion")) {
+ setProtocolVersion(pThis, pProp->val.vShort);
+ } else if(isProp("iSeverity")) {
+ pThis->iSeverity = pProp->val.vShort;
+ } else if(isProp("iFacility")) {
+ pThis->iFacility = pProp->val.vShort;
+ } else if(isProp("msgFlags")) {
+ pThis->msgFlags = pProp->val.vInt;
+ } else if(isProp("pszRawMsg")) {
+ MsgSetRawMsg(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.vpCStr));
+ } else if(isProp("pszMSG")) {
+ MsgSetMSG(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.vpCStr));
+ } else if(isProp("pszTAG")) {
+ MsgSetTAG(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.vpCStr));
+ } else if(isProp("pszHOSTNAME")) {
+ MsgSetHOSTNAME(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.vpCStr));
+ } else if(isProp("pszUxTradMsg")) {
+ MsgSetUxTradMsg(pThis, (char*) rsCStrGetSzStrNoNULL(pProp->val.vpCStr));
+ }
+
+ return iRet;
+}
+#undef isProp
+
+
/* Initialize the message class. Must be called as the very first method
* before anything else is called inside this class.
* rgerhards, 2008-01-04
*/
BEGINObjClassInit(Msg, 1)
OBJSetMethodHandler(objMethod_SERIALIZE, MsgSerialize);
+ OBJSetMethodHandler(objMethod_SETPROPERTY, MsgSetProperty);
/* initially, we have no need to lock message objects */
funcLock = MsgLockingDummy;
funcUnlock = MsgLockingDummy;
diff --git a/msg.h b/msg.h
index b904785b..bd8d4f89 100644
--- a/msg.h
+++ b/msg.h
@@ -108,7 +108,7 @@ typedef struct msg msg_t; /* new name */
*/
PROTOTYPEObjClassInit(Msg);
char* getProgramName(msg_t*);
-msg_t* MsgConstruct(void);
+rsRetVal MsgConstruct(msg_t **ppThis);
rsRetVal MsgDestruct(msg_t * pM);
msg_t* MsgDup(msg_t* pOld);
msg_t *MsgAddRef(msg_t *pM);
diff --git a/obj.c b/obj.c
index 458f7856..356d38d9 100644
--- a/obj.c
+++ b/obj.c
@@ -30,6 +30,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <ctype.h>
#include <assert.h>
#include "rsyslog.h"
@@ -40,6 +41,13 @@
/* static data */
static objInfo_t *arrObjInfo[OBJ_NUM_IDS]; /* array with object information pointers */
+/* some defines */
+
+/* cookies for serialized lines */
+#define COOKIE_OBJLINE '<'
+#define COOKIE_PROPLINE '+'
+#define COOKIE_ENDLINE '>'
+
/* methods */
/* This is a dummy method to be used when a standard method has not been
@@ -55,11 +63,12 @@ static rsRetVal objInfoNotImplementedDummy(void __attribute__((unused)) *pThis)
/* construct an object Info object. Each class shall do this on init. The
* resulting object shall be cached during the lifetime of the class and each
- * object shall receive a reference. A constructor MUST be provided for all
- * objects, thus it is in the parameter list.
+ * object shall receive a reference. A constructor and destructor MUST be provided for all
+ * objects, thus they are in the parameter list.
* pszName must point to constant pool memory. It is never freed.
*/
-rsRetVal objInfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers, rsRetVal (*pDestruct)(void *))
+rsRetVal objInfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers,
+ rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *))
{
DEFiRet;
int i;
@@ -75,8 +84,9 @@ rsRetVal objInfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int
pThis->iObjVers = iObjVers;
pThis->objID = objID;
- pThis->objMethods[0] = pDestruct;
- for(i = 1 ; i < OBJ_NUM_METHODS ; ++i) {
+ pThis->objMethods[0] = pConstruct;
+ pThis->objMethods[1] = pDestruct;
+ for(i = 2 ; i < OBJ_NUM_METHODS ; ++i) {
pThis->objMethods[i] = objInfoNotImplementedDummy;
}
@@ -191,6 +201,8 @@ rsRetVal objSerializeProp(rsCStrObj *pCStr, uchar *pszPropName, propertyType_t p
break;
}
+ /* cookie */
+ CHKiRet(rsCStrAppendChar(pCStr, COOKIE_PROPLINE));
/* name */
CHKiRet(rsCStrAppendStr(pCStr, pszPropName));
CHKiRet(rsCStrAppendChar(pCStr, ':'));
@@ -205,6 +217,7 @@ rsRetVal objSerializeProp(rsCStrObj *pCStr, uchar *pszPropName, propertyType_t p
CHKiRet(rsCStrAppendStrWithLen(pCStr, (uchar*) pszBuf, lenBuf));
/* trailer */
+ CHKiRet(rsCStrAppendChar(pCStr, ':'));
CHKiRet(rsCStrAppendChar(pCStr, '\n'));
finalize_it:
@@ -225,7 +238,8 @@ static rsRetVal objSerializeHeader(rsCStrObj **ppCStr, obj_t *pObj, rsCStrObj *p
rsCStrSetAllocIncrement(pCStr, iAllocIncrement);
/* object cookie and serializer version (so far always 1) */
- CHKiRet(rsCStrAppendStr(pCStr, (uchar*) "$Obj1"));
+ CHKiRet(rsCStrAppendChar(pCStr, COOKIE_OBJLINE));
+ CHKiRet(rsCStrAppendStr(pCStr, (uchar*) "Obj1"));
/* object type, version and string length */
CHKiRet(rsCStrAppendChar(pCStr, ':'));
@@ -242,6 +256,7 @@ static rsRetVal objSerializeHeader(rsCStrObj **ppCStr, obj_t *pObj, rsCStrObj *p
CHKiRet(rsCStrAppendChar(pCStr, ':'));
CHKiRet(rsCStrAppendStr(pCStr, objGetName(pObj)));
/* record trailer */
+ CHKiRet(rsCStrAppendChar(pCStr, ':'));
CHKiRet(rsCStrAppendChar(pCStr, '\n'));
*ppCStr = pCStr;
@@ -263,7 +278,8 @@ rsRetVal objEndSerialize(rsCStrObj **ppCStr, obj_t *pObj)
CHKiRet(objSerializeHeader(&pCStr, pObj, *ppCStr, rsCStrGetAllocIncrement(*ppCStr)));
CHKiRet(rsCStrAppendStrWithLen(pCStr, rsCStrGetBufBeg(*ppCStr), rsCStrLen(*ppCStr)));
- CHKiRet(rsCStrAppendStr(pCStr, (uchar*) ".\n"));
+ CHKiRet(rsCStrAppendChar(pCStr, COOKIE_ENDLINE));
+ CHKiRet(rsCStrAppendStr(pCStr, (uchar*) "EndObj\n\n"));
CHKiRet(rsCStrFinish(pCStr));
rsCStrDestruct(*ppCStr);
@@ -275,6 +291,258 @@ finalize_it:
return iRet;
}
+
+/* define a helper to make code below a bit cleaner (and quicker to write) */
+#define NEXTC CHKiRet(serialStoreGetChar(pSerStore, &c))//;dbgprintf("c: %c\n", c);
+
+/* de-serialize an (long) integer */
+static rsRetVal objDeserializeLong(long *pInt, serialStore_t *pSerStore)
+{
+ DEFiRet;
+ int i;
+ uchar c;
+
+ assert(pInt != NULL);
+
+ NEXTC;
+ i = 0;
+ while(isdigit(c)) {
+ i = i * 10 + c - '0';
+ NEXTC;
+ }
+
+ if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_DELIMITER);
+
+ *pInt = i;
+finalize_it:
+ return iRet;
+}
+
+
+/* de-serialize a string, length must be provided */
+static rsRetVal objDeserializeStr(rsCStrObj **ppCStr, int iLen, serialStore_t *pSerStore)
+{
+ DEFiRet;
+ int i;
+ uchar c;
+ rsCStrObj *pCStr = NULL;
+
+ assert(ppCStr != NULL);
+ assert(iLen > 0);
+
+ if((pCStr = rsCStrConstruct()) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ NEXTC;
+dbgprintf("deserializestring, c: %c (%x)\n", c, c);
+ for(i = 0 ; i < iLen ; ++i) {
+ CHKiRet(rsCStrAppendChar(pCStr, c));
+ NEXTC;
+ }
+ CHKiRet(rsCStrFinish(pCStr));
+
+ /* check terminator */
+ if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_DELIMITER);
+
+ *ppCStr = pCStr;
+
+finalize_it:
+ if(iRet != RS_RET_OK && pCStr != NULL)
+ rsCStrDestruct(pCStr);
+
+ return iRet;
+}
+
+
+/* de-serialize an object header
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal objDeserializeHeader(objID_t *poID, int* poVers, serialStore_t *pSerStore)
+{
+ DEFiRet;
+ long ioID;
+ long oVers;
+ uchar c;
+
+ assert(poID != NULL);
+ assert(poVers != NULL);
+
+ /* check header cookie */
+ NEXTC; if(c != COOKIE_OBJLINE) ABORT_FINALIZE(RS_RET_INVALID_HEADER);
+ NEXTC; if(c != 'O') ABORT_FINALIZE(RS_RET_INVALID_HEADER);
+ NEXTC; if(c != 'b') ABORT_FINALIZE(RS_RET_INVALID_HEADER);
+ NEXTC; if(c != 'j') ABORT_FINALIZE(RS_RET_INVALID_HEADER);
+ NEXTC; if(c != '1') ABORT_FINALIZE(RS_RET_INVALID_HEADER_VERS);
+ NEXTC; if(c != ':') ABORT_FINALIZE(RS_RET_INVALID_HEADER_VERS);
+
+ /* object type and version and string length */
+ CHKiRet(objDeserializeLong(&ioID, pSerStore));
+ CHKiRet(objDeserializeLong(&oVers, pSerStore));
+
+ if(ioID < 1 || ioID >= OBJ_NUM_IDS)
+ ABORT_FINALIZE(RS_RET_INVALID_OID);
+
+ /* and now we skip over the rest until the delemiting \n */
+ NEXTC;
+ while(c != '\n')
+ NEXTC;
+
+ *poID = (objID_t) ioID;
+ *poVers = oVers;
+
+finalize_it:
+dbgprintf("DeserializeHeader oid: %ld, vers: %ld, iRet: %d\n", ioID, oVers, iRet);
+ return iRet;
+}
+
+
+/* Deserialize a single property. Pointer must be positioned at begin of line. Whole line
+ * up until the \n is read.
+ */
+static rsRetVal objDeserializeProperty(property_t *pProp, serialStore_t *pSerStore)
+{
+ DEFiRet;
+ long i;
+ long iLen;
+ uchar c;
+
+ assert(pProp != NULL);
+
+ /* check cookie */
+ NEXTC;
+ if(c != COOKIE_PROPLINE) {
+ /* oops, we've read one char that does not belong to use - unget it first */
+ CHKiRet(serialStoreUngetChar(pSerStore, c));
+ ABORT_FINALIZE(RS_RET_NO_PROPLINE);
+ }
+
+ /* get the property name first */
+ if((pProp->pcsName = rsCStrConstruct()) == NULL)
+ ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
+
+ NEXTC;
+ while(c != ':') {
+ CHKiRet(rsCStrAppendChar(pProp->pcsName, c));
+ NEXTC;
+ }
+ CHKiRet(rsCStrFinish(pProp->pcsName));
+
+ /* property type */
+ CHKiRet(objDeserializeLong(&i, pSerStore));
+ pProp->propType = i;
+
+ /* size (needed for strings) */
+ CHKiRet(objDeserializeLong(&iLen, pSerStore));
+
+ /* we now need to deserialize the value */
+dbgprintf("deserialized property name '%s', type %d, size %ld, c: %c\n", rsCStrGetSzStrNoNULL(pProp->pcsName), pProp->propType, iLen, c);
+ switch(pProp->propType) {
+ case PROPTYPE_PSZ:
+ CHKiRet(objDeserializeStr(&pProp->val.vpCStr, iLen, pSerStore));
+ break;
+ case PROPTYPE_SHORT:
+ CHKiRet(objDeserializeLong(&i, pSerStore));
+ pProp->val.vShort = i;
+ break;
+ case PROPTYPE_INT:
+ CHKiRet(objDeserializeLong(&i, pSerStore));
+ pProp->val.vInt = i;
+ break;
+ case PROPTYPE_LONG:
+ CHKiRet(objDeserializeLong(&pProp->val.vLong, pSerStore));
+ break;
+ case PROPTYPE_CSTR:
+ CHKiRet(objDeserializeStr(&pProp->val.vpCStr, iLen, pSerStore));
+ break;
+ case PROPTYPE_SYSLOGTIME:
+ /* dummy */ NEXTC; while(c != ':') NEXTC;
+ break;
+ }
+
+ /* we should now be at the end of the line. So the next char must be \n */
+ NEXTC;
+ if(c != '\n') ABORT_FINALIZE(RS_RET_INVALID_PROPFRAME);
+
+finalize_it:
+ return iRet;
+}
+
+
+/* de-serialize an object trailer. This does not get any data but checks if the
+ * format is ok.
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal objDeserializeTrailer(serialStore_t *pSerStore)
+{
+ DEFiRet;
+ uchar c;
+
+ /* check header cookie */
+ NEXTC; if(c != COOKIE_ENDLINE) ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'E') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'd') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'O') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'b') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != 'j') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != '\n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+ NEXTC; if(c != '\n') ABORT_FINALIZE(RS_RET_INVALID_TRAILER);
+
+dbgprintf("obj trailer OK\n");
+finalize_it:
+ return iRet;
+}
+
+
+/* De-Serialize an object.
+ * Params: Pointer to object Pointer (pObj) (like a obj_t**, but can not do that due to compiler warning)
+ * expected object ID (to check against)
+ * Function that returns the next character from the serialized object (from file, memory, whatever)
+ * Pointer to be passed to the function
+ * The caller must destruct the created object.
+ * rgerhards, 2008-01-07
+ */
+rsRetVal objDeserialize(void *ppObj, objID_t objTypeExpected, serialStore_t *pSerStore)
+{
+ DEFiRet;
+ obj_t *pObj = NULL;
+ property_t propBuf;
+ objID_t oID = 0; /* this assignment is just to supress a compiler warning - this saddens me */
+ int oVers = 0; /* after all, it is totally useless but takes up some execution time... */
+
+ assert(ppObj != NULL);
+ assert(objTypeExpected > 0 && objTypeExpected < OBJ_NUM_IDS);
+ assert(pSerStore != NULL);
+
+ CHKiRet(objDeserializeHeader(&oID, &oVers, pSerStore));
+
+ if(oID != objTypeExpected)
+ ABORT_FINALIZE(RS_RET_INVALID_OID);
+ CHKiRet(arrObjInfo[oID]->objMethods[objMethod_CONSTRUCT](&pObj));
+
+ /* we got the object, now we need to fill the properties */
+ iRet = objDeserializeProperty(&propBuf, pSerStore);
+ while(iRet == RS_RET_OK) {
+ CHKiRet(arrObjInfo[oID]->objMethods[objMethod_SETPROPERTY](pObj, &propBuf));
+ iRet = objDeserializeProperty(&propBuf, pSerStore);
+ }
+ rsCStrDestruct(propBuf.pcsName); /* todo: a destructor would be nice here... -- rger, 2008-01-07 */
+
+ if(iRet != RS_RET_NO_PROPLINE)
+ FINALIZE;
+dbgprintf("good propline loop exit\n");
+
+ CHKiRet(objDeserializeTrailer(pSerStore)); /* do trailer checks */
+
+ *((obj_t**) ppObj) = pObj;
+
+finalize_it:
+ return iRet;
+}
+
+#undef NEXTC /* undef helper macro */
+
+
/* --------------- end object serializiation / deserialization support --------------- */
/* register a classe's info pointer, so that we can reference it later, if needed to
diff --git a/obj.h b/obj.h
index f4c9f6cd..74fe5b7c 100644
--- a/obj.h
+++ b/obj.h
@@ -38,6 +38,19 @@ typedef enum { /* do NOT start at 0 to detect uninitialized types after calloc(
PROPTYPE_SYSLOGTIME = 6
} propertyType_t;
+typedef struct {
+ rsCStrObj *pcsName;
+ propertyType_t propType;
+ union {
+ short vShort;
+ int vInt;
+ long vLong;
+ rsCStrObj *vpCStr; /* used for both rsCStr and psz */
+ struct syslogTime vSyslogTime;
+
+ } val;
+} property_t;
+
/* object Types/IDs */
typedef enum { /* IDs of known object "types/classes" */
objNull = 0, /* no valid object (we do not start at zero so we can detect calloc()) */
@@ -48,12 +61,14 @@ typedef enum { /* IDs of known object "types/classes" */
typedef enum { /* IDs of base methods supported by all objects - used for jump table, so
* they must start at zero and be incremented. -- rgerahrds, 2008-01-04
*/
- objMethod_DESTRUCT = 0,
- objMethod_SERIALIZE = 1,
- objMethod_DESERIALIZE = 2,
- objMethod_DEBUGPRINT = 3
+ objMethod_CONSTRUCT = 0,
+ objMethod_DESTRUCT = 1,
+ objMethod_SERIALIZE = 2,
+ objMethod_DESERIALIZE = 3,
+ objMethod_SETPROPERTY = 4,
+ objMethod_DEBUGPRINT = 5
} objMethod_t;
-#define OBJ_NUM_METHODS 4 /* must be updated to contain the max number of methods supported */
+#define OBJ_NUM_METHODS 6 /* must be updated to contain the max number of methods supported */
typedef struct objInfo_s {
objID_t objID;
@@ -66,6 +81,18 @@ typedef struct obj { /* the dummy struct that each derived class can be casted t
objInfo_t *pObjInfo;
} obj_t;
+/* the following structure is used for deserialization. It defines a serial storage with a single
+ * ungetc() capability. This should probably become its own object some time. -- rgerhards, 2008-01-07
+ */
+typedef struct serialStore_s {
+ void *pUsr; /* Pointer to some user data */
+ /* methods */
+ rsRetVal (*funcGetChar)(void*, uchar*);
+ rsRetVal (*funcUngetChar)(void*, uchar);
+} serialStore_t;
+#define serialStoreGetChar(pThis, c) (pThis->funcGetChar(pThis->pUsr, c))
+#define serialStoreUngetChar(pThis, c) (pThis->funcUngetChar(pThis->pUsr, c))
+
/* macros */
#define objSerializeSCALAR(propName, propType) \
@@ -87,7 +114,8 @@ typedef struct obj { /* the dummy struct that each derived class can be casted t
rsRetVal objName##ClassInit(void) \
{ \
DEFiRet; \
- CHKiRet(objInfoConstruct(&pObjInfoOBJ, obj##objName, (uchar*) #objName, objVers, (rsRetVal (*)(void*))objName##Destruct));
+ CHKiRet(objInfoConstruct(&pObjInfoOBJ, obj##objName, (uchar*) #objName, objVers, \
+ (rsRetVal (*)(void*))objName##Construct, (rsRetVal (*)(void*))objName##Destruct));
#define ENDObjClassInit(objName) \
objRegisterObj(obj##objName, pObjInfoOBJ); \
@@ -100,13 +128,14 @@ finalize_it: \
/* prototypes */
-rsRetVal objInfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers, rsRetVal (*pDestruct)(void *));
+rsRetVal objInfoConstruct(objInfo_t **ppThis, objID_t objID, uchar *pszName, int iObjVers, rsRetVal (*pConstruct)(void *), rsRetVal (*pDestruct)(void *));
rsRetVal objInfoSetMethod(objInfo_t *pThis, objMethod_t objMethod, rsRetVal (*pHandler)(void*));
rsRetVal objBeginSerialize(rsCStrObj **ppCStr, obj_t *pObj, size_t iExpectedObjSize);
rsRetVal objSerializePsz(rsCStrObj *pCStr, uchar *psz, size_t len);
rsRetVal objEndSerialize(rsCStrObj **ppCStr, obj_t *pObj);
rsRetVal objSerializeProp(rsCStrObj *pCStr, uchar *pszPropName, propertyType_t propType, void *pUsr);
rsRetVal objRegisterObj(objID_t oID, objInfo_t *pInfo);
+rsRetVal objDeserialize(void *ppObj, objID_t objTypeExpected, serialStore_t *pSerStore);
PROTOTYPEObjClassInit(obj);
#endif /* #ifndef OBJ_H_INCLUDED */
diff --git a/plugins/imklog/imklog.c b/plugins/imklog/imklog.c
index 11bc8d41..8ed900dd 100644
--- a/plugins/imklog/imklog.c
+++ b/plugins/imklog/imklog.c
@@ -131,14 +131,7 @@ static rsRetVal writeSyslogV(int iPRI, const char *szFmt, va_list va)
/* here we must create our message object and supply it to the message queue
*/
- if((pMsg = MsgConstruct()) == NULL){
- /* There is not much we can do in this case - we discard the message
- * then.
- */
- dbgprintf("Memory shortage in imklogd: could not construct Msg object.\n");
- return RS_RET_OUT_OF_MEMORY;
- }
-
+ CHKiRet(MsgConstruct(&pMsg));
MsgSetUxTradMsg(pMsg, msgBuf);
MsgSetRawMsg(pMsg, msgBuf);
MsgSetMSG(pMsg, (msgBuf + iLen));
@@ -152,6 +145,7 @@ static rsRetVal writeSyslogV(int iPRI, const char *szFmt, va_list va)
/* provide message to the queue engine */
logmsg(iPRI, pMsg, INTERNAL_MSG);
+finalize_it:
return iRet;
}
diff --git a/queue.c b/queue.c
index c2b67d13..8630938a 100644
--- a/queue.c
+++ b/queue.c
@@ -42,6 +42,7 @@
#include "queue.h"
#include "stringbuf.h"
#include "srUtils.h"
+#include "obj.h"
/* static data */
@@ -275,6 +276,12 @@ static rsRetVal qDiskReadChar(queueFileDescription_t *pFile, uchar *pC)
ABORT_FINALIZE(RS_RET_OUT_OF_MEMORY);
pFile->iBufPtrMax = 0; /* results in immediate read request */
}
+
+ if(pFile->iUngetC != -1) { /* do we have an "unread" char that we need to provide? */
+ *pC = pFile->iUngetC;
+ pFile->iUngetC = -1;
+ ABORT_FINALIZE(RS_RET_OK);
+ }
/* do we need to obtain a new buffer */
if(pFile->iBufPtr >= pFile->iBufPtrMax) {
@@ -295,6 +302,26 @@ finalize_it:
return iRet;
}
+
+/* unget a single character just like ungetc(). As with that call, there is only a single
+ * character buffering capability.
+ * rgerhards, 2008-01-07
+ */
+static rsRetVal qDiskUnreadChar(queueFileDescription_t *pFile, uchar c)
+{
+ assert(pFile != NULL);
+ assert(pFile->iUngetC == -1);
+ pFile->iUngetC = c;
+
+ return RS_RET_OK;
+}
+
+#if 0
+/* we have commented out the code below because we would like to preserve it. It
+ * is currently not needed, but may be useful if we implemented a bufferred file
+ * class.
+ * rgerhards, 2008-01-07
+ */
/* read a line from a queue file. A line is terminated by LF. The LF is read, but it
* is not returned in the buffer (it is discared). The caller is responsible for
* destruction of the returned CStr object!
@@ -328,6 +355,7 @@ finalize_it:
return iRet;
}
+#endif /* #if 0 - saved code */
/*** end buffered read functions for queue files ***/
@@ -349,10 +377,12 @@ static rsRetVal qConstructDisk(queue_t *pThis)
pThis->tVars.disk.fWrite.iCurrFileNum = 1;
pThis->tVars.disk.fWrite.iCurrOffs = 0;
pThis->tVars.disk.fWrite.fd = -1;
+ pThis->tVars.disk.fWrite.iUngetC = -1;
pThis->tVars.disk.fRead.iCurrFileNum = 1;
pThis->tVars.disk.fRead.fd = -1;
- pThis->tVars.disk.fWrite.iCurrOffs = 0;
+ pThis->tVars.disk.fRead.iCurrOffs = 0;
+ pThis->tVars.disk.fRead.iUngetC = -1;
finalize_it:
return iRet;
@@ -401,29 +431,31 @@ finalize_it:
return iRet;
}
-static rsRetVal qDelDisk(queue_t __attribute__((unused)) *pThis, void __attribute__((unused)) **ppUsr)
+static rsRetVal qDelDisk(queue_t *pThis, void **ppUsr)
{
DEFiRet;
+ msg_t *pMsg = NULL;
+ serialStore_t serialStore;
assert(pThis != NULL);
if(pThis->tVars.disk.fRead.fd == -1)
CHKiRet(qDiskOpenFile(pThis, &pThis->tVars.disk.fRead, O_RDONLY, 0600)); // TODO: open modes!
- /* read here */
- rsCStrObj *pCStr = NULL;
- CHKiRet(qDiskReadLine(&pThis->tVars.disk.fRead, &pCStr));
- dbgprintf("qDelDisk read line '%s'\n", rsCStrGetSzStr(pCStr));
- rsCStrDestruct(pCStr);
- /* de-serialize here */
+ /* de-serialize object from file */
+ serialStore.pUsr = &pThis->tVars.disk.fRead;
+ serialStore.funcGetChar = (rsRetVal (*)(void*, uchar*)) qDiskReadChar;
+ serialStore.funcUngetChar = (rsRetVal (*)(void*, uchar)) qDiskUnreadChar;
+ CHKiRet(objDeserialize((void*) &pMsg, objMsg, &serialStore));
/* switch to next file when EOF is reached. We may also delete the last file in that case.
pThis->tVars.disk.fWrite.iCurrOffs += iWritten;
if(pThis->tVars.disk.fWrite.iCurrOffs >= pThis->tVars.disk.iMaxFileSize)
CHKiRet(qDiskNextFile(pThis, &pThis->tVars.disk.fWrite));
*/
+dbgprintf("got object %lx\n", (unsigned long) pMsg);
- iRet = RS_RET_ERR;
+ *ppUsr = (void*) pMsg;
finalize_it:
return iRet;
diff --git a/queue.h b/queue.h
index 8459d0f6..80b835ab 100644
--- a/queue.h
+++ b/queue.h
@@ -38,6 +38,7 @@ typedef struct {
uchar *pIOBuf; /* io Buffer */
int iBufPtrMax; /* current max Ptr in Buffer (if partial read!) */
int iBufPtr; /* pointer into current buffer */
+ int iUngetC; /* char set via UngetChar() call or -1 if none set */
} queueFileDescription_t;
#define qFILE_IOBUF_SIZE 4096 /* size of the IO buffer */
@@ -97,7 +98,6 @@ typedef struct queue_s {
} tVars;
} queue_t;
-
/* prototypes */
rsRetVal queueDestruct(queue_t *pThis);
rsRetVal queueEnqObj(queue_t *pThis, void *pUsr);
diff --git a/rsyslog.h b/rsyslog.h
index c9993c3f..b46b4b10 100644
--- a/rsyslog.h
+++ b/rsyslog.h
@@ -97,6 +97,12 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_EOF = -2026, /**< end of file reached, not necessarily an error */
RS_RET_IO_ERROR = -2027, /**< some kind of IO error happened */
RS_RET_INVALID_OID = -2028, /**< invalid object ID */
+ RS_RET_INVALID_HEADER = -2029, /**< invalid header */
+ RS_RET_INVALID_HEADER_VERS = -2030, /**< invalid header version */
+ RS_RET_INVALID_DELIMITER = -2031, /**< invalid delimiter, e.g. between params */
+ RS_RET_INVALID_PROPFRAME = -2032, /**< invalid framing in serialized property */
+ RS_RET_NO_PROPLINE = -2033, /**< line is not a property line */
+ RS_RET_INVALID_TRAILER = -2034, /**< invalid trailer */
RS_RET_OK_DELETE_LISTENTRY = 1, /**< operation successful, but callee requested the deletion of an entry (special state) */
RS_RET_TERMINATE_NOW = 2, /**< operation successful, function is requested to terminate (mostly used with threads) */
RS_RET_NO_RUN = 3, /**< operation successful, but function does not like to be executed */
@@ -175,6 +181,9 @@ typedef unsigned char uchar;
# define __attribute__(x) /*NOTHING*/
#endif
+/* The following prototype is convenient, even though it may not be the 100% correct place.. -- rgerhards 2008-01-07 */
+void dbgprintf(char *, ...) __attribute__((format(printf, 1, 2)));
+
#endif /* multi-include protection */
/*
* vi:set ai:
diff --git a/syslogd.c b/syslogd.c
index 1df661cd..bb3866f4 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -1254,22 +1254,16 @@ void untty(void)
* changed parameter iSource to bParseHost. For details, see comment in
* printchopped(). rgerhards 2005-10-06
*/
-void printline(char *hname, char *msg, int bParseHost)
+rsRetVal printline(char *hname, char *msg, int bParseHost)
{
+ DEFiRet;
register char *p;
int pri;
msg_t *pMsg;
/* Now it is time to create the message object (rgerhards)
*/
- if((pMsg = MsgConstruct()) == NULL){
- /* rgerhards, 2007-06-21: if we can not get memory, we discard this
- * message but continue to run (in the hope that things improve)
- */
- glblHadMemShortage = 1;
- dbgprintf("Memory shortage in printline(): Could not construct Msg object.\n");
- return;
- }
+ CHKiRet(MsgConstruct(&pMsg));
MsgSetRawMsg(pMsg, msg);
pMsg->bParseHOSTNAME = bParseHost;
@@ -1306,11 +1300,13 @@ void printline(char *hname, char *msg, int bParseHost)
* message. As we like to emulate it, we need to add the hostname
* to it.
*/
- if(MsgSetUxTradMsg(pMsg, p) != 0) return;
+ if(MsgSetUxTradMsg(pMsg, p) != 0)
+ ABORT_FINALIZE(RS_RET_ERR);
logmsg(pri, pMsg, SYNC_FILE);
- return;
+finalize_it:
+ return iRet;
}
@@ -1500,29 +1496,13 @@ void printchopped(char *hname, char *msg, int len, int fd, int bParseHost)
* function here probably is only an interim solution and that we need to
* think on the best way to do this.
*/
-void
+rsRetVal
logmsgInternal(int pri, char *msg, int flags)
{
+ DEFiRet;
msg_t *pMsg;
- if((pMsg = MsgConstruct()) == NULL){
- /* rgerhards 2004-11-09: calling panic might not be the
- * brightest idea - however, it is the best I currently have
- * (think a bit more about this).
- * rgehards, 2007-06-21: I have now thought a bit more about
- * it. If we are so low on memory, there is few we can do. calling
- * panic so far only write a debug line - this is seomthing we keep.
- * Other than that, however, we ignore the error and hope that
- * memory shortage will be resolved while we continue to run. In any
- * case, there is no valid point in aborting the syslogd for this
- * reason - that would be counter-productive. So we ignore the
- * to be logged message.
- */
- glblHadMemShortage = 1;
- dbgprintf("Memory shortage in logmsgInternal: could not construct Msg object.\n");
- return;
- }
-
+ CHKiRet(MsgConstruct(&pMsg));
MsgSetUxTradMsg(pMsg, msg);
MsgSetRawMsg(pMsg, msg);
MsgSetHOSTNAME(pMsg, LocalHostName);
@@ -1541,6 +1521,8 @@ logmsgInternal(int pri, char *msg, int flags)
*/
logmsg(pri, pMsg, flags);
}
+finalize_it:
+ return iRet;
}
/* This functions looks at the given message and checks if it matches the
diff --git a/syslogd.h b/syslogd.h
index 3eb002fc..67f10daf 100644
--- a/syslogd.h
+++ b/syslogd.h
@@ -49,7 +49,6 @@
#define ADDDATE 0x004 /* add a date to the message */
#define MARK 0x008 /* this message is a mark */
-void dbgprintf(char *, ...) __attribute__((format(printf, 1, 2)));
void logerror(char *type);
void logerrorSz(char *type, char *errMsg);
void logerrorInt(char *type, int iErr);
@@ -68,7 +67,7 @@ int getSubString(uchar **ppSrc, char *pDst, size_t DstSize, char cSep);
/* the following prototypes should go away once we have an input
* module interface -- rgerhards, 2007-12-12
*/
-void logmsgInternal(int pri, char *msg, int flags);
+rsRetVal logmsgInternal(int pri, char *msg, int flags);
void logmsg(int pri, msg_t *pMsg, int flags);
extern int glblHadMemShortage; /* indicates if we had memory shortage some time during the run */
extern char LocalHostName[];