nand_base: We have to ignore the -EUCLEAN error
[barebox-mini2440.git] / common / env.c
blobedaf38895643390f34ffa45e4dc1ffe2feb5c9f7
1 /*
2 * env.c - environment variables storage
4 * Copyright (c) 2007 Sascha Hauer <s.hauer@pengutronix.de>, Pengutronix
6 * See file CREDITS for list of people who contributed to this
7 * project.
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2
11 * as published by the Free Software Foundation.
13 * This program is distributed in the hope that it will be useful,
14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 * GNU General Public License for more details.
18 * You should have received a copy of the GNU General Public License
19 * along with this program; if not, write to the Free Software
20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
23 /**
24 * @file
25 * @brief Environment support
28 #include <common.h>
29 #include <driver.h>
30 #include <malloc.h>
31 #include <xfuncs.h>
32 #include <errno.h>
33 #include <init.h>
34 #include <environment.h>
36 #define VARIABLE_D_SIZE(name, value) (sizeof(struct variable_d) + strlen(name) + strlen(value) + 2)
38 static struct env_context *context;
40 /**
41 * Remove a list of environment variables
42 * @param[in] v Variable anchor to remove
44 static void free_variables(struct variable_d *v)
46 struct variable_d *next;
48 while (v) {
49 next = v->next;
50 free(v);
51 v = next;
55 /** Read back current context */
56 struct env_context *get_current_context(void)
58 return context;
60 EXPORT_SYMBOL(get_current_context);
63 /**
64 * FIXME
66 int env_push_context(void)
68 struct env_context *c = xzalloc(sizeof(struct env_context));
70 c->local = xzalloc(VARIABLE_D_SIZE("", ""));
71 c->global = xzalloc(VARIABLE_D_SIZE("", ""));
73 if (!context) {
74 context = c;
75 return 0;
78 c->parent = context;
79 context = c;
81 return 0;
84 late_initcall(env_push_context);
86 /**
87 * FIXME
89 int env_pop_context(void)
91 struct env_context *c = context;
93 if (context->parent) {
94 c = context->parent;
95 free_variables(context->local);
96 free_variables(context->global);
97 free(context);
98 context = c;
99 return 0;
101 return -EINVAL;
105 * Return variable's value
106 * @param[in] var Variable of interest
107 * @return Value as text
109 char *var_val(struct variable_d *var)
111 return &var->data[strlen(var->data) + 1];
115 * Return variable's name
116 * @param[in] var Variable of interest
117 * @return Name as text
119 char *var_name(struct variable_d *var)
121 return var->data;
124 static const char *getenv_raw(struct variable_d *var, const char *name)
126 while (var) {
127 if (!strcmp(var_name(var), name))
128 return var_val(var);
129 var = var->next;
131 return NULL;
134 const char *getenv (const char *name)
136 struct env_context *c;
137 const char *val;
139 if (strchr(name, '.')) {
140 const char *ret = 0;
141 char *devstr = strdup(name);
142 char *par = strchr(devstr, '.');
143 struct device_d *dev;
144 *par = 0;
145 dev = get_device_by_name(devstr);
146 if (dev) {
147 par++;
148 ret = dev_get_param(dev, par);
150 free(devstr);
151 return ret;
154 c = context;
156 val = getenv_raw(c->local, name);
157 if (val)
158 return val;
160 while (c) {
161 val = getenv_raw(c->global, name);
162 if (val)
163 return val;
164 c = c->parent;
166 return NULL;
168 EXPORT_SYMBOL(getenv);
170 static int setenv_raw(struct variable_d *var, const char *name, const char *value)
172 struct variable_d *newvar = NULL;
174 if (value) {
175 newvar = xzalloc(VARIABLE_D_SIZE(name, value));
176 strcpy(&newvar->data[0], name);
177 strcpy(&newvar->data[strlen(name) + 1], value);
180 while (var->next) {
181 if (!strcmp(var->next->data, name)) {
182 if (value) {
183 newvar->next = var->next->next;
184 free(var->next);
185 var->next = newvar;
186 return 0;
187 } else {
188 struct variable_d *tmp;
189 tmp = var->next;
190 var->next = var->next->next;
191 free(tmp);
192 return 0;
195 var = var->next;
197 var->next = newvar;
198 return 0;
201 int setenv(const char *_name, const char *value)
203 char *name = strdup(_name);
204 char *par;
205 struct variable_d *var;
206 int ret = 0;
208 if (!*value)
209 value = NULL;
212 if ((par = strchr(name, '.'))) {
213 struct device_d *dev;
215 *par++ = 0;
216 dev = get_device_by_name(name);
217 if (dev)
218 ret = dev_set_param(dev, par, value);
219 else
220 ret = -ENODEV;
222 errno = ret;
224 if (ret < 0)
225 perror("set parameter");
227 goto out;
230 if (getenv_raw(context->global, name))
231 var = context->global;
232 else
233 var = context->local;
235 ret = setenv_raw(var, name, value);
236 out:
237 free(name);
239 return ret;
241 EXPORT_SYMBOL(setenv);
243 int export(const char *varname)
245 const char *val = getenv_raw(context->local, varname);
247 if (val) {
248 setenv_raw(context->global, varname, val);
249 setenv_raw(context->local, varname, NULL);
250 return 0;
252 return -1;
254 EXPORT_SYMBOL(export);