1
/***************************************************************************
3
* Copyright (c) 2000,2001,2002 BalaBit IT Ltd, Budapest, Hungary
5
* This program is free software; you can redistribute it and/or modify
6
* it under the terms of the GNU General Public License as published by
7
* the Free Software Foundation; either version 2 of the License, or
8
* (at your option) any later version.
10
* This program is distributed in the hope that it will be useful,
11
* but WITHOUT ANY WARRANTY; without even the implied warranty of
12
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13
* GNU General Public License for more details.
15
* You should have received a copy of the GNU General Public License
16
* along with this program; if not, write to the Free Software
17
* Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
19
* $Id: log.c,v 1.40.2.8 2003/09/16 19:40:28 sasa Exp $
23
* Last audited version: 1.7
26
***************************************************************************/
29
#include <zorp/thread.h>
30
#include <zorp/error.h>
41
#include <sys/types.h>
42
#ifdef HAVE_SYS_TIME_H
51
# include <sys/socket.h>
56
#define G_LOG_DOMAIN "Zorp"
58
#define SYSLOG_SOCKET "/dev/log"
60
GHashTable *class_hash = NULL;
61
GStaticRWLock log_lock = G_STATIC_RW_LOCK_INIT;
62
unsigned int verbose_level = 3;
63
unsigned int log_tags = 0;
64
gchar *logspec = NULL;
65
gchar *syslog_tag = NULL;
66
unsigned int syslog_fd = -1;
67
gboolean stderr_syslog = FALSE;
69
gchar fake_session_id[256] = "noname/nosession";
71
static GMainContext *context = NULL;
75
* This is a private reimplementation of syslog() as that one had a
76
* mysterious bug in it and my bug reports were ignored.
81
* @tag: program name used in log messages
83
* Analogous to openlog(), open the syslog() connection to local syslogd.
88
z_open_syslog(gchar *tag)
90
struct sockaddr_un s_un;
93
syslog_fd = socket(AF_UNIX, SOCK_STREAM, 0);
100
s_un.sun_family = AF_UNIX;
101
strcpy(s_un.sun_path, SYSLOG_SOCKET);
102
if (connect(syslog_fd, (struct sockaddr *) &s_un, sizeof(s_un)) == -1)
105
syslog_fd = socket(AF_UNIX, SOCK_DGRAM, 0);
106
if (connect(syslog_fd, (struct sockaddr *) &s_un, sizeof(s_un)) == -1)
118
* @syslog_fd: syslog connection to close
120
* Close the connection to the local syslogd. The syslog connection is
121
* specified by the @syslog_fd argument to avoid races.
123
* Returns: whether the operation was succesful
126
z_close_syslog(int syslog_fd)
138
* @pri: syslog priority
139
* @msg: syslog message
141
* Send the specified message to syslog.
144
z_send_syslog(gint pri, const gchar *msg)
150
gint len, rc = 0, attempt = 0;
152
static GStaticMutex lock = G_STATIC_MUTEX_INIT;
155
localtime_r(&now, &t);
157
strftime(timestamp, sizeof(timestamp), "%h %e %H:%M:%S", &t);
159
g_snprintf(buf, sizeof(buf), "<%d>%s %s[%d]: %s\n", pri, timestamp, syslog_tag, (int) getpid(), msg);
160
len = strlen(buf) + 1;
165
rc = write(sfd, buf, len);
166
if (sfd == -1 || (rc == -1 && errno != EINTR && errno != EAGAIN))
168
g_static_mutex_lock(&lock);
169
if (sfd == syslog_fd)
171
z_open_syslog(syslog_tag);
176
g_static_mutex_unlock(&lock);
179
while (rc == -1 && attempt <= 1);
185
z_close_syslog(int syslog_fd)
194
* @class: log message class
195
* @level: log message level
197
* Checks if a message with a given class/level combination would actually
198
* be written to the log. It can be used prior to constructing complex log
199
* messages to decide whether the messages need to be constucted at all.
200
* All results are cached, thus the second invocation will not parse the
201
* log specifications again.
203
* Returns: TRUE if the log would be written, FALSE otherwise
206
z_log_enabled(gchar *class, int level)
210
g_static_rw_lock_reader_lock(&log_lock);
213
g_static_rw_lock_reader_unlock(&log_lock);
216
verbose = GPOINTER_TO_UINT(g_hash_table_lookup(class_hash, class));
217
g_static_rw_lock_reader_unlock(&log_lock);
220
verbose = z_log_register_class(class);
223
g_static_rw_lock_writer_lock(&log_lock);
224
g_hash_table_insert(class_hash, class, GUINT_TO_POINTER(verbose + 1));
225
g_static_rw_lock_writer_unlock(&log_lock);
229
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_WARNING, "Invalid syntax in logspec line, class=%s", class);
230
/* hack to let this message out */
242
return (level <= verbose);
247
* @class: log message class
248
* @level: log message verbosity level
249
* @format: log message format specified in printf form
250
* @ap: format arguments va_list
252
* This function sends a message formatted as printf format string and
253
* arguments to the syslog. The associated class/level pair is checked
254
* whether the message really needs to be written.
257
z_logv(gchar *class, int level, gchar *format, va_list ap)
259
int saved_errno = errno;
261
if (z_log_enabled(class, level))
266
g_vsnprintf(msgbuf, sizeof(msgbuf), format, ap);
268
#if ZORPLIB_ENABLE_TRACE
269
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%p -> %s(%d): %s", g_thread_self(), class, level, msgbuf);
271
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%s(%d): %s", class, level, msgbuf);
276
g_logv(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, format, ap);
284
* @class: log message class
285
* @level: log message verbosity level
286
* @format: log message format specified in printf form
288
* This message is the same as z_logv() but format string and arguments
289
* are specified directly.
292
z_llog(gchar *class, int level, gchar *format, ...)
297
z_logv(class, level, format, l);
303
void z_log(gchar* session_id, gchar* class, int level, gchar* format, ...)
310
g_vsnprintf(msgbuf, sizeof(msgbuf), format, l);
312
g_log(G_LOG_DOMAIN, G_LOG_LEVEL_INFO, "%p -> %s(%d): %s", g_thread_self(), class, level, msgbuf);
314
if (session_id == NULL || *((char *) session_id) == 0)
315
z_llog(class, level, "(%s %s): ", format, z_log_session_id(session_id) , l);
317
z_llog(class, level, "(%s %s): ", format, (char *) session_id , l);
322
void z_proxy_log(ZProxy *self, gchar* class, int level, char* format, ...)
327
z_log(((ZProxy *)self)->session_id, class, level, format, l)
337
* @log_domain: GLIB log domain
338
* @log_flags: GLIB log flags
340
* @user_data: not used
342
* This function is registered as a GLib log handler and sends all GLIB
343
* messages to messages to syslog. Zorp itself does not use GLIB logging
344
* it calls z_log() directly.
347
z_log_func(const gchar *log_domain,
348
GLogLevelFlags log_flags,
349
const gchar *message,
353
if (log_flags & G_LOG_LEVEL_DEBUG)
355
else if (log_flags & G_LOG_LEVEL_WARNING)
357
else if (log_flags & G_LOG_LEVEL_ERROR)
360
z_send_syslog(pri | ZORP_SYSLOG_FACILITY, message);
365
/*+ log handler function to send Win32 debug message +*/
367
z_log_win32_debugmsg(const gchar *log_domain,
368
GLogLevelFlags log_flags,
369
const gchar *message,
372
OutputDebugString(message);
373
OutputDebugString("\n");
380
* @channel: the read end of the STDERR pipe
381
* @condition: the I/O condition triggering this callback
384
* This function is registered as a read callback of the STDERR pipe to
385
* fetch messages sent to stderr. It fetches messages line-by-line and
386
* uses z_log() to send messages to log.
388
* Returns: TRUE to indicate further reading is needed, FALSE otherwise
391
z_fetch_stderr(GIOChannel *channel, GIOCondition condition, gpointer arg)
394
GIOStatus status = G_IO_STATUS_NORMAL;
397
status = g_io_channel_read_line(channel, &line, NULL, NULL, &err);
401
case G_IO_STATUS_NORMAL:
402
z_log(NULL, CORE_STDERR, 3, "%s", line);
404
case G_IO_STATUS_AGAIN:
406
case G_IO_STATUS_EOF:
408
This message arrive when a program using Zorp library
411
z_log(NULL, CORE_STDERR, 4, "The program close its stderr. No further stderr logging will be performed.");
415
This message is attempt when zorplib cannot read from
416
program stderr stream.
418
z_log(NULL, CORE_STDERR, 3, "Cannot read from stderr; result='%s'", (err != NULL) ? ((err)->message) : ("Unknown error"));
427
* @fd: read side of the stderr pipe
429
* Creates the source watching the stderr pipe.
432
z_log_source_new(gint fd)
437
channel = g_io_channel_unix_new(fd);
438
g_io_channel_set_encoding(channel, NULL, NULL);
439
g_io_channel_set_flags(channel, G_IO_FLAG_NONBLOCK, NULL);
440
source = g_io_create_watch(channel, G_IO_IN);
441
g_source_set_callback(source, (GSourceFunc) z_fetch_stderr, NULL, NULL);
442
g_source_attach(source, context);
443
g_source_unref(source);
454
z_log_glob_match(const gchar *glob, const gchar *class)
459
p1 = strchr(glob, '.');
460
p2 = strchr(class, '.');
466
if (((len1 != 1) || (memcmp(glob, "*", 1) != 0)) &&
467
((len1 != len2) || memcmp(glob, class, len1) != 0))
472
p1 = strchr(glob, '.');
473
p2 = strchr(class, '.');
482
len2 = strlen(class);
483
if (((len1 != 1) || (memcmp(glob, "*", 1) != 0)) &&
484
((len1 != len2) || memcmp(glob, class, len1) != 0))
488
if (strlen(glob) > strlen(class))
494
* z_log_register_class:
495
* @class: message class
498
z_log_register_class(gchar *class)
500
const gchar *src = logspec;
501
gint level = verbose_level, new_level;
505
const gchar *glob, *num;
508
while (*src == ',' || *src == ' ')
512
while (isalnum((guchar) (*src)) || *src == '.' || *src == '*')
517
/* invalid log spec */
520
colon = (gchar *) src;
525
new_level = strtoul(num, &end, 10);
526
if (z_log_glob_match(glob, class))
530
while (*src && *src != ',')
539
* Clear the log-spec hash. It is called after changing the verbosity level.
540
* FIXME: this contains a race condition.
545
g_static_rw_lock_writer_lock(&log_lock);
546
g_hash_table_destroy(class_hash);
547
class_hash = g_hash_table_new(g_str_hash, g_str_equal);
548
g_static_rw_lock_writer_unlock(&log_lock);
553
* @session_id: default session_id
555
* This helper function is used by the z_log() macro to get the current
556
* session id. If the argument is NULL the session_id assigned to the
557
* current thread is used, otherwise the value of the argument is returned.
560
z_log_session_id(const gchar *session_id)
562
if (session_id == NULL || session_id[0] == 0)
564
ZThread *thread = z_thread_self();
566
return fake_session_id;
575
* @user_data: thread data pointer, assumed to point to the stderr fd
577
* STDERR reading thread function.
580
z_log_run(gpointer user_data)
582
GMainContext *c, *old_context;
583
gint *fd = (gint *)user_data;
585
old_context = context = g_main_context_new();
586
g_main_context_acquire(context);
587
z_log_source_new(*fd);
594
g_main_context_iteration(c, TRUE);
598
g_main_context_release(old_context);
599
g_main_context_unref(old_context);
605
* @ls: log specification
606
* @syslog_name: the program name to appear in syslogs
607
* @flags: log flags (ZLF_* macros)
609
* Initialize the logging subsystem according to the options
610
* in specified in the @flags parameter.
613
z_log_init(const gchar *ls, const gchar *syslog_name, guint flags)
615
logspec = (gchar *) (ls ? ls : "");
616
log_tags = !!(flags & ZLF_TAGS);
617
class_hash = g_hash_table_new(g_str_hash, g_str_equal);
619
if (flags & ZLF_SYSLOG)
626
z_open_syslog((char *)syslog_name);
627
g_log_set_handler(G_LOG_DOMAIN, 0xff, z_log_func, NULL);
629
if (flags & ZLF_STDERR)
634
This message is appear when cannot create
635
pipe. The possible couse is zorp weaok on fd.
637
z_log(NULL, CORE_ERROR, 3, "Error creating stderr-syslog pipe;");
640
stderr_syslog = TRUE;
643
if (grab[1] != 2 && grab[1] != 1)
646
if (~flags & ZLF_THREAD)
648
context = g_main_context_default();
649
if (!g_main_context_acquire(context))
651
context = g_main_context_new();
652
g_main_context_acquire(context);
654
g_main_context_ref(context);
655
z_log_source_new(grab[0]);
658
z_thread_new("Log thread", z_log_run, &grab[0]);
663
g_log_set_handler(G_LOG_DOMAIN, 0xff, z_log_win32_debugmsg, NULL);
672
* Deinitialize the logging subsystem.
685
g_static_rw_lock_writer_lock(&log_lock);
686
g_hash_table_destroy(class_hash);
688
g_static_rw_lock_writer_unlock(&log_lock);
689
z_close_syslog(syslog_fd);
693
g_main_context_wakeup(c);