A few more fixes.
diff --git a/iptables-save.c b/iptables-save.c
index 2a86718..00da8df 100644
--- a/iptables-save.c
+++ b/iptables-save.c
@@ -7,11 +7,13 @@
 #include "packet-match/userspace/libiptc/libiptc.h"
 #include "packet-match/userspace/iptables.h"
 
-/* Keeping track of external matches and targets.  */
+static int binary = 0, counters = 0;
+
 static struct option options[] = {
-	{ "binary", 1, 0, 'b' },
-	{ "counters", 1, 0, 'c' },
-	{ "dump", 1, 0, 'd' },
+	{ "binary", 0, 0, 'b' },
+	{ "counters", 0, 0, 'c' },
+	{ "dump", 0, 0, 'd' },
+	{ "table", 1, 0, 't' },
 	{ 0 }
 };
 
@@ -164,16 +166,117 @@
 /* Debugging prototype. */
 extern void dump_entries(iptc_handle_t handle);
 
+static int for_each_table(int (*func)(const char *tablename))
+{
+        int ret = 1;
+	FILE *procfile;
+	char tablename[IPT_TABLE_MAXNAMELEN+1];
+
+	procfile = fopen("/proc/net/ip_tables_names", O_RDONLY);
+	if (!procfile)
+		return 0;
+
+	while (fgets(tablename, sizeof(tablename), procfile)) {
+		if (tablename[strlen(tablename) - 1] != '\n')
+			exit_error(OTHER_PROBLEM, 
+				   "Badly formed tablename `%s'\n",
+				   tablename);
+		tablename[strlen(tablename) - 1] = '\0';
+		ret &= func(tablename);
+	}
+
+	return ret;
+}
+	
+
+static int dump_table(const char *tablename)
+{
+	iptc_handle_t h;
+
+	if (!tablename)
+		return for_each_table(&dump_table);
+
+	/* Debugging dump. */
+	h = iptc_init(tablename);
+	if (!h)
+		exit_error(OTHER_PROBLEM, "iptc_init: %s\n",
+			   iptc_strerror(errno));
+	dump_entries(h);
+}
+	
+static int do_output(const char *tablename)
+{
+	iptc_handle_t h;
+	const char *chain = NULL;
+
+	if (!tablename)
+		return for_each_table(&do_output);
+
+	h = iptc_init(tablename);
+	if (!h)
+ 		exit_error(OTHER_PROBLEM, "Can't initialize: %s\n",
+			   iptc_strerror(errno));
+
+	if (!binary) {
+		time_t now = time(NULL);
+
+		printf("# Generated by iptables-save v%s on %s",
+		       NETFILTER_VERSION, ctime(&now));
+
+		/* Dump out chain names */
+		for (chain = iptc_first_chain(&h);
+		     chain;
+		     chain = iptc_next_chain(&h)) {
+			printf(":%s ", chain);
+			if (iptc_builtin(chain, &h)) {
+				struct ipt_counters count;
+				printf("%s ",
+				       iptc_get_policy(chain, &count, &h));
+				printf("%llu %llu\n", count.pcnt, count.bcnt);
+			} else {
+				printf("- 0 0\n");
+			}
+		}
+
+		/* Dump out rules */
+		for (chain = iptc_first_chain(&h);
+		     chain;
+		     chain = iptc_next_chain(&h)) {
+			unsigned int i;
+
+			for (i = 0; i < iptc_num_rules(chain, &h); i++) {
+				const struct ipt_entry *e
+					= iptc_get_rule(chain, i, &h);
+
+				if (!e)
+					exit_error(OTHER_PROBLEM,
+						   "Can't read rule %u"
+						   " of chain %s: %s\n",
+						   i, chain,
+						   iptc_strerror(errno));
+				print_rule(e, counters);
+			}
+		}
+
+		now = time(NULL);
+		printf("COMMIT\n");
+		printf("# Completed on %s", ctime(&now));
+	} else {
+		/* Binary, huh?  OK. */
+		exit_error(OTHER_PROBLEM, "Binary NYI\n");
+	}
+
+	return 1;
+}
+
 /* Format:
  * :Chain name POLICY packets bytes
  * rule
  */
 int main(int argc, char *argv[])
 {
-	iptc_handle_t h;
-	const char *chain = NULL;
+	const char *tablename = NULL;
 	int c;
-	int binary = 0, counters = 0;
 
 	program_name = "iptables-save";
 	program_version = NETFILTER_VERSION;
@@ -188,13 +291,12 @@
 			counters = 1;
 			break;
 
+		case 't':
+			/* Select specific table. */
+			tablename = optarg;
+			break;
 		case 'd':
-			/* Debugging dump. */
-			h = iptc_init();
-			if (!h)
-				exit_error(OTHER_PROBLEM, "iptc_init: %s\n",
-					   iptc_strerror(errno));
-			dump_entries(h);
+			dump_table(tablename);
 			exit(0);
 		}
 	}
@@ -204,58 +306,5 @@
 		exit(1);
 	}
 
-	h = iptc_init();
-	if (!h) {
-		fprintf(stderr, "Can't initialize: %s\n",
-			iptc_strerror(errno));
-		exit(1);
-	}
-
-	if (!binary) {
-		time_t now = time(NULL);
-
-		printf("# Generated by iptables-save v%s on %s",
-		       NETFILTER_VERSION, ctime(&now));
-
-		/* Dump out chain names */
-		while ((chain = iptc_next_chain(chain, &h)) != NULL) {
-			printf(":%s ", chain);
-			if (iptc_builtin(chain, &h)) {
-				struct ipt_counters count;
-				printf("%s ",
-				       iptc_get_policy(chain, &count, &h));
-				printf("%llu %llu\n", count.pcnt, count.bcnt);
-			} else {
-				printf("- 0 0\n");
-			}
-		}
-
-		/* Dump out rules */
-		while ((chain = iptc_next_chain(chain, &h)) != NULL) {
-			unsigned int i;
-
-			for (i = 0; i < iptc_num_rules(chain, &h); i++) {
-				const struct ipt_entry *e
-					= iptc_get_rule(chain, i, &h);
-
-				if (!e) {
-					fprintf(stderr,
-						"Can't read rule %u of chain %s: %s\n",
-						i, chain, iptc_strerror(errno));
-					exit(1);
-				}
-				print_rule(e, counters);
-			}
-		}
-
-		now = time(NULL);
-		printf("COMMIT\n");
-		printf("# Completed on %s", ctime(&now));
-	} else {
-		/* Binary, huh?  OK. */
-		fprintf(stderr, "Binary NYI\n");
-		exit(1);
-	}
-
-	return 0;
+	return !do_output(tablename);
 }