169 lines
3.4 KiB
C
169 lines
3.4 KiB
C
#define _GNU_SOURCE
|
|
#include <stdio.h>
|
|
#include <stdlib.h>
|
|
#include <freetdm.h>
|
|
#include <ftdm_dso.h>
|
|
#include <dlfcn.h>
|
|
#include <execinfo.h>
|
|
|
|
#define ARRLEN(obj) (sizeof(obj)/sizeof(obj[0]))
|
|
|
|
struct dso_entry {
|
|
char name[25];
|
|
ftdm_dso_lib_t lib;
|
|
};
|
|
|
|
struct dso_entry loaded[10];
|
|
|
|
static void *(*real_dlopen)(const char *filename, int flag) = NULL;
|
|
static int (*real_dlclose)(void *handle) = NULL;
|
|
|
|
static void print_stack()
|
|
{
|
|
void *stacktrace[100];
|
|
char **symbols;
|
|
int size;
|
|
int i;
|
|
size = backtrace(stacktrace, ARRLEN(stacktrace));
|
|
symbols = backtrace_symbols(stacktrace, size);
|
|
if (!symbols) {
|
|
return;
|
|
}
|
|
for (i = 0; i < size; i++) {
|
|
ftdm_log(FTDM_LOG_DEBUG, "%s\n", symbols[i]);
|
|
}
|
|
free(symbols);
|
|
}
|
|
|
|
void *dlopen(const char *filename, int flag)
|
|
{
|
|
char *msg = NULL;
|
|
void *handle = NULL;
|
|
print_stack();
|
|
if (real_dlopen == NULL) {
|
|
dlerror();
|
|
real_dlopen = dlsym(RTLD_NEXT, "dlopen");
|
|
if ((msg = dlerror()) != NULL) {
|
|
fprintf(stderr, "dlsym failed: %s\n", msg);
|
|
exit(1);
|
|
}
|
|
fprintf(stderr, "Real dlopen at addr %p\n", real_dlopen);
|
|
}
|
|
handle = real_dlopen(filename, flag);
|
|
if (!handle) {
|
|
return NULL;
|
|
}
|
|
ftdm_log(FTDM_LOG_NOTICE, "Loaded %s with handle %p\n", filename, handle);
|
|
return handle;
|
|
}
|
|
|
|
int dlclose(void *handle)
|
|
{
|
|
char *msg = NULL;
|
|
print_stack();
|
|
if (real_dlclose == NULL) {
|
|
dlerror();
|
|
real_dlclose = dlsym(RTLD_NEXT, "dlclose");
|
|
if ((msg = dlerror()) != NULL) {
|
|
fprintf(stderr, "dlsym failed: %s\n", msg);
|
|
exit(1);
|
|
}
|
|
fprintf(stderr, "Real dlclose at addr %p\n", real_dlclose);
|
|
}
|
|
ftdm_log(FTDM_LOG_NOTICE, "Unloading %p\n", handle);
|
|
return real_dlclose(handle);
|
|
}
|
|
|
|
int load(char *name)
|
|
{
|
|
char path[255];
|
|
char *err;
|
|
struct dso_entry *entry = NULL;
|
|
int i;
|
|
|
|
for (i = 0; i < ARRLEN(loaded); i++) {
|
|
if (!loaded[i].lib) {
|
|
entry = &loaded[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!entry) {
|
|
ftdm_log(FTDM_LOG_CRIT, "Cannot load more libraries\n");
|
|
return -1;
|
|
}
|
|
|
|
ftdm_build_dso_path(name, path, sizeof(path));
|
|
ftdm_log(FTDM_LOG_DEBUG, "Loading %s!\n", path);
|
|
entry->lib = ftdm_dso_open(path, &err);
|
|
if (!entry->lib) {
|
|
ftdm_log(FTDM_LOG_CRIT, "Cannot load library '%s': %s\n", path, err);
|
|
return -1;
|
|
}
|
|
strncpy(entry->name, name, sizeof(entry->name)-1);
|
|
entry->name[sizeof(entry->name)-1] = 0;
|
|
return 0;
|
|
}
|
|
|
|
int unload(char *name)
|
|
{
|
|
int i;
|
|
struct dso_entry *entry = NULL;
|
|
ftdm_log(FTDM_LOG_DEBUG, "Unloading %s!\n", name);
|
|
for (i = 0; i < ARRLEN(loaded); i++) {
|
|
if (loaded[i].lib && !strcasecmp(loaded[i].name, name)) {
|
|
entry = &loaded[i];
|
|
break;
|
|
}
|
|
}
|
|
|
|
if (!entry) {
|
|
ftdm_log(FTDM_LOG_CRIT, "Library %s not found\n", name);
|
|
return -1;
|
|
}
|
|
|
|
ftdm_dso_destroy(&entry->lib);
|
|
entry->lib = NULL;
|
|
return 0;
|
|
}
|
|
|
|
int main(int argc, char *argv[])
|
|
{
|
|
char cmdline[255];
|
|
char name[255];
|
|
|
|
ftdm_global_set_default_logger(FTDM_LOG_LEVEL_DEBUG);
|
|
|
|
if (ftdm_global_init() != FTDM_SUCCESS) {
|
|
fprintf(stderr, "Error loading FreeTDM\n");
|
|
exit(-1);
|
|
}
|
|
|
|
memset(loaded, 0, sizeof(loaded));
|
|
|
|
printf("CLI> ");
|
|
while (fgets(cmdline, sizeof(cmdline), stdin)) {
|
|
if (sscanf(cmdline, "load=%s\n", name) == 1) {
|
|
load(name);
|
|
} else if (sscanf(cmdline, "unload=%s\n", name) == 1) {
|
|
unload(name);
|
|
} else if (!strncasecmp(cmdline, "exit", sizeof("exit")-1)) {
|
|
printf("Quitting ...\n");
|
|
sleep(1);
|
|
break;
|
|
} else {
|
|
fprintf(stderr, "load=<name> | unload=<name> | exit\n");
|
|
}
|
|
printf("\nCLI> ");
|
|
}
|
|
|
|
|
|
ftdm_global_destroy();
|
|
|
|
printf("Done, press any key to die!\n");
|
|
|
|
getchar();
|
|
return 0;
|
|
}
|
|
|