home *** CD-ROM | disk | FTP | other *** search
/ NetNews Usenet Archive 1992 #31 / NN_1992_31.iso / spool / comp / unix / aix / 12867 < prev    next >
Encoding:
Internet Message Format  |  1992-12-27  |  16.6 KB

  1. Path: sparky!uunet!spool.mu.edu!yale.edu!ira.uka.de!Sirius.dfn.de!rrz.uni-koeln.de!Germany.EU.net!horga!agsc!veeble.han.sub.org!jum
  2. From: jum@veeble.han.sub.org (Jens-Uwe Mager)
  3. Subject: libdl.a - SunOS/S5R4 dlopen emulator
  4. Newsgroups: comp.unix.aix
  5. Date: Sun, 27 Dec 92 20:23:50 GMT
  6. Organization: veeble Hannover, W-Germany
  7. Keywords: dlopen dynamic loading
  8. Message-ID: <1992Dec27.202350.21450@veeble.han.sub.org>
  9. Lines: 660
  10.  
  11. This is a repost of the dlopen emulutor posted a while back. I have improved
  12. the emulator to support the LIBPATH environment variable and to support
  13. initialization and termination handlers.
  14.  
  15. #!/bin/sh
  16. # This is a shell archive (shar 3.24)
  17. # made 12/27/1992 20:05 UTC by jum@ibm
  18. # Source directory /home/jum/dyn/dl
  19. #
  20. # existing files WILL be overwritten
  21. #
  22. # This shar contains:
  23. # length  mode       name
  24. # ------ ---------- ------------------------------------------
  25. #   3007 -rw-rw-r-- README
  26. #    745 -rw-rw-r-- Makefile
  27. #    696 -r--r--r-- dlfcn.h
  28. #   9132 -r--r--r-- dlfcn.c
  29. #     54 -rw-rw-r-- dl.exp
  30. #
  31. if touch 2>&1 | fgrep '[-amc]' > /dev/null
  32.  then TOUCH=touch
  33.  else TOUCH=true
  34. fi
  35. # ============= README ==============
  36. echo "x - extracting README (Text)"
  37. sed 's/^X//' << 'SHAR_EOF' > README &&
  38. XCopyright (c) 1992, Jens-Uwe Mager, Helios Software GmbH
  39. XNot derived from licensed software.
  40. X
  41. XPermission is granted to freely use, copy, modify, and redistribute
  42. Xthis software, provided that no attempt is made to gain profit from it,
  43. Xthe author is not construed to be liable for any results of using the
  44. Xsoftware, alterations are clearly marked as such, and this notice is
  45. Xnot modified.
  46. X
  47. Xlibdl.a
  48. X-------
  49. X
  50. XThis is an emulation library to emulate the SunOS/System V.4 functions
  51. Xto access the runtime linker. The functions are emulated by using the
  52. XAIX load() function and by reading the .loader section of the loaded
  53. Xmodule to find the exports. The to be loaded module should be linked as
  54. Xfollows:
  55. X
  56. X    cc -o module.so -bM:SRE -bE:module.exp -e _nostart $(OBJS)
  57. X
  58. XThe module export file contains the symbols to be exported. Because
  59. Xthis library uses the loader section, the final module.so file can be
  60. Xstripped.
  61. X
  62. XUsage
  63. X-----
  64. X
  65. Xvoid *dlopen(const char *path, int mode);
  66. X
  67. XThis routine loads the module pointed to by path and reads its export
  68. Xtable. If the path does not contain a '/' character, dlopen will search
  69. Xfor the module using the LIBPATH environment variable. It returns an
  70. Xopaque handle to the module or NULL on error. The flags parameter is
  71. Xcurrently ignored.
  72. X
  73. X
  74. Xvoid *dlsym(void *handle, const char *symbol);
  75. X
  76. XThis routine searches for the symbol in the module referred to by
  77. Xhandle and returns its address. If the symbol could not be found, the
  78. Xfunction returns NULL. The return value must be casted to a proper
  79. Xfunction pointer before it can be used. SunOS/System V.4 allow handle
  80. Xto be a NULL pointer to refer to the module the call is made from, this
  81. Xis not implemented.
  82. X
  83. Xint dlclose(void *handle);
  84. X
  85. XThis routine unloads the module referred to by the handle and disposes
  86. Xof any local storage. this function returns -1 on failure.
  87. X
  88. Xchar *dlerror(void);
  89. X
  90. XThis routine can be used to retrieve a text message describing the most
  91. Xrecent error that occured on on of the above routines. This function
  92. Xreturns NULL if there is not error information.
  93. X
  94. XInitialization and termination handlers
  95. X---------------------------------------
  96. X
  97. XThe emulation provides for an initialization and a termination
  98. Xhandler.  The dlfcn.h file contains a structure declaration named
  99. Xdl_info with following members:
  100. X
  101. X    void (*init)(void);
  102. X    void (*fini)(void);
  103. X
  104. XThe init function is called upon first referencing the library. The
  105. Xfini function is called at dlclose() time or when the process exits.
  106. XThe module should declare a variable named dl_info that contains this
  107. Xstructure which must be exported.  These functions correspond to the
  108. Xdocumented _init() and _fini() functions of SunOS 4.x, but these are
  109. Xappearently not implemented in SunOS.  When using SunOS 5.0, these
  110. Xcorrespond to #pragma init and #pragma fini respectively.
  111. X
  112. XJens-Uwe Mager
  113. X
  114. XHELIOS Software GmbH
  115. XLavesstr. 80
  116. X3000 Hannover 1
  117. XGermany
  118. X
  119. XPhone:        +49 511 3681093
  120. XFAX:        +49 511 3681095
  121. XAppleLink:    ger.xse0082    Attn: Jens-Uwe Mager
  122. Xuucp:        jum@helios.de    or heliosd!jum
  123. SHAR_EOF
  124. $TOUCH -am 1227210392 README &&
  125. chmod 0664 README ||
  126. echo "restore of README failed"
  127. set `wc -c README`;Wc_c=$1
  128. if test "$Wc_c" != "3007"; then
  129.     echo original size 3007, current size $Wc_c
  130. fi
  131. # ============= Makefile ==============
  132. echo "x - extracting Makefile (Text)"
  133. sed 's/^X//' << 'SHAR_EOF' > Makefile &&
  134. X# %W% revision of %E%  %U%
  135. X# This is an unpublished work copyright (c) 1992 Helios Software GmbH
  136. X# 3000 Hannover 1, West Germany
  137. X
  138. XSHELL=/bin/sh
  139. XIPATH=
  140. XDEFS=
  141. XDEBUGFLAGS=-g -DDEBUG
  142. XNODEBUGFLAGS=-O
  143. XCFLAGS=$(IPATH) $(DEFS) $(NODEBUGFLAGS)
  144. XTARGETS=libdl.a
  145. XDEST=/usr/local/lib
  146. XHDRS=dlfcn.h
  147. XSRCS=dlfcn.c
  148. XOBJS=$(SRCS:%.c=%.o)
  149. X
  150. Xall:        $(TARGETS) dlfcn.c
  151. X
  152. X$(TARGETS):    shr.o
  153. X        ar rv $@ $?
  154. X
  155. Xdlfcn.o:    dlfcn.h
  156. X
  157. Xshr.o:        $(OBJS) dl.exp
  158. X        $(CC) -o $@ $(OBJS) -bE:dl.exp -bM:SRE -e _nostart -lld
  159. X
  160. Xlint:
  161. X        lint $(IPATH) $(DEFS) $(SRCS) >lintout
  162. X
  163. Xinfo:
  164. X        sccs info
  165. X
  166. Xclean:
  167. X        rm -f lintout a.out core *.o *-lg *% *~ tags deps%
  168. X
  169. Xclobber:    clean
  170. X        rm -f $(TARGETS) deps
  171. X
  172. Xinstall:    all
  173. X        cp $(TARGETS) $(DEST)
  174. X
  175. Xshar:
  176. X        shar README Makefile dlfcn.h dlfcn.c dl.exp >dl.shar
  177. SHAR_EOF
  178. $TOUCH -am 1227210492 Makefile &&
  179. chmod 0664 Makefile ||
  180. echo "restore of Makefile failed"
  181. set `wc -c Makefile`;Wc_c=$1
  182. if test "$Wc_c" != "745"; then
  183.     echo original size 745, current size $Wc_c
  184. fi
  185. # ============= dlfcn.h ==============
  186. echo "x - extracting dlfcn.h (Text)"
  187. sed 's/^X//' << 'SHAR_EOF' > dlfcn.h &&
  188. X/*
  189. X * @(#)dlfcn.h    1.3 revision of 92/12/27  20:58:32
  190. X * This is an unpublished work copyright (c) 1992 Helios Software GmbH
  191. X * 3000 Hannover 1, Germany
  192. X */
  193. X
  194. X/*
  195. X * Mode flags for the dlopen routine.
  196. X */
  197. X#define RTLD_LAZY    1
  198. X#define RTLD_NOW    2
  199. X
  200. X/*
  201. X * To be able to intialize, a library may provide a dl_info structure
  202. X * that contains functions to be called to initialize and terminate.
  203. X */
  204. Xstruct dl_info {
  205. X    void (*init)(void);
  206. X    void (*fini)(void);
  207. X};
  208. X
  209. X#if __STDC__ || defined(_IBMR2)
  210. Xvoid *dlopen(const char *path, int mode);
  211. Xvoid *dlsym(void *handle, const char *symbol);
  212. Xchar *dlerror(void);
  213. Xint dlclose(void *handle);
  214. X#else
  215. Xvoid *dlopen();
  216. Xvoid *dlsym();
  217. Xchar *dlerror();
  218. Xint dlclose();
  219. X#endif
  220. SHAR_EOF
  221. $TOUCH -am 1227210092 dlfcn.h &&
  222. chmod 0444 dlfcn.h ||
  223. echo "restore of dlfcn.h failed"
  224. set `wc -c dlfcn.h`;Wc_c=$1
  225. if test "$Wc_c" != "696"; then
  226.     echo original size 696, current size $Wc_c
  227. fi
  228. # ============= dlfcn.c ==============
  229. echo "x - extracting dlfcn.c (Text)"
  230. sed 's/^X//' << 'SHAR_EOF' > dlfcn.c &&
  231. X/*
  232. X * @(#)dlfcn.c    1.3 revision of 92/12/27  20:59:55
  233. X * This is an unpublished work copyright (c) 1992 Helios Software GmbH
  234. X * 3000 Hannover 1, Germany
  235. X */
  236. X
  237. X#include <stdio.h>
  238. X#include <errno.h>
  239. X#include <string.h>
  240. X#include <stdlib.h>
  241. X#include <sys/types.h>
  242. X#include <sys/ldr.h>
  243. X#include <a.out.h>
  244. X#include <ldfcn.h>
  245. X#include "dlfcn.h"
  246. X
  247. X/*
  248. X * We simulate dlopen() et al. through a call to load. Because AIX has
  249. X * no call to find an exported symbol we read the loader section of the
  250. X * loaded module and build a list of exported symbols and their virtual
  251. X * address.
  252. X */
  253. X
  254. Xtypedef struct {
  255. X    char        *name;        /* the symbols's name */
  256. X    void        *addr;        /* its relocated virtual address */
  257. X} Export, *ExportPtr;
  258. X
  259. X/*
  260. X * The void * handle returned from dlopen is actually a ModulePtr.
  261. X */
  262. Xtypedef struct Module {
  263. X    struct Module    *next;
  264. X    char        *name;        /* module name for refcounting */
  265. X    int        refCnt;        /* the number of references */
  266. X    void        *entry;        /* entry point from load */
  267. X    struct dl_info    *info;        /* optional init/terminate functions */
  268. X    int        nExports;    /* the number of exports found */
  269. X    ExportPtr    exports;    /* the array of exports */
  270. X} Module, *ModulePtr;
  271. X
  272. X/*
  273. X * We keep a list of all loaded modules to be able to call the fini
  274. X * handlers at atexit() time.
  275. X */
  276. Xstatic ModulePtr modList;
  277. X
  278. X/*
  279. X * The last error from one of the dl* routines is kept in static
  280. X * variables here. Each error is returned only once to the caller.
  281. X */
  282. Xstatic char errbuf[BUFSIZ];
  283. Xstatic int errvalid;
  284. X
  285. Xextern char *strdup(const char *);
  286. Xstatic void caterr(char *);
  287. Xstatic int readExports(ModulePtr);
  288. Xstatic void terminate(void);
  289. X
  290. X/* ARGSUSED */
  291. Xvoid *dlopen(const char *path, int mode)
  292. X{
  293. X    register ModulePtr mp;
  294. X    static int beenHere;
  295. X
  296. X    /*
  297. X     * Upon the first call register a terminate handler that will
  298. X     * close all libraries.
  299. X     */
  300. X    if (!beenHere) {
  301. X        atexit(terminate);
  302. X        beenHere = 1;
  303. X    }
  304. X    /*
  305. X     * Scan the list of modules if have the module already loaded.
  306. X     */
  307. X    for (mp = modList; mp; mp = mp->next)
  308. X        if (strcmp(mp->name, path) == 0) {
  309. X            mp->refCnt++;
  310. X            return mp;
  311. X        }
  312. X    if ((mp = (ModulePtr)calloc(1, sizeof(*mp))) == NULL) {
  313. X        errvalid++;
  314. X        strcpy(errbuf, "calloc: ");
  315. X        strcat(errbuf, strerror(errno));
  316. X        return NULL;
  317. X    }
  318. X    if ((mp->name = strdup(path)) == NULL) {
  319. X        errvalid++;
  320. X        strcpy(errbuf, "strdup: ");
  321. X        strcat(errbuf, strerror(errno));
  322. X        free(mp);
  323. X        return NULL;
  324. X    }
  325. X    /*
  326. X     * load should be declared load(const char *...). Thus we
  327. X     * cast the path to a normal char *. Ugly.
  328. X     */
  329. X    if ((mp->entry = (void *)load((char *)path, 0, NULL)) == NULL) {
  330. X        free(mp->name);
  331. X        free(mp);
  332. X        errvalid++;
  333. X        strcpy(errbuf, "dlopen: ");
  334. X        /*
  335. X         * If AIX says the file is not executable, the error
  336. X         * can be further described by querying the loader about
  337. X         * the last error.
  338. X         */
  339. X        if (errno == ENOEXEC) {
  340. X            char *tmp[BUFSIZ/sizeof(char *)];
  341. X            if (loadquery(L_GETMESSAGES, tmp, sizeof(tmp)) == -1)
  342. X                strcpy(errbuf, strerror(errno));
  343. X            else {
  344. X                char **p;
  345. X                for (p = tmp; *p; p++)
  346. X                    caterr(*p);
  347. X            }
  348. X        } else
  349. X            strcat(errbuf, strerror(errno));
  350. X        return NULL;
  351. X    }
  352. X    mp->refCnt = 1;
  353. X    mp->next = modList;
  354. X    modList = mp;
  355. X    if (readExports(mp) == -1) {
  356. X        dlclose(mp);
  357. X        return NULL;
  358. X    }
  359. X    /*
  360. X     * If there is a dl_info structure, call the init function.
  361. X     */
  362. X    if (mp->info = (struct dl_info *)dlsym(mp, "dl_info")) {
  363. X        if (mp->info->init)
  364. X            (*mp->info->init)();
  365. X    } else
  366. X        errvalid = 0;
  367. X    return mp;
  368. X}
  369. X
  370. X/*
  371. X * Attempt to decipher an AIX loader error message and append it
  372. X * to our static error message buffer.
  373. X */
  374. Xstatic void caterr(char *s)
  375. X{
  376. X    register char *p = s;
  377. X
  378. X    while (*p >= '0' && *p <= '9')
  379. X        p++;
  380. X    switch(atoi(s)) {
  381. X    case L_ERROR_TOOMANY:
  382. X        strcat(errbuf, "to many errors");
  383. X        break;
  384. X    case L_ERROR_NOLIB:
  385. X        strcat(errbuf, "can't load library");
  386. X        strcat(errbuf, p);
  387. X        break;
  388. X    case L_ERROR_UNDEF:
  389. X        strcat(errbuf, "can't find symbol");
  390. X        strcat(errbuf, p);
  391. X        break;
  392. X    case L_ERROR_RLDBAD:
  393. X        strcat(errbuf, "bad RLD");
  394. X        strcat(errbuf, p);
  395. X        break;
  396. X    case L_ERROR_FORMAT:
  397. X        strcat(errbuf, "bad exec format in");
  398. X        strcat(errbuf, p);
  399. X        break;
  400. X    case L_ERROR_ERRNO:
  401. X        strcat(errbuf, strerror(atoi(++p)));
  402. X        break;
  403. X    default:
  404. X        strcat(errbuf, s);
  405. X        break;
  406. X    }
  407. X}
  408. X
  409. Xvoid *dlsym(void *handle, const char *symbol)
  410. X{
  411. X    register ModulePtr mp = (ModulePtr)handle;
  412. X    register ExportPtr ep;
  413. X    register int i;
  414. X
  415. X    /*
  416. X     * Could speed up search, but I assume that one assigns
  417. X     * the result to function pointers anyways.
  418. X     */
  419. X    for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
  420. X        if (strcmp(ep->name, symbol) == 0)
  421. X            return ep->addr;
  422. X    errvalid++;
  423. X    strcpy(errbuf, "dlsym: undefined symbol ");
  424. X    strcat(errbuf, symbol);
  425. X    return NULL;
  426. X}
  427. X
  428. Xchar *dlerror(void)
  429. X{
  430. X    if (errvalid) {
  431. X        errvalid = 0;
  432. X        return errbuf;
  433. X    }
  434. X    return NULL;
  435. X}
  436. X
  437. Xint dlclose(void *handle)
  438. X{
  439. X    register ModulePtr mp = (ModulePtr)handle;
  440. X    int result;
  441. X    register ModulePtr mp1;
  442. X
  443. X    if (--mp->refCnt > 0)
  444. X        return 0;
  445. X    if (mp->info && mp->info->fini)
  446. X        (*mp->info->fini)();
  447. X    result = unload(mp->entry);
  448. X    if (result == -1) {
  449. X        errvalid++;
  450. X        strcpy(errbuf, strerror(errno));
  451. X    }
  452. X    if (mp->exports) {
  453. X        register ExportPtr ep;
  454. X        register int i;
  455. X        for (ep = mp->exports, i = mp->nExports; i; i--, ep++)
  456. X            if (ep->name)
  457. X                free(ep->name);
  458. X        free(mp->exports);
  459. X    }
  460. X    if (mp == modList)
  461. X        modList = mp->next;
  462. X    else {
  463. X        for (mp1 = modList; mp1; mp1 = mp1->next)
  464. X            if (mp1->next == mp) {
  465. X                mp1->next = mp->next;
  466. X                break;
  467. X            }
  468. X    }
  469. X    free(mp->name);
  470. X    free(mp);
  471. X    return result;
  472. X}
  473. X
  474. Xstatic void terminate(void)
  475. X{
  476. X    while (modList)
  477. X        dlclose(modList);
  478. X}
  479. X
  480. X/*
  481. X * Build the export table from the XCOFF .loader section.
  482. X */
  483. Xstatic int readExports(ModulePtr mp)
  484. X{
  485. X    LDFILE *ldp = NULL;
  486. X    SCNHDR sh;
  487. X    LDHDR *lhp;
  488. X    char *ldbuf;
  489. X    LDSYM *ls;
  490. X    int i;
  491. X    ExportPtr ep;
  492. X
  493. X    if ((ldp = ldopen(mp->name, ldp)) == NULL) {
  494. X        struct ld_info *lp;
  495. X        char *buf;
  496. X        int size = 4*1024;
  497. X        if (errno != ENOENT) {
  498. X            errvalid++;
  499. X            strcpy(errbuf, "readExports: ");
  500. X            strcat(errbuf, strerror(errno));
  501. X            return -1;
  502. X        }
  503. X        /*
  504. X         * The module might be loaded due to the LIBPATH
  505. X         * environment variable. Search for the loaded
  506. X         * module using L_GETINFO.
  507. X         */
  508. X        if ((buf = malloc(size)) == NULL) {
  509. X            errvalid++;
  510. X            strcpy(errbuf, "readExports: ");
  511. X            strcat(errbuf, strerror(errno));
  512. X            return -1;
  513. X        }
  514. X        while ((i = loadquery(L_GETINFO, buf, size)) == -1 && errno == ENOMEM) {
  515. X            free(buf);
  516. X            size += 4*1024;
  517. X            if ((buf = malloc(size)) == NULL) {
  518. X                errvalid++;
  519. X                strcpy(errbuf, "readExports: ");
  520. X                strcat(errbuf, strerror(errno));
  521. X                return -1;
  522. X            }
  523. X        }
  524. X        if (i == -1) {
  525. X            errvalid++;
  526. X            strcpy(errbuf, "readExports: ");
  527. X            strcat(errbuf, strerror(errno));
  528. X            free(buf);
  529. X            return -1;
  530. X        }
  531. X        /*
  532. X         * Traverse the list of loaded modules. The entry point
  533. X         * returned by load() does actually point to the data
  534. X         * segment origin.
  535. X         */
  536. X        lp = (struct ld_info *)buf;
  537. X        while (lp) {
  538. X            if (lp->ldinfo_dataorg == mp->entry) {
  539. X                ldp = ldopen(lp->ldinfo_filename, ldp);
  540. X                break;
  541. X            }
  542. X            if (lp->ldinfo_next == 0)
  543. X                lp = NULL;
  544. X            else
  545. X                lp = (struct ld_info *)((char *)lp + lp->ldinfo_next);
  546. X        }
  547. X        free(buf);
  548. X        if (!ldp) {
  549. X            errvalid++;
  550. X            strcpy(errbuf, "readExports: ");
  551. X            strcat(errbuf, strerror(errno));
  552. X            return -1;
  553. X        }
  554. X    }
  555. X    if (TYPE(ldp) != U802TOCMAGIC) {
  556. X        errvalid++;
  557. X        strcpy(errbuf, "readExports: bad magic");
  558. X        while(ldclose(ldp) == FAILURE)
  559. X            ;
  560. X        return -1;
  561. X    }
  562. X    if (ldnshread(ldp, _LOADER, &sh) != SUCCESS) {
  563. X        errvalid++;
  564. X        strcpy(errbuf, "readExports: cannot read loader section header");
  565. X        while(ldclose(ldp) == FAILURE)
  566. X            ;
  567. X        return -1;
  568. X    }
  569. X    /*
  570. X     * We read the complete loader section in one chunk, this makes
  571. X     * finding long symbol names residing in the string table easier.
  572. X     */
  573. X    if ((ldbuf = (char *)malloc(sh.s_size)) == NULL) {
  574. X        errvalid++;
  575. X        strcpy(errbuf, "readExports: ");
  576. X        strcat(errbuf, strerror(errno));
  577. X        while(ldclose(ldp) == FAILURE)
  578. X            ;
  579. X        return -1;
  580. X    }
  581. X    if (FSEEK(ldp, sh.s_scnptr, BEGINNING) != OKFSEEK) {
  582. X        errvalid++;
  583. X        strcpy(errbuf, "readExports: cannot seek to loader section");
  584. X        free(ldbuf);
  585. X        while(ldclose(ldp) == FAILURE)
  586. X            ;
  587. X        return -1;
  588. X    }
  589. X    if (FREAD(ldbuf, sh.s_size, 1, ldp) != 1) {
  590. X        errvalid++;
  591. X        strcpy(errbuf, "readExports: cannot read loader section");
  592. X        free(ldbuf);
  593. X        while(ldclose(ldp) == FAILURE)
  594. X            ;
  595. X        return -1;
  596. X    }
  597. X    lhp = (LDHDR *)ldbuf;
  598. X    ls = (LDSYM *)(ldbuf+LDHDRSZ);
  599. X    /*
  600. X     * Count the number of exports to include in our export table.
  601. X     */
  602. X    for (i = lhp->l_nsyms; i; i--, ls++) {
  603. X        if (!LDR_EXPORT(*ls))
  604. X            continue;
  605. X        mp->nExports++;
  606. X    }
  607. X    if ((mp->exports = (ExportPtr)calloc(mp->nExports, sizeof(*mp->exports))) == NULL) {
  608. X        errvalid++;
  609. X        strcpy(errbuf, "readExports: ");
  610. X        strcat(errbuf, strerror(errno));
  611. X        free(ldbuf);
  612. X        while(ldclose(ldp) == FAILURE)
  613. X            ;
  614. X        return -1;
  615. X    }
  616. X    /*
  617. X     * Fill in the export table. All entries are relative to
  618. X     * the entry point we got from load.
  619. X     */
  620. X    ep = mp->exports;
  621. X    ls = (LDSYM *)(ldbuf+LDHDRSZ);
  622. X    for (i = lhp->l_nsyms; i; i--, ls++) {
  623. X        char *symname;
  624. X        if (!LDR_EXPORT(*ls))
  625. X            continue;
  626. X        if (ls->l_zeroes == 0)
  627. X            symname = ls->l_offset+lhp->l_stoff+ldbuf;
  628. X        else
  629. X            symname = ls->l_name;
  630. X        ep->name = strdup(symname);
  631. X        ep->addr = (void *)((unsigned long)mp->entry + ls->l_value);
  632. X        ep++;
  633. X    }
  634. X    free(ldbuf);
  635. X    while(ldclose(ldp) == FAILURE)
  636. X        ;
  637. X    return 0;
  638. X}
  639. SHAR_EOF
  640. $TOUCH -am 1227210092 dlfcn.c &&
  641. chmod 0444 dlfcn.c ||
  642. echo "restore of dlfcn.c failed"
  643. set `wc -c dlfcn.c`;Wc_c=$1
  644. if test "$Wc_c" != "9132"; then
  645.     echo original size 9132, current size $Wc_c
  646. fi
  647. # ============= dl.exp ==============
  648. echo "x - extracting dl.exp (Text)"
  649. sed 's/^X//' << 'SHAR_EOF' > dl.exp &&
  650. X#!/usr/local/lib/libdl.a
  651. Xdlopen
  652. Xdlclose
  653. Xdlsym
  654. Xdlerror
  655. SHAR_EOF
  656. $TOUCH -am 0802175192 dl.exp &&
  657. chmod 0664 dl.exp ||
  658. echo "restore of dl.exp failed"
  659. set `wc -c dl.exp`;Wc_c=$1
  660. if test "$Wc_c" != "54"; then
  661.     echo original size 54, current size $Wc_c
  662. fi
  663. exit 0
  664.  
  665.  
  666. -- 
  667. Jens-Uwe Mager
  668. HELIOS Software GmbH
  669. Lavesstr. 80
  670. 3000 Hannover 1, Germany
  671.