xref: /openbmc/qemu/util/envlist.c (revision a53b931645183bd0c15dd19ae0708fc3c81ecf1d)
1aafd7584SPeter Maydell #include "qemu/osdep.h"
2baacf047SPaolo Bonzini #include "qemu/queue.h"
3baacf047SPaolo Bonzini #include "qemu/envlist.h"
4baacf047SPaolo Bonzini 
5baacf047SPaolo Bonzini struct envlist_entry {
6baacf047SPaolo Bonzini     const char *ev_var;            /* actual env value */
7baacf047SPaolo Bonzini     QLIST_ENTRY(envlist_entry) ev_link;
8baacf047SPaolo Bonzini };
9baacf047SPaolo Bonzini 
10baacf047SPaolo Bonzini struct envlist {
11baacf047SPaolo Bonzini     QLIST_HEAD(, envlist_entry) el_entries; /* actual entries */
12baacf047SPaolo Bonzini     size_t el_count;                        /* number of entries */
13baacf047SPaolo Bonzini };
14baacf047SPaolo Bonzini 
15baacf047SPaolo Bonzini /*
16ec45bbe5SSaurav Sachidanand  * Allocates new envlist and returns pointer to it.
17baacf047SPaolo Bonzini  */
18baacf047SPaolo Bonzini envlist_t *
envlist_create(void)19baacf047SPaolo Bonzini envlist_create(void)
20baacf047SPaolo Bonzini {
21baacf047SPaolo Bonzini     envlist_t *envlist;
22baacf047SPaolo Bonzini 
23ec45bbe5SSaurav Sachidanand     envlist = g_malloc(sizeof(*envlist));
24baacf047SPaolo Bonzini 
25baacf047SPaolo Bonzini     QLIST_INIT(&envlist->el_entries);
26baacf047SPaolo Bonzini     envlist->el_count = 0;
27baacf047SPaolo Bonzini 
28baacf047SPaolo Bonzini     return (envlist);
29baacf047SPaolo Bonzini }
30baacf047SPaolo Bonzini 
31baacf047SPaolo Bonzini /*
32baacf047SPaolo Bonzini  * Releases given envlist and its entries.
33baacf047SPaolo Bonzini  */
34baacf047SPaolo Bonzini void
envlist_free(envlist_t * envlist)35baacf047SPaolo Bonzini envlist_free(envlist_t *envlist)
36baacf047SPaolo Bonzini {
37baacf047SPaolo Bonzini     struct envlist_entry *entry;
38baacf047SPaolo Bonzini 
39baacf047SPaolo Bonzini     assert(envlist != NULL);
40baacf047SPaolo Bonzini 
41baacf047SPaolo Bonzini     while (envlist->el_entries.lh_first != NULL) {
42baacf047SPaolo Bonzini         entry = envlist->el_entries.lh_first;
43baacf047SPaolo Bonzini         QLIST_REMOVE(entry, ev_link);
44baacf047SPaolo Bonzini 
45ec45bbe5SSaurav Sachidanand         g_free((char *)entry->ev_var);
46ec45bbe5SSaurav Sachidanand         g_free(entry);
47baacf047SPaolo Bonzini     }
48ec45bbe5SSaurav Sachidanand     g_free(envlist);
49baacf047SPaolo Bonzini }
50baacf047SPaolo Bonzini 
51baacf047SPaolo Bonzini /*
52baacf047SPaolo Bonzini  * Sets environment value to envlist in similar manner
53baacf047SPaolo Bonzini  * than putenv(3).
54baacf047SPaolo Bonzini  *
55baacf047SPaolo Bonzini  * Returns 0 in success, errno otherwise.
56baacf047SPaolo Bonzini  */
57baacf047SPaolo Bonzini int
envlist_setenv(envlist_t * envlist,const char * env)58baacf047SPaolo Bonzini envlist_setenv(envlist_t *envlist, const char *env)
59baacf047SPaolo Bonzini {
60baacf047SPaolo Bonzini     struct envlist_entry *entry = NULL;
61baacf047SPaolo Bonzini     const char *eq_sign;
62baacf047SPaolo Bonzini     size_t envname_len;
63baacf047SPaolo Bonzini 
64baacf047SPaolo Bonzini     if ((envlist == NULL) || (env == NULL))
65baacf047SPaolo Bonzini         return (EINVAL);
66baacf047SPaolo Bonzini 
67baacf047SPaolo Bonzini     /* find out first equals sign in given env */
68baacf047SPaolo Bonzini     if ((eq_sign = strchr(env, '=')) == NULL)
69baacf047SPaolo Bonzini         return (EINVAL);
70baacf047SPaolo Bonzini     envname_len = eq_sign - env + 1;
71baacf047SPaolo Bonzini 
72baacf047SPaolo Bonzini     /*
73baacf047SPaolo Bonzini      * If there already exists variable with given name
74baacf047SPaolo Bonzini      * we remove and release it before allocating a whole
75baacf047SPaolo Bonzini      * new entry.
76baacf047SPaolo Bonzini      */
77baacf047SPaolo Bonzini     for (entry = envlist->el_entries.lh_first; entry != NULL;
78baacf047SPaolo Bonzini         entry = entry->ev_link.le_next) {
79baacf047SPaolo Bonzini         if (strncmp(entry->ev_var, env, envname_len) == 0)
80baacf047SPaolo Bonzini             break;
81baacf047SPaolo Bonzini     }
82baacf047SPaolo Bonzini 
83baacf047SPaolo Bonzini     if (entry != NULL) {
84baacf047SPaolo Bonzini         QLIST_REMOVE(entry, ev_link);
85ec45bbe5SSaurav Sachidanand         g_free((char *)entry->ev_var);
86ec45bbe5SSaurav Sachidanand         g_free(entry);
87baacf047SPaolo Bonzini     } else {
88baacf047SPaolo Bonzini         envlist->el_count++;
89baacf047SPaolo Bonzini     }
90baacf047SPaolo Bonzini 
91ec45bbe5SSaurav Sachidanand     entry = g_malloc(sizeof(*entry));
92ec45bbe5SSaurav Sachidanand     entry->ev_var = g_strdup(env);
93baacf047SPaolo Bonzini     QLIST_INSERT_HEAD(&envlist->el_entries, entry, ev_link);
94baacf047SPaolo Bonzini 
95baacf047SPaolo Bonzini     return (0);
96baacf047SPaolo Bonzini }
97baacf047SPaolo Bonzini 
98baacf047SPaolo Bonzini /*
99baacf047SPaolo Bonzini  * Removes given env value from envlist in similar manner
100baacf047SPaolo Bonzini  * than unsetenv(3).  Returns 0 in success, errno otherwise.
101baacf047SPaolo Bonzini  */
102baacf047SPaolo Bonzini int
envlist_unsetenv(envlist_t * envlist,const char * env)103baacf047SPaolo Bonzini envlist_unsetenv(envlist_t *envlist, const char *env)
104baacf047SPaolo Bonzini {
105baacf047SPaolo Bonzini     struct envlist_entry *entry;
106baacf047SPaolo Bonzini     size_t envname_len;
107baacf047SPaolo Bonzini 
108baacf047SPaolo Bonzini     if ((envlist == NULL) || (env == NULL))
109baacf047SPaolo Bonzini         return (EINVAL);
110baacf047SPaolo Bonzini 
111baacf047SPaolo Bonzini     /* env is not allowed to contain '=' */
112baacf047SPaolo Bonzini     if (strchr(env, '=') != NULL)
113baacf047SPaolo Bonzini         return (EINVAL);
114baacf047SPaolo Bonzini 
115baacf047SPaolo Bonzini     /*
116baacf047SPaolo Bonzini      * Find out the requested entry and remove
117baacf047SPaolo Bonzini      * it from the list.
118baacf047SPaolo Bonzini      */
119baacf047SPaolo Bonzini     envname_len = strlen(env);
120baacf047SPaolo Bonzini     for (entry = envlist->el_entries.lh_first; entry != NULL;
121baacf047SPaolo Bonzini         entry = entry->ev_link.le_next) {
122baacf047SPaolo Bonzini         if (strncmp(entry->ev_var, env, envname_len) == 0)
123baacf047SPaolo Bonzini             break;
124baacf047SPaolo Bonzini     }
125baacf047SPaolo Bonzini     if (entry != NULL) {
126baacf047SPaolo Bonzini         QLIST_REMOVE(entry, ev_link);
127ec45bbe5SSaurav Sachidanand         g_free((char *)entry->ev_var);
128ec45bbe5SSaurav Sachidanand         g_free(entry);
129baacf047SPaolo Bonzini 
130baacf047SPaolo Bonzini         envlist->el_count--;
131baacf047SPaolo Bonzini     }
132baacf047SPaolo Bonzini     return (0);
133baacf047SPaolo Bonzini }
134baacf047SPaolo Bonzini 
135baacf047SPaolo Bonzini /*
136baacf047SPaolo Bonzini  * Returns given envlist as array of strings (in same form that
137baacf047SPaolo Bonzini  * global variable environ is).  Caller must free returned memory
138ec45bbe5SSaurav Sachidanand  * by calling g_free for each element and the array.
139ec45bbe5SSaurav Sachidanand  * Returned array and given envlist are not related (no common
140ec45bbe5SSaurav Sachidanand  * references).
141baacf047SPaolo Bonzini  *
142baacf047SPaolo Bonzini  * If caller provides count pointer, number of items in array is
143ec45bbe5SSaurav Sachidanand  * stored there.
144baacf047SPaolo Bonzini  */
145baacf047SPaolo Bonzini char **
envlist_to_environ(const envlist_t * envlist,size_t * count)146baacf047SPaolo Bonzini envlist_to_environ(const envlist_t *envlist, size_t *count)
147baacf047SPaolo Bonzini {
148baacf047SPaolo Bonzini     struct envlist_entry *entry;
149baacf047SPaolo Bonzini     char **env, **penv;
150baacf047SPaolo Bonzini 
151*b21e2380SMarkus Armbruster     penv = env = g_new(char *, envlist->el_count + 1);
152baacf047SPaolo Bonzini 
153baacf047SPaolo Bonzini     for (entry = envlist->el_entries.lh_first; entry != NULL;
154baacf047SPaolo Bonzini         entry = entry->ev_link.le_next) {
155ec45bbe5SSaurav Sachidanand         *(penv++) = g_strdup(entry->ev_var);
156baacf047SPaolo Bonzini     }
157baacf047SPaolo Bonzini     *penv = NULL; /* NULL terminate the list */
158baacf047SPaolo Bonzini 
159baacf047SPaolo Bonzini     if (count != NULL)
160baacf047SPaolo Bonzini         *count = envlist->el_count;
161baacf047SPaolo Bonzini 
162baacf047SPaolo Bonzini     return (env);
163baacf047SPaolo Bonzini }
164