source: trunk/src/sh_error.c@ 137

Last change on this file since 137 was 133, checked in by rainer, 17 years ago

Reentrant checksum/hash functions.

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