Nilorea Library
C utilities for networking, threading, graphics
n_log.c
Go to the documentation of this file.
1
7#include "nilorea/n_common.h"
8#include "nilorea/n_log.h"
9
10#include <pthread.h>
11#include <string.h>
12#include <inttypes.h>
13
14#ifndef __windows__
15#include <syslog.h>
16#else
17#include <time.h>
18#endif
19
21typedef struct LOG_LEVELS
22{
24 char *c_name;
26 int c_val;
28 char *w_name;
29
31
34{
35 { "EMERG", LOG_EMERG, "ERROR" },
36 { "ALERT", LOG_ALERT, "ERROR" },
37 { "CRITICAL", LOG_CRIT, "ERROR" },
38 { "ERR", LOG_ERR, "ERROR" },
39 { "WARNING", LOG_WARNING, "WARNING" },
40 { "NOTICE", LOG_NOTICE, "SUCCESS" },
41 { "INFO", LOG_INFO, "INFORMATION" },
42 { "DEBUG", LOG_DEBUG, "INFORMATION" },
43 { NULL, -1, NULL }
44};
45
47static int LOG_LEVEL = LOG_NULL ;
48
50static int LOG_TYPE = LOG_STDERR ;
51
53static FILE *log_file = NULL ;
54
56char *proc_name = NULL ;
57
58
64char *open_sysjrnl( char *identity )
65{
66 __n_assert( identity, return NULL );
67#ifndef __windows__
68 /* LOG_CONS: log to console if no syslog available
69 * LOG_PID: add pid of calling process to log
70 * Local use 7 : compat with older logging systems
71 */
72 openlog ( identity, LOG_CONS|LOG_PID|LOG_NDELAY, LOG_LOCAL7 );
73#endif
74 proc_name = strdup( identity );
75 return proc_name ;
76} /* open_sysjrnl */
77
78
79
83void close_sysjrnl( void )
84{
85#ifndef __windows__
86 closelog();
87#endif
89} /* close_sysjrnl */
90
91
92
97void set_log_level( const int log_level )
98{
99 if( log_level == LOG_FILE )
100 {
102 return ;
103 }
104 if( log_level == LOG_STDERR )
105 {
107 return ;
108 }
109 if( log_level == LOG_SYSJRNL )
110 {
112 return ;
113 }
114 LOG_LEVEL = log_level ;
115} /* set_log_level() */
116
117
118
123int get_log_level( void )
124{
125 return LOG_LEVEL ;
126} /* get_log_level() */
127
128
129
135int set_log_file( char *file )
136{
137 __n_assert( file, return FALSE );
138
139 if( !log_file )
140 log_file = fopen( file, "a+" );
141 else
142 {
143 fclose( log_file );
144 log_file = fopen( file, "a+" );
145 }
146
148
149 __n_assert( log_file, return FALSE );
150
151 return TRUE ;
152} /* set_log_file */
153
154
155
160FILE *get_log_file( void )
161{
162 return log_file ;
163} /*get_log_level() */
164
165#ifndef _vscprintf
172int _vscprintf_so(const char * format, va_list pargs)
173{
174 int retval;
175 va_list argcopy;
176 va_copy(argcopy, pargs);
177 retval = vsnprintf(NULL, 0, format, argcopy);
178 va_end(argcopy);
179 return retval;
180}
181#endif
182
183#ifndef vasprintf
191int vasprintf(char **strp, const char *fmt, va_list ap)
192{
193 long long int len = _vscprintf_so(fmt, ap);
194 if (len == -1)
195 return -1;
196 char *str = NULL ;
197 Malloc( str, char, (size_t) len + 1 + sizeof( void *) ); // len + EndOfString + padding
198 if (!str)
199 return -1;
200 int r = vsnprintf(str, (size_t)(len+1), fmt, ap); /* "secure" version of vsprintf */
201 if (r == -1)
202 return free(str), -1;
203 *strp = str;
204 return r;
205}
206#endif
207
208#ifndef asprintf
216int asprintf(char *strp[], const char *fmt, ...)
217{
218 va_list ap;
219 va_start(ap, fmt);
220 int r = vasprintf(strp, fmt, ap);
221 va_end(ap);
222 return r;
223}
224#endif
225
234void _n_log( int level, const char *file, const char *func, int line, const char *format, ... )
235{
236 FILE *out = NULL ;
237
238 if( level == LOG_NULL )
239 return ;
240
241 if( !log_file )
242 out = stderr ;
243 else
244 out = log_file ;
245
246 int log_level = get_log_level();
247
248 if( level <= log_level )
249 {
250 va_list args ;
251 char *syslogbuffer = NULL ;
252 char *eventbuffer = NULL ;
253#ifdef __windows__
254 size_t needed = 0 ;
255 char *name = "NULL" ;
256 if( proc_name )
257 name = proc_name ;
258#endif
259
260 switch( LOG_TYPE )
261 {
262 case LOG_SYSJRNL :
263 va_start (args, format);
264 vasprintf( &syslogbuffer, format, args );
265 va_end( args );
266#ifdef __windows__
267 needed = (unsigned long long)snprintf( NULL, 0, "start /B EventCreate /t %s /id 666 /l APPLICATION /so %s /d \"%s\" > NUL 2>&1", prioritynames[ level ] . w_name, name, syslogbuffer );
268 Malloc( eventbuffer, char, needed + 4 );
269 sprintf( eventbuffer, "start /B EventCreate /t %s /id 666 /l APPLICATION /so %s /d \"%s\" > NUL 2>&1", prioritynames[ level ] . w_name, name, syslogbuffer );
270 system( eventbuffer );
271#else
272 syslog( level, "%s->%s:%d %s", file, func, line, syslogbuffer );
273#endif
274 FreeNoLog( syslogbuffer );
275 FreeNoLog( eventbuffer );
276 break ;
277 default:
278 fprintf( out, "%s:%jd:%s->%s:%d ", prioritynames[ level ] . c_name, (intmax_t)time( NULL ), file, func, line );
279 va_start (args, format);
280 vfprintf( out, format, args );
281 va_end( args );
282 fprintf( out, "\n" );
283 break ;
284 }
285 fflush( out );
286 }
287} /* _n_log( ... ) */
288
289
290
298int open_safe_logging( TS_LOG **log, char *pathname, char *opt )
299{
300
301 if( (*log) )
302 {
303
304 if( (*log) -> file )
305 return -1000; /* already open */
306
307 return FALSE;
308 }
309
310 if( !pathname )
311 return FALSE; /* no path/filename */
312
313 Malloc( (*log), TS_LOG, 1 );
314
315 if( !(*log) )
316 return FALSE;
317
318 pthread_mutex_init( &(*log) -> LOG_MUTEX, NULL );
319
320 (*log) -> file = fopen( pathname, opt );
321
322 if( !(*log) -> file )
323 return FALSE;
324
325 return TRUE;
326
327}/* open_safe_logging(...) */
328
329
330
337int write_safe_log( TS_LOG *log, char *pat, ... )
338{
339 /* argument list */
340 va_list arg;
341 char str[2048] = "" ;
342
343 if( !log )
344 return FALSE;
345
346 va_start( arg, pat );
347
348 vsnprintf( str, sizeof(str), pat, arg );
349
350 va_end( arg );
351
352 pthread_mutex_lock( &log -> LOG_MUTEX );
353 fprintf( log -> file, "%s", str );
354 fflush( log -> file );
355 pthread_mutex_unlock( &log -> LOG_MUTEX );
356
357 return TRUE;
358
359} /* write_safe_log( ... ) */
360
361
362
369{
370 if( !log )
371 return FALSE;
372
373 pthread_mutex_lock( &log -> LOG_MUTEX );
374 fflush( log -> file );
375 pthread_mutex_unlock( &log -> LOG_MUTEX );
376
377 pthread_mutex_destroy( &log -> LOG_MUTEX );
378
379 fclose( log -> file );
380
381 return TRUE;
382
383}/* close_safe_logging( ...) */
#define FreeNoLog(__ptr)
Free Handler without log.
Definition: n_common.h:268
#define Malloc(__ptr, __struct, __size)
Malloc Handler to get errors and set to 0.
Definition: n_common.h:183
#define __n_assert(__ptr, __ret)
macro to assert things
Definition: n_common.h:276
#define LOG_ALERT
action must be taken immediately
Definition: n_log.h:54
#define LOG_SYSJRNL
to sysjrnl
Definition: n_log.h:33
FILE * get_log_file(void)
return the current log_file
Definition: n_log.c:160
int write_safe_log(TS_LOG *log, char *pat,...)
write to a thread-safe logging file
Definition: n_log.c:337
int open_safe_logging(TS_LOG **log, char *pathname, char *opt)
Open a thread-safe logging file.
Definition: n_log.c:298
#define LOG_EMERG
system is unusable
Definition: n_log.h:52
char * open_sysjrnl(char *identity)
Open connection to syslog or create internals for event log.
Definition: n_log.c:64
#define LOG_FILE
internal, logging to file
Definition: n_log.h:29
void close_sysjrnl(void)
Close syslog connection or clean internals for event log.
Definition: n_log.c:83
#define LOG_DEBUG
debug-level messages
Definition: n_log.h:66
#define LOG_ERR
error conditions
Definition: n_log.h:58
#define LOG_STDERR
internal, default LOG_TYPE
Definition: n_log.h:31
#define LOG_CRIT
critical conditions
Definition: n_log.h:56
int close_safe_logging(TS_LOG *log)
close a thread-safe logging file
Definition: n_log.c:368
int set_log_file(char *file)
Set the logging to a file instead of stderr.
Definition: n_log.c:135
void set_log_level(const int log_level)
Set the global log level value ( static int LOG_LEVEL )
Definition: n_log.c:97
#define LOG_NOTICE
normal but significant condition
Definition: n_log.h:62
#define LOG_WARNING
warning conditions
Definition: n_log.h:60
#define LOG_NULL
no log output
Definition: n_log.h:27
#define LOG_INFO
informational
Definition: n_log.h:64
void _n_log(int level, const char *file, const char *func, int line, const char *format,...)
Logging function.
Definition: n_log.c:234
int get_log_level(void)
Get the global log level value.
Definition: n_log.c:123
ThreadSafe LOGging structure.
Definition: n_log.h:83
Common headers and low-level hugly functions & define.
static LOG_LEVELS prioritynames[]
array of log levels
Definition: n_log.c:33
char * proc_name
static proc name, for windows event log
Definition: n_log.c:56
int c_val
numeric value of log type
Definition: n_log.c:26
static int LOG_LEVEL
static global maximum wanted log level value
Definition: n_log.c:47
static int LOG_TYPE
static global logging type ( STDERR, FILE, SYSJRNL )
Definition: n_log.c:50
int vasprintf(char **strp, const char *fmt, va_list ap)
snprintf from a va_list, helper for asprintf
Definition: n_log.c:191
int asprintf(char *strp[], const char *fmt,...)
snprintf from a va_list
Definition: n_log.c:216
static FILE * log_file
static FILE handling if logging to file is enabled
Definition: n_log.c:53
char * w_name
event log value
Definition: n_log.c:28
char * c_name
string of log type
Definition: n_log.c:24
int _vscprintf_so(const char *format, va_list pargs)
compute the size of a string made with format 'fmt' and arguments in the va_list 'ap',...
Definition: n_log.c:172
internal struct to handle log types
Definition: n_log.c:22
Generic log system.