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