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