Skip to content

Commit d1bca11

Browse files
committed
Add two pieces of related functionality. The first is a plugin manager so we don't need to be repeating the same code in all our programs that use plugins (e.g., adcs, libpolydrivers, satnet). The related functionality is deferred parsing of configuration files so we can only load the modules we need, and not just load them all to get access to the configuration objects.
1 parent 482cb9d commit d1bca11

18 files changed

+766
-42
lines changed

Makefile

+2-2
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,13 @@ include Make.rules.$(PLAT)
55
include Make.rules.arm
66

77
# Input/Output Variables
8-
SOURCES=priorityQueue.c events.c proclib.c ipc.c debug.c cmd.c config.c hashtable.c util.c md5.c critical.c eventTimer.c telm_dict.c zmqlite.c json.c cmd-pkt.c xdr.c
8+
SOURCES=priorityQueue.c events.c proclib.c ipc.c debug.c cmd.c config.c hashtable.c util.c md5.c critical.c eventTimer.c telm_dict.c zmqlite.c json.c cmd-pkt.c xdr.c plugin.c
99
LIBRARY_NAME=proc
1010
MAJOR_VERS=3
1111
MINOR_VERS=0.1
1212

1313
# Install Variables
14-
INCLUDE=proclib.h events.h ipc.h config.h debug.h cmd.h polysat.h hashtable.h util.h md5.h priorityQueue.h eventTimer.h telm_dict.h zmqlite.h critical.h xdr.h cmd-pkt.h
14+
INCLUDE=proclib.h events.h ipc.h config.h debug.h cmd.h polysat.h hashtable.h util.h md5.h priorityQueue.h eventTimer.h telm_dict.h zmqlite.h critical.h xdr.h cmd-pkt.h plugin.h
1515

1616
# Build Variables
1717
override CFLAGS+=$(SYMBOLS) -Wall -Werror -std=gnu99 -D_GNU_SOURCE -D_FORTIFY_SOURCE=2 $(SO_CFLAGS)

config.c

+181-34
Original file line numberDiff line numberDiff line change
@@ -32,6 +32,14 @@
3232
#include "config.h"
3333
#include "debug.h"
3434

35+
struct CFG_buffered_obj
36+
{
37+
void *parsed_cfg;
38+
char *buff;
39+
size_t len;
40+
struct CFG_ParseValue val;
41+
};
42+
3543
static char gConfigPath[PATH_MAX+1] = "";
3644

3745
const char *CFG_getPath()
@@ -82,6 +90,11 @@ int CFG_locateConfigFile(const char *name)
8290
struct CFG_Context {
8391
FILE *file;
8492
int lineNum;
93+
char *accum;
94+
size_t used, len;
95+
char *replay;
96+
int stop;
97+
int allow_buffering;
8598
char buff[1024*4];
8699
};
87100

@@ -97,6 +110,22 @@ static int NextLine(struct CFG_Context *ctx)
97110
{
98111
int len, start, i;
99112
int skipFlag = 0; //If full line is not read in, skip last bit of junk
113+
char *sep;
114+
115+
if (ctx->replay) {
116+
sep = strchr(ctx->replay, '\n');
117+
if (sep)
118+
*sep++ = 0;
119+
strncpy(ctx->buff, ctx->replay, sizeof(ctx->buff));
120+
ctx->buff[sizeof(ctx->buff) - 1] = 0;
121+
ctx->replay = sep;
122+
if (!sep)
123+
ctx->stop = 1;
124+
ctx->lineNum++;
125+
return 1;
126+
}
127+
if (ctx->stop)
128+
return 1;
100129

101130
for ( ; NULL != fgets(ctx->buff, sizeof(ctx->buff), ctx->file);
102131
++ctx->lineNum) {
@@ -145,7 +174,7 @@ static void *processKeyValueLine(struct CFG_Context *ctx,
145174
for(curr = keys; curr && curr->name; curr++) {
146175
if (!strcasecmp(curr->name, key)) {
147176
found = 1;
148-
if (curr->subObj) {
177+
if (curr->lookup_cb) {
149178
DBG_print(DBG_LEVEL_WARN, "Warning: Option name '%s' can not be a "
150179
"sub-object at line %d\n", key, ctx->lineNum);
151180
} else {
@@ -162,6 +191,27 @@ static void *processKeyValueLine(struct CFG_Context *ctx,
162191
return data;
163192
}
164193

194+
static void accumulate_line(struct CFG_Context *ctx)
195+
{
196+
int len = strlen(ctx->buff);
197+
198+
if (!ctx->accum || !ctx->len) {
199+
ctx->len = 1024;
200+
ctx->accum = malloc(ctx->len);
201+
ctx->used = 0;
202+
}
203+
204+
if (len >= ctx->len - ctx->used - 3) {
205+
ctx->len *= 2;
206+
ctx->accum = realloc(ctx->accum, ctx->len);
207+
}
208+
209+
memcpy(&ctx->accum[ctx->used], ctx->buff, len);
210+
ctx->used += len;
211+
ctx->accum[ctx->used++] = '\n';
212+
ctx->accum[ctx->used] = 0;
213+
}
214+
165215
static void *ParseObject(struct CFG_Context *ctx, struct CFG_ParseObj *parObj,
166216
void *parData)
167217
{
@@ -170,9 +220,11 @@ static void *ParseObject(struct CFG_Context *ctx, struct CFG_ParseObj *parObj,
170220
char *objLcl, *paramsLcl = NULL;
171221
int more;
172222
struct CFG_ParseValue *curr = NULL;
173-
struct CFG_ParseObj *child = NULL, **itr = NULL;
223+
struct CFG_ParseObj *child = NULL;
174224
void *data = NULL;
175225
char subobj_type_buff[256];
226+
int buffer_obj = ctx->allow_buffering;
227+
struct CFG_buffered_obj *obj_buff = NULL;
176228

177229
subobj_type_buff[0] = 0;
178230
if (obj[strlen(obj)-1] != '>') {
@@ -203,69 +255,84 @@ static void *ParseObject(struct CFG_Context *ctx, struct CFG_ParseObj *parObj,
203255
}
204256
}
205257

206-
207-
if (parObj) {
258+
if (parObj && !ctx->accum) {
208259
for(curr = parObj->keys; curr->name; curr++) {
209260
if (!strcasecmp(obj, curr->name))
210261
break;
211262
}
212263
if (!curr->name)
213264
curr = NULL;
214-
if (curr && !curr->subObj && !curr->subObjArr) {
265+
if (curr && !curr->lookup_cb) {
215266
DBG_print(DBG_LEVEL_WARN, "Warning: Option %s not a sub"
216267
"-object ,line %d\n", obj, ctx->lineNum);
217268
curr = NULL;
218-
} else if (curr && curr->subObj) {
219-
child = curr->subObj;
220269
}
221-
else if (curr && !curr->subObj && curr->subObjArr) {
270+
else if (curr && curr->lookup_cb) {
222271
snprintf(subobj_type_buff, sizeof(subobj_type_buff), "__type_%s", obj);
223272
subobj_type_buff[sizeof(subobj_type_buff)-1] = 0;
224-
225-
child = NULL;
226-
itr = curr->subObjArr;
227-
while(*itr) {
228-
if (!strcasecmp((*itr)->subtype, paramsLcl)) {
229-
child = *itr;
230-
break;
231-
}
232-
itr++;
273+
child = curr->lookup_cb(paramsLcl, curr->lookup_arg, &buffer_obj);
274+
if (buffer_obj) {
275+
obj_buff = (struct CFG_buffered_obj*) malloc(sizeof(*obj_buff));
276+
memset(obj_buff, 0, sizeof(*obj_buff));
277+
obj_buff->val = *curr;
233278
}
234279
}
235280
}
236281

237-
if (!child)
282+
if (ctx->accum || (!child && obj_buff)) {
283+
char *oterm = &obj[strlen(obj)];
284+
if (params) {
285+
*oterm = ' ';
286+
params[strlen(params)] = '>';
287+
}
288+
else
289+
*oterm = '>';
290+
291+
accumulate_line(ctx);
292+
*oterm = 0;
293+
if (params)
294+
params[strlen(params) - 1] = 0;
295+
}
296+
297+
if (!child && !ctx->accum)
238298
DBG_print(DBG_LEVEL_WARN, "Warning: Description for '%s/%s' not found, "
239299
"line %d\n", obj, paramsLcl, ctx->lineNum);
240300

241301
if (child && child->initCb.cb)
242302
data = (*child->initCb.cb)(objLcl, paramsLcl, data,
243303
child->initCb.p1, child->initCb.p2);
244304

245-
if (child && paramsLcl) {
305+
if (paramsLcl) {
246306
struct CFG_ParseValue *currLine = NULL;
247-
for(currLine = parObj->keys; currLine && currLine->name; currLine++) {
248-
if (!strcasecmp(currLine->name, subobj_type_buff)) {
249-
if (currLine->cb.cb)
250-
(*currLine->cb.cb)(subobj_type_buff, paramsLcl, parData,
251-
currLine->cb.p1, currLine->cb.p2);
252-
break;
307+
if (parObj) {
308+
for(currLine = parObj->keys; currLine && currLine->name; currLine++) {
309+
if (!strcasecmp(currLine->name, subobj_type_buff)) {
310+
if (currLine->cb.cb)
311+
(*currLine->cb.cb)(subobj_type_buff, paramsLcl, parData,
312+
currLine->cb.p1, currLine->cb.p2);
313+
break;
314+
}
253315
}
254316
}
255317

256-
for(currLine = child->keys; currLine && currLine->name; currLine++) {
257-
if (!strcasecmp(currLine->name, "__type")) {
258-
if (currLine->cb.cb)
259-
(*currLine->cb.cb)("__type", paramsLcl, data,
260-
currLine->cb.p1, currLine->cb.p2);
261-
break;
318+
if (child) {
319+
for(currLine = child->keys; currLine && currLine->name; currLine++) {
320+
if (!strcasecmp(currLine->name, "__type")) {
321+
if (currLine->cb.cb)
322+
(*currLine->cb.cb)("__type", paramsLcl, data,
323+
currLine->cb.p1, currLine->cb.p2);
324+
break;
325+
}
262326
}
263327
}
264328
}
265329

266330
while((more = NextLine(ctx)) ) {
267331
obj = ctx->buff;
332+
268333
if (obj[0] == '<' && obj[1] == '/') {
334+
if (ctx->accum)
335+
accumulate_line(ctx);
269336
obj[strlen(obj) - 1] = 0;
270337
if (strlen(obj) < 3 || strcasecmp(&obj[2], objLcl)) {
271338
DBG_print(DBG_LEVEL_WARN, "Warning: Malformed end object line in "
@@ -276,11 +343,17 @@ static void *ParseObject(struct CFG_Context *ctx, struct CFG_ParseObj *parObj,
276343
}
277344

278345
if (obj[0] == '<') {
346+
buffer_obj = ctx->allow_buffering;
347+
ctx->allow_buffering = 1;
279348
data = ParseObject(ctx, child, data);
349+
ctx->allow_buffering = buffer_obj;
280350
continue;
281351
}
282352

283-
data = processKeyValueLine(ctx, child ? child->keys : NULL, data);
353+
if (!ctx->accum)
354+
data = processKeyValueLine(ctx, child ? child->keys : NULL, data);
355+
else
356+
accumulate_line(ctx);
284357
}
285358
if (!more) {
286359
DBG_print(DBG_LEVEL_WARN, "Warning: permature end of config file\n");
@@ -290,11 +363,23 @@ static void *ParseObject(struct CFG_Context *ctx, struct CFG_ParseObj *parObj,
290363
data = (*child->finiCb.cb)(objLcl, paramsLcl, data,
291364
child->finiCb.p1, child->finiCb.p2);
292365

366+
if (obj_buff) {
367+
if (child)
368+
obj_buff->parsed_cfg = data;
369+
else {
370+
obj_buff->len = ctx->used;
371+
obj_buff->buff = ctx->accum;
372+
ctx->accum = NULL;
373+
ctx->len = ctx->used = 0;
374+
}
375+
data = obj_buff;
376+
}
377+
293378
free(objLcl);
294379
if (paramsLcl)
295380
free(paramsLcl);
296381

297-
if (child && curr && curr->cb.cb)
382+
if (curr && curr->cb.cb)
298383
data = (*curr->cb.cb)(curr->name, data, parData,
299384
curr->cb.p1, curr->cb.p2);
300385
else
@@ -303,16 +388,52 @@ static void *ParseObject(struct CFG_Context *ctx, struct CFG_ParseObj *parObj,
303388
return data;
304389
}
305390

391+
void *CFG_cfg_for_object_buffer(struct CFG_buffered_obj *obj)
392+
{
393+
struct CFG_ParseObj fake_root;
394+
struct CFG_ParseValue fake_keys[2];
395+
struct CFG_Context ctx;
396+
397+
if (!obj)
398+
return NULL;
399+
400+
if (obj->parsed_cfg)
401+
return obj->parsed_cfg;
402+
403+
memset(&ctx, 0, sizeof(ctx));
404+
memset(&fake_root, 0, sizeof(fake_root));
405+
memset(&fake_keys, 0, sizeof(fake_keys));
406+
fake_keys[0] = obj->val;
407+
fake_root.keys = fake_keys;
408+
409+
fake_keys[0].cb.cb = &CFG_PtrCpyCB;
410+
fake_keys[0].cb.p1 = NULL;
411+
fake_keys[0].cb.p2 = NULL;
412+
413+
ctx.replay = obj->buff;
414+
415+
if (NextLine(&ctx)) {
416+
ParseObject(&ctx, &fake_root, &obj->parsed_cfg);
417+
}
418+
if (obj->buff)
419+
free(obj->buff);
420+
obj->buff = NULL;
421+
422+
return obj->parsed_cfg;
423+
}
424+
306425
void *CFG_parseFile(struct CFG_ParseObj *rootObj)
307426
{
308427
return CFG_parseFileAtPath(rootObj, gConfigPath);
309428
}
310429

311430
void *CFG_parseFileAtPath(struct CFG_ParseObj *rootObj, const char *path)
312431
{
313-
struct CFG_Context ctx = { NULL, 0 };
432+
struct CFG_Context ctx;
314433
void *data = NULL;
315434

435+
memset(&ctx, 0, sizeof(ctx));
436+
ctx.allow_buffering = 1;
316437
if( !(ctx.file = fopen(path, "r")) ){
317438
ERRNO_WARN("Failed to fdopen config file '%s'", path);
318439
return NULL;
@@ -513,3 +634,29 @@ void CFG_freeArray(struct CFG_Array *arr, CFG_objFreeCb_t freeCb)
513634
arr->len = 0;
514635
}
515636
}
637+
638+
struct CFG_ParseObj *CFG_static_obj(
639+
const char *params, void *arg, int *buffer_obj)
640+
{
641+
*buffer_obj = 0;
642+
return (struct CFG_ParseObj*)arg;
643+
}
644+
645+
struct CFG_ParseObj *CFG_static_arr_obj(
646+
const char *params, void *arg, int *buffer_obj)
647+
{
648+
*buffer_obj = 0;
649+
struct CFG_ParseObj *result = NULL, **itr;
650+
651+
itr = (struct CFG_ParseObj**)arg;
652+
653+
while(*itr) {
654+
if (!strcasecmp((*itr)->subtype, params)) {
655+
result = *itr;
656+
break;
657+
}
658+
itr++;
659+
}
660+
661+
return result;
662+
}

0 commit comments

Comments
 (0)