summaryrefslogtreecommitdiffstats
path: root/grammar
diff options
context:
space:
mode:
authorRainer Gerhards <rgerhards@adiscon.com>2011-07-19 09:31:17 +0200
committerRainer Gerhards <rgerhards@adiscon.com>2011-07-19 09:31:17 +0200
commit127d61fea78c967d2cdc536f898da425ffdd8a11 (patch)
treef0f72c30d774657b9ee81174a4a0701e87216de9 /grammar
parent63d357862051fd8fea4e26bd424bdfc0e837a158 (diff)
downloadrsyslog-127d61fea78c967d2cdc536f898da425ffdd8a11.tar.gz
rsyslog-127d61fea78c967d2cdc536f898da425ffdd8a11.tar.xz
rsyslog-127d61fea78c967d2cdc536f898da425ffdd8a11.zip
milestone: first steps at global() conf obj implementation
also, the foundation for accessing conf file params has been laid. Still more work to do...
Diffstat (limited to 'grammar')
-rw-r--r--grammar/Makefile.am2
-rw-r--r--grammar/rainerscript.c139
-rw-r--r--grammar/rainerscript.h43
3 files changed, 184 insertions, 0 deletions
diff --git a/grammar/Makefile.am b/grammar/Makefile.am
index 9767c12f..4746a9de 100644
--- a/grammar/Makefile.am
+++ b/grammar/Makefile.am
@@ -11,7 +11,9 @@ libgrammar_la_SOURCES = \
rainerscript.h \
parserif.h \
grammar.h
+libgrammar_la_CPPFLAGS = $(RSRT_CFLAGS)
testdriver_SOURCES = testdriver.c libgrammar.la
+testdriver_CPPFLAGS = $(RSRT_CFLAGS)
testdriver_LDADD = libgrammar.la
testdriver_LDFLAGS = -lestr
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c
index 16140a3f..754910da 100644
--- a/grammar/rainerscript.c
+++ b/grammar/rainerscript.c
@@ -97,6 +97,7 @@ nvlstNew(es_str_t *name, es_str_t *value)
lst->name = name;
lst->val.datatype = 'S';
lst->val.d.estr = value;
+ lst->bUsed = 0;
}
return lst;
@@ -145,6 +146,18 @@ nvlstFindName(struct nvlst *lst, es_str_t *name)
}
+/* find a name starting at node lst. SAme as nvlstFindName, but
+ * for classical C strings. This is useful because the config system
+ * uses C string constants.
+ */
+static inline struct nvlst*
+nvlstFindNameCStr(struct nvlst *lst, char *name)
+{
+ while(lst != NULL && es_strbufcmp(lst->name, (uchar*)name, strlen(name)))
+ lst = lst->next;
+ return lst;
+}
+
/* check if there are duplicate names inside a nvlst and emit
* an error message, if so.
*/
@@ -167,6 +180,113 @@ nvlstChkDupes(struct nvlst *lst)
}
+/* check for unused params and emit error message is found. This must
+ * be called after all config params have been pulled from the object
+ * (otherwise the flags are not correctly set).
+ */
+void
+nvlstChkUnused(struct nvlst *lst)
+{
+ char *cstr;
+
+ while(lst != NULL) {
+ if(!lst->bUsed) {
+ cstr = es_str2cstr(lst->name, NULL);
+ parser_errmsg("parameter '%s' not known -- "
+ "typo in config file?",
+ cstr);
+ free(cstr);
+ }
+ lst = lst->next;
+ }
+}
+
+
+/* get a single parameter according to its definition. Helper to
+ * nvlstGetParams.
+ */
+static inline void
+nvlstGetParam(struct nvlst *valnode, struct cnfparamdescr *param,
+ struct cnfparamvals *vals)
+{
+ dbgprintf("XXXX: in nvlstGetParam, name '%s', type %d\n",
+ param->name, (int) param->type);
+ switch(param->type) {
+ case eCmdHdlrUID:
+ break;
+ case eCmdHdlrGID:
+ break;
+ case eCmdHdlrBinary:
+ break;
+ case eCmdHdlrFileCreateMode:
+ break;
+ case eCmdHdlrInt:
+ break;
+ case eCmdHdlrSize:
+ break;
+ case eCmdHdlrGetChar:
+ break;
+ case eCmdHdlrFacility:
+ break;
+ case eCmdHdlrSeverity:
+ break;
+ case eCmdHdlrGetWord:
+ break;
+ case eCmdHdlrString:
+ break;
+ case eCmdHdlrGoneAway:
+ parser_errmsg("parameter '%s' is no longer supported",
+ param->name);
+ break;
+ default:
+ dbgprintf("error: invalid param type\n");
+ break;
+ }
+}
+
+
+/* obtain conf params from an nvlst and emit error messages if
+ * necessary. If an already-existing param value is passed, that is
+ * used. If NULL is passed instead, a new one is allocated. In that case,
+ * it is the caller's duty to free it when no longer needed.
+ * NULL is returned on error, otherwise a pointer to the vals array.
+ */
+struct cnfparamvals*
+nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
+ struct cnfparamvals *vals)
+{
+ int i;
+ struct nvlst *valnode;
+ struct cnfparamdescr *param;
+
+ if(params->version != CNFPARAMBLK_VERSION) {
+ dbgprintf("nvlstGetParams: invalid param block version "
+ "%d, expected %d\n",
+ params->version, CNFPARAMBLK_VERSION);
+ return NULL;
+ }
+
+ if(vals == NULL) {
+ if((vals = malloc(params->nParams *
+ sizeof(struct cnfparamvals))) == NULL)
+ return NULL;
+ }
+
+ for(i = 0 ; i < params->nParams ; ++i) {
+ param = params->descr + i;
+ if((valnode = nvlstFindNameCStr(lst, param->name)) == NULL)
+ continue;
+ if(vals[i].bUsed) {
+ parser_errmsg("parameter '%s' specified more than once - "
+ "one instance is ignored. Fix config", param->name);
+ continue;
+ }
+ nvlstGetParam(lst, param, vals + i);
+ }
+ return vals;
+}
+
+
struct cnfobj*
cnfobjNew(enum cnfobjType objType, struct nvlst *lst)
{
@@ -1140,6 +1260,25 @@ cnfDoInclude(char *name)
return 0;
}
+/* find the index (or -1!) for a config param by name. This is used to
+ * address the parameter array. Of course, we could use with static
+ * indices, but that would create some extra bug potential. So we
+ * resort to names. As we do this only during the initial config parsing
+ * stage the (considerable!) extra overhead is OK. -- rgerhards, 2011-07-19
+ */
+int
+cnfparamGetIdx(struct cnfparamblk *params, char *name)
+{
+ int i;
+ for(i = 0 ; i < params->nParams ; ++i)
+ if(!strcmp(params->descr[i].name, name))
+ break;
+ if(i == params->nParams)
+ i = -1; /* not found */
+ return i;
+}
+
+
void
cstrPrint(char *text, es_str_t *estr)
{
diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h
index 2c4d764f..1dc5719d 100644
--- a/grammar/rainerscript.h
+++ b/grammar/rainerscript.h
@@ -2,6 +2,7 @@
#define INC_UTILS_H
#include <stdio.h>
#include <libestr.h>
+#include <typedefs.h>
#define CNFFUNC_MAX_ARGS 32
/**< maximum number of arguments that any function can have (among
@@ -65,6 +66,11 @@ struct nvlst {
struct nvlst *next;
es_str_t *name;
struct var val;
+ unsigned char *bUsed;
+ /**< was this node used during config processing? If not, this
+ * indicates an error. After all, the user specified a setting
+ * that the software does not know.
+ */
};
struct cnfcfsyslinelst {
@@ -172,6 +178,40 @@ struct x {
};
*/
+
+/* the following defines describe the parameter block for puling
+ * config parameters. Note that the focus is on ease and saveness of
+ * use, not performance. For example, we address parameters by name
+ * instead of index, because the former is less error-prone. The (severe)
+ * performance hit does not matter, as it is a one-time hit during config
+ * load but never during actual processing. So there is really no reason
+ * to care.
+ */
+struct cnfparamdescr { /* first the param description */
+ char *name; /**< not a es_str_t to ease definition in code */
+ ecslCmdHdrlType type;
+ unsigned flags;
+};
+/* flags for cnfparamdescr: */
+#define CNFPARAM_REQUIRED 0x0001
+
+struct cnfparamblk { /* now the actual param block use in API calls */
+ unsigned short version;
+ unsigned short nParams;
+ struct cnfparamdescr *descr;
+};
+#define CNFPARAMBLK_VERSION 1
+ /**< caller must have same version as engine -- else things may
+ * be messed up. But note that we may support multiple versions
+ * inside the engine, if at some later stage we want to do
+ * that. -- rgerhards, 2011-07-15
+ */
+struct cnfparamvals { /* the values we obtained for param descr. */
+ struct var val;
+ unsigned char bUsed;
+};
+
+
int cnfParseBuffer(char *buf, unsigned lenBuf);
void readConfFile(FILE *fp, es_str_t **str);
struct nvlst* nvlstNew(es_str_t *name, es_str_t *value);
@@ -198,6 +238,9 @@ struct cnfvar* cnfvarNew(char *name);
struct cnffunc * cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst);
struct cnffparamlst * cnffparamlstNew(struct cnfexpr *expr, struct cnffparamlst *next);
int cnfDoInclude(char *name);
+int cnfparamGetIdx(struct cnfparamblk *params, char *name);
+struct cnfparamvals* nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
+ struct cnfparamvals *vals);
/* debug helper */
void cstrPrint(char *text, es_str_t *estr);