diff options
| -rw-r--r-- | common/cmd_nvedit.c | 3 | ||||
| -rw-r--r-- | common/env_common.c | 8 | ||||
| -rw-r--r-- | include/environment.h | 9 | ||||
| -rw-r--r-- | include/search.h | 14 | ||||
| -rw-r--r-- | lib/hashtable.c | 20 | 
5 files changed, 48 insertions, 6 deletions
| diff --git a/common/cmd_nvedit.c b/common/cmd_nvedit.c index c601b3ac2..ddf3b8dfe 100644 --- a/common/cmd_nvedit.c +++ b/common/cmd_nvedit.c @@ -202,6 +202,7 @@ static int do_env_grep(cmd_tbl_t *cmdtp, int flag,   * environment variable, then (if successful) apply the changes to internals so   * to make them effective.  Code for this function was taken out of   * _do_env_set(), which now calls it instead. + * Also called as a callback function by himport_r().   * Returns 0 in case of success, 1 in case of failure.   * When (flag & H_FORCE) is set, do not print out any error message and force   * overwriting of write-once variables. @@ -915,7 +916,7 @@ static int do_env_import(cmd_tbl_t *cmdtp, int flag,  	}  	if (himport_r(&env_htab, addr, size, sep, del ? 0 : H_NOCLEAR, -			0, NULL) == 0) { +			0, NULL, 0 /* do_apply */) == 0) {  		error("Environment import failed: errno = %d\n", errno);  		return 1;  	} diff --git a/common/env_common.c b/common/env_common.c index c5cefd8a5..b9865bf63 100644 --- a/common/env_common.c +++ b/common/env_common.c @@ -136,7 +136,9 @@ const uchar default_environment[] = {  	"\0"  }; -struct hsearch_data env_htab; +struct hsearch_data env_htab = { +	.apply = env_check_apply, +};  static uchar __env_get_char_spec(int index)  { @@ -197,7 +199,7 @@ void set_default_env(const char *s)  	if (himport_r(&env_htab, (char *)default_environment,  			sizeof(default_environment), '\0', 0, -			0, NULL) == 0) +			0, NULL, 0 /* do_apply */) == 0)  		error("Environment import failed: errno = %d\n", errno);  	gd->flags |= GD_FLG_ENV_READY; @@ -223,7 +225,7 @@ int env_import(const char *buf, int check)  	}  	if (himport_r(&env_htab, (char *)ep->data, ENV_SIZE, '\0', 0, -			0, NULL)) { +			0, NULL, 0 /* do_apply */)) {  		gd->flags |= GD_FLG_ENV_READY;  		return 1;  	} diff --git a/include/environment.h b/include/environment.h index ae3f7b6ae..90fb1302b 100644 --- a/include/environment.h +++ b/include/environment.h @@ -184,6 +184,15 @@ void set_default_env(const char *s);  /* Import from binary representation into hash table */  int env_import(const char *buf, int check); +/* + * Check if variable "name" can be changed from oldval to newval, + * and if so, apply the changes (e.g. baudrate). + * When (flag & H_FORCE) is set, it does not print out any error + * message and forces overwriting of write-once variables. + */ +int env_check_apply(const char *name, const char *oldval, +			const char *newval, int flag); +  #endif /* DO_DEPS_ONLY */  #endif /* _ENVIRONMENT_H_ */ diff --git a/include/search.h b/include/search.h index 94d75fc65..721c8acda 100644 --- a/include/search.h +++ b/include/search.h @@ -57,6 +57,16 @@ struct hsearch_data {  	struct _ENTRY *table;  	unsigned int size;  	unsigned int filled; +/* + * Callback function which will check whether the given change for variable + * "name" from "oldval" to "newval" may be applied or not, and possibly apply + * such change. + * When (flag & H_FORCE) is set, it shall not print out any error message and + * shall force overwriting of write-once variables. +.* Must return 0 for approval, 1 for denial. + */ +	int (*apply)(const char *name, const char *oldval, +			const char *newval, int flag);  };  /* Create a new hashing table which will at most contain NEL elements.  */ @@ -97,10 +107,12 @@ extern ssize_t hexport_r(struct hsearch_data *__htab,  /*   * nvars: length of vars array   * vars: array of strings (variable names) to import (nvars == 0 means all) + * do_apply: whether to call callback function to check the new argument, + * and possibly apply changes (false means accept everything)   */  extern int himport_r(struct hsearch_data *__htab,  		     const char *__env, size_t __size, const char __sep, -		     int __flag, int nvars, char * const vars[]); +		     int __flag, int nvars, char * const vars[], int do_apply);  /* Flags for himport_r() */  #define	H_NOCLEAR	(1 << 0) /* do not clear hash table before importing */ diff --git a/lib/hashtable.c b/lib/hashtable.c index 0610e867d..6cfba5668 100644 --- a/lib/hashtable.c +++ b/lib/hashtable.c @@ -658,7 +658,7 @@ static int is_var_in_set(const char *name, int nvars, char * const vars[])  int himport_r(struct hsearch_data *htab,  		const char *env, size_t size, const char sep, int flag, -		int nvars, char * const vars[]) +		int nvars, char * const vars[], int do_apply)  {  	char *data, *sp, *dp, *name, *value; @@ -772,6 +772,24 @@ int himport_r(struct hsearch_data *htab,  		e.key = name;  		e.data = value; +		/* if there is an apply function, check what it has to say */ +		if (do_apply && htab->apply != NULL) { +			debug("searching before calling cb function" +				" for  %s\n", name); +			/* +			 * Search for variable in existing env, so to pass +			 * its previous value to the apply callback +			 */ +			hsearch_r(e, FIND, &rv, htab); +			debug("previous value was %s\n", rv ? rv->data : ""); +			if (htab->apply(name, rv ? rv->data : NULL, +				value, flag)) { +				debug("callback function refused to set" +					" variable %s, skipping it!\n", name); +				continue; +			} +		} +  		hsearch_r(e, ENTER, &rv, htab);  		if (rv == NULL) {  			printf("himport_r: can't insert \"%s=%s\" into hash table\n", |