Merge tag 'pull-loongarch-20241016' of https://gitlab.com/gaosong/qemu into staging
[qemu/armbru.git] / util / envlist.c
blob15fdbb109d66273d7b98151f86648654598faa94
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 */
16 * Allocates new envlist and returns pointer to it.
18 envlist_t *
19 envlist_create(void)
21 envlist_t *envlist;
23 envlist = g_malloc(sizeof(*envlist));
25 QLIST_INIT(&envlist->el_entries);
26 envlist->el_count = 0;
28 return (envlist);
32 * Releases given envlist and its entries.
34 void
35 envlist_free(envlist_t *envlist)
37 struct envlist_entry *entry;
39 assert(envlist != NULL);
41 while (envlist->el_entries.lh_first != NULL) {
42 entry = envlist->el_entries.lh_first;
43 QLIST_REMOVE(entry, ev_link);
45 g_free((char *)entry->ev_var);
46 g_free(entry);
48 g_free(envlist);
52 * Sets environment value to envlist in similar manner
53 * than putenv(3).
55 * Returns 0 in success, errno otherwise.
57 int
58 envlist_setenv(envlist_t *envlist, const char *env)
60 struct envlist_entry *entry = NULL;
61 const char *eq_sign;
62 size_t envname_len;
64 if ((envlist == NULL) || (env == NULL))
65 return (EINVAL);
67 /* find out first equals sign in given env */
68 if ((eq_sign = strchr(env, '=')) == NULL)
69 return (EINVAL);
70 envname_len = eq_sign - env + 1;
73 * If there already exists variable with given name
74 * we remove and release it before allocating a whole
75 * new entry.
77 for (entry = envlist->el_entries.lh_first; entry != NULL;
78 entry = entry->ev_link.le_next) {
79 if (strncmp(entry->ev_var, env, envname_len) == 0)
80 break;
83 if (entry != NULL) {
84 QLIST_REMOVE(entry, ev_link);
85 g_free((char *)entry->ev_var);
86 g_free(entry);
87 } else {
88 envlist->el_count++;
91 entry = g_malloc(sizeof(*entry));
92 entry->ev_var = g_strdup(env);
93 QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
95 return (0);
99 * Removes given env value from envlist in similar manner
100 * than unsetenv(3). Returns 0 in success, errno otherwise.
103 envlist_unsetenv(envlist_t *envlist, const char *env)
105 struct envlist_entry *entry;
106 size_t envname_len;
108 if ((envlist == NULL) || (env == NULL))
109 return (EINVAL);
111 /* env is not allowed to contain '=' */
112 if (strchr(env, '=') != NULL)
113 return (EINVAL);
116 * Find out the requested entry and remove
117 * it from the list.
119 envname_len = strlen(env);
120 for (entry = envlist->el_entries.lh_first; entry != NULL;
121 entry = entry->ev_link.le_next) {
122 if (strncmp(entry->ev_var, env, envname_len) == 0)
123 break;
125 if (entry != NULL) {
126 QLIST_REMOVE(entry, ev_link);
127 g_free((char *)entry->ev_var);
128 g_free(entry);
130 envlist->el_count--;
132 return (0);
136 * Returns given envlist as array of strings (in same form that
137 * global variable environ is). Caller must free returned memory
138 * by calling g_free for each element and the array.
139 * Returned array and given envlist are not related (no common
140 * references).
142 * If caller provides count pointer, number of items in array is
143 * stored there.
145 char **
146 envlist_to_environ(const envlist_t *envlist, size_t *count)
148 struct envlist_entry *entry;
149 char **env, **penv;
151 penv = env = g_new(char *, envlist->el_count + 1);
153 for (entry = envlist->el_entries.lh_first; entry != NULL;
154 entry = entry->ev_link.le_next) {
155 *(penv++) = g_strdup(entry->ev_var);
157 *penv = NULL; /* NULL terminate the list */
159 if (count != NULL)
160 *count = envlist->el_count;
162 return (env);