#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <errno.h>

#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main()
{
	int sock;
	int client;
	struct sockaddr_in addr;

	char buf[128];
	size_t size;
	int recvd;

	size_t to_send;
	int sent;

	sock = socket(AF_INET, SOCK_STREAM, 0);
	if(sock == -1)
	{
		fprintf(stderr, "socket() failed: %s\n", strerror(errno));
		return -1;
	}

	addr.sin_family = AF_INET;
	addr.sin_port = htons(113);
	addr.sin_addr.s_addr = INADDR_ANY;

	if(bind(sock, (struct sockaddr*)&addr, sizeof(addr)) == -1)
	{
		fprintf(stderr, "bind() failed: %s\n", strerror(errno));
		return -1;
	}

	if(listen(sock, 5) == -1)
	{
		fprintf(stderr, "listen() failed: %s\n", strerror(errno));
		return -1;
	}

	switch(fork())
	{
	case -1:
		fprintf(stderr, "fork() failed: %s\n", strerror(errno));
		break;
	case 0:
		break;
	default:
		exit(EXIT_SUCCESS);
		break;
	}

	while((client = accept(sock, NULL, NULL)) != -1)
	{
		size = 0;

		/* recv until '\n' is reached, maximum 32 bytes */
		do
		{
			recvd = recv(
				client,
				buf + size,
				32 - size,
				MSG_NOSIGNAL
			);

			if(recvd > 0) size += recvd;
		} while(recvd > 0 && size < 32 && buf[size - 1] != '\n');

		if(buf[size - 1] != '\n' || recvd < 0 || size < 2)
		{
			close(client);
			continue;
		}

		strcpy(buf + size - 2, " : USERID : UNIX : ck\r\n");
		to_send = strlen(buf);

		size = 0;
		while(size < to_send)
		{
			sent = send(
				client,
				buf + size,
				to_send - size,
				MSG_NOSIGNAL
			);

			if(sent <= 0) break;

			printf("%.*s", sent, buf + size);
			fflush(stdout);

			size += sent;
		}

		close(client);
	}

	close(sock);
	return EXIT_SUCCESS;
}

