]> git.draconx.ca Git - upkg.git/blob - src/module.c
Implement dynamic loading of modules.
[upkg.git] / src / module.c
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <string.h>
4 #include <ctype.h>
5 #include <glib-object.h>
6 #include <ltdl.h>
7
8 #include "module.h"
9
10 G_DEFINE_TYPE(UPkgModule, upkg_module, G_TYPE_TYPE_MODULE);
11
12 static unsigned initialized;
13
14 static void dl_print_errors(const char *prefix)
15 {
16         const char *err;
17         while (err = lt_dlerror()) {
18                 if (prefix) fprintf(stderr, "%s: ", prefix);
19                 puts(err);
20         }
21 }
22
23 static gboolean module_load(GTypeModule *m)
24 {
25         UPkgModule *mod = UPKG_MODULE(m);
26         int (*init_func)(GTypeModule *);
27
28         mod->dl = lt_dlopenext(G_TYPE_MODULE(m)->name);
29         if (!mod->dl) {
30                 dl_print_errors(__func__);
31                 return FALSE;
32         }
33
34         init_func = lt_dlsym(mod->dl, "init");
35         if (!init_func || init_func(m) != 0) {
36                 dl_print_errors(__func__);
37                 lt_dlclose(mod->dl);
38                 return FALSE;
39         }
40
41         return TRUE;
42 }
43
44 static void module_unload(GTypeModule *m)
45 {
46         UPkgModule *mod = UPKG_MODULE(m);
47
48         if (lt_dlclose(mod->dl) != 0) {
49                 dl_print_errors(__func__);
50         }
51 }
52
53 static void upkg_module_init(UPkgModule *mod)
54 {
55 }
56
57 static void upkg_module_class_init(UPkgModuleClass *class)
58 {
59         GTypeModuleClass *modclass = G_TYPE_MODULE_CLASS(class);
60
61         modclass->load   = module_load;
62         modclass->unload = module_unload;
63 }
64
65 UPkgModule *upkg_module_new(const char *name)
66 {
67         char *name2;
68         size_t len;
69
70         if (!name) {
71                 return NULL;
72         }
73
74         len   = strlen(name);
75         name2 = malloc(len+1);
76         if (!name2) {
77                 return NULL;
78         }
79
80         UPkgModule *mod = g_object_new(UPKG_MODULE_TYPE, NULL);
81         if (!mod) {
82                 free(name2);
83                 return NULL;
84         }
85
86         G_TYPE_MODULE(mod)->name = name2;
87         for (size_t i = 0; i < len; i++) {
88                 name2[i] = tolower(name[i]);
89         }
90         name2[len] = 0;
91
92         return mod;
93 }
94
95 int module_init(void)
96 {
97         if (!initialized) {
98                 if (lt_dlinit() != 0) {
99                         dl_print_errors(__func__);
100                         return -1;
101                 }
102
103                 g_type_init();
104         }
105
106         initialized++;
107         return 0;
108 }
109
110 int module_exit(void)
111 {
112         if (--initialized)
113                 return 0;
114
115         if (lt_dlexit() != 0) {
116                 dl_print_errors(__func__);
117                 return -1;
118         }
119 }