diff --git a/zio-dump.c b/zio-dump.c
index 1611717bf576ea4f076628f2cd25b3f3dc9cda42..2964421a9d810d815c443c741bc2fde5a38b5207 100644
--- a/zio-dump.c
+++ b/zio-dump.c
@@ -10,40 +10,138 @@
 #include <fcntl.h>
 #include <sys/types.h>
 #include <sys/stat.h>
+#include <sys/select.h>
 
 #include <linux/zio.h>
 #include <linux/zio-buffer.h>
 
-#define FD_C 0
-#define FD_D 1
-#define ZIO_CONTROL_SIZE	512
-#define ZIO_NAME_LEN 32
-
 unsigned char buf[1024*1024];
+char *prgname;
+
+void read_channel(int cfd, int dfd, FILE *log)
+{
+	struct zio_control ctrl;
+	int i, j;
+
+	i = read(cfd, &ctrl, sizeof(ctrl));
+	switch(i) {
+	case -1:
+		fprintf(stderr, "%s: control read: %s\n",
+			prgname, strerror(errno));
+		exit(1);
+	case 0:
+		fprintf(stderr, "%s: control read: unexpected EOF\n",
+			prgname);
+		exit(1);
+	default:
+		fprintf(stderr, "%s: ctrl read: %i bytes (expected %i)\n",
+			prgname, i, sizeof(ctrl));
+		/* continue anyways */
+	case sizeof(ctrl):
+		break; /* ok */
+	}
+
+	printf("Ctrl: version %i.%i, trigger %.16s, dev %.16s, "
+	       "cset %i, chan %i\n",
+	       ctrl.major_version, ctrl.minor_version,
+	       ctrl.triggername, ctrl.devname, ctrl.cset_i,
+	       ctrl.chan_i);
+	printf("Ctrl: seq %i, n %i, size %i, bits %i, "
+	       "flags %08x (%s)\n",
+	       ctrl.seq_num,
+	       ctrl.nsamples,
+	       ctrl.ssize,
+	       ctrl.sbits,
+	       ctrl.flags,
+	       ctrl.flags & ZIO_CONTROL_LITTLE_ENDIAN
+	       ? "little-endian" :
+	       ctrl.flags & ZIO_CONTROL_BIG_ENDIAN
+	       ? "big-endian" : "unknown-endian");
+	printf("Ctrl: stamp %lli.%09lli (%lli)\n",
+	       (long long)ctrl.tstamp.secs,
+	       (long long)ctrl.tstamp.ticks,
+	       (long long)ctrl.tstamp.bins);
+	/* FIXME: some control information is missing */
+
+	i = read(dfd, buf, sizeof(buf));
+	if (i < 0) {
+		fprintf(stderr, "%s: data read: %s\n",
+			prgname, strerror(errno));
+		return; /* next ctrl, let's see... */
+	}
+	if (!i) {
+		fprintf(stderr, "%s: data read: unexpected EOF\n", prgname);
+		return;
+	}
+	if (i != ctrl.nsamples * ctrl.ssize) {
+		if (i == sizeof(buf)) {
+			fprintf(stderr, "%s: buffer too small: "
+				"please fix me and recompile\n", prgname);
+			/* FIXME: empty the data channel */
+		} else {
+			fprintf(stderr, "%s: ctrl: read %i bytes "
+				"(exp %i)\n", prgname, i,
+				ctrl.nsamples * ctrl.ssize);
+		}
+		/* continue anyways */
+	}
+	fwrite(buf, 1, i, log);
+
+	/* report data to stdout */
+	for (j = 0; j < i; j++) {
+		if (!(j & 0xf))
+			printf("Data:");
+		printf(" %02x", buf[j]);
+		if ((j & 0xf) == 0xf || j == i - 1)
+			putchar('\n');
+	}
+	putchar('\n');
+}
 
 int main(int argc, char **argv)
 {
 	FILE *f;
 	char *outfname;
-	int fd[2];
-	int i, j;
+	int *cfd; /* control file descriptors */
+	int *dfd; /* data file descriptors */
+	fd_set control_set, ready_set;
+	int i, j, maxfd, ndev;
 
-	if (argc != 3) {
-		fprintf(stderr, "%s: use \"%s <ctrl-file> <data-file>\"\n",
+	if (argc < 3 || (argc & 1) != 1) {
+		fprintf(stderr, "%s: Wrong number of arguments\n"
+			"Use: \"%s <ctrl-file> <data-file> [...]\"\n",
 			argv[0], argv[0]);
 		exit(1);
 	}
+	prgname = argv[0];
+	cfd = malloc(argc / 2 * sizeof(*cfd));
+	dfd = malloc(argc / 2 * sizeof(*dfd));
+	if (!cfd || !dfd) {
+		fprintf(stderr, "%s: malloc: %s\n", prgname, strerror(errno));
+		exit(1);
+	}
 
-	for (i = 0; i < 2; i++) {
-		fd[i] = open(argv[i + 1], O_RDONLY);
-		if (fd[i] < 0) {
-			fprintf(stderr, "%s: %s: %s\n", argv[0], argv[i + 1],
+	/* Open all pairs, and build the fd_set for later select() */
+	FD_ZERO(&control_set);
+	for (i = 1, j = 0; i < argc; i+=2, j++) {
+		cfd[j] = open(argv[i], O_RDONLY);
+		dfd[j] = open(argv[i + 1], O_RDONLY);
+		if (cfd[j] < 0) {
+			fprintf(stderr, "%s: %s: %s\n", prgname, argv[i],
+				strerror(errno));
+			exit(1);
+		}
+		if (dfd[j] < 0) {
+			fprintf(stderr, "%s: %s: %s\n", prgname, argv[i + 1],
 				strerror(errno));
 			exit(1);
 		}
+		/* ctrl file is used in select, data file is non-blocking */
+		FD_SET(cfd[j], &control_set);
+		fcntl(dfd[j], F_SETFL, fcntl(dfd[j], F_GETFL) | O_NONBLOCK);
+		maxfd = dfd[j];
 	}
-	/* the data channel is non-blocking */
-	fcntl(fd[FD_D], F_SETFL, fcntl(fd[FD_D], F_GETFL) | O_NONBLOCK);
+	ndev = j;
 
 	/* always log data we read to some filename */
 	outfname = getenv("ZIO_DUMP_TO");
@@ -51,7 +149,7 @@ int main(int argc, char **argv)
 		outfname = "/dev/null";
 	f = fopen(outfname, "w");
 	if (!f) {
-		fprintf(stderr, "%s: %s: %s\n", argv[0], outfname,
+		fprintf(stderr, "%s: %s: %s\n", prgname, outfname,
 			strerror(errno));
 		exit(1);
 	}
@@ -59,83 +157,19 @@ int main(int argc, char **argv)
 	setlinebuf(stdout);
 	setbuf(f, NULL);
 
-	/* now read control and data, forever */
+	/* now read control and then data, forever */
 	while (1) {
-		struct zio_control ctrl;
-
-		/* This is a blocking read to the control file */
-		i = read(fd[FD_C], &ctrl, sizeof(ctrl));
-		switch (i) {
-		case -1:
-			fprintf(stderr, "%s: %s: read(): %s\n",
-				argv[0], argv[1 + FD_C], strerror(errno));
-			exit(1);
-		case 0:
-			fprintf(stderr, "%s: %s: unexpected EOF\n",
-				argv[0], argv[1 + FD_C]);
-			exit(1);
-		default:
-			fprintf(stderr, "%s: ctrl: read %i bytes (exp %i)\n",
-				argv[0], i, sizeof(ctrl));
-			/* continue anyways */
-		case sizeof(ctrl):
-			break; /* ok */
-		}
-		printf("Ctrl: version %i.%i, trigger %.16s, dev %.16s, "
-		       "cset %i, chan %i\n",
-		       ctrl.major_version, ctrl.minor_version,
-		       ctrl.triggername, ctrl.devname, ctrl.cset_i,
-		       ctrl.chan_i);
-		printf("Ctrl: seq %i, n %i, size %i, bits %i, "
-		       "flags %08x (%s)\n",
-		       ctrl.seq_num,
-		       ctrl.nsamples,
-		       ctrl.ssize,
-		       ctrl.sbits,
-		       ctrl.flags,
-		       ctrl.flags & ZIO_CONTROL_LITTLE_ENDIAN
-		       ? "little-endian" :
-		       ctrl.flags & ZIO_CONTROL_BIG_ENDIAN
-		       ? "big-endian" : "unknown-endian");
-		printf("Ctrl: stamp %lli.%09lli (%lli)\n",
-		       (long long)ctrl.tstamp.secs,
-		       (long long)ctrl.tstamp.ticks,
-		       (long long)ctrl.tstamp.bins);
-		/* FIXME: some control information is missing */
-
-		i = read(fd[FD_D], buf, sizeof(buf));
-		if (i < 0) {
-			fprintf(stderr, "%s: %s: read(): %s\n",
-				argv[0], argv[1 + FD_D], strerror(errno));
-			continue; /* next ctrl, let's see... */
-		}
-		if (!i) {
-			fprintf(stderr, "%s: %s: unexpected EOF\n",
-				argv[0], argv[1 + FD_D]);
+		ready_set = control_set;
+		i = select(maxfd + 1, &ready_set, NULL, NULL, NULL);
+		if (i <0 && errno == EINTR)
 			continue;
+		if (i < 0) {
+			fprintf(stderr, "%s: select(): %s\n", prgname,
+				strerror(errno));
+			exit(1);
 		}
-		if (i != ctrl.nsamples * ctrl.ssize) {
-			if (i == sizeof(buf)) {
-				fprintf(stderr, "%s: buffer too small\n",
-					argv[0]);
-				/* FIXME: empty the data channel */
-			} else {
-				fprintf(stderr, "%s: ctrl: read %i bytes "
-					"(exp %i)\n", argv[0], i,
-					ctrl.nsamples * ctrl.ssize);
-			}
-			/* continue anyways */
-		}
-		fwrite(buf, 1, i, f);
-
-		/* report data to stdout */
-		for (j = 0; j < i; j++) {
-			if (!(j & 0xf))
-				printf("Data:");
-			printf(" %02x", buf[j]);
-			if ((j & 0xf) == 0xf || j == i - 1)
-				putchar('\n');
-		}
-	putchar('\n');
+		for (j = 0; j < ndev; j++)
+			if (FD_ISSET(cfd[j], & ready_set))
+				read_channel(cfd[j], dfd[j], f);
 	}
 }