/*
 *	select: read from several files using select
 */

#include <stdio.h>

main(argc, argv)
char **argv;
{
	int savereadmask = 0;	/* bit mask for select */
	int readmask;		/* copy to pass to select() */
	int filefd;		/* fd open to file to read */
	int nfds = 0;		/* max active fd + 1 */
	int nready;		/* return value from select */
	char *filename[20];	/* file names for error reporting */
	int debug = 0;		/* give running comemntary */
	int i;

	for (i=1; i<argc; i++) {
		if (argv[i][0] == '-') {
			switch (argv[i][1]) {
			case 'd':	/* debug trace on */
				debug = 1;
				break;
			case '\0':	/* read stdin */
				filename[0] = "stdin";
				savereadmask |= 01;
				if (nfds < 1) nfds = 1;
				break;
			default:
				fputs("Usage: select [-d] [file] ...\n", stderr);
				exit(1);
			}
			continue;
		}
	
		filefd = open(argv[i], 0);
		if (filefd < 0) {
			perror(argv[i]);
		} else {
			filename[filefd] = argv[i];
			savereadmask |= 1 << filefd;
			/* nfds = max(fd)+1 */
			if (nfds < filefd+1) nfds = filefd+1;
		}
	}


	readmask = savereadmask;
	if (debug) {
		fputs("selecting:\t", stderr);
		print(nfds, readmask);
	}
	while (readmask != 0 && (nready = select(nfds, &readmask, 0, 0, 0)) > 0) {
		if (debug) {
			fputs("returned:\t", stderr);
			print(nready, readmask);
		}
		for (i=0; i<nfds; i++) {
			if ((readmask & (1<<i)) != 0) {
				char buf[BUFSIZ];
				int nbytes;

				nbytes = read(i, buf, BUFSIZ);
				switch (nbytes) {
				case 0:
					if (debug) fprintf(stderr, "EOF on %d (%s)\n", i, filename[i]);
					savereadmask &= ~(1<<i);
					break;
				case -1:
					fprintf(stderr, "Error on %d (%s)\n", i, filename[i]);
					savereadmask &= ~(1<<i);
					break;
				default:
					if (debug) fprintf(stderr, "Reading %d (%s)\n", i, filename[i]);
					write(1, buf, nbytes);
					break;
				}
			}
		}
		readmask = savereadmask;	/* restore for select */
		if (debug) {
			fputs("selecting:\t", stderr);
			print(nfds, readmask);
		}
	}
	exit(0);
}

print(nfds, bitmask)
{
	int i;

	fprintf(stderr, "%d:", nfds);
	for (i=0; i<32; i++) {
		putc( ((bitmask & (1<<i)) != 0) ? '1' : '0' , stderr);
	}
	putchar('\n');
}
