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