diff options
Diffstat (limited to 'fluent-bit/lib/monkey/mk_core/mk_rconf.c')
-rw-r--r-- | fluent-bit/lib/monkey/mk_core/mk_rconf.c | 779 |
1 files changed, 0 insertions, 779 deletions
diff --git a/fluent-bit/lib/monkey/mk_core/mk_rconf.c b/fluent-bit/lib/monkey/mk_core/mk_rconf.c deleted file mode 100644 index bf169d0e8..000000000 --- a/fluent-bit/lib/monkey/mk_core/mk_rconf.c +++ /dev/null @@ -1,779 +0,0 @@ -/* -*- Mode: C; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ - -/* Monkey HTTP Server - * ================== - * Copyright 2001-2017 Eduardo Silva <eduardo@monkey.io> - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -#include <ctype.h> -#include <string.h> -#include <time.h> -#include <string.h> -#include <sys/types.h> -#include <sys/stat.h> -#ifndef _MSC_VER -#include <glob.h> -#endif - -#include <mk_core/mk_rconf.h> -#include <mk_core/mk_utils.h> -#include <mk_core/mk_string.h> -#include <mk_core/mk_list.h> - -#ifdef _WIN32 -#include <Windows.h> -#include <strsafe.h> -#define PATH_MAX MAX_PATH -#endif - -/* Raise a configuration schema error */ -static void mk_config_error(const char *path, int line, const char *msg) -{ - mk_err("File %s", path); - mk_err("Error in line %i: %s", line, msg); -} - -/* Raise a warning */ -static void mk_rconf_warning(const char *path, int line, const char *msg) -{ - mk_warn("Config file warning '%s':\n" - "\t\t\t\tat line %i: %s", - path, line, msg); -} - - -/* Returns a configuration section by [section name] */ -struct mk_rconf_section *mk_rconf_section_get(struct mk_rconf *conf, - const char *name) -{ - struct mk_list *head; - struct mk_rconf_section *section; - - mk_list_foreach(head, &conf->sections) { - section = mk_list_entry(head, struct mk_rconf_section, _head); - if (strcasecmp(section->name, name) == 0) { - return section; - } - } - - return NULL; -} - -/* Register a key/value entry in the last section available of the struct */ -static void mk_rconf_section_entry_add(struct mk_rconf *conf, - const char *key, const char *val) -{ - struct mk_rconf_section *section; - struct mk_rconf_entry *new; - struct mk_list *head = &conf->sections; - - if (mk_list_is_empty(&conf->sections) == 0) { - mk_err("Error: there are not sections available on %s!", conf->file); - return; - } - - /* Last section */ - section = mk_list_entry_last(head, struct mk_rconf_section, _head); - - /* Alloc new entry */ - new = mk_mem_alloc(sizeof(struct mk_rconf_entry)); - new->key = mk_string_dup(key); - new->val = mk_string_dup(val); - - mk_list_add(&new->_head, §ion->entries); -} - -/* Create a configuration schema */ -struct mk_rconf *mk_rconf_create(const char *name) -{ - struct mk_rconf *conf = NULL; - - /* Alloc configuration node */ - conf = mk_mem_alloc_z(sizeof(struct mk_rconf)); - if (!conf) { - perror("malloc"); - return NULL; - } - conf->created = time(NULL); - conf->file = mk_string_dup(name); - mk_list_init(&conf->sections); - - return conf; -} - -static int is_file_included(struct mk_rconf *conf, const char *path) -{ - struct mk_list *head; - struct mk_rconf_file *file; - - mk_list_foreach(head, &conf->includes) { - file = mk_list_entry(head, struct mk_rconf_file, _head); - if (strcmp(file->path, path) == 0) { - return MK_TRUE; - } - } - - return MK_FALSE; -} - -char *mk_rconf_meta_get(struct mk_rconf *conf, char *key) -{ - struct mk_list *head; - struct mk_rconf_entry *meta; - - mk_list_foreach(head, &conf->metas) { - meta = mk_list_entry(head, struct mk_rconf_entry, _head); - if (strcmp(meta->key, key) == 0) { - return meta->val; - } - } - - return NULL; -} - -static int mk_rconf_meta_add(struct mk_rconf *conf, char *buf, int len) -{ - int xlen; - char *p; - char *tmp; - struct mk_rconf_entry *meta; - - if (buf[0] != '@') { - return -1; - } - - meta = mk_mem_alloc(sizeof(struct mk_rconf_entry)); - if (!meta) { - return -1; - } - - p = buf; - tmp = strchr(p, ' '); - xlen = (tmp - p); - meta->key = mk_string_copy_substr(buf, 1, xlen); - mk_string_trim(&meta->key); - - meta->val = mk_string_copy_substr(buf, xlen + 1, len); - mk_string_trim(&meta->val); - - mk_list_add(&meta->_head, &conf->metas); - return 0; -} - -static int check_indent(const char *line, const char *indent) -{ - while (*line == *indent && *indent) { - line++; - indent++; - } - - if (*indent != '\0') { - if (isblank(*line)) { - mk_err("[config] Inconsistent use of tab and space"); - } - else { - mk_err("[config] Indentation level is too low"); - } - return -1; - } - - if (isblank(*line)) { - mk_err("[config] Extra indentation level found"); - return -1; - } - - return 0; -} - -/* To call this function from mk_rconf_read */ -static int mk_rconf_read_glob(struct mk_rconf *conf, const char * path); - -static int mk_rconf_read(struct mk_rconf *conf, const char *path) -{ - int i; - int len; - int ret; - int line = 0; - int indent_len = -1; - int n_keys = 0; - char *buf; - char tmp[PATH_MAX]; - char *section = NULL; - char *indent = NULL; - char *key, *val; - char *cfg_file = (char *) path; - struct stat st; - struct mk_rconf_file *file; - struct mk_rconf_section *current = NULL; - FILE *f; - - /* Check if the path exists (relative cases for included files) */ - if (conf->level >= 0) { - ret = stat(path, &st); - if (ret == -1 && errno == ENOENT) { - /* Try to resolve the real path (if exists) */ - if (path[0] == '/') { - return -1; - } - - if (conf->root_path) { - snprintf(tmp, PATH_MAX, "%s/%s", conf->root_path, path); - cfg_file = tmp; - } - } - } - - /* Check this file have not been included before */ - ret = is_file_included(conf, cfg_file); - if (ret == MK_TRUE) { - mk_err("[config] file already included %s", cfg_file); - return -1; - } - - conf->level++; - - /* Open configuration file */ - if ((f = fopen(cfg_file, "r")) == NULL) { - mk_warn("[config] I cannot open %s file", cfg_file); - return -1; - } - - /* Allocate temporal buffer to read file content */ - buf = mk_mem_alloc(MK_RCONF_KV_SIZE); - if (!buf) { - fclose(f); - perror("malloc"); - return -1; - } - - /* looking for configuration directives */ - while (fgets(buf, MK_RCONF_KV_SIZE, f)) { - len = strlen(buf); - if (len > 0 && buf[len - 1] == '\n') { - buf[--len] = 0; - if (len && buf[len - 1] == '\r') { - buf[--len] = 0; - } - } - else { - /* - * If we don't find a break line, validate if we got an EOF or not. No EOF - * means that the incoming string is not finished so we must raise an - * exception. - */ - if (!feof(f)) { - mk_config_error(path, line, "Length of content has exceeded limit"); - fclose(f); - mk_mem_free(buf); - return -1; - } - } - - /* Line number */ - line++; - - if (!buf[0]) { - continue; - } - - /* Skip commented lines */ - if (buf[0] == '#') { - continue; - } - - if (len > 9 && strncasecmp(buf, "@INCLUDE ", 9) == 0) { - if (strchr(buf + 9, '*') != NULL) { - ret = mk_rconf_read_glob(conf, buf + 9); - } - else { - ret = mk_rconf_read(conf, buf + 9); - } - if (ret == -1) { - conf->level--; - fclose(f); - if (indent) { - mk_mem_free(indent); - } - mk_mem_free(buf); - return -1; - } - continue; - } - else if (buf[0] == '@' && len > 3) { - ret = mk_rconf_meta_add(conf, buf, len); - if (ret == -1) { - fclose(f); - if (indent) { - mk_mem_free(indent); - } - mk_mem_free(buf); - return -1; - } - continue; - } - - /* Section definition */ - if (buf[0] == '[') { - int end = -1; - end = mk_string_char_search(buf, ']', len); - if (end > 0) { - /* - * Before to add a new section, lets check the previous - * one have at least one key set - */ - if (current && n_keys == 0) { - mk_rconf_warning(path, line, "Previous section did not have keys"); - } - - /* Create new section */ - section = mk_string_copy_substr(buf, 1, end); - current = mk_rconf_section_add(conf, section); - if (!current) { - fclose(f); - if (indent) { - mk_mem_free(indent); - } - mk_mem_free(buf); - mk_mem_free(section); - return -1; - } - mk_mem_free(section); - n_keys = 0; - continue; - } - else { - mk_config_error(path, line, "Bad header definition"); - fclose(f); - mk_mem_free(buf); - return -1; - } - } - - /* No separator defined */ - if (!indent) { - i = 0; - - do { i++; } while (i < len && isblank(buf[i])); - - indent = mk_string_copy_substr(buf, 0, i); - indent_len = strlen(indent); - - /* Blank indented line */ - if (i == len) { - continue; - } - } - - /* Validate indentation level */ - if (check_indent(buf, indent) < 0) { - mk_config_error(path, line, "Invalid indentation level"); - fclose(f); - return -1; - } - - if (buf[indent_len] == '#' || indent_len == len) { - continue; - } - - if (len - indent_len >= 3 && strncmp(buf + indent_len, "---", 3) == 0) { - continue; - } - - /* Get key and val */ - i = mk_string_char_search(buf + indent_len, ' ', len - indent_len); - key = mk_string_copy_substr(buf + indent_len, 0, i); - val = mk_string_copy_substr(buf + indent_len + i, 1, len - indent_len - i); - - if (!key || !val || i < 0) { - mk_config_error(path, line, "Each key must have a value"); - fclose(f); - mk_mem_free(key); - mk_mem_free(val); - return -1; - } - - /* Trim strings */ - mk_string_trim(&key); - mk_string_trim(&val); - - if (strlen(val) == 0) { - mk_config_error(path, line, "Key has an empty value"); - fclose(f); - mk_mem_free(key); - mk_mem_free(val); - return -1; - } - - /* Register entry: key and val are copied as duplicated */ - mk_rconf_section_entry_add(conf, key, val); - - /* Free temporal key and val */ - mk_mem_free(key); - mk_mem_free(val); - - n_keys++; - } - - if (section && n_keys == 0) { - /* No key, no warning */ - } - - /* - struct mk_config_section *s; - struct mk_rconf_entry *e; - - s = conf->section; - while(s) { - printf("\n[%s]", s->name); - e = s->entry; - while(e) { - printf("\n %s = %s", e->key, e->val); - e = e->next; - } - s = s->next; - } - fflush(stdout); - */ - fclose(f); - if (indent) { - mk_mem_free(indent); - } - mk_mem_free(buf); - - /* Append this file to the list */ - file = mk_mem_alloc(sizeof(struct mk_rconf_file)); - if (!file) { - conf->level--; - return -1; - } - - file->path = mk_string_dup(path); - mk_list_add(&file->_head, &conf->includes); - conf->level--; - return 0; -} - -#ifndef _WIN32 -static int mk_rconf_read_glob(struct mk_rconf *conf, const char * path) -{ - int ret = -1; - glob_t glb; - char tmp[PATH_MAX]; - - const char *glb_path; - size_t i; - int ret_glb = -1; - - if (conf->root_path && path[0] != '/') { - snprintf(tmp, PATH_MAX, "%s/%s", conf->root_path, path); - glb_path = tmp; - } - else { - glb_path = path; - } - - ret_glb = glob(glb_path, GLOB_NOSORT, NULL, &glb); - if (ret_glb != 0) { - switch(ret_glb){ - case GLOB_NOSPACE: - mk_warn("[%s] glob: [%s] no space", __FUNCTION__, glb_path); - break; - case GLOB_NOMATCH: - mk_warn("[%s] glob: [%s] no match", __FUNCTION__, glb_path); - break; - case GLOB_ABORTED: - mk_warn("[%s] glob: [%s] aborted", __FUNCTION__, glb_path); - break; - default: - mk_warn("[%s] glob: [%s] other error", __FUNCTION__, glb_path); - } - return ret; - } - - for (i = 0; i < glb.gl_pathc; i++) { - ret = mk_rconf_read(conf, glb.gl_pathv[i]); - if (ret < 0) { - break; - } - } - - globfree(&glb); - return ret; -} -#else -static int mk_rconf_read_glob(struct mk_rconf *conf, const char *path) -{ - char *star, *p0, *p1; - char pattern[MAX_PATH]; - char buf[MAX_PATH]; - int ret; - struct stat st; - HANDLE h; - WIN32_FIND_DATA data; - - if (strlen(path) > MAX_PATH - 1) { - return -1; - } - - star = strchr(path, '*'); - if (star == NULL) { - return -1; - } - - /* - * C:\data\tmp\input_*.conf - * 0<-----| - */ - p0 = star; - while (path <= p0 && *p0 != '\\') { - p0--; - } - - /* - * C:\data\tmp\input_*.conf - * |---->1 - */ - p1 = star; - while (*p1 && *p1 != '\\') { - p1++; - } - - memcpy(pattern, path, (p1 - path)); - pattern[p1 - path] = '\0'; - - h = FindFirstFileA(pattern, &data); - if (h == INVALID_HANDLE_VALUE) { - return 0; - } - - do { - /* Ignore the current and parent dirs */ - if (!strcmp(".", data.cFileName) || !strcmp("..", data.cFileName)) { - continue; - } - - /* Avoid an infinite loop */ - if (strchr(data.cFileName, '*')) { - continue; - } - - /* Create a path (prefix + filename + suffix) */ - memcpy(buf, path, p0 - path + 1); - buf[p0 - path + 1] = '\0'; - - if (FAILED(StringCchCatA(buf, MAX_PATH, data.cFileName))) { - continue; - } - if (FAILED(StringCchCatA(buf, MAX_PATH, p1))) { - continue; - } - - if (strchr(p1, '*')) { - mk_rconf_read_glob(conf, buf); /* recursive */ - continue; - } - - ret = stat(buf, &st); - if (ret == 0 && (st.st_mode & S_IFMT) == S_IFREG) { - if (mk_rconf_read(conf, buf) < 0) { - return -1; - } - } - } while (FindNextFileA(h, &data) != 0); - - FindClose(h); - return 0; -} -#endif - -static int mk_rconf_path_set(struct mk_rconf *conf, char *file) -{ - char *p; - char *end; - char path[PATH_MAX + 1]; - -#ifdef _MSC_VER - p = _fullpath(path, file, PATH_MAX + 1); -#else - p = realpath(file, path); -#endif - if (!p) { - return -1; - } - - /* lookup path ending and truncate */ - end = strrchr(path, '/'); - if (!end) { - return -1; - } - - end++; - *end = '\0'; - conf->root_path = mk_string_dup(path); - - return 0; -} - -struct mk_rconf *mk_rconf_open(const char *path) -{ - int ret; - struct mk_rconf *conf = NULL; - - if (!path) { - mk_warn("[config] invalid path file %s", path); - return NULL; - } - - /* Alloc configuration node */ - conf = mk_mem_alloc_z(sizeof(struct mk_rconf)); - if (!conf) { - perror("malloc"); - return NULL; - } - conf->created = time(NULL); - conf->file = mk_string_dup(path); - conf->level = -1; - mk_list_init(&conf->sections); - mk_list_init(&conf->includes); - mk_list_init(&conf->metas); - - /* Set the absolute path for the entrypoint file */ - mk_rconf_path_set(conf, (char *) path); - - /* Read entrypoint */ - ret = mk_rconf_read(conf, path); - if (ret == -1) { - mk_rconf_free(conf); - return NULL; - } - - return conf; -} - -void mk_rconf_free(struct mk_rconf *conf) -{ - struct mk_list *head, *tmp; - struct mk_rconf_section *section; - struct mk_rconf_entry *entry; - struct mk_rconf_file *file; - - /* Remove included files */ - mk_list_foreach_safe(head, tmp, &conf->includes) { - file = mk_list_entry(head, struct mk_rconf_file, _head); - mk_list_del(&file->_head); - mk_mem_free(file->path); - mk_mem_free(file); - } - - /* Remove metas */ - mk_list_foreach_safe(head, tmp, &conf->metas) { - entry = mk_list_entry(head, struct mk_rconf_entry, _head); - mk_list_del(&entry->_head); - mk_mem_free(entry->key); - mk_mem_free(entry->val); - mk_mem_free(entry); - } - - /* Free sections */ - mk_list_foreach_safe(head, tmp, &conf->sections) { - section = mk_list_entry(head, struct mk_rconf_section, _head); - mk_list_del(§ion->_head); - - /* Free section entries */ - mk_rconf_free_entries(section); - - /* Free section node */ - mk_mem_free(section->name); - mk_mem_free(section); - } - if (conf->file) { - mk_mem_free(conf->file); - } - - mk_mem_free(conf->root_path); - mk_mem_free(conf); -} - -void mk_rconf_free_entries(struct mk_rconf_section *section) -{ - struct mk_rconf_entry *entry; - struct mk_list *head, *tmp; - - mk_list_foreach_safe(head, tmp, §ion->entries) { - entry = mk_list_entry(head, struct mk_rconf_entry, _head); - mk_list_del(&entry->_head); - - /* Free memory assigned */ - mk_mem_free(entry->key); - mk_mem_free(entry->val); - mk_mem_free(entry); - } -} - -/* Register a new section into the configuration struct */ -struct mk_rconf_section *mk_rconf_section_add(struct mk_rconf *conf, - char *name) -{ - struct mk_rconf_section *new; - - /* Alloc section node */ - new = mk_mem_alloc(sizeof(struct mk_rconf_section)); - if (!new) { - return NULL; - } - new->name = mk_string_dup(name); - mk_list_init(&new->entries); - mk_list_add(&new->_head, &conf->sections); - - return new; -} - -/* Return the value of a key of a specific section */ -void *mk_rconf_section_get_key(struct mk_rconf_section *section, - char *key, int mode) -{ - int on, off; - struct mk_rconf_entry *entry; - struct mk_list *head; - - mk_list_foreach(head, §ion->entries) { - entry = mk_list_entry(head, struct mk_rconf_entry, _head); - - if (strcasecmp(entry->key, key) == 0) { - switch (mode) { - case MK_RCONF_STR: - return (void *) mk_string_dup(entry->val); - case MK_RCONF_NUM: - return (void *) strtol(entry->val, (char **) NULL, 10); - case MK_RCONF_BOOL: - on = strcasecmp(entry->val, MK_RCONF_ON); - off = strcasecmp(entry->val, MK_RCONF_OFF); - - if (on != 0 && off != 0) { - return (void *) -1; - } - else if (on >= 0) { - return (void *) MK_TRUE; - } - else { - return (void *) MK_FALSE; - } - case MK_RCONF_LIST: - return (void *)mk_string_split_line(entry->val); - } - } - } - return NULL; -} |