#include <signal.h>
#include <socket.h>
#include <errno.h>
#include <stdarg.h>
#include "beport.h"

#undef write
#undef read
#undef close
#undef select
#undef ioctl
#undef dup2
#undef open
#undef exit
#undef __exit

int forked;
int signalled;

int setpgrp(void)
{
	return setpgid(0, 0);
}

int vhangup(void)
{
	return (kill(-getpid(), SIGHUP));
}


int
is_socket(int fd)
{
	return (fd == 0);
}

int
to_socket(int fd)
{
	return (fd);
}


int
setenv(const char *name, const char *value, int overwrite)
{
	char buf[256];

	sprintf(buf, "%s=%s", name, value);
	return (putenv(buf));
}

int
unsetenv(const char *name)
{
	char buf[256];

	sprintf(buf, "%s=", name);
	return (putenv(buf));
}

int
check_dup2(int fd, int fd2)
{
	int ret;

	if (fd == 0 && !forked) {
		if (!signalled) dprintf("Warning: dup2 on socket\n");
		errno = ENOTTY;
		return (-1);
	} else {
		if (!signalled) dprintf("dup2(%d, %d)\n", fd, fd2);
		ret = dup2(fd, fd2);
		if (fd2 == 0) {
			forked++;
		}
		return (ret);
	}
	
}

#if DEBUG
static void
showbuf(const char *buf, int len)
{
	int i;
	char line[80];
	unsigned char c;

	for (i = 0; i < len; i++) {
		c = buf[i];
		if (c >= ' ' && c <= '~') {
			sprintf(&line[(i % 25) * 3], " %c ", c);
		} else {
			sprintf(&line[(i % 25) * 3], "x%02x", c);
		}
		if ((i % 25) == 24) {
			if (!signalled) dprintf("%s\n", line);
		}
	}
	if ((i % 25) != 0) {
		if (!signalled) dprintf("%s\n", line);
	}
}
#else
#define showbuf(x, y)
#endif

int
check_write(int fd, const char *buf, int len)
{
	int ret;

	if (fd == 0 && !forked) {
		if (!signalled) dprintf("Warning: send(%d, %d)...\n", fd, len);
		showbuf(buf, len);
		ret = send(fd, buf, len, 0);
		if (!signalled) dprintf("send(%d, %d) = %d\n", fd, len, ret);
		return (ret);
	} else {
		if (!signalled) dprintf("write(%d, %d)...\n", fd, len);
		showbuf(buf, len);
		ret = write(fd, buf, len);
		if (!signalled) dprintf("write(%d, %d) = %d\n", fd, len, ret);
		return (ret);
	}
}

int
check_read(int fd, char *buf, int len)
{
	int ret;

	if (fd == 0 && !forked) {
		if (!signalled) dprintf("Warning: recv(%d, %d)...\n", fd, len);
		ret = recv(fd, buf, len, 0);
		if (ret >= 0) {
			showbuf(buf, ret);
		}
		if (!signalled) dprintf("recv(%d, %d) = %d\n", fd, len, ret);
		return (ret);
	} else {
		if (!signalled) dprintf("read(%d, %d)...\n", fd, len);
		ret = read(fd, buf, len);
		if (ret >= 0) {
			showbuf(buf, ret);
		}
		if (!signalled) dprintf("read(%d, %d) = %d\n", fd, len, ret);
		return (ret);
	}
}

int
check_close(int fd)
{
	if (fd == 0 && !forked) {
		if (!signalled) dprintf("Warning: closesocket(%d)\n", fd);
		return (closesocket(fd));
	} else {
		if (!signalled) dprintf("close(%d)\n", fd);
		return (close(fd));
	}
}

int
check_open(const char *filename, int flags, int mode)
{
	int ret;

	ret = open(filename, flags, mode);
	if (!signalled) dprintf("open(%s) = %d\n", filename, ret);
	return (ret);
}

int
check_ioctl(int fd, int cmd, char *data)
{
	int ret;

	if (fd == 0 && !forked) {
		if (!signalled) dprintf("Warning: ioctl on socket\n");
		errno = ENOTTY;
		return (-1);
	} else {
		if (cmd == 1) {
			debugger("ioctl");
		}
		if (!signalled) dprintf("ioctl(%d, %08x)...\n", fd, cmd);
		ret = ioctl(fd, cmd, data);
		if (!signalled) dprintf("ioctl(%d, %08x) = %d\n", fd, cmd, ret);
		return (ret);
	}
}
