source: trunk/src/sh_error.c@ 142

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

Login watch runs in thread.

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