source: branches/samhain-2_2-branch/src/sh_error.c@ 454

Last change on this file since 454 was 65, checked in by rainer, 18 years ago

Fix some minor bugs.

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