| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | /* Support for dynamic loading of extension modules */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include <kernel/image.h>
 | 
					
						
							|  |  |  | #include <kernel/OS.h>
 | 
					
						
							|  |  |  | #include <stdlib.h>
 | 
					
						
							|  |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Python.h"
 | 
					
						
							|  |  |  | #include "importdl.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | const struct filedescr _PyImport_DynLoadFiletab[] = { | 
					
						
							|  |  |  | 	{".so", "rb", C_EXTENSION}, | 
					
						
							|  |  |  | 	{"module.so", "rb", C_EXTENSION}, | 
					
						
							|  |  |  | 	{0, 0} | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #if defined(MAXPATHLEN) && !defined(_SYS_PARAM_H)
 | 
					
						
							|  |  |  | #undef MAXPATHLEN
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WITH_THREAD
 | 
					
						
							|  |  |  | #include "pythread.h"
 | 
					
						
							|  |  |  | static PyThread_type_lock beos_dyn_lock; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static PyObject *beos_dyn_images = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* ----------------------------------------------------------------------
 | 
					
						
							|  |  |  |  * BeOS dynamic loading support | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * This uses shared libraries, but BeOS has its own way of doing things | 
					
						
							|  |  |  |  * (much easier than dlfnc.h, from the look of things).  We'll use a | 
					
						
							|  |  |  |  * Python Dictionary object to store the images_ids so we can be very | 
					
						
							|  |  |  |  * nice and unload them when we exit. | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * Note that this is thread-safe.  Probably irrelevent, because of losing | 
					
						
							|  |  |  |  * systems... Python probably disables threads while loading modules. | 
					
						
							|  |  |  |  * Note the use of "probably"!  Better to be safe than sorry. [chrish] | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * As of 1.5.1 this should also work properly when you've configured | 
					
						
							|  |  |  |  * Python without thread support; the 1.5 version required it, which wasn't | 
					
						
							|  |  |  |  * very friendly.  Note that I haven't tested it without threading... why | 
					
						
							|  |  |  |  * would you want to avoid threads on BeOS? [chrish] | 
					
						
							|  |  |  |  * | 
					
						
							|  |  |  |  * As of 1.5.2, the PyImport_BeImageID() function has been removed; Donn | 
					
						
							|  |  |  |  * tells me it's not necessary anymore because of PyCObject_Import(). | 
					
						
							|  |  |  |  * [chrish] | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* Whack an item; the item is an image_id in disguise, so we'll call
 | 
					
						
							|  |  |  |  * unload_add_on() for it. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void beos_nuke_dyn( PyObject *item ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	status_t retval; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( item ) { | 
					
						
							|  |  |  | 		image_id id = (image_id)PyInt_AsLong( item ); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		retval = unload_add_on( id ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /* atexit() handler that'll call unload_add_on() for every item in the
 | 
					
						
							|  |  |  |  * dictionary. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void beos_cleanup_dyn( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if( beos_dyn_images ) { | 
					
						
							|  |  |  | 		int idx; | 
					
						
							|  |  |  | 		int list_size; | 
					
						
							|  |  |  | 		PyObject *id_list; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WITH_THREAD
 | 
					
						
							|  |  |  | 		PyThread_acquire_lock( beos_dyn_lock, 1 ); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		id_list = PyDict_Values( beos_dyn_images ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		list_size = PyList_Size( id_list ); | 
					
						
							|  |  |  | 		for( idx = 0; idx < list_size; idx++ ) { | 
					
						
							|  |  |  | 			PyObject *the_item; | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 			the_item = PyList_GetItem( id_list, idx ); | 
					
						
							|  |  |  | 			beos_nuke_dyn( the_item ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyDict_Clear( beos_dyn_images ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WITH_THREAD
 | 
					
						
							|  |  |  | 		PyThread_free_lock( beos_dyn_lock ); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Initialize our dictionary, and the dictionary mutex. | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void beos_init_dyn( void ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	/* We're protected from a race condition here by the atomic init_count
 | 
					
						
							|  |  |  | 	 * variable. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	static int32 init_count = 0; | 
					
						
							|  |  |  | 	int32 val; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	val = atomic_add( &init_count, 1 ); | 
					
						
							|  |  |  | 	if( beos_dyn_images == NULL && val == 0 ) { | 
					
						
							|  |  |  | 		beos_dyn_images = PyDict_New(); | 
					
						
							|  |  |  | #ifdef WITH_THREAD
 | 
					
						
							|  |  |  | 		beos_dyn_lock = PyThread_allocate_lock(); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 		atexit( beos_cleanup_dyn ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | /*
 | 
					
						
							|  |  |  |  * Add an image_id to the dictionary; the module name of the loaded image | 
					
						
							|  |  |  |  * is the key.  Note that if the key is already in the dict, we unload | 
					
						
							|  |  |  |  * that image; this should allow reload() to work on dynamically loaded | 
					
						
							|  |  |  |  * modules (super-keen!). | 
					
						
							|  |  |  |  */ | 
					
						
							|  |  |  | static void beos_add_dyn( char *name, image_id id ) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	int retval; | 
					
						
							|  |  |  | 	PyObject *py_id; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if( beos_dyn_images == NULL ) { | 
					
						
							|  |  |  | 		beos_init_dyn(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WITH_THREAD
 | 
					
						
							|  |  |  | 	retval = PyThread_acquire_lock( beos_dyn_lock, 1 ); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* If there's already an object with this key in the dictionary,
 | 
					
						
							|  |  |  | 	 * we're doing a reload(), so let's nuke it. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	py_id = PyDict_GetItemString( beos_dyn_images, name ); | 
					
						
							|  |  |  | 	if( py_id ) { | 
					
						
							|  |  |  | 		beos_nuke_dyn( py_id ); | 
					
						
							|  |  |  | 		retval = PyDict_DelItemString( beos_dyn_images, name ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	py_id = PyInt_FromLong( (long)id ); | 
					
						
							|  |  |  | 	if( py_id ) { | 
					
						
							|  |  |  | 		retval = PyDict_SetItemString( beos_dyn_images, name, py_id ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef WITH_THREAD
 | 
					
						
							|  |  |  | 	PyThread_release_lock( beos_dyn_lock ); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-12-22 14:09:35 +00:00
										 |  |  | dl_funcptr _PyImport_GetDynLoadFunc(const char *fqname, const char *shortname, | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 				    const char *pathname, FILE *fp) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	dl_funcptr p; | 
					
						
							|  |  |  | 	image_id the_id; | 
					
						
							|  |  |  | 	status_t retval; | 
					
						
							|  |  |  | 	char fullpath[PATH_MAX]; | 
					
						
							| 
									
										
										
										
											1999-12-22 14:09:35 +00:00
										 |  |  | 	char funcname[258]; | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if( Py_VerboseFlag ) { | 
					
						
							|  |  |  | 		printf( "load_add_on( %s )\n", pathname ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Hmm, this old bug appears to have regenerated itself; if the
 | 
					
						
							|  |  |  | 	 * path isn't absolute, load_add_on() will fail.  Reported to Be | 
					
						
							|  |  |  | 	 * April 21, 1998. | 
					
						
							|  |  |  | 	 */ | 
					
						
							|  |  |  | 	if( pathname[0] != '/' ) { | 
					
						
							|  |  |  | 		(void)getcwd( fullpath, PATH_MAX ); | 
					
						
							|  |  |  | 		(void)strncat( fullpath, "/", PATH_MAX ); | 
					
						
							|  |  |  | 		(void)strncat( fullpath, pathname, PATH_MAX ); | 
					
						
							|  |  |  | 			 | 
					
						
							|  |  |  | 		if( Py_VerboseFlag ) { | 
					
						
							|  |  |  | 			printf( "load_add_on( %s )\n", fullpath ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} else { | 
					
						
							|  |  |  | 		(void)strcpy( fullpath, pathname ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	the_id = load_add_on( fullpath ); | 
					
						
							|  |  |  | 	if( the_id < B_NO_ERROR ) { | 
					
						
							|  |  |  | 		/* It's too bad load_add_on() doesn't set errno or something...
 | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		char buff[256];  /* hate hard-coded string sizes... */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( Py_VerboseFlag ) { | 
					
						
							|  |  |  | 			printf( "load_add_on( %s ) failed", fullpath ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch( the_id ) { | 
					
						
							|  |  |  | 		case B_ERROR: | 
					
						
							|  |  |  | 			sprintf( buff, "BeOS: Failed to load %.200s", fullpath ); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			sprintf( buff, "Unknown error loading %.200s", fullpath ); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyErr_SetString( PyExc_ImportError, buff ); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											1999-12-22 14:09:35 +00:00
										 |  |  | 	sprintf(funcname, "init%.200s", shortname); | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 	if( Py_VerboseFlag ) { | 
					
						
							|  |  |  | 		printf( "get_image_symbol( %s )\n", funcname ); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	retval = get_image_symbol( the_id, funcname, B_SYMBOL_TYPE_TEXT, &p ); | 
					
						
							|  |  |  | 	if( retval != B_NO_ERROR || p == NULL ) { | 
					
						
							|  |  |  | 		/* That's bad, we can't find that symbol in the module...
 | 
					
						
							|  |  |  | 		 */ | 
					
						
							|  |  |  | 		char buff[256];  /* hate hard-coded string sizes... */ | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if( Py_VerboseFlag ) { | 
					
						
							|  |  |  | 			printf( "get_image_symbol( %s ) failed", funcname ); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		switch( retval ) { | 
					
						
							|  |  |  | 		case B_BAD_IMAGE_ID: | 
					
						
							|  |  |  | 			sprintf( buff, "can't load init function for dynamic module: " | 
					
						
							|  |  |  | 			               "Invalid image ID for %.180s", fullpath ); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		case B_BAD_INDEX: | 
					
						
							|  |  |  | 			sprintf( buff, "can't load init function for dynamic module: " | 
					
						
							|  |  |  | 			               "Bad index for %.180s", funcname ); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		default: | 
					
						
							|  |  |  | 			sprintf( buff, "can't load init function for dynamic module: " | 
					
						
							|  |  |  | 			               "Unknown error looking up %.180s", funcname ); | 
					
						
							|  |  |  | 			break; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		retval = unload_add_on( the_id ); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PyErr_SetString( PyExc_ImportError, buff ); | 
					
						
							|  |  |  | 		return NULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	/* Save the module name and image ID for later so we can clean up
 | 
					
						
							|  |  |  | 	 * gracefully. | 
					
						
							|  |  |  | 	 */ | 
					
						
							| 
									
										
										
										
											1999-12-22 14:09:35 +00:00
										 |  |  | 	beos_add_dyn( fqname, the_id ); | 
					
						
							| 
									
										
										
										
											1999-12-20 21:18:49 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	return p; | 
					
						
							|  |  |  | } |