xref: /nrf52832-nimble/rt-thread/components/utilities/ulog/syslog/syslog.c (revision 104654410c56c573564690304ae786df310c91fc)
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