/*
 * chttpd/1.0
 * * logging facilities 
 * * 
 * *  copyright (c) 0x7d0
 * *  Greg Olszewski <noop@nwonknu.org>
 * * 
 * *   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., 675 Mass Ave, Cambridge, MA 02139, USA.
 */

#include <stdarg.h>
#include <stdio.h>
#include <time.h>
#include <syslog.h>
#include <string.h>
#include <stdlib.h>
#include <autoconf.h>

#define LOG_ERROR 0x00
#define LOG_INFOR 0x01
#define ERRSYSLOG 0x02
#define ERRFILE   0x01
#define ERRNONE   0x00

static int      err_log = ERRNONE;
static FILE    *logfile = NULL;
static FILE    *errfile = NULL;
const char      name[] = "chttpd";
extern unsigned int debug;

#ifndef HAVE_VSYSLOG
#include <stdlib.h>
static char    *buffer;
static size_t   buflen;
#endif

/*
 * log_info
 * logs to info file
 */
void
log_info(const char *fmt, ...)
{
    time_t          now;
    va_list         ap_save;
    char           *stime,
                   *tmp;
    now = time(&now);
    va_start(ap_save, fmt);
    if (logfile) {
	stime = ctime(&now);
	tmp = strchr(stime, '\n');
	if (tmp)
	    *tmp = '\0';
	fprintf(logfile, "%s: ", stime);
	vfprintf(logfile, fmt, ap_save);
    }
    fflush(logfile);
    va_end(ap_save);
}


/*
 * log_error
 * logs to error file or syslog
 */
void
log_error(const char *fmt, ...)
{
#ifndef HAVE_VSYSLOG
    int             err;
    char           *err2;
#endif
    char           *errtwo,
                   *errthree;
    va_list         ap_save;
    time_t          now;
    debug = 1;
    va_start(ap_save, fmt);
    if (err_log == ERRNONE)
	va_end(ap_save);
    if (err_log == ERRFILE) {
	errtwo = ctime(&now);
	if ((errthree = strchr(errtwo, '\n')))
	    *errthree = '\0';
	fprintf(errfile, "%s", ctime(&now));
	vfprintf(errfile, fmt, ap_save);
	fprintf(errfile, "\n");
    } else if (err_log == ERRSYSLOG)
#ifndef HAVE_VSYSLOG
    {
	if (!buffer) {
	    buffer = (char *) malloc(4096 * sizeof(*buffer));
	    if (!buffer) {
		syslog(LOG_ERR, "Couldn't malloc memory to log");
		va_end(ap_save);
	    }
	    buflen = 4096;
	}
	err = vsprintf(buffer, fmt, ap_save);
	while (err == -1 && buflen < 32768) {	/*
						 * we limit buflen here cuz.
						 */
	    err2 = realloc((void *) buffer, buflen + 1024);
	    if (!err2) {
		syslog(LOG_CRIT,
		       "Couldn't realloc memory while trying to print");
		syslog(LOG_CRIT, "%s", buffer);
		va_end(ap_save);
	    }
	    buffer = err2;
	    buflen += 1024;
	    err = vsprintf(buffer, fmt, ap_save);
	}
	if (err == -1) {
	    syslog(LOG_ERR,
		   "Tried to log really log error which started as");
	    syslog(LOG_ERR, "%s", buffer);
	}
	err2 = (char *) realloc(buffer, 4096);
	if (!err2) {
	    free(buffer);
	    buffer = NULL;
	    buflen = 0;
	} else {
	    buffer = err2;
	    buflen = 4096;
	}
    }
#else
	vsyslog(LOG_ERR, fmt, ap_save);
#endif
    va_end(ap_save);
}
/*
 * init_log
 * returns 0 for success 1 for error
 */
int
init_log(int errlog, const char *where_log, const char *where_err)
{
    time_t          now;
    int             status = 0;
    err_log = errlog;
    switch (errlog) {
    case ERRSYSLOG:
	errfile = NULL;
#ifndef HAVE_VSYSLOG
	buffer = (char *) malloc(4096 * sizeof(*buffer));
	if (!buffer) {
	    syslog(LOG_CRIT,
		   "couldn't allocate initial buffer, error logging may be unreliable");
	    buflen = 0;
	} else
	    buflen = 4096;
#endif
	openlog(name, 0, LOG_LOCAL7);
	syslog(LOG_INFOR, "starting up");
	break;
    case ERRFILE:
	errfile = fopen(where_err, "a");
	if (!errfile) {
	    fprintf(stderr, "Couldn't open errror log:%s\n", where_err);
	    status = 1;
	} else
	    fprintf(stderr, "Using error file:%s\n", where_err);
	break;
    case ERRNONE:
	fprintf(stderr, "No error file\n");
	errfile = NULL;
	break;
    default:
      fprintf(stderr, "unexpected error: contact noop@nwonknu.org\n");
      abort();

    }
    if (!where_log) {
      where_log = DEFAULT_LOGFILE;
    }
    fprintf(stderr, "Using informational logfile:%s\n", where_log);
    if (where_log) {
	logfile = fopen(where_log, "a");
	if (!logfile) {
	    fprintf(stderr, "Couldn't open log file:%s\n", where_log);
	    if (errfile)
		fclose(errfile);
	    status = 1;
	}
	fprintf(logfile, "chttpd: starting up: %s", ctime(&now));
	fflush(logfile);
    } else {
	logfile = NULL;
    }
    return status;
}

void
close_log(void)
{
    if (logfile)
	fclose(logfile);
    if (err_log == ERRSYSLOG)
	syslog(LOG_INFO, "shutting down log");
}
