source: trunk/src/sh_error.c@ 131

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

Use thread-safe libc functions.

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