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