2005-07-06 [colin] 1.9.12cvs23
[claws.git] / src / etpan / etpan-log.c
1 #include "etpan-log.h"
2
3 #include <pthread.h>
4 #include <stdio.h>
5 #include <stdarg.h>
6 #include <sys/time.h>
7 #include <libetpan/libetpan.h>
8 #include <stdlib.h>
9 #include <string.h>
10
11 #define MAX_LOG_LINE 1024
12 static pthread_mutex_t log_lock = PTHREAD_MUTEX_INITIALIZER;
13 static char log_line[MAX_LOG_LINE];
14 static chash * log_filter = NULL;
15
16 static void etpan_str_log(void)
17 {
18   fprintf(stderr, "%s\n", log_line);
19 }
20
21 void etpan_log_init(void)
22 {
23   pthread_mutex_lock(&log_lock);
24   if (log_filter == NULL) {
25     char * env_value;
26     
27     env_value = getenv("ETPAN_LOG");
28     if (env_value != NULL) {
29       strncpy(log_line, env_value, sizeof(log_line));
30       log_line[sizeof(log_line) - 1] = '\0';
31     }
32     else {
33       * log_line = '\0';
34     }
35     env_value = log_line;
36     
37     log_filter = chash_new(CHASH_DEFAULTSIZE, CHASH_COPYKEY);
38     if (log_filter != NULL) {
39       chashdatum key;
40       chashdatum value;
41       
42       key.data = "LOG";
43       key.len = strlen("LOG");
44       value.data = NULL;
45       value.len = 0;
46       chash_set(log_filter, &key, &value, NULL);
47       
48       while (env_value != NULL) {
49         char * p;
50         
51         p = strchr(env_value, ' ');
52         if (p != NULL) {
53           * p = '\0';
54           key.data = env_value;
55           key.len = strlen(env_value);
56           value.data = NULL;
57           value.len = 0;
58           chash_set(log_filter, &key, &value, NULL);
59           
60           env_value = p + 1;
61         }
62         else {
63           key.data = env_value;
64           key.len = strlen(env_value);
65           value.data = NULL;
66           value.len = 0;
67           chash_set(log_filter, &key, &value, NULL);
68           
69           env_value = p;
70         }
71       }
72     }
73   }
74   pthread_mutex_unlock(&log_lock);
75 }
76
77 void etpan_log_done(void)
78 {
79   pthread_mutex_lock(&log_lock);
80   if (log_filter != NULL) {
81     chash_free(log_filter);
82     log_filter = NULL;
83   }
84   pthread_mutex_unlock(&log_lock);
85 }
86
87 void etpan_log(char * log_id, char * format, ...)
88 {
89   va_list argp;
90   struct timeval time_info;
91   int r;
92   chashdatum key;
93   chashdatum value;
94   
95   etpan_log_init();
96   
97   key.data = log_id;
98   key.len = strlen(log_id);
99   r = chash_get(log_filter, &key, &value);
100   if (r < 0)
101     return;
102   
103   r = gettimeofday(&time_info, NULL);
104   if (r == 0) {
105     fprintf(stderr, "%4lu.%03u [%s] ", time_info.tv_sec % 3600,
106         (unsigned int) (time_info.tv_usec / 1000), log_id);
107   }
108   
109   va_start(argp, format);
110   pthread_mutex_lock(&log_lock);
111   vsnprintf(log_line, sizeof(log_line), format, argp);
112   etpan_str_log();
113   pthread_mutex_unlock(&log_lock);
114   va_end(argp);
115 }
116
117 #if defined(__APPLE__) && defined(__MACH__)
118 #include <mach/vm_types.h>
119
120 extern void thread_stack_pcs(vm_address_t *buffer,
121     unsigned max, unsigned *num);
122
123 void etpan_log_stack(void)
124 {
125   unsigned buffer[256];
126   int num_frames;
127   int i;
128   char output[1024];
129   char * current_output;
130   size_t remaining;
131   
132   thread_stack_pcs(buffer, sizeof(buffer) / sizeof(buffer[0]), &num_frames);
133   remaining = sizeof(output);
134   current_output = output;
135   for(i = 0 ; i < num_frames ; i ++) {
136     size_t len;
137     
138     snprintf(current_output, remaining, "0x%x ", buffer[i]);
139     len = strlen(current_output);
140     remaining -= len;
141     current_output += len;
142     if (remaining == 0)
143       break;
144   }
145   ETPAN_STACK_LOG(output);
146 }
147 #else
148 #if defined(__linux__)
149 #include <execinfo.h>
150
151 extern char **backtrace_symbols (void *__const *__array, int __size) __THROW;
152
153 void etpan_log_stack(void)
154 {
155   void * buffer[256];
156   char ** table;
157   int num_frames;
158   int i;
159   char output[1024];
160   char * current_output;
161   size_t remaining;
162   
163   num_frames = backtrace(buffer, sizeof(buffer) / sizeof(buffer[0]));
164   remaining = sizeof(output);
165   current_output = output;
166   for(i = 0 ; i < num_frames ; i ++) {
167     size_t len;
168     
169     snprintf(current_output, remaining, "%p ", buffer[i]);
170     len = strlen(current_output);
171     remaining -= len;
172     current_output += len;
173     if (remaining == 0)
174       break;
175   }
176   ETPAN_STACK_LOG(output);
177 }
178
179 #else
180
181 void etpan_log_stack(void)
182 {
183   ETPAN_STACK_LOG("this feature not available");
184 }
185
186 #endif
187 #endif