source: trunk/src/samhain.c

Last change on this file was 550, checked in by katerina, 2 years ago

Fix for ticket #442 (support for OpenBSD signify).

File size: 54.2 KB
Line 
1/* SAMHAIN file system integrity testing                                   */
2/* Copyright (C) 1999, 2000 Rainer Wichmann                                */
3/*                                                                         */
4/*  This program is free software; you can redistribute it                 */
5/*  and/or modify                                                          */
6/*  it under the terms of the GNU General Public License as                */
7/*  published by                                                           */
8/*  the Free Software Foundation; either version 2 of the License, or      */
9/*  (at your option) any later version.                                    */
10/*                                                                         */
11/*  This program is distributed in the hope that it will be useful,        */
12/*  but WITHOUT ANY WARRANTY; without even the implied warranty of         */
13/*  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the          */
14/*  GNU General Public License for more details.                           */
15/*                                                                         */
16/*  You should have received a copy of the GNU General Public License      */
17/*  along with this program; if not, write to the Free Software            */
18/*  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.              */
19
20#include "config_xor.h"
21
22
23#include <stdio.h>
24#include <stdlib.h>
25#include <string.h>
26#include <unistd.h>
27#include <fcntl.h>
28
29/* samhainctl */
30#include <sys/types.h>
31#include <sys/stat.h>
32#include <sys/wait.h>
33#include <signal.h>
34#include <errno.h>
35
36
37#if TIME_WITH_SYS_TIME
38#include <sys/time.h>
39#include <time.h>
40#else
41#if HAVE_SYS_TIME_H
42#include <sys/time.h>
43#else
44#include <time.h>
45#endif
46#endif
47
48#ifdef HAVE_MEMORY_H
49#include <memory.h>
50#endif
51
52#ifdef HAVE_SETPRIORITY
53#include <sys/resource.h>
54#endif
55
56#ifndef HAVE_LSTAT
57#define lstat stat
58#endif
59
60/* for FLT_EPSILON
61 */
62#include <float.h>
63
64#include "samhain.h"
65#include "sh_pthread.h"
66#include "sh_utils.h"
67#include "sh_error.h"
68#include "sh_unix.h"
69#include "sh_files.h"
70#include "sh_getopt.h"
71#include "sh_readconf.h"
72#include "sh_hash.h"
73#include "sh_dbIO.h"
74#include "sh_restrict.h"
75
76#include "sh_nmail.h"
77
78#include "sh_tiger.h"
79#include "sh_sig.h"
80#include "sh_mem.h"
81#include "sh_xfer.h"
82#include "sh_tools.h"
83#include "sh_hash.h"
84#if defined(WITH_EXTERNAL)
85#include "sh_extern.h"
86#endif
87#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
88#include "sh_modules.h"
89#include "sh_ignore.h"
90#include "sh_prelink.h"
91#include "sh_sem.h"
92#endif
93
94#undef  FIL__
95#define FIL__  _("samhain.c")
96
97
98/**************************************************
99 *
100 * Needed to compile the key into the code.
101 *
102 **************************************************/
103
104extern UINT32  ErrFlag[2];
105#include "sh_MK.h"
106
107/**************************************************
108 *
109 * Variables for signal handling.
110 *
111 **************************************************/
112
113volatile  int      sig_raised;
114volatile  int      sig_urgent;
115volatile  int      sig_debug_switch;       /* SIGUSR1 */
116volatile  int      sig_suspend_switch;     /* SIGUSR2 */
117volatile  int      sh_global_suspend_flag;
118volatile  int      sig_fresh_trail;        /* SIGIOT  */
119volatile  int      sh_thread_pause_flag = S_FALSE;
120volatile  int      sig_config_read_again;  /* SIGHUP  */
121volatile  int      sig_terminate;          /* SIGQUIT */
122volatile  int      sig_termfast;           /* SIGTERM */
123volatile  int      sig_force_check;        /* SIGTTOU */
124volatile  int      sig_force_silent;       /* SIGTSTP */
125volatile  int      sh_global_check_silent;
126volatile  int      sh_load_delta_flag;
127long int           eintr__result;
128char               sh_sig_msg[SH_MINIBUF];
129
130
131#ifdef SH_STEALTH
132/**************************************************
133 *
134 * The following set of functions is required for
135 * the 'stealth' mode.
136 *
137 **************************************************/
138
139#ifndef SH_MAX_GLOBS
140#define SH_MAX_GLOBS 16
141#endif
142
143#ifndef GLOB_LEN
144#define GLOB_LEN 511
145#endif
146
147#ifdef HAVE_PTHREAD
148struct gt {
149  size_t g_count;
150  char * g_glob;
151};
152
153pthread_key_t g_key;
154
155int sh_g_thread()
156{
157  struct gt * ptr = calloc(1,sizeof(struct gt));
158  if (!ptr)
159    return -1;
160  ptr->g_count    = 0;
161  ptr->g_glob     = calloc(1, SH_MAX_GLOBS * (GLOB_LEN+1));
162  if (!(ptr->g_glob))
163    {
164      free(ptr);
165      return -1;
166    }
167  return pthread_setspecific(g_key, ptr);
168}
169
170void sh_g_destroy(void * data)
171{
172  struct gt * ptr = (struct gt *) data;
173  free(ptr->g_glob);
174  free(ptr);
175  return;
176}
177
178void sh_g_init(void)
179{
180#if !defined(USE_SYSTEM_MALLOC) && defined(USE_MALLOC_LOCK)
181  extern int dnmalloc_pthread_init(void);
182  dnmalloc_pthread_init();
183#endif
184
185  if (0 != pthread_key_create(&g_key, sh_g_destroy))
186    {
187      perror("1");
188      exit(EXIT_FAILURE);
189    }
190
191  if (0 != sh_g_thread())
192    {
193      perror("2");
194      exit(EXIT_FAILURE);
195    }
196  return;
197}
198#define SH_G_INIT sh_g_init()
199#else
200#define SH_G_INIT ((void)0)
201#endif
202
203char * globber(const char * str)
204{
205  size_t i;
206  size_t j;
207
208#ifndef HAVE_PTHREAD
209  static   size_t  count = 0;
210  static   char glob[SH_MAX_GLOBS * (GLOB_LEN+1)];
211#else
212  struct gt * ptr = pthread_getspecific(g_key);
213  size_t count;
214  char *  glob;
215
216  if (ptr) {
217    count = ptr->g_count;
218    glob  = ptr->g_glob;
219  } else {
220    return NULL;
221  }
222#endif
223
224  if (str != NULL)
225    j = strlen(str);
226  else
227    return NULL;
228
229  ASSERT((j <= GLOB_LEN), _("j <= GLOB_LEN"))
230
231  if (j > GLOB_LEN) 
232    j = GLOB_LEN;
233
234  /* Overwrap the buffer.
235   */
236  if ( (count + j) >= (SH_MAX_GLOBS * (GLOB_LEN+1)))
237    {
238      count = 0;
239    }
240
241  for (i = 0; i < j; ++i)
242    {
243      if (str[i] != '\n' && str[i] != '\t' && str[i] != '\r' && str[i] != '"')
244        glob[count + i] = str[i] ^ XOR_CODE;
245      else
246        glob[count + i] = str[i];
247    }
248  glob[count + j] = '\0';
249
250  i     = count;
251#ifdef HAVE_PTHREAD
252  ptr->g_count = count + j + 1;
253#else
254  count = count + j + 1;
255#endif
256  return &glob[i];
257}
258
259void sh_do_encode (char * str, int len)
260{
261  register          int i;
262
263  /* this is a symmetric operation
264   */
265  for (i = 0; i < len; ++i)
266    {
267      str[i] = str[i] ^ XOR_CODE;
268    }
269  return;
270}
271
272#else
273/* not stealth */
274#define SH_G_INIT ((void)0)
275#endif
276
277/**************************************************
278 *
279 * Global variables.
280 *
281 **************************************************/
282
283sh_struct   sh;
284/*@null@*/ sh_key_t  * skey = NULL;
285
286extern unsigned char TcpFlag[8][PW_LEN+1];
287
288/**************************************************
289 *
290 * Initializing.
291 *
292 **************************************************/
293
294static int is_samhainctl_init = S_FALSE;
295
296static
297void sh_init (void)
298{
299  unsigned char * dez = NULL;
300  int             i;
301#if defined(SH_WITH_MAIL)
302  char          * p;
303  char            q[SH_PATHBUF];
304#endif
305
306  SL_ENTER(_("sh_init"));
307
308#ifdef MKA_09
309  ErrFlag[0] |= (1 << 8);
310#endif
311#ifdef MKA_10
312  ErrFlag[0] |= (1 << 9);
313#endif
314#ifdef MKA_11
315  ErrFlag[0] |= (1 << 10);
316#endif
317#ifdef MKA_12
318  ErrFlag[0] |= (1 << 11);
319#endif
320
321  sh.delayload = 0;
322
323#ifdef MKA_13
324  ErrFlag[0] |= (1 << 12);
325#endif
326#ifdef MKA_14
327  ErrFlag[0] |= (1 << 13);
328#endif
329#ifdef MKA_15
330  ErrFlag[0] |= (1 << 14);
331#endif
332#ifdef MKA_16
333  ErrFlag[0] |= (1 << 15);
334#endif
335
336  /* Signal handling.
337   */
338  sig_raised             = 0;
339  sig_config_read_again  = 0;           /* SIGHUP  */
340  sig_debug_switch       = 0;           /* SIGUSR1 */
341  sig_suspend_switch     = 0;           /* SIGUSR2 */
342  sh_global_suspend_flag = 0;           /* SIGUSR2 */
343  sig_fresh_trail        = 0;           /* SIGIOT  */
344  sig_terminate          = 0;           /* SIGQUIT */
345  sig_termfast           = 0;           /* SIGTERM */
346  sig_force_check        = 0;           /* SIGTTOU */
347  sig_force_silent       = 0;           /* SIGTSTP */
348  sh_global_check_silent = 0;
349  sh_load_delta_flag     = 0;
350  sh_sig_msg[4] = '\0';
351  sh_sig_msg[3] = 'e';
352  sh_sig_msg[2] = 'n';
353  sh_sig_msg[1] = 'o';
354  sh_sig_msg[0] = 'N';
355
356#ifdef MKB_01
357  ErrFlag[1] |= (1 << 0);
358#endif
359#ifdef MKB_02
360  ErrFlag[1] |= (1 << 1);
361#endif
362#ifdef MKB_03
363  ErrFlag[1] |= (1 << 2);
364#endif
365#ifdef MKB_04
366  ErrFlag[1] |= (1 << 3);
367#endif
368#ifdef MKB_05
369  ErrFlag[1] |= (1 << 4);
370#endif
371#ifdef MKB_06
372  ErrFlag[1] |= (1 << 5);
373#endif
374#ifdef MKB_07
375  ErrFlag[1] |= (1 << 6);
376#endif
377#ifdef MKB_08
378  ErrFlag[1] |= (1 << 7);
379#endif
380
381#if defined(SH_WITH_SERVER) && !defined(SH_WITH_CLIENT)
382  strncpy(sh.prg_name, _("Yule"), 8);
383  sh.prg_name[4] = '\0';
384#else
385  strncpy(sh.prg_name, _("Samhain"), 8);
386  sh.prg_name[7] = '\0';
387#endif
388
389  sh.pid = (UINT64) getpid();
390
391  sh.outpath = NULL;
392
393  /* The flags.
394   */
395  if (is_samhainctl_init == S_FALSE)
396    sh.flag.checkSum        = SH_CHECK_NONE;
397  sh.flag.update          = S_FALSE;
398  sh.flag.opts            = S_FALSE;
399  sh.flag.started         = S_FALSE;
400  if (is_samhainctl_init == S_FALSE)
401    sh.flag.isdaemon        = S_FALSE;
402  sh.flag.isserver        = S_FALSE;
403  sh.flag.islocked        = S_FALSE;
404  sh.flag.smsg            = S_FALSE;
405  sh.flag.log_start       = S_TRUE;
406  sh.flag.reportonce      = S_TRUE;
407  sh.flag.fulldetail      = S_FALSE;
408  sh.flag.audit           = S_FALSE;
409  sh.flag.nice            = 0;
410  sh.flag.aud_mask        = 0xFFFFFFFFUL;
411  sh.flag.client_severity = S_FALSE;
412  sh.flag.client_class    = S_FALSE;
413  sh.flag.hidefile        = S_FALSE;
414  sh.flag.loop            = S_FALSE;
415  sh.flag.inotify         = 0;
416
417#ifdef MKB_09
418  ErrFlag[1] |= (1 << 8);
419#endif
420#ifdef MKB_10
421  ErrFlag[1] |= (1 << 9);
422#endif
423#ifdef MKB_11
424  ErrFlag[1] |= (1 << 10);
425#endif
426#ifdef MKB_12
427  ErrFlag[1] |= (1 << 11);
428#endif
429#ifdef MKB_13
430  ErrFlag[1] |= (1 << 12);
431#endif
432#ifdef MKB_14
433  ErrFlag[1] |= (1 << 13);
434#endif
435#ifdef MKB_15
436  ErrFlag[1] |= (1 << 14);
437#endif
438#ifdef MKB_16
439  ErrFlag[1] |= (1 << 15);
440#endif
441
442  /* The stats.
443   */
444  sh.statistics.bytes_speed   = 0;
445  sh.statistics.bytes_hashed  = 0;
446  sh.statistics.files_report  = 0;
447  sh.statistics.files_error   = 0;
448  sh.statistics.files_nodir   = 0;
449
450  sh.statistics.mail_success = 0;
451  sh.statistics.mail_failed  = 0;
452  sh.statistics.time_start   = time(NULL);
453  sh.statistics.time_check   = (time_t) 0;
454
455#ifdef MKC_01
456  ErrFlag[0] |= (1 << 16);
457#endif
458#ifdef MKC_02
459  ErrFlag[0] |= (1 << 17);
460#endif
461#ifdef MKC_03
462  ErrFlag[0] |= (1 << 18);
463#endif
464#ifdef MKC_04
465  ErrFlag[0] |= (1 << 19);
466#endif
467#ifdef MKC_05
468  ErrFlag[0] |= (1 << 20);
469#endif
470#ifdef MKC_06
471  ErrFlag[0] |= (1 << 21);
472#endif
473#ifdef MKC_07
474  ErrFlag[0] |= (1 << 22);
475#endif
476#ifdef MKC_08
477  ErrFlag[0] |= (1 << 23);
478#endif
479
480
481  /* The local host.
482   */
483  (void) sl_strlcpy (sh.host.name,  _("localhost"),  SH_MINIBUF);
484  sh.host.system[0]     = '\0'; /* flawfinder: ignore *//* ff bug */
485  sh.host.release[0]    = '\0';
486  sh.host.machine[0]    = '\0';
487
488#ifdef MKC_09
489  ErrFlag[0] |= (1 << 24);
490#endif
491#ifdef MKC_10
492  ErrFlag[0] |= (1 << 25);
493#endif
494#ifdef MKC_11
495  ErrFlag[0] |= (1 << 26);
496#endif
497#ifdef MKC_12
498  ErrFlag[0] |= (1 << 27);
499#endif
500#ifdef MKC_13
501  ErrFlag[0] |= (1 << 28);
502#endif
503#ifdef MKC_14
504  ErrFlag[0] |= (1 << 29);
505#endif
506#ifdef MKC_15
507  ErrFlag[0] |= (1 << 30);
508#endif
509#ifdef MKC_16
510  ErrFlag[0] |= (1UL << 31);
511#endif
512
513  /* The paths.
514   */
515  (void) sl_strlcpy (sh.conf.path,  DEFAULT_CONFIGFILE,    SH_PATHBUF);
516  sh.conf.hash[0] = '\0';
517  (void) sl_strlcpy (sh.data.path,  DEFAULT_DATA_FILE,     SH_PATHBUF);
518  sh.data.hash[0] = '\0';
519  sh.exec.path[0] = '\0';
520  sh.exec.hash[0] = '\0';
521
522#ifdef MKD_01
523  ErrFlag[1] |= (1 << 16);
524#endif
525#ifdef MKD_02
526  ErrFlag[1] |= (1 << 17);
527#endif
528#ifdef MKD_03
529  ErrFlag[1] |= (1 << 18);
530#endif
531#ifdef MKD_04
532  ErrFlag[1] |= (1 << 19);
533#endif
534#ifdef MKD_05
535  ErrFlag[1] |= (1 << 20);
536#endif
537#ifdef MKD_06
538  ErrFlag[1] |= (1 << 21);
539#endif
540#ifdef MKD_07
541  ErrFlag[1] |= (1 << 22);
542#endif
543#ifdef MKD_08
544  ErrFlag[1] |= (1 << 23);
545#endif
546
547  /* The addresses.
548   */
549#if defined(SH_WITH_MAIL)
550  if (0 != strcmp (DEFAULT_MAILADDRESS, _("NULL")))
551    {
552#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
553      char * saveptr;
554      (void) sl_strncpy(q, DEFAULT_MAILADDRESS, SH_PATHBUF);
555      p = strtok_r (q, ", \t", &saveptr);
556      if (p)
557        {
558          (void) sh_nmail_add_compiled_recipient (p);
559          while (NULL != (p = strtok_r (NULL, ", \t", &saveptr)))
560            (void) sh_nmail_add_compiled_recipient (p);
561        }
562#else
563      (void) sl_strncpy(q, DEFAULT_MAILADDRESS, SH_PATHBUF);
564      p = strtok (q, ", \t");
565      if (p)
566        {
567          (void) sh_nmail_add_compiled_recipient (p);
568          while (NULL != (p = strtok (NULL, ", \t")))
569            (void) sh_nmail_add_compiled_recipient (p);
570        }
571#endif
572    }
573#endif
574
575  if (0 == strcmp (ALT_TIMESERVER, _("NULL")))
576    sh.srvtime.alt[0] = '\0';
577  else
578    (void) sl_strlcpy (sh.srvtime.alt, ALT_TIMESERVER,        SH_PATHBUF);
579  if (0 == strcmp (DEFAULT_TIMESERVER, _("NULL")))
580    sh.srvtime.name[0] = '\0';
581  else
582    (void) sl_strlcpy (sh.srvtime.name, DEFAULT_TIMESERVER,   SH_PATHBUF);
583
584
585  if (0 == strcmp (ALT_LOGSERVER, _("NULL")))
586    sh.srvexport.alt[0] = '\0';
587  else
588    (void) sl_strlcpy (sh.srvexport.alt,  ALT_LOGSERVER,  SH_PATHBUF);
589  if (0 == strcmp (DEFAULT_LOGSERVER, _("NULL")))
590    sh.srvexport.name[0] = '\0';
591  else
592    (void) sl_strlcpy (sh.srvexport.name,  DEFAULT_LOGSERVER, SH_PATHBUF);
593
594
595  if (0 == strcmp (DEFAULT_ERRLOCK, _("NULL")))
596    sh.srvlog.alt[0] = '\0';
597  else
598    (void) sl_strlcpy (sh.srvlog.alt,  DEFAULT_ERRLOCK,       SH_PATHBUF);
599  if (0 == strcmp (DEFAULT_ERRFILE, _("NULL")))
600    sh.srvlog.name[0] = '\0';
601  else
602    (void) sl_strlcpy (sh.srvlog.name,  DEFAULT_ERRFILE,      SH_PATHBUF);
603
604  if (0 == strcmp (ALT_CONSOLE, _("NULL")))
605    sh.srvcons.alt[0] = '\0';
606  else
607    (void) sl_strlcpy (sh.srvcons.alt,  ALT_CONSOLE,          SH_PATHBUF);
608#ifndef DEFAULT_CONSOLE
609  (void) sl_strlcpy (sh.srvcons.name, _("/dev/console"),    SH_PATHBUF);
610#else
611  if (0 == strcmp (DEFAULT_CONSOLE, _("NULL")))
612    (void) sl_strlcpy (sh.srvcons.name, _("/dev/console"),    SH_PATHBUF);
613  else
614    (void) sl_strlcpy (sh.srvcons.name,  DEFAULT_CONSOLE,     SH_PATHBUF);
615#endif
616
617#ifdef MKD_09
618  ErrFlag[1] |= (1 << 24);
619#endif
620#ifdef MKD_10
621  ErrFlag[1] |= (1 << 25);
622#endif
623#ifdef MKD_11
624  ErrFlag[1] |= (1 << 26);
625#endif
626#ifdef MKD_12
627  ErrFlag[1] |= (1 << 27);
628#endif
629#ifdef MKD_13
630  ErrFlag[1] |= (1 << 28);
631#endif
632#ifdef MKD_14
633  ErrFlag[1] |= (1 << 29);
634#endif
635#ifdef MKD_15
636  ErrFlag[1] |= (1 << 30);
637#endif
638#ifdef MKD_16
639  ErrFlag[1] |= (1UL << 31);
640#endif
641
642
643  /* The timers.
644   */
645  sh.fileCheck.alarm_last     = 0;
646  sh.fileCheck.alarm_interval = 600; /* ten minutes */
647
648  sh.mailTime.alarm_last     = 0;
649  sh.mailTime.alarm_interval = 86400;
650
651  sh.mailNum.alarm_last      = 0;
652  sh.mailNum.alarm_interval  = 10;
653
654  sh.looptime     = 60;
655
656#ifdef SCREW_IT_UP
657  sh.sigtrap_max_duration = 500000; /* 500ms */
658#endif
659
660  /* The struct to hold privileged information.
661   */
662  skey = calloc(1,sizeof(sh_key_t));
663  if (skey != NULL)
664    {
665
666      skey->mlock_failed = S_FALSE;
667      skey->rngI         = BAD;
668      /* properly initialized later
669       */
670      skey->rng0[0] = 0x03; skey->rng0[1] = 0x09; skey->rng0[2] = 0x17;
671      skey->rng1[0] = 0x03; skey->rng1[1] = 0x09; skey->rng1[2] = 0x17;
672      skey->rng2[0] = 0x03; skey->rng2[1] = 0x09; skey->rng2[2] = 0x17;
673     
674      for (i = 0; i < KEY_BYT; ++i)
675        skey->poolv[i] = '\0';
676     
677      skey->poolc        = 0;
678     
679      skey->ErrFlag[0]   = ErrFlag[0];
680      ErrFlag[0]         = 0;
681      skey->ErrFlag[1]   = ErrFlag[1];
682      ErrFlag[1]         = 0;
683     
684      dez = &(TcpFlag[POS_TF-1][0]);
685      for (i = 0; i < PW_LEN; ++i)
686        { 
687          skey->pw[i] = (char) (*dez); 
688          (*dez)      = '\0';
689          ++dez; 
690        }
691     
692      skey->sh_sockpass[0]  = '\0';
693      skey->sigkey_old[0]   = '\0';
694      skey->sigkey_new[0]   = '\0';
695      skey->mailkey_old[0]  = '\0';
696      skey->mailkey_new[0]  = '\0';
697      skey->crypt[0]        = '\0'; /* flawfinder: ignore *//* ff bug */
698      skey->session[0]      = '\0';
699      skey->vernam[0]       = '\0';
700    }
701  else
702    {
703      perror(_("sh_init"));
704      _exit (EXIT_FAILURE);
705    }
706
707  sh_unix_memlock();
708  SL_RET0(_("sh_init"));
709}
710
711
712#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
713#include <sys/mman.h>
714#endif
715
716#if defined(SH_USE_XML)
717extern int    sh_log_file    (char * message, char * inet_peer);
718#endif
719
720/*******************************************************
721 *
722 * Exit Handler
723 *
724 *******************************************************/
725static void exit_handler(void)
726{
727  /* --- Clean up modules, if any. ---
728   */
729#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
730  int modnum;
731#endif
732#if defined(SH_WITH_SERVER)
733  extern int sh_socket_remove (void);
734  extern int sh_html_zero();
735#endif
736
737#if defined(SH_WITH_SERVER)
738  sh_socket_remove ();
739#endif
740
741#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
742  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
743    {
744      if (modList[modnum].initval == SH_MOD_ACTIVE)
745        (void) modList[modnum].mod_cleanup();
746    }
747#ifdef HAVE_PTHREAD
748  sh_pthread_cancel_all();
749#endif
750#endif
751
752  /* --- Push out all pending messages. ---
753   */
754#if defined(SH_WITH_MAIL)
755  if (sh.mailNum.alarm_last > 0) 
756    {
757      (void) sh_nmail_flush ();
758    }
759#endif
760
761  /* --- Write the server stat. ---
762   */
763#if defined(SH_WITH_SERVER)
764  /* zero out the status file at exit, such that the status
765   * of client becomes unknown in the beltane interface
766   */
767  sh_html_zero();
768#endif
769
770  /* --- Clean up memory to check for problems. ---
771   */
772#ifdef MEM_DEBUG
773#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
774  sh_files_deldirstack ();
775  sh_files_delfilestack ();
776  sh_files_delglobstack ();
777  sh_hash_hashdelete();
778  sh_files_hle_reg (NULL);
779  /*
780   * Only flush on exit if running as deamon.
781   * Otherwise we couldn't run another instance
782   * while the deamon is running (would leave the
783   * deamon with flushed ruleset).
784   */
785  if (sh.flag.isdaemon == S_TRUE)
786    {
787      sh_audit_delete_all ();
788    }
789#endif
790#if defined(SH_WITH_SERVER)
791  sh_xfer_free_all ();
792#endif
793#if defined(SH_WITH_MAIL)
794  sh_nmail_free();
795#endif
796  delete_cache();
797  sh_userid_destroy ();
798  sh_mem_stat();
799#endif
800
801#ifdef MEM_DEBUG
802  sh_unix_count_mlock();
803#endif
804
805  /* --- Checksum of executable. ---
806   */
807  {
808    volatile  int sig_store = sig_termfast;
809
810    sig_termfast = 0;
811    (void) sh_unix_self_check();
812    sig_termfast = sig_store;
813  }
814
815
816  /* --- Exit Message. ---
817   */
818  if (sh.flag.exit == EXIT_FAILURE && !strcmp(sh_sig_msg, _("None")))
819    sl_strlcpy(sh_sig_msg, _("exit_failure"), SH_MINIBUF);
820  if (sh.flag.exit == EXIT_SUCCESS && !strcmp(sh_sig_msg, _("None")))
821    sl_strlcpy(sh_sig_msg, _("exit_success"), SH_MINIBUF);
822  sh_error_handle ((-1), FIL__, __LINE__, sh.flag.exit, MSG_EXIT_NORMAL, 
823                   sh.prg_name, sh_sig_msg);
824#ifdef SH_USE_XML
825  (void) sh_log_file (NULL, NULL);
826#endif
827
828
829  /* --- Restrict error logging to stderr. ---
830   */
831  close_ipc ();
832  sh_error_only_stderr (S_TRUE);
833
834  /* --- Remove lock, delete critical information. ---
835   */
836  (void) sh_unix_rm_lock_file (sh.srvlog.name);
837  if (sh.flag.isdaemon == S_TRUE)
838    (void) sh_unix_rm_pid_file ();
839  if (skey != NULL)
840    memset (skey, 0, sizeof(sh_key_t));
841 
842  /* --- Exit. ---
843   */
844  SL_RET0(_("exit_handler"));
845}
846
847/***********************************************************
848 *
849 */
850#ifndef SIGHUP
851#define SIGHUP   1
852#endif
853#ifndef SIGTERM
854#define SIGTERM 15
855#endif
856#ifndef SIGKILL
857#define SIGKILL  9
858#endif
859
860#if defined(__linux__) || defined(sun) || defined(__sun) || defined(__sun__)
861#include <dirent.h>
862static pid_t * procdirSamhain (void)
863{
864  pid_t        * pidlist;
865  struct dirent * d;
866  DIR *        dp;
867  long         ino;
868  struct stat  buf;
869  int          i;
870  pid_t        pid, mypid = getpid();
871  char       * tail;
872  char         exef[128];
873
874  if (0 != stat(SH_INSTALL_PATH, &buf))
875    {
876      return NULL;
877    }
878
879  ino = (long) buf.st_ino;
880   
881  if (NULL == (dp = opendir(_("/proc"))))
882    {
883      /* cppcheck-suppress resourceLeak */
884      return NULL;
885    }
886
887  SH_MUTEX_LOCK(mutex_readdir);
888
889  pidlist =  calloc(1, sizeof(pid_t) * 65535);
890  if (!pidlist)
891    goto unlock_and_out;
892
893  for (i = 0; i < 65535; ++i) pidlist[i] = 0;
894
895  i = 0;
896  while (NULL != (d = readdir(dp)) && i < 65535)
897    {
898      if (0 != strcmp(d->d_name, ".") && 0 != strcmp(d->d_name, ".."))
899        {
900          errno = 0;
901          pid = (pid_t) strtol (d->d_name, &tail, 0);
902          if (*tail != '\0' || errno != 0)
903            continue;
904          if (pid == mypid)
905            continue;
906#if defined(__linux__)
907          sprintf(exef, _("/proc/%d/exe"), (int) pid); /* known to fit  */
908#else
909          sprintf(exef, _("/proc/%d/object/a.out"),    /* known to fit  */
910                  (int) pid);
911#endif
912          if (0 == stat(exef, &buf) && ino == (long) buf.st_ino)
913            { pidlist[i] = (pid_t) pid; ++i; }
914        }
915    }
916
917 unlock_and_out:
918  ;
919  SH_MUTEX_UNLOCK(mutex_readdir);
920
921  closedir(dp);
922  return pidlist;
923}
924#else
925static pid_t * procdirSamhain (void)
926{
927  return NULL;
928}
929#endif
930
931static int killprocSamhain (pid_t pid)
932{
933  int i;
934
935  /* fprintf(stderr, "Killing %d\n", pid); */
936  if (pid > 0 && 0 == kill (pid, SIGTERM))
937    {
938      for (i = 0; i < 16; ++i)
939        {
940          (void) retry_msleep(1, 0);
941          if (0 != kill (pid, 0) && errno == ESRCH)
942            return (0);
943        }
944     
945      (void) kill (pid, SIGKILL);
946      return (0);
947    }
948  if (pid > 0)
949    {
950      if (errno == ESRCH)
951        return 7;
952      if (errno == EPERM)
953        return 4;
954      return 1;
955    }
956  else
957    return (7);
958}
959
960static pid_t pidofSamhain (int flag)
961{
962  FILE      * fp;
963  char        line[256];
964  char      * tail;
965  char      * p;
966  pid_t       pid;
967  long        inpid;
968  struct stat buf;
969 
970  fp = fopen (DEFAULT_ERRLOCK, "r");
971
972  if (!fp)
973    { if (errno != ENOENT) perror(_("fopen")); return 0; }
974  if (NULL == fgets(line, sizeof(line), fp))
975    { perror(_("fgets")); (void) sl_fclose(FIL__, __LINE__, fp); return 0; }
976  (void) sl_fclose(FIL__, __LINE__, fp); 
977  p = line; 
978  while (*p == ' '  || *p == '\f' || *p == '\n' || 
979         *p == '\r' || *p == '\t' || *p == '\v')
980    ++p;
981  errno = 0;
982  inpid = strtol (p, &tail, 0);
983  if (p == tail || errno != 0)
984    { perror(_("strtol")); return 0; }
985
986  pid = (pid_t) inpid;
987  if (inpid != (long) pid)
988    { perror(_("strtol")); return 0; }
989
990  /* remove stale pid file
991   */
992  if (flag == 1 && pid > 0 && 0 != kill(pid, 0) && errno == ESRCH)
993    {
994      if /*@-unrecog@*/ (0 == lstat (DEFAULT_ERRLOCK, &buf))/*@+unrecog@*/
995        {
996          if /*@-usedef@*/(S_ISREG(buf.st_mode))/*@+usedef@*/ 
997            {
998              (void) unlink(DEFAULT_ERRLOCK);
999            }
1000        }
1001      else 
1002        {
1003          perror(_("lstat")); return 0;
1004        }
1005      pid = 0;
1006    }
1007  return pid;
1008}
1009
1010/* 1: start 2:stop 3:reload 4:status
1011 */
1012/*@-exitarg@*/
1013static int samhainctl(int ctl, int * argc, char * argv[])
1014{
1015  char * fullpath;
1016  pid_t  pid;
1017  int    status;
1018  int    res;
1019  pid_t  respid;
1020  int    times;
1021  char * argp[32];
1022  pid_t       * pidlist;
1023  int         i;
1024#ifdef WCONTINUED
1025      int wflags = WNOHANG|WUNTRACED|WCONTINUED;
1026#else
1027      int wflags = WNOHANG|WUNTRACED;
1028#endif
1029
1030  fullpath = strdup (SH_INSTALL_PATH);
1031  if (fullpath == NULL)
1032    { perror(_("strdup")); exit (1); }
1033
1034  argp[0]  = strdup (SH_INSTALL_PATH);
1035  if (argp[0] == NULL)
1036    { perror(_("strdup")); exit (1); }
1037
1038  for (times = 1; times < 32; ++times)  argp[times] = NULL;
1039
1040  res = (*argc > 32) ? 32 : *argc;
1041
1042  for (times = 2; times < res; ++times) 
1043    {
1044      argp[times-1] = strdup (argv[times]);
1045      if (argp[times-1] == NULL)
1046        { perror(_("strdup")); exit (1); }
1047    }
1048
1049  if (ctl == 1)
1050    {
1051      pid = pidofSamhain(1);
1052
1053      if (pid != 0 && 0 == kill (pid, 0)) /* already started */
1054        exit (0);
1055
1056      pid = fork();
1057      switch (pid) {
1058      case ((pid_t) -1):
1059        perror(_("fork"));
1060        exit (1);
1061      case  0:
1062        if (0 != sl_close_fd (FIL__, __LINE__, 0))
1063          {
1064            _exit(4);
1065          }
1066        (void) execv(fullpath, argp); /* flawfinder: ignore *//* wtf? */
1067        if (errno == EPERM)
1068          _exit(4);
1069        else if (errno == ENOENT)
1070          _exit(5);
1071        _exit (1);
1072      default:
1073        times = 0;
1074        while (times < 300) {
1075          respid = waitpid(pid, &status, wflags);
1076          if ((pid_t)-1 == respid)
1077            {
1078              perror(_("waitpid"));
1079              exit (1);
1080            }
1081          else if (pid == respid)
1082            {
1083#ifndef USE_UNO
1084              if (0 != WIFEXITED(status))
1085                {
1086                  res = WEXITSTATUS(status);
1087                  exit (res == 0 ? 0 : res );
1088                }
1089              else
1090                exit (1);
1091#else
1092              exit (1);
1093#endif
1094            }
1095          ++times;
1096          (void) retry_msleep(1, 0);
1097        }
1098        exit (0); /* assume that it runs ok */
1099      }
1100    }
1101
1102  pid = pidofSamhain(0);
1103
1104  if (ctl == 2)  /* stop */
1105    {
1106      pidlist = procdirSamhain ();
1107      if (pid == 0 && NULL == pidlist) /* pid file not found */ 
1108        {
1109          free(fullpath);
1110          return (0);
1111        }
1112         
1113      status = 0;
1114      if (pid != 0)
1115         status = killprocSamhain(pid);
1116      if (pidlist != NULL)
1117        {
1118          i = 0; 
1119          while (i < 65535 && pidlist[i] != 0)
1120            { 
1121              if (pidlist[i] != pid) 
1122                status = killprocSamhain(pidlist[i]);
1123              ++i;
1124            }
1125        }
1126      free(fullpath);
1127      if (status == 7)
1128        return 0;
1129      else
1130        return status;
1131    }
1132       
1133  if (ctl == 3)  /* reload */
1134    {
1135      if (pid == 0)
1136        exit (7);
1137      if (0 == kill (pid, SIGHUP))
1138        exit (0);
1139      else
1140        {
1141          if (errno == EPERM)
1142            exit (4);
1143          if (errno == ESRCH)
1144            exit (7);
1145          exit (1);
1146        }
1147    }
1148
1149  if (ctl == 4)  /* status */
1150    {
1151      if (pid == 0)
1152        exit (3);
1153      if (0 == kill (pid, 0))
1154        exit (0);
1155      else
1156        {
1157          if (errno == EPERM)
1158            exit (4);
1159          if (errno == ESRCH)
1160            exit (1);
1161        }
1162    }
1163  free(fullpath); /* silence smatch false positive */
1164  exit (1); /* no exit handler installed yet */
1165  /*@notreached@*/
1166  return (0);
1167}
1168/*@+exitarg@*/
1169
1170#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1171#include "sh_schedule.h"
1172static sh_schedule_t * FileSchedOne = NULL;
1173static sh_schedule_t * FileSchedTwo = NULL;
1174
1175/* free a linked list of schedules
1176 */
1177static sh_schedule_t *  free_sched (sh_schedule_t * isched)
1178{
1179  sh_schedule_t * current = isched;
1180  sh_schedule_t * next    = NULL;
1181
1182  while (current != NULL)
1183    {
1184      next = current->next;
1185      SH_FREE(current);
1186      current = next;
1187    }
1188  return NULL;
1189}
1190
1191/* Add a new schedule to the linked list of schedules
1192 */
1193static sh_schedule_t * sh_set_schedule_int (const char * str, 
1194                                            sh_schedule_t * FileSchedIn, 
1195                                            /*@out@*/ int * status)
1196{
1197  sh_schedule_t * FileSched;
1198
1199  SL_ENTER(_("sh_set_schedule_int"));
1200
1201  if (0 == sl_strncmp(str, _("NULL"), 4))
1202    {
1203      (void) free_sched(FileSchedIn);
1204      FileSchedIn = NULL;
1205      *status = 0;
1206      SL_RETURN(NULL, _("sh_set_schedule_int"));
1207    }
1208
1209  FileSched = SH_ALLOC(sizeof(sh_schedule_t));
1210  *status = create_sched(str, FileSched);
1211  if (*status != 0)
1212    {
1213      SH_FREE(FileSched);
1214      FileSched = NULL;
1215      SL_RETURN(FileSchedIn , _("sh_set_schedule_int"));
1216    }
1217  else {
1218    FileSched->next = FileSchedIn;
1219  }
1220  SL_RETURN(FileSched , _("sh_set_schedule_int"));
1221}
1222
1223/* Add a new schedule to the linked list FileSchedOne
1224 */
1225int sh_set_schedule_one (const char * str)
1226{
1227  int status;
1228  FileSchedOne = sh_set_schedule_int (str, FileSchedOne, &status);
1229  return status;
1230}
1231
1232/* Add a new schedule to the linked list FileSchedTwo
1233 */
1234int sh_set_schedule_two (const char * str)
1235{
1236  int status;
1237  FileSchedTwo = sh_set_schedule_int (str, FileSchedTwo, &status);
1238  return status;
1239}
1240
1241static int sh_flag_silent = S_FALSE;
1242
1243int sh_set_silent_full (const char * str)
1244{
1245  int status = sh_util_flagval(str, &sh_flag_silent);
1246  return status;
1247}
1248
1249
1250void do_reconf()
1251{
1252  int status, modnum;
1253
1254  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_RECONF);
1255 
1256  sh_thread_pause_flag = S_TRUE;
1257
1258  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
1259    {
1260      if (0 != (SH_MODFL_NEEDPAUSED & modList[modnum].flags) &&
1261          modList[modnum].initval == SH_MOD_THREAD)
1262        {
1263          int count = 50;
1264          while (count && 0 == (SH_MODFL_ISPAUSED & modList[modnum].flags))
1265            retry_msleep(0, 100), --count;
1266        }
1267    }
1268 
1269#if defined(WITH_EXTERNAL)
1270  /* delete list of external tasks
1271   */
1272  (void) sh_ext_cleanup();
1273#endif
1274#if defined(SH_WITH_MAIL)
1275  sh_nmail_free();
1276#endif
1277 
1278  /* delete the file list, make all database
1279   * entries visible (allignore = FALSE)
1280   */
1281  (void) sh_files_deldirstack ();
1282  (void) sh_files_delfilestack ();
1283  (void) sh_files_delglobstack ();
1284  (void) sh_ignore_clean ();
1285  (void) hash_full_tree ();
1286  sh_audit_delete_all ();
1287 
1288 
1289#if defined(SH_WITH_CLIENT)
1290  reset_count_dev_server();
1291#endif
1292#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
1293  sh_restrict_purge ();
1294 
1295 
1296  FileSchedOne = free_sched(FileSchedOne);
1297  FileSchedTwo = free_sched(FileSchedTwo);
1298 
1299  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
1300    {
1301      /* sh_thread_pause_flag is true, and we block in lock
1302       * until check has returned, so we are sure check will
1303       * not run until sh_thread_pause_flag is set to false
1304       */
1305      /* if (modList[modnum].initval >= SH_MOD_ACTIVE) */
1306      (void) modList[modnum].mod_reconf();
1307    }
1308#endif
1309 
1310  reset_count_dev_console();
1311  reset_count_dev_time();
1312 
1313  (void) sh_unix_maskreset();
1314 
1315#ifdef RELOAD_DATABASE
1316  sh_hash_hashdelete();
1317
1318  if (0 != sl_strcmp(file_path('D', 'R'), _("REQ_FROM_SERVER")))
1319    {
1320      char hashbuf[KEYBUF_SIZE];
1321      (void) sl_strlcpy(sh.data.hash,
1322                        sh_tiger_hash (file_path('D', 'R'), 
1323                                       TIGER_FILE, TIGER_NOLIM, 
1324                                       hashbuf, sizeof(hashbuf)), 
1325                        KEY_LEN+1);
1326    }
1327#endif
1328  (void) sl_trust_purge_user();
1329  (void) sh_files_hle_reg (NULL);
1330  (void) sh_prelink_run (NULL, NULL, 0, 0);
1331 
1332  /* --------------------------
1333   * --- READ CONFIGURATION ---
1334   * --------------------------
1335   */
1336  (void) sh_readconf_read ();
1337  sig_config_read_again = 0;
1338  (void) sh_files_setrec();
1339  (void) sh_files_test_setup();
1340  sh_audit_commit ();
1341 
1342  if (0 != sh.flag.nice)
1343    {
1344#ifdef HAVE_SETPRIORITY
1345      setpriority(PRIO_PROCESS, 0, sh.flag.nice);
1346#else
1347      nice(sh.flag.nice);
1348#endif
1349    }
1350 
1351  if (sh.flag.checkSum == SH_CHECK_INIT)
1352    {
1353      sh.flag.isdaemon = S_FALSE;
1354      sh.flag.loop     = S_FALSE;
1355    }
1356 
1357 
1358  /* --- Initialize modules. ---
1359   */
1360  TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")));
1361  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
1362    {
1363      status = modList[modnum].mod_init(&(modList[modnum]));
1364     
1365      if (status < 0)
1366        {
1367          if (status == (-1)) {
1368            sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, 
1369                             status, MSG_MOD_FAIL,
1370                             _(modList[modnum].name),
1371                             status+SH_MOD_OFFSET);
1372          } else {
1373            sh_error_handle ((-1), FIL__, __LINE__, 
1374                             status, MSG_MOD_FAIL,
1375                             _(modList[modnum].name),
1376                             status+SH_MOD_OFFSET);
1377          }
1378          modList[modnum].initval = SH_MOD_FAILED;
1379        }
1380      else
1381        {
1382          sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_OK,
1383                           _(modList[modnum].name));
1384          modList[modnum].initval = status;
1385        }
1386    }
1387 
1388  /* module is properly set up now
1389   */
1390  sh_thread_pause_flag = S_FALSE;
1391
1392  return;
1393}
1394
1395static void check_signals (volatile int *flag_check_1, 
1396                           volatile int * flag_check_2)
1397{
1398  if (sig_raised > 0) 
1399    {
1400     
1401      TPT((0, FIL__, __LINE__, _("msg=<Process a signal.>\n")))
1402       
1403        if (sig_termfast == 1)  /* SIGTERM */
1404          {
1405            TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1406            --sig_raised; --sig_urgent;
1407            aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1408          }
1409     
1410      if (sig_force_check == 1) /* SIGTTOU / SIGTSTP */
1411        {
1412          TPT((0, FIL__, __LINE__, _("msg=<Check run triggered.>\n")));
1413          *flag_check_1 = 1; *flag_check_2 = 1;
1414          sig_force_check = 0; --sig_raised;
1415          if (sig_force_silent)
1416            {
1417              sig_force_silent       = 0;
1418              sh_global_check_silent = (sh_flag_silent == S_FALSE) ? SH_SILENT_STD : SH_SILENT_FULL;
1419            }
1420          sh_sem_trylock();
1421        }
1422     
1423      if (sig_config_read_again == 1 && /* SIGHUP */
1424          sh_global_suspend_flag == 0)
1425        {
1426          TPT((0, FIL__, __LINE__, _("msg=<Re-read configuration.>\n")));
1427          do_reconf();
1428          --sig_raised;
1429        }
1430     
1431      if (sig_fresh_trail == 1) /* SIGIOT */
1432        {
1433          if (sh_global_suspend_flag == 0)
1434            {
1435              SH_MUTEX_LOCK(mutex_thread_nolog);
1436             
1437              /* Logfile access
1438               */
1439#ifdef SH_USE_XML
1440              (void) sh_log_file (NULL, NULL);
1441#endif
1442              TPT((0, FIL__, __LINE__, _("msg=<Logfile stop/restart.>\n")));
1443              sh_error_only_stderr (S_TRUE);
1444              (void) sh_unix_rm_lock_file(sh.srvlog.name);
1445              (void) retry_msleep(3, 0);
1446              sh.flag.log_start = S_TRUE;
1447              sh_error_only_stderr (S_FALSE);
1448              sh_thread_pause_flag = S_FALSE;
1449              sig_fresh_trail       = 0;
1450              --sig_raised;
1451              SH_MUTEX_UNLOCK(mutex_thread_nolog);
1452            }
1453        }
1454     
1455      if (sig_terminate == 1)  /* SIGQUIT */
1456        {
1457          TPT((0, FIL__, __LINE__, _("msg=<Terminate.>\n")));
1458          strncpy (sh_sig_msg, _("Quit"), 20);
1459          --sig_raised;
1460          aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1461        }
1462         
1463      if (sig_debug_switch == 1)  /* SIGUSR1 */
1464        {
1465          TPT((0, FIL__, __LINE__, _("msg=<Debug switch.>\n")));
1466          sh_error_dbg_switch();
1467          sig_debug_switch = 0;
1468          --sig_raised;
1469        }
1470         
1471      if (sig_suspend_switch > 0)  /* SIGUSR2 */
1472        {
1473          TPT((0, FIL__, __LINE__, _("msg=<Suspend switch.>\n")));
1474          if (sh_global_suspend_flag != 1) {
1475            SH_MUTEX_LOCK_UNSAFE(mutex_thread_nolog);
1476            sh_global_suspend_flag = 1;
1477            sh_error_handle((-1), FIL__, __LINE__, 0, MSG_SUSPEND, 
1478                            sh.prg_name);
1479          } else {
1480            sh_global_suspend_flag = 0;
1481            SH_MUTEX_UNLOCK_UNSAFE(mutex_thread_nolog);
1482          }
1483          --sig_suspend_switch;
1484          --sig_raised; --sig_urgent;
1485        }
1486
1487      if (sh_load_delta_flag > 0 &&
1488          sh_global_suspend_flag == 0)  /* DELTA Command */
1489        {
1490          if (0 == sh_dbIO_load_delta())
1491            {
1492              --sh_load_delta_flag; --sig_raised;
1493            } 
1494        }
1495
1496      sig_raised = (sig_raised < 0) ? 0 : sig_raised;
1497      sig_urgent = (sig_urgent < 0) ? 0 : sig_urgent;
1498      TPT((0, FIL__, __LINE__, _("msg=<End signal processing.>\n")));
1499    }
1500  return;
1501}
1502
1503void check_for_delta_db()
1504{
1505  /* Need to contact the server.
1506   */
1507  if (sh_global_check_silent < SH_SILENT_FULL)
1508    sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_2);
1509
1510  if (sig_raised > 0 && sh_load_delta_flag > 0)  /* DELTA Command */
1511    {
1512      /* There was a DELTA Command
1513       */
1514      if (0 == sh_dbIO_load_delta())
1515        {
1516          --sh_load_delta_flag; --sig_raised;
1517        } 
1518    }
1519  return;
1520}
1521
1522#endif
1523
1524/*******************************************************
1525 *
1526 * Main program
1527 *
1528 *******************************************************/
1529#if !defined(SH_CUTEST)
1530int main(int argc, char * argv[])
1531#else
1532int undef_main(int argc, char * argv[])
1533#endif
1534{
1535#if defined(INET_SYSLOG)
1536  extern int    sh_xfer_create_syslog_socket (int flag);
1537#endif
1538#if defined(SH_WITH_SERVER)
1539  extern int    sh_create_tcp_socket(void);
1540#endif
1541
1542#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1543  int           modnum;
1544  time_t        runtim;
1545  float         st_1, st_2;
1546  int           status;
1547  volatile long          cct = 0; /* main loop iterations */
1548
1549  volatile int           flag_check_1 = 0;
1550  volatile int           flag_check_2 = 0;
1551
1552  int           check_done   = 0;
1553#endif
1554
1555  volatile time_t        told;
1556  volatile time_t        tcurrent;
1557  size_t        tzlen;
1558  char *        tzptr;
1559  int           res;
1560
1561#if defined (SH_STEALTH_NOCL)
1562  char    command_line[256];
1563  int     my_argc = 0;
1564  char  * my_argv[32];
1565#endif
1566
1567#if !defined(USE_SYSTEM_MALLOC)
1568  typedef void assert_handler_tp(const char * error, const char *file, int line);
1569  extern assert_handler_tp *dnmalloc_set_handler(assert_handler_tp *new);
1570  (void) dnmalloc_set_handler(safe_fatal);
1571#endif
1572
1573  SH_G_INIT; /* Must precede any use of _() */
1574
1575  SL_ENTER(_("main"));
1576
1577  /* --- Close all but first three file descriptors. ---
1578   */
1579  sh_unix_closeall(3, -1, S_FALSE); /* at program start */
1580
1581
1582  if (argc >= 2 && 0 != getuid() &&
1583      (0 == strcmp(argv[1], _("start")) ||
1584       0 == strcmp(argv[1], _("stop")) ||
1585       0 == strcmp(argv[1], _("reload")) ||
1586       0 == strcmp(argv[1], _("force-reload")) ||
1587       0 == strcmp(argv[1], _("status")) ||
1588       0 == strcmp(argv[1], _("restart"))))
1589    {
1590      return 4;
1591    }
1592       
1593  if (argc >= 2 && 0 == getuid())
1594    {
1595      /* return codes:
1596       * 0    Success
1597       * 1    Can not send signal / start program
1598       * 2    Pid file does not exist
1599       */
1600      if      (0 == strcmp(argv[1], _("start")))
1601        {
1602          (void) samhainctl (1, &argc, argv); /* does not return */
1603        }
1604      else if (0 == strcmp(argv[1], _("stop")))
1605        return (samhainctl (2, &argc, argv));
1606      else if (0 == strcmp(argv[1], _("reload")))
1607        (void) samhainctl (3, &argc, argv);   /* does not return */
1608      else if (0 == strcmp(argv[1], _("force-reload")))
1609        (void) samhainctl (3, &argc, argv);   /* does not return */
1610      else if (0 == strcmp(argv[1], _("status")))
1611        (void) samhainctl (4, &argc, argv);   /* does not return */
1612      else if (0 == strcmp(argv[1], _("restart")))
1613        {
1614          res = samhainctl (2, &argc, argv);
1615          if (res == 0 || res == 7)
1616            {
1617              (void) samhainctl (1, &argc, argv); /* does not return */
1618            }
1619          else
1620            return (res);
1621        }
1622    }
1623 
1624  /* if fd 0 is closed, presume that we want to be daemon and
1625   * run in check mode
1626   */
1627  if ((-1) == retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) && 
1628           errno == EBADF)
1629    {
1630      sh.flag.opts = S_TRUE;
1631      (void) sh_unix_setdeamon(NULL);
1632#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1633      sh.flag.checkSum = SH_CHECK_CHECK;
1634      /* (void) sh_util_setchecksum(_("check")); */
1635#endif
1636      is_samhainctl_init = S_TRUE;
1637      sh.flag.opts = S_FALSE;
1638    }
1639
1640
1641  /* --- Install the exit handler. ---
1642   */
1643  (void) atexit(exit_handler);
1644
1645  /* --- Zero the mailer key, and fill it. ---
1646   */
1647  memset (ErrFlag, 0, 2*sizeof(UINT32));
1648
1649#ifdef MKA_01
1650  ErrFlag[0] |= (1 << 0);
1651#endif
1652#ifdef MKA_02
1653  ErrFlag[0] |= (1 << 1);
1654#endif
1655#ifdef MKA_03
1656  ErrFlag[0] |= (1 << 2);
1657#endif
1658#ifdef MKA_04
1659  ErrFlag[0] |= (1 << 3);
1660#endif
1661#ifdef MKA_05
1662  ErrFlag[0] |= (1 << 4);
1663#endif
1664#ifdef MKA_06
1665  ErrFlag[0] |= (1 << 5);
1666#endif
1667#ifdef MKA_07
1668  ErrFlag[0] |= (1 << 6);
1669#endif
1670#ifdef MKA_08
1671  ErrFlag[0] |= (1 << 7);
1672#endif
1673
1674#if defined(SCREW_IT_UP)
1675  BREAKEXIT(sh_sigtrap_prepare);
1676  (void) sh_sigtrap_prepare();
1677#endif
1678
1679  /* Save the timezone.
1680   */
1681  if (NULL != (tzptr = getenv("TZ"))) /* flawfinder: ignore */
1682    {
1683      tzlen       = strlen(tzptr);
1684      if (tzlen < 1024)
1685        {
1686          sh.timezone = calloc(1, tzlen + 1);
1687          if (sh.timezone != NULL)
1688            (void) sl_strlcpy (sh.timezone, tzptr, tzlen + 1);
1689        }
1690      else
1691        sh.timezone = NULL;
1692    }
1693  else
1694     sh.timezone = NULL;
1695
1696
1697  /* --------  INIT  --------   
1698   */
1699  sh_unix_ign_sigpipe();
1700
1701  /* Restrict error logging to stderr.
1702   */
1703  sh_error_only_stderr (S_TRUE);
1704
1705  /* Check that first three descriptors are open.
1706   */
1707  if ( retry_fcntl(FIL__, __LINE__, 0, F_GETFL, 0) == (-1))
1708    (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 0);
1709  if ( retry_fcntl(FIL__, __LINE__, 1, F_GETFL, 0) == (-1))
1710    (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 1);
1711  if ( retry_fcntl(FIL__, __LINE__, 2, F_GETFL, 0) == (-1))
1712    (void) aud_open(FIL__, __LINE__, SL_NOPRIV, _("/dev/null"), O_RDWR, 2);
1713
1714  /* --- Set default values. ---
1715   */
1716  BREAKEXIT(sh_init);
1717  sh_init ();    /* we are still privileged here, so we can mlock skey */
1718#if (defined (SH_WITH_SERVER) && !defined (SH_WITH_CLIENT))
1719  sh.flag.isserver = S_TRUE;
1720#endif
1721
1722  /* --- First check for an attached debugger (after setting
1723         sh.sigtrap_max_duration which has to be done before). ---
1724   */
1725  BREAKEXIT(sh_derr);
1726  (void) sh_derr();
1727
1728  /* --- Get local hostname. ---
1729   */
1730  BREAKEXIT(sh_unix_localhost);
1731  sh_unix_localhost();
1732
1733  /* --- Read the command line. ---
1734   */
1735  sh.flag.opts = S_TRUE;
1736
1737#if !defined(SH_STEALTH_NOCL)
1738  sh_argc_store = argc;
1739  sh_argv_store = argv;
1740  (void) sh_getopt_get (argc, argv);
1741#else
1742  if (argc > 1 && argv[1] != NULL && 
1743      strlen(argv[1]) > 0 && strlen(NOCL_CODE) > 0)
1744    {
1745      if ( 0 == strcmp(argv[1], NOCL_CODE) )
1746        {
1747#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1748          char * saveptr;
1749#endif
1750          my_argv[0] = argv[0]; ++my_argc; 
1751          command_line[0] = '\0';
1752          if (NULL != fgets (command_line, sizeof(command_line), stdin))
1753            command_line[sizeof(command_line)-1] = '\0';
1754
1755          do {
1756#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
1757            my_argv[my_argc] = 
1758              strtok_r( (my_argc == 1) ? command_line : NULL, " \n", &saveptr);
1759#else
1760            my_argv[my_argc] = 
1761              strtok( (my_argc == 1) ? command_line : NULL, " \n");
1762#endif
1763            if (my_argv[my_argc] != NULL) {
1764              ++my_argc;
1765            } else {
1766              break;
1767            }
1768          } while (my_argc < 32);
1769
1770          sh_argc_store = my_argc;
1771          sh_argv_store = my_argv;
1772
1773          (void) sh_getopt_get (my_argc, my_argv);
1774        }
1775      else
1776        {
1777          /* discard command line */
1778          /* _exit(EXIT_FAILURE)  */  ; 
1779        }
1780    }
1781#endif
1782  sh.flag.opts = S_FALSE;
1783 
1784
1785  /* --- Get user info. ---
1786   */
1787  TPT((0, FIL__, __LINE__, _("msg=<Get user name.>\n")))
1788  if (0 != sh_unix_getUser ())
1789    {
1790      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1791                       sh.prg_name);
1792      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1793    }
1794
1795
1796  /* *****************************
1797   *
1798   *  Read the configuration file.
1799   *
1800   * *****************************/
1801
1802  TPT((0, FIL__, __LINE__, _("msg=<Read the configuration file.>\n")))
1803  BREAKEXIT(sh_readconf_read);
1804  (void) sh_readconf_read ();
1805
1806  sh_calls_enable_sub();
1807
1808#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1809  if (sh.flag.checkSum == SH_CHECK_NONE)
1810    {
1811      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_E_SUBGEN,
1812                       _("No action specified: init, update, or check"), 
1813                       _("main"));
1814      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1815                       sh.prg_name);
1816      aud_exit (FIL__, __LINE__, EXIT_FAILURE);
1817    }
1818#endif
1819
1820  /* do not append to database if run SUID
1821   */
1822  if ((sh.flag.checkSum == SH_CHECK_INIT) && (0 != sl_is_suid())) 
1823    {
1824      (void) dlog(1, FIL__, __LINE__, 
1825           _("Cannot initialize database when running with SUID credentials.\nYou need to run this with the user ID %d.\nYour current user ID is %d."), 
1826           (int) geteuid(), (int) sh.real.uid);
1827      sh_error_handle ((-1), FIL__, __LINE__, EACCES, MSG_ACCESS,
1828                       (long) sh.real.uid, sh.data.path);
1829      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1830    }
1831
1832  /* avoid daemon mode for initialization
1833   */
1834  if (sh.flag.checkSum == SH_CHECK_INIT)
1835    {
1836      sh.flag.isdaemon = S_FALSE;
1837      sh.flag.loop     = S_FALSE;
1838    }
1839
1840  /* --- load database; checksum of database
1841   */
1842#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1843  if (0 == sh.delayload)
1844    sh_hash_init_and_checksum();
1845#endif
1846
1847  /* --- initialize signal handling etc.; fork daemon
1848   */
1849  if (sh_unix_init(sh.flag.isdaemon) == -1) 
1850    {
1851      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1852                       sh.prg_name);
1853      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1854    }
1855
1856#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1857  if (sh.delayload)
1858    {
1859      sleep(sh.delayload);
1860      sh_hash_init_and_checksum();
1861    }
1862#endif
1863
1864  /* --- drop privileges eventually ---
1865   */
1866#if defined(SH_WITH_SERVER)
1867  sh_create_tcp_socket ();
1868#if defined(INET_SYSLOG)
1869  sh_xfer_create_syslog_socket (S_TRUE);
1870#endif
1871  SL_REQUIRE(sl_policy_get_real(DEFAULT_IDENT) == SL_ENONE, 
1872             _("sl_policy_get_real(DEFAULT_IDENT) == SL_ENONE"));
1873#else
1874  SL_REQUIRE(sl_policy_get_user(DEFAULT_IDENT) == SL_ENONE, 
1875             _("sl_policy_get_user(DEFAULT_IDENT) == SL_ENONE"));
1876#endif
1877
1878  /* --- Get user info (again). ---
1879   */
1880  TPT((0, FIL__, __LINE__, _("msg=<Get user name.>\n")))
1881  if (0 != sh_unix_getUser ())
1882    {
1883      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_EXIT_ABORT1,
1884                       sh.prg_name);
1885      aud_exit(FIL__, __LINE__, EXIT_FAILURE);
1886    }
1887
1888  /* --- now check whether we really wanted it; if not, close ---
1889   */
1890#if defined(INET_SYSLOG) && defined(SH_WITH_SERVER)
1891  sh_xfer_create_syslog_socket (S_FALSE);
1892#endif
1893
1894
1895  /* --- Enable full error logging ---
1896   */
1897  sh_error_only_stderr (S_FALSE);
1898
1899  sh.flag.started = S_TRUE;
1900
1901  /****************************************************
1902   *
1903   *   SERVER
1904   *
1905   ****************************************************/
1906
1907#if defined(SH_WITH_SERVER) && !defined(SH_WITH_CLIENT)
1908
1909#if defined(WITH_GPG)
1910  /* log startup */
1911  sh_sig_log_startup ();
1912#else
1913  sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
1914                   sh.prg_name, (long) sh.real.uid, 
1915                   (sh.flag.hidefile == S_TRUE) ? 
1916                   _("(hidden)") : file_path('C','R'), 
1917                   sh.conf.hash);
1918#endif
1919
1920#else
1921
1922  /****************************************************
1923   *
1924   *   CLIENT/STANDALONE
1925   *
1926   ****************************************************/
1927
1928  BREAKEXIT(sh_error_handle);
1929
1930  if (sh.flag.checkSum == SH_CHECK_CHECK) 
1931    {
1932#if defined(WITH_GPG)
1933      /* log startup */
1934      sh_sig_log_startup ();
1935#else
1936      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_2H,
1937                       sh.prg_name, (long) sh.real.uid,
1938                       (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), sh.conf.hash,
1939                       (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('D', 'R'), sh.data.hash);
1940#endif
1941    }
1942  else
1943    {
1944#if defined(WITH_GPG)
1945      /* log startup */
1946      sh_sig_log_startup ();
1947#else
1948      sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_START_1H,
1949                       sh.prg_name, (long) sh.real.uid,
1950                       (sh.flag.hidefile == S_TRUE) ? _("(hidden)") : file_path('C', 'R'), sh.conf.hash);
1951#endif
1952    }
1953#endif
1954
1955 
1956  if ((skey == NULL) || (skey->mlock_failed == S_TRUE))
1957    sh_error_handle ((-1), FIL__, __LINE__, EPERM, MSG_MLOCK);
1958
1959  /* timer
1960   */
1961  tcurrent                   = time (NULL);
1962  told                       = tcurrent;
1963  sh.mailTime.alarm_last     = told;
1964
1965
1966  /****************************************************
1967   *
1968   *   SERVER
1969   *
1970   ****************************************************/
1971
1972#if defined(SH_WITH_SERVER)
1973  TPT((0, FIL__, __LINE__, _("msg=<Start server.>\n")))
1974
1975#if defined (SH_WITH_CLIENT)
1976  if (sh.flag.isserver == S_TRUE)
1977    { 
1978      sh_xfer_start_server();
1979      TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
1980      aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1981    }
1982#else
1983  sh_xfer_start_server();
1984  TPT((0, FIL__, __LINE__, _("msg=<End server.>\n")))
1985  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
1986#endif
1987
1988#endif
1989
1990  /****************************************************
1991   *
1992   *   CLIENT/STANDALONE
1993   *
1994   ****************************************************/
1995#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1996
1997
1998  /* --- Initialize modules. ---
1999   */
2000  TPT((0, FIL__, __LINE__, _("msg=<Initialize modules.>\n")))
2001  for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
2002    {
2003      status = modList[modnum].mod_init(&(modList[modnum]));
2004      if ( status < 0 )
2005        {
2006          if (status == (-1)) {
2007            sh_error_handle (SH_ERR_NOTICE, FIL__, __LINE__, status, 
2008                             MSG_MOD_FAIL,
2009                             _(modList[modnum].name),
2010                             status+SH_MOD_OFFSET);
2011          } else {
2012            sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_FAIL,
2013                             _(modList[modnum].name),
2014                             status+SH_MOD_OFFSET);
2015          }
2016          modList[modnum].initval = SH_MOD_FAILED;
2017        }
2018      else
2019        {
2020          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_MOD_OK,
2021                           _(modList[modnum].name));
2022          modList[modnum].initval = status;
2023        }
2024    }
2025   
2026  /*  --------  TEST SETUP  ---------
2027   */
2028  (void) sh_files_setrec();
2029  (void) sh_files_test_setup();
2030  sh_audit_commit ();
2031
2032  /* --------  NICE LEVEL   ---------
2033   */
2034  if (0 != sh.flag.nice)
2035    {
2036#ifdef HAVE_SETPRIORITY
2037      /*@-unrecog@*/
2038      (void) setpriority(PRIO_PROCESS, 0, sh.flag.nice);
2039      /*@+unrecog@*/
2040#else
2041      (void) nice(sh.flag.nice);
2042#endif
2043    }
2044
2045  /*  --------  CREATE SEMAPHORE  ---------
2046   */
2047  sh_sem_open();
2048
2049  /*  --------  MAIN LOOP  ---------
2050   */
2051  sh.statistics.bytes_speed   = 0;
2052  sh.statistics.bytes_hashed  = 0;
2053  sh.statistics.files_report  = 0;
2054  sh.statistics.files_error   = 0;
2055  sh.statistics.files_nodir   = 0;
2056
2057  while (1 == 1) 
2058    {
2059      ++cct;
2060
2061      BREAKEXIT(sh_error_handle);
2062
2063      TPT((0, FIL__, __LINE__, _("msg=<Start main loop.>, iter=<%ld>\n"), cct))
2064
2065      tcurrent = time (NULL);
2066
2067      do {
2068        check_signals(&flag_check_1, &flag_check_2);
2069        if (sh_global_suspend_flag == 1)
2070          (void) retry_msleep (1, 0);
2071      } while (sh_global_suspend_flag == 1);
2072     
2073      /* see whether its time to check files
2074       */
2075      if      (sh.flag.checkSum == SH_CHECK_INIT ||
2076               (sh.flag.inotify & SH_INOTIFY_DOSCAN) != 0 ||
2077               (sh.flag.checkSum == SH_CHECK_CHECK &&
2078                (sh.flag.isdaemon == S_FALSE && sh.flag.loop == S_FALSE)))
2079        {
2080          flag_check_1 = 1;
2081          if (FileSchedTwo != NULL) 
2082            flag_check_2 = 1;
2083        }
2084      else if (sh.flag.checkSum == SH_CHECK_CHECK || 
2085               (sh.flag.update == S_TRUE && 
2086                (sh.flag.isdaemon == S_TRUE || sh.flag.loop == S_TRUE)))
2087        {
2088          if (FileSchedOne == NULL)
2089            {
2090              /* use interval if we have no schedule
2091               */
2092              if (tcurrent - sh.fileCheck.alarm_last >= 
2093                  sh.fileCheck.alarm_interval)
2094                flag_check_1 = 1;
2095            }
2096          else
2097            {
2098              flag_check_1 = test_sched(FileSchedOne);
2099              if (FileSchedTwo != NULL) 
2100                flag_check_2 = test_sched(FileSchedTwo);
2101              if (flag_check_2 == 1) 
2102                flag_check_1 = 1;
2103            }
2104        }
2105
2106      check_done = 0;
2107
2108      if (sh.flag.checkSum != SH_CHECK_NONE &&
2109          (flag_check_1 == 1 || flag_check_2 == 1))
2110        {
2111          sh_sem_trylock();
2112
2113          /* Starting a check now, so make sure to fetch delta DB
2114           * if there is one to download.
2115           */
2116          check_for_delta_db();
2117
2118          SH_INOTIFY_IFUSED( sh.flag.inotify |= SH_INOTIFY_INSCAN; );
2119          /* Refresh list files matching glob patterns.
2120           */
2121          if (sh.flag.checkSum != SH_CHECK_INIT)
2122            sh_files_check_globPatterns();
2123
2124          /*
2125           * check directories and files
2126           * ORDER IS IMPORTANT -- DIRZ FIRST
2127           */
2128          sh.statistics.bytes_hashed   = 0;
2129          sh.statistics.time_start     = time (NULL);
2130          sh.statistics.dirs_checked   = 0;
2131          sh.statistics.files_checked  = 0;
2132          sh.statistics.files_report   = 0;
2133          sh.statistics.files_error    = 0;
2134          sh.statistics.files_nodir    = 0;
2135
2136          TPT((0, FIL__, __LINE__, _("msg=<Check directories.>\n")))
2137          BREAKEXIT(sh_dirs_chk);
2138          if (flag_check_1 == 1)
2139            {
2140              (void) sh_dirs_chk  (1);
2141#ifndef SH_PROFILE
2142              (void) retry_aud_chdir (FIL__, __LINE__, "/");
2143#endif
2144            }
2145          if (flag_check_2 == 1)
2146            {
2147              (void) sh_dirs_chk  (2); 
2148#ifndef SH_PROFILE
2149              (void) retry_aud_chdir (FIL__, __LINE__, "/");
2150#endif
2151            }
2152          TPT((0, FIL__, __LINE__, _("msg=<Check files.>\n")))
2153          BREAKEXIT(sh_files_chk);
2154          if (flag_check_1 == 1)
2155            (void) sh_files_chk ();
2156
2157          if (sig_urgent > 0) { sh_sem_unlock(sh.statistics.files_report); sh_global_check_silent = 0; continue; }
2158          /*
2159           * check for files not visited
2160           */
2161          if (flag_check_2 == 1 || FileSchedTwo == NULL)
2162            {
2163              TPT((0, FIL__, __LINE__, _("msg=<Check for missing files.>\n")))
2164              sh_hash_unvisited (ShDFLevel[SH_ERR_T_FILE]);
2165            }
2166
2167          if (sig_urgent > 0) { sh_sem_unlock(sh.statistics.files_report); sh_global_check_silent = 0; continue; }
2168
2169          /* reset
2170           */
2171          TPT((0, FIL__, __LINE__, _("msg=<Reset status.>\n")))
2172          sh_dirs_reset  ();
2173
2174          if (sig_urgent > 0) { sh_sem_unlock(sh.statistics.files_report); sh_global_check_silent = 0; continue; }
2175
2176          sh_files_reset ();
2177          check_done   = 1;
2178
2179          flag_check_1 = 0;
2180          flag_check_2 = 0;
2181          sh_sem_unlock(sh.statistics.files_report);
2182
2183          SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_INSCAN; );
2184          SH_INOTIFY_IFUSED( sh.flag.inotify &= ~SH_INOTIFY_DOSCAN; );
2185
2186          (void) sh_prelink_run (NULL, NULL, 0, 0);
2187
2188          if (sig_urgent > 0) { sh_global_check_silent = 0; continue; }
2189
2190          runtim = time(NULL) - sh.statistics.time_start;
2191          sh.statistics.time_check = runtim;
2192       
2193          if ((sh.statistics.dirs_checked == 0) && 
2194              (sh.statistics.files_checked == 0) &&
2195              (sh_global_check_silent < SH_SILENT_FULL))
2196            sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_0);
2197
2198          else
2199            {
2200              st_1 = (float) sh.statistics.bytes_hashed;
2201              st_2 = (float) runtim;
2202
2203
2204              if (st_1 > FLT_EPSILON && st_2 > FLT_EPSILON) 
2205                st_1 = st_1/st_2;
2206              else if (st_1 > FLT_EPSILON)
2207                st_1 = (float) (st_1 * 1.0);
2208              else
2209                st_1 = 0.0;
2210
2211              sh.statistics.bytes_speed = (unsigned long) st_1;
2212
2213              if (sh_global_check_silent < SH_SILENT_FULL)
2214                sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_CHECK_1,
2215                                 (long) runtim, 
2216                                 0.001 * st_1);
2217
2218              if (sh.flag.checkSum != SH_CHECK_INIT)
2219                sh_efile_report();
2220            }
2221         
2222          if (0 == sh_global_check_silent)
2223            sh.fileCheck.alarm_last = time (NULL);
2224
2225          sh_global_check_silent = 0;
2226         
2227          if (sig_urgent > 0) continue;
2228
2229          /*
2230           * flush mail queue
2231           */
2232#if defined(SH_WITH_MAIL)
2233          TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
2234          (void) sh_nmail_flush ();
2235#endif
2236        }
2237     
2238      if (sig_urgent > 0) continue;
2239     
2240      /* execute modules
2241       */
2242      TPT((0, FIL__, __LINE__, _("msg=<Execute modules.>\n")))
2243      for (modnum = 0; modList[modnum].name != NULL; ++modnum) 
2244        {
2245          if (modList[modnum].initval == SH_MOD_ACTIVE &&
2246              0 != modList[modnum].mod_timer(tcurrent))
2247            if (0 != (status = modList[modnum].mod_check()))
2248              sh_error_handle ((-1), FIL__, __LINE__, status, MSG_MOD_EXEC,
2249                               _(modList[modnum].name), (long) (status+SH_MOD_OFFSET));
2250        }
2251     
2252      /* 27.05.2002 avoid empty database
2253       * 22.10.2002 moved here b/o suid check initialization
2254       */ 
2255      if      (sh.flag.checkSum == SH_CHECK_INIT)
2256        sh_dbIO_data_write (NULL, NULL);
2257
2258      /* write out database
2259       */
2260      if (sh.flag.checkSum == SH_CHECK_CHECK && 
2261          sh.flag.update == S_TRUE && 
2262          check_done == 1)
2263        sh_dbIO_writeout_update ();
2264
2265      /* no-op unless MEM_LOG is defined in sh_mem.c
2266       */
2267#ifdef MEM_DEBUG
2268      sh_mem_dump ();
2269#endif
2270
2271      {
2272        char * stale;
2273
2274        stale = sl_check_stale();
2275        if (stale)
2276          {
2277            sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2278                            stale, _("sl_check_stale"));
2279          }
2280
2281        stale = sl_check_badfd();
2282        if (stale)
2283          {
2284            sh_error_handle(SH_ERR_ERR, FIL__, __LINE__, 0, MSG_E_SUBGEN,
2285                            stale, _("sl_check_stale"));
2286          }
2287      }
2288
2289      /* no loop if not daemon
2290       */
2291      if (sh.flag.isdaemon != S_TRUE && sh.flag.loop == S_FALSE) break;
2292      if (sig_urgent > 0) continue;
2293
2294      /* see whether its time to send mail
2295       */
2296#if defined(SH_WITH_MAIL)
2297      if (tcurrent - sh.mailTime.alarm_last >= sh.mailTime.alarm_interval) 
2298        {
2299          TPT((0, FIL__, __LINE__, _("msg=<Flush mail queue.>\n")))
2300          (void) sh_nmail_flush ();
2301          sh.mailTime.alarm_last = time (NULL);
2302        }
2303#endif
2304      if (sig_urgent > 0) continue;
2305           
2306      /* log the timestamp
2307       */
2308      if ((int)(tcurrent - told) >= sh.looptime )
2309        {
2310          TPT((0, FIL__, __LINE__, _("msg=<Log the timestamp.>\n")))
2311          told = tcurrent;
2312#ifdef MEM_DEBUG
2313          sh_mem_check();
2314          sh_unix_count_mlock();
2315#else
2316          sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_STAMP);
2317#endif
2318        }
2319   
2320      /* seed / re-seed the PRNG if required
2321       */
2322      (void) taus_seed();
2323     
2324      if (sig_urgent > 0) continue;
2325     
2326      /* reset cache
2327       */
2328      sh_userid_destroy();
2329
2330      /* go to sleep
2331       */
2332      (void) retry_msleep (1, 0);
2333
2334      BREAKEXIT(sh_derr);
2335      (void) sh_derr();
2336    }
2337 
2338  /*   ------  END  -----------
2339   */
2340
2341
2342
2343  /*
2344   * cleanup
2345   */
2346  TPT((0, FIL__, __LINE__, _("msg=<Cleanup.>\n")));
2347  sh_hash_hashdelete(); 
2348
2349#if defined(SH_WITH_MAIL)
2350  if (sh.mailNum.alarm_last > 0) 
2351    (void)sh_nmail_flush ();
2352#endif
2353
2354  /* #if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE) */
2355#endif
2356
2357  aud_exit (FIL__, __LINE__, EXIT_SUCCESS);
2358  SL_RETURN(0, _("main"));
2359}
Note: See TracBrowser for help on using the repository browser.