#include #include #include #include #include #include #include #include #include struct _hexagram_module { const char *soname; void *handle; char *(*name)(); int (*run)(hexagram_dict *buses); pid_t pid; }; hexagram_module *hexagram_module_open(const char *soname) { hexagram_module *module; if ((module = malloc(sizeof(*module))) == NULL) { goto error_malloc; } if ((module->handle = dlopen(soname, RTLD_LAZY)) == NULL) { goto error_dlopen; } if ((module->run = dlsym(module->handle, "_hexagram_module_run")) == NULL) { goto error_dlsym; } if ((module->name = dlsym(module->handle, "_hexagram_module_name")) == NULL) { goto error_dlsym; } module->soname = soname; module->pid = 0; return module; error_dlsym: dlclose(module->handle); error_dlopen: free(module); error_malloc: return NULL; } const char *hexagram_module_name(hexagram_module *module) { if (module->name == NULL) { return NULL; } return module->name(); } int hexagram_module_run(hexagram_module *module, hexagram_dict *buses) { if (module->run == NULL) { return -1; } /* * Module already stopped */ if (module->pid < 0) { return -1; } if ((module->pid = fork()) < 0) { goto error_fork; } if (module->pid == 0) { exit(module->run(buses)); } return 0; error_fork: return -1; } int hexagram_module_stop(hexagram_module *module) { if (module->pid <= 0) { return 0; } if (kill(module->pid, SIGTERM) < 0) { if (kill(module->pid, SIGKILL) < 0) { goto error_kill; } } if (waitpid(module->pid, NULL, 0) < 0) { goto error_waitpid; } /* * Mark the module as stopped */ module->pid = -1; return 0; error_waitpid: error_kill: return -1; } int hexagram_module_close(hexagram_module *module) { if (hexagram_module_stop(module) < 0) { goto error_stop_module; } if (dlclose(module->handle) < 0) { goto error_dlclose; } memset(module, '\0', sizeof(*module)); free(module); return 0; error_dlclose: memset(module, '\0', sizeof(*module)); free(module); error_stop_module: return -1; }