-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathtrigger.c
executable file
·181 lines (148 loc) · 3.88 KB
/
trigger.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include "plugin_manager.h"
#include "trigger.h"
#include "list.h"
/* Structure that defines a hash table [name]<->[callback] */
struct callbacks_table {
char name[MAX_HOOK_NAME];
callback_t callback;
UT_hash_handle hh;
};
static callback_t get_callback(struct trigger *trigger, const char *name)
{
struct callbacks_table *item = NULL;
HASH_FIND_STR(trigger->callbacks, name, item);
if (!item)
return NULL;
return item->callback;
}
static int
set_callback(struct trigger *trigger, const char *name, callback_t callback)
{
struct callbacks_table *item = NULL;
if (get_callback(trigger, name))
return -EEXIST;
item = (struct callbacks_table *)
calloc(1, sizeof(struct callbacks_table));
if (!item) {
fprintf(stderr, "malloc callbacks_table: %m\n");
return -errno;
}
strncpy(item->name, name, MAX_HOOK_NAME);
item->name[MAX_HOOK_NAME - 1] = '\0';
item->callback = callback;
/* In the below macro the argument 'name' is the key field in struct*/
HASH_ADD_STR(trigger->callbacks, name, item);
return 0;
}
static int
run_hooks(struct list_head *head, int post_hook, void *args, void *data)
{
struct module_hooks_node *curr_hook = NULL;
struct list_head *curr = NULL;
int ret = 0;
/* No modules where registered */
if (!head)
return -ENOENT;
list_for_each(curr, head) {
curr_hook = list_entry(curr, struct module_hooks_node, list);
if (post_hook)
ret = curr_hook->m_hook->post_hook(args, data);
else
ret = curr_hook->m_hook->pre_hook(args, data);
if (ret)
goto skip_later;
}
skip_later:
return ret;
}
static void hooked_loop(struct trigger *trigger, void *args)
{
struct list_head *curr = NULL;
struct general_hooks_node *curr_hook = NULL;
struct list_head *head = get_general_hooks(trigger->plug_mgr);
// for each init-hook
list_for_each(curr, head) {
curr_hook = list_entry(curr, struct general_hooks_node, list);
curr_hook->g_hook->init_hook((void *)trigger);
}
trigger->loop(args);
// for each exit-hook
list_for_each(curr, head) {
curr_hook = list_entry(curr, struct general_hooks_node, list);
curr_hook->g_hook->exit_hook((void *)trigger);
}
}
int register_callback(struct trigger *trigger, const char *name, callback_t cb)
{
int ret = 0;
ret = register_module(trigger->plug_mgr, name);
if (ret) {
printf("Could not register plugin module.");
goto error_register;
}
ret = set_callback(trigger, name, cb);
if (ret)
printf("Could not register callback for module.");
error_register:
return ret;
}
int handle_callback(struct trigger *trigger, const char *name,
void *args, void *data)
{
struct list_head *head = get_module_hooks(trigger->plug_mgr, name);
callback_t callback = 0;
int ret = -1;
callback = get_callback(trigger, name);
if (!callback) {
printf("module '%s' not registered.\n", name);
ret = ENOENT;
goto error_no_callback;
}
ret = run_hooks(head, 0, args, data);
if (!ret)
ret = callback(args, data);
ret = run_hooks(head, 1, args, data);
error_no_callback:
return ret;
}
void register_loop(struct trigger *trigger, loop_t loop)
{
trigger->loop = loop;
}
int init_trigger(struct trigger *trigger, const char *path)
{
trigger->callbacks = NULL;
trigger->loop = NULL;
trigger->plug_mgr = init_plugin_manager(path);
if (!trigger->plug_mgr)
return -1;
return 0;
}
void destory_trigger(struct trigger *trigger)
{
struct callbacks_table *item = NULL;
struct callbacks_table *tmp = NULL;
destroy_plugin_manager(trigger->plug_mgr);
/* free callbacks table */
HASH_ITER(hh, trigger->callbacks, item, tmp) {
HASH_DEL(trigger->callbacks, item);
free(item);
}
}
int run_trigger(struct trigger *trigger, void *args)
{
int ret = -1;
if (load_plugins(trigger->plug_mgr)) {
fprintf(stderr, "failed loading plugins\n");
goto plugin_error;
}
hooked_loop(trigger, args);
destory_trigger(trigger);
ret = 0;
plugin_error:
return ret;
}