1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156
|
/*
* From: TCP Wrapper.
*
* Many systems have putenv() but no setenv(). Other systems have setenv() but
* no putenv() (MIPS). Still other systems have neither (NeXT). This is a
* re-implementation that hopefully ends all problems.
*
* Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
*/
#include "sys_defs.h"
#ifdef MISSING_SETENV_PUTENV
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
extern char **environ;
static int addenv(char *); /* append entry to environment */
static int allocated = 0; /* environ is, or is not, allocated */
#define DO_CLOBBER 1
/* namelength - determine length of name in "name=whatever" */
static ssize_t namelength(const char *name)
{
char *equal;
equal = strchr(name, '=');
return ((equal == 0) ? strlen(name) : (equal - name));
}
/* findenv - given name, locate name=value */
static char **findenv(const char *name, ssize_t len)
{
char **envp;
for (envp = environ; envp && *envp; envp++)
if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=')
return (envp);
return (0);
}
#if 0
/* getenv - given name, locate value */
char *getenv(const char *name)
{
ssize_t len = namelength(name);
char **envp = findenv(name, len);
return (envp ? *envp + len + 1 : 0);
}
/* putenv - update or append environment (name,value) pair */
int putenv(const char *nameval)
{
char *equal = strchr(nameval, '=');
char *value = (equal ? equal : "");
return (setenv(nameval, value, DO_CLOBBER));
}
/* unsetenv - remove variable from environment */
void unsetenv(const char *name)
{
char **envp;
while ((envp = findenv(name, namelength(name))) != 0)
while (envp[0] = envp[1])
envp++;
}
#endif
/* setenv - update or append environment (name,value) pair */
int setenv(const char *name, const char *value, int clobber)
{
char *destination;
char **envp;
ssize_t l_name; /* length of name part */
unsigned int l_nameval; /* length of name=value */
/* Permit name= and =value. */
l_name = namelength(name);
envp = findenv(name, l_name);
if (envp != 0 && clobber == 0)
return (0);
if (*value == '=')
value++;
l_nameval = l_name + strlen(value) + 1;
/*
* Use available memory if the old value is long enough. Never free an
* old name=value entry because it may not be allocated.
*/
destination = (envp != 0 && strlen(*envp) >= l_nameval) ?
*envp : malloc(l_nameval + 1);
if (destination == 0)
return (-1);
strncpy(destination, name, l_name);
destination[l_name] = '=';
strcpy(destination + l_name + 1, value);
return ((envp == 0) ? addenv(destination) : (*envp = destination, 0));
}
/* cmalloc - malloc and copy block of memory */
static char *cmalloc(ssize_t new_len, char *old, ssize_t old_len)
{
char *new = malloc(new_len);
if (new != 0)
memcpy(new, old, old_len);
return (new);
}
/* addenv - append environment entry */
static int addenv(char *nameval)
{
char **envp;
ssize_t n_used; /* number of environment entries */
ssize_t l_used; /* bytes used excl. terminator */
ssize_t l_need; /* bytes needed incl. terminator */
for (envp = environ; envp && *envp; envp++)
/* void */ ;
n_used = envp - environ;
l_used = n_used * sizeof(*envp);
l_need = l_used + 2 * sizeof(*envp);
envp = allocated ?
(char **) realloc((char *) environ, l_need) :
(char **) cmalloc(l_need, (char *) environ, l_used);
if (envp == 0) {
return (-1);
} else {
allocated = 1;
environ = envp;
environ[n_used++] = nameval; /* add new entry */
environ[n_used] = 0; /* terminate list */
return (0);
}
}
#endif
|