source: trunk/src/sh_error.c@ 271

Last change on this file since 271 was 214, checked in by katerina, 16 years ago

Rewrite mail subsystem for more flexibility (closes ticket #141).

File size: 38.5 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_nmail.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@*/const 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, TIGER_NOLIM);
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(void)
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(void)
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(void)
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 const 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(void)
800{
801#if defined(HAVE_LIBPRELUDE)
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(void)
816{
817#if defined(HAVE_LIBPRELUDE)
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, const 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;
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 else
978 {
979 flag_inet = S_FALSE;
980 }
981
982 /* --- Messages not wanted for logging. ---
983 */
984 if ( ( (errFlags.printlevel & severity ) == 0 ||
985 (errFlags.print_class & (1 << class)) == 0 ) &&
986 ( (errFlags.loglevel & severity ) == 0 ||
987 (errFlags.log_class & (1 << class)) == 0 ) &&
988 ( (errFlags.sysloglevel & severity ) == 0 ||
989 (errFlags.syslog_class & (1 << class)) == 0 ) &&
990#if defined(SH_WITH_CLIENT) || defined(SH_WITH_CLIENT)
991 ( (errFlags.exportlevel & severity ) == 0 ||
992 (errFlags.export_class & (1 << class)) == 0 ) &&
993#endif
994#ifdef WITH_EXTERNAL
995 ( (errFlags.externallevel & severity ) == 0 ||
996 (errFlags.external_class & (1 << class)) == 0 ) &&
997#endif
998#ifdef HAVE_LIBPRELUDE
999 ( (errFlags.preludelevel & severity ) == 0 ||
1000 (errFlags.prelude_class & (1 << class)) == 0 ) &&
1001#endif
1002#ifdef WITH_DATABASE
1003 ( (errFlags.databaselevel & severity ) == 0 ||
1004 (errFlags.database_class & (1 << class)) == 0 ) &&
1005#endif
1006 ( (errFlags.maillevel & severity ) == 0 ||
1007 (errFlags.mail_class & (1 << class)) == 0 )
1008#ifdef SH_WITH_SERVER
1009 && (flag_inet == S_FALSE) /* still log messages from remote sources */
1010#endif
1011 )
1012 {
1013 goto exit_here;
1014 }
1015
1016 if ((severity & SH_ERR_NOT) != 0)
1017 {
1018 goto exit_here;
1019 }
1020
1021
1022 /* Allocate space for the message.
1023 */
1024 own_block = 1;
1025 lmsg = (struct _log_t *) SH_ALLOC(sizeof(struct _log_t));
1026 MLOCK( (char *) lmsg, sizeof(struct _log_t));
1027 /*@i@*/lmsg->msg = NULL;
1028
1029 /*@i@*/(void) sl_strlcpy(lmsg->format, fmt, SH_PATHBUF);
1030 (void) sl_strlcpy(lmsg->file, file, SH_PATHBUF);
1031 lmsg->severity = severity;
1032 lmsg->class = (int) class;
1033 lmsg->line = line;
1034 lmsg->status = status;
1035
1036 /* Format the log message with timestamp etc.
1037 * Allocate lmsg->msg
1038 */
1039 va_start (vl, msg_id);
1040 (void) sh_error_string (lmsg, vl);
1041 va_end (vl);
1042 own_block = 0;
1043
1044
1045 /* Log to stderr.
1046 */
1047 if ( ((errFlags.printlevel & severity) != 0 &&
1048 (errFlags.print_class & (1 << class)) != 0 &&
1049 (errFlags.printlevel & SH_ERR_NOT) == 0)
1050#ifdef SH_WITH_SERVER
1051 || (flag_inet == S_TRUE)
1052#endif
1053 )
1054 {
1055 if (print_block == 0 && (errFlags.printlevel & SH_ERR_NOT) == 0)
1056 {
1057 /* no truncation
1058 */
1059 print_block = 1;
1060 TPT(( 0, FIL__, __LINE__, lmsg->msg));
1061 /*
1062 * Reports first error after failure. Always tries.
1063 */
1064 (void) sh_log_console (lmsg->msg);
1065 print_block = 0;
1066 }
1067 }
1068
1069
1070 /* Full logging enabled.
1071 */
1072 if (OnlyStderr == S_FALSE) /* full error logging enabled */
1073 {
1074
1075 /* Log to syslog.
1076 */
1077 if ( (errFlags.sysloglevel & severity) != 0 &&
1078 (errFlags.syslog_class & (1 << class)) != 0 &&
1079#ifndef INET_SYSLOG
1080 (flag_inet != S_TRUE) && /* !inet->syslog */
1081#endif
1082 (errFlags.sysloglevel & SH_ERR_NOT) == 0 )
1083 {
1084 /* will truncate to 1023 bytes
1085 */
1086 if (syslog_block == 0)
1087 {
1088 syslog_block = 1;
1089 /*
1090 * Ignores errors. Always tries.
1091 */
1092 (void) sh_log_syslog (lmsg->severity, lmsg->msg);
1093 syslog_block = 0;
1094 }
1095 }
1096
1097#if defined(WITH_EXTERNAL)
1098 /*
1099 * -- external facility
1100 */
1101 if ((errFlags.externallevel & severity) != 0 &&
1102 (errFlags.external_class & (1 << class)) != 0 &&
1103 (errFlags.externallevel & SH_ERR_NOT) == 0 &&
1104 class != AUD)
1105 {
1106 if (external_block == 0)
1107 {
1108 /* no truncation
1109 */
1110 external_block = 1;
1111 /*
1112 * Reports first error after failure. Always tries.
1113 */
1114 (void) sh_ext_execute ('l', 'o', 'g', lmsg->msg, 0);
1115 external_block = 0;
1116 }
1117 }
1118#endif
1119
1120#if defined(WITH_DATABASE)
1121 /*
1122 * -- database facility
1123 */
1124 if ((errFlags.databaselevel & severity) != 0 &&
1125 (errFlags.database_class & (1 << class)) != 0 &&
1126 (errFlags.databaselevel & SH_ERR_NOT) == 0 &&
1127 class != AUD)
1128 {
1129 if (database_block == 0 && enableUnsafe == S_TRUE)
1130 {
1131 /* truncates; query_max is 16k
1132 */
1133 database_block = 1;
1134#ifndef SH_STANDALONE
1135 if (msg_id == MSG_TCP_MSG
1136#ifdef INET_SYSLOG
1137 || msg_id == MSG_INET_SYSLOG
1138#endif
1139 )
1140 {
1141 /* do not escape twice
1142 */
1143 /*
1144 * Reports failure every 60 min. Always tries.
1145 */
1146 (void) sh_database_insert (lmsg->msg);
1147 }
1148 else
1149#endif
1150 {
1151 escape_msg = sh_tools_safe_name(lmsg->msg, 0);
1152 /*
1153 * Reports failure every 60 min. Always tries.
1154 */
1155 (void) sh_database_insert (escape_msg);
1156 SH_FREE(escape_msg);
1157 }
1158 database_block = 0;
1159 }
1160 }
1161#endif
1162
1163 /****************************************************
1164 * Optionally include client code for TCP forwarding
1165 * to log server
1166 ****************************************************/
1167#if defined(SH_WITH_CLIENT) || defined(SH_WITH_SERVER)
1168 /* Export by TCP.
1169 */
1170
1171 if ( ((errFlags.exportlevel & severity ) != 0 &&
1172 (errFlags.export_class & (1 << class)) != 0 &&
1173 (errFlags.exportlevel & SH_ERR_NOT) == 0 &&
1174 class != AUD )
1175#ifdef SH_WITH_SERVER
1176 /* always log inet to export */
1177 || (flag_inet == S_TRUE && sh.srvexport.name[0] != '\0')
1178#endif
1179 /* sh.flag.isserver != GOOD && */
1180 /* (flag_inet == S_FALSE) */ /* don't log inet to export */
1181 )
1182 {
1183 if (export_block == 0)
1184 {
1185 int retval;
1186 size_t ex_len;
1187
1188 /* will truncate to 65280 bytes
1189 */
1190 export_block = 1;
1191 /* ex_len = 64 + sl_strlen(lmsg->msg) + 1; */
1192 ex_len = sl_strlen(lmsg->msg);
1193 if (sl_ok_adds(ex_len, 65))
1194 ex_len = 64 + ex_len + 1;
1195 ex_msg = SH_ALLOC (ex_len);
1196
1197 sl_snprintf(ex_msg, ex_len, _("%d?%u?%s"),
1198 severity, class, lmsg->msg);
1199 retval = sh_forward (ex_msg);
1200 SH_FREE(ex_msg);
1201 export_block = 0;
1202 if (retval == -2)
1203 {
1204 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1205 _("log server"));
1206 }
1207 }
1208 }
1209#endif
1210
1211
1212 /* Log to mail.
1213 */
1214#if defined(SH_WITH_MAIL)
1215 if ((errFlags.maillevel & severity ) != 0 &&
1216 (errFlags.mail_class & (1 << class)) != 0 &&
1217 (errFlags.maillevel & SH_ERR_NOT) == 0 &&
1218 class != AUD &&
1219 (flag_inet == S_FALSE) ) /* don't log inet to email */
1220 {
1221 if (mail_block == 0)
1222 {
1223 int retval;
1224
1225 /* will truncate to 998 bytes
1226 */
1227 mail_block = 1;
1228
1229 BREAKEXIT(sh_nmail_msg);
1230 if ( (severity & SH_ERR_FATAL) == 0)
1231 retval = sh_nmail_pushstack (severity, lmsg->msg, NULL);
1232 else
1233 retval = sh_nmail_msg (severity, lmsg->msg, NULL);
1234
1235 mail_block = 0;
1236 if (retval == -2)
1237 {
1238 sh_error_handle ((-1), FIL__, __LINE__, 0, MSG_QUEUE_FULL,
1239 _("email"));
1240 }
1241 }
1242 }
1243#endif
1244
1245#ifdef HAVE_LIBPRELUDE
1246 if (((errFlags.preludelevel & severity ) != 0 &&
1247 (errFlags.prelude_class & (1 << class)) != 0 &&
1248 (errFlags.preludelevel & SH_ERR_NOT) == 0 &&
1249 (class != AUD))
1250#ifdef SH_WITH_SERVER
1251 || (flag_inet == S_TRUE)
1252#endif
1253 )
1254 {
1255 if (prelude_block == 0 && enableUnsafe == S_TRUE)
1256 {
1257 /* will truncate to 998 bytes
1258 */
1259 prelude_block = 1;
1260
1261 BREAKEXIT(sh_prelude_alert);
1262 /*
1263 * Reports first error after failure. Always tries.
1264 */
1265 (void) sh_prelude_alert (severity, (int) class, lmsg->msg,
1266 lmsg->status, msg_id);
1267
1268 prelude_block = 0;
1269 }
1270 }
1271#endif
1272
1273 /* Log to logfile
1274 */
1275
1276 if ( ( ( (errFlags.loglevel & severity) != 0 &&
1277 (errFlags.log_class & (1 << class)) != 0 &&
1278 (errFlags.loglevel & SH_ERR_NOT) == 0 )
1279#ifdef SH_WITH_SERVER
1280 || (flag_inet == S_TRUE)
1281#endif
1282 ) &&
1283 class != AUD &&
1284 (errFlags.HaveLog != BAD) && /* temporary switched off */
1285 (severity & SH_ERR_NOT) == 0 /* paranoia */
1286 )
1287 {
1288 if (log_block == 0)
1289 {
1290 /* no truncation
1291 */
1292 log_block = 1;
1293 BREAKEXIT(sh_log_file);
1294#ifdef SH_WITH_SERVER
1295 if (0 != sl_ret_euid())
1296 {
1297 /*
1298 * Reports first error after failure. Always tries.
1299 */
1300 if (local_inet_peer[0] == '\0')
1301 (void) sh_log_file (lmsg->msg, NULL);
1302 else
1303 (void) sh_log_file (lmsg->msg, local_inet_peer);
1304 }
1305#else
1306 (void) sh_log_file (lmsg->msg, NULL);
1307#endif
1308 /* sh_log_file (lmsg->msg); */
1309 log_block = 0;
1310 }
1311 }
1312
1313 }
1314
1315 /* Cleanup.
1316 */
1317 own_block = 1;
1318
1319 if (lmsg->msg)
1320 SH_FREE( lmsg->msg );
1321
1322 memset ( lmsg, (int) '\0', sizeof(struct _log_t) );
1323 MUNLOCK( (char *) lmsg, sizeof(struct _log_t) );
1324 SH_FREE( lmsg );
1325 own_block = 0;
1326
1327 exit_here:
1328 ; /* label at end of compound statement */
1329 SH_MUTEX_RECURSIVE_UNLOCK(mutex_err_handle);
1330
1331 /*@i@*/SL_RET0(_("sh_error_handle"));
1332/*@i@*/}
1333
1334
1335/* -------------------------
1336 *
1337 * private functions below
1338 *
1339 * -------------------------
1340 */
1341
1342
1343/* --- Get the format from the message catalog. ---
1344 */
1345/*@owned@*/ /*@null@*/inline
1346static char * get_format(unsigned long msg_id, /*@out@*/ int * priority,
1347 /*@out@*/unsigned int * class)
1348{
1349 int i = 0;
1350
1351 SL_ENTER(_("get_format"));
1352 while (1 == 1)
1353 {
1354 if ( msg_cat[i].format == NULL )
1355 break;
1356
1357 if ( (unsigned long) msg_cat[i].id == msg_id)
1358 {
1359 *priority = (int) msg_cat[i].priority;
1360 *class = (unsigned int) msg_cat[i].class;
1361 SL_RETURN (((char *) _(msg_cat[i].format)), _("get_format"));
1362 }
1363 ++i;
1364 }
1365 *priority = SH_ERR_ERR;
1366 *class = ERR;
1367 SL_RETURN (NULL, _("get_format"));
1368}
1369
1370/*@null@*//*@only@*/static char * ehead_format = NULL;
1371
1372/* allocate space for user-defined message header
1373 */
1374int sh_error_ehead (/*@null@*/const char * str_s)
1375{
1376 size_t size;
1377 const char * s;
1378
1379 SL_ENTER(_("sh_error_ehead"));
1380
1381 if (str_s == NULL)
1382 {
1383 SL_RETURN (-1, _("sh_error_ehead"));
1384 }
1385
1386 /* ascii 34 ist t\"ttelchen
1387 */
1388 /*@i@*/ if (str_s[0] == 34) s = &str_s[1];
1389 else s = str_s;
1390
1391 size = /*@i@*/strlen(s);
1392 if (/*@i@*/s[size-1] == (char) 34) --size; /* truncate */
1393
1394 if (ehead_format != NULL)
1395 SH_FREE(ehead_format);
1396
1397 /*@i@*/ehead_format = SH_ALLOC(size+1);
1398 /*@i@*/ (void) sl_strlcpy(ehead_format, s, size+1);
1399
1400 SL_RETURN( 0, _("sh_error_ehead"));
1401}
1402
1403#if !defined(VA_COPY)
1404#if defined(__GNUC__) && defined(__PPC__) && (defined(_CALL_SYSV) || defined(_WIN32))
1405#define VA_COPY(ap1, ap2) (*(ap1) = *(ap2))
1406#elif defined(VA_COPY_AS_ARRAY)
1407#define VA_COPY(ap1, ap2) memmove ((ap1), (ap2), sizeof (va_list))
1408#else /* va_list is a pointer */
1409#define VA_COPY(ap1, ap2) ((ap1) = (ap2))
1410#endif
1411#endif
1412
1413
1414/* print an error into string
1415 */
1416static int sh_error_string (struct _log_t * lmsg, va_list vl)
1417{
1418 size_t len;
1419 int required;
1420 unsigned long line;
1421 char sev[16] = "";
1422 char cla[16] = "";
1423 char tst[64] = "";
1424 char *p;
1425 va_list vl2;
1426
1427 st_format rep_ehead_tab[] = {
1428 { 'S', S_FMT_STRING, 0, 0, NULL}, /* severity */
1429 { 'T', S_FMT_STRING, 0, 0, NULL}, /* timestamp */
1430 { 'F', S_FMT_STRING, 0, 0, NULL}, /* file */
1431 { 'L', S_FMT_ULONG, 0, 0, NULL}, /* line */
1432 { 'C', S_FMT_STRING, 0, 0, NULL}, /* class */
1433 { 'E', S_FMT_LONG, 0, 0, NULL}, /* status */
1434 {'\0', S_FMT_ULONG, 0, 0, NULL},
1435 };
1436
1437 SL_ENTER(_("sh_error_string"));
1438
1439 if (ehead_format == NULL)
1440 {
1441 ehead_format = SH_ALLOC(64);
1442#ifdef SH_USE_XML
1443 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1444 (void) sl_strlcpy(ehead_format,
1445 _("<log sev=\"%S\" tstamp=\"%T\" "), 64);
1446 else
1447 (void) sl_strlcpy(ehead_format,
1448 _("<log sev=\"%S\" tstamp=\"%T\" p.f=\"%F\" p.l=\"%L\" p.s=\"%E\" "), 64);
1449#else
1450 if ((errFlags.printlevel & SH_ERR_ALL) == 0)
1451 (void) sl_strlcpy(ehead_format, _("%S %T "), 64);
1452 else
1453 (void) sl_strlcpy(ehead_format, _("%S %T (%F, %L, %E) "), 64);
1454#endif
1455 }
1456
1457 /* header of error message
1458 */
1459#ifdef SH_USE_XML
1460 if ( (lmsg->severity & SH_ERR_INET) != 0)
1461 (void) sl_strlcpy (sev, _("RCVT"), 11);
1462 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1463 (void) sl_strlcpy (sev, _("DEBG"), 11);
1464 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1465 (void) sl_strlcpy (sev, _("INFO"), 11);
1466 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1467 (void) sl_strlcpy (sev, _("NOTE"), 11);
1468 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1469 (void) sl_strlcpy (sev, _("WARN"), 11);
1470 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1471 (void) sl_strlcpy (sev, _("MARK"), 11);
1472 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1473 (void) sl_strlcpy (sev, _("ERRO"), 11);
1474 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1475 (void) sl_strlcpy (sev, _("CRIT"), 11);
1476 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1477 (void) sl_strlcpy (sev, _("ALRT"), 11);
1478 else {
1479 (void) sl_strlcpy (sev, _("????"), 11);
1480#else
1481#if defined(INET_SYSLOG)
1482 if ( (lmsg->severity & SH_ERR_INET) != 0)
1483 (void) sl_strlcpy (sev, _("<NET> : "), 11);
1484#else
1485 if ( (lmsg->severity & SH_ERR_INET) != 0)
1486 (void) sl_strlcpy (sev, _("<TCP> : "), 11);
1487#endif
1488 else if ( (lmsg->severity & SH_ERR_ALL) != 0)
1489 (void) sl_strlcpy (sev, _("DEBUG : "), 11);
1490 else if ( (lmsg->severity & SH_ERR_INFO) != 0)
1491 (void) sl_strlcpy (sev, _("INFO : "), 11);
1492 else if ( (lmsg->severity & SH_ERR_NOTICE) != 0)
1493 (void) sl_strlcpy (sev, _("NOTICE : "), 11);
1494 else if ( (lmsg->severity & SH_ERR_WARN) != 0)
1495 (void) sl_strlcpy (sev, _("WARN : "), 11);
1496 else if ( (lmsg->severity & SH_ERR_STAMP) != 0)
1497 (void) sl_strlcpy (sev, _("MARK : "), 11);
1498 else if ( (lmsg->severity & SH_ERR_ERR) != 0)
1499 (void) sl_strlcpy (sev, _("ERROR : "), 11);
1500 else if ( (lmsg->severity & SH_ERR_SEVERE) != 0)
1501 (void) sl_strlcpy (sev, _("CRIT : "), 11);
1502 else if ( (lmsg->severity & SH_ERR_FATAL) != 0)
1503 (void) sl_strlcpy (sev, _("ALERT : "), 11);
1504 else {
1505 (void) sl_strlcpy (sev, _("??? : "), 11);
1506#endif
1507 }
1508
1509 (void) sh_unix_time (0, tst, 64);
1510 line = (unsigned long) lmsg->line;
1511 (void) sl_strlcpy (cla, _(class_cat[lmsg->class]), 11);
1512
1513 /*@i@*/rep_ehead_tab[0].data_str = sev;
1514 /*@i@*/rep_ehead_tab[1].data_str = tst;
1515 /*@i@*/rep_ehead_tab[2].data_str = lmsg->file;
1516 /*@i@*/rep_ehead_tab[3].data_ulong = line;
1517 /*@i@*/rep_ehead_tab[4].data_str = cla;
1518 /*@i@*/rep_ehead_tab[5].data_long = lmsg->status;
1519
1520 p = /*@i@*/sh_util_formatted(ehead_format, rep_ehead_tab);
1521
1522 /* --- copy the header to lmsg->msg ---
1523 */
1524 /*@i@*/lmsg->msg = SH_ALLOC(SH_BUFSIZE);
1525 lmsg->msg_len = SH_BUFSIZE;
1526
1527 if (p)
1528 {
1529 (void) sl_strlcpy (lmsg->msg, p, SH_BUFSIZE);
1530 SH_FREE(p);
1531 }
1532 else
1533 {
1534 lmsg->msg[0] = '\0';
1535 }
1536
1537
1538 /* --- copy message to lmsg->msg ---
1539 */
1540 if ( NULL == strchr(lmsg->format, '%') )
1541 {
1542 (void) sl_strlcat (lmsg->msg, lmsg->format, (size_t) lmsg->msg_len);
1543 }
1544 else
1545 {
1546 /* use VA_COPY */
1547 /*@i@*/VA_COPY(vl2, vl);
1548 len = sl_strlen(lmsg->msg);
1549 /*@i@*/required = sl_vsnprintf(&(lmsg->msg[len]),
1550 (lmsg->msg_len - len), lmsg->format, vl);
1551
1552 if ((required >= 0) &&
1553 sl_ok_adds(required, len) &&
1554 sl_ok_adds((required+len), 4) &&
1555 ((required + len) > (lmsg->msg_len - 4)) )
1556 {
1557 /*@i@*/p = SH_ALLOC(required + len + 4);
1558 (void) sl_strlcpy (p, lmsg->msg, required + len + 1);
1559 SH_FREE(lmsg->msg);
1560 lmsg->msg = p;
1561 lmsg->msg_len = required + len + 4;
1562 (void) sl_vsnprintf(&(lmsg->msg[len]),
1563 (required + 1), lmsg->format, vl2);
1564 }
1565 va_end(vl2);
1566 }
1567
1568#ifdef SH_USE_XML
1569 /* closing tag
1570 */
1571 if (lmsg->msg[sl_strlen(lmsg->msg)-1] != '>')
1572 (void) sl_strlcat (lmsg->msg, _(" />"), lmsg->msg_len);
1573#endif
1574
1575 SL_RETURN(0, _("sh_error_string"));
1576}
1577
1578
1579
1580
1581/* --- Initialize. ---
1582 */
1583static int sh_error_init ()
1584{
1585 register int j;
1586
1587 SL_ENTER(_("sh_error_init"));
1588
1589 errFlags.debug = 0;
1590 errFlags.HaveLog = GOOD;
1591 errFlags.sysloglevel = SH_ERR_NOT;
1592#if defined(SH_STEALTH)
1593 errFlags.loglevel = SH_ERR_NOT;
1594#else
1595 errFlags.loglevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1596 SH_ERR_FATAL);
1597#endif
1598 errFlags.externallevel = SH_ERR_NOT;
1599 errFlags.databaselevel = SH_ERR_NOT;
1600 errFlags.preludelevel = SH_ERR_NOT;
1601 errFlags.maillevel = SH_ERR_FATAL;
1602#if defined(SH_STEALTH)
1603 errFlags.printlevel = SH_ERR_NOT;
1604#else
1605 errFlags.printlevel = (SH_ERR_INFO | SH_ERR_NOTICE | SH_ERR_WARN |
1606 SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1607 SH_ERR_FATAL);
1608 flag_err_info = SL_TRUE;
1609#endif
1610
1611#if defined(SH_WITH_SERVER)
1612 errFlags.exportlevel = SH_ERR_NOT;
1613#else
1614 errFlags.exportlevel = (SH_ERR_STAMP | SH_ERR_ERR | SH_ERR_SEVERE |
1615 SH_ERR_FATAL);
1616#endif
1617
1618 errFlags.log_class = 0xFFFF;
1619 errFlags.print_class = 0xFFFF;
1620 errFlags.mail_class = 0xFFFF;
1621 errFlags.export_class = 0xFFFF;
1622 errFlags.syslog_class = 0xFFFF;
1623 errFlags.external_class = 0xFFFF;
1624 errFlags.database_class = 0xFFFF;
1625 errFlags.prelude_class = 0xFFFF;
1626
1627
1628 for (j = 0; j < SH_ERR_T_END; ++j)
1629 ShDFLevel[j] = SH_ERR_SEVERE;
1630
1631 IsInitialized = GOOD;
1632 SL_RETURN (0, _("sh_error_init"));
1633}
Note: See TracBrowser for help on using the repository browser.