source: trunk/src/sh_error.c @ 133

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

Reentrant checksum/hash functions.

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