blob: e81fe29fef66cd7cc1144eaf2971a003aaeb1cc8 [file] [log] [blame]
Benny Prijono9033e312005-11-21 02:08:39 +00001/* $Id$ */
2/*
3 * Copyright (C)2003-2006 Benny Prijono <benny@prijono.org>
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#include <pj/types.h>
20#include <pj/log.h>
21#include <pj/string.h>
22#include <pj/os.h>
Benny Prijono9033e312005-11-21 02:08:39 +000023#include <pj/compat/stdarg.h>
24
25#if PJ_LOG_MAX_LEVEL >= 1
26
27static int log_max_level = PJ_LOG_MAX_LEVEL;
28static pj_log_func *log_writer = &pj_log_write;
29static unsigned log_decor = PJ_LOG_HAS_TIME | PJ_LOG_HAS_MICRO_SEC |
30 PJ_LOG_HAS_SENDER | PJ_LOG_HAS_NEWLINE;
31
32#if PJ_LOG_USE_STACK_BUFFER==0
33static char log_buffer[PJ_LOG_MAX_SIZE];
34#endif
35
36PJ_DEF(void) pj_log_set_decor(unsigned decor)
37{
38 log_decor = decor;
39}
40
41PJ_DEF(unsigned) pj_log_get_decor(void)
42{
43 return log_decor;
44}
45
46PJ_DEF(void) pj_log_set_level(int level)
47{
48 log_max_level = level;
49}
50
51PJ_DEF(int) pj_log_get_level(void)
52{
53 return log_max_level;
54}
55
56PJ_DEF(void) pj_log_set_log_func( pj_log_func *func )
57{
58 log_writer = func;
59}
60
61PJ_DEF(pj_log_func*) pj_log_get_log_func(void)
62{
63 return log_writer;
64}
65
66PJ_DEF(void) pj_log( const char *sender, int level,
67 const char *format, va_list marker)
68{
69 pj_time_val now;
70 pj_parsed_time ptime;
71 char *pre;
72#if PJ_LOG_USE_STACK_BUFFER
73 char log_buffer[PJ_LOG_MAX_SIZE];
74#endif
Benny Prijonoccf95622006-02-07 18:48:01 +000075 int len, print_len;
Benny Prijono9033e312005-11-21 02:08:39 +000076
77 PJ_CHECK_STACK();
78
79 if (level > log_max_level)
80 return;
81
82 /* Get current date/time. */
83 pj_gettimeofday(&now);
84 pj_time_decode(&now, &ptime);
85
86 pre = log_buffer;
87 if (log_decor & PJ_LOG_HAS_DAY_NAME) {
88 static const char *wdays[] = { "Sun", "Mon", "Tue", "Wed",
89 "Thu", "Fri", "Sat"};
Benny Prijonoed811d72006-03-10 12:57:12 +000090 pj_ansi_strcpy(pre, wdays[ptime.wday]);
Benny Prijono9033e312005-11-21 02:08:39 +000091 pre += 3;
92 }
93 if (log_decor & PJ_LOG_HAS_YEAR) {
94 *pre++ = ' ';
95 pre += pj_utoa(ptime.year, pre);
96 }
97 if (log_decor & PJ_LOG_HAS_MONTH) {
98 *pre++ = '-';
99 pre += pj_utoa_pad(ptime.mon, pre, 2, '0');
100 }
101 if (log_decor & PJ_LOG_HAS_DAY_OF_MON) {
102 *pre++ = ' ';
103 pre += pj_utoa_pad(ptime.day, pre, 2, '0');
104 }
105 if (log_decor & PJ_LOG_HAS_TIME) {
106 *pre++ = ' ';
107 pre += pj_utoa_pad(ptime.hour, pre, 2, '0');
108 *pre++ = ':';
109 pre += pj_utoa_pad(ptime.min, pre, 2, '0');
110 *pre++ = ':';
111 pre += pj_utoa_pad(ptime.sec, pre, 2, '0');
112 }
113 if (log_decor & PJ_LOG_HAS_MICRO_SEC) {
114 *pre++ = '.';
115 pre += pj_utoa_pad(ptime.msec, pre, 3, '0');
116 }
117 if (log_decor & PJ_LOG_HAS_SENDER) {
118 enum { SENDER_WIDTH = 12 };
119 int sender_len = strlen(sender);
120 *pre++ = ' ';
121 if (sender_len <= SENDER_WIDTH) {
122 while (sender_len < SENDER_WIDTH)
123 *pre++ = ' ', ++sender_len;
124 while (*sender)
125 *pre++ = *sender++;
126 } else {
127 int i;
128 for (i=0; i<SENDER_WIDTH; ++i)
129 *pre++ = *sender++;
130 }
131 }
132
133 if (log_decor != 0 && log_decor != PJ_LOG_HAS_NEWLINE)
134 *pre++ = ' ';
135
136 len = pre - log_buffer;
137
138 /* Print the whole message to the string log_buffer. */
Benny Prijonoed811d72006-03-10 12:57:12 +0000139 print_len = pj_ansi_vsnprintf(pre, sizeof(log_buffer)-len, format,
140 marker);
Benny Prijonoccf95622006-02-07 18:48:01 +0000141 if (print_len < 0) {
Benny Prijono6e996dd2006-06-19 12:08:27 +0000142 level = 1;
Benny Prijonoed811d72006-03-10 12:57:12 +0000143 print_len = pj_ansi_snprintf(pre, sizeof(log_buffer)-len,
144 "<logging error: msg too long>");
Benny Prijonoccf95622006-02-07 18:48:01 +0000145 }
146 len = len + print_len;
Benny Prijono9cf138e2006-01-19 03:58:29 +0000147 if (len > 0 && len < sizeof(log_buffer)-2) {
148 if (log_decor & PJ_LOG_HAS_CR) {
149 log_buffer[len++] = '\r';
150 }
Benny Prijono9033e312005-11-21 02:08:39 +0000151 if (log_decor & PJ_LOG_HAS_NEWLINE) {
152 log_buffer[len++] = '\n';
153 }
154 log_buffer[len++] = '\0';
155 } else {
156 len = sizeof(log_buffer)-1;
Benny Prijono9cf138e2006-01-19 03:58:29 +0000157 if (log_decor & PJ_LOG_HAS_CR) {
158 log_buffer[sizeof(log_buffer)-3] = '\r';
159 }
Benny Prijono9033e312005-11-21 02:08:39 +0000160 if (log_decor & PJ_LOG_HAS_NEWLINE) {
161 log_buffer[sizeof(log_buffer)-2] = '\n';
162 }
163 log_buffer[sizeof(log_buffer)-1] = '\0';
164 }
165
166 if (log_writer)
167 (*log_writer)(level, log_buffer, len);
168}
169
170PJ_DEF(void) pj_log_0(const char *obj, const char *format, ...)
171{
172 va_list arg;
173 va_start(arg, format);
174 pj_log(obj, 0, format, arg);
175 va_end(arg);
176}
177
178PJ_DEF(void) pj_log_1(const char *obj, const char *format, ...)
179{
180 va_list arg;
181 va_start(arg, format);
182 pj_log(obj, 1, format, arg);
183 va_end(arg);
184}
185#endif /* PJ_LOG_MAX_LEVEL >= 1 */
186
187#if PJ_LOG_MAX_LEVEL >= 2
188PJ_DEF(void) pj_log_2(const char *obj, const char *format, ...)
189{
190 va_list arg;
191 va_start(arg, format);
192 pj_log(obj, 2, format, arg);
193 va_end(arg);
194}
195#endif
196
197#if PJ_LOG_MAX_LEVEL >= 3
198PJ_DEF(void) pj_log_3(const char *obj, const char *format, ...)
199{
200 va_list arg;
201 va_start(arg, format);
202 pj_log(obj, 3, format, arg);
203 va_end(arg);
204}
205#endif
206
207#if PJ_LOG_MAX_LEVEL >= 4
208PJ_DEF(void) pj_log_4(const char *obj, const char *format, ...)
209{
210 va_list arg;
211 va_start(arg, format);
212 pj_log(obj, 4, format, arg);
213 va_end(arg);
214}
215#endif
216
217#if PJ_LOG_MAX_LEVEL >= 5
218PJ_DEF(void) pj_log_5(const char *obj, const char *format, ...)
219{
220 va_list arg;
221 va_start(arg, format);
222 pj_log(obj, 5, format, arg);
223 va_end(arg);
224}
225#endif
226
227#if PJ_LOG_MAX_LEVEL >= 6
228PJ_DEF(void) pj_log_6(const char *obj, const char *format, ...)
229{
230 va_list arg;
231 va_start(arg, format);
232 pj_log(obj, 6, format, arg);
233 va_end(arg);
234}
235#endif
236