mirror of
https://git.rwth-aachen.de/acs/public/villas/node/
synced 2025-03-09 00:00:00 +01:00
improved configuration file format for hooks
This commit is contained in:
parent
5b93da867a
commit
8e53725c33
15 changed files with 212 additions and 141 deletions
|
@ -148,8 +148,6 @@ paths = (
|
|||
rate = 100, # Send message over this path with a fixed (constant) rate (default: 0).
|
||||
# Setting this value to 0 will disable this feature.
|
||||
|
||||
hook = "print", # Register custom hook funktion (see src/hooks.c)
|
||||
|
||||
poolsize = 30 # The amount of samples which are kept in a circular buffer.
|
||||
# This number must be larger than the 'vectorize' settings of all
|
||||
# associated input and output nodes!
|
||||
|
@ -160,23 +158,31 @@ paths = (
|
|||
|
||||
in = "opal_node", # There's only a single source node allowed!
|
||||
out = [ "udp_node", "tcp_node" ], # Multiple destination nodes are supported too.
|
||||
|
||||
hook = [ "print", "decimate:10" ] # Same is true for hooks.
|
||||
# Multipe hook functions are executed in the order they are specified here.
|
||||
},
|
||||
{
|
||||
in = "socket_node",
|
||||
out = "file_node", # This path includes all available example hooks.
|
||||
|
||||
hook = [
|
||||
"ts", # Replace the timestamp of messages with the time of reception
|
||||
"skip_unchanged:0.1", # Skip messages whose values have not changed more than 0.1 from the previous message.
|
||||
"skip_first:10", # Skip all messages which have been received in the first 10 seconds
|
||||
"print", # Print all messages to stdout
|
||||
"decimate:2", # Only forward every 2nd message
|
||||
"convert:fixed", # Convert all values to fixed precission. Use 'float' to convert to floating point.
|
||||
"fir:0" # Apply finite impulse response filter to first value.
|
||||
# Coefficients are hard-coded in 'include/config.h'.
|
||||
]
|
||||
# A complete list of supported hooks
|
||||
print = {
|
||||
output = "stdout"
|
||||
priority = 0
|
||||
},
|
||||
ts = {
|
||||
priority = 1
|
||||
}
|
||||
decimate = {
|
||||
ratio = 2 # Only forward every 2nd message
|
||||
},
|
||||
convert = {
|
||||
mode = "fixed" # Convert all values to fixed precission. Use 'float' to convert to floating point.
|
||||
},
|
||||
skip_first = {
|
||||
seconds = 10 # Skip the first 10 seconds of this path
|
||||
},
|
||||
shift = {
|
||||
mode = "origin", # Shift origin timestam of samples by +10 seconds
|
||||
offset = 10
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -40,6 +40,10 @@ paths = (
|
|||
{
|
||||
in = "node1", # Name of the node we listen to (see above)
|
||||
out = "node1", # And we loop back to the origin
|
||||
hook = ["print"]
|
||||
|
||||
# Hooks
|
||||
print = {
|
||||
output = "stdout"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -40,6 +40,10 @@ paths = (
|
|||
{
|
||||
in = "node1", # Name of the node we listen to (see above)
|
||||
out = "node2", # And we loop back to the origin
|
||||
hook = ["print"]
|
||||
|
||||
# Hooks
|
||||
print = {
|
||||
output = "stdout"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -40,6 +40,10 @@ paths = (
|
|||
{
|
||||
in = "node1", # Name of the node we listen to (see above)
|
||||
out = "node2", # And we loop back to the origin
|
||||
hook = ["print"]
|
||||
|
||||
# Hooks
|
||||
print = {
|
||||
output = "stdout"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -40,6 +40,10 @@ paths = (
|
|||
{
|
||||
in = "node1", # Name of the node we listen to (see above)
|
||||
out = "node1", # And we loop back to the origin
|
||||
hook = ["print"]
|
||||
|
||||
# Hooks
|
||||
print = {
|
||||
output = "stdout"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -41,6 +41,10 @@ paths = (
|
|||
{
|
||||
in = "node1", # Name of the node we listen to (see above)
|
||||
out = "node1", # And we loop back to the origin
|
||||
hook = ["print"]
|
||||
|
||||
# Hooks
|
||||
print = {
|
||||
output = "stdout"
|
||||
}
|
||||
}
|
||||
);
|
||||
|
|
|
@ -62,6 +62,5 @@ paths = (
|
|||
{
|
||||
in = "node1", # Name of the node we listen to (see above)
|
||||
out = "node2", # And we loop back to the origin
|
||||
hook = ["decimate:2", "print"]
|
||||
}
|
||||
);
|
||||
|
|
|
@ -96,19 +96,21 @@ enum hook_when {
|
|||
struct hook_type {
|
||||
enum hook_when when; /**< The type of the hook as a bitfield */
|
||||
hook_cb_t cb; /**< The hook callback function as a function pointer. */
|
||||
int priority; /**< A priority to change the order of execution within one type of hook */
|
||||
int priority; /**< Default priority of this hook type. */
|
||||
};
|
||||
|
||||
/** Descriptor for user defined hooks. See hooks[]. */
|
||||
struct hook {
|
||||
enum state state;
|
||||
|
||||
const char *parameter; /**< A parameter string for this hook. Can be used to configure the hook behaviour. */
|
||||
|
||||
|
||||
struct sample *prev, *last;
|
||||
|
||||
struct hook_type *_vt; /**< C++ like Vtable pointer. */
|
||||
void *_vd; /**< Private data for this hook. This pointer can be used to pass data between consecutive calls of the callback. */
|
||||
|
||||
int priority; /**< A priority to change the order of execution within one type of hook. */
|
||||
|
||||
config_setting_t *cfg;
|
||||
};
|
||||
|
||||
/** Save references to global nodes, paths and settings */
|
||||
|
@ -142,10 +144,18 @@ int hook_cmp_priority(const void *a, const void *b);
|
|||
*/
|
||||
void * hook_storage(struct hook *h, int when, size_t len, ctor_cb_t ctor, dtor_cb_t dtor);
|
||||
|
||||
/** Parse an array or single hook function.
|
||||
/** Parses an object of hooks
|
||||
*
|
||||
* Examples:
|
||||
* hooks = [ "print", "fir" ]
|
||||
* hooks = "log"
|
||||
* Example:
|
||||
*
|
||||
* {
|
||||
* stats = {
|
||||
* output = "stdout"
|
||||
* },
|
||||
* skip_first = {
|
||||
* seconds = 10
|
||||
* },
|
||||
* hooks = [ "print" ]
|
||||
* }
|
||||
*/
|
||||
int hook_parse_list(struct list *list, config_setting_t *cfg);
|
||||
int hook_parse_list(struct list *list, config_setting_t *cfg, struct super_node *sn);
|
79
lib/hook.c
79
lib/hook.c
|
@ -31,6 +31,7 @@ int hook_init(struct hook *h, struct hook_type *vt, struct super_node *sn)
|
|||
assert(h->state == STATE_DESTROYED);
|
||||
|
||||
h->_vt = vt;
|
||||
h->priority = vt->priority;
|
||||
|
||||
ret = hook_run(h, HOOK_INIT, &i);
|
||||
if (ret)
|
||||
|
@ -43,29 +44,14 @@ int hook_init(struct hook *h, struct hook_type *vt, struct super_node *sn)
|
|||
|
||||
int hook_parse(struct hook *h, config_setting_t *cfg)
|
||||
{
|
||||
const char *hookline;
|
||||
char *name, *param;
|
||||
struct plugin *p;
|
||||
int ret;
|
||||
|
||||
|
||||
assert(h->state != STATE_DESTROYED);
|
||||
|
||||
hookline = config_setting_get_string(cfg);
|
||||
if (!hookline)
|
||||
cerror(cfg, "Invalid hook function");
|
||||
h->cfg = cfg;
|
||||
|
||||
name = strtok((char *) hookline, ":");
|
||||
param = strtok(NULL, "");
|
||||
config_setting_lookup_int(h->cfg, "priority", &h->priority);
|
||||
|
||||
p = plugin_lookup(PLUGIN_TYPE_HOOK, name);
|
||||
if (!p)
|
||||
cerror(cfg, "Unknown hook function '%s'", name);
|
||||
|
||||
if (p->hook.when & HOOK_AUTO)
|
||||
cerror(cfg, "Hook '%s' is built-in and can not be added manually.", name);
|
||||
|
||||
h->parameter = param;
|
||||
|
||||
/* Parse hook arguments */
|
||||
ret = hook_run(h, HOOK_PARSE, NULL);
|
||||
if (ret)
|
||||
|
@ -96,12 +82,12 @@ int hook_cmp_priority(const void *a, const void *b)
|
|||
struct hook *ha = (struct hook *) a;
|
||||
struct hook *hb = (struct hook *) b;
|
||||
|
||||
return ha->_vt->priority - hb->_vt->priority;
|
||||
return ha->priority - hb->priority;
|
||||
}
|
||||
|
||||
int hook_run(struct hook *h, int when, struct hook_info *i)
|
||||
{
|
||||
debug(LOG_HOOK | 22, "Running hook '%s' when=%u, prio=%u, cnt=%zu", plugin_name(h->_vt), when, h->_vt->priority, i ? i->count : 0);
|
||||
debug(LOG_HOOK | 22, "Running hook '%s' when=%u, prio=%u, cnt=%zu", plugin_name(h->_vt), when, h->priority, i ? i->count : 0);
|
||||
|
||||
return h->_vt->when & when ? h->_vt->cb(h, when, i) : 0;
|
||||
}
|
||||
|
@ -129,33 +115,40 @@ void * hook_storage(struct hook *h, int when, size_t len, ctor_cb_t ctor, dtor_c
|
|||
return h->_vd;
|
||||
}
|
||||
|
||||
/** Parse an array or single hook function.
|
||||
*
|
||||
* Examples:
|
||||
* hooks = [ "print", "fir" ]
|
||||
* hooks = "log"
|
||||
*/
|
||||
int hook_parse_list(struct list *list, config_setting_t *cfg)
|
||||
int hook_parse_list(struct list *list, config_setting_t *cfg, struct super_node *sn)
|
||||
{
|
||||
struct hook h;
|
||||
struct plugin *p;
|
||||
|
||||
int ret;
|
||||
|
||||
if (!config_setting_is_group(cfg))
|
||||
cerror(cfg, "Hooks must be configured with an object");
|
||||
|
||||
switch (config_setting_type(cfg)) {
|
||||
case CONFIG_TYPE_STRING:
|
||||
hook_parse(&h, cfg);
|
||||
list_push(list, memdup(&h, sizeof(h)));
|
||||
break;
|
||||
int priority = 10;
|
||||
for (int i = 0; i < config_setting_length(cfg); i++) {
|
||||
config_setting_t *cfg_hook = config_setting_get_elem(cfg, i);
|
||||
|
||||
const char *name = config_setting_name(cfg_hook);
|
||||
|
||||
p = plugin_lookup(PLUGIN_TYPE_HOOK, name);
|
||||
if (!p)
|
||||
continue; /* We ignore all non hook settings in this libconfig object setting */
|
||||
|
||||
if (!config_setting_is_group(cfg_hook))
|
||||
cerror(cfg_hook, "The 'hooks' setting must be an array of strings.");
|
||||
|
||||
ret = hook_init(&h, &p->hook, sn);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
h.priority = priority++;
|
||||
|
||||
ret = hook_parse(&h, cfg_hook);
|
||||
if (ret)
|
||||
continue;
|
||||
|
||||
case CONFIG_TYPE_ARRAY:
|
||||
for (int i = 0; i < config_setting_length(cfg); i++) {
|
||||
config_setting_t *cfg_hook = config_setting_get_elem(cfg, i);
|
||||
|
||||
hook_parse(&h, cfg_hook);
|
||||
list_push(list, memdup(&h, sizeof(h)));
|
||||
}
|
||||
break;
|
||||
|
||||
default:
|
||||
cerror(cfg, "Invalid hook functions");
|
||||
list_push(list, memdup(&h, sizeof(h)));
|
||||
}
|
||||
|
||||
return list_length(list);
|
||||
|
|
|
@ -20,17 +20,22 @@ static int hook_convert(struct hook *h, int when, struct hook_info *j)
|
|||
} mode;
|
||||
} *private = hook_storage(h, when, sizeof(*private), NULL, NULL);
|
||||
|
||||
const char *mode;
|
||||
|
||||
switch (when) {
|
||||
case HOOK_PARSE:
|
||||
if (!h->parameter)
|
||||
error("Missing parameter for hook: '%s'", plugin_name(h->_vt));
|
||||
|
||||
if (!strcmp(h->parameter, "fixed"))
|
||||
if (!h->cfg)
|
||||
error("Missing configuration for hook: '%s'", plugin_name(h->_vt));
|
||||
|
||||
if (!config_setting_lookup_string(h->cfg, "mode", &mode))
|
||||
cerror(h->cfg, "Missing setting 'mode' for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
if (!strcmp(mode, "fixed"))
|
||||
private->mode = TO_FIXED;
|
||||
else if (!strcmp(h->parameter, "float"))
|
||||
else if (!strcmp(mode, "float"))
|
||||
private->mode = TO_FLOAT;
|
||||
else
|
||||
error("Invalid parameter '%s' for hook 'convert'", h->parameter);
|
||||
error("Invalid parameter '%s' for hook 'convert'", mode);
|
||||
break;
|
||||
|
||||
case HOOK_READ:
|
||||
|
@ -56,7 +61,7 @@ static struct plugin p = {
|
|||
.hook = {
|
||||
.priority = 99,
|
||||
.cb = hook_convert,
|
||||
.when = HOOK_STORAGE | HOOK_READ
|
||||
.when = HOOK_STORAGE | HOOK_PARSE | HOOK_READ
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -14,22 +14,24 @@
|
|||
static int hook_decimate(struct hook *h, int when, struct hook_info *j)
|
||||
{
|
||||
struct {
|
||||
unsigned ratio;
|
||||
int ratio;
|
||||
unsigned counter;
|
||||
} *private = hook_storage(h, when, sizeof(*private), NULL, NULL);
|
||||
|
||||
switch (when) {
|
||||
case HOOK_PARSE:
|
||||
if (!h->parameter)
|
||||
error("Missing parameter for hook: '%s'", plugin_name(h->_vt));
|
||||
|
||||
private->ratio = strtol(h->parameter, NULL, 10);
|
||||
if (!private->ratio)
|
||||
error("Invalid parameter '%s' for hook 'decimate'", h->parameter);
|
||||
|
||||
case HOOK_INIT:
|
||||
private->counter = 0;
|
||||
break;
|
||||
|
||||
case HOOK_PARSE:
|
||||
if (!h->cfg)
|
||||
error("Missing configuration for hook: '%s'", plugin_name(h->_vt));
|
||||
|
||||
if (!config_setting_lookup_int(h->cfg, "ratio", &private->ratio))
|
||||
cerror(h->cfg, "Missing setting 'ratio' for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
break;
|
||||
|
||||
case HOOK_READ:
|
||||
assert(j->samples);
|
||||
|
||||
|
@ -57,7 +59,7 @@ static struct plugin p = {
|
|||
.hook = {
|
||||
.priority = 99,
|
||||
.cb = hook_decimate,
|
||||
.when = HOOK_STORAGE | HOOK_DESTROY | HOOK_READ
|
||||
.when = HOOK_STORAGE | HOOK_PARSE | HOOK_DESTROY | HOOK_READ
|
||||
}
|
||||
};
|
||||
|
||||
|
|
|
@ -27,55 +27,55 @@ static int hook_shift(struct hook *h, int when, struct hook_info *j)
|
|||
SHIFT_SEQUENCE
|
||||
} mode;
|
||||
} *private = hook_storage(h, when, sizeof(*private), NULL, NULL);
|
||||
|
||||
const char *mode;
|
||||
|
||||
switch (when) {
|
||||
case HOOK_INIT:
|
||||
private->mode = SHIFT_TS_ORIGIN; /* Default mode */
|
||||
break;
|
||||
|
||||
case HOOK_PARSE:
|
||||
if (!h->parameter)
|
||||
error("Missing parameter for hook: '%s'", plugin_name(h->_vt));
|
||||
if (!h->cfg)
|
||||
error("Missing configuration for hook: '%s'", plugin_name(h->_vt));
|
||||
|
||||
char *endptr, *off;
|
||||
|
||||
char *cpy = strdup(h->parameter);
|
||||
char *tok1 = strtok(cpy, ",");
|
||||
char *tok2 = strtok(NULL, ",");
|
||||
|
||||
if (tok2) {
|
||||
off = tok2;
|
||||
|
||||
if (!strcmp(tok1, "origin"))
|
||||
if (config_setting_lookup_string(h->cfg, "mode", &mode)) {
|
||||
if (!strcmp(mode, "origin"))
|
||||
private->mode = SHIFT_TS_ORIGIN;
|
||||
else if (!strcmp(tok1, "received"))
|
||||
else if (!strcmp(mode, "received"))
|
||||
private->mode = SHIFT_TS_RECEIVED;
|
||||
else if (!strcmp(tok1, "sent"))
|
||||
else if (!strcmp(mode, "sent"))
|
||||
private->mode = SHIFT_TS_SENT;
|
||||
else if (!strcmp(tok1, "sequence"))
|
||||
else if (!strcmp(mode, "sequence"))
|
||||
private->mode = SHIFT_SEQUENCE;
|
||||
else
|
||||
error("Invalid mode parameter for hook '%s'", plugin_name(h->_vt));
|
||||
}
|
||||
else {
|
||||
off = tok1;
|
||||
|
||||
private->mode = SHIFT_TS_ORIGIN; /* Default mode */
|
||||
error("Invalid mode parameter '%s' for hook '%s'", mode, plugin_name(h->_vt));
|
||||
}
|
||||
|
||||
switch (private->mode) {
|
||||
case SHIFT_TS_ORIGIN:
|
||||
case SHIFT_TS_RECEIVED:
|
||||
case SHIFT_TS_SENT:
|
||||
private->offset.ts = time_from_double(strtod(off, &endptr));
|
||||
case SHIFT_TS_SENT: {
|
||||
double offset;
|
||||
|
||||
if (!config_setting_lookup_float(h->cfg, "offset", &offset))
|
||||
cerror(h->cfg, "Missing setting 'offset' for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
private->offset.ts = time_from_double(offset);
|
||||
break;
|
||||
}
|
||||
|
||||
case SHIFT_SEQUENCE:
|
||||
private->offset.seq = strtoul(off, &endptr, 10);
|
||||
case SHIFT_SEQUENCE: {
|
||||
int offset;
|
||||
|
||||
if (!config_setting_lookup_int(h->cfg, "offset", &offset))
|
||||
cerror(h->cfg, "Missing setting 'offset' for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
private->offset.seq = offset;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endptr == off)
|
||||
error("Invalid offset parameter for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
free(cpy);
|
||||
|
||||
break;
|
||||
|
||||
case HOOK_READ:
|
||||
|
|
|
@ -8,6 +8,8 @@
|
|||
* @{
|
||||
*/
|
||||
|
||||
#include <libconfig.h>
|
||||
|
||||
#include "hook.h"
|
||||
#include "plugin.h"
|
||||
#include "timing.h"
|
||||
|
@ -24,20 +26,19 @@ static int hook_skip_first(struct hook *h, int when, struct hook_info *j)
|
|||
} state;
|
||||
} *private = hook_storage(h, when, sizeof(*private), NULL, NULL);
|
||||
|
||||
char *endptr;
|
||||
double wait;
|
||||
|
||||
switch (when) {
|
||||
case HOOK_PARSE:
|
||||
if (!h->parameter)
|
||||
error("Missing parameter for hook: '%s'", plugin_name(h->_vt));
|
||||
|
||||
wait = strtof(h->parameter, &endptr);
|
||||
if (h->parameter == endptr)
|
||||
error("Invalid parameter '%s' for hook 'skip_first'", h->parameter);
|
||||
case HOOK_PARSE: {
|
||||
double wait;
|
||||
|
||||
if (!h->cfg)
|
||||
error("Missing configuration for hook: '%s'", plugin_name(h->_vt));
|
||||
|
||||
if (!config_setting_lookup_float(h->cfg, "seconds", &wait))
|
||||
cerror(h->cfg, "Missing setting 'seconds' for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
private->skip = time_from_double(wait);
|
||||
break;
|
||||
}
|
||||
|
||||
case HOOK_PATH_START:
|
||||
case HOOK_PATH_RESTART:
|
||||
|
|
|
@ -63,12 +63,17 @@ static int hook_stats_send(struct hook *h, int when, struct hook_info *j)
|
|||
assert(j->nodes);
|
||||
assert(j->path);
|
||||
|
||||
if (!h->parameter)
|
||||
error("Missing parameter for hook '%s'", plugin_name(h->_vt));
|
||||
if (!h->cfg)
|
||||
error("Missing configuration for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
private->dest = list_lookup(j->nodes, h->parameter);
|
||||
const char *dest;
|
||||
|
||||
if (!config_setting_lookup_string(h->cfg, "destination", &dest))
|
||||
cerror(h->cfg, "Missing setting 'destination' for hook '%s'", plugin_name(h->_vt));
|
||||
|
||||
private->dest = list_lookup(j->nodes, dest);
|
||||
if (!private->dest)
|
||||
error("Invalid destination node '%s' for hook '%s'", h->parameter, plugin_name(h->_vt));
|
||||
cerror(h->cfg, "Invalid destination node '%s' for hook '%s'", dest, plugin_name(h->_vt));
|
||||
break;
|
||||
|
||||
case HOOK_PATH_START:
|
||||
|
|
44
src/hook.c
44
src/hook.c
|
@ -24,15 +24,46 @@
|
|||
|
||||
#include "config.h"
|
||||
|
||||
static int hook_parse_cli(struct hook *h, char *param)
|
||||
{
|
||||
int ret;
|
||||
|
||||
config_t cfg;
|
||||
config_setting_t *cfg_root;
|
||||
|
||||
config_init(&cfg);
|
||||
config_set_auto_convert(&cfg, 1);
|
||||
|
||||
cfg_root = config_root_setting(&cfg);
|
||||
|
||||
ret = config_read_string(&cfg, param);
|
||||
if (ret != CONFIG_TRUE)
|
||||
error("Failed to parse argument '%s': %s", param, config_error_text(&cfg));
|
||||
|
||||
config_write(&cfg, stdout);
|
||||
|
||||
ret = hook_parse(h, cfg_root);
|
||||
if (ret)
|
||||
error("Failed to parse hook settings");
|
||||
|
||||
config_destroy(&cfg);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void usage()
|
||||
{
|
||||
printf("Usage: villas-hook [OPTIONS] NAME [PARAMETER] \n");
|
||||
printf("Usage: villas-hook [OPTIONS] NAME [PARAMETER1 PARAMTER2 ...] \n");
|
||||
printf(" NAME the name of the hook function to run\n");
|
||||
printf(" PARAM the name of the node to which samples are sent and received from\n\n");
|
||||
printf(" OPTIONS are:\n");
|
||||
printf(" -h show this help\n");
|
||||
printf(" -d LVL set debug level to LVL\n");
|
||||
printf(" -v CNT process CNT samples at once\n\n");
|
||||
printf(" -v CNT process CNT samples at once\n");
|
||||
printf("\n");
|
||||
printf("Example:");
|
||||
printf(" villas-signal random | villas-hook skip_first seconds=10\n");
|
||||
printf("\n");
|
||||
|
||||
print_copyright();
|
||||
}
|
||||
|
@ -45,7 +76,7 @@ int main(int argc, char *argv[])
|
|||
level = V;
|
||||
cnt = 1;
|
||||
|
||||
char *name, *parameter;
|
||||
char *name;
|
||||
|
||||
struct log log;
|
||||
struct plugin *p;
|
||||
|
@ -86,17 +117,16 @@ int main(int argc, char *argv[])
|
|||
error("Failed to initilize memory pool");
|
||||
|
||||
name = argv[optind];
|
||||
parameter = argc >= optind + 2 ? argv[optind + 1] : NULL;
|
||||
|
||||
h.parameter = parameter;
|
||||
|
||||
p = plugin_lookup(PLUGIN_TYPE_HOOK, name);
|
||||
if (!p)
|
||||
error("Unknown hook function '%s'", argv[optind]);
|
||||
|
||||
hook_init(&h, &p->hook, NULL);
|
||||
|
||||
if (argc > optind + 1)
|
||||
hook_parse_cli(&h, argv[optind + 1]);
|
||||
|
||||
hook_run(&h, HOOK_PARSE, &hi);
|
||||
hook_run(&h, HOOK_PATH_START, &hi);
|
||||
|
||||
while (!feof(stdin)) {
|
||||
|
|
Loading…
Add table
Reference in a new issue