source: trunk/src/sh_error.c@ 132

Last change on this file since 132 was 132, checked in by rainer, 18 years ago

Make utility functions thread-safe.

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