summaryrefslogtreecommitdiff
path: root/src/logmsg.c
blob: f18bda97f5e91d15da0ddb1538a7b347a0caea87 (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
98
99
100
101
102
103
#include "logmsg.h"

#include <unistd.h>

#include <errno.h>
#include <stdarg.h>

#include "buffer.h"
#include "fmt.h"
#include "str.h"
#include "stralloc.h"

/**
  @file logmsg.c
  @author kp, feh
  @ref 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);
}