1 /* Copyright (c) 2008, 2009
2  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
3  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
4  *      Micah Cowan (micah@cowan.name)
5  *      Sadrul Habib Chowdhury (sadrul@users.sourceforge.net)
6  * Copyright (c) 1993-2002, 2003, 2005, 2006, 2007
7  *      Juergen Weigert (jnweiger@immd4.informatik.uni-erlangen.de)
8  *      Michael Schroeder (mlschroe@immd4.informatik.uni-erlangen.de)
9  * Copyright (c) 1987 Oliver Laumann
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License as published by
13  * the Free Software Foundation; either version 3, or (at your option)
14  * any later version.
15  *
16  * This program is distributed in the hope that it will be useful,
17  * but WITHOUT ANY WARRANTY; without even the implied warranty of
18  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
19  * GNU General Public License for more details.
20  *
21  * You should have received a copy of the GNU General Public License
22  * along with this program (see the file COPYING); if not, see
23  * https://www.gnu.org/licenses/, or contact Free Software Foundation, Inc.,
24  * 51 Franklin Street, Fifth Floor, Boston, MA  02111-1301  USA
25  *
26  ****************************************************************
27  */
28 
29 /*
30  *  putenv  --  put value into environment
31  *
32  *  Usage:  i = putenv (string)
33  *    int i;
34  *    char  *string;
35  *
36  *  where string is of the form <name>=<value>.
37  *  If "value" is 0, then "name" will be deleted from the environment.
38  *  Putenv returns 0 normally, -1 on error (not enough core for malloc).
39  *
40  *  Putenv may need to add a new name into the environment, or to
41  *  associate a value longer than the current value with a particular
42  *  name.  So, to make life simpler, putenv() copies your entire
43  *  environment into the heap (i.e. malloc()) from the stack
44  *  (i.e. where it resides when your process is initiated) the first
45  *  time you call it.
46  *
47  *  HISTORY
48  *  3-Sep-91 Michael Schroeder (mlschroe). Modified to behave as
49  *    as putenv.
50  * 16-Aug-91 Tim MacKenzie (tym) at Monash University. Modified for
51  *    use in screen (iScreen) (ignores final int parameter)
52  * 14-Oct-85 Michael Mauldin (mlm) at Carnegie-Mellon University
53  *      Ripped out of CMU lib for Rob-O-Matic portability
54  * 20-Nov-79  Steven Shafer (sas) at Carnegie-Mellon University
55  *    Created for VAX.  Too bad Bell Labs didn't provide this.  It's
56  *    unfortunate that you have to copy the whole environment onto the
57  *    heap, but the bookkeeping-and-not-so-much-copying approach turns
58  *    out to be much hairier.  So, I decided to do the simple thing,
59  *    copying the entire environment onto the heap the first time you
60  *    call putenv(), then doing realloc() uniformly later on.
61  */
62 
63 #include "config.h"
64 
65 #ifdef NEEDPUTENV
66 
67 #if defined(__STDC__)
68 # define __P(a) a
69 #else
70 # define __P(a) ()
71 #endif
72 
73 char  *malloc __P((int));
74 char  *realloc __P((char *, int));
75 void   free __P((char *));
76 int    sprintf __P((char *, char *, ...));
77 
78 #define EXTRASIZE 5		/* increment to add to env. size */
79 
80 static int  envsize = -1;	/* current size of environment */
81 extern char **environ;		/* the global which is your env. */
82 
83 static int  findenv __P((char *));  /* look for a name in the env. */
84 static int  newenv __P((void));     /* copy env. from stack to heap */
85 static int  moreenv __P((void));    /* incr. size of env. */
86 
87 int
unsetenv(name)88 unsetenv(name)
89 char *name;
90 {
91   register int i;
92 
93   if (envsize < 0)
94     {				/* first time putenv called */
95       if (newenv() < 0)		/* copy env. to heap */
96 	return -1;
97     }
98   i = findenv(name);
99   if (i < 0)
100     return 0;			/* Already here */
101 
102   free(environ[i]);
103   if (envsize > 0)
104     envsize--;
105   for (; environ[i]; i++)
106     environ[i] = environ[i+1];
107   return 0;			/* Already here */
108 }
109 
110 int
putenv(string)111 putenv(string)
112 char *string;
113 {
114   register int  i;
115   register char *p;
116 
117   if (envsize < 0)
118     {				/* first time putenv called */
119       if (newenv() < 0)		/* copy env. to heap */
120 	return -1;
121     }
122 
123   i = findenv(string);		/* look for name in environment */
124 
125   if (i < 0)
126     {			/* name must be added */
127       for (i = 0; environ[i]; i++);
128       if (i >= (envsize - 1))
129 	{			/* need new slot */
130 	  if (moreenv() < 0)
131 	    return -1;
132 	}
133       p = malloc(strlen(string) + 1);
134       if (p == 0)		/* not enough core */
135 	return -1;
136       environ[i + 1] = 0;	/* new end of env. */
137     }
138   else
139     {			/* name already in env. */
140       p = realloc(environ[i], strlen(string) + 1);
141       if (p == 0)
142 	return -1;
143     }
144   sprintf(p, "%s", string); /* copy into env. */
145   environ[i] = p;
146 
147   return 0;
148 }
149 
150 static int
findenv(name)151 findenv(name)
152 char *name;
153 {
154   register char *namechar, *envchar;
155   register int  i, found;
156 
157   found = 0;
158   for (i = 0; environ[i] && !found; i++)
159     {
160       envchar = environ[i];
161       namechar = name;
162       while (*namechar && *namechar != '=' && (*namechar == *envchar))
163         {
164 	  namechar++;
165 	  envchar++;
166         }
167       found = ((*namechar == '\0' || *namechar == '=') && *envchar == '=');
168     }
169   return found ? i - 1 : -1;
170 }
171 
172 static int
newenv()173 newenv()
174 {
175   register char **env, *elem;
176   register int i, esize;
177 
178   for (i = 0; environ[i]; i++)
179     ;
180   esize = i + EXTRASIZE + 1;
181   env = (char **)malloc(esize * sizeof (elem));
182   if (env == 0)
183     return -1;
184 
185   for (i = 0; environ[i]; i++)
186     {
187       elem = malloc(strlen(environ[i]) + 1);
188       if (elem == 0)
189 	return -1;
190       env[i] = elem;
191       strcpy(elem, environ[i]);
192     }
193 
194   env[i] = 0;
195   environ = env;
196   envsize = esize;
197   return 0;
198 }
199 
200 static int
moreenv()201 moreenv()
202 {
203   register int  esize;
204   register char **env;
205 
206   esize = envsize + EXTRASIZE;
207   env = (char **)realloc((char *)environ, esize * sizeof (*env));
208   if (env == 0)
209     return -1;
210   environ = env;
211   envsize = esize;
212   return 0;
213 }
214 
215 #endif /* NEEDPUTENV */
216 
217