~ubuntu-branches/ubuntu/gutsy/net-snmp/gutsy-security

« back to all changes in this revision

Viewing changes to agent/mibgroup/ucd-snmp/dlmod.c

  • Committer: Bazaar Package Importer
  • Author(s): Martin Pitt
  • Date: 2004-09-13 12:06:21 UTC
  • Revision ID: james.westby@ubuntu.com-20040913120621-g952ntonlleihcvm
Tags: upstream-5.1.1
ImportĀ upstreamĀ versionĀ 5.1.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/*
 
2
 *  Dynamic Loadable Agent Modules MIB (UCD-DLMOD-MIB) - dlmod.c
 
3
 *
 
4
 */
 
5
#include <net-snmp/net-snmp-config.h>
 
6
 
 
7
#if HAVE_STDLIB_H
 
8
#include <stdlib.h>
 
9
#endif
 
10
#include <stdio.h>
 
11
#if HAVE_STRING_H
 
12
#include <string.h>
 
13
#else
 
14
#include <strings.h>
 
15
#endif
 
16
#if HAVE_UNISTD_H
 
17
#include <unistd.h>
 
18
#endif
 
19
#include <ctype.h>
 
20
 
 
21
#if HAVE_WINSOCK_H
 
22
#include <winsock.h>
 
23
#endif
 
24
 
 
25
#include <net-snmp/net-snmp-includes.h>
 
26
#include <net-snmp/agent/net-snmp-agent-includes.h>
 
27
 
 
28
#include "struct.h"
 
29
#include "util_funcs.h"
 
30
 
 
31
#if defined(HAVE_DLFCN_H) && ( defined(HAVE_DLOPEN) || defined(HAVE_LIBDL) )
 
32
 
 
33
#include <dlfcn.h>
 
34
#include "dlmod.h"
 
35
 
 
36
static struct dlmod *dlmods = NULL;
 
37
static int      dlmod_next_index = 1;
 
38
static char     dlmod_path[1024];
 
39
 
 
40
static void     dlmod_parse_config(const char *, char *);
 
41
static void     dlmod_free_config(void);
 
42
 
 
43
/*
 
44
 * this variable defines function callbacks and type return
 
45
 * information for the dlmod mib
 
46
 */
 
47
static struct variable4 dlmod_variables[] = {
 
48
    {DLMODNEXTINDEX, ASN_INTEGER, RONLY, var_dlmod, 1, {1}},
 
49
    {DLMODNAME, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 2}},
 
50
    {DLMODPATH, ASN_OCTET_STR, RWRITE, var_dlmodEntry, 3, {2, 1, 3}},
 
51
    {DLMODERROR, ASN_OCTET_STR, RONLY, var_dlmodEntry, 3, {2, 1, 4}},
 
52
    {DLMODSTATUS, ASN_INTEGER, RWRITE, var_dlmodEntry, 3, {2, 1, 5}},
 
53
};
 
54
 
 
55
static oid      dlmod_variables_oid[] = { 1, 3, 6, 1, 4, 1, 2021, 13, 14 };
 
56
static int      dlmod_variables_oid_len = 9;
 
57
 
 
58
void
 
59
init_dlmod(void)
 
60
{
 
61
    char           *p;
 
62
    int             len;
 
63
 
 
64
    REGISTER_MIB("dlmod", dlmod_variables, variable4, dlmod_variables_oid);
 
65
 
 
66
    /*
 
67
     * TODO: REGISTER_SYSOR_ENTRY 
 
68
     */
 
69
 
 
70
    DEBUGMSGTL(("dlmod", "register mib\n"));
 
71
 
 
72
    snmpd_register_config_handler("dlmod", dlmod_parse_config,
 
73
                                  dlmod_free_config,
 
74
                                  "module-name module-path");
 
75
 
 
76
    p = getenv("SNMPDLMODPATH");
 
77
    strncpy(dlmod_path, SNMPDLMODPATH, sizeof(dlmod_path));
 
78
    dlmod_path[ sizeof(dlmod_path)-1 ] = 0;
 
79
    if (p) {
 
80
        if (p[0] == ':') {
 
81
            len = strlen(dlmod_path);
 
82
            if (dlmod_path[len - 1] != ':') {
 
83
                strncat(dlmod_path, ":", sizeof(dlmod_path) - len -1);
 
84
                len++;
 
85
            }
 
86
            strncat(dlmod_path, p + 1,   sizeof(dlmod_path) - len);
 
87
        } else
 
88
            strncpy(dlmod_path, p, sizeof(dlmod_path));
 
89
    }
 
90
    dlmod_path[ sizeof(dlmod_path)-1 ] = 0;
 
91
    DEBUGMSGTL(("dlmod", "dlmod_path: %s\n", dlmod_path));
 
92
}
 
93
 
 
94
void
 
95
deinit_dlmod(void)
 
96
{
 
97
    unregister_mib(dlmod_variables_oid, dlmod_variables_oid_len);
 
98
    snmpd_unregister_config_handler("dlmod");
 
99
}
 
100
 
 
101
struct dlmod   *
 
102
dlmod_create_module(void)
 
103
{
 
104
    struct dlmod  **pdlmod, *dlm;
 
105
 
 
106
    DEBUGMSGTL(("dlmod", "dlmod_create_module\n"));
 
107
    dlm = (struct dlmod *) calloc(1, sizeof(struct dlmod));
 
108
    if (dlm == NULL)
 
109
        return NULL;
 
110
 
 
111
    dlm->index = dlmod_next_index++;
 
112
    dlm->status = DLMOD_UNLOADED;
 
113
 
 
114
    for (pdlmod = &dlmods; *pdlmod != NULL; pdlmod = &((*pdlmod)->next));
 
115
    (*pdlmod) = dlm;
 
116
 
 
117
    return dlm;
 
118
}
 
119
 
 
120
void
 
121
dlmod_delete_module(struct dlmod *dlm)
 
122
{
 
123
    struct dlmod  **pdlmod;
 
124
 
 
125
    DEBUGMSGTL(("dlmod", "dlmod_delete_module\n"));
 
126
    if (!dlm || dlm->status != DLMOD_UNLOADED)
 
127
        return;
 
128
 
 
129
    for (pdlmod = &dlmods; *pdlmod; pdlmod = &((*pdlmod)->next))
 
130
        if (*pdlmod == dlm) {
 
131
            *pdlmod = dlm->next;
 
132
            free(dlm);
 
133
            return;
 
134
        }
 
135
}
 
136
 
 
137
void
 
138
dlmod_load_module(struct dlmod *dlm)
 
139
{
 
140
    char            sym_init[64];
 
141
    char           *p, tmp_path[255];
 
142
    int             (*dl_init) (void);
 
143
 
 
144
    DEBUGMSGTL(("dlmod", "dlmod_load_module %s: %s\n", dlm->name,
 
145
                dlm->path));
 
146
 
 
147
    if (!dlm || !dlm->path || !dlm->name ||
 
148
        (dlm->status != DLMOD_UNLOADED && dlm->status != DLMOD_ERROR))
 
149
        return;
 
150
 
 
151
    if (dlm->path[0] == '/') {
 
152
#ifdef RTLD_NOW
 
153
        dlm->handle = dlopen(dlm->path, RTLD_NOW);
 
154
#else
 
155
        dlm->handle = dlopen(dlm->path, RTLD_LAZY);
 
156
#endif
 
157
        if (dlm->handle == NULL) {
 
158
            snprintf(dlm->error, sizeof(dlm->error),
 
159
                     "dlopen failed: %s", dlerror());
 
160
            dlm->status = DLMOD_ERROR;
 
161
            return;
 
162
        }
 
163
    } else {
 
164
        for (p = strtok(dlmod_path, ":"); p; p = strtok(NULL, ":")) {
 
165
            snprintf(tmp_path, sizeof(tmp_path), "%s/%s.so", p, dlm->path);
 
166
            DEBUGMSGTL(("dlmod", "p: %s tmp_path: %s\n", p, tmp_path));
 
167
#ifdef RTLD_NOW
 
168
            dlm->handle = dlopen(tmp_path, RTLD_NOW);
 
169
#else
 
170
            dlm->handle = dlopen(tmp_path, RTLD_LAZY);
 
171
#endif
 
172
            if (dlm->handle == NULL) {
 
173
                snprintf(dlm->error, sizeof(dlm->error),
 
174
                         "dlopen failed: %s", dlerror());
 
175
                dlm->status = DLMOD_ERROR;
 
176
            }
 
177
        }
 
178
        strncpy(dlm->path, tmp_path, sizeof(dlm->path));
 
179
        if (dlm->status == DLMOD_ERROR)
 
180
            return;
 
181
    }
 
182
    snprintf(sym_init, sizeof(sym_init), "init_%s", dlm->name);
 
183
    dl_init = dlsym(dlm->handle, sym_init);
 
184
    if (dl_init == NULL) {
 
185
        dlclose(dlm->handle);
 
186
        snprintf(dlm->error, sizeof(dlm->error),
 
187
                 "dlsym failed: can't find \'%s\'", sym_init);
 
188
        dlm->status = DLMOD_ERROR;
 
189
        return;
 
190
    }
 
191
 
 
192
    dl_init();
 
193
    dlm->error[0] = '\0';
 
194
    dlm->status = DLMOD_LOADED;
 
195
}
 
196
 
 
197
void
 
198
dlmod_unload_module(struct dlmod *dlm)
 
199
{
 
200
    char            sym_deinit[64];
 
201
    int             (*dl_deinit) (void);
 
202
 
 
203
    if (!dlm || dlm->status != DLMOD_LOADED)
 
204
        return;
 
205
 
 
206
    snprintf(sym_deinit, sizeof(sym_deinit), "deinit_%s", dlm->name);
 
207
    dl_deinit = dlsym(dlm->handle, sym_deinit);
 
208
    if (dl_deinit == NULL) {
 
209
        snprintf(dlm->error, sizeof(dlm->error),
 
210
                 "dlsym failed: can't find \'%s\'", sym_deinit);
 
211
    } else {
 
212
        dl_deinit();
 
213
    }
 
214
    dlclose(dlm->handle);
 
215
    dlm->status = DLMOD_UNLOADED;
 
216
    DEBUGMSGTL(("dlmod", "Module %s unloaded\n", dlm->name));
 
217
}
 
218
 
 
219
struct dlmod   *
 
220
dlmod_get_by_index(int iindex)
 
221
{
 
222
    struct dlmod   *dlmod;
 
223
 
 
224
    for (dlmod = dlmods; dlmod; dlmod = dlmod->next)
 
225
        if (dlmod->index == iindex)
 
226
            return dlmod;
 
227
 
 
228
    return NULL;
 
229
}
 
230
 
 
231
static void
 
232
dlmod_parse_config(const char *token, char *cptr)
 
233
{
 
234
    char           *dlm_name, *dlm_path;
 
235
    struct dlmod   *dlm;
 
236
 
 
237
    if (cptr == NULL) {
 
238
        config_perror("Bad dlmod line");
 
239
        return;
 
240
    }
 
241
    /*
 
242
     * remove comments 
 
243
     */
 
244
    *(cptr + strcspn(cptr, "#;\r\n")) = '\0';
 
245
 
 
246
    dlm = dlmod_create_module();
 
247
    if (!dlm)
 
248
        return;
 
249
 
 
250
    /*
 
251
     * dynamic module name 
 
252
     */
 
253
    dlm_name = strtok(cptr, "\t ");
 
254
    if (dlm_name == NULL) {
 
255
        config_perror("Bad dlmod line");
 
256
        dlmod_delete_module(dlm);
 
257
        return;
 
258
    }
 
259
    strncpy(dlm->name, dlm_name, sizeof(dlm->name));
 
260
 
 
261
    /*
 
262
     * dynamic module path 
 
263
     */
 
264
    dlm_path = strtok(NULL, "\t ");
 
265
    if (dlm_path)
 
266
        strncpy(dlm->path, dlm_path, sizeof(dlm->path));
 
267
    else
 
268
        strncpy(dlm->path, dlm_name, sizeof(dlm->path));
 
269
 
 
270
    dlmod_load_module(dlm);
 
271
 
 
272
    if (dlm->status == DLMOD_ERROR)
 
273
        snmp_log(LOG_ERR, "%s\n", dlm->error);
 
274
}
 
275
 
 
276
static void
 
277
dlmod_free_config(void)
 
278
{
 
279
    struct dlmod   *dtmp, *dtmp2;
 
280
 
 
281
    for (dtmp = dlmods; dtmp != NULL;) {
 
282
        dtmp2 = dtmp;
 
283
        dtmp = dtmp->next;
 
284
        dlmod_unload_module(dtmp2);
 
285
        free(dtmp2);
 
286
    }
 
287
    dlmods = NULL;
 
288
}
 
289
 
 
290
 
 
291
/*
 
292
 * header_dlmod(...
 
293
 * Arguments:
 
294
 * vp     IN      - pointer to variable entry that points here
 
295
 * name    IN/OUT  - IN/name requested, OUT/name found
 
296
 * length  IN/OUT  - length of IN/OUT oid's 
 
297
 * exact   IN      - TRUE if an exact match was requested
 
298
 * var_len OUT     - length of variable or 0 if function returned
 
299
 * write_method
 
300
 */
 
301
 
 
302
static int
 
303
header_dlmod(struct variable *vp,
 
304
             oid * name,
 
305
             size_t * length,
 
306
             int exact, size_t * var_len, WriteMethod ** write_method)
 
307
{
 
308
#define DLMOD_NAME_LENGTH 10
 
309
    oid             newname[MAX_OID_LEN];
 
310
    int             result;
 
311
 
 
312
    memcpy((char *) newname, (char *) vp->name,
 
313
           (int) vp->namelen * sizeof(oid));
 
314
    newname[DLMOD_NAME_LENGTH] = 0;
 
315
 
 
316
    result =
 
317
        snmp_oid_compare(name, *length, newname, (int) vp->namelen + 1);
 
318
    if ((exact && (result != 0)) || (!exact && (result >= 0))) {
 
319
        return MATCH_FAILED;
 
320
    }
 
321
 
 
322
    memcpy((char *) name, (char *) newname,
 
323
           ((int) vp->namelen + 1) * sizeof(oid));
 
324
    *length = vp->namelen + 1;
 
325
    *write_method = 0;
 
326
    *var_len = sizeof(long);    /* default to 'long' results */
 
327
    return MATCH_SUCCEEDED;
 
328
}
 
329
 
 
330
 
 
331
u_char         *
 
332
var_dlmod(struct variable * vp,
 
333
          oid * name,
 
334
          size_t * length,
 
335
          int exact, size_t * var_len, WriteMethod ** write_method)
 
336
{
 
337
 
 
338
    /*
 
339
     * variables we may use later 
 
340
     */
 
341
 
 
342
    *write_method = 0;          /* assume it isnt writable for the time being */
 
343
    *var_len = sizeof(int);     /* assume an integer and change later
 
344
                                 * if not */
 
345
 
 
346
    if (header_dlmod(vp, name, length, exact,
 
347
                     var_len, write_method) == MATCH_FAILED)
 
348
        return 0;
 
349
 
 
350
    /*
 
351
     * this is where we do the value assignments for the mib results. 
 
352
     */
 
353
    switch (vp->magic) {
 
354
    case DLMODNEXTINDEX:
 
355
        long_return = dlmod_next_index;
 
356
        return (unsigned char *) &long_return;
 
357
    default:
 
358
        DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmod\n",
 
359
                    vp->magic));
 
360
    }
 
361
    return 0;
 
362
}
 
363
 
 
364
 
 
365
/*
 
366
 * header_dlmodEntry(...
 
367
 * Arguments:
 
368
 * vp     IN      - pointer to variable entry that points here
 
369
 * name    IN/OUT  - IN/name requested, OUT/name found
 
370
 * length  IN/OUT  - length of IN/OUT oid's 
 
371
 * exact   IN      - TRUE if an exact match was requested
 
372
 * var_len OUT     - length of variable or 0 if function returned
 
373
 * write_method
 
374
 * 
 
375
 */
 
376
 
 
377
 
 
378
static struct dlmod *
 
379
header_dlmodEntry(struct variable *vp,
 
380
                  oid * name,
 
381
                  size_t * length,
 
382
                  int exact, size_t * var_len, WriteMethod ** write_method)
 
383
{
 
384
#define DLMODENTRY_NAME_LENGTH 12
 
385
    oid             newname[MAX_OID_LEN];
 
386
    int             result;
 
387
    struct dlmod   *dlm = 0;
 
388
    int             dlmod_index;
 
389
 
 
390
    memcpy((char *) newname, (char *) vp->name,
 
391
           (int) vp->namelen * sizeof(oid));
 
392
    *write_method = 0;
 
393
 
 
394
    for (dlmod_index = 1; dlmod_index < dlmod_next_index; dlmod_index++) {
 
395
        dlm = dlmod_get_by_index(dlmod_index);
 
396
 
 
397
        DEBUGMSGTL(("dlmod", "dlmodEntry dlm: %p dlmod_index: %d\n",
 
398
                    dlm, dlmod_index));
 
399
 
 
400
        if (dlm) {
 
401
            newname[12] = dlmod_index;
 
402
            result = snmp_oid_compare(name, *length, newname,
 
403
                                      (int) vp->namelen + 1);
 
404
 
 
405
            if ((exact && (result == 0)) || (!exact && (result < 0)))
 
406
                break;
 
407
        }
 
408
    }
 
409
 
 
410
    if (dlmod_index >= dlmod_next_index) {
 
411
        if (dlmod_index == dlmod_next_index &&
 
412
            exact && vp->magic == DLMODSTATUS)
 
413
 
 
414
            *write_method = write_dlmodStatus;
 
415
        return NULL;
 
416
    }
 
417
 
 
418
    memcpy((char *) name, (char *) newname,
 
419
           ((int) vp->namelen + 1) * sizeof(oid));
 
420
    *length = vp->namelen + 1;
 
421
    *var_len = sizeof(long);
 
422
    return dlm;
 
423
}
 
424
 
 
425
u_char         *
 
426
var_dlmodEntry(struct variable * vp,
 
427
               oid * name,
 
428
               size_t * length,
 
429
               int exact, size_t * var_len, WriteMethod ** write_method)
 
430
{
 
431
    /*
 
432
     * variables we may use later 
 
433
     */
 
434
    struct dlmod   *dlm;
 
435
 
 
436
    *var_len = sizeof(int);     /* assume an integer and change later
 
437
                                 * if not */
 
438
 
 
439
    dlm =
 
440
        header_dlmodEntry(vp, name, length, exact, var_len, write_method);
 
441
    if (dlm == NULL)
 
442
        return 0;
 
443
 
 
444
    /*
 
445
     * this is where we do the value assignments for the mib results. 
 
446
     */
 
447
    switch (vp->magic) {
 
448
    case DLMODNAME:
 
449
        *write_method = write_dlmodName;
 
450
        *var_len = strlen(dlm->name);
 
451
        return (unsigned char *) dlm->name;
 
452
    case DLMODPATH:
 
453
        *write_method = write_dlmodPath;
 
454
        *var_len = strlen(dlm->path);
 
455
        return (unsigned char *) dlm->path;
 
456
    case DLMODERROR:
 
457
        *var_len = strlen(dlm->error);
 
458
        return (unsigned char *) dlm->error;
 
459
    case DLMODSTATUS:
 
460
        *write_method = write_dlmodStatus;
 
461
        long_return = dlm->status;
 
462
        return (unsigned char *) &long_return;
 
463
    default:
 
464
        DEBUGMSGTL(("dlmod", "unknown sub-id %d in var_dlmodEntry\n",
 
465
                    vp->magic));
 
466
    }
 
467
    return 0;
 
468
}
 
469
 
 
470
int
 
471
write_dlmodName(int action,
 
472
                u_char * var_val,
 
473
                u_char var_val_type,
 
474
                size_t var_val_len,
 
475
                u_char * statP, oid * name, size_t name_len)
 
476
{
 
477
    static struct dlmod *dlm;
 
478
 
 
479
    if (var_val_type != ASN_OCTET_STR) {
 
480
        snmp_log(LOG_ERR, "write to dlmodName not ASN_OCTET_STR\n");
 
481
        return SNMP_ERR_WRONGTYPE;
 
482
    }
 
483
    if (var_val_len > sizeof(dlm->name)) {
 
484
        snmp_log(LOG_ERR, "write to dlmodName: bad length\n");
 
485
        return SNMP_ERR_WRONGLENGTH;
 
486
    }
 
487
    if (action == COMMIT) {
 
488
        dlm = dlmod_get_by_index(name[12]);
 
489
        if (!dlm || dlm->status == DLMOD_LOADED)
 
490
            return SNMP_ERR_RESOURCEUNAVAILABLE;
 
491
        strncpy(dlm->name, (const char *) var_val, var_val_len);
 
492
        dlm->name[var_val_len] = 0;
 
493
    }
 
494
    return SNMP_ERR_NOERROR;
 
495
}
 
496
 
 
497
int
 
498
write_dlmodPath(int action,
 
499
                u_char * var_val,
 
500
                u_char var_val_type,
 
501
                size_t var_val_len,
 
502
                u_char * statP, oid * name, size_t name_len)
 
503
{
 
504
    static struct dlmod *dlm;
 
505
 
 
506
    if (var_val_type != ASN_OCTET_STR) {
 
507
        snmp_log(LOG_ERR, "write to dlmodPath not ASN_OCTET_STR\n");
 
508
        return SNMP_ERR_WRONGTYPE;
 
509
    }
 
510
    if (var_val_len > sizeof(dlm->path)) {
 
511
        snmp_log(LOG_ERR, "write to dlmodPath: bad length\n");
 
512
        return SNMP_ERR_WRONGLENGTH;
 
513
    }
 
514
    if (action == COMMIT) {
 
515
        dlm = dlmod_get_by_index(name[12]);
 
516
        if (!dlm || dlm->status == DLMOD_LOADED)
 
517
            return SNMP_ERR_RESOURCEUNAVAILABLE;
 
518
        strncpy(dlm->path, (const char *) var_val, var_val_len);
 
519
        dlm->path[var_val_len] = 0;
 
520
    }
 
521
    return SNMP_ERR_NOERROR;
 
522
}
 
523
 
 
524
int
 
525
write_dlmodStatus(int action,
 
526
                  u_char * var_val,
 
527
                  u_char var_val_type,
 
528
                  size_t var_val_len,
 
529
                  u_char * statP, oid * name, size_t name_len)
 
530
{
 
531
    /*
 
532
     * variables we may use later 
 
533
     */
 
534
    struct dlmod   *dlm;
 
535
 
 
536
    if (var_val_type != ASN_INTEGER) {
 
537
        snmp_log(LOG_ERR, "write to dlmodStatus not ASN_INTEGER\n");
 
538
        return SNMP_ERR_WRONGTYPE;
 
539
    }
 
540
    if (var_val_len > sizeof(long)) {
 
541
        snmp_log(LOG_ERR, "write to dlmodStatus: bad length\n");
 
542
        return SNMP_ERR_WRONGLENGTH;
 
543
    }
 
544
    if (action == COMMIT) {
 
545
        /*
 
546
         * object identifier in form .1.3.6.1.4.1.2021.13.14.2.1.4.x 
 
547
         * where X is index with offset 12 
 
548
         */
 
549
 
 
550
        dlm = dlmod_get_by_index(name[12]);
 
551
        switch (*((long *) var_val)) {
 
552
        case DLMOD_CREATE:
 
553
            if (dlm || (name[12] != dlmod_next_index))
 
554
                return SNMP_ERR_RESOURCEUNAVAILABLE;
 
555
            dlm = dlmod_create_module();
 
556
            if (!dlm)
 
557
                return SNMP_ERR_RESOURCEUNAVAILABLE;
 
558
            break;
 
559
        case DLMOD_LOAD:
 
560
            if (!dlm || dlm->status == DLMOD_LOADED)
 
561
                return SNMP_ERR_RESOURCEUNAVAILABLE;
 
562
            dlmod_load_module(dlm);
 
563
            break;
 
564
        case DLMOD_UNLOAD:
 
565
            if (!dlm || dlm->status != DLMOD_LOADED)
 
566
                return SNMP_ERR_RESOURCEUNAVAILABLE;
 
567
            dlmod_unload_module(dlm);
 
568
            break;
 
569
        case DLMOD_DELETE:
 
570
            if (!dlm || dlm->status == DLMOD_LOADED)
 
571
                return SNMP_ERR_RESOURCEUNAVAILABLE;
 
572
            dlmod_delete_module(dlm);
 
573
            break;
 
574
        default:
 
575
            return SNMP_ERR_WRONGVALUE;
 
576
        }
 
577
    }
 
578
    return SNMP_ERR_NOERROR;
 
579
}
 
580
 
 
581
#else                           /* no dlopen support */
 
582
 
 
583
void
 
584
init_dlmod(void)
 
585
{
 
586
    DEBUGMSGTL(("dlmod",
 
587
                "Dynamic modules not support on this platform\n"));
 
588
}
 
589
 
 
590
#endif