1 : /*
2 : +----------------------------------------------------------------------+
3 : | Zend Engine |
4 : +----------------------------------------------------------------------+
5 : | Copyright (c) 1998-2009 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 286859 2009-08-06 01:33:54Z scottmac $ */
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(const 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 (strcmp(ZEND_EXTENSION_BUILD_ID, extension_version_info->build_id) &&
83 : (!new_extension->build_id_check || new_extension->build_id_check(ZEND_EXTENSION_BUILD_ID) != SUCCESS)) {
84 0 : fprintf(stderr, "Cannot load %s - it was built with configuration %s, whereas running engine is %s\n",
85 : new_extension->name, extension_version_info->build_id, ZEND_EXTENSION_BUILD_ID);
86 0 : DL_UNLOAD(handle);
87 0 : return FAILURE;
88 : }
89 :
90 0 : return zend_register_extension(new_extension, handle);
91 : #else
92 : fprintf(stderr, "Extensions are not supported on this platform.\n");
93 : return FAILURE;
94 : #endif
95 : }
96 :
97 :
98 : int zend_register_extension(zend_extension *new_extension, DL_HANDLE handle)
99 0 : {
100 : #if ZEND_EXTENSIONS_SUPPORT
101 : zend_extension extension;
102 :
103 0 : extension = *new_extension;
104 0 : extension.handle = handle;
105 :
106 0 : zend_extension_dispatch_message(ZEND_EXTMSG_NEW_EXTENSION, &extension);
107 :
108 0 : zend_llist_add_element(&zend_extensions, &extension);
109 :
110 : /*fprintf(stderr, "Loaded %s, version %s\n", extension.name, extension.version);*/
111 : #endif
112 :
113 0 : return SUCCESS;
114 : }
115 :
116 :
117 : static void zend_extension_shutdown(zend_extension *extension TSRMLS_DC)
118 0 : {
119 : #if ZEND_EXTENSIONS_SUPPORT
120 0 : if (extension->shutdown) {
121 0 : extension->shutdown(extension);
122 : }
123 : #endif
124 0 : }
125 :
126 : static int zend_extension_startup(zend_extension *extension)
127 0 : {
128 : #if ZEND_EXTENSIONS_SUPPORT
129 0 : if (extension->startup) {
130 0 : if (extension->startup(extension)!=SUCCESS) {
131 0 : return 1;
132 : }
133 0 : zend_append_version_info(extension);
134 : }
135 : #endif
136 0 : return 0;
137 : }
138 :
139 :
140 : int zend_startup_extensions_mechanism()
141 17633 : {
142 : /* Startup extensions mechanism */
143 17633 : zend_llist_init(&zend_extensions, sizeof(zend_extension), (void (*)(void *)) zend_extension_dtor, 1);
144 17633 : last_resource_number = 0;
145 17633 : return SUCCESS;
146 : }
147 :
148 :
149 : int zend_startup_extensions()
150 17633 : {
151 17633 : zend_llist_apply_with_del(&zend_extensions, (int (*)(void *)) zend_extension_startup);
152 17633 : return SUCCESS;
153 : }
154 :
155 :
156 : void zend_shutdown_extensions(TSRMLS_D)
157 17665 : {
158 17665 : zend_llist_apply(&zend_extensions, (llist_apply_func_t) zend_extension_shutdown TSRMLS_CC);
159 17665 : zend_llist_destroy(&zend_extensions);
160 17665 : }
161 :
162 :
163 : void zend_extension_dtor(zend_extension *extension)
164 0 : {
165 : #if ZEND_EXTENSIONS_SUPPORT && !ZEND_DEBUG
166 0 : if (extension->handle) {
167 0 : DL_UNLOAD(extension->handle);
168 : }
169 : #endif
170 0 : }
171 :
172 :
173 : static void zend_extension_message_dispatcher(const zend_extension *extension, int num_args, va_list args TSRMLS_DC)
174 0 : {
175 : int message;
176 : void *arg;
177 :
178 0 : if (!extension->message_handler || num_args!=2) {
179 0 : return;
180 : }
181 0 : message = va_arg(args, int);
182 0 : arg = va_arg(args, void *);
183 0 : extension->message_handler(message, arg);
184 : }
185 :
186 :
187 : ZEND_API void zend_extension_dispatch_message(int message, void *arg)
188 0 : {
189 : TSRMLS_FETCH();
190 :
191 0 : zend_llist_apply_with_arguments(&zend_extensions, (llist_apply_with_args_func_t) zend_extension_message_dispatcher TSRMLS_CC, 2, message, arg);
192 0 : }
193 :
194 :
195 : ZEND_API int zend_get_resource_handle(zend_extension *extension)
196 0 : {
197 0 : if (last_resource_number<ZEND_MAX_RESERVED_RESOURCES) {
198 0 : extension->resource_number = last_resource_number;
199 0 : return last_resource_number++;
200 : } else {
201 0 : return -1;
202 : }
203 : }
204 :
205 :
206 : ZEND_API zend_extension *zend_get_extension(const char *extension_name)
207 0 : {
208 : zend_llist_element *element;
209 :
210 0 : for (element = zend_extensions.head; element; element = element->next) {
211 0 : zend_extension *extension = (zend_extension *) element->data;
212 :
213 0 : if (!strcmp(extension->name, extension_name)) {
214 0 : return extension;
215 : }
216 : }
217 0 : return NULL;
218 : }
219 :
220 : /*
221 : * Local variables:
222 : * tab-width: 4
223 : * c-basic-offset: 4
224 : * indent-tabs-mode: t
225 : * End:
226 : */
|