]> git.draconx.ca Git - upkg.git/blob - src/package.c
license: Add permissive license to build related source files.
[upkg.git] / src / package.c
1 /*
2  *  upkg: tool for manipulating Unreal Tournament packages.
3  *  Copyright (C) 2009 Nick Bowler
4  *
5  *  This program is free software: you can redistribute it and/or modify
6  *  it under the terms of the GNU General Public License as published by
7  *  the Free Software Foundation, either version 3 of the License, or
8  *  (at your option) any later version.
9  *
10  *  This program is distributed in the hope that it will be useful,
11  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
12  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13  *  GNU General Public License for more details.
14  *
15  *  You should have received a copy of the GNU General Public License
16  *  along with this program.  If not, see <http://www.gnu.org/licenses/>.
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <string.h>
22 #include <ctype.h>
23
24 #include <glib-object.h>
25 #include <ltdl.h>
26
27 #include <uobject/package.h>
28
29 #define U_PKG_GET_PRIV(o) \
30         G_TYPE_INSTANCE_GET_PRIVATE(o, U_PKG_TYPE, struct upkg_priv)
31
32 struct upkg_priv {
33         lt_dlhandle native;
34 };
35
36 G_DEFINE_TYPE(UPkg, u_pkg, G_TYPE_TYPE_MODULE);
37
38 static char *str_cpy_lower(char *dst, const char *src)
39 {
40         size_t i;
41
42         for (i = 0; src[i]; i++)
43                 dst[i] = tolower(src[i]);
44         dst[i] = 0;
45
46         return dst;
47 }
48
49 static void dl_print_errors(const char *prefix)
50 {
51         const char *err;
52         while ((err = lt_dlerror())) {
53                 if (prefix) fprintf(stderr, "%s: ", prefix);
54                 fprintf(stderr, "%s\n", err);
55         }
56 }
57
58 static gboolean u_pkg_load(GTypeModule *m)
59 {
60         struct upkg_priv *priv = U_PKG_GET_PRIV(m);
61         int (*init_func)(GTypeModule *);
62
63         priv->native = lt_dlopenext(m->name);
64         if (!priv->native) {
65                 dl_print_errors(m->name);
66                 return FALSE;
67         }
68
69         init_func = lt_dlsym(priv->native, "init");
70         if (!init_func || init_func(m) != 0) {
71                 dl_print_errors(__func__);
72                 lt_dlclose(priv->native);
73                 return FALSE;
74         }
75
76         return TRUE;
77 }
78
79 static void u_pkg_unload(GTypeModule *m)
80 {
81         struct upkg_priv *priv = U_PKG_GET_PRIV(m);
82         void (*exit_func)(GTypeModule *);
83
84         if (priv->native) {
85                 exit_func = lt_dlsym(priv->native, "exit");
86                 if (exit_func) {
87                         exit_func(m);
88                 }
89
90                 if (lt_dlclose(priv->native) != 0) {
91                         dl_print_errors(__func__);
92                 }
93         }
94 }
95
96 static void u_pkg_init(UPkg *pkg)
97 {
98
99 }
100
101 static void u_pkg_class_init(UPkgClass *class)
102 {
103         GTypeModuleClass *modclass = G_TYPE_MODULE_CLASS(class);
104         const char *modpath = getenv("UOBJECT_MODULE_PATH");
105
106         g_type_class_add_private(class, sizeof (struct upkg_priv));
107
108         if (lt_dlinit() != 0) {
109                 dl_print_errors(__func__);
110         }
111
112         if (modpath && lt_dlsetsearchpath(modpath) != 0) {
113                 dl_print_errors(__func__);
114         }
115         if (lt_dladdsearchdir(PKGLIBDIR) != 0) {
116                 dl_print_errors(__func__);
117         }
118
119         modclass->load   = u_pkg_load;
120         modclass->unload = u_pkg_unload;
121 }
122
123 GTypeModule *u_pkg_new(const char *name)
124 {
125         g_return_val_if_fail(name != NULL, NULL);
126
127         char *pkgname = malloc(strlen(name)+1);
128         if (!pkgname) {
129                 return NULL;
130         }
131
132         GTypeModule *mod = g_object_new(U_PKG_TYPE, NULL);
133         if (!mod) {
134                 free(pkgname);
135                 return NULL;
136         }
137
138         mod->name = str_cpy_lower(pkgname, name);
139         return mod;
140 }