clsync
Loading...
Searching...
No Matches
error.c
Go to the documentation of this file.
1/*
2 clsync - file tree sync utility based on inotify/kqueue
3
4 Copyright (C) 2013-2014 Dmitry Yu Okunev <dyokunev@ut.mephi.ru> 0x8E30679C
5
6 This program is free software: you can redistribute it and/or modify
7 it under the terms of the GNU General Public License as published by
8 the Free Software Foundation, either version 3 of the License, or
9 (at your option) any later version.
10
11 This program is distributed in the hope that it will be useful,
12 but WITHOUT ANY WARRANTY; without even the implied warranty of
13 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 GNU General Public License for more details.
15
16 You should have received a copy of the GNU General Public License
17 along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20/*
21 * This file implements way to output debugging information. It's supposed
22 * to be slow but convenient functions.
23 */
24
25#include <stdlib.h>
26#include <stdio.h>
27#include <errno.h>
28#include <string.h>
29#include <stdarg.h>
30#include <syslog.h>
31#include <pthread.h> /* pthread_self() */
32#include <sys/types.h> /* getpid() */
33#include <unistd.h> /* getpid() */
34
35#include "macros.h"
36#include "configuration.h"
37
38#include "error.h"
39#include "pthreadex.h" /* pthread_*_shared() */
40
41#ifdef BACKTRACE_SUPPORT
42#include <execinfo.h>
43#endif
44
45static int zero = 0;
46static int three = 3;
47
48static int *outputmethod = &zero;
49static int *debug = &zero;
50static int *quiet = &zero;
51static int *verbose = &three;
52
53pthread_mutex_t *error_mutex_p = NULL;
54
55static int printf_stderr ( const char *fmt, ... )
56{
57 va_list args;
58 int rc;
59 va_start ( args, fmt );
60 rc = vfprintf ( stderr, fmt, args );
61 va_end ( args );
62 return rc;
63}
64
65static int printf_stdout ( const char *fmt, ... )
66{
67 va_list args;
68 int rc;
69 va_start ( args, fmt );
70 rc = vfprintf ( stdout, fmt, args );
71 va_end ( args );
72 return rc;
73}
74
75static int vprintf_stderr ( const char *fmt, va_list args )
76{
77 return vfprintf ( stderr, fmt, args );
78}
79
80static int vprintf_stdout ( const char *fmt, va_list args )
81{
82 return vfprintf ( stdout, fmt, args );
83}
84
85
86static void flush_stderr ( int level )
87{
88 ( void ) level;
89 fprintf ( stderr, "\n" );
90 fflush ( stderr );
91}
92
93static void flush_stdout ( int level )
94{
95 ( void ) level;
96 fprintf ( stdout, "\n" );
97 fflush ( stdout );
98}
99
100
101static char _syslog_buffer[SYSLOG_BUFSIZ + 1] = {0};
103
104static int vsyslog_buf ( const char *fmt, va_list args )
105{
106 int len;
107 size_t size;
109#ifdef VERYPARANOID
110
111 if (
112 ( size > SYSLOG_BUFSIZ ) ||
115 ) {
116 fprintf ( stderr, "Security problem while vsyslog_buf(): "
117 "_syslog_buffer_filled == %lu; "
118 "size == %lu; "
119 "SYSLOG_BUFSIZ == "XTOSTR ( SYSLOG_BUFSIZ ) "\n",
120 _syslog_buffer_filled, size );
121 exit ( ENOBUFS );
122 }
123
124#endif
125
126 if ( !size )
127 return 0;
128
129 len = vsnprintf (
131 size,
132 fmt,
133 args
134 );
135
136 if ( len > 0 ) {
138
141 }
142
143 return 0;
144}
145
146static int syslog_buf ( const char *fmt, ... )
147{
148 va_list args;
149 int rc;
150 va_start ( args, fmt );
151 rc = vsyslog_buf ( fmt, args );
152 va_end ( args );
153 return rc;
154}
155
156static void syslog_flush ( int level )
157{
158 syslog ( level, "%s", _syslog_buffer );
160}
161
162typedef int ( *outfunct_t ) ( const char *format, ... );
163typedef int ( *voutfunct_t ) ( const char *format, va_list ap );
164typedef void ( *flushfunct_t ) ( int level );
165
171
177
183
184void _critical ( const char *const function_name, const char *fmt, ... )
185{
186 if ( *quiet )
187 return;
188
189 struct timespec abs_time;
190 clock_gettime ( CLOCK_REALTIME, &abs_time );
191 abs_time.tv_sec += 1;
192
193 if ( error_mutex_p != NULL )
194 pthread_mutex_timedlock ( error_mutex_p, &abs_time );
195
197 {
198 va_list args;
199 pthread_t thread = pthread_self();
200 pid_t pid = getpid();
201 outfunct[method] ( "Critical (pid: %u; thread: %p): %s(): ", pid, thread, function_name );
202 va_start ( args, fmt );
203 voutfunct[method] ( fmt, args );
204 va_end ( args );
205 outfunct[method] ( " (current errno %i: %s)", errno, strerror ( errno ) );
206 flushfunct[method] ( LOG_CRIT );
207 }
208#ifdef BACKTRACE_SUPPORT
209 {
210 void *buf[BACKTRACE_LENGTH];
211 char **strings;
212 int backtrace_len = backtrace ( ( void ** ) buf, BACKTRACE_LENGTH );
213 strings = backtrace_symbols ( buf, backtrace_len );
214
215 if ( strings == NULL ) {
216 outfunct[method] ( "_critical(): Got error, but cannot print the backtrace. Current errno: %u: %s\n",
217 errno, strerror ( errno ) );
218 flushfunct[method] ( LOG_CRIT );
219 pthread_mutex_unlock ( error_mutex_p );
220 exit ( EXIT_FAILURE );
221 }
222
223 for ( int j = 1; j < backtrace_len; j++ ) {
224 outfunct[method] ( " %s", strings[j] );
225 flushfunct[method] ( LOG_CRIT );
226 }
227 }
228#endif
229
230 if ( error_mutex_p != NULL )
231 pthread_mutex_unlock ( error_mutex_p );
232
233 error_deinit();
234 exit ( errno );
235 return;
236}
237
238void _error ( const char *const function_name, const char *fmt, ... )
239{
240 va_list args;
241
242 if ( *quiet )
243 return;
244
245 if ( *verbose < 1 )
246 return;
247
248 if ( error_mutex_p != NULL )
250
251 pthread_t thread = pthread_self();
252 pid_t pid = getpid();
254 outfunct[method] ( *debug ? "Error (pid: %u; thread: %p): %s(): " : "Error: ", pid, thread, function_name );
255 va_start ( args, fmt );
256 voutfunct[method] ( fmt, args );
257 va_end ( args );
258
259 if ( errno )
260 outfunct[method] ( " (%i: %s)", errno, strerror ( errno ) );
261
262 flushfunct[method] ( LOG_ERR );
263
264 if ( error_mutex_p != NULL )
265 pthread_mutex_unlock ( error_mutex_p );
266
267 return;
268}
269
270void _info ( const char *const function_name, const char *fmt, ... )
271{
272 va_list args;
273
274 if ( *quiet )
275 return;
276
277 if ( *verbose < 3 )
278 return;
279
280 if ( error_mutex_p != NULL )
282
283 pthread_t thread = pthread_self();
284 pid_t pid = getpid();
286 outfunct[method] ( *debug ? "Info (pid: %u; thread: %p): %s(): " : "Info: ", pid, thread, function_name );
287 va_start ( args, fmt );
288 voutfunct[method] ( fmt, args );
289 va_end ( args );
290 flushfunct[method] ( LOG_INFO );
291
292 if ( error_mutex_p != NULL )
293 pthread_mutex_unlock ( error_mutex_p );
294
295 return;
296}
297
298void _warning ( const char *const function_name, const char *fmt, ... )
299{
300 va_list args;
301
302 if ( *quiet )
303 return;
304
305 if ( *verbose < 2 )
306 return;
307
308 if ( error_mutex_p != NULL )
310
311 pthread_t thread = pthread_self();
312 pid_t pid = getpid();
314 outfunct[method] ( *debug ? "Warning (pid: %u; thread: %p): %s(): " : "Warning: ", pid, thread, function_name );
315 va_start ( args, fmt );
316 voutfunct[method] ( fmt, args );
317 va_end ( args );
318 flushfunct[method] ( LOG_WARNING );
319
320 if ( error_mutex_p != NULL )
321 pthread_mutex_unlock ( error_mutex_p );
322
323 return;
324}
325
326#ifdef _DEBUG_SUPPORT
327void _debug ( int debug_level, const char *const function_name, const char *fmt, ... )
328{
329 va_list args;
330
331 if ( *quiet )
332 return;
333
334 if ( debug_level > *debug )
335 return;
336
337 if ( error_mutex_p != NULL )
339
340 pthread_t thread = pthread_self();
341 pid_t pid = getpid();
343 outfunct[method] ( "Debug%u (pid: %u; thread: %p): %s(): ", debug_level, pid, thread, function_name );
344 va_start ( args, fmt );
345 voutfunct[method] ( fmt, args );
346 va_end ( args );
347 flushfunct[method] ( LOG_DEBUG );
348
349 if ( error_mutex_p != NULL )
350 pthread_mutex_unlock ( error_mutex_p );
351
352 return;
353}
354#endif
355
356void error_init ( void *_outputmethod, int *_quiet, int *_verbose, int *_debug )
357{
358 outputmethod = _outputmethod;
359 quiet = _quiet;
360 verbose = _verbose;
361 debug = _debug;
362 openlog ( NULL, SYSLOG_FLAGS, SYSLOG_FACILITY );
363 return;
364}
365
367void error_init_ipc ( ipc_type_t _ipc_type )
368{
369 static pthread_mutex_t error_mutex = PTHREAD_MUTEX_INITIALIZER;
370 ipc_type = _ipc_type;
371
372 switch ( ipc_type ) {
373 case IPCT_SHARED:
375 break;
376
377 case IPCT_PRIVATE:
378 error_mutex_p = &error_mutex;
379 pthread_mutex_init ( error_mutex_p, NULL );
380 break;
381
382 default:
383 critical ( "Unknown ipc_type: %i", ipc_type );
384 }
385
386 return;
387}
388
390{
391 switch ( ipc_type ) {
392 case IPCT_SHARED:
394 error_mutex_p = NULL;
395 break;
396
397 case IPCT_PRIVATE:
398 break;
399 }
400
401 return;
402}
403
#define SYSLOG_FLAGS
#define OUTPUT_LOCK_TIMEOUT
#define SYSLOG_FACILITY
#define SYSLOG_BUFSIZ
static int * quiet
Definition error.c:50
static int syslog_buf(const char *fmt,...)
Definition error.c:146
static void flush_stdout(int level)
Definition error.c:93
static int vprintf_stdout(const char *fmt, va_list args)
Definition error.c:80
ipc_type_t ipc_type
Definition error.c:366
void(* flushfunct_t)(int level)
Definition error.c:164
void _warning(const char *const function_name, const char *fmt,...)
Definition error.c:298
void error_init(void *_outputmethod, int *_quiet, int *_verbose, int *_debug)
Definition error.c:356
int(* voutfunct_t)(const char *format, va_list ap)
Definition error.c:163
static int zero
Definition error.c:45
static int * verbose
Definition error.c:51
void error_init_ipc(ipc_type_t _ipc_type)
Definition error.c:367
static int vsyslog_buf(const char *fmt, va_list args)
Definition error.c:104
static int three
Definition error.c:46
int(* outfunct_t)(const char *format,...)
Definition error.c:162
void error_deinit()
Definition error.c:389
void _info(const char *const function_name, const char *fmt,...)
Definition error.c:270
static int printf_stdout(const char *fmt,...)
Definition error.c:65
static int * debug
Definition error.c:49
static voutfunct_t voutfunct[]
Definition error.c:172
static int printf_stderr(const char *fmt,...)
Definition error.c:55
static int * outputmethod
Definition error.c:48
void _critical(const char *const function_name, const char *fmt,...)
Definition error.c:184
static flushfunct_t flushfunct[]
Definition error.c:178
static int vprintf_stderr(const char *fmt, va_list args)
Definition error.c:75
pthread_mutex_t * error_mutex_p
Definition error.c:53
size_t _syslog_buffer_filled
Definition error.c:102
static void syslog_flush(int level)
Definition error.c:156
static void flush_stderr(int level)
Definition error.c:86
void _error(const char *const function_name, const char *fmt,...)
Definition error.c:238
static char _syslog_buffer[(1<< 16)+1]
Definition error.c:101
static outfunct_t outfunct[]
Definition error.c:166
enum ipc_type ipc_type_t
Definition error.h:63
#define critical(...)
Definition error.h:32
#define BACKTRACE_LENGTH
Definition error.h:23
outputmethod
Definition error.h:69
@ OM_STDOUT
Definition error.h:71
@ OM_STDERR
Definition error.h:70
@ OM_SYSLOG
Definition error.h:72
ipc_type
Definition error.h:59
@ IPCT_SHARED
Definition error.h:61
@ IPCT_PRIVATE
Definition error.h:60
enum outputmethod outputmethod_t
Definition error.h:76
#define XTOSTR(a)
Definition macros.h:45
int pthread_mutex_init_shared(pthread_mutex_t **mutex_p)
Definition pthreadex.c:25
int pthread_mutex_reltimedlock(pthread_mutex_t *mutex_p, long tv_sec, long tv_nsec)
Definition pthreadex.c:63
int pthread_mutex_destroy_shared(pthread_mutex_t *mutex_p)
Definition pthreadex.c:36