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

Annotation of /lbbs/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.91 - (hide annotations)
Fri Dec 19 14:08:44 2025 UTC (2 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.90: +12 -0 lines
Content type: text/x-csrc
Use hash_dict for tag_name search
Fix bug for over-length tag_param

1 sysadm 1.69 /* SPDX-License-Identifier: GPL-3.0-or-later */
2     /*
3     * main
4     * - entry of server program
5     *
6 sysadm 1.70 * Copyright (C) 2004-2025 Leaflet <leaflet@leafok.com>
7 sysadm 1.69 */
8 sysadm 1.1
9 sysadm 1.74 #ifdef HAVE_CONFIG_H
10     #include "config.h"
11     #endif
12    
13 sysadm 1.4 #include "bbs.h"
14 sysadm 1.72 #include "bwf.h"
15 sysadm 1.55 #include "common.h"
16     #include "file_loader.h"
17 sysadm 1.20 #include "init.h"
18 sysadm 1.55 #include "io.h"
19 sysadm 1.91 #include "lml.h"
20 sysadm 1.20 #include "log.h"
21 sysadm 1.9 #include "menu.h"
22 sysadm 1.55 #include "net_server.h"
23 sysadm 1.42 #include "section_list_loader.h"
24 sysadm 1.63 #include "user_list.h"
25 sysadm 1.48 #include <errno.h>
26 sysadm 1.55 #include <libgen.h>
27 sysadm 1.73 #include <locale.h>
28 sysadm 1.55 #include <signal.h>
29 sysadm 1.56 #include <stdio.h>
30 sysadm 1.20 #include <stdlib.h>
31 sysadm 1.7 #include <string.h>
32 sysadm 1.20 #include <unistd.h>
33 sysadm 1.55 #include <sys/stat.h>
34 sysadm 1.15 #include <sys/types.h>
35 sysadm 1.80 #include <sys/wait.h>
36 sysadm 1.1
37 sysadm 1.87 static inline void app_help(void)
38 sysadm 1.6 {
39 sysadm 1.56 fprintf(stderr, "Usage: bbsd [-fhv] [...]\n\n"
40     "-f\t--foreground\t\tForce program run in foreground\n"
41     "-h\t--help\t\t\tDisplay this help message\n"
42     "-v\t--version\t\tDisplay version information\n"
43     "\t--display-log\t\tDisplay standard log information\n"
44     "\t--display-error-log\tDisplay error log information\n"
45 sysadm 1.87 "-C\t--compile-config\tDisplay compile configuration\n"
46 sysadm 1.56 "\n If meet any bug, please report to <leaflet@leafok.com>\n\n");
47 sysadm 1.6 }
48    
49 sysadm 1.87 static inline void arg_error(void)
50 sysadm 1.6 {
51 sysadm 1.56 fprintf(stderr, "Invalid arguments\n");
52 sysadm 1.18 app_help();
53 sysadm 1.6 }
54    
55 sysadm 1.87 static inline void app_compile_info(void)
56     {
57     printf("%s\n"
58     "--enable-shared\t\t[%s]\n"
59     "--enable-systemd\t[%s]\n"
60     "--with-debug\t\t[%s]\n"
61     "--with-epoll\t\t[%s]\n"
62     "--with-mariadb\t\t[%s]\n"
63     "--with-sysv\t\t[%s]\n",
64     APP_INFO,
65     #ifdef _ENABLE_SHARED
66     "yes",
67     #else
68     "no",
69     #endif
70     #ifdef HAVE_SYSTEMD_SD_DAEMON_H
71     "yes",
72     #else
73     "no",
74     #endif
75     #ifdef _DEBUG
76     "yes",
77     #else
78     "no",
79     #endif
80     #ifdef HAVE_SYS_EPOLL_H
81     "yes",
82     #else
83     "no",
84     #endif
85     #ifdef HAVE_MARIADB_CLIENT
86     "yes",
87     #else
88     "no",
89     #endif
90     #ifdef HAVE_SYSTEM_V
91     "yes"
92     #else
93     "no"
94     #endif
95     );
96     }
97    
98 sysadm 1.18 int main(int argc, char *argv[])
99 sysadm 1.1 {
100 sysadm 1.21 char file_path_temp[FILE_PATH_LEN];
101     int daemon = 1;
102     int std_log_redir = 0;
103     int error_log_redir = 0;
104 sysadm 1.42 FILE *fp;
105 sysadm 1.47 int ret;
106     int last_aid;
107 sysadm 1.52 struct sigaction act = {0};
108 sysadm 1.80 int i;
109     int j;
110 sysadm 1.88 struct stat file_stat;
111 sysadm 1.18
112     // Parse args
113 sysadm 1.80 for (i = 1; i < argc; i++)
114 sysadm 1.12 {
115 sysadm 1.18 switch (argv[i][0])
116 sysadm 1.12 {
117 sysadm 1.18 case '-':
118     if (argv[i][1] != '-')
119     {
120 sysadm 1.80 for (j = 1; j < strlen(argv[i]); j++)
121 sysadm 1.18 {
122     switch (argv[i][j])
123     {
124     case 'f':
125     daemon = 0;
126     break;
127     case 'h':
128     app_help();
129 sysadm 1.30 return 0;
130 sysadm 1.18 case 'v':
131 sysadm 1.77 printf("%s\n", APP_INFO);
132     printf("%s\n", COPYRIGHT_INFO);
133 sysadm 1.30 return 0;
134 sysadm 1.87 case 'C':
135     app_compile_info();
136     return 0;
137 sysadm 1.18 default:
138     arg_error();
139 sysadm 1.30 return 1;
140 sysadm 1.18 }
141     }
142     }
143     else
144     {
145     if (strcmp(argv[i] + 2, "foreground") == 0)
146     {
147     daemon = 0;
148     break;
149     }
150     if (strcmp(argv[i] + 2, "help") == 0)
151     {
152     app_help();
153 sysadm 1.30 return 0;
154 sysadm 1.18 }
155     if (strcmp(argv[i] + 2, "version") == 0)
156     {
157 sysadm 1.76 printf("%s\n", APP_INFO);
158     printf("%s\n", COPYRIGHT_INFO);
159 sysadm 1.30 return 0;
160 sysadm 1.18 }
161     if (strcmp(argv[i] + 2, "display-log") == 0)
162     {
163     std_log_redir = 1;
164     }
165     if (strcmp(argv[i] + 2, "display-error-log") == 0)
166     {
167     error_log_redir = 1;
168     }
169 sysadm 1.87 if (strcmp(argv[i] + 2, "compile-config") == 0)
170     {
171     app_compile_info();
172     return 0;
173     }
174 sysadm 1.18 }
175     break;
176 sysadm 1.12 }
177     }
178    
179 sysadm 1.18 // Initialize daemon
180     if (daemon)
181 sysadm 1.20 {
182 sysadm 1.31 init_daemon();
183 sysadm 1.20 }
184 sysadm 1.18
185     // Change current dir
186 sysadm 1.21 strncpy(file_path_temp, argv[0], sizeof(file_path_temp) - 1);
187 sysadm 1.22 file_path_temp[sizeof(file_path_temp) - 1] = '\0';
188    
189 sysadm 1.61 if (chdir(dirname(file_path_temp)) < 0)
190     {
191     fprintf(stderr, "chdir(%s) error: %d\n", dirname(file_path_temp), errno);
192     return -1;
193     }
194     if (chdir("..") < 0)
195     {
196     fprintf(stderr, "chdir(..) error: %d\n", errno);
197     return -1;
198     }
199 sysadm 1.18
200 sysadm 1.73 // Apply the specified locale
201     if (setlocale(LC_ALL, "en_US.UTF-8") == NULL)
202     {
203     fprintf(stderr, "setlocale(LC_ALL, en_US.UTF-8) error\n");
204     return -1;
205     }
206    
207 sysadm 1.18 // Initialize log
208 sysadm 1.21 if (log_begin(LOG_FILE_INFO, LOG_FILE_ERROR) < 0)
209     {
210 sysadm 1.30 return -1;
211 sysadm 1.21 }
212 sysadm 1.18
213     if ((!daemon) && std_log_redir)
214 sysadm 1.21 {
215 sysadm 1.50 log_common_redir(STDERR_FILENO);
216 sysadm 1.21 }
217 sysadm 1.18 if ((!daemon) && error_log_redir)
218 sysadm 1.21 {
219 sysadm 1.50 log_error_redir(STDERR_FILENO);
220 sysadm 1.21 }
221 sysadm 1.18
222 sysadm 1.90 log_common("Starting %s", APP_INFO);
223 sysadm 1.51
224 sysadm 1.18 // Load configuration
225 sysadm 1.26 if (load_conf(CONF_BBSD) < 0)
226     {
227 sysadm 1.30 return -2;
228 sysadm 1.26 }
229 sysadm 1.18
230 sysadm 1.72 // Load BWF config
231     if (bwf_load(CONF_BWF) < 0)
232     {
233     return -2;
234     }
235    
236 sysadm 1.88 // Get EULA modification tm
237     if (stat(DATA_EULA, &file_stat) == -1)
238     {
239 sysadm 1.90 log_error("stat(%s) error", DATA_EULA, errno);
240 sysadm 1.88 goto cleanup;
241     }
242     BBS_eula_tm = file_stat.st_mtim.tv_sec;
243    
244 sysadm 1.48 // Check article cache dir
245 sysadm 1.49 ret = mkdir(VAR_ARTICLE_CACHE_DIR, 0750);
246 sysadm 1.48 if (ret == -1 && errno != EEXIST)
247     {
248 sysadm 1.90 log_error("mkdir(%s) error (%d)", VAR_ARTICLE_CACHE_DIR, errno);
249 sysadm 1.48 goto cleanup;
250     }
251    
252 sysadm 1.68 // Check section aid location dir
253     ret = mkdir(VAR_SECTION_AID_LOC_DIR, 0750);
254     if (ret == -1 && errno != EEXIST)
255     {
256 sysadm 1.90 log_error("mkdir(%s) error (%d)", VAR_SECTION_AID_LOC_DIR, errno);
257 sysadm 1.68 goto cleanup;
258     }
259    
260 sysadm 1.42 // Initialize data pools
261 sysadm 1.63 if ((fp = fopen(VAR_ARTICLE_BLOCK_SHM, "w")) == NULL)
262     {
263 sysadm 1.90 log_error("fopen(%s) error", VAR_ARTICLE_BLOCK_SHM);
264 sysadm 1.63 goto cleanup;
265     }
266     fclose(fp);
267     if ((fp = fopen(VAR_SECTION_LIST_SHM, "w")) == NULL)
268 sysadm 1.42 {
269 sysadm 1.90 log_error("fopen(%s) error", VAR_SECTION_LIST_SHM);
270 sysadm 1.43 goto cleanup;
271 sysadm 1.42 }
272     fclose(fp);
273 sysadm 1.63 if ((fp = fopen(VAR_TRIE_DICT_SHM, "w")) == NULL)
274 sysadm 1.42 {
275 sysadm 1.90 log_error("fopen(%s) error", VAR_TRIE_DICT_SHM);
276 sysadm 1.43 goto cleanup;
277 sysadm 1.42 }
278     fclose(fp);
279 sysadm 1.63 if ((fp = fopen(VAR_USER_LIST_SHM, "w")) == NULL)
280 sysadm 1.42 {
281 sysadm 1.90 log_error("fopen(%s) error", VAR_USER_LIST_SHM);
282 sysadm 1.43 goto cleanup;
283 sysadm 1.42 }
284     fclose(fp);
285    
286     if (trie_dict_init(VAR_TRIE_DICT_SHM, TRIE_NODE_PER_POOL) < 0)
287 sysadm 1.39 {
288 sysadm 1.90 log_error("trie_dict_init(%s, %d) error", VAR_TRIE_DICT_SHM, TRIE_NODE_PER_POOL);
289 sysadm 1.43 goto cleanup;
290 sysadm 1.39 }
291 sysadm 1.71 if (article_block_init(VAR_ARTICLE_BLOCK_SHM, BBS_article_limit_per_section * BBS_max_section / BBS_article_count_per_block) < 0)
292 sysadm 1.42 {
293 sysadm 1.90 log_error("article_block_init(%s, %d) error", VAR_ARTICLE_BLOCK_SHM, BBS_article_limit_per_section * BBS_max_section / BBS_article_count_per_block);
294 sysadm 1.43 goto cleanup;
295 sysadm 1.42 }
296     if (section_list_init(VAR_SECTION_LIST_SHM) < 0)
297     {
298 sysadm 1.90 log_error("section_list_pool_init(%s) error", VAR_SECTION_LIST_SHM);
299 sysadm 1.43 goto cleanup;
300 sysadm 1.42 }
301 sysadm 1.39
302 sysadm 1.91 // Init LML module
303     if (lml_init() < 0)
304     {
305     log_error("lml_init() error");
306     goto cleanup;
307     }
308    
309 sysadm 1.36 // Load BBS cmd
310     if (load_cmd() < 0)
311     {
312 sysadm 1.91 log_error("load_cmd() error");
313 sysadm 1.43 goto cleanup;
314 sysadm 1.36 }
315    
316 sysadm 1.18 // Load menus
317 sysadm 1.59 if (load_menu(&bbs_menu, CONF_MENU) < 0)
318 sysadm 1.32 {
319 sysadm 1.90 log_error("load_menu(bbs_menu) error");
320 sysadm 1.43 goto cleanup;
321 sysadm 1.26 }
322 sysadm 1.62 if (load_menu(&top10_menu, CONF_TOP10_MENU) < 0)
323     {
324 sysadm 1.90 log_error("load_menu(top10_menu) error");
325 sysadm 1.62 goto cleanup;
326     }
327     top10_menu.allow_exit = 1;
328 sysadm 1.18
329 sysadm 1.34 // Load data files
330     for (int i = 0; i < data_files_load_startup_count; i++)
331     {
332 sysadm 1.39 if (load_file(data_files_load_startup[i]) < 0)
333 sysadm 1.34 {
334 sysadm 1.90 log_error("load_file(%s) error", data_files_load_startup[i]);
335 sysadm 1.34 }
336     }
337    
338 sysadm 1.64 // Load user_list and online_user_list
339 sysadm 1.66 if (user_list_pool_init(VAR_USER_LIST_SHM) < 0)
340 sysadm 1.64 {
341 sysadm 1.90 log_error("user_list_pool_init(%s) error", VAR_USER_LIST_SHM);
342 sysadm 1.64 goto cleanup;
343     }
344     if (user_list_pool_reload(0) < 0)
345     {
346 sysadm 1.90 log_error("user_list_pool_reload(all_user) error");
347 sysadm 1.64 goto cleanup;
348     }
349     if (user_list_pool_reload(1) < 0)
350     {
351 sysadm 1.90 log_error("user_list_pool_reload(online_user) error");
352 sysadm 1.64 goto cleanup;
353     }
354    
355 sysadm 1.60 // Load section config and gen_ex
356     if (load_section_config_from_db(1) < 0)
357 sysadm 1.42 {
358 sysadm 1.90 log_error("load_section_config_from_db(0) error");
359 sysadm 1.43 goto cleanup;
360 sysadm 1.42 }
361    
362 sysadm 1.46 set_last_article_op_log_from_db();
363 sysadm 1.47 last_aid = 0;
364    
365 sysadm 1.45 // Load section articles
366 sysadm 1.47 do
367 sysadm 1.43 {
368 sysadm 1.47 if ((ret = append_articles_from_db(last_aid + 1, 1, LOAD_ARTICLE_COUNT_LIMIT)) < 0)
369     {
370 sysadm 1.90 log_error("append_articles_from_db(0, 1, %d) error", LOAD_ARTICLE_COUNT_LIMIT);
371 sysadm 1.47 goto cleanup;
372     }
373    
374     last_aid = article_block_last_aid();
375     } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
376 sysadm 1.43
377 sysadm 1.90 log_common("Initially load %d articles, last_aid = %d", article_block_article_count(), article_block_last_aid());
378 sysadm 1.43
379 sysadm 1.65 if ((ret = user_stat_update()) < 0)
380     {
381 sysadm 1.90 log_error("user_stat_update() error");
382 sysadm 1.65 goto cleanup;
383     }
384    
385 sysadm 1.18 // Set signal handler
386 sysadm 1.52 act.sa_handler = sig_hup_handler;
387     if (sigaction(SIGHUP, &act, NULL) == -1)
388     {
389 sysadm 1.90 log_error("set signal action of SIGHUP error: %d", errno);
390 sysadm 1.52 goto cleanup;
391     }
392     act.sa_handler = sig_chld_handler;
393     if (sigaction(SIGCHLD, &act, NULL) == -1)
394     {
395 sysadm 1.90 log_error("set signal action of SIGCHLD error: %d", errno);
396 sysadm 1.52 goto cleanup;
397     }
398     act.sa_handler = sig_term_handler;
399     if (sigaction(SIGTERM, &act, NULL) == -1)
400     {
401 sysadm 1.90 log_error("set signal action of SIGTERM error: %d", errno);
402 sysadm 1.52 goto cleanup;
403     }
404 sysadm 1.75 act.sa_handler = SIG_IGN;
405 sysadm 1.89 if (sigaction(SIGPIPE, &act, NULL) == -1)
406     {
407 sysadm 1.90 log_error("set signal action of SIGPIPE error: %d", errno);
408 sysadm 1.89 goto cleanup;
409     }
410     act.sa_handler = SIG_IGN;
411 sysadm 1.75 if (sigaction(SIGUSR1, &act, NULL) == -1)
412     {
413 sysadm 1.90 log_error("set signal action of SIGUSR1 error: %d", errno);
414 sysadm 1.75 goto cleanup;
415     }
416 sysadm 1.18
417 sysadm 1.45 // Launch section_list_loader process
418     if (section_list_loader_launch() < 0)
419     {
420 sysadm 1.90 log_error("section_list_loader_launch() error");
421 sysadm 1.45 goto cleanup;
422     }
423    
424 sysadm 1.18 // Initialize socket server
425 sysadm 1.33 net_server(BBS_address, BBS_port);
426 sysadm 1.18
427 sysadm 1.43 cleanup:
428 sysadm 1.80 // Cleanup loader process if still running
429     if (SYS_child_process_count > 0)
430     {
431     SYS_child_exit = 0;
432 sysadm 1.87
433 sysadm 1.80 if (kill(section_list_loader_pid, SIGTERM) < 0)
434     {
435 sysadm 1.90 log_error("Send SIGTERM signal failed (%d)", errno);
436 sysadm 1.80 }
437    
438 sysadm 1.87 for (i = 0; SYS_child_exit == 0 && i < 5; i++)
439 sysadm 1.80 {
440     sleep(1); // second
441     }
442    
443     if ((ret = waitpid(section_list_loader_pid, NULL, WNOHANG)) < 0)
444     {
445 sysadm 1.90 log_error("waitpid(%d) error (%d)", section_list_loader_pid, errno);
446 sysadm 1.80 }
447     else if (ret == 0)
448     {
449 sysadm 1.90 log_common("Force kill section_list_loader process (%d)", section_list_loader_pid);
450 sysadm 1.80 if (kill(section_list_loader_pid, SIGKILL) < 0)
451     {
452 sysadm 1.90 log_error("Send SIGKILL signal failed (%d)", errno);
453 sysadm 1.80 }
454     }
455     }
456    
457 sysadm 1.34 // Cleanup loaded data files
458 sysadm 1.83 for (int i = 0; i < data_files_load_startup_count; i++)
459     {
460     if (unload_file(data_files_load_startup[i]) < 0)
461     {
462 sysadm 1.90 log_error("unload_file(%s) error", data_files_load_startup[i]);
463 sysadm 1.83 }
464     }
465 sysadm 1.42
466 sysadm 1.32 // Cleanup menu
467 sysadm 1.59 unload_menu(&bbs_menu);
468 sysadm 1.62 unload_menu(&top10_menu);
469 sysadm 1.15
470 sysadm 1.91 // Cleanup LML module
471     lml_cleanup();
472    
473 sysadm 1.42 // Cleanup data pools
474     section_list_cleanup();
475     article_block_cleanup();
476 sysadm 1.39 trie_dict_cleanup();
477 sysadm 1.63 user_list_pool_cleanup();
478 sysadm 1.39
479 sysadm 1.42 if (unlink(VAR_ARTICLE_BLOCK_SHM) < 0)
480     {
481 sysadm 1.90 log_error("unlink(%s) error", VAR_ARTICLE_BLOCK_SHM);
482 sysadm 1.42 }
483     if (unlink(VAR_SECTION_LIST_SHM) < 0)
484     {
485 sysadm 1.90 log_error("unlink(%s) error", VAR_SECTION_LIST_SHM);
486 sysadm 1.42 }
487 sysadm 1.63 if (unlink(VAR_TRIE_DICT_SHM) < 0)
488     {
489 sysadm 1.90 log_error("unlink(%s) error", VAR_TRIE_DICT_SHM);
490 sysadm 1.63 }
491     if (unlink(VAR_USER_LIST_SHM) < 0)
492     {
493 sysadm 1.90 log_error("unlink(%s) error", VAR_SECTION_LIST_SHM);
494 sysadm 1.63 }
495 sysadm 1.42
496 sysadm 1.90 log_common("Main process exit normally");
497 sysadm 1.42
498 sysadm 1.57 log_end();
499    
500 sysadm 1.30 return 0;
501 sysadm 1.1 }

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