Imported Upstream version 1.37
[platform/upstream/connman.git] / src / log.c
1 /*
2  *
3  *  Connection Manager
4  *
5  *  Copyright (C) 2007-2013  Intel Corporation. All rights reserved.
6  *
7  *  This program is free software; you can redistribute it and/or modify
8  *  it under the terms of the GNU General Public License version 2 as
9  *  published by the Free Software Foundation.
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, write to the Free Software
18  *  Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
19  *
20  */
21
22 #ifdef HAVE_CONFIG_H
23 #include <config.h>
24 #endif
25
26 #include <stdio.h>
27 #include <unistd.h>
28 #include <stdarg.h>
29 #include <stdlib.h>
30 #include <string.h>
31 #include <syslog.h>
32 #include <dlfcn.h>
33 #include <signal.h>
34
35 #include "connman.h"
36
37 static const char *program_exec;
38 static const char *program_path;
39
40 /* This makes sure we always have a __debug section. */
41 CONNMAN_DEBUG_DEFINE(dummy);
42
43 /**
44  * connman_info:
45  * @format: format string
46  * @Varargs: list of arguments
47  *
48  * Output general information
49  */
50 void connman_info(const char *format, ...)
51 {
52         va_list ap;
53
54         va_start(ap, format);
55
56         vsyslog(LOG_INFO, format, ap);
57
58         va_end(ap);
59 }
60
61 /**
62  * connman_warn:
63  * @format: format string
64  * @Varargs: list of arguments
65  *
66  * Output warning messages
67  */
68 void connman_warn(const char *format, ...)
69 {
70         va_list ap;
71
72         va_start(ap, format);
73
74         vsyslog(LOG_WARNING, format, ap);
75
76         va_end(ap);
77 }
78
79 /**
80  * connman_error:
81  * @format: format string
82  * @varargs: list of arguments
83  *
84  * Output error messages
85  */
86 void connman_error(const char *format, ...)
87 {
88         va_list ap;
89
90         va_start(ap, format);
91
92         vsyslog(LOG_ERR, format, ap);
93
94         va_end(ap);
95 }
96
97 /**
98  * connman_debug:
99  * @format: format string
100  * @varargs: list of arguments
101  *
102  * Output debug message
103  */
104 void connman_debug(const char *format, ...)
105 {
106         va_list ap;
107
108         va_start(ap, format);
109
110         vsyslog(LOG_DEBUG, format, ap);
111
112         va_end(ap);
113 }
114
115 static void signal_handler(int signo)
116 {
117         connman_error("Aborting (signal %d) [%s]", signo, program_exec);
118
119         print_backtrace(program_path, program_exec, 2);
120
121         exit(EXIT_FAILURE);
122 }
123
124 static void signal_setup(sighandler_t handler)
125 {
126         struct sigaction sa;
127         sigset_t mask;
128
129         sigemptyset(&mask);
130         sa.sa_handler = handler;
131         sa.sa_mask = mask;
132         sa.sa_flags = 0;
133         sigaction(SIGBUS, &sa, NULL);
134         sigaction(SIGILL, &sa, NULL);
135         sigaction(SIGFPE, &sa, NULL);
136         sigaction(SIGSEGV, &sa, NULL);
137         sigaction(SIGABRT, &sa, NULL);
138         sigaction(SIGPIPE, &sa, NULL);
139 }
140
141 extern struct connman_debug_desc __start___debug[];
142 extern struct connman_debug_desc __stop___debug[];
143
144 static gchar **enabled = NULL;
145
146 static bool is_enabled(struct connman_debug_desc *desc)
147 {
148         int i;
149
150         if (!enabled)
151                 return false;
152
153         for (i = 0; enabled[i]; i++) {
154                 if (desc->name && g_pattern_match_simple(enabled[i],
155                                                         desc->name))
156                         return true;
157                 if (desc->file && g_pattern_match_simple(enabled[i],
158                                                         desc->file))
159                         return true;
160         }
161
162         return false;
163 }
164
165 void __connman_log_enable(struct connman_debug_desc *start,
166                                         struct connman_debug_desc *stop)
167 {
168         struct connman_debug_desc *desc;
169         const char *name = NULL, *file = NULL;
170
171         if (!start || !stop)
172                 return;
173
174         for (desc = start; desc < stop; desc++) {
175                 if (desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) {
176                         file = desc->file;
177                         name = desc->name;
178                         continue;
179                 }
180
181                 if (file || name) {
182                         if (g_strcmp0(desc->file, file) == 0) {
183                                 if (!desc->name)
184                                         desc->name = name;
185                         } else
186                                 file = NULL;
187                 }
188
189                 if (is_enabled(desc))
190                         desc->flags |= CONNMAN_DEBUG_FLAG_PRINT;
191         }
192 }
193
194 int __connman_log_init(const char *program, const char *debug,
195                 gboolean detach, gboolean backtrace,
196                 const char *program_name, const char *program_version)
197 {
198         static char path[PATH_MAX];
199         int option = LOG_NDELAY | LOG_PID;
200
201         program_exec = program;
202         program_path = getcwd(path, sizeof(path));
203
204         if (debug)
205                 enabled = g_strsplit_set(debug, ":, ", 0);
206
207         __connman_log_enable(__start___debug, __stop___debug);
208
209         if (!detach)
210                 option |= LOG_PERROR;
211
212         if (backtrace)
213                 signal_setup(signal_handler);
214
215         openlog(basename(program), option, LOG_DAEMON);
216
217         syslog(LOG_INFO, "%s version %s", program_name, program_version);
218
219         return 0;
220 }
221
222 void __connman_log_cleanup(gboolean backtrace)
223 {
224         syslog(LOG_INFO, "Exit");
225
226         closelog();
227
228         if (backtrace)
229                 signal_setup(SIG_DFL);
230
231         g_strfreev(enabled);
232 }