>From a105d76fada85542837870e1050f12875c668634 Mon Sep 17 00:00:00 2001
From: Nikos Mavrogiannopoulos <nmav@gennetsa.com>
Date: Thu, 30 Apr 2009 12:36:45 +0300
Subject: [PATCH] Allow fw_setenv to write multiple variables in the same command line, thus reducing
 to one the flash erase/write needed to write a bunch of variables. To erase a variable
 use an argument of "".

---
 tools/env/fw_env.c |  156 ++++++++++++++++++++++++++--------------------------
 1 files changed, 79 insertions(+), 77 deletions(-)

diff --git a/tools/env/fw_env.c b/tools/env/fw_env.c
index a46205d..8e58860 100644
--- a/tools/env/fw_env.c
+++ b/tools/env/fw_env.c
@@ -337,12 +337,19 @@ int fw_printenv (int argc, char *argv[])
  */
 int fw_setenv (int argc, char *argv[])
 {
-	int i, len;
+	int i, len, j;
 	char *env, *nxt;
 	char *oldval = NULL;
-	char *name;
+	char *name, *val;
 
 	if (argc < 2) {
+		fprintf(stderr, "Too few arguments (%d)\n", argc-1);
+		errno = EINVAL;
+		return -1;
+	}
+	
+	if (argc > 2 && (argc - 1) % 2 != 0) {
+		fprintf(stderr, "Need an even number of argument (%d)\n", argc-1);
 		errno = EINVAL;
 		return -1;
 	}
@@ -350,102 +357,97 @@ int fw_setenv (int argc, char *argv[])
 	if (env_init ())
 		return -1;
 
-	name = argv[1];
+	for (j=1;j<argc;j+=2) {
 
-	/*
-	 * search if variable with this name already exists
-	 */
-	for (nxt = env = environment.data; *env; env = nxt + 1) {
-		for (nxt = env; *nxt; ++nxt) {
-			if (nxt >= &environment.data[ENV_SIZE]) {
-				fprintf (stderr, "## Error: "
+		name = argv[j];
+		
+		/*
+		 * search if variable with this name already exists
+		 */
+		for (nxt = env = environment.data; *env; env = nxt + 1) {
+			for (nxt = env; *nxt; ++nxt) {
+				if (nxt >= &environment.data[ENV_SIZE]) {
+					fprintf (stderr, "## Error: "
 					"environment not terminated\n");
-				errno = EINVAL;
-				return -1;
+					errno = EINVAL;
+					return -1;
+				}
 			}
+			if ((oldval = envmatch (name, env)) != NULL)
+				break;
 		}
-		if ((oldval = envmatch (name, env)) != NULL)
-			break;
-	}
 
-	/*
-	 * Delete any existing definition
-	 */
-	if (oldval) {
 		/*
-		 * Ethernet Address and serial# can be set only once
+		 * Delete any existing definition
 		 */
-		if ((strcmp (name, "ethaddr") == 0) ||
-			(strcmp (name, "serial#") == 0)) {
-			fprintf (stderr, "Can't overwrite \"%s\"\n", name);
-			errno = EROFS;
-			return -1;
-		}
+		 if (oldval) {
+		 	/*
+		 	 * Ethernet Address and serial# can be set only once
+		 	 */
+		 	 if ((strcmp (name, "ethaddr") == 0) ||
+		 	 	(strcmp (name, "serial#") == 0)) {
+		 	 	fprintf (stderr, "Can't overwrite \"%s\"\n", name);
+		 	 	errno = EROFS;
+		 	 	return -1;
+			}
 
-		if (*++nxt == '\0') {
-			*env = '\0';
-		} else {
-			for (;;) {
-				*env = *nxt++;
-				if ((*env == '\0') && (*nxt == '\0'))
-					break;
-				++env;
+			if (*++nxt == '\0') {
+				*env = '\0';
+			} else {
+				for (;;) {
+					*env = *nxt++;
+					if ((*env == '\0') && (*nxt == '\0'))
+						break;
+					++env;
+				}
 			}
+			*++env = '\0';
 		}
-		*++env = '\0';
-	}
 
-	/* Delete only ? */
-	if (argc < 3)
-		goto WRITE_FLASH;
+		/* this value is being deleted */
+		if (argv[j+1] == NULL || argv[j+1][0] == 0) continue;
 
-	/*
-	 * Append new definition at the end
-	 */
-	for (env = environment.data; *env || *(env + 1); ++env);
-	if (env > environment.data)
-		++env;
-	/*
-	 * Overflow when:
-	 * "name" + "=" + "val" +"\0\0"  > CONFIG_ENV_SIZE - (env-environment)
-	 */
-	len = strlen (name) + 2;
-	/* add '=' for first arg, ' ' for all others */
-	for (i = 2; i < argc; ++i) {
-		len += strlen (argv[i]) + 1;
-	}
-	if (len > (&environment.data[ENV_SIZE] - env)) {
-		fprintf (stderr,
-			"Error: environment overflow, \"%s\" deleted\n",
-			name);
-		return -1;
-	}
-	while ((*env = *name++) != '\0')
-		env++;
-	for (i = 2; i < argc; ++i) {
-		char *val = argv[i];
+		/*
+		 * Append new definition at the end
+		 */
+		 for (env = environment.data; *env || *(env + 1); ++env);
+		 if (env > environment.data)
+		 	++env;
+	
+		/*
+		 * Overflow when:
+		 * "name" + "=" + "val" +"\0\0"  > CFG_ENV_SIZE - (env-environment)
+		 */
+		 len = strlen (name) + 2;
+		 /* add '=' for first arg, ' ' for all others */
+		 len += strlen (argv[j+1]) + 1;
+		 if (len > (&environment.data[ENV_SIZE] - env)) {
+		 	fprintf (stderr, "Error: environment overflow, \"%s\" deleted\n", name);
+		 	return (-1);
+		}
 
-		*env = (i == 2) ? '=' : ' ';
-		while ((*++env = *val++) != '\0');
-	}
+		while ((*env = *name++) != '\0')
+			env++;
 
-	/* end is marked with double '\0' */
-	*++env = '\0';
+		val = argv[j+1];
 
-  WRITE_FLASH:
+		*env = '=';
+		while ((*++env = *val++) != '\0');
 
-	/*
-	 * Update CRC
-	 */
-	*environment.crc = crc32 (0, (uint8_t *) environment.data, ENV_SIZE);
+		/* end is marked with double '\0' */
+		*++env = '\0';
+	}
+
+	/* Update CRC */
+	environment.crc = crc32 (0, (uint8_t*) environment.data, ENV_SIZE);
 
 	/* write environment back to flash */
 	if (flash_io (O_RDWR)) {
 		fprintf (stderr, "Error: can't write fw_env to flash\n");
-		return -1;
+		return (-1);
 	}
 
-	return 0;
+	return (0);
 }
 
 /*
-- 
1.6.0.4

