Imported Upstream version 1.35
[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 #define _GNU_SOURCE
27 #include <stdio.h>
28 #include <unistd.h>
29 #include <stdarg.h>
30 #include <stdlib.h>
31 #include <string.h>
32 #include <syslog.h>
33 #include <dlfcn.h>
34
35 #include "connman.h"
36
37 static const char *program_exec;
38 static const char *program_path;
39
40 /**
41  * connman_info:
42  * @format: format string
43  * @Varargs: list of arguments
44  *
45  * Output general information
46  */
47 void connman_info(const char *format, ...)
48 {
49         va_list ap;
50
51         va_start(ap, format);
52
53         vsyslog(LOG_INFO, format, ap);
54
55         va_end(ap);
56 }
57
58 /**
59  * connman_warn:
60  * @format: format string
61  * @Varargs: list of arguments
62  *
63  * Output warning messages
64  */
65 void connman_warn(const char *format, ...)
66 {
67         va_list ap;
68
69         va_start(ap, format);
70
71         vsyslog(LOG_WARNING, format, ap);
72
73         va_end(ap);
74 }
75
76 /**
77  * connman_error:
78  * @format: format string
79  * @varargs: list of arguments
80  *
81  * Output error messages
82  */
83 void connman_error(const char *format, ...)
84 {
85         va_list ap;
86
87         va_start(ap, format);
88
89         vsyslog(LOG_ERR, format, ap);
90
91         va_end(ap);
92 }
93
94 /**
95  * connman_debug:
96  * @format: format string
97  * @varargs: list of arguments
98  *
99  * Output debug message
100  */
101 void connman_debug(const char *format, ...)
102 {
103         va_list ap;
104
105         va_start(ap, format);
106
107         vsyslog(LOG_DEBUG, format, ap);
108
109         va_end(ap);
110 }
111
112 static void signal_handler(int signo)
113 {
114         connman_error("Aborting (signal %d) [%s]", signo, program_exec);
115
116         print_backtrace(program_path, program_exec, 2);
117
118         exit(EXIT_FAILURE);
119 }
120
121 static void signal_setup(sighandler_t handler)
122 {
123         struct sigaction sa;
124         sigset_t mask;
125
126         sigemptyset(&mask);
127         sa.sa_handler = handler;
128         sa.sa_mask = mask;
129         sa.sa_flags = 0;
130         sigaction(SIGBUS, &sa, NULL);
131         sigaction(SIGILL, &sa, NULL);
132         sigaction(SIGFPE, &sa, NULL);
133         sigaction(SIGSEGV, &sa, NULL);
134         sigaction(SIGABRT, &sa, NULL);
135         sigaction(SIGPIPE, &sa, NULL);
136 }
137
138 extern struct connman_debug_desc __start___debug[];
139 extern struct connman_debug_desc __stop___debug[];
140
141 static gchar **enabled = NULL;
142
143 static bool is_enabled(struct connman_debug_desc *desc)
144 {
145         int i;
146
147         if (!enabled)
148                 return false;
149
150         for (i = 0; enabled[i]; i++) {
151                 if (desc->name && g_pattern_match_simple(enabled[i],
152                                                         desc->name))
153                         return true;
154                 if (desc->file && g_pattern_match_simple(enabled[i],
155                                                         desc->file))
156                         return true;
157         }
158
159         return false;
160 }
161
162 void __connman_log_enable(struct connman_debug_desc *start,
163                                         struct connman_debug_desc *stop)
164 {
165         struct connman_debug_desc *desc;
166         const char *name = NULL, *file = NULL;
167
168         if (!start || !stop)
169                 return;
170
171         for (desc = start; desc < stop; desc++) {
172                 if (desc->flags & CONNMAN_DEBUG_FLAG_ALIAS) {
173                         file = desc->file;
174                         name = desc->name;
175                         continue;
176                 }
177
178                 if (file || name) {
179                         if (g_strcmp0(desc->file, file) == 0) {
180                                 if (!desc->name)
181                                         desc->name = name;
182                         } else
183                                 file = NULL;
184                 }
185
186                 if (is_enabled(desc))
187                         desc->flags |= CONNMAN_DEBUG_FLAG_PRINT;
188         }
189 }
190
191 int __connman_log_init(const char *program, const char *debug,
192                 gboolean detach, gboolean backtrace,
193                 const char *program_name, const char *program_version)
194 {
195         static char path[PATH_MAX];
196         int option = LOG_NDELAY | LOG_PID;
197
198         program_exec = program;
199         program_path = getcwd(path, sizeof(path));
200
201         if (debug)
202                 enabled = g_strsplit_set(debug, ":, ", 0);
203
204         __connman_log_enable(__start___debug, __stop___debug);
205
206         if (!detach)
207                 option |= LOG_PERROR;
208
209         if (backtrace)
210                 signal_setup(signal_handler);
211
212         openlog(basename(program), option, LOG_DAEMON);
213
214         syslog(LOG_INFO, "%s version %s", program_name, program_version);
215
216         return 0;
217 }
218
219 void __connman_log_cleanup(gboolean backtrace)
220 {
221         syslog(LOG_INFO, "Exit");
222
223         closelog();
224
225         if (backtrace)
226                 signal_setup(SIG_DFL);
227
228         g_strfreev(enabled);
229 }