Blame os400/dlfcn/dlfcn.c

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