source: trunk/src/sh_error.c@ 23

Last change on this file since 23 was 22, checked in by rainer, 19 years ago

Minor code revisions.

File size: 36.6 KB
RevLine 
[1]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 */
[22]104int sh_error_convert_level (const char * str_s);
[1]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
[20]117int sh_error_verify (const char * s)
[1]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
[22]221static int sh_error_set_classmask (const char * str, int * facility_mask)
[1]222{
223 char * p;
224 int num = 0;
225 unsigned int i;
226 size_t len;
[22]227 char * c;
[1]228
229 SL_ENTER(_("sh_error_set_classmask"));
230
[22]231 if (str == NULL)
[1]232 SL_RETURN( -1, _("sh_error_set_classmask"));
233
234 if (IsInitialized == BAD)
235 (void) sh_error_init();
236
[22]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
[1]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
[22]280 SH_FREE(c);
[1]281 SL_RETURN( 0, _("sh_error_set_classmask"));
282}
283
[22]284int sh_error_log_mask (const char * c)
[1]285{
286 return (sh_error_set_classmask(c, &(errFlags.log_class)));
287}
[22]288int sh_error_mail_mask (const char * c)
[1]289{
290 return (sh_error_set_classmask(c, &(errFlags.mail_class)));
291}
[22]292int sh_error_print_mask (const char * c)
[1]293{
294 return (sh_error_set_classmask(c, &(errFlags.print_class)));
295}
[22]296int sh_error_export_mask (const char * c)
[1]297{
298 return (sh_error_set_classmask(c, &(errFlags.export_class)));
299}
[22]300int sh_error_syslog_mask (const char * c)
[1]301{
302 return (sh_error_set_classmask(c, &(errFlags.syslog_class)));
303}
[22]304int sh_error_external_mask (const char * c)
[1]305{
306 return (sh_error_set_classmask(c, &(errFlags.external_class)));
307}
[22]308int sh_error_database_mask (const char * c)
[1]309{
310 return (sh_error_set_classmask(c, &(errFlags.database_class)));
311}
[22]312int sh_error_prelude_mask (const char * c)
[1]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
[22]454int sh_error_convert_level (const char * str_s)
[1]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 */
[22]480int sh_error_set_iv (int iv, const char * str_s)
[1]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
[20]512int sh_error_set_level(const char * str_in, int * facility)
[1]513{
514 register int i, j, f = BAD;
515
516 int old_facility;
[20]517 const char * str_s = str_in;
[1]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#ifdef SH_WITH_CLIENT
642/* set severity for TCP export
643 */
[20]644int sh_error_setexport(const char * str_s)
[1]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
[20]661int sh_error_setprint(const char * str_s)
[1]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 */
[20]684int sh_error_setlog(const char * str_s)
[1]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 */
[20]699int sh_error_set_syslog (const char * str_s)
[1]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 */
[20]714int sh_error_set_external (const char * str_s)
[1]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 */
[20]730int sh_error_set_database (const char * str_s)
[1]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 */
[20]746int sh_error_set_prelude (const char * str_s)
[1]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 */
[20]792int sh_error_setseverity (const char * str_s)
[1]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)
[11]810 inet_peer[0] = '\0';
[1]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#ifdef SH_WITH_CLIENT
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)
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 if ((severity & SH_ERR_INET) != 0)
929 {
930 flag_inet = S_TRUE;
931 }
932
933 /* --- Messages not wanted for logging. ---
934 */
935 if ( ( (errFlags.printlevel & severity ) == 0 ||
936 (errFlags.print_class & (1 << class)) == 0 ) &&
937 ( (errFlags.loglevel & severity ) == 0 ||
938 (errFlags.log_class & (1 << class)) == 0 ) &&
939 ( (errFlags.sysloglevel & severity ) == 0 ||
940 (errFlags.syslog_class & (1 << class)) == 0 ) &&
941#ifdef SH_WITH_CLIENT
942 ( (errFlags.exportlevel & severity ) == 0 ||
943 (errFlags.export_class & (1 << class)) == 0 ) &&
944#endif
945#ifdef WITH_EXTERNAL
946 ( (errFlags.externallevel & severity ) == 0 ||
947 (errFlags.external_class & (1 << class)) == 0 ) &&
948#endif
949#ifdef HAVE_LIBPRELUDE
950 ( (errFlags.preludelevel & severity ) == 0 ||
951 (errFlags.prelude_class & (1 << class)) == 0 ) &&
952#endif
953#ifdef WITH_DATABASE
954 ( (errFlags.databaselevel & severity ) == 0 ||
955 (errFlags.database_class & (1 << class)) == 0 ) &&
956#endif
957 ( (errFlags.maillevel & severity ) == 0 ||
958 (errFlags.mail_class & (1 << class)) == 0 )
959#ifdef SH_WITH_SERVER
960 && (flag_inet == S_FALSE)
961#endif
962 )
963 {
964 SL_RET0(_("sh_error_handle"));
965 }
966
967 if ((severity & SH_ERR_NOT) != 0)
968 {
969 SL_RET0(_("sh_error_handle"));
970 }
971
972
973 /* Allocate space for the message.
974 */
975 own_block = 1;
976 lmsg = (struct _log_t *) SH_ALLOC(sizeof(struct _log_t));
977 MLOCK( (char *) lmsg, sizeof(struct _log_t));
978 /*@i@*/lmsg->msg = NULL;
979
980 /*@i@*/(void) sl_strlcpy(lmsg->format, fmt, SH_PATHBUF);
981 (void) sl_strlcpy(lmsg->file, file, SH_PATHBUF);
982 lmsg->severity = severity;
983 lmsg->class = (int) class;
984 lmsg->line = line;
985 lmsg->status = status;
986 own_block = 0;
987
988
989 /* Format the log message with timestamp etc.
990 * Allocate lmsg->msg
991 */
992 own_block = 1;
993 va_start (vl, msg_id);
994 (void) sh_error_string (lmsg, vl);
995 va_end (vl);
996 own_block = 0;
997
998
999 /* Log to stderr.
1000 */
1001 if ( ((errFlags.printlevel & severity) != 0 &&
1002 (errFlags.print_class & (1 << class)) != 0 &&
1003 (errFlags.printlevel & SH_ERR_NOT) == 0)
1004#ifdef SH_WITH_SERVER
1005 || (flag_inet == S_TRUE)
1006#endif
1007 )
1008 {
1009 if (print_block == 0 && (errFlags.printlevel & SH_ERR_NOT) == 0)
1010 {
1011 /* no truncation
1012 */
1013 print_block = 1;
1014 TPT(( 0, FIL__, __LINE__, lmsg->msg));
1015 /*
1016 * Reports first error after failure. Always tries.
1017 */
1018 (void) sh_log_console (lmsg->msg);
1019 print_block = 0;
1020 }
1021 }
1022
1023
1024 /* Full logging enabled.
1025 */
1026 if (OnlyStderr == BAD) /* full error logging enabled */
1027 {
1028
1029 /* Log to syslog.
1030 */
1031 if ( (errFlags.sysloglevel & severity) != 0 &&
1032 (errFlags.syslog_class & (1 << class)) != 0 &&
1033#ifndef INET_SYSLOG
1034 (flag_inet != S_TRUE) && /* !inet->syslog */
1035#endif
1036 (errFlags.sysloglevel & SH_ERR_NOT) == 0 )
1037 {
1038 /* will truncate to 1023 bytes
1039 */
1040 if (syslog_block == 0)
1041 {
1042 syslog_block = 1;
1043 /*
1044 * Ignores errors. Always tries.
1045 */
1046 (void) sh_log_syslog (lmsg->severity, lmsg->msg);
1047 syslog_block = 0;
1048 }
1049 }
1050
1051#if defined(WITH_EXTERNAL)
1052 /*
1053 * -- external facility
1054 */
1055 if ((errFlags.externallevel & severity) != 0 &&
1056 (errFlags.external_class & (1 << class)) != 0 &&
1057 (errFlags.externallevel & SH_ERR_NOT) == 0 &&
1058 class != AUD)
1059 {
1060 if (external_block == 0)
1061 {
1062 /* no truncation
1063 */
1064 external_block = 1;
1065 /*
1066 * Reports first error after failure. Always tries.
1067 */
1068 (void) sh_ext_execute ('l', 'o', 'g', lmsg->msg, 0);
1069 external_block = 0;
1070 }
1071 }
1072#endif
1073
1074#if defined(WITH_DATABASE)
1075 /*
1076 * -- database facility
1077 */
1078 if ((errFlags.databaselevel & severity) != 0 &&
1079 (errFlags.database_class & (1 << class)) != 0 &&
1080 (errFlags.databaselevel & SH_ERR_NOT) == 0 &&
1081 class != AUD)
1082 {
1083 if (database_block == 0)
1084 {
1085 /* truncates; query_max is 16k
1086 */
1087 database_block = 1;
1088#ifndef SH_STANDALONE
1089 if (msg_id == MSG_TCP_MSG
1090#ifdef INET_SYSLOG
1091 || msg_id == MSG_INET_SYSLOG
1092#endif
1093 )
1094 {
1095 /* do not escape twice
1096 */
1097 /*
1098 * Reports failure every 60 min. Always tries.
1099 */
1100 (void) sh_database_insert (lmsg->msg);
1101 }
1102 else
1103#endif
1104 {
1105 escape_msg = sh_tools_safe_name(lmsg->msg, 0);
1106 /*
1107 * Reports failure every 60 min. Always tries.
1108 */
1109 (void) sh_database_insert (escape_msg);
1110 SH_FREE(escape_msg);
1111 }
1112 database_block = 0;
1113 }
1114 }
1115#endif
1116
1117 /****************************************************
1118 * Optionally include client code for TCP forwarding
1119 * to log server
1120 ****************************************************/
1121#ifdef SH_WITH_CLIENT
1122 /* Export by TCP.
1123 */
1124 if ((errFlags.exportlevel & severity ) != 0 &&
1125 (errFlags.export_class & (1 << class)) != 0 &&
1126 (errFlags.exportlevel & SH_ERR_NOT) == 0 &&
1127 class != AUD &&
1128 sh.flag.isserver != GOOD &&
1129 (flag_inet == S_FALSE) ) /* don't log inet to export */
1130 {
1131 if (export_block == 0)
1132 {
1133 int retval;
[22]1134 size_t ex_len;
[1]1135
1136 /* will truncate to 65280 bytes
1137 */
1138 export_block = 1;
[22]1139 ex_len = 64 + sl_strlen(lmsg->msg) + 1;
1140 ex_msg = SH_ALLOC (ex_len);
1141
1142 sl_snprintf(ex_msg, ex_len, _("%d?%u?%s"),
1143 severity, class, lmsg->msg);
1144
[1]1145 retval = sh_forward (ex_msg);
1146 SH_FREE(ex_msg);
1147 export_block = 0;
1148 if (retval == -2)
1149 {
1150 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1151 _("log server"));
1152 }
1153 }
1154 }
1155#endif
1156
1157
1158 /* Log to mail.
1159 */
1160#if defined(SH_WITH_MAIL)
1161 if ((errFlags.maillevel & severity ) != 0 &&
1162 (errFlags.mail_class & (1 << class)) != 0 &&
1163 (errFlags.maillevel & SH_ERR_NOT) == 0 &&
1164 class != AUD &&
1165 (flag_inet == S_FALSE) ) /* don't log inet to email */
1166 {
1167 if (mail_block == 0)
1168 {
1169 int retval;
1170
1171 /* will truncate to 998 bytes
1172 */
1173 mail_block = 1;
1174
1175 BREAKEXIT(sh_mail_msg);
1176 if ( (severity & SH_ERR_FATAL) == 0)
1177 retval = sh_mail_pushstack (lmsg->msg);
1178 else
1179 retval = sh_mail_msg (lmsg->msg);
1180
1181 mail_block = 0;
1182 if (retval == -2)
1183 {
1184 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1185 _("email"));
1186 }
1187 }
1188 }
1189#endif
1190
1191#ifdef HAVE_LIBPRELUDE
1192 if (((errFlags.preludelevel & severity ) != 0 &&
1193 (errFlags.prelude_class & (1 << class)) != 0 &&
1194 (errFlags.preludelevel & SH_ERR_NOT) == 0 &&
1195 (class != AUD))
1196#ifdef SH_WITH_SERVER
1197 || (flag_inet == S_TRUE)
1198#endif
1199 )
1200 {
1201 if (prelude_block == 0)
1202 {
1203 /* will truncate to 998 bytes
1204 */
1205 prelude_block = 1;
1206
1207 BREAKEXIT(sh_prelude_alert);
1208 /*
1209 * Reports first error after failure. Always tries.
1210 */
1211 (void) sh_prelude_alert (severity, (int) class, lmsg->msg,
1212 lmsg->status, msg_id);
1213
1214 prelude_block = 0;
1215 }
1216 }
1217#endif
1218
1219 /* Log to logfile
1220 */
1221
1222 if ( ( ( (errFlags.loglevel & severity) != 0 &&
1223 (errFlags.log_class & (1 << class)) != 0 &&
1224 (errFlags.loglevel & SH_ERR_NOT) == 0 )
1225#ifdef SH_WITH_SERVER
1226 || (flag_inet == S_TRUE)
1227#endif
1228 ) &&
1229 class != AUD &&
1230 (errFlags.HaveLog != BAD) && /* temporary switched off */
1231 (severity & SH_ERR_NOT) == 0 /* paranoia */
1232 )
1233 {
1234 if (log_block == 0)
1235 {
1236 /* no truncation
1237 */
1238 log_block = 1;
1239 BREAKEXIT(sh_log_file);
1240#ifdef SH_WITH_SERVER
1241 if (0 != sl_ret_euid())
1242 {
1243 /*
1244 * Reports first error after failure. Always tries.
1245 */
1246 if (local_inet_peer[0] == '\0')
1247 (void) sh_log_file (lmsg->msg, NULL);
1248 else
1249 (void) sh_log_file (lmsg->msg, local_inet_peer);
1250 }
1251#else
1252 (void) sh_log_file (lmsg->msg, NULL);
1253#endif
1254 /* sh_log_file (lmsg->msg); */
1255 log_block = 0;
1256 }
1257 }
1258
1259 }
1260
1261 /* Cleanup.
1262 */
1263 own_block = 1;
1264
1265 if (lmsg->msg)
1266 SH_FREE( lmsg->msg );
1267
1268 memset ( lmsg, (int) '\0', sizeof(struct _log_t) );
1269 MUNLOCK( (char *) lmsg, sizeof(struct _log_t) );
1270 SH_FREE( lmsg );
1271 own_block = 0;
1272
1273 /*@i@*/SL_RET0(_("sh_error_handle"));
1274/*@i@*/}
1275
1276
1277/* -------------------------
1278 *
1279 * private functions below
1280 *
1281 * -------------------------
1282 */
1283
1284
1285/* --- Get the format from the message catalog. ---
1286 */
1287/*@owned@*/ /*@null@*/inline
1288static char * get_format(unsigned long msg_id, /*@out@*/ int * priority,
1289 /*@out@*/unsigned int * class)
1290{
1291 int i = 0;
1292
1293 SL_ENTER(_("get_format"));
1294 while (1 == 1)
1295 {
1296 if ( msg_cat[i].format == NULL )
1297 break;
1298
1299 if ( (unsigned long) msg_cat[i].id == msg_id)
1300 {
1301 *priority = (int) msg_cat[i].priority;
1302 *class = (unsigned int) msg_cat[i].class;
1303 SL_RETURN (_(msg_cat[i].format), _("get_format"));
1304 }
1305 ++i;
1306 }
1307 *priority = SH_ERR_ERR;
1308 *class = ERR;
1309 SL_RETURN (NULL, _("get_format"));
1310}
1311
1312/*@null@*//*@only@*/static char * ehead_format = NULL;
1313
1314/* allocate space for user-defined message header
1315 */
[22]1316int sh_error_ehead (/*@null@*/const char * str_s)
[1]1317{
1318 size_t size;
[22]1319 const char * s;
[1]1320
1321 SL_ENTER(_("sh_error_ehead"));
1322
1323 if (str_s == NULL)
1324 {
1325 SL_RETURN (-1, _("sh_error_ehead"));
1326 }
1327
1328 /* ascii 34 ist t\"ttelchen
1329 */
1330 /*@i@*/ if (str_s[0] == 34) s = &str_s[1];
1331 else s = str_s;
1332
1333 size = /*@i@*/strlen(s);
[22]1334 if (/*@i@*/s[size-1] == (char) 34) --size; /* truncate */
[1]1335
1336 if (ehead_format != NULL)
1337 SH_FREE(ehead_format);
1338
1339 /*@i@*/ehead_format = SH_ALLOC(size+1);
1340 /*@i@*/ (void) sl_strlcpy(ehead_format, s, size+1);
1341
1342 SL_RETURN( 0, _("sh_error_ehead"));
1343}
1344
1345#if !defined(VA_COPY)
1346#if defined(__GNUC__) && defined(__PPC__) && (defined(_CALL_SYSV) || defined(_WIN32))
1347#define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
1348#elif defined(VA_COPY_AS_ARRAY)
1349#define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
1350#else /* va_list is a pointer */
1351#define VA_COPY(ap1, ap2) ((ap1) = (ap2))
1352#endif
1353#endif
1354
1355
1356/* print an error into string
1357 */
1358static int sh_error_string (struct _log_t * lmsg, va_list vl)
1359{
1360 size_t len;
1361 int required;
1362 unsigned long line;
1363 char sev[16] = "";
1364 char cla[16] = "";
1365 char tst[64] = "";
1366 char *p;
1367 va_list vl2;
1368
1369 st_format rep_ehead_tab[] = {
1370 { 'S', S_FMT_STRING, 0, 0, NULL}, /* severity */
1371 { 'T', S_FMT_STRING, 0, 0, NULL}, /* timestamp */
1372 { 'F', S_FMT_STRING, 0, 0, NULL}, /* file */
1373 { 'L', S_FMT_ULONG, 0, 0, NULL}, /* line */
1374 { 'C', S_FMT_STRING, 0, 0, NULL}, /* class */
1375 { 'E', S_FMT_LONG, 0, 0, NULL}, /* status */
1376 {'\0', S_FMT_ULONG, 0, 0, NULL},
1377 };
1378
1379 SL_ENTER(_("sh_error_string"));
1380
1381 if (ehead_format == NULL)
1382 {
1383 ehead_format = SH_ALLOC(64);
1384#ifdef SH_USE_XML
1385 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1386 (void) sl_strlcpy(ehead_format,
1387 _("<log sev=\"%S\" tstamp=\"%T\" "), 64);
1388 else
1389 (void) sl_strlcpy(ehead_format,
1390 _("<log sev=\"%S\" tstamp=\"%T\" p.f=\"%F\" p.l=\"%L\" p.s=\"%E\" "), 64);
1391#else
1392 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1393 (void) sl_strlcpy(ehead_format, _("%S %T "), 64);
1394 else
1395 (void) sl_strlcpy(ehead_format, _("%S %T (%F, %L, %E) "), 64);
1396#endif
1397 }
1398
1399 /* header of error message
1400 */
1401#ifdef SH_USE_XML
1402 if ( (lmsg->severity & SH_ERR_INET) != 0)
1403 (void) sl_strlcpy (sev, _("RCVT"), 11);
1404 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1405 (void) sl_strlcpy (sev, _("DEBG"), 11);
1406 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1407 (void) sl_strlcpy (sev, _("INFO"), 11);
1408 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1409 (void) sl_strlcpy (sev, _("NOTE"), 11);
1410 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1411 (void) sl_strlcpy (sev, _("WARN"), 11);
1412 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1413 (void) sl_strlcpy (sev, _("MARK"), 11);
1414 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1415 (void) sl_strlcpy (sev, _("ERRO"), 11);
1416 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1417 (void) sl_strlcpy (sev, _("CRIT"), 11);
1418 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1419 (void) sl_strlcpy (sev, _("ALRT"), 11);
1420 else {
1421 (void) sl_strlcpy (sev, _("????"), 11);
1422#else
1423#if defined(INET_SYSLOG)
1424 if ( (lmsg->severity & SH_ERR_INET) != 0)
1425 (void) sl_strlcpy (sev, _("<NET> : "), 11);
1426#else
1427 if ( (lmsg->severity & SH_ERR_INET) != 0)
1428 (void) sl_strlcpy (sev, _("<TCP> : "), 11);
1429#endif
1430 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1431 (void) sl_strlcpy (sev, _("DEBUG : "), 11);
1432 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1433 (void) sl_strlcpy (sev, _("INFO : "), 11);
1434 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1435 (void) sl_strlcpy (sev, _("NOTICE : "), 11);
1436 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1437 (void) sl_strlcpy (sev, _("WARN : "), 11);
1438 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1439 (void) sl_strlcpy (sev, _("MARK : "), 11);
1440 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1441 (void) sl_strlcpy (sev, _("ERROR : "), 11);
1442 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1443 (void) sl_strlcpy (sev, _("CRIT : "), 11);
1444 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1445 (void) sl_strlcpy (sev, _("ALERT : "), 11);
1446 else {
1447 (void) sl_strlcpy (sev, _("??? : "), 11);
1448#endif
1449 }
1450
1451 (void) sl_strlcpy (tst, sh_unix_time (0), 64);
1452 line = (unsigned long) lmsg->line;
1453 (void) sl_strlcpy (cla, _(class_cat[lmsg->class]), 11);
1454
1455 /*@i@*/rep_ehead_tab[0].data_str = sev;
1456 /*@i@*/rep_ehead_tab[1].data_str = tst;
1457 /*@i@*/rep_ehead_tab[2].data_str = lmsg->file;
1458 /*@i@*/rep_ehead_tab[3].data_ulong = line;
1459 /*@i@*/rep_ehead_tab[4].data_str = cla;
1460 /*@i@*/rep_ehead_tab[5].data_long = lmsg->status;
1461
1462 p = /*@i@*/sh_util_formatted(ehead_format, rep_ehead_tab);
1463
1464 /* --- copy the header to lmsg->msg ---
1465 */
1466 /*@i@*/lmsg->msg = SH_ALLOC(SH_BUFSIZE);
1467 lmsg->msg_len = SH_BUFSIZE;
1468
1469 if (p)
1470 {
1471 (void) sl_strlcpy (lmsg->msg, p, SH_BUFSIZE);
1472 SH_FREE(p);
1473 }
1474 else
1475 {
1476 lmsg->msg[0] = '\0';
1477 }
1478
1479
1480 /* --- copy message to lmsg->msg ---
1481 */
1482 if ( NULL == strchr(lmsg->format, '%') )
1483 {
1484 (void) sl_strlcat (lmsg->msg, lmsg->format, (size_t) lmsg->msg_len);
1485 }
1486 else
1487 {
1488 /* use VA_COPY */
1489 /*@i@*/VA_COPY(vl2, vl);
1490 len = sl_strlen(lmsg->msg);
1491 /*@i@*/required = sl_vsnprintf(&(lmsg->msg[len]),
[22]1492 (lmsg->msg_len - len), lmsg->format, vl);
[1]1493 if ( (required + len) > (lmsg->msg_len - 4) )
1494 {
1495 /*@i@*/p = SH_ALLOC(required + len + 4);
1496 (void) sl_strlcpy (p, lmsg->msg, required + len + 1);
1497 SH_FREE(lmsg->msg);
1498 lmsg->msg = p;
1499 lmsg->msg_len = required + len + 4;
1500 (void) sl_vsnprintf(&(lmsg->msg[len]),
1501 (required + len + 1), lmsg->format, vl2);
1502 }
1503 va_end(vl2);
1504 }
1505
1506#ifdef SH_USE_XML
1507 /* closing tag
1508 */
1509 if (lmsg->msg[sl_strlen(lmsg->msg)-1] != '>')
1510 (void) sl_strlcat (lmsg->msg, _(" />"), lmsg->msg_len);
1511#endif
1512
1513 SL_RETURN(0, _("sh_error_string"));
1514}
1515
1516
1517
1518
1519/* --- Initialize. ---
1520 */
1521static int sh_error_init ()
1522{
1523 register int j;
1524
1525 SL_ENTER(_("sh_error_init"));
1526
1527 errFlags.debug = 0;
1528 errFlags.HaveLog = GOOD;
1529 errFlags.sysloglevel = SH_ERR_NOT;
1530#if defined(SH_STEALTH)
1531 errFlags.loglevel = SH_ERR_NOT;
1532#else
1533 errFlags.loglevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1534 SH_ERR_FATAL);
1535#endif
1536 errFlags.externallevel = SH_ERR_NOT;
1537 errFlags.databaselevel = SH_ERR_NOT;
1538 errFlags.preludelevel = SH_ERR_NOT;
1539 errFlags.maillevel = SH_ERR_FATAL;
1540#if defined(SH_STEALTH)
1541 errFlags.printlevel = SH_ERR_NOT;
1542#else
1543 errFlags.printlevel = (SH_ERR_INFO | SH_ERR_NOTICE | SH_ERR_WARN |
1544 SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1545 SH_ERR_FATAL);
[5]1546 flag_err_info = SL_TRUE;
[1]1547#endif
1548 errFlags.exportlevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1549 SH_ERR_FATAL);
1550
1551 errFlags.log_class = 0xFFFF;
1552 errFlags.print_class = 0xFFFF;
1553 errFlags.mail_class = 0xFFFF;
1554 errFlags.export_class = 0xFFFF;
1555 errFlags.syslog_class = 0xFFFF;
1556 errFlags.external_class = 0xFFFF;
1557 errFlags.database_class = 0xFFFF;
1558 errFlags.prelude_class = 0xFFFF;
1559
1560
1561 for (j = 0; j < SH_ERR_T_END; ++j)
1562 ShDFLevel[j] = SH_ERR_SEVERE;
1563
1564 IsInitialized = GOOD;
1565 SL_RETURN (0, _("sh_error_init"));
1566}
Note: See TracBrowser for help on using the repository browser.