source: trunk/src/sh_error.c@ 117

Last change on this file since 117 was 86, checked in by rainer, 18 years ago

More thorough fix for ticket #47, and corresponding regression test.

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