#define _GNU_SOURCE #include #include #include #include #include #include #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= | unload= | exit\n"); } printf("\nCLI> "); } ftdm_global_destroy(); printf("Done, press any key to die!\n"); getchar(); return 0; }