source: trunk/oscam-log.c@ 3181

Last change on this file since 3181 was 3181, checked in by dingo35, 10 years ago

Adding threadsafety FIXMEs, feel free to join checking..

File size: 9.6 KB
Line 
1//FIXME Not checked on threadsafety yet; after checking please remove this line
2#include "globals.h"
3#include <syslog.h>
4#include <stdlib.h>
5
6int number_of_chars_printed = 0;
7
8static FILE *fp=(FILE *)0;
9static FILE *fps=(FILE *)0;
10static int use_syslog=0;
11static int use_stdout=0;
12
13#ifdef CS_ANTICASC
14FILE *fpa=(FILE *)0;
15#endif
16
17static void switch_log(char* file, FILE **f, int (*pfinit)(char*))
18{
19 if( cfg->max_log_size )
20 {
21 struct stat stlog;
22 if( stat(file, &stlog)!=0 )
23 {
24 fprintf(stderr, "stat('%s',..) failed (errno=%d)\n", file, errno);
25 return;
26 }
27
28 if( stlog.st_size >= cfg->max_log_size*1024 ) {
29 int rc;
30 char prev_log[128];
31 sprintf(prev_log, "%s-prev", file);
32 fprintf(*f, "switch log file\n");
33 fflush(*f);
34 fclose(*f);
35 *f = (FILE *)0;
36 rc = rename(file, prev_log);
37 if( rc!=0 ) {
38 fprintf(stderr, "rename(%s, %s) failed (errno=%d)\n",
39 file, prev_log, errno);
40 }
41 else if( pfinit(file))
42 cs_exit(0);
43 }
44 }
45}
46
47void cs_write_log(char *txt)
48{
49#ifdef CS_ANTICASC
50 if( client[cs_idx].typ == 'a' && fpa ) {
51 switch_log(cfg->ac_logfile, &fpa, ac_init_log);
52 fprintf(fpa, "%s", txt);
53 fflush(fpa);
54 }
55 else
56#endif
57 // filter out entries with leading 's' and forward to statistics
58 if(txt[0] == 's') {
59 if (fps) {
60 switch_log(cfg->usrfile, &fps, cs_init_statistics);
61 fprintf(fps, "%s", txt + 1); // remove the leading 's' and write to file
62 fflush(fps);
63 }
64 } else {
65 if (fp || use_stdout) {
66 if( !use_stdout && !use_syslog)
67 switch_log(cfg->logfile, &fp, cs_init_log);
68 if (!cfg->disablelog){
69 fprintf(fp, "%s", txt);
70 fflush(fp);
71 }
72 }
73 }
74}
75
76int cs_init_log(char *file)
77{
78 static char *head = ">> OSCam << cardserver started version " CS_VERSION ", build #" CS_SVN_VERSION " (" CS_OSTYPE ")";
79
80 if (!strcmp(file, "stdout")) {
81 use_stdout = 1;
82 fp = stdout;
83 cs_log(head);
84 cs_log_config();
85 return(0);
86 }
87 if (strcmp(file, "syslog")) {
88 if (!fp) {
89 if ((fp = fopen(file, "a+")) <= (FILE *)0) {
90 fp = (FILE *)0;
91 fprintf(stderr, "couldn't open logfile: %s (errno %d)\n", file, errno);
92 } else {
93 time_t t;
94 char line[80];
95 memset(line, '-', sizeof(line));
96 line[(sizeof(line)/sizeof(char)) - 1] = '\0';
97 time(&t);
98 if (!cfg->disablelog)
99 fprintf(fp, "\n%s\n>> OSCam << cardserver started at %s%s\n", line, ctime(&t), line);
100 cs_log_config();
101 }
102 }
103 return(fp <= (FILE *)0);
104 } else {
105 openlog("oscam", LOG_NDELAY, LOG_DAEMON);
106 use_syslog = 1;
107 cs_log(head);
108 cs_log_config();
109 return(0);
110 }
111}
112
113static char *get_log_header(int m, char *txt)
114{
115 if(m) {
116 sprintf(txt, "%6d ", getpid());
117 if (cs_idx) {
118 switch (client[cs_idx].typ) {
119 case 'r':
120 case 'p':
121 case 'm':
122 case 'c': sprintf(txt+7, "%c%02d ", client[cs_idx].typ, cs_idx);
123 break;
124#ifdef CS_ANTICASC
125 case 'a':
126#endif
127 case 'l':
128#ifdef WEBIF
129 case 'h':
130#endif
131 case 'n': sprintf(txt+7, "%c " , client[cs_idx].typ);
132 break;
133 }
134 } else {
135 strcpy(txt+7, "s ");
136 }
137 } else {
138 sprintf(txt, "%-11.11s", "");
139 }
140 return(txt);
141}
142
143static void write_to_log(int flag, char *txt)
144{
145 //flag = -1 is old behaviour, before implementation of debug_nolf (=debug no line feed)
146 //
147 int i;
148 time_t t;
149 struct tm *lt;
150 char sbuf[16];
151 char log_buf[700];
152
153 // get_log_header(flag, sbuf);
154 // memcpy(txt, sbuf, 11);
155
156#ifdef CS_ANTICASC
157 if (use_syslog && client[cs_idx].typ != 'a') // system-logfile
158#else
159 if (use_syslog) // system-logfile
160#endif
161 syslog(LOG_INFO, "%s", txt);
162
163 time(&t);
164 lt=localtime(&t);
165
166 switch(flag) {
167 case -1:
168 sprintf(log_buf, "[LOG000]%4d/%02d/%02d %2d:%02d:%02d %s\n",
169 lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
170 lt->tm_hour, lt->tm_min, lt->tm_sec, txt);
171 break;
172 case 1:
173 sprintf(log_buf, "[LOG000]%4d/%02d/%02d %2d:%02d:%02d %s",
174 lt->tm_year+1900, lt->tm_mon+1, lt->tm_mday,
175 lt->tm_hour, lt->tm_min, lt->tm_sec, txt);
176 break;
177 case 16:
178 number_of_chars_printed = 0;
179 sprintf(log_buf, "[LOG000]%s\n", txt);
180 break;
181 default:
182 sprintf(log_buf, "[LOG000]%s", txt);
183 }
184
185 cs_write_log(log_buf + 8);
186
187 store_logentry(log_buf);
188
189 for (i = 0; i < CS_MAXPID; i++) // monitor-clients
190 {
191 if ((client[i].pid) && (client[i].log))
192 {
193 if (client[i].monlvl<2)
194 {
195 if ((client[cs_idx].typ != 'c') && (client[cs_idx].typ != 'm'))
196 continue;
197 if (strcmp(client[cs_idx].usr, client[i].usr))
198 continue;
199 }
200 sprintf(sbuf, "%03d", client[i].logcounter);
201 client[i].logcounter = (client[i].logcounter+1) % 1000;
202 memcpy(log_buf + 4, sbuf, 3);
203 monitor_send_idx(i, log_buf);
204 }
205 }
206}
207
208void cs_log(const char *fmt,...)
209{
210 char log_txt[512];
211 get_log_header(1, log_txt);
212 va_list params;
213 va_start(params, fmt);
214 vsprintf(log_txt+11, fmt, params);
215 va_end(params);
216 write_to_log(-1, log_txt);
217}
218
219void cs_close_log(void)
220{
221 cs_log("LOG CLOSED");
222 if (use_stdout || use_syslog || !fp) return;
223 fclose(fp);
224 fp=(FILE *)0;
225}
226#ifdef WITH_DEBUG
227void cs_debug(const char *fmt,...)
228{
229 // cs_log("cs_debug called, cs_ptyp=%d, cs_dblevel=%d, %d", cs_ptyp, cs_dblevel ,client[cs_idx].cs_ptyp & cs_dblevel);
230 char log_txt[512];
231 if (cs_dblevel & client[cs_idx].cs_ptyp)
232 {
233 get_log_header(1, log_txt);
234 va_list params;
235 va_start(params, fmt);
236 vsprintf(log_txt+11, fmt, params);
237 va_end(params);
238 write_to_log(-1, log_txt);
239 }
240}
241
242void cs_debug_mask(unsigned short mask, const char *fmt,...)
243{
244 char log_txt[512];
245 if (cs_dblevel & mask)
246 {
247 get_log_header(1, log_txt);
248 va_list params;
249 va_start(params, fmt);
250 vsprintf(log_txt+11, fmt, params);
251 va_end(params);
252 write_to_log(-1, log_txt);
253 }
254}
255
256void cs_debug_nolf(const char *fmt,...)
257{
258 char log_txt[512];
259 if (cs_dblevel & client[cs_idx].cs_ptyp)
260 {
261 va_list params;
262 va_start(params, fmt);
263 vsprintf(log_txt, fmt, params);
264 va_end(params);
265 if(!memcmp(log_txt,"\n", 1)) {
266 number_of_chars_printed = 0;
267 }
268 else
269 number_of_chars_printed++;
270 write_to_log(number_of_chars_printed, log_txt);
271 }
272}
273#endif
274void cs_dump(const uchar *buf, int n, char *fmt, ...)
275{
276 char log_txt[512];
277 int i;
278
279 if( fmt )
280 {
281 get_log_header(1, log_txt);
282 va_list params;
283 va_start(params, fmt);
284 vsprintf(log_txt+11, fmt, params);
285 va_end(params);
286 write_to_log(-1, log_txt);
287 //printf("LOG: %s\n", txt); fflush(stdout);
288 }
289
290 for( i=0; i<n; i+=16 )
291 {
292 get_log_header(0, log_txt);
293 sprintf(log_txt+11, "%s", cs_hexdump(1, buf+i, (n-i>16) ? 16 : n-i));
294 write_to_log(-1, log_txt);
295 }
296}
297#ifdef WITH_DEBUG
298void cs_ddump(const uchar *buf, int n, char *fmt, ...)
299{
300 char log_txt[512];
301 int i;
302
303 //if (((cs_ptyp & cs_dblevel)==cs_ptyp) && (fmt))
304 if ((client[cs_idx].cs_ptyp & cs_dblevel) && (fmt))
305 {
306 get_log_header(1, log_txt);
307 va_list params;
308 va_start(params, fmt);
309 vsprintf(log_txt+11, fmt, params);
310 va_end(params);
311 write_to_log(-1, log_txt);
312 //printf("LOG: %s\n", txt); fflush(stdout);
313 }
314 //if (((client[cs_idx].cs_ptyp | D_DUMP) & cs_dblevel)==(cs_ptyp | D_DUMP))
315 if (client[cs_idx].cs_ptyp & cs_dblevel)
316 {
317 for (i=0; i<n; i+=16)
318 {
319 get_log_header(0, log_txt);
320 sprintf(log_txt+11, "%s", cs_hexdump(1, buf+i, (n-i>16) ? 16 : n-i));
321 write_to_log(-1, log_txt);
322 }
323 }
324}
325
326void cs_ddump_mask(unsigned short mask, const uchar *buf, int n, char *fmt, ...)
327{
328
329 char log_txt[512];
330 int i;
331 //if (((cs_ptyp & cs_dblevel)==cs_ptyp) && (fmt))
332 if ((mask & cs_dblevel) && (fmt))
333 {
334 get_log_header(1, log_txt);
335 va_list params;
336 va_start(params, fmt);
337 vsprintf(log_txt+11, fmt, params);
338 va_end(params);
339 write_to_log(-1, log_txt);
340 //printf("LOG: %s\n", txt); fflush(stdout);
341 }
342 //if (((cs_ptyp | D_DUMP) & cs_dblevel)==(cs_ptyp | D_DUMP))
343 if (mask & cs_dblevel)
344 {
345 for (i=0; i<n; i+=16)
346 {
347 get_log_header(0, log_txt);
348 sprintf(log_txt+11, "%s", cs_hexdump(1, buf+i, (n-i>16) ? 16 : n-i));
349 write_to_log(-1, log_txt);
350 }
351 }
352}
353#endif
354int cs_init_statistics(char *file)
355{
356 if ((!fps) && (file != NULL))
357 {
358 if ((fps=fopen(file, "a+"))<=(FILE *)0)
359 {
360 fps=(FILE *)0;
361 cs_log("couldn't open statistics file: %s", file);
362 }
363 }
364 return(fps<=(FILE *)0);
365}
366
367void cs_statistics(int idx)
368{
369 if (!cfg->disableuserfile){
370 time_t t;
371 struct tm *lt;
372 char buf[512];
373
374 float cwps;
375
376 time(&t);
377 lt=localtime(&t);
378 if (client[idx].cwfound+client[idx].cwnot>0)
379 {
380 cwps=client[idx].last-client[idx].login;
381 cwps/=client[idx].cwfound+client[idx].cwnot;
382 }
383 else
384 cwps=0;
385
386 char *channel ="";
387 if(cfg->mon_appendchaninfo)
388 channel = get_servicename(client[idx].last_srvid,client[idx].last_caid);
389
390 int lsec;
391 if ((client[idx].last_caid == 0xFFFF) && (client[idx].last_srvid == 0xFFFF))
392 lsec = client[idx].last - client[idx].login; //client leave calc total duration
393 else
394 lsec = client[idx].last - client[idx].lastswitch;
395
396 int secs = 0, fullmins = 0, mins = 0, fullhours = 0;
397
398 if((lsec > 0) && (lsec < 1000000)) {
399 secs = lsec % 60;
400 if (lsec > 60) {
401 fullmins = lsec / 60;
402 mins = fullmins % 60;
403 if(fullmins > 60) {
404 fullhours = fullmins / 60;
405 }
406 }
407 }
408
409 /* statistics entry start with 's' to filter it out on other end of pipe
410 * so we can use the same Pipe as Log
411 */
412 sprintf(buf, "s%02d.%02d.%02d %02d:%02d:%02d %3.1f %s %s %d %d %d %d %d %d %d %ld %ld %02d:%02d:%02d %s %04X:%04X %s\n",
413 lt->tm_mday, lt->tm_mon+1, lt->tm_year%100,
414 lt->tm_hour, lt->tm_min, lt->tm_sec, cwps,
415 client[idx].usr[0] ? client[idx].usr : "-",
416 cs_inet_ntoa(client[idx].ip),
417 client[idx].port,
418 client[idx].cwfound,
419 client[idx].cwcache,
420 client[idx].cwnot,
421 client[idx].cwignored,
422 client[idx].cwtout,
423 client[idx].cwtun,
424 client[idx].login,
425 client[idx].last,
426 fullhours, mins, secs,
427 ph[client[idx].ctyp].desc,
428 client[idx].last_caid,
429 client[idx].last_srvid,
430 channel);
431
432 cs_write_log(buf);
433 }
434}
Note: See TracBrowser for help on using the repository browser.