source: trunk/src/sh_error.c@ 323

Last change on this file since 323 was 283, checked in by katerina, 14 years ago

Patch for ticket #207 (server logs client reports to prelude).

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