diff options
-rw-r--r-- | grammar/rainerscript.c | 50 | ||||
-rw-r--r-- | grammar/rainerscript.h | 3 | ||||
-rw-r--r-- | runtime/lookup.c | 60 | ||||
-rw-r--r-- | runtime/lookup.h | 2 |
4 files changed, 106 insertions, 9 deletions
diff --git a/grammar/rainerscript.c b/grammar/rainerscript.c index e3e7cb32..ef44a410 100644 --- a/grammar/rainerscript.c +++ b/grammar/rainerscript.c @@ -1334,6 +1334,7 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) int bMustFree; es_str_t *estr; char *str; + char *s; uchar *resStr; int retval; struct var r[CNFFUNC_MAX_ARGS]; @@ -1471,6 +1472,20 @@ doFuncCall(struct cnffunc *func, struct var *ret, void* usrptr) ret->d.n = 1; ret->datatype = 'N'; break; + case CNFFUNC_LOOKUP: +dbgprintf("DDDD: executing lookup\n"); + ret->datatype = 'S'; + if(func->funcdata == NULL) { + ret->d.estr = es_newStrFromCStr("TABLE-NOT-FOUND", sizeof("TABLE-NOT-FOUND")-1); + break; + } + cnfexprEval(func->expr[1], &r[1], usrptr); + str = (char*) var2CString(&r[1], &bMustFree); + s = (char*)lookupKey(func->funcdata, (uchar*)str); + ret->d.estr = es_newStrFromCStr(s, strlen(s)); + if(bMustFree) free(str); + if(r[1].datatype == 'S') es_deleteStr(r[1].d.estr); + break; default: if(Debug) { fname = es_str2cstr(func->fname, NULL); @@ -3233,6 +3248,13 @@ funcName2ID(es_str_t *fname, unsigned short nParams) return CNFFUNC_INVALID; } return CNFFUNC_PRIFILT; + } else if(!es_strbufcmp(fname, (unsigned char*)"lookup", sizeof("lookup") - 1)) { + if(nParams != 2) { + parser_errmsg("number of parameters for lookup() must be two " + "but is %d.", nParams); + return CNFFUNC_INVALID; + } + return CNFFUNC_LOOKUP; } else { return CNFFUNC_INVALID; } @@ -3297,6 +3319,31 @@ finalize_it: } +static inline rsRetVal +initFunc_lookup(struct cnffunc *func) +{ + struct funcData_prifilt *pData; + uchar *cstr = NULL; + DEFiRet; + + func->funcdata = NULL; + if(func->expr[0]->nodetype != 'S') { + parser_errmsg("table name (param 1) of lookup() must be a constant string"); + FINALIZE; + } + + cstr = (uchar*)es_str2cstr(((struct cnfstringval*) func->expr[0])->estr, NULL); + if((func->funcdata = lookupFindTable(cstr)) == NULL) { + parser_errmsg("lookup table '%s' not found", cstr); + FINALIZE; + } + +finalize_it: + free(cstr); + RETiRet; +} + + struct cnffunc * cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst) { @@ -3334,6 +3381,9 @@ cnffuncNew(es_str_t *fname, struct cnffparamlst* paramlst) case CNFFUNC_PRIFILT: initFunc_prifilt(func); break; + case CNFFUNC_LOOKUP: + initFunc_lookup(func); + break; default:break; } } diff --git a/grammar/rainerscript.h b/grammar/rainerscript.h index cb8c968f..5c9a05ac 100644 --- a/grammar/rainerscript.h +++ b/grammar/rainerscript.h @@ -232,7 +232,8 @@ enum cnffuncid { CNFFUNC_RE_MATCH, CNFFUNC_RE_EXTRACT, CNFFUNC_FIELD, - CNFFUNC_PRIFILT + CNFFUNC_PRIFILT, + CNFFUNC_LOOKUP }; struct cnffunc { diff --git a/runtime/lookup.c b/runtime/lookup.c index 7ee2eba3..e83f5979 100644 --- a/runtime/lookup.c +++ b/runtime/lookup.c @@ -98,7 +98,7 @@ lookupInitCnf(lookup_tables_t *lu_tabs) } -/* comparison function for qsort() and bsearch() string array compare +/* comparison function for qsort() and string array compare * this is for the string lookup table type */ static int @@ -106,6 +106,14 @@ qs_arrcmp_strtab(const void *s1, const void *s2) { return ustrcmp(((lookup_string_tab_etry_t*)s1)->key, ((lookup_string_tab_etry_t*)s2)->key); } +/* comparison function for bsearch() and string array compare + * this is for the string lookup table type + */ +static int +bs_arrcmp_strtab(const void *s1, const void *s2) +{ + return strcmp((char*)s1, (char*)((lookup_string_tab_etry_t*)s2)->key); +} rsRetVal lookupBuildTable(lookup_t *pThis, struct json_object *jroot) @@ -120,11 +128,6 @@ lookupBuildTable(lookup_t *pThis, struct json_object *jroot) jnomatch = json_object_object_get(jroot, "nomatch"); jtype = json_object_object_get(jroot, "type"); jtab = json_object_object_get(jroot, "table"); -DBGPRINTF("DDDD: version: %d, nomatch %s, type %s, table: '%s'\n", - json_object_get_int(jversion), - json_object_get_string(jnomatch), - json_object_get_string(jtype), - json_object_get_string(jtab)); pThis->nmemb = json_object_array_length(jtab); CHKmalloc(pThis->d.strtab = malloc(pThis->nmemb * sizeof(lookup_string_tab_etry_t))); @@ -142,10 +145,48 @@ DBGPRINTF("DDDD: version: %d, nomatch %s, type %s, table: '%s'\n", dbgprintf("DDDD: table loaded (max size %u):\n", maxStrSize); for(i = 0 ; i < pThis->nmemb ; ++i) dbgprintf("key: '%s', val: '%s'\n", pThis->d.strtab[i].key, pThis->d.strtab[i].val); + finalize_it: RETiRet; } + +/* find a lookup table. This is a naive O(n) algo, but this really + * doesn't matter as it is called only a few times during config + * load. The function returns either a pointer to the requested + * table or NULL, if not found. + */ +lookup_t * +lookupFindTable(uchar *name) +{ + lookup_t *curr; + + for(curr = loadConf->lu_tabs.root ; curr != NULL ; curr = curr->next) { + if(!ustrcmp(curr->name, name)) + break; + } + return curr; +} + + +/* returns either a pointer to the value (read only!) or NULL + * if either the key could not be found or an error occured. + */ +uchar * +lookupKey(lookup_t *pThis, uchar *key) +{ + lookup_string_tab_etry_t *etry; + uchar *r; + etry = bsearch(key, pThis->d.strtab, pThis->nmemb, sizeof(lookup_string_tab_etry_t), bs_arrcmp_strtab); + if(etry == NULL) { + r = (uchar*)""; // TODO: use set default + } else { + r = etry->val; + } + return r; +} + + /* note: widely-deployed json_c 0.9 does NOT support incremental * parsing. In order to keep compatible with e.g. Ubuntu 12.04LTS, * we read the file into one big memory buffer and parse it at once. @@ -157,7 +198,7 @@ rsRetVal lookupReadFile(lookup_t *pThis) { struct json_tokener *tokener = NULL; - struct json_object *json; + struct json_object *json = NULL; int eno = errno; char errStr[1024]; char *iobuf = NULL; @@ -187,7 +228,6 @@ lookupReadFile(lookup_t *pThis) tokener = json_tokener_new(); nread = read(fd, iobuf, sb.st_size); -dbgprintf("DDDD: read buffer of %lld bytes: '%s'\n", (long long) sb.st_size, iobuf); if(nread != (ssize_t) sb.st_size) { eno = errno; errmsg.LogError(0, RS_RET_READ_ERR, @@ -203,6 +243,8 @@ dbgprintf("DDDD: read buffer of %lld bytes: '%s'\n", (long long) sb.st_size, iob pThis->filename); ABORT_FINALIZE(RS_RET_JSON_PARSE_ERR); } + free(iobuf); /* early free to sever resources*/ + iobuf = NULL; /* make sure no double-free */ /* got json object, now populate our own in-memory structure */ CHKiRet(lookupBuildTable(pThis, json)); @@ -211,6 +253,8 @@ finalize_it: free(iobuf); if(tokener != NULL) json_tokener_free(tokener); + if(json != NULL) + json_object_put(json); RETiRet; } diff --git a/runtime/lookup.h b/runtime/lookup.h index 5dd02283..db2737a2 100644 --- a/runtime/lookup.h +++ b/runtime/lookup.h @@ -44,6 +44,8 @@ struct lookup_s { /* prototypes */ void lookupInitCnf(lookup_tables_t *lu_tabs); rsRetVal lookupProcessCnf(struct cnfobj *o); +lookup_t *lookupFindTable(uchar *name); +uchar *lookupKey(lookup_t *pThis, uchar *key); void lookupDestruct(lookup_t *pThis); void lookupClassExit(void); rsRetVal lookupClassInit(void); |