--- lbbs/src/bbs_main.c 2025/05/15 05:14:57 1.45 +++ lbbs/src/bbs_main.c 2025/11/02 08:13:50 1.96 @@ -14,170 +14,112 @@ * * ***************************************************************************/ -#include "bbs_main.h" +#include "article_favor.h" +#include "article_view_log.h" #include "bbs.h" -#include "login.h" -#include "user_priv.h" +#include "bbs_cmd.h" +#include "bbs_main.h" #include "common.h" #include "database.h" -#include "log.h" +#include "editor.h" #include "io.h" -#include "screen.h" +#include "log.h" +#include "login.h" #include "menu.h" -#include "bbs_cmd.h" -#include -#include +#include "screen.h" +#include "section_list.h" +#include "section_list_display.h" +#include "trie_dict.h" +#include "user_list.h" +#include "user_priv.h" +#include +#include +#include #include +#include +#include int bbs_info() { - prints("欢迎光临 \033[1;33m%s \033[32m[%s] \033[37m( %s )\r\n", - BBS_name, BBS_server, app_version); + prints("娆㈣繋鍏変复 \033[1;33m%s \033[32m[%s] \033[37m( %s )\033[m\r\n", + BBS_name, BBS_server, APP_INFO); return iflush(); } -int bbs_welcome(MYSQL *db) +int bbs_welcome(void) { - char sql[SQL_BUFFER_LEN]; - - u_int32_t u_online = 0; - u_int32_t u_anonymous = 0; - u_int32_t u_total = 0; - u_int32_t max_u_online = 0; - u_int32_t u_login_count = 0; - - MYSQL_RES *rs; - MYSQL_ROW row; - - snprintf(sql, sizeof(sql), - "SELECT COUNT(*) AS cc FROM " - "(SELECT DISTINCT SID FROM user_online " - "WHERE last_tm >= SUBDATE(NOW(), INTERVAL %d SECOND)) AS t1", - BBS_user_off_line); - if (mysql_query(db, sql) != 0) - { - log_error("Query user_online failed\n"); - return -2; - } - if ((rs = mysql_store_result(db)) == NULL) - { - log_error("Get user_online data failed\n"); - return -2; - } - if ((row = mysql_fetch_row(rs))) - { - u_online = (u_int32_t)atoi(row[0]); - } - mysql_free_result(rs); + int u_online = 0; + int u_anonymous = 0; + int u_total = 0; + int u_login_count = 0; - snprintf(sql, sizeof(sql), - "SELECT COUNT(*) AS cc FROM " - "(SELECT DISTINCT SID FROM user_online " - "WHERE UID = 0 AND last_tm >= SUBDATE(NOW(), INTERVAL %d SECOND)) AS t1", - BBS_user_off_line); - if (mysql_query(db, sql) != 0) + if (get_user_online_list_count(&u_online, &u_anonymous) < 0) { - log_error("Query user_online failed\n"); - return -2; - } - if ((rs = mysql_store_result(db)) == NULL) - { - log_error("Get user_online data failed\n"); - return -2; - } - if ((row = mysql_fetch_row(rs))) - { - u_anonymous = (u_int32_t)atoi(row[0]); - } - mysql_free_result(rs); - - snprintf(sql, sizeof(sql), "SELECT COUNT(UID) AS cc FROM user_list WHERE enable"); - if (mysql_query(db, sql) != 0) - { - log_error("Query user_list failed\n"); - return -2; - } - if ((rs = mysql_store_result(db)) == NULL) - { - log_error("Get user_list data failed\n"); - return -2; + log_error("get_user_online_list_count() error\n"); + u_online = 0; } - if ((row = mysql_fetch_row(rs))) + u_online += u_anonymous; + u_online++; // current user + if (BBS_priv.uid == 0) { - u_total = (u_int32_t)atoi(row[0]); + u_anonymous++; } - mysql_free_result(rs); - snprintf(sql, sizeof(sql), "SELECT ID FROM user_login_log ORDER BY ID LIMIT 1"); - if (mysql_query(db, sql) != 0) + if (get_user_list_count(&u_total) < 0) { - log_error("Query user_login_log failed\n"); - return -2; - } - if ((rs = mysql_store_result(db)) == NULL) - { - log_error("Get user_login_log data failed\n"); - return -2; - } - if ((row = mysql_fetch_row(rs))) - { - u_login_count = (u_int32_t)atoi(row[0]); + log_error("get_user_list_count() error\n"); + u_total = 0; } - mysql_free_result(rs); - // Log max user_online - FILE *fin, *fout; - if ((fin = fopen(VAR_MAX_USER_ONLINE, "r")) != NULL) - { - fscanf(fin, "%d", &max_u_online); - fclose(fin); - } - if (u_online > max_u_online) + if (get_user_login_count(&u_login_count) < 0) { - max_u_online = u_online; - if ((fout = fopen(VAR_MAX_USER_ONLINE, "w")) == NULL) - { - log_error("Open max_user_online.dat failed\n"); - return -3; - } - fprintf(fout, "%d\n", max_u_online); - fclose(fout); + log_error("get_user_login_count() error\n"); + u_login_count = 0; } - // Count current user before login - u_online++; - u_anonymous++; - // Display logo - display_file(DATA_WELCOME); + display_file(DATA_WELCOME, 2); // Display welcome message - prints("\033[1;35m欢迎光临\033[33m 【 %s 】 \033[35mBBS\r\n" - "\033[32m目前上站人数 [\033[36m%d/%d\033[32m] " - "匿名游客[\033[36m%d\033[32m] " - "注册用户数[\033[36m%d/%d\033[32m]\r\n" - "从 [\033[36m%s\033[32m] 起,最高人数记录:" - "[\033[36m%d\033[32m],累计访问人次:[\033[36m%d\033[32m]\r\n", + prints("\r\033[1;35m娆㈣繋鍏変复\033[33m 銆 %s 銆 \033[35mBBS\r\n" + "\033[32m鐩墠涓婄珯浜烘暟 [\033[36m%d/%d\033[32m] " + "鍖垮悕娓稿[\033[36m%d\033[32m] " + "娉ㄥ唽鐢ㄦ埛鏁癧\033[36m%d/%d\033[32m]\r\n" + "浠 [\033[36m%s\033[32m] 璧凤紝绱璁块棶浜烘锛歔\033[36m%d\033[32m]\033[m\r\n", BBS_name, u_online, BBS_max_client, u_anonymous, u_total, - BBS_max_user, BBS_start_dt, max_u_online, u_login_count); + BBS_max_user_count, BBS_start_dt, u_login_count); + + iflush(); return 0; } -int bbs_logout(MYSQL *db) +int bbs_logout(void) { - if (user_online_del(db) < 0) + MYSQL *db; + + db = db_open(); + if (db == NULL) { return -1; } - if (display_file_ex(DATA_GOODBYE, 1, 0) < 0) + if (user_online_exp(db) < 0) { return -2; } - log_std("User logout\n"); + if (user_online_del(db) < 0) + { + return -3; + } + + mysql_close(db); + + display_file(DATA_GOODBYE, 1); + + log_common("User [%s] logout, idle for %ld seconds since last input\n", BBS_username, time(NULL) - BBS_last_access_tm); return 0; } @@ -187,57 +129,110 @@ int bbs_center() int ch; time_t t_last_action; - BBS_last_access_tm = t_last_action = time(0); + BBS_last_access_tm = t_last_action = time(NULL); clearscr(); - show_top(""); + show_top("", BBS_name, ""); show_active_board(); show_bottom(""); - display_menu(p_bbs_menu); + display_menu(&bbs_menu); + iflush(); while (!SYS_server_exit) { ch = igetch(100); - if (time(0) - t_last_action >= 10) + if (ch != KEY_NULL && ch != KEY_TIMEOUT) { - t_last_action = time(0); + BBS_last_access_tm = time(NULL); + } + + if (bbs_menu.choose_step == 0 && time(NULL) - t_last_action >= 10) + { + t_last_action = time(NULL); + show_active_board(); show_bottom(""); + display_menu_cursor(&bbs_menu, 1); + iflush(); + } + + if (user_online_update("MENU") < 0) + { + log_error("user_online_update(MENU) error\n"); } switch (ch) { case KEY_NULL: // broken pipe + log_error("KEY_NULL\n"); return 0; case KEY_TIMEOUT: - if (time(0) - BBS_last_access_tm >= MAX_DELAY_TIME) + if (time(NULL) - BBS_last_access_tm >= MAX_DELAY_TIME) { + log_error("User input timeout\n"); return 0; } continue; case CR: - igetch_reset(); default: - switch (menu_control(p_bbs_menu, ch)) + switch (menu_control(&bbs_menu, ch)) { case EXITBBS: + case EXITMENU: return 0; case REDRAW: + t_last_action = time(NULL); clearscr(); - show_top(""); + show_top("", BBS_name, ""); show_active_board(); show_bottom(""); - display_menu(p_bbs_menu); + display_menu(&bbs_menu); break; case NOREDRAW: case UNKNOWN_CMD: default: break; } + iflush(); + } + } + + return 0; +} + +int bbs_charset_select() +{ + char msg[LINE_BUFFER_LEN]; + int ch; + + snprintf(msg, sizeof(msg), + "\rChoose character set in 5 seconds [UTF-8, GBK]: [U/g]"); + + while (!SYS_server_exit) + { + ch = press_any_key_ex(msg, 5); + switch (ch) + { + case KEY_NULL: + return -1; + case KEY_TIMEOUT: + case CR: + case 'u': + case 'U': + return 0; + case 'g': + case 'G': + if (io_conv_init("GBK") < 0) + { + log_error("io_conv_init(%s) error\n", "GBK"); + return -1; + } + return 0; + default: + continue; } - BBS_last_access_tm = time(0); } return 0; @@ -245,51 +240,162 @@ int bbs_center() int bbs_main() { - MYSQL *db; + struct sigaction act = {0}; + char msg[LINE_BUFFER_LEN]; + + // Set signal handler + act.sa_handler = SIG_IGN; + if (sigaction(SIGHUP, &act, NULL) == -1) + { + log_error("set signal action of SIGHUP error: %d\n", errno); + goto cleanup; + } + act.sa_handler = SIG_DFL; + if (sigaction(SIGCHLD, &act, NULL) == -1) + { + log_error("set signal action of SIGCHLD error: %d\n", errno); + goto cleanup; + } + + // Set data pools in shared memory readonly + if (set_trie_dict_shm_readonly() < 0) + { + goto cleanup; + } + if (set_article_block_shm_readonly() < 0) + { + goto cleanup; + } + if (set_section_list_shm_readonly() < 0) + { + goto cleanup; + } + if (set_user_list_pool_shm_readonly() < 0) + { + goto cleanup; + } + + // Load menu in shared memory + if (set_menu_shm_readonly(&bbs_menu) < 0) + { + goto cleanup; + } + + // Set default charset + if (io_conv_init(BBS_DEFAULT_CHARSET) < 0) + { + log_error("io_conv_init(%s) error\n", BBS_DEFAULT_CHARSET); + goto cleanup; + } set_input_echo(0); + // Set user charset + bbs_charset_select(); + // System info if (bbs_info() < 0) { - return -1; + goto cleanup; } - db = db_open(); - if (db == NULL) + // Welcome + if (bbs_welcome() < 0) { - prints("无法连接数据库\n"); - return -2; + goto cleanup; } - // Welcome - if (bbs_welcome(db) < 0) + // User login + if (SSH_v2) { - mysql_close(db); - return -3; + snprintf(msg, sizeof(msg), "\033[1m%s 娆㈣繋浣跨敤ssh鏂瑰紡璁块棶 \033[1;33m鎸変换鎰忛敭缁х画...\033[m", BBS_username); + press_any_key_ex(msg, 60); + } + else if (bbs_login() < 0) + { + goto cleanup; } + log_common("User [%s] login\n", BBS_username); - // User login - if (bbs_login(db) < 0) + // Load section aid locations + if (section_aid_locations_load(BBS_priv.uid) < 0) { - mysql_close(db); - return -4; + log_error("article_view_log_load() error\n"); + goto cleanup; + } + + // Load article view log + if (article_view_log_load(BBS_priv.uid, &BBS_article_view_log, 0) < 0) + { + log_error("article_view_log_load() error\n"); + goto cleanup; } - clearscr(); - // BBS Top 10 - if (display_file_ex("./var/bbs_top.txt", 1, 1) < 0) + // Load article favorite + if (article_favor_load(BBS_priv.uid, &BBS_article_favor, 0) < 0) { - prints("无法加载本站十大\n"); + log_error("article_favor_load() error\n"); + goto cleanup; } + // Init editor memory pool + if (editor_memory_pool_init() < 0) + { + log_error("editor_memory_pool_init() error\n"); + goto cleanup; + } + + clearscr(); + + // BBS Top 10 + display_file(VAR_BBS_TOP, 1); + // Main bbs_center(); // Logout - bbs_logout(db); + bbs_logout(); - mysql_close(db); + // Save section aid locations + if (section_aid_locations_save(BBS_priv.uid) < 0) + { + log_error("article_view_log_save() error\n"); + } + + // Save incremental article view log + if (article_view_log_save_inc(&BBS_article_view_log) < 0) + { + log_error("article_view_log_save_inc() error\n"); + } + + // Save incremental article favorite + if (article_favor_save_inc(&BBS_article_favor) < 0) + { + log_error("article_favor_save_inc() error\n"); + } + +cleanup: + // Cleanup iconv + io_conv_cleanup(); + + // Cleanup editor memory pool + editor_memory_pool_cleanup(); + + // Unload article view log + article_view_log_unload(&BBS_article_view_log); + + // Unload article favor + article_favor_unload(&BBS_article_favor); + + // Detach menu in shared memory + detach_menu_shm(&bbs_menu); + detach_menu_shm(&top10_menu); + + // Detach data pools shm + detach_user_list_pool_shm(); + detach_section_list_shm(); + detach_article_block_shm(); + detach_trie_dict_shm(); return 0; }