summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2005-10-19 12:23:42 +0000
committerRainer Gerhards <rgerhards@adiscon.com>2005-10-19 12:23:42 +0000
commitbc6d3e81e83de83871b03856d55eb71c6a5a0a4c (patch)
tree86414482a4fa2f44a5c4b92ff1bda7757987d29d
parent8dc836cf04eaf061fb4ee31bcc771e2297f7630b (diff)
downloadrsyslog-bc6d3e81e83de83871b03856d55eb71c6a5a0a4c.tar.gz
rsyslog-bc6d3e81e83de83871b03856d55eb71c6a5a0a4c.tar.xz
rsyslog-bc6d3e81e83de83871b03856d55eb71c6a5a0a4c.zip
made "!progname" fully BSD-compliant; added property "programname"
-rw-r--r--NEWS5
-rw-r--r--doc/property_replacer.html4
-rw-r--r--rsyslog.h1
-rwxr-xr-xstringbuf.c19
-rwxr-xr-xstringbuf.h1
-rw-r--r--syslogd.c115
6 files changed, 111 insertions, 34 deletions
diff --git a/NEWS b/NEWS
index 693f42d2..7bcc02f5 100644
--- a/NEWS
+++ b/NEWS
@@ -5,9 +5,8 @@ Version 1.11.1 (RGer), 2005-10-13
- added ability to specify listen port for rfc3195d
- changed more functions to "static" storage class to help compiler
optimize (should have been static in the first place...)
-- support for BSD-style program and host blocks ("program" actually
- is tag and probably has slightly different semantics than in BSD
- syslogd - but that should be easy to deal with)
+- support for BSD-style program name and host blocks
+- added a new property "programname" that can be used in templates
- fixed a potential memory leak in the string buffer class destructor.
As the destructur was previously never called, the leak did not actually
appear.
diff --git a/doc/property_replacer.html b/doc/property_replacer.html
index 6bc00fe1..f4c6bd64 100644
--- a/doc/property_replacer.html
+++ b/doc/property_replacer.html
@@ -27,6 +27,8 @@ socket. Should be useful for debugging.</td></tr>
from (in a relay chain, this is the system immediately in front of us and
not necessarily the original sender)</td></tr>
<tr><td><b>syslogtag</b></td><td>TAG from the message</td></tr>
+<tr><td><b>programname</b></td><td>the &quot;static&quot; part of the tag, as defined by
+BSD syslogd. For example, when TAG is "named[12345]", programname is "named".</td></tr>
<tr><td><b>PRI</b></td><td>PRI part of the message - undecoded (single value)</td></tr>
<tr><td><b>IUT</b></td><td>the monitorware InfoUnitType - used when talking
to a <a href="http://www.monitorware.com">MonitorWare</a> backend (also for
@@ -73,4 +75,4 @@ are defined:</p>
</table>
</body>
-</html> \ No newline at end of file
+</html>
diff --git a/rsyslog.h b/rsyslog.h
index 339cf8ae..36ab14e4 100644
--- a/rsyslog.h
+++ b/rsyslog.h
@@ -38,6 +38,7 @@ enum rsRetVal_ /** return value. All methods return this if not specified oth
RS_RET_NO_DIGIT = -3005, /**< an digit was expected, but none found (mostly parsing) */
RS_RET_NO_MORE_DATA = -3006, /**< insufficient data, e.g. end of string during parsing */
RS_RET_INVALID_IP = -3007, /**< invalid ip found where valid was expected */
+ RS_RET_OBJ_CREATION_FAILED = - 3008, /**< the creation of an object failed (no details available) */
RS_RET_OK = 0 /**< operation successful */
};
typedef enum rsRetVal_ rsRetVal; /**< friendly type for global return value */
diff --git a/stringbuf.c b/stringbuf.c
index ea008e77..5aa94fc4 100755
--- a/stringbuf.c
+++ b/stringbuf.c
@@ -236,10 +236,29 @@ rsRetVal rsCStrSetSzStr(rsCStrObj *pThis, char *pszNew)
return RS_RET_OK;
}
+/* Converts the CStr object to a classical sz string and returns that.
+ * Same restrictions as in rsCStrGetSzStr() applies (see there!). This
+ * function here guarantees that a valid string is returned, even if
+ * the CStr object currently holds a NULL pointer string buffer. If so,
+ * "" is returned.
+ * rgerhards 2005-10-19
+ */
+char* rsCStrGetSzStrNoNULL(rsCStrObj *pThis)
+{
+ rsCHECKVALIDOBJECT(pThis, OIDrsCStr);
+ if(pThis->pBuf == NULL)
+ return "";
+ else
+ return rsCStrGetSzStr(pThis);
+}
+
/* Converts the CStr object to a classical zero-terminated C string
* and returns that string. The caller must not free it and must not
* destroy the CStr object as long as the ascii string is used.
+ * This function may return NULL, if the string is currently NULL. This
+ * is a feature, not a bug. If you need non-NULL in any case, use
+ * rsCStrGetSzStrNoNULL() instead.
* rgerhards, 2005-09-15
*/
char* rsCStrGetSzStr(rsCStrObj *pThis)
diff --git a/stringbuf.h b/stringbuf.h
index 3b039358..c8359ab8 100755
--- a/stringbuf.h
+++ b/stringbuf.h
@@ -102,6 +102,7 @@ rsRetVal rsCStrAppendInt(rsCStrObj *pThis, int i);
char* rsCStrGetSzStr(rsCStrObj *pThis);
+char* rsCStrGetSzStrNoNULL(rsCStrObj *pThis);
rsRetVal rsCStrSetSzStr(rsCStrObj *pThis, char *pszNew);
char* rsCStrConvSzStrAndDestruct(rsCStrObj *pThis);
int rsCStrCStrCmp(rsCStrObj *pCS1, rsCStrObj *pCS2);
diff --git a/syslogd.c b/syslogd.c
index 38f94013..27b394d5 100644
--- a/syslogd.c
+++ b/syslogd.c
@@ -494,7 +494,7 @@ struct filed {
} f_filter_type;
EHostnameCmpMode eHostnameCmpMode;
rsCStrObj *pCSHostnameComp;/* hostname to check */
- rsCStrObj *pCSTagComp; /* tag to check or NULL, if not to be checked */
+ rsCStrObj *pCSProgNameComp; /* tag to check or NULL, if not to be checked */
union {
u_char f_pmask[LOG_NFACILITIES+1]; /* priority mask */
struct {
@@ -558,7 +558,7 @@ struct filed {
*/
static EHostnameCmpMode eDfltHostnameCmpMode;
static rsCStrObj *pDfltHostnameCmp;
-static rsCStrObj *pDfltTagCmp;
+static rsCStrObj *pDfltProgNameCmp;
/*
* Intervals at which we flush out "message repeated" messages,
@@ -2118,9 +2118,9 @@ static char *getRcvFrom(struct msg *pM)
}
-/* get the "programname". Programname is a BSD concept, it is the tag
- * without any instance-specific information. Precisely, the programname
- * is terminated by either (whichever occurs first):
+/* Parse and set the "programname" for a given MSG object. Programname
+ * is a BSD concept, it is the tag without any instance-specific information.
+ * Precisely, the programname is terminated by either (whichever occurs first):
* - end of tag
* - nonprintable character
* - ':'
@@ -2129,17 +2129,70 @@ static char *getRcvFrom(struct msg *pM)
* The above definition has been taken from the FreeBSD syslogd sources.
*
* The program name is not parsed by default, because it is infrequently-used.
- * Thus, this function first checks if it already exists. If not, it is generated
- * before being returned. A message must be provided, else a crash will occur.
+ * If it is needed, this function should be called first. It checks if it is
+ * already set and extracts it, if not.
+ * A message object must be provided, else a crash will occur.
* rgerhards, 2005-10-19
*/
-static char *getProgramName(struct msg *pM)
+static rsRetVal aquireProgramName(struct msg *pM)
{
+ register int i;
+ int iRet;
+
assert(pM != NULL);
if(pM->pCSProgName == NULL) {
- } else {
- return pM->pszHOSTNAME;
+ /* ok, we do not yet have it. So let's parse the TAG
+ * to obtain it.
+ */
+ if((pM->pCSProgName = rsCStrConstruct()) == NULL)
+ return RS_RET_OBJ_CREATION_FAILED; /* best we can do... */
+ rsCStrSetAllocIncrement(pM->pCSProgName, 33);
+ for( i = 0
+ ; (i < pM->iLenTAG) && isprint(pM->pszTAG[i])
+ && (pM->pszTAG[i] != '\0') && (pM->pszTAG[i] != ':')
+ && (pM->pszTAG[i] != '[') && (pM->pszTAG[i] != '/')
+ ; ++i) {
+ if((iRet = rsCStrAppendChar(pM->pCSProgName, pM->pszTAG[i])) != RS_RET_OK)
+ return iRet;
+ }
+ if((iRet = rsCStrFinish(pM->pCSProgName)) != RS_RET_OK)
+ return iRet;
}
+ return RS_RET_OK;
+}
+
+
+/* get the length of the "programname" sz string
+ * rgerhards, 2005-10-19
+ */
+static int getProgramNameLen(struct msg *pM)
+{
+ int iRet;
+
+ assert(pM != NULL);
+ if((iRet = aquireProgramName(pM)) != RS_RET_OK) {
+ dprintf("error %d returned by aquireProgramName() in getProgramNameLen()\n", iRet);
+ return 0; /* best we can do (consistent wiht what getProgramName() returns) */
+ }
+
+ return (pM->pCSProgName == NULL) ? 0 : rsCStrLen(pM->pCSProgName);
+}
+
+
+/* get the "programname" as sz string
+ * rgerhards, 2005-10-19
+ */
+static char *getProgramName(struct msg *pM)
+{
+ int iRet;
+
+ assert(pM != NULL);
+ if((iRet = aquireProgramName(pM)) != RS_RET_OK) {
+ dprintf("error %d returned by aquireProgramName() in getProgramName()\n", iRet);
+ return ""; /* best we can do */
+ }
+
+ return (pM->pCSProgName == NULL) ? "" : rsCStrGetSzStrNoNULL(pM->pCSProgName);
}
@@ -2403,6 +2456,8 @@ static char *MsgGetProp(struct msg *pMsg, struct templateEntry *pTpe,
} else if(!strcmp(pName, "timereported")
|| !strcmp(pName, "TIMESTAMP")) {
pRes = getTimeReported(pMsg, pTpe->data.field.eDateFormat);
+ } else if(!strcmp(pName, "programname")) {
+ pRes = getProgramName(pMsg);
} else {
pRes = "**INVALID PROPERTY NAME**";
}
@@ -3618,11 +3673,11 @@ int shouldProcessThisMessage(struct filed *f, struct msg *pMsg)
}
}
- if(f->pCSTagComp != NULL) {
- if(rsCStrSzStrCmp(f->pCSTagComp, getTAG(pMsg), getTAGLen(pMsg))) {
+ if(f->pCSProgNameComp != NULL) {
+ if(rsCStrSzStrCmp(f->pCSProgNameComp, getProgramName(pMsg), getProgramNameLen(pMsg))) {
/* not equal, so we are already done... */
- dprintf("tag filter '%s' does not match '%s'\n",
- rsCStrGetSzStr(f->pCSTagComp), getTAG(pMsg));
+ dprintf("programname filter '%s' does not match '%s'\n",
+ rsCStrGetSzStr(f->pCSProgNameComp), getProgramName(pMsg));
return 0;
}
}
@@ -5207,7 +5262,7 @@ static void init()
/* initialize some static variables */
pDfltHostnameCmp = NULL;
- pDfltTagCmp = NULL;
+ pDfltProgNameCmp = NULL;
eDfltHostnameCmpMode = HN_NO_COMP;
nextp = NULL;
@@ -5373,9 +5428,9 @@ static void init()
pDfltHostnameCmp = NULL;
}
- if(pDfltTagCmp != NULL) {
- rsCStrDestruct(pDfltTagCmp);
- pDfltTagCmp = NULL;
+ if(pDfltProgNameCmp != NULL) {
+ rsCStrDestruct(pDfltProgNameCmp);
+ pDfltProgNameCmp = NULL;
}
@@ -5425,8 +5480,8 @@ static void init()
printf("Active selectors:\n");
for (f = Files; f; f = f->f_next) {
if (f->f_type != F_UNUSED) {
- if(f->pCSTagComp != NULL)
- printf("tag: '%s'\n", rsCStrGetSzStr(f->pCSTagComp));
+ if(f->pCSProgNameComp != NULL)
+ printf("tag: '%s'\n", rsCStrGetSzStr(f->pCSProgNameComp));
if(f->eHostnameCmpMode != HN_NO_COMP)
printf("hostname: %s '%s'\n",
f->eHostnameCmpMode == HN_COMP_MATCH ?
@@ -6059,20 +6114,20 @@ static rsRetVal cflineProcessTagSelector(char **pline, register struct filed *f)
* Order of conditions in the if-statement is vital! rgerhards 2005-10-18
*/
if(**pline != '\0' && **pline == '*' && *(*pline+1) == '\0') {
- dprintf("resetting tag filter\n");
- if(pDfltTagCmp != NULL) {
- if((iRet = rsCStrSetSzStr(pDfltTagCmp, NULL)) != RS_RET_OK)
+ dprintf("resetting programname filter\n");
+ if(pDfltProgNameCmp != NULL) {
+ if((iRet = rsCStrSetSzStr(pDfltProgNameCmp, NULL)) != RS_RET_OK)
return(iRet);
- pDfltTagCmp = NULL;
+ pDfltProgNameCmp = NULL;
}
} else {
- dprintf("setting tag filter to '%s'\n", *pline);
- if(pDfltTagCmp == NULL) {
+ dprintf("setting programname filter to '%s'\n", *pline);
+ if(pDfltProgNameCmp == NULL) {
/* create string for parser */
- if((iRet = rsCStrConstructFromszStr(&pDfltTagCmp, *pline)) != RS_RET_OK)
+ if((iRet = rsCStrConstructFromszStr(&pDfltProgNameCmp, *pline)) != RS_RET_OK)
return(iRet);
} else { /* string objects exists, just update... */
- if((iRet = rsCStrSetSzStr(pDfltTagCmp, *pline)) != RS_RET_OK)
+ if((iRet = rsCStrSetSzStr(pDfltProgNameCmp, *pline)) != RS_RET_OK)
return(iRet);
}
}
@@ -6138,8 +6193,8 @@ static rsRetVal cfline(char *line, register struct filed *f)
/* we now check if there are some global (BSD-style) filter conditions
* and, if so, we copy them over. rgerhards, 2005-10-18
*/
- if(pDfltTagCmp != NULL)
- if((iRet = rsCStrConstructFromCStr(&(f->pCSTagComp), pDfltTagCmp)) != RS_RET_OK)
+ if(pDfltProgNameCmp != NULL)
+ if((iRet = rsCStrConstructFromCStr(&(f->pCSProgNameComp), pDfltProgNameCmp)) != RS_RET_OK)
return(iRet);
if(eDfltHostnameCmpMode != HN_NO_COMP) {