1#include "qemu-common.h"
2#include "qemu/queue.h"
3#include "qemu/envlist.h"
4
5struct envlist_entry {
6 const char *ev_var;
7 QLIST_ENTRY(envlist_entry) ev_link;
8};
9
10struct envlist {
11 QLIST_HEAD(, envlist_entry) el_entries;
12 size_t el_count;
13};
14
15static int envlist_parse(envlist_t *envlist,
16 const char *env, int (*)(envlist_t *, const char *));
17
18
19
20
21
22envlist_t *
23envlist_create(void)
24{
25 envlist_t *envlist;
26
27 if ((envlist = malloc(sizeof (*envlist))) == NULL)
28 return (NULL);
29
30 QLIST_INIT(&envlist->el_entries);
31 envlist->el_count = 0;
32
33 return (envlist);
34}
35
36
37
38
39void
40envlist_free(envlist_t *envlist)
41{
42 struct envlist_entry *entry;
43
44 assert(envlist != NULL);
45
46 while (envlist->el_entries.lh_first != NULL) {
47 entry = envlist->el_entries.lh_first;
48 QLIST_REMOVE(entry, ev_link);
49
50 free((char *)entry->ev_var);
51 free(entry);
52 }
53 free(envlist);
54}
55
56
57
58
59
60
61
62
63
64
65
66
67int
68envlist_parse_set(envlist_t *envlist, const char *env)
69{
70 return (envlist_parse(envlist, env, &envlist_setenv));
71}
72
73
74
75
76
77
78
79int
80envlist_parse_unset(envlist_t *envlist, const char *env)
81{
82 return (envlist_parse(envlist, env, &envlist_unsetenv));
83}
84
85
86
87
88
89
90
91static int
92envlist_parse(envlist_t *envlist, const char *env,
93 int (*callback)(envlist_t *, const char *))
94{
95 char *tmpenv, *envvar;
96 char *envsave = NULL;
97 int ret = 0;
98 assert(callback != NULL);
99
100 if ((envlist == NULL) || (env == NULL))
101 return (EINVAL);
102
103 if ((tmpenv = strdup(env)) == NULL)
104 return (errno);
105 envsave = tmpenv;
106
107 do {
108 envvar = strchr(tmpenv, ',');
109 if (envvar != NULL) {
110 *envvar = '\0';
111 }
112 if ((*callback)(envlist, tmpenv) != 0) {
113 ret = errno;
114 break;
115 }
116 tmpenv = envvar + 1;
117 } while (envvar != NULL);
118
119 free(envsave);
120 return ret;
121}
122
123
124
125
126
127
128
129int
130envlist_setenv(envlist_t *envlist, const char *env)
131{
132 struct envlist_entry *entry = NULL;
133 const char *eq_sign;
134 size_t envname_len;
135
136 if ((envlist == NULL) || (env == NULL))
137 return (EINVAL);
138
139
140 if ((eq_sign = strchr(env, '=')) == NULL)
141 return (EINVAL);
142 envname_len = eq_sign - env + 1;
143
144
145
146
147
148
149 for (entry = envlist->el_entries.lh_first; entry != NULL;
150 entry = entry->ev_link.le_next) {
151 if (strncmp(entry->ev_var, env, envname_len) == 0)
152 break;
153 }
154
155 if (entry != NULL) {
156 QLIST_REMOVE(entry, ev_link);
157 free((char *)entry->ev_var);
158 free(entry);
159 } else {
160 envlist->el_count++;
161 }
162
163 if ((entry = malloc(sizeof (*entry))) == NULL)
164 return (errno);
165 if ((entry->ev_var = strdup(env)) == NULL) {
166 free(entry);
167 return (errno);
168 }
169 QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
170
171 return (0);
172}
173
174
175
176
177
178int
179envlist_unsetenv(envlist_t *envlist, const char *env)
180{
181 struct envlist_entry *entry;
182 size_t envname_len;
183
184 if ((envlist == NULL) || (env == NULL))
185 return (EINVAL);
186
187
188 if (strchr(env, '=') != NULL)
189 return (EINVAL);
190
191
192
193
194
195 envname_len = strlen(env);
196 for (entry = envlist->el_entries.lh_first; entry != NULL;
197 entry = entry->ev_link.le_next) {
198 if (strncmp(entry->ev_var, env, envname_len) == 0)
199 break;
200 }
201 if (entry != NULL) {
202 QLIST_REMOVE(entry, ev_link);
203 free((char *)entry->ev_var);
204 free(entry);
205
206 envlist->el_count--;
207 }
208 return (0);
209}
210
211
212
213
214
215
216
217
218
219
220
221char **
222envlist_to_environ(const envlist_t *envlist, size_t *count)
223{
224 struct envlist_entry *entry;
225 char **env, **penv;
226
227 penv = env = malloc((envlist->el_count + 1) * sizeof (char *));
228 if (env == NULL)
229 return (NULL);
230
231 for (entry = envlist->el_entries.lh_first; entry != NULL;
232 entry = entry->ev_link.le_next) {
233 *(penv++) = strdup(entry->ev_var);
234 }
235 *penv = NULL;
236
237 if (count != NULL)
238 *count = envlist->el_count;
239
240 return (env);
241}
242