1*0Sstevel@tonic-gate /* 2*0Sstevel@tonic-gate * Many systems have putenv() but no setenv(). Other systems have setenv() 3*0Sstevel@tonic-gate * but no putenv() (MIPS). Still other systems have neither (NeXT). This is a 4*0Sstevel@tonic-gate * re-implementation that hopefully ends all problems. 5*0Sstevel@tonic-gate * 6*0Sstevel@tonic-gate * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 7*0Sstevel@tonic-gate */ 8*0Sstevel@tonic-gate 9*0Sstevel@tonic-gate #ifndef lint 10*0Sstevel@tonic-gate static char sccsid[] = "@(#) environ.c 1.2 94/03/23 16:09:46"; 11*0Sstevel@tonic-gate #endif 12*0Sstevel@tonic-gate 13*0Sstevel@tonic-gate /* System libraries. */ 14*0Sstevel@tonic-gate 15*0Sstevel@tonic-gate extern char **environ; 16*0Sstevel@tonic-gate extern char *strchr(); 17*0Sstevel@tonic-gate extern char *strcpy(); 18*0Sstevel@tonic-gate extern char *strncpy(); 19*0Sstevel@tonic-gate extern char *malloc(); 20*0Sstevel@tonic-gate extern char *realloc(); 21*0Sstevel@tonic-gate extern int strncmp(); 22*0Sstevel@tonic-gate extern void free(); 23*0Sstevel@tonic-gate 24*0Sstevel@tonic-gate #ifdef no_memcpy 25*0Sstevel@tonic-gate #define memcpy(d,s,l) bcopy(s,d,l) 26*0Sstevel@tonic-gate #else 27*0Sstevel@tonic-gate extern char *memcpy(); 28*0Sstevel@tonic-gate #endif 29*0Sstevel@tonic-gate 30*0Sstevel@tonic-gate /* Local stuff. */ 31*0Sstevel@tonic-gate 32*0Sstevel@tonic-gate static int addenv(); /* append entry to environment */ 33*0Sstevel@tonic-gate 34*0Sstevel@tonic-gate static int allocated = 0; /* environ is, or is not, allocated */ 35*0Sstevel@tonic-gate 36*0Sstevel@tonic-gate #define DO_CLOBBER 1 37*0Sstevel@tonic-gate 38*0Sstevel@tonic-gate /* namelength - determine length of name in "name=whatever" */ 39*0Sstevel@tonic-gate 40*0Sstevel@tonic-gate static int namelength(name) 41*0Sstevel@tonic-gate char *name; 42*0Sstevel@tonic-gate { 43*0Sstevel@tonic-gate char *equal; 44*0Sstevel@tonic-gate 45*0Sstevel@tonic-gate equal = strchr(name, '='); 46*0Sstevel@tonic-gate return ((equal == 0) ? strlen(name) : (equal - name)); 47*0Sstevel@tonic-gate } 48*0Sstevel@tonic-gate 49*0Sstevel@tonic-gate /* findenv - given name, locate name=value */ 50*0Sstevel@tonic-gate 51*0Sstevel@tonic-gate static char **findenv(name, len) 52*0Sstevel@tonic-gate char *name; 53*0Sstevel@tonic-gate int len; 54*0Sstevel@tonic-gate { 55*0Sstevel@tonic-gate char **envp; 56*0Sstevel@tonic-gate 57*0Sstevel@tonic-gate for (envp = environ; envp && *envp; envp++) 58*0Sstevel@tonic-gate if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=') 59*0Sstevel@tonic-gate return (envp); 60*0Sstevel@tonic-gate return (0); 61*0Sstevel@tonic-gate } 62*0Sstevel@tonic-gate 63*0Sstevel@tonic-gate /* getenv - given name, locate value */ 64*0Sstevel@tonic-gate 65*0Sstevel@tonic-gate char *getenv(name) 66*0Sstevel@tonic-gate char *name; 67*0Sstevel@tonic-gate { 68*0Sstevel@tonic-gate int len = namelength(name); 69*0Sstevel@tonic-gate char **envp = findenv(name, len); 70*0Sstevel@tonic-gate 71*0Sstevel@tonic-gate return (envp ? *envp + len + 1 : 0); 72*0Sstevel@tonic-gate } 73*0Sstevel@tonic-gate 74*0Sstevel@tonic-gate /* putenv - update or append environment (name,value) pair */ 75*0Sstevel@tonic-gate 76*0Sstevel@tonic-gate int putenv(nameval) 77*0Sstevel@tonic-gate char *nameval; 78*0Sstevel@tonic-gate { 79*0Sstevel@tonic-gate char *equal = strchr(nameval, '='); 80*0Sstevel@tonic-gate char *value = (equal ? equal : ""); 81*0Sstevel@tonic-gate 82*0Sstevel@tonic-gate return (setenv(nameval, value, DO_CLOBBER)); 83*0Sstevel@tonic-gate } 84*0Sstevel@tonic-gate 85*0Sstevel@tonic-gate /* unsetenv - remove variable from environment */ 86*0Sstevel@tonic-gate 87*0Sstevel@tonic-gate void unsetenv(name) 88*0Sstevel@tonic-gate char *name; 89*0Sstevel@tonic-gate { 90*0Sstevel@tonic-gate char **envp; 91*0Sstevel@tonic-gate 92*0Sstevel@tonic-gate if ((envp = findenv(name, namelength(name))) != 0) 93*0Sstevel@tonic-gate while (envp[0] = envp[1]) 94*0Sstevel@tonic-gate envp++; 95*0Sstevel@tonic-gate } 96*0Sstevel@tonic-gate 97*0Sstevel@tonic-gate /* setenv - update or append environment (name,value) pair */ 98*0Sstevel@tonic-gate 99*0Sstevel@tonic-gate int setenv(name, value, clobber) 100*0Sstevel@tonic-gate char *name; 101*0Sstevel@tonic-gate char *value; 102*0Sstevel@tonic-gate int clobber; 103*0Sstevel@tonic-gate { 104*0Sstevel@tonic-gate char *destination; 105*0Sstevel@tonic-gate char **envp; 106*0Sstevel@tonic-gate int l_name; /* length of name part */ 107*0Sstevel@tonic-gate int l_nameval; /* length of name=value */ 108*0Sstevel@tonic-gate 109*0Sstevel@tonic-gate /* Permit name= and =value. */ 110*0Sstevel@tonic-gate 111*0Sstevel@tonic-gate l_name = namelength(name); 112*0Sstevel@tonic-gate envp = findenv(name, l_name); 113*0Sstevel@tonic-gate if (envp != 0 && clobber == 0) 114*0Sstevel@tonic-gate return (0); 115*0Sstevel@tonic-gate if (*value == '=') 116*0Sstevel@tonic-gate value++; 117*0Sstevel@tonic-gate l_nameval = l_name + strlen(value) + 1; 118*0Sstevel@tonic-gate 119*0Sstevel@tonic-gate /* 120*0Sstevel@tonic-gate * Use available memory if the old value is long enough. Never free an 121*0Sstevel@tonic-gate * old name=value entry because it may not be allocated. 122*0Sstevel@tonic-gate */ 123*0Sstevel@tonic-gate 124*0Sstevel@tonic-gate destination = (envp != 0 && strlen(*envp) >= l_nameval) ? 125*0Sstevel@tonic-gate *envp : malloc(l_nameval + 1); 126*0Sstevel@tonic-gate if (destination == 0) 127*0Sstevel@tonic-gate return (-1); 128*0Sstevel@tonic-gate strncpy(destination, name, l_name); 129*0Sstevel@tonic-gate destination[l_name] = '='; 130*0Sstevel@tonic-gate strcpy(destination + l_name + 1, value); 131*0Sstevel@tonic-gate return ((envp == 0) ? addenv(destination) : (*envp = destination, 0)); 132*0Sstevel@tonic-gate } 133*0Sstevel@tonic-gate 134*0Sstevel@tonic-gate /* cmalloc - malloc and copy block of memory */ 135*0Sstevel@tonic-gate 136*0Sstevel@tonic-gate static char *cmalloc(new_len, old, old_len) 137*0Sstevel@tonic-gate char *old; 138*0Sstevel@tonic-gate int old_len; 139*0Sstevel@tonic-gate { 140*0Sstevel@tonic-gate char *new = malloc(new_len); 141*0Sstevel@tonic-gate 142*0Sstevel@tonic-gate if (new != 0) 143*0Sstevel@tonic-gate memcpy(new, old, old_len); 144*0Sstevel@tonic-gate return (new); 145*0Sstevel@tonic-gate } 146*0Sstevel@tonic-gate 147*0Sstevel@tonic-gate /* addenv - append environment entry */ 148*0Sstevel@tonic-gate 149*0Sstevel@tonic-gate static int addenv(nameval) 150*0Sstevel@tonic-gate char *nameval; 151*0Sstevel@tonic-gate { 152*0Sstevel@tonic-gate char **envp; 153*0Sstevel@tonic-gate int n_used; /* number of environment entries */ 154*0Sstevel@tonic-gate int l_used; /* bytes used excl. terminator */ 155*0Sstevel@tonic-gate int l_need; /* bytes needed incl. terminator */ 156*0Sstevel@tonic-gate 157*0Sstevel@tonic-gate for (envp = environ; envp && *envp; envp++) 158*0Sstevel@tonic-gate /* void */ ; 159*0Sstevel@tonic-gate n_used = envp - environ; 160*0Sstevel@tonic-gate l_used = n_used * sizeof(*envp); 161*0Sstevel@tonic-gate l_need = l_used + 2 * sizeof(*envp); 162*0Sstevel@tonic-gate 163*0Sstevel@tonic-gate envp = allocated ? 164*0Sstevel@tonic-gate (char **) realloc((char *) environ, l_need) : 165*0Sstevel@tonic-gate (char **) cmalloc(l_need, (char *) environ, l_used); 166*0Sstevel@tonic-gate if (envp == 0) { 167*0Sstevel@tonic-gate return (-1); 168*0Sstevel@tonic-gate } else { 169*0Sstevel@tonic-gate allocated = 1; 170*0Sstevel@tonic-gate environ = envp; 171*0Sstevel@tonic-gate environ[n_used++] = nameval; /* add new entry */ 172*0Sstevel@tonic-gate environ[n_used] = 0; /* terminate list */ 173*0Sstevel@tonic-gate return (0); 174*0Sstevel@tonic-gate } 175*0Sstevel@tonic-gate } 176*0Sstevel@tonic-gate 177*0Sstevel@tonic-gate #ifdef TEST 178*0Sstevel@tonic-gate 179*0Sstevel@tonic-gate /* 180*0Sstevel@tonic-gate * Stand-alone program for test purposes. 181*0Sstevel@tonic-gate */ 182*0Sstevel@tonic-gate 183*0Sstevel@tonic-gate /* printenv - display environment */ 184*0Sstevel@tonic-gate 185*0Sstevel@tonic-gate static void printenv() 186*0Sstevel@tonic-gate { 187*0Sstevel@tonic-gate char **envp; 188*0Sstevel@tonic-gate 189*0Sstevel@tonic-gate for (envp = environ; envp && *envp; envp++) 190*0Sstevel@tonic-gate printf("%s\n", *envp); 191*0Sstevel@tonic-gate } 192*0Sstevel@tonic-gate 193*0Sstevel@tonic-gate int main(argc, argv) 194*0Sstevel@tonic-gate int argc; 195*0Sstevel@tonic-gate char **argv; 196*0Sstevel@tonic-gate { 197*0Sstevel@tonic-gate char *cp; 198*0Sstevel@tonic-gate int changed = 0; 199*0Sstevel@tonic-gate 200*0Sstevel@tonic-gate if (argc < 2) { 201*0Sstevel@tonic-gate printf("usage: %s name[=value]...\n", argv[0]); 202*0Sstevel@tonic-gate return (1); 203*0Sstevel@tonic-gate } 204*0Sstevel@tonic-gate while (--argc && *++argv) { 205*0Sstevel@tonic-gate if (argv[0][0] == '-') { /* unsetenv() test */ 206*0Sstevel@tonic-gate unsetenv(argv[0] + 1); 207*0Sstevel@tonic-gate changed = 1; 208*0Sstevel@tonic-gate } else if (strchr(argv[0], '=') == 0) { /* getenv() test */ 209*0Sstevel@tonic-gate cp = getenv(argv[0]); 210*0Sstevel@tonic-gate printf("%s: %s\n", argv[0], cp ? cp : "not found"); 211*0Sstevel@tonic-gate } else { /* putenv() test */ 212*0Sstevel@tonic-gate if (putenv(argv[0])) { 213*0Sstevel@tonic-gate perror("putenv"); 214*0Sstevel@tonic-gate return (1); 215*0Sstevel@tonic-gate } 216*0Sstevel@tonic-gate changed = 1; 217*0Sstevel@tonic-gate } 218*0Sstevel@tonic-gate } 219*0Sstevel@tonic-gate if (changed) 220*0Sstevel@tonic-gate printenv(); 221*0Sstevel@tonic-gate return (0); 222*0Sstevel@tonic-gate } 223*0Sstevel@tonic-gate 224*0Sstevel@tonic-gate #endif /* TEST */ 225