qemu

Форк
0
/
envlist.c 
232 строки · 5.4 Кб
1
#include "qemu/osdep.h"
2
#include "qemu/queue.h"
3
#include "qemu/envlist.h"
4

5
struct envlist_entry {
6
    const char *ev_var;            /* actual env value */
7
    QLIST_ENTRY(envlist_entry) ev_link;
8
};
9

10
struct envlist {
11
    QLIST_HEAD(, envlist_entry) el_entries; /* actual entries */
12
    size_t el_count;                        /* number of entries */
13
};
14

15
static int envlist_parse(envlist_t *envlist,
16
    const char *env, int (*)(envlist_t *, const char *));
17

18
/*
19
 * Allocates new envlist and returns pointer to it.
20
 */
21
envlist_t *
22
envlist_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
 * Releases given envlist and its entries.
36
 */
37
void
38
envlist_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
 * Parses comma separated list of set/modify environment
56
 * variable entries and updates given enlist accordingly.
57
 *
58
 * For example:
59
 *     envlist_parse(el, "HOME=foo,SHELL=/bin/sh");
60
 *
61
 * inserts/sets environment variables HOME and SHELL.
62
 *
63
 * Returns 0 on success, errno otherwise.
64
 */
65
int
66
envlist_parse_set(envlist_t *envlist, const char *env)
67
{
68
    return (envlist_parse(envlist, env, &envlist_setenv));
69
}
70

71
/*
72
 * Parses comma separated list of unset environment variable
73
 * entries and removes given variables from given envlist.
74
 *
75
 * Returns 0 on success, errno otherwise.
76
 */
77
int
78
envlist_parse_unset(envlist_t *envlist, const char *env)
79
{
80
    return (envlist_parse(envlist, env, &envlist_unsetenv));
81
}
82

83
/*
84
 * Parses comma separated list of set, modify or unset entries
85
 * and calls given callback for each entry.
86
 *
87
 * Returns 0 in case of success, errno otherwise.
88
 */
89
static int
90
envlist_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
 * Sets environment value to envlist in similar manner
122
 * than putenv(3).
123
 *
124
 * Returns 0 in success, errno otherwise.
125
 */
126
int
127
envlist_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
    /* 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;
140

141
    /*
142
     * If there already exists variable with given name
143
     * we remove and release it before allocating a whole
144
     * new entry.
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
 * Removes given env value from envlist in similar manner
169
 * than unsetenv(3).  Returns 0 in success, errno otherwise.
170
 */
171
int
172
envlist_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
    /* env is not allowed to contain '=' */
181
    if (strchr(env, '=') != NULL)
182
        return (EINVAL);
183

184
    /*
185
     * Find out the requested entry and remove
186
     * it from the list.
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
 * 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).
210
 *
211
 * If caller provides count pointer, number of items in array is
212
 * stored there.
213
 */
214
char **
215
envlist_to_environ(const envlist_t *envlist, size_t *count)
216
{
217
    struct envlist_entry *entry;
218
    char **env, **penv;
219

220
    penv = env = g_new(char *, envlist->el_count + 1);
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; /* NULL terminate the list */
227

228
    if (count != NULL)
229
        *count = envlist->el_count;
230

231
    return (env);
232
}
233

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.