/[LeafOK_CVS]/lbbs/src/bbs_main.c
ViewVC logotype

Contents of /lbbs/src/bbs_main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.123 - (show annotations)
Sat Jan 3 10:27:14 2026 UTC (2 months, 1 week ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.122: +1 -1 lines
Content type: text/x-csrc
Update copyright info

1 /* SPDX-License-Identifier: GPL-3.0-or-later */
2 /*
3 * bbs_main
4 * - entry and major procedures of user interactive access
5 *
6 * Copyright (C) 2004-2026 Leaflet <leaflet@leafok.com>
7 */
8
9 #ifdef HAVE_CONFIG_H
10 #include "config.h"
11 #endif
12
13 #include "article_favor.h"
14 #include "article_view_log.h"
15 #include "bbs.h"
16 #include "bbs_cmd.h"
17 #include "bbs_main.h"
18 #include "bwf.h"
19 #include "common.h"
20 #include "database.h"
21 #include "editor.h"
22 #include "io.h"
23 #include "log.h"
24 #include "login.h"
25 #include "menu.h"
26 #include "screen.h"
27 #include "section_list.h"
28 #include "section_list_display.h"
29 #include "str_process.h"
30 #include "trie_dict.h"
31 #include "user_list.h"
32 #include "user_priv.h"
33 #include <ctype.h>
34 #include <errno.h>
35 #include <signal.h>
36 #include <stdlib.h>
37 #include <string.h>
38 #include <time.h>
39 #include <unistd.h>
40
41 static void child_proc_sig_usr1_handler(int i)
42 {
43 // Restart log
44 if (log_restart() < 0)
45 {
46 log_error("Restart logging failed");
47 }
48 }
49
50 int bbs_info()
51 {
52 prints("\r\n欢迎光临 \033[1;33m%s \033[32m[%s] \033[37m(%s)\033[m\r\n",
53 BBS_name, BBS_server, APP_INFO);
54
55 return iflush();
56 }
57
58 int bbs_welcome(void)
59 {
60 int u_online = 0;
61 int u_anonymous = 0;
62 int u_total = 0;
63 int u_login_count = 0;
64
65 if (get_user_online_list_count(&u_online, &u_anonymous) < 0)
66 {
67 log_error("get_user_online_list_count() error");
68 u_online = 0;
69 }
70 u_online += u_anonymous;
71 u_online++; // current user
72 if (BBS_priv.uid == 0)
73 {
74 u_anonymous++;
75 }
76
77 if (get_user_list_count(&u_total) < 0)
78 {
79 log_error("get_user_list_count() error");
80 u_total = 0;
81 }
82
83 if (get_user_login_count(&u_login_count) < 0)
84 {
85 log_error("get_user_login_count() error");
86 u_login_count = 0;
87 }
88
89 // Display logo
90 display_file(DATA_WELCOME, 2);
91
92 // Display welcome message
93 prints("\r\033[1;35m欢迎光临\033[33m 【 %s 】 \033[35mBBS\r\n"
94 "\033[32m目前上站人数 [\033[36m%d/%d\033[32m] "
95 "匿名游客[\033[36m%d\033[32m] "
96 "注册用户数[\033[36m%d/%d\033[32m]\r\n"
97 "从 [\033[36m%s\033[32m] 起,累计访问人次: [\033[36m%d\033[32m]\033[m\r\n",
98 BBS_name, u_online, BBS_max_client, u_anonymous, u_total,
99 BBS_max_user_count, BBS_start_dt, u_login_count);
100
101 iflush();
102
103 return 0;
104 }
105
106 int bbs_logout(void)
107 {
108 MYSQL *db;
109
110 db = db_open();
111 if (db == NULL)
112 {
113 return -1;
114 }
115
116 if (user_online_exp(db) < 0)
117 {
118 return -2;
119 }
120
121 mysql_close(db);
122
123 display_file(DATA_GOODBYE, 1);
124
125 log_common("User [%s] (uid=%d) logout, idle for %ld seconds since last input",
126 BBS_username, BBS_priv.uid, time(NULL) - BBS_last_access_tm);
127
128 return 0;
129 }
130
131 int bbs_session_cleanup(void)
132 {
133 MYSQL *db;
134
135 db = db_open();
136 if (db == NULL)
137 {
138 return -1;
139 }
140
141 if (user_online_del(db) < 0)
142 {
143 return -2;
144 }
145
146 mysql_close(db);
147
148 return 0;
149 }
150
151 int bbs_center()
152 {
153 int ch;
154 int loop;
155 time_t t_last_action;
156
157 BBS_last_access_tm = t_last_action = time(NULL);
158
159 clearscr();
160
161 show_top("", BBS_name, "");
162 show_active_board();
163 show_bottom("");
164 display_menu(&bbs_menu);
165 iflush();
166
167 for (loop = 1; !SYS_server_exit && loop;)
168 {
169 ch = igetch(100);
170
171 if (ch != KEY_NULL && ch != KEY_TIMEOUT)
172 {
173 BBS_last_access_tm = time(NULL);
174 log_debug("Debug: BBS_last_access_tm is updated");
175 }
176
177 if (bbs_menu.choose_step == 0 && time(NULL) - t_last_action >= 10)
178 {
179 t_last_action = time(NULL);
180
181 show_active_board();
182 show_bottom("");
183 display_menu_cursor(&bbs_menu, 1);
184 iflush();
185 }
186
187 if (user_online_update("MENU") < 0)
188 {
189 log_error("user_online_update(MENU) error");
190 }
191
192 switch (ch)
193 {
194 case KEY_NULL: // broken pipe
195 log_debug("KEY_NULL");
196 loop = 0;
197 break;
198 case KEY_TIMEOUT:
199 if (time(NULL) - BBS_last_access_tm >= BBS_max_user_idle_time)
200 {
201 log_debug("User input timeout");
202 loop = 0;
203 break;
204 }
205 continue;
206 case CR:
207 default:
208 switch (menu_control(&bbs_menu, ch))
209 {
210 case EXITBBS:
211 case EXITMENU:
212 loop = 0;
213 break;
214 case REDRAW:
215 t_last_action = time(NULL);
216 clearscr();
217 show_top("", BBS_name, "");
218 show_active_board();
219 show_bottom("");
220 display_menu(&bbs_menu);
221 break;
222 case NOREDRAW:
223 case UNKNOWN_CMD:
224 default:
225 break;
226 }
227 iflush();
228 }
229 }
230
231 return 0;
232 }
233
234 int bbs_charset_select()
235 {
236 char msg[LINE_BUFFER_LEN];
237 int ch;
238
239 snprintf(msg, sizeof(msg),
240 "\rChoose character set in 5 seconds, (U)UTF-8, (G)GBK [U]: ");
241
242 while (!SYS_server_exit)
243 {
244 ch = press_any_key_ex(msg, 5);
245 switch (toupper(ch))
246 {
247 case KEY_NULL:
248 return -1;
249 case KEY_TIMEOUT:
250 case CR:
251 case 'U':
252 break;
253 case 'G':
254 if (io_conv_init("GBK") < 0)
255 {
256 log_error("io_conv_init(%s) error", "GBK");
257 return -1;
258 }
259 break;
260 default:
261 continue;
262 }
263
264 break;
265 }
266
267 snprintf(msg, sizeof(msg),
268 "\r请在5秒内选择宽字符显示规则, (V)变宽, (F)定宽? [V]: ");
269
270 while (!SYS_server_exit)
271 {
272 ch = press_any_key_ex(msg, 5);
273 switch (toupper(ch))
274 {
275 case KEY_NULL:
276 return -1;
277 case KEY_TIMEOUT:
278 case CR:
279 case 'V':
280 UTF8_fixed_width = 0;
281 break;
282 case 'F':
283 UTF8_fixed_width = 1;
284 break;
285 default:
286 continue;
287 }
288
289 break;
290 }
291
292 return 0;
293 }
294
295 int bbs_main()
296 {
297 struct sigaction act = {0};
298 char msg[LINE_BUFFER_LEN];
299
300 // Set signal handler
301 act.sa_handler = SIG_IGN;
302 if (sigaction(SIGHUP, &act, NULL) == -1)
303 {
304 log_error("set signal action of SIGHUP error: %d", errno);
305 goto cleanup;
306 }
307 act.sa_handler = SIG_DFL;
308 if (sigaction(SIGCHLD, &act, NULL) == -1)
309 {
310 log_error("set signal action of SIGCHLD error: %d", errno);
311 goto cleanup;
312 }
313 act.sa_handler = child_proc_sig_usr1_handler;
314 if (sigaction(SIGUSR1, &act, NULL) == -1)
315 {
316 log_error("set signal action of SIGUSR1 error: %d", errno);
317 goto cleanup;
318 }
319
320 // Set data pools in shared memory readonly
321 if (set_trie_dict_shm_readonly() < 0)
322 {
323 goto cleanup;
324 }
325 if (set_article_block_shm_readonly() < 0)
326 {
327 goto cleanup;
328 }
329 #ifdef HAVE_SYSTEM_V
330 if (set_section_list_shm_readonly() < 0)
331 {
332 goto cleanup;
333 }
334 if (set_user_list_pool_shm_readonly() < 0)
335 {
336 goto cleanup;
337 }
338 #endif
339
340 // Load menu in shared memory
341 if (set_menu_shm_readonly(&bbs_menu) < 0)
342 {
343 goto cleanup;
344 }
345
346 // Set default charset
347 if (io_conv_init(BBS_default_charset) < 0)
348 {
349 log_error("io_conv_init(%s) error", BBS_default_charset);
350 goto cleanup;
351 }
352
353 set_input_echo(0);
354
355 // Set user charset
356 if (bbs_charset_select() < 0)
357 {
358 goto cleanup;
359 }
360
361 // System info
362 if (bbs_info() < 0)
363 {
364 goto cleanup;
365 }
366
367 // Welcome
368 if (bbs_welcome() < 0)
369 {
370 goto cleanup;
371 }
372
373 // User login
374 if (SSH_v2)
375 {
376 snprintf(msg, sizeof(msg), "\033[1m%s 欢迎使用ssh方式访问 \033[1;33m按任意键继续...\033[m", BBS_username);
377 press_any_key_ex(msg, 60);
378 }
379 else if (bbs_login() < 0)
380 {
381 goto cleanup;
382 }
383 log_common("User [%s] (uid=%d) login from %s:%d",
384 BBS_username, BBS_priv.uid, hostaddr_client, port_client);
385
386 // Check EULA update status
387 if (BBS_update_eula)
388 {
389 user_update_agreement();
390 goto cleanup;
391 }
392
393 // Load section aid locations
394 if (section_aid_locations_load(BBS_priv.uid) < 0)
395 {
396 log_error("article_view_log_load() error");
397 goto cleanup;
398 }
399
400 // Load article view log
401 if (article_view_log_load(BBS_priv.uid, &BBS_article_view_log, 0) < 0)
402 {
403 log_error("article_view_log_load() error");
404 goto cleanup;
405 }
406
407 // Load article favorite
408 if (article_favor_load(BBS_priv.uid, &BBS_article_favor, 0) < 0)
409 {
410 log_error("article_favor_load() error");
411 goto cleanup;
412 }
413
414 // Init editor memory pool
415 if (editor_memory_pool_init() < 0)
416 {
417 log_error("editor_memory_pool_init() error");
418 goto cleanup;
419 }
420
421 clearscr();
422
423 // BBS Top 10
424 display_file(VAR_BBS_TOP, 1);
425
426 // Main
427 bbs_center();
428
429 // Logout
430 bbs_logout();
431
432 // Save section aid locations
433 if (section_aid_locations_save(BBS_priv.uid) < 0)
434 {
435 log_error("article_view_log_save() error");
436 }
437
438 // Save incremental article view log
439 if (article_view_log_save_inc(&BBS_article_view_log) < 0)
440 {
441 log_error("article_view_log_save_inc() error");
442 }
443
444 // Save incremental article favorite
445 if (article_favor_save_inc(&BBS_article_favor) < 0)
446 {
447 log_error("article_favor_save_inc() error");
448 }
449
450 cleanup:
451 // Cleanup session
452 bbs_session_cleanup();
453
454 // Cleanup iconv
455 io_conv_cleanup();
456
457 // Cleanup editor memory pool
458 editor_memory_pool_cleanup();
459
460 // Unload article view log
461 article_view_log_unload(&BBS_article_view_log);
462
463 // Unload article favor
464 article_favor_unload(&BBS_article_favor);
465
466 // Detach menu in shared memory
467 detach_menu_shm(&bbs_menu);
468 detach_menu_shm(&top10_menu);
469
470 // Detach data pools shm
471 detach_user_list_pool_shm();
472 detach_section_list_shm();
473 detach_article_block_shm();
474 detach_trie_dict_shm();
475
476 // Cleanup BWF
477 bwf_cleanup();
478
479 return 0;
480 }

webmaster@leafok.com
ViewVC Help
Powered by ViewVC 1.3.0-beta1