1 /* Gammu logging/debugging functions */
2 /* Copyright (c) 2008-2009 by Michal Cihar <michal@cihar.com> */
3 /* Licensed under GPL2+ */
10 /* Commit flag for opening files is MS extension, some other
11 * implementations (like BCC 5.5) don't like this flag at all */
13 # define COMMIT_FLAG "c"
15 # define COMMIT_FLAG ""
18 GSM_Debug_Info GSM_none_debug
= {
29 GSM_Debug_Info GSM_global_debug
= {
41 * Actually writes message to debuging file.
43 void dbg_write(GSM_Debug_Info
*d
, const char *text
)
45 if (d
->log_function
!= NULL
) {
46 d
->log_function(text
, d
->user_data
);
47 } else if (d
->df
!= NULL
) {
48 fprintf(d
->df
, "%s", text
);
53 int dbg_vprintf(GSM_Debug_Info
*d
, const char *format
, va_list argp
)
56 char buffer
[3000], timestamp
[60];
59 GSM_DateTime date_time
;
64 if (l
== DL_NONE
) return 0;
66 result
= vsnprintf(buffer
, sizeof(buffer
) - 1, format
, argp
);
71 /* Find new line in string */
72 end
= strstr(pos
, "\n");
74 /* Are we at start of line? */
77 if (l
== DL_TEXTALLDATE
|| l
== DL_TEXTERRORDATE
|| l
== DL_TEXTDATE
) {
78 GSM_GetCurrentDateTime(&date_time
);
79 sprintf(timestamp
, "%s %4d/%02d/%02d %02d:%02d:%02d: ",
80 DayOfWeek(date_time
.Year
, date_time
.Month
, date_time
.Day
),
81 date_time
.Year
, date_time
.Month
, date_time
.Day
,
82 date_time
.Hour
, date_time
.Minute
, date_time
.Second
);
83 dbg_write(d
, timestamp
);
88 /* Remember end char */
102 /* Restore saved char */
105 /* Advance to next line */
106 pos
= end
+ strlen("\n");
108 /* We hit end of string */
113 /* Flush buffers, this might be configurable, but it could cause drop of last log messages */
121 GSM_Error
GSM_SetDebugFileDescriptor(FILE *fd
, gboolean closable
, GSM_Debug_Info
*privdi
)
123 privdi
->was_lf
= TRUE
;
125 if (privdi
->df
!= NULL
126 && fileno(privdi
->df
) != fileno(stderr
)
127 && fileno(privdi
->df
) != fileno(stdout
)
128 && privdi
->closable
) {
133 privdi
->closable
= closable
;
138 GSM_Error
GSM_SetDebugFile(const char *info
, GSM_Debug_Info
*privdi
)
142 if (info
== NULL
|| strlen(info
) == 0) {
143 return GSM_SetDebugFileDescriptor(NULL
, FALSE
, privdi
);
146 switch (privdi
->dl
) {
148 testfile
= fopen(info
,"wb" COMMIT_FLAG
);
151 case DL_TEXTERRORDATE
:
152 testfile
= fopen(info
,"a" COMMIT_FLAG
);
154 dbgprintf(privdi
, "Can't open debug file\n");
155 return ERR_CANTOPENFILE
;
157 fseek(testfile
, 0, SEEK_END
);
158 if (ftell(testfile
) > 5000000) {
160 testfile
= fopen(info
,"w" COMMIT_FLAG
);
164 testfile
= fopen(info
,"w" COMMIT_FLAG
);
167 if (testfile
== NULL
) {
168 dbgprintf(privdi
, "Can't open debug file\n");
169 return ERR_CANTOPENFILE
;
171 return GSM_SetDebugFileDescriptor(testfile
, TRUE
, privdi
);
175 GSM_Error
GSM_SetDebugFunction(GSM_Log_Function info
, void *data
, GSM_Debug_Info
* privdi
)
177 privdi
->log_function
= info
;
178 privdi
->user_data
= data
;
182 gboolean
GSM_SetDebugLevel(const char *info
, GSM_Debug_Info
*privdi
)
185 privdi
->dl
= DL_NONE
;
188 if (!strcasecmp(info
, "nothing")) {
189 privdi
->dl
= DL_NONE
;
192 if (!strcasecmp(info
, "text")) {
193 privdi
->dl
= DL_TEXT
;
196 if (!strcasecmp(info
, "textall")) {
197 privdi
->dl
= DL_TEXTALL
;
200 if (!strcasecmp(info
, "binary")) {
201 privdi
->dl
= DL_BINARY
;
204 if (!strcasecmp(info
, "errors")) {
205 privdi
->dl
= DL_TEXTERROR
;
208 if (!strcasecmp(info
, "textdate")) {
209 privdi
->dl
= DL_TEXTDATE
;
212 if (!strcasecmp(info
, "textalldate")) {
213 privdi
->dl
= DL_TEXTALLDATE
;
216 if (!strcasecmp(info
, "errorsdate")) {
217 privdi
->dl
= DL_TEXTERRORDATE
;
223 gboolean
GSM_SetDebugCoding(const char *info
, GSM_Debug_Info
*privdi
)
225 privdi
->coding
= info
;
229 gboolean
GSM_SetDebugGlobal(gboolean info
, GSM_Debug_Info
*privdi
)
231 privdi
->use_global
= info
;
236 int smfprintf(GSM_Debug_Info
*d
, const char *format
, ...)
240 GSM_Debug_Info
*tmpdi
;
242 if (d
== NULL
|| d
->use_global
) {
243 tmpdi
= &GSM_global_debug
;
248 va_start(argp
, format
);
249 result
= dbg_vprintf(tmpdi
, format
, argp
);
257 int smprintf(GSM_StateMachine
*s
, const char *format
, ...)
261 GSM_Debug_Info
*curdi
;
263 curdi
= GSM_GetDI(s
);
265 va_start(argp
, format
);
267 result
= dbg_vprintf(curdi
, format
, argp
);
274 int smprintf_level(GSM_StateMachine
* s
, GSM_DebugSeverity severity
, const char *format
, ...)
278 GSM_Debug_Info
*curdi
;
280 curdi
= GSM_GetDI(s
);
282 if (severity
== D_TEXT
) {
283 if (curdi
->dl
!= DL_TEXT
&&
284 curdi
->dl
!= DL_TEXTALL
&&
285 curdi
->dl
!= DL_TEXTDATE
&&
286 curdi
->dl
!= DL_TEXTALLDATE
) {
289 } else if (severity
== D_ERROR
) {
290 if (curdi
->dl
!= DL_TEXT
&&
291 curdi
->dl
!= DL_TEXTALL
&&
292 curdi
->dl
!= DL_TEXTDATE
&&
293 curdi
->dl
!= DL_TEXTALLDATE
&&
294 curdi
->dl
!= DL_TEXTERROR
&&
295 curdi
->dl
!= DL_TEXTERRORDATE
) {
299 va_start(argp
, format
);
301 result
= dbg_vprintf(curdi
, format
, argp
);
307 #define CHARS_PER_LINE (16)
309 /* Dumps a message */
310 void DumpMessage(GSM_Debug_Info
*d
, const unsigned char *message
, const int messagesize
)
313 char buffer
[(CHARS_PER_LINE
* 5) + 1];
317 if (messagesize
== 0) return;
319 memset(buffer
, ' ', CHARS_PER_LINE
* 5);
320 buffer
[CHARS_PER_LINE
* 5] = 0;
322 for (i
= 0; i
< messagesize
; i
++) {
323 /* Write hex number */
324 snprintf(buffer
+ (j
* 4), 3, "%02X", message
[i
]);
325 buffer
[(j
* 4) + 2] = ' '; /* wipe snprintf's \0 */
327 /* Write char if possible */
328 if (isprint(message
[i
])
330 && message
[i
] != 0x09
331 /* 0x01 = beep in windows xp */
332 && message
[i
] != 0x01
333 /* these are empty in windows xp */
334 && message
[i
] != 0x85
335 && message
[i
] != 0x95
336 && message
[i
] != 0xA6
337 && message
[i
] != 0xB7) {
338 buffer
[(j
* 4) + 2] = message
[i
];
339 buffer
[(CHARS_PER_LINE
- 1) * 4 + j
+ 4] = message
[i
];
341 buffer
[(CHARS_PER_LINE
- 1) * 4 + j
+ 4] = '.';
344 /* Write char separator */
345 if (j
!= CHARS_PER_LINE
- 1 && i
!= messagesize
- 1) {
346 buffer
[j
* 4 + 3] = '|';
349 /* Print out buffer */
350 if (j
== CHARS_PER_LINE
- 1) {
351 smfprintf(d
, "%s\n", buffer
);
352 memset(buffer
, ' ', CHARS_PER_LINE
* 5);
359 /* Anything remains to be printed? */
361 smfprintf(d
, "%s\n", buffer
);
365 #undef CHARS_PER_LINE
367 void DumpMessageText(GSM_Debug_Info
*d
, const unsigned char *message
, const int messagesize
)
369 if (d
== NULL
|| (d
->dl
!= DL_TEXTALL
&& d
->dl
== DL_TEXTALLDATE
)) return;
370 DumpMessage(d
, message
, messagesize
);
373 /* How should editor hadle tabs in this file? Add editor commands here.
374 * vim: noexpandtab sw=8 ts=8 sts=8: