1 /*
2 * Status buffer routines for the CUPS scheduler.
3 *
4 * Copyright 2007-2014 by Apple Inc.
5 * Copyright 1997-2006 by Easy Software Products, all rights reserved.
6 *
7 * Licensed under Apache License v2.0. See the file "LICENSE" for more information.
8 */
9
10 /*
11 * Include necessary headers...
12 */
13
14 #include "cupsd.h"
15 #include <stdarg.h>
16
17
18 /*
19 * 'cupsdStatBufDelete()' - Destroy a status buffer.
20 */
21
22 void
cupsdStatBufDelete(cupsd_statbuf_t * sb)23 cupsdStatBufDelete(cupsd_statbuf_t *sb) /* I - Status buffer */
24 {
25 /*
26 * Range check input...
27 */
28
29 if (!sb)
30 return;
31
32 /*
33 * Close the status pipe and free memory used...
34 */
35
36 close(sb->fd);
37
38 free(sb);
39 }
40
41
42 /*
43 * 'cupsdStatBufNew()' - Create a new status buffer.
44 */
45
46 cupsd_statbuf_t * /* O - New status buffer */
cupsdStatBufNew(int fd,const char * prefix,...)47 cupsdStatBufNew(int fd, /* I - File descriptor of pipe */
48 const char *prefix, /* I - Printf-style prefix string */
49 ...) /* I - Additional args as needed */
50 {
51 cupsd_statbuf_t *sb; /* New status buffer */
52 va_list ap; /* Argument list */
53
54
55 /*
56 * Range check input...
57 */
58
59 if (fd < 0)
60 return (NULL);
61
62 /*
63 * Allocate the status buffer...
64 */
65
66 if ((sb = calloc(1, sizeof(cupsd_statbuf_t))) != NULL)
67 {
68 /*
69 * Assign the file descriptor...
70 */
71
72 sb->fd = fd;
73
74 /*
75 * Format the prefix string, if any. This is usually "[Job 123]"
76 * or "[Sub 123]", and so forth.
77 */
78
79 if (prefix)
80 {
81 /*
82 * Printf-style prefix string...
83 */
84
85 va_start(ap, prefix);
86 vsnprintf(sb->prefix, sizeof(sb->prefix), prefix, ap);
87 va_end(ap);
88 }
89 else
90 {
91 /*
92 * No prefix string...
93 */
94
95 sb->prefix[0] = '\0';
96 }
97 }
98
99 return (sb);
100 }
101
102
103 /*
104 * 'cupsdStatBufUpdate()' - Update the status buffer.
105 */
106
107 char * /* O - Line from buffer, "", or NULL */
cupsdStatBufUpdate(cupsd_statbuf_t * sb,int * loglevel,char * line,int linelen)108 cupsdStatBufUpdate(
109 cupsd_statbuf_t *sb, /* I - Status buffer */
110 int *loglevel, /* O - Log level */
111 char *line, /* I - Line buffer */
112 int linelen) /* I - Size of line buffer */
113 {
114 int bytes; /* Number of bytes read */
115 char *lineptr, /* Pointer to end of line in buffer */
116 *message; /* Pointer to message text */
117
118
119 /*
120 * Check if the buffer already contains a full line...
121 */
122
123 if ((lineptr = strchr(sb->buffer, '\n')) == NULL)
124 {
125 /*
126 * No, read more data...
127 */
128
129 if ((bytes = read(sb->fd, sb->buffer + sb->bufused, (size_t)(CUPSD_SB_BUFFER_SIZE - sb->bufused - 1))) > 0)
130 {
131 sb->bufused += bytes;
132 sb->buffer[sb->bufused] = '\0';
133
134 /*
135 * Guard against a line longer than the max buffer size...
136 */
137
138 if ((lineptr = strchr(sb->buffer, '\n')) == NULL &&
139 sb->bufused == (CUPSD_SB_BUFFER_SIZE - 1))
140 lineptr = sb->buffer + sb->bufused;
141 }
142 else if (bytes < 0 && errno == EINTR)
143 {
144 /*
145 * Return an empty line if we are interrupted...
146 */
147
148 *loglevel = CUPSD_LOG_NONE;
149 line[0] = '\0';
150
151 return (line);
152 }
153 else
154 {
155 /*
156 * End-of-file, so use the whole buffer...
157 */
158
159 lineptr = sb->buffer + sb->bufused;
160 *lineptr = '\0';
161 }
162
163 /*
164 * Final check for end-of-file...
165 */
166
167 if (sb->bufused == 0 && bytes == 0)
168 lineptr = NULL;
169 }
170
171 if (!lineptr)
172 {
173 /*
174 * End of file...
175 */
176
177 *loglevel = CUPSD_LOG_NONE;
178 line[0] = '\0';
179
180 return (NULL);
181 }
182
183 /*
184 * Terminate the line and process it...
185 */
186
187 *lineptr++ = '\0';
188
189 /*
190 * Figure out the logging level...
191 */
192
193 if (!strncmp(sb->buffer, "EMERG:", 6))
194 {
195 *loglevel = CUPSD_LOG_EMERG;
196 message = sb->buffer + 6;
197 }
198 else if (!strncmp(sb->buffer, "ALERT:", 6))
199 {
200 *loglevel = CUPSD_LOG_ALERT;
201 message = sb->buffer + 6;
202 }
203 else if (!strncmp(sb->buffer, "CRIT:", 5))
204 {
205 *loglevel = CUPSD_LOG_CRIT;
206 message = sb->buffer + 5;
207 }
208 else if (!strncmp(sb->buffer, "ERROR:", 6))
209 {
210 *loglevel = CUPSD_LOG_ERROR;
211 message = sb->buffer + 6;
212 }
213 else if (!strncmp(sb->buffer, "WARNING:", 8))
214 {
215 *loglevel = CUPSD_LOG_WARN;
216 message = sb->buffer + 8;
217 }
218 else if (!strncmp(sb->buffer, "NOTICE:", 7))
219 {
220 *loglevel = CUPSD_LOG_NOTICE;
221 message = sb->buffer + 7;
222 }
223 else if (!strncmp(sb->buffer, "INFO:", 5))
224 {
225 *loglevel = CUPSD_LOG_INFO;
226 message = sb->buffer + 5;
227 }
228 else if (!strncmp(sb->buffer, "DEBUG:", 6))
229 {
230 *loglevel = CUPSD_LOG_DEBUG;
231 message = sb->buffer + 6;
232 }
233 else if (!strncmp(sb->buffer, "DEBUG2:", 7))
234 {
235 *loglevel = CUPSD_LOG_DEBUG2;
236 message = sb->buffer + 7;
237 }
238 else if (!strncmp(sb->buffer, "PAGE:", 5))
239 {
240 *loglevel = CUPSD_LOG_PAGE;
241 message = sb->buffer + 5;
242 }
243 else if (!strncmp(sb->buffer, "STATE:", 6))
244 {
245 *loglevel = CUPSD_LOG_STATE;
246 message = sb->buffer + 6;
247 }
248 else if (!strncmp(sb->buffer, "JOBSTATE:", 9))
249 {
250 *loglevel = CUPSD_LOG_JOBSTATE;
251 message = sb->buffer + 9;
252 }
253 else if (!strncmp(sb->buffer, "ATTR:", 5))
254 {
255 *loglevel = CUPSD_LOG_ATTR;
256 message = sb->buffer + 5;
257 }
258 else if (!strncmp(sb->buffer, "PPD:", 4))
259 {
260 *loglevel = CUPSD_LOG_PPD;
261 message = sb->buffer + 4;
262 }
263 else
264 {
265 *loglevel = CUPSD_LOG_DEBUG;
266 message = sb->buffer;
267 }
268
269 /*
270 * Skip leading whitespace in the message...
271 */
272
273 while (isspace(*message & 255))
274 message ++;
275
276 /*
277 * Send it to the log file as needed...
278 */
279
280 if (sb->prefix[0])
281 {
282 if (*loglevel > CUPSD_LOG_NONE &&
283 (*loglevel != CUPSD_LOG_INFO || LogLevel >= CUPSD_LOG_DEBUG))
284 {
285 /*
286 * General status message; send it to the error_log file...
287 */
288
289 if (message[0] == '[')
290 cupsdLogMessage(*loglevel, "%s", message);
291 else
292 cupsdLogMessage(*loglevel, "%s %s", sb->prefix, message);
293 }
294 else if (*loglevel < CUPSD_LOG_NONE && LogLevel >= CUPSD_LOG_DEBUG)
295 cupsdLogMessage(CUPSD_LOG_DEBUG2, "%s %s", sb->prefix, sb->buffer);
296 }
297
298 /*
299 * Copy the message to the line buffer...
300 */
301
302 strlcpy(line, message, (size_t)linelen);
303
304 /*
305 * Copy over the buffer data we've used up...
306 */
307
308 if (lineptr < sb->buffer + sb->bufused)
309 _cups_strcpy(sb->buffer, lineptr);
310
311 sb->bufused -= lineptr - sb->buffer;
312
313 if (sb->bufused < 0)
314 sb->bufused = 0;
315
316 return (line);
317 }
318