1 /* $OpenBSD: setenv.c,v 1.11 2009/06/04 20:39:13 millert Exp $ */ 2 /* 3 * Copyright (c) 1987 Regents of the University of California. 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. Neither the name of the University nor the names of its contributors 15 * may be used to endorse or promote products derived from this software 16 * without specific prior written permission. 17 * 18 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31 #include <errno.h> 32 #include <stdlib.h> 33 #include <string.h> 34 35 char *__findenv(const char *name, int len, int *offset); 36 37 extern char **environ; 38 static char **lastenv; /* last value of environ */ 39 40 /* 41 * putenv -- 42 * Add a name=value string directly to the environmental, replacing 43 * any current value. 44 */ 45 int 46 putenv(char *str) 47 { 48 char **P, *cp; 49 size_t cnt; 50 int offset; 51 52 for (cp = str; *cp && *cp != '='; ++cp) 53 ; 54 if (*cp != '=') { 55 errno = EINVAL; 56 return (-1); /* missing `=' in string */ 57 } 58 59 if (__findenv(str, (int)(cp - str), &offset) != NULL) { 60 environ[offset] = str; 61 return (0); 62 } 63 64 /* create new slot for string */ 65 for (P = environ; *P != NULL; P++) 66 ; 67 cnt = P - environ; 68 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); 69 if (!P) 70 return (-1); 71 if (lastenv != environ) 72 memcpy(P, environ, cnt * sizeof(char *)); 73 lastenv = environ = P; 74 environ[cnt] = str; 75 environ[cnt + 1] = NULL; 76 return (0); 77 } 78 79 /* 80 * setenv -- 81 * Set the value of the environmental variable "name" to be 82 * "value". If rewrite is set, replace any current value. 83 */ 84 int 85 setenv(const char *name, const char *value, int rewrite) 86 { 87 char *C; 88 const char *np; 89 int l_value, offset; 90 91 for (np = name; *np && *np != '='; ++np) 92 ; 93 #ifdef notyet 94 if (*np) { 95 errno = EINVAL; 96 return (-1); /* has `=' in name */ 97 } 98 #endif 99 100 l_value = strlen(value); 101 if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { 102 if (!rewrite) 103 return (0); 104 #if 0 /* XXX - existing entry may not be writable */ 105 if (strlen(C) >= l_value) { /* old larger; copy over */ 106 while ((*C++ = *value++)) 107 ; 108 return (0); 109 } 110 #endif 111 } else { /* create new slot */ 112 size_t cnt; 113 char **P; 114 115 for (P = environ; *P != NULL; P++) 116 ; 117 cnt = P - environ; 118 P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); 119 if (!P) 120 return (-1); 121 if (lastenv != environ) 122 memcpy(P, environ, cnt * sizeof(char *)); 123 lastenv = environ = P; 124 offset = cnt; 125 environ[cnt + 1] = NULL; 126 } 127 if (!(environ[offset] = /* name + `=' + value */ 128 malloc((size_t)((int)(np - name) + l_value + 2)))) 129 return (-1); 130 for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 131 ; 132 for (*C++ = '='; (*C++ = *value++); ) 133 ; 134 return (0); 135 } 136 137 /* 138 * unsetenv(name) -- 139 * Delete environmental variable "name". 140 */ 141 int 142 unsetenv(const char *name) 143 { 144 char **P; 145 const char *np; 146 int offset; 147 148 for (np = name; *np && *np != '='; ++np) 149 ; 150 if (*np) { 151 errno = EINVAL; 152 return (-1); /* has `=' in name */ 153 } 154 155 /* could be set multiple times */ 156 while (__findenv(name, (int)(np - name), &offset)) { 157 for (P = &environ[offset];; ++P) 158 if (!(*P = *(P + 1))) 159 break; 160 } 161 return (0); 162 } 163