cScm Configuration Daemon

cScm – is a tool to convert SCM configuration files into binary format and store its in shared memory for reading by cSvn-ui and cGit-ui CGI scripts

2 Commits   0 Branches   1 Tag
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   1) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   2) #ifdef HAVE_CONFIG_H
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   3) #include <config.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   4) #endif
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   5) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   6) #include <stdlib.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   7) #include <stdio.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   8) #include <sys/sysinfo.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300   9) #include <sys/types.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  10) #include <stdint.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  11) #include <dirent.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  12) #include <sys/stat.h> /* chmod(2)    */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  13) #include <fcntl.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  14) #include <limits.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  15) #include <string.h>   /* strdup(3)   */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  16) #include <libgen.h>   /* basename(3) */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  17) #include <ctype.h>    /* tolower(3)  */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  18) #include <errno.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  19) #include <time.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  20) #include <sys/time.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  21) #include <pwd.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  22) #include <grp.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  23) #include <stdarg.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  24) #include <unistd.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  25) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  26) #include <sys/inotify.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  27) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  28) #include <locale.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  29) #include <wchar.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  30) #include <wctype.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  31) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  32) #include <sys/wait.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  33) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  34) #include <sys/resource.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  35) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  36) #include <signal.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  37) #if !defined SIGCHLD && defined SIGCLD
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  38) # define SIGCHLD SIGCLD
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  39) #endif
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  40) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  41) #define _GNU_SOURCE
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  42) #include <getopt.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  43) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  44) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  45) #include <daemon.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  46) #include <msglog.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  47) #include <error.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  48) #include <utf8ing.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  49) #include <symtab.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  50) #include <parse.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  51) #include <lex.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  52) #include <bconf.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  53) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  54) #include <defs.h>
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  55) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  56) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  57) /*********************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  58)   Default File Names:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  59)  */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  60) const char *CONFIG_FILE = CSVN_CONFIG;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  61) const char *BCF_FILE    = CSVN_HOME_DIR "/" CSVN_PROGRAM ".bcf";
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  62) const char *LOG_FILE    = CSCM_LOG_DIR  "/" CSVN_PROGRAM "d.log";
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  63) const char *PID_FILE    = CSCM_PID_DIR  "/" CSVN_PROGRAM "d.pid";
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  64) const char *SHM_BCF     = CSVN_SHM_BCF;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  65) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  66) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  67) char *program = PROGRAM_DAEMON;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  68) int   exit_status = EXIT_SUCCESS; /* errors counter */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  69) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  70) FILE *config = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  71) char *config_fname = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  72) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  73) char *log_fname = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  74) char *pid_fname = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  75) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  76) static sigset_t  blockmask;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  77) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  78) static int  run_as_daemon = 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  79) static int  test_config_file = 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  80) static int  config_inotify = 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  81) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  82) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  83) static void free_resources( void );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  84) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  85) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  86) /***********************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  87)   Inotify declarations:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  88)  */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  89) #define IN_BUFFER_SIZE  (7 * (sizeof(struct inotify_event) + NAME_MAX + 1))
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  90) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  91) static int inotify_fd = 0, wd = 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  92) static struct inotify_event *event = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  93) static char buf[IN_BUFFER_SIZE] __attribute__ ((aligned(8)));
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  94) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  95) static int check_event( struct inotify_event *e )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  96) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  97)   if( e->mask & IN_CLOSE_WRITE ) return 1;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  98)   return 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300  99) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 100) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 101) static void init_config_inotify( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 102) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 103)   inotify_fd = inotify_init(); /* Create inotify instance */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 104)   if( inotify_fd == -1 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 105)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 106)     ERROR( "Cannot initialize inotify for file: %s", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 107)     LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 108)     free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 109)     exit( 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 110)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 111) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 112)   wd = inotify_add_watch( inotify_fd, config_fname, IN_CLOSE_WRITE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 113)   if( wd == -1 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 114)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 115)     ERROR( "Cannot add inotify watch for file: %s", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 116)     LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 117)     free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 118)     exit( 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 119)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 120) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 121) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 122) static void fini_config_inotify( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 123) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 124)   if( wd > 0 )         { (void)inotify_rm_watch( inotify_fd, wd ); wd = 0; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 125)   if( inotify_fd > 0 ) { (void)close( inotify_fd ); inotify_fd = 0;        }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 126) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 127) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 128) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 129) static void free_resources( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 130) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 131)   fini_config_inotify();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 132) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 133)   if( log_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 134)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 135)     if( errlog ) { fclose( errlog ); errlog = NULL; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 136)     free( log_fname ); log_fname = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 137)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 138)   if( config_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 139)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 140)     if( config ) { fclose( config ); config = NULL; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 141)     free( config_fname ); config_fname = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 142)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 143)   bcf_shm_free();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 144)   if( bcf_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 145)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 146)     if( bcf ) { fclose( bcf ); bcf = NULL; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 147)     (void)unlink( (const char *)bcf_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 148)     free( bcf_fname ); bcf_fname = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 149)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 150)   if( pid_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 151)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 152)     (void)unlink( (const char *)pid_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 153)     free( pid_fname ); pid_fname = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 154)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 155) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 156) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 157) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 158) void usage()
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 159) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 160)   free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 161) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 162)   fprintf( stdout, "\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 163)   fprintf( stdout, "Usage: %s [options]\n", program );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 164)   fprintf( stdout, "\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 165)   fprintf( stdout, "Start cScm Configuration Daemon to read config file.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 166)   fprintf( stdout, "\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 167)   fprintf( stdout, "Options:\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 168)   fprintf( stdout, "  -h,--help                     Display this information.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 169)   fprintf( stdout, "  -v,--version                  Display the version of %s utility.\n", program );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 170)   fprintf( stdout, "  -d,--daemonize                Run in background as a daemon.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 171)   fprintf( stdout, "  -i,--inotify                  Notify about configuration changes.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 172)   fprintf( stdout, "  -b,--bcf=<BCF_FILE>           Binary config file. Default: %s.\n", BCF_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 173)   fprintf( stdout, "  -c,--config=<CONFIG_FILE>     Config file. Default: %s.\n", CONFIG_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 174)   fprintf( stdout, "  -l,--log=<LOG_FILE>           Log file. Default: %s.\n", LOG_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 175)   fprintf( stdout, "  -p,--pid=<PID_FILE>           PID file. Default: %s.\n", PID_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 176)   fprintf( stdout, "  -s,--scm=<SCM>                SCM 'svn' or 'git'. Default: 'svn'.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 177)   fprintf( stdout, "  -t,--test                     Test config file and exit.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 178)   fprintf( stdout, "\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 179) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 180)   exit( EXIT_FAILURE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 181) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 182) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 183) void to_lowercase( char *s )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 184) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 185)   char *p = s;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 186)   while( p && *p ) { int c = *p; *p = tolower( c ); ++p; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 187) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 188) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 189) void to_uppercase( char *s )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 190) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 191)   char *p = s;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 192)   while( p && *p ) { int c = *p; *p = toupper( c ); ++p; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 193) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 194) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 195) void version()
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 196) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 197)   char *upper = NULL;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 198) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 199)   upper = (char *)alloca( strlen( program ) + 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 200) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 201)   strcpy( (char *)upper, (const char *)program );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 202)   to_uppercase( upper );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 203) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 204)   fprintf( stdout, "%s (%s) %s\n", program, upper, PROGRAM_VERSION );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 205) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 206)   fprintf( stdout, "Copyright (C) 2022 Andrey V.Kosteltsev.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 207)   fprintf( stdout, "This is free software.   There is NO warranty; not even\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 208)   fprintf( stdout, "for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 209)   fprintf( stdout, "\n" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 210) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 211)   free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 212)   exit( EXIT_SUCCESS );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 213) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 214) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 215) void get_args( int argc, char *argv[] )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 216) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 217)   const char* short_options = "hvdic:l:p:s:t";
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 218) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 219)   const struct option long_options[] =
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 220)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 221)     { "help",               no_argument,       NULL, 'h' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 222)     { "version",            no_argument,       NULL, 'v' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 223)     { "daemonize",          no_argument,       NULL, 'd' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 224)     { "inotify",            no_argument,       NULL, 'i' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 225)     { "bcf",                required_argument, NULL, 'b' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 226)     { "config",             required_argument, NULL, 'c' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 227)     { "log",                required_argument, NULL, 'l' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 228)     { "pid",                required_argument, NULL, 'p' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 229)     { "scm",                required_argument, NULL, 's' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 230)     { "test",               no_argument,       NULL, 't' },
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 231)     { NULL,                 0,                 NULL,  0  }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 232)   };
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 233) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 234)   int ret;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 235)   int option_index = 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 236) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 237)   while( (ret = getopt_long( argc, argv, short_options, long_options, &option_index )) != -1 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 238)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 239)     switch( ret )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 240)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 241)       case 'h':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 242)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 243)         usage();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 244)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 245)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 246)       case 'v':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 247)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 248)         version();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 249)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 250)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 251)       case 'd':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 252)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 253)         run_as_daemon = 1;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 254)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 255)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 256)       case 'i':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 257)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 258)         config_inotify = 1;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 259)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 260)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 261)       case 't':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 262)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 263)         test_config_file = 1;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 264)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 265)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 266) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 267)       case 'b':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 268)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 269)         if( optarg != NULL )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 270)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 271)           bcf_fname = strdup( optarg );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 272)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 273)         else
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 274)           /* option is present but without value */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 275)           usage();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 276)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 277)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 278) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 279)       case 'c':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 280)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 281)         if( optarg != NULL )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 282)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 283)           config_fname = strdup( optarg );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 284)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 285)         else
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 286)           /* option is present but without value */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 287)           usage();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 288)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 289)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 290) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 291)       case 'l':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 292)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 293)         if( optarg != NULL )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 294)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 295)           log_fname = strdup( optarg );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 296)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 297)         else
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 298)           /* option is present but without value */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 299)           usage();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 300)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 301)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 302) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 303)       case 'p':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 304)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 305)         if( optarg != NULL )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 306)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 307)           pid_fname = strdup( optarg );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 308)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 309)         else
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 310)           /* option is present but without value */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 311)           usage();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 312)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 313)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 314) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 315)       case 's':
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 316)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 317)         if( optarg != NULL )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 318)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 319)           if( *optarg && !strncmp( optarg, "git", 3 ) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 320)           {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 321)             CONFIG_FILE = CGIT_CONFIG;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 322)                BCF_FILE = CGIT_HOME_DIR "/" CGIT_PROGRAM ".bcf";
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 323)                LOG_FILE = CSCM_LOG_DIR  "/" CGIT_PROGRAM "d.log";
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 324)                PID_FILE = CSCM_PID_DIR  "/" CGIT_PROGRAM "d.pid";
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 325)                 SHM_BCF = CGIT_SHM_BCF;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 326)           }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 327)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 328)         else
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 329)           /* option is present but without value */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 330)           usage();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 331)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 332)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 333) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 334)       case '?': default:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 335)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 336)         usage();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 337)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 338)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 339)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 340)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 341) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 342) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 343) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 344) static int is_directory( const char *path )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 345) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 346)   struct stat st;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 347)   return ( !stat( path, &st ) && S_ISDIR(st.st_mode) );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 348) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 349) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 350) static void logpid( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 351) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 352)   FILE *fp;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 353) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 354)   if( !pid_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 355)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 356)     /* allocate memory for PID file name */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 357)     pid_fname = (char *)malloc( strlen( PID_FILE ) + 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 358)     if( !pid_fname ) { FATAL_ERROR( "Cannot allocate memory for PID file name: %s", PID_FILE ); }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 359)     (void)strcpy( pid_fname, PID_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 360)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 361) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 362)   /* Create CSCM_PID_DIR if not exists: */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 363)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 364)     char  *pid_dir = NULL, *dir = strdup( pid_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 365) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 366)     pid_dir = dirname( dir );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 367) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 368)     if( !is_directory( (const char *)pid_dir ) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 369)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 370)       /* Create if not exists */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 371)       if( 0 != mkdir( (const char *)pid_dir, 0755 ) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 372)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 373)         FATAL_ERROR( "Cannot create directory for PID file: %s", PID_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 374)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 375)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 376)     free( dir );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 377)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 378) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 379)   if( (fp = fopen( pid_fname, "w" )) != NULL )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 380)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 381)     fprintf( fp, "%u\n", getpid() );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 382)     (void)fclose( fp );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 383)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 384) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 385) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 386) void init_logs( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 387) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 388)   /* print to stderr until the errlog file is open */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 389)   errlog = stderr;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 390) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 391)   if( !log_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 392)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 393)     /* allocate memory for LOG file name */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 394)     log_fname = (char *)malloc( strlen( LOG_FILE ) + 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 395)     if( !log_fname ) { FATAL_ERROR( "Cannot open log file: %s", LOG_FILE ); }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 396)     (void)strcpy( log_fname, LOG_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 397)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 398) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 399)   /* Create CSCM_LOG_DIR if not exists: */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 400)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 401)     char  *log_dir = NULL, *dir = strdup( log_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 402) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 403)     log_dir = dirname( dir );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 404) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 405)     if( !is_directory( (const char *)log_dir ) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 406)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 407)       /* Create if not exists */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 408)       if( 0 != mkdir( (const char *)log_dir, 0755 ) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 409)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 410)         FATAL_ERROR( "Cannot create directory for log file: %s", LOG_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 411)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 412)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 413)     free( dir );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 414)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 415) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 416)   /* open LOG file */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 417)   errlog = fopen( (const char *)log_fname, "a" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 418)   if( !errlog ) { errlog = stderr; FATAL_ERROR( "Cannot open log file: %s", log_fname ); }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 419) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 420) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 421) void open_config_file( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 422) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 423)   if( !config_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 424)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 425)     /* allocate memory for CONFIG file name */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 426)     config_fname = (char *)malloc( strlen( CONFIG_FILE ) + 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 427)     if( !config_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 428)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 429)       FATAL_ERROR( "Cannot open config file: %s", CONFIG_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 430)       if( log_fname ) { fclose( errlog ); free( log_fname ); }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 431)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 432)     (void)strcpy( config_fname, CONFIG_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 433)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 434) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 435)   /* open CONFIG file */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 436)   config = fopen( (const char *)config_fname, "r" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 437)   if( !config )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 438)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 439)     FATAL_ERROR( "Cannot open config file: %s", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 440)     if( log_fname ) { fclose( errlog ); free( log_fname ); }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 441)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 442) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 443)   if( !bcf_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 444)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 445)     /* allocate memory for BCF file name */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 446)     bcf_fname = (char *)malloc( strlen( BCF_FILE ) + 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 447)     if( !bcf_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 448)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 449)       FATAL_ERROR( "Cannot allocate memory gor BCF file name: %s", BCF_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 450)       if( log_fname ) { fclose( errlog ); free( log_fname ); }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 451)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 452)     (void)strcpy( bcf_fname, BCF_FILE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 453)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 454) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 455) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 456) void close_config_file( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 457) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 458)   if( config ) { fclose( config ); config = NULL; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 459) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 460) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 461) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 462) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 463) void parse_config_file( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 464) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 465)   int ret;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 466) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 467)   /***********************************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 468)     Blick signals until parser works:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 469)    */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 470)   (void)sigprocmask( SIG_BLOCK, (const sigset_t *)&blockmask, (sigset_t *)NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 471) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 472)   open_config_file();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 473)   init_symtab();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 474)   init_lex();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 475) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 476)   if( !(ret = yyparse()) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 477)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 478)     reverse_symlist( (SYMBOL **)&symlist );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 479)     remove_consts( (SYMBOL **)&symlist );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 480)     (void)write_binary_config();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 481)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 482)   else
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 483)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 484)     bcf_shm_free();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 485)     if( bcf_fname )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 486)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 487)       if( bcf ) { fclose( bcf ); bcf = NULL; }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 488)       (void)unlink( (const char *)bcf_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 489)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 490)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 491) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 492)   fini_lex();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 493)   fini_symtab();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 494)   close_config_file();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 495) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 496)   (void)sigprocmask( SIG_UNBLOCK, (const sigset_t *)&blockmask, (sigset_t *)NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 497) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 498)   if( test_config_file )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 499)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 500)     if( ret )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 501)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 502)       fprintf( stdout, "%s: %s: Config file is not correct. See: %s\n", program, config_fname, log_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 503)       LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 504)       free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 505)       exit( 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 506)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 507)     else
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 508)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 509)       fprintf( stdout, "%s: %s: Config file is correct.\n", program, config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 510)       LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 511)       free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 512)       exit( 0 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 513)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 514)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 515) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 516) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 517) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 518) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 519) void fatal_error_actions( void )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 520) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 521)   free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 522) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 523) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 524) void sigint( int signum )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 525) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 526)   (void)signum;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 527) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 528)   LOG( "received SIGINT: free resources at exit" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 529)   LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 530) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 531)   free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 532)   exit( 0 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 533) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 534) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 535) void sigusr( int signum )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 536) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 537)   if( signum == SIGUSR1 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 538)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 539)     LOG( "signal USR1 has been received" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 540)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 541)   else if( signum == SIGUSR2 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 542)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 543)     LOG( "signal USR2 has been received" );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 544)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 545) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 546) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 547) void sighup( int signum )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 548) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 549)   (void)signum;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 550) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 551)   LOG( "received SIGHUP: parse config file: %s", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 552) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 553)   parse_config_file();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 554) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 555) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 556) static void set_signal_handlers()
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 557) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 558)   struct sigaction  sa;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 559)   sigset_t          set;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 560) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 561)   memset( &sa, 0, sizeof( sa ) );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 562)   sa.sa_handler = sighup;          /* HUP: read config file */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 563)   sa.sa_flags = SA_RESTART;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 564)   sigemptyset( &set );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 565)   sigaddset( &set, SIGHUP );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 566)   sa.sa_mask = set;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 567)   sigaction( SIGHUP, &sa, NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 568) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 569)   memset( &sa, 0, sizeof( sa ) );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 570)   sa.sa_handler = sigusr;          /* USR1, USR2 */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 571)   sa.sa_flags = SA_RESTART;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 572)   sigemptyset( &set );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 573)   sigaddset( &set, SIGUSR1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 574)   sigaddset( &set, SIGUSR2 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 575)   sa.sa_mask = set;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 576)   sigaction( SIGUSR1, &sa, NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 577)   sigaction( SIGUSR2, &sa, NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 578) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 579)   memset( &sa, 0, sizeof( sa ) );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 580)   sa.sa_handler = sigint;          /* TERM, INT */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 581)   sa.sa_flags = SA_RESTART;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 582)   sigemptyset( &set );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 583)   sigaddset( &set, SIGTERM );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 584)   sigaddset( &set, SIGINT );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 585)   sa.sa_mask = set;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 586)   sigaction( SIGTERM, &sa, NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 587)   sigaction( SIGINT, &sa,  NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 588) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 589)   memset( &sa, 0, sizeof( sa ) );  /* ignore SIGPIPE */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 590)   sa.sa_handler = SIG_IGN;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 591)   sa.sa_flags = 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 592)   sigaction( SIGPIPE, &sa, NULL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 593) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 594)   /* на случай блокировки сигналов с помощью sigprocmask(): */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 595)   sigemptyset( &blockmask );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 596)   sigaddset( &blockmask, SIGHUP );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 597)   sigaddset( &blockmask, SIGUSR1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 598)   sigaddset( &blockmask, SIGUSR2 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 599)   sigaddset( &blockmask, SIGTERM );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 600)   sigaddset( &blockmask, SIGINT );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 601) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 602)   /* System V fork+wait does not work if SIGCHLD is ignored */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 603)   signal( SIGCHLD, SIG_DFL );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 604) }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 605) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 606) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 607) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 608) int main( int argc, char *argv[] )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 609) {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 610)   gid_t  gid;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 611) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 612)   set_signal_handlers();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 613) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 614)   gid = getgid();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 615)   setgroups( 1, &gid );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 616) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 617)   fatal_error_hook = fatal_error_actions;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 618) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 619)   program = basename( argv[0] );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 620)   get_args( argc, argv );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 621) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 622)   if( getppid() != 1 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 623)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 624)     if( run_as_daemon ) daemon( 1, 0 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 625)   }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 626) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 627)   init_logs();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 628)   logpid();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 629) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 630)   LOG( "Start cScm Configuration Daemon..." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 631) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 632)   parse_config_file();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 633) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 634)   if( config_inotify ) init_config_inotify();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 635) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 636)   for( ;; )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 637)   {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 638)     int    max_sd;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 639)     struct timeval timeout;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 640)     fd_set listen_set;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 641) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 642)     /*************************************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 643)       Waiting for events from inotify_fd:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 644)      */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 645)     max_sd = inotify_fd + 1;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 646)     FD_ZERO( &listen_set );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 647)     FD_SET( inotify_fd, &listen_set );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 648) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 649)     do
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 650)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 651)       int rc;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 652) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 653)       /*********************************************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 654)         Initialize the timeval struct to 5 seconds:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 655)        */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 656)       timeout.tv_sec  = 5;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 657)       timeout.tv_usec = 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 658) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 659)       rc = select( max_sd, &listen_set, NULL, NULL, &timeout );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 660) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 661)       /*****************************************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 662)         Check to see if the select call failed:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 663)        */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 664)       if( rc < 0 && errno != EINTR )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 665)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 666)         WARNING( "%s: inotify select() failed", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 667)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 668)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 669) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 670)       /************************************************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 671)         Check to see if the 5 second time out expired:
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 672)        */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 673)       if( rc == 0 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 674)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 675)         /* Here we can output some log info. */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 676)         break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 677)       }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 678) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 679)       if( FD_ISSET( inotify_fd, &listen_set ) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 680)       {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 681)         ssize_t  n;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 682)         char    *p;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 683) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 684)         n = read( inotify_fd, buf, IN_BUFFER_SIZE );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 685)         if( n == 0 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 686)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 687)           ERROR( "%s: read() from inotify file descriptor returned '0'", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 688)           LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 689)           free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 690)           exit( 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 691)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 692)         if( n == -1 )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 693)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 694)           ERROR( "%s: read() from inotify file descriptor returned '-1'", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 695)           LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 696)           free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 697)           exit( 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 698)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 699) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 700)         for( p = buf; p < buf + n; )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 701)         {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 702)           event = (struct inotify_event *)p;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 703)           /************************************************************
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 704)             в принципе, нам хватает одного события и, если мы получили
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 705)             нужное событие и перечитали config file, то здесь мы можем
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 706)             выйти из цикла чтения событий с помощью break
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 707)            */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 708)           if( check_event( event ) )
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 709)           {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 710)             LOG( "Config file '%s' has been changed. Read new config content...", config_fname );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 711)             parse_config_file();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 712)             break;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 713)           }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 714)           p += sizeof(struct inotify_event) + event->len;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 715)         }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 716) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 717)       } /* End if( FD_ISSET() ) */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 718) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 719)     } while( 1 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 720) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 721)     /*
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 722)       Здесь мы можем выполнить действия, которые необходимы
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 723)       в том случае, если в течение 5-и секунд мы не получили
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 724)       ни одного сигнала об изменении дескриптора inotify_fd.
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 725)      */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 726)     {
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 727)       sleep( 5 );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 728)     }
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 729) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 730)   } /* End of waiting for( ;; ) */
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 731) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 732) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 733)   LOG( "Stop cScm Configuration Daemon." );
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 734)   free_resources();
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 735) 
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 736)   return 0;
12c7b1c5 (kx 2023-03-24 02:53:04 +0300 737) }