verbosity: Prepare hooking of log messages
[src/app-framework-binder.git] / src / verbose.c
1 /*
2  Copyright (C) 2016, 2017 "IoT.bzh"
3
4  author: José Bollo <jose.bollo@iot.bzh>
5
6  Licensed under the Apache License, Version 2.0 (the "License");
7  you may not use this file except in compliance with the License.
8  You may obtain a copy of the License at
9
10      http://www.apache.org/licenses/LICENSE-2.0
11
12  Unless required by applicable law or agreed to in writing, software
13  distributed under the License is distributed on an "AS IS" BASIS,
14  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  See the License for the specific language governing permissions and
16  limitations under the License.
17 */
18
19 #include <stdio.h>
20 #include <stdarg.h>
21
22 #include "verbose.h"
23
24 #if !defined(DEFAULT_VERBOSITY)
25 # define DEFAULT_VERBOSITY Verbosity_Level_Warning
26 #endif
27
28 int verbosity = 1;
29 void (*verbose_observer)(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args);
30
31 #define CROP_LOGLEVEL(x) ((x) < Log_Level_Emergency ? Log_Level_Emergency : (x) > Log_Level_Debug ? Log_Level_Debug : (x))
32
33 #if defined(VERBOSE_WITH_SYSLOG)
34
35 #include <syslog.h>
36
37 static void _vverbose_(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args)
38 {
39         char *p;
40
41         if (file == NULL || vasprintf(&p, fmt, args) < 0)
42                 vsyslog(loglevel, fmt, args);
43         else {
44                 syslog(CROP_LOGLEVEL(loglevel), "%s [%s:%d, function]", p, file, line, function);
45                 free(p);
46         }
47 }
48
49 void verbose_set_name(const char *name, int authority)
50 {
51         openlog(name, LOG_PERROR, authority ? LOG_AUTH : LOG_USER);
52 }
53
54 #elif defined(VERBOSE_WITH_SYSTEMD)
55
56 #define SD_JOURNAL_SUPPRESS_LOCATION
57
58 #include <systemd/sd-journal.h>
59
60 static const char *appname;
61
62 static int appauthority;
63
64 static void _vverbose_(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args)
65 {
66         char lino[20];
67
68         if (file == NULL) {
69                 sd_journal_printv(loglevel, fmt, args);
70         } else {
71                 sprintf(lino, "%d", line);
72                 sd_journal_printv_with_location(loglevel, file, lino, function, fmt, args);
73         }
74 }
75
76 void verbose_set_name(const char *name, int authority)
77 {
78         appname = name;
79         appauthority = authority;
80 }
81
82 #else
83
84 #include <unistd.h>
85 #include <errno.h>
86
87 static const char *appname;
88
89 static int appauthority;
90
91 static const char *prefixes[] = {
92         "<0> EMERGENCY",
93         "<1> ALERT",
94         "<2> CRITICAL",
95         "<3> ERROR",
96         "<4> WARNING",
97         "<5> NOTICE",
98         "<6> INFO",
99         "<7> DEBUG"
100 };
101
102 static void _vverbose_(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args)
103 {
104         int saverr = errno;
105         int tty = isatty(fileno(stderr));
106         errno = saverr;
107
108         fprintf(stderr, "%s: ", prefixes[CROP_LOGLEVEL(loglevel)] + (tty ? 4 : 0));
109         vfprintf(stderr, fmt, args);
110         if (file != NULL && (!tty || verbosity > 2))
111                 fprintf(stderr, " [%s:%d,%s]\n", file, line, function);
112         else
113                 fprintf(stderr, "\n");
114 }
115
116 void verbose_set_name(const char *name, int authority)
117 {
118         appname = name;
119         appauthority = authority;
120 }
121
122 #endif
123
124 void verbose(int loglevel, const char *file, int line, const char *function, const char *fmt, ...)
125 {
126         va_list ap;
127
128         va_start(ap, fmt);
129         vverbose(loglevel, file, line, function, fmt, ap);
130         va_end(ap);
131 }
132
133 void vverbose(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args)
134 {
135         if (verbose_observer) {
136                 va_list ap;
137                 va_copy(ap, args);
138                 verbose_observer(loglevel, file, line, function, fmt, ap);
139                 va_end(ap);
140         }
141         _vverbose_(loglevel, file, line, function, fmt, args);
142 }
143