source: trunk/src/sh_error.c@ 371

Last change on this file since 371 was 352, checked in by katerina, 13 years ago

Fix ticket #257 (error message may contain uninitialized string).

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