1 /* This file is part of GNU Pies.
2 Copyright (C) 2009-2020 Sergey Poznyakoff
3
4 GNU Pies is free software; you can redistribute it and/or modify
5 it under the terms of the GNU General Public License as published by
6 the Free Software Foundation; either version 3, or (at your option)
7 any later version.
8
9 GNU Pies is distributed in the hope that it will be useful,
10 but WITHOUT ANY WARRANTY; without even the implied warranty of
11 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12 GNU General Public License for more details.
13
14 You should have received a copy of the GNU General Public License
15 along with GNU Pies. If not, see <http://www.gnu.org/licenses/>. */
16
17 #include "pies.h"
18
19 typedef struct
20 {
21 int open;
22 FILE *file;
23 } LOGSTREAM;
24
25
26 static int
syslog_printer(LOGSTREAM * str,int prio,const char * fmt,va_list ap)27 syslog_printer (LOGSTREAM *str, int prio, const char *fmt, va_list ap)
28 {
29 pies_vsyslog (prio, fmt, ap);
30 return 0;
31 }
32
33 static int
syslog_open(int logf,LOGSTREAM * str)34 syslog_open (int logf, LOGSTREAM *str)
35 {
36 if (logf & DIAG_REOPEN_LOG)
37 {
38 pies_syslog_open ();
39 str->open = 1;
40 }
41 else
42 str->open = 0;
43 return 0;
44 }
45
46 static void
syslog_close(LOGSTREAM * str)47 syslog_close (LOGSTREAM *str)
48 {
49 if (str->open)
50 pies_syslog_close ();
51 }
52
53 static int
stderr_printer(LOGSTREAM * str,int prio,const char * fmt,va_list ap)54 stderr_printer (LOGSTREAM *str, int prio, const char *fmt, va_list ap)
55 {
56 FILE *fp = str->file;
57 va_list aq;
58
59 fprintf (fp, "%s: ", program_name);
60 va_copy (aq, ap);
61 vfprintf (fp, fmt, aq);
62 va_end (aq);
63 fprintf (fp, "\n");
64 return 0;
65 }
66
67 static int
stderr_open(int logf,LOGSTREAM * str)68 stderr_open (int logf, LOGSTREAM *str)
69 {
70 if (PIES_SYSVINIT_ENABLED && (logf & DIAG_REOPEN_LOG))
71 {
72 int fd = console_open (O_WRONLY|O_NOCTTY|O_NDELAY);
73 if (fd == -1)
74 return -1;
75 str->file = fdopen (fd, "w");
76 if (!str->file)
77 {
78 close (fd);
79 return -1;
80 }
81 str->open = 1;
82 }
83 else
84 {
85 str->file = stderr;
86 str->open = 0;
87 }
88 return 0;
89 }
90
91 static void
stderr_close(LOGSTREAM * str)92 stderr_close (LOGSTREAM *str)
93 {
94 if (str->open)
95 fclose (str->file);
96 }
97
98 struct logger
99 {
100 int mask;
101 int (*printer) (LOGSTREAM *, int prio, const char *fmt, va_list ap);
102 int (*open) (int flags, LOGSTREAM *);
103 void (*close) (LOGSTREAM *);
104 };
105
106 struct logger logger[] = {
107 { DIAG_TO_STDERR, stderr_printer, stderr_open, stderr_close },
108 { DIAG_TO_SYSLOG, syslog_printer, syslog_open, syslog_close }
109 };
110
111 void
vdiagmsg(int logf,int prio,const char * fmt,va_list ap)112 vdiagmsg (int logf, int prio, const char *fmt, va_list ap)
113 {
114 int i;
115 for (i = 0; i < ARRAY_SIZE (logger); i++)
116 {
117 if (logger[i].mask & (logf & DIAG_TO_MASK))
118 {
119 LOGSTREAM stream;
120 if (logger[i].open (logf, &stream) == 0)
121 {
122 logger[i].printer (&stream, prio, fmt, ap);
123 logger[i].close (&stream);
124 }
125 }
126 }
127 }
128
129 void
diagmsg(int logf,int prio,const char * fmt,...)130 diagmsg (int logf, int prio, const char *fmt, ...)
131 {
132 va_list ap;
133 va_start (ap, fmt);
134 vdiagmsg (logf, prio, fmt, ap);
135 va_end (ap);
136 }
137
138 unsigned debug_level;
139 int source_info_option;
140 int diag_output = DIAG_TO_STDERR;
141
142 void
diag_setup(int flags)143 diag_setup (int flags)
144 {
145 if (flags)
146 diag_output = flags;
147 if (diag_output & DIAG_TO_SYSLOG)
148 pies_syslog_open ();
149 }
150
151 void
vlogmsg(int prio,const char * fmt,va_list ap)152 vlogmsg (int prio, const char *fmt, va_list ap)
153 {
154 vdiagmsg (diag_output, prio, fmt, ap);
155 }
156
157 void
logmsg(int prio,const char * fmt,...)158 logmsg (int prio, const char *fmt, ...)
159 {
160 va_list ap;
161 va_start (ap, fmt);
162 vlogmsg (prio, fmt, ap);
163 va_end (ap);
164 }
165
166 void
debug_msg(const char * fmt,...)167 debug_msg (const char *fmt, ...)
168 {
169 va_list ap;
170 va_start (ap, fmt);
171 vlogmsg (LOG_DEBUG, fmt, ap);
172 va_end (ap);
173 }
174
175
176 void
logmsg_vprintf(int prio,const char * fmt,va_list ap)177 logmsg_vprintf (int prio, const char *fmt, va_list ap)
178 {
179 char *p, *t, *str;
180 static char *buf = NULL;
181 static size_t len = 0;
182 static struct grecs_txtacc *log_acc;
183
184 if (grecs_vasprintf (&buf, &len, fmt, ap))
185 {
186 logmsg (LOG_CRIT, _("out of memory trying to log a message"));
187 return;
188 }
189 if (!log_acc)
190 log_acc = grecs_txtacc_create ();
191
192 str = buf;
193
194 while (str)
195 {
196 p = strchr (str, '\n');
197 if (p)
198 {
199 *p++ = 0;
200 if (!*p)
201 p = NULL;
202 grecs_txtacc_grow_string (log_acc, str);
203 grecs_txtacc_grow_char (log_acc, 0);
204 t = grecs_txtacc_finish (log_acc, 0);
205 logmsg (prio, "%s", t);
206 grecs_txtacc_free_string (log_acc, t);
207 }
208 else
209 grecs_txtacc_grow_string (log_acc, str);
210 str = p;
211 }
212 }
213
214 void
logmsg_printf(int prio,const char * fmt,...)215 logmsg_printf (int prio, const char *fmt, ...)
216 {
217 va_list ap;
218 va_start (ap, fmt);
219 logmsg_vprintf (prio, fmt, ap);
220 va_end (ap);
221 }
222
223 void
pies_diag_printer(grecs_locus_t const * locus,int err,int errcode,const char * msg)224 pies_diag_printer (grecs_locus_t const *locus, int err, int errcode,
225 const char *msg)
226 {
227 if (locus)
228 {
229 char *locstr = NULL;
230 size_t locsize = 0;
231
232 grecs_asprint_locus (&locstr, &locsize, locus);
233
234 if (errcode)
235 logmsg (err ? LOG_ERR : LOG_WARNING, "%s: %s: %s",
236 locstr, msg, strerror (errcode));
237 else
238 logmsg (err ? LOG_ERR : LOG_WARNING, "%s: %s",
239 locstr, msg);
240 free (locstr);
241 }
242 else
243 {
244 if (errcode)
245 logmsg (err ? LOG_ERR : LOG_WARNING, "%s: %s", msg,
246 strerror (errcode));
247 else
248 logmsg (err ? LOG_ERR : LOG_WARNING, "%s", msg);
249 }
250 }
251
252 void
logfuncall(const char * fun,const char * arg,int err)253 logfuncall (const char *fun, const char *arg, int err)
254 {
255 if (arg)
256 grecs_error (NULL, err, _("%s: %s failed"), arg, fun);
257 else
258 grecs_error (NULL, err, _("%s failed"), fun);
259 }
260