zend_extensions.c 7.5 KB

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