#include <stdio.h>
#include <sys/signal.h>
#include <sys/socket.h>
#include <netinet/in.h>

main(argc, argv)
int argc;
char **argv;
{
	int verbose;
	int lfd, sfd;
	struct sockaddr_in myaddr, claddr;
	struct in_addr ia;
	int inane;
	int pid;
	FILE *sfp;

	verbose = 0;
	if (argc > 1 && strcmp(argv[1], "-v") == 0) {
		verbose = 1;
		argc--;
		argv++;
	}
	if ((lfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
		perror("socket");
		exit(1);
	}
	myaddr.sin_family = AF_INET;
	myaddr.sin_port = htons(33333);
	myaddr.sin_addr.s_addr = INADDR_ANY;
	if (bind(lfd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0) {
		perror("bind");
		exit(1);
	}
	inane = sizeof(myaddr);
	if (getsockname(lfd, (struct sockaddr *)&myaddr, &inane) < 0) {
		perror("getsockname");
		exit(1);
	}
	if (listen(lfd, 5) < 0) {
		perror("listen");
		exit(1);
	}
	fprintf(stderr, "listening on %d\n", ntohs(myaddr.sin_port));
	fflush(stdout);
	while (inane = sizeof(claddr), (sfd = accept(lfd, (struct sockaddr *)&claddr, &inane)) >= 0) {
		if ((pid = fork()) < 0) {
			perror("fork");
			continue;
		}
		if (pid == 0) {		/* child: copy in */
			if ((sfp = fdopen(sfd, "r")) == NULL) {
				fprintf(stderr, "child can't fdopen connection for reading\n");
				exit(1);
			}
			copydata(sfp, stdout, verbose);
			exit(0);
		} else {		/* parent: copy out */
			if (verbose)
				fprintf(stderr, "accept %s:%d, pid %d\n",
					inet_ntoa(claddr.sin_addr),
					ntohs(claddr.sin_port), pid);
			if ((sfp = fdopen(sfd, "w")) == NULL) {
				fprintf(stderr, "parent can't fdopen connection for writing\n");
				continue;	/* leave child running */
			}
			copydata(stdin, sfp, 0);
			fclose(sfp);
			kill(pid, SIGTERM);	/* kill child, so connection closes */
			clearerr(stdin);	/* clear EOF flag */
		}
		close(sfd);
	}
	exit(0);
}

copydata(frfp, tofp, verbose)
FILE *frfp, *tofp;
int verbose;
{
	char buf[200];
	int mypid;

	mypid = getpid();
	while (fgets(buf, sizeof(buf), frfp)) {
		if (verbose)
			fprintf(tofp, "%d: ", mypid);
		if (fputs(buf, tofp) == EOF
		||  fflush(tofp) == EOF) {
			perror("write");
			break;
		}
	}
}
