diff --git a/ChangeLog.md b/ChangeLog.md index 5d3ff3a..158bdbf 100644 --- a/ChangeLog.md +++ b/ChangeLog.md @@ -3,6 +3,13 @@ 中文版本的ChangeLog.md位于[ChangeLog.zh_CN.md](ChangeLog.zh_CN.md) +2025-12-26 v1.7 +================= +Add minor features + +1. Enhance article management + + 2025-11-21 v1.6 ================= Support running on MSYS2 / MinGW64 diff --git a/ChangeLog.zh_CN.md b/ChangeLog.zh_CN.md index 200563e..336e5b5 100644 --- a/ChangeLog.zh_CN.md +++ b/ChangeLog.zh_CN.md @@ -1,6 +1,13 @@ # Changelog of LBBS - Classical terminal server of LeafOK BBS +2025-12-26 v1.7 +================= +新增功能 + +1. 完善文章管理 + + 2025-11-21 v1.6 ================= 支持运行在MSYS2 / MinGW64环境上 diff --git a/Makefile.am b/Makefile.am index 8eacd35..5a8febd 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,6 @@ ACLOCAL_AMFLAGS = -I m4 -EXTRA_DIST = README.md README.zh_CN.md INSTALL.md INSTALL.zh_CN.md ChangeLog.md ChangeLog.zh_CN.md LICENSE conf data +EXTRA_DIST = README.md README.zh_CN.md INSTALL.md INSTALL.zh_CN.md ChangeLog.md ChangeLog.zh_CN.md Tutorial.md Tutorial.zh_CN.md LICENSE conf data SUBDIRS = utils src install-data-local: diff --git a/README.md b/README.md index f91b401..5164081 100644 --- a/README.md +++ b/README.md @@ -22,7 +22,12 @@ System Requirement Installation ================== -See guide in [INSTALL.md](INSTALL.md) +See guide in [INSTALL.md](INSTALL.md) + + +Tutorial +================== +Watch demos and keynotes in [Tutorial.md](Tutorial.md) Copyright diff --git a/README.zh_CN.md b/README.zh_CN.md index c7b096b..359a29d 100644 --- a/README.zh_CN.md +++ b/README.zh_CN.md @@ -19,7 +19,12 @@ 安装说明 ================== -中文安装说明位于[INSTALL.zh_CN.md](INSTALL.zh_CN.md) +中文安装说明位于[INSTALL.zh_CN.md](INSTALL.zh_CN.md) + + +教程 +================== +安装演示和技术架构介绍位于[Tutorial.zh_CN.md](Tutorial.zh_CN.md) 版权信息 diff --git a/Tutorial.md b/Tutorial.md new file mode 100644 index 0000000..6614851 --- /dev/null +++ b/Tutorial.md @@ -0,0 +1,19 @@ +Notice +================== +All tutorial videos are conducted in Mandarine without subtitles. + + +Installation Guide +================== +[Web version](https://www.bilibili.com/video/BV1BqBGBFExZ/) [watch on Youtube](https://www.youtube.com/watch?v=AzMRaLtpGSc) +[Telnet version](https://www.bilibili.com/video/BV186BLBREuz/) [watch on Youtube](https://www.youtube.com/watch?v=h2Eex3b2XpY) + + +Introduction of Technical Design +================== +[Talk 1 --- Background of LBBS project](https://www.bilibili.com/video/BV1wqBjB2E5L/) [watch on Youtube](https://www.youtube.com/watch?v=BjNz187AhFI) +[Talk 2 --- Architecture of Network Server with Socket Programming](https://www.bilibili.com/video/BV1ZUBDBKEhA/) [watch on Youtube](https://www.youtube.com/watch?v=eqBXOjG2BbI) +[Talk 3 --- Optimization for High-concurrent Traversal and Browse of Articles](https://www.bilibili.com/video/BV16mBXByEuA/) [watch on Youtube](https://www.youtube.com/watch?v=0MzrSFdq3fo) +[Talk 4 --- Difficulties in Building Text Editor](https://www.bilibili.com/video/BV1fKBXBkESL/) [watch on Youtube](https://www.youtube.com/watch?v=KgaX3auf8pA) +[Talk 5 --- Data Structures and Algorithms](https://www.bilibili.com/video/BV1B7BoBQEcD/) [watch on Youtube](https://www.youtube.com/watch?v=fJsAtVQZNv0) +[Talk 6 --- Access Control and Data Security](https://www.bilibili.com/video/BV1enBaBkErp/) [watch on Youtube](https://www.youtube.com/watch?v=MuQEQ_6wKu0) diff --git a/Tutorial.zh_CN.md b/Tutorial.zh_CN.md new file mode 100644 index 0000000..e558ba5 --- /dev/null +++ b/Tutorial.zh_CN.md @@ -0,0 +1,19 @@ +注意 +================== +全部视频都使用中文讲解,但没有字幕 + + +安装演示 +================== +[Web版](https://www.bilibili.com/video/BV1BqBGBFExZ/) [去Youtube观看](https://www.youtube.com/watch?v=AzMRaLtpGSc) +[Telnet版](https://www.bilibili.com/video/BV186BLBREuz/) [去Youtube观看](https://www.youtube.com/watch?v=h2Eex3b2XpY) + + +技术架构介绍 +================== +[介绍1 --- 终端服务器的项目背景](https://www.bilibili.com/video/BV1wqBjB2E5L/) [去Youtube观看](https://www.youtube.com/watch?v=BjNz187AhFI) +[介绍2 --- 服务端架构和socket网络编程](https://www.bilibili.com/video/BV1ZUBDBKEhA/) [去Youtube观看](https://www.youtube.com/watch?v=eqBXOjG2BbI) +[介绍3 --- 为高并发的遍历和浏览优化](https://www.bilibili.com/video/BV16mBXByEuA/) [去Youtube观看](https://www.youtube.com/watch?v=0MzrSFdq3fo) +[介绍4 --- 漫谈文本编辑器](https://www.bilibili.com/video/BV1fKBXBkESL/) [去Youtube观看](https://www.youtube.com/watch?v=KgaX3auf8pA) +[介绍5 --- 数据结构和算法](https://www.bilibili.com/video/BV1B7BoBQEcD/) [去Youtube观看](https://www.youtube.com/watch?v=fJsAtVQZNv0) +[介绍6 --- 访问控制和数据安全](https://www.bilibili.com/video/BV1enBaBkErp/) [去Youtube观看](https://www.youtube.com/watch?v=MuQEQ_6wKu0) diff --git a/configure.ac b/configure.ac index fa066a9..48774f2 100644 --- a/configure.ac +++ b/configure.ac @@ -2,7 +2,7 @@ # Process this file with autoconf to produce a configure script. AC_PREREQ([2.69]) -AC_INIT([lbbs],[1.6.3]) +AC_INIT([lbbs],[1.7.0]) AC_CONFIG_SRCDIR([src/]) AC_CONFIG_HEADERS([config.h]) AC_CONFIG_MACRO_DIRS([m4]) @@ -113,7 +113,7 @@ AC_DEFINE_UNQUOTED([RETSIGTYPE], AC_FUNC_STRFTIME AC_FUNC_VPRINTF -AC_CHECK_FUNCS([dup2 gethostbyname inet_ntoa memset mkdir rmdir regcomp poll socket strstr]) +AC_CHECK_FUNCS([dup2 getaddrinfo inet_ntop memset mkdir rmdir regcomp poll socket strstr]) AC_CONFIG_FILES([Makefile src/Makefile diff --git a/data/version.txt b/data/version.txt index 638ae52..3c7698b 100644 --- a/data/version.txt +++ b/data/version.txt @@ -1,6 +1,10 @@ LeafOK BBS(Telnet版本) 版本变更记录 +1.7 +================= + 完善文章管理 + 1.6 ================= 可以在MSYS2 / MinGW64环境上运行 diff --git a/src/login.c b/src/login.c index bdd967c..f264320 100644 --- a/src/login.c +++ b/src/login.c @@ -41,11 +41,10 @@ int bbs_login(void) { char username[BBS_username_max_len + 1]; char password[BBS_password_max_len + 1]; - int i = 0; - int ok = 0; + int i; int ret; - for (; !SYS_server_exit && !ok && i < BBS_login_retry_times; i++) + for (i = 0; !SYS_server_exit && i < BBS_login_retry_times; i++) { prints("\033[1;33m请输入帐号\033[m(试用请输入`\033[1;36mguest\033[m', " "注册请输入`\033[1;31mnew\033[m'): "); @@ -59,14 +58,13 @@ int bbs_login(void) if (strcmp(username, "guest") == 0) { load_guest_info(); - + log_common("User [%s] authenticated successfully", username); return 0; } if (strcmp(username, "new") == 0) { display_file(DATA_REGISTER, 1); - return -1; } @@ -87,18 +85,20 @@ int bbs_login(void) ret = 0; } - ok = (ret == 0); + if (ret == 0) + { + log_common("User [%s] authenticated successfully", username); + return 0; + } + + log_common("User [%s] authentication failed (%d/%d)", username, + i + 1, BBS_login_retry_times); iflush(); } } - if (!ok) - { - display_file(DATA_LOGIN_ERROR, 1); - return -1; - } - - return 0; + display_file(DATA_LOGIN_ERROR, 1); + return -1; } int check_user(const char *username, const char *password) diff --git a/src/net_server.c b/src/net_server.c index 7ba4b88..ce5527b 100644 --- a/src/net_server.c +++ b/src/net_server.c @@ -124,6 +124,7 @@ static int auth_password(ssh_session session, const char *user, if (ret == 0) { + log_common("User [%s] authenticated successfully", user); return SSH_AUTH_SUCCESS; } @@ -132,6 +133,8 @@ static int auth_password(ssh_session session, const char *user, sdata->error = 1; } + log_common("User [%s] authentication failed (%d/%d)", user, + sdata->tries, BBS_login_retry_times); return SSH_AUTH_DENIED; } @@ -518,6 +521,7 @@ int net_server(const char *hostaddr, in_port_t port[]) int ret; int flags_server[2]; struct sockaddr_in sin; + char local_addr[INET_ADDRSTRLEN]; #ifdef HAVE_SYS_EPOLL_H struct epoll_event ev, events[MAX_EVENTS]; @@ -606,6 +610,12 @@ int net_server(const char *hostaddr, in_port_t port[]) sin.sin_addr.s_addr = (hostaddr[0] != '\0' ? inet_addr(hostaddr) : INADDR_ANY); sin.sin_port = htons(port[i]); + if (inet_ntop(AF_INET, &(sin.sin_addr), local_addr, sizeof(local_addr)) == NULL) + { + log_error("inet_ntop() error (%d)", errno); + return -1; + } + // Reuse address and port flags_server[i] = 1; if (setsockopt(socket_server[i], SOL_SOCKET, SO_REUSEADDR, &flags_server[i], sizeof(flags_server[i])) < 0) @@ -622,7 +632,7 @@ int net_server(const char *hostaddr, in_port_t port[]) if (bind(socket_server[i], (struct sockaddr *)&sin, sizeof(sin)) < 0) { log_error("Bind address %s:%u error (%d)", - inet_ntoa(sin.sin_addr), ntohs(sin.sin_port), errno); + local_addr, port[i], errno); return -1; } @@ -632,7 +642,7 @@ int net_server(const char *hostaddr, in_port_t port[]) return -1; } - log_common("Listening at %s:%u", inet_ntoa(sin.sin_addr), ntohs(sin.sin_port)); + log_common("Listening at %s:%u", local_addr, port[i]); #ifdef HAVE_SYS_EPOLL_H ev.events = EPOLLIN; @@ -790,7 +800,7 @@ int net_server(const char *hostaddr, in_port_t port[]) #endif log_common("Reload configuration"); - + // Restart log if (log_restart() < 0) { @@ -931,9 +941,12 @@ int net_server(const char *hostaddr, in_port_t port[]) } } - strncpy(hostaddr_client, inet_ntoa(sin.sin_addr), sizeof(hostaddr_client) - 1); - hostaddr_client[sizeof(hostaddr_client) - 1] = '\0'; - + if (inet_ntop(AF_INET, &(sin.sin_addr), hostaddr_client, sizeof(hostaddr_client)) == NULL) + { + log_error("inet_ntop() error (%d)", errno); + close(socket_client); + break; + } port_client = ntohs(sin.sin_port); if (SYS_child_process_count - 1 < BBS_max_client) diff --git a/src/screen.c b/src/screen.c index dcc9568..94d29df 100644 --- a/src/screen.c +++ b/src/screen.c @@ -165,7 +165,7 @@ static int _str_input(char *buffer, int buf_size, int max_display_len, enum io_e { continue; } - else if (ch == BACKSPACE) + else if (ch == BACKSPACE || ch == KEY_DEL) { if (offset > 0) {