4 * Log file routines for the CUPS scheduler.
6 * Copyright 2007-2013 by Apple Inc.
7 * Copyright 1997-2007 by Easy Software Products, all rights reserved.
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/".
17 * Include necessary headers...
29 static _cups_mutex_t log_mutex
= _CUPS_MUTEX_INITIALIZER
;
30 /* Mutex for logging */
31 static int log_linesize
= 0; /* Size of line for output file */
32 static char *log_line
= NULL
; /* Line for output file */
35 static const int syslevels
[] = /* SYSLOG levels... */
48 #endif /* HAVE_VSYSLOG */
55 static int format_log_line(const char *message
, va_list ap
);
59 * 'cupsdCheckLogFile()' - Open/rotate a log file if it needs it.
62 int /* O - 1 if log file open */
63 cupsdCheckLogFile(cups_file_t
**lf
, /* IO - Log file */
64 const char *logname
) /* I - Log filename */
66 char backname
[1024], /* Backup log filename */
67 filename
[1024], /* Formatted log filename */
68 *ptr
; /* Pointer into filename */
69 const char *logptr
; /* Pointer into log filename */
73 * See if we have a log file to check...
76 if (!lf
|| !logname
|| !logname
[0])
80 * Format the filename as needed...
84 (strncmp(logname
, "/dev/", 5) && cupsFileTell(*lf
) > MaxLogSize
&&
88 * Handle format strings...
91 filename
[sizeof(filename
) - 1] = '\0';
93 if (logname
[0] != '/')
95 strlcpy(filename
, ServerRoot
, sizeof(filename
));
96 strlcat(filename
, "/", sizeof(filename
));
101 for (logptr
= logname
, ptr
= filename
+ strlen(filename
);
102 *logptr
&& ptr
< (filename
+ sizeof(filename
) - 1);
114 * Insert the server name...
117 strlcpy(ptr
, ServerName
, sizeof(filename
) - (ptr
- filename
));
123 * Otherwise just insert the character...
136 * See if the log file is open...
142 * Nope, open the log file...
145 if ((*lf
= cupsFileOpen(filename
, "a")) == NULL
)
148 * If the file is in CUPS_LOGDIR then try to create a missing directory...
151 if (!strncmp(filename
, CUPS_LOGDIR
, strlen(CUPS_LOGDIR
)))
154 * Try updating the permissions of the containing log directory, using
155 * the log file permissions as a basis...
158 int log_dir_perm
= 0300 | LogFilePerm
;
159 /* LogFilePerm + owner write/search */
160 if (log_dir_perm
& 0040)
161 log_dir_perm
|= 0010; /* Add group search */
162 if (log_dir_perm
& 0004)
163 log_dir_perm
|= 0001; /* Add other search */
165 cupsdCheckPermissions(CUPS_LOGDIR
, NULL
, log_dir_perm
, RunUser
, Group
,
168 *lf
= cupsFileOpen(filename
, "a");
173 syslog(LOG_ERR
, "Unable to open log file \"%s\" - %s", filename
,
176 if (FatalErrors
& CUPSD_FATAL_LOG
)
177 cupsdEndProcess(getpid(), 0);
183 if (strncmp(filename
, "/dev/", 5))
186 * Change ownership and permissions of non-device logs...
189 fchown(cupsFileNumber(*lf
), RunUser
, Group
);
190 fchmod(cupsFileNumber(*lf
), LogFilePerm
);
195 * Do we need to rotate the log?
198 if (strncmp(logname
, "/dev/", 5) && cupsFileTell(*lf
) > MaxLogSize
&&
207 strlcpy(backname
, filename
, sizeof(backname
));
208 strlcat(backname
, ".O", sizeof(backname
));
211 rename(filename
, backname
);
213 if ((*lf
= cupsFileOpen(filename
, "a")) == NULL
)
215 syslog(LOG_ERR
, "Unable to open log file \"%s\" - %s", filename
,
218 if (FatalErrors
& CUPSD_FATAL_LOG
)
219 cupsdEndProcess(getpid(), 0);
225 * Change ownership and permissions of non-device logs...
228 fchown(cupsFileNumber(*lf
), RunUser
, Group
);
229 fchmod(cupsFileNumber(*lf
), LogFilePerm
);
237 * 'cupsdGetDateTime()' - Returns a pointer to a date/time string.
240 char * /* O - Date/time string */
241 cupsdGetDateTime(struct timeval
*t
, /* I - Time value or NULL for current */
242 cupsd_time_t format
) /* I - Format to use */
244 struct timeval curtime
; /* Current time value */
245 struct tm
*date
; /* Date/time value */
246 static struct timeval last_time
= { 0, 0 };
247 /* Last time we formatted */
248 static char s
[1024]; /* Date/time string */
249 static const char * const months
[12] =/* Months */
267 * Make sure we have a valid time...
272 gettimeofday(&curtime
, NULL
);
276 if (t
->tv_sec
!= last_time
.tv_sec
||
277 (LogTimeFormat
== CUPSD_TIME_USECS
&& t
->tv_usec
!= last_time
.tv_usec
))
282 * Get the date and time from the UNIX time value, and then format it
283 * into a string. Note that we *can't* use the strftime() function since
284 * it is localized and will seriously confuse automatic programs if the
285 * month names are in the wrong language!
287 * Also, we use the "timezone" variable that contains the current timezone
288 * offset from GMT in seconds so that we are reporting local time in the
289 * log files. If you want GMT, set the TZ environment variable accordingly
290 * before starting the scheduler.
292 * (*BSD and Darwin store the timezone offset in the tm structure)
295 date
= localtime(&(t
->tv_sec
));
297 if (format
== CUPSD_TIME_STANDARD
)
298 snprintf(s
, sizeof(s
), "[%02d/%s/%04d:%02d:%02d:%02d %+03ld%02ld]",
299 date
->tm_mday
, months
[date
->tm_mon
], 1900 + date
->tm_year
,
300 date
->tm_hour
, date
->tm_min
, date
->tm_sec
,
301 #ifdef HAVE_TM_GMTOFF
302 date
->tm_gmtoff
/ 3600, (date
->tm_gmtoff
/ 60) % 60);
304 timezone
/ 3600, (timezone
/ 60) % 60);
305 #endif /* HAVE_TM_GMTOFF */
307 snprintf(s
, sizeof(s
), "[%02d/%s/%04d:%02d:%02d:%02d.%06d %+03ld%02ld]",
308 date
->tm_mday
, months
[date
->tm_mon
], 1900 + date
->tm_year
,
309 date
->tm_hour
, date
->tm_min
, date
->tm_sec
, (int)t
->tv_usec
,
310 #ifdef HAVE_TM_GMTOFF
311 date
->tm_gmtoff
/ 3600, (date
->tm_gmtoff
/ 60) % 60);
313 timezone
/ 3600, (timezone
/ 60) % 60);
314 #endif /* HAVE_TM_GMTOFF */
322 * 'cupsdLogFCMessage()' - Log a file checking message.
327 void *context
, /* I - Printer (if any) */
328 _cups_fc_result_t result
, /* I - Check result */
329 const char *message
) /* I - Message to log */
331 cupsd_printer_t
*p
= (cupsd_printer_t
*)context
;
333 cupsd_loglevel_t level
; /* Log level */
336 if (result
== _CUPS_FILE_CHECK_OK
)
337 level
= CUPSD_LOG_DEBUG2
;
339 level
= CUPSD_LOG_ERROR
;
343 cupsdLogMessage(level
, "%s: %s", p
->name
, message
);
345 if (result
== _CUPS_FILE_CHECK_MISSING
||
346 result
== _CUPS_FILE_CHECK_WRONG_TYPE
)
348 strlcpy(p
->state_message
, message
, sizeof(p
->state_message
));
350 if (cupsdSetPrinterReasons(p
, "+cups-missing-filter-warning"))
351 cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE
, p
, NULL
, "%s", message
);
353 else if (result
== _CUPS_FILE_CHECK_PERMISSIONS
||
354 result
== _CUPS_FILE_CHECK_RELATIVE_PATH
)
356 strlcpy(p
->state_message
, message
, sizeof(p
->state_message
));
358 if (cupsdSetPrinterReasons(p
, "+cups-insecure-filter-warning"))
359 cupsdAddEvent(CUPSD_EVENT_PRINTER_STATE
, p
, NULL
, "%s", message
);
363 cupsdLogMessage(level
, "%s", message
);
369 * 'cupsdLogGSSMessage()' - Log a GSSAPI error...
372 int /* O - 1 on success, 0 on error */
374 int level
, /* I - Log level */
375 int major_status
, /* I - Major GSSAPI status */
376 int minor_status
, /* I - Minor GSSAPI status */
377 const char *message
, /* I - printf-style message string */
378 ...) /* I - Additional args as needed */
380 OM_uint32 err_major_status
, /* Major status code for display */
381 err_minor_status
; /* Minor status code for display */
382 OM_uint32 msg_ctx
; /* Message context */
383 gss_buffer_desc major_status_string
= GSS_C_EMPTY_BUFFER
,
384 /* Major status message */
385 minor_status_string
= GSS_C_EMPTY_BUFFER
;
386 /* Minor status message */
387 int ret
; /* Return value */
388 char buffer
[8192]; /* Buffer for vsnprintf */
391 if (strchr(message
, '%'))
394 * Format the message string...
397 va_list ap
; /* Pointer to arguments */
399 va_start(ap
, message
);
400 vsnprintf(buffer
, sizeof(buffer
), message
, ap
);
407 err_major_status
= gss_display_status(&err_minor_status
,
412 &major_status_string
);
414 if (!GSS_ERROR(err_major_status
))
415 gss_display_status(&err_minor_status
, minor_status
, GSS_C_MECH_CODE
,
416 GSS_C_NULL_OID
, &msg_ctx
, &minor_status_string
);
418 ret
= cupsdLogMessage(level
, "%s: %s, %s", message
,
419 (char *)major_status_string
.value
,
420 (char *)minor_status_string
.value
);
421 gss_release_buffer(&err_minor_status
, &major_status_string
);
422 gss_release_buffer(&err_minor_status
, &minor_status_string
);
426 #endif /* HAVE_GSSAPI */
430 * 'cupsdLogClient()' - Log a client message.
433 int /* O - 1 on success, 0 on error */
434 cupsdLogClient(cupsd_client_t
*con
, /* I - Client connection */
435 int level
, /* I - Log level */
436 const char *message
, /* I - Printf-style message string */
437 ...) /* I - Additional arguments as needed */
439 va_list ap
, ap2
; /* Argument pointers */
440 char clientmsg
[1024];/* Format string for client message */
441 int status
; /* Formatting status */
445 * See if we want to log this message...
448 if (TestConfigFile
|| !ErrorLog
)
451 if (level
> LogLevel
)
455 * Format and write the log message...
459 snprintf(clientmsg
, sizeof(clientmsg
), "[Client %d] %s", con
->number
,
462 strlcpy(clientmsg
, message
, sizeof(clientmsg
));
464 va_start(ap
, message
);
469 status
= format_log_line(clientmsg
, ap2
);
477 return (cupsdWriteErrorLog(level
, log_line
));
479 return (cupsdWriteErrorLog(CUPSD_LOG_ERROR
,
480 "Unable to allocate memory for log line."));
485 * 'cupsdLogJob()' - Log a job message.
488 int /* O - 1 on success, 0 on error */
489 cupsdLogJob(cupsd_job_t
*job
, /* I - Job */
490 int level
, /* I - Log level */
491 const char *message
, /* I - Printf-style message string */
492 ...) /* I - Additional arguments as needed */
494 va_list ap
, ap2
; /* Argument pointers */
495 char jobmsg
[1024]; /* Format string for job message */
496 int status
; /* Formatting status */
500 * See if we want to log this message...
503 if (TestConfigFile
|| !ErrorLog
)
506 if ((level
> LogLevel
||
507 (level
== CUPSD_LOG_INFO
&& LogLevel
< CUPSD_LOG_DEBUG
)) &&
508 LogDebugHistory
<= 0)
512 * Format and write the log message...
516 snprintf(jobmsg
, sizeof(jobmsg
), "[Job %d] %s", job
->id
, message
);
518 strlcpy(jobmsg
, message
, sizeof(jobmsg
));
520 va_start(ap
, message
);
525 status
= format_log_line(jobmsg
, ap2
);
536 (level
== CUPSD_LOG_INFO
&& LogLevel
< CUPSD_LOG_DEBUG
)) &&
540 * Add message to the job history...
543 cupsd_joblog_t
*temp
; /* Copy of log message */
544 size_t log_len
= strlen(log_line
);
545 /* Length of log message */
547 if ((temp
= malloc(sizeof(cupsd_joblog_t
) + log_len
)) != NULL
)
549 temp
->time
= time(NULL
);
550 memcpy(temp
->message
, log_line
, log_len
+ 1);
554 job
->history
= cupsArrayNew(NULL
, NULL
);
556 if (job
->history
&& temp
)
558 cupsArrayAdd(job
->history
, temp
);
560 if (cupsArrayCount(job
->history
) > LogDebugHistory
)
563 * Remove excess messages...
566 temp
= cupsArrayFirst(job
->history
);
567 cupsArrayRemove(job
->history
, temp
);
576 else if (level
<= LogLevel
&&
577 (level
!= CUPSD_LOG_INFO
|| LogLevel
>= CUPSD_LOG_DEBUG
))
578 return (cupsdWriteErrorLog(level
, log_line
));
583 return (cupsdWriteErrorLog(CUPSD_LOG_ERROR
,
584 "Unable to allocate memory for log line."));
589 * 'cupsdLogMessage()' - Log a message to the error log file.
592 int /* O - 1 on success, 0 on error */
593 cupsdLogMessage(int level
, /* I - Log level */
594 const char *message
, /* I - printf-style message string */
595 ...) /* I - Additional args as needed */
597 va_list ap
, ap2
; /* Argument pointers */
598 int status
; /* Formatting status */
602 * See if we want to log this message...
605 if ((TestConfigFile
|| !ErrorLog
) && level
<= CUPSD_LOG_WARN
)
607 va_start(ap
, message
);
609 vsyslog(LOG_LPR
| syslevels
[level
], message
, ap
);
611 vfprintf(stderr
, message
, ap
);
613 #endif /* HAVE_VSYSLOG */
619 if (level
> LogLevel
|| !ErrorLog
)
623 * Format and write the log message...
626 va_start(ap
, message
);
631 status
= format_log_line(message
, ap2
);
639 return (cupsdWriteErrorLog(level
, log_line
));
641 return (cupsdWriteErrorLog(CUPSD_LOG_ERROR
,
642 "Unable to allocate memory for log line!"));
647 * 'cupsdLogPage()' - Log a page to the page log file.
650 int /* O - 1 on success, 0 on error */
651 cupsdLogPage(cupsd_job_t
*job
, /* I - Job being printed */
652 const char *page
) /* I - Page being printed */
654 int i
; /* Looping var */
655 char buffer
[2048], /* Buffer for page log */
656 *bufptr
, /* Pointer into buffer */
657 name
[256]; /* Attribute name */
658 const char *format
, /* Pointer into PageLogFormat */
659 *nameend
; /* End of attribute name */
660 ipp_attribute_t
*attr
; /* Current attribute */
661 char number
[256]; /* Page number */
662 int copies
; /* Number of copies */
666 * Format the line going into the page log...
672 strlcpy(number
, "1", sizeof(number
));
674 sscanf(page
, "%255s%d", number
, &copies
);
676 for (format
= PageLogFormat
, bufptr
= buffer
; *format
; format
++)
684 case '%' : /* Literal % */
685 if (bufptr
< (buffer
+ sizeof(buffer
) - 1))
689 case 'p' : /* Printer name */
690 strlcpy(bufptr
, job
->printer
->name
,
691 sizeof(buffer
) - (bufptr
- buffer
));
692 bufptr
+= strlen(bufptr
);
695 case 'j' : /* Job ID */
696 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
), "%d", job
->id
);
697 bufptr
+= strlen(bufptr
);
700 case 'u' : /* Username */
701 strlcpy(bufptr
, job
->username
? job
->username
: "-",
702 sizeof(buffer
) - (bufptr
- buffer
));
703 bufptr
+= strlen(bufptr
);
706 case 'T' : /* Date and time */
707 strlcpy(bufptr
, cupsdGetDateTime(NULL
, LogTimeFormat
),
708 sizeof(buffer
) - (bufptr
- buffer
));
709 bufptr
+= strlen(bufptr
);
712 case 'P' : /* Page number */
713 strlcpy(bufptr
, number
, sizeof(buffer
) - (bufptr
- buffer
));
714 bufptr
+= strlen(bufptr
);
717 case 'C' : /* Number of copies */
718 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
), "%d", copies
);
719 bufptr
+= strlen(bufptr
);
722 case '{' : /* {attribute} */
723 if ((nameend
= strchr(format
, '}')) != NULL
&&
724 (nameend
- format
- 2) < (sizeof(name
) - 1))
727 * Pull the name from inside the brackets...
730 memcpy(name
, format
+ 1, nameend
- format
- 1);
731 name
[nameend
- format
- 1] = '\0';
735 if ((attr
= ippFindAttribute(job
->attrs
, name
,
736 IPP_TAG_ZERO
)) != NULL
)
739 * Add the attribute value...
743 i
< attr
->num_values
&&
744 bufptr
< (buffer
+ sizeof(buffer
) - 1);
750 switch (attr
->value_tag
)
752 case IPP_TAG_INTEGER
:
754 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
),
755 "%d", attr
->values
[i
].integer
);
756 bufptr
+= strlen(bufptr
);
759 case IPP_TAG_BOOLEAN
:
760 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
),
761 "%d", attr
->values
[i
].boolean
);
762 bufptr
+= strlen(bufptr
);
765 case IPP_TAG_TEXTLANG
:
766 case IPP_TAG_NAMELANG
:
769 case IPP_TAG_KEYWORD
:
771 case IPP_TAG_URISCHEME
:
772 case IPP_TAG_CHARSET
:
773 case IPP_TAG_LANGUAGE
:
774 case IPP_TAG_MIMETYPE
:
775 strlcpy(bufptr
, attr
->values
[i
].string
.text
,
776 sizeof(buffer
) - (bufptr
- buffer
));
777 bufptr
+= strlen(bufptr
);
781 strlcpy(bufptr
, "???",
782 sizeof(buffer
) - (bufptr
- buffer
));
783 bufptr
+= strlen(bufptr
);
788 else if (bufptr
< (buffer
+ sizeof(buffer
) - 1))
794 if (bufptr
< (buffer
+ sizeof(buffer
) - 2))
802 else if (bufptr
< (buffer
+ sizeof(buffer
) - 1))
810 * See if we are logging pages via syslog...
813 if (!strcmp(PageLog
, "syslog"))
815 syslog(LOG_INFO
, "%s", buffer
);
819 #endif /* HAVE_VSYSLOG */
822 * Not using syslog; check the log file...
825 if (!cupsdCheckLogFile(&PageFile
, PageLog
))
829 * Print a page log entry of the form:
831 * printer user job-id [DD/MON/YYYY:HH:MM:SS +TTTT] page num-copies \
835 cupsFilePrintf(PageFile
, "%s\n", buffer
);
836 cupsFileFlush(PageFile
);
843 * 'cupsdLogRequest()' - Log an HTTP request in Common Log Format.
846 int /* O - 1 on success, 0 on error */
847 cupsdLogRequest(cupsd_client_t
*con
, /* I - Request to log */
848 http_status_t code
) /* I - Response code */
850 char temp
[2048]; /* Temporary string for URI */
851 static const char * const states
[] = /* HTTP client states... */
871 * Filter requests as needed...
874 if (AccessLogLevel
< CUPSD_ACCESSLOG_ALL
)
877 * Eliminate simple GET, POST, and PUT requests...
880 if ((con
->operation
== HTTP_GET
&&
881 strncmp(con
->uri
, "/admin/conf", 11) &&
882 strncmp(con
->uri
, "/admin/log", 10)) ||
883 (con
->operation
== HTTP_POST
&& !con
->request
&&
884 strncmp(con
->uri
, "/admin", 6)) ||
885 (con
->operation
!= HTTP_GET
&& con
->operation
!= HTTP_POST
&&
886 con
->operation
!= HTTP_PUT
))
889 if (con
->request
&& con
->response
&&
890 (con
->response
->request
.status
.status_code
< IPP_REDIRECTION_OTHER_SITE
||
891 con
->response
->request
.status
.status_code
== IPP_NOT_FOUND
))
894 * Check successful requests...
897 ipp_op_t op
= con
->request
->request
.op
.operation_id
;
898 static cupsd_accesslog_t standard_ops
[] =
900 CUPSD_ACCESSLOG_ALL
, /* reserved */
901 CUPSD_ACCESSLOG_ALL
, /* reserved */
902 CUPSD_ACCESSLOG_ACTIONS
,/* Print-Job */
903 CUPSD_ACCESSLOG_ACTIONS
,/* Print-URI */
904 CUPSD_ACCESSLOG_ACTIONS
,/* Validate-Job */
905 CUPSD_ACCESSLOG_ACTIONS
,/* Create-Job */
906 CUPSD_ACCESSLOG_ACTIONS
,/* Send-Document */
907 CUPSD_ACCESSLOG_ACTIONS
,/* Send-URI */
908 CUPSD_ACCESSLOG_ACTIONS
,/* Cancel-Job */
909 CUPSD_ACCESSLOG_ALL
, /* Get-Job-Attributes */
910 CUPSD_ACCESSLOG_ALL
, /* Get-Jobs */
911 CUPSD_ACCESSLOG_ALL
, /* Get-Printer-Attributes */
912 CUPSD_ACCESSLOG_ACTIONS
,/* Hold-Job */
913 CUPSD_ACCESSLOG_ACTIONS
,/* Release-Job */
914 CUPSD_ACCESSLOG_ACTIONS
,/* Restart-Job */
915 CUPSD_ACCESSLOG_ALL
, /* reserved */
916 CUPSD_ACCESSLOG_CONFIG
, /* Pause-Printer */
917 CUPSD_ACCESSLOG_CONFIG
, /* Resume-Printer */
918 CUPSD_ACCESSLOG_CONFIG
, /* Purge-Jobs */
919 CUPSD_ACCESSLOG_CONFIG
, /* Set-Printer-Attributes */
920 CUPSD_ACCESSLOG_ACTIONS
,/* Set-Job-Attributes */
921 CUPSD_ACCESSLOG_CONFIG
, /* Get-Printer-Supported-Values */
922 CUPSD_ACCESSLOG_ACTIONS
,/* Create-Printer-Subscription */
923 CUPSD_ACCESSLOG_ACTIONS
,/* Create-Job-Subscription */
924 CUPSD_ACCESSLOG_ALL
, /* Get-Subscription-Attributes */
925 CUPSD_ACCESSLOG_ALL
, /* Get-Subscriptions */
926 CUPSD_ACCESSLOG_ACTIONS
,/* Renew-Subscription */
927 CUPSD_ACCESSLOG_ACTIONS
,/* Cancel-Subscription */
928 CUPSD_ACCESSLOG_ALL
, /* Get-Notifications */
929 CUPSD_ACCESSLOG_ACTIONS
,/* Send-Notifications */
930 CUPSD_ACCESSLOG_ALL
, /* reserved */
931 CUPSD_ACCESSLOG_ALL
, /* reserved */
932 CUPSD_ACCESSLOG_ALL
, /* reserved */
933 CUPSD_ACCESSLOG_ALL
, /* Get-Print-Support-Files */
934 CUPSD_ACCESSLOG_CONFIG
, /* Enable-Printer */
935 CUPSD_ACCESSLOG_CONFIG
, /* Disable-Printer */
936 CUPSD_ACCESSLOG_CONFIG
, /* Pause-Printer-After-Current-Job */
937 CUPSD_ACCESSLOG_ACTIONS
,/* Hold-New-Jobs */
938 CUPSD_ACCESSLOG_ACTIONS
,/* Release-Held-New-Jobs */
939 CUPSD_ACCESSLOG_CONFIG
, /* Deactivate-Printer */
940 CUPSD_ACCESSLOG_CONFIG
, /* Activate-Printer */
941 CUPSD_ACCESSLOG_CONFIG
, /* Restart-Printer */
942 CUPSD_ACCESSLOG_CONFIG
, /* Shutdown-Printer */
943 CUPSD_ACCESSLOG_CONFIG
, /* Startup-Printer */
944 CUPSD_ACCESSLOG_ACTIONS
,/* Reprocess-Job */
945 CUPSD_ACCESSLOG_ACTIONS
,/* Cancel-Current-Job */
946 CUPSD_ACCESSLOG_ACTIONS
,/* Suspend-Current-Job */
947 CUPSD_ACCESSLOG_ACTIONS
,/* Resume-Job */
948 CUPSD_ACCESSLOG_ACTIONS
,/* Promote-Job */
949 CUPSD_ACCESSLOG_ACTIONS
/* Schedule-Job-After */
951 static cupsd_accesslog_t cups_ops
[] =
953 CUPSD_ACCESSLOG_ALL
, /* CUPS-Get-Default */
954 CUPSD_ACCESSLOG_ALL
, /* CUPS-Get-Printers */
955 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Add-Modify-Printer */
956 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Delete-Printer */
957 CUPSD_ACCESSLOG_ALL
, /* CUPS-Get-Classes */
958 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Add-Modify-Class */
959 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Delete-Class */
960 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Accept-Jobs */
961 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Reject-Jobs */
962 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Set-Default */
963 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Get-Devices */
964 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Get-PPDs */
965 CUPSD_ACCESSLOG_ACTIONS
,/* CUPS-Move-Job */
966 CUPSD_ACCESSLOG_ACTIONS
,/* CUPS-Authenticate-Job */
967 CUPSD_ACCESSLOG_ALL
/* CUPS-Get-PPD */
971 if ((op
<= IPP_SCHEDULE_JOB_AFTER
&& standard_ops
[op
] > AccessLogLevel
) ||
972 (op
>= CUPS_GET_DEFAULT
&& op
<= CUPS_GET_PPD
&&
973 cups_ops
[op
- CUPS_GET_DEFAULT
] > AccessLogLevel
))
980 * See if we are logging accesses via syslog...
983 if (!strcmp(AccessLog
, "syslog"))
986 "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT
" %s %s\n",
987 con
->http
->hostname
, con
->username
[0] != '\0' ? con
->username
: "-",
988 states
[con
->operation
], _httpEncodeURI(temp
, con
->uri
, sizeof(temp
)),
989 con
->http
->version
/ 100, con
->http
->version
% 100,
990 code
, CUPS_LLCAST con
->bytes
,
992 ippOpString(con
->request
->request
.op
.operation_id
) : "-",
994 ippErrorString(con
->response
->request
.status
.status_code
) : "-");
998 #endif /* HAVE_VSYSLOG */
1001 * Not using syslog; check the log file...
1004 if (!cupsdCheckLogFile(&AccessFile
, AccessLog
))
1008 * Write a log of the request in "common log format"...
1011 cupsFilePrintf(AccessFile
,
1012 "%s - %s %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT
" %s %s\n",
1013 con
->http
->hostname
,
1014 con
->username
[0] != '\0' ? con
->username
: "-",
1015 cupsdGetDateTime(&(con
->start
), LogTimeFormat
),
1016 states
[con
->operation
],
1017 _httpEncodeURI(temp
, con
->uri
, sizeof(temp
)),
1018 con
->http
->version
/ 100, con
->http
->version
% 100,
1019 code
, CUPS_LLCAST con
->bytes
,
1021 ippOpString(con
->request
->request
.op
.operation_id
) : "-",
1023 ippErrorString(con
->response
->request
.status
.status_code
) :
1026 cupsFileFlush(AccessFile
);
1033 * 'cupsdWriteErrorLog()' - Write a line to the ErrorLog.
1036 int /* O - 1 on success, 0 on failure */
1037 cupsdWriteErrorLog(int level
, /* I - Log level */
1038 const char *message
) /* I - Message string */
1040 int ret
= 1; /* Return value */
1041 static const char levels
[] = /* Log levels... */
1058 * See if we are logging errors via syslog...
1061 if (!strcmp(ErrorLog
, "syslog"))
1063 syslog(syslevels
[level
], "%s", message
);
1066 #endif /* HAVE_VSYSLOG */
1069 * Not using syslog; check the log file...
1072 _cupsMutexLock(&log_mutex
);
1074 if (!cupsdCheckLogFile(&ErrorFile
, ErrorLog
))
1081 * Write the log message...
1084 cupsFilePrintf(ErrorFile
, "%c %s %s\n", levels
[level
],
1085 cupsdGetDateTime(NULL
, LogTimeFormat
), message
);
1086 cupsFileFlush(ErrorFile
);
1089 _cupsMutexUnlock(&log_mutex
);
1096 * 'format_log_line()' - Format a line for a log file.
1098 * This function resizes a global string buffer as needed. Each call returns
1099 * a pointer to this buffer, so the contents are only good until the next call
1100 * to format_log_line()...
1103 static int /* O - -1 for fatal, 0 for retry, 1 for success */
1104 format_log_line(const char *message
, /* I - Printf-style format string */
1105 va_list ap
) /* I - Argument list */
1107 int len
; /* Length of formatted line */
1111 * Allocate the line buffer as needed...
1116 log_linesize
= 8192;
1117 log_line
= malloc(log_linesize
);
1124 * Format the log message...
1127 len
= vsnprintf(log_line
, log_linesize
, message
, ap
);
1130 * Resize the buffer as needed...
1133 if (len
>= log_linesize
&& log_linesize
< 65536)
1135 char *temp
; /* Temporary string pointer */
1142 else if (len
> 65536)
1145 temp
= realloc(log_line
, len
);