#include <dlfcn.h>
#include <err.h>
#include <stdio.h>
#include <stdlib.h>
void *libaa, *libab;
#define CALLBACK(name) static void name(void) { printf("exe "#name"\n"); }
CALLBACK(cleanup1)
CALLBACK(cleanup2)
CALLBACK(cleanup3)
static void
cleanup_dlclose(void)
{
printf("exe cleanup_dlclose begin\n");
dlclose(libaa);
dlclose(libab);
printf("exe cleanup_dlclose end\n");
}
static void
aa(void)
{
void (*func)(void) = dlsym(libaa, "aa");
if (func == NULL)
errx(1, "dlsym(libaa, aa): %s", dlerror());
func();
}
static void
ab(void)
{
void (*func)(void) = dlsym(libab, "ab");
if (func == NULL)
errx(1, "dlsym(libab, ab): %s", dlerror());
func();
}
int
main(int argc, char **argv)
{
int test;
libaa = dlopen(LIBAA, RTLD_LAZY);
if (libaa == NULL)
errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAA, dlerror());
libab = dlopen(LIBAB, RTLD_LAZY);
if (libab == NULL)
errx(1, "dlopen(%s, RTLD_LAZY): %s", LIBAB, dlerror());
if (argc != 2)
test = 0;
else
test = atoi(argv[1]);
switch (test) {
case 0:
atexit(cleanup1);
aa();
atexit(cleanup2);
ab();
atexit(cleanup3);
exit(0);
case 1:
atexit(cleanup1);
aa();
atexit(cleanup2);
ab();
atexit(cleanup3);
dlclose(libaa);
dlclose(libab);
exit(0);
case 2:
atexit(cleanup1);
aa();
atexit(cleanup_dlclose);
ab();
atexit(cleanup3);
exit(0);
case 3:
atexit(cleanup1);
aa();
atexit(cleanup2);
ab();
atexit(cleanup_dlclose);
exit(0);
}
return (0);
}