fixing a lot of bugs / cleaning up
- no more dependency problems with user-defined chains
- cleanup of the old strtok problem ( no more goto)
diff --git a/iptables-restore.8 b/iptables-restore.8
index 4e4e150..2ca6973 100644
--- a/iptables-restore.8
+++ b/iptables-restore.8
@@ -38,18 +38,7 @@
 .B iptables-restore
 flushes (deletes) all previous contents of the respective IP Table.
 .SH BUGS
-.B iptables-save
-doesn't order user-defined chains and builtin chains in any specific manner.
-This raises some dependency problems when using the unmodified output of 
-.B iptables-restore
-as input for
-.B iptables-restore.
-.PP
-Expect this to be fixed in the next iptables release.
-.PP
-To make it work, reorder the output in a way that in every table, all 
-user-defined chains are created before any other chain uses this chain
-as target.
+None known as of iptables-1.2.1 release
 .SH AUTHOR
 Harald Welte <laforge@gnumonks.org>
 .SH SEE ALSO
diff --git a/iptables-restore.c b/iptables-restore.c
index b4a8135..936c666 100644
--- a/iptables-restore.c
+++ b/iptables-restore.c
@@ -4,7 +4,7 @@
  *
  * This coude is distributed under the terms of GNU GPL
  *
- * $Id: iptables-restore.c,v 1.8 2001/01/23 22:54:34 laforge Exp $
+ * $Id: iptables-restore.c,v 1.9 2001/02/26 17:31:20 laforge Exp $
  */
 
 #include <getopt.h>
@@ -65,6 +65,21 @@
 	return (sscanf(string, "[%llu:%llu]", &ctr->pcnt, &ctr->bcnt) == 2);
 }
 
+/* global new argv and argc */
+static char* newargv[1024];
+static int newargc;
+
+/* function adding one argument to newargv, updating newargc 
+ * returns true if argument added, false otherwise */
+static int add_argv(char *what) {
+	if (what && ((newargc + 1) < sizeof(newargv)/sizeof(char *))) {
+		newargv[newargc] = what;
+		newargc++;
+		return 1;
+	} else 
+		return 0;
+}
+
 int main(int argc, char *argv[])
 {
 	iptc_handle_t handle;
@@ -72,7 +87,6 @@
 	unsigned int line = 0;
 	int c;
 	char curtable[IPT_TABLE_MAXNAMELEN + 1];
-	char curchain[IPT_FUNCTION_MAXNAMELEN + 1];
 	FILE *in;
 
 	program_name = "iptables-restore";
@@ -109,17 +123,7 @@
 		exit(1);
 	}
 	else in = stdin;
-/*
-	handle = iptc_init("filter");
-	if (!handle)
-		exit_error(VERSION_PROBLEM,
-			   "can't initialize iptables-restore: %s",
-			   iptc_strerror(errno));
-
-	if (!clean_slate(&handle))
-		exit_error(OTHER_PROBLEM, "Deleting old chains: %s",
-			   iptc_strerror(errno));
-*/
+	
 	/* Grab standard input. */
 	while (fgets(buffer, sizeof(buffer), in)) {
 		int ret;
@@ -173,16 +177,14 @@
 					   program_name, line);
 				exit(1);
 			}
-			strncpy(curchain, chain, IPT_FUNCTION_MAXNAMELEN);
 
-			/* why the f... does iptc_builtin not work here ? */
 			/* FIXME: abort if chain creation fails --RR */
-//			if (!iptc_builtin(curchain, &handle)) {
-				DEBUGP("Creating new chain '%s'\n", curchain);
-				if (!iptc_create_chain(curchain, &handle))
-				DEBUGP("unable to create chain '%s':%s\n", curchain,
+			if (!iptc_builtin(chain, handle)) {
+				DEBUGP("Creating new chain '%s'\n", chain);
+				if (!iptc_create_chain(chain, &handle))
+				DEBUGP("unable to create chain '%s':%s\n", chain,
 					strerror(errno));
-//			}
+			}
 
 			policy = strtok(NULL, " \t\n");
 			DEBUGP("line %u, policy '%s'\n", line, policy);
@@ -222,66 +224,64 @@
 			ret = 1;
 
 		} else {
-			char *newargv[1024];
-			int i,a, argvsize;
+			int a;
 			char *ptr = buffer;
 			char *pcnt = NULL;
 			char *bcnt = NULL;
+			char *parsestart;
+
+			/* reset the newargv */
+			newargc = 0;
 
 			if (buffer[0] == '[') {
+				/* we have counters in our input */
 				ptr = strchr(buffer, ']');
 				if (!ptr)
 					exit_error(PARAMETER_PROBLEM,
 						   "Bad line %u: need ]\n",
 						   line);
+
 				pcnt = strtok(buffer+1, ":");
+				if (!pcnt)
+					exit_error(PARAMETER_PROBLEM,
+						   "Bad line %u: need :\n",
+						   line);
+
 				bcnt = strtok(NULL, "]");
+				if (!bcnt)
+					exit_error(PARAMETER_PROBLEM,
+						   "Bad line %u: need ]\n",
+						   line);
+
+				/* start command parsing after counter */
+				parsestart = ptr + 1;
+			} else {
+				/* start command parsing at start of line */
+				parsestart = buffer;
 			}
 
-			newargv[0] = argv[0];
-			newargv[1] = "-t";
-			newargv[2] = (char *) &curtable;
-			newargv[3] = "-A";
-			newargv[4] = (char *) &curchain;
-			argvsize = 5;
-
+			add_argv(argv[0]);
+			add_argv("-t");
+			add_argv((char *) &curtable);
+			
 			if (counters && pcnt && bcnt) {
-				newargv[5] = "--set-counters";
-				newargv[6] = (char *) pcnt;
-				newargv[7] = (char *) bcnt;
-				argvsize = 8;
+				add_argv("--set-counters");
+				add_argv((char *) pcnt);
+				add_argv((char *) bcnt);
 			}
 
-			// strtok initcialize!
-			if ( buffer[0]!='[' )
-			{
-				if (!(newargv[argvsize] = strtok(buffer, " \t\n")))
-					goto ImLaMeR;
-					//break;
-				argvsize++;
-			}
-
-			/* strtok: a function only a coder could love */
-			for (i = argvsize; i < sizeof(newargv)/sizeof(char *); 
-					i++) {
-				if (!(newargv[i] = strtok(NULL, " \t\n")))
-					break;
-				ptr = NULL;
-			}
-ImLaMeR:		if (i == sizeof(newargv)/sizeof(char *)) {
-				fprintf(stderr,
-					"%s: line %u too many arguments\n",
-					program_name, line);
-				exit(1);
+			/* parse till end of line */
+			if (add_argv(strtok(parsestart, " \t\n"))) {
+				while (add_argv(strtok(NULL, " \t\n")));
 			}
 
 			DEBUGP("===>calling do_command(%u, argv, &%s, handle):\n",
-					i, curtable);
+					newargc, curtable);
 
-			for (a = 0; a <= i; a++)
+			for (a = 0; a <= newargc; a++)
 				DEBUGP("argv[%u]: %s\n", a, newargv[a]);
 
-			ret = do_command(i, newargv, &newargv[2], &handle);
+			ret = do_command(newargc, newargv, &newargv[2], &handle);
 		}
 		if (!ret) {
 			fprintf(stderr, "%s: line %u failed\n",
diff --git a/iptables-save.8 b/iptables-save.8
index 32b70ef..71a957d 100644
--- a/iptables-save.8
+++ b/iptables-save.8
@@ -37,18 +37,7 @@
 restrict output to only one table. If not specified, output includes all
 available tables.
 .SH BUGS
-.B iptables-save
-doesn't order user-defined chains and builtin chains in any specific manner.
-This raises some dependency problems when using the unmodified output of 
-.B iptables-save
-as input for
-.B iptables-restore.
-.PP
-Expect this to be fixed in the next iptables release.
-.PP
-To make it work, reorder the output in a way that in every table, all 
-user-defined chains are created before any other chain uses this chain
-as target.
+None known as of iptables-1.2.1 release
 .SH AUTHOR
 Harald Welte <laforge@gnumonks.org>
 .SH SEE ALSO
diff --git a/iptables-save.c b/iptables-save.c
index f648efa..282ca7f 100644
--- a/iptables-save.c
+++ b/iptables-save.c
@@ -145,7 +145,7 @@
 /* We want this to be readable, so only print out neccessary fields.
  * Because that's the kind of world I want to live in.  */
 static void print_rule(const struct ipt_entry *e, 
-		iptc_handle_t *h, int counters)
+		iptc_handle_t *h, const char *chain, int counters)
 {
 	struct ipt_entry_target *t;
 
@@ -153,6 +153,9 @@
 	if (counters)
 		printf("[%llu:%llu] ", e->counters.pcnt, e->counters.bcnt);
 
+	/* print chain name */
+	printf("-A %s ", chain);
+
 	/* Print IP part. */
 	print_ip("-s", e->ip.src.s_addr,e->ip.smsk.s_addr,
 			e->ip.invflags & IPT_INV_SRCIP);	
@@ -246,12 +249,12 @@
 		       NETFILTER_VERSION, ctime(&now));
 		printf("*%s\n", tablename);
 
-		/* Dump out chain names */
+		/* Dump out chain names first, 
+		 * thereby preventing dependency conflicts */
 		for (chain = iptc_first_chain(&h);
 		     chain;
 		     chain = iptc_next_chain(&h)) {
-			const struct ipt_entry *e;
-
+			
 			printf(":%s ", chain);
 			if (iptc_builtin(chain, h)) {
 				struct ipt_counters count;
@@ -261,11 +264,18 @@
 			} else {
 				printf("- [0:0]\n");
 			}
+		}
+				
+
+		for (chain = iptc_first_chain(&h);
+		     chain;
+		     chain = iptc_next_chain(&h)) {
+			const struct ipt_entry *e;
 
 			/* Dump out rules */
 			e = iptc_first_rule(chain, &h);
 			while(e) {
-				print_rule(e, &h, counters);
+				print_rule(e, &h, chain, counters);
 				e = iptc_next_rule(e, &h);
 			}
 		}