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