summaryrefslogtreecommitdiff
path: root/os400/dlfcn/dlfcn.c
diff options
context:
space:
mode:
Diffstat (limited to 'os400/dlfcn/dlfcn.c')
-rw-r--r--os400/dlfcn/dlfcn.c1213
1 files changed, 0 insertions, 1213 deletions
diff --git a/os400/dlfcn/dlfcn.c b/os400/dlfcn/dlfcn.c
deleted file mode 100644
index 1488e12..0000000
--- a/os400/dlfcn/dlfcn.c
+++ /dev/null
@@ -1,1213 +0,0 @@
-/**
-*** dlopen(), dlclose() dlsym(), dlerror() emulation for OS/400.
-***
-*** See Copyright for the status of this software.
-***
-*** Author: Patrick Monnerat <pm@datasphere.ch>, DATASPHERE S.A.
-**/
-
-#include <stdarg.h>
-#include <stdio.h>
-#include <ctype.h>
-#include <errno.h>
-#include <stdlib.h>
-#include <unistd.h>
-#include <string.h>
-#include <dirent.h>
-#include <pthread.h>
-
-#include <sys/types.h>
-#include <sys/stat.h>
-
-#include <except.h> /* AS400 exceptions. */
-#include <miptrnam.h> /* MI pointers support. */
-#include <qusec.h> /* Error structures. */
-#include <qp0lstdi.h> /* Path to QSYS object name. */
-#include <qp0z1170.h> /* For Qp0zInitEnv(). */
-#include <qleawi.h> /* For QleActBndPgmLong() definitions. */
-#include <qsy.h> /* Qualified name structure. */
-#include <qmhrtvm.h> /* Retrieve message from message file. */
-
-#include <mih/rinzstat.h>
-#include <mih/matactex.h>
-
-#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:
- ***
- *** '/'+ [ <library> [ '/'+ <file> [ '/'+ <member> ] ] '/'* ]
- *** <library> '/'+ <file> [ '/'+ <member> ] '/'*
- *** <file> '/'*
- ***
- *** 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 <file>.
- **/
-
- 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;
-}