--- lbbs/src/bbs_main.c 2005/03/21 17:08:21 1.24 +++ lbbs/src/bbs_main.c 2025/11/20 09:02:46 1.111 @@ -1,162 +1,451 @@ -/*************************************************************************** - bbs_main.c - description - ------------------- - begin : Mon Oct 18 2004 - copyright : (C) 2004 by Leaflet - email : leaflet@leafok.com - ***************************************************************************/ - -/*************************************************************************** - * * - * This program is free software; you can redistribute it and/or modify * - * it under the terms of the GNU General Public License as published by * - * the Free Software Foundation; either version 2 of the License, or * - * (at your option) any later version. * - * * - ***************************************************************************/ +/* SPDX-License-Identifier: GPL-3.0-or-later */ +/* + * bbs_main + * - entry and major procedures of user interactive access + * + * Copyright (C) 2004-2025 Leaflet + */ + +#ifdef HAVE_CONFIG_H +#include "config.h" +#endif +#include "article_favor.h" +#include "article_view_log.h" #include "bbs.h" +#include "bbs_cmd.h" +#include "bbs_main.h" +#include "bwf.h" #include "common.h" +#include "database.h" +#include "editor.h" #include "io.h" +#include "log.h" +#include "login.h" #include "menu.h" -#include "bbs_cmd.h" +#include "screen.h" +#include "section_list.h" +#include "section_list_display.h" +#include "str_process.h" +#include "trie_dict.h" +#include "user_list.h" +#include "user_priv.h" +#include +#include +#include +#include +#include #include -#include #include -#include -int -bbs_main () +static void child_proc_sig_usr1_handler(int i) { - char temp[256]; - int ret; + // Restart log + if (log_restart() < 0) + { + log_error("Restart logging failed\n"); + } +} - set_input_echo (0); +int bbs_info() +{ + prints("\r\n欢迎光临 \033[1;33m%s \033[32m[%s] \033[37m(%s)\033[m\r\n", + BBS_name, BBS_server, APP_INFO); - bbs_info (); + return iflush(); +} - //Welcome - bbs_welcome (); +int bbs_welcome(void) +{ + int u_online = 0; + int u_anonymous = 0; + int u_total = 0; + int u_login_count = 0; - //Login - ret = bbs_login (); - if (ret < 0) - return -1; - clearscr (); + if (get_user_online_list_count(&u_online, &u_anonymous) < 0) + { + log_error("get_user_online_list_count() error\n"); + u_online = 0; + } + u_online += u_anonymous; + u_online++; // current user + if (BBS_priv.uid == 0) + { + u_anonymous++; + } - //BBS Top 10 - strcpy (temp, app_home_dir); - strcat (temp, "data/bbs_top.txt"); - display_file_ex (temp, 1, 1); + if (get_user_list_count(&u_total) < 0) + { + log_error("get_user_list_count() error\n"); + u_total = 0; + } - //Main - bbs_center (); + if (get_user_login_count(&u_login_count) < 0) + { + log_error("get_user_login_count() error\n"); + u_login_count = 0; + } + + // Display logo + display_file(DATA_WELCOME, 2); - //Logout - bbs_exit (); + // Display welcome message + 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_count, BBS_start_dt, u_login_count); - return 0; + iflush(); + + return 0; } -int -bbs_info () +int bbs_logout(void) { - prints ("ӭ \033[1;33m%s \033[32m[%s] \033[37m( %s )\r\n", - BBS_name, BBS_server, app_version); + MYSQL *db; - iflush (); + db = db_open(); + if (db == NULL) + { + return -1; + } - return 0; -} + if (user_online_exp(db) < 0) + { + return -2; + } -int -bbs_exit () -{ - char temp[256]; + if (user_online_del(db) < 0) + { + return -3; + } + + mysql_close(db); - strcpy (temp, app_home_dir); - strcat (temp, "data/goodbye.txt"); - display_file_ex (temp, 1, 0); + display_file(DATA_GOODBYE, 1); - sleep (1); + log_common("User [%s] logout, idle for %ld seconds since last input\n", BBS_username, time(NULL) - BBS_last_access_tm); - return 0; + return 0; } -int -bbs_center () +int bbs_center() { - int ch, result; - char action[MAX_MENUACTION_LENGTH]; - time_t t_last_action; - fd_set inputs, testfds; - struct timeval timeout; + int ch; + time_t t_last_action; + + BBS_last_access_tm = t_last_action = time(NULL); + + clearscr(); + + show_top("", BBS_name, ""); + show_active_board(); + show_bottom(""); + display_menu(&bbs_menu); + iflush(); + + while (!SYS_server_exit) + { + ch = igetch(100); - FD_ZERO (&inputs); - FD_SET (0, &inputs); + if (ch != KEY_NULL && ch != KEY_TIMEOUT) + { + BBS_last_access_tm = time(NULL); +#ifdef _DEBUG + log_error("Debug: BBS_last_access_tm is updated\n"); +#endif + } - t_last_action = time (0); + if (bbs_menu.choose_step == 0 && time(NULL) - t_last_action >= 10) + { + t_last_action = time(NULL); - clearscr (); + show_active_board(); + show_bottom(""); + display_menu_cursor(&bbs_menu, 1); + iflush(); + } - show_top (""); - show_active_board (); - show_bottom (""); - display_menu (get_menu (&bbs_menu, "TOPMENU")); + if (user_online_update("MENU") < 0) + { + log_error("user_online_update(MENU) error\n"); + } - while (1) - { - testfds = inputs; - timeout.tv_sec = 0; - timeout.tv_usec = 100000; + switch (ch) + { + case KEY_NULL: // broken pipe + log_error("KEY_NULL\n"); + return 0; + case KEY_TIMEOUT: + if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time) + { + log_error("User input timeout\n"); + return 0; + } + continue; + case CR: + default: + switch (menu_control(&bbs_menu, ch)) + { + case EXITBBS: + case EXITMENU: + return 0; + case REDRAW: + t_last_action = time(NULL); + clearscr(); + show_top("", BBS_name, ""); + show_active_board(); + show_bottom(""); + display_menu(&bbs_menu); + break; + case NOREDRAW: + case UNKNOWN_CMD: + default: + break; + } + iflush(); + } + } + + return 0; +} - result = select (FD_SETSIZE, &testfds, (fd_set *) NULL, - (fd_set *) NULL, &timeout); +int bbs_charset_select() +{ + char msg[LINE_BUFFER_LEN]; + int ch; + + snprintf(msg, sizeof(msg), + "\rChoose character set in 5 seconds, (U)UTF-8, (G)GBK [U]: "); - switch (result) + while (!SYS_server_exit) { - case 0: - break; - case -1: - log_error ("select() error!\n"); - break; - default: - if (FD_ISSET (0, &testfds)) - { - ch = igetch (); + ch = press_any_key_ex(msg, 5); + switch (toupper(ch)) + { + case KEY_NULL: + return -1; + case KEY_TIMEOUT: + case CR: + case 'U': + break; + case 'G': + if (io_conv_init("GBK") < 0) + { + log_error("io_conv_init(%s) error\n", "GBK"); + return -1; + } + break; + default: + continue; + } + + break; + } - switch (ch) + snprintf(msg, sizeof(msg), + "\r请在5秒内选择宽字符显示规则, (V)变宽, (F)定宽? [V]: "); + + while (!SYS_server_exit) + { + ch = press_any_key_ex(msg, 5); + switch (toupper(ch)) { case KEY_NULL: - return 0; + return -1; + case KEY_TIMEOUT: + case CR: + case 'V': + UTF8_fixed_width = 0; + break; + case 'F': + UTF8_fixed_width = 1; + break; default: - strcpy (action, menu_control (&bbs_menu, ch)); - switch (get_cmd_value (action)) - { - case EXITBBS: - return 0; - case BBSNET: - bbs_net (); - clearscr (); - show_top (""); - show_active_board (); - show_bottom (""); - display_current_menu (&bbs_menu); - break; - case UNKNOWN_CMD: - break; - } - } - } - break; - } - if (time (0) - t_last_action >= 10) - { - t_last_action = time (0); - show_active_board (); - show_bottom (""); + continue; + } + + break; } - } - return 0; + return 0; +} + +int bbs_main() +{ + 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; + } + act.sa_handler = child_proc_sig_usr1_handler; + if (sigaction(SIGUSR1, &act, NULL) == -1) + { + log_error("set signal action of SIGUSR1 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; + } +#ifdef HAVE_SYSTEM_V + if (set_user_list_pool_shm_readonly() < 0) + { + goto cleanup; + } +#endif + + // 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 + if (bbs_charset_select() < 0) + { + goto cleanup; + } + + // System info + if (bbs_info() < 0) + { + goto cleanup; + } + + // Welcome + if (bbs_welcome() < 0) + { + goto cleanup; + } + + // User login + if (SSH_v2) + { + 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); + + // Load section aid locations + if (section_aid_locations_load(BBS_priv.uid) < 0) + { + 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; + } + + // Load article favorite + if (article_favor_load(BBS_priv.uid, &BBS_article_favor, 0) < 0) + { + 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(); + + // 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(); + + // Cleanup BWF + bwf_unload(); + + return 0; }