Main Page | Modules | File List | Globals

access.c

00001 #include <time.h>
00002 #include <u/libu.h>
00003 #include <klone/klone.h>
00004 #include <klone/context.h>
00005 #include <klone/klog.h>
00006 #include <klone/access.h>
00007 #include <klone/server_ppc_cmd.h>
00008 
00009 static inline const char *value_or_dash(const char *v)
00010 {
00011     static const char dash[] = "-";
00012 
00013     return (v ? v : dash);
00014 }
00015 
00016 static long get_timezone(struct tm *tm)
00017 {
00018 #ifdef HAVE_STRUCT_TM_TM_GMTOFF
00019     long int h, m, sign;
00020 
00021     sign = (tm->tm_gmtoff > 0 ? 1 : -1);
00022     h = abs(tm->tm_gmtoff) / 3600;
00023     m = (h % 3600) / 60;
00024 
00025     return sign * (h * 100 + m);
00026 #else
00027     return 0;
00028 #endif
00029 }
00030 
00031 int access_log(http_t *h, u_config_t *config, request_t *rq, response_t *rs)
00032 {
00033     static const char *months[] = {
00034         "Jan", "Feb", "Mar", "Apr", "May", "Jun",
00035         "Jul", "Aug", "Sep", "Oct", "Nov", "Dec"
00036     };
00037     static const char default_prefix[] = "[access]";
00038     const char *ip,  *fn, *value, *prefix;
00039     char buf[U_MAX_LOG_LENGTH];
00040     u_config_t *sub;
00041     vhost_t *vhost;
00042     addr_t *addr;
00043     struct timeval tv;
00044     struct tm tm;
00045     time_t now;
00046     int logrq, n;
00047 
00048     dbg_err_if(h == NULL);
00049     dbg_err_if(config == NULL);
00050     dbg_err_if(rq == NULL);
00051     dbg_err_if(rs == NULL);
00052 
00053     dbg_err_if((vhost = http_get_vhost(h, rq)) == NULL);
00054 
00055     /* exit if access logging is not configured */
00056     dbg_err_if(vhost->klog == NULL);
00057 
00058     fn = request_get_filename(rq);
00059     dbg_err_if(fn == NULL);
00060 
00061     logrq = 0;
00062 
00063     /* if the user specifies what to log */
00064     if(u_config_get_child_n(config, "log", 0))
00065     {
00066         for(n = 0; (sub = u_config_get_child_n(config, "log", n)) != NULL; ++n)
00067         {
00068             if((value = u_config_get_value(sub)) == NULL)
00069                 continue;
00070             if(!fnmatch(value, fn, 0))
00071             {
00072                 logrq++;
00073                 break; /* log it */
00074             }
00075         }
00076     } else {
00077         /* no "log" key found, match all filenames */
00078         logrq++;
00079     }
00080     
00081     if(!logrq)
00082         return 0; /* don't log this request */
00083 
00084     /* the user specified what is NOT to be logged */
00085     for(n = 0; (sub = u_config_get_child_n(config, "dontlog", n)) != NULL; ++n)
00086     {
00087         if((value = u_config_get_value(sub)) == NULL)
00088             continue;
00089         if(fnmatch(value, fn, 0) == FNM_NOMATCH)
00090             continue;
00091         else 
00092             return 0; /* a "dontlog" item matches the filename, don't log */
00093     }
00094 
00095     gettimeofday(&tv, NULL);
00096 
00097     addr = request_get_peer_addr(rq);
00098     ip = inet_ntoa(addr->sa.sin.sin_addr);
00099 
00100     now = tv.tv_sec;
00101 #ifdef HAVE_LOCALTIME_R
00102     localtime_r(&now, &tm);
00103 #else
00104     tm = *localtime(&now);
00105 #endif
00106     tm.tm_year += 1900;
00107 
00108     if((sub = u_config_get_child(config, "prefix")) == NULL || 
00109             (prefix = u_config_get_value(sub)) == NULL)
00110     {
00111         prefix = default_prefix;
00112     }
00113 
00114     /* build the log message */
00115     dbg_err_if(u_snprintf(buf, sizeof(buf),
00116             "%s %s - - [%02d/%s/%4d:%02d:%02d:%02d %ld]"
00117             " \"%s\" %d %s \"%s\" \"%s\" \"-\"", 
00118             prefix,
00119             value_or_dash(ip),
00120             /* date */ 
00121             tm.tm_mday, months[tm.tm_mon], tm.tm_year,
00122             /* time */ 
00123             tm.tm_hour, tm.tm_min, tm.tm_sec, get_timezone(&tm),
00124             /* uri */
00125             value_or_dash(request_get_client_request(rq)),
00126             /* status */
00127             response_get_status(rs),
00128             /* bytes returned */
00129             value_or_dash(response_get_field_value(rs, "Content-Length")),
00130             /* referer and user-agent */
00131             value_or_dash(request_get_field_value(rq, "Referer")),
00132             value_or_dash(request_get_field_value(rq, "User-Agent"))
00133             ));
00134 
00135     /* syslog klog doesn't go through ppc */
00136     if(vhost->klog->type == KLOG_TYPE_SYSLOG || ctx->pipc == 0)
00137     {   /* syslog klog or parent context */
00138         if(vhost->klog)
00139             dbg_err_if(klog(vhost->klog, KLOG_INFO, "%s", buf));
00140     } else {
00141         /* children context */
00142         dbg_err_if(ctx->server == NULL);
00143         dbg_err_if(ctx->backend == NULL);
00144         dbg_err_if(server_ppc_cmd_access_log(ctx->server, ctx->backend->id, 
00145                     vhost->id, buf));
00146     }
00147 
00148     return 0;
00149 err:
00150     return ~0;
00151 }