00001
00002
00003
00004
00005
00006
00007
00008
00009
00010
00011
00012
00013
00014
00015
00016
00017
00018
00019
00027 #include "engines_int.h"
00028
00029 #include <ltdl.h>
00030 #include <stdio.h>
00031 #include <string.h>
00032
00033 RCSTAG("@(#)$Id: event_init.c,v 1.28 2005/12/18 00:15:11 klmitch Exp $");
00034
00040 #define FNAME_BUF 1024
00041
00048 #define MODULE_INIT "engine_mod_init"
00049
00056 #define MODULE_ENGINE "engine_module"
00057
00064 #define VAR_MODULES PACKAGE_TARNAME ".modules"
00065
00072 #define VAR_LIBPATH PACKAGE_TARNAME ".libpath"
00073
00080 #define VAR_MODLIST PACKAGE_TARNAME ".modlist"
00081
00094 #define confdir(fname) SYSCONFDIR "/" PACKAGE_TARNAME "/" fname ".tc"
00095
00107 #define homedir(fname) "~/." fname ".tc"
00108
00115 static _ev_attr_t const _ev__defattr = {
00116 EV_ATTR_MAGIC,
00117
00118
00119 (confdir(PACKAGE_TARNAME) ":" homedir(PACKAGE_TARNAME) ":"
00120 confdir("%p") ":" homedir("%p")),
00121
00122
00123 PKGLIBDIR,
00124
00125
00126 "select",
00127
00128 0, 0, 0
00129 };
00130 const _ev_attr_t const *_ev_defattr = &_ev__defattr;
00131
00151 static int
00152 new_modvar(treeconf_ctx_t *ctx, treeconf_node_t *parent, treeconf_str_t *name,
00153 int elements)
00154 {
00155
00156 return !(tn_type(parent) & TC_NODETYPE_IMPLICIT) && elements == 2;
00157 }
00158
00188 static ev_err_t
00189 engine_load(ev_ctx_t *ctx, treeconf_str_t *path, int path_cnt,
00190 treeconf_str_t *module, ev_flags_t *flag_p)
00191 {
00192 ev_err_t err = 0;
00193 ev_engine_t *eng;
00194 ev_flags_t init_flags = 0;
00195 const char *mname, *fls = 0;
00196 int mname_len, fl_len = 0, cmp;
00197
00198 ev_trace();
00199
00200
00201 mname = ts_string(module, 0);
00202 for (mname_len = ts_length(module, 0); mname_len; mname_len--)
00203 if (mname[mname_len - 1] == ':') {
00204 fls = mname + mname_len;
00205 fl_len = ts_length(module, 0) - mname_len;
00206 break;
00207 }
00208
00209 if (mname_len)
00210 mname_len--;
00211 else
00212 mname_len = ts_length(module, 0);
00213
00214
00215 if (fls)
00216 while (fl_len--)
00217 switch (*fls++) {
00218 case 's':
00219 init_flags |= EV_ENGINE_SOCKET;
00220 break;
00221 case 'i':
00222 init_flags |= EV_ENGINE_SIGNAL;
00223 break;
00224 case 't':
00225 init_flags |= EV_ENGINE_TIMER;
00226 break;
00227 default:
00228 break;
00229 }
00230 else
00231 init_flags = EV_ENGINE_COMPMASK;
00232
00233 init_flags &= ~*flag_p;
00234
00235 if (!init_flags)
00236 ev_return(0);
00237
00238
00239 for (eng = ctx->ec_engine; eng; eng = eng->eng_list.el_next)
00240 if (!(cmp = strncmp(eng->eng_name, mname, mname_len)) &&
00241 strlen(eng->eng_name) == mname_len)
00242 break;
00243 else if (cmp >= 0) {
00244 eng = 0;
00245 break;
00246 }
00247
00248 if (eng && (eng->eng_runfl & EV_ENGINE_RUNNING))
00249 ev_return(0);
00250 else if (!eng) {
00251 ev_modinit_t modinit;
00252 lt_dlhandle handle = 0;
00253 char fname[FNAME_BUF];
00254 int i;
00255
00256 for (i = 0; i < path_cnt; i++) {
00257 if (ts_length(path, i) + mname_len + 2 > FNAME_BUF)
00258 continue;
00259
00260 sprintf(fname, "%.*s/%.*s", ts_length(path, i), ts_string(path, i),
00261 mname_len, mname);
00262
00263 _ev_debug(EVAS_LOG, __FILE__, __LINE__, _gca_func,
00264 "Attempting to load engine module %s...", fname);
00265
00266
00267 if (!(handle = lt_dlopenext(fname))) {
00268 _ev_debug(EVAS_LOG, __FILE__, __LINE__, _gca_func,
00269 "Can't load %s: %s", fname, lt_dlerror());
00270 continue;
00271 }
00272
00273
00274
00275
00276 if ((modinit = (ev_modinit_t)lt_dlsym(handle, MODULE_INIT))) {
00277 if ((eng = (modinit)(ctx)) &&
00278 (eng->eng_runfl & EV_ENGINE_REGISTERED))
00279 break;
00280
00281
00282 } else if ((eng = (ev_engine_t *)lt_dlsym(handle, MODULE_ENGINE)) &&
00283 !engine_register(ctx, eng))
00284 break;
00285
00286
00287 lt_dlclose(handle);
00288 }
00289
00290 if (!eng)
00291 ev_return(0);
00292
00293 ev_assert(handle);
00294
00295 eng->eng_handle = (void *)handle;
00296 }
00297
00298 ev_assert(eng);
00299 ev_assert(eng->eng_runfl & EV_ENGINE_REGISTERED);
00300
00301
00302 init_flags &= eng->eng_flags;
00303
00304
00305 if (!init_flags || (err = eng_init(ctx, eng, &init_flags))) {
00306
00307
00308 if (eng->eng_handle) {
00309 if (eng->eng_list.el_next)
00310 eng->eng_list.el_next->eng_list.el_prev = eng->eng_list.el_prev;
00311 if (eng->eng_list.el_prev)
00312 eng->eng_list.el_prev->eng_list.el_next = eng->eng_list.el_next;
00313 else
00314 ctx->ec_engine = eng->eng_list.el_next;
00315
00316 lt_dlclose((lt_dlhandle)eng->eng_handle);
00317 }
00318
00319 if (init_flags)
00320 _ev_debug(EVAS_LOG, __FILE__, __LINE__, _gca_func,
00321 "eng_init() failure initializing engine %s: %u",
00322 eng->eng_name, err);
00323
00324 ev_return(0);
00325 }
00326
00327 *flag_p |= init_flags;
00328
00329 ev_return(0);
00330 }
00331
00332 ev_err_t
00333 event_init(ev_ctx_t *ctx, const ev_attr_t *attr, ev_flags_t flags,
00334 const char *prog, const char *envpath)
00335 {
00336 ev_err_t err = 0;
00337 treeconf_subst_t substs[] = {
00338 TC_SUBST_INIT('n', 0, TC_SUBST_INSECURE),
00339 TC_SUBST_INIT('p', 0, 0)
00340 };
00341 treeconf_str_t *path = 0, *modules = 0;
00342 int path_cnt, mod_cnt, i;
00343 const char *val;
00344 ev_varlist_t *vlist;
00345 ev_overvars_t *ovlist;
00346 ev_engine_t *eng, *eng_next;
00347 ev_flags_t comps = 0;
00348
00349 ev_init();
00350
00351 if (!ctx || (attr && !ea_verify(attr)))
00352 ev_return(EINVAL);
00353
00354 if (!attr)
00355 attr = (const ev_attr_t *)&_ev_defattr;
00356
00357 if (prog)
00358 tu_value(&substs[1]) = prog;
00359 else
00360 tu_flags(&substs[1]) |= TC_SUBST_IGNORE;
00361
00362 tc_init(ec_conf(ctx));
00363
00364
00365 ctx->ec_flags = (flags & EV_INIT_SECURE) ? EV_CTX_SECURE : 0;
00366 ctx->ec_prog = prog;
00367
00368 ctx->ec_maxgen = 0;
00369 ctx->ec_gens = 0;
00370
00371 ctx->ec_timtree.tt_root = 0;
00372 ctx->ec_timtree.tt_insert = 0;
00373
00374 ctx->ec_engine = 0;
00375
00376 ctx->ec_socket.el_first = ctx->ec_socket.el_last = 0;
00377 ctx->ec_signal.el_first = ctx->ec_signal.el_last = 0;
00378 ctx->ec_timer.el_first = ctx->ec_timer.el_last = 0;
00379
00380 ctx->ec_evcnt = 0;
00381 ctx->ec_evs = 0;
00382
00383
00384 ctx->ec_magic = EV_CTX_MAGIC;
00385
00386
00387 if ((err = tc_register(ec_conf(ctx), VAR_MODULES, 0, 0, new_modvar, 0, 0)) ||
00388 (err = tc_register(ec_conf(ctx), VAR_LIBPATH, ea_libpath(attr),
00389 0, 0, 0, 0)) ||
00390 (err = tc_register(ec_conf(ctx), VAR_MODLIST, ea_modlist(attr),
00391 0, 0, 0, 0)))
00392 goto error;
00393
00394
00395
00396
00397 for (vlist = ea_varlist(attr); vlist; vlist = vlist->vl_next)
00398 if ((err = tc_register(ec_conf(ctx), vlist->vl_name, vlist->vl_default, 0,
00399 vlist->vl_nodown, vlist->vl_change,
00400 vlist->vl_assoc)))
00401 goto error;
00402
00403
00404 if ((err = tc_path((flags & EV_INIT_SECURE) ? 0 : envpath, ea_confpath(attr),
00405 substs, sizeof(substs) / sizeof(treeconf_subst_t),
00406 ((flags & EV_INIT_SECURE) ? TC_PATH_SECURE : 0) |
00407 TC_PATH_ALL, tc_load, ec_conf(ctx))))
00408 goto error;
00409
00410
00411 for (ovlist = ea_ovars(attr); ovlist; ovlist = ovlist->ov_next)
00412 if ((err = tc_set(ec_conf(ctx), ovlist->ov_name, ovlist->ov_value, 0)))
00413 goto error;
00414
00415
00416 if ((err = event_gen_register(ctx, EGT_SOCKET, EV_SOCK_MAGIC,
00417 sizeof(ev_sock_t), 0)) ||
00418 (err = event_gen_register(ctx, EGT_SIGNAL, EV_SIG_MAGIC,
00419 sizeof(ev_sig_t), 0)) ||
00420 (err = event_gen_register(ctx, EGT_TIMER, EV_TIM_MAGIC,
00421 sizeof(ev_tim_t), 0)))
00422 goto error;
00423
00424
00425 for (eng = ea_engines(attr); eng; eng = eng_next) {
00426 eng_next = eng->eng_list.el_next;
00427 englink_clr(&eng->eng_list);
00428 if ((err = engine_register(ctx, eng)))
00429 goto error;
00430 }
00431
00432
00433 if ((err = tc_get(ec_conf(ctx), VAR_LIBPATH, &val, 0)) ||
00434 (err = tc_break(&path, &path_cnt, val, ":")) ||
00435 (err = tc_get(ec_conf(ctx), VAR_MODLIST, &val, 0)) ||
00436 (err = tc_break(&modules, &mod_cnt, val, " \t")))
00437 goto error;
00438
00439
00440 if (lt_dlinit()) {
00441 err = EV_ERR_LIBLTDL;
00442 goto error;
00443 } else
00444 ctx->ec_flags |= EV_CTX_LTDLINIT;
00445
00446
00447 for (i = 0; i < mod_cnt && (comps ^ EV_ENGINE_COMPMASK); i++)
00448 if ((err = engine_load(ctx, path, path_cnt, modules + i, &comps)))
00449 goto error;
00450
00451
00452 if ((comps ^ EV_ENGINE_COMPMASK) || !ctx->ec_socket.el_first ||
00453 !ctx->ec_signal.el_first || !ctx->ec_timer.el_first)
00454 err = EV_ERR_NOENGINE;
00455
00456
00457
00458
00459
00460 error:
00461 if (modules)
00462 free(modules);
00463 if (path)
00464 free(path);
00465 if (err)
00466 event_destroy(ctx);
00467
00468 ev_return(err);
00469 }