1*10465441SEvalZero /*
2*10465441SEvalZero * Copyright (c) 2006-2018, RT-Thread Development Team
3*10465441SEvalZero *
4*10465441SEvalZero * SPDX-License-Identifier: Apache-2.0
5*10465441SEvalZero *
6*10465441SEvalZero * Change Logs:
7*10465441SEvalZero * Date Author Notes
8*10465441SEvalZero * 2018-09-07 armink the first version
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero #include <stdarg.h>
12*10465441SEvalZero #include <ulog.h>
13*10465441SEvalZero #include <rthw.h>
14*10465441SEvalZero #include "syslog.h"
15*10465441SEvalZero
16*10465441SEvalZero #ifdef ULOG_OUTPUT_FLOAT
17*10465441SEvalZero #include <stdio.h>
18*10465441SEvalZero #endif
19*10465441SEvalZero
20*10465441SEvalZero /*
21*10465441SEvalZero * reference:
22*10465441SEvalZero * http://pubs.opengroup.org/onlinepubs/7908799/xsh/syslog.h.html
23*10465441SEvalZero * https://www.gnu.org/software/libc/manual/html_node/Submitting-Syslog-Messages.html
24*10465441SEvalZero * http://man7.org/linux/man-pages/man3/syslog.3.html
25*10465441SEvalZero */
26*10465441SEvalZero
27*10465441SEvalZero #ifdef ULOG_USING_SYSLOG
28*10465441SEvalZero
29*10465441SEvalZero #include <sys/time.h>
30*10465441SEvalZero
31*10465441SEvalZero #ifndef ULOG_SYSLOG_IDENT_MAX_LEN
32*10465441SEvalZero #define ULOG_SYSLOG_IDENT_MAX_LEN ULOG_FILTER_TAG_MAX_LEN
33*10465441SEvalZero #endif
34*10465441SEvalZero
35*10465441SEvalZero static char local_ident[ULOG_SYSLOG_IDENT_MAX_LEN + 1];
36*10465441SEvalZero static int local_facility = LOG_USER;
37*10465441SEvalZero static int local_option = LOG_USER;
38*10465441SEvalZero static rt_bool_t is_open = RT_FALSE;
39*10465441SEvalZero
40*10465441SEvalZero /**
41*10465441SEvalZero * open connection to syslog
42*10465441SEvalZero *
43*10465441SEvalZero * @param ident is an arbitrary identification string which future syslog invocations will prefix to each message.
44*10465441SEvalZero * @param option is not using on ulog.
45*10465441SEvalZero * @param facility is the default facility code for this connection.
46*10465441SEvalZero */
openlog(const char * ident,int option,int facility)47*10465441SEvalZero void openlog(const char *ident, int option, int facility)
48*10465441SEvalZero {
49*10465441SEvalZero rt_base_t level;
50*10465441SEvalZero
51*10465441SEvalZero ulog_init();
52*10465441SEvalZero
53*10465441SEvalZero level = rt_hw_interrupt_disable();
54*10465441SEvalZero
55*10465441SEvalZero rt_memset(local_ident, 0, sizeof(local_ident));
56*10465441SEvalZero if (ident)
57*10465441SEvalZero {
58*10465441SEvalZero rt_strncpy(local_ident, ident, ULOG_SYSLOG_IDENT_MAX_LEN);
59*10465441SEvalZero }
60*10465441SEvalZero else
61*10465441SEvalZero {
62*10465441SEvalZero rt_strncpy(local_ident, "rtt", ULOG_SYSLOG_IDENT_MAX_LEN);
63*10465441SEvalZero }
64*10465441SEvalZero
65*10465441SEvalZero local_option = option;
66*10465441SEvalZero
67*10465441SEvalZero if (facility)
68*10465441SEvalZero {
69*10465441SEvalZero local_facility = facility;
70*10465441SEvalZero }
71*10465441SEvalZero else
72*10465441SEvalZero {
73*10465441SEvalZero /* default facility is LOG_USER */
74*10465441SEvalZero local_facility = LOG_USER;
75*10465441SEvalZero }
76*10465441SEvalZero /* output all level log */
77*10465441SEvalZero setlogmask(LOG_UPTO(LOG_DEBUG));
78*10465441SEvalZero
79*10465441SEvalZero is_open = RT_TRUE;
80*10465441SEvalZero
81*10465441SEvalZero rt_hw_interrupt_enable(level);
82*10465441SEvalZero
83*10465441SEvalZero }
84*10465441SEvalZero
85*10465441SEvalZero /**
86*10465441SEvalZero * This is functionally identical to syslog.
87*10465441SEvalZero *
88*10465441SEvalZero * @param priority log priority, can be generated by the macro LOG_MAKEPRI
89*10465441SEvalZero * @param format log format
90*10465441SEvalZero * @param args log arguments
91*10465441SEvalZero */
vsyslog(int priority,const char * format,va_list args)92*10465441SEvalZero void vsyslog(int priority, const char *format, va_list args)
93*10465441SEvalZero {
94*10465441SEvalZero if (LOG_FAC(priority) == 0)
95*10465441SEvalZero {
96*10465441SEvalZero /* using local facility */
97*10465441SEvalZero priority |= local_facility;
98*10465441SEvalZero }
99*10465441SEvalZero
100*10465441SEvalZero ulog_voutput(priority, local_ident, RT_TRUE, format, args);
101*10465441SEvalZero }
102*10465441SEvalZero
103*10465441SEvalZero /**
104*10465441SEvalZero * generates a log message
105*10465441SEvalZero *
106*10465441SEvalZero * @param priority log priority, can be generated by the macro LOG_MAKEPRI
107*10465441SEvalZero * @param format log format, like printf()
108*10465441SEvalZero */
syslog(int priority,const char * format,...)109*10465441SEvalZero void syslog(int priority, const char *format, ...)
110*10465441SEvalZero {
111*10465441SEvalZero va_list args;
112*10465441SEvalZero
113*10465441SEvalZero if (!is_open)
114*10465441SEvalZero {
115*10465441SEvalZero openlog(0, 0, 0);
116*10465441SEvalZero }
117*10465441SEvalZero /* args point to the first variable parameter */
118*10465441SEvalZero va_start(args, format);
119*10465441SEvalZero
120*10465441SEvalZero vsyslog(priority, format, args);
121*10465441SEvalZero
122*10465441SEvalZero va_end(args);
123*10465441SEvalZero }
124*10465441SEvalZero
125*10465441SEvalZero /**
126*10465441SEvalZero * close the syslog
127*10465441SEvalZero */
closelog(void)128*10465441SEvalZero void closelog(void)
129*10465441SEvalZero {
130*10465441SEvalZero ulog_deinit();
131*10465441SEvalZero
132*10465441SEvalZero is_open = RT_FALSE;
133*10465441SEvalZero }
134*10465441SEvalZero
135*10465441SEvalZero /**
136*10465441SEvalZero * set log priority mask
137*10465441SEvalZero *
138*10465441SEvalZero * @param mask The log priority mask which generate by macro LOG_MASK and LOG_UPTO.
139*10465441SEvalZero *
140*10465441SEvalZero * @return This function returns the previous log priority mask.
141*10465441SEvalZero */
setlogmask(int mask)142*10465441SEvalZero int setlogmask(int mask)
143*10465441SEvalZero {
144*10465441SEvalZero static int old_mask = 0;
145*10465441SEvalZero int return_mask = old_mask;
146*10465441SEvalZero
147*10465441SEvalZero ulog_tag_lvl_filter_set(local_ident, mask);
148*10465441SEvalZero
149*10465441SEvalZero old_mask = mask;
150*10465441SEvalZero
151*10465441SEvalZero return return_mask;
152*10465441SEvalZero }
153*10465441SEvalZero
get_month_str(uint8_t month)154*10465441SEvalZero static const char *get_month_str(uint8_t month)
155*10465441SEvalZero {
156*10465441SEvalZero switch(month)
157*10465441SEvalZero {
158*10465441SEvalZero case 1: return "Jan";
159*10465441SEvalZero case 2: return "Feb";
160*10465441SEvalZero case 3: return "Mar";
161*10465441SEvalZero case 4: return "Apr";
162*10465441SEvalZero case 5: return "May";
163*10465441SEvalZero case 6: return "June";
164*10465441SEvalZero case 7: return "July";
165*10465441SEvalZero case 8: return "Aug";
166*10465441SEvalZero case 9: return "Sept";
167*10465441SEvalZero case 10: return "Oct";
168*10465441SEvalZero case 11: return "Nov";
169*10465441SEvalZero case 12: return "Dec";
170*10465441SEvalZero default: return "Unknown";
171*10465441SEvalZero }
172*10465441SEvalZero }
173*10465441SEvalZero
syslog_formater(char * log_buf,int level,const char * tag,rt_bool_t newline,const char * format,va_list args)174*10465441SEvalZero RT_WEAK rt_size_t syslog_formater(char *log_buf, int level, const char *tag, rt_bool_t newline, const char *format, va_list args)
175*10465441SEvalZero {
176*10465441SEvalZero extern size_t ulog_strcpy(size_t cur_len, char *dst, const char *src);
177*10465441SEvalZero
178*10465441SEvalZero rt_size_t log_len = 0, newline_len = rt_strlen(ULOG_NEWLINE_SIGN);
179*10465441SEvalZero int fmt_result;
180*10465441SEvalZero
181*10465441SEvalZero RT_ASSERT(log_buf);
182*10465441SEvalZero RT_ASSERT(LOG_PRI(level) <= LOG_DEBUG);
183*10465441SEvalZero RT_ASSERT(tag);
184*10465441SEvalZero RT_ASSERT(format);
185*10465441SEvalZero
186*10465441SEvalZero /* add time and priority (level) info */
187*10465441SEvalZero {
188*10465441SEvalZero time_t now = time(RT_NULL);
189*10465441SEvalZero struct tm *tm, tm_tmp;
190*10465441SEvalZero
191*10465441SEvalZero tm = gmtime_r(&now, &tm_tmp);
192*10465441SEvalZero
193*10465441SEvalZero #ifdef ULOG_OUTPUT_LEVEL
194*10465441SEvalZero rt_snprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, "<%d>%s%3d %02d:%02d:%02d", level,
195*10465441SEvalZero get_month_str(tm->tm_mon + 1), tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rt_tick_get() % 1000);
196*10465441SEvalZero #else
197*10465441SEvalZero rt_snprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, "%s%3d %02d:%02d:%02d",
198*10465441SEvalZero get_month_str(tm->tm_mon + 1), tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec, rt_tick_get() % 1000);
199*10465441SEvalZero #endif /* ULOG_OUTPUT_LEVEL */
200*10465441SEvalZero
201*10465441SEvalZero log_len += rt_strlen(log_buf + log_len);
202*10465441SEvalZero }
203*10465441SEvalZero
204*10465441SEvalZero #ifdef ULOG_OUTPUT_TAG
205*10465441SEvalZero /* add identification (tag) info */
206*10465441SEvalZero {
207*10465441SEvalZero log_len += ulog_strcpy(log_len, log_buf + log_len, " ");
208*10465441SEvalZero log_len += ulog_strcpy(log_len, log_buf + log_len, tag);
209*10465441SEvalZero }
210*10465441SEvalZero #endif /* ULOG_OUTPUT_TAG */
211*10465441SEvalZero
212*10465441SEvalZero #ifdef ULOG_OUTPUT_THREAD_NAME
213*10465441SEvalZero /* add thread info */
214*10465441SEvalZero {
215*10465441SEvalZero log_len += ulog_strcpy(log_len, log_buf + log_len, " ");
216*10465441SEvalZero /* is not in interrupt context */
217*10465441SEvalZero if (rt_interrupt_get_nest() == 0)
218*10465441SEvalZero {
219*10465441SEvalZero log_len += ulog_strcpy(log_len, log_buf + log_len, rt_thread_self()->name);
220*10465441SEvalZero }
221*10465441SEvalZero else
222*10465441SEvalZero {
223*10465441SEvalZero log_len += ulog_strcpy(log_len, log_buf + log_len, "ISR");
224*10465441SEvalZero }
225*10465441SEvalZero }
226*10465441SEvalZero #endif /* ULOG_OUTPUT_THREAD_NAME */
227*10465441SEvalZero
228*10465441SEvalZero log_len += ulog_strcpy(log_len, log_buf + log_len, ": ");
229*10465441SEvalZero
230*10465441SEvalZero #ifdef ULOG_OUTPUT_FLOAT
231*10465441SEvalZero fmt_result = vsnprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, format, args);
232*10465441SEvalZero #else
233*10465441SEvalZero fmt_result = rt_vsnprintf(log_buf + log_len, ULOG_LINE_BUF_SIZE - log_len, format, args);
234*10465441SEvalZero #endif /* ULOG_OUTPUT_FLOAT */
235*10465441SEvalZero
236*10465441SEvalZero /* calculate log length */
237*10465441SEvalZero if ((log_len + fmt_result <= ULOG_LINE_BUF_SIZE) && (fmt_result > -1))
238*10465441SEvalZero {
239*10465441SEvalZero log_len += fmt_result;
240*10465441SEvalZero }
241*10465441SEvalZero else
242*10465441SEvalZero {
243*10465441SEvalZero /* using max length */
244*10465441SEvalZero log_len = ULOG_LINE_BUF_SIZE;
245*10465441SEvalZero }
246*10465441SEvalZero
247*10465441SEvalZero /* overflow check and reserve some space for newline sign */
248*10465441SEvalZero if (log_len + newline_len > ULOG_LINE_BUF_SIZE)
249*10465441SEvalZero {
250*10465441SEvalZero /* using max length */
251*10465441SEvalZero log_len = ULOG_LINE_BUF_SIZE;
252*10465441SEvalZero /* reserve some space for newline sign */
253*10465441SEvalZero log_len -= newline_len;
254*10465441SEvalZero }
255*10465441SEvalZero
256*10465441SEvalZero /* package newline sign */
257*10465441SEvalZero if (newline)
258*10465441SEvalZero {
259*10465441SEvalZero log_len += ulog_strcpy(log_len, log_buf + log_len, ULOG_NEWLINE_SIGN);
260*10465441SEvalZero }
261*10465441SEvalZero
262*10465441SEvalZero return log_len;
263*10465441SEvalZero }
264*10465441SEvalZero
265*10465441SEvalZero #endif /* ULOG_USING_SYSLOG */
266