Merge tag 'v9.0.0-rc3'
[qemu/ar7.git] / util / envlist.c
blobdb937c04276110db06144132bd3caa2fff398dc7
1 #include "qemu/osdep.h"
2 #include "qemu/queue.h"
3 #include "qemu/envlist.h"
5 struct envlist_entry {
6 const char *ev_var; /* actual env value */
7 QLIST_ENTRY(envlist_entry) ev_link;
8 };
10 struct envlist {
11 QLIST_HEAD(, envlist_entry) el_entries; /* actual entries */
12 size_t el_count; /* number of entries */
15 static int envlist_parse(envlist_t *envlist,
16 const char *env, int (*)(envlist_t *, const char *));
19 * Allocates new envlist and returns pointer to it.
21 envlist_t *
22 envlist_create(void)
24 envlist_t *envlist;
26 envlist = g_malloc(sizeof(*envlist));
28 QLIST_INIT(&envlist->el_entries);
29 envlist->el_count = 0;
31 return (envlist);
35 * Releases given envlist and its entries.
37 void
38 envlist_free(envlist_t *envlist)
40 struct envlist_entry *entry;
42 assert(envlist != NULL);
44 while (envlist->el_entries.lh_first != NULL) {
45 entry = envlist->el_entries.lh_first;
46 QLIST_REMOVE(entry, ev_link);
48 g_free((char *)entry->ev_var);
49 g_free(entry);
51 g_free(envlist);
55 * Parses comma separated list of set/modify environment
56 * variable entries and updates given enlist accordingly.
58 * For example:
59 * envlist_parse(el, "HOME=foo,SHELL=/bin/sh");
61 * inserts/sets environment variables HOME and SHELL.
63 * Returns 0 on success, errno otherwise.
65 int
66 envlist_parse_set(envlist_t *envlist, const char *env)
68 return (envlist_parse(envlist, env, &envlist_setenv));
72 * Parses comma separated list of unset environment variable
73 * entries and removes given variables from given envlist.
75 * Returns 0 on success, errno otherwise.
77 int
78 envlist_parse_unset(envlist_t *envlist, const char *env)
80 return (envlist_parse(envlist, env, &envlist_unsetenv));
84 * Parses comma separated list of set, modify or unset entries
85 * and calls given callback for each entry.
87 * Returns 0 in case of success, errno otherwise.
89 static int
90 envlist_parse(envlist_t *envlist, const char *env,
91 int (*callback)(envlist_t *, const char *))
93 char *tmpenv, *envvar;
94 char *envsave = NULL;
95 int ret = 0;
96 assert(callback != NULL);
98 if ((envlist == NULL) || (env == NULL))
99 return (EINVAL);
101 tmpenv = g_strdup(env);
102 envsave = tmpenv;
104 do {
105 envvar = strchr(tmpenv, ',');
106 if (envvar != NULL) {
107 *envvar = '\0';
109 if ((*callback)(envlist, tmpenv) != 0) {
110 ret = errno;
111 break;
113 tmpenv = envvar + 1;
114 } while (envvar != NULL);
116 g_free(envsave);
117 return ret;
121 * Sets environment value to envlist in similar manner
122 * than putenv(3).
124 * Returns 0 in success, errno otherwise.
127 envlist_setenv(envlist_t *envlist, const char *env)
129 struct envlist_entry *entry = NULL;
130 const char *eq_sign;
131 size_t envname_len;
133 if ((envlist == NULL) || (env == NULL))
134 return (EINVAL);
136 /* find out first equals sign in given env */
137 if ((eq_sign = strchr(env, '=')) == NULL)
138 return (EINVAL);
139 envname_len = eq_sign - env + 1;
142 * If there already exists variable with given name
143 * we remove and release it before allocating a whole
144 * new entry.
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;
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++;
160 entry = g_malloc(sizeof(*entry));
161 entry->ev_var = g_strdup(env);
162 QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
164 return (0);
168 * Removes given env value from envlist in similar manner
169 * than unsetenv(3). Returns 0 in success, errno otherwise.
172 envlist_unsetenv(envlist_t *envlist, const char *env)
174 struct envlist_entry *entry;
175 size_t envname_len;
177 if ((envlist == NULL) || (env == NULL))
178 return (EINVAL);
180 /* env is not allowed to contain '=' */
181 if (strchr(env, '=') != NULL)
182 return (EINVAL);
185 * Find out the requested entry and remove
186 * it from the list.
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;
194 if (entry != NULL) {
195 QLIST_REMOVE(entry, ev_link);
196 g_free((char *)entry->ev_var);
197 g_free(entry);
199 envlist->el_count--;
201 return (0);
205 * Returns given envlist as array of strings (in same form that
206 * global variable environ is). Caller must free returned memory
207 * by calling g_free for each element and the array.
208 * Returned array and given envlist are not related (no common
209 * references).
211 * If caller provides count pointer, number of items in array is
212 * stored there.
214 char **
215 envlist_to_environ(const envlist_t *envlist, size_t *count)
217 struct envlist_entry *entry;
218 char **env, **penv;
220 penv = env = g_new(char *, envlist->el_count + 1);
222 for (entry = envlist->el_entries.lh_first; entry != NULL;
223 entry = entry->ev_link.le_next) {
224 *(penv++) = g_strdup(entry->ev_var);
226 *penv = NULL; /* NULL terminate the list */
228 if (count != NULL)
229 *count = envlist->el_count;
231 return (env);