source: trunk/src/sh_error.c @ 481

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

Enhancements and fixes for tickets #374, #375, #376, #377, #378, and #379.

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