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

int
main(int ac, char **av)
{
	int i, port;
	int sfd, cfd, clen;
	struct sockaddr_in saddr, caddr;
	fd_set rfs;

	for(i=1; i<ac; i++) if(strcmp(av[i], "-p") == 0) break;
	if(i+1 >= ac){
		fprintf(stderr, "-p port\n");
		exit(1);
	}
	port = strtol(av[i+1], NULL, 0);

	if((sfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){
		perror("socket");
		exit(1);
	}
	memset(&saddr, 0, sizeof(saddr));
	saddr.sin_family = AF_INET;
	saddr.sin_addr.s_addr = htonl(INADDR_ANY);
	saddr.sin_port = htons(port);
	if(bind(sfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1){
		perror("bind");
		exit(1);
	}
	if(listen(sfd, 5) == -1){
		perror("listen");
		exit(1);
	}
	FD_ZERO(&rfs);
	FD_SET(0, &rfs);	
	FD_SET(sfd, &rfs);
	
	while(1){
		int nfds = 0, fd, fd2;
		fd_set res_rfs = rfs;
		for(fd=0; fd<FD_SETSIZE; fd++) if(FD_ISSET(fd, &res_rfs) && fd > nfds) nfds = fd;
		if(select(nfds+1, &res_rfs, NULL, NULL, NULL) <= 0) continue;

		for(fd=0; fd<FD_SETSIZE; fd++){
			char buf[4096];
			int n;

			if(!FD_ISSET(fd, &res_rfs)) continue;
			if(fd == 0){
				n = read(0, buf, sizeof(buf));
				for(fd2=4; fd2<FD_SETSIZE; fd2++){
					if(!FD_ISSET(fd2, &rfs)) continue;
					write(fd2, buf, n);
				}
			}else if(fd == sfd){
				memset(&caddr, 0, sizeof(caddr));
				clen = sizeof(caddr);
				if((cfd = accept(sfd, (struct sockaddr *)&caddr, (socklen_t *)&clen)) == -1){
					perror("accept");
					exit(1);
				}
				FD_SET(cfd, &rfs);
			}else{
				n = read(fd, buf, sizeof(buf));
				if(n > 0) write(1, buf, n);
				else FD_CLR(fd, &rfs);
			}
		}
	}
	return 0;
}

/* EOF */