↑ 1 #include <stdio.h>
↑ 2 #include <stdlib.h>
↑ 3 #include <dlfcn.h>
↑ 4 #include <errno.h>
↑ 5 #include "rh_string.h"
↑ 6 #include "handler.h"
↑ 7
↑ 8 handler_t * handler_load (handler_base_t *base,
↑ 9 const char *name, const char *filename)
↑ 10 {
↑ 11 void *dl;
↑ 12 void *sym;
↑ 13 handler_t *handler;
↑ 14 #if 0
↑ 15 printf ("%s(%p, %s, %s)\n", __FUNCTION__,
↑ 16 (void*)base,
↑ 17 name,
↑ 18 filename);
↑ 19 #endif
↑ 20
↑ 21 dl = dlopen (filename, RTLD_LAZY);
↑ 22 if (NULL == dl) {
↑ 23 printf ("%s(): %s\n", __FUNCTION__, dlerror());
↑ 24 return NULL;
↑ 25 }
↑ 26
↑ 27 sym = dlsym (dl, name);
↑ 28 if (NULL == sym) {
↑ 29 printf ("%s(): %s\n", __FUNCTION__, dlerror());
↑ 30 dlclose (dl);
↑ 31 return NULL;
↑ 32 }
↑ 33
↑ 34 handler = calloc (1, sizeof(*handler));
↑ 35 if (NULL == handler) {
↑ 36 printf ("%s(): %s\n", __FUNCTION__, strerror(errno));
↑ 37 dlclose (dl);
↑ 38 return NULL;
↑ 39 }
↑ 40
↑ 41 handler->base = base;
↑ 42 handler->library = dl;
↑ 43 handler->def = sym;
↑ 44 handler->reference = 1;
↑ 45
↑ 46 TAILQ_INSERT_TAIL (&base->handler, handler, list);
↑ 47
↑ 48 if (HANDLER_SUCCESS != HANDLER_CALL_MAYBE(handler, setup)) {
↑ 49 handler_free (handler);
↑ 50 return NULL;
↑ 51 }
↑ 52
↑ 53 return handler;
↑ 54 }
↑ 55
↑ 56 int handler_free (handler_t *handler)
↑ 57 {
↑ 58 handler_t *parent;
↑ 59 #if 0
↑ 60 printf ("%s(%p): name(%s) ref(%zu) pref(%zu)\n",
↑ 61 __FUNCTION__, (void*)handler,
↑ 62 handler->def->name,
↑ 63 handler->reference,
↑ 64 (handler->parent ? handler->parent->reference : 0) );
↑ 65 #endif
↑ 66
↑ 67 if (NULL == handler) {
↑ 68 errno = EINVAL;
↑ 69 return -1;
↑ 70 }
↑ 71
↑ 72 parent = handler->parent;
↑ 73
↑ 74 if (parent && parent->reference)
↑ 75 --parent->reference;
↑ 76
↑ 77 if (handler->reference > 1) {
↑ 78 --handler->reference;
↑ 79 errno = EBUSY;
↑ 80 return -1;
↑ 81 }
↑ 82
↑ 83 /* destroy the local data */
↑ 84 if (handler->data_local) {
↑ 85 if (HANDLER_CALL_MAYBE(handler, free)) {
↑ 86 /* what to do? */
↑ 87 }
↑ 88 }
↑ 89
↑ 90 /* am i the parent handler? */
↑ 91 if (NULL == parent) {
↑ 92 if (handler->data_global) {
↑ 93 if (HANDLER_CALL_MAYBE(handler, free_global)) {
↑ 94 /* what to do? */
↑ 95 }
↑ 96 }
↑ 97
↑ 98 if (handler->library) {
↑ 99 dlclose (handler->library);
↑100 }
↑101 }
↑102
↑103 if (handler->base) {
↑104 TAILQ_REMOVE(&handler->base->handler, handler, list);
↑105 }
↑106
↑107 TYPE_ZERO(handler);
↑108
↑109 free (handler);
↑110
↑111 return 0;
↑112 }
↑113
↑114
↑115 handler_t * handler_dup (const handler_t *handler_src)
↑116 {
↑117 handler_t *handler;
↑118
↑119 handler = calloc (1, sizeof(*handler));
↑120 if (NULL == handler)
↑121 return NULL;
↑122
↑123 if (handler_src->parent)
↑124 handler->parent = handler_src->parent;
↑125 else
↑126 handler->parent = (handler_t*)handler_src;
↑127
↑128 handler->parent->reference++;
↑129
↑130 handler->data_global = handler->parent->data_global;
↑131 handler->def = handler->parent->def;
↑132 handler->reference = 1;
↑133
↑134 return handler;
↑135 }
↑136
↑137 void handler_base_init (handler_base_t *base, struct config_base *config)
↑138 {
↑139 TAILQ_INIT(&base->handler);
↑140 base->config = config;
↑141 }
↑142
↑143 int handler_base_init_handlers (handler_base_t *base)
↑144 {
↑145 handler_t *handler;
↑146
↑147 TAILQ_FOREACH(handler, &base->handler, list) {
↑148 int retcode;
↑149
↑150 retcode = HANDLER_CALL_MAYBE(handler, init);
↑151
↑152 if (HANDLER_SUCCESS != retcode)
↑153 return retcode;
↑154 }
↑155
↑156 return 0;
↑157 }
↑158
↑159 void handler_base_destroy (handler_base_t *base)
↑160 {
↑161 while (!TAILQ_EMPTY(&base->handler)) {
↑162 handler_t *handler;
↑163
↑164 handler = TAILQ_FIRST(&base->handler);
↑165 if (0 != handler_free (handler)) {
↑166 perror ("handler_free()");
↑167 return;
↑168 }
↑169 }
↑170 base->config = NULL;
↑171 }
↑172
↑173 int handler_base_dup (handler_base_t *dst, const handler_base_t *src)
↑174 {
↑175 const handler_t *src_handler;
↑176
↑177 TAILQ_FOREACH(src_handler, &src->handler, list) {
↑178 handler_t *dst_handler;
↑179
↑180 dst_handler = handler_dup (src_handler);
↑181 if (NULL == dst_handler)
↑182 return -1;
↑183
↑184 dst_handler->base = dst;
↑185 TAILQ_INSERT_TAIL(&dst->handler, dst_handler, list);
↑186 }
↑187
↑188 return 0;
↑189 }
↑190
↑191 int handler_base_prepend_handler (handler_base_t *base,
↑192 const handler_t *src_handler)
↑193 {
↑194 handler_t *handler;
↑195
↑196 handler = handler_dup (src_handler);
↑197 if (NULL == handler)
↑198 return -1;
↑199
↑200 handler->base = base;
↑201
↑202 TAILQ_INSERT_HEAD(&base->handler, handler, list);
↑203
↑204 return 0;
↑205 }
↑206
↑207 int handler_base_append_handler (handler_base_t *base,
↑208 const handler_t *src_handler)
↑209 {
↑210 handler_t *handler;
↑211
↑212 handler = handler_dup (src_handler);
↑213 if (NULL == handler)
↑214 return -1;
↑215
↑216 handler->base = base;
↑217
↑218 TAILQ_INSERT_TAIL(&base->handler, handler, list);
↑219
↑220 return 0;
↑221 }
↑222
↑223 int handler_base_remove_handlers (handler_base_t *base, int type)
↑224 {
↑225 handler_t *handler;
↑226
↑227 while ( (handler = TAILQ_FIRST(&base->handler)) ) {
↑228 if (handler->def->type != type)
↑229 return 0;
↑230
↑231 if (0 != handler_free (handler))
↑232 return -1;
↑233 }
↑234
↑235 return 0;
↑236 }
syntax highlighted by Code2HTML, v. 0.9.1