Logo Search packages:      
Sourcecode: ziproxy version File versions  Download package

log.c

/* log.c - part of ziproxy package
 *
 * Copyright (c)2003-2004 Juraj Variny<variny@naex.sk>
 * Copyright (c)2005-2009 Daniel Mealha Cabrita
 *
 * Released subject to GNU General Public License v2 or later version.
 *
 * Convenient logging functions.
 */
#ifdef HAVE_CONFIG_H
#include "config.h"
#endif

#include <stdio.h>
#include <stdarg.h>
#include <time.h>
#include <sys/time.h>
#include "cfgfile.h"
#include "http.h"
#include "log.h"
#include <sys/types.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>

#define LOGGING ((LogFileName != NULL) || (LogPipe != NULL))

t_accesslog_data accesslog_data_d; // PRIVATE
t_accesslog_data *accesslog_data = &accesslog_data_d; // this is a global var, always points to accesslog_data_d

int minus_one = -1;

static FILE *logfile;
static int logpid;

static struct timeval newtime, oldtime;
static long timeval_subtract_us ( struct timeval *x, struct timeval *y);
static void goodbye(void);

static FILE *accesslog_file = NULL;

void init_logging(){
          time_t tm;
      if (! LOGGING) return;
      
      logpid = getpid();
      time(&tm);
    //open logging file
      if (LogPipe != NULL)
            logfile = stderr;
      else if (LogFileName != NULL) {
            struct tm *btime;
            time_t cas;
            char logname[50];

            time(&cas);
            btime = localtime(&cas);
            strftime(logname,sizeof(logname),LogFileName,btime);
            logfile = fopen(logname, "a");
      }     
      //set line buffered mode for logfile
      setvbuf(logfile,NULL,_IOLBF,BUFSIZ);
      //setlinebuf(logfile);
      
      fprintf(logfile, "[%d] Starting - %s", logpid, ctime(&tm));

      gettimeofday(&oldtime,NULL);
      atexit(&goodbye);
}

void set_logpid_current (void) {
      if (! LOGGING)
            return;
      logpid = getpid ();
}

int logprintf(char *fmt, ...){
      va_list ap;
      int i;
      if (! LOGGING) return 0;
      va_start(ap, fmt);
      fprintf(logfile,"[%d] ", logpid);
      i = vfprintf(logfile, fmt, ap);
      va_end(ap);
      return i;
}

void logputs(char *str){
      if (! LOGGING) return;
//    check_trim(str);//strip any trailing newlines
      fprintf(logfile,"[%d] %s\n", logpid, str);
}

void logputs_hdr(char *str){
      if (! LOGGING) return;
      fprintf(logfile,"[%d]   %s\n", logpid, str);
}

void reset_logdifftime (void) {
      gettimeofday (&oldtime, NULL);
}

void logdifftime(char * activity){
      if (! LOGGING) return;
      gettimeofday(&newtime,NULL);
      fprintf(logfile, "[%d] %s took %ld us. \n", 
                  logpid, activity,
                  timeval_subtract_us(&newtime, &oldtime));
      gettimeofday(&oldtime,NULL);

}

static long timeval_subtract_us (struct timeval *x, struct timeval *y){
      struct timeval result;
      
        /* Perform the carry for the later subtraction by updating Y. */
        if (x->tv_usec < y->tv_usec) {
          int nsec = (y->tv_usec - x->tv_usec) / 1000000 + 1;
          y->tv_usec -= 1000000 * nsec;
          y->tv_sec += nsec;
        }
        if (x->tv_usec - y->tv_usec > 1000000) {
          int nsec = (x->tv_usec - y->tv_usec) / 1000000;
          y->tv_usec += 1000000 * nsec;
          y->tv_sec -= nsec;
        }
      
        /* Compute the time remaining to wait.
           `tv_usec' is certainly positive. */
        result.tv_sec = x->tv_sec - y->tv_sec;
        result.tv_usec = x->tv_usec - y->tv_usec;
      
        return 1000000*result.tv_sec + result.tv_usec;
}


static void goodbye(void){
      logputs("Finished.");
}

/* returns: 0=ok 1=error */
int init_access_log (void) {
      accesslog_data->username = NULL;

      if (AccessLogFileName != NULL) {
            if ((accesslog_file = fopen (AccessLogFileName, "a")) != NULL) {
                  // set line buffered mode for access logfile
                  setvbuf (accesslog_file, NULL, _IOLBF, BUFSIZ);
                  return (0);
            }
            return (1); 
      }
      return (0);
}

/*
 *  there's no "close_access_log" function
 * when a process finishes, the file handler is automatically
 * closed by the OS
 */

/* same as access_log, except that extra_flags are appended to the existing ones */
/* if inlen/outlen != NULL, then its value overrides the one at accesslog_data */
void access_log_flags (int *inlen_o, int *outlen_o, const char *extra_flags) {
      char flags_str[30];
      int has_client_addr = 0;
      int has_username = 0;
      struct timeval currtime;
      int time_spent_msec;
      http_headers *client_hdr      = accesslog_data->hdr; // client headers
      struct timeval *giventime     = accesslog_data->giventime;
      const char *client_addr       = accesslog_data->client_addr;
      int inlen               = accesslog_data->inlen;
      int outlen              = accesslog_data->outlen;
      int flag_as_broken_pipe       = accesslog_data->flag_as_broken_pipe;
      int flag_as_image_too_expansive     = accesslog_data->flag_as_image_too_expansive;
      char client_source [200];     // string composed of: [username@]<IP|"?">

      if (accesslog_file == NULL)
            return;

      /* if we don't have headers yet (nor any other data)
       * since we don't want to crash nor to trash the access logfile, we do nothing
       * this may happen if the process was signalled (broken pipe, timeout etc)
       * before getting a chance to collect that data */
      if (accesslog_data->hdr == NULL)
            return;
      
      if (inlen_o != NULL)
            inlen = *inlen_o;
      if (outlen_o != NULL)
            outlen = *outlen_o;
      
      gettimeofday (&currtime, NULL);
      time_spent_msec = timeval_subtract_us (&currtime, giventime) / 1000;
      
      if (client_addr != NULL)
            has_client_addr = 1;
      if (accesslog_data->username != NULL)
            has_username = 1;
      
      flags_str[0]='\0';
      // Transparent or normal Proxy?
      if (client_hdr->flags & H_TRANSP_PROXY_REQUEST) {
            strcat (flags_str, "T");
      } else {
            strcat (flags_str, "P");
      }
      // SSL?
      if (client_hdr->flags & H_USE_SSL)
            strcat (flags_str, "S");
      // broken pipe?
      if (flag_as_broken_pipe != 0)
            strcat (flags_str, "B");
      // image bomb?
      if (flag_as_image_too_expansive != 0)
            strcat (flags_str, "K");
      // extra flags to add to logging?
      if (extra_flags != NULL)
            strcat (flags_str, extra_flags);

      client_source [199] = '\0';
      snprintf (client_source, 199, "%s%s%s", has_username?accesslog_data->username:"", has_username?"@":"", has_client_addr?client_addr:"?");
      
      fprintf (accesslog_file, "%d.%03d %6d %15s %2s %6d %6d %s %s\n", currtime.tv_sec, (int) currtime.tv_usec / 1000, time_spent_msec, client_source, flags_str, inlen, outlen, client_hdr->method, client_hdr->url);
}

void access_log (int *inlen_o, int *outlen_o) {
      access_log_flags (inlen_o, outlen_o, NULL);
}

/* username may be free'ed/changed after calling this */
void access_log_define_username (const char *username) {
      if (accesslog_data->username != NULL)
            free (accesslog_data->username);
      accesslog_data->username = strdup (username);
}


Generated by  Doxygen 1.6.0   Back to index