1
2 /* Abstract logging system used to facilitate multiple modes*/
3 /* of logging*/
4
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #ifndef _MSC_VER
9 #include <syslog.h>
10 #endif
11 #include <errno.h>
12 #include <stdarg.h>
13 #include <ctype.h>
14
15 #include "localization.h"
16 #include "logger.h"
17 #include "sci_malloc.h"
18 #include "charEncoding.h"
19
20 //#define SYSLOG_ENABLE 1
21
22 #ifndef _MSC_VER
23 static int _LOGGER_mode = _LOGGER_SYSLOG;
24 static int _LOGGER_syslog_mode = LOG_MAIL | LOG_INFO;
25 #else
26 static int _LOGGER_mode = _LOGGER_STDERR;
27 static int _LOGGER_syslog_mode = 0;
28 #endif
29
30 static FILE *_LOGGER_outf;
31
32 struct LOGGER_globals
33 {
34 int wrap;
35 int wraplength;
36 };
37
38 /* Create and Initialise the global structure for LOGGER,*/
39 /* we init it to have NO wrapping.*/
40
41 static struct LOGGER_globals LOGGER_glb = { 0, 0 };
42
43 #ifdef _MSC_VER
44 #define vsnprintf _vsnprintf
45 #endif
46
47 /*------------------------------------------------------------------------
48 Procedure: LOGGER_get_file ID:1
49 Purpose: Returns the pointer to the file being used to output logs to
50 Input:
51 Output:
52 Errors:
53 ------------------------------------------------------------------------*/
LOGGER_get_file(void)54 FILE *LOGGER_get_file( void )
55 {
56 return _LOGGER_outf;
57 }
58
59
60 /*------------------------------------------------------------------------
61 Procedure: LOGGER_set_output_mode ID:1
62 Purpose: Sets the message/log output method, ie, stderr, stdout
63 or syslog
64 Input:
65 Output:
66 Errors:
67 ------------------------------------------------------------------------*/
LOGGER_set_output_mode(int modechoice)68 int LOGGER_set_output_mode( int modechoice )
69 {
70 _LOGGER_mode = modechoice;
71 return 0;
72 }
73
74 /*------------------------------------------------------------------------
75 Procedure: LOGGER_set_output_file ID:1
76 Purpose: Sets the output file for when _LOGGER_mode is set to
77 _LOGGER_file
78 Input:
79 Output:
80 Errors:
81 ------------------------------------------------------------------------*/
LOGGER_set_output_file(FILE * f)82 int LOGGER_set_output_file( FILE *f )
83 {
84 _LOGGER_outf = f;
85 return 0;
86 }
87
88 /*------------------------------------------------------------------------
89 Procedure: LOGGER_set_syslog_mode ID:1
90 Purpose: Sets the mode that messaging to the syslog daemon will
91 be sent as (ie, LOG_MAIL|LOG_INFO)
92 Input:
93 Output:
94 Errors:
95 ------------------------------------------------------------------------*/
LOGGER_set_syslog_mode(int syslogmode)96 int LOGGER_set_syslog_mode( int syslogmode )
97 {
98 _LOGGER_syslog_mode = syslogmode;
99 return 0;
100 }
101
102
103
104
105 /*------------------------------------------------------------------------
106 Procedure: LOGGER_set_logfile ID:1
107 Purpose: Opens and setups the internal Log file file pointer with the
108 log file as given by lfname
109 Input:
110 Output:
111 Errors:
112 ------------------------------------------------------------------------*/
LOGGER_set_logfile(char * lfname)113 int LOGGER_set_logfile( char *lfname )
114 {
115 int result = 0;
116
117 wcfopen(_LOGGER_outf, lfname, "a");
118 if (!_LOGGER_outf)
119 {
120 #if !defined(_MSC_VER) && defined(SYSLOG_ENABLE)
121 syslog(1, _("LOGGER_set_logfile: ERROR - Cannot open logfile '%s' (%s)"), lfname, strerror(errno));
122 #else
123 fprintf(stderr, _("LOGGER_set_logfile: ERROR - Cannot open logfile '%s' (%s)\n"), lfname, strerror(errno));
124 #endif
125 result = -1;
126 }
127
128 return result;
129 }
130
131
132
133 /*------------------------------------------------------------------------
134 Procedure: LOGGER_set_wraplength ID:1
135 Purpose: Sets the character count at which LOGGER will break a line
136 Input: int length: Positive int indicating number of chracters at which to wrap at
137 Output:
138 Errors:
139 ------------------------------------------------------------------------*/
LOGGER_set_wraplength(int length)140 int LOGGER_set_wraplength( int length )
141 {
142 if ( length >= 0 )
143 {
144 LOGGER_glb.wraplength = length;
145 }
146
147 return LOGGER_glb.wraplength;
148 }
149
150 /*------------------------------------------------------------------------
151 Procedure: LOGGER_set_wrap ID:1
152 Purpose: Set log output wrapping to on or off
153 Input: int level: 0 = no wrap, > 0 = wrap.
154 Output:
155 Errors:
156 ------------------------------------------------------------------------*/
LOGGER_set_wrap(int level)157 int LOGGER_set_wrap( int level )
158 {
159 if ( level >= 0 )
160 {
161 LOGGER_glb.wrap = level;
162 }
163
164 return LOGGER_glb.wrap;
165 }
166
167
168
169 /*------------------------------------------------------------------------
170 Procedure: LOGGER_close_logfile ID:1
171 Purpose: Closes the modules log file pointer.
172 Input:
173 Output:
174 Errors:
175 ------------------------------------------------------------------------*/
LOGGER_close_logfile(void)176 int LOGGER_close_logfile( void )
177 {
178 int result = 0;
179
180 if (_LOGGER_outf)
181 {
182 fclose(_LOGGER_outf);
183 }
184
185 return result;
186 }
187
188
189
190 /*------------------------------------------------------------------------
191 Procedure: LOGGER_clean_output ID:1
192 Purpose: Checks through the output string for any characters which could cause
193 potential 'isssues' with the data writing calls, items such as stray non-escaped
194 % characters can cause havoc.
195 Input: char *string: Raw string
196 int maxsize: Maximum available buffer size for this string to expand to
197 Output:
198 Errors:
199 ------------------------------------------------------------------------*/
LOGGER_clean_output(char * string,char ** buffer)200 int LOGGER_clean_output( char *string, char **buffer )
201 {
202 char *newstr;
203 char *p, *q;
204 char *next_space;
205
206 int pc;
207 int slen = (int)strlen( string );
208 int line_size;
209 int maxsize = slen * 2;
210
211 /* First up, allocate maxsize bytes for a temporary new string.*/
212 newstr = MALLOC(slen * 2 + 1);
213 if ( newstr == NULL )
214 {
215 /* FIXME - Report an error here ... to -somewhere-*/
216 return -1;
217 }
218
219 p = newstr;
220 q = string;
221 pc = 0;
222 line_size = 0;
223
224 while (slen--)
225 {
226
227 /* Do we need to apply any wrapping to the output? If so then we*/
228 /* shall embark on a journey of strange space and distance*/
229 /* evaluations to determine if we should wrap now or later*/
230
231 if ( LOGGER_glb.wrap > 0 )
232 {
233 if (isspace((int)*q))
234 {
235 next_space = strpbrk( (q + 1), "\t\n\v " );
236 if (next_space != NULL)
237 {
238 if ((line_size + (next_space - q)) >= LOGGER_glb.wraplength)
239 {
240 *p = '\n';
241 p++;
242 pc++;
243 line_size = 0;
244 }
245 }
246 }
247
248 if ( line_size >= LOGGER_glb.wraplength )
249 {
250 *p = '\n';
251 p++;
252 pc++;
253 line_size = 0;
254 }
255 }
256
257 /* If the string has a % in it, then we need to encode it as*/
258 /* a DOUBLE % symbol.*/
259
260 if (*q == '%')
261 {
262 /* if (strchr("fdlsxXn",*(q+1)))*/
263 /* {*/
264 *p = '%';
265 p++;
266 pc++;
267 /* }*/
268 }
269
270 /* Copy the character of the string in*/
271 *p = *q;
272
273 /* Move everything along.*/
274 q++;
275 p++;
276 pc++;
277 line_size++;
278
279 if ( pc > (maxsize - 1) )
280 {
281 break;
282 }
283 }
284
285 *p = '\0';
286
287 /* This will have to be deallocated later!*/
288 if (newstr)
289 {
290 *buffer = newstr;
291 }
292
293 return 0;
294 }
295
296 /*------------------------------------------------------------------------
297 Procedure: LOGGER_log ID:1
298 Purpose: Logs the params as supplied to the required
299 output as defined by LOGGER_set_output
300 Input:
301 Output:
302 Errors:
303 ------------------------------------------------------------------------*/
LOGGER_log(char * format,...)304 int LOGGER_log( char *format, ...)
305 {
306 va_list ptr;
307 char tmpoutput[10240];
308 char linebreak[] = "\n";
309 char nolinebreak[] = "";
310 char *lineend;
311 char *output;
312
313
314 /* get our variable arguments*/
315 va_start(ptr, format);
316
317 /* produce output, and spit to the log file*/
318 #ifdef NO_SNPRINTF
319 vsprintf(tmpoutput, format, ptr);
320 #else
321 vsnprintf(tmpoutput, 10240, format, ptr);
322 #endif
323
324 LOGGER_clean_output( tmpoutput, &output );
325
326 if ( output[strlen(output) - 1] == '\n' )
327 {
328 lineend = nolinebreak;
329 }
330 else
331 {
332 lineend = linebreak;
333 }
334
335 if ( output[strlen(output) - 1] == '\n' )
336 {
337 lineend = nolinebreak;
338 }
339 else
340 {
341 lineend = linebreak;
342 }
343
344 /* Send the output to the appropriate output destination*/
345 switch (_LOGGER_mode)
346 {
347 case _LOGGER_SYSLOG:
348 #if !defined(_MSC_VER) && defined(SYSLOG_ENABLE)
349 syslog(_LOGGER_syslog_mode, "%s", output);
350 break;
351 #endif
352 case _LOGGER_STDERR:
353 fprintf(stderr, "%s%s", output, lineend );
354 break;
355
356 case _LOGGER_STDOUT:
357 fprintf(stdout, "%s%s", output, lineend);
358 fflush(stdout);
359 break;
360 case _LOGGER_FILE:
361 fprintf(_LOGGER_outf, "%s%s", output, lineend);
362 fflush(_LOGGER_outf);
363 break;
364 default:
365 fprintf(stdout, _("LOGGER-Default: %s%s"), output, lineend);
366 }
367
368
369 if (output)
370 {
371 FREE(output);
372 }
373
374 va_end(ptr);
375
376 return 0;
377 }
378
379
380
381
382