1 /* -*- c-basic-offset:2; tab-width:2; indent-tabs-mode:nil -*- */
2 
3 /* Don't include bl_debug.h because macros in android/jni/bl_debug.h causes compiling error. */
4 #include "bl_def.h" /* HAVE_ERRNO_H */
5 
6 #include <stdio.h>
7 #include <stdarg.h>
8 #include <string.h> /* strlen */
9 #include <unistd.h> /* getpid */
10 #include <time.h>   /* time/ctime */
11 #ifdef HAVE_ERRNO_H
12 #include <errno.h>
13 #endif
14 
15 #include "bl_mem.h"     /* alloca */
16 #include "bl_util.h"    /* DIGIT_STR_LEN */
17 #include "bl_conf_io.h" /* bl_get_user_rc_path */
18 
19 #if 0
20 #define __DEBUG
21 #endif
22 
23 /* --- static variables --- */
24 
25 static char *log_file_path;
26 
27 /* --- static functions --- */
28 
open_msg_file(void)29 static FILE *open_msg_file(void) {
30   FILE *fp;
31 
32   if (log_file_path && (fp = fopen(log_file_path, "a+"))) {
33     char ch;
34     time_t tm;
35     char *time_str;
36 
37     if (fseek(fp, -1, SEEK_END) == 0) {
38       if (fread(&ch, 1, 1, fp) == 1 && ch != '\n') {
39         fseek(fp, 0, SEEK_SET);
40 
41         return fp;
42       }
43 
44       fseek(fp, 0, SEEK_SET);
45     }
46 
47     tm = time(NULL);
48     time_str = ctime(&tm);
49     time_str[19] = '\0';
50     time_str += 4;
51     fprintf(fp, "%s[%d] ", time_str, getpid());
52 
53     return fp;
54   }
55 
56   return stderr;
57 }
58 
close_msg_file(FILE * fp)59 static void close_msg_file(FILE *fp) {
60   if (fp != stderr) {
61     fclose(fp);
62   } else {
63 #ifdef USE_WIN32API
64     fflush(fp);
65 #endif
66   }
67 }
68 
69 #if defined(__APPLE__) && defined(USE_NSLOG)
70 #include <CoreFoundation/CoreFoundation.h>
71 
debug_printf(const char * prefix,const char * format,va_list arg_list)72 static int debug_printf(const char *prefix, const char *format, va_list arg_list) {
73   CFStringRef cffmt = CFStringCreateWithCString(NULL, format, kCFStringEncodingUTF8);
74   NSLog(cffmt, arg_list);
75 
76   return 1;
77 }
78 #else
debug_printf(const char * prefix,const char * format,va_list arg_list)79 static int debug_printf(const char *prefix, const char *format, va_list arg_list) {
80   size_t prefix_len;
81   int ret;
82   FILE *fp;
83 
84   if ((prefix_len = strlen(prefix)) > 0) {
85     char *new_format;
86 
87     if ((new_format = alloca(prefix_len + strlen(format) + 1)) == NULL) {
88       /* error */
89 
90       return 0;
91     }
92 
93     sprintf(new_format, "%s%s", prefix, format);
94     format = new_format;
95   }
96 
97   fp = open_msg_file();
98   ret = vfprintf(fp, format, arg_list);
99   close_msg_file(fp);
100 
101   return ret;
102 }
103 #endif
104 
105 /* --- global functions --- */
106 
107 /*
108  * this is usually used between #ifdef __DEBUG ... #endif
109  */
bl_debug_printf(const char * format,...)110 int bl_debug_printf(const char *format, ...) {
111   va_list arg_list;
112 
113   va_start(arg_list, format);
114 
115   return debug_printf("DEBUG: ", format, arg_list);
116 }
117 
118 /*
119  * this is usually used between #ifdef DEBUG ... #endif
120  */
bl_warn_printf(const char * format,...)121 int bl_warn_printf(const char *format, ...) {
122   va_list arg_list;
123 
124   va_start(arg_list, format);
125 
126   return debug_printf("WARN: ", format, arg_list);
127 }
128 
129 /*
130  * this is usually used without #ifdef ... #endif
131  */
bl_error_printf(const char * format,...)132 int bl_error_printf(const char *format, ...) {
133   va_list arg_list;
134   char *prefix;
135   int ret;
136 
137   va_start(arg_list, format);
138 
139 #ifdef HAVE_ERRNO_H
140   if (errno != 0) {
141     char *error;
142 
143     error = strerror(errno);
144 
145     if (!(prefix = alloca(6 + strlen(error) + 3 + 1))) {
146       ret = 0;
147       goto end;
148     }
149 
150     sprintf(prefix, "ERROR(%s): ", error);
151   } else
152 #endif
153   {
154     prefix = "ERROR: ";
155   }
156 
157   ret = debug_printf(prefix, format, arg_list);
158 
159 end:
160   va_end(arg_list);
161 
162   return ret;
163 }
164 
165 /*
166  * for noticing message.
167  */
bl_msg_printf(const char * format,...)168 int bl_msg_printf(const char *format, ...) {
169   va_list arg_list;
170 
171   va_start(arg_list, format);
172 
173   return debug_printf("", format, arg_list);
174 }
175 
bl_set_msg_log_file_name(const char * name)176 int bl_set_msg_log_file_name(const char *name) {
177   free(log_file_path);
178 
179   if (name && *name) {
180     log_file_path = bl_get_user_rc_path(name);
181   } else {
182     log_file_path = NULL;
183   }
184 
185   return 1;
186 }
187