/* logfile.c -- handle logfile management for ttywatch
 *
 * Copyright © 2000, 2001 Michael K. Johnson <a1237+ttywatch@danlj.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., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <errno.h>
#include <fcntl.h>
#include <glib.h>
#include <unistd.h>

#include "ttywatch.h"
#include "telnet.h"
#include "errors.h"

static char *logpath;

void
setup_logpath(char *path) {
    logpath = path;
}

void
open_one_logfile(machine *m) {
    char *logname;

    logname = alloca(strlen(logpath)+strlen(m->name)+6);
    sprintf(logname, "%s/%s.log", logpath, m->name);
    m->log_fd = open(logname, O_RDWR|O_CREAT|O_APPEND, 0666);
    if (m->log_fd < 0)
	warn(m, strerror(errno));
}

void
reopen_one_logfile(gpointer data, gpointer ignore) {
    machine *m = data;

    /* no logfile if a module is being used */
    if (m->log_fd) close(m->log_fd);
    open_one_logfile(m);
}

void
logfile_spew(net_conn *nc) {
    int log_fd;
    struct stat sb;
    int offset = 0, quantity;
    char *logname;
    char *buffer;

    logname = alloca(strlen(logpath)+strlen(nc->m->name)+6);
    sprintf(logname, "%s/%s.log", logpath, nc->m->name);
    log_fd = open(logname, O_RDONLY);
    if (log_fd < 0) {
	warn(nc->m, strerror(errno));
	return;
    }

    if (fstat(log_fd, &sb)) {
	warn(nc->m, strerror(errno));
	goto out;
    }

    quantity = sb.st_size;
    if (quantity > nc->m->logspew) {
	offset = quantity - nc->m->logspew;
	quantity = nc->m->logspew;
    }
    
    if (lseek(log_fd, offset, SEEK_SET) != offset) {
	warn(nc->m, strerror(errno));
	goto out;
    }

    buffer = alloca(quantity);
    if (!buffer) {
	warn(nc->m, "out of memory");
	goto out;
    }

    quantity = read(log_fd, buffer, quantity);
    if (quantity == -1) {
	warn(nc->m, strerror(errno));
	goto out;
    }

    telnet_send_output(nc, buffer, quantity);

out:
    close(log_fd);
}

/* CR/NL -> NL */
ssize_t
logfile_write(int outfd, char *data, size_t count) {
    char *s, *d; /* source, destination */
    char *buf;
    int len = count;

    buf = alloca(count);

    /* remove all CR characters */
    for (s=data, d=buf; s < data+count; s++, d++) {
	while ((s < data+count) && (*s == '\r')) {
	    /* skip all CR characters */
	    s++;
	    len--;
	}
	if (s < data+count) *d = *s;
    }
    
    return write(outfd, buf, len);
}
