]>
Commit | Line | Data |
---|---|---|
ef416fc2 | 1 | /* |
996acce8 | 2 | * Log file routines for the CUPS scheduler. |
ef416fc2 | 3 | * |
e7729c5a | 4 | * Copyright 2007-2017 by Apple Inc. |
996acce8 | 5 | * Copyright 1997-2007 by Easy Software Products, all rights reserved. |
ef416fc2 | 6 | * |
e3101897 | 7 | * Licensed under Apache License v2.0. See the file "LICENSE" for more information. |
ef416fc2 | 8 | */ |
9 | ||
10 | /* | |
11 | * Include necessary headers... | |
12 | */ | |
13 | ||
14 | #include "cupsd.h" | |
15 | #include <stdarg.h> | |
0dc4a6bf MS |
16 | #ifdef HAVE_ASL_H |
17 | # include <asl.h> | |
18 | #elif defined(HAVE_SYSTEMD_SD_JOURNAL_H) | |
19 | # define SD_JOURNAL_SUPPRESS_LOCATION | |
20 | # include <systemd/sd-journal.h> | |
21 | #endif /* HAVE_ASL_H */ | |
b423cd4c | 22 | #include <syslog.h> |
ef416fc2 | 23 | |
24 | ||
0dc4a6bf MS |
25 | /* |
26 | * Constants for log keys from PWG 5110.3 (PWG Common Log Format)... | |
27 | */ | |
28 | ||
29 | #define PWG_DeviceUUID "DUU" | |
30 | #define PWG_Event "E" | |
31 | #define PWG_LogNaturalLanguage "NL" | |
32 | #define PWG_Status "S" | |
33 | #define PWG_ServiceURI "URI" | |
34 | #define PWG_UserHost "UH" | |
35 | #define PWG_UserName "UN" | |
36 | #define PWG_UserURI "UU" | |
37 | #define PWG_ServiceIsAcceptingJobs "IAJ" | |
38 | #define PWG_ServiceState "ST" | |
39 | #define PWG_ServiceStateReasons "SR" | |
40 | #define PWG_ServiceUUID "SUU" | |
41 | #define PWG_JobID "JID" | |
42 | #define PWG_JobUUID "JUU" | |
43 | #define PWG_JobImagesCompleted "JIM" | |
44 | #define PWG_JobImpressionsCompleted "JIC" | |
45 | #define PWG_JobDestinationURI "JD" | |
46 | #define PWG_JobState "JS" | |
47 | #define PWG_JobStateReasons "JR" | |
48 | #define PWG_JobAccountingID "JA" | |
49 | #define PWG_JobAcountingUserName "JAUN" | |
50 | #define PWG_JobAccountingUserURI "JAUU" | |
51 | ||
52 | ||
75bd9771 MS |
53 | /* |
54 | * Local globals... | |
55 | */ | |
56 | ||
28a463e0 MS |
57 | static _cups_mutex_t log_mutex = _CUPS_MUTEX_INITIALIZER; |
58 | /* Mutex for logging */ | |
7e86f2f6 | 59 | static size_t log_linesize = 0; /* Size of line for output file */ |
75bd9771 MS |
60 | static char *log_line = NULL; /* Line for output file */ |
61 | ||
0dc4a6bf MS |
62 | #ifdef HAVE_ASL_H |
63 | static const int log_levels[] = /* ASL levels... */ | |
64 | { | |
65 | ASL_LEVEL_EMERG, | |
66 | ASL_LEVEL_EMERG, | |
67 | ASL_LEVEL_ALERT, | |
68 | ASL_LEVEL_CRIT, | |
69 | ASL_LEVEL_ERR, | |
70 | ASL_LEVEL_WARNING, | |
71 | ASL_LEVEL_NOTICE, | |
72 | ASL_LEVEL_INFO, | |
73 | ASL_LEVEL_DEBUG, | |
74 | ASL_LEVEL_DEBUG | |
75 | }; | |
76 | #elif defined(HAVE_VSYSLOG) || defined(HAVE_SYSTEMD_SD_JOURNAL_H) | |
77 | static const int log_levels[] = /* SYSLOG levels... */ | |
cb7f98ee MS |
78 | { |
79 | 0, | |
80 | LOG_EMERG, | |
81 | LOG_ALERT, | |
82 | LOG_CRIT, | |
83 | LOG_ERR, | |
84 | LOG_WARNING, | |
85 | LOG_NOTICE, | |
86 | LOG_INFO, | |
87 | LOG_DEBUG, | |
88 | LOG_DEBUG | |
89 | }; | |
0dc4a6bf | 90 | #endif /* HAVE_ASL_H */ |
cb7f98ee | 91 | |
75bd9771 | 92 | |
ef416fc2 | 93 | /* |
94 | * Local functions... | |
95 | */ | |
96 | ||
005dd1eb | 97 | static int format_log_line(const char *message, va_list ap); |
ef416fc2 | 98 | |
99 | ||
22c9029b MS |
100 | /* |
101 | * 'cupsdCheckLogFile()' - Open/rotate a log file if it needs it. | |
102 | */ | |
103 | ||
104 | int /* O - 1 if log file open */ | |
105 | cupsdCheckLogFile(cups_file_t **lf, /* IO - Log file */ | |
106 | const char *logname) /* I - Log filename */ | |
107 | { | |
108 | char backname[1024], /* Backup log filename */ | |
109 | filename[1024], /* Formatted log filename */ | |
110 | *ptr; /* Pointer into filename */ | |
111 | const char *logptr; /* Pointer into log filename */ | |
112 | ||
113 | ||
114 | /* | |
115 | * See if we have a log file to check... | |
116 | */ | |
117 | ||
118 | if (!lf || !logname || !logname[0]) | |
119 | return (1); | |
120 | ||
a1797929 MS |
121 | /* |
122 | * Handle logging to stderr... | |
123 | */ | |
124 | ||
125 | if (!strcmp(logname, "stderr")) | |
126 | { | |
127 | *lf = LogStderr; | |
128 | return (1); | |
129 | } | |
130 | ||
22c9029b MS |
131 | /* |
132 | * Format the filename as needed... | |
133 | */ | |
134 | ||
135 | if (!*lf || | |
136 | (strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize && | |
137 | MaxLogSize > 0)) | |
138 | { | |
139 | /* | |
140 | * Handle format strings... | |
141 | */ | |
142 | ||
143 | filename[sizeof(filename) - 1] = '\0'; | |
144 | ||
145 | if (logname[0] != '/') | |
146 | { | |
147 | strlcpy(filename, ServerRoot, sizeof(filename)); | |
148 | strlcat(filename, "/", sizeof(filename)); | |
149 | } | |
150 | else | |
151 | filename[0] = '\0'; | |
152 | ||
153 | for (logptr = logname, ptr = filename + strlen(filename); | |
154 | *logptr && ptr < (filename + sizeof(filename) - 1); | |
155 | logptr ++) | |
156 | if (*logptr == '%') | |
157 | { | |
158 | /* | |
159 | * Format spec... | |
160 | */ | |
161 | ||
162 | logptr ++; | |
163 | if (*logptr == 's') | |
164 | { | |
165 | /* | |
166 | * Insert the server name... | |
167 | */ | |
168 | ||
7e86f2f6 | 169 | strlcpy(ptr, ServerName, sizeof(filename) - (size_t)(ptr - filename)); |
22c9029b MS |
170 | ptr += strlen(ptr); |
171 | } | |
172 | else | |
173 | { | |
174 | /* | |
175 | * Otherwise just insert the character... | |
176 | */ | |
177 | ||
178 | *ptr++ = *logptr; | |
179 | } | |
180 | } | |
181 | else | |
182 | *ptr++ = *logptr; | |
183 | ||
184 | *ptr = '\0'; | |
185 | } | |
186 | ||
187 | /* | |
188 | * See if the log file is open... | |
189 | */ | |
190 | ||
191 | if (!*lf) | |
192 | { | |
193 | /* | |
194 | * Nope, open the log file... | |
195 | */ | |
196 | ||
197 | if ((*lf = cupsFileOpen(filename, "a")) == NULL) | |
198 | { | |
199 | /* | |
200 | * If the file is in CUPS_LOGDIR then try to create a missing directory... | |
201 | */ | |
202 | ||
203 | if (!strncmp(filename, CUPS_LOGDIR, strlen(CUPS_LOGDIR))) | |
204 | { | |
205 | /* | |
206 | * Try updating the permissions of the containing log directory, using | |
207 | * the log file permissions as a basis... | |
208 | */ | |
209 | ||
7e86f2f6 | 210 | mode_t log_dir_perm = (mode_t)(0300 | LogFilePerm); |
22c9029b MS |
211 | /* LogFilePerm + owner write/search */ |
212 | if (log_dir_perm & 0040) | |
213 | log_dir_perm |= 0010; /* Add group search */ | |
214 | if (log_dir_perm & 0004) | |
215 | log_dir_perm |= 0001; /* Add other search */ | |
216 | ||
7e86f2f6 | 217 | cupsdCheckPermissions(CUPS_LOGDIR, NULL, log_dir_perm, RunUser, Group, 1, -1); |
22c9029b MS |
218 | |
219 | *lf = cupsFileOpen(filename, "a"); | |
220 | } | |
221 | ||
222 | if (*lf == NULL) | |
223 | { | |
250bb8a9 | 224 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
0dc4a6bf | 225 | sd_journal_print(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); |
0dc4a6bf MS |
226 | #else |
227 | syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); | |
250bb8a9 | 228 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ |
22c9029b MS |
229 | |
230 | if (FatalErrors & CUPSD_FATAL_LOG) | |
231 | cupsdEndProcess(getpid(), 0); | |
232 | ||
233 | return (0); | |
234 | } | |
235 | } | |
236 | ||
237 | if (strncmp(filename, "/dev/", 5)) | |
238 | { | |
239 | /* | |
240 | * Change ownership and permissions of non-device logs... | |
241 | */ | |
242 | ||
243 | fchown(cupsFileNumber(*lf), RunUser, Group); | |
244 | fchmod(cupsFileNumber(*lf), LogFilePerm); | |
245 | } | |
246 | } | |
247 | ||
248 | /* | |
249 | * Do we need to rotate the log? | |
250 | */ | |
251 | ||
252 | if (strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize && | |
253 | MaxLogSize > 0) | |
254 | { | |
255 | /* | |
256 | * Rotate log file... | |
257 | */ | |
258 | ||
259 | cupsFileClose(*lf); | |
260 | ||
5a9febac | 261 | strlcpy(backname, filename, sizeof(backname)); |
22c9029b MS |
262 | strlcat(backname, ".O", sizeof(backname)); |
263 | ||
264 | unlink(backname); | |
265 | rename(filename, backname); | |
266 | ||
267 | if ((*lf = cupsFileOpen(filename, "a")) == NULL) | |
268 | { | |
250bb8a9 MS |
269 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
270 | sd_journal_print(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); | |
0dc4a6bf MS |
271 | |
272 | #else | |
250bb8a9 MS |
273 | syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename, strerror(errno)); |
274 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ | |
22c9029b MS |
275 | |
276 | if (FatalErrors & CUPSD_FATAL_LOG) | |
277 | cupsdEndProcess(getpid(), 0); | |
278 | ||
279 | return (0); | |
280 | } | |
281 | ||
282 | /* | |
283 | * Change ownership and permissions of non-device logs... | |
284 | */ | |
285 | ||
286 | fchown(cupsFileNumber(*lf), RunUser, Group); | |
287 | fchmod(cupsFileNumber(*lf), LogFilePerm); | |
288 | } | |
289 | ||
290 | return (1); | |
291 | } | |
292 | ||
293 | ||
ef416fc2 | 294 | /* |
295 | * 'cupsdGetDateTime()' - Returns a pointer to a date/time string. | |
296 | */ | |
297 | ||
298 | char * /* O - Date/time string */ | |
dfd5680b MS |
299 | cupsdGetDateTime(struct timeval *t, /* I - Time value or NULL for current */ |
300 | cupsd_time_t format) /* I - Format to use */ | |
ef416fc2 | 301 | { |
dfd5680b MS |
302 | struct timeval curtime; /* Current time value */ |
303 | struct tm *date; /* Date/time value */ | |
304 | static struct timeval last_time = { 0, 0 }; | |
305 | /* Last time we formatted */ | |
306 | static char s[1024]; /* Date/time string */ | |
ef416fc2 | 307 | static const char * const months[12] =/* Months */ |
308 | { | |
309 | "Jan", | |
310 | "Feb", | |
311 | "Mar", | |
312 | "Apr", | |
313 | "May", | |
314 | "Jun", | |
315 | "Jul", | |
316 | "Aug", | |
317 | "Sep", | |
318 | "Oct", | |
319 | "Nov", | |
320 | "Dec" | |
321 | }; | |
322 | ||
323 | ||
839a51c8 MS |
324 | /* |
325 | * Make sure we have a valid time... | |
326 | */ | |
327 | ||
328 | if (!t) | |
dfd5680b MS |
329 | { |
330 | gettimeofday(&curtime, NULL); | |
331 | t = &curtime; | |
332 | } | |
839a51c8 | 333 | |
dfd5680b MS |
334 | if (t->tv_sec != last_time.tv_sec || |
335 | (LogTimeFormat == CUPSD_TIME_USECS && t->tv_usec != last_time.tv_usec)) | |
ef416fc2 | 336 | { |
dfd5680b | 337 | last_time = *t; |
ef416fc2 | 338 | |
339 | /* | |
340 | * Get the date and time from the UNIX time value, and then format it | |
341 | * into a string. Note that we *can't* use the strftime() function since | |
342 | * it is localized and will seriously confuse automatic programs if the | |
343 | * month names are in the wrong language! | |
344 | * | |
345 | * Also, we use the "timezone" variable that contains the current timezone | |
346 | * offset from GMT in seconds so that we are reporting local time in the | |
347 | * log files. If you want GMT, set the TZ environment variable accordingly | |
348 | * before starting the scheduler. | |
349 | * | |
350 | * (*BSD and Darwin store the timezone offset in the tm structure) | |
351 | */ | |
352 | ||
dfd5680b | 353 | date = localtime(&(t->tv_sec)); |
ef416fc2 | 354 | |
dfd5680b MS |
355 | if (format == CUPSD_TIME_STANDARD) |
356 | snprintf(s, sizeof(s), "[%02d/%s/%04d:%02d:%02d:%02d %+03ld%02ld]", | |
357 | date->tm_mday, months[date->tm_mon], 1900 + date->tm_year, | |
358 | date->tm_hour, date->tm_min, date->tm_sec, | |
359 | #ifdef HAVE_TM_GMTOFF | |
360 | date->tm_gmtoff / 3600, (date->tm_gmtoff / 60) % 60); | |
361 | #else | |
362 | timezone / 3600, (timezone / 60) % 60); | |
363 | #endif /* HAVE_TM_GMTOFF */ | |
364 | else | |
365 | snprintf(s, sizeof(s), "[%02d/%s/%04d:%02d:%02d:%02d.%06d %+03ld%02ld]", | |
366 | date->tm_mday, months[date->tm_mon], 1900 + date->tm_year, | |
bf3816c7 | 367 | date->tm_hour, date->tm_min, date->tm_sec, (int)t->tv_usec, |
ef416fc2 | 368 | #ifdef HAVE_TM_GMTOFF |
dfd5680b | 369 | date->tm_gmtoff / 3600, (date->tm_gmtoff / 60) % 60); |
ef416fc2 | 370 | #else |
dfd5680b | 371 | timezone / 3600, (timezone / 60) % 60); |
ef416fc2 | 372 | #endif /* HAVE_TM_GMTOFF */ |
373 | } | |
374 | ||
375 | return (s); | |
376 | } | |
377 | ||
378 | ||
22c9029b MS |
379 | /* |
380 | * 'cupsdLogFCMessage()' - Log a file checking message. | |
381 | */ | |
382 | ||
383 | void | |
384 | cupsdLogFCMessage( | |
385 | void *context, /* I - Printer (if any) */ | |
386 | _cups_fc_result_t result, /* I - Check result */ | |
387 | const char *message) /* I - Message to log */ | |
388 | { | |
389 | cupsd_printer_t *p = (cupsd_printer_t *)context; | |
390 | /* Printer */ | |
391 | cupsd_loglevel_t level; /* Log level */ | |
392 | ||
393 | ||
394 | if (result == _CUPS_FILE_CHECK_OK) | |
395 | level = CUPSD_LOG_DEBUG2; | |
396 | else | |
397 | level = CUPSD_LOG_ERROR; | |
398 | ||
399 | if (p) | |
400 | { | |
401 | cupsdLogMessage(level, "%s: %s", p->name, message); | |
402 | ||
403 | if (result == _CUPS_FILE_CHECK_MISSING || | |
404 | result == _CUPS_FILE_CHECK_WRONG_TYPE) | |
405 | { | |
406 | strlcpy(p->state_message, message, sizeof(p->state_message)); | |
407 | ||
408 | if (cupsdSetPrinterReasons(p, "+cups-missing-filter-warning")) | |
409 | cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, "%s", message); | |
410 | } | |
88f9aafc MS |
411 | else if (result == _CUPS_FILE_CHECK_PERMISSIONS || |
412 | result == _CUPS_FILE_CHECK_RELATIVE_PATH) | |
22c9029b MS |
413 | { |
414 | strlcpy(p->state_message, message, sizeof(p->state_message)); | |
415 | ||
416 | if (cupsdSetPrinterReasons(p, "+cups-insecure-filter-warning")) | |
417 | cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE, p, NULL, "%s", message); | |
418 | } | |
419 | } | |
420 | else | |
421 | cupsdLogMessage(level, "%s", message); | |
422 | } | |
423 | ||
424 | ||
f7deaa1a | 425 | #ifdef HAVE_GSSAPI |
426 | /* | |
427 | * 'cupsdLogGSSMessage()' - Log a GSSAPI error... | |
428 | */ | |
429 | ||
430 | int /* O - 1 on success, 0 on error */ | |
431 | cupsdLogGSSMessage( | |
432 | int level, /* I - Log level */ | |
7e86f2f6 MS |
433 | OM_uint32 major_status, /* I - Major GSSAPI status */ |
434 | OM_uint32 minor_status, /* I - Minor GSSAPI status */ | |
f7deaa1a | 435 | const char *message, /* I - printf-style message string */ |
436 | ...) /* I - Additional args as needed */ | |
437 | { | |
438 | OM_uint32 err_major_status, /* Major status code for display */ | |
439 | err_minor_status; /* Minor status code for display */ | |
440 | OM_uint32 msg_ctx; /* Message context */ | |
441 | gss_buffer_desc major_status_string = GSS_C_EMPTY_BUFFER, | |
442 | /* Major status message */ | |
443 | minor_status_string = GSS_C_EMPTY_BUFFER; | |
444 | /* Minor status message */ | |
445 | int ret; /* Return value */ | |
dcb445bc | 446 | char buffer[8192]; /* Buffer for vsnprintf */ |
f7deaa1a | 447 | |
448 | ||
dcb445bc MS |
449 | if (strchr(message, '%')) |
450 | { | |
451 | /* | |
452 | * Format the message string... | |
453 | */ | |
454 | ||
455 | va_list ap; /* Pointer to arguments */ | |
456 | ||
457 | va_start(ap, message); | |
458 | vsnprintf(buffer, sizeof(buffer), message, ap); | |
459 | va_end(ap); | |
460 | ||
461 | message = buffer; | |
462 | } | |
463 | ||
f7deaa1a | 464 | msg_ctx = 0; |
465 | err_major_status = gss_display_status(&err_minor_status, | |
466 | major_status, | |
467 | GSS_C_GSS_CODE, | |
468 | GSS_C_NO_OID, | |
469 | &msg_ctx, | |
470 | &major_status_string); | |
471 | ||
472 | if (!GSS_ERROR(err_major_status)) | |
1f0275e3 MS |
473 | gss_display_status(&err_minor_status, minor_status, GSS_C_MECH_CODE, |
474 | GSS_C_NULL_OID, &msg_ctx, &minor_status_string); | |
f7deaa1a | 475 | |
476 | ret = cupsdLogMessage(level, "%s: %s, %s", message, | |
477 | (char *)major_status_string.value, | |
478 | (char *)minor_status_string.value); | |
479 | gss_release_buffer(&err_minor_status, &major_status_string); | |
480 | gss_release_buffer(&err_minor_status, &minor_status_string); | |
481 | ||
482 | return (ret); | |
483 | } | |
484 | #endif /* HAVE_GSSAPI */ | |
485 | ||
486 | ||
996acce8 MS |
487 | /* |
488 | * 'cupsdLogClient()' - Log a client message. | |
489 | */ | |
490 | ||
491 | int /* O - 1 on success, 0 on error */ | |
492 | cupsdLogClient(cupsd_client_t *con, /* I - Client connection */ | |
493 | int level, /* I - Log level */ | |
494 | const char *message, /* I - Printf-style message string */ | |
495 | ...) /* I - Additional arguments as needed */ | |
496 | { | |
497 | va_list ap, ap2; /* Argument pointers */ | |
498 | char clientmsg[1024];/* Format string for client message */ | |
499 | int status; /* Formatting status */ | |
500 | ||
501 | ||
502 | /* | |
503 | * See if we want to log this message... | |
504 | */ | |
505 | ||
506 | if (TestConfigFile || !ErrorLog) | |
507 | return (1); | |
508 | ||
509 | if (level > LogLevel) | |
510 | return (1); | |
511 | ||
512 | /* | |
513 | * Format and write the log message... | |
514 | */ | |
515 | ||
516 | if (con) | |
517 | snprintf(clientmsg, sizeof(clientmsg), "[Client %d] %s", con->number, | |
518 | message); | |
519 | else | |
520 | strlcpy(clientmsg, message, sizeof(clientmsg)); | |
521 | ||
522 | va_start(ap, message); | |
523 | ||
524 | do | |
525 | { | |
526 | va_copy(ap2, ap); | |
527 | status = format_log_line(clientmsg, ap2); | |
528 | va_end(ap2); | |
529 | } | |
530 | while (status == 0); | |
531 | ||
532 | va_end(ap); | |
533 | ||
534 | if (status > 0) | |
535 | return (cupsdWriteErrorLog(level, log_line)); | |
536 | else | |
537 | return (cupsdWriteErrorLog(CUPSD_LOG_ERROR, | |
538 | "Unable to allocate memory for log line.")); | |
539 | } | |
540 | ||
541 | ||
ef416fc2 | 542 | /* |
75bd9771 | 543 | * 'cupsdLogJob()' - Log a job message. |
ef416fc2 | 544 | */ |
545 | ||
546 | int /* O - 1 on success, 0 on error */ | |
75bd9771 MS |
547 | cupsdLogJob(cupsd_job_t *job, /* I - Job */ |
548 | int level, /* I - Log level */ | |
549 | const char *message, /* I - Printf-style message string */ | |
550 | ...) /* I - Additional arguments as needed */ | |
ef416fc2 | 551 | { |
dcb445bc | 552 | va_list ap, ap2; /* Argument pointers */ |
005dd1eb MS |
553 | char jobmsg[1024]; /* Format string for job message */ |
554 | int status; /* Formatting status */ | |
ef416fc2 | 555 | |
556 | ||
557 | /* | |
558 | * See if we want to log this message... | |
559 | */ | |
560 | ||
94da7e34 MS |
561 | if (TestConfigFile || !ErrorLog) |
562 | return (1); | |
563 | ||
75c86da7 | 564 | if (level > LogLevel && LogDebugHistory <= 0) |
2e4ff8af | 565 | return (1); |
2e4ff8af | 566 | |
250bb8a9 | 567 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
0dc4a6bf MS |
568 | if (!strcmp(ErrorLog, "syslog")) |
569 | { | |
f495e905 | 570 | cupsd_printer_t *printer = job ? (job->printer ? job->printer : (job->dest ? cupsdFindDest(job->dest) : NULL)) : NULL; |
0dc4a6bf MS |
571 | static const char * const job_states[] = |
572 | { /* job-state strings */ | |
573 | "Pending", | |
574 | "PendingHeld", | |
575 | "Processing", | |
576 | "ProcessingStopped", | |
577 | "Canceled", | |
578 | "Aborted", | |
579 | "Completed" | |
580 | }; | |
581 | ||
582 | va_start(ap, message); | |
583 | ||
584 | do | |
585 | { | |
586 | va_copy(ap2, ap); | |
587 | status = format_log_line(message, ap2); | |
588 | va_end(ap2); | |
589 | } | |
590 | while (status == 0); | |
591 | ||
592 | va_end(ap); | |
593 | ||
7c91f59a MS |
594 | if (job) |
595 | sd_journal_send("MESSAGE=%s", log_line, | |
596 | "PRIORITY=%i", log_levels[level], | |
597 | PWG_Event"=JobStateChanged", | |
598 | PWG_ServiceURI"=%s", printer ? printer->uri : "", | |
599 | PWG_JobID"=%d", job->id, | |
69223177 | 600 | PWG_JobState"=%s", job->state_value < IPP_JSTATE_PENDING ? "" : job_states[job->state_value - IPP_JSTATE_PENDING], |
7c91f59a MS |
601 | PWG_JobImpressionsCompleted"=%d", ippGetInteger(job->impressions, 0), |
602 | NULL); | |
603 | else | |
604 | sd_journal_send("MESSAGE=%s", log_line, | |
605 | "PRIORITY=%i", log_levels[level], | |
606 | NULL); | |
607 | ||
0dc4a6bf MS |
608 | return (1); |
609 | } | |
250bb8a9 | 610 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ |
0dc4a6bf | 611 | |
ef416fc2 | 612 | /* |
75bd9771 | 613 | * Format and write the log message... |
ef416fc2 | 614 | */ |
615 | ||
dcb445bc MS |
616 | if (job) |
617 | snprintf(jobmsg, sizeof(jobmsg), "[Job %d] %s", job->id, message); | |
618 | else | |
619 | strlcpy(jobmsg, message, sizeof(jobmsg)); | |
620 | ||
621 | va_start(ap, message); | |
ef416fc2 | 622 | |
005dd1eb MS |
623 | do |
624 | { | |
dcb445bc MS |
625 | va_copy(ap2, ap); |
626 | status = format_log_line(jobmsg, ap2); | |
627 | va_end(ap2); | |
005dd1eb MS |
628 | } |
629 | while (status == 0); | |
771bd8cb | 630 | |
dcb445bc MS |
631 | va_end(ap); |
632 | ||
005dd1eb | 633 | if (status > 0) |
178cb736 | 634 | { |
75c86da7 | 635 | if (job && level > LogLevel && LogDebugHistory > 0) |
178cb736 MS |
636 | { |
637 | /* | |
638 | * Add message to the job history... | |
639 | */ | |
640 | ||
641 | cupsd_joblog_t *temp; /* Copy of log message */ | |
ff2b08f9 MS |
642 | size_t log_len = strlen(log_line); |
643 | /* Length of log message */ | |
178cb736 | 644 | |
ff2b08f9 | 645 | if ((temp = malloc(sizeof(cupsd_joblog_t) + log_len)) != NULL) |
178cb736 MS |
646 | { |
647 | temp->time = time(NULL); | |
ff2b08f9 | 648 | memcpy(temp->message, log_line, log_len + 1); |
178cb736 MS |
649 | } |
650 | ||
651 | if (!job->history) | |
652 | job->history = cupsArrayNew(NULL, NULL); | |
653 | ||
654 | if (job->history && temp) | |
655 | { | |
656 | cupsArrayAdd(job->history, temp); | |
657 | ||
658 | if (cupsArrayCount(job->history) > LogDebugHistory) | |
659 | { | |
660 | /* | |
661 | * Remove excess messages... | |
662 | */ | |
663 | ||
664 | temp = cupsArrayFirst(job->history); | |
665 | cupsArrayRemove(job->history, temp); | |
666 | free(temp); | |
667 | } | |
668 | } | |
669 | else if (temp) | |
670 | free(temp); | |
671 | ||
672 | return (1); | |
673 | } | |
75c86da7 | 674 | else if (level <= LogLevel) |
178cb736 MS |
675 | return (cupsdWriteErrorLog(level, log_line)); |
676 | else | |
677 | return (1); | |
678 | } | |
75bd9771 MS |
679 | else |
680 | return (cupsdWriteErrorLog(CUPSD_LOG_ERROR, | |
996acce8 | 681 | "Unable to allocate memory for log line.")); |
75bd9771 | 682 | } |
ef416fc2 | 683 | |
ef416fc2 | 684 | |
75bd9771 MS |
685 | /* |
686 | * 'cupsdLogMessage()' - Log a message to the error log file. | |
687 | */ | |
ef416fc2 | 688 | |
75bd9771 MS |
689 | int /* O - 1 on success, 0 on error */ |
690 | cupsdLogMessage(int level, /* I - Log level */ | |
691 | const char *message, /* I - printf-style message string */ | |
692 | ...) /* I - Additional args as needed */ | |
693 | { | |
dcb445bc | 694 | va_list ap, ap2; /* Argument pointers */ |
005dd1eb | 695 | int status; /* Formatting status */ |
ef416fc2 | 696 | |
ef416fc2 | 697 | |
698 | /* | |
75bd9771 | 699 | * See if we want to log this message... |
ef416fc2 | 700 | */ |
701 | ||
9eb416ee MS |
702 | if (TestConfigFile && level <= CUPSD_LOG_WARN) |
703 | { | |
704 | va_start(ap, message); | |
705 | ||
706 | vfprintf(stderr, message, ap); | |
707 | putc('\n', stderr); | |
708 | ||
709 | va_end(ap); | |
710 | ||
711 | return (1); | |
712 | } | |
713 | else if (!ErrorLog && level <= CUPSD_LOG_WARN) | |
ef416fc2 | 714 | { |
a4845881 | 715 | va_start(ap, message); |
0dc4a6bf | 716 | |
250bb8a9 | 717 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
0dc4a6bf MS |
718 | sd_journal_printv(log_levels[level], message, ap); |
719 | ||
720 | #elif defined(HAVE_VSYSLOG) | |
721 | vsyslog(LOG_LPR | log_levels[level], message, ap); | |
722 | ||
cb7f98ee | 723 | #else |
a4845881 MS |
724 | vfprintf(stderr, message, ap); |
725 | putc('\n', stderr); | |
250bb8a9 | 726 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ |
0dc4a6bf | 727 | |
a4845881 | 728 | va_end(ap); |
ef416fc2 | 729 | |
75bd9771 | 730 | return (1); |
ef416fc2 | 731 | } |
9eb416ee | 732 | else if (level > LogLevel || !ErrorLog) |
75bd9771 | 733 | return (1); |
ef416fc2 | 734 | |
250bb8a9 | 735 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
9eb416ee | 736 | else if (!strcmp(ErrorLog, "syslog")) |
a990ad13 | 737 | { |
67fe5048 | 738 | va_start(ap, message); |
a990ad13 | 739 | sd_journal_printv(log_levels[level], message, ap); |
67fe5048 | 740 | va_end(ap); |
a990ad13 MS |
741 | return (1); |
742 | } | |
250bb8a9 | 743 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ |
0dc4a6bf | 744 | |
ef416fc2 | 745 | /* |
75bd9771 | 746 | * Format and write the log message... |
ef416fc2 | 747 | */ |
748 | ||
dcb445bc MS |
749 | va_start(ap, message); |
750 | ||
005dd1eb MS |
751 | do |
752 | { | |
dcb445bc MS |
753 | va_copy(ap2, ap); |
754 | status = format_log_line(message, ap2); | |
755 | va_end(ap2); | |
005dd1eb MS |
756 | } |
757 | while (status == 0); | |
ef416fc2 | 758 | |
dcb445bc MS |
759 | va_end(ap); |
760 | ||
005dd1eb MS |
761 | if (status > 0) |
762 | return (cupsdWriteErrorLog(level, log_line)); | |
75bd9771 MS |
763 | else |
764 | return (cupsdWriteErrorLog(CUPSD_LOG_ERROR, | |
765 | "Unable to allocate memory for log line!")); | |
ef416fc2 | 766 | } |
767 | ||
768 | ||
769 | /* | |
770 | * 'cupsdLogPage()' - Log a page to the page log file. | |
771 | */ | |
772 | ||
773 | int /* O - 1 on success, 0 on error */ | |
774 | cupsdLogPage(cupsd_job_t *job, /* I - Job being printed */ | |
775 | const char *page) /* I - Page being printed */ | |
776 | { | |
01ce6322 MS |
777 | int i; /* Looping var */ |
778 | char buffer[2048], /* Buffer for page log */ | |
779 | *bufptr, /* Pointer into buffer */ | |
780 | name[256]; /* Attribute name */ | |
781 | const char *format, /* Pointer into PageLogFormat */ | |
782 | *nameend; /* End of attribute name */ | |
783 | ipp_attribute_t *attr; /* Current attribute */ | |
771bd8cb MS |
784 | char number[256]; /* Page number */ |
785 | int copies; /* Number of copies */ | |
ef416fc2 | 786 | |
787 | ||
01ce6322 MS |
788 | /* |
789 | * Format the line going into the page log... | |
790 | */ | |
791 | ||
792 | if (!PageLogFormat) | |
793 | return (1); | |
794 | ||
5a9febac | 795 | strlcpy(number, "1", sizeof(number)); |
771bd8cb MS |
796 | copies = 1; |
797 | sscanf(page, "%255s%d", number, &copies); | |
01ce6322 MS |
798 | |
799 | for (format = PageLogFormat, bufptr = buffer; *format; format ++) | |
800 | { | |
801 | if (*format == '%') | |
802 | { | |
803 | format ++; | |
804 | ||
805 | switch (*format) | |
806 | { | |
807 | case '%' : /* Literal % */ | |
808 | if (bufptr < (buffer + sizeof(buffer) - 1)) | |
809 | *bufptr++ = '%'; | |
810 | break; | |
811 | ||
812 | case 'p' : /* Printer name */ | |
5252fc7a | 813 | strlcpy(bufptr, job->dest, sizeof(buffer) - (size_t)(bufptr - buffer)); |
01ce6322 MS |
814 | bufptr += strlen(bufptr); |
815 | break; | |
816 | ||
817 | case 'j' : /* Job ID */ | |
7e86f2f6 | 818 | snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", job->id); |
01ce6322 MS |
819 | bufptr += strlen(bufptr); |
820 | break; | |
821 | ||
822 | case 'u' : /* Username */ | |
7e86f2f6 | 823 | strlcpy(bufptr, job->username ? job->username : "-", sizeof(buffer) - (size_t)(bufptr - buffer)); |
01ce6322 MS |
824 | bufptr += strlen(bufptr); |
825 | break; | |
826 | ||
827 | case 'T' : /* Date and time */ | |
7e86f2f6 | 828 | strlcpy(bufptr, cupsdGetDateTime(NULL, LogTimeFormat), sizeof(buffer) - (size_t)(bufptr - buffer)); |
01ce6322 MS |
829 | bufptr += strlen(bufptr); |
830 | break; | |
831 | ||
832 | case 'P' : /* Page number */ | |
7e86f2f6 | 833 | strlcpy(bufptr, number, sizeof(buffer) - (size_t)(bufptr - buffer)); |
01ce6322 MS |
834 | bufptr += strlen(bufptr); |
835 | break; | |
836 | ||
837 | case 'C' : /* Number of copies */ | |
7e86f2f6 | 838 | snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", copies); |
01ce6322 MS |
839 | bufptr += strlen(bufptr); |
840 | break; | |
841 | ||
842 | case '{' : /* {attribute} */ | |
7e86f2f6 | 843 | if ((nameend = strchr(format, '}')) != NULL && (size_t)(nameend - format - 2) < (sizeof(name) - 1)) |
01ce6322 MS |
844 | { |
845 | /* | |
846 | * Pull the name from inside the brackets... | |
847 | */ | |
848 | ||
07623986 | 849 | memcpy(name, format + 1, (size_t)(nameend - format - 1)); |
75bd9771 MS |
850 | name[nameend - format - 1] = '\0'; |
851 | ||
852 | format = nameend; | |
01ce6322 | 853 | |
bf1bc4c6 MS |
854 | attr = ippFindAttribute(job->attrs, name, IPP_TAG_ZERO); |
855 | if (!attr && !strcmp(name, "job-billing")) | |
856 | { | |
857 | /* | |
858 | * Handle alias "job-account-id" (which was standardized after | |
859 | * "job-billing" was defined for CUPS... | |
860 | */ | |
861 | ||
862 | attr = ippFindAttribute(job->attrs, "job-account-id", IPP_TAG_ZERO); | |
863 | } | |
864 | else if (!attr && !strcmp(name, "media")) | |
865 | { | |
866 | /* | |
867 | * Handle alias "media-col" which uses dimensions instead of | |
868 | * names... | |
869 | */ | |
870 | ||
871 | attr = ippFindAttribute(job->attrs, "media-col/media-size", IPP_TAG_BEGIN_COLLECTION); | |
872 | } | |
873 | ||
874 | if (attr) | |
01ce6322 MS |
875 | { |
876 | /* | |
877 | * Add the attribute value... | |
878 | */ | |
879 | ||
01ce6322 MS |
880 | for (i = 0; |
881 | i < attr->num_values && | |
882 | bufptr < (buffer + sizeof(buffer) - 1); | |
883 | i ++) | |
884 | { | |
885 | if (i) | |
886 | *bufptr++ = ','; | |
887 | ||
888 | switch (attr->value_tag) | |
889 | { | |
890 | case IPP_TAG_INTEGER : | |
891 | case IPP_TAG_ENUM : | |
7e86f2f6 | 892 | snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", attr->values[i].integer); |
01ce6322 MS |
893 | bufptr += strlen(bufptr); |
894 | break; | |
895 | ||
896 | case IPP_TAG_BOOLEAN : | |
7e86f2f6 | 897 | snprintf(bufptr, sizeof(buffer) - (size_t)(bufptr - buffer), "%d", attr->values[i].boolean); |
01ce6322 MS |
898 | bufptr += strlen(bufptr); |
899 | break; | |
900 | ||
901 | case IPP_TAG_TEXTLANG : | |
902 | case IPP_TAG_NAMELANG : | |
903 | case IPP_TAG_TEXT : | |
904 | case IPP_TAG_NAME : | |
905 | case IPP_TAG_KEYWORD : | |
906 | case IPP_TAG_URI : | |
907 | case IPP_TAG_URISCHEME : | |
908 | case IPP_TAG_CHARSET : | |
909 | case IPP_TAG_LANGUAGE : | |
910 | case IPP_TAG_MIMETYPE : | |
7e86f2f6 | 911 | strlcpy(bufptr, attr->values[i].string.text, sizeof(buffer) - (size_t)(bufptr - buffer)); |
01ce6322 MS |
912 | bufptr += strlen(bufptr); |
913 | break; | |
914 | ||
bf1bc4c6 MS |
915 | case IPP_TAG_BEGIN_COLLECTION : |
916 | if (!strcmp(attr->name, "media-size")) | |
917 | { | |
918 | ipp_attribute_t *x_dimension = ippFindAttribute(ippGetCollection(attr, 0), "x-dimension", IPP_TAG_INTEGER); | |
919 | ipp_attribute_t *y_dimension = ippFindAttribute(ippGetCollection(attr, 0), "y-dimension", IPP_TAG_INTEGER); | |
920 | /* Media dimensions */ | |
921 | ||
922 | if (x_dimension && y_dimension) | |
923 | { | |
924 | pwg_media_t *pwg = pwgMediaForSize(ippGetInteger(x_dimension, 0), ippGetInteger(y_dimension, 0)); | |
925 | /* PWG media name */ | |
926 | strlcpy(bufptr, pwg->pwg, sizeof(buffer) - (size_t)(bufptr - buffer)); | |
927 | break; | |
928 | } | |
929 | } | |
930 | ||
01ce6322 | 931 | default : |
7e86f2f6 | 932 | strlcpy(bufptr, "???", sizeof(buffer) - (size_t)(bufptr - buffer)); |
01ce6322 MS |
933 | bufptr += strlen(bufptr); |
934 | break; | |
935 | } | |
936 | } | |
937 | } | |
938 | else if (bufptr < (buffer + sizeof(buffer) - 1)) | |
939 | *bufptr++ = '-'; | |
940 | break; | |
941 | } | |
942 | ||
943 | default : | |
944 | if (bufptr < (buffer + sizeof(buffer) - 2)) | |
945 | { | |
946 | *bufptr++ = '%'; | |
947 | *bufptr++ = *format; | |
948 | } | |
949 | break; | |
950 | } | |
951 | } | |
952 | else if (bufptr < (buffer + sizeof(buffer) - 1)) | |
953 | *bufptr++ = *format; | |
954 | } | |
ef416fc2 | 955 | |
01ce6322 | 956 | *bufptr = '\0'; |
771bd8cb | 957 | |
250bb8a9 | 958 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
0dc4a6bf MS |
959 | if (!strcmp(ErrorLog, "syslog")) |
960 | { | |
0dc4a6bf MS |
961 | static const char * const job_states[] = |
962 | { /* job-state strings */ | |
963 | "Pending", | |
964 | "PendingHeld", | |
965 | "Processing", | |
966 | "ProcessingStopped", | |
967 | "Canceled", | |
968 | "Aborted", | |
969 | "Completed" | |
970 | }; | |
971 | ||
a990ad13 MS |
972 | sd_journal_send("MESSAGE=%s", buffer, |
973 | "PRIORITY=%i", LOG_INFO, | |
0dc4a6bf MS |
974 | PWG_Event"=JobStateChanged", |
975 | PWG_ServiceURI"=%s", job->printer->uri, | |
976 | PWG_JobID"=%d", job->id, | |
977 | PWG_JobState"=%s", job_states[job->state_value - IPP_JSTATE_PENDING], | |
978 | PWG_JobImpressionsCompleted"=%d", ippGetInteger(job->impressions, 0), | |
979 | NULL); | |
980 | return (1); | |
981 | } | |
982 | ||
983 | #elif defined(HAVE_VSYSLOG) | |
ef416fc2 | 984 | /* |
985 | * See if we are logging pages via syslog... | |
986 | */ | |
987 | ||
988 | if (!strcmp(PageLog, "syslog")) | |
989 | { | |
01ce6322 | 990 | syslog(LOG_INFO, "%s", buffer); |
ef416fc2 | 991 | |
992 | return (1); | |
993 | } | |
250bb8a9 | 994 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ |
ef416fc2 | 995 | |
996 | /* | |
997 | * Not using syslog; check the log file... | |
998 | */ | |
999 | ||
22c9029b | 1000 | if (!cupsdCheckLogFile(&PageFile, PageLog)) |
ef416fc2 | 1001 | return (0); |
1002 | ||
1003 | /* | |
1004 | * Print a page log entry of the form: | |
1005 | * | |
ac884b6a | 1006 | * printer user job-id [DD/MON/YYYY:HH:MM:SS +TTTT] page num-copies \ |
ef416fc2 | 1007 | * billing hostname |
1008 | */ | |
1009 | ||
01ce6322 | 1010 | cupsFilePrintf(PageFile, "%s\n", buffer); |
ef416fc2 | 1011 | cupsFileFlush(PageFile); |
1012 | ||
1013 | return (1); | |
1014 | } | |
1015 | ||
1016 | ||
1017 | /* | |
1018 | * 'cupsdLogRequest()' - Log an HTTP request in Common Log Format. | |
1019 | */ | |
1020 | ||
1021 | int /* O - 1 on success, 0 on error */ | |
1022 | cupsdLogRequest(cupsd_client_t *con, /* I - Request to log */ | |
1023 | http_status_t code) /* I - Response code */ | |
1024 | { | |
839a51c8 | 1025 | char temp[2048]; /* Temporary string for URI */ |
ef416fc2 | 1026 | static const char * const states[] = /* HTTP client states... */ |
1027 | { | |
1028 | "WAITING", | |
1029 | "OPTIONS", | |
1030 | "GET", | |
1031 | "GET", | |
1032 | "HEAD", | |
1033 | "POST", | |
1034 | "POST", | |
1035 | "POST", | |
1036 | "PUT", | |
1037 | "PUT", | |
1038 | "DELETE", | |
1039 | "TRACE", | |
1040 | "CLOSE", | |
1041 | "STATUS" | |
1042 | }; | |
1043 | ||
1044 | ||
1f0275e3 MS |
1045 | /* |
1046 | * Filter requests as needed... | |
1047 | */ | |
1048 | ||
c9dcc485 MS |
1049 | if (AccessLogLevel == CUPSD_ACCESSLOG_NONE) |
1050 | return (1); | |
1051 | else if (AccessLogLevel < CUPSD_ACCESSLOG_ALL) | |
1f0275e3 MS |
1052 | { |
1053 | /* | |
ba55dc12 | 1054 | * Eliminate simple GET, POST, and PUT requests... |
1f0275e3 MS |
1055 | */ |
1056 | ||
1057 | if ((con->operation == HTTP_GET && | |
1058 | strncmp(con->uri, "/admin/conf", 11) && | |
1059 | strncmp(con->uri, "/admin/log", 10)) || | |
1060 | (con->operation == HTTP_POST && !con->request && | |
1061 | strncmp(con->uri, "/admin", 6)) || | |
ba55dc12 MS |
1062 | (con->operation != HTTP_GET && con->operation != HTTP_POST && |
1063 | con->operation != HTTP_PUT)) | |
1f0275e3 MS |
1064 | return (1); |
1065 | ||
1066 | if (con->request && con->response && | |
e07d4801 MS |
1067 | (con->response->request.status.status_code < IPP_REDIRECTION_OTHER_SITE || |
1068 | con->response->request.status.status_code == IPP_NOT_FOUND)) | |
1f0275e3 MS |
1069 | { |
1070 | /* | |
1071 | * Check successful requests... | |
1072 | */ | |
1073 | ||
1074 | ipp_op_t op = con->request->request.op.operation_id; | |
1075 | static cupsd_accesslog_t standard_ops[] = | |
1076 | { | |
1077 | CUPSD_ACCESSLOG_ALL, /* reserved */ | |
1078 | CUPSD_ACCESSLOG_ALL, /* reserved */ | |
1079 | CUPSD_ACCESSLOG_ACTIONS,/* Print-Job */ | |
1080 | CUPSD_ACCESSLOG_ACTIONS,/* Print-URI */ | |
1081 | CUPSD_ACCESSLOG_ACTIONS,/* Validate-Job */ | |
1082 | CUPSD_ACCESSLOG_ACTIONS,/* Create-Job */ | |
1083 | CUPSD_ACCESSLOG_ACTIONS,/* Send-Document */ | |
1084 | CUPSD_ACCESSLOG_ACTIONS,/* Send-URI */ | |
1085 | CUPSD_ACCESSLOG_ACTIONS,/* Cancel-Job */ | |
1086 | CUPSD_ACCESSLOG_ALL, /* Get-Job-Attributes */ | |
1087 | CUPSD_ACCESSLOG_ALL, /* Get-Jobs */ | |
1088 | CUPSD_ACCESSLOG_ALL, /* Get-Printer-Attributes */ | |
1089 | CUPSD_ACCESSLOG_ACTIONS,/* Hold-Job */ | |
1090 | CUPSD_ACCESSLOG_ACTIONS,/* Release-Job */ | |
1091 | CUPSD_ACCESSLOG_ACTIONS,/* Restart-Job */ | |
1092 | CUPSD_ACCESSLOG_ALL, /* reserved */ | |
1093 | CUPSD_ACCESSLOG_CONFIG, /* Pause-Printer */ | |
1094 | CUPSD_ACCESSLOG_CONFIG, /* Resume-Printer */ | |
1095 | CUPSD_ACCESSLOG_CONFIG, /* Purge-Jobs */ | |
1096 | CUPSD_ACCESSLOG_CONFIG, /* Set-Printer-Attributes */ | |
1097 | CUPSD_ACCESSLOG_ACTIONS,/* Set-Job-Attributes */ | |
1098 | CUPSD_ACCESSLOG_CONFIG, /* Get-Printer-Supported-Values */ | |
1099 | CUPSD_ACCESSLOG_ACTIONS,/* Create-Printer-Subscription */ | |
1100 | CUPSD_ACCESSLOG_ACTIONS,/* Create-Job-Subscription */ | |
1101 | CUPSD_ACCESSLOG_ALL, /* Get-Subscription-Attributes */ | |
1102 | CUPSD_ACCESSLOG_ALL, /* Get-Subscriptions */ | |
1103 | CUPSD_ACCESSLOG_ACTIONS,/* Renew-Subscription */ | |
1104 | CUPSD_ACCESSLOG_ACTIONS,/* Cancel-Subscription */ | |
1105 | CUPSD_ACCESSLOG_ALL, /* Get-Notifications */ | |
1106 | CUPSD_ACCESSLOG_ACTIONS,/* Send-Notifications */ | |
1107 | CUPSD_ACCESSLOG_ALL, /* reserved */ | |
1108 | CUPSD_ACCESSLOG_ALL, /* reserved */ | |
1109 | CUPSD_ACCESSLOG_ALL, /* reserved */ | |
1110 | CUPSD_ACCESSLOG_ALL, /* Get-Print-Support-Files */ | |
1111 | CUPSD_ACCESSLOG_CONFIG, /* Enable-Printer */ | |
1112 | CUPSD_ACCESSLOG_CONFIG, /* Disable-Printer */ | |
1113 | CUPSD_ACCESSLOG_CONFIG, /* Pause-Printer-After-Current-Job */ | |
1114 | CUPSD_ACCESSLOG_ACTIONS,/* Hold-New-Jobs */ | |
1115 | CUPSD_ACCESSLOG_ACTIONS,/* Release-Held-New-Jobs */ | |
1116 | CUPSD_ACCESSLOG_CONFIG, /* Deactivate-Printer */ | |
1117 | CUPSD_ACCESSLOG_CONFIG, /* Activate-Printer */ | |
1118 | CUPSD_ACCESSLOG_CONFIG, /* Restart-Printer */ | |
1119 | CUPSD_ACCESSLOG_CONFIG, /* Shutdown-Printer */ | |
1120 | CUPSD_ACCESSLOG_CONFIG, /* Startup-Printer */ | |
1121 | CUPSD_ACCESSLOG_ACTIONS,/* Reprocess-Job */ | |
1122 | CUPSD_ACCESSLOG_ACTIONS,/* Cancel-Current-Job */ | |
1123 | CUPSD_ACCESSLOG_ACTIONS,/* Suspend-Current-Job */ | |
1124 | CUPSD_ACCESSLOG_ACTIONS,/* Resume-Job */ | |
1125 | CUPSD_ACCESSLOG_ACTIONS,/* Promote-Job */ | |
1126 | CUPSD_ACCESSLOG_ACTIONS /* Schedule-Job-After */ | |
1127 | }; | |
1128 | static cupsd_accesslog_t cups_ops[] = | |
1129 | { | |
1130 | CUPSD_ACCESSLOG_ALL, /* CUPS-Get-Default */ | |
1131 | CUPSD_ACCESSLOG_ALL, /* CUPS-Get-Printers */ | |
1132 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Add-Modify-Printer */ | |
1133 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Delete-Printer */ | |
1134 | CUPSD_ACCESSLOG_ALL, /* CUPS-Get-Classes */ | |
1135 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Add-Modify-Class */ | |
1136 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Delete-Class */ | |
1137 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Accept-Jobs */ | |
1138 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Reject-Jobs */ | |
1139 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Set-Default */ | |
1140 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Get-Devices */ | |
1141 | CUPSD_ACCESSLOG_CONFIG, /* CUPS-Get-PPDs */ | |
1142 | CUPSD_ACCESSLOG_ACTIONS,/* CUPS-Move-Job */ | |
1143 | CUPSD_ACCESSLOG_ACTIONS,/* CUPS-Authenticate-Job */ | |
1144 | CUPSD_ACCESSLOG_ALL /* CUPS-Get-PPD */ | |
1145 | }; | |
771bd8cb | 1146 | |
1f0275e3 MS |
1147 | |
1148 | if ((op <= IPP_SCHEDULE_JOB_AFTER && standard_ops[op] > AccessLogLevel) || | |
1149 | (op >= CUPS_GET_DEFAULT && op <= CUPS_GET_PPD && | |
1150 | cups_ops[op - CUPS_GET_DEFAULT] > AccessLogLevel)) | |
1151 | return (1); | |
1152 | } | |
1153 | } | |
1154 | ||
250bb8a9 | 1155 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
71187167 | 1156 | if (!strcmp(AccessLog, "syslog")) |
a990ad13 MS |
1157 | { |
1158 | sd_journal_print(LOG_INFO, "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s", con->http->hostname, con->username[0] != '\0' ? con->username : "-", states[con->operation], _httpEncodeURI(temp, con->uri, sizeof(temp)), con->http->version / 100, con->http->version % 100, code, CUPS_LLCAST con->bytes, con->request ? ippOpString(con->request->request.op.operation_id) : "-", con->response ? ippErrorString(con->response->request.status.status_code) : "-"); | |
1159 | return (1); | |
1160 | } | |
0dc4a6bf MS |
1161 | |
1162 | #elif defined(HAVE_VSYSLOG) | |
ef416fc2 | 1163 | /* |
1164 | * See if we are logging accesses via syslog... | |
1165 | */ | |
1166 | ||
1167 | if (!strcmp(AccessLog, "syslog")) | |
1168 | { | |
2abf387c | 1169 | syslog(LOG_INFO, |
1170 | "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n", | |
996acce8 | 1171 | con->http->hostname, con->username[0] != '\0' ? con->username : "-", |
839a51c8 | 1172 | states[con->operation], _httpEncodeURI(temp, con->uri, sizeof(temp)), |
996acce8 | 1173 | con->http->version / 100, con->http->version % 100, |
2abf387c | 1174 | code, CUPS_LLCAST con->bytes, |
1175 | con->request ? | |
1176 | ippOpString(con->request->request.op.operation_id) : "-", | |
1177 | con->response ? | |
1178 | ippErrorString(con->response->request.status.status_code) : "-"); | |
ef416fc2 | 1179 | |
1180 | return (1); | |
1181 | } | |
250bb8a9 | 1182 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ |
ef416fc2 | 1183 | |
1184 | /* | |
1185 | * Not using syslog; check the log file... | |
1186 | */ | |
1187 | ||
22c9029b | 1188 | if (!cupsdCheckLogFile(&AccessFile, AccessLog)) |
ef416fc2 | 1189 | return (0); |
1190 | ||
1191 | /* | |
1192 | * Write a log of the request in "common log format"... | |
1193 | */ | |
1194 | ||
1195 | cupsFilePrintf(AccessFile, | |
1196 | "%s - %s %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n", | |
996acce8 | 1197 | con->http->hostname, |
c8fef167 | 1198 | con->username[0] != '\0' ? con->username : "-", |
dfd5680b MS |
1199 | cupsdGetDateTime(&(con->start), LogTimeFormat), |
1200 | states[con->operation], | |
839a51c8 | 1201 | _httpEncodeURI(temp, con->uri, sizeof(temp)), |
996acce8 | 1202 | con->http->version / 100, con->http->version % 100, |
ef416fc2 | 1203 | code, CUPS_LLCAST con->bytes, |
1204 | con->request ? | |
1205 | ippOpString(con->request->request.op.operation_id) : "-", | |
1206 | con->response ? | |
1207 | ippErrorString(con->response->request.status.status_code) : | |
1208 | "-"); | |
1209 | ||
1210 | cupsFileFlush(AccessFile); | |
1211 | ||
1212 | return (1); | |
1213 | } | |
1214 | ||
1215 | ||
75bd9771 MS |
1216 | /* |
1217 | * 'cupsdWriteErrorLog()' - Write a line to the ErrorLog. | |
1218 | */ | |
1219 | ||
1220 | int /* O - 1 on success, 0 on failure */ | |
1221 | cupsdWriteErrorLog(int level, /* I - Log level */ | |
1222 | const char *message) /* I - Message string */ | |
1223 | { | |
28a463e0 | 1224 | int ret = 1; /* Return value */ |
75bd9771 MS |
1225 | static const char levels[] = /* Log levels... */ |
1226 | { | |
1227 | ' ', | |
1228 | 'X', | |
1229 | 'A', | |
1230 | 'C', | |
1231 | 'E', | |
1232 | 'W', | |
1233 | 'N', | |
1234 | 'I', | |
1235 | 'D', | |
1236 | 'd' | |
1237 | }; | |
75bd9771 MS |
1238 | |
1239 | ||
250bb8a9 | 1240 | #ifdef HAVE_SYSTEMD_SD_JOURNAL_H |
a990ad13 MS |
1241 | if (!strcmp(ErrorLog, "syslog")) |
1242 | { | |
1243 | sd_journal_print(log_levels[level], "%s", message); | |
1244 | return (1); | |
1245 | } | |
0dc4a6bf MS |
1246 | |
1247 | #elif defined(HAVE_VSYSLOG) | |
75bd9771 MS |
1248 | /* |
1249 | * See if we are logging errors via syslog... | |
1250 | */ | |
1251 | ||
1252 | if (!strcmp(ErrorLog, "syslog")) | |
1253 | { | |
0dc4a6bf | 1254 | syslog(log_levels[level], "%s", message); |
75bd9771 MS |
1255 | return (1); |
1256 | } | |
250bb8a9 | 1257 | #endif /* HAVE_SYSTEMD_SD_JOURNAL_H */ |
75bd9771 MS |
1258 | |
1259 | /* | |
1260 | * Not using syslog; check the log file... | |
1261 | */ | |
1262 | ||
28a463e0 MS |
1263 | _cupsMutexLock(&log_mutex); |
1264 | ||
22c9029b | 1265 | if (!cupsdCheckLogFile(&ErrorFile, ErrorLog)) |
28a463e0 MS |
1266 | { |
1267 | ret = 0; | |
1268 | } | |
1269 | else | |
1270 | { | |
1271 | /* | |
1272 | * Write the log message... | |
1273 | */ | |
75bd9771 | 1274 | |
28a463e0 MS |
1275 | cupsFilePrintf(ErrorFile, "%c %s %s\n", levels[level], |
1276 | cupsdGetDateTime(NULL, LogTimeFormat), message); | |
1277 | cupsFileFlush(ErrorFile); | |
1278 | } | |
75bd9771 | 1279 | |
28a463e0 | 1280 | _cupsMutexUnlock(&log_mutex); |
75bd9771 | 1281 | |
28a463e0 | 1282 | return (ret); |
75bd9771 MS |
1283 | } |
1284 | ||
1285 | ||
ef416fc2 | 1286 | /* |
75bd9771 MS |
1287 | * 'format_log_line()' - Format a line for a log file. |
1288 | * | |
1289 | * This function resizes a global string buffer as needed. Each call returns | |
1290 | * a pointer to this buffer, so the contents are only good until the next call | |
1291 | * to format_log_line()... | |
1292 | */ | |
1293 | ||
005dd1eb | 1294 | static int /* O - -1 for fatal, 0 for retry, 1 for success */ |
75bd9771 MS |
1295 | format_log_line(const char *message, /* I - Printf-style format string */ |
1296 | va_list ap) /* I - Argument list */ | |
1297 | { | |
7e86f2f6 | 1298 | ssize_t len; /* Length of formatted line */ |
75bd9771 MS |
1299 | |
1300 | ||
1301 | /* | |
1302 | * Allocate the line buffer as needed... | |
1303 | */ | |
1304 | ||
1305 | if (!log_linesize) | |
1306 | { | |
1307 | log_linesize = 8192; | |
1308 | log_line = malloc(log_linesize); | |
1309 | ||
1310 | if (!log_line) | |
005dd1eb | 1311 | return (-1); |
75bd9771 MS |
1312 | } |
1313 | ||
1314 | /* | |
1315 | * Format the log message... | |
1316 | */ | |
1317 | ||
59189c00 | 1318 | len = _cups_safe_vsnprintf(log_line, log_linesize, message, ap); |
75bd9771 MS |
1319 | |
1320 | /* | |
1321 | * Resize the buffer as needed... | |
1322 | */ | |
1323 | ||
7e86f2f6 | 1324 | if ((size_t)len >= log_linesize && log_linesize < 65536) |
75bd9771 MS |
1325 | { |
1326 | char *temp; /* Temporary string pointer */ | |
1327 | ||
75bd9771 MS |
1328 | len ++; |
1329 | ||
1330 | if (len < 8192) | |
1331 | len = 8192; | |
1332 | else if (len > 65536) | |
1333 | len = 65536; | |
1334 | ||
7e86f2f6 | 1335 | temp = realloc(log_line, (size_t)len); |
75bd9771 MS |
1336 | |
1337 | if (temp) | |
1338 | { | |
1339 | log_line = temp; | |
7e86f2f6 | 1340 | log_linesize = (size_t)len; |
75bd9771 | 1341 | |
005dd1eb MS |
1342 | return (0); |
1343 | } | |
75bd9771 MS |
1344 | } |
1345 | ||
005dd1eb | 1346 | return (1); |
75bd9771 | 1347 | } |