2 * "$Id: log.c 7918 2008-09-08 22:03:01Z mike $"
4 * Log file routines for the Common UNIX Printing System (CUPS).
6 * Copyright 2007-2009 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 * cupsdGetDateTime() - Returns a pointer to a date/time string.
18 * cupsdLogGSSMessage() - Log a GSSAPI error...
19 * cupsdLogJob() - Log a job message.
20 * cupsdLogMessage() - Log a message to the error log file.
21 * cupsdLogPage() - Log a page to the page log file.
22 * cupsdLogRequest() - Log an HTTP request in Common Log Format.
23 * cupsdWriteErrorLog() - Write a line to the ErrorLog.
24 * check_log_file() - Open/rotate a log file if it needs it.
25 * format_log_line() - Format a line for a log file.
29 * Include necessary headers...
41 static int log_linesize
= 0; /* Size of line for output file */
42 static char *log_line
= NULL
; /* Line for output file */
49 static int check_log_file(cups_file_t
**lf
, const char *logname
);
50 static int format_log_line(const char *message
, va_list ap
);
54 * 'cupsdGetDateTime()' - Returns a pointer to a date/time string.
57 char * /* O - Date/time string */
58 cupsdGetDateTime(struct timeval
*t
, /* I - Time value or NULL for current */
59 cupsd_time_t format
) /* I - Format to use */
61 struct timeval curtime
; /* Current time value */
62 struct tm
*date
; /* Date/time value */
63 static struct timeval last_time
= { 0, 0 };
64 /* Last time we formatted */
65 static char s
[1024]; /* Date/time string */
66 static const char * const months
[12] =/* Months */
84 * Make sure we have a valid time...
89 gettimeofday(&curtime
, NULL
);
93 if (t
->tv_sec
!= last_time
.tv_sec
||
94 (LogTimeFormat
== CUPSD_TIME_USECS
&& t
->tv_usec
!= last_time
.tv_usec
))
99 * Get the date and time from the UNIX time value, and then format it
100 * into a string. Note that we *can't* use the strftime() function since
101 * it is localized and will seriously confuse automatic programs if the
102 * month names are in the wrong language!
104 * Also, we use the "timezone" variable that contains the current timezone
105 * offset from GMT in seconds so that we are reporting local time in the
106 * log files. If you want GMT, set the TZ environment variable accordingly
107 * before starting the scheduler.
109 * (*BSD and Darwin store the timezone offset in the tm structure)
112 date
= localtime(&(t
->tv_sec
));
114 if (format
== CUPSD_TIME_STANDARD
)
115 snprintf(s
, sizeof(s
), "[%02d/%s/%04d:%02d:%02d:%02d %+03ld%02ld]",
116 date
->tm_mday
, months
[date
->tm_mon
], 1900 + date
->tm_year
,
117 date
->tm_hour
, date
->tm_min
, date
->tm_sec
,
118 #ifdef HAVE_TM_GMTOFF
119 date
->tm_gmtoff
/ 3600, (date
->tm_gmtoff
/ 60) % 60);
121 timezone
/ 3600, (timezone
/ 60) % 60);
122 #endif /* HAVE_TM_GMTOFF */
124 snprintf(s
, sizeof(s
), "[%02d/%s/%04d:%02d:%02d:%02d.%06d %+03ld%02ld]",
125 date
->tm_mday
, months
[date
->tm_mon
], 1900 + date
->tm_year
,
126 date
->tm_hour
, date
->tm_min
, date
->tm_sec
, (int)t
->tv_usec
,
127 #ifdef HAVE_TM_GMTOFF
128 date
->tm_gmtoff
/ 3600, (date
->tm_gmtoff
/ 60) % 60);
130 timezone
/ 3600, (timezone
/ 60) % 60);
131 #endif /* HAVE_TM_GMTOFF */
140 * 'cupsdLogGSSMessage()' - Log a GSSAPI error...
143 int /* O - 1 on success, 0 on error */
145 int level
, /* I - Log level */
146 int major_status
, /* I - Major GSSAPI status */
147 int minor_status
, /* I - Minor GSSAPI status */
148 const char *message
, /* I - printf-style message string */
149 ...) /* I - Additional args as needed */
151 OM_uint32 err_major_status
, /* Major status code for display */
152 err_minor_status
; /* Minor status code for display */
153 OM_uint32 msg_ctx
; /* Message context */
154 gss_buffer_desc major_status_string
= GSS_C_EMPTY_BUFFER
,
155 /* Major status message */
156 minor_status_string
= GSS_C_EMPTY_BUFFER
;
157 /* Minor status message */
158 int ret
; /* Return value */
162 err_major_status
= gss_display_status(&err_minor_status
,
167 &major_status_string
);
169 if (!GSS_ERROR(err_major_status
))
170 gss_display_status(&err_minor_status
, minor_status
, GSS_C_MECH_CODE
,
171 GSS_C_NULL_OID
, &msg_ctx
, &minor_status_string
);
173 ret
= cupsdLogMessage(level
, "%s: %s, %s", message
,
174 (char *)major_status_string
.value
,
175 (char *)minor_status_string
.value
);
176 gss_release_buffer(&err_minor_status
, &major_status_string
);
177 gss_release_buffer(&err_minor_status
, &minor_status_string
);
181 #endif /* HAVE_GSSAPI */
185 * 'cupsdLogJob()' - Log a job message.
188 int /* O - 1 on success, 0 on error */
189 cupsdLogJob(cupsd_job_t
*job
, /* I - Job */
190 int level
, /* I - Log level */
191 const char *message
, /* I - Printf-style message string */
192 ...) /* I - Additional arguments as needed */
194 va_list ap
; /* Argument pointer */
195 char jobmsg
[1024]; /* Format string for job message */
196 int status
; /* Formatting status */
200 * See if we want to log this message...
203 if (TestConfigFile
|| level
> LogLevel
|| !ErrorLog
)
207 * Format and write the log message...
210 snprintf(jobmsg
, sizeof(jobmsg
), "[Job %d] %s", job
->id
, message
);
214 va_start(ap
, message
);
215 status
= format_log_line(jobmsg
, ap
);
221 return (cupsdWriteErrorLog(level
, log_line
));
223 return (cupsdWriteErrorLog(CUPSD_LOG_ERROR
,
224 "Unable to allocate memory for log line!"));
229 * 'cupsdLogMessage()' - Log a message to the error log file.
232 int /* O - 1 on success, 0 on error */
233 cupsdLogMessage(int level
, /* I - Log level */
234 const char *message
, /* I - printf-style message string */
235 ...) /* I - Additional args as needed */
237 va_list ap
; /* Argument pointer */
238 int status
; /* Formatting status */
242 * See if we want to log this message...
247 if (level
<= CUPSD_LOG_WARN
)
249 va_start(ap
, message
);
250 vfprintf(stderr
, message
, ap
);
258 if (level
> LogLevel
|| !ErrorLog
)
262 * Format and write the log message...
267 va_start(ap
, message
);
268 status
= format_log_line(message
, ap
);
274 return (cupsdWriteErrorLog(level
, log_line
));
276 return (cupsdWriteErrorLog(CUPSD_LOG_ERROR
,
277 "Unable to allocate memory for log line!"));
282 * 'cupsdLogPage()' - Log a page to the page log file.
285 int /* O - 1 on success, 0 on error */
286 cupsdLogPage(cupsd_job_t
*job
, /* I - Job being printed */
287 const char *page
) /* I - Page being printed */
289 int i
; /* Looping var */
290 char buffer
[2048], /* Buffer for page log */
291 *bufptr
, /* Pointer into buffer */
292 name
[256]; /* Attribute name */
293 const char *format
, /* Pointer into PageLogFormat */
294 *nameend
; /* End of attribute name */
295 ipp_attribute_t
*attr
; /* Current attribute */
296 int number
; /* Page number */
297 char copies
[256]; /* Number of copies */
301 * Format the line going into the page log...
309 sscanf(page
, "%d%255s", &number
, copies
);
311 for (format
= PageLogFormat
, bufptr
= buffer
; *format
; format
++)
319 case '%' : /* Literal % */
320 if (bufptr
< (buffer
+ sizeof(buffer
) - 1))
324 case 'p' : /* Printer name */
325 strlcpy(bufptr
, job
->printer
->name
,
326 sizeof(buffer
) - (bufptr
- buffer
));
327 bufptr
+= strlen(bufptr
);
330 case 'j' : /* Job ID */
331 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
), "%d", job
->id
);
332 bufptr
+= strlen(bufptr
);
335 case 'u' : /* Username */
336 strlcpy(bufptr
, job
->username
? job
->username
: "-",
337 sizeof(buffer
) - (bufptr
- buffer
));
338 bufptr
+= strlen(bufptr
);
341 case 'T' : /* Date and time */
342 strlcpy(bufptr
, cupsdGetDateTime(NULL
, LogTimeFormat
),
343 sizeof(buffer
) - (bufptr
- buffer
));
344 bufptr
+= strlen(bufptr
);
347 case 'P' : /* Page number */
348 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
), "%d", number
);
349 bufptr
+= strlen(bufptr
);
352 case 'C' : /* Number of copies */
353 strlcpy(bufptr
, copies
, sizeof(buffer
) - (bufptr
- buffer
));
354 bufptr
+= strlen(bufptr
);
357 case '{' : /* {attribute} */
358 if ((nameend
= strchr(format
, '}')) != NULL
&&
359 (nameend
- format
- 2) < (sizeof(name
) - 1))
362 * Pull the name from inside the brackets...
365 memcpy(name
, format
+ 1, nameend
- format
- 1);
366 name
[nameend
- format
- 1] = '\0';
370 if ((attr
= ippFindAttribute(job
->attrs
, name
,
371 IPP_TAG_ZERO
)) != NULL
)
374 * Add the attribute value...
378 i
< attr
->num_values
&&
379 bufptr
< (buffer
+ sizeof(buffer
) - 1);
385 switch (attr
->value_tag
)
387 case IPP_TAG_INTEGER
:
389 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
),
390 "%d", attr
->values
[i
].integer
);
391 bufptr
+= strlen(bufptr
);
394 case IPP_TAG_BOOLEAN
:
395 snprintf(bufptr
, sizeof(buffer
) - (bufptr
- buffer
),
396 "%d", attr
->values
[i
].boolean
);
397 bufptr
+= strlen(bufptr
);
400 case IPP_TAG_TEXTLANG
:
401 case IPP_TAG_NAMELANG
:
404 case IPP_TAG_KEYWORD
:
406 case IPP_TAG_URISCHEME
:
407 case IPP_TAG_CHARSET
:
408 case IPP_TAG_LANGUAGE
:
409 case IPP_TAG_MIMETYPE
:
410 strlcpy(bufptr
, attr
->values
[i
].string
.text
,
411 sizeof(buffer
) - (bufptr
- buffer
));
412 bufptr
+= strlen(bufptr
);
416 strlcpy(bufptr
, "???",
417 sizeof(buffer
) - (bufptr
- buffer
));
418 bufptr
+= strlen(bufptr
);
423 else if (bufptr
< (buffer
+ sizeof(buffer
) - 1))
429 if (bufptr
< (buffer
+ sizeof(buffer
) - 2))
437 else if (bufptr
< (buffer
+ sizeof(buffer
) - 1))
445 * See if we are logging pages via syslog...
448 if (!strcmp(PageLog
, "syslog"))
450 syslog(LOG_INFO
, "%s", buffer
);
454 #endif /* HAVE_VSYSLOG */
457 * Not using syslog; check the log file...
460 if (!check_log_file(&PageFile
, PageLog
))
464 * Print a page log entry of the form:
466 * printer user job-id [DD/MON/YYYY:HH:MM:SS +TTTT] page num-copies \
470 cupsFilePrintf(PageFile
, "%s\n", buffer
);
471 cupsFileFlush(PageFile
);
478 * 'cupsdLogRequest()' - Log an HTTP request in Common Log Format.
481 int /* O - 1 on success, 0 on error */
482 cupsdLogRequest(cupsd_client_t
*con
, /* I - Request to log */
483 http_status_t code
) /* I - Response code */
485 char temp
[2048]; /* Temporary string for URI */
486 static const char * const states
[] = /* HTTP client states... */
506 * Filter requests as needed...
509 if (AccessLogLevel
< CUPSD_ACCESSLOG_ALL
)
512 * Eliminate simple GET requests...
515 if ((con
->operation
== HTTP_GET
&&
516 strncmp(con
->uri
, "/admin/conf", 11) &&
517 strncmp(con
->uri
, "/admin/log", 10)) ||
518 (con
->operation
== HTTP_POST
&& !con
->request
&&
519 strncmp(con
->uri
, "/admin", 6)) ||
520 (con
->operation
!= HTTP_POST
&& con
->operation
!= HTTP_PUT
))
523 if (con
->request
&& con
->response
&&
524 con
->response
->request
.status
.status_code
< IPP_REDIRECTION_OTHER_SITE
)
527 * Check successful requests...
530 ipp_op_t op
= con
->request
->request
.op
.operation_id
;
531 static cupsd_accesslog_t standard_ops
[] =
533 CUPSD_ACCESSLOG_ALL
, /* reserved */
534 CUPSD_ACCESSLOG_ALL
, /* reserved */
535 CUPSD_ACCESSLOG_ACTIONS
,/* Print-Job */
536 CUPSD_ACCESSLOG_ACTIONS
,/* Print-URI */
537 CUPSD_ACCESSLOG_ACTIONS
,/* Validate-Job */
538 CUPSD_ACCESSLOG_ACTIONS
,/* Create-Job */
539 CUPSD_ACCESSLOG_ACTIONS
,/* Send-Document */
540 CUPSD_ACCESSLOG_ACTIONS
,/* Send-URI */
541 CUPSD_ACCESSLOG_ACTIONS
,/* Cancel-Job */
542 CUPSD_ACCESSLOG_ALL
, /* Get-Job-Attributes */
543 CUPSD_ACCESSLOG_ALL
, /* Get-Jobs */
544 CUPSD_ACCESSLOG_ALL
, /* Get-Printer-Attributes */
545 CUPSD_ACCESSLOG_ACTIONS
,/* Hold-Job */
546 CUPSD_ACCESSLOG_ACTIONS
,/* Release-Job */
547 CUPSD_ACCESSLOG_ACTIONS
,/* Restart-Job */
548 CUPSD_ACCESSLOG_ALL
, /* reserved */
549 CUPSD_ACCESSLOG_CONFIG
, /* Pause-Printer */
550 CUPSD_ACCESSLOG_CONFIG
, /* Resume-Printer */
551 CUPSD_ACCESSLOG_CONFIG
, /* Purge-Jobs */
552 CUPSD_ACCESSLOG_CONFIG
, /* Set-Printer-Attributes */
553 CUPSD_ACCESSLOG_ACTIONS
,/* Set-Job-Attributes */
554 CUPSD_ACCESSLOG_CONFIG
, /* Get-Printer-Supported-Values */
555 CUPSD_ACCESSLOG_ACTIONS
,/* Create-Printer-Subscription */
556 CUPSD_ACCESSLOG_ACTIONS
,/* Create-Job-Subscription */
557 CUPSD_ACCESSLOG_ALL
, /* Get-Subscription-Attributes */
558 CUPSD_ACCESSLOG_ALL
, /* Get-Subscriptions */
559 CUPSD_ACCESSLOG_ACTIONS
,/* Renew-Subscription */
560 CUPSD_ACCESSLOG_ACTIONS
,/* Cancel-Subscription */
561 CUPSD_ACCESSLOG_ALL
, /* Get-Notifications */
562 CUPSD_ACCESSLOG_ACTIONS
,/* Send-Notifications */
563 CUPSD_ACCESSLOG_ALL
, /* reserved */
564 CUPSD_ACCESSLOG_ALL
, /* reserved */
565 CUPSD_ACCESSLOG_ALL
, /* reserved */
566 CUPSD_ACCESSLOG_ALL
, /* Get-Print-Support-Files */
567 CUPSD_ACCESSLOG_CONFIG
, /* Enable-Printer */
568 CUPSD_ACCESSLOG_CONFIG
, /* Disable-Printer */
569 CUPSD_ACCESSLOG_CONFIG
, /* Pause-Printer-After-Current-Job */
570 CUPSD_ACCESSLOG_ACTIONS
,/* Hold-New-Jobs */
571 CUPSD_ACCESSLOG_ACTIONS
,/* Release-Held-New-Jobs */
572 CUPSD_ACCESSLOG_CONFIG
, /* Deactivate-Printer */
573 CUPSD_ACCESSLOG_CONFIG
, /* Activate-Printer */
574 CUPSD_ACCESSLOG_CONFIG
, /* Restart-Printer */
575 CUPSD_ACCESSLOG_CONFIG
, /* Shutdown-Printer */
576 CUPSD_ACCESSLOG_CONFIG
, /* Startup-Printer */
577 CUPSD_ACCESSLOG_ACTIONS
,/* Reprocess-Job */
578 CUPSD_ACCESSLOG_ACTIONS
,/* Cancel-Current-Job */
579 CUPSD_ACCESSLOG_ACTIONS
,/* Suspend-Current-Job */
580 CUPSD_ACCESSLOG_ACTIONS
,/* Resume-Job */
581 CUPSD_ACCESSLOG_ACTIONS
,/* Promote-Job */
582 CUPSD_ACCESSLOG_ACTIONS
/* Schedule-Job-After */
584 static cupsd_accesslog_t cups_ops
[] =
586 CUPSD_ACCESSLOG_ALL
, /* CUPS-Get-Default */
587 CUPSD_ACCESSLOG_ALL
, /* CUPS-Get-Printers */
588 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Add-Modify-Printer */
589 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Delete-Printer */
590 CUPSD_ACCESSLOG_ALL
, /* CUPS-Get-Classes */
591 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Add-Modify-Class */
592 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Delete-Class */
593 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Accept-Jobs */
594 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Reject-Jobs */
595 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Set-Default */
596 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Get-Devices */
597 CUPSD_ACCESSLOG_CONFIG
, /* CUPS-Get-PPDs */
598 CUPSD_ACCESSLOG_ACTIONS
,/* CUPS-Move-Job */
599 CUPSD_ACCESSLOG_ACTIONS
,/* CUPS-Authenticate-Job */
600 CUPSD_ACCESSLOG_ALL
/* CUPS-Get-PPD */
604 if ((op
<= IPP_SCHEDULE_JOB_AFTER
&& standard_ops
[op
] > AccessLogLevel
) ||
605 (op
>= CUPS_GET_DEFAULT
&& op
<= CUPS_GET_PPD
&&
606 cups_ops
[op
- CUPS_GET_DEFAULT
] > AccessLogLevel
))
613 * See if we are logging accesses via syslog...
616 if (!strcmp(AccessLog
, "syslog"))
619 "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT
" %s %s\n",
620 con
->http
.hostname
, con
->username
[0] != '\0' ? con
->username
: "-",
621 states
[con
->operation
], _httpEncodeURI(temp
, con
->uri
, sizeof(temp
)),
622 con
->http
.version
/ 100, con
->http
.version
% 100,
623 code
, CUPS_LLCAST con
->bytes
,
625 ippOpString(con
->request
->request
.op
.operation_id
) : "-",
627 ippErrorString(con
->response
->request
.status
.status_code
) : "-");
631 #endif /* HAVE_VSYSLOG */
634 * Not using syslog; check the log file...
637 if (!check_log_file(&AccessFile
, AccessLog
))
641 * Write a log of the request in "common log format"...
644 cupsFilePrintf(AccessFile
,
645 "%s - %s %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT
" %s %s\n",
646 con
->http
.hostname
, con
->username
[0] != '\0' ? con
->username
: "-",
647 cupsdGetDateTime(&(con
->start
), LogTimeFormat
),
648 states
[con
->operation
],
649 _httpEncodeURI(temp
, con
->uri
, sizeof(temp
)),
650 con
->http
.version
/ 100, con
->http
.version
% 100,
651 code
, CUPS_LLCAST con
->bytes
,
653 ippOpString(con
->request
->request
.op
.operation_id
) : "-",
655 ippErrorString(con
->response
->request
.status
.status_code
) :
658 cupsFileFlush(AccessFile
);
665 * 'cupsdWriteErrorLog()' - Write a line to the ErrorLog.
668 int /* O - 1 on success, 0 on failure */
669 cupsdWriteErrorLog(int level
, /* I - Log level */
670 const char *message
) /* I - Message string */
672 static const char levels
[] = /* Log levels... */
686 static const int syslevels
[] = /* SYSLOG levels... */
699 #endif /* HAVE_VSYSLOG */
704 * See if we are logging errors via syslog...
707 if (!strcmp(ErrorLog
, "syslog"))
709 syslog(syslevels
[level
], "%s", message
);
712 #endif /* HAVE_VSYSLOG */
715 * Not using syslog; check the log file...
718 if (!check_log_file(&ErrorFile
, ErrorLog
))
722 * Write the log message...
725 cupsFilePrintf(ErrorFile
, "%c %s %s\n", levels
[level
],
726 cupsdGetDateTime(NULL
, LogTimeFormat
), message
);
727 cupsFileFlush(ErrorFile
);
734 * 'check_log_file()' - Open/rotate a log file if it needs it.
737 static int /* O - 1 if log file open */
738 check_log_file(cups_file_t
**lf
, /* IO - Log file */
739 const char *logname
) /* I - Log filename */
741 char backname
[1024], /* Backup log filename */
742 filename
[1024], /* Formatted log filename */
743 *ptr
; /* Pointer into filename */
744 const char *logptr
; /* Pointer into log filename */
748 * See if we have a log file to check...
751 if (!lf
|| !logname
|| !logname
[0])
755 * Format the filename as needed...
759 (strncmp(logname
, "/dev/", 5) && cupsFileTell(*lf
) > MaxLogSize
&&
763 * Handle format strings...
766 filename
[sizeof(filename
) - 1] = '\0';
768 if (logname
[0] != '/')
770 strlcpy(filename
, ServerRoot
, sizeof(filename
));
771 strlcat(filename
, "/", sizeof(filename
));
776 for (logptr
= logname
, ptr
= filename
+ strlen(filename
);
777 *logptr
&& ptr
< (filename
+ sizeof(filename
) - 1);
789 * Insert the server name...
792 strlcpy(ptr
, ServerName
, sizeof(filename
) - (ptr
- filename
));
798 * Otherwise just insert the character...
811 * See if the log file is open...
817 * Nope, open the log file...
820 if ((*lf
= cupsFileOpen(filename
, "a")) == NULL
)
823 * If the file is in CUPS_LOGDIR then try to create a missing directory...
826 if (!strncmp(filename
, CUPS_LOGDIR
, strlen(CUPS_LOGDIR
)))
829 * Try updating the permissions of the containing log directory, using
830 * the log file permissions as a basis...
833 int log_dir_perm
= 0300 | LogFilePerm
;
834 /* LogFilePerm + owner write/search */
835 if (log_dir_perm
& 0040)
836 log_dir_perm
|= 0010; /* Add group search */
837 if (log_dir_perm
& 0004)
838 log_dir_perm
|= 0001; /* Add other search */
840 cupsdCheckPermissions(CUPS_LOGDIR
, NULL
, log_dir_perm
, RunUser
, Group
,
843 *lf
= cupsFileOpen(filename
, "a");
848 syslog(LOG_ERR
, "Unable to open log file \"%s\" - %s", filename
,
851 if (FatalErrors
& CUPSD_FATAL_LOG
)
852 cupsdEndProcess(getpid(), 0);
858 if (strncmp(filename
, "/dev/", 5))
861 * Change ownership and permissions of non-device logs...
864 fchown(cupsFileNumber(*lf
), RunUser
, Group
);
865 fchmod(cupsFileNumber(*lf
), LogFilePerm
);
870 * Do we need to rotate the log?
873 if (strncmp(logname
, "/dev/", 5) && cupsFileTell(*lf
) > MaxLogSize
&&
882 strcpy(backname
, filename
);
883 strlcat(backname
, ".O", sizeof(backname
));
886 rename(filename
, backname
);
888 if ((*lf
= cupsFileOpen(filename
, "a")) == NULL
)
890 syslog(LOG_ERR
, "Unable to open log file \"%s\" - %s", filename
,
893 if (FatalErrors
& CUPSD_FATAL_LOG
)
894 cupsdEndProcess(getpid(), 0);
900 * Change ownership and permissions of non-device logs...
903 fchown(cupsFileNumber(*lf
), RunUser
, Group
);
904 fchmod(cupsFileNumber(*lf
), LogFilePerm
);
912 * 'format_log_line()' - Format a line for a log file.
914 * This function resizes a global string buffer as needed. Each call returns
915 * a pointer to this buffer, so the contents are only good until the next call
916 * to format_log_line()...
919 static int /* O - -1 for fatal, 0 for retry, 1 for success */
920 format_log_line(const char *message
, /* I - Printf-style format string */
921 va_list ap
) /* I - Argument list */
923 int len
; /* Length of formatted line */
927 * Allocate the line buffer as needed...
933 log_line
= malloc(log_linesize
);
940 * Format the log message...
943 len
= vsnprintf(log_line
, log_linesize
, message
, ap
);
946 * Resize the buffer as needed...
949 if (len
>= log_linesize
&& log_linesize
< 65536)
951 char *temp
; /* Temporary string pointer */
958 else if (len
> 65536)
961 temp
= realloc(log_line
, len
);
977 * End of "$Id: log.c 7918 2008-09-08 22:03:01Z mike $".