#include <curses.h>
#include <errno.h>
#include <signal.h>
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

int wait_for_connection(char *interface, int portnr, struct sockaddr_in *clientaddr)
{
	int clientaddrlen = sizeof(struct sockaddr_in);
	struct sockaddr_in ServerAddr;
	int ServerAddrLen = sizeof(ServerAddr);
        int ReUseAddr = 1;
	int fd = socket(AF_INET, SOCK_STREAM, 0), new_fd;
	if (fd == -1)
	{
		fprintf(stderr, "Could not create socket! Reason: %s\n", strerror(errno));
		return -1;
	}

        if (setsockopt(fd, SOL_SOCKET, SO_REUSEADDR, (char *)&ReUseAddr, sizeof(ReUseAddr)) == -1)
	{
		fprintf(stderr, "Could not set socket to 'reuse address'! Reason: %s\n", strerror(errno));
                return -1;
	}

	memset((char *)&ServerAddr, '\0', ServerAddrLen);
	ServerAddr.sin_family = AF_INET;
	if (interface)
	{
		if (inet_aton(interface, &ServerAddr.sin_addr) == 0)
		{
			fprintf(stderr, "Could not convert interface address %s!\n", interface);
			close(fd);
			return -1;
		}
	}
	else
	{
		ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);
	}
	ServerAddr.sin_port = htons(portnr);

	if (bind(fd, (struct sockaddr *)&ServerAddr, ServerAddrLen) == -1)
	{
		fprintf(stderr, "Could not bind socket to interface %s! Reason: %s\n", interface?interface:"(any)", strerror(errno));
		close(fd);
		return -1;
	}

	if (listen(fd, 1) == -1)
	{
		fprintf(stderr, "Could not setup listen queue! Reason: %s\n", strerror(errno));
		close(fd);
		return -1;
	}

	new_fd = accept(fd, (struct sockaddr *)clientaddr, &clientaddrlen);
	if (new_fd == -1)
	{
		fprintf(stderr, "Problem accepting new connection! Reason: %s\n", strerror(errno));
		close(fd);
		return -1;
	}

	close(fd);

	return new_fd;
}

void usage(void)
{
	fprintf(stderr, "recvnet v" VERSION ", (C) 2004 by folkert@vanheusden.com\n\n");
	fprintf(stderr, "-i interface	interface to bind to. default is any\n");
	fprintf(stderr, "-p port	port to listen on. default is telnet (23)\n");
	fprintf(stderr, "-h		this help\n");
	fprintf(stderr, "-V		version information\n");
}

int main(int argc, char *argv[])
{
	struct sockaddr_in clientaddr;
	int fd;
	int portnr=23;
	char *interface = NULL;
	int c;

        while((c = getopt(argc, argv, "i:p:hV")) != -1)
	{
		switch(c)
		{
		case 'i':
			interface = optarg;
			break;

		case 'p':
			portnr = atoi(optarg);
			break;

		case 'h':
			usage();
			return 1;

		case 'V':
			fprintf(stderr, VERSION ", (C) 2004 by folkert@vanheusden.com\n");
			return 1;
		}
	}

	printf("Listening on %s:%d\n", interface?interface:"(any)", portnr);

	fd = wait_for_connection(interface, portnr, &clientaddr);
	if (fd == -1)
		return 1;

	/* start curses */
	initscr();
	/* set terminal to non-cooked mode */
	cbreak();
	/* enable 8-bit input */
	meta(stdscr, TRUE);
	/* will take care of this */
	noecho();

	printw("Connection made with %s:%d\n", inet_ntoa(clientaddr.sin_addr), clientaddr.sin_port);
	printw("Escape character is '^]'.\n");
	refresh();

	signal(SIGINT, SIG_IGN);

	/* do terminal */
	for(;;)
	{
		fd_set rfds;
		int rc;
		char buffer[4096 + 1];

		FD_ZERO(&rfds);
		FD_SET(0, &rfds);
		FD_SET(fd, &rfds);

		if (select(fd + 1, &rfds, NULL, NULL, NULL) > 0)
		{
			if (FD_ISSET(0, &rfds))
			{
				buffer[0] = getch();

				/* escapecode? */
				if (buffer[0] == 29)
				{
					/* ... */
					endwin();
					fprintf(stderr, "\nConnection closed.\n");
					break;	/* should give some prompt */
				}
				else
				{
					/* transmit to other side */
					do
					{
						rc = write(fd, buffer, 1);
					}
					while(rc == -1 && errno == EINTR);

					if (buffer[0] == 10)
						wprintw(stdscr, "\n");
					else
						wprintw(stdscr, "%c", buffer[0]);
				}
			}

			if (FD_ISSET(fd, &rfds))
			{
				int loop;

				do
				{
					rc = read(fd, buffer, 4096);
				}
				while(rc == -1 && errno == EINTR);

				if (rc == 0)
				{
					endwin();
					fprintf(stderr, "\nConnection closed by foreign host.\n");
					break;
				}
				else if (rc == -1)
				{
					endwin();
					fprintf(stderr, "\nRead error. Reason: %s\n", strerror(errno));
					break;
				}

				buffer[rc] = 0x00;

				for(loop=0; loop<rc; loop++)
				{
					if (buffer[loop] != 13)
						wprintw(stdscr, "%c", buffer[loop]);
				}
			}

			refresh();
		}
	}

	close(fd);

	return 0;
}


syntax highlighted by Code2HTML, v. 0.9.1