unescape parameters

Max Kellermann <max@duempel.org>
diff --git a/ip6tables-restore.c b/ip6tables-restore.c
index 12f8d8c..2d2f8b0 100644
--- a/ip6tables-restore.c
+++ b/ip6tables-restore.c
@@ -311,8 +311,9 @@
 			char *parsestart;
 
 			/* the parser */
-			char *param_start, *curchar;
-			int quote_open;
+			char *curchar;
+			int quote_open, escaped;
+			size_t param_len;
 
 			/* reset the newargv */
 			newargc = 0;
@@ -359,41 +360,45 @@
 			 * longer a real hacker, but I can live with that */
 
 			quote_open = 0;
-			param_start = parsestart;
+			escaped = 0;
+			param_len = 0;
 
 			for (curchar = parsestart; *curchar; curchar++) {
-				if (*curchar == '"') {
-					/* quote_open cannot be true if there
-					 * was no previous character.  Thus, 
-					 * curchar-1 has to be within bounds */
-					if (quote_open && 
-					    *(curchar-1) != '\\') {
+				char param_buffer[1024];
+
+				if (escaped) {
+					param_buffer[param_len++] = *curchar;
+					escaped = 0;
+					continue;
+				}
+
+				if (quote_open) {
+					if (*curchar == '\\') {
+						escaped = 1;
+						continue;
+					} else if (*curchar == '"') {
 						quote_open = 0;
 						*curchar = ' ';
 					} else {
-						quote_open = 1;
-						param_start++;
+						param_buffer[param_len++] = *curchar;
+						continue;
 					}
-				} 
+				} else {
+					if (*curchar == '"') {
+						quote_open = 1;
+						continue;
+					}
+				}
+
 				if (*curchar == ' '
 				    || *curchar == '\t'
 				    || * curchar == '\n') {
-					char param_buffer[1024];
-					int param_len = curchar-param_start;
-
-					if (quote_open)
-						continue;
-
 					if (!param_len) {
 						/* two spaces? */
-						param_start++;
 						continue;
 					}
-					
-					/* end of one parameter */
-					strncpy(param_buffer, param_start,
-						param_len);
-					*(param_buffer+param_len) = '\0';
+
+					param_buffer[param_len] = '\0';
 
 					/* check if table name specified */
 					if (!strncmp(param_buffer, "-t", 3)
@@ -405,9 +410,14 @@
 					}
 
 					add_argv(param_buffer);
-					param_start += param_len + 1;
+					param_len = 0;
 				} else {
-					/* regular character, skip */
+					/* regular character, copy to buffer */
+					param_buffer[param_len++] = *curchar;
+
+					if (param_len >= sizeof(param_buffer))
+						exit_error(PARAMETER_PROBLEM, 
+						   "Parameter too long!");
 				}
 			}