~ubuntu-branches/ubuntu/quantal/uclibc/quantal

« back to all changes in this revision

Viewing changes to libc/stdlib/setenv.c

  • Committer: Bazaar Package Importer
  • Author(s): Hector Oron
  • Date: 2011-06-11 03:06:20 UTC
  • mfrom: (1.1.3 upstream)
  • Revision ID: james.westby@ubuntu.com-20110611030620-ywjfvyuqvrpsm282
Tags: 0.9.32-1
* New upstream release
* Add myself as maintainer
* Bump standards version 
* Add Vcs-Git, Vcs-Browser and Homepage fields
* Add watch file 

Show diffs side-by-side

added added

removed removed

Lines of Context:
25
25
#include <string.h>
26
26
#include <unistd.h>
27
27
 
28
 
/* Experimentally off - libc_hidden_proto(memcpy) */
29
 
/* Experimentally off - libc_hidden_proto(strchr) */
30
 
/* Experimentally off - libc_hidden_proto(strlen) */
31
 
/* Experimentally off - libc_hidden_proto(strncmp) */
32
 
/* Experimentally off - libc_hidden_proto(strndup) */
33
 
libc_hidden_proto(unsetenv)
34
28
 
35
29
#include <bits/uClibc_mutex.h>
36
30
__UCLIBC_MUTEX_STATIC(mylock, PTHREAD_MUTEX_INITIALIZER);
46
40
   is then placed in the environment, while the argument of `putenv'
47
41
   must be used directly.  This is all complicated by the fact that we try
48
42
   to reuse values once generated for a `setenv' call since we can never
49
 
   free the strings.  */
50
 
int __add_to_environ (const char *name, const char *value,
51
 
        const char *combined, int replace) attribute_hidden;
52
 
int __add_to_environ (const char *name, const char *value,
53
 
                                          const char *combined, int replace)
 
43
   free the strings. [in uclibc, we do not]  */
 
44
static int __add_to_environ(const char *name, const char *value,
 
45
                int replace)
54
46
{
55
 
    register char **ep;
56
 
    register size_t size;
57
 
    const size_t namelen = strlen (name);
58
 
    const size_t vallen = value != NULL ? strlen (value) + 1 : 0;
59
 
    int rv = -1;
60
 
 
61
 
    __UCLIBC_MUTEX_LOCK(mylock);
62
 
 
63
 
    /* We have to get the pointer now that we have the lock and not earlier
64
 
       since another thread might have created a new environment.  */
65
 
    ep = __environ;
66
 
 
67
 
    size = 0;
68
 
    if (ep != NULL) {
69
 
                for (; *ep != NULL; ++ep) {
70
 
                        if (!strncmp (*ep, name, namelen) && (*ep)[namelen] == '=')
71
 
                                break;
72
 
                        else
73
 
                                ++size;
 
47
        register char **ep;
 
48
        register size_t size;
 
49
        char *var_val;
 
50
        char **new_environ;
 
51
        /* name may come from putenv() and thus may contain "=VAL" part */
 
52
        const size_t namelen = strchrnul(name, '=') - name;
 
53
        int rv = -1;
 
54
 
 
55
        __UCLIBC_MUTEX_LOCK(mylock);
 
56
 
 
57
        /* We have to get the pointer now that we have the lock and not earlier
 
58
           since another thread might have created a new environment.  */
 
59
        ep = __environ;
 
60
 
 
61
        size = 0;
 
62
        if (ep != NULL) {
 
63
                while (*ep != NULL) {
 
64
                        if (!strncmp(*ep, name, namelen) && (*ep)[namelen] == '=') {
 
65
                                /* Found */
 
66
                                if (!replace)
 
67
                                        goto DONE_OK;
 
68
                                goto REPLACE;
 
69
                        }
 
70
                        ++size;
 
71
                        ++ep;
74
72
                }
75
 
    }
76
 
 
77
 
    if (ep == NULL || *ep == NULL) {
78
 
                char **new_environ;
79
 
 
80
 
                /* We allocated this space; we can extend it.  */
81
 
                new_environ = (char **) realloc (last_environ, (size + 2) * sizeof (char *));
82
 
                if (new_environ == NULL) {
 
73
        }
 
74
 
 
75
        /* Not found, add at the end */
 
76
 
 
77
        /* We allocated this space; we can extend it.  */
 
78
        new_environ = realloc(last_environ, (size + 2) * sizeof(char *));
 
79
        if (new_environ == NULL) {
 
80
                __set_errno(ENOMEM);
 
81
                goto DONE;
 
82
        }
 
83
        if (__environ != last_environ) {
 
84
                memcpy(new_environ, __environ, size * sizeof(char *));
 
85
        }
 
86
        last_environ = __environ = new_environ;
 
87
 
 
88
        ep = &new_environ[size];
 
89
        /* Ensure env is NULL terminated in case malloc below fails */
 
90
        ep[0] = NULL;
 
91
        ep[1] = NULL;
 
92
 
 
93
 REPLACE:
 
94
        var_val = (char*) name;
 
95
        /* Build VAR=VAL if we called by setenv, not putenv.  */
 
96
        if (value != NULL) {
 
97
                const size_t vallen = strlen(value) + 1;
 
98
 
 
99
                var_val = malloc(namelen + 1 + vallen);
 
100
                if (var_val == NULL) {
 
101
                        __set_errno(ENOMEM);
83
102
                        goto DONE;
84
103
                }
85
 
 
86
 
                /* If the whole entry is given add it.  */
87
 
                if (combined != NULL) {
88
 
                        /* We must not add the string to the search tree since it belongs
89
 
                           to the user.  */
90
 
                        new_environ[size] = (char *) combined;
91
 
                } else {
92
 
                        /* See whether the value is already known.  */
93
 
                        new_environ[size] = (char *) malloc (namelen + 1 + vallen);
94
 
                        if (new_environ[size] == NULL) {
95
 
                                __set_errno (ENOMEM);
96
 
                                goto DONE;
97
 
                        }
98
 
 
99
 
                        memcpy (new_environ[size], name, namelen);
100
 
                        new_environ[size][namelen] = '=';
101
 
                        memcpy (&new_environ[size][namelen + 1], value, vallen);
102
 
                }
103
 
 
104
 
                if (__environ != last_environ) {
105
 
                        memcpy ((char *) new_environ, (char *) __environ,
106
 
                                        size * sizeof (char *));
107
 
                }
108
 
 
109
 
                new_environ[size + 1] = NULL;
110
 
                last_environ = __environ = new_environ;
111
 
    } else if (replace) {
112
 
                char *np;
113
 
 
114
 
                /* Use the user string if given.  */
115
 
                if (combined != NULL) {
116
 
                        np = (char *) combined;
117
 
                } else {
118
 
                        np = malloc (namelen + 1 + vallen);
119
 
                        if (np == NULL) {
120
 
                                goto DONE;
121
 
                        }
122
 
                        memcpy (np, name, namelen);
123
 
                        np[namelen] = '=';
124
 
                        memcpy (&np[namelen + 1], value, vallen);
125
 
                }
126
 
                *ep = np;
127
 
    }
128
 
 
129
 
    rv = 0;
 
104
                memcpy(var_val, name, namelen);
 
105
                var_val[namelen] = '=';
 
106
                memcpy(&var_val[namelen + 1], value, vallen);
 
107
        }
 
108
        *ep = var_val;
 
109
 
 
110
 DONE_OK:
 
111
        rv = 0;
130
112
 
131
113
 DONE:
132
 
    __UCLIBC_MUTEX_UNLOCK(mylock);
133
 
    return rv;
 
114
        __UCLIBC_MUTEX_UNLOCK(mylock);
 
115
        return rv;
134
116
}
135
117
 
136
 
libc_hidden_proto(setenv)
137
 
int setenv (const char *name, const char *value, int replace)
 
118
int setenv(const char *name, const char *value, int replace)
138
119
{
139
 
    return __add_to_environ (name, value, NULL, replace);
 
120
        /* NB: setenv("VAR", NULL, 1) inserts "VAR=" string */
 
121
        return __add_to_environ(name, value ? value : "", replace);
140
122
}
141
123
libc_hidden_def(setenv)
142
124
 
143
 
libc_hidden_proto(unsetenv)
144
 
int unsetenv (const char *name)
 
125
int unsetenv(const char *name)
145
126
{
146
 
    size_t len;
147
 
    char **ep;
 
127
        const char *eq;
 
128
        size_t len;
 
129
        char **ep;
148
130
 
149
 
    if (name == NULL || *name == '\0' || strchr (name, '=') != NULL) {
150
 
                __set_errno (EINVAL);
 
131
        if (name == NULL || *name == '\0'
 
132
         || *(eq = strchrnul(name, '=')) == '='
 
133
        ) {
 
134
                __set_errno(EINVAL);
151
135
                return -1;
152
 
    }
 
136
        }
 
137
        len = eq - name; /* avoiding strlen this way */
153
138
 
154
 
    len = strlen (name);
155
 
    __UCLIBC_MUTEX_LOCK(mylock);
156
 
    ep = __environ;
157
 
    while (*ep != NULL) {
158
 
                if (!strncmp (*ep, name, len) && (*ep)[len] == '=') {
 
139
        __UCLIBC_MUTEX_LOCK(mylock);
 
140
        ep = __environ;
 
141
        /* NB: clearenv(); unsetenv("foo"); should not segfault */
 
142
        if (ep) while (*ep != NULL) {
 
143
                if (!strncmp(*ep, name, len) && (*ep)[len] == '=') {
159
144
                        /* Found it.  Remove this pointer by moving later ones back.  */
160
145
                        char **dp = ep;
161
146
                        do {
165
150
                } else {
166
151
                        ++ep;
167
152
                }
168
 
    }
169
 
    __UCLIBC_MUTEX_UNLOCK(mylock);
170
 
    return 0;
 
153
        }
 
154
        __UCLIBC_MUTEX_UNLOCK(mylock);
 
155
        return 0;
171
156
}
172
157
libc_hidden_def(unsetenv)
173
158
 
174
159
/* The `clearenv' was planned to be added to POSIX.1 but probably
175
160
   never made it.  Nevertheless the POSIX.9 standard (POSIX bindings
176
161
   for Fortran 77) requires this function.  */
177
 
int clearenv (void)
 
162
int clearenv(void)
178
163
{
179
 
    __UCLIBC_MUTEX_LOCK(mylock);
180
 
    if (__environ == last_environ && __environ != NULL) {
181
 
                /* We allocated this environment so we can free it.  */
182
 
                free (__environ);
183
 
                last_environ = NULL;
184
 
    }
185
 
    /* Clear the environment pointer removes the whole environment.  */
186
 
    __environ = NULL;
187
 
    __UCLIBC_MUTEX_UNLOCK(mylock);
188
 
    return 0;
 
164
        __UCLIBC_MUTEX_LOCK(mylock);
 
165
        /* If we allocated this environment we can free it.
 
166
         * If we did not allocate this environment, it's NULL already
 
167
         * and is safe to free().  */
 
168
        free(last_environ);
 
169
        last_environ = NULL;
 
170
        /* Clearing environ removes the whole environment.  */
 
171
        __environ = NULL;
 
172
        __UCLIBC_MUTEX_UNLOCK(mylock);
 
173
        return 0;
189
174
}
190
175
 
191
176
/* Put STRING, which is of the form "NAME=VALUE", in the environment.  */
192
 
int putenv (char *string)
 
177
int putenv(char *string)
193
178
{
194
 
    int result;
195
 
    const char *const name_end = strchr (string, '=');
196
 
 
197
 
    if (name_end != NULL) {
198
 
                char *name = strndup(string, name_end - string);
199
 
                result = __add_to_environ (name, NULL, string, 1);
200
 
                free(name);
201
 
                return(result);
202
 
    }
203
 
    unsetenv (string);
204
 
    return 0;
 
179
        if (strchr(string, '=') != NULL) {
 
180
                return __add_to_environ(string, NULL, 1);
 
181
        }
 
182
        return unsetenv(string);
205
183
}
206