/* MiddleMan filtering proxy server Copyright (C) 2002 Jason McLaughlin 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-1307 USA */ #include #include #include #include #include #include #include #include "proto.h" #ifdef USE_SYSLOG #include #endif /* USE_SYSLOG */ int logfd = -1; extern int loglevel; extern char logfile[]; extern LOGBUFFER *logbuffer; pthread_mutex_t logfile_lock = PTHREAD_MUTEX_INITIALIZER; /* write message to logfile */ void putlog(int level, char *fmt, ...) { #ifndef USE_SYSLOG time_t tt; struct tm *tv; #endif va_list valist; char buf[1024], *ptr; pthread_mutex_lock(&logfile_lock); ptr = buf; #ifndef USE_SYSLOG time(&tt); tv = localtime(&tt); ptr += strftime(ptr, 24, TIMEFORMAT, tv); ptr += sprintf(ptr, " [%u] ", (unsigned int) getpid()); #endif switch (level) { case MMLOG_REQUEST: ptr += sprintf(ptr, "request: "); break; case MMLOG_NETWORK: ptr += sprintf(ptr, "network: "); break; case MMLOG_FILTER: ptr += sprintf(ptr, "url filter: "); break; case MMLOG_HEADER: ptr += sprintf(ptr, "header: "); break; case MMLOG_MIME: ptr += sprintf(ptr, "mime filter: "); break; case MMLOG_COOKIE: ptr += sprintf(ptr, "cooke filter: "); break; case MMLOG_REDIRECT: ptr += sprintf(ptr, "redirect: "); break; case MMLOG_TEMPLATE: ptr += sprintf(ptr, "template: "); break; case MMLOG_KEYWORDS: ptr += sprintf(ptr, "keyword filter: "); break; case MMLOG_WARN: ptr += sprintf(ptr, "warning: "); break; case MMLOG_ERROR: ptr += sprintf(ptr, "error: "); break; case MMLOG_DEBUG: ptr += sprintf(ptr, "debug: "); break; } va_start(valist, fmt); ptr += vsnprintf(ptr, sizeof(buf) - (ptr - buf - 1), fmt, valist); va_end(valist); if (level != MMLOG_DEBUG) logbuffer_add(logbuffer, buf); if (!*logfile || !(loglevel & level)) goto out; if (*(ptr - 1) != '\n') { *(ptr++) = '\n'; *ptr = '\0'; } #ifdef USE_SYSLOG syslog(LOG_INFO, "%s", buf); #else if (logfd == -1) { logfd = open(logfile, O_RDWR | O_CREAT, 0644); if (logfd == -1) goto out; lseek(logfd, 0, SEEK_END); } write(logfd, buf, strlen(buf)); #endif out: pthread_mutex_unlock(&logfile_lock); } void logbuffer_add(LOGBUFFER * logbuffer, char *msg) { struct LOGBUFFER_LIST *ll; pthread_rwlock_wrlock(&logbuffer->lock); if (logbuffer->size == 0) { pthread_rwlock_unlock(&logbuffer->lock); return; } ll = xmalloc(sizeof(struct LOGBUFFER_LIST)); ll->msg = xstrdup(msg); ll->prev = NULL; ll->next = logbuffer->head; if (logbuffer->head != NULL) logbuffer->head->prev = ll; if (logbuffer->tail == NULL) logbuffer->tail = ll; logbuffer->head = ll; if (logbuffer->entries == logbuffer->size) { /* remove last log entry if we're at the size limit */ ll = logbuffer->tail; logbuffer->tail = ll->prev; ll->prev->next = NULL; xfree(ll->msg); xfree(ll); } else logbuffer->entries++; pthread_rwlock_unlock(&logbuffer->lock); } void logbuffer_clear(LOGBUFFER * logbuffer) { struct LOGBUFFER_LIST *ll, *tmp; pthread_rwlock_wrlock(&logbuffer->lock); ll = logbuffer->head; logbuffer->head = NULL; logbuffer->tail = NULL; logbuffer->entries = 0; while (ll != NULL) { tmp = ll->next; xfree(ll->msg); xfree(ll); ll = tmp; } pthread_rwlock_unlock(&logbuffer->lock); } /* reduce number of entries to logbuffer->size */ void logbuffer_resize(LOGBUFFER * logbuffer, int size) { int x; struct LOGBUFFER_LIST *ll, *tmp; if (size < 0) return; pthread_rwlock_wrlock(&logbuffer->lock); ll = logbuffer->head; for (x = 0; x < size && ll != NULL; x++, ll = ll->next); if (ll != NULL) { if (logbuffer->head == ll) logbuffer->head = NULL; logbuffer->tail = ll->prev; if (ll->prev != NULL) ll->prev->next = NULL; while (ll != NULL) { tmp = ll->next; xfree(ll->msg); xfree(ll); ll = tmp; } logbuffer->entries = size; } logbuffer->size = size; pthread_rwlock_unlock(&logbuffer->lock); }