1 /*-------------------------------------------------------------------------
2  *
3  * unsetenv.c
4  *	  unsetenv() emulation for machines without it
5  *
6  * Portions Copyright (c) 1996-2017, PostgreSQL Global Development Group
7  * Portions Copyright (c) 1994, Regents of the University of California
8  *
9  *
10  * IDENTIFICATION
11  *	  src/port/unsetenv.c
12  *
13  *-------------------------------------------------------------------------
14  */
15 
16 #include "c.h"
17 
18 
19 void
unsetenv(const char * name)20 unsetenv(const char *name)
21 {
22 	char	   *envstr;
23 
24 	if (getenv(name) == NULL)
25 		return;					/* no work */
26 
27 	/*
28 	 * The technique embodied here works if libc follows the Single Unix Spec
29 	 * and actually uses the storage passed to putenv() to hold the environ
30 	 * entry.  When we clobber the entry in the second step we are ensuring
31 	 * that we zap the actual environ member.  However, there are some libc
32 	 * implementations (notably recent BSDs) that do not obey SUS but copy the
33 	 * presented string.  This method fails on such platforms.  Hopefully all
34 	 * such platforms have unsetenv() and thus won't be using this hack. See:
35 	 * http://www.greenend.org.uk/rjk/2008/putenv.html
36 	 *
37 	 * Note that repeatedly setting and unsetting a var using this code will
38 	 * leak memory.
39 	 */
40 
41 	envstr = (char *) malloc(strlen(name) + 2);
42 	if (!envstr)				/* not much we can do if no memory */
43 		return;
44 
45 	/* Override the existing setting by forcibly defining the var */
46 	sprintf(envstr, "%s=", name);
47 	putenv(envstr);
48 
49 	/* Now we can clobber the variable definition this way: */
50 	strcpy(envstr, "=");
51 
52 	/*
53 	 * This last putenv cleans up if we have multiple zero-length names as a
54 	 * result of unsetting multiple things.
55 	 */
56 	putenv(envstr);
57 }
58