Imported Upstream version 2.1.2
[platform/upstream/cups.git] / scheduler / statbuf.c
1 /*
2  * "$Id: statbuf.c 11594 2014-02-14 20:09:01Z 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
28 void
29 cupsdStatBufDelete(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
52 cupsd_statbuf_t *                       /* O - New status buffer */
53 cupsdStatBufNew(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
113 char *                                  /* O - Line from buffer, "", or NULL */
114 cupsdStatBufUpdate(
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 11594 2014-02-14 20:09:01Z msweet $".
328  */