379 lines
12 KiB
C
Executable File
379 lines
12 KiB
C
Executable File
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <dirent.h>
|
|
#include <errno.h>
|
|
#include <syslog.h>
|
|
|
|
|
|
#include "log_remote.h"
|
|
#include "log_common.h"
|
|
|
|
#define LOG_CONF_REMOTE_FILE_NAME "log-remote.conf"
|
|
|
|
#define RESET_SEEK(fp) fseek(fp, 0, SEEK_SET)
|
|
|
|
#define LOG_CONF_KEY_REMOTE_LEVEL "remote.level="
|
|
|
|
typedef enum {
|
|
LOG_REMOTE_OP_ADD = 0,
|
|
LOG_REMOTE_OP_DEL,
|
|
LOG_REMOTE_MAX
|
|
} log_op_t;
|
|
|
|
|
|
typedef struct _rfc_key_fmt {
|
|
log_rfc_t rfc;
|
|
char fmt[20];
|
|
} rfc_key_fmt;
|
|
|
|
static rfc_key_fmt rfc_tbl[] = {
|
|
{LOG_RFC_3164, "RFC3164fmt"},
|
|
{LOG_RFC_5424, "RFC5424fmt"}
|
|
};
|
|
|
|
typedef int (*op_func)(const log_remote_host_t *conf);
|
|
|
|
static int add_remote_host(const log_remote_host_t *conf);
|
|
static int del_remote_host(const log_remote_host_t *conf);
|
|
|
|
static op_func remote_funcs[] = {
|
|
add_remote_host,
|
|
del_remote_host
|
|
};
|
|
|
|
static int match_remote_config(const char *line, const void *src)
|
|
{
|
|
char text_level[MAX_LINE_SZ], old_redirect[MAX_LINE_SZ];
|
|
int n;
|
|
|
|
ULOG_DEBUG(g_log, "The line:%s will be matched", line);
|
|
n = sscanf(line, "%s"REDIRECT_SEPERATE"%s", text_level, old_redirect);
|
|
if (errno != 0) {
|
|
// 错误发生
|
|
ULOG_ERR(g_log, "Parsing remote line is failure:%s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
if (n == 2) {
|
|
// 匹配到
|
|
// 是否相同配置判读
|
|
ULOG_DEBUG(g_log, "%s will compare with %s", old_redirect, (const char *)src);
|
|
if (strcmp(old_redirect, src) == 0) {
|
|
return 0;
|
|
}
|
|
} else {
|
|
// 未能识别行
|
|
ULOG_DEBUG(g_log, "The line:%s can't be parsed", line);
|
|
}
|
|
|
|
return -1;
|
|
}
|
|
|
|
static int remote_conf_content(FILE *fp, const u8 level, const char *filter_mod,
|
|
int (*match_cb)(const char *line, const void *src),
|
|
int (*final_cb)(FILE *fp, const u8 level, const char *filter_mod, void *arg),
|
|
void *arg)
|
|
{
|
|
int ret = -1;
|
|
FILE *bak_fp = NULL;
|
|
char path[MAX_PATH_SZ];
|
|
snprintf(path, sizeof(path), BAK_FILE, LOG_CONF_REMOTE_FILE_NAME);
|
|
bak_fp = fopen(path, "r");
|
|
if (bak_fp == NULL) {
|
|
if (errno == ENOENT) {
|
|
goto FINAL_PHASE;
|
|
} else {
|
|
ULOG_ERR(g_log, "Opening remote backup file:%s is failure:%s", path, strerror(errno));
|
|
return -1;
|
|
}
|
|
}
|
|
|
|
char *line = NULL;
|
|
ssize_t n, n1;
|
|
char text_level[MAX_LINE_SZ], old_redirect[MAX_LINE_SZ];
|
|
while ((n = getline(&line, &n, bak_fp)) != -1) {
|
|
int match = match_cb(line, arg);
|
|
if (match == -1) {
|
|
ULOG_ERR(g_log, "Configure which is matched is failure");
|
|
} else if (match == 0) {
|
|
ULOG_DEBUG(g_log, "Be matched");
|
|
continue;
|
|
}
|
|
|
|
ULOG_DEBUG(g_log, "Recover old line:%s to file:%s", line, path);
|
|
n1 = fwrite(line, 1, n, fp);
|
|
if (n != n1) {
|
|
ULOG_ERR(g_log, "Recovering old line:%s to file is failure:%s", line, strerror(errno));
|
|
goto END;
|
|
}
|
|
}
|
|
|
|
FINAL_PHASE:
|
|
if (final_cb != NULL) {
|
|
if (final_cb(fp, level, filter_mod, arg) != 0) {
|
|
ULOG_ERR(g_log, "Executing final callback is failure");
|
|
goto END;
|
|
}
|
|
}
|
|
|
|
ret = 0;
|
|
END:
|
|
if (line != NULL) {
|
|
free(line);
|
|
}
|
|
if (bak_fp != NULL) {
|
|
fclose(bak_fp);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int remote_conf_level_content(FILE *fp, const u8 level)
|
|
{
|
|
int ret = -1;
|
|
FILE *bak_fp = NULL;
|
|
char path[MAX_PATH_SZ];
|
|
snprintf(path, sizeof(path), BAK_FILE, LOG_CONF_REMOTE_FILE_NAME);
|
|
bak_fp = fopen(path, "r");
|
|
if (bak_fp == NULL) {
|
|
ULOG_ERR(g_log, "Opening remote backup file:%s is failure:%s", path, strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
char *line = NULL;
|
|
ssize_t n, n1;
|
|
ssize_t n3;
|
|
char text_level[MAX_LINE_SZ], old_redirect[MAX_LINE_SZ];
|
|
char rewrite_line[MAX_LINE_SZ];
|
|
while ((n1 = getline(&line, &n, bak_fp)) != -1) {
|
|
n3 = sscanf(line, "%s"REDIRECT_SEPERATE"%s", text_level, old_redirect);
|
|
if (errno != 0) {
|
|
// 错误发生
|
|
ULOG_ERR(g_log, "Parsing remote line is failure:%s", strerror(errno));
|
|
goto END;
|
|
}
|
|
if (n3 == 2) {
|
|
// 匹配到
|
|
// 改变该行日志级别
|
|
memset(rewrite_line, 0, sizeof(rewrite_line));
|
|
if (log_level_to_str(level, rewrite_line, sizeof(rewrite_line)) != 0) {
|
|
ULOG_ERR(g_log, "Log level converts str is failure");
|
|
goto END;
|
|
}
|
|
strcat(rewrite_line, REDIRECT_SEPERATE);
|
|
strcat(rewrite_line, old_redirect);
|
|
strcat(rewrite_line, "\n");
|
|
n3 = strlen(rewrite_line);
|
|
} else {
|
|
// 未能识别行
|
|
ULOG_DEBUG(g_log, "The line:%s can't be parsed", line);
|
|
}
|
|
|
|
ULOG_DEBUG(g_log, "Recover old line:%s to file:%s", rewrite_line, path);
|
|
n1 = fwrite(rewrite_line, 1, n3, fp);
|
|
if (n3 != n1) {
|
|
ULOG_ERR(g_log, "Recovering old line:%s to file is failure:%s", rewrite_line, strerror(errno));
|
|
goto END;
|
|
}
|
|
}
|
|
|
|
ret = 0;
|
|
END:
|
|
if (line != NULL) {
|
|
free(line);
|
|
}
|
|
if (bak_fp != NULL) {
|
|
fclose(bak_fp);
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int add_remote_conf_content(FILE *fp, const u8 level, const char *filter_mod, void *arg)
|
|
{
|
|
return remote_conf_content(fp, level, filter_mod, match_remote_config, write_conf_content, arg);
|
|
}
|
|
|
|
static int del_remote_conf_content(FILE *fp, const u8 level, const char *filter_mod, void *arg)
|
|
{
|
|
return remote_conf_content(fp, level, filter_mod, match_remote_config, NULL, arg);
|
|
}
|
|
|
|
static int modify_remote_conf_log_level(FILE *fp, const u8 level, const char *filter_mod, void *arg)
|
|
{
|
|
return remote_conf_level_content(fp, level);
|
|
}
|
|
|
|
static int get_log_level()
|
|
{
|
|
if (RESET_SEEK(g_conf_fp) == -1) {
|
|
ULOG_ERR(g_log, "[get log level]Seeknig config to begin is faiure:%s", strerror(errno));
|
|
return -1;
|
|
}
|
|
|
|
ssize_t n, n1, n2;
|
|
char *line;
|
|
u8 value;
|
|
while ((n1 = getline(&line, &n, g_conf_fp)) != -1) {
|
|
n2 = sscanf(line, LOG_CONF_KEY_REMOTE_LEVEL"%u", &value);
|
|
if (errno != 0) {
|
|
// 错误发生
|
|
ULOG_ERR(g_log, "Parsing level from configure is failure:%s", strerror(errno));
|
|
return -1;
|
|
}
|
|
if (n2 == 1) {
|
|
return value;
|
|
} else {
|
|
ULOG_DEBUG(g_log, "Unknown level row:%s", line);
|
|
}
|
|
}
|
|
|
|
return LOG_INFO;
|
|
}
|
|
|
|
static int add_remote_host(const log_remote_host_t *conf)
|
|
{
|
|
ULOG_INFO(g_log, "Adding remote log server[%s:%u], rfc is %s", conf->host, conf->port, rfc_tbl[conf->rfc].fmt);
|
|
char prefix[1] = "";
|
|
if (conf->rfc == LOG_RFC_5424) {
|
|
strcat(prefix, "@");
|
|
};
|
|
|
|
char redirect[MAX_LINE_SZ];
|
|
if (snprintf(redirect, sizeof(redirect), "%s@%s:%u:%s",
|
|
prefix, conf->host, conf->port, rfc_tbl[conf->rfc].fmt) < 0) {
|
|
ULOG_ERR(g_log, "Setting remote redirect[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt);
|
|
return -1;
|
|
}
|
|
|
|
int level = get_log_level();
|
|
if (level == -1) {
|
|
ULOG_ERR(g_log, "Getting log level is failure");
|
|
return -1;
|
|
}
|
|
if (log_conf(level, LOG_CONF_PATH, LOG_CONF_REMOTE_FILE_NAME, NULL,
|
|
add_remote_conf_content, (void *)redirect) != 0) {
|
|
ULOG_ERR(g_log, "Adding remote server[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static int del_remote_host(const log_remote_host_t *conf)
|
|
{
|
|
int ret;
|
|
char prefix[1] = "";
|
|
|
|
ULOG_INFO(g_log, "Deleting remote log server[%s:%u], rfc is %s", conf->host, conf->port, rfc_tbl[conf->rfc].fmt);
|
|
if (conf->rfc == LOG_RFC_5424) {
|
|
strcat(prefix, "@");
|
|
};
|
|
char redirect[MAX_LINE_SZ];
|
|
if (snprintf(redirect, sizeof(redirect), "%s@%s:%u:%s",
|
|
prefix, conf->host, conf->port, rfc_tbl[conf->rfc].fmt) < 0) {
|
|
ULOG_ERR(g_log, "Setting remote redirect[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt);
|
|
return -1;
|
|
}
|
|
|
|
if (log_conf(7, LOG_CONF_PATH, LOG_CONF_REMOTE_FILE_NAME, NULL,
|
|
del_remote_conf_content, (void *)redirect) != 0) {
|
|
ULOG_ERR(g_log, "Adding remote server[%s:%u:%s] is faulure", conf->host, conf->port, rfc_tbl[conf->rfc].fmt);
|
|
return -1;
|
|
}
|
|
|
|
return ret;
|
|
}
|
|
|
|
static int config_log_remote_host(const log_op_t op, const log_remote_host_t *conf)
|
|
{
|
|
if ((sizeof(rfc_tbl) / sizeof(rfc_key_fmt)) < conf->rfc) {
|
|
ULOG_WARNING(g_log, "Unknown rfc format key:%u", conf->rfc);
|
|
return -1;
|
|
}
|
|
if (op >= LOG_REMOTE_MAX) {
|
|
ULOG_WARNING(g_log, "Unknown operation type:%u", op);
|
|
return -1;
|
|
}
|
|
return remote_funcs[op](conf);
|
|
}
|
|
|
|
static int config_log_remote_level(const log_remote_level_t *level)
|
|
{
|
|
if (truncate(g_conf_file, 0) == -1) {
|
|
ULOG_ERR(g_log, "Truncate configure:%s is faiure:%s", g_conf_file, strerror(errno));
|
|
return -1;
|
|
}
|
|
/* 定位到开始位置 */
|
|
if (RESET_SEEK(g_conf_fp) == -1) {
|
|
ULOG_ERR(g_log, "Seeknig config to begin is faiure:%s", strerror(errno));
|
|
return -1;
|
|
}
|
|
char fmt[MAX_LINE_SZ];
|
|
snprintf(fmt, sizeof(fmt), LOG_CONF_KEY_REMOTE_LEVEL"%u", level->level);
|
|
ULOG_DEBUG(g_log, "Configure content is %s", fmt);
|
|
int len = strlen(fmt);
|
|
int n = fwrite(fmt, 1, len, g_conf_fp);
|
|
if (len != n) {
|
|
ULOG_ERR(g_log, "Writing remote level is failure:%s", strerror(errno));
|
|
return -1;
|
|
}
|
|
fflush(g_conf_fp);
|
|
|
|
if (log_conf(level->level, LOG_CONF_PATH, LOG_CONF_REMOTE_FILE_NAME, NULL,
|
|
modify_remote_conf_log_level, NULL) != 0) {
|
|
ULOG_ERR(g_log, "Modifing log level:%u of remote server [%s:%u:%s] is faulure", level->level);
|
|
return -1;
|
|
}
|
|
|
|
return 0;
|
|
}
|
|
|
|
static void rpc_conf_log_remote(const log_op_t op, rpc_conn *conn, pointer input, int input_len, pointer data)
|
|
{
|
|
if (input == NULL) {
|
|
ULOG_WARNING(g_log, "Remote log configure can't null");
|
|
return;
|
|
}
|
|
|
|
u32 need_len = sizeof(log_remote_host_t);
|
|
if (input_len < need_len) {
|
|
ULOG_WARNING(g_log,
|
|
"The input paramter of rpc log remote host is needed length of %u, but the actual length is %u",
|
|
need_len, input_len);
|
|
return;
|
|
}
|
|
|
|
config_log_remote_host(op, (const log_remote_host_t *)input);
|
|
}
|
|
|
|
void rpc_conf_log_add_remote(rpc_conn *conn, pointer input, int input_len, pointer data)
|
|
{
|
|
rpc_conf_log_remote(LOG_REMOTE_OP_ADD, conn, input, input_len, data);
|
|
}
|
|
|
|
void rpc_conf_log_del_remote(rpc_conn *conn, pointer input, int input_len, pointer data)
|
|
{
|
|
rpc_conf_log_remote(LOG_REMOTE_OP_DEL, conn, input, input_len, data);
|
|
}
|
|
|
|
|
|
void rpc_conf_log_remote_level(rpc_conn *conn, pointer input, int input_len, pointer data)
|
|
{
|
|
if (input == NULL) {
|
|
ULOG_WARNING(g_log, "Remote log level can't null");
|
|
return;
|
|
}
|
|
|
|
u32 need_len = sizeof(log_remote_level_t);
|
|
if (input_len < need_len) {
|
|
ULOG_WARNING(g_log,
|
|
"The input paramter of rpc log remote level is needed length of %u, but the actual length is %u",
|
|
need_len, input_len);
|
|
return;
|
|
}
|
|
|
|
config_log_remote_level((const log_remote_level_t *)input);
|
|
}
|
|
|