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