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

Contents of /lbbs/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.72 - (show annotations)
Fri Nov 7 04:58:09 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.71: +10 -0 lines
Content type: text/x-csrc
Load / Reload BWF config file on startup / reload

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

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