Imported Upstream version 2.3.1
[platform/upstream/cups.git] / scheduler / statbuf.c
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
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 */
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 */
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 }