131de2854Smrg/* $OpenBSD: setenv.c,v 1.13 2010/08/23 22:31:50 millert Exp $ */ 231de2854Smrg/* 331de2854Smrg * Copyright (c) 1987 Regents of the University of California. 431de2854Smrg * All rights reserved. 531de2854Smrg * 631de2854Smrg * Redistribution and use in source and binary forms, with or without 731de2854Smrg * modification, are permitted provided that the following conditions 831de2854Smrg * are met: 931de2854Smrg * 1. Redistributions of source code must retain the above copyright 1031de2854Smrg * notice, this list of conditions and the following disclaimer. 1131de2854Smrg * 2. Redistributions in binary form must reproduce the above copyright 1231de2854Smrg * notice, this list of conditions and the following disclaimer in the 1331de2854Smrg * documentation and/or other materials provided with the distribution. 1431de2854Smrg * 3. Neither the name of the University nor the names of its contributors 1531de2854Smrg * may be used to endorse or promote products derived from this software 1631de2854Smrg * without specific prior written permission. 1731de2854Smrg * 1831de2854Smrg * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 1931de2854Smrg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 2031de2854Smrg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 2131de2854Smrg * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 2231de2854Smrg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 2331de2854Smrg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 2431de2854Smrg * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 2531de2854Smrg * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 2631de2854Smrg * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 2731de2854Smrg * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 2831de2854Smrg * SUCH DAMAGE. 2931de2854Smrg */ 3031de2854Smrg 3131de2854Smrg#include <errno.h> 3231de2854Smrg#include <stdlib.h> 3331de2854Smrg#include <string.h> 3431de2854Smrg 3531de2854Smrgchar *__findenv(const char *name, int len, int *offset); 3631de2854Smrg 3731de2854Smrgextern char **environ; 3831de2854Smrgstatic char **lastenv; /* last value of environ */ 3931de2854Smrg 4031de2854Smrg/* 4131de2854Smrg * putenv -- 4231de2854Smrg * Add a name=value string directly to the environmental, replacing 4331de2854Smrg * any current value. 4431de2854Smrg */ 4531de2854Smrgint 4631de2854Smrgputenv(char *str) 4731de2854Smrg{ 4831de2854Smrg char **P, *cp; 4931de2854Smrg size_t cnt; 5031de2854Smrg int offset = 0; 5131de2854Smrg 5231de2854Smrg for (cp = str; *cp && *cp != '='; ++cp) 5331de2854Smrg ; 5431de2854Smrg if (*cp != '=') { 5531de2854Smrg errno = EINVAL; 5631de2854Smrg return (-1); /* missing `=' in string */ 5731de2854Smrg } 5831de2854Smrg 5931de2854Smrg if (__findenv(str, (int)(cp - str), &offset) != NULL) { 6031de2854Smrg environ[offset++] = str; 6131de2854Smrg /* could be set multiple times */ 6231de2854Smrg while (__findenv(str, (int)(cp - str), &offset)) { 6331de2854Smrg for (P = &environ[offset];; ++P) 6431de2854Smrg if (!(*P = *(P + 1))) 6531de2854Smrg break; 6631de2854Smrg } 6731de2854Smrg return (0); 6831de2854Smrg } 6931de2854Smrg 7031de2854Smrg /* create new slot for string */ 7131de2854Smrg for (P = environ; *P != NULL; P++) 7231de2854Smrg ; 7331de2854Smrg cnt = P - environ; 7431de2854Smrg P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); 7531de2854Smrg if (!P) 7631de2854Smrg return (-1); 7731de2854Smrg if (lastenv != environ) 7831de2854Smrg memcpy(P, environ, cnt * sizeof(char *)); 7931de2854Smrg lastenv = environ = P; 8031de2854Smrg environ[cnt] = str; 8131de2854Smrg environ[cnt + 1] = NULL; 8231de2854Smrg return (0); 8331de2854Smrg} 8431de2854Smrg 8531de2854Smrg/* 8631de2854Smrg * setenv -- 8731de2854Smrg * Set the value of the environmental variable "name" to be 8831de2854Smrg * "value". If rewrite is set, replace any current value. 8931de2854Smrg */ 9031de2854Smrgint 9131de2854Smrgsetenv(const char *name, const char *value, int rewrite) 9231de2854Smrg{ 9331de2854Smrg char *C, **P; 9431de2854Smrg const char *np; 9531de2854Smrg int l_value, offset = 0; 9631de2854Smrg 9731de2854Smrg for (np = name; *np && *np != '='; ++np) 9831de2854Smrg ; 9931de2854Smrg#ifdef notyet 10031de2854Smrg if (*np) { 10131de2854Smrg errno = EINVAL; 10231de2854Smrg return (-1); /* has `=' in name */ 10331de2854Smrg } 10431de2854Smrg#endif 10531de2854Smrg 10631de2854Smrg l_value = strlen(value); 10731de2854Smrg if ((C = __findenv(name, (int)(np - name), &offset)) != NULL) { 10831de2854Smrg int tmpoff = offset + 1; 10931de2854Smrg if (!rewrite) 11031de2854Smrg return (0); 11131de2854Smrg#if 0 /* XXX - existing entry may not be writable */ 11231de2854Smrg if (strlen(C) >= l_value) { /* old larger; copy over */ 11331de2854Smrg while ((*C++ = *value++)) 11431de2854Smrg ; 11531de2854Smrg return (0); 11631de2854Smrg } 11731de2854Smrg#endif 11831de2854Smrg /* could be set multiple times */ 11931de2854Smrg while (__findenv(name, (int)(np - name), &tmpoff)) { 12031de2854Smrg for (P = &environ[tmpoff];; ++P) 12131de2854Smrg if (!(*P = *(P + 1))) 12231de2854Smrg break; 12331de2854Smrg } 12431de2854Smrg } else { /* create new slot */ 12531de2854Smrg size_t cnt; 12631de2854Smrg 12731de2854Smrg for (P = environ; *P != NULL; P++) 12831de2854Smrg ; 12931de2854Smrg cnt = P - environ; 13031de2854Smrg P = (char **)realloc(lastenv, sizeof(char *) * (cnt + 2)); 13131de2854Smrg if (!P) 13231de2854Smrg return (-1); 13331de2854Smrg if (lastenv != environ) 13431de2854Smrg memcpy(P, environ, cnt * sizeof(char *)); 13531de2854Smrg lastenv = environ = P; 13631de2854Smrg offset = cnt; 13731de2854Smrg environ[cnt + 1] = NULL; 13831de2854Smrg } 13931de2854Smrg if (!(environ[offset] = /* name + `=' + value */ 14031de2854Smrg malloc((size_t)((int)(np - name) + l_value + 2)))) 14131de2854Smrg return (-1); 14231de2854Smrg for (C = environ[offset]; (*C = *name++) && *C != '='; ++C) 14331de2854Smrg ; 14431de2854Smrg for (*C++ = '='; (*C++ = *value++); ) 14531de2854Smrg ; 14631de2854Smrg return (0); 14731de2854Smrg} 14831de2854Smrg 14931de2854Smrg/* 15031de2854Smrg * unsetenv(name) -- 15131de2854Smrg * Delete environmental variable "name". 15231de2854Smrg */ 15331de2854Smrgint 15431de2854Smrgunsetenv(const char *name) 15531de2854Smrg{ 15631de2854Smrg char **P; 15731de2854Smrg const char *np; 15831de2854Smrg int offset = 0; 15931de2854Smrg 16031de2854Smrg if (!name || !*name) { 16131de2854Smrg errno = EINVAL; 16231de2854Smrg return (-1); 16331de2854Smrg } 16431de2854Smrg for (np = name; *np && *np != '='; ++np) 16531de2854Smrg ; 16631de2854Smrg if (*np) { 16731de2854Smrg errno = EINVAL; 16831de2854Smrg return (-1); /* has `=' in name */ 16931de2854Smrg } 17031de2854Smrg 17131de2854Smrg /* could be set multiple times */ 17231de2854Smrg while (__findenv(name, (int)(np - name), &offset)) { 17331de2854Smrg for (P = &environ[offset];; ++P) 17431de2854Smrg if (!(*P = *(P + 1))) 17531de2854Smrg break; 17631de2854Smrg } 17731de2854Smrg return (0); 17831de2854Smrg} 179