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

Contents of /lbbs/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.85 - (show annotations)
Fri Nov 21 08:59:29 2025 UTC (3 months, 3 weeks ago) by sysadm
Branch: MAIN
Changes since 1.84: +4 -0 lines
Content type: text/x-csrc
Fix segment fault issue caused by pcre2api with multi-process on MSYS2

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

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