1*0d943ef0Sguenther /* $OpenBSD: setenv.c,v 1.16 2015/09/13 08:31:47 guenther Exp $ */ 2df930be7Sderaadt /* 3df930be7Sderaadt * Copyright (c) 1987 Regents of the University of California. 4df930be7Sderaadt * All rights reserved. 5df930be7Sderaadt * 6df930be7Sderaadt * Redistribution and use in source and binary forms, with or without 7df930be7Sderaadt * modification, are permitted provided that the following conditions 8df930be7Sderaadt * are met: 9df930be7Sderaadt * 1. Redistributions of source code must retain the above copyright 10df930be7Sderaadt * notice, this list of conditions and the following disclaimer. 11df930be7Sderaadt * 2. Redistributions in binary form must reproduce the above copyright 12df930be7Sderaadt * notice, this list of conditions and the following disclaimer in the 13df930be7Sderaadt * documentation and/or other materials provided with the distribution. 146580fee3Smillert * 3. Neither the name of the University nor the names of its contributors 15df930be7Sderaadt * may be used to endorse or promote products derived from this software 16df930be7Sderaadt * without specific prior written permission. 17df930be7Sderaadt * 18df930be7Sderaadt * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19df930be7Sderaadt * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20df930be7Sderaadt * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21df930be7Sderaadt * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22df930be7Sderaadt * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23df930be7Sderaadt * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24df930be7Sderaadt * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25df930be7Sderaadt * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26df930be7Sderaadt * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27df930be7Sderaadt * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28df930be7Sderaadt * SUCH DAMAGE. 29df930be7Sderaadt */ 30df930be7Sderaadt 31471b62eeSmillert #include <errno.h> 32df930be7Sderaadt #include <stdlib.h> 33df930be7Sderaadt #include <string.h> 34df930be7Sderaadt 3531acb996Smillert extern char **environ; 36471b62eeSmillert static char **lastenv; /* last value of environ */ 37471b62eeSmillert 38471b62eeSmillert /* 39471b62eeSmillert * putenv -- 40471b62eeSmillert * Add a name=value string directly to the environmental, replacing 41471b62eeSmillert * any current value. 42471b62eeSmillert */ 43471b62eeSmillert int 44471b62eeSmillert putenv(char *str) 45471b62eeSmillert { 46471b62eeSmillert char **P, *cp; 47471b62eeSmillert size_t cnt; 4800a0724bSmillert int offset = 0; 49471b62eeSmillert 50471b62eeSmillert for (cp = str; *cp && *cp != '='; ++cp) 51471b62eeSmillert ; 52471b62eeSmillert if (*cp != '=') { 53471b62eeSmillert errno = EINVAL; 54471b62eeSmillert return (-1); /* missing `=' in string */ 55471b62eeSmillert } 56471b62eeSmillert 57471b62eeSmillert if (__findenv(str, (int)(cp - str), &offset) != NULL) { 5800a0724bSmillert environ[offset++] = str; 5900a0724bSmillert /* could be set multiple times */ 6000a0724bSmillert while (__findenv(str, (int)(cp - str), &offset)) { 6100a0724bSmillert for (P = &environ[offset];; ++P) 6200a0724bSmillert if (!(*P = *(P + 1))) 6300a0724bSmillert break; 6400a0724bSmillert } 65471b62eeSmillert return (0); 66471b62eeSmillert } 67471b62eeSmillert 68471b62eeSmillert /* create new slot for string */ 69471b62eeSmillert for (P = environ; *P != NULL; P++) 70471b62eeSmillert ; 71471b62eeSmillert cnt = P - environ; 72ed7f1a02Sderaadt P = reallocarray(lastenv, cnt + 2, sizeof(char *)); 73471b62eeSmillert if (!P) 74471b62eeSmillert return (-1); 75471b62eeSmillert if (lastenv != environ) 76471b62eeSmillert memcpy(P, environ, cnt * sizeof(char *)); 77471b62eeSmillert lastenv = environ = P; 78471b62eeSmillert environ[cnt] = str; 79471b62eeSmillert environ[cnt + 1] = NULL; 80471b62eeSmillert return (0); 81471b62eeSmillert } 82*0d943ef0Sguenther DEF_WEAK(putenv); 8331acb996Smillert 84df930be7Sderaadt /* 85df930be7Sderaadt * setenv -- 86df930be7Sderaadt * Set the value of the environmental variable "name" to be 87df930be7Sderaadt * "value". If rewrite is set, replace any current value. 88df930be7Sderaadt */ 89df930be7Sderaadt int 90d8bc04e4Spat setenv(const char *name, const char *value, int rewrite) 91df930be7Sderaadt { 9200a0724bSmillert char *C, **P; 93471b62eeSmillert const char *np; 9400a0724bSmillert int l_value, offset = 0; 95df930be7Sderaadt 9698da8fe0Sjeremy if (!name || !*name) { 9798da8fe0Sjeremy errno = EINVAL; 9898da8fe0Sjeremy return (-1); 9998da8fe0Sjeremy } 100471b62eeSmillert for (np = name; *np && *np != '='; ++np) 101471b62eeSmillert ; 102471b62eeSmillert if (*np) { 103471b62eeSmillert errno = EINVAL; 104471b62eeSmillert return (-1); /* has `=' in name */ 105471b62eeSmillert } 106471b62eeSmillert 107df930be7Sderaadt l_value = strlen(value); 108471b62eeSmillert if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { 10900a0724bSmillert int tmpoff = offset + 1; 110df930be7Sderaadt if (!rewrite) 111df930be7Sderaadt return (0); 112fa860d8fSmillert #if 0 /* XXX - existing entry may not be writable */ 113df930be7Sderaadt if (strlen(C) >= l_value) { /* old larger; copy over */ 11420675415Sderaadt while ((*C++ = *value++)) 11520675415Sderaadt ; 116df930be7Sderaadt return (0); 117df930be7Sderaadt } 118fa860d8fSmillert #endif 11900a0724bSmillert /* could be set multiple times */ 12000a0724bSmillert while (__findenv(name, (int)(np - name), &tmpoff)) { 12100a0724bSmillert for (P = &environ[tmpoff];; ++P) 12200a0724bSmillert if (!(*P = *(P + 1))) 12300a0724bSmillert break; 12400a0724bSmillert } 125df930be7Sderaadt } else { /* create new slot */ 12631acb996Smillert size_t cnt; 127df930be7Sderaadt 12831acb996Smillert for (P = environ; *P != NULL; P++) 12931acb996Smillert ; 13031acb996Smillert cnt = P - environ; 131ed7f1a02Sderaadt P = reallocarray(lastenv, cnt + 2, sizeof(char *)); 13248d1b8abSmillert if (!P) 133df930be7Sderaadt return (-1); 13431acb996Smillert if (lastenv != environ) 13531acb996Smillert memcpy(P, environ, cnt * sizeof(char *)); 13631acb996Smillert lastenv = environ = P; 137df930be7Sderaadt offset = cnt; 13831acb996Smillert environ[cnt + 1] = NULL; 139df930be7Sderaadt } 140df930be7Sderaadt if (!(environ[offset] = /* name + `=' + value */ 141471b62eeSmillert malloc((size_t)((int)(np - name) + l_value + 2)))) 142df930be7Sderaadt return (-1); 143df930be7Sderaadt for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 144df930be7Sderaadt ; 14520675415Sderaadt for (*C++ = '='; (*C++ = *value++); ) 146df930be7Sderaadt ; 147df930be7Sderaadt return (0); 148df930be7Sderaadt } 149*0d943ef0Sguenther DEF_WEAK(setenv); 150df930be7Sderaadt 151df930be7Sderaadt /* 152df930be7Sderaadt * unsetenv(name) -- 153df930be7Sderaadt * Delete environmental variable "name". 154df930be7Sderaadt */ 155471b62eeSmillert int 156d8bc04e4Spat unsetenv(const char *name) 157df930be7Sderaadt { 15831acb996Smillert char **P; 159471b62eeSmillert const char *np; 16000a0724bSmillert int offset = 0; 161df930be7Sderaadt 162f1fdc1beSnaddy if (!name || !*name) { 163f1fdc1beSnaddy errno = EINVAL; 164f1fdc1beSnaddy return (-1); 165f1fdc1beSnaddy } 166471b62eeSmillert for (np = name; *np && *np != '='; ++np) 167471b62eeSmillert ; 168471b62eeSmillert if (*np) { 169471b62eeSmillert errno = EINVAL; 170471b62eeSmillert return (-1); /* has `=' in name */ 171471b62eeSmillert } 172471b62eeSmillert 173471b62eeSmillert /* could be set multiple times */ 174471b62eeSmillert while (__findenv(name, (int)(np - name), &offset)) { 175df930be7Sderaadt for (P = &environ[offset];; ++P) 176df930be7Sderaadt if (!(*P = *(P + 1))) 177df930be7Sderaadt break; 178df930be7Sderaadt } 179471b62eeSmillert return (0); 180471b62eeSmillert } 181*0d943ef0Sguenther DEF_WEAK(unsetenv); 182