1 /* -*- Mode: C; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 8 -*-
2  *
3  * Copyright (C) 2007 William Jon McCann <mccann@jhu.edu>
4  *
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.
9  *
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.
14  *
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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18  *
19  * Authors: William Jon McCann <mccann@jhu.edu>
20  *
21  */
22 
23 #include "config.h"
24 
25 #include <stdio.h>
26 #include <string.h>
27 #include <stdarg.h>
28 #include <unistd.h>
29 
30 #include <syslog.h>
31 
32 #include <glib.h>
33 #include <glib/gstdio.h>
34 
35 #include "ck-log.h"
36 
37 static gboolean initialized = FALSE;
38 static int      syslog_levels = (G_LOG_LEVEL_ERROR | G_LOG_LEVEL_CRITICAL | G_LOG_LEVEL_WARNING);
39 
40 static void
log_level_to_priority_and_prefix(GLogLevelFlags log_level,int * priorityp,const char ** prefixp)41 log_level_to_priority_and_prefix (GLogLevelFlags log_level,
42                                   int           *priorityp,
43                                   const char   **prefixp)
44 {
45         int         priority;
46         const char *prefix;
47 
48         /* Process the message prefix and priority */
49         switch (log_level & G_LOG_LEVEL_MASK) {
50         case G_LOG_FLAG_FATAL:
51                 priority = LOG_EMERG;
52                 prefix = "FATAL";
53                 break;
54         case G_LOG_LEVEL_ERROR:
55                 priority = LOG_ERR;
56                 prefix = "ERROR";
57                 break;
58         case G_LOG_LEVEL_CRITICAL:
59                 priority = LOG_CRIT;
60                 prefix = "CRITICAL";
61                 break;
62         case G_LOG_LEVEL_WARNING:
63                 priority = LOG_WARNING;
64                 prefix = "WARNING";
65                 break;
66         case G_LOG_LEVEL_MESSAGE:
67                 priority = LOG_NOTICE;
68                 prefix = "MESSAGE";
69                 break;
70         case G_LOG_LEVEL_INFO:
71                 priority = LOG_INFO;
72                 prefix = "INFO";
73                 break;
74         case G_LOG_LEVEL_DEBUG:
75                 /* if debug was requested then bump this up to ERROR
76                  * to ensure it is seen in a log */
77                 if (syslog_levels & G_LOG_LEVEL_DEBUG) {
78                         priority = LOG_WARNING;
79                 } else {
80                         priority = LOG_DEBUG;
81                 }
82                 prefix = "DEBUG";
83                 break;
84         default:
85                 priority = LOG_DEBUG;
86                 prefix = "UNKNOWN";
87                 break;
88         }
89 
90         if (priorityp != NULL) {
91                 *priorityp = priority;
92         }
93         if (prefixp != NULL) {
94                 *prefixp = prefix;
95         }
96 }
97 
98 void
ck_log_default_handler(const gchar * log_domain,GLogLevelFlags log_level,const gchar * message,gpointer unused_data)99 ck_log_default_handler (const gchar   *log_domain,
100                         GLogLevelFlags log_level,
101                         const gchar   *message,
102                         gpointer       unused_data)
103 {
104         GString     *gstring;
105         int          priority;
106         const char  *level_prefix;
107         char        *string;
108         gboolean     do_log;
109         gboolean     is_fatal;
110 
111         is_fatal = (log_level & G_LOG_FLAG_FATAL) != 0;
112 
113         do_log = (log_level & syslog_levels);
114         if (! do_log) {
115                 return;
116         }
117 
118         if (! initialized) {
119                 ck_log_init ();
120         }
121 
122         log_level_to_priority_and_prefix (log_level,
123                                           &priority,
124                                           &level_prefix);
125 
126         gstring = g_string_new (NULL);
127 
128         if (log_domain != NULL) {
129                 g_string_append (gstring, log_domain);
130                 g_string_append_c (gstring, '-');
131         }
132         g_string_append (gstring, level_prefix);
133 
134         g_string_append (gstring, ": ");
135         if (message == NULL) {
136                 g_string_append (gstring, "(NULL) message");
137         } else {
138                 g_string_append (gstring, message);
139         }
140         if (is_fatal) {
141                 g_string_append (gstring, "\naborting...\n");
142         } else {
143                 g_string_append (gstring, "\n");
144         }
145 
146         string = g_string_free (gstring, FALSE);
147 
148         syslog (priority, "%s", string);
149 
150         g_free (string);
151 }
152 
153 void
ck_log_toggle_debug(void)154 ck_log_toggle_debug (void)
155 {
156         if (syslog_levels & G_LOG_LEVEL_DEBUG) {
157                 g_debug ("Debugging disabled");
158                 syslog_levels &= ~G_LOG_LEVEL_DEBUG;
159         } else {
160                 syslog_levels |= G_LOG_LEVEL_DEBUG;
161                 g_debug ("Debugging enabled");
162         }
163 }
164 
165 void
ck_log_set_debug(gboolean debug)166 ck_log_set_debug (gboolean debug)
167 {
168         if (debug) {
169                 syslog_levels |= G_LOG_LEVEL_DEBUG;
170                 g_debug ("Debugging enabled");
171         } else {
172                 g_debug ("Debugging disabled");
173                 syslog_levels &= ~G_LOG_LEVEL_DEBUG;
174         }
175 }
176 
177 void
ck_log_init(void)178 ck_log_init (void)
179 {
180         const char *prg_name;
181         int         options;
182 
183         g_log_set_default_handler (ck_log_default_handler, NULL);
184 
185         prg_name = g_get_prgname ();
186 
187         options = LOG_PID;
188 #ifdef LOG_PERROR
189         options |= LOG_PERROR;
190 #endif
191 
192         openlog (prg_name, options, LOG_DAEMON);
193 
194         initialized = TRUE;
195 }
196 
197 void
ck_log_shutdown(void)198 ck_log_shutdown (void)
199 {
200         closelog ();
201         initialized = FALSE;
202 }
203 
204