1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2007 Zend Technologies Ltd. (http://www.zend.com) |
6 : +----------------------------------------------------------------------+
7 : | This source file is subject to version 2.00 of the Zend license, |
8 : | that is bundled with this package in the file LICENSE, and is |
9 : | available through the world-wide-web at the following url: |
10 : | http://www.zend.com/license/2_00.txt. |
11 : | If you did not receive a copy of the Zend license and are unable to |
12 : | obtain it through the world-wide-web, please send a note to |
13 : | license@zend.com so we can mail you a copy immediately. |
14 : +----------------------------------------------------------------------+
15 : | Authors: Andi Gutmans <andi@zend.com> |
16 : | Zeev Suraski <zeev@zend.com> |
17 : +----------------------------------------------------------------------+
18 : */
19 :
20 : /* $Id: zend_extensions.c,v 1.48.2.1.2.2 2007/01/01 09:35:46 sebastian Exp $ */
21 :
22 : #include "zend_extensions.h"
23 :
24 : ZEND_API zend_llist zend_extensions;
25 : static int last_resource_number;
26 :
27 : int zend_load_extension(char *path)
28 0 : {
29 : #if ZEND_EXTENSIONS_SUPPORT
30 : DL_HANDLE handle;
31 : zend_extension *new_extension;
32 : zend_extension_version_info *extension_version_info;
33 :
34 0 : handle = DL_LOAD(path);
35 0 : if (!handle) {
36 : #ifndef ZEND_WIN32
37 0 : fprintf(stderr, "Failed loading %s: %s\n", path, DL_ERROR());
38 : #else
39 : fprintf(stderr, "Failed loading %s\n", path);
40 : #endif
41 0 : return FAILURE;
42 : }
43 :
44 0 : extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info");
45 0 : if (!extension_version_info) {
46 0 : extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "_extension_version_info");
47 : }
48 0 : new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry");
49 0 : if (!new_extension) {
50 0 : new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry");
51 : }
52 0 : if (!extension_version_info || !new_extension) {
53 0 : fprintf(stderr, "%s doesn't appear to be a valid Zend extension\n", path);
54 0 : DL_UNLOAD(handle);
55 0 : return FAILURE;
56 : }
57 :
58 :
59 : /* allow extension to proclaim compatibility with any Zend version */
60 0 : if (extension_version_info->zend_extension_api_no != ZEND_EXTENSION_API_NO &&(!new_extension->api_no_check || new_extension->api_no_check(ZEND_EXTENSION_API_NO) != SUCCESS)) {
61 0 : if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) {
62 0 : fprintf(stderr, "%s requires Zend Engine API version %d.\n"
63 : "The Zend Engine API version %d which is installed, is outdated.\n\n",
64 : new_extension->name,
65 : extension_version_info->zend_extension_api_no,
66 : ZEND_EXTENSION_API_NO);
67 0 : DL_UNLOAD(handle);
68 0 : return FAILURE;
69 0 : } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
70 0 : fprintf(stderr, "%s requires Zend Engine API version %d.\n"
71 : "The Zend Engine API version %d which is installed, is newer.\n"
72 : "Contact %s at %s for a later version of %s.\n\n",
73 : new_extension->name,
74 : extension_version_info->zend_extension_api_no,
75 : ZEND_EXTENSION_API_NO,
76 : new_extension->author,
77 : new_extension->URL,
78 : new_extension->name);
79 0 : DL_UNLOAD(handle);
80 0 : return FAILURE;
81 : }
82 0 : } else if (ZTS_V!=extension_version_info->thread_safe) {
83 0 : fprintf(stderr, "Cannot load %s - it %s thread safe, whereas Zend %s\n",
84 : new_extension->name,
85 : (extension_version_info->thread_safe?"is":"isn't"),
86 : (ZTS_V?"is":"isn't"));
87 0 : DL_UNLOAD(handle);
88 0 : return FAILURE;
89 0 : } else if (ZEND_DEBUG!=extension_version_info->debug) {
90 0 : fprintf(stderr, "Cannot load %s - it %s debug information, whereas Zend %s\n",
91 : new_extension->name,
92 : (extension_version_info->debug?"contains":"does not contain"),
93 : (ZEND_DEBUG?"does":"does not"));
94 0 : DL_UNLOAD(handle);
95 0 : return FAILURE;
96 : }
97 :
98 0 : return zend_register_extension(new_extension, handle);
99 : #else
100 : fprintf(stderr, "Extensions are not supported on this platform.\n");
101 : return FAILURE;
102 : #endif
103 : }
104 :
105 :
106 : int zend_register_extension(zend_extension *new_extension, DL_HANDLE handle)
107 0 : {
108 : #if ZEND_EXTENSIONS_SUPPORT
109 : zend_extension extension;
110 :
111 0 : extension = *new_extension;
112 0 : extension.handle = handle;
113 :
114 0 : zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension);
115 :
116 0 : zend_llist_add_element(&zend_extensions, &extension);
117 :
118 : /*fprintf(stderr, "Loaded %s, version %s\n", extension.name, extension.version);*/
119 : #endif
120 :
121 0 : return SUCCESS;
122 : }
123 :
124 :
125 : static void zend_extension_shutdown(zend_extension *extension TSRMLS_DC)
126 0 : {
127 : #if ZEND_EXTENSIONS_SUPPORT
128 0 : if (extension->shutdown) {
129 0 : extension->shutdown(extension);
130 : }
131 : #endif
132 0 : }
133 :
134 : static int zend_extension_startup(zend_extension *extension)
135 0 : {
136 : #if ZEND_EXTENSIONS_SUPPORT
137 0 : if (extension->startup) {
138 0 : if (extension->startup(extension)!=SUCCESS) {
139 0 : return 1;
140 : }
141 0 : zend_append_version_info(extension);
142 : }
143 : #endif
144 0 : return 0;
145 : }
146 :
147 :
148 : int zend_startup_extensions_mechanism()
149 220 : {
150 : /* Startup extensions mechanism */
151 220 : zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1);
152 220 : last_resource_number = 0;
153 220 : return SUCCESS;
154 : }
155 :
156 :
157 : int zend_startup_extensions()
158 220 : {
159 220 : zend_llist_apply_with_del(&zend_extensions, (int (*)(void *)) zend_extension_startup);
160 220 : return SUCCESS;
161 : }
162 :
163 :
164 : void zend_shutdown_extensions(TSRMLS_D)
165 219 : {
166 219 : zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_shutdown TSRMLS_CC);
167 219 : zend_llist_destroy(&zend_extensions);
168 219 : }
169 :
170 :
171 : void zend_extension_dtor(zend_extension *extension)
172 0 : {
173 : #if ZEND_EXTENSIONS_SUPPORT && !ZEND_DEBUG
174 0 : if (extension->handle) {
175 0 : DL_UNLOAD(extension->handle);
176 : }
177 : #endif
178 0 : }
179 :
180 :
181 : static void zend_extension_message_dispatcher(zend_extension *extension, int num_args, va_list args TSRMLS_DC)
182 0 : {
183 : int message;
184 : void *arg;
185 :
186 0 : if (!extension->message_handler || num_args!=2) {
187 0 : return;
188 : }
189 0 : message = va_arg(args, int);
190 0 : arg = va_arg(args, void *);
191 0 : extension->message_handler(message, arg);
192 : }
193 :
194 :
195 : ZEND_API void zend_extension_dispatch_message(int message, void *arg)
196 0 : {
197 : TSRMLS_FETCH();
198 :
199 0 : zend_llist_apply_with_arguments(&zend_extensions, (llist_apply_with_args_func_t) zend_extension_message_dispatcher TSRMLS_CC, 2, message, arg);
200 0 : }
201 :
202 :
203 : ZEND_API int zend_get_resource_handle(zend_extension *extension)
204 0 : {
205 0 : if (last_resource_number<ZEND_MAX_RESERVED_RESOURCES) {
206 0 : extension->resource_number = last_resource_number;
207 0 : return last_resource_number++;
208 : } else {
209 0 : return -1;
210 : }
211 : }
212 :
213 :
214 : ZEND_API zend_extension *zend_get_extension(char *extension_name)
215 0 : {
216 : zend_llist_element *element;
217 :
218 0 : for (element = zend_extensions.head; element; element = element->next) {
219 0 : zend_extension *extension = (zend_extension *) element->data;
220 :
221 0 : if (!strcmp(extension->name, extension_name)) {
222 0 : return extension;
223 : }
224 : }
225 0 : return NULL;
226 : }
227 :
228 : /*
229 : * Support for dynamic loading of MH_BUNDLEs on Darwin / Mac OS X
230 : *
231 : */
232 :
233 : #if HAVE_MACH_O_DYLD_H
234 :
235 : void *zend_mh_bundle_load(char* bundle_path)
236 : {
237 : NSObjectFileImage bundle_image;
238 : NSModule bundle_handle;
239 : NSSymbol bundle_init_nssymbol;
240 : void (*bundle_init)(void);
241 :
242 : if (NSCreateObjectFileImageFromFile(bundle_path, &bundle_image) != NSObjectFileImageSuccess) {
243 : return NULL;
244 : }
245 :
246 : bundle_handle = NSLinkModule(bundle_image, bundle_path, NSLINKMODULE_OPTION_PRIVATE);
247 : NSDestroyObjectFileImage(bundle_image);
248 :
249 : /* call the init function of the bundle */
250 : bundle_init_nssymbol = NSLookupSymbolInModule(bundle_handle, "__init");
251 : if (bundle_init_nssymbol != NULL) {
252 : bundle_init = NSAddressOfSymbol(bundle_init_nssymbol);
253 : bundle_init();
254 : }
255 :
256 : return bundle_handle;
257 : }
258 :
259 : int zend_mh_bundle_unload(void *bundle_handle)
260 : {
261 : NSSymbol bundle_fini_nssymbol;
262 : void (*bundle_fini)(void);
263 :
264 : /* call the fini function of the bundle */
265 : bundle_fini_nssymbol = NSLookupSymbolInModule(bundle_handle, "__fini");
266 : if (bundle_fini_nssymbol != NULL) {
267 : bundle_fini = NSAddressOfSymbol(bundle_fini_nssymbol);
268 : bundle_fini();
269 : }
270 :
271 : return (int) NSUnLinkModule(bundle_handle, NULL);
272 : }
273 :
274 : void *zend_mh_bundle_symbol(void *bundle_handle, const char *symbol_name)
275 : {
276 : NSSymbol symbol;
277 : symbol = NSLookupSymbolInModule(bundle_handle, symbol_name);
278 : return NSAddressOfSymbol(symbol);
279 : }
280 :
281 : const char *zend_mh_bundle_error(void)
282 : {
283 : /* Witness the state of the art error reporting */
284 : return NULL;
285 : }
286 :
287 : #endif /* HAVE_MACH_O_DYLD_H */
288 :
289 : /*
290 : * Local variables:
291 : * tab-width: 4
292 : * c-basic-offset: 4
293 : * indent-tabs-mode: t
294 : * End:
295 : */
|