Tizen 2.1 base
[framework/system/dlog.git] / log.c
1 /*
2  * DLOG
3  * Copyright (c) 2005-2008, The Android Open Source Project
4  * Copyright (c) 2012-2013 Samsung Electronics Co., Ltd.
5  *
6  * Licensed under the Apache License, Version 2.0 (the License);
7  * you may not use this file except in compliance with the License.
8  * You may obtain a copy of the License at
9  *
10  *     http://www.apache.org/licenses/LICENSE-2.0
11  *
12  * Unless required by applicable law or agreed to in writing, software
13  * distributed under the License is distributed on an "AS IS" BASIS,
14  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15  * See the License for the specific language governing permissions and
16  * limitations under the License.
17  */
18 #include <pthread.h>
19 #include <stdlib.h>
20 #include <string.h>
21 #include <stdarg.h>
22 #include <fcntl.h>
23 #include <sys/uio.h>
24 #include <stdio.h>
25 #include <errno.h>
26 #include <dlog.h>
27 #ifdef SD_JOURNAL_SUPPORT
28 #include <syslog.h>
29 #include <systemd/sd-journal.h>
30 #endif
31 #define LOG_BUF_SIZE    1024
32
33 #define LOG_MAIN        "log_main"
34 #define LOG_RADIO       "log_radio"
35 #define LOG_SYSTEM      "log_system"
36 #define LOG_APPS        "log_apps"
37
38 static int log_fds[(int)LOG_ID_MAX] = { -1, -1, -1, -1 };
39
40 static int g_logging_on = 1;
41 static int g_dlog_level = DLOG_SILENT;
42
43 static int __dlog_init(log_id_t, log_priority, const char *tag, const char *msg);
44 static int (*write_to_log)(log_id_t, log_priority, const char *tag, const char *msg) = __dlog_init;
45 static pthread_mutex_t log_init_lock = PTHREAD_MUTEX_INITIALIZER;
46 static int __write_to_log_null(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
47 {
48         return -1;
49 }
50 static int __write_to_log_kernel(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
51 {
52         ssize_t ret;
53         int log_fd;
54         struct iovec vec[3];
55
56         if (log_id < LOG_ID_APPS) {
57                 if(prio < g_dlog_level) {
58                         return 0;
59                 }
60         } else if (LOG_ID_MAX <= log_id) {
61                 return 0;
62         }
63         if (log_id < LOG_ID_MAX)
64                 log_fd = log_fds[log_id];
65         else
66                 return -1; // for TC
67
68         if (!tag)
69                 tag = "";
70
71         if (!msg)
72                 return -1;
73
74         vec[0].iov_base = (unsigned char *) &prio;
75         vec[0].iov_len  = 1;
76         vec[1].iov_base = (void *) tag;
77         vec[1].iov_len  = strlen(tag) + 1;
78         vec[2].iov_base = (void *) msg;
79         vec[2].iov_len  = strlen(msg) + 1;
80
81         ret = writev(log_fd, vec, 3);
82
83         return ret;
84 }
85 static char dlog_pri_to_char (log_priority pri)
86 {
87         switch (pri) {
88                 case DLOG_VERBOSE:       return 'V';
89                 case DLOG_DEBUG:         return 'D';
90                 case DLOG_INFO:          return 'I';
91                 case DLOG_WARN:          return 'W';
92                 case DLOG_ERROR:         return 'E';
93                 case DLOG_FATAL:         return 'F';
94                 case DLOG_SILENT:        return 'S';
95
96                 case DLOG_DEFAULT:
97                 case DLOG_UNKNOWN:
98                 default:
99                                                                  return '?';
100         }
101 }
102 #ifdef SD_JOURNAL_SUPPORT
103 static int dlog_pri_to_journal_pri(log_priority prio)
104 {
105         int journal_prio = LOG_DEBUG;
106
107         switch(prio) {
108         case DLOG_UNKNOWN:
109         case DLOG_DEFAULT:
110         case DLOG_VERBOSE:
111                 journal_prio = LOG_DEBUG;
112                 break;
113         case DLOG_DEBUG:
114                 journal_prio = LOG_DEBUG;
115                 break;
116         case DLOG_INFO:
117                 journal_prio = LOG_INFO;
118                 break;
119         case DLOG_WARN:
120                 journal_prio = LOG_WARNING;
121                 break;
122         case DLOG_ERROR:
123                 journal_prio = LOG_ERR;
124                 break;
125         case DLOG_FATAL:
126                 journal_prio = LOG_CRIT;
127                 break;
128         case DLOG_SILENT:
129         default:
130                 journal_prio = -1;
131                 break;
132         }
133         return journal_prio;
134 }
135 static int __write_to_log_sd_journal_print(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
136 {
137         ssize_t ret;
138         int log_fd;
139
140         if (log_id < LOG_ID_APPS) {
141                 if(prio < g_dlog_level) {
142                         return 0;
143                 }
144         } else if (LOG_ID_MAX <= log_id) {
145                 return 0;
146         }
147         if (log_id < LOG_ID_MAX)
148                 log_fd = log_fds[log_id];
149         else
150                 return -1;
151         return sd_journal_print(dlog_pri_to_journal_pri(prio), "%c %s: %s",dlog_pri_to_char(prio), tag, msg);
152 }
153 #endif
154 void init_dlog_level(void)
155 {
156         char *dlog_level_env;
157         char *logging_mode_env;
158         if (g_logging_on) {
159                 logging_mode_env = getenv("TIZEN_PLATFORMLOGGING_MODE");
160                 if (!logging_mode_env)
161                                 g_logging_on = 0;
162                         else
163                                 g_logging_on = atoi(logging_mode_env);
164         }
165         if (g_logging_on) {
166                 dlog_level_env = getenv("TIZEN_DLOG_LEVEL");
167                 if (!dlog_level_env) {
168                         g_dlog_level = 8;
169                 } else {
170                         g_dlog_level = atoi(dlog_level_env);
171                 }
172         } else
173                 g_dlog_level = 8;
174 }
175 static int __dlog_init(log_id_t log_id, log_priority prio, const char *tag, const char *msg)
176 {
177         pthread_mutex_lock(&log_init_lock);
178         // get filtering info
179         // open device
180         if (write_to_log == __dlog_init) {
181                 init_dlog_level();
182
183                 log_fds[LOG_ID_MAIN] = open("/dev/"LOG_MAIN, O_WRONLY);
184                 log_fds[LOG_ID_RADIO] = open("/dev/"LOG_RADIO, O_WRONLY);
185                 log_fds[LOG_ID_SYSTEM] = open("/dev/"LOG_SYSTEM, O_WRONLY);
186                 log_fds[LOG_ID_APPS] = open("/dev/"LOG_APPS, O_WRONLY);
187
188                 if (log_fds[LOG_ID_MAIN] < 0 || log_fds[LOG_ID_RADIO] < 0) {
189                         fprintf(stderr, "open log dev is failed\n");
190                         write_to_log = __write_to_log_null;
191                 } else {
192 #ifdef SD_JOURNAL_SUPPORT
193                         write_to_log = __write_to_log_sd_journal_print;
194 #else
195                         write_to_log = __write_to_log_kernel;
196 #endif
197                 }
198
199                 if (log_fds[LOG_ID_SYSTEM] < 0)
200                         log_fds[LOG_ID_SYSTEM] = log_fds[LOG_ID_MAIN];
201
202                 if (log_fds[LOG_ID_APPS] < 0)
203                         log_fds[LOG_ID_APPS] = log_fds[LOG_ID_MAIN];
204         }
205         pthread_mutex_unlock(&log_init_lock);
206         return write_to_log(log_id, prio, tag, msg);
207 }
208
209 int __dlog_vprint(log_id_t log_id, int prio, const char *tag, const char *fmt, va_list ap)
210 {
211         char buf[LOG_BUF_SIZE];
212
213         vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
214
215         return write_to_log(log_id, prio, tag, buf);
216 }
217
218 int __dlog_print(log_id_t log_id, int prio, const char *tag, const char *fmt, ...)
219 {
220         va_list ap;
221         char buf[LOG_BUF_SIZE];
222
223         va_start(ap, fmt);
224         vsnprintf(buf, LOG_BUF_SIZE, fmt, ap);
225         va_end(ap);
226
227         return write_to_log(log_id, prio, tag, buf);
228 }
229 int _get_logging_on(void)
230 {
231         return g_logging_on;
232 }