]> git.ipfire.org Git - thirdparty/cups.git/blame - cups/debug.c
Merge changes from CUPS 1.4svn-r7696.
[thirdparty/cups.git] / cups / debug.c
CommitLineData
ae71f5de
MS
1/*
2 * "$Id$"
3 *
4 * Debugging functions for the Common UNIX Printing System (CUPS).
5 *
6 * Copyright 2008 by Apple Inc.
7 *
8 * These coded instructions, statements, and computer programs are the
9 * property of Apple Inc. and are protected by Federal copyright
10 * law. Distribution and use rights are outlined in the file "LICENSE.txt"
11 * which should have been included with this file. If this file is
12 * file is missing or damaged, see the license at "http://www.cups.org/".
13 *
14 * This file is subject to the Apple OS-Developed Software exception.
15 *
16 * Contents:
17 *
18 * _cups_debug_printf() - Write a formatted line to the log.
19 * _cups_debug_puts() - Write a single line to the log.
20 */
21
22/*
23 * Include necessary headers...
24 */
25
26#include "globals.h"
27#include "debug.h"
28#include <sys/time.h>
29#include <fcntl.h>
30#include <unistd.h>
31
32
33#ifdef DEBUG
34/*
35 * 'debug_vsnprintf()' - Format a string into a fixed size buffer.
36 */
37
38int /* O - Number of bytes formatted */
39debug_vsnprintf(char *buffer, /* O - Output buffer */
40 size_t bufsize, /* O - Size of output buffer */
41 const char *format, /* I - printf-style format string */
42 va_list ap) /* I - Pointer to additional arguments */
43{
44 char *bufptr, /* Pointer to position in buffer */
45 *bufend, /* Pointer to end of buffer */
46 sign, /* Sign of format width */
47 size, /* Size character (h, l, L) */
48 type; /* Format type character */
49 int width, /* Width of field */
50 prec; /* Number of characters of precision */
51 char tformat[100], /* Temporary format string for sprintf() */
52 *tptr, /* Pointer into temporary format */
53 temp[1024]; /* Buffer for formatted numbers */
54 char *s; /* Pointer to string */
55 int bytes; /* Total number of bytes needed */
56
57
58 /*
59 * Loop through the format string, formatting as needed...
60 */
61
62 bufptr = buffer;
63 bufend = buffer + bufsize - 1;
64 bytes = 0;
65
66 while (*format)
67 {
68 if (*format == '%')
69 {
70 tptr = tformat;
71 *tptr++ = *format++;
72
73 if (*format == '%')
74 {
75 if (bufptr && bufptr < bufend) *bufptr++ = *format;
76 bytes ++;
77 format ++;
78 continue;
79 }
80 else if (strchr(" -+#\'", *format))
81 {
82 *tptr++ = *format;
83 sign = *format++;
84 }
85 else
86 sign = 0;
87
88 if (*format == '*')
89 {
90 /*
91 * Get width from argument...
92 */
93
94 format ++;
95 width = va_arg(ap, int);
96
97 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", width);
98 tptr += strlen(tptr);
99 }
100 else
101 {
102 width = 0;
103
104 while (isdigit(*format & 255))
105 {
106 if (tptr < (tformat + sizeof(tformat) - 1))
107 *tptr++ = *format;
108
109 width = width * 10 + *format++ - '0';
110 }
111 }
112
113 if (*format == '.')
114 {
115 if (tptr < (tformat + sizeof(tformat) - 1))
116 *tptr++ = *format;
117
118 format ++;
119
120 if (*format == '*')
121 {
122 /*
123 * Get precision from argument...
124 */
125
126 format ++;
127 prec = va_arg(ap, int);
128
129 snprintf(tptr, sizeof(tformat) - (tptr - tformat), "%d", prec);
130 tptr += strlen(tptr);
131 }
132 else
133 {
134 prec = 0;
135
136 while (isdigit(*format & 255))
137 {
138 if (tptr < (tformat + sizeof(tformat) - 1))
139 *tptr++ = *format;
140
141 prec = prec * 10 + *format++ - '0';
142 }
143 }
144 }
145 else
146 prec = -1;
147
148 if (*format == 'l' && format[1] == 'l')
149 {
150 size = 'L';
151
152 if (tptr < (tformat + sizeof(tformat) - 2))
153 {
154 *tptr++ = 'l';
155 *tptr++ = 'l';
156 }
157
158 format += 2;
159 }
160 else if (*format == 'h' || *format == 'l' || *format == 'L')
161 {
162 if (tptr < (tformat + sizeof(tformat) - 1))
163 *tptr++ = *format;
164
165 size = *format++;
166 }
167
168 if (!*format)
169 break;
170
171 if (tptr < (tformat + sizeof(tformat) - 1))
172 *tptr++ = *format;
173
174 type = *format++;
175 *tptr = '\0';
176
177 switch (type)
178 {
179 case 'E' : /* Floating point formats */
180 case 'G' :
181 case 'e' :
182 case 'f' :
183 case 'g' :
184 if ((width + 2) > sizeof(temp))
185 break;
186
187 sprintf(temp, tformat, va_arg(ap, double));
188
189 bytes += (int)strlen(temp);
190
191 if (bufptr)
192 {
193 if ((bufptr + strlen(temp)) > bufend)
194 {
195 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
196 bufptr = bufend;
197 }
198 else
199 {
200 strcpy(bufptr, temp);
201 bufptr += strlen(temp);
202 }
203 }
204 break;
205
206 case 'B' : /* Integer formats */
207 case 'X' :
208 case 'b' :
209 case 'd' :
210 case 'i' :
211 case 'o' :
212 case 'u' :
213 case 'x' :
214 if ((width + 2) > sizeof(temp))
215 break;
216
217#ifdef HAVE_LONG_LONG
218 if (size == 'L')
219 sprintf(temp, tformat, va_arg(ap, long long));
220 else
221#endif /* HAVE_LONG_LONG */
222 if (size == 'l')
223 sprintf(temp, tformat, va_arg(ap, long));
224 else
225 sprintf(temp, tformat, va_arg(ap, int));
226
227 bytes += (int)strlen(temp);
228
229 if (bufptr)
230 {
231 if ((bufptr + strlen(temp)) > bufend)
232 {
233 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
234 bufptr = bufend;
235 }
236 else
237 {
238 strcpy(bufptr, temp);
239 bufptr += strlen(temp);
240 }
241 }
242 break;
243
244 case 'p' : /* Pointer value */
245 if ((width + 2) > sizeof(temp))
246 break;
247
248 sprintf(temp, tformat, va_arg(ap, void *));
249
250 bytes += (int)strlen(temp);
251
252 if (bufptr)
253 {
254 if ((bufptr + strlen(temp)) > bufend)
255 {
256 strncpy(bufptr, temp, (size_t)(bufend - bufptr));
257 bufptr = bufend;
258 }
259 else
260 {
261 strcpy(bufptr, temp);
262 bufptr += strlen(temp);
263 }
264 }
265 break;
266
267 case 'c' : /* Character or character array */
268 bytes += width;
269
270 if (bufptr)
271 {
272 if (width <= 1)
273 *bufptr++ = va_arg(ap, int);
274 else
275 {
276 if ((bufptr + width) > bufend)
277 width = (int)(bufend - bufptr);
278
279 memcpy(bufptr, va_arg(ap, char *), (size_t)width);
280 bufptr += width;
281 }
282 }
283 break;
284
285 case 's' : /* String */
286 if ((s = va_arg(ap, char *)) == NULL)
287 s = "(null)";
288
289 /*
290 * Copy the C string, replacing control chars and \ with
291 * C character escapes...
292 */
293
294 for (bufend --; *s && bufptr < bufend; s ++)
295 {
296 if (*s == '\n')
297 {
298 *bufptr++ = '\\';
299 *bufptr++ = 'n';
300 }
301 else if (*s == '\r')
302 {
303 *bufptr++ = '\\';
304 *bufptr++ = 'r';
305 }
306 else if (*s == '\t')
307 {
308 *bufptr++ = '\\';
309 *bufptr++ = 't';
310 }
311 else if (*s == '\\')
312 {
313 *bufptr++ = '\\';
314 *bufptr++ = '\\';
315 }
316 else if (*s == '\'')
317 {
318 *bufptr++ = '\\';
319 *bufptr++ = '\'';
320 }
321 else if (*s == '\"')
322 {
323 *bufptr++ = '\\';
324 *bufptr++ = '\"';
325 }
326 else if ((*s & 255) < ' ')
327 {
328 *bufptr++ = '\\';
329 *bufptr++ = '0';
330 *bufptr++ = '0' + *s / 8;
331 *bufptr++ = '0' + (*s & 7);
332 }
333 else
334 *bufptr++ = *s;
335 }
336
337 bufend ++;
338 break;
339
340 case 'n' : /* Output number of chars so far */
341 *(va_arg(ap, int *)) = bytes;
342 break;
343 }
344 }
345 else
346 {
347 bytes ++;
348
349 if (bufptr && bufptr < bufend)
350 *bufptr++ = *format;
351
352 format ++;
353 }
354 }
355
356 /*
357 * Nul-terminate the string and return the number of characters needed.
358 */
359
360 *bufptr = '\0';
361
362 return (bytes);
363}
364
365
366/*
367 * '_cups_debug_printf()' - Write a formatted line to the log.
368 */
369
370void
371_cups_debug_printf(const char *format, /* I - Printf-style format string */
372 ...) /* I - Additional arguments as needed */
373{
374 va_list ap; /* Pointer to arguments */
375 struct timeval curtime; /* Current time */
376 char buffer[2048]; /* Output buffer */
377 size_t bytes; /* Number of bytes in buffer */
378 const char *cups_debug_log;/* CUPS_DEBUG_LOG environment variable */
379 _cups_globals_t *cg = _cupsGlobals();
380 /* Global data */
381
382
383 /*
384 * See if we need to do any logging...
385 */
386
387 if (!cg->debug_init)
388 {
389 cg->debug_init = 1;
390
391 if ((cups_debug_log = getenv("CUPS_DEBUG_LOG")) == NULL)
392 cg->debug_fd = -1;
393 else if (!strcmp(cups_debug_log, "-"))
394 cg->debug_fd = 2;
395 else
dd1abb6b
MS
396 {
397 snprintf(buffer, sizeof(buffer), cups_debug_log, getpid());
398 cg->debug_fd = open(buffer, O_WRONLY | O_APPEND | O_CREAT, 0644);
399 }
ae71f5de
MS
400 }
401
402 if (cg->debug_fd < 0)
403 return;
404
405 /*
406 * Format the message...
407 */
408
409 gettimeofday(&curtime, NULL);
410 snprintf(buffer, sizeof(buffer), "%02d:%02d:%02d.%03d ",
411 (int)((curtime.tv_sec / 3600) % 24),
412 (int)((curtime.tv_sec / 60) % 60),
413 (int)(curtime.tv_sec % 60), (int)(curtime.tv_usec / 1000));
414
415 va_start(ap, format);
416 debug_vsnprintf(buffer + 13, sizeof(buffer) - 14, format, ap);
417 va_end(ap);
418
419 bytes = strlen(buffer);
420 if (buffer[bytes - 1] != '\n')
421 {
422 buffer[bytes] = '\n';
423 bytes ++;
424 buffer[bytes] = '\0';
425 }
426
427 /*
428 * Write it out...
429 */
430
431 write(cg->debug_fd, buffer, bytes);
432}
433
434
435/*
436 * '_cups_debug_puts()' - Write a single line to the log.
437 */
438
439void
440_cups_debug_puts(const char *s) /* I - String to output */
441{
442 _cups_debug_printf("%s\n", s);
443}
444
445
446#elif defined(__APPLE__)
447/* Mac OS X needs these stubbed since we reference them in the libcups.exp file */
448void _cups_debug_printf(const char *format, ...) {}
449void _cups_debug_puts(const char *s) {}
450#endif /* DEBUG */
451
452
453/*
454 * End of "$Id$".
455 */