xref: /freebsd/contrib/tcp_wrappers/environ.c (revision 14f102eacc8434a5a1f96466752578a4167140c9)
12aef6930SMark Murray /*
22aef6930SMark Murray  * Many systems have putenv() but no setenv(). Other systems have setenv()
32aef6930SMark Murray  * but no putenv() (MIPS). Still other systems have neither (NeXT). This is a
42aef6930SMark Murray  * re-implementation that hopefully ends all problems.
52aef6930SMark Murray  *
62aef6930SMark Murray  * Author: Wietse Venema, Eindhoven University of Technology, The Netherlands.
72aef6930SMark Murray  */
82aef6930SMark Murray 
92aef6930SMark Murray #ifndef lint
102aef6930SMark Murray static char sccsid[] = "@(#) environ.c 1.2 94/03/23 16:09:46";
112aef6930SMark Murray #endif
122aef6930SMark Murray 
132aef6930SMark Murray /* System libraries. */
142aef6930SMark Murray 
152aef6930SMark Murray extern char **environ;
162aef6930SMark Murray extern char *strchr();
172aef6930SMark Murray extern char *strcpy();
182aef6930SMark Murray extern char *strncpy();
192aef6930SMark Murray extern char *malloc();
202aef6930SMark Murray extern char *realloc();
212aef6930SMark Murray extern int strncmp();
222aef6930SMark Murray extern void free();
232aef6930SMark Murray 
242aef6930SMark Murray #ifdef no_memcpy
252aef6930SMark Murray #define memcpy(d,s,l) bcopy(s,d,l)
262aef6930SMark Murray #else
272aef6930SMark Murray extern char *memcpy();
282aef6930SMark Murray #endif
292aef6930SMark Murray 
302aef6930SMark Murray /* Local stuff. */
312aef6930SMark Murray 
322aef6930SMark Murray static int addenv();			/* append entry to environment */
332aef6930SMark Murray 
342aef6930SMark Murray static int allocated = 0;		/* environ is, or is not, allocated */
352aef6930SMark Murray 
362aef6930SMark Murray #define DO_CLOBBER	1
372aef6930SMark Murray 
382aef6930SMark Murray /* namelength - determine length of name in "name=whatever" */
392aef6930SMark Murray 
namelength(char * name)40*14f102eaSEd Maste static int namelength(char *name)
412aef6930SMark Murray {
422aef6930SMark Murray     char   *equal;
432aef6930SMark Murray 
442aef6930SMark Murray     equal = strchr(name, '=');
452aef6930SMark Murray     return ((equal == 0) ? strlen(name) : (equal - name));
462aef6930SMark Murray }
472aef6930SMark Murray 
482aef6930SMark Murray /* findenv - given name, locate name=value */
492aef6930SMark Murray 
findenv(char * name,int len)50*14f102eaSEd Maste static char **findenv(char *name, int len)
512aef6930SMark Murray {
522aef6930SMark Murray     char  **envp;
532aef6930SMark Murray 
542aef6930SMark Murray     for (envp = environ; envp && *envp; envp++)
552aef6930SMark Murray 	if (strncmp(name, *envp, len) == 0 && (*envp)[len] == '=')
562aef6930SMark Murray 	    return (envp);
572aef6930SMark Murray     return (0);
582aef6930SMark Murray }
592aef6930SMark Murray 
602aef6930SMark Murray /* getenv - given name, locate value */
612aef6930SMark Murray 
getenv(char * name)62*14f102eaSEd Maste char   *getenv(char *name)
632aef6930SMark Murray {
642aef6930SMark Murray     int     len = namelength(name);
652aef6930SMark Murray     char  **envp = findenv(name, len);
662aef6930SMark Murray 
672aef6930SMark Murray     return (envp ? *envp + len + 1 : 0);
682aef6930SMark Murray }
692aef6930SMark Murray 
702aef6930SMark Murray /* putenv - update or append environment (name,value) pair */
712aef6930SMark Murray 
putenv(char * nameval)72*14f102eaSEd Maste int     putenv(char *nameval)
732aef6930SMark Murray {
742aef6930SMark Murray     char   *equal = strchr(nameval, '=');
752aef6930SMark Murray     char   *value = (equal ? equal : "");
762aef6930SMark Murray 
772aef6930SMark Murray     return (setenv(nameval, value, DO_CLOBBER));
782aef6930SMark Murray }
792aef6930SMark Murray 
802aef6930SMark Murray /* unsetenv - remove variable from environment */
812aef6930SMark Murray 
unsetenv(char * name)82*14f102eaSEd Maste void    unsetenv(char *name)
832aef6930SMark Murray {
842aef6930SMark Murray     char  **envp;
852aef6930SMark Murray 
862aef6930SMark Murray     if ((envp = findenv(name, namelength(name))) != 0)
872aef6930SMark Murray 	while (envp[0] = envp[1])
882aef6930SMark Murray 	    envp++;
892aef6930SMark Murray }
902aef6930SMark Murray 
912aef6930SMark Murray /* setenv - update or append environment (name,value) pair */
922aef6930SMark Murray 
setenv(char * name,char * value,int clobber)93*14f102eaSEd Maste int     setenv(char *name, char *value, int clobber)
942aef6930SMark Murray {
952aef6930SMark Murray     char   *destination;
962aef6930SMark Murray     char  **envp;
972aef6930SMark Murray     int     l_name;			/* length of name part */
982aef6930SMark Murray     int     l_nameval;			/* length of name=value */
992aef6930SMark Murray 
1002aef6930SMark Murray     /* Permit name= and =value. */
1012aef6930SMark Murray 
1022aef6930SMark Murray     l_name = namelength(name);
1032aef6930SMark Murray     envp = findenv(name, l_name);
1042aef6930SMark Murray     if (envp != 0 && clobber == 0)
1052aef6930SMark Murray 	return (0);
1062aef6930SMark Murray     if (*value == '=')
1072aef6930SMark Murray 	value++;
1082aef6930SMark Murray     l_nameval = l_name + strlen(value) + 1;
1092aef6930SMark Murray 
1102aef6930SMark Murray     /*
1112aef6930SMark Murray      * Use available memory if the old value is long enough. Never free an
1122aef6930SMark Murray      * old name=value entry because it may not be allocated.
1132aef6930SMark Murray      */
1142aef6930SMark Murray 
1152aef6930SMark Murray     destination = (envp != 0 && strlen(*envp) >= l_nameval) ?
1162aef6930SMark Murray 	*envp : malloc(l_nameval + 1);
1172aef6930SMark Murray     if (destination == 0)
1182aef6930SMark Murray 	return (-1);
1192aef6930SMark Murray     strncpy(destination, name, l_name);
1202aef6930SMark Murray     destination[l_name] = '=';
1212aef6930SMark Murray     strcpy(destination + l_name + 1, value);
1222aef6930SMark Murray     return ((envp == 0) ? addenv(destination) : (*envp = destination, 0));
1232aef6930SMark Murray }
1242aef6930SMark Murray 
1252aef6930SMark Murray /* cmalloc - malloc and copy block of memory */
1262aef6930SMark Murray 
cmalloc(int new_len,char * old,int old_len)127*14f102eaSEd Maste static char *cmalloc(int new_len, char *old, int old_len)
1282aef6930SMark Murray {
1292aef6930SMark Murray     char   *new = malloc(new_len);
1302aef6930SMark Murray 
1312aef6930SMark Murray     if (new != 0)
1322aef6930SMark Murray 	memcpy(new, old, old_len);
1332aef6930SMark Murray     return (new);
1342aef6930SMark Murray }
1352aef6930SMark Murray 
1362aef6930SMark Murray /* addenv - append environment entry */
1372aef6930SMark Murray 
addenv(char * nameval)138*14f102eaSEd Maste static int addenv(char *nameval)
1392aef6930SMark Murray {
1402aef6930SMark Murray     char  **envp;
1412aef6930SMark Murray     int     n_used;			/* number of environment entries */
1422aef6930SMark Murray     int     l_used;			/* bytes used excl. terminator */
1432aef6930SMark Murray     int     l_need;			/* bytes needed incl. terminator */
1442aef6930SMark Murray 
1452aef6930SMark Murray     for (envp = environ; envp && *envp; envp++)
1462aef6930SMark Murray 	 /* void */ ;
1472aef6930SMark Murray     n_used = envp - environ;
1482aef6930SMark Murray     l_used = n_used * sizeof(*envp);
1492aef6930SMark Murray     l_need = l_used + 2 * sizeof(*envp);
1502aef6930SMark Murray 
1512aef6930SMark Murray     envp = allocated ?
1522aef6930SMark Murray 	(char **) realloc((char *) environ, l_need) :
1532aef6930SMark Murray 	(char **) cmalloc(l_need, (char *) environ, l_used);
1542aef6930SMark Murray     if (envp == 0) {
1552aef6930SMark Murray 	return (-1);
1562aef6930SMark Murray     } else {
1572aef6930SMark Murray 	allocated = 1;
1582aef6930SMark Murray 	environ = envp;
1592aef6930SMark Murray 	environ[n_used++] = nameval;		/* add new entry */
1602aef6930SMark Murray 	environ[n_used] = 0;			/* terminate list */
1612aef6930SMark Murray 	return (0);
1622aef6930SMark Murray     }
1632aef6930SMark Murray }
1642aef6930SMark Murray 
1652aef6930SMark Murray #ifdef TEST
1662aef6930SMark Murray 
1672aef6930SMark Murray  /*
1682aef6930SMark Murray   * Stand-alone program for test purposes.
1692aef6930SMark Murray   */
1702aef6930SMark Murray 
1712aef6930SMark Murray /* printenv - display environment */
1722aef6930SMark Murray 
printenv()1732aef6930SMark Murray static void printenv()
1742aef6930SMark Murray {
1752aef6930SMark Murray     char  **envp;
1762aef6930SMark Murray 
1772aef6930SMark Murray     for (envp = environ; envp && *envp; envp++)
1782aef6930SMark Murray 	printf("%s\n", *envp);
1792aef6930SMark Murray }
1802aef6930SMark Murray 
main(int argc,char ** argv)181*14f102eaSEd Maste int     main(int argc, char **argv)
1822aef6930SMark Murray {
1832aef6930SMark Murray     char   *cp;
1842aef6930SMark Murray     int     changed = 0;
1852aef6930SMark Murray 
1862aef6930SMark Murray     if (argc < 2) {
1872aef6930SMark Murray 	printf("usage: %s name[=value]...\n", argv[0]);
1882aef6930SMark Murray 	return (1);
1892aef6930SMark Murray     }
1902aef6930SMark Murray     while (--argc && *++argv) {
1912aef6930SMark Murray 	if (argv[0][0] == '-') {		/* unsetenv() test */
1922aef6930SMark Murray 	    unsetenv(argv[0] + 1);
1932aef6930SMark Murray 	    changed = 1;
1942aef6930SMark Murray 	} else if (strchr(argv[0], '=') == 0) {	/* getenv() test */
1952aef6930SMark Murray 	    cp = getenv(argv[0]);
1962aef6930SMark Murray 	    printf("%s: %s\n", argv[0], cp ? cp : "not found");
1972aef6930SMark Murray 	} else {				/* putenv() test */
1982aef6930SMark Murray 	    if (putenv(argv[0])) {
1992aef6930SMark Murray 		perror("putenv");
2002aef6930SMark Murray 		return (1);
2012aef6930SMark Murray 	    }
2022aef6930SMark Murray 	    changed = 1;
2032aef6930SMark Murray 	}
2042aef6930SMark Murray     }
2052aef6930SMark Murray     if (changed)
2062aef6930SMark Murray 	printenv();
2072aef6930SMark Murray     return (0);
2082aef6930SMark Murray }
2092aef6930SMark Murray 
2102aef6930SMark Murray #endif /* TEST */
211