/* ==================================================================== * * Copyright (c) 1996 NeoSoft, Inc. All rights reserved. * * You may freely redistribute most NeoSoft extensions to the Apache webserver * for any purpose except commercial resale and/or use in secure servers, * which requires, in either case, written permission from NeoSoft, Inc. Any * redistribution of this software must retain this copyright, unmodified * from the original. * * Certain NeoSoft extensions, such as those in support of electronic * commerce, require a license for use and may not be redistributed * without explicit written permission, obtained in advance of any * such distribution from NeoSoft, Inc. These files are clearly marked * with a different copyright. * * Other packages included with this distribution may contain their own * copyrights. It is your responsibility to insure that you are operating * in compliance with all relevant copyrights. The NeoSoft copyright is * not intenteded to infringe on the rights of the authors or owners of * said copyrights. * * Some of the software in this file may be derived from code * Copyright (c) 1995 The Apache Group. All rights reserved. * * Redistribution and use of Apache code in source and binary forms is * permitted under most conditions. Please consult the source code to * a standard Apache module, such as mod_include.c, for the exact * terms of this copyright. * * THIS SOFTWARE IS PROVIDED BY NEOSOFT ``AS IS'' AND ANY * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL NEOSOFT, THE APACHE GROUP, OR * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED * OF THE POSSIBILITY OF SUCH DAMAGE. * ==================================================================== */ #include "httpd.h" #include "http_config.h" #include "http_core.h" #include "ap_compat.h" #include module neo_log_module; static int xfer_flags = ( O_WRONLY | O_APPEND | O_CREAT ); static mode_t xfer_mode = ( S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH ); typedef struct { char *fname; int log_fd; } neo_log_state; void *make_neo_log_state (pool *p, server_rec *s) { neo_log_state *cls = (neo_log_state *)palloc (p, sizeof (neo_log_state)); cls->fname = DEFAULT_XFERLOG; cls->log_fd = -1; return (void *)cls; } const char *set_neo_log (cmd_parms *parms, void *dummy, char *arg) { neo_log_state *cls = get_module_config (parms->server->module_config, &neo_log_module); cls->fname = arg; return NULL; } command_rec neo_log_cmds[] = { { "NeoTransferLog", set_neo_log, NULL, RSRC_CONF, TAKE1, "the filename of the Tcl list-styled access log" }, { NULL } }; static int neo_log_child(void *cmd, child_info *pinfo) { /* Child process code for 'NeoTransferLog "|..."'; * may want a neo framework for this, since I expect it will * be neo for other foo-loggers to want this sort of thing... */ cleanup_for_exec(); signal(SIGHUP, SIG_IGN); execl(SHELL_PATH, SHELL_PATH, "-c", (char *)cmd, NULL); fprintf(stderr, "Exec of shell for logging failed!!!\n"); exit(1); } void open_neo_log (server_rec *s, pool *p) { neo_log_state *cls = get_module_config (s->module_config, &neo_log_module); char *fname = server_root_relative (p, cls->fname); int rc; if (cls->log_fd > 0) return; /* virtual log shared w/main server */ if (*cls->fname == '|') { FILE *dummy; rc = spawn_child(p, neo_log_child, (void *)(cls->fname+1), kill_after_timeout, &dummy, NULL); if (rc == 0 || dummy == NULL) { fprintf (stderr, "Couldn't fork child for NeoTransferLog process\n"); exit(1); } cls->log_fd = fileno (dummy); } else if((cls->log_fd = popenf(p, fname, xfer_flags, xfer_mode)) < 0) { fprintf(stderr,"httpd: could not open transfer log file %s.\n", fname); perror("open"); exit(1); } } void init_neo_log (server_rec *s, pool *p) { for (; s; s = s->next) open_neo_log (s, p); } int neo_log_transaction(request_rec *orig) { neo_log_state *cls = get_module_config(orig->server->module_config, &neo_log_module); char convbuf[MAX_STRING_LEN]; conn_rec *c = orig->connection; request_rec *r; time_t tloc; char *agent; Tcl_DString logString; Tcl_DStringInit(&logString); for (r = orig; r->next; r = r->next) continue; time(&tloc); sprintf(convbuf, "%ld", (long)tloc); Tcl_DStringAppendElement(&logString, convbuf); Tcl_DStringAppendElement(&logString, (char *)get_remote_host(r->connection, r->per_dir_config, REMOTE_NAME)); Tcl_DStringAppendElement(&logString, (c->remote_logname != NULL ? c->remote_logname : "")); Tcl_DStringAppendElement(&logString, (c->user != NULL ? c->user : "")); if (r->status != -1) { sprintf(convbuf, "%d", r->status); Tcl_DStringAppendElement(&logString, convbuf); } else { Tcl_DStringAppendElement(&logString, ""); } if(r->bytes_sent != -1) { sprintf(convbuf, "%ld", r->bytes_sent); Tcl_DStringAppendElement(&logString, convbuf); } else { Tcl_DStringAppendElement(&logString, ""); } Tcl_DStringAppendElement(&logString, c->server->server_hostname); Tcl_DStringAppendElement(&logString, (orig->the_request != NULL ? orig->the_request : "")); agent = (char *)table_get(orig->headers_in, "User-Agent"); Tcl_DStringAppendElement(&logString, (agent != NULL ? agent : "")); Tcl_DStringAppend(&logString, "\n", 1); write(cls->log_fd, Tcl_DStringValue(&logString), Tcl_DStringLength(&logString)); Tcl_DStringFree(&logString); return OK; } module neo_log_module = { STANDARD_MODULE_STUFF, init_neo_log, /* initializer */ NULL, /* create per-dir config */ NULL, /* merge per-dir config */ make_neo_log_state, /* server config */ NULL, /* merge server config */ neo_log_cmds, /* command table */ NULL, /* handlers */ NULL, /* filename translation */ NULL, /* check_user_id */ NULL, /* check auth */ NULL, /* check access */ NULL, /* type_checker */ NULL, /* fixups */ neo_log_transaction /* logger */ };