]> git.draconx.ca Git - upkg.git/blob - src/package.c
module: Split out the GTypeModule subclass.
[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 2 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, write to the Free Software
17  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
18  */
19
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <string.h>
23 #include <ctype.h>
24
25 #include <glib-object.h>
26 #include <ltdl.h>
27
28 #include <uobject/package.h>
29
30 #define U_PKG_GET_PRIV(o) \
31         G_TYPE_INSTANCE_GET_PRIVATE(o, U_PKG_TYPE, struct upkg_priv)
32
33 struct upkg_priv {
34         lt_dlhandle native;
35 };
36
37 G_DEFINE_TYPE(UPkg, u_pkg, G_TYPE_TYPE_MODULE);
38
39 static char *str_cpy_lower(char *dst, const char *src)
40 {
41         size_t i;
42
43         for (i = 0; src[i]; i++)
44                 dst[i] = tolower(src[i]);
45         dst[i] = 0;
46
47         return dst;
48 }
49
50 static void dl_print_errors(const char *prefix)
51 {
52         const char *err;
53         while ((err = lt_dlerror())) {
54                 if (prefix) fprintf(stderr, "%s: ", prefix);
55                 fprintf(stderr, "%s\n", err);
56         }
57 }
58
59 static gboolean u_pkg_load(GTypeModule *m)
60 {
61         struct upkg_priv *priv = U_PKG_GET_PRIV(m);
62         int (*init_func)(GTypeModule *);
63
64         priv->native = lt_dlopenext(m->name);
65         if (!priv->native) {
66                 dl_print_errors(m->name);
67                 return FALSE;
68         }
69
70         init_func = lt_dlsym(priv->native, "init");
71         if (!init_func || init_func(m) != 0) {
72                 dl_print_errors(__func__);
73                 lt_dlclose(priv->native);
74                 return FALSE;
75         }
76
77         return TRUE;
78 }
79
80 static void u_pkg_unload(GTypeModule *m)
81 {
82         struct upkg_priv *priv = U_PKG_GET_PRIV(m);
83         void (*exit_func)(GTypeModule *);
84
85         if (priv->native) {
86                 exit_func = lt_dlsym(priv->native, "exit");
87                 if (exit_func) {
88                         exit_func(m);
89                 }
90
91                 if (lt_dlclose(priv->native) != 0) {
92                         dl_print_errors(__func__);
93                 }
94         }
95 }
96
97 static void u_pkg_init(UPkg *pkg)
98 {
99
100 }
101
102 static void u_pkg_class_init(UPkgClass *class)
103 {
104         g_type_class_add_private(class, sizeof (struct upkg_priv));
105
106         GTypeModuleClass *modclass = G_TYPE_MODULE_CLASS(class);
107
108         if (lt_dlinit() != 0) {
109                 dl_print_errors(__func__);
110         }
111
112         modclass->load   = u_pkg_load;
113         modclass->unload = u_pkg_unload;
114 }
115
116 GTypeModule *u_pkg_new(const char *name)
117 {
118         g_return_val_if_fail(name != NULL, NULL);
119
120         char *pkgname = malloc(strlen(name)+1);
121         if (!pkgname) {
122                 return NULL;
123         }
124
125         GTypeModule *mod = g_object_new(U_PKG_TYPE, NULL);
126         if (!mod) {
127                 free(pkgname);
128                 return NULL;
129         }
130
131         mod->name = str_cpy_lower(pkgname, name);
132         return mod;
133 }