| 165 | */ |
| 166 | static std::map<const char *, Plugin *, CStrCmp> plugins; |
| 167 | Plugin *openPlugin(const char *basename) |
| 168 | { |
| 169 | std::string filename(basename); |
| 170 | if (!hasSuffix(filename, ".so")) |
| 171 | filename += ".so"; |
| 172 | const char *pathname = realpath(filename.c_str(), nullptr); |
| 173 | if (pathname == nullptr) |
| 174 | error("failed to create path for plugin \"%s\"; %s", basename, |
| 175 | strerror(errno)); |
| 176 | auto i = plugins.find(pathname); |
| 177 | if (i != plugins.end()) |
| 178 | { |
| 179 | free((char *)pathname); |
| 180 | return i->second; |
| 181 | } |
| 182 | |
| 183 | void *handle = dlopen(pathname, RTLD_LOCAL | RTLD_LAZY); |
| 184 | if (handle == nullptr) |
| 185 | error("failed to load plugin \"%s\": %s", pathname, dlerror()); |
| 186 | |
| 187 | Plugin *plugin = new Plugin; |
| 188 | plugin->filename = pathname; |
| 189 | plugin->handle = handle; |
| 190 | plugin->context = nullptr; |
| 191 | plugin->result = 0; |
| 192 | plugin->initFunc = (PluginInit)dlsym(handle, "e9_plugin_init"); |
| 193 | plugin->eventFunc = (PluginEvent)dlsym(handle, "e9_plugin_event"); |
| 194 | plugin->matchFunc = (PluginMatch)dlsym(handle, "e9_plugin_match"); |
| 195 | plugin->codeFunc = (PluginCode)dlsym(handle, "e9_plugin_code"); |
| 196 | plugin->dataFunc = (PluginData)dlsym(handle, "e9_plugin_data"); |
| 197 | plugin->patchFunc = (PluginPatch)dlsym(handle, "e9_plugin_patch"); |
| 198 | plugin->finiFunc = (PluginFini)dlsym(handle, "e9_plugin_fini"); |
| 199 | if (plugin->initFunc == nullptr && plugin->eventFunc == nullptr && |
| 200 | plugin->codeFunc == nullptr && plugin->dataFunc == nullptr && |
| 201 | plugin->matchFunc == nullptr && plugin->patchFunc == nullptr && |
| 202 | plugin->finiFunc == nullptr) |
| 203 | error("failed to load plugin \"%s\"; the shared " |
| 204 | "object does not export any plugin API functions", |
| 205 | plugin->filename); |
| 206 | |
| 207 | plugin->argv.push_back(strDup(basename)); |
| 208 | for (auto &entry: option_plugin) |
| 209 | { |
| 210 | if (entry.first == nullptr) |
| 211 | continue; |
| 212 | if (strcmp(entry.first, basename) != 0) |
| 213 | continue; |
| 214 | if (entry.second != nullptr) |
| 215 | plugin->argv.push_back(entry.second); |
| 216 | delete entry.first; |
| 217 | entry.first = entry.second = nullptr; |
| 218 | } |
| 219 | plugin->argv.shrink_to_fit(); |
| 220 | plugins.insert({plugin->filename, plugin}); |
| 221 | return plugin; |
| 222 | } |
| 223 | |
| 224 | /* |