summaryrefslogtreecommitdiff
path: root/src/logmsg.c
blob: 3f079f413ebf518b13b49e72ca28da1af3c62c98 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
#include <unistd.h>
#include <stdarg.h>
#include <errno.h>
#include "buffer.h"
#include "fmt.h"
#include "str.h" 
#include "stralloc.h" 
#include "logmsg.h"

/**
	@file logmsg.c
	@author kp, feh
	@source qlibs
	@brief unified system and error message handling
*/

#define WHO "logmsg"

char *build_log_msg(const char *x[])
{
  stralloc sa = {0};
  stralloc_copys(&sa,"");  

  while(*x) { if (!stralloc_cats(&sa,*x++)) err_sys(WHO,errno); } /* concatenate *x */
  
  if (!stralloc_0(&sa)) err_sys(WHO,errno);
  return(sa.s);
}

void logmsg(const char *who,int ecode,unsigned int class,const char *msg)
{
  char strnum[FMT_ULONG];
  char *codestr = "";
  char *classstr = "";
  char *errmsg = "";

  errno = 0;   /* re-initialize errno, value is in 'code' now */

/* Part 1: obtain the (error) code -- perhaps received from OS */

  if (ecode != 0) {
    codestr = "";
    if (ecode < 0) {           // check for negative error codes 
      ecode = (ecode^-1) + 1;
      codestr = "-";
    }
    strnum[fmt_ulong(strnum,ecode)] = 0;    /* format for output */
    char *temp = strnum;
    codestr = str_cat(codestr,temp);
  }

/* Part 2: behavioral on error */

  switch (class) {
    case ERROR:  classstr = "error: ";    break;   // info + exit
    case FATAL:  classstr = "fatal: ";    break;   // info + exit 
    case DROP:   classstr = "drop: ";     break;   // info + next call/iteration
    case ALERT:  classstr = "alert: ";    break;   // info + next statement
    case WARN:   classstr = "warning: ";  break;   // info + next statement
    case INFO:   classstr = "info: ";     break;   // info + continue
    case SYNTAX: classstr = "syntax: ";   break;   // info + exit
    case USAGE:  classstr = "usage: ";    break;   // info + exit
    case TEMP:   classstr = "temp: ";    break;   // info + exit
    case CAT:    classstr = "";	          break;   // info w/o \n
    default: 
      class = LOG; classstr =  "";        break;   // custom info + continue
  }

/* Part 3: get system error message */

  if (class == FATAL || class == DROP)
    errmsg = error_str(errno);

/* Part 4: construct log message: Source: Class (Ecode) Message: Errmsg */

  buffer_puts(buffer_2,who);
  buffer_puts(buffer_2,": ");
  buffer_puts(buffer_2,classstr);
  if (class == FATAL || class == DROP || class == ERROR) {
    buffer_puts(buffer_2,"(");
    buffer_puts(buffer_2,codestr);
    buffer_puts(buffer_2,") ");
  }
  buffer_puts(buffer_2,msg);
  if (errno)  {
    buffer_puts(buffer_2,": ");
    buffer_puts(buffer_2,errmsg);
  }
  if (class != CAT) {
    buffer_puts(buffer_2,"\n");
    buffer_flush(buffer_2);
  }

  if (class == USAGE) _exit(USAGE); 
  if (class == SYNTAX) _exit(SYNTAX); 
  if (class == FATAL || class == DROP || class == ERROR) _exit(ecode);
}