]> git.netwichtig.de Git - user/henk/code/inspircd.git/blob - src/dynamic.cpp
Made SANICK not collide the user (theres no need to in the new 1.1 now we have return...
[user/henk/code/inspircd.git] / src / dynamic.cpp
1 /*       +------------------------------------+
2  *       | Inspire Internet Relay Chat Daemon |
3  *       +------------------------------------+
4  *
5  *  InspIRCd is copyright (C) 2002-2006 ChatSpike-Dev.
6  *                       E-mail:
7  *                <brain@chatspike.net>
8  *                <Craig@chatspike.net>
9  *     
10  * Written by Craig Edwards, Craig McLure, and others.
11  * This program is free but copyrighted software; see
12  *            the file COPYING for details.
13  *
14  * ---------------------------------------------------
15  */
16
17 using namespace std;
18
19 #include "configreader.h"
20 #include "dynamic.h"
21
22 #ifndef STATIC_LINK
23 #include <dlfcn.h>
24 #else
25 #include "modlist.h"
26 #endif
27
28 #include "inspircd.h"
29
30 DLLManager::DLLManager(InspIRCd* ServerInstance, const char *fname)
31 {
32         err = NULL;
33
34         if (!strstr(fname,".so"))
35         {
36                 err = "This doesn't look like a module file to me...";
37                 return;
38         }
39 #ifdef STATIC_LINK
40         this->staticname[0] = '\0';
41         ServerInstance->Log(DEBUG,"Loading core-compiled module '%s'",fname);
42         for (int j = 0; modsyms[j].name; j++)
43         {
44                 ServerInstance->Log(DEBUG,"Check %s",modsyms[j].name);
45                 if (!strcmp(modsyms[j].name,fname))
46                 {
47                         ServerInstance->Log(DEBUG,"Found %s",fname);
48                         strlcpy(this->staticname,fname,1020);
49                         err = 0;
50                         return;
51                 }
52         }
53         err = "Module is not statically compiled into the ircd";
54 #else
55         // Copy the library to a temp location, this makes recompiles
56         // a little safer if the ircd is running at the time as the
57         // shared libraries are mmap()ed and not doing this causes
58         // segfaults.
59         FILE* x = fopen(fname,"rb");
60         if (!x)
61         {
62                 err = strerror(errno);
63                 return;
64         }
65         ServerInstance->Log(DEBUG,"Opened module file %s",fname);
66         char tmpfile_template[255];
67         char buffer[65536];
68         snprintf(tmpfile_template, 255, "%s/inspircd_file.so.%d.XXXXXXXXXX",ServerInstance->Config->TempDir,getpid());
69         int fd = mkstemp(tmpfile_template);
70         if (fd == -1)
71         {
72                 fclose(x);
73                 err = strerror(errno);
74                 return;
75         }
76         ServerInstance->Log(DEBUG,"Copying %s to %s",fname, tmpfile_template);
77         while (!feof(x))
78         {
79                 int n = fread(buffer, 1, 65535, x);
80                 if (n)
81                 {
82                         int written = write(fd,buffer,n);
83                         if (written != n)
84                         {
85                                 fclose(x);
86                                 err = strerror(errno);
87                                 return;
88                         }
89                 }
90         }
91         ServerInstance->Log(DEBUG,"Copied entire file.");
92         // Try to open the library now and get any error message.
93
94         if (close(fd) == -1)
95                 err = strerror(errno);
96         if (fclose(x) == EOF)
97                 err = strerror(errno);
98
99         h = dlopen(fname, RTLD_NOW|RTLD_LOCAL);
100         if (!h)
101         {
102                 ServerInstance->Log(DEBUG,"dlerror occured!");
103                 err = (char*)dlerror();
104                 return;
105         }
106
107         ServerInstance->Log(DEBUG,"Finished loading '%s': %0x",tmpfile_template, h);
108
109         // We can delete the tempfile once it's loaded, leaving just the inode.
110         if (!err && !ServerInstance->Config->debugging)
111         {
112                 ServerInstance->Log(DEBUG,"Deleteting %s",tmpfile_template);
113                 if (unlink(tmpfile_template) == -1)
114                         err = strerror(errno);
115         }
116 #endif
117 }
118
119 DLLManager::~DLLManager()
120 {
121 #ifndef STATIC_LINK
122         // close the library if it isn't null
123         if (h)
124                 dlclose(h);
125 #endif
126 }
127
128
129
130 #ifdef STATIC_LINK
131
132 bool DLLManager::GetSymbol(initfunc* &v, const char *sym_name)
133 {
134         for (int j = 0; modsyms[j].name; j++)
135         {
136                 if (!strcmp(this->staticname,modsyms[j].name))
137                 {
138                         v = modsyms[j].value;
139                         err = 0;
140                         return true;
141                 }
142         }
143         err = "Module symbol missing from the core";
144         return false;
145 }
146
147 #else
148
149 bool DLLManager::GetSymbol(void** v, const char* sym_name)
150 {
151         // try extract a symbol from the library
152         // get any error message is there is any
153         
154         if (h)
155         {
156                 dlerror(); // clear value
157                 *v = dlsym(h, sym_name);
158                 err = (char*)dlerror();
159                 if (!*v || err)
160                         return false;
161         }
162         
163         if (err)
164         {
165                 return false;
166         }
167         else
168         {       
169                 return true;
170         }
171 }
172
173 #endif
174
175 DLLFactoryBase::DLLFactoryBase(InspIRCd* Instance, const char* fname, const char* symbol) : DLLManager(Instance, fname)
176 {
177         // try get the factory function if there is no error yet
178         factory_func = 0;
179         
180         if (!LastError())
181         {
182 #ifdef STATIC_LINK
183                 if (!GetSymbol( factory_func, symbol ? symbol : "init_module"))
184 #else
185                 if (!GetSymbol( (void **)&factory_func, symbol ? symbol : "init_module"))
186 #endif
187                 {
188                         throw ModuleException("Missing init_module() entrypoint!");
189                 }
190         }
191 }
192
193 DLLFactoryBase::~DLLFactoryBase()
194 {
195 }
196