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

Annotation of /lbbs/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log


Revision 1.94 - (hide annotations)
Thu Jan 8 14:22:57 2026 UTC (2 months, 1 week ago) by sysadm
Branch: MAIN
CVS Tags: HEAD
Changes since 1.93: +40 -25 lines
Content type: text/x-csrc
Refine handling of cmdline arguments

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

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