Project

General

Profile

Statistics
| Branch: | Tag: | Revision:

gdp / ep / ep_log.c @ master

History | View | Annotate | Download (5.31 KB)

1 67565068 Eric Allman
/* vim: set ai sw=8 sts=8 ts=8 : */
2 0c663d10 Eric Allman
3 47c6ea64 Eric Allman
/***********************************************************************
4 055d3009 Eric Allman
**  ----- BEGIN LICENSE BLOCK -----
5
**        LIBEP: Enhanced Portability Library (Reduced Edition)
6
**
7 c87dd166 Eric Allman
**        Copyright (c) 2008-2019, Eric P. Allman.  All rights reserved.
8
**        Copyright (c) 2015-2019, Regents of the University of California.
9 6bd5476b Eric Allman
**        All rights reserved.
10 055d3009 Eric Allman
**
11 6bd5476b Eric Allman
**        Permission is hereby granted, without written agreement and without
12
**        license or royalty fees, to use, copy, modify, and distribute this
13
**        software and its documentation for any purpose, provided that the above
14
**        copyright notice and the following two paragraphs appear in all copies
15
**        of this software.
16 055d3009 Eric Allman
**
17 6bd5476b Eric Allman
**        IN NO EVENT SHALL REGENTS BE LIABLE TO ANY PARTY FOR DIRECT, INDIRECT,
18
**        SPECIAL, INCIDENTAL, OR CONSEQUENTIAL DAMAGES, INCLUDING LOST
19
**        PROFITS, ARISING OUT OF THE USE OF THIS SOFTWARE AND ITS DOCUMENTATION,
20
**        EVEN IF REGENTS HAS BEEN ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
21 055d3009 Eric Allman
**
22 6bd5476b Eric Allman
**        REGENTS SPECIFICALLY DISCLAIMS ANY WARRANTIES, INCLUDING, BUT NOT
23 055d3009 Eric Allman
**        LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
24 6bd5476b Eric Allman
**        FOR A PARTICULAR PURPOSE. THE SOFTWARE AND ACCOMPANYING DOCUMENTATION,
25
**        IF ANY, PROVIDED HEREUNDER IS PROVIDED "AS IS". REGENTS HAS NO
26
**        OBLIGATION TO PROVIDE MAINTENANCE, SUPPORT, UPDATES, ENHANCEMENTS,
27
**        OR MODIFICATIONS.
28 055d3009 Eric Allman
**  ----- END LICENSE BLOCK -----
29 47c6ea64 Eric Allman
***********************************************************************/
30
31
/*
32 67565068 Eric Allman
**  Message logging.
33 47c6ea64 Eric Allman
*/
34
35 67565068 Eric Allman
#include <ep/ep.h>
36
#include <ep/ep_app.h>
37 58c51fe6 Eric Allman
#include <ep/ep_log.h>
38 67565068 Eric Allman
#include <ep/ep_stat.h>
39
#include <ep/ep_string.h>
40
#include <ep/ep_syslog.h>
41
#include <ep/ep_time.h>
42 47c6ea64 Eric Allman
43 67565068 Eric Allman
#include <inttypes.h>
44
#include <time.h>
45
#include <sys/cdefs.h>
46
#include <sys/time.h>
47 47c6ea64 Eric Allman
48 58c51fe6 Eric Allman
struct logfunc
49
{
50
        struct logfunc        *next;                // next in chain
51
        EP_LOG_FUNC        *func;                // function to call
52
        void                *ctx;                // external context
53 328ab6a8 Eric Allman
        unsigned int        minsev;                // minimum severity to log
54 58c51fe6 Eric Allman
};
55
56 67565068 Eric Allman
static const char        *LogTag = NULL;
57
static int                LogFac = -1;
58 58c51fe6 Eric Allman
static struct logfunc        *LogFuncList = NULL;
59 67565068 Eric Allman
static bool                LogInitialized = false;
60 47c6ea64 Eric Allman
61
62 58c51fe6 Eric Allman
void
63
ep_log_file(void *_fp,
64
        EP_STAT estat,
65 e41619fe Eric Allman
        const char *fmt,
66 58c51fe6 Eric Allman
        va_list ap)
67 47c6ea64 Eric Allman
{
68 67565068 Eric Allman
        char tbuf[40];
69
        struct tm *tm;
70
        time_t tvsec;
71 58c51fe6 Eric Allman
        EP_TIME_SPEC tv;
72 fc0cbc23 Eric Allman
        FILE *fp = (FILE *) _fp;
73 67565068 Eric Allman
74 fb937b04 Eric Allman
        flockfile(fp);
75 58c51fe6 Eric Allman
        if (fp == stderr || fp == stdout)
76
                fprintf(fp, "%s", EpVid->vidfgcyan);
77
        ep_time_now(&tv);
78
        tvsec = tv.tv_sec;                //XXX may overflow if time_t is 32 bits!
79 67565068 Eric Allman
        if ((tm = localtime(&tvsec)) == NULL)
80
                snprintf(tbuf, sizeof tbuf, "%"PRIu64".%06lu",
81 58c51fe6 Eric Allman
                                tv.tv_sec, tv.tv_nsec / 1000L);
82 67565068 Eric Allman
        else
83
        {
84
                char lbuf[40];
85 47c6ea64 Eric Allman
86 67565068 Eric Allman
                snprintf(lbuf, sizeof lbuf, "%%Y-%%m-%%d %%H:%%M:%%S.%06lu %%z",
87 58c51fe6 Eric Allman
                                tv.tv_nsec / 1000L);
88 67565068 Eric Allman
                strftime(tbuf, sizeof tbuf, lbuf, tm);
89
        }
90 47c6ea64 Eric Allman
91 67565068 Eric Allman
        fprintf(fp, "%s %s: ", tbuf, LogTag);
92
        vfprintf(fp, fmt, ap);
93
        if (!EP_STAT_ISOK(estat))
94
        {
95
                char ebuf[100];
96 47c6ea64 Eric Allman
97 67565068 Eric Allman
                ep_stat_tostr(estat, ebuf, sizeof ebuf);
98
                fprintf(fp, ": %s", ebuf);
99
        }
100
        fprintf(fp, "\n");
101 58c51fe6 Eric Allman
        if (fp == stderr || fp == stdout)
102 fb937b04 Eric Allman
                fprintf(fp, "%s", EpVid->vidnorm);
103
        fprintf(fp, "\n");
104
        funlockfile(fp);
105 47c6ea64 Eric Allman
}
106
107
108 67565068 Eric Allman
static void
109 58c51fe6 Eric Allman
ep_log_syslog(void *unused, EP_STAT estat, const char *fmt, va_list ap)
110 47c6ea64 Eric Allman
{
111 67565068 Eric Allman
        char ebuf[100];
112
        char mbuf[500];
113
        int sev = EP_STAT_SEVERITY(estat);
114
        int logsev;
115
        static bool inited = false;
116
117
        // initialize log if necessary
118
        if (!inited)
119
        {
120
                openlog(LogTag, LOG_PID, LogFac);
121
                inited = true;
122
        }
123 47c6ea64 Eric Allman
124 67565068 Eric Allman
        // map estat severity to syslog priority
125
        switch (sev)
126 47c6ea64 Eric Allman
        {
127 67565068 Eric Allman
          case EP_STAT_SEV_OK:
128
                logsev = LOG_INFO;
129
                break;
130 47c6ea64 Eric Allman
131 67565068 Eric Allman
          case EP_STAT_SEV_WARN:
132
                logsev = LOG_WARNING;
133
                break;
134 47c6ea64 Eric Allman
135 67565068 Eric Allman
          case EP_STAT_SEV_ERROR:
136
                logsev = LOG_ERR;
137
                break;
138 47c6ea64 Eric Allman
139 67565068 Eric Allman
          case EP_STAT_SEV_SEVERE:
140
                logsev = LOG_CRIT;
141
                break;
142 47c6ea64 Eric Allman
143 67565068 Eric Allman
          case EP_STAT_SEV_ABORT:
144
                logsev = LOG_ALERT;
145
                break;
146
147
          default:
148
                // %%% for lack of anything better
149
                logsev = LOG_ERR;
150
                break;
151 47c6ea64 Eric Allman
152
        }
153
154 7101103c Eric Allman
        ep_stat_tostr(estat, ebuf, sizeof ebuf);
155 67565068 Eric Allman
        vsnprintf(mbuf, sizeof mbuf, fmt, ap);
156 7101103c Eric Allman
        syslog(logsev, "%s: %s", mbuf, ebuf);
157 67565068 Eric Allman
}
158 47c6ea64 Eric Allman
159
160
void
161 58c51fe6 Eric Allman
ep_log_init(const char *tag,        // NULL => use program name
162
        int logfac,                // -1 => don't use syslog
163
        FILE *logfile)                // NULL => don't print to open file
164 47c6ea64 Eric Allman
{
165
166 58c51fe6 Eric Allman
        if (tag == NULL)
167
                tag = ep_app_getprogname();
168
        LogTag = tag;
169
170
        if (logfac >= 0)
171
                ep_log_addmethod(&ep_log_syslog, NULL, EP_STAT_SEV_OK);
172
        LogFac = logfac;
173
174
        if (logfile != NULL)
175
                ep_log_addmethod(&ep_log_file, logfile, EP_STAT_SEV_OK);
176
177
        LogInitialized = true;
178
}
179
180
181
void
182
ep_log_addmethod(EP_LOG_FUNC *func, void *ctx, int minsev)
183
{
184
        struct logfunc *lf;
185
        struct logfunc **lfh;
186
187
        for (lfh = &LogFuncList; (lf = *lfh) != NULL; lfh = &lf->next)
188
                continue;
189 fc0cbc23 Eric Allman
        *lfh = lf = (struct logfunc *) ep_mem_zalloc(sizeof *lf);
190 58c51fe6 Eric Allman
        lf->func = func;
191
        lf->ctx = ctx;
192
        lf->minsev = minsev;
193
}
194
195
void
196
ep_logv(EP_STAT estat, const char *fmt, va_list _ap)
197
{
198
        struct logfunc *lf;
199 47c6ea64 Eric Allman
200 67565068 Eric Allman
        if (!LogInitialized)
201 47c6ea64 Eric Allman
        {
202 58c51fe6 Eric Allman
                const char *p;
203
                int logfac = -1;
204
                FILE *logfp = NULL;
205 47c6ea64 Eric Allman
206 58c51fe6 Eric Allman
                p = ep_adm_getstrparam("libep.log.facility", "user");
207
                if (p != NULL)
208
                        logfac = ep_syslog_fac_from_name(p);
209 91d48757 Eric Allman
210 58c51fe6 Eric Allman
                p = ep_adm_getstrparam("libep.log.fileout", "stderr");
211
                if (strcasecmp(p, "stderr") == 0)
212
                        logfp = stderr;
213
                else if (strcmp(p, "stdout") == 0)
214
                        logfp = stdout;
215 47c6ea64 Eric Allman
216 58c51fe6 Eric Allman
                ep_log_init(NULL, logfac, logfp);
217 47c6ea64 Eric Allman
        }
218 58c51fe6 Eric Allman
219
        // call other log functions
220
        for (lf = LogFuncList; lf != NULL; lf = lf->next)
221 47c6ea64 Eric Allman
        {
222 58c51fe6 Eric Allman
                va_list ap;
223
224
                if (EP_STAT_SEVERITY(estat) < lf->minsev)
225
                        continue;
226 1081f575 Eric Allman
                va_copy(ap, _ap);
227 58c51fe6 Eric Allman
                (*lf->func)(lf->ctx, estat, fmt, ap);
228 47c6ea64 Eric Allman
        }
229
}
230 1081f575 Eric Allman
231
232
void
233
ep_log(EP_STAT estat, const char *fmt, ...)
234
{
235
        va_list ap;
236
237
        va_start(ap, fmt);
238
        ep_logv(estat, fmt, ap);
239
        va_end(ap);
240
}