Port from 2.7: Logging infrastructure updates.
* Basic port of the Squid-2.7 modular logging code
* Adds support for async daemon helpers.
* One daemon helper for file IO is included.
* Adds UDP stream logging facility. (Tim Starling)
Ported by Amos Jeffries.
fi
AC_SUBST(DIGEST_AUTH_HELPERS)
+dnl Select logging daemon helpers to build
+LOG_DAEMON_HELPERS="all"
+AC_ARG_ENABLE(log-daemon-helpers,
+ AS_HELP_STRING([--enable-log-daemon-auth-helpers="list of helpers"],[This option selects which logging daemon
+ helpers to build and install as part of the normal build process. For a list of available
+ helpers see the helpers/log_daemon directory.]),
+[ case "$enableval" in
+ yes)
+ LOG_DAEMON_HELPERS="all"
+ ;;
+ no)
+ LOG_DAEMON_HELPERS=""
+ ;;
+ *)
+ LOG_DAEMON_HELPERS="`echo $enableval| sed -e 's/,/ /g;s/ */ /g'`"
+ ;;
+ esac
+])
+if test "$LOG_DAEMON_HELPERS" = "all" ; then
+ LOG_DAEMON_HELPERS=""
+ for dir in $srcdir/helpers/log_daemon/*; do
+ helper="`basename $dir`"
+ if test -f $dir/config.test && sh $dir/config.test "$@"; then
+ LOG_DAEMON_HELPERS="$LOG_DAEMON_HELPERS $helper"
+ elif test -d $srcdir/helpers/log_daemon/$helper ; then
+ AC_MSG_NOTICE([Log daemon auth helper $helper ... found but cannot be built])
+ fi
+ done
+fi
+if test -n "$LOG_DAEMON_HELPERS"; then
+ for helper in $LOG_DAEMON_HELPERS; do
+ if test -d $srcdir/helpers/log_daemon/$helper; then
+ :
+ else
+ AC_MSG_ERROR(Log daemon helper $helper does not exist)
+ fi
+ done
+ AC_MSG_NOTICE([Log daemon helpers built: $LOG_DAEMON_HELPERS])
+fi
+AC_SUBST(LOG_DAEMON_HELPERS)
+
dnl
dnl Check Kerberos/GSSAPI/SPNEGO
dnl
src/icmp/Makefile \
src/ident/Makefile \
src/ip/Makefile \
+ src/log/Makefile \
contrib/Makefile \
snmplib/Makefile \
icons/Makefile \
helpers/external_acl/wbinfo_group/Makefile \
helpers/external_acl/mswin_ad_group/Makefile \
helpers/external_acl/mswin_lm_group/Makefile \
+ helpers/log_daemon/Makefile \
+ helpers/log_daemon/file/Makefile \
helpers/url_rewrite/Makefile \
helpers/url_rewrite/fake/Makefile \
tools/Makefile
network Only objects fetched from network is kept in memory
</verb>
+ <tag>logfile_daemon</tag>
+ <p>Ported from 2.7
+
</descrip>
<sect1>Changes to existing tags<label id="modifiedtags">
<tag>redirector_bypass</tag>
<p>Replaced by <em>url_rewrite_bypass</em>
+ <tag>upgrade_http0.9</tag>
+ <p>Obsolete.
+
<tag>zph_local</tag>
<p>Replaced by <em>qos_flows local-hit=</em>
<tag>location_rewrite_program</tag>
<p>Not yet ported from 2.6
- <tag>logfile_daemon</tag>
- <p>Not yet ported from 2.7
-
<tag>logformat</tag>
<p><em>%oa</em> tag not yet ported from 2.7
<tag>update_headers</tag>
<p>Not yet ported from 2.7
- <tag>upgrade_http0.9</tag>
- <p>Not yet ported from 2.7
-
<tag>zero_buffers</tag>
<p>Not yet ported from 2.7
-SUBDIRS = basic_auth ntlm_auth digest_auth negotiate_auth external_acl url_rewrite
+SUBDIRS = \
+ basic_auth \
+ digest_auth \
+ external_acl \
+ log_daemon \
+ negotiate_auth \
+ ntlm_auth \
+ url_rewrite
--- /dev/null
+## Alphabetical list of sub-directories to distribute with Squid:
+DIST_SUBDIRS = \
+ file
+
+SUBDIRS = $(LOG_DAEMON_HELPERS)
--- /dev/null
+include $(top_srcdir)/src/Common.am
+
+libexec_PROGRAMS = log_file_daemon
+log_file_daemon_SOURCES = log_file_daemon.cc
--- /dev/null
+#!/bin/sh
+exit 0
--- /dev/null
+#include "config.h"
+
+#if HAVE_STDIO_H
+#include <stdio.h>
+#endif
+#if HAVE_STDLIB_H
+#include <stdlib.h>
+#endif
+#if HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+#if HAVE_FCNTL_H
+#include <fcntl.h>
+#endif
+#if HAVE_ASSERT_H
+#include <assert.h>
+#endif
+#if HAVE_SYS_PARAM_H
+#include <sys/param.h>
+#endif
+#if HAVE_SYS_STAT_H
+#include <sys/stat.h>
+#endif
+#if HAVE_SIGNAL_H
+#include <signal.h>
+#endif
+#if HAVE_ERRNO_H
+#include <errno.h>
+#endif
+#if HAVE_STRING_H
+#include <string.h>
+#endif
+#if HAVE_PATHS_H
+#include <paths.h>
+#endif
+
+#include "defines.h"
+
+/* parse buffer - ie, length of longest expected line */
+#define LOGFILE_BUF_LEN 65536
+
+static void
+rotate(const char *path, int rotate_count)
+{
+#ifdef S_ISREG
+ struct stat sb;
+#endif
+ int i;
+ char from[MAXPATHLEN];
+ char to[MAXPATHLEN];
+ assert(path);
+#ifdef S_ISREG
+ if (stat(path, &sb) == 0)
+ if (S_ISREG(sb.st_mode) == 0)
+ return;
+#endif
+ /* Rotate numbers 0 through N up one */
+ for (i = rotate_count; i > 1;) {
+ i--;
+ snprintf(from, MAXPATHLEN, "%s.%d", path, i - 1);
+ snprintf(to, MAXPATHLEN, "%s.%d", path, i);
+#if defined(_SQUID_OS2_) || defined(_SQUID_WIN32_)
+ remove(to);
+#endif
+ rename(from, to);
+ }
+ if (rotate_count > 0) {
+ snprintf(to, MAXPATHLEN, "%s.%d", path, 0);
+#if defined(_SQUID_OS2_) || defined(_SQUID_WIN32_)
+ remove(to);
+#endif
+ rename(path, to);
+ }
+}
+
+/**
+ * The commands:
+ *
+ * L<data>\n - logfile data
+ * R\n - rotate file
+ * T\n - truncate file
+ * O\n - repoen file
+ * F\n - flush file
+ * r<n>\n - set rotate count to <n>
+ * b<n>\n - 1 = buffer output, 0 = don't buffer output
+ */
+int
+main(int argc, char *argv[])
+{
+ int t;
+ FILE *fp;
+ char buf[LOGFILE_BUF_LEN];
+ int rotate_count = 10;
+ int do_buffer = 1;
+
+ if (argc < 2) {
+ printf("Error: usage: %s <logfile>\n", argv[0]);
+ exit(1);
+ }
+ fp = fopen(argv[1], "a");
+ if (fp == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+ setbuf(stdout, NULL);
+ close(2);
+ t = open(_PATH_DEVNULL, O_RDWR);
+ assert(t > -1);
+ dup2(t, 2);
+
+ while (fgets(buf, LOGFILE_BUF_LEN, stdin)) {
+ /* First byte indicates what we're logging! */
+ switch (buf[0]) {
+ case 'L':
+ if (buf[1] != '\0') {
+ fprintf(fp, "%s", buf + 1);
+ }
+ if (!do_buffer)
+ fflush(fp);
+ break;
+ case 'R':
+ fclose(fp);
+ rotate(argv[1], rotate_count);
+ fp = fopen(argv[1], "a");
+ if (fp == NULL) {
+ perror("fopen");
+ exit(1);
+ }
+ break;
+ case 'T':
+ break;
+ case 'O':
+ break;
+ case 'r':
+ //fprintf(fp, "SET ROTATE: %s\n", buf + 1);
+ rotate_count = atoi(buf + 1);
+ break;
+ case 'b':
+ //fprintf(fp, "SET BUFFERED: %s\n", buf + 1);
+ do_buffer = (buf[1] == '1');
+ break;
+ case 'F':
+ fflush(fp);
+ break;
+ default:
+ /* Just in case .. */
+ fprintf(fp, "%s", buf);
+ break;
+ }
+ }
+ fclose(fp);
+ fp = NULL;
+ exit(0);
+}
#define LEAK_CHECK_MODE 1
#endif
+/* temp hack: needs to be pre-defined for now. */
+#define SQUID_MAXPATHLEN 256
/*
* strnstr() is needed. The OS may not provide a working copy.
LoadableModules.h \
LoadableModules.cc
-SUBDIRS = base eui acl fs repl auth ip icmp ident
+SUBDIRS = base eui acl fs repl auth ip icmp ident log
if USE_ADAPTATION
SUBDIRS += adaptation
squid_SOURCES = \
$(ACL_REGISTRATION_SOURCES) \
- access_log.cc \
AccessLogEntry.h \
AsyncEngine.cc \
AsyncEngine.h \
ipcache.cc \
$(LEAKFINDERSOURCE) \
list.cc \
- logfile.cc \
lookup_t.h \
main.cc \
mem.cc \
$(COMMON_LIBS) \
eui/libeui.la \
icmp/libicmp.la icmp/libicmp-core.la \
+ log/liblog.la \
$(XTRA_OBJS) \
$(DISK_LINKOBJS) \
$(REPL_OBJS) \
unlinkd_SOURCES = unlinkd_daemon.cc SquidNew.cc
-dnsserver_SOURCES = dnsserver.cc SquidNew.cc
+dnsserver_SOURCES = dnsserver.cc SquidNew.cc test_tools.cc time.cc
recv_announce_SOURCES = recv-announce.cc SquidNew.cc
## What requires what..
MemBuf.cc \
MemBuf.cci \
MemBuf.h \
+ Parsing.h \
store_key_md5.cc \
StoreMeta.cc \
StoreMetaMD5.cc \
$(REGEXLIB) \
$(SNMPLIB) \
$(SSLLIB) \
- -L$(top_builddir)/lib -lmiscutil \
+ $(COMPAT_LIB) \
$(EPOLL_LIBS) \
$(MINGW_LIBS) \
$(XTRA_LIBS)
data_DATA = \
mib.txt
-LDADD = $(COMMON_LIBS)\
+LDADD = $(COMMON_LIBS) \
-L../lib \
-lmiscutil \
$(EPOLL_LIBS) \
DEFAULT_SWAP_DIR = $(localstatedir)/cache
DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'`
DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'`
+DEFAULT_LOGFILED = $(libexecdir)/`echo log_file_daemon | sed '$(transform);s/$$/$(EXEEXT)/'`
DEFAULT_DISKD = $(libexecdir)/`echo diskd | sed '$(transform);s/$$/$(EXEEXT)/'`
DEFAULT_ICON_DIR = $(datadir)/icons
DEFAULT_ERROR_DIR = $(datadir)/errors
-e "s%[@]DEFAULT_UNLINKD[@]%$(DEFAULT_UNLINKD)%g" \
-e "s%[@]DEFAULT_PINGER[@]%$(DEFAULT_PINGER)%g" \
-e "s%[@]DEFAULT_DISKD[@]%$(DEFAULT_DISKD)%g" \
+ -e "s%[@]DEFAULT_LOGFILED[@]%$(DEFAULT_LOGFILED)%g;" \
-e "s%[@]DEFAULT_CACHE_LOG[@]%$(DEFAULT_CACHE_LOG)%g" \
-e "s%[@]DEFAULT_ACCESS_LOG[@]%$(DEFAULT_ACCESS_LOG)%g" \
-e "s%[@]DEFAULT_STORE_LOG[@]%$(DEFAULT_STORE_LOG)%g" \
tests/stub_MemObject.cc mem_node.cc \
tests/stub_cache_manager.cc \
stmem.cc \
- tests/stub_comm.cc \
- tests/stub_http.cc \
HttpMsg.cc \
HttpRequestMethod.cc \
- tests/stub_mime.cc \
tests/stub_access_log.cc \
+ tests/stub_comm.cc \
+ tests/stub_http.cc \
+ tests/stub_mime.cc \
time.cc \
URLScheme.cc \
$(TEST_CALL_SOURCES) \
wordlist.cc
## acl.cc cache_cf.cc tools.cc \
## helper.cc String.cc cbdata.cc HttpHeaderTools.cc store.cc cache_manager.cc \
-## HttpHeader.cc url.cc mem.cc HttpRequest.cc Packer.cc access_log.cc \
-## MemBuf.cc StatHist.cc logfile.cc
+## HttpHeader.cc url.cc mem.cc HttpRequest.cc Packer.cc \
+## MemBuf.cc StatHist.cc
nodist_tests_testAuth_SOURCES = \
$(TESTSOURCES)
tests/testCacheManager.h \
tests/testMain.cc \
time.cc \
- access_log.cc \
BodyPipe.cc \
cache_manager.cc \
cache_cf.cc \
int.cc \
internal.cc \
list.cc \
- logfile.cc \
multicast.cc \
mem_node.cc \
MemBuf.cc \
tests_testCacheManager_LDADD = \
$(COMMON_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
+ log/liblog.la \
$(REPL_OBJS) \
${ADAPTATION_LIBS} \
$(ESI_LIBS) \
tests/testEvent.h \
tests/testMain.cc \
time.cc \
- access_log.cc \
BodyPipe.cc \
cache_manager.cc \
cache_cf.cc \
int.cc \
internal.cc \
list.cc \
- logfile.cc \
multicast.cc \
mem_node.cc \
MemBuf.cc \
tests_testEvent_LDADD = \
$(COMMON_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
+ log/liblog.la \
$(REPL_OBJS) \
${ADAPTATION_LIBS} \
$(ESI_LIBS) \
tests/testEventLoop.h \
tests/testMain.cc \
time.cc \
- access_log.cc \
BodyPipe.cc \
cache_manager.cc \
cache_cf.cc \
int.cc \
internal.cc \
list.cc \
- logfile.cc \
multicast.cc \
mem_node.cc \
MemBuf.cc \
tests_testEventLoop_LDADD = \
$(COMMON_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
+ log/liblog.la \
$(REPL_OBJS) \
${ADAPTATION_LIBS} \
$(ESI_LIBS) \
tests_test_http_range_SOURCES = \
tests/test_http_range.cc \
- access_log.cc \
BodyPipe.cc \
cache_cf.cc \
ProtoPort.cc \
$(IPC_SOURCE) \
ipcache.cc \
list.cc \
- logfile.cc \
mem.cc \
mem_node.cc \
MemObject.cc \
tests_test_http_range_LDADD = \
$(COMMON_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
+ log/liblog.la \
$(REPL_OBJS) \
${ADAPTATION_LIBS} \
$(ESI_LIBS) \
tests/testHttpRequestMethod.cc \
tests/testMain.cc \
time.cc \
- access_log.cc \
BodyPipe.cc \
cache_manager.cc \
cache_cf.cc \
int.cc \
internal.cc \
list.cc \
- logfile.cc \
multicast.cc \
mem_node.cc \
MemBuf.cc \
tests_testHttpRequest_LDADD = \
$(COMMON_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
+ log/liblog.la \
$(REPL_OBJS) \
${ADAPTATION_LIBS} \
$(ESI_LIBS) \
tests/testURLScheme.h \
tests/testMain.cc \
time.cc \
- access_log.cc \
BodyPipe.cc \
cache_manager.cc \
cache_cf.cc \
int.cc \
internal.cc \
list.cc \
- logfile.cc \
multicast.cc \
mem_node.cc \
MemBuf.cc \
tests_testURL_LDADD = \
$(COMMON_LIBS) \
icmp/libicmp.la icmp/libicmp-core.la \
+ log/liblog.la \
$(REGEXLIB) \
$(REPL_OBJS) \
${ADAPTATION_LIBS} \
return false;
}
+
+bool
+GetHostWithPort(char *token, IpAddress *ipa)
+{
+ char *t;
+ char *host;
+ char *tmp;
+ unsigned short port;
+
+ host = NULL;
+ port = 0;
+
+#if USE_IPV6
+ if (*token == '[') {
+ /* [host]:port */
+ host = token + 1;
+ t = strchr(host, ']');
+ if (!t)
+ return false;
+ *t++ = '\0';
+ if (*t != ':')
+ return false;
+ port = xatos(t + 1);
+ } else
+#endif
+ if ((t = strchr(token, ':'))) {
+ /* host:port */
+ host = token;
+ *t = '\0';
+ port = xatos(t + 1);
+
+ if (0 == port)
+ return false;
+ } else if ((port = strtol(token, &tmp, 10)), !*tmp) {
+ /* port */
+ } else {
+ host = token;
+ port = 0;
+ }
+
+ if (NULL == host)
+ ipa->SetAnyAddr();
+ else if ( ipa->GetHostByName(host) ) /* dont use ipcache. Accept either FQDN or IPA. */
+ (void) 0;
+ else
+ return false;
+
+ /* port MUST be set after the IPA lookup/conversion is performed. */
+ ipa->SetPort(port);
+
+ return true;
+}
extern bool StringToInt(const char *str, int &result, const char **p, int base);
extern bool StringToInt64(const char *str, int64_t &result, const char **p, int base);
+/**
+ * Parse a socket address (host:port), fill the given IpAddress object
+ * \retval false Failure.
+ * \retval true Success.
+ * Destroys token during parse.
+ */
+extern bool GetHostWithPort(char *token, IpAddress *ipa);
+
#endif /* SQUID_PARSING_H */
#include "squid.h"
#include "icap_log.h"
#include "AccessLogEntry.h"
+#include "log/File.h"
int IcapLogfileStatus = LOG_DISABLE;
*/
#include "squid.h"
-#include "ProtoPort.h"
-#include "HttpRequestMethod.h"
+
+#include "acl/Acl.h"
+#include "acl/Gadgets.h"
+#include "acl/MethodData.h"
+#if USE_ADAPTATION
+#include "adaptation/Config.h"
+#endif
+#if ICAP_CLIENT
+#include "adaptation/icap/Config.h"
+#endif
+#if USE_ECAP
+#include "adaptation/ecap/Config.h"
+#endif
#include "auth/Config.h"
#include "auth/Scheme.h"
#include "CacheManager.h"
-#include "Store.h"
-#include "SwapDir.h"
#include "ConfigParser.h"
-#include "acl/Acl.h"
-#include "acl/MethodData.h"
-#include "acl/Gadgets.h"
-#include "StoreFileSystem.h"
+#include "eui/Config.h"
+#if USE_SQUID_ESI
+#include "esi/Parser.h"
+#endif
+#include "HttpRequestMethod.h"
+#include "ident/Config.h"
+#include "ip/IpIntercept.h"
+#include "log/Config.h"
+#include "MemBuf.h"
#include "Parsing.h"
+#include "ProtoPort.h"
#include "rfc1738.h"
-#include "MemBuf.h"
+#if SQUID_SNMP
+#include "snmp.h"
+#endif
+#include "Store.h"
+#include "StoreFileSystem.h"
+#include "SwapDir.h"
#include "wordlist.h"
-#include "ident/Config.h"
-#include "ip/IpIntercept.h"
#if HAVE_GLOB_H
#include <glob.h>
#endif
-#if SQUID_SNMP
-#include "snmp.h"
-#endif
-#if USE_SQUID_ESI
-#include "esi/Parser.h"
-#endif
-#include "eui/Config.h"
-
#if USE_ADAPTATION
-#include "adaptation/Config.h"
-
static void parse_adaptation_service_set_type();
static void parse_adaptation_service_chain_type();
static void parse_adaptation_access_type();
-
#endif
#if ICAP_CLIENT
-#include "adaptation/icap/Config.h"
-
static void parse_icap_service_type(Adaptation::Icap::Config *);
static void dump_icap_service_type(StoreEntry *, const char *, const Adaptation::Icap::Config &);
static void free_icap_service_type(Adaptation::Icap::Config *);
static void parse_icap_class_type();
static void parse_icap_access_type();
-
#endif
#if USE_ECAP
-#include "adaptation/ecap/Config.h"
static void parse_ecap_service_type(Adaptation::Ecap::Config *);
static void dump_ecap_service_type(StoreEntry *, const char *, const Adaptation::Ecap::Config &);
static void free_ecap_service_type(Adaptation::Ecap::Config *);
requirePathnameExists("unlinkd_program", Config.Program.unlinkd);
#endif
-
+ requirePathnameExists("logfile_daemon", Log::TheConfig.logfile_daemon);
if (Config.Program.redirect)
requirePathnameExists("redirect_program", Config.Program.redirect->key);
}
#if USE_WCCPv2
-void
-parse_IpAddress_list_token(IpAddress_list ** head, char *token)
-{
- char *t;
- char *host;
- char *tmp;
-
- IpAddress ipa;
- unsigned short port;
- IpAddress_list *s;
-
- host = NULL;
- port = 0;
-
-#if USE_IPV6
- if (*token == '[') {
- /* [host]:port */
- host = token + 1;
- t = strchr(host, ']');
- if (!t)
- self_destruct();
- *t++ = '\0';
- if (*t != ':')
- self_destruct();
- port = xatos(t + 1);
- } else
-#endif
- if ((t = strchr(token, ':'))) {
- /* host:port */
- host = token;
- *t = '\0';
- port = xatos(t + 1);
-
- if (0 == port)
- self_destruct();
- } else if ((port = strtol(token, &tmp, 10)), !*tmp) {
- /* port */
- } else {
- host = token;
- port = 0;
- }
-
- if (NULL == host)
- ipa.SetAnyAddr();
- else if ( ipa.GetHostByName(host) ) /* dont use ipcache. Accept either FQDN or IPA. */
- (void) 0;
- else
- self_destruct();
-
- /* port MUST be set after the IPA lookup/conversion is perofrmed. */
- ipa.SetPort(port);
-
- while (*head)
- head = &(*head)->next;
-
- s = static_cast<IpAddress_list *>(xcalloc(1, sizeof(*s)));
- s->s = ipa;
-
- *head = s;
-}
-
static void
parse_IpAddress_list(IpAddress_list ** head)
{
char *token;
+ IpAddress_list *s;
+ IpAddress ipa;
while ((token = strtok(NULL, w_space))) {
- parse_IpAddress_list_token(head, token);
+ if (GetHostWithPort(token, &ipa)) {
+
+ while (*head)
+ head = &(*head)->next;
+
+ s = static_cast<IpAddress_list *>(xcalloc(1, sizeof(*s)));
+ s->s = ipa;
+
+ *head = s;
+ }
+ else
+ self_destruct();
}
}
TYPE: access_log
LOC: Config.Log.accesslogs
DEFAULT: none
-DEFAULT_IF_NONE: @DEFAULT_ACCESS_LOG@ squid
+DEFAULT_IF_NONE: daemon:@DEFAULT_ACCESS_LOG@ squid
DOC_START
These files log client request activities. Has a line every HTTP or
ICP request. The format is:
- access_log <filepath> [<logformat name> [acl acl ...]]
+ access_log <module>:<place> [<logformat name> [acl acl ...]]
access_log none [acl acl ...]]
-
- Will log to the specified file using the specified format (which
+
+ Will log to the specified module:place using the specified format (which
must be defined in a logformat directive) those entries which match
ALL the acl's specified (which must be defined in acl clauses).
- If no acl is specified, all requests will be logged to this file.
-
- To disable logging of a request use the filepath "none", in which case
- a logformat name should not be specified.
-
- To log the request via syslog specify a filepath of "syslog":
+ If no acl is specified, all requests will be logged to this destination.
+
+ ===== Modules Currently available =====
+
+ none Do not log any requests matchign these ACL.
+ Do not specify Place or logformat name.
+
+ stdio Write each log line to disk immediately at the completion of
+ each request.
+ Place: the filename and path to be written.
+
+ daemon Very similar to stdio. But instead of writing to disk the log
+ line is passed to a daemon helper for asychronous handling instead.
+ Place: varies depending on the daemon.
+
+ log_file_daemon Place: the file name and path to be written.
+
+ syslog To log each request via syslog facility.
+ Place: The syslog facility and priority level for these entries.
+ Place Format: facility.priority
- access_log syslog[:facility.priority] [format [acl1 [acl2 ....]]]
- where facility could be any of:
- authpriv, daemon, local0 .. local7 or user.
+ where facility could be any of:
+ authpriv, daemon, local0 ... local7 or user.
- And priority could be any of:
- err, warning, notice, info, debug.
+ And priority could be any of:
+ err, warning, notice, info, debug.
+
+ udp To send each log line as text data to a UDP receiver.
+ Place: The destination host name or IP and port.
+ Place Format: \\host:port
Default:
- access_log @DEFAULT_ACCESS_LOG@ squid
+ access_log daemon:@DEFAULT_ACCESS_LOG@ squid
DOC_END
NAME: icap_log
See also: logformat, log_icap, and %icap::<last_h
DOC_END
+NAME: logfile_daemon
+TYPE: string
+DEFAULT: @DEFAULT_LOGFILED@
+LOC: Log::TheConfig.logfile_daemon
+DOC_START
+ Specify the path to the logfile-writing daemon. This daemon is
+ used to write the access and store logs, if configured.
+DOC_END
+
NAME: log_access
TYPE: acl_access
LOC: Config.accessList.log
/* for shutting_down flag in xassert() */
#include "globals.h"
-/* cope with no squid.h */
-#ifndef MAXPATHLEN
-#define MAXPATHLEN 256
-#endif
-
char *Debug::debugOptions = NULL;
int Debug::override_X = 0;
int Debug::log_stderr = -1;
#include "squid.h"
#include "icmp/net_db.h"
+#include "log/File.h"
#include "cbdata.h"
#include "event.h"
#include "CacheManager.h"
*/
#include "config.h"
+#include "Debug.h"
#include "ip/IpAddress.h"
#include "util.h"
#error "INET6 defined but has been deprecated! Try running bootstrap and configure again."
#endif
-/* We want to use the debug routines when running as module of squid. */
-/* otherwise fallback to printf if those are not available. */
-#ifndef SQUID_DEBUG
-# define debugs(a,b,c) // drop.
-#else
-#warning "IpAddress built with Debugs!!"
-# include "../src/Debug.h"
-#endif
-
#if !USE_IPV6
// So there are some places where I will drop to using Macros too.
// At least I can restrict them to this file so they don't corrupt the app with C code.
testIpAddress.cc \
testIpAddress.h
nodist_testIpAddress_SOURCES= \
- ../tests/testMain.cc
+ $(top_srcdir)/src/tests/testMain.cc \
+ $(top_srcdir)/test-suite/test_tools.cc
testIpAddress_LDADD= \
libip.la \
$(XTRA_LIBS) \
struct timeval current_time;
double current_dtime;
time_t squid_curtime = 0;
-
+int shutting_down = 0;
void
testIpAddress::testDefaults()
--- /dev/null
+#include "config.h"
+#include "log/Config.h"
+
+Log::LogConfig Log::TheConfig;
--- /dev/null
+#ifndef SQUID_SRC_LOG_CONFIG_H
+#define SQUID_SRC_LOG_CONFIG_H
+
+namespace Log {
+
+class LogConfig
+{
+public:
+ char *logfile_daemon;
+};
+
+extern LogConfig TheConfig;
+
+}; // namespace Log
+
+#endif
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+#include "fde.h"
+#include "log/File.h"
+#include "log/ModDaemon.h"
+#include "log/ModStdio.h"
+#include "log/ModSyslog.h"
+#include "log/ModUdp.h"
+
+CBDATA_TYPE(Logfile);
+
+Logfile *
+logfileOpen(const char *path, size_t bufsz, int fatal_flag)
+{
+ int ret;
+ const char *patharg;
+
+ debugs(50, 1, "Logfile: opening log " << path);
+ CBDATA_INIT_TYPE(Logfile);
+
+ Logfile *lf = cbdataAlloc(Logfile);
+ xstrncpy(lf->path, path, MAXPATHLEN);
+ patharg = path;
+ /* need to call the per-logfile-type code */
+ if (strncmp(path, "stdio:", 6) == 0) {
+ patharg = path + 6;
+ ret = logfile_mod_stdio_open(lf, patharg, bufsz, fatal_flag);
+ } else if (strncmp(path, "daemon:", 7) == 0) {
+ patharg = path + 7;
+ ret = logfile_mod_daemon_open(lf, patharg, bufsz, fatal_flag);
+ } else if (strncmp(path, "udp:", 4) == 0) {
+ patharg = path + 4;
+ ret = logfile_mod_udp_open(lf, patharg, bufsz, fatal_flag);
+#if HAVE_SYSLOG
+ } else if (strncmp(path, "syslog:", 7) == 0) {
+ patharg = path + 7;
+ ret = logfile_mod_syslog_open(lf, patharg, bufsz, fatal_flag);
+#endif
+ } else {
+ ret = logfile_mod_stdio_open(lf, patharg, bufsz, fatal_flag);
+ }
+ if (!ret) {
+ if (fatal_flag)
+ fatalf("logfileOpen: path %s: couldn't open!\n", path);
+ else
+ debugs(50, 1, "logfileOpen: path " << path << ": couldn't open!");
+ lf->f_close(lf);
+ cbdataFree(lf);
+ return NULL;
+ }
+ assert(lf->data != NULL);
+
+ if (fatal_flag)
+ lf->flags.fatal = 1;
+
+ lf->sequence_number = 0;
+
+ return lf;
+}
+
+void
+logfileClose(Logfile * lf)
+{
+ debugs(50, 1, "Logfile: closing log " << lf->path);
+ lf->f_flush(lf);
+ lf->f_close(lf);
+ cbdataFree(lf);
+}
+
+void
+logfileRotate(Logfile * lf)
+{
+ debugs(50, 1, "logfileRotate: " << lf->path);
+ lf->f_rotate(lf);
+}
+
+void
+logfileWrite(Logfile * lf, char *buf, size_t len)
+{
+ lf->f_linewrite(lf, buf, len);
+}
+
+void
+logfilePrintf(Logfile * lf, const char *fmt,...)
+{
+ va_list args;
+ char buf[8192];
+ int s;
+
+ va_start(args, fmt);
+
+ s = vsnprintf(buf, 8192, fmt, args);
+
+ if (s > 8192) {
+ s = 8192;
+
+ if (fmt[strlen(fmt) - 1] == '\n')
+ buf[8191] = '\n';
+ }
+
+ logfileWrite(lf, buf, (size_t) s);
+ va_end(args);
+}
+
+void
+logfileLineStart(Logfile * lf)
+{
+ lf->f_linestart(lf);
+}
+
+void
+logfileLineEnd(Logfile * lf)
+{
+ lf->f_lineend(lf);
+ lf->sequence_number++;
+}
+
+void
+logfileFlush(Logfile * lf)
+{
+ lf->f_flush(lf);
+}
--- /dev/null
+#ifndef SQUID_SRC_LOG_FILE_H
+#define SQUID_SRC_LOG_FILE_H
+
+#include "config.h"
+#include "dlink.h"
+
+class logfile_buffer_t {
+public:
+ char *buf;
+ int size;
+ int len;
+ int written_len;
+ dlink_node node;
+};
+
+class Logfile;
+
+typedef void LOGLINESTART(Logfile *);
+typedef void LOGWRITE(Logfile *, const char *, size_t len);
+typedef void LOGLINEEND(Logfile *);
+typedef void LOGFLUSH(Logfile *);
+typedef void LOGROTATE(Logfile *);
+typedef void LOGCLOSE(Logfile *);
+
+class Logfile {
+
+public:
+ char path[SQUID_MAXPATHLEN];
+
+ struct {
+ unsigned int fatal;
+ } flags;
+
+ int64_t sequence_number; ///< Unique sequence number per log line.
+
+public:
+ void *data;
+
+ LOGLINESTART *f_linestart;
+ LOGWRITE *f_linewrite;
+ LOGLINEEND *f_lineend;
+ LOGFLUSH *f_flush;
+ LOGROTATE *f_rotate;
+ LOGCLOSE *f_close;
+};
+
+/* Legacy API */
+extern Logfile *logfileOpen(const char *path, size_t bufsz, int);
+extern void logfileClose(Logfile * lf);
+extern void logfileRotate(Logfile * lf);
+extern void logfileWrite(Logfile * lf, char *buf, size_t len);
+extern void logfileFlush(Logfile * lf);
+extern void logfilePrintf(Logfile * lf, const char *fmt,...) PRINTF_FORMAT_ARG2;
+extern void logfileLineStart(Logfile * lf);
+extern void logfileLineEnd(Logfile * lf);
+
+#endif /* SQUID_SRC_LOG_FILE_H */
--- /dev/null
+include $(top_srcdir)/src/Common.am
+include $(top_srcdir)/src/TestHeaders.am
+
+noinst_LTLIBRARIES = liblog.la
+
+liblog_la_SOURCES = \
+ access_log.cc \
+ Config.cc \
+ Config.h \
+ File.cc \
+ File.h \
+ ModDaemon.cc \
+ ModDaemon.h \
+ ModStdio.cc \
+ ModStdio.h \
+ ModSyslog.cc \
+ ModSyslog.h \
+ ModUdp.cc \
+ ModUdp.h
--- /dev/null
+/*
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Adrian Chadd <adrian@squid-cache.org>
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+#include "cbdata.h"
+#include "fde.h"
+#include "log/Config.h"
+#include "log/File.h"
+#include "log/ModDaemon.h"
+#include "SquidTime.h"
+
+/* How many buffers to keep before we say we've buffered too much */
+#define LOGFILE_MAXBUFS 128
+
+/* Size of the logfile buffer */
+/*
+ * For optimal performance this should match LOGFILE_BUFSIZ in logfile-daemon.c
+ */
+#define LOGFILE_BUFSZ 32768
+
+/* How many seconds between warnings */
+#define LOGFILE_WARN_TIME 30
+
+static LOGWRITE logfile_mod_daemon_writeline;
+static LOGLINESTART logfile_mod_daemon_linestart;
+static LOGLINEEND logfile_mod_daemon_lineend;
+static LOGROTATE logfile_mod_daemon_rotate;
+static LOGFLUSH logfile_mod_daemon_flush;
+static LOGCLOSE logfile_mod_daemon_close;
+
+static void logfile_mod_daemon_append(Logfile * lf, const char *buf, int len);
+
+struct _l_daemon {
+ int rfd, wfd;
+ char eol;
+ pid_t pid;
+ int flush_pending;
+ dlink_list bufs;
+ int nbufs;
+ int last_warned;
+};
+
+typedef struct _l_daemon l_daemon_t;
+
+/* Internal code */
+static void
+logfileNewBuffer(Logfile * lf)
+{
+ l_daemon_t *ll = (l_daemon_t *) lf->data;
+ logfile_buffer_t *b;
+
+ debugs(50, 5, "logfileNewBuffer: " << lf->path << ": new buffer");
+
+ b = static_cast<logfile_buffer_t*>(xcalloc(1, sizeof(logfile_buffer_t)));
+ assert(b != NULL);
+ b->buf = static_cast<char*>(xcalloc(1, LOGFILE_BUFSZ));
+ assert(b->buf != NULL);
+ b->size = LOGFILE_BUFSZ;
+ b->written_len = 0;
+ b->len = 0;
+ dlinkAddTail(b, &b->node, &ll->bufs);
+ ll->nbufs++;
+}
+
+static void
+logfileFreeBuffer(Logfile * lf, logfile_buffer_t * b)
+{
+ l_daemon_t *ll = (l_daemon_t *) lf->data;
+ assert(b != NULL);
+ dlinkDelete(&b->node, &ll->bufs);
+ ll->nbufs--;
+ xfree(b->buf);
+ xfree(b);
+}
+
+static void
+logfileHandleWrite(int fd, void *data)
+{
+ Logfile *lf = (Logfile *) data;
+ l_daemon_t *ll = (l_daemon_t *) lf->data;
+ int ret;
+ logfile_buffer_t *b;
+
+ /*
+ * We'll try writing the first entry until its done - if we
+ * get a partial write then we'll re-schedule until its completed.
+ * Its naive but it'll do for now.
+ */
+ b = static_cast<logfile_buffer_t*>(ll->bufs.head->data);
+ assert(b != NULL);
+ ll->flush_pending = 0;
+
+ ret = FD_WRITE_METHOD(ll->wfd, b->buf + b->written_len, b->len - b->written_len);
+ debugs(50, 3, "logfileHandleWrite: " << lf->path << ": write returned " << ret);
+ if (ret < 0) {
+ if (ignoreErrno(errno)) {
+ /* something temporary */
+ goto reschedule;
+ }
+ debugs(50, DBG_IMPORTANT,"logfileHandleWrite: " << lf->path << ": error writing (" << xstrerror() << ")");
+ /* XXX should handle this better */
+ fatal("I don't handle this error well!");
+ }
+ if (ret == 0) {
+ /* error? */
+ debugs(50, DBG_IMPORTANT, "logfileHandleWrite: " << lf->path << ": wrote 0 bytes?");
+ /* XXX should handle this better */
+ fatal("I don't handle this error well!");
+ }
+ /* ret > 0, so something was written */
+ b->written_len += ret;
+ assert(b->written_len <= b->len);
+ if (b->written_len == b->len) {
+ /* written the whole buffer! */
+ logfileFreeBuffer(lf, b);
+ b = NULL;
+ }
+ /* Is there more to write? */
+ if (ll->bufs.head == NULL) {
+ goto finish;
+ }
+ /* there is, so schedule more */
+
+ reschedule:
+ commSetSelect(ll->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0);
+ ll->flush_pending = 1;
+ finish:
+ return;
+}
+
+static void
+logfileQueueWrite(Logfile * lf)
+{
+ l_daemon_t *ll = (l_daemon_t *) lf->data;
+ if (ll->flush_pending || ll->bufs.head == NULL) {
+ return;
+ }
+ ll->flush_pending = 1;
+ if (ll->bufs.head) {
+ logfile_buffer_t *b = static_cast<logfile_buffer_t*>(ll->bufs.head->data);
+ if (b->len + 2 <= b->size)
+ logfile_mod_daemon_append(lf, "F\n", 2);
+ }
+ /* Ok, schedule a write-event */
+ commSetSelect(ll->wfd, COMM_SELECT_WRITE, logfileHandleWrite, lf, 0);
+}
+
+static void
+logfile_mod_daemon_append(Logfile * lf, const char *buf, int len)
+{
+ l_daemon_t *ll = (l_daemon_t *) lf->data;
+ logfile_buffer_t *b;
+ int s;
+
+ /* Is there a buffer? If not, create one */
+ if (ll->bufs.head == NULL) {
+ logfileNewBuffer(lf);
+ }
+ debugs(50, 3, "logfile_mod_daemon_append: " << lf->path << ": appending " << len << " bytes");
+ /* Copy what can be copied */
+ while (len > 0) {
+ b = static_cast<logfile_buffer_t*>(ll->bufs.tail->data);
+ debugs(50, 3, "logfile_mod_daemon_append: current buffer has " << b->len << " of " << b->size << " bytes before append");
+ s = min(len, (b->size - b->len));
+ xmemcpy(b->buf + b->len, buf, s);
+ len = len - s;
+ buf = buf + s;
+ b->len = b->len + s;
+ assert(b->len <= LOGFILE_BUFSZ);
+ assert(len >= 0);
+ if (len > 0) {
+ logfileNewBuffer(lf);
+ }
+ }
+}
+
+/*
+ * only schedule a flush (write) if one isn't scheduled.
+ */
+static void
+logfileFlushEvent(void *data)
+{
+ Logfile *lf = static_cast<Logfile *>(data);
+
+ /*
+ * This might work better if we keep track of when we wrote last and only
+ * schedule a write if we haven't done so in the last second or two.
+ */
+ logfileQueueWrite(lf);
+ eventAdd("logfileFlush", logfileFlushEvent, lf, 1.0, 1);
+}
+
+
+/* External code */
+
+int
+logfile_mod_daemon_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
+{
+ const char *args[5];
+ char *tmpbuf;
+ l_daemon_t *ll;
+
+ lf->f_close = logfile_mod_daemon_close;
+ lf->f_linewrite = logfile_mod_daemon_writeline;
+ lf->f_linestart = logfile_mod_daemon_linestart;
+ lf->f_lineend = logfile_mod_daemon_lineend;
+ lf->f_flush = logfile_mod_daemon_flush;
+ lf->f_rotate = logfile_mod_daemon_rotate;
+
+ cbdataInternalLock(lf); // WTF?
+ debugs(50, 1, "Logfile Daemon: opening log " << path);
+ ll = static_cast<l_daemon_t*>(xcalloc(1, sizeof(*ll)));
+ lf->data = ll;
+ ll->eol = 1;
+ {
+ IpAddress localhost;
+ args[0] = "(logfile-daemon)";
+ args[1] = path;
+ args[2] = NULL;
+ localhost.SetLocalhost();
+ ll->pid = ipcCreate(IPC_STREAM, Log::TheConfig.logfile_daemon, args, "logfile-daemon", localhost, &ll->rfd, &ll->wfd, NULL);
+ if (ll->pid < 0)
+ fatal("Couldn't start logfile helper");
+ }
+ ll->nbufs = 0;
+
+ /* Queue the initial control data */
+ tmpbuf = static_cast<char*>(xmalloc(BUFSIZ));
+ snprintf(tmpbuf, BUFSIZ, "r%d\nb%d\n", Config.Log.rotateNumber, Config.onoff.buffered_logs);
+ logfile_mod_daemon_append(lf, tmpbuf, strlen(tmpbuf));
+ xfree(tmpbuf);
+
+ /* Start the flush event */
+ eventAdd("logfileFlush", logfileFlushEvent, lf, 1.0, 1);
+
+ return 1;
+}
+
+static void
+logfile_mod_daemon_close(Logfile * lf)
+{
+ l_daemon_t *ll = static_cast<l_daemon_t *>(lf->data);
+ debugs(50, 1, "Logfile Daemon: closing log " << lf->path);
+ logfileFlush(lf);
+ if (ll->rfd == ll->wfd)
+ comm_close(ll->rfd);
+ else {
+ comm_close(ll->rfd);
+ comm_close(ll->wfd);
+ }
+ kill(ll->pid, SIGTERM);
+ eventDelete(logfileFlushEvent, lf);
+ xfree(ll);
+ lf->data = NULL;
+ cbdataInternalUnlock(lf); // WTF??
+}
+
+static void
+logfile_mod_daemon_rotate(Logfile * lf)
+{
+ char tb[3];
+ debugs(50, 1, "logfileRotate: " << lf->path);
+ tb[0] = 'R';
+ tb[1] = '\n';
+ tb[2] = '\0';
+ logfile_mod_daemon_append(lf, tb, 2);
+}
+
+/*
+ * This routine assumes that up to one line is written. Don't try to
+ * call this routine with more than one line or subsequent lines
+ * won't be prefixed with the command type and confuse the logging
+ * daemon somewhat.
+ */
+static void
+logfile_mod_daemon_writeline(Logfile * lf, const char *buf, size_t len)
+{
+ l_daemon_t *ll = static_cast<l_daemon_t *>(lf->data);
+ /* Make sure the logfile buffer isn't too large */
+ if (ll->nbufs > LOGFILE_MAXBUFS) {
+ if (ll->last_warned < squid_curtime - LOGFILE_WARN_TIME) {
+ ll->last_warned = squid_curtime;
+ debugs(50, DBG_IMPORTANT, "Logfile: " << lf->path << ": queue is too large; some log messages have been lost.");
+ }
+ return;
+ }
+ /* Append this data to the end buffer; create a new one if needed */
+ /* Are we eol? If so, prefix with our logfile command byte */
+ logfile_mod_daemon_append(lf, buf, len);
+}
+
+static void
+logfile_mod_daemon_linestart(Logfile * lf)
+{
+ l_daemon_t *ll = static_cast<l_daemon_t *>(lf->data);
+ char tb[2];
+ assert(ll->eol == 1);
+ ll->eol = 0;
+ tb[0] = 'L';
+ tb[1] = '\0';
+ logfile_mod_daemon_append(lf, tb, 1);
+}
+
+static void
+logfile_mod_daemon_lineend(Logfile * lf)
+{
+ l_daemon_t *ll = static_cast<l_daemon_t *>(lf->data);
+ logfile_buffer_t *b;
+ assert(ll->eol == 0);
+ ll->eol = 1;
+ /* Kick a write off if the head buffer is -full- */
+ if (ll->bufs.head != NULL) {
+ b = static_cast<logfile_buffer_t*>(ll->bufs.head->data);
+ if (b->node.next != NULL || !Config.onoff.buffered_logs)
+ logfileQueueWrite(lf);
+ }
+}
+
+static void
+logfile_mod_daemon_flush(Logfile * lf)
+{
+ l_daemon_t *ll = static_cast<l_daemon_t *>(lf->data);
+ if (commUnsetNonBlocking(ll->wfd)) {
+ debugs(50, DBG_IMPORTANT, "Logfile Daemon: Couldn't set the pipe blocking for flush! You're now missing some log entries.");
+ return;
+ }
+ while (ll->bufs.head != NULL) {
+ logfileHandleWrite(ll->wfd, lf);
+ }
+ if (commSetNonBlocking(ll->wfd)) {
+ fatalf("Logfile Daemon: %s: Couldn't set the pipe non-blocking for flush!\n", lf->path);
+ return;
+ }
+}
--- /dev/null
+/*
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Adrian Chadd <adrian@squid-cache.org>
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+#ifndef _SQUID_SRC_LOG_MODDAEMON_H
+#define _SQUID_SRC_LOG_MODDAEMON_H
+
+#include "config.h"
+
+class Logfile;
+
+extern int logfile_mod_daemon_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag);
+
+#endif /* _SQUID_SRC_LOG_MODDAEMON_H */
--- /dev/null
+/*
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+#include "fde.h"
+#include "log/File.h"
+#include "log/ModStdio.h"
+
+typedef struct {
+ int fd;
+ char *buf;
+ size_t bufsz;
+ int offset;
+} l_stdio_t;
+
+/*
+ * Aborts with fatal message if write() returns something other
+ * than its length argument.
+ */
+static void
+logfileWriteWrapper(Logfile * lf, const void *buf, size_t len)
+{
+ l_stdio_t *ll = (l_stdio_t *) lf->data;
+ size_t s;
+ s = FD_WRITE_METHOD(ll->fd, (char const *) buf, len);
+ fd_bytes(ll->fd, s, FD_WRITE);
+
+ if (s == len)
+ return;
+
+ if (!lf->flags.fatal)
+ return;
+
+ fatalf("logfileWrite (stdio): %s: %s\n", lf->path, xstrerror());
+}
+
+static void
+logfile_mod_stdio_writeline(Logfile * lf, const char *buf, size_t len)
+{
+ l_stdio_t *ll = (l_stdio_t *) lf->data;
+
+ if (0 == ll->bufsz) {
+ /* buffering disabled */
+ logfileWriteWrapper(lf, buf, len);
+ return;
+ }
+ if (ll->offset > 0 && (ll->offset + len) > ll->bufsz)
+ logfileFlush(lf);
+
+ if (len > ll->bufsz) {
+ /* too big to fit in buffer */
+ logfileWriteWrapper(lf, buf, len);
+ return;
+ }
+ /* buffer it */
+ xmemcpy(ll->buf + ll->offset, buf, len);
+
+ ll->offset += len;
+
+ assert(ll->offset >= 0);
+
+ assert((size_t) ll->offset <= ll->bufsz);
+}
+
+static void
+logfile_mod_stdio_linestart(Logfile * lf)
+{
+}
+
+static void
+logfile_mod_stdio_lineend(Logfile * lf)
+{
+ lf->f_flush(lf);
+}
+
+static void
+logfile_mod_stdio_flush(Logfile * lf)
+{
+ l_stdio_t *ll = (l_stdio_t *) lf->data;
+ if (0 == ll->offset)
+ return;
+ logfileWriteWrapper(lf, ll->buf, (size_t) ll->offset);
+ ll->offset = 0;
+}
+
+static void
+logfile_mod_stdio_rotate(Logfile * lf)
+{
+#ifdef S_ISREG
+
+ struct stat sb;
+#endif
+
+ int i;
+ char from[MAXPATHLEN];
+ char to[MAXPATHLEN];
+ l_stdio_t *ll = (l_stdio_t *) lf->data;
+ assert(lf->path);
+
+#ifdef S_ISREG
+
+ if (stat(lf->path, &sb) == 0)
+ if (S_ISREG(sb.st_mode) == 0)
+ return;
+
+#endif
+
+ debugs(0, DBG_IMPORTANT, "logfileRotate (stdio): " << lf->path);
+
+ /* Rotate numbers 0 through N up one */
+ for (i = Config.Log.rotateNumber; i > 1;) {
+ i--;
+ snprintf(from, MAXPATHLEN, "%s.%d", lf->path, i - 1);
+ snprintf(to, MAXPATHLEN, "%s.%d", lf->path, i);
+ xrename(from, to);
+ }
+
+ /* Rotate the current log to .0 */
+ logfileFlush(lf);
+
+ file_close(ll->fd); /* always close */
+
+ if (Config.Log.rotateNumber > 0) {
+ snprintf(to, MAXPATHLEN, "%s.%d", lf->path, 0);
+ xrename(lf->path, to);
+ }
+ /* Reopen the log. It may have been renamed "manually" */
+ ll->fd = file_open(lf->path, O_WRONLY | O_CREAT | O_TEXT);
+
+ if (DISK_ERROR == ll->fd && lf->flags.fatal) {
+ debugs(50, DBG_CRITICAL, "logfileRotate (stdio): " << lf->path << ": " << xstrerror());
+ fatalf("Cannot open %s: %s", lf->path, xstrerror());
+ }
+}
+
+static void
+logfile_mod_stdio_close(Logfile * lf)
+{
+ l_stdio_t *ll = (l_stdio_t *) lf->data;
+ lf->f_flush(lf);
+
+ if (ll->fd >= 0)
+ file_close(ll->fd);
+
+ if (ll->buf)
+ xfree(ll->buf);
+
+ xfree(lf->data);
+ lf->data = NULL;
+}
+
+/*
+ * This code expects the path to be a writable filename
+ */
+int
+logfile_mod_stdio_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
+{
+ lf->f_close = logfile_mod_stdio_close;
+ lf->f_linewrite = logfile_mod_stdio_writeline;
+ lf->f_linestart = logfile_mod_stdio_linestart;
+ lf->f_lineend = logfile_mod_stdio_lineend;
+ lf->f_flush = logfile_mod_stdio_flush;
+ lf->f_rotate = logfile_mod_stdio_rotate;
+
+ l_stdio_t *ll = static_cast<l_stdio_t*>(xcalloc(1, sizeof(*ll)));
+ lf->data = ll;
+
+ ll->fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT);
+
+ if (DISK_ERROR == ll->fd) {
+ if (ENOENT == errno && fatal_flag) {
+ fatalf("Cannot open '%s' because\n"
+ "\tthe parent directory does not exist.\n"
+ "\tPlease create the directory.\n", path);
+ } else if (EACCES == errno && fatal_flag) {
+ fatalf("Cannot open '%s' for writing.\n"
+ "\tThe parent directory must be writeable by the\n"
+ "\tuser '%s', which is the cache_effective_user\n"
+ "\tset in squid.conf.", path, Config.effectiveUser);
+ } else {
+ debugs(50, DBG_IMPORTANT, "logfileOpen (stdio): " << path << ": " << xstrerror());
+ return 0;
+ }
+ }
+ if (bufsz > 0) {
+ ll->buf = static_cast<char*>(xmalloc(bufsz));
+ ll->bufsz = bufsz;
+ }
+ return 1;
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+#ifndef _SQUID_SRC_LOG_MODSTDIO_H
+#define _SQUID_SRC_LOG_MODSTDIO_H
+
+#include "config.h"
+
+class Logfile;
+
+extern int logfile_mod_stdio_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag);
+
+#endif /* _SQUID_SRC_LOG_MODSTDIO_H */
--- /dev/null
+/*
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+
+#if HAVE_SYSLOG
+
+#include "log/File.h"
+#include "log/ModSyslog.h"
+
+/* Define LOG_AUTHPRIV as LOG_AUTH on systems still using the old deprecated LOG_AUTH */
+#if !defined(LOG_AUTHPRIV) && defined(LOG_AUTH)
+#define LOG_AUTHPRIV LOG_AUTH
+#endif
+
+typedef struct {
+ const char *name;
+ int value;
+} syslog_symbol_t;
+
+static int
+syslog_ntoa(const char *s)
+{
+#define syslog_symbol(a) #a, a
+ static syslog_symbol_t symbols[] =
+ {
+#ifdef LOG_AUTHPRIV
+ {syslog_symbol(LOG_AUTHPRIV)},
+#endif
+#ifdef LOG_DAEMON
+ {syslog_symbol(LOG_DAEMON)},
+#endif
+#ifdef LOG_LOCAL0
+ {syslog_symbol(LOG_LOCAL0)},
+#endif
+#ifdef LOG_LOCAL1
+ {syslog_symbol(LOG_LOCAL1)},
+#endif
+#ifdef LOG_LOCAL2
+ {syslog_symbol(LOG_LOCAL2)},
+#endif
+#ifdef LOG_LOCAL3
+ {syslog_symbol(LOG_LOCAL3)},
+#endif
+#ifdef LOG_LOCAL4
+ {syslog_symbol(LOG_LOCAL4)},
+#endif
+#ifdef LOG_LOCAL5
+ {syslog_symbol(LOG_LOCAL5)},
+#endif
+#ifdef LOG_LOCAL6
+ {syslog_symbol(LOG_LOCAL6)},
+#endif
+#ifdef LOG_LOCAL7
+ {syslog_symbol(LOG_LOCAL7)},
+#endif
+#ifdef LOG_USER
+ {syslog_symbol(LOG_USER)},
+#endif
+#ifdef LOG_ERR
+ {syslog_symbol(LOG_ERR)},
+#endif
+#ifdef LOG_WARNING
+ {syslog_symbol(LOG_WARNING)},
+#endif
+#ifdef LOG_NOTICE
+ {syslog_symbol(LOG_NOTICE)},
+#endif
+#ifdef LOG_INFO
+ {syslog_symbol(LOG_INFO)},
+#endif
+#ifdef LOG_DEBUG
+ {syslog_symbol(LOG_DEBUG)},
+#endif
+ {NULL, 0}
+ };
+ syslog_symbol_t *p;
+
+ for (p = symbols; p->name != NULL; ++p)
+ if (!strcmp(s, p->name) || !strcasecmp(s, p->name + 4))
+ return p->value;
+
+ debugs(1, 1, "Unknown syslog facility/priority '" << s << "'");
+ return 0;
+}
+
+typedef struct {
+ int syslog_priority;
+} l_syslog_t;
+
+#define PRIORITY_MASK (LOG_ERR | LOG_WARNING | LOG_NOTICE | LOG_INFO | LOG_DEBUG)
+
+static void
+logfile_mod_syslog_writeline(Logfile * lf, const char *buf, size_t len)
+{
+ l_syslog_t *ll = (l_syslog_t *) lf->data;
+ syslog(ll->syslog_priority, "%s", (char *) buf);
+}
+
+static void
+logfile_mod_syslog_linestart(Logfile * lf)
+{
+}
+
+static void
+logfile_mod_syslog_lineend(Logfile * lf)
+{
+}
+
+static void
+logfile_mod_syslog_flush(Logfile * lf)
+{
+}
+
+static void
+logfile_mod_syslog_rotate(Logfile * lf)
+{
+}
+
+static void
+logfile_mod_syslog_close(Logfile * lf)
+{
+ xfree(lf->data);
+ lf->data = NULL;
+}
+
+
+
+/*
+ * This code expects the path to be syslog:<priority>
+ */
+int
+logfile_mod_syslog_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
+{
+ lf->f_close = logfile_mod_syslog_close;
+ lf->f_linewrite = logfile_mod_syslog_writeline;
+ lf->f_linestart = logfile_mod_syslog_linestart;
+ lf->f_lineend = logfile_mod_syslog_lineend;
+ lf->f_flush = logfile_mod_syslog_flush;
+ lf->f_rotate = logfile_mod_syslog_rotate;
+
+ l_syslog_t *ll = static_cast<l_syslog_t*>(xcalloc(1, sizeof(*ll)));
+ lf->data = ll;
+
+ ll->syslog_priority = LOG_INFO;
+
+ if (path[6] != '\0') {
+ char *priority = xstrdup(path);
+ char *facility = (char *) strchr(priority, '.');
+ if (!facility)
+ facility = (char *) strchr(priority, '|');
+ if (facility) {
+ *facility++ = '\0';
+ ll->syslog_priority |= syslog_ntoa(facility);
+ }
+ ll->syslog_priority |= syslog_ntoa(priority);
+ xfree(priority);
+ if ((ll->syslog_priority & PRIORITY_MASK) == 0)
+ ll->syslog_priority |= LOG_INFO;
+ }
+
+ return 1;
+}
+#endif
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Duane Wessels
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+#ifndef _SQUID_SRC_LOG_MODSYSLOG_H
+#define _SQUID_SRC_LOG_MODSYSLOG_H
+
+#include "config.h"
+
+class Logfile;
+
+extern int logfile_mod_syslog_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag);
+
+#endif /* _SQUID_SRC_LOG_MODSYSLOG_H */
--- /dev/null
+/*
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Adrian Chadd
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+
+#include "squid.h"
+#include "comm.h"
+#include "log/File.h"
+#include "log/ModUdp.h"
+#include "Parsing.h"
+
+/*
+ * This logfile UDP module is mostly inspired by a patch by Tim Starling
+ * from Wikimedia.
+ *
+ * It doesn't do any UDP buffering - it'd be quite a bit of work for
+ * something which the kernel could be doing for you!
+ */
+
+typedef struct {
+ int fd;
+ char *buf;
+ size_t bufsz;
+ int offset;
+} l_udp_t;
+
+static void
+logfile_mod_udp_write(Logfile * lf, const char *buf, size_t len)
+{
+ l_udp_t *ll = (l_udp_t *) lf->data;
+ ssize_t s;
+ s = write(ll->fd, (char const *) buf, len);
+ fd_bytes(ll->fd, s, FD_WRITE);
+#if 0
+ if (s < 0) {
+ debugs(1, 1, "logfile (udp): got errno (" << errno << "):" << xstrerror());
+ }
+ if (s != len) {
+ debugs(1, 1, "logfile (udp): len=" << len << ", wrote=" << s);
+ }
+#endif
+
+ /* We don't worry about network errors for now */
+}
+
+static void
+logfile_mod_udp_flush(Logfile * lf)
+{
+ l_udp_t *ll = (l_udp_t *) lf->data;
+ if (0 == ll->offset)
+ return;
+ logfile_mod_udp_write(lf, ll->buf, (size_t) ll->offset);
+ ll->offset = 0;
+}
+
+static void
+logfile_mod_udp_writeline(Logfile * lf, const char *buf, size_t len)
+{
+ l_udp_t *ll = (l_udp_t *) lf->data;
+
+ if (0 == ll->bufsz) {
+ /* buffering disabled */
+ logfile_mod_udp_write(lf, buf, len);
+ return;
+ }
+ if (ll->offset > 0 && (ll->offset + len + 4) > ll->bufsz)
+ logfile_mod_udp_flush(lf);
+
+ if (len > ll->bufsz) {
+ /* too big to fit in buffer */
+ logfile_mod_udp_write(lf, buf, len);
+ return;
+ }
+ /* buffer it */
+ xmemcpy(ll->buf + ll->offset, buf, len);
+
+ ll->offset += len;
+
+ assert(ll->offset >= 0);
+
+ assert((size_t) ll->offset <= ll->bufsz);
+}
+
+static void
+logfile_mod_udp_linestart(Logfile * lf)
+{
+}
+
+static void
+logfile_mod_udp_lineend(Logfile * lf)
+{
+}
+
+static void
+logfile_mod_udp_rotate(Logfile * lf)
+{
+ return;
+}
+
+static void
+logfile_mod_udp_close(Logfile * lf)
+{
+ l_udp_t *ll = (l_udp_t *) lf->data;
+ lf->f_flush(lf);
+
+ if (ll->fd >= 0)
+ file_close(ll->fd);
+
+ if (ll->buf)
+ xfree(ll->buf);
+
+ xfree(lf->data);
+ lf->data = NULL;
+}
+
+
+
+/*
+ * This code expects the path to be //host:port
+ */
+int
+logfile_mod_udp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag)
+{
+ IpAddress addr;
+ char *strAddr;
+
+ lf->f_close = logfile_mod_udp_close;
+ lf->f_linewrite = logfile_mod_udp_writeline;
+ lf->f_linestart = logfile_mod_udp_linestart;
+ lf->f_lineend = logfile_mod_udp_lineend;
+ lf->f_flush = logfile_mod_udp_flush;
+ lf->f_rotate = logfile_mod_udp_rotate;
+
+ l_udp_t *ll = static_cast<l_udp_t*>(xcalloc(1, sizeof(*ll)));
+ lf->data = ll;
+
+ if (strncmp(path, "//", 2) == 0) {
+ path += 2;
+ }
+ strAddr = xstrdup(path);
+ if (!GetHostWithPort(strAddr, &addr)) {
+ if (lf->flags.fatal) {
+ fatalf("Invalid UDP logging address '%s'\n", lf->path);
+ } else {
+ debugs(50, DBG_IMPORTANT, "Invalid UDP logging address '" << lf->path << "'");
+ safe_free(strAddr);
+ return FALSE;
+ }
+ }
+ safe_free(strAddr);
+
+ IpAddress no_addr;
+ no_addr.SetNoAddr();
+
+#if USE_IPV6
+ // require the sending UDP port to be of the right family for the destination address.
+ if (addr.IsIPv4())
+ no_addr.SetIPv4();
+#endif
+
+ ll->fd = comm_open(SOCK_DGRAM, IPPROTO_UDP, no_addr, COMM_NONBLOCKING, "UDP log socket");
+ if (ll->fd < 0) {
+ if (lf->flags.fatal) {
+ fatalf("Unable to open UDP socket for logging\n");
+ } else {
+ debugs(50, DBG_IMPORTANT, "Unable to open UDP socket for logging");
+ return FALSE;
+ }
+ }
+ else if (comm_connect_addr(ll->fd, &addr)) {
+ if (lf->flags.fatal) {
+ fatalf("Unable to connect to %s for UDP log: %s\n", lf->path, xstrerror());
+ } else {
+ debugs(50, DBG_IMPORTANT, "Unable to connect to " << lf->path << " for UDP log: " << xstrerror());
+ return FALSE;
+ }
+ }
+ if (ll->fd == -1) {
+ if (ENOENT == errno && fatal_flag) {
+ fatalf("Cannot open '%s' because\n"
+ "\tthe parent directory does not exist.\n"
+ "\tPlease create the directory.\n", path);
+ } else if (EACCES == errno && fatal_flag) {
+ fatalf("Cannot open '%s' for writing.\n"
+ "\tThe parent directory must be writeable by the\n"
+ "\tuser '%s', which is the cache_effective_user\n"
+ "\tset in squid.conf.", path, Config.effectiveUser);
+ } else {
+ debugs(50, DBG_IMPORTANT, "logfileOpen (UDP): " << lf->path << ": " << xstrerror());
+ return 0;
+ }
+ }
+ /* Force buffer size to something roughly fitting inside an MTU */
+ /*
+ * XXX note the receive side needs to receive the whole packet at once;
+ * applications like netcat have a small default receive buffer and will
+ * truncate!
+ */
+ bufsz = 1400;
+ if (bufsz > 0) {
+ ll->buf = static_cast<char*>(xmalloc(bufsz));
+ ll->bufsz = bufsz;
+ }
+
+ return 1;
+}
--- /dev/null
+/*
+ * $Id$
+ *
+ * DEBUG: section 50 Log file handling
+ * AUTHOR: Adrian Chadd
+ *
+ * SQUID Web Proxy Cache http://www.squid-cache.org/
+ * ----------------------------------------------------------
+ *
+ * Squid is the result of efforts by numerous individuals from
+ * the Internet community; see the CONTRIBUTORS file for full
+ * details. Many organizations have provided support for Squid's
+ * development; see the SPONSORS file for full details. Squid is
+ * Copyrighted (C) 2001 by the Regents of the University of
+ * California; see the COPYRIGHT file for full details. Squid
+ * incorporates software developed and/or copyrighted by other
+ * sources; see the CREDITS file for full details.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
+ *
+ */
+#ifndef _SQUID_SRC_LOG_MODUDP_H
+#define _SQUID_SRC_LOG_MODSYSLOG_H
+
+#include "config.h"
+
+class Logfile;
+
+extern int logfile_mod_udp_open(Logfile * lf, const char *path, size_t bufsz, int fatal_flag);
+
+#endif /* _SQUID_SRC_LOG_MODSYSLOG_H */
#include "hier_code.h"
#include "HttpReply.h"
#include "HttpRequest.h"
+#include "log/File.h"
#include "MemBuf.h"
#include "rfc1738.h"
#include "SquidTime.h"
if (checklist && log->aclList && !checklist->matchAclListFast(log->aclList))
continue;
- switch (log->type) {
-
- case CLF_AUTO:
-
- if (Config.onoff.common_log)
- accessLogCommon(al, log->logfile);
- else
- accessLogSquid(al, log->logfile);
-
- break;
+ if (log->logfile) {
+ logfileLineStart(log->logfile);
- case CLF_SQUID:
- accessLogSquid(al, log->logfile);
+ switch (log->type) {
- break;
-
- case CLF_COMMON:
- accessLogCommon(al, log->logfile);
+ case CLF_AUTO:
+ if (Config.onoff.common_log)
+ accessLogCommon(al, log->logfile);
+ else
+ accessLogSquid(al, log->logfile);
+ break;
- break;
+ case CLF_SQUID:
+ accessLogSquid(al, log->logfile);
+ break;
- case CLF_CUSTOM:
- accessLogCustom(al, log);
+ case CLF_COMMON:
+ accessLogCommon(al, log->logfile);
+ break;
- break;
+ case CLF_CUSTOM:
+ accessLogCustom(al, log);
+ break;
#if ICAP_CLIENT
- case CLF_ICAP_SQUID:
- accessLogICAPSquid(al, log->logfile);
-
- break;
+ case CLF_ICAP_SQUID:
+ accessLogICAPSquid(al, log->logfile);
+ break;
#endif
- case CLF_NONE:
- goto last;
+ case CLF_NONE:
+ return; // abort!
- default:
- fatalf("Unknown log format %d\n", log->type);
+ default:
+ fatalf("Unknown log format %d\n", log->type);
+ break;
+ }
- break;
+ logfileLineEnd(log->logfile);
}
- logfileFlush(log->logfile);
-
+ // NP: WTF? if _any_ log line has no checklist ignore the following ones?
if (!checklist)
break;
}
-
-last:
- (void)0; /* NULL statement for label */
}
void
if (log->type == CLF_NONE)
continue;
- log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1);
+ log->logfile = logfileOpen(log->filename, MAX_URL << 2, 1);
LogfileStatus = LOG_ENABLE;
S = (unsigned short) HTTP_STATUS_NONE;
logfileWrite(headerslog, &magic, sizeof(magic));
-
logfileWrite(headerslog, &M, sizeof(M));
-
logfileWrite(headerslog, &S, sizeof(S));
-
logfileWrite(headerslog, hmask, sizeof(HttpHeaderMask));
-
logfileWrite(headerslog, &ccmask, sizeof(int));
-
- logfileFlush(headerslog);
}
#endif
+++ /dev/null
-/*
- * $Id$
- *
- * DEBUG: section 50 Log file handling
- * AUTHOR: Duane Wessels
- *
- * SQUID Web Proxy Cache http://www.squid-cache.org/
- * ----------------------------------------------------------
- *
- * Squid is the result of efforts by numerous individuals from
- * the Internet community; see the CONTRIBUTORS file for full
- * details. Many organizations have provided support for Squid's
- * development; see the SPONSORS file for full details. Squid is
- * Copyrighted (C) 2001 by the Regents of the University of
- * California; see the COPYRIGHT file for full details. Squid
- * incorporates software developed and/or copyrighted by other
- * sources; see the CREDITS file for full details.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111, USA.
- *
- */
-
-#include "squid.h"
-#include "fde.h"
-
-static void logfileWriteWrapper(Logfile * lf, const void *buf, size_t len);
-
-#if HAVE_SYSLOG
-
-/* Define LOG_AUTHPRIV as LOG_AUTH on systems still using the old deprecated LOG_AUTH */
-#if !defined(LOG_AUTHPRIV) && defined(LOG_AUTH)
-#define LOG_AUTHPRIV LOG_AUTH
-#endif
-
-struct syslog_symbol_t {
- const char* name;
- int value;
-};
-
-static int syslog_ntoa (const char* s)
-{
-#define syslog_symbol(a) #a, a
- static syslog_symbol_t _symbols[] = {
- { syslog_symbol(LOG_AUTHPRIV) },
- { syslog_symbol(LOG_DAEMON) },
- { syslog_symbol(LOG_LOCAL0) },
- { syslog_symbol(LOG_LOCAL1) },
- { syslog_symbol(LOG_LOCAL2) },
- { syslog_symbol(LOG_LOCAL3) },
- { syslog_symbol(LOG_LOCAL4) },
- { syslog_symbol(LOG_LOCAL5) },
- { syslog_symbol(LOG_LOCAL6) },
- { syslog_symbol(LOG_LOCAL7) },
- { syslog_symbol(LOG_USER) },
- { syslog_symbol(LOG_ERR) },
- { syslog_symbol(LOG_WARNING) },
- { syslog_symbol(LOG_NOTICE) },
- { syslog_symbol(LOG_INFO) },
- { syslog_symbol(LOG_DEBUG) },
- { NULL, 0 }
- };
-
- for (syslog_symbol_t* p = _symbols; p->name != NULL; ++p)
- if (!strcmp(s, p->name) || !strcasecmp(s, p->name+4))
- return p->value;
-
- debugs(1, 1, "Unknown syslog facility/priority '" << s << "'");
-
- return 0;
-}
-
-#define PRIORITY_MASK (LOG_ERR | LOG_WARNING | LOG_NOTICE | LOG_INFO | LOG_DEBUG)
-#endif
-Logfile *
-logfileOpen(const char *path, size_t bufsz, int fatal_flag)
-{
- int fd;
- Logfile *lf = static_cast<Logfile *>(xcalloc(1, sizeof(*lf)));
-
- xstrncpy(lf->path, path, MAXPATHLEN);
-
-#if HAVE_SYSLOG
-
- if (strncmp(path, "syslog", 6) == 0) {
- lf->flags.syslog = 1;
- lf->syslog_priority = LOG_INFO;
- lf->fd = -1;
-
- if (path[6] != '\0') {
- path += 7;
- char *priority = xstrdup(path);
- char *facility = (char *) strchr(priority, '.');
- if (!facility)
- facility = (char *) strchr(priority, '|');
- if (facility) {
- *facility++ = '\0';
- lf->syslog_priority |= syslog_ntoa(facility);
- }
- lf->syslog_priority |= syslog_ntoa(priority);
- xfree(priority);
- if (0 == (lf->syslog_priority & PRIORITY_MASK))
- lf->syslog_priority |= LOG_INFO;
- }
- } else
-#endif
- {
- fd = file_open(path, O_WRONLY | O_CREAT | O_TEXT);
-
- if (DISK_ERROR == fd) {
- if (ENOENT == errno && fatal_flag) {
- fatalf("Cannot open '%s' because\n"
- "\tthe parent directory does not exist.\n"
- "\tPlease create the directory.\n", path);
- } else if (EACCES == errno && fatal_flag) {
- fatalf("Cannot open '%s' for writing.\n"
- "\tThe parent directory must be writeable by the\n"
- "\tuser '%s', which is the cache_effective_user\n"
- "\tset in squid.conf.", path, Config.effectiveUser);
- } else {
- debugs(50, 1, "logfileOpen: " << path << ": " << xstrerror());
- return NULL;
- }
- }
-
- lf->fd = fd;
-
- if (bufsz > 0) {
- lf->buf = (char *) xmalloc(bufsz);
- lf->bufsz = bufsz;
- }
- }
-
- if (fatal_flag)
- lf->flags.fatal = 1;
-
- lf->sequence_number = 0;
-
- return lf;
-}
-
-void
-logfileClose(Logfile * lf)
-{
- logfileFlush(lf);
-
- if (lf->fd >= 0)
- file_close(lf->fd);
-
- if (lf->buf)
- xfree(lf->buf);
-
- xfree(lf);
-}
-
-void
-logfileRotate(Logfile * lf)
-{
-#ifdef S_ISREG
-
- struct stat sb;
-#endif
-
- int i;
- char from[MAXPATHLEN];
- char to[MAXPATHLEN];
- assert(lf->path);
-
- if (lf->flags.syslog)
- return;
-
-#ifdef S_ISREG
-
- if (stat(lf->path, &sb) == 0)
- if (S_ISREG(sb.st_mode) == 0)
- return;
-
-#endif
-
- debugs(0, 1, "logfileRotate: " << lf->path);
-
- /* Rotate numbers 0 through N up one */
- for (i = Config.Log.rotateNumber; i > 1;) {
- i--;
- snprintf(from, MAXPATHLEN, "%s.%d", lf->path, i - 1);
- snprintf(to, MAXPATHLEN, "%s.%d", lf->path, i);
- xrename(from, to);
- }
-
- /* Rotate the current log to .0 */
- logfileFlush(lf);
-
- file_close(lf->fd); /* always close */
-
- if (Config.Log.rotateNumber > 0) {
- snprintf(to, MAXPATHLEN, "%s.%d", lf->path, 0);
- xrename(lf->path, to);
- }
-
- /* Reopen the log. It may have been renamed "manually" */
- lf->fd = file_open(lf->path, O_WRONLY | O_CREAT | O_TEXT);
-
- if (DISK_ERROR == lf->fd && lf->flags.fatal) {
- debugs(50, 1, "logfileRotate: " << lf->path << ": " << xstrerror());
- fatalf("Cannot open %s: %s", lf->path, xstrerror());
- }
-}
-
-void
-logfileWrite(Logfile * lf, void *buf, size_t len)
-{
- /* AYJ: this write gets called once per line? Squid-2 did it in lineEnd which we dont have. */
- lf->sequence_number++;
-
-#if HAVE_SYSLOG
-
- if (lf->flags.syslog) {
- syslog(lf->syslog_priority, "%s", (char *)buf);
- return;
- }
-
-#endif
-
- if (0 == lf->bufsz) {
- /* buffering disabled */
- logfileWriteWrapper(lf, buf, len);
- return;
- }
-
- if (lf->offset > 0 && lf->offset + len > lf->bufsz)
- logfileFlush(lf);
-
- if (len > lf->bufsz) {
- /* too big to fit in buffer */
- logfileWriteWrapper(lf, buf, len);
- return;
- }
-
- /* buffer it */
- xmemcpy(lf->buf + lf->offset, buf, len);
-
- lf->offset += len;
-
- assert (lf->offset >= 0);
-
- assert((size_t)lf->offset <= lf->bufsz);
-}
-
-void
-logfilePrintf(Logfile * lf, const char *fmt,...)
-{
- va_list args;
- char buf[8192];
- int s;
-
- va_start(args, fmt);
-
- s = vsnprintf(buf, 8192, fmt, args);
-
- if (s > 8192) {
- s = 8192;
-
- if (fmt[strlen(fmt) - 1] == '\n')
- buf[8191] = '\n';
- }
-
- logfileWrite(lf, buf, (size_t) s);
- va_end(args);
-}
-
-void
-logfileFlush(Logfile * lf)
-{
- if (0 == lf->offset)
- return;
-
- logfileWriteWrapper(lf, lf->buf, (size_t) lf->offset);
-
- lf->offset = 0;
-}
-
-/*
- * Aborts with fatal message if write() returns something other
- * than its length argument.
- */
-static void
-logfileWriteWrapper(Logfile * lf, const void *buf, size_t len)
-{
- size_t s;
- s = FD_WRITE_METHOD(lf->fd, (char const *)buf, len);
- fd_bytes(lf->fd, s, FD_WRITE);
-
- if (s == len)
- return;
-
- if (!lf->flags.fatal)
- return;
-
- fatalf("logfileWrite: %s: %s\n", lf->path, xstrerror());
-}
extern void clientAccessCheck(void *);
#include "Debug.h"
+
/* see debug.c for info on context-based debugging */
SQUIDCEXTERN Ctx ctx_enter(const char *descr);
SQUIDCEXTERN void ctx_exit(Ctx ctx);
SQUIDCEXTERN void *leakFreeFL(void *, const char *, int);
#endif
-/* logfile.c */
-SQUIDCEXTERN Logfile *logfileOpen(const char *path, size_t bufsz, int);
-SQUIDCEXTERN void logfileClose(Logfile * lf);
-SQUIDCEXTERN void logfileRotate(Logfile * lf);
-SQUIDCEXTERN void logfileWrite(Logfile * lf, void *buf, size_t len);
-SQUIDCEXTERN void logfileFlush(Logfile * lf);
-SQUIDCEXTERN void logfilePrintf(Logfile * lf, const char *fmt,...) PRINTF_FORMAT_ARG2;
-
/*
* prototypes for system functions missing from system includes
*/
*/
#include "squid.h"
-
+#include "log/File.h"
#include "SquidTime.h"
#if USE_REFERER_LOG
#define SQUIDHOSTNAMELEN 256
#endif
-#define SQUID_MAXPATHLEN 256
#ifndef MAXPATHLEN
#define MAXPATHLEN SQUID_MAXPATHLEN
#endif
+
#if !HAVE_STRUCT_RUSAGE
/*
* If we don't have getrusage() then we create a fake structure
*/
#include "squid.h"
-#include "Store.h"
-#include "MemObject.h"
-#include "HttpReply.h"
#include "CacheManager.h"
+#include "HttpReply.h"
+#include "log/File.h"
+#include "MemObject.h"
+#include "Store.h"
#include "SquidTime.h"
static const char *storeLogTags[] = {
String ctype=(reply->content_type.size() ? reply->content_type.termedBuf() : str_unknown);
+ logfileLineStart(storelog);
logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s %4d %9d %9d %9d " SQUIDSTRINGPH " %"PRId64"/%"PRId64" %s %s\n",
(int) current_time.tv_sec,
(int) current_time.tv_usec / 1000,
e->contentLen(),
RequestMethodStr(mem->method),
mem->log_url);
+ logfileLineEnd(storelog);
} else {
/* no mem object. Most RELEASE cases */
+ logfileLineStart(storelog);
logfilePrintf(storelog, "%9d.%03d %-7s %02d %08X %s ? ? ? ? ?/? ?/? ? ?\n",
(int) current_time.tv_sec,
(int) current_time.tv_usec / 1000,
e->swap_dirn,
e->swap_filen,
e->getMD5Text());
+ logfileLineEnd(storelog);
}
}
int zero_object_sz;
};
-struct _Logfile {
- int fd;
- char path[MAXPATHLEN];
- char *buf;
- size_t bufsz;
- size_t offset;
-
- struct {
- unsigned int fatal;
- unsigned int syslog;
- } flags;
-
- int syslog_priority;
-
- int64_t sequence_number; ///< Unique sequence number per log line.
-};
-
class logformat_token;
struct _logformat {
logformat *next;
};
+class Logfile;
+
struct _customlog {
char *filename;
ACLList *aclList;
typedef struct _link_list link_list;
-typedef struct _Logfile Logfile;
-
typedef struct _logformat logformat;
typedef struct _customlog customlog;
-
/*
* $Id$
*
*/
#include "squid.h"
+#include "log/File.h"
#include "SquidTime.h"
#if USE_USERAGENT_LOG
DISTCLEANFILES =
LDADD = \
- ../compat/libcompat.la \
- ../src/ip/libip.la \
- -L../lib -lmiscutil \
+ $(top_builddir)/src/time.o \
+ $(top_builddir)/src/ip/libip.la \
+ $(COMPAT_LIB) \
$(XTRA_LIBS)
include $(top_srcdir)/doc/manuals/Substitute.am
+test_tools.cc: $(top_srcdir)/test-suite/test_tools.cc
+ cp $(top_srcdir)/test-suite/test_tools.cc .
+
+# stock tools for unit tests - library independent versions of dlink_list
+# etc.
+# globals.cc is needed by test_tools.cc.
+# Neither of these should be disted from here.
+TESTSOURCES= test_tools.cc
## ##### squidclient #####
bin_PROGRAMS = squidclient
-squidclient_SOURCES = squidclient.cc
+squidclient_SOURCES = squidclient.cc \
+ test_tools.cc
EXTRA_DIST += squidclient.1
man_MANS += squidclient.1
libexec_PROGRAMS = cachemgr$(CGIEXT)
-cachemgr__CGIEXT__SOURCES = cachemgr.cc
+cachemgr__CGIEXT__SOURCES = cachemgr.cc \
+ test_tools.cc
+
cachemgr__CGIEXT__CXXFLAGS = -DDEFAULT_CACHEMGR_CONFIG=\"$(DEFAULT_CACHEMGR_CONFIG)\" $(AM_CXXFLAGS)
EXTRA_DIST += cachemgr.conf cachemgr.cgi.8 cachemgr.cgi.8.in