source: trunk/src/samhain.c@ 408

Last change on this file since 408 was 405, checked in by katerina, 12 years ago

Fix for tickets #303, #304, #305. #306, and #307. Update version number.

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