source: trunk/src/sh_error.c@ 573

Last change on this file since 573 was 541, checked in by katerina, 6 years ago

Fix for ticket #433 (coding standardisation).

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