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