source: trunk/src/sh_error.c@ 63

Last change on this file since 63 was 34, checked in by rainer, 19 years ago

Code cleanup and minor fixes

File size: 37.2 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
[27]641#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]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
[27]845#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]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;
[27]864#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]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
[27]928 /* these are messages from remote sources
929 */
[1]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 ) &&
[27]943#if defined(SH_WITH_CLIENT) || defined(SH_WITH_CLIENT)
[1]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
[27]962 && (flag_inet == S_FALSE) /* still log messages from remote sources */
[1]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 ****************************************************/
[27]1123#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
[1]1124 /* Export by TCP.
1125 */
[27]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 || (flag_inet == S_TRUE) /* always log inet to export */
1133#endif
1134 /* sh.flag.isserver != GOOD && */
1135 /* (flag_inet == S_FALSE) */ /* don't log inet to export */
1136 )
[1]1137 {
1138 if (export_block == 0)
1139 {
1140 int retval;
[22]1141 size_t ex_len;
[1]1142
1143 /* will truncate to 65280 bytes
1144 */
1145 export_block = 1;
[34]1146 /* ex_len = 64 + sl_strlen(lmsg->msg) + 1; */
1147 ex_len = sl_strlen(lmsg->msg);
1148 if (sl_ok_adds(ex_len, 65))
1149 ex_len = 64 + ex_len + 1;
[22]1150 ex_msg = SH_ALLOC (ex_len);
1151
1152 sl_snprintf(ex_msg, ex_len, _("%d?%u?%s"),
1153 severity, class, lmsg->msg);
[1]1154 retval = sh_forward (ex_msg);
1155 SH_FREE(ex_msg);
1156 export_block = 0;
1157 if (retval == -2)
1158 {
1159 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1160 _("log server"));
1161 }
1162 }
1163 }
1164#endif
1165
1166
1167 /* Log to mail.
1168 */
1169#if defined(SH_WITH_MAIL)
1170 if ((errFlags.maillevel & severity ) != 0 &&
1171 (errFlags.mail_class & (1 << class)) != 0 &&
1172 (errFlags.maillevel & SH_ERR_NOT) == 0 &&
1173 class != AUD &&
1174 (flag_inet == S_FALSE) ) /* don't log inet to email */
1175 {
1176 if (mail_block == 0)
1177 {
1178 int retval;
1179
1180 /* will truncate to 998 bytes
1181 */
1182 mail_block = 1;
1183
1184 BREAKEXIT(sh_mail_msg);
1185 if ( (severity & SH_ERR_FATAL) == 0)
1186 retval = sh_mail_pushstack (lmsg->msg);
1187 else
1188 retval = sh_mail_msg (lmsg->msg);
1189
1190 mail_block = 0;
1191 if (retval == -2)
1192 {
1193 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1194 _("email"));
1195 }
1196 }
1197 }
1198#endif
1199
1200#ifdef HAVE_LIBPRELUDE
1201 if (((errFlags.preludelevel & severity ) != 0 &&
1202 (errFlags.prelude_class & (1 << class)) != 0 &&
1203 (errFlags.preludelevel & SH_ERR_NOT) == 0 &&
1204 (class != AUD))
1205#ifdef SH_WITH_SERVER
1206 || (flag_inet == S_TRUE)
1207#endif
1208 )
1209 {
1210 if (prelude_block == 0)
1211 {
1212 /* will truncate to 998 bytes
1213 */
1214 prelude_block = 1;
1215
1216 BREAKEXIT(sh_prelude_alert);
1217 /*
1218 * Reports first error after failure. Always tries.
1219 */
1220 (void) sh_prelude_alert (severity, (int) class, lmsg->msg,
1221 lmsg->status, msg_id);
1222
1223 prelude_block = 0;
1224 }
1225 }
1226#endif
1227
1228 /* Log to logfile
1229 */
1230
1231 if ( ( ( (errFlags.loglevel & severity) != 0 &&
1232 (errFlags.log_class & (1 << class)) != 0 &&
1233 (errFlags.loglevel & SH_ERR_NOT) == 0 )
1234#ifdef SH_WITH_SERVER
1235 || (flag_inet == S_TRUE)
1236#endif
1237 ) &&
1238 class != AUD &&
1239 (errFlags.HaveLog != BAD) && /* temporary switched off */
1240 (severity & SH_ERR_NOT) == 0 /* paranoia */
1241 )
1242 {
1243 if (log_block == 0)
1244 {
1245 /* no truncation
1246 */
1247 log_block = 1;
1248 BREAKEXIT(sh_log_file);
1249#ifdef SH_WITH_SERVER
1250 if (0 != sl_ret_euid())
1251 {
1252 /*
1253 * Reports first error after failure. Always tries.
1254 */
1255 if (local_inet_peer[0] == '\0')
1256 (void) sh_log_file (lmsg->msg, NULL);
1257 else
1258 (void) sh_log_file (lmsg->msg, local_inet_peer);
1259 }
1260#else
1261 (void) sh_log_file (lmsg->msg, NULL);
1262#endif
1263 /* sh_log_file (lmsg->msg); */
1264 log_block = 0;
1265 }
1266 }
1267
1268 }
1269
1270 /* Cleanup.
1271 */
1272 own_block = 1;
1273
1274 if (lmsg->msg)
1275 SH_FREE( lmsg->msg );
1276
1277 memset ( lmsg, (int) '\0', sizeof(struct _log_t) );
1278 MUNLOCK( (char *) lmsg, sizeof(struct _log_t) );
1279 SH_FREE( lmsg );
1280 own_block = 0;
1281
1282 /*@i@*/SL_RET0(_("sh_error_handle"));
1283/*@i@*/}
1284
1285
1286/* -------------------------
1287 *
1288 * private functions below
1289 *
1290 * -------------------------
1291 */
1292
1293
1294/* --- Get the format from the message catalog. ---
1295 */
1296/*@owned@*/ /*@null@*/inline
1297static char * get_format(unsigned long msg_id, /*@out@*/ int * priority,
1298 /*@out@*/unsigned int * class)
1299{
1300 int i = 0;
1301
1302 SL_ENTER(_("get_format"));
1303 while (1 == 1)
1304 {
1305 if ( msg_cat[i].format == NULL )
1306 break;
1307
1308 if ( (unsigned long) msg_cat[i].id == msg_id)
1309 {
1310 *priority = (int) msg_cat[i].priority;
1311 *class = (unsigned int) msg_cat[i].class;
1312 SL_RETURN (_(msg_cat[i].format), _("get_format"));
1313 }
1314 ++i;
1315 }
1316 *priority = SH_ERR_ERR;
1317 *class = ERR;
1318 SL_RETURN (NULL, _("get_format"));
1319}
1320
1321/*@null@*//*@only@*/static char * ehead_format = NULL;
1322
1323/* allocate space for user-defined message header
1324 */
[22]1325int sh_error_ehead (/*@null@*/const char * str_s)
[1]1326{
1327 size_t size;
[22]1328 const char * s;
[1]1329
1330 SL_ENTER(_("sh_error_ehead"));
1331
1332 if (str_s == NULL)
1333 {
1334 SL_RETURN (-1, _("sh_error_ehead"));
1335 }
1336
1337 /* ascii 34 ist t\"ttelchen
1338 */
1339 /*@i@*/ if (str_s[0] == 34) s = &str_s[1];
1340 else s = str_s;
1341
1342 size = /*@i@*/strlen(s);
[22]1343 if (/*@i@*/s[size-1] == (char) 34) --size; /* truncate */
[1]1344
1345 if (ehead_format != NULL)
1346 SH_FREE(ehead_format);
1347
1348 /*@i@*/ehead_format = SH_ALLOC(size+1);
1349 /*@i@*/ (void) sl_strlcpy(ehead_format, s, size+1);
1350
1351 SL_RETURN( 0, _("sh_error_ehead"));
1352}
1353
1354#if !defined(VA_COPY)
1355#if defined(__GNUC__) && defined(__PPC__) && (defined(_CALL_SYSV) || defined(_WIN32))
1356#define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
1357#elif defined(VA_COPY_AS_ARRAY)
1358#define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
1359#else /* va_list is a pointer */
1360#define VA_COPY(ap1, ap2) ((ap1) = (ap2))
1361#endif
1362#endif
1363
1364
1365/* print an error into string
1366 */
1367static int sh_error_string (struct _log_t * lmsg, va_list vl)
1368{
1369 size_t len;
1370 int required;
1371 unsigned long line;
1372 char sev[16] = "";
1373 char cla[16] = "";
1374 char tst[64] = "";
1375 char *p;
1376 va_list vl2;
1377
1378 st_format rep_ehead_tab[] = {
1379 { 'S', S_FMT_STRING, 0, 0, NULL}, /* severity */
1380 { 'T', S_FMT_STRING, 0, 0, NULL}, /* timestamp */
1381 { 'F', S_FMT_STRING, 0, 0, NULL}, /* file */
1382 { 'L', S_FMT_ULONG, 0, 0, NULL}, /* line */
1383 { 'C', S_FMT_STRING, 0, 0, NULL}, /* class */
1384 { 'E', S_FMT_LONG, 0, 0, NULL}, /* status */
1385 {'\0', S_FMT_ULONG, 0, 0, NULL},
1386 };
1387
1388 SL_ENTER(_("sh_error_string"));
1389
1390 if (ehead_format == NULL)
1391 {
1392 ehead_format = SH_ALLOC(64);
1393#ifdef SH_USE_XML
1394 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1395 (void) sl_strlcpy(ehead_format,
1396 _("<log sev=\"%S\" tstamp=\"%T\" "), 64);
1397 else
1398 (void) sl_strlcpy(ehead_format,
1399 _("<log sev=\"%S\" tstamp=\"%T\" p.f=\"%F\" p.l=\"%L\" p.s=\"%E\" "), 64);
1400#else
1401 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1402 (void) sl_strlcpy(ehead_format, _("%S %T "), 64);
1403 else
1404 (void) sl_strlcpy(ehead_format, _("%S %T (%F, %L, %E) "), 64);
1405#endif
1406 }
1407
1408 /* header of error message
1409 */
1410#ifdef SH_USE_XML
1411 if ( (lmsg->severity & SH_ERR_INET) != 0)
1412 (void) sl_strlcpy (sev, _("RCVT"), 11);
1413 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1414 (void) sl_strlcpy (sev, _("DEBG"), 11);
1415 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1416 (void) sl_strlcpy (sev, _("INFO"), 11);
1417 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1418 (void) sl_strlcpy (sev, _("NOTE"), 11);
1419 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1420 (void) sl_strlcpy (sev, _("WARN"), 11);
1421 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1422 (void) sl_strlcpy (sev, _("MARK"), 11);
1423 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1424 (void) sl_strlcpy (sev, _("ERRO"), 11);
1425 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1426 (void) sl_strlcpy (sev, _("CRIT"), 11);
1427 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1428 (void) sl_strlcpy (sev, _("ALRT"), 11);
1429 else {
1430 (void) sl_strlcpy (sev, _("????"), 11);
1431#else
1432#if defined(INET_SYSLOG)
1433 if ( (lmsg->severity & SH_ERR_INET) != 0)
1434 (void) sl_strlcpy (sev, _("<NET> : "), 11);
1435#else
1436 if ( (lmsg->severity & SH_ERR_INET) != 0)
1437 (void) sl_strlcpy (sev, _("<TCP> : "), 11);
1438#endif
1439 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1440 (void) sl_strlcpy (sev, _("DEBUG : "), 11);
1441 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1442 (void) sl_strlcpy (sev, _("INFO : "), 11);
1443 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1444 (void) sl_strlcpy (sev, _("NOTICE : "), 11);
1445 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1446 (void) sl_strlcpy (sev, _("WARN : "), 11);
1447 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1448 (void) sl_strlcpy (sev, _("MARK : "), 11);
1449 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1450 (void) sl_strlcpy (sev, _("ERROR : "), 11);
1451 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1452 (void) sl_strlcpy (sev, _("CRIT : "), 11);
1453 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1454 (void) sl_strlcpy (sev, _("ALERT : "), 11);
1455 else {
1456 (void) sl_strlcpy (sev, _("??? : "), 11);
1457#endif
1458 }
1459
1460 (void) sl_strlcpy (tst, sh_unix_time (0), 64);
1461 line = (unsigned long) lmsg->line;
1462 (void) sl_strlcpy (cla, _(class_cat[lmsg->class]), 11);
1463
1464 /*@i@*/rep_ehead_tab[0].data_str = sev;
1465 /*@i@*/rep_ehead_tab[1].data_str = tst;
1466 /*@i@*/rep_ehead_tab[2].data_str = lmsg->file;
1467 /*@i@*/rep_ehead_tab[3].data_ulong = line;
1468 /*@i@*/rep_ehead_tab[4].data_str = cla;
1469 /*@i@*/rep_ehead_tab[5].data_long = lmsg->status;
1470
1471 p = /*@i@*/sh_util_formatted(ehead_format, rep_ehead_tab);
1472
1473 /* --- copy the header to lmsg->msg ---
1474 */
1475 /*@i@*/lmsg->msg = SH_ALLOC(SH_BUFSIZE);
1476 lmsg->msg_len = SH_BUFSIZE;
1477
1478 if (p)
1479 {
1480 (void) sl_strlcpy (lmsg->msg, p, SH_BUFSIZE);
1481 SH_FREE(p);
1482 }
1483 else
1484 {
1485 lmsg->msg[0] = '\0';
1486 }
1487
1488
1489 /* --- copy message to lmsg->msg ---
1490 */
1491 if ( NULL == strchr(lmsg->format, '%') )
1492 {
1493 (void) sl_strlcat (lmsg->msg, lmsg->format, (size_t) lmsg->msg_len);
1494 }
1495 else
1496 {
1497 /* use VA_COPY */
1498 /*@i@*/VA_COPY(vl2, vl);
1499 len = sl_strlen(lmsg->msg);
1500 /*@i@*/required = sl_vsnprintf(&(lmsg->msg[len]),
[22]1501 (lmsg->msg_len - len), lmsg->format, vl);
[34]1502 if ((required >= 0) &&
1503 sl_ok_adds(required, len) &&
1504 sl_ok_adds((required+len), 4) &&
1505 ((required + len) > (lmsg->msg_len - 4)) )
[1]1506 {
1507 /*@i@*/p = SH_ALLOC(required + len + 4);
1508 (void) sl_strlcpy (p, lmsg->msg, required + len + 1);
1509 SH_FREE(lmsg->msg);
1510 lmsg->msg = p;
1511 lmsg->msg_len = required + len + 4;
1512 (void) sl_vsnprintf(&(lmsg->msg[len]),
1513 (required + len + 1), lmsg->format, vl2);
1514 }
1515 va_end(vl2);
1516 }
1517
1518#ifdef SH_USE_XML
1519 /* closing tag
1520 */
1521 if (lmsg->msg[sl_strlen(lmsg->msg)-1] != '>')
1522 (void) sl_strlcat (lmsg->msg, _(" />"), lmsg->msg_len);
1523#endif
1524
1525 SL_RETURN(0, _("sh_error_string"));
1526}
1527
1528
1529
1530
1531/* --- Initialize. ---
1532 */
1533static int sh_error_init ()
1534{
1535 register int j;
1536
1537 SL_ENTER(_("sh_error_init"));
1538
1539 errFlags.debug = 0;
1540 errFlags.HaveLog = GOOD;
1541 errFlags.sysloglevel = SH_ERR_NOT;
1542#if defined(SH_STEALTH)
1543 errFlags.loglevel = SH_ERR_NOT;
1544#else
1545 errFlags.loglevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1546 SH_ERR_FATAL);
1547#endif
1548 errFlags.externallevel = SH_ERR_NOT;
1549 errFlags.databaselevel = SH_ERR_NOT;
1550 errFlags.preludelevel = SH_ERR_NOT;
1551 errFlags.maillevel = SH_ERR_FATAL;
1552#if defined(SH_STEALTH)
1553 errFlags.printlevel = SH_ERR_NOT;
1554#else
1555 errFlags.printlevel = (SH_ERR_INFO | SH_ERR_NOTICE | SH_ERR_WARN |
1556 SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1557 SH_ERR_FATAL);
[5]1558 flag_err_info = SL_TRUE;
[1]1559#endif
1560 errFlags.exportlevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1561 SH_ERR_FATAL);
1562
1563 errFlags.log_class = 0xFFFF;
1564 errFlags.print_class = 0xFFFF;
1565 errFlags.mail_class = 0xFFFF;
1566 errFlags.export_class = 0xFFFF;
1567 errFlags.syslog_class = 0xFFFF;
1568 errFlags.external_class = 0xFFFF;
1569 errFlags.database_class = 0xFFFF;
1570 errFlags.prelude_class = 0xFFFF;
1571
1572
1573 for (j = 0; j < SH_ERR_T_END; ++j)
1574 ShDFLevel[j] = SH_ERR_SEVERE;
1575
1576 IsInitialized = GOOD;
1577 SL_RETURN (0, _("sh_error_init"));
1578}
Note: See TracBrowser for help on using the repository browser.