3b8bf2c97ac0e859edfc54ae5eb94b45e1223d66
[profile/ivi/ico-uxf-utilities.git] / src / ico_log.c
1 /*
2  * Copyright (c) 2013, TOYOTA MOTOR CORPORATION.
3  *
4  * This program is licensed under the terms and conditions of the
5  * Apache License, version 2.0.  The full text of the Apache License is at
6  * http://www.apache.org/licenses/LICENSE-2.0
7  *
8  */
9
10 /*------------------------------------------------------------------------*/
11 /**
12  *  @file   ico_log.c
13  *
14  *  @brief
15  */
16 /*------------------------------------------------------------------------*/
17
18 #include <stdbool.h>
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <stdarg.h>
22 #include <unistd.h>
23 #include <string.h>
24 #include <sys/time.h>
25 #include <sys/types.h>
26 #include <time.h>
27 #include "ico_log.h"
28
29 /*============================================================================*/
30 /* global API                                                                 */
31 /*============================================================================*/
32 #if defined(__GNUC__) && __GNUC__ >= 4
33 #define ICO_API __attribute__ ((visibility("default")))
34 #else
35 #define ICO_API
36 #endif
37
38 /*========================================================================*/
39 /**
40  *  static variable
41  */
42 /*========================================================================*/
43
44 static int  time_zone    = 99*60*60;    /*!< local time difference(sec)       */
45 static int  log_level    = 0x7FFFFFFF;  /*!< output level debug log           */
46 static bool flush_mode   = true;        /*!< flush mode flag                  */
47 static bool initialized  = false;       /*!< initialized flag                 */
48 static FILE *log_fd      = NULL;        /*!< file descriptor of output debug log*/
49 static int  log_stdout   = 0;           /*!< flag for log output to stdout    */
50 static int  log_lines    = 0;           /*!< output lines                     */
51 static char log_prog[32] = {0,};        /*!< name of output source module     */
52
53
54 /*------------------------------------------------------------------------*/
55 /**
56  *  @brief  printout log message
57  *
58  *  @param [in] level   log output level
59  *  @param [in] fmt     message format(same as printf)
60  *  @param [in] ...     arguments if need
61  */
62 /*------------------------------------------------------------------------*/
63 ICO_API void
64 ico_log_print(int level, const char *fmt, ...)
65 {
66     if (log_level < level) {
67         return;
68     }
69     va_list     list;
70
71     if (NULL == log_fd) {
72         ico_log_open(NULL);
73     }
74 #if ICO_APF_LOG_STDOUT == 0
75     else if (log_lines >= (ICO_LOG_MAXLINES-2)) {
76         if (log_lines >= ICO_LOG_MAXLINES)  {
77             ico_log_close();
78             ico_log_open(log_prog);
79         }
80         else    {
81             fflush(log_fd);
82         }
83     }
84 #endif /*ICO_APF_LOG_STDOUT*/
85     if (NULL != log_fd) {
86         va_start(list, fmt);
87         vfprintf(log_fd, fmt, list);
88         va_end(list);
89         if (flush_mode)  {
90             fflush(log_fd);
91         }
92     }
93     if (log_stdout == 0)    {
94         log_lines ++;
95     }
96 }
97
98 /*------------------------------------------------------------------------*/
99 /**
100  *  @brief  open log file
101  *
102  *  @param [in] prog    program name
103  */
104 /*------------------------------------------------------------------------*/
105 ICO_API void
106 ico_log_open(const char *prog)
107 {
108 #if ICO_LOG_STDOUT == 0
109     int     idx;
110     char    sPath[128];
111     char    sPath2[128];
112 #endif /*ICO_LOG_STDOUT*/
113
114     if (NULL != log_fd) {
115         fflush(log_fd);
116         if (log_stdout == 0)    {
117             fclose(log_fd);
118         }
119     }
120
121     log_lines = 0;
122
123     if ((! prog) || (*prog == 0)) {
124         log_stdout = 1;
125         log_fd = stdout;
126         log_prog[0] = 0;
127         return;
128     }
129     else {
130         strncpy(log_prog, prog, sizeof(log_prog)-1);
131         log_prog[sizeof(log_prog)-1] = 0;
132     }
133 #if ICO_LOG_STDOUT > 0
134     log_stdout = 1;
135     log_fd = stdout;
136 #else  /*ICO_LOG_STDOUT*/
137     snprintf(sPath, sizeof(sPath)-1, "%s/%s.log%d",
138              ICO_LOG_DIR, log_prog, ICO_LOG_MAXFILES-1);
139     (void)remove(sPath);
140
141     for (idx = (ICO_LOG_MAXFILES-1); idx > 0; idx--) {
142         strcpy(sPath2, sPath);
143         if (idx > 1)    {
144             snprintf(sPath, sizeof(sPath)-1, "%s/%s.log%d",
145                      ICO_LOG_DIR, log_prog, idx-1);
146         }
147         else    {
148             snprintf(sPath, sizeof(sPath)-1, "%s/%s.log",
149                      ICO_LOG_DIR, log_prog);
150         }
151         (void)rename(sPath, sPath2);
152     }
153
154     log_fd = fopen(sPath, "w");
155     if (NULL == log_fd) {
156         log_stdout = 1;
157         log_fd = stdout;
158     }
159     else if ((initialized == false) &&
160              (log_fd != stdout) && (log_fd != stderr)) {
161         initialized = true;
162         fflush(stdout);
163         fflush(stderr);
164         stdout = log_fd;
165         stderr = log_fd;
166     }
167 #endif /*ICO_LOG_STDOUT*/
168 }
169
170 /*------------------------------------------------------------------------*/
171 /**
172  *  @brief  close log file
173  */
174 /*------------------------------------------------------------------------*/
175 ICO_API void
176 ico_log_close(void)
177 {
178 #if ICO_LOG_STDOUT == 0
179     if (NULL != log_fd) {
180         fflush(log_fd);
181         if (log_stdout == 0)    {
182             fclose(log_fd);
183         }
184         log_fd = (FILE *)NULL;
185     }
186 #endif /*ICO_LOG_STDOUT*/
187 }
188
189 /*------------------------------------------------------------------------*/
190 /**
191  *  @brief  flush log file
192  */
193 /*------------------------------------------------------------------------*/
194 ICO_API void
195 ico_log_flush(void)
196 {
197     if ((NULL != log_fd) && (false == flush_mode)) {
198         fflush(log_fd);
199     }
200 }
201
202 /*------------------------------------------------------------------------*/
203 /**
204  *  @brief   get current time string
205  *
206  *  @param [in] level   log level string(header of log message)
207  *  @return current time string
208  */
209 /*------------------------------------------------------------------------*/
210 ICO_API char *
211 ico_get_str_cur_time(const char *level)
212 {
213     struct timeval  NowTime;
214     extern long     timezone;
215     static char     sBuf[28];
216
217     gettimeofday(&NowTime, (struct timezone *)0);
218     if (time_zone > (24*60*60)) {
219         tzset();
220         time_zone = timezone;
221     }
222     NowTime.tv_sec -= time_zone;
223
224     sprintf(sBuf, "%02d:%02d:%02d.%03d[%s]@%d",
225             (int)((NowTime.tv_sec/3600) % 24),
226             (int)((NowTime.tv_sec/60) % 60),
227             (int)(NowTime.tv_sec % 60),
228             (int)NowTime.tv_usec/1000, level, getpid());
229
230     return sBuf;
231 }
232
233 /*------------------------------------------------------------------------*/
234 /**
235  *  @brief  set log output level
236  *
237  *  @param [in] level   log output level
238  */
239 /*------------------------------------------------------------------------*/
240 ICO_API void
241 ico_log_set_level(int level)
242 {
243     log_level = level & (~(ICO_LOG_FLUSH|ICO_LOG_NOFLUSH));
244
245     if (log_level & (ICO_LOG_FLUSH|ICO_LOG_NOFLUSH)) {
246         if (log_level & ICO_LOG_FLUSH) {
247             flush_mode = true;
248         }
249         else    {
250             flush_mode = false;
251         }
252     }
253 }
254 /* vim:set expandtab ts=4 sw=4: */