xref: /PHP-5.5/Zend/zend_extensions.c (revision 73c1be26)
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