source: branches/samhain_3_1/src/sh_error.c@ 522

Last change on this file since 522 was 476, checked in by katerina, 9 years ago

Fix for ticket #373 (better autoconf macro for va_copy).

File size: 42.4 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/* Required on Linux to get the correct strerror_r function. Also
23 * for recursive mutexes (_XOPEN_SOURCE >= 500). Gives funny error
24 * on Solaris 10/gcc ('c99' compiler required - huh? Isn't gcc
25 * good enough?).
26 */
27#if !defined(__sun__) && !defined(__sun)
28#define _XOPEN_SOURCE 600
29#undef _GNU_SOURCE
30#endif
31#include <string.h>
32#include <stdio.h>
33#include <stdlib.h>
34#include <stdarg.h>
35#include <ctype.h>
36#include <limits.h>
37#include <errno.h>
38
39/* Required on FreeBSD
40 */
41#include <sys/types.h>
42
43#ifdef HAVE_MEMORY_H
44#include <memory.h>
45#endif
46
47#if defined(HAVE_MLOCK) && !defined(HAVE_BROKEN_MLOCK)
48#include <sys/mman.h>
49#endif
50
51
52
53#include "samhain.h"
54
55#include "sh_cat.h"
56#include "sh_database.h"
57#include "sh_error.h"
58#include "sh_utils.h"
59#include "sh_unix.h"
60#include "sh_tiger.h"
61#include "sh_nmail.h"
62#include "sh_forward.h"
63#include "sh_prelude.h"
64#include "sh_pthread.h"
65
66#if defined(WITH_DATABASE)
67#include "sh_tools.h"
68#endif
69
70#if defined(WITH_EXTERNAL)
71#include "sh_extern.h"
72#endif
73
74#undef FIL__
75#define FIL__ _("sh_error.c")
76/*@-noret -compmempass@*/
77extern int clt_class;
78
79int flag_err_debug = SL_FALSE;
80int flag_err_info = SL_FALSE;
81
82int ShDFLevel[SH_ERR_T_END];
83
84typedef struct _log_t {
85 char file[SH_PATHBUF];
86 char format[SH_PATHBUF];
87 /*@null@*/char * msg;
88 size_t msg_len;
89 int severity;
90 int class;
91 int pid;
92 long status;
93 long line;
94 char timestamp[TIM_MAX];
95} sh_log_t;
96
97
98struct _errFlags errFlags;
99
100static int sh_error_init (void);
101
102/*@owned@*//*@null@*/inline
103static char * get_format(unsigned long msg_id, /*@out@*/int * priority,
104 /*@out@*/unsigned int * class);
105
106static int sh_error_string (struct _log_t * lmsg, va_list vl);
107
108extern int sh_log_console (/*@null@*/const char *message);
109extern int sh_log_syslog (int severity, /*@null@*/char *message);
110extern int sh_log_file (/*@null@*/char *message,
111 /*@null@*/char * inet_peer);
112/* convert a string to a numeric priority
113 */
114int sh_error_convert_level (const char * str_s);
115
116static int IsInitialized = BAD;
117
118/* --- Only log to stderr. ---
119 */
120int OnlyStderr = S_TRUE;
121
122/* --- Enable facilities not safe for closeall(). ---
123 */
124int enableUnsafe = S_FALSE;
125
126/*********************************************
127 * utility functions for verifying entries
128 *********************************************/
129
130int sh_error_verify (const char * s)
131{
132 char * foo;
133 char hashbuf[KEYBUF_SIZE];
134
135 if (s[0] == '/')
136 {
137 foo = sh_tiger_hash_gpg (s, TIGER_FILE, TIGER_NOLIM);
138 fprintf (stdout, _("%s\n"), foo);
139 SH_FREE(foo);
140 }
141 else
142 {
143 fprintf (stdout, _("string=<%s>, hash=<%s>\n"),
144 s, sh_tiger_hash (s, TIGER_DATA,
145 (unsigned long) sl_strlen(s),
146 hashbuf, sizeof(hashbuf))
147 );
148 }
149 (void) fflush(stdout);
150 _exit (EXIT_SUCCESS);
151 /*@i@*/return 0;
152}
153
154
155
156/*********************************************
157 * end utility functions
158 *********************************************/
159
160void sh_error_only_stderr (int flag)
161{
162 OnlyStderr = flag;
163 return;
164}
165
166void sh_error_enable_unsafe (int flag)
167{
168 enableUnsafe = flag;
169 return;
170}
171
172static int dbg_store = 0;
173static int dbg_flag = 0;
174
175static
176void compute_flag_err_debug(void)
177{
178 if ((errFlags.loglevel & SH_ERR_ALL) != 0)
179 flag_err_debug = SL_TRUE;
180 else if ((errFlags.printlevel & SH_ERR_ALL) != 0)
181 flag_err_debug = SL_TRUE;
182 else if ((errFlags.maillevel & SH_ERR_ALL) != 0)
183 flag_err_debug = SL_TRUE;
184 else if ((errFlags.exportlevel & SH_ERR_ALL) != 0)
185 flag_err_debug = SL_TRUE;
186 else if ((errFlags.sysloglevel & SH_ERR_ALL) != 0)
187 flag_err_debug = SL_TRUE;
188 else if ((errFlags.externallevel & SH_ERR_ALL) != 0)
189 flag_err_debug = SL_TRUE;
190 else if ((errFlags.databaselevel & SH_ERR_ALL) != 0)
191 flag_err_debug = SL_TRUE;
192 else if ((errFlags.preludelevel & SH_ERR_ALL) != 0)
193 flag_err_debug = SL_TRUE;
194 else
195 flag_err_debug = SL_FALSE;
196 return;
197}
198
199static
200void compute_flag_err_info(void)
201{
202 if ((errFlags.loglevel & SH_ERR_INFO) != 0)
203 flag_err_info = SL_TRUE;
204 else if ((errFlags.printlevel & SH_ERR_INFO) != 0)
205 flag_err_info = SL_TRUE;
206 else if ((errFlags.maillevel & SH_ERR_INFO) != 0)
207 flag_err_info = SL_TRUE;
208 else if ((errFlags.exportlevel & SH_ERR_INFO) != 0)
209 flag_err_info = SL_TRUE;
210 else if ((errFlags.sysloglevel & SH_ERR_INFO) != 0)
211 flag_err_info = SL_TRUE;
212 else if ((errFlags.externallevel & SH_ERR_INFO) != 0)
213 flag_err_info = SL_TRUE;
214 else if ((errFlags.databaselevel & SH_ERR_INFO) != 0)
215 flag_err_info = SL_TRUE;
216 else if ((errFlags.preludelevel & SH_ERR_INFO) != 0)
217 flag_err_info = SL_TRUE;
218 else
219 flag_err_info = SL_FALSE;
220 return;
221}
222
223void sh_error_dbg_switch(void)
224{
225 if (dbg_flag == 0)
226 {
227 dbg_store = errFlags.printlevel;
228 errFlags.printlevel = (SH_ERR_ALL | SH_ERR_INFO | SH_ERR_NOTICE |
229 SH_ERR_WARN | SH_ERR_STAMP | SH_ERR_ERR |
230 SH_ERR_SEVERE | SH_ERR_FATAL);
231 dbg_flag = 1;
232 flag_err_debug = SL_TRUE;
233 }
234 else {
235 errFlags.printlevel = dbg_store;
236 dbg_store = 0;
237 dbg_flag = 0;
238 compute_flag_err_debug();
239 }
240 return;
241}
242
243static int sh_error_set_classmask (const char * str, int * facility_mask)
244{
245 char * p;
246 int num = 0;
247 unsigned int i;
248 size_t len;
249 char * c;
250
251 SL_ENTER(_("sh_error_set_classmask"));
252
253 if (str == NULL)
254 SL_RETURN( -1, _("sh_error_set_classmask"));
255
256 if (IsInitialized == BAD)
257 (void) sh_error_init();
258
259 if (str[0] == (char) 34)
260 ++str;
261 len = strlen(str);
262
263 c = SH_ALLOC(len+1);
264 sl_strlcpy(c, str, len+1);
265
266 if (c[len-1] == (char) 34)
267 c[len-1] = '\0';
268
269 *facility_mask = 0;
270
271 do {
272#if defined(HAVE_PTHREAD) && defined (_POSIX_THREAD_SAFE_FUNCTIONS) && defined(HAVE_STRTOK_R)
273 char * saveptr;
274 if (num == 0) {
275 p = strtok_r (c, " ,\t", &saveptr);
276 ++num;
277 } else {
278 p = strtok_r (NULL, " ,\t", &saveptr);
279 }
280#else
281 if (num == 0) {
282 p = strtok (c, " ,\t");
283 ++num;
284 } else {
285 p = strtok (NULL, " ,\t");
286 }
287#endif
288
289 if (p == NULL)
290 break;
291
292 for (i = 0; i < SH_CLA_MAX; ++i)
293 {
294 if (i < SH_CLA_RAW_MAX) {
295 if (0 == strcmp(p, _(class_cat[i])))
296 *facility_mask |= (1 << i);
297 } else {
298 if (0 == strcmp(p, _(class_cat[SH_CLA_RAW_MAX + 0])))
299 *facility_mask |= OTHER_CLA;
300 if (0 == strcmp(p, _(class_cat[SH_CLA_RAW_MAX + 1])))
301 *facility_mask |= RUN_NEW;
302 if (0 == strcmp(p, _(class_cat[SH_CLA_RAW_MAX + 2])))
303 *facility_mask |= FIL_NEW;
304 if (0 == strcmp(p, _(class_cat[SH_CLA_RAW_MAX + 3])))
305 *facility_mask |= ERROR_CLA;
306 }
307 }
308
309 } while (p);
310
311 SH_FREE(c);
312 SL_RETURN( 0, _("sh_error_set_classmask"));
313}
314
315int sh_error_log_mask (const char * c)
316{
317 return (sh_error_set_classmask(c, &(errFlags.log_class)));
318}
319int sh_error_mail_mask (const char * c)
320{
321 return (sh_error_set_classmask(c, &(errFlags.mail_class)));
322}
323int sh_error_print_mask (const char * c)
324{
325 return (sh_error_set_classmask(c, &(errFlags.print_class)));
326}
327int sh_error_export_mask (const char * c)
328{
329 return (sh_error_set_classmask(c, &(errFlags.export_class)));
330}
331int sh_error_syslog_mask (const char * c)
332{
333 return (sh_error_set_classmask(c, &(errFlags.syslog_class)));
334}
335int sh_error_external_mask (const char * c)
336{
337 return (sh_error_set_classmask(c, &(errFlags.external_class)));
338}
339int sh_error_database_mask (const char * c)
340{
341 return (sh_error_set_classmask(c, &(errFlags.database_class)));
342}
343int sh_error_prelude_mask (const char * c)
344{
345 return (sh_error_set_classmask(c, &(errFlags.prelude_class)));
346}
347
348
349
350char * sh_error_message (int tellme, char * str, size_t len)
351{
352
353#if defined(HAVE_STRERROR_R)
354 if (len > 0) str[0] = '\0';
355 strerror_r(tellme, str, len);
356 return str;
357#elif defined(HAVE_STRERROR)
358 sl_strlcpy(str, strerror(tellme), len);
359 return str;
360#else
361
362 char *p = NULL;
363#ifdef EACCES
364 if (tellme == EACCES) p = _("Permission denied.");
365#endif
366#ifdef EAGAIN
367 if (tellme == EAGAIN) p = _("Try again.");
368#endif
369#ifdef EBADF
370 if (tellme == EBADF) p = _("File descriptor in bad state.");
371#endif
372#ifdef EEXIST
373 if (tellme == EEXIST) p = _("File exists.");
374#endif
375#ifdef EFAULT
376 if (tellme == EFAULT) p = _("Bad address.");
377#endif
378#ifdef EINVAL
379 if (tellme == EINVAL) p = _("Invalid argument.");
380#endif
381#ifdef EISDIR
382 if (tellme == EISDIR) p = _("Is a directory.");
383#endif
384#ifdef EINTR
385 if (tellme == EINTR) p = _("System call was interrupted.");
386#endif
387#ifdef EIO
388 if (tellme == EIO) p = _("Low-level I/O error.");
389#endif
390#ifdef ELOOP
391 if (tellme == ELOOP) p = _("Too many symbolic links encountered.");
392#endif
393#ifdef EMFILE
394 if (tellme == EMFILE) p = _("Too many open files.");
395#endif
396#ifdef EMLINK
397 if (tellme == EMLINK) p = _("Too many links.");
398#endif
399#ifdef ENAMETOOLONG
400 if (tellme == ENAMETOOLONG)
401 p = _("File name too long.");
402#endif
403#ifdef ENFILE
404 if (tellme == ENFILE) p = _("File table overflow.");
405#endif
406#ifdef ENOENT
407 if (tellme == ENOENT) p = _("File does not exist.");
408#endif
409#ifdef ENOMEM
410 if (tellme == ENOMEM) p = _("Out of memory.");
411#endif
412#ifdef ENOSPC
413 if (tellme == ENOSPC) p = _("No space on device.");
414#endif
415#ifdef ENOTDIR
416 if (tellme == ENOTDIR) p = _("Not a directory.");
417#endif
418#ifdef ENOTSOCK
419 if (tellme == ENOTSOCK) p = _("Not a socket.");
420#endif
421#ifdef EOPNOTSUPP
422 if (tellme == EOPNOTSUPP) p = _("Socket is not of type SOCK_STREAM.");
423#endif
424#ifdef EPERM
425 if (tellme == EPERM) p = _("Permission denied.");
426#endif
427#ifdef EPIPE
428 if (tellme == EPIPE) p = _("No read on pipe.");
429#endif
430#ifdef EROFS
431 if (tellme == EROFS) p = _("Read-only file system.");
432#endif
433#ifdef ETXTBSY
434 if (tellme == ETXTBSY) p = _("Text file busy.");
435#endif
436#ifdef EWOULDBLOCK
437 if (tellme == EWOULDBLOCK)
438 p = _("No connections on non-blocking socket.");
439#endif
440#ifdef EXDEV
441 if (tellme == EXDEV) p = _("Not on same file system.");
442#endif
443 if (!p) p = _("Unknown error");
444 sl_strlcpy(str, p, len);
445 return str;
446#endif /* ifndef HAVE_STRERROR */
447}
448
449
450/* switch off file log
451 */
452void sh_error_logoff()
453{
454 errFlags.HaveLog = BAD;
455 return;
456}
457
458/* switch on file log
459 */
460void sh_error_logrestore()
461{
462 errFlags.HaveLog = GOOD;
463 return;
464}
465
466/* --- Relate priority levels to literals. ---
467 */
468typedef struct eef
469{
470 const char * str;
471 int val;
472} eef_struc;
473
474static eef_struc eef_tab[] =
475{
476 { N_("none"), SH_ERR_NOT },
477 { N_("debug"), SH_ERR_ALL },
478 { N_("info"), SH_ERR_INFO },
479 { N_("notice"), SH_ERR_NOTICE },
480 { N_("warn"), SH_ERR_WARN },
481 { N_("mark"), SH_ERR_STAMP },
482 { N_("err"), SH_ERR_ERR },
483 { N_("crit"), SH_ERR_SEVERE },
484 { N_("alert"), SH_ERR_FATAL },
485#if defined(SH_WITH_SERVER)
486#define SH_EEF_MAX 10
487 { N_("inet"), SH_ERR_INET },
488#else
489#define SH_EEF_MAX 9
490#endif
491};
492
493int sh_error_convert_level (const char * str_s)
494{
495 int i;
496 int level = (-1);
497
498 SL_ENTER(_("sh_error_convert_level"));
499
500 if (str_s == NULL)
501 SL_RETURN( -1, _("sh_error_convert_level"));
502
503 for (i = 0; i < SH_EEF_MAX; ++i)
504 {
505 if (0 == sl_strncmp(str_s, _(eef_tab[i].str),
506 sl_strlen(eef_tab[i].str)))
507 {
508 level = eef_tab[i].val;
509 break;
510 }
511 }
512
513 SL_RETURN( level, _("sh_error_convert_level"));
514}
515
516
517/* --- Set severity levels. ---
518 */
519int sh_error_set_iv (int iv, const char * str_s)
520{
521 int level = (-1);
522
523 SL_ENTER(_("sh_error_set_iv"));
524
525 if (IsInitialized == BAD)
526 (void) sh_error_init();
527
528 level = sh_error_convert_level (str_s);
529
530 if (level == (-1))
531 {
532 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
533 _("severity"),
534 str_s != NULL ? str_s : _("(NULL)"));
535 SL_RETURN (-1, _("sh_error_set_iv"));
536 }
537
538 if (iv > SH_ERR_T_START && iv < SH_ERR_T_END)
539 {
540 ShDFLevel[iv] = level;
541 }
542 else
543 {
544 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALL,
545 _("severity"), (long) iv);
546 SL_RETURN (-1, _("sh_error_set_iv"));
547 }
548 SL_RETURN (0, _("sh_error_set_iv"));
549}
550
551int sh_error_set_level(const char * str_in, int * facility)
552{
553 register int i, j, f = BAD;
554
555 int old_facility;
556 const char * str_s = str_in;
557
558 SL_ENTER(_("sh_error_set_level"));
559
560 if (IsInitialized == BAD)
561 (void) sh_error_init();
562
563 old_facility = *facility;
564 *facility = 0;
565
566 checkstr:
567
568 if (str_s != NULL)
569 {
570 if (0 == sl_strncmp(str_s, _(eef_tab[0].str), sl_strlen(eef_tab[0].str)))
571 {
572 *facility |= eef_tab[0].val; /* This is 'none' */
573 for (i = 1; i < SH_EEF_MAX; ++i)
574 *facility &= ~eef_tab[i].val;
575 f = GOOD;
576 }
577 else if (str_s[0] == '*') /* all */
578 {
579 for (i = 1; i < SH_EEF_MAX; ++i)
580 *facility |= eef_tab[i].val;
581 f = GOOD;
582 }
583 else if (str_s[0] == '=')
584 {
585 for (i = 1; i < SH_EEF_MAX; ++i)
586 if (0 == sl_strncmp(&str_s[1], _(eef_tab[i].str),
587 sl_strlen(eef_tab[i].str)))
588 {
589 *facility |= eef_tab[i].val;
590 f = GOOD;
591 }
592 }
593 else if (str_s[0] == '!')
594 {
595 if (str_s[1] == '*' ||
596 0 == sl_strncmp(&str_s[1], _(eef_tab[1].str),
597 sl_strlen(eef_tab[1].str)))
598 {
599 *facility |= eef_tab[0].val; /* This is 'none' */
600 for (i = 1; i < SH_EEF_MAX; ++i)
601 *facility &= ~eef_tab[i].val;
602 f = GOOD;
603 }
604 else if (str_s[1] == '=')
605 {
606 for (i = 1; i < SH_EEF_MAX; ++i)
607 {
608 if (0 == sl_strncmp(&str_s[2], _(eef_tab[i].str),
609 sl_strlen(eef_tab[i].str)))
610 {
611 *facility &= ~eef_tab[i].val;
612 f = GOOD;
613 }
614 }
615 }
616 else
617 {
618 for (i = 1; i < SH_EEF_MAX; ++i)
619 {
620 if (0 == sl_strncmp(&str_s[1], _(eef_tab[i].str),
621 sl_strlen(eef_tab[i].str)))
622 {
623 for (j = i; j < SH_EEF_MAX; ++j)
624 {
625 *facility &= ~eef_tab[j].val;
626 }
627 f = GOOD;
628 }
629 }
630 }
631 }
632 else /* plain severity name */
633 {
634 for (i = 1; i < SH_EEF_MAX; ++i)
635 {
636 if (0 == sl_strncmp(str_s, _(eef_tab[i].str),
637 sl_strlen(eef_tab[i].str)))
638 {
639 for (j = i; j < SH_EEF_MAX; ++j)
640 {
641 *facility |= eef_tab[j].val;
642 }
643 f = GOOD;
644 break;
645 }
646 }
647 }
648 }
649
650 if (!str_s)
651 {
652 SL_RETURN ((-1), _("sh_error_set_level"));
653 }
654 /* skip to end of string
655 */
656 while (*str_s != '\0' && *str_s != ';' && *str_s != ',' &&
657 *str_s != ' ' && *str_s != '\t')
658 ++str_s;
659
660 /* skip seperator
661 */
662 while ((*str_s != '\0') &&
663 (*str_s == ';' || *str_s == ',' || *str_s == ' ' || *str_s == '\t'))
664 ++str_s;
665
666 if (*str_s != '\0')
667 {
668 f = BAD;
669 goto checkstr;
670 }
671
672 if (f == BAD)
673 {
674 *facility = old_facility;
675 sh_error_handle ((-1), FIL__, __LINE__, EINVAL, MSG_EINVALS,
676 _("priority"), str_in);
677 SL_RETURN (-1, _("sh_error_set_level"));
678 }
679 compute_flag_err_debug();
680 compute_flag_err_info();
681 SL_RETURN (0, _("sh_error_set_level"));
682}
683
684#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
685/* set severity for TCP export
686 */
687int sh_error_setexport(const char * str_s)
688{
689 static int reject = 0;
690 if (reject == 1)
691 return (0);
692
693 if (sh.flag.opts == S_TRUE)
694 reject = 1;
695
696 return (sh_error_set_level(str_s, &errFlags.exportlevel));
697}
698#endif
699
700/* set severity for printing
701 */
702extern void dlog_set_active(int flag);
703
704int sh_error_setprint(const char * str_s)
705{
706 static int reject = 0;
707 int retval;
708
709 if (reject == 1)
710 return (0);
711
712 if (sh.flag.opts == S_TRUE)
713 reject = 1;
714
715 retval = sh_error_set_level(str_s, &errFlags.printlevel);
716
717 if (0 != (errFlags.printlevel & SH_ERR_INFO))
718 dlog_set_active(1);
719 if (0 != (errFlags.printlevel & SH_ERR_ALL))
720 dlog_set_active(2);
721 return retval;
722}
723
724
725/* set level for error logging
726 */
727int sh_error_setlog(const char * str_s)
728{
729 static int reject = 0;
730 if (reject == 1)
731 return (0);
732
733 if (sh.flag.opts == S_TRUE)
734 reject = 1;
735
736 return ( sh_error_set_level(str_s, &errFlags.loglevel) );
737}
738
739
740/* set severity for syslog
741 */
742int sh_error_set_syslog (const char * str_s)
743{
744 static int reject = 0;
745 if (reject == 1)
746 return (0);
747
748 if (sh.flag.opts == S_TRUE)
749 reject = 1;
750
751 return (sh_error_set_level(str_s, &errFlags.sysloglevel));
752}
753
754#if defined(WITH_EXTERNAL)
755/* set severity for external
756 */
757int sh_error_set_external (const char * str_s)
758{
759 static int reject = 0;
760 if (reject == 1)
761 return (0);
762
763 if (sh.flag.opts == S_TRUE)
764 reject = 1;
765
766 return (sh_error_set_level(str_s, &errFlags.externallevel));
767}
768#endif
769
770#if defined(WITH_DATABASE)
771/* set severity for database
772 */
773int sh_error_set_database (const char * str_s)
774{
775 static int reject = 0;
776 if (reject == 1)
777 return (0);
778
779 if (sh.flag.opts == S_TRUE)
780 reject = 1;
781
782 return (sh_error_set_level(str_s, &errFlags.databaselevel));
783}
784#endif
785
786#if defined(HAVE_LIBPRELUDE)
787/* set severity for prelude
788 */
789int sh_error_set_prelude (const char * str_s)
790{
791 static int reject = 0;
792
793 if (reject == 1)
794 return (0);
795
796 if (sh.flag.opts == S_TRUE)
797 reject = 1;
798
799 return sh_error_set_level(str_s, &errFlags.preludelevel);
800}
801#endif
802
803/* init or re-init log facilities that need it
804 */
805void sh_error_fixup(void)
806{
807#if defined(HAVE_LIBPRELUDE)
808 if ((errFlags.preludelevel & SH_ERR_NOT) == 0)
809 sh_prelude_init();
810 else
811 sh_prelude_stop();
812#endif
813#ifdef WITH_DATABASE
814 sh_database_reset();
815#endif
816 return;
817}
818
819/* to be called from sh_prelude_reset
820 */
821void sh_error_init_prelude(void)
822{
823#if defined(HAVE_LIBPRELUDE)
824 if ((errFlags.preludelevel & SH_ERR_NOT) == 0)
825 sh_prelude_init();
826 else
827 sh_prelude_stop();
828#endif
829 return;
830}
831
832
833/* set severity for mailing
834 */
835int sh_error_setseverity (const char * str_s)
836{
837 static int reject = 0;
838 if (reject == 1)
839 return (0);
840
841 if (sh.flag.opts == S_TRUE)
842 reject = 1;
843
844 return (sh_error_set_level(str_s, &errFlags.maillevel));
845}
846
847#ifdef SH_WITH_SERVER
848static char inet_peer[SH_MINIBUF] = { '\0' };
849#ifdef HAVE_LIBPRELUDE
850static char inet_peer_ip[SH_IP_BUF] = { '\0' };
851
852void sh_error_set_peer_ip(const char * str)
853{
854 if (str == NULL)
855 inet_peer_ip[0] = '\0';
856 else
857 sl_strlcpy(inet_peer_ip, str, sizeof(inet_peer_ip));
858}
859#endif
860
861void sh_error_set_peer(const char * str)
862{
863 if (str == NULL)
864 inet_peer[0] = '\0';
865 else
866 sl_strlcpy(inet_peer, str, sizeof(inet_peer));
867}
868#endif
869
870#if defined(SH_WITH_CLIENT) || defined(SH_STANDALONE)
871#include "sh_checksum.h"
872static char * sh_error_replace(const char * msg)
873{
874 char * ret = NULL;
875
876 if (sh_tiger_get_hashtype () == SH_SHA256)
877 {
878 char * store = NULL;
879
880#ifdef SH_USE_XML
881 char c_end = '"';
882 char * str = _("chksum_old=\"");
883 char * str2 = _("chksum_new=\"");
884#else
885 char c_end = '>';
886 char * str = _("chksum_old=<");
887 char * str2 = _("chksum_new=<");
888#endif
889
890 ret = SHA256_ReplaceBaseByHex(msg, str, c_end);
891
892 if (ret) {
893 store = ret;
894 ret = SHA256_ReplaceBaseByHex(ret, str2, c_end);
895 if (ret)
896 SH_FREE(store);
897 else
898 ret = store;
899 } else {
900 ret = SHA256_ReplaceBaseByHex(msg, str2, c_end);
901 }
902 }
903 return ret;
904}
905static void sh_replace_free(char * msg)
906{
907 if (msg)
908 SH_FREE(msg);
909 return;
910}
911#else
912static char * sh_error_replace(const char * msg) { (void) msg; return NULL; }
913static void sh_replace_free(char * msg) { (void) msg; return; }
914#endif
915
916/**********************************************************
917 **********************************************************
918 *
919 * -------- MAIN ERROR HANDLING FUNCTION -----------------
920 *
921 *
922 * this function should be called to report an error
923 *
924 **********************************************************
925 **********************************************************/
926
927SH_MUTEX_RECURSIVE(mutex_err_handle);
928
929void sh_error_handle (int sev1, const char * file, long line,
930 long status, unsigned long msg_id, ...)
931{
932 va_list vl; /* argument list */
933 struct _log_t * lmsg;
934
935 int severity;
936 unsigned int class;
937 char * fmt;
938 volatile int sev = sev1; /* Avoids the 'clobbered by longjmp' warning. */
939
940 int flag_inet;
941
942#ifdef SH_WITH_SERVER
943 int class_inet = clt_class; /* initialize from global */
944 char local_inet_peer[SH_MINIBUF];
945#ifdef HAVE_LIBPRELUDE
946 char local_inet_peer_ip[SH_IP_BUF];
947#endif
948#endif
949
950#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
951 char * ex_msg;
952#endif
953#if defined(WITH_DATABASE)
954 char * escape_msg;
955#endif
956
957 char * hexmsg = NULL;
958
959 static int own_block = 0;
960
961 /*
962 * Block a facility for errors generated
963 * within that facility.
964 */
965 static int print_block = 0;
966#if defined(SH_WITH_MAIL)
967 static int mail_block = 0;
968#endif
969 static int syslog_block = 0;
970 static int log_block = 0;
971#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
972 static int export_block = 0;
973#endif
974#if defined(WITH_EXTERNAL)
975 static int external_block = 0;
976#endif
977#if defined(WITH_DATABASE)
978 static int database_block = 0;
979#endif
980#ifdef HAVE_LIBPRELUDE
981 static int prelude_block = 0;
982#endif
983
984 SL_ENTER(_("sh_error_handle"));
985
986 SH_MUTEX_RECURSIVE_INIT(mutex_err_handle);
987 SH_MUTEX_RECURSIVE_LOCK(mutex_err_handle);
988
989#ifdef SH_WITH_SERVER
990 /* copy the global string into a local array
991 */
992 if ((msg_id == MSG_TCP_MSG) && (inet_peer[0] != '\0'))
993 {
994 sl_strlcpy(local_inet_peer, inet_peer, sizeof(local_inet_peer));
995 sh_error_set_peer(NULL);
996 }
997 else
998 local_inet_peer[0] = '\0';
999
1000#ifdef HAVE_LIBPRELUDE
1001 if ((msg_id == MSG_TCP_MSG) && (inet_peer_ip[0] != '\0'))
1002 {
1003 sl_strlcpy(local_inet_peer_ip, inet_peer_ip, sizeof(local_inet_peer_ip));
1004 sh_error_set_peer_ip(NULL);
1005 }
1006 else
1007 local_inet_peer_ip[0] = '\0';
1008#endif
1009
1010 clt_class = (-1); /* reset global */
1011#endif
1012
1013
1014 if (own_block == 1)
1015 {
1016 goto exit_here;
1017 }
1018
1019 /* --- Initialize to default values. ---
1020 */
1021 if (IsInitialized == BAD)
1022 (void) sh_error_init();
1023
1024 /* Returns pointer to (constant|thread-specific) static memory
1025 */
1026 fmt = /*@i@*/get_format (msg_id, &severity, &class);
1027
1028#ifdef SH_WITH_SERVER
1029 if (class_inet != (-1))
1030 class = (unsigned int) class_inet;
1031#endif
1032
1033 /* --- Consistency check. ---
1034 */
1035 ASSERT((fmt != NULL), _("fmt != NULL"))
1036 if (fmt == NULL)
1037 {
1038 fprintf(stderr,
1039 _("ERROR: msg=<NULL format>, file=<%s>, line=<%ld>\n"),
1040 file, line);
1041 goto exit_here;
1042 }
1043
1044 /* --- Override the catalogue severity. ---
1045 */
1046 if (sev != (-1))
1047 severity = sev;
1048
1049 /* --- Some statistics. ---
1050 */
1051#if defined (SH_WITH_CLIENT) || defined (SH_STANDALONE)
1052 if ( ((1 << class) & ERROR_CLA) &&
1053 (severity & (SH_ERR_ERR|SH_ERR_SEVERE|SH_ERR_FATAL)))
1054 {
1055 ++sh.statistics.files_error;
1056 }
1057#endif
1058
1059 /* these are messages from remote sources
1060 */
1061 if ((severity & SH_ERR_INET) != 0)
1062 {
1063 flag_inet = S_TRUE;
1064 }
1065 else
1066 {
1067 flag_inet = S_FALSE;
1068 }
1069
1070 /* --- Messages not wanted for logging. ---
1071 */
1072 if ( ( (errFlags.printlevel & severity ) == 0 ||
1073 (errFlags.print_class & (1 << class)) == 0 ) &&
1074 ( (errFlags.loglevel & severity ) == 0 ||
1075 (errFlags.log_class & (1 << class)) == 0 ) &&
1076 ( (errFlags.sysloglevel & severity ) == 0 ||
1077 (errFlags.syslog_class & (1 << class)) == 0 ) &&
1078#if defined(SH_WITH_CLIENT) || defined(SH_WITH_CLIENT)
1079 ( (errFlags.exportlevel & severity ) == 0 ||
1080 (errFlags.export_class & (1 << class)) == 0 ) &&
1081#endif
1082#ifdef WITH_EXTERNAL
1083 ( (errFlags.externallevel & severity ) == 0 ||
1084 (errFlags.external_class & (1 << class)) == 0 ) &&
1085#endif
1086#ifdef HAVE_LIBPRELUDE
1087 ( (errFlags.preludelevel & severity ) == 0 ||
1088 (errFlags.prelude_class & (1 << class)) == 0 ) &&
1089#endif
1090#ifdef WITH_DATABASE
1091 ( (errFlags.databaselevel & severity ) == 0 ||
1092 (errFlags.database_class & (1 << class)) == 0 ) &&
1093#endif
1094 ( (errFlags.maillevel & severity ) == 0 ||
1095 (errFlags.mail_class & (1 << class)) == 0 )
1096#ifdef SH_WITH_SERVER
1097 && (flag_inet == S_FALSE) /* still log messages from remote sources */
1098#endif
1099 )
1100 {
1101 goto exit_here;
1102 }
1103
1104 if ((severity & SH_ERR_NOT) != 0)
1105 {
1106 goto exit_here;
1107 }
1108
1109
1110 /* Allocate space for the message.
1111 */
1112 own_block = 1;
1113 lmsg = (struct _log_t *) SH_ALLOC(sizeof(struct _log_t));
1114 MLOCK( (char *) lmsg, sizeof(struct _log_t));
1115 /*@i@*/lmsg->msg = NULL;
1116
1117 /*@i@*/(void) sl_strlcpy(lmsg->format, fmt, SH_PATHBUF);
1118 (void) sl_strlcpy(lmsg->file, file, SH_PATHBUF);
1119 lmsg->severity = severity;
1120 lmsg->class = (int) class;
1121 lmsg->line = line;
1122 lmsg->status = status;
1123
1124 /* Format the log message with timestamp etc.
1125 * Allocate lmsg->msg
1126 */
1127 va_start (vl, msg_id);
1128 (void) sh_error_string (lmsg, vl);
1129 va_end (vl);
1130 own_block = 0;
1131
1132 hexmsg = sh_error_replace(lmsg->msg);
1133
1134 /* Log to stderr.
1135 */
1136 if ( ((errFlags.printlevel & severity) != 0 &&
1137 (errFlags.print_class & (1 << class)) != 0 &&
1138 (errFlags.printlevel & SH_ERR_NOT) == 0)
1139#ifdef SH_WITH_SERVER
1140 || (flag_inet == S_TRUE)
1141#endif
1142 )
1143 {
1144 if (print_block == 0 && (errFlags.printlevel & SH_ERR_NOT) == 0)
1145 {
1146 /* no truncation
1147 */
1148 print_block = 1;
1149 TPT(( 0, FIL__, __LINE__, lmsg->msg));
1150 /*
1151 * Reports first error after failure. Always tries.
1152 */
1153 (void) sh_log_console (hexmsg ? hexmsg : lmsg->msg);
1154 print_block = 0;
1155 }
1156 }
1157
1158
1159 /* Full logging enabled.
1160 */
1161 if (OnlyStderr == S_FALSE) /* full error logging enabled */
1162 {
1163
1164 /* Log to syslog.
1165 */
1166 if ( (errFlags.sysloglevel & severity) != 0 &&
1167 (errFlags.syslog_class & (1 << class)) != 0 &&
1168#ifndef INET_SYSLOG
1169 (flag_inet != S_TRUE) && /* !inet->syslog */
1170#endif
1171 (errFlags.sysloglevel & SH_ERR_NOT) == 0 )
1172 {
1173 /* will truncate to 1023 bytes
1174 */
1175 if (syslog_block == 0)
1176 {
1177 syslog_block = 1;
1178 /*
1179 * Ignores errors. Always tries.
1180 */
1181 (void) sh_log_syslog (lmsg->severity, hexmsg ? hexmsg : lmsg->msg);
1182 syslog_block = 0;
1183 }
1184 }
1185
1186#if defined(WITH_EXTERNAL)
1187 /*
1188 * -- external facility
1189 */
1190 if ((errFlags.externallevel & severity) != 0 &&
1191 (errFlags.external_class & (1 << class)) != 0 &&
1192 (errFlags.externallevel & SH_ERR_NOT) == 0 &&
1193 class != AUD)
1194 {
1195 if (external_block == 0)
1196 {
1197 /* no truncation
1198 */
1199 external_block = 1;
1200 /*
1201 * Reports first error after failure. Always tries.
1202 */
1203 (void) sh_ext_execute ('l', 'o', 'g', hexmsg ? hexmsg : lmsg->msg, 0);
1204 external_block = 0;
1205 }
1206 }
1207#endif
1208
1209#if defined(WITH_DATABASE)
1210 /*
1211 * -- database facility
1212 */
1213 if ((errFlags.databaselevel & severity) != 0 &&
1214 (errFlags.database_class & (1 << class)) != 0 &&
1215 (errFlags.databaselevel & SH_ERR_NOT) == 0 &&
1216 class != AUD)
1217 {
1218 if (database_block == 0 && enableUnsafe == S_TRUE)
1219 {
1220 /* truncates; query_max is 16k
1221 */
1222 database_block = 1;
1223#ifndef SH_STANDALONE
1224 if (msg_id == MSG_TCP_MSG
1225#ifdef INET_SYSLOG
1226 || msg_id == MSG_INET_SYSLOG
1227#endif
1228 )
1229 {
1230 /* do not escape twice
1231 */
1232 /*
1233 * Reports failure every 60 min. Always tries.
1234 */
1235 (void) sh_database_insert (lmsg->msg);
1236 }
1237 else
1238#endif
1239 {
1240 escape_msg = sh_tools_safe_name(lmsg->msg, 0);
1241 /*
1242 * Reports failure every 60 min. Always tries.
1243 */
1244 (void) sh_database_insert (escape_msg);
1245 SH_FREE(escape_msg);
1246 }
1247 database_block = 0;
1248 }
1249 }
1250#endif
1251
1252 /****************************************************
1253 * Optionally include client code for TCP forwarding
1254 * to log server
1255 ****************************************************/
1256#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1257 /* Export by TCP.
1258 */
1259
1260 if ( ((errFlags.exportlevel & severity ) != 0 &&
1261 (errFlags.export_class & (1 << class)) != 0 &&
1262 (errFlags.exportlevel & SH_ERR_NOT) == 0 &&
1263 class != AUD )
1264#ifdef SH_WITH_SERVER
1265 /* always log inet to export */
1266 || (flag_inet == S_TRUE && sh.srvexport.name[0] != '\0')
1267#endif
1268 /* sh.flag.isserver != GOOD && */
1269 /* (flag_inet == S_FALSE) */ /* don't log inet to export */
1270 )
1271 {
1272 if (export_block == 0)
1273 {
1274 int retval;
1275 size_t ex_len;
1276
1277 /* will truncate to 65280 bytes
1278 */
1279 export_block = 1;
1280 /* ex_len = 64 + sl_strlen(lmsg->msg) + 1; */
1281 ex_len = sl_strlen(lmsg->msg);
1282 if (sl_ok_adds(ex_len, 65))
1283 ex_len = 64 + ex_len + 1;
1284 ex_msg = SH_ALLOC (ex_len);
1285
1286 sl_snprintf(ex_msg, ex_len, _("%d?%u?%s"),
1287 severity, class, lmsg->msg);
1288 retval = sh_forward (ex_msg);
1289 SH_FREE(ex_msg);
1290 export_block = 0;
1291 if (retval == -2)
1292 {
1293 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1294 _("log server"));
1295 }
1296 }
1297 }
1298#endif
1299
1300
1301 /* Log to mail.
1302 */
1303#if defined(SH_WITH_MAIL)
1304 if ((errFlags.maillevel & severity ) != 0 &&
1305 (errFlags.mail_class & (1 << class)) != 0 &&
1306 (errFlags.maillevel & SH_ERR_NOT) == 0 &&
1307 class != AUD &&
1308 (flag_inet == S_FALSE) ) /* don't log inet to email */
1309 {
1310 if (mail_block == 0)
1311 {
1312 int retval;
1313
1314 /* will truncate to 998 bytes
1315 */
1316 mail_block = 1;
1317
1318 BREAKEXIT(sh_nmail_msg);
1319 if ( (severity & SH_ERR_FATAL) == 0)
1320 retval = sh_nmail_pushstack (severity, hexmsg ? hexmsg : lmsg->msg, NULL);
1321 else
1322 retval = sh_nmail_msg (severity, hexmsg ? hexmsg : lmsg->msg, NULL);
1323
1324 mail_block = 0;
1325 if (retval == -2)
1326 {
1327 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1328 _("email"));
1329 }
1330 }
1331 }
1332#endif
1333
1334#ifdef HAVE_LIBPRELUDE
1335 if (((errFlags.preludelevel & severity ) != 0 &&
1336 (errFlags.prelude_class & (1 << class)) != 0 &&
1337 (errFlags.preludelevel & SH_ERR_NOT) == 0 &&
1338 (class != AUD))
1339#ifdef SH_WITH_SERVER
1340 || (flag_inet == S_TRUE)
1341#endif
1342 )
1343 {
1344 if (prelude_block == 0 && enableUnsafe == S_TRUE)
1345 {
1346 /* will truncate to 998 bytes
1347 */
1348 prelude_block = 1;
1349
1350 BREAKEXIT(sh_prelude_alert);
1351 /*
1352 * Reports first error after failure. Always tries.
1353 */
1354#if defined(HAVE_LIBPRELUDE) && defined(SH_WITH_SERVER)
1355 (void) sh_prelude_alert (severity, (int) class,
1356 hexmsg ? hexmsg : lmsg->msg, lmsg->status, msg_id,
1357 local_inet_peer_ip);
1358#else
1359 (void) sh_prelude_alert (severity, (int) class,
1360 hexmsg ? hexmsg : lmsg->msg, lmsg->status, msg_id,
1361 NULL);
1362#endif
1363 prelude_block = 0;
1364 }
1365 }
1366#endif
1367
1368 /* Log to logfile
1369 */
1370
1371 if ( ( ( (errFlags.loglevel & severity) != 0 &&
1372 (errFlags.log_class & (1 << class)) != 0 &&
1373 (errFlags.loglevel & SH_ERR_NOT) == 0 )
1374#ifdef SH_WITH_SERVER
1375 || (flag_inet == S_TRUE)
1376#endif
1377 ) &&
1378 class != AUD &&
1379 (errFlags.HaveLog != BAD) && /* temporary switched off */
1380 (severity & SH_ERR_NOT) == 0 /* paranoia */
1381 )
1382 {
1383 if (log_block == 0)
1384 {
1385 /* no truncation
1386 */
1387 log_block = 1;
1388 BREAKEXIT(sh_log_file);
1389#ifdef SH_WITH_SERVER
1390 if (0 != sl_ret_euid())
1391 {
1392 /*
1393 * Reports first error after failure. Always tries.
1394 */
1395 if (local_inet_peer[0] == '\0')
1396 (void) sh_log_file (lmsg->msg, NULL);
1397 else
1398 (void) sh_log_file (lmsg->msg, local_inet_peer);
1399 }
1400#else
1401 (void) sh_log_file (hexmsg ? hexmsg : lmsg->msg, NULL);
1402#endif
1403 /* sh_log_file (lmsg->msg); */
1404 log_block = 0;
1405 }
1406 }
1407
1408 }
1409
1410 /* Cleanup.
1411 */
1412 own_block = 1;
1413
1414 if (lmsg->msg)
1415 SH_FREE( lmsg->msg );
1416 sh_replace_free(hexmsg);
1417
1418 memset ( lmsg, (int) '\0', sizeof(struct _log_t) );
1419 MUNLOCK( (char *) lmsg, sizeof(struct _log_t) );
1420 SH_FREE( lmsg );
1421 own_block = 0;
1422
1423 exit_here:
1424 ; /* label at end of compound statement */
1425 SH_MUTEX_RECURSIVE_UNLOCK(mutex_err_handle);
1426
1427 /*@i@*/SL_RET0(_("sh_error_handle"));
1428/*@i@*/}
1429
1430#if defined(SH_WITH_MAIL)
1431void sh_error_mail (const char * alias, int sev,
1432 const char * file, long line,
1433 long status, unsigned long msg_id, ...)
1434{
1435 va_list vl; /* argument list */
1436 struct _log_t * lmsg;
1437
1438 int severity;
1439 unsigned int class;
1440 char * fmt;
1441 int retval;
1442
1443 SL_ENTER(_("sh_error_mail"));
1444
1445 /* Returns pointer to (constant|thread-specific) static memory
1446 */
1447 fmt = /*@i@*/get_format (msg_id, &severity, &class);
1448
1449 if (!fmt)
1450 {
1451 SL_RET0(_("sh_error_mail"));
1452 }
1453
1454 /* --- Override the catalogue severity. ---
1455 */
1456 if (sev != (-1))
1457 severity = sev;
1458
1459 /* --- Build the message. ---
1460 */
1461 lmsg = (struct _log_t *) SH_ALLOC(sizeof(struct _log_t));
1462 MLOCK( (char *) lmsg, sizeof(struct _log_t));
1463 /*@i@*/lmsg->msg = NULL;
1464
1465 /*@i@*/(void) sl_strlcpy(lmsg->format, fmt, SH_PATHBUF);
1466 (void) sl_strlcpy(lmsg->file, file, SH_PATHBUF);
1467 lmsg->severity = severity;
1468 lmsg->class = (int) class;
1469 lmsg->line = line;
1470 lmsg->status = status;
1471
1472 /* Format the log message with timestamp etc.
1473 * Allocate lmsg->msg
1474 */
1475 va_start (vl, msg_id);
1476 (void) sh_error_string (lmsg, vl);
1477 va_end (vl);
1478
1479 if ( (severity & SH_ERR_FATAL) == 0)
1480 retval = sh_nmail_pushstack (severity, lmsg->msg, alias);
1481 else
1482 retval = sh_nmail_msg (severity, lmsg->msg, alias);
1483
1484 if (retval == -2)
1485 {
1486 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1487 _("email"));
1488 }
1489 SL_RET0(_("sh_error_mail"));
1490}
1491#else
1492void sh_error_mail (const char * alias, int sev,
1493 const char * file, long line,
1494 long status, unsigned long msg_id, ...)
1495{
1496 (void) alias;
1497 (void) sev;
1498 (void) file;
1499 (void) line;
1500 (void) status;
1501 (void) msg_id;
1502
1503 return;
1504}
1505/* defined(SH_WITH_MAIL) */
1506#endif
1507
1508/* -------------------------
1509 *
1510 * private functions below
1511 *
1512 * -------------------------
1513 */
1514
1515
1516/* --- Get the format from the message catalog. ---
1517 */
1518/*@owned@*/ /*@null@*/inline
1519static char * get_format(unsigned long msg_id, /*@out@*/ int * priority,
1520 /*@out@*/unsigned int * class)
1521{
1522 int i = 0;
1523
1524 SL_ENTER(_("get_format"));
1525 while (1 == 1)
1526 {
1527 if ( msg_cat[i].format == NULL )
1528 break;
1529
1530 if ( (unsigned long) msg_cat[i].id == msg_id)
1531 {
1532 *priority = (int) msg_cat[i].priority;
1533 *class = (unsigned int) msg_cat[i].class;
1534 SL_RETURN (((char *) _(msg_cat[i].format)), _("get_format"));
1535 }
1536 ++i;
1537 }
1538 *priority = SH_ERR_ERR;
1539 *class = ERR;
1540 SL_RETURN (NULL, _("get_format"));
1541}
1542
1543/*@null@*//*@only@*/static char * ehead_format = NULL;
1544
1545/* allocate space for user-defined message header
1546 */
1547int sh_error_ehead (/*@null@*/const char * str_s)
1548{
1549 size_t size;
1550 const char * s;
1551
1552 SL_ENTER(_("sh_error_ehead"));
1553
1554 if (str_s == NULL)
1555 {
1556 SL_RETURN (-1, _("sh_error_ehead"));
1557 }
1558
1559 /* ascii 34 ist t\"ttelchen
1560 */
1561 /*@i@*/ if (str_s[0] == 34) s = &str_s[1];
1562 else s = str_s;
1563
1564 size = /*@i@*/strlen(s);
1565 if (/*@i@*/s[size-1] == (char) 34) --size; /* truncate */
1566
1567 if (ehead_format != NULL)
1568 SH_FREE(ehead_format);
1569
1570 /*@i@*/ehead_format = SH_ALLOC(size+1);
1571 /*@i@*/ (void) sl_strlcpy(ehead_format, s, size+1);
1572
1573 SL_RETURN( 0, _("sh_error_ehead"));
1574}
1575
1576
1577/* print an error into string
1578 */
1579static int sh_error_string (struct _log_t * lmsg, va_list vl)
1580{
1581 size_t len;
1582 int required;
1583 unsigned long line;
1584 char sev[16] = "";
1585 char cla[16] = "";
1586 char tst[64] = "";
1587 char *p;
1588 va_list vl2;
1589
1590 st_format rep_ehead_tab[] = {
1591 { 'S', S_FMT_STRING, 0, 0, NULL}, /* severity */
1592 { 'T', S_FMT_STRING, 0, 0, NULL}, /* timestamp */
1593 { 'F', S_FMT_STRING, 0, 0, NULL}, /* file */
1594 { 'L', S_FMT_ULONG, 0, 0, NULL}, /* line */
1595 { 'C', S_FMT_STRING, 0, 0, NULL}, /* class */
1596 { 'E', S_FMT_LONG, 0, 0, NULL}, /* status */
1597 {'\0', S_FMT_ULONG, 0, 0, NULL},
1598 };
1599
1600 SL_ENTER(_("sh_error_string"));
1601
1602 if (ehead_format == NULL)
1603 {
1604 ehead_format = SH_ALLOC(64);
1605#ifdef SH_USE_XML
1606 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1607 (void) sl_strlcpy(ehead_format,
1608 _("<log sev=\"%S\" tstamp=\"%T\" "), 64);
1609 else
1610 (void) sl_strlcpy(ehead_format,
1611 _("<log sev=\"%S\" tstamp=\"%T\" p.f=\"%F\" p.l=\"%L\" p.s=\"%E\" "), 64);
1612#else
1613 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1614 (void) sl_strlcpy(ehead_format, _("%S %T "), 64);
1615 else
1616 (void) sl_strlcpy(ehead_format, _("%S %T (%F, %L, %E) "), 64);
1617#endif
1618 }
1619
1620 /* header of error message
1621 */
1622#ifdef SH_USE_XML
1623 if ( (lmsg->severity & SH_ERR_INET) != 0)
1624 (void) sl_strlcpy (sev, _("RCVT"), 11);
1625 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1626 (void) sl_strlcpy (sev, _("DEBG"), 11);
1627 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1628 (void) sl_strlcpy (sev, _("INFO"), 11);
1629 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1630 (void) sl_strlcpy (sev, _("NOTE"), 11);
1631 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1632 (void) sl_strlcpy (sev, _("WARN"), 11);
1633 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1634 (void) sl_strlcpy (sev, _("MARK"), 11);
1635 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1636 (void) sl_strlcpy (sev, _("ERRO"), 11);
1637 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1638 (void) sl_strlcpy (sev, _("CRIT"), 11);
1639 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1640 (void) sl_strlcpy (sev, _("ALRT"), 11);
1641 else {
1642 (void) sl_strlcpy (sev, _("????"), 11);
1643#else
1644#if defined(INET_SYSLOG)
1645 if ( (lmsg->severity & SH_ERR_INET) != 0)
1646 (void) sl_strlcpy (sev, _("<NET> : "), 11);
1647#else
1648 if ( (lmsg->severity & SH_ERR_INET) != 0)
1649 (void) sl_strlcpy (sev, _("<TCP> : "), 11);
1650#endif
1651 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1652 (void) sl_strlcpy (sev, _("DEBUG : "), 11);
1653 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1654 (void) sl_strlcpy (sev, _("INFO : "), 11);
1655 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1656 (void) sl_strlcpy (sev, _("NOTICE : "), 11);
1657 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1658 (void) sl_strlcpy (sev, _("WARN : "), 11);
1659 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1660 (void) sl_strlcpy (sev, _("MARK : "), 11);
1661 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1662 (void) sl_strlcpy (sev, _("ERROR : "), 11);
1663 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1664 (void) sl_strlcpy (sev, _("CRIT : "), 11);
1665 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1666 (void) sl_strlcpy (sev, _("ALERT : "), 11);
1667 else {
1668 (void) sl_strlcpy (sev, _("??? : "), 11);
1669#endif
1670 }
1671
1672 (void) sh_unix_time (0, tst, 64);
1673 line = (unsigned long) lmsg->line;
1674 (void) sl_strlcpy (cla, _(class_cat[lmsg->class]), 11);
1675
1676 /*@i@*/rep_ehead_tab[0].data_str = sev;
1677 /*@i@*/rep_ehead_tab[1].data_str = tst;
1678 /*@i@*/rep_ehead_tab[2].data_str = lmsg->file;
1679 /*@i@*/rep_ehead_tab[3].data_ulong = line;
1680 /*@i@*/rep_ehead_tab[4].data_str = cla;
1681 /*@i@*/rep_ehead_tab[5].data_long = lmsg->status;
1682
1683 p = /*@i@*/sh_util_formatted(ehead_format, rep_ehead_tab);
1684
1685 /* --- copy the header to lmsg->msg ---
1686 */
1687 /*@i@*/lmsg->msg = SH_ALLOC(SH_BUFSIZE);
1688 lmsg->msg_len = SH_BUFSIZE;
1689
1690 if (p)
1691 {
1692 (void) sl_strlcpy (lmsg->msg, p, SH_BUFSIZE);
1693 SH_FREE(p);
1694 }
1695 else
1696 {
1697 lmsg->msg[0] = '\0';
1698 }
1699
1700
1701 /* --- copy message to lmsg->msg ---
1702 */
1703 if ( NULL == strchr(lmsg->format, '%') )
1704 {
1705 (void) sl_strlcat (lmsg->msg, lmsg->format, (size_t) lmsg->msg_len);
1706 }
1707 else
1708 {
1709 /* use va_copy */
1710 /*@i@*/va_copy(vl2, vl);
1711 len = sl_strlen(lmsg->msg);
1712 /*@i@*/required = sl_vsnprintf(&(lmsg->msg[len]),
1713 (lmsg->msg_len - len), lmsg->format, vl);
1714
1715 if ((required >= 0) &&
1716 sl_ok_adds(required, len) &&
1717 sl_ok_adds((required+len), 4) &&
1718 ((required + len) > (lmsg->msg_len - 4)) )
1719 {
1720 /*@i@*/p = SH_ALLOC(required + len + 4);
1721 (void) sl_strlcpy (p, lmsg->msg, required + len + 1);
1722 SH_FREE(lmsg->msg);
1723 lmsg->msg = p;
1724 lmsg->msg_len = required + len + 4;
1725 (void) sl_vsnprintf(&(lmsg->msg[len]),
1726 (required + 1), lmsg->format, vl2);
1727 }
1728 va_end(vl2);
1729 }
1730
1731#ifdef SH_USE_XML
1732 /* closing tag
1733 */
1734 if (lmsg->msg[sl_strlen(lmsg->msg)-1] != '>')
1735 (void) sl_strlcat (lmsg->msg, _(" />"), lmsg->msg_len);
1736#endif
1737
1738 SL_RETURN(0, _("sh_error_string"));
1739}
1740
1741
1742
1743
1744/* --- Initialize. ---
1745 */
1746static int sh_error_init ()
1747{
1748 register int j;
1749
1750 SL_ENTER(_("sh_error_init"));
1751
1752 errFlags.debug = 0;
1753 errFlags.HaveLog = GOOD;
1754 errFlags.sysloglevel = SH_ERR_NOT;
1755#if defined(SH_STEALTH)
1756 errFlags.loglevel = SH_ERR_NOT;
1757#else
1758 errFlags.loglevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1759 SH_ERR_FATAL);
1760#endif
1761 errFlags.externallevel = SH_ERR_NOT;
1762 errFlags.databaselevel = SH_ERR_NOT;
1763 errFlags.preludelevel = SH_ERR_NOT;
1764 errFlags.maillevel = SH_ERR_FATAL;
1765#if defined(SH_STEALTH)
1766 errFlags.printlevel = SH_ERR_NOT;
1767#else
1768 errFlags.printlevel = (SH_ERR_INFO | SH_ERR_NOTICE | SH_ERR_WARN |
1769 SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1770 SH_ERR_FATAL);
1771 flag_err_info = SL_TRUE;
1772#endif
1773
1774#if defined(SH_WITH_SERVER)
1775 errFlags.exportlevel = SH_ERR_NOT;
1776#else
1777 errFlags.exportlevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1778 SH_ERR_FATAL);
1779#endif
1780
1781 errFlags.log_class = 0xFFFF;
1782 errFlags.print_class = 0xFFFF;
1783 errFlags.mail_class = 0xFFFF;
1784 errFlags.export_class = 0xFFFF;
1785 errFlags.syslog_class = 0xFFFF;
1786 errFlags.external_class = 0xFFFF;
1787 errFlags.database_class = 0xFFFF;
1788 errFlags.prelude_class = 0xFFFF;
1789
1790
1791 for (j = 0; j < SH_ERR_T_END; ++j)
1792 ShDFLevel[j] = SH_ERR_SEVERE;
1793
1794 IsInitialized = GOOD;
1795 SL_RETURN (0, _("sh_error_init"));
1796}
Note: See TracBrowser for help on using the repository browser.