Return to dl.c CVS log | Up to [ELWIX - Embedded LightWeight unIX -] / embedaddon / php / ext / standard |
1.1 ! misho 1: /* ! 2: +----------------------------------------------------------------------+ ! 3: | PHP Version 5 | ! 4: +----------------------------------------------------------------------+ ! 5: | Copyright (c) 1997-2012 The PHP Group | ! 6: +----------------------------------------------------------------------+ ! 7: | This source file is subject to version 3.01 of the PHP 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.php.net/license/3_01.txt | ! 11: | If you did not receive a copy of the PHP license and are unable to | ! 12: | obtain it through the world-wide-web, please send a note to | ! 13: | license@php.net so we can mail you a copy immediately. | ! 14: +----------------------------------------------------------------------+ ! 15: | Authors: Brian Schaffner <brian@tool.net> | ! 16: | Shane Caraveo <shane@caraveo.com> | ! 17: | Zeev Suraski <zeev@zend.com> | ! 18: +----------------------------------------------------------------------+ ! 19: */ ! 20: ! 21: /* $Id: dl.c 321634 2012-01-01 13:15:04Z felipe $ */ ! 22: ! 23: #include "php.h" ! 24: #include "dl.h" ! 25: #include "php_globals.h" ! 26: #include "php_ini.h" ! 27: #include "ext/standard/info.h" ! 28: ! 29: #include "SAPI.h" ! 30: ! 31: #if defined(HAVE_LIBDL) ! 32: #include <stdlib.h> ! 33: #include <stdio.h> ! 34: #ifdef HAVE_STRING_H ! 35: #include <string.h> ! 36: #else ! 37: #include <strings.h> ! 38: #endif ! 39: #ifdef PHP_WIN32 ! 40: #include "win32/param.h" ! 41: #include "win32/winutil.h" ! 42: #define GET_DL_ERROR() php_win_err() ! 43: #elif defined(NETWARE) ! 44: #include <sys/param.h> ! 45: #define GET_DL_ERROR() dlerror() ! 46: #else ! 47: #include <sys/param.h> ! 48: #define GET_DL_ERROR() DL_ERROR() ! 49: #endif ! 50: #endif /* defined(HAVE_LIBDL) */ ! 51: ! 52: /* {{{ proto int dl(string extension_filename) ! 53: Load a PHP extension at runtime */ ! 54: PHPAPI PHP_FUNCTION(dl) ! 55: { ! 56: char *filename; ! 57: int filename_len; ! 58: ! 59: if (zend_parse_parameters(ZEND_NUM_ARGS() TSRMLS_CC, "s", &filename, &filename_len) == FAILURE) { ! 60: return; ! 61: } ! 62: ! 63: if (!PG(enable_dl)) { ! 64: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extensions aren't enabled"); ! 65: RETURN_FALSE; ! 66: } else if (PG(safe_mode)) { ! 67: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Dynamically loaded extensions aren't allowed when running in Safe Mode"); ! 68: RETURN_FALSE; ! 69: } ! 70: ! 71: if (filename_len >= MAXPATHLEN) { ! 72: php_error_docref(NULL TSRMLS_CC, E_WARNING, "File name exceeds the maximum allowed length of %d characters", MAXPATHLEN); ! 73: RETURN_FALSE; ! 74: } ! 75: ! 76: if ((strncmp(sapi_module.name, "cgi", 3) != 0) && ! 77: (strcmp(sapi_module.name, "cli") != 0) && ! 78: (strncmp(sapi_module.name, "embed", 5) != 0) ! 79: ) { ! 80: #ifdef ZTS ! 81: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Not supported in multithreaded Web servers - use extension=%s in your php.ini", filename); ! 82: RETURN_FALSE; ! 83: #else ! 84: php_error_docref(NULL TSRMLS_CC, E_DEPRECATED, "dl() is deprecated - use extension=%s in your php.ini", filename); ! 85: #endif ! 86: } ! 87: ! 88: php_dl(filename, MODULE_TEMPORARY, return_value, 0 TSRMLS_CC); ! 89: if (Z_LVAL_P(return_value) == 1) { ! 90: EG(full_tables_cleanup) = 1; ! 91: } ! 92: } ! 93: /* }}} */ ! 94: ! 95: #if defined(HAVE_LIBDL) ! 96: ! 97: #ifdef ZTS ! 98: #define USING_ZTS 1 ! 99: #else ! 100: #define USING_ZTS 0 ! 101: #endif ! 102: ! 103: /* {{{ php_dl ! 104: */ ! 105: PHPAPI int php_load_extension(char *filename, int type, int start_now TSRMLS_DC) /* {{{ */ ! 106: { ! 107: void *handle; ! 108: char *libpath; ! 109: zend_module_entry *module_entry; ! 110: zend_module_entry *(*get_module)(void); ! 111: int error_type; ! 112: char *extension_dir; ! 113: ! 114: if (type == MODULE_PERSISTENT) { ! 115: extension_dir = INI_STR("extension_dir"); ! 116: } else { ! 117: extension_dir = PG(extension_dir); ! 118: } ! 119: ! 120: if (type == MODULE_TEMPORARY) { ! 121: error_type = E_WARNING; ! 122: } else { ! 123: error_type = E_CORE_WARNING; ! 124: } ! 125: ! 126: /* Check if passed filename contains directory separators */ ! 127: if (strchr(filename, '/') != NULL || strchr(filename, DEFAULT_SLASH) != NULL) { ! 128: /* Passing modules with full path is not supported for dynamically loaded extensions */ ! 129: if (type == MODULE_TEMPORARY) { ! 130: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Temporary module name should contain only filename"); ! 131: return FAILURE; ! 132: } ! 133: libpath = estrdup(filename); ! 134: } else if (extension_dir && extension_dir[0]) { ! 135: int extension_dir_len = strlen(extension_dir); ! 136: ! 137: if (IS_SLASH(extension_dir[extension_dir_len-1])) { ! 138: spprintf(&libpath, 0, "%s%s", extension_dir, filename); /* SAFE */ ! 139: } else { ! 140: spprintf(&libpath, 0, "%s%c%s", extension_dir, DEFAULT_SLASH, filename); /* SAFE */ ! 141: } ! 142: } else { ! 143: return FAILURE; /* Not full path given or extension_dir is not set */ ! 144: } ! 145: ! 146: /* load dynamic symbol */ ! 147: handle = DL_LOAD(libpath); ! 148: if (!handle) { ! 149: #if PHP_WIN32 ! 150: char *err = GET_DL_ERROR(); ! 151: if (err && (*err != "")) { ! 152: php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, err); ! 153: LocalFree(err); ! 154: } else { ! 155: php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, "Unknown reason"); ! 156: } ! 157: #else ! 158: php_error_docref(NULL TSRMLS_CC, error_type, "Unable to load dynamic library '%s' - %s", libpath, GET_DL_ERROR()); ! 159: GET_DL_ERROR(); /* free the buffer storing the error */ ! 160: #endif ! 161: efree(libpath); ! 162: return FAILURE; ! 163: } ! 164: efree(libpath); ! 165: ! 166: get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "get_module"); ! 167: ! 168: /* Some OS prepend _ to symbol names while their dynamic linker ! 169: * does not do that automatically. Thus we check manually for ! 170: * _get_module. */ ! 171: ! 172: if (!get_module) { ! 173: get_module = (zend_module_entry *(*)(void)) DL_FETCH_SYMBOL(handle, "_get_module"); ! 174: } ! 175: ! 176: if (!get_module) { ! 177: DL_UNLOAD(handle); ! 178: php_error_docref(NULL TSRMLS_CC, error_type, "Invalid library (maybe not a PHP library) '%s'", filename); ! 179: return FAILURE; ! 180: } ! 181: module_entry = get_module(); ! 182: if (module_entry->zend_api != ZEND_MODULE_API_NO) { ! 183: /* Check for pre-4.1.0 module which has a slightly different module_entry structure :( */ ! 184: struct pre_4_1_0_module_entry { ! 185: char *name; ! 186: zend_function_entry *functions; ! 187: int (*module_startup_func)(INIT_FUNC_ARGS); ! 188: int (*module_shutdown_func)(SHUTDOWN_FUNC_ARGS); ! 189: int (*request_startup_func)(INIT_FUNC_ARGS); ! 190: int (*request_shutdown_func)(SHUTDOWN_FUNC_ARGS); ! 191: void (*info_func)(ZEND_MODULE_INFO_FUNC_ARGS); ! 192: int (*global_startup_func)(void); ! 193: int (*global_shutdown_func)(void); ! 194: int globals_id; ! 195: int module_started; ! 196: unsigned char type; ! 197: void *handle; ! 198: int module_number; ! 199: unsigned char zend_debug; ! 200: unsigned char zts; ! 201: unsigned int zend_api; ! 202: }; ! 203: ! 204: const char *name; ! 205: int zend_api; ! 206: ! 207: if ((((struct pre_4_1_0_module_entry *)module_entry)->zend_api > 20000000) && ! 208: (((struct pre_4_1_0_module_entry *)module_entry)->zend_api < 20010901) ! 209: ) { ! 210: name = ((struct pre_4_1_0_module_entry *)module_entry)->name; ! 211: zend_api = ((struct pre_4_1_0_module_entry *)module_entry)->zend_api; ! 212: } else { ! 213: name = module_entry->name; ! 214: zend_api = module_entry->zend_api; ! 215: } ! 216: ! 217: php_error_docref(NULL TSRMLS_CC, error_type, ! 218: "%s: Unable to initialize module\n" ! 219: "Module compiled with module API=%d\n" ! 220: "PHP compiled with module API=%d\n" ! 221: "These options need to match\n", ! 222: name, zend_api, ZEND_MODULE_API_NO); ! 223: DL_UNLOAD(handle); ! 224: return FAILURE; ! 225: } ! 226: if(strcmp(module_entry->build_id, ZEND_MODULE_BUILD_ID)) { ! 227: php_error_docref(NULL TSRMLS_CC, error_type, ! 228: "%s: Unable to initialize module\n" ! 229: "Module compiled with build ID=%s\n" ! 230: "PHP compiled with build ID=%s\n" ! 231: "These options need to match\n", ! 232: module_entry->name, module_entry->build_id, ZEND_MODULE_BUILD_ID); ! 233: DL_UNLOAD(handle); ! 234: return FAILURE; ! 235: } ! 236: module_entry->type = type; ! 237: module_entry->module_number = zend_next_free_module(); ! 238: module_entry->handle = handle; ! 239: ! 240: if ((module_entry = zend_register_module_ex(module_entry TSRMLS_CC)) == NULL) { ! 241: DL_UNLOAD(handle); ! 242: return FAILURE; ! 243: } ! 244: ! 245: if ((type == MODULE_TEMPORARY || start_now) && zend_startup_module_ex(module_entry TSRMLS_CC) == FAILURE) { ! 246: DL_UNLOAD(handle); ! 247: return FAILURE; ! 248: } ! 249: ! 250: if ((type == MODULE_TEMPORARY || start_now) && module_entry->request_startup_func) { ! 251: if (module_entry->request_startup_func(type, module_entry->module_number TSRMLS_CC) == FAILURE) { ! 252: php_error_docref(NULL TSRMLS_CC, error_type, "Unable to initialize module '%s'", module_entry->name); ! 253: DL_UNLOAD(handle); ! 254: return FAILURE; ! 255: } ! 256: } ! 257: ! 258: #if SUHOSIN_PATCH ! 259: if (strncmp("suhosin", module_entry->name, sizeof("suhosin")-1) == 0) { ! 260: void *log_func; ! 261: /* sucessfully loaded suhosin extension, now check for logging function replacement */ ! 262: log_func = (void *) DL_FETCH_SYMBOL(handle, "suhosin_log"); ! 263: if (log_func == NULL) { ! 264: log_func = (void *) DL_FETCH_SYMBOL(handle, "_suhosin_log"); ! 265: } ! 266: if (log_func != NULL) { ! 267: zend_suhosin_log = log_func; ! 268: } else { ! 269: zend_suhosin_log(S_MISC, "could not replace logging function"); ! 270: } ! 271: } ! 272: #endif ! 273: ! 274: return SUCCESS; ! 275: } ! 276: /* }}} */ ! 277: ! 278: /* {{{ php_dl ! 279: */ ! 280: PHPAPI void php_dl(char *file, int type, zval *return_value, int start_now TSRMLS_DC) ! 281: { ! 282: /* Load extension */ ! 283: if (php_load_extension(file, type, start_now TSRMLS_CC) == FAILURE) { ! 284: RETVAL_FALSE; ! 285: } else { ! 286: RETVAL_TRUE; ! 287: } ! 288: } ! 289: /* }}} */ ! 290: ! 291: PHP_MINFO_FUNCTION(dl) ! 292: { ! 293: php_info_print_table_row(2, "Dynamic Library Support", "enabled"); ! 294: } ! 295: ! 296: #else ! 297: ! 298: PHPAPI void php_dl(char *file, int type, zval *return_value, int start_now TSRMLS_DC) ! 299: { ! 300: php_error_docref(NULL TSRMLS_CC, E_WARNING, "Cannot dynamically load %s - dynamic modules are not supported", file); ! 301: RETURN_FALSE; ! 302: } ! 303: ! 304: PHP_MINFO_FUNCTION(dl) ! 305: { ! 306: PUTS("Dynamic Library support not available<br />.\n"); ! 307: } ! 308: ! 309: #endif ! 310: ! 311: /* ! 312: * Local variables: ! 313: * tab-width: 4 ! 314: * c-basic-offset: 4 ! 315: * End: ! 316: * vim600: sw=4 ts=4 fdm=marker ! 317: * vim<600: sw=4 ts=4 ! 318: */