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

Contents of /lbbs/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.73 - (show annotations)
Sat Nov 8 08:21:31 2025 UTC (4 months, 1 week ago) by sysadm
Branch: MAIN
Changes since 1.72: +8 -0 lines
Content type: text/x-csrc
Support dynamic wide-character display width in str_process and editor related functions
Add dynamic / fixed wide-character display width selection

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

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