#include "cupsd.h"
#include <stdarg.h>
#include <syslog.h>
static int check_log_file(cups_file_t **, const char *);
char *
cupsdGetDateTime(time_t t)
{
struct tm *date;
static time_t last_time = -1;
static char s[1024];
static const char * const months[12] =
{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
if (t != last_time)
{
last_time = t;
date = localtime(&t);
snprintf(s, sizeof(s), "[%02d/%s/%04d:%02d:%02d:%02d %+03ld%02ld]",
date->tm_mday, months[date->tm_mon], 1900 + date->tm_year,
date->tm_hour, date->tm_min, date->tm_sec,
#ifdef HAVE_TM_GMTOFF
date->tm_gmtoff / 3600, (date->tm_gmtoff / 60) % 60);
#else
timezone / 3600, (timezone / 60) % 60);
#endif
}
return (s);
}
#ifdef HAVE_GSSAPI
int
cupsdLogGSSMessage(
int level,
int major_status,
int minor_status,
const char *message,
...)
{
OM_uint32 err_major_status,
err_minor_status;
OM_uint32 msg_ctx;
gss_buffer_desc major_status_string = GSS_C_EMPTY_BUFFER,
minor_status_string = GSS_C_EMPTY_BUFFER;
int ret;
msg_ctx = 0;
err_major_status = gss_display_status(&err_minor_status,
major_status,
GSS_C_GSS_CODE,
GSS_C_NO_OID,
&msg_ctx,
&major_status_string);
if (!GSS_ERROR(err_major_status))
err_major_status = gss_display_status(&err_minor_status,
minor_status,
GSS_C_MECH_CODE,
GSS_C_NULL_OID,
&msg_ctx,
&minor_status_string);
ret = cupsdLogMessage(level, "%s: %s, %s", message,
(char *)major_status_string.value,
(char *)minor_status_string.value);
gss_release_buffer(&err_minor_status, &major_status_string);
gss_release_buffer(&err_minor_status, &minor_status_string);
return (ret);
}
#endif
int
cupsdLogMessage(int level,
const char *message,
...)
{
int len;
va_list ap;
static const char levels[] =
{
' ',
'X',
'A',
'C',
'E',
'W',
'N',
'I',
'D',
'd'
};
#ifdef HAVE_VSYSLOG
static const int syslevels[] =
{
0,
LOG_EMERG,
LOG_ALERT,
LOG_CRIT,
LOG_ERR,
LOG_WARNING,
LOG_NOTICE,
LOG_INFO,
LOG_DEBUG,
LOG_DEBUG
};
#endif
static int linesize = 0;
static char *line = NULL;
if (level > LogLevel || !ErrorLog)
return (1);
#ifdef HAVE_VSYSLOG
if (!strcmp(ErrorLog, "syslog"))
{
va_start(ap, message);
vsyslog(syslevels[level], message, ap);
va_end(ap);
return (1);
}
#endif
if (!check_log_file(&ErrorFile, ErrorLog))
return (0);
cupsFilePrintf(ErrorFile, "%c %s ", levels[level], cupsdGetDateTime(time(NULL)));
if (!linesize)
{
linesize = 8192;
line = malloc(linesize);
if (!line)
{
cupsFilePrintf(ErrorFile,
"ERROR: Unable to allocate memory for line - %s\n",
strerror(errno));
cupsFileFlush(ErrorFile);
return (0);
}
}
va_start(ap, message);
len = vsnprintf(line, linesize, message, ap);
va_end(ap);
if (len >= linesize)
{
char *temp;
len ++;
if (len < 8192)
len = 8192;
else if (len > 65536)
len = 65536;
temp = realloc(line, len);
if (temp)
{
line = temp;
linesize = len;
}
va_start(ap, message);
len = vsnprintf(line, linesize, message, ap);
va_end(ap);
}
if (len >= linesize)
len = linesize - 1;
cupsFilePuts(ErrorFile, line);
if (len > 0 && line[len - 1] != '\n')
cupsFilePutChar(ErrorFile, '\n');
cupsFileFlush(ErrorFile);
return (1);
}
int
cupsdLogPage(cupsd_job_t *job,
const char *page)
{
ipp_attribute_t *billing,
*hostname;
billing = ippFindAttribute(job->attrs, "job-billing", IPP_TAG_ZERO);
hostname = ippFindAttribute(job->attrs, "job-originating-host-name",
IPP_TAG_ZERO);
#ifdef HAVE_VSYSLOG
if (!strcmp(PageLog, "syslog"))
{
syslog(LOG_INFO, "PAGE %s %s %d %s %s %s", job->printer->name,
job->username ? job->username : "-",
job->id, page, billing ? billing->values[0].string.text : "-",
hostname->values[0].string.text);
return (1);
}
#endif
if (!check_log_file(&PageFile, PageLog))
return (0);
cupsFilePrintf(PageFile, "%s %s %d %s %s %s %s\n", job->printer->name,
job->username ? job->username : "-",
job->id, cupsdGetDateTime(time(NULL)), page,
billing ? billing->values[0].string.text : "-",
hostname->values[0].string.text);
cupsFileFlush(PageFile);
return (1);
}
int
cupsdLogRequest(cupsd_client_t *con,
http_status_t code)
{
static const char * const states[] =
{
"WAITING",
"OPTIONS",
"GET",
"GET",
"HEAD",
"POST",
"POST",
"POST",
"PUT",
"PUT",
"DELETE",
"TRACE",
"CLOSE",
"STATUS"
};
#ifdef HAVE_VSYSLOG
if (!strcmp(AccessLog, "syslog"))
{
syslog(LOG_INFO,
"REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n",
con->http.hostname, con->username[0] != '\0' ? con->username : "-",
states[con->operation], con->uri,
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) : "-");
return (1);
}
#endif
if (!check_log_file(&AccessFile, AccessLog))
return (0);
cupsFilePrintf(AccessFile,
"%s - %s %s \"%s %s HTTP/%d.%d\" %d " CUPS_LLFMT " %s %s\n",
con->http.hostname, con->username[0] != '\0' ? con->username : "-",
cupsdGetDateTime(con->start), states[con->operation], con->uri,
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) :
"-");
cupsFileFlush(AccessFile);
return (1);
}
static int
check_log_file(cups_file_t **lf,
const char *logname)
{
char backname[1024],
filename[1024],
*ptr;
const char *logptr;
if (!lf || !logname || !logname[0])
return (1);
if (!*lf ||
(strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize &&
MaxLogSize > 0))
{
filename[sizeof(filename) - 1] = '\0';
if (logname[0] != '/')
{
strlcpy(filename, ServerRoot, sizeof(filename));
strlcat(filename, "/", sizeof(filename));
}
else
filename[0] = '\0';
for (logptr = logname, ptr = filename + strlen(filename);
*logptr && ptr < (filename + sizeof(filename) - 1);
logptr ++)
if (*logptr == '%')
{
logptr ++;
if (*logptr == 's')
{
strlcpy(ptr, ServerName, sizeof(filename) - (ptr - filename));
ptr += strlen(ptr);
}
else
{
*ptr++ = *logptr;
}
}
else
*ptr++ = *logptr;
*ptr = '\0';
}
if (!*lf)
{
if ((*lf = cupsFileOpen(filename, "a")) == NULL)
{
if (!strncmp(filename, CUPS_LOGDIR, strlen(CUPS_LOGDIR)))
{
cupsdCheckPermissions(CUPS_LOGDIR, NULL, 0755, RunUser, Group, 1, -1);
*lf = cupsFileOpen(filename, "a");
}
if (*lf == NULL)
{
syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename,
strerror(errno));
return (0);
}
}
if (strncmp(filename, "/dev/", 5))
{
fchown(cupsFileNumber(*lf), RunUser, Group);
fchmod(cupsFileNumber(*lf), LogFilePerm);
}
}
if (strncmp(logname, "/dev/", 5) && cupsFileTell(*lf) > MaxLogSize &&
MaxLogSize > 0)
{
cupsFileClose(*lf);
strcpy(backname, filename);
strlcat(backname, ".O", sizeof(backname));
unlink(backname);
rename(filename, backname);
if ((*lf = cupsFileOpen(filename, "a")) == NULL)
{
syslog(LOG_ERR, "Unable to open log file \"%s\" - %s", filename,
strerror(errno));
return (0);
}
fchown(cupsFileNumber(*lf), RunUser, Group);
fchmod(cupsFileNumber(*lf), LogFilePerm);
}
return (1);
}