This patch is generated from the s26_logfile_daemon branch of HEAD in squid Mon Aug 13 00:18:09 2007 GMT See http://devel.squid-cache.org/ Index: squid/src/Makefile.am diff -u squid/src/Makefile.am:1.51 squid/src/Makefile.am:1.44.2.8 --- squid/src/Makefile.am:1.51 Sun May 20 06:52:24 2007 +++ squid/src/Makefile.am Tue May 22 01:36:05 2007 @@ -44,6 +44,8 @@ UNLINKD = endif +LOGFILED = logfile-daemon + if ENABLE_PINGER PINGER = pinger else @@ -110,7 +112,8 @@ libexec_PROGRAMS = \ $(PINGER) \ $(DNSSERVER) \ - $(UNLINKD) + $(UNLINKD) \ + $(LOGFILED) cf_gen_SOURCES = cf_gen.c defines.h debug.c nodist_cf_gen_SOURCES = globals.c @@ -195,6 +198,12 @@ $(LEAKFINDERSOURCE) \ locrewrite.c \ logfile.c \ + logfile_mod_daemon.c \ + logfile_mod_daemon.h \ + logfile_mod_stdio.c \ + logfile_mod_stdio.h \ + logfile_mod_syslog.c \ + logfile_mod_syslog.h \ main.c \ mem.c \ MemPool.c \ @@ -332,6 +341,7 @@ DEFAULT_PINGER = $(libexecdir)/`echo pinger | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_UNLINKD = $(libexecdir)/`echo unlinkd | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_DISKD = $(libexecdir)/`echo diskd-daemon | sed '$(transform);s/$$/$(EXEEXT)/'` +DEFAULT_LOGFILED = $(libexecdir)/`echo logfile-daemon | sed '$(transform);s/$$/$(EXEEXT)/'` DEFAULT_ICON_DIR = $(datadir)/icons DEFAULT_ERROR_DIR = $(datadir)/errors/@ERR_DEFAULT_LANGUAGE@ DEFAULT_MIB_PATH = $(datadir)/mib.txt @@ -379,6 +389,7 @@ s%@DEFAULT_UNLINKD@%$(DEFAULT_UNLINKD)%g;\ s%@DEFAULT_PINGER@%$(DEFAULT_PINGER)%g;\ s%@DEFAULT_DISKD@%$(DEFAULT_DISKD)%g;\ + s%@DEFAULT_LOGFILED@%$(DEFAULT_LOGFILED)%g;\ s%@DEFAULT_CACHE_LOG@%$(DEFAULT_CACHE_LOG)%g;\ s%@DEFAULT_ACCESS_LOG@%$(DEFAULT_ACCESS_LOG)%g;\ s%@DEFAULT_STORE_LOG@%$(DEFAULT_STORE_LOG)%g;\ Index: squid/src/access_log.c diff -u squid/src/access_log.c:1.40 squid/src/access_log.c:1.28.2.11 --- squid/src/access_log.c:1.40 Thu May 17 13:53:38 2007 +++ squid/src/access_log.c Tue May 22 01:36:05 2007 @@ -1133,29 +1133,32 @@ for (log = Config.Log.accesslogs; log; log = log->next) { if (checklist && log->aclList && aclMatchAclList(log->aclList, checklist) != 1) continue; - switch (log->type) { - case CLF_AUTO: - if (Config.onoff.common_log) - accessLogCommon(al, log->logfile); - else + if (log->logfile) { + logfileLineStart(log->logfile); + switch (log->type) { + case CLF_AUTO: + if (Config.onoff.common_log) + accessLogCommon(al, log->logfile); + else + accessLogSquid(al, log->logfile); + break; + case CLF_SQUID: accessLogSquid(al, log->logfile); - break; - case CLF_SQUID: - accessLogSquid(al, log->logfile); - break; - case CLF_COMMON: - accessLogCommon(al, log->logfile); - break; - case CLF_CUSTOM: - accessLogCustom(al, log); - break; - case CLF_NONE: - goto last; - default: - fatalf("Unknown log format %d\n", log->type); - break; + break; + case CLF_COMMON: + accessLogCommon(al, log->logfile); + break; + case CLF_CUSTOM: + accessLogCustom(al, log); + break; + case CLF_NONE: + goto last; + default: + fatalf("Unknown log format %d\n", log->type); + break; + } + logfileLineEnd(log->logfile); } - logfileFlush(log->logfile); if (!checklist) break; } @@ -1235,7 +1238,7 @@ for (log = Config.Log.accesslogs; log; log = log->next) { if (log->type == CLF_NONE) continue; - log->logfile = logfileOpen(log->filename, MAX_URL << 1, 1); + log->logfile = logfileOpen(log->filename, Config.Log.logtype, MAX_URL << 2, 1); LogfileStatus = LOG_ENABLE; } #if HEADERS_LOG @@ -1454,7 +1457,6 @@ logfileWrite(headerslog, &S, sizeof(S)); logfileWrite(headerslog, hmask, sizeof(HttpHeaderMask)); logfileWrite(headerslog, &ccmask, sizeof(int)); - logfileFlush(headerslog); } #endif Index: squid/src/cache_cf.c diff -u squid/src/cache_cf.c:1.97 squid/src/cache_cf.c:1.81.2.5 --- squid/src/cache_cf.c:1.97 Fri Jul 20 14:52:58 2007 +++ squid/src/cache_cf.c Sat Aug 11 18:12:37 2007 @@ -470,6 +470,7 @@ #if USE_UNLINKD requirePathnameExists("unlinkd_program", Config.Program.unlinkd); #endif + requirePathnameExists("logfile_daemon", Config.Program.logfile_daemon); if (Config.Program.url_rewrite.command) requirePathnameExists("url_rewrite_program", Config.Program.url_rewrite.command->key); if (Config.Program.location_rewrite.command) Index: squid/src/cf.data.pre diff -u squid/src/cf.data.pre:1.190 squid/src/cf.data.pre:1.147.2.8 --- squid/src/cf.data.pre:1.190 Tue Aug 7 05:51:57 2007 +++ squid/src/cf.data.pre Sat Aug 11 18:12:37 2007 @@ -1262,6 +1262,27 @@ NOCOMMENT_END DOC_END +NAME: logtype +TYPE: string +LOC: Config.Log.logtype +DEFAULT: stdio +DOC_START + Usage: + + logtype stdio|daemon|syslog + + Choose the logging method used to write access and store logs, if enabled. +DOC_END + +NAME: logfile_daemon +TYPE: string +DEFAULT: @DEFAULT_LOGFILED@ +LOC: Config.Program.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: cache_log TYPE: string DEFAULT: @DEFAULT_CACHE_LOG@ Index: squid/src/logfile-daemon.c diff -u /dev/null squid/src/logfile-daemon.c:1.1.2.12 --- /dev/null Thu Jan 1 01:00:00 1970 +++ squid/src/logfile-daemon.c Sat Sep 2 07:12:19 2006 @@ -0,0 +1,159 @@ +#include "config.h" + +#if HAVE_STDIO_H +#include +#endif +#if HAVE_STDLIB_H +#include +#endif +#if HAVE_UNISTD_H +#include +#endif +#if HAVE_FCNTL_H +#include +#endif +#if HAVE_ASSERT_H +#include +#endif +#if HAVE_SYS_PARAM_H +#include +#endif +#if HAVE_SYS_STAT_H +#include +#endif +#if HAVE_SIGNAL_H +#include +#endif +#if HAVE_ERRNO_H +#include +#endif +#if HAVE_STRING_H +#include +#endif +#if HAVE_PATHS_H +#include +#endif + +#include "defines.h" + +#define SQUID_MAXPATHLEN 256 +#ifndef MAXPATHLEN +#define MAXPATHLEN SQUID_MAXPATHLEN +#endif + +/* 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\n - logfile data + * R\n - rotate file + * T\n - truncate file + * O\n - repoen file + * F\n - flush file + * r\n - set rotate count to + * b\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 \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: squid/src/logfile.c diff -u squid/src/logfile.c:1.15 squid/src/logfile.c:1.12.2.16 --- squid/src/logfile.c:1.15 Sat Sep 2 07:17:45 2006 +++ squid/src/logfile.c Fri May 18 12:13:12 2007 @@ -34,133 +34,43 @@ #include "squid.h" -static void logfileWriteWrapper(Logfile * lf, const void *buf, size_t len); - +#include "logfile_mod_daemon.h" #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 +#include "logfile_mod_syslog.h" #endif +#include "logfile_mod_stdio.h" -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) || !strcmp(s, p->name + 4)) - return p->value; - return 0; -} - -#define PRIORITY_MASK (LOG_ERR | LOG_WARNING | LOG_NOTICE | LOG_INFO | LOG_DEBUG) -#endif /* HAVE_SYSLOG */ +/* External code */ +CBDATA_TYPE(Logfile); Logfile * -logfileOpen(const char *path, size_t bufsz, int fatal_flag) +logfileOpen(const char *path, const char *type, size_t bufsz, int fatal_flag) { - Logfile *lf = xcalloc(1, sizeof(*lf)); + Logfile *lf; + CBDATA_INIT_TYPE(Logfile); + lf = cbdataAlloc(Logfile); + int ret; + cbdataLock(lf); + debug(50, 1) ("Logfile: opening log %s\n", path); xstrncpy(lf->path, path, MAXPATHLEN); + + /* need to call the per-logfile-type code */ + if (strcmp(type, "stdio") == 0) { + ret = logfile_mod_stdio_open(lf, path, bufsz, fatal_flag); + } else if (strcmp(type, "daemon") == 0) { + ret = logfile_mod_daemon_open(lf, path, bufsz, fatal_flag); #if HAVE_SYSLOG - if (strcmp(path, "syslog") == 0 || strncmp(path, "syslog:", 7) == 0) { - lf->flags.syslog = 1; - lf->fd = -1; - if (path[6] != '\0') { - const char *priority = path + 7; - char *facility = (char *) strchr(priority, '|'); - if (facility) { - *facility++ = '\0'; - lf->syslog_priority |= syslog_ntoa(facility); - } - lf->syslog_priority |= syslog_ntoa(priority); - } - if ((lf->syslog_priority & PRIORITY_MASK) == 0) - lf->syslog_priority |= LOG_INFO; - } else + } else if (strcmp(type, "syslog") == 0) { + ret = logfile_mod_syslog_open(lf, path, bufsz, fatal_flag); #endif - { - int 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 { - debug(50, 1) ("logfileOpen: %s: %s\n", path, xstrerror()); - safe_free(lf); - return NULL; - } - } - lf->fd = fd; - if (bufsz > 0) { - lf->buf = xmalloc(bufsz); - lf->bufsz = bufsz; - } + } else { + fatalf("logfileOpen: unknown logtype '%s'\n", type); + } + if (fatal_flag && ! ret) { + fatalf("logfileOpen: type %s path %s: couldn't open!\n", type, path); } + assert(lf->data != NULL); + if (fatal_flag) lf->flags.fatal = 1; return lf; @@ -169,79 +79,37 @@ void logfileClose(Logfile * lf) { - logfileFlush(lf); - if (lf->fd >= 0) - file_close(lf->fd); - if (lf->buf) - xfree(lf->buf); - xfree(lf); + debug(50, 1) ("Logfile: closing log %s\n", lf->path); + lf->f_flush(lf); + lf->f_close(lf); + cbdataUnlock(lf); + cbdataFree(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 - debug(0, 1) ("logfileRotate: %s\n", 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) { - debug(50, 1) ("logfileRotate: %s: %s\n", lf->path, xstrerror()); - fatalf("Cannot open %s: %s", lf->path, xstrerror()); - } + debug(50, 1) ("logfileRotate: %s\n", lf->path); + lf->f_rotate(lf); } + void -logfileWrite(Logfile * lf, void *buf, size_t len) +logfileWrite(Logfile * lf, char *buf, size_t len) { -#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 <= lf->bufsz); + lf->f_linewrite(lf, buf, len); +} + +void +logfileLineStart(Logfile * lf) +{ + lf->f_linestart(lf); +} + +void +logfileLineEnd(Logfile * lf) +{ + lf->f_lineend(lf); } void @@ -280,25 +148,5 @@ 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) -{ - int s; - s = FD_WRITE_METHOD(lf->fd, 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()); + lf->f_flush(lf); } Index: squid/src/logfile_mod_daemon.c diff -u /dev/null squid/src/logfile_mod_daemon.c:1.1.2.3 --- /dev/null Thu Jan 1 01:00:00 1970 +++ squid/src/logfile_mod_daemon.c Mon May 14 18:38:31 2007 @@ -0,0 +1,354 @@ +/* + * $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 "logfile_mod_daemon.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; + + debug(50, 5) ("logfileNewBuffer: %s: new buffer\n", lf->path); + + b = xcalloc(1, sizeof(logfile_buffer_t)); + assert(b != NULL); + b->buf = 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 = 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); + debug(50, 3) ("logfileHandleWrite: %s: write returned %d\n", lf->path, ret); + if (ret < 0) { + if (ignoreErrno(errno)) { + /* something temporary */ + goto reschedule; + } + debug(50, 1) ("logfileHandleWrite: %s: error writing (%s)\n", lf->path, xstrerror()); + /* XXX should handle this better */ + fatal("I don't handle this error well!"); + } + if (ret == 0) { + /* error? */ + debug(50, 1) ("logfileHandleWrite: %s: wrote 0 bytes?\n", lf->path); + /* 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 = 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); + } + debug(50, 3) ("logfile_mod_daemon_append: %s: appending %d bytes\n", lf->path, len); + /* Copy what can be copied */ + while (len > 0) { + b = ll->bufs.tail->data; + debug(50, 3) ("logfile_mod_daemon_append: current buffer has %d of %d bytes before append\n", b->len, b->size); + s = XMIN(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 = (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; + + cbdataLock(lf); + debug(50, 1) ("Logfile Daemon: opening log %s\n", path); + ll = xcalloc(1, sizeof(*ll)); + lf->data = ll; + ll->eol = 1; + { + args[0] = "(logfile-daemon)"; + args[1] = path; + args[2] = NULL; + ll->pid = ipcCreate(IPC_STREAM, Config.Program.logfile_daemon, args, "logfile-daemon", &ll->rfd, &ll->wfd, NULL); + if (ll->pid < 0) + fatal("Couldn't start logfile helper"); + } + ll->nbufs = 0; + + /* Queue the initial control data */ + tmpbuf = (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); + + 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; + + return 1; +} + +static void +logfile_mod_daemon_close(Logfile * lf) +{ + l_daemon_t *ll = (l_daemon_t *) lf->data; + debug(50, 1) ("Logfile Daemon: closing log %s\n", lf->path); + logfileFlush(lf); + fd_close(ll->rfd); + fd_close(ll->wfd); + kill(ll->pid, SIGTERM); + eventDelete(logfileFlushEvent, lf); + xfree(ll); + lf->data = NULL; + cbdataUnlock(lf); +} + +static void +logfile_mod_daemon_rotate(Logfile * lf) +{ + char tb[3]; + debug(50, 1) ("logfileRotate: %s\n", 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 = (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; + debug(50, 1) ("Logfile: %s: queue is too large; some log messages have been lost.\n", lf->path); + } + 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 = (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 = (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 = 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 = (l_daemon_t *) lf->data; + if (commUnsetNonBlocking(ll->wfd)) { + debug(50, 1) ("Logfile Daemon: Couldn't set the pipe blocking for flush! You're now missing some log entries.\n"); + 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; + } +} Index: squid/src/logfile_mod_daemon.h diff -u /dev/null squid/src/logfile_mod_daemon.h:1.1.2.1 --- /dev/null Thu Jan 1 01:00:00 1970 +++ squid/src/logfile_mod_daemon.h Mon May 14 18:38:31 2007 @@ -0,0 +1,35 @@ +/* + * $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. + * + */ + +extern int logfile_mod_daemon_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag); Index: squid/src/logfile_mod_stdio.c diff -u /dev/null squid/src/logfile_mod_stdio.c:1.1.2.4 --- /dev/null Thu Jan 1 01:00:00 1970 +++ squid/src/logfile_mod_stdio.c Mon May 14 18:38:31 2007 @@ -0,0 +1,230 @@ +/* + * $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 "logfile_mod_stdio.h" + +typedef struct { + int fd; + char *buf; + int 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 + + debug(0, 1) ("logfileRotate (stdio): %s\n", 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) { + debug(50, 1) ("logfileRotate (stdio): %s: %s\n", 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 syslog: + */ +int +logfile_mod_stdio_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag) +{ + l_stdio_t *ll; + + ll = 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 { + debug(50, 1) ("logfileOpen (stdio): %s: %s\n", path, xstrerror()); + return 0; + } + } + + if (bufsz > 0) { + ll->buf = (char *) xmalloc(bufsz); + ll->bufsz = bufsz; + } + + 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; + + return 1; +} + Index: squid/src/logfile_mod_stdio.h diff -u /dev/null squid/src/logfile_mod_stdio.h:1.1.2.1 --- /dev/null Thu Jan 1 01:00:00 1970 +++ squid/src/logfile_mod_stdio.h Mon May 14 18:38:31 2007 @@ -0,0 +1,35 @@ +/* + * $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. + * + */ + +extern int logfile_mod_stdio_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag); Index: squid/src/logfile_mod_syslog.c diff -u /dev/null squid/src/logfile_mod_syslog.c:1.1.2.5 --- /dev/null Thu Jan 1 01:00:00 1970 +++ squid/src/logfile_mod_syslog.c Fri May 18 12:13:12 2007 @@ -0,0 +1,187 @@ +/* + * $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" +#if HAVE_SYSLOG +#include "logfile_mod_syslog.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) || !strcmp(s, p->name + 4)) + return p->value; + 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: + */ +int +logfile_mod_syslog_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag) +{ + l_syslog_t *ll; + + ll = xcalloc(1, sizeof(*ll)); + lf->data = ll; + + if (path[6] != '\0') { + const char *priority = path + 7; + char *facility = (char *) strchr(priority, '|'); + if (facility) { + *facility++ = '\0'; + ll->syslog_priority |= syslog_ntoa(facility); + } + ll->syslog_priority |= syslog_ntoa(priority); + } + if ((ll->syslog_priority & PRIORITY_MASK) == 0) + ll->syslog_priority |= LOG_INFO; + + 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; + + return 1; +} +#endif Index: squid/src/logfile_mod_syslog.h diff -u /dev/null squid/src/logfile_mod_syslog.h:1.1.2.1 --- /dev/null Thu Jan 1 01:00:00 1970 +++ squid/src/logfile_mod_syslog.h Mon May 14 18:38:31 2007 @@ -0,0 +1,35 @@ +/* + * $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. + * + */ + +extern int logfile_mod_syslog_open(Logfile *lf, const char *path, size_t bufsz, int fatal_flag); Index: squid/src/net_db.c diff -u squid/src/net_db.c:1.24 squid/src/net_db.c:1.22.10.2 --- squid/src/net_db.c:1.24 Mon Feb 26 01:51:32 2007 +++ squid/src/net_db.c Fri May 18 12:15:28 2007 @@ -387,7 +387,7 @@ * logfileOpen() use O_TRUNC. */ unlink(path); - lf = logfileOpen(path, 4096, 0); + lf = logfileOpen(path, Config.Log.logtype, 4096, 0); if (NULL == lf) { debug(50, 1) ("netdbSaveState: %s: %s\n", path, xstrerror()); return; Index: squid/src/protos.h diff -u squid/src/protos.h:1.142 squid/src/protos.h:1.118.2.10 --- squid/src/protos.h:1.142 Sat Jul 14 22:51:51 2007 +++ squid/src/protos.h Sat Aug 11 18:12:40 2007 @@ -1334,11 +1334,13 @@ #endif /* logfile.c */ -extern Logfile *logfileOpen(const char *path, size_t bufsz, int); +extern Logfile *logfileOpen(const char *path, const char *type, size_t bufsz, int); extern void logfileClose(Logfile * lf); extern void logfileRotate(Logfile * lf); -extern void logfileWrite(Logfile * lf, void *buf, size_t len); +extern void logfileWrite(Logfile * lf, char *buf, size_t len); extern void logfileFlush(Logfile * lf); +extern void logfileLineStart(Logfile * lf); +extern void logfileLineEnd(Logfile * lf); #if STDC_HEADERS extern void logfilePrintf(Logfile * lf, const char *fmt,...) PRINTF_FORMAT_ARG2; Index: squid/src/referer.c diff -u squid/src/referer.c:1.5 squid/src/referer.c:1.5.34.1 --- squid/src/referer.c:1.5 Sun Oct 13 14:46:16 2002 +++ squid/src/referer.c Fri May 18 12:15:28 2007 @@ -49,7 +49,7 @@ debug(40, 1) ("Referer logging is disabled.\n"); return; } - refererlog = logfileOpen(Config.Log.referer, 0, 1); + refererlog = logfileOpen(Config.Log.referer, Config.Log.logtype, 0, 1); #endif } Index: squid/src/store_log.c diff -u squid/src/store_log.c:1.11 squid/src/store_log.c:1.8.32.3 --- squid/src/store_log.c:1.11 Sun Jan 21 06:04:11 2007 +++ squid/src/store_log.c Sun Mar 11 15:02:49 2007 @@ -64,6 +64,7 @@ * Because if we print it before the swap file number, it'll break * the existing log format. */ + logfileLineStart(storelog); logfilePrintf(storelog, "%9ld.%03d %-7s %02d %08X %s %4d %9ld %9ld %9ld %s %" PRINTF_OFF_T "/%" PRINTF_OFF_T " %s %s\n", (long int) current_time.tv_sec, (int) current_time.tv_usec / 1000, @@ -80,8 +81,10 @@ mem->inmem_hi - mem->reply->hdr_sz, RequestMethods[mem->method].str, rfc1738_escape_unescaped(mem->url)); + logfileLineEnd(storelog); } else { /* no mem object. Most RELEASE cases */ + logfileLineStart(storelog); logfilePrintf(storelog, "%9ld.%03d %-7s %02d %08X %s ? ? ? ? ?/? ?/? ? ?\n", (long int) current_time.tv_sec, (int) current_time.tv_usec / 1000, @@ -89,6 +92,7 @@ e->swap_dirn, e->swap_filen, storeKeyText(e->hash.key)); + logfileLineEnd(storelog); } } @@ -116,5 +120,5 @@ debug(20, 1) ("Store logging disabled\n"); return; } - storelog = logfileOpen(Config.Log.store, 0, 1); + storelog = logfileOpen(Config.Log.store, Config.Log.logtype, 0, 1); } Index: squid/src/structs.h diff -u squid/src/structs.h:1.150 squid/src/structs.h:1.126.2.13 --- squid/src/structs.h:1.150 Fri Jul 20 14:52:59 2007 +++ squid/src/structs.h Sat Aug 11 18:12:40 2007 @@ -527,6 +527,7 @@ #endif logformat *logformats; customlog *accesslogs; + char *logtype; int rotateNumber; } Log; char *adminEmail; @@ -559,6 +560,7 @@ #if USE_SSL char *ssl_password; #endif + char *logfile_daemon; } Program; #if USE_DNSSERVERS int dnsChildren; @@ -2450,17 +2452,28 @@ } shm; }; +struct _logfile_buffer { + char *buf; + int size; + int len; + int written_len; + dlink_node node; +}; + struct _Logfile { - int fd; char path[MAXPATHLEN]; - char *buf; - size_t bufsz; - ssize_t offset; struct { unsigned int fatal; - unsigned int syslog; } flags; - int syslog_priority; + + void *data; + + LOGLINESTART * f_linestart; + LOGWRITE * f_linewrite; + LOGLINEEND * f_lineend; + LOGFLUSH * f_flush; + LOGROTATE * f_rotate; + LOGCLOSE * f_close; }; struct _logformat { Index: squid/src/typedefs.h diff -u squid/src/typedefs.h:1.42 squid/src/typedefs.h:1.39.2.3 --- squid/src/typedefs.h:1.42 Sun Jan 21 06:04:14 2007 +++ squid/src/typedefs.h Sun Mar 11 15:02:50 2007 @@ -213,6 +213,7 @@ typedef struct _storefs_entry storefs_entry_t; typedef struct _storerepl_entry storerepl_entry_t; typedef struct _diskd_queue diskd_queue; +typedef struct _logfile_buffer logfile_buffer_t; typedef struct _Logfile Logfile; typedef struct _logformat_token logformat_token; typedef struct _logformat logformat; @@ -409,4 +410,11 @@ typedef struct rms rms_t; +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 *); + #endif /* SQUID_TYPEDEFS_H */ Index: squid/src/useragent.c diff -u squid/src/useragent.c:1.7 squid/src/useragent.c:1.7.128.1 --- squid/src/useragent.c:1.7 Mon Jul 16 23:57:31 2001 +++ squid/src/useragent.c Fri May 18 12:15:28 2007 @@ -48,7 +48,7 @@ debug(40, 1) ("User-Agent logging is disabled.\n"); return; } - useragentlog = logfileOpen(Config.Log.useragent, 0, 1); + useragentlog = logfileOpen(Config.Log.useragent, Config.Log.logtype, 0, 1); #endif }