From 35a201cc8ef0c3f5b2df88d2e528aabee1048348 Mon Sep 17 00:00:00 2001 From: Wojtek Kosior Date: Fri, 30 Apr 2021 18:47:09 +0200 Subject: Initial/Final commit --- libxml2-2.9.10/os400/dlfcn/dlfcn.c | 1213 ++++++++++++++++++++++++++++++++++++ 1 file changed, 1213 insertions(+) create mode 100644 libxml2-2.9.10/os400/dlfcn/dlfcn.c (limited to 'libxml2-2.9.10/os400/dlfcn/dlfcn.c') diff --git a/libxml2-2.9.10/os400/dlfcn/dlfcn.c b/libxml2-2.9.10/os400/dlfcn/dlfcn.c new file mode 100644 index 0000000..77190b3 --- /dev/null +++ b/libxml2-2.9.10/os400/dlfcn/dlfcn.c @@ -0,0 +1,1213 @@ +/** +*** dlopen(), dlclose() dlsym(), dlerror() emulation for OS/400. +*** +*** See Copyright for the status of this software. +*** +*** Author: Patrick Monnerat , DATASPHERE S.A. +**/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include +#include + +#include /* AS400 exceptions. */ +#include /* MI pointers support. */ +#include /* Error structures. */ +#include /* Path to QSYS object name. */ +#include /* For Qp0zInitEnv(). */ +#include /* For QleActBndPgmLong() definitions. */ +#include /* Qualified name structure. */ +#include /* Retrieve message from message file. */ + +#include +#include + +#include "libxml/hash.h" +#include "dlfcn.h" + + +/** +*** Maximum internal path length. +**/ + +#define MAXPATHLEN 5120 + + +/** +*** Maximum error string length. +**/ + +#define MAX_ERR_STR 511 + + +/** +*** Field address macro. +**/ + +#define offset_by(t, b, o) ((t *) ((char *) (b) + (unsigned int) (o))) + + +/** +*** Global flags. +**/ + +#define INITED 000001 /* Package has been initialized. */ +#define THREADS 000002 /* Multithreaded job. */ +#define MULTIBUF 000004 /* One error buffer per thread. */ + + +/** +*** DLL handle private structure. +**/ + +typedef struct { + Qle_ABP_Info_Long_t actinfo; /* Activation information. */ + _SYSPTR pointer; /* Pointer to DLL object. */ + unsigned int actcount; /* Activation count. */ +} dlinfo; + + +/** +*** Per-thread structure. +**/ + +typedef struct { + unsigned int lockcount; /* Mutex lock count. */ + unsigned int iserror; /* Flag error present. */ + char str[MAX_ERR_STR + 1]; /* Error string buffer. */ +} dlts_t; + + +static pthread_mutex_t dlmutex = PTHREAD_MUTEX_INITIALIZER; +static xmlHashTablePtr dldir = (xmlHashTablePtr) NULL; /* DLL directory. */ +static unsigned int dlflags = 0; /* Package flags. */ +static pthread_key_t dlkey; +static dlts_t static_buf; /* Static error buffer. */ + + + +static void +dlthreadterm(void * mem) + +{ + free(mem); + pthread_setspecific(dlkey, NULL); +} + + +static void +dlterm(void) + +{ + void * p; + + if (dlflags & MULTIBUF) { + p = pthread_getspecific(dlkey); + + if (p) + dlthreadterm(p); + } + + if (dlflags & THREADS) + pthread_mutex_lock(&dlmutex); + + if (dldir) { + xmlHashFree(dldir, (xmlHashDeallocator) NULL); + dldir = NULL; + } + + if (dlflags & MULTIBUF) + pthread_key_delete(dlkey); + + dlflags |= ~(INITED | MULTIBUF); + pthread_mutex_unlock(&dlmutex); + pthread_mutex_destroy(&dlmutex); +} + + +static void +dlinit(void) + +{ + int locked; + + /** + *** Initialize the package. + *** Should be call once per process. + **/ + + locked = !pthread_mutex_lock(&dlmutex); + + if (!(dlflags & INITED)) { + dlflags &= ~THREADS; + + if (locked) + dlflags |= THREADS; + + Qp0zInitEnv(); + dldir = xmlHashCreate(16); + dlflags &= ~MULTIBUF; + + if (dlflags & THREADS) + if (!pthread_key_create(&dlkey, dlthreadterm)) + dlflags |= MULTIBUF; + + atexit(dlterm); + dlflags |= INITED; + } + + if (locked) + pthread_mutex_unlock(&dlmutex); +} + + +static void +dlthreadinit(void) + +{ + dlts_t * p; + + if (!(dlflags & INITED)) + dlinit(); + + if (dlflags & MULTIBUF) { + p = pthread_getspecific(dlkey); + + if (!p) { + p = (dlts_t *) malloc(sizeof *p); + + if (p) { + p->lockcount = 0; + p->iserror = 0; + + if (pthread_setspecific(dlkey, p)) + free(p); + } + } + } +} + + +static void +dllock(void) + +{ + dlts_t * p; + + if (!(dlflags & THREADS)) + return; + + if (dlflags & MULTIBUF) { + p = pthread_getspecific(dlkey); + + if (p && p->lockcount) { + p->lockcount++; + return; + } + } + else + p = (dlts_t *) NULL; + + if (pthread_mutex_lock(&dlmutex)) + return; + + if (p) + p->lockcount++; +} + + +static void +dlunlock(void) + +{ + dlts_t * p; + + if (!(dlflags & THREADS)) + return; + + if (dlflags & MULTIBUF) { + p = pthread_getspecific(dlkey); + + if (p && p->lockcount > 1) { + p->lockcount--; + return; + } + } + else + p = (dlts_t *) NULL; + + if (pthread_mutex_unlock(&dlmutex)) + return; + + if (p) + p->lockcount--; +} + + +const char * +dlerror(void) + +{ + dlts_t * p; + + dlthreadinit(); + + if (!(dlflags & MULTIBUF)) + p = &static_buf; + else if (!(p = (dlts_t *) pthread_getspecific(dlkey))) + p = &static_buf; + + if (!p->iserror) + return (const char *) NULL; + + p->iserror = 0; + return p->str; +} + + +static void +dlseterror_from_errno(unsigned int err_no) + +{ + dlts_t * p; + + if (!(dlflags & MULTIBUF)) + p = &static_buf; + else if (!(p = (dlts_t *) pthread_getspecific(dlkey))) + p = &static_buf; + + strcpy(p->str, strerror(err_no)); + p->iserror = 1; +} + + +static void +dlseterror_from_exception(volatile _INTRPT_Hndlr_Parms_T * excp) + +{ + int i; + Qmh_Rtvm_RTVM0300_t * imp; + char * cp; + _INTRPT_Hndlr_Parms_T * p; + dlts_t * q; + char rtvmbuf[30000]; + Qus_EC_t errinfo; + + p = (_INTRPT_Hndlr_Parms_T *) excp; + errinfo.Bytes_Provided = 0; /* Exception on error. */ + QMHRTVM(rtvmbuf, sizeof rtvmbuf, "RTVM0300", p->Msg_Id, + "QCPFMSG QSYS ", p->Ex_Data, p->Msg_Data_Len, + "*YES ", "*NO ", &errinfo); + imp = offset_by(Qmh_Rtvm_RTVM0300_t, rtvmbuf, 0); + + if (!(dlflags & MULTIBUF)) + q = &static_buf; + else if (!(q = (dlts_t *) pthread_getspecific(dlkey))) + q = &static_buf; + + if (i = imp->Length_Message_Returned) + cp = offset_by(char, imp, imp->Offset_Message_Returned); + else if (i = imp->Length_Help_Returned) + cp = offset_by(char, imp, imp->Offset_Help_Returned); + else { + q->iserror = 0; + return; + } + + q->iserror = 1; + + if (i > sizeof q->str - 1) + i = sizeof q->str - 1; + + memcpy(q->str, cp, i); + q->str[i] = '\0'; +} + + +static int +dlparentpath(const char * path, size_t len) + +{ + if (len <= 1) + return len; + + while (path[--len] != '/') + ; + + return len? len: 1; +} + + +static int +dlmakepath(char * path, size_t pathlen, const char * tail, size_t taillen) + +{ + int i; + + if (taillen && tail[0] == '/') + pathlen = 0; + + for (;;) { + while (taillen && *tail == '/') { + tail++; + taillen--; + } + + if (!taillen) + break; + + for (i = 0; i < taillen; i++) + if (tail[i] == '/') + break; + + if (*tail == '.') + switch (i) { + + case 2: + if (tail[1] != '.') + break; + + pathlen = dlparentpath(path, pathlen); + + case 1: + tail += i; + taillen -= i; + continue; + } + + if (pathlen + i + 1 >= MAXPATHLEN) { + errno = ENAMETOOLONG; + return -1; + } + + path[pathlen++] = '/'; + memcpy(path + pathlen, tail, i); + pathlen += i; + } + + if (!pathlen) + path[pathlen++] = '/'; + + path[pathlen] = '\0'; + return pathlen; +} + + +static int +dlresolveLink(const char * path, char * buf, size_t bufsiz) + +{ + int n; + int l1; + int l2; + struct stat sbuf; + char buf1[MAXPATHLEN + 1]; + char buf2[MAXPATHLEN + 1]; + + /** + *** Resolve symbolic link to IFS object name. + **/ + + if (!buf) { + errno = EFAULT; + return -1; + } + + if (!path || !*path || !bufsiz) { + errno = EINVAL; + return -1; + } + + if (*path != '/') { + if (!getcwd(buf1, sizeof buf1)) + return -1; + + l1 = strlen(buf1); + } + else + l1 = 0; + + l1 = dlmakepath(buf1, l1, path, strlen(path)); + n = 0; + + for (;;) { + if (l1 < 0) + return -1; + + if (n++ >= 256) { + errno = ELOOP; + return -1; + } + + if (lstat(buf1, &sbuf)) { + if (errno == ENOENT) + break; + + return -1; + } + + if (!S_ISLNK(sbuf.st_mode)) + break; + + if (sbuf.st_size > MAXPATHLEN) { + errno = ENAMETOOLONG; + return -1; + } + + l2 = readlink(buf1, buf2, MAXPATHLEN + 1); + + if (l2 < 0) + return -1; + + if (buf2[0] != '/') + l1 = dlparentpath(buf1, l1); + + l1 = dlmakepath(buf1, l1, buf2, l2); + } + + if (l1 >= bufsiz) { + errno = ENAMETOOLONG; + return -1; + } + + memcpy(buf, buf1, l1 + 1); + return l1; +} + + +static int +dlGetObjectName(Qp0l_QSYS_Info_t * qsysinfo, const char * dir, + int dirlen, const char * link) + +{ + int n; + char * namebuf; + Qlg_Path_Name_T * qptp; + char pathbuf[sizeof(Qlg_Path_Name_T) + _QP0L_DIR_NAME_LG + 4]; + Qus_EC_t errinfo; + struct stat sbuf; + + /** + *** Get QSYS object library/name/member and type corresponding to + *** the symbolic `link' in directory `dir'. + **/ + + if (!qsysinfo) { + errno = EFAULT; + return -1; + } + + if (!dir && !link) { + errno = EINVAL; + return -1; + } + + qptp = (Qlg_Path_Name_T *) pathbuf; + namebuf = pathbuf + sizeof(Qlg_Path_Name_T); + n = 0; + + /** + *** Build full path. + **/ + + if (dir) { + if (dirlen < 0 || dirlen > _QP0L_DIR_NAME_LG + 4) + dirlen = _QP0L_DIR_NAME_LG + 4; + + while (*dir && n < dirlen) + namebuf[n++] = *dir++; + } + + if (n && namebuf[n - 1] == '/') + n--; + + if (link) { + if (*link && *link != '/' && n < _QP0L_DIR_NAME_LG + 4) + namebuf[n++] = '/'; + + while (*link && n < _QP0L_DIR_NAME_LG + 4) + namebuf[n++] = *link++; + } + + if (!n || n > _QP0L_DIR_NAME_LG) { + errno = ENAMETOOLONG; + return -1; + } + + namebuf[n] = '\0'; + n = dlresolveLink(namebuf, namebuf, _QP0L_DIR_NAME_LG + 1); + + if (n == -1) + return -1; + + if (stat(namebuf, &sbuf)) + return -1; + + memset((char *) qptp, 0, sizeof *qptp); + qptp->Path_Length = n; + qptp->Path_Name_Delimiter[0] = '/'; + errinfo.Bytes_Provided = sizeof errinfo; + Qp0lCvtPathToQSYSObjName(qptp, qsysinfo, "QSYS0100", sizeof *qsysinfo, + 0, &errinfo); + return errinfo.Bytes_Available? -1: 0; +} + + +static const char * +getcomponent(char * dst, const char * src) + +{ + int i; + + /** + *** Get a path component of at most 10 characters and + *** map it to upper case. + *** Return the address of the next delimiter in source. + **/ + + for (i = 0;; src++) { + if (!*src || *src == ' ' || *src == '/') { + *dst = '\0'; + return src; + } + + if (i < 10) { + *dst++ = toupper(*src); + i++; + } + } +} + + +static int +dlpath2QSYS(Qp0l_QSYS_Info_t * qsysinfo, const char * path, const char * dftlib) + +{ + unsigned int flags; + char * cp; + + /** + *** Convert the given path to a QSYS object name. + *** Syntax rules for paths are: + *** + *** '/'+ [ [ '/'+ [ '/'+ ] ] '/'* ] + *** '/'+ [ '/'+ ] '/'* + *** '/'* + *** + *** If default library is not given, *LIBL is assumed. + *** Components may no contain spaces. They are translated to + *** uppercase. Only the first 10 characters are significant. + *** There is no check for the validity of the given components and + *** for the object existence. + *** Component types are not in the path, but generated internally. + *** CCSID is not processed. + *** + *** Return 0 upon success, else -1. + **/ + + if (!qsysinfo || !path) { + errno = EFAULT; + return -1; + } + + /** + *** Strip leading spaces. + **/ + + while (*path == ' ') + path++; + + /** + *** Check for null path. + **/ + + if (!*path) { + errno = EINVAL; + return -1; + } + + /** + *** Preset the result structure. + **/ + + memset((char *) qsysinfo, 0, sizeof *qsysinfo); + + /** + *** Determine the format. + **/ + + if (*path == '/') { + /** + *** Library component present. + **/ + + while (*++path == '/') + ; + + if (!*path || *path == ' ') + strcpy(qsysinfo->Lib_Name, "QSYS"); + else + path = getcomponent(qsysinfo->Lib_Name, path); + + /** + *** Check for file component and get it. + **/ + + if (*path == '/') { + while (*++path == '/') + ; + + if (*path && *path != ' ') + path = getcomponent(qsysinfo->Obj_Name, path); + } + } + else { + /** + *** The mandatory component is the . + **/ + + path = getcomponent(qsysinfo->Obj_Name, path); + + while (*path == '/') + path++; + + /** + *** If there is a second component, move the first to + *** the library name and parse the file name. + **/ + + if (*path && *path != ' ') { + strcpy(qsysinfo->Lib_Name, qsysinfo->Obj_Name); + memset(qsysinfo->Obj_Name, 0, + sizeof qsysinfo->Obj_Name); + path = getcomponent(qsysinfo->Obj_Name, path); + } + else + strcpy(qsysinfo->Lib_Name, dftlib? dftlib: "*LIBL"); + } + + /** + *** Check and set-up member. + **/ + + while (*path == '/') + path++; + + if (*path && *path != ' ') { + path = getcomponent(qsysinfo->Mbr_Name, path); + strcpy(qsysinfo->Mbr_Type, "*MBR"); + + while (*path == '/') + path++; + } + + strcpy(qsysinfo->Lib_Type, "*LIB"); + + if (qsysinfo->Obj_Name[0]) + strcpy(qsysinfo->Obj_Type, "*FILE"); + + qsysinfo->Bytes_Returned = sizeof *qsysinfo; + qsysinfo->Bytes_Available = sizeof *qsysinfo; + + /** + *** Strip trailing spaces. + **/ + + while (*path == ' ') + path++; + + if (*path) { + errno = EINVAL; + return -1; + } + + return 0; +} + + +static int +dl_ifs_link(Qp0l_QSYS_Info_t * qsysinfo, const char * pathname) + +{ + /** + *** If `pathname' is a link found in IFS, set `qsysinfo' to its + *** DB2 name. + *** Return 0 if OK, else -1. + **/ + + return dlGetObjectName(qsysinfo, (const char *) NULL, 0, pathname); +} + + +static int +dl_path_link(Qp0l_QSYS_Info_t * qsysinfo, const char * pathvar, + const char * filename, int (* testproc)(const Qp0l_QSYS_Info_t *)) + +{ + const char * p; + const char * q; + unsigned int i; + const char * path; + + /** + *** If `filename' is not a path and is a link found in one of the + *** colon-separated paths in environment variable `pathvar', + *** set `qsysinfo' to its DB2 name. + *** Return 0 if OK, else -1. + **/ + + i = _QP0L_DIR_NAME_LG; + + for (p = filename; *p; p++) + if (*p == '/' || !--i) + return -1; /* Too long or a path. */ + + /** + *** Make sure we have the LD_LIBRARY_PATH environment + *** variable value. + **/ + + path = getenv(pathvar); + + if (!path) + return -1; /* No path list. */ + + /** + *** Try in each path listed. + **/ + + q = path; + + if (!*q) + return -1; /* No path list. */ + + for (;;) { + for (p = q; *p && *p != ':'; p++) + ; + + if (p > q) /* Ignore null path. */ + if (!dlGetObjectName(qsysinfo, q, p - q, filename)) + if (!testproc || (*testproc)(qsysinfo)) + return 0; /* Found: return. */ + + if (!*p) + break; + + q = p + 1; + } + + errno = ENOENT; + return -1; +} + + +static int +dl_DB2_path(Qp0l_QSYS_Info_t * qsysinfo, const char * pathname) + +{ + if (dlpath2QSYS(qsysinfo, pathname, (const char *) NULL)) + return -1; + + if (qsysinfo->Mbr_Type[0]) + return -1; /* Service program may not have members. */ + + if (!qsysinfo->Obj_Type[0]) + return -1; /* Object must be specified. */ + + strcpy(qsysinfo->Obj_Type, "*SRVPGM"); /* Set our object type. */ + return 0; +} + + +static int +dl_DB2_name(char * dst, const char * name) + +{ + int i; + + for (i = 0; i < 10; i++) { + switch (*name) { + + default: + if (!islower(*name)) + break; + + case '\0': + case '/': + case ' ': + return -1; + } + + *dst++ = *name++; + } + + if (!i) + return -1; + + *dst = '\0'; + return 0; +} + + +static int +dl_qualified_object(Qp0l_QSYS_Info_t * qsysinfo, const char * pathname) + +{ + memset((char *) qsysinfo, 0, sizeof *qsysinfo); + + if (dl_DB2_name(qsysinfo->Obj_Name, pathname) || + dl_DB2_name(qsysinfo->Lib_Name, pathname + 10)) + return -1; + + strcpy(qsysinfo->Lib_Type, "*LIB"); + strcpy(qsysinfo->Obj_Type, "*SRVPGM"); + return 0; +} + + +static int +dl_lib_object(Qp0l_QSYS_Info_t * qsysinfo, + const char * libname, const char * pathname) + +{ + int i; + char * cp; + + strcpy(qsysinfo->Lib_Name, libname); + strcpy(qsysinfo->Lib_Type, "*LIB"); + strcpy(qsysinfo->Obj_Type, "*SRVPGM"); + cp = qsysinfo->Obj_Name; + + while (*pathname == ' ') + pathname++; + + for (i = 0;; pathname++) { + switch (*pathname) { + + case '\0': + case ' ': + break; + + case '/': + return -1; + + default: + if (i < 10) + *cp++ = toupper(*pathname); + + i++; + continue; + } + + break; + } + + while (*pathname == ' ') + pathname++; + + if (!i || *pathname) + return -1; + + *cp = '\0'; + return 0; +} + + +static int +dl_is_srvpgm(const Qp0l_QSYS_Info_t * qsysinfo) + +{ + struct stat sbuf; + char namebuf[100]; + + if (!qsysinfo->Lib_Name[0] || strcmp(qsysinfo->Lib_Type, "*LIB") || + !qsysinfo->Obj_Name[0] || strcmp(qsysinfo->Obj_Type, "*SRVPGM") || + qsysinfo->Mbr_Name[0] || qsysinfo->Mbr_Type[0]) + return 0; + + /** + *** Build the IFS path name for the DB2 object. + **/ + + sprintf(namebuf, "%s/%s.LIB/%s.SRVPGM", + strcmp(qsysinfo->Lib_Name, "QSYS")? "/QSYS.LIB": "", + qsysinfo->Lib_Name, qsysinfo->Obj_Name); + + return stat(namebuf, &sbuf) == 0; +} + + +static int +dlreinit(dlinfo * dlip) + +{ + RINZ_TEMPL_T t; + RINZ_TEMPL_T * p; + volatile _INTRPT_Hndlr_Parms_T excbuf; + + if (dlip->actinfo.Flags & QLE_ABP_WAS_ACTIVE) + return 0; + + /** + *** Attempt to reinitialize the service program that was loaded. + *** The service program must be created to allow re-initialization: + *** ALWRINZ(*YES) for this to work. The default is + *** ALWRINZ(*NO). + **/ + +#pragma exception_handler(err, excbuf, 0, _C2_MH_ESCAPE, _CTLA_HANDLE_NO_MSG) + p = &t; + t.rinz_pgm = dlip->pointer; + t.rinz_agpmk = dlip->actinfo.Act_Grp_Mark; + _RINZSTAT(p); +#pragma disable_handler + + return 0; + +err: + if (!memcmp((char *) excbuf.Msg_Id, "MCH4421", 7)) + return 0; /* Program cannot be reinitialized. */ + + dlseterror_from_exception(&excbuf); + return -1; +} + + +void * +dlsym(void * handle, const char * symbol) + +{ + dlinfo * dlip; + void * p; + int export_type; + Qus_EC_t errinfo; + volatile _INTRPT_Hndlr_Parms_T excbuf; + static int zero = 0; + + dlthreadinit(); + + if (!handle || !symbol) { + dlseterror_from_errno(EFAULT); + return (void *) NULL; + } + + dlip = (dlinfo *) handle; + +#pragma exception_handler(error, excbuf, 0, _C2_MH_ESCAPE, _CTLA_HANDLE_NO_MSG) + errinfo.Bytes_Provided = 0; + QleGetExpLong(&dlip->actinfo.Act_Mark, &zero, &zero, + (char *) symbol, &p, &export_type, &errinfo); + return p; +#pragma disable_handler + +error: + dlseterror_from_exception(&excbuf); + return (void *) NULL; +} + + +int +dlclose(void * handle) + +{ + dlinfo * dlip; + void (* _fini)(void); + + dlthreadinit(); + + if (!handle) { + dlseterror_from_errno(EFAULT); + return -1; + } + + dlip = (dlinfo *) handle; + + if (dlip->actcount) { + if (--(dlip->actcount)) + return 0; + + if (_fini = dlsym(handle, "_fini")) + (*_fini)(); + } + + return dlreinit(dlip); +} + + +static void * +dlopenqsys(const Qp0l_QSYS_Info_t * dllinfo) + +{ + dlinfo * dlip; + dlinfo * dlip2; + void (* _init)(void); + unsigned int i; + _SYSPTR pgmptr; + unsigned long long actmark; + Qus_EC_t errinfo; + char actmarkstr[2 * sizeof actmark + 1]; + static int actinfo_size = sizeof dlip->actinfo; + volatile _INTRPT_Hndlr_Parms_T excbuf; + + /** + *** Capture any type of error and if any occurs, + *** return not found. + **/ + +#pragma exception_handler(error1, excbuf, 0, _C2_MH_ESCAPE, _CTLA_HANDLE_NO_MSG) + pgmptr = rslvsp(WLI_SRVPGM, (char *) dllinfo->Obj_Name, + (char *) dllinfo->Lib_Name ,_AUTH_NONE); + + if (!pgmptr) { + errno = ENOENT; + return (void *) NULL; + } + + /** + *** Create a new DLL info block. + **/ + + dlip = (dlinfo *) malloc(sizeof *dlip); + + if (!dlip) + return (void *) NULL; /* Cannot create block. */ +#pragma disable_handler + + dllock(); + +#pragma exception_handler(error2, excbuf, 0, _C2_MH_ESCAPE, _CTLA_HANDLE_NO_MSG) + memset((char *) dlip, 0, sizeof *dlip); + dlip->pointer = pgmptr; + + /** + *** Activate the DLL. + **/ + + errinfo.Bytes_Provided = 0; + QleActBndPgmLong(&pgmptr, &actmark, + &dlip->actinfo, &actinfo_size, &errinfo); + dlip->actinfo.Act_Mark = actmark; + + /** + *** Dummy string encoding activation mark to use as hash table key. + **/ + + for (i = 0; actmark; actmark >>= 6) + actmarkstr[i++] = 0x40 + (actmark & 0x3F); + + actmarkstr[i] = '\0'; + + /** + *** Check if already activated. + **/ + + dlip2 = (dlinfo *) xmlHashLookup(dldir, actmarkstr); + + if (dlip2) { + free((char *) dlip); + dlip = dlip2; + } + else if (xmlHashAddEntry(dldir, (const xmlChar *) actmarkstr, dlip)) { + dlreinit(dlip); + free((char *) dlip); + dlunlock(); + return (void *) NULL; + } +#pragma disable_handler + +#pragma exception_handler(error2, excbuf, 0, _C2_MH_ESCAPE, _CTLA_HANDLE_NO_MSG) + + /** + *** Bump activation counter. + **/ + + if (!(dlip->actcount++) && (_init = dlsym(dlip, "_init"))) + (*_init)(); + + dlunlock(); + + /** + *** Return the handle. + **/ + + return (void *) dlip; +#pragma disable_handler + +error2: + free((char *) dlip); + dlunlock(); + +error1: + dlseterror_from_exception(&excbuf); + return (void *) NULL; +} + + +void * +dlopen(const char * filename, int flag) + +{ + void * dlhandle; + int sverrno; + Qp0l_QSYS_Info_t dllinfo; + + sverrno = errno; + errno = 0; + + dlthreadinit(); + + if (!filename) { + dlseterror_from_errno(EFAULT); + errno = sverrno; + return NULL; + } + + /** + *** Try to locate the object in the following order: + *** _ `filename' is an IFS path. + *** _ `filename' is not a path and resides in one of + *** LD_LIBRARY_PATH colon-separated paths. + *** _ `filename' is not a path and resides in one of + *** PATH colon-separated paths. + *** _ `filename' is a DB2 path (as /library/object). + *** _ `filename' is a qualified object name. + *** _ `filename' is an object in *CURLIB. + *** _ `filename' is an object in *LIBL. + **/ + + if (!dl_ifs_link(&dllinfo, filename) && dl_is_srvpgm(&dllinfo)) + dlhandle = dlopenqsys(&dllinfo); + else if (!dl_path_link(&dllinfo, + "LD_LIBRARY_PATH", filename, dl_is_srvpgm)) + dlhandle = dlopenqsys(&dllinfo); + else if (!dl_path_link(&dllinfo, "PATH", filename, dl_is_srvpgm)) + dlhandle = dlopenqsys(&dllinfo); + else if (!dl_DB2_path(&dllinfo, filename) && dl_is_srvpgm(&dllinfo)) + dlhandle = dlopenqsys(&dllinfo); + else if (!dl_qualified_object(&dllinfo, filename) && + dl_is_srvpgm(&dllinfo)) + dlhandle = dlopenqsys(&dllinfo); + else if (!dl_lib_object(&dllinfo, "*CURLIB", filename) && + dl_is_srvpgm(&dllinfo)) + dlhandle = dlopenqsys(&dllinfo); + else if (!dl_lib_object(&dllinfo, "*LIBL", filename) && + dl_is_srvpgm(&dllinfo)) + dlhandle = dlopenqsys(&dllinfo); + else + dlhandle = NULL; + + if (!dlhandle && errno) + dlseterror_from_errno(errno); + + errno = sverrno; + return dlhandle; +} -- cgit v1.2.3