rsyslog/grammar/rainerscript.h
Rainer Gerhards 6327e43ea9 config: add include() script object
This permits to include files (like legacy $IncludeConfig) via a
script object. Needless to say, the script object offers more
features:

- include files can now be
  - required, with rsyslog aborting when not present
  - required, with rsyslog emitting an error message but otherwise
    continuing when not present
  - optional, which means non-present include files will be
    skipped without notice
  This is controlled by the "mode" parameter.
- text can be included form e.g. an environment variable
  --> ex: include(text=`echo $ENVVAR`)

This finally really obsoletes $IncludeConfig.

closes https://github.com/rsyslog/rsyslog/issues/2151
2018-01-22 18:36:03 +01:00

377 lines
11 KiB
C

/* rsyslog rainerscript definitions
*
* Copyright 2011-2018 Rainer Gerhards
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
* -or-
* see COPYING.ASL20 in the source distribution
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
#ifndef INC_UTILS_H
#define INC_UTILS_H
#include <stdio.h>
#include <libestr.h>
#include <typedefs.h>
#include <sys/types.h>
#include <json.h>
#include <regex.h>
#include "typedefs.h"
#define LOG_NFACILITIES 24+1 /* we copy&paste this as including rsyslog.h gets us in off64_t trouble... :-( */
#define CNFFUNC_MAX_ARGS 32
/**< maximum number of arguments that any function can have (among
* others, this is used to size data structures).
*/
enum cnfobjType {
CNFOBJ_ACTION,
CNFOBJ_RULESET,
CNFOBJ_GLOBAL,
CNFOBJ_INPUT,
CNFOBJ_MODULE,
CNFOBJ_TPL,
CNFOBJ_PROPERTY,
CNFOBJ_CONSTANT,
CNFOBJ_MAINQ,
CNFOBJ_LOOKUP_TABLE,
CNFOBJ_PARSER,
CNFOBJ_TIMEZONE,
CNFOBJ_DYN_STATS,
CNFOBJ_INVALID = 0
};
const char* cnfobjType2str(enum cnfobjType ot);
/* a variant type, for example used for expression evaluation
* 2011-07-15/rger: note that there exists a "legacy" object var,
* which implements the same idea, but in a suboptimal manner. I have
* stipped this down as much as possible, but will keep it for a while
* to avoid unnecessary complexity during development. TODO: in the long
* term, var shall be replaced by struct svar.
*/
struct svar{
union {
es_str_t *estr;
struct cnfarray *ar;
long long n;
struct json_object *json;
} d;
char datatype; /* 'N' number, 'S' string, 'J' JSON, 'A' array
* Note: 'A' is only supported during config phase
*/
};
struct cnfobj {
enum cnfobjType objType;
struct nvlst *nvlst;
struct objlst *subobjs;
struct cnfstmt *script;
};
struct objlst {
struct objlst *next;
struct cnfobj *obj;
};
struct nvlst {
struct nvlst *next;
es_str_t *name;
struct svar 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.
*/
};
/* the following structures support expressions, and may (very much later
* be the sole foundation for the AST.
*
* nodetypes (list not yet complete)
* F - function
* N - number
* P - fparamlst
* R - rule
* S - string
* V - var
* A - (string) array
* ... plus the S_* #define's below:
*/
#define S_STOP 4000
#define S_PRIFILT 4001
#define S_PROPFILT 4002
#define S_IF 4003
#define S_ACT 4004
#define S_NOP 4005 /* usually used to disable some statement */
#define S_SET 4006
#define S_UNSET 4007
#define S_CALL 4008
#define S_FOREACH 4009
#define S_RELOAD_LOOKUP_TABLE 4010
#define S_CALL_INDIRECT 4011
enum cnfFiltType { CNFFILT_NONE, CNFFILT_PRI, CNFFILT_PROP, CNFFILT_SCRIPT };
const char* cnfFiltType2str(const enum cnfFiltType filttype);
struct cnfstmt {
unsigned nodetype;
struct cnfstmt *next;
uchar *printable; /* printable text for debugging */
union {
struct {
struct cnfexpr *expr;
struct cnfstmt *t_then;
struct cnfstmt *t_else;
} s_if;
struct {
uchar *varname;
struct cnfexpr *expr;
int force_reset;
} s_set;
struct {
uchar *varname;
} s_unset;
struct {
es_str_t *name;
struct cnfstmt *stmt;
ruleset_t *ruleset; /* non-NULL if the ruleset has a queue assigned */
} s_call;
struct {
struct cnfexpr *expr;
} s_call_ind;
struct {
uchar pmask[LOG_NFACILITIES+1]; /* priority mask */
struct cnfstmt *t_then;
struct cnfstmt *t_else;
} s_prifilt;
struct {
fiop_t operation;
regex_t *regex_cache;/* cache for compiled REs, if used */
struct cstr_s *pCSCompValue;/* value to "compare" against */
sbool isNegated;
msgPropDescr_t prop; /* requested property */
struct cnfstmt *t_then;
struct cnfstmt *t_else;
} s_propfilt;
struct action_s *act;
struct {
struct cnfitr *iter;
struct cnfstmt *body;
} s_foreach;
struct {
lookup_ref_t *table;
uchar *table_name;
uchar *stub_value;
} s_reload_lookup_table;
} d;
};
struct cnfexpr {
unsigned nodetype;
struct cnfexpr *l;
struct cnfexpr *r;
} __attribute__((aligned (8)));
struct cnfitr {
char* var;
struct cnfexpr* collection;
} __attribute__((aligned (8)));
struct cnfnumval {
unsigned nodetype;
long long val;
} __attribute__((aligned (8)));
struct cnfstringval {
unsigned nodetype;
es_str_t *estr;
} __attribute__((aligned (8)));
struct cnfvar {
unsigned nodetype;
char *name;
msgPropDescr_t prop;
} __attribute__((aligned (8)));
struct cnfarray {
unsigned nodetype;
int nmemb;
es_str_t **arr;
} __attribute__((aligned (8)));
struct cnffparamlst {
unsigned nodetype; /* P */
struct cnffparamlst *next;
struct cnfexpr *expr;
} __attribute__((aligned (8)));
enum cnffuncid {
CNFFUNC_INVALID = 0, /**< defunct entry, do not use (should normally not be present) */
CNFFUNC_NAME = 1, /**< use name to call function (for future use) */
CNFFUNC_STRLEN,
CNFFUNC_SUBSTRING,
CNFFUNC_GETENV,
CNFFUNC_TOLOWER,
CNFFUNC_CSTR,
CNFFUNC_CNUM,
CNFFUNC_RE_MATCH,
CNFFUNC_RE_EXTRACT,
CNFFUNC_FIELD,
CNFFUNC_PRIFILT,
CNFFUNC_LOOKUP,
CNFFUNC_EXEC_TEMPLATE,
CNFFUNC_REPLACE,
CNFFUNC_WRAP,
CNFFUNC_RANDOM,
CNFFUNC_DYN_INC,
CNFFUNC_IPV42NUM,
CNFFUNC_NUM2IPV4,
CNFFUNC_INT2HEX,
CNFFUNC_LTRIM,
CNFFUNC_RTRIM,
CNFFUNC_FORMAT_TIME,
CNFFUNC_PARSE_TIME,
CNFFUNC_PARSE_JSON,
CNFFUNC_PREVIOUS_ACTION_SUSPENDED,
CNFFUNC_SCRIPT_ERROR,
CNFFUNC_HTTP_REQUEST,
CNFFUNC_IS_TIME
};
struct cnffunc {
unsigned nodetype;
es_str_t *fname;
unsigned short nParams;
enum cnffuncid fID; /* function ID for built-ins, 0 means use name */
void *funcdata; /* global data for function-specific use (e.g. compiled regex) */
uint8_t destructable_funcdata;
struct cnfexpr *expr[];
} __attribute__((aligned (8)));
/* future extensions
struct x {
int nodetype;
};
*/
/* 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 */
const char *name;/**< not a es_str_t to ease definition in code */
ecslCmdHdrlType type;
unsigned flags;
};
/* flags for cnfparamdescr: */
#define CNFPARAM_REQUIRED 0x0001
#define CNFPARAM_DEPRECATED 0x0002
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 svar val;
unsigned char bUsed;
};
struct funcData_prifilt {
uchar pmask[LOG_NFACILITIES+1]; /* priority mask */
};
/* script errno-like interface error codes: */
#define RS_SCRIPT_EOK 0
#define RS_SCRIPT_EINVAL 1
int cnfParseBuffer(char *buf, unsigned lenBuf);
void readConfFile(FILE *fp, es_str_t **str);
struct objlst* objlstNew(struct cnfobj *obj);
void objlstDestruct(struct objlst *lst);
void objlstPrint(struct objlst *lst);
struct nvlst* nvlstNewArray(struct cnfarray *ar);
struct nvlst* nvlstNewStr(es_str_t *value);
struct nvlst* nvlstNewStrBackticks(es_str_t *const value);
struct nvlst* nvlstSetName(struct nvlst *lst, es_str_t *name);
void nvlstDestruct(struct nvlst *lst);
void nvlstPrint(struct nvlst *lst);
void nvlstChkUnused(struct nvlst *lst);
struct nvlst* nvlstFindName(struct nvlst *lst, es_str_t *name);
struct cnfobj* cnfobjNew(enum cnfobjType objType, struct nvlst *lst);
void cnfobjDestruct(struct cnfobj *o);
void cnfobjPrint(struct cnfobj *o);
struct cnfexpr* cnfexprNew(unsigned nodetype, struct cnfexpr *l, struct cnfexpr *r);
void cnfexprPrint(struct cnfexpr *expr, int indent);
void cnfexprEval(const struct cnfexpr *const expr, struct svar *ret, void *pusr, wti_t *pWti);
int cnfexprEvalBool(struct cnfexpr *expr, void *usrptr, wti_t *pWti);
struct json_object* cnfexprEvalCollection(struct cnfexpr * const expr, void * const usrptr, wti_t *pWti);
void cnfexprDestruct(struct cnfexpr *expr);
struct cnfnumval* cnfnumvalNew(long long val);
struct cnfstringval* cnfstringvalNew(es_str_t *estr);
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(const char *name, const int optional);
int cnfparamGetIdx(struct cnfparamblk *params, const char *name);
struct cnfparamvals* nvlstGetParams(struct nvlst *lst, struct cnfparamblk *params,
struct cnfparamvals *vals);
void cnfparamsPrint(const struct cnfparamblk *params, const struct cnfparamvals *vals);
int cnfparamvalsIsSet(struct cnfparamblk *params, struct cnfparamvals *vals);
void varDelete(const struct svar *v);
void cnfparamvalsDestruct(const struct cnfparamvals *paramvals, const struct cnfparamblk *blk);
struct cnfstmt * cnfstmtNew(unsigned s_type);
struct cnfitr * cnfNewIterator(char *var, struct cnfexpr *collection);
void cnfstmtPrintOnly(struct cnfstmt *stmt, int indent, sbool subtree);
void cnfstmtPrint(struct cnfstmt *stmt, int indent);
struct cnfstmt* scriptAddStmt(struct cnfstmt *root, struct cnfstmt *s);
struct objlst* objlstAdd(struct objlst *root, struct cnfobj *o);
char *rmLeadingSpace(char *s);
struct cnfstmt * cnfstmtNewPRIFILT(char *prifilt, struct cnfstmt *t_then);
struct cnfstmt * cnfstmtNewPROPFILT(char *propfilt, struct cnfstmt *t_then);
struct cnfstmt * cnfstmtNewAct(struct nvlst *lst);
struct cnfstmt * cnfstmtNewLegaAct(char *actline);
struct cnfstmt * cnfstmtNewSet(char *var, struct cnfexpr *expr, int force_reset);
struct cnfstmt * cnfstmtNewUnset(char *var);
struct cnfstmt * cnfstmtNewCall(es_str_t *name);
struct cnfstmt * cnfstmtNewContinue(void);
struct cnfstmt * cnfstmtNewReloadLookupTable(struct cnffparamlst *fparams);
void cnfstmtDestructLst(struct cnfstmt *root);
void cnfstmtOptimize(struct cnfstmt *root);
struct cnfarray* cnfarrayNew(es_str_t *val);
struct cnfarray* cnfarrayDup(struct cnfarray *old);
struct cnfarray* cnfarrayAdd(struct cnfarray *ar, es_str_t *val);
void cnfarrayContentDestruct(struct cnfarray *ar);
const char* getFIOPName(unsigned iFIOP);
rsRetVal initRainerscript(void);
void unescapeStr(uchar *s, int len);
const char * tokenval2str(int tok);
uchar* var2CString(struct svar *__restrict__ const r, int *__restrict__ const bMustFree);
void includeProcessCnf(struct nvlst *const lst);
/* debug helper */
void cstrPrint(const char *text, es_str_t *estr);
#endif