source: trunk/src/sh_error.c @ 132

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

Make utility functions thread-safe.

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