xref: /aosp_15_r20/external/libcups/cups/debug.c (revision 5e7646d21f1134fb0638875d812ef646c12ab91e)
1*5e7646d2SAndroid Build Coastguard Worker /*
2*5e7646d2SAndroid Build Coastguard Worker  * Debugging functions for CUPS.
3*5e7646d2SAndroid Build Coastguard Worker  *
4*5e7646d2SAndroid Build Coastguard Worker  * Copyright © 2008-2018 by Apple Inc.
5*5e7646d2SAndroid Build Coastguard Worker  *
6*5e7646d2SAndroid Build Coastguard Worker  * Licensed under Apache License v2.0.  See the file "LICENSE" for more
7*5e7646d2SAndroid Build Coastguard Worker  * information.
8*5e7646d2SAndroid Build Coastguard Worker  */
9*5e7646d2SAndroid Build Coastguard Worker 
10*5e7646d2SAndroid Build Coastguard Worker /*
11*5e7646d2SAndroid Build Coastguard Worker  * Include necessary headers...
12*5e7646d2SAndroid Build Coastguard Worker  */
13*5e7646d2SAndroid Build Coastguard Worker 
14*5e7646d2SAndroid Build Coastguard Worker #include "cups-private.h"
15*5e7646d2SAndroid Build Coastguard Worker #include "debug-internal.h"
16*5e7646d2SAndroid Build Coastguard Worker #include "thread-private.h"
17*5e7646d2SAndroid Build Coastguard Worker #ifdef _WIN32
18*5e7646d2SAndroid Build Coastguard Worker #  include <sys/timeb.h>
19*5e7646d2SAndroid Build Coastguard Worker #  include <time.h>
20*5e7646d2SAndroid Build Coastguard Worker #  include <io.h>
21*5e7646d2SAndroid Build Coastguard Worker #  define getpid (int)GetCurrentProcessId
22*5e7646d2SAndroid Build Coastguard Worker int					/* O  - 0 on success, -1 on failure */
_cups_gettimeofday(struct timeval * tv,void * tz)23*5e7646d2SAndroid Build Coastguard Worker _cups_gettimeofday(struct timeval *tv,	/* I  - Timeval struct */
24*5e7646d2SAndroid Build Coastguard Worker                    void		  *tz)	/* I  - Timezone */
25*5e7646d2SAndroid Build Coastguard Worker {
26*5e7646d2SAndroid Build Coastguard Worker   struct _timeb timebuffer;		/* Time buffer struct */
27*5e7646d2SAndroid Build Coastguard Worker   _ftime(&timebuffer);
28*5e7646d2SAndroid Build Coastguard Worker   tv->tv_sec  = (long)timebuffer.time;
29*5e7646d2SAndroid Build Coastguard Worker   tv->tv_usec = timebuffer.millitm * 1000;
30*5e7646d2SAndroid Build Coastguard Worker   return 0;
31*5e7646d2SAndroid Build Coastguard Worker }
32*5e7646d2SAndroid Build Coastguard Worker #else
33*5e7646d2SAndroid Build Coastguard Worker #  include <sys/time.h>
34*5e7646d2SAndroid Build Coastguard Worker #  include <unistd.h>
35*5e7646d2SAndroid Build Coastguard Worker #endif /* _WIN32 */
36*5e7646d2SAndroid Build Coastguard Worker #include <regex.h>
37*5e7646d2SAndroid Build Coastguard Worker #include <fcntl.h>
38*5e7646d2SAndroid Build Coastguard Worker 
39*5e7646d2SAndroid Build Coastguard Worker 
40*5e7646d2SAndroid Build Coastguard Worker #ifdef DEBUG
41*5e7646d2SAndroid Build Coastguard Worker /*
42*5e7646d2SAndroid Build Coastguard Worker  * Globals...
43*5e7646d2SAndroid Build Coastguard Worker  */
44*5e7646d2SAndroid Build Coastguard Worker 
45*5e7646d2SAndroid Build Coastguard Worker int			_cups_debug_fd = -1;
46*5e7646d2SAndroid Build Coastguard Worker 					/* Debug log file descriptor */
47*5e7646d2SAndroid Build Coastguard Worker int			_cups_debug_level = 1;
48*5e7646d2SAndroid Build Coastguard Worker 					/* Log level (0 to 9) */
49*5e7646d2SAndroid Build Coastguard Worker 
50*5e7646d2SAndroid Build Coastguard Worker 
51*5e7646d2SAndroid Build Coastguard Worker /*
52*5e7646d2SAndroid Build Coastguard Worker  * Local globals...
53*5e7646d2SAndroid Build Coastguard Worker  */
54*5e7646d2SAndroid Build Coastguard Worker 
55*5e7646d2SAndroid Build Coastguard Worker static regex_t		*debug_filter = NULL;
56*5e7646d2SAndroid Build Coastguard Worker 					/* Filter expression for messages */
57*5e7646d2SAndroid Build Coastguard Worker static int		debug_init = 0;	/* Did we initialize debugging? */
58*5e7646d2SAndroid Build Coastguard Worker static _cups_mutex_t	debug_init_mutex = _CUPS_MUTEX_INITIALIZER,
59*5e7646d2SAndroid Build Coastguard Worker 					/* Mutex to control initialization */
60*5e7646d2SAndroid Build Coastguard Worker 			debug_log_mutex = _CUPS_MUTEX_INITIALIZER;
61*5e7646d2SAndroid Build Coastguard Worker 					/* Mutex to serialize log entries */
62*5e7646d2SAndroid Build Coastguard Worker 
63*5e7646d2SAndroid Build Coastguard Worker 
64*5e7646d2SAndroid Build Coastguard Worker /*
65*5e7646d2SAndroid Build Coastguard Worker  * 'debug_thread_id()' - Return an integer representing the current thread.
66*5e7646d2SAndroid Build Coastguard Worker  */
67*5e7646d2SAndroid Build Coastguard Worker 
68*5e7646d2SAndroid Build Coastguard Worker static int				/* O - Local thread ID */
debug_thread_id(void)69*5e7646d2SAndroid Build Coastguard Worker debug_thread_id(void)
70*5e7646d2SAndroid Build Coastguard Worker {
71*5e7646d2SAndroid Build Coastguard Worker   _cups_globals_t *cg = _cupsGlobals();	/* Global data */
72*5e7646d2SAndroid Build Coastguard Worker 
73*5e7646d2SAndroid Build Coastguard Worker 
74*5e7646d2SAndroid Build Coastguard Worker   return (cg->thread_id);
75*5e7646d2SAndroid Build Coastguard Worker }
76*5e7646d2SAndroid Build Coastguard Worker 
77*5e7646d2SAndroid Build Coastguard Worker 
78*5e7646d2SAndroid Build Coastguard Worker /*
79*5e7646d2SAndroid Build Coastguard Worker  * '_cups_debug_printf()' - Write a formatted line to the log.
80*5e7646d2SAndroid Build Coastguard Worker  */
81*5e7646d2SAndroid Build Coastguard Worker 
82*5e7646d2SAndroid Build Coastguard Worker void
_cups_debug_printf(const char * format,...)83*5e7646d2SAndroid Build Coastguard Worker _cups_debug_printf(const char *format,	/* I - Printf-style format string */
84*5e7646d2SAndroid Build Coastguard Worker                    ...)			/* I - Additional arguments as needed */
85*5e7646d2SAndroid Build Coastguard Worker {
86*5e7646d2SAndroid Build Coastguard Worker   va_list		ap;		/* Pointer to arguments */
87*5e7646d2SAndroid Build Coastguard Worker   struct timeval	curtime;	/* Current time */
88*5e7646d2SAndroid Build Coastguard Worker   char			buffer[2048];	/* Output buffer */
89*5e7646d2SAndroid Build Coastguard Worker   ssize_t		bytes;		/* Number of bytes in buffer */
90*5e7646d2SAndroid Build Coastguard Worker   int			level;		/* Log level in message */
91*5e7646d2SAndroid Build Coastguard Worker 
92*5e7646d2SAndroid Build Coastguard Worker 
93*5e7646d2SAndroid Build Coastguard Worker  /*
94*5e7646d2SAndroid Build Coastguard Worker   * See if we need to do any logging...
95*5e7646d2SAndroid Build Coastguard Worker   */
96*5e7646d2SAndroid Build Coastguard Worker 
97*5e7646d2SAndroid Build Coastguard Worker   if (!debug_init)
98*5e7646d2SAndroid Build Coastguard Worker     _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"),
99*5e7646d2SAndroid Build Coastguard Worker                     getenv("CUPS_DEBUG_FILTER"), 0);
100*5e7646d2SAndroid Build Coastguard Worker 
101*5e7646d2SAndroid Build Coastguard Worker   if (_cups_debug_fd < 0)
102*5e7646d2SAndroid Build Coastguard Worker     return;
103*5e7646d2SAndroid Build Coastguard Worker 
104*5e7646d2SAndroid Build Coastguard Worker  /*
105*5e7646d2SAndroid Build Coastguard Worker   * Filter as needed...
106*5e7646d2SAndroid Build Coastguard Worker   */
107*5e7646d2SAndroid Build Coastguard Worker 
108*5e7646d2SAndroid Build Coastguard Worker   if (isdigit(format[0]))
109*5e7646d2SAndroid Build Coastguard Worker     level = *format++ - '0';
110*5e7646d2SAndroid Build Coastguard Worker   else
111*5e7646d2SAndroid Build Coastguard Worker     level = 0;
112*5e7646d2SAndroid Build Coastguard Worker 
113*5e7646d2SAndroid Build Coastguard Worker   if (level > _cups_debug_level)
114*5e7646d2SAndroid Build Coastguard Worker     return;
115*5e7646d2SAndroid Build Coastguard Worker 
116*5e7646d2SAndroid Build Coastguard Worker   if (debug_filter)
117*5e7646d2SAndroid Build Coastguard Worker   {
118*5e7646d2SAndroid Build Coastguard Worker     int	result;				/* Filter result */
119*5e7646d2SAndroid Build Coastguard Worker 
120*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexLock(&debug_init_mutex);
121*5e7646d2SAndroid Build Coastguard Worker     result = regexec(debug_filter, format, 0, NULL, 0);
122*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexUnlock(&debug_init_mutex);
123*5e7646d2SAndroid Build Coastguard Worker 
124*5e7646d2SAndroid Build Coastguard Worker     if (result)
125*5e7646d2SAndroid Build Coastguard Worker       return;
126*5e7646d2SAndroid Build Coastguard Worker   }
127*5e7646d2SAndroid Build Coastguard Worker 
128*5e7646d2SAndroid Build Coastguard Worker  /*
129*5e7646d2SAndroid Build Coastguard Worker   * Format the message...
130*5e7646d2SAndroid Build Coastguard Worker   */
131*5e7646d2SAndroid Build Coastguard Worker 
132*5e7646d2SAndroid Build Coastguard Worker   gettimeofday(&curtime, NULL);
133*5e7646d2SAndroid Build Coastguard Worker   snprintf(buffer, sizeof(buffer), "T%03d %02d:%02d:%02d.%03d  ",
134*5e7646d2SAndroid Build Coastguard Worker            debug_thread_id(), (int)((curtime.tv_sec / 3600) % 24),
135*5e7646d2SAndroid Build Coastguard Worker 	   (int)((curtime.tv_sec / 60) % 60),
136*5e7646d2SAndroid Build Coastguard Worker 	   (int)(curtime.tv_sec % 60), (int)(curtime.tv_usec / 1000));
137*5e7646d2SAndroid Build Coastguard Worker 
138*5e7646d2SAndroid Build Coastguard Worker   va_start(ap, format);
139*5e7646d2SAndroid Build Coastguard Worker   bytes = _cups_safe_vsnprintf(buffer + 19, sizeof(buffer) - 20, format, ap) + 19;
140*5e7646d2SAndroid Build Coastguard Worker   va_end(ap);
141*5e7646d2SAndroid Build Coastguard Worker 
142*5e7646d2SAndroid Build Coastguard Worker   if ((size_t)bytes >= (sizeof(buffer) - 1))
143*5e7646d2SAndroid Build Coastguard Worker   {
144*5e7646d2SAndroid Build Coastguard Worker     buffer[sizeof(buffer) - 2] = '\n';
145*5e7646d2SAndroid Build Coastguard Worker     bytes = sizeof(buffer) - 1;
146*5e7646d2SAndroid Build Coastguard Worker   }
147*5e7646d2SAndroid Build Coastguard Worker   else if (buffer[bytes - 1] != '\n')
148*5e7646d2SAndroid Build Coastguard Worker   {
149*5e7646d2SAndroid Build Coastguard Worker     buffer[bytes++] = '\n';
150*5e7646d2SAndroid Build Coastguard Worker     buffer[bytes]   = '\0';
151*5e7646d2SAndroid Build Coastguard Worker   }
152*5e7646d2SAndroid Build Coastguard Worker 
153*5e7646d2SAndroid Build Coastguard Worker  /*
154*5e7646d2SAndroid Build Coastguard Worker   * Write it out...
155*5e7646d2SAndroid Build Coastguard Worker   */
156*5e7646d2SAndroid Build Coastguard Worker 
157*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&debug_log_mutex);
158*5e7646d2SAndroid Build Coastguard Worker   write(_cups_debug_fd, buffer, (size_t)bytes);
159*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&debug_log_mutex);
160*5e7646d2SAndroid Build Coastguard Worker }
161*5e7646d2SAndroid Build Coastguard Worker 
162*5e7646d2SAndroid Build Coastguard Worker 
163*5e7646d2SAndroid Build Coastguard Worker /*
164*5e7646d2SAndroid Build Coastguard Worker  * '_cups_debug_puts()' - Write a single line to the log.
165*5e7646d2SAndroid Build Coastguard Worker  */
166*5e7646d2SAndroid Build Coastguard Worker 
167*5e7646d2SAndroid Build Coastguard Worker void
_cups_debug_puts(const char * s)168*5e7646d2SAndroid Build Coastguard Worker _cups_debug_puts(const char *s)		/* I - String to output */
169*5e7646d2SAndroid Build Coastguard Worker {
170*5e7646d2SAndroid Build Coastguard Worker   struct timeval	curtime;	/* Current time */
171*5e7646d2SAndroid Build Coastguard Worker   char			buffer[2048];	/* Output buffer */
172*5e7646d2SAndroid Build Coastguard Worker   ssize_t		bytes;		/* Number of bytes in buffer */
173*5e7646d2SAndroid Build Coastguard Worker   int			level;		/* Log level in message */
174*5e7646d2SAndroid Build Coastguard Worker 
175*5e7646d2SAndroid Build Coastguard Worker 
176*5e7646d2SAndroid Build Coastguard Worker  /*
177*5e7646d2SAndroid Build Coastguard Worker   * See if we need to do any logging...
178*5e7646d2SAndroid Build Coastguard Worker   */
179*5e7646d2SAndroid Build Coastguard Worker 
180*5e7646d2SAndroid Build Coastguard Worker   if (!debug_init)
181*5e7646d2SAndroid Build Coastguard Worker     _cups_debug_set(getenv("CUPS_DEBUG_LOG"), getenv("CUPS_DEBUG_LEVEL"),
182*5e7646d2SAndroid Build Coastguard Worker                     getenv("CUPS_DEBUG_FILTER"), 0);
183*5e7646d2SAndroid Build Coastguard Worker 
184*5e7646d2SAndroid Build Coastguard Worker   if (_cups_debug_fd < 0)
185*5e7646d2SAndroid Build Coastguard Worker     return;
186*5e7646d2SAndroid Build Coastguard Worker 
187*5e7646d2SAndroid Build Coastguard Worker  /*
188*5e7646d2SAndroid Build Coastguard Worker   * Filter as needed...
189*5e7646d2SAndroid Build Coastguard Worker   */
190*5e7646d2SAndroid Build Coastguard Worker 
191*5e7646d2SAndroid Build Coastguard Worker   if (isdigit(s[0]))
192*5e7646d2SAndroid Build Coastguard Worker     level = *s++ - '0';
193*5e7646d2SAndroid Build Coastguard Worker   else
194*5e7646d2SAndroid Build Coastguard Worker     level = 0;
195*5e7646d2SAndroid Build Coastguard Worker 
196*5e7646d2SAndroid Build Coastguard Worker   if (level > _cups_debug_level)
197*5e7646d2SAndroid Build Coastguard Worker     return;
198*5e7646d2SAndroid Build Coastguard Worker 
199*5e7646d2SAndroid Build Coastguard Worker   if (debug_filter)
200*5e7646d2SAndroid Build Coastguard Worker   {
201*5e7646d2SAndroid Build Coastguard Worker     int	result;				/* Filter result */
202*5e7646d2SAndroid Build Coastguard Worker 
203*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexLock(&debug_init_mutex);
204*5e7646d2SAndroid Build Coastguard Worker     result = regexec(debug_filter, s, 0, NULL, 0);
205*5e7646d2SAndroid Build Coastguard Worker     _cupsMutexUnlock(&debug_init_mutex);
206*5e7646d2SAndroid Build Coastguard Worker 
207*5e7646d2SAndroid Build Coastguard Worker     if (result)
208*5e7646d2SAndroid Build Coastguard Worker       return;
209*5e7646d2SAndroid Build Coastguard Worker   }
210*5e7646d2SAndroid Build Coastguard Worker 
211*5e7646d2SAndroid Build Coastguard Worker  /*
212*5e7646d2SAndroid Build Coastguard Worker   * Format the message...
213*5e7646d2SAndroid Build Coastguard Worker   */
214*5e7646d2SAndroid Build Coastguard Worker 
215*5e7646d2SAndroid Build Coastguard Worker   gettimeofday(&curtime, NULL);
216*5e7646d2SAndroid Build Coastguard Worker   bytes = snprintf(buffer, sizeof(buffer), "T%03d %02d:%02d:%02d.%03d  %s",
217*5e7646d2SAndroid Build Coastguard Worker                    debug_thread_id(), (int)((curtime.tv_sec / 3600) % 24),
218*5e7646d2SAndroid Build Coastguard Worker 		   (int)((curtime.tv_sec / 60) % 60),
219*5e7646d2SAndroid Build Coastguard Worker 		   (int)(curtime.tv_sec % 60), (int)(curtime.tv_usec / 1000),
220*5e7646d2SAndroid Build Coastguard Worker 		   s);
221*5e7646d2SAndroid Build Coastguard Worker 
222*5e7646d2SAndroid Build Coastguard Worker   if ((size_t)bytes >= (sizeof(buffer) - 1))
223*5e7646d2SAndroid Build Coastguard Worker   {
224*5e7646d2SAndroid Build Coastguard Worker     buffer[sizeof(buffer) - 2] = '\n';
225*5e7646d2SAndroid Build Coastguard Worker     bytes = sizeof(buffer) - 1;
226*5e7646d2SAndroid Build Coastguard Worker   }
227*5e7646d2SAndroid Build Coastguard Worker   else if (buffer[bytes - 1] != '\n')
228*5e7646d2SAndroid Build Coastguard Worker   {
229*5e7646d2SAndroid Build Coastguard Worker     buffer[bytes++] = '\n';
230*5e7646d2SAndroid Build Coastguard Worker     buffer[bytes]   = '\0';
231*5e7646d2SAndroid Build Coastguard Worker   }
232*5e7646d2SAndroid Build Coastguard Worker 
233*5e7646d2SAndroid Build Coastguard Worker  /*
234*5e7646d2SAndroid Build Coastguard Worker   * Write it out...
235*5e7646d2SAndroid Build Coastguard Worker   */
236*5e7646d2SAndroid Build Coastguard Worker 
237*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&debug_log_mutex);
238*5e7646d2SAndroid Build Coastguard Worker   write(_cups_debug_fd, buffer, (size_t)bytes);
239*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&debug_log_mutex);
240*5e7646d2SAndroid Build Coastguard Worker }
241*5e7646d2SAndroid Build Coastguard Worker 
242*5e7646d2SAndroid Build Coastguard Worker 
243*5e7646d2SAndroid Build Coastguard Worker /*
244*5e7646d2SAndroid Build Coastguard Worker  * '_cups_debug_set()' - Enable or disable debug logging.
245*5e7646d2SAndroid Build Coastguard Worker  */
246*5e7646d2SAndroid Build Coastguard Worker 
247*5e7646d2SAndroid Build Coastguard Worker void
_cups_debug_set(const char * logfile,const char * level,const char * filter,int force)248*5e7646d2SAndroid Build Coastguard Worker _cups_debug_set(const char *logfile,	/* I - Log file or NULL */
249*5e7646d2SAndroid Build Coastguard Worker                 const char *level,	/* I - Log level or NULL */
250*5e7646d2SAndroid Build Coastguard Worker 		const char *filter,	/* I - Filter string or NULL */
251*5e7646d2SAndroid Build Coastguard Worker 		int        force)	/* I - Force initialization */
252*5e7646d2SAndroid Build Coastguard Worker {
253*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexLock(&debug_init_mutex);
254*5e7646d2SAndroid Build Coastguard Worker 
255*5e7646d2SAndroid Build Coastguard Worker   if (!debug_init || force)
256*5e7646d2SAndroid Build Coastguard Worker   {
257*5e7646d2SAndroid Build Coastguard Worker    /*
258*5e7646d2SAndroid Build Coastguard Worker     * Restore debug settings to defaults...
259*5e7646d2SAndroid Build Coastguard Worker     */
260*5e7646d2SAndroid Build Coastguard Worker 
261*5e7646d2SAndroid Build Coastguard Worker     if (_cups_debug_fd != -1)
262*5e7646d2SAndroid Build Coastguard Worker     {
263*5e7646d2SAndroid Build Coastguard Worker       close(_cups_debug_fd);
264*5e7646d2SAndroid Build Coastguard Worker       _cups_debug_fd = -1;
265*5e7646d2SAndroid Build Coastguard Worker     }
266*5e7646d2SAndroid Build Coastguard Worker 
267*5e7646d2SAndroid Build Coastguard Worker     if (debug_filter)
268*5e7646d2SAndroid Build Coastguard Worker     {
269*5e7646d2SAndroid Build Coastguard Worker       regfree((regex_t *)debug_filter);
270*5e7646d2SAndroid Build Coastguard Worker       debug_filter = NULL;
271*5e7646d2SAndroid Build Coastguard Worker     }
272*5e7646d2SAndroid Build Coastguard Worker 
273*5e7646d2SAndroid Build Coastguard Worker     _cups_debug_level = 1;
274*5e7646d2SAndroid Build Coastguard Worker 
275*5e7646d2SAndroid Build Coastguard Worker    /*
276*5e7646d2SAndroid Build Coastguard Worker     * Open logs, set log levels, etc.
277*5e7646d2SAndroid Build Coastguard Worker     */
278*5e7646d2SAndroid Build Coastguard Worker 
279*5e7646d2SAndroid Build Coastguard Worker     if (!logfile)
280*5e7646d2SAndroid Build Coastguard Worker       _cups_debug_fd = -1;
281*5e7646d2SAndroid Build Coastguard Worker     else if (!strcmp(logfile, "-"))
282*5e7646d2SAndroid Build Coastguard Worker       _cups_debug_fd = 2;
283*5e7646d2SAndroid Build Coastguard Worker     else
284*5e7646d2SAndroid Build Coastguard Worker     {
285*5e7646d2SAndroid Build Coastguard Worker       char	buffer[1024];		/* Filename buffer */
286*5e7646d2SAndroid Build Coastguard Worker 
287*5e7646d2SAndroid Build Coastguard Worker       snprintf(buffer, sizeof(buffer), logfile, getpid());
288*5e7646d2SAndroid Build Coastguard Worker 
289*5e7646d2SAndroid Build Coastguard Worker       if (buffer[0] == '+')
290*5e7646d2SAndroid Build Coastguard Worker 	_cups_debug_fd = open(buffer + 1, O_WRONLY | O_APPEND | O_CREAT, 0644);
291*5e7646d2SAndroid Build Coastguard Worker       else
292*5e7646d2SAndroid Build Coastguard Worker 	_cups_debug_fd = open(buffer, O_WRONLY | O_TRUNC | O_CREAT, 0644);
293*5e7646d2SAndroid Build Coastguard Worker     }
294*5e7646d2SAndroid Build Coastguard Worker 
295*5e7646d2SAndroid Build Coastguard Worker     if (level)
296*5e7646d2SAndroid Build Coastguard Worker       _cups_debug_level = atoi(level);
297*5e7646d2SAndroid Build Coastguard Worker 
298*5e7646d2SAndroid Build Coastguard Worker     if (filter)
299*5e7646d2SAndroid Build Coastguard Worker     {
300*5e7646d2SAndroid Build Coastguard Worker       if ((debug_filter = (regex_t *)calloc(1, sizeof(regex_t))) == NULL)
301*5e7646d2SAndroid Build Coastguard Worker 	fputs("Unable to allocate memory for CUPS_DEBUG_FILTER - results not "
302*5e7646d2SAndroid Build Coastguard Worker 	      "filtered!\n", stderr);
303*5e7646d2SAndroid Build Coastguard Worker       else if (regcomp(debug_filter, filter, REG_EXTENDED))
304*5e7646d2SAndroid Build Coastguard Worker       {
305*5e7646d2SAndroid Build Coastguard Worker 	fputs("Bad regular expression in CUPS_DEBUG_FILTER - results not "
306*5e7646d2SAndroid Build Coastguard Worker 	      "filtered!\n", stderr);
307*5e7646d2SAndroid Build Coastguard Worker 	free(debug_filter);
308*5e7646d2SAndroid Build Coastguard Worker 	debug_filter = NULL;
309*5e7646d2SAndroid Build Coastguard Worker       }
310*5e7646d2SAndroid Build Coastguard Worker     }
311*5e7646d2SAndroid Build Coastguard Worker 
312*5e7646d2SAndroid Build Coastguard Worker     debug_init = 1;
313*5e7646d2SAndroid Build Coastguard Worker   }
314*5e7646d2SAndroid Build Coastguard Worker 
315*5e7646d2SAndroid Build Coastguard Worker   _cupsMutexUnlock(&debug_init_mutex);
316*5e7646d2SAndroid Build Coastguard Worker }
317*5e7646d2SAndroid Build Coastguard Worker 
318*5e7646d2SAndroid Build Coastguard Worker 
319*5e7646d2SAndroid Build Coastguard Worker #else
320*5e7646d2SAndroid Build Coastguard Worker /*
321*5e7646d2SAndroid Build Coastguard Worker  * '_cups_debug_set()' - Enable or disable debug logging.
322*5e7646d2SAndroid Build Coastguard Worker  */
323*5e7646d2SAndroid Build Coastguard Worker 
324*5e7646d2SAndroid Build Coastguard Worker void
_cups_debug_set(const char * logfile,const char * level,const char * filter,int force)325*5e7646d2SAndroid Build Coastguard Worker _cups_debug_set(const char *logfile,	/* I - Log file or NULL */
326*5e7646d2SAndroid Build Coastguard Worker 		const char *level,	/* I - Log level or NULL */
327*5e7646d2SAndroid Build Coastguard Worker 		const char *filter,	/* I - Filter string or NULL */
328*5e7646d2SAndroid Build Coastguard Worker 		int        force)	/* I - Force initialization */
329*5e7646d2SAndroid Build Coastguard Worker {
330*5e7646d2SAndroid Build Coastguard Worker   (void)logfile;
331*5e7646d2SAndroid Build Coastguard Worker   (void)level;
332*5e7646d2SAndroid Build Coastguard Worker   (void)filter;
333*5e7646d2SAndroid Build Coastguard Worker   (void)force;
334*5e7646d2SAndroid Build Coastguard Worker }
335*5e7646d2SAndroid Build Coastguard Worker #endif /* DEBUG */
336*5e7646d2SAndroid Build Coastguard Worker 
337*5e7646d2SAndroid Build Coastguard Worker 
338*5e7646d2SAndroid Build Coastguard Worker /*
339*5e7646d2SAndroid Build Coastguard Worker  * '_cups_safe_vsnprintf()' - Format a string into a fixed size buffer,
340*5e7646d2SAndroid Build Coastguard Worker  *                            quoting special characters.
341*5e7646d2SAndroid Build Coastguard Worker  */
342*5e7646d2SAndroid Build Coastguard Worker 
343*5e7646d2SAndroid Build Coastguard Worker ssize_t					/* O - Number of bytes formatted */
_cups_safe_vsnprintf(char * buffer,size_t bufsize,const char * format,va_list ap)344*5e7646d2SAndroid Build Coastguard Worker _cups_safe_vsnprintf(
345*5e7646d2SAndroid Build Coastguard Worker     char       *buffer,			/* O - Output buffer */
346*5e7646d2SAndroid Build Coastguard Worker     size_t     bufsize,			/* O - Size of output buffer */
347*5e7646d2SAndroid Build Coastguard Worker     const char *format,			/* I - printf-style format string */
348*5e7646d2SAndroid Build Coastguard Worker     va_list    ap)			/* I - Pointer to additional arguments */
349*5e7646d2SAndroid Build Coastguard Worker {
350*5e7646d2SAndroid Build Coastguard Worker   char		*bufptr,		/* Pointer to position in buffer */
351*5e7646d2SAndroid Build Coastguard Worker 		*bufend,		/* Pointer to end of buffer */
352*5e7646d2SAndroid Build Coastguard Worker 		size,			/* Size character (h, l, L) */
353*5e7646d2SAndroid Build Coastguard Worker 		type;			/* Format type character */
354*5e7646d2SAndroid Build Coastguard Worker   int		width,			/* Width of field */
355*5e7646d2SAndroid Build Coastguard Worker 		prec;			/* Number of characters of precision */
356*5e7646d2SAndroid Build Coastguard Worker   char		tformat[100],		/* Temporary format string for snprintf() */
357*5e7646d2SAndroid Build Coastguard Worker 		*tptr,			/* Pointer into temporary format */
358*5e7646d2SAndroid Build Coastguard Worker 		temp[1024];		/* Buffer for formatted numbers */
359*5e7646d2SAndroid Build Coastguard Worker   char		*s;			/* Pointer to string */
360*5e7646d2SAndroid Build Coastguard Worker   ssize_t	bytes;			/* Total number of bytes needed */
361*5e7646d2SAndroid Build Coastguard Worker 
362*5e7646d2SAndroid Build Coastguard Worker 
363*5e7646d2SAndroid Build Coastguard Worker   if (!buffer || bufsize < 2 || !format)
364*5e7646d2SAndroid Build Coastguard Worker     return (-1);
365*5e7646d2SAndroid Build Coastguard Worker 
366*5e7646d2SAndroid Build Coastguard Worker  /*
367*5e7646d2SAndroid Build Coastguard Worker   * Loop through the format string, formatting as needed...
368*5e7646d2SAndroid Build Coastguard Worker   */
369*5e7646d2SAndroid Build Coastguard Worker 
370*5e7646d2SAndroid Build Coastguard Worker   bufptr = buffer;
371*5e7646d2SAndroid Build Coastguard Worker   bufend = buffer + bufsize - 1;
372*5e7646d2SAndroid Build Coastguard Worker   bytes  = 0;
373*5e7646d2SAndroid Build Coastguard Worker 
374*5e7646d2SAndroid Build Coastguard Worker   while (*format)
375*5e7646d2SAndroid Build Coastguard Worker   {
376*5e7646d2SAndroid Build Coastguard Worker     if (*format == '%')
377*5e7646d2SAndroid Build Coastguard Worker     {
378*5e7646d2SAndroid Build Coastguard Worker       tptr = tformat;
379*5e7646d2SAndroid Build Coastguard Worker       *tptr++ = *format++;
380*5e7646d2SAndroid Build Coastguard Worker 
381*5e7646d2SAndroid Build Coastguard Worker       if (*format == '%')
382*5e7646d2SAndroid Build Coastguard Worker       {
383*5e7646d2SAndroid Build Coastguard Worker         if (bufptr < bufend)
384*5e7646d2SAndroid Build Coastguard Worker 	  *bufptr++ = *format;
385*5e7646d2SAndroid Build Coastguard Worker         bytes ++;
386*5e7646d2SAndroid Build Coastguard Worker         format ++;
387*5e7646d2SAndroid Build Coastguard Worker 	continue;
388*5e7646d2SAndroid Build Coastguard Worker       }
389*5e7646d2SAndroid Build Coastguard Worker       else if (strchr(" -+#\'", *format))
390*5e7646d2SAndroid Build Coastguard Worker         *tptr++ = *format++;
391*5e7646d2SAndroid Build Coastguard Worker 
392*5e7646d2SAndroid Build Coastguard Worker       if (*format == '*')
393*5e7646d2SAndroid Build Coastguard Worker       {
394*5e7646d2SAndroid Build Coastguard Worker        /*
395*5e7646d2SAndroid Build Coastguard Worker         * Get width from argument...
396*5e7646d2SAndroid Build Coastguard Worker 	*/
397*5e7646d2SAndroid Build Coastguard Worker 
398*5e7646d2SAndroid Build Coastguard Worker 	format ++;
399*5e7646d2SAndroid Build Coastguard Worker 	width = va_arg(ap, int);
400*5e7646d2SAndroid Build Coastguard Worker 
401*5e7646d2SAndroid Build Coastguard Worker 	snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", width);
402*5e7646d2SAndroid Build Coastguard Worker 	tptr += strlen(tptr);
403*5e7646d2SAndroid Build Coastguard Worker       }
404*5e7646d2SAndroid Build Coastguard Worker       else
405*5e7646d2SAndroid Build Coastguard Worker       {
406*5e7646d2SAndroid Build Coastguard Worker 	width = 0;
407*5e7646d2SAndroid Build Coastguard Worker 
408*5e7646d2SAndroid Build Coastguard Worker 	while (isdigit(*format & 255))
409*5e7646d2SAndroid Build Coastguard Worker 	{
410*5e7646d2SAndroid Build Coastguard Worker 	  if (tptr < (tformat + sizeof(tformat) - 1))
411*5e7646d2SAndroid Build Coastguard Worker 	    *tptr++ = *format;
412*5e7646d2SAndroid Build Coastguard Worker 
413*5e7646d2SAndroid Build Coastguard Worker 	  width = width * 10 + *format++ - '0';
414*5e7646d2SAndroid Build Coastguard Worker 	}
415*5e7646d2SAndroid Build Coastguard Worker       }
416*5e7646d2SAndroid Build Coastguard Worker 
417*5e7646d2SAndroid Build Coastguard Worker       if (*format == '.')
418*5e7646d2SAndroid Build Coastguard Worker       {
419*5e7646d2SAndroid Build Coastguard Worker 	if (tptr < (tformat + sizeof(tformat) - 1))
420*5e7646d2SAndroid Build Coastguard Worker 	  *tptr++ = *format;
421*5e7646d2SAndroid Build Coastguard Worker 
422*5e7646d2SAndroid Build Coastguard Worker         format ++;
423*5e7646d2SAndroid Build Coastguard Worker 
424*5e7646d2SAndroid Build Coastguard Worker         if (*format == '*')
425*5e7646d2SAndroid Build Coastguard Worker 	{
426*5e7646d2SAndroid Build Coastguard Worker          /*
427*5e7646d2SAndroid Build Coastguard Worker 	  * Get precision from argument...
428*5e7646d2SAndroid Build Coastguard Worker 	  */
429*5e7646d2SAndroid Build Coastguard Worker 
430*5e7646d2SAndroid Build Coastguard Worker 	  format ++;
431*5e7646d2SAndroid Build Coastguard Worker 	  prec = va_arg(ap, int);
432*5e7646d2SAndroid Build Coastguard Worker 
433*5e7646d2SAndroid Build Coastguard Worker 	  snprintf(tptr, sizeof(tformat) - (size_t)(tptr - tformat), "%d", prec);
434*5e7646d2SAndroid Build Coastguard Worker 	  tptr += strlen(tptr);
435*5e7646d2SAndroid Build Coastguard Worker 	}
436*5e7646d2SAndroid Build Coastguard Worker 	else
437*5e7646d2SAndroid Build Coastguard Worker 	{
438*5e7646d2SAndroid Build Coastguard Worker 	  prec = 0;
439*5e7646d2SAndroid Build Coastguard Worker 
440*5e7646d2SAndroid Build Coastguard Worker 	  while (isdigit(*format & 255))
441*5e7646d2SAndroid Build Coastguard Worker 	  {
442*5e7646d2SAndroid Build Coastguard Worker 	    if (tptr < (tformat + sizeof(tformat) - 1))
443*5e7646d2SAndroid Build Coastguard Worker 	      *tptr++ = *format;
444*5e7646d2SAndroid Build Coastguard Worker 
445*5e7646d2SAndroid Build Coastguard Worker 	    prec = prec * 10 + *format++ - '0';
446*5e7646d2SAndroid Build Coastguard Worker 	  }
447*5e7646d2SAndroid Build Coastguard Worker 	}
448*5e7646d2SAndroid Build Coastguard Worker       }
449*5e7646d2SAndroid Build Coastguard Worker 
450*5e7646d2SAndroid Build Coastguard Worker       if (*format == 'l' && format[1] == 'l')
451*5e7646d2SAndroid Build Coastguard Worker       {
452*5e7646d2SAndroid Build Coastguard Worker         size = 'L';
453*5e7646d2SAndroid Build Coastguard Worker 
454*5e7646d2SAndroid Build Coastguard Worker 	if (tptr < (tformat + sizeof(tformat) - 2))
455*5e7646d2SAndroid Build Coastguard Worker 	{
456*5e7646d2SAndroid Build Coastguard Worker 	  *tptr++ = 'l';
457*5e7646d2SAndroid Build Coastguard Worker 	  *tptr++ = 'l';
458*5e7646d2SAndroid Build Coastguard Worker 	}
459*5e7646d2SAndroid Build Coastguard Worker 
460*5e7646d2SAndroid Build Coastguard Worker 	format += 2;
461*5e7646d2SAndroid Build Coastguard Worker       }
462*5e7646d2SAndroid Build Coastguard Worker       else if (*format == 'h' || *format == 'l' || *format == 'L')
463*5e7646d2SAndroid Build Coastguard Worker       {
464*5e7646d2SAndroid Build Coastguard Worker 	if (tptr < (tformat + sizeof(tformat) - 1))
465*5e7646d2SAndroid Build Coastguard Worker 	  *tptr++ = *format;
466*5e7646d2SAndroid Build Coastguard Worker 
467*5e7646d2SAndroid Build Coastguard Worker         size = *format++;
468*5e7646d2SAndroid Build Coastguard Worker       }
469*5e7646d2SAndroid Build Coastguard Worker       else
470*5e7646d2SAndroid Build Coastguard Worker         size = 0;
471*5e7646d2SAndroid Build Coastguard Worker 
472*5e7646d2SAndroid Build Coastguard Worker       if (!*format)
473*5e7646d2SAndroid Build Coastguard Worker         break;
474*5e7646d2SAndroid Build Coastguard Worker 
475*5e7646d2SAndroid Build Coastguard Worker       if (tptr < (tformat + sizeof(tformat) - 1))
476*5e7646d2SAndroid Build Coastguard Worker         *tptr++ = *format;
477*5e7646d2SAndroid Build Coastguard Worker 
478*5e7646d2SAndroid Build Coastguard Worker       type  = *format++;
479*5e7646d2SAndroid Build Coastguard Worker       *tptr = '\0';
480*5e7646d2SAndroid Build Coastguard Worker 
481*5e7646d2SAndroid Build Coastguard Worker       switch (type)
482*5e7646d2SAndroid Build Coastguard Worker       {
483*5e7646d2SAndroid Build Coastguard Worker 	case 'E' : /* Floating point formats */
484*5e7646d2SAndroid Build Coastguard Worker 	case 'G' :
485*5e7646d2SAndroid Build Coastguard Worker 	case 'e' :
486*5e7646d2SAndroid Build Coastguard Worker 	case 'f' :
487*5e7646d2SAndroid Build Coastguard Worker 	case 'g' :
488*5e7646d2SAndroid Build Coastguard Worker 	    if ((size_t)(width + 2) > sizeof(temp))
489*5e7646d2SAndroid Build Coastguard Worker 	      break;
490*5e7646d2SAndroid Build Coastguard Worker 
491*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(temp, sizeof(temp), tformat, va_arg(ap, double));
492*5e7646d2SAndroid Build Coastguard Worker 
493*5e7646d2SAndroid Build Coastguard Worker             bytes += (int)strlen(temp);
494*5e7646d2SAndroid Build Coastguard Worker 
495*5e7646d2SAndroid Build Coastguard Worker             if (bufptr)
496*5e7646d2SAndroid Build Coastguard Worker 	    {
497*5e7646d2SAndroid Build Coastguard Worker 	      strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
498*5e7646d2SAndroid Build Coastguard Worker 	      bufptr += strlen(bufptr);
499*5e7646d2SAndroid Build Coastguard Worker 	    }
500*5e7646d2SAndroid Build Coastguard Worker 	    break;
501*5e7646d2SAndroid Build Coastguard Worker 
502*5e7646d2SAndroid Build Coastguard Worker         case 'B' : /* Integer formats */
503*5e7646d2SAndroid Build Coastguard Worker 	case 'X' :
504*5e7646d2SAndroid Build Coastguard Worker 	case 'b' :
505*5e7646d2SAndroid Build Coastguard Worker         case 'd' :
506*5e7646d2SAndroid Build Coastguard Worker 	case 'i' :
507*5e7646d2SAndroid Build Coastguard Worker 	case 'o' :
508*5e7646d2SAndroid Build Coastguard Worker 	case 'u' :
509*5e7646d2SAndroid Build Coastguard Worker 	case 'x' :
510*5e7646d2SAndroid Build Coastguard Worker 	    if ((size_t)(width + 2) > sizeof(temp))
511*5e7646d2SAndroid Build Coastguard Worker 	      break;
512*5e7646d2SAndroid Build Coastguard Worker 
513*5e7646d2SAndroid Build Coastguard Worker #  ifdef HAVE_LONG_LONG
514*5e7646d2SAndroid Build Coastguard Worker             if (size == 'L')
515*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(temp, sizeof(temp), tformat, va_arg(ap, long long));
516*5e7646d2SAndroid Build Coastguard Worker 	    else
517*5e7646d2SAndroid Build Coastguard Worker #  endif /* HAVE_LONG_LONG */
518*5e7646d2SAndroid Build Coastguard Worker             if (size == 'l')
519*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(temp, sizeof(temp), tformat, va_arg(ap, long));
520*5e7646d2SAndroid Build Coastguard Worker 	    else
521*5e7646d2SAndroid Build Coastguard Worker 	      snprintf(temp, sizeof(temp), tformat, va_arg(ap, int));
522*5e7646d2SAndroid Build Coastguard Worker 
523*5e7646d2SAndroid Build Coastguard Worker             bytes += (int)strlen(temp);
524*5e7646d2SAndroid Build Coastguard Worker 
525*5e7646d2SAndroid Build Coastguard Worker 	    if (bufptr)
526*5e7646d2SAndroid Build Coastguard Worker 	    {
527*5e7646d2SAndroid Build Coastguard Worker 	      strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
528*5e7646d2SAndroid Build Coastguard Worker 	      bufptr += strlen(bufptr);
529*5e7646d2SAndroid Build Coastguard Worker 	    }
530*5e7646d2SAndroid Build Coastguard Worker 	    break;
531*5e7646d2SAndroid Build Coastguard Worker 
532*5e7646d2SAndroid Build Coastguard Worker 	case 'p' : /* Pointer value */
533*5e7646d2SAndroid Build Coastguard Worker 	    if ((size_t)(width + 2) > sizeof(temp))
534*5e7646d2SAndroid Build Coastguard Worker 	      break;
535*5e7646d2SAndroid Build Coastguard Worker 
536*5e7646d2SAndroid Build Coastguard Worker 	    snprintf(temp, sizeof(temp), tformat, va_arg(ap, void *));
537*5e7646d2SAndroid Build Coastguard Worker 
538*5e7646d2SAndroid Build Coastguard Worker             bytes += (int)strlen(temp);
539*5e7646d2SAndroid Build Coastguard Worker 
540*5e7646d2SAndroid Build Coastguard Worker 	    if (bufptr)
541*5e7646d2SAndroid Build Coastguard Worker 	    {
542*5e7646d2SAndroid Build Coastguard Worker 	      strlcpy(bufptr, temp, (size_t)(bufend - bufptr));
543*5e7646d2SAndroid Build Coastguard Worker 	      bufptr += strlen(bufptr);
544*5e7646d2SAndroid Build Coastguard Worker 	    }
545*5e7646d2SAndroid Build Coastguard Worker 	    break;
546*5e7646d2SAndroid Build Coastguard Worker 
547*5e7646d2SAndroid Build Coastguard Worker         case 'c' : /* Character or character array */
548*5e7646d2SAndroid Build Coastguard Worker 	    bytes += width;
549*5e7646d2SAndroid Build Coastguard Worker 
550*5e7646d2SAndroid Build Coastguard Worker 	    if (bufptr)
551*5e7646d2SAndroid Build Coastguard Worker 	    {
552*5e7646d2SAndroid Build Coastguard Worker 	      if (width <= 1)
553*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = (char)va_arg(ap, int);
554*5e7646d2SAndroid Build Coastguard Worker 	      else
555*5e7646d2SAndroid Build Coastguard Worker 	      {
556*5e7646d2SAndroid Build Coastguard Worker 		if ((bufptr + width) > bufend)
557*5e7646d2SAndroid Build Coastguard Worker 		  width = (int)(bufend - bufptr);
558*5e7646d2SAndroid Build Coastguard Worker 
559*5e7646d2SAndroid Build Coastguard Worker 		memcpy(bufptr, va_arg(ap, char *), (size_t)width);
560*5e7646d2SAndroid Build Coastguard Worker 		bufptr += width;
561*5e7646d2SAndroid Build Coastguard Worker 	      }
562*5e7646d2SAndroid Build Coastguard Worker 	    }
563*5e7646d2SAndroid Build Coastguard Worker 	    break;
564*5e7646d2SAndroid Build Coastguard Worker 
565*5e7646d2SAndroid Build Coastguard Worker 	case 's' : /* String */
566*5e7646d2SAndroid Build Coastguard Worker 	    if ((s = va_arg(ap, char *)) == NULL)
567*5e7646d2SAndroid Build Coastguard Worker 	      s = "(null)";
568*5e7646d2SAndroid Build Coastguard Worker 
569*5e7646d2SAndroid Build Coastguard Worker            /*
570*5e7646d2SAndroid Build Coastguard Worker 	    * Copy the C string, replacing control chars and \ with
571*5e7646d2SAndroid Build Coastguard Worker 	    * C character escapes...
572*5e7646d2SAndroid Build Coastguard Worker 	    */
573*5e7646d2SAndroid Build Coastguard Worker 
574*5e7646d2SAndroid Build Coastguard Worker             for (bufend --; *s && bufptr < bufend; s ++)
575*5e7646d2SAndroid Build Coastguard Worker 	    {
576*5e7646d2SAndroid Build Coastguard Worker 	      if (*s == '\n')
577*5e7646d2SAndroid Build Coastguard Worker 	      {
578*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '\\';
579*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = 'n';
580*5e7646d2SAndroid Build Coastguard Worker 		bytes += 2;
581*5e7646d2SAndroid Build Coastguard Worker 	      }
582*5e7646d2SAndroid Build Coastguard Worker 	      else if (*s == '\r')
583*5e7646d2SAndroid Build Coastguard Worker 	      {
584*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '\\';
585*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = 'r';
586*5e7646d2SAndroid Build Coastguard Worker 		bytes += 2;
587*5e7646d2SAndroid Build Coastguard Worker 	      }
588*5e7646d2SAndroid Build Coastguard Worker 	      else if (*s == '\t')
589*5e7646d2SAndroid Build Coastguard Worker 	      {
590*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '\\';
591*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = 't';
592*5e7646d2SAndroid Build Coastguard Worker 		bytes += 2;
593*5e7646d2SAndroid Build Coastguard Worker 	      }
594*5e7646d2SAndroid Build Coastguard Worker 	      else if (*s == '\\')
595*5e7646d2SAndroid Build Coastguard Worker 	      {
596*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '\\';
597*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = '\\';
598*5e7646d2SAndroid Build Coastguard Worker 		bytes += 2;
599*5e7646d2SAndroid Build Coastguard Worker 	      }
600*5e7646d2SAndroid Build Coastguard Worker 	      else if (*s == '\'')
601*5e7646d2SAndroid Build Coastguard Worker 	      {
602*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '\\';
603*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = '\'';
604*5e7646d2SAndroid Build Coastguard Worker 		bytes += 2;
605*5e7646d2SAndroid Build Coastguard Worker 	      }
606*5e7646d2SAndroid Build Coastguard Worker 	      else if (*s == '\"')
607*5e7646d2SAndroid Build Coastguard Worker 	      {
608*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '\\';
609*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = '\"';
610*5e7646d2SAndroid Build Coastguard Worker 		bytes += 2;
611*5e7646d2SAndroid Build Coastguard Worker 	      }
612*5e7646d2SAndroid Build Coastguard Worker 	      else if ((*s & 255) < ' ')
613*5e7646d2SAndroid Build Coastguard Worker 	      {
614*5e7646d2SAndroid Build Coastguard Worker 	        if ((bufptr + 2) >= bufend)
615*5e7646d2SAndroid Build Coastguard Worker 	          break;
616*5e7646d2SAndroid Build Coastguard Worker 
617*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = '\\';
618*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = '0';
619*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = '0' + *s / 8;
620*5e7646d2SAndroid Build Coastguard Worker 		*bufptr++ = '0' + (*s & 7);
621*5e7646d2SAndroid Build Coastguard Worker 		bytes += 4;
622*5e7646d2SAndroid Build Coastguard Worker 	      }
623*5e7646d2SAndroid Build Coastguard Worker 	      else
624*5e7646d2SAndroid Build Coastguard Worker 	      {
625*5e7646d2SAndroid Build Coastguard Worker 	        *bufptr++ = *s;
626*5e7646d2SAndroid Build Coastguard Worker 		bytes ++;
627*5e7646d2SAndroid Build Coastguard Worker 	      }
628*5e7646d2SAndroid Build Coastguard Worker             }
629*5e7646d2SAndroid Build Coastguard Worker 
630*5e7646d2SAndroid Build Coastguard Worker             bufend ++;
631*5e7646d2SAndroid Build Coastguard Worker 	    break;
632*5e7646d2SAndroid Build Coastguard Worker 
633*5e7646d2SAndroid Build Coastguard Worker 	case 'n' : /* Output number of chars so far */
634*5e7646d2SAndroid Build Coastguard Worker 	    *(va_arg(ap, int *)) = (int)bytes;
635*5e7646d2SAndroid Build Coastguard Worker 	    break;
636*5e7646d2SAndroid Build Coastguard Worker       }
637*5e7646d2SAndroid Build Coastguard Worker     }
638*5e7646d2SAndroid Build Coastguard Worker     else
639*5e7646d2SAndroid Build Coastguard Worker     {
640*5e7646d2SAndroid Build Coastguard Worker       bytes ++;
641*5e7646d2SAndroid Build Coastguard Worker 
642*5e7646d2SAndroid Build Coastguard Worker       if (bufptr < bufend)
643*5e7646d2SAndroid Build Coastguard Worker         *bufptr++ = *format;
644*5e7646d2SAndroid Build Coastguard Worker 
645*5e7646d2SAndroid Build Coastguard Worker       format ++;
646*5e7646d2SAndroid Build Coastguard Worker     }
647*5e7646d2SAndroid Build Coastguard Worker   }
648*5e7646d2SAndroid Build Coastguard Worker 
649*5e7646d2SAndroid Build Coastguard Worker  /*
650*5e7646d2SAndroid Build Coastguard Worker   * Nul-terminate the string and return the number of characters needed.
651*5e7646d2SAndroid Build Coastguard Worker   */
652*5e7646d2SAndroid Build Coastguard Worker 
653*5e7646d2SAndroid Build Coastguard Worker   *bufptr = '\0';
654*5e7646d2SAndroid Build Coastguard Worker 
655*5e7646d2SAndroid Build Coastguard Worker   return (bytes);
656*5e7646d2SAndroid Build Coastguard Worker }
657