/* -*- C -*- * FILE: "/home/joze/pub/zimg/zimg/dynaload.c" * LAST MODIFICATION: "Wed, 02 Jul 2003 21:12:22 CEST (joze)" * (C) 2003 by Johannes Zellner, * $Id: dynaload.c,v 1.10 2003/07/02 19:19:56 joze Exp $ */ #ifdef HAVE_CONFIG_H # include "config.h" #endif #ifdef HAVE_DLFCN_H # include #elif defined HAVE_DL_H # include #endif #if defined(HAVE_DLSYM) || defined(HAVE_SHL_LOAD) #include "dynaload.h" #include "path.h" #include #include #include #include #include #include #include static const char* dynaload_zimg_expression = "zimg_expression"; static void* dynaload_lib = (void*)0; static zimg_expression_t dynaload_expression_func = (zimg_expression_t)0; extern int debug; static char get_random_char(void) { static const char* const str = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; static const double len = 62; /* length of 'str': 2 * 26 + 10 */ return str[(int)(drand48() * len)]; } static char* tempname_pair(char* suffix1, char* suffix2) { char* tmpdir = getenv("TMPDIR"); char root[0xff]; char file1[0xff]; char file2[0xff]; unsigned int i; srand48((long int)time((time_t*)0)); for (i = 0; i < 99999; i++) { char* ptr; char* endptr; if (tmpdir) { strcpy(root, tmpdir); strcat(root, "/"); strcat(root, "file"); } else { strcpy(root, "file"); } for (ptr = strchr(root, '\0'), endptr = ptr + 6; ptr < endptr; ptr++) { *ptr = get_random_char(); } *ptr = '\0'; /* null terminate */ strcpy(file1, root); strcat(file1, suffix1); strcpy(file2, root); strcat(file2, suffix2); if (access(file1, F_OK) && access(file2, F_OK)) { if (debug) fprintf(stderr, "(tempname_pair) root = |%s|\n", root); return strdup(root); } } return (char*)0; } char* dynaload_compile(char* expression, char* dynaload_source, char* dynaload_dest) { char* root = (char*)0; char* source = (char*)0; char* dest = (char*)0; char* compilestring = (char*)0; int ret; if (!dynaload_source || !dynaload_dest) root = tempname_pair(".c", ".so"); if (!dynaload_source) { source = malloc(sizeof (char) * ((strlen(root) + 5))); if (!source) { perror("dynaload_compile->source"); exit(2); } strcpy(source, root); strcat(source, ".c"); } else { source = dynaload_source; } if (!dynaload_dest) { dest = malloc(sizeof (char) * ((strlen(root) + 5))); if (!dest) { perror("dynaload_compile->dest"); exit(2); } strcpy(dest, root); strcat(dest, ".so"); } else { dest = dynaload_dest; } /* write source file */ if (expression) { FILE* fp = fopen(source, "w"); if (!fp) { perror(source); exit(2); } fprintf(fp, "#include \n" "#include \n" "float\n" "%s(unsigned int ix, unsigned int iy,\n" " float x, float y, float z,\n" " const zimg_expression_info_t* info)\n" "{\n" " volatile unsigned int width = info->width;\n" " volatile unsigned int height = info->height;\n" " return %s;\n" "}\n", dynaload_zimg_expression, expression); fclose(fp); } else { /* check if source file is readable */ if (access(source, R_OK)) { fprintf(stderr, "** Error: source file %s is not readable\n", source); exit(2); } } /* create compilestring */ compilestring = (char*)malloc(sizeof (char) * ( strlen(DYNALOAD_CC) + strlen(DYNALOAD_CFLAGS) + strlen(source) + strlen(dest) + 100 )); if (!compilestring) { perror("dynaload->compilestring"); exit(2); } strcpy(compilestring, DYNALOAD_CC); strcat(compilestring, " -I. -I"); strcat(compilestring, INCLUDEDIR); strcat(compilestring, " "); strcat(compilestring, DYNALOAD_CFLAGS); strcat(compilestring, " "); strcat(compilestring, dest); strcat(compilestring, " "); strcat(compilestring, source); if (debug) fprintf(stderr, "(dynaload_compile) compilestring = %s\n", compilestring); ret = system(compilestring); if (ret) { fprintf(stderr, "** Error:\n%s\nreturned non-zero (%d)\n", compilestring, ret); if (!dynaload_dest) free(dest); dest = (char*)0; } if (!dynaload_source) { unlink(source); free(source); } free(compilestring); free(root); return dest; } zimg_expression_t dynaload_expression_load(const char* objectfile) { char* objectptr = (char*)0; assert(objectfile); objectptr = search_file(objectfile, "expr", PKGLIBDIR, 1 /* absolute */); #ifdef HAVE_DLSYM dynaload_lib = dlopen(objectptr, RTLD_NOW # ifdef RTLD_LOCAL | RTLD_LOCAL # endif ); if (!dynaload_lib) { fprintf(stderr, "dynaload_expression_load->dlopen: %s\n", dlerror()); exit(2); } dynaload_expression_func = (zimg_expression_t)dlsym(dynaload_lib, dynaload_zimg_expression); if (debug) fprintf(stderr, "(dynaload_expression_load) dynaload_expression_func = %p\n", dynaload_expression_func); #elif defined HAVE_SHL_LOAD /* TODO not tested !!! */ dynaload_lib = shl_load(objectptr, BIND_IMMEDIATE|BIND_VERBOSE, 0L); if (shl_findsym(&dynaload_lib, dynaload_zimg_expression, TYPE_PROCEDURE, (void*)&dynaload_expression_func) < 0) dynaload_expression_func = (zimg_expression_t)0; #endif if (objectptr) free(objectptr); return dynaload_expression_func; } void dynaload_expression_unload(void) { if (dynaload_lib) { #ifdef HAVE_DLSYM dlclose(dynaload_lib); #elif defined HAVE_SHL_LOAD shl_unload(dynaload_lib); #endif } } #endif /* defined(HAVE_DLSYM) || defined(HAVE_SHL_LOAD) */