/*
 * Copyright (C) 2002 Jeff Dike (jdike@karaya.com) and
 * geoffrey hing <ghing@net.ohio-state.edu>
 * Licensed under the GPL
 */

#include <errno.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/time.h>
#include "init.h"
#include "user.h"
#include "kern_util.h"
#include "os.h"

#define TTY_LOG_DIR "./"

/* Set early in boot and then unchanged */
static char *tty_log_dir = TTY_LOG_DIR;
static int tty_log_fd = -1;

#define TTY_LOG_OPEN 1
#define TTY_LOG_CLOSE 2
#define TTY_LOG_WRITE 3
#define TTY_LOG_EXEC 4

#define TTY_READ 1
#define TTY_WRITE 2

struct tty_log_buf {
	int what;
	unsigned long tty;
	int len;
	int direction;
	unsigned long sec;
	unsigned long usec;
};

int open_tty_log(void *tty, void *current_tty)
{
	struct timeval tv;
	struct tty_log_buf data;
	char buf[strlen(tty_log_dir) + sizeof("01234567890-01234567\0")];
	int fd;

	gettimeofday(&tv, NULL);
	if(tty_log_fd != -1){
		data = ((struct tty_log_buf) { .what 	= TTY_LOG_OPEN,
					       .tty  = (unsigned long) tty,
					       .len  = sizeof(current_tty),
					       .direction = 0,
					       .sec = tv.tv_sec,
					       .usec = tv.tv_usec } );
		os_write_file(tty_log_fd, &data, sizeof(data));
		os_write_file(tty_log_fd, &current_tty, data.len);
		return tty_log_fd;
	}

	sprintf(buf, "%s/%0u-%0u", tty_log_dir, (unsigned int) tv.tv_sec,
 		(unsigned int) tv.tv_usec);

	fd = os_open_file(buf, of_append(of_create(of_rdwr(OPENFLAGS()))),
			  0644);
	if(fd < 0){
		printk("open_tty_log : couldn't open '%s', errno = %d\n",
		       buf, -fd);
	}
	return fd;
}

void close_tty_log(int fd, void *tty)
{
	struct tty_log_buf data;
	struct timeval tv;

	if(tty_log_fd != -1){
		gettimeofday(&tv, NULL);
		data = ((struct tty_log_buf) { .what 	= TTY_LOG_CLOSE,
					       .tty  = (unsigned long) tty,
					       .len  = 0,
					       .direction = 0,
					       .sec = tv.tv_sec,
					       .usec = tv.tv_usec } );
		os_write_file(tty_log_fd, &data, sizeof(data));
		return;
	}
	os_close_file(fd);
}

static int log_chunk(int fd, const char *buf, int len)
{
	int total = 0, try, missed, n;
	char chunk[64];

	while(len > 0){
		try = (len > sizeof(chunk)) ? sizeof(chunk) : len;
		missed = copy_from_user_proc(chunk, (char *) buf, try);
		try -= missed;
		n = os_write_file(fd, chunk, try);
		if(n != try) {
			if(n < 0)
				return n;
			return -EIO;
		}
		if(missed != 0)
			return -EFAULT;

		len -= try;
		total += try;
		buf += try;
	}

	return total;
}

int write_tty_log(int fd, const char *buf, int len, void *tty, int is_read)
{
	struct timeval tv;
	struct tty_log_buf data;
	int direction;

	if(fd == tty_log_fd){
		gettimeofday(&tv, NULL);
		direction = is_read ? TTY_READ : TTY_WRITE;
		data = ((struct tty_log_buf) { .what 	= TTY_LOG_WRITE,
					       .tty  = (unsigned long) tty,
					       .len  = len,
					       .direction = direction,
					       .sec = tv.tv_sec,
					       .usec = tv.tv_usec } );
		os_write_file(tty_log_fd, &data, sizeof(data));
	}

	return log_chunk(fd, buf, len);
}

void log_exec(char **argv, void *tty)
{
	struct timeval tv;
	struct tty_log_buf data;
	char **ptr,*arg;
	int len;

	if(tty_log_fd == -1) return;

	gettimeofday(&tv, NULL);

	len = 0;
	for(ptr = argv; ; ptr++){
		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
			return;
		if(arg == NULL) break;
		len += strlen_user_proc(arg);
	}

	data = ((struct tty_log_buf) { .what 	= TTY_LOG_EXEC,
				       .tty  = (unsigned long) tty,
				       .len  = len,
				       .direction = 0,
				       .sec = tv.tv_sec,
				       .usec = tv.tv_usec } );
	os_write_file(tty_log_fd, &data, sizeof(data));

	for(ptr = argv; ; ptr++){
		if(copy_from_user_proc(&arg, ptr, sizeof(arg)))
			return;
		if(arg == NULL) break;
		log_chunk(tty_log_fd, arg, strlen_user_proc(arg));
	}
}

extern void register_tty_logger(int (*opener)(void *, void *),
				int (*writer)(int, const char *, int,
					      void *, int),
				void (*closer)(int, void *));

static int register_logger(void)
{
	register_tty_logger(open_tty_log, write_tty_log, close_tty_log);
	return 0;
}

__uml_initcall(register_logger);

static int __init set_tty_log_dir(char *name, int *add)
{
	tty_log_dir = name;
	return 0;
}

__uml_setup("tty_log_dir=", set_tty_log_dir,
"tty_log_dir=<directory>\n"
"    This is used to specify the directory where the logs of all pty\n"
"    data from this UML machine will be written.\n\n"
);

static int __init set_tty_log_fd(char *name, int *add)
{
	char *end;

	tty_log_fd = strtoul(name, &end, 0);
	if((*end != '\0') || (end == name)){
		printf("set_tty_log_fd - strtoul failed on '%s'\n", name);
		tty_log_fd = -1;
	}

	*add = 0;
	return 0;
}

__uml_setup("tty_log_fd=", set_tty_log_fd,
"tty_log_fd=<fd>\n"
"    This is used to specify a preconfigured file descriptor to which all\n"
"    tty data will be written.  Preconfigure the descriptor with something\n"
"    like '10>tty_log tty_log_fd=10'.\n\n"
);
