1*7f2fe78bSCy Schubert /*
2*7f2fe78bSCy Schubert * Copyright 2011 Red Hat, Inc.
3*7f2fe78bSCy Schubert *
4*7f2fe78bSCy Schubert * Permission is hereby granted, free of charge, to any person
5*7f2fe78bSCy Schubert * obtaining a copy of this software and associated documentation files
6*7f2fe78bSCy Schubert * (the "Software"), to deal in the Software without restriction,
7*7f2fe78bSCy Schubert * including without limitation the rights to use, copy, modify, merge,
8*7f2fe78bSCy Schubert * publish, distribute, sublicense, and/or sell copies of the Software,
9*7f2fe78bSCy Schubert * and to permit persons to whom the Software is furnished to do so,
10*7f2fe78bSCy Schubert * subject to the following conditions:
11*7f2fe78bSCy Schubert *
12*7f2fe78bSCy Schubert * The above copyright notice and this permission notice shall be
13*7f2fe78bSCy Schubert * included in all copies or substantial portions of the Software.
14*7f2fe78bSCy Schubert *
15*7f2fe78bSCy Schubert * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16*7f2fe78bSCy Schubert * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17*7f2fe78bSCy Schubert * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18*7f2fe78bSCy Schubert * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19*7f2fe78bSCy Schubert * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20*7f2fe78bSCy Schubert * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21*7f2fe78bSCy Schubert * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22*7f2fe78bSCy Schubert * SOFTWARE.
23*7f2fe78bSCy Schubert */
24*7f2fe78bSCy Schubert
25*7f2fe78bSCy Schubert #include <stdio.h>
26*7f2fe78bSCy Schubert #include <stdlib.h>
27*7f2fe78bSCy Schubert #include <string.h>
28*7f2fe78bSCy Schubert #include <signal.h>
29*7f2fe78bSCy Schubert #include <assert.h>
30*7f2fe78bSCy Schubert #include <stdarg.h>
31*7f2fe78bSCy Schubert
32*7f2fe78bSCy Schubert #include <libgen.h>
33*7f2fe78bSCy Schubert #include <sys/types.h>
34*7f2fe78bSCy Schubert #include <dirent.h>
35*7f2fe78bSCy Schubert
36*7f2fe78bSCy Schubert #ifdef HAVE_PTHREAD
37*7f2fe78bSCy Schubert #include <pthread.h>
38*7f2fe78bSCy Schubert #endif
39*7f2fe78bSCy Schubert
40*7f2fe78bSCy Schubert #include <verto-module.h>
41*7f2fe78bSCy Schubert #include "module.h"
42*7f2fe78bSCy Schubert
43*7f2fe78bSCy Schubert #define _str(s) # s
44*7f2fe78bSCy Schubert #define __str(s) _str(s)
45*7f2fe78bSCy Schubert
46*7f2fe78bSCy Schubert #define MUTABLE(flags) (flags & _VERTO_EV_FLAG_MUTABLE_MASK)
47*7f2fe78bSCy Schubert
48*7f2fe78bSCy Schubert /* Remove flags we can emulate */
49*7f2fe78bSCy Schubert #define make_actual(flags) ((flags) & ~(VERTO_EV_FLAG_PERSIST|VERTO_EV_FLAG_IO_CLOSE_FD))
50*7f2fe78bSCy Schubert
51*7f2fe78bSCy Schubert struct verto_ctx {
52*7f2fe78bSCy Schubert size_t ref;
53*7f2fe78bSCy Schubert verto_mod_ctx *ctx;
54*7f2fe78bSCy Schubert const verto_module *module;
55*7f2fe78bSCy Schubert verto_ev *events;
56*7f2fe78bSCy Schubert int deflt;
57*7f2fe78bSCy Schubert int exit;
58*7f2fe78bSCy Schubert };
59*7f2fe78bSCy Schubert
60*7f2fe78bSCy Schubert typedef struct {
61*7f2fe78bSCy Schubert verto_proc proc;
62*7f2fe78bSCy Schubert verto_proc_status status;
63*7f2fe78bSCy Schubert } verto_child;
64*7f2fe78bSCy Schubert
65*7f2fe78bSCy Schubert typedef struct {
66*7f2fe78bSCy Schubert int fd;
67*7f2fe78bSCy Schubert verto_ev_flag state;
68*7f2fe78bSCy Schubert } verto_io;
69*7f2fe78bSCy Schubert
70*7f2fe78bSCy Schubert struct verto_ev {
71*7f2fe78bSCy Schubert verto_ev *next;
72*7f2fe78bSCy Schubert verto_ctx *ctx;
73*7f2fe78bSCy Schubert verto_ev_type type;
74*7f2fe78bSCy Schubert verto_callback *callback;
75*7f2fe78bSCy Schubert verto_callback *onfree;
76*7f2fe78bSCy Schubert void *priv;
77*7f2fe78bSCy Schubert verto_mod_ev *ev;
78*7f2fe78bSCy Schubert verto_ev_flag flags;
79*7f2fe78bSCy Schubert verto_ev_flag actual;
80*7f2fe78bSCy Schubert size_t depth;
81*7f2fe78bSCy Schubert int deleted;
82*7f2fe78bSCy Schubert union {
83*7f2fe78bSCy Schubert verto_io io;
84*7f2fe78bSCy Schubert int signal;
85*7f2fe78bSCy Schubert time_t interval;
86*7f2fe78bSCy Schubert verto_child child;
87*7f2fe78bSCy Schubert } option;
88*7f2fe78bSCy Schubert };
89*7f2fe78bSCy Schubert
90*7f2fe78bSCy Schubert typedef struct module_record module_record;
91*7f2fe78bSCy Schubert struct module_record {
92*7f2fe78bSCy Schubert module_record *next;
93*7f2fe78bSCy Schubert const verto_module *module;
94*7f2fe78bSCy Schubert void *dll;
95*7f2fe78bSCy Schubert char *filename;
96*7f2fe78bSCy Schubert verto_ctx *defctx;
97*7f2fe78bSCy Schubert };
98*7f2fe78bSCy Schubert
99*7f2fe78bSCy Schubert
100*7f2fe78bSCy Schubert #ifdef BUILTIN_MODULE
101*7f2fe78bSCy Schubert #define _MODTABLE(n) verto_module_table_ ## n
102*7f2fe78bSCy Schubert #define MODTABLE(n) _MODTABLE(n)
103*7f2fe78bSCy Schubert /*
104*7f2fe78bSCy Schubert * This symbol can be used when embedding verto.c in a library along with a
105*7f2fe78bSCy Schubert * built-in private module, to preload the module instead of dynamically
106*7f2fe78bSCy Schubert * linking it in later. Define to <modulename>.
107*7f2fe78bSCy Schubert */
108*7f2fe78bSCy Schubert extern verto_module MODTABLE(BUILTIN_MODULE);
109*7f2fe78bSCy Schubert static module_record builtin_record = {
110*7f2fe78bSCy Schubert NULL, &MODTABLE(BUILTIN_MODULE), NULL, "", NULL
111*7f2fe78bSCy Schubert };
112*7f2fe78bSCy Schubert static module_record *loaded_modules = &builtin_record;
113*7f2fe78bSCy Schubert #else
114*7f2fe78bSCy Schubert static module_record *loaded_modules;
115*7f2fe78bSCy Schubert #endif
116*7f2fe78bSCy Schubert
117*7f2fe78bSCy Schubert static void *(*resize_cb)(void *mem, size_t size);
118*7f2fe78bSCy Schubert static int resize_cb_hierarchical;
119*7f2fe78bSCy Schubert
120*7f2fe78bSCy Schubert #ifdef HAVE_PTHREAD
121*7f2fe78bSCy Schubert static pthread_mutex_t loaded_modules_mutex = PTHREAD_MUTEX_INITIALIZER;
122*7f2fe78bSCy Schubert
123*7f2fe78bSCy Schubert #ifndef NDEBUG
124*7f2fe78bSCy Schubert #define mutex_lock(x) { \
125*7f2fe78bSCy Schubert int c = pthread_mutex_lock(x); \
126*7f2fe78bSCy Schubert if (c != 0) { \
127*7f2fe78bSCy Schubert fprintf(stderr, "pthread_mutex_lock returned %d (%s) in %s", \
128*7f2fe78bSCy Schubert c, strerror(c), __FUNCTION__); \
129*7f2fe78bSCy Schubert } \
130*7f2fe78bSCy Schubert assert(c == 0); \
131*7f2fe78bSCy Schubert }
132*7f2fe78bSCy Schubert #define mutex_unlock(x) { \
133*7f2fe78bSCy Schubert int c = pthread_mutex_unlock(x); \
134*7f2fe78bSCy Schubert if (c != 0) { \
135*7f2fe78bSCy Schubert fprintf(stderr, "pthread_mutex_unlock returned %d (%s) in %s", \
136*7f2fe78bSCy Schubert c, strerror(c), __FUNCTION__); \
137*7f2fe78bSCy Schubert } \
138*7f2fe78bSCy Schubert assert(c == 0); \
139*7f2fe78bSCy Schubert }
140*7f2fe78bSCy Schubert #define mutex_destroy(x) { \
141*7f2fe78bSCy Schubert int c = pthread_mutex_destroy(x); \
142*7f2fe78bSCy Schubert if (c != 0) { \
143*7f2fe78bSCy Schubert fprintf(stderr, "pthread_mutex_destroy returned %d (%s) in %s", \
144*7f2fe78bSCy Schubert c, strerror(c), __FUNCTION__); \
145*7f2fe78bSCy Schubert } \
146*7f2fe78bSCy Schubert assert(c == 0); \
147*7f2fe78bSCy Schubert }
148*7f2fe78bSCy Schubert #else /* NDEBUG */
149*7f2fe78bSCy Schubert #define mutex_lock pthread_mutex_lock
150*7f2fe78bSCy Schubert #define mutex_unlock pthread_mutex_unlock
151*7f2fe78bSCy Schubert #define mutex_destroy pthread_mutex_destroy
152*7f2fe78bSCy Schubert #endif /* NDEBUG */
153*7f2fe78bSCy Schubert
154*7f2fe78bSCy Schubert #else /* HAVE_PTHREAD */
155*7f2fe78bSCy Schubert #define mutex_lock(x)
156*7f2fe78bSCy Schubert #define mutex_unlock(x)
157*7f2fe78bSCy Schubert #define mutex_destroy(x)
158*7f2fe78bSCy Schubert #endif /* HAVE_PTHREAD */
159*7f2fe78bSCy Schubert
160*7f2fe78bSCy Schubert #define vfree(mem) vresize(mem, 0)
161*7f2fe78bSCy Schubert static void *
vresize(void * mem,size_t size)162*7f2fe78bSCy Schubert vresize(void *mem, size_t size)
163*7f2fe78bSCy Schubert {
164*7f2fe78bSCy Schubert if (!resize_cb)
165*7f2fe78bSCy Schubert resize_cb = &realloc;
166*7f2fe78bSCy Schubert if (size == 0 && resize_cb == &realloc) {
167*7f2fe78bSCy Schubert /* Avoid memleak as realloc(X, 0) can return a free-able pointer. */
168*7f2fe78bSCy Schubert free(mem);
169*7f2fe78bSCy Schubert return NULL;
170*7f2fe78bSCy Schubert }
171*7f2fe78bSCy Schubert return (*resize_cb)(mem, size);
172*7f2fe78bSCy Schubert }
173*7f2fe78bSCy Schubert
174*7f2fe78bSCy Schubert #ifndef BUILTIN_MODULE
175*7f2fe78bSCy Schubert static char *
string_aconcat(const char * first,const char * second,const char * third)176*7f2fe78bSCy Schubert string_aconcat(const char *first, const char *second, const char *third) {
177*7f2fe78bSCy Schubert char *ret;
178*7f2fe78bSCy Schubert size_t len;
179*7f2fe78bSCy Schubert
180*7f2fe78bSCy Schubert len = strlen(first) + strlen(second);
181*7f2fe78bSCy Schubert if (third)
182*7f2fe78bSCy Schubert len += strlen(third);
183*7f2fe78bSCy Schubert
184*7f2fe78bSCy Schubert ret = malloc(len + 1);
185*7f2fe78bSCy Schubert if (!ret)
186*7f2fe78bSCy Schubert return NULL;
187*7f2fe78bSCy Schubert
188*7f2fe78bSCy Schubert strncpy(ret, first, strlen(first));
189*7f2fe78bSCy Schubert strncpy(ret + strlen(first), second, strlen(second));
190*7f2fe78bSCy Schubert if (third)
191*7f2fe78bSCy Schubert strncpy(ret + strlen(first) + strlen(second), third, strlen(third));
192*7f2fe78bSCy Schubert
193*7f2fe78bSCy Schubert ret[len] = '\0';
194*7f2fe78bSCy Schubert return ret;
195*7f2fe78bSCy Schubert }
196*7f2fe78bSCy Schubert
197*7f2fe78bSCy Schubert static char *
int_get_table_name_from_filename(const char * filename)198*7f2fe78bSCy Schubert int_get_table_name_from_filename(const char *filename)
199*7f2fe78bSCy Schubert {
200*7f2fe78bSCy Schubert char *bn = NULL, *tmp = NULL;
201*7f2fe78bSCy Schubert
202*7f2fe78bSCy Schubert if (!filename)
203*7f2fe78bSCy Schubert return NULL;
204*7f2fe78bSCy Schubert
205*7f2fe78bSCy Schubert tmp = strdup(filename);
206*7f2fe78bSCy Schubert if (!tmp)
207*7f2fe78bSCy Schubert return NULL;
208*7f2fe78bSCy Schubert
209*7f2fe78bSCy Schubert bn = basename(tmp);
210*7f2fe78bSCy Schubert if (bn)
211*7f2fe78bSCy Schubert bn = strdup(bn);
212*7f2fe78bSCy Schubert free(tmp);
213*7f2fe78bSCy Schubert if (!bn)
214*7f2fe78bSCy Schubert return NULL;
215*7f2fe78bSCy Schubert
216*7f2fe78bSCy Schubert tmp = strchr(bn, '-');
217*7f2fe78bSCy Schubert if (tmp) {
218*7f2fe78bSCy Schubert if (strchr(tmp+1, '.')) {
219*7f2fe78bSCy Schubert *strchr(tmp+1, '.') = '\0';
220*7f2fe78bSCy Schubert tmp = string_aconcat(__str(VERTO_MODULE_TABLE()), tmp + 1, NULL);
221*7f2fe78bSCy Schubert } else
222*7f2fe78bSCy Schubert tmp = NULL;
223*7f2fe78bSCy Schubert }
224*7f2fe78bSCy Schubert
225*7f2fe78bSCy Schubert free(bn);
226*7f2fe78bSCy Schubert return tmp;
227*7f2fe78bSCy Schubert }
228*7f2fe78bSCy Schubert
229*7f2fe78bSCy Schubert typedef struct {
230*7f2fe78bSCy Schubert int reqsym;
231*7f2fe78bSCy Schubert verto_ev_type reqtypes;
232*7f2fe78bSCy Schubert } shouldload_data;
233*7f2fe78bSCy Schubert
234*7f2fe78bSCy Schubert static int
shouldload(void * symb,void * misc,char ** err)235*7f2fe78bSCy Schubert shouldload(void *symb, void *misc, char **err)
236*7f2fe78bSCy Schubert {
237*7f2fe78bSCy Schubert verto_module *table = (verto_module*) symb;
238*7f2fe78bSCy Schubert shouldload_data *data = (shouldload_data*) misc;
239*7f2fe78bSCy Schubert
240*7f2fe78bSCy Schubert /* Make sure we have the proper version */
241*7f2fe78bSCy Schubert if (table->vers != VERTO_MODULE_VERSION) {
242*7f2fe78bSCy Schubert if (err)
243*7f2fe78bSCy Schubert *err = strdup("Invalid module version!");
244*7f2fe78bSCy Schubert return 0;
245*7f2fe78bSCy Schubert }
246*7f2fe78bSCy Schubert
247*7f2fe78bSCy Schubert /* Check to make sure that we have our required symbol if reqsym == true */
248*7f2fe78bSCy Schubert if (table->symb && data->reqsym
249*7f2fe78bSCy Schubert && !module_symbol_is_present(NULL, table->symb)) {
250*7f2fe78bSCy Schubert if (err)
251*7f2fe78bSCy Schubert *err = string_aconcat("Symbol not found: ", table->symb, "!");
252*7f2fe78bSCy Schubert return 0;
253*7f2fe78bSCy Schubert }
254*7f2fe78bSCy Schubert
255*7f2fe78bSCy Schubert /* Check to make sure that this module supports our required features */
256*7f2fe78bSCy Schubert if (data->reqtypes != VERTO_EV_TYPE_NONE
257*7f2fe78bSCy Schubert && (table->types & data->reqtypes) != data->reqtypes) {
258*7f2fe78bSCy Schubert if (err)
259*7f2fe78bSCy Schubert *err = strdup("Module does not support required features!");
260*7f2fe78bSCy Schubert return 0;
261*7f2fe78bSCy Schubert }
262*7f2fe78bSCy Schubert
263*7f2fe78bSCy Schubert return 1;
264*7f2fe78bSCy Schubert }
265*7f2fe78bSCy Schubert
266*7f2fe78bSCy Schubert static int
do_load_file(const char * filename,int reqsym,verto_ev_type reqtypes,module_record ** record)267*7f2fe78bSCy Schubert do_load_file(const char *filename, int reqsym, verto_ev_type reqtypes,
268*7f2fe78bSCy Schubert module_record **record)
269*7f2fe78bSCy Schubert {
270*7f2fe78bSCy Schubert char *tblname = NULL, *error = NULL;
271*7f2fe78bSCy Schubert module_record *tmp;
272*7f2fe78bSCy Schubert shouldload_data data = { reqsym, reqtypes };
273*7f2fe78bSCy Schubert
274*7f2fe78bSCy Schubert /* Check the loaded modules to see if we already loaded one */
275*7f2fe78bSCy Schubert mutex_lock(&loaded_modules_mutex);
276*7f2fe78bSCy Schubert for (*record = loaded_modules ; *record ; *record = (*record)->next) {
277*7f2fe78bSCy Schubert if (!strcmp((*record)->filename, filename)) {
278*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
279*7f2fe78bSCy Schubert return 1;
280*7f2fe78bSCy Schubert }
281*7f2fe78bSCy Schubert }
282*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
283*7f2fe78bSCy Schubert
284*7f2fe78bSCy Schubert /* Create our module record */
285*7f2fe78bSCy Schubert tmp = *record = vresize(NULL, sizeof(module_record));
286*7f2fe78bSCy Schubert if (!tmp)
287*7f2fe78bSCy Schubert return 0;
288*7f2fe78bSCy Schubert memset(tmp, 0, sizeof(module_record));
289*7f2fe78bSCy Schubert tmp->filename = strdup(filename);
290*7f2fe78bSCy Schubert if (!tmp->filename) {
291*7f2fe78bSCy Schubert vfree(tmp);
292*7f2fe78bSCy Schubert return 0;
293*7f2fe78bSCy Schubert }
294*7f2fe78bSCy Schubert
295*7f2fe78bSCy Schubert /* Get the name of the module struct in the library */
296*7f2fe78bSCy Schubert tblname = int_get_table_name_from_filename(filename);
297*7f2fe78bSCy Schubert if (!tblname) {
298*7f2fe78bSCy Schubert free(tblname);
299*7f2fe78bSCy Schubert free(tmp->filename);
300*7f2fe78bSCy Schubert vfree(tmp);
301*7f2fe78bSCy Schubert return 0;
302*7f2fe78bSCy Schubert }
303*7f2fe78bSCy Schubert
304*7f2fe78bSCy Schubert /* Load the module */
305*7f2fe78bSCy Schubert error = module_load(filename, tblname, shouldload, &data, &tmp->dll,
306*7f2fe78bSCy Schubert (void **) &tmp->module);
307*7f2fe78bSCy Schubert if (error || !tmp->dll || !tmp->module) {
308*7f2fe78bSCy Schubert /*if (error)
309*7f2fe78bSCy Schubert fprintf(stderr, "%s\n", error);*/
310*7f2fe78bSCy Schubert free(error);
311*7f2fe78bSCy Schubert module_close(tmp->dll);
312*7f2fe78bSCy Schubert free(tblname);
313*7f2fe78bSCy Schubert free(tmp->filename);
314*7f2fe78bSCy Schubert vfree(tmp);
315*7f2fe78bSCy Schubert return 0;
316*7f2fe78bSCy Schubert }
317*7f2fe78bSCy Schubert
318*7f2fe78bSCy Schubert /* Append the new module to the end of the loaded modules */
319*7f2fe78bSCy Schubert mutex_lock(&loaded_modules_mutex);
320*7f2fe78bSCy Schubert for (tmp = loaded_modules ; tmp && tmp->next; tmp = tmp->next)
321*7f2fe78bSCy Schubert continue;
322*7f2fe78bSCy Schubert if (tmp)
323*7f2fe78bSCy Schubert tmp->next = *record;
324*7f2fe78bSCy Schubert else
325*7f2fe78bSCy Schubert loaded_modules = *record;
326*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
327*7f2fe78bSCy Schubert
328*7f2fe78bSCy Schubert free(tblname);
329*7f2fe78bSCy Schubert return 1;
330*7f2fe78bSCy Schubert }
331*7f2fe78bSCy Schubert
332*7f2fe78bSCy Schubert static int
do_load_dir(const char * dirname,const char * prefix,const char * suffix,int reqsym,verto_ev_type reqtypes,module_record ** record)333*7f2fe78bSCy Schubert do_load_dir(const char *dirname, const char *prefix, const char *suffix,
334*7f2fe78bSCy Schubert int reqsym, verto_ev_type reqtypes, module_record **record)
335*7f2fe78bSCy Schubert {
336*7f2fe78bSCy Schubert DIR *dir;
337*7f2fe78bSCy Schubert struct dirent *ent = NULL;
338*7f2fe78bSCy Schubert
339*7f2fe78bSCy Schubert *record = NULL;
340*7f2fe78bSCy Schubert dir = opendir(dirname);
341*7f2fe78bSCy Schubert if (!dir)
342*7f2fe78bSCy Schubert return 0;
343*7f2fe78bSCy Schubert
344*7f2fe78bSCy Schubert
345*7f2fe78bSCy Schubert while ((ent = readdir(dir))) {
346*7f2fe78bSCy Schubert char *tmp = NULL;
347*7f2fe78bSCy Schubert int success;
348*7f2fe78bSCy Schubert size_t flen, slen;
349*7f2fe78bSCy Schubert
350*7f2fe78bSCy Schubert flen = strlen(ent->d_name);
351*7f2fe78bSCy Schubert slen = strlen(suffix);
352*7f2fe78bSCy Schubert
353*7f2fe78bSCy Schubert if (!strcmp(".", ent->d_name) || !strcmp("..", ent->d_name))
354*7f2fe78bSCy Schubert continue;
355*7f2fe78bSCy Schubert if (strstr(ent->d_name, prefix) != ent->d_name)
356*7f2fe78bSCy Schubert continue;
357*7f2fe78bSCy Schubert if (flen < slen || strcmp(ent->d_name + flen - slen, suffix))
358*7f2fe78bSCy Schubert continue;
359*7f2fe78bSCy Schubert
360*7f2fe78bSCy Schubert tmp = string_aconcat(dirname, "/", ent->d_name);
361*7f2fe78bSCy Schubert if (!tmp)
362*7f2fe78bSCy Schubert continue;
363*7f2fe78bSCy Schubert
364*7f2fe78bSCy Schubert success = do_load_file(tmp, reqsym, reqtypes, record);
365*7f2fe78bSCy Schubert free(tmp);
366*7f2fe78bSCy Schubert if (success)
367*7f2fe78bSCy Schubert break;
368*7f2fe78bSCy Schubert *record = NULL;
369*7f2fe78bSCy Schubert }
370*7f2fe78bSCy Schubert
371*7f2fe78bSCy Schubert closedir(dir);
372*7f2fe78bSCy Schubert return *record != NULL;
373*7f2fe78bSCy Schubert }
374*7f2fe78bSCy Schubert #endif
375*7f2fe78bSCy Schubert
376*7f2fe78bSCy Schubert static int
load_module(const char * impl,verto_ev_type reqtypes,module_record ** record)377*7f2fe78bSCy Schubert load_module(const char *impl, verto_ev_type reqtypes, module_record **record)
378*7f2fe78bSCy Schubert {
379*7f2fe78bSCy Schubert int success = 0;
380*7f2fe78bSCy Schubert #ifndef BUILTIN_MODULE
381*7f2fe78bSCy Schubert char *prefix = NULL;
382*7f2fe78bSCy Schubert char *suffix = NULL;
383*7f2fe78bSCy Schubert char *tmp = NULL;
384*7f2fe78bSCy Schubert #endif
385*7f2fe78bSCy Schubert
386*7f2fe78bSCy Schubert /* Check the cache */
387*7f2fe78bSCy Schubert mutex_lock(&loaded_modules_mutex);
388*7f2fe78bSCy Schubert if (impl) {
389*7f2fe78bSCy Schubert for (*record = loaded_modules ; *record ; *record = (*record)->next) {
390*7f2fe78bSCy Schubert if ((strchr(impl, '/') && !strcmp(impl, (*record)->filename))
391*7f2fe78bSCy Schubert || !strcmp(impl, (*record)->module->name)) {
392*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
393*7f2fe78bSCy Schubert return 1;
394*7f2fe78bSCy Schubert }
395*7f2fe78bSCy Schubert }
396*7f2fe78bSCy Schubert } else if (loaded_modules) {
397*7f2fe78bSCy Schubert for (*record = loaded_modules ; *record ; *record = (*record)->next) {
398*7f2fe78bSCy Schubert if (reqtypes == VERTO_EV_TYPE_NONE
399*7f2fe78bSCy Schubert || ((*record)->module->types & reqtypes) == reqtypes) {
400*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
401*7f2fe78bSCy Schubert return 1;
402*7f2fe78bSCy Schubert }
403*7f2fe78bSCy Schubert }
404*7f2fe78bSCy Schubert }
405*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
406*7f2fe78bSCy Schubert
407*7f2fe78bSCy Schubert #ifndef BUILTIN_MODULE
408*7f2fe78bSCy Schubert if (!module_get_filename_for_symbol(verto_convert_module, &prefix))
409*7f2fe78bSCy Schubert return 0;
410*7f2fe78bSCy Schubert
411*7f2fe78bSCy Schubert /* Example output:
412*7f2fe78bSCy Schubert * prefix == /usr/lib/libverto-
413*7f2fe78bSCy Schubert * impl == glib
414*7f2fe78bSCy Schubert * suffix == .so.0
415*7f2fe78bSCy Schubert * Put them all together: /usr/lib/libverto-glib.so.0 */
416*7f2fe78bSCy Schubert tmp = strdup(prefix);
417*7f2fe78bSCy Schubert if (!tmp) {
418*7f2fe78bSCy Schubert free(prefix);
419*7f2fe78bSCy Schubert return 0;
420*7f2fe78bSCy Schubert }
421*7f2fe78bSCy Schubert
422*7f2fe78bSCy Schubert suffix = basename(tmp);
423*7f2fe78bSCy Schubert suffix = strchr(suffix, '.');
424*7f2fe78bSCy Schubert if (!suffix || strlen(suffix) < 1 || !(suffix = strdup(suffix))) {
425*7f2fe78bSCy Schubert free(prefix);
426*7f2fe78bSCy Schubert free(tmp);
427*7f2fe78bSCy Schubert return 0;
428*7f2fe78bSCy Schubert }
429*7f2fe78bSCy Schubert strcpy(prefix + strlen(prefix) - strlen(suffix), "-");
430*7f2fe78bSCy Schubert free(tmp);
431*7f2fe78bSCy Schubert
432*7f2fe78bSCy Schubert if (impl) {
433*7f2fe78bSCy Schubert /* Try to do a load by the path */
434*7f2fe78bSCy Schubert if (!success && strchr(impl, '/'))
435*7f2fe78bSCy Schubert success = do_load_file(impl, 0, reqtypes, record);
436*7f2fe78bSCy Schubert if (!success) {
437*7f2fe78bSCy Schubert /* Try to do a load by the name */
438*7f2fe78bSCy Schubert tmp = string_aconcat(prefix, impl, suffix);
439*7f2fe78bSCy Schubert if (tmp) {
440*7f2fe78bSCy Schubert success = do_load_file(tmp, 0, reqtypes, record);
441*7f2fe78bSCy Schubert free(tmp);
442*7f2fe78bSCy Schubert }
443*7f2fe78bSCy Schubert }
444*7f2fe78bSCy Schubert } else {
445*7f2fe78bSCy Schubert /* NULL was passed, so we will use the dirname of
446*7f2fe78bSCy Schubert * the prefix to try and find any possible plugins */
447*7f2fe78bSCy Schubert tmp = strdup(prefix);
448*7f2fe78bSCy Schubert if (tmp) {
449*7f2fe78bSCy Schubert char *dname = strdup(dirname(tmp));
450*7f2fe78bSCy Schubert free(tmp);
451*7f2fe78bSCy Schubert
452*7f2fe78bSCy Schubert tmp = strdup(basename(prefix));
453*7f2fe78bSCy Schubert free(prefix);
454*7f2fe78bSCy Schubert prefix = tmp;
455*7f2fe78bSCy Schubert
456*7f2fe78bSCy Schubert if (dname && prefix) {
457*7f2fe78bSCy Schubert /* Attempt to find a module we are already linked to */
458*7f2fe78bSCy Schubert success = do_load_dir(dname, prefix, suffix, 1, reqtypes,
459*7f2fe78bSCy Schubert record);
460*7f2fe78bSCy Schubert if (!success) {
461*7f2fe78bSCy Schubert #ifdef DEFAULT_MODULE
462*7f2fe78bSCy Schubert /* Attempt to find the default module */
463*7f2fe78bSCy Schubert success = load_module(DEFAULT_MODULE, reqtypes, record);
464*7f2fe78bSCy Schubert if (!success)
465*7f2fe78bSCy Schubert #endif /* DEFAULT_MODULE */
466*7f2fe78bSCy Schubert /* Attempt to load any plugin (we're desperate) */
467*7f2fe78bSCy Schubert success = do_load_dir(dname, prefix, suffix, 0,
468*7f2fe78bSCy Schubert reqtypes, record);
469*7f2fe78bSCy Schubert }
470*7f2fe78bSCy Schubert }
471*7f2fe78bSCy Schubert
472*7f2fe78bSCy Schubert free(dname);
473*7f2fe78bSCy Schubert }
474*7f2fe78bSCy Schubert }
475*7f2fe78bSCy Schubert
476*7f2fe78bSCy Schubert free(suffix);
477*7f2fe78bSCy Schubert free(prefix);
478*7f2fe78bSCy Schubert #endif /* BUILTIN_MODULE */
479*7f2fe78bSCy Schubert return success;
480*7f2fe78bSCy Schubert }
481*7f2fe78bSCy Schubert
482*7f2fe78bSCy Schubert static verto_ev *
make_ev(verto_ctx * ctx,verto_callback * callback,verto_ev_type type,verto_ev_flag flags)483*7f2fe78bSCy Schubert make_ev(verto_ctx *ctx, verto_callback *callback,
484*7f2fe78bSCy Schubert verto_ev_type type, verto_ev_flag flags)
485*7f2fe78bSCy Schubert {
486*7f2fe78bSCy Schubert verto_ev *ev = NULL;
487*7f2fe78bSCy Schubert
488*7f2fe78bSCy Schubert if (!ctx || !callback)
489*7f2fe78bSCy Schubert return NULL;
490*7f2fe78bSCy Schubert
491*7f2fe78bSCy Schubert ev = vresize(NULL, sizeof(verto_ev));
492*7f2fe78bSCy Schubert if (ev) {
493*7f2fe78bSCy Schubert memset(ev, 0, sizeof(verto_ev));
494*7f2fe78bSCy Schubert ev->ctx = ctx;
495*7f2fe78bSCy Schubert ev->type = type;
496*7f2fe78bSCy Schubert ev->callback = callback;
497*7f2fe78bSCy Schubert ev->flags = flags;
498*7f2fe78bSCy Schubert }
499*7f2fe78bSCy Schubert
500*7f2fe78bSCy Schubert return ev;
501*7f2fe78bSCy Schubert }
502*7f2fe78bSCy Schubert
503*7f2fe78bSCy Schubert static void
push_ev(verto_ctx * ctx,verto_ev * ev)504*7f2fe78bSCy Schubert push_ev(verto_ctx *ctx, verto_ev *ev)
505*7f2fe78bSCy Schubert {
506*7f2fe78bSCy Schubert verto_ev *tmp;
507*7f2fe78bSCy Schubert
508*7f2fe78bSCy Schubert if (!ctx || !ev)
509*7f2fe78bSCy Schubert return;
510*7f2fe78bSCy Schubert
511*7f2fe78bSCy Schubert tmp = ctx->events;
512*7f2fe78bSCy Schubert ctx->events = ev;
513*7f2fe78bSCy Schubert ctx->events->next = tmp;
514*7f2fe78bSCy Schubert }
515*7f2fe78bSCy Schubert
516*7f2fe78bSCy Schubert static void
remove_ev(verto_ev ** origin,verto_ev * item)517*7f2fe78bSCy Schubert remove_ev(verto_ev **origin, verto_ev *item)
518*7f2fe78bSCy Schubert {
519*7f2fe78bSCy Schubert if (!origin || !*origin || !item)
520*7f2fe78bSCy Schubert return;
521*7f2fe78bSCy Schubert
522*7f2fe78bSCy Schubert if (*origin == item)
523*7f2fe78bSCy Schubert *origin = (*origin)->next;
524*7f2fe78bSCy Schubert else
525*7f2fe78bSCy Schubert remove_ev(&((*origin)->next), item);
526*7f2fe78bSCy Schubert }
527*7f2fe78bSCy Schubert
528*7f2fe78bSCy Schubert static void
signal_ignore(verto_ctx * ctx,verto_ev * ev)529*7f2fe78bSCy Schubert signal_ignore(verto_ctx *ctx, verto_ev *ev)
530*7f2fe78bSCy Schubert {
531*7f2fe78bSCy Schubert (void) ctx;
532*7f2fe78bSCy Schubert (void) ev;
533*7f2fe78bSCy Schubert }
534*7f2fe78bSCy Schubert
535*7f2fe78bSCy Schubert verto_ctx *
verto_new(const char * impl,verto_ev_type reqtypes)536*7f2fe78bSCy Schubert verto_new(const char *impl, verto_ev_type reqtypes)
537*7f2fe78bSCy Schubert {
538*7f2fe78bSCy Schubert module_record *mr = NULL;
539*7f2fe78bSCy Schubert
540*7f2fe78bSCy Schubert if (!load_module(impl, reqtypes, &mr))
541*7f2fe78bSCy Schubert return NULL;
542*7f2fe78bSCy Schubert
543*7f2fe78bSCy Schubert return verto_convert_module(mr->module, 0, NULL);
544*7f2fe78bSCy Schubert }
545*7f2fe78bSCy Schubert
546*7f2fe78bSCy Schubert verto_ctx *
verto_default(const char * impl,verto_ev_type reqtypes)547*7f2fe78bSCy Schubert verto_default(const char *impl, verto_ev_type reqtypes)
548*7f2fe78bSCy Schubert {
549*7f2fe78bSCy Schubert module_record *mr = NULL;
550*7f2fe78bSCy Schubert
551*7f2fe78bSCy Schubert if (!load_module(impl, reqtypes, &mr))
552*7f2fe78bSCy Schubert return NULL;
553*7f2fe78bSCy Schubert
554*7f2fe78bSCy Schubert return verto_convert_module(mr->module, 1, NULL);
555*7f2fe78bSCy Schubert }
556*7f2fe78bSCy Schubert
557*7f2fe78bSCy Schubert int
verto_set_default(const char * impl,verto_ev_type reqtypes)558*7f2fe78bSCy Schubert verto_set_default(const char *impl, verto_ev_type reqtypes)
559*7f2fe78bSCy Schubert {
560*7f2fe78bSCy Schubert module_record *mr;
561*7f2fe78bSCy Schubert
562*7f2fe78bSCy Schubert mutex_lock(&loaded_modules_mutex);
563*7f2fe78bSCy Schubert if (loaded_modules || !impl) {
564*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
565*7f2fe78bSCy Schubert return 0;
566*7f2fe78bSCy Schubert }
567*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
568*7f2fe78bSCy Schubert
569*7f2fe78bSCy Schubert return load_module(impl, reqtypes, &mr);
570*7f2fe78bSCy Schubert }
571*7f2fe78bSCy Schubert
572*7f2fe78bSCy Schubert int
verto_set_allocator(void * (* resize)(void * mem,size_t size),int hierarchical)573*7f2fe78bSCy Schubert verto_set_allocator(void *(*resize)(void *mem, size_t size),
574*7f2fe78bSCy Schubert int hierarchical)
575*7f2fe78bSCy Schubert {
576*7f2fe78bSCy Schubert if (resize_cb || !resize)
577*7f2fe78bSCy Schubert return 0;
578*7f2fe78bSCy Schubert resize_cb = resize;
579*7f2fe78bSCy Schubert resize_cb_hierarchical = hierarchical;
580*7f2fe78bSCy Schubert return 1;
581*7f2fe78bSCy Schubert }
582*7f2fe78bSCy Schubert
583*7f2fe78bSCy Schubert void
verto_free(verto_ctx * ctx)584*7f2fe78bSCy Schubert verto_free(verto_ctx *ctx)
585*7f2fe78bSCy Schubert {
586*7f2fe78bSCy Schubert if (!ctx)
587*7f2fe78bSCy Schubert return;
588*7f2fe78bSCy Schubert
589*7f2fe78bSCy Schubert ctx->ref = ctx->ref > 0 ? ctx->ref - 1 : 0;
590*7f2fe78bSCy Schubert if (ctx->ref > 0)
591*7f2fe78bSCy Schubert return;
592*7f2fe78bSCy Schubert
593*7f2fe78bSCy Schubert /* Cancel all pending events */
594*7f2fe78bSCy Schubert while (ctx->events)
595*7f2fe78bSCy Schubert verto_del(ctx->events);
596*7f2fe78bSCy Schubert
597*7f2fe78bSCy Schubert /* Free the private */
598*7f2fe78bSCy Schubert if (!ctx->deflt || !ctx->module->funcs->ctx_default)
599*7f2fe78bSCy Schubert ctx->module->funcs->ctx_free(ctx->ctx);
600*7f2fe78bSCy Schubert
601*7f2fe78bSCy Schubert vfree(ctx);
602*7f2fe78bSCy Schubert }
603*7f2fe78bSCy Schubert
604*7f2fe78bSCy Schubert void
verto_cleanup(void)605*7f2fe78bSCy Schubert verto_cleanup(void)
606*7f2fe78bSCy Schubert {
607*7f2fe78bSCy Schubert module_record *record;
608*7f2fe78bSCy Schubert
609*7f2fe78bSCy Schubert mutex_lock(&loaded_modules_mutex);
610*7f2fe78bSCy Schubert
611*7f2fe78bSCy Schubert for (record = loaded_modules; record; record = record->next) {
612*7f2fe78bSCy Schubert module_close(record->dll);
613*7f2fe78bSCy Schubert free(record->filename);
614*7f2fe78bSCy Schubert }
615*7f2fe78bSCy Schubert
616*7f2fe78bSCy Schubert vfree(loaded_modules);
617*7f2fe78bSCy Schubert loaded_modules = NULL;
618*7f2fe78bSCy Schubert
619*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
620*7f2fe78bSCy Schubert mutex_destroy(&loaded_modules_mutex);
621*7f2fe78bSCy Schubert }
622*7f2fe78bSCy Schubert
623*7f2fe78bSCy Schubert void
verto_run(verto_ctx * ctx)624*7f2fe78bSCy Schubert verto_run(verto_ctx *ctx)
625*7f2fe78bSCy Schubert {
626*7f2fe78bSCy Schubert if (!ctx)
627*7f2fe78bSCy Schubert return;
628*7f2fe78bSCy Schubert
629*7f2fe78bSCy Schubert if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run)
630*7f2fe78bSCy Schubert ctx->module->funcs->ctx_run(ctx->ctx);
631*7f2fe78bSCy Schubert else {
632*7f2fe78bSCy Schubert while (!ctx->exit)
633*7f2fe78bSCy Schubert ctx->module->funcs->ctx_run_once(ctx->ctx);
634*7f2fe78bSCy Schubert ctx->exit = 0;
635*7f2fe78bSCy Schubert }
636*7f2fe78bSCy Schubert }
637*7f2fe78bSCy Schubert
638*7f2fe78bSCy Schubert void
verto_run_once(verto_ctx * ctx)639*7f2fe78bSCy Schubert verto_run_once(verto_ctx *ctx)
640*7f2fe78bSCy Schubert {
641*7f2fe78bSCy Schubert if (!ctx)
642*7f2fe78bSCy Schubert return;
643*7f2fe78bSCy Schubert ctx->module->funcs->ctx_run_once(ctx->ctx);
644*7f2fe78bSCy Schubert }
645*7f2fe78bSCy Schubert
646*7f2fe78bSCy Schubert void
verto_break(verto_ctx * ctx)647*7f2fe78bSCy Schubert verto_break(verto_ctx *ctx)
648*7f2fe78bSCy Schubert {
649*7f2fe78bSCy Schubert if (!ctx)
650*7f2fe78bSCy Schubert return;
651*7f2fe78bSCy Schubert
652*7f2fe78bSCy Schubert if (ctx->module->funcs->ctx_break && ctx->module->funcs->ctx_run)
653*7f2fe78bSCy Schubert ctx->module->funcs->ctx_break(ctx->ctx);
654*7f2fe78bSCy Schubert else
655*7f2fe78bSCy Schubert ctx->exit = 1;
656*7f2fe78bSCy Schubert }
657*7f2fe78bSCy Schubert
658*7f2fe78bSCy Schubert int
verto_reinitialize(verto_ctx * ctx)659*7f2fe78bSCy Schubert verto_reinitialize(verto_ctx *ctx)
660*7f2fe78bSCy Schubert {
661*7f2fe78bSCy Schubert verto_ev *tmp, *next;
662*7f2fe78bSCy Schubert int error = 1;
663*7f2fe78bSCy Schubert
664*7f2fe78bSCy Schubert if (!ctx)
665*7f2fe78bSCy Schubert return 0;
666*7f2fe78bSCy Schubert
667*7f2fe78bSCy Schubert /* Delete all events, but keep around the forkable ev structs */
668*7f2fe78bSCy Schubert for (tmp = ctx->events; tmp; tmp = next) {
669*7f2fe78bSCy Schubert next = tmp->next;
670*7f2fe78bSCy Schubert
671*7f2fe78bSCy Schubert if (tmp->flags & VERTO_EV_FLAG_REINITIABLE)
672*7f2fe78bSCy Schubert ctx->module->funcs->ctx_del(ctx->ctx, tmp, tmp->ev);
673*7f2fe78bSCy Schubert else
674*7f2fe78bSCy Schubert verto_del(tmp);
675*7f2fe78bSCy Schubert }
676*7f2fe78bSCy Schubert
677*7f2fe78bSCy Schubert /* Reinit the loop */
678*7f2fe78bSCy Schubert if (ctx->module->funcs->ctx_reinitialize)
679*7f2fe78bSCy Schubert ctx->module->funcs->ctx_reinitialize(ctx->ctx);
680*7f2fe78bSCy Schubert
681*7f2fe78bSCy Schubert /* Recreate events that were marked forkable */
682*7f2fe78bSCy Schubert for (tmp = ctx->events; tmp; tmp = tmp->next) {
683*7f2fe78bSCy Schubert tmp->actual = make_actual(tmp->flags);
684*7f2fe78bSCy Schubert tmp->ev = ctx->module->funcs->ctx_add(ctx->ctx, tmp, &tmp->actual);
685*7f2fe78bSCy Schubert if (!tmp->ev)
686*7f2fe78bSCy Schubert error = 0;
687*7f2fe78bSCy Schubert }
688*7f2fe78bSCy Schubert
689*7f2fe78bSCy Schubert return error;
690*7f2fe78bSCy Schubert }
691*7f2fe78bSCy Schubert
692*7f2fe78bSCy Schubert #define doadd(ev, set, type) \
693*7f2fe78bSCy Schubert ev = make_ev(ctx, callback, type, flags); \
694*7f2fe78bSCy Schubert if (ev) { \
695*7f2fe78bSCy Schubert set; \
696*7f2fe78bSCy Schubert ev->actual = make_actual(ev->flags); \
697*7f2fe78bSCy Schubert ev->ev = ctx->module->funcs->ctx_add(ctx->ctx, ev, &ev->actual); \
698*7f2fe78bSCy Schubert if (!ev->ev) { \
699*7f2fe78bSCy Schubert vfree(ev); \
700*7f2fe78bSCy Schubert return NULL; \
701*7f2fe78bSCy Schubert } \
702*7f2fe78bSCy Schubert push_ev(ctx, ev); \
703*7f2fe78bSCy Schubert }
704*7f2fe78bSCy Schubert
705*7f2fe78bSCy Schubert verto_ev *
verto_add_io(verto_ctx * ctx,verto_ev_flag flags,verto_callback * callback,int fd)706*7f2fe78bSCy Schubert verto_add_io(verto_ctx *ctx, verto_ev_flag flags,
707*7f2fe78bSCy Schubert verto_callback *callback, int fd)
708*7f2fe78bSCy Schubert {
709*7f2fe78bSCy Schubert verto_ev *ev;
710*7f2fe78bSCy Schubert
711*7f2fe78bSCy Schubert if (fd < 0 || !(flags & (VERTO_EV_FLAG_IO_READ | VERTO_EV_FLAG_IO_WRITE)))
712*7f2fe78bSCy Schubert return NULL;
713*7f2fe78bSCy Schubert
714*7f2fe78bSCy Schubert doadd(ev, ev->option.io.fd = fd, VERTO_EV_TYPE_IO);
715*7f2fe78bSCy Schubert return ev;
716*7f2fe78bSCy Schubert }
717*7f2fe78bSCy Schubert
718*7f2fe78bSCy Schubert verto_ev *
verto_add_timeout(verto_ctx * ctx,verto_ev_flag flags,verto_callback * callback,time_t interval)719*7f2fe78bSCy Schubert verto_add_timeout(verto_ctx *ctx, verto_ev_flag flags,
720*7f2fe78bSCy Schubert verto_callback *callback, time_t interval)
721*7f2fe78bSCy Schubert {
722*7f2fe78bSCy Schubert verto_ev *ev;
723*7f2fe78bSCy Schubert doadd(ev, ev->option.interval = interval, VERTO_EV_TYPE_TIMEOUT);
724*7f2fe78bSCy Schubert return ev;
725*7f2fe78bSCy Schubert }
726*7f2fe78bSCy Schubert
727*7f2fe78bSCy Schubert verto_ev *
verto_add_idle(verto_ctx * ctx,verto_ev_flag flags,verto_callback * callback)728*7f2fe78bSCy Schubert verto_add_idle(verto_ctx *ctx, verto_ev_flag flags,
729*7f2fe78bSCy Schubert verto_callback *callback)
730*7f2fe78bSCy Schubert {
731*7f2fe78bSCy Schubert verto_ev *ev;
732*7f2fe78bSCy Schubert doadd(ev,, VERTO_EV_TYPE_IDLE);
733*7f2fe78bSCy Schubert return ev;
734*7f2fe78bSCy Schubert }
735*7f2fe78bSCy Schubert
736*7f2fe78bSCy Schubert verto_ev *
verto_add_signal(verto_ctx * ctx,verto_ev_flag flags,verto_callback * callback,int signal)737*7f2fe78bSCy Schubert verto_add_signal(verto_ctx *ctx, verto_ev_flag flags,
738*7f2fe78bSCy Schubert verto_callback *callback, int signal)
739*7f2fe78bSCy Schubert {
740*7f2fe78bSCy Schubert verto_ev *ev;
741*7f2fe78bSCy Schubert
742*7f2fe78bSCy Schubert if (signal < 0)
743*7f2fe78bSCy Schubert return NULL;
744*7f2fe78bSCy Schubert #ifndef WIN32
745*7f2fe78bSCy Schubert if (signal == SIGCHLD)
746*7f2fe78bSCy Schubert return NULL;
747*7f2fe78bSCy Schubert #endif
748*7f2fe78bSCy Schubert if (callback == VERTO_SIG_IGN) {
749*7f2fe78bSCy Schubert callback = signal_ignore;
750*7f2fe78bSCy Schubert if (!(flags & VERTO_EV_FLAG_PERSIST))
751*7f2fe78bSCy Schubert return NULL;
752*7f2fe78bSCy Schubert }
753*7f2fe78bSCy Schubert doadd(ev, ev->option.signal = signal, VERTO_EV_TYPE_SIGNAL);
754*7f2fe78bSCy Schubert return ev;
755*7f2fe78bSCy Schubert }
756*7f2fe78bSCy Schubert
757*7f2fe78bSCy Schubert verto_ev *
verto_add_child(verto_ctx * ctx,verto_ev_flag flags,verto_callback * callback,verto_proc proc)758*7f2fe78bSCy Schubert verto_add_child(verto_ctx *ctx, verto_ev_flag flags,
759*7f2fe78bSCy Schubert verto_callback *callback, verto_proc proc)
760*7f2fe78bSCy Schubert {
761*7f2fe78bSCy Schubert verto_ev *ev;
762*7f2fe78bSCy Schubert
763*7f2fe78bSCy Schubert if (flags & VERTO_EV_FLAG_PERSIST) /* persist makes no sense */
764*7f2fe78bSCy Schubert return NULL;
765*7f2fe78bSCy Schubert #ifdef WIN32
766*7f2fe78bSCy Schubert if (proc == NULL)
767*7f2fe78bSCy Schubert #else
768*7f2fe78bSCy Schubert if (proc < 1)
769*7f2fe78bSCy Schubert #endif
770*7f2fe78bSCy Schubert return NULL;
771*7f2fe78bSCy Schubert doadd(ev, ev->option.child.proc = proc, VERTO_EV_TYPE_CHILD);
772*7f2fe78bSCy Schubert return ev;
773*7f2fe78bSCy Schubert }
774*7f2fe78bSCy Schubert
775*7f2fe78bSCy Schubert void
verto_set_private(verto_ev * ev,void * priv,verto_callback * free)776*7f2fe78bSCy Schubert verto_set_private(verto_ev *ev, void *priv, verto_callback *free)
777*7f2fe78bSCy Schubert {
778*7f2fe78bSCy Schubert if (!ev)
779*7f2fe78bSCy Schubert return;
780*7f2fe78bSCy Schubert if (ev->onfree && free)
781*7f2fe78bSCy Schubert ev->onfree(ev->ctx, ev);
782*7f2fe78bSCy Schubert ev->priv = priv;
783*7f2fe78bSCy Schubert ev->onfree = free;
784*7f2fe78bSCy Schubert }
785*7f2fe78bSCy Schubert
786*7f2fe78bSCy Schubert void *
verto_get_private(const verto_ev * ev)787*7f2fe78bSCy Schubert verto_get_private(const verto_ev *ev)
788*7f2fe78bSCy Schubert {
789*7f2fe78bSCy Schubert return ev->priv;
790*7f2fe78bSCy Schubert }
791*7f2fe78bSCy Schubert
792*7f2fe78bSCy Schubert verto_ev_type
verto_get_type(const verto_ev * ev)793*7f2fe78bSCy Schubert verto_get_type(const verto_ev *ev)
794*7f2fe78bSCy Schubert {
795*7f2fe78bSCy Schubert return ev->type;
796*7f2fe78bSCy Schubert }
797*7f2fe78bSCy Schubert
798*7f2fe78bSCy Schubert verto_ev_flag
verto_get_flags(const verto_ev * ev)799*7f2fe78bSCy Schubert verto_get_flags(const verto_ev *ev)
800*7f2fe78bSCy Schubert {
801*7f2fe78bSCy Schubert return ev->flags;
802*7f2fe78bSCy Schubert }
803*7f2fe78bSCy Schubert
804*7f2fe78bSCy Schubert void
verto_set_flags(verto_ev * ev,verto_ev_flag flags)805*7f2fe78bSCy Schubert verto_set_flags(verto_ev *ev, verto_ev_flag flags)
806*7f2fe78bSCy Schubert {
807*7f2fe78bSCy Schubert if (!ev)
808*7f2fe78bSCy Schubert return;
809*7f2fe78bSCy Schubert
810*7f2fe78bSCy Schubert /* No modification is needed, so do nothing. */
811*7f2fe78bSCy Schubert if (MUTABLE(ev->flags) == MUTABLE(flags))
812*7f2fe78bSCy Schubert return;
813*7f2fe78bSCy Schubert
814*7f2fe78bSCy Schubert ev->flags &= ~_VERTO_EV_FLAG_MUTABLE_MASK;
815*7f2fe78bSCy Schubert ev->flags |= MUTABLE(flags);
816*7f2fe78bSCy Schubert
817*7f2fe78bSCy Schubert /* If setting flags isn't supported, just rebuild the event */
818*7f2fe78bSCy Schubert if (!ev->ctx->module->funcs->ctx_set_flags) {
819*7f2fe78bSCy Schubert ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
820*7f2fe78bSCy Schubert ev->actual = make_actual(ev->flags);
821*7f2fe78bSCy Schubert ev->ev = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual);
822*7f2fe78bSCy Schubert assert(ev->ev); /* Here is the main reason why modules should */
823*7f2fe78bSCy Schubert return; /* implement set_flags(): we cannot fail gracefully. */
824*7f2fe78bSCy Schubert }
825*7f2fe78bSCy Schubert
826*7f2fe78bSCy Schubert ev->actual &= ~_VERTO_EV_FLAG_MUTABLE_MASK;
827*7f2fe78bSCy Schubert ev->actual |= MUTABLE(flags);
828*7f2fe78bSCy Schubert ev->ctx->module->funcs->ctx_set_flags(ev->ctx->ctx, ev, ev->ev);
829*7f2fe78bSCy Schubert }
830*7f2fe78bSCy Schubert
831*7f2fe78bSCy Schubert int
verto_get_fd(const verto_ev * ev)832*7f2fe78bSCy Schubert verto_get_fd(const verto_ev *ev)
833*7f2fe78bSCy Schubert {
834*7f2fe78bSCy Schubert if (ev && (ev->type == VERTO_EV_TYPE_IO))
835*7f2fe78bSCy Schubert return ev->option.io.fd;
836*7f2fe78bSCy Schubert return -1;
837*7f2fe78bSCy Schubert }
838*7f2fe78bSCy Schubert
839*7f2fe78bSCy Schubert verto_ev_flag
verto_get_fd_state(const verto_ev * ev)840*7f2fe78bSCy Schubert verto_get_fd_state(const verto_ev *ev)
841*7f2fe78bSCy Schubert {
842*7f2fe78bSCy Schubert return ev->option.io.state;
843*7f2fe78bSCy Schubert }
844*7f2fe78bSCy Schubert
845*7f2fe78bSCy Schubert time_t
verto_get_interval(const verto_ev * ev)846*7f2fe78bSCy Schubert verto_get_interval(const verto_ev *ev)
847*7f2fe78bSCy Schubert {
848*7f2fe78bSCy Schubert if (ev && (ev->type == VERTO_EV_TYPE_TIMEOUT))
849*7f2fe78bSCy Schubert return ev->option.interval;
850*7f2fe78bSCy Schubert return 0;
851*7f2fe78bSCy Schubert }
852*7f2fe78bSCy Schubert
853*7f2fe78bSCy Schubert int
verto_get_signal(const verto_ev * ev)854*7f2fe78bSCy Schubert verto_get_signal(const verto_ev *ev)
855*7f2fe78bSCy Schubert {
856*7f2fe78bSCy Schubert if (ev && (ev->type == VERTO_EV_TYPE_SIGNAL))
857*7f2fe78bSCy Schubert return ev->option.signal;
858*7f2fe78bSCy Schubert return -1;
859*7f2fe78bSCy Schubert }
860*7f2fe78bSCy Schubert
861*7f2fe78bSCy Schubert verto_proc
verto_get_proc(const verto_ev * ev)862*7f2fe78bSCy Schubert verto_get_proc(const verto_ev *ev) {
863*7f2fe78bSCy Schubert if (ev && ev->type == VERTO_EV_TYPE_CHILD)
864*7f2fe78bSCy Schubert return ev->option.child.proc;
865*7f2fe78bSCy Schubert return (verto_proc) 0;
866*7f2fe78bSCy Schubert }
867*7f2fe78bSCy Schubert
868*7f2fe78bSCy Schubert verto_proc_status
verto_get_proc_status(const verto_ev * ev)869*7f2fe78bSCy Schubert verto_get_proc_status(const verto_ev *ev)
870*7f2fe78bSCy Schubert {
871*7f2fe78bSCy Schubert return ev->option.child.status;
872*7f2fe78bSCy Schubert }
873*7f2fe78bSCy Schubert
874*7f2fe78bSCy Schubert verto_ctx *
verto_get_ctx(const verto_ev * ev)875*7f2fe78bSCy Schubert verto_get_ctx(const verto_ev *ev)
876*7f2fe78bSCy Schubert {
877*7f2fe78bSCy Schubert return ev->ctx;
878*7f2fe78bSCy Schubert }
879*7f2fe78bSCy Schubert
880*7f2fe78bSCy Schubert void
verto_del(verto_ev * ev)881*7f2fe78bSCy Schubert verto_del(verto_ev *ev)
882*7f2fe78bSCy Schubert {
883*7f2fe78bSCy Schubert if (!ev)
884*7f2fe78bSCy Schubert return;
885*7f2fe78bSCy Schubert
886*7f2fe78bSCy Schubert /* If the event is freed in the callback, we just set a flag so that
887*7f2fe78bSCy Schubert * verto_fire() can actually do the delete when the callback completes.
888*7f2fe78bSCy Schubert *
889*7f2fe78bSCy Schubert * If we don't do this, than verto_fire() will access freed memory. */
890*7f2fe78bSCy Schubert if (ev->depth > 0) {
891*7f2fe78bSCy Schubert ev->deleted = 1;
892*7f2fe78bSCy Schubert return;
893*7f2fe78bSCy Schubert }
894*7f2fe78bSCy Schubert
895*7f2fe78bSCy Schubert if (ev->onfree)
896*7f2fe78bSCy Schubert ev->onfree(ev->ctx, ev);
897*7f2fe78bSCy Schubert ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
898*7f2fe78bSCy Schubert remove_ev(&(ev->ctx->events), ev);
899*7f2fe78bSCy Schubert
900*7f2fe78bSCy Schubert if ((ev->type == VERTO_EV_TYPE_IO) &&
901*7f2fe78bSCy Schubert (ev->flags & VERTO_EV_FLAG_IO_CLOSE_FD) &&
902*7f2fe78bSCy Schubert !(ev->actual & VERTO_EV_FLAG_IO_CLOSE_FD))
903*7f2fe78bSCy Schubert close(ev->option.io.fd);
904*7f2fe78bSCy Schubert
905*7f2fe78bSCy Schubert vfree(ev);
906*7f2fe78bSCy Schubert }
907*7f2fe78bSCy Schubert
908*7f2fe78bSCy Schubert verto_ev_type
verto_get_supported_types(verto_ctx * ctx)909*7f2fe78bSCy Schubert verto_get_supported_types(verto_ctx *ctx)
910*7f2fe78bSCy Schubert {
911*7f2fe78bSCy Schubert return ctx->module->types;
912*7f2fe78bSCy Schubert }
913*7f2fe78bSCy Schubert
914*7f2fe78bSCy Schubert /*** THE FOLLOWING ARE FOR IMPLEMENTATION MODULES ONLY ***/
915*7f2fe78bSCy Schubert
916*7f2fe78bSCy Schubert verto_ctx *
verto_convert_module(const verto_module * module,int deflt,verto_mod_ctx * mctx)917*7f2fe78bSCy Schubert verto_convert_module(const verto_module *module, int deflt, verto_mod_ctx *mctx)
918*7f2fe78bSCy Schubert {
919*7f2fe78bSCy Schubert verto_ctx *ctx = NULL;
920*7f2fe78bSCy Schubert module_record *mr;
921*7f2fe78bSCy Schubert
922*7f2fe78bSCy Schubert if (!module)
923*7f2fe78bSCy Schubert return NULL;
924*7f2fe78bSCy Schubert
925*7f2fe78bSCy Schubert if (deflt) {
926*7f2fe78bSCy Schubert mutex_lock(&loaded_modules_mutex);
927*7f2fe78bSCy Schubert for (mr = loaded_modules ; mr ; mr = mr->next) {
928*7f2fe78bSCy Schubert verto_ctx *tmp;
929*7f2fe78bSCy Schubert if (mr->module == module && mr->defctx) {
930*7f2fe78bSCy Schubert if (mctx)
931*7f2fe78bSCy Schubert module->funcs->ctx_free(mctx);
932*7f2fe78bSCy Schubert tmp = mr->defctx;
933*7f2fe78bSCy Schubert tmp->ref++;
934*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
935*7f2fe78bSCy Schubert return tmp;
936*7f2fe78bSCy Schubert }
937*7f2fe78bSCy Schubert }
938*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
939*7f2fe78bSCy Schubert }
940*7f2fe78bSCy Schubert
941*7f2fe78bSCy Schubert if (!mctx) {
942*7f2fe78bSCy Schubert mctx = deflt
943*7f2fe78bSCy Schubert ? (module->funcs->ctx_default
944*7f2fe78bSCy Schubert ? module->funcs->ctx_default()
945*7f2fe78bSCy Schubert : module->funcs->ctx_new())
946*7f2fe78bSCy Schubert : module->funcs->ctx_new();
947*7f2fe78bSCy Schubert if (!mctx)
948*7f2fe78bSCy Schubert goto error;
949*7f2fe78bSCy Schubert }
950*7f2fe78bSCy Schubert
951*7f2fe78bSCy Schubert ctx = vresize(NULL, sizeof(verto_ctx));
952*7f2fe78bSCy Schubert if (!ctx)
953*7f2fe78bSCy Schubert goto error;
954*7f2fe78bSCy Schubert memset(ctx, 0, sizeof(verto_ctx));
955*7f2fe78bSCy Schubert
956*7f2fe78bSCy Schubert ctx->ref = 1;
957*7f2fe78bSCy Schubert ctx->ctx = mctx;
958*7f2fe78bSCy Schubert ctx->module = module;
959*7f2fe78bSCy Schubert ctx->deflt = deflt;
960*7f2fe78bSCy Schubert
961*7f2fe78bSCy Schubert if (deflt) {
962*7f2fe78bSCy Schubert module_record **tmp;
963*7f2fe78bSCy Schubert
964*7f2fe78bSCy Schubert mutex_lock(&loaded_modules_mutex);
965*7f2fe78bSCy Schubert tmp = &loaded_modules;
966*7f2fe78bSCy Schubert for (mr = loaded_modules ; mr ; mr = mr->next) {
967*7f2fe78bSCy Schubert if (mr->module == module) {
968*7f2fe78bSCy Schubert assert(mr->defctx == NULL);
969*7f2fe78bSCy Schubert mr->defctx = ctx;
970*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
971*7f2fe78bSCy Schubert return ctx;
972*7f2fe78bSCy Schubert }
973*7f2fe78bSCy Schubert
974*7f2fe78bSCy Schubert if (!mr->next) {
975*7f2fe78bSCy Schubert tmp = &mr->next;
976*7f2fe78bSCy Schubert break;
977*7f2fe78bSCy Schubert }
978*7f2fe78bSCy Schubert }
979*7f2fe78bSCy Schubert mutex_unlock(&loaded_modules_mutex);
980*7f2fe78bSCy Schubert
981*7f2fe78bSCy Schubert *tmp = vresize(NULL, sizeof(module_record));
982*7f2fe78bSCy Schubert if (!*tmp) {
983*7f2fe78bSCy Schubert vfree(ctx);
984*7f2fe78bSCy Schubert goto error;
985*7f2fe78bSCy Schubert }
986*7f2fe78bSCy Schubert
987*7f2fe78bSCy Schubert memset(*tmp, 0, sizeof(module_record));
988*7f2fe78bSCy Schubert (*tmp)->defctx = ctx;
989*7f2fe78bSCy Schubert (*tmp)->module = module;
990*7f2fe78bSCy Schubert }
991*7f2fe78bSCy Schubert
992*7f2fe78bSCy Schubert return ctx;
993*7f2fe78bSCy Schubert
994*7f2fe78bSCy Schubert error:
995*7f2fe78bSCy Schubert if (mctx)
996*7f2fe78bSCy Schubert module->funcs->ctx_free(mctx);
997*7f2fe78bSCy Schubert return NULL;
998*7f2fe78bSCy Schubert }
999*7f2fe78bSCy Schubert
1000*7f2fe78bSCy Schubert void
verto_fire(verto_ev * ev)1001*7f2fe78bSCy Schubert verto_fire(verto_ev *ev)
1002*7f2fe78bSCy Schubert {
1003*7f2fe78bSCy Schubert void *priv;
1004*7f2fe78bSCy Schubert
1005*7f2fe78bSCy Schubert ev->depth++;
1006*7f2fe78bSCy Schubert ev->callback(ev->ctx, ev);
1007*7f2fe78bSCy Schubert ev->depth--;
1008*7f2fe78bSCy Schubert
1009*7f2fe78bSCy Schubert if (ev->depth == 0) {
1010*7f2fe78bSCy Schubert if (!(ev->flags & VERTO_EV_FLAG_PERSIST) || ev->deleted)
1011*7f2fe78bSCy Schubert verto_del(ev);
1012*7f2fe78bSCy Schubert else {
1013*7f2fe78bSCy Schubert if (!(ev->actual & VERTO_EV_FLAG_PERSIST)) {
1014*7f2fe78bSCy Schubert ev->actual = make_actual(ev->flags);
1015*7f2fe78bSCy Schubert priv = ev->ctx->module->funcs->ctx_add(ev->ctx->ctx, ev, &ev->actual);
1016*7f2fe78bSCy Schubert assert(priv); /* TODO: create an error callback */
1017*7f2fe78bSCy Schubert ev->ctx->module->funcs->ctx_del(ev->ctx->ctx, ev, ev->ev);
1018*7f2fe78bSCy Schubert ev->ev = priv;
1019*7f2fe78bSCy Schubert }
1020*7f2fe78bSCy Schubert
1021*7f2fe78bSCy Schubert if (ev->type == VERTO_EV_TYPE_IO)
1022*7f2fe78bSCy Schubert ev->option.io.state = VERTO_EV_FLAG_NONE;
1023*7f2fe78bSCy Schubert if (ev->type == VERTO_EV_TYPE_CHILD)
1024*7f2fe78bSCy Schubert ev->option.child.status = 0;
1025*7f2fe78bSCy Schubert }
1026*7f2fe78bSCy Schubert }
1027*7f2fe78bSCy Schubert }
1028*7f2fe78bSCy Schubert
1029*7f2fe78bSCy Schubert void
verto_set_proc_status(verto_ev * ev,verto_proc_status status)1030*7f2fe78bSCy Schubert verto_set_proc_status(verto_ev *ev, verto_proc_status status)
1031*7f2fe78bSCy Schubert {
1032*7f2fe78bSCy Schubert if (ev && ev->type == VERTO_EV_TYPE_CHILD)
1033*7f2fe78bSCy Schubert ev->option.child.status = status;
1034*7f2fe78bSCy Schubert }
1035*7f2fe78bSCy Schubert
1036*7f2fe78bSCy Schubert void
verto_set_fd_state(verto_ev * ev,verto_ev_flag state)1037*7f2fe78bSCy Schubert verto_set_fd_state(verto_ev *ev, verto_ev_flag state)
1038*7f2fe78bSCy Schubert {
1039*7f2fe78bSCy Schubert /* Filter out only the io flags */
1040*7f2fe78bSCy Schubert state = state & (VERTO_EV_FLAG_IO_READ |
1041*7f2fe78bSCy Schubert VERTO_EV_FLAG_IO_WRITE |
1042*7f2fe78bSCy Schubert VERTO_EV_FLAG_IO_ERROR);
1043*7f2fe78bSCy Schubert
1044*7f2fe78bSCy Schubert /* Don't report read/write if the socket is closed */
1045*7f2fe78bSCy Schubert if (state & VERTO_EV_FLAG_IO_ERROR)
1046*7f2fe78bSCy Schubert state = VERTO_EV_FLAG_IO_ERROR;
1047*7f2fe78bSCy Schubert
1048*7f2fe78bSCy Schubert if (ev && ev->type == VERTO_EV_TYPE_IO)
1049*7f2fe78bSCy Schubert ev->option.io.state = state;
1050*7f2fe78bSCy Schubert }
1051