xref: /PHP-5.6/Zend/zend_extensions.c (revision 3537e95d)
1 /*
2    +----------------------------------------------------------------------+
3    | Zend Engine                                                          |
4    +----------------------------------------------------------------------+
5    | Copyright (c) 1998-2016 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 	} else if (zend_get_extension(new_extension->name)) {
109 		fprintf(stderr, "Cannot load %s - extension already loaded\n", new_extension->name);
110 /* See http://support.microsoft.com/kb/190351 */
111 #ifdef PHP_WIN32
112 		fflush(stderr);
113 #endif
114 		DL_UNLOAD(handle);
115 		return FAILURE;
116 	}
117 
118 	return zend_register_extension(new_extension, handle);
119 #else
120 	fprintf(stderr, "Extensions are not supported on this platform.\n");
121 /* See http://support.microsoft.com/kb/190351 */
122 #ifdef PHP_WIN32
123 	fflush(stderr);
124 #endif
125 	return FAILURE;
126 #endif
127 }
128 
129 
zend_register_extension(zend_extension * new_extension,DL_HANDLE handle)130 int zend_register_extension(zend_extension *new_extension, DL_HANDLE handle)
131 {
132 #if ZEND_EXTENSIONS_SUPPORT
133 	zend_extension extension;
134 
135 	extension = *new_extension;
136 	extension.handle = handle;
137 
138 	zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension);
139 
140 	zend_llist_add_element(&zend_extensions, &extension);
141 
142 	/*fprintf(stderr, "Loaded %s, version %s\n", extension.name, extension.version);*/
143 #endif
144 
145 	return SUCCESS;
146 }
147 
148 
zend_extension_shutdown(zend_extension * extension TSRMLS_DC)149 static void zend_extension_shutdown(zend_extension *extension TSRMLS_DC)
150 {
151 #if ZEND_EXTENSIONS_SUPPORT
152 	if (extension->shutdown) {
153 		extension->shutdown(extension);
154 	}
155 #endif
156 }
157 
zend_extension_startup(zend_extension * extension)158 static int zend_extension_startup(zend_extension *extension)
159 {
160 #if ZEND_EXTENSIONS_SUPPORT
161 	if (extension->startup) {
162 		if (extension->startup(extension)!=SUCCESS) {
163 			return 1;
164 		}
165 		zend_append_version_info(extension);
166 	}
167 #endif
168 	return 0;
169 }
170 
171 
zend_startup_extensions_mechanism()172 int zend_startup_extensions_mechanism()
173 {
174 	/* Startup extensions mechanism */
175 	zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1);
176 	last_resource_number = 0;
177 	return SUCCESS;
178 }
179 
180 
zend_startup_extensions()181 int zend_startup_extensions()
182 {
183 	zend_llist_apply_with_del(&zend_extensions, (int (*)(void *)) zend_extension_startup);
184 	return SUCCESS;
185 }
186 
187 
zend_shutdown_extensions(TSRMLS_D)188 void zend_shutdown_extensions(TSRMLS_D)
189 {
190 	zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_shutdown TSRMLS_CC);
191 	zend_llist_destroy(&zend_extensions);
192 }
193 
194 
zend_extension_dtor(zend_extension * extension)195 void zend_extension_dtor(zend_extension *extension)
196 {
197 #if ZEND_EXTENSIONS_SUPPORT && !ZEND_DEBUG
198 	if (extension->handle) {
199 		DL_UNLOAD(extension->handle);
200 	}
201 #endif
202 }
203 
204 
zend_extension_message_dispatcher(const zend_extension * extension,int num_args,va_list args TSRMLS_DC)205 static void zend_extension_message_dispatcher(const zend_extension *extension, int num_args, va_list args TSRMLS_DC)
206 {
207 	int message;
208 	void *arg;
209 
210 	if (!extension->message_handler || num_args!=2) {
211 		return;
212 	}
213 	message = va_arg(args, int);
214 	arg = va_arg(args, void *);
215 	extension->message_handler(message, arg);
216 }
217 
218 
zend_extension_dispatch_message(int message,void * arg)219 ZEND_API void zend_extension_dispatch_message(int message, void *arg)
220 {
221 	TSRMLS_FETCH();
222 
223 	zend_llist_apply_with_arguments(&zend_extensions, (llist_apply_with_args_func_t) zend_extension_message_dispatcher TSRMLS_CC, 2, message, arg);
224 }
225 
226 
zend_get_resource_handle(zend_extension * extension)227 ZEND_API int zend_get_resource_handle(zend_extension *extension)
228 {
229 	if (last_resource_number<ZEND_MAX_RESERVED_RESOURCES) {
230 		extension->resource_number = last_resource_number;
231 		return last_resource_number++;
232 	} else {
233 		return -1;
234 	}
235 }
236 
237 
zend_get_extension(const char * extension_name)238 ZEND_API zend_extension *zend_get_extension(const char *extension_name)
239 {
240 	zend_llist_element *element;
241 
242 	for (element = zend_extensions.head; element; element = element->next) {
243 		zend_extension *extension = (zend_extension *) element->data;
244 
245 		if (!strcmp(extension->name, extension_name)) {
246 			return extension;
247 		}
248 	}
249 	return NULL;
250 }
251 
252 /*
253  * Local variables:
254  * tab-width: 4
255  * c-basic-offset: 4
256  * indent-tabs-mode: t
257  * End:
258  */
259