144743Smarkm/* 244743Smarkm * Many systems have putenv() but no setenv(). Other systems have setenv() 344743Smarkm * but no putenv() (MIPS). Still other systems have neither (NeXT). This is a 444743Smarkm * re-implementation that hopefully ends all problems. 544743Smarkm * 644743Smarkm * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands. 744743Smarkm */ 844743Smarkm 944743Smarkm#ifndef lint 1044743Smarkmstatic char sccsid[] = "@(#) environ.c 1.2 94/03/23 16:09:46"; 1144743Smarkm#endif 1244743Smarkm 1344743Smarkm/* System libraries. */ 1444743Smarkm 1544743Smarkmextern char **environ; 1644743Smarkmextern char *strchr(); 1744743Smarkmextern char *strcpy(); 1844743Smarkmextern char *strncpy(); 1944743Smarkmextern char *malloc(); 2044743Smarkmextern char *realloc(); 2144743Smarkmextern int strncmp(); 2244743Smarkmextern void free(); 2344743Smarkm 2444743Smarkm#ifdef no_memcpy 2544743Smarkm#define memcpy(d,s,l) bcopy(s,d,l) 2644743Smarkm#else 2744743Smarkmextern char *memcpy(); 2844743Smarkm#endif 2944743Smarkm 3044743Smarkm/* Local stuff. */ 3144743Smarkm 3244743Smarkmstatic int addenv(); /* append entry to environment */ 3344743Smarkm 3444743Smarkmstatic int allocated = 0; /* environ is, or is not, allocated */ 3544743Smarkm 3644743Smarkm#define DO_CLOBBER 1 3744743Smarkm 3844743Smarkm/* namelength - determine length of name in "name=whatever" */ 3944743Smarkm 4044743Smarkmstatic int namelength(name) 4144743Smarkmchar *name; 4244743Smarkm{ 4344743Smarkm char *equal; 4444743Smarkm 4544743Smarkm equal = strchr(name, '='); 4644743Smarkm return ((equal == 0) ? strlen(name) : (equal - name)); 4744743Smarkm} 4844743Smarkm 4944743Smarkm/* findenv - given name, locate name=value */ 5044743Smarkm 5144743Smarkmstatic char **findenv(name, len) 5244743Smarkmchar *name; 5344743Smarkmint len; 5444743Smarkm{ 5544743Smarkm char **envp; 5644743Smarkm 5744743Smarkm for (envp = environ; envp && *envp; envp++) 5844743Smarkm if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=') 5944743Smarkm return (envp); 6044743Smarkm return (0); 6144743Smarkm} 6244743Smarkm 6344743Smarkm/* getenv - given name, locate value */ 6444743Smarkm 6544743Smarkmchar *getenv(name) 6644743Smarkmchar *name; 6744743Smarkm{ 6844743Smarkm int len = namelength(name); 6944743Smarkm char **envp = findenv(name, len); 7044743Smarkm 7144743Smarkm return (envp ? *envp + len + 1 : 0); 7244743Smarkm} 7344743Smarkm 7444743Smarkm/* putenv - update or append environment (name,value) pair */ 7544743Smarkm 7644743Smarkmint putenv(nameval) 7744743Smarkmchar *nameval; 7844743Smarkm{ 7944743Smarkm char *equal = strchr(nameval, '='); 8044743Smarkm char *value = (equal ? equal : ""); 8144743Smarkm 8244743Smarkm return (setenv(nameval, value, DO_CLOBBER)); 8344743Smarkm} 8444743Smarkm 8544743Smarkm/* unsetenv - remove variable from environment */ 8644743Smarkm 8744743Smarkmvoid unsetenv(name) 8844743Smarkmchar *name; 8944743Smarkm{ 9044743Smarkm char **envp; 9144743Smarkm 9244743Smarkm if ((envp = findenv(name, namelength(name))) != 0) 9344743Smarkm while (envp[0] = envp[1]) 9444743Smarkm envp++; 9544743Smarkm} 9644743Smarkm 9744743Smarkm/* setenv - update or append environment (name,value) pair */ 9844743Smarkm 9944743Smarkmint setenv(name, value, clobber) 10044743Smarkmchar *name; 10144743Smarkmchar *value; 10244743Smarkmint clobber; 10344743Smarkm{ 10444743Smarkm char *destination; 10544743Smarkm char **envp; 10644743Smarkm int l_name; /* length of name part */ 10744743Smarkm int l_nameval; /* length of name=value */ 10844743Smarkm 10944743Smarkm /* Permit name= and =value. */ 11044743Smarkm 11144743Smarkm l_name = namelength(name); 11244743Smarkm envp = findenv(name, l_name); 11344743Smarkm if (envp != 0 && clobber == 0) 11444743Smarkm return (0); 11544743Smarkm if (*value == '=') 11644743Smarkm value++; 11744743Smarkm l_nameval = l_name + strlen(value) + 1; 11844743Smarkm 11944743Smarkm /* 12044743Smarkm * Use available memory if the old value is long enough. Never free an 12144743Smarkm * old name=value entry because it may not be allocated. 12244743Smarkm */ 12344743Smarkm 12444743Smarkm destination = (envp != 0 && strlen(*envp) >= l_nameval) ? 12544743Smarkm *envp : malloc(l_nameval + 1); 12644743Smarkm if (destination == 0) 12744743Smarkm return (-1); 12844743Smarkm strncpy(destination, name, l_name); 12944743Smarkm destination[l_name] = '='; 13044743Smarkm strcpy(destination + l_name + 1, value); 13144743Smarkm return ((envp == 0) ? addenv(destination) : (*envp = destination, 0)); 13244743Smarkm} 13344743Smarkm 13444743Smarkm/* cmalloc - malloc and copy block of memory */ 13544743Smarkm 13644743Smarkmstatic char *cmalloc(new_len, old, old_len) 13744743Smarkmchar *old; 13844743Smarkmint old_len; 13944743Smarkm{ 14044743Smarkm char *new = malloc(new_len); 14144743Smarkm 14244743Smarkm if (new != 0) 14344743Smarkm memcpy(new, old, old_len); 14444743Smarkm return (new); 14544743Smarkm} 14644743Smarkm 14744743Smarkm/* addenv - append environment entry */ 14844743Smarkm 14944743Smarkmstatic int addenv(nameval) 15044743Smarkmchar *nameval; 15144743Smarkm{ 15244743Smarkm char **envp; 15344743Smarkm int n_used; /* number of environment entries */ 15444743Smarkm int l_used; /* bytes used excl. terminator */ 15544743Smarkm int l_need; /* bytes needed incl. terminator */ 15644743Smarkm 15744743Smarkm for (envp = environ; envp && *envp; envp++) 15844743Smarkm /* void */ ; 15944743Smarkm n_used = envp - environ; 16044743Smarkm l_used = n_used * sizeof(*envp); 16144743Smarkm l_need = l_used + 2 * sizeof(*envp); 16244743Smarkm 16344743Smarkm envp = allocated ? 16444743Smarkm (char **) realloc((char *) environ, l_need) : 16544743Smarkm (char **) cmalloc(l_need, (char *) environ, l_used); 16644743Smarkm if (envp == 0) { 16744743Smarkm return (-1); 16844743Smarkm } else { 16944743Smarkm allocated = 1; 17044743Smarkm environ = envp; 17144743Smarkm environ[n_used++] = nameval; /* add new entry */ 17244743Smarkm environ[n_used] = 0; /* terminate list */ 17344743Smarkm return (0); 17444743Smarkm } 17544743Smarkm} 17644743Smarkm 17744743Smarkm#ifdef TEST 17844743Smarkm 17944743Smarkm /* 18044743Smarkm * Stand-alone program for test purposes. 18144743Smarkm */ 18244743Smarkm 18344743Smarkm/* printenv - display environment */ 18444743Smarkm 18544743Smarkmstatic void printenv() 18644743Smarkm{ 18744743Smarkm char **envp; 18844743Smarkm 18944743Smarkm for (envp = environ; envp && *envp; envp++) 19044743Smarkm printf("%s\n", *envp); 19144743Smarkm} 19244743Smarkm 19344743Smarkmint main(argc, argv) 19444743Smarkmint argc; 19544743Smarkmchar **argv; 19644743Smarkm{ 19744743Smarkm char *cp; 19844743Smarkm int changed = 0; 19944743Smarkm 20044743Smarkm if (argc < 2) { 20144743Smarkm printf("usage: %s name[=value]...\n", argv[0]); 20244743Smarkm return (1); 20344743Smarkm } 20444743Smarkm while (--argc && *++argv) { 20544743Smarkm if (argv[0][0] == '-') { /* unsetenv() test */ 20644743Smarkm unsetenv(argv[0] + 1); 20744743Smarkm changed = 1; 20844743Smarkm } else if (strchr(argv[0], '=') == 0) { /* getenv() test */ 20944743Smarkm cp = getenv(argv[0]); 21044743Smarkm printf("%s: %s\n", argv[0], cp ? cp : "not found"); 21144743Smarkm } else { /* putenv() test */ 21244743Smarkm if (putenv(argv[0])) { 21344743Smarkm perror("putenv"); 21444743Smarkm return (1); 21544743Smarkm } 21644743Smarkm changed = 1; 21744743Smarkm } 21844743Smarkm } 21944743Smarkm if (changed) 22044743Smarkm printenv(); 22144743Smarkm return (0); 22244743Smarkm} 22344743Smarkm 22444743Smarkm#endif /* TEST */ 225