]> git.ipfire.org Git - thirdparty/squid.git/commitdiff
Author: Adrian Chadd + Tim Starling
authorAmos Jeffries <squid3@treenet.co.nz>
Sun, 22 Nov 2009 20:37:27 +0000 (09:37 +1300)
committerAmos Jeffries <squid3@treenet.co.nz>
Sun, 22 Nov 2009 20:37:27 +0000 (09:37 +1300)
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.

42 files changed:
configure.in
doc/release-notes/release-3.2.sgml
helpers/Makefile.am
helpers/log_daemon/Makefile.am [new file with mode: 0644]
helpers/log_daemon/file/Makefile.am [new file with mode: 0644]
helpers/log_daemon/file/config.test [new file with mode: 0755]
helpers/log_daemon/file/log_file_daemon.cc [new file with mode: 0644]
include/config.h
src/Makefile.am
src/Parsing.cc
src/Parsing.h
src/adaptation/icap/icap_log.cc
src/cache_cf.cc
src/cf.data.pre
src/debug.cc
src/icmp/net_db.cc
src/ip/IpAddress.cc
src/ip/Makefile.am
src/ip/testIpAddress.cc
src/log/Config.cc [new file with mode: 0644]
src/log/Config.h [new file with mode: 0644]
src/log/File.cc [new file with mode: 0644]
src/log/File.h [new file with mode: 0644]
src/log/Makefile.am [new file with mode: 0644]
src/log/ModDaemon.cc [new file with mode: 0644]
src/log/ModDaemon.h [new file with mode: 0644]
src/log/ModStdio.cc [new file with mode: 0644]
src/log/ModStdio.h [new file with mode: 0644]
src/log/ModSyslog.cc [new file with mode: 0644]
src/log/ModSyslog.h [new file with mode: 0644]
src/log/ModUdp.cc [new file with mode: 0644]
src/log/ModUdp.h [new file with mode: 0644]
src/log/access_log.cc [moved from src/access_log.cc with 98% similarity]
src/logfile.cc [deleted file]
src/protos.h
src/referer.cc
src/squid.h
src/store_log.cc
src/structs.h
src/typedefs.h
src/useragent.cc
tools/Makefile.am

index 811a9255f348e0735424a51eb78f4a65e33deab0..441737526cf4cae69b851cf7ee91c01aa866753b 100644 (file)
@@ -1894,6 +1894,47 @@ if test -n "$DIGEST_AUTH_HELPERS"; then
 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
@@ -4240,6 +4281,7 @@ AC_CONFIG_FILES([\
        src/icmp/Makefile \
        src/ident/Makefile \
        src/ip/Makefile \
+       src/log/Makefile \
        contrib/Makefile \
        snmplib/Makefile \
        icons/Makefile \
@@ -4283,6 +4325,8 @@ AC_CONFIG_FILES([\
        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
index 506a581cdc1e9e81ecbff4339036a92e07684576..641b072d0733663cdd5a04ef3c1e59480a266610 100644 (file)
@@ -309,6 +309,9 @@ This section gives a thorough account of those changes in three categories:
        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">
@@ -420,6 +423,9 @@ This section gives an account of those changes in three categories:
        <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>
 
@@ -583,9 +589,6 @@ This section gives an account of those changes in three categories:
        <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
 
@@ -622,9 +625,6 @@ This section gives an account of those changes in three categories:
        <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
 
index 0123cb9dc75f765edc313aeac6f9ba19dc98e1af..aa4675c24f467f1c07a607817e62c86446ab2e62 100644 (file)
@@ -1 +1,8 @@
-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
diff --git a/helpers/log_daemon/Makefile.am b/helpers/log_daemon/Makefile.am
new file mode 100644 (file)
index 0000000..1208bc4
--- /dev/null
@@ -0,0 +1,5 @@
+## Alphabetical list of sub-directories to distribute with Squid:
+DIST_SUBDIRS = \
+       file
+
+SUBDIRS        = $(LOG_DAEMON_HELPERS)
diff --git a/helpers/log_daemon/file/Makefile.am b/helpers/log_daemon/file/Makefile.am
new file mode 100644 (file)
index 0000000..ff893d8
--- /dev/null
@@ -0,0 +1,4 @@
+include $(top_srcdir)/src/Common.am
+
+libexec_PROGRAMS = log_file_daemon
+log_file_daemon_SOURCES = log_file_daemon.cc
diff --git a/helpers/log_daemon/file/config.test b/helpers/log_daemon/file/config.test
new file mode 100755 (executable)
index 0000000..039e4d0
--- /dev/null
@@ -0,0 +1,2 @@
+#!/bin/sh
+exit 0
diff --git a/helpers/log_daemon/file/log_file_daemon.cc b/helpers/log_daemon/file/log_file_daemon.cc
new file mode 100644 (file)
index 0000000..aaa4e48
--- /dev/null
@@ -0,0 +1,154 @@
+#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);
+}
index 76d18fc3bc8a84263bdf76d3cf1953755efb5d98..215a22a05223cfc4f5faf721efa7e2484d28bc6e 100644 (file)
@@ -262,6 +262,8 @@ typedef long mtyp_t;
 #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.
index baa764c31c4f16fd6f341fcff01392921ccb1950..d9e242c7ce64fbaef8c84431a2e25dace1968114 100644 (file)
@@ -34,7 +34,7 @@ LOADABLE_MODULES_SOURCES = \
        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
@@ -258,7 +258,6 @@ libsquid_la_SOURCES = \
 
 squid_SOURCES = \
        $(ACL_REGISTRATION_SOURCES) \
-       access_log.cc \
        AccessLogEntry.h \
        AsyncEngine.cc \
        AsyncEngine.h \
@@ -371,7 +370,6 @@ squid_SOURCES = \
        ipcache.cc \
        $(LEAKFINDERSOURCE) \
        list.cc \
-       logfile.cc \
        lookup_t.h \
        main.cc \
        mem.cc \
@@ -534,6 +532,7 @@ squid_LDADD = \
        $(COMMON_LIBS) \
        eui/libeui.la \
        icmp/libicmp.la icmp/libicmp-core.la \
+       log/liblog.la \
        $(XTRA_OBJS) \
        $(DISK_LINKOBJS) \
        $(REPL_OBJS) \
@@ -577,7 +576,7 @@ INCLUDES += $(KRB5INCS)
 
 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..
@@ -609,6 +608,7 @@ ufsdump_SOURCES = \
        MemBuf.cc \
        MemBuf.cci \
        MemBuf.h \
+       Parsing.h \
        store_key_md5.cc \
        StoreMeta.cc \
        StoreMetaMD5.cc \
@@ -635,7 +635,7 @@ ufsdump_LDADD = \
        $(REGEXLIB) \
        $(SNMPLIB) \
        $(SSLLIB) \
-       -L$(top_builddir)/lib -lmiscutil \
+       $(COMPAT_LIB) \
        $(EPOLL_LIBS) \
        $(MINGW_LIBS) \
        $(XTRA_LIBS)
@@ -656,7 +656,7 @@ sysconf_DATA = \
 data_DATA = \
        mib.txt
 
-LDADD = $(COMMON_LIBS)\
+LDADD = $(COMMON_LIBS) \
        -L../lib \
        -lmiscutil \
        $(EPOLL_LIBS) \
@@ -734,6 +734,7 @@ DEFAULT_NETDB_FILE      = $(DEFAULT_LOG_PREFIX)/netdb.state
 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
@@ -798,6 +799,7 @@ cf.data: cf.data.pre Makefile
        -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" \
@@ -968,20 +970,20 @@ tests_testAuth_SOURCES = \
        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)
 
@@ -1088,7 +1090,6 @@ tests_testCacheManager_SOURCES = \
        tests/testCacheManager.h \
        tests/testMain.cc \
        time.cc \
-       access_log.cc \
        BodyPipe.cc \
        cache_manager.cc \
        cache_cf.cc \
@@ -1144,7 +1145,6 @@ tests_testCacheManager_SOURCES = \
        int.cc \
        internal.cc \
        list.cc \
-       logfile.cc \
        multicast.cc \
        mem_node.cc \
        MemBuf.cc \
@@ -1208,6 +1208,7 @@ nodist_tests_testCacheManager_SOURCES = \
 tests_testCacheManager_LDADD = \
        $(COMMON_LIBS) \
        icmp/libicmp.la icmp/libicmp-core.la \
+       log/liblog.la \
        $(REPL_OBJS) \
        ${ADAPTATION_LIBS} \
        $(ESI_LIBS) \
@@ -1262,7 +1263,6 @@ tests_testEvent_SOURCES = \
        tests/testEvent.h \
        tests/testMain.cc \
        time.cc \
-       access_log.cc \
        BodyPipe.cc \
        cache_manager.cc \
        cache_cf.cc \
@@ -1318,7 +1318,6 @@ tests_testEvent_SOURCES = \
        int.cc \
        internal.cc \
        list.cc \
-       logfile.cc \
        multicast.cc \
        mem_node.cc \
        MemBuf.cc \
@@ -1381,6 +1380,7 @@ nodist_tests_testEvent_SOURCES = \
 tests_testEvent_LDADD = \
        $(COMMON_LIBS) \
        icmp/libicmp.la icmp/libicmp-core.la \
+       log/liblog.la \
        $(REPL_OBJS) \
        ${ADAPTATION_LIBS} \
        $(ESI_LIBS) \
@@ -1411,7 +1411,6 @@ tests_testEventLoop_SOURCES = \
        tests/testEventLoop.h \
        tests/testMain.cc \
        time.cc \
-       access_log.cc \
        BodyPipe.cc \
        cache_manager.cc \
        cache_cf.cc \
@@ -1467,7 +1466,6 @@ tests_testEventLoop_SOURCES = \
        int.cc \
        internal.cc \
        list.cc \
-       logfile.cc \
        multicast.cc \
        mem_node.cc \
        MemBuf.cc \
@@ -1530,6 +1528,7 @@ nodist_tests_testEventLoop_SOURCES = \
 tests_testEventLoop_LDADD = \
        $(COMMON_LIBS) \
        icmp/libicmp.la icmp/libicmp-core.la \
+       log/liblog.la \
        $(REPL_OBJS) \
        ${ADAPTATION_LIBS} \
        $(ESI_LIBS) \
@@ -1548,7 +1547,6 @@ tests_testEventLoop_DEPENDENCIES =  $(top_builddir)/lib/libmiscutil.a \
 
 tests_test_http_range_SOURCES = \
        tests/test_http_range.cc \
-       access_log.cc \
        BodyPipe.cc \
        cache_cf.cc \
        ProtoPort.cc \
@@ -1607,7 +1605,6 @@ tests_test_http_range_SOURCES = \
        $(IPC_SOURCE) \
        ipcache.cc \
        list.cc \
-       logfile.cc \
        mem.cc \
        mem_node.cc \
        MemObject.cc \
@@ -1674,6 +1671,7 @@ nodist_tests_test_http_range_SOURCES = \
 tests_test_http_range_LDADD = \
        $(COMMON_LIBS) \
        icmp/libicmp.la icmp/libicmp-core.la \
+       log/liblog.la \
        $(REPL_OBJS) \
        ${ADAPTATION_LIBS} \
        $(ESI_LIBS) \
@@ -1703,7 +1701,6 @@ tests_testHttpRequest_SOURCES = \
        tests/testHttpRequestMethod.cc \
        tests/testMain.cc \
        time.cc \
-       access_log.cc \
        BodyPipe.cc \
        cache_manager.cc \
        cache_cf.cc \
@@ -1759,7 +1756,6 @@ tests_testHttpRequest_SOURCES = \
        int.cc \
        internal.cc \
        list.cc \
-       logfile.cc \
        multicast.cc \
        mem_node.cc \
        MemBuf.cc \
@@ -1823,6 +1819,7 @@ nodist_tests_testHttpRequest_SOURCES = \
 tests_testHttpRequest_LDADD = \
        $(COMMON_LIBS) \
        icmp/libicmp.la icmp/libicmp-core.la \
+       log/liblog.la \
        $(REPL_OBJS) \
        ${ADAPTATION_LIBS} \
        $(ESI_LIBS) \
@@ -2061,7 +2058,6 @@ tests_testURL_SOURCES = \
        tests/testURLScheme.h \
        tests/testMain.cc \
        time.cc \
-       access_log.cc \
        BodyPipe.cc \
        cache_manager.cc \
        cache_cf.cc \
@@ -2117,7 +2113,6 @@ tests_testURL_SOURCES = \
        int.cc \
        internal.cc \
        list.cc \
-       logfile.cc \
        multicast.cc \
        mem_node.cc \
        MemBuf.cc \
@@ -2178,6 +2173,7 @@ nodist_tests_testURL_SOURCES = \
 tests_testURL_LDADD = \
        $(COMMON_LIBS) \
        icmp/libicmp.la icmp/libicmp-core.la \
+       log/liblog.la \
        $(REGEXLIB) \
        $(REPL_OBJS) \
        ${ADAPTATION_LIBS} \
index 57656174a7a78cc8217b8b29148a0fa0841034de..a20ba9efca1754d89f10a81c2939ef3d3ce33195 100644 (file)
@@ -160,3 +160,55 @@ StringToInt64(const char *s, int64_t &result, const char **p, int base)
 
     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;
+}
index b18dc5e4361845eed985b4e1b60b0d3d630525cb..91f444988e42aad046407eb1025859d728d40986 100644 (file)
@@ -60,4 +60,12 @@ extern u_short GetShort(void);
 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 */
index fc149740e9572ccc3d102a451a2e7eccef11610f..b9f85e60731f54e6be42d52645840b8d5eee9373 100644 (file)
@@ -1,6 +1,7 @@
 #include "squid.h"
 #include "icap_log.h"
 #include "AccessLogEntry.h"
+#include "log/File.h"
 
 int IcapLogfileStatus = LOG_DISABLE;
 
index b943ba14cb5161e4cc1f44cdeb97e6b42e950c39..2ca6c9d498030a0b99b83873d49a0a8b21ada79d 100644 (file)
  */
 
 #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 *);
@@ -527,7 +530,7 @@ configDoConfigure(void)
 
     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);
 
@@ -2855,74 +2858,26 @@ parseNeighborType(const char *s)
 }
 
 #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();
     }
 }
 
index 1d05fb3eee70af7e15e74c36d572eabf1d2112e9..f8a366ec86626b0f9cc2587884e8fac632f1c63c 100644 (file)
@@ -2546,32 +2546,49 @@ NAME: access_log cache_access_log
 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
@@ -2656,6 +2673,15 @@ logformat icap_squid %ts.%03tu %6icap::tr %>a %icap::to/%03icap::Hs %icap::<size
        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
index 8f29b627376258d93243fdabd3c973567745c934..b82ffdd878e55bbdd51f6b5b4159d551e9d2522d 100644 (file)
 /* 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;
index 84c771799ba9d91eadc6202353fefde5d788072c..66f8d3ff04d9a5dcd803c4885e6ab43f557750c4 100644 (file)
@@ -40,6 +40,7 @@
 
 #include "squid.h"
 #include "icmp/net_db.h"
+#include "log/File.h"
 #include "cbdata.h"
 #include "event.h"
 #include "CacheManager.h"
index 482bce937208875ea9a45d44f6d8b9719840b1b0..222cbad05d81b7bfe1f3f5e8d5bc722e67b3f81b 100644 (file)
@@ -35,6 +35,7 @@
  */
 
 #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.
index d8a48540631e8382f38184832e1e27190655c412..fb84c1ab0d72d97d8ae5e0beb2b21b882b2898e3 100644 (file)
@@ -19,7 +19,8 @@ testIpAddress_SOURCES= \
        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) \
index 67c66705488fcb4c7d661b292e26e6396f971693..b86513b5bebcd8739b690acb2e0d579df29ab2b7 100644 (file)
@@ -28,7 +28,7 @@ CPPUNIT_TEST_SUITE_REGISTRATION( testIpAddress );
 struct timeval current_time;
 double current_dtime;
 time_t squid_curtime = 0;
-
+int shutting_down = 0;
 
 void
 testIpAddress::testDefaults()
diff --git a/src/log/Config.cc b/src/log/Config.cc
new file mode 100644 (file)
index 0000000..2360212
--- /dev/null
@@ -0,0 +1,4 @@
+#include "config.h"
+#include "log/Config.h"
+
+Log::LogConfig Log::TheConfig;
diff --git a/src/log/Config.h b/src/log/Config.h
new file mode 100644 (file)
index 0000000..f0266ee
--- /dev/null
@@ -0,0 +1,16 @@
+#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
diff --git a/src/log/File.cc b/src/log/File.cc
new file mode 100644 (file)
index 0000000..9a6ff35
--- /dev/null
@@ -0,0 +1,155 @@
+/*
+ * $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);
+}
diff --git a/src/log/File.h b/src/log/File.h
new file mode 100644 (file)
index 0000000..bb6df08
--- /dev/null
@@ -0,0 +1,57 @@
+#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 */
diff --git a/src/log/Makefile.am b/src/log/Makefile.am
new file mode 100644 (file)
index 0000000..89c872c
--- /dev/null
@@ -0,0 +1,19 @@
+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
diff --git a/src/log/ModDaemon.cc b/src/log/ModDaemon.cc
new file mode 100644 (file)
index 0000000..624804f
--- /dev/null
@@ -0,0 +1,363 @@
+/*
+ * 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;
+    }
+}
diff --git a/src/log/ModDaemon.h b/src/log/ModDaemon.h
new file mode 100644 (file)
index 0000000..1baed9d
--- /dev/null
@@ -0,0 +1,41 @@
+/*
+ * 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 */
diff --git a/src/log/ModStdio.cc b/src/log/ModStdio.cc
new file mode 100644 (file)
index 0000000..9788e6b
--- /dev/null
@@ -0,0 +1,219 @@
+/*
+ * 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;
+}
diff --git a/src/log/ModStdio.h b/src/log/ModStdio.h
new file mode 100644 (file)
index 0000000..5e61ef7
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * $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 */
diff --git a/src/log/ModSyslog.cc b/src/log/ModSyslog.cc
new file mode 100644 (file)
index 0000000..c47126e
--- /dev/null
@@ -0,0 +1,193 @@
+/*
+ * 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
diff --git a/src/log/ModSyslog.h b/src/log/ModSyslog.h
new file mode 100644 (file)
index 0000000..b5bce2d
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * $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 */
diff --git a/src/log/ModUdp.cc b/src/log/ModUdp.cc
new file mode 100644 (file)
index 0000000..343d3b8
--- /dev/null
@@ -0,0 +1,233 @@
+/*
+ * 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;
+}
diff --git a/src/log/ModUdp.h b/src/log/ModUdp.h
new file mode 100644 (file)
index 0000000..1d7ba4a
--- /dev/null
@@ -0,0 +1,43 @@
+/*
+ * $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 */
similarity index 98%
rename from src/access_log.cc
rename to src/log/access_log.cc
index d08280e75a10d49d4dd30493cd9e14f1afbc13b5..042627dd1d3b661f50aa1e6b5c02ff9e71b3e63a 100644 (file)
@@ -48,6 +48,7 @@
 #include "hier_code.h"
 #include "HttpReply.h"
 #include "HttpRequest.h"
+#include "log/File.h"
 #include "MemBuf.h"
 #include "rfc1738.h"
 #include "SquidTime.h"
@@ -1889,56 +1890,51 @@ accessLogLogTo(customlog* log, AccessLogEntry * al, ACLChecklist * checklist)
         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
@@ -2075,7 +2071,7 @@ accessLogInit(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;
 
@@ -2352,16 +2348,10 @@ headersLog(int cs, int pq, const HttpRequestMethod& method, void *data)
         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
diff --git a/src/logfile.cc b/src/logfile.cc
deleted file mode 100644 (file)
index 0c86333..0000000
+++ /dev/null
@@ -1,311 +0,0 @@
-/*
- * $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());
-}
index 4493fa20035b1f94d97de8d4e76d5b3bd2bb6e3d..25149234e652e9b5971070b054c38844e615b7c0 100644 (file)
@@ -98,6 +98,7 @@ SQUIDCEXTERN void httpRequestFree(void *);
 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);
@@ -704,14 +705,6 @@ SQUIDCEXTERN void *leakTouchFL(void *, const char *, int);
 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
  */
index 72b83af0ebff2875b94899f25c8bd116c421071e..7a1eb5d398fc309b97c774e7a7fa8fb13152cbaf 100644 (file)
@@ -34,7 +34,7 @@
  */
 
 #include "squid.h"
-
+#include "log/File.h"
 #include "SquidTime.h"
 
 #if USE_REFERER_LOG
index 308d3598f02e0c05ab3b20fa350a8f565f6ee228..dea358caa50eb2955f424a345d92998ec5256b46 100644 (file)
@@ -205,11 +205,11 @@ using namespace Squid;
 #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
index 3656f539c6106a54a91c8bc0476a8a8ab10cc358..617c57e29e279e97887082aebab2aabf3966e698 100644 (file)
  */
 
 #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[] = {
@@ -83,6 +84,7 @@ storeLog(int tag, const StoreEntry * e)
 
         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,
@@ -99,8 +101,10 @@ storeLog(int tag, const StoreEntry * e)
                       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,
@@ -108,6 +112,7 @@ storeLog(int tag, const StoreEntry * e)
                       e->swap_dirn,
                       e->swap_filen,
                       e->getMD5Text());
+        logfileLineEnd(storelog);
     }
 }
 
index 661236ee8b2c51787e9bc33f5a4fe0b5a58a3102..02cf57ab4feee997a85edd717bac71f0db625681 100644 (file)
@@ -1292,23 +1292,6 @@ struct _store_rebuild_data {
     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 {
@@ -1317,6 +1300,8 @@ struct _logformat {
     logformat *next;
 };
 
+class Logfile;
+
 struct _customlog {
     char *filename;
     ACLList *aclList;
index 9c8fb001a029fcd065a334c23f386ffba021322d..b316c47a42d960849bb184c1a59c76980255c18c 100644 (file)
@@ -170,8 +170,6 @@ typedef struct _Version Version;
 
 typedef struct _link_list link_list;
 
-typedef struct _Logfile Logfile;
-
 typedef struct _logformat logformat;
 
 typedef struct _customlog customlog;
index db839ef42fb5c1bc0e425660f55677b03615ae86..996b7f87000c296352033dceb2b92d32571b0500 100644 (file)
@@ -1,4 +1,3 @@
-
 /*
  * $Id$
  *
@@ -34,6 +33,7 @@
  */
 
 #include "squid.h"
+#include "log/File.h"
 #include "SquidTime.h"
 
 #if USE_USERAGENT_LOG
index 54728d5a95338629a722edd3982a23d92bbde5ec..adf21124aea7b1bec7df9accbff6a558a1d9612e 100644 (file)
@@ -17,19 +17,28 @@ man_MANS =
 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
@@ -42,7 +51,9 @@ DEFAULT_CACHEMGR_CONFIG = $(sysconfdir)/cachemgr.conf
 
 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