From 7165246ba6a85b6d9443ccb396f60250baee6931 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E9=BB=91=E5=99=9C?= <51919849+ytht@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:19:27 +0800 Subject: [PATCH 01/15] Add CI workflow for lbbs_dev branch --- .github/workflows/lbbs_dev.yml | 38 ++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) create mode 100644 .github/workflows/lbbs_dev.yml diff --git a/.github/workflows/lbbs_dev.yml b/.github/workflows/lbbs_dev.yml new file mode 100644 index 00000000..92208bf2 --- /dev/null +++ b/.github/workflows/lbbs_dev.yml @@ -0,0 +1,38 @@ +name: Makefile CI + +on: + push: + branches: [ "lbbs_dev" ] + pull_request: + branches: [ "lbbs_dev" ] + +jobs: + build: + + runs-on: ubuntu-latest + + steps: + - uses: actions/checkout@v4 + + - name: autogen + run: sh autogen.sh + + - name: Install dependencies + run: | + sudo apt-get update + sudo apt-get install -y libssh-dev libsystemd-dev + + - name: Display GCC version + run: gcc -v + + - name: configure + run: ./configure + + - name: Run make + run: make V=1 + + - name: Run check + run: make check + + - name: Run distcheck + run: make distcheck From dd4045b09c558567b6d43ca884e586a960c35444 Mon Sep 17 00:00:00 2001 From: ytht <2391669999@qq.com> Date: Tue, 11 Nov 2025 19:22:52 +0800 Subject: [PATCH 02/15] =?UTF-8?q?=E8=AE=BE=E7=BD=AE=E4=B8=8D=E5=90=88?= =?UTF-8?q?=E5=B9=B6yml=E6=96=87=E4=BB=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .gitattributes | 1 + .github/workflows/lbbs_dev.yml | 38 ---------------------------------- 2 files changed, 1 insertion(+), 38 deletions(-) create mode 100644 .gitattributes delete mode 100644 .github/workflows/lbbs_dev.yml diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 00000000..91bae6d9 --- /dev/null +++ b/.gitattributes @@ -0,0 +1 @@ +.github/workflows/*.yml merge=notMerge diff --git a/.github/workflows/lbbs_dev.yml b/.github/workflows/lbbs_dev.yml deleted file mode 100644 index 92208bf2..00000000 --- a/.github/workflows/lbbs_dev.yml +++ /dev/null @@ -1,38 +0,0 @@ -name: Makefile CI - -on: - push: - branches: [ "lbbs_dev" ] - pull_request: - branches: [ "lbbs_dev" ] - -jobs: - build: - - runs-on: ubuntu-latest - - steps: - - uses: actions/checkout@v4 - - - name: autogen - run: sh autogen.sh - - - name: Install dependencies - run: | - sudo apt-get update - sudo apt-get install -y libssh-dev libsystemd-dev - - - name: Display GCC version - run: gcc -v - - - name: configure - run: ./configure - - - name: Run make - run: make V=1 - - - name: Run check - run: make check - - - name: Run distcheck - run: make distcheck From c0345b7b7c633b430e8b8a59c398a251e2ac5df8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E8=80=81=E9=BB=91=E5=99=9C?= <51919849+ytht@users.noreply.github.com> Date: Tue, 11 Nov 2025 19:39:33 +0800 Subject: [PATCH 03/15] Add lbbs_dev branch to CI workflow --- .github/workflows/makefile.yml | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 00d389ca..ed8a470e 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -2,10 +2,14 @@ name: Makefile CI on: push: - branches: [ "main" ] + branches: + - "main" + - "lbbs_dev" pull_request: - branches: [ "main" ] - + branches: + - "main" + - "lbbs_dev" + jobs: build: From e576a07fef403dc0f3afb56c00f4082240d5a823 Mon Sep 17 00:00:00 2001 From: ytht <2391669999@qq.com> Date: Mon, 17 Nov 2025 21:03:38 +0800 Subject: [PATCH 04/15] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=20=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E6=94=B6=E5=BD=95/=E7=A7=BB=E5=87=BA=E6=96=87=E6=91=98?= =?UTF-8?q?=E5=8C=BA=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/article_op.h | 6 ++ src/article_op.c | 196 +++++++++++++++++++++++++++++++++++++ src/section_list_display.c | 19 ++++ 3 files changed, 221 insertions(+) diff --git a/include/article_op.h b/include/article_op.h index f9423dfd..9642a1ed 100644 --- a/include/article_op.h +++ b/include/article_op.h @@ -11,6 +11,12 @@ #include +enum bbs_article_op_type_t +{ + BBS_article_set_excerption = 'E', + BBS_article_unset_excerption = 'O', +}; extern int display_article_meta(int32_t aid); +extern int article_exc_set(int32_t aid, int8_t is_exc); #endif //_ARTICLE_OP_H_ diff --git a/src/article_op.c b/src/article_op.c index 50080a8b..bf8014ed 100644 --- a/src/article_op.c +++ b/src/article_op.c @@ -12,8 +12,19 @@ #include "article_op.h" #include "bbs.h" +#include "common.h" +#include "database.h" #include "io.h" +#include "log.h" #include "screen.h" +#include "user_priv.h" +#include +#include + +enum ret_msg_len_t +{ + ret_msg_len = 20, +}; int display_article_meta(int32_t aid) { @@ -26,3 +37,188 @@ int display_article_meta(int32_t aid) return 0; } + +int article_exc_set(int32_t aid, int8_t is_exc) +{ + MYSQL *db = NULL; + MYSQL_RES *rs = NULL; + MYSQL_ROW row; + char sql[SQL_BUFFER_LEN]; + int ret = 0; + int uid = 0; + int tid = 0; + int sid = 0; + int8_t transship = 0; + int8_t excerption = 0; + int8_t set_exc = !is_exc; + char ret_msg[ret_msg_len] = ""; + + db = db_open(); + if (db == NULL) + { + log_error("db_open() error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + // Begin transaction + if (mysql_query(db, "SET autocommit=0") != 0) + { + log_error("SET autocommit=0 error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + if (mysql_query(db, "BEGIN") != 0) + { + log_error("Begin transaction error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + + snprintf(sql, sizeof(sql), + "SELECT UID, TID, SID, transship, excerption FROM bbs WHERE visible and AID=%d FOR UPDATE", + aid); + if (mysql_query(db, sql) != 0) + { + log_error("Query bbs error: %s\n", mysql_error(db)); + ret = -2; + goto cleanup; + } + if ((rs = mysql_store_result(db)) == NULL) + { + log_error("Get article data failed\n"); + ret = -2; + goto cleanup; + } + if ((row = mysql_fetch_row(rs))) + { + uid = atoi(row[0]); + tid = atoi(row[1]); + sid = atoi(row[2]); + transship = (int8_t)atoi(row[3]); + excerption = (int8_t)atoi(row[4]); + } + else + { + if (mysql_errno(db)) + { + log_error("mysql_fetch_row() error: %s\n", mysql_error(db)); + ret = -2; + } + else + { + strncpy(ret_msg, "文章不存在", ret_msg_len); + ret = -1; + } + goto cleanup; + } + mysql_free_result(rs); + rs = NULL; + + // Check if already set + if (set_exc == excerption) + { + snprintf(ret_msg, sizeof(ret_msg), "已%s文摘区", set_exc ? "收录" : "移出"); + ret = 1; + goto cleanup; + } + + // Update article(s) + snprintf(sql, sizeof(sql), + "UPDATE bbs SET excerption = %d WHERE AID=%d", + set_exc, aid); + if (mysql_query(db, sql) != 0) + { + log_error("Update article set error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + + // Clear gen_ex if unset excerption + if (set_exc == 0) + { + snprintf(sql, sizeof(sql), + "UPDATE bbs SET gen_ex = 0, static = 0 WHERE AID=%d OR TID =%d", + aid, aid); + + if (mysql_query(db, sql) != 0) + { + log_error("Clear gen_ex error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + + // Delete ex_dir path if head of thread + if (tid == 0) + { + snprintf(sql, sizeof(sql), + "DELETE FROM ex_file WHERE AID = %d", + aid); + + if (mysql_query(db, sql) != 0) + { + log_error("Delete ex_dir error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + } + } + + // Change UID of attachments + snprintf(sql, sizeof(sql), + "UPDATE upload_file SET UID = %d WHERE ref_AID = %d AND deleted = 0", + set_exc ? 0 : uid, aid); + if (mysql_query(db, sql) != 0) + { + log_error("Change UID error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + + // Modify exp + if (checkpriv(&BBS_priv, sid, S_GETEXP)) // Except in test section + { + snprintf(sql, sizeof(sql), + "UPDATE user_pubinfo SET exp = exp + %d WHERE UID = %d", + (set_exc ? 1 : -1) * (tid == 0 ? (transship ? 20 : 50) : 10), uid); + + if (mysql_query(db, sql) != 0) + { + log_error("Update exp error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + } + + // Add log + snprintf(sql, sizeof(sql), + "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip)" + "VALUES(%d, %d, '%c', NOW(), '%s')", + aid, BBS_priv.uid, set_exc ? BBS_article_set_excerption : BBS_article_unset_excerption, hostaddr_client); + + if (mysql_query(db, sql) != 0) + { + log_error("Add log error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + + // Commit transaction + if (mysql_query(db, "COMMIT") != 0) + { + log_error("Commit transaction error: %s\n", mysql_error(db)); + ret = -1; + goto cleanup; + } + + mysql_close(db); + db = NULL; + + snprintf(ret_msg, sizeof(ret_msg), "已%s文摘区", set_exc ? "收录" : "移出"); + ret = 1; // Success + +cleanup: + mysql_free_result(rs); + mysql_close(db); + press_any_key_ex(ret_msg, 3); + return ret; +} diff --git a/src/section_list_display.c b/src/section_list_display.c index 8ab93c9d..2e79f45f 100644 --- a/src/section_list_display.c +++ b/src/section_list_display.c @@ -58,6 +58,7 @@ enum select_cmd_t QUERY_USER, SET_FAVOR_ARTICLE, UNSET_FAVOR_ARTICLE, + SET_EXCERPTION_ARTICLE, FIRST_TOPIC_ARTICLE, LAST_TOPIC_ARTICLE, LAST_SECTION_ARTICLE, @@ -335,6 +336,12 @@ static enum select_cmd_t section_list_select(int total_page, int item_count, int return UNSET_FAVOR_ARTICLE; } break; + case 'm': + if (item_count > 0) + { + return SET_EXCERPTION_ARTICLE; + } + break; case KEY_HOME: *p_page_id = 0; case 'P': @@ -1087,6 +1094,18 @@ int section_list_display(const char *sname, int32_t aid) p_articles[selected_index]->tid == 0 ? p_articles[selected_index]->aid : p_articles[selected_index]->tid); } break; + case SET_EXCERPTION_ARTICLE: + if (!checkpriv(&BBS_priv, p_section->sid, S_POST) || !checkpriv(&BBS_priv, p_section->sid, S_MAN_S)) + { + break; + } + ret = article_exc_set(p_articles[selected_index]->aid, p_articles[selected_index]->excerption); + if (ret < 0) + { + log_error("article_exc_set(aid=%d, excerption=%d) error\n", + p_articles[selected_index]->aid, p_articles[selected_index]->excerption); + } + break; case FIRST_TOPIC_ARTICLE: case LAST_TOPIC_ARTICLE: page_id_cur = page_id; From f4b1df2139b709d9b6f3224471bc8fb8a3bb124c Mon Sep 17 00:00:00 2001 From: ytht <2391669999@qq.com> Date: Thu, 4 Dec 2025 20:22:00 +0800 Subject: [PATCH 05/15] =?UTF-8?q?=E4=BC=98=E5=8C=96=20=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E6=94=B6=E5=BD=95/=E7=A7=BB=E5=87=BA=E6=96=87=E6=91=98?= =?UTF-8?q?=E5=8C=BA=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- include/article_op.h | 7 ++++--- src/article_op.c | 12 ++++++++++-- src/section_list_display.c | 2 +- 3 files changed, 15 insertions(+), 6 deletions(-) diff --git a/include/article_op.h b/include/article_op.h index 9642a1ed..f6afe138 100644 --- a/include/article_op.h +++ b/include/article_op.h @@ -9,14 +9,15 @@ #ifndef _ARTICLE_OP_H_ #define _ARTICLE_OP_H_ +#include #include enum bbs_article_op_type_t { - BBS_article_set_excerption = 'E', - BBS_article_unset_excerption = 'O', + BBS_article_set_excerption = 'E', + BBS_article_unset_excerption = 'O', }; extern int display_article_meta(int32_t aid); -extern int article_exc_set(int32_t aid, int8_t is_exc); +extern int article_exc_set(SECTION_LIST *p_section,int32_t aid, int8_t is_exc); #endif //_ARTICLE_OP_H_ diff --git a/src/article_op.c b/src/article_op.c index ba2d914f..c482d353 100644 --- a/src/article_op.c +++ b/src/article_op.c @@ -38,7 +38,7 @@ int display_article_meta(int32_t aid) return 0; } -int article_exc_set(int32_t aid, int8_t is_exc) +int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) { MYSQL *db = NULL; MYSQL_RES *rs = NULL; @@ -202,9 +202,17 @@ int article_exc_set(int32_t aid, int8_t is_exc) goto cleanup; } + section_list_rw_lock(p_section); + section_list_set_article_excerption(p_section,aid,set_exc); + section_list_rw_unlock(p_section); + // Commit transaction if (mysql_query(db, "COMMIT") != 0) { + section_list_rw_lock(p_section); + section_list_set_article_excerption(p_section,aid,!set_exc); + section_list_rw_unlock(p_section); + log_error("Commit transaction error: %s\n", mysql_error(db)); ret = -1; goto cleanup; @@ -219,6 +227,6 @@ int article_exc_set(int32_t aid, int8_t is_exc) cleanup: mysql_free_result(rs); mysql_close(db); - press_any_key_ex(ret_msg, 3); + //press_any_key_ex(ret_msg, 3); return ret; } diff --git a/src/section_list_display.c b/src/section_list_display.c index d6738434..59fc5818 100644 --- a/src/section_list_display.c +++ b/src/section_list_display.c @@ -1099,7 +1099,7 @@ int section_list_display(const char *sname, int32_t aid) { break; } - ret = article_exc_set(p_articles[selected_index]->aid, p_articles[selected_index]->excerption); + ret = article_exc_set(p_section, p_articles[selected_index]->aid, p_articles[selected_index]->excerption); if (ret < 0) { log_error("article_exc_set(aid=%d, excerption=%d) error\n", From f97b25262485837bc64106896e34dbbb8013f5f0 Mon Sep 17 00:00:00 2001 From: ytht <2391669999@qq.com> Date: Mon, 8 Dec 2025 07:01:18 +0800 Subject: [PATCH 06/15] =?UTF-8?q?=E4=BC=98=E5=8C=96=20=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E6=94=B6=E5=BD=95/=E7=A7=BB=E5=87=BA=E6=96=87=E6=91=98?= =?UTF-8?q?=E5=8C=BA=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/article_op.c | 87 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 68 insertions(+), 19 deletions(-) diff --git a/src/article_op.c b/src/article_op.c index c482d353..240cf235 100644 --- a/src/article_op.c +++ b/src/article_op.c @@ -52,6 +52,16 @@ int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) int8_t excerption = 0; int8_t set_exc = !is_exc; char ret_msg[ret_msg_len] = ""; + int section_set_exc_ret = 0; + + if (p_section == NULL) + { + log_error("NULL pointer error\n"); + ret = -1; + goto cleanup; + } + + sid = p_section->sid; db = db_open(); if (db == NULL) @@ -91,24 +101,21 @@ int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) } if ((row = mysql_fetch_row(rs))) { + if (sid != atoi(row[2])) + { + log_error("sid error: sid = %d, row[2]= %s, aid = %d\n", sid, row[2], aid); + ret = -2; + goto cleanup; + } uid = atoi(row[0]); tid = atoi(row[1]); - sid = atoi(row[2]); transship = (int8_t)atoi(row[3]); excerption = (int8_t)atoi(row[4]); } else { - if (mysql_errno(db)) - { - log_error("mysql_fetch_row() error: %s\n", mysql_error(db)); - ret = -2; - } - else - { - strncpy(ret_msg, "文章不存在", ret_msg_len); - ret = -1; - } + log_error("mysql_fetch_row() error: %s\n", mysql_error(db)); + ret = -2; goto cleanup; } mysql_free_result(rs); @@ -116,7 +123,7 @@ int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) // Check if already set if (set_exc == excerption) - { + { snprintf(ret_msg, sizeof(ret_msg), "已%s文摘区", set_exc ? "收录" : "移出"); ret = 1; goto cleanup; @@ -202,16 +209,58 @@ int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) goto cleanup; } - section_list_rw_lock(p_section); - section_list_set_article_excerption(p_section,aid,set_exc); - section_list_rw_unlock(p_section); + if (section_list_rw_lock(p_section) != 0) + { + log_error("section_list_rw_lock error on section %d\n", sid); + ret = -1; + goto cleanup; + } + section_set_exc_ret = section_list_set_article_excerption(p_section, aid, set_exc); + if (section_set_exc_ret == 0) + { + ret = 1; + goto cleanup; + } + else if (section_set_exc_ret < 0) + { + log_error("section_list_set_article_excerption error sid = %d, aid= %d, set_exc= %d\n", sid, aid, set_exc); + ret = -1; + goto cleanup; + } + if (section_list_rw_unlock(p_section) != 0) + { + log_error("section_list_rw_unlock error on section %d\n", sid); + ret = -1; + goto cleanup; + } // Commit transaction if (mysql_query(db, "COMMIT") != 0) { - section_list_rw_lock(p_section); - section_list_set_article_excerption(p_section,aid,!set_exc); - section_list_rw_unlock(p_section); + if (section_list_rw_lock(p_section) != 0) + { + log_error("section_list_rw_lock error on section %d\n", sid); + ret = -1; + goto cleanup; + } + section_set_exc_ret = section_list_set_article_excerption(p_section, aid, !set_exc); + if (section_set_exc_ret == 0) + { + ret = -1; + goto cleanup; + } + else if (section_set_exc_ret < 0) + { + log_error("section_list_set_article_excerption error sid = %d, aid= %d, set_exc= %d\n", sid, aid, !set_exc); + ret = -1; + goto cleanup; + } + if (section_list_rw_unlock(p_section) != 0) + { + log_error("section_list_rw_unlock error on section %d\n", sid); + ret = -1; + goto cleanup; + } log_error("Commit transaction error: %s\n", mysql_error(db)); ret = -1; @@ -227,6 +276,6 @@ int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) cleanup: mysql_free_result(rs); mysql_close(db); - //press_any_key_ex(ret_msg, 3); + // press_any_key_ex(ret_msg, 3); return ret; } From aacdade10addd6aab788a5ef3b4a0633ee2344a3 Mon Sep 17 00:00:00 2001 From: ytht <2391669999@qq.com> Date: Sat, 20 Dec 2025 16:53:12 +0800 Subject: [PATCH 07/15] =?UTF-8?q?=E4=BC=98=E5=8C=96=20=E6=96=87=E7=AB=A0?= =?UTF-8?q?=E6=94=B6=E5=BD=95/=E7=A7=BB=E5=87=BA=E6=96=87=E6=91=98?= =?UTF-8?q?=E5=8C=BA=20=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- src/article_op.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/article_op.c b/src/article_op.c index 240cf235..da255250 100644 --- a/src/article_op.c +++ b/src/article_op.c @@ -123,7 +123,7 @@ int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) // Check if already set if (set_exc == excerption) - { + { snprintf(ret_msg, sizeof(ret_msg), "已%s文摘区", set_exc ? "收录" : "移出"); ret = 1; goto cleanup; From 303a76efe367fdd3fca7b2f5aeff7e3fb1618a3e Mon Sep 17 00:00:00 2001 From: Leaflet Date: Sat, 20 Dec 2025 19:36:24 +0800 Subject: [PATCH 08/15] Remove unwanted change --- .gitattributes | 1 - .github/workflows/makefile.yml | 10 +++------- 2 files changed, 3 insertions(+), 8 deletions(-) delete mode 100644 .gitattributes diff --git a/.gitattributes b/.gitattributes deleted file mode 100644 index 91bae6d9..00000000 --- a/.gitattributes +++ /dev/null @@ -1 +0,0 @@ -.github/workflows/*.yml merge=notMerge diff --git a/.github/workflows/makefile.yml b/.github/workflows/makefile.yml index 4ae70463..dc95348c 100644 --- a/.github/workflows/makefile.yml +++ b/.github/workflows/makefile.yml @@ -2,14 +2,10 @@ name: Makefile CI on: push: - branches: - - "main" - - "lbbs_dev" + branches: [ "main" ] pull_request: - branches: - - "main" - - "lbbs_dev" - + branches: [ "main" ] + jobs: build: From 48e49b0ab8f9ab7a36664eab4b4bb6798beda801 Mon Sep 17 00:00:00 2001 From: Leaflet Date: Sat, 20 Dec 2025 21:07:38 +0800 Subject: [PATCH 09/15] Refine logic to keep consistent with Web version --- include/article_op.h | 9 +- src/article_op.c | 233 ++++++++++++++++++------------------- src/section_list_display.c | 15 ++- 3 files changed, 122 insertions(+), 135 deletions(-) diff --git a/include/article_op.h b/include/article_op.h index f6afe138..c3d46e7b 100644 --- a/include/article_op.h +++ b/include/article_op.h @@ -9,15 +9,10 @@ #ifndef _ARTICLE_OP_H_ #define _ARTICLE_OP_H_ -#include +#include "section_list.h" #include -enum bbs_article_op_type_t -{ - BBS_article_set_excerption = 'E', - BBS_article_unset_excerption = 'O', -}; extern int display_article_meta(int32_t aid); -extern int article_exc_set(SECTION_LIST *p_section,int32_t aid, int8_t is_exc); +extern int article_excerption_set(SECTION_LIST *p_section, int32_t aid, int8_t set); #endif //_ARTICLE_OP_H_ diff --git a/src/article_op.c b/src/article_op.c index da255250..a3eb1246 100644 --- a/src/article_op.c +++ b/src/article_op.c @@ -12,14 +12,11 @@ #include "article_op.h" #include "bbs.h" -#include "common.h" #include "database.h" #include "io.h" #include "log.h" #include "screen.h" #include "user_priv.h" -#include -#include enum ret_msg_len_t { @@ -38,7 +35,7 @@ int display_article_meta(int32_t aid) return 0; } -int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) +int article_excerption_set(SECTION_LIST *p_section, int32_t aid, int8_t set) { MYSQL *db = NULL; MYSQL_RES *rs = NULL; @@ -50,232 +47,228 @@ int article_exc_set(SECTION_LIST *p_section, int32_t aid, int8_t is_exc) int sid = 0; int8_t transship = 0; int8_t excerption = 0; - int8_t set_exc = !is_exc; - char ret_msg[ret_msg_len] = ""; - int section_set_exc_ret = 0; if (p_section == NULL) { - log_error("NULL pointer error\n"); + log_error("NULL pointer error"); ret = -1; goto cleanup; } - sid = p_section->sid; + if (set) + { + set = 1; + } db = db_open(); if (db == NULL) { - log_error("db_open() error: %s\n", mysql_error(db)); + log_error("db_open() error: %s", mysql_error(db)); ret = -1; goto cleanup; } + // Begin transaction if (mysql_query(db, "SET autocommit=0") != 0) { - log_error("SET autocommit=0 error: %s\n", mysql_error(db)); + log_error("SET autocommit=0 error: %s", mysql_error(db)); ret = -1; goto cleanup; } + if (mysql_query(db, "BEGIN") != 0) { - log_error("Begin transaction error: %s\n", mysql_error(db)); + log_error("Begin transaction error: %s", mysql_error(db)); ret = -1; goto cleanup; } snprintf(sql, sizeof(sql), - "SELECT UID, TID, SID, transship, excerption FROM bbs WHERE visible and AID=%d FOR UPDATE", + "SELECT UID, TID, SID, transship, excerption FROM bbs " + "WHERE AID = %d AND visible FOR UPDATE", aid); if (mysql_query(db, sql) != 0) { - log_error("Query bbs error: %s\n", mysql_error(db)); + log_error("Query article error: %s", mysql_error(db)); ret = -2; goto cleanup; } + if ((rs = mysql_store_result(db)) == NULL) { - log_error("Get article data failed\n"); + log_error("Get article data failed"); ret = -2; goto cleanup; } + if ((row = mysql_fetch_row(rs))) { - if (sid != atoi(row[2])) - { - log_error("sid error: sid = %d, row[2]= %s, aid = %d\n", sid, row[2], aid); - ret = -2; - goto cleanup; - } uid = atoi(row[0]); tid = atoi(row[1]); + sid = atoi(row[2]); transship = (int8_t)atoi(row[3]); excerption = (int8_t)atoi(row[4]); } else { - log_error("mysql_fetch_row() error: %s\n", mysql_error(db)); + log_error("Article not found: aid=%d", aid); ret = -2; goto cleanup; } mysql_free_result(rs); rs = NULL; - // Check if already set - if (set_exc == excerption) - { - snprintf(ret_msg, sizeof(ret_msg), "已%s文摘区", set_exc ? "收录" : "移出"); - ret = 1; - goto cleanup; - } - - // Update article(s) - snprintf(sql, sizeof(sql), - "UPDATE bbs SET excerption = %d WHERE AID=%d", - set_exc, aid); - if (mysql_query(db, sql) != 0) + if (p_section->sid != sid) { - log_error("Update article set error: %s\n", mysql_error(db)); - ret = -1; + log_error("Inconsistent SID of article (aid=%d): %d!=%d", aid, p_section->sid, sid); + ret = -2; goto cleanup; } - // Clear gen_ex if unset excerption - if (set_exc == 0) + // Check if already set + if (excerption != set) { snprintf(sql, sizeof(sql), - "UPDATE bbs SET gen_ex = 0, static = 0 WHERE AID=%d OR TID =%d", - aid, aid); - + "UPDATE bbs SET excerption = %d WHERE AID = %d", + set, aid); if (mysql_query(db, sql) != 0) { - log_error("Clear gen_ex error: %s\n", mysql_error(db)); - ret = -1; + log_error("Set excerption error: %s", mysql_error(db)); + ret = -2; goto cleanup; } - // Delete ex_dir path if head of thread - if (tid == 0) + // Clear gen_ex if unset excerption + if (set == 0) { snprintf(sql, sizeof(sql), - "DELETE FROM ex_file WHERE AID = %d", - aid); + "UPDATE bbs SET gen_ex = 0, static = 0 WHERE AID = %d OR TID = %d", + aid, aid); if (mysql_query(db, sql) != 0) { - log_error("Delete ex_dir error: %s\n", mysql_error(db)); - ret = -1; + log_error("Set gen_ex error: %s", mysql_error(db)); + ret = -2; goto cleanup; } + + // Delete ex_dir path if head of thread + if (tid == 0) + { + snprintf(sql, sizeof(sql), + "DELETE FROM ex_file WHERE AID = %d", + aid); + + if (mysql_query(db, sql) != 0) + { + log_error("Delete ex_file error: %s", mysql_error(db)); + ret = -2; + goto cleanup; + } + } } - } - // Change UID of attachments - snprintf(sql, sizeof(sql), - "UPDATE upload_file SET UID = %d WHERE ref_AID = %d AND deleted = 0", - set_exc ? 0 : uid, aid); - if (mysql_query(db, sql) != 0) - { - log_error("Change UID error: %s\n", mysql_error(db)); - ret = -1; - goto cleanup; - } + // Change UID of attachments + snprintf(sql, sizeof(sql), + "UPDATE upload_file SET UID = %d " + "WHERE ref_AID = %d AND deleted = 0", + (set ? 0 : uid), aid); + if (mysql_query(db, sql) != 0) + { + log_error("Set attachment status error: %s", mysql_error(db)); + ret = -2; + goto cleanup; + } - // Modify exp - if (checkpriv(&BBS_priv, sid, S_GETEXP)) // Except in test section - { + // Modify exp + if (checkpriv(&BBS_priv, sid, S_GETEXP)) // Except in test section + { + snprintf(sql, sizeof(sql), + "UPDATE user_pubinfo SET exp = exp + %d WHERE UID = %d", + (set ? 1 : -1) * (tid == 0 ? (transship ? 20 : 50) : 10), uid); + + if (mysql_query(db, sql) != 0) + { + log_error("Change exp error: %s", mysql_error(db)); + ret = -2; + goto cleanup; + } + } + + // Add log snprintf(sql, sizeof(sql), - "UPDATE user_pubinfo SET exp = exp + %d WHERE UID = %d", - (set_exc ? 1 : -1) * (tid == 0 ? (transship ? 20 : 50) : 10), uid); + "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip) " + "VALUES(%d, %d, '%c', NOW(), '%s')", + aid, BBS_priv.uid, (set ? 'E' : 'O'), hostaddr_client); if (mysql_query(db, sql) != 0) { - log_error("Update exp error: %s\n", mysql_error(db)); - ret = -1; + log_error("Add log error: %s", mysql_error(db)); + ret = -2; goto cleanup; } } - // Add log - snprintf(sql, sizeof(sql), - "INSERT INTO bbs_article_op(AID, UID, type, op_dt, op_ip)" - "VALUES(%d, %d, '%c', NOW(), '%s')", - aid, BBS_priv.uid, set_exc ? BBS_article_set_excerption : BBS_article_unset_excerption, hostaddr_client); - - if (mysql_query(db, sql) != 0) + if (section_list_rw_lock(p_section) < 0) { - log_error("Add log error: %s\n", mysql_error(db)); - ret = -1; + log_error("section_list_rw_lock(sid=%d) error", sid); + ret = -3; goto cleanup; } - if (section_list_rw_lock(p_section) != 0) - { - log_error("section_list_rw_lock error on section %d\n", sid); - ret = -1; - goto cleanup; - } - section_set_exc_ret = section_list_set_article_excerption(p_section, aid, set_exc); - if (section_set_exc_ret == 0) + ret = section_list_set_article_excerption(p_section, aid, set); + if (ret < 0) { - ret = 1; + log_error("section_list_set_article_excerption(sid=%d, aid=%d, set=%d) error", sid, aid, set); + ret = -3; goto cleanup; } - else if (section_set_exc_ret < 0) - { - log_error("section_list_set_article_excerption error sid = %d, aid= %d, set_exc= %d\n", sid, aid, set_exc); - ret = -1; - goto cleanup; - } - if (section_list_rw_unlock(p_section) != 0) + + if (section_list_rw_unlock(p_section) < 0) { - log_error("section_list_rw_unlock error on section %d\n", sid); - ret = -1; + log_error("section_list_rw_unlock(sid=%d) error", sid); + ret = -3; goto cleanup; } // Commit transaction if (mysql_query(db, "COMMIT") != 0) { - if (section_list_rw_lock(p_section) != 0) - { - log_error("section_list_rw_lock error on section %d\n", sid); - ret = -1; - goto cleanup; - } - section_set_exc_ret = section_list_set_article_excerption(p_section, aid, !set_exc); - if (section_set_exc_ret == 0) + log_error("Mysqli error: %s\n", mysql_error(db)); + + // Rollback change to avoid data inconsistency + if (section_list_rw_lock(p_section) < 0) { - ret = -1; + log_error("section_list_rw_lock(sid=%d) error", sid); + ret = -3; goto cleanup; } - else if (section_set_exc_ret < 0) + + ret = section_list_set_article_excerption(p_section, aid, excerption); + if (ret < 0) { - log_error("section_list_set_article_excerption error sid = %d, aid= %d, set_exc= %d\n", sid, aid, !set_exc); - ret = -1; + log_error("section_list_set_article_excerption(sid=%d, aid=%d, set=%d) error", sid, aid, excerption); + ret = -3; goto cleanup; } - if (section_list_rw_unlock(p_section) != 0) + + if (section_list_rw_unlock(p_section) < 0) { - log_error("section_list_rw_unlock error on section %d\n", sid); - ret = -1; + log_error("section_list_rw_unlock(sid=%d) error", sid); + ret = -3; goto cleanup; } - log_error("Commit transaction error: %s\n", mysql_error(db)); - ret = -1; - goto cleanup; + ret = 0; + } + else + { + ret = 1; // Success } - - mysql_close(db); - db = NULL; - - snprintf(ret_msg, sizeof(ret_msg), "已%s文摘区", set_exc ? "收录" : "移出"); - ret = 1; // Success cleanup: mysql_free_result(rs); mysql_close(db); - // press_any_key_ex(ret_msg, 3); + return ret; } diff --git a/src/section_list_display.c b/src/section_list_display.c index 608f285b..d4aadd39 100644 --- a/src/section_list_display.c +++ b/src/section_list_display.c @@ -1101,15 +1101,14 @@ int section_list_display(const char *sname, int32_t aid) } break; case SET_EXCERPTION_ARTICLE: - if (!checkpriv(&BBS_priv, p_section->sid, S_POST) || !checkpriv(&BBS_priv, p_section->sid, S_MAN_S)) + if (checkpriv(&BBS_priv, p_section->sid, S_POST | S_MAN_S)) { - break; - } - ret = article_exc_set(p_section, p_articles[selected_index]->aid, p_articles[selected_index]->excerption); - if (ret < 0) - { - log_error("article_exc_set(aid=%d, excerption=%d) error\n", - p_articles[selected_index]->aid, p_articles[selected_index]->excerption); + ret = article_excerption_set(p_section, p_articles[selected_index]->aid, (p_articles[selected_index]->excerption ? 0 : 1)); + if (ret < 0) + { + log_error("article_excerption_set(sid=%d, aid=%d, set=%d) error\n", + p_section->sid, p_articles[selected_index]->aid, (p_articles[selected_index]->excerption ? 0 : 1)); + } } break; case FIRST_TOPIC_ARTICLE: From ce90ba023b179ce91ea67a2794f95d2e864c1c7c Mon Sep 17 00:00:00 2001 From: Leaflet Date: Sat, 20 Dec 2025 21:12:09 +0800 Subject: [PATCH 10/15] Remove unwanted change --- src/article_op.c | 7 +------ 1 file changed, 1 insertion(+), 6 deletions(-) diff --git a/src/article_op.c b/src/article_op.c index a3eb1246..e282ccbc 100644 --- a/src/article_op.c +++ b/src/article_op.c @@ -18,11 +18,6 @@ #include "screen.h" #include "user_priv.h" -enum ret_msg_len_t -{ - ret_msg_len = 20, -}; - int display_article_meta(int32_t aid) { clearscr(); @@ -234,7 +229,7 @@ int article_excerption_set(SECTION_LIST *p_section, int32_t aid, int8_t set) // Commit transaction if (mysql_query(db, "COMMIT") != 0) { - log_error("Mysqli error: %s\n", mysql_error(db)); + log_error("Mysqli error: %s", mysql_error(db)); // Rollback change to avoid data inconsistency if (section_list_rw_lock(p_section) < 0) From a52994cfefd5c623e95e520cd234ef57dab7c669 Mon Sep 17 00:00:00 2001 From: Leaflet Date: Sat, 20 Dec 2025 22:16:04 +0800 Subject: [PATCH 11/15] Add required header file --- src/article_op.c | 1 + 1 file changed, 1 insertion(+) diff --git a/src/article_op.c b/src/article_op.c index e282ccbc..8a221974 100644 --- a/src/article_op.c +++ b/src/article_op.c @@ -17,6 +17,7 @@ #include "log.h" #include "screen.h" #include "user_priv.h" +#include int display_article_meta(int32_t aid) { From 009dec11912a08c73dddf32c4903ae1286b32e41 Mon Sep 17 00:00:00 2001 From: Leaflet Date: Sun, 21 Dec 2025 20:28:48 +0800 Subject: [PATCH 12/15] Fix bug: checklevel2() should be called after load_user_info() --- src/login.c | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/login.c b/src/login.c index 3448006a..22141cfe 100644 --- a/src/login.c +++ b/src/login.c @@ -324,13 +324,6 @@ int check_user(const char *username, const char *password) goto cleanup; } - if (!SSH_v2 && checklevel2(&BBS_priv, P_MAN_S)) - { - prints("\033[1;31m非普通账户必须使用SSH方式登录\033[m\r\n"); - ret = 1; - goto cleanup; - } - ret = load_user_info(db, BBS_uid); switch (ret) @@ -353,6 +346,13 @@ int check_user(const char *username, const char *password) goto cleanup; } + if (!SSH_v2 && checklevel2(&BBS_priv, P_MAN_S)) + { + prints("\033[1;31m非普通账户必须使用SSH方式登录\033[m\r\n"); + ret = 1; + goto cleanup; + } + snprintf(sql, sizeof(sql), "UPDATE user_pubinfo SET visit_count = visit_count + 1, " "last_login_dt = NOW() WHERE UID = %d", From db201f499490bcfaa34c692e304137a955537962 Mon Sep 17 00:00:00 2001 From: Leaflet Date: Sun, 21 Dec 2025 20:42:49 +0800 Subject: [PATCH 13/15] User with special privilege is not allowed to re-confirm EULA in plain telnet mode. --- src/login.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) diff --git a/src/login.c b/src/login.c index 22141cfe..bdd967cd 100644 --- a/src/login.c +++ b/src/login.c @@ -329,12 +329,24 @@ int check_user(const char *username, const char *password) switch (ret) { case 0: // Login successfully + if (!SSH_v2 && checklevel2(&BBS_priv, P_MAN_S)) + { + prints("\033[1;31m非普通账户必须使用SSH方式登录\033[m\r\n"); + ret = 1; + goto cleanup; + } break; case -1: // Load data error prints("\033[1;31m读取用户数据错误...\033[m\r\n"); ret = -1; goto cleanup; case -2: // Enforce update user agreement + if (!SSH_v2 && checklevel2(&BBS_priv, P_MAN_S)) + { + prints("\033[1;31m非普通账户必须使用SSH方式登录\033[m\r\n"); + ret = 1; + goto cleanup; + } ret = 2; goto cleanup; case -3: // Dead @@ -346,13 +358,6 @@ int check_user(const char *username, const char *password) goto cleanup; } - if (!SSH_v2 && checklevel2(&BBS_priv, P_MAN_S)) - { - prints("\033[1;31m非普通账户必须使用SSH方式登录\033[m\r\n"); - ret = 1; - goto cleanup; - } - snprintf(sql, sizeof(sql), "UPDATE user_pubinfo SET visit_count = visit_count + 1, " "last_login_dt = NOW() WHERE UID = %d", From 250e4f77c7e7f7c11a66708e027a30a747ac7359 Mon Sep 17 00:00:00 2001 From: Leaflet Date: Mon, 22 Dec 2025 14:48:32 +0800 Subject: [PATCH 14/15] Refine --- src/bbs_net.c | 125 ++++++++++++++++++++++++++++++++++---------------- 1 file changed, 86 insertions(+), 39 deletions(-) diff --git a/src/bbs_net.c b/src/bbs_net.c index bf34d146..2501f5ba 100644 --- a/src/bbs_net.c +++ b/src/bbs_net.c @@ -45,12 +45,14 @@ #include #endif -static const char MENU_CONF_DELIM[] = " \t\r\n"; - enum _bbs_net_constant_t { MAXSTATION = 26 * 2, STATION_PER_LINE = 4, + ORG_NAME_MAX_LEN = 40, + SITE_NAME_MAX_LEN = 40, + HOSTNAME_MAX_LEN = 253, + PORT_STR_MAX_LEN = 5, USERNAME_MAX_LEN = 20, PASSWORD_MAX_LEN = 20, REMOTE_CONNECT_TIMEOUT = 10, // seconds @@ -60,25 +62,30 @@ enum _bbs_net_constant_t struct _bbsnet_conf { - char org_name[40]; - char site_name[40]; - char host_name[IP_ADDR_LEN]; - char port[6]; + char org_name[ORG_NAME_MAX_LEN + 1]; + char site_name[SITE_NAME_MAX_LEN + 1]; + char host_name[HOSTNAME_MAX_LEN + 1]; + char port[PORT_STR_MAX_LEN + 1]; int8_t use_ssh; char charset[CHARSET_MAX_LEN + 1]; } bbsnet_conf[MAXSTATION]; +static const char MENU_CONF_DELIM[] = " \t\r\n"; + static MENU_SET bbsnet_menu; static void unload_bbsnet_conf(void); static int load_bbsnet_conf(const char *file_config) { - FILE *fp; + FILE *fin; + int fin_line = 0; MENU *p_menu; MENU_ITEM *p_menu_item; MENU_ITEM_ID menu_item_id; - char line[LINE_BUFFER_LEN], *t1, *t2, *t3, *t4, *t5, *t6, *saveptr; + char line[LINE_BUFFER_LEN]; + char *p = NULL; + char *saveptr = NULL; long port; char *endptr; @@ -108,54 +115,92 @@ static int load_bbsnet_conf(const char *file_config) p_menu->title.show = 0; p_menu->screen_show = 0; - fp = fopen(file_config, "r"); - if (fp == NULL) + fin = fopen(file_config, "r"); + if (fin == NULL) { unload_bbsnet_conf(); return -2; } menu_item_id = 0; - while (fgets(line, sizeof(line), fp) && menu_item_id < MAXSTATION) + while (fgets(line, sizeof(line), fin) && menu_item_id < MAXSTATION) { - t1 = strtok_r(line, MENU_CONF_DELIM, &saveptr); - t2 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); - t3 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); - t4 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); - t5 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); - t6 = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); - - if (t1 == NULL || t2 == NULL || t3 == NULL || t4 == NULL || - t5 == NULL || t6 == NULL || t1[0] == '#') + fin_line++; + + p = strtok_r(line, MENU_CONF_DELIM, &saveptr); + if (p == NULL) // Blank line { continue; } - strncpy(bbsnet_conf[menu_item_id].site_name, t2, sizeof(bbsnet_conf[menu_item_id].site_name) - 1); - bbsnet_conf[menu_item_id].site_name[sizeof(bbsnet_conf[menu_item_id].site_name) - 1] = '\0'; - strncpy(bbsnet_conf[menu_item_id].org_name, t1, sizeof(bbsnet_conf[menu_item_id].org_name) - 1); + if (*p == '#' || *p == '\r' || *p == '\n') // Comment or blank line + { + continue; + } + + if (strlen(p) > sizeof(bbsnet_conf[menu_item_id].org_name) - 1) + { + log_error("Error org_name in BBSNET config line %d", fin_line); + continue; + } + strncpy(bbsnet_conf[menu_item_id].org_name, p, sizeof(bbsnet_conf[menu_item_id].org_name) - 1); bbsnet_conf[menu_item_id].org_name[sizeof(bbsnet_conf[menu_item_id].org_name) - 1] = '\0'; - strncpy(bbsnet_conf[menu_item_id].host_name, t3, sizeof(bbsnet_conf[menu_item_id].host_name) - 1); + + p = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); + if (p == NULL || strlen(p) > sizeof(bbsnet_conf[menu_item_id].site_name) - 1) + { + log_error("Error site_name in BBSNET config line %d", fin_line); + continue; + } + strncpy(bbsnet_conf[menu_item_id].site_name, p, sizeof(bbsnet_conf[menu_item_id].site_name) - 1); + bbsnet_conf[menu_item_id].site_name[sizeof(bbsnet_conf[menu_item_id].site_name) - 1] = '\0'; + + p = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); + if (p == NULL || strlen(p) > sizeof(bbsnet_conf[menu_item_id].host_name) - 1) + { + log_error("Error host_name in BBSNET config line %d", fin_line); + continue; + } + strncpy(bbsnet_conf[menu_item_id].host_name, p, sizeof(bbsnet_conf[menu_item_id].host_name) - 1); bbsnet_conf[menu_item_id].host_name[sizeof(bbsnet_conf[menu_item_id].host_name) - 1] = '\0'; - port = strtol(t4, &endptr, 10); + + p = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); + if (p == NULL || strlen(p) > sizeof(bbsnet_conf[menu_item_id].port) - 1) + { + log_error("Error port in BBSNET config line %d", fin_line); + continue; + } + port = strtol(p, &endptr, 10); if (*endptr != '\0' || port <= 0 || port > 65535) { - log_error("Invalid port value %ld of menu item %d", port, menu_item_id); - fclose(fp); - unload_bbsnet_conf(); - return -3; + log_error("Invalid port %ld in BBSNET config line %d", port, fin_line); + continue; } - strncpy(bbsnet_conf[menu_item_id].port, t4, sizeof(bbsnet_conf[menu_item_id].port) - 1); + strncpy(bbsnet_conf[menu_item_id].port, p, sizeof(bbsnet_conf[menu_item_id].port) - 1); bbsnet_conf[menu_item_id].port[sizeof(bbsnet_conf[menu_item_id].port) - 1] = '\0'; - bbsnet_conf[menu_item_id].use_ssh = (toupper(t5[0]) == 'Y'); - strncpy(bbsnet_conf[menu_item_id].charset, t6, sizeof(bbsnet_conf[menu_item_id].charset) - 1); + + p = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); + if (p == NULL || strlen(p) != 1) + { + log_error("Error use_ssh in BBSNET config line %d", fin_line); + continue; + } + bbsnet_conf[menu_item_id].use_ssh = (toupper(p[0]) == 'Y'); + + p = strtok_r(NULL, MENU_CONF_DELIM, &saveptr); + if (p == NULL || strlen(p) > sizeof(bbsnet_conf[menu_item_id].charset) - 1) + { + log_error("Error charset in BBSNET config line %d", fin_line); + continue; + } + strncpy(bbsnet_conf[menu_item_id].charset, p, sizeof(bbsnet_conf[menu_item_id].charset) - 1); bbsnet_conf[menu_item_id].charset[sizeof(bbsnet_conf[menu_item_id].charset) - 1] = '\0'; p_menu_item = get_menu_item_by_id(&bbsnet_menu, menu_item_id); if (p_menu_item == NULL) { - log_error("get_menu_item_by_id(%d) return NULL pointer", menu_item_id); - fclose(fp); + log_error("get_menu_item_by_id(%d) error: NULL pointer", menu_item_id); + fclose(fin); unload_bbsnet_conf(); return -3; } @@ -182,7 +227,7 @@ static int load_bbsnet_conf(const char *file_config) bbsnet_menu.menu_item_pos[0] = 0; bbsnet_menu.choose_step = 0; - fclose(fp); + fclose(fin); return 0; } @@ -359,8 +404,9 @@ static int bbsnet_connect(int n) } moveto(1, 1); - prints("通过SSH方式连接[%s]...", bbsnet_conf[n].site_name); - moveto(2, 1); + prints("\033[1;32m正在准备往 %s (%s:%s) 的%s连接... \033[m\r\n", + bbsnet_conf[n].site_name, bbsnet_conf[n].host_name, bbsnet_conf[n].port, + (bbsnet_conf[n].use_ssh ? "SSH" : "Telnet")); prints("请输入用户名: "); iflush(); if (str_input(remote_user, sizeof(remote_user), DOECHO) < 0) @@ -388,8 +434,9 @@ static int bbsnet_connect(int n) clearscr(); moveto(1, 1); - prints("\033[1;32m正在测试往 %s (%s) 的连接,请稍候... \033[m\r\n", - bbsnet_conf[n].site_name, bbsnet_conf[n].host_name); + prints("\033[1;32m正在测试往 %s (%s:%s) 的%s连接,请稍候... \033[m\r\n", + bbsnet_conf[n].site_name, bbsnet_conf[n].host_name, bbsnet_conf[n].port, + (bbsnet_conf[n].use_ssh ? "SSH" : "Telnet")); prints("\033[1;32m连接进行中,按\033[1;33mCtrl+C\033[1;32m中断。\033[m\r\n"); progress_bar(0, PROGRESS_BAR_LEN); From a731472e54e8aae9e7908e5e69baadcce1111451 Mon Sep 17 00:00:00 2001 From: Leaflet Date: Tue, 23 Dec 2025 21:07:21 +0800 Subject: [PATCH 15/15] Refact handling of cmdline arguments --- src/main.c | 162 ++++++++++++++++++++++++++++------------------------- 1 file changed, 87 insertions(+), 75 deletions(-) diff --git a/src/main.c b/src/main.c index 7ba0952b..51169b05 100644 --- a/src/main.c +++ b/src/main.c @@ -34,25 +34,78 @@ #include #include -static inline void app_help(void) +typedef void (*arg_option_handler_t)(void); + +struct arg_option_t +{ + const char *short_arg; + const char *long_arg; + const char *description; + arg_option_handler_t handler; +}; +typedef struct arg_option_t ARG_OPTION; + +static void arg_foreground(void); +static void arg_help(void); +static void arg_version(void); +static void arg_display_log(void); +static void arg_display_error_log(void); +static void arg_compile_info(void); +static void arg_error(void); + +static const ARG_OPTION arg_options[] = { + {"-f", "--foreground", "Run in foreground", arg_foreground}, + {"-h", "--help", "Display help message", arg_help}, + {"-v", "--version", "Display version information", arg_version}, + {NULL, "--display-log", "Display standard log information", arg_display_log}, + {NULL, "--display-error-log", "Display error log information", arg_display_error_log}, + {"-C", "--compile-config", "Display compile configuration", arg_compile_info}}; + +static const int arg_options_count = sizeof(arg_options) / sizeof(ARG_OPTION); + +static int daemon_service = 1; +static int std_log_redir = 0; +static int error_log_redir = 0; + +static void arg_foreground(void) { - fprintf(stderr, "Usage: bbsd [-fhv] [...]\n\n" - "-f\t--foreground\t\tForce program run in foreground\n" - "-h\t--help\t\t\tDisplay this help message\n" - "-v\t--version\t\tDisplay version information\n" - "\t--display-log\t\tDisplay standard log information\n" - "\t--display-error-log\tDisplay error log information\n" - "-C\t--compile-config\tDisplay compile configuration\n" - "\n If meet any bug, please report to \n\n"); + daemon_service = 0; } -static inline void arg_error(void) +static void arg_help(void) { - fprintf(stderr, "Invalid arguments\n"); - app_help(); + fprintf(stderr, "Usage: bbsd [-fhv] [...]\n\n"); + + for (int i = 0; i < arg_options_count; i++) + { + fprintf(stderr, "%s%*s%s%*s%s\n", + arg_options[i].short_arg ? arg_options[i].short_arg : "", + 8 - (arg_options[i].short_arg ? (int)strlen(arg_options[i].short_arg) : 0), "", + arg_options[i].long_arg ? arg_options[i].long_arg : "", + 24 - (arg_options[i].long_arg ? (int)strlen(arg_options[i].long_arg) : 0), "", + arg_options[i].description ? arg_options[i].description : ""); + } + + fprintf(stderr, "\n If meet any bug, please report to \n\n"); +} + +static void arg_version(void) +{ + printf("%s\n", APP_INFO); + printf("%s\n", COPYRIGHT_INFO); +} + +static void arg_display_log(void) +{ + std_log_redir = 1; +} + +static void arg_display_error_log(void) +{ + error_log_redir = 1; } -static inline void app_compile_info(void) +static void arg_compile_info(void) { printf("%s\n" "--enable-shared\t\t[%s]\n" @@ -95,12 +148,15 @@ static inline void app_compile_info(void) ); } +static void arg_error(void) +{ + fprintf(stderr, "Invalid arguments\n"); + arg_help(); +} + int main(int argc, char *argv[]) { char file_path_temp[FILE_PATH_LEN]; - int daemon = 1; - int std_log_redir = 0; - int error_log_redir = 0; FILE *fp; int ret; int last_aid; @@ -112,72 +168,28 @@ int main(int argc, char *argv[]) // Parse args for (i = 1; i < argc; i++) { - switch (argv[i][0]) + for (j = 0; j < arg_options_count; j++) { - case '-': - if (argv[i][1] != '-') + if (arg_options[j].short_arg && strcmp(argv[i], arg_options[j].short_arg) == 0) { - for (j = 1; j < strlen(argv[i]); j++) - { - switch (argv[i][j]) - { - case 'f': - daemon = 0; - break; - case 'h': - app_help(); - return 0; - case 'v': - printf("%s\n", APP_INFO); - printf("%s\n", COPYRIGHT_INFO); - return 0; - case 'C': - app_compile_info(); - return 0; - default: - arg_error(); - return 1; - } - } + arg_options[j].handler(); + break; } - else + else if (arg_options[j].long_arg && strcmp(argv[i], arg_options[j].long_arg) == 0) { - if (strcmp(argv[i] + 2, "foreground") == 0) - { - daemon = 0; - break; - } - if (strcmp(argv[i] + 2, "help") == 0) - { - app_help(); - return 0; - } - if (strcmp(argv[i] + 2, "version") == 0) - { - printf("%s\n", APP_INFO); - printf("%s\n", COPYRIGHT_INFO); - return 0; - } - if (strcmp(argv[i] + 2, "display-log") == 0) - { - std_log_redir = 1; - } - if (strcmp(argv[i] + 2, "display-error-log") == 0) - { - error_log_redir = 1; - } - if (strcmp(argv[i] + 2, "compile-config") == 0) - { - app_compile_info(); - return 0; - } + arg_options[j].handler(); + break; } - break; + } + if (j == arg_options_count) + { + arg_error(); + return -1; } } // Initialize daemon - if (daemon) + if (daemon_service) { init_daemon(); } @@ -210,11 +222,11 @@ int main(int argc, char *argv[]) return -1; } - if ((!daemon) && std_log_redir) + if ((!daemon_service) && std_log_redir) { log_common_redir(STDERR_FILENO); } - if ((!daemon) && error_log_redir) + if ((!daemon_service) && error_log_redir) { log_error_redir(STDERR_FILENO); }