1 /*
2 +----------------------------------------------------------------------+
3 | Zend Engine |
4 +----------------------------------------------------------------------+
5 | Copyright (c) 1998-2015 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$ */
21
22 #include "zend_extensions.h"
23
24 ZEND_API zend_llist zend_extensions;
25 static int last_resource_number;
26
zend_load_extension(const char * path)27 int zend_load_extension(const char *path)
28 {
29 #if ZEND_EXTENSIONS_SUPPORT
30 DL_HANDLE handle;
31 zend_extension *new_extension;
32 zend_extension_version_info *extension_version_info;
33
34 handle = DL_LOAD(path);
35 if (!handle) {
36 #ifndef ZEND_WIN32
37 fprintf(stderr, "Failed loading %s: %s\n", path, DL_ERROR());
38 /* See http://support.microsoft.com/kb/190351 */
39 #ifdef PHP_WIN32
40 fflush(stderr);
41 #endif
42 #else
43 fprintf(stderr, "Failed loading %s\n", path);
44 #endif
45 return FAILURE;
46 }
47
48 extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "extension_version_info");
49 if (!extension_version_info) {
50 extension_version_info = (zend_extension_version_info *) DL_FETCH_SYMBOL(handle, "_extension_version_info");
51 }
52 new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "zend_extension_entry");
53 if (!new_extension) {
54 new_extension = (zend_extension *) DL_FETCH_SYMBOL(handle, "_zend_extension_entry");
55 }
56 if (!extension_version_info || !new_extension) {
57 fprintf(stderr, "%s doesn't appear to be a valid Zend extension\n", path);
58 /* See http://support.microsoft.com/kb/190351 */
59 #ifdef PHP_WIN32
60 fflush(stderr);
61 #endif
62 DL_UNLOAD(handle);
63 return FAILURE;
64 }
65
66
67 /* allow extension to proclaim compatibility with any Zend version */
68 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)) {
69 if (extension_version_info->zend_extension_api_no > ZEND_EXTENSION_API_NO) {
70 fprintf(stderr, "%s requires Zend Engine API version %d.\n"
71 "The Zend Engine API version %d which is installed, is outdated.\n\n",
72 new_extension->name,
73 extension_version_info->zend_extension_api_no,
74 ZEND_EXTENSION_API_NO);
75 /* See http://support.microsoft.com/kb/190351 */
76 #ifdef PHP_WIN32
77 fflush(stderr);
78 #endif
79 DL_UNLOAD(handle);
80 return FAILURE;
81 } else if (extension_version_info->zend_extension_api_no < ZEND_EXTENSION_API_NO) {
82 fprintf(stderr, "%s requires Zend Engine API version %d.\n"
83 "The Zend Engine API version %d which is installed, is newer.\n"
84 "Contact %s at %s for a later version of %s.\n\n",
85 new_extension->name,
86 extension_version_info->zend_extension_api_no,
87 ZEND_EXTENSION_API_NO,
88 new_extension->author,
89 new_extension->URL,
90 new_extension->name);
91 /* See http://support.microsoft.com/kb/190351 */
92 #ifdef PHP_WIN32
93 fflush(stderr);
94 #endif
95 DL_UNLOAD(handle);
96 return FAILURE;
97 }
98 } else if (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) &&
99 (!new_extension->build_id_check || new_extension->build_id_check(ZEND_EXTENSION_BUILD_ID) != SUCCESS)) {
100 fprintf(stderr, "Cannot load %s - it was built with configuration %s, whereas running engine is %s\n",
101 new_extension->name, extension_version_info->build_id, ZEND_EXTENSION_BUILD_ID);
102 /* See http://support.microsoft.com/kb/190351 */
103 #ifdef PHP_WIN32
104 fflush(stderr);
105 #endif
106 DL_UNLOAD(handle);
107 return FAILURE;
108 }
109
110 return zend_register_extension(new_extension, handle);
111 #else
112 fprintf(stderr, "Extensions are not supported on this platform.\n");
113 /* See http://support.microsoft.com/kb/190351 */
114 #ifdef PHP_WIN32
115 fflush(stderr);
116 #endif
117 return FAILURE;
118 #endif
119 }
120
121
zend_register_extension(zend_extension * new_extension,DL_HANDLE handle)122 int zend_register_extension(zend_extension *new_extension, DL_HANDLE handle)
123 {
124 #if ZEND_EXTENSIONS_SUPPORT
125 zend_extension extension;
126
127 extension = *new_extension;
128 extension.handle = handle;
129
130 zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension);
131
132 zend_llist_add_element(&zend_extensions, &extension);
133
134 /*fprintf(stderr, "Loaded %s, version %s\n", extension.name, extension.version);*/
135 #endif
136
137 return SUCCESS;
138 }
139
140
zend_extension_shutdown(zend_extension * extension TSRMLS_DC)141 static void zend_extension_shutdown(zend_extension *extension TSRMLS_DC)
142 {
143 #if ZEND_EXTENSIONS_SUPPORT
144 if (extension->shutdown) {
145 extension->shutdown(extension);
146 }
147 #endif
148 }
149
zend_extension_startup(zend_extension * extension)150 static int zend_extension_startup(zend_extension *extension)
151 {
152 #if ZEND_EXTENSIONS_SUPPORT
153 if (extension->startup) {
154 if (extension->startup(extension)!=SUCCESS) {
155 return 1;
156 }
157 zend_append_version_info(extension);
158 }
159 #endif
160 return 0;
161 }
162
163
zend_startup_extensions_mechanism()164 int zend_startup_extensions_mechanism()
165 {
166 /* Startup extensions mechanism */
167 zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1);
168 last_resource_number = 0;
169 return SUCCESS;
170 }
171
172
zend_startup_extensions()173 int zend_startup_extensions()
174 {
175 zend_llist_apply_with_del(&zend_extensions, (int (*)(void *)) zend_extension_startup);
176 return SUCCESS;
177 }
178
179
zend_shutdown_extensions(TSRMLS_D)180 void zend_shutdown_extensions(TSRMLS_D)
181 {
182 zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_shutdown TSRMLS_CC);
183 zend_llist_destroy(&zend_extensions);
184 }
185
186
zend_extension_dtor(zend_extension * extension)187 void zend_extension_dtor(zend_extension *extension)
188 {
189 #if ZEND_EXTENSIONS_SUPPORT && !ZEND_DEBUG
190 if (extension->handle) {
191 DL_UNLOAD(extension->handle);
192 }
193 #endif
194 }
195
196
zend_extension_message_dispatcher(const zend_extension * extension,int num_args,va_list args TSRMLS_DC)197 static void zend_extension_message_dispatcher(const zend_extension *extension, int num_args, va_list args TSRMLS_DC)
198 {
199 int message;
200 void *arg;
201
202 if (!extension->message_handler || num_args!=2) {
203 return;
204 }
205 message = va_arg(args, int);
206 arg = va_arg(args, void *);
207 extension->message_handler(message, arg);
208 }
209
210
zend_extension_dispatch_message(int message,void * arg)211 ZEND_API void zend_extension_dispatch_message(int message, void *arg)
212 {
213 TSRMLS_FETCH();
214
215 zend_llist_apply_with_arguments(&zend_extensions, (llist_apply_with_args_func_t) zend_extension_message_dispatcher TSRMLS_CC, 2, message, arg);
216 }
217
218
zend_get_resource_handle(zend_extension * extension)219 ZEND_API int zend_get_resource_handle(zend_extension *extension)
220 {
221 if (last_resource_number<ZEND_MAX_RESERVED_RESOURCES) {
222 extension->resource_number = last_resource_number;
223 return last_resource_number++;
224 } else {
225 return -1;
226 }
227 }
228
229
zend_get_extension(const char * extension_name)230 ZEND_API zend_extension *zend_get_extension(const char *extension_name)
231 {
232 zend_llist_element *element;
233
234 for (element = zend_extensions.head; element; element = element->next) {
235 zend_extension *extension = (zend_extension *) element->data;
236
237 if (!strcmp(extension->name, extension_name)) {
238 return extension;
239 }
240 }
241 return NULL;
242 }
243
244 /*
245 * Local variables:
246 * tab-width: 4
247 * c-basic-offset: 4
248 * indent-tabs-mode: t
249 * End:
250 */
251