hooking: Add hook at global scope
[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         void (*observer)(int loglevel, const char *file, int line, const char *function, const char *fmt, va_list args) = verbose_observer;
136
137         if (!observer)
138                 _vverbose_(loglevel, file, line, function, fmt, args);
139         else {
140                 va_list ap;
141                 va_copy(ap, args);
142                 _vverbose_(loglevel, file, line, function, fmt, args);
143                 observer(loglevel, file, line, function, fmt, ap);
144                 va_end(ap);
145         }
146 }
147