OSDN Git Service

target/openrisc: Reorg tlb lookup
[qmiga/qemu.git] / util / envlist.c
1 #include "qemu/osdep.h"
2 #include "qemu-common.h"
3 #include "qemu/queue.h"
4 #include "qemu/envlist.h"
5
6 struct envlist_entry {
7         const char *ev_var;                     /* actual env value */
8         QLIST_ENTRY(envlist_entry) ev_link;
9 };
10
11 struct envlist {
12         QLIST_HEAD(, envlist_entry) el_entries; /* actual entries */
13         size_t el_count;                        /* number of entries */
14 };
15
16 static int envlist_parse(envlist_t *envlist,
17     const char *env, int (*)(envlist_t *, const char *));
18
19 /*
20  * Allocates new envlist and returns pointer to it.
21  */
22 envlist_t *
23 envlist_create(void)
24 {
25         envlist_t *envlist;
26
27         envlist = g_malloc(sizeof(*envlist));
28
29         QLIST_INIT(&envlist->el_entries);
30         envlist->el_count = 0;
31
32         return (envlist);
33 }
34
35 /*
36  * Releases given envlist and its entries.
37  */
38 void
39 envlist_free(envlist_t *envlist)
40 {
41         struct envlist_entry *entry;
42
43         assert(envlist != NULL);
44
45         while (envlist->el_entries.lh_first != NULL) {
46                 entry = envlist->el_entries.lh_first;
47                 QLIST_REMOVE(entry, ev_link);
48
49                 g_free((char *)entry->ev_var);
50                 g_free(entry);
51         }
52         g_free(envlist);
53 }
54
55 /*
56  * Parses comma separated list of set/modify environment
57  * variable entries and updates given enlist accordingly.
58  *
59  * For example:
60  *     envlist_parse(el, "HOME=foo,SHELL=/bin/sh");
61  *
62  * inserts/sets environment variables HOME and SHELL.
63  *
64  * Returns 0 on success, errno otherwise.
65  */
66 int
67 envlist_parse_set(envlist_t *envlist, const char *env)
68 {
69         return (envlist_parse(envlist, env, &envlist_setenv));
70 }
71
72 /*
73  * Parses comma separated list of unset environment variable
74  * entries and removes given variables from given envlist.
75  *
76  * Returns 0 on success, errno otherwise.
77  */
78 int
79 envlist_parse_unset(envlist_t *envlist, const char *env)
80 {
81         return (envlist_parse(envlist, env, &envlist_unsetenv));
82 }
83
84 /*
85  * Parses comma separated list of set, modify or unset entries
86  * and calls given callback for each entry.
87  *
88  * Returns 0 in case of success, errno otherwise.
89  */
90 static int
91 envlist_parse(envlist_t *envlist, const char *env,
92     int (*callback)(envlist_t *, const char *))
93 {
94         char *tmpenv, *envvar;
95         char *envsave = NULL;
96     int ret = 0;
97     assert(callback != NULL);
98
99         if ((envlist == NULL) || (env == NULL))
100                 return (EINVAL);
101
102         tmpenv = g_strdup(env);
103     envsave = tmpenv;
104
105     do {
106         envvar = strchr(tmpenv, ',');
107         if (envvar != NULL) {
108             *envvar = '\0';
109         }
110         if ((*callback)(envlist, tmpenv) != 0) {
111             ret = errno;
112             break;
113                 }
114         tmpenv = envvar + 1;
115     } while (envvar != NULL);
116
117     g_free(envsave);
118     return ret;
119 }
120
121 /*
122  * Sets environment value to envlist in similar manner
123  * than putenv(3).
124  *
125  * Returns 0 in success, errno otherwise.
126  */
127 int
128 envlist_setenv(envlist_t *envlist, const char *env)
129 {
130         struct envlist_entry *entry = NULL;
131         const char *eq_sign;
132         size_t envname_len;
133
134         if ((envlist == NULL) || (env == NULL))
135                 return (EINVAL);
136
137         /* find out first equals sign in given env */
138         if ((eq_sign = strchr(env, '=')) == NULL)
139                 return (EINVAL);
140         envname_len = eq_sign - env + 1;
141
142         /*
143          * If there already exists variable with given name
144          * we remove and release it before allocating a whole
145          * new entry.
146          */
147         for (entry = envlist->el_entries.lh_first; entry != NULL;
148             entry = entry->ev_link.le_next) {
149                 if (strncmp(entry->ev_var, env, envname_len) == 0)
150                         break;
151         }
152
153         if (entry != NULL) {
154                 QLIST_REMOVE(entry, ev_link);
155                 g_free((char *)entry->ev_var);
156                 g_free(entry);
157         } else {
158                 envlist->el_count++;
159         }
160
161         entry = g_malloc(sizeof(*entry));
162         entry->ev_var = g_strdup(env);
163         QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
164
165         return (0);
166 }
167
168 /*
169  * Removes given env value from envlist in similar manner
170  * than unsetenv(3).  Returns 0 in success, errno otherwise.
171  */
172 int
173 envlist_unsetenv(envlist_t *envlist, const char *env)
174 {
175         struct envlist_entry *entry;
176         size_t envname_len;
177
178         if ((envlist == NULL) || (env == NULL))
179                 return (EINVAL);
180
181         /* env is not allowed to contain '=' */
182         if (strchr(env, '=') != NULL)
183                 return (EINVAL);
184
185         /*
186          * Find out the requested entry and remove
187          * it from the list.
188          */
189         envname_len = strlen(env);
190         for (entry = envlist->el_entries.lh_first; entry != NULL;
191             entry = entry->ev_link.le_next) {
192                 if (strncmp(entry->ev_var, env, envname_len) == 0)
193                         break;
194         }
195         if (entry != NULL) {
196                 QLIST_REMOVE(entry, ev_link);
197                 g_free((char *)entry->ev_var);
198                 g_free(entry);
199
200                 envlist->el_count--;
201         }
202         return (0);
203 }
204
205 /*
206  * Returns given envlist as array of strings (in same form that
207  * global variable environ is).  Caller must free returned memory
208  * by calling g_free for each element and the array.
209  * Returned array and given envlist are not related (no common
210  * references).
211  *
212  * If caller provides count pointer, number of items in array is
213  * stored there.
214  */
215 char **
216 envlist_to_environ(const envlist_t *envlist, size_t *count)
217 {
218         struct envlist_entry *entry;
219         char **env, **penv;
220
221         penv = env = g_malloc((envlist->el_count + 1) * sizeof(char *));
222
223         for (entry = envlist->el_entries.lh_first; entry != NULL;
224             entry = entry->ev_link.le_next) {
225                 *(penv++) = g_strdup(entry->ev_var);
226         }
227         *penv = NULL; /* NULL terminate the list */
228
229         if (count != NULL)
230                 *count = envlist->el_count;
231
232         return (env);
233 }