source: trunk/src/sh_error.c@ 157

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

Fix some more queer compile problems.

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