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

Diff of /lbbs/src/main.c

Parent Directory Parent Directory | Revision Log Revision Log | View Patch Patch

Revision 1.68 by sysadm, Sun Nov 2 08:13:50 2025 UTC Revision 1.91 by sysadm, Fri Dec 19 14:08:44 2025 UTC
# Line 1  Line 1 
1  /***************************************************************************  /* SPDX-License-Identifier: GPL-3.0-or-later */
2                                                    main.c  -  description  /*
3                                                           -------------------   * main
4          Copyright            : (C) 2004-2025 by Leaflet   *   - entry of server program
5          Email                : leaflet@leafok.com   *
6   ***************************************************************************/   * Copyright (C) 2004-2025  Leaflet <leaflet@leafok.com>
7     */
8  /***************************************************************************  
9   *                                                                         *  #ifdef HAVE_CONFIG_H
10   *   This program is free software; you can redistribute it and/or modify  *  #include "config.h"
11   *   it under the terms of the GNU General Public License as published by  *  #endif
  *   the Free Software Foundation; either version 3 of the License, or     *  
  *   (at your option) any later version.                                   *  
  *                                                                         *  
  ***************************************************************************/  
12    
13  #include "bbs.h"  #include "bbs.h"
14    #include "bwf.h"
15  #include "common.h"  #include "common.h"
16  #include "file_loader.h"  #include "file_loader.h"
17  #include "init.h"  #include "init.h"
18  #include "io.h"  #include "io.h"
19    #include "lml.h"
20  #include "log.h"  #include "log.h"
21  #include "menu.h"  #include "menu.h"
22  #include "net_server.h"  #include "net_server.h"
# Line 26  Line 24 
24  #include "user_list.h"  #include "user_list.h"
25  #include <errno.h>  #include <errno.h>
26  #include <libgen.h>  #include <libgen.h>
27    #include <locale.h>
28  #include <signal.h>  #include <signal.h>
29  #include <stdio.h>  #include <stdio.h>
30  #include <stdlib.h>  #include <stdlib.h>
# Line 33  Line 32 
32  #include <unistd.h>  #include <unistd.h>
33  #include <sys/stat.h>  #include <sys/stat.h>
34  #include <sys/types.h>  #include <sys/types.h>
35    #include <sys/wait.h>
36    
37  static void app_help(void)  static inline void app_help(void)
38  {  {
39          fprintf(stderr, "Usage: bbsd [-fhv] [...]\n\n"          fprintf(stderr, "Usage: bbsd [-fhv] [...]\n\n"
40                                          "-f\t--foreground\t\tForce program run in foreground\n"                                          "-f\t--foreground\t\tForce program run in foreground\n"
# Line 42  static void app_help(void) Line 42  static void app_help(void)
42                                          "-v\t--version\t\tDisplay version information\n"                                          "-v\t--version\t\tDisplay version information\n"
43                                          "\t--display-log\t\tDisplay standard log information\n"                                          "\t--display-log\t\tDisplay standard log information\n"
44                                          "\t--display-error-log\tDisplay error log information\n"                                          "\t--display-error-log\tDisplay error log information\n"
45                                            "-C\t--compile-config\tDisplay compile configuration\n"
46                                          "\n    If meet any bug, please report to <leaflet@leafok.com>\n\n");                                          "\n    If meet any bug, please report to <leaflet@leafok.com>\n\n");
47  }  }
48    
49  static void arg_error(void)  static inline void arg_error(void)
50  {  {
51          fprintf(stderr, "Invalid arguments\n");          fprintf(stderr, "Invalid arguments\n");
52          app_help();          app_help();
53  }  }
54    
55    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  int main(int argc, char *argv[])  int main(int argc, char *argv[])
99  {  {
100          char file_path_temp[FILE_PATH_LEN];          char file_path_temp[FILE_PATH_LEN];
# Line 61  int main(int argc, char *argv[]) Line 105  int main(int argc, char *argv[])
105          int ret;          int ret;
106          int last_aid;          int last_aid;
107          struct sigaction act = {0};          struct sigaction act = {0};
108            int i;
109            int j;
110            struct stat file_stat;
111    
112          // Parse args          // Parse args
113          for (int i = 1; i < argc; i++)          for (i = 1; i < argc; i++)
114          {          {
115                  switch (argv[i][0])                  switch (argv[i][0])
116                  {                  {
117                  case '-':                  case '-':
118                          if (argv[i][1] != '-')                          if (argv[i][1] != '-')
119                          {                          {
120                                  for (int j = 1; j < strlen(argv[i]); j++)                                  for (j = 1; j < strlen(argv[i]); j++)
121                                  {                                  {
122                                          switch (argv[i][j])                                          switch (argv[i][j])
123                                          {                                          {
# Line 81  int main(int argc, char *argv[]) Line 128  int main(int argc, char *argv[])
128                                                  app_help();                                                  app_help();
129                                                  return 0;                                                  return 0;
130                                          case 'v':                                          case 'v':
131                                                  puts(APP_INFO);                                                  printf("%s\n", APP_INFO);
132                                                    printf("%s\n", COPYRIGHT_INFO);
133                                                    return 0;
134                                            case 'C':
135                                                    app_compile_info();
136                                                  return 0;                                                  return 0;
137                                          default:                                          default:
138                                                  arg_error();                                                  arg_error();
# Line 103  int main(int argc, char *argv[]) Line 154  int main(int argc, char *argv[])
154                                  }                                  }
155                                  if (strcmp(argv[i] + 2, "version") == 0)                                  if (strcmp(argv[i] + 2, "version") == 0)
156                                  {                                  {
157                                          puts(APP_INFO);                                          printf("%s\n", APP_INFO);
158                                            printf("%s\n", COPYRIGHT_INFO);
159                                          return 0;                                          return 0;
160                                  }                                  }
161                                  if (strcmp(argv[i] + 2, "display-log") == 0)                                  if (strcmp(argv[i] + 2, "display-log") == 0)
# Line 114  int main(int argc, char *argv[]) Line 166  int main(int argc, char *argv[])
166                                  {                                  {
167                                          error_log_redir = 1;                                          error_log_redir = 1;
168                                  }                                  }
169                                    if (strcmp(argv[i] + 2, "compile-config") == 0)
170                                    {
171                                            app_compile_info();
172                                            return 0;
173                                    }
174                          }                          }
175                          break;                          break;
176                  }                  }
# Line 140  int main(int argc, char *argv[]) Line 197  int main(int argc, char *argv[])
197                  return -1;                  return -1;
198          }          }
199    
200            // 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          // Initialize log          // Initialize log
208          if (log_begin(LOG_FILE_INFO, LOG_FILE_ERROR) < 0)          if (log_begin(LOG_FILE_INFO, LOG_FILE_ERROR) < 0)
209          {          {
# Line 155  int main(int argc, char *argv[]) Line 219  int main(int argc, char *argv[])
219                  log_error_redir(STDERR_FILENO);                  log_error_redir(STDERR_FILENO);
220          }          }
221    
222          log_common("Starting %s\n", APP_INFO);          log_common("Starting %s", APP_INFO);
223    
224          // Load configuration          // Load configuration
225          if (load_conf(CONF_BBSD) < 0)          if (load_conf(CONF_BBSD) < 0)
# Line 163  int main(int argc, char *argv[]) Line 227  int main(int argc, char *argv[])
227                  return -2;                  return -2;
228          }          }
229    
230            // Load BWF config
231            if (bwf_load(CONF_BWF) < 0)
232            {
233                    return -2;
234            }
235    
236            // Get EULA modification tm
237            if (stat(DATA_EULA, &file_stat) == -1)
238            {
239                    log_error("stat(%s) error", DATA_EULA, errno);
240                    goto cleanup;
241            }
242            BBS_eula_tm = file_stat.st_mtim.tv_sec;
243    
244          // Check article cache dir          // Check article cache dir
245          ret = mkdir(VAR_ARTICLE_CACHE_DIR, 0750);          ret = mkdir(VAR_ARTICLE_CACHE_DIR, 0750);
246          if (ret == -1 && errno != EEXIST)          if (ret == -1 && errno != EEXIST)
247          {          {
248                  log_error("mkdir(%s) error (%d)\n", VAR_ARTICLE_CACHE_DIR, errno);                  log_error("mkdir(%s) error (%d)", VAR_ARTICLE_CACHE_DIR, errno);
249                  goto cleanup;                  goto cleanup;
250          }          }
251    
# Line 175  int main(int argc, char *argv[]) Line 253  int main(int argc, char *argv[])
253          ret = mkdir(VAR_SECTION_AID_LOC_DIR, 0750);          ret = mkdir(VAR_SECTION_AID_LOC_DIR, 0750);
254          if (ret == -1 && errno != EEXIST)          if (ret == -1 && errno != EEXIST)
255          {          {
256                  log_error("mkdir(%s) error (%d)\n", VAR_SECTION_AID_LOC_DIR, errno);                  log_error("mkdir(%s) error (%d)", VAR_SECTION_AID_LOC_DIR, errno);
257                  goto cleanup;                  goto cleanup;
258          }          }
259    
260          // Initialize data pools          // Initialize data pools
261          if ((fp = fopen(VAR_ARTICLE_BLOCK_SHM, "w")) == NULL)          if ((fp = fopen(VAR_ARTICLE_BLOCK_SHM, "w")) == NULL)
262          {          {
263                  log_error("fopen(%s) error\n", VAR_ARTICLE_BLOCK_SHM);                  log_error("fopen(%s) error", VAR_ARTICLE_BLOCK_SHM);
264                  goto cleanup;                  goto cleanup;
265          }          }
266          fclose(fp);          fclose(fp);
267          if ((fp = fopen(VAR_SECTION_LIST_SHM, "w")) == NULL)          if ((fp = fopen(VAR_SECTION_LIST_SHM, "w")) == NULL)
268          {          {
269                  log_error("fopen(%s) error\n", VAR_SECTION_LIST_SHM);                  log_error("fopen(%s) error", VAR_SECTION_LIST_SHM);
270                  goto cleanup;                  goto cleanup;
271          }          }
272          fclose(fp);          fclose(fp);
273          if ((fp = fopen(VAR_TRIE_DICT_SHM, "w")) == NULL)          if ((fp = fopen(VAR_TRIE_DICT_SHM, "w")) == NULL)
274          {          {
275                  log_error("fopen(%s) error\n", VAR_TRIE_DICT_SHM);                  log_error("fopen(%s) error", VAR_TRIE_DICT_SHM);
276                  goto cleanup;                  goto cleanup;
277          }          }
278          fclose(fp);          fclose(fp);
279          if ((fp = fopen(VAR_USER_LIST_SHM, "w")) == NULL)          if ((fp = fopen(VAR_USER_LIST_SHM, "w")) == NULL)
280          {          {
281                  log_error("fopen(%s) error\n", VAR_USER_LIST_SHM);                  log_error("fopen(%s) error", VAR_USER_LIST_SHM);
282                  goto cleanup;                  goto cleanup;
283          }          }
284          fclose(fp);          fclose(fp);
285    
286          if (trie_dict_init(VAR_TRIE_DICT_SHM, TRIE_NODE_PER_POOL) < 0)          if (trie_dict_init(VAR_TRIE_DICT_SHM, TRIE_NODE_PER_POOL) < 0)
287          {          {
288                  printf("trie_dict_init(%s, %d) error\n", VAR_TRIE_DICT_SHM, TRIE_NODE_PER_POOL);                  log_error("trie_dict_init(%s, %d) error", VAR_TRIE_DICT_SHM, TRIE_NODE_PER_POOL);
289                  goto cleanup;                  goto cleanup;
290          }          }
291          if (article_block_init(VAR_ARTICLE_BLOCK_SHM, BBS_article_limit_per_section * BBS_max_section / ARTICLE_PER_BLOCK) < 0)          if (article_block_init(VAR_ARTICLE_BLOCK_SHM, BBS_article_limit_per_section * BBS_max_section / BBS_article_count_per_block) < 0)
292          {          {
293                  log_error("article_block_init(%s, %d) error\n", VAR_ARTICLE_BLOCK_SHM, BBS_article_limit_per_section * BBS_max_section / ARTICLE_PER_BLOCK);                  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                  goto cleanup;                  goto cleanup;
295          }          }
296          if (section_list_init(VAR_SECTION_LIST_SHM) < 0)          if (section_list_init(VAR_SECTION_LIST_SHM) < 0)
297          {          {
298                  log_error("section_list_pool_init(%s) error\n", VAR_SECTION_LIST_SHM);                  log_error("section_list_pool_init(%s) error", VAR_SECTION_LIST_SHM);
299                    goto cleanup;
300            }
301    
302            // Init LML module
303            if (lml_init() < 0)
304            {
305                    log_error("lml_init() error");
306                  goto cleanup;                  goto cleanup;
307          }          }
308    
309          // Load BBS cmd          // Load BBS cmd
310          if (load_cmd() < 0)          if (load_cmd() < 0)
311          {          {
312                    log_error("load_cmd() error");
313                  goto cleanup;                  goto cleanup;
314          }          }
315    
316          // Load menus          // Load menus
317          if (load_menu(&bbs_menu, CONF_MENU) < 0)          if (load_menu(&bbs_menu, CONF_MENU) < 0)
318          {          {
319                  log_error("load_menu(%s) error\n", CONF_MENU);                  log_error("load_menu(bbs_menu) error");
320                  goto cleanup;                  goto cleanup;
321          }          }
322          if (load_menu(&top10_menu, CONF_TOP10_MENU) < 0)          if (load_menu(&top10_menu, CONF_TOP10_MENU) < 0)
323          {          {
324                  log_error("load_menu(%s) error\n", CONF_TOP10_MENU);                  log_error("load_menu(top10_menu) error");
325                  goto cleanup;                  goto cleanup;
326          }          }
327          top10_menu.allow_exit = 1;          top10_menu.allow_exit = 1;
328    
329          // Load data files          // Load data files
         if (file_loader_init() < 0)  
         {  
                 log_error("file_loader_init() error\n");  
                 goto cleanup;  
         }  
330          for (int i = 0; i < data_files_load_startup_count; i++)          for (int i = 0; i < data_files_load_startup_count; i++)
331          {          {
332                  if (load_file(data_files_load_startup[i]) < 0)                  if (load_file(data_files_load_startup[i]) < 0)
333                  {                  {
334                          log_error("load_file(%s) error\n", data_files_load_startup[i]);                          log_error("load_file(%s) error", data_files_load_startup[i]);
335                  }                  }
336          }          }
337    
338          // Load user_list and online_user_list          // Load user_list and online_user_list
339          if (user_list_pool_init(VAR_USER_LIST_SHM) < 0)          if (user_list_pool_init(VAR_USER_LIST_SHM) < 0)
340          {          {
341                  log_error("user_list_pool_init(%s) error\n", VAR_USER_LIST_SHM);                  log_error("user_list_pool_init(%s) error", VAR_USER_LIST_SHM);
342                  goto cleanup;                  goto cleanup;
343          }          }
344          if (user_list_pool_reload(0) < 0)          if (user_list_pool_reload(0) < 0)
345          {          {
346                  log_error("user_list_pool_reload(all_user) error\n");                  log_error("user_list_pool_reload(all_user) error");
347                  goto cleanup;                  goto cleanup;
348          }          }
349          if (user_list_pool_reload(1) < 0)          if (user_list_pool_reload(1) < 0)
350          {          {
351                  log_error("user_list_pool_reload(online_user) error\n");                  log_error("user_list_pool_reload(online_user) error");
352                  goto cleanup;                  goto cleanup;
353          }          }
354    
355          // Load section config and gen_ex          // Load section config and gen_ex
356          if (load_section_config_from_db(1) < 0)          if (load_section_config_from_db(1) < 0)
357          {          {
358                  log_error("load_section_config_from_db(0) error\n");                  log_error("load_section_config_from_db(0) error");
359                  goto cleanup;                  goto cleanup;
360          }          }
361    
# Line 286  int main(int argc, char *argv[]) Line 367  int main(int argc, char *argv[])
367          {          {
368                  if ((ret = append_articles_from_db(last_aid + 1, 1, LOAD_ARTICLE_COUNT_LIMIT)) < 0)                  if ((ret = append_articles_from_db(last_aid + 1, 1, LOAD_ARTICLE_COUNT_LIMIT)) < 0)
369                  {                  {
370                          log_error("append_articles_from_db(0, 1, %d) error\n", LOAD_ARTICLE_COUNT_LIMIT);                          log_error("append_articles_from_db(0, 1, %d) error", LOAD_ARTICLE_COUNT_LIMIT);
371                          goto cleanup;                          goto cleanup;
372                  }                  }
373    
374                  last_aid = article_block_last_aid();                  last_aid = article_block_last_aid();
375          } while (ret == LOAD_ARTICLE_COUNT_LIMIT);          } while (ret == LOAD_ARTICLE_COUNT_LIMIT);
376    
377          log_common("Initially load %d articles, last_aid = %d\n", article_block_article_count(), article_block_last_aid());          log_common("Initially load %d articles, last_aid = %d", article_block_article_count(), article_block_last_aid());
378    
379          if ((ret = user_stat_update()) < 0)          if ((ret = user_stat_update()) < 0)
380          {          {
381                  log_error("user_stat_update() error\n");                  log_error("user_stat_update() error");
382                  goto cleanup;                  goto cleanup;
383          }          }
384    
# Line 305  int main(int argc, char *argv[]) Line 386  int main(int argc, char *argv[])
386          act.sa_handler = sig_hup_handler;          act.sa_handler = sig_hup_handler;
387          if (sigaction(SIGHUP, &act, NULL) == -1)          if (sigaction(SIGHUP, &act, NULL) == -1)
388          {          {
389                  log_error("set signal action of SIGHUP error: %d\n", errno);                  log_error("set signal action of SIGHUP error: %d", errno);
390                  goto cleanup;                  goto cleanup;
391          }          }
392          act.sa_handler = sig_chld_handler;          act.sa_handler = sig_chld_handler;
393          if (sigaction(SIGCHLD, &act, NULL) == -1)          if (sigaction(SIGCHLD, &act, NULL) == -1)
394          {          {
395                  log_error("set signal action of SIGCHLD error: %d\n", errno);                  log_error("set signal action of SIGCHLD error: %d", errno);
396                  goto cleanup;                  goto cleanup;
397          }          }
398          act.sa_handler = sig_term_handler;          act.sa_handler = sig_term_handler;
399          if (sigaction(SIGTERM, &act, NULL) == -1)          if (sigaction(SIGTERM, &act, NULL) == -1)
400          {          {
401                  log_error("set signal action of SIGTERM error: %d\n", errno);                  log_error("set signal action of SIGTERM error: %d", errno);
402                    goto cleanup;
403            }
404            act.sa_handler = SIG_IGN;
405            if (sigaction(SIGPIPE, &act, NULL) == -1)
406            {
407                    log_error("set signal action of SIGPIPE error: %d", errno);
408                    goto cleanup;
409            }
410            act.sa_handler = SIG_IGN;
411            if (sigaction(SIGUSR1, &act, NULL) == -1)
412            {
413                    log_error("set signal action of SIGUSR1 error: %d", errno);
414                  goto cleanup;                  goto cleanup;
415          }          }
416    
417          // Launch section_list_loader process          // Launch section_list_loader process
418          if (section_list_loader_launch() < 0)          if (section_list_loader_launch() < 0)
419          {          {
420                  log_error("section_list_loader_launch() error\n");                  log_error("section_list_loader_launch() error");
421                  goto cleanup;                  goto cleanup;
422          }          }
423    
# Line 332  int main(int argc, char *argv[]) Line 425  int main(int argc, char *argv[])
425          net_server(BBS_address, BBS_port);          net_server(BBS_address, BBS_port);
426    
427  cleanup:  cleanup:
428            // Cleanup loader process if still running
429            if (SYS_child_process_count > 0)
430            {
431                    SYS_child_exit = 0;
432    
433                    if (kill(section_list_loader_pid, SIGTERM) < 0)
434                    {
435                            log_error("Send SIGTERM signal failed (%d)", errno);
436                    }
437    
438                    for (i = 0; SYS_child_exit == 0 && i < 5; i++)
439                    {
440                            sleep(1); // second
441                    }
442    
443                    if ((ret = waitpid(section_list_loader_pid, NULL, WNOHANG)) < 0)
444                    {
445                            log_error("waitpid(%d) error (%d)", section_list_loader_pid, errno);
446                    }
447                    else if (ret == 0)
448                    {
449                            log_common("Force kill section_list_loader process (%d)", section_list_loader_pid);
450                            if (kill(section_list_loader_pid, SIGKILL) < 0)
451                            {
452                                    log_error("Send SIGKILL signal failed (%d)", errno);
453                            }
454                    }
455            }
456    
457          // Cleanup loaded data files          // Cleanup loaded data files
458          file_loader_cleanup();          for (int i = 0; i < data_files_load_startup_count; i++)
459            {
460                    if (unload_file(data_files_load_startup[i]) < 0)
461                    {
462                            log_error("unload_file(%s) error", data_files_load_startup[i]);
463                    }
464            }
465    
466          // Cleanup menu          // Cleanup menu
467          unload_menu(&bbs_menu);          unload_menu(&bbs_menu);
468          unload_menu(&top10_menu);          unload_menu(&top10_menu);
469    
470            // Cleanup LML module
471            lml_cleanup();
472    
473          // Cleanup data pools          // Cleanup data pools
474          section_list_cleanup();          section_list_cleanup();
475          article_block_cleanup();          article_block_cleanup();
# Line 347  cleanup: Line 478  cleanup:
478    
479          if (unlink(VAR_ARTICLE_BLOCK_SHM) < 0)          if (unlink(VAR_ARTICLE_BLOCK_SHM) < 0)
480          {          {
481                  log_error("unlink(%s) error\n", VAR_ARTICLE_BLOCK_SHM);                  log_error("unlink(%s) error", VAR_ARTICLE_BLOCK_SHM);
482          }          }
483          if (unlink(VAR_SECTION_LIST_SHM) < 0)          if (unlink(VAR_SECTION_LIST_SHM) < 0)
484          {          {
485                  log_error("unlink(%s) error\n", VAR_SECTION_LIST_SHM);                  log_error("unlink(%s) error", VAR_SECTION_LIST_SHM);
486          }          }
487          if (unlink(VAR_TRIE_DICT_SHM) < 0)          if (unlink(VAR_TRIE_DICT_SHM) < 0)
488          {          {
489                  log_error("unlink(%s) error\n", VAR_TRIE_DICT_SHM);                  log_error("unlink(%s) error", VAR_TRIE_DICT_SHM);
490          }          }
491          if (unlink(VAR_USER_LIST_SHM) < 0)          if (unlink(VAR_USER_LIST_SHM) < 0)
492          {          {
493                  log_error("unlink(%s) error\n", VAR_SECTION_LIST_SHM);                  log_error("unlink(%s) error", VAR_SECTION_LIST_SHM);
494          }          }
495    
496          log_common("Main process exit normally\n");          log_common("Main process exit normally");
497    
498          log_end();          log_end();
499    


Legend:
Removed lines/characters  
Changed lines/characters
  Added lines/characters

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