#include #include #include "toml/toml.h" #include "plugin_manager_config.h" /****************************************************************************** * Private API (For Parse) ******************************************************************************/ static int toml_parse_string(toml_table_t *table, const char *string_key, const char *file, char **out) { toml_datum_t string_val = toml_string_in(table, string_key); if (!string_val.ok) { plugin_manager_log(ERROR, "can't find '%s' configuration iterm in %s", string_key, file); return -1; } if (strlen(string_val.u.s) <= 0) { plugin_manager_log(ERROR, "invalid value for '%s' configuration item in %s", string_key, file); safe_free(string_val.u.s); return -1; } *out = safe_dup(string_val.u.s); safe_free(string_val.u.s); return 0; } static int toml_parse_table(toml_table_t *table, const char *string_key, const char *file, toml_table_t **out) { *out = toml_table_in(table, string_key); if (*out == NULL) { plugin_manager_log(ERROR, "can't find '%s' section in %s", string_key, file); return -1; } return 0; } static int toml_parse_plugin_section(toml_table_t *root, struct plugin_manager_config *config, const char *file) { toml_table_t *plugin_section = NULL; if (toml_parse_table(root, "PLUGINFO", file, &plugin_section) == -1) { return -1; } if (toml_parse_string(plugin_section, "INIT_FUNC", file, &config->plugin_section.init_func_name) == -1) { return -1; } if (toml_parse_string(plugin_section, "EXIT_FUNC", file, &config->plugin_section.exit_func_name) == -1) { return -1; } if (toml_parse_string(plugin_section, "LIBRARY_PATH", file, &config->plugin_section.lib_path) == -1) { return -1; } return 0; } static int toml_parse_session_section(toml_table_t *root, struct plugin_manager_config *config, const char *file) { toml_table_t *session_section = NULL; toml_table_t *sub_session_section = NULL; const char *session_name = NULL; toml_array_t *event_type_array = NULL; toml_datum_t type_str; enum session_event_type type_int; if (toml_parse_table(root, "SESSION_NAME", file, &session_section) == -1) { return -1; } for (int i = 0; i < toml_table_ntab(session_section); i++) { session_name = NULL; sub_session_section = NULL; event_type_array = NULL; config->session_section = (struct session_section_config *)realloc(config->session_section, sizeof(struct session_section_config) * (config->session_section_num + 1)); config->session_section[config->session_section_num].event = SESSION_EVENT_UNKNOWN; config->session_section[config->session_section_num].cb_func_name = NULL; memset(config->session_section[config->session_section_num].session_name, 0, MAX_SESSION_NAME_LENGTH); // parse session name session_name = toml_key_in(session_section, i); int session_name_len = strlen(session_name); if (session_name_len <= 0) { plugin_manager_log(ERROR, "invalid value for 'SESSION_NAME' configuration item in %s", file); return -1; } if (session_name_len > MAX_SESSION_NAME_LENGTH) { plugin_manager_log(ERROR, "invalid value for 'SESSION_NAME' configuration item in %s, '%s' is too long and exceeds %d bytes", file, session_name, MAX_SESSION_NAME_LENGTH); return -1; } if (toml_parse_table(session_section, session_name, file, &sub_session_section) == -1) { return -1; } strncpy(config->session_section[config->session_section_num].session_name, session_name, session_name_len); // parse session event callback if (toml_parse_string(sub_session_section, "SESSION_EVENT_CALLBACK", file, &config->session_section[config->session_section_num].cb_func_name) == -1) { return -1; } event_type_array = toml_array_in(sub_session_section, "SESSION_EVENT_TYPE"); if (event_type_array == NULL) { plugin_manager_log(ERROR, "can't find 'SESSION_EVENT_TYPE' configuration iterm in '[SESSION_NAME.%s]' section of %s", session_name, file); return -1; } for (int i = 0; i < toml_array_nelem(event_type_array); i++) { type_int = SESSION_EVENT_UNKNOWN; type_str = toml_string_at(event_type_array, i); if (!type_str.ok) { plugin_manager_log(ERROR, "can't parse 'SESSION_EVENT_TYPE' configuration iterm in '[SESSION_NAME.%s]' section of %s", session_name, file); return -1; } type_int = session_event_type_str2int(type_str.u.s); if (type_int == SESSION_EVENT_UNKNOWN) { plugin_manager_log(ERROR, "invalid value '%s' for 'SESSION_EVENT_TYPE' configuration item in '[SESSION_NAME.%s]' section of %s", type_str.u.s, session_name, file); safe_free(type_str.u.s); return -1; } (config->session_section[config->session_section_num].event) = (enum session_event_type)((config->session_section[config->session_section_num].event) | type_int); safe_free(type_str.u.s); } if ((config->session_section[config->session_section_num].event & SESSION_EVENT_CLOSING) == 0) { plugin_manager_log(WARN, "can't find 'SESSION_EVENT_CLOSING' value for 'SESSION_EVENT_TYPE' configuration item in '[SESSION_NAME.%s]' section of %s", session_name, file); } config->session_section_num++; } return 0; } /****************************************************************************** * Public API ******************************************************************************/ struct plugin_manager_config *plugin_mangager_config_create() { struct plugin_manager_config *config = safe_alloc(struct plugin_manager_config, 1); config->file_path = NULL; config->session_section_num = 0; config->session_section = NULL; config->plugin_section.init_func_name = NULL; config->plugin_section.exit_func_name = NULL; config->plugin_section.lib_path = NULL; return config; } void plugin_mangager_config_destory(struct plugin_manager_config *config) { if (config) { safe_free(config->file_path); safe_free(config->plugin_section.init_func_name); safe_free(config->plugin_section.exit_func_name); safe_free(config->plugin_section.lib_path); if (config->session_section) { for (int i = 0; i < config->session_section_num; i++) { struct session_section_config *temp = &config->session_section[i]; safe_free(temp->cb_func_name); } config->session_section_num = 0; safe_free(config->session_section); } safe_free(config); } } void plugin_mangager_config_dump(struct plugin_manager_config *config) { if (config) { plugin_manager_log(DEBUG, "[CONFIG_FILE] : %s", config->file_path); plugin_manager_log(DEBUG, "[PLUGINFO]->INIT_FUNC : %s", config->plugin_section.init_func_name); plugin_manager_log(DEBUG, "[PLUGINFO]->EXIT_FUNC : %s", config->plugin_section.exit_func_name); plugin_manager_log(DEBUG, "[PLUGINFO]->LIBRARY_PATH : %s", config->plugin_section.lib_path); if (config->session_section) { for (int i = 0; i < config->session_section_num; i++) { char tmp_buffer[1024] = {0}; struct session_section_config *temp = &config->session_section[i]; session_event_type_int2str(temp->event, tmp_buffer, 1024); plugin_manager_log(DEBUG, "[SESSION_NAME.%s]->SESSION_EVENT_TYPE : %d, %s", temp->session_name, temp->event, tmp_buffer); plugin_manager_log(DEBUG, "[SESSION_NAME.%s]->SESSION_EVENT_CALLBACK : %s", temp->session_name, temp->cb_func_name); } } } } int plugin_mangager_config_parse(struct plugin_manager_config *config, const char *file) { FILE *fp = NULL; toml_table_t *root = NULL; char errbuf[200] = {0}; config->file_path = safe_dup(file); fp = fopen(config->file_path, "r"); if (fp == NULL) { plugin_manager_log(ERROR, "can't open %s, %s", config->file_path, strerror(errno)); return -1; } root = toml_parse_file(fp, errbuf, sizeof(errbuf)); if (root == NULL) { plugin_manager_log(ERROR, "toml parsing %s failed, %s", file, errbuf); goto err; } if (toml_parse_plugin_section(root, config, file) == -1) { goto err; } if (toml_parse_session_section(root, config, file) == -1) { goto err; } toml_free(root); fclose(fp); plugin_manager_log(INFO, "plugin config file '%s' parse success", config->file_path); return 0; err: if (root) { toml_free(root); } if (fp) { fclose(fp); fp = NULL; } return -1; }