#include #include #include #include #include #include #include #include #include "log_pty.h" #include "log_types.h" #include "log_common.h" #include "ret_errno.h" #include "sev_sched.h" #define MAX_EVENT_NUMBER 64 #define LOG_DEV_PTY_DIR LOG_DEV_DIR"pts/" #define LOG_CONF_PTY_FILE_NAME "log-pty.conf" #define LOG_CONF_KEY_PTY_LEVEL_STR "pty.level" #define LOG_CONF_KEY_PTY_MODULE_STR "pty.module" pthread_mutex_t g_mutex_pty; volatile int g_epoll_fd = -1; int g_watch_fd = -1; int g_inotify_fd = -1; pthread_t g_monitor_thread; static int write_pty_content(FILE *fp, const u8 level, const char *filter_mod, void *arg); static ret_code write_pty_conf() { char value_str[128]=""; uint level = LOG_INFO; char *module = NULL; ret_code ret = RET_OK; memset(value_str, 0, sizeof(value_str)); sprintf(value_str, "%s%s", LOG_CONF_PATH, LOG_CONF_PTY_FILE_NAME); if (access(value_str, 0) == 0) { /* 获取配置 */ memset(value_str, 0, sizeof(value_str)); if (get_log_file_conf(LOG_CONF_KEY_PTY_LEVEL_STR, value_str, sizeof(value_str)) == 0) { level = atoi(value_str); } memset(value_str, 0, sizeof(value_str)); if (get_log_file_conf(LOG_CONF_KEY_PTY_MODULE_STR, value_str, sizeof(value_str)) == 0) { module = value_str; } pthread_mutex_lock(&g_mutex_pty); int ret_conf = log_conf((u8)level, LOG_CONF_PATH, LOG_CONF_PTY_FILE_NAME, module, write_pty_content, NULL); pthread_mutex_unlock(&g_mutex_pty); if (ret_conf != 0) { ULOG_ERR(g_log, "Log's pty configure which is written is failure"); ret = RET_ERR; } else { ULOG_DEBUG(g_log, "Pty config level(%u) and module(%s) successed.", level, module!=NULL?module:"NULL"); } } return ret; } static void *pty_monitor_thread(void *arg) { struct epoll_event events[MAX_EVENT_NUMBER]; ret_code ret_c; char buf[MAX_LINE_SZ]; ssize_t len; char *ptr; struct inotify_event *inotify_ev; ULOG_DEBUG(g_log, "Monitor pty is begining"); while (1) { //ULOG_DEBUG(g_log, "Epoll is waiting"); int ret = epoll_wait(g_epoll_fd, events, MAX_EVENT_NUMBER, 1000); if (ret == -1) { if (errno == EBADF) { ULOG_DEBUG(g_log, "Epoll has been shut or invalid"); } else { ULOG_ERR(g_log, "Waiting epoll is failure:%s, code:%d", strerror(errno), errno); } break; } if (ret == 0) { // 超时 continue; } for (int i = 0; i < MAX_EVENT_NUMBER; i++) { ULOG_DEBUG(g_log, "Epoll event value is 0x%x", events[i].events); if ((events[i].events & EPOLLIN) != EPOLLIN) { continue; } len = read(g_inotify_fd, buf, sizeof(buf)); if ((len == -1) && (errno != EAGAIN)) { ULOG_ERR(g_log, "Reading inotify is failure:%s", strerror(errno)); break; } if (len <= 0) { continue; } for (ptr = buf; ptr < buf + len; ptr += sizeof(struct inotify_event) + inotify_ev->len) { inotify_ev = (struct inotify_event *) ptr; if (((inotify_ev->mask & IN_CREATE) != IN_CREATE) && ((inotify_ev->mask & IN_DELETE) != IN_DELETE)) { ULOG_DEBUG(g_log, "Current ev mask:%u, anything willn't be done", inotify_ev->mask); continue; } // sleep一下,防止权限修改不成功 sleep(1); ULOG_DEBUG(g_log, "Current ev mask:%u, wo will write configure and restart rsyslog", inotify_ev->mask); ret_c = write_pty_conf(); if (ret_c != RET_OK) { ULOG_ERR(g_log, "Pty monitor write pty configure is failure(code:%d)", ret_c); continue; } if (log_sev_restart() != 0) { ULOG_ERR(g_log, "Pty monitor restart rsyslog 2 is failure"); } } } } ULOG_ERR(g_log, "Monitor pty is end"); } static void close_monitor() { if (g_epoll_fd != -1) { close(g_epoll_fd); g_epoll_fd = -1; } if (g_watch_fd != -1) { inotify_rm_watch(g_inotify_fd, g_watch_fd); close(g_watch_fd); g_watch_fd = -1; } if (g_inotify_fd != -1) { close(g_inotify_fd); g_inotify_fd = -1; } } static ret_code start_dev_pty_monitor() { if (g_inotify_fd != -1) { ULOG_ERR(g_log, "Monitoring pty has started up, value:%d", g_inotify_fd); return RET_OK; } g_inotify_fd = inotify_init(); if (g_inotify_fd == -1) { ULOG_ERR(g_log, "Initiating file notify is failure:%s", strerror(errno)); return RET_ERR; } g_watch_fd = inotify_add_watch(g_inotify_fd, LOG_DEV_PTY_DIR, IN_CREATE | IN_DELETE); if(g_watch_fd == -1) { ULOG_ERR(g_log, "Intify add watch is failure:%s", strerror(errno)); goto FAIL; } g_epoll_fd = epoll_create1(0); if (g_epoll_fd == -1) { ULOG_ERR(g_log, "Creating epoll is failure:%s", strerror(errno)); goto FAIL; } struct epoll_event ev; ev.events = EPOLLIN; ev.data.fd = g_inotify_fd; if (epoll_ctl(g_epoll_fd, EPOLL_CTL_ADD, g_inotify_fd, &ev) == -1) { ULOG_ERR(g_log, "Setting epoll is failure:%s", strerror(errno)); goto FAIL; } int ret = pthread_create(&g_monitor_thread, NULL, pty_monitor_thread, NULL); if (ret != 0) { ULOG_ERR(g_log, "Creating monitor thread is failure:%d", ret); goto FAIL; } return RET_OK; FAIL: close_monitor(); return RET_ERR; } static void stop_dev_pty_monitor() { ULOG_DEBUG(g_log, "Stopping dev pty monitor"); close_monitor(); pthread_join(g_monitor_thread, NULL); } static int write_pty_content(FILE *fp, const u8 level, const char *filter_mod, void *arg) { DIR *dir; if ((dir = opendir(LOG_DEV_PTY_DIR)) == NULL) { ULOG_ERR(g_log, "Open dir:[%s] is failure:%d", LOG_DEV_PTY_DIR, strerror(errno)); return -1; } struct dirent *ptr; char path[MAX_PATH_SZ]; while ((ptr = readdir(dir)) != NULL) { if ((strcmp(ptr->d_name, ".") == 0) || (strcmp(ptr->d_name, "..") == 0) || (ptr->d_type == DT_DIR)) { ///current dir OR parrent dir ULOG_DEBUG(g_log,"The file:[%s] or directory jump over\n", ptr->d_name); continue; } if (strstr(ptr->d_name, "ptmx") != NULL) { ULOG_DEBUG(g_log,"The file:[%s] isn't redirected\n", ptr->d_name); continue; } ULOG_DEBUG(g_log, "pty name:%s", ptr->d_name); if (snprintf(path, sizeof(path), "%s%s", LOG_DEV_PTY_DIR, ptr->d_name) < 0) { ULOG_ERR(g_log, "Setting pty of log[%s] is failure", ptr->d_name); closedir(dir); return -1; } if (write_conf_content_authorizing(fp, level, filter_mod, path) != 0) { ULOG_ERR(g_log, "Writing pty[module:%s] of log is failure", filter_mod); closedir(dir); return -1; } } closedir(dir); if (start_dev_pty_monitor() != RET_OK) { ULOG_ERR(g_log, "Starting pty monitor is failure"); return -1; } return 0; } static int config_log_pty(const log_pty_t *conf) { int ret = -1; char value_str[128]=""; switch (conf->on) { case LOG_OFF: stop_dev_pty_monitor(); ret = log_off_with_file(LOG_CONF_PATH, LOG_CONF_PTY_FILE_NAME); /* off时,将log-sched配置文件中pty日志级别调成默认值info,即level=6 */ if (0 == ret) { memset(value_str, 0, sizeof(value_str)); snprintf(value_str, sizeof(value_str), "%u", LOG_INFO); if (write_log_file_conf(LOG_CONF_KEY_PTY_LEVEL_STR, value_str) != 0) { ULOG_ERR(g_log, "Pty-level which is written is failure"); return -1; } } break; case LOG_ON: pthread_mutex_lock(&g_mutex_pty); ret = log_conf(conf->level, LOG_CONF_PATH, LOG_CONF_PTY_FILE_NAME, conf->module, write_pty_content, NULL); pthread_mutex_unlock(&g_mutex_pty); if (ret != 0) { ULOG_ERR(g_log, "Log's pty configure which is written is failure"); } else { ret = 0; } /* 写pty日志级别与模块名称到log-sched配置文件 */ if (0 == ret) { memset(value_str, 0, sizeof(value_str)); sprintf(value_str, "%u", conf->level); if (write_log_file_conf(LOG_CONF_KEY_PTY_LEVEL_STR, value_str) != 0) { ULOG_ERR(g_log, "Pty-level which is written is failure"); return -1; } memset(value_str, 0, sizeof(value_str)); sprintf(value_str, "%s", conf->module); if (write_log_file_conf(LOG_CONF_KEY_PTY_MODULE_STR, value_str) != 0) { ULOG_ERR(g_log, "Pty-module which is written is failure"); return -1; } } break; default: ULOG_WARNING(g_log, "Unknown on value:%u", conf->on); break; } return ret; } static int __rpc_conf_log_pty(pointer input, const void *arg, char *str_err, int str_len) { if (config_log_pty((const log_pty_t *)input) != 0) { strncpy(str_err, "Configuring pty of log is faiure", str_len); return -1; } return 0; } void rpc_conf_log_pty(rpc_conn *conn, pointer input, int input_len, pointer data) { rpc_conf_proc(conn, input, input_len, sizeof(log_pty_t), __rpc_conf_log_pty, NULL); } ret_code pty_initial() { int thread_ret = pthread_mutex_init(&g_mutex_pty, NULL); if (thread_ret != 0) { ULOG_DEBUG(g_log, "Initiating pthread lock is failure(cdoe:%d)", thread_ret); } ret_code ret = write_pty_conf(); if (ret != RET_OK) { ULOG_DEBUG(g_log, "Initiating pty is failure(cdoe:%d)", ret); } else { ULOG_INFO(g_log, "Initiating pty is success"); } return ret; } ret_code pty_exit() { ret_code ret = RET_OK; int thread_ret = pthread_mutex_destroy(&g_mutex_pty); if (0 != thread_ret) { ret = RET_ERR; ULOG_DEBUG(g_log, "Destroying pthread lock is failure(cdoe:%d)", thread_ret); } stop_dev_pty_monitor(); return ret; }