#include "cupsd.h"
#include <stdarg.h>
#ifdef HAVE_VSYSLOG
# include <syslog.h>
#endif
static int check_log_file(cups_file_t **, const char *);
char *
GetDateTime(time_t t)
{
struct tm *date;
static char s[1024];
static const char * const months[12] =
{
"Jan",
"Feb",
"Mar",
"Apr",
"May",
"Jun",
"Jul",
"Aug",
"Sep",
"Oct",
"Nov",
"Dec"
};
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);
}
int
LogMessage(int level,
const char *message,
...)
{
int len;
char *ptr;
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;
static char sigbuf[1024];
if (level > LogLevel)
return (1);
HoldSignals();
#ifdef HAVE_VSYSLOG
if (strcmp(ErrorLog, "syslog") == 0)
{
va_start(ap, message);
vsyslog(syslevels[level], message, ap);
va_end(ap);
ReleaseSignals();
return (1);
}
#endif
if (!check_log_file(&ErrorFile, ErrorLog))
{
ReleaseSignals();
return (0);
}
cupsFilePrintf(ErrorFile, "%c %s ", levels[level], GetDateTime(time(NULL)));
if (SignalCount)
{
va_start(ap, message);
len = vsnprintf(sigbuf, sizeof(sigbuf), message, ap);
va_end(ap);
ptr = sigbuf;
if (len >= sizeof(sigbuf))
len = sizeof(sigbuf) - 1;
}
else
{
if (!linesize)
{
linesize = 8192;
line = malloc(linesize);
if (!line)
{
cupsFilePrintf(ErrorFile,
"ERROR: Unable to allocate memory for line - %s\n",
strerror(errno));
cupsFileFlush(ErrorFile);
ReleaseSignals();
return (0);
}
}
va_start(ap, message);
len = vsnprintf(line, linesize, message, ap);
va_end(ap);
if (len >= linesize)
{
len ++;
if (len < 8192)
len = 8192;
else if (len > 65536)
len = 65536;
line = realloc(line, len);
if (line)
linesize = len;
else
{
cupsFilePrintf(ErrorFile,
"ERROR: Unable to allocate memory for line - %s\n",
strerror(errno));
cupsFileFlush(ErrorFile);
ReleaseSignals();
return (0);
}
va_start(ap, message);
len = vsnprintf(line, linesize, message, ap);
va_end(ap);
}
ptr = line;
if (len >= linesize)
len = linesize - 1;
}
cupsFilePuts(ErrorFile, line);
if (len > 0 && line[len - 1] != '\n')
cupsFilePutChar(ErrorFile, '\n');
cupsFileFlush(ErrorFile);
ReleaseSignals();
return (1);
}
int
LogPage(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);
HoldSignals();
#ifdef HAVE_VSYSLOG
if (strcmp(PageLog, "syslog") == 0)
{
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);
ReleaseSignals();
return (1);
}
#endif
if (!check_log_file(&PageFile, PageLog))
{
ReleaseSignals();
return (0);
}
cupsFilePrintf(PageFile, "%s %s %d %s %s %s %s\n", job->printer->name,
job->username ? job->username : "-",
job->id, GetDateTime(time(NULL)), page,
billing ? billing->values[0].string.text : "-",
hostname->values[0].string.text);
cupsFileFlush(PageFile);
ReleaseSignals();
return (1);
}
int
LogRequest(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"
};
HoldSignals();
#ifdef HAVE_VSYSLOG
if (strcmp(AccessLog, "syslog") == 0)
{
syslog(LOG_INFO, "REQUEST %s - %s \"%s %s HTTP/%d.%d\" %d %d\n",
con->http.hostname, con->username[0] != '\0' ? con->username : "-",
states[con->operation], con->uri,
con->http.version / 100, con->http.version % 100,
code, con->bytes);
ReleaseSignals();
return (1);
}
#endif
if (!check_log_file(&AccessFile, AccessLog))
{
ReleaseSignals();
return (0);
}
cupsFilePrintf(AccessFile, "%s - %s %s \"%s %s HTTP/%d.%d\" %d %d\n",
con->http.hostname, con->username[0] != '\0' ? con->username : "-",
GetDateTime(con->start), states[con->operation], con->uri,
con->http.version / 100, con->http.version % 100,
code, con->bytes);
cupsFileFlush(AccessFile);
ReleaseSignals();
return (1);
}
static int
check_log_file(cups_file_t **log,
const char *logname)
{
char backname[1024],
filename[1024],
*ptr;
if (log == NULL || logname == NULL || !logname[0] || SignalCount)
return (1);
if (*log == NULL ||
(cupsFileTell(*log) > 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 (ptr = filename + strlen(filename);
*logname && ptr < (filename + sizeof(filename) - 1);
logname ++)
if (*logname == '%')
{
logname ++;
if (*logname == 's')
{
strlcpy(ptr, ServerName, sizeof(filename) - (ptr - filename));
ptr += strlen(ptr);
}
else
{
*ptr++ = *logname;
}
}
else
*ptr++ = *logname;
*ptr = '\0';
}
if (*log == NULL)
{
if ((*log = cupsFileOpen(filename, "a")) == NULL)
return (0);
if (strncmp(filename, "/dev/", 5))
{
fchown(cupsFileNumber(*log), User, Group);
fchmod(cupsFileNumber(*log), LogFilePerm);
}
}
if (cupsFileTell(*log) > MaxLogSize && MaxLogSize > 0)
{
cupsFileClose(*log);
strcpy(backname, filename);
strlcat(backname, ".O", sizeof(backname));
unlink(backname);
rename(filename, backname);
if ((*log = cupsFileOpen(filename, "a")) == NULL)
return (0);
if (strncmp(filename, "/dev/", 5))
{
fchown(cupsFileNumber(*log), User, Group);
fchmod(cupsFileNumber(*log), LogFilePerm);
}
}
return (1);
}