1/* Licensed to the Apache Software Foundation (ASF) under one or more
2 * contributor license agreements.  See the NOTICE file distributed with
3 * this work for additional information regarding copyright ownership.
4 * The ASF licenses this file to You under the Apache License, Version 2.0
5 * (the "License"); you may not use this file except in compliance with
6 * the License.  You may obtain a copy of the License at
7 *
8 *     http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17#include "apr_arch_dso.h"
18#include "apr_strings.h"
19#include "apr_portable.h"
20
21#include <library.h>
22#include <unistd.h>
23
24APR_DECLARE(apr_status_t) apr_os_dso_handle_put(apr_dso_handle_t **aprdso,
25                                                apr_os_dso_handle_t osdso,
26                                                apr_pool_t *pool)
27{
28    *aprdso = apr_pcalloc(pool, sizeof **aprdso);
29    (*aprdso)->handle = osdso;
30    (*aprdso)->pool = pool;
31    return APR_SUCCESS;
32}
33
34APR_DECLARE(apr_status_t) apr_os_dso_handle_get(apr_os_dso_handle_t *osdso,
35                                                apr_dso_handle_t *aprdso)
36{
37    *osdso = aprdso->handle;
38    return APR_SUCCESS;
39}
40
41static apr_status_t dso_cleanup(void *thedso)
42{
43    apr_dso_handle_t *dso = thedso;
44    sym_list *symbol = NULL;
45    void *NLMHandle = getnlmhandle();
46
47    if (dso->handle == NULL)
48        return APR_SUCCESS;
49
50    if (dso->symbols != NULL) {
51        symbol = dso->symbols;
52        while (symbol) {
53            UnImportPublicObject(NLMHandle, symbol->symbol);
54            symbol = symbol->next;
55        }
56    }
57
58    if (dlclose(dso->handle) != 0)
59        return APR_EINIT;
60
61    dso->handle = NULL;
62    dso->symbols = NULL;
63    dso->path = NULL;
64
65    return APR_SUCCESS;
66}
67
68APR_DECLARE(apr_status_t) apr_dso_load(apr_dso_handle_t **res_handle,
69                                       const char *path, apr_pool_t *pool)
70{
71
72    void *os_handle = NULL;
73    char *fullpath = NULL;
74    apr_status_t rv;
75
76    if ((rv = apr_filepath_merge(&fullpath, NULL, path,
77                                 APR_FILEPATH_NATIVE, pool)) != APR_SUCCESS) {
78        return rv;
79    }
80
81    os_handle = dlopen(fullpath, RTLD_NOW | RTLD_LOCAL);
82
83    *res_handle = apr_pcalloc(pool, sizeof(**res_handle));
84
85    if(os_handle == NULL) {
86        (*res_handle)->errormsg = dlerror();
87        return APR_EDSOOPEN;
88    }
89
90    (*res_handle)->handle = (void*)os_handle;
91    (*res_handle)->pool = pool;
92    (*res_handle)->errormsg = NULL;
93    (*res_handle)->symbols = NULL;
94    (*res_handle)->path = apr_pstrdup(pool, fullpath);
95
96    apr_pool_cleanup_register(pool, *res_handle, dso_cleanup, apr_pool_cleanup_null);
97
98    return APR_SUCCESS;
99}
100
101APR_DECLARE(apr_status_t) apr_dso_unload(apr_dso_handle_t *handle)
102{
103    return apr_pool_cleanup_run(handle->pool, handle, dso_cleanup);
104}
105
106APR_DECLARE(apr_status_t) apr_dso_sym(apr_dso_handle_sym_t *ressym,
107                                      apr_dso_handle_t *handle,
108                                      const char *symname)
109{
110    sym_list *symbol = NULL;
111    void *retval = dlsym(handle->handle, symname);
112
113    if (retval == NULL) {
114        handle->errormsg = dlerror();
115        return APR_ESYMNOTFOUND;
116    }
117
118    symbol = apr_pcalloc(handle->pool, sizeof(sym_list));
119    symbol->next = handle->symbols;
120    handle->symbols = symbol;
121    symbol->symbol = apr_pstrdup(handle->pool, symname);
122
123    *ressym = retval;
124
125    return APR_SUCCESS;
126}
127
128APR_DECLARE(const char *) apr_dso_error(apr_dso_handle_t *dso, char *buffer,
129                                        apr_size_t buflen)
130{
131    if (dso->errormsg) {
132        apr_cpystrn(buffer, dso->errormsg, buflen);
133        return dso->errormsg;
134    }
135    return "No Error";
136}
137
138